aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJonathan McCrohan <jmccrohan@gmail.com>2012-04-14 12:56:48 +0100
committerJonathan McCrohan <jmccrohan@gmail.com>2012-04-14 12:56:48 +0100
commit0b624384cd52be20e61284551d832b499d7b7707 (patch)
tree6f95a4bbef47abc9720b96c0722e8f632aef228a
downloadlibphidget21-0b624384cd52be20e61284551d832b499d7b7707.tar.gz
Imported Upstream version 2.1.8.20120216upstream/2.1.8.20120216
-rw-r--r--AUTHORS1
-rw-r--r--COPYING165
-rw-r--r--ChangeLog471
-rw-r--r--INSTALL302
-rw-r--r--Java/com/phidgets/AccelerometerPhidget.java116
-rw-r--r--Java/com/phidgets/AdvancedServoPhidget.java492
-rw-r--r--Java/com/phidgets/AnalogPhidget.java78
-rw-r--r--Java/com/phidgets/BridgePhidget.java202
-rw-r--r--Java/com/phidgets/Dictionary.java348
-rw-r--r--Java/com/phidgets/DictionaryKeyListener.java184
-rw-r--r--Java/com/phidgets/EncoderPhidget.java173
-rw-r--r--Java/com/phidgets/FrequencyCounterPhidget.java171
-rw-r--r--Java/com/phidgets/GPSPhidget.java151
-rw-r--r--Java/com/phidgets/IRCode.java93
-rw-r--r--Java/com/phidgets/IRCodeInfo.java360
-rw-r--r--Java/com/phidgets/IRLearnedCode.java51
-rw-r--r--Java/com/phidgets/IRPhidget.java239
-rw-r--r--Java/com/phidgets/InterfaceKitPhidget.java346
-rw-r--r--Java/com/phidgets/LEDPhidget.java141
-rw-r--r--Java/com/phidgets/Manager.java408
-rw-r--r--Java/com/phidgets/MotorControlPhidget.java497
-rw-r--r--Java/com/phidgets/PHSensorPhidget.java136
-rw-r--r--Java/com/phidgets/Phidget.java1000
-rw-r--r--Java/com/phidgets/PhidgetException.java337
-rw-r--r--Java/com/phidgets/RFIDPhidget.java197
-rw-r--r--Java/com/phidgets/ServoPhidget.java286
-rw-r--r--Java/com/phidgets/SpatialEventData.java101
-rw-r--r--Java/com/phidgets/SpatialPhidget.java205
-rw-r--r--Java/com/phidgets/StepperPhidget.java422
-rw-r--r--Java/com/phidgets/TemperatureSensorPhidget.java213
-rw-r--r--Java/com/phidgets/TextLCDPhidget.java278
-rw-r--r--Java/com/phidgets/TextLEDPhidget.java68
-rw-r--r--Java/com/phidgets/WeightSensorPhidget.java89
-rw-r--r--Java/com/phidgets/event/AccelerationChangeEvent.java69
-rw-r--r--Java/com/phidgets/event/AccelerationChangeListener.java20
-rw-r--r--Java/com/phidgets/event/AttachEvent.java46
-rw-r--r--Java/com/phidgets/event/AttachListener.java20
-rw-r--r--Java/com/phidgets/event/BackEMFUpdateEvent.java70
-rw-r--r--Java/com/phidgets/event/BackEMFUpdateListener.java21
-rw-r--r--Java/com/phidgets/event/BridgeDataEvent.java69
-rw-r--r--Java/com/phidgets/event/BridgeDataListener.java20
-rw-r--r--Java/com/phidgets/event/CodeEvent.java73
-rw-r--r--Java/com/phidgets/event/CodeListener.java21
-rw-r--r--Java/com/phidgets/event/CurrentChangeEvent.java69
-rw-r--r--Java/com/phidgets/event/CurrentChangeListener.java21
-rw-r--r--Java/com/phidgets/event/CurrentUpdateEvent.java70
-rw-r--r--Java/com/phidgets/event/CurrentUpdateListener.java20
-rw-r--r--Java/com/phidgets/event/DetachEvent.java46
-rw-r--r--Java/com/phidgets/event/DetachListener.java20
-rw-r--r--Java/com/phidgets/event/EncoderPositionChangeEvent.java84
-rw-r--r--Java/com/phidgets/event/EncoderPositionChangeListener.java20
-rw-r--r--Java/com/phidgets/event/EncoderPositionUpdateEvent.java73
-rw-r--r--Java/com/phidgets/event/EncoderPositionUpdateListener.java20
-rw-r--r--Java/com/phidgets/event/ErrorEvent.java59
-rw-r--r--Java/com/phidgets/event/ErrorListener.java21
-rw-r--r--Java/com/phidgets/event/FrequencyCounterCountEvent.java81
-rw-r--r--Java/com/phidgets/event/FrequencyCounterCountListener.java20
-rw-r--r--Java/com/phidgets/event/GPSPositionChangeEvent.java80
-rw-r--r--Java/com/phidgets/event/GPSPositionChangeListener.java20
-rw-r--r--Java/com/phidgets/event/GPSPositionFixStatusChangeEvent.java58
-rw-r--r--Java/com/phidgets/event/GPSPositionFixStatusChangeListener.java20
-rw-r--r--Java/com/phidgets/event/InputChangeEvent.java69
-rw-r--r--Java/com/phidgets/event/InputChangeListener.java21
-rw-r--r--Java/com/phidgets/event/KeyChangeEvent.java63
-rw-r--r--Java/com/phidgets/event/KeyChangeListener.java21
-rw-r--r--Java/com/phidgets/event/KeyRemovalEvent.java61
-rw-r--r--Java/com/phidgets/event/KeyRemovalListener.java21
-rw-r--r--Java/com/phidgets/event/LearnEvent.java60
-rw-r--r--Java/com/phidgets/event/LearnListener.java21
-rw-r--r--Java/com/phidgets/event/MotorVelocityChangeEvent.java69
-rw-r--r--Java/com/phidgets/event/MotorVelocityChangeListener.java20
-rw-r--r--Java/com/phidgets/event/OutputChangeEvent.java69
-rw-r--r--Java/com/phidgets/event/OutputChangeListener.java21
-rw-r--r--Java/com/phidgets/event/PHChangeEvent.java58
-rw-r--r--Java/com/phidgets/event/PHChangeListener.java20
-rw-r--r--Java/com/phidgets/event/RawDataEvent.java70
-rw-r--r--Java/com/phidgets/event/RawDataListener.java21
-rw-r--r--Java/com/phidgets/event/SensorChangeEvent.java69
-rw-r--r--Java/com/phidgets/event/SensorChangeListener.java19
-rw-r--r--Java/com/phidgets/event/SensorUpdateEvent.java70
-rw-r--r--Java/com/phidgets/event/SensorUpdateListener.java19
-rw-r--r--Java/com/phidgets/event/ServerConnectEvent.java48
-rw-r--r--Java/com/phidgets/event/ServerConnectListener.java20
-rw-r--r--Java/com/phidgets/event/ServerDisconnectEvent.java48
-rw-r--r--Java/com/phidgets/event/ServerDisconnectListener.java20
-rw-r--r--Java/com/phidgets/event/ServoPositionChangeEvent.java70
-rw-r--r--Java/com/phidgets/event/ServoPositionChangeListener.java21
-rw-r--r--Java/com/phidgets/event/ServoVelocityChangeEvent.java69
-rw-r--r--Java/com/phidgets/event/ServoVelocityChangeListener.java20
-rw-r--r--Java/com/phidgets/event/SpatialDataEvent.java60
-rw-r--r--Java/com/phidgets/event/SpatialDataListener.java21
-rw-r--r--Java/com/phidgets/event/StepperPositionChangeEvent.java70
-rw-r--r--Java/com/phidgets/event/StepperPositionChangeListener.java21
-rw-r--r--Java/com/phidgets/event/StepperVelocityChangeEvent.java69
-rw-r--r--Java/com/phidgets/event/StepperVelocityChangeListener.java20
-rw-r--r--Java/com/phidgets/event/TagGainEvent.java59
-rw-r--r--Java/com/phidgets/event/TagGainListener.java21
-rw-r--r--Java/com/phidgets/event/TagLossEvent.java59
-rw-r--r--Java/com/phidgets/event/TagLossListener.java21
-rw-r--r--Java/com/phidgets/event/TemperatureChangeEvent.java70
-rw-r--r--Java/com/phidgets/event/TemperatureChangeListener.java20
-rw-r--r--Java/com/phidgets/event/WeightChangeEvent.java58
-rw-r--r--Java/com/phidgets/event/WeightChangeListener.java20
-rw-r--r--Java/com/phidgets/macros/BridgePhidget.jm171
-rw-r--r--Java/com_phidgets_AccelerometerPhidget.c21
-rw-r--r--Java/com_phidgets_AccelerometerPhidget.h221
-rw-r--r--Java/com_phidgets_AdvancedServoPhidget.c66
-rw-r--r--Java/com_phidgets_AdvancedServoPhidget.h439
-rw-r--r--Java/com_phidgets_AnalogPhidget.c17
-rw-r--r--Java/com_phidgets_AnalogPhidget.h221
-rw-r--r--Java/com_phidgets_BridgePhidget.c40
-rw-r--r--Java/com_phidgets_BridgePhidget.h283
-rw-r--r--Java/com_phidgets_Dictionary.c334
-rw-r--r--Java/com_phidgets_Dictionary.h133
-rw-r--r--Java/com_phidgets_DictionaryKeyListener.c132
-rw-r--r--Java/com_phidgets_DictionaryKeyListener.h21
-rw-r--r--Java/com_phidgets_EncoderPhidget.c31
-rw-r--r--Java/com_phidgets_EncoderPhidget.h261
-rw-r--r--Java/com_phidgets_FrequencyCounterPhidget.c49
-rw-r--r--Java/com_phidgets_FrequencyCounterPhidget.h267
-rw-r--r--Java/com_phidgets_GPSPhidget.c101
-rw-r--r--Java/com_phidgets_GPSPhidget.h237
-rw-r--r--Java/com_phidgets_IRPhidget.c777
-rw-r--r--Java/com_phidgets_IRPhidget.h239
-rw-r--r--Java/com_phidgets_InterfaceKitPhidget.c36
-rw-r--r--Java/com_phidgets_InterfaceKitPhidget.h317
-rw-r--r--Java/com_phidgets_LEDPhidget.c38
-rw-r--r--Java/com_phidgets_LEDPhidget.h237
-rw-r--r--Java/com_phidgets_Manager.c392
-rw-r--r--Java/com_phidgets_Manager.h133
-rw-r--r--Java/com_phidgets_MotorControlPhidget.c75
-rw-r--r--Java/com_phidgets_MotorControlPhidget.h437
-rw-r--r--Java/com_phidgets_PHSensorPhidget.c24
-rw-r--r--Java/com_phidgets_PHSensorPhidget.h245
-rw-r--r--Java/com_phidgets_Phidget.c630
-rw-r--r--Java/com_phidgets_Phidget.h405
-rw-r--r--Java/com_phidgets_RFIDPhidget.c104
-rw-r--r--Java/com_phidgets_RFIDPhidget.h261
-rw-r--r--Java/com_phidgets_ServoPhidget.c47
-rw-r--r--Java/com_phidgets_ServoPhidget.h319
-rw-r--r--Java/com_phidgets_SpatialPhidget.c166
-rw-r--r--Java/com_phidgets_SpatialPhidget.h325
-rw-r--r--Java/com_phidgets_StepperPhidget.c53
-rw-r--r--Java/com_phidgets_StepperPhidget.h405
-rw-r--r--Java/com_phidgets_TemperatureSensorPhidget.c42
-rw-r--r--Java/com_phidgets_TemperatureSensorPhidget.h301
-rw-r--r--Java/com_phidgets_TextLCDPhidget.c97
-rw-r--r--Java/com_phidgets_TextLCDPhidget.h359
-rw-r--r--Java/com_phidgets_TextLEDPhidget.c29
-rw-r--r--Java/com_phidgets_TextLEDPhidget.h205
-rw-r--r--Java/com_phidgets_WeightSensorPhidget.c18
-rw-r--r--Java/com_phidgets_WeightSensorPhidget.h197
-rw-r--r--Java/phidget_jni.c156
-rw-r--r--Java/phidget_jni.h322
-rw-r--r--Makefile.am376
-rw-r--r--Makefile.in1475
-rw-r--r--NEWS0
-rw-r--r--README160
-rw-r--r--aclocal.m48943
-rw-r--r--clog.c176
-rw-r--r--clog.h50
-rwxr-xr-xconfig.guess1561
-rwxr-xr-xconfig.sub1686
-rwxr-xr-xconfigure13760
-rw-r--r--configure.ac94
-rw-r--r--cphidget.c1637
-rw-r--r--cphidget.h396
-rw-r--r--cphidgetaccelerometer.c258
-rw-r--r--cphidgetaccelerometer.h85
-rw-r--r--cphidgetadvancedservo.c923
-rw-r--r--cphidgetadvancedservo.h335
-rw-r--r--cphidgetanalog.c424
-rw-r--r--cphidgetanalog.h97
-rw-r--r--cphidgetattr.h261
-rw-r--r--cphidgetbridge.c446
-rw-r--r--cphidgetbridge.h145
-rw-r--r--cphidgetconstants.c153
-rw-r--r--cphidgetconstants.h88
-rw-r--r--cphidgetconstantsinternal.h130
-rw-r--r--cphidgetdictionary.c328
-rw-r--r--cphidgetdictionary.h178
-rw-r--r--cphidgetencoder.c455
-rw-r--r--cphidgetencoder.h121
-rw-r--r--cphidgetfrequencycounter.c393
-rw-r--r--cphidgetfrequencycounter.h154
-rw-r--r--cphidgetgeneric.c119
-rw-r--r--cphidgetgeneric.h35
-rw-r--r--cphidgetgps.c586
-rw-r--r--cphidgetgps.h231
-rw-r--r--cphidgetinterfacekit.c1426
-rw-r--r--cphidgetinterfacekit.h219
-rw-r--r--cphidgetir.c1889
-rw-r--r--cphidgetir.h203
-rw-r--r--cphidgetled.c669
-rw-r--r--cphidgetled.h137
-rw-r--r--cphidgetlist.c148
-rw-r--r--cphidgetlist.h19
-rw-r--r--cphidgetmacros.h316
-rw-r--r--cphidgetmanager.c492
-rw-r--r--cphidgetmanager.h153
-rw-r--r--cphidgetmotorcontrol.c1022
-rw-r--r--cphidgetmotorcontrol.h331
-rw-r--r--cphidgetphsensor.c241
-rw-r--r--cphidgetphsensor.h99
-rw-r--r--cphidgetrfid.c2791
-rw-r--r--cphidgetrfid.h331
-rw-r--r--cphidgetsbc.c255
-rw-r--r--cphidgetsbc.h71
-rw-r--r--cphidgetservo.c541
-rw-r--r--cphidgetservo.h142
-rw-r--r--cphidgetspatial.c1382
-rw-r--r--cphidgetspatial.h256
-rw-r--r--cphidgetstepper.c933
-rw-r--r--cphidgetstepper.h294
-rw-r--r--cphidgettemperaturesensor.c1319
-rw-r--r--cphidgettemperaturesensor.h172
-rw-r--r--cphidgettextlcd.c1160
-rw-r--r--cphidgettextlcd.h237
-rw-r--r--cphidgettextled.c492
-rw-r--r--cphidgettextled.h75
-rw-r--r--cphidgetweightsensor.c116
-rw-r--r--cphidgetweightsensor.h56
-rw-r--r--cppfooter3
-rw-r--r--cppheader21
-rw-r--r--csocket.h144
-rw-r--r--csocketevents.c2201
-rw-r--r--csocketevents.h21
-rw-r--r--csocketopen.c2641
-rw-r--r--cthread.c668
-rw-r--r--cthread.h64
-rw-r--r--cusb.h30
-rwxr-xr-xdepcomp630
-rw-r--r--dict/pdict-impl.h38
-rw-r--r--dict/pdict.c500
-rw-r--r--dict/pdict.h70
-rw-r--r--dict/pdictclient.c1490
-rw-r--r--dict/pdictclient.h128
-rw-r--r--examples/Makefile.am7
-rw-r--r--examples/Makefile.in499
-rw-r--r--examples/README13
-rw-r--r--examples/ifkit.c136
-rw-r--r--examples/manager.c73
-rw-r--r--examples/phidgetsbclist.c104
-rw-r--r--hotplug/phidgets7
-rw-r--r--hotplug/phidgets.usermap134
-rw-r--r--include/dns_sd.h2359
-rw-r--r--include/jni/jawt.h278
-rw-r--r--include/jni/jni.h1951
-rw-r--r--include/jni/jvmdi.h1012
-rw-r--r--include/jni/jvmpi.h642
-rw-r--r--include/jni/linux/jawt_md.h43
-rw-r--r--include/jni/linux/jni_md.h24
-rwxr-xr-xinstall-sh520
-rw-r--r--labview/phidget_labview.c429
-rw-r--r--labview/phidget_labview.h642
-rw-r--r--linux/avahi-client/client.h119
-rw-r--r--linux/avahi-client/lookup.h295
-rw-r--r--linux/avahi-client/publish.h174
-rw-r--r--linux/avahi-common/address.h121
-rw-r--r--linux/avahi-common/alternative.h45
-rw-r--r--linux/avahi-common/cdecl.h40
-rw-r--r--linux/avahi-common/defs.h354
-rw-r--r--linux/avahi-common/domain.h131
-rw-r--r--linux/avahi-common/error.h109
-rw-r--r--linux/avahi-common/gccmacro.h67
-rw-r--r--linux/avahi-common/llist.h77
-rw-r--r--linux/avahi-common/malloc.h98
-rw-r--r--linux/avahi-common/rlist.h51
-rw-r--r--linux/avahi-common/simple-watch.h87
-rw-r--r--linux/avahi-common/strlst.h182
-rw-r--r--linux/avahi-common/thread-watch.h82
-rw-r--r--linux/avahi-common/timeval.h56
-rw-r--r--linux/avahi-common/watch.h99
-rw-r--r--linux/cusblinux.c673
-rw-r--r--linux/zeroconf_avahi.c1056
-rwxr-xr-xltmain.sh8413
-rwxr-xr-xmissing376
-rw-r--r--phidget21.c38
-rw-r--r--phidget21.h793
-rw-r--r--phidget21int.h135
-rw-r--r--stdafx.h272
-rw-r--r--udev/99-phidgets.rules7
-rw-r--r--utils/cvtutf.c339
-rw-r--r--utils/cvtutf.h110
-rw-r--r--utils/md5.c382
-rw-r--r--utils/md5.h91
-rw-r--r--utils/plist.c151
-rw-r--r--utils/plist.h13
-rw-r--r--utils/ptree.c460
-rw-r--r--utils/ptree.h33
-rw-r--r--utils/utils.c1223
-rw-r--r--utils/utils.h49
-rwxr-xr-xversion.sh2
-rw-r--r--zeroconf.c1231
-rw-r--r--zeroconf.h19
-rw-r--r--zeroconf_lookup.c1713
296 files changed, 113289 insertions, 0 deletions
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..f8688f3
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1 @@
+Copyright (C) 2010 Phidgets Inc. <patrick@phidgets.com> \ No newline at end of file
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..02bbb60
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,165 @@
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+
+ This version of the GNU Lesser General Public License incorporates
+the terms and conditions of version 3 of the GNU General Public
+License, supplemented by the additional permissions listed below.
+
+ 0. Additional Definitions.
+
+ As used herein, "this License" refers to version 3 of the GNU Lesser
+General Public License, and the "GNU GPL" refers to version 3 of the GNU
+General Public License.
+
+ "The Library" refers to a covered work governed by this License,
+other than an Application or a Combined Work as defined below.
+
+ An "Application" is any work that makes use of an interface provided
+by the Library, but which is not otherwise based on the Library.
+Defining a subclass of a class defined by the Library is deemed a mode
+of using an interface provided by the Library.
+
+ A "Combined Work" is a work produced by combining or linking an
+Application with the Library. The particular version of the Library
+with which the Combined Work was made is also called the "Linked
+Version".
+
+ The "Minimal Corresponding Source" for a Combined Work means the
+Corresponding Source for the Combined Work, excluding any source code
+for portions of the Combined Work that, considered in isolation, are
+based on the Application, and not on the Linked Version.
+
+ The "Corresponding Application Code" for a Combined Work means the
+object code and/or source code for the Application, including any data
+and utility programs needed for reproducing the Combined Work from the
+Application, but excluding the System Libraries of the Combined Work.
+
+ 1. Exception to Section 3 of the GNU GPL.
+
+ You may convey a covered work under sections 3 and 4 of this License
+without being bound by section 3 of the GNU GPL.
+
+ 2. Conveying Modified Versions.
+
+ If you modify a copy of the Library, and, in your modifications, a
+facility refers to a function or data to be supplied by an Application
+that uses the facility (other than as an argument passed when the
+facility is invoked), then you may convey a copy of the modified
+version:
+
+ a) under this License, provided that you make a good faith effort to
+ ensure that, in the event an Application does not supply the
+ function or data, the facility still operates, and performs
+ whatever part of its purpose remains meaningful, or
+
+ b) under the GNU GPL, with none of the additional permissions of
+ this License applicable to that copy.
+
+ 3. Object Code Incorporating Material from Library Header Files.
+
+ The object code form of an Application may incorporate material from
+a header file that is part of the Library. You may convey such object
+code under terms of your choice, provided that, if the incorporated
+material is not limited to numerical parameters, data structure
+layouts and accessors, or small macros, inline functions and templates
+(ten or fewer lines in length), you do both of the following:
+
+ a) Give prominent notice with each copy of the object code that the
+ Library is used in it and that the Library and its use are
+ covered by this License.
+
+ b) Accompany the object code with a copy of the GNU GPL and this license
+ document.
+
+ 4. Combined Works.
+
+ You may convey a Combined Work under terms of your choice that,
+taken together, effectively do not restrict modification of the
+portions of the Library contained in the Combined Work and reverse
+engineering for debugging such modifications, if you also do each of
+the following:
+
+ a) Give prominent notice with each copy of the Combined Work that
+ the Library is used in it and that the Library and its use are
+ covered by this License.
+
+ b) Accompany the Combined Work with a copy of the GNU GPL and this license
+ document.
+
+ c) For a Combined Work that displays copyright notices during
+ execution, include the copyright notice for the Library among
+ these notices, as well as a reference directing the user to the
+ copies of the GNU GPL and this license document.
+
+ d) Do one of the following:
+
+ 0) Convey the Minimal Corresponding Source under the terms of this
+ License, and the Corresponding Application Code in a form
+ suitable for, and under terms that permit, the user to
+ recombine or relink the Application with a modified version of
+ the Linked Version to produce a modified Combined Work, in the
+ manner specified by section 6 of the GNU GPL for conveying
+ Corresponding Source.
+
+ 1) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (a) uses at run time
+ a copy of the Library already present on the user's computer
+ system, and (b) will operate properly with a modified version
+ of the Library that is interface-compatible with the Linked
+ Version.
+
+ e) Provide Installation Information, but only if you would otherwise
+ be required to provide such information under section 6 of the
+ GNU GPL, and only to the extent that such information is
+ necessary to install and execute a modified version of the
+ Combined Work produced by recombining or relinking the
+ Application with a modified version of the Linked Version. (If
+ you use option 4d0, the Installation Information must accompany
+ the Minimal Corresponding Source and Corresponding Application
+ Code. If you use option 4d1, you must provide the Installation
+ Information in the manner specified by section 6 of the GNU GPL
+ for conveying Corresponding Source.)
+
+ 5. Combined Libraries.
+
+ You may place library facilities that are a work based on the
+Library side by side in a single library together with other library
+facilities that are not Applications and are not covered by this
+License, and convey such a combined library under terms of your
+choice, if you do both of the following:
+
+ a) Accompany the combined library with a copy of the same work based
+ on the Library, uncombined with any other library facilities,
+ conveyed under the terms of this License.
+
+ b) Give prominent notice with the combined library that part of it
+ is a work based on the Library, and explaining where to find the
+ accompanying uncombined form of the same work.
+
+ 6. Revised Versions of the GNU Lesser General Public License.
+
+ The Free Software Foundation may publish revised and/or new versions
+of the GNU Lesser General Public License from time to time. Such new
+versions will be similar in spirit to the present version, but may
+differ in detail to address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Library as you received it specifies that a certain numbered version
+of the GNU Lesser General Public License "or any later version"
+applies to it, you have the option of following the terms and
+conditions either of that published version or of any later version
+published by the Free Software Foundation. If the Library as you
+received it does not specify a version number of the GNU Lesser
+General Public License, you may choose any version of the GNU Lesser
+General Public License ever published by the Free Software Foundation.
+
+ If the Library as you received it specifies that a proxy can decide
+whether future versions of the GNU Lesser General Public License shall
+apply, that proxy's public statement of acceptance of any version is
+permanent authorization for you to choose that version for the
+Library. \ No newline at end of file
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 0000000..a21dc7b
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,471 @@
+2.1.8
+new webservice version - 1.0.8
+-support for new devices
+-support for error events
+
+2.1.7.20110203
+fixed crash on close of remote Phidget on MacOS
+C# ifkit example bugfix - crashed on 1015/1016
+webservice improvements
+Switch to IP address for SBC config in browser
+Faster IP lookup for SBCs in control panel
+
+2.1.7.20101222 / 2.1.7.20101223
+fixed getServerID on Linux
+removed report ack
+this was causing some bad side effects
+manual .local lookups on Windows
+much faster then letting Windows do it itself
+Support for new Labview library
+Fixed PhidgetIR bug where library would crash if repeat code is longer then IR_MAX_REPEAT_LENGTH
+
+2.1.7.20101103
+Decreased Phidget Webservice event latency on Windows
+Preliminary support for 1002, 1011, 1040, 1045, 1046, 1054, 1065, 1204 (C, .NET)
+Webservice version updated to 1.0.7
+support for 1045, 1011, 1204
+Fixed a bug where webservice connections could be unexpectedly lost
+Bugfix: couldn't set interfacekit data rate over webservice.
+Fixed some memory leaks in the Mac library
+Fixed bug where blocking for >2 seconds in an events handler when opening remotely could cause a crash.
+
+2.1.7.20100803
+Windows only release
+fixed setLabel in WindowsCE
+fixed getHashCode in .NET library - needed for working with Phidgets in Labview via .NET
+
+2.1.7.20100621
+Linux only release - autotools updates
+call ldconfig automatically
+remove old phidget21 library (pre-autotools) when installing new one.
+
+2.1.7.20100620
+Linux only release - added version.sh for autoreconf
+
+2.1.7.20100618
+Linux only release - added udev/hotplug files
+
+2.1.7.20100617
+Linux only release
+Transitioned to autotools in linux for phidget21 / webservice
+phidget21 library and webservice are now separate downloads
+
+2.1.7.20100525
+full support for PhidgetSpatial and PhidgetIR in all libraries
+fixed 1031 not attaching in AS3.0
+Better error messages in JNI
+Updated error codes, device ID/Class lists in Java, Flash, COM, etc.
+Fixed TemperatureSensor version 200,201,202 bug - ambient sensor would not report negative temperatures.
+Revised temperaturesensor API to report tempMin/tempMax and errors more accurately.
+Added initial events for encoder digital inputs
+full support for 1047
+Added new device support to WindowsCE
+Updated mac examples for 1047, 1048
+
+2.1.6.20100504
+Windows only Release
+Added 1131 and 1132 to InterfaceKit example in MSI
+
+2.1.6.20100428
+limit data rate maximum to 16ms over the webservice for devices that expose dataRate (InterfaceKit, Spatial)
+fixed bug where TextLCD 8/8/8 would stay in Bonjour list after webservice is shutdown
+set/get Brightness for 1203_2
+Support 1048 in C# example
+webservice version incremented to 1.0.6
+TextLCD set/get brightness
+PhidgetIR support
+PhidgetSpatial support
+1047 support (enable, index)
+
+2.1.6.20100406
+Support for 1018_2, 1203_2 (dataRate)
+Webservice version incremented to 1.0.5
+
+2.1.6.20100401
+Updated InterfaceKit example with new sensors
+make Windows connect cancelable
+make pending zeroconf lookups cancelable during close
+
+2.1.6.20100318
+Mac only release
+Added WillSleep and Wakeup events to give user control of Phidgets immediately before and after a system sleep (MacOS Only).
+
+2.1.6.20100317
+Windows only release
+Some of the examples were being built using an out of date .NET library
+
+2.1.6.20100310
+MaxMSP fix - 2.1.6.20100126 introduced a bug for some Phidgets where openremote/open by serial didn't work and MaxMSP would sometimes crash.
+No code changes to any of the other libraries.
+
+2.1.6.20100304
+stopped property changes trigger events over webservice so they are noticed.
+more compatible with how local open works
+added 5 new servos
+fixed bug where remote close would not set detached so a subsequent open would not always connect.
+handle UninitializeZeroconf better - shut down thread before closing handles, fixes hang on SBC
+fixed bug on Mac where detaching 2 or more Phidgets at the same time caused a crash
+fixed close blocking because of a pending connect (mac, linux)
+Final support for 1031 in all libraries.
+
+2.1.6.20100129
+Implemented initial events in Flash
+Flash behaviour should now be identical to C library local and remote.
+Fix RFID issue where close could cause crash
+increment webservice version to 1.0.4
+fixed RFID remote open
+Flash would never get an attach event if the reader had been previously opened
+Initial tag event would not be fired when a tag was present and the antenna was enabled prior to open
+fixed openRemote failing on Mac
+fixed deadlock in webservice which could be hit by opening/closing a device over and over again.
+fixed bug in stepper, which caused seg fault on SBC on position change events.
+
+2.1.6.20100126
+added network open support in Max/MSP
+
+2.1.6.20100115
+Increased network performance for Linux/MacOS
+Added five servo types
+
+2.1.6.20091215
+Fixed busy loop in Linux openRemote
+JNI Library relocated to /Library/Java/Extensions on MacOS
+
+2.1.6.20091211
+Heartbeat now works on Linux as well (had to make sockets non-blocking)
+
+2.1.6.20091130
+Added heartbeat to webservice (client side)
+Better detects network failures by using active polling timeouts
+Fixed 0/8/8 over webservice
+
+2.1.6.20091020
+Fixed 1052 counting issue on 1070 (-1 reported as 255)
+Fixed issue where Phidget21 would try to reinstall from a limited user account or when the Control Panel was disabled.
+64-bit kernel support in Snow Leopard
+
+2.1.6.20090928
+Support for PhidgetSBC (1070)
+zeroconf can handle starting up before the mdns daemon, and will keep trying to connect.
+fixed 1066 not showing up on Mac
+added advanced servo example to mac pref pane
+implemented proper error handling in COM
+default behavious remains the same, enable proper error handling with 'EnableVerboseErrors'
+implemented error events in Java
+
+2.1.6.20090917
+Updated webservice protocol version to 1.0.3
+Fixed stepper under AS3.0
+added setServoType, getServoType, setServoParameters to PhidgetServo and PhidgetAdvancedServo
+possible race condition fixed in webservice (pdictclient.c:907)
+
+2.1.6.20090902
+Support MacOSX 10.6, drop support for 10.3.9, require 10.4 or newer
+Fully 64-bit compliant, library supports ppc, i386, x86_64
+
+2.1.6.20090806
+Added 1049 support
+Fixed RFID tag events over webservice
+
+2.1.6.20090804
+Added 1051_2 support
+Fixed various small initialization issues - stepper, adv servo, rfid
+Added 32-bit library install to 64-bit installer
+VB6.0, etc. need the 32-bit COM library on 64-bit windows
+
+2.1.6.20090708
+Added DeviceID to zeroconf
+fixed RFID.LastTag in .NET
+Changed the error codes returned by error events; error events now have their own set of error codes rather then sharing the function return codes.
+Added support for 1047, 1048
+Added error event codes rather then trying to reuse the EPHIDGET return codes.
+fixed TextLCD issue where display could get corrupted during a detach/attach
+made mac more reliable on attach
+more error logging on mac
+
+2.1.6.20090525
+fixed RFID not attaching via webservice if a tag is present.
+bugfix related to double free on detach event.
+Implemented getKey
+Added MIPS II support to Windows CE
+
+2.1.6.20090430
+Added ActiveX interface to COM library
+Added stepper and advancedServo to Flex .swc library
+
+2.1.6.20090417
+added PhidgetIR prototype support to C library
+properly handles sleeping on OSX
+fixed some webservice field initializations in Flash and C
+fixed security exceptions in Phidget Control Panel under Vista
+added Phidget Control Panel to start menu
+Fixed AdvancedServo in Flash - wouldn't attach
+
+2.1.6.20090317
+Phidget control panel properly supports Vista UAC and Limited user accounts in XP, etc.
+Added 64-bit release of Phidget21.msi for Windows
+
+2.1.6.20090312
+added 1064, 1059 to WindowsCE
+fixed opening 1051 over webservice
+fixed opening 1015/1016 over webservice broken in last release
+
+2.1.6.20090302
+Advanced servo bugfix: stopped would stop being true if min/max was set to exclude current position.
+linux USB improvements when many Phidgets are attached and opened at once.
+1031 support in phidget21, webservice, .NET - hidden until product release
+CPhidgetLED_setVoltage
+CPhidgetLED_getVoltage
+CPhidgetLED_setCurrentLimit
+CPhidgetLED_getCurrentLimit
+unknown timechange == PUNK_INT in encoder position change event
+1st position change event
+>30 seconds time change
+AS3 updates
+updated to 1.0.2 webservice
+encoder position change events report relative change rather then absolute position
+encoder adds getTimeChange function for timing encoder changes
+webservice updated to 1.0.2
+Authorization is asynchronous
+Doesn't match the old version checking, so errors will not be nice when trying to connect to an old webservice
+Sends out all initial data, so it's just like opening locally
+supports interfacekit Raw sensor value
+supports labels on remoteIP managers
+avahi bugfix
+webservice more stable against forcefully closed clients
+closing a network Phidget won't block - ever.
+no longer using quit, just closing the socket
+added libavahi-client.so.3 reference to linux library.
+Fixed bug with opening one phidget with serial and no serial at the same time over the webservice
+
+2.1.5.20090105
+Phidget control panel stability improvements
+added CPhidgetSBC_getHostname
+advanced servo 1 motor current sense equation - support should now be complete
+webservice and network code bugfixes - crash / deadlock during close, problems with concurrent connections, etc.
+fixed close on remote and remoteIP managers
+name of RFID changed from "Phidget RFID 4-output" to "Phidget RFID 2-output" - updated anything referencing old name.
+
+2.1.5.20081023
+added advanced servo and stepper examples to VB6.0, VB.NET and C
+added deviceClass and deviceID
+updated Mac examples
+webservice protocol version enforcement
+internal fix/rework of device id's etc.
+Fixed memory leaks in webservice and phidget21 network code.
+Dictionary and network stability improvements.
+duplicate calls to open or close are now silently ignored.
+
+2.1.4.20080924
+Old TextLCD 0/8/8's can now have both halves open at the same time on Windows
+fixed bug with composite devices on linux
+fixed manager on linux to better deal with unique devices
+
+2.1.4.20080922
+Updated Delphi files
+TextLCD can display 0x80-0xFF characters from Java
+getAttachedDevices works for mdns managers
+fixed a deadlock in the webservice
+better network error handling / password support for windows C# examples
+waitForAttachment will return EPHIDGET_CLOSED if the handle is closed while it is waiting.
+added EPHIDGET_CLOSED
+joining central threads checks whether they are trying to be joined by themselves first (avoid deadlocks).
+changed context of error event to be free from locks (can call close, open, etc. from them).
+
+2.1.4.20080821
+zeroconf threads exit cleanly on last _close (apple zeroconf)
+Added advanced servo and stepper to Max
+
+2.1.4.20080811
+Fixed manager on Mac (wasn't working at all since 2.1.4.20080808)
+
+2.1.4.20080808
+added CPhidgetSBC and CPhidgetSBCManager to the c library - these interfaces are hidden from users and meant to be used internally (for now).
+CPhidgetManager_open no longer blocks to send out initial attach events. These initial events are sent from the CentralThread context like all other attach events.
+fixed CThread_wait_on_event on Linux
+added CPhidgetGeneric interface for prototyping to C, .NET libraries. product ID is 0x99. These are only visible in debug releases, only to be used internally.
+
+2.1.4.20080715
+udev rules fixed for product IDs with alpha-hex values
+blocking in an attach event does not block calls to open anymore
+RFID tag event handlers can now handle blocking - tag lost is timed after the tag handler exits.
+
+2.1.4.20080623
+Flex .swc library was out of sync
+fixed CPhidgetManager_getAttachedDevices for network managers
+Added CPhidgetManager_freeAttachedDevicesArray
+
+2.1.4.20080613
+Max/MSP RFID fixed
+0/0/8 and advanced servo added to CE
+fixed flash policy file server in webservice
+webservice with password and asynchronous together work now
+
+2.1.4.20080602
+phidget21.h -> phidget21int.h so as not to be confused with generated phidget21.h
+some changes to Makefile fro crosscompiling
+no more vbscript in msi
+
+2.1.4.20080513
+removed long long from COM - not supported by VB6.0
+added LastTag to RFID in .NET
+
+2.1.4.20080428
+support Mac OS X 10.3.9 again
+Rev up to 2.1.4
+finalize Phidget Stepper API - Phidget Stepper requires 2.1.4 as a minimum
+fixed serverConnect and serverDisconnect handlers for manager and dictionary in COM
+Changed:
+PhidgetStepper and PhidgetAdvancedServo
+MotorPosition -> Position
+MotorOn -> Engaged
+MotorStopped -> Stopped
+Added:
+CPhidgetStepper_getCurrentLimit
+CPhidgetEncoder_getPosition
+CPhidgetEncoder_setPosition
+CPhidgetMotorControl_getVelocity
+CPhidgetMotorControl_setVelocity
+CPhidgetMotorControl_set_OnVelocityChange_Handler
+CPhidgetServo_setEngaged
+CPhidgetServo_getEngaged
+CPhidgetServo_getPosition
+CPhidgetServo_setPosition
+CPhidgetServo_set_OnPositionChange_Handler
+CPhidgetServo_getPositionMax
+CPhidgetServo_getPositionMin
+Count functions
+Deprecated:
+CPhidgetEncoder_getEncoderPosition
+CPhidgetEncoder_setEncoderPosition
+CPhidgetMotorControl_getMotorSpeed
+CPhidgetMotorControl_setMotorSpeed
+CPhidgetMotorControl_set_OnMotorChange_Handler
+CPhidgetServo_setMotorOn
+CPhidgetServo_getMotorOn
+CPhidgetServo_getMotorPosition
+CPhidgetServo_setMotorPosition
+CPhidgetServo_set_OnMotorPositionChange_Handler
+CPhidgetServo_getMotorPositionMax
+CPhidgetServo_getMotorPositionMin
+Num functions
+Added ability to deprecate funcitons in the C library - compiler will issue a warning when they are used.
+added names to some arguments in phidget21.h
+fixes to the webservice for initial state stuff - now it behaves almost like non-webservice, with guaranteed initial events, but we don't guarantee initial state in the attach event yet. Min/Max, Num motors, inputs, etc. are all guaranteed in the attach handler.
+Finalized support for Phidget Stepper
+
+2.1.3.20080402
+Fixed windows BUG - Device Type was showing up wrong
+CPhidgetStepper_getPosition -> CPhidgetStepper_getCurrentPosition
+
+2.1.3.20080327
+added:
+CPhidgetAdvancedServo_setMotorPositionMax
+CPhidgetAdvancedServo_setMotorPositionMin
+CPhidgetAdvancedServo_getMotorStopped
+changes to API:
+CPhidgetStepper_setMotorPosition -> CPhidgetStepper_setTargetMotorPosition
+added CPhidgetStepper_getTargetMotorPosition
+Stepper MotorSpeed -> Velocity
+Stepper and AdvancedServo MaxVelocity -> VelocityLimit
+add waitForAttachment to COM
+COM getbool (not indexed) will now return FALSE on false (rather then always returning true)
+fixed write thread timeouts - was setting attached after starting write thread so write thread would see a detached device and exit immediately
+
+2.1.3.20080206
+changed long long to __int64, to be happy in borland C++
+added:
+CPhidgetStepper_getMaxMotorSpeed
+CPhidgetStepper_setMotorOn
+CPhidgetStepper_getMotorOn
+CPhidgetStepper_getMotorStopped
+CPhidgetStepper_setCurrentMotorPosition
+removed CPhidgetStepper_setVelocity
+added CPhidgetStepper_setMaxVelocity, CPhidgetStepper_getMaxVelocity
+
+2.1.3.20080114
+Added new functions to Flash API
+Added new functions to Webservice Protocol
+Added new functions to COM Library
+Added new functions to Java Library
+All device fiels in C library cleaned up and made consistent
+Open in windows is exclusive - this needs to be tested for stability
+No data will be returned / accepted if it lies outside of max/min range
+if a data value is unknown, user variable is set to PUNK_INT, PUNK_DBL, or PUNK_BOOL, and return value is EPHIDGET_UNKNOWNVAL
+Proper Device initializations on Attach:
+triggers are set to defaults on attach
+device state is read in and preserved on attach
+during attach event, all sensor data, etc. is provided if available
+no data events until after the attach event returns
+everything initialized by the time waitForAttachment returns
+after attach event returns, a full set of initial state data events are thrown
+.NET collections are readonly, and never NULL (but empty when phidget detached)
+.NET callbacks no longer catch and hide all exceptions
+make sure to use try/catch blocks especially in Attach when accessing properties that may not be initialized.
+added min/max functions:
+CPhidgetAccelerometer_getAccelerationMax
+CPhidgetAccelerometer_getAccelerationMin
+CPhidgetAdvancedServo_getAccelerationMax
+CPhidgetAdvancedServo_getAccelerationMin
+CPhidgetAdvancedServo_getVelocityMax
+CPhidgetAdvancedServo_getVelocityMin
+CPhidgetAdvancedServo_getMotorPositionMax
+CPhidgetAdvancedServo_getMotorPositionMin
+CPhidgetMotorControl_getAccelerationMax
+CPhidgetMotorControl_getAccelerationMin
+CPhidgetPHSensor_getPHMax
+CPhidgetPHSensor_getPHMin
+CPhidgetPHSensor_getPotentialMax
+CPhidgetPHSensor_getPotentialMin
+CPhidgetServo_getMotorPositionMax
+CPhidgetServo_getMotorPositionMin
+CPhidgetStepper_getAccelerationMax
+CPhidgetStepper_getAccelerationMin
+CPhidgetStepper_getMotorSpeedMax
+CPhidgetStepper_getMotorSpeedMin
+CPhidgetStepper_getMotorPositionMax
+CPhidgetStepper_getMotorPositionMin
+CPhidgetTemperatureSensor_getPotentialMax
+CPhidgetTemperatureSensor_getPotentialMin
+CPhidgetTemperatureSensor_getAmbientTemperatureMax
+CPhidgetTemperatureSensor_getAmbientTemperatureMin
+CPhidgetTemperatureSensor_getTemperatureMax
+CPhidgetTemperatureSensor_getTemperatureMin
+Added functions:
+CPhidgetTemperatureSensor_getAmbientTemperature
+CPhidgetTemperatureSensor_getThermocoupleType
+CPhidgetTemperatureSensor_setThermocoupleType
+CPhidget_set_OnServerConnectHandler
+CPhidget_set_OnServerDisconnectHandler
+CPhidgetDictionary_set_OnServerConnectHandler
+CPhidgetDictionary_set_OnServerDisconnectHandler
+CPhidgetManager_set_OnServerConnectHandler
+CPhidgetManager_set_OnServerDisconnectHandler
+CPhidgetDictionary_getServerID
+CPhidgetDictionary_getServerAddress
+CPhidgetDictionary_getServerStatus
+CPhidgetManager_getServerID
+CPhidgetManager_getServerAddress
+CPhidgetManager_getServerStatus
+CPhidgetServo_setMotorOn
+CPhidgetServo_getMotorOn
+Removed functions:
+CPhidgetServo_setMotorOff
+TemperatureSensor:
+Ambient sensor is accessed with it's own function
+first thermocouple is Index 0 everywhere
+no ambient sensor events
+getServerID is implemented
+changed the internal network structure (added CPhidgetRemote)
+reworked the USB code (mostly on Windows)
+Better handles closing, ESD events, timeouts
+fixed issues with Encoder, RFID stopping reading after a certain time.
+added USB error flag
+openRemote functions have been implemented
+these require bonjour (mac / windows) or avahi (linux) to be installed on both the client and server
+if they are not, you get EPHIDGET_UNSUPPORTED when you call them
+openRemoteIP functions are asynchronous and persistent
+include cphidgetconstants.h in phidget21.h for users
+
+2.1.2.20071108
+Start of changelog \ No newline at end of file
diff --git a/INSTALL b/INSTALL
new file mode 100644
index 0000000..2550dab
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,302 @@
+Installation Instructions
+*************************
+
+Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005,
+2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+
+ This file is free documentation; the Free Software Foundation gives
+unlimited permission to copy, distribute and modify it.
+
+Basic Installation
+==================
+
+ Briefly, the shell commands `./configure; make; make install' should
+configure, build, and install this package. The following
+more-detailed instructions are generic; see the `README' file for
+instructions specific to this package.
+
+ The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation. It uses
+those values to create a `Makefile' in each directory of the package.
+It may also create one or more `.h' files containing system-dependent
+definitions. Finally, it creates a shell script `config.status' that
+you can run in the future to recreate the current configuration, and a
+file `config.log' containing compiler output (useful mainly for
+debugging `configure').
+
+ It can also use an optional file (typically called `config.cache'
+and enabled with `--cache-file=config.cache' or simply `-C') that saves
+the results of its tests to speed up reconfiguring. Caching is
+disabled by default to prevent problems with accidental use of stale
+cache files.
+
+ If you need to do unusual things to compile the package, please try
+to figure out how `configure' could check whether to do them, and mail
+diffs or instructions to the address given in the `README' so they can
+be considered for the next release. If you are using the cache, and at
+some point `config.cache' contains results you don't want to keep, you
+may remove or edit it.
+
+ The file `configure.ac' (or `configure.in') is used to create
+`configure' by a program called `autoconf'. You need `configure.ac' if
+you want to change it or regenerate `configure' using a newer version
+of `autoconf'.
+
+The simplest way to compile this package is:
+
+ 1. `cd' to the directory containing the package's source code and type
+ `./configure' to configure the package for your system.
+
+ Running `configure' might take a while. While running, it prints
+ some messages telling which features it is checking for.
+
+ 2. Type `make' to compile the package.
+
+ 3. Optionally, type `make check' to run any self-tests that come with
+ the package.
+
+ 4. Type `make install' to install the programs and any data files and
+ documentation.
+
+ 5. You can remove the program binaries and object files from the
+ source code directory by typing `make clean'. To also remove the
+ files that `configure' created (so you can compile the package for
+ a different kind of computer), type `make distclean'. There is
+ also a `make maintainer-clean' target, but that is intended mainly
+ for the package's developers. If you use it, you may have to get
+ all sorts of other programs in order to regenerate files that came
+ with the distribution.
+
+ 6. Often, you can also type `make uninstall' to remove the installed
+ files again.
+
+Compilers and Options
+=====================
+
+ Some systems require unusual options for compilation or linking that
+the `configure' script does not know about. Run `./configure --help'
+for details on some of the pertinent environment variables.
+
+ You can give `configure' initial values for configuration parameters
+by setting variables in the command line or in the environment. Here
+is an example:
+
+ ./configure CC=c99 CFLAGS=-g LIBS=-lposix
+
+ *Note Defining Variables::, for more details.
+
+Compiling For Multiple Architectures
+====================================
+
+ You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory. To do this, you can use GNU `make'. `cd' to the
+directory where you want the object files and executables to go and run
+the `configure' script. `configure' automatically checks for the
+source code in the directory that `configure' is in and in `..'.
+
+ With a non-GNU `make', it is safer to compile the package for one
+architecture at a time in the source code directory. After you have
+installed the package for one architecture, use `make distclean' before
+reconfiguring for another architecture.
+
+ On MacOS X 10.5 and later systems, you can create libraries and
+executables that work on multiple system types--known as "fat" or
+"universal" binaries--by specifying multiple `-arch' options to the
+compiler but only a single `-arch' option to the preprocessor. Like
+this:
+
+ ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
+ CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
+ CPP="gcc -E" CXXCPP="g++ -E"
+
+ This is not guaranteed to produce working output in all cases, you
+may have to build one architecture at a time and combine the results
+using the `lipo' tool if you have problems.
+
+Installation Names
+==================
+
+ By default, `make install' installs the package's commands under
+`/usr/local/bin', include files under `/usr/local/include', etc. You
+can specify an installation prefix other than `/usr/local' by giving
+`configure' the option `--prefix=PREFIX'.
+
+ You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files. If you
+pass the option `--exec-prefix=PREFIX' to `configure', the package uses
+PREFIX as the prefix for installing programs and libraries.
+Documentation and other data files still use the regular prefix.
+
+ In addition, if you use an unusual directory layout you can give
+options like `--bindir=DIR' to specify different values for particular
+kinds of files. Run `configure --help' for a list of the directories
+you can set and what kinds of files go in them.
+
+ If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving `configure' the
+option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+
+Optional Features
+=================
+
+ Some packages pay attention to `--enable-FEATURE' options to
+`configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to `--with-PACKAGE' options, where PACKAGE
+is something like `gnu-as' or `x' (for the X Window System). The
+`README' should mention any `--enable-' and `--with-' options that the
+package recognizes.
+
+ For packages that use the X Window System, `configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the `configure' options `--x-includes=DIR' and
+`--x-libraries=DIR' to specify their locations.
+
+Particular systems
+==================
+
+ On HP-UX, the default C compiler is not ANSI C compatible. If GNU
+CC is not installed, it is recommended to use the following options in
+order to use an ANSI C compiler:
+
+ ./configure CC="cc -Ae -D_XOPEN_SOURCE=500"
+
+and if that doesn't work, install pre-built binaries of GCC for HP-UX.
+
+ On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot
+parse its `<wchar.h>' header file. The option `-nodtk' can be used as
+a workaround. If GNU CC is not installed, it is therefore recommended
+to try
+
+ ./configure CC="cc"
+
+and if that doesn't work, try
+
+ ./configure CC="cc -nodtk"
+
+ On Solaris, don't put `/usr/ucb' early in your `PATH'. This
+directory contains several dysfunctional programs; working variants of
+these programs are available in `/usr/bin'. So, if you need `/usr/ucb'
+in your `PATH', put it _after_ `/usr/bin'.
+
+ On Haiku, software installed for all users goes in `/boot/common',
+not `/usr/local'. It is recommended to use the following options:
+
+ ./configure --prefix=/boot/common
+
+Specifying the System Type
+==========================
+
+ There may be some features `configure' cannot figure out
+automatically, but needs to determine by the type of machine the package
+will run on. Usually, assuming the package is built to be run on the
+_same_ architectures, `configure' can figure that out, but if it prints
+a message saying it cannot guess the machine type, give it the
+`--build=TYPE' option. TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name which has the form:
+
+ CPU-COMPANY-SYSTEM
+
+where SYSTEM can have one of these forms:
+
+ OS
+ KERNEL-OS
+
+ See the file `config.sub' for the possible values of each field. If
+`config.sub' isn't included in this package, then this package doesn't
+need to know the machine type.
+
+ If you are _building_ compiler tools for cross-compiling, you should
+use the option `--target=TYPE' to select the type of system they will
+produce code for.
+
+ If you want to _use_ a cross compiler, that generates code for a
+platform different from the build platform, you should specify the
+"host" platform (i.e., that on which the generated programs will
+eventually be run) with `--host=TYPE'.
+
+Sharing Defaults
+================
+
+ If you want to set default values for `configure' scripts to share,
+you can create a site shell script called `config.site' that gives
+default values for variables like `CC', `cache_file', and `prefix'.
+`configure' looks for `PREFIX/share/config.site' if it exists, then
+`PREFIX/etc/config.site' if it exists. Or, you can set the
+`CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all `configure' scripts look for a site script.
+
+Defining Variables
+==================
+
+ Variables not defined in a site shell script can be set in the
+environment passed to `configure'. However, some packages may run
+configure again during the build, and the customized values of these
+variables may be lost. In order to avoid this problem, you should set
+them in the `configure' command line, using `VAR=value'. For example:
+
+ ./configure CC=/usr/local2/bin/gcc
+
+causes the specified `gcc' to be used as the C compiler (unless it is
+overridden in the site shell script).
+
+Unfortunately, this technique does not work for `CONFIG_SHELL' due to
+an Autoconf bug. Until the bug is fixed you can use this workaround:
+
+ CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash
+
+`configure' Invocation
+======================
+
+ `configure' recognizes the following options to control how it
+operates.
+
+`--help'
+`-h'
+ Print a summary of all of the options to `configure', and exit.
+
+`--help=short'
+`--help=recursive'
+ Print a summary of the options unique to this package's
+ `configure', and exit. The `short' variant lists options used
+ only in the top level, while the `recursive' variant lists options
+ also present in any nested packages.
+
+`--version'
+`-V'
+ Print the version of Autoconf used to generate the `configure'
+ script, and exit.
+
+`--cache-file=FILE'
+ Enable the cache: use and save the results of the tests in FILE,
+ traditionally `config.cache'. FILE defaults to `/dev/null' to
+ disable caching.
+
+`--config-cache'
+`-C'
+ Alias for `--cache-file=config.cache'.
+
+`--quiet'
+`--silent'
+`-q'
+ Do not print messages saying which checks are being made. To
+ suppress all normal output, redirect it to `/dev/null' (any error
+ messages will still be shown).
+
+`--srcdir=DIR'
+ Look for the package's source code in directory DIR. Usually
+ `configure' can determine that directory automatically.
+
+`--prefix=DIR'
+ Use DIR as the installation prefix. *Note Installation Names::
+ for more details, including other options available for fine-tuning
+ the installation locations.
+
+`--no-create'
+`-n'
+ Run the configure checks, but stop before creating any output
+ files.
+
+`configure' also accepts some other, not widely useful, options. Run
+`configure --help' for more details.
+
diff --git a/Java/com/phidgets/AccelerometerPhidget.java b/Java/com/phidgets/AccelerometerPhidget.java
new file mode 100644
index 0000000..c0c82ae
--- /dev/null
+++ b/Java/com/phidgets/AccelerometerPhidget.java
@@ -0,0 +1,116 @@
+
+/*
+ * Copyright 2006 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets;
+import java.util.Iterator;
+import java.util.LinkedList;
+import com.phidgets.event.*;
+/**
+ * This class represents a Phidget Accelerometer. All methods to read
+ * acceleration data from an Accelerometer are implemented in this class.
+ <p>
+ The Phidget Accelerometer provides 2 or 3 axes of acceleration data, at anywhere from 2g to 10g
+ sensitivity, depending on the specific revision. See your hardware documetation for more information.
+ They can measure both static (gravity) and dynamic acceleration.
+
+ * @author Phidgets Inc.
+ */
+public final class AccelerometerPhidget extends Phidget
+{
+ public AccelerometerPhidget () throws PhidgetException
+ {
+ super (create ());
+ }
+ private static native long create () throws PhidgetException;
+
+ /**
+ * Returns the number of accelerometer axes. Currently all accelerometers provide two or three axes of acceleration - x, y, (and z).
+ * @return number of axes of acceleration
+ */
+ public native int getAxisCount () throws PhidgetException;
+ /**
+ * Returns the acceleration of a particular axis. This value is returned in g's, where one g of acceleration is
+ * equal to gravity. This means that at a standstill each axis will measure between -1.0 and 1.0 g's depending on
+ * orientation.
+ * <P>
+ * This value will always be between {@link #getAccelerationMin getAccelerationMin} and {@link #getAccelerationMax getAccelerationMax}.
+ * <p>
+ * Index 0 is the x-axis, 1 is the y-axis, and 2 is the z-axis (where available).
+ *
+ * @param index index of the axis
+ * @return acceleration of the selected axis
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is out of range.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native double getAcceleration (int index) throws PhidgetException;
+ /**
+ * Returns the maximum acceleration value that this axis will report. This will be set to just higher then the maximum
+ * acceleration that this axis can measure. If the acceleration is equal to this maximum, assume that that axis is saturated
+ * beyond what it can measure.
+ * @return maximum acceleration
+ */
+ public native double getAccelerationMax (int index) throws PhidgetException;
+ /**
+ * Returns the minimum acceleration value that this axis will report. This will be set to just lower then the minimum
+ * acceleration that this axis can measure. If the acceleration is equal to this minimum, assume that that axis is saturated
+ * beyond what it can measure.
+ * @return minimum acceleration
+ */
+ public native double getAccelerationMin (int index) throws PhidgetException;
+ /**
+ * Sets the change trigger for an Axis. This value is in g's and is by default set to 0.
+ * This is the difference in acceleration that must appear between succesive calls to the
+ * OnAccelerationChange event handler.
+ * @param index index of the axis
+ * @param newVal the new change trigger for this axis
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is out of range.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native void setAccelerationChangeTrigger (int index, double newVal) throws PhidgetException;
+ /**
+ * Returns the change trigger for an Axis. This value is in g's and is by default set to 0.
+ * @param index index of the axis
+ * @return change trigger of the selected axis
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is out of range.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native double getAccelerationChangeTrigger (int index) throws PhidgetException;
+
+ private final void enableDeviceSpecificEvents (boolean b)
+ {
+ enableAccelerationChangeEvents (b && accelerationChangeListeners.size () > 0);
+ }
+ /**
+ * Adds an acceleration change listener. The acceleration change handler is a method that will be called when the acceleration
+ * of an axis has changed by at least the {@link #getAccelerationChangeTrigger(int) Trigger} that has been set for that axis.
+ * <p>
+ * There is no limit on the number of acceleration change handlers that can be registered for a particular Phidget.
+ *
+ * @param l An implemetation of the {@link com.phidgets.event.AccelerationChangeListener AccelerationChangeListener} interface
+ */
+ public final void addAccelerationChangeListener (AccelerationChangeListener l)
+ {
+ synchronized (accelerationChangeListeners)
+ {
+ accelerationChangeListeners.add (l);
+ enableAccelerationChangeEvents (true);
+ }} private LinkedList accelerationChangeListeners = new LinkedList ();
+ private long nativeAccelerationChangeHandler = 0;
+ public final void removeAccelerationChangeListener (AccelerationChangeListener l)
+ {
+ synchronized (accelerationChangeListeners)
+ {
+ accelerationChangeListeners.remove (l);
+ enableAccelerationChangeEvents (accelerationChangeListeners.size () > 0);
+ }} private void fireAccelerationChange (AccelerationChangeEvent e)
+ {
+ synchronized (accelerationChangeListeners)
+ {
+ for (Iterator it = accelerationChangeListeners.iterator (); it.hasNext ();)
+ ((AccelerationChangeListener) it.next ()).accelerationChanged (e);
+ }
+ }
+ private native void enableAccelerationChangeEvents (boolean b);
+}
diff --git a/Java/com/phidgets/AdvancedServoPhidget.java b/Java/com/phidgets/AdvancedServoPhidget.java
new file mode 100644
index 0000000..1aa485a
--- /dev/null
+++ b/Java/com/phidgets/AdvancedServoPhidget.java
@@ -0,0 +1,492 @@
+
+/*
+ * Copyright 2006 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets;
+import java.util.Iterator;
+import java.util.LinkedList;
+import com.phidgets.event.*;
+/**
+ * This class represents a Phidget Advanced Servo Controller. All methods
+ * to to control a motor controller and read back motor data are implemented in this class.
+ * <p>
+ * The Phidget Advanced Servo Controller is able to control 1 or more servo motors. Motos acceleration
+ * and Velocity are controllable. The number of servos that can be controlled depends on the
+ * version of the controller.
+ *
+ * @author Phidgets Inc.
+ */
+public final class AdvancedServoPhidget extends Phidget
+{
+ public AdvancedServoPhidget () throws PhidgetException
+ {
+ super (create ());
+ }
+ private static native long create () throws PhidgetException;
+
+ /**
+ * Default - This is what the servo API been historically used, originally based on the Futaba FP-S148. This is used with {@link #getServoType getServoType} and {@link #setServoType setServoType}
+ */
+ public static final int PHIDGET_SERVO_DEFAULT = 1;
+ /**
+ * Raw us mode - all position, velocity, acceleration functions are specified in microseconds rather then degrees. This is used with {@link #getServoType getServoType} and {@link #setServoType setServoType}
+ */
+ public static final int PHIDGET_SERVO_RAW_us_MODE = 2;
+ /**
+ * HiTec HS-322HD Standard Servo. This is used with {@link #getServoType getServoType} and {@link #setServoType setServoType}
+ */
+ public static final int PHIDGET_SERVO_HITEC_HS322HD = 3;
+ /**
+ * HiTec HS-5245MG Digital Mini Servo. This is used with {@link #getServoType getServoType} and {@link #setServoType setServoType}
+ */
+ public static final int PHIDGET_SERVO_HITEC_HS5245MG = 4;
+ /**
+ * HiTec HS-805BB Mega Quarter Scale Servo. This is used with {@link #getServoType getServoType} and {@link #setServoType setServoType}
+ */
+ public static final int PHIDGET_SERVO_HITEC_805BB = 5;
+ /**
+ * HiTec HS-422 Standard Servo. This is used with {@link #getServoType getServoType} and {@link #setServoType setServoType}
+ */
+ public static final int PHIDGET_SERVO_HITEC_HS422 = 6;
+ /**
+ * Tower Pro MG90 Micro Servo. This is used with {@link #getServoType getServoType} and {@link #setServoType setServoType}
+ */
+ public static final int PHIDGET_SERVO_TOWERPRO_MG90 = 7;
+ /**
+ * HiTec HSR-1425CR Continuous Rotation Servo. This is used with {@link #getServoType getServoType} and {@link #setServoType setServoType}
+ */
+ public static final int PHIDGET_SERVO_HITEC_HSR1425CR = 8;
+ /**
+ * HiTec HS-785HB Sail Winch Servo. This is used with {@link #getServoType getServoType} and {@link #setServoType setServoType}
+ */
+ public static final int PHIDGET_SERVO_HITEC_HS785HB = 9;
+ /**
+ * HiTec HS-485HB Deluxe Servo. This is used with {@link #getServoType getServoType} and {@link #setServoType setServoType}
+ */
+ public static final int PHIDGET_SERVO_HITEC_HS485HB = 10;
+ /**
+ * HiTec HS-645MG Ultra Torque Servo. This is used with {@link #getServoType getServoType} and {@link #setServoType setServoType}
+ */
+ public static final int PHIDGET_SERVO_HITEC_HS645MG = 11;
+ /**
+ * HiTec HS-815BB Mega Sail Servo. This is used with {@link #getServoType getServoType} and {@link #setServoType setServoType}
+ */
+ public static final int PHIDGET_SERVO_HITEC_815BB = 12;
+ /**
+ * Firgelli L12 Linear Actuator 30mm 50:1. This is used with {@link #getServoType getServoType} and {@link #setServoType setServoType}
+ */
+ public static final int PHIDGET_SERVO_FIRGELLI_L12_30_50_06_R = 13;
+ /**
+ * Firgelli L12 Linear Actuator 50mm 100:1. This is used with {@link #getServoType getServoType} and {@link #setServoType setServoType}
+ */
+ public static final int PHIDGET_SERVO_FIRGELLI_L12_50_100_06_R = 14;
+ /**
+ * Firgelli L12 Linear Actuator 50mm 210:1. This is used with {@link #getServoType getServoType} and {@link #setServoType setServoType}
+ */
+ public static final int PHIDGET_SERVO_FIRGELLI_L12_50_210_06_R = 15;
+ /**
+ * Firgelli L12 Linear Actuator 100mm 50:1. This is used with {@link #getServoType getServoType} and {@link #setServoType setServoType}
+ */
+ public static final int PHIDGET_SERVO_FIRGELLI_L12_100_50_06_R = 16;
+ /**
+ * Firgelli L12 Linear Actuator 100mm 100:1. This is used with {@link #getServoType getServoType} and {@link #setServoType setServoType}
+ */
+ public static final int PHIDGET_SERVO_FIRGELLI_L12_100_100_06_R = 17;
+ /**
+ * SpringRC SM-S2313M Micro Servo. This is used with {@link #getServoType getServoType} and {@link #setServoType setServoType}
+ */
+ public static final int PHIDGET_SERVO_SPRINGRC_SM_S2313M = 18;
+ /**
+ * SpringRC SM-S3317M Small Servo. This is used with {@link #getServoType getServoType} and {@link #setServoType setServoType}
+ */
+ public static final int PHIDGET_SERVO_SPRINGRC_SM_S3317M = 19;
+ /**
+ * SpringRC SM-S3317SR Small Continuous Rotation Servo. This is used with {@link #getServoType getServoType} and {@link #setServoType setServoType}
+ */
+ public static final int PHIDGET_SERVO_SPRINGRC_SM_S3317SR = 20;
+ /**
+ * SpringRC SM-S4303R Standard Continuous Rotation Servo. This is used with {@link #getServoType getServoType} and {@link #setServoType setServoType}
+ */
+ public static final int PHIDGET_SERVO_SPRINGRC_SM_S4303R = 21;
+ /**
+ * SpringRC SM-S4315M High Torque Servo. This is used with {@link #getServoType getServoType} and {@link #setServoType setServoType}
+ */
+ public static final int PHIDGET_SERVO_SPRINGRC_SM_S4315M = 22;
+ /**
+ * SpringRC SM-S4315R High Torque Continuous Rotation Servo. This is used with {@link #getServoType getServoType} and {@link #setServoType setServoType}
+ */
+ public static final int PHIDGET_SERVO_SPRINGRC_SM_S4315R = 23;
+ /**
+ * SpringRC SM-S4505B Standard Servo. This is used with {@link #getServoType getServoType} and {@link #setServoType setServoType}
+ */
+ public static final int PHIDGET_SERVO_SPRINGRC_SM_S4505B = 24;
+ /**
+ * User Defined servo parameters. This is used with {@link #getServoType getServoType}
+ */
+ public static final int PHIDGET_SERVO_USER_DEFINED = 25;
+
+ /**
+ * Returns the number of servo motors supported by this Phidget. This does not neccesarily correspond
+ * to the number of motors actually attached to the board.
+ * @return number of supported motors
+ * @throws PhidgetException If this Phidget is not opened and attached.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native int getMotorCount () throws PhidgetException;
+ /**
+ * Returns the maximum acceleration that a motor will accept, or return.
+ * <p>This value is in degrees per second squared.
+ * @param index Index of the motor
+ * @return Maximum acceleration
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is invalid.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native double getAccelerationMax (int index) throws PhidgetException;
+ /**
+ * Returns the minimum acceleration that a motor will accept, or return.
+ * <p>This value is in degrees per second squared.
+ * @param index Index of the motor
+ * @return Minimum acceleration
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is invalid.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native double getAccelerationMin (int index) throws PhidgetException;
+ /**
+ * Returns the maximum velocity that a servo motor will accept, or return.
+ * <p>This value is in degrees per second.
+ * @param index Index of the motor
+ * @return Maximum velocity
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is invalid.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native double getVelocityMax (int index) throws PhidgetException;
+ /**
+ * Returns the minimum velocity that a servo motor will accept, or return.
+ * <p>This value is in degrees per second.
+ * @param index Index of the motor
+ * @return Minimum velocity
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is invalid.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native double getVelocityMin (int index) throws PhidgetException;
+ /**
+ * Returns the maximum position that a servo motor will accept, or return.
+ * <p>This value is in degrees.
+ * @param index Index of the motor
+ * @return Maximum position
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is invalid.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native double getPositionMax (int index) throws PhidgetException;
+ /**
+ * Sets the maximum position that a servo motor will accept, or return. This is for limiting the range of motion of the servo
+ * controller. The Maximum cannot be extended beyond it's original value.
+ * <p>This value is in degrees.
+ * @param index Index of the motor
+ * @param position Maximum position
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is invalid.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native void setPositionMax (int index, double position) throws PhidgetException;
+ /**
+ * Returns the minimum position that a servo motor will accept, or return.
+ * <p>This value uses the same units as
+ * <p>This value is in degrees.
+ * @param index Index of the motor
+ * @return Minimum position
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is invalid.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native double getPositionMin (int index) throws PhidgetException;
+ /**
+ * Sets the minimum position that a servo motor will accept, or return. This is for limiting the range of motion of the servo
+ * controller. The Minimum cannot be extended beyond it's original value.
+ * <p>This value is in degrees.
+ * @param index Index of the motor
+ * @param position Minimum position
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is invalid.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native void setPositionMin (int index, double position) throws PhidgetException;
+ /**
+ * Returns a motor's acceleration. The valid range is between {@link #getAccelerationMin getAccelerationMin}
+ * and {@link #getAccelerationMax getAccelerationMax}, and refers to how fast the Servo Controller will change the speed of a motor.
+ * <p>This value is in degrees per second squared.
+ * @param index index of motor
+ * @return acceleration of motor
+ * @throws PhidgetException If this Phidget is not opened and attached, if the index is invalid, or if the acceleration is unknown.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native double getAcceleration (int index) throws PhidgetException;
+ /**
+ * Sets a motor's acceleration.
+ * The valid range is between {@link #getAccelerationMin getAccelerationMin} and {@link #getAccelerationMax getAccelerationMax}.
+ * This controls how fast the motor changes speed.
+ * <p>This value is in degrees per second squared.
+ * @param index index of the motor
+ * @param acceleration requested acceleration for that motor
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index or acceleration are invalid.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native void setAcceleration (int index, double acceleration) throws PhidgetException;
+ /**
+ * Returns a motor's velocity limit. This is the maximum velocity that the motor will turn at.
+ * The valid range is between {@link #getVelocityMin getVelocityMin} and {@link #getVelocityMax getVelocityMax},
+ * with 0 being stopped.
+ * <p>This value is in degrees per second.
+ * @param index index of the motor
+ * @return current speed of the motor
+ * @throws PhidgetException If this Phidget is not opened and attached, if the index is invalid, or if the velocity in unknown.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native double getVelocityLimit (int index) throws PhidgetException;
+ /**
+ * Sets a motor's velocity limit. This is the maximum velocity that the motor will turn at.
+ * The valid range is between {@link #getVelocityMin getVelocityMin} and {@link #getVelocityMax getVelocityMax},
+ * with 0 being stopped.
+ * <p>This value is in degrees per second.
+ * @param index index of the motor
+ * @param velocity requested velocity for the motor
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index or velocity are invalid.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native void setVelocityLimit (int index, double velocity) throws PhidgetException;
+ /**
+ * Returns a motor's current velocity. The valid range is between {@link #getVelocityMin getVelocityMin} and {@link #getVelocityMax getVelocityMax},
+ * with 0 being stopped.
+ * <p>This value is in degrees per second.
+ * @param index index of the motor
+ * @return current speed of the motor
+ * @throws PhidgetException If this Phidget is not opened and attached, if the index is invalid, or if the velocity in unknown.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native double getVelocity (int index) throws PhidgetException;
+ /**
+ * Returns a motor's current position. This is the actual position that the motor is at right now.
+ * The valid range is between {@link #getPositionMin getPositionMin} and {@link #getPositionMax getPositionMax}.
+ * <p>This value is in degrees.
+ * @param index index of the motor
+ * @return current position of the motor
+ * @throws PhidgetException If this Phidget is not opened and attached, if the index is invalid, or if the position in unknown.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native double getPosition (int index) throws PhidgetException;
+ /**
+ * Sets a motor's target position. Use this is set the target position for the servo.
+ * If the servo is {@link #setEngaged engaged} it will start moving towards this target position.
+ * The valid range is between {@link #getPositionMin getPositionMin} and {@link #getPositionMax getPositionMax}.
+ * <p>This value is in degrees.
+ * @param index index of the motor
+ * @param position target position of the motor
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index or position are invalid.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native void setPosition (int index, double position) throws PhidgetException;
+ /**
+ * Returns the engaged state of a motor.
+ *
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is out of range.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native boolean getEngaged (int index) throws PhidgetException;
+ /**
+ * Engage or disengage a motor.
+ * <p>
+ * This engages or disengages the servo motor. The motors are by default disengaged when the servo controller is plugged in.
+ * When the servo is disengaged, position, velocity, etc. can all be set, but the motor will not start moving until it is engaged.
+ * If position is read when a motor is disengaged, it will throw an exception.
+ * <p>
+ * This corresponds to a PCM of 0 being sent to the servo.
+ *
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is out of range.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native void setEngaged (int index, boolean state) throws PhidgetException;
+ /**
+ * Returns the speed ramping state of a motor.
+ *
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is out of range.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native boolean getSpeedRampingOn (int index) throws PhidgetException;
+ /**
+ * Sets the speed ramping state.
+ * <p>
+ * Disable speed ramping to disable velocity and acceleration control. With speed ramping disabled, the servo will be sent to
+ * the desired position immediately upon recieving the command. This is how the regular Phidget Servo Controller works.
+ * <p>
+ * This is turned on by default.
+ *
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is out of range.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native void setSpeedRampingOn (int index, boolean state) throws PhidgetException;
+ /**
+ * Returns a motor's current usage. The valid range depends on the servo controller.
+ * This value is in Amps.
+ * @param index index of the motor
+ * @return current usage of the motor
+ * @throws PhidgetException If this Phidget is not opened and attached, if the index is invalid, or if the value is unknown.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native double getCurrent (int index) throws PhidgetException;
+ /**
+ * Returns the stopped state of a motor. Use this to determine if the motor is moving and/or up to date with the latest commands you have sent.
+ * If this is true, the motor is guaranteed to be stopped and to have processed every command issued. Generally, this would
+ * be polled after a target position is set to wait until that position is reached.
+ *
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is out of range.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native boolean getStopped (int index) throws PhidgetException;
+ /**
+ * Returns the servo type for an index.
+ * The possible values for type are {@link #PHIDGET_SERVO_DEFAULT PHIDGET_SERVO_DEFAULT},
+ * {@link #PHIDGET_SERVO_RAW_us_MODE PHIDGET_SERVO_RAW_us_MODE}, {@link #PHIDGET_SERVO_HITEC_HS322HD PHIDGET_SERVO_HITEC_HS322HD},
+ * {@link #PHIDGET_SERVO_HITEC_HS5245MG PHIDGET_SERVO_HITEC_HS5245MG}, {@link #PHIDGET_SERVO_HITEC_805BB PHIDGET_SERVO_HITEC_805BB},
+ * {@link #PHIDGET_SERVO_HITEC_HS422 PHIDGET_SERVO_HITEC_HS422}, etc.
+ * @param index Input
+ * @return Servo Type
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is out of range.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native int getServoType (int index) throws PhidgetException;
+ /**
+ * Sets the servo type for an index.
+ * <p>
+ * This constrains the PCM to the valid range of the servo, and sets the degrees-to-PCM ratio to match the actual servo rotation.
+ * Velocity is also constrained to the maximum speed attainable by the servo.
+ * <p>
+ * The possible values for type are {@link #PHIDGET_SERVO_DEFAULT PHIDGET_SERVO_DEFAULT},
+ * {@link #PHIDGET_SERVO_RAW_us_MODE PHIDGET_SERVO_RAW_us_MODE}, {@link #PHIDGET_SERVO_HITEC_HS322HD PHIDGET_SERVO_HITEC_HS322HD},
+ * {@link #PHIDGET_SERVO_HITEC_HS5245MG PHIDGET_SERVO_HITEC_HS5245MG}, {@link #PHIDGET_SERVO_HITEC_805BB PHIDGET_SERVO_HITEC_805BB},
+ * {@link #PHIDGET_SERVO_HITEC_HS422 PHIDGET_SERVO_HITEC_HS422}, etc.
+ * <p>
+ * Support for other servo types can be achieved by using {@link #setServoParameters setServoParameters}.
+ * <p>
+ * The default setting is {@link #PHIDGET_SERVO_DEFAULT PHIDGET_SERVO_DEFAULT}, which is used for historical (backwards compatibility) reasons.
+ * @param index Input
+ * @param type Servo Type
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is out of range.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native void setServoType (int index, int type) throws PhidgetException;
+ /**
+ * Sets the servo parameters for a custom servo definition.
+ * <p>
+ * This constrains the PCM to the valid range of the servo, and sets the degrees-to-PCM ratio to match the actual servo rotation.
+ * Velocity is also constrained to the maximum speed attainable by the servo.
+ * <p>
+ * @param index Servo Index
+ * @param minUs Minimum PCM supported in microseconds
+ * @param maxUs Maximum PCM supported in microseconds
+ * @param degrees Degrees of rotation represented by the given PCM range
+ * @param velocityMax Maximum supported velocity of the servo in degrees/second
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is out of range.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native void setServoParameters (int index, double minUs, double maxUs, double degrees, double velocityMax) throws PhidgetException;
+
+ private final void enableDeviceSpecificEvents (boolean b)
+ {
+ enableServoPositionChangeEvents (b && servoPositionChangeListeners.size () > 0);
+ enableServoVelocityChangeEvents (b && servoVelocityChangeListeners.size () > 0);
+ enableCurrentChangeEvents (b && currentChangeListeners.size () > 0);
+ }
+ /**
+ * Adds a position change listener. The position change handler is a method that will be called when the servo
+ * position has changed.
+ * <p>
+ * There is no limit on the number of position change handlers that can be registered for a particular Phidget.
+ *
+ * @param l An implemetation of the {@link com.phidgets.event.ServoPositionChangeListener ServoPositionChangeListener} interface
+ */
+ public final void addServoPositionChangeListener (ServoPositionChangeListener l)
+ {
+ synchronized (servoPositionChangeListeners)
+ {
+ servoPositionChangeListeners.add (l);
+ enableServoPositionChangeEvents (true);
+ }} private LinkedList servoPositionChangeListeners = new LinkedList ();
+ private long nativeServoPositionChangeHandler = 0;
+ public final void removeServoPositionChangeListener (ServoPositionChangeListener l)
+ {
+ synchronized (servoPositionChangeListeners)
+ {
+ servoPositionChangeListeners.remove (l);
+ enableServoPositionChangeEvents (servoPositionChangeListeners.size () > 0);
+ }} private void fireServoPositionChange (ServoPositionChangeEvent e)
+ {
+ synchronized (servoPositionChangeListeners)
+ {
+ for (Iterator it = servoPositionChangeListeners.iterator (); it.hasNext ();)
+ ((ServoPositionChangeListener) it.next ()).servoPositionChanged (e);
+ }
+ }
+ private native void enableServoPositionChangeEvents (boolean b);
+ /**
+ * Adds a velocity change listener. The velocity change handler is a method that will be called when the servo
+ * velocity has changed.
+ * <p>
+ * There is no limit on the number of velocity change handlers that can be registered for a particular Phidget.
+ *
+ * @param l An implemetation of the {@link com.phidgets.event.ServoVelocityChangeListener ServoVelocityChangeListener} interface
+ */
+ public final void addServoVelocityChangeListener (ServoVelocityChangeListener l)
+ {
+ synchronized (servoVelocityChangeListeners)
+ {
+ servoVelocityChangeListeners.add (l);
+ enableServoVelocityChangeEvents (true);
+ }} private LinkedList servoVelocityChangeListeners = new LinkedList ();
+ private long nativeServoVelocityChangeHandler = 0;
+ public final void removeServoVelocityChangeListener (ServoVelocityChangeListener l)
+ {
+ synchronized (servoVelocityChangeListeners)
+ {
+ servoVelocityChangeListeners.remove (l);
+ enableServoVelocityChangeEvents (servoVelocityChangeListeners.size () > 0);
+ }} private void fireServoVelocityChange (ServoVelocityChangeEvent e)
+ {
+ synchronized (servoVelocityChangeListeners)
+ {
+ for (Iterator it = servoVelocityChangeListeners.iterator (); it.hasNext ();)
+ ((ServoVelocityChangeListener) it.next ()).servoVelocityChanged (e);
+ }
+ }
+ private native void enableServoVelocityChangeEvents (boolean b);
+ /**
+ * Adds a current change listener. The current change handler is a method that will be called when the servo
+ * current has changed.
+ * <p>
+ * There is no limit on the number of current change handlers that can be registered for a particular Phidget.
+ * <p>
+ * Note that not all stepper controllers support current sensing.
+ *
+ * @param l An implemetation of the {@link com.phidgets.event.CurrentChangeListener CurrentChangeListener} interface
+ */
+ public final void addCurrentChangeListener (CurrentChangeListener l)
+ {
+ synchronized (currentChangeListeners)
+ {
+ currentChangeListeners.add (l);
+ enableCurrentChangeEvents (true);
+ }} private LinkedList currentChangeListeners = new LinkedList ();
+ private long nativeCurrentChangeHandler = 0;
+ public final void removeCurrentChangeListener (CurrentChangeListener l)
+ {
+ synchronized (currentChangeListeners)
+ {
+ currentChangeListeners.remove (l);
+ enableCurrentChangeEvents (currentChangeListeners.size () > 0);
+ }} private void fireCurrentChange (CurrentChangeEvent e)
+ {
+ synchronized (currentChangeListeners)
+ {
+ for (Iterator it = currentChangeListeners.iterator (); it.hasNext ();)
+ ((CurrentChangeListener) it.next ()).currentChanged (e);
+ }
+ }
+ private native void enableCurrentChangeEvents (boolean b);
+}
diff --git a/Java/com/phidgets/AnalogPhidget.java b/Java/com/phidgets/AnalogPhidget.java
new file mode 100644
index 0000000..b8f4c0a
--- /dev/null
+++ b/Java/com/phidgets/AnalogPhidget.java
@@ -0,0 +1,78 @@
+
+/*
+ * Copyright 2011 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets;
+import java.util.Iterator;
+import java.util.LinkedList;
+import com.phidgets.event.*;
+/**
+ * This class represents a Phidget Analog. All methods
+ * to manipulate the Phidget Analog are implemented in this class.
+ *
+ * @author Phidgets Inc.
+ */
+public final class AnalogPhidget extends Phidget
+{
+ public AnalogPhidget () throws PhidgetException
+ {
+ super (create ());
+ }
+ private static native long create () throws PhidgetException;
+
+ /**
+ * Returns the number of analog outputs.
+ * @return Number of analog outputs
+ */
+ public native int getOutputCount () throws PhidgetException;
+ /**
+ * Returns the current voltage output setting for an analog output, in Volts. The range is between {@link #getVoltageMin(int) getVoltageMin} and {@link #getVoltageMax(int) getVoltageMax}.
+ * @param index index of the analog output
+ * @return current voltage for an analog output, in Volts
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is out of range.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native double getVoltage (int index) throws PhidgetException;
+ /**
+ * Sets the current voltage setting for an analog output, in Volts. The range is between {@link #getVoltageMin(int) getVoltageMin} and {@link #getVoltageMax(int) getVoltageMax}.
+ * @param index index of the analog output
+ * @param current new voltage for an analog output, in Volts
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is out of range.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native void setVoltage (int index, double current) throws PhidgetException;
+ /**
+ * Gets the minimum supported voltage for an output, in Volts.
+ * @param index index of the analog output
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is out of range.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native double getVoltageMin (int index) throws PhidgetException;
+ /**
+ * Gets the maximum supported voltage for an output, in Volts.
+ * @param index index of the analog output
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is out of range.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native double getVoltageMax (int index) throws PhidgetException;
+ /**
+ * Returns the enabled state for an analog output. When enabled, the output drives at the set Voltage, up to 20mA. When disabled, the output is tied to ground via a 4K pull-down.
+ * @param index index of the analog output
+ * @return enabled state for an output
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is invalid.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native boolean getEnabled (int index) throws PhidgetException;
+ /**
+ * Sets the enabled state for a an analog output. When enabled, the output drives at the set Voltage, up to 20mA. When disabled, the output is tied to ground via a 4K pull-down.
+ * @param index index of the analog output
+ * @param state new state of the analog output
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is invalid.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native void setEnabled (int index, boolean state) throws PhidgetException;
+ private final void enableDeviceSpecificEvents (boolean b)
+ {
+ }
+}
diff --git a/Java/com/phidgets/BridgePhidget.java b/Java/com/phidgets/BridgePhidget.java
new file mode 100644
index 0000000..55f0b65
--- /dev/null
+++ b/Java/com/phidgets/BridgePhidget.java
@@ -0,0 +1,202 @@
+
+/*
+ * Copyright 2011 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets;
+import java.util.Iterator;
+import java.util.LinkedList;
+import com.phidgets.event.*;
+/**
+ * This class represents a Phidget Bridge. All methods
+ * to manipulate the Phidget Bridge are implemented in this class.
+ * <p>
+ *
+ * @author Phidgets Inc.
+ */
+public final class BridgePhidget extends Phidget
+{
+ public BridgePhidget () throws PhidgetException
+ {
+ super (create ());
+ }
+ private static native long create () throws PhidgetException;
+ /**
+ * 1 Gain. This is used with {@link #getGain(int) getGain} and {@link #setGain(int, int) setGain}
+ */
+ public static final int PHIDGET_BRIDGE_GAIN_1 = 1;
+ /**
+ * 8 Gain. This is used with {@link #getGain(int) getGain} and {@link #setGain(int, int) setGain}
+ */
+ public static final int PHIDGET_BRIDGE_GAIN_8 = 2;
+ /**
+ * 16 Gain. This is used with {@link #getGain(int) getGain} and {@link #setGain(int, int) setGain}
+ */
+ public static final int PHIDGET_BRIDGE_GAIN_16 = 3;
+ /**
+ * 32 Gain. This is used with {@link #getGain(int) getGain} and {@link #setGain(int, int) setGain}
+ */
+ public static final int PHIDGET_BRIDGE_GAIN_32 = 4;
+ /**
+ * 64 Gain. This is used with {@link #getGain(int) getGain} and {@link #setGain(int, int) setGain}
+ */
+ public static final int PHIDGET_BRIDGE_GAIN_64 = 5;
+ /**
+ * 128 Gain. This is used with {@link #getGain(int) getGain} and {@link #setGain(int, int) setGain}
+ */
+ public static final int PHIDGET_BRIDGE_GAIN_128 = 6;
+ /**
+ * Unknown Gain. This is used with {@link #getGain(int) getGain} and {@link #setGain(int, int) setGain}
+ */
+ public static final int PHIDGET_BRIDGE_GAIN_UNKNOWN = 7;
+ /**
+ * Returns the number of bridges.
+ * @return Number of bridges
+ */
+ public native int getInputCount () throws PhidgetException;
+ /**
+ * Returns the value of the selected input, in mV/V. If the input is not enabled, an EPHIDGET_UNKNOWNVAL exception will be thrown. If the bridge is saturated
+ *, this will be equal to BridgeMax or BridgeMin and an error event will be fired - in this case, gain should be reduced if possible.
+ * @param index Index of the bridge
+ * @return bridge value
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is out of range.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native double getBridgeValue (int index) throws PhidgetException;
+ /**
+ * Returns the minimum value that the selected bridge can measure, in mV/V. This value will depend on the selected gain. At a gain of 1, BridgeMin == -1000 mV/V.
+ * @param index Index of the bridge
+ * @return minimum value
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is out of range.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native double getBridgeMin (int index) throws PhidgetException;
+ /**
+ * Returns the maximum value that the selected bridge can measure, in mV/V. This value will depend on the selected gain. At a gain of 1, BridgeMin == 1000 mV/V.
+ * @param index Index of the bridge
+ * @return maximum value
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is out of range.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native double getBridgeMax (int index) throws PhidgetException;
+ /**
+ * Returns the enabled state of the specified bridge. This applies power between +5v and Ground, and starts measuring the differential on the +/- pins. By default, all bridges are
+ * disabled, and need to be explicitly enabled on startup.
+ * @param index Index of the bridge
+ * @return state of the specified bridge
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is invalid.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native boolean getEnabled (int index) throws PhidgetException;
+ /**
+ * Sets the enabled state of the specified bridge. This applies power between +5v and Ground, and starts measuring the differential on the +/- pins. By default, all bridges are
+ * disabled, and need to be explicitly enabled on startup.
+ * @param index Index of the bridge
+ * @param state new state of the specified bridge
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is invalid.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native void setEnabled (int index, boolean state) throws PhidgetException;
+ /**
+ * Returns the gain for the selected bridge. Note that increasing the gains will reduce the measurable
+ * voltage difference by the gain factor, with +-1000 mV/V being the maximum, with no gain.
+ * The possible values for gain are {@link #PHIDGET_BRIDGE_GAIN_1 PHIDGET_BRIDGE_GAIN_1},
+ * {@link #PHIDGET_BRIDGE_GAIN_8 PHIDGET_BRIDGE_GAIN_8}, {@link #PHIDGET_BRIDGE_GAIN_16 PHIDGET_BRIDGE_GAIN_16},
+ * {@link #PHIDGET_BRIDGE_GAIN_32 PHIDGET_BRIDGE_GAIN_32}, {@link #PHIDGET_BRIDGE_GAIN_64 PHIDGET_BRIDGE_GAIN_64},
+ * {@link #PHIDGET_BRIDGE_GAIN_128 PHIDGET_BRIDGE_GAIN_128}, {@link #PHIDGET_BRIDGE_GAIN_UNKNOWN PHIDGET_BRIDGE_GAIN_UNKNOWN}
+ * <p>
+ * @param index Index of the bridge
+ * @return gain
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is invalid.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native int getGain (int index) throws PhidgetException;
+ /**
+ * Sets the gain for the selected bridge. Note that increasing the gains will reduce the measurable
+ * voltage difference by the gain factor, with +-1000 mV/V being the maximum, with no gain.
+ * <p>
+ * The possible values for gain are {@link #PHIDGET_BRIDGE_GAIN_1 PHIDGET_BRIDGE_GAIN_1},
+ * {@link #PHIDGET_BRIDGE_GAIN_8 PHIDGET_BRIDGE_GAIN_8}, {@link #PHIDGET_BRIDGE_GAIN_16 PHIDGET_BRIDGE_GAIN_16},
+ * {@link #PHIDGET_BRIDGE_GAIN_32 PHIDGET_BRIDGE_GAIN_32}, {@link #PHIDGET_BRIDGE_GAIN_64 PHIDGET_BRIDGE_GAIN_64},
+ * {@link #PHIDGET_BRIDGE_GAIN_128 PHIDGET_BRIDGE_GAIN_128}, {@link #PHIDGET_BRIDGE_GAIN_UNKNOWN PHIDGET_BRIDGE_GAIN_UNKNOWN}
+ * <p>
+ * @param index Index of the bridge
+ * @param gain new gain
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is invalid.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native void setGain (int index, int gain) throws PhidgetException;
+ /**
+ * Returns the data rate, in ms. Data rate applies to all 4 bridges simultaneously. Setting a slower data rate will reduce
+ * noise at the cost of sample time. Also note that each bridge is being sampled only 1/4 of the time - this is okay for very stable signals,
+ * but for changing signals, it is best to set a higher sampling rate and do averaging in the software.
+ * <p>
+ * Data rate must be a multiple of 8ms. Trying to set something between multiplies of 8 will cause an EPHIDGET_INVALIDARG exception.
+ * <p>
+ * @return Data Rate
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is invalid.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native int getDataRate () throws PhidgetException;
+ /**
+ * Sets the data rate, in ms. Data rate applies to all 4 bridges simultaneously. Setting a slower data rate will reduce
+ * noise at the cost of sample time. Also note that each bridge is being sampled only 1/4 of the time - this is okay for very stable signals,
+ * but for changing signals, it is best to set a higher sampling rate and do averaging in the software.
+ * <p>
+ * Data rate must be a multiple of 8ms. Trying to set something between multiplies of 8 will cause an EPHIDGET_INVALIDARG exception.
+ * <p>
+ * @param rate new data rate
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the data rate is out of range
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native void setDataRate (int rate) throws PhidgetException;
+ /**
+ * Gets the minimum supported data rate, in ms.
+ * @return minimum supported data rate
+ * @throws PhidgetException If this Phidget is not opened and attached.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native int getDataRateMin () throws PhidgetException;
+ /**
+ * Gets the maximum supported data rate, in ms.
+ * @return maximum supported data rate
+ * @throws PhidgetException If this Phidget is not opened and attached.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native int getDataRateMax () throws PhidgetException;
+
+ private final void enableDeviceSpecificEvents (boolean b)
+ {
+ enableBridgeDataEvents (b && bridgeDataListeners.size () > 0);
+ }
+ /**
+ * Adds a bridge data listener. The bridge data handler is a method that will be called at the specified data rate, for each enabled bridge. Value is the bridgeValue, in mV/V.
+ * <p>
+ * There is no limit on the number of bridge data handlers that can be registered for a particular Phidget.
+ *
+ * @param l An implemetation of the {@link com.phidgets.event.BridgeDataListener BridgeDataListener} interface
+ */
+ public final void addBridgeDataListener (BridgeDataListener l)
+ {
+ synchronized (bridgeDataListeners)
+ {
+ bridgeDataListeners.add (l);
+ enableBridgeDataEvents (true);
+ }} private LinkedList bridgeDataListeners = new LinkedList ();
+ private long nativeBridgeDataHandler = 0;
+ public final void removeBridgeDataListener (BridgeDataListener l)
+ {
+ synchronized (bridgeDataListeners)
+ {
+ bridgeDataListeners.remove (l);
+ enableBridgeDataEvents (bridgeDataListeners.size () > 0);
+ }} private void fireBridgeData (BridgeDataEvent e)
+ {
+ synchronized (bridgeDataListeners)
+ {
+ for (Iterator it = bridgeDataListeners.iterator (); it.hasNext ();)
+ ((BridgeDataListener) it.next ()).bridgeData (e);
+ }
+ }
+ private native void enableBridgeDataEvents (boolean b);
+}
diff --git a/Java/com/phidgets/Dictionary.java b/Java/com/phidgets/Dictionary.java
new file mode 100644
index 0000000..0afde5e
--- /dev/null
+++ b/Java/com/phidgets/Dictionary.java
@@ -0,0 +1,348 @@
+/*
+ * Copyright 2006 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets;
+
+import com.phidgets.event.*;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.Vector;
+
+/**
+ * This class represents the Phidget Dictionary.
+ * <p>
+ * The Phidget Dictionary is a service provided by the Phidget Webservice.
+ * The Webservice maintains a centralized dictionary of key-value pairs that can be accessed and changed from any number of clients.
+ * <p>
+ * Note that the Webservice uses this dictionary to control access to Phidgets through the openRemote and openRemoteIP interfaces,
+ * and as such, you should never add or modify a key that starts with /PSK/ or /PCK/, unless you want to explicitly modify Phidget
+ * specific data -- and this is highly discouraged, as it's very easy to break things. Listening to these keys is fine if so desired.
+ * <p>
+ * The intended use for the dictionary is as a central repository for communication and persistent storage of data between several
+ * client applications. As an example - a higher level interface exposed by one application -- which controls the Phidgets, for
+ * others to access -- rather then every client talking directly to the Phidgets themselves.
+ * <p>
+ * The dictionary makes use of extended regular expressions for key matching.
+ *
+ * @author Phidgets Inc.
+ */
+public class Dictionary
+{
+ static
+ {
+ try
+ {
+ System.loadLibrary("phidget21");
+ }
+ catch(UnsatisfiedLinkError ex)
+ {
+ String os = System.getProperty("os.name");
+ if(os.startsWith("Linux"))
+ {
+ throw new ExceptionInInitializerError(ex.getMessage()
+ +"\nCould not locate the Phidget C library (libphidget21.so)."
+ +"\nMake sure it is installed, and add it's path to LD_LIBRARY_PATH.");
+ }
+ else if(os.startsWith("Windows"))
+ {
+ throw new ExceptionInInitializerError(ex.getMessage()
+ +"\nCould not locate the Phidget C library."
+ +"\nThe Windows Phidget21 MSI must be installed.");
+ }
+ else if(os.startsWith("Mac"))
+ {
+ throw new ExceptionInInitializerError(ex.getMessage()
+ +"\nCould not locate the Phidget C library."
+ +"\nThe Mac Phidget21 DMG must be installed.");
+ }
+ else
+ {
+ throw new ExceptionInInitializerError(ex.getMessage()
+ +"\nCould not locate the Phidget C library.");
+ }
+ }
+ }
+
+ public long handle = 0;
+ /**
+ * The default constructor. Creating a Phidget Dictionary object will initialize the
+ * dictionary handle internally, but {@link #open(String, int) open} still needs to be called
+ * to actually work with it.
+ */
+ public Dictionary() throws PhidgetException
+ {
+ handle = create();
+ }
+ private final native long create() throws PhidgetException;
+
+ private final native void nativeClose() throws PhidgetException;
+ private final native void nativeDelete() throws PhidgetException;
+ private final native void nativeOpenRemote(String serverID, String pass) throws PhidgetException;
+ private final native void nativeOpenRemoteIP(String ipAddress, int port, String pass) throws PhidgetException;
+ private final native void nativeAddKey(String key, String val, int persistent) throws PhidgetException;
+ private final native void nativeRemoveKey(String keyPattern) throws PhidgetException;
+ private final native String nativeGetKey(String key) throws PhidgetException;
+
+
+ /**
+ * Returns the Address of a Phidget Webservice when this Dictionary was opened as remote. This may be an IP Address or a hostname.
+ *
+ * @return Server Address
+ * @throws PhidgetException if this Dictionary was not opened.
+ */
+ public final native String getServerAddress() throws PhidgetException;
+ /**
+ * Returns the Server ID of a Phidget Webservice when this Dictionary was opened as remote. This is an arbitrary server identifier,
+ * independant of IP address and Port.
+ *
+ * @return Server ID
+ * @throws PhidgetException if this Dictionary was not opened.
+ */
+ public final native String getServerID() throws PhidgetException;
+ /**
+ * Returns the Port of a Phidget Webservice when this Dictionary was opened as remote.
+ *
+ * @return Server Port
+ * @throws PhidgetException if this Dictionary was not opened.
+ */
+ public final native int getServerPort() throws PhidgetException;
+ /**
+ * Returns the attached status of this Dictionary.
+ *
+ * @return Status
+ * @throws PhidgetException If this Dictionary is not opened.
+ */
+ public final native boolean isAttached() throws PhidgetException;
+
+ /**
+ * Returns the network attached status for remotely opened Phidgets. This method returns True or False, depending on whether a connection to the
+ * Phidget WebService is open - or not. If this is false for a remote Phidget then the connection is not active - either because a connection
+ * has not yet been established, or because the connection was terminated.
+ *
+ * @return Status
+ * @throws PhidgetException If this Phidget is not opened.
+ */
+ public final native boolean isAttachedToServer() throws PhidgetException;
+
+ /**
+ * Adds a new key to the Dictionary, or modifies the value of an existing key.
+ * <p>
+ * The key can only contain numbers, letters, "/", ".", "-", "_", and must begin with a letter, "_" or "/".
+ * <p>
+ * The value can contain any value.
+ * <p>
+ * The key will stay in the dictionary until explicitly removed.
+ *
+ *
+ */
+ public final void add(String key, String val) throws PhidgetException
+ {
+ nativeAddKey(key, val, 1);
+ }
+
+ /**
+ * Adds a new key to the Dictionary, or modifies the value of an existing key.
+ * <p>
+ * The key can only contain numbers, letters, "/", ".", "-", "_", and must begin with a letter, "_" or "/".
+ * <p>
+ * The value can contain any value.
+ * <p>
+ * The persistent value controls whether a key will stay in the dictionary after the client that created it disconnects.
+ * If persistent == 0, the key is removed when the connection closes. Otherwise the key remains in the dictionary until
+ * it is explicitly removed.
+ *
+ */
+ public final void add(String key, String val, boolean persistent) throws PhidgetException
+ {
+ if (persistent) nativeAddKey(key, val, 1);
+ else nativeAddKey(key, val, 0);
+ }
+ /**
+ * Removes a key, or set of keys, from the Dictionary.
+ * <p>
+ * The key name is a regular expressions pattern, and so care must be taken to only have it match the specific keys you want to remove.
+ */
+ public final void remove(String pattern) throws PhidgetException
+ {
+ nativeRemoveKey(pattern);
+ }
+
+ /**
+ * Gets the value for a key.
+ */
+ public final String get(String key) throws PhidgetException
+ {
+ return nativeGetKey(key);
+ }
+
+ /**
+ * Open this Dictionary remotely and securely, using an IP Address.
+ * <p>
+ * This method is the same as {@link #open(String, int) open(String ipAddress, int port)}, except that it specifies a password.
+ * This password can be set as a parameter when starting the Phidget Webservice.
+ */
+ public final void open(String ipAddress, int port, String password) throws PhidgetException
+ {
+ enableEvents(true);
+ nativeOpenRemoteIP(ipAddress, port, password);
+ }
+ /**
+ * Open this Dictionary remotely using an IP Address.
+ * <p>
+ * This version of open is network based, and relies on the Phidget Webservice running at the specified Address and Port
+ * before open is called.
+ * <p>
+ * @param ipAddress IP Address or hostname of the Phidget Webservice
+ * @param port Port of the Phidget Webservice
+ * @throws PhidgetException if the Phidget Webservice cannot be contacted
+ */
+ public final void open(String ipAddress, int port) throws PhidgetException
+ {
+ enableEvents(true);
+ nativeOpenRemoteIP(ipAddress, port, "");
+ }
+ /**
+ * Open this Dictionary remotely and securely, using a Server ID.
+ * <p>
+ * This method is the same as {@link #open(String) open(String serverID)}, except that it specifies a password.
+ * This password can be set as a parameter when starting the Phidget Webservice.
+ */
+ public final void open(String serverID, String password) throws PhidgetException
+ {
+ enableEvents(true);
+ nativeOpenRemote(serverID, password);
+ }
+ /**
+ * Open this Dictionary remotely using a Server ID.
+ * <p>
+ * This version of open is network based.
+ *
+ * @param serverID ServerID of the Phidget Webservice
+ */
+ public final void open(String serverID) throws PhidgetException
+ {
+ enableEvents(true);
+ nativeOpenRemote(serverID, "");
+ }
+ /**
+ * Closes this Dictionary.
+ * This will shut down all threads dealing with this Dictionary and you won't recieve any more events.
+ *
+ * @throws PhidgetException If this Dictionary is not opened.
+ */
+ public final void close() throws PhidgetException
+ {
+ enableEvents(false);
+ nativeClose();
+ }
+
+ private void enableEvents(boolean b)
+ {
+ enableServerConnectEvents(b && serverConnectListeners.size() > 0);
+ enableServerDisconnectEvents(b && serverDisconnectListeners.size() > 0);
+ }
+
+ private LinkedList serverConnectListeners = new LinkedList();
+ private long nativeServerConnectHandler = 0;
+
+ /**
+ * Adds an serverConnect listener. The serverConnect handler is a method that will be called when a connection to a server is made
+ * <p>
+ * There is no limit on the number of serverConnect handlers that can be registered for a particular Manager.
+ *
+ * @param l An implemetation of the {@link com.phidgets.event.ServerConnectListener ServerConnectListener} interface
+ */
+ public final void addServerConnectListener(ServerConnectListener l)
+ {
+ synchronized (serverConnectListeners)
+ {
+ serverConnectListeners.add(l);
+ enableServerConnectEvents(true);
+ }
+ }
+
+ /**
+ * Removes an serverConnect listener. This will remove a previously added serverConnect listener.
+ */
+ public final void removeServerConnectListener(ServerConnectListener l)
+ {
+ synchronized (serverConnectListeners)
+ {
+ serverConnectListeners.remove(l);
+ enableServerConnectEvents(serverConnectListeners.size() > 0);
+ }
+ }
+ private void fireServerConnect(ServerConnectEvent e)
+ {
+ synchronized (serverConnectListeners)
+ {
+ for (Iterator it = serverConnectListeners.iterator();
+ it.hasNext(); )
+ ((ServerConnectListener)it.next()).serverConnected(e);
+ }
+ }
+ private native void enableServerConnectEvents(boolean b);
+
+
+ private LinkedList serverDisconnectListeners = new LinkedList();
+ private long nativeServerDisconnectHandler = 0;
+
+ /**
+ * Adds an serverDisconnect listener. The serverDisconnect handler is a method that will be called when a connection to a server is terminated.
+ * <p>
+ * There is no limit on the number of serverDisconnect handlers that can be registered for a particular Manager.
+ *
+ * @param l An implemetation of the {@link com.phidgets.event.ServerDisconnectListener ServerDisconnectListener} interface
+ */
+ public final void addServerDisconnectListener(ServerDisconnectListener l)
+ {
+ synchronized (serverDisconnectListeners)
+ {
+ serverDisconnectListeners.add(l);
+ enableServerDisconnectEvents(true);
+ }
+ }
+
+ /**
+ * Removes an serverDisconnect listener. This will remove a previously added serverDisconnect listener.
+ */
+ public final void removeServerDisconnectListener(ServerDisconnectListener l)
+ {
+ synchronized (serverDisconnectListeners)
+ {
+ serverDisconnectListeners.remove(l);
+ enableServerDisconnectEvents(serverDisconnectListeners.size() > 0);
+ }
+ }
+ private void fireServerDisconnect(ServerDisconnectEvent e)
+ {
+ synchronized (serverDisconnectListeners)
+ {
+ for (Iterator it = serverDisconnectListeners.iterator();
+ it.hasNext(); )
+ ((ServerDisconnectListener)it.next()).serverDisconnected(e);
+ }
+ }
+ private native void enableServerDisconnectEvents(boolean b);
+
+ /**
+ * Return a Sring describing this dictionary.
+ */
+ public String toString()
+ {
+ return "PhidgetDictionary: ";
+ }
+
+ protected void finalize() {
+ try
+ {
+ close();
+ nativeDelete();
+ handle = 0;
+ } catch (Exception e) {
+ ;
+ }
+ }
+}
diff --git a/Java/com/phidgets/DictionaryKeyListener.java b/Java/com/phidgets/DictionaryKeyListener.java
new file mode 100644
index 0000000..db09a90
--- /dev/null
+++ b/Java/com/phidgets/DictionaryKeyListener.java
@@ -0,0 +1,184 @@
+/*
+ * Copyright 2006 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets;
+
+import com.phidgets.event.*;
+
+import com.phidgets.Dictionary;
+import java.util.Iterator;
+import java.util.LinkedList;
+
+/**
+ * This class represents a key listener.
+ * <p>
+ * This key listener is used, along with the Dictionary object, to set up listener for specific keys, or groups of keys.
+ * Events are available for key add or change, and for key removal.
+ */
+public class DictionaryKeyListener
+{
+ private String pattern;
+ Dictionary dict;
+
+ static
+ {
+ try
+ {
+ System.loadLibrary("phidget21");
+ }
+ catch(UnsatisfiedLinkError ex)
+ {
+ String os = System.getProperty("os.name");
+ if(os.startsWith("Linux"))
+ {
+ throw new ExceptionInInitializerError(ex.getMessage()
+ +"\nCould not locate the Phidget C library."
+ +"\nMake sure to compile with 'make jni' and install with 'make install'.");
+ }
+ else if(os.startsWith("Windows"))
+ {
+ throw new ExceptionInInitializerError(ex.getMessage()
+ +"\nCould not locate the Phidget C library."
+ +"\nThe Windows Phidget21 MSI must be installed.");
+ }
+ else if(os.startsWith("Mac"))
+ {
+ throw new ExceptionInInitializerError(ex.getMessage()
+ +"\nCould not locate the Phidget C library."
+ +"\nThe Mac Phidget21 DMG must be installed.");
+ }
+ else
+ {
+ throw new ExceptionInInitializerError(ex.getMessage()
+ +"\nCould not locate the Phidget C library.");
+ }
+ }
+ }
+
+ private long handle = 0;
+ private long nativeHandler = 0;
+ public long listenerhandle = 0;
+
+ /**
+ * Start this key listener. This method should not be called until the coresponding dictionary is connected.
+ */
+ public void start() throws PhidgetException
+ {
+ this.handle = dict.handle;
+ if (handle == 0)
+ throw (new PhidgetException(5, "Dictionary is not attached - call open first"));
+ listenerhandle = enableDictionaryKeyEvents((keyChangeListeners.size() > 0) || (keyRemovalListeners.size() > 0), pattern);
+ }
+
+ /**
+ * Stop this key listener.
+ */
+ public void stop()
+ {
+ listenerhandle = enableDictionaryKeyEvents(false, pattern);
+ }
+
+ /**
+ * Returns the Dictionary object that this listener is listening on.
+ */
+ public Dictionary getDictionary()
+ {
+ return dict;
+ }
+
+ /**
+ * Creates a new key listener, for a specific pattern, on a specific dictionary object.
+ * The pattern is a regular expression.
+ */
+ public DictionaryKeyListener(Dictionary dict, String pattern)
+ {
+ this.pattern = pattern;
+ this.dict = dict;
+ this.handle = dict.handle;
+ }
+
+ private LinkedList keyChangeListeners = new LinkedList();
+ private long nativeKeyChangeHandler = 0;
+
+ /**
+ * Add a new listener for key change events. This also applies for key add events..
+ */
+ public final void addKeyChangeListener(KeyChangeListener l)
+ {
+ synchronized (keyChangeListeners)
+ {
+ keyChangeListeners.add(l);
+ //enableDictionaryKeyEvents(true, pattern);
+ }
+ }
+ /**
+ * Removes a key change listener.
+ */
+ public final void removeKeyChangeListener(KeyChangeListener l)
+ {
+ synchronized (keyChangeListeners)
+ {
+ keyChangeListeners.remove(l);
+ //enableDictionaryKeyEvents(keyChangeListeners.size() > 0, pattern);
+ }
+ }
+ private void fireKeyChange(KeyChangeEvent e)
+ {
+ synchronized (keyChangeListeners)
+ {
+ for (Iterator it = keyChangeListeners.iterator();
+ it.hasNext(); )
+ ((KeyChangeListener)it.next()).keyChanged(e);
+ }
+ }
+ private native long enableDictionaryKeyEvents(boolean b, String pattern);
+
+ private LinkedList keyRemovalListeners = new LinkedList();
+ private long nativeKeyRemovalHandler = 0;
+
+ /**
+ * Add a new listener for key removal events.
+ */
+ public final void addKeyRemovalListener(KeyRemovalListener l)
+ {
+ synchronized (keyRemovalListeners)
+ {
+ keyRemovalListeners.add(l);
+ //enableDictionaryKeyEvents(true, pattern);
+ }
+ }
+ /**
+ * removes a key removal listener.
+ */
+ public final void removeKeyRemovalListener(KeyRemovalListener l)
+ {
+ synchronized (keyRemovalListeners)
+ {
+ keyRemovalListeners.remove(l);
+ //enableDictionaryKeyEvents(keyRemovalListeners.size() > 0, pattern);
+ }
+ }
+ private void fireKeyRemoval(KeyRemovalEvent e)
+ {
+ synchronized (keyRemovalListeners)
+ {
+ for (Iterator it = keyRemovalListeners.iterator();
+ it.hasNext(); )
+ ((KeyRemovalListener)it.next()).keyRemoved(e);
+ }
+ }
+
+ /**
+ * Return a Sring describing this dictionary key listener.
+ */
+ public String toString()
+ {
+ return dict.toString() + "Dictionary Key Listener ("+pattern+"): ";
+ }
+
+ protected void finalize()
+ {
+ listenerhandle = enableDictionaryKeyEvents(false, pattern);
+ }
+}
diff --git a/Java/com/phidgets/EncoderPhidget.java b/Java/com/phidgets/EncoderPhidget.java
new file mode 100644
index 0000000..1543bd3
--- /dev/null
+++ b/Java/com/phidgets/EncoderPhidget.java
@@ -0,0 +1,173 @@
+
+/*
+ * Copyright 2006 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets;
+import java.util.Iterator;
+import java.util.LinkedList;
+import com.phidgets.event.*;
+/**
+ * This class represents a Phidget Encoder. All methods
+ * to read encoder data from an encoder are implemented in this class.
+ <p>
+ Phidget Encoder boards generally support 1 or more encoders with 0 or more digital inputs.
+ Both high speed optical and low speed mechanical encoders are supported with this API.
+ *
+ * @author Phidgets Inc.
+ */
+public final class EncoderPhidget extends Phidget
+{
+ public EncoderPhidget () throws PhidgetException
+ {
+ super (create ());
+ }
+ private static native long create () throws PhidgetException;
+ /**
+ * Returns number of encoders. All current encoder boards support one encoder.
+ * @return number of encoders
+ * @throws PhidgetException If this Phidget is not opened and attached.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native int getEncoderCount () throws PhidgetException;
+ /**
+ * Returns number of digital inputs. On the mechanical encoder this refers to the pushbutton. The
+ high speed encoder does not have any digital inputs.
+ * @return number of inputs
+ * @throws PhidgetException If this Phidget is not opened and attached.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native int getInputCount () throws PhidgetException;
+ /**
+ * Returns the position of an encoder. This is an absolute position as calcutated since the encoder was plugged in.
+ This value can be reset to anything using {@link #setEncoderPosition(int, int) setEncoderPosition}.
+ * @param index index of the encoder
+ * @return position of the encoder
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is out of range.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native int getPosition (int index) throws PhidgetException;
+ /**
+ * Returns the last index position of an encoder. This is the position of the last index pulse. Not all encoders support index.
+ * @param index index of the encoder
+ * @return last index position of the encoder
+ * @throws PhidgetException If this Phidget is not opened and attached, if the index is out of range, of if index is not supported.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native int getIndexPosition (int index) throws PhidgetException;
+ /**
+ * @deprecated Replaced by
+ * {@link #getPosition}
+ */
+ public native int getEncoderPosition (int index) throws PhidgetException;
+ /**
+ * Sets the position of a specific encoder. This resets the internal position count for an encoder. This call in no way actually
+ sends information to the device, as an absolute position is maintained only in the library. After this call, position changes
+ from the encoder will use the new value to calculate absolute position as reported by {@link #getEncoderPosition}.
+ * @param index index of the encoder
+ * @param position new position for this encoder.
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is out of range.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native void setPosition (int index, int position) throws PhidgetException;
+ /**
+ * @deprecated Replaced by
+ * {@link #setPosition}
+ */
+ public native void setEncoderPosition (int index, int position) throws PhidgetException;
+ /**
+ * Returns the state of a digital input. On the mechanical encoder this refers to the pushbutton. The
+ high speed encoder does not have any digital inputs. A value of true means that the input is active(the button is pushed).
+ * @param index index of the input
+ * @return state of the input
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is out of range.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native boolean getInputState (int index) throws PhidgetException;
+ /**
+ * Returns the enabled state of an encoder. True indicated activated, False deactivated, which is the default.
+ * @param index index of the encoder
+ * @return state of the encoder
+ * @throws PhidgetException If this Phidget is not opened and attached, the index is out of range, or enable is not supported.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native boolean getEnabled (int index) throws PhidgetException;
+ /**
+ * Sets the enabled state of an encoder. True indicated activated, False deactivated, which is the default.
+ * @param index index of the encoder
+ * @param state desired state
+ * @throws PhidgetException If this Phidget is not opened and attached, the index is out of range, or enable is not supported.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native void setEnabled (int index, boolean state) throws PhidgetException;
+
+ private final void enableDeviceSpecificEvents (boolean b)
+ {
+ enableEncoderPositionChangeEvents (b && encoderPositionChangeListeners.size () > 0);
+ enableInputChangeEvents (b && inputChangeListeners.size () > 0);
+ }
+ /**
+ * Adds a position change listener. The position change handler is a method that will be called when the position of an
+ encoder changes. The position change event provides data about how many ticks have occured, and how much time has
+ passed since the last position change event, but does not contain an absolute position. This can be obtained from
+ {@link #getEncoderPosition}.
+ * <p>
+ * There is no limit on the number of position change handlers that can be registered for a particular Phidget.
+ *
+ * @param l An implemetation of the {@link com.phidgets.event.EncoderPositionChangeListener EncoderPositionChangeListener} interface
+ */
+ public final void addEncoderPositionChangeListener (EncoderPositionChangeListener l)
+ {
+ synchronized (encoderPositionChangeListeners)
+ {
+ encoderPositionChangeListeners.add (l);
+ enableEncoderPositionChangeEvents (true);
+ }} private LinkedList encoderPositionChangeListeners = new LinkedList ();
+ private long nativeEncoderPositionChangeHandler = 0;
+ public final void removeEncoderPositionChangeListener (EncoderPositionChangeListener l)
+ {
+ synchronized (encoderPositionChangeListeners)
+ {
+ encoderPositionChangeListeners.remove (l);
+ enableEncoderPositionChangeEvents (encoderPositionChangeListeners.size () > 0);
+ }} private void fireEncoderPositionChange (EncoderPositionChangeEvent e)
+ {
+ synchronized (encoderPositionChangeListeners)
+ {
+ for (Iterator it = encoderPositionChangeListeners.iterator (); it.hasNext ();)
+ ((EncoderPositionChangeListener) it.next ()).encoderPositionChanged (e);
+ }
+ }
+ private native void enableEncoderPositionChangeEvents (boolean b);
+ /**
+ * Adds an input change listener. The input change handler is a method that will be called when an input on this
+ * Encoder board has changed.
+ * <p>
+ * There is no limit on the number of input change handlers that can be registered for a particular Phidget.
+ *
+ * @param l An implemetation of the {@link com.phidgets.event.InputChangeListener InputChangeListener} interface
+ */
+ public final void addInputChangeListener (InputChangeListener l)
+ {
+ synchronized (inputChangeListeners)
+ {
+ inputChangeListeners.add (l);
+ enableInputChangeEvents (true);
+ }} private LinkedList inputChangeListeners = new LinkedList ();
+ private long nativeInputChangeHandler = 0;
+ public final void removeInputChangeListener (InputChangeListener l)
+ {
+ synchronized (inputChangeListeners)
+ {
+ inputChangeListeners.remove (l);
+ enableInputChangeEvents (inputChangeListeners.size () > 0);
+ }} private void fireInputChange (InputChangeEvent e)
+ {
+ synchronized (inputChangeListeners)
+ {
+ for (Iterator it = inputChangeListeners.iterator (); it.hasNext ();)
+ ((InputChangeListener) it.next ()).inputChanged (e);
+ }
+ }
+ private native void enableInputChangeEvents (boolean b);
+}
diff --git a/Java/com/phidgets/FrequencyCounterPhidget.java b/Java/com/phidgets/FrequencyCounterPhidget.java
new file mode 100644
index 0000000..b6b138e
--- /dev/null
+++ b/Java/com/phidgets/FrequencyCounterPhidget.java
@@ -0,0 +1,171 @@
+
+/*
+ * Copyright 2011 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets;
+import java.util.Iterator;
+import java.util.LinkedList;
+import com.phidgets.event.*;
+/**
+ * This class represents a Phidget Frequency Counter. All methods
+ * to read manipulate the Phidget Frequency Counter are implemented in this class.
+ * <p>
+ *
+ * @author Phidgets Inc.
+ */
+public final class FrequencyCounterPhidget extends Phidget
+{
+ public FrequencyCounterPhidget () throws PhidgetException
+ {
+ super (create ());
+ }
+ private static native long create () throws PhidgetException;
+ /**
+ * Zero-Crossing Filter Type. This is used with {@link #getFilter(int) getFilter} and {@link #setFilter(int, int) setFilter}
+ */
+ public static final int PHIDGET_FREQUENCYCOUNTER_FILTERTYPE_ZERO_CROSSING = 1;
+ /**
+ * Logic-Level Filter Type. This is used with {@link #getFilter(int) getFilter} and {@link #setFilter(int, int) setFilter}
+ */
+ public static final int PHIDGET_FREQUENCYCOUNTER_FILTERTYPE_LOGIC_LEVEL = 2;
+ /**
+ * Unknown Filter Type. This is used with {@link #getFilter(int) getFilter} and {@link #setFilter(int, int) setFilter}
+ */
+ public static final int PHIDGET_FREQUENCYCOUNTER_FILTERTYPE_UNKNOWN = 3;
+ /**
+ * Returns the number of channels.
+ * @return Number of inputs
+ */
+ public native int getFrequencyInputCount () throws PhidgetException;
+ /**
+ * Returns the last calcualted frequency on the specified channel, in Hz. This function will return 0 if the {@link #getTimeout(int) getTimeout} value elapses without detecting a signal.
+ * Frequency is recalculated up to 31.25 times a second, depending on the pulse rate.
+ * @param index Index of the channel
+ * @return frequency of the channel
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is out of range.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native double getFrequency (int index) throws PhidgetException;
+ /**
+ * Returns the total number of pulses detected on the specified channel since the Phidget was opened, or since the last reset.
+ * @param index Index of the channel
+ * @return total number of pulses
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is out of range.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native long getTotalCount (int index) throws PhidgetException;
+ /**
+ * Returns the total elapsed tiem since Phidget was opened, or since the last reset, in microseconds. This time corresponds to the {@link #getTotalCount(int) getTotalCount} property.
+ * @param index Index of the channel
+ * @return total time, in microseconds
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is out of range.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native long getTotalTime (int index) throws PhidgetException;
+ /**
+ * Returns the timeout value, in microseconds. This value is used to set the time to wait without detecting a signal before reporting 0 Hz. The valid range is 0.1 - 100 seconds(100,000 - 100,000,000 microseconds).
+ * 0.1 timeout represents the lowest frequency that will be measurable.
+ * @param index Index of the channel
+ * @return timeout value
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is out of range.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native int getTimeout (int index) throws PhidgetException;
+ /**
+ * Sets the timeout value, in microseconds. This value is used to set the time to wait without detecting a signal before reporting 0 Hz. The valid range is 0.1 - 100 seconds(100,000 - 100,000,000 microseconds).
+ * 0.1 timeout represents the lowest frequency that will be measurable.
+ * @param index Index of the channel
+ * @param timeout new timeout value
+ * @throws PhidgetException If this Phidget is not opened and attached, the index is out of range or the the timeout value is out of range.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native void setTimeout (int index, int timeout) throws PhidgetException;
+ /**
+ * Returns the enabled state on the specified channel. When the channel is disabled, it will no longer register counts. TotalTime and TotalCount properties will not be incremented until
+ * the channel is re-enabled.
+ * @param index Index of the channel
+ * @return state
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is invalid.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native boolean getEnabled (int index) throws PhidgetException;
+ /**
+ * Gets the enabled state on the specified channel. When the channel is disabled, it will no longer register counts. TotalTime and TotalCount properties will not be incremented until
+ * the channel is re-enabled.
+ * @param index Index of the channel
+ * @param state new enabled state
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is invalid.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native void setEnabled (int index, boolean state) throws PhidgetException;
+ /**
+ * Gets the channel filter mode. This controls the type of signal that the Frequency Counter will respond to - either a zero-centered or a logic-level signal.
+ * <p>
+ * The possible values for type are {@link #PHIDGET_FREQUENCYCOUNTER_FILTERTYPE_ZERO_CROSSING PHIDGET_FREQUENCYCOUNTER_FILTERTYPE_ZERO_CROSSING},
+ * {@link #PHIDGET_FREQUENCYCOUNTER_FILTERTYPE_LOGIC_LEVEL PHIDGET_FREQUENCYCOUNTER_FILTERTYPE_LOGIC_LEVEL}, {@link #PHIDGET_FREQUENCYCOUNTER_FILTERTYPE_UNKNOWN PHIDGET_FREQUENCYCOUNTER_FILTERTYPE_UNKNOWN}
+ * <p>
+ * @param index Index of the channel
+ * @return filter type
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is invalid.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native int getFilter (int index) throws PhidgetException;
+ /**
+ * Sets the channel filter mode. This controls the type of signal that the Frequency Counter will respond to - either a zero-centered or a logic-level signal.
+ * <p>
+ * The possible values for type are {@link #PHIDGET_FREQUENCYCOUNTER_FILTERTYPE_ZERO_CROSSING PHIDGET_FREQUENCYCOUNTER_FILTERTYPE_ZERO_CROSSING},
+ * {@link #PHIDGET_FREQUENCYCOUNTER_FILTERTYPE_LOGIC_LEVEL PHIDGET_FREQUENCYCOUNTER_FILTERTYPE_LOGIC_LEVEL}, {@link #PHIDGET_FREQUENCYCOUNTER_FILTERTYPE_UNKNOWN PHIDGET_FREQUENCYCOUNTER_FILTERTYPE_UNKNOWN}
+ * <p>
+ * @param index Index of the channel
+ * @param type new filter type
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is invalid.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native void setFilter (int index, int type) throws PhidgetException;
+ /**
+ * Resets the {@link #getTotalCount(int) getTotalCount} and {@link #getTotalTime(int) getTotalTime} counters to 0 for the specified channel. For best performance, this should be called when the channel is disabled.
+ * @param index Index of the channel
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is invalid.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native void reset (int index) throws PhidgetException;
+
+ private final void enableDeviceSpecificEvents (boolean b)
+ {
+ enableFrequencyCounterCountEvents (b && frequencyCounterCountListeners.size () > 0);
+ }
+ /**
+ * Adds a count listener. The count handler is a method that will be called whenever some counts have been detected.
+ * This event will fire up to 31.25 times a second, depending on the pulse rate. The time is in microseconds and represents the amount
+ * of time in which the number of counts occured. This event can be used to calculate frequency independently of the phidget21 library frequency implementation.
+ * This event will fire with a count of 0 once, after the Timeout time has elapsed with no counts for a channel, to indicate 0 Hz.
+ * <p>
+ * There is no limit on the number of count handlers that can be registered for a particular Phidget.
+ *
+ * @param l An implemetation of the {@link com.phidgets.event.FrequencyCounterCountListener FrequencyCounterCountListener} interface
+ */
+ public final void addFrequencyCounterCountListener (FrequencyCounterCountListener l)
+ {
+ synchronized (frequencyCounterCountListeners)
+ {
+ frequencyCounterCountListeners.add (l);
+ enableFrequencyCounterCountEvents (true);
+ }} private LinkedList frequencyCounterCountListeners = new LinkedList ();
+ private long nativeFrequencyCounterCountHandler = 0;
+ public final void removeFrequencyCounterCountListener (FrequencyCounterCountListener l)
+ {
+ synchronized (frequencyCounterCountListeners)
+ {
+ frequencyCounterCountListeners.remove (l);
+ enableFrequencyCounterCountEvents (frequencyCounterCountListeners.size () > 0);
+ }} private void fireFrequencyCounterCount (FrequencyCounterCountEvent e)
+ {
+ synchronized (frequencyCounterCountListeners)
+ {
+ for (Iterator it = frequencyCounterCountListeners.iterator (); it.hasNext ();)
+ ((FrequencyCounterCountListener) it.next ()).frequencyCounterCounted (e);
+ }
+ }
+ private native void enableFrequencyCounterCountEvents (boolean b);
+}
diff --git a/Java/com/phidgets/GPSPhidget.java b/Java/com/phidgets/GPSPhidget.java
new file mode 100644
index 0000000..dde1400
--- /dev/null
+++ b/Java/com/phidgets/GPSPhidget.java
@@ -0,0 +1,151 @@
+
+/*
+ * Copyright 2011 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets;
+import java.util.Iterator;
+import java.util.LinkedList;
+import com.phidgets.event.*;
+import java.util.Calendar;
+ /**
+ * This class represents a Phidget GPS. All methods
+ * to manipulate the Phidget GPS are implemented in this class.
+ * <p>
+ *
+ * @author Phidgets Inc.
+ */
+public final class GPSPhidget extends Phidget
+{
+ public GPSPhidget () throws PhidgetException
+ {
+ super (create ());
+ }
+ private static native long create () throws PhidgetException;
+
+ /**
+ * Returns the current latitude, in signed degrees format.
+ * @return Current latitude, in signed degrees format.
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the GPS is not plugged into the board.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ * If the latitude is not available, an EPHIDGET_UNKNOWNVAL exception is thrown.
+ */
+ public native double getLatitude () throws PhidgetException;
+ /**
+ * Returns the current longitude, in signed degrees format.
+ * @return Current longitude, in signed degrees format.
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the GPS is not plugged into the board.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ * If the longitude is not available, an EPHIDGET_UNKNOWNVAL exception is thrown.
+ */
+ public native double getLongitude () throws PhidgetException;
+ /**
+ * Returns the current altitude, in meters.
+ * @return Current altitude, in meters.
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the GPS is not plugged into the board.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ * If the altitude is not available, an EPHIDGET_UNKNOWNVAL exception is thrown.
+ */
+ public native double getAltitude () throws PhidgetException;
+ /**
+ * Returns the current heading, in degrees - compass bearing format. Heading is only accurate if the GPS is moving, and it represents
+ * a heading over time, and not the actual direction the PhidgetGPS is pointing.
+ * exception is thrown.
+ * @return Heading in degrees(compass bearing format).
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the GPS is not plugged into the board.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ * If the heading is not available, an EPHIDGET_UNKNOWNVAL.
+ */
+ public native double getHeading () throws PhidgetException;
+ /**
+ * Returns the current velocity, in km/h. Velocity is only accurate if the PhidgetGPS is moving.
+ * @return Velocity in km/h.
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the GPS is not plugged into the board.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ * If the velocity is not available, an EPHIDGET_UNKNOWNVAL exception is thrown.
+ */
+ public native double getVelocity () throws PhidgetException;
+ /**
+ * Returns the current GPS date and time, in UTC. The time is updated 10 times a second and is accurate to within at least 500ms when {@link #getPositionFixStatus getPositionFixStatus} is true.
+ * @return Current GPS date and time.
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the GPS is not plugged into the board.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ * If the date or time are not available, an EPHIDGET_UNKNOWNVAL exception is thrown.
+ */
+ public native Calendar getDateAndTime () throws PhidgetException;
+ /**
+ * Returns the current position fix status. If true, all of the above properties will be available. Time and date may or may not be available, but they can only be trusted
+ * as accurate when the PositionFixStatus is true.
+ * @return Current position fix status.
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the GPS is not plugged into the board.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ * If false, the {@link #getHeading getHeading} / {@link #getVelocity getVelocity} will throw an EPHIDGET_UNKNOWN exception.
+ */
+ public native boolean getPositionFixStatus () throws PhidgetException;
+
+ private final void enableDeviceSpecificEvents (boolean b)
+ {
+ enableGPSPositionFixStatusChangeEvents (b && gpsPositionFixStatusChangeListeners.size () > 0);
+ enableGPSPositionChangeEvents (b && gpsPositionChangeListeners.size () > 0);
+ }
+ /**
+ * Adds a position fix status change listener. The position fix status change handler is a method that will be called when the position fix status changes.
+ * <p>
+ * There is no limit on the number of position fix status change handlers that can be registered for a particular Phidget.
+ *
+ * @param l An implemetation of the {@link com.phidgets.event.GPSPositionFixStatusChangeListener GPSPositionFixStatusChangeListener} interface
+ */
+ public final void addGPSPositionFixStatusChangeListener (GPSPositionFixStatusChangeListener l)
+ {
+ synchronized (gpsPositionFixStatusChangeListeners)
+ {
+ gpsPositionFixStatusChangeListeners.add (l);
+ enableGPSPositionFixStatusChangeEvents (true);
+ }} private LinkedList gpsPositionFixStatusChangeListeners = new LinkedList ();
+ private long nativeGPSPositionFixStatusChangeHandler = 0;
+ public final void removeGPSPositionFixStatusChangeListener (GPSPositionFixStatusChangeListener l)
+ {
+ synchronized (gpsPositionFixStatusChangeListeners)
+ {
+ gpsPositionFixStatusChangeListeners.remove (l);
+ enableGPSPositionFixStatusChangeEvents (gpsPositionFixStatusChangeListeners.size () > 0);
+ }} private void fireGPSPositionFixStatusChange (GPSPositionFixStatusChangeEvent e)
+ {
+ synchronized (gpsPositionFixStatusChangeListeners)
+ {
+ for (Iterator it = gpsPositionFixStatusChangeListeners.iterator (); it.hasNext ();)
+ ((GPSPositionFixStatusChangeListener) it.next ()).gpsPositionFixStatusChanged (e);
+ }
+ }
+ private native void enableGPSPositionFixStatusChangeEvents (boolean b);
+ /**
+ * Adds a position change listener. The position change handler is a method that will be called when the position changes.
+ * <p>
+ * There is no limit on the number of position change handlers that can be registered for a particular Phidget.
+ *
+ * @param l An implemetation of the {@link com.phidgets.event.GPSPositionChangeListener GPSPositionChangeListener} interface
+ */
+ public final void addGPSPositionChangeListener (GPSPositionChangeListener l)
+ {
+ synchronized (gpsPositionChangeListeners)
+ {
+ gpsPositionChangeListeners.add (l);
+ enableGPSPositionChangeEvents (true);
+ }} private LinkedList gpsPositionChangeListeners = new LinkedList ();
+ private long nativeGPSPositionChangeHandler = 0;
+ public final void removeGPSPositionChangeListener (GPSPositionChangeListener l)
+ {
+ synchronized (gpsPositionChangeListeners)
+ {
+ gpsPositionChangeListeners.remove (l);
+ enableGPSPositionChangeEvents (gpsPositionChangeListeners.size () > 0);
+ }} private void fireGPSPositionChange (GPSPositionChangeEvent e)
+ {
+ synchronized (gpsPositionChangeListeners)
+ {
+ for (Iterator it = gpsPositionChangeListeners.iterator (); it.hasNext ();)
+ ((GPSPositionChangeListener) it.next ()).gpsPositionChanged (e);
+ }
+ }
+ private native void enableGPSPositionChangeEvents (boolean b);
+}
diff --git a/Java/com/phidgets/IRCode.java b/Java/com/phidgets/IRCode.java
new file mode 100644
index 0000000..51b014c
--- /dev/null
+++ b/Java/com/phidgets/IRCode.java
@@ -0,0 +1,93 @@
+
+/*
+ * Copyright 2006 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets;
+/**
+ * This class represents an IR Code.
+ *
+ * @author Phidget Inc.
+ */
+public final class IRCode
+{
+ private short[] data;
+ /**
+ * IR code data. This is MSB first, right justified. This is really an (unsigned) Byte array,
+ * so values range from 0-255. We have to use shorts because Java doesn't support unsigned types.
+ */
+ public short[] getData()
+ {
+ return data;
+ }
+ private int bitCount;
+ /**
+ * Data bits. This is important because many codes use a number of bits that doesn't line up with byte (8-bit) borders.
+ */
+ public int getBitCount()
+ {
+ return bitCount;
+ }
+
+ /**
+ * Creates a new IR Code from a string.
+ * @param code the IR code
+ * @param bitCount the code length in bits.
+ */
+ public IRCode(String code, int bitCount)
+ {
+ this.data = HexToData(code);
+ this.bitCount = bitCount;
+ }
+
+ /**
+ * Creates a new IR Code from a data array.
+ * @param data the IR code data
+ * @param bitCount the code length in bits.
+ */
+ public IRCode(short[] data, int bitCount)
+ {
+ int length = (bitCount / 8) + ((bitCount % 8 > 0) ? 1 : 0);
+
+ this.data = new short[length];
+ for (int i = 0; i < length; i++)
+ this.data[i] = data[i];
+
+ this.bitCount = bitCount;
+ }
+
+ private short[] HexToData(String hexString)
+ {
+ if (hexString == null)
+ return null;
+
+ if (hexString.startsWith("0x")){
+ hexString = hexString.substring(2);
+ }
+
+ if (hexString.length() % 2 == 1)
+ hexString = '0' + hexString; // Up to you whether to pad the first or last byte
+
+ short[] data = new short[hexString.length() / 2];
+
+ for (int i = 0; i < data.length; i++){
+ data[i] = (short) Integer.parseInt(hexString.substring(i * 2, (i * 2) + 2), 16);
+ }
+
+ return data;
+ }
+ private char[] hexlookup = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
+ /**
+ * String representation of the IR code.
+ */
+ public String toString()
+ {
+ String out = "";
+ for(int i=0;i<data.length;i++)
+ {
+ out = out + (hexlookup[data[i] / 16]);
+ out = out + (hexlookup[data[i] % 16]);
+ }
+ return out;
+ }
+}
diff --git a/Java/com/phidgets/IRCodeInfo.java b/Java/com/phidgets/IRCodeInfo.java
new file mode 100644
index 0000000..8c67b10
--- /dev/null
+++ b/Java/com/phidgets/IRCodeInfo.java
@@ -0,0 +1,360 @@
+
+/*
+ * Copyright 2006 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets;
+/**
+ * This class represents IR Code Properties needed for transmit.
+ *
+ * @author Phidget Inc.
+ */
+public final class IRCodeInfo
+{
+ /**
+ * Unknown encoding. This is used with {@link #getEncoding getEncoding}
+ */
+ public static final int ENCODING_UNKNOWN = 1;
+ /**
+ * Space encoding. This is used with {@link #getEncoding getEncoding}
+ */
+ public static final int ENCODING_SPACE = 2;
+ /**
+ * Pulse encoding. This is used with {@link #getEncoding getEncoding}
+ */
+ public static final int ENCODING_PULSE = 3;
+ /**
+ * BiPhase encoding. This is used with {@link #getEncoding getEncoding}
+ */
+ public static final int ENCODING_BIPHASE = 4;
+ /**
+ * RC5 encoding. This is used with {@link #getEncoding getEncoding}
+ */
+ public static final int ENCODING_RC5 = 5;
+ /**
+ * RC6 encoding. This is used with {@link #getEncoding getEncoding}
+ */
+ public static final int ENCODING_RC6 = 6;
+
+ /**
+ * Unknown length. This is used with {@link #getLength getLength}
+ */
+ public static final int LENGTH_UNKNOWN = 1;
+ /**
+ * Constant length. This is used with {@link #getLength getLength}
+ */
+ public static final int LENGTH_CONSTANT = 2;
+ /**
+ * Variable length. This is used with {@link #getLength getLength}
+ */
+ public static final int LENGTH_VARIABLE = 3;
+
+ private int encoding=ENCODING_UNKNOWN, length=LENGTH_UNKNOWN, bitCount=0, gap=0, trail=0, minRepeat=1, carrierFrequency=38000, dutyCycle=33;
+ private int[] header=null, one=new int[] {0,0}, zero=new int[] {0,0}, repeat=null;
+ private IRCode toggleMask=null;
+
+ /**
+ * Creates a new IR Code Info object.
+ * @param bitCount the bit count
+ */
+ public IRCodeInfo(int bitCount) throws PhidgetException
+ {
+ this.bitCount = bitCount;
+ }
+
+ /**
+ * Creates a new IR Code Info object.
+ * @param encoding the encoding - one of {@link #ENCODING_SPACE ENCODING_SPACE},
+ * {@link #ENCODING_PULSE ENCODING_PULSE}, {@link #ENCODING_BIPHASE ENCODING_BIPHASE},
+ * {@link #ENCODING_RC5 ENCODING_RC5} or {@link #ENCODING_RC6 ENCODING_RC6}
+ * @param bitCount the bit count
+ */
+ public IRCodeInfo(int encoding, int bitCount) throws PhidgetException
+ {
+ this.encoding = encoding;
+ this.bitCount = bitCount;
+ }
+
+ /**
+ * Creates a new IR Code Info object.
+ * @param encoding the encoding - one of {@link #ENCODING_SPACE ENCODING_SPACE},
+ * {@link #ENCODING_PULSE ENCODING_PULSE}, {@link #ENCODING_BIPHASE ENCODING_BIPHASE},
+ * {@link #ENCODING_RC5 ENCODING_RC5} or {@link #ENCODING_RC6 ENCODING_RC6}
+ * @param bitCount the bit count
+ * @param header the header (pulse,space)
+ * @param zero the zero (pulse, space)
+ * @param one the one (pulse, space)
+ * @param trail the trailing pulse
+ * @param gap the trailing gap
+ */
+ public IRCodeInfo(int encoding, int bitCount, int[] header, int[] zero, int[] one, int trail, int gap) throws PhidgetException
+ {
+ this.encoding = encoding;
+ this.bitCount = bitCount;
+
+ if(header != null)
+ {
+ if(header.length != 2)
+ throw new PhidgetException(PhidgetException.EPHIDGET_INVALIDARG, "header must have 2 elements");
+ this.header = new int[] { header[0], header[1] };
+ }
+
+ if(zero==null || zero.length != 2)
+ throw new PhidgetException(PhidgetException.EPHIDGET_INVALIDARG, "zero must have 2 elements");
+ this.zero = new int[] { zero[0], zero[1] };
+
+ if(one==null || one.length != 2)
+ throw new PhidgetException(PhidgetException.EPHIDGET_INVALIDARG, "one must have 2 elements");
+ this.one = new int[] { one[0], one[1] };
+
+ this.trail = trail;
+ this.gap = gap;
+ }
+
+ /**
+ * Creates a new IR Code Info object.
+ * @param encoding the encoding - one of {@link #ENCODING_SPACE ENCODING_SPACE},
+ * {@link #ENCODING_PULSE ENCODING_PULSE}, {@link #ENCODING_BIPHASE ENCODING_BIPHASE},
+ * {@link #ENCODING_RC5 ENCODING_RC5} or {@link #ENCODING_RC6 ENCODING_RC6}
+ * @param bitCount the bit count
+ * @param header the header (pulse,space)
+ * @param zero the zero (pulse, space)
+ * @param one the one (pulse, space)
+ * @param trail the trailing pulse
+ * @param gap the trailing gap
+ * @param repeat the special repeat code
+ */
+ public IRCodeInfo(int encoding, int bitCount, int[] header, int[] zero, int[] one, int trail, int gap, int[] repeat) throws PhidgetException
+ {
+ this.encoding = encoding;
+ this.bitCount = bitCount;
+
+ if(header != null)
+ {
+ if(header.length != 2)
+ throw new PhidgetException(PhidgetException.EPHIDGET_INVALIDARG, "header must have 2 elements");
+ this.header = new int[] { header[0], header[1] };
+ }
+
+ if(zero==null || zero.length != 2)
+ throw new PhidgetException(PhidgetException.EPHIDGET_INVALIDARG, "zero must have 2 elements");
+ this.zero = new int[] { zero[0], zero[1] };
+
+ if(one==null || one.length != 2)
+ throw new PhidgetException(PhidgetException.EPHIDGET_INVALIDARG, "one must have 2 elements");
+ this.one = new int[] { one[0], one[1] };
+
+ this.trail = trail;
+ this.gap = gap;
+
+ if(repeat != null)
+ {
+ this.repeat = new int[repeat.length];
+ for(int i=0; i<repeat.length; i++)
+ this.repeat[i] = repeat[i];
+ }
+ }
+
+ /**
+ * Creates a new IR Code Info object.
+ * @param encoding the encoding - one of {@link #ENCODING_SPACE ENCODING_SPACE},
+ * {@link #ENCODING_PULSE ENCODING_PULSE}, {@link #ENCODING_BIPHASE ENCODING_BIPHASE},
+ * {@link #ENCODING_RC5 ENCODING_RC5} or {@link #ENCODING_RC6 ENCODING_RC6}
+ * @param bitCount the bit count
+ * @param header the header (pulse,space)
+ * @param zero the zero (pulse, space)
+ * @param one the one (pulse, space)
+ * @param trail the trailing pulse
+ * @param gap the trailing gap
+ * @param repeat the special repeat code
+ * @param minRepeat the minimum number of times to repeat the code
+ * @param toggleMask the bits to toggle when minRepeat is > 1
+ * @param length the length style - one of {@link #LENGTH_CONSTANT LENGTH_CONSTANT} or {@link #LENGTH_VARIABLE LENGTH_VARIABLE}
+ * @param carrierFrequency the carrier frequency in kHz
+ * @param dutyCycle the duty cycle in percent
+ */
+ public IRCodeInfo(
+ int encoding,
+ int bitCount,
+ int[] header,
+ int[] zero,
+ int[] one,
+ int trail,
+ int gap,
+ int[] repeat,
+ int minRepeat,
+ IRCode toggleMask,
+ int length,
+ int carrierFrequency,
+ int dutyCycle) throws PhidgetException
+ {
+ this.encoding = encoding;
+ this.bitCount = bitCount;
+
+ if(header != null)
+ {
+ if(header.length != 2)
+ throw new PhidgetException(PhidgetException.EPHIDGET_INVALIDARG, "header must have 2 elements");
+ this.header = new int[] { header[0], header[1] };
+ }
+
+ if(zero==null || zero.length != 2)
+ throw new PhidgetException(PhidgetException.EPHIDGET_INVALIDARG, "zero must have 2 elements");
+ this.zero = new int[] { zero[0], zero[1] };
+
+ if(one==null || one.length != 2)
+ throw new PhidgetException(PhidgetException.EPHIDGET_INVALIDARG, "one must have 2 elements");
+ this.one = new int[] { one[0], one[1] };
+
+ this.trail = trail;
+ this.gap = gap;
+
+ if(repeat != null)
+ {
+ this.repeat = new int[repeat.length];
+ for(int i=0; i<repeat.length; i++)
+ this.repeat[i] = repeat[i];
+ }
+
+ this.minRepeat = minRepeat;
+
+ if(toggleMask != null)
+ toggleMask = new IRCode(toggleMask.getData(), toggleMask.getBitCount());
+
+ this.length = length;
+ this.carrierFrequency = carrierFrequency;
+ this.dutyCycle = dutyCycle;
+ }
+
+ /**
+ * Returns the encoding.
+ * @return encoding
+ */
+ public int getEncoding()
+ {
+ return encoding;
+ }
+ /**
+ * Returns the length style.
+ * @return length style
+ */
+ public int getLength()
+ {
+ return length;
+ }
+ /**
+ * Returns the bit count.
+ * @return bit count
+ */
+ public int getBitCount()
+ {
+ return bitCount;
+ }
+ /**
+ * Returns the gap.
+ * @return gap
+ */
+ public int getGap()
+ {
+ return gap;
+ }
+ /**
+ * Returns the trail.
+ * @return trail
+ */
+ public int getTrail()
+ {
+ return trail;
+ }
+ /**
+ * Returns the min repeat.
+ * @return min repeat
+ */
+ public int getMinRepeat()
+ {
+ return minRepeat;
+ }
+ /**
+ * Returns the carrier frequency.
+ * @return carrier frequency
+ */
+ public int getCarrierFrequency()
+ {
+ return carrierFrequency;
+ }
+ /**
+ * Returns the duty cycle.
+ * @return duty cycle
+ */
+ public int getDutyCycle()
+ {
+ return dutyCycle;
+ }
+ /**
+ * Returns the header.
+ * @return header
+ */
+ public int[] getHeader()
+ {
+ return header;
+ }
+ /**
+ * Returns the zero.
+ * @return zero
+ */
+ public int[] getZero()
+ {
+ return zero;
+ }
+ /**
+ * Returns the one.
+ * @return one
+ */
+ public int[] getOne()
+ {
+ return one;
+ }
+ /**
+ * Returns the repeat code.
+ * @return repeat code
+ */
+ public int[] getRepeat()
+ {
+ return repeat;
+ }
+ /**
+ * Returns the toggle mask.
+ * @return toggle mask
+ */
+ public IRCode getToggleMask()
+ {
+ return toggleMask;
+ }
+
+
+ public String toString()
+ {
+ String out = "";
+ out = out + " Encoding: " + encoding + "\n";
+ out = out + " Zero: " + zero[0] + ", " + zero[1] + "\n";
+ out = out + " One: " + one[0] + ", " + one[1] + "\n";
+ if (header != null)
+ {
+ if (header[0] != 0)
+ out = out + " Header: " + header[0] + ", " + header[1] + "\n";
+ }
+
+ if (trail != 0)
+ out = out + " Trail: " + trail + "\n";
+ if (gap != 0)
+ out = out + " Gap: " + gap + "\n";
+ if (repeat != null)
+ {
+ out = out + " Repeat: ";
+ for(int i=0;i<repeat.length;i++)
+ out = out + repeat[i] + ", ";
+ out = out + "\n";
+ }
+ return out;
+ }
+}
diff --git a/Java/com/phidgets/IRLearnedCode.java b/Java/com/phidgets/IRLearnedCode.java
new file mode 100644
index 0000000..4949d07
--- /dev/null
+++ b/Java/com/phidgets/IRLearnedCode.java
@@ -0,0 +1,51 @@
+
+/*
+ * Copyright 2006 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets;
+/**
+ * This class represents an IR Learned Code. This is used in the Learn event.
+ *
+ * @author Phidget Inc.
+ */
+public final class IRLearnedCode
+{
+ private IRCode code;
+ private IRCodeInfo codeInfo;
+
+ /**
+ * Creates a new IR Learned Code. This is used in the Learn event.
+ * @param code the IR code
+ * @param codeInfo the code parameters
+ */
+ public IRLearnedCode(IRCode code, IRCodeInfo codeInfo)
+ {
+ this.code=code;
+ this.codeInfo=codeInfo;
+ }
+
+ /**
+ * Returns the code.
+ * @return code
+ */
+ public IRCode getCode()
+ {
+ return code;
+ }
+
+ /**
+ * Returns the code parameters.
+ * @return code parameters
+ */
+ public IRCodeInfo getCodeInfo()
+ {
+ return codeInfo;
+ }
+
+ public String toString()
+ {
+ return code.toString() + " (" + code.getBitCount() + "-bit)\n" + codeInfo.toString();
+ }
+}
+
diff --git a/Java/com/phidgets/IRPhidget.java b/Java/com/phidgets/IRPhidget.java
new file mode 100644
index 0000000..8418d74
--- /dev/null
+++ b/Java/com/phidgets/IRPhidget.java
@@ -0,0 +1,239 @@
+
+/*
+ * Copyright 2010 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets;
+import java.util.Iterator;
+import java.util.LinkedList;
+import com.phidgets.event.*;
+/**
+ * This class represents a Phidget IR. All methods
+ * to send and receive IR data are implemented in this class.
+ * <p>
+ * The Phidget IR Receiver-Transmitter can send and receive Consumer-IR signals. Ability to learn and re-transmit codes,
+ * as well as low-level access to raw data, is provided.
+ *
+ * @author Phidgets Inc.
+ */
+public final class IRPhidget extends Phidget
+{
+ public IRPhidget () throws PhidgetException
+ {
+ super (create ());
+ }
+ private static native long create () throws PhidgetException;
+
+ /**
+ * Represents a long space (greater then 327,670 microseconds) in raw data.
+ * This can be considered a period of no IR activity. This is used with {@link #readRaw readRaw}
+ */
+ public static final int RAWDATA_LONGSPACE = 0x7fffffff;
+
+ /**
+ * Transmits a code.
+ * @param code the code to transmit
+ * @param codeInfo the code specification
+ * @throws PhidgetException If this Phidget is not opened and attached.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native void transmit (IRCode code, IRCodeInfo codeInfo) throws PhidgetException;
+ /**
+ * Transmits a repeat. This needs to be called within the gap time of a transmit to be meaningful.
+ * @throws PhidgetException If this Phidget is not opened and attached.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native void transmitRepeat () throws PhidgetException;
+ /**
+ * Transmits raw data.
+ * @param data data in microseconds, must start and end with a pulse
+ * @param offset offset in the data array to start transmitting
+ * @param count number of elements of data to transmit
+ * @param gap gap size in microseconds
+ * @param carrierFrequency carrier frequency in kHz
+ * @param dutyCycle duty cycle in percent
+ * @throws PhidgetException If this Phidget is not opened and attached.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native void transmitRaw (int[]data, int offset, int count, int gap, int carrierFrequency, int dutyCycle) throws PhidgetException;
+ /**
+ * Transmits raw data.
+ * @param data data in microseconds, must start and end with a pulse
+ * @throws PhidgetException If this Phidget is not opened and attached.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public final void transmitRaw (int[]data) throws PhidgetException
+ {
+ transmitRaw (data, 0, data.length, 0, 0, 0);
+ }
+ /**
+ * Transmits raw data.
+ * @param data data in microseconds, must start and end with a pulse
+ * @param gap gap size in microseconds
+ * @throws PhidgetException If this Phidget is not opened and attached.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public final void transmitRaw (int[]data, int gap) throws PhidgetException
+ {
+ transmitRaw (data, 0, data.length, gap, 0, 0);
+ }
+ /**
+ * Transmits raw data.
+ * @param data data in microseconds, must start and end with a pulse
+ * @param offset offset in the data array to start transmitting
+ * @param count number of elements of data to transmit
+ * @throws PhidgetException If this Phidget is not opened and attached.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public final void transmitRaw (int[]data, int offset, int count) throws PhidgetException
+ {
+ transmitRaw (data, offset, count, 0, 0, 0);
+ }
+ /**
+ * Transmits raw data.
+ * @param data data in microseconds, must start and end with a pulse
+ * @param offset offset in the data array to start transmitting
+ * @param count number of elements of data to transmit
+ * @param gap gap size in microseconds
+ * @throws PhidgetException If this Phidget is not opened and attached.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public final void transmitRaw (int[]data, int offset, int count, int gap) throws PhidgetException
+ {
+ transmitRaw (data, offset, count, gap, 0, 0);
+ }
+ /**
+ * Reads raw data. Use {@link #RAWDATA_LONGSPACE RAWDATA_LONGSPACE} to detect gaps in IR data.
+ * @param buffer array into which data will be read.
+ * @param offset offset in data to start writing
+ * @param count maximum ammount of data to read
+ * @return ammount of data read
+ * @throws PhidgetException If this Phidget is not opened and attached.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native int readRaw (int[]buffer, int offset, int count) throws PhidgetException;
+ /**
+ * Reads raw data. Use {@link #RAWDATA_LONGSPACE RAWDATA_LONGSPACE} to detect gaps in IR data.
+ * @param buffer array into which data will be read.
+ * @return ammount of data read
+ * @throws PhidgetException If this Phidget is not opened and attached.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public final int readRaw (int[]buffer) throws PhidgetException
+ {
+ return readRaw (buffer, 0, buffer.length);
+ }
+ /**
+ * Returns the last recieved code. This is updated right after the code event returns.
+ * @return last code
+ * @throws PhidgetException If this Phidget is not opened and attached.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native IRCode getLastCode () throws PhidgetException;
+ /**
+ * Returns the last learned code. This is updated right after the learn event returns.
+ * @return last learned code
+ * @throws PhidgetException If this Phidget is not opened and attached.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native IRLearnedCode getLastLearnedCode () throws PhidgetException;
+
+ private final void enableDeviceSpecificEvents (boolean b)
+ {
+ enableCodeEvents (b && codeListeners.size () > 0);
+ enableLearnEvents (b && learnListeners.size () > 0);
+ enableRawDataEvents (b && rawDataListeners.size () > 0);
+ }
+ /**
+ * Adds a code listener. The code handler is a method that will be called when a new code is
+ seen by the reader. The event is fired on each code, including repetitions.
+ * <p>
+ * There is no limit on the number of code handlers that can be registered for a particular Phidget.
+ *
+ * @param l An implemetation of the {@link com.phidgets.event.CodeListener CodeListener} interface
+ */
+ public final void addCodeListener (CodeListener l)
+ {
+ synchronized (codeListeners)
+ {
+ codeListeners.add (l);
+ enableCodeEvents (true);
+ }} private LinkedList codeListeners = new LinkedList ();
+ private long nativeCodeHandler = 0;
+ public final void removeCodeListener (CodeListener l)
+ {
+ synchronized (codeListeners)
+ {
+ codeListeners.remove (l);
+ enableCodeEvents (codeListeners.size () > 0);
+ }} private void fireCode (CodeEvent e)
+ {
+ synchronized (codeListeners)
+ {
+ for (Iterator it = codeListeners.iterator (); it.hasNext ();)
+ ((CodeListener) it.next ()).code (e);
+ }
+ }
+ private native void enableCodeEvents (boolean b);
+ /**
+ * Adds a code learn listener. The learn handler is a method that will be called when a new code is
+ learned by the reader. This requires that the code be repeated several times.
+ * <p>
+ * There is no limit on the number of learn handlers that can be registered for a particular Phidget.
+ *
+ * @param l An implemetation of the {@link com.phidgets.event.LearnListener LearnListener} interface
+ */
+ public final void addLearnListener (LearnListener l)
+ {
+ synchronized (learnListeners)
+ {
+ learnListeners.add (l);
+ enableLearnEvents (true);
+ }} private LinkedList learnListeners = new LinkedList ();
+ private long nativeLearnHandler = 0;
+ public final void removeLearnListener (LearnListener l)
+ {
+ synchronized (learnListeners)
+ {
+ learnListeners.remove (l);
+ enableLearnEvents (learnListeners.size () > 0);
+ }} private void fireLearn (LearnEvent e)
+ {
+ synchronized (learnListeners)
+ {
+ for (Iterator it = learnListeners.iterator (); it.hasNext ();)
+ ((LearnListener) it.next ()).learn (e);
+ }
+ }
+ private native void enableLearnEvents (boolean b);
+ /**
+ * Adds a rawData listener. The rawData handler is a method that will be called when a raw IR data is recieved.
+ * <p>
+ * There is no limit on the number of rawData handlers that can be registered for a particular Phidget.
+ *
+ * @param l An implemetation of the {@link com.phidgets.event.RawDataListener RawDataListener} interface
+ */
+ public final void addRawDataListener (RawDataListener l)
+ {
+ synchronized (rawDataListeners)
+ {
+ rawDataListeners.add (l);
+ enableRawDataEvents (true);
+ }} private LinkedList rawDataListeners = new LinkedList ();
+ private long nativeRawDataHandler = 0;
+ public final void removeRawDataListener (RawDataListener l)
+ {
+ synchronized (rawDataListeners)
+ {
+ rawDataListeners.remove (l);
+ enableRawDataEvents (rawDataListeners.size () > 0);
+ }} private void fireRawData (RawDataEvent e)
+ {
+ synchronized (rawDataListeners)
+ {
+ for (Iterator it = rawDataListeners.iterator (); it.hasNext ();)
+ ((RawDataListener) it.next ()).rawData (e);
+ }
+ }
+ private native void enableRawDataEvents (boolean b);
+}
diff --git a/Java/com/phidgets/InterfaceKitPhidget.java b/Java/com/phidgets/InterfaceKitPhidget.java
new file mode 100644
index 0000000..d7aed29
--- /dev/null
+++ b/Java/com/phidgets/InterfaceKitPhidget.java
@@ -0,0 +1,346 @@
+/*
+ * Copyright 2006 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+
+import com.phidgets.event.*;
+
+/**
+ * This class represents a Phidget Interface Kit. All methods
+ * to read and write data to and from an Interface Kit are implemented in this class.
+ * <p>
+ * There are many types of Interface Kits, but each is simply a collection of 0 or more
+ * digital inputs, digital outpus and analog sensors. Inputs can be read and outputs can be set,
+ * and event handlers can be set for each of these.
+ * <p>
+ * See your hardware documentation for more information on the I/O specific to your Phidget.
+ *
+ * @author Phidgets Inc.
+ */
+public final class InterfaceKitPhidget extends Phidget
+{
+ /**
+ * Class Constructor. Calling this opens a connection to the phidget21 C library creates
+ * an internal handle for this Phidget, ready to call open on.
+ *
+ * @throws PhidgetException If there was a problem connecting to phidget21 or creating
+ * the internal handle.
+ */
+ public InterfaceKitPhidget() throws PhidgetException {
+ super(create());
+ }
+
+ private static native long create() throws PhidgetException;
+
+ /**
+ * Returns the number of digital outputs on this Interface Kit. Not all interface kits
+ * have the same number of digital outputs, and some don't have any digital outputs at all.
+ *
+ * @return Number of digital outputs
+ * @throws PhidgetException If this Phidget is not opened and attached.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native int getOutputCount() throws PhidgetException;
+
+ /**
+ * Returns the number of ditigal inputs on this Interface Kit. Not all interface kits
+ * have the same number of digital inputs, and some don't have any digital inputs at all.
+ *
+ * @return Number of digital inputs
+ * @throws PhidgetException If this Phidget is not opened and attached.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native int getInputCount() throws PhidgetException;
+
+ /**
+ * Returns the number of analog inputs on the Interface Kit. Not all interface kits
+ * have the same number of analog inputs, and some don't have any analog inputs at all.
+ *
+ * @return Number of analog inputs
+ * @throws PhidgetException If this Phidget is not opened and attached.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native int getSensorCount() throws PhidgetException;
+
+ /**
+ * Returns the minimum data rate for a sensor, in milliseconds.
+ *
+ * @param index Index of the input
+ * @return minimum data rate
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is out of range.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native int getDataRateMin(int index) throws PhidgetException;
+
+ /**
+ * Returns the maximum data rate for a sensor, in milliseconds.
+ *
+ * @param index Index of the input
+ * @return maximum data rate
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is out of range.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native int getDataRateMax(int index) throws PhidgetException;
+
+ /**
+ * Returns the state of a digital input. Digital inputs read True where they are activated and false
+ * when they are in their default state.
+ * <p>
+ * Be sure to check {@link #getInputCount() getInputCount} first if you are unsure as to the number of inputs, so as not to
+ * set an Index that is out of range.
+ *
+ * @param index Index of the input
+ * @return State of the input
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is out of range.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native boolean getInputState(int index) throws PhidgetException;
+
+ /**
+ * Returns the state of a digital output. Depending on the Phidget, this value may be either the value that you last
+ * wrote out to the Phidget, or the value that the Phidget last returned. This is because some Phidgets return their output state
+ * and others do not. This means that with some devices, reading the output
+ * state of a pin directly after setting it, may not return the value that you just set.
+ * <p>
+ * Be sure to check {@link #getOutputCount() getOutputCount} first if you are unsure as to the number of outputs, so as not to
+ * attempt to get an Index that is out of range.
+ *
+ * @param index Index of the output
+ * @return State of the output
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is out of range.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native boolean getOutputState(int index) throws PhidgetException;
+
+ /**
+ * Returns the value of a analog input.
+ * The analog inputs are where analog sensors are attached on the InterfaceKit 8/8/8.
+ * On the Linear and Circular touch sensor Phidgets, analog input 0 represents position
+ * on the slider.
+ * <p>
+ * The valid range is 0-1000. In the case of a sensor, this value can be converted to an actual
+ * sensor value using the formulas provided here: http://www.phidgets.com/documentation/Sensors.pdf
+ *
+ * @param index Index of the sensor
+ * @return Sensor value
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is out of range.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native int getSensorValue(int index) throws PhidgetException;
+
+ /**
+ * Returns the raw value of a analog input. This is a more accurate version of {@link #getSensorValue(int) getSensorValue}.
+ * The valid range is 0-4095. Note however that the analog outputs on the Interface Kit 8/8/8 are only 10-bit values
+ * and this value represents an oversampling to 12-bit.
+ *
+ * @param index Index of the sensor
+ * @return Sensor value
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is out of range.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native int getSensorRawValue(int index) throws PhidgetException;
+
+ /**
+ * Returns the change trigger for an analog input. This is the ammount that an inputs must change
+ * between successive SensorChangeEvents. This is based on the 0-1000 range provided by getSensorValue.
+ * This value is by default set to 10 for most Interface Kits with analog inputs.
+ *
+ * @param index Index of the sensor
+ * @return Trigger value
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is out of range.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native int getSensorChangeTrigger(int index)
+ throws PhidgetException;
+
+ /**
+ * Returns the data rate for a sensor, in milliseconds.
+ *
+ * @param index Index of the sensor
+ * @return data rate
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is out of range.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native int getDataRate(int index)
+ throws PhidgetException;
+
+ /**
+ * Gets the ratiometric state for the analog sensors
+ *
+ * @return state State
+ * @throws PhidgetException If this Phidget is not opened and attached, or if this phidget does not support ratiometric.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native boolean getRatiometric()
+ throws PhidgetException;
+
+ /**
+ * Sets the state of a digital output. Setting this to true will activate the output, False is the default state.
+ *
+ * @param index Index of the output
+ * @param newVal State to set the output to
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is out of range.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native void setOutputState(int index, boolean newVal)
+ throws PhidgetException;
+
+ /**
+ * Sets the change trigger for an analog input. This is the ammount that an inputs must change
+ * between successive SensorChangeEvents. This is based on the 0-1000 range provided by getSensorValue.
+ * This value is by default set to 10 for most Interface Kits with analog inputs.
+ *
+ * @param index Input
+ * @param newVal Value
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is out of range.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native void setSensorChangeTrigger(int index, int newVal)
+ throws PhidgetException;
+
+ /**
+ * Sets the data rate of a sensor, in milliseconds.
+ *
+ * @param index Input
+ * @param newVal data rate
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is out of range.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native void setDataRate(int index, int newVal)
+ throws PhidgetException;
+
+ /**
+ * Sets the ratiometric state for the analog inputs. The default is for ratiometric to be set on and this
+ * is appropriate for most sensors.
+ *
+ * @param state State
+ * @throws PhidgetException If this Phidget is not opened and attached, or if this Phidget does not support ratiometric
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native void setRatiometric(boolean state)
+ throws PhidgetException;
+
+ private final void enableDeviceSpecificEvents(boolean b) {
+ enableInputChangeEvents(b && inputChangeListeners.size() > 0);
+ enableOutputChangeEvents(b && outputChangeListeners.size() > 0);
+ enableSensorChangeEvents(b && sensorChangeListeners.size() > 0);
+ }
+
+ private LinkedList inputChangeListeners = new LinkedList();
+ private long nativeInputChangeHandler = 0;
+
+ /**
+ * Adds an input change listener. The input change handler is a method that will be called when an input on this
+ * Interface Kit has changed.
+ * <p>
+ * There is no limit on the number of input change handlers that can be registered for a particular Phidget.
+ *
+ * @param l An implemetation of the {@link com.phidgets.event.InputChangeListener InputChangeListener} interface
+ */
+ public final void addInputChangeListener(InputChangeListener l) {
+ synchronized (inputChangeListeners) {
+ inputChangeListeners.add(l);
+ enableInputChangeEvents(true);
+ }
+ }
+
+ /**
+ * Removes an input change listener. This will remove a previously added input change listener.
+ */
+ public final void removeInputChangeListener(InputChangeListener l) {
+ synchronized (inputChangeListeners) {
+ inputChangeListeners.remove(l);
+ enableInputChangeEvents(inputChangeListeners.size() >
+ 0);
+ }
+ }
+ private void fireInputChange(InputChangeEvent e) {
+ synchronized (inputChangeListeners) {
+ for (Iterator it = inputChangeListeners.iterator();
+ it.hasNext(); )
+ ((InputChangeListener)it.next()).inputChanged(
+ e);
+ }
+ }
+ private native void enableInputChangeEvents(boolean b);
+
+ private LinkedList outputChangeListeners = new LinkedList();
+ private long nativeOutputChangeHandler = 0;
+
+ /**
+ * Adds an output change listener. The output change handler is a method that will be called when an output on this
+ * Interface Kit has changed.
+ * <p>
+ * There is no limit on the number of output change handlers that can be registered for a particular Phidget.
+ *
+ * @param l An implemetation of the {@link com.phidgets.event.OutputChangeListener OutputChangeListener} interface
+ */
+ public final void addOutputChangeListener(OutputChangeListener l) {
+ synchronized (outputChangeListeners) {
+ outputChangeListeners.add(l);
+ enableOutputChangeEvents(true);
+ }
+ }
+
+ /**
+ * Removes an output change listener. This will remove a previously added output change listener.
+ */
+ public final void removeOutputChangeListener(OutputChangeListener l) {
+ synchronized (outputChangeListeners) {
+ outputChangeListeners.remove(l);
+ enableOutputChangeEvents(outputChangeListeners.size()
+ > 0);
+ }
+ }
+ private void fireOutputChange(OutputChangeEvent e) {
+ synchronized (outputChangeListeners) {
+ for (Iterator it = outputChangeListeners.iterator();
+ it.hasNext(); )
+ ((OutputChangeListener)it.next())
+ .outputChanged(e);
+ }
+ }
+ private native void enableOutputChangeEvents(boolean b);
+
+ private LinkedList sensorChangeListeners = new LinkedList();
+ private long nativeSensorChangeHandler = 0;
+
+ /**
+ * Adds a sensor change listener. The sensor change handler is a method that will be called when a sensor on this
+ * Interface Kit has changed by at least the {@link #getSensorChangeTrigger(int) Trigger} that has been set for this sensor.
+ * <p>
+ * There is no limit on the number of sensor change handlers that can be registered for a particular Phidget.
+ *
+ * @param l An implemetation of the {@link com.phidgets.event.SensorChangeListener SensorChangeListener} interface
+ */
+ public final void addSensorChangeListener(SensorChangeListener l) {
+ synchronized (sensorChangeListeners) {
+ sensorChangeListeners.add(l);
+ enableSensorChangeEvents(true);
+ }
+ }
+
+ /**
+ * Removes a sensor change listener. This will remove a previously added sensor change listener.
+ */
+ public final void removeSensorChangeListener(SensorChangeListener l) {
+ synchronized (sensorChangeListeners) {
+ sensorChangeListeners.remove(l);
+ enableSensorChangeEvents(sensorChangeListeners.size()
+ > 0);
+ }
+ }
+ private void fireSensorChange(SensorChangeEvent e) {
+ synchronized (sensorChangeListeners) {
+ for (Iterator it = sensorChangeListeners.iterator();
+ it.hasNext(); )
+ ((SensorChangeListener)it.next())
+ .sensorChanged(e);
+ }
+ }
+ private native void enableSensorChangeEvents(boolean b);
+}
diff --git a/Java/com/phidgets/LEDPhidget.java b/Java/com/phidgets/LEDPhidget.java
new file mode 100644
index 0000000..77a37e2
--- /dev/null
+++ b/Java/com/phidgets/LEDPhidget.java
@@ -0,0 +1,141 @@
+
+/*
+ * Copyright 2006 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets;
+import java.util.Iterator;
+import java.util.LinkedList;
+import com.phidgets.event.*;
+/**
+ * This class represents a Phidget LED. All methods
+ * to control a Phidget LED are implemented in this class.
+ <p>
+ The Phidget LED is a board that is meant for driving LEDs. Currently, the
+ only available version drives 64 LEDs, but other versions may become available
+ so this number is not absolute.
+ <p>
+ LEDs can be controlled individually, at brightness levels from 0-100.
+ *
+ * @author Phidgets Inc.
+ */
+public final class LEDPhidget extends Phidget
+{
+ public LEDPhidget () throws PhidgetException
+ {
+ super (create ());
+ }
+ private static native long create () throws PhidgetException;
+
+ /**
+ * 20mA current limit. This is used with {@link #getCurrentLimit getCurrentLimit} and {@link #setCurrentLimit setCurrentLimit}
+ */
+ public static final int PHIDGET_LED_CURRENT_LIMIT_20mA = 1;
+ /**
+ * 40mA current limit. This is used with {@link #getCurrentLimit getCurrentLimit} and {@link #setCurrentLimit setCurrentLimit}
+ */
+ public static final int PHIDGET_LED_CURRENT_LIMIT_40mA = 2;
+ /**
+ * 60mA current limit. This is used with {@link #getCurrentLimit getCurrentLimit} and {@link #setCurrentLimit setCurrentLimit}
+ */
+ public static final int PHIDGET_LED_CURRENT_LIMIT_60mA = 3;
+ /**
+ * 80mA current limit. This is used with {@link #getCurrentLimit getCurrentLimit} and {@link #setCurrentLimit setCurrentLimit}
+ */
+ public static final int PHIDGET_LED_CURRENT_LIMIT_80mA = 4;
+
+ /**
+ * 1.7V Voltage output. This is used with {@link #getVoltage getVoltage} and {@link #setVoltage setVoltage}
+ */
+ public static final int PHIDGET_LED_VOLTAGE_1_7V = 1;
+ /**
+ * 2.75V Voltage output. This is used with {@link #getVoltage getVoltage} and {@link #setVoltage setVoltage}
+ */
+ public static final int PHIDGET_LED_VOLTAGE_2_75V = 2;
+ /**
+ * 3.9V Voltage output. This is used with {@link #getVoltage getVoltage} and {@link #setVoltage setVoltage}
+ */
+ public static final int PHIDGET_LED_VOLTAGE_3_9V = 3;
+ /**
+ * 5.0V Voltage output. This is used with {@link #getVoltage getVoltage} and {@link #setVoltage setVoltage}
+ */
+ public static final int PHIDGET_LED_VOLTAGE_5_0V = 4;
+
+ /**
+ * Returns the current limit for the all outputs. This is only supported by some PhidgetLEDs - see the product manual.
+ * The possible values for type are {@link #PHIDGET_LED_CURRENT_LIMIT_20mA PHIDGET_LED_CURRENT_LIMIT_20mA},
+ * {@link #PHIDGET_LED_CURRENT_LIMIT_40mA PHIDGET_LED_CURRENT_LIMIT_40mA}, {@link #PHIDGET_LED_CURRENT_LIMIT_60mA PHIDGET_LED_CURRENT_LIMIT_60mA} and
+ * {@link #PHIDGET_LED_CURRENT_LIMIT_80mA PHIDGET_LED_CURRENT_LIMIT_80mA}
+ * @return Current Limit
+ * @throws PhidgetException If this Phidget is not opened and attached, if the index is out of range, or if unsupported by this board.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native int getCurrentLimit () throws PhidgetException;
+ /**
+ * Sets the current limit for all outputs. This is only supported by some PhidgetLEDs - see the product manual.
+ * <p>
+ * The possible values for type are {@link #PHIDGET_LED_CURRENT_LIMIT_20mA PHIDGET_LED_CURRENT_LIMIT_20mA},
+ * {@link #PHIDGET_LED_CURRENT_LIMIT_40mA PHIDGET_LED_CURRENT_LIMIT_40mA}, {@link #PHIDGET_LED_CURRENT_LIMIT_60mA PHIDGET_LED_CURRENT_LIMIT_60mA} and
+ * {@link #PHIDGET_LED_CURRENT_LIMIT_80mA PHIDGET_LED_CURRENT_LIMIT_80mA}
+ * <p>
+ * By default, currentLimit is set to {@link #PHIDGET_LED_CURRENT_LIMIT_20mA PHIDGET_LED_CURRENT_LIMIT_20mA}.
+ * @param currentLimit Current Limit
+ * @throws PhidgetException If this Phidget is not opened and attached, if the index is out of range, or if unsupported by this board.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native void setCurrentLimit (int currentLimit) throws PhidgetException;
+
+ /**
+ * Returns the voltage output for the all outputs. This is only supported by some PhidgetLEDs - see the product manual.
+ * The possible values for type are {@link #PHIDGET_LED_VOLTAGE_1_7V PHIDGET_LED_VOLTAGE_1_7V},
+ * {@link #PHIDGET_LED_VOLTAGE_2_75V PHIDGET_LED_VOLTAGE_2_75V}, {@link #PHIDGET_LED_VOLTAGE_3_9V PHIDGET_LED_VOLTAGE_3_9V} and
+ * {@link #PHIDGET_LED_VOLTAGE_5_0V PHIDGET_LED_VOLTAGE_5_0V}
+ * @return Voltage
+ * @throws PhidgetException If this Phidget is not opened and attached, if the index is out of range, or if unsupported by this board.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native int getVoltage () throws PhidgetException;
+ /**
+ * Sets the voltage output for all outputs. This is only supported by some PhidgetLEDs - see the product manual.
+ * <p>
+ * The possible values for type are {@link #PHIDGET_LED_VOLTAGE_1_7V PHIDGET_LED_VOLTAGE_1_7V},
+ * {@link #PHIDGET_LED_VOLTAGE_2_75V PHIDGET_LED_VOLTAGE_2_75V}, {@link #PHIDGET_LED_VOLTAGE_3_9V PHIDGET_LED_VOLTAGE_3_9V} and
+ * {@link #PHIDGET_LED_VOLTAGE_5_0V PHIDGET_LED_VOLTAGE_5_0V}
+ * <p>
+ * By default, voltage is set to {@link #PHIDGET_LED_VOLTAGE_2_75V PHIDGET_LED_VOLTAGE_2_75V}.
+ * @param voltage Voltage
+ * @throws PhidgetException If this Phidget is not opened and attached, if the index is out of range, or if unsupported by this board.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native void setVoltage (int voltage) throws PhidgetException;
+
+ /**
+ * Returns the number of LEDs that this board can drive. This may not correspond to the actual number
+ of LEDs attached.
+ * @return number of LEDs
+ * @throws PhidgetException If this Phidget is not opened and attached.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native int getLEDCount () throws PhidgetException;
+ /**
+ * Returns the brightness value of an LED. This value ranges from 0-100.
+ * @param index LED
+ * @return brightness
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is out of range.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native int getDiscreteLED (int index) throws PhidgetException;
+ /**
+ * Sets the brightness of an LED.
+ * Valid values are 0-100, with 0 being off and 100 being the brightest. This 0-100 value is converted internally to a
+ 6-bit value (0-63) so only 64 levels of brightness are actually possible.
+ * @param index index of the LED
+ * @param brightness desired brightness of this LED
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index of brightness value are out of range.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native void setDiscreteLED (int index, int brightness) throws PhidgetException;
+ private final void enableDeviceSpecificEvents (boolean b)
+ {
+ }
+}
diff --git a/Java/com/phidgets/Manager.java b/Java/com/phidgets/Manager.java
new file mode 100644
index 0000000..7e7cafb
--- /dev/null
+++ b/Java/com/phidgets/Manager.java
@@ -0,0 +1,408 @@
+/*
+ * Copyright 2006 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets;
+
+import com.phidgets.event.*;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.Vector;
+
+/**
+ * <p>
+ * This class represents a Phidget Manager.
+ * The Phidget manager is a way to keep track of attached phidgets, it will send
+ * Attach and Detach events as Phidgets are added and removed fromt the system.
+ * <p>
+ * The Phidget manager deals in base Phidget objects. These objects are not actually connected to
+ * opened Phidgets but can be used to get serial number, name, version, etc.
+ *
+ * @author Phidgets Inc.
+ */
+public class Manager
+{
+ private Vector phidgets;
+
+ static
+ {
+ try
+ {
+ System.loadLibrary("phidget21");
+ }
+ catch(UnsatisfiedLinkError ex)
+ {
+ String os = System.getProperty("os.name");
+ if(os.startsWith("Linux"))
+ {
+ throw new ExceptionInInitializerError(ex.getMessage()
+ +"\nCould not locate the Phidget C library (libphidget21.so)."
+ +"\nMake sure it is installed, and add it's path to LD_LIBRARY_PATH.");
+ }
+ else if(os.startsWith("Windows"))
+ {
+ throw new ExceptionInInitializerError(ex.getMessage()
+ +"\nCould not locate the Phidget C library."
+ +"\nThe Windows Phidget21 MSI must be installed.");
+ }
+ else if(os.startsWith("Mac"))
+ {
+ throw new ExceptionInInitializerError(ex.getMessage()
+ +"\nCould not locate the Phidget C library."
+ +"\nThe Mac Phidget21 DMG must be installed.");
+ }
+ else
+ {
+ throw new ExceptionInInitializerError(ex.getMessage()
+ +"\nCould not locate the Phidget C library.");
+ }
+ }
+ }
+
+ private long handle = 0;
+ /**
+ * The default constructor. Creating a Phidget Manager object will initialize the
+ * attach and detach handlers internally, but {@link #open() open} still needs to be called
+ * to actually recieve event notifications.
+ */
+ public Manager() throws PhidgetException
+ {
+ handle = create();
+ phidgets = new Vector();
+ addAttachListener(new AttachListener()
+ {
+ public void attached(AttachEvent ae)
+ {
+ phidgets.add(ae.getSource());
+ }
+ });
+ addDetachListener(new DetachListener()
+ {
+ public void detached(DetachEvent ae)
+ {
+ phidgets.remove(ae.getSource());
+ }
+ });
+ }
+ private final native long create() throws PhidgetException;
+
+ /**
+ * Returns the Address of a Phidget Webservice when this Manager was opened as remote. This may be an IP Address or a hostname.
+ *
+ * @return Server Address
+ * @throws PhidgetException if this Manager was not opened.
+ */
+ public final native String getServerAddress() throws PhidgetException;
+ /**
+ * Returns the Server ID of a Phidget Webservice when this Manager was opened as remote. This is an arbitrary server identifier,
+ * independant of IP address and Port.
+ *
+ * @return Server ID
+ * @throws PhidgetException if this Manager was not opened.
+ */
+ public final native String getServerID() throws PhidgetException;
+ /**
+ * Returns the Port of a Phidget Webservice when this Manager was opened as remote.
+ *
+ * @return Server Port
+ * @throws PhidgetException if this Manager was not opened.
+ */
+ public final native int getServerPort() throws PhidgetException;
+ /**
+ * Returns the attached status of this Manager.
+ *
+ * @return Status
+ * @throws PhidgetException If this Manager is not opened.
+ */
+ public final native boolean isAttached() throws PhidgetException;
+
+ /**
+ * Returns the network attached status for remotely opened Phidgets. This method returns True or False, depending on whether a connection to the
+ * Phidget WebService is open - or not. If this is false for a remote Phidget then the connection is not active - either because a connection
+ * has not yet been established, or because the connection was terminated.
+ *
+ * @return Status
+ * @throws PhidgetException If this Phidget is not opened.
+ */
+ public final native boolean isAttachedToServer() throws PhidgetException;
+
+ private final native void nativeClose() throws PhidgetException;
+ private final native void nativeDelete() throws PhidgetException;
+ private final native void nativeOpen() throws PhidgetException;
+ private final native void nativeOpenRemote(String serverID, String pass) throws PhidgetException;
+ private final native void nativeOpenRemoteIP(String ipAddress, int port, String pass) throws PhidgetException;
+
+ /**
+ * Starts the PhidgetManager. This method starts the phidget manager running in the base Phidget21 C library.
+ * If attach and detach listeners are to be used, they should be registered before start is called so
+ * that no events are missed. Once start is called, the Phidget Manager will be active until {@link #close() close} is called.
+ */
+ public final void open() throws PhidgetException {
+ enableEvents(true);
+ nativeOpen();
+ }
+ /**
+ * Open this Manager remotely and securely, using an IP Address.
+ * <p>
+ * This method is the same as {@link #open(String, int) open(String ipAddress, int port)}, except that it specifies a password.
+ * This password can be set as a parameter when starting the Phidget Webservice.
+ */
+ public final void open(String ipAddress, int port, String password) throws PhidgetException
+ {
+ enableEvents(true);
+ nativeOpenRemoteIP(ipAddress, port, password);
+ }
+ /**
+ * Open this Manager remotely using an IP Address.
+ * <p>
+ * This version of open is network based.
+ * <p>
+ * @param ipAddress IP Address or hostname of the Phidget Webservice
+ * @param port Port of the Phidget Webservice
+ * @throws PhidgetException if the Phidget Webservice cannot be contacted
+ */
+ public final void open(String ipAddress, int port) throws PhidgetException
+ {
+ enableEvents(true);
+ nativeOpenRemoteIP(ipAddress, port, "");
+ }
+ /**
+ * Open this Manager remotely and securely, using a Server ID.
+ * <p>
+ * This method is the same as {@link #open(String) open(String serverID)}, except that it specifies a password.
+ * This password can be set as a parameter when starting the Phidget Webservice.
+ */
+ public final void open(String serverID, String password) throws PhidgetException
+ {
+ enableEvents(true);
+ nativeOpenRemote(serverID, password);
+ }
+ /**
+ * Open this Manager remotely using a Server ID.
+ * <p>
+ * This version of open is network based.
+ * <p>
+ * ServerID can be NULL to get a listing of all Phidgets on all Servers
+ *
+ * @param serverID ServerID of the Phidget Webservice
+ */
+ public final void open(String serverID) throws PhidgetException
+ {
+ enableEvents(true);
+ nativeOpenRemote(serverID, "");
+ }
+
+ /**
+ * Shuts down the Phidget Manager. This method should be called to close down the Phidget Manager.
+ * Events will no longer be recieved. This method gets calledd automatically when the class is
+ * destroyed so calling it is not required.
+ */
+ public final void close() throws PhidgetException {
+ enableEvents(false);
+ nativeClose();
+ }
+
+ private void enableEvents(boolean b)
+ {
+ enableManagerAttachEvents(b && attachListeners.size() > 0);
+ enableManagerDetachEvents(b && detachListeners.size() > 0);
+ enableServerConnectEvents(b && serverConnectListeners.size() > 0);
+ enableServerDisconnectEvents(b && serverDisconnectListeners.size() > 0);
+ }
+
+ private LinkedList attachListeners = new LinkedList();
+ private long nativeAttachHandler = 0;
+
+ /**
+ * Adds an attach listener. The attach handler is a method that will be called when a Phidget is phisically attached
+ * to the system, and has gone through its initalization, and so is ready to be used.
+ * <p>
+ * There is no limit on the number of attach handlers that can be registered for a particular Phidget.
+ *
+ * @param l An implemetation of the {@link com.phidgets.event.AttachListener AttachListener} interface
+ */
+ public final void addAttachListener(AttachListener l) {
+ synchronized (attachListeners) {
+ attachListeners.add(l);
+ enableManagerAttachEvents(true);
+ }
+ }
+
+ /**
+ * Removes an attach listener. This will remove a previously added attach listener.
+ */
+ public final void removeAttachListener(AttachListener l) {
+ synchronized (attachListeners) {
+ attachListeners.remove(l);
+ enableManagerAttachEvents(attachListeners.size() > 0);
+ }
+ }
+ private void fireAttach(AttachEvent e) {
+ synchronized (attachListeners) {
+ for (Iterator it = attachListeners.iterator();
+ it.hasNext(); )
+ ((AttachListener)it.next()).attached(e);
+ }
+ }
+ private native void enableManagerAttachEvents(boolean b);
+
+ private LinkedList detachListeners = new LinkedList();
+ private long nativeDetachHandler = 0;
+
+ /**
+ * Adds a detach listener. The detach handler is a method that will be called when a Phidget is phisically detached
+ * from the system, and is no longer available.
+ * <p>
+ * There is no limit on the number of detach handlers that can be registered for a particular Phidget.
+ *
+ * @param l An implemetation of the {@link com.phidgets.event.DetachListener DetachListener} interface
+ */
+ public final void addDetachListener(DetachListener l) {
+ synchronized (detachListeners) {
+ detachListeners.add(l);
+ enableManagerDetachEvents(true);
+ }
+ }
+
+ /**
+ * Removes a detach listener. This will remove a previously added detach listener.
+ */
+ public final void removeDetachListener(DetachListener l) {
+ synchronized (detachListeners) {
+ detachListeners.remove(l);
+ enableManagerDetachEvents(detachListeners.size() > 0);
+ }
+ }
+ private void fireDetach(DetachEvent e) {
+ synchronized (detachListeners) {
+ for (Iterator it = detachListeners.iterator();
+ it.hasNext(); )
+ ((DetachListener)it.next()).detached(e);
+ }
+ }
+ private native void enableManagerDetachEvents(boolean b);
+
+ private LinkedList serverConnectListeners = new LinkedList();
+ private long nativeServerConnectHandler = 0;
+
+ /**
+ * Adds an serverConnect listener. The serverConnect handler is a method that will be called when a connection to a server is made
+ * <p>
+ * There is no limit on the number of serverConnect handlers that can be registered for a particular Manager.
+ *
+ * @param l An implemetation of the {@link com.phidgets.event.ServerConnectListener ServerConnectListener} interface
+ */
+ public final void addServerConnectListener(ServerConnectListener l)
+ {
+ synchronized (serverConnectListeners)
+ {
+ serverConnectListeners.add(l);
+ enableServerConnectEvents(true);
+ }
+ }
+
+ /**
+ * Removes an serverConnect listener. This will remove a previously added serverConnect listener.
+ */
+ public final void removeServerConnectListener(ServerConnectListener l)
+ {
+ synchronized (serverConnectListeners)
+ {
+ serverConnectListeners.remove(l);
+ enableServerConnectEvents(serverConnectListeners.size() > 0);
+ }
+ }
+ private void fireServerConnect(ServerConnectEvent e)
+ {
+ synchronized (serverConnectListeners)
+ {
+ for (Iterator it = serverConnectListeners.iterator();
+ it.hasNext(); )
+ ((ServerConnectListener)it.next()).serverConnected(e);
+ }
+ }
+ private native void enableServerConnectEvents(boolean b);
+
+
+ private LinkedList serverDisconnectListeners = new LinkedList();
+ private long nativeServerDisconnectHandler = 0;
+
+ /**
+ * Adds an serverDisconnect listener. The serverDisconnect handler is a method that will be called when a connection to a server is terminated.
+ * <p>
+ * There is no limit on the number of serverDisconnect handlers that can be registered for a particular Manager.
+ *
+ * @param l An implemetation of the {@link com.phidgets.event.ServerDisconnectListener ServerDisconnectListener} interface
+ */
+ public final void addServerDisconnectListener(ServerDisconnectListener l)
+ {
+ synchronized (serverDisconnectListeners)
+ {
+ serverDisconnectListeners.add(l);
+ enableServerDisconnectEvents(true);
+ }
+ }
+
+ /**
+ * Removes an serverDisconnect listener. This will remove a previously added serverDisconnect listener.
+ */
+ public final void removeServerDisconnectListener(ServerDisconnectListener l)
+ {
+ synchronized (serverDisconnectListeners)
+ {
+ serverDisconnectListeners.remove(l);
+ enableServerDisconnectEvents(serverDisconnectListeners.size() > 0);
+ }
+ }
+ private void fireServerDisconnect(ServerDisconnectEvent e)
+ {
+ synchronized (serverDisconnectListeners)
+ {
+ for (Iterator it = serverDisconnectListeners.iterator();
+ it.hasNext(); )
+ ((ServerDisconnectListener)it.next()).serverDisconnected(e);
+ }
+ }
+ private native void enableServerDisconnectEvents(boolean b);
+
+ protected void finalize() throws Throwable
+ {
+ try
+ {
+ close();
+ } catch (Exception e) {
+ ;
+ }
+ try
+ {
+ nativeDelete();
+ }
+ catch (Exception e)
+ {
+ ;
+ }
+ finally{
+ handle = 0;
+ super.finalize();
+ }
+ }
+
+ /**
+ * Return a Sring describing this manager.
+ */
+ public String toString()
+ {
+ return "PhidgetManager: ";
+ }
+
+ /**
+ * Returns a list of Phidgets attached to the host computer. This list is updated right before the attach and detach
+ * events, and so will be up to date within these events.
+ * @return list of attached Phidgets
+ */
+ public Vector getPhidgets()
+ {
+ return phidgets;
+ }
+}
diff --git a/Java/com/phidgets/MotorControlPhidget.java b/Java/com/phidgets/MotorControlPhidget.java
new file mode 100644
index 0000000..8539b98
--- /dev/null
+++ b/Java/com/phidgets/MotorControlPhidget.java
@@ -0,0 +1,497 @@
+
+/*
+ * Copyright 2011 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets;
+import java.util.Iterator;
+import java.util.LinkedList;
+import com.phidgets.event.*;
+/**
+ * This class represents a Phidget Motor Controller. All Methods
+ * to to control a motor controller and read back motor data are implemented in this class.
+ <p>
+ The Motor Control Phidget is able to control 1 or more DC motors.
+ Both speed and acceleration are controllable. Speed is controlled via PWM. The size of the motors
+ that can be driven depends on the motor controller. See your hardware documentation for more information.
+ <p>
+ The motor Controller boards also has 0 or more digital inputs.
+ *
+ * @author Phidgets Inc.
+ */
+public final class MotorControlPhidget extends Phidget
+{
+ public MotorControlPhidget () throws PhidgetException
+ {
+ super (create ());
+ }
+ private static native long create () throws PhidgetException;
+
+ /**
+ * Returns the number of motors supported by this Phidget. This does not neccesarily correspond
+ to the number of motors actually attached to the board.
+ * @return number of supported motors
+ * @throws PhidgetException If this Phidget is not opened and attached.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native int getMotorCount () throws PhidgetException;
+ /**
+ * Returns the number of digital inputs. Not all Motor Controllers have digital inputs.
+ * @return number of digital inputs
+ * @throws PhidgetException If this Phidget is not opened and attached.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native int getInputCount () throws PhidgetException;
+ /**
+ * Returns the number of encoders. Not all Motor Controllers have encoders.
+ * @return number of encoders
+ * @throws PhidgetException If this Phidget is not opened and attached.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native int getEncoderCount () throws PhidgetException;
+ /**
+ * Returns the number of analog inputs. Not all Motor Controllers have analog inputs.
+ * @return number of analog inputs
+ * @throws PhidgetException If this Phidget is not opened and attached.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native int getSensorCount () throws PhidgetException;
+ /**
+ * Returns the state of a digital input. True means that the input is activated, and False indicates the default state.
+ * @param index index of the input
+ * @return state of the input
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is invalid.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native boolean getInputState (int index) throws PhidgetException;
+ /**
+ * Returns the position of an encoder. This is an absolute position as calcutated since the encoder was plugged in.
+ This value can be reset to anything using {@link #setEncoderPosition(int, int) setEncoderPosition}. Not all Motor Controllers have encoders.
+
+ * @param index index of the encoder
+ * @return position of the encoder
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is out of range.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native int getEncoderPosition (int index) throws PhidgetException;
+ /**
+ * Sets the position of a specific encoder. This resets the internal position count for an encoder. This call in no way actually
+ sends information to the device, as an absolute position is maintained only in the library. After this call, position changes
+ from the encoder will use the new value to calculate absolute position as reported by {@link #getEncoderPosition}. Not all Motor Controllers have encoders.
+ * @param index index of the encoder
+ * @param position new position for a encoder.
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is out of range.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native void setEncoderPosition (int index, int position) throws PhidgetException;
+ /**
+ * Returns the value of a sensor. Not all Motor Controllers have analog sensors.
+ * @param index index of the sensor
+ * @return sensor value of the sensor. Range is 0-1000.
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is out of range.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native int getSensorValue (int index) throws PhidgetException;
+ /**
+ * Returns the raw value of a sensor(12-bit). Not all Motor Controllers have analog sensors.
+ * @param index index of the sensor
+ * @return sensor raw value of the sensor. Range is 0-4096.
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is out of range.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native int getSensorRawValue (int index) throws PhidgetException;
+ /**
+ * Returns the ratiometric state of a sensor. Not all Motor Controllers have analog sensors.
+ * @return ratiometric state of sensors
+ * @throws PhidgetException If this Phidget is not opened and attached.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native boolean getRatiometric () throws PhidgetException;
+ /**
+ * Sets the ratiometric state. This controls the voltage reference used for sampling the analog sensors.
+ * @param ratiometric new ratiometric state of the sensors
+ * @throws PhidgetException If this Phidget is not opened and attached.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native void setRatiometric (boolean ratiometric) throws PhidgetException;
+ /**
+ * Returns a motor's acceleration. The valid range is between {@link #getAccelerationMin getAccelerationMin} and {@link #getAccelerationMax getAccelerationMax}, and refers to how fast the Motor Controller
+ will change the speed of a motor.
+ * @param index Index of motor
+ * @return acceleration of motor
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is invalid.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native double getAcceleration (int index) throws PhidgetException;
+ /**
+ * Sets a motor's acceleration.
+ * The valid range is between {@link #getAccelerationMin getAccelerationMin} and {@link #getAccelerationMax getAccelerationMax}. This controls how fast the motor changes speed.
+ * @param index index of the motor
+ * @param acceleration requested acceleration for that motor
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index or acceleration value are invalid.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native void setAcceleration (int index, double acceleration) throws PhidgetException;
+ /**
+ * Returns the maximum acceleration that a motor will accept, or return.
+ * @param index Index of the motor
+ * @return Maximum acceleration
+ * @throws PhidgetException If this Phidget is not opened and attached.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native double getAccelerationMax (int index) throws PhidgetException;
+ /**
+ * Returns the minimum acceleration that a motor will accept, or return.
+ * @param index Index of the motor
+ * @return Minimum acceleration
+ * @throws PhidgetException If this Phidget is not opened and attached.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native double getAccelerationMin (int index) throws PhidgetException;
+ /**
+ * Returns a motor's velocity. The valid range is -100 - 100, with 0 being stopped.
+ * @param index index of the motor
+ * @return current velocity of the motor
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is invalid.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native double getVelocity (int index) throws PhidgetException;
+ /**
+ * @deprecated Replaced by
+ * {@link #getVelocity}
+ */
+ public native double getSpeed (int index) throws PhidgetException;
+ /**
+ * Sets a motor's velocity.
+ * The valid range is from -100 to 100, with 0 being stopped. -100 and 100 both correspond to full voltage,
+ with the value in between corresponding to different widths of PWM.
+ * @param index index of the motor
+ * @param velocity requested velocity for the motor
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index or speed value are invalid.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native void setVelocity (int index, double velocity) throws PhidgetException;
+ /**
+ * @deprecated Replaced by
+ * {@link #setVelocity}
+ */
+ public native void setSpeed (int index, double speed) throws PhidgetException;
+ /**
+ * Returns a motor's current usage. The valid range is 0 - 255. Note that this is not supported on all motor controllers.
+ * @param index index of the motor
+ * @return current usage of the motor
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is invalid.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native double getCurrent (int index) throws PhidgetException;
+ /**
+ * Returns the Back EMF sensing state for a specific motor. Note that this is not supported on all motor controllers.
+ * @param index Index of the motor
+ * @return Back EMF Sensing state for the motor
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is invalid.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native boolean getBackEMFSensingState (int index) throws PhidgetException;
+ /**
+ * Sets the Back EMF sensing state for a specific motor. Note that this is not supported on all motor controllers.
+ * @param index Index of the motor
+ * @param bEMFState new Back EMF Sensing State
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is invalid.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native void setBackEMFSensingState (int index, boolean bEMFState) throws PhidgetException;
+ /**
+ * Sets the Back EMF voltage for a specific motor. Note that this is not supported on all motor controllers.
+ * @param index Index of the motor
+ * @return Back EMF voltage of the motor
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is invalid.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native double getBackEMF (int index) throws PhidgetException;
+ /**
+ * Sets the supply voltage for the motors. This could be higher than the actual voltage. Note that this is not supported on all motor controllers.
+ * @return Supply voltage of the motor, in volts
+ * @throws PhidgetException If this Phidget is not opened and attached, the index is invalid, or if {@link #setBackEMFSensingState setBackEMFSensingState} is not set.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native double getSupplyVoltage () throws PhidgetException;
+ /**
+ * Returns the braking value for a specific motor. Note that this is not supported on all motor controllers.
+ * @param index index of the motor
+ * @return Braking value for the motor
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is invalid.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native double getBraking (int index) throws PhidgetException;
+ /**
+ * Sets the braking value for a specific motor. This is applied when velocity is 0. Default is 0%. Note that this is not supported on all motor controllers. Range is 0-100.
+ * @param index index of the motor
+ * @param braking new braking value for a specific motor
+ * @throws PhidgetException If this Phidget is not opened and attached, the index is invalid, or the brake value is invalid
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native void setBraking (int index, double braking) throws PhidgetException;
+
+ private final void enableDeviceSpecificEvents (boolean b)
+ {
+ enableMotorVelocityChangeEvents (b && motorVelocityChangeListeners.size () > 0);
+ enableCurrentChangeEvents (b && currentChangeListeners.size () > 0);
+ enableCurrentUpdateEvents (b && currentUpdateListeners.size () > 0);
+ enableInputChangeEvents (b && inputChangeListeners.size () > 0);
+ enableEncoderPositionChangeEvents (b && encoderPositionChangeListeners.size () > 0);
+ enableEncoderPositionUpdateEvents (b && encoderPositionUpdateListeners.size () > 0);
+ enableBackEMFUpdateEvents (b && backEMFUpdateListeners.size () > 0);
+ enableSensorUpdateEvents (b && sensorUpdateListeners.size () > 0);
+ }
+ /**
+ * Adds a velocity change listener. The velocity change handler is a method that will be called when the velocity
+ of a motor changes. These velocity changes are reported back from the Motor Controller and so correspond to actual motor speeds
+ over time.
+ * <p>
+ * There is no limit on the number of velocity change handlers that can be registered for a particular Phidget.
+ *
+ * @param l An implemetation of the {@link com.phidgets.event.MotorVelocityChangeListener MotorVelocityChangeListener} interface
+ */
+ public final void addMotorVelocityChangeListener (MotorVelocityChangeListener l)
+ {
+ synchronized (motorVelocityChangeListeners)
+ {
+ motorVelocityChangeListeners.add (l);
+ enableMotorVelocityChangeEvents (true);
+ }} private LinkedList motorVelocityChangeListeners = new LinkedList ();
+ private long nativeMotorVelocityChangeHandler = 0;
+ public final void removeMotorVelocityChangeListener (MotorVelocityChangeListener l)
+ {
+ synchronized (motorVelocityChangeListeners)
+ {
+ motorVelocityChangeListeners.remove (l);
+ enableMotorVelocityChangeEvents (motorVelocityChangeListeners.size () > 0);
+ }} private void fireMotorVelocityChange (MotorVelocityChangeEvent e)
+ {
+ synchronized (motorVelocityChangeListeners)
+ {
+ for (Iterator it = motorVelocityChangeListeners.iterator (); it.hasNext ();)
+ ((MotorVelocityChangeListener) it.next ()).motorVelocityChanged (e);
+ }
+ }
+ private native void enableMotorVelocityChangeEvents (boolean b);
+ /**
+ * Adds a current change listener. The current change handler is a method that will be called when the current
+ consumed by a motor changes. Note that this event is not supported with the current motor controller, but
+ will be supported in the future
+ * <p>
+ * There is no limit on the number of current change handlers that can be registered for a particular Phidget.
+ *
+ * @param l An implemetation of the {@link com.phidgets.event.CurrentChangeListener CurrentChangeListener} interface
+ */
+ public final void addCurrentChangeListener (CurrentChangeListener l)
+ {
+ synchronized (currentChangeListeners)
+ {
+ currentChangeListeners.add (l);
+ enableCurrentChangeEvents (true);
+ }} private LinkedList currentChangeListeners = new LinkedList ();
+ private long nativeCurrentChangeHandler = 0;
+ public final void removeCurrentChangeListener (CurrentChangeListener l)
+ {
+ synchronized (currentChangeListeners)
+ {
+ currentChangeListeners.remove (l);
+ enableCurrentChangeEvents (currentChangeListeners.size () > 0);
+ }} private void fireCurrentChange (CurrentChangeEvent e)
+ {
+ synchronized (currentChangeListeners)
+ {
+ for (Iterator it = currentChangeListeners.iterator (); it.hasNext ();)
+ ((CurrentChangeListener) it.next ()).currentChanged (e);
+ }
+ }
+ private native void enableCurrentChangeEvents (boolean b);
+ /**
+ * Adds a current update listener. The current change handler is a method that will be called every 8ms, regardless whether the current
+ consumed by a motor changes. Note that this event is not supported with all motor controllers
+ * <p>
+ * There is no limit on the number of current update handlers that can be registered for a particular Phidget.
+ *
+ * @param l An implemetation of the {@link com.phidgets.event.CurrentUpdateListener CurrentUpdateListener} interface
+ */
+ public final void addCurrentUpdateListener (CurrentUpdateListener l)
+ {
+ synchronized (currentUpdateListeners)
+ {
+ currentUpdateListeners.add (l);
+ enableCurrentUpdateEvents (true);
+ }} private LinkedList currentUpdateListeners = new LinkedList ();
+ private long nativeCurrentUpdateHandler = 0;
+ public final void removeCurrentUpdateListener (CurrentUpdateListener l)
+ {
+ synchronized (currentUpdateListeners)
+ {
+ currentUpdateListeners.remove (l);
+ enableCurrentUpdateEvents (currentUpdateListeners.size () > 0);
+ }} private void fireCurrentUpdate (CurrentUpdateEvent e)
+ {
+ synchronized (currentUpdateListeners)
+ {
+ for (Iterator it = currentUpdateListeners.iterator (); it.hasNext ();)
+ ((CurrentUpdateListener) it.next ()).currentUpdated (e);
+ }
+ }
+ private native void enableCurrentUpdateEvents (boolean b);
+ /**
+ * Adds an input change listener. The input change handler is a method that will be called when an input on this
+ * Motor Controller board has changed.
+ * <p>
+ * There is no limit on the number of input change handlers that can be registered for a particular Phidget.
+ *
+ * @param l An implemetation of the {@link com.phidgets.event.InputChangeListener InputChangeListener} interface
+ */
+ public final void addInputChangeListener (InputChangeListener l)
+ {
+ synchronized (inputChangeListeners)
+ {
+ inputChangeListeners.add (l);
+ enableInputChangeEvents (true);
+ }} private LinkedList inputChangeListeners = new LinkedList ();
+ private long nativeInputChangeHandler = 0;
+ public final void removeInputChangeListener (InputChangeListener l)
+ {
+ synchronized (inputChangeListeners)
+ {
+ inputChangeListeners.remove (l);
+ enableInputChangeEvents (inputChangeListeners.size () > 0);
+ }} private void fireInputChange (InputChangeEvent e)
+ {
+ synchronized (inputChangeListeners)
+ {
+ for (Iterator it = inputChangeListeners.iterator (); it.hasNext ();)
+ ((InputChangeListener) it.next ()).inputChanged (e);
+ }
+ }
+ private native void enableInputChangeEvents (boolean b);
+ /**
+ * Adds a position change listener. The position change handler is a method that will be called when the position of an
+ encoder changes. The position change event provides data about how many ticks have occured, and how much time has
+ passed since the last position change event, but does not contain an absolute position. This can be obtained from
+ {@link #getEncoderPosition}.
+ * <p>
+ * There is no limit on the number of encoder position change handlers that can be registered for a particular Phidget.
+ *
+ * @param l An implemetation of the {@link com.phidgets.event.EncoderPositionChangeListener EncoderPositionChangeListener} interface
+ */
+ public final void addEncoderPositionChangeListener (EncoderPositionChangeListener l)
+ {
+ synchronized (encoderPositionChangeListeners)
+ {
+ encoderPositionChangeListeners.add (l);
+ enableEncoderPositionChangeEvents (true);
+ }} private LinkedList encoderPositionChangeListeners = new LinkedList ();
+ private long nativeEncoderPositionChangeHandler = 0;
+ public final void removeEncoderPositionChangeListener (EncoderPositionChangeListener l)
+ {
+ synchronized (encoderPositionChangeListeners)
+ {
+ encoderPositionChangeListeners.remove (l);
+ enableEncoderPositionChangeEvents (encoderPositionChangeListeners.size () > 0);
+ }} private void fireEncoderPositionChange (EncoderPositionChangeEvent e)
+ {
+ synchronized (encoderPositionChangeListeners)
+ {
+ for (Iterator it = encoderPositionChangeListeners.iterator (); it.hasNext ();)
+ ((EncoderPositionChangeListener) it.next ()).encoderPositionChanged (e);
+ }
+ }
+ private native void enableEncoderPositionChangeEvents (boolean b);
+ /**
+ * Adds a position update listener. The position update handler is a method that will be called at a constant rate; every 8ms, whether the encoder position has changed or not.
+ * The position update event provides data about how many ticks have occured since the last position update event, but does not contain an absolute position. This can be obtained from
+ *{@link #getEncoderPosition}.
+ * <p>
+ * There is no limit on the number of encoder position update handlers that can be registered for a particular Phidget.
+ *
+ * @param l An implemetation of the {@link com.phidgets.event.EncoderPositionUpdateListener EncoderPositionUpdateListener} interface
+ */
+ public final void addEncoderPositionUpdateListener (EncoderPositionUpdateListener l)
+ {
+ synchronized (encoderPositionUpdateListeners)
+ {
+ encoderPositionUpdateListeners.add (l);
+ enableEncoderPositionUpdateEvents (true);
+ }} private LinkedList encoderPositionUpdateListeners = new LinkedList ();
+ private long nativeEncoderPositionUpdateHandler = 0;
+ public final void removeEncoderPositionUpdateListener (EncoderPositionUpdateListener l)
+ {
+ synchronized (encoderPositionUpdateListeners)
+ {
+ encoderPositionUpdateListeners.remove (l);
+ enableEncoderPositionUpdateEvents (encoderPositionUpdateListeners.size () > 0);
+ }} private void fireEncoderPositionUpdate (EncoderPositionUpdateEvent e)
+ {
+ synchronized (encoderPositionUpdateListeners)
+ {
+ for (Iterator it = encoderPositionUpdateListeners.iterator (); it.hasNext ();)
+ ((EncoderPositionUpdateListener) it.next ()).encoderPositionUpdated (e);
+ }
+ }
+ private native void enableEncoderPositionUpdateEvents (boolean b);
+ /**
+ * Adds a Back EMF update listener. The Back EMF update handler is a method that will be called at a constant rate; every 8ms, whether the Back EMF value has changed or not.
+ * <p>
+ * There is no limit on the number of Back EMF update handlers that can be registered for a particular Phidget.
+ *
+ * @param l An implemetation of the {@link com.phidgets.event.BackEMFUpdateListener BackEMFUpdateListener} interface
+ */
+ public final void addBackEMFUpdateListener (BackEMFUpdateListener l)
+ {
+ synchronized (backEMFUpdateListeners)
+ {
+ backEMFUpdateListeners.add (l);
+ enableBackEMFUpdateEvents (true);
+ }} private LinkedList backEMFUpdateListeners = new LinkedList ();
+ private long nativeBackEMFUpdateHandler = 0;
+ public final void removeBackEMFUpdateListener (BackEMFUpdateListener l)
+ {
+ synchronized (backEMFUpdateListeners)
+ {
+ backEMFUpdateListeners.remove (l);
+ enableBackEMFUpdateEvents (backEMFUpdateListeners.size () > 0);
+ }} private void fireBackEMFUpdate (BackEMFUpdateEvent e)
+ {
+ synchronized (backEMFUpdateListeners)
+ {
+ for (Iterator it = backEMFUpdateListeners.iterator (); it.hasNext ();)
+ ((BackEMFUpdateListener) it.next ()).backEMFUpdated (e);
+ }
+ }
+ private native void enableBackEMFUpdateEvents (boolean b);
+ /**
+ * Adds a sensor update listener. The sensor update handler is a method that will be called at a constant rate; every 8ms, whether the sensor value has changed or not.
+ * <p>
+ * There is no limit on the number of sensor update handlers that can be registered for a particular Phidget.
+ *
+ * @param l An implemetation of the {@link com.phidgets.event.SensorUpdateListener SensorUpdateListener} interface
+ */
+ public final void addSensorUpdateListener (SensorUpdateListener l)
+ {
+ synchronized (sensorUpdateListeners)
+ {
+ sensorUpdateListeners.add (l);
+ enableSensorUpdateEvents (true);
+ }} private LinkedList sensorUpdateListeners = new LinkedList ();
+ private long nativeSensorUpdateHandler = 0;
+ public final void removeSensorUpdateListener (SensorUpdateListener l)
+ {
+ synchronized (sensorUpdateListeners)
+ {
+ sensorUpdateListeners.remove (l);
+ enableSensorUpdateEvents (sensorUpdateListeners.size () > 0);
+ }} private void fireSensorUpdate (SensorUpdateEvent e)
+ {
+ synchronized (sensorUpdateListeners)
+ {
+ for (Iterator it = sensorUpdateListeners.iterator (); it.hasNext ();)
+ ((SensorUpdateListener) it.next ()).sensorUpdated (e);
+ }
+ }
+ private native void enableSensorUpdateEvents (boolean b);
+}
diff --git a/Java/com/phidgets/PHSensorPhidget.java b/Java/com/phidgets/PHSensorPhidget.java
new file mode 100644
index 0000000..dc9ecf6
--- /dev/null
+++ b/Java/com/phidgets/PHSensorPhidget.java
@@ -0,0 +1,136 @@
+
+/*
+ * Copyright 2006 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets;
+import java.util.Iterator;
+import java.util.LinkedList;
+import com.phidgets.event.*;
+/**
+ * This class represents a Phidget PH Sensor. All methods
+ * to read pH data from the PH Sensor are implemented in this class.
+ * <p>
+ * The Phidget PH Sensor provides one standard pH sensor input.
+ *
+ * @author Phidgets Inc.
+ */
+public final class PHSensorPhidget extends Phidget
+{
+ public PHSensorPhidget () throws PhidgetException
+ {
+ super (create ());
+ }
+ private static native long create () throws PhidgetException;
+ /**
+ * Returns the measured pH. This value can range from between {@link #getPHMin getPHMin} and {@link #getPHMax getPHMax}, but
+ * some of this range is likely outside of the valid range of most pH sensors. For example, when there is no pH sensor
+ * attached, the board will often report an (invalid) pH of 15, which while technically within a valid pH range, is unlikely to be seen.
+ * @return the current pH
+ * @throws PhidgetException If this Phidget is not opened and attached.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native double getPH () throws PhidgetException;
+ /**
+ * Returns the maximum pH that will be returned by the pH sensor input.
+ * @return Maximum pH
+ * @throws PhidgetException If this Phidget is not opened and attached.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native double getPHMax () throws PhidgetException;
+ /**
+ * Returns the minimum pH that will be returned by the pH sensor input.
+ * @return Minimum pH
+ * @throws PhidgetException If this Phidget is not opened and attached.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native double getPHMin () throws PhidgetException;
+ /**
+ * Returns the Potential, in millivolts. This returns the actual voltage potential measured by the A/D.
+ * This value will always be between {@link #getPotentialMin getPotentialMin} and {@link #getPotentialMax getPotentialMax}.
+ * This is the value that is internally used to calculate pH in the library.
+ * @return the current potential
+ * @throws PhidgetException If this Phidget is not opened and attached.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native double getPotential () throws PhidgetException;
+ /**
+ * Returns the maximum potential that will be returned by the pH sensor input.
+ * @return Maximum potential in millivolts
+ * @throws PhidgetException If this Phidget is not opened and attached.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native double getPotentialMax () throws PhidgetException;
+ /**
+ * Returns the minimum potential that will be returned by the pH sensor input.
+ * @return Minimum potential in millivolts
+ * @throws PhidgetException If this Phidget is not opened and attached.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native double getPotentialMin () throws PhidgetException;
+ /**
+ * Sets the probe temperature in degrees celcius.
+ * This value is used while calculating the pH. The default value in the libary is 20 degrees celcius. If the temperature
+ * of the liquid being measured is not 20 degrees, then it should be measued and set for maximum accuracy.
+ * <p>
+ * Note: All that this does is set a value in the library that is used for calculating ph. This does not set anything
+ * in the hardware itself.
+ *
+ * @param newVal temperature
+ * @throws PhidgetException If this Phidget is not opened and attached.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native void setTemperature (double newVal) throws PhidgetException;
+ /**
+ * Sets the change trigger.
+ * This is how much the pH much change between successive PHChangeEvents. By default this value is set to 0.05
+ * @param newVal Trigger
+ * @throws PhidgetException If this Phidget is not opened and attached.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native void setPHChangeTrigger (double newVal) throws PhidgetException;
+ /**
+ * Returns the change trigger.
+ * This is how much the pH much change between successive PHChangeEvents. By default this value is set to 0.05
+ * @return Trigger
+ * @throws PhidgetException If this Phidget is not opened and attached.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native double getPHChangeTrigger () throws PhidgetException;
+
+ private final void enableDeviceSpecificEvents (boolean b)
+ {
+ enablePHChangeEvents (b && phChangeListeners.size () > 0);
+ }
+ /**
+ * Adds a pH change listener. The pH change handler is a method that will be called when the pH
+ * has changed by at least the {@link #getPHChangeTrigger() Trigger} that has been set.
+ * <p>
+ * There is no limit on the number of pH change handlers that can be registered for a particular Phidget.
+ *
+ * @param l An implemetation of the {@link com.phidgets.event.PHChangeListener PHChangeListener} interface
+ */
+ public final void addPHChangeListener (PHChangeListener l)
+ {
+ synchronized (phChangeListeners)
+ {
+ phChangeListeners.add (l);
+ enablePHChangeEvents (true);
+ }} private LinkedList phChangeListeners = new LinkedList ();
+ private long nativePHChangeHandler = 0;
+ public final void removePHChangeListener (PHChangeListener l)
+ {
+ synchronized (phChangeListeners)
+ {
+ phChangeListeners.remove (l);
+ enablePHChangeEvents (phChangeListeners.size () > 0);
+ }} private void firePHChange (PHChangeEvent e)
+ {
+ synchronized (phChangeListeners)
+ {
+ for (Iterator it = phChangeListeners.iterator (); it.hasNext ();)
+ ((PHChangeListener) it.next ()).phChanged (e);
+ }
+ }
+ private native void enablePHChangeEvents (boolean b);
+}
diff --git a/Java/com/phidgets/Phidget.java b/Java/com/phidgets/Phidget.java
new file mode 100644
index 0000000..e2d611c
--- /dev/null
+++ b/Java/com/phidgets/Phidget.java
@@ -0,0 +1,1000 @@
+/*
+ * Copyright 2006 Phidgets Inc. All rights reserved.
+ */
+package com.phidgets;
+
+import com.phidgets.event.*;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+
+/**
+ * This is the base class from which all Phidget device classes derive.
+ * Don't create phidget devices directly using this class. Use the specific class for the
+ * device that you wish to access.
+ *
+ * @author Phidgets Inc.
+ * @version 2.1.7
+ */
+public class Phidget
+{
+ static
+ {
+ try
+ {
+
+ System.loadLibrary("phidget21");
+
+ }
+ catch(UnsatisfiedLinkError ex)
+ {
+ String os = System.getProperty("os.name");
+ if(os.startsWith("Linux"))
+ {
+ throw new ExceptionInInitializerError(ex.getMessage()
+ +"\nCould not locate the Phidget C library (libphidget21.so)."
+ +"\nMake sure it is installed, and add it's path to LD_LIBRARY_PATH.");
+ }
+ else if(os.startsWith("Windows"))
+ {
+ throw new ExceptionInInitializerError(ex.getMessage()
+ +"\nCould not locate the Phidget C library."
+ +"\nThe Windows Phidget21 MSI must be installed.");
+ }
+ else if(os.startsWith("Mac"))
+ {
+ throw new ExceptionInInitializerError(ex.getMessage()
+ +"\nCould not locate the Phidget C library."
+ +"\nThe Mac Phidget21 DMG must be installed.");
+ }
+ else
+ {
+ throw new ExceptionInInitializerError(ex.getMessage()
+ +"\nCould not locate the Phidget C library.");
+ }
+ }
+
+
+
+ }
+
+ private long handle = 0;
+ boolean managerPhidget = false;
+
+ /**
+ * Class constructor specifying a handle. This constructor is to be used only by subclasses, as the Phidget calss should never need to
+ * be instatiated directly by the user.
+ *
+ * @param handle A native Handle points to the underlying phidget structure in the base phidget21 C library.
+ */
+ public Phidget(long handle) {
+ this.handle = handle;
+ }
+
+ private final long getHandle() {
+ return handle;
+ }
+
+ /**
+ * Returns the library version. This is the library version of the underlying phidget21 C library and not the version of the
+ * JNI wrapper implementation.
+ * <p>
+ * The version is retured at a string which contains the version number and build date.
+ *
+ * @return Library Version
+ */
+ public final static native String getLibraryVersion();
+
+ /**
+ * Critial error messages. This is used with {@link #enableLogging enableLogging} and {@link #log log}
+ * <p>
+ * This is the lowest logging level. Errors at this level are generally non-recoverable and indicate either hardware problems,
+ * library bugs, or other serious issues.
+ * <P>
+ * If logging is enabled at this level, only {@link #PHIDGET_LOG_CRITICAL PHIDGET_LOG_CRITICAL} messages are logged.
+ */
+ public static final int PHIDGET_LOG_CRITICAL = 1;
+ /**
+ * Non-critical error messages. This is used with {@link #enableLogging enableLogging} and {@link #log log}
+ * <P>
+ * Errors at this level are generally automatically recoverable, but may help to track down issues.
+ * <p>
+ * If logging is enabled at this level, {@link #PHIDGET_LOG_ERROR PHIDGET_LOG_ERROR} as well as
+ * {@link #PHIDGET_LOG_CRITICAL PHIDGET_LOG_CRITICAL} messages are logged.
+ */
+ public static final int PHIDGET_LOG_ERROR = 2;
+ /**
+ * Warning messages. This is used with {@link #enableLogging enableLogging} and {@link #log log}
+ * <P>
+ * Warnings are used to log behaviour that is not neccessarily in error, but is nevertheless odd or unexpected.
+ * <p>
+ * If logging is enabled at this level, {@link #PHIDGET_LOG_WARNING PHIDGET_LOG_WARNING} as well as
+ * {@link #PHIDGET_LOG_ERROR PHIDGET_LOG_ERROR} and {@link #PHIDGET_LOG_CRITICAL PHIDGET_LOG_CRITICAL} messages are logged.
+ */
+ public static final int PHIDGET_LOG_WARNING = 3;
+ /**
+ * Debug messages. This is used with {@link #enableLogging enableLogging} and {@link #log log}
+ * <P>
+ * Debug messages are generally used for debugging at Phdigets Inc.
+ * <p>
+ * Note: {@link #PHIDGET_LOG_DEBUG PHIDGET_LOG_DEBUG} messages are only logged in the debug version of the library, regardless of logging level.
+ * Thus, these logs should never be seen outside of Phidgets Inc.
+ * <p>
+ * If logging is enabled at this level, {@link #PHIDGET_LOG_DEBUG PHIDGET_LOG_DEBUG} as well as
+ * {@link #PHIDGET_LOG_WARNING PHIDGET_LOG_WARNING}, {@link #PHIDGET_LOG_ERROR PHIDGET_LOG_ERROR}
+ * and {@link #PHIDGET_LOG_CRITICAL PHIDGET_LOG_CRITICAL} messages are logged.
+ */
+ public static final int PHIDGET_LOG_DEBUG = 4;
+ /**
+ * Informational messages. This is used with {@link #enableLogging enableLogging} and {@link #log log}
+ * <P>
+ * Informational messages track key happenings within phidget21 - mostly to do with threads starting and shutting down, and the
+ * internals of the USB code.
+ * <p>
+ * If logging is enabled at this level, {@link #PHIDGET_LOG_INFO PHIDGET_LOG_INFO} as well as
+ * {@link #PHIDGET_LOG_DEBUG PHIDGET_LOG_DEBUG}, {@link #PHIDGET_LOG_WARNING PHIDGET_LOG_WARNING}, {@link #PHIDGET_LOG_ERROR PHIDGET_LOG_ERROR}
+ * and {@link #PHIDGET_LOG_CRITICAL PHIDGET_LOG_CRITICAL} messages are logged.
+ */
+ public static final int PHIDGET_LOG_INFO = 5;
+ /**
+ * Verbose messages. This is used with {@link #enableLogging enableLogging} and {@link #log log}
+ * <P>
+ * This is the highest logging level. Verbose messages are informational messages that are expected to happen so
+ * frequently that they tend to drown out other log messages.
+ * <p>
+ * If logging is enabled at this level, {@link #PHIDGET_LOG_VERBOSE PHIDGET_LOG_VERBOSE} as well as
+ * {@link #PHIDGET_LOG_INFO PHIDGET_LOG_INFO}, {@link #PHIDGET_LOG_DEBUG PHIDGET_LOG_DEBUG},
+ * {@link #PHIDGET_LOG_WARNING PHIDGET_LOG_WARNING}, {@link #PHIDGET_LOG_ERROR PHIDGET_LOG_ERROR}
+ * and {@link #PHIDGET_LOG_CRITICAL PHIDGET_LOG_CRITICAL} messages are logged.
+ */
+ public static final int PHIDGET_LOG_VERBOSE = 6;
+
+ private final static native void nativeEnableLogging(int level, String file);
+
+ /**
+ * Turns on logging in the native C Library. This is mostly usefull for debugging purposes - when an issue needs to be resolved by
+ * Phidgets Inc. The output is mostly low-level library information, that won't be usefull for most users.
+ * <p>
+ * Logging may be usefull for users trying to debug their own problems, as logs can be inserted by the user using {@link #log log}.
+ * <p>
+ * The level can be one of: {@link #PHIDGET_LOG_VERBOSE PHIDGET_LOG_VERBOSE},
+ * {@link #PHIDGET_LOG_INFO PHIDGET_LOG_INFO}, {@link #PHIDGET_LOG_DEBUG PHIDGET_LOG_DEBUG},
+ * {@link #PHIDGET_LOG_WARNING PHIDGET_LOG_WARNING}, {@link #PHIDGET_LOG_ERROR PHIDGET_LOG_ERROR}
+ * or {@link #PHIDGET_LOG_CRITICAL PHIDGET_LOG_CRITICAL}
+ *
+ * @param level highest level of logging that will be output
+ * @param file file to output log to. specify 'null' to output to the console
+ */
+ public final static void enableLogging(int level, String file)
+ {
+ nativeEnableLogging(level, file);
+ }
+
+ /**
+ * Turns off logging in the native C Library. This only needs to be called if enableLogging was called to turn logging on.
+ * This will turn logging back off.
+ */
+ public final static native void disableLogging();
+
+ private final static native void nativeLog(int level, String id, String log);
+
+ /**
+ * Adds a log entry into the phidget log. This log is enabled by calling {@link #enableLogging(int level, String file) enableLogging}
+ * and this allows the entry of user logs in amongst the phidget library logs.
+ * <p>
+ * The level can be one of: {@link #PHIDGET_LOG_VERBOSE PHIDGET_LOG_VERBOSE},
+ * {@link #PHIDGET_LOG_INFO PHIDGET_LOG_INFO}, {@link #PHIDGET_LOG_DEBUG PHIDGET_LOG_DEBUG},
+ * {@link #PHIDGET_LOG_WARNING PHIDGET_LOG_WARNING}, {@link #PHIDGET_LOG_ERROR PHIDGET_LOG_ERROR}
+ * or {@link #PHIDGET_LOG_CRITICAL PHIDGET_LOG_CRITICAL}
+ * <p>
+ * Note: {@link #PHIDGET_LOG_DEBUG PHIDGET_LOG_DEBUG} should not be used, as these logs are only printed when using the debug library,
+ * which is not generally available.
+ *
+ * @param level level to enter the log at
+ * @param id an arbitrary identifier for this log. This can be NULL. The C library uses this field for source filename and line number
+ * @param log the message to log
+ */
+ public final static void log(int level, String id, String log)
+ {
+ nativeLog(level, id, log);
+ }
+
+ public static final int PHIDID_NOTHING = 1;
+
+ /* These are all current devices */
+ public static final int PHIDID_ACCELEROMETER_3AXIS = 0x07E;
+ public static final int PHIDID_ADVANCEDSERVO_1MOTOR = 0x082;
+ public static final int PHIDID_ANALOG_4OUTPUT = 0x037;
+ public static final int PHIDID_ADVANCEDSERVO_8MOTOR = 0x03A;
+ public static final int PHIDID_BIPOLAR_STEPPER_1MOTOR = 0x07B;
+ public static final int PHIDID_BRIDGE_4INPUT = 0x03B;
+ public static final int PHIDID_ENCODER_1ENCODER_1INPUT = 0x04B;
+ public static final int PHIDID_ENCODER_HS_1ENCODER = 0x080;
+ public static final int PHIDID_ENCODER_HS_4ENCODER_4INPUT = 0x04F;
+ public static final int PHIDID_FREQUENCYCOUNTER_2INPUT = 0x035;
+ public static final int PHIDID_GPS = 0x079;
+ public static final int PHIDID_INTERFACEKIT_0_0_4 = 0x040;
+ public static final int PHIDID_INTERFACEKIT_0_0_8 = 0x081;
+ public static final int PHIDID_INTERFACEKIT_0_16_16 = 0x044;
+ public static final int PHIDID_INTERFACEKIT_8_8_8 = 0x045;
+ public static final int PHIDID_INTERFACEKIT_8_8_8_w_LCD = 0x07D;
+ public static final int PHIDID_IR = 0x04D;
+ public static final int PHIDID_LED_64 = 0x04A;
+ public static final int PHIDID_LED_64_ADV = 0x04C;
+ public static final int PHIDID_LINEAR_TOUCH = 0x076;
+ public static final int PHIDID_MOTORCONTROL_HC_2MOTOR = 0x059;
+ public static final int PHIDID_MOTORCONTROL_LV_2MOTOR_4INPUT = 0x058;
+ public static final int PHIDID_MOTORCONTROL_1MOTOR = 0x03E;
+ public static final int PHIDID_PHSENSOR = 0x074;
+ public static final int PHIDID_RFID_2OUTPUT = 0x031;
+ public static final int PHIDID_ROTARY_TOUCH = 0x077;
+ public static final int PHIDID_SERVO_1MOTOR = 0x039;
+ public static final int PHIDID_SPATIAL_ACCEL_3AXIS = 0x07F;
+ public static final int PHIDID_SPATIAL_ACCEL_GYRO_COMPASS = 0x033;
+ public static final int PHIDID_TEMPERATURESENSOR = 0x070;
+ public static final int PHIDID_TEMPERATURESENSOR_4 = 0x032;
+ public static final int PHIDID_TEXTLCD_2x20_w_8_8_8 = 0x17D;
+ public static final int PHIDID_TEXTLCD_ADAPTER = 0x03D;
+ public static final int PHIDID_UNIPOLAR_STEPPER_4MOTOR = 0x07A;
+
+ /* These are all past devices (no longer sold) */
+ public static final int PHIDID_ACCELEROMETER_2AXIS = 0x071;
+ public static final int PHIDID_INTERFACEKIT_0_8_8_w_LCD = 0x053;
+ public static final int PHIDID_INTERFACEKIT_4_8_8 = 4;
+ public static final int PHIDID_RFID = 0x030;
+ public static final int PHIDID_SERVO_1MOTOR_OLD = 2;
+ public static final int PHIDID_SERVO_4MOTOR = 0x038;
+ public static final int PHIDID_SERVO_4MOTOR_OLD = 3;
+ public static final int PHIDID_TEXTLCD_2x20 = 0x052;
+ public static final int PHIDID_TEXTLCD_2x20_w_0_8_8 = 0x153;
+ public static final int PHIDID_TEXTLED_1x8 = 0x049;
+ public static final int PHIDID_TEXTLED_4x8 = 0x048;
+ public static final int PHIDID_WEIGHTSENSOR = 0x072;
+
+
+ /**
+ * Returns the Device ID of this Phidget. This is one of the PHIDID_(...) constants defined above. This uniquely identifies a specific type of Phidget.
+ *
+ * @return Device ID
+ * @throws PhidgetException If this Phidget is not opened and attached. See {@link #open(int) open} for information on determining if a device is attached.
+ */
+ public final native int getDeviceID() throws PhidgetException;
+
+ public static final int PHIDCLASS_NOTHING = 1;
+ public static final int PHIDCLASS_ACCELEROMETER = 2;
+ public static final int PHIDCLASS_ADVANCEDSERVO = 3;
+ public static final int PHIDCLASS_ANALOG = 22;
+ public static final int PHIDCLASS_BRIDGE = 23;
+ public static final int PHIDCLASS_ENCODER = 4;
+ public static final int PHIDCLASS_FREQUENCYCOUNTER = 21;
+ public static final int PHIDCLASS_GPS = 5;
+ public static final int PHIDCLASS_INTERFACEKIT = 7;
+ public static final int PHIDCLASS_LED = 8;
+ public static final int PHIDCLASS_MOTORCONTROL = 9;
+ public static final int PHIDCLASS_PHSENSOR = 10;
+ public static final int PHIDCLASS_RFID = 11;
+ public static final int PHIDCLASS_SERVO = 12;
+ public static final int PHIDCLASS_STEPPER = 13;
+ public static final int PHIDCLASS_TEMPERATURESENSOR = 14;
+ public static final int PHIDCLASS_TEXTLCD = 15;
+ public static final int PHIDCLASS_TEXTLED = 16;
+ public static final int PHIDCLASS_WEIGHTSENSOR = 17;
+
+ /**
+ * Returns the Device Class of this Phidget. This is one of the PHIDCLASS_(...) constants defined above. This represents a class of Phidgets - ie Interface Kit.
+ *
+ * @return Device ID
+ * @throws PhidgetException If this Phidget is not opened and attached. See {@link #open(int) open} for information on determining if a device is attached.
+ */
+ public final native int getDeviceClass() throws PhidgetException;
+
+ /**
+ * Returns the unique serial number of this Phidget. This number is set during manufacturing, and is unique across all Phidgets.
+ * This number can be used in calls to {@link #open(int) open} to specify this specific Phidget to be opened.
+ *
+ * @return Serial Number
+ * @throws PhidgetException If this Phidget is not opened and attached. See {@link #open(int) open} for information on determining if a device is attached.
+ */
+ public final native int getSerialNumber() throws PhidgetException;
+
+ /**
+ * Returns the device version of this Phidget. This number is simply a way of distinguishing between different revisions
+ * of a specific type of Phidget, and is only really of use if you need to troubleshoot device problems with Phidgets Inc.
+ *
+ * @return Version
+ * @throws PhidgetException If this Phidget is not opened and attached. See {@link #open(int) open} for information on determining if a device is attached.
+ */
+ public final native int getDeviceVersion() throws PhidgetException;
+
+ /**
+ * Return the device type of this Phidget. This is a string that describes the device as a class of devices. For example,
+ * all PhidgetInterfaceKit Phidgets will returns the String "PhidgetInterfaceKit".
+ * <p>
+ * This function is mostly usefull if you are using the {@link com.phidgets.Manager Phidget Manager} because it's attach and detach handlers
+ * return {link com.phidgets.phidget phidget} objects, and you can use this method to determine their proper type.
+ *
+ * @return Device Type
+ * @throws PhidgetException If this Phidget is not opened and attached. See {@link #open(int) open} for information on determining if a device is attached.
+ */
+ public final native String getDeviceType() throws PhidgetException;
+
+ /**
+ * Return the name of this Phidget. This is a string that describes the device. For example, a PhidgetInterfaceKit could be described
+ * as "Phidget InterfaceKit 8/8/8", or "Phidget InterfaceKit 0/0/4", among others, depending on the specific device.
+ * <p>
+ * This lets you determine the specific type of a Phidget, within the broader classes of Phidgets, such as PhidgetInterfaceKit, or PhidgetServo
+ *
+ * @return Name
+ * @throws PhidgetException If this Phidget is not opened and attached. See {@link #open(int) open} for information on determining if a device is attached.
+ */
+ public final native String getDeviceName() throws PhidgetException;
+
+ /**
+ * Returns the attached status of this Phidget. This method returns True or False, depending on whether the Phidget is phisically plugged
+ * into the computer, initialized, and ready to use - or not. If a Phidget is not attached, many functions calls will fail with a PhidgetException,
+ * so either checking this function, or using the Attach and Detach events, is recommended, if a device is likely to be attached or
+ * detached during use.
+ *
+ * @return Status
+ * @throws PhidgetException If this Phidget is not opened.
+ */
+ public final native boolean isAttached() throws PhidgetException;
+
+ /**
+ * Returns the network attached status for remotely opened Phidgets. This method returns True or False, depending on whether a connection to the
+ * Phidget WebService is open - or not. If this is false for a remote Phidget then the connection is not active - either because a connection
+ * has not yet been established, or because the connection was terminated.
+ *
+ * @return Status
+ * @throws PhidgetException If this Phidget is not opened.
+ */
+ public final native boolean isAttachedToServer() throws PhidgetException;
+
+ /**
+ * Returns the label associated with this Phidget. This label is a String - up to ten digits - that is stored in the Flash memory
+ * of newer Phidgets. This label can be set programatically (see {@link #setDeviceLabel(String) setDeviceLabel}), and is non-volatile - so it is remembered
+ * even if the Phidget is unplugged.
+ *
+ * @return Label
+ * @throws PhidgetException If this Phidget is not opened and attached, or if this Phidget does not support labels.
+ * See {@link #open(int) open} for determining if a device is attached.
+ */
+ public final native String getDeviceLabel() throws PhidgetException;
+
+ /**
+ * Sets the Label associated with this Phidget. Labels are user defined Strings that persist in a Phidget's Flash.
+ * They are only supported in the newer Phidgets. The maximum length is 10 characters.
+ * <p>
+ * Labels can not currently be set from Windows because of driver incompatibility. Labels can be set from MacOS, Linux and Windows CE.
+ *
+ * @param label Label
+ * @throws PhidgetException If this Phidget is not opened and attached, or if this Phidget does not support labels, or if this is
+ * called from Windows. See {@link #open(int) open} for determining if a device is attached.
+ */
+ public final native void setDeviceLabel(String label) throws PhidgetException;
+
+ /**
+ * Returns the Address of a Phidget Webservice when this Phidget was opened as remote. This may be an IP Address or a hostname.
+ *
+ * @return Server Address
+ * @throws PhidgetException if this Phidget was open opened as a remote Phidget.
+ */
+ public final native String getServerAddress() throws PhidgetException;
+ /**
+ * Returns the Server ID of a Phidget Webservice when this Phidget was opened as remote. This is an arbitrary server identifier,
+ * independant of IP address and Port.
+ *
+ * @return Server ID
+ * @throws PhidgetException if this Phidget was open opened as a remote Phidget.
+ */
+ public final native String getServerID() throws PhidgetException;
+ /**
+ * Returns the Port of a Phidget Webservice when this Phidget was opened as remote.
+ *
+ * @return Server Port
+ * @throws PhidgetException if this Phidget was open opened as a remote Phidget.
+ */
+ public final native int getServerPort() throws PhidgetException;
+
+ private final native void nativeClose() throws PhidgetException;
+ private final native void nativeDelete() throws PhidgetException;
+ private final native void nativeOpen(int serial) throws PhidgetException;
+ private final native void nativeOpenRemote(int serial, String serverID, String pass) throws PhidgetException;
+ private final native void nativeOpenRemoteIP(int serial, String ipAddress, int port, String pass) throws PhidgetException;
+ private final native void nativeOpenLabel(String label) throws PhidgetException;
+ private final native void nativeOpenLabelRemote(String label, String serverID, String pass) throws PhidgetException;
+ private final native void nativeOpenLabelRemoteIP(String label, String ipAddress, int port, String pass) throws PhidgetException;
+
+ /**
+ * Open this Phidget with a specific serial number.
+ * <p>
+ * Open is pervasive. What this means is that you can call open on a device before it is plugged in,
+ * and keep the device opened across device dis- and re-connections.
+ * <p>
+ * Open is Asynchronous. What this means is that open will return immediately --
+ * before the device being opened is actually available, so you need to use either the {@link #addAttachListener(AttachListener l) attach event}
+ * or the {@link #waitForAttachment() waitForAttachment} method to determine if a device
+ * is available before using it.
+ * <p>
+ * This version of open specifies a serial number - The serial number is a unique number assigned to each Phidget
+ * during production and can be used to uniquely identify specific phidgets.
+ * use {@link #openAny() openAny} to open a device without specifying the serial number.
+ *
+ * @param serial Serial Number
+ */
+ public final void open(int serial) throws PhidgetException {
+ enableEvents(true);
+ nativeOpen(serial);
+ }
+
+ /**
+ * Open this Phidget remotely using an IP Address, and a specific serial number.
+ * <p>
+ * This version of open is network based.
+ * <p>
+ * Open is pervasive. What this means is that you can call open on a device before it is plugged in,
+ * and on a server before it is running, and keep the device opened across device, and server dis- and re-connections.
+ * <p>
+ * Open is Asynchronous. What this means is that open will return immediately --
+ * before the device being opened is actually available, so you need to use either the {@link #addAttachListener(AttachListener l) attach event}
+ * or the {@link #waitForAttachment() waitForAttachment} method to determine if a device
+ * is available before using it.
+ * <p>
+ * This version of open specifies a serial number - The serial number is a unique number assigned to each Phidget
+ * during production and can be used to uniquely identify specific phidgets.
+ * use {@link #openAny(String ipAddress, int port) openAny(String ipAddress, int port)} to open a device without specifying the serial number.
+ *
+ * @param serial Serial Number
+ * @param ipAddress IP Address or hostname of the Phidget Webservice
+ * @param port Port of the Phidget Webservice
+ * @throws PhidgetException if the Phidget Webservice cannot be contacted
+ */
+ public final void open(int serial, String ipAddress, int port) throws PhidgetException
+ {
+ open(serial, ipAddress, port, "");
+ }
+ /**
+ * Open this Phidget remotely and securely, using an IP Address, and a specific serial number.
+ * <p>
+ * This method is the same as {@link #open(int, String, int) open(int serial, String ipAddress, int port)}, except that it specifies a password.
+ * This password can be set as a parameter when starting the Phidget Webservice.
+ */
+ public final void open(int serial, String ipAddress, int port, String password) throws PhidgetException
+ {
+ enableEvents(true);
+ nativeOpenRemoteIP(serial, ipAddress, port, password);
+ }
+
+ /**
+ * Open this Phidget remotely using a Server ID, and a specific serial number.
+ * <p>
+ * This version of open is network based.
+ * <p>
+ * Open is pervasive. What this means is that you can call open on a device before it is plugged in,
+ * and on a server before it is running, and keep the device opened across device, and server dis- and re-connections.
+ * <p>
+ * Open is Asynchronous. What this means is that open will return immediately --
+ * before the device being opened is actually available, so you need to use either the {@link #addAttachListener(AttachListener l) attach event}
+ * or the {@link #waitForAttachment() waitForAttachment} method to determine if a device
+ * is available before using it.
+ * <p>
+ * This version of open specifies a serial number - The serial number is a unique number assigned to each Phidget
+ * during production and can be used to uniquely identify specific phidgets.
+ * use {@link #openAny(String) openAny(String serverID)} to open a device without specifying the serial number.
+ * <p>
+ * ServerID can be set to null, if the ServerID does not matter. In this case, the specified Phidget (by serial number) will be opened
+ * whenever it is seen on the network, regardless of which server it appears on. This also applies when not specifying a serial number.
+ * <p>
+ * Note: All open methods that specify a ServerID rather then an IP Addresss and Port require that both the client and host sides of the
+ * connection be running an implementation of zeroconf:
+ * <ul><li>On Windows, this means installing Apple's Bonjour - available <a href="http://www.apple.com/support/downloads/bonjourforwindows.html">here</a>.</li>
+ * <li>On Linux, this means Avahi, which is usually either installed by default or available as a package install.</li>
+ * <li>On MacOSX, Bonjour is already integrated into the operationg system.</li></ul>
+ *
+ * @param serial Serial Number
+ * @param serverID ServerID of the Phidget Webservice
+ */
+ public final void open(int serial, String serverID) throws PhidgetException
+ {
+ open(serial, serverID, "");
+ }
+
+ /**
+ * Open this Phidget remotely and securely, using a Server ID, and a specific serial number.
+ * <p>
+ * This method is the same as {@link #open(int, String) open(int serial, String serverID)}, except that it specifies a password.
+ * This password can be set as a parameter when starting the Phidget Webservice.
+ */
+ public final void open(int serial, String serverID, String password) throws PhidgetException
+ {
+ enableEvents(true);
+ nativeOpenRemote(serial, serverID, password);
+ }
+
+ /**
+ * Open a this Phidget without a serial number. This method is the same as {@link #open(int) open}, except that it specifies no serial number. Therefore, the first available
+ * Phidget will be opened. If there are two Phidgets of the same type attached to the system, you should specify a serial number, as
+ * there is no guarantee which Phidget will be selected by the call to openAny().
+ */
+ public final void openAny() throws PhidgetException {
+ open(-1);
+ }
+
+ /**
+ * Open this Phidget remotely using an IP Address, without a serial number.
+ * This method is the same as {@link #open(int, String, int) open(int serial, String ipAddress, int port)},
+ * except that it specifies no serial number. Therefore, the first available
+ * Phidget will be opened. If there are two Phidgets of the same type attached to the system, you should specify a serial number, as
+ * there is no guarantee which Phidget will be selected by the call to openAny().
+ */
+ public final void openAny(String ipAddress, int port) throws PhidgetException
+ {
+ open(-1, ipAddress, port, "");
+ }
+
+
+ /**
+ * Open this Phidget remotely and securely, using an IP Address, without a serial number.
+ * This method is the same as {@link #open(int, String, int, String) open(int serial, String ipAddress, int port, String password)},
+ * except that it specifies no serial number. Therefore, the first available
+ * Phidget will be opened. If there are two Phidgets of the same type attached to the system, you should specify a serial number, as
+ * there is no guarantee which Phidget will be selected by the call to openAny().
+ */
+ public final void openAny(String ipAddress, int port, String password) throws PhidgetException
+ {
+ open(-1, ipAddress, port, password);
+ }
+
+
+ /**
+ * Open this Phidget remotely using a Server ID, without a serial number.
+ * This method is the same as {@link #open(int, String) open(int serial, String serverID)},
+ * except that it specifies no serial number. Therefore, the first available
+ * Phidget will be opened. If there are two Phidgets of the same type attached to the system, you should specify a serial number, as
+ * there is no guarantee which Phidget will be selected by the call to openAny().
+ */
+ public final void openAny(String serverID) throws PhidgetException
+ {
+ open(-1, serverID, "");
+ }
+
+ /**
+ * Open this Phidget remotely and securely, using a Server ID, without a serial number.
+ * This method is the same as {@link #open(int, String, String) open(int serial, String serverID, String password)},
+ * except that it specifies no serial number. Therefore, the first available
+ * Phidget will be opened. If there are two Phidgets of the same type attached to the system, you should specify a serial number, as
+ * there is no guarantee which Phidget will be selected by the call to openAny().
+ */
+ public final void openAny(String serverID, String password) throws PhidgetException
+ {
+ open(-1, serverID, password);
+ }
+
+ /**
+ * Open this Phidget with a specific label.
+ * <p>
+ * Open is pervasive. What this means is that you can call open on a device before it is plugged in,
+ * and keep the device opened across device dis- and re-connections.
+ * <p>
+ * Open is Asynchronous. What this means is that open will return immediately --
+ * before the device being opened is actually available, so you need to use either the {@link #addAttachListener(AttachListener l) attach event}
+ * or the {@link #waitForAttachment() waitForAttachment} method to determine if a device
+ * is available before using it.
+ * <p>
+ * This version of open specifies a label - The label can be set and changed by using the setLabel method (setLabel is unsupported on Windows).
+ * use {@link #openAny() openAny} to open a device without specifying the label.
+ *
+ * @param label The Label
+ */
+ public final void openLabel(String label) throws PhidgetException {
+ enableEvents(true);
+ nativeOpenLabel(label);
+ }
+
+ /**
+ * Open this Phidget remotely using an IP Address, and a specific label.
+ * <p>
+ * This version of open is network based.
+ * <p>
+ * Open is pervasive. What this means is that you can call open on a device before it is plugged in,
+ * and on a server before it is running, and keep the device opened across device, and server dis- and re-connections.
+ * <p>
+ * Open is Asynchronous. What this means is that open will return immediately --
+ * before the device being opened is actually available, so you need to use either the {@link #addAttachListener(AttachListener l) attach event}
+ * or the {@link #waitForAttachment() waitForAttachment} method to determine if a device
+ * is available before using it.
+ * <p>
+ * This version of open specifies a label - The label can be set and changed by using the setLabel method (setLabel is unsupported on Windows).
+ * use {@link #openAny(String ipAddress, int port) openAny(String ipAddress, int port)} to open a device without specifying the label.
+ *
+ * @param label The Label
+ * @param ipAddress IP Address or hostname of the Phidget Webservice
+ * @param port Port of the Phidget Webservice
+ * @throws PhidgetException if the Phidget Webservice cannot be contacted
+ */
+ public final void openLabel(String label, String ipAddress, int port) throws PhidgetException
+ {
+ openLabel(label, ipAddress, port, "");
+ }
+ /**
+ * Open this Phidget remotely and securely, using an IP Address, and a specific label.
+ * <p>
+ * This method is the same as {@link #openLabel(String, String, int) openLabel(String label, String ipAddress, int port)}, except that it specifies a password.
+ * This password can be set as a parameter when starting the Phidget Webservice.
+ */
+ public final void openLabel(String label, String ipAddress, int port, String password) throws PhidgetException
+ {
+ enableEvents(true);
+ nativeOpenLabelRemoteIP(label, ipAddress, port, password);
+ }
+
+ /**
+ * Open this Phidget remotely using a Server ID, and a specific label.
+ * <p>
+ * This version of open is network based.
+ * <p>
+ * Open is pervasive. What this means is that you can call open on a device before it is plugged in,
+ * and on a server before it is running, and keep the device opened across device, and server dis- and re-connections.
+ * <p>
+ * Open is Asynchronous. What this means is that open will return immediately --
+ * before the device being opened is actually available, so you need to use either the {@link #addAttachListener(AttachListener l) attach event}
+ * or the {@link #waitForAttachment() waitForAttachment} method to determine if a device
+ * is available before using it.
+ * <p>
+ * This version of open specifies a label - The label can be set and changed by using the setLabel method (setLabel is unsupported on Windows).
+ * use {@link #openAny(String) openAny(String serverID)} to open a device without specifying the label.
+ * <p>
+ * ServerID can be set to null, if the ServerID does not matter. In this case, the specified Phidget (by label) will be opened
+ * whenever it is seen on the network, regardless of which server it appears on. This also applies when not specifying a label.
+ * <p>
+ * Note: All open methods that specify a ServerID rather then an IP Addresss and Port require that both the client and host sides of the
+ * connection be running an implementation of zeroconf:
+ * <ul><li>On Windows, this means installing Apple's Bonjour - available <a href="http://www.apple.com/support/downloads/bonjourforwindows.html">here</a>.</li>
+ * <li>On Linux, this means Avahi, which is usually either installed by default or available as a package install.</li>
+ * <li>On MacOSX, Bonjour is already integrated into the operationg system.</li></ul>
+ *
+ * @param label The Label
+ * @param serverID ServerID of the Phidget Webservice
+ */
+ public final void openLabel(String label, String serverID) throws PhidgetException
+ {
+ openLabel(label, serverID, "");
+ }
+
+ /**
+ * Open this Phidget remotely and securely, using a Server ID, and a specific label.
+ * <p>
+ * This method is the same as {@link #openLabel(String, String) openLabel(String label, String serverID)}, except that it specifies a password.
+ * This password can be set as a parameter when starting the Phidget Webservice.
+ */
+ public final void openLabel(String label, String serverID, String password) throws PhidgetException
+ {
+ enableEvents(true);
+ nativeOpenLabelRemote(label, serverID, password);
+ }
+
+ /**
+ * Closes this Phidget.
+ * This will shut down all threads dealing with this Phidget and you won't recieve any more events.
+ *
+ * @throws PhidgetException If this Phidget is not opened.
+ */
+ public final void close() throws PhidgetException {
+ if(!managerPhidget)
+ {
+ enableEvents(false);
+ nativeClose();
+ }
+ }
+
+ private void enableEvents(boolean b) {
+ enableAttachEvents(b && attachListeners.size() > 0);
+ enableDetachEvents(b && detachListeners.size() > 0);
+ enableErrorEvents(b && errorListeners.size() > 0);
+ enableServerConnectEvents(b && serverConnectListeners.size() > 0);
+ enableServerDisconnectEvents(b && serverDisconnectListeners.size() > 0);
+ enableDeviceSpecificEvents(b);
+ }
+
+ /**
+ * Waits for this Phidget to become available. This method can be called after open has been called
+ * to wait for thid Phidget to become available. This is usefull because open is asynchronous (and thus returns immediately),
+ * and most methods will throw a PhidgetException is they are called before a device is actually ready. This method is
+ * synonymous with polling the isAttached method until it returns True, or using the Attach event.
+ * <p>
+ * This method blocks for up to the timeout, at which point it will throw a PhidgetException. Otherwise, it returns when
+ * the phidget is attached and initialized.
+ * <p>
+ * A timeout of 0 is infinite.
+ *
+ * @param timeout Timeout in milliseconds
+ * @throws PhidgetException If this Phidget is not opened.
+ */
+ public final native void waitForAttachment(int timeout) throws PhidgetException;
+ /**
+ * Waits for this Phidget to become available. This method can be called after open has been called
+ * to wait for thid Phidget to become available. This is usefull because open is asynchronous (and thus returns immediately),
+ * and most methods will throw a PhidgetException is they are called before a device is actually ready. This method is
+ * synonymous with polling the isAttached method until it returns True, or using the Attach event.
+ * <p>
+ * This method blocks indefinitely until the Phidget becomes available. This can be quite some time
+ * (forever), if the Phidget is never plugged in.
+ *
+ * @throws PhidgetException If this Phidget is not opened.
+ */
+ public final void waitForAttachment() throws PhidgetException
+ {
+ waitForAttachment(0);
+ }
+
+ private void enableDeviceSpecificEvents(boolean b) { }
+
+ private LinkedList attachListeners = new LinkedList();
+ private long nativeAttachHandler = 0;
+
+ /**
+ * Adds an attach listener. The attach handler is a method that will be called when this Phidget is phisically attached
+ * to the system, and has gone through its initalization, and so is ready to be used.
+ * <p>
+ * There is no limit on the number of attach handlers that can be registered for a particular Phidget.
+ *
+ * @param l An implemetation of the {@link com.phidgets.event.AttachListener AttachListener} interface
+ */
+ public final void addAttachListener(AttachListener l) {
+ synchronized (attachListeners) {
+ attachListeners.add(l);
+ enableAttachEvents(true);
+ }
+ }
+
+ /**
+ * Removes an attach listener. This will remove a previously added attach listener.
+ */
+ public final void removeAttachListener(AttachListener l) {
+ synchronized (attachListeners) {
+ attachListeners.remove(l);
+ enableAttachEvents(attachListeners.size() > 0);
+ }
+ }
+ private void fireAttach(AttachEvent e) {
+ synchronized (attachListeners) {
+ for (Iterator it = attachListeners.iterator();
+ it.hasNext(); )
+ ((AttachListener)it.next()).attached(e);
+ }
+ }
+ private native void enableAttachEvents(boolean b);
+
+ private LinkedList errorListeners = new LinkedList();
+ private long nativeErrorHandler = 0;
+
+ /**
+ * Adds an error listener. The error handler is a method that will be called when an asynchronous error occurs.
+ * Error events are not currently used, but will be in the future to report any problems that happen out of context from
+ * a direct function call.
+ * <p>
+ * There is no limit on the number of error handlers that can be registered for a particular Phidget.
+ *
+ * @param l An implemetation of the {@link com.phidgets.event.ErrorListener ErrorListener} interface
+ */
+ public final void addErrorListener(ErrorListener l) {
+ synchronized (errorListeners) {
+ errorListeners.add(l);
+ enableErrorEvents(true);
+ }
+ }
+
+ /**
+ * Removes an error listener. This will remove a previously added error listener.
+ */
+ public final void removeErrorListener(ErrorListener l) {
+ synchronized (errorListeners) {
+ errorListeners.remove(l);
+ enableErrorEvents(errorListeners.size() > 0);
+ }
+ }
+ private void fireError(ErrorEvent e) {
+ synchronized (errorListeners) {
+ for (Iterator it = errorListeners.iterator();
+ it.hasNext(); )
+ ((ErrorListener)it.next()).error(e);
+ }
+ }
+ private native void enableErrorEvents(boolean b);
+
+ private LinkedList detachListeners = new LinkedList();
+ private long nativeDetachHandler = 0;
+
+ /**
+ * Adds a detach listener. The detach handler is a method that will be called when this Phidget is phisically detached
+ * from the system, and is no longer available. This is particularly usefull for applications when a phisical detach would be expected.
+ * <p>
+ * Remember that many of the methods, if called on an unattached device, will throw a PhidgetException. This Exception can be checked to see if it
+ * was caused by a device being unattached, but a better method would be to regiter the detach handler, which could notify the main program logic that
+ * the device is no longer available, disable GUI controls, etc.
+ * <p>
+ * There is no limit on the number of detach handlers that can be registered for a particular Phidget.
+ *
+ * @param l An implemetation of the {@link com.phidgets.event.DetachListener DetachListener} interface
+ */
+ public final void addDetachListener(DetachListener l) {
+ synchronized (detachListeners) {
+ detachListeners.add(l);
+ enableDetachEvents(true);
+ }
+ }
+ /**
+ * Removes a detach listener. This will remove a previously added detach listener.
+ */
+ public final void removeDetachListener(DetachListener l) {
+ synchronized (detachListeners) {
+ detachListeners.remove(l);
+ enableDetachEvents(detachListeners.size() > 0);
+ }
+ }
+ private void fireDetach(DetachEvent e) {
+ synchronized (detachListeners) {
+ for (Iterator it = detachListeners.iterator();
+ it.hasNext(); )
+ ((DetachListener)it.next()).detached(e);
+ }
+ }
+ private native void enableDetachEvents(boolean b);
+
+
+ private LinkedList serverConnectListeners = new LinkedList();
+ private long nativeServerConnectHandler = 0;
+
+ /**
+ * Adds an serverConnect listener. The serverConnect handler is a method that will be called when a connection to a server is made.
+ * This is only usefull for Phidgets opened remotely.
+ * <p>
+ * There is no limit on the number of serverConnect handlers that can be registered for a particular Phidget.
+ *
+ * @param l An implemetation of the {@link com.phidgets.event.ServerConnectListener ServerConnectListener} interface
+ */
+ public final void addServerConnectListener(ServerConnectListener l)
+ {
+ synchronized (serverConnectListeners)
+ {
+ serverConnectListeners.add(l);
+ enableServerConnectEvents(true);
+ }
+ }
+
+ /**
+ * Removes an serverConnect listener. This will remove a previously added serverConnect listener.
+ */
+ public final void removeServerConnectListener(ServerConnectListener l)
+ {
+ synchronized (serverConnectListeners)
+ {
+ serverConnectListeners.remove(l);
+ enableServerConnectEvents(serverConnectListeners.size() > 0);
+ }
+ }
+ private void fireServerConnect(ServerConnectEvent e)
+ {
+ synchronized (serverConnectListeners)
+ {
+ for (Iterator it = serverConnectListeners.iterator();
+ it.hasNext(); )
+ ((ServerConnectListener)it.next()).serverConnected(e);
+ }
+ }
+ private native void enableServerConnectEvents(boolean b);
+
+
+ private LinkedList serverDisconnectListeners = new LinkedList();
+ private long nativeServerDisconnectHandler = 0;
+
+ /**
+ * Adds an serverDisconnect listener. The serverDisconnect handler is a method that will be called when a connection to a server is terminated.
+ * This is only usefull for Phidgets opened remotely.
+ * <p>
+ * There is no limit on the number of serverDisconnect handlers that can be registered for a particular Phidget.
+ *
+ * @param l An implemetation of the {@link com.phidgets.event.ServerDisconnectListener ServerDisconnectListener} interface
+ */
+ public final void addServerDisconnectListener(ServerDisconnectListener l)
+ {
+ synchronized (serverDisconnectListeners)
+ {
+ serverDisconnectListeners.add(l);
+ enableServerDisconnectEvents(true);
+ }
+ }
+
+ /**
+ * Removes an serverDisconnect listener. This will remove a previously added serverDisconnect listener.
+ */
+ public final void removeServerDisconnectListener(ServerDisconnectListener l)
+ {
+ synchronized (serverDisconnectListeners)
+ {
+ serverDisconnectListeners.remove(l);
+ enableServerDisconnectEvents(serverDisconnectListeners.size() > 0);
+ }
+ }
+ private void fireServerDisconnect(ServerDisconnectEvent e)
+ {
+ synchronized (serverDisconnectListeners)
+ {
+ for (Iterator it = serverDisconnectListeners.iterator();
+ it.hasNext(); )
+ ((ServerDisconnectListener)it.next()).serverDisconnected(e);
+ }
+ }
+ private native void enableServerDisconnectEvents(boolean b);
+
+ /**
+ * Return a Sring describing this Phidget.
+ */
+ public String toString() {
+ int dv = -1;
+ int sn = -1;
+ String dt = null;
+ String at = "";
+
+ try {
+ dv = getDeviceVersion();
+ sn = getSerialNumber();
+ dt = getDeviceType();
+ at = isAttached() ? " (attached)" : " (unattached)";
+ } catch (PhidgetException e) {
+ ;
+ } finally {
+ if (dt == null)
+ dt = getClass().getName().replaceFirst(
+ ".*\\.", "");
+ }
+ return dt + " v" + dv + " #" + sn + at;
+ }
+
+ protected void finalize() throws Throwable
+ {
+ try
+ {
+ if(!managerPhidget)
+ {
+ try
+ {
+ close();
+ }
+ catch (Exception e)
+ {
+ ;
+ }
+ try
+ {
+ nativeDelete();
+ }
+ catch (Exception e)
+ {
+ ;
+ }
+ }
+ }
+ finally
+ {
+ handle = 0;
+ super.finalize();
+ }
+ }
+
+ /**
+ * Compares two Phidgets. This method compares two Phidgets using serial number, device type and version.
+ */
+ public boolean equals(Object comp)
+ {
+ Phidget temp = (Phidget)comp;
+ try
+ {
+ if (temp.getSerialNumber() == getSerialNumber() && temp.getDeviceType().equals(getDeviceType()) &&
+ temp.getDeviceVersion() == getDeviceVersion())
+ return true;
+ }
+ catch (Exception e) { }
+ return false;
+ }
+}
diff --git a/Java/com/phidgets/PhidgetException.java b/Java/com/phidgets/PhidgetException.java
new file mode 100644
index 0000000..f33d345
--- /dev/null
+++ b/Java/com/phidgets/PhidgetException.java
@@ -0,0 +1,337 @@
+/*
+ * Copyright 2006 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets;
+
+/**
+ * This class represents Phidget related exceptions. All Phidget exceptions originate in the phidget21 C library.
+ * These exceptions can be thrown by most function in the library and cover such things as trying to access
+ * a Phidget before opening it, or before it is attached and ready to use, out of bounds Index and data values,
+ * trying to read data that isn't available, and other less common problems. EPHIDGET_(error) errors are thrown
+ * by any API calls, EEPHIDGET_(error) errors are returned via the {@link com.phidgets.event.ErrorEvent Error} event.
+ */
+public class PhidgetException extends java.lang.Exception {
+ private int errno;
+ private String description;
+
+ /**
+ * Constructor which takes in an error number and description.
+ * These exceptions originate from and are filled in by the phidget 21 C library.
+ */
+ public PhidgetException(int errno, String description) {
+ this.description = description;
+ this.errno = errno;
+ }
+
+ /**
+ * Phidget not found exception. "A Phidget matching the type and or serial number could not be found."
+ * <P>
+ * This exception is not currently used externally.
+ * <p>
+ * This is returned by {@link #getErrorNumber getErrorNumber}
+ */
+ public static final int EPHIDGET_NOTFOUND = 1;
+ /**
+ * No memory exception. "Memory could not be allocated."
+ * <P>
+ * This exception is thrown when a memory allocation (malloc) call fails in the c library.
+ * <p>
+ * This is returned by {@link #getErrorNumber getErrorNumber}
+ */
+ public static final int EPHIDGET_NOMEMORY = 2;
+ /**
+ * Unexpected exception. "Unexpected Error. Contact Phidgets Inc. for support."
+ * <P>
+ * This exception is thrown when something unexpected happens (more enexpected then another exception). This generally
+ * points to a bug or bad code in the C library, and hopefully won't even be seen.
+ * <p>
+ * This is returned by {@link #getErrorNumber getErrorNumber}
+ */
+ public static final int EPHIDGET_UNEXPECTED = 3;
+ /**
+ * Invalid argument exception. "Invalid argument passed to function."
+ * <P>
+ * This exception is thrown whenever a function recieves an unexpected null pointer, or a value that is out of range. ie setting a motor's speed to 101 when the maximum is 100.
+ * <p>
+ * This is returned by {@link #getErrorNumber getErrorNumber}
+ */
+ public static final int EPHIDGET_INVALIDARG = 4;
+ /**
+ * Phidget not attached exception. "Phidget not physically attached."
+ * <P>
+ * This exception is thrown when a method is called on a device that is not attached, and the method requires the device to be attached. ie trying to read the serial number, or
+ * the state of an ouput.
+ * <p>
+ * This is returned by {@link #getErrorNumber getErrorNumber}
+ */
+ public static final int EPHIDGET_NOTATTACHED = 5;
+ /**
+ * Interrupted exception. "Read/Write operation was interrupted."
+ * <P>
+ * This exception is not currently used externally.
+ * <p>
+ * This is returned by {@link #getErrorNumber getErrorNumber}
+ */
+ public static final int EPHIDGET_INTERRUPTED = 6;
+ /**
+ * Invalid error exception. "The Error Code is not defined."
+ * <P>
+ * This exception is thrown when trying to get the string description of an undefined error code. This should not be seen in Java.
+ * <p>
+ * This is returned by {@link #getErrorNumber getErrorNumber}
+ */
+ public static final int EPHIDGET_INVALID = 7;
+ /**
+ * Network exception. "Network Error."
+ * <P>
+ * This exception is thrown when a network related error occurs. The {@link #EEPHIDGET_NETWORK EEPHIDGET_NETWORK} code is more often used (in error events)
+ * because most network exceptions come through asynchronously.
+ * <p>
+ * This is returned by {@link #getErrorNumber getErrorNumber}
+ */
+ public static final int EPHIDGET_NETWORK = 8;
+ /**
+ * Value unknown exception. "Value is Unknown (State not yet received from device, or not yet set by user)."
+ * <P>
+ * This exception is thrown when a device that is set to unknow is read. ie trying to read the position of a servo before setting it's position.
+ * <p>
+ * Every effort is made in the library to fill in as much of a device's state before the attach event gets thrown, however, many there are some states
+ * that cannot be filled in automatically. ie older interface kits do not return their output states, and so these will be unknown until they are set.
+ * <p>
+ * This is a quite common exception for some devices, and so should always be caught
+ * <p>
+ * This is returned by {@link #getErrorNumber getErrorNumber}
+ */
+ public static final int EPHIDGET_UNKNOWNVAL = 9;
+ /**
+ * Authorization exception. "Authorization Failed."
+ * <P>
+ * This exception has been replaced by {@link #EEPHIDGET_BADPASSWORD EEPHIDGET_BADPASSWORD}.
+ * <p>
+ * This is returned by {@link #getErrorNumber getErrorNumber}
+ */
+ public static final int EPHIDGET_BADPASSWORD = 10;
+ /**
+ * Unsupported exception. "Not Supported."
+ * <P>
+ * This exception is thrown when a method is called that is not supported, either by that device, or by the system. ie calling setRatiometric on an interfaceKit that does not have sensors.
+ * <p>
+ * This is also used for methods that are not yet complete, ie setLabel on Windows.
+ * <p>
+ * This is returned by {@link #getErrorNumber getErrorNumber}
+ */
+ public static final int EPHIDGET_UNSUPPORTED = 11;
+ /**
+ * Duplicate request exception. "Duplicated request."
+ * <P>
+ * This exception is thrown when open is called twice on a device, without calling close in between. The second call to open is ignored.
+ * <p>
+ * This is returned by {@link #getErrorNumber getErrorNumber}
+ */
+ public static final int EPHIDGET_DUPLICATE = 12;
+ /**
+ * Timeout exception. "Given timeout has been exceeded."
+ * <P>
+ * This exception is thrown by {@link com.phidgets.Phidget#waitForAttachment(int) waitForAttachment(int)} if the provided timeout expires before an attach happens.
+ * This may also be thrown by a device set request, if the set times out - though this should not happen, and would generally mean a problem with the device.
+ * <p>
+ * This is returned by {@link #getErrorNumber getErrorNumber}
+ */
+ public static final int EPHIDGET_TIMEOUT = 13;
+ /**
+ * Out of bounds exception. "Index out of Bounds."
+ * <P>
+ * This exception is thrown anytime an indexed set or get method is called with an out of bounds index.
+ * <p>
+ * This is returned by {@link #getErrorNumber getErrorNumber}
+ */
+ public static final int EPHIDGET_OUTOFBOUNDS = 14;
+ /**
+ * Event exception. "A non-null error code was returned from an event handler."
+ * <P>
+ * This exception is not currently used.
+ * <p>
+ * This is returned by {@link #getErrorNumber getErrorNumber}
+ */
+ public static final int EPHIDGET_EVENT = 15;
+ /**
+ * Network not connected exception. "A connection to the server does not exist."
+ * <P>
+ * This exception is thrown when a network specific method is called on a device that was opened remotely, but there is no connection to a server. ie getServerID.
+ * <p>
+ * This is returned by {@link #getErrorNumber getErrorNumber}
+ */
+ public static final int EPHIDGET_NETWORK_NOTCONNECTED = 16;
+ /**
+ * Wrong device exception. "Function is not applicable for this device."
+ * <P>
+ * This exception is thrown when a method from device is called by another device. ie casting an InterfaceKit to a Servo and calling setPosition.
+ * <p>
+ * This is returned by {@link #getErrorNumber getErrorNumber}
+ */
+ public static final int EPHIDGET_WRONGDEVICE = 17;
+ /**
+ * Phidget closed exception. "Phidget handle was closed."
+ * <P>
+ * This exception is thrown when {@link com.phidgets.Phidget#waitForAttachment waitForAttachment} is called on a Phidget that has not been opened, or was closed.
+ * <p>
+ * This is returned by {@link #getErrorNumber getErrorNumber}
+ */
+ public static final int EPHIDGET_CLOSED = 18;
+ /**
+ * Version mismatch exception. "Webservice and Client protocol versions don't match. Update to newest release."
+ * <P>
+ * This exception has been replaced by {@link #EEPHIDGET_BADVERSION EEPHIDGET_BADVERSION}.
+ * <p>
+ * This is returned by {@link #getErrorNumber getErrorNumber}
+ */
+ public static final int EPHIDGET_BADVERSION = 19;
+
+
+ //Error Event codes
+
+ /**
+ * Network exception. "Network Error."
+ * <P>
+ * This exception is sent via the {@link com.phidgets.event.ErrorEvent Error} event. It will be accompanied by a specific Description of the network problem.
+ * <p>
+ * This is returned by {@link #getErrorNumber getErrorNumber}
+ */
+ public static final int EEPHIDGET_NETWORK = 0x8001;
+ /**
+ * Authorization exception. "Authorization Failed."
+ * <P>
+ * This exception is sent via the {@link com.phidgets.event.ErrorEvent Error} event. It means that a connection could not be authenticated because of a passwrod missmatch.
+ * <p>
+ * This is returned by {@link #getErrorNumber getErrorNumber}
+ */
+ public static final int EEPHIDGET_BADPASSWORD = 0x8002;
+ /**
+ * Version mismatch exception. "Webservice and Client protocol versions don't match. Update to newest release."
+ * <P>
+ * This exception is sent via the {@link com.phidgets.event.ErrorEvent Error} event when trying to connect to a remote phidget and the webservice version does not match your client library version.
+ * <p>
+ * This is returned by {@link #getErrorNumber getErrorNumber}
+ */
+ public static final int EEPHIDGET_BADVERSION = 0x8003;
+ /**
+ * Overrun exception. "A sampling overrun happend in firmware."
+ * <P>
+ * This exception sent via in the {@link com.phidgets.event.ErrorEvent Error} event. It is accompanied by a specific {@link #getDescription description}.
+ * <p>
+ * This is returned by {@link #getErrorNumber getErrorNumber}
+ */
+ public static final int EEPHIDGET_OVERRUN = 0x9002;
+ /**
+ * Packet lost exception. "One or more packets were lost."
+ * <P>
+ * This exception sent via in the {@link com.phidgets.event.ErrorEvent Error} event. It is accompanied by a specific {@link #getDescription description}.
+ * <p>
+ * This is returned by {@link #getErrorNumber getErrorNumber}
+ */
+ public static final int EEPHIDGET_PACKETLOST = 0x9003;
+ /**
+ * Wraparound exception. "A variable has wrapped around."
+ * <P>
+ * This exception sent via in the {@link com.phidgets.event.ErrorEvent Error} event. It is accompanied by a specific {@link #getDescription description}.
+ * <p>
+ * This is returned by {@link #getErrorNumber getErrorNumber}
+ */
+ public static final int EEPHIDGET_WRAP = 0x9004;
+ /**
+ * Overtemperature exception. "Overtemperature condition detected."
+ * <P>
+ * This exception sent via in the {@link com.phidgets.event.ErrorEvent Error} event. It is accompanied by a specific {@link #getDescription description}.
+ * <p>
+ * This is returned by {@link #getErrorNumber getErrorNumber}
+ */
+ public static final int EEPHIDGET_OVERTEMP = 0x9005;
+ /**
+ * Overcurrent exception. "Overcurrent condition detected."
+ * <P>
+ * This exception sent via in the {@link com.phidgets.event.ErrorEvent Error} event. It is accompanied by a specific {@link #getDescription description}.
+ * <p>
+ * This is returned by {@link #getErrorNumber getErrorNumber}
+ */
+ public static final int EEPHIDGET_OVERCURRENT = 0x9006;
+ /**
+ * Out of range exception. "Out of range condition detected."
+ * <P>
+ * This exception sent via in the {@link com.phidgets.event.ErrorEvent Error} event. It is accompanied by a specific {@link #getDescription description}.
+ * <p>
+ * This is returned by {@link #getErrorNumber getErrorNumber}
+ */
+ public static final int EEPHIDGET_OUTOFRANGE = 0x9007;
+ /**
+ * Bad power exception. "Power supply problem detected."
+ * <P>
+ * This exception sent via in the {@link com.phidgets.event.ErrorEvent Error} event. It is accompanied by a specific {@link #getDescription description}.
+ * <p>
+ * This is returned by {@link #getErrorNumber getErrorNumber}
+ */
+ public static final int EEPHIDGET_BADPOWER = 0x9008;
+
+ /**
+ * Returns the error number of this exception. This error number will match one of the EPHIDGET_(error) or EEPHIDGET_(error) constants defined in this class.
+ * These numbers are defined in the phidget21 c library and are consistent across all APIs.
+ * <p>
+ * There are 19 error codes defined, as follows:
+ * <br>
+ * {@link #EPHIDGET_NOTFOUND EPHIDGET_NOTFOUND},
+ * {@link #EPHIDGET_NOMEMORY EPHIDGET_NOMEMORY},
+ * {@link #EPHIDGET_UNEXPECTED EPHIDGET_UNEXPECTED},
+ * {@link #EPHIDGET_INVALIDARG EPHIDGET_INVALIDARG},
+ * {@link #EPHIDGET_NOTATTACHED EPHIDGET_NOTATTACHED},
+ * {@link #EPHIDGET_INTERRUPTED EPHIDGET_INTERRUPTED},
+ * {@link #EPHIDGET_INVALID EPHIDGET_INVALID},
+ * {@link #EPHIDGET_NETWORK EPHIDGET_NETWORK},
+ * {@link #EPHIDGET_UNKNOWNVAL EPHIDGET_UNKNOWNVAL},
+ * {@link #EPHIDGET_BADPASSWORD EPHIDGET_BADPASSWORD},
+ * {@link #EPHIDGET_UNSUPPORTED EPHIDGET_UNSUPPORTED},
+ * {@link #EPHIDGET_DUPLICATE EPHIDGET_DUPLICATE},
+ * {@link #EPHIDGET_TIMEOUT EPHIDGET_TIMEOUT},
+ * {@link #EPHIDGET_OUTOFBOUNDS EPHIDGET_OUTOFBOUNDS},
+ * {@link #EPHIDGET_EVENT EPHIDGET_EVENT},
+ * {@link #EPHIDGET_NETWORK_NOTCONNECTED EPHIDGET_NETWORK_NOTCONNECTED},
+ * {@link #EPHIDGET_WRONGDEVICE EPHIDGET_WRONGDEVICE},
+ * {@link #EPHIDGET_CLOSED EPHIDGET_CLOSED} and
+ * {@link #EPHIDGET_BADVERSION EPHIDGET_BADVERSION}</pre>
+ * <p>
+ * There are also 9 error event codes defined, as follows:
+ * <br>
+ * {@link #EEPHIDGET_NETWORK EEPHIDGET_NETWORK},
+ * {@link #EEPHIDGET_BADPASSWORD EEPHIDGET_BADPASSWORD},
+ * {@link #EEPHIDGET_BADVERSION EEPHIDGET_BADVERSION},
+ * {@link #EEPHIDGET_OVERRUN EEPHIDGET_OVERRUN},
+ * {@link #EEPHIDGET_PACKETLOST EEPHIDGET_PACKETLOST},
+ * {@link #EEPHIDGET_WRAP EEPHIDGET_WRAP},
+ * {@link #EEPHIDGET_OVERTEMP EEPHIDGET_OVERTEMP},
+ * {@link #EEPHIDGET_OVERCURRENT EEPHIDGET_OVERCURRENT},
+ * {@link #EEPHIDGET_OUTOFRANGE EEPHIDGET_OUTOFRANGE}</pre>
+ *
+ * @return The error code
+ */
+ public int getErrorNumber() {
+ return errno;
+ }
+
+ /**
+ * Returns a description of this exception. This is an english phrase that describes the exception that
+ * occured. These strings originate in the base phidget21 C library, and should help to diagnose problems.
+ *
+ * @return The error description
+ */
+ public String getDescription() {
+ return description;
+ }
+
+ /**
+ * Returns a string containing the error number and exception description.
+ *
+ * @return A string describing the error
+ */
+ public String toString() {
+ return "PhidgetException " + errno + " (" + description + ")";
+ }
+}
diff --git a/Java/com/phidgets/RFIDPhidget.java b/Java/com/phidgets/RFIDPhidget.java
new file mode 100644
index 0000000..b102b67
--- /dev/null
+++ b/Java/com/phidgets/RFIDPhidget.java
@@ -0,0 +1,197 @@
+
+/*
+ * Copyright 2006 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets;
+import java.util.Iterator;
+import java.util.LinkedList;
+import com.phidgets.event.*;
+/**
+ * This class represents a Phidget RFID Reader. All methods
+ * to read tags and set outputs on the RFID reader are implemented in this class.
+ * <p>
+ * The Phidget RFID reader can read one tag at a time. Both tag and tagloss event handlers are provided,
+ * as well as control over the antenna so that multiple readers can exists in close proximity without interference.
+ *
+ * @author Phidgets Inc.
+ */
+public final class RFIDPhidget extends Phidget
+{
+ public RFIDPhidget () throws PhidgetException
+ {
+ super (create ());
+ }
+ private static native long create () throws PhidgetException;
+ /**
+ * Returns the number of outputs. These are the outputs provided by the terminal block.
+ * Older RFID readers do not have these outputs, and this method will return 0.
+ * @return number of outputs
+ * @throws PhidgetException If this Phidget is not opened and attached.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native int getOutputCount () throws PhidgetException;
+ /**
+ * Returns the state of an output. True indicated activated, False deactivated, which is the default.
+ * @param index index of the output
+ * @return state of the output
+ * @throws PhidgetException If this Phidget is not opened and attached, or the index is out of range.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native boolean getOutputState (int index) throws PhidgetException;
+ /**
+ * Sets the state of a digital output. True indicated activated, False deactivated, which is the default.
+ * @param index index of the output
+ * @param state desired state
+ * @throws PhidgetException If this Phidget is not opened and attached, or the index is out of range.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native void setOutputState (int index, boolean state) throws PhidgetException;
+ /**
+ * Returns the state of the antenna. True indicated that the antenna is active, False indicated inactive.
+ * @return state of the antenna
+ * @throws PhidgetException If this Phidget is not opened and attached.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native boolean getAntennaOn () throws PhidgetException;
+ /**
+ * Sets the state of the antenna. True turns the antenna on, False turns it off. The antenna if by default
+ * turned off, and needs to be explicitely activated before tags can be read. Control over the antenna
+ * allows multiple readers to be used in close proximity, as multiple readers will interfere with each other if
+ * their antenna's are activated simultaneously.
+ * @param state new state for the antenna
+ * @throws PhidgetException If this Phidget is not opened and attached.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native void setAntennaOn (boolean state) throws PhidgetException;
+ /**
+ * Returns the state of the onboard LED. This LED is by default turned off.
+ * @return state of the LED
+ * @throws PhidgetException If this Phidget is not opened and attached.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native boolean getLEDOn () throws PhidgetException;
+ /**
+ * Sets the state of the onboard LED. True turns the LED on, False turns it off. The LED is by default turned off.
+ * @param state new state for the LED
+ * @throws PhidgetException If this Phidget is not opened and attached.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native void setLEDOn (boolean state) throws PhidgetException;
+ /**
+ * Returns the last tag read. This method will only return a valid tag after a tag has been seen.
+ * This method can be used even after a tag has been removed from the reader
+ * @return tag
+ * @throws PhidgetException If this Phidget is not opened and attached.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native String getLastTag () throws PhidgetException;
+ /**
+ * Returns the state of whether or not a tag is being read by the reader.
+ * True indicated that a tag is on (or near) the reader, false indicates that one is not.
+ * @return tag read state
+ * @throws PhidgetException If this Phidget is not opened and attached.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native boolean getTagStatus () throws PhidgetException;
+
+ private final void enableDeviceSpecificEvents (boolean b)
+ {
+ enableTagGainEvents (b && tagGainListeners.size () > 0);
+ enableTagLossEvents (b && tagLossListeners.size () > 0);
+ enableOutputChangeEvents (b && outputChangeListeners.size () > 0);
+ }
+ /**
+ * Adds a tag gained listener. The tag gaiend handler is a method that will be called when a new tag is
+ seen by the reader. The event is only fired one time for a new tag, so the tag has to be removed and then replaced before
+ another tag gained event will fire.
+ * <p>
+ * There is no limit on the number of tag gained change handlers that can be registered for a particular Phidget.
+ *
+ * @param l An implemetation of the {@link com.phidgets.event.TagGainListener TagGainListener} interface
+ */
+ public final void addTagGainListener (TagGainListener l)
+ {
+ synchronized (tagGainListeners)
+ {
+ tagGainListeners.add (l);
+ enableTagGainEvents (true);
+ }} private LinkedList tagGainListeners = new LinkedList ();
+ private long nativeTagGainHandler = 0;
+ public final void removeTagGainListener (TagGainListener l)
+ {
+ synchronized (tagGainListeners)
+ {
+ tagGainListeners.remove (l);
+ enableTagGainEvents (tagGainListeners.size () > 0);
+ }} private void fireTagGain (TagGainEvent e)
+ {
+ synchronized (tagGainListeners)
+ {
+ for (Iterator it = tagGainListeners.iterator (); it.hasNext ();)
+ ((TagGainListener) it.next ()).tagGained (e);
+ }
+ }
+ private native void enableTagGainEvents (boolean b);
+ /**
+ * Adds a tag lost listener. The tag lost handler is a method that will be called when a tag is
+ removed from the reader.
+ * <p>
+ * There is no limit on the number of tag lost change handlers that can be registered for a particular Phidget.
+ *
+ * @param l An implemetation of the {@link com.phidgets.event.TagLossListener TagLossListener} interface
+ */
+ public final void addTagLossListener (TagLossListener l)
+ {
+ synchronized (tagLossListeners)
+ {
+ tagLossListeners.add (l);
+ enableTagLossEvents (true);
+ }} private LinkedList tagLossListeners = new LinkedList ();
+ private long nativeTagLossHandler = 0;
+ public final void removeTagLossListener (TagLossListener l)
+ {
+ synchronized (tagLossListeners)
+ {
+ tagLossListeners.remove (l);
+ enableTagLossEvents (tagLossListeners.size () > 0);
+ }} private void fireTagLoss (TagLossEvent e)
+ {
+ synchronized (tagLossListeners)
+ {
+ for (Iterator it = tagLossListeners.iterator (); it.hasNext ();)
+ ((TagLossListener) it.next ()).tagLost (e);
+ }
+ }
+ private native void enableTagLossEvents (boolean b);
+ /**
+ * Adds an output change listener. The output change handler is a method that will be called when an output has changed.
+ * <p>
+ * There is no limit on the number of output change handlers that can be registered for a particular Phidget.
+ *
+ * @param l An implemetation of the {@link com.phidgets.event.OutputChangeListener OutputChangeListener} interface
+ */
+ public final void addOutputChangeListener (OutputChangeListener l)
+ {
+ synchronized (outputChangeListeners)
+ {
+ outputChangeListeners.add (l);
+ enableOutputChangeEvents (true);
+ }} private LinkedList outputChangeListeners = new LinkedList ();
+ private long nativeOutputChangeHandler = 0;
+ public final void removeOutputChangeListener (OutputChangeListener l)
+ {
+ synchronized (outputChangeListeners)
+ {
+ outputChangeListeners.remove (l);
+ enableOutputChangeEvents (outputChangeListeners.size () > 0);
+ }} private void fireOutputChange (OutputChangeEvent e)
+ {
+ synchronized (outputChangeListeners)
+ {
+ for (Iterator it = outputChangeListeners.iterator (); it.hasNext ();)
+ ((OutputChangeListener) it.next ()).outputChanged (e);
+ }
+ }
+ private native void enableOutputChangeEvents (boolean b);
+}
diff --git a/Java/com/phidgets/ServoPhidget.java b/Java/com/phidgets/ServoPhidget.java
new file mode 100644
index 0000000..aa9f05f
--- /dev/null
+++ b/Java/com/phidgets/ServoPhidget.java
@@ -0,0 +1,286 @@
+
+/*
+ * Copyright 2006 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets;
+import java.util.Iterator;
+import java.util.LinkedList;
+import com.phidgets.event.*;
+/**
+ * This class represents a Phidget servo Controller. All methods
+ * to control a Servo Controller are implemented in this class.
+ * <p>
+ * The Phidget Sevo controller simply outputs varying widths of PWM, which is what
+ * most servo motors take as an input driving signal.
+ *
+ * @author Phidgets Inc.
+ */
+public final class ServoPhidget extends Phidget
+{
+ public ServoPhidget () throws PhidgetException
+ {
+ super (create ());
+ }
+ private static native long create () throws PhidgetException;
+
+ /**
+ * Default - This is what the servo API been historically used, originally based on the Futaba FP-S148. This is used with {@link #getServoType getServoType} and {@link #setServoType setServoType}
+ */
+ public static final int PHIDGET_SERVO_DEFAULT = 1;
+ /**
+ * Raw us mode - all position, velocity, acceleration functions are specified in microseconds rather then degrees. This is used with {@link #getServoType getServoType} and {@link #setServoType setServoType}
+ */
+ public static final int PHIDGET_SERVO_RAW_us_MODE = 2;
+ /**
+ * HiTec HS-322HD Standard Servo. This is used with {@link #getServoType getServoType} and {@link #setServoType setServoType}
+ */
+ public static final int PHIDGET_SERVO_HITEC_HS322HD = 3;
+ /**
+ * HiTec HS-5245MG Digital Mini Servo. This is used with {@link #getServoType getServoType} and {@link #setServoType setServoType}
+ */
+ public static final int PHIDGET_SERVO_HITEC_HS5245MG = 4;
+ /**
+ * HiTec HS-805BB Mega Quarter Scale Servo. This is used with {@link #getServoType getServoType} and {@link #setServoType setServoType}
+ */
+ public static final int PHIDGET_SERVO_HITEC_805BB = 5;
+ /**
+ * HiTec HS-422 Standard Servo. This is used with {@link #getServoType getServoType} and {@link #setServoType setServoType}
+ */
+ public static final int PHIDGET_SERVO_HITEC_HS422 = 6;
+ /**
+ * Tower Pro MG90 Micro Servo. This is used with {@link #getServoType getServoType} and {@link #setServoType setServoType}
+ */
+ public static final int PHIDGET_SERVO_TOWERPRO_MG90 = 7;
+ /**
+ * HiTec HSR-1425CR Continuous Rotation Servo. This is used with {@link #getServoType getServoType} and {@link #setServoType setServoType}
+ */
+ public static final int PHIDGET_SERVO_HITEC_HSR1425CR = 8;
+ /**
+ * HiTec HS-785HB Sail Winch Servo. This is used with {@link #getServoType getServoType} and {@link #setServoType setServoType}
+ */
+ public static final int PHIDGET_SERVO_HITEC_HS785HB = 9;
+ /**
+ * HiTec HS-485HB Deluxe Servo. This is used with {@link #getServoType getServoType} and {@link #setServoType setServoType}
+ */
+ public static final int PHIDGET_SERVO_HITEC_HS485HB = 10;
+ /**
+ * HiTec HS-645MG Ultra Torque Servo. This is used with {@link #getServoType getServoType} and {@link #setServoType setServoType}
+ */
+ public static final int PHIDGET_SERVO_HITEC_HS645MG = 11;
+ /**
+ * HiTec HS-815BB Mega Sail Servo. This is used with {@link #getServoType getServoType} and {@link #setServoType setServoType}
+ */
+ public static final int PHIDGET_SERVO_HITEC_815BB = 12;
+ /**
+ * Firgelli L12 Linear Actuator 30mm 50:1. This is used with {@link #getServoType getServoType} and {@link #setServoType setServoType}
+ */
+ public static final int PHIDGET_SERVO_FIRGELLI_L12_30_50_06_R = 13;
+ /**
+ * Firgelli L12 Linear Actuator 50mm 100:1. This is used with {@link #getServoType getServoType} and {@link #setServoType setServoType}
+ */
+ public static final int PHIDGET_SERVO_FIRGELLI_L12_50_100_06_R = 14;
+ /**
+ * Firgelli L12 Linear Actuator 50mm 210:1. This is used with {@link #getServoType getServoType} and {@link #setServoType setServoType}
+ */
+ public static final int PHIDGET_SERVO_FIRGELLI_L12_50_210_06_R = 15;
+ /**
+ * Firgelli L12 Linear Actuator 100mm 50:1. This is used with {@link #getServoType getServoType} and {@link #setServoType setServoType}
+ */
+ public static final int PHIDGET_SERVO_FIRGELLI_L12_100_50_06_R = 16;
+ /**
+ * Firgelli L12 Linear Actuator 100mm 100:1. This is used with {@link #getServoType getServoType} and {@link #setServoType setServoType}
+ */
+ public static final int PHIDGET_SERVO_FIRGELLI_L12_100_100_06_R = 17;
+ /**
+ * SpringRC SM-S2313M Micro Servo. This is used with {@link #getServoType getServoType} and {@link #setServoType setServoType}
+ */
+ public static final int PHIDGET_SERVO_SPRINGRC_SM_S2313M = 18;
+ /**
+ * SpringRC SM-S3317M Small Servo. This is used with {@link #getServoType getServoType} and {@link #setServoType setServoType}
+ */
+ public static final int PHIDGET_SERVO_SPRINGRC_SM_S3317M = 19;
+ /**
+ * SpringRC SM-S3317SR Small Continuous Rotation Servo. This is used with {@link #getServoType getServoType} and {@link #setServoType setServoType}
+ */
+ public static final int PHIDGET_SERVO_SPRINGRC_SM_S3317SR = 20;
+ /**
+ * SpringRC SM-S4303R Standard Continuous Rotation Servo. This is used with {@link #getServoType getServoType} and {@link #setServoType setServoType}
+ */
+ public static final int PHIDGET_SERVO_SPRINGRC_SM_S4303R = 21;
+ /**
+ * SpringRC SM-S4315M High Torque Servo. This is used with {@link #getServoType getServoType} and {@link #setServoType setServoType}
+ */
+ public static final int PHIDGET_SERVO_SPRINGRC_SM_S4315M = 22;
+ /**
+ * SpringRC SM-S4315R High Torque Continuous Rotation Servo. This is used with {@link #getServoType getServoType} and {@link #setServoType setServoType}
+ */
+ public static final int PHIDGET_SERVO_SPRINGRC_SM_S4315R = 23;
+ /**
+ * SpringRC SM-S4505B Standard Servo. This is used with {@link #getServoType getServoType} and {@link #setServoType setServoType}
+ */
+ public static final int PHIDGET_SERVO_SPRINGRC_SM_S4505B = 24;
+ /**
+ * User Defined servo parameters. This is used with {@link #getServoType getServoType}
+ */
+ public static final int PHIDGET_SERVO_USER_DEFINED = 25;
+
+ /**
+ * Returns the number of motors this Phidget can support. Note that there is no way of programatically
+ * determining how many motors are actaully attached to the board.
+ * @return number of motors
+ */
+ public native int getMotorCount () throws PhidgetException;
+ /**
+ * Returns the position of a servo motor. Note that since servo motors do not offer any feedback in their interface,
+ * this value is simply whatever the servo was last set to. There is no way of determining the position of a servo
+ * that has been plugged in, until it's position has been set. Therefore, if an initial position is important, it
+ * should be set as part of initialization.
+ * <p>
+ * If the servo is not engaged, the position is unknown and calling this function will throw an exception.
+ * <p>
+ * The range here is between {@link #getPositionMin getPositionMin} and {@link #getPositionMax getPositionMax},
+ * and corresponds aproximately to an angle in degrees. Note that most servos will not be able to operate
+ * accross this entire range.
+ * @param index index of the motor
+ * @return current position of the selected motor
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is out of range.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native double getPosition (int index) throws PhidgetException;
+ /**
+ * Returns the maximum position that a servo will accept, or return.
+ * @param index Index of the servo
+ * @return Maximum position in degrees
+ * @throws PhidgetException If this Phidget is not opened and attached.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native double getPositionMax (int index) throws PhidgetException;
+ /**
+ * Returns the minimum position that a servo will accept, or return.
+ * @param index Index of the servo
+ * @return Minimum position in degrees
+ * @throws PhidgetException If this Phidget is not opened and attached.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native double getPositionMin (int index) throws PhidgetException;
+ /**
+ * Sets the position of a servo motor.
+ * <p>
+ * The range here is between {@link #getPositionMin getPositionMin} and {@link #getPositionMax getPositionMax},
+ * and corresponds aproximately to an angle in degrees. Note that most servos will not be able to operate
+ * accross this entire range. Typically, the range might be 25 - 180 degrees, but this depends on the servo
+ * @param index index of the motor
+ * @param position desired position
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index or position is out of range.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native void setPosition (int index, double position) throws PhidgetException;
+ /**
+ * Engage or disengage a servo motor.
+ * <p>
+ * This engages or disengages the servo. The motor is engaged whenever you set a position,
+ * use this function to disengage, and reengage without setting a position.
+ *
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is out of range.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native void setEngaged (int index, boolean state) throws PhidgetException;
+ /**
+ * @deprecated Replaced by
+ * {@link #setEngaged}
+ */
+ public native void setMotorOn (int index, boolean state) throws PhidgetException;
+ /**
+ * Returns the engaged state or a servo.
+ *
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is out of range.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native boolean getEngaged (int index) throws PhidgetException;
+ /**
+ * @deprecated Replaced by
+ * {@link #getEngaged}
+ */
+ public native boolean getMotorOn (int index) throws PhidgetException;
+ /**
+ * Returns the servo type for an index.
+ * The possible values for type are {@link #PHIDGET_SERVO_DEFAULT PHIDGET_SERVO_DEFAULT},
+ * {@link #PHIDGET_SERVO_RAW_us_MODE PHIDGET_SERVO_RAW_us_MODE}, {@link #PHIDGET_SERVO_HITEC_HS322HD PHIDGET_SERVO_HITEC_HS322HD},
+ * {@link #PHIDGET_SERVO_HITEC_HS5245MG PHIDGET_SERVO_HITEC_HS5245MG}, {@link #PHIDGET_SERVO_HITEC_805BB PHIDGET_SERVO_HITEC_805BB},
+ * {@link #PHIDGET_SERVO_HITEC_HS422 PHIDGET_SERVO_HITEC_HS422}, etc.
+ * @param index Input
+ * @return Servo Type
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is out of range.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native int getServoType (int index) throws PhidgetException;
+ /**
+ * Sets the servo type for an index.
+ * <p>
+ * This constrains the PCM to the valid range of the servo, and sets the degrees-to-PCM ratio to match the actual servo rotation.
+ * <p>
+ * The possible values for type are {@link #PHIDGET_SERVO_DEFAULT PHIDGET_SERVO_DEFAULT},
+ * {@link #PHIDGET_SERVO_RAW_us_MODE PHIDGET_SERVO_RAW_us_MODE}, {@link #PHIDGET_SERVO_HITEC_HS322HD PHIDGET_SERVO_HITEC_HS322HD},
+ * {@link #PHIDGET_SERVO_HITEC_HS5245MG PHIDGET_SERVO_HITEC_HS5245MG}, {@link #PHIDGET_SERVO_HITEC_805BB PHIDGET_SERVO_HITEC_805BB},
+ * {@link #PHIDGET_SERVO_HITEC_HS422 PHIDGET_SERVO_HITEC_HS422}, etc.
+ * <p>
+ * Support for other servo types can be achieved by using {@link #setServoParameters setServoParameters}.
+ * <p>
+ * The default setting is {@link #PHIDGET_SERVO_DEFAULT PHIDGET_SERVO_DEFAULT}, which is used for historical (backwards compatibility) reasons.
+ * @param index Input
+ * @param type Servo Type
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is out of range.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native void setServoType (int index, int type) throws PhidgetException;
+ /**
+ * Sets the servo parameters for a custom servo definition.
+ * <p>
+ * This constrains the PCM to the valid range of the servo, and sets the degrees-to-PCM ratio to match the actual servo rotation.
+ * <p>
+ * @param index Servo Index
+ * @param minUs Minimum PCM supported in microseconds
+ * @param maxUs Maximum PCM supported in microseconds
+ * @param degrees Degrees of rotation represented by the given PCM range
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is out of range.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native void setServoParameters (int index, double minUs, double maxUs, double degrees) throws PhidgetException;
+
+ private final void enableDeviceSpecificEvents (boolean b)
+ {
+ enableServoPositionChangeEvents (b && servoPositionChangeListeners.size () > 0);
+ }
+ /**
+ * Adds a servo position change listener. The servo position change handler is a method that will be called when the servo position
+ * has changed. The event will get fired after every call to {@link #setPosition(int, double) setPosition}.
+ * <p>
+ * There is no limit on the number of servo position change handlers that can be registered for a particular Phidget.
+ *
+ * @param l An implemetation of the {@link com.phidgets.event.ServoPositionChangeListener ServoPositionChangeListener} interface
+ */
+ public final void addServoPositionChangeListener (ServoPositionChangeListener l)
+ {
+ synchronized (servoPositionChangeListeners)
+ {
+ servoPositionChangeListeners.add (l);
+ enableServoPositionChangeEvents (true);
+ }} private LinkedList servoPositionChangeListeners = new LinkedList ();
+ private long nativeServoPositionChangeHandler = 0;
+ public final void removeServoPositionChangeListener (ServoPositionChangeListener l)
+ {
+ synchronized (servoPositionChangeListeners)
+ {
+ servoPositionChangeListeners.remove (l);
+ enableServoPositionChangeEvents (servoPositionChangeListeners.size () > 0);
+ }} private void fireServoPositionChange (ServoPositionChangeEvent e)
+ {
+ synchronized (servoPositionChangeListeners)
+ {
+ for (Iterator it = servoPositionChangeListeners.iterator (); it.hasNext ();)
+ ((ServoPositionChangeListener) it.next ()).servoPositionChanged (e);
+ }
+ }
+ private native void enableServoPositionChangeEvents (boolean b);
+}
diff --git a/Java/com/phidgets/SpatialEventData.java b/Java/com/phidgets/SpatialEventData.java
new file mode 100644
index 0000000..0f7f9c9
--- /dev/null
+++ b/Java/com/phidgets/SpatialEventData.java
@@ -0,0 +1,101 @@
+
+/*
+ * Copyright 2006 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets;
+/**
+ * This class represents an a set of spatial data. It's used in the SpatialData event.
+ *
+ * @author Phidget Inc.
+ */
+public final class SpatialEventData
+{
+ private double[] acceleration;
+ private double[] angularRate;
+ private double[] magneticField;
+ private int timeSeconds, timeMicroSeconds;
+
+ /**
+ * Creates a new SpatialEventData object.
+ * @param acceleration the acceleration data
+ * @param angularRate the gyro data
+ * @param magneticField the compass data
+ * @param timeSeconds the timestamp in seconds
+ * @param timeMicroSeconds the time since the last second in microseconds
+ */
+ public SpatialEventData(double[] acceleration, double[] angularRate, double[] magneticField, int timeSeconds, int timeMicroSeconds)
+ {
+ this.acceleration = new double[acceleration.length];
+ this.angularRate = new double[angularRate.length];
+ this.magneticField = new double[magneticField.length];
+ for(int i=0;i<acceleration.length;i++)
+ this.acceleration[i] = acceleration[i];
+ for(int i=0;i<angularRate.length;i++)
+ this.angularRate[i] = angularRate[i];
+ for(int i=0;i<magneticField.length;i++)
+ this.magneticField[i] = magneticField[i];
+ this.timeSeconds = timeSeconds;
+ this.timeMicroSeconds = timeMicroSeconds;
+ }
+
+ /**
+ * Returns the acceleration data.
+ * @return acceleration data
+ */
+ public double[] getAcceleration()
+ {
+ return acceleration;
+ }
+
+ /**
+ * Returns the angularRate data.
+ * @return angularRate data
+ */
+ public double[] getAngularRate()
+ {
+ return angularRate;
+ }
+
+ /**
+ * Returns the magneticField data.
+ * @return magneticField data
+ */
+ public double[] getMagneticField()
+ {
+ return magneticField;
+ }
+
+ /**
+ * Returns the seconds since attach timestamp.
+ * @return whole seconds
+ */
+ public int getTimeSeconds()
+ {
+ return timeSeconds;
+ }
+
+ /**
+ * Returns the microseconds since last second.
+ * @return microseconds
+ */
+ public int getTimeMicroSeconds()
+ {
+ return timeMicroSeconds;
+ }
+
+ /**
+ * Returns time since attach in seconds
+ * @return seconds
+ */
+ public double getTime()
+ {
+ return (timeMicroSeconds/1000000.0 + timeSeconds);
+ }
+
+ public String toString()
+ {
+ return "Spatial Data";
+ }
+}
+
diff --git a/Java/com/phidgets/SpatialPhidget.java b/Java/com/phidgets/SpatialPhidget.java
new file mode 100644
index 0000000..bec1de7
--- /dev/null
+++ b/Java/com/phidgets/SpatialPhidget.java
@@ -0,0 +1,205 @@
+
+/*
+ * Copyright 2006 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets;
+import java.util.Iterator;
+import java.util.LinkedList;
+import com.phidgets.event.*;
+/**
+ * This class represents a Phidget Spatial. All methods for a PhidgetSpatial are implemented in this class.
+ <p>
+ The Phidget Spatial may provide up to 3 axes of acceleration data, 3 axes of angular rate data and 3 axes of magnetic field data.
+
+ * @author Phidgets Inc.
+ */
+public final class SpatialPhidget extends Phidget
+{
+ public SpatialPhidget () throws PhidgetException
+ {
+ super (create ());
+ }
+ private static native long create () throws PhidgetException;
+
+ /**
+ * Returns the number of accelerometer axes.
+ * @return number of axes of acceleration
+ */
+ public native int getAccelerationAxisCount () throws PhidgetException;
+ /**
+ * Returns the acceleration of a particular axis.
+ *
+ * @param index index of the axis
+ * @return acceleration of the selected axis
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is out of range.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native double getAcceleration (int index) throws PhidgetException;
+ /**
+ * Returns the maximum acceleration value that this axis will report.
+ * @return maximum acceleration
+ */
+ public native double getAccelerationMax (int index) throws PhidgetException;
+ /**
+ * Returns the minimum acceleration value that this axis will report.
+ * @return minimum acceleration
+ */
+ public native double getAccelerationMin (int index) throws PhidgetException;
+
+ /**
+ * Returns the number of gyro axes.
+ * @return number of axes of angularRate
+ */
+ public native int getGyroAxisCount () throws PhidgetException;
+ /**
+ * Returns the angularRate of a particular axis.
+ *
+ * @param index index of the axis
+ * @return angularRate of the selected axis
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is out of range.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native double getAngularRate (int index) throws PhidgetException;
+ /**
+ * Returns the maximum angularRate value that this axis will report.
+ * @return maximum angularRate
+ */
+ public native double getAngularRateMax (int index) throws PhidgetException;
+ /**
+ * Returns the minimum angularRate value that this axis will report.
+ * @return minimum angularRate
+ */
+ public native double getAngularRateMin (int index) throws PhidgetException;
+
+ /**
+ * Returns the number of compass axes.
+ * @return number of axes of magneticField
+ */
+ public native int getCompassAxisCount () throws PhidgetException;
+ /**
+ * Returns the magneticField of a particular axis.
+ *
+ * @param index index of the axis
+ * @return magneticField of the selected axis
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is out of range.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native double getMagneticField (int index) throws PhidgetException;
+ /**
+ * Returns the maximum magneticField value that this axis will report.
+ * @return maximum magneticField
+ */
+ public native double getMagneticFieldMax (int index) throws PhidgetException;
+ /**
+ * Returns the minimum magneticField value that this axis will report.
+ * @return minimum magneticField
+ */
+ public native double getMagneticFieldMin (int index) throws PhidgetException;
+
+ /**
+ * Returns the data rate, in milliseconds.
+ *
+ * @return data rate
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is out of range.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native int getDataRate () throws PhidgetException;
+ /**
+ * Sets the data rate, in milliseconds.
+ *
+ * @param rate data rate
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is out of range.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native void setDataRate (int rate) throws PhidgetException;
+ /**
+ * Returns the minimum data rate, in milliseconds.
+ *
+ * @return minimum data rate
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is out of range.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native int getDataRateMin () throws PhidgetException;
+ /**
+ * Returns the maximum data rate, in milliseconds.
+ *
+ * @return maximum data rate
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is out of range.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native int getDataRateMax () throws PhidgetException;
+
+ /**
+ * Zeroes the gyroscope. This takes about two seconds and the gyro zxes will report 0 during the process.
+ * This should only be called when the board is not moving.
+ *
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is out of range.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native void zeroGyro () throws PhidgetException;
+ /**
+ * Sets the compass correction factors. This can be used to correcting any sensor errors, including hard and soft iron offsets and sensor error factors.
+ *
+ * @param magField Local magnetic field strength.
+ * @param offset0 Axis 0 offset correction.
+ * @param offset1 Axis 1 offset correction.
+ * @param offset2 Axis 2 offset correction.
+ * @param gain0 Axis 0 gain correction.
+ * @param gain1 Axis 1 gain correction.
+ * @param gain2 Axis 2 gain correction.
+ * @param T0 Non-orthogonality correction factor 0.
+ * @param T1 Non-orthogonality correction factor 1.
+ * @param T2 Non-orthogonality correction factor 2.
+ * @param T3 Non-orthogonality correction factor 3.
+ * @param T4 Non-orthogonality correction factor 4.
+ * @param T5 Non-orthogonality correction factor 5.
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is out of range.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native void setCompassCorrectionParameters (double magField, double offset0, double offset1, double offset2, double gain0, double gain1, double gain2, double T0, double T1, double T2,
+ double T3, double T4, double T5) throws PhidgetException;
+ /**
+ * Resets the compass correction factors. Magnetic field data will be presented directly as reported by the sensor.
+ *
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is out of range.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native void resetCompassCorrectionParameters () throws PhidgetException;
+
+ private final void enableDeviceSpecificEvents (boolean b)
+ {
+ enableSpatialDataEvents (b && spatialDataListeners.size () > 0);
+ }
+ /**
+ * Adds a spatial data listener. The spatial data handler is a method that will be called at a rate of
+ * {@link #getDataRate() DataRate} that has been set for the device. This event contains data for all axes of all sensors.
+ * <p>
+ * There is no limit on the number of spatial data handlers that can be registered for a particular Phidget.
+ *
+ * @param l An implemetation of the {@link com.phidgets.event.SpatialDataListener SpatialDataListener} interface
+ */
+ public final void addSpatialDataListener (SpatialDataListener l)
+ {
+ synchronized (spatialDataListeners)
+ {
+ spatialDataListeners.add (l);
+ enableSpatialDataEvents (true);
+ }} private LinkedList spatialDataListeners = new LinkedList ();
+ private long nativeSpatialDataHandler = 0;
+ public final void removeSpatialDataListener (SpatialDataListener l)
+ {
+ synchronized (spatialDataListeners)
+ {
+ spatialDataListeners.remove (l);
+ enableSpatialDataEvents (spatialDataListeners.size () > 0);
+ }} private void fireSpatialData (SpatialDataEvent e)
+ {
+ synchronized (spatialDataListeners)
+ {
+ for (Iterator it = spatialDataListeners.iterator (); it.hasNext ();)
+ ((SpatialDataListener) it.next ()).data (e);
+ }
+ }
+ private native void enableSpatialDataEvents (boolean b);
+}
diff --git a/Java/com/phidgets/StepperPhidget.java b/Java/com/phidgets/StepperPhidget.java
new file mode 100644
index 0000000..83fa772
--- /dev/null
+++ b/Java/com/phidgets/StepperPhidget.java
@@ -0,0 +1,422 @@
+
+/*
+ * Copyright 2006 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets;
+import java.util.Iterator;
+import java.util.LinkedList;
+import com.phidgets.event.*;
+/**
+ * This class represents a Phidget Stepper Controller. All methods
+ * to to control a stepper controller and read back stepper data are implemented in this class.
+ * <p>
+ * The Phidget Stepper is able to control 1 or more Stepper motors. Motor Acceleration and Velocity are
+ * controllable, and micro-stepping is used. The type and number of motors that can be controlled
+ * depend on the Stepper Controller. Digital inputs are available on select Phidget Stepper Controllers.
+ *
+ * @author Phidgets Inc.
+ */
+public final class StepperPhidget extends Phidget
+{
+ public StepperPhidget () throws PhidgetException
+ {
+ super (create ());
+ }
+ private static native long create () throws PhidgetException;
+ /**
+ * Returns the number of stepper motors supported by this Phidget. This does not neccesarily correspond
+ to the number of motors actually attached to the board.
+ * @return number of supported motors
+ * @throws PhidgetException If this Phidget is not opened and attached.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native int getMotorCount () throws PhidgetException;
+ /**
+ * Returns the number of digital inputs. Not all Stepper Controllers have digital inputs.
+ * @return number of digital inputs
+ * @throws PhidgetException If this Phidget is not opened and attached.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native int getInputCount () throws PhidgetException;
+ /**
+ * Returns the state of a digital input. True means that the input is activated, and False indicated the default state.
+ * @param index index of the input
+ * @return state of the input
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is invalid.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native boolean getInputState (int index) throws PhidgetException;
+ /**
+ * Returns a motor's acceleration. The valid range is between {@link #getAccelerationMin getAccelerationMin}
+ * and {@link #getAccelerationMax getAccelerationMax}, and refers to how fast the Stepper Controller will change the speed of a motor.
+ * <p>This value is in (micro)steps per second squared. The step unit will depend on the Stepper Controller. For example, the Bipolar
+ * Stepper controller has an accuracy of 16th steps, so this value would be in 16th steps per second squared.
+ * @param index index of motor
+ * @return acceleration of motor
+ * @throws PhidgetException If this Phidget is not opened and attached, if the index is invalid, or if the acceleration is unknown.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native double getAcceleration (int index) throws PhidgetException;
+ /**
+ * Returns the maximum acceleration that a motor will accept, or return.
+ * <p>This value uses the same units as {@link #setAcceleration setAcceleration}/{@link #getAcceleration getAcceleration}.
+ * @param index Index of the motor
+ * @return Maximum acceleration
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is invalid.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native double getAccelerationMax (int index) throws PhidgetException;
+ /**
+ * Returns the minimum acceleration that a motor will accept, or return.
+ * <p>This value uses the same units as {@link #setAcceleration setAcceleration}/{@link #getAcceleration getAcceleration}.
+ * @param index Index of the motor
+ * @return Minimum acceleration
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is invalid.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native double getAccelerationMin (int index) throws PhidgetException;
+ /**
+ * Sets a motor's acceleration.
+ * The valid range is between {@link #getAccelerationMin getAccelerationMin} and {@link #getAccelerationMax getAccelerationMax}.
+ * This controls how fast the motor changes speed.
+ * <p>This value is in (micro)steps per second squared. The step unit will depend on the Stepper Controller. For example, the Bipolar
+ * Stepper controller has an accuracy of 16th steps, so this value would be in 16th steps per second squared.
+ * @param index index of the motor
+ * @param acceleration requested acceleration for that motor
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index or acceleration are invalid.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native void setAcceleration (int index, double acceleration) throws PhidgetException;
+ /**
+ * Returns a motor's current velocity. The valid range is between {@link #getVelocityMin getVelocityMin} and {@link #getVelocityMax getVelocityMax},
+ * with 0 being stopped.
+ * <p>This value is in (micro)steps per second. The step unit will depend on the Stepper Controller. For example, the Bipolar
+ * Stepper controller has an accuracy of 16th steps, so this value would be in 16th steps per second.
+ * @param index index of the motor
+ * @return current speed of the motor
+ * @throws PhidgetException If this Phidget is not opened and attached, if the index is invalid, or if the velocity in unknown.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native double getVelocity (int index) throws PhidgetException;
+ /**
+ * Returns the maximum velocity that a stepper motor will accept, or return.
+ * <p>This value uses the same units as {@link #setVelocityLimit setVelocityLimit}/{@link #getVelocityLimit getVelocityLimit} and {@link #getVelocity getVelocity}.
+ * @param index Index of the motor
+ * @return Maximum velocity
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is invalid.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native double getVelocityMax (int index) throws PhidgetException;
+ /**
+ * Returns the minimum velocity that a stepper motor will accept, or return.
+ * <p>This value uses the same units as {@link #setVelocityLimit setVelocityLimit}/{@link #getVelocityLimit getVelocityLimit} and {@link #getVelocity getVelocity}.
+ * @param index Index of the motor
+ * @return Minimum velocity
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is invalid.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native double getVelocityMin (int index) throws PhidgetException;
+ /**
+ * Sets a motor's velocity limit. This is the maximum velocity that the motor will turn at.
+ * The valid range is between {@link #getVelocityMin getVelocityMin} and {@link #getVelocityMax getVelocityMax},
+ * with 0 being stopped.
+ * <p>This value is in (micro)steps per second. The step unit will depend on the Stepper Controller. For example, the Bipolar
+ * Stepper controller has an accuracy of 16th steps, so this value would be in 16th steps per second.
+ * @param index index of the motor
+ * @param velocity requested velocity for the motor
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index or velocity are invalid.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native void setVelocityLimit (int index, double velocity) throws PhidgetException;
+ /**
+ * Returns a motor's velocity limit. This is the maximum velocity that the motor will turn at.
+ * The valid range is between {@link #getVelocityMin getVelocityMin} and {@link #getVelocityMax getVelocityMax},
+ * with 0 being stopped.
+ * <p>This value is in (micro)steps per second. The step unit will depend on the Stepper Controller. For example, the Bipolar
+ * Stepper controller has an accuracy of 16th steps, so this value would be in 16th steps per second.
+ * @param index index of the motor
+ * @return current speed of the motor
+ * @throws PhidgetException If this Phidget is not opened and attached, if the index is invalid, or if the velocity in unknown.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native double getVelocityLimit (int index) throws PhidgetException;
+ /**
+ * Returns the maximum position that a stepper motor will accept, or return.
+ * <p>This value uses the same units as
+ * {@link #setTargetPosition setTargetPosition}/{@link #getTargetPosition getTargetPosition} and {@link #setCurrentPosition setCurrentPosition}/{@link #getCurrentPosition getCurrentPosition}.
+ * @param index Index of the motor
+ * @return Maximum position
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is invalid.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native long getPositionMax (int index) throws PhidgetException;
+ /**
+ * Returns the minimum position that a stepper motor will accept, or return.
+ * <p>This value uses the same units as
+ * {@link #setTargetPosition setTargetPosition}/{@link #getTargetPosition getTargetPosition} and {@link #setCurrentPosition setCurrentPosition}/{@link #getCurrentPosition getCurrentPosition}.
+ * @param index Index of the motor
+ * @return Minimum position
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is invalid.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native long getPositionMin (int index) throws PhidgetException;
+ /**
+ * Sets a motor's current position. Use this is (re)set the current physical position of the motor to a specific position value.
+ * This does not move the motor, and if the motor is moving, calling this will cause it to stop moving. Use {@link #setTargetPosition setTargetPosition}
+ * to move the motor to a position.
+ * The valid range is between {@link #getPositionMin getPositionMin} and {@link #getPositionMax getPositionMax}.
+ * <p>This value is in (micro)steps. The step unit will depend on the Stepper Controller. For example, the Bipolar
+ * Stepper controller has an accuracy of 16th steps, so this value would be in 16th steps.
+ * @param index index of the motor
+ * @param position current position of the motor
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index or position are invalid.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native void setCurrentPosition (int index, long position) throws PhidgetException;
+ /**
+ * Returns a motor's current position. This is the actual step position that the motor is at right now.
+ * The valid range is between {@link #getPositionMin getPositionMin} and {@link #getPositionMax getPositionMax}.
+ * <p>This value is in (micro)steps. The step unit will depend on the Stepper Controller. For example, the Bipolar
+ * Stepper controller has an accuracy of 16th steps, so this value would be in 16th steps.
+ * @param index index of the motor
+ * @return current position of the motor
+ * @throws PhidgetException If this Phidget is not opened and attached, if the index is invalid, or if the position in unknown.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native long getCurrentPosition (int index) throws PhidgetException;
+ /**
+ * Sets a motor's target position. Use this is set the target position for the stepper. If the stepper is {@link #setEngaged engaged} it will start moving towards
+ * this target position.
+ * The valid range is between {@link #getPositionMin getPositionMin} and {@link #getPositionMax getPositionMax}.
+ * <p>This value is in (micro)steps. The step unit will depend on the Stepper Controller. For example, the Bipolar
+ * Stepper controller has an accuracy of 16th steps, so this value would be in 16th steps.
+ * @param index index of the motor
+ * @param position target position of the motor
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index or position are invalid.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native void setTargetPosition (int index, long position) throws PhidgetException;
+ /**
+ * Returns a motor's target position. This is the position that the motor wants to be at. If the motor is not moving,
+ * it probably has reached the target position, and this will match {@link #getCurrentPosition current position}.
+ * The valid range is between {@link #getPositionMin getPositionMin} and {@link #getPositionMax getPositionMax}.
+ * <p>This value is in (micro)steps. The step unit will depend on the Stepper Controller. For example, the Bipolar
+ * Stepper controller has an accuracy of 16th steps, so this value would be in 16th steps.
+ * @param index index of the motor
+ * @return target position of the motor
+ * @throws PhidgetException If this Phidget is not opened and attached, if the index is invalid, or if the position in unknown.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native long getTargetPosition (int index) throws PhidgetException;
+ /**
+ * Returns a motor's current usage. The valid range is between {@link #getCurrentMin getCurrentMin} and {@link #getCurrentMax getCurrentMax}.
+ * This value is in Amps.
+ * <p>Note that this is not supported on all stepper controllers.
+ * @param index index of the motor
+ * @return current usage of the motor
+ * @throws PhidgetException If this Phidget is not opened and attached, if the index is invalid, if the value is unknown, or if this is not supported.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native double getCurrent (int index) throws PhidgetException;
+ /**
+ * Returns the current limit.
+ * <p>This value is in Amps.
+ * @param index Index of the motor
+ * @return Current Limit
+ * @throws PhidgetException If this Phidget is not opened and attached, if the index is invalid, if the value is unknown, or if this is not supported.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native double getCurrentLimit (int index) throws PhidgetException;
+ /**
+ * Sets a motor's current usage limit. The valid range is between {@link #getCurrentMin getCurrentMin} and {@link #getCurrentMax getCurrentMax}.
+ * This sets the maximum current that a motor will be allowed to draw. Use this with the Bipolar stepper controller to get smooth micro stepping -
+ * see the product manual for more details. This value is in Amps.
+ * <p>Note that this is not supported on all stepper controllers.
+ * @param index index of the motor
+ * @param current current limit for the motor
+ * @throws PhidgetException If this Phidget is not opened and attached, if the index is invalid, if the value is unknown, or if this is not supported.
+ *
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native void setCurrentLimit (int index, double current) throws PhidgetException;
+ /**
+ * Returns the maximum current that a stepper motor will accept, or return.
+ * <p>This value is in Amps.
+ * @param index Index of the motor
+ * @return Maximum current
+ * @throws PhidgetException If this Phidget is not opened and attached, if the index is invalid, or if this is not supported.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native double getCurrentMax (int index) throws PhidgetException;
+ /**
+ * Returns the minimum current that a stepper motor will accept, or return.
+ * <p>This value is in Amps.
+ * @param index Index of the motor
+ * @return Minimum current
+ * @throws PhidgetException If this Phidget is not opened and attached, if the index is invalid, or if this is not supported.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native double getCurrentMin (int index) throws PhidgetException;
+ /**
+ * Engage or disengage a motor.
+ * <p>
+ * This engages or disengages the stepper motor. The motors are by default disengaged when the stepper controller is plugged in.
+ * When the stepper is disengaged, position, velocity, etc. can all be set, but the motor will not start moving until it is engaged.
+ * If position is read when a motor is disengaged, it will throw an exception.
+ *
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is out of range.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native void setEngaged (int index, boolean state) throws PhidgetException;
+ /**
+ * Returns the engaged state of a motor.
+ *
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is out of range.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native boolean getEngaged (int index) throws PhidgetException;
+ /**
+ * Returns the stopped state of a motor. Use this to determine if the motor is moving and/or up to date with the latest commands you have sent.
+ * If this is true, the motor is guaranteed to be stopped and to have processed every command issued. Generally, this would
+ * be polled after a target position is set to wait until that position is reached.
+ *
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is out of range.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native boolean getStopped (int index) throws PhidgetException;
+
+ private final void enableDeviceSpecificEvents (boolean b)
+ {
+ enableStepperPositionChangeEvents (b && stepperPositionChangeListeners.size () > 0);
+ enableStepperVelocityChangeEvents (b && stepperVelocityChangeListeners.size () > 0);
+ enableCurrentChangeEvents (b && currentChangeListeners.size () > 0);
+ enableInputChangeEvents (b && inputChangeListeners.size () > 0);
+ }
+ /**
+ * Adds a position change listener. The position change handler is a method that will be called when the stepper
+ * position has changed.
+ * <p>
+ * There is no limit on the number of position change handlers that can be registered for a particular Phidget.
+ *
+ * @param l An implemetation of the {@link com.phidgets.event.StepperPositionChangeListener StepperPositionChangeListener} interface
+ */
+ public final void addStepperPositionChangeListener (StepperPositionChangeListener l)
+ {
+ synchronized (stepperPositionChangeListeners)
+ {
+ stepperPositionChangeListeners.add (l);
+ enableStepperPositionChangeEvents (true);
+ }} private LinkedList stepperPositionChangeListeners = new LinkedList ();
+ private long nativeStepperPositionChangeHandler = 0;
+ public final void removeStepperPositionChangeListener (StepperPositionChangeListener l)
+ {
+ synchronized (stepperPositionChangeListeners)
+ {
+ stepperPositionChangeListeners.remove (l);
+ enableStepperPositionChangeEvents (stepperPositionChangeListeners.size () > 0);
+ }} private void fireStepperPositionChange (StepperPositionChangeEvent e)
+ {
+ synchronized (stepperPositionChangeListeners)
+ {
+ for (Iterator it = stepperPositionChangeListeners.iterator (); it.hasNext ();)
+ ((StepperPositionChangeListener) it.next ()).stepperPositionChanged (e);
+ }
+ }
+ private native void enableStepperPositionChangeEvents (boolean b);
+ /**
+ * Adds a velocity change listener. The velocity change handler is a method that will be called when the stepper
+ * velocity has changed.
+ * <p>
+ * There is no limit on the number of velocity change handlers that can be registered for a particular Phidget.
+ *
+ * @param l An implemetation of the {@link com.phidgets.event.StepperVelocityChangeListener StepperVelocityChangeListener} interface
+ */
+ public final void addStepperVelocityChangeListener (StepperVelocityChangeListener l)
+ {
+ synchronized (stepperVelocityChangeListeners)
+ {
+ stepperVelocityChangeListeners.add (l);
+ enableStepperVelocityChangeEvents (true);
+ }} private LinkedList stepperVelocityChangeListeners = new LinkedList ();
+ private long nativeStepperVelocityChangeHandler = 0;
+ public final void removeStepperVelocityChangeListener (StepperVelocityChangeListener l)
+ {
+ synchronized (stepperVelocityChangeListeners)
+ {
+ stepperVelocityChangeListeners.remove (l);
+ enableStepperVelocityChangeEvents (stepperVelocityChangeListeners.size () > 0);
+ }} private void fireStepperVelocityChange (StepperVelocityChangeEvent e)
+ {
+ synchronized (stepperVelocityChangeListeners)
+ {
+ for (Iterator it = stepperVelocityChangeListeners.iterator (); it.hasNext ();)
+ ((StepperVelocityChangeListener) it.next ()).stepperVelocityChanged (e);
+ }
+ }
+ private native void enableStepperVelocityChangeEvents (boolean b);
+ /**
+ * Adds a current change listener. The current change handler is a method that will be called when the stepper
+ * current has changed.
+ * <p>
+ * There is no limit on the number of current change handlers that can be registered for a particular Phidget.
+ * <p>
+ * Note that not all stepper controllers support current sensing.
+ *
+ * @param l An implemetation of the {@link com.phidgets.event.CurrentChangeListener CurrentChangeListener} interface
+ */
+ public final void addCurrentChangeListener (CurrentChangeListener l)
+ {
+ synchronized (currentChangeListeners)
+ {
+ currentChangeListeners.add (l);
+ enableCurrentChangeEvents (true);
+ }} private LinkedList currentChangeListeners = new LinkedList ();
+ private long nativeCurrentChangeHandler = 0;
+ public final void removeCurrentChangeListener (CurrentChangeListener l)
+ {
+ synchronized (currentChangeListeners)
+ {
+ currentChangeListeners.remove (l);
+ enableCurrentChangeEvents (currentChangeListeners.size () > 0);
+ }} private void fireCurrentChange (CurrentChangeEvent e)
+ {
+ synchronized (currentChangeListeners)
+ {
+ for (Iterator it = currentChangeListeners.iterator (); it.hasNext ();)
+ ((CurrentChangeListener) it.next ()).currentChanged (e);
+ }
+ }
+ private native void enableCurrentChangeEvents (boolean b);
+ /**
+ * Adds an input change listener. The input change handler is a method that will be called when an input on this
+ * Stepper Controller board has changed.
+ * <p>
+ * There is no limit on the number of input change handlers that can be registered for a particular Phidget.
+ *
+ * @param l An implemetation of the {@link com.phidgets.event.InputChangeListener InputChangeListener} interface
+ */
+ public final void addInputChangeListener (InputChangeListener l)
+ {
+ synchronized (inputChangeListeners)
+ {
+ inputChangeListeners.add (l);
+ enableInputChangeEvents (true);
+ }} private LinkedList inputChangeListeners = new LinkedList ();
+ private long nativeInputChangeHandler = 0;
+ public final void removeInputChangeListener (InputChangeListener l)
+ {
+ synchronized (inputChangeListeners)
+ {
+ inputChangeListeners.remove (l);
+ enableInputChangeEvents (inputChangeListeners.size () > 0);
+ }} private void fireInputChange (InputChangeEvent e)
+ {
+ synchronized (inputChangeListeners)
+ {
+ for (Iterator it = inputChangeListeners.iterator (); it.hasNext ();)
+ ((InputChangeListener) it.next ()).inputChanged (e);
+ }
+ }
+ private native void enableInputChangeEvents (boolean b);
+}
diff --git a/Java/com/phidgets/TemperatureSensorPhidget.java b/Java/com/phidgets/TemperatureSensorPhidget.java
new file mode 100644
index 0000000..baaa589
--- /dev/null
+++ b/Java/com/phidgets/TemperatureSensorPhidget.java
@@ -0,0 +1,213 @@
+
+/*
+ * Copyright 2006 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets;
+import java.util.Iterator;
+import java.util.LinkedList;
+import com.phidgets.event.*;
+/**
+ * This class represents a Phidget temperature Sensor. All methods
+ * to read temperaure data from the sensor are implemented in this class.
+ * <p>
+ * The Temperature Phidget consists of a thermocouple interface, and a temperature
+ * sensing IC, which is used to measure the temperature of the thermocouple cold junction
+ * and calibrate the thermocouple sensed temperature.
+ * <p>
+ * Both the thermocouple and temperature IC temperatures can be read. Value are returned in degrees celcius.
+ *
+ * @author Phidgets Inc.
+ */
+public final class TemperatureSensorPhidget extends Phidget
+{
+ public TemperatureSensorPhidget () throws PhidgetException
+ {
+ super (create ());
+ }
+ private static native long create () throws PhidgetException;
+
+ /**
+ * K-Type Thermocouple. This is used with {@link #getThermocoupleType getThermocoupleType} and {@link #setThermocoupleType setThermocoupleType}
+ */
+ public static final int PHIDGET_TEMPERATURE_SENSOR_K_TYPE = 1;
+ /**
+ * J-Type Thermocouple. This is used with {@link #getThermocoupleType getThermocoupleType} and {@link #setThermocoupleType setThermocoupleType}
+ */
+ public static final int PHIDGET_TEMPERATURE_SENSOR_J_TYPE = 2;
+ /**
+ * E-Type Thermocouple. This is used with {@link #getThermocoupleType getThermocoupleType} and {@link #setThermocoupleType setThermocoupleType}
+ */
+ public static final int PHIDGET_TEMPERATURE_SENSOR_E_TYPE = 3;
+ /**
+ * T-Type Thermocouple. This is used with {@link #getThermocoupleType getThermocoupleType} and {@link #setThermocoupleType setThermocoupleType}
+ */
+ public static final int PHIDGET_TEMPERATURE_SENSOR_T_TYPE = 4;
+
+ /**
+ * Returns the number of thermocouples.
+ * @return Number of inputs
+ */
+ public native int getTemperatureInputCount () throws PhidgetException;
+ /**
+ * @deprecated Replaced by
+ * {@link #getTemperatureInputCount}
+ */
+ public native int getSensorCount () throws PhidgetException;
+ /**
+ * Returns the temperature of a thermocouple. This value is returned in degrees celcius but can easily be converted into other units.
+ * This value will always be between {@link #getTemperatureMin getTemperatureMin} and {@link #getTemperatureMax getTemperatureMax}.
+ * The accuracy depends on the thermocouple used. The board is calibrated during manufacture.
+ * @param index Index of the thermocouple
+ * @return Temperature in derees celcius
+ * @throws PhidgetException If this Phidget is not opened and attached, or if a thermocouple sensor is not plugged into the board.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native double getTemperature (int index) throws PhidgetException;
+ /**
+ * Returns the maximum temperature that will be returned by a thermocouple input. This value depends on the thermocouple type.
+ * @param index Index of the thermocouple
+ * @return Maximum temperature in derees celcius
+ * @throws PhidgetException If this Phidget is not opened and attached.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native double getTemperatureMax (int index) throws PhidgetException;
+ /**
+ * Returns the minimum temperature that will be returned by a thermocouple input. This value depends on the thermocouple type.
+ * @param index Index of the thermocouple
+ * @return Minimum temperature in derees celcius
+ * @throws PhidgetException If this Phidget is not opened and attached.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native double getTemperatureMin (int index) throws PhidgetException;
+ /**
+ * Returns the temperature of the ambient sensor. This value is returned in degrees celcius but can easily be converted into other units.
+ * This value will always be between {@link #getAmbientTemperatureMin getAmbientTemperatureMin} and {@link #getAmbientTemperatureMax getAmbientTemperatureMax}.
+ * This is the temperature of the board at the thermocouple cold junction.
+ * @return Temperature in derees celcius
+ * @throws PhidgetException If this Phidget is not opened and attached.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native double getAmbientTemperature () throws PhidgetException;
+ /**
+ * Returns the maximum temperature that will be returned by the ambient sensor.
+ * @return Maximum ambient temperature in derees celcius
+ * @throws PhidgetException If this Phidget is not opened and attached.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native double getAmbientTemperatureMax () throws PhidgetException;
+ /**
+ * Returns the minimum temperature that will be returned by the ambient sensor.
+ * @return Minimum ambient temperature in derees celcius
+ * @throws PhidgetException If this Phidget is not opened and attached.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native double getAmbientTemperatureMin () throws PhidgetException;
+ /**
+ * Returns the potential of a thermocouple input. This value is returned in millivolts.
+ * This value will always be between {@link #getPotentialMin getPotentialMin} and {@link #getPotentialMax getPotentialMax}.
+ * This is very accurate, as it is a raw value from the A/D. This is the value that is internally used to calculate temperature in the library.
+ * @param index Index of the thermocouple
+ * @return Potential in millivolts
+ * @throws PhidgetException If this Phidget is not opened and attached.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native double getPotential (int index) throws PhidgetException;
+ /**
+ * Returns the maximum potential that will be returned by a thermocouple input.
+ * @param index Index of the thermocouple
+ * @return Maximum potential in millivolts
+ * @throws PhidgetException If this Phidget is not opened and attached.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native double getPotentialMax (int index) throws PhidgetException;
+ /**
+ * Returns the minimum potential that will be returned by a thermocouple input.
+ * @param index Index of the thermocouple
+ * @return Minimum potential in millivolts
+ * @throws PhidgetException If this Phidget is not opened and attached.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native double getPotentialMin (int index) throws PhidgetException;
+ /**
+ * Sets the change trigger for an input. This is the ammount by which the sensed temperature must
+ * change between TemperatureChangeEvents. By default this is set to 0.5.
+ * @param index Input
+ * @param newVal Trigger
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is out of range.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native void setTemperatureChangeTrigger (int index, double newVal) throws PhidgetException;
+ /**
+ * Returns the change trigger for an input. This is the ammount by which the sensed temperature must
+ * change between TemperatureChangeEvents. By default this is set to 0.5.
+ * @param index Input
+ * @return Trigger
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is out of range.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native double getTemperatureChangeTrigger (int index) throws PhidgetException;
+ /**
+ * Returns the thermocouple type for an input.
+ * The possible values for type are {@link #PHIDGET_TEMPERATURE_SENSOR_K_TYPE PHIDGET_TEMPERATURE_SENSOR_K_TYPE},
+ * {@link #PHIDGET_TEMPERATURE_SENSOR_J_TYPE PHIDGET_TEMPERATURE_SENSOR_J_TYPE}, {@link #PHIDGET_TEMPERATURE_SENSOR_E_TYPE PHIDGET_TEMPERATURE_SENSOR_E_TYPE} and
+ * {@link #PHIDGET_TEMPERATURE_SENSOR_T_TYPE PHIDGET_TEMPERATURE_SENSOR_T_TYPE}
+ * @param index Input
+ * @return Thermocouple Type
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is out of range.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native int getThermocoupleType (int index) throws PhidgetException;
+ /**
+ * Sets the thermocouple type for an input. The Phidget Temperature Sensor board can be used with K, E, J and T-Type Thermocouples.
+ * Support for other thermocouple types, and voltage sources other then thermocouples in the valid range (between {@link #getPotentialMin getPotentialMin} and {@link #getPotentialMax getPotentialMax}) can
+ * be achieved using {@link #getPotential getPotential}.
+ * <p>
+ * The possible values for type are {@link #PHIDGET_TEMPERATURE_SENSOR_K_TYPE PHIDGET_TEMPERATURE_SENSOR_K_TYPE},
+ * {@link #PHIDGET_TEMPERATURE_SENSOR_J_TYPE PHIDGET_TEMPERATURE_SENSOR_J_TYPE}, {@link #PHIDGET_TEMPERATURE_SENSOR_E_TYPE PHIDGET_TEMPERATURE_SENSOR_E_TYPE} and
+ * {@link #PHIDGET_TEMPERATURE_SENSOR_T_TYPE PHIDGET_TEMPERATURE_SENSOR_T_TYPE}
+ * <p>
+ * By default, type is set to {@link #PHIDGET_TEMPERATURE_SENSOR_K_TYPE PHIDGET_TEMPERATURE_SENSOR_K_TYPE}.
+ * @param index Input
+ * @param type Thermocouple Type
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is out of range.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native void setThermocoupleType (int index, int type) throws PhidgetException;
+
+ private final void enableDeviceSpecificEvents (boolean b)
+ {
+ enableTemperatureChangeEvents (b && temperatureChangeListeners.size () > 0);
+ }
+ /**
+ * Adds a temperature change listener. The temperature change handler is a method that will be called when the temperature
+ * has changed by at least the {@link #getTemperatureChangeTrigger(int) Trigger} that has been set.
+ * <p>
+ * There is no limit on the number of temperature change handlers that can be registered for a particular Phidget.
+ *
+ * @param l An implemetation of the {@link com.phidgets.event.TemperatureChangeListener TemperatureChangeListener} interface
+ */
+ public final void addTemperatureChangeListener (TemperatureChangeListener l)
+ {
+ synchronized (temperatureChangeListeners)
+ {
+ temperatureChangeListeners.add (l);
+ enableTemperatureChangeEvents (true);
+ }} private LinkedList temperatureChangeListeners = new LinkedList ();
+ private long nativeTemperatureChangeHandler = 0;
+ public final void removeTemperatureChangeListener (TemperatureChangeListener l)
+ {
+ synchronized (temperatureChangeListeners)
+ {
+ temperatureChangeListeners.remove (l);
+ enableTemperatureChangeEvents (temperatureChangeListeners.size () > 0);
+ }} private void fireTemperatureChange (TemperatureChangeEvent e)
+ {
+ synchronized (temperatureChangeListeners)
+ {
+ for (Iterator it = temperatureChangeListeners.iterator (); it.hasNext ();)
+ ((TemperatureChangeListener) it.next ()).temperatureChanged (e);
+ }
+ }
+ private native void enableTemperatureChangeEvents (boolean b);
+}
diff --git a/Java/com/phidgets/TextLCDPhidget.java b/Java/com/phidgets/TextLCDPhidget.java
new file mode 100644
index 0000000..ac4c500
--- /dev/null
+++ b/Java/com/phidgets/TextLCDPhidget.java
@@ -0,0 +1,278 @@
+
+/*
+ * Copyright 2011 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets;
+import java.util.Iterator;
+import java.util.LinkedList;
+import com.phidgets.event.*;
+/**
+ * This class represents a Phidget Text LCD. All methods
+ * to control the Text LCD are implemented in this class.
+ * <p>
+ * The TextLCD Phidget consists of a Vacuum Fluorescent display that is capable of
+ * displaying Standard as well as custom characters in multiple rows.
+ *
+ * @author Phidgets Inc.
+ */
+public final class TextLCDPhidget extends Phidget
+{
+ public TextLCDPhidget () throws PhidgetException
+ {
+ super (create ());
+ }
+ private static native long create () throws PhidgetException;
+ /**
+ * No screens attached. This is used with {@link #getScreenSize() getScreenSize} and {@link #setScreenSize(int) setScreenSize}
+ */
+ public static final int PHIDGET_TEXTLCD_SCREEN_NONE = 1;
+ /**
+ * 1 row, 8 column screen. This is used with {@link #getScreenSize() getScreenSize} and {@link #setScreenSize(int) setScreenSize}
+ */
+ public static final int PHIDGET_TEXTLCD_SCREEN_1x8 = 2;
+ /**
+ * 2 row, 8 column screen. This is used with {@link #getScreenSize() getScreenSize} and {@link #setScreenSize(int) setScreenSize}
+ */
+ public static final int PHIDGET_TEXTLCD_SCREEN_2x8 = 3;
+ /**
+ * 1 row, 16 column screen. This is used with {@link #getScreenSize() getScreenSize} and {@link #setScreenSize(int) setScreenSize}
+ */
+ public static final int PHIDGET_TEXTLCD_SCREEN_1x16 = 4;
+ /**
+ * 2 row, 16 column screen. This is used with {@link #getScreenSize() getScreenSize} and {@link #setScreenSize(int) setScreenSize}
+ */
+ public static final int PHIDGET_TEXTLCD_SCREEN_2x16 = 5;
+ /**
+ * 4 row, 16 column screen. This is used with {@link #getScreenSize() getScreenSize} and {@link #setScreenSize(int) setScreenSize}
+ */
+ public static final int PHIDGET_TEXTLCD_SCREEN_4x16 = 6;
+ /**
+ * 2 row, 20 column screen. This is used with {@link #getScreenSize() getScreenSize} and {@link #setScreenSize(int) setScreenSize}
+ */
+ public static final int PHIDGET_TEXTLCD_SCREEN_2x20 = 7;
+ /**
+ * 4 row, 20 column screen. This is used with {@link #getScreenSize() getScreenSize} and {@link #setScreenSize(int) setScreenSize}
+ */
+ public static final int PHIDGET_TEXTLCD_SCREEN_4x20 = 8;
+ /**
+ * 2 row, 24 column screen. This is used with {@link #getScreenSize() getScreenSize} and {@link #setScreenSize(int) setScreenSize}
+ */
+ public static final int PHIDGET_TEXTLCD_SCREEN_2x24 = 9;
+ /**
+ * 1 row, 40 column screen. This is used with {@link #getScreenSize() getScreenSize} and {@link #setScreenSize(int) setScreenSize}
+ */
+ public static final int PHIDGET_TEXTLCD_SCREEN_1x40 = 10;
+ /**
+ * 2 row, 40 column screen. This is used with {@link #getScreenSize() getScreenSize} and {@link #setScreenSize(int) setScreenSize}
+ */
+ public static final int PHIDGET_TEXTLCD_SCREEN_2x40 = 11;
+ /**
+ * 4 row, 40 column screen. This is used with {@link #getScreenSize() getScreenSize} and {@link #setScreenSize(int) setScreenSize}
+ */
+ public static final int PHIDGET_TEXTLCD_SCREEN_4x40 = 12;
+ /**
+ * Unknown screen size. This is used with {@link #getScreenSize() getScreenSize} and {@link #setScreenSize(int) setScreenSize}
+ */
+ public static final int PHIDGET_TEXTLCD_SCREEN_UNKNOWN = 13;
+ /**
+ * Returns the number of rows available on the display.
+ * @return Number of rows
+ * @throws PhidgetException If this Phidget is not opened and attached.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native int getRowCount () throws PhidgetException;
+ /**
+ * Returns the number of columns (characters per row) available on the display. This value is
+ * the same for every row.
+ * @return Number of columns
+ * @throws PhidgetException If this Phidget is not opened and attached.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native int getColumnCount () throws PhidgetException;
+ /**
+ * Returns the number of screens supported by the TextLCD. Not all TextLCDs support this method.
+ * @return Number of screens.
+ * @throws PhidgetException If this Phidget is not opened and attached.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native int getScreenCount () throws PhidgetException;
+ /**
+ * Returns the active screen. Not all TextLCDs support this method.
+ * @return active screen
+ * @throws PhidgetException If this Phidget is not opened and attached, or screen is not supported.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native int getScreen () throws PhidgetException;
+ /**
+ * Sets the active screen. All other API calls depend on this being called first to select the screen that subsequent calls affect.
+ * When making calls from multiple threads, selecting the screen should be synchronized with setting screen properties in order to avoid
+ * having messages go to the wrong display. Not all TextLCDs support this method.
+ * @param screen Screen
+ * @throws PhidgetException If this Phidget is not opened and attached, the screen number is out of range, or screen is not supported.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native void setScreen (int screen) throws PhidgetException;
+
+ /**
+ * Returns the screen size for the active TextLCD display. The TextLCD Adapter supports a pre-defined set of screen sizes to choose from.
+ * By default, all screens are set to {@link #PHIDGET_TEXTLCD_SCREEN_NONE PHIDGET_TEXTLCD_SCREEN_NONE}.
+ * Not all TextLCDs support this method.
+ * <p>
+ * The possible values for screen size are {@link #PHIDGET_TEXTLCD_SCREEN_NONE PHIDGET_TEXTLCD_SCREEN_NONE},
+ * {@link #PHIDGET_TEXTLCD_SCREEN_1x8 PHIDGET_TEXTLCD_SCREEN_1x8}, {@link #PHIDGET_TEXTLCD_SCREEN_2x8 PHIDGET_TEXTLCD_SCREEN_2x8},
+ * {@link #PHIDGET_TEXTLCD_SCREEN_1x16 PHIDGET_TEXTLCD_SCREEN_1x16}, {@link #PHIDGET_TEXTLCD_SCREEN_2x16 PHIDGET_TEXTLCD_SCREEN_2x16},
+ * {@link #PHIDGET_TEXTLCD_SCREEN_4x16 PHIDGET_TEXTLCD_SCREEN_4x16}, {@link #PHIDGET_TEXTLCD_SCREEN_2x20 PHIDGET_TEXTLCD_SCREEN_2x20},
+ * {@link #PHIDGET_TEXTLCD_SCREEN_4x20 PHIDGET_TEXTLCD_SCREEN_4x20}, {@link #PHIDGET_TEXTLCD_SCREEN_2x24 PHIDGET_TEXTLCD_SCREEN_2x24},
+ * {@link #PHIDGET_TEXTLCD_SCREEN_1x40 PHIDGET_TEXTLCD_SCREEN_1x40}, {@link #PHIDGET_TEXTLCD_SCREEN_2x40 PHIDGET_TEXTLCD_SCREEN_2x40},
+ * {@link #PHIDGET_TEXTLCD_SCREEN_4x40 PHIDGET_TEXTLCD_SCREEN_4x40}, {@link #PHIDGET_TEXTLCD_SCREEN_UNKNOWN PHIDGET_TEXTLCD_SCREEN_UNKNOWN}
+ * <p>
+ * By default, all screens are set to {@link #PHIDGET_TEXTLCD_SCREEN_NONE PHIDGET_TEXTLCD_SCREEN_NONE}
+ * <p>
+ * @return screen size
+ * @throws PhidgetException If this Phidget is not opened and attached, or screen size is not supported.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native int getScreenSize () throws PhidgetException;
+ /**
+ * Sets the screen size for the active TextLCD display. The TextLCD Adapter supports a pre-defined set of screen sizes to choose from.
+ * This method must always be called when trying to write text to a display.
+ * Not all TextLCDs support this method.
+ * @param screenSize Screen size
+ * The possible values for screen size are {@link #PHIDGET_TEXTLCD_SCREEN_NONE PHIDGET_TEXTLCD_SCREEN_NONE},
+ * {@link #PHIDGET_TEXTLCD_SCREEN_1x8 PHIDGET_TEXTLCD_SCREEN_1x8}, {@link #PHIDGET_TEXTLCD_SCREEN_2x8 PHIDGET_TEXTLCD_SCREEN_2x8},
+ * {@link #PHIDGET_TEXTLCD_SCREEN_1x16 PHIDGET_TEXTLCD_SCREEN_1x16}, {@link #PHIDGET_TEXTLCD_SCREEN_2x16 PHIDGET_TEXTLCD_SCREEN_2x16},
+ * {@link #PHIDGET_TEXTLCD_SCREEN_4x16 PHIDGET_TEXTLCD_SCREEN_4x16}, {@link #PHIDGET_TEXTLCD_SCREEN_2x20 PHIDGET_TEXTLCD_SCREEN_2x20},
+ * {@link #PHIDGET_TEXTLCD_SCREEN_4x20 PHIDGET_TEXTLCD_SCREEN_4x20}, {@link #PHIDGET_TEXTLCD_SCREEN_2x24 PHIDGET_TEXTLCD_SCREEN_2x24},
+ * {@link #PHIDGET_TEXTLCD_SCREEN_1x40 PHIDGET_TEXTLCD_SCREEN_1x40}, {@link #PHIDGET_TEXTLCD_SCREEN_2x40 PHIDGET_TEXTLCD_SCREEN_2x40},
+ * {@link #PHIDGET_TEXTLCD_SCREEN_4x40 PHIDGET_TEXTLCD_SCREEN_4x40}, {@link #PHIDGET_TEXTLCD_SCREEN_UNKNOWN PHIDGET_TEXTLCD_SCREEN_UNKNOWN}
+ * <p>
+ * By default, all screens are set to {@link #PHIDGET_TEXTLCD_SCREEN_NONE PHIDGET_TEXTLCD_SCREEN_NONE}
+ * <p>
+ * @throws PhidgetException If this Phidget is not opened and attached, the screen number is out of range, or screen size is not supported.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native void setScreenSize (int screenSize) throws PhidgetException;
+ /**
+ * Returns the contrast of the display. This is the contrast of the entire display.
+ * @return Current contrast
+ * @throws PhidgetException If this Phidget is not opened and attached.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native int getContrast () throws PhidgetException;
+ /**
+ * Sets the contrast of the display. The valid range is 0-255. Changing the contrast can increase the readability
+ * of the display in certain viewing situation, such as at an odd angle.
+ * @param contrast New contrast to set
+ * @throws PhidgetException If this Phidget is not opened and attached, or the contrast value is out of range.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native void setContrast (int contrast) throws PhidgetException;
+ /**
+ * Returns the brightness of the display. This is the brightness of the backlight. Not all TextLCDs support this method.
+ * @return Current brightness
+ * @throws PhidgetException If this Phidget is not opened and attached.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached, or brightness is not supported.
+ */
+ public native int getBrightness () throws PhidgetException;
+ /**
+ * Sets the brightness of the display. The valid range is 0-255. Changing the brightness can increase the readability of the display in certain viewing situation, such as at an odd angle.
+ * Not all TextLCDs support this method.
+ * @param brightness New brightness to set
+ * @throws PhidgetException If this Phidget is not opened and attached, or the brightness value is out of range, or brightness is not supported.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native void setBrightness (int brightness) throws PhidgetException;
+ /**
+ * Returns the status of the backlight. True indicated that the backlight is on, False indicated that it is off.
+ * The backlight is by default turned on.
+ * @return Status of the backlight
+ * @throws PhidgetException If this Phidget is not opened and attached.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native boolean getBacklight () throws PhidgetException;
+ /**
+ * Sets the status of the backlight. True turns the backlight on, False turns it off.
+ * The backlight is by default turned on.
+ * @param backlight New backlight state
+ * @throws PhidgetException If this Phidget is not opened and attached.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native void setBacklight (boolean backlight) throws PhidgetException;
+ /**
+ * Returns the status of the cursor. True turns the cursor is on, False turns it off.
+ * The cursor is an underscore which appears directly to the right of the last entered character
+ * on the display. The cursor is by default disabled.
+ * @return Status of the cursor
+ * @throws PhidgetException If this Phidget is not opened and attached.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native boolean getCursor () throws PhidgetException;
+ /**
+ * Sets the state of the cursor. True indicates that the cursor on, False indicates that it is off.
+ * The cursor is an underscore which appears directly to the right of the last entered character
+ * on the display. The cursor is by default disabled.
+ * @param cursor New cursor state
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the cursor has not been set
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native void setCursor (boolean cursor) throws PhidgetException;
+ /**
+ * Returns the status of the cursor blink. True turns the cursor blink on, False turns it off.
+ * The cursor blink is an flashing box which appears directly to the right of the last entered character
+ * on the display, in the same spot as the cursor if it is enabled. The cursor blink is by default disabled.
+ * @return Status of the cursor blink
+ * @throws PhidgetException If this Phidget is not opened and attached.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native boolean getCursorBlink () throws PhidgetException;
+ /**
+ * Sets the state of the cursor blink. True indicates that the cursor blink is on, False indicates that it is off.
+ * The cursor blink is an flashing box which appears directly to the right of the last entered character
+ * on the display, in the same spot as the cursor if it is enabled. The cursor blink is by default disabled.
+ * @param cursorblink New cursor blink state
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the cursor has not been set.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native void setCursorBlink (boolean cursorblink) throws PhidgetException;
+ /**
+ * Sets the display string of a certain row.
+ * @param index row
+ * @param text String
+ * @throws PhidgetException If this Phidget is not opened and attached, if the string is too long, or if the row is invalid.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native void setDisplayString (int index, String text) throws PhidgetException;
+ /**
+ * Sets the character to display at a certain row and column.
+ * @param row row
+ * @param column column
+ * @param character character
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the row or column is invalid.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native void setDisplayCharacter (int row, int column, char character) throws PhidgetException;
+ /**
+ * Sets a custom character. You can set up to 8 custom characters, each one is completely defined by two integers, and gets
+ * stored in the character display until power is removed, whence they must be re-programmed. The characters lie in positions 8-15, and
+ * can be displayed by sending these codes to setDisplayString in amongst standard ASCII characters. See the TextLCD Java example for
+ * more information.
+ * @param index position ( 8-15 )
+ * @param param1 first half of the character code
+ * @param param2 second half of the character code
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is invalid.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native void setCustomCharacter (int index, int param1, int param2) throws PhidgetException;
+ /**
+ * Initializes the active TextLCD Display. This runs an initialization routine which sets up and clears the display. This can be used for
+ * activating a display that was plugged in after the TextLCD Adapter was attached, to clear the display after setting/getting the screen size,
+ * and to re-initialize a display if it has become corrupted(display not working). Not all TextLCDs supported this method.
+ * @throws PhidgetException If this Phidget is not opened and attached, or initialize is not supported.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native void initialize () throws PhidgetException;
+ private final void enableDeviceSpecificEvents (boolean b)
+ {
+ }
+}
diff --git a/Java/com/phidgets/TextLEDPhidget.java b/Java/com/phidgets/TextLEDPhidget.java
new file mode 100644
index 0000000..a2f39c8
--- /dev/null
+++ b/Java/com/phidgets/TextLEDPhidget.java
@@ -0,0 +1,68 @@
+
+/*
+ * Copyright 2006 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets;
+import java.util.Iterator;
+import java.util.LinkedList;
+import com.phidgets.event.*;
+/**
+ * This class represents a Phidget Text LED. All methods
+ * to control the Text LED are implemented in this class.
+ * <p>
+ * The Text LED is a Phidget that displays text and numerals on LED
+ * numeric display in rows. The number of rows and size of each row depends on
+ * your configuration.
+ *
+ * @author Phidgets Inc.
+ */
+public final class TextLEDPhidget extends Phidget
+{
+ public TextLEDPhidget () throws PhidgetException
+ {
+ super (create ());
+ }
+ private static native long create () throws PhidgetException;
+ /**
+ * Returns the number of rows. This returns the maximum number of rows supported by the device, not neccessarily
+ * the number of rows actually available with your coniguration.
+ * @return rows
+ * @throws PhidgetException If this Phidget is not opened and attached.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native int getRowCount () throws PhidgetException;
+ /**
+ * Returns the number of columns (Characters per row). This returns the maximum number of columns supported by the device, not neccessarily
+ * the number of columns actually available with your coniguration.
+ * @return columns
+ * @throws PhidgetException If this Phidget is not opened and attached.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native int getColumnCount () throws PhidgetException;
+ /**
+ * Returns the bringhtness. This is the brightneww of all rows. The Default brightness is 100.
+ * @return brightness
+ * @throws PhidgetException If this Phidget is not opened and attached.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native int getBrightness () throws PhidgetException;
+ /**
+ * Sets the brightness of all rows. The valid range is 0-100.
+ * @param brightness brightness
+ * @throws PhidgetException If this Phidget is not opened and attached, or the brightness value is out of range.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native void setBrightness (int brightness) throws PhidgetException;
+ /**
+ * Sets the display string of a certain row. If the string is longer then the row, it will be truncated.
+ * @param index Row
+ * @param text String
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the row is out of range.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native void setDisplayString (int index, String text) throws PhidgetException;
+ private final void enableDeviceSpecificEvents (boolean b)
+ {
+ }
+}
diff --git a/Java/com/phidgets/WeightSensorPhidget.java b/Java/com/phidgets/WeightSensorPhidget.java
new file mode 100644
index 0000000..b2bd9e8
--- /dev/null
+++ b/Java/com/phidgets/WeightSensorPhidget.java
@@ -0,0 +1,89 @@
+
+/*
+ * Copyright 2006 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets;
+import java.util.Iterator;
+import java.util.LinkedList;
+import com.phidgets.event.*;
+/**
+ * This class represents a Phidget Weight Sensor. All methods
+ * to read weight data from the weight sensor are implemented in this class.
+ * <p>
+ * The Phidget Weight Sensor is simply an electronic scale with a USB interface.
+ * It provides one weight value, in kg.
+ *
+ * @author Phidget Inc.
+ */
+public final class WeightSensorPhidget extends Phidget
+{
+ public WeightSensorPhidget () throws PhidgetException
+ {
+ super (create ());
+ }
+ private static native long create () throws PhidgetException;
+ /**
+ * Returns the sensed weight in kg. This weight is in kg (kilograms), but can
+ * easily be converted into other units. The accuracy, sesitivity and range depends on the scale and version.
+ *
+ * @return The sensed weight
+ * @throws PhidgetException If this Phidget is not opened and attached.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native double getWeight () throws PhidgetException;
+ /**
+ * Sets the weight change trigger. This is the ammount by which the sensed weight must
+ * change between WeightChangeEvents. By default this is set to 5.
+ *
+ * @param newVal The new trigger value
+ * @throws PhidgetException If this Phidget is not opened and attached.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native void setWeightChangeTrigger (double newVal) throws PhidgetException;
+ /**
+ * Returns the weight change trigger. This is the ammount by which the sensed weight must
+ * change between WeightChangeEvents. By default this is set to 5.
+ *
+ * @return The trigger value
+ * @throws PhidgetException If this Phidget is not opened and attached.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ public native double getWeightChangeTrigger () throws PhidgetException;
+
+ private final void enableDeviceSpecificEvents (boolean b)
+ {
+ enableWeightChangeEvents (b && weightChangeListeners.size () > 0);
+ }
+ /**
+ * Adds a weight change listener. The weight change handler is a method that will be called when the weight
+ * has changed by at least the {@link #getWeightChangeTrigger() Trigger} that has been set.
+ * <p>
+ * There is no limit on the number of weight change handlers that can be registered for a particular Phidget.
+ *
+ * @param l An implemetation of the {@link com.phidgets.event.WeightChangeListener WeightChangeListener} interface
+ */
+ public final void addWeightChangeListener (WeightChangeListener l)
+ {
+ synchronized (weightChangeListeners)
+ {
+ weightChangeListeners.add (l);
+ enableWeightChangeEvents (true);
+ }} private LinkedList weightChangeListeners = new LinkedList ();
+ private long nativeWeightChangeHandler = 0;
+ public final void removeWeightChangeListener (WeightChangeListener l)
+ {
+ synchronized (weightChangeListeners)
+ {
+ weightChangeListeners.remove (l);
+ enableWeightChangeEvents (weightChangeListeners.size () > 0);
+ }} private void fireWeightChange (WeightChangeEvent e)
+ {
+ synchronized (weightChangeListeners)
+ {
+ for (Iterator it = weightChangeListeners.iterator (); it.hasNext ();)
+ ((WeightChangeListener) it.next ()).weightChanged (e);
+ }
+ }
+ private native void enableWeightChangeEvents (boolean b);
+}
diff --git a/Java/com/phidgets/event/AccelerationChangeEvent.java b/Java/com/phidgets/event/AccelerationChangeEvent.java
new file mode 100644
index 0000000..92f9c69
--- /dev/null
+++ b/Java/com/phidgets/event/AccelerationChangeEvent.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2006 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets.event;
+
+import com.phidgets.Phidget;
+
+/**
+ * This class represents the data for an AccelerationChangeEvent.
+ *
+ * @author Phidgets Inc.
+ */
+public class AccelerationChangeEvent
+{
+ Phidget source;
+ int index;
+ double value;
+
+ /**
+ * Class constructor. This is called internally by the phidget library when creating this event.
+ *
+ * @param source the Phidget object from which this event originated
+ */
+ public AccelerationChangeEvent(Phidget source, int index, double value) {
+ this.source = source;
+ this.index = index;
+ this.value = value;
+ }
+
+ /**
+ * Returns the source Phidget of this event. This is a reference to the Phidget object from which this
+ * event was called. This object can be cast into a specific type of Phidget object to call specific
+ * device calls on it.
+ *
+ * @return the event caller
+ */
+ public Phidget getSource() {
+ return source;
+ }
+
+ /**
+ * Returns the index of the axis.
+ *
+ * @return the index of the axis
+ */
+ public int getIndex() {
+ return index;
+ }
+
+ /**
+ * Returns the acceleration. This is returned in g's
+ *
+ * @return the acceleration of the axis
+ */
+ public double getValue() {
+ return value;
+ }
+
+ /**
+ * Returns a string containing information about the event.
+ *
+ * @return an informative event string
+ */
+ public String toString() {
+ return source.toString() + " Acceleration " + index + " changed to "
+ + value;
+ }
+}
diff --git a/Java/com/phidgets/event/AccelerationChangeListener.java b/Java/com/phidgets/event/AccelerationChangeListener.java
new file mode 100644
index 0000000..b97172e
--- /dev/null
+++ b/Java/com/phidgets/event/AccelerationChangeListener.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2006 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets.event;
+
+/**
+ * This interface represents a AccelerationChangeEvent. This event originates from the Phidget Accelerometer
+ *
+ * @author Phidgets Inc.
+ */
+public interface AccelerationChangeListener
+{
+ /**
+ * This method is called with the event data when a new event arrives.
+ *
+ * @param ae the event data object containing event data
+ */
+ public void accelerationChanged(AccelerationChangeEvent ae);
+}
diff --git a/Java/com/phidgets/event/AttachEvent.java b/Java/com/phidgets/event/AttachEvent.java
new file mode 100644
index 0000000..eecb7b0
--- /dev/null
+++ b/Java/com/phidgets/event/AttachEvent.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2006 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets.event;
+
+import com.phidgets.Phidget;
+
+/**
+ * This class represents the data for a AttachEvent.
+ *
+ * @author Phidgets Inc.
+ */
+public class AttachEvent
+{
+ Phidget source;
+
+ /**
+ * Class constructor. This is called internally by the phidget library when creating this event.
+ *
+ * @param source the Phidget object from which this event originated
+ */
+ public AttachEvent(Phidget source) {
+ this.source = source;
+ }
+
+ /**
+ * Returns the source Phidget of this event. This is a reference to the Phidget object from which this
+ * event was called. This object can be cast into a specific type of Phidget object to call specific
+ * device calls on it.
+ *
+ * @return the event caller
+ */
+ public Phidget getSource() {
+ return source;
+ }
+
+ /**
+ * Returns a string containing information about the event.
+ *
+ * @return an informative event string
+ */
+ public String toString() {
+ return source.toString();
+ }
+}
diff --git a/Java/com/phidgets/event/AttachListener.java b/Java/com/phidgets/event/AttachListener.java
new file mode 100644
index 0000000..5fe8c00
--- /dev/null
+++ b/Java/com/phidgets/event/AttachListener.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2006 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets.event;
+
+/**
+ * This interface represents a AttachEvent. This event originates from all Phidgets.
+ *
+ * @author Phidgets Inc.
+ */
+public interface AttachListener
+{
+ /**
+ * This method is called with the event data when a new event arrives.
+ *
+ * @param ae the event data object containing event data
+ */
+ public void attached(AttachEvent ae);
+}
diff --git a/Java/com/phidgets/event/BackEMFUpdateEvent.java b/Java/com/phidgets/event/BackEMFUpdateEvent.java
new file mode 100644
index 0000000..7dace73
--- /dev/null
+++ b/Java/com/phidgets/event/BackEMFUpdateEvent.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2011 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets.event;
+
+import com.phidgets.Phidget;
+
+/**
+ * This class represents the data for a BackEMFUpdateEvent.
+ *
+ * @author Phidgets Inc.
+ */
+public class BackEMFUpdateEvent
+{
+ Phidget source;
+ int index;
+ double voltage;
+
+ /**
+ * Class constructor. This is called internally by the phidget library when creating this event.
+ *
+ * @param source the Phidget object from which this event originated
+ */
+ public BackEMFUpdateEvent(Phidget source, int index, double voltage)
+ {
+ this.source = source;
+ this.index = index;
+ this.voltage = voltage;
+ }
+
+ /**
+ * Returns the source Phidget of this event. This is a reference to the Phidget object from which this
+ * event was called. This object can be cast into a specific type of Phidget object to call specific
+ * device calls on it.
+ *
+ * @return the event caller
+ */
+ public Phidget getSource() {
+ return source;
+ }
+
+ /**
+ * Returns the index of the motor.
+ *
+ * @return the index of the motor
+ */
+ public int getIndex() {
+ return index;
+ }
+
+ /**
+ * Returns the backEMF value.
+ *
+ * @return the backEMF value
+ */
+ public double getVoltage() {
+ return voltage;
+ }
+
+ /**
+ * Returns a string containing information about the event.
+ *
+ * @return an informative event string
+ */
+ public String toString() {
+ return source.toString() + " BackEMF Value " + index + " is "
+ + voltage;
+ }
+}
diff --git a/Java/com/phidgets/event/BackEMFUpdateListener.java b/Java/com/phidgets/event/BackEMFUpdateListener.java
new file mode 100644
index 0000000..9a99a97
--- /dev/null
+++ b/Java/com/phidgets/event/BackEMFUpdateListener.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2011 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets.event;
+
+/**
+ * This interface represents a BackEMFUpdateEvent. This event originates from the
+ * Phidget Motor Control. This event is not supported by all Motor Controllers.
+ *
+ * @author Phidgets Inc.
+ */
+public interface BackEMFUpdateListener
+{
+ /**
+ * This method is called with the event data every 16ms, when back EMF sensing is enabled for that motor.
+ *
+ * @param ae the event data object containing event data
+ */
+ public void backEMFUpdated(BackEMFUpdateEvent ae);
+}
diff --git a/Java/com/phidgets/event/BridgeDataEvent.java b/Java/com/phidgets/event/BridgeDataEvent.java
new file mode 100644
index 0000000..3dd1578
--- /dev/null
+++ b/Java/com/phidgets/event/BridgeDataEvent.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2011 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets.event;
+
+import com.phidgets.Phidget;
+
+/**
+ * This class represents the data for a BridgeDataEvent.
+ *
+ * @author Phidgets Inc.
+ */
+public class BridgeDataEvent
+{
+ Phidget source;
+ int index;
+ double value;
+
+ /**
+ * Class constructor. This is called internally by the phidget library when creating this event.
+ *
+ * @param source the Phidget object from which this event originated
+ */
+ public BridgeDataEvent(Phidget source, int index, double value) {
+ this.source = source;
+ this.index = index;
+ this.value = value;
+ }
+
+ /**
+ * Returns the source Phidget of this event. This is a reference to the Phidget object from which this
+ * event was called. This object can be cast into a specific type of Phidget object to call specific
+ * device calls on it.
+ *
+ * @return the event caller
+ */
+ public Phidget getSource() {
+ return source;
+ }
+
+ /**
+ * Returns the index of the bridge.
+ *
+ * @return the index of the bridge
+ */
+ public int getIndex() {
+ return index;
+ }
+
+ /**
+ * Retuns the bridge value, in mV/V.
+ *
+ * @return the bridge value
+ */
+ public double getValue() {
+ return value;
+ }
+
+ /**
+ * Returns a string containing information about the event.
+ *
+ * @return an informative event string
+ */
+ public String toString() {
+ return source.toString() + " bridge " + index + " value changed to "
+ + value;
+ }
+}
diff --git a/Java/com/phidgets/event/BridgeDataListener.java b/Java/com/phidgets/event/BridgeDataListener.java
new file mode 100644
index 0000000..de2f993
--- /dev/null
+++ b/Java/com/phidgets/event/BridgeDataListener.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2011 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets.event;
+/**
+ * This interface represents a BridgeDataEvent. This event originates from the Phidget Bridge
+ *
+ * @author Phidgets Inc.
+ */
+public interface BridgeDataListener
+{
+ /**
+ * This method is called with the event data when a new event arrives. The event is issued at the specified data rate, for
+ * each enabled bridge.
+ *
+ * @param ae the event data object containing event data
+ */
+ public void bridgeData(BridgeDataEvent ae);
+}
diff --git a/Java/com/phidgets/event/CodeEvent.java b/Java/com/phidgets/event/CodeEvent.java
new file mode 100644
index 0000000..0cb5336
--- /dev/null
+++ b/Java/com/phidgets/event/CodeEvent.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2006 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets.event;
+
+import com.phidgets.Phidget;
+import com.phidgets.IRCode;
+
+/**
+ * This class represents the data for a CodeEvent.
+ *
+ * @author Phidgets Inc.
+ */
+public class CodeEvent
+{
+ Phidget source;
+ IRCode code;
+ boolean repeat;
+
+ /**
+ * Class constructor. This is called internally by the phidget library when creating this event.
+ *
+ * @param source the Phidget object from which this event originated
+ * @param code the IR code
+ * @param repeat whether the code is a repeat
+ */
+ public CodeEvent(Phidget source, IRCode code, boolean repeat)
+ {
+ this.source = source;
+ this.code = code;
+ this.repeat = repeat;
+ }
+
+ /**
+ * Returns the source Phidget of this event. This is a reference to the Phidget object from which this
+ * event was called. This object can be cast into a specific type of Phidget object to call specific
+ * device calls on it.
+ *
+ * @return the event caller
+ */
+ public Phidget getSource() {
+ return source;
+ }
+
+ /**
+ * Returns the code.
+ *
+ * @return the code
+ */
+ public IRCode getCode() {
+ return code;
+ }
+
+ /**
+ * Returns the repeat identifier.
+ *
+ * @return whether this is a repeat
+ */
+ public boolean getRepeat() {
+ return repeat;
+ }
+
+ /**
+ * Returns a string containing information about the event.
+ *
+ * @return an informative event string
+ */
+ public String toString() {
+ return source.toString() + " Code: "
+ + code.toString();
+ }
+}
diff --git a/Java/com/phidgets/event/CodeListener.java b/Java/com/phidgets/event/CodeListener.java
new file mode 100644
index 0000000..30bdde1
--- /dev/null
+++ b/Java/com/phidgets/event/CodeListener.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2006 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets.event;
+
+/**
+ * This interface represents a CodeEvent. This event originates from the Phidget IR.
+ * This event occurs when a code is seen by the reader.
+ *
+ * @author Phidgets Inc.
+ */
+public interface CodeListener
+{
+ /**
+ * This method is called with the event data when a new event arrives.
+ *
+ * @param ae the event data object containing event data
+ */
+ public void code(CodeEvent ae);
+}
diff --git a/Java/com/phidgets/event/CurrentChangeEvent.java b/Java/com/phidgets/event/CurrentChangeEvent.java
new file mode 100644
index 0000000..b279ce8
--- /dev/null
+++ b/Java/com/phidgets/event/CurrentChangeEvent.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2006 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets.event;
+
+import com.phidgets.Phidget;
+
+/**
+ * This class represents the data for a CurrentChangeEvent.
+ *
+ * @author Phidgets Inc.
+ */
+public class CurrentChangeEvent
+{
+ Phidget source;
+ int index;
+ double value;
+
+ /**
+ * Class constructor. This is called internally by the phidget library when creating this event.
+ *
+ * @param source the Phidget object from which this event originated
+ */
+ public CurrentChangeEvent(Phidget source, int index, double value) {
+ this.source = source;
+ this.index = index;
+ this.value = value;
+ }
+
+ /**
+ * Returns the source Phidget of this event. This is a reference to the Phidget object from which this
+ * event was called. This object can be cast into a specific type of Phidget object to call specific
+ * device calls on it.
+ *
+ * @return the event caller
+ */
+ public Phidget getSource() {
+ return source;
+ }
+
+ /**
+ * Returns the index of the motor.
+ *
+ * @return the index of the motor
+ */
+ public int getIndex() {
+ return index;
+ }
+
+ /**
+ * Returns the current of the motor. This is a representation of the ammount of current being used by the motor.
+ *
+ * @return the motor's current draw
+ */
+ public double getValue() {
+ return value;
+ }
+
+ /**
+ * Returns a string containing information about the event.
+ *
+ * @return an informative event string
+ */
+ public String toString() {
+ return source.toString() + " current " + index + " changed to "
+ + value;
+ }
+}
diff --git a/Java/com/phidgets/event/CurrentChangeListener.java b/Java/com/phidgets/event/CurrentChangeListener.java
new file mode 100644
index 0000000..f45681c
--- /dev/null
+++ b/Java/com/phidgets/event/CurrentChangeListener.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2011 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets.event;
+
+/**
+ * This interface represents a CurrentChangeEvent. This event originates from the Phidget Motor Controller.
+ * This event is not supported by all Motor Controllers.
+ *
+ * @author Phidgets Inc.
+ */
+public interface CurrentChangeListener
+{
+ /**
+ * This method is called with the event data when a new event arrives.
+ *
+ * @param ae the event data object containing event data
+ */
+ public void currentChanged(CurrentChangeEvent ae);
+}
diff --git a/Java/com/phidgets/event/CurrentUpdateEvent.java b/Java/com/phidgets/event/CurrentUpdateEvent.java
new file mode 100644
index 0000000..12265e5
--- /dev/null
+++ b/Java/com/phidgets/event/CurrentUpdateEvent.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2006 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets.event;
+
+import com.phidgets.Phidget;
+
+/**
+ * This class represents the data for a CurrentUpdateEvent.
+ *
+ * @author Phidgets Inc.
+ */
+public class CurrentUpdateEvent
+{
+ Phidget source;
+ int index;
+ double value;
+
+ /**
+ * Class constructor. This is called internally by the Phidget library when creating this event.
+ *
+ * @param source the Phidget object from which this event originated
+ */
+ public CurrentUpdateEvent(Phidget source, int index, double value)
+ {
+ this.source = source;
+ this.index = index;
+ this.value = value;
+ }
+
+ /**
+ * Returns the source Phidget of this event. This is a reference to the Phidget object from which this
+ * event was called. This object can be cast into a specific type of Phidget object to call specific
+ * device calls on it.
+ *
+ * @return the event caller
+ */
+ public Phidget getSource() {
+ return source;
+ }
+
+ /**
+ * Returns the index of the motor.
+ *
+ * @return the index of the motor
+ */
+ public int getIndex() {
+ return index;
+ }
+
+ /**
+ * Returns the current of the motor. This is a representation of the amount of current being used by the motor.
+ *
+ * @return the motor's current draw
+ */
+ public double getValue() {
+ return value;
+ }
+
+ /**
+ * Returns a string containing information about the event.
+ *
+ * @return an informative event string
+ */
+ public String toString() {
+ return source.toString() + " current " + index + " is "
+ + value;
+ }
+}
diff --git a/Java/com/phidgets/event/CurrentUpdateListener.java b/Java/com/phidgets/event/CurrentUpdateListener.java
new file mode 100644
index 0000000..20a6784
--- /dev/null
+++ b/Java/com/phidgets/event/CurrentUpdateListener.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2011 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets.event;
+
+/**
+ * This interface represents a CurrentUpdateEvent. This event originates from the Phidget Motor Controller. This event is not supported by all Motor Controllers.
+ *
+ * @author Phidgets Inc.
+ */
+public interface CurrentUpdateListener
+{
+ /**
+ * This method is called with every 8ms.
+ *
+ * @param ae the event data object containing event data
+ */
+ public void currentUpdated(CurrentUpdateEvent ae);
+}
diff --git a/Java/com/phidgets/event/DetachEvent.java b/Java/com/phidgets/event/DetachEvent.java
new file mode 100644
index 0000000..97bfe29
--- /dev/null
+++ b/Java/com/phidgets/event/DetachEvent.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2006 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets.event;
+
+import com.phidgets.Phidget;
+
+/**
+ * This class represents the data for a DetachEvent.
+ *
+ * @author Phidgets Inc.
+ */
+public class DetachEvent
+{
+ Phidget source;
+
+ /**
+ * Class constructor. This is called internally by the phidget library when creating this event.
+ *
+ * @param source the Phidget object from which this event originated
+ */
+ public DetachEvent(Phidget source) {
+ this.source = source;
+ }
+
+ /**
+ * Returns the source Phidget of this event. This is a reference to the Phidget object from which this
+ * event was called. This object can be cast into a specific type of Phidget object to call specific
+ * device calls on it.
+ *
+ * @return the event caller
+ */
+ public Phidget getSource() {
+ return source;
+ }
+
+ /**
+ * Returns a string containing information about the event.
+ *
+ * @return an informative event string
+ */
+ public String toString() {
+ return source.toString();
+ }
+}
diff --git a/Java/com/phidgets/event/DetachListener.java b/Java/com/phidgets/event/DetachListener.java
new file mode 100644
index 0000000..b74e0ec
--- /dev/null
+++ b/Java/com/phidgets/event/DetachListener.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2006 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets.event;
+
+/**
+ * This interface represents a DetachEvent. This event originates from all Phidgets, as well as the Phidget Manager.
+ *
+ * @author Phidgets Inc.
+ */
+public interface DetachListener
+{
+ /**
+ * This method is called with the event data when a new event arrives.
+ *
+ * @param ae the event data object containing event data
+ */
+ public void detached(DetachEvent ae);
+}
diff --git a/Java/com/phidgets/event/EncoderPositionChangeEvent.java b/Java/com/phidgets/event/EncoderPositionChangeEvent.java
new file mode 100644
index 0000000..52118a7
--- /dev/null
+++ b/Java/com/phidgets/event/EncoderPositionChangeEvent.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2006 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets.event;
+
+import com.phidgets.Phidget;
+
+/**
+ * This class represents the data for a EncoderPositionChangeEvent.
+ *
+ * @author Phidgets Inc.
+ */
+public class EncoderPositionChangeEvent
+{
+ Phidget source;
+ int index;
+ int value;
+ int time;
+
+ /**
+ * Class constructor. This is called internally by the phidget library when creating this event.
+ *
+ * @param source the Phidget object from which this event originated
+ */
+ public EncoderPositionChangeEvent(Phidget source, int index, int time, int value) {
+ this.source = source;
+ this.index = index;
+ this.value = value;
+ this.time = time;
+ }
+
+ /**
+ * Returns the source Phidget of this event. This is a reference to the Phidget object from which this
+ * event was called. This object can be cast into a specific type of Phidget object to call specific
+ * device calls on it.
+ *
+ * @return the event caller
+ */
+ public Phidget getSource() {
+ return source;
+ }
+
+ /**
+ * Returns the index of the encoder.
+ *
+ * @return the index of the encoder
+ */
+ public int getIndex() {
+ return index;
+ }
+
+ /**
+ * Returns the position change of the encoder. This is the amount of change in the encoder's position
+ * since the last {@link #EncoderPositionChangeEvent}.
+ *
+ * @return the change in position of the encoder
+ */
+ public int getValue() {
+ return value;
+ }
+
+ /**
+ * Returns the timestamp of this position change. This is the time since the last {@link #EncoderPositionChangeEvent}.
+ * This time is not represented in a real quantitly such as seconds, but can be used as a qualitative quantity.
+ *
+ * @return the timestamp of this change event
+ */
+ public int getTime()
+ {
+ return time;
+ }
+
+ /**
+ * Returns a string containing information about the event.
+ *
+ * @return an informative event string
+ */
+ public String toString() {
+
+ return source.toString() + " encoder position " + index + " changed by "
+ + value + " Time: " + time;
+ }
+}
diff --git a/Java/com/phidgets/event/EncoderPositionChangeListener.java b/Java/com/phidgets/event/EncoderPositionChangeListener.java
new file mode 100644
index 0000000..dabdb08
--- /dev/null
+++ b/Java/com/phidgets/event/EncoderPositionChangeListener.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2006 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets.event;
+
+/**
+ * This interface represents an EncoderPositionChangeEvent. This event originates from the Phidget Encoder and the Phidget Motor Controller. This event is not supported by all Motor Controllers.
+ *
+ * @author Phidgets Inc.
+ */
+public interface EncoderPositionChangeListener
+{
+ /**
+ * This method is called with the event data when a new event arrives.
+ *
+ * @param ae the event data object containing event data
+ */
+ public void encoderPositionChanged(EncoderPositionChangeEvent ae);
+}
diff --git a/Java/com/phidgets/event/EncoderPositionUpdateEvent.java b/Java/com/phidgets/event/EncoderPositionUpdateEvent.java
new file mode 100644
index 0000000..8124b04
--- /dev/null
+++ b/Java/com/phidgets/event/EncoderPositionUpdateEvent.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2011 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets.event;
+
+import com.phidgets.Phidget;
+
+/**
+ * This class represents the data for a EncoderPositionUpdateEvent.
+ *
+ * @author Phidgets Inc.
+ */
+public class EncoderPositionUpdateEvent
+{
+ Phidget source;
+ int index;
+ int value;
+
+ /**
+ * Class constructor. This is called internally by the Phidget library when creating this event.
+ *
+ * @param source the Phidget object from which this event originated
+ */
+ public EncoderPositionUpdateEvent(Phidget source, int index, int value)
+ {
+ this.source = source;
+ this.index = index;
+ this.value = value;
+
+ }
+
+ /**
+ * Returns the source Phidget of this event. This is a reference to the Phidget object from which this
+ * event was called. This object can be cast into a specific type of Phidget object to call specific
+ * device calls on it.
+ *
+ * @return the event caller
+ */
+ public Phidget getSource() {
+ return source;
+ }
+
+ /**
+ * Returns the index of the encoder.
+ *
+ * @return the index of the encoder
+ */
+ public int getIndex() {
+ return index;
+ }
+
+ /**
+ * Returns the position change of the encoder. This is the amount of change in the encoder's position
+ * since the last {@link #EncoderPositionUpdateEvent}.
+ *
+ * @return the change in position of the encoder
+ */
+ public int getValue() {
+ return value;
+ }
+
+ /**
+ * Returns a string containing information about the event.
+ *
+ * @return an informative event string
+ */
+ public String toString() {
+
+ return source.toString() + " encoder position " + index + " is "
+ + value;
+ }
+}
diff --git a/Java/com/phidgets/event/EncoderPositionUpdateListener.java b/Java/com/phidgets/event/EncoderPositionUpdateListener.java
new file mode 100644
index 0000000..f16c899
--- /dev/null
+++ b/Java/com/phidgets/event/EncoderPositionUpdateListener.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2011 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets.event;
+
+/**
+ * This interface represents an EncoderPositionUpdateEvent. This event originates from the Phidget Motor Controller. This event is not supported by all Motor Controllers.
+ *
+ * @author Phidgets Inc.
+ */
+public interface EncoderPositionUpdateListener
+{
+ /**
+ * This method is called with the event data when a new event arrives.
+ *
+ * @param ae the event data object containing event data
+ */
+ public void encoderPositionUpdated(EncoderPositionUpdateEvent ae);
+}
diff --git a/Java/com/phidgets/event/ErrorEvent.java b/Java/com/phidgets/event/ErrorEvent.java
new file mode 100644
index 0000000..e0dc374
--- /dev/null
+++ b/Java/com/phidgets/event/ErrorEvent.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2006 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets.event;
+
+import com.phidgets.Phidget;
+import com.phidgets.PhidgetException;
+
+/**
+ * This class represents the data for a ErrorEvent.
+ *
+ * @author Phidgets Inc.
+ */
+public class ErrorEvent
+{
+ Phidget source;
+ PhidgetException exception;
+
+ /**
+ * Class constructor. This is called internally by the phidget library when creating this event.
+ *
+ * @param source the Phidget object from which this event originated
+ */
+ public ErrorEvent(Phidget source, PhidgetException ex) {
+ this.source = source;
+ this.exception = ex;
+ }
+
+ /**
+ * Returns the source Phidget of this event. This is a reference to the Phidget object from which this
+ * event was called. This object can be cast into a specific type of Phidget object to call specific
+ * device calls on it.
+ *
+ * @return the event caller
+ */
+ public Phidget getSource() {
+ return source;
+ }
+
+ /**
+ * Returns the exception that describes the error.
+ *
+ * @return the event exception
+ */
+ public PhidgetException getException()
+ {
+ return exception;
+ }
+
+ /**
+ * Returns a string containing information about the event.
+ *
+ * @return an informative event string
+ */
+ public String toString() {
+ return "Error Event (" + exception.getErrorNumber() + "): " + exception.getDescription();
+ }
+}
diff --git a/Java/com/phidgets/event/ErrorListener.java b/Java/com/phidgets/event/ErrorListener.java
new file mode 100644
index 0000000..a1a0207
--- /dev/null
+++ b/Java/com/phidgets/event/ErrorListener.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2006 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets.event;
+
+/**
+ * This interface represents a ErrorEvent. This event originates from all Phidgets.
+ * It is used for asynchronous error handling.
+ *
+ * @author Phidgets Inc.
+ */
+public interface ErrorListener
+{
+ /**
+ * This method is called with the event data when a new event arrives.
+ *
+ * @param ae the event data object containing event data
+ */
+ public void error(ErrorEvent ae);
+}
diff --git a/Java/com/phidgets/event/FrequencyCounterCountEvent.java b/Java/com/phidgets/event/FrequencyCounterCountEvent.java
new file mode 100644
index 0000000..4a9291b
--- /dev/null
+++ b/Java/com/phidgets/event/FrequencyCounterCountEvent.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2011 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets.event;
+
+import com.phidgets.Phidget;
+
+/**
+ * This class represents the data for a FrequencyCounterCountEvent.
+ *
+ * @author Phidgets Inc.
+ */
+public class FrequencyCounterCountEvent
+{
+ Phidget source;
+ int index;
+ int time;
+ int count;
+
+ /**
+ * Class constructor. This is called internally by the phidget library when creating this event.
+ *
+ * @param source the Phidget object from which this event originated
+ */
+ public FrequencyCounterCountEvent(Phidget source, int index, int time, int count) {
+ this.source = source;
+ this.index = index;
+ this.time = time;
+ this.count = count;
+ }
+
+ /**
+ * Returns the source Phidget of this event. This is a reference to the Phidget object from which this
+ * event was called. This object can be cast into a specific type of Phidget object to call specific
+ * device calls on it.
+ *
+ * @return the event caller
+ */
+ public Phidget getSource() {
+ return source;
+ }
+
+ /**
+ * Returns the index of the channel.
+ *
+ * @return the index of the channel
+ */
+ public int getIndex() {
+ return index;
+ }
+
+ /**
+ * Returns the amount of time in which the number of counts occured, in microseconds.
+ *
+ * @return the amount of time in which the number of counts occured
+ */
+ public int getTime() {
+ return time;
+ }
+
+ /**
+ * Returns the number of counts detected.
+ *
+ * @return the number of counts detected
+ */
+ public int getCount() {
+ return count;
+ }
+
+ /**
+ * Returns a string containing information about the event.
+ *
+ * @return an informative event string
+ */
+ public String toString() {
+
+ return source.toString() + " Channel " + index + ": " + count + " pulses in "
+ + time + " miroseconds";
+ }
+}
diff --git a/Java/com/phidgets/event/FrequencyCounterCountListener.java b/Java/com/phidgets/event/FrequencyCounterCountListener.java
new file mode 100644
index 0000000..fd19348
--- /dev/null
+++ b/Java/com/phidgets/event/FrequencyCounterCountListener.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2011 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets.event;
+
+/**
+ * This interface represents a FrequencyCounterCountEvent. This event originates from the Phidget Frequency Counter
+ *
+ * @author Phidgets Inc.
+ */
+public interface FrequencyCounterCountListener
+{
+ /**
+ * This method is called with the event data when a new event arrives.
+ *
+ * @param ae the event data object containing event data
+ */
+ public void frequencyCounterCounted(FrequencyCounterCountEvent ae);
+}
diff --git a/Java/com/phidgets/event/GPSPositionChangeEvent.java b/Java/com/phidgets/event/GPSPositionChangeEvent.java
new file mode 100644
index 0000000..42b9199
--- /dev/null
+++ b/Java/com/phidgets/event/GPSPositionChangeEvent.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2006 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets.event;
+
+import com.phidgets.Phidget;
+
+/**
+ * This class represents the data for a GPSPositionChangeEvent.
+ *
+ * @author Phidgets Inc.
+ */
+public class GPSPositionChangeEvent
+{
+ Phidget source;
+ double latitude;
+ double longitude;
+ double altitude;
+
+ /**
+ * Class constructor. This is called internally by the phidget library when creating this event.
+ *
+ * @param source the Phidget object from which this event originated
+ */
+ public GPSPositionChangeEvent(Phidget source, double latitude, double longitude, double altitude) {
+ this.source = source;
+ this.latitude = latitude;
+ this.longitude = longitude;
+ this.altitude = altitude;
+ }
+
+ /**
+ * Returns the source Phidget of this event. This is a reference to the Phidget object from which this
+ * event was called. This object can be cast into a specific type of Phidget object to call specific
+ * device calls on it.
+ *
+ * @return the event caller
+ */
+ public Phidget getSource() {
+ return source;
+ }
+
+ /**
+ * Returns the latitude of the GPS, in signed degrees format.
+ *
+ * @return the latitude
+ */
+ public double getLatitude() {
+ return latitude;
+ }
+
+ /**
+ * Returns the longitude of the GPS, in signed degrees format
+ *
+ * @return the longitude
+ */
+ public double getLongitude() {
+ return longitude;
+ }
+
+ /**
+ * Returns the altitude of the GPS, in meters.
+ *
+ * @return the altitude
+ */
+ public double getAltitude() {
+ return altitude;
+ }
+
+ /**
+ * Returns a string containing information about the event.
+ *
+ * @return an informative event string
+ */
+ public String toString() {
+ return("Position is - Latitude: "+ latitude + " degrees" +
+ ", Longitude: " + longitude + " degrees" + ", Altitude: "+ altitude + "m");
+ }
+}
diff --git a/Java/com/phidgets/event/GPSPositionChangeListener.java b/Java/com/phidgets/event/GPSPositionChangeListener.java
new file mode 100644
index 0000000..dceb712
--- /dev/null
+++ b/Java/com/phidgets/event/GPSPositionChangeListener.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2011 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets.event;
+
+/**
+ * This interface represents a GPSPositionChangeEvent. This event originates from the Phidget GPS
+ *
+ * @author Phidgets Inc.
+ */
+public interface GPSPositionChangeListener
+{
+ /**
+ * This method is called with the event data when a new event arrives.
+ *
+ * @param ae the event data object containing event data
+ */
+ public void gpsPositionChanged(GPSPositionChangeEvent ae);
+}
diff --git a/Java/com/phidgets/event/GPSPositionFixStatusChangeEvent.java b/Java/com/phidgets/event/GPSPositionFixStatusChangeEvent.java
new file mode 100644
index 0000000..94f08a9
--- /dev/null
+++ b/Java/com/phidgets/event/GPSPositionFixStatusChangeEvent.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2006 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets.event;
+
+import com.phidgets.Phidget;
+
+/**
+ * This class represents the data for a GPSPositionFixStatusChangeEvent.
+ *
+ * @author Phidgets Inc.
+ */
+public class GPSPositionFixStatusChangeEvent
+{
+ Phidget source;
+ boolean status;
+
+
+ /**
+ * Class constructor. This is called internally by the phidget library when creating this event.
+ *
+ * @param source the Phidget object from which this event originated
+ */
+ public GPSPositionFixStatusChangeEvent(Phidget source, boolean status) {
+ this.source = source;
+ this.status = status;
+ }
+
+ /**
+ * Returns the source Phidget of this event. This is a reference to the Phidget object from which this
+ * event was called. This object can be cast into a specific type of Phidget object to call specific
+ * device calls on it.
+ *
+ * @return the event caller
+ */
+ public Phidget getSource() {
+ return source;
+ }
+
+ /**
+ * Returns the position fix status of the GPS.
+ *
+ * @return the position fix status
+ */
+ public boolean getStatus() {
+ return status;
+ }
+
+ /**
+ * Returns a string containing information about the event.
+ *
+ * @return an informative event string
+ */
+ public String toString() {
+ return("Position fix status IS : " + status);
+ }
+}
diff --git a/Java/com/phidgets/event/GPSPositionFixStatusChangeListener.java b/Java/com/phidgets/event/GPSPositionFixStatusChangeListener.java
new file mode 100644
index 0000000..2768cea
--- /dev/null
+++ b/Java/com/phidgets/event/GPSPositionFixStatusChangeListener.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2011 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets.event;
+
+/**
+ * This interface represents a GPSPositionFixStatusChangeEvent. This event originates from the Phidget GPS
+ *
+ * @author Phidgets Inc.
+ */
+public interface GPSPositionFixStatusChangeListener
+{
+ /**
+ * This method is called with the event data when a new event arrives.
+ *
+ * @param ae the event data object containing event data
+ */
+ public void gpsPositionFixStatusChanged(GPSPositionFixStatusChangeEvent ae);
+}
diff --git a/Java/com/phidgets/event/InputChangeEvent.java b/Java/com/phidgets/event/InputChangeEvent.java
new file mode 100644
index 0000000..273bb9b
--- /dev/null
+++ b/Java/com/phidgets/event/InputChangeEvent.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2006 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets.event;
+
+import com.phidgets.Phidget;
+
+/**
+ * This class represents the data for a InputChangeEvent.
+ *
+ * @author Phidgets Inc.
+ */
+public class InputChangeEvent
+{
+ Phidget source;
+ int index;
+ boolean state;
+
+ /**
+ * Class constructor. This is called internally by the phidget library when creating this event.
+ *
+ * @param source the Phidget object from which this event originated
+ */
+ public InputChangeEvent(Phidget source, int index, boolean state) {
+ this.source = source;
+ this.index = index;
+ this.state = state;
+ }
+
+ /**
+ * Returns the source Phidget of this event. This is a reference to the Phidget object from which this
+ * event was called. This object can be cast into a specific type of Phidget object to call specific
+ * device calls on it.
+ *
+ * @return the event caller
+ */
+ public Phidget getSource() {
+ return source;
+ }
+
+ /**
+ * Returns the index of the digital input.
+ *
+ * @return the index of the input
+ */
+ public int getIndex() {
+ return index;
+ }
+
+ /**
+ * Returns the state of the input. True indicates that it is activated, False indicated the default state.
+ *
+ * @return the state of the input
+ */
+ public boolean getState() {
+ return state;
+ }
+
+ /**
+ * Returns a string containing information about the event.
+ *
+ * @return an informative event string
+ */
+ public String toString() {
+ return source.toString() + " input " + index + " changed to "
+ + state;
+ }
+}
diff --git a/Java/com/phidgets/event/InputChangeListener.java b/Java/com/phidgets/event/InputChangeListener.java
new file mode 100644
index 0000000..c63ade9
--- /dev/null
+++ b/Java/com/phidgets/event/InputChangeListener.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2006 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets.event;
+
+/**
+ * This interface represents a InputChangeEvent. This event originates from the Phidget Encoder, the Phidget InterfaceKit,
+ * and the Phidget Motor Controller.
+ *
+ * @author Phidgets Inc.
+ */
+public interface InputChangeListener
+{
+ /**
+ * This method is called with the event data when a new event arrives.
+ *
+ * @param ae the event data object containing event data
+ */
+ public void inputChanged(InputChangeEvent ae);
+}
diff --git a/Java/com/phidgets/event/KeyChangeEvent.java b/Java/com/phidgets/event/KeyChangeEvent.java
new file mode 100644
index 0000000..fe86cda
--- /dev/null
+++ b/Java/com/phidgets/event/KeyChangeEvent.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2006 Dictionarys Inc. All rights reserved.
+ */
+
+package com.phidgets.event;
+
+import com.phidgets.Dictionary;
+
+/**
+ * This class represents the data for a KeyChangeEvent.
+ *
+ * @author Dictionarys Inc.
+ */
+public class KeyChangeEvent
+{
+ Dictionary source;
+ String value;
+ String key;
+
+ /**
+ * Class constructor. This is called internally by the Dictionary library when creating this event.
+ *
+ * @param source the Dictionary object from which this event originated
+ */
+ public KeyChangeEvent(Dictionary source, String key, String value)
+ {
+ this.source = source;
+ this.value = value;
+ this.key = key;
+ }
+
+ /**
+ * Returns the source Dictionary of this event. This is a reference to the Dictionary object from which this
+ * event was called. This object can be cast into a specific type of Dictionary object to call specific
+ * device calls on it.
+ *
+ * @return the event caller
+ */
+ public Dictionary getSource() {
+ return source;
+ }
+
+ public String getKey()
+ {
+ return key;
+ }
+
+ public String getValue()
+ {
+ return value;
+ }
+
+ /**
+ * Returns a string containing information about the event.
+ *
+ * @return an informative event string
+ */
+ public String toString()
+ {
+ return source.toString() + " Key changed: "
+ + key + ":" + value;
+ }
+}
diff --git a/Java/com/phidgets/event/KeyChangeListener.java b/Java/com/phidgets/event/KeyChangeListener.java
new file mode 100644
index 0000000..07772c2
--- /dev/null
+++ b/Java/com/phidgets/event/KeyChangeListener.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2006 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets.event;
+
+/**
+ * This interface represents a KeyChangeEvent. This event originates from the Phidget Dictionary. Key Change events
+ * occur when key that matches the listen pattern is either added or changes in the Dictionary.
+ *
+ * @author Phidgets Inc.
+ */
+public interface KeyChangeListener
+{
+ /**
+ * This method is called with the event data when a new event arrives.
+ *
+ * @param ae the event data object containing event data
+ */
+ public void keyChanged(KeyChangeEvent ae);
+}
diff --git a/Java/com/phidgets/event/KeyRemovalEvent.java b/Java/com/phidgets/event/KeyRemovalEvent.java
new file mode 100644
index 0000000..1a7fe9f
--- /dev/null
+++ b/Java/com/phidgets/event/KeyRemovalEvent.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2006 Dictionarys Inc. All rights reserved.
+ */
+
+package com.phidgets.event;
+
+import com.phidgets.Dictionary;
+
+/**
+ * This class represents the data for a KeyRemovalEvent.
+ *
+ * @author Dictionarys Inc.
+ */
+public class KeyRemovalEvent
+{
+ Dictionary source;
+ String value;
+ String key;
+
+ /**
+ * Class constructor. This is called internally by the Dictionary library when creating this event.
+ *
+ * @param source the Dictionary object from which this event originated
+ */
+ public KeyRemovalEvent(Dictionary source, String key, String value)
+ {
+ this.source = source;
+ this.value = value;
+ this.key = key;
+ }
+
+ /**
+ * Returns the source Dictionary of this event. This is a reference to the Dictionary object from which this
+ * event was called. This object can be cast into a specific type of Dictionary object to call specific
+ * device calls on it.
+ *
+ * @return the event caller
+ */
+ public Dictionary getSource() {
+ return source;
+ }
+
+ public String getKey()
+ {
+ return key;
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+ /**
+ * Returns a string containing information about the event.
+ *
+ * @return an informative event string
+ */
+ public String toString() {
+ return source.toString() + " Key removed: "
+ + key + ":" + value;
+ }
+}
diff --git a/Java/com/phidgets/event/KeyRemovalListener.java b/Java/com/phidgets/event/KeyRemovalListener.java
new file mode 100644
index 0000000..bac9a92
--- /dev/null
+++ b/Java/com/phidgets/event/KeyRemovalListener.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2006 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets.event;
+
+/**
+ * This interface represents a KeyRemovalEvent. This event originates from the Phidget Dictionary.
+ * This event occurs key that matches the listen pattern is removed.
+ *
+ * @author Phidgets Inc.
+ */
+public interface KeyRemovalListener
+{
+ /**
+ * This method is called with the event data when a new event arrives.
+ *
+ * @param ae the event data object containing event data
+ */
+ public void keyRemoved(KeyRemovalEvent ae);
+}
diff --git a/Java/com/phidgets/event/LearnEvent.java b/Java/com/phidgets/event/LearnEvent.java
new file mode 100644
index 0000000..f0a784d
--- /dev/null
+++ b/Java/com/phidgets/event/LearnEvent.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2006 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets.event;
+
+import com.phidgets.Phidget;
+import com.phidgets.IRLearnedCode;
+
+/**
+ * This class represents the data for a LearnEvent.
+ *
+ * @author Phidgets Inc.
+ */
+public class LearnEvent
+{
+ Phidget source;
+ IRLearnedCode value;
+
+ /**
+ * Class constructor. This is called internally by the phidget library when creating this event.
+ *
+ * @param source the Phidget object from which this event originated
+ */
+ public LearnEvent(Phidget source, IRLearnedCode value)
+ {
+ this.source = source;
+ this.value = value;
+ }
+
+ /**
+ * Returns the source Phidget of this event. This is a reference to the Phidget object from which this
+ * event was called. This object can be cast into a specific type of Phidget object to call specific
+ * device calls on it.
+ *
+ * @return the event caller
+ */
+ public Phidget getSource() {
+ return source;
+ }
+
+ /**
+ * Returns the learned code.
+ *
+ * @return the learned code
+ */
+ public IRLearnedCode getValue() {
+ return value;
+ }
+
+ /**
+ * Returns a string containing information about the event.
+ *
+ * @return an informative event string
+ */
+ public String toString() {
+ return source.toString() + " Learned Code: "
+ + value;
+ }
+}
diff --git a/Java/com/phidgets/event/LearnListener.java b/Java/com/phidgets/event/LearnListener.java
new file mode 100644
index 0000000..174aa30
--- /dev/null
+++ b/Java/com/phidgets/event/LearnListener.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2006 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets.event;
+
+/**
+ * This interface represents a LearnEvent. This event originates from the Phidget IR.
+ * This event occurs when a code is learned by the reader.
+ *
+ * @author Phidgets Inc.
+ */
+public interface LearnListener
+{
+ /**
+ * This method is called with the event data when a new event arrives.
+ *
+ * @param ae the event data object containing event data
+ */
+ public void learn(LearnEvent ae);
+}
diff --git a/Java/com/phidgets/event/MotorVelocityChangeEvent.java b/Java/com/phidgets/event/MotorVelocityChangeEvent.java
new file mode 100644
index 0000000..b3aef63
--- /dev/null
+++ b/Java/com/phidgets/event/MotorVelocityChangeEvent.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2006 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets.event;
+
+import com.phidgets.Phidget;
+
+/**
+ * This class represents the data for a MotorVelocityChangeEvent.
+ *
+ * @author Phidgets Inc.
+ */
+public class MotorVelocityChangeEvent
+{
+ Phidget source;
+ int index;
+ double value;
+
+ /**
+ * Class constructor. This is called internally by the phidget library when creating this event.
+ *
+ * @param source the Phidget object from which this event originated
+ */
+ public MotorVelocityChangeEvent(Phidget source, int index, double value) {
+ this.source = source;
+ this.index = index;
+ this.value = value;
+ }
+
+ /**
+ * Returns the source Phidget of this event. This is a reference to the Phidget object from which this
+ * event was called. This object can be cast into a specific type of Phidget object to call specific
+ * device calls on it.
+ *
+ * @return the event caller
+ */
+ public Phidget getSource() {
+ return source;
+ }
+
+ /**
+ * Returns the index of the motor.
+ *
+ * @return the index of the motor
+ */
+ public int getIndex() {
+ return index;
+ }
+
+ /**
+ * Return the velocity of the motor. This is reported back from the motor controller as the motor changes speed.
+ *
+ * @return the motor velocity
+ */
+ public double getValue() {
+ return value;
+ }
+
+ /**
+ * Returns a string containing information about the event.
+ *
+ * @return an informative event string
+ */
+ public String toString() {
+ return source.toString() + " motor velocity " + index + " changed to "
+ + value;
+ }
+}
diff --git a/Java/com/phidgets/event/MotorVelocityChangeListener.java b/Java/com/phidgets/event/MotorVelocityChangeListener.java
new file mode 100644
index 0000000..88cd722
--- /dev/null
+++ b/Java/com/phidgets/event/MotorVelocityChangeListener.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2006 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets.event;
+
+/**
+ * This interface represents a MotorVelocityChangeEvent. This event originates from the Phidget Motor Controller
+ *
+ * @author Phidgets Inc.
+ */
+public interface MotorVelocityChangeListener
+{
+ /**
+ * This method is called with the event data when a new event arrives.
+ *
+ * @param ae the event data object containing event data
+ */
+ public void motorVelocityChanged(MotorVelocityChangeEvent ae);
+}
diff --git a/Java/com/phidgets/event/OutputChangeEvent.java b/Java/com/phidgets/event/OutputChangeEvent.java
new file mode 100644
index 0000000..01e6af5
--- /dev/null
+++ b/Java/com/phidgets/event/OutputChangeEvent.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2006 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets.event;
+
+import com.phidgets.Phidget;
+
+/**
+ * This class represents the data for a OutputChangeEvent.
+ *
+ * @author Phidgets Inc.
+ */
+public class OutputChangeEvent
+{
+ Phidget source;
+ int index;
+ boolean state;
+
+ /**
+ * Class constructor. This is called internally by the phidget library when creating this event.
+ *
+ * @param source the Phidget object from which this event originated
+ */
+ public OutputChangeEvent(Phidget source, int index, boolean state) {
+ this.source = source;
+ this.index = index;
+ this.state = state;
+ }
+
+ /**
+ * Returns the source Phidget of this event. This is a reference to the Phidget object from which this
+ * event was called. This object can be cast into a specific type of Phidget object to call specific
+ * device calls on it.
+ *
+ * @return the event caller
+ */
+ public Phidget getSource() {
+ return source;
+ }
+
+ /**
+ * Returns the index of the output.
+ *
+ * @return the index of the output
+ */
+ public int getIndex() {
+ return index;
+ }
+
+ /**
+ * Returns the state of the output. True indicated that the output is active, False indicated the default inactive state.
+ *
+ * @return the state of the output
+ */
+ public boolean getState() {
+ return state;
+ }
+
+ /**
+ * Returns a string containing information about the event.
+ *
+ * @return an informative event string
+ */
+ public String toString() {
+ return source.toString() + " output " + index + " changed to "
+ + state;
+ }
+}
diff --git a/Java/com/phidgets/event/OutputChangeListener.java b/Java/com/phidgets/event/OutputChangeListener.java
new file mode 100644
index 0000000..998ffbf
--- /dev/null
+++ b/Java/com/phidgets/event/OutputChangeListener.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2006 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets.event;
+
+/**
+ * This interface represents a OutputChangeEvent. This event originates from the
+ * Phidget Interface Kit and the Phidget RFID Reader
+ *
+ * @author Phidgets Inc.
+ */
+public interface OutputChangeListener
+{
+ /**
+ * This method is called with the event data when a new event arrives.
+ *
+ * @param ae the event data object containing event data
+ */
+ public void outputChanged(OutputChangeEvent ae);
+}
diff --git a/Java/com/phidgets/event/PHChangeEvent.java b/Java/com/phidgets/event/PHChangeEvent.java
new file mode 100644
index 0000000..a885132
--- /dev/null
+++ b/Java/com/phidgets/event/PHChangeEvent.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2006 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets.event;
+
+import com.phidgets.Phidget;
+
+/**
+ * This class represents the data for a PHChangeEvent.
+ *
+ * @author Phidgets Inc.
+ */
+public class PHChangeEvent
+{
+ Phidget source;
+ double value;
+
+ /**
+ * Class constructor. This is called internally by the phidget library when creating this event.
+ *
+ * @param source the Phidget object from which this event originated
+ */
+ public PHChangeEvent(Phidget source, double value) {
+ this.source = source;
+ this.value = value;
+ }
+
+ /**
+ * Returns the source Phidget of this event. This is a reference to the Phidget object from which this
+ * event was called. This object can be cast into a specific type of Phidget object to call specific
+ * device calls on it.
+ *
+ * @return the event caller
+ */
+ public Phidget getSource() {
+ return source;
+ }
+
+ /**
+ * Returns the pH. This value can range from 0-14
+ *
+ * @return the pH
+ */
+ public double getValue() {
+ return value;
+ }
+
+ /**
+ * Returns a string containing information about the event.
+ *
+ * @return an informative event string
+ */
+ public String toString() {
+ return source.toString() + " ph changed to "
+ + value;
+ }
+}
diff --git a/Java/com/phidgets/event/PHChangeListener.java b/Java/com/phidgets/event/PHChangeListener.java
new file mode 100644
index 0000000..0791631
--- /dev/null
+++ b/Java/com/phidgets/event/PHChangeListener.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2006 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets.event;
+
+/**
+ * This interface represents a PHChangeEvent. This event originates from the Phidget PH Sensor
+ *
+ * @author Phidgets Inc.
+ */
+public interface PHChangeListener
+{
+ /**
+ * This method is called with the event data when a new event arrives.
+ *
+ * @param ae the event data object containing event data
+ */
+ public void phChanged(PHChangeEvent ae);
+}
diff --git a/Java/com/phidgets/event/RawDataEvent.java b/Java/com/phidgets/event/RawDataEvent.java
new file mode 100644
index 0000000..ba0c644
--- /dev/null
+++ b/Java/com/phidgets/event/RawDataEvent.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2006 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets.event;
+
+import com.phidgets.Phidget;
+
+/**
+ * This class represents the data for a RawDataEvent.
+ *
+ * @author Phidgets Inc.
+ */
+public class RawDataEvent
+{
+ Phidget source;
+ int[] data;
+
+ /**
+ * Class constructor. This is called internally by the phidget library when creating this event.
+ *
+ * @param source the Phidget object from which this event originated
+ */
+ public RawDataEvent(Phidget source, int[] data)
+ {
+ this.source = source;
+ this.data = new int[data.length];
+ for(int i=0;i<data.length;i++)
+ this.data[i] = data[i];
+ }
+
+ /**
+ * Returns the source Phidget of this event. This is a reference to the Phidget object from which this
+ * event was called. This object can be cast into a specific type of Phidget object to call specific
+ * device calls on it.
+ *
+ * @return the event caller
+ */
+ public Phidget getSource() {
+ return source;
+ }
+
+ /**
+ * Returns the raw data.
+ *
+ * @return the raw data
+ */
+ public int[] getData() {
+ return data;
+ }
+
+ /**
+ * Returns a string containing information about the event.
+ *
+ * @return an informative event string
+ */
+ public String toString() {
+ String out = " Raw data:";
+ for(int i=0;i<data.length;i++)
+ {
+ if(i%8 == 0) out = out + "\n";
+ if(data[i]==com.phidgets.IRPhidget.RAWDATA_LONGSPACE)
+ out = out + "LONG";
+ else
+ out = out + data[i];
+ if((i+1)%8 != 0) out = out + ", ";
+ }
+ return out;
+ }
+}
diff --git a/Java/com/phidgets/event/RawDataListener.java b/Java/com/phidgets/event/RawDataListener.java
new file mode 100644
index 0000000..2a656bd
--- /dev/null
+++ b/Java/com/phidgets/event/RawDataListener.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2006 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets.event;
+
+/**
+ * This interface represents a RawDataEvent. This event originates from the Phidget IR.
+ * This event occurs when the reader sees IR data.
+ *
+ * @author Phidgets Inc.
+ */
+public interface RawDataListener
+{
+ /**
+ * This method is called with the event data when a new event arrives.
+ *
+ * @param ae the event data object containing event data
+ */
+ public void rawData(RawDataEvent ae);
+}
diff --git a/Java/com/phidgets/event/SensorChangeEvent.java b/Java/com/phidgets/event/SensorChangeEvent.java
new file mode 100644
index 0000000..fce96ca
--- /dev/null
+++ b/Java/com/phidgets/event/SensorChangeEvent.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2006 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets.event;
+
+import com.phidgets.Phidget;
+
+/**
+ * This class represents the data for a SensorChangeEvent.
+ *
+ * @author Phidgets Inc.
+ */
+public class SensorChangeEvent
+{
+ Phidget source;
+ int index;
+ int value;
+
+ /**
+ * Class constructor. This is called internally by the phidget library when creating this event.
+ *
+ * @param source the Phidget object from which this event originated
+ */
+ public SensorChangeEvent(Phidget source, int index, int value) {
+ this.source = source;
+ this.index = index;
+ this.value = value;
+ }
+
+ /**
+ * Returns the source Phidget of this event. This is a reference to the Phidget object from which this
+ * event was called. This object can be cast into a specific type of Phidget object to call specific
+ * device calls on it.
+ *
+ * @return the event caller
+ */
+ public Phidget getSource() {
+ return source;
+ }
+
+ /**
+ * Returns the index of the sensor.
+ *
+ * @return the index of the sensor
+ */
+ public int getIndex() {
+ return index;
+ }
+
+ /**
+ * Retuns the value of the sensor. This value can range from 0-1000.
+ *
+ * @return the value of the sensor
+ */
+ public int getValue() {
+ return value;
+ }
+
+ /**
+ * Returns a string containing information about the event.
+ *
+ * @return an informative event string
+ */
+ public String toString() {
+ return source.toString() + " sensor " + index + " changed to "
+ + value;
+ }
+}
diff --git a/Java/com/phidgets/event/SensorChangeListener.java b/Java/com/phidgets/event/SensorChangeListener.java
new file mode 100644
index 0000000..5a4cb40
--- /dev/null
+++ b/Java/com/phidgets/event/SensorChangeListener.java
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2006 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets.event;
+/**
+ * This interface represents a SensorChangeEvent. This event originates from the Phidget Interface Kit
+ *
+ * @author Phidgets Inc.
+ */
+public interface SensorChangeListener
+{
+ /**
+ * This method is called with the event data when a new event arrives.
+ *
+ * @param ae the event data object containing event data
+ */
+ public void sensorChanged(SensorChangeEvent ae);
+}
diff --git a/Java/com/phidgets/event/SensorUpdateEvent.java b/Java/com/phidgets/event/SensorUpdateEvent.java
new file mode 100644
index 0000000..24edd6e
--- /dev/null
+++ b/Java/com/phidgets/event/SensorUpdateEvent.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2011 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets.event;
+
+import com.phidgets.Phidget;
+
+/**
+ * This class represents the data for a SensorUpdateEvent.
+ *
+ * @author Phidgets Inc.
+ */
+public class SensorUpdateEvent
+{
+ Phidget source;
+ int index;
+ int value;
+
+ /**
+ * Class constructor. This is called internally by the phidget library when creating this event.
+ *
+ * @param source the Phidget object from which this event originated
+ */
+ public SensorUpdateEvent(Phidget source, int index, int value)
+ {
+ this.source = source;
+ this.index = index;
+ this.value = value;
+ }
+
+ /**
+ * Returns the source Phidget of this event. This is a reference to the Phidget object from which this
+ * event was called. This object can be cast into a specific type of Phidget object to call specific
+ * device calls on it.
+ *
+ * @return the event caller
+ */
+ public Phidget getSource() {
+ return source;
+ }
+
+ /**
+ * Returns the index of the sensor.
+ *
+ * @return the index of the sensor
+ */
+ public int getIndex() {
+ return index;
+ }
+
+ /**
+ * Retuns the value of the sensor. This value ranges from 0-1000.
+ *
+ * @return the value of the sensor
+ */
+ public int getValue() {
+ return value;
+ }
+
+ /**
+ * Returns a string containing information about the event.
+ *
+ * @return an informative event string
+ */
+ public String toString() {
+ return source.toString() + " sensor " + index + " is "
+ + value;
+ }
+}
diff --git a/Java/com/phidgets/event/SensorUpdateListener.java b/Java/com/phidgets/event/SensorUpdateListener.java
new file mode 100644
index 0000000..5c491cc
--- /dev/null
+++ b/Java/com/phidgets/event/SensorUpdateListener.java
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2011 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets.event;
+/**
+ * This interface represents a SensorUpdateEvent. This event originates from the Phidget Motor Control
+ *
+ * @author Phidgets Inc.
+ */
+public interface SensorUpdateListener
+{
+ /**
+ * This method is called with the event data every 8ms.
+ *
+ * @param ae the event data object containing event data
+ */
+ public void sensorUpdated(SensorUpdateEvent ae);
+}
diff --git a/Java/com/phidgets/event/ServerConnectEvent.java b/Java/com/phidgets/event/ServerConnectEvent.java
new file mode 100644
index 0000000..cc89dde
--- /dev/null
+++ b/Java/com/phidgets/event/ServerConnectEvent.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2006 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets.event;
+
+import com.phidgets.Phidget;
+
+/**
+ * This class represents the data for a ServerConnectEvent.
+ *
+ * @author Phidgets Inc.
+ */
+public class ServerConnectEvent
+{
+ Object source;
+
+ /**
+ * Class constructor. This is called internally by the phidget library when creating this event.
+ *
+ * @param source the object from which this event originated
+ */
+ public ServerConnectEvent(Object source)
+ {
+ this.source = source;
+ }
+
+ /**
+ * Returns the source Object of this event. This is a reference to the object from which this
+ * event was called. This object can be cast into a specific type of Phidget object to call specific
+ * device calls on it.
+ *
+ * @return the event caller
+ */
+ public Object getSource()
+ {
+ return source;
+ }
+
+ /**
+ * Returns a string containing information about the event.
+ *
+ * @return an informative event string
+ */
+ public String toString() {
+ return source.toString();
+ }
+}
diff --git a/Java/com/phidgets/event/ServerConnectListener.java b/Java/com/phidgets/event/ServerConnectListener.java
new file mode 100644
index 0000000..5667a30
--- /dev/null
+++ b/Java/com/phidgets/event/ServerConnectListener.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2006 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets.event;
+
+/**
+ * This interface represents a ServerConnectEvent. This event originates from all Phidgets.
+ *
+ * @author Phidgets Inc.
+ */
+public interface ServerConnectListener
+{
+ /**
+ * This method is called with the event data when a new event arrives.
+ *
+ * @param ae the event data object containing event data
+ */
+ public void serverConnected(ServerConnectEvent ae);
+}
diff --git a/Java/com/phidgets/event/ServerDisconnectEvent.java b/Java/com/phidgets/event/ServerDisconnectEvent.java
new file mode 100644
index 0000000..1b4740d
--- /dev/null
+++ b/Java/com/phidgets/event/ServerDisconnectEvent.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2006 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets.event;
+
+import com.phidgets.Phidget;
+
+/**
+ * This class represents the data for a ServerDisconnectEvent.
+ *
+ * @author Phidgets Inc.
+ */
+public class ServerDisconnectEvent
+{
+ Object source;
+
+ /**
+ * Class constructor. This is called internally by the phidget library when creating this event.
+ *
+ * @param source the object from which this event originated
+ */
+ public ServerDisconnectEvent(Object source)
+ {
+ this.source = source;
+ }
+
+ /**
+ * Returns the source Object of this event. This is a reference to the object from which this
+ * event was called. This object can be cast into a specific type of object to call specific
+ * device calls on it.
+ *
+ * @return the event caller
+ */
+ public Object getSource()
+ {
+ return source;
+ }
+
+ /**
+ * Returns a string containing information about the event.
+ *
+ * @return an informative event string
+ */
+ public String toString() {
+ return source.toString();
+ }
+}
diff --git a/Java/com/phidgets/event/ServerDisconnectListener.java b/Java/com/phidgets/event/ServerDisconnectListener.java
new file mode 100644
index 0000000..93df8f9
--- /dev/null
+++ b/Java/com/phidgets/event/ServerDisconnectListener.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2006 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets.event;
+
+/**
+ * This interface represents a ServerDisconnectEvent. This event originates from all Phidgets.
+ *
+ * @author Phidgets Inc.
+ */
+public interface ServerDisconnectListener
+{
+ /**
+ * This method is called with the event data when a new event arrives.
+ *
+ * @param ae the event data object containing event data
+ */
+ public void serverDisconnected(ServerDisconnectEvent ae);
+}
diff --git a/Java/com/phidgets/event/ServoPositionChangeEvent.java b/Java/com/phidgets/event/ServoPositionChangeEvent.java
new file mode 100644
index 0000000..f685964
--- /dev/null
+++ b/Java/com/phidgets/event/ServoPositionChangeEvent.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2006 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets.event;
+
+import com.phidgets.Phidget;
+
+/**
+ * This class represents the data for a ServoPositionChangeEvent.
+ *
+ * @author Phidgets Inc.
+ */
+public class ServoPositionChangeEvent
+{
+ Phidget source;
+ int index;
+ double value;
+
+ /**
+ * Class constructor. This is called internally by the phidget library when creating this event.
+ *
+ * @param source the Phidget object from which this event originated
+ */
+ public ServoPositionChangeEvent(Phidget source, int index, double value) {
+ this.source = source;
+ this.index = index;
+ this.value = value;
+ }
+
+ /**
+ * Returns the source Phidget of this event. This is a reference to the Phidget object from which this
+ * event was called. This object can be cast into a specific type of Phidget object to call specific
+ * device calls on it.
+ *
+ * @return the event caller
+ */
+ public Phidget getSource() {
+ return source;
+ }
+
+ /**
+ * Returns the index of the servo motor.
+ *
+ * @return index of the servo
+ */
+ public int getIndex() {
+ return index;
+ }
+
+ /**
+ * Returns the position of the servo motor. This is esentially just the last position that the
+ * servo was set to, echoed back from the controller board.
+ *
+ * @return position of the servo
+ */
+ public double getValue() {
+ return value;
+ }
+
+ /**
+ * Returns a string containing information about the event.
+ *
+ * @return an informative event string
+ */
+ public String toString() {
+ return source.toString() + " servo position " + index + " changed to "
+ + value;
+ }
+}
diff --git a/Java/com/phidgets/event/ServoPositionChangeListener.java b/Java/com/phidgets/event/ServoPositionChangeListener.java
new file mode 100644
index 0000000..00e8cf8
--- /dev/null
+++ b/Java/com/phidgets/event/ServoPositionChangeListener.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2006 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets.event;
+
+/**
+ * This interface represents a ServoPositionChangeEvent. This event originates from the Phidget Servo Controller and the
+ * Phidget Advanced Servo Controller.
+ *
+ * @author Phidgets Inc.
+ */
+public interface ServoPositionChangeListener
+{
+ /**
+ * This method is called with the event data when a new event arrives.
+ *
+ * @param ae the event data object containing event data
+ */
+ public void servoPositionChanged(ServoPositionChangeEvent ae);
+}
diff --git a/Java/com/phidgets/event/ServoVelocityChangeEvent.java b/Java/com/phidgets/event/ServoVelocityChangeEvent.java
new file mode 100644
index 0000000..9c43651
--- /dev/null
+++ b/Java/com/phidgets/event/ServoVelocityChangeEvent.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2006 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets.event;
+
+import com.phidgets.Phidget;
+
+/**
+ * This class represents the data for a ServoVelocityChangeEvent.
+ *
+ * @author Phidgets Inc.
+ */
+public class ServoVelocityChangeEvent
+{
+ Phidget source;
+ int index;
+ double value;
+
+ /**
+ * Class constructor. This is called internally by the phidget library when creating this event.
+ *
+ * @param source the Phidget object from which this event originated
+ */
+ public ServoVelocityChangeEvent(Phidget source, int index, double value) {
+ this.source = source;
+ this.index = index;
+ this.value = value;
+ }
+
+ /**
+ * Returns the source Phidget of this event. This is a reference to the Phidget object from which this
+ * event was called. This object can be cast into a specific type of Phidget object to call specific
+ * device calls on it.
+ *
+ * @return the event caller
+ */
+ public Phidget getSource() {
+ return source;
+ }
+
+ /**
+ * Returns the index of the Servo.
+ *
+ * @return the index of the servo
+ */
+ public int getIndex() {
+ return index;
+ }
+
+ /**
+ * Return the velocity of the Servo. This is reported back from the Servo controller as the Servo changes speed.
+ *
+ * @return the Servo velocity
+ */
+ public double getValue() {
+ return value;
+ }
+
+ /**
+ * Returns a string containing information about the event.
+ *
+ * @return an informative event string
+ */
+ public String toString() {
+ return source.toString() + " Servo velocity " + index + " changed to "
+ + value;
+ }
+}
diff --git a/Java/com/phidgets/event/ServoVelocityChangeListener.java b/Java/com/phidgets/event/ServoVelocityChangeListener.java
new file mode 100644
index 0000000..962ca53
--- /dev/null
+++ b/Java/com/phidgets/event/ServoVelocityChangeListener.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2006 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets.event;
+
+/**
+ * This interface represents a ServoVelocityChangeEvent. This event originates from the Phidget Advanced Servo Controller
+ *
+ * @author Phidgets Inc.
+ */
+public interface ServoVelocityChangeListener
+{
+ /**
+ * This method is called with the event data when a new event arrives.
+ *
+ * @param ae the event data object containing event data
+ */
+ public void servoVelocityChanged(ServoVelocityChangeEvent ae);
+}
diff --git a/Java/com/phidgets/event/SpatialDataEvent.java b/Java/com/phidgets/event/SpatialDataEvent.java
new file mode 100644
index 0000000..e6c6dae
--- /dev/null
+++ b/Java/com/phidgets/event/SpatialDataEvent.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2006 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets.event;
+
+import com.phidgets.Phidget;
+import com.phidgets.SpatialEventData;
+
+/**
+ * This class represents the data for a SpatialDataEvent.
+ *
+ * @author Phidgets Inc.
+ */
+public class SpatialDataEvent
+{
+ Phidget source;
+ SpatialEventData[] data;
+
+ /**
+ * Class constructor. This is called internally by the phidget library when creating this event.
+ *
+ * @param source the Phidget object from which this event originated
+ * @param data the spatial data
+ */
+ public SpatialDataEvent(Phidget source, SpatialEventData[] data)
+ {
+ this.source = source;
+ this.data = data;
+ }
+
+ /**
+ * Returns the source Phidget of this event. This is a reference to the Phidget object from which this
+ * event was called. This object can be cast into a specific type of Phidget object to call specific
+ * device calls on it.
+ *
+ * @return the event caller
+ */
+ public Phidget getSource() {
+ return source;
+ }
+
+ /**
+ * Returns the data. This may contain multiple sets of data for high data rates.
+ *
+ * @return the data
+ */
+ public SpatialEventData[] getData() {
+ return data;
+ }
+
+ /**
+ * Returns a string containing information about the event.
+ *
+ * @return an informative event string
+ */
+ public String toString() {
+ return source.toString() + " Spatial Data";
+ }
+}
diff --git a/Java/com/phidgets/event/SpatialDataListener.java b/Java/com/phidgets/event/SpatialDataListener.java
new file mode 100644
index 0000000..a381777
--- /dev/null
+++ b/Java/com/phidgets/event/SpatialDataListener.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2006 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets.event;
+
+/**
+ * This interface represents a SpatialDataEvent. This event originates from the Phidget Spatial.
+ * This event occurs when spatial data comes in
+ *
+ * @author Phidgets Inc.
+ */
+public interface SpatialDataListener
+{
+ /**
+ * This method is called with the event data when a new event arrives.
+ *
+ * @param ae the event data object containing event data
+ */
+ public void data(SpatialDataEvent ae);
+}
diff --git a/Java/com/phidgets/event/StepperPositionChangeEvent.java b/Java/com/phidgets/event/StepperPositionChangeEvent.java
new file mode 100644
index 0000000..e002dd9
--- /dev/null
+++ b/Java/com/phidgets/event/StepperPositionChangeEvent.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2006 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets.event;
+
+import com.phidgets.Phidget;
+
+/**
+ * This class represents the data for a StepperPositionChangeEvent.
+ *
+ * @author Phidgets Inc.
+ */
+public class StepperPositionChangeEvent
+{
+ Phidget source;
+ int index;
+ long value;
+
+ /**
+ * Class constructor. This is called internally by the phidget library when creating this event.
+ *
+ * @param source the Phidget object from which this event originated
+ */
+ public StepperPositionChangeEvent(Phidget source, int index, long value) {
+ this.source = source;
+ this.index = index;
+ this.value = value;
+ }
+
+ /**
+ * Returns the source Phidget of this event. This is a reference to the Phidget object from which this
+ * event was called. This object can be cast into a specific type of Phidget object to call specific
+ * device calls on it.
+ *
+ * @return the event caller
+ */
+ public Phidget getSource() {
+ return source;
+ }
+
+ /**
+ * Returns the index of the Stepper motor.
+ *
+ * @return index of the Stepper
+ */
+ public int getIndex() {
+ return index;
+ }
+
+ /**
+ * Returns the position of the Stepper motor. This is esentially just the last position that the
+ * Stepper was set to, echoed back from the controller board.
+ *
+ * @return position of the Stepper
+ */
+ public double getValue() {
+ return value;
+ }
+
+ /**
+ * Returns a string containing information about the event.
+ *
+ * @return an informative event string
+ */
+ public String toString() {
+ return source.toString() + " Stepper position " + index + " changed to "
+ + value;
+ }
+}
diff --git a/Java/com/phidgets/event/StepperPositionChangeListener.java b/Java/com/phidgets/event/StepperPositionChangeListener.java
new file mode 100644
index 0000000..b1cf3fc
--- /dev/null
+++ b/Java/com/phidgets/event/StepperPositionChangeListener.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2006 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets.event;
+
+/**
+ * This interface represents a StepperPositionChangeEvent. This event originates from the Phidget Stepper Controller and the
+ * Phidget Advanced Stepper Controller.
+ *
+ * @author Phidgets Inc.
+ */
+public interface StepperPositionChangeListener
+{
+ /**
+ * This method is called with the event data when a new event arrives.
+ *
+ * @param ae the event data object containing event data
+ */
+ public void stepperPositionChanged(StepperPositionChangeEvent ae);
+}
diff --git a/Java/com/phidgets/event/StepperVelocityChangeEvent.java b/Java/com/phidgets/event/StepperVelocityChangeEvent.java
new file mode 100644
index 0000000..6154170
--- /dev/null
+++ b/Java/com/phidgets/event/StepperVelocityChangeEvent.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2006 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets.event;
+
+import com.phidgets.Phidget;
+
+/**
+ * This class represents the data for a StepperVelocityChangeEvent.
+ *
+ * @author Phidgets Inc.
+ */
+public class StepperVelocityChangeEvent
+{
+ Phidget source;
+ int index;
+ double value;
+
+ /**
+ * Class constructor. This is called internally by the phidget library when creating this event.
+ *
+ * @param source the Phidget object from which this event originated
+ */
+ public StepperVelocityChangeEvent(Phidget source, int index, double value) {
+ this.source = source;
+ this.index = index;
+ this.value = value;
+ }
+
+ /**
+ * Returns the source Phidget of this event. This is a reference to the Phidget object from which this
+ * event was called. This object can be cast into a specific type of Phidget object to call specific
+ * device calls on it.
+ *
+ * @return the event caller
+ */
+ public Phidget getSource() {
+ return source;
+ }
+
+ /**
+ * Returns the index of the Stepper.
+ *
+ * @return the index of the Stepper
+ */
+ public int getIndex() {
+ return index;
+ }
+
+ /**
+ * Return the velocity of the Stepper. This is reported back from the Stepper controller as the Stepper changes speed.
+ *
+ * @return the Stepper velocity
+ */
+ public double getValue() {
+ return value;
+ }
+
+ /**
+ * Returns a string containing information about the event.
+ *
+ * @return an informative event string
+ */
+ public String toString() {
+ return source.toString() + " Stepper velocity " + index + " changed to "
+ + value;
+ }
+}
diff --git a/Java/com/phidgets/event/StepperVelocityChangeListener.java b/Java/com/phidgets/event/StepperVelocityChangeListener.java
new file mode 100644
index 0000000..b416441
--- /dev/null
+++ b/Java/com/phidgets/event/StepperVelocityChangeListener.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2006 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets.event;
+
+/**
+ * This interface represents a StepperVelocityChangeEvent. This event originates from the Phidget Stepper Controller
+ *
+ * @author Phidgets Inc.
+ */
+public interface StepperVelocityChangeListener
+{
+ /**
+ * This method is called with the event data when a new event arrives.
+ *
+ * @param ae the event data object containing event data
+ */
+ public void stepperVelocityChanged(StepperVelocityChangeEvent ae);
+}
diff --git a/Java/com/phidgets/event/TagGainEvent.java b/Java/com/phidgets/event/TagGainEvent.java
new file mode 100644
index 0000000..6cb7a74
--- /dev/null
+++ b/Java/com/phidgets/event/TagGainEvent.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2006 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets.event;
+
+import com.phidgets.Phidget;
+
+/**
+ * This class represents the data for a TagGainEvent.
+ *
+ * @author Phidgets Inc.
+ */
+public class TagGainEvent
+{
+ Phidget source;
+ String value;
+
+ /**
+ * Class constructor. This is called internally by the phidget library when creating this event.
+ *
+ * @param source the Phidget object from which this event originated
+ */
+ public TagGainEvent(Phidget source, String value)
+ {
+ this.source = source;
+ this.value = value;
+ }
+
+ /**
+ * Returns the source Phidget of this event. This is a reference to the Phidget object from which this
+ * event was called. This object can be cast into a specific type of Phidget object to call specific
+ * device calls on it.
+ *
+ * @return the event caller
+ */
+ public Phidget getSource() {
+ return source;
+ }
+
+ /**
+ * Returns the gained tag. The tag is a 10 digit hex number represented as a string.
+ *
+ * @return the gained tag
+ */
+ public String getValue() {
+ return value;
+ }
+
+ /**
+ * Returns a string containing information about the event.
+ *
+ * @return an informative event string
+ */
+ public String toString() {
+ return source.toString() + " Tag Gained: "
+ + value;
+ }
+}
diff --git a/Java/com/phidgets/event/TagGainListener.java b/Java/com/phidgets/event/TagGainListener.java
new file mode 100644
index 0000000..df7b43f
--- /dev/null
+++ b/Java/com/phidgets/event/TagGainListener.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2006 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets.event;
+
+/**
+ * This interface represents a TagGainEvent. This event originates from the Phidget RFID Reader.
+ * This event occurs when a tag is placed on a reader.
+ *
+ * @author Phidgets Inc.
+ */
+public interface TagGainListener
+{
+ /**
+ * This method is called with the event data when a new event arrives.
+ *
+ * @param ae the event data object containing event data
+ */
+ public void tagGained(TagGainEvent ae);
+}
diff --git a/Java/com/phidgets/event/TagLossEvent.java b/Java/com/phidgets/event/TagLossEvent.java
new file mode 100644
index 0000000..ccca4fe
--- /dev/null
+++ b/Java/com/phidgets/event/TagLossEvent.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2006 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets.event;
+
+import com.phidgets.Phidget;
+
+/**
+ * This class represents the data for a TagLossEvent.
+ *
+ * @author Phidgets Inc.
+ */
+public class TagLossEvent
+{
+ Phidget source;
+ String value;
+
+ /**
+ * Class constructor. This is called internally by the phidget library when creating this event.
+ *
+ * @param source the Phidget object from which this event originated
+ */
+ public TagLossEvent(Phidget source, String value)
+ {
+ this.source = source;
+ this.value = value;
+ }
+
+ /**
+ * Returns the source Phidget of this event. This is a reference to the Phidget object from which this
+ * event was called. This object can be cast into a specific type of Phidget object to call specific
+ * device calls on it.
+ *
+ * @return the event caller
+ */
+ public Phidget getSource() {
+ return source;
+ }
+
+ /**
+ * Returns the Tag that was lost. This is a 10 digit hex number as a string.
+ *
+ * @return the lost tag
+ */
+ public String getValue() {
+ return value;
+ }
+
+ /**
+ * Returns a string containing information about the event.
+ *
+ * @return an informative event string
+ */
+ public String toString() {
+ return source.toString() + " Tag lost: "
+ + value;
+ }
+}
diff --git a/Java/com/phidgets/event/TagLossListener.java b/Java/com/phidgets/event/TagLossListener.java
new file mode 100644
index 0000000..66a3a8a
--- /dev/null
+++ b/Java/com/phidgets/event/TagLossListener.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2006 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets.event;
+
+/**
+ * This interface represents a TagLossEvent. This event originates from the Phidget RFID reader. Tag loss events
+ * occur when a tag is removed from the RFID reader.
+ *
+ * @author Phidgets Inc.
+ */
+public interface TagLossListener
+{
+ /**
+ * This method is called with the event data when a new event arrives.
+ *
+ * @param ae the event data object containing event data
+ */
+ public void tagLost(TagLossEvent ae);
+}
diff --git a/Java/com/phidgets/event/TemperatureChangeEvent.java b/Java/com/phidgets/event/TemperatureChangeEvent.java
new file mode 100644
index 0000000..5de528c
--- /dev/null
+++ b/Java/com/phidgets/event/TemperatureChangeEvent.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2006 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets.event;
+
+import com.phidgets.Phidget;
+
+/**
+ * This class represents the data for a TemperatureChangeEvent.
+ *
+ * @author Phidgets Inc.
+ */
+public class TemperatureChangeEvent
+{
+ Phidget source;
+ int index;
+ double value;
+
+ /**
+ * Class constructor. This is called internally by the phidget library when creating this event.
+ *
+ * @param source the Phidget object from which this event originated
+ */
+ public TemperatureChangeEvent(Phidget source, int index, double value) {
+ this.source = source;
+ this.index = index;
+ this.value = value;
+ }
+
+ /**
+ * Returns the source Phidget of this event. This is a reference to the Phidget object from which this
+ * event was called. This object can be cast into a specific type of Phidget object to call specific
+ * device calls on it.
+ *
+ * @return the event caller
+ */
+ public Phidget getSource() {
+ return source;
+ }
+
+ /**
+ * Returns the index of the temperature sensor. An index of 0 indicated the Cold Juction Temperature sensing IC.
+ * An index of 1 indicated the thermocouple.
+ *
+ * @return the index of the sensor
+ */
+ public int getIndex() {
+ return index;
+ }
+
+ /**
+ * Returns the temperature of the sensor is degrees celcius.
+ *
+ * @return the temperature of the sensor
+ */
+ public double getValue() {
+ return value;
+ }
+
+ /**
+ * Returns a string containing information about the event.
+ *
+ * @return an informative event string
+ */
+ public String toString() {
+ return source.toString() + " Temperature " + index + " changed to "
+ + value;
+ }
+}
diff --git a/Java/com/phidgets/event/TemperatureChangeListener.java b/Java/com/phidgets/event/TemperatureChangeListener.java
new file mode 100644
index 0000000..a9eccb7
--- /dev/null
+++ b/Java/com/phidgets/event/TemperatureChangeListener.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2006 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets.event;
+
+/**
+ * This interface represents a TemperatureChangeEvent. This event originates from the Phidget Temperature Sensor
+ *
+ * @author Phidgets Inc.
+ */
+public interface TemperatureChangeListener
+{
+ /**
+ * This method is called with the event data when a new event arrives.
+ *
+ * @param ae the event data object containing event data
+ */
+ public void temperatureChanged(TemperatureChangeEvent ae);
+}
diff --git a/Java/com/phidgets/event/WeightChangeEvent.java b/Java/com/phidgets/event/WeightChangeEvent.java
new file mode 100644
index 0000000..1277003
--- /dev/null
+++ b/Java/com/phidgets/event/WeightChangeEvent.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2006 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets.event;
+
+import com.phidgets.Phidget;
+
+/**
+ * This class represents the data for a WeightChangeEvent.
+ *
+ * @author Phidgets Inc.
+ */
+public class WeightChangeEvent
+{
+ Phidget source;
+ double value;
+ /**
+ * Class constructor. This is called internally by the phidget library when creating this event.
+ *
+ * @param source the Phidget object from which this event originated
+ */
+ public WeightChangeEvent(Phidget source, double value)
+ {
+ this.source = source;
+ this.value = value;
+ }
+
+ /**
+ * Returns the source Phidget of this event. This is a reference to the Phidget object from which this
+ * event was called. This object can be cast into a specific type of Phidget object to call specific
+ * device calls on it.
+ *
+ * @return the event caller
+ */
+ public Phidget getSource() {
+ return source;
+ }
+
+ /**
+ * Returns the weight in kg.
+ *
+ * @return the weight
+ */
+ public double getValue() {
+ return value;
+ }
+
+ /**
+ * Returns a string containing information about the event.
+ *
+ * @return an informative event string
+ */
+ public String toString() {
+ return source.toString() + " Weight changed to "
+ + value;
+ }
+}
diff --git a/Java/com/phidgets/event/WeightChangeListener.java b/Java/com/phidgets/event/WeightChangeListener.java
new file mode 100644
index 0000000..d6794db
--- /dev/null
+++ b/Java/com/phidgets/event/WeightChangeListener.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2006 Phidgets Inc. All rights reserved.
+ */
+
+package com.phidgets.event;
+
+/**
+ * This interface represents a WeightChangeEvent. This event originates from the Phidget Weight Sensor
+ *
+ * @author Phidgets Inc.
+ */
+public interface WeightChangeListener
+{
+ /**
+ * This method is called with the event data when a new event arrives.
+ *
+ * @param ae the event data object containing event data
+ */
+ public void weightChanged(WeightChangeEvent ae);
+}
diff --git a/Java/com/phidgets/macros/BridgePhidget.jm b/Java/com/phidgets/macros/BridgePhidget.jm
new file mode 100644
index 0000000..d2c2cf5
--- /dev/null
+++ b/Java/com/phidgets/macros/BridgePhidget.jm
@@ -0,0 +1,171 @@
+/*
+ * Copyright 2011 Phidgets Inc. All rights reserved.
+ */
+
+ #include "javamacros.h"
+PACKAGEIMPORTS
+/**
+ * This class represents a Phidget Bridge. All methods
+ * to manipulate the Phidget Bridge are implemented in this class.
+ * <p>
+ *
+ * @author Phidgets Inc.
+ */
+CLASSDEF(Bridge)
+ /**
+ * 1 Gain. This is used with {@link #getGain(int) getGain} and {@link #setGain(int, int) setGain}
+ */
+ public static final int PHIDGET_BRIDGE_GAIN_1 = 1;
+ /**
+ * 8 Gain. This is used with {@link #getGain(int) getGain} and {@link #setGain(int, int) setGain}
+ */
+ public static final int PHIDGET_BRIDGE_GAIN_8 = 2;
+ /**
+ * 16 Gain. This is used with {@link #getGain(int) getGain} and {@link #setGain(int, int) setGain}
+ */
+ public static final int PHIDGET_BRIDGE_GAIN_16 = 3;
+ /**
+ * 32 Gain. This is used with {@link #getGain(int) getGain} and {@link #setGain(int, int) setGain}
+ */
+ public static final int PHIDGET_BRIDGE_GAIN_32 = 4;
+ /**
+ * 64 Gain. This is used with {@link #getGain(int) getGain} and {@link #setGain(int, int) setGain}
+ */
+ public static final int PHIDGET_BRIDGE_GAIN_64 = 5;
+ /**
+ * 128 Gain. This is used with {@link #getGain(int) getGain} and {@link #setGain(int, int) setGain}
+ */
+ public static final int PHIDGET_BRIDGE_GAIN_128 = 6;
+ /**
+ * Unknown Gain. This is used with {@link #getGain(int) getGain} and {@link #setGain(int, int) setGain}
+ */
+ public static final int PHIDGET_BRIDGE_GAIN_UNKNOWN = 7;
+ /**
+ * Returns the number of bridges.
+ * @return Number of bridges
+ */
+ PUBLIC_NATIVE(int, getInputCount,)
+ /**
+ * Returns the value of the selected input, in mV/V. If the input is not enabled, an EPHIDGET_UNKNOWNVAL exception will be thrown. If the bridge is saturated
+ *, this will be equal to BridgeMax or BridgeMin and an error event will be fired - in this case, gain should be reduced if possible.
+ * @param index Index of the bridge
+ * @return bridge value
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is out of range.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ PUBLIC_NATIVE(double, getBridgeValue, int index)
+ /**
+ * Returns the minimum value that the selected bridge can measure, in mV/V. This value will depend on the selected gain. At a gain of 1, BridgeMin == -1000 mV/V.
+ * @param index Index of the bridge
+ * @return minimum value
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is out of range.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ PUBLIC_NATIVE(double, getBridgeMin, int index)
+ /**
+ * Returns the maximum value that the selected bridge can measure, in mV/V. This value will depend on the selected gain. At a gain of 1, BridgeMin == 1000 mV/V.
+ * @param index Index of the bridge
+ * @return maximum value
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is out of range.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ PUBLIC_NATIVE(double, getBridgeMax, int index)
+ /**
+ * Returns the enabled state of the specified bridge. This applies power between +5v and Ground, and starts measuring the differential on the +/- pins. By default, all bridges are
+ * disabled, and need to be explicitly enabled on startup.
+ * @param index Index of the bridge
+ * @return state of the specified bridge
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is invalid.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ PUBLIC_NATIVE(boolean, getEnabled, int index)
+ /**
+ * Sets the enabled state of the specified bridge. This applies power between +5v and Ground, and starts measuring the differential on the +/- pins. By default, all bridges are
+ * disabled, and need to be explicitly enabled on startup.
+ * @param index Index of the bridge
+ * @param state new state of the specified bridge
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is invalid.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ PUBLIC_NATIVE(void, setEnabled, int index, boolean state)
+ /**
+ * Returns the gain for the selected bridge. Note that increasing the gains will reduce the measurable
+ * voltage difference by the gain factor, with +-1000 mV/V being the maximum, with no gain.
+ * The possible values for gain are {@link #PHIDGET_BRIDGE_GAIN_1 PHIDGET_BRIDGE_GAIN_1},
+ * {@link #PHIDGET_BRIDGE_GAIN_8 PHIDGET_BRIDGE_GAIN_8}, {@link #PHIDGET_BRIDGE_GAIN_16 PHIDGET_BRIDGE_GAIN_16},
+ * {@link #PHIDGET_BRIDGE_GAIN_32 PHIDGET_BRIDGE_GAIN_32}, {@link #PHIDGET_BRIDGE_GAIN_64 PHIDGET_BRIDGE_GAIN_64},
+ * {@link #PHIDGET_BRIDGE_GAIN_128 PHIDGET_BRIDGE_GAIN_128}, {@link #PHIDGET_BRIDGE_GAIN_UNKNOWN PHIDGET_BRIDGE_GAIN_UNKNOWN}
+ * <p>
+ * @param index Index of the bridge
+ * @return gain
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is invalid.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ PUBLIC_NATIVE(int, getGain, int index)
+ /**
+ * Sets the gain for the selected bridge. Note that increasing the gains will reduce the measurable
+ * voltage difference by the gain factor, with +-1000 mV/V being the maximum, with no gain.
+ * <p>
+ * The possible values for gain are {@link #PHIDGET_BRIDGE_GAIN_1 PHIDGET_BRIDGE_GAIN_1},
+ * {@link #PHIDGET_BRIDGE_GAIN_8 PHIDGET_BRIDGE_GAIN_8}, {@link #PHIDGET_BRIDGE_GAIN_16 PHIDGET_BRIDGE_GAIN_16},
+ * {@link #PHIDGET_BRIDGE_GAIN_32 PHIDGET_BRIDGE_GAIN_32}, {@link #PHIDGET_BRIDGE_GAIN_64 PHIDGET_BRIDGE_GAIN_64},
+ * {@link #PHIDGET_BRIDGE_GAIN_128 PHIDGET_BRIDGE_GAIN_128}, {@link #PHIDGET_BRIDGE_GAIN_UNKNOWN PHIDGET_BRIDGE_GAIN_UNKNOWN}
+ * <p>
+ * @param index Index of the bridge
+ * @param gain new gain
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is invalid.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ PUBLIC_NATIVE(void, setGain, int index, int gain)
+ /**
+ * Returns the data rate, in ms. Data rate applies to all 4 bridges simultaneously. Setting a slower data rate will reduce
+ * noise at the cost of sample time. Also note that each bridge is being sampled only 1/4 of the time - this is okay for very stable signals,
+ * but for changing signals, it is best to set a higher sampling rate and do averaging in the software.
+ * <p>
+ * Data rate must be a multiple of 8ms. Trying to set something between multiplies of 8 will cause an EPHIDGET_INVALIDARG exception.
+ * <p>
+ * @return Data Rate
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the index is invalid.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ PUBLIC_NATIVE(int, getDataRate,)
+ /**
+ * Sets the data rate, in ms. Data rate applies to all 4 bridges simultaneously. Setting a slower data rate will reduce
+ * noise at the cost of sample time. Also note that each bridge is being sampled only 1/4 of the time - this is okay for very stable signals,
+ * but for changing signals, it is best to set a higher sampling rate and do averaging in the software.
+ * <p>
+ * Data rate must be a multiple of 8ms. Trying to set something between multiplies of 8 will cause an EPHIDGET_INVALIDARG exception.
+ * <p>
+ * @param rate new data rate
+ * @throws PhidgetException If this Phidget is not opened and attached, or if the data rate is out of range
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ PUBLIC_NATIVE(void, setDataRate, int rate)
+ /**
+ * Gets the minimum supported data rate, in ms.
+ * @return minimum supported data rate
+ * @throws PhidgetException If this Phidget is not opened and attached.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ PUBLIC_NATIVE(int, getDataRateMin,)
+ /**
+ * Gets the maximum supported data rate, in ms.
+ * @return maximum supported data rate
+ * @throws PhidgetException If this Phidget is not opened and attached.
+ * See {@link com.phidgets.Phidget#open(int) open} for information on determining if a device is attached.
+ */
+ PUBLIC_NATIVE(int, getDataRateMax,)
+
+ ENABLE_EVENTS
+ {
+ EVENT_ENABLE(bridgeData, BridgeData)
+ }
+ /**
+ * Adds a bridge data listener. The bridge data handler is a method that will be called at the specified data rate, for each enabled bridge. Value is the bridgeValue, in mV/V.
+ * <p>
+ * There is no limit on the number of bridge data handlers that can be registered for a particular Phidget.
+ *
+ * @param l An implemetation of the {@link com.phidgets.event.BridgeDataListener BridgeDataListener} interface
+ */
+ EVENT(bridgeData, BridgeData, bridgeData)
+} \ No newline at end of file
diff --git a/Java/com_phidgets_AccelerometerPhidget.c b/Java/com_phidgets_AccelerometerPhidget.c
new file mode 100644
index 0000000..6d7bd0b
--- /dev/null
+++ b/Java/com_phidgets_AccelerometerPhidget.c
@@ -0,0 +1,21 @@
+#include "../stdafx.h"
+#include "phidget_jni.h"
+#include "com_phidgets_AccelerometerPhidget.h"
+#include "../cphidgetaccelerometer.h"
+
+EVENT_VARS(accelerationChange, AccelerationChange)
+
+JNI_LOAD(accel, Accelerometer)
+ EVENT_VAR_SETUP(accel, accelerationChange, AccelerationChange, ID, V)
+}
+
+EVENT_HANDLER_INDEXED(Accelerometer, accelerationChange, AccelerationChange,
+ CPhidgetAccelerometer_set_OnAccelerationChange_Handler, double)
+
+JNI_CREATE(Accelerometer)
+JNI_INDEXED_GETFUNC(Accelerometer, AccelerationChangeTrigger, AccelerationChangeTrigger, jdouble)
+JNI_INDEXED_SETFUNC(Accelerometer, AccelerationChangeTrigger, AccelerationChangeTrigger, jdouble)
+JNI_INDEXED_GETFUNC(Accelerometer, AccelerationMax, AccelerationMax, jdouble)
+JNI_INDEXED_GETFUNC(Accelerometer, AccelerationMin, AccelerationMin, jdouble)
+JNI_INDEXED_GETFUNC(Accelerometer, Acceleration, Acceleration, jdouble)
+JNI_GETFUNC(Accelerometer, AxisCount, AxisCount, jint)
diff --git a/Java/com_phidgets_AccelerometerPhidget.h b/Java/com_phidgets_AccelerometerPhidget.h
new file mode 100644
index 0000000..15de1ca
--- /dev/null
+++ b/Java/com_phidgets_AccelerometerPhidget.h
@@ -0,0 +1,221 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class com_phidgets_AccelerometerPhidget */
+
+#ifndef _Included_com_phidgets_AccelerometerPhidget
+#define _Included_com_phidgets_AccelerometerPhidget
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef com_phidgets_AccelerometerPhidget_PHIDGET_LOG_CRITICAL
+#define com_phidgets_AccelerometerPhidget_PHIDGET_LOG_CRITICAL 1L
+#undef com_phidgets_AccelerometerPhidget_PHIDGET_LOG_ERROR
+#define com_phidgets_AccelerometerPhidget_PHIDGET_LOG_ERROR 2L
+#undef com_phidgets_AccelerometerPhidget_PHIDGET_LOG_WARNING
+#define com_phidgets_AccelerometerPhidget_PHIDGET_LOG_WARNING 3L
+#undef com_phidgets_AccelerometerPhidget_PHIDGET_LOG_DEBUG
+#define com_phidgets_AccelerometerPhidget_PHIDGET_LOG_DEBUG 4L
+#undef com_phidgets_AccelerometerPhidget_PHIDGET_LOG_INFO
+#define com_phidgets_AccelerometerPhidget_PHIDGET_LOG_INFO 5L
+#undef com_phidgets_AccelerometerPhidget_PHIDGET_LOG_VERBOSE
+#define com_phidgets_AccelerometerPhidget_PHIDGET_LOG_VERBOSE 6L
+#undef com_phidgets_AccelerometerPhidget_PHIDID_NOTHING
+#define com_phidgets_AccelerometerPhidget_PHIDID_NOTHING 1L
+#undef com_phidgets_AccelerometerPhidget_PHIDID_ACCELEROMETER_3AXIS
+#define com_phidgets_AccelerometerPhidget_PHIDID_ACCELEROMETER_3AXIS 126L
+#undef com_phidgets_AccelerometerPhidget_PHIDID_ADVANCEDSERVO_1MOTOR
+#define com_phidgets_AccelerometerPhidget_PHIDID_ADVANCEDSERVO_1MOTOR 130L
+#undef com_phidgets_AccelerometerPhidget_PHIDID_ANALOG_4OUTPUT
+#define com_phidgets_AccelerometerPhidget_PHIDID_ANALOG_4OUTPUT 55L
+#undef com_phidgets_AccelerometerPhidget_PHIDID_ADVANCEDSERVO_8MOTOR
+#define com_phidgets_AccelerometerPhidget_PHIDID_ADVANCEDSERVO_8MOTOR 58L
+#undef com_phidgets_AccelerometerPhidget_PHIDID_BIPOLAR_STEPPER_1MOTOR
+#define com_phidgets_AccelerometerPhidget_PHIDID_BIPOLAR_STEPPER_1MOTOR 123L
+#undef com_phidgets_AccelerometerPhidget_PHIDID_BRIDGE_4INPUT
+#define com_phidgets_AccelerometerPhidget_PHIDID_BRIDGE_4INPUT 59L
+#undef com_phidgets_AccelerometerPhidget_PHIDID_ENCODER_1ENCODER_1INPUT
+#define com_phidgets_AccelerometerPhidget_PHIDID_ENCODER_1ENCODER_1INPUT 75L
+#undef com_phidgets_AccelerometerPhidget_PHIDID_ENCODER_HS_1ENCODER
+#define com_phidgets_AccelerometerPhidget_PHIDID_ENCODER_HS_1ENCODER 128L
+#undef com_phidgets_AccelerometerPhidget_PHIDID_ENCODER_HS_4ENCODER_4INPUT
+#define com_phidgets_AccelerometerPhidget_PHIDID_ENCODER_HS_4ENCODER_4INPUT 79L
+#undef com_phidgets_AccelerometerPhidget_PHIDID_FREQUENCYCOUNTER_2INPUT
+#define com_phidgets_AccelerometerPhidget_PHIDID_FREQUENCYCOUNTER_2INPUT 53L
+#undef com_phidgets_AccelerometerPhidget_PHIDID_GPS
+#define com_phidgets_AccelerometerPhidget_PHIDID_GPS 121L
+#undef com_phidgets_AccelerometerPhidget_PHIDID_INTERFACEKIT_0_0_4
+#define com_phidgets_AccelerometerPhidget_PHIDID_INTERFACEKIT_0_0_4 64L
+#undef com_phidgets_AccelerometerPhidget_PHIDID_INTERFACEKIT_0_0_8
+#define com_phidgets_AccelerometerPhidget_PHIDID_INTERFACEKIT_0_0_8 129L
+#undef com_phidgets_AccelerometerPhidget_PHIDID_INTERFACEKIT_0_16_16
+#define com_phidgets_AccelerometerPhidget_PHIDID_INTERFACEKIT_0_16_16 68L
+#undef com_phidgets_AccelerometerPhidget_PHIDID_INTERFACEKIT_8_8_8
+#define com_phidgets_AccelerometerPhidget_PHIDID_INTERFACEKIT_8_8_8 69L
+#undef com_phidgets_AccelerometerPhidget_PHIDID_INTERFACEKIT_8_8_8_w_LCD
+#define com_phidgets_AccelerometerPhidget_PHIDID_INTERFACEKIT_8_8_8_w_LCD 125L
+#undef com_phidgets_AccelerometerPhidget_PHIDID_IR
+#define com_phidgets_AccelerometerPhidget_PHIDID_IR 77L
+#undef com_phidgets_AccelerometerPhidget_PHIDID_LED_64
+#define com_phidgets_AccelerometerPhidget_PHIDID_LED_64 74L
+#undef com_phidgets_AccelerometerPhidget_PHIDID_LED_64_ADV
+#define com_phidgets_AccelerometerPhidget_PHIDID_LED_64_ADV 76L
+#undef com_phidgets_AccelerometerPhidget_PHIDID_LINEAR_TOUCH
+#define com_phidgets_AccelerometerPhidget_PHIDID_LINEAR_TOUCH 118L
+#undef com_phidgets_AccelerometerPhidget_PHIDID_MOTORCONTROL_HC_2MOTOR
+#define com_phidgets_AccelerometerPhidget_PHIDID_MOTORCONTROL_HC_2MOTOR 89L
+#undef com_phidgets_AccelerometerPhidget_PHIDID_MOTORCONTROL_LV_2MOTOR_4INPUT
+#define com_phidgets_AccelerometerPhidget_PHIDID_MOTORCONTROL_LV_2MOTOR_4INPUT 88L
+#undef com_phidgets_AccelerometerPhidget_PHIDID_MOTORCONTROL_1MOTOR
+#define com_phidgets_AccelerometerPhidget_PHIDID_MOTORCONTROL_1MOTOR 62L
+#undef com_phidgets_AccelerometerPhidget_PHIDID_PHSENSOR
+#define com_phidgets_AccelerometerPhidget_PHIDID_PHSENSOR 116L
+#undef com_phidgets_AccelerometerPhidget_PHIDID_RFID_2OUTPUT
+#define com_phidgets_AccelerometerPhidget_PHIDID_RFID_2OUTPUT 49L
+#undef com_phidgets_AccelerometerPhidget_PHIDID_ROTARY_TOUCH
+#define com_phidgets_AccelerometerPhidget_PHIDID_ROTARY_TOUCH 119L
+#undef com_phidgets_AccelerometerPhidget_PHIDID_SERVO_1MOTOR
+#define com_phidgets_AccelerometerPhidget_PHIDID_SERVO_1MOTOR 57L
+#undef com_phidgets_AccelerometerPhidget_PHIDID_SPATIAL_ACCEL_3AXIS
+#define com_phidgets_AccelerometerPhidget_PHIDID_SPATIAL_ACCEL_3AXIS 127L
+#undef com_phidgets_AccelerometerPhidget_PHIDID_SPATIAL_ACCEL_GYRO_COMPASS
+#define com_phidgets_AccelerometerPhidget_PHIDID_SPATIAL_ACCEL_GYRO_COMPASS 51L
+#undef com_phidgets_AccelerometerPhidget_PHIDID_TEMPERATURESENSOR
+#define com_phidgets_AccelerometerPhidget_PHIDID_TEMPERATURESENSOR 112L
+#undef com_phidgets_AccelerometerPhidget_PHIDID_TEMPERATURESENSOR_4
+#define com_phidgets_AccelerometerPhidget_PHIDID_TEMPERATURESENSOR_4 50L
+#undef com_phidgets_AccelerometerPhidget_PHIDID_TEXTLCD_2x20_w_8_8_8
+#define com_phidgets_AccelerometerPhidget_PHIDID_TEXTLCD_2x20_w_8_8_8 381L
+#undef com_phidgets_AccelerometerPhidget_PHIDID_TEXTLCD_ADAPTER
+#define com_phidgets_AccelerometerPhidget_PHIDID_TEXTLCD_ADAPTER 61L
+#undef com_phidgets_AccelerometerPhidget_PHIDID_UNIPOLAR_STEPPER_4MOTOR
+#define com_phidgets_AccelerometerPhidget_PHIDID_UNIPOLAR_STEPPER_4MOTOR 122L
+#undef com_phidgets_AccelerometerPhidget_PHIDID_ACCELEROMETER_2AXIS
+#define com_phidgets_AccelerometerPhidget_PHIDID_ACCELEROMETER_2AXIS 113L
+#undef com_phidgets_AccelerometerPhidget_PHIDID_INTERFACEKIT_0_8_8_w_LCD
+#define com_phidgets_AccelerometerPhidget_PHIDID_INTERFACEKIT_0_8_8_w_LCD 83L
+#undef com_phidgets_AccelerometerPhidget_PHIDID_INTERFACEKIT_4_8_8
+#define com_phidgets_AccelerometerPhidget_PHIDID_INTERFACEKIT_4_8_8 4L
+#undef com_phidgets_AccelerometerPhidget_PHIDID_RFID
+#define com_phidgets_AccelerometerPhidget_PHIDID_RFID 48L
+#undef com_phidgets_AccelerometerPhidget_PHIDID_SERVO_1MOTOR_OLD
+#define com_phidgets_AccelerometerPhidget_PHIDID_SERVO_1MOTOR_OLD 2L
+#undef com_phidgets_AccelerometerPhidget_PHIDID_SERVO_4MOTOR
+#define com_phidgets_AccelerometerPhidget_PHIDID_SERVO_4MOTOR 56L
+#undef com_phidgets_AccelerometerPhidget_PHIDID_SERVO_4MOTOR_OLD
+#define com_phidgets_AccelerometerPhidget_PHIDID_SERVO_4MOTOR_OLD 3L
+#undef com_phidgets_AccelerometerPhidget_PHIDID_TEXTLCD_2x20
+#define com_phidgets_AccelerometerPhidget_PHIDID_TEXTLCD_2x20 82L
+#undef com_phidgets_AccelerometerPhidget_PHIDID_TEXTLCD_2x20_w_0_8_8
+#define com_phidgets_AccelerometerPhidget_PHIDID_TEXTLCD_2x20_w_0_8_8 339L
+#undef com_phidgets_AccelerometerPhidget_PHIDID_TEXTLED_1x8
+#define com_phidgets_AccelerometerPhidget_PHIDID_TEXTLED_1x8 73L
+#undef com_phidgets_AccelerometerPhidget_PHIDID_TEXTLED_4x8
+#define com_phidgets_AccelerometerPhidget_PHIDID_TEXTLED_4x8 72L
+#undef com_phidgets_AccelerometerPhidget_PHIDID_WEIGHTSENSOR
+#define com_phidgets_AccelerometerPhidget_PHIDID_WEIGHTSENSOR 114L
+#undef com_phidgets_AccelerometerPhidget_PHIDCLASS_NOTHING
+#define com_phidgets_AccelerometerPhidget_PHIDCLASS_NOTHING 1L
+#undef com_phidgets_AccelerometerPhidget_PHIDCLASS_ACCELEROMETER
+#define com_phidgets_AccelerometerPhidget_PHIDCLASS_ACCELEROMETER 2L
+#undef com_phidgets_AccelerometerPhidget_PHIDCLASS_ADVANCEDSERVO
+#define com_phidgets_AccelerometerPhidget_PHIDCLASS_ADVANCEDSERVO 3L
+#undef com_phidgets_AccelerometerPhidget_PHIDCLASS_ANALOG
+#define com_phidgets_AccelerometerPhidget_PHIDCLASS_ANALOG 22L
+#undef com_phidgets_AccelerometerPhidget_PHIDCLASS_BRIDGE
+#define com_phidgets_AccelerometerPhidget_PHIDCLASS_BRIDGE 23L
+#undef com_phidgets_AccelerometerPhidget_PHIDCLASS_ENCODER
+#define com_phidgets_AccelerometerPhidget_PHIDCLASS_ENCODER 4L
+#undef com_phidgets_AccelerometerPhidget_PHIDCLASS_FREQUENCYCOUNTER
+#define com_phidgets_AccelerometerPhidget_PHIDCLASS_FREQUENCYCOUNTER 21L
+#undef com_phidgets_AccelerometerPhidget_PHIDCLASS_GPS
+#define com_phidgets_AccelerometerPhidget_PHIDCLASS_GPS 5L
+#undef com_phidgets_AccelerometerPhidget_PHIDCLASS_INTERFACEKIT
+#define com_phidgets_AccelerometerPhidget_PHIDCLASS_INTERFACEKIT 7L
+#undef com_phidgets_AccelerometerPhidget_PHIDCLASS_LED
+#define com_phidgets_AccelerometerPhidget_PHIDCLASS_LED 8L
+#undef com_phidgets_AccelerometerPhidget_PHIDCLASS_MOTORCONTROL
+#define com_phidgets_AccelerometerPhidget_PHIDCLASS_MOTORCONTROL 9L
+#undef com_phidgets_AccelerometerPhidget_PHIDCLASS_PHSENSOR
+#define com_phidgets_AccelerometerPhidget_PHIDCLASS_PHSENSOR 10L
+#undef com_phidgets_AccelerometerPhidget_PHIDCLASS_RFID
+#define com_phidgets_AccelerometerPhidget_PHIDCLASS_RFID 11L
+#undef com_phidgets_AccelerometerPhidget_PHIDCLASS_SERVO
+#define com_phidgets_AccelerometerPhidget_PHIDCLASS_SERVO 12L
+#undef com_phidgets_AccelerometerPhidget_PHIDCLASS_STEPPER
+#define com_phidgets_AccelerometerPhidget_PHIDCLASS_STEPPER 13L
+#undef com_phidgets_AccelerometerPhidget_PHIDCLASS_TEMPERATURESENSOR
+#define com_phidgets_AccelerometerPhidget_PHIDCLASS_TEMPERATURESENSOR 14L
+#undef com_phidgets_AccelerometerPhidget_PHIDCLASS_TEXTLCD
+#define com_phidgets_AccelerometerPhidget_PHIDCLASS_TEXTLCD 15L
+#undef com_phidgets_AccelerometerPhidget_PHIDCLASS_TEXTLED
+#define com_phidgets_AccelerometerPhidget_PHIDCLASS_TEXTLED 16L
+#undef com_phidgets_AccelerometerPhidget_PHIDCLASS_WEIGHTSENSOR
+#define com_phidgets_AccelerometerPhidget_PHIDCLASS_WEIGHTSENSOR 17L
+/*
+ * Class: com_phidgets_AccelerometerPhidget
+ * Method: create
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL Java_com_phidgets_AccelerometerPhidget_create
+ (JNIEnv *, jclass);
+
+/*
+ * Class: com_phidgets_AccelerometerPhidget
+ * Method: getAxisCount
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_phidgets_AccelerometerPhidget_getAxisCount
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_AccelerometerPhidget
+ * Method: getAcceleration
+ * Signature: (I)D
+ */
+JNIEXPORT jdouble JNICALL Java_com_phidgets_AccelerometerPhidget_getAcceleration
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_AccelerometerPhidget
+ * Method: getAccelerationMax
+ * Signature: (I)D
+ */
+JNIEXPORT jdouble JNICALL Java_com_phidgets_AccelerometerPhidget_getAccelerationMax
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_AccelerometerPhidget
+ * Method: getAccelerationMin
+ * Signature: (I)D
+ */
+JNIEXPORT jdouble JNICALL Java_com_phidgets_AccelerometerPhidget_getAccelerationMin
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_AccelerometerPhidget
+ * Method: setAccelerationChangeTrigger
+ * Signature: (ID)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_AccelerometerPhidget_setAccelerationChangeTrigger
+ (JNIEnv *, jobject, jint, jdouble);
+
+/*
+ * Class: com_phidgets_AccelerometerPhidget
+ * Method: getAccelerationChangeTrigger
+ * Signature: (I)D
+ */
+JNIEXPORT jdouble JNICALL Java_com_phidgets_AccelerometerPhidget_getAccelerationChangeTrigger
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_AccelerometerPhidget
+ * Method: enableAccelerationChangeEvents
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_AccelerometerPhidget_enableAccelerationChangeEvents
+ (JNIEnv *, jobject, jboolean);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/Java/com_phidgets_AdvancedServoPhidget.c b/Java/com_phidgets_AdvancedServoPhidget.c
new file mode 100644
index 0000000..960ce29
--- /dev/null
+++ b/Java/com_phidgets_AdvancedServoPhidget.c
@@ -0,0 +1,66 @@
+#include "../stdafx.h"
+#include "phidget_jni.h"
+#include "com_phidgets_AdvancedServoPhidget.h"
+#include "../cphidgetadvancedservo.h"
+
+EVENT_VARS(servoPositionChange, ServoPositionChange)
+EVENT_VARS(servoVelocityChange, ServoVelocityChange)
+EVENT_VARS(currentChange, CurrentChange)
+
+JNI_LOAD(advservo, AdvancedServo)
+ EVENT_VAR_SETUP(advservo, servoPositionChange, ServoPositionChange, ID, V)
+ EVENT_VAR_SETUP(advservo, servoVelocityChange, ServoVelocityChange, ID, V)
+ EVENT_VAR_SETUP(advservo, currentChange, CurrentChange, ID, V)
+}
+
+EVENT_HANDLER_INDEXED(AdvancedServo, servoPositionChange, ServoPositionChange,
+ CPhidgetAdvancedServo_set_OnPositionChange_Handler, double)
+EVENT_HANDLER_INDEXED(AdvancedServo, servoVelocityChange, ServoVelocityChange,
+ CPhidgetAdvancedServo_set_OnVelocityChange_Handler, double)
+EVENT_HANDLER_INDEXED(AdvancedServo, currentChange, CurrentChange,
+ CPhidgetAdvancedServo_set_OnCurrentChange_Handler, double)
+
+JNI_CREATE(AdvancedServo)
+JNI_INDEXED_GETFUNC(AdvancedServo, Acceleration, Acceleration, jdouble)
+JNI_INDEXED_SETFUNC(AdvancedServo, Acceleration, Acceleration, jdouble)
+JNI_INDEXED_GETFUNC(AdvancedServo, AccelerationMin, AccelerationMin, jdouble)
+JNI_INDEXED_GETFUNC(AdvancedServo, AccelerationMax, AccelerationMax, jdouble)
+JNI_INDEXED_GETFUNC(AdvancedServo, VelocityLimit, VelocityLimit, jdouble)
+JNI_INDEXED_SETFUNC(AdvancedServo, VelocityLimit, VelocityLimit, jdouble)
+JNI_INDEXED_GETFUNC(AdvancedServo, Velocity, Velocity, jdouble)
+JNI_INDEXED_GETFUNC(AdvancedServo, VelocityMin, VelocityMin, jdouble)
+JNI_INDEXED_GETFUNC(AdvancedServo, VelocityMax, VelocityMax, jdouble)
+JNI_INDEXED_GETFUNC(AdvancedServo, Position, Position, jdouble)
+JNI_INDEXED_SETFUNC(AdvancedServo, Position, Position, jdouble)
+JNI_INDEXED_GETFUNC(AdvancedServo, PositionMin, PositionMin, jdouble)
+JNI_INDEXED_GETFUNC(AdvancedServo, PositionMax, PositionMax, jdouble)
+JNI_INDEXED_SETFUNC(AdvancedServo, PositionMin, PositionMin, jdouble)
+JNI_INDEXED_SETFUNC(AdvancedServo, PositionMax, PositionMax, jdouble)
+JNI_INDEXED_GETFUNCBOOL(AdvancedServo, Engaged, Engaged)
+JNI_INDEXED_SETFUNC(AdvancedServo, Engaged, Engaged, jboolean)
+JNI_INDEXED_GETFUNCBOOL(AdvancedServo, Stopped, Stopped)
+JNI_INDEXED_GETFUNCBOOL(AdvancedServo, SpeedRampingOn, SpeedRampingOn)
+JNI_INDEXED_SETFUNC(AdvancedServo, SpeedRampingOn, SpeedRampingOn, jboolean)
+JNI_INDEXED_GETFUNC(AdvancedServo, Current, Current, jdouble)
+JNIEXPORT jint JNICALL
+Java_com_phidgets_AdvancedServoPhidget_getServoType(JNIEnv *env, jobject obj, jint index)
+{
+ CPhidgetAdvancedServoHandle h = (CPhidgetAdvancedServoHandle)(uintptr_t)
+ (*env)->GetLongField(env, obj, handle_fid);
+ int error;
+ CPhidget_ServoType v;
+ if ((error = CPhidgetAdvancedServo_getServoType(h, index, &v)))
+ PH_THROW(error);
+ return (jint)v;
+}
+JNI_INDEXED_SETFUNC(AdvancedServo, ServoType, ServoType, jint)
+JNIEXPORT void JNICALL
+Java_com_phidgets_AdvancedServoPhidget_setServoParameters(JNIEnv *env, jobject obj, jint index, jdouble minUs, jdouble maxUs, jdouble degrees, jdouble velocityMax)
+{
+ CPhidgetAdvancedServoHandle h = (CPhidgetAdvancedServoHandle)(uintptr_t)
+ (*env)->GetLongField(env, obj, handle_fid);
+ int error;
+ if ((error = CPhidgetAdvancedServo_setServoParameters(h, index, minUs, maxUs, degrees, velocityMax)))
+ PH_THROW(error);
+}
+JNI_GETFUNC(AdvancedServo, MotorCount, MotorCount, jint)
diff --git a/Java/com_phidgets_AdvancedServoPhidget.h b/Java/com_phidgets_AdvancedServoPhidget.h
new file mode 100644
index 0000000..1f7b40c
--- /dev/null
+++ b/Java/com_phidgets_AdvancedServoPhidget.h
@@ -0,0 +1,439 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class com_phidgets_AdvancedServoPhidget */
+
+#ifndef _Included_com_phidgets_AdvancedServoPhidget
+#define _Included_com_phidgets_AdvancedServoPhidget
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef com_phidgets_AdvancedServoPhidget_PHIDGET_LOG_CRITICAL
+#define com_phidgets_AdvancedServoPhidget_PHIDGET_LOG_CRITICAL 1L
+#undef com_phidgets_AdvancedServoPhidget_PHIDGET_LOG_ERROR
+#define com_phidgets_AdvancedServoPhidget_PHIDGET_LOG_ERROR 2L
+#undef com_phidgets_AdvancedServoPhidget_PHIDGET_LOG_WARNING
+#define com_phidgets_AdvancedServoPhidget_PHIDGET_LOG_WARNING 3L
+#undef com_phidgets_AdvancedServoPhidget_PHIDGET_LOG_DEBUG
+#define com_phidgets_AdvancedServoPhidget_PHIDGET_LOG_DEBUG 4L
+#undef com_phidgets_AdvancedServoPhidget_PHIDGET_LOG_INFO
+#define com_phidgets_AdvancedServoPhidget_PHIDGET_LOG_INFO 5L
+#undef com_phidgets_AdvancedServoPhidget_PHIDGET_LOG_VERBOSE
+#define com_phidgets_AdvancedServoPhidget_PHIDGET_LOG_VERBOSE 6L
+#undef com_phidgets_AdvancedServoPhidget_PHIDID_NOTHING
+#define com_phidgets_AdvancedServoPhidget_PHIDID_NOTHING 1L
+#undef com_phidgets_AdvancedServoPhidget_PHIDID_ACCELEROMETER_3AXIS
+#define com_phidgets_AdvancedServoPhidget_PHIDID_ACCELEROMETER_3AXIS 126L
+#undef com_phidgets_AdvancedServoPhidget_PHIDID_ADVANCEDSERVO_1MOTOR
+#define com_phidgets_AdvancedServoPhidget_PHIDID_ADVANCEDSERVO_1MOTOR 130L
+#undef com_phidgets_AdvancedServoPhidget_PHIDID_ANALOG_4OUTPUT
+#define com_phidgets_AdvancedServoPhidget_PHIDID_ANALOG_4OUTPUT 55L
+#undef com_phidgets_AdvancedServoPhidget_PHIDID_ADVANCEDSERVO_8MOTOR
+#define com_phidgets_AdvancedServoPhidget_PHIDID_ADVANCEDSERVO_8MOTOR 58L
+#undef com_phidgets_AdvancedServoPhidget_PHIDID_BIPOLAR_STEPPER_1MOTOR
+#define com_phidgets_AdvancedServoPhidget_PHIDID_BIPOLAR_STEPPER_1MOTOR 123L
+#undef com_phidgets_AdvancedServoPhidget_PHIDID_BRIDGE_4INPUT
+#define com_phidgets_AdvancedServoPhidget_PHIDID_BRIDGE_4INPUT 59L
+#undef com_phidgets_AdvancedServoPhidget_PHIDID_ENCODER_1ENCODER_1INPUT
+#define com_phidgets_AdvancedServoPhidget_PHIDID_ENCODER_1ENCODER_1INPUT 75L
+#undef com_phidgets_AdvancedServoPhidget_PHIDID_ENCODER_HS_1ENCODER
+#define com_phidgets_AdvancedServoPhidget_PHIDID_ENCODER_HS_1ENCODER 128L
+#undef com_phidgets_AdvancedServoPhidget_PHIDID_ENCODER_HS_4ENCODER_4INPUT
+#define com_phidgets_AdvancedServoPhidget_PHIDID_ENCODER_HS_4ENCODER_4INPUT 79L
+#undef com_phidgets_AdvancedServoPhidget_PHIDID_FREQUENCYCOUNTER_2INPUT
+#define com_phidgets_AdvancedServoPhidget_PHIDID_FREQUENCYCOUNTER_2INPUT 53L
+#undef com_phidgets_AdvancedServoPhidget_PHIDID_GPS
+#define com_phidgets_AdvancedServoPhidget_PHIDID_GPS 121L
+#undef com_phidgets_AdvancedServoPhidget_PHIDID_INTERFACEKIT_0_0_4
+#define com_phidgets_AdvancedServoPhidget_PHIDID_INTERFACEKIT_0_0_4 64L
+#undef com_phidgets_AdvancedServoPhidget_PHIDID_INTERFACEKIT_0_0_8
+#define com_phidgets_AdvancedServoPhidget_PHIDID_INTERFACEKIT_0_0_8 129L
+#undef com_phidgets_AdvancedServoPhidget_PHIDID_INTERFACEKIT_0_16_16
+#define com_phidgets_AdvancedServoPhidget_PHIDID_INTERFACEKIT_0_16_16 68L
+#undef com_phidgets_AdvancedServoPhidget_PHIDID_INTERFACEKIT_8_8_8
+#define com_phidgets_AdvancedServoPhidget_PHIDID_INTERFACEKIT_8_8_8 69L
+#undef com_phidgets_AdvancedServoPhidget_PHIDID_INTERFACEKIT_8_8_8_w_LCD
+#define com_phidgets_AdvancedServoPhidget_PHIDID_INTERFACEKIT_8_8_8_w_LCD 125L
+#undef com_phidgets_AdvancedServoPhidget_PHIDID_IR
+#define com_phidgets_AdvancedServoPhidget_PHIDID_IR 77L
+#undef com_phidgets_AdvancedServoPhidget_PHIDID_LED_64
+#define com_phidgets_AdvancedServoPhidget_PHIDID_LED_64 74L
+#undef com_phidgets_AdvancedServoPhidget_PHIDID_LED_64_ADV
+#define com_phidgets_AdvancedServoPhidget_PHIDID_LED_64_ADV 76L
+#undef com_phidgets_AdvancedServoPhidget_PHIDID_LINEAR_TOUCH
+#define com_phidgets_AdvancedServoPhidget_PHIDID_LINEAR_TOUCH 118L
+#undef com_phidgets_AdvancedServoPhidget_PHIDID_MOTORCONTROL_HC_2MOTOR
+#define com_phidgets_AdvancedServoPhidget_PHIDID_MOTORCONTROL_HC_2MOTOR 89L
+#undef com_phidgets_AdvancedServoPhidget_PHIDID_MOTORCONTROL_LV_2MOTOR_4INPUT
+#define com_phidgets_AdvancedServoPhidget_PHIDID_MOTORCONTROL_LV_2MOTOR_4INPUT 88L
+#undef com_phidgets_AdvancedServoPhidget_PHIDID_MOTORCONTROL_1MOTOR
+#define com_phidgets_AdvancedServoPhidget_PHIDID_MOTORCONTROL_1MOTOR 62L
+#undef com_phidgets_AdvancedServoPhidget_PHIDID_PHSENSOR
+#define com_phidgets_AdvancedServoPhidget_PHIDID_PHSENSOR 116L
+#undef com_phidgets_AdvancedServoPhidget_PHIDID_RFID_2OUTPUT
+#define com_phidgets_AdvancedServoPhidget_PHIDID_RFID_2OUTPUT 49L
+#undef com_phidgets_AdvancedServoPhidget_PHIDID_ROTARY_TOUCH
+#define com_phidgets_AdvancedServoPhidget_PHIDID_ROTARY_TOUCH 119L
+#undef com_phidgets_AdvancedServoPhidget_PHIDID_SERVO_1MOTOR
+#define com_phidgets_AdvancedServoPhidget_PHIDID_SERVO_1MOTOR 57L
+#undef com_phidgets_AdvancedServoPhidget_PHIDID_SPATIAL_ACCEL_3AXIS
+#define com_phidgets_AdvancedServoPhidget_PHIDID_SPATIAL_ACCEL_3AXIS 127L
+#undef com_phidgets_AdvancedServoPhidget_PHIDID_SPATIAL_ACCEL_GYRO_COMPASS
+#define com_phidgets_AdvancedServoPhidget_PHIDID_SPATIAL_ACCEL_GYRO_COMPASS 51L
+#undef com_phidgets_AdvancedServoPhidget_PHIDID_TEMPERATURESENSOR
+#define com_phidgets_AdvancedServoPhidget_PHIDID_TEMPERATURESENSOR 112L
+#undef com_phidgets_AdvancedServoPhidget_PHIDID_TEMPERATURESENSOR_4
+#define com_phidgets_AdvancedServoPhidget_PHIDID_TEMPERATURESENSOR_4 50L
+#undef com_phidgets_AdvancedServoPhidget_PHIDID_TEXTLCD_2x20_w_8_8_8
+#define com_phidgets_AdvancedServoPhidget_PHIDID_TEXTLCD_2x20_w_8_8_8 381L
+#undef com_phidgets_AdvancedServoPhidget_PHIDID_TEXTLCD_ADAPTER
+#define com_phidgets_AdvancedServoPhidget_PHIDID_TEXTLCD_ADAPTER 61L
+#undef com_phidgets_AdvancedServoPhidget_PHIDID_UNIPOLAR_STEPPER_4MOTOR
+#define com_phidgets_AdvancedServoPhidget_PHIDID_UNIPOLAR_STEPPER_4MOTOR 122L
+#undef com_phidgets_AdvancedServoPhidget_PHIDID_ACCELEROMETER_2AXIS
+#define com_phidgets_AdvancedServoPhidget_PHIDID_ACCELEROMETER_2AXIS 113L
+#undef com_phidgets_AdvancedServoPhidget_PHIDID_INTERFACEKIT_0_8_8_w_LCD
+#define com_phidgets_AdvancedServoPhidget_PHIDID_INTERFACEKIT_0_8_8_w_LCD 83L
+#undef com_phidgets_AdvancedServoPhidget_PHIDID_INTERFACEKIT_4_8_8
+#define com_phidgets_AdvancedServoPhidget_PHIDID_INTERFACEKIT_4_8_8 4L
+#undef com_phidgets_AdvancedServoPhidget_PHIDID_RFID
+#define com_phidgets_AdvancedServoPhidget_PHIDID_RFID 48L
+#undef com_phidgets_AdvancedServoPhidget_PHIDID_SERVO_1MOTOR_OLD
+#define com_phidgets_AdvancedServoPhidget_PHIDID_SERVO_1MOTOR_OLD 2L
+#undef com_phidgets_AdvancedServoPhidget_PHIDID_SERVO_4MOTOR
+#define com_phidgets_AdvancedServoPhidget_PHIDID_SERVO_4MOTOR 56L
+#undef com_phidgets_AdvancedServoPhidget_PHIDID_SERVO_4MOTOR_OLD
+#define com_phidgets_AdvancedServoPhidget_PHIDID_SERVO_4MOTOR_OLD 3L
+#undef com_phidgets_AdvancedServoPhidget_PHIDID_TEXTLCD_2x20
+#define com_phidgets_AdvancedServoPhidget_PHIDID_TEXTLCD_2x20 82L
+#undef com_phidgets_AdvancedServoPhidget_PHIDID_TEXTLCD_2x20_w_0_8_8
+#define com_phidgets_AdvancedServoPhidget_PHIDID_TEXTLCD_2x20_w_0_8_8 339L
+#undef com_phidgets_AdvancedServoPhidget_PHIDID_TEXTLED_1x8
+#define com_phidgets_AdvancedServoPhidget_PHIDID_TEXTLED_1x8 73L
+#undef com_phidgets_AdvancedServoPhidget_PHIDID_TEXTLED_4x8
+#define com_phidgets_AdvancedServoPhidget_PHIDID_TEXTLED_4x8 72L
+#undef com_phidgets_AdvancedServoPhidget_PHIDID_WEIGHTSENSOR
+#define com_phidgets_AdvancedServoPhidget_PHIDID_WEIGHTSENSOR 114L
+#undef com_phidgets_AdvancedServoPhidget_PHIDCLASS_NOTHING
+#define com_phidgets_AdvancedServoPhidget_PHIDCLASS_NOTHING 1L
+#undef com_phidgets_AdvancedServoPhidget_PHIDCLASS_ACCELEROMETER
+#define com_phidgets_AdvancedServoPhidget_PHIDCLASS_ACCELEROMETER 2L
+#undef com_phidgets_AdvancedServoPhidget_PHIDCLASS_ADVANCEDSERVO
+#define com_phidgets_AdvancedServoPhidget_PHIDCLASS_ADVANCEDSERVO 3L
+#undef com_phidgets_AdvancedServoPhidget_PHIDCLASS_ANALOG
+#define com_phidgets_AdvancedServoPhidget_PHIDCLASS_ANALOG 22L
+#undef com_phidgets_AdvancedServoPhidget_PHIDCLASS_BRIDGE
+#define com_phidgets_AdvancedServoPhidget_PHIDCLASS_BRIDGE 23L
+#undef com_phidgets_AdvancedServoPhidget_PHIDCLASS_ENCODER
+#define com_phidgets_AdvancedServoPhidget_PHIDCLASS_ENCODER 4L
+#undef com_phidgets_AdvancedServoPhidget_PHIDCLASS_FREQUENCYCOUNTER
+#define com_phidgets_AdvancedServoPhidget_PHIDCLASS_FREQUENCYCOUNTER 21L
+#undef com_phidgets_AdvancedServoPhidget_PHIDCLASS_GPS
+#define com_phidgets_AdvancedServoPhidget_PHIDCLASS_GPS 5L
+#undef com_phidgets_AdvancedServoPhidget_PHIDCLASS_INTERFACEKIT
+#define com_phidgets_AdvancedServoPhidget_PHIDCLASS_INTERFACEKIT 7L
+#undef com_phidgets_AdvancedServoPhidget_PHIDCLASS_LED
+#define com_phidgets_AdvancedServoPhidget_PHIDCLASS_LED 8L
+#undef com_phidgets_AdvancedServoPhidget_PHIDCLASS_MOTORCONTROL
+#define com_phidgets_AdvancedServoPhidget_PHIDCLASS_MOTORCONTROL 9L
+#undef com_phidgets_AdvancedServoPhidget_PHIDCLASS_PHSENSOR
+#define com_phidgets_AdvancedServoPhidget_PHIDCLASS_PHSENSOR 10L
+#undef com_phidgets_AdvancedServoPhidget_PHIDCLASS_RFID
+#define com_phidgets_AdvancedServoPhidget_PHIDCLASS_RFID 11L
+#undef com_phidgets_AdvancedServoPhidget_PHIDCLASS_SERVO
+#define com_phidgets_AdvancedServoPhidget_PHIDCLASS_SERVO 12L
+#undef com_phidgets_AdvancedServoPhidget_PHIDCLASS_STEPPER
+#define com_phidgets_AdvancedServoPhidget_PHIDCLASS_STEPPER 13L
+#undef com_phidgets_AdvancedServoPhidget_PHIDCLASS_TEMPERATURESENSOR
+#define com_phidgets_AdvancedServoPhidget_PHIDCLASS_TEMPERATURESENSOR 14L
+#undef com_phidgets_AdvancedServoPhidget_PHIDCLASS_TEXTLCD
+#define com_phidgets_AdvancedServoPhidget_PHIDCLASS_TEXTLCD 15L
+#undef com_phidgets_AdvancedServoPhidget_PHIDCLASS_TEXTLED
+#define com_phidgets_AdvancedServoPhidget_PHIDCLASS_TEXTLED 16L
+#undef com_phidgets_AdvancedServoPhidget_PHIDCLASS_WEIGHTSENSOR
+#define com_phidgets_AdvancedServoPhidget_PHIDCLASS_WEIGHTSENSOR 17L
+#undef com_phidgets_AdvancedServoPhidget_PHIDGET_SERVO_DEFAULT
+#define com_phidgets_AdvancedServoPhidget_PHIDGET_SERVO_DEFAULT 1L
+#undef com_phidgets_AdvancedServoPhidget_PHIDGET_SERVO_RAW_us_MODE
+#define com_phidgets_AdvancedServoPhidget_PHIDGET_SERVO_RAW_us_MODE 2L
+#undef com_phidgets_AdvancedServoPhidget_PHIDGET_SERVO_HITEC_HS322HD
+#define com_phidgets_AdvancedServoPhidget_PHIDGET_SERVO_HITEC_HS322HD 3L
+#undef com_phidgets_AdvancedServoPhidget_PHIDGET_SERVO_HITEC_HS5245MG
+#define com_phidgets_AdvancedServoPhidget_PHIDGET_SERVO_HITEC_HS5245MG 4L
+#undef com_phidgets_AdvancedServoPhidget_PHIDGET_SERVO_HITEC_805BB
+#define com_phidgets_AdvancedServoPhidget_PHIDGET_SERVO_HITEC_805BB 5L
+#undef com_phidgets_AdvancedServoPhidget_PHIDGET_SERVO_HITEC_HS422
+#define com_phidgets_AdvancedServoPhidget_PHIDGET_SERVO_HITEC_HS422 6L
+#undef com_phidgets_AdvancedServoPhidget_PHIDGET_SERVO_TOWERPRO_MG90
+#define com_phidgets_AdvancedServoPhidget_PHIDGET_SERVO_TOWERPRO_MG90 7L
+#undef com_phidgets_AdvancedServoPhidget_PHIDGET_SERVO_HITEC_HSR1425CR
+#define com_phidgets_AdvancedServoPhidget_PHIDGET_SERVO_HITEC_HSR1425CR 8L
+#undef com_phidgets_AdvancedServoPhidget_PHIDGET_SERVO_HITEC_HS785HB
+#define com_phidgets_AdvancedServoPhidget_PHIDGET_SERVO_HITEC_HS785HB 9L
+#undef com_phidgets_AdvancedServoPhidget_PHIDGET_SERVO_HITEC_HS485HB
+#define com_phidgets_AdvancedServoPhidget_PHIDGET_SERVO_HITEC_HS485HB 10L
+#undef com_phidgets_AdvancedServoPhidget_PHIDGET_SERVO_HITEC_HS645MG
+#define com_phidgets_AdvancedServoPhidget_PHIDGET_SERVO_HITEC_HS645MG 11L
+#undef com_phidgets_AdvancedServoPhidget_PHIDGET_SERVO_HITEC_815BB
+#define com_phidgets_AdvancedServoPhidget_PHIDGET_SERVO_HITEC_815BB 12L
+#undef com_phidgets_AdvancedServoPhidget_PHIDGET_SERVO_FIRGELLI_L12_30_50_06_R
+#define com_phidgets_AdvancedServoPhidget_PHIDGET_SERVO_FIRGELLI_L12_30_50_06_R 13L
+#undef com_phidgets_AdvancedServoPhidget_PHIDGET_SERVO_FIRGELLI_L12_50_100_06_R
+#define com_phidgets_AdvancedServoPhidget_PHIDGET_SERVO_FIRGELLI_L12_50_100_06_R 14L
+#undef com_phidgets_AdvancedServoPhidget_PHIDGET_SERVO_FIRGELLI_L12_50_210_06_R
+#define com_phidgets_AdvancedServoPhidget_PHIDGET_SERVO_FIRGELLI_L12_50_210_06_R 15L
+#undef com_phidgets_AdvancedServoPhidget_PHIDGET_SERVO_FIRGELLI_L12_100_50_06_R
+#define com_phidgets_AdvancedServoPhidget_PHIDGET_SERVO_FIRGELLI_L12_100_50_06_R 16L
+#undef com_phidgets_AdvancedServoPhidget_PHIDGET_SERVO_FIRGELLI_L12_100_100_06_R
+#define com_phidgets_AdvancedServoPhidget_PHIDGET_SERVO_FIRGELLI_L12_100_100_06_R 17L
+#undef com_phidgets_AdvancedServoPhidget_PHIDGET_SERVO_SPRINGRC_SM_S2313M
+#define com_phidgets_AdvancedServoPhidget_PHIDGET_SERVO_SPRINGRC_SM_S2313M 18L
+#undef com_phidgets_AdvancedServoPhidget_PHIDGET_SERVO_SPRINGRC_SM_S3317M
+#define com_phidgets_AdvancedServoPhidget_PHIDGET_SERVO_SPRINGRC_SM_S3317M 19L
+#undef com_phidgets_AdvancedServoPhidget_PHIDGET_SERVO_SPRINGRC_SM_S3317SR
+#define com_phidgets_AdvancedServoPhidget_PHIDGET_SERVO_SPRINGRC_SM_S3317SR 20L
+#undef com_phidgets_AdvancedServoPhidget_PHIDGET_SERVO_SPRINGRC_SM_S4303R
+#define com_phidgets_AdvancedServoPhidget_PHIDGET_SERVO_SPRINGRC_SM_S4303R 21L
+#undef com_phidgets_AdvancedServoPhidget_PHIDGET_SERVO_SPRINGRC_SM_S4315M
+#define com_phidgets_AdvancedServoPhidget_PHIDGET_SERVO_SPRINGRC_SM_S4315M 22L
+#undef com_phidgets_AdvancedServoPhidget_PHIDGET_SERVO_SPRINGRC_SM_S4315R
+#define com_phidgets_AdvancedServoPhidget_PHIDGET_SERVO_SPRINGRC_SM_S4315R 23L
+#undef com_phidgets_AdvancedServoPhidget_PHIDGET_SERVO_SPRINGRC_SM_S4505B
+#define com_phidgets_AdvancedServoPhidget_PHIDGET_SERVO_SPRINGRC_SM_S4505B 24L
+#undef com_phidgets_AdvancedServoPhidget_PHIDGET_SERVO_USER_DEFINED
+#define com_phidgets_AdvancedServoPhidget_PHIDGET_SERVO_USER_DEFINED 25L
+/*
+ * Class: com_phidgets_AdvancedServoPhidget
+ * Method: create
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL Java_com_phidgets_AdvancedServoPhidget_create
+ (JNIEnv *, jclass);
+
+/*
+ * Class: com_phidgets_AdvancedServoPhidget
+ * Method: getMotorCount
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_phidgets_AdvancedServoPhidget_getMotorCount
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_AdvancedServoPhidget
+ * Method: getAccelerationMax
+ * Signature: (I)D
+ */
+JNIEXPORT jdouble JNICALL Java_com_phidgets_AdvancedServoPhidget_getAccelerationMax
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_AdvancedServoPhidget
+ * Method: getAccelerationMin
+ * Signature: (I)D
+ */
+JNIEXPORT jdouble JNICALL Java_com_phidgets_AdvancedServoPhidget_getAccelerationMin
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_AdvancedServoPhidget
+ * Method: getVelocityMax
+ * Signature: (I)D
+ */
+JNIEXPORT jdouble JNICALL Java_com_phidgets_AdvancedServoPhidget_getVelocityMax
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_AdvancedServoPhidget
+ * Method: getVelocityMin
+ * Signature: (I)D
+ */
+JNIEXPORT jdouble JNICALL Java_com_phidgets_AdvancedServoPhidget_getVelocityMin
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_AdvancedServoPhidget
+ * Method: getPositionMax
+ * Signature: (I)D
+ */
+JNIEXPORT jdouble JNICALL Java_com_phidgets_AdvancedServoPhidget_getPositionMax
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_AdvancedServoPhidget
+ * Method: setPositionMax
+ * Signature: (ID)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_AdvancedServoPhidget_setPositionMax
+ (JNIEnv *, jobject, jint, jdouble);
+
+/*
+ * Class: com_phidgets_AdvancedServoPhidget
+ * Method: getPositionMin
+ * Signature: (I)D
+ */
+JNIEXPORT jdouble JNICALL Java_com_phidgets_AdvancedServoPhidget_getPositionMin
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_AdvancedServoPhidget
+ * Method: setPositionMin
+ * Signature: (ID)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_AdvancedServoPhidget_setPositionMin
+ (JNIEnv *, jobject, jint, jdouble);
+
+/*
+ * Class: com_phidgets_AdvancedServoPhidget
+ * Method: getAcceleration
+ * Signature: (I)D
+ */
+JNIEXPORT jdouble JNICALL Java_com_phidgets_AdvancedServoPhidget_getAcceleration
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_AdvancedServoPhidget
+ * Method: setAcceleration
+ * Signature: (ID)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_AdvancedServoPhidget_setAcceleration
+ (JNIEnv *, jobject, jint, jdouble);
+
+/*
+ * Class: com_phidgets_AdvancedServoPhidget
+ * Method: getVelocityLimit
+ * Signature: (I)D
+ */
+JNIEXPORT jdouble JNICALL Java_com_phidgets_AdvancedServoPhidget_getVelocityLimit
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_AdvancedServoPhidget
+ * Method: setVelocityLimit
+ * Signature: (ID)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_AdvancedServoPhidget_setVelocityLimit
+ (JNIEnv *, jobject, jint, jdouble);
+
+/*
+ * Class: com_phidgets_AdvancedServoPhidget
+ * Method: getVelocity
+ * Signature: (I)D
+ */
+JNIEXPORT jdouble JNICALL Java_com_phidgets_AdvancedServoPhidget_getVelocity
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_AdvancedServoPhidget
+ * Method: getPosition
+ * Signature: (I)D
+ */
+JNIEXPORT jdouble JNICALL Java_com_phidgets_AdvancedServoPhidget_getPosition
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_AdvancedServoPhidget
+ * Method: setPosition
+ * Signature: (ID)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_AdvancedServoPhidget_setPosition
+ (JNIEnv *, jobject, jint, jdouble);
+
+/*
+ * Class: com_phidgets_AdvancedServoPhidget
+ * Method: getEngaged
+ * Signature: (I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_phidgets_AdvancedServoPhidget_getEngaged
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_AdvancedServoPhidget
+ * Method: setEngaged
+ * Signature: (IZ)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_AdvancedServoPhidget_setEngaged
+ (JNIEnv *, jobject, jint, jboolean);
+
+/*
+ * Class: com_phidgets_AdvancedServoPhidget
+ * Method: getSpeedRampingOn
+ * Signature: (I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_phidgets_AdvancedServoPhidget_getSpeedRampingOn
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_AdvancedServoPhidget
+ * Method: setSpeedRampingOn
+ * Signature: (IZ)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_AdvancedServoPhidget_setSpeedRampingOn
+ (JNIEnv *, jobject, jint, jboolean);
+
+/*
+ * Class: com_phidgets_AdvancedServoPhidget
+ * Method: getCurrent
+ * Signature: (I)D
+ */
+JNIEXPORT jdouble JNICALL Java_com_phidgets_AdvancedServoPhidget_getCurrent
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_AdvancedServoPhidget
+ * Method: getStopped
+ * Signature: (I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_phidgets_AdvancedServoPhidget_getStopped
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_AdvancedServoPhidget
+ * Method: getServoType
+ * Signature: (I)I
+ */
+JNIEXPORT jint JNICALL Java_com_phidgets_AdvancedServoPhidget_getServoType
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_AdvancedServoPhidget
+ * Method: setServoType
+ * Signature: (II)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_AdvancedServoPhidget_setServoType
+ (JNIEnv *, jobject, jint, jint);
+
+/*
+ * Class: com_phidgets_AdvancedServoPhidget
+ * Method: setServoParameters
+ * Signature: (IDDDD)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_AdvancedServoPhidget_setServoParameters
+ (JNIEnv *, jobject, jint, jdouble, jdouble, jdouble, jdouble);
+
+/*
+ * Class: com_phidgets_AdvancedServoPhidget
+ * Method: enableServoPositionChangeEvents
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_AdvancedServoPhidget_enableServoPositionChangeEvents
+ (JNIEnv *, jobject, jboolean);
+
+/*
+ * Class: com_phidgets_AdvancedServoPhidget
+ * Method: enableServoVelocityChangeEvents
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_AdvancedServoPhidget_enableServoVelocityChangeEvents
+ (JNIEnv *, jobject, jboolean);
+
+/*
+ * Class: com_phidgets_AdvancedServoPhidget
+ * Method: enableCurrentChangeEvents
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_AdvancedServoPhidget_enableCurrentChangeEvents
+ (JNIEnv *, jobject, jboolean);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/Java/com_phidgets_AnalogPhidget.c b/Java/com_phidgets_AnalogPhidget.c
new file mode 100644
index 0000000..35bd2d5
--- /dev/null
+++ b/Java/com_phidgets_AnalogPhidget.c
@@ -0,0 +1,17 @@
+#include "../stdafx.h"
+#include "phidget_jni.h"
+#include "com_phidgets_AnalogPhidget.h"
+#include "../cphidgetanalog.h"
+
+JNI_LOAD(analog, Analog)
+}
+
+JNI_CREATE(Analog)
+
+JNI_GETFUNC(Analog, OutputCount, OutputCount, jint)
+JNI_INDEXED_GETFUNC(Analog, Voltage, Voltage, jdouble)
+JNI_INDEXED_SETFUNC(Analog, Voltage, Voltage, jdouble)
+JNI_INDEXED_GETFUNC(Analog, VoltageMax, VoltageMax, jdouble)
+JNI_INDEXED_GETFUNC(Analog, VoltageMin, VoltageMin, jdouble)
+JNI_INDEXED_GETFUNCBOOL(Analog, Enabled, Enabled)
+JNI_INDEXED_SETFUNC(Analog, Enabled, Enabled, jboolean) \ No newline at end of file
diff --git a/Java/com_phidgets_AnalogPhidget.h b/Java/com_phidgets_AnalogPhidget.h
new file mode 100644
index 0000000..047a063
--- /dev/null
+++ b/Java/com_phidgets_AnalogPhidget.h
@@ -0,0 +1,221 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class com_phidgets_AnalogPhidget */
+
+#ifndef _Included_com_phidgets_AnalogPhidget
+#define _Included_com_phidgets_AnalogPhidget
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef com_phidgets_AnalogPhidget_PHIDGET_LOG_CRITICAL
+#define com_phidgets_AnalogPhidget_PHIDGET_LOG_CRITICAL 1L
+#undef com_phidgets_AnalogPhidget_PHIDGET_LOG_ERROR
+#define com_phidgets_AnalogPhidget_PHIDGET_LOG_ERROR 2L
+#undef com_phidgets_AnalogPhidget_PHIDGET_LOG_WARNING
+#define com_phidgets_AnalogPhidget_PHIDGET_LOG_WARNING 3L
+#undef com_phidgets_AnalogPhidget_PHIDGET_LOG_DEBUG
+#define com_phidgets_AnalogPhidget_PHIDGET_LOG_DEBUG 4L
+#undef com_phidgets_AnalogPhidget_PHIDGET_LOG_INFO
+#define com_phidgets_AnalogPhidget_PHIDGET_LOG_INFO 5L
+#undef com_phidgets_AnalogPhidget_PHIDGET_LOG_VERBOSE
+#define com_phidgets_AnalogPhidget_PHIDGET_LOG_VERBOSE 6L
+#undef com_phidgets_AnalogPhidget_PHIDID_NOTHING
+#define com_phidgets_AnalogPhidget_PHIDID_NOTHING 1L
+#undef com_phidgets_AnalogPhidget_PHIDID_ACCELEROMETER_3AXIS
+#define com_phidgets_AnalogPhidget_PHIDID_ACCELEROMETER_3AXIS 126L
+#undef com_phidgets_AnalogPhidget_PHIDID_ADVANCEDSERVO_1MOTOR
+#define com_phidgets_AnalogPhidget_PHIDID_ADVANCEDSERVO_1MOTOR 130L
+#undef com_phidgets_AnalogPhidget_PHIDID_ANALOG_4OUTPUT
+#define com_phidgets_AnalogPhidget_PHIDID_ANALOG_4OUTPUT 55L
+#undef com_phidgets_AnalogPhidget_PHIDID_ADVANCEDSERVO_8MOTOR
+#define com_phidgets_AnalogPhidget_PHIDID_ADVANCEDSERVO_8MOTOR 58L
+#undef com_phidgets_AnalogPhidget_PHIDID_BIPOLAR_STEPPER_1MOTOR
+#define com_phidgets_AnalogPhidget_PHIDID_BIPOLAR_STEPPER_1MOTOR 123L
+#undef com_phidgets_AnalogPhidget_PHIDID_BRIDGE_4INPUT
+#define com_phidgets_AnalogPhidget_PHIDID_BRIDGE_4INPUT 59L
+#undef com_phidgets_AnalogPhidget_PHIDID_ENCODER_1ENCODER_1INPUT
+#define com_phidgets_AnalogPhidget_PHIDID_ENCODER_1ENCODER_1INPUT 75L
+#undef com_phidgets_AnalogPhidget_PHIDID_ENCODER_HS_1ENCODER
+#define com_phidgets_AnalogPhidget_PHIDID_ENCODER_HS_1ENCODER 128L
+#undef com_phidgets_AnalogPhidget_PHIDID_ENCODER_HS_4ENCODER_4INPUT
+#define com_phidgets_AnalogPhidget_PHIDID_ENCODER_HS_4ENCODER_4INPUT 79L
+#undef com_phidgets_AnalogPhidget_PHIDID_FREQUENCYCOUNTER_2INPUT
+#define com_phidgets_AnalogPhidget_PHIDID_FREQUENCYCOUNTER_2INPUT 53L
+#undef com_phidgets_AnalogPhidget_PHIDID_GPS
+#define com_phidgets_AnalogPhidget_PHIDID_GPS 121L
+#undef com_phidgets_AnalogPhidget_PHIDID_INTERFACEKIT_0_0_4
+#define com_phidgets_AnalogPhidget_PHIDID_INTERFACEKIT_0_0_4 64L
+#undef com_phidgets_AnalogPhidget_PHIDID_INTERFACEKIT_0_0_8
+#define com_phidgets_AnalogPhidget_PHIDID_INTERFACEKIT_0_0_8 129L
+#undef com_phidgets_AnalogPhidget_PHIDID_INTERFACEKIT_0_16_16
+#define com_phidgets_AnalogPhidget_PHIDID_INTERFACEKIT_0_16_16 68L
+#undef com_phidgets_AnalogPhidget_PHIDID_INTERFACEKIT_8_8_8
+#define com_phidgets_AnalogPhidget_PHIDID_INTERFACEKIT_8_8_8 69L
+#undef com_phidgets_AnalogPhidget_PHIDID_INTERFACEKIT_8_8_8_w_LCD
+#define com_phidgets_AnalogPhidget_PHIDID_INTERFACEKIT_8_8_8_w_LCD 125L
+#undef com_phidgets_AnalogPhidget_PHIDID_IR
+#define com_phidgets_AnalogPhidget_PHIDID_IR 77L
+#undef com_phidgets_AnalogPhidget_PHIDID_LED_64
+#define com_phidgets_AnalogPhidget_PHIDID_LED_64 74L
+#undef com_phidgets_AnalogPhidget_PHIDID_LED_64_ADV
+#define com_phidgets_AnalogPhidget_PHIDID_LED_64_ADV 76L
+#undef com_phidgets_AnalogPhidget_PHIDID_LINEAR_TOUCH
+#define com_phidgets_AnalogPhidget_PHIDID_LINEAR_TOUCH 118L
+#undef com_phidgets_AnalogPhidget_PHIDID_MOTORCONTROL_HC_2MOTOR
+#define com_phidgets_AnalogPhidget_PHIDID_MOTORCONTROL_HC_2MOTOR 89L
+#undef com_phidgets_AnalogPhidget_PHIDID_MOTORCONTROL_LV_2MOTOR_4INPUT
+#define com_phidgets_AnalogPhidget_PHIDID_MOTORCONTROL_LV_2MOTOR_4INPUT 88L
+#undef com_phidgets_AnalogPhidget_PHIDID_MOTORCONTROL_1MOTOR
+#define com_phidgets_AnalogPhidget_PHIDID_MOTORCONTROL_1MOTOR 62L
+#undef com_phidgets_AnalogPhidget_PHIDID_PHSENSOR
+#define com_phidgets_AnalogPhidget_PHIDID_PHSENSOR 116L
+#undef com_phidgets_AnalogPhidget_PHIDID_RFID_2OUTPUT
+#define com_phidgets_AnalogPhidget_PHIDID_RFID_2OUTPUT 49L
+#undef com_phidgets_AnalogPhidget_PHIDID_ROTARY_TOUCH
+#define com_phidgets_AnalogPhidget_PHIDID_ROTARY_TOUCH 119L
+#undef com_phidgets_AnalogPhidget_PHIDID_SERVO_1MOTOR
+#define com_phidgets_AnalogPhidget_PHIDID_SERVO_1MOTOR 57L
+#undef com_phidgets_AnalogPhidget_PHIDID_SPATIAL_ACCEL_3AXIS
+#define com_phidgets_AnalogPhidget_PHIDID_SPATIAL_ACCEL_3AXIS 127L
+#undef com_phidgets_AnalogPhidget_PHIDID_SPATIAL_ACCEL_GYRO_COMPASS
+#define com_phidgets_AnalogPhidget_PHIDID_SPATIAL_ACCEL_GYRO_COMPASS 51L
+#undef com_phidgets_AnalogPhidget_PHIDID_TEMPERATURESENSOR
+#define com_phidgets_AnalogPhidget_PHIDID_TEMPERATURESENSOR 112L
+#undef com_phidgets_AnalogPhidget_PHIDID_TEMPERATURESENSOR_4
+#define com_phidgets_AnalogPhidget_PHIDID_TEMPERATURESENSOR_4 50L
+#undef com_phidgets_AnalogPhidget_PHIDID_TEXTLCD_2x20_w_8_8_8
+#define com_phidgets_AnalogPhidget_PHIDID_TEXTLCD_2x20_w_8_8_8 381L
+#undef com_phidgets_AnalogPhidget_PHIDID_TEXTLCD_ADAPTER
+#define com_phidgets_AnalogPhidget_PHIDID_TEXTLCD_ADAPTER 61L
+#undef com_phidgets_AnalogPhidget_PHIDID_UNIPOLAR_STEPPER_4MOTOR
+#define com_phidgets_AnalogPhidget_PHIDID_UNIPOLAR_STEPPER_4MOTOR 122L
+#undef com_phidgets_AnalogPhidget_PHIDID_ACCELEROMETER_2AXIS
+#define com_phidgets_AnalogPhidget_PHIDID_ACCELEROMETER_2AXIS 113L
+#undef com_phidgets_AnalogPhidget_PHIDID_INTERFACEKIT_0_8_8_w_LCD
+#define com_phidgets_AnalogPhidget_PHIDID_INTERFACEKIT_0_8_8_w_LCD 83L
+#undef com_phidgets_AnalogPhidget_PHIDID_INTERFACEKIT_4_8_8
+#define com_phidgets_AnalogPhidget_PHIDID_INTERFACEKIT_4_8_8 4L
+#undef com_phidgets_AnalogPhidget_PHIDID_RFID
+#define com_phidgets_AnalogPhidget_PHIDID_RFID 48L
+#undef com_phidgets_AnalogPhidget_PHIDID_SERVO_1MOTOR_OLD
+#define com_phidgets_AnalogPhidget_PHIDID_SERVO_1MOTOR_OLD 2L
+#undef com_phidgets_AnalogPhidget_PHIDID_SERVO_4MOTOR
+#define com_phidgets_AnalogPhidget_PHIDID_SERVO_4MOTOR 56L
+#undef com_phidgets_AnalogPhidget_PHIDID_SERVO_4MOTOR_OLD
+#define com_phidgets_AnalogPhidget_PHIDID_SERVO_4MOTOR_OLD 3L
+#undef com_phidgets_AnalogPhidget_PHIDID_TEXTLCD_2x20
+#define com_phidgets_AnalogPhidget_PHIDID_TEXTLCD_2x20 82L
+#undef com_phidgets_AnalogPhidget_PHIDID_TEXTLCD_2x20_w_0_8_8
+#define com_phidgets_AnalogPhidget_PHIDID_TEXTLCD_2x20_w_0_8_8 339L
+#undef com_phidgets_AnalogPhidget_PHIDID_TEXTLED_1x8
+#define com_phidgets_AnalogPhidget_PHIDID_TEXTLED_1x8 73L
+#undef com_phidgets_AnalogPhidget_PHIDID_TEXTLED_4x8
+#define com_phidgets_AnalogPhidget_PHIDID_TEXTLED_4x8 72L
+#undef com_phidgets_AnalogPhidget_PHIDID_WEIGHTSENSOR
+#define com_phidgets_AnalogPhidget_PHIDID_WEIGHTSENSOR 114L
+#undef com_phidgets_AnalogPhidget_PHIDCLASS_NOTHING
+#define com_phidgets_AnalogPhidget_PHIDCLASS_NOTHING 1L
+#undef com_phidgets_AnalogPhidget_PHIDCLASS_ACCELEROMETER
+#define com_phidgets_AnalogPhidget_PHIDCLASS_ACCELEROMETER 2L
+#undef com_phidgets_AnalogPhidget_PHIDCLASS_ADVANCEDSERVO
+#define com_phidgets_AnalogPhidget_PHIDCLASS_ADVANCEDSERVO 3L
+#undef com_phidgets_AnalogPhidget_PHIDCLASS_ANALOG
+#define com_phidgets_AnalogPhidget_PHIDCLASS_ANALOG 22L
+#undef com_phidgets_AnalogPhidget_PHIDCLASS_BRIDGE
+#define com_phidgets_AnalogPhidget_PHIDCLASS_BRIDGE 23L
+#undef com_phidgets_AnalogPhidget_PHIDCLASS_ENCODER
+#define com_phidgets_AnalogPhidget_PHIDCLASS_ENCODER 4L
+#undef com_phidgets_AnalogPhidget_PHIDCLASS_FREQUENCYCOUNTER
+#define com_phidgets_AnalogPhidget_PHIDCLASS_FREQUENCYCOUNTER 21L
+#undef com_phidgets_AnalogPhidget_PHIDCLASS_GPS
+#define com_phidgets_AnalogPhidget_PHIDCLASS_GPS 5L
+#undef com_phidgets_AnalogPhidget_PHIDCLASS_INTERFACEKIT
+#define com_phidgets_AnalogPhidget_PHIDCLASS_INTERFACEKIT 7L
+#undef com_phidgets_AnalogPhidget_PHIDCLASS_LED
+#define com_phidgets_AnalogPhidget_PHIDCLASS_LED 8L
+#undef com_phidgets_AnalogPhidget_PHIDCLASS_MOTORCONTROL
+#define com_phidgets_AnalogPhidget_PHIDCLASS_MOTORCONTROL 9L
+#undef com_phidgets_AnalogPhidget_PHIDCLASS_PHSENSOR
+#define com_phidgets_AnalogPhidget_PHIDCLASS_PHSENSOR 10L
+#undef com_phidgets_AnalogPhidget_PHIDCLASS_RFID
+#define com_phidgets_AnalogPhidget_PHIDCLASS_RFID 11L
+#undef com_phidgets_AnalogPhidget_PHIDCLASS_SERVO
+#define com_phidgets_AnalogPhidget_PHIDCLASS_SERVO 12L
+#undef com_phidgets_AnalogPhidget_PHIDCLASS_STEPPER
+#define com_phidgets_AnalogPhidget_PHIDCLASS_STEPPER 13L
+#undef com_phidgets_AnalogPhidget_PHIDCLASS_TEMPERATURESENSOR
+#define com_phidgets_AnalogPhidget_PHIDCLASS_TEMPERATURESENSOR 14L
+#undef com_phidgets_AnalogPhidget_PHIDCLASS_TEXTLCD
+#define com_phidgets_AnalogPhidget_PHIDCLASS_TEXTLCD 15L
+#undef com_phidgets_AnalogPhidget_PHIDCLASS_TEXTLED
+#define com_phidgets_AnalogPhidget_PHIDCLASS_TEXTLED 16L
+#undef com_phidgets_AnalogPhidget_PHIDCLASS_WEIGHTSENSOR
+#define com_phidgets_AnalogPhidget_PHIDCLASS_WEIGHTSENSOR 17L
+/*
+ * Class: com_phidgets_AnalogPhidget
+ * Method: create
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL Java_com_phidgets_AnalogPhidget_create
+ (JNIEnv *, jclass);
+
+/*
+ * Class: com_phidgets_AnalogPhidget
+ * Method: getOutputCount
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_phidgets_AnalogPhidget_getOutputCount
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_AnalogPhidget
+ * Method: getVoltage
+ * Signature: (I)D
+ */
+JNIEXPORT jdouble JNICALL Java_com_phidgets_AnalogPhidget_getVoltage
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_AnalogPhidget
+ * Method: setVoltage
+ * Signature: (ID)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_AnalogPhidget_setVoltage
+ (JNIEnv *, jobject, jint, jdouble);
+
+/*
+ * Class: com_phidgets_AnalogPhidget
+ * Method: getVoltageMin
+ * Signature: (I)D
+ */
+JNIEXPORT jdouble JNICALL Java_com_phidgets_AnalogPhidget_getVoltageMin
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_AnalogPhidget
+ * Method: getVoltageMax
+ * Signature: (I)D
+ */
+JNIEXPORT jdouble JNICALL Java_com_phidgets_AnalogPhidget_getVoltageMax
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_AnalogPhidget
+ * Method: getEnabled
+ * Signature: (I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_phidgets_AnalogPhidget_getEnabled
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_AnalogPhidget
+ * Method: setEnabled
+ * Signature: (IZ)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_AnalogPhidget_setEnabled
+ (JNIEnv *, jobject, jint, jboolean);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/Java/com_phidgets_BridgePhidget.c b/Java/com_phidgets_BridgePhidget.c
new file mode 100644
index 0000000..6f42cf7
--- /dev/null
+++ b/Java/com_phidgets_BridgePhidget.c
@@ -0,0 +1,40 @@
+#include "../stdafx.h"
+#include "phidget_jni.h"
+#include "com_phidgets_BridgePhidget.h"
+#include "../cphidgetbridge.h"
+
+EVENT_VARS(bridgeData, BridgeData)
+
+JNI_LOAD(bridge, Bridge)
+ EVENT_VAR_SETUP(bridge, bridgeData, BridgeData, ID, V)
+}
+
+EVENT_HANDLER_INDEXED(Bridge, bridgeData, BridgeData,
+ CPhidgetBridge_set_OnBridgeData_Handler, double)
+
+JNI_CREATE(Bridge)
+
+JNI_GETFUNC(Bridge, InputCount, InputCount, jint)
+JNI_INDEXED_GETFUNC(Bridge, BridgeValue, BridgeValue, jdouble)
+JNI_INDEXED_GETFUNC(Bridge, BridgeMin, BridgeMin, jdouble)
+JNI_INDEXED_GETFUNC(Bridge, BridgeMax, BridgeMax, jdouble)
+JNI_INDEXED_GETFUNCBOOL(Bridge, Enabled, Enabled)
+JNI_INDEXED_SETFUNC(Bridge, Enabled, Enabled, jboolean)
+
+JNIEXPORT jint JNICALL
+Java_com_phidgets_BridgePhidget_getGain(JNIEnv *env, jobject obj, jint index)
+{
+ CPhidgetBridgeHandle h = (CPhidgetBridgeHandle)(uintptr_t)
+ (*env)->GetLongField(env, obj, handle_fid);
+ int error;
+ CPhidgetBridge_Gain v;
+ if ((error = CPhidgetBridge_getGain(h, index, &v)))
+ PH_THROW(error);
+ return (jint)v;
+}
+
+JNI_INDEXED_SETFUNC(Bridge, Gain, Gain, jint)
+JNI_GETFUNC(Bridge, DataRate, DataRate, jint)
+JNI_SETFUNC(Bridge, DataRate, DataRate, jint)
+JNI_GETFUNC(Bridge, DataRateMin, DataRateMin, jint)
+JNI_GETFUNC(Bridge, DataRateMax, DataRateMax, jint) \ No newline at end of file
diff --git a/Java/com_phidgets_BridgePhidget.h b/Java/com_phidgets_BridgePhidget.h
new file mode 100644
index 0000000..4575081
--- /dev/null
+++ b/Java/com_phidgets_BridgePhidget.h
@@ -0,0 +1,283 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class com_phidgets_BridgePhidget */
+
+#ifndef _Included_com_phidgets_BridgePhidget
+#define _Included_com_phidgets_BridgePhidget
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef com_phidgets_BridgePhidget_PHIDGET_LOG_CRITICAL
+#define com_phidgets_BridgePhidget_PHIDGET_LOG_CRITICAL 1L
+#undef com_phidgets_BridgePhidget_PHIDGET_LOG_ERROR
+#define com_phidgets_BridgePhidget_PHIDGET_LOG_ERROR 2L
+#undef com_phidgets_BridgePhidget_PHIDGET_LOG_WARNING
+#define com_phidgets_BridgePhidget_PHIDGET_LOG_WARNING 3L
+#undef com_phidgets_BridgePhidget_PHIDGET_LOG_DEBUG
+#define com_phidgets_BridgePhidget_PHIDGET_LOG_DEBUG 4L
+#undef com_phidgets_BridgePhidget_PHIDGET_LOG_INFO
+#define com_phidgets_BridgePhidget_PHIDGET_LOG_INFO 5L
+#undef com_phidgets_BridgePhidget_PHIDGET_LOG_VERBOSE
+#define com_phidgets_BridgePhidget_PHIDGET_LOG_VERBOSE 6L
+#undef com_phidgets_BridgePhidget_PHIDID_NOTHING
+#define com_phidgets_BridgePhidget_PHIDID_NOTHING 1L
+#undef com_phidgets_BridgePhidget_PHIDID_ACCELEROMETER_3AXIS
+#define com_phidgets_BridgePhidget_PHIDID_ACCELEROMETER_3AXIS 126L
+#undef com_phidgets_BridgePhidget_PHIDID_ADVANCEDSERVO_1MOTOR
+#define com_phidgets_BridgePhidget_PHIDID_ADVANCEDSERVO_1MOTOR 130L
+#undef com_phidgets_BridgePhidget_PHIDID_ANALOG_4OUTPUT
+#define com_phidgets_BridgePhidget_PHIDID_ANALOG_4OUTPUT 55L
+#undef com_phidgets_BridgePhidget_PHIDID_ADVANCEDSERVO_8MOTOR
+#define com_phidgets_BridgePhidget_PHIDID_ADVANCEDSERVO_8MOTOR 58L
+#undef com_phidgets_BridgePhidget_PHIDID_BIPOLAR_STEPPER_1MOTOR
+#define com_phidgets_BridgePhidget_PHIDID_BIPOLAR_STEPPER_1MOTOR 123L
+#undef com_phidgets_BridgePhidget_PHIDID_BRIDGE_4INPUT
+#define com_phidgets_BridgePhidget_PHIDID_BRIDGE_4INPUT 59L
+#undef com_phidgets_BridgePhidget_PHIDID_ENCODER_1ENCODER_1INPUT
+#define com_phidgets_BridgePhidget_PHIDID_ENCODER_1ENCODER_1INPUT 75L
+#undef com_phidgets_BridgePhidget_PHIDID_ENCODER_HS_1ENCODER
+#define com_phidgets_BridgePhidget_PHIDID_ENCODER_HS_1ENCODER 128L
+#undef com_phidgets_BridgePhidget_PHIDID_ENCODER_HS_4ENCODER_4INPUT
+#define com_phidgets_BridgePhidget_PHIDID_ENCODER_HS_4ENCODER_4INPUT 79L
+#undef com_phidgets_BridgePhidget_PHIDID_FREQUENCYCOUNTER_2INPUT
+#define com_phidgets_BridgePhidget_PHIDID_FREQUENCYCOUNTER_2INPUT 53L
+#undef com_phidgets_BridgePhidget_PHIDID_GPS
+#define com_phidgets_BridgePhidget_PHIDID_GPS 121L
+#undef com_phidgets_BridgePhidget_PHIDID_INTERFACEKIT_0_0_4
+#define com_phidgets_BridgePhidget_PHIDID_INTERFACEKIT_0_0_4 64L
+#undef com_phidgets_BridgePhidget_PHIDID_INTERFACEKIT_0_0_8
+#define com_phidgets_BridgePhidget_PHIDID_INTERFACEKIT_0_0_8 129L
+#undef com_phidgets_BridgePhidget_PHIDID_INTERFACEKIT_0_16_16
+#define com_phidgets_BridgePhidget_PHIDID_INTERFACEKIT_0_16_16 68L
+#undef com_phidgets_BridgePhidget_PHIDID_INTERFACEKIT_8_8_8
+#define com_phidgets_BridgePhidget_PHIDID_INTERFACEKIT_8_8_8 69L
+#undef com_phidgets_BridgePhidget_PHIDID_INTERFACEKIT_8_8_8_w_LCD
+#define com_phidgets_BridgePhidget_PHIDID_INTERFACEKIT_8_8_8_w_LCD 125L
+#undef com_phidgets_BridgePhidget_PHIDID_IR
+#define com_phidgets_BridgePhidget_PHIDID_IR 77L
+#undef com_phidgets_BridgePhidget_PHIDID_LED_64
+#define com_phidgets_BridgePhidget_PHIDID_LED_64 74L
+#undef com_phidgets_BridgePhidget_PHIDID_LED_64_ADV
+#define com_phidgets_BridgePhidget_PHIDID_LED_64_ADV 76L
+#undef com_phidgets_BridgePhidget_PHIDID_LINEAR_TOUCH
+#define com_phidgets_BridgePhidget_PHIDID_LINEAR_TOUCH 118L
+#undef com_phidgets_BridgePhidget_PHIDID_MOTORCONTROL_HC_2MOTOR
+#define com_phidgets_BridgePhidget_PHIDID_MOTORCONTROL_HC_2MOTOR 89L
+#undef com_phidgets_BridgePhidget_PHIDID_MOTORCONTROL_LV_2MOTOR_4INPUT
+#define com_phidgets_BridgePhidget_PHIDID_MOTORCONTROL_LV_2MOTOR_4INPUT 88L
+#undef com_phidgets_BridgePhidget_PHIDID_MOTORCONTROL_1MOTOR
+#define com_phidgets_BridgePhidget_PHIDID_MOTORCONTROL_1MOTOR 62L
+#undef com_phidgets_BridgePhidget_PHIDID_PHSENSOR
+#define com_phidgets_BridgePhidget_PHIDID_PHSENSOR 116L
+#undef com_phidgets_BridgePhidget_PHIDID_RFID_2OUTPUT
+#define com_phidgets_BridgePhidget_PHIDID_RFID_2OUTPUT 49L
+#undef com_phidgets_BridgePhidget_PHIDID_ROTARY_TOUCH
+#define com_phidgets_BridgePhidget_PHIDID_ROTARY_TOUCH 119L
+#undef com_phidgets_BridgePhidget_PHIDID_SERVO_1MOTOR
+#define com_phidgets_BridgePhidget_PHIDID_SERVO_1MOTOR 57L
+#undef com_phidgets_BridgePhidget_PHIDID_SPATIAL_ACCEL_3AXIS
+#define com_phidgets_BridgePhidget_PHIDID_SPATIAL_ACCEL_3AXIS 127L
+#undef com_phidgets_BridgePhidget_PHIDID_SPATIAL_ACCEL_GYRO_COMPASS
+#define com_phidgets_BridgePhidget_PHIDID_SPATIAL_ACCEL_GYRO_COMPASS 51L
+#undef com_phidgets_BridgePhidget_PHIDID_TEMPERATURESENSOR
+#define com_phidgets_BridgePhidget_PHIDID_TEMPERATURESENSOR 112L
+#undef com_phidgets_BridgePhidget_PHIDID_TEMPERATURESENSOR_4
+#define com_phidgets_BridgePhidget_PHIDID_TEMPERATURESENSOR_4 50L
+#undef com_phidgets_BridgePhidget_PHIDID_TEXTLCD_2x20_w_8_8_8
+#define com_phidgets_BridgePhidget_PHIDID_TEXTLCD_2x20_w_8_8_8 381L
+#undef com_phidgets_BridgePhidget_PHIDID_TEXTLCD_ADAPTER
+#define com_phidgets_BridgePhidget_PHIDID_TEXTLCD_ADAPTER 61L
+#undef com_phidgets_BridgePhidget_PHIDID_UNIPOLAR_STEPPER_4MOTOR
+#define com_phidgets_BridgePhidget_PHIDID_UNIPOLAR_STEPPER_4MOTOR 122L
+#undef com_phidgets_BridgePhidget_PHIDID_ACCELEROMETER_2AXIS
+#define com_phidgets_BridgePhidget_PHIDID_ACCELEROMETER_2AXIS 113L
+#undef com_phidgets_BridgePhidget_PHIDID_INTERFACEKIT_0_8_8_w_LCD
+#define com_phidgets_BridgePhidget_PHIDID_INTERFACEKIT_0_8_8_w_LCD 83L
+#undef com_phidgets_BridgePhidget_PHIDID_INTERFACEKIT_4_8_8
+#define com_phidgets_BridgePhidget_PHIDID_INTERFACEKIT_4_8_8 4L
+#undef com_phidgets_BridgePhidget_PHIDID_RFID
+#define com_phidgets_BridgePhidget_PHIDID_RFID 48L
+#undef com_phidgets_BridgePhidget_PHIDID_SERVO_1MOTOR_OLD
+#define com_phidgets_BridgePhidget_PHIDID_SERVO_1MOTOR_OLD 2L
+#undef com_phidgets_BridgePhidget_PHIDID_SERVO_4MOTOR
+#define com_phidgets_BridgePhidget_PHIDID_SERVO_4MOTOR 56L
+#undef com_phidgets_BridgePhidget_PHIDID_SERVO_4MOTOR_OLD
+#define com_phidgets_BridgePhidget_PHIDID_SERVO_4MOTOR_OLD 3L
+#undef com_phidgets_BridgePhidget_PHIDID_TEXTLCD_2x20
+#define com_phidgets_BridgePhidget_PHIDID_TEXTLCD_2x20 82L
+#undef com_phidgets_BridgePhidget_PHIDID_TEXTLCD_2x20_w_0_8_8
+#define com_phidgets_BridgePhidget_PHIDID_TEXTLCD_2x20_w_0_8_8 339L
+#undef com_phidgets_BridgePhidget_PHIDID_TEXTLED_1x8
+#define com_phidgets_BridgePhidget_PHIDID_TEXTLED_1x8 73L
+#undef com_phidgets_BridgePhidget_PHIDID_TEXTLED_4x8
+#define com_phidgets_BridgePhidget_PHIDID_TEXTLED_4x8 72L
+#undef com_phidgets_BridgePhidget_PHIDID_WEIGHTSENSOR
+#define com_phidgets_BridgePhidget_PHIDID_WEIGHTSENSOR 114L
+#undef com_phidgets_BridgePhidget_PHIDCLASS_NOTHING
+#define com_phidgets_BridgePhidget_PHIDCLASS_NOTHING 1L
+#undef com_phidgets_BridgePhidget_PHIDCLASS_ACCELEROMETER
+#define com_phidgets_BridgePhidget_PHIDCLASS_ACCELEROMETER 2L
+#undef com_phidgets_BridgePhidget_PHIDCLASS_ADVANCEDSERVO
+#define com_phidgets_BridgePhidget_PHIDCLASS_ADVANCEDSERVO 3L
+#undef com_phidgets_BridgePhidget_PHIDCLASS_ANALOG
+#define com_phidgets_BridgePhidget_PHIDCLASS_ANALOG 22L
+#undef com_phidgets_BridgePhidget_PHIDCLASS_BRIDGE
+#define com_phidgets_BridgePhidget_PHIDCLASS_BRIDGE 23L
+#undef com_phidgets_BridgePhidget_PHIDCLASS_ENCODER
+#define com_phidgets_BridgePhidget_PHIDCLASS_ENCODER 4L
+#undef com_phidgets_BridgePhidget_PHIDCLASS_FREQUENCYCOUNTER
+#define com_phidgets_BridgePhidget_PHIDCLASS_FREQUENCYCOUNTER 21L
+#undef com_phidgets_BridgePhidget_PHIDCLASS_GPS
+#define com_phidgets_BridgePhidget_PHIDCLASS_GPS 5L
+#undef com_phidgets_BridgePhidget_PHIDCLASS_INTERFACEKIT
+#define com_phidgets_BridgePhidget_PHIDCLASS_INTERFACEKIT 7L
+#undef com_phidgets_BridgePhidget_PHIDCLASS_LED
+#define com_phidgets_BridgePhidget_PHIDCLASS_LED 8L
+#undef com_phidgets_BridgePhidget_PHIDCLASS_MOTORCONTROL
+#define com_phidgets_BridgePhidget_PHIDCLASS_MOTORCONTROL 9L
+#undef com_phidgets_BridgePhidget_PHIDCLASS_PHSENSOR
+#define com_phidgets_BridgePhidget_PHIDCLASS_PHSENSOR 10L
+#undef com_phidgets_BridgePhidget_PHIDCLASS_RFID
+#define com_phidgets_BridgePhidget_PHIDCLASS_RFID 11L
+#undef com_phidgets_BridgePhidget_PHIDCLASS_SERVO
+#define com_phidgets_BridgePhidget_PHIDCLASS_SERVO 12L
+#undef com_phidgets_BridgePhidget_PHIDCLASS_STEPPER
+#define com_phidgets_BridgePhidget_PHIDCLASS_STEPPER 13L
+#undef com_phidgets_BridgePhidget_PHIDCLASS_TEMPERATURESENSOR
+#define com_phidgets_BridgePhidget_PHIDCLASS_TEMPERATURESENSOR 14L
+#undef com_phidgets_BridgePhidget_PHIDCLASS_TEXTLCD
+#define com_phidgets_BridgePhidget_PHIDCLASS_TEXTLCD 15L
+#undef com_phidgets_BridgePhidget_PHIDCLASS_TEXTLED
+#define com_phidgets_BridgePhidget_PHIDCLASS_TEXTLED 16L
+#undef com_phidgets_BridgePhidget_PHIDCLASS_WEIGHTSENSOR
+#define com_phidgets_BridgePhidget_PHIDCLASS_WEIGHTSENSOR 17L
+#undef com_phidgets_BridgePhidget_PHIDGET_BRIDGE_GAIN_1
+#define com_phidgets_BridgePhidget_PHIDGET_BRIDGE_GAIN_1 1L
+#undef com_phidgets_BridgePhidget_PHIDGET_BRIDGE_GAIN_8
+#define com_phidgets_BridgePhidget_PHIDGET_BRIDGE_GAIN_8 2L
+#undef com_phidgets_BridgePhidget_PHIDGET_BRIDGE_GAIN_16
+#define com_phidgets_BridgePhidget_PHIDGET_BRIDGE_GAIN_16 3L
+#undef com_phidgets_BridgePhidget_PHIDGET_BRIDGE_GAIN_32
+#define com_phidgets_BridgePhidget_PHIDGET_BRIDGE_GAIN_32 4L
+#undef com_phidgets_BridgePhidget_PHIDGET_BRIDGE_GAIN_64
+#define com_phidgets_BridgePhidget_PHIDGET_BRIDGE_GAIN_64 5L
+#undef com_phidgets_BridgePhidget_PHIDGET_BRIDGE_GAIN_128
+#define com_phidgets_BridgePhidget_PHIDGET_BRIDGE_GAIN_128 6L
+#undef com_phidgets_BridgePhidget_PHIDGET_BRIDGE_GAIN_UNKNOWN
+#define com_phidgets_BridgePhidget_PHIDGET_BRIDGE_GAIN_UNKNOWN 7L
+/*
+ * Class: com_phidgets_BridgePhidget
+ * Method: create
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL Java_com_phidgets_BridgePhidget_create
+ (JNIEnv *, jclass);
+
+/*
+ * Class: com_phidgets_BridgePhidget
+ * Method: getInputCount
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_phidgets_BridgePhidget_getInputCount
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_BridgePhidget
+ * Method: getBridgeValue
+ * Signature: (I)D
+ */
+JNIEXPORT jdouble JNICALL Java_com_phidgets_BridgePhidget_getBridgeValue
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_BridgePhidget
+ * Method: getBridgeMin
+ * Signature: (I)D
+ */
+JNIEXPORT jdouble JNICALL Java_com_phidgets_BridgePhidget_getBridgeMin
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_BridgePhidget
+ * Method: getBridgeMax
+ * Signature: (I)D
+ */
+JNIEXPORT jdouble JNICALL Java_com_phidgets_BridgePhidget_getBridgeMax
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_BridgePhidget
+ * Method: getEnabled
+ * Signature: (I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_phidgets_BridgePhidget_getEnabled
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_BridgePhidget
+ * Method: setEnabled
+ * Signature: (IZ)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_BridgePhidget_setEnabled
+ (JNIEnv *, jobject, jint, jboolean);
+
+/*
+ * Class: com_phidgets_BridgePhidget
+ * Method: getGain
+ * Signature: (I)I
+ */
+JNIEXPORT jint JNICALL Java_com_phidgets_BridgePhidget_getGain
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_BridgePhidget
+ * Method: setGain
+ * Signature: (II)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_BridgePhidget_setGain
+ (JNIEnv *, jobject, jint, jint);
+
+/*
+ * Class: com_phidgets_BridgePhidget
+ * Method: getDataRate
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_phidgets_BridgePhidget_getDataRate
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_BridgePhidget
+ * Method: setDataRate
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_BridgePhidget_setDataRate
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_BridgePhidget
+ * Method: getDataRateMin
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_phidgets_BridgePhidget_getDataRateMin
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_BridgePhidget
+ * Method: getDataRateMax
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_phidgets_BridgePhidget_getDataRateMax
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_BridgePhidget
+ * Method: enableBridgeDataEvents
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_BridgePhidget_enableBridgeDataEvents
+ (JNIEnv *, jobject, jboolean);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/Java/com_phidgets_Dictionary.c b/Java/com_phidgets_Dictionary.c
new file mode 100644
index 0000000..2a83f4c
--- /dev/null
+++ b/Java/com_phidgets_Dictionary.c
@@ -0,0 +1,334 @@
+#include "../stdafx.h"
+#include <stdlib.h>
+#include "com_phidgets_Dictionary.h"
+#include "../cphidgetdictionary.h"
+#include "../csocket.h"
+#include "phidget_jni.h"
+
+static int CCONV serverConnect_handler(CPhidgetDictionaryHandle h, void *arg);
+static int CCONV serverDisconnect_handler(CPhidgetDictionaryHandle h, void *arg);
+
+static jclass dictionary_class;
+
+static jfieldID dictionary_handle_fid;
+static jfieldID nativeServerConnectHandler_fid;
+static jfieldID nativeServerDisconnectHandler_fid;
+
+static jmethodID fireServerConnect_mid;
+static jmethodID fireServerDisconnect_mid;
+
+void
+com_phidgets_Dictionary_OnLoad(JNIEnv *env)
+{
+ //Dictionary
+ if (!(dictionary_class = (*env)->FindClass(env, "com/phidgets/Dictionary")))
+ JNI_ABORT_STDERR("Couldn't FindClass com/phidgets/Dictionary");
+ if (!(dictionary_class = (jclass)(*env)->NewGlobalRef(env, dictionary_class)))
+ JNI_ABORT_STDERR("Couldn't create global ref dictionary_class");
+
+ if (!(dictionary_handle_fid = (*env)->GetFieldID(env, dictionary_class, "handle", "J")))
+ JNI_ABORT_STDERR("Couldn't get Field ID handle from dictionary_class");
+ if (!(nativeServerConnectHandler_fid = (*env)->GetFieldID(env, dictionary_class, "nativeServerConnectHandler", "J")))
+ JNI_ABORT_STDERR("Couldn't get Field ID nativeServerConnectHandler from dictionary_class");
+ if (!(nativeServerDisconnectHandler_fid = (*env)->GetFieldID(env, dictionary_class, "nativeServerDisconnectHandler", "J")))
+ JNI_ABORT_STDERR("Couldn't get Field ID nativeServerDisconnectHandler from dictionary_class");
+
+ if (!(fireServerConnect_mid = (*env)->GetMethodID(env, dictionary_class, "fireServerConnect", "(Lcom/phidgets/event/ServerConnectEvent;)V")))
+ JNI_ABORT_STDERR("Couldn't get method ID fireServerConnect from dictionary_class");
+ if (!(fireServerDisconnect_mid = (*env)->GetMethodID(env, dictionary_class, "fireServerDisconnect", "(Lcom/phidgets/event/ServerDisconnectEvent;)V")))
+ JNI_ABORT_STDERR("Couldn't get method ID fireServerDisconnect from dictionary_class");
+}
+
+JNIEXPORT void JNICALL
+Java_com_phidgets_Dictionary_enableServerConnectEvents(JNIEnv *env, jobject obj,
+ jboolean b)
+{
+ jlong gr = updateGlobalRef(env, obj, nativeServerConnectHandler_fid, b);
+ CPhidgetDictionaryHandle h = (CPhidgetDictionaryHandle)(uintptr_t)(*env)->GetLongField(env,
+ obj, dictionary_handle_fid);
+
+ CPhidgetDictionary_set_OnServerConnect_Handler(h, b ? serverConnect_handler : 0,
+ (void *)(uintptr_t)gr);
+}
+
+static int CCONV
+serverConnect_handler(CPhidgetDictionaryHandle h, void *arg)
+{
+ JNIEnv *env;
+ jobject obj;
+ jobject serverConnectEvent;
+ jint result;
+
+ result = (*ph_vm)->GetEnv(ph_vm, (void **)&env, JNI_VERSION_1_4);
+
+ if(result == JNI_EDETACHED)
+ {
+ if ((*ph_vm)->AttachCurrentThread(ph_vm, (JNIEnvPtr)&env, NULL))
+ JNI_ABORT_STDERR("Couldn't AttachCurrentThread");
+ }
+
+ obj = (jobject)arg;
+
+ if (!(serverConnectEvent = (*env)->NewObject(env, serverConnectEvent_class, serverConnectEvent_cons,
+ obj)))
+ return -1;
+ (*env)->CallVoidMethod(env, obj, fireServerConnect_mid, serverConnectEvent);
+ (*env)->DeleteLocalRef(env, serverConnectEvent);
+ (*ph_vm)->DetachCurrentThread(ph_vm);
+
+ return 0;
+}
+
+JNIEXPORT void JNICALL
+Java_com_phidgets_Dictionary_enableServerDisconnectEvents(JNIEnv *env, jobject obj,
+ jboolean b)
+{
+ jlong gr = updateGlobalRef(env, obj, nativeServerDisconnectHandler_fid, b);
+ CPhidgetDictionaryHandle h = (CPhidgetDictionaryHandle)(uintptr_t)(*env)->GetLongField(env,
+ obj, dictionary_handle_fid);
+
+ CPhidgetDictionary_set_OnServerDisconnect_Handler(h, b ? serverDisconnect_handler : 0,
+ (void *)(uintptr_t)gr);
+}
+
+static int CCONV
+serverDisconnect_handler(CPhidgetDictionaryHandle h, void *arg)
+{
+ JNIEnv *env;
+ jobject obj;
+ jobject serverDisconnectEvent;
+ jint result;
+
+ result = (*ph_vm)->GetEnv(ph_vm, (void **)&env, JNI_VERSION_1_4);
+
+ if(result == JNI_EDETACHED)
+ {
+ if ((*ph_vm)->AttachCurrentThread(ph_vm, (JNIEnvPtr)&env, NULL))
+ JNI_ABORT_STDERR("Couldn't AttachCurrentThread");
+ }
+
+ obj = (jobject)arg;
+
+ if (!(serverDisconnectEvent = (*env)->NewObject(env, serverDisconnectEvent_class, serverDisconnectEvent_cons,
+ obj)))
+ return -1;
+ (*env)->CallVoidMethod(env, obj, fireServerDisconnect_mid, serverDisconnectEvent);
+ (*env)->DeleteLocalRef(env, serverDisconnectEvent);
+ (*ph_vm)->DetachCurrentThread(ph_vm);
+
+ return 0;
+}
+
+JNIEXPORT jboolean JNICALL
+Java_com_phidgets_Dictionary_isAttached(JNIEnv *env, jobject obj)
+{
+ CPhidgetHandle h = (CPhidgetHandle)(uintptr_t)(*env)->GetLongField(env,
+ obj, dictionary_handle_fid);
+ int error;
+ int s;
+
+ if ((error = CPhidget_getDeviceStatus(h, &s)))
+ PH_THROW(error);
+
+ return s == PHIDGET_ATTACHED;
+}
+
+JNIEXPORT jboolean JNICALL
+Java_com_phidgets_Dictionary_isAttachedToServer(JNIEnv *env, jobject obj)
+{
+ CPhidgetDictionaryHandle h = (CPhidgetDictionaryHandle)(uintptr_t)(*env)->GetLongField(env,
+ obj, dictionary_handle_fid);
+ int error;
+ int s;
+
+ if ((error = CPhidgetDictionary_getServerStatus(h, &s)))
+ PH_THROW(error);
+
+ return s == PHIDGET_ATTACHED;
+}
+
+JNIEXPORT jint JNICALL
+Java_com_phidgets_Dictionary_getServerPort(JNIEnv *env, jobject obj)
+{
+ CPhidgetDictionaryHandle h = (CPhidgetDictionaryHandle)(uintptr_t)(*env)->GetLongField(env,
+ obj, dictionary_handle_fid);
+ int error;
+ int port;
+ const char *addr;
+
+ if ((error = CPhidgetDictionary_getServerAddress(h, &addr, &port)))
+ PH_THROW(error);
+
+ return port;
+}
+
+JNIEXPORT jstring JNICALL
+Java_com_phidgets_Dictionary_getServerAddress(JNIEnv *env, jobject obj)
+{
+ CPhidgetDictionaryHandle h = (CPhidgetDictionaryHandle)(uintptr_t)(*env)->GetLongField(env,
+ obj, dictionary_handle_fid);
+ int error;
+ int port;
+ const char *addr;
+
+ if ((error = CPhidgetDictionary_getServerAddress(h, &addr, &port)))
+ PH_THROW(error);
+
+ return (*env)->NewStringUTF(env, addr);
+}
+
+JNIEXPORT jstring JNICALL
+Java_com_phidgets_Dictionary_getServerID(JNIEnv *env, jobject obj)
+{
+ CPhidgetDictionaryHandle h = (CPhidgetDictionaryHandle)(uintptr_t)(*env)->GetLongField(env,
+ obj, dictionary_handle_fid);
+ int error;
+ const char *id;
+
+ if ((error = CPhidgetDictionary_getServerID(h, &id)))
+ PH_THROW(error);
+
+ return (*env)->NewStringUTF(env, id);
+}
+
+JNIEXPORT void JNICALL
+Java_com_phidgets_Dictionary_nativeOpenRemote(JNIEnv *env, jobject obj, jstring serverID, jstring pass)
+{
+ int error;
+ jboolean iscopy;
+ const char *serverIDcopy = serverID?(*env)->GetStringUTFChars(
+ env, serverID, &iscopy):0;
+ const char *passcopy = (*env)->GetStringUTFChars(
+ env, pass, &iscopy);
+
+ CPhidgetDictionaryHandle h = (CPhidgetDictionaryHandle)(uintptr_t)
+ (*env)->GetLongField(env, obj, dictionary_handle_fid);
+
+ if ((error = CPhidgetDictionary_openRemote(h, serverIDcopy, passcopy)))
+ PH_THROW(error);
+
+ if(serverID)
+ (*env)->ReleaseStringUTFChars(env, serverID, serverIDcopy);
+ (*env)->ReleaseStringUTFChars(env, pass, passcopy);
+}
+
+JNIEXPORT void JNICALL
+Java_com_phidgets_Dictionary_nativeOpenRemoteIP(JNIEnv *env, jobject obj, jstring ipAddr, jint port, jstring pass)
+{
+ int error;
+ jboolean iscopy;
+ const char *ipAddrcopy = (*env)->GetStringUTFChars(
+ env, ipAddr, &iscopy);
+ const char *passcopy = (*env)->GetStringUTFChars(
+ env, pass, &iscopy);
+
+ CPhidgetDictionaryHandle h = (CPhidgetDictionaryHandle)(uintptr_t)
+ (*env)->GetLongField(env, obj, dictionary_handle_fid);
+
+ if ((error = CPhidgetDictionary_openRemoteIP(h, ipAddrcopy, port, passcopy)))
+ PH_THROW(error);
+
+ (*env)->ReleaseStringUTFChars(env, ipAddr, ipAddrcopy);
+ (*env)->ReleaseStringUTFChars(env, pass, passcopy);
+}
+
+JNIEXPORT void JNICALL
+Java_com_phidgets_Dictionary_nativeDelete(JNIEnv *env, jobject obj)
+{
+ int error;
+
+ CPhidgetDictionaryHandle h = (CPhidgetDictionaryHandle)(uintptr_t)
+ (*env)->GetLongField(env, obj, dictionary_handle_fid);
+
+ if ((error = CPhidgetDictionary_delete(h)))
+ PH_THROW(error);
+}
+
+JNIEXPORT void JNICALL
+Java_com_phidgets_Dictionary_nativeClose(JNIEnv *env, jobject obj)
+{
+ int error;
+
+ CPhidgetDictionaryHandle h = (CPhidgetDictionaryHandle)(uintptr_t)
+ (*env)->GetLongField(env, obj, dictionary_handle_fid);
+
+ if ((error = CPhidgetDictionary_close(h)))
+ PH_THROW(error);
+}
+
+JNIEXPORT void JNICALL
+Java_com_phidgets_Dictionary_nativeAddKey(JNIEnv *env, jobject obj, jstring key, jstring val, jint persistent)
+{
+ int error;
+
+ jboolean iscopy;
+ const char *keyString = (*env)->GetStringUTFChars(
+ env, key, &iscopy);
+ const char *valString = (*env)->GetStringUTFChars(
+ env, val, &iscopy);
+
+ CPhidgetDictionaryHandle h = (CPhidgetDictionaryHandle)(uintptr_t)
+ (*env)->GetLongField(env, obj, dictionary_handle_fid);
+
+ if ((error = CPhidgetDictionary_addKey(h, keyString, valString, persistent)))
+ PH_THROW(error);
+
+ (*env)->ReleaseStringUTFChars(env, key, keyString);
+ (*env)->ReleaseStringUTFChars(env, val, valString);
+}
+
+JNIEXPORT void JNICALL
+Java_com_phidgets_Dictionary_nativeRemoveKey(JNIEnv *env, jobject obj, jstring pattern)
+{
+ int error;
+
+ jboolean iscopy;
+ const char *patternString = (*env)->GetStringUTFChars(
+ env, pattern, &iscopy);
+
+ CPhidgetDictionaryHandle h = (CPhidgetDictionaryHandle)(uintptr_t)
+ (*env)->GetLongField(env, obj, dictionary_handle_fid);
+
+ if ((error = CPhidgetDictionary_removeKey(h, patternString)))
+ PH_THROW(error);
+
+ (*env)->ReleaseStringUTFChars(env, pattern, patternString);
+}
+
+JNIEXPORT jstring JNICALL
+Java_com_phidgets_Dictionary_nativeGetKey(JNIEnv *env, jobject obj, jstring key)
+{
+ int error;
+
+ char val[1024]; //TODO: unimpose this limit
+
+ jboolean iscopy;
+ const char *keyString = (*env)->GetStringUTFChars(
+ env, key, &iscopy);
+
+ CPhidgetDictionaryHandle h = (CPhidgetDictionaryHandle)(uintptr_t)
+ (*env)->GetLongField(env, obj, dictionary_handle_fid);
+
+ if ((error = CPhidgetDictionary_getKey(h, keyString, val, sizeof(val))))
+ {
+ PH_THROW(error);
+ (*env)->ReleaseStringUTFChars(env, key, keyString);
+ return (*env)->NewStringUTF(env, "");
+ }
+ else
+ {
+ (*env)->ReleaseStringUTFChars(env, key, keyString);
+ return (*env)->NewStringUTF(env, val);
+ }
+}
+
+JNIEXPORT jlong JNICALL
+Java_com_phidgets_Dictionary_create(JNIEnv *env, jobject obj)
+{
+ int error;
+ CPhidgetDictionaryHandle dict;
+
+ if ((error = CPhidgetDictionary_create(&dict)))
+ PH_THROW(error);
+ return (jlong)(uintptr_t)dict;
+}
diff --git a/Java/com_phidgets_Dictionary.h b/Java/com_phidgets_Dictionary.h
new file mode 100644
index 0000000..82bc3c5
--- /dev/null
+++ b/Java/com_phidgets_Dictionary.h
@@ -0,0 +1,133 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class com_phidgets_Dictionary */
+
+#ifndef _Included_com_phidgets_Dictionary
+#define _Included_com_phidgets_Dictionary
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: com_phidgets_Dictionary
+ * Method: create
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL Java_com_phidgets_Dictionary_create
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_Dictionary
+ * Method: nativeClose
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_Dictionary_nativeClose
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_Dictionary
+ * Method: nativeDelete
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_Dictionary_nativeDelete
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_Dictionary
+ * Method: nativeOpenRemote
+ * Signature: (Ljava/lang/String;Ljava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_Dictionary_nativeOpenRemote
+ (JNIEnv *, jobject, jstring, jstring);
+
+/*
+ * Class: com_phidgets_Dictionary
+ * Method: nativeOpenRemoteIP
+ * Signature: (Ljava/lang/String;ILjava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_Dictionary_nativeOpenRemoteIP
+ (JNIEnv *, jobject, jstring, jint, jstring);
+
+/*
+ * Class: com_phidgets_Dictionary
+ * Method: nativeAddKey
+ * Signature: (Ljava/lang/String;Ljava/lang/String;I)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_Dictionary_nativeAddKey
+ (JNIEnv *, jobject, jstring, jstring, jint);
+
+/*
+ * Class: com_phidgets_Dictionary
+ * Method: nativeRemoveKey
+ * Signature: (Ljava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_Dictionary_nativeRemoveKey
+ (JNIEnv *, jobject, jstring);
+
+/*
+ * Class: com_phidgets_Dictionary
+ * Method: nativeGetKey
+ * Signature: (Ljava/lang/String;)Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_com_phidgets_Dictionary_nativeGetKey
+ (JNIEnv *, jobject, jstring);
+
+/*
+ * Class: com_phidgets_Dictionary
+ * Method: getServerAddress
+ * Signature: ()Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_com_phidgets_Dictionary_getServerAddress
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_Dictionary
+ * Method: getServerID
+ * Signature: ()Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_com_phidgets_Dictionary_getServerID
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_Dictionary
+ * Method: getServerPort
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_phidgets_Dictionary_getServerPort
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_Dictionary
+ * Method: isAttached
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_phidgets_Dictionary_isAttached
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_Dictionary
+ * Method: isAttachedToServer
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_phidgets_Dictionary_isAttachedToServer
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_Dictionary
+ * Method: enableServerConnectEvents
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_Dictionary_enableServerConnectEvents
+ (JNIEnv *, jobject, jboolean);
+
+/*
+ * Class: com_phidgets_Dictionary
+ * Method: enableServerDisconnectEvents
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_Dictionary_enableServerDisconnectEvents
+ (JNIEnv *, jobject, jboolean);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/Java/com_phidgets_DictionaryKeyListener.c b/Java/com_phidgets_DictionaryKeyListener.c
new file mode 100644
index 0000000..a4f6593
--- /dev/null
+++ b/Java/com_phidgets_DictionaryKeyListener.c
@@ -0,0 +1,132 @@
+#include "../stdafx.h"
+#include <stdlib.h>
+#include "com_phidgets_Dictionary.h"
+#include "../cphidgetdictionary.h"
+#include "../csocket.h"
+#include "phidget_jni.h"
+
+static int CCONV
+key_handler(CPhidgetDictionaryHandle h, void *arg, const char *key, const char *val, CPhidgetDictionary_keyChangeReason reason);
+
+static jfieldID dictionaryKeyListener_handle_fid;
+static jfieldID nativeHandler_fid;
+static jfieldID nativeListener_fid;
+static jmethodID keyChangeEvent_cons; //constructor
+static jmethodID keyRemovalEvent_cons;
+static jmethodID fireKeyChange_mid;
+static jmethodID fireKeyRemoval_mid;
+static jclass dicitonaryKeyListener_class;
+static jclass keyChangeEvent_class;
+static jclass keyRemovalEvent_class;
+
+void
+com_phidgets_DictionaryKeyListener_OnLoad(JNIEnv *env)
+{
+ //DictionaryKeyListener
+ if (!(dicitonaryKeyListener_class = (*env)->FindClass(env, "com/phidgets/DictionaryKeyListener")))
+ JNI_ABORT_STDERR("Couldn't FindClass com/phidgets/DictionaryKeyListener");
+ if (!(dicitonaryKeyListener_class = (jclass)(*env)->NewGlobalRef(env, dicitonaryKeyListener_class)))
+ JNI_ABORT_STDERR("Couldn't create global ref dicitonaryKeyListener_class");
+
+ if (!(dictionaryKeyListener_handle_fid = (*env)->GetFieldID(env, dicitonaryKeyListener_class, "handle", "J")))
+ JNI_ABORT_STDERR("Couldn't get Field ID handle from dicitonaryKeyListener_class");
+ if (!(nativeHandler_fid = (*env)->GetFieldID(env, dicitonaryKeyListener_class, "nativeHandler", "J")))
+ JNI_ABORT_STDERR("Couldn't get Field ID nativeHandler from dicitonaryKeyListener_class");
+ if (!(nativeListener_fid = (*env)->GetFieldID(env, dicitonaryKeyListener_class, "listenerhandle", "J")))
+ JNI_ABORT_STDERR("Couldn't get Field ID listenerhandle from dicitonaryKeyListener_class");
+
+ if (!(fireKeyChange_mid = (*env)->GetMethodID(env, dicitonaryKeyListener_class, "fireKeyChange", "(Lcom/phidgets/event/KeyChangeEvent;)V")))
+ JNI_ABORT_STDERR("Couldn't get method ID fireKeyChange from dicitonaryKeyListener_class");
+ if (!(fireKeyRemoval_mid = (*env)->GetMethodID(env, dicitonaryKeyListener_class, "fireKeyRemoval", "(Lcom/phidgets/event/KeyRemovalEvent;)V")))
+ JNI_ABORT_STDERR("Couldn't get method ID fireKeyRemoval from dicitonaryKeyListener_class");
+
+ //KeyChangeEvent
+ if (!(keyChangeEvent_class = (*env)->FindClass(env, "com/phidgets/event/KeyChangeEvent")))
+ JNI_ABORT_STDERR("Couldn't FindClass com/phidgets/event/KeyChangeEvent");
+ if (!(keyChangeEvent_class = (jclass)(*env)->NewGlobalRef(env, keyChangeEvent_class)))
+ JNI_ABORT_STDERR("Couldn't create global ref keyChangeEvent_class");
+ if (!(keyChangeEvent_cons = (*env)->GetMethodID(env, keyChangeEvent_class, "<init>", "(Lcom/phidgets/Dictionary;Ljava/lang/String;Ljava/lang/String;)V")))
+ JNI_ABORT_STDERR("Couldn't get method ID <init> from keyChangeEvent_class");
+
+ //KeyRemovalEvent
+ if (!(keyRemovalEvent_class = (*env)->FindClass(env, "com/phidgets/event/KeyRemovalEvent")))
+ JNI_ABORT_STDERR("Couldn't FindClass com/phidgets/event/KeyRemovalEvent");
+ if (!(keyRemovalEvent_class = (jclass)(*env)->NewGlobalRef(env, keyRemovalEvent_class)))
+ JNI_ABORT_STDERR("Couldn't create global ref keyRemovalEvent_class");
+ if (!(keyRemovalEvent_cons = (*env)->GetMethodID(env, keyRemovalEvent_class, "<init>", "(Lcom/phidgets/Dictionary;Ljava/lang/String;Ljava/lang/String;)V")))
+ JNI_ABORT_STDERR("Couldn't get method ID <init> from keyRemovalEvent_class");
+}
+
+JNIEXPORT jlong JNICALL
+Java_com_phidgets_DictionaryKeyListener_enableDictionaryKeyEvents(JNIEnv *env, jobject obj,
+ jboolean b, jstring pattern)
+{
+ CPhidgetDictionaryListenerHandle keylistener;
+ jlong gr = updateGlobalRef(env, obj, nativeHandler_fid, b);
+
+ jboolean iscopy;
+ const char *textString = (*env)->GetStringUTFChars(
+ env, pattern, &iscopy);
+
+ CPhidgetDictionaryHandle h = (CPhidgetDictionaryHandle)(uintptr_t)
+ (*env)->GetLongField(env, obj, dictionaryKeyListener_handle_fid);
+
+ if(b)
+ {
+ CPhidgetDictionary_set_OnKeyChange_Handler(h, &keylistener, textString, b ? key_handler : 0,
+ (void *)(uintptr_t)gr);
+ }
+ else
+ {
+ keylistener = (CPhidgetDictionaryListenerHandle)(uintptr_t)
+ (*env)->GetLongField(env, obj, nativeListener_fid);
+ CPhidgetDictionary_remove_OnKeyChange_Handler(keylistener);
+ keylistener = NULL;
+ }
+
+ (*env)->ReleaseStringUTFChars(env, pattern, textString);
+
+ return (jlong)(uintptr_t)keylistener;
+}
+
+static int CCONV
+key_handler(CPhidgetDictionaryHandle h, void *arg, const char *key, const char *val, CPhidgetDictionary_keyChangeReason reason)
+{
+ JNIEnv *env;
+ jobject obj;
+ jobject keyEvent;
+ jstring k;
+ jstring v;
+
+ if ((*ph_vm)->AttachCurrentThread(ph_vm, (JNIEnvPtr)&env, NULL))
+ JNI_ABORT_STDERR("Couldn't AttachCurrentThread");
+
+ obj = (jobject)arg;
+
+ k=(*env)->NewStringUTF(env, key);
+ v=(*env)->NewStringUTF(env, val);
+
+ switch(reason)
+ {
+ case PHIDGET_DICTIONARY_ENTRY_REMOVING:
+ {
+ if (!(keyEvent = (*env)->NewObject(env, keyRemovalEvent_class, keyRemovalEvent_cons,
+ obj, k, v)))
+ return -1;
+ (*env)->CallVoidMethod(env, obj, fireKeyRemoval_mid, keyEvent);
+ break;
+ }
+ default:
+ {
+ if (!(keyEvent = (*env)->NewObject(env, keyChangeEvent_class, keyChangeEvent_cons,
+ obj, k, v)))
+ return -1;
+ (*env)->CallVoidMethod(env, obj, fireKeyChange_mid, keyEvent);
+ }
+ }
+
+ (*env)->DeleteLocalRef(env, keyEvent);
+ (*ph_vm)->DetachCurrentThread(ph_vm);
+
+ return 0;
+}
diff --git a/Java/com_phidgets_DictionaryKeyListener.h b/Java/com_phidgets_DictionaryKeyListener.h
new file mode 100644
index 0000000..5d8515a
--- /dev/null
+++ b/Java/com_phidgets_DictionaryKeyListener.h
@@ -0,0 +1,21 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class com_phidgets_DictionaryKeyListener */
+
+#ifndef _Included_com_phidgets_DictionaryKeyListener
+#define _Included_com_phidgets_DictionaryKeyListener
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: com_phidgets_DictionaryKeyListener
+ * Method: enableDictionaryKeyEvents
+ * Signature: (ZLjava/lang/String;)J
+ */
+JNIEXPORT jlong JNICALL Java_com_phidgets_DictionaryKeyListener_enableDictionaryKeyEvents
+ (JNIEnv *, jobject, jboolean, jstring);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/Java/com_phidgets_EncoderPhidget.c b/Java/com_phidgets_EncoderPhidget.c
new file mode 100644
index 0000000..e46389e
--- /dev/null
+++ b/Java/com_phidgets_EncoderPhidget.c
@@ -0,0 +1,31 @@
+#include "../stdafx.h"
+#include "phidget_jni.h"
+#include "com_phidgets_EncoderPhidget.h"
+#include "../cphidgetencoder.h"
+
+EVENT_VARS(inputChange, InputChange)
+EVENT_VARS(encoderPositionChange, EncoderPositionChange)
+
+JNI_LOAD(enc, Encoder)
+ EVENT_VAR_SETUP(enc, inputChange, InputChange, IZ, V)
+ EVENT_VAR_SETUP(enc, encoderPositionChange, EncoderPositionChange, III, V)
+}
+
+EVENT_HANDLER_INDEXED(Encoder, inputChange, InputChange,
+ CPhidgetEncoder_set_OnInputChange_Handler, int)
+EVENT_HANDLER_INDEXED2(Encoder, encoderPositionChange, EncoderPositionChange,
+ CPhidgetEncoder_set_OnPositionChange_Handler, int, int)
+
+JNI_CREATE(Encoder)
+JNI_INDEXED_GETFUNC(Encoder, Position, Position, jint)
+JNI_INDEXED_SETFUNC(Encoder, Position, Position, jint)
+JNI_INDEXED_GETFUNCBOOL(Encoder, InputState, InputState)
+JNI_GETFUNC(Encoder, EncoderCount, EncoderCount, jint)
+JNI_GETFUNC(Encoder, InputCount, InputCount, jint)
+JNI_INDEXED_GETFUNC(Encoder, IndexPosition, IndexPosition, jint)
+JNI_INDEXED_GETFUNCBOOL(Encoder, Enabled, Enabled)
+JNI_INDEXED_SETFUNC(Encoder, Enabled, Enabled, jboolean)
+
+//Deprecated
+JNI_INDEXED_GETFUNC(Encoder, EncoderPosition, Position, jint)
+JNI_INDEXED_SETFUNC(Encoder, EncoderPosition, Position, jint)
diff --git a/Java/com_phidgets_EncoderPhidget.h b/Java/com_phidgets_EncoderPhidget.h
new file mode 100644
index 0000000..fa7cefc
--- /dev/null
+++ b/Java/com_phidgets_EncoderPhidget.h
@@ -0,0 +1,261 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class com_phidgets_EncoderPhidget */
+
+#ifndef _Included_com_phidgets_EncoderPhidget
+#define _Included_com_phidgets_EncoderPhidget
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef com_phidgets_EncoderPhidget_PHIDGET_LOG_CRITICAL
+#define com_phidgets_EncoderPhidget_PHIDGET_LOG_CRITICAL 1L
+#undef com_phidgets_EncoderPhidget_PHIDGET_LOG_ERROR
+#define com_phidgets_EncoderPhidget_PHIDGET_LOG_ERROR 2L
+#undef com_phidgets_EncoderPhidget_PHIDGET_LOG_WARNING
+#define com_phidgets_EncoderPhidget_PHIDGET_LOG_WARNING 3L
+#undef com_phidgets_EncoderPhidget_PHIDGET_LOG_DEBUG
+#define com_phidgets_EncoderPhidget_PHIDGET_LOG_DEBUG 4L
+#undef com_phidgets_EncoderPhidget_PHIDGET_LOG_INFO
+#define com_phidgets_EncoderPhidget_PHIDGET_LOG_INFO 5L
+#undef com_phidgets_EncoderPhidget_PHIDGET_LOG_VERBOSE
+#define com_phidgets_EncoderPhidget_PHIDGET_LOG_VERBOSE 6L
+#undef com_phidgets_EncoderPhidget_PHIDID_NOTHING
+#define com_phidgets_EncoderPhidget_PHIDID_NOTHING 1L
+#undef com_phidgets_EncoderPhidget_PHIDID_ACCELEROMETER_3AXIS
+#define com_phidgets_EncoderPhidget_PHIDID_ACCELEROMETER_3AXIS 126L
+#undef com_phidgets_EncoderPhidget_PHIDID_ADVANCEDSERVO_1MOTOR
+#define com_phidgets_EncoderPhidget_PHIDID_ADVANCEDSERVO_1MOTOR 130L
+#undef com_phidgets_EncoderPhidget_PHIDID_ANALOG_4OUTPUT
+#define com_phidgets_EncoderPhidget_PHIDID_ANALOG_4OUTPUT 55L
+#undef com_phidgets_EncoderPhidget_PHIDID_ADVANCEDSERVO_8MOTOR
+#define com_phidgets_EncoderPhidget_PHIDID_ADVANCEDSERVO_8MOTOR 58L
+#undef com_phidgets_EncoderPhidget_PHIDID_BIPOLAR_STEPPER_1MOTOR
+#define com_phidgets_EncoderPhidget_PHIDID_BIPOLAR_STEPPER_1MOTOR 123L
+#undef com_phidgets_EncoderPhidget_PHIDID_BRIDGE_4INPUT
+#define com_phidgets_EncoderPhidget_PHIDID_BRIDGE_4INPUT 59L
+#undef com_phidgets_EncoderPhidget_PHIDID_ENCODER_1ENCODER_1INPUT
+#define com_phidgets_EncoderPhidget_PHIDID_ENCODER_1ENCODER_1INPUT 75L
+#undef com_phidgets_EncoderPhidget_PHIDID_ENCODER_HS_1ENCODER
+#define com_phidgets_EncoderPhidget_PHIDID_ENCODER_HS_1ENCODER 128L
+#undef com_phidgets_EncoderPhidget_PHIDID_ENCODER_HS_4ENCODER_4INPUT
+#define com_phidgets_EncoderPhidget_PHIDID_ENCODER_HS_4ENCODER_4INPUT 79L
+#undef com_phidgets_EncoderPhidget_PHIDID_FREQUENCYCOUNTER_2INPUT
+#define com_phidgets_EncoderPhidget_PHIDID_FREQUENCYCOUNTER_2INPUT 53L
+#undef com_phidgets_EncoderPhidget_PHIDID_GPS
+#define com_phidgets_EncoderPhidget_PHIDID_GPS 121L
+#undef com_phidgets_EncoderPhidget_PHIDID_INTERFACEKIT_0_0_4
+#define com_phidgets_EncoderPhidget_PHIDID_INTERFACEKIT_0_0_4 64L
+#undef com_phidgets_EncoderPhidget_PHIDID_INTERFACEKIT_0_0_8
+#define com_phidgets_EncoderPhidget_PHIDID_INTERFACEKIT_0_0_8 129L
+#undef com_phidgets_EncoderPhidget_PHIDID_INTERFACEKIT_0_16_16
+#define com_phidgets_EncoderPhidget_PHIDID_INTERFACEKIT_0_16_16 68L
+#undef com_phidgets_EncoderPhidget_PHIDID_INTERFACEKIT_8_8_8
+#define com_phidgets_EncoderPhidget_PHIDID_INTERFACEKIT_8_8_8 69L
+#undef com_phidgets_EncoderPhidget_PHIDID_INTERFACEKIT_8_8_8_w_LCD
+#define com_phidgets_EncoderPhidget_PHIDID_INTERFACEKIT_8_8_8_w_LCD 125L
+#undef com_phidgets_EncoderPhidget_PHIDID_IR
+#define com_phidgets_EncoderPhidget_PHIDID_IR 77L
+#undef com_phidgets_EncoderPhidget_PHIDID_LED_64
+#define com_phidgets_EncoderPhidget_PHIDID_LED_64 74L
+#undef com_phidgets_EncoderPhidget_PHIDID_LED_64_ADV
+#define com_phidgets_EncoderPhidget_PHIDID_LED_64_ADV 76L
+#undef com_phidgets_EncoderPhidget_PHIDID_LINEAR_TOUCH
+#define com_phidgets_EncoderPhidget_PHIDID_LINEAR_TOUCH 118L
+#undef com_phidgets_EncoderPhidget_PHIDID_MOTORCONTROL_HC_2MOTOR
+#define com_phidgets_EncoderPhidget_PHIDID_MOTORCONTROL_HC_2MOTOR 89L
+#undef com_phidgets_EncoderPhidget_PHIDID_MOTORCONTROL_LV_2MOTOR_4INPUT
+#define com_phidgets_EncoderPhidget_PHIDID_MOTORCONTROL_LV_2MOTOR_4INPUT 88L
+#undef com_phidgets_EncoderPhidget_PHIDID_MOTORCONTROL_1MOTOR
+#define com_phidgets_EncoderPhidget_PHIDID_MOTORCONTROL_1MOTOR 62L
+#undef com_phidgets_EncoderPhidget_PHIDID_PHSENSOR
+#define com_phidgets_EncoderPhidget_PHIDID_PHSENSOR 116L
+#undef com_phidgets_EncoderPhidget_PHIDID_RFID_2OUTPUT
+#define com_phidgets_EncoderPhidget_PHIDID_RFID_2OUTPUT 49L
+#undef com_phidgets_EncoderPhidget_PHIDID_ROTARY_TOUCH
+#define com_phidgets_EncoderPhidget_PHIDID_ROTARY_TOUCH 119L
+#undef com_phidgets_EncoderPhidget_PHIDID_SERVO_1MOTOR
+#define com_phidgets_EncoderPhidget_PHIDID_SERVO_1MOTOR 57L
+#undef com_phidgets_EncoderPhidget_PHIDID_SPATIAL_ACCEL_3AXIS
+#define com_phidgets_EncoderPhidget_PHIDID_SPATIAL_ACCEL_3AXIS 127L
+#undef com_phidgets_EncoderPhidget_PHIDID_SPATIAL_ACCEL_GYRO_COMPASS
+#define com_phidgets_EncoderPhidget_PHIDID_SPATIAL_ACCEL_GYRO_COMPASS 51L
+#undef com_phidgets_EncoderPhidget_PHIDID_TEMPERATURESENSOR
+#define com_phidgets_EncoderPhidget_PHIDID_TEMPERATURESENSOR 112L
+#undef com_phidgets_EncoderPhidget_PHIDID_TEMPERATURESENSOR_4
+#define com_phidgets_EncoderPhidget_PHIDID_TEMPERATURESENSOR_4 50L
+#undef com_phidgets_EncoderPhidget_PHIDID_TEXTLCD_2x20_w_8_8_8
+#define com_phidgets_EncoderPhidget_PHIDID_TEXTLCD_2x20_w_8_8_8 381L
+#undef com_phidgets_EncoderPhidget_PHIDID_TEXTLCD_ADAPTER
+#define com_phidgets_EncoderPhidget_PHIDID_TEXTLCD_ADAPTER 61L
+#undef com_phidgets_EncoderPhidget_PHIDID_UNIPOLAR_STEPPER_4MOTOR
+#define com_phidgets_EncoderPhidget_PHIDID_UNIPOLAR_STEPPER_4MOTOR 122L
+#undef com_phidgets_EncoderPhidget_PHIDID_ACCELEROMETER_2AXIS
+#define com_phidgets_EncoderPhidget_PHIDID_ACCELEROMETER_2AXIS 113L
+#undef com_phidgets_EncoderPhidget_PHIDID_INTERFACEKIT_0_8_8_w_LCD
+#define com_phidgets_EncoderPhidget_PHIDID_INTERFACEKIT_0_8_8_w_LCD 83L
+#undef com_phidgets_EncoderPhidget_PHIDID_INTERFACEKIT_4_8_8
+#define com_phidgets_EncoderPhidget_PHIDID_INTERFACEKIT_4_8_8 4L
+#undef com_phidgets_EncoderPhidget_PHIDID_RFID
+#define com_phidgets_EncoderPhidget_PHIDID_RFID 48L
+#undef com_phidgets_EncoderPhidget_PHIDID_SERVO_1MOTOR_OLD
+#define com_phidgets_EncoderPhidget_PHIDID_SERVO_1MOTOR_OLD 2L
+#undef com_phidgets_EncoderPhidget_PHIDID_SERVO_4MOTOR
+#define com_phidgets_EncoderPhidget_PHIDID_SERVO_4MOTOR 56L
+#undef com_phidgets_EncoderPhidget_PHIDID_SERVO_4MOTOR_OLD
+#define com_phidgets_EncoderPhidget_PHIDID_SERVO_4MOTOR_OLD 3L
+#undef com_phidgets_EncoderPhidget_PHIDID_TEXTLCD_2x20
+#define com_phidgets_EncoderPhidget_PHIDID_TEXTLCD_2x20 82L
+#undef com_phidgets_EncoderPhidget_PHIDID_TEXTLCD_2x20_w_0_8_8
+#define com_phidgets_EncoderPhidget_PHIDID_TEXTLCD_2x20_w_0_8_8 339L
+#undef com_phidgets_EncoderPhidget_PHIDID_TEXTLED_1x8
+#define com_phidgets_EncoderPhidget_PHIDID_TEXTLED_1x8 73L
+#undef com_phidgets_EncoderPhidget_PHIDID_TEXTLED_4x8
+#define com_phidgets_EncoderPhidget_PHIDID_TEXTLED_4x8 72L
+#undef com_phidgets_EncoderPhidget_PHIDID_WEIGHTSENSOR
+#define com_phidgets_EncoderPhidget_PHIDID_WEIGHTSENSOR 114L
+#undef com_phidgets_EncoderPhidget_PHIDCLASS_NOTHING
+#define com_phidgets_EncoderPhidget_PHIDCLASS_NOTHING 1L
+#undef com_phidgets_EncoderPhidget_PHIDCLASS_ACCELEROMETER
+#define com_phidgets_EncoderPhidget_PHIDCLASS_ACCELEROMETER 2L
+#undef com_phidgets_EncoderPhidget_PHIDCLASS_ADVANCEDSERVO
+#define com_phidgets_EncoderPhidget_PHIDCLASS_ADVANCEDSERVO 3L
+#undef com_phidgets_EncoderPhidget_PHIDCLASS_ANALOG
+#define com_phidgets_EncoderPhidget_PHIDCLASS_ANALOG 22L
+#undef com_phidgets_EncoderPhidget_PHIDCLASS_BRIDGE
+#define com_phidgets_EncoderPhidget_PHIDCLASS_BRIDGE 23L
+#undef com_phidgets_EncoderPhidget_PHIDCLASS_ENCODER
+#define com_phidgets_EncoderPhidget_PHIDCLASS_ENCODER 4L
+#undef com_phidgets_EncoderPhidget_PHIDCLASS_FREQUENCYCOUNTER
+#define com_phidgets_EncoderPhidget_PHIDCLASS_FREQUENCYCOUNTER 21L
+#undef com_phidgets_EncoderPhidget_PHIDCLASS_GPS
+#define com_phidgets_EncoderPhidget_PHIDCLASS_GPS 5L
+#undef com_phidgets_EncoderPhidget_PHIDCLASS_INTERFACEKIT
+#define com_phidgets_EncoderPhidget_PHIDCLASS_INTERFACEKIT 7L
+#undef com_phidgets_EncoderPhidget_PHIDCLASS_LED
+#define com_phidgets_EncoderPhidget_PHIDCLASS_LED 8L
+#undef com_phidgets_EncoderPhidget_PHIDCLASS_MOTORCONTROL
+#define com_phidgets_EncoderPhidget_PHIDCLASS_MOTORCONTROL 9L
+#undef com_phidgets_EncoderPhidget_PHIDCLASS_PHSENSOR
+#define com_phidgets_EncoderPhidget_PHIDCLASS_PHSENSOR 10L
+#undef com_phidgets_EncoderPhidget_PHIDCLASS_RFID
+#define com_phidgets_EncoderPhidget_PHIDCLASS_RFID 11L
+#undef com_phidgets_EncoderPhidget_PHIDCLASS_SERVO
+#define com_phidgets_EncoderPhidget_PHIDCLASS_SERVO 12L
+#undef com_phidgets_EncoderPhidget_PHIDCLASS_STEPPER
+#define com_phidgets_EncoderPhidget_PHIDCLASS_STEPPER 13L
+#undef com_phidgets_EncoderPhidget_PHIDCLASS_TEMPERATURESENSOR
+#define com_phidgets_EncoderPhidget_PHIDCLASS_TEMPERATURESENSOR 14L
+#undef com_phidgets_EncoderPhidget_PHIDCLASS_TEXTLCD
+#define com_phidgets_EncoderPhidget_PHIDCLASS_TEXTLCD 15L
+#undef com_phidgets_EncoderPhidget_PHIDCLASS_TEXTLED
+#define com_phidgets_EncoderPhidget_PHIDCLASS_TEXTLED 16L
+#undef com_phidgets_EncoderPhidget_PHIDCLASS_WEIGHTSENSOR
+#define com_phidgets_EncoderPhidget_PHIDCLASS_WEIGHTSENSOR 17L
+/*
+ * Class: com_phidgets_EncoderPhidget
+ * Method: create
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL Java_com_phidgets_EncoderPhidget_create
+ (JNIEnv *, jclass);
+
+/*
+ * Class: com_phidgets_EncoderPhidget
+ * Method: getEncoderCount
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_phidgets_EncoderPhidget_getEncoderCount
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_EncoderPhidget
+ * Method: getInputCount
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_phidgets_EncoderPhidget_getInputCount
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_EncoderPhidget
+ * Method: getPosition
+ * Signature: (I)I
+ */
+JNIEXPORT jint JNICALL Java_com_phidgets_EncoderPhidget_getPosition
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_EncoderPhidget
+ * Method: getIndexPosition
+ * Signature: (I)I
+ */
+JNIEXPORT jint JNICALL Java_com_phidgets_EncoderPhidget_getIndexPosition
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_EncoderPhidget
+ * Method: getEncoderPosition
+ * Signature: (I)I
+ */
+JNIEXPORT jint JNICALL Java_com_phidgets_EncoderPhidget_getEncoderPosition
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_EncoderPhidget
+ * Method: setPosition
+ * Signature: (II)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_EncoderPhidget_setPosition
+ (JNIEnv *, jobject, jint, jint);
+
+/*
+ * Class: com_phidgets_EncoderPhidget
+ * Method: setEncoderPosition
+ * Signature: (II)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_EncoderPhidget_setEncoderPosition
+ (JNIEnv *, jobject, jint, jint);
+
+/*
+ * Class: com_phidgets_EncoderPhidget
+ * Method: getInputState
+ * Signature: (I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_phidgets_EncoderPhidget_getInputState
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_EncoderPhidget
+ * Method: getEnabled
+ * Signature: (I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_phidgets_EncoderPhidget_getEnabled
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_EncoderPhidget
+ * Method: setEnabled
+ * Signature: (IZ)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_EncoderPhidget_setEnabled
+ (JNIEnv *, jobject, jint, jboolean);
+
+/*
+ * Class: com_phidgets_EncoderPhidget
+ * Method: enableEncoderPositionChangeEvents
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_EncoderPhidget_enableEncoderPositionChangeEvents
+ (JNIEnv *, jobject, jboolean);
+
+/*
+ * Class: com_phidgets_EncoderPhidget
+ * Method: enableInputChangeEvents
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_EncoderPhidget_enableInputChangeEvents
+ (JNIEnv *, jobject, jboolean);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/Java/com_phidgets_FrequencyCounterPhidget.c b/Java/com_phidgets_FrequencyCounterPhidget.c
new file mode 100644
index 0000000..dd3d38c
--- /dev/null
+++ b/Java/com_phidgets_FrequencyCounterPhidget.c
@@ -0,0 +1,49 @@
+#include "../stdafx.h"
+#include "phidget_jni.h"
+#include "com_phidgets_FrequencyCounterPhidget.h"
+#include "../cphidgetfrequencycounter.h"
+
+EVENT_VARS(frequencyCounterCount, FrequencyCounterCount)
+
+JNI_LOAD(frequencyCounter, FrequencyCounter)
+ EVENT_VAR_SETUP(frequencyCounter, frequencyCounterCount, FrequencyCounterCount, III, V)
+}
+
+EVENT_HANDLER_INDEXED2(FrequencyCounter, frequencyCounterCount, FrequencyCounterCount,
+ CPhidgetFrequencyCounter_set_OnCount_Handler, int, int)
+
+JNI_CREATE(FrequencyCounter)
+
+JNI_GETFUNC(FrequencyCounter, FrequencyInputCount, FrequencyInputCount, jint)
+JNI_INDEXED_GETFUNC(FrequencyCounter, Frequency, Frequency, jdouble)
+JNI_INDEXED_GETFUNC(FrequencyCounter, TotalTime, TotalTime, jlong)
+JNI_INDEXED_GETFUNC(FrequencyCounter, TotalCount, TotalCount, jlong)
+JNI_INDEXED_GETFUNC(FrequencyCounter, Timeout, Timeout, jint)
+JNI_INDEXED_SETFUNC(FrequencyCounter, Timeout, Timeout, jint)
+JNI_INDEXED_GETFUNCBOOL(FrequencyCounter, Enabled, Enabled)
+JNI_INDEXED_SETFUNC(FrequencyCounter, Enabled, Enabled, jboolean)
+
+JNIEXPORT jint JNICALL
+Java_com_phidgets_FrequencyCounterPhidget_getFilter(JNIEnv *env, jobject obj, jint index)
+{
+ CPhidgetFrequencyCounterHandle h = (CPhidgetFrequencyCounterHandle)(uintptr_t)
+ (*env)->GetLongField(env, obj, handle_fid);
+ int error;
+ CPhidgetFrequencyCounter_FilterType v;
+ if ((error = CPhidgetFrequencyCounter_getFilter(h, index, &v)))
+ PH_THROW(error);
+ return (jint)v;
+}
+
+JNI_INDEXED_SETFUNC(FrequencyCounter, Filter, Filter, jint)
+
+JNIEXPORT void JNICALL
+Java_com_phidgets_FrequencyCounterPhidget_reset(JNIEnv *env, jobject obj, jint index)
+{
+ CPhidgetFrequencyCounterHandle h = (CPhidgetFrequencyCounterHandle)(uintptr_t)
+ (*env)->GetLongField(env, obj, handle_fid);
+ int error;
+
+ if ((error = CPhidgetFrequencyCounter_reset(h, index)))
+ PH_THROW(error);
+} \ No newline at end of file
diff --git a/Java/com_phidgets_FrequencyCounterPhidget.h b/Java/com_phidgets_FrequencyCounterPhidget.h
new file mode 100644
index 0000000..59c0075
--- /dev/null
+++ b/Java/com_phidgets_FrequencyCounterPhidget.h
@@ -0,0 +1,267 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class com_phidgets_FrequencyCounterPhidget */
+
+#ifndef _Included_com_phidgets_FrequencyCounterPhidget
+#define _Included_com_phidgets_FrequencyCounterPhidget
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef com_phidgets_FrequencyCounterPhidget_PHIDGET_LOG_CRITICAL
+#define com_phidgets_FrequencyCounterPhidget_PHIDGET_LOG_CRITICAL 1L
+#undef com_phidgets_FrequencyCounterPhidget_PHIDGET_LOG_ERROR
+#define com_phidgets_FrequencyCounterPhidget_PHIDGET_LOG_ERROR 2L
+#undef com_phidgets_FrequencyCounterPhidget_PHIDGET_LOG_WARNING
+#define com_phidgets_FrequencyCounterPhidget_PHIDGET_LOG_WARNING 3L
+#undef com_phidgets_FrequencyCounterPhidget_PHIDGET_LOG_DEBUG
+#define com_phidgets_FrequencyCounterPhidget_PHIDGET_LOG_DEBUG 4L
+#undef com_phidgets_FrequencyCounterPhidget_PHIDGET_LOG_INFO
+#define com_phidgets_FrequencyCounterPhidget_PHIDGET_LOG_INFO 5L
+#undef com_phidgets_FrequencyCounterPhidget_PHIDGET_LOG_VERBOSE
+#define com_phidgets_FrequencyCounterPhidget_PHIDGET_LOG_VERBOSE 6L
+#undef com_phidgets_FrequencyCounterPhidget_PHIDID_NOTHING
+#define com_phidgets_FrequencyCounterPhidget_PHIDID_NOTHING 1L
+#undef com_phidgets_FrequencyCounterPhidget_PHIDID_ACCELEROMETER_3AXIS
+#define com_phidgets_FrequencyCounterPhidget_PHIDID_ACCELEROMETER_3AXIS 126L
+#undef com_phidgets_FrequencyCounterPhidget_PHIDID_ADVANCEDSERVO_1MOTOR
+#define com_phidgets_FrequencyCounterPhidget_PHIDID_ADVANCEDSERVO_1MOTOR 130L
+#undef com_phidgets_FrequencyCounterPhidget_PHIDID_ANALOG_4OUTPUT
+#define com_phidgets_FrequencyCounterPhidget_PHIDID_ANALOG_4OUTPUT 55L
+#undef com_phidgets_FrequencyCounterPhidget_PHIDID_ADVANCEDSERVO_8MOTOR
+#define com_phidgets_FrequencyCounterPhidget_PHIDID_ADVANCEDSERVO_8MOTOR 58L
+#undef com_phidgets_FrequencyCounterPhidget_PHIDID_BIPOLAR_STEPPER_1MOTOR
+#define com_phidgets_FrequencyCounterPhidget_PHIDID_BIPOLAR_STEPPER_1MOTOR 123L
+#undef com_phidgets_FrequencyCounterPhidget_PHIDID_BRIDGE_4INPUT
+#define com_phidgets_FrequencyCounterPhidget_PHIDID_BRIDGE_4INPUT 59L
+#undef com_phidgets_FrequencyCounterPhidget_PHIDID_ENCODER_1ENCODER_1INPUT
+#define com_phidgets_FrequencyCounterPhidget_PHIDID_ENCODER_1ENCODER_1INPUT 75L
+#undef com_phidgets_FrequencyCounterPhidget_PHIDID_ENCODER_HS_1ENCODER
+#define com_phidgets_FrequencyCounterPhidget_PHIDID_ENCODER_HS_1ENCODER 128L
+#undef com_phidgets_FrequencyCounterPhidget_PHIDID_ENCODER_HS_4ENCODER_4INPUT
+#define com_phidgets_FrequencyCounterPhidget_PHIDID_ENCODER_HS_4ENCODER_4INPUT 79L
+#undef com_phidgets_FrequencyCounterPhidget_PHIDID_FREQUENCYCOUNTER_2INPUT
+#define com_phidgets_FrequencyCounterPhidget_PHIDID_FREQUENCYCOUNTER_2INPUT 53L
+#undef com_phidgets_FrequencyCounterPhidget_PHIDID_GPS
+#define com_phidgets_FrequencyCounterPhidget_PHIDID_GPS 121L
+#undef com_phidgets_FrequencyCounterPhidget_PHIDID_INTERFACEKIT_0_0_4
+#define com_phidgets_FrequencyCounterPhidget_PHIDID_INTERFACEKIT_0_0_4 64L
+#undef com_phidgets_FrequencyCounterPhidget_PHIDID_INTERFACEKIT_0_0_8
+#define com_phidgets_FrequencyCounterPhidget_PHIDID_INTERFACEKIT_0_0_8 129L
+#undef com_phidgets_FrequencyCounterPhidget_PHIDID_INTERFACEKIT_0_16_16
+#define com_phidgets_FrequencyCounterPhidget_PHIDID_INTERFACEKIT_0_16_16 68L
+#undef com_phidgets_FrequencyCounterPhidget_PHIDID_INTERFACEKIT_8_8_8
+#define com_phidgets_FrequencyCounterPhidget_PHIDID_INTERFACEKIT_8_8_8 69L
+#undef com_phidgets_FrequencyCounterPhidget_PHIDID_INTERFACEKIT_8_8_8_w_LCD
+#define com_phidgets_FrequencyCounterPhidget_PHIDID_INTERFACEKIT_8_8_8_w_LCD 125L
+#undef com_phidgets_FrequencyCounterPhidget_PHIDID_IR
+#define com_phidgets_FrequencyCounterPhidget_PHIDID_IR 77L
+#undef com_phidgets_FrequencyCounterPhidget_PHIDID_LED_64
+#define com_phidgets_FrequencyCounterPhidget_PHIDID_LED_64 74L
+#undef com_phidgets_FrequencyCounterPhidget_PHIDID_LED_64_ADV
+#define com_phidgets_FrequencyCounterPhidget_PHIDID_LED_64_ADV 76L
+#undef com_phidgets_FrequencyCounterPhidget_PHIDID_LINEAR_TOUCH
+#define com_phidgets_FrequencyCounterPhidget_PHIDID_LINEAR_TOUCH 118L
+#undef com_phidgets_FrequencyCounterPhidget_PHIDID_MOTORCONTROL_HC_2MOTOR
+#define com_phidgets_FrequencyCounterPhidget_PHIDID_MOTORCONTROL_HC_2MOTOR 89L
+#undef com_phidgets_FrequencyCounterPhidget_PHIDID_MOTORCONTROL_LV_2MOTOR_4INPUT
+#define com_phidgets_FrequencyCounterPhidget_PHIDID_MOTORCONTROL_LV_2MOTOR_4INPUT 88L
+#undef com_phidgets_FrequencyCounterPhidget_PHIDID_MOTORCONTROL_1MOTOR
+#define com_phidgets_FrequencyCounterPhidget_PHIDID_MOTORCONTROL_1MOTOR 62L
+#undef com_phidgets_FrequencyCounterPhidget_PHIDID_PHSENSOR
+#define com_phidgets_FrequencyCounterPhidget_PHIDID_PHSENSOR 116L
+#undef com_phidgets_FrequencyCounterPhidget_PHIDID_RFID_2OUTPUT
+#define com_phidgets_FrequencyCounterPhidget_PHIDID_RFID_2OUTPUT 49L
+#undef com_phidgets_FrequencyCounterPhidget_PHIDID_ROTARY_TOUCH
+#define com_phidgets_FrequencyCounterPhidget_PHIDID_ROTARY_TOUCH 119L
+#undef com_phidgets_FrequencyCounterPhidget_PHIDID_SERVO_1MOTOR
+#define com_phidgets_FrequencyCounterPhidget_PHIDID_SERVO_1MOTOR 57L
+#undef com_phidgets_FrequencyCounterPhidget_PHIDID_SPATIAL_ACCEL_3AXIS
+#define com_phidgets_FrequencyCounterPhidget_PHIDID_SPATIAL_ACCEL_3AXIS 127L
+#undef com_phidgets_FrequencyCounterPhidget_PHIDID_SPATIAL_ACCEL_GYRO_COMPASS
+#define com_phidgets_FrequencyCounterPhidget_PHIDID_SPATIAL_ACCEL_GYRO_COMPASS 51L
+#undef com_phidgets_FrequencyCounterPhidget_PHIDID_TEMPERATURESENSOR
+#define com_phidgets_FrequencyCounterPhidget_PHIDID_TEMPERATURESENSOR 112L
+#undef com_phidgets_FrequencyCounterPhidget_PHIDID_TEMPERATURESENSOR_4
+#define com_phidgets_FrequencyCounterPhidget_PHIDID_TEMPERATURESENSOR_4 50L
+#undef com_phidgets_FrequencyCounterPhidget_PHIDID_TEXTLCD_2x20_w_8_8_8
+#define com_phidgets_FrequencyCounterPhidget_PHIDID_TEXTLCD_2x20_w_8_8_8 381L
+#undef com_phidgets_FrequencyCounterPhidget_PHIDID_TEXTLCD_ADAPTER
+#define com_phidgets_FrequencyCounterPhidget_PHIDID_TEXTLCD_ADAPTER 61L
+#undef com_phidgets_FrequencyCounterPhidget_PHIDID_UNIPOLAR_STEPPER_4MOTOR
+#define com_phidgets_FrequencyCounterPhidget_PHIDID_UNIPOLAR_STEPPER_4MOTOR 122L
+#undef com_phidgets_FrequencyCounterPhidget_PHIDID_ACCELEROMETER_2AXIS
+#define com_phidgets_FrequencyCounterPhidget_PHIDID_ACCELEROMETER_2AXIS 113L
+#undef com_phidgets_FrequencyCounterPhidget_PHIDID_INTERFACEKIT_0_8_8_w_LCD
+#define com_phidgets_FrequencyCounterPhidget_PHIDID_INTERFACEKIT_0_8_8_w_LCD 83L
+#undef com_phidgets_FrequencyCounterPhidget_PHIDID_INTERFACEKIT_4_8_8
+#define com_phidgets_FrequencyCounterPhidget_PHIDID_INTERFACEKIT_4_8_8 4L
+#undef com_phidgets_FrequencyCounterPhidget_PHIDID_RFID
+#define com_phidgets_FrequencyCounterPhidget_PHIDID_RFID 48L
+#undef com_phidgets_FrequencyCounterPhidget_PHIDID_SERVO_1MOTOR_OLD
+#define com_phidgets_FrequencyCounterPhidget_PHIDID_SERVO_1MOTOR_OLD 2L
+#undef com_phidgets_FrequencyCounterPhidget_PHIDID_SERVO_4MOTOR
+#define com_phidgets_FrequencyCounterPhidget_PHIDID_SERVO_4MOTOR 56L
+#undef com_phidgets_FrequencyCounterPhidget_PHIDID_SERVO_4MOTOR_OLD
+#define com_phidgets_FrequencyCounterPhidget_PHIDID_SERVO_4MOTOR_OLD 3L
+#undef com_phidgets_FrequencyCounterPhidget_PHIDID_TEXTLCD_2x20
+#define com_phidgets_FrequencyCounterPhidget_PHIDID_TEXTLCD_2x20 82L
+#undef com_phidgets_FrequencyCounterPhidget_PHIDID_TEXTLCD_2x20_w_0_8_8
+#define com_phidgets_FrequencyCounterPhidget_PHIDID_TEXTLCD_2x20_w_0_8_8 339L
+#undef com_phidgets_FrequencyCounterPhidget_PHIDID_TEXTLED_1x8
+#define com_phidgets_FrequencyCounterPhidget_PHIDID_TEXTLED_1x8 73L
+#undef com_phidgets_FrequencyCounterPhidget_PHIDID_TEXTLED_4x8
+#define com_phidgets_FrequencyCounterPhidget_PHIDID_TEXTLED_4x8 72L
+#undef com_phidgets_FrequencyCounterPhidget_PHIDID_WEIGHTSENSOR
+#define com_phidgets_FrequencyCounterPhidget_PHIDID_WEIGHTSENSOR 114L
+#undef com_phidgets_FrequencyCounterPhidget_PHIDCLASS_NOTHING
+#define com_phidgets_FrequencyCounterPhidget_PHIDCLASS_NOTHING 1L
+#undef com_phidgets_FrequencyCounterPhidget_PHIDCLASS_ACCELEROMETER
+#define com_phidgets_FrequencyCounterPhidget_PHIDCLASS_ACCELEROMETER 2L
+#undef com_phidgets_FrequencyCounterPhidget_PHIDCLASS_ADVANCEDSERVO
+#define com_phidgets_FrequencyCounterPhidget_PHIDCLASS_ADVANCEDSERVO 3L
+#undef com_phidgets_FrequencyCounterPhidget_PHIDCLASS_ANALOG
+#define com_phidgets_FrequencyCounterPhidget_PHIDCLASS_ANALOG 22L
+#undef com_phidgets_FrequencyCounterPhidget_PHIDCLASS_BRIDGE
+#define com_phidgets_FrequencyCounterPhidget_PHIDCLASS_BRIDGE 23L
+#undef com_phidgets_FrequencyCounterPhidget_PHIDCLASS_ENCODER
+#define com_phidgets_FrequencyCounterPhidget_PHIDCLASS_ENCODER 4L
+#undef com_phidgets_FrequencyCounterPhidget_PHIDCLASS_FREQUENCYCOUNTER
+#define com_phidgets_FrequencyCounterPhidget_PHIDCLASS_FREQUENCYCOUNTER 21L
+#undef com_phidgets_FrequencyCounterPhidget_PHIDCLASS_GPS
+#define com_phidgets_FrequencyCounterPhidget_PHIDCLASS_GPS 5L
+#undef com_phidgets_FrequencyCounterPhidget_PHIDCLASS_INTERFACEKIT
+#define com_phidgets_FrequencyCounterPhidget_PHIDCLASS_INTERFACEKIT 7L
+#undef com_phidgets_FrequencyCounterPhidget_PHIDCLASS_LED
+#define com_phidgets_FrequencyCounterPhidget_PHIDCLASS_LED 8L
+#undef com_phidgets_FrequencyCounterPhidget_PHIDCLASS_MOTORCONTROL
+#define com_phidgets_FrequencyCounterPhidget_PHIDCLASS_MOTORCONTROL 9L
+#undef com_phidgets_FrequencyCounterPhidget_PHIDCLASS_PHSENSOR
+#define com_phidgets_FrequencyCounterPhidget_PHIDCLASS_PHSENSOR 10L
+#undef com_phidgets_FrequencyCounterPhidget_PHIDCLASS_RFID
+#define com_phidgets_FrequencyCounterPhidget_PHIDCLASS_RFID 11L
+#undef com_phidgets_FrequencyCounterPhidget_PHIDCLASS_SERVO
+#define com_phidgets_FrequencyCounterPhidget_PHIDCLASS_SERVO 12L
+#undef com_phidgets_FrequencyCounterPhidget_PHIDCLASS_STEPPER
+#define com_phidgets_FrequencyCounterPhidget_PHIDCLASS_STEPPER 13L
+#undef com_phidgets_FrequencyCounterPhidget_PHIDCLASS_TEMPERATURESENSOR
+#define com_phidgets_FrequencyCounterPhidget_PHIDCLASS_TEMPERATURESENSOR 14L
+#undef com_phidgets_FrequencyCounterPhidget_PHIDCLASS_TEXTLCD
+#define com_phidgets_FrequencyCounterPhidget_PHIDCLASS_TEXTLCD 15L
+#undef com_phidgets_FrequencyCounterPhidget_PHIDCLASS_TEXTLED
+#define com_phidgets_FrequencyCounterPhidget_PHIDCLASS_TEXTLED 16L
+#undef com_phidgets_FrequencyCounterPhidget_PHIDCLASS_WEIGHTSENSOR
+#define com_phidgets_FrequencyCounterPhidget_PHIDCLASS_WEIGHTSENSOR 17L
+#undef com_phidgets_FrequencyCounterPhidget_PHIDGET_FREQUENCYCOUNTER_FILTERTYPE_ZERO_CROSSING
+#define com_phidgets_FrequencyCounterPhidget_PHIDGET_FREQUENCYCOUNTER_FILTERTYPE_ZERO_CROSSING 1L
+#undef com_phidgets_FrequencyCounterPhidget_PHIDGET_FREQUENCYCOUNTER_FILTERTYPE_LOGIC_LEVEL
+#define com_phidgets_FrequencyCounterPhidget_PHIDGET_FREQUENCYCOUNTER_FILTERTYPE_LOGIC_LEVEL 2L
+#undef com_phidgets_FrequencyCounterPhidget_PHIDGET_FREQUENCYCOUNTER_FILTERTYPE_UNKNOWN
+#define com_phidgets_FrequencyCounterPhidget_PHIDGET_FREQUENCYCOUNTER_FILTERTYPE_UNKNOWN 3L
+/*
+ * Class: com_phidgets_FrequencyCounterPhidget
+ * Method: create
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL Java_com_phidgets_FrequencyCounterPhidget_create
+ (JNIEnv *, jclass);
+
+/*
+ * Class: com_phidgets_FrequencyCounterPhidget
+ * Method: getFrequencyInputCount
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_phidgets_FrequencyCounterPhidget_getFrequencyInputCount
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_FrequencyCounterPhidget
+ * Method: getFrequency
+ * Signature: (I)D
+ */
+JNIEXPORT jdouble JNICALL Java_com_phidgets_FrequencyCounterPhidget_getFrequency
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_FrequencyCounterPhidget
+ * Method: getTotalCount
+ * Signature: (I)J
+ */
+JNIEXPORT jlong JNICALL Java_com_phidgets_FrequencyCounterPhidget_getTotalCount
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_FrequencyCounterPhidget
+ * Method: getTotalTime
+ * Signature: (I)J
+ */
+JNIEXPORT jlong JNICALL Java_com_phidgets_FrequencyCounterPhidget_getTotalTime
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_FrequencyCounterPhidget
+ * Method: getTimeout
+ * Signature: (I)I
+ */
+JNIEXPORT jint JNICALL Java_com_phidgets_FrequencyCounterPhidget_getTimeout
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_FrequencyCounterPhidget
+ * Method: setTimeout
+ * Signature: (II)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_FrequencyCounterPhidget_setTimeout
+ (JNIEnv *, jobject, jint, jint);
+
+/*
+ * Class: com_phidgets_FrequencyCounterPhidget
+ * Method: getEnabled
+ * Signature: (I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_phidgets_FrequencyCounterPhidget_getEnabled
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_FrequencyCounterPhidget
+ * Method: setEnabled
+ * Signature: (IZ)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_FrequencyCounterPhidget_setEnabled
+ (JNIEnv *, jobject, jint, jboolean);
+
+/*
+ * Class: com_phidgets_FrequencyCounterPhidget
+ * Method: getFilter
+ * Signature: (I)I
+ */
+JNIEXPORT jint JNICALL Java_com_phidgets_FrequencyCounterPhidget_getFilter
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_FrequencyCounterPhidget
+ * Method: setFilter
+ * Signature: (II)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_FrequencyCounterPhidget_setFilter
+ (JNIEnv *, jobject, jint, jint);
+
+/*
+ * Class: com_phidgets_FrequencyCounterPhidget
+ * Method: reset
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_FrequencyCounterPhidget_reset
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_FrequencyCounterPhidget
+ * Method: enableFrequencyCounterCountEvents
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_FrequencyCounterPhidget_enableFrequencyCounterCountEvents
+ (JNIEnv *, jobject, jboolean);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/Java/com_phidgets_GPSPhidget.c b/Java/com_phidgets_GPSPhidget.c
new file mode 100644
index 0000000..f2769d5
--- /dev/null
+++ b/Java/com_phidgets_GPSPhidget.c
@@ -0,0 +1,101 @@
+#include "../stdafx.h"
+#include "phidget_jni.h"
+#include "com_phidgets_GPSPhidget.h"
+#include "../cphidgetgps.h"
+
+static jclass irCode_class;
+static jmethodID irCode_getInstance;
+static jmethodID irCode_set;
+
+static jclass javaTimeZone_class; //class
+static jmethodID javaTimeZone_getTimeZone;
+
+EVENT_VARS(gpsPositionFixStatusChange, GPSPositionFixStatusChange)
+EVENT_VARS(gpsPositionChange, GPSPositionChange)
+
+JNI_LOAD(gps, GPS)
+
+ if (!(irCode_class = (*env)->FindClass(env,"java/util/Calendar")))
+ JNI_ABORT_STDERR("Couldn't FindClass java.util.Calendar");
+ if (!(irCode_class = (jclass)(*env)->NewGlobalRef(env, irCode_class)))
+ JNI_ABORT_STDERR("Couldn't create global ref irCode_class");
+ if (!(irCode_getInstance = (*env)->GetStaticMethodID(env, irCode_class, "getInstance", "(Ljava/util/TimeZone;)Ljava/util/Calendar;")))
+ JNI_ABORT_STDERR("Couldn't get method ID getInstance");
+ if (!(irCode_set = (*env)->GetMethodID(env, irCode_class, "set", "(II)V")))
+ JNI_ABORT_STDERR("Couldn't get method ID set");
+
+ if (!(javaTimeZone_class = (*env)->FindClass(env,"java/util/TimeZone")))
+ JNI_ABORT_STDERR("Couldn't FindClass java.util.TimeZone");
+ if (!(javaTimeZone_class = (jclass)(*env)->NewGlobalRef(env, javaTimeZone_class)))
+ JNI_ABORT_STDERR("Couldn't create global ref java.util.TimeZone");
+ if (!(javaTimeZone_getTimeZone = (*env)->GetStaticMethodID(env, javaTimeZone_class, "getTimeZone", "(Ljava/lang/String;)Ljava/util/TimeZone;")))
+ JNI_ABORT_STDERR("Couldn't get method ID from getTimeZone");
+
+ EVENT_VAR_SETUP(gps, gpsPositionFixStatusChange, GPSPositionFixStatusChange, Z, V)
+ EVENT_VAR_SETUP(gps, gpsPositionChange, GPSPositionChange, DDD, V)
+}
+
+EVENT_HANDLER(GPS, gpsPositionFixStatusChange, GPSPositionFixStatusChange, CPhidgetGPS_set_OnPositionFixStatusChange_Handler, int)
+EVENT_HANDLER_3(GPS, gpsPositionChange, GPSPositionChange, CPhidgetGPS_set_OnPositionChange_Handler, double, double, double)
+
+JNI_CREATE(GPS)
+
+JNI_GETFUNC(GPS, Latitude, Latitude, jdouble)
+JNI_GETFUNC(GPS, Longitude, Longitude, jdouble)
+JNI_GETFUNC(GPS, Altitude, Altitude, jdouble)
+JNI_GETFUNC(GPS, Heading, Heading, jdouble)
+JNI_GETFUNC(GPS, Velocity, Velocity, jdouble)
+JNI_GETFUNCBOOL(GPS, PositionFixStatus, PositionFixStatus)
+
+JNIEXPORT jobject JNICALL
+Java_com_phidgets_GPSPhidget_getDateAndTime(JNIEnv *env, jobject obj)
+{
+ CPhidgetGPSHandle h = (CPhidgetGPSHandle)(uintptr_t)(*env)->GetLongField( env, obj, handle_fid);
+ int error;
+ GPSTime cGPSTime;
+ GPSDate cGPSDate;
+ jobject GPSTimeAndDate, GPSTimeZone;
+
+ char* buf;
+
+ if ((error = CPhidgetGPS_getTime(h, &cGPSTime)))
+ {
+ PH_THROW(error);
+ return NULL;
+ }
+
+ if ((error = CPhidgetGPS_getDate(h, &cGPSDate)))
+ {
+ PH_THROW(error);
+ return NULL;
+ }
+
+ buf = "PST\0";
+ //create a Java abstract TimeZone object with a time zone of UTC
+ if(!(GPSTimeZone=(*env)->CallStaticObjectMethod(env, javaTimeZone_class, javaTimeZone_getTimeZone,
+ (*env)->NewStringUTF(env, buf)))){
+ PH_THROW(EPHIDGET_UNEXPECTED);
+ return NULL;
+ }
+
+ //calls the Java static method Calendar.getInstance object said TimeZone
+ if (!(GPSTimeAndDate = (*env)->CallStaticObjectMethod(env, irCode_class, irCode_getInstance, GPSTimeZone)))
+ {
+ PH_THROW(EPHIDGET_UNEXPECTED);
+ return NULL;
+ }
+
+ (*env)->CallVoidMethod(env, GPSTimeAndDate, irCode_set, 1, cGPSDate.tm_year); //year
+ (*env)->CallVoidMethod(env, GPSTimeAndDate, irCode_set, 2, (cGPSDate.tm_mon-1)); //month(0-11)
+ (*env)->CallVoidMethod(env, GPSTimeAndDate, irCode_set, 5, cGPSDate.tm_mday); //day(1-31)
+
+ (*env)->CallVoidMethod(env, GPSTimeAndDate, irCode_set, 11, (jint)cGPSTime.tm_hour); //hour(0-23)
+ (*env)->CallVoidMethod(env, GPSTimeAndDate, irCode_set, 12, cGPSTime.tm_min); //minute(0-59)
+ (*env)->CallVoidMethod(env, GPSTimeAndDate, irCode_set, 13, cGPSTime.tm_sec); //second(0-59)
+ (*env)->CallVoidMethod(env, GPSTimeAndDate, irCode_set, 14, cGPSTime.tm_ms); //milliseconds
+
+ return GPSTimeAndDate;
+}
+
+
+
diff --git a/Java/com_phidgets_GPSPhidget.h b/Java/com_phidgets_GPSPhidget.h
new file mode 100644
index 0000000..de6c01d
--- /dev/null
+++ b/Java/com_phidgets_GPSPhidget.h
@@ -0,0 +1,237 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class com_phidgets_GPSPhidget */
+
+#ifndef _Included_com_phidgets_GPSPhidget
+#define _Included_com_phidgets_GPSPhidget
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef com_phidgets_GPSPhidget_PHIDGET_LOG_CRITICAL
+#define com_phidgets_GPSPhidget_PHIDGET_LOG_CRITICAL 1L
+#undef com_phidgets_GPSPhidget_PHIDGET_LOG_ERROR
+#define com_phidgets_GPSPhidget_PHIDGET_LOG_ERROR 2L
+#undef com_phidgets_GPSPhidget_PHIDGET_LOG_WARNING
+#define com_phidgets_GPSPhidget_PHIDGET_LOG_WARNING 3L
+#undef com_phidgets_GPSPhidget_PHIDGET_LOG_DEBUG
+#define com_phidgets_GPSPhidget_PHIDGET_LOG_DEBUG 4L
+#undef com_phidgets_GPSPhidget_PHIDGET_LOG_INFO
+#define com_phidgets_GPSPhidget_PHIDGET_LOG_INFO 5L
+#undef com_phidgets_GPSPhidget_PHIDGET_LOG_VERBOSE
+#define com_phidgets_GPSPhidget_PHIDGET_LOG_VERBOSE 6L
+#undef com_phidgets_GPSPhidget_PHIDID_NOTHING
+#define com_phidgets_GPSPhidget_PHIDID_NOTHING 1L
+#undef com_phidgets_GPSPhidget_PHIDID_ACCELEROMETER_3AXIS
+#define com_phidgets_GPSPhidget_PHIDID_ACCELEROMETER_3AXIS 126L
+#undef com_phidgets_GPSPhidget_PHIDID_ADVANCEDSERVO_1MOTOR
+#define com_phidgets_GPSPhidget_PHIDID_ADVANCEDSERVO_1MOTOR 130L
+#undef com_phidgets_GPSPhidget_PHIDID_ANALOG_4OUTPUT
+#define com_phidgets_GPSPhidget_PHIDID_ANALOG_4OUTPUT 55L
+#undef com_phidgets_GPSPhidget_PHIDID_ADVANCEDSERVO_8MOTOR
+#define com_phidgets_GPSPhidget_PHIDID_ADVANCEDSERVO_8MOTOR 58L
+#undef com_phidgets_GPSPhidget_PHIDID_BIPOLAR_STEPPER_1MOTOR
+#define com_phidgets_GPSPhidget_PHIDID_BIPOLAR_STEPPER_1MOTOR 123L
+#undef com_phidgets_GPSPhidget_PHIDID_BRIDGE_4INPUT
+#define com_phidgets_GPSPhidget_PHIDID_BRIDGE_4INPUT 59L
+#undef com_phidgets_GPSPhidget_PHIDID_ENCODER_1ENCODER_1INPUT
+#define com_phidgets_GPSPhidget_PHIDID_ENCODER_1ENCODER_1INPUT 75L
+#undef com_phidgets_GPSPhidget_PHIDID_ENCODER_HS_1ENCODER
+#define com_phidgets_GPSPhidget_PHIDID_ENCODER_HS_1ENCODER 128L
+#undef com_phidgets_GPSPhidget_PHIDID_ENCODER_HS_4ENCODER_4INPUT
+#define com_phidgets_GPSPhidget_PHIDID_ENCODER_HS_4ENCODER_4INPUT 79L
+#undef com_phidgets_GPSPhidget_PHIDID_FREQUENCYCOUNTER_2INPUT
+#define com_phidgets_GPSPhidget_PHIDID_FREQUENCYCOUNTER_2INPUT 53L
+#undef com_phidgets_GPSPhidget_PHIDID_GPS
+#define com_phidgets_GPSPhidget_PHIDID_GPS 121L
+#undef com_phidgets_GPSPhidget_PHIDID_INTERFACEKIT_0_0_4
+#define com_phidgets_GPSPhidget_PHIDID_INTERFACEKIT_0_0_4 64L
+#undef com_phidgets_GPSPhidget_PHIDID_INTERFACEKIT_0_0_8
+#define com_phidgets_GPSPhidget_PHIDID_INTERFACEKIT_0_0_8 129L
+#undef com_phidgets_GPSPhidget_PHIDID_INTERFACEKIT_0_16_16
+#define com_phidgets_GPSPhidget_PHIDID_INTERFACEKIT_0_16_16 68L
+#undef com_phidgets_GPSPhidget_PHIDID_INTERFACEKIT_8_8_8
+#define com_phidgets_GPSPhidget_PHIDID_INTERFACEKIT_8_8_8 69L
+#undef com_phidgets_GPSPhidget_PHIDID_INTERFACEKIT_8_8_8_w_LCD
+#define com_phidgets_GPSPhidget_PHIDID_INTERFACEKIT_8_8_8_w_LCD 125L
+#undef com_phidgets_GPSPhidget_PHIDID_IR
+#define com_phidgets_GPSPhidget_PHIDID_IR 77L
+#undef com_phidgets_GPSPhidget_PHIDID_LED_64
+#define com_phidgets_GPSPhidget_PHIDID_LED_64 74L
+#undef com_phidgets_GPSPhidget_PHIDID_LED_64_ADV
+#define com_phidgets_GPSPhidget_PHIDID_LED_64_ADV 76L
+#undef com_phidgets_GPSPhidget_PHIDID_LINEAR_TOUCH
+#define com_phidgets_GPSPhidget_PHIDID_LINEAR_TOUCH 118L
+#undef com_phidgets_GPSPhidget_PHIDID_MOTORCONTROL_HC_2MOTOR
+#define com_phidgets_GPSPhidget_PHIDID_MOTORCONTROL_HC_2MOTOR 89L
+#undef com_phidgets_GPSPhidget_PHIDID_MOTORCONTROL_LV_2MOTOR_4INPUT
+#define com_phidgets_GPSPhidget_PHIDID_MOTORCONTROL_LV_2MOTOR_4INPUT 88L
+#undef com_phidgets_GPSPhidget_PHIDID_MOTORCONTROL_1MOTOR
+#define com_phidgets_GPSPhidget_PHIDID_MOTORCONTROL_1MOTOR 62L
+#undef com_phidgets_GPSPhidget_PHIDID_PHSENSOR
+#define com_phidgets_GPSPhidget_PHIDID_PHSENSOR 116L
+#undef com_phidgets_GPSPhidget_PHIDID_RFID_2OUTPUT
+#define com_phidgets_GPSPhidget_PHIDID_RFID_2OUTPUT 49L
+#undef com_phidgets_GPSPhidget_PHIDID_ROTARY_TOUCH
+#define com_phidgets_GPSPhidget_PHIDID_ROTARY_TOUCH 119L
+#undef com_phidgets_GPSPhidget_PHIDID_SERVO_1MOTOR
+#define com_phidgets_GPSPhidget_PHIDID_SERVO_1MOTOR 57L
+#undef com_phidgets_GPSPhidget_PHIDID_SPATIAL_ACCEL_3AXIS
+#define com_phidgets_GPSPhidget_PHIDID_SPATIAL_ACCEL_3AXIS 127L
+#undef com_phidgets_GPSPhidget_PHIDID_SPATIAL_ACCEL_GYRO_COMPASS
+#define com_phidgets_GPSPhidget_PHIDID_SPATIAL_ACCEL_GYRO_COMPASS 51L
+#undef com_phidgets_GPSPhidget_PHIDID_TEMPERATURESENSOR
+#define com_phidgets_GPSPhidget_PHIDID_TEMPERATURESENSOR 112L
+#undef com_phidgets_GPSPhidget_PHIDID_TEMPERATURESENSOR_4
+#define com_phidgets_GPSPhidget_PHIDID_TEMPERATURESENSOR_4 50L
+#undef com_phidgets_GPSPhidget_PHIDID_TEXTLCD_2x20_w_8_8_8
+#define com_phidgets_GPSPhidget_PHIDID_TEXTLCD_2x20_w_8_8_8 381L
+#undef com_phidgets_GPSPhidget_PHIDID_TEXTLCD_ADAPTER
+#define com_phidgets_GPSPhidget_PHIDID_TEXTLCD_ADAPTER 61L
+#undef com_phidgets_GPSPhidget_PHIDID_UNIPOLAR_STEPPER_4MOTOR
+#define com_phidgets_GPSPhidget_PHIDID_UNIPOLAR_STEPPER_4MOTOR 122L
+#undef com_phidgets_GPSPhidget_PHIDID_ACCELEROMETER_2AXIS
+#define com_phidgets_GPSPhidget_PHIDID_ACCELEROMETER_2AXIS 113L
+#undef com_phidgets_GPSPhidget_PHIDID_INTERFACEKIT_0_8_8_w_LCD
+#define com_phidgets_GPSPhidget_PHIDID_INTERFACEKIT_0_8_8_w_LCD 83L
+#undef com_phidgets_GPSPhidget_PHIDID_INTERFACEKIT_4_8_8
+#define com_phidgets_GPSPhidget_PHIDID_INTERFACEKIT_4_8_8 4L
+#undef com_phidgets_GPSPhidget_PHIDID_RFID
+#define com_phidgets_GPSPhidget_PHIDID_RFID 48L
+#undef com_phidgets_GPSPhidget_PHIDID_SERVO_1MOTOR_OLD
+#define com_phidgets_GPSPhidget_PHIDID_SERVO_1MOTOR_OLD 2L
+#undef com_phidgets_GPSPhidget_PHIDID_SERVO_4MOTOR
+#define com_phidgets_GPSPhidget_PHIDID_SERVO_4MOTOR 56L
+#undef com_phidgets_GPSPhidget_PHIDID_SERVO_4MOTOR_OLD
+#define com_phidgets_GPSPhidget_PHIDID_SERVO_4MOTOR_OLD 3L
+#undef com_phidgets_GPSPhidget_PHIDID_TEXTLCD_2x20
+#define com_phidgets_GPSPhidget_PHIDID_TEXTLCD_2x20 82L
+#undef com_phidgets_GPSPhidget_PHIDID_TEXTLCD_2x20_w_0_8_8
+#define com_phidgets_GPSPhidget_PHIDID_TEXTLCD_2x20_w_0_8_8 339L
+#undef com_phidgets_GPSPhidget_PHIDID_TEXTLED_1x8
+#define com_phidgets_GPSPhidget_PHIDID_TEXTLED_1x8 73L
+#undef com_phidgets_GPSPhidget_PHIDID_TEXTLED_4x8
+#define com_phidgets_GPSPhidget_PHIDID_TEXTLED_4x8 72L
+#undef com_phidgets_GPSPhidget_PHIDID_WEIGHTSENSOR
+#define com_phidgets_GPSPhidget_PHIDID_WEIGHTSENSOR 114L
+#undef com_phidgets_GPSPhidget_PHIDCLASS_NOTHING
+#define com_phidgets_GPSPhidget_PHIDCLASS_NOTHING 1L
+#undef com_phidgets_GPSPhidget_PHIDCLASS_ACCELEROMETER
+#define com_phidgets_GPSPhidget_PHIDCLASS_ACCELEROMETER 2L
+#undef com_phidgets_GPSPhidget_PHIDCLASS_ADVANCEDSERVO
+#define com_phidgets_GPSPhidget_PHIDCLASS_ADVANCEDSERVO 3L
+#undef com_phidgets_GPSPhidget_PHIDCLASS_ANALOG
+#define com_phidgets_GPSPhidget_PHIDCLASS_ANALOG 22L
+#undef com_phidgets_GPSPhidget_PHIDCLASS_BRIDGE
+#define com_phidgets_GPSPhidget_PHIDCLASS_BRIDGE 23L
+#undef com_phidgets_GPSPhidget_PHIDCLASS_ENCODER
+#define com_phidgets_GPSPhidget_PHIDCLASS_ENCODER 4L
+#undef com_phidgets_GPSPhidget_PHIDCLASS_FREQUENCYCOUNTER
+#define com_phidgets_GPSPhidget_PHIDCLASS_FREQUENCYCOUNTER 21L
+#undef com_phidgets_GPSPhidget_PHIDCLASS_GPS
+#define com_phidgets_GPSPhidget_PHIDCLASS_GPS 5L
+#undef com_phidgets_GPSPhidget_PHIDCLASS_INTERFACEKIT
+#define com_phidgets_GPSPhidget_PHIDCLASS_INTERFACEKIT 7L
+#undef com_phidgets_GPSPhidget_PHIDCLASS_LED
+#define com_phidgets_GPSPhidget_PHIDCLASS_LED 8L
+#undef com_phidgets_GPSPhidget_PHIDCLASS_MOTORCONTROL
+#define com_phidgets_GPSPhidget_PHIDCLASS_MOTORCONTROL 9L
+#undef com_phidgets_GPSPhidget_PHIDCLASS_PHSENSOR
+#define com_phidgets_GPSPhidget_PHIDCLASS_PHSENSOR 10L
+#undef com_phidgets_GPSPhidget_PHIDCLASS_RFID
+#define com_phidgets_GPSPhidget_PHIDCLASS_RFID 11L
+#undef com_phidgets_GPSPhidget_PHIDCLASS_SERVO
+#define com_phidgets_GPSPhidget_PHIDCLASS_SERVO 12L
+#undef com_phidgets_GPSPhidget_PHIDCLASS_STEPPER
+#define com_phidgets_GPSPhidget_PHIDCLASS_STEPPER 13L
+#undef com_phidgets_GPSPhidget_PHIDCLASS_TEMPERATURESENSOR
+#define com_phidgets_GPSPhidget_PHIDCLASS_TEMPERATURESENSOR 14L
+#undef com_phidgets_GPSPhidget_PHIDCLASS_TEXTLCD
+#define com_phidgets_GPSPhidget_PHIDCLASS_TEXTLCD 15L
+#undef com_phidgets_GPSPhidget_PHIDCLASS_TEXTLED
+#define com_phidgets_GPSPhidget_PHIDCLASS_TEXTLED 16L
+#undef com_phidgets_GPSPhidget_PHIDCLASS_WEIGHTSENSOR
+#define com_phidgets_GPSPhidget_PHIDCLASS_WEIGHTSENSOR 17L
+/*
+ * Class: com_phidgets_GPSPhidget
+ * Method: create
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL Java_com_phidgets_GPSPhidget_create
+ (JNIEnv *, jclass);
+
+/*
+ * Class: com_phidgets_GPSPhidget
+ * Method: getLatitude
+ * Signature: ()D
+ */
+JNIEXPORT jdouble JNICALL Java_com_phidgets_GPSPhidget_getLatitude
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_GPSPhidget
+ * Method: getLongitude
+ * Signature: ()D
+ */
+JNIEXPORT jdouble JNICALL Java_com_phidgets_GPSPhidget_getLongitude
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_GPSPhidget
+ * Method: getAltitude
+ * Signature: ()D
+ */
+JNIEXPORT jdouble JNICALL Java_com_phidgets_GPSPhidget_getAltitude
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_GPSPhidget
+ * Method: getHeading
+ * Signature: ()D
+ */
+JNIEXPORT jdouble JNICALL Java_com_phidgets_GPSPhidget_getHeading
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_GPSPhidget
+ * Method: getVelocity
+ * Signature: ()D
+ */
+JNIEXPORT jdouble JNICALL Java_com_phidgets_GPSPhidget_getVelocity
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_GPSPhidget
+ * Method: getDateAndTime
+ * Signature: ()Ljava/util/Calendar;
+ */
+JNIEXPORT jobject JNICALL Java_com_phidgets_GPSPhidget_getDateAndTime
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_GPSPhidget
+ * Method: getPositionFixStatus
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_phidgets_GPSPhidget_getPositionFixStatus
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_GPSPhidget
+ * Method: enableGPSPositionFixStatusChangeEvents
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_GPSPhidget_enableGPSPositionFixStatusChangeEvents
+ (JNIEnv *, jobject, jboolean);
+
+/*
+ * Class: com_phidgets_GPSPhidget
+ * Method: enableGPSPositionChangeEvents
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_GPSPhidget_enableGPSPositionChangeEvents
+ (JNIEnv *, jobject, jboolean);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/Java/com_phidgets_IRPhidget.c b/Java/com_phidgets_IRPhidget.c
new file mode 100644
index 0000000..e2cfb45
--- /dev/null
+++ b/Java/com_phidgets_IRPhidget.c
@@ -0,0 +1,777 @@
+#include "../stdafx.h"
+#include "phidget_jni.h"
+#include "com_phidgets_IRPhidget.h"
+#include "../cphidgetir.h"
+
+EVENT_VARS(code, Code)
+EVENT_VARS(learn, Learn)
+EVENT_VARS(rawData, RawData)
+
+static jclass irCode_class; //class
+static jmethodID irCode_cons; //constructor
+static jmethodID irCode_getData;
+static jclass irCodeInfo_class; //class
+static jmethodID irCodeInfo_cons; //constructor
+static jmethodID irCodeInfo_getEncoding;
+static jmethodID irCodeInfo_getLength;
+static jmethodID irCodeInfo_getBitCount;
+static jmethodID irCodeInfo_getGap;
+static jmethodID irCodeInfo_getTrail;
+static jmethodID irCodeInfo_getMinRepeat;
+static jmethodID irCodeInfo_getCarrierFrequency;
+static jmethodID irCodeInfo_getDutyCycle;
+static jmethodID irCodeInfo_getHeader;
+static jmethodID irCodeInfo_getZero;
+static jmethodID irCodeInfo_getOne;
+static jmethodID irCodeInfo_getRepeat;
+static jmethodID irCodeInfo_getToggleMask;
+static jclass irLearn_class; //class
+static jmethodID irLearn_cons; //constructor
+
+JNI_LOAD(ir, IR)
+ EVENT_VAR_SETUP(ir, learn, Learn, Lcom/phidgets/IRLearnedCode;, V)
+ EVENT_VAR_SETUP(ir, rawData, RawData, [I, V)
+ EVENT_VAR_SETUP(ir, code, Code, Lcom/phidgets/IRCode;Z, V)
+
+ if (!(irCode_class = (*env)->FindClass(env,"com/phidgets/IRCode")))
+ JNI_ABORT_STDERR("Couldn't FindClass com/phidgets/IRCode");
+ if (!(irCode_class = (jclass)(*env)->NewGlobalRef(env, irCode_class)))
+ JNI_ABORT_STDERR("Couldn't create global ref irCode_class");
+ if (!(irCode_cons = (*env)->GetMethodID(env, irCode_class, "<init>", "([SI)V")))
+ JNI_ABORT_STDERR("Couldn't get method ID <init> from irCode_class");
+
+ if (!(irCode_getData = (*env)->GetMethodID(env, irCode_class, "getData", "()[S")))
+ JNI_ABORT_STDERR("Couldn't get method ID getData from irCode_class");
+
+ if (!(irCodeInfo_class = (*env)->FindClass(env,"com/phidgets/IRCodeInfo")))
+ JNI_ABORT_STDERR("Couldn't FindClass com/phidgets/IRCodeInfo");
+ if (!(irCodeInfo_class = (jclass)(*env)->NewGlobalRef(env, irCodeInfo_class)))
+ JNI_ABORT_STDERR("Couldn't create global ref irCodeInfo_class");
+ if (!(irCodeInfo_cons = (*env)->GetMethodID(env, irCodeInfo_class, "<init>", "(II[I[I[III[IILcom/phidgets/IRCode;III)V")))
+ JNI_ABORT_STDERR("Couldn't get method ID <init> from irCodeInfo_class");
+
+ if (!(irCodeInfo_getEncoding = (*env)->GetMethodID(env, irCodeInfo_class, "getEncoding", "()I")))
+ JNI_ABORT_STDERR("Couldn't get method ID getEncoding from irCodeInfo_class");
+ if (!(irCodeInfo_getLength = (*env)->GetMethodID(env, irCodeInfo_class, "getLength", "()I")))
+ JNI_ABORT_STDERR("Couldn't get method ID getLength from irCodeInfo_class");
+ if (!(irCodeInfo_getBitCount = (*env)->GetMethodID(env, irCodeInfo_class, "getBitCount", "()I")))
+ JNI_ABORT_STDERR("Couldn't get method ID getBitCount from irCodeInfo_class");
+ if (!(irCodeInfo_getGap = (*env)->GetMethodID(env, irCodeInfo_class, "getGap", "()I")))
+ JNI_ABORT_STDERR("Couldn't get method ID getGap from irCodeInfo_class");
+ if (!(irCodeInfo_getTrail = (*env)->GetMethodID(env, irCodeInfo_class, "getTrail", "()I")))
+ JNI_ABORT_STDERR("Couldn't get method ID getTrail from irCodeInfo_class");
+ if (!(irCodeInfo_getMinRepeat = (*env)->GetMethodID(env, irCodeInfo_class, "getMinRepeat", "()I")))
+ JNI_ABORT_STDERR("Couldn't get method ID getMinRepeat from irCodeInfo_class");
+ if (!(irCodeInfo_getCarrierFrequency = (*env)->GetMethodID(env, irCodeInfo_class, "getCarrierFrequency", "()I")))
+ JNI_ABORT_STDERR("Couldn't get method ID getCarrierFrequency from irCodeInfo_class");
+ if (!(irCodeInfo_getDutyCycle = (*env)->GetMethodID(env, irCodeInfo_class, "getDutyCycle", "()I")))
+ JNI_ABORT_STDERR("Couldn't get method ID getDutyCycle from irCodeInfo_class");
+ if (!(irCodeInfo_getHeader = (*env)->GetMethodID(env, irCodeInfo_class, "getHeader", "()[I")))
+ JNI_ABORT_STDERR("Couldn't get method ID getHeader from irCodeInfo_class");
+ if (!(irCodeInfo_getZero = (*env)->GetMethodID(env, irCodeInfo_class, "getZero", "()[I")))
+ JNI_ABORT_STDERR("Couldn't get method ID getZero from irCodeInfo_class");
+ if (!(irCodeInfo_getOne = (*env)->GetMethodID(env, irCodeInfo_class, "getOne", "()[I")))
+ JNI_ABORT_STDERR("Couldn't get method ID getOne from irCodeInfo_class");
+ if (!(irCodeInfo_getRepeat = (*env)->GetMethodID(env, irCodeInfo_class, "getRepeat", "()[I")))
+ JNI_ABORT_STDERR("Couldn't get method ID getRepeat from irCodeInfo_class");
+ if (!(irCodeInfo_getToggleMask = (*env)->GetMethodID(env, irCodeInfo_class, "getToggleMask", "()Lcom/phidgets/IRCode;")))
+ JNI_ABORT_STDERR("Couldn't get method ID getToggleMask from irCodeInfo_class");
+
+ if (!(irLearn_class = (*env)->FindClass(env,"com/phidgets/IRLearnedCode")))
+ JNI_ABORT_STDERR("Couldn't FindClass com/phidgets/IRLearnedCode");
+ if (!(irLearn_class = (jclass)(*env)->NewGlobalRef(env, irLearn_class)))
+ JNI_ABORT_STDERR("Couldn't create global ref irLearn_class");
+ if (!(irLearn_cons = (*env)->GetMethodID(env, irLearn_class, "<init>", "(Lcom/phidgets/IRCode;Lcom/phidgets/IRCodeInfo;)V")))
+ JNI_ABORT_STDERR("Couldn't get method ID <init> from irLearn_class");
+}
+
+//Code event
+static int CCONV code_handler(CPhidgetIRHandle h, void *arg, unsigned char *data, int dataLength, int bitCount, int repeat);
+JNIEXPORT void JNICALL
+Java_com_phidgets_IRPhidget_enableCodeEvents(JNIEnv *env, jobject obj, jboolean b)
+{
+ jlong gr = updateGlobalRef(env, obj, nativeCodeHandler_fid, b);
+ CPhidgetIRHandle h = (CPhidgetIRHandle)(uintptr_t)(*env)->GetLongField(env, obj, handle_fid);
+ CPhidgetIR_set_OnCode_Handler(h, b ? code_handler : 0, (void *)(uintptr_t)gr);
+}
+static int CCONV
+code_handler(CPhidgetIRHandle h, void *arg, unsigned char *data, int dataLength, int bitCount, int repeat)
+{
+ JNIEnv *env;
+ jobject obj;
+ jobject codeEv;
+ jobject ircode;
+ jshortArray js;
+ jshort *datas;
+ int i;
+
+ if ((*ph_vm)->AttachCurrentThread(ph_vm, (JNIEnvPtr)&env, NULL))
+ JNI_ABORT_STDERR("Couldn't AttachCurrentThread");
+
+ obj = (jobject)arg;
+
+ //create and fill in short array
+ js = (*env)->NewShortArray(env, dataLength);
+ if (!js)
+ return -1;
+ datas = (*env)->GetShortArrayElements(env, js, 0);
+ if (!datas)
+ return -1;
+ for (i=0; i<dataLength; i++)
+ datas[i] = (jshort)data[i];
+ (*env)->ReleaseShortArrayElements(env, js, datas, 0);
+
+ if (!(ircode = (*env)->NewObject(env, irCode_class, irCode_cons, js, bitCount)))
+ {
+ return -1;
+ }
+
+ if (!(codeEv = (*env)->NewObject(env, codeEvent_class,
+ codeEvent_cons, obj, ircode, repeat)))
+ {
+ (*env)->DeleteLocalRef(env, ircode);
+ return -1;
+ }
+
+ (*env)->CallVoidMethod(env, obj, fireCode_mid, codeEv);
+
+ (*env)->DeleteLocalRef(env, codeEv);
+ (*env)->DeleteLocalRef(env, ircode);
+
+ (*ph_vm)->DetachCurrentThread(ph_vm);
+
+ return 0;
+
+}
+
+//Learn event
+static int CCONV learn_handler(CPhidgetIRHandle h, void *arg, unsigned char *data, int dataLength, CPhidgetIR_CodeInfoHandle codeInfo);
+JNIEXPORT void JNICALL
+Java_com_phidgets_IRPhidget_enableLearnEvents(JNIEnv *env, jobject obj, jboolean b)
+{
+ jlong gr = updateGlobalRef(env, obj, nativeLearnHandler_fid, b);
+ CPhidgetIRHandle h = (CPhidgetIRHandle)(uintptr_t)(*env)->GetLongField(env, obj, handle_fid);
+ CPhidgetIR_set_OnLearn_Handler(h, b ? learn_handler : 0, (void *)(uintptr_t)gr);
+}
+static int CCONV
+learn_handler(CPhidgetIRHandle h, void *arg, unsigned char *data, int dataLength, CPhidgetIR_CodeInfoHandle codeInfo)
+{
+ JNIEnv *env;
+ jobject obj;
+ jobject learnEv;
+ jobject ircode, ircodeinfo, irlearn, togglemask;
+ jshortArray codeData;
+ jintArray headerArray, zeroArray, oneArray, repeatArray;
+ jshort *datas;
+ jint *datai;
+ int i,j;
+
+ if ((*ph_vm)->AttachCurrentThread(ph_vm, (JNIEnvPtr)&env, NULL))
+ JNI_ABORT_STDERR("Couldn't AttachCurrentThread");
+
+ obj = (jobject)arg;
+
+ //create and fill in short array
+ if(dataLength > 0){
+ codeData = (*env)->NewShortArray(env, dataLength);
+ if (!codeData)
+ return -1;
+ datas = (*env)->GetShortArrayElements(env, codeData, 0);
+ if (!datas)
+ return -1;
+ for (i=0; i<dataLength; i++)
+ datas[i] = (jshort)data[i];
+ (*env)->ReleaseShortArrayElements(env, codeData, datas, 0);
+ }
+ else
+ codeData=NULL;
+ //create IRCode object
+ if (!(ircode = (*env)->NewObject(env, irCode_class, irCode_cons, codeData, codeInfo->bitCount)))
+ {
+ return -1;
+ }
+
+ //Header
+ if(codeInfo->header[0])
+ {
+ headerArray = (*env)->NewIntArray(env, 2);
+ if (!headerArray)
+ return -1;
+ datai = (*env)->GetIntArrayElements(env, headerArray, 0);
+ if (!datai)
+ return -1;
+ for (i=0; i<2; i++)
+ datai[i] = (jint)codeInfo->header[i];
+ (*env)->ReleaseIntArrayElements(env, headerArray, datai, 0);
+ }
+ else
+ headerArray=NULL;
+
+ //Zero
+ zeroArray = (*env)->NewIntArray(env, 2);
+ if (!zeroArray)
+ return -1;
+ datai = (*env)->GetIntArrayElements(env, zeroArray, 0);
+ if (!datai)
+ return -1;
+ for (i=0; i<2; i++)
+ datai[i] = (jint)codeInfo->zero[i];
+ (*env)->ReleaseIntArrayElements(env, zeroArray, datai, 0);
+
+ //One
+ oneArray = (*env)->NewIntArray(env, 2);
+ if (!oneArray)
+ return -1;
+ datai = (*env)->GetIntArrayElements(env, oneArray, 0);
+ if (!datai)
+ return -1;
+ for (i=0; i<2; i++)
+ datai[i] = (jint)codeInfo->one[i];
+ (*env)->ReleaseIntArrayElements(env, oneArray, datai, 0);
+
+ //Repeat
+ i=0;
+ while(codeInfo->repeat[i])
+ i++;
+ if(i)
+ {
+ repeatArray = (*env)->NewIntArray(env, i);
+ if (!repeatArray)
+ return -1;
+ datai = (*env)->GetIntArrayElements(env, repeatArray, 0);
+ if (!datai)
+ return -1;
+ for (j=0; j<i; j++)
+ datai[j] = (jint)codeInfo->repeat[j];
+ (*env)->ReleaseIntArrayElements(env, repeatArray, datai, 0);
+ }
+ else{
+ repeatArray = NULL;
+ }
+
+ //ToggleMask
+ if(dataLength > 0){
+ codeData = (*env)->NewShortArray(env, dataLength);
+ if (!codeData)
+ return -1;
+ datas = (*env)->GetShortArrayElements(env, codeData, 0);
+ if (!datas)
+ return -1;
+ for (i=0; i<dataLength; i++)
+ datas[i] = (jshort)codeInfo->toggle_mask[i];
+ (*env)->ReleaseShortArrayElements(env, codeData, datas, 0);
+ if (!(togglemask = (*env)->NewObject(env, irCode_class, irCode_cons, codeData, codeInfo->bitCount)))
+ {
+ return -1;
+ }
+ }
+ else{
+ codeData=NULL;
+ }
+ //create IRCodeInfo object
+ if (!(ircodeinfo = (*env)->NewObject(env, irCodeInfo_class, irCodeInfo_cons,
+ codeInfo->encoding, codeInfo->bitCount, headerArray, zeroArray, oneArray,
+ codeInfo->trail, codeInfo->gap, repeatArray, codeInfo->min_repeat, togglemask,
+ codeInfo->length, codeInfo->carrierFrequency, codeInfo->dutyCycle)))
+ {
+ (*env)->DeleteLocalRef(env, ircode);
+ return -1;
+ }
+
+ //create IRLearn object
+ if (!(irlearn = (*env)->NewObject(env, irLearn_class, irLearn_cons, ircode, ircodeinfo)))
+ {
+ (*env)->DeleteLocalRef(env, ircode);
+ (*env)->DeleteLocalRef(env, ircodeinfo);
+ return -1;
+ }
+
+ if (!(learnEv = (*env)->NewObject(env, learnEvent_class,
+ learnEvent_cons, obj, irlearn)))
+ {
+ (*env)->DeleteLocalRef(env, ircode);
+ (*env)->DeleteLocalRef(env, ircodeinfo);
+ (*env)->DeleteLocalRef(env, irlearn);
+ return -1;
+ }
+
+ (*env)->CallVoidMethod(env, obj, fireLearn_mid, learnEv);
+
+ (*env)->DeleteLocalRef(env, learnEv);
+ (*env)->DeleteLocalRef(env, ircode);
+ (*env)->DeleteLocalRef(env, ircodeinfo);
+ (*env)->DeleteLocalRef(env, irlearn);
+
+ (*ph_vm)->DetachCurrentThread(ph_vm);
+
+ return 0;
+}
+
+//RawData event
+static int CCONV rawData_handler(CPhidgetIRHandle h, void *arg, int *data, int dataLength);
+JNIEXPORT void JNICALL
+Java_com_phidgets_IRPhidget_enableRawDataEvents(JNIEnv *env, jobject obj, jboolean b)
+{
+ jlong gr = updateGlobalRef(env, obj, nativeRawDataHandler_fid, b);
+ CPhidgetIRHandle h = (CPhidgetIRHandle)(uintptr_t)(*env)->GetLongField(env, obj, handle_fid);
+ CPhidgetIR_set_OnRawData_Handler(h, b ? rawData_handler : 0, (void *)(uintptr_t)gr);
+}
+static int CCONV
+rawData_handler(CPhidgetIRHandle h, void *arg, int *data, int dataLength)
+{
+ JNIEnv *env;
+ jobject obj;
+ jobject rawDataEv;
+ jintArray js;
+ jint *datas;
+ int i;
+
+ if ((*ph_vm)->AttachCurrentThread(ph_vm, (JNIEnvPtr)&env, NULL))
+ JNI_ABORT_STDERR("Couldn't AttachCurrentThread");
+
+ obj = (jobject)arg;
+
+ //create and fill in int array
+ js = (*env)->NewIntArray(env, dataLength);
+ if (!js)
+ return -1;
+ datas = (*env)->GetIntArrayElements(env, js, 0);
+ if (!datas)
+ return -1;
+ for (i=0; i<dataLength; i++)
+ datas[i] = (jint)data[i];
+ (*env)->ReleaseIntArrayElements(env, js, datas, 0);
+
+ if (!(rawDataEv = (*env)->NewObject(env, rawDataEvent_class, rawDataEvent_cons, obj, js)))
+ return -1;
+
+ (*env)->CallVoidMethod(env, obj, fireRawData_mid, rawDataEv);
+
+ (*env)->DeleteLocalRef(env, rawDataEv);
+
+ (*ph_vm)->DetachCurrentThread(ph_vm);
+
+ return 0;
+}
+
+JNI_CREATE(IR)
+
+JNIEXPORT jobject JNICALL
+Java_com_phidgets_IRPhidget_getLastCode(JNIEnv *env, jobject obj)
+{
+ CPhidgetIRHandle h = (CPhidgetIRHandle)(uintptr_t)(*env)->GetLongField( env, obj, handle_fid);
+ int error;
+ unsigned char data[IR_MAX_CODE_DATA_LENGTH];
+ int dataLength=IR_MAX_CODE_DATA_LENGTH, bitCount, i;
+ jobject ircode;
+ jshortArray js;
+ jshort *datas;
+
+ if ((error = CPhidgetIR_getLastCode(h, data, &dataLength, &bitCount)))
+ {
+ PH_THROW(error);
+ return NULL;
+ }
+
+ //create and fill in short array
+ js = (*env)->NewShortArray(env, dataLength);
+ if (!js)
+ {
+ PH_THROW(EPHIDGET_UNEXPECTED);
+ return NULL;
+ }
+ datas = (*env)->GetShortArrayElements(env, js, 0);
+ if (!datas)
+ {
+ PH_THROW(EPHIDGET_UNEXPECTED);
+ return NULL;
+ }
+ for (i=0; i<dataLength; i++)
+ datas[i] = (jshort)data[i];
+ (*env)->ReleaseShortArrayElements(env, js, datas, 0);
+
+ //create and return IRCode object
+ if (!(ircode = (*env)->NewObject(env, irCode_class, irCode_cons, js, bitCount)))
+ {
+ PH_THROW(EPHIDGET_UNEXPECTED);
+ return NULL;
+ }
+
+ return ircode;
+}
+
+JNIEXPORT jint JNICALL
+Java_com_phidgets_IRPhidget_readRaw(JNIEnv *env, jobject obj, jintArray intArray, jint offset, jint count)
+{
+ CPhidgetIRHandle h = (CPhidgetIRHandle)(uintptr_t)(*env)->GetLongField( env, obj, handle_fid);
+ int error, dataLength = count;
+ jint *datai;
+
+ //create and fill in int array
+ datai = (*env)->GetIntArrayElements(env, intArray, 0);
+ if (!datai)
+ {
+ PH_THROW(EPHIDGET_UNEXPECTED);
+ return -1;
+ }
+ if ((error = CPhidgetIR_getRawData(h, datai, &dataLength)))
+ {
+ (*env)->ReleaseIntArrayElements(env, intArray, datai, 0);
+ PH_THROW(error);
+ return -1;
+ }
+ (*env)->ReleaseIntArrayElements(env, intArray, datai, 0);
+
+ return dataLength;
+}
+
+JNIEXPORT jobject JNICALL
+Java_com_phidgets_IRPhidget_getLastLearnedCode(JNIEnv *env, jobject obj)
+{
+ CPhidgetIRHandle h = (CPhidgetIRHandle)(uintptr_t)(*env)->GetLongField( env, obj, handle_fid);
+ int error;
+ unsigned char data[IR_MAX_CODE_DATA_LENGTH];
+ int dataLength=IR_MAX_CODE_DATA_LENGTH;
+ CPhidgetIR_CodeInfo codeInfoReal;
+ CPhidgetIR_CodeInfoHandle codeInfo = &codeInfoReal;
+ jobject ircode, ircodeinfo, irlearn, togglemask;
+ jshortArray codeData;
+ jintArray headerArray, zeroArray, oneArray, repeatArray;
+ jshort *datas;
+ jint *datai;
+ int i,j;
+
+ if ((error = CPhidgetIR_getLastLearnedCode(h, data, &dataLength, codeInfo)))
+ {
+ PH_THROW(error);
+ return NULL;
+ }
+
+ //create and fill in short array
+ if(dataLength > 0){
+ codeData = (*env)->NewShortArray(env, dataLength);
+ if (!codeData)
+ {
+ PH_THROW(EPHIDGET_UNEXPECTED);
+ return NULL;
+ }
+ datas = (*env)->GetShortArrayElements(env, codeData, 0);
+ if (!datas)
+ {
+ PH_THROW(EPHIDGET_UNEXPECTED);
+ return NULL;
+ }
+ for (i=0; i<dataLength; i++)
+ datas[i] = (jshort)data[i];
+ (*env)->ReleaseShortArrayElements(env, codeData, datas, 0);
+ }
+ else
+ codeData=NULL;
+ //create IRCode object
+ if (!(ircode = (*env)->NewObject(env, irCode_class, irCode_cons, codeData, codeInfo->bitCount)))
+ {
+ PH_THROW(EPHIDGET_UNEXPECTED);
+ return NULL;
+ }
+
+ //Header
+ if(codeInfo->header[0])
+ {
+ headerArray = (*env)->NewIntArray(env, 2);
+ if (!headerArray)
+ {
+ PH_THROW(EPHIDGET_UNEXPECTED);
+ return NULL;
+ }
+ datai = (*env)->GetIntArrayElements(env, headerArray, 0);
+ if (!datai)
+ {
+ PH_THROW(EPHIDGET_UNEXPECTED);
+ return NULL;
+ }
+ for (i=0; i<2; i++)
+ datai[i] = (jint)codeInfo->header[i];
+ (*env)->ReleaseIntArrayElements(env, headerArray, datai, 0);
+ }
+ else
+ headerArray=NULL;
+
+ //Zero
+ zeroArray = (*env)->NewIntArray(env, 2);
+ if (!zeroArray)
+ {
+ PH_THROW(EPHIDGET_UNEXPECTED);
+ return NULL;
+ }
+ datai = (*env)->GetIntArrayElements(env, zeroArray, 0);
+ if (!datai)
+ {
+ PH_THROW(EPHIDGET_UNEXPECTED);
+ return NULL;
+ }
+ for (i=0; i<2; i++)
+ datai[i] = (jint)codeInfo->zero[i];
+ (*env)->ReleaseIntArrayElements(env, zeroArray, datai, 0);
+
+ //One
+ oneArray = (*env)->NewIntArray(env, 2);
+ if (!oneArray)
+ {
+ PH_THROW(EPHIDGET_UNEXPECTED);
+ return NULL;
+ }
+ datai = (*env)->GetIntArrayElements(env, oneArray, 0);
+ if (!datai)
+ {
+ PH_THROW(EPHIDGET_UNEXPECTED);
+ return NULL;
+ }
+ for (i=0; i<2; i++)
+ datai[i] = (jint)codeInfo->one[i];
+ (*env)->ReleaseIntArrayElements(env, oneArray, datai, 0);
+
+ //Repeat
+ i=0;
+ while(codeInfo->repeat[i])
+ i++;
+ if(i)
+ {
+ repeatArray = (*env)->NewIntArray(env, i);
+ if (!repeatArray)
+ {
+ PH_THROW(EPHIDGET_UNEXPECTED);
+ return NULL;
+ }
+ datai = (*env)->GetIntArrayElements(env, repeatArray, 0);
+ if (!datai)
+ {
+ PH_THROW(EPHIDGET_UNEXPECTED);
+ return NULL;
+ }
+ for (j=0; j<i; j++)
+ datai[j] = (jint)codeInfo->repeat[j];
+ (*env)->ReleaseIntArrayElements(env, repeatArray, datai, 0);
+ }
+ else{
+ repeatArray=NULL;
+ }
+
+ //ToggleMask
+
+ if(dataLength > 0){
+ codeData = (*env)->NewShortArray(env, dataLength);
+ if (!codeData)
+ {
+ PH_THROW(EPHIDGET_UNEXPECTED);
+ return NULL;
+ }
+ datas = (*env)->GetShortArrayElements(env, codeData, 0);
+ if (!datas)
+ {
+ PH_THROW(EPHIDGET_UNEXPECTED);
+ return NULL;
+ }
+ for (i=0; i<dataLength; i++){
+
+ datas[i] = (jshort)codeInfo->toggle_mask[i];
+ }
+ (*env)->ReleaseShortArrayElements(env, codeData, datas, 0);
+ }
+ else{
+ codeData=NULL;
+ }
+
+ if (!(togglemask = (*env)->NewObject(env, irCode_class, irCode_cons, codeData, codeInfo->bitCount)))
+ {
+ PH_THROW(EPHIDGET_UNEXPECTED);
+ return NULL;
+ }
+
+ //create IRCodeInfo object
+ if (!(ircodeinfo = (*env)->NewObject(env, irCodeInfo_class, irCodeInfo_cons,
+ codeInfo->encoding, codeInfo->bitCount, headerArray, zeroArray, oneArray,
+ codeInfo->trail, codeInfo->gap, repeatArray, codeInfo->min_repeat, togglemask,
+ codeInfo->length, codeInfo->carrierFrequency, codeInfo->dutyCycle)))
+ {
+ (*env)->DeleteLocalRef(env, ircode);
+ PH_THROW(EPHIDGET_UNEXPECTED);
+ return NULL;
+ }
+
+ //create IRLearn object
+ if (!(irlearn = (*env)->NewObject(env, irLearn_class, irLearn_cons, ircode, ircodeinfo)))
+ {
+ (*env)->DeleteLocalRef(env, ircode);
+ (*env)->DeleteLocalRef(env, ircodeinfo);
+ PH_THROW(EPHIDGET_UNEXPECTED);
+ return NULL;
+ }
+
+ return irlearn;
+}
+
+JNIEXPORT void JNICALL
+Java_com_phidgets_IRPhidget_transmit(JNIEnv *env, jobject obj, jobject code, jobject irCodeInfo)
+{
+ CPhidgetIRHandle h = (CPhidgetIRHandle)(uintptr_t)(*env)->GetLongField( env, obj, handle_fid);
+ jshortArray codeData;
+ jintArray headerArray, zeroArray, oneArray, repeatArray;
+ jobject togglemask;
+ jshort *datas;
+ jint *datai;
+ unsigned char data[IR_MAX_CODE_DATA_LENGTH];
+ jsize len;
+ CPhidgetIR_CodeInfo codeInfoReal = {0};
+ CPhidgetIR_CodeInfoHandle codeInfo = &codeInfoReal;
+ int i;
+ int error;
+
+ //read in code
+ if (!(codeData = (*env)->CallObjectMethod(env, code, irCode_getData)))
+ {
+ PH_THROW(EPHIDGET_UNEXPECTED);
+ return;
+ }
+ datas = (*env)->GetShortArrayElements(env, codeData, 0);
+ if (!datas)
+ {
+ PH_THROW(EPHIDGET_UNEXPECTED);
+ return;
+ }
+ len = (*env)->GetArrayLength(env, codeData);
+ for(i=0;i<len;i++)
+ {
+ data[i] = (unsigned char)datas[i];
+ }
+ (*env)->ReleaseShortArrayElements(env, codeData, datas, 0);
+
+ //read in codeInfo
+ //ints
+ codeInfo->encoding = (*env)->CallIntMethod(env, irCodeInfo, irCodeInfo_getEncoding);
+ codeInfo->length = (*env)->CallIntMethod(env, irCodeInfo, irCodeInfo_getLength);
+ codeInfo->bitCount = (*env)->CallIntMethod(env, irCodeInfo, irCodeInfo_getBitCount);
+ codeInfo->gap = (*env)->CallIntMethod(env, irCodeInfo, irCodeInfo_getGap);
+ codeInfo->trail = (*env)->CallIntMethod(env, irCodeInfo, irCodeInfo_getTrail);
+ codeInfo->min_repeat = (*env)->CallIntMethod(env, irCodeInfo, irCodeInfo_getMinRepeat);
+ codeInfo->carrierFrequency = (*env)->CallIntMethod(env, irCodeInfo, irCodeInfo_getCarrierFrequency);
+ codeInfo->dutyCycle = (*env)->CallIntMethod(env, irCodeInfo, irCodeInfo_getDutyCycle);
+ //arrays/objects
+ //Header
+ headerArray = (*env)->CallObjectMethod(env, irCodeInfo, irCodeInfo_getHeader);
+ if(headerArray)
+ {
+ datai = (*env)->GetIntArrayElements(env, headerArray, 0);
+ if (!datai)
+ {
+ PH_THROW(EPHIDGET_UNEXPECTED);
+ return;
+ }
+ for (i=0; i<2; i++)
+ codeInfo->header[i] = datai[i];
+ (*env)->ReleaseIntArrayElements(env, headerArray, datai, 0);
+ }
+ else
+ headerArray=NULL;
+
+ //Zero
+ zeroArray = (*env)->CallObjectMethod(env, irCodeInfo, irCodeInfo_getZero);
+ datai = (*env)->GetIntArrayElements(env, zeroArray, 0);
+ if (!datai)
+ {
+ PH_THROW(EPHIDGET_UNEXPECTED);
+ return;
+ }
+ for (i=0; i<2; i++)
+ codeInfo->zero[i] = datai[i];
+ (*env)->ReleaseIntArrayElements(env, zeroArray, datai, 0);
+
+ //One
+ oneArray = (*env)->CallObjectMethod(env, irCodeInfo, irCodeInfo_getOne);
+ datai = (*env)->GetIntArrayElements(env, oneArray, 0);
+ if (!datai)
+ {
+ PH_THROW(EPHIDGET_UNEXPECTED);
+ return;
+ }
+ for (i=0; i<2; i++)
+ codeInfo->one[i] = datai[i];
+ (*env)->ReleaseIntArrayElements(env, oneArray, datai, 0);
+
+ //Repeat
+ repeatArray = (*env)->CallObjectMethod(env, irCodeInfo, irCodeInfo_getRepeat);
+ if(repeatArray)
+ {
+ len = (*env)->GetArrayLength(env, repeatArray);
+ if(len)
+ {
+ datai = (*env)->GetIntArrayElements(env, repeatArray, 0);
+ if (!datai)
+ {
+ PH_THROW(EPHIDGET_UNEXPECTED);
+ return;
+ }
+ for (i=0; i<len; i++)
+ codeInfo->repeat[i] = datai[i];
+ (*env)->ReleaseIntArrayElements(env, repeatArray, datai, 0);
+ }
+ }
+ else
+ repeatArray=NULL;
+
+ //ToggleMask
+ togglemask = (*env)->CallObjectMethod(env, irCodeInfo, irCodeInfo_getToggleMask);
+ if(togglemask)
+ {
+ if (!(codeData = (*env)->CallObjectMethod(env, togglemask, irCode_getData)))
+ {
+ PH_THROW(EPHIDGET_UNEXPECTED);
+ return;
+ }
+ datas = (*env)->GetShortArrayElements(env, codeData, 0);
+ if (!datas)
+ {
+ PH_THROW(EPHIDGET_UNEXPECTED);
+ return;
+ }
+ len = (*env)->GetArrayLength(env, codeData);
+ for(i=0;i<len;i++)
+ {
+ codeInfo->toggle_mask[i] = (unsigned char)datas[i];
+ }
+ (*env)->ReleaseShortArrayElements(env, codeData, datas, 0);
+ }
+ else
+ togglemask=NULL;
+
+ if ((error = CPhidgetIR_Transmit(h, data, codeInfo)))
+ PH_THROW(error);
+}
+
+JNIEXPORT void JNICALL
+Java_com_phidgets_IRPhidget_transmitRepeat(JNIEnv *env, jobject obj)
+{
+ CPhidgetIRHandle h = (CPhidgetIRHandle)(uintptr_t)(*env)->GetLongField( env, obj, handle_fid);
+ int error;
+ if ((error = CPhidgetIR_TransmitRepeat(h)))
+ PH_THROW(error);
+}
+
+JNIEXPORT void JNICALL
+Java_com_phidgets_IRPhidget_transmitRaw(JNIEnv *env, jobject obj, jintArray data, jint offset, jint count, jint gap, jint carrierFrequency, jint dutyCycle)
+{
+ CPhidgetIRHandle h = (CPhidgetIRHandle)(uintptr_t)(*env)->GetLongField( env, obj, handle_fid);
+ int error;
+ jint *datai;
+
+ datai = (*env)->GetIntArrayElements(env, data, 0);
+ if (!datai)
+ {
+ PH_THROW(EPHIDGET_UNEXPECTED);
+ return;
+ }
+
+ if ((error = CPhidgetIR_TransmitRaw(h, datai+offset, count, carrierFrequency, dutyCycle, gap)))
+ PH_THROW(error);
+
+ (*env)->ReleaseIntArrayElements(env, data, datai, 0);
+}
diff --git a/Java/com_phidgets_IRPhidget.h b/Java/com_phidgets_IRPhidget.h
new file mode 100644
index 0000000..66feca2
--- /dev/null
+++ b/Java/com_phidgets_IRPhidget.h
@@ -0,0 +1,239 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class com_phidgets_IRPhidget */
+
+#ifndef _Included_com_phidgets_IRPhidget
+#define _Included_com_phidgets_IRPhidget
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef com_phidgets_IRPhidget_PHIDGET_LOG_CRITICAL
+#define com_phidgets_IRPhidget_PHIDGET_LOG_CRITICAL 1L
+#undef com_phidgets_IRPhidget_PHIDGET_LOG_ERROR
+#define com_phidgets_IRPhidget_PHIDGET_LOG_ERROR 2L
+#undef com_phidgets_IRPhidget_PHIDGET_LOG_WARNING
+#define com_phidgets_IRPhidget_PHIDGET_LOG_WARNING 3L
+#undef com_phidgets_IRPhidget_PHIDGET_LOG_DEBUG
+#define com_phidgets_IRPhidget_PHIDGET_LOG_DEBUG 4L
+#undef com_phidgets_IRPhidget_PHIDGET_LOG_INFO
+#define com_phidgets_IRPhidget_PHIDGET_LOG_INFO 5L
+#undef com_phidgets_IRPhidget_PHIDGET_LOG_VERBOSE
+#define com_phidgets_IRPhidget_PHIDGET_LOG_VERBOSE 6L
+#undef com_phidgets_IRPhidget_PHIDID_NOTHING
+#define com_phidgets_IRPhidget_PHIDID_NOTHING 1L
+#undef com_phidgets_IRPhidget_PHIDID_ACCELEROMETER_3AXIS
+#define com_phidgets_IRPhidget_PHIDID_ACCELEROMETER_3AXIS 126L
+#undef com_phidgets_IRPhidget_PHIDID_ADVANCEDSERVO_1MOTOR
+#define com_phidgets_IRPhidget_PHIDID_ADVANCEDSERVO_1MOTOR 130L
+#undef com_phidgets_IRPhidget_PHIDID_ANALOG_4OUTPUT
+#define com_phidgets_IRPhidget_PHIDID_ANALOG_4OUTPUT 55L
+#undef com_phidgets_IRPhidget_PHIDID_ADVANCEDSERVO_8MOTOR
+#define com_phidgets_IRPhidget_PHIDID_ADVANCEDSERVO_8MOTOR 58L
+#undef com_phidgets_IRPhidget_PHIDID_BIPOLAR_STEPPER_1MOTOR
+#define com_phidgets_IRPhidget_PHIDID_BIPOLAR_STEPPER_1MOTOR 123L
+#undef com_phidgets_IRPhidget_PHIDID_BRIDGE_4INPUT
+#define com_phidgets_IRPhidget_PHIDID_BRIDGE_4INPUT 59L
+#undef com_phidgets_IRPhidget_PHIDID_ENCODER_1ENCODER_1INPUT
+#define com_phidgets_IRPhidget_PHIDID_ENCODER_1ENCODER_1INPUT 75L
+#undef com_phidgets_IRPhidget_PHIDID_ENCODER_HS_1ENCODER
+#define com_phidgets_IRPhidget_PHIDID_ENCODER_HS_1ENCODER 128L
+#undef com_phidgets_IRPhidget_PHIDID_ENCODER_HS_4ENCODER_4INPUT
+#define com_phidgets_IRPhidget_PHIDID_ENCODER_HS_4ENCODER_4INPUT 79L
+#undef com_phidgets_IRPhidget_PHIDID_FREQUENCYCOUNTER_2INPUT
+#define com_phidgets_IRPhidget_PHIDID_FREQUENCYCOUNTER_2INPUT 53L
+#undef com_phidgets_IRPhidget_PHIDID_GPS
+#define com_phidgets_IRPhidget_PHIDID_GPS 121L
+#undef com_phidgets_IRPhidget_PHIDID_INTERFACEKIT_0_0_4
+#define com_phidgets_IRPhidget_PHIDID_INTERFACEKIT_0_0_4 64L
+#undef com_phidgets_IRPhidget_PHIDID_INTERFACEKIT_0_0_8
+#define com_phidgets_IRPhidget_PHIDID_INTERFACEKIT_0_0_8 129L
+#undef com_phidgets_IRPhidget_PHIDID_INTERFACEKIT_0_16_16
+#define com_phidgets_IRPhidget_PHIDID_INTERFACEKIT_0_16_16 68L
+#undef com_phidgets_IRPhidget_PHIDID_INTERFACEKIT_8_8_8
+#define com_phidgets_IRPhidget_PHIDID_INTERFACEKIT_8_8_8 69L
+#undef com_phidgets_IRPhidget_PHIDID_INTERFACEKIT_8_8_8_w_LCD
+#define com_phidgets_IRPhidget_PHIDID_INTERFACEKIT_8_8_8_w_LCD 125L
+#undef com_phidgets_IRPhidget_PHIDID_IR
+#define com_phidgets_IRPhidget_PHIDID_IR 77L
+#undef com_phidgets_IRPhidget_PHIDID_LED_64
+#define com_phidgets_IRPhidget_PHIDID_LED_64 74L
+#undef com_phidgets_IRPhidget_PHIDID_LED_64_ADV
+#define com_phidgets_IRPhidget_PHIDID_LED_64_ADV 76L
+#undef com_phidgets_IRPhidget_PHIDID_LINEAR_TOUCH
+#define com_phidgets_IRPhidget_PHIDID_LINEAR_TOUCH 118L
+#undef com_phidgets_IRPhidget_PHIDID_MOTORCONTROL_HC_2MOTOR
+#define com_phidgets_IRPhidget_PHIDID_MOTORCONTROL_HC_2MOTOR 89L
+#undef com_phidgets_IRPhidget_PHIDID_MOTORCONTROL_LV_2MOTOR_4INPUT
+#define com_phidgets_IRPhidget_PHIDID_MOTORCONTROL_LV_2MOTOR_4INPUT 88L
+#undef com_phidgets_IRPhidget_PHIDID_MOTORCONTROL_1MOTOR
+#define com_phidgets_IRPhidget_PHIDID_MOTORCONTROL_1MOTOR 62L
+#undef com_phidgets_IRPhidget_PHIDID_PHSENSOR
+#define com_phidgets_IRPhidget_PHIDID_PHSENSOR 116L
+#undef com_phidgets_IRPhidget_PHIDID_RFID_2OUTPUT
+#define com_phidgets_IRPhidget_PHIDID_RFID_2OUTPUT 49L
+#undef com_phidgets_IRPhidget_PHIDID_ROTARY_TOUCH
+#define com_phidgets_IRPhidget_PHIDID_ROTARY_TOUCH 119L
+#undef com_phidgets_IRPhidget_PHIDID_SERVO_1MOTOR
+#define com_phidgets_IRPhidget_PHIDID_SERVO_1MOTOR 57L
+#undef com_phidgets_IRPhidget_PHIDID_SPATIAL_ACCEL_3AXIS
+#define com_phidgets_IRPhidget_PHIDID_SPATIAL_ACCEL_3AXIS 127L
+#undef com_phidgets_IRPhidget_PHIDID_SPATIAL_ACCEL_GYRO_COMPASS
+#define com_phidgets_IRPhidget_PHIDID_SPATIAL_ACCEL_GYRO_COMPASS 51L
+#undef com_phidgets_IRPhidget_PHIDID_TEMPERATURESENSOR
+#define com_phidgets_IRPhidget_PHIDID_TEMPERATURESENSOR 112L
+#undef com_phidgets_IRPhidget_PHIDID_TEMPERATURESENSOR_4
+#define com_phidgets_IRPhidget_PHIDID_TEMPERATURESENSOR_4 50L
+#undef com_phidgets_IRPhidget_PHIDID_TEXTLCD_2x20_w_8_8_8
+#define com_phidgets_IRPhidget_PHIDID_TEXTLCD_2x20_w_8_8_8 381L
+#undef com_phidgets_IRPhidget_PHIDID_TEXTLCD_ADAPTER
+#define com_phidgets_IRPhidget_PHIDID_TEXTLCD_ADAPTER 61L
+#undef com_phidgets_IRPhidget_PHIDID_UNIPOLAR_STEPPER_4MOTOR
+#define com_phidgets_IRPhidget_PHIDID_UNIPOLAR_STEPPER_4MOTOR 122L
+#undef com_phidgets_IRPhidget_PHIDID_ACCELEROMETER_2AXIS
+#define com_phidgets_IRPhidget_PHIDID_ACCELEROMETER_2AXIS 113L
+#undef com_phidgets_IRPhidget_PHIDID_INTERFACEKIT_0_8_8_w_LCD
+#define com_phidgets_IRPhidget_PHIDID_INTERFACEKIT_0_8_8_w_LCD 83L
+#undef com_phidgets_IRPhidget_PHIDID_INTERFACEKIT_4_8_8
+#define com_phidgets_IRPhidget_PHIDID_INTERFACEKIT_4_8_8 4L
+#undef com_phidgets_IRPhidget_PHIDID_RFID
+#define com_phidgets_IRPhidget_PHIDID_RFID 48L
+#undef com_phidgets_IRPhidget_PHIDID_SERVO_1MOTOR_OLD
+#define com_phidgets_IRPhidget_PHIDID_SERVO_1MOTOR_OLD 2L
+#undef com_phidgets_IRPhidget_PHIDID_SERVO_4MOTOR
+#define com_phidgets_IRPhidget_PHIDID_SERVO_4MOTOR 56L
+#undef com_phidgets_IRPhidget_PHIDID_SERVO_4MOTOR_OLD
+#define com_phidgets_IRPhidget_PHIDID_SERVO_4MOTOR_OLD 3L
+#undef com_phidgets_IRPhidget_PHIDID_TEXTLCD_2x20
+#define com_phidgets_IRPhidget_PHIDID_TEXTLCD_2x20 82L
+#undef com_phidgets_IRPhidget_PHIDID_TEXTLCD_2x20_w_0_8_8
+#define com_phidgets_IRPhidget_PHIDID_TEXTLCD_2x20_w_0_8_8 339L
+#undef com_phidgets_IRPhidget_PHIDID_TEXTLED_1x8
+#define com_phidgets_IRPhidget_PHIDID_TEXTLED_1x8 73L
+#undef com_phidgets_IRPhidget_PHIDID_TEXTLED_4x8
+#define com_phidgets_IRPhidget_PHIDID_TEXTLED_4x8 72L
+#undef com_phidgets_IRPhidget_PHIDID_WEIGHTSENSOR
+#define com_phidgets_IRPhidget_PHIDID_WEIGHTSENSOR 114L
+#undef com_phidgets_IRPhidget_PHIDCLASS_NOTHING
+#define com_phidgets_IRPhidget_PHIDCLASS_NOTHING 1L
+#undef com_phidgets_IRPhidget_PHIDCLASS_ACCELEROMETER
+#define com_phidgets_IRPhidget_PHIDCLASS_ACCELEROMETER 2L
+#undef com_phidgets_IRPhidget_PHIDCLASS_ADVANCEDSERVO
+#define com_phidgets_IRPhidget_PHIDCLASS_ADVANCEDSERVO 3L
+#undef com_phidgets_IRPhidget_PHIDCLASS_ANALOG
+#define com_phidgets_IRPhidget_PHIDCLASS_ANALOG 22L
+#undef com_phidgets_IRPhidget_PHIDCLASS_BRIDGE
+#define com_phidgets_IRPhidget_PHIDCLASS_BRIDGE 23L
+#undef com_phidgets_IRPhidget_PHIDCLASS_ENCODER
+#define com_phidgets_IRPhidget_PHIDCLASS_ENCODER 4L
+#undef com_phidgets_IRPhidget_PHIDCLASS_FREQUENCYCOUNTER
+#define com_phidgets_IRPhidget_PHIDCLASS_FREQUENCYCOUNTER 21L
+#undef com_phidgets_IRPhidget_PHIDCLASS_GPS
+#define com_phidgets_IRPhidget_PHIDCLASS_GPS 5L
+#undef com_phidgets_IRPhidget_PHIDCLASS_INTERFACEKIT
+#define com_phidgets_IRPhidget_PHIDCLASS_INTERFACEKIT 7L
+#undef com_phidgets_IRPhidget_PHIDCLASS_LED
+#define com_phidgets_IRPhidget_PHIDCLASS_LED 8L
+#undef com_phidgets_IRPhidget_PHIDCLASS_MOTORCONTROL
+#define com_phidgets_IRPhidget_PHIDCLASS_MOTORCONTROL 9L
+#undef com_phidgets_IRPhidget_PHIDCLASS_PHSENSOR
+#define com_phidgets_IRPhidget_PHIDCLASS_PHSENSOR 10L
+#undef com_phidgets_IRPhidget_PHIDCLASS_RFID
+#define com_phidgets_IRPhidget_PHIDCLASS_RFID 11L
+#undef com_phidgets_IRPhidget_PHIDCLASS_SERVO
+#define com_phidgets_IRPhidget_PHIDCLASS_SERVO 12L
+#undef com_phidgets_IRPhidget_PHIDCLASS_STEPPER
+#define com_phidgets_IRPhidget_PHIDCLASS_STEPPER 13L
+#undef com_phidgets_IRPhidget_PHIDCLASS_TEMPERATURESENSOR
+#define com_phidgets_IRPhidget_PHIDCLASS_TEMPERATURESENSOR 14L
+#undef com_phidgets_IRPhidget_PHIDCLASS_TEXTLCD
+#define com_phidgets_IRPhidget_PHIDCLASS_TEXTLCD 15L
+#undef com_phidgets_IRPhidget_PHIDCLASS_TEXTLED
+#define com_phidgets_IRPhidget_PHIDCLASS_TEXTLED 16L
+#undef com_phidgets_IRPhidget_PHIDCLASS_WEIGHTSENSOR
+#define com_phidgets_IRPhidget_PHIDCLASS_WEIGHTSENSOR 17L
+#undef com_phidgets_IRPhidget_RAWDATA_LONGSPACE
+#define com_phidgets_IRPhidget_RAWDATA_LONGSPACE 2147483647L
+/*
+ * Class: com_phidgets_IRPhidget
+ * Method: create
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL Java_com_phidgets_IRPhidget_create
+ (JNIEnv *, jclass);
+
+/*
+ * Class: com_phidgets_IRPhidget
+ * Method: transmit
+ * Signature: (Lcom/phidgets/IRCode;Lcom/phidgets/IRCodeInfo;)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_IRPhidget_transmit
+ (JNIEnv *, jobject, jobject, jobject);
+
+/*
+ * Class: com_phidgets_IRPhidget
+ * Method: transmitRepeat
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_IRPhidget_transmitRepeat
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_IRPhidget
+ * Method: transmitRaw
+ * Signature: ([IIIIII)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_IRPhidget_transmitRaw
+ (JNIEnv *, jobject, jintArray, jint, jint, jint, jint, jint);
+
+/*
+ * Class: com_phidgets_IRPhidget
+ * Method: readRaw
+ * Signature: ([III)I
+ */
+JNIEXPORT jint JNICALL Java_com_phidgets_IRPhidget_readRaw
+ (JNIEnv *, jobject, jintArray, jint, jint);
+
+/*
+ * Class: com_phidgets_IRPhidget
+ * Method: getLastCode
+ * Signature: ()Lcom/phidgets/IRCode;
+ */
+JNIEXPORT jobject JNICALL Java_com_phidgets_IRPhidget_getLastCode
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_IRPhidget
+ * Method: getLastLearnedCode
+ * Signature: ()Lcom/phidgets/IRLearnedCode;
+ */
+JNIEXPORT jobject JNICALL Java_com_phidgets_IRPhidget_getLastLearnedCode
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_IRPhidget
+ * Method: enableCodeEvents
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_IRPhidget_enableCodeEvents
+ (JNIEnv *, jobject, jboolean);
+
+/*
+ * Class: com_phidgets_IRPhidget
+ * Method: enableLearnEvents
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_IRPhidget_enableLearnEvents
+ (JNIEnv *, jobject, jboolean);
+
+/*
+ * Class: com_phidgets_IRPhidget
+ * Method: enableRawDataEvents
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_IRPhidget_enableRawDataEvents
+ (JNIEnv *, jobject, jboolean);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/Java/com_phidgets_InterfaceKitPhidget.c b/Java/com_phidgets_InterfaceKitPhidget.c
new file mode 100644
index 0000000..923b83f
--- /dev/null
+++ b/Java/com_phidgets_InterfaceKitPhidget.c
@@ -0,0 +1,36 @@
+#include "../stdafx.h"
+#include "phidget_jni.h"
+#include "com_phidgets_InterfaceKitPhidget.h"
+#include "../cphidgetinterfacekit.h"
+
+EVENT_VARS(inputChange, InputChange)
+EVENT_VARS(outputChange, OutputChange)
+EVENT_VARS(sensorChange, SensorChange)
+
+JNI_LOAD(ifkit, InterfaceKit)
+ EVENT_VAR_SETUP(ifkit, inputChange, InputChange, IZ, V)
+ EVENT_VAR_SETUP(ifkit, outputChange, OutputChange, IZ, V)
+ EVENT_VAR_SETUP(ifkit, sensorChange, SensorChange, II, V)
+}
+
+EVENT_HANDLER_INDEXED(InterfaceKit, inputChange, InputChange, CPhidgetInterfaceKit_set_OnInputChange_Handler, int)
+EVENT_HANDLER_INDEXED(InterfaceKit, outputChange, OutputChange, CPhidgetInterfaceKit_set_OnOutputChange_Handler, int)
+EVENT_HANDLER_INDEXED(InterfaceKit, sensorChange, SensorChange, CPhidgetInterfaceKit_set_OnSensorChange_Handler, int)
+
+JNI_CREATE(InterfaceKit)
+JNI_GETFUNC(InterfaceKit, OutputCount, OutputCount, jint)
+JNI_GETFUNC(InterfaceKit, InputCount, InputCount, jint)
+JNI_GETFUNC(InterfaceKit, SensorCount, SensorCount, jint)
+JNI_INDEXED_GETFUNCBOOL(InterfaceKit, InputState, InputState)
+JNI_INDEXED_GETFUNCBOOL(InterfaceKit, OutputState, OutputState)
+JNI_INDEXED_GETFUNC(InterfaceKit, SensorValue, SensorValue, jint)
+JNI_INDEXED_GETFUNC(InterfaceKit, SensorRawValue, SensorRawValue, jint)
+JNI_INDEXED_GETFUNC(InterfaceKit, DataRateMin, DataRateMin, jint)
+JNI_INDEXED_GETFUNC(InterfaceKit, DataRateMax, DataRateMax, jint)
+JNI_INDEXED_GETFUNC(InterfaceKit, DataRate, DataRate, jint)
+JNI_INDEXED_GETFUNC(InterfaceKit, SensorChangeTrigger, SensorChangeTrigger, jint)
+JNI_GETFUNCBOOL(InterfaceKit, Ratiometric, Ratiometric)
+JNI_INDEXED_SETFUNC(InterfaceKit, OutputState, OutputState, jboolean)
+JNI_INDEXED_SETFUNC(InterfaceKit, DataRate, DataRate, jint)
+JNI_INDEXED_SETFUNC(InterfaceKit, SensorChangeTrigger, SensorChangeTrigger, jint)
+JNI_SETFUNC(InterfaceKit, Ratiometric, Ratiometric, jboolean)
diff --git a/Java/com_phidgets_InterfaceKitPhidget.h b/Java/com_phidgets_InterfaceKitPhidget.h
new file mode 100644
index 0000000..c985f9e
--- /dev/null
+++ b/Java/com_phidgets_InterfaceKitPhidget.h
@@ -0,0 +1,317 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class com_phidgets_InterfaceKitPhidget */
+
+#ifndef _Included_com_phidgets_InterfaceKitPhidget
+#define _Included_com_phidgets_InterfaceKitPhidget
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef com_phidgets_InterfaceKitPhidget_PHIDGET_LOG_CRITICAL
+#define com_phidgets_InterfaceKitPhidget_PHIDGET_LOG_CRITICAL 1L
+#undef com_phidgets_InterfaceKitPhidget_PHIDGET_LOG_ERROR
+#define com_phidgets_InterfaceKitPhidget_PHIDGET_LOG_ERROR 2L
+#undef com_phidgets_InterfaceKitPhidget_PHIDGET_LOG_WARNING
+#define com_phidgets_InterfaceKitPhidget_PHIDGET_LOG_WARNING 3L
+#undef com_phidgets_InterfaceKitPhidget_PHIDGET_LOG_DEBUG
+#define com_phidgets_InterfaceKitPhidget_PHIDGET_LOG_DEBUG 4L
+#undef com_phidgets_InterfaceKitPhidget_PHIDGET_LOG_INFO
+#define com_phidgets_InterfaceKitPhidget_PHIDGET_LOG_INFO 5L
+#undef com_phidgets_InterfaceKitPhidget_PHIDGET_LOG_VERBOSE
+#define com_phidgets_InterfaceKitPhidget_PHIDGET_LOG_VERBOSE 6L
+#undef com_phidgets_InterfaceKitPhidget_PHIDID_NOTHING
+#define com_phidgets_InterfaceKitPhidget_PHIDID_NOTHING 1L
+#undef com_phidgets_InterfaceKitPhidget_PHIDID_ACCELEROMETER_3AXIS
+#define com_phidgets_InterfaceKitPhidget_PHIDID_ACCELEROMETER_3AXIS 126L
+#undef com_phidgets_InterfaceKitPhidget_PHIDID_ADVANCEDSERVO_1MOTOR
+#define com_phidgets_InterfaceKitPhidget_PHIDID_ADVANCEDSERVO_1MOTOR 130L
+#undef com_phidgets_InterfaceKitPhidget_PHIDID_ANALOG_4OUTPUT
+#define com_phidgets_InterfaceKitPhidget_PHIDID_ANALOG_4OUTPUT 55L
+#undef com_phidgets_InterfaceKitPhidget_PHIDID_ADVANCEDSERVO_8MOTOR
+#define com_phidgets_InterfaceKitPhidget_PHIDID_ADVANCEDSERVO_8MOTOR 58L
+#undef com_phidgets_InterfaceKitPhidget_PHIDID_BIPOLAR_STEPPER_1MOTOR
+#define com_phidgets_InterfaceKitPhidget_PHIDID_BIPOLAR_STEPPER_1MOTOR 123L
+#undef com_phidgets_InterfaceKitPhidget_PHIDID_BRIDGE_4INPUT
+#define com_phidgets_InterfaceKitPhidget_PHIDID_BRIDGE_4INPUT 59L
+#undef com_phidgets_InterfaceKitPhidget_PHIDID_ENCODER_1ENCODER_1INPUT
+#define com_phidgets_InterfaceKitPhidget_PHIDID_ENCODER_1ENCODER_1INPUT 75L
+#undef com_phidgets_InterfaceKitPhidget_PHIDID_ENCODER_HS_1ENCODER
+#define com_phidgets_InterfaceKitPhidget_PHIDID_ENCODER_HS_1ENCODER 128L
+#undef com_phidgets_InterfaceKitPhidget_PHIDID_ENCODER_HS_4ENCODER_4INPUT
+#define com_phidgets_InterfaceKitPhidget_PHIDID_ENCODER_HS_4ENCODER_4INPUT 79L
+#undef com_phidgets_InterfaceKitPhidget_PHIDID_FREQUENCYCOUNTER_2INPUT
+#define com_phidgets_InterfaceKitPhidget_PHIDID_FREQUENCYCOUNTER_2INPUT 53L
+#undef com_phidgets_InterfaceKitPhidget_PHIDID_GPS
+#define com_phidgets_InterfaceKitPhidget_PHIDID_GPS 121L
+#undef com_phidgets_InterfaceKitPhidget_PHIDID_INTERFACEKIT_0_0_4
+#define com_phidgets_InterfaceKitPhidget_PHIDID_INTERFACEKIT_0_0_4 64L
+#undef com_phidgets_InterfaceKitPhidget_PHIDID_INTERFACEKIT_0_0_8
+#define com_phidgets_InterfaceKitPhidget_PHIDID_INTERFACEKIT_0_0_8 129L
+#undef com_phidgets_InterfaceKitPhidget_PHIDID_INTERFACEKIT_0_16_16
+#define com_phidgets_InterfaceKitPhidget_PHIDID_INTERFACEKIT_0_16_16 68L
+#undef com_phidgets_InterfaceKitPhidget_PHIDID_INTERFACEKIT_8_8_8
+#define com_phidgets_InterfaceKitPhidget_PHIDID_INTERFACEKIT_8_8_8 69L
+#undef com_phidgets_InterfaceKitPhidget_PHIDID_INTERFACEKIT_8_8_8_w_LCD
+#define com_phidgets_InterfaceKitPhidget_PHIDID_INTERFACEKIT_8_8_8_w_LCD 125L
+#undef com_phidgets_InterfaceKitPhidget_PHIDID_IR
+#define com_phidgets_InterfaceKitPhidget_PHIDID_IR 77L
+#undef com_phidgets_InterfaceKitPhidget_PHIDID_LED_64
+#define com_phidgets_InterfaceKitPhidget_PHIDID_LED_64 74L
+#undef com_phidgets_InterfaceKitPhidget_PHIDID_LED_64_ADV
+#define com_phidgets_InterfaceKitPhidget_PHIDID_LED_64_ADV 76L
+#undef com_phidgets_InterfaceKitPhidget_PHIDID_LINEAR_TOUCH
+#define com_phidgets_InterfaceKitPhidget_PHIDID_LINEAR_TOUCH 118L
+#undef com_phidgets_InterfaceKitPhidget_PHIDID_MOTORCONTROL_HC_2MOTOR
+#define com_phidgets_InterfaceKitPhidget_PHIDID_MOTORCONTROL_HC_2MOTOR 89L
+#undef com_phidgets_InterfaceKitPhidget_PHIDID_MOTORCONTROL_LV_2MOTOR_4INPUT
+#define com_phidgets_InterfaceKitPhidget_PHIDID_MOTORCONTROL_LV_2MOTOR_4INPUT 88L
+#undef com_phidgets_InterfaceKitPhidget_PHIDID_MOTORCONTROL_1MOTOR
+#define com_phidgets_InterfaceKitPhidget_PHIDID_MOTORCONTROL_1MOTOR 62L
+#undef com_phidgets_InterfaceKitPhidget_PHIDID_PHSENSOR
+#define com_phidgets_InterfaceKitPhidget_PHIDID_PHSENSOR 116L
+#undef com_phidgets_InterfaceKitPhidget_PHIDID_RFID_2OUTPUT
+#define com_phidgets_InterfaceKitPhidget_PHIDID_RFID_2OUTPUT 49L
+#undef com_phidgets_InterfaceKitPhidget_PHIDID_ROTARY_TOUCH
+#define com_phidgets_InterfaceKitPhidget_PHIDID_ROTARY_TOUCH 119L
+#undef com_phidgets_InterfaceKitPhidget_PHIDID_SERVO_1MOTOR
+#define com_phidgets_InterfaceKitPhidget_PHIDID_SERVO_1MOTOR 57L
+#undef com_phidgets_InterfaceKitPhidget_PHIDID_SPATIAL_ACCEL_3AXIS
+#define com_phidgets_InterfaceKitPhidget_PHIDID_SPATIAL_ACCEL_3AXIS 127L
+#undef com_phidgets_InterfaceKitPhidget_PHIDID_SPATIAL_ACCEL_GYRO_COMPASS
+#define com_phidgets_InterfaceKitPhidget_PHIDID_SPATIAL_ACCEL_GYRO_COMPASS 51L
+#undef com_phidgets_InterfaceKitPhidget_PHIDID_TEMPERATURESENSOR
+#define com_phidgets_InterfaceKitPhidget_PHIDID_TEMPERATURESENSOR 112L
+#undef com_phidgets_InterfaceKitPhidget_PHIDID_TEMPERATURESENSOR_4
+#define com_phidgets_InterfaceKitPhidget_PHIDID_TEMPERATURESENSOR_4 50L
+#undef com_phidgets_InterfaceKitPhidget_PHIDID_TEXTLCD_2x20_w_8_8_8
+#define com_phidgets_InterfaceKitPhidget_PHIDID_TEXTLCD_2x20_w_8_8_8 381L
+#undef com_phidgets_InterfaceKitPhidget_PHIDID_TEXTLCD_ADAPTER
+#define com_phidgets_InterfaceKitPhidget_PHIDID_TEXTLCD_ADAPTER 61L
+#undef com_phidgets_InterfaceKitPhidget_PHIDID_UNIPOLAR_STEPPER_4MOTOR
+#define com_phidgets_InterfaceKitPhidget_PHIDID_UNIPOLAR_STEPPER_4MOTOR 122L
+#undef com_phidgets_InterfaceKitPhidget_PHIDID_ACCELEROMETER_2AXIS
+#define com_phidgets_InterfaceKitPhidget_PHIDID_ACCELEROMETER_2AXIS 113L
+#undef com_phidgets_InterfaceKitPhidget_PHIDID_INTERFACEKIT_0_8_8_w_LCD
+#define com_phidgets_InterfaceKitPhidget_PHIDID_INTERFACEKIT_0_8_8_w_LCD 83L
+#undef com_phidgets_InterfaceKitPhidget_PHIDID_INTERFACEKIT_4_8_8
+#define com_phidgets_InterfaceKitPhidget_PHIDID_INTERFACEKIT_4_8_8 4L
+#undef com_phidgets_InterfaceKitPhidget_PHIDID_RFID
+#define com_phidgets_InterfaceKitPhidget_PHIDID_RFID 48L
+#undef com_phidgets_InterfaceKitPhidget_PHIDID_SERVO_1MOTOR_OLD
+#define com_phidgets_InterfaceKitPhidget_PHIDID_SERVO_1MOTOR_OLD 2L
+#undef com_phidgets_InterfaceKitPhidget_PHIDID_SERVO_4MOTOR
+#define com_phidgets_InterfaceKitPhidget_PHIDID_SERVO_4MOTOR 56L
+#undef com_phidgets_InterfaceKitPhidget_PHIDID_SERVO_4MOTOR_OLD
+#define com_phidgets_InterfaceKitPhidget_PHIDID_SERVO_4MOTOR_OLD 3L
+#undef com_phidgets_InterfaceKitPhidget_PHIDID_TEXTLCD_2x20
+#define com_phidgets_InterfaceKitPhidget_PHIDID_TEXTLCD_2x20 82L
+#undef com_phidgets_InterfaceKitPhidget_PHIDID_TEXTLCD_2x20_w_0_8_8
+#define com_phidgets_InterfaceKitPhidget_PHIDID_TEXTLCD_2x20_w_0_8_8 339L
+#undef com_phidgets_InterfaceKitPhidget_PHIDID_TEXTLED_1x8
+#define com_phidgets_InterfaceKitPhidget_PHIDID_TEXTLED_1x8 73L
+#undef com_phidgets_InterfaceKitPhidget_PHIDID_TEXTLED_4x8
+#define com_phidgets_InterfaceKitPhidget_PHIDID_TEXTLED_4x8 72L
+#undef com_phidgets_InterfaceKitPhidget_PHIDID_WEIGHTSENSOR
+#define com_phidgets_InterfaceKitPhidget_PHIDID_WEIGHTSENSOR 114L
+#undef com_phidgets_InterfaceKitPhidget_PHIDCLASS_NOTHING
+#define com_phidgets_InterfaceKitPhidget_PHIDCLASS_NOTHING 1L
+#undef com_phidgets_InterfaceKitPhidget_PHIDCLASS_ACCELEROMETER
+#define com_phidgets_InterfaceKitPhidget_PHIDCLASS_ACCELEROMETER 2L
+#undef com_phidgets_InterfaceKitPhidget_PHIDCLASS_ADVANCEDSERVO
+#define com_phidgets_InterfaceKitPhidget_PHIDCLASS_ADVANCEDSERVO 3L
+#undef com_phidgets_InterfaceKitPhidget_PHIDCLASS_ANALOG
+#define com_phidgets_InterfaceKitPhidget_PHIDCLASS_ANALOG 22L
+#undef com_phidgets_InterfaceKitPhidget_PHIDCLASS_BRIDGE
+#define com_phidgets_InterfaceKitPhidget_PHIDCLASS_BRIDGE 23L
+#undef com_phidgets_InterfaceKitPhidget_PHIDCLASS_ENCODER
+#define com_phidgets_InterfaceKitPhidget_PHIDCLASS_ENCODER 4L
+#undef com_phidgets_InterfaceKitPhidget_PHIDCLASS_FREQUENCYCOUNTER
+#define com_phidgets_InterfaceKitPhidget_PHIDCLASS_FREQUENCYCOUNTER 21L
+#undef com_phidgets_InterfaceKitPhidget_PHIDCLASS_GPS
+#define com_phidgets_InterfaceKitPhidget_PHIDCLASS_GPS 5L
+#undef com_phidgets_InterfaceKitPhidget_PHIDCLASS_INTERFACEKIT
+#define com_phidgets_InterfaceKitPhidget_PHIDCLASS_INTERFACEKIT 7L
+#undef com_phidgets_InterfaceKitPhidget_PHIDCLASS_LED
+#define com_phidgets_InterfaceKitPhidget_PHIDCLASS_LED 8L
+#undef com_phidgets_InterfaceKitPhidget_PHIDCLASS_MOTORCONTROL
+#define com_phidgets_InterfaceKitPhidget_PHIDCLASS_MOTORCONTROL 9L
+#undef com_phidgets_InterfaceKitPhidget_PHIDCLASS_PHSENSOR
+#define com_phidgets_InterfaceKitPhidget_PHIDCLASS_PHSENSOR 10L
+#undef com_phidgets_InterfaceKitPhidget_PHIDCLASS_RFID
+#define com_phidgets_InterfaceKitPhidget_PHIDCLASS_RFID 11L
+#undef com_phidgets_InterfaceKitPhidget_PHIDCLASS_SERVO
+#define com_phidgets_InterfaceKitPhidget_PHIDCLASS_SERVO 12L
+#undef com_phidgets_InterfaceKitPhidget_PHIDCLASS_STEPPER
+#define com_phidgets_InterfaceKitPhidget_PHIDCLASS_STEPPER 13L
+#undef com_phidgets_InterfaceKitPhidget_PHIDCLASS_TEMPERATURESENSOR
+#define com_phidgets_InterfaceKitPhidget_PHIDCLASS_TEMPERATURESENSOR 14L
+#undef com_phidgets_InterfaceKitPhidget_PHIDCLASS_TEXTLCD
+#define com_phidgets_InterfaceKitPhidget_PHIDCLASS_TEXTLCD 15L
+#undef com_phidgets_InterfaceKitPhidget_PHIDCLASS_TEXTLED
+#define com_phidgets_InterfaceKitPhidget_PHIDCLASS_TEXTLED 16L
+#undef com_phidgets_InterfaceKitPhidget_PHIDCLASS_WEIGHTSENSOR
+#define com_phidgets_InterfaceKitPhidget_PHIDCLASS_WEIGHTSENSOR 17L
+/*
+ * Class: com_phidgets_InterfaceKitPhidget
+ * Method: create
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL Java_com_phidgets_InterfaceKitPhidget_create
+ (JNIEnv *, jclass);
+
+/*
+ * Class: com_phidgets_InterfaceKitPhidget
+ * Method: getOutputCount
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_phidgets_InterfaceKitPhidget_getOutputCount
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_InterfaceKitPhidget
+ * Method: getInputCount
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_phidgets_InterfaceKitPhidget_getInputCount
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_InterfaceKitPhidget
+ * Method: getSensorCount
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_phidgets_InterfaceKitPhidget_getSensorCount
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_InterfaceKitPhidget
+ * Method: getDataRateMin
+ * Signature: (I)I
+ */
+JNIEXPORT jint JNICALL Java_com_phidgets_InterfaceKitPhidget_getDataRateMin
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_InterfaceKitPhidget
+ * Method: getDataRateMax
+ * Signature: (I)I
+ */
+JNIEXPORT jint JNICALL Java_com_phidgets_InterfaceKitPhidget_getDataRateMax
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_InterfaceKitPhidget
+ * Method: getInputState
+ * Signature: (I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_phidgets_InterfaceKitPhidget_getInputState
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_InterfaceKitPhidget
+ * Method: getOutputState
+ * Signature: (I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_phidgets_InterfaceKitPhidget_getOutputState
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_InterfaceKitPhidget
+ * Method: getSensorValue
+ * Signature: (I)I
+ */
+JNIEXPORT jint JNICALL Java_com_phidgets_InterfaceKitPhidget_getSensorValue
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_InterfaceKitPhidget
+ * Method: getSensorRawValue
+ * Signature: (I)I
+ */
+JNIEXPORT jint JNICALL Java_com_phidgets_InterfaceKitPhidget_getSensorRawValue
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_InterfaceKitPhidget
+ * Method: getSensorChangeTrigger
+ * Signature: (I)I
+ */
+JNIEXPORT jint JNICALL Java_com_phidgets_InterfaceKitPhidget_getSensorChangeTrigger
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_InterfaceKitPhidget
+ * Method: getDataRate
+ * Signature: (I)I
+ */
+JNIEXPORT jint JNICALL Java_com_phidgets_InterfaceKitPhidget_getDataRate
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_InterfaceKitPhidget
+ * Method: getRatiometric
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_phidgets_InterfaceKitPhidget_getRatiometric
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_InterfaceKitPhidget
+ * Method: setOutputState
+ * Signature: (IZ)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_InterfaceKitPhidget_setOutputState
+ (JNIEnv *, jobject, jint, jboolean);
+
+/*
+ * Class: com_phidgets_InterfaceKitPhidget
+ * Method: setSensorChangeTrigger
+ * Signature: (II)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_InterfaceKitPhidget_setSensorChangeTrigger
+ (JNIEnv *, jobject, jint, jint);
+
+/*
+ * Class: com_phidgets_InterfaceKitPhidget
+ * Method: setDataRate
+ * Signature: (II)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_InterfaceKitPhidget_setDataRate
+ (JNIEnv *, jobject, jint, jint);
+
+/*
+ * Class: com_phidgets_InterfaceKitPhidget
+ * Method: setRatiometric
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_InterfaceKitPhidget_setRatiometric
+ (JNIEnv *, jobject, jboolean);
+
+/*
+ * Class: com_phidgets_InterfaceKitPhidget
+ * Method: enableInputChangeEvents
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_InterfaceKitPhidget_enableInputChangeEvents
+ (JNIEnv *, jobject, jboolean);
+
+/*
+ * Class: com_phidgets_InterfaceKitPhidget
+ * Method: enableOutputChangeEvents
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_InterfaceKitPhidget_enableOutputChangeEvents
+ (JNIEnv *, jobject, jboolean);
+
+/*
+ * Class: com_phidgets_InterfaceKitPhidget
+ * Method: enableSensorChangeEvents
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_InterfaceKitPhidget_enableSensorChangeEvents
+ (JNIEnv *, jobject, jboolean);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/Java/com_phidgets_LEDPhidget.c b/Java/com_phidgets_LEDPhidget.c
new file mode 100644
index 0000000..20097b9
--- /dev/null
+++ b/Java/com_phidgets_LEDPhidget.c
@@ -0,0 +1,38 @@
+#include "../stdafx.h"
+#include "phidget_jni.h"
+#include "com_phidgets_LEDPhidget.h"
+#include "../cphidgetled.h"
+
+JNI_LOAD(accel, LED)
+}
+
+JNI_CREATE(LED)
+JNI_INDEXED_GETFUNC(LED, DiscreteLED, DiscreteLED, jint)
+JNI_INDEXED_SETFUNC(LED, DiscreteLED, DiscreteLED, jint)
+JNI_GETFUNC(LED, LEDCount, LEDCount, jint)
+
+JNIEXPORT jint JNICALL
+Java_com_phidgets_LEDPhidget_getCurrentLimit(JNIEnv *env, jobject obj)
+{
+ CPhidgetLEDHandle h = (CPhidgetLEDHandle)(uintptr_t)
+ (*env)->GetLongField(env, obj, handle_fid);
+ int error;
+ CPhidgetLED_CurrentLimit v;
+ if ((error = CPhidgetLED_getCurrentLimit(h, &v)))
+ PH_THROW(error);
+ return (jint)v;
+}
+JNI_SETFUNC(LED, CurrentLimit, CurrentLimit, jint)
+
+JNIEXPORT jint JNICALL
+Java_com_phidgets_LEDPhidget_getVoltage(JNIEnv *env, jobject obj)
+{
+ CPhidgetLEDHandle h = (CPhidgetLEDHandle)(uintptr_t)
+ (*env)->GetLongField(env, obj, handle_fid);
+ int error;
+ CPhidgetLED_Voltage v;
+ if ((error = CPhidgetLED_getVoltage(h, &v)))
+ PH_THROW(error);
+ return (jint)v;
+}
+JNI_SETFUNC(LED, Voltage, Voltage, jint) \ No newline at end of file
diff --git a/Java/com_phidgets_LEDPhidget.h b/Java/com_phidgets_LEDPhidget.h
new file mode 100644
index 0000000..be631c8
--- /dev/null
+++ b/Java/com_phidgets_LEDPhidget.h
@@ -0,0 +1,237 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class com_phidgets_LEDPhidget */
+
+#ifndef _Included_com_phidgets_LEDPhidget
+#define _Included_com_phidgets_LEDPhidget
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef com_phidgets_LEDPhidget_PHIDGET_LOG_CRITICAL
+#define com_phidgets_LEDPhidget_PHIDGET_LOG_CRITICAL 1L
+#undef com_phidgets_LEDPhidget_PHIDGET_LOG_ERROR
+#define com_phidgets_LEDPhidget_PHIDGET_LOG_ERROR 2L
+#undef com_phidgets_LEDPhidget_PHIDGET_LOG_WARNING
+#define com_phidgets_LEDPhidget_PHIDGET_LOG_WARNING 3L
+#undef com_phidgets_LEDPhidget_PHIDGET_LOG_DEBUG
+#define com_phidgets_LEDPhidget_PHIDGET_LOG_DEBUG 4L
+#undef com_phidgets_LEDPhidget_PHIDGET_LOG_INFO
+#define com_phidgets_LEDPhidget_PHIDGET_LOG_INFO 5L
+#undef com_phidgets_LEDPhidget_PHIDGET_LOG_VERBOSE
+#define com_phidgets_LEDPhidget_PHIDGET_LOG_VERBOSE 6L
+#undef com_phidgets_LEDPhidget_PHIDID_NOTHING
+#define com_phidgets_LEDPhidget_PHIDID_NOTHING 1L
+#undef com_phidgets_LEDPhidget_PHIDID_ACCELEROMETER_3AXIS
+#define com_phidgets_LEDPhidget_PHIDID_ACCELEROMETER_3AXIS 126L
+#undef com_phidgets_LEDPhidget_PHIDID_ADVANCEDSERVO_1MOTOR
+#define com_phidgets_LEDPhidget_PHIDID_ADVANCEDSERVO_1MOTOR 130L
+#undef com_phidgets_LEDPhidget_PHIDID_ANALOG_4OUTPUT
+#define com_phidgets_LEDPhidget_PHIDID_ANALOG_4OUTPUT 55L
+#undef com_phidgets_LEDPhidget_PHIDID_ADVANCEDSERVO_8MOTOR
+#define com_phidgets_LEDPhidget_PHIDID_ADVANCEDSERVO_8MOTOR 58L
+#undef com_phidgets_LEDPhidget_PHIDID_BIPOLAR_STEPPER_1MOTOR
+#define com_phidgets_LEDPhidget_PHIDID_BIPOLAR_STEPPER_1MOTOR 123L
+#undef com_phidgets_LEDPhidget_PHIDID_BRIDGE_4INPUT
+#define com_phidgets_LEDPhidget_PHIDID_BRIDGE_4INPUT 59L
+#undef com_phidgets_LEDPhidget_PHIDID_ENCODER_1ENCODER_1INPUT
+#define com_phidgets_LEDPhidget_PHIDID_ENCODER_1ENCODER_1INPUT 75L
+#undef com_phidgets_LEDPhidget_PHIDID_ENCODER_HS_1ENCODER
+#define com_phidgets_LEDPhidget_PHIDID_ENCODER_HS_1ENCODER 128L
+#undef com_phidgets_LEDPhidget_PHIDID_ENCODER_HS_4ENCODER_4INPUT
+#define com_phidgets_LEDPhidget_PHIDID_ENCODER_HS_4ENCODER_4INPUT 79L
+#undef com_phidgets_LEDPhidget_PHIDID_FREQUENCYCOUNTER_2INPUT
+#define com_phidgets_LEDPhidget_PHIDID_FREQUENCYCOUNTER_2INPUT 53L
+#undef com_phidgets_LEDPhidget_PHIDID_GPS
+#define com_phidgets_LEDPhidget_PHIDID_GPS 121L
+#undef com_phidgets_LEDPhidget_PHIDID_INTERFACEKIT_0_0_4
+#define com_phidgets_LEDPhidget_PHIDID_INTERFACEKIT_0_0_4 64L
+#undef com_phidgets_LEDPhidget_PHIDID_INTERFACEKIT_0_0_8
+#define com_phidgets_LEDPhidget_PHIDID_INTERFACEKIT_0_0_8 129L
+#undef com_phidgets_LEDPhidget_PHIDID_INTERFACEKIT_0_16_16
+#define com_phidgets_LEDPhidget_PHIDID_INTERFACEKIT_0_16_16 68L
+#undef com_phidgets_LEDPhidget_PHIDID_INTERFACEKIT_8_8_8
+#define com_phidgets_LEDPhidget_PHIDID_INTERFACEKIT_8_8_8 69L
+#undef com_phidgets_LEDPhidget_PHIDID_INTERFACEKIT_8_8_8_w_LCD
+#define com_phidgets_LEDPhidget_PHIDID_INTERFACEKIT_8_8_8_w_LCD 125L
+#undef com_phidgets_LEDPhidget_PHIDID_IR
+#define com_phidgets_LEDPhidget_PHIDID_IR 77L
+#undef com_phidgets_LEDPhidget_PHIDID_LED_64
+#define com_phidgets_LEDPhidget_PHIDID_LED_64 74L
+#undef com_phidgets_LEDPhidget_PHIDID_LED_64_ADV
+#define com_phidgets_LEDPhidget_PHIDID_LED_64_ADV 76L
+#undef com_phidgets_LEDPhidget_PHIDID_LINEAR_TOUCH
+#define com_phidgets_LEDPhidget_PHIDID_LINEAR_TOUCH 118L
+#undef com_phidgets_LEDPhidget_PHIDID_MOTORCONTROL_HC_2MOTOR
+#define com_phidgets_LEDPhidget_PHIDID_MOTORCONTROL_HC_2MOTOR 89L
+#undef com_phidgets_LEDPhidget_PHIDID_MOTORCONTROL_LV_2MOTOR_4INPUT
+#define com_phidgets_LEDPhidget_PHIDID_MOTORCONTROL_LV_2MOTOR_4INPUT 88L
+#undef com_phidgets_LEDPhidget_PHIDID_MOTORCONTROL_1MOTOR
+#define com_phidgets_LEDPhidget_PHIDID_MOTORCONTROL_1MOTOR 62L
+#undef com_phidgets_LEDPhidget_PHIDID_PHSENSOR
+#define com_phidgets_LEDPhidget_PHIDID_PHSENSOR 116L
+#undef com_phidgets_LEDPhidget_PHIDID_RFID_2OUTPUT
+#define com_phidgets_LEDPhidget_PHIDID_RFID_2OUTPUT 49L
+#undef com_phidgets_LEDPhidget_PHIDID_ROTARY_TOUCH
+#define com_phidgets_LEDPhidget_PHIDID_ROTARY_TOUCH 119L
+#undef com_phidgets_LEDPhidget_PHIDID_SERVO_1MOTOR
+#define com_phidgets_LEDPhidget_PHIDID_SERVO_1MOTOR 57L
+#undef com_phidgets_LEDPhidget_PHIDID_SPATIAL_ACCEL_3AXIS
+#define com_phidgets_LEDPhidget_PHIDID_SPATIAL_ACCEL_3AXIS 127L
+#undef com_phidgets_LEDPhidget_PHIDID_SPATIAL_ACCEL_GYRO_COMPASS
+#define com_phidgets_LEDPhidget_PHIDID_SPATIAL_ACCEL_GYRO_COMPASS 51L
+#undef com_phidgets_LEDPhidget_PHIDID_TEMPERATURESENSOR
+#define com_phidgets_LEDPhidget_PHIDID_TEMPERATURESENSOR 112L
+#undef com_phidgets_LEDPhidget_PHIDID_TEMPERATURESENSOR_4
+#define com_phidgets_LEDPhidget_PHIDID_TEMPERATURESENSOR_4 50L
+#undef com_phidgets_LEDPhidget_PHIDID_TEXTLCD_2x20_w_8_8_8
+#define com_phidgets_LEDPhidget_PHIDID_TEXTLCD_2x20_w_8_8_8 381L
+#undef com_phidgets_LEDPhidget_PHIDID_TEXTLCD_ADAPTER
+#define com_phidgets_LEDPhidget_PHIDID_TEXTLCD_ADAPTER 61L
+#undef com_phidgets_LEDPhidget_PHIDID_UNIPOLAR_STEPPER_4MOTOR
+#define com_phidgets_LEDPhidget_PHIDID_UNIPOLAR_STEPPER_4MOTOR 122L
+#undef com_phidgets_LEDPhidget_PHIDID_ACCELEROMETER_2AXIS
+#define com_phidgets_LEDPhidget_PHIDID_ACCELEROMETER_2AXIS 113L
+#undef com_phidgets_LEDPhidget_PHIDID_INTERFACEKIT_0_8_8_w_LCD
+#define com_phidgets_LEDPhidget_PHIDID_INTERFACEKIT_0_8_8_w_LCD 83L
+#undef com_phidgets_LEDPhidget_PHIDID_INTERFACEKIT_4_8_8
+#define com_phidgets_LEDPhidget_PHIDID_INTERFACEKIT_4_8_8 4L
+#undef com_phidgets_LEDPhidget_PHIDID_RFID
+#define com_phidgets_LEDPhidget_PHIDID_RFID 48L
+#undef com_phidgets_LEDPhidget_PHIDID_SERVO_1MOTOR_OLD
+#define com_phidgets_LEDPhidget_PHIDID_SERVO_1MOTOR_OLD 2L
+#undef com_phidgets_LEDPhidget_PHIDID_SERVO_4MOTOR
+#define com_phidgets_LEDPhidget_PHIDID_SERVO_4MOTOR 56L
+#undef com_phidgets_LEDPhidget_PHIDID_SERVO_4MOTOR_OLD
+#define com_phidgets_LEDPhidget_PHIDID_SERVO_4MOTOR_OLD 3L
+#undef com_phidgets_LEDPhidget_PHIDID_TEXTLCD_2x20
+#define com_phidgets_LEDPhidget_PHIDID_TEXTLCD_2x20 82L
+#undef com_phidgets_LEDPhidget_PHIDID_TEXTLCD_2x20_w_0_8_8
+#define com_phidgets_LEDPhidget_PHIDID_TEXTLCD_2x20_w_0_8_8 339L
+#undef com_phidgets_LEDPhidget_PHIDID_TEXTLED_1x8
+#define com_phidgets_LEDPhidget_PHIDID_TEXTLED_1x8 73L
+#undef com_phidgets_LEDPhidget_PHIDID_TEXTLED_4x8
+#define com_phidgets_LEDPhidget_PHIDID_TEXTLED_4x8 72L
+#undef com_phidgets_LEDPhidget_PHIDID_WEIGHTSENSOR
+#define com_phidgets_LEDPhidget_PHIDID_WEIGHTSENSOR 114L
+#undef com_phidgets_LEDPhidget_PHIDCLASS_NOTHING
+#define com_phidgets_LEDPhidget_PHIDCLASS_NOTHING 1L
+#undef com_phidgets_LEDPhidget_PHIDCLASS_ACCELEROMETER
+#define com_phidgets_LEDPhidget_PHIDCLASS_ACCELEROMETER 2L
+#undef com_phidgets_LEDPhidget_PHIDCLASS_ADVANCEDSERVO
+#define com_phidgets_LEDPhidget_PHIDCLASS_ADVANCEDSERVO 3L
+#undef com_phidgets_LEDPhidget_PHIDCLASS_ANALOG
+#define com_phidgets_LEDPhidget_PHIDCLASS_ANALOG 22L
+#undef com_phidgets_LEDPhidget_PHIDCLASS_BRIDGE
+#define com_phidgets_LEDPhidget_PHIDCLASS_BRIDGE 23L
+#undef com_phidgets_LEDPhidget_PHIDCLASS_ENCODER
+#define com_phidgets_LEDPhidget_PHIDCLASS_ENCODER 4L
+#undef com_phidgets_LEDPhidget_PHIDCLASS_FREQUENCYCOUNTER
+#define com_phidgets_LEDPhidget_PHIDCLASS_FREQUENCYCOUNTER 21L
+#undef com_phidgets_LEDPhidget_PHIDCLASS_GPS
+#define com_phidgets_LEDPhidget_PHIDCLASS_GPS 5L
+#undef com_phidgets_LEDPhidget_PHIDCLASS_INTERFACEKIT
+#define com_phidgets_LEDPhidget_PHIDCLASS_INTERFACEKIT 7L
+#undef com_phidgets_LEDPhidget_PHIDCLASS_LED
+#define com_phidgets_LEDPhidget_PHIDCLASS_LED 8L
+#undef com_phidgets_LEDPhidget_PHIDCLASS_MOTORCONTROL
+#define com_phidgets_LEDPhidget_PHIDCLASS_MOTORCONTROL 9L
+#undef com_phidgets_LEDPhidget_PHIDCLASS_PHSENSOR
+#define com_phidgets_LEDPhidget_PHIDCLASS_PHSENSOR 10L
+#undef com_phidgets_LEDPhidget_PHIDCLASS_RFID
+#define com_phidgets_LEDPhidget_PHIDCLASS_RFID 11L
+#undef com_phidgets_LEDPhidget_PHIDCLASS_SERVO
+#define com_phidgets_LEDPhidget_PHIDCLASS_SERVO 12L
+#undef com_phidgets_LEDPhidget_PHIDCLASS_STEPPER
+#define com_phidgets_LEDPhidget_PHIDCLASS_STEPPER 13L
+#undef com_phidgets_LEDPhidget_PHIDCLASS_TEMPERATURESENSOR
+#define com_phidgets_LEDPhidget_PHIDCLASS_TEMPERATURESENSOR 14L
+#undef com_phidgets_LEDPhidget_PHIDCLASS_TEXTLCD
+#define com_phidgets_LEDPhidget_PHIDCLASS_TEXTLCD 15L
+#undef com_phidgets_LEDPhidget_PHIDCLASS_TEXTLED
+#define com_phidgets_LEDPhidget_PHIDCLASS_TEXTLED 16L
+#undef com_phidgets_LEDPhidget_PHIDCLASS_WEIGHTSENSOR
+#define com_phidgets_LEDPhidget_PHIDCLASS_WEIGHTSENSOR 17L
+#undef com_phidgets_LEDPhidget_PHIDGET_LED_CURRENT_LIMIT_20mA
+#define com_phidgets_LEDPhidget_PHIDGET_LED_CURRENT_LIMIT_20mA 1L
+#undef com_phidgets_LEDPhidget_PHIDGET_LED_CURRENT_LIMIT_40mA
+#define com_phidgets_LEDPhidget_PHIDGET_LED_CURRENT_LIMIT_40mA 2L
+#undef com_phidgets_LEDPhidget_PHIDGET_LED_CURRENT_LIMIT_60mA
+#define com_phidgets_LEDPhidget_PHIDGET_LED_CURRENT_LIMIT_60mA 3L
+#undef com_phidgets_LEDPhidget_PHIDGET_LED_CURRENT_LIMIT_80mA
+#define com_phidgets_LEDPhidget_PHIDGET_LED_CURRENT_LIMIT_80mA 4L
+#undef com_phidgets_LEDPhidget_PHIDGET_LED_VOLTAGE_1_7V
+#define com_phidgets_LEDPhidget_PHIDGET_LED_VOLTAGE_1_7V 1L
+#undef com_phidgets_LEDPhidget_PHIDGET_LED_VOLTAGE_2_75V
+#define com_phidgets_LEDPhidget_PHIDGET_LED_VOLTAGE_2_75V 2L
+#undef com_phidgets_LEDPhidget_PHIDGET_LED_VOLTAGE_3_9V
+#define com_phidgets_LEDPhidget_PHIDGET_LED_VOLTAGE_3_9V 3L
+#undef com_phidgets_LEDPhidget_PHIDGET_LED_VOLTAGE_5_0V
+#define com_phidgets_LEDPhidget_PHIDGET_LED_VOLTAGE_5_0V 4L
+/*
+ * Class: com_phidgets_LEDPhidget
+ * Method: create
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL Java_com_phidgets_LEDPhidget_create
+ (JNIEnv *, jclass);
+
+/*
+ * Class: com_phidgets_LEDPhidget
+ * Method: getCurrentLimit
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_phidgets_LEDPhidget_getCurrentLimit
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_LEDPhidget
+ * Method: setCurrentLimit
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_LEDPhidget_setCurrentLimit
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_LEDPhidget
+ * Method: getVoltage
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_phidgets_LEDPhidget_getVoltage
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_LEDPhidget
+ * Method: setVoltage
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_LEDPhidget_setVoltage
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_LEDPhidget
+ * Method: getLEDCount
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_phidgets_LEDPhidget_getLEDCount
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_LEDPhidget
+ * Method: getDiscreteLED
+ * Signature: (I)I
+ */
+JNIEXPORT jint JNICALL Java_com_phidgets_LEDPhidget_getDiscreteLED
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_LEDPhidget
+ * Method: setDiscreteLED
+ * Signature: (II)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_LEDPhidget_setDiscreteLED
+ (JNIEnv *, jobject, jint, jint);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/Java/com_phidgets_Manager.c b/Java/com_phidgets_Manager.c
new file mode 100644
index 0000000..95e131a
--- /dev/null
+++ b/Java/com_phidgets_Manager.c
@@ -0,0 +1,392 @@
+#include "../stdafx.h"
+#include <stdlib.h>
+#include "com_phidgets_Manager.h"
+#include "../cphidgetmanager.h"
+#include "../csocket.h"
+#include "phidget_jni.h"
+
+static int CCONV attach_handler(CPhidgetHandle h, void *arg);
+static int CCONV detach_handler(CPhidgetHandle h, void *arg);
+static int CCONV serverConnect_handler(CPhidgetManagerHandle h, void *arg);
+static int CCONV serverDisconnect_handler(CPhidgetManagerHandle h, void *arg);
+
+extern jfieldID managerPhidget_fid;
+
+static jclass manager_class;
+
+static jfieldID manager_handle_fid;
+static jfieldID nativeAttachHandler_fid;
+static jfieldID nativeDetachHandler_fid;
+static jfieldID nativeServerConnectHandler_fid;
+static jfieldID nativeServerDisconnectHandler_fid;
+
+static jmethodID fireAttach_mid;
+static jmethodID fireDetach_mid;
+static jmethodID fireServerConnect_mid;
+static jmethodID fireServerDisconnect_mid;
+
+void
+com_phidgets_Manager_OnLoad(JNIEnv *env)
+{
+ //Manager
+ if (!(manager_class = (*env)->FindClass(env, "com/phidgets/Manager")))
+ JNI_ABORT_STDERR("");
+ if (!(manager_class = (jclass)(*env)->NewGlobalRef(env, manager_class)))
+ JNI_ABORT_STDERR("");
+
+ if (!(manager_handle_fid = (*env)->GetFieldID(env, manager_class, "handle", "J")))
+ JNI_ABORT_STDERR("");
+ if (!(nativeAttachHandler_fid = (*env)->GetFieldID(env, manager_class, "nativeAttachHandler", "J")))
+ JNI_ABORT_STDERR("");
+ if (!(nativeDetachHandler_fid = (*env)->GetFieldID(env, manager_class, "nativeDetachHandler", "J")))
+ JNI_ABORT_STDERR("");
+ if (!(nativeServerConnectHandler_fid = (*env)->GetFieldID(env, manager_class, "nativeServerConnectHandler", "J")))
+ JNI_ABORT_STDERR("");
+ if (!(nativeServerDisconnectHandler_fid = (*env)->GetFieldID(env, manager_class, "nativeServerDisconnectHandler", "J")))
+ JNI_ABORT_STDERR("");
+
+ if (!(fireAttach_mid = (*env)->GetMethodID(env, manager_class, "fireAttach", "(Lcom/phidgets/event/AttachEvent;)V")))
+ JNI_ABORT_STDERR("");
+ if (!(fireDetach_mid = (*env)->GetMethodID(env, manager_class, "fireDetach", "(Lcom/phidgets/event/DetachEvent;)V")))
+ JNI_ABORT_STDERR("");
+ if (!(fireServerConnect_mid = (*env)->GetMethodID(env, manager_class, "fireServerConnect", "(Lcom/phidgets/event/ServerConnectEvent;)V")))
+ JNI_ABORT_STDERR("");
+ if (!(fireServerDisconnect_mid = (*env)->GetMethodID(env, manager_class, "fireServerDisconnect", "(Lcom/phidgets/event/ServerDisconnectEvent;)V")))
+ JNI_ABORT_STDERR("");
+}
+
+JNIEXPORT jboolean JNICALL
+Java_com_phidgets_Manager_isAttached(JNIEnv *env, jobject obj)
+{
+ CPhidgetHandle h = (CPhidgetHandle)(uintptr_t)(*env)->GetLongField(env,
+ obj, manager_handle_fid);
+ int error;
+ int s;
+
+ if ((error = CPhidget_getDeviceStatus(h, &s)))
+ PH_THROW(error);
+
+ return s == PHIDGET_ATTACHED;
+}
+
+JNIEXPORT jboolean JNICALL
+Java_com_phidgets_Manager_isAttachedToServer(JNIEnv *env, jobject obj)
+{
+ CPhidgetManagerHandle h = (CPhidgetManagerHandle)(uintptr_t)(*env)->GetLongField(env,
+ obj, manager_handle_fid);
+ int error;
+ int s;
+
+ if ((error = CPhidgetManager_getServerStatus(h, &s)))
+ PH_THROW(error);
+
+ return s == PHIDGET_ATTACHED;
+}
+
+JNIEXPORT jint JNICALL
+Java_com_phidgets_Manager_getServerPort(JNIEnv *env, jobject obj)
+{
+ CPhidgetManagerHandle h = (CPhidgetManagerHandle)(uintptr_t)(*env)->GetLongField(env,
+ obj, manager_handle_fid);
+ int error;
+ int port;
+ const char *addr;
+
+ if ((error = CPhidgetManager_getServerAddress(h, &addr, &port)))
+ PH_THROW(error);
+
+ return port;
+}
+
+JNIEXPORT jstring JNICALL
+Java_com_phidgets_Manager_getServerAddress(JNIEnv *env, jobject obj)
+{
+ CPhidgetManagerHandle h = (CPhidgetManagerHandle)(uintptr_t)(*env)->GetLongField(env,
+ obj, manager_handle_fid);
+ int error;
+ int port;
+ const char *addr;
+
+ if ((error = CPhidgetManager_getServerAddress(h, &addr, &port)))
+ PH_THROW(error);
+
+ return (*env)->NewStringUTF(env, addr);
+}
+
+JNIEXPORT jstring JNICALL
+Java_com_phidgets_Manager_getServerID(JNIEnv *env, jobject obj)
+{
+ CPhidgetManagerHandle h = (CPhidgetManagerHandle)(uintptr_t)(*env)->GetLongField(env,
+ obj, manager_handle_fid);
+ int error;
+ const char *id;
+
+ if ((error = CPhidgetManager_getServerID(h, &id)))
+ PH_THROW(error);
+
+ return (*env)->NewStringUTF(env, id);
+}
+
+JNIEXPORT void JNICALL
+Java_com_phidgets_Manager_enableManagerAttachEvents(JNIEnv *env, jobject obj,
+ jboolean b)
+{
+ jlong gr = updateGlobalRef(env, obj, nativeAttachHandler_fid, b);
+
+ CPhidgetManagerHandle h = (CPhidgetManagerHandle)(uintptr_t)
+ (*env)->GetLongField(env, obj, manager_handle_fid);
+
+ CPhidgetManager_set_OnAttach_Handler(h, b ? attach_handler : 0,
+ (void *)(uintptr_t)gr);
+}
+
+static int CCONV
+attach_handler(CPhidgetHandle h, void *arg)
+{
+ JNIEnv *env;
+ jobject obj;
+ jobject device;
+ jobject attachEvent;
+ jlong devhandle;
+
+ //could pass this to AttachCurrentThread for named threads.
+ //Test first!
+ JavaVMAttachArgs args;
+ args.version = JNI_VERSION_1_2;
+ args.name = "Central Thread";
+ args.group = NULL;
+
+ if ((*ph_vm)->AttachCurrentThread(ph_vm, (JNIEnvPtr)&env, NULL))
+ JNI_ABORT_STDERR("Couldn't AttachCurrentThread");
+
+ obj = (jobject)arg;
+ devhandle = (jlong)(uintptr_t)h;
+
+ if (!(device = (*env)->NewObject(env, phidget_class, phidget_cons,
+ devhandle)))
+ return -1;
+
+ (*env)->SetBooleanField(env, device, managerPhidget_fid, JNI_TRUE);
+
+ if (!(attachEvent = (*env)->NewObject(env, attachEvent_class, attachEvent_cons,
+ device)))
+ return -1;
+ (*env)->CallVoidMethod(env, obj, fireAttach_mid, attachEvent);
+ (*env)->DeleteLocalRef(env, device);
+ (*env)->DeleteLocalRef(env, attachEvent);
+ (*ph_vm)->DetachCurrentThread(ph_vm);
+
+ return 0;
+}
+
+JNIEXPORT void JNICALL
+Java_com_phidgets_Manager_enableManagerDetachEvents(JNIEnv *env, jobject obj,
+ jboolean b)
+{
+ jlong gr = updateGlobalRef(env, obj, nativeDetachHandler_fid, b);
+
+ CPhidgetManagerHandle h = (CPhidgetManagerHandle)(uintptr_t)
+ (*env)->GetLongField(env, obj, manager_handle_fid);
+
+ CPhidgetManager_set_OnDetach_Handler(h, b ? detach_handler : 0, (void *)(uintptr_t)gr);
+}
+
+static int CCONV
+detach_handler(CPhidgetHandle h, void *arg)
+{
+ JNIEnv *env;
+ jobject obj;
+ jobject device;
+ jobject detachEvent;
+ jlong devhandle;
+
+ if ((*ph_vm)->AttachCurrentThread(ph_vm, (JNIEnvPtr)&env, NULL))
+ JNI_ABORT_STDERR("Couldn't AttachCurrentThread");
+
+ obj = (jobject)arg;
+ devhandle = (jlong)(uintptr_t)h;
+
+ if (!(device = (*env)->NewObject(env, phidget_class, phidget_cons,
+ devhandle)))
+ return -1;
+
+ (*env)->SetBooleanField(env, device, managerPhidget_fid, JNI_TRUE);
+
+ if (!(detachEvent = (*env)->NewObject(env, detachEvent_class, detachEvent_cons,
+ device)))
+ return -1;
+ (*env)->CallVoidMethod(env, obj, fireDetach_mid, detachEvent);
+ (*env)->DeleteLocalRef(env, device);
+ (*env)->DeleteLocalRef(env, detachEvent);
+ (*ph_vm)->DetachCurrentThread(ph_vm);
+
+ return 0;
+}
+
+JNIEXPORT void JNICALL
+Java_com_phidgets_Manager_enableServerConnectEvents(JNIEnv *env, jobject obj,
+ jboolean b)
+{
+ jlong gr = updateGlobalRef(env, obj, nativeServerConnectHandler_fid, b);
+ CPhidgetManagerHandle h = (CPhidgetManagerHandle)(uintptr_t)(*env)->GetLongField(env,
+ obj, manager_handle_fid);
+
+ CPhidgetManager_set_OnServerConnect_Handler(h, b ? serverConnect_handler : 0,
+ (void *)(uintptr_t)gr);
+}
+
+static int CCONV
+serverConnect_handler(CPhidgetManagerHandle h, void *arg)
+{
+ JNIEnv *env;
+ jobject obj;
+ jobject serverConnectEvent;
+ jint result;
+
+ result = (*ph_vm)->GetEnv(ph_vm, (void **)&env, JNI_VERSION_1_4);
+
+ if(result == JNI_EDETACHED)
+ {
+ if ((*ph_vm)->AttachCurrentThread(ph_vm, (JNIEnvPtr)&env, NULL))
+ JNI_ABORT_STDERR("Couldn't AttachCurrentThread");
+ }
+
+ obj = (jobject)arg;
+
+ if (!(serverConnectEvent = (*env)->NewObject(env, serverConnectEvent_class, serverConnectEvent_cons,
+ obj)))
+ return -1;
+ (*env)->CallVoidMethod(env, obj, fireServerConnect_mid, serverConnectEvent);
+ (*env)->DeleteLocalRef(env, serverConnectEvent);
+ (*ph_vm)->DetachCurrentThread(ph_vm);
+
+ return 0;
+}
+
+JNIEXPORT void JNICALL
+Java_com_phidgets_Manager_enableServerDisconnectEvents(JNIEnv *env, jobject obj,
+ jboolean b)
+{
+ jlong gr = updateGlobalRef(env, obj, nativeServerDisconnectHandler_fid, b);
+ CPhidgetManagerHandle h = (CPhidgetManagerHandle)(uintptr_t)(*env)->GetLongField(env,
+ obj, manager_handle_fid);
+
+ CPhidgetManager_set_OnServerDisconnect_Handler(h, b ? serverDisconnect_handler : 0,
+ (void *)(uintptr_t)gr);
+}
+
+static int CCONV
+serverDisconnect_handler(CPhidgetManagerHandle h, void *arg)
+{
+ JNIEnv *env;
+ jobject obj;
+ jobject serverDisconnectEvent;
+ jint result;
+
+ result = (*ph_vm)->GetEnv(ph_vm, (void **)&env, JNI_VERSION_1_4);
+
+ if(result == JNI_EDETACHED)
+ {
+ if ((*ph_vm)->AttachCurrentThread(ph_vm, (JNIEnvPtr)&env, NULL))
+ JNI_ABORT_STDERR("Couldn't AttachCurrentThread");
+ }
+
+ obj = (jobject)arg;
+
+ if (!(serverDisconnectEvent = (*env)->NewObject(env, serverDisconnectEvent_class, serverDisconnectEvent_cons,
+ obj)))
+ return -1;
+ (*env)->CallVoidMethod(env, obj, fireServerDisconnect_mid, serverDisconnectEvent);
+ (*env)->DeleteLocalRef(env, serverDisconnectEvent);
+ (*ph_vm)->DetachCurrentThread(ph_vm);
+
+ return 0;
+}
+
+JNIEXPORT void JNICALL
+Java_com_phidgets_Manager_nativeOpen(JNIEnv *env, jobject obj)
+{
+ int error;
+
+ CPhidgetManagerHandle h = (CPhidgetManagerHandle)(uintptr_t)
+ (*env)->GetLongField(env, obj, manager_handle_fid);
+
+ if ((error = CPhidgetManager_open(h)))
+ PH_THROW(error);
+}
+
+JNIEXPORT void JNICALL
+Java_com_phidgets_Manager_nativeOpenRemote(JNIEnv *env, jobject obj, jstring serverID, jstring pass)
+{
+ int error;
+ jboolean iscopy;
+ const char *serverIDcopy = serverID?(*env)->GetStringUTFChars(
+ env, serverID, &iscopy):0;
+ const char *passcopy = (*env)->GetStringUTFChars(
+ env, pass, &iscopy);
+
+ CPhidgetManagerHandle h = (CPhidgetManagerHandle)(uintptr_t)
+ (*env)->GetLongField(env, obj, manager_handle_fid);
+
+ if ((error = CPhidgetManager_openRemote(h, serverIDcopy, passcopy)))
+ PH_THROW(error);
+
+ if(serverID)
+ (*env)->ReleaseStringUTFChars(env, serverID, serverIDcopy);
+ (*env)->ReleaseStringUTFChars(env, pass, passcopy);
+}
+
+JNIEXPORT void JNICALL
+Java_com_phidgets_Manager_nativeOpenRemoteIP(JNIEnv *env, jobject obj, jstring ipAddr, jint port, jstring pass)
+{
+ int error;
+ jboolean iscopy;
+ const char *ipAddrcopy = (*env)->GetStringUTFChars(
+ env, ipAddr, &iscopy);
+ const char *passcopy = (*env)->GetStringUTFChars(
+ env, pass, &iscopy);
+
+ CPhidgetManagerHandle h = (CPhidgetManagerHandle)(uintptr_t)
+ (*env)->GetLongField(env, obj, manager_handle_fid);
+
+ if ((error = CPhidgetManager_openRemoteIP(h, ipAddrcopy, port, passcopy)))
+ PH_THROW(error);
+
+ (*env)->ReleaseStringUTFChars(env, ipAddr, ipAddrcopy);
+ (*env)->ReleaseStringUTFChars(env, pass, passcopy);
+}
+
+JNIEXPORT void JNICALL
+Java_com_phidgets_Manager_nativeDelete(JNIEnv *env, jobject obj)
+{
+ int error;
+
+ CPhidgetManagerHandle h = (CPhidgetManagerHandle)(uintptr_t)
+ (*env)->GetLongField(env, obj, manager_handle_fid);
+
+ if ((error = CPhidgetManager_delete(h)))
+ PH_THROW(error);
+}
+
+JNIEXPORT void JNICALL
+Java_com_phidgets_Manager_nativeClose(JNIEnv *env, jobject obj)
+{
+ int error;
+
+ CPhidgetManagerHandle h = (CPhidgetManagerHandle)(uintptr_t)
+ (*env)->GetLongField(env, obj, manager_handle_fid);
+
+ if ((error = CPhidgetManager_close(h)))
+ PH_THROW(error);
+}
+
+JNIEXPORT jlong JNICALL
+Java_com_phidgets_Manager_create(JNIEnv *env, jobject obj)
+{
+ int error;
+ CPhidgetManagerHandle phidm;
+
+ if ((error = CPhidgetManager_create(&phidm)))
+ PH_THROW(error);
+ return (jlong)(uintptr_t)phidm;
+}
diff --git a/Java/com_phidgets_Manager.h b/Java/com_phidgets_Manager.h
new file mode 100644
index 0000000..5dcf1a5
--- /dev/null
+++ b/Java/com_phidgets_Manager.h
@@ -0,0 +1,133 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class com_phidgets_Manager */
+
+#ifndef _Included_com_phidgets_Manager
+#define _Included_com_phidgets_Manager
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: com_phidgets_Manager
+ * Method: create
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL Java_com_phidgets_Manager_create
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_Manager
+ * Method: getServerAddress
+ * Signature: ()Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_com_phidgets_Manager_getServerAddress
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_Manager
+ * Method: getServerID
+ * Signature: ()Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_com_phidgets_Manager_getServerID
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_Manager
+ * Method: getServerPort
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_phidgets_Manager_getServerPort
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_Manager
+ * Method: isAttached
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_phidgets_Manager_isAttached
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_Manager
+ * Method: isAttachedToServer
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_phidgets_Manager_isAttachedToServer
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_Manager
+ * Method: nativeClose
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_Manager_nativeClose
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_Manager
+ * Method: nativeDelete
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_Manager_nativeDelete
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_Manager
+ * Method: nativeOpen
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_Manager_nativeOpen
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_Manager
+ * Method: nativeOpenRemote
+ * Signature: (Ljava/lang/String;Ljava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_Manager_nativeOpenRemote
+ (JNIEnv *, jobject, jstring, jstring);
+
+/*
+ * Class: com_phidgets_Manager
+ * Method: nativeOpenRemoteIP
+ * Signature: (Ljava/lang/String;ILjava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_Manager_nativeOpenRemoteIP
+ (JNIEnv *, jobject, jstring, jint, jstring);
+
+/*
+ * Class: com_phidgets_Manager
+ * Method: enableManagerAttachEvents
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_Manager_enableManagerAttachEvents
+ (JNIEnv *, jobject, jboolean);
+
+/*
+ * Class: com_phidgets_Manager
+ * Method: enableManagerDetachEvents
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_Manager_enableManagerDetachEvents
+ (JNIEnv *, jobject, jboolean);
+
+/*
+ * Class: com_phidgets_Manager
+ * Method: enableServerConnectEvents
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_Manager_enableServerConnectEvents
+ (JNIEnv *, jobject, jboolean);
+
+/*
+ * Class: com_phidgets_Manager
+ * Method: enableServerDisconnectEvents
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_Manager_enableServerDisconnectEvents
+ (JNIEnv *, jobject, jboolean);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/Java/com_phidgets_MotorControlPhidget.c b/Java/com_phidgets_MotorControlPhidget.c
new file mode 100644
index 0000000..582b1bd
--- /dev/null
+++ b/Java/com_phidgets_MotorControlPhidget.c
@@ -0,0 +1,75 @@
+#include "../stdafx.h"
+#include "phidget_jni.h"
+#include "com_phidgets_MotorControlPhidget.h"
+#include "../cphidgetmotorcontrol.h"
+
+EVENT_VARS(inputChange, InputChange)
+EVENT_VARS(motorVelocityChange, MotorVelocityChange)
+EVENT_VARS(currentChange, CurrentChange)
+EVENT_VARS(currentUpdate, CurrentUpdate)
+EVENT_VARS(encoderPositionChange, EncoderPositionChange)
+EVENT_VARS(encoderPositionUpdate, EncoderPositionUpdate)
+EVENT_VARS(backEMFUpdate, BackEMFUpdate)
+EVENT_VARS(sensorUpdate, SensorUpdate)
+
+JNI_LOAD(motor, MotorControl)
+ EVENT_VAR_SETUP(motor, inputChange, InputChange, IZ, V)
+ EVENT_VAR_SETUP(motor, motorVelocityChange, MotorVelocityChange, ID, V)
+ EVENT_VAR_SETUP(motor, currentChange, CurrentChange, ID, V)
+ EVENT_VAR_SETUP(motor, currentUpdate, CurrentUpdate, ID, V)
+ EVENT_VAR_SETUP(motor, encoderPositionChange, EncoderPositionChange, III, V)
+ EVENT_VAR_SETUP(motor, encoderPositionUpdate, EncoderPositionUpdate, II, V)
+ EVENT_VAR_SETUP(motor, backEMFUpdate, BackEMFUpdate, ID, V)
+ EVENT_VAR_SETUP(motor, sensorUpdate, SensorUpdate, II, V)
+
+}
+
+EVENT_HANDLER_INDEXED(MotorControl, inputChange, InputChange,
+ CPhidgetMotorControl_set_OnInputChange_Handler, int)
+EVENT_HANDLER_INDEXED(MotorControl, motorVelocityChange, MotorVelocityChange,
+ CPhidgetMotorControl_set_OnVelocityChange_Handler, double)
+EVENT_HANDLER_INDEXED(MotorControl, currentChange, CurrentChange,
+ CPhidgetMotorControl_set_OnCurrentChange_Handler, double)
+EVENT_HANDLER_INDEXED(MotorControl, currentUpdate, CurrentUpdate,
+ CPhidgetMotorControl_set_OnCurrentUpdate_Handler, double)
+EVENT_HANDLER_INDEXED2(MotorControl, encoderPositionChange, EncoderPositionChange,
+ CPhidgetMotorControl_set_OnEncoderPositionChange_Handler, int, int)
+EVENT_HANDLER_INDEXED(MotorControl, encoderPositionUpdate, EncoderPositionUpdate,
+ CPhidgetMotorControl_set_OnEncoderPositionUpdate_Handler, int)
+EVENT_HANDLER_INDEXED(MotorControl, backEMFUpdate, BackEMFUpdate,
+ CPhidgetMotorControl_set_OnBackEMFUpdate_Handler, double)
+EVENT_HANDLER_INDEXED(MotorControl, sensorUpdate, SensorUpdate,
+ CPhidgetMotorControl_set_OnSensorUpdate_Handler, int)
+
+
+JNI_CREATE(MotorControl)
+JNI_INDEXED_GETFUNC(MotorControl, Acceleration, Acceleration, jdouble)
+JNI_INDEXED_SETFUNC(MotorControl, Acceleration, Acceleration, jdouble)
+JNI_INDEXED_GETFUNC(MotorControl, AccelerationMin, AccelerationMin, jdouble)
+JNI_INDEXED_GETFUNC(MotorControl, AccelerationMax, AccelerationMax, jdouble)
+JNI_INDEXED_GETFUNC(MotorControl, Velocity, Velocity, jdouble)
+JNI_INDEXED_SETFUNC(MotorControl, Velocity, Velocity, jdouble)
+JNI_INDEXED_GETFUNC(MotorControl, Current, Current, jdouble)
+JNI_INDEXED_GETFUNCBOOL(MotorControl, InputState, InputState)
+
+JNI_INDEXED_GETFUNC(MotorControl, EncoderPosition, EncoderPosition, jint)
+JNI_INDEXED_SETFUNC(MotorControl, EncoderPosition, EncoderPosition, jint)
+JNI_INDEXED_GETFUNCBOOL(MotorControl, BackEMFSensingState, BackEMFSensingState)
+JNI_INDEXED_SETFUNC(MotorControl, BackEMFSensingState, BackEMFSensingState, jboolean)
+JNI_INDEXED_GETFUNC(MotorControl, BackEMF, BackEMF, jdouble)
+JNI_GETFUNC(MotorControl, SupplyVoltage, SupplyVoltage, jdouble)
+JNI_INDEXED_GETFUNC(MotorControl, Braking, Braking, jdouble)
+JNI_INDEXED_SETFUNC(MotorControl, Braking, Braking, jdouble)
+JNI_INDEXED_GETFUNC(MotorControl, SensorValue, SensorValue, jint)
+JNI_INDEXED_GETFUNC(MotorControl, SensorRawValue, SensorRawValue, jint)
+JNI_GETFUNCBOOL(MotorControl, Ratiometric, Ratiometric)
+JNI_SETFUNC(MotorControl, Ratiometric, Ratiometric, jboolean)
+
+JNI_GETFUNC(MotorControl, MotorCount, MotorCount, jint)
+JNI_GETFUNC(MotorControl, InputCount, InputCount, jint)
+JNI_GETFUNC(MotorControl, EncoderCount, EncoderCount, jint)
+JNI_GETFUNC(MotorControl, SensorCount, SensorCount, jint)
+
+//Deprecated
+JNI_INDEXED_GETFUNC(MotorControl, Speed, Velocity, jdouble)
+JNI_INDEXED_SETFUNC(MotorControl, Speed, Velocity, jdouble)
diff --git a/Java/com_phidgets_MotorControlPhidget.h b/Java/com_phidgets_MotorControlPhidget.h
new file mode 100644
index 0000000..790e336
--- /dev/null
+++ b/Java/com_phidgets_MotorControlPhidget.h
@@ -0,0 +1,437 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class com_phidgets_MotorControlPhidget */
+
+#ifndef _Included_com_phidgets_MotorControlPhidget
+#define _Included_com_phidgets_MotorControlPhidget
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef com_phidgets_MotorControlPhidget_PHIDGET_LOG_CRITICAL
+#define com_phidgets_MotorControlPhidget_PHIDGET_LOG_CRITICAL 1L
+#undef com_phidgets_MotorControlPhidget_PHIDGET_LOG_ERROR
+#define com_phidgets_MotorControlPhidget_PHIDGET_LOG_ERROR 2L
+#undef com_phidgets_MotorControlPhidget_PHIDGET_LOG_WARNING
+#define com_phidgets_MotorControlPhidget_PHIDGET_LOG_WARNING 3L
+#undef com_phidgets_MotorControlPhidget_PHIDGET_LOG_DEBUG
+#define com_phidgets_MotorControlPhidget_PHIDGET_LOG_DEBUG 4L
+#undef com_phidgets_MotorControlPhidget_PHIDGET_LOG_INFO
+#define com_phidgets_MotorControlPhidget_PHIDGET_LOG_INFO 5L
+#undef com_phidgets_MotorControlPhidget_PHIDGET_LOG_VERBOSE
+#define com_phidgets_MotorControlPhidget_PHIDGET_LOG_VERBOSE 6L
+#undef com_phidgets_MotorControlPhidget_PHIDID_NOTHING
+#define com_phidgets_MotorControlPhidget_PHIDID_NOTHING 1L
+#undef com_phidgets_MotorControlPhidget_PHIDID_ACCELEROMETER_3AXIS
+#define com_phidgets_MotorControlPhidget_PHIDID_ACCELEROMETER_3AXIS 126L
+#undef com_phidgets_MotorControlPhidget_PHIDID_ADVANCEDSERVO_1MOTOR
+#define com_phidgets_MotorControlPhidget_PHIDID_ADVANCEDSERVO_1MOTOR 130L
+#undef com_phidgets_MotorControlPhidget_PHIDID_ANALOG_4OUTPUT
+#define com_phidgets_MotorControlPhidget_PHIDID_ANALOG_4OUTPUT 55L
+#undef com_phidgets_MotorControlPhidget_PHIDID_ADVANCEDSERVO_8MOTOR
+#define com_phidgets_MotorControlPhidget_PHIDID_ADVANCEDSERVO_8MOTOR 58L
+#undef com_phidgets_MotorControlPhidget_PHIDID_BIPOLAR_STEPPER_1MOTOR
+#define com_phidgets_MotorControlPhidget_PHIDID_BIPOLAR_STEPPER_1MOTOR 123L
+#undef com_phidgets_MotorControlPhidget_PHIDID_BRIDGE_4INPUT
+#define com_phidgets_MotorControlPhidget_PHIDID_BRIDGE_4INPUT 59L
+#undef com_phidgets_MotorControlPhidget_PHIDID_ENCODER_1ENCODER_1INPUT
+#define com_phidgets_MotorControlPhidget_PHIDID_ENCODER_1ENCODER_1INPUT 75L
+#undef com_phidgets_MotorControlPhidget_PHIDID_ENCODER_HS_1ENCODER
+#define com_phidgets_MotorControlPhidget_PHIDID_ENCODER_HS_1ENCODER 128L
+#undef com_phidgets_MotorControlPhidget_PHIDID_ENCODER_HS_4ENCODER_4INPUT
+#define com_phidgets_MotorControlPhidget_PHIDID_ENCODER_HS_4ENCODER_4INPUT 79L
+#undef com_phidgets_MotorControlPhidget_PHIDID_FREQUENCYCOUNTER_2INPUT
+#define com_phidgets_MotorControlPhidget_PHIDID_FREQUENCYCOUNTER_2INPUT 53L
+#undef com_phidgets_MotorControlPhidget_PHIDID_GPS
+#define com_phidgets_MotorControlPhidget_PHIDID_GPS 121L
+#undef com_phidgets_MotorControlPhidget_PHIDID_INTERFACEKIT_0_0_4
+#define com_phidgets_MotorControlPhidget_PHIDID_INTERFACEKIT_0_0_4 64L
+#undef com_phidgets_MotorControlPhidget_PHIDID_INTERFACEKIT_0_0_8
+#define com_phidgets_MotorControlPhidget_PHIDID_INTERFACEKIT_0_0_8 129L
+#undef com_phidgets_MotorControlPhidget_PHIDID_INTERFACEKIT_0_16_16
+#define com_phidgets_MotorControlPhidget_PHIDID_INTERFACEKIT_0_16_16 68L
+#undef com_phidgets_MotorControlPhidget_PHIDID_INTERFACEKIT_8_8_8
+#define com_phidgets_MotorControlPhidget_PHIDID_INTERFACEKIT_8_8_8 69L
+#undef com_phidgets_MotorControlPhidget_PHIDID_INTERFACEKIT_8_8_8_w_LCD
+#define com_phidgets_MotorControlPhidget_PHIDID_INTERFACEKIT_8_8_8_w_LCD 125L
+#undef com_phidgets_MotorControlPhidget_PHIDID_IR
+#define com_phidgets_MotorControlPhidget_PHIDID_IR 77L
+#undef com_phidgets_MotorControlPhidget_PHIDID_LED_64
+#define com_phidgets_MotorControlPhidget_PHIDID_LED_64 74L
+#undef com_phidgets_MotorControlPhidget_PHIDID_LED_64_ADV
+#define com_phidgets_MotorControlPhidget_PHIDID_LED_64_ADV 76L
+#undef com_phidgets_MotorControlPhidget_PHIDID_LINEAR_TOUCH
+#define com_phidgets_MotorControlPhidget_PHIDID_LINEAR_TOUCH 118L
+#undef com_phidgets_MotorControlPhidget_PHIDID_MOTORCONTROL_HC_2MOTOR
+#define com_phidgets_MotorControlPhidget_PHIDID_MOTORCONTROL_HC_2MOTOR 89L
+#undef com_phidgets_MotorControlPhidget_PHIDID_MOTORCONTROL_LV_2MOTOR_4INPUT
+#define com_phidgets_MotorControlPhidget_PHIDID_MOTORCONTROL_LV_2MOTOR_4INPUT 88L
+#undef com_phidgets_MotorControlPhidget_PHIDID_MOTORCONTROL_1MOTOR
+#define com_phidgets_MotorControlPhidget_PHIDID_MOTORCONTROL_1MOTOR 62L
+#undef com_phidgets_MotorControlPhidget_PHIDID_PHSENSOR
+#define com_phidgets_MotorControlPhidget_PHIDID_PHSENSOR 116L
+#undef com_phidgets_MotorControlPhidget_PHIDID_RFID_2OUTPUT
+#define com_phidgets_MotorControlPhidget_PHIDID_RFID_2OUTPUT 49L
+#undef com_phidgets_MotorControlPhidget_PHIDID_ROTARY_TOUCH
+#define com_phidgets_MotorControlPhidget_PHIDID_ROTARY_TOUCH 119L
+#undef com_phidgets_MotorControlPhidget_PHIDID_SERVO_1MOTOR
+#define com_phidgets_MotorControlPhidget_PHIDID_SERVO_1MOTOR 57L
+#undef com_phidgets_MotorControlPhidget_PHIDID_SPATIAL_ACCEL_3AXIS
+#define com_phidgets_MotorControlPhidget_PHIDID_SPATIAL_ACCEL_3AXIS 127L
+#undef com_phidgets_MotorControlPhidget_PHIDID_SPATIAL_ACCEL_GYRO_COMPASS
+#define com_phidgets_MotorControlPhidget_PHIDID_SPATIAL_ACCEL_GYRO_COMPASS 51L
+#undef com_phidgets_MotorControlPhidget_PHIDID_TEMPERATURESENSOR
+#define com_phidgets_MotorControlPhidget_PHIDID_TEMPERATURESENSOR 112L
+#undef com_phidgets_MotorControlPhidget_PHIDID_TEMPERATURESENSOR_4
+#define com_phidgets_MotorControlPhidget_PHIDID_TEMPERATURESENSOR_4 50L
+#undef com_phidgets_MotorControlPhidget_PHIDID_TEXTLCD_2x20_w_8_8_8
+#define com_phidgets_MotorControlPhidget_PHIDID_TEXTLCD_2x20_w_8_8_8 381L
+#undef com_phidgets_MotorControlPhidget_PHIDID_TEXTLCD_ADAPTER
+#define com_phidgets_MotorControlPhidget_PHIDID_TEXTLCD_ADAPTER 61L
+#undef com_phidgets_MotorControlPhidget_PHIDID_UNIPOLAR_STEPPER_4MOTOR
+#define com_phidgets_MotorControlPhidget_PHIDID_UNIPOLAR_STEPPER_4MOTOR 122L
+#undef com_phidgets_MotorControlPhidget_PHIDID_ACCELEROMETER_2AXIS
+#define com_phidgets_MotorControlPhidget_PHIDID_ACCELEROMETER_2AXIS 113L
+#undef com_phidgets_MotorControlPhidget_PHIDID_INTERFACEKIT_0_8_8_w_LCD
+#define com_phidgets_MotorControlPhidget_PHIDID_INTERFACEKIT_0_8_8_w_LCD 83L
+#undef com_phidgets_MotorControlPhidget_PHIDID_INTERFACEKIT_4_8_8
+#define com_phidgets_MotorControlPhidget_PHIDID_INTERFACEKIT_4_8_8 4L
+#undef com_phidgets_MotorControlPhidget_PHIDID_RFID
+#define com_phidgets_MotorControlPhidget_PHIDID_RFID 48L
+#undef com_phidgets_MotorControlPhidget_PHIDID_SERVO_1MOTOR_OLD
+#define com_phidgets_MotorControlPhidget_PHIDID_SERVO_1MOTOR_OLD 2L
+#undef com_phidgets_MotorControlPhidget_PHIDID_SERVO_4MOTOR
+#define com_phidgets_MotorControlPhidget_PHIDID_SERVO_4MOTOR 56L
+#undef com_phidgets_MotorControlPhidget_PHIDID_SERVO_4MOTOR_OLD
+#define com_phidgets_MotorControlPhidget_PHIDID_SERVO_4MOTOR_OLD 3L
+#undef com_phidgets_MotorControlPhidget_PHIDID_TEXTLCD_2x20
+#define com_phidgets_MotorControlPhidget_PHIDID_TEXTLCD_2x20 82L
+#undef com_phidgets_MotorControlPhidget_PHIDID_TEXTLCD_2x20_w_0_8_8
+#define com_phidgets_MotorControlPhidget_PHIDID_TEXTLCD_2x20_w_0_8_8 339L
+#undef com_phidgets_MotorControlPhidget_PHIDID_TEXTLED_1x8
+#define com_phidgets_MotorControlPhidget_PHIDID_TEXTLED_1x8 73L
+#undef com_phidgets_MotorControlPhidget_PHIDID_TEXTLED_4x8
+#define com_phidgets_MotorControlPhidget_PHIDID_TEXTLED_4x8 72L
+#undef com_phidgets_MotorControlPhidget_PHIDID_WEIGHTSENSOR
+#define com_phidgets_MotorControlPhidget_PHIDID_WEIGHTSENSOR 114L
+#undef com_phidgets_MotorControlPhidget_PHIDCLASS_NOTHING
+#define com_phidgets_MotorControlPhidget_PHIDCLASS_NOTHING 1L
+#undef com_phidgets_MotorControlPhidget_PHIDCLASS_ACCELEROMETER
+#define com_phidgets_MotorControlPhidget_PHIDCLASS_ACCELEROMETER 2L
+#undef com_phidgets_MotorControlPhidget_PHIDCLASS_ADVANCEDSERVO
+#define com_phidgets_MotorControlPhidget_PHIDCLASS_ADVANCEDSERVO 3L
+#undef com_phidgets_MotorControlPhidget_PHIDCLASS_ANALOG
+#define com_phidgets_MotorControlPhidget_PHIDCLASS_ANALOG 22L
+#undef com_phidgets_MotorControlPhidget_PHIDCLASS_BRIDGE
+#define com_phidgets_MotorControlPhidget_PHIDCLASS_BRIDGE 23L
+#undef com_phidgets_MotorControlPhidget_PHIDCLASS_ENCODER
+#define com_phidgets_MotorControlPhidget_PHIDCLASS_ENCODER 4L
+#undef com_phidgets_MotorControlPhidget_PHIDCLASS_FREQUENCYCOUNTER
+#define com_phidgets_MotorControlPhidget_PHIDCLASS_FREQUENCYCOUNTER 21L
+#undef com_phidgets_MotorControlPhidget_PHIDCLASS_GPS
+#define com_phidgets_MotorControlPhidget_PHIDCLASS_GPS 5L
+#undef com_phidgets_MotorControlPhidget_PHIDCLASS_INTERFACEKIT
+#define com_phidgets_MotorControlPhidget_PHIDCLASS_INTERFACEKIT 7L
+#undef com_phidgets_MotorControlPhidget_PHIDCLASS_LED
+#define com_phidgets_MotorControlPhidget_PHIDCLASS_LED 8L
+#undef com_phidgets_MotorControlPhidget_PHIDCLASS_MOTORCONTROL
+#define com_phidgets_MotorControlPhidget_PHIDCLASS_MOTORCONTROL 9L
+#undef com_phidgets_MotorControlPhidget_PHIDCLASS_PHSENSOR
+#define com_phidgets_MotorControlPhidget_PHIDCLASS_PHSENSOR 10L
+#undef com_phidgets_MotorControlPhidget_PHIDCLASS_RFID
+#define com_phidgets_MotorControlPhidget_PHIDCLASS_RFID 11L
+#undef com_phidgets_MotorControlPhidget_PHIDCLASS_SERVO
+#define com_phidgets_MotorControlPhidget_PHIDCLASS_SERVO 12L
+#undef com_phidgets_MotorControlPhidget_PHIDCLASS_STEPPER
+#define com_phidgets_MotorControlPhidget_PHIDCLASS_STEPPER 13L
+#undef com_phidgets_MotorControlPhidget_PHIDCLASS_TEMPERATURESENSOR
+#define com_phidgets_MotorControlPhidget_PHIDCLASS_TEMPERATURESENSOR 14L
+#undef com_phidgets_MotorControlPhidget_PHIDCLASS_TEXTLCD
+#define com_phidgets_MotorControlPhidget_PHIDCLASS_TEXTLCD 15L
+#undef com_phidgets_MotorControlPhidget_PHIDCLASS_TEXTLED
+#define com_phidgets_MotorControlPhidget_PHIDCLASS_TEXTLED 16L
+#undef com_phidgets_MotorControlPhidget_PHIDCLASS_WEIGHTSENSOR
+#define com_phidgets_MotorControlPhidget_PHIDCLASS_WEIGHTSENSOR 17L
+/*
+ * Class: com_phidgets_MotorControlPhidget
+ * Method: create
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL Java_com_phidgets_MotorControlPhidget_create
+ (JNIEnv *, jclass);
+
+/*
+ * Class: com_phidgets_MotorControlPhidget
+ * Method: getMotorCount
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_phidgets_MotorControlPhidget_getMotorCount
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_MotorControlPhidget
+ * Method: getInputCount
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_phidgets_MotorControlPhidget_getInputCount
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_MotorControlPhidget
+ * Method: getEncoderCount
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_phidgets_MotorControlPhidget_getEncoderCount
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_MotorControlPhidget
+ * Method: getSensorCount
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_phidgets_MotorControlPhidget_getSensorCount
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_MotorControlPhidget
+ * Method: getInputState
+ * Signature: (I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_phidgets_MotorControlPhidget_getInputState
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_MotorControlPhidget
+ * Method: getEncoderPosition
+ * Signature: (I)I
+ */
+JNIEXPORT jint JNICALL Java_com_phidgets_MotorControlPhidget_getEncoderPosition
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_MotorControlPhidget
+ * Method: setEncoderPosition
+ * Signature: (II)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_MotorControlPhidget_setEncoderPosition
+ (JNIEnv *, jobject, jint, jint);
+
+/*
+ * Class: com_phidgets_MotorControlPhidget
+ * Method: getSensorValue
+ * Signature: (I)I
+ */
+JNIEXPORT jint JNICALL Java_com_phidgets_MotorControlPhidget_getSensorValue
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_MotorControlPhidget
+ * Method: getSensorRawValue
+ * Signature: (I)I
+ */
+JNIEXPORT jint JNICALL Java_com_phidgets_MotorControlPhidget_getSensorRawValue
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_MotorControlPhidget
+ * Method: getRatiometric
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_phidgets_MotorControlPhidget_getRatiometric
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_MotorControlPhidget
+ * Method: setRatiometric
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_MotorControlPhidget_setRatiometric
+ (JNIEnv *, jobject, jboolean);
+
+/*
+ * Class: com_phidgets_MotorControlPhidget
+ * Method: getAcceleration
+ * Signature: (I)D
+ */
+JNIEXPORT jdouble JNICALL Java_com_phidgets_MotorControlPhidget_getAcceleration
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_MotorControlPhidget
+ * Method: setAcceleration
+ * Signature: (ID)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_MotorControlPhidget_setAcceleration
+ (JNIEnv *, jobject, jint, jdouble);
+
+/*
+ * Class: com_phidgets_MotorControlPhidget
+ * Method: getAccelerationMax
+ * Signature: (I)D
+ */
+JNIEXPORT jdouble JNICALL Java_com_phidgets_MotorControlPhidget_getAccelerationMax
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_MotorControlPhidget
+ * Method: getAccelerationMin
+ * Signature: (I)D
+ */
+JNIEXPORT jdouble JNICALL Java_com_phidgets_MotorControlPhidget_getAccelerationMin
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_MotorControlPhidget
+ * Method: getVelocity
+ * Signature: (I)D
+ */
+JNIEXPORT jdouble JNICALL Java_com_phidgets_MotorControlPhidget_getVelocity
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_MotorControlPhidget
+ * Method: getSpeed
+ * Signature: (I)D
+ */
+JNIEXPORT jdouble JNICALL Java_com_phidgets_MotorControlPhidget_getSpeed
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_MotorControlPhidget
+ * Method: setVelocity
+ * Signature: (ID)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_MotorControlPhidget_setVelocity
+ (JNIEnv *, jobject, jint, jdouble);
+
+/*
+ * Class: com_phidgets_MotorControlPhidget
+ * Method: setSpeed
+ * Signature: (ID)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_MotorControlPhidget_setSpeed
+ (JNIEnv *, jobject, jint, jdouble);
+
+/*
+ * Class: com_phidgets_MotorControlPhidget
+ * Method: getCurrent
+ * Signature: (I)D
+ */
+JNIEXPORT jdouble JNICALL Java_com_phidgets_MotorControlPhidget_getCurrent
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_MotorControlPhidget
+ * Method: getBackEMFSensingState
+ * Signature: (I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_phidgets_MotorControlPhidget_getBackEMFSensingState
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_MotorControlPhidget
+ * Method: setBackEMFSensingState
+ * Signature: (IZ)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_MotorControlPhidget_setBackEMFSensingState
+ (JNIEnv *, jobject, jint, jboolean);
+
+/*
+ * Class: com_phidgets_MotorControlPhidget
+ * Method: getBackEMF
+ * Signature: (I)D
+ */
+JNIEXPORT jdouble JNICALL Java_com_phidgets_MotorControlPhidget_getBackEMF
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_MotorControlPhidget
+ * Method: getSupplyVoltage
+ * Signature: ()D
+ */
+JNIEXPORT jdouble JNICALL Java_com_phidgets_MotorControlPhidget_getSupplyVoltage
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_MotorControlPhidget
+ * Method: getBraking
+ * Signature: (I)D
+ */
+JNIEXPORT jdouble JNICALL Java_com_phidgets_MotorControlPhidget_getBraking
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_MotorControlPhidget
+ * Method: setBraking
+ * Signature: (ID)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_MotorControlPhidget_setBraking
+ (JNIEnv *, jobject, jint, jdouble);
+
+/*
+ * Class: com_phidgets_MotorControlPhidget
+ * Method: enableMotorVelocityChangeEvents
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_MotorControlPhidget_enableMotorVelocityChangeEvents
+ (JNIEnv *, jobject, jboolean);
+
+/*
+ * Class: com_phidgets_MotorControlPhidget
+ * Method: enableCurrentChangeEvents
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_MotorControlPhidget_enableCurrentChangeEvents
+ (JNIEnv *, jobject, jboolean);
+
+/*
+ * Class: com_phidgets_MotorControlPhidget
+ * Method: enableCurrentUpdateEvents
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_MotorControlPhidget_enableCurrentUpdateEvents
+ (JNIEnv *, jobject, jboolean);
+
+/*
+ * Class: com_phidgets_MotorControlPhidget
+ * Method: enableInputChangeEvents
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_MotorControlPhidget_enableInputChangeEvents
+ (JNIEnv *, jobject, jboolean);
+
+/*
+ * Class: com_phidgets_MotorControlPhidget
+ * Method: enableEncoderPositionChangeEvents
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_MotorControlPhidget_enableEncoderPositionChangeEvents
+ (JNIEnv *, jobject, jboolean);
+
+/*
+ * Class: com_phidgets_MotorControlPhidget
+ * Method: enableEncoderPositionUpdateEvents
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_MotorControlPhidget_enableEncoderPositionUpdateEvents
+ (JNIEnv *, jobject, jboolean);
+
+/*
+ * Class: com_phidgets_MotorControlPhidget
+ * Method: enableBackEMFUpdateEvents
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_MotorControlPhidget_enableBackEMFUpdateEvents
+ (JNIEnv *, jobject, jboolean);
+
+/*
+ * Class: com_phidgets_MotorControlPhidget
+ * Method: enableSensorUpdateEvents
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_MotorControlPhidget_enableSensorUpdateEvents
+ (JNIEnv *, jobject, jboolean);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/Java/com_phidgets_PHSensorPhidget.c b/Java/com_phidgets_PHSensorPhidget.c
new file mode 100644
index 0000000..a6f20a1
--- /dev/null
+++ b/Java/com_phidgets_PHSensorPhidget.c
@@ -0,0 +1,24 @@
+#include "../stdafx.h"
+#include "phidget_jni.h"
+#include "com_phidgets_PHSensorPhidget.h"
+#include "../cphidgetphsensor.h"
+
+EVENT_VARS(phChange, PHChange)
+
+JNI_LOAD(ph, PHSensor)
+ EVENT_VAR_SETUP(ph, phChange, PHChange, D, V)
+}
+
+EVENT_HANDLER(PHSensor, phChange, PHChange,
+ CPhidgetPHSensor_set_OnPHChange_Handler, double)
+
+JNI_CREATE(PHSensor)
+JNI_GETFUNC(PHSensor, PHChangeTrigger, PHChangeTrigger, jdouble)
+JNI_SETFUNC(PHSensor, PHChangeTrigger, PHChangeTrigger, jdouble)
+JNI_GETFUNC(PHSensor, PH, PH, jdouble)
+JNI_GETFUNC(PHSensor, PHMin, PHMin, jdouble)
+JNI_GETFUNC(PHSensor, PHMax, PHMax, jdouble)
+JNI_GETFUNC(PHSensor, Potential, Potential, jdouble)
+JNI_GETFUNC(PHSensor, PotentialMin, PotentialMin, jdouble)
+JNI_GETFUNC(PHSensor, PotentialMax, PotentialMax, jdouble)
+JNI_SETFUNC(PHSensor, Temperature, Temperature, jdouble)
diff --git a/Java/com_phidgets_PHSensorPhidget.h b/Java/com_phidgets_PHSensorPhidget.h
new file mode 100644
index 0000000..2fa9b2e
--- /dev/null
+++ b/Java/com_phidgets_PHSensorPhidget.h
@@ -0,0 +1,245 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class com_phidgets_PHSensorPhidget */
+
+#ifndef _Included_com_phidgets_PHSensorPhidget
+#define _Included_com_phidgets_PHSensorPhidget
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef com_phidgets_PHSensorPhidget_PHIDGET_LOG_CRITICAL
+#define com_phidgets_PHSensorPhidget_PHIDGET_LOG_CRITICAL 1L
+#undef com_phidgets_PHSensorPhidget_PHIDGET_LOG_ERROR
+#define com_phidgets_PHSensorPhidget_PHIDGET_LOG_ERROR 2L
+#undef com_phidgets_PHSensorPhidget_PHIDGET_LOG_WARNING
+#define com_phidgets_PHSensorPhidget_PHIDGET_LOG_WARNING 3L
+#undef com_phidgets_PHSensorPhidget_PHIDGET_LOG_DEBUG
+#define com_phidgets_PHSensorPhidget_PHIDGET_LOG_DEBUG 4L
+#undef com_phidgets_PHSensorPhidget_PHIDGET_LOG_INFO
+#define com_phidgets_PHSensorPhidget_PHIDGET_LOG_INFO 5L
+#undef com_phidgets_PHSensorPhidget_PHIDGET_LOG_VERBOSE
+#define com_phidgets_PHSensorPhidget_PHIDGET_LOG_VERBOSE 6L
+#undef com_phidgets_PHSensorPhidget_PHIDID_NOTHING
+#define com_phidgets_PHSensorPhidget_PHIDID_NOTHING 1L
+#undef com_phidgets_PHSensorPhidget_PHIDID_ACCELEROMETER_3AXIS
+#define com_phidgets_PHSensorPhidget_PHIDID_ACCELEROMETER_3AXIS 126L
+#undef com_phidgets_PHSensorPhidget_PHIDID_ADVANCEDSERVO_1MOTOR
+#define com_phidgets_PHSensorPhidget_PHIDID_ADVANCEDSERVO_1MOTOR 130L
+#undef com_phidgets_PHSensorPhidget_PHIDID_ANALOG_4OUTPUT
+#define com_phidgets_PHSensorPhidget_PHIDID_ANALOG_4OUTPUT 55L
+#undef com_phidgets_PHSensorPhidget_PHIDID_ADVANCEDSERVO_8MOTOR
+#define com_phidgets_PHSensorPhidget_PHIDID_ADVANCEDSERVO_8MOTOR 58L
+#undef com_phidgets_PHSensorPhidget_PHIDID_BIPOLAR_STEPPER_1MOTOR
+#define com_phidgets_PHSensorPhidget_PHIDID_BIPOLAR_STEPPER_1MOTOR 123L
+#undef com_phidgets_PHSensorPhidget_PHIDID_BRIDGE_4INPUT
+#define com_phidgets_PHSensorPhidget_PHIDID_BRIDGE_4INPUT 59L
+#undef com_phidgets_PHSensorPhidget_PHIDID_ENCODER_1ENCODER_1INPUT
+#define com_phidgets_PHSensorPhidget_PHIDID_ENCODER_1ENCODER_1INPUT 75L
+#undef com_phidgets_PHSensorPhidget_PHIDID_ENCODER_HS_1ENCODER
+#define com_phidgets_PHSensorPhidget_PHIDID_ENCODER_HS_1ENCODER 128L
+#undef com_phidgets_PHSensorPhidget_PHIDID_ENCODER_HS_4ENCODER_4INPUT
+#define com_phidgets_PHSensorPhidget_PHIDID_ENCODER_HS_4ENCODER_4INPUT 79L
+#undef com_phidgets_PHSensorPhidget_PHIDID_FREQUENCYCOUNTER_2INPUT
+#define com_phidgets_PHSensorPhidget_PHIDID_FREQUENCYCOUNTER_2INPUT 53L
+#undef com_phidgets_PHSensorPhidget_PHIDID_GPS
+#define com_phidgets_PHSensorPhidget_PHIDID_GPS 121L
+#undef com_phidgets_PHSensorPhidget_PHIDID_INTERFACEKIT_0_0_4
+#define com_phidgets_PHSensorPhidget_PHIDID_INTERFACEKIT_0_0_4 64L
+#undef com_phidgets_PHSensorPhidget_PHIDID_INTERFACEKIT_0_0_8
+#define com_phidgets_PHSensorPhidget_PHIDID_INTERFACEKIT_0_0_8 129L
+#undef com_phidgets_PHSensorPhidget_PHIDID_INTERFACEKIT_0_16_16
+#define com_phidgets_PHSensorPhidget_PHIDID_INTERFACEKIT_0_16_16 68L
+#undef com_phidgets_PHSensorPhidget_PHIDID_INTERFACEKIT_8_8_8
+#define com_phidgets_PHSensorPhidget_PHIDID_INTERFACEKIT_8_8_8 69L
+#undef com_phidgets_PHSensorPhidget_PHIDID_INTERFACEKIT_8_8_8_w_LCD
+#define com_phidgets_PHSensorPhidget_PHIDID_INTERFACEKIT_8_8_8_w_LCD 125L
+#undef com_phidgets_PHSensorPhidget_PHIDID_IR
+#define com_phidgets_PHSensorPhidget_PHIDID_IR 77L
+#undef com_phidgets_PHSensorPhidget_PHIDID_LED_64
+#define com_phidgets_PHSensorPhidget_PHIDID_LED_64 74L
+#undef com_phidgets_PHSensorPhidget_PHIDID_LED_64_ADV
+#define com_phidgets_PHSensorPhidget_PHIDID_LED_64_ADV 76L
+#undef com_phidgets_PHSensorPhidget_PHIDID_LINEAR_TOUCH
+#define com_phidgets_PHSensorPhidget_PHIDID_LINEAR_TOUCH 118L
+#undef com_phidgets_PHSensorPhidget_PHIDID_MOTORCONTROL_HC_2MOTOR
+#define com_phidgets_PHSensorPhidget_PHIDID_MOTORCONTROL_HC_2MOTOR 89L
+#undef com_phidgets_PHSensorPhidget_PHIDID_MOTORCONTROL_LV_2MOTOR_4INPUT
+#define com_phidgets_PHSensorPhidget_PHIDID_MOTORCONTROL_LV_2MOTOR_4INPUT 88L
+#undef com_phidgets_PHSensorPhidget_PHIDID_MOTORCONTROL_1MOTOR
+#define com_phidgets_PHSensorPhidget_PHIDID_MOTORCONTROL_1MOTOR 62L
+#undef com_phidgets_PHSensorPhidget_PHIDID_PHSENSOR
+#define com_phidgets_PHSensorPhidget_PHIDID_PHSENSOR 116L
+#undef com_phidgets_PHSensorPhidget_PHIDID_RFID_2OUTPUT
+#define com_phidgets_PHSensorPhidget_PHIDID_RFID_2OUTPUT 49L
+#undef com_phidgets_PHSensorPhidget_PHIDID_ROTARY_TOUCH
+#define com_phidgets_PHSensorPhidget_PHIDID_ROTARY_TOUCH 119L
+#undef com_phidgets_PHSensorPhidget_PHIDID_SERVO_1MOTOR
+#define com_phidgets_PHSensorPhidget_PHIDID_SERVO_1MOTOR 57L
+#undef com_phidgets_PHSensorPhidget_PHIDID_SPATIAL_ACCEL_3AXIS
+#define com_phidgets_PHSensorPhidget_PHIDID_SPATIAL_ACCEL_3AXIS 127L
+#undef com_phidgets_PHSensorPhidget_PHIDID_SPATIAL_ACCEL_GYRO_COMPASS
+#define com_phidgets_PHSensorPhidget_PHIDID_SPATIAL_ACCEL_GYRO_COMPASS 51L
+#undef com_phidgets_PHSensorPhidget_PHIDID_TEMPERATURESENSOR
+#define com_phidgets_PHSensorPhidget_PHIDID_TEMPERATURESENSOR 112L
+#undef com_phidgets_PHSensorPhidget_PHIDID_TEMPERATURESENSOR_4
+#define com_phidgets_PHSensorPhidget_PHIDID_TEMPERATURESENSOR_4 50L
+#undef com_phidgets_PHSensorPhidget_PHIDID_TEXTLCD_2x20_w_8_8_8
+#define com_phidgets_PHSensorPhidget_PHIDID_TEXTLCD_2x20_w_8_8_8 381L
+#undef com_phidgets_PHSensorPhidget_PHIDID_TEXTLCD_ADAPTER
+#define com_phidgets_PHSensorPhidget_PHIDID_TEXTLCD_ADAPTER 61L
+#undef com_phidgets_PHSensorPhidget_PHIDID_UNIPOLAR_STEPPER_4MOTOR
+#define com_phidgets_PHSensorPhidget_PHIDID_UNIPOLAR_STEPPER_4MOTOR 122L
+#undef com_phidgets_PHSensorPhidget_PHIDID_ACCELEROMETER_2AXIS
+#define com_phidgets_PHSensorPhidget_PHIDID_ACCELEROMETER_2AXIS 113L
+#undef com_phidgets_PHSensorPhidget_PHIDID_INTERFACEKIT_0_8_8_w_LCD
+#define com_phidgets_PHSensorPhidget_PHIDID_INTERFACEKIT_0_8_8_w_LCD 83L
+#undef com_phidgets_PHSensorPhidget_PHIDID_INTERFACEKIT_4_8_8
+#define com_phidgets_PHSensorPhidget_PHIDID_INTERFACEKIT_4_8_8 4L
+#undef com_phidgets_PHSensorPhidget_PHIDID_RFID
+#define com_phidgets_PHSensorPhidget_PHIDID_RFID 48L
+#undef com_phidgets_PHSensorPhidget_PHIDID_SERVO_1MOTOR_OLD
+#define com_phidgets_PHSensorPhidget_PHIDID_SERVO_1MOTOR_OLD 2L
+#undef com_phidgets_PHSensorPhidget_PHIDID_SERVO_4MOTOR
+#define com_phidgets_PHSensorPhidget_PHIDID_SERVO_4MOTOR 56L
+#undef com_phidgets_PHSensorPhidget_PHIDID_SERVO_4MOTOR_OLD
+#define com_phidgets_PHSensorPhidget_PHIDID_SERVO_4MOTOR_OLD 3L
+#undef com_phidgets_PHSensorPhidget_PHIDID_TEXTLCD_2x20
+#define com_phidgets_PHSensorPhidget_PHIDID_TEXTLCD_2x20 82L
+#undef com_phidgets_PHSensorPhidget_PHIDID_TEXTLCD_2x20_w_0_8_8
+#define com_phidgets_PHSensorPhidget_PHIDID_TEXTLCD_2x20_w_0_8_8 339L
+#undef com_phidgets_PHSensorPhidget_PHIDID_TEXTLED_1x8
+#define com_phidgets_PHSensorPhidget_PHIDID_TEXTLED_1x8 73L
+#undef com_phidgets_PHSensorPhidget_PHIDID_TEXTLED_4x8
+#define com_phidgets_PHSensorPhidget_PHIDID_TEXTLED_4x8 72L
+#undef com_phidgets_PHSensorPhidget_PHIDID_WEIGHTSENSOR
+#define com_phidgets_PHSensorPhidget_PHIDID_WEIGHTSENSOR 114L
+#undef com_phidgets_PHSensorPhidget_PHIDCLASS_NOTHING
+#define com_phidgets_PHSensorPhidget_PHIDCLASS_NOTHING 1L
+#undef com_phidgets_PHSensorPhidget_PHIDCLASS_ACCELEROMETER
+#define com_phidgets_PHSensorPhidget_PHIDCLASS_ACCELEROMETER 2L
+#undef com_phidgets_PHSensorPhidget_PHIDCLASS_ADVANCEDSERVO
+#define com_phidgets_PHSensorPhidget_PHIDCLASS_ADVANCEDSERVO 3L
+#undef com_phidgets_PHSensorPhidget_PHIDCLASS_ANALOG
+#define com_phidgets_PHSensorPhidget_PHIDCLASS_ANALOG 22L
+#undef com_phidgets_PHSensorPhidget_PHIDCLASS_BRIDGE
+#define com_phidgets_PHSensorPhidget_PHIDCLASS_BRIDGE 23L
+#undef com_phidgets_PHSensorPhidget_PHIDCLASS_ENCODER
+#define com_phidgets_PHSensorPhidget_PHIDCLASS_ENCODER 4L
+#undef com_phidgets_PHSensorPhidget_PHIDCLASS_FREQUENCYCOUNTER
+#define com_phidgets_PHSensorPhidget_PHIDCLASS_FREQUENCYCOUNTER 21L
+#undef com_phidgets_PHSensorPhidget_PHIDCLASS_GPS
+#define com_phidgets_PHSensorPhidget_PHIDCLASS_GPS 5L
+#undef com_phidgets_PHSensorPhidget_PHIDCLASS_INTERFACEKIT
+#define com_phidgets_PHSensorPhidget_PHIDCLASS_INTERFACEKIT 7L
+#undef com_phidgets_PHSensorPhidget_PHIDCLASS_LED
+#define com_phidgets_PHSensorPhidget_PHIDCLASS_LED 8L
+#undef com_phidgets_PHSensorPhidget_PHIDCLASS_MOTORCONTROL
+#define com_phidgets_PHSensorPhidget_PHIDCLASS_MOTORCONTROL 9L
+#undef com_phidgets_PHSensorPhidget_PHIDCLASS_PHSENSOR
+#define com_phidgets_PHSensorPhidget_PHIDCLASS_PHSENSOR 10L
+#undef com_phidgets_PHSensorPhidget_PHIDCLASS_RFID
+#define com_phidgets_PHSensorPhidget_PHIDCLASS_RFID 11L
+#undef com_phidgets_PHSensorPhidget_PHIDCLASS_SERVO
+#define com_phidgets_PHSensorPhidget_PHIDCLASS_SERVO 12L
+#undef com_phidgets_PHSensorPhidget_PHIDCLASS_STEPPER
+#define com_phidgets_PHSensorPhidget_PHIDCLASS_STEPPER 13L
+#undef com_phidgets_PHSensorPhidget_PHIDCLASS_TEMPERATURESENSOR
+#define com_phidgets_PHSensorPhidget_PHIDCLASS_TEMPERATURESENSOR 14L
+#undef com_phidgets_PHSensorPhidget_PHIDCLASS_TEXTLCD
+#define com_phidgets_PHSensorPhidget_PHIDCLASS_TEXTLCD 15L
+#undef com_phidgets_PHSensorPhidget_PHIDCLASS_TEXTLED
+#define com_phidgets_PHSensorPhidget_PHIDCLASS_TEXTLED 16L
+#undef com_phidgets_PHSensorPhidget_PHIDCLASS_WEIGHTSENSOR
+#define com_phidgets_PHSensorPhidget_PHIDCLASS_WEIGHTSENSOR 17L
+/*
+ * Class: com_phidgets_PHSensorPhidget
+ * Method: create
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL Java_com_phidgets_PHSensorPhidget_create
+ (JNIEnv *, jclass);
+
+/*
+ * Class: com_phidgets_PHSensorPhidget
+ * Method: getPH
+ * Signature: ()D
+ */
+JNIEXPORT jdouble JNICALL Java_com_phidgets_PHSensorPhidget_getPH
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_PHSensorPhidget
+ * Method: getPHMax
+ * Signature: ()D
+ */
+JNIEXPORT jdouble JNICALL Java_com_phidgets_PHSensorPhidget_getPHMax
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_PHSensorPhidget
+ * Method: getPHMin
+ * Signature: ()D
+ */
+JNIEXPORT jdouble JNICALL Java_com_phidgets_PHSensorPhidget_getPHMin
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_PHSensorPhidget
+ * Method: getPotential
+ * Signature: ()D
+ */
+JNIEXPORT jdouble JNICALL Java_com_phidgets_PHSensorPhidget_getPotential
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_PHSensorPhidget
+ * Method: getPotentialMax
+ * Signature: ()D
+ */
+JNIEXPORT jdouble JNICALL Java_com_phidgets_PHSensorPhidget_getPotentialMax
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_PHSensorPhidget
+ * Method: getPotentialMin
+ * Signature: ()D
+ */
+JNIEXPORT jdouble JNICALL Java_com_phidgets_PHSensorPhidget_getPotentialMin
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_PHSensorPhidget
+ * Method: setTemperature
+ * Signature: (D)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_PHSensorPhidget_setTemperature
+ (JNIEnv *, jobject, jdouble);
+
+/*
+ * Class: com_phidgets_PHSensorPhidget
+ * Method: setPHChangeTrigger
+ * Signature: (D)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_PHSensorPhidget_setPHChangeTrigger
+ (JNIEnv *, jobject, jdouble);
+
+/*
+ * Class: com_phidgets_PHSensorPhidget
+ * Method: getPHChangeTrigger
+ * Signature: ()D
+ */
+JNIEXPORT jdouble JNICALL Java_com_phidgets_PHSensorPhidget_getPHChangeTrigger
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_PHSensorPhidget
+ * Method: enablePHChangeEvents
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_PHSensorPhidget_enablePHChangeEvents
+ (JNIEnv *, jobject, jboolean);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/Java/com_phidgets_Phidget.c b/Java/com_phidgets_Phidget.c
new file mode 100644
index 0000000..82a9294
--- /dev/null
+++ b/Java/com_phidgets_Phidget.c
@@ -0,0 +1,630 @@
+#include "../stdafx.h"
+#include <stdlib.h>
+#include "com_phidgets_Phidget.h"
+#include "../cphidget.h"
+#include "../csocket.h"
+#include "phidget_jni.h"
+
+static int CCONV attach_handler(CPhidgetHandle h, void *arg);
+static int CCONV detach_handler(CPhidgetHandle h, void *arg);
+static int CCONV serverConnect_handler(CPhidgetHandle h, void *arg);
+static int CCONV serverDisconnect_handler(CPhidgetHandle h, void *arg);
+static int CCONV error_handler(CPhidgetHandle h, void *, int l, const char *arg);
+
+jfieldID handle_fid;
+jfieldID managerPhidget_fid;
+static jfieldID nativeAttachHandler_fid;
+static jfieldID nativeDetachHandler_fid;
+static jfieldID nativeErrorHandler_fid;
+static jfieldID nativeServerConnectHandler_fid;
+static jfieldID nativeServerDisconnectHandler_fid;
+
+static jmethodID fireAttach_mid;
+static jmethodID fireDetach_mid;
+static jmethodID fireError_mid;
+static jmethodID fireServerConnect_mid;
+static jmethodID fireServerDisconnect_mid;
+
+void
+com_phidgets_Phidget_OnLoad(JNIEnv *env)
+{
+ if (!(handle_fid = (*env)->GetFieldID(env, phidget_class, "handle", "J")))
+ JNI_ABORT_STDERR("Couldn't get Field ID handle from phidget_class");
+ if (!(managerPhidget_fid = (*env)->GetFieldID(env, phidget_class, "managerPhidget", "Z")))
+ JNI_ABORT_STDERR("Couldn't get Field ID managerPhidget from phidget_class");
+ if (!(nativeAttachHandler_fid = (*env)->GetFieldID(env, phidget_class, "nativeAttachHandler", "J")))
+ JNI_ABORT_STDERR("Couldn't get Field ID nativeAttachHandler from phidget_class");
+ if (!(nativeDetachHandler_fid = (*env)->GetFieldID(env, phidget_class, "nativeDetachHandler", "J")))
+ JNI_ABORT_STDERR("Couldn't get Field ID nativeDetachHandler from phidget_class");
+ if (!(nativeErrorHandler_fid = (*env)->GetFieldID(env, phidget_class, "nativeErrorHandler", "J")))
+ JNI_ABORT_STDERR("Couldn't get Field ID nativeErrorHandler from phidget_class");
+ if (!(nativeServerConnectHandler_fid = (*env)->GetFieldID(env, phidget_class, "nativeServerConnectHandler", "J")))
+ JNI_ABORT_STDERR("Couldn't get Field ID nativeServerConnectHandler from phidget_class");
+ if (!(nativeServerDisconnectHandler_fid = (*env)->GetFieldID(env, phidget_class, "nativeServerDisconnectHandler", "J")))
+ JNI_ABORT_STDERR("Couldn't get Field ID nativeServerDisconnectHandler from phidget_class");
+
+ if (!(fireAttach_mid = (*env)->GetMethodID(env, phidget_class, "fireAttach", "(Lcom/phidgets/event/AttachEvent;)V")))
+ JNI_ABORT_STDERR("Couldn't get method ID fireAttach from phidget_class");
+ if (!(fireDetach_mid = (*env)->GetMethodID(env, phidget_class, "fireDetach", "(Lcom/phidgets/event/DetachEvent;)V")))
+ JNI_ABORT_STDERR("Couldn't get method ID fireDetach from phidget_class");
+ if (!(fireError_mid = (*env)->GetMethodID(env, phidget_class, "fireError", "(Lcom/phidgets/event/ErrorEvent;)V")))
+ JNI_ABORT_STDERR("Couldn't get method ID fireError from phidget_class");
+ if (!(fireServerConnect_mid = (*env)->GetMethodID(env, phidget_class, "fireServerConnect", "(Lcom/phidgets/event/ServerConnectEvent;)V")))
+ JNI_ABORT_STDERR("Couldn't get method ID fireServerConnect from phidget_class");
+ if (!(fireServerDisconnect_mid = (*env)->GetMethodID(env, phidget_class, "fireServerDisconnect", "(Lcom/phidgets/event/ServerDisconnectEvent;)V")))
+ JNI_ABORT_STDERR("Couldn't get method ID fireServerDisconnect from phidget_class");
+}
+
+JNIEXPORT void JNICALL
+Java_com_phidgets_Phidget_enableAttachEvents(JNIEnv *env, jobject obj,
+ jboolean b)
+{
+ jlong gr = updateGlobalRef(env, obj, nativeAttachHandler_fid, b);
+ CPhidgetHandle h = (CPhidgetHandle)(uintptr_t)(*env)->GetLongField(env,
+ obj, handle_fid);
+
+ CPhidget_set_OnAttach_Handler(h, b ? attach_handler : 0,
+ (void *)(uintptr_t)gr);
+}
+
+static int CCONV
+attach_handler(CPhidgetHandle h, void *arg)
+{
+ JNIEnv *env;
+ jobject obj;
+ jobject attachEvent;
+ jint result;
+
+ result = (*ph_vm)->GetEnv(ph_vm, (void **)&env, JNI_VERSION_1_4);
+
+ if(result == JNI_EDETACHED)
+ {
+ if ((*ph_vm)->AttachCurrentThread(ph_vm, (JNIEnvPtr)&env, NULL))
+ JNI_ABORT_STDERR("Couldn't AttachCurrentThread");
+ }
+
+ obj = (jobject)arg;
+
+ if (!(attachEvent = (*env)->NewObject(env, attachEvent_class, attachEvent_cons,
+ obj)))
+ return -1;
+ (*env)->CallVoidMethod(env, obj, fireAttach_mid, attachEvent);
+ (*env)->DeleteLocalRef(env, attachEvent);
+ (*ph_vm)->DetachCurrentThread(ph_vm);
+
+ return 0;
+}
+
+JNIEXPORT void JNICALL
+Java_com_phidgets_Phidget_enableDetachEvents(JNIEnv *env, jobject obj,
+ jboolean b)
+{
+ jlong gr = updateGlobalRef(env, obj, nativeDetachHandler_fid, b);
+ CPhidgetHandle h = (CPhidgetHandle)(uintptr_t)(*env)->GetLongField(env,
+ obj, handle_fid);
+
+ CPhidget_set_OnDetach_Handler(h, b ? detach_handler : 0, (void *)(uintptr_t)gr);
+}
+
+static int CCONV
+detach_handler(CPhidgetHandle h, void *arg)
+{
+ JNIEnv *env;
+ jobject obj;
+ jobject detachEvent;
+
+ if ((*ph_vm)->AttachCurrentThread(ph_vm, (JNIEnvPtr)&env, NULL))
+ JNI_ABORT_STDERR("Couldn't AttachCurrentThread");
+
+ obj = (jobject)arg;
+
+ if (!(detachEvent = (*env)->NewObject(env, detachEvent_class, detachEvent_cons,
+ obj)))
+ return -1;
+ (*env)->CallVoidMethod(env, obj, fireDetach_mid, detachEvent);
+ (*env)->DeleteLocalRef(env, detachEvent);
+ (*ph_vm)->DetachCurrentThread(ph_vm);
+
+ return 0;
+}
+
+JNIEXPORT void JNICALL
+Java_com_phidgets_Phidget_enableErrorEvents(JNIEnv *env, jobject obj,
+ jboolean b)
+{
+ jlong gr = updateGlobalRef(env, obj, nativeErrorHandler_fid, b);
+ CPhidgetHandle h = (CPhidgetHandle)(uintptr_t)(*env)->GetLongField(env,
+ obj, handle_fid);
+
+ CPhidget_set_OnError_Handler(h, b ? error_handler : 0, (void *)(uintptr_t)gr);
+}
+
+static int CCONV
+error_handler(CPhidgetHandle h, void *arg, int l, const char *v)
+{
+ JNIEnv *env;
+ jobject obj;
+ jobject errorEvent;
+ jobject eobj;
+ jstring edesc;
+
+ if ((*ph_vm)->AttachCurrentThread(ph_vm, (JNIEnvPtr)&env, NULL))
+ JNI_ABORT_STDERR("Couldn't AttachCurrentThread");
+
+ obj = (jobject)arg;
+
+ if (!(edesc = (*env)->NewStringUTF(env, v)))
+ return -1;
+
+ if (!(eobj = (*env)->NewObject(env, ph_exception_class, ph_exception_cons, l, edesc)))
+ return -1;
+
+ if (!(errorEvent = (*env)->NewObject(env, errorEvent_class, errorEvent_cons, obj, eobj)))
+ return -1;
+
+ (*env)->CallVoidMethod(env, obj, fireError_mid, errorEvent);
+ (*env)->DeleteLocalRef(env, errorEvent);
+ (*ph_vm)->DetachCurrentThread(ph_vm);
+
+ return 0;
+}
+
+JNIEXPORT void JNICALL
+Java_com_phidgets_Phidget_enableServerConnectEvents(JNIEnv *env, jobject obj,
+ jboolean b)
+{
+ jlong gr = updateGlobalRef(env, obj, nativeServerConnectHandler_fid, b);
+ CPhidgetHandle h = (CPhidgetHandle)(uintptr_t)(*env)->GetLongField(env,
+ obj, handle_fid);
+
+ CPhidget_set_OnServerConnect_Handler(h, b ? serverConnect_handler : 0,
+ (void *)(uintptr_t)gr);
+}
+
+static int CCONV
+serverConnect_handler(CPhidgetHandle h, void *arg)
+{
+ JNIEnv *env;
+ jobject obj;
+ jobject serverConnectEvent;
+ jint result;
+
+ result = (*ph_vm)->GetEnv(ph_vm, (void **)&env, JNI_VERSION_1_4);
+
+ if(result == JNI_EDETACHED)
+ {
+ if ((*ph_vm)->AttachCurrentThread(ph_vm, (JNIEnvPtr)&env, NULL))
+ JNI_ABORT_STDERR("Couldn't AttachCurrentThread");
+ }
+
+ obj = (jobject)arg;
+
+ if (!(serverConnectEvent = (*env)->NewObject(env, serverConnectEvent_class, serverConnectEvent_cons,
+ obj)))
+ return -1;
+ (*env)->CallVoidMethod(env, obj, fireServerConnect_mid, serverConnectEvent);
+ (*env)->DeleteLocalRef(env, serverConnectEvent);
+ (*ph_vm)->DetachCurrentThread(ph_vm);
+
+ return 0;
+}
+
+JNIEXPORT void JNICALL
+Java_com_phidgets_Phidget_enableServerDisconnectEvents(JNIEnv *env, jobject obj,
+ jboolean b)
+{
+ jlong gr = updateGlobalRef(env, obj, nativeServerDisconnectHandler_fid, b);
+ CPhidgetHandle h = (CPhidgetHandle)(uintptr_t)(*env)->GetLongField(env,
+ obj, handle_fid);
+
+ CPhidget_set_OnServerDisconnect_Handler(h, b ? serverDisconnect_handler : 0,
+ (void *)(uintptr_t)gr);
+}
+
+static int CCONV
+serverDisconnect_handler(CPhidgetHandle h, void *arg)
+{
+ JNIEnv *env;
+ jobject obj;
+ jobject serverDisconnectEvent;
+ jint result;
+
+ result = (*ph_vm)->GetEnv(ph_vm, (void **)&env, JNI_VERSION_1_4);
+
+ if(result == JNI_EDETACHED)
+ {
+ if ((*ph_vm)->AttachCurrentThread(ph_vm, (JNIEnvPtr)&env, NULL))
+ JNI_ABORT_STDERR("Couldn't AttachCurrentThread");
+ }
+
+ obj = (jobject)arg;
+
+ if (!(serverDisconnectEvent = (*env)->NewObject(env, serverDisconnectEvent_class, serverDisconnectEvent_cons,
+ obj)))
+ return -1;
+ (*env)->CallVoidMethod(env, obj, fireServerDisconnect_mid, serverDisconnectEvent);
+ (*env)->DeleteLocalRef(env, serverDisconnectEvent);
+ (*ph_vm)->DetachCurrentThread(ph_vm);
+
+ return 0;
+}
+
+JNIEXPORT void JNICALL
+Java_com_phidgets_Phidget_nativeOpen(JNIEnv *env, jobject obj, jint ser)
+{
+ CPhidgetHandle h = (CPhidgetHandle)(uintptr_t)(*env)->GetLongField(env,
+ obj, handle_fid);
+ int error;
+
+ if ((error = CPhidget_open(h, ser)))
+ PH_THROW(error);
+}
+
+JNIEXPORT void JNICALL
+Java_com_phidgets_Phidget_nativeOpenRemote(JNIEnv *env, jobject obj, jint ser, jstring serverID, jstring pass)
+{
+ int error;
+ jboolean iscopy;
+ const char *serverIDcopy = serverID?(*env)->GetStringUTFChars(
+ env, serverID, &iscopy):0;
+ const char *passcopy = (*env)->GetStringUTFChars(
+ env, pass, &iscopy);
+
+ CPhidgetHandle h = (CPhidgetHandle)(uintptr_t)
+ (*env)->GetLongField(env, obj, handle_fid);
+
+ if ((error = CPhidget_openRemote(h, ser, serverIDcopy, passcopy)))
+ PH_THROW(error);
+
+ if(serverID)
+ (*env)->ReleaseStringUTFChars(env, serverID, serverIDcopy);
+ (*env)->ReleaseStringUTFChars(env, pass, passcopy);
+}
+
+JNIEXPORT void JNICALL
+Java_com_phidgets_Phidget_nativeOpenRemoteIP(JNIEnv *env, jobject obj, jint ser, jstring ipAddr, jint port, jstring pass)
+{
+ int error;
+ jboolean iscopy;
+ const char *ipAddrcopy = (*env)->GetStringUTFChars(
+ env, ipAddr, &iscopy);
+ const char *passcopy = (*env)->GetStringUTFChars(
+ env, pass, &iscopy);
+
+ CPhidgetHandle h = (CPhidgetHandle)(uintptr_t)
+ (*env)->GetLongField(env, obj, handle_fid);
+
+ if ((error = CPhidget_openRemoteIP(h, ser, ipAddrcopy, port, passcopy)))
+ PH_THROW(error);
+
+ (*env)->ReleaseStringUTFChars(env, ipAddr, ipAddrcopy);
+ (*env)->ReleaseStringUTFChars(env, pass, passcopy);
+}
+
+JNIEXPORT void JNICALL
+Java_com_phidgets_Phidget_nativeOpenLabel(JNIEnv *env, jobject obj, jstring label)
+{
+ int error;
+ jboolean iscopy;
+ const char *labelcopy = (*env)->GetStringUTFChars(
+ env, label, &iscopy);
+
+ CPhidgetHandle h = (CPhidgetHandle)(uintptr_t)(*env)->GetLongField(env,
+ obj, handle_fid);
+
+ if ((error = CPhidget_openLabel(h, labelcopy)))
+ PH_THROW(error);
+
+ (*env)->ReleaseStringUTFChars(env, label, labelcopy);
+}
+
+JNIEXPORT void JNICALL
+Java_com_phidgets_Phidget_nativeOpenLabelRemote(JNIEnv *env, jobject obj, jstring label, jstring serverID, jstring pass)
+{
+ int error;
+ jboolean iscopy;
+ const char *serverIDcopy = serverID?(*env)->GetStringUTFChars(
+ env, serverID, &iscopy):0;
+ const char *passcopy = (*env)->GetStringUTFChars(
+ env, pass, &iscopy);
+ const char *labelcopy = (*env)->GetStringUTFChars(
+ env, label, &iscopy);
+
+ CPhidgetHandle h = (CPhidgetHandle)(uintptr_t)
+ (*env)->GetLongField(env, obj, handle_fid);
+
+ if ((error = CPhidget_openLabelRemote(h, labelcopy, serverIDcopy, passcopy)))
+ PH_THROW(error);
+
+ if(serverID)
+ (*env)->ReleaseStringUTFChars(env, serverID, serverIDcopy);
+ (*env)->ReleaseStringUTFChars(env, pass, passcopy);
+ (*env)->ReleaseStringUTFChars(env, label, labelcopy);
+}
+
+JNIEXPORT void JNICALL
+Java_com_phidgets_Phidget_nativeOpenLabelRemoteIP(JNIEnv *env, jobject obj, jstring label, jstring ipAddr, jint port, jstring pass)
+{
+ int error;
+ jboolean iscopy;
+ const char *ipAddrcopy = (*env)->GetStringUTFChars(
+ env, ipAddr, &iscopy);
+ const char *passcopy = (*env)->GetStringUTFChars(
+ env, pass, &iscopy);
+ const char *labelcopy = (*env)->GetStringUTFChars(
+ env, label, &iscopy);
+
+ CPhidgetHandle h = (CPhidgetHandle)(uintptr_t)
+ (*env)->GetLongField(env, obj, handle_fid);
+
+ if ((error = CPhidget_openLabelRemoteIP(h, labelcopy, ipAddrcopy, port, passcopy)))
+ PH_THROW(error);
+
+ (*env)->ReleaseStringUTFChars(env, ipAddr, ipAddrcopy);
+ (*env)->ReleaseStringUTFChars(env, pass, passcopy);
+ (*env)->ReleaseStringUTFChars(env, label, labelcopy);
+}
+
+JNIEXPORT void JNICALL
+Java_com_phidgets_Phidget_nativeClose(JNIEnv *env, jobject obj)
+{
+ CPhidgetHandle h = (CPhidgetHandle)(uintptr_t)(*env)->GetLongField(env,
+ obj, handle_fid);
+ int error;
+
+ if ((error = CPhidget_close(h)))
+ PH_THROW(error);
+}
+
+JNIEXPORT void JNICALL
+Java_com_phidgets_Phidget_nativeDelete(JNIEnv *env, jobject obj)
+{
+ CPhidgetHandle h = (CPhidgetHandle)(uintptr_t)(*env)->GetLongField(env,
+ obj, handle_fid);
+ int error;
+
+ if ((error = CPhidget_delete(h)))
+ PH_THROW(error);
+}
+
+JNIEXPORT jint JNICALL
+Java_com_phidgets_Phidget_getSerialNumber(JNIEnv *env, jobject obj)
+{
+ CPhidgetHandle h = (CPhidgetHandle)(uintptr_t)(*env)->GetLongField(env,
+ obj, handle_fid);
+ int error;
+ int ser;
+
+ if ((error = CPhidget_getSerialNumber(h, &ser)))
+ PH_THROW(error);
+
+ return ser;
+}
+
+JNIEXPORT jint JNICALL
+Java_com_phidgets_Phidget_getServerPort(JNIEnv *env, jobject obj)
+{
+ CPhidgetHandle h = (CPhidgetHandle)(uintptr_t)(*env)->GetLongField(env,
+ obj, handle_fid);
+ int error;
+ int port;
+ const char *addr;
+
+ if ((error = CPhidget_getServerAddress(h, &addr, &port)))
+ PH_THROW(error);
+
+ return port;
+}
+
+JNIEXPORT jstring JNICALL
+Java_com_phidgets_Phidget_getServerAddress(JNIEnv *env, jobject obj)
+{
+ CPhidgetHandle h = (CPhidgetHandle)(uintptr_t)(*env)->GetLongField(env,
+ obj, handle_fid);
+ int error;
+ int port;
+ const char *addr;
+
+ if ((error = CPhidget_getServerAddress(h, &addr, &port)))
+ PH_THROW(error);
+
+ return (*env)->NewStringUTF(env, addr);
+}
+
+JNIEXPORT jstring JNICALL
+Java_com_phidgets_Phidget_getServerID(JNIEnv *env, jobject obj)
+{
+ CPhidgetHandle h = (CPhidgetHandle)(uintptr_t)(*env)->GetLongField(env,
+ obj, handle_fid);
+ int error;
+ const char *id;
+
+ if ((error = CPhidget_getServerID(h, &id)))
+ PH_THROW(error);
+
+ return (*env)->NewStringUTF(env, id);
+}
+
+JNIEXPORT jint JNICALL
+Java_com_phidgets_Phidget_getDeviceID(JNIEnv *env, jobject obj)
+{
+ CPhidgetHandle h = (CPhidgetHandle)(uintptr_t)(*env)->GetLongField(env,
+ obj, handle_fid);
+ int error;
+ CPhidget_DeviceID id;
+
+ if ((error = CPhidget_getDeviceID(h, &id)))
+ PH_THROW(error);
+
+ return (int)id;
+}
+
+JNIEXPORT jint JNICALL
+Java_com_phidgets_Phidget_getDeviceClass(JNIEnv *env, jobject obj)
+{
+ CPhidgetHandle h = (CPhidgetHandle)(uintptr_t)(*env)->GetLongField(env,
+ obj, handle_fid);
+ int error;
+ CPhidget_DeviceClass cls;
+
+ if ((error = CPhidget_getDeviceClass(h, &cls)))
+ PH_THROW(error);
+
+ return (int)cls;
+}
+
+JNIEXPORT jint JNICALL
+Java_com_phidgets_Phidget_getDeviceVersion(JNIEnv *env, jobject obj)
+{
+ CPhidgetHandle h = (CPhidgetHandle)(uintptr_t)(*env)->GetLongField(env,
+ obj, handle_fid);
+ int error;
+ int ver;
+
+ if ((error = CPhidget_getDeviceVersion(h, &ver)))
+ PH_THROW(error);
+
+ return ver;
+}
+
+JNIEXPORT jstring JNICALL
+Java_com_phidgets_Phidget_getDeviceType(JNIEnv *env, jobject obj)
+{
+ CPhidgetHandle h = (CPhidgetHandle)(uintptr_t)(*env)->GetLongField(env,
+ obj, handle_fid);
+ const char *type;
+ int error;
+
+ if ((error = CPhidget_getDeviceType(h, &type)))
+ PH_THROW(error);
+
+ return (*env)->NewStringUTF(env, type);
+}
+
+JNIEXPORT jstring JNICALL
+Java_com_phidgets_Phidget_getDeviceName(JNIEnv *env, jobject obj)
+{
+ CPhidgetHandle h = (CPhidgetHandle)(uintptr_t)(*env)->GetLongField(env,
+ obj, handle_fid);
+ const char *type;
+ int error;
+
+ if ((error = CPhidget_getDeviceName(h, &type)))
+ PH_THROW(error);
+
+ return (*env)->NewStringUTF(env, type);
+}
+
+JNIEXPORT jstring JNICALL
+Java_com_phidgets_Phidget_getDeviceLabel(JNIEnv *env, jobject obj)
+{
+ CPhidgetHandle h = (CPhidgetHandle)(uintptr_t)(*env)->GetLongField(env,
+ obj, handle_fid);
+ const char *label;
+ int error;
+
+ if ((error = CPhidget_getDeviceLabel(h, &label)))
+ PH_THROW(error);
+
+ return (*env)->NewStringUTF(env, label);
+}
+
+JNIEXPORT void JNICALL
+Java_com_phidgets_Phidget_setDeviceLabel(JNIEnv *env, jobject obj, jstring v)
+{
+ CPhidgetHandle h = (CPhidgetHandle)(uintptr_t)
+ (*env)->GetLongField(env, obj, handle_fid);
+ int error;
+ jboolean iscopy;
+ const char *textString = (*env)->GetStringUTFChars(
+ env, v, &iscopy);
+ if ((error = CPhidget_setDeviceLabel(h, (char *)textString)))
+ PH_THROW(error);
+ (*env)->ReleaseStringUTFChars(env, v, textString);
+}
+
+JNIEXPORT void JNICALL
+Java_com_phidgets_Phidget_nativeEnableLogging(JNIEnv *env, jclass cls, jint level, jstring file)
+{
+ int error;
+ jboolean iscopy;
+ const char *textString = file ? (*env)->GetStringUTFChars(
+ env, file, &iscopy) : NULL;
+ if ((error = CPhidget_enableLogging(level, (char *)textString)))
+ PH_THROW(error);
+ (*env)->ReleaseStringUTFChars(env, file, textString);
+}
+
+JNIEXPORT void JNICALL
+Java_com_phidgets_Phidget_disableLogging(JNIEnv *env, jclass cls)
+{
+ int error;
+ if ((error = CPhidget_disableLogging()))
+ PH_THROW(error);
+}
+
+JNIEXPORT void JNICALL
+Java_com_phidgets_Phidget_nativeLog(JNIEnv *env, jclass cls, jint level, jstring id, jstring log)
+{
+ int error;
+ jboolean iscopy1;
+ const char *textString1 = (*env)->GetStringUTFChars(
+ env, id, &iscopy1);
+ jboolean iscopy2;
+ const char *textString2 = (*env)->GetStringUTFChars(
+ env, log, &iscopy2);
+ if ((error = CPhidget_log(level, (char *)textString1, (char *)textString2)))
+ PH_THROW(error);
+ (*env)->ReleaseStringUTFChars(env, id, textString1);
+ (*env)->ReleaseStringUTFChars(env, log, textString2);
+}
+
+JNIEXPORT jstring JNICALL
+Java_com_phidgets_Phidget_getLibraryVersion(JNIEnv *env, jclass cls)
+{
+ const char *ver;
+
+ CPhidget_getLibraryVersion(&ver);
+
+ return (*env)->NewStringUTF(env, ver);
+}
+
+JNIEXPORT jboolean JNICALL
+Java_com_phidgets_Phidget_isAttached(JNIEnv *env, jobject obj)
+{
+ CPhidgetHandle h = (CPhidgetHandle)(uintptr_t)(*env)->GetLongField(env,
+ obj, handle_fid);
+ int error;
+ int s;
+
+ if ((error = CPhidget_getDeviceStatus(h, &s)))
+ PH_THROW(error);
+
+ return s == PHIDGET_ATTACHED;
+}
+
+JNIEXPORT jboolean JNICALL
+Java_com_phidgets_Phidget_isAttachedToServer(JNIEnv *env, jobject obj)
+{
+ CPhidgetHandle h = (CPhidgetHandle)(uintptr_t)(*env)->GetLongField(env,
+ obj, handle_fid);
+ int error;
+ int s;
+
+ if ((error = CPhidget_getServerStatus(h, &s)))
+ PH_THROW(error);
+
+ return s == PHIDGET_ATTACHED;
+}
+
+JNIEXPORT void JNICALL
+Java_com_phidgets_Phidget_waitForAttachment(JNIEnv *env, jobject obj, jint timeout)
+{
+ int error;
+ CPhidgetHandle h = (CPhidgetHandle)(uintptr_t)(*env)->GetLongField(env, obj, handle_fid);
+
+ if ((error = CPhidget_waitForAttachment(h, timeout)))
+ PH_THROW(error);
+
+ return;
+}
diff --git a/Java/com_phidgets_Phidget.h b/Java/com_phidgets_Phidget.h
new file mode 100644
index 0000000..1def627
--- /dev/null
+++ b/Java/com_phidgets_Phidget.h
@@ -0,0 +1,405 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class com_phidgets_Phidget */
+
+#ifndef _Included_com_phidgets_Phidget
+#define _Included_com_phidgets_Phidget
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef com_phidgets_Phidget_PHIDGET_LOG_CRITICAL
+#define com_phidgets_Phidget_PHIDGET_LOG_CRITICAL 1L
+#undef com_phidgets_Phidget_PHIDGET_LOG_ERROR
+#define com_phidgets_Phidget_PHIDGET_LOG_ERROR 2L
+#undef com_phidgets_Phidget_PHIDGET_LOG_WARNING
+#define com_phidgets_Phidget_PHIDGET_LOG_WARNING 3L
+#undef com_phidgets_Phidget_PHIDGET_LOG_DEBUG
+#define com_phidgets_Phidget_PHIDGET_LOG_DEBUG 4L
+#undef com_phidgets_Phidget_PHIDGET_LOG_INFO
+#define com_phidgets_Phidget_PHIDGET_LOG_INFO 5L
+#undef com_phidgets_Phidget_PHIDGET_LOG_VERBOSE
+#define com_phidgets_Phidget_PHIDGET_LOG_VERBOSE 6L
+#undef com_phidgets_Phidget_PHIDID_NOTHING
+#define com_phidgets_Phidget_PHIDID_NOTHING 1L
+#undef com_phidgets_Phidget_PHIDID_ACCELEROMETER_3AXIS
+#define com_phidgets_Phidget_PHIDID_ACCELEROMETER_3AXIS 126L
+#undef com_phidgets_Phidget_PHIDID_ADVANCEDSERVO_1MOTOR
+#define com_phidgets_Phidget_PHIDID_ADVANCEDSERVO_1MOTOR 130L
+#undef com_phidgets_Phidget_PHIDID_ANALOG_4OUTPUT
+#define com_phidgets_Phidget_PHIDID_ANALOG_4OUTPUT 55L
+#undef com_phidgets_Phidget_PHIDID_ADVANCEDSERVO_8MOTOR
+#define com_phidgets_Phidget_PHIDID_ADVANCEDSERVO_8MOTOR 58L
+#undef com_phidgets_Phidget_PHIDID_BIPOLAR_STEPPER_1MOTOR
+#define com_phidgets_Phidget_PHIDID_BIPOLAR_STEPPER_1MOTOR 123L
+#undef com_phidgets_Phidget_PHIDID_BRIDGE_4INPUT
+#define com_phidgets_Phidget_PHIDID_BRIDGE_4INPUT 59L
+#undef com_phidgets_Phidget_PHIDID_ENCODER_1ENCODER_1INPUT
+#define com_phidgets_Phidget_PHIDID_ENCODER_1ENCODER_1INPUT 75L
+#undef com_phidgets_Phidget_PHIDID_ENCODER_HS_1ENCODER
+#define com_phidgets_Phidget_PHIDID_ENCODER_HS_1ENCODER 128L
+#undef com_phidgets_Phidget_PHIDID_ENCODER_HS_4ENCODER_4INPUT
+#define com_phidgets_Phidget_PHIDID_ENCODER_HS_4ENCODER_4INPUT 79L
+#undef com_phidgets_Phidget_PHIDID_FREQUENCYCOUNTER_2INPUT
+#define com_phidgets_Phidget_PHIDID_FREQUENCYCOUNTER_2INPUT 53L
+#undef com_phidgets_Phidget_PHIDID_GPS
+#define com_phidgets_Phidget_PHIDID_GPS 121L
+#undef com_phidgets_Phidget_PHIDID_INTERFACEKIT_0_0_4
+#define com_phidgets_Phidget_PHIDID_INTERFACEKIT_0_0_4 64L
+#undef com_phidgets_Phidget_PHIDID_INTERFACEKIT_0_0_8
+#define com_phidgets_Phidget_PHIDID_INTERFACEKIT_0_0_8 129L
+#undef com_phidgets_Phidget_PHIDID_INTERFACEKIT_0_16_16
+#define com_phidgets_Phidget_PHIDID_INTERFACEKIT_0_16_16 68L
+#undef com_phidgets_Phidget_PHIDID_INTERFACEKIT_8_8_8
+#define com_phidgets_Phidget_PHIDID_INTERFACEKIT_8_8_8 69L
+#undef com_phidgets_Phidget_PHIDID_INTERFACEKIT_8_8_8_w_LCD
+#define com_phidgets_Phidget_PHIDID_INTERFACEKIT_8_8_8_w_LCD 125L
+#undef com_phidgets_Phidget_PHIDID_IR
+#define com_phidgets_Phidget_PHIDID_IR 77L
+#undef com_phidgets_Phidget_PHIDID_LED_64
+#define com_phidgets_Phidget_PHIDID_LED_64 74L
+#undef com_phidgets_Phidget_PHIDID_LED_64_ADV
+#define com_phidgets_Phidget_PHIDID_LED_64_ADV 76L
+#undef com_phidgets_Phidget_PHIDID_LINEAR_TOUCH
+#define com_phidgets_Phidget_PHIDID_LINEAR_TOUCH 118L
+#undef com_phidgets_Phidget_PHIDID_MOTORCONTROL_HC_2MOTOR
+#define com_phidgets_Phidget_PHIDID_MOTORCONTROL_HC_2MOTOR 89L
+#undef com_phidgets_Phidget_PHIDID_MOTORCONTROL_LV_2MOTOR_4INPUT
+#define com_phidgets_Phidget_PHIDID_MOTORCONTROL_LV_2MOTOR_4INPUT 88L
+#undef com_phidgets_Phidget_PHIDID_MOTORCONTROL_1MOTOR
+#define com_phidgets_Phidget_PHIDID_MOTORCONTROL_1MOTOR 62L
+#undef com_phidgets_Phidget_PHIDID_PHSENSOR
+#define com_phidgets_Phidget_PHIDID_PHSENSOR 116L
+#undef com_phidgets_Phidget_PHIDID_RFID_2OUTPUT
+#define com_phidgets_Phidget_PHIDID_RFID_2OUTPUT 49L
+#undef com_phidgets_Phidget_PHIDID_ROTARY_TOUCH
+#define com_phidgets_Phidget_PHIDID_ROTARY_TOUCH 119L
+#undef com_phidgets_Phidget_PHIDID_SERVO_1MOTOR
+#define com_phidgets_Phidget_PHIDID_SERVO_1MOTOR 57L
+#undef com_phidgets_Phidget_PHIDID_SPATIAL_ACCEL_3AXIS
+#define com_phidgets_Phidget_PHIDID_SPATIAL_ACCEL_3AXIS 127L
+#undef com_phidgets_Phidget_PHIDID_SPATIAL_ACCEL_GYRO_COMPASS
+#define com_phidgets_Phidget_PHIDID_SPATIAL_ACCEL_GYRO_COMPASS 51L
+#undef com_phidgets_Phidget_PHIDID_TEMPERATURESENSOR
+#define com_phidgets_Phidget_PHIDID_TEMPERATURESENSOR 112L
+#undef com_phidgets_Phidget_PHIDID_TEMPERATURESENSOR_4
+#define com_phidgets_Phidget_PHIDID_TEMPERATURESENSOR_4 50L
+#undef com_phidgets_Phidget_PHIDID_TEXTLCD_2x20_w_8_8_8
+#define com_phidgets_Phidget_PHIDID_TEXTLCD_2x20_w_8_8_8 381L
+#undef com_phidgets_Phidget_PHIDID_TEXTLCD_ADAPTER
+#define com_phidgets_Phidget_PHIDID_TEXTLCD_ADAPTER 61L
+#undef com_phidgets_Phidget_PHIDID_UNIPOLAR_STEPPER_4MOTOR
+#define com_phidgets_Phidget_PHIDID_UNIPOLAR_STEPPER_4MOTOR 122L
+#undef com_phidgets_Phidget_PHIDID_ACCELEROMETER_2AXIS
+#define com_phidgets_Phidget_PHIDID_ACCELEROMETER_2AXIS 113L
+#undef com_phidgets_Phidget_PHIDID_INTERFACEKIT_0_8_8_w_LCD
+#define com_phidgets_Phidget_PHIDID_INTERFACEKIT_0_8_8_w_LCD 83L
+#undef com_phidgets_Phidget_PHIDID_INTERFACEKIT_4_8_8
+#define com_phidgets_Phidget_PHIDID_INTERFACEKIT_4_8_8 4L
+#undef com_phidgets_Phidget_PHIDID_RFID
+#define com_phidgets_Phidget_PHIDID_RFID 48L
+#undef com_phidgets_Phidget_PHIDID_SERVO_1MOTOR_OLD
+#define com_phidgets_Phidget_PHIDID_SERVO_1MOTOR_OLD 2L
+#undef com_phidgets_Phidget_PHIDID_SERVO_4MOTOR
+#define com_phidgets_Phidget_PHIDID_SERVO_4MOTOR 56L
+#undef com_phidgets_Phidget_PHIDID_SERVO_4MOTOR_OLD
+#define com_phidgets_Phidget_PHIDID_SERVO_4MOTOR_OLD 3L
+#undef com_phidgets_Phidget_PHIDID_TEXTLCD_2x20
+#define com_phidgets_Phidget_PHIDID_TEXTLCD_2x20 82L
+#undef com_phidgets_Phidget_PHIDID_TEXTLCD_2x20_w_0_8_8
+#define com_phidgets_Phidget_PHIDID_TEXTLCD_2x20_w_0_8_8 339L
+#undef com_phidgets_Phidget_PHIDID_TEXTLED_1x8
+#define com_phidgets_Phidget_PHIDID_TEXTLED_1x8 73L
+#undef com_phidgets_Phidget_PHIDID_TEXTLED_4x8
+#define com_phidgets_Phidget_PHIDID_TEXTLED_4x8 72L
+#undef com_phidgets_Phidget_PHIDID_WEIGHTSENSOR
+#define com_phidgets_Phidget_PHIDID_WEIGHTSENSOR 114L
+#undef com_phidgets_Phidget_PHIDCLASS_NOTHING
+#define com_phidgets_Phidget_PHIDCLASS_NOTHING 1L
+#undef com_phidgets_Phidget_PHIDCLASS_ACCELEROMETER
+#define com_phidgets_Phidget_PHIDCLASS_ACCELEROMETER 2L
+#undef com_phidgets_Phidget_PHIDCLASS_ADVANCEDSERVO
+#define com_phidgets_Phidget_PHIDCLASS_ADVANCEDSERVO 3L
+#undef com_phidgets_Phidget_PHIDCLASS_ANALOG
+#define com_phidgets_Phidget_PHIDCLASS_ANALOG 22L
+#undef com_phidgets_Phidget_PHIDCLASS_BRIDGE
+#define com_phidgets_Phidget_PHIDCLASS_BRIDGE 23L
+#undef com_phidgets_Phidget_PHIDCLASS_ENCODER
+#define com_phidgets_Phidget_PHIDCLASS_ENCODER 4L
+#undef com_phidgets_Phidget_PHIDCLASS_FREQUENCYCOUNTER
+#define com_phidgets_Phidget_PHIDCLASS_FREQUENCYCOUNTER 21L
+#undef com_phidgets_Phidget_PHIDCLASS_GPS
+#define com_phidgets_Phidget_PHIDCLASS_GPS 5L
+#undef com_phidgets_Phidget_PHIDCLASS_INTERFACEKIT
+#define com_phidgets_Phidget_PHIDCLASS_INTERFACEKIT 7L
+#undef com_phidgets_Phidget_PHIDCLASS_LED
+#define com_phidgets_Phidget_PHIDCLASS_LED 8L
+#undef com_phidgets_Phidget_PHIDCLASS_MOTORCONTROL
+#define com_phidgets_Phidget_PHIDCLASS_MOTORCONTROL 9L
+#undef com_phidgets_Phidget_PHIDCLASS_PHSENSOR
+#define com_phidgets_Phidget_PHIDCLASS_PHSENSOR 10L
+#undef com_phidgets_Phidget_PHIDCLASS_RFID
+#define com_phidgets_Phidget_PHIDCLASS_RFID 11L
+#undef com_phidgets_Phidget_PHIDCLASS_SERVO
+#define com_phidgets_Phidget_PHIDCLASS_SERVO 12L
+#undef com_phidgets_Phidget_PHIDCLASS_STEPPER
+#define com_phidgets_Phidget_PHIDCLASS_STEPPER 13L
+#undef com_phidgets_Phidget_PHIDCLASS_TEMPERATURESENSOR
+#define com_phidgets_Phidget_PHIDCLASS_TEMPERATURESENSOR 14L
+#undef com_phidgets_Phidget_PHIDCLASS_TEXTLCD
+#define com_phidgets_Phidget_PHIDCLASS_TEXTLCD 15L
+#undef com_phidgets_Phidget_PHIDCLASS_TEXTLED
+#define com_phidgets_Phidget_PHIDCLASS_TEXTLED 16L
+#undef com_phidgets_Phidget_PHIDCLASS_WEIGHTSENSOR
+#define com_phidgets_Phidget_PHIDCLASS_WEIGHTSENSOR 17L
+/*
+ * Class: com_phidgets_Phidget
+ * Method: getLibraryVersion
+ * Signature: ()Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_com_phidgets_Phidget_getLibraryVersion
+ (JNIEnv *, jclass);
+
+/*
+ * Class: com_phidgets_Phidget
+ * Method: nativeEnableLogging
+ * Signature: (ILjava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_Phidget_nativeEnableLogging
+ (JNIEnv *, jclass, jint, jstring);
+
+/*
+ * Class: com_phidgets_Phidget
+ * Method: disableLogging
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_Phidget_disableLogging
+ (JNIEnv *, jclass);
+
+/*
+ * Class: com_phidgets_Phidget
+ * Method: nativeLog
+ * Signature: (ILjava/lang/String;Ljava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_Phidget_nativeLog
+ (JNIEnv *, jclass, jint, jstring, jstring);
+
+/*
+ * Class: com_phidgets_Phidget
+ * Method: getDeviceID
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_phidgets_Phidget_getDeviceID
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_Phidget
+ * Method: getDeviceClass
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_phidgets_Phidget_getDeviceClass
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_Phidget
+ * Method: getSerialNumber
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_phidgets_Phidget_getSerialNumber
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_Phidget
+ * Method: getDeviceVersion
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_phidgets_Phidget_getDeviceVersion
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_Phidget
+ * Method: getDeviceType
+ * Signature: ()Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_com_phidgets_Phidget_getDeviceType
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_Phidget
+ * Method: getDeviceName
+ * Signature: ()Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_com_phidgets_Phidget_getDeviceName
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_Phidget
+ * Method: isAttached
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_phidgets_Phidget_isAttached
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_Phidget
+ * Method: isAttachedToServer
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_phidgets_Phidget_isAttachedToServer
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_Phidget
+ * Method: getDeviceLabel
+ * Signature: ()Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_com_phidgets_Phidget_getDeviceLabel
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_Phidget
+ * Method: setDeviceLabel
+ * Signature: (Ljava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_Phidget_setDeviceLabel
+ (JNIEnv *, jobject, jstring);
+
+/*
+ * Class: com_phidgets_Phidget
+ * Method: getServerAddress
+ * Signature: ()Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_com_phidgets_Phidget_getServerAddress
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_Phidget
+ * Method: getServerID
+ * Signature: ()Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_com_phidgets_Phidget_getServerID
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_Phidget
+ * Method: getServerPort
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_phidgets_Phidget_getServerPort
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_Phidget
+ * Method: nativeClose
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_Phidget_nativeClose
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_Phidget
+ * Method: nativeDelete
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_Phidget_nativeDelete
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_Phidget
+ * Method: nativeOpen
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_Phidget_nativeOpen
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_Phidget
+ * Method: nativeOpenRemote
+ * Signature: (ILjava/lang/String;Ljava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_Phidget_nativeOpenRemote
+ (JNIEnv *, jobject, jint, jstring, jstring);
+
+/*
+ * Class: com_phidgets_Phidget
+ * Method: nativeOpenRemoteIP
+ * Signature: (ILjava/lang/String;ILjava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_Phidget_nativeOpenRemoteIP
+ (JNIEnv *, jobject, jint, jstring, jint, jstring);
+
+/*
+ * Class: com_phidgets_Phidget
+ * Method: nativeOpenLabel
+ * Signature: (Ljava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_Phidget_nativeOpenLabel
+ (JNIEnv *, jobject, jstring);
+
+/*
+ * Class: com_phidgets_Phidget
+ * Method: nativeOpenLabelRemote
+ * Signature: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_Phidget_nativeOpenLabelRemote
+ (JNIEnv *, jobject, jstring, jstring, jstring);
+
+/*
+ * Class: com_phidgets_Phidget
+ * Method: nativeOpenLabelRemoteIP
+ * Signature: (Ljava/lang/String;Ljava/lang/String;ILjava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_Phidget_nativeOpenLabelRemoteIP
+ (JNIEnv *, jobject, jstring, jstring, jint, jstring);
+
+/*
+ * Class: com_phidgets_Phidget
+ * Method: waitForAttachment
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_Phidget_waitForAttachment
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_Phidget
+ * Method: enableAttachEvents
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_Phidget_enableAttachEvents
+ (JNIEnv *, jobject, jboolean);
+
+/*
+ * Class: com_phidgets_Phidget
+ * Method: enableErrorEvents
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_Phidget_enableErrorEvents
+ (JNIEnv *, jobject, jboolean);
+
+/*
+ * Class: com_phidgets_Phidget
+ * Method: enableDetachEvents
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_Phidget_enableDetachEvents
+ (JNIEnv *, jobject, jboolean);
+
+/*
+ * Class: com_phidgets_Phidget
+ * Method: enableServerConnectEvents
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_Phidget_enableServerConnectEvents
+ (JNIEnv *, jobject, jboolean);
+
+/*
+ * Class: com_phidgets_Phidget
+ * Method: enableServerDisconnectEvents
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_Phidget_enableServerDisconnectEvents
+ (JNIEnv *, jobject, jboolean);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/Java/com_phidgets_RFIDPhidget.c b/Java/com_phidgets_RFIDPhidget.c
new file mode 100644
index 0000000..c20b8ad
--- /dev/null
+++ b/Java/com_phidgets_RFIDPhidget.c
@@ -0,0 +1,104 @@
+#include "../stdafx.h"
+#include "phidget_jni.h"
+#include "com_phidgets_RFIDPhidget.h"
+#include "../cphidgetrfid.h"
+
+EVENT_VARS(outputChange, OutputChange)
+EVENT_VARS(tagLoss, TagLoss)
+EVENT_VARS(tagGain, TagGain)
+
+JNI_LOAD(rfid, RFID)
+ EVENT_VAR_SETUP(rfid, outputChange, OutputChange, IZ, V)
+ EVENT_VAR_SETUP(rfid, tagLoss, TagLoss, Ljava/lang/String;, V)
+ EVENT_VAR_SETUP(rfid, tagGain, TagGain, Ljava/lang/String;, V)
+}
+
+EVENT_HANDLER_INDEXED(RFID, outputChange, OutputChange,
+ CPhidgetRFID_set_OnOutputChange_Handler, int)
+
+static int CCONV tagLoss_handler (CPhidgetRFIDHandle h, void *arg, unsigned char *);
+JNIEXPORT void JNICALL Java_com_phidgets_RFIDPhidget_enableTagLossEvents (JNIEnv * env, jobject obj, jboolean b)
+{
+ jlong gr = updateGlobalRef (env, obj, nativeTagLossHandler_fid, b);
+ CPhidgetRFIDHandle h = (CPhidgetRFIDHandle) (uintptr_t) (*env)->GetLongField (env, obj, handle_fid);
+ CPhidgetRFID_set_OnTagLost_Handler (h, b ? tagLoss_handler : 0, (void *) (uintptr_t) gr);
+} static int CCONV
+tagLoss_handler (CPhidgetRFIDHandle h, void *arg, unsigned char *v)
+{
+ JNIEnv *env;
+ jobject obj;
+ jobject tagLossEv;
+ char stringbuffer[20];
+ jstring jb;
+ if ((*ph_vm)->AttachCurrentThread (ph_vm, (JNIEnvPtr) &env, ((void *) 0)))
+ JNI_ABORT_STDERR("Couldn't AttachCurrentThread");
+ obj = (jobject) arg;
+
+ sprintf(stringbuffer, "%02x%02x%02x%02x%02x",v[0],v[1],v[2],v[3],v[4]);
+ jb=(*env)->NewStringUTF(env, stringbuffer);
+
+ if (!(tagLossEv = (*env)->NewObject (env, tagLossEvent_class, tagLossEvent_cons, obj, jb)))
+ return -1;
+ (*env)->CallVoidMethod (env, obj, fireTagLoss_mid, tagLossEv);
+ (*env)->DeleteLocalRef (env, tagLossEv);
+ (*ph_vm)->DetachCurrentThread (ph_vm);
+ return 0;
+}
+
+static int CCONV tagGain_handler (CPhidgetRFIDHandle h, void *arg, unsigned char *);
+JNIEXPORT void JNICALL Java_com_phidgets_RFIDPhidget_enableTagGainEvents (JNIEnv * env, jobject obj, jboolean b)
+{
+ jlong gr = updateGlobalRef (env, obj, nativeTagGainHandler_fid, b);
+ CPhidgetRFIDHandle h = (CPhidgetRFIDHandle) (uintptr_t) (*env)->GetLongField (env, obj, handle_fid);
+ CPhidgetRFID_set_OnTag_Handler (h, b ? tagGain_handler : 0, (void *) (uintptr_t) gr);
+} static int CCONV
+tagGain_handler (CPhidgetRFIDHandle h, void *arg, unsigned char *v)
+{
+ JNIEnv *env;
+ jobject obj;
+ jobject tagGainEv;
+ char stringbuffer[20];
+ jstring jb;
+ if ((*ph_vm)->AttachCurrentThread (ph_vm, (JNIEnvPtr) &env, ((void *) 0)))
+ JNI_ABORT_STDERR("Couldn't AttachCurrentThread");
+ obj = (jobject) arg;
+
+ sprintf(stringbuffer, "%02x%02x%02x%02x%02x",v[0],v[1],v[2],v[3],v[4]);
+ jb=(*env)->NewStringUTF(env, stringbuffer);
+
+ if (!(tagGainEv = (*env)->NewObject (env, tagGainEvent_class, tagGainEvent_cons, obj, jb)))
+ return -1;
+ (*env)->CallVoidMethod (env, obj, fireTagGain_mid, tagGainEv);
+ (*env)->DeleteLocalRef (env, tagGainEv);
+ (*ph_vm)->DetachCurrentThread (ph_vm);
+ return 0;
+}
+
+
+JNI_CREATE(RFID)
+JNI_INDEXED_GETFUNCBOOL(RFID, OutputState, OutputState)
+JNI_INDEXED_SETFUNC(RFID, OutputState, OutputState, jboolean)
+JNI_GETFUNCBOOL(RFID, AntennaOn, AntennaOn)
+JNI_SETFUNC(RFID, AntennaOn, AntennaOn, jboolean)
+JNI_GETFUNCBOOL(RFID, LEDOn, LEDOn)
+JNI_GETFUNCBOOL(RFID, TagStatus, TagStatus)
+JNI_SETFUNC(RFID, LEDOn, LEDOn, jboolean)
+JNI_GETFUNC(RFID, OutputCount, OutputCount, jint)
+
+JNIEXPORT jstring JNICALL
+Java_com_phidgets_RFIDPhidget_getLastTag (JNIEnv *env, jobject obj)
+{
+ CPhidgetRFIDHandle h = (CPhidgetRFIDHandle)(uintptr_t)
+ (*env)->GetLongField( env, obj, handle_fid);
+ int error;
+ unsigned char buffer[11];
+ char stringbuffer[20];
+ jstring jb;
+ if ((error = CPhidgetRFID_getLastTag(h, (unsigned char *)&buffer)))
+ PH_THROW(error);
+
+ sprintf(stringbuffer, "%02x%02x%02x%02x%02x",buffer[0],buffer[1],buffer[2],buffer[3],buffer[4]);
+
+ jb=(*env)->NewStringUTF(env, stringbuffer);
+ return jb;
+}
diff --git a/Java/com_phidgets_RFIDPhidget.h b/Java/com_phidgets_RFIDPhidget.h
new file mode 100644
index 0000000..d6a123e
--- /dev/null
+++ b/Java/com_phidgets_RFIDPhidget.h
@@ -0,0 +1,261 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class com_phidgets_RFIDPhidget */
+
+#ifndef _Included_com_phidgets_RFIDPhidget
+#define _Included_com_phidgets_RFIDPhidget
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef com_phidgets_RFIDPhidget_PHIDGET_LOG_CRITICAL
+#define com_phidgets_RFIDPhidget_PHIDGET_LOG_CRITICAL 1L
+#undef com_phidgets_RFIDPhidget_PHIDGET_LOG_ERROR
+#define com_phidgets_RFIDPhidget_PHIDGET_LOG_ERROR 2L
+#undef com_phidgets_RFIDPhidget_PHIDGET_LOG_WARNING
+#define com_phidgets_RFIDPhidget_PHIDGET_LOG_WARNING 3L
+#undef com_phidgets_RFIDPhidget_PHIDGET_LOG_DEBUG
+#define com_phidgets_RFIDPhidget_PHIDGET_LOG_DEBUG 4L
+#undef com_phidgets_RFIDPhidget_PHIDGET_LOG_INFO
+#define com_phidgets_RFIDPhidget_PHIDGET_LOG_INFO 5L
+#undef com_phidgets_RFIDPhidget_PHIDGET_LOG_VERBOSE
+#define com_phidgets_RFIDPhidget_PHIDGET_LOG_VERBOSE 6L
+#undef com_phidgets_RFIDPhidget_PHIDID_NOTHING
+#define com_phidgets_RFIDPhidget_PHIDID_NOTHING 1L
+#undef com_phidgets_RFIDPhidget_PHIDID_ACCELEROMETER_3AXIS
+#define com_phidgets_RFIDPhidget_PHIDID_ACCELEROMETER_3AXIS 126L
+#undef com_phidgets_RFIDPhidget_PHIDID_ADVANCEDSERVO_1MOTOR
+#define com_phidgets_RFIDPhidget_PHIDID_ADVANCEDSERVO_1MOTOR 130L
+#undef com_phidgets_RFIDPhidget_PHIDID_ANALOG_4OUTPUT
+#define com_phidgets_RFIDPhidget_PHIDID_ANALOG_4OUTPUT 55L
+#undef com_phidgets_RFIDPhidget_PHIDID_ADVANCEDSERVO_8MOTOR
+#define com_phidgets_RFIDPhidget_PHIDID_ADVANCEDSERVO_8MOTOR 58L
+#undef com_phidgets_RFIDPhidget_PHIDID_BIPOLAR_STEPPER_1MOTOR
+#define com_phidgets_RFIDPhidget_PHIDID_BIPOLAR_STEPPER_1MOTOR 123L
+#undef com_phidgets_RFIDPhidget_PHIDID_BRIDGE_4INPUT
+#define com_phidgets_RFIDPhidget_PHIDID_BRIDGE_4INPUT 59L
+#undef com_phidgets_RFIDPhidget_PHIDID_ENCODER_1ENCODER_1INPUT
+#define com_phidgets_RFIDPhidget_PHIDID_ENCODER_1ENCODER_1INPUT 75L
+#undef com_phidgets_RFIDPhidget_PHIDID_ENCODER_HS_1ENCODER
+#define com_phidgets_RFIDPhidget_PHIDID_ENCODER_HS_1ENCODER 128L
+#undef com_phidgets_RFIDPhidget_PHIDID_ENCODER_HS_4ENCODER_4INPUT
+#define com_phidgets_RFIDPhidget_PHIDID_ENCODER_HS_4ENCODER_4INPUT 79L
+#undef com_phidgets_RFIDPhidget_PHIDID_FREQUENCYCOUNTER_2INPUT
+#define com_phidgets_RFIDPhidget_PHIDID_FREQUENCYCOUNTER_2INPUT 53L
+#undef com_phidgets_RFIDPhidget_PHIDID_GPS
+#define com_phidgets_RFIDPhidget_PHIDID_GPS 121L
+#undef com_phidgets_RFIDPhidget_PHIDID_INTERFACEKIT_0_0_4
+#define com_phidgets_RFIDPhidget_PHIDID_INTERFACEKIT_0_0_4 64L
+#undef com_phidgets_RFIDPhidget_PHIDID_INTERFACEKIT_0_0_8
+#define com_phidgets_RFIDPhidget_PHIDID_INTERFACEKIT_0_0_8 129L
+#undef com_phidgets_RFIDPhidget_PHIDID_INTERFACEKIT_0_16_16
+#define com_phidgets_RFIDPhidget_PHIDID_INTERFACEKIT_0_16_16 68L
+#undef com_phidgets_RFIDPhidget_PHIDID_INTERFACEKIT_8_8_8
+#define com_phidgets_RFIDPhidget_PHIDID_INTERFACEKIT_8_8_8 69L
+#undef com_phidgets_RFIDPhidget_PHIDID_INTERFACEKIT_8_8_8_w_LCD
+#define com_phidgets_RFIDPhidget_PHIDID_INTERFACEKIT_8_8_8_w_LCD 125L
+#undef com_phidgets_RFIDPhidget_PHIDID_IR
+#define com_phidgets_RFIDPhidget_PHIDID_IR 77L
+#undef com_phidgets_RFIDPhidget_PHIDID_LED_64
+#define com_phidgets_RFIDPhidget_PHIDID_LED_64 74L
+#undef com_phidgets_RFIDPhidget_PHIDID_LED_64_ADV
+#define com_phidgets_RFIDPhidget_PHIDID_LED_64_ADV 76L
+#undef com_phidgets_RFIDPhidget_PHIDID_LINEAR_TOUCH
+#define com_phidgets_RFIDPhidget_PHIDID_LINEAR_TOUCH 118L
+#undef com_phidgets_RFIDPhidget_PHIDID_MOTORCONTROL_HC_2MOTOR
+#define com_phidgets_RFIDPhidget_PHIDID_MOTORCONTROL_HC_2MOTOR 89L
+#undef com_phidgets_RFIDPhidget_PHIDID_MOTORCONTROL_LV_2MOTOR_4INPUT
+#define com_phidgets_RFIDPhidget_PHIDID_MOTORCONTROL_LV_2MOTOR_4INPUT 88L
+#undef com_phidgets_RFIDPhidget_PHIDID_MOTORCONTROL_1MOTOR
+#define com_phidgets_RFIDPhidget_PHIDID_MOTORCONTROL_1MOTOR 62L
+#undef com_phidgets_RFIDPhidget_PHIDID_PHSENSOR
+#define com_phidgets_RFIDPhidget_PHIDID_PHSENSOR 116L
+#undef com_phidgets_RFIDPhidget_PHIDID_RFID_2OUTPUT
+#define com_phidgets_RFIDPhidget_PHIDID_RFID_2OUTPUT 49L
+#undef com_phidgets_RFIDPhidget_PHIDID_ROTARY_TOUCH
+#define com_phidgets_RFIDPhidget_PHIDID_ROTARY_TOUCH 119L
+#undef com_phidgets_RFIDPhidget_PHIDID_SERVO_1MOTOR
+#define com_phidgets_RFIDPhidget_PHIDID_SERVO_1MOTOR 57L
+#undef com_phidgets_RFIDPhidget_PHIDID_SPATIAL_ACCEL_3AXIS
+#define com_phidgets_RFIDPhidget_PHIDID_SPATIAL_ACCEL_3AXIS 127L
+#undef com_phidgets_RFIDPhidget_PHIDID_SPATIAL_ACCEL_GYRO_COMPASS
+#define com_phidgets_RFIDPhidget_PHIDID_SPATIAL_ACCEL_GYRO_COMPASS 51L
+#undef com_phidgets_RFIDPhidget_PHIDID_TEMPERATURESENSOR
+#define com_phidgets_RFIDPhidget_PHIDID_TEMPERATURESENSOR 112L
+#undef com_phidgets_RFIDPhidget_PHIDID_TEMPERATURESENSOR_4
+#define com_phidgets_RFIDPhidget_PHIDID_TEMPERATURESENSOR_4 50L
+#undef com_phidgets_RFIDPhidget_PHIDID_TEXTLCD_2x20_w_8_8_8
+#define com_phidgets_RFIDPhidget_PHIDID_TEXTLCD_2x20_w_8_8_8 381L
+#undef com_phidgets_RFIDPhidget_PHIDID_TEXTLCD_ADAPTER
+#define com_phidgets_RFIDPhidget_PHIDID_TEXTLCD_ADAPTER 61L
+#undef com_phidgets_RFIDPhidget_PHIDID_UNIPOLAR_STEPPER_4MOTOR
+#define com_phidgets_RFIDPhidget_PHIDID_UNIPOLAR_STEPPER_4MOTOR 122L
+#undef com_phidgets_RFIDPhidget_PHIDID_ACCELEROMETER_2AXIS
+#define com_phidgets_RFIDPhidget_PHIDID_ACCELEROMETER_2AXIS 113L
+#undef com_phidgets_RFIDPhidget_PHIDID_INTERFACEKIT_0_8_8_w_LCD
+#define com_phidgets_RFIDPhidget_PHIDID_INTERFACEKIT_0_8_8_w_LCD 83L
+#undef com_phidgets_RFIDPhidget_PHIDID_INTERFACEKIT_4_8_8
+#define com_phidgets_RFIDPhidget_PHIDID_INTERFACEKIT_4_8_8 4L
+#undef com_phidgets_RFIDPhidget_PHIDID_RFID
+#define com_phidgets_RFIDPhidget_PHIDID_RFID 48L
+#undef com_phidgets_RFIDPhidget_PHIDID_SERVO_1MOTOR_OLD
+#define com_phidgets_RFIDPhidget_PHIDID_SERVO_1MOTOR_OLD 2L
+#undef com_phidgets_RFIDPhidget_PHIDID_SERVO_4MOTOR
+#define com_phidgets_RFIDPhidget_PHIDID_SERVO_4MOTOR 56L
+#undef com_phidgets_RFIDPhidget_PHIDID_SERVO_4MOTOR_OLD
+#define com_phidgets_RFIDPhidget_PHIDID_SERVO_4MOTOR_OLD 3L
+#undef com_phidgets_RFIDPhidget_PHIDID_TEXTLCD_2x20
+#define com_phidgets_RFIDPhidget_PHIDID_TEXTLCD_2x20 82L
+#undef com_phidgets_RFIDPhidget_PHIDID_TEXTLCD_2x20_w_0_8_8
+#define com_phidgets_RFIDPhidget_PHIDID_TEXTLCD_2x20_w_0_8_8 339L
+#undef com_phidgets_RFIDPhidget_PHIDID_TEXTLED_1x8
+#define com_phidgets_RFIDPhidget_PHIDID_TEXTLED_1x8 73L
+#undef com_phidgets_RFIDPhidget_PHIDID_TEXTLED_4x8
+#define com_phidgets_RFIDPhidget_PHIDID_TEXTLED_4x8 72L
+#undef com_phidgets_RFIDPhidget_PHIDID_WEIGHTSENSOR
+#define com_phidgets_RFIDPhidget_PHIDID_WEIGHTSENSOR 114L
+#undef com_phidgets_RFIDPhidget_PHIDCLASS_NOTHING
+#define com_phidgets_RFIDPhidget_PHIDCLASS_NOTHING 1L
+#undef com_phidgets_RFIDPhidget_PHIDCLASS_ACCELEROMETER
+#define com_phidgets_RFIDPhidget_PHIDCLASS_ACCELEROMETER 2L
+#undef com_phidgets_RFIDPhidget_PHIDCLASS_ADVANCEDSERVO
+#define com_phidgets_RFIDPhidget_PHIDCLASS_ADVANCEDSERVO 3L
+#undef com_phidgets_RFIDPhidget_PHIDCLASS_ANALOG
+#define com_phidgets_RFIDPhidget_PHIDCLASS_ANALOG 22L
+#undef com_phidgets_RFIDPhidget_PHIDCLASS_BRIDGE
+#define com_phidgets_RFIDPhidget_PHIDCLASS_BRIDGE 23L
+#undef com_phidgets_RFIDPhidget_PHIDCLASS_ENCODER
+#define com_phidgets_RFIDPhidget_PHIDCLASS_ENCODER 4L
+#undef com_phidgets_RFIDPhidget_PHIDCLASS_FREQUENCYCOUNTER
+#define com_phidgets_RFIDPhidget_PHIDCLASS_FREQUENCYCOUNTER 21L
+#undef com_phidgets_RFIDPhidget_PHIDCLASS_GPS
+#define com_phidgets_RFIDPhidget_PHIDCLASS_GPS 5L
+#undef com_phidgets_RFIDPhidget_PHIDCLASS_INTERFACEKIT
+#define com_phidgets_RFIDPhidget_PHIDCLASS_INTERFACEKIT 7L
+#undef com_phidgets_RFIDPhidget_PHIDCLASS_LED
+#define com_phidgets_RFIDPhidget_PHIDCLASS_LED 8L
+#undef com_phidgets_RFIDPhidget_PHIDCLASS_MOTORCONTROL
+#define com_phidgets_RFIDPhidget_PHIDCLASS_MOTORCONTROL 9L
+#undef com_phidgets_RFIDPhidget_PHIDCLASS_PHSENSOR
+#define com_phidgets_RFIDPhidget_PHIDCLASS_PHSENSOR 10L
+#undef com_phidgets_RFIDPhidget_PHIDCLASS_RFID
+#define com_phidgets_RFIDPhidget_PHIDCLASS_RFID 11L
+#undef com_phidgets_RFIDPhidget_PHIDCLASS_SERVO
+#define com_phidgets_RFIDPhidget_PHIDCLASS_SERVO 12L
+#undef com_phidgets_RFIDPhidget_PHIDCLASS_STEPPER
+#define com_phidgets_RFIDPhidget_PHIDCLASS_STEPPER 13L
+#undef com_phidgets_RFIDPhidget_PHIDCLASS_TEMPERATURESENSOR
+#define com_phidgets_RFIDPhidget_PHIDCLASS_TEMPERATURESENSOR 14L
+#undef com_phidgets_RFIDPhidget_PHIDCLASS_TEXTLCD
+#define com_phidgets_RFIDPhidget_PHIDCLASS_TEXTLCD 15L
+#undef com_phidgets_RFIDPhidget_PHIDCLASS_TEXTLED
+#define com_phidgets_RFIDPhidget_PHIDCLASS_TEXTLED 16L
+#undef com_phidgets_RFIDPhidget_PHIDCLASS_WEIGHTSENSOR
+#define com_phidgets_RFIDPhidget_PHIDCLASS_WEIGHTSENSOR 17L
+/*
+ * Class: com_phidgets_RFIDPhidget
+ * Method: create
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL Java_com_phidgets_RFIDPhidget_create
+ (JNIEnv *, jclass);
+
+/*
+ * Class: com_phidgets_RFIDPhidget
+ * Method: getOutputCount
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_phidgets_RFIDPhidget_getOutputCount
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_RFIDPhidget
+ * Method: getOutputState
+ * Signature: (I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_phidgets_RFIDPhidget_getOutputState
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_RFIDPhidget
+ * Method: setOutputState
+ * Signature: (IZ)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_RFIDPhidget_setOutputState
+ (JNIEnv *, jobject, jint, jboolean);
+
+/*
+ * Class: com_phidgets_RFIDPhidget
+ * Method: getAntennaOn
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_phidgets_RFIDPhidget_getAntennaOn
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_RFIDPhidget
+ * Method: setAntennaOn
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_RFIDPhidget_setAntennaOn
+ (JNIEnv *, jobject, jboolean);
+
+/*
+ * Class: com_phidgets_RFIDPhidget
+ * Method: getLEDOn
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_phidgets_RFIDPhidget_getLEDOn
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_RFIDPhidget
+ * Method: setLEDOn
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_RFIDPhidget_setLEDOn
+ (JNIEnv *, jobject, jboolean);
+
+/*
+ * Class: com_phidgets_RFIDPhidget
+ * Method: getLastTag
+ * Signature: ()Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_com_phidgets_RFIDPhidget_getLastTag
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_RFIDPhidget
+ * Method: getTagStatus
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_phidgets_RFIDPhidget_getTagStatus
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_RFIDPhidget
+ * Method: enableTagGainEvents
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_RFIDPhidget_enableTagGainEvents
+ (JNIEnv *, jobject, jboolean);
+
+/*
+ * Class: com_phidgets_RFIDPhidget
+ * Method: enableTagLossEvents
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_RFIDPhidget_enableTagLossEvents
+ (JNIEnv *, jobject, jboolean);
+
+/*
+ * Class: com_phidgets_RFIDPhidget
+ * Method: enableOutputChangeEvents
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_RFIDPhidget_enableOutputChangeEvents
+ (JNIEnv *, jobject, jboolean);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/Java/com_phidgets_ServoPhidget.c b/Java/com_phidgets_ServoPhidget.c
new file mode 100644
index 0000000..f016002
--- /dev/null
+++ b/Java/com_phidgets_ServoPhidget.c
@@ -0,0 +1,47 @@
+#include "../stdafx.h"
+#include "phidget_jni.h"
+#include "com_phidgets_ServoPhidget.h"
+#include "../cphidgetservo.h"
+
+EVENT_VARS(servoPositionChange, ServoPositionChange)
+
+JNI_LOAD(servo, Servo)
+ EVENT_VAR_SETUP(servo, servoPositionChange, ServoPositionChange, ID, V)
+}
+
+EVENT_HANDLER_INDEXED(Servo, servoPositionChange, ServoPositionChange,
+ CPhidgetServo_set_OnPositionChange_Handler, double)
+
+JNI_CREATE(Servo)
+JNI_INDEXED_GETFUNC(Servo, Position, Position, jdouble)
+JNI_INDEXED_SETFUNC(Servo, Position, Position, jdouble)
+JNI_INDEXED_GETFUNC(Servo, PositionMin, PositionMin, jdouble)
+JNI_INDEXED_GETFUNC(Servo, PositionMax, PositionMax, jdouble)
+JNI_INDEXED_GETFUNCBOOL(Servo, Engaged, Engaged)
+JNI_INDEXED_SETFUNC(Servo, Engaged, Engaged, jboolean)
+JNI_GETFUNC(Servo, MotorCount, MotorCount, jint)
+JNIEXPORT jint JNICALL
+Java_com_phidgets_ServoPhidget_getServoType(JNIEnv *env, jobject obj, jint index)
+{
+ CPhidgetServoHandle h = (CPhidgetServoHandle)(uintptr_t)
+ (*env)->GetLongField(env, obj, handle_fid);
+ int error;
+ CPhidget_ServoType v;
+ if ((error = CPhidgetServo_getServoType(h, index, &v)))
+ PH_THROW(error);
+ return (jint)v;
+}
+JNI_INDEXED_SETFUNC(Servo, ServoType, ServoType, jint)
+JNIEXPORT void JNICALL
+Java_com_phidgets_ServoPhidget_setServoParameters(JNIEnv *env, jobject obj, jint index, jdouble minUs, jdouble maxUs, jdouble degrees)
+{
+ CPhidgetServoHandle h = (CPhidgetServoHandle)(uintptr_t)
+ (*env)->GetLongField(env, obj, handle_fid);
+ int error;
+ if ((error = CPhidgetServo_setServoParameters(h, index, minUs, maxUs, degrees)))
+ PH_THROW(error);
+}
+
+//Deprecated
+JNI_INDEXED_GETFUNCBOOL(Servo, MotorOn, Engaged)
+JNI_INDEXED_SETFUNC(Servo, MotorOn, Engaged, jboolean)
diff --git a/Java/com_phidgets_ServoPhidget.h b/Java/com_phidgets_ServoPhidget.h
new file mode 100644
index 0000000..17a7fc6
--- /dev/null
+++ b/Java/com_phidgets_ServoPhidget.h
@@ -0,0 +1,319 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class com_phidgets_ServoPhidget */
+
+#ifndef _Included_com_phidgets_ServoPhidget
+#define _Included_com_phidgets_ServoPhidget
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef com_phidgets_ServoPhidget_PHIDGET_LOG_CRITICAL
+#define com_phidgets_ServoPhidget_PHIDGET_LOG_CRITICAL 1L
+#undef com_phidgets_ServoPhidget_PHIDGET_LOG_ERROR
+#define com_phidgets_ServoPhidget_PHIDGET_LOG_ERROR 2L
+#undef com_phidgets_ServoPhidget_PHIDGET_LOG_WARNING
+#define com_phidgets_ServoPhidget_PHIDGET_LOG_WARNING 3L
+#undef com_phidgets_ServoPhidget_PHIDGET_LOG_DEBUG
+#define com_phidgets_ServoPhidget_PHIDGET_LOG_DEBUG 4L
+#undef com_phidgets_ServoPhidget_PHIDGET_LOG_INFO
+#define com_phidgets_ServoPhidget_PHIDGET_LOG_INFO 5L
+#undef com_phidgets_ServoPhidget_PHIDGET_LOG_VERBOSE
+#define com_phidgets_ServoPhidget_PHIDGET_LOG_VERBOSE 6L
+#undef com_phidgets_ServoPhidget_PHIDID_NOTHING
+#define com_phidgets_ServoPhidget_PHIDID_NOTHING 1L
+#undef com_phidgets_ServoPhidget_PHIDID_ACCELEROMETER_3AXIS
+#define com_phidgets_ServoPhidget_PHIDID_ACCELEROMETER_3AXIS 126L
+#undef com_phidgets_ServoPhidget_PHIDID_ADVANCEDSERVO_1MOTOR
+#define com_phidgets_ServoPhidget_PHIDID_ADVANCEDSERVO_1MOTOR 130L
+#undef com_phidgets_ServoPhidget_PHIDID_ANALOG_4OUTPUT
+#define com_phidgets_ServoPhidget_PHIDID_ANALOG_4OUTPUT 55L
+#undef com_phidgets_ServoPhidget_PHIDID_ADVANCEDSERVO_8MOTOR
+#define com_phidgets_ServoPhidget_PHIDID_ADVANCEDSERVO_8MOTOR 58L
+#undef com_phidgets_ServoPhidget_PHIDID_BIPOLAR_STEPPER_1MOTOR
+#define com_phidgets_ServoPhidget_PHIDID_BIPOLAR_STEPPER_1MOTOR 123L
+#undef com_phidgets_ServoPhidget_PHIDID_BRIDGE_4INPUT
+#define com_phidgets_ServoPhidget_PHIDID_BRIDGE_4INPUT 59L
+#undef com_phidgets_ServoPhidget_PHIDID_ENCODER_1ENCODER_1INPUT
+#define com_phidgets_ServoPhidget_PHIDID_ENCODER_1ENCODER_1INPUT 75L
+#undef com_phidgets_ServoPhidget_PHIDID_ENCODER_HS_1ENCODER
+#define com_phidgets_ServoPhidget_PHIDID_ENCODER_HS_1ENCODER 128L
+#undef com_phidgets_ServoPhidget_PHIDID_ENCODER_HS_4ENCODER_4INPUT
+#define com_phidgets_ServoPhidget_PHIDID_ENCODER_HS_4ENCODER_4INPUT 79L
+#undef com_phidgets_ServoPhidget_PHIDID_FREQUENCYCOUNTER_2INPUT
+#define com_phidgets_ServoPhidget_PHIDID_FREQUENCYCOUNTER_2INPUT 53L
+#undef com_phidgets_ServoPhidget_PHIDID_GPS
+#define com_phidgets_ServoPhidget_PHIDID_GPS 121L
+#undef com_phidgets_ServoPhidget_PHIDID_INTERFACEKIT_0_0_4
+#define com_phidgets_ServoPhidget_PHIDID_INTERFACEKIT_0_0_4 64L
+#undef com_phidgets_ServoPhidget_PHIDID_INTERFACEKIT_0_0_8
+#define com_phidgets_ServoPhidget_PHIDID_INTERFACEKIT_0_0_8 129L
+#undef com_phidgets_ServoPhidget_PHIDID_INTERFACEKIT_0_16_16
+#define com_phidgets_ServoPhidget_PHIDID_INTERFACEKIT_0_16_16 68L
+#undef com_phidgets_ServoPhidget_PHIDID_INTERFACEKIT_8_8_8
+#define com_phidgets_ServoPhidget_PHIDID_INTERFACEKIT_8_8_8 69L
+#undef com_phidgets_ServoPhidget_PHIDID_INTERFACEKIT_8_8_8_w_LCD
+#define com_phidgets_ServoPhidget_PHIDID_INTERFACEKIT_8_8_8_w_LCD 125L
+#undef com_phidgets_ServoPhidget_PHIDID_IR
+#define com_phidgets_ServoPhidget_PHIDID_IR 77L
+#undef com_phidgets_ServoPhidget_PHIDID_LED_64
+#define com_phidgets_ServoPhidget_PHIDID_LED_64 74L
+#undef com_phidgets_ServoPhidget_PHIDID_LED_64_ADV
+#define com_phidgets_ServoPhidget_PHIDID_LED_64_ADV 76L
+#undef com_phidgets_ServoPhidget_PHIDID_LINEAR_TOUCH
+#define com_phidgets_ServoPhidget_PHIDID_LINEAR_TOUCH 118L
+#undef com_phidgets_ServoPhidget_PHIDID_MOTORCONTROL_HC_2MOTOR
+#define com_phidgets_ServoPhidget_PHIDID_MOTORCONTROL_HC_2MOTOR 89L
+#undef com_phidgets_ServoPhidget_PHIDID_MOTORCONTROL_LV_2MOTOR_4INPUT
+#define com_phidgets_ServoPhidget_PHIDID_MOTORCONTROL_LV_2MOTOR_4INPUT 88L
+#undef com_phidgets_ServoPhidget_PHIDID_MOTORCONTROL_1MOTOR
+#define com_phidgets_ServoPhidget_PHIDID_MOTORCONTROL_1MOTOR 62L
+#undef com_phidgets_ServoPhidget_PHIDID_PHSENSOR
+#define com_phidgets_ServoPhidget_PHIDID_PHSENSOR 116L
+#undef com_phidgets_ServoPhidget_PHIDID_RFID_2OUTPUT
+#define com_phidgets_ServoPhidget_PHIDID_RFID_2OUTPUT 49L
+#undef com_phidgets_ServoPhidget_PHIDID_ROTARY_TOUCH
+#define com_phidgets_ServoPhidget_PHIDID_ROTARY_TOUCH 119L
+#undef com_phidgets_ServoPhidget_PHIDID_SERVO_1MOTOR
+#define com_phidgets_ServoPhidget_PHIDID_SERVO_1MOTOR 57L
+#undef com_phidgets_ServoPhidget_PHIDID_SPATIAL_ACCEL_3AXIS
+#define com_phidgets_ServoPhidget_PHIDID_SPATIAL_ACCEL_3AXIS 127L
+#undef com_phidgets_ServoPhidget_PHIDID_SPATIAL_ACCEL_GYRO_COMPASS
+#define com_phidgets_ServoPhidget_PHIDID_SPATIAL_ACCEL_GYRO_COMPASS 51L
+#undef com_phidgets_ServoPhidget_PHIDID_TEMPERATURESENSOR
+#define com_phidgets_ServoPhidget_PHIDID_TEMPERATURESENSOR 112L
+#undef com_phidgets_ServoPhidget_PHIDID_TEMPERATURESENSOR_4
+#define com_phidgets_ServoPhidget_PHIDID_TEMPERATURESENSOR_4 50L
+#undef com_phidgets_ServoPhidget_PHIDID_TEXTLCD_2x20_w_8_8_8
+#define com_phidgets_ServoPhidget_PHIDID_TEXTLCD_2x20_w_8_8_8 381L
+#undef com_phidgets_ServoPhidget_PHIDID_TEXTLCD_ADAPTER
+#define com_phidgets_ServoPhidget_PHIDID_TEXTLCD_ADAPTER 61L
+#undef com_phidgets_ServoPhidget_PHIDID_UNIPOLAR_STEPPER_4MOTOR
+#define com_phidgets_ServoPhidget_PHIDID_UNIPOLAR_STEPPER_4MOTOR 122L
+#undef com_phidgets_ServoPhidget_PHIDID_ACCELEROMETER_2AXIS
+#define com_phidgets_ServoPhidget_PHIDID_ACCELEROMETER_2AXIS 113L
+#undef com_phidgets_ServoPhidget_PHIDID_INTERFACEKIT_0_8_8_w_LCD
+#define com_phidgets_ServoPhidget_PHIDID_INTERFACEKIT_0_8_8_w_LCD 83L
+#undef com_phidgets_ServoPhidget_PHIDID_INTERFACEKIT_4_8_8
+#define com_phidgets_ServoPhidget_PHIDID_INTERFACEKIT_4_8_8 4L
+#undef com_phidgets_ServoPhidget_PHIDID_RFID
+#define com_phidgets_ServoPhidget_PHIDID_RFID 48L
+#undef com_phidgets_ServoPhidget_PHIDID_SERVO_1MOTOR_OLD
+#define com_phidgets_ServoPhidget_PHIDID_SERVO_1MOTOR_OLD 2L
+#undef com_phidgets_ServoPhidget_PHIDID_SERVO_4MOTOR
+#define com_phidgets_ServoPhidget_PHIDID_SERVO_4MOTOR 56L
+#undef com_phidgets_ServoPhidget_PHIDID_SERVO_4MOTOR_OLD
+#define com_phidgets_ServoPhidget_PHIDID_SERVO_4MOTOR_OLD 3L
+#undef com_phidgets_ServoPhidget_PHIDID_TEXTLCD_2x20
+#define com_phidgets_ServoPhidget_PHIDID_TEXTLCD_2x20 82L
+#undef com_phidgets_ServoPhidget_PHIDID_TEXTLCD_2x20_w_0_8_8
+#define com_phidgets_ServoPhidget_PHIDID_TEXTLCD_2x20_w_0_8_8 339L
+#undef com_phidgets_ServoPhidget_PHIDID_TEXTLED_1x8
+#define com_phidgets_ServoPhidget_PHIDID_TEXTLED_1x8 73L
+#undef com_phidgets_ServoPhidget_PHIDID_TEXTLED_4x8
+#define com_phidgets_ServoPhidget_PHIDID_TEXTLED_4x8 72L
+#undef com_phidgets_ServoPhidget_PHIDID_WEIGHTSENSOR
+#define com_phidgets_ServoPhidget_PHIDID_WEIGHTSENSOR 114L
+#undef com_phidgets_ServoPhidget_PHIDCLASS_NOTHING
+#define com_phidgets_ServoPhidget_PHIDCLASS_NOTHING 1L
+#undef com_phidgets_ServoPhidget_PHIDCLASS_ACCELEROMETER
+#define com_phidgets_ServoPhidget_PHIDCLASS_ACCELEROMETER 2L
+#undef com_phidgets_ServoPhidget_PHIDCLASS_ADVANCEDSERVO
+#define com_phidgets_ServoPhidget_PHIDCLASS_ADVANCEDSERVO 3L
+#undef com_phidgets_ServoPhidget_PHIDCLASS_ANALOG
+#define com_phidgets_ServoPhidget_PHIDCLASS_ANALOG 22L
+#undef com_phidgets_ServoPhidget_PHIDCLASS_BRIDGE
+#define com_phidgets_ServoPhidget_PHIDCLASS_BRIDGE 23L
+#undef com_phidgets_ServoPhidget_PHIDCLASS_ENCODER
+#define com_phidgets_ServoPhidget_PHIDCLASS_ENCODER 4L
+#undef com_phidgets_ServoPhidget_PHIDCLASS_FREQUENCYCOUNTER
+#define com_phidgets_ServoPhidget_PHIDCLASS_FREQUENCYCOUNTER 21L
+#undef com_phidgets_ServoPhidget_PHIDCLASS_GPS
+#define com_phidgets_ServoPhidget_PHIDCLASS_GPS 5L
+#undef com_phidgets_ServoPhidget_PHIDCLASS_INTERFACEKIT
+#define com_phidgets_ServoPhidget_PHIDCLASS_INTERFACEKIT 7L
+#undef com_phidgets_ServoPhidget_PHIDCLASS_LED
+#define com_phidgets_ServoPhidget_PHIDCLASS_LED 8L
+#undef com_phidgets_ServoPhidget_PHIDCLASS_MOTORCONTROL
+#define com_phidgets_ServoPhidget_PHIDCLASS_MOTORCONTROL 9L
+#undef com_phidgets_ServoPhidget_PHIDCLASS_PHSENSOR
+#define com_phidgets_ServoPhidget_PHIDCLASS_PHSENSOR 10L
+#undef com_phidgets_ServoPhidget_PHIDCLASS_RFID
+#define com_phidgets_ServoPhidget_PHIDCLASS_RFID 11L
+#undef com_phidgets_ServoPhidget_PHIDCLASS_SERVO
+#define com_phidgets_ServoPhidget_PHIDCLASS_SERVO 12L
+#undef com_phidgets_ServoPhidget_PHIDCLASS_STEPPER
+#define com_phidgets_ServoPhidget_PHIDCLASS_STEPPER 13L
+#undef com_phidgets_ServoPhidget_PHIDCLASS_TEMPERATURESENSOR
+#define com_phidgets_ServoPhidget_PHIDCLASS_TEMPERATURESENSOR 14L
+#undef com_phidgets_ServoPhidget_PHIDCLASS_TEXTLCD
+#define com_phidgets_ServoPhidget_PHIDCLASS_TEXTLCD 15L
+#undef com_phidgets_ServoPhidget_PHIDCLASS_TEXTLED
+#define com_phidgets_ServoPhidget_PHIDCLASS_TEXTLED 16L
+#undef com_phidgets_ServoPhidget_PHIDCLASS_WEIGHTSENSOR
+#define com_phidgets_ServoPhidget_PHIDCLASS_WEIGHTSENSOR 17L
+#undef com_phidgets_ServoPhidget_PHIDGET_SERVO_DEFAULT
+#define com_phidgets_ServoPhidget_PHIDGET_SERVO_DEFAULT 1L
+#undef com_phidgets_ServoPhidget_PHIDGET_SERVO_RAW_us_MODE
+#define com_phidgets_ServoPhidget_PHIDGET_SERVO_RAW_us_MODE 2L
+#undef com_phidgets_ServoPhidget_PHIDGET_SERVO_HITEC_HS322HD
+#define com_phidgets_ServoPhidget_PHIDGET_SERVO_HITEC_HS322HD 3L
+#undef com_phidgets_ServoPhidget_PHIDGET_SERVO_HITEC_HS5245MG
+#define com_phidgets_ServoPhidget_PHIDGET_SERVO_HITEC_HS5245MG 4L
+#undef com_phidgets_ServoPhidget_PHIDGET_SERVO_HITEC_805BB
+#define com_phidgets_ServoPhidget_PHIDGET_SERVO_HITEC_805BB 5L
+#undef com_phidgets_ServoPhidget_PHIDGET_SERVO_HITEC_HS422
+#define com_phidgets_ServoPhidget_PHIDGET_SERVO_HITEC_HS422 6L
+#undef com_phidgets_ServoPhidget_PHIDGET_SERVO_TOWERPRO_MG90
+#define com_phidgets_ServoPhidget_PHIDGET_SERVO_TOWERPRO_MG90 7L
+#undef com_phidgets_ServoPhidget_PHIDGET_SERVO_HITEC_HSR1425CR
+#define com_phidgets_ServoPhidget_PHIDGET_SERVO_HITEC_HSR1425CR 8L
+#undef com_phidgets_ServoPhidget_PHIDGET_SERVO_HITEC_HS785HB
+#define com_phidgets_ServoPhidget_PHIDGET_SERVO_HITEC_HS785HB 9L
+#undef com_phidgets_ServoPhidget_PHIDGET_SERVO_HITEC_HS485HB
+#define com_phidgets_ServoPhidget_PHIDGET_SERVO_HITEC_HS485HB 10L
+#undef com_phidgets_ServoPhidget_PHIDGET_SERVO_HITEC_HS645MG
+#define com_phidgets_ServoPhidget_PHIDGET_SERVO_HITEC_HS645MG 11L
+#undef com_phidgets_ServoPhidget_PHIDGET_SERVO_HITEC_815BB
+#define com_phidgets_ServoPhidget_PHIDGET_SERVO_HITEC_815BB 12L
+#undef com_phidgets_ServoPhidget_PHIDGET_SERVO_FIRGELLI_L12_30_50_06_R
+#define com_phidgets_ServoPhidget_PHIDGET_SERVO_FIRGELLI_L12_30_50_06_R 13L
+#undef com_phidgets_ServoPhidget_PHIDGET_SERVO_FIRGELLI_L12_50_100_06_R
+#define com_phidgets_ServoPhidget_PHIDGET_SERVO_FIRGELLI_L12_50_100_06_R 14L
+#undef com_phidgets_ServoPhidget_PHIDGET_SERVO_FIRGELLI_L12_50_210_06_R
+#define com_phidgets_ServoPhidget_PHIDGET_SERVO_FIRGELLI_L12_50_210_06_R 15L
+#undef com_phidgets_ServoPhidget_PHIDGET_SERVO_FIRGELLI_L12_100_50_06_R
+#define com_phidgets_ServoPhidget_PHIDGET_SERVO_FIRGELLI_L12_100_50_06_R 16L
+#undef com_phidgets_ServoPhidget_PHIDGET_SERVO_FIRGELLI_L12_100_100_06_R
+#define com_phidgets_ServoPhidget_PHIDGET_SERVO_FIRGELLI_L12_100_100_06_R 17L
+#undef com_phidgets_ServoPhidget_PHIDGET_SERVO_SPRINGRC_SM_S2313M
+#define com_phidgets_ServoPhidget_PHIDGET_SERVO_SPRINGRC_SM_S2313M 18L
+#undef com_phidgets_ServoPhidget_PHIDGET_SERVO_SPRINGRC_SM_S3317M
+#define com_phidgets_ServoPhidget_PHIDGET_SERVO_SPRINGRC_SM_S3317M 19L
+#undef com_phidgets_ServoPhidget_PHIDGET_SERVO_SPRINGRC_SM_S3317SR
+#define com_phidgets_ServoPhidget_PHIDGET_SERVO_SPRINGRC_SM_S3317SR 20L
+#undef com_phidgets_ServoPhidget_PHIDGET_SERVO_SPRINGRC_SM_S4303R
+#define com_phidgets_ServoPhidget_PHIDGET_SERVO_SPRINGRC_SM_S4303R 21L
+#undef com_phidgets_ServoPhidget_PHIDGET_SERVO_SPRINGRC_SM_S4315M
+#define com_phidgets_ServoPhidget_PHIDGET_SERVO_SPRINGRC_SM_S4315M 22L
+#undef com_phidgets_ServoPhidget_PHIDGET_SERVO_SPRINGRC_SM_S4315R
+#define com_phidgets_ServoPhidget_PHIDGET_SERVO_SPRINGRC_SM_S4315R 23L
+#undef com_phidgets_ServoPhidget_PHIDGET_SERVO_SPRINGRC_SM_S4505B
+#define com_phidgets_ServoPhidget_PHIDGET_SERVO_SPRINGRC_SM_S4505B 24L
+#undef com_phidgets_ServoPhidget_PHIDGET_SERVO_USER_DEFINED
+#define com_phidgets_ServoPhidget_PHIDGET_SERVO_USER_DEFINED 25L
+/*
+ * Class: com_phidgets_ServoPhidget
+ * Method: create
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL Java_com_phidgets_ServoPhidget_create
+ (JNIEnv *, jclass);
+
+/*
+ * Class: com_phidgets_ServoPhidget
+ * Method: getMotorCount
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_phidgets_ServoPhidget_getMotorCount
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_ServoPhidget
+ * Method: getPosition
+ * Signature: (I)D
+ */
+JNIEXPORT jdouble JNICALL Java_com_phidgets_ServoPhidget_getPosition
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_ServoPhidget
+ * Method: getPositionMax
+ * Signature: (I)D
+ */
+JNIEXPORT jdouble JNICALL Java_com_phidgets_ServoPhidget_getPositionMax
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_ServoPhidget
+ * Method: getPositionMin
+ * Signature: (I)D
+ */
+JNIEXPORT jdouble JNICALL Java_com_phidgets_ServoPhidget_getPositionMin
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_ServoPhidget
+ * Method: setPosition
+ * Signature: (ID)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_ServoPhidget_setPosition
+ (JNIEnv *, jobject, jint, jdouble);
+
+/*
+ * Class: com_phidgets_ServoPhidget
+ * Method: setEngaged
+ * Signature: (IZ)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_ServoPhidget_setEngaged
+ (JNIEnv *, jobject, jint, jboolean);
+
+/*
+ * Class: com_phidgets_ServoPhidget
+ * Method: setMotorOn
+ * Signature: (IZ)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_ServoPhidget_setMotorOn
+ (JNIEnv *, jobject, jint, jboolean);
+
+/*
+ * Class: com_phidgets_ServoPhidget
+ * Method: getEngaged
+ * Signature: (I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_phidgets_ServoPhidget_getEngaged
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_ServoPhidget
+ * Method: getMotorOn
+ * Signature: (I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_phidgets_ServoPhidget_getMotorOn
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_ServoPhidget
+ * Method: getServoType
+ * Signature: (I)I
+ */
+JNIEXPORT jint JNICALL Java_com_phidgets_ServoPhidget_getServoType
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_ServoPhidget
+ * Method: setServoType
+ * Signature: (II)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_ServoPhidget_setServoType
+ (JNIEnv *, jobject, jint, jint);
+
+/*
+ * Class: com_phidgets_ServoPhidget
+ * Method: setServoParameters
+ * Signature: (IDDD)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_ServoPhidget_setServoParameters
+ (JNIEnv *, jobject, jint, jdouble, jdouble, jdouble);
+
+/*
+ * Class: com_phidgets_ServoPhidget
+ * Method: enableServoPositionChangeEvents
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_ServoPhidget_enableServoPositionChangeEvents
+ (JNIEnv *, jobject, jboolean);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/Java/com_phidgets_SpatialPhidget.c b/Java/com_phidgets_SpatialPhidget.c
new file mode 100644
index 0000000..361b989
--- /dev/null
+++ b/Java/com_phidgets_SpatialPhidget.c
@@ -0,0 +1,166 @@
+#include "../stdafx.h"
+#include "phidget_jni.h"
+#include "com_phidgets_SpatialPhidget.h"
+#include "../cphidgetspatial.h"
+
+EVENT_VARS(spatialData, SpatialData)
+
+static jclass spatialEventData_class; //class
+static jmethodID spatialEventData_cons; //constructor
+
+JNI_LOAD(spatial, Spatial)
+ EVENT_VAR_SETUP(spatial, spatialData, SpatialData, [Lcom/phidgets/SpatialEventData;, V)
+
+ if (!(spatialEventData_class = (*env)->FindClass(env,"com/phidgets/SpatialEventData")))
+ JNI_ABORT_STDERR("Couldn't FindClass com/phidgets/SpatialEventData");
+ if (!(spatialEventData_class = (jclass)(*env)->NewGlobalRef(env, spatialEventData_class)))
+ JNI_ABORT_STDERR("Couldn't create global ref spatialEventData_class");
+ if (!(spatialEventData_cons = (*env)->GetMethodID(env, spatialEventData_class, "<init>", "([D[D[DII)V")))
+ JNI_ABORT_STDERR("Couldn't get method ID <init> from spatialEventData_class");
+}
+
+//SpatialData event
+static int CCONV spatialData_handler(CPhidgetSpatialHandle h, void *arg, CPhidgetSpatial_SpatialEventDataHandle *, int);
+JNIEXPORT void JNICALL
+Java_com_phidgets_SpatialPhidget_enableSpatialDataEvents(JNIEnv *env, jobject obj, jboolean b)
+{
+ jlong gr = updateGlobalRef(env, obj, nativeSpatialDataHandler_fid, b);
+ CPhidgetSpatialHandle h = (CPhidgetSpatialHandle)(uintptr_t)(*env)->GetLongField(env, obj, handle_fid);
+ CPhidgetSpatial_set_OnSpatialData_Handler(h, b ? spatialData_handler : 0, (void *)(uintptr_t)gr);
+}
+static int CCONV
+spatialData_handler(CPhidgetSpatialHandle h, void *arg, CPhidgetSpatial_SpatialEventDataHandle *data, int dataLength)
+{
+ JNIEnv *env;
+ jobject obj;
+ jobject spatialDataEv;
+ jobjectArray jo;
+ int i, j;
+
+ if ((*ph_vm)->AttachCurrentThread(ph_vm, (JNIEnvPtr)&env, NULL))
+ JNI_ABORT_STDERR("Couldn't AttachCurrentThread");
+
+ obj = (jobject)arg;
+
+ //create and fill in short array
+ jo = (*env)->NewObjectArray(env, dataLength, spatialEventData_class, NULL);
+ if (!jo)
+ return -1;
+
+ for (i=0; i<dataLength; i++)
+ {
+ jdoubleArray accel, gyro, mag;
+ jdouble *datas;
+
+ //create and fill in data arrays
+ accel = (*env)->NewDoubleArray(env, h->phid.attr.spatial.numAccelAxes);
+ gyro = (*env)->NewDoubleArray(env, h->phid.attr.spatial.numGyroAxes);
+ mag = (*env)->NewDoubleArray(env, data[i]->magneticField[0]==PUNK_DBL?0:h->phid.attr.spatial.numCompassAxes);
+ if (!accel || !gyro || !mag)
+ {
+ PH_THROW(EPHIDGET_UNEXPECTED);
+ return -1;
+ }
+ if(h->phid.attr.spatial.numAccelAxes)
+ {
+ datas = (*env)->GetDoubleArrayElements(env, accel, 0);
+ if (!datas)
+ {
+ PH_THROW(EPHIDGET_UNEXPECTED);
+ return -1;
+ }
+ for (j=0; j<h->phid.attr.spatial.numAccelAxes; j++)
+ datas[j] = (jdouble)data[i]->acceleration[j];
+ (*env)->ReleaseDoubleArrayElements(env, accel, datas, 0);
+ }
+ if(h->phid.attr.spatial.numGyroAxes)
+ {
+ datas = (*env)->GetDoubleArrayElements(env, gyro, 0);
+ if (!datas)
+ {
+ PH_THROW(EPHIDGET_UNEXPECTED);
+ return -1;
+ }
+ for (j=0; j<h->phid.attr.spatial.numGyroAxes; j++)
+ datas[j] = (jdouble)data[i]->angularRate[j];
+ (*env)->ReleaseDoubleArrayElements(env, gyro, datas, 0);
+ }
+ if(data[i]->magneticField[0]==PUNK_DBL?0:h->phid.attr.spatial.numCompassAxes)
+ {
+ datas = (*env)->GetDoubleArrayElements(env, mag, 0);
+ if (!datas)
+ {
+ PH_THROW(EPHIDGET_UNEXPECTED);
+ return -1;
+ }
+ for (j=0; j<h->phid.attr.spatial.numCompassAxes; j++)
+ datas[j] = (jdouble)data[i]->magneticField[j];
+ (*env)->ReleaseDoubleArrayElements(env, mag, datas, 0);
+ }
+
+ //create and add the SpatialEventData object to its array
+ (*env)->SetObjectArrayElement(env,jo,i,(*env)->NewObject(env, spatialEventData_class, spatialEventData_cons, accel, gyro, mag, data[i]->timestamp.seconds, data[i]->timestamp.microseconds));
+ }
+
+ if (!(spatialDataEv = (*env)->NewObject(env, spatialDataEvent_class, spatialDataEvent_cons, obj, jo)))
+ {
+ return -1;
+ }
+
+ (*env)->CallVoidMethod(env, obj, fireSpatialData_mid, spatialDataEv);
+
+ (*env)->DeleteLocalRef(env, spatialDataEv);
+ (*ph_vm)->DetachCurrentThread(ph_vm);
+
+ return 0;
+}
+
+JNI_CREATE(Spatial)
+
+JNI_INDEXED_GETFUNC(Spatial, AccelerationMax, AccelerationMax, jdouble)
+JNI_INDEXED_GETFUNC(Spatial, AccelerationMin, AccelerationMin, jdouble)
+JNI_INDEXED_GETFUNC(Spatial, Acceleration, Acceleration, jdouble)
+JNI_GETFUNC(Spatial, AccelerationAxisCount, AccelerationAxisCount, jint)
+
+JNI_INDEXED_GETFUNC(Spatial, AngularRateMax, AngularRateMax, jdouble)
+JNI_INDEXED_GETFUNC(Spatial, AngularRateMin, AngularRateMin, jdouble)
+JNI_INDEXED_GETFUNC(Spatial, AngularRate, AngularRate, jdouble)
+JNI_GETFUNC(Spatial, GyroAxisCount, GyroAxisCount, jint)
+
+JNI_INDEXED_GETFUNC(Spatial, MagneticFieldMax, MagneticFieldMax, jdouble)
+JNI_INDEXED_GETFUNC(Spatial, MagneticFieldMin, MagneticFieldMin, jdouble)
+JNI_INDEXED_GETFUNC(Spatial, MagneticField, MagneticField, jdouble)
+JNI_GETFUNC(Spatial, CompassAxisCount, CompassAxisCount, jint)
+
+JNI_GETFUNC(Spatial, DataRateMin, DataRateMin, jint)
+JNI_GETFUNC(Spatial, DataRateMax, DataRateMax, jint)
+JNI_GETFUNC(Spatial, DataRate, DataRate, jint)
+JNI_SETFUNC(Spatial, DataRate, DataRate, jint)
+
+JNIEXPORT void JNICALL Java_com_phidgets_SpatialPhidget_zeroGyro (JNIEnv *env, jobject obj)
+{
+ CPhidgetSpatialHandle h = (CPhidgetSpatialHandle)(uintptr_t)(*env)->GetLongField( env, obj, handle_fid);
+ int error;
+ if ((error = CPhidgetSpatial_zeroGyro(h)))
+ PH_THROW(error);
+}
+
+JNIEXPORT void JNICALL Java_com_phidgets_SpatialPhidget_setCompassCorrectionParameters (JNIEnv *env, jobject obj,
+ jdouble magField,
+ jdouble offset0, jdouble offset1, jdouble offset2,
+ jdouble gain0, jdouble gain1, jdouble gain2,
+ jdouble T0, jdouble T1, jdouble T2, jdouble T3, jdouble T4, jdouble T5)
+{
+ CPhidgetSpatialHandle h = (CPhidgetSpatialHandle)(uintptr_t)(*env)->GetLongField( env, obj, handle_fid);
+ int error;
+ if ((error = CPhidgetSpatial_setCompassCorrectionParameters(h, magField, offset0, offset1, offset2, gain0, gain1, gain2, T0, T1, T2, T3, T4, T5)))
+ PH_THROW(error);
+}
+
+JNIEXPORT void JNICALL Java_com_phidgets_SpatialPhidget_resetCompassCorrectionParameters (JNIEnv *env, jobject obj)
+{
+ CPhidgetSpatialHandle h = (CPhidgetSpatialHandle)(uintptr_t)(*env)->GetLongField( env, obj, handle_fid);
+ int error;
+ if ((error = CPhidgetSpatial_resetCompassCorrectionParameters(h)))
+ PH_THROW(error);
+}
diff --git a/Java/com_phidgets_SpatialPhidget.h b/Java/com_phidgets_SpatialPhidget.h
new file mode 100644
index 0000000..ef1ba3e
--- /dev/null
+++ b/Java/com_phidgets_SpatialPhidget.h
@@ -0,0 +1,325 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class com_phidgets_SpatialPhidget */
+
+#ifndef _Included_com_phidgets_SpatialPhidget
+#define _Included_com_phidgets_SpatialPhidget
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef com_phidgets_SpatialPhidget_PHIDGET_LOG_CRITICAL
+#define com_phidgets_SpatialPhidget_PHIDGET_LOG_CRITICAL 1L
+#undef com_phidgets_SpatialPhidget_PHIDGET_LOG_ERROR
+#define com_phidgets_SpatialPhidget_PHIDGET_LOG_ERROR 2L
+#undef com_phidgets_SpatialPhidget_PHIDGET_LOG_WARNING
+#define com_phidgets_SpatialPhidget_PHIDGET_LOG_WARNING 3L
+#undef com_phidgets_SpatialPhidget_PHIDGET_LOG_DEBUG
+#define com_phidgets_SpatialPhidget_PHIDGET_LOG_DEBUG 4L
+#undef com_phidgets_SpatialPhidget_PHIDGET_LOG_INFO
+#define com_phidgets_SpatialPhidget_PHIDGET_LOG_INFO 5L
+#undef com_phidgets_SpatialPhidget_PHIDGET_LOG_VERBOSE
+#define com_phidgets_SpatialPhidget_PHIDGET_LOG_VERBOSE 6L
+#undef com_phidgets_SpatialPhidget_PHIDID_NOTHING
+#define com_phidgets_SpatialPhidget_PHIDID_NOTHING 1L
+#undef com_phidgets_SpatialPhidget_PHIDID_ACCELEROMETER_3AXIS
+#define com_phidgets_SpatialPhidget_PHIDID_ACCELEROMETER_3AXIS 126L
+#undef com_phidgets_SpatialPhidget_PHIDID_ADVANCEDSERVO_1MOTOR
+#define com_phidgets_SpatialPhidget_PHIDID_ADVANCEDSERVO_1MOTOR 130L
+#undef com_phidgets_SpatialPhidget_PHIDID_ANALOG_4OUTPUT
+#define com_phidgets_SpatialPhidget_PHIDID_ANALOG_4OUTPUT 55L
+#undef com_phidgets_SpatialPhidget_PHIDID_ADVANCEDSERVO_8MOTOR
+#define com_phidgets_SpatialPhidget_PHIDID_ADVANCEDSERVO_8MOTOR 58L
+#undef com_phidgets_SpatialPhidget_PHIDID_BIPOLAR_STEPPER_1MOTOR
+#define com_phidgets_SpatialPhidget_PHIDID_BIPOLAR_STEPPER_1MOTOR 123L
+#undef com_phidgets_SpatialPhidget_PHIDID_BRIDGE_4INPUT
+#define com_phidgets_SpatialPhidget_PHIDID_BRIDGE_4INPUT 59L
+#undef com_phidgets_SpatialPhidget_PHIDID_ENCODER_1ENCODER_1INPUT
+#define com_phidgets_SpatialPhidget_PHIDID_ENCODER_1ENCODER_1INPUT 75L
+#undef com_phidgets_SpatialPhidget_PHIDID_ENCODER_HS_1ENCODER
+#define com_phidgets_SpatialPhidget_PHIDID_ENCODER_HS_1ENCODER 128L
+#undef com_phidgets_SpatialPhidget_PHIDID_ENCODER_HS_4ENCODER_4INPUT
+#define com_phidgets_SpatialPhidget_PHIDID_ENCODER_HS_4ENCODER_4INPUT 79L
+#undef com_phidgets_SpatialPhidget_PHIDID_FREQUENCYCOUNTER_2INPUT
+#define com_phidgets_SpatialPhidget_PHIDID_FREQUENCYCOUNTER_2INPUT 53L
+#undef com_phidgets_SpatialPhidget_PHIDID_GPS
+#define com_phidgets_SpatialPhidget_PHIDID_GPS 121L
+#undef com_phidgets_SpatialPhidget_PHIDID_INTERFACEKIT_0_0_4
+#define com_phidgets_SpatialPhidget_PHIDID_INTERFACEKIT_0_0_4 64L
+#undef com_phidgets_SpatialPhidget_PHIDID_INTERFACEKIT_0_0_8
+#define com_phidgets_SpatialPhidget_PHIDID_INTERFACEKIT_0_0_8 129L
+#undef com_phidgets_SpatialPhidget_PHIDID_INTERFACEKIT_0_16_16
+#define com_phidgets_SpatialPhidget_PHIDID_INTERFACEKIT_0_16_16 68L
+#undef com_phidgets_SpatialPhidget_PHIDID_INTERFACEKIT_8_8_8
+#define com_phidgets_SpatialPhidget_PHIDID_INTERFACEKIT_8_8_8 69L
+#undef com_phidgets_SpatialPhidget_PHIDID_INTERFACEKIT_8_8_8_w_LCD
+#define com_phidgets_SpatialPhidget_PHIDID_INTERFACEKIT_8_8_8_w_LCD 125L
+#undef com_phidgets_SpatialPhidget_PHIDID_IR
+#define com_phidgets_SpatialPhidget_PHIDID_IR 77L
+#undef com_phidgets_SpatialPhidget_PHIDID_LED_64
+#define com_phidgets_SpatialPhidget_PHIDID_LED_64 74L
+#undef com_phidgets_SpatialPhidget_PHIDID_LED_64_ADV
+#define com_phidgets_SpatialPhidget_PHIDID_LED_64_ADV 76L
+#undef com_phidgets_SpatialPhidget_PHIDID_LINEAR_TOUCH
+#define com_phidgets_SpatialPhidget_PHIDID_LINEAR_TOUCH 118L
+#undef com_phidgets_SpatialPhidget_PHIDID_MOTORCONTROL_HC_2MOTOR
+#define com_phidgets_SpatialPhidget_PHIDID_MOTORCONTROL_HC_2MOTOR 89L
+#undef com_phidgets_SpatialPhidget_PHIDID_MOTORCONTROL_LV_2MOTOR_4INPUT
+#define com_phidgets_SpatialPhidget_PHIDID_MOTORCONTROL_LV_2MOTOR_4INPUT 88L
+#undef com_phidgets_SpatialPhidget_PHIDID_MOTORCONTROL_1MOTOR
+#define com_phidgets_SpatialPhidget_PHIDID_MOTORCONTROL_1MOTOR 62L
+#undef com_phidgets_SpatialPhidget_PHIDID_PHSENSOR
+#define com_phidgets_SpatialPhidget_PHIDID_PHSENSOR 116L
+#undef com_phidgets_SpatialPhidget_PHIDID_RFID_2OUTPUT
+#define com_phidgets_SpatialPhidget_PHIDID_RFID_2OUTPUT 49L
+#undef com_phidgets_SpatialPhidget_PHIDID_ROTARY_TOUCH
+#define com_phidgets_SpatialPhidget_PHIDID_ROTARY_TOUCH 119L
+#undef com_phidgets_SpatialPhidget_PHIDID_SERVO_1MOTOR
+#define com_phidgets_SpatialPhidget_PHIDID_SERVO_1MOTOR 57L
+#undef com_phidgets_SpatialPhidget_PHIDID_SPATIAL_ACCEL_3AXIS
+#define com_phidgets_SpatialPhidget_PHIDID_SPATIAL_ACCEL_3AXIS 127L
+#undef com_phidgets_SpatialPhidget_PHIDID_SPATIAL_ACCEL_GYRO_COMPASS
+#define com_phidgets_SpatialPhidget_PHIDID_SPATIAL_ACCEL_GYRO_COMPASS 51L
+#undef com_phidgets_SpatialPhidget_PHIDID_TEMPERATURESENSOR
+#define com_phidgets_SpatialPhidget_PHIDID_TEMPERATURESENSOR 112L
+#undef com_phidgets_SpatialPhidget_PHIDID_TEMPERATURESENSOR_4
+#define com_phidgets_SpatialPhidget_PHIDID_TEMPERATURESENSOR_4 50L
+#undef com_phidgets_SpatialPhidget_PHIDID_TEXTLCD_2x20_w_8_8_8
+#define com_phidgets_SpatialPhidget_PHIDID_TEXTLCD_2x20_w_8_8_8 381L
+#undef com_phidgets_SpatialPhidget_PHIDID_TEXTLCD_ADAPTER
+#define com_phidgets_SpatialPhidget_PHIDID_TEXTLCD_ADAPTER 61L
+#undef com_phidgets_SpatialPhidget_PHIDID_UNIPOLAR_STEPPER_4MOTOR
+#define com_phidgets_SpatialPhidget_PHIDID_UNIPOLAR_STEPPER_4MOTOR 122L
+#undef com_phidgets_SpatialPhidget_PHIDID_ACCELEROMETER_2AXIS
+#define com_phidgets_SpatialPhidget_PHIDID_ACCELEROMETER_2AXIS 113L
+#undef com_phidgets_SpatialPhidget_PHIDID_INTERFACEKIT_0_8_8_w_LCD
+#define com_phidgets_SpatialPhidget_PHIDID_INTERFACEKIT_0_8_8_w_LCD 83L
+#undef com_phidgets_SpatialPhidget_PHIDID_INTERFACEKIT_4_8_8
+#define com_phidgets_SpatialPhidget_PHIDID_INTERFACEKIT_4_8_8 4L
+#undef com_phidgets_SpatialPhidget_PHIDID_RFID
+#define com_phidgets_SpatialPhidget_PHIDID_RFID 48L
+#undef com_phidgets_SpatialPhidget_PHIDID_SERVO_1MOTOR_OLD
+#define com_phidgets_SpatialPhidget_PHIDID_SERVO_1MOTOR_OLD 2L
+#undef com_phidgets_SpatialPhidget_PHIDID_SERVO_4MOTOR
+#define com_phidgets_SpatialPhidget_PHIDID_SERVO_4MOTOR 56L
+#undef com_phidgets_SpatialPhidget_PHIDID_SERVO_4MOTOR_OLD
+#define com_phidgets_SpatialPhidget_PHIDID_SERVO_4MOTOR_OLD 3L
+#undef com_phidgets_SpatialPhidget_PHIDID_TEXTLCD_2x20
+#define com_phidgets_SpatialPhidget_PHIDID_TEXTLCD_2x20 82L
+#undef com_phidgets_SpatialPhidget_PHIDID_TEXTLCD_2x20_w_0_8_8
+#define com_phidgets_SpatialPhidget_PHIDID_TEXTLCD_2x20_w_0_8_8 339L
+#undef com_phidgets_SpatialPhidget_PHIDID_TEXTLED_1x8
+#define com_phidgets_SpatialPhidget_PHIDID_TEXTLED_1x8 73L
+#undef com_phidgets_SpatialPhidget_PHIDID_TEXTLED_4x8
+#define com_phidgets_SpatialPhidget_PHIDID_TEXTLED_4x8 72L
+#undef com_phidgets_SpatialPhidget_PHIDID_WEIGHTSENSOR
+#define com_phidgets_SpatialPhidget_PHIDID_WEIGHTSENSOR 114L
+#undef com_phidgets_SpatialPhidget_PHIDCLASS_NOTHING
+#define com_phidgets_SpatialPhidget_PHIDCLASS_NOTHING 1L
+#undef com_phidgets_SpatialPhidget_PHIDCLASS_ACCELEROMETER
+#define com_phidgets_SpatialPhidget_PHIDCLASS_ACCELEROMETER 2L
+#undef com_phidgets_SpatialPhidget_PHIDCLASS_ADVANCEDSERVO
+#define com_phidgets_SpatialPhidget_PHIDCLASS_ADVANCEDSERVO 3L
+#undef com_phidgets_SpatialPhidget_PHIDCLASS_ANALOG
+#define com_phidgets_SpatialPhidget_PHIDCLASS_ANALOG 22L
+#undef com_phidgets_SpatialPhidget_PHIDCLASS_BRIDGE
+#define com_phidgets_SpatialPhidget_PHIDCLASS_BRIDGE 23L
+#undef com_phidgets_SpatialPhidget_PHIDCLASS_ENCODER
+#define com_phidgets_SpatialPhidget_PHIDCLASS_ENCODER 4L
+#undef com_phidgets_SpatialPhidget_PHIDCLASS_FREQUENCYCOUNTER
+#define com_phidgets_SpatialPhidget_PHIDCLASS_FREQUENCYCOUNTER 21L
+#undef com_phidgets_SpatialPhidget_PHIDCLASS_GPS
+#define com_phidgets_SpatialPhidget_PHIDCLASS_GPS 5L
+#undef com_phidgets_SpatialPhidget_PHIDCLASS_INTERFACEKIT
+#define com_phidgets_SpatialPhidget_PHIDCLASS_INTERFACEKIT 7L
+#undef com_phidgets_SpatialPhidget_PHIDCLASS_LED
+#define com_phidgets_SpatialPhidget_PHIDCLASS_LED 8L
+#undef com_phidgets_SpatialPhidget_PHIDCLASS_MOTORCONTROL
+#define com_phidgets_SpatialPhidget_PHIDCLASS_MOTORCONTROL 9L
+#undef com_phidgets_SpatialPhidget_PHIDCLASS_PHSENSOR
+#define com_phidgets_SpatialPhidget_PHIDCLASS_PHSENSOR 10L
+#undef com_phidgets_SpatialPhidget_PHIDCLASS_RFID
+#define com_phidgets_SpatialPhidget_PHIDCLASS_RFID 11L
+#undef com_phidgets_SpatialPhidget_PHIDCLASS_SERVO
+#define com_phidgets_SpatialPhidget_PHIDCLASS_SERVO 12L
+#undef com_phidgets_SpatialPhidget_PHIDCLASS_STEPPER
+#define com_phidgets_SpatialPhidget_PHIDCLASS_STEPPER 13L
+#undef com_phidgets_SpatialPhidget_PHIDCLASS_TEMPERATURESENSOR
+#define com_phidgets_SpatialPhidget_PHIDCLASS_TEMPERATURESENSOR 14L
+#undef com_phidgets_SpatialPhidget_PHIDCLASS_TEXTLCD
+#define com_phidgets_SpatialPhidget_PHIDCLASS_TEXTLCD 15L
+#undef com_phidgets_SpatialPhidget_PHIDCLASS_TEXTLED
+#define com_phidgets_SpatialPhidget_PHIDCLASS_TEXTLED 16L
+#undef com_phidgets_SpatialPhidget_PHIDCLASS_WEIGHTSENSOR
+#define com_phidgets_SpatialPhidget_PHIDCLASS_WEIGHTSENSOR 17L
+/*
+ * Class: com_phidgets_SpatialPhidget
+ * Method: create
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL Java_com_phidgets_SpatialPhidget_create
+ (JNIEnv *, jclass);
+
+/*
+ * Class: com_phidgets_SpatialPhidget
+ * Method: getAccelerationAxisCount
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_phidgets_SpatialPhidget_getAccelerationAxisCount
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_SpatialPhidget
+ * Method: getAcceleration
+ * Signature: (I)D
+ */
+JNIEXPORT jdouble JNICALL Java_com_phidgets_SpatialPhidget_getAcceleration
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_SpatialPhidget
+ * Method: getAccelerationMax
+ * Signature: (I)D
+ */
+JNIEXPORT jdouble JNICALL Java_com_phidgets_SpatialPhidget_getAccelerationMax
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_SpatialPhidget
+ * Method: getAccelerationMin
+ * Signature: (I)D
+ */
+JNIEXPORT jdouble JNICALL Java_com_phidgets_SpatialPhidget_getAccelerationMin
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_SpatialPhidget
+ * Method: getGyroAxisCount
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_phidgets_SpatialPhidget_getGyroAxisCount
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_SpatialPhidget
+ * Method: getAngularRate
+ * Signature: (I)D
+ */
+JNIEXPORT jdouble JNICALL Java_com_phidgets_SpatialPhidget_getAngularRate
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_SpatialPhidget
+ * Method: getAngularRateMax
+ * Signature: (I)D
+ */
+JNIEXPORT jdouble JNICALL Java_com_phidgets_SpatialPhidget_getAngularRateMax
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_SpatialPhidget
+ * Method: getAngularRateMin
+ * Signature: (I)D
+ */
+JNIEXPORT jdouble JNICALL Java_com_phidgets_SpatialPhidget_getAngularRateMin
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_SpatialPhidget
+ * Method: getCompassAxisCount
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_phidgets_SpatialPhidget_getCompassAxisCount
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_SpatialPhidget
+ * Method: getMagneticField
+ * Signature: (I)D
+ */
+JNIEXPORT jdouble JNICALL Java_com_phidgets_SpatialPhidget_getMagneticField
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_SpatialPhidget
+ * Method: getMagneticFieldMax
+ * Signature: (I)D
+ */
+JNIEXPORT jdouble JNICALL Java_com_phidgets_SpatialPhidget_getMagneticFieldMax
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_SpatialPhidget
+ * Method: getMagneticFieldMin
+ * Signature: (I)D
+ */
+JNIEXPORT jdouble JNICALL Java_com_phidgets_SpatialPhidget_getMagneticFieldMin
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_SpatialPhidget
+ * Method: getDataRate
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_phidgets_SpatialPhidget_getDataRate
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_SpatialPhidget
+ * Method: setDataRate
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_SpatialPhidget_setDataRate
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_SpatialPhidget
+ * Method: getDataRateMin
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_phidgets_SpatialPhidget_getDataRateMin
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_SpatialPhidget
+ * Method: getDataRateMax
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_phidgets_SpatialPhidget_getDataRateMax
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_SpatialPhidget
+ * Method: zeroGyro
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_SpatialPhidget_zeroGyro
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_SpatialPhidget
+ * Method: setCompassCorrectionParameters
+ * Signature: (DDDDDDDDDDDDD)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_SpatialPhidget_setCompassCorrectionParameters
+ (JNIEnv *, jobject, jdouble, jdouble, jdouble, jdouble, jdouble, jdouble, jdouble, jdouble, jdouble, jdouble, jdouble, jdouble, jdouble);
+
+/*
+ * Class: com_phidgets_SpatialPhidget
+ * Method: resetCompassCorrectionParameters
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_SpatialPhidget_resetCompassCorrectionParameters
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_SpatialPhidget
+ * Method: enableSpatialDataEvents
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_SpatialPhidget_enableSpatialDataEvents
+ (JNIEnv *, jobject, jboolean);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/Java/com_phidgets_StepperPhidget.c b/Java/com_phidgets_StepperPhidget.c
new file mode 100644
index 0000000..bdc12a6
--- /dev/null
+++ b/Java/com_phidgets_StepperPhidget.c
@@ -0,0 +1,53 @@
+#include "../stdafx.h"
+#include "phidget_jni.h"
+#include "com_phidgets_StepperPhidget.h"
+#include "../cphidgetstepper.h"
+
+EVENT_VARS(stepperPositionChange, StepperPositionChange)
+EVENT_VARS(inputChange, InputChange)
+EVENT_VARS(stepperVelocityChange, StepperVelocityChange)
+EVENT_VARS(currentChange, CurrentChange)
+
+JNI_LOAD(stepper, Stepper)
+ EVENT_VAR_SETUP(stepper, stepperPositionChange, StepperPositionChange, IJ, V)
+ EVENT_VAR_SETUP(stepper, inputChange, InputChange, IZ, V)
+ EVENT_VAR_SETUP(stepper, stepperVelocityChange, StepperVelocityChange, ID, V)
+ EVENT_VAR_SETUP(stepper, currentChange, CurrentChange, ID, V)
+}
+
+EVENT_HANDLER_INDEXED(Stepper, stepperPositionChange, StepperPositionChange,
+ CPhidgetStepper_set_OnPositionChange_Handler, long long)
+EVENT_HANDLER_INDEXED(Stepper, inputChange, InputChange,
+ CPhidgetStepper_set_OnInputChange_Handler, int)
+EVENT_HANDLER_INDEXED(Stepper, stepperVelocityChange, StepperVelocityChange,
+ CPhidgetStepper_set_OnVelocityChange_Handler, double)
+EVENT_HANDLER_INDEXED(Stepper, currentChange, CurrentChange,
+ CPhidgetStepper_set_OnCurrentChange_Handler, double)
+
+JNI_CREATE(Stepper)
+JNI_INDEXED_GETFUNC(Stepper, Acceleration, Acceleration, jdouble)
+JNI_INDEXED_SETFUNC(Stepper, Acceleration, Acceleration, jdouble)
+JNI_INDEXED_GETFUNC(Stepper, AccelerationMin, AccelerationMin, jdouble)
+JNI_INDEXED_GETFUNC(Stepper, AccelerationMax, AccelerationMax, jdouble)
+JNI_INDEXED_GETFUNC(Stepper, Velocity, Velocity, jdouble)
+JNI_INDEXED_SETFUNC(Stepper, VelocityLimit, VelocityLimit, jdouble)
+JNI_INDEXED_GETFUNC(Stepper, VelocityLimit, VelocityLimit, jdouble)
+JNI_INDEXED_GETFUNC(Stepper, VelocityMin, VelocityMin, jdouble)
+JNI_INDEXED_GETFUNC(Stepper, VelocityMax, VelocityMax, jdouble)
+JNI_INDEXED_GETFUNC(Stepper, TargetPosition, TargetPosition, jlong)
+JNI_INDEXED_SETFUNC(Stepper, TargetPosition, TargetPosition, jlong)
+JNI_INDEXED_GETFUNC(Stepper, CurrentPosition, CurrentPosition, jlong)
+JNI_INDEXED_SETFUNC(Stepper, CurrentPosition, CurrentPosition, jlong)
+JNI_INDEXED_GETFUNC(Stepper, PositionMin, PositionMin, jlong)
+JNI_INDEXED_GETFUNC(Stepper, PositionMax, PositionMax, jlong)
+JNI_INDEXED_GETFUNC(Stepper, Current, Current, jdouble)
+JNI_INDEXED_SETFUNC(Stepper, CurrentLimit, CurrentLimit, jdouble)
+JNI_INDEXED_GETFUNC(Stepper, CurrentLimit, CurrentLimit, jdouble)
+JNI_INDEXED_GETFUNC(Stepper, CurrentMin, CurrentMin, jdouble)
+JNI_INDEXED_GETFUNC(Stepper, CurrentMax, CurrentMax, jdouble)
+JNI_INDEXED_GETFUNCBOOL(Stepper, Stopped, Stopped)
+JNI_INDEXED_GETFUNCBOOL(Stepper, Engaged, Engaged)
+JNI_INDEXED_SETFUNC(Stepper, Engaged, Engaged, jboolean)
+JNI_INDEXED_GETFUNCBOOL(Stepper, InputState, InputState)
+JNI_GETFUNC(Stepper, MotorCount, MotorCount, jint)
+JNI_GETFUNC(Stepper, InputCount, InputCount, jint)
diff --git a/Java/com_phidgets_StepperPhidget.h b/Java/com_phidgets_StepperPhidget.h
new file mode 100644
index 0000000..a3fbfdd
--- /dev/null
+++ b/Java/com_phidgets_StepperPhidget.h
@@ -0,0 +1,405 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class com_phidgets_StepperPhidget */
+
+#ifndef _Included_com_phidgets_StepperPhidget
+#define _Included_com_phidgets_StepperPhidget
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef com_phidgets_StepperPhidget_PHIDGET_LOG_CRITICAL
+#define com_phidgets_StepperPhidget_PHIDGET_LOG_CRITICAL 1L
+#undef com_phidgets_StepperPhidget_PHIDGET_LOG_ERROR
+#define com_phidgets_StepperPhidget_PHIDGET_LOG_ERROR 2L
+#undef com_phidgets_StepperPhidget_PHIDGET_LOG_WARNING
+#define com_phidgets_StepperPhidget_PHIDGET_LOG_WARNING 3L
+#undef com_phidgets_StepperPhidget_PHIDGET_LOG_DEBUG
+#define com_phidgets_StepperPhidget_PHIDGET_LOG_DEBUG 4L
+#undef com_phidgets_StepperPhidget_PHIDGET_LOG_INFO
+#define com_phidgets_StepperPhidget_PHIDGET_LOG_INFO 5L
+#undef com_phidgets_StepperPhidget_PHIDGET_LOG_VERBOSE
+#define com_phidgets_StepperPhidget_PHIDGET_LOG_VERBOSE 6L
+#undef com_phidgets_StepperPhidget_PHIDID_NOTHING
+#define com_phidgets_StepperPhidget_PHIDID_NOTHING 1L
+#undef com_phidgets_StepperPhidget_PHIDID_ACCELEROMETER_3AXIS
+#define com_phidgets_StepperPhidget_PHIDID_ACCELEROMETER_3AXIS 126L
+#undef com_phidgets_StepperPhidget_PHIDID_ADVANCEDSERVO_1MOTOR
+#define com_phidgets_StepperPhidget_PHIDID_ADVANCEDSERVO_1MOTOR 130L
+#undef com_phidgets_StepperPhidget_PHIDID_ANALOG_4OUTPUT
+#define com_phidgets_StepperPhidget_PHIDID_ANALOG_4OUTPUT 55L
+#undef com_phidgets_StepperPhidget_PHIDID_ADVANCEDSERVO_8MOTOR
+#define com_phidgets_StepperPhidget_PHIDID_ADVANCEDSERVO_8MOTOR 58L
+#undef com_phidgets_StepperPhidget_PHIDID_BIPOLAR_STEPPER_1MOTOR
+#define com_phidgets_StepperPhidget_PHIDID_BIPOLAR_STEPPER_1MOTOR 123L
+#undef com_phidgets_StepperPhidget_PHIDID_BRIDGE_4INPUT
+#define com_phidgets_StepperPhidget_PHIDID_BRIDGE_4INPUT 59L
+#undef com_phidgets_StepperPhidget_PHIDID_ENCODER_1ENCODER_1INPUT
+#define com_phidgets_StepperPhidget_PHIDID_ENCODER_1ENCODER_1INPUT 75L
+#undef com_phidgets_StepperPhidget_PHIDID_ENCODER_HS_1ENCODER
+#define com_phidgets_StepperPhidget_PHIDID_ENCODER_HS_1ENCODER 128L
+#undef com_phidgets_StepperPhidget_PHIDID_ENCODER_HS_4ENCODER_4INPUT
+#define com_phidgets_StepperPhidget_PHIDID_ENCODER_HS_4ENCODER_4INPUT 79L
+#undef com_phidgets_StepperPhidget_PHIDID_FREQUENCYCOUNTER_2INPUT
+#define com_phidgets_StepperPhidget_PHIDID_FREQUENCYCOUNTER_2INPUT 53L
+#undef com_phidgets_StepperPhidget_PHIDID_GPS
+#define com_phidgets_StepperPhidget_PHIDID_GPS 121L
+#undef com_phidgets_StepperPhidget_PHIDID_INTERFACEKIT_0_0_4
+#define com_phidgets_StepperPhidget_PHIDID_INTERFACEKIT_0_0_4 64L
+#undef com_phidgets_StepperPhidget_PHIDID_INTERFACEKIT_0_0_8
+#define com_phidgets_StepperPhidget_PHIDID_INTERFACEKIT_0_0_8 129L
+#undef com_phidgets_StepperPhidget_PHIDID_INTERFACEKIT_0_16_16
+#define com_phidgets_StepperPhidget_PHIDID_INTERFACEKIT_0_16_16 68L
+#undef com_phidgets_StepperPhidget_PHIDID_INTERFACEKIT_8_8_8
+#define com_phidgets_StepperPhidget_PHIDID_INTERFACEKIT_8_8_8 69L
+#undef com_phidgets_StepperPhidget_PHIDID_INTERFACEKIT_8_8_8_w_LCD
+#define com_phidgets_StepperPhidget_PHIDID_INTERFACEKIT_8_8_8_w_LCD 125L
+#undef com_phidgets_StepperPhidget_PHIDID_IR
+#define com_phidgets_StepperPhidget_PHIDID_IR 77L
+#undef com_phidgets_StepperPhidget_PHIDID_LED_64
+#define com_phidgets_StepperPhidget_PHIDID_LED_64 74L
+#undef com_phidgets_StepperPhidget_PHIDID_LED_64_ADV
+#define com_phidgets_StepperPhidget_PHIDID_LED_64_ADV 76L
+#undef com_phidgets_StepperPhidget_PHIDID_LINEAR_TOUCH
+#define com_phidgets_StepperPhidget_PHIDID_LINEAR_TOUCH 118L
+#undef com_phidgets_StepperPhidget_PHIDID_MOTORCONTROL_HC_2MOTOR
+#define com_phidgets_StepperPhidget_PHIDID_MOTORCONTROL_HC_2MOTOR 89L
+#undef com_phidgets_StepperPhidget_PHIDID_MOTORCONTROL_LV_2MOTOR_4INPUT
+#define com_phidgets_StepperPhidget_PHIDID_MOTORCONTROL_LV_2MOTOR_4INPUT 88L
+#undef com_phidgets_StepperPhidget_PHIDID_MOTORCONTROL_1MOTOR
+#define com_phidgets_StepperPhidget_PHIDID_MOTORCONTROL_1MOTOR 62L
+#undef com_phidgets_StepperPhidget_PHIDID_PHSENSOR
+#define com_phidgets_StepperPhidget_PHIDID_PHSENSOR 116L
+#undef com_phidgets_StepperPhidget_PHIDID_RFID_2OUTPUT
+#define com_phidgets_StepperPhidget_PHIDID_RFID_2OUTPUT 49L
+#undef com_phidgets_StepperPhidget_PHIDID_ROTARY_TOUCH
+#define com_phidgets_StepperPhidget_PHIDID_ROTARY_TOUCH 119L
+#undef com_phidgets_StepperPhidget_PHIDID_SERVO_1MOTOR
+#define com_phidgets_StepperPhidget_PHIDID_SERVO_1MOTOR 57L
+#undef com_phidgets_StepperPhidget_PHIDID_SPATIAL_ACCEL_3AXIS
+#define com_phidgets_StepperPhidget_PHIDID_SPATIAL_ACCEL_3AXIS 127L
+#undef com_phidgets_StepperPhidget_PHIDID_SPATIAL_ACCEL_GYRO_COMPASS
+#define com_phidgets_StepperPhidget_PHIDID_SPATIAL_ACCEL_GYRO_COMPASS 51L
+#undef com_phidgets_StepperPhidget_PHIDID_TEMPERATURESENSOR
+#define com_phidgets_StepperPhidget_PHIDID_TEMPERATURESENSOR 112L
+#undef com_phidgets_StepperPhidget_PHIDID_TEMPERATURESENSOR_4
+#define com_phidgets_StepperPhidget_PHIDID_TEMPERATURESENSOR_4 50L
+#undef com_phidgets_StepperPhidget_PHIDID_TEXTLCD_2x20_w_8_8_8
+#define com_phidgets_StepperPhidget_PHIDID_TEXTLCD_2x20_w_8_8_8 381L
+#undef com_phidgets_StepperPhidget_PHIDID_TEXTLCD_ADAPTER
+#define com_phidgets_StepperPhidget_PHIDID_TEXTLCD_ADAPTER 61L
+#undef com_phidgets_StepperPhidget_PHIDID_UNIPOLAR_STEPPER_4MOTOR
+#define com_phidgets_StepperPhidget_PHIDID_UNIPOLAR_STEPPER_4MOTOR 122L
+#undef com_phidgets_StepperPhidget_PHIDID_ACCELEROMETER_2AXIS
+#define com_phidgets_StepperPhidget_PHIDID_ACCELEROMETER_2AXIS 113L
+#undef com_phidgets_StepperPhidget_PHIDID_INTERFACEKIT_0_8_8_w_LCD
+#define com_phidgets_StepperPhidget_PHIDID_INTERFACEKIT_0_8_8_w_LCD 83L
+#undef com_phidgets_StepperPhidget_PHIDID_INTERFACEKIT_4_8_8
+#define com_phidgets_StepperPhidget_PHIDID_INTERFACEKIT_4_8_8 4L
+#undef com_phidgets_StepperPhidget_PHIDID_RFID
+#define com_phidgets_StepperPhidget_PHIDID_RFID 48L
+#undef com_phidgets_StepperPhidget_PHIDID_SERVO_1MOTOR_OLD
+#define com_phidgets_StepperPhidget_PHIDID_SERVO_1MOTOR_OLD 2L
+#undef com_phidgets_StepperPhidget_PHIDID_SERVO_4MOTOR
+#define com_phidgets_StepperPhidget_PHIDID_SERVO_4MOTOR 56L
+#undef com_phidgets_StepperPhidget_PHIDID_SERVO_4MOTOR_OLD
+#define com_phidgets_StepperPhidget_PHIDID_SERVO_4MOTOR_OLD 3L
+#undef com_phidgets_StepperPhidget_PHIDID_TEXTLCD_2x20
+#define com_phidgets_StepperPhidget_PHIDID_TEXTLCD_2x20 82L
+#undef com_phidgets_StepperPhidget_PHIDID_TEXTLCD_2x20_w_0_8_8
+#define com_phidgets_StepperPhidget_PHIDID_TEXTLCD_2x20_w_0_8_8 339L
+#undef com_phidgets_StepperPhidget_PHIDID_TEXTLED_1x8
+#define com_phidgets_StepperPhidget_PHIDID_TEXTLED_1x8 73L
+#undef com_phidgets_StepperPhidget_PHIDID_TEXTLED_4x8
+#define com_phidgets_StepperPhidget_PHIDID_TEXTLED_4x8 72L
+#undef com_phidgets_StepperPhidget_PHIDID_WEIGHTSENSOR
+#define com_phidgets_StepperPhidget_PHIDID_WEIGHTSENSOR 114L
+#undef com_phidgets_StepperPhidget_PHIDCLASS_NOTHING
+#define com_phidgets_StepperPhidget_PHIDCLASS_NOTHING 1L
+#undef com_phidgets_StepperPhidget_PHIDCLASS_ACCELEROMETER
+#define com_phidgets_StepperPhidget_PHIDCLASS_ACCELEROMETER 2L
+#undef com_phidgets_StepperPhidget_PHIDCLASS_ADVANCEDSERVO
+#define com_phidgets_StepperPhidget_PHIDCLASS_ADVANCEDSERVO 3L
+#undef com_phidgets_StepperPhidget_PHIDCLASS_ANALOG
+#define com_phidgets_StepperPhidget_PHIDCLASS_ANALOG 22L
+#undef com_phidgets_StepperPhidget_PHIDCLASS_BRIDGE
+#define com_phidgets_StepperPhidget_PHIDCLASS_BRIDGE 23L
+#undef com_phidgets_StepperPhidget_PHIDCLASS_ENCODER
+#define com_phidgets_StepperPhidget_PHIDCLASS_ENCODER 4L
+#undef com_phidgets_StepperPhidget_PHIDCLASS_FREQUENCYCOUNTER
+#define com_phidgets_StepperPhidget_PHIDCLASS_FREQUENCYCOUNTER 21L
+#undef com_phidgets_StepperPhidget_PHIDCLASS_GPS
+#define com_phidgets_StepperPhidget_PHIDCLASS_GPS 5L
+#undef com_phidgets_StepperPhidget_PHIDCLASS_INTERFACEKIT
+#define com_phidgets_StepperPhidget_PHIDCLASS_INTERFACEKIT 7L
+#undef com_phidgets_StepperPhidget_PHIDCLASS_LED
+#define com_phidgets_StepperPhidget_PHIDCLASS_LED 8L
+#undef com_phidgets_StepperPhidget_PHIDCLASS_MOTORCONTROL
+#define com_phidgets_StepperPhidget_PHIDCLASS_MOTORCONTROL 9L
+#undef com_phidgets_StepperPhidget_PHIDCLASS_PHSENSOR
+#define com_phidgets_StepperPhidget_PHIDCLASS_PHSENSOR 10L
+#undef com_phidgets_StepperPhidget_PHIDCLASS_RFID
+#define com_phidgets_StepperPhidget_PHIDCLASS_RFID 11L
+#undef com_phidgets_StepperPhidget_PHIDCLASS_SERVO
+#define com_phidgets_StepperPhidget_PHIDCLASS_SERVO 12L
+#undef com_phidgets_StepperPhidget_PHIDCLASS_STEPPER
+#define com_phidgets_StepperPhidget_PHIDCLASS_STEPPER 13L
+#undef com_phidgets_StepperPhidget_PHIDCLASS_TEMPERATURESENSOR
+#define com_phidgets_StepperPhidget_PHIDCLASS_TEMPERATURESENSOR 14L
+#undef com_phidgets_StepperPhidget_PHIDCLASS_TEXTLCD
+#define com_phidgets_StepperPhidget_PHIDCLASS_TEXTLCD 15L
+#undef com_phidgets_StepperPhidget_PHIDCLASS_TEXTLED
+#define com_phidgets_StepperPhidget_PHIDCLASS_TEXTLED 16L
+#undef com_phidgets_StepperPhidget_PHIDCLASS_WEIGHTSENSOR
+#define com_phidgets_StepperPhidget_PHIDCLASS_WEIGHTSENSOR 17L
+/*
+ * Class: com_phidgets_StepperPhidget
+ * Method: create
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL Java_com_phidgets_StepperPhidget_create
+ (JNIEnv *, jclass);
+
+/*
+ * Class: com_phidgets_StepperPhidget
+ * Method: getMotorCount
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_phidgets_StepperPhidget_getMotorCount
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_StepperPhidget
+ * Method: getInputCount
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_phidgets_StepperPhidget_getInputCount
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_StepperPhidget
+ * Method: getInputState
+ * Signature: (I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_phidgets_StepperPhidget_getInputState
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_StepperPhidget
+ * Method: getAcceleration
+ * Signature: (I)D
+ */
+JNIEXPORT jdouble JNICALL Java_com_phidgets_StepperPhidget_getAcceleration
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_StepperPhidget
+ * Method: getAccelerationMax
+ * Signature: (I)D
+ */
+JNIEXPORT jdouble JNICALL Java_com_phidgets_StepperPhidget_getAccelerationMax
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_StepperPhidget
+ * Method: getAccelerationMin
+ * Signature: (I)D
+ */
+JNIEXPORT jdouble JNICALL Java_com_phidgets_StepperPhidget_getAccelerationMin
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_StepperPhidget
+ * Method: setAcceleration
+ * Signature: (ID)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_StepperPhidget_setAcceleration
+ (JNIEnv *, jobject, jint, jdouble);
+
+/*
+ * Class: com_phidgets_StepperPhidget
+ * Method: getVelocity
+ * Signature: (I)D
+ */
+JNIEXPORT jdouble JNICALL Java_com_phidgets_StepperPhidget_getVelocity
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_StepperPhidget
+ * Method: getVelocityMax
+ * Signature: (I)D
+ */
+JNIEXPORT jdouble JNICALL Java_com_phidgets_StepperPhidget_getVelocityMax
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_StepperPhidget
+ * Method: getVelocityMin
+ * Signature: (I)D
+ */
+JNIEXPORT jdouble JNICALL Java_com_phidgets_StepperPhidget_getVelocityMin
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_StepperPhidget
+ * Method: setVelocityLimit
+ * Signature: (ID)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_StepperPhidget_setVelocityLimit
+ (JNIEnv *, jobject, jint, jdouble);
+
+/*
+ * Class: com_phidgets_StepperPhidget
+ * Method: getVelocityLimit
+ * Signature: (I)D
+ */
+JNIEXPORT jdouble JNICALL Java_com_phidgets_StepperPhidget_getVelocityLimit
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_StepperPhidget
+ * Method: getPositionMax
+ * Signature: (I)J
+ */
+JNIEXPORT jlong JNICALL Java_com_phidgets_StepperPhidget_getPositionMax
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_StepperPhidget
+ * Method: getPositionMin
+ * Signature: (I)J
+ */
+JNIEXPORT jlong JNICALL Java_com_phidgets_StepperPhidget_getPositionMin
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_StepperPhidget
+ * Method: setCurrentPosition
+ * Signature: (IJ)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_StepperPhidget_setCurrentPosition
+ (JNIEnv *, jobject, jint, jlong);
+
+/*
+ * Class: com_phidgets_StepperPhidget
+ * Method: getCurrentPosition
+ * Signature: (I)J
+ */
+JNIEXPORT jlong JNICALL Java_com_phidgets_StepperPhidget_getCurrentPosition
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_StepperPhidget
+ * Method: setTargetPosition
+ * Signature: (IJ)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_StepperPhidget_setTargetPosition
+ (JNIEnv *, jobject, jint, jlong);
+
+/*
+ * Class: com_phidgets_StepperPhidget
+ * Method: getTargetPosition
+ * Signature: (I)J
+ */
+JNIEXPORT jlong JNICALL Java_com_phidgets_StepperPhidget_getTargetPosition
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_StepperPhidget
+ * Method: getCurrent
+ * Signature: (I)D
+ */
+JNIEXPORT jdouble JNICALL Java_com_phidgets_StepperPhidget_getCurrent
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_StepperPhidget
+ * Method: getCurrentLimit
+ * Signature: (I)D
+ */
+JNIEXPORT jdouble JNICALL Java_com_phidgets_StepperPhidget_getCurrentLimit
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_StepperPhidget
+ * Method: setCurrentLimit
+ * Signature: (ID)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_StepperPhidget_setCurrentLimit
+ (JNIEnv *, jobject, jint, jdouble);
+
+/*
+ * Class: com_phidgets_StepperPhidget
+ * Method: getCurrentMax
+ * Signature: (I)D
+ */
+JNIEXPORT jdouble JNICALL Java_com_phidgets_StepperPhidget_getCurrentMax
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_StepperPhidget
+ * Method: getCurrentMin
+ * Signature: (I)D
+ */
+JNIEXPORT jdouble JNICALL Java_com_phidgets_StepperPhidget_getCurrentMin
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_StepperPhidget
+ * Method: setEngaged
+ * Signature: (IZ)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_StepperPhidget_setEngaged
+ (JNIEnv *, jobject, jint, jboolean);
+
+/*
+ * Class: com_phidgets_StepperPhidget
+ * Method: getEngaged
+ * Signature: (I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_phidgets_StepperPhidget_getEngaged
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_StepperPhidget
+ * Method: getStopped
+ * Signature: (I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_phidgets_StepperPhidget_getStopped
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_StepperPhidget
+ * Method: enableStepperPositionChangeEvents
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_StepperPhidget_enableStepperPositionChangeEvents
+ (JNIEnv *, jobject, jboolean);
+
+/*
+ * Class: com_phidgets_StepperPhidget
+ * Method: enableStepperVelocityChangeEvents
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_StepperPhidget_enableStepperVelocityChangeEvents
+ (JNIEnv *, jobject, jboolean);
+
+/*
+ * Class: com_phidgets_StepperPhidget
+ * Method: enableCurrentChangeEvents
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_StepperPhidget_enableCurrentChangeEvents
+ (JNIEnv *, jobject, jboolean);
+
+/*
+ * Class: com_phidgets_StepperPhidget
+ * Method: enableInputChangeEvents
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_StepperPhidget_enableInputChangeEvents
+ (JNIEnv *, jobject, jboolean);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/Java/com_phidgets_TemperatureSensorPhidget.c b/Java/com_phidgets_TemperatureSensorPhidget.c
new file mode 100644
index 0000000..233826b
--- /dev/null
+++ b/Java/com_phidgets_TemperatureSensorPhidget.c
@@ -0,0 +1,42 @@
+#include "../stdafx.h"
+#include "phidget_jni.h"
+#include "com_phidgets_TemperatureSensorPhidget.h"
+#include "../cphidgettemperaturesensor.h"
+
+EVENT_VARS(temperatureChange, TemperatureChange)
+
+JNI_LOAD(temp, TemperatureSensor)
+ EVENT_VAR_SETUP(temp, temperatureChange, TemperatureChange, ID, V)
+}
+
+EVENT_HANDLER_INDEXED(TemperatureSensor, temperatureChange, TemperatureChange,
+ CPhidgetTemperatureSensor_set_OnTemperatureChange_Handler, double)
+
+JNI_CREATE(TemperatureSensor)
+JNI_INDEXED_GETFUNC(TemperatureSensor, TemperatureChangeTrigger, TemperatureChangeTrigger, jdouble)
+JNI_INDEXED_SETFUNC(TemperatureSensor, TemperatureChangeTrigger, TemperatureChangeTrigger, jdouble)
+JNIEXPORT jint JNICALL
+Java_com_phidgets_TemperatureSensorPhidget_getThermocoupleType(JNIEnv *env, jobject obj, jint index)
+{
+ CPhidgetTemperatureSensorHandle h = (CPhidgetTemperatureSensorHandle)(uintptr_t)
+ (*env)->GetLongField(env, obj, handle_fid);
+ int error;
+ CPhidgetTemperatureSensor_ThermocoupleType v;
+ if ((error = CPhidgetTemperatureSensor_getThermocoupleType(h, index, &v)))
+ PH_THROW(error);
+ return (jint)v;
+}
+JNI_INDEXED_SETFUNC(TemperatureSensor, ThermocoupleType, ThermocoupleType, jint)
+JNI_INDEXED_GETFUNC(TemperatureSensor, Temperature, Temperature, jdouble)
+JNI_INDEXED_GETFUNC(TemperatureSensor, TemperatureMin, TemperatureMin, jdouble)
+JNI_INDEXED_GETFUNC(TemperatureSensor, TemperatureMax, TemperatureMax, jdouble)
+JNI_INDEXED_GETFUNC(TemperatureSensor, Potential, Potential, jdouble)
+JNI_INDEXED_GETFUNC(TemperatureSensor, PotentialMin, PotentialMin, jdouble)
+JNI_INDEXED_GETFUNC(TemperatureSensor, PotentialMax, PotentialMax, jdouble)
+JNI_GETFUNC(TemperatureSensor, AmbientTemperature, AmbientTemperature, jdouble)
+JNI_GETFUNC(TemperatureSensor, AmbientTemperatureMin, AmbientTemperatureMin, jdouble)
+JNI_GETFUNC(TemperatureSensor, AmbientTemperatureMax, AmbientTemperatureMax, jdouble)
+JNI_GETFUNC(TemperatureSensor, TemperatureInputCount, TemperatureInputCount, jint)
+
+//Deprecated
+JNI_GETFUNC(TemperatureSensor, SensorCount, TemperatureInputCount, jint)
diff --git a/Java/com_phidgets_TemperatureSensorPhidget.h b/Java/com_phidgets_TemperatureSensorPhidget.h
new file mode 100644
index 0000000..dba8b34
--- /dev/null
+++ b/Java/com_phidgets_TemperatureSensorPhidget.h
@@ -0,0 +1,301 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class com_phidgets_TemperatureSensorPhidget */
+
+#ifndef _Included_com_phidgets_TemperatureSensorPhidget
+#define _Included_com_phidgets_TemperatureSensorPhidget
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef com_phidgets_TemperatureSensorPhidget_PHIDGET_LOG_CRITICAL
+#define com_phidgets_TemperatureSensorPhidget_PHIDGET_LOG_CRITICAL 1L
+#undef com_phidgets_TemperatureSensorPhidget_PHIDGET_LOG_ERROR
+#define com_phidgets_TemperatureSensorPhidget_PHIDGET_LOG_ERROR 2L
+#undef com_phidgets_TemperatureSensorPhidget_PHIDGET_LOG_WARNING
+#define com_phidgets_TemperatureSensorPhidget_PHIDGET_LOG_WARNING 3L
+#undef com_phidgets_TemperatureSensorPhidget_PHIDGET_LOG_DEBUG
+#define com_phidgets_TemperatureSensorPhidget_PHIDGET_LOG_DEBUG 4L
+#undef com_phidgets_TemperatureSensorPhidget_PHIDGET_LOG_INFO
+#define com_phidgets_TemperatureSensorPhidget_PHIDGET_LOG_INFO 5L
+#undef com_phidgets_TemperatureSensorPhidget_PHIDGET_LOG_VERBOSE
+#define com_phidgets_TemperatureSensorPhidget_PHIDGET_LOG_VERBOSE 6L
+#undef com_phidgets_TemperatureSensorPhidget_PHIDID_NOTHING
+#define com_phidgets_TemperatureSensorPhidget_PHIDID_NOTHING 1L
+#undef com_phidgets_TemperatureSensorPhidget_PHIDID_ACCELEROMETER_3AXIS
+#define com_phidgets_TemperatureSensorPhidget_PHIDID_ACCELEROMETER_3AXIS 126L
+#undef com_phidgets_TemperatureSensorPhidget_PHIDID_ADVANCEDSERVO_1MOTOR
+#define com_phidgets_TemperatureSensorPhidget_PHIDID_ADVANCEDSERVO_1MOTOR 130L
+#undef com_phidgets_TemperatureSensorPhidget_PHIDID_ANALOG_4OUTPUT
+#define com_phidgets_TemperatureSensorPhidget_PHIDID_ANALOG_4OUTPUT 55L
+#undef com_phidgets_TemperatureSensorPhidget_PHIDID_ADVANCEDSERVO_8MOTOR
+#define com_phidgets_TemperatureSensorPhidget_PHIDID_ADVANCEDSERVO_8MOTOR 58L
+#undef com_phidgets_TemperatureSensorPhidget_PHIDID_BIPOLAR_STEPPER_1MOTOR
+#define com_phidgets_TemperatureSensorPhidget_PHIDID_BIPOLAR_STEPPER_1MOTOR 123L
+#undef com_phidgets_TemperatureSensorPhidget_PHIDID_BRIDGE_4INPUT
+#define com_phidgets_TemperatureSensorPhidget_PHIDID_BRIDGE_4INPUT 59L
+#undef com_phidgets_TemperatureSensorPhidget_PHIDID_ENCODER_1ENCODER_1INPUT
+#define com_phidgets_TemperatureSensorPhidget_PHIDID_ENCODER_1ENCODER_1INPUT 75L
+#undef com_phidgets_TemperatureSensorPhidget_PHIDID_ENCODER_HS_1ENCODER
+#define com_phidgets_TemperatureSensorPhidget_PHIDID_ENCODER_HS_1ENCODER 128L
+#undef com_phidgets_TemperatureSensorPhidget_PHIDID_ENCODER_HS_4ENCODER_4INPUT
+#define com_phidgets_TemperatureSensorPhidget_PHIDID_ENCODER_HS_4ENCODER_4INPUT 79L
+#undef com_phidgets_TemperatureSensorPhidget_PHIDID_FREQUENCYCOUNTER_2INPUT
+#define com_phidgets_TemperatureSensorPhidget_PHIDID_FREQUENCYCOUNTER_2INPUT 53L
+#undef com_phidgets_TemperatureSensorPhidget_PHIDID_GPS
+#define com_phidgets_TemperatureSensorPhidget_PHIDID_GPS 121L
+#undef com_phidgets_TemperatureSensorPhidget_PHIDID_INTERFACEKIT_0_0_4
+#define com_phidgets_TemperatureSensorPhidget_PHIDID_INTERFACEKIT_0_0_4 64L
+#undef com_phidgets_TemperatureSensorPhidget_PHIDID_INTERFACEKIT_0_0_8
+#define com_phidgets_TemperatureSensorPhidget_PHIDID_INTERFACEKIT_0_0_8 129L
+#undef com_phidgets_TemperatureSensorPhidget_PHIDID_INTERFACEKIT_0_16_16
+#define com_phidgets_TemperatureSensorPhidget_PHIDID_INTERFACEKIT_0_16_16 68L
+#undef com_phidgets_TemperatureSensorPhidget_PHIDID_INTERFACEKIT_8_8_8
+#define com_phidgets_TemperatureSensorPhidget_PHIDID_INTERFACEKIT_8_8_8 69L
+#undef com_phidgets_TemperatureSensorPhidget_PHIDID_INTERFACEKIT_8_8_8_w_LCD
+#define com_phidgets_TemperatureSensorPhidget_PHIDID_INTERFACEKIT_8_8_8_w_LCD 125L
+#undef com_phidgets_TemperatureSensorPhidget_PHIDID_IR
+#define com_phidgets_TemperatureSensorPhidget_PHIDID_IR 77L
+#undef com_phidgets_TemperatureSensorPhidget_PHIDID_LED_64
+#define com_phidgets_TemperatureSensorPhidget_PHIDID_LED_64 74L
+#undef com_phidgets_TemperatureSensorPhidget_PHIDID_LED_64_ADV
+#define com_phidgets_TemperatureSensorPhidget_PHIDID_LED_64_ADV 76L
+#undef com_phidgets_TemperatureSensorPhidget_PHIDID_LINEAR_TOUCH
+#define com_phidgets_TemperatureSensorPhidget_PHIDID_LINEAR_TOUCH 118L
+#undef com_phidgets_TemperatureSensorPhidget_PHIDID_MOTORCONTROL_HC_2MOTOR
+#define com_phidgets_TemperatureSensorPhidget_PHIDID_MOTORCONTROL_HC_2MOTOR 89L
+#undef com_phidgets_TemperatureSensorPhidget_PHIDID_MOTORCONTROL_LV_2MOTOR_4INPUT
+#define com_phidgets_TemperatureSensorPhidget_PHIDID_MOTORCONTROL_LV_2MOTOR_4INPUT 88L
+#undef com_phidgets_TemperatureSensorPhidget_PHIDID_MOTORCONTROL_1MOTOR
+#define com_phidgets_TemperatureSensorPhidget_PHIDID_MOTORCONTROL_1MOTOR 62L
+#undef com_phidgets_TemperatureSensorPhidget_PHIDID_PHSENSOR
+#define com_phidgets_TemperatureSensorPhidget_PHIDID_PHSENSOR 116L
+#undef com_phidgets_TemperatureSensorPhidget_PHIDID_RFID_2OUTPUT
+#define com_phidgets_TemperatureSensorPhidget_PHIDID_RFID_2OUTPUT 49L
+#undef com_phidgets_TemperatureSensorPhidget_PHIDID_ROTARY_TOUCH
+#define com_phidgets_TemperatureSensorPhidget_PHIDID_ROTARY_TOUCH 119L
+#undef com_phidgets_TemperatureSensorPhidget_PHIDID_SERVO_1MOTOR
+#define com_phidgets_TemperatureSensorPhidget_PHIDID_SERVO_1MOTOR 57L
+#undef com_phidgets_TemperatureSensorPhidget_PHIDID_SPATIAL_ACCEL_3AXIS
+#define com_phidgets_TemperatureSensorPhidget_PHIDID_SPATIAL_ACCEL_3AXIS 127L
+#undef com_phidgets_TemperatureSensorPhidget_PHIDID_SPATIAL_ACCEL_GYRO_COMPASS
+#define com_phidgets_TemperatureSensorPhidget_PHIDID_SPATIAL_ACCEL_GYRO_COMPASS 51L
+#undef com_phidgets_TemperatureSensorPhidget_PHIDID_TEMPERATURESENSOR
+#define com_phidgets_TemperatureSensorPhidget_PHIDID_TEMPERATURESENSOR 112L
+#undef com_phidgets_TemperatureSensorPhidget_PHIDID_TEMPERATURESENSOR_4
+#define com_phidgets_TemperatureSensorPhidget_PHIDID_TEMPERATURESENSOR_4 50L
+#undef com_phidgets_TemperatureSensorPhidget_PHIDID_TEXTLCD_2x20_w_8_8_8
+#define com_phidgets_TemperatureSensorPhidget_PHIDID_TEXTLCD_2x20_w_8_8_8 381L
+#undef com_phidgets_TemperatureSensorPhidget_PHIDID_TEXTLCD_ADAPTER
+#define com_phidgets_TemperatureSensorPhidget_PHIDID_TEXTLCD_ADAPTER 61L
+#undef com_phidgets_TemperatureSensorPhidget_PHIDID_UNIPOLAR_STEPPER_4MOTOR
+#define com_phidgets_TemperatureSensorPhidget_PHIDID_UNIPOLAR_STEPPER_4MOTOR 122L
+#undef com_phidgets_TemperatureSensorPhidget_PHIDID_ACCELEROMETER_2AXIS
+#define com_phidgets_TemperatureSensorPhidget_PHIDID_ACCELEROMETER_2AXIS 113L
+#undef com_phidgets_TemperatureSensorPhidget_PHIDID_INTERFACEKIT_0_8_8_w_LCD
+#define com_phidgets_TemperatureSensorPhidget_PHIDID_INTERFACEKIT_0_8_8_w_LCD 83L
+#undef com_phidgets_TemperatureSensorPhidget_PHIDID_INTERFACEKIT_4_8_8
+#define com_phidgets_TemperatureSensorPhidget_PHIDID_INTERFACEKIT_4_8_8 4L
+#undef com_phidgets_TemperatureSensorPhidget_PHIDID_RFID
+#define com_phidgets_TemperatureSensorPhidget_PHIDID_RFID 48L
+#undef com_phidgets_TemperatureSensorPhidget_PHIDID_SERVO_1MOTOR_OLD
+#define com_phidgets_TemperatureSensorPhidget_PHIDID_SERVO_1MOTOR_OLD 2L
+#undef com_phidgets_TemperatureSensorPhidget_PHIDID_SERVO_4MOTOR
+#define com_phidgets_TemperatureSensorPhidget_PHIDID_SERVO_4MOTOR 56L
+#undef com_phidgets_TemperatureSensorPhidget_PHIDID_SERVO_4MOTOR_OLD
+#define com_phidgets_TemperatureSensorPhidget_PHIDID_SERVO_4MOTOR_OLD 3L
+#undef com_phidgets_TemperatureSensorPhidget_PHIDID_TEXTLCD_2x20
+#define com_phidgets_TemperatureSensorPhidget_PHIDID_TEXTLCD_2x20 82L
+#undef com_phidgets_TemperatureSensorPhidget_PHIDID_TEXTLCD_2x20_w_0_8_8
+#define com_phidgets_TemperatureSensorPhidget_PHIDID_TEXTLCD_2x20_w_0_8_8 339L
+#undef com_phidgets_TemperatureSensorPhidget_PHIDID_TEXTLED_1x8
+#define com_phidgets_TemperatureSensorPhidget_PHIDID_TEXTLED_1x8 73L
+#undef com_phidgets_TemperatureSensorPhidget_PHIDID_TEXTLED_4x8
+#define com_phidgets_TemperatureSensorPhidget_PHIDID_TEXTLED_4x8 72L
+#undef com_phidgets_TemperatureSensorPhidget_PHIDID_WEIGHTSENSOR
+#define com_phidgets_TemperatureSensorPhidget_PHIDID_WEIGHTSENSOR 114L
+#undef com_phidgets_TemperatureSensorPhidget_PHIDCLASS_NOTHING
+#define com_phidgets_TemperatureSensorPhidget_PHIDCLASS_NOTHING 1L
+#undef com_phidgets_TemperatureSensorPhidget_PHIDCLASS_ACCELEROMETER
+#define com_phidgets_TemperatureSensorPhidget_PHIDCLASS_ACCELEROMETER 2L
+#undef com_phidgets_TemperatureSensorPhidget_PHIDCLASS_ADVANCEDSERVO
+#define com_phidgets_TemperatureSensorPhidget_PHIDCLASS_ADVANCEDSERVO 3L
+#undef com_phidgets_TemperatureSensorPhidget_PHIDCLASS_ANALOG
+#define com_phidgets_TemperatureSensorPhidget_PHIDCLASS_ANALOG 22L
+#undef com_phidgets_TemperatureSensorPhidget_PHIDCLASS_BRIDGE
+#define com_phidgets_TemperatureSensorPhidget_PHIDCLASS_BRIDGE 23L
+#undef com_phidgets_TemperatureSensorPhidget_PHIDCLASS_ENCODER
+#define com_phidgets_TemperatureSensorPhidget_PHIDCLASS_ENCODER 4L
+#undef com_phidgets_TemperatureSensorPhidget_PHIDCLASS_FREQUENCYCOUNTER
+#define com_phidgets_TemperatureSensorPhidget_PHIDCLASS_FREQUENCYCOUNTER 21L
+#undef com_phidgets_TemperatureSensorPhidget_PHIDCLASS_GPS
+#define com_phidgets_TemperatureSensorPhidget_PHIDCLASS_GPS 5L
+#undef com_phidgets_TemperatureSensorPhidget_PHIDCLASS_INTERFACEKIT
+#define com_phidgets_TemperatureSensorPhidget_PHIDCLASS_INTERFACEKIT 7L
+#undef com_phidgets_TemperatureSensorPhidget_PHIDCLASS_LED
+#define com_phidgets_TemperatureSensorPhidget_PHIDCLASS_LED 8L
+#undef com_phidgets_TemperatureSensorPhidget_PHIDCLASS_MOTORCONTROL
+#define com_phidgets_TemperatureSensorPhidget_PHIDCLASS_MOTORCONTROL 9L
+#undef com_phidgets_TemperatureSensorPhidget_PHIDCLASS_PHSENSOR
+#define com_phidgets_TemperatureSensorPhidget_PHIDCLASS_PHSENSOR 10L
+#undef com_phidgets_TemperatureSensorPhidget_PHIDCLASS_RFID
+#define com_phidgets_TemperatureSensorPhidget_PHIDCLASS_RFID 11L
+#undef com_phidgets_TemperatureSensorPhidget_PHIDCLASS_SERVO
+#define com_phidgets_TemperatureSensorPhidget_PHIDCLASS_SERVO 12L
+#undef com_phidgets_TemperatureSensorPhidget_PHIDCLASS_STEPPER
+#define com_phidgets_TemperatureSensorPhidget_PHIDCLASS_STEPPER 13L
+#undef com_phidgets_TemperatureSensorPhidget_PHIDCLASS_TEMPERATURESENSOR
+#define com_phidgets_TemperatureSensorPhidget_PHIDCLASS_TEMPERATURESENSOR 14L
+#undef com_phidgets_TemperatureSensorPhidget_PHIDCLASS_TEXTLCD
+#define com_phidgets_TemperatureSensorPhidget_PHIDCLASS_TEXTLCD 15L
+#undef com_phidgets_TemperatureSensorPhidget_PHIDCLASS_TEXTLED
+#define com_phidgets_TemperatureSensorPhidget_PHIDCLASS_TEXTLED 16L
+#undef com_phidgets_TemperatureSensorPhidget_PHIDCLASS_WEIGHTSENSOR
+#define com_phidgets_TemperatureSensorPhidget_PHIDCLASS_WEIGHTSENSOR 17L
+#undef com_phidgets_TemperatureSensorPhidget_PHIDGET_TEMPERATURE_SENSOR_K_TYPE
+#define com_phidgets_TemperatureSensorPhidget_PHIDGET_TEMPERATURE_SENSOR_K_TYPE 1L
+#undef com_phidgets_TemperatureSensorPhidget_PHIDGET_TEMPERATURE_SENSOR_J_TYPE
+#define com_phidgets_TemperatureSensorPhidget_PHIDGET_TEMPERATURE_SENSOR_J_TYPE 2L
+#undef com_phidgets_TemperatureSensorPhidget_PHIDGET_TEMPERATURE_SENSOR_E_TYPE
+#define com_phidgets_TemperatureSensorPhidget_PHIDGET_TEMPERATURE_SENSOR_E_TYPE 3L
+#undef com_phidgets_TemperatureSensorPhidget_PHIDGET_TEMPERATURE_SENSOR_T_TYPE
+#define com_phidgets_TemperatureSensorPhidget_PHIDGET_TEMPERATURE_SENSOR_T_TYPE 4L
+/*
+ * Class: com_phidgets_TemperatureSensorPhidget
+ * Method: create
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL Java_com_phidgets_TemperatureSensorPhidget_create
+ (JNIEnv *, jclass);
+
+/*
+ * Class: com_phidgets_TemperatureSensorPhidget
+ * Method: getTemperatureInputCount
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_phidgets_TemperatureSensorPhidget_getTemperatureInputCount
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_TemperatureSensorPhidget
+ * Method: getSensorCount
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_phidgets_TemperatureSensorPhidget_getSensorCount
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_TemperatureSensorPhidget
+ * Method: getTemperature
+ * Signature: (I)D
+ */
+JNIEXPORT jdouble JNICALL Java_com_phidgets_TemperatureSensorPhidget_getTemperature
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_TemperatureSensorPhidget
+ * Method: getTemperatureMax
+ * Signature: (I)D
+ */
+JNIEXPORT jdouble JNICALL Java_com_phidgets_TemperatureSensorPhidget_getTemperatureMax
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_TemperatureSensorPhidget
+ * Method: getTemperatureMin
+ * Signature: (I)D
+ */
+JNIEXPORT jdouble JNICALL Java_com_phidgets_TemperatureSensorPhidget_getTemperatureMin
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_TemperatureSensorPhidget
+ * Method: getAmbientTemperature
+ * Signature: ()D
+ */
+JNIEXPORT jdouble JNICALL Java_com_phidgets_TemperatureSensorPhidget_getAmbientTemperature
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_TemperatureSensorPhidget
+ * Method: getAmbientTemperatureMax
+ * Signature: ()D
+ */
+JNIEXPORT jdouble JNICALL Java_com_phidgets_TemperatureSensorPhidget_getAmbientTemperatureMax
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_TemperatureSensorPhidget
+ * Method: getAmbientTemperatureMin
+ * Signature: ()D
+ */
+JNIEXPORT jdouble JNICALL Java_com_phidgets_TemperatureSensorPhidget_getAmbientTemperatureMin
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_TemperatureSensorPhidget
+ * Method: getPotential
+ * Signature: (I)D
+ */
+JNIEXPORT jdouble JNICALL Java_com_phidgets_TemperatureSensorPhidget_getPotential
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_TemperatureSensorPhidget
+ * Method: getPotentialMax
+ * Signature: (I)D
+ */
+JNIEXPORT jdouble JNICALL Java_com_phidgets_TemperatureSensorPhidget_getPotentialMax
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_TemperatureSensorPhidget
+ * Method: getPotentialMin
+ * Signature: (I)D
+ */
+JNIEXPORT jdouble JNICALL Java_com_phidgets_TemperatureSensorPhidget_getPotentialMin
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_TemperatureSensorPhidget
+ * Method: setTemperatureChangeTrigger
+ * Signature: (ID)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_TemperatureSensorPhidget_setTemperatureChangeTrigger
+ (JNIEnv *, jobject, jint, jdouble);
+
+/*
+ * Class: com_phidgets_TemperatureSensorPhidget
+ * Method: getTemperatureChangeTrigger
+ * Signature: (I)D
+ */
+JNIEXPORT jdouble JNICALL Java_com_phidgets_TemperatureSensorPhidget_getTemperatureChangeTrigger
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_TemperatureSensorPhidget
+ * Method: getThermocoupleType
+ * Signature: (I)I
+ */
+JNIEXPORT jint JNICALL Java_com_phidgets_TemperatureSensorPhidget_getThermocoupleType
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_TemperatureSensorPhidget
+ * Method: setThermocoupleType
+ * Signature: (II)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_TemperatureSensorPhidget_setThermocoupleType
+ (JNIEnv *, jobject, jint, jint);
+
+/*
+ * Class: com_phidgets_TemperatureSensorPhidget
+ * Method: enableTemperatureChangeEvents
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_TemperatureSensorPhidget_enableTemperatureChangeEvents
+ (JNIEnv *, jobject, jboolean);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/Java/com_phidgets_TextLCDPhidget.c b/Java/com_phidgets_TextLCDPhidget.c
new file mode 100644
index 0000000..a917bfd
--- /dev/null
+++ b/Java/com_phidgets_TextLCDPhidget.c
@@ -0,0 +1,97 @@
+#include "../stdafx.h"
+#include "phidget_jni.h"
+#include "com_phidgets_TextLCDPhidget.h"
+#include "../cphidgettextlcd.h"
+
+JNI_LOAD(lcd, TextLCD)
+}
+
+JNI_CREATE(TextLCD)
+JNI_GETFUNCBOOL(TextLCD, Backlight, Backlight)
+JNI_SETFUNC(TextLCD, Backlight, Backlight, jboolean)
+JNI_GETFUNC(TextLCD, Contrast, Contrast, jint)
+JNI_SETFUNC(TextLCD, Contrast, Contrast, jint)
+JNI_GETFUNC(TextLCD, Brightness, Brightness, jint)
+JNI_SETFUNC(TextLCD, Brightness, Brightness, jint)
+JNI_GETFUNCBOOL(TextLCD, Cursor, CursorOn)
+JNI_SETFUNC(TextLCD, Cursor, CursorOn, jboolean)
+JNI_GETFUNCBOOL(TextLCD, CursorBlink, CursorBlink)
+JNI_SETFUNC(TextLCD, CursorBlink, CursorBlink, jboolean)
+JNI_GETFUNC(TextLCD, RowCount, RowCount, jint)
+JNI_GETFUNC(TextLCD, ColumnCount, ColumnCount, jint)
+JNI_GETFUNC(TextLCD, ScreenCount, ScreenCount, jint)
+
+JNIEXPORT void JNICALL
+Java_com_phidgets_TextLCDPhidget_setDisplayString(JNIEnv *env, jobject obj, jint index, jstring v)
+{
+ CPhidgetTextLCDHandle h = (CPhidgetTextLCDHandle)(uintptr_t)
+ (*env)->GetLongField(env, obj, handle_fid);
+ int error, i;
+ jboolean iscopy;
+ char string[TEXTLCD_MAXCOLS+2];
+
+ //we can't use GetStringUTFChars here because it converts the UTF-16 to UTF-8 and this screws up the 0x80-0xFF characters
+ const jchar *textString = (*env)->GetStringChars(env, v, &iscopy);
+
+ for(i=0;i<TEXTLCD_MAXCOLS+2;i++)
+ {
+ string[i] = (char)textString[i];
+ if(!textString[i])
+ break;
+ }
+ string[TEXTLCD_MAXCOLS+1] = '\0';
+
+ if ((error = CPhidgetTextLCD_setDisplayString(h, index, (char *)string)))
+ PH_THROW(error);
+
+ (*env)->ReleaseStringChars(env, v, textString);
+}
+
+JNIEXPORT void JNICALL
+Java_com_phidgets_TextLCDPhidget_setDisplayCharacter(JNIEnv *env, jobject obj, jint row, jint column, jchar v)
+{
+ CPhidgetTextLCDHandle h = (CPhidgetTextLCDHandle)(uintptr_t)
+ (*env)->GetLongField(env, obj, handle_fid);
+ int error;
+
+ if ((error = CPhidgetTextLCD_setDisplayCharacter(h, row, column, (char)v)))
+ PH_THROW(error);
+}
+
+JNIEXPORT void JNICALL
+Java_com_phidgets_TextLCDPhidget_setCustomCharacter(JNIEnv *env, jobject obj, jint index, jint v, jint v2)
+{
+ CPhidgetTextLCDHandle h = (CPhidgetTextLCDHandle)(uintptr_t)
+ (*env)->GetLongField(env, obj, handle_fid);
+ int error;
+ if ((error = CPhidgetTextLCD_setCustomCharacter(h, index, v, v2)))
+ PH_THROW(error);
+}
+
+JNI_GETFUNC(TextLCD, Screen, Screen, jint)
+JNI_SETFUNC(TextLCD, Screen, Screen, jint)
+
+JNIEXPORT jint JNICALL
+Java_com_phidgets_TextLCDPhidget_getScreenSize(JNIEnv *env, jobject obj)
+{
+ CPhidgetTextLCDHandle h = (CPhidgetTextLCDHandle)(uintptr_t)
+ (*env)->GetLongField(env, obj, handle_fid);
+ int error;
+ CPhidgetTextLCD_ScreenSize v;
+ if ((error = CPhidgetTextLCD_getScreenSize(h, &v)))
+ PH_THROW(error);
+ return (jint)v;
+}
+
+JNI_SETFUNC(TextLCD, ScreenSize, ScreenSize, jint)
+
+JNIEXPORT void JNICALL
+Java_com_phidgets_TextLCDPhidget_initialize(JNIEnv *env, jobject obj)
+{
+ CPhidgetTextLCDHandle h = (CPhidgetTextLCDHandle)(uintptr_t)
+ (*env)->GetLongField(env, obj, handle_fid);
+ int error;
+
+ if ((error = CPhidgetTextLCD_initialize(h)))
+ PH_THROW(error);
+}
diff --git a/Java/com_phidgets_TextLCDPhidget.h b/Java/com_phidgets_TextLCDPhidget.h
new file mode 100644
index 0000000..d96d7b1
--- /dev/null
+++ b/Java/com_phidgets_TextLCDPhidget.h
@@ -0,0 +1,359 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class com_phidgets_TextLCDPhidget */
+
+#ifndef _Included_com_phidgets_TextLCDPhidget
+#define _Included_com_phidgets_TextLCDPhidget
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef com_phidgets_TextLCDPhidget_PHIDGET_LOG_CRITICAL
+#define com_phidgets_TextLCDPhidget_PHIDGET_LOG_CRITICAL 1L
+#undef com_phidgets_TextLCDPhidget_PHIDGET_LOG_ERROR
+#define com_phidgets_TextLCDPhidget_PHIDGET_LOG_ERROR 2L
+#undef com_phidgets_TextLCDPhidget_PHIDGET_LOG_WARNING
+#define com_phidgets_TextLCDPhidget_PHIDGET_LOG_WARNING 3L
+#undef com_phidgets_TextLCDPhidget_PHIDGET_LOG_DEBUG
+#define com_phidgets_TextLCDPhidget_PHIDGET_LOG_DEBUG 4L
+#undef com_phidgets_TextLCDPhidget_PHIDGET_LOG_INFO
+#define com_phidgets_TextLCDPhidget_PHIDGET_LOG_INFO 5L
+#undef com_phidgets_TextLCDPhidget_PHIDGET_LOG_VERBOSE
+#define com_phidgets_TextLCDPhidget_PHIDGET_LOG_VERBOSE 6L
+#undef com_phidgets_TextLCDPhidget_PHIDID_NOTHING
+#define com_phidgets_TextLCDPhidget_PHIDID_NOTHING 1L
+#undef com_phidgets_TextLCDPhidget_PHIDID_ACCELEROMETER_3AXIS
+#define com_phidgets_TextLCDPhidget_PHIDID_ACCELEROMETER_3AXIS 126L
+#undef com_phidgets_TextLCDPhidget_PHIDID_ADVANCEDSERVO_1MOTOR
+#define com_phidgets_TextLCDPhidget_PHIDID_ADVANCEDSERVO_1MOTOR 130L
+#undef com_phidgets_TextLCDPhidget_PHIDID_ANALOG_4OUTPUT
+#define com_phidgets_TextLCDPhidget_PHIDID_ANALOG_4OUTPUT 55L
+#undef com_phidgets_TextLCDPhidget_PHIDID_ADVANCEDSERVO_8MOTOR
+#define com_phidgets_TextLCDPhidget_PHIDID_ADVANCEDSERVO_8MOTOR 58L
+#undef com_phidgets_TextLCDPhidget_PHIDID_BIPOLAR_STEPPER_1MOTOR
+#define com_phidgets_TextLCDPhidget_PHIDID_BIPOLAR_STEPPER_1MOTOR 123L
+#undef com_phidgets_TextLCDPhidget_PHIDID_BRIDGE_4INPUT
+#define com_phidgets_TextLCDPhidget_PHIDID_BRIDGE_4INPUT 59L
+#undef com_phidgets_TextLCDPhidget_PHIDID_ENCODER_1ENCODER_1INPUT
+#define com_phidgets_TextLCDPhidget_PHIDID_ENCODER_1ENCODER_1INPUT 75L
+#undef com_phidgets_TextLCDPhidget_PHIDID_ENCODER_HS_1ENCODER
+#define com_phidgets_TextLCDPhidget_PHIDID_ENCODER_HS_1ENCODER 128L
+#undef com_phidgets_TextLCDPhidget_PHIDID_ENCODER_HS_4ENCODER_4INPUT
+#define com_phidgets_TextLCDPhidget_PHIDID_ENCODER_HS_4ENCODER_4INPUT 79L
+#undef com_phidgets_TextLCDPhidget_PHIDID_FREQUENCYCOUNTER_2INPUT
+#define com_phidgets_TextLCDPhidget_PHIDID_FREQUENCYCOUNTER_2INPUT 53L
+#undef com_phidgets_TextLCDPhidget_PHIDID_GPS
+#define com_phidgets_TextLCDPhidget_PHIDID_GPS 121L
+#undef com_phidgets_TextLCDPhidget_PHIDID_INTERFACEKIT_0_0_4
+#define com_phidgets_TextLCDPhidget_PHIDID_INTERFACEKIT_0_0_4 64L
+#undef com_phidgets_TextLCDPhidget_PHIDID_INTERFACEKIT_0_0_8
+#define com_phidgets_TextLCDPhidget_PHIDID_INTERFACEKIT_0_0_8 129L
+#undef com_phidgets_TextLCDPhidget_PHIDID_INTERFACEKIT_0_16_16
+#define com_phidgets_TextLCDPhidget_PHIDID_INTERFACEKIT_0_16_16 68L
+#undef com_phidgets_TextLCDPhidget_PHIDID_INTERFACEKIT_8_8_8
+#define com_phidgets_TextLCDPhidget_PHIDID_INTERFACEKIT_8_8_8 69L
+#undef com_phidgets_TextLCDPhidget_PHIDID_INTERFACEKIT_8_8_8_w_LCD
+#define com_phidgets_TextLCDPhidget_PHIDID_INTERFACEKIT_8_8_8_w_LCD 125L
+#undef com_phidgets_TextLCDPhidget_PHIDID_IR
+#define com_phidgets_TextLCDPhidget_PHIDID_IR 77L
+#undef com_phidgets_TextLCDPhidget_PHIDID_LED_64
+#define com_phidgets_TextLCDPhidget_PHIDID_LED_64 74L
+#undef com_phidgets_TextLCDPhidget_PHIDID_LED_64_ADV
+#define com_phidgets_TextLCDPhidget_PHIDID_LED_64_ADV 76L
+#undef com_phidgets_TextLCDPhidget_PHIDID_LINEAR_TOUCH
+#define com_phidgets_TextLCDPhidget_PHIDID_LINEAR_TOUCH 118L
+#undef com_phidgets_TextLCDPhidget_PHIDID_MOTORCONTROL_HC_2MOTOR
+#define com_phidgets_TextLCDPhidget_PHIDID_MOTORCONTROL_HC_2MOTOR 89L
+#undef com_phidgets_TextLCDPhidget_PHIDID_MOTORCONTROL_LV_2MOTOR_4INPUT
+#define com_phidgets_TextLCDPhidget_PHIDID_MOTORCONTROL_LV_2MOTOR_4INPUT 88L
+#undef com_phidgets_TextLCDPhidget_PHIDID_MOTORCONTROL_1MOTOR
+#define com_phidgets_TextLCDPhidget_PHIDID_MOTORCONTROL_1MOTOR 62L
+#undef com_phidgets_TextLCDPhidget_PHIDID_PHSENSOR
+#define com_phidgets_TextLCDPhidget_PHIDID_PHSENSOR 116L
+#undef com_phidgets_TextLCDPhidget_PHIDID_RFID_2OUTPUT
+#define com_phidgets_TextLCDPhidget_PHIDID_RFID_2OUTPUT 49L
+#undef com_phidgets_TextLCDPhidget_PHIDID_ROTARY_TOUCH
+#define com_phidgets_TextLCDPhidget_PHIDID_ROTARY_TOUCH 119L
+#undef com_phidgets_TextLCDPhidget_PHIDID_SERVO_1MOTOR
+#define com_phidgets_TextLCDPhidget_PHIDID_SERVO_1MOTOR 57L
+#undef com_phidgets_TextLCDPhidget_PHIDID_SPATIAL_ACCEL_3AXIS
+#define com_phidgets_TextLCDPhidget_PHIDID_SPATIAL_ACCEL_3AXIS 127L
+#undef com_phidgets_TextLCDPhidget_PHIDID_SPATIAL_ACCEL_GYRO_COMPASS
+#define com_phidgets_TextLCDPhidget_PHIDID_SPATIAL_ACCEL_GYRO_COMPASS 51L
+#undef com_phidgets_TextLCDPhidget_PHIDID_TEMPERATURESENSOR
+#define com_phidgets_TextLCDPhidget_PHIDID_TEMPERATURESENSOR 112L
+#undef com_phidgets_TextLCDPhidget_PHIDID_TEMPERATURESENSOR_4
+#define com_phidgets_TextLCDPhidget_PHIDID_TEMPERATURESENSOR_4 50L
+#undef com_phidgets_TextLCDPhidget_PHIDID_TEXTLCD_2x20_w_8_8_8
+#define com_phidgets_TextLCDPhidget_PHIDID_TEXTLCD_2x20_w_8_8_8 381L
+#undef com_phidgets_TextLCDPhidget_PHIDID_TEXTLCD_ADAPTER
+#define com_phidgets_TextLCDPhidget_PHIDID_TEXTLCD_ADAPTER 61L
+#undef com_phidgets_TextLCDPhidget_PHIDID_UNIPOLAR_STEPPER_4MOTOR
+#define com_phidgets_TextLCDPhidget_PHIDID_UNIPOLAR_STEPPER_4MOTOR 122L
+#undef com_phidgets_TextLCDPhidget_PHIDID_ACCELEROMETER_2AXIS
+#define com_phidgets_TextLCDPhidget_PHIDID_ACCELEROMETER_2AXIS 113L
+#undef com_phidgets_TextLCDPhidget_PHIDID_INTERFACEKIT_0_8_8_w_LCD
+#define com_phidgets_TextLCDPhidget_PHIDID_INTERFACEKIT_0_8_8_w_LCD 83L
+#undef com_phidgets_TextLCDPhidget_PHIDID_INTERFACEKIT_4_8_8
+#define com_phidgets_TextLCDPhidget_PHIDID_INTERFACEKIT_4_8_8 4L
+#undef com_phidgets_TextLCDPhidget_PHIDID_RFID
+#define com_phidgets_TextLCDPhidget_PHIDID_RFID 48L
+#undef com_phidgets_TextLCDPhidget_PHIDID_SERVO_1MOTOR_OLD
+#define com_phidgets_TextLCDPhidget_PHIDID_SERVO_1MOTOR_OLD 2L
+#undef com_phidgets_TextLCDPhidget_PHIDID_SERVO_4MOTOR
+#define com_phidgets_TextLCDPhidget_PHIDID_SERVO_4MOTOR 56L
+#undef com_phidgets_TextLCDPhidget_PHIDID_SERVO_4MOTOR_OLD
+#define com_phidgets_TextLCDPhidget_PHIDID_SERVO_4MOTOR_OLD 3L
+#undef com_phidgets_TextLCDPhidget_PHIDID_TEXTLCD_2x20
+#define com_phidgets_TextLCDPhidget_PHIDID_TEXTLCD_2x20 82L
+#undef com_phidgets_TextLCDPhidget_PHIDID_TEXTLCD_2x20_w_0_8_8
+#define com_phidgets_TextLCDPhidget_PHIDID_TEXTLCD_2x20_w_0_8_8 339L
+#undef com_phidgets_TextLCDPhidget_PHIDID_TEXTLED_1x8
+#define com_phidgets_TextLCDPhidget_PHIDID_TEXTLED_1x8 73L
+#undef com_phidgets_TextLCDPhidget_PHIDID_TEXTLED_4x8
+#define com_phidgets_TextLCDPhidget_PHIDID_TEXTLED_4x8 72L
+#undef com_phidgets_TextLCDPhidget_PHIDID_WEIGHTSENSOR
+#define com_phidgets_TextLCDPhidget_PHIDID_WEIGHTSENSOR 114L
+#undef com_phidgets_TextLCDPhidget_PHIDCLASS_NOTHING
+#define com_phidgets_TextLCDPhidget_PHIDCLASS_NOTHING 1L
+#undef com_phidgets_TextLCDPhidget_PHIDCLASS_ACCELEROMETER
+#define com_phidgets_TextLCDPhidget_PHIDCLASS_ACCELEROMETER 2L
+#undef com_phidgets_TextLCDPhidget_PHIDCLASS_ADVANCEDSERVO
+#define com_phidgets_TextLCDPhidget_PHIDCLASS_ADVANCEDSERVO 3L
+#undef com_phidgets_TextLCDPhidget_PHIDCLASS_ANALOG
+#define com_phidgets_TextLCDPhidget_PHIDCLASS_ANALOG 22L
+#undef com_phidgets_TextLCDPhidget_PHIDCLASS_BRIDGE
+#define com_phidgets_TextLCDPhidget_PHIDCLASS_BRIDGE 23L
+#undef com_phidgets_TextLCDPhidget_PHIDCLASS_ENCODER
+#define com_phidgets_TextLCDPhidget_PHIDCLASS_ENCODER 4L
+#undef com_phidgets_TextLCDPhidget_PHIDCLASS_FREQUENCYCOUNTER
+#define com_phidgets_TextLCDPhidget_PHIDCLASS_FREQUENCYCOUNTER 21L
+#undef com_phidgets_TextLCDPhidget_PHIDCLASS_GPS
+#define com_phidgets_TextLCDPhidget_PHIDCLASS_GPS 5L
+#undef com_phidgets_TextLCDPhidget_PHIDCLASS_INTERFACEKIT
+#define com_phidgets_TextLCDPhidget_PHIDCLASS_INTERFACEKIT 7L
+#undef com_phidgets_TextLCDPhidget_PHIDCLASS_LED
+#define com_phidgets_TextLCDPhidget_PHIDCLASS_LED 8L
+#undef com_phidgets_TextLCDPhidget_PHIDCLASS_MOTORCONTROL
+#define com_phidgets_TextLCDPhidget_PHIDCLASS_MOTORCONTROL 9L
+#undef com_phidgets_TextLCDPhidget_PHIDCLASS_PHSENSOR
+#define com_phidgets_TextLCDPhidget_PHIDCLASS_PHSENSOR 10L
+#undef com_phidgets_TextLCDPhidget_PHIDCLASS_RFID
+#define com_phidgets_TextLCDPhidget_PHIDCLASS_RFID 11L
+#undef com_phidgets_TextLCDPhidget_PHIDCLASS_SERVO
+#define com_phidgets_TextLCDPhidget_PHIDCLASS_SERVO 12L
+#undef com_phidgets_TextLCDPhidget_PHIDCLASS_STEPPER
+#define com_phidgets_TextLCDPhidget_PHIDCLASS_STEPPER 13L
+#undef com_phidgets_TextLCDPhidget_PHIDCLASS_TEMPERATURESENSOR
+#define com_phidgets_TextLCDPhidget_PHIDCLASS_TEMPERATURESENSOR 14L
+#undef com_phidgets_TextLCDPhidget_PHIDCLASS_TEXTLCD
+#define com_phidgets_TextLCDPhidget_PHIDCLASS_TEXTLCD 15L
+#undef com_phidgets_TextLCDPhidget_PHIDCLASS_TEXTLED
+#define com_phidgets_TextLCDPhidget_PHIDCLASS_TEXTLED 16L
+#undef com_phidgets_TextLCDPhidget_PHIDCLASS_WEIGHTSENSOR
+#define com_phidgets_TextLCDPhidget_PHIDCLASS_WEIGHTSENSOR 17L
+#undef com_phidgets_TextLCDPhidget_PHIDGET_TEXTLCD_SCREEN_NONE
+#define com_phidgets_TextLCDPhidget_PHIDGET_TEXTLCD_SCREEN_NONE 1L
+#undef com_phidgets_TextLCDPhidget_PHIDGET_TEXTLCD_SCREEN_1x8
+#define com_phidgets_TextLCDPhidget_PHIDGET_TEXTLCD_SCREEN_1x8 2L
+#undef com_phidgets_TextLCDPhidget_PHIDGET_TEXTLCD_SCREEN_2x8
+#define com_phidgets_TextLCDPhidget_PHIDGET_TEXTLCD_SCREEN_2x8 3L
+#undef com_phidgets_TextLCDPhidget_PHIDGET_TEXTLCD_SCREEN_1x16
+#define com_phidgets_TextLCDPhidget_PHIDGET_TEXTLCD_SCREEN_1x16 4L
+#undef com_phidgets_TextLCDPhidget_PHIDGET_TEXTLCD_SCREEN_2x16
+#define com_phidgets_TextLCDPhidget_PHIDGET_TEXTLCD_SCREEN_2x16 5L
+#undef com_phidgets_TextLCDPhidget_PHIDGET_TEXTLCD_SCREEN_4x16
+#define com_phidgets_TextLCDPhidget_PHIDGET_TEXTLCD_SCREEN_4x16 6L
+#undef com_phidgets_TextLCDPhidget_PHIDGET_TEXTLCD_SCREEN_2x20
+#define com_phidgets_TextLCDPhidget_PHIDGET_TEXTLCD_SCREEN_2x20 7L
+#undef com_phidgets_TextLCDPhidget_PHIDGET_TEXTLCD_SCREEN_4x20
+#define com_phidgets_TextLCDPhidget_PHIDGET_TEXTLCD_SCREEN_4x20 8L
+#undef com_phidgets_TextLCDPhidget_PHIDGET_TEXTLCD_SCREEN_2x24
+#define com_phidgets_TextLCDPhidget_PHIDGET_TEXTLCD_SCREEN_2x24 9L
+#undef com_phidgets_TextLCDPhidget_PHIDGET_TEXTLCD_SCREEN_1x40
+#define com_phidgets_TextLCDPhidget_PHIDGET_TEXTLCD_SCREEN_1x40 10L
+#undef com_phidgets_TextLCDPhidget_PHIDGET_TEXTLCD_SCREEN_2x40
+#define com_phidgets_TextLCDPhidget_PHIDGET_TEXTLCD_SCREEN_2x40 11L
+#undef com_phidgets_TextLCDPhidget_PHIDGET_TEXTLCD_SCREEN_4x40
+#define com_phidgets_TextLCDPhidget_PHIDGET_TEXTLCD_SCREEN_4x40 12L
+#undef com_phidgets_TextLCDPhidget_PHIDGET_TEXTLCD_SCREEN_UNKNOWN
+#define com_phidgets_TextLCDPhidget_PHIDGET_TEXTLCD_SCREEN_UNKNOWN 13L
+/*
+ * Class: com_phidgets_TextLCDPhidget
+ * Method: create
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL Java_com_phidgets_TextLCDPhidget_create
+ (JNIEnv *, jclass);
+
+/*
+ * Class: com_phidgets_TextLCDPhidget
+ * Method: getRowCount
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_phidgets_TextLCDPhidget_getRowCount
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_TextLCDPhidget
+ * Method: getColumnCount
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_phidgets_TextLCDPhidget_getColumnCount
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_TextLCDPhidget
+ * Method: getScreenCount
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_phidgets_TextLCDPhidget_getScreenCount
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_TextLCDPhidget
+ * Method: getScreen
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_phidgets_TextLCDPhidget_getScreen
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_TextLCDPhidget
+ * Method: setScreen
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_TextLCDPhidget_setScreen
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_TextLCDPhidget
+ * Method: getScreenSize
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_phidgets_TextLCDPhidget_getScreenSize
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_TextLCDPhidget
+ * Method: setScreenSize
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_TextLCDPhidget_setScreenSize
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_TextLCDPhidget
+ * Method: getContrast
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_phidgets_TextLCDPhidget_getContrast
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_TextLCDPhidget
+ * Method: setContrast
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_TextLCDPhidget_setContrast
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_TextLCDPhidget
+ * Method: getBrightness
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_phidgets_TextLCDPhidget_getBrightness
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_TextLCDPhidget
+ * Method: setBrightness
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_TextLCDPhidget_setBrightness
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_TextLCDPhidget
+ * Method: getBacklight
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_phidgets_TextLCDPhidget_getBacklight
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_TextLCDPhidget
+ * Method: setBacklight
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_TextLCDPhidget_setBacklight
+ (JNIEnv *, jobject, jboolean);
+
+/*
+ * Class: com_phidgets_TextLCDPhidget
+ * Method: getCursor
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_phidgets_TextLCDPhidget_getCursor
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_TextLCDPhidget
+ * Method: setCursor
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_TextLCDPhidget_setCursor
+ (JNIEnv *, jobject, jboolean);
+
+/*
+ * Class: com_phidgets_TextLCDPhidget
+ * Method: getCursorBlink
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_phidgets_TextLCDPhidget_getCursorBlink
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_TextLCDPhidget
+ * Method: setCursorBlink
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_TextLCDPhidget_setCursorBlink
+ (JNIEnv *, jobject, jboolean);
+
+/*
+ * Class: com_phidgets_TextLCDPhidget
+ * Method: setDisplayString
+ * Signature: (ILjava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_TextLCDPhidget_setDisplayString
+ (JNIEnv *, jobject, jint, jstring);
+
+/*
+ * Class: com_phidgets_TextLCDPhidget
+ * Method: setDisplayCharacter
+ * Signature: (IIC)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_TextLCDPhidget_setDisplayCharacter
+ (JNIEnv *, jobject, jint, jint, jchar);
+
+/*
+ * Class: com_phidgets_TextLCDPhidget
+ * Method: setCustomCharacter
+ * Signature: (III)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_TextLCDPhidget_setCustomCharacter
+ (JNIEnv *, jobject, jint, jint, jint);
+
+/*
+ * Class: com_phidgets_TextLCDPhidget
+ * Method: initialize
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_TextLCDPhidget_initialize
+ (JNIEnv *, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/Java/com_phidgets_TextLEDPhidget.c b/Java/com_phidgets_TextLEDPhidget.c
new file mode 100644
index 0000000..f6f139c
--- /dev/null
+++ b/Java/com_phidgets_TextLEDPhidget.c
@@ -0,0 +1,29 @@
+#include "../stdafx.h"
+#include "phidget_jni.h"
+#include "com_phidgets_TextLEDPhidget.h"
+#include "../cphidgettextled.h"
+
+JNI_LOAD(led, TextLED)
+}
+
+JNI_CREATE(TextLED)
+JNI_GETFUNC(TextLED, Brightness, Brightness, jint)
+JNI_SETFUNC(TextLED, Brightness, Brightness, jint)
+JNI_GETFUNC(TextLED, RowCount, RowCount, jint)
+JNI_GETFUNC(TextLED, ColumnCount, ColumnCount, jint)
+
+JNIEXPORT void JNICALL
+Java_com_phidgets_TextLEDPhidget_setDisplayString(JNIEnv *env, jobject obj, jint index, jstring v)
+{
+ CPhidgetTextLEDHandle h = (CPhidgetTextLEDHandle)(uintptr_t)
+ (*env)->GetLongField(env, obj, handle_fid);
+ int error;
+ jboolean iscopy;
+ const char *textString = (*env)->GetStringUTFChars(
+ env, v, &iscopy);
+
+ if ((error = CPhidgetTextLED_setDisplayString(h, index, (char *)textString)))
+ PH_THROW(error);
+
+ (*env)->ReleaseStringUTFChars(env, v, textString);
+}
diff --git a/Java/com_phidgets_TextLEDPhidget.h b/Java/com_phidgets_TextLEDPhidget.h
new file mode 100644
index 0000000..b62ffa1
--- /dev/null
+++ b/Java/com_phidgets_TextLEDPhidget.h
@@ -0,0 +1,205 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class com_phidgets_TextLEDPhidget */
+
+#ifndef _Included_com_phidgets_TextLEDPhidget
+#define _Included_com_phidgets_TextLEDPhidget
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef com_phidgets_TextLEDPhidget_PHIDGET_LOG_CRITICAL
+#define com_phidgets_TextLEDPhidget_PHIDGET_LOG_CRITICAL 1L
+#undef com_phidgets_TextLEDPhidget_PHIDGET_LOG_ERROR
+#define com_phidgets_TextLEDPhidget_PHIDGET_LOG_ERROR 2L
+#undef com_phidgets_TextLEDPhidget_PHIDGET_LOG_WARNING
+#define com_phidgets_TextLEDPhidget_PHIDGET_LOG_WARNING 3L
+#undef com_phidgets_TextLEDPhidget_PHIDGET_LOG_DEBUG
+#define com_phidgets_TextLEDPhidget_PHIDGET_LOG_DEBUG 4L
+#undef com_phidgets_TextLEDPhidget_PHIDGET_LOG_INFO
+#define com_phidgets_TextLEDPhidget_PHIDGET_LOG_INFO 5L
+#undef com_phidgets_TextLEDPhidget_PHIDGET_LOG_VERBOSE
+#define com_phidgets_TextLEDPhidget_PHIDGET_LOG_VERBOSE 6L
+#undef com_phidgets_TextLEDPhidget_PHIDID_NOTHING
+#define com_phidgets_TextLEDPhidget_PHIDID_NOTHING 1L
+#undef com_phidgets_TextLEDPhidget_PHIDID_ACCELEROMETER_3AXIS
+#define com_phidgets_TextLEDPhidget_PHIDID_ACCELEROMETER_3AXIS 126L
+#undef com_phidgets_TextLEDPhidget_PHIDID_ADVANCEDSERVO_1MOTOR
+#define com_phidgets_TextLEDPhidget_PHIDID_ADVANCEDSERVO_1MOTOR 130L
+#undef com_phidgets_TextLEDPhidget_PHIDID_ANALOG_4OUTPUT
+#define com_phidgets_TextLEDPhidget_PHIDID_ANALOG_4OUTPUT 55L
+#undef com_phidgets_TextLEDPhidget_PHIDID_ADVANCEDSERVO_8MOTOR
+#define com_phidgets_TextLEDPhidget_PHIDID_ADVANCEDSERVO_8MOTOR 58L
+#undef com_phidgets_TextLEDPhidget_PHIDID_BIPOLAR_STEPPER_1MOTOR
+#define com_phidgets_TextLEDPhidget_PHIDID_BIPOLAR_STEPPER_1MOTOR 123L
+#undef com_phidgets_TextLEDPhidget_PHIDID_BRIDGE_4INPUT
+#define com_phidgets_TextLEDPhidget_PHIDID_BRIDGE_4INPUT 59L
+#undef com_phidgets_TextLEDPhidget_PHIDID_ENCODER_1ENCODER_1INPUT
+#define com_phidgets_TextLEDPhidget_PHIDID_ENCODER_1ENCODER_1INPUT 75L
+#undef com_phidgets_TextLEDPhidget_PHIDID_ENCODER_HS_1ENCODER
+#define com_phidgets_TextLEDPhidget_PHIDID_ENCODER_HS_1ENCODER 128L
+#undef com_phidgets_TextLEDPhidget_PHIDID_ENCODER_HS_4ENCODER_4INPUT
+#define com_phidgets_TextLEDPhidget_PHIDID_ENCODER_HS_4ENCODER_4INPUT 79L
+#undef com_phidgets_TextLEDPhidget_PHIDID_FREQUENCYCOUNTER_2INPUT
+#define com_phidgets_TextLEDPhidget_PHIDID_FREQUENCYCOUNTER_2INPUT 53L
+#undef com_phidgets_TextLEDPhidget_PHIDID_GPS
+#define com_phidgets_TextLEDPhidget_PHIDID_GPS 121L
+#undef com_phidgets_TextLEDPhidget_PHIDID_INTERFACEKIT_0_0_4
+#define com_phidgets_TextLEDPhidget_PHIDID_INTERFACEKIT_0_0_4 64L
+#undef com_phidgets_TextLEDPhidget_PHIDID_INTERFACEKIT_0_0_8
+#define com_phidgets_TextLEDPhidget_PHIDID_INTERFACEKIT_0_0_8 129L
+#undef com_phidgets_TextLEDPhidget_PHIDID_INTERFACEKIT_0_16_16
+#define com_phidgets_TextLEDPhidget_PHIDID_INTERFACEKIT_0_16_16 68L
+#undef com_phidgets_TextLEDPhidget_PHIDID_INTERFACEKIT_8_8_8
+#define com_phidgets_TextLEDPhidget_PHIDID_INTERFACEKIT_8_8_8 69L
+#undef com_phidgets_TextLEDPhidget_PHIDID_INTERFACEKIT_8_8_8_w_LCD
+#define com_phidgets_TextLEDPhidget_PHIDID_INTERFACEKIT_8_8_8_w_LCD 125L
+#undef com_phidgets_TextLEDPhidget_PHIDID_IR
+#define com_phidgets_TextLEDPhidget_PHIDID_IR 77L
+#undef com_phidgets_TextLEDPhidget_PHIDID_LED_64
+#define com_phidgets_TextLEDPhidget_PHIDID_LED_64 74L
+#undef com_phidgets_TextLEDPhidget_PHIDID_LED_64_ADV
+#define com_phidgets_TextLEDPhidget_PHIDID_LED_64_ADV 76L
+#undef com_phidgets_TextLEDPhidget_PHIDID_LINEAR_TOUCH
+#define com_phidgets_TextLEDPhidget_PHIDID_LINEAR_TOUCH 118L
+#undef com_phidgets_TextLEDPhidget_PHIDID_MOTORCONTROL_HC_2MOTOR
+#define com_phidgets_TextLEDPhidget_PHIDID_MOTORCONTROL_HC_2MOTOR 89L
+#undef com_phidgets_TextLEDPhidget_PHIDID_MOTORCONTROL_LV_2MOTOR_4INPUT
+#define com_phidgets_TextLEDPhidget_PHIDID_MOTORCONTROL_LV_2MOTOR_4INPUT 88L
+#undef com_phidgets_TextLEDPhidget_PHIDID_MOTORCONTROL_1MOTOR
+#define com_phidgets_TextLEDPhidget_PHIDID_MOTORCONTROL_1MOTOR 62L
+#undef com_phidgets_TextLEDPhidget_PHIDID_PHSENSOR
+#define com_phidgets_TextLEDPhidget_PHIDID_PHSENSOR 116L
+#undef com_phidgets_TextLEDPhidget_PHIDID_RFID_2OUTPUT
+#define com_phidgets_TextLEDPhidget_PHIDID_RFID_2OUTPUT 49L
+#undef com_phidgets_TextLEDPhidget_PHIDID_ROTARY_TOUCH
+#define com_phidgets_TextLEDPhidget_PHIDID_ROTARY_TOUCH 119L
+#undef com_phidgets_TextLEDPhidget_PHIDID_SERVO_1MOTOR
+#define com_phidgets_TextLEDPhidget_PHIDID_SERVO_1MOTOR 57L
+#undef com_phidgets_TextLEDPhidget_PHIDID_SPATIAL_ACCEL_3AXIS
+#define com_phidgets_TextLEDPhidget_PHIDID_SPATIAL_ACCEL_3AXIS 127L
+#undef com_phidgets_TextLEDPhidget_PHIDID_SPATIAL_ACCEL_GYRO_COMPASS
+#define com_phidgets_TextLEDPhidget_PHIDID_SPATIAL_ACCEL_GYRO_COMPASS 51L
+#undef com_phidgets_TextLEDPhidget_PHIDID_TEMPERATURESENSOR
+#define com_phidgets_TextLEDPhidget_PHIDID_TEMPERATURESENSOR 112L
+#undef com_phidgets_TextLEDPhidget_PHIDID_TEMPERATURESENSOR_4
+#define com_phidgets_TextLEDPhidget_PHIDID_TEMPERATURESENSOR_4 50L
+#undef com_phidgets_TextLEDPhidget_PHIDID_TEXTLCD_2x20_w_8_8_8
+#define com_phidgets_TextLEDPhidget_PHIDID_TEXTLCD_2x20_w_8_8_8 381L
+#undef com_phidgets_TextLEDPhidget_PHIDID_TEXTLCD_ADAPTER
+#define com_phidgets_TextLEDPhidget_PHIDID_TEXTLCD_ADAPTER 61L
+#undef com_phidgets_TextLEDPhidget_PHIDID_UNIPOLAR_STEPPER_4MOTOR
+#define com_phidgets_TextLEDPhidget_PHIDID_UNIPOLAR_STEPPER_4MOTOR 122L
+#undef com_phidgets_TextLEDPhidget_PHIDID_ACCELEROMETER_2AXIS
+#define com_phidgets_TextLEDPhidget_PHIDID_ACCELEROMETER_2AXIS 113L
+#undef com_phidgets_TextLEDPhidget_PHIDID_INTERFACEKIT_0_8_8_w_LCD
+#define com_phidgets_TextLEDPhidget_PHIDID_INTERFACEKIT_0_8_8_w_LCD 83L
+#undef com_phidgets_TextLEDPhidget_PHIDID_INTERFACEKIT_4_8_8
+#define com_phidgets_TextLEDPhidget_PHIDID_INTERFACEKIT_4_8_8 4L
+#undef com_phidgets_TextLEDPhidget_PHIDID_RFID
+#define com_phidgets_TextLEDPhidget_PHIDID_RFID 48L
+#undef com_phidgets_TextLEDPhidget_PHIDID_SERVO_1MOTOR_OLD
+#define com_phidgets_TextLEDPhidget_PHIDID_SERVO_1MOTOR_OLD 2L
+#undef com_phidgets_TextLEDPhidget_PHIDID_SERVO_4MOTOR
+#define com_phidgets_TextLEDPhidget_PHIDID_SERVO_4MOTOR 56L
+#undef com_phidgets_TextLEDPhidget_PHIDID_SERVO_4MOTOR_OLD
+#define com_phidgets_TextLEDPhidget_PHIDID_SERVO_4MOTOR_OLD 3L
+#undef com_phidgets_TextLEDPhidget_PHIDID_TEXTLCD_2x20
+#define com_phidgets_TextLEDPhidget_PHIDID_TEXTLCD_2x20 82L
+#undef com_phidgets_TextLEDPhidget_PHIDID_TEXTLCD_2x20_w_0_8_8
+#define com_phidgets_TextLEDPhidget_PHIDID_TEXTLCD_2x20_w_0_8_8 339L
+#undef com_phidgets_TextLEDPhidget_PHIDID_TEXTLED_1x8
+#define com_phidgets_TextLEDPhidget_PHIDID_TEXTLED_1x8 73L
+#undef com_phidgets_TextLEDPhidget_PHIDID_TEXTLED_4x8
+#define com_phidgets_TextLEDPhidget_PHIDID_TEXTLED_4x8 72L
+#undef com_phidgets_TextLEDPhidget_PHIDID_WEIGHTSENSOR
+#define com_phidgets_TextLEDPhidget_PHIDID_WEIGHTSENSOR 114L
+#undef com_phidgets_TextLEDPhidget_PHIDCLASS_NOTHING
+#define com_phidgets_TextLEDPhidget_PHIDCLASS_NOTHING 1L
+#undef com_phidgets_TextLEDPhidget_PHIDCLASS_ACCELEROMETER
+#define com_phidgets_TextLEDPhidget_PHIDCLASS_ACCELEROMETER 2L
+#undef com_phidgets_TextLEDPhidget_PHIDCLASS_ADVANCEDSERVO
+#define com_phidgets_TextLEDPhidget_PHIDCLASS_ADVANCEDSERVO 3L
+#undef com_phidgets_TextLEDPhidget_PHIDCLASS_ANALOG
+#define com_phidgets_TextLEDPhidget_PHIDCLASS_ANALOG 22L
+#undef com_phidgets_TextLEDPhidget_PHIDCLASS_BRIDGE
+#define com_phidgets_TextLEDPhidget_PHIDCLASS_BRIDGE 23L
+#undef com_phidgets_TextLEDPhidget_PHIDCLASS_ENCODER
+#define com_phidgets_TextLEDPhidget_PHIDCLASS_ENCODER 4L
+#undef com_phidgets_TextLEDPhidget_PHIDCLASS_FREQUENCYCOUNTER
+#define com_phidgets_TextLEDPhidget_PHIDCLASS_FREQUENCYCOUNTER 21L
+#undef com_phidgets_TextLEDPhidget_PHIDCLASS_GPS
+#define com_phidgets_TextLEDPhidget_PHIDCLASS_GPS 5L
+#undef com_phidgets_TextLEDPhidget_PHIDCLASS_INTERFACEKIT
+#define com_phidgets_TextLEDPhidget_PHIDCLASS_INTERFACEKIT 7L
+#undef com_phidgets_TextLEDPhidget_PHIDCLASS_LED
+#define com_phidgets_TextLEDPhidget_PHIDCLASS_LED 8L
+#undef com_phidgets_TextLEDPhidget_PHIDCLASS_MOTORCONTROL
+#define com_phidgets_TextLEDPhidget_PHIDCLASS_MOTORCONTROL 9L
+#undef com_phidgets_TextLEDPhidget_PHIDCLASS_PHSENSOR
+#define com_phidgets_TextLEDPhidget_PHIDCLASS_PHSENSOR 10L
+#undef com_phidgets_TextLEDPhidget_PHIDCLASS_RFID
+#define com_phidgets_TextLEDPhidget_PHIDCLASS_RFID 11L
+#undef com_phidgets_TextLEDPhidget_PHIDCLASS_SERVO
+#define com_phidgets_TextLEDPhidget_PHIDCLASS_SERVO 12L
+#undef com_phidgets_TextLEDPhidget_PHIDCLASS_STEPPER
+#define com_phidgets_TextLEDPhidget_PHIDCLASS_STEPPER 13L
+#undef com_phidgets_TextLEDPhidget_PHIDCLASS_TEMPERATURESENSOR
+#define com_phidgets_TextLEDPhidget_PHIDCLASS_TEMPERATURESENSOR 14L
+#undef com_phidgets_TextLEDPhidget_PHIDCLASS_TEXTLCD
+#define com_phidgets_TextLEDPhidget_PHIDCLASS_TEXTLCD 15L
+#undef com_phidgets_TextLEDPhidget_PHIDCLASS_TEXTLED
+#define com_phidgets_TextLEDPhidget_PHIDCLASS_TEXTLED 16L
+#undef com_phidgets_TextLEDPhidget_PHIDCLASS_WEIGHTSENSOR
+#define com_phidgets_TextLEDPhidget_PHIDCLASS_WEIGHTSENSOR 17L
+/*
+ * Class: com_phidgets_TextLEDPhidget
+ * Method: create
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL Java_com_phidgets_TextLEDPhidget_create
+ (JNIEnv *, jclass);
+
+/*
+ * Class: com_phidgets_TextLEDPhidget
+ * Method: getRowCount
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_phidgets_TextLEDPhidget_getRowCount
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_TextLEDPhidget
+ * Method: getColumnCount
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_phidgets_TextLEDPhidget_getColumnCount
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_TextLEDPhidget
+ * Method: getBrightness
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_phidgets_TextLEDPhidget_getBrightness
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_TextLEDPhidget
+ * Method: setBrightness
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_TextLEDPhidget_setBrightness
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: com_phidgets_TextLEDPhidget
+ * Method: setDisplayString
+ * Signature: (ILjava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_TextLEDPhidget_setDisplayString
+ (JNIEnv *, jobject, jint, jstring);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/Java/com_phidgets_WeightSensorPhidget.c b/Java/com_phidgets_WeightSensorPhidget.c
new file mode 100644
index 0000000..59a88bd
--- /dev/null
+++ b/Java/com_phidgets_WeightSensorPhidget.c
@@ -0,0 +1,18 @@
+#include "../stdafx.h"
+#include "phidget_jni.h"
+#include "com_phidgets_WeightSensorPhidget.h"
+#include "../cphidgetweightsensor.h"
+
+EVENT_VARS(weightChange, WeightChange)
+
+JNI_LOAD(weight, WeightSensor)
+ EVENT_VAR_SETUP(weight, weightChange, WeightChange, D, V)
+}
+
+EVENT_HANDLER(WeightSensor, weightChange, WeightChange,
+ CPhidgetWeightSensor_set_OnWeightChange_Handler, double)
+
+JNI_CREATE(WeightSensor)
+JNI_GETFUNC(WeightSensor, WeightChangeTrigger, WeightChangeTrigger, jdouble)
+JNI_SETFUNC(WeightSensor, WeightChangeTrigger, WeightChangeTrigger, jdouble)
+JNI_GETFUNC(WeightSensor, Weight, Weight, jdouble)
diff --git a/Java/com_phidgets_WeightSensorPhidget.h b/Java/com_phidgets_WeightSensorPhidget.h
new file mode 100644
index 0000000..2de6bde
--- /dev/null
+++ b/Java/com_phidgets_WeightSensorPhidget.h
@@ -0,0 +1,197 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class com_phidgets_WeightSensorPhidget */
+
+#ifndef _Included_com_phidgets_WeightSensorPhidget
+#define _Included_com_phidgets_WeightSensorPhidget
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef com_phidgets_WeightSensorPhidget_PHIDGET_LOG_CRITICAL
+#define com_phidgets_WeightSensorPhidget_PHIDGET_LOG_CRITICAL 1L
+#undef com_phidgets_WeightSensorPhidget_PHIDGET_LOG_ERROR
+#define com_phidgets_WeightSensorPhidget_PHIDGET_LOG_ERROR 2L
+#undef com_phidgets_WeightSensorPhidget_PHIDGET_LOG_WARNING
+#define com_phidgets_WeightSensorPhidget_PHIDGET_LOG_WARNING 3L
+#undef com_phidgets_WeightSensorPhidget_PHIDGET_LOG_DEBUG
+#define com_phidgets_WeightSensorPhidget_PHIDGET_LOG_DEBUG 4L
+#undef com_phidgets_WeightSensorPhidget_PHIDGET_LOG_INFO
+#define com_phidgets_WeightSensorPhidget_PHIDGET_LOG_INFO 5L
+#undef com_phidgets_WeightSensorPhidget_PHIDGET_LOG_VERBOSE
+#define com_phidgets_WeightSensorPhidget_PHIDGET_LOG_VERBOSE 6L
+#undef com_phidgets_WeightSensorPhidget_PHIDID_NOTHING
+#define com_phidgets_WeightSensorPhidget_PHIDID_NOTHING 1L
+#undef com_phidgets_WeightSensorPhidget_PHIDID_ACCELEROMETER_3AXIS
+#define com_phidgets_WeightSensorPhidget_PHIDID_ACCELEROMETER_3AXIS 126L
+#undef com_phidgets_WeightSensorPhidget_PHIDID_ADVANCEDSERVO_1MOTOR
+#define com_phidgets_WeightSensorPhidget_PHIDID_ADVANCEDSERVO_1MOTOR 130L
+#undef com_phidgets_WeightSensorPhidget_PHIDID_ANALOG_4OUTPUT
+#define com_phidgets_WeightSensorPhidget_PHIDID_ANALOG_4OUTPUT 55L
+#undef com_phidgets_WeightSensorPhidget_PHIDID_ADVANCEDSERVO_8MOTOR
+#define com_phidgets_WeightSensorPhidget_PHIDID_ADVANCEDSERVO_8MOTOR 58L
+#undef com_phidgets_WeightSensorPhidget_PHIDID_BIPOLAR_STEPPER_1MOTOR
+#define com_phidgets_WeightSensorPhidget_PHIDID_BIPOLAR_STEPPER_1MOTOR 123L
+#undef com_phidgets_WeightSensorPhidget_PHIDID_BRIDGE_4INPUT
+#define com_phidgets_WeightSensorPhidget_PHIDID_BRIDGE_4INPUT 59L
+#undef com_phidgets_WeightSensorPhidget_PHIDID_ENCODER_1ENCODER_1INPUT
+#define com_phidgets_WeightSensorPhidget_PHIDID_ENCODER_1ENCODER_1INPUT 75L
+#undef com_phidgets_WeightSensorPhidget_PHIDID_ENCODER_HS_1ENCODER
+#define com_phidgets_WeightSensorPhidget_PHIDID_ENCODER_HS_1ENCODER 128L
+#undef com_phidgets_WeightSensorPhidget_PHIDID_ENCODER_HS_4ENCODER_4INPUT
+#define com_phidgets_WeightSensorPhidget_PHIDID_ENCODER_HS_4ENCODER_4INPUT 79L
+#undef com_phidgets_WeightSensorPhidget_PHIDID_FREQUENCYCOUNTER_2INPUT
+#define com_phidgets_WeightSensorPhidget_PHIDID_FREQUENCYCOUNTER_2INPUT 53L
+#undef com_phidgets_WeightSensorPhidget_PHIDID_GPS
+#define com_phidgets_WeightSensorPhidget_PHIDID_GPS 121L
+#undef com_phidgets_WeightSensorPhidget_PHIDID_INTERFACEKIT_0_0_4
+#define com_phidgets_WeightSensorPhidget_PHIDID_INTERFACEKIT_0_0_4 64L
+#undef com_phidgets_WeightSensorPhidget_PHIDID_INTERFACEKIT_0_0_8
+#define com_phidgets_WeightSensorPhidget_PHIDID_INTERFACEKIT_0_0_8 129L
+#undef com_phidgets_WeightSensorPhidget_PHIDID_INTERFACEKIT_0_16_16
+#define com_phidgets_WeightSensorPhidget_PHIDID_INTERFACEKIT_0_16_16 68L
+#undef com_phidgets_WeightSensorPhidget_PHIDID_INTERFACEKIT_8_8_8
+#define com_phidgets_WeightSensorPhidget_PHIDID_INTERFACEKIT_8_8_8 69L
+#undef com_phidgets_WeightSensorPhidget_PHIDID_INTERFACEKIT_8_8_8_w_LCD
+#define com_phidgets_WeightSensorPhidget_PHIDID_INTERFACEKIT_8_8_8_w_LCD 125L
+#undef com_phidgets_WeightSensorPhidget_PHIDID_IR
+#define com_phidgets_WeightSensorPhidget_PHIDID_IR 77L
+#undef com_phidgets_WeightSensorPhidget_PHIDID_LED_64
+#define com_phidgets_WeightSensorPhidget_PHIDID_LED_64 74L
+#undef com_phidgets_WeightSensorPhidget_PHIDID_LED_64_ADV
+#define com_phidgets_WeightSensorPhidget_PHIDID_LED_64_ADV 76L
+#undef com_phidgets_WeightSensorPhidget_PHIDID_LINEAR_TOUCH
+#define com_phidgets_WeightSensorPhidget_PHIDID_LINEAR_TOUCH 118L
+#undef com_phidgets_WeightSensorPhidget_PHIDID_MOTORCONTROL_HC_2MOTOR
+#define com_phidgets_WeightSensorPhidget_PHIDID_MOTORCONTROL_HC_2MOTOR 89L
+#undef com_phidgets_WeightSensorPhidget_PHIDID_MOTORCONTROL_LV_2MOTOR_4INPUT
+#define com_phidgets_WeightSensorPhidget_PHIDID_MOTORCONTROL_LV_2MOTOR_4INPUT 88L
+#undef com_phidgets_WeightSensorPhidget_PHIDID_MOTORCONTROL_1MOTOR
+#define com_phidgets_WeightSensorPhidget_PHIDID_MOTORCONTROL_1MOTOR 62L
+#undef com_phidgets_WeightSensorPhidget_PHIDID_PHSENSOR
+#define com_phidgets_WeightSensorPhidget_PHIDID_PHSENSOR 116L
+#undef com_phidgets_WeightSensorPhidget_PHIDID_RFID_2OUTPUT
+#define com_phidgets_WeightSensorPhidget_PHIDID_RFID_2OUTPUT 49L
+#undef com_phidgets_WeightSensorPhidget_PHIDID_ROTARY_TOUCH
+#define com_phidgets_WeightSensorPhidget_PHIDID_ROTARY_TOUCH 119L
+#undef com_phidgets_WeightSensorPhidget_PHIDID_SERVO_1MOTOR
+#define com_phidgets_WeightSensorPhidget_PHIDID_SERVO_1MOTOR 57L
+#undef com_phidgets_WeightSensorPhidget_PHIDID_SPATIAL_ACCEL_3AXIS
+#define com_phidgets_WeightSensorPhidget_PHIDID_SPATIAL_ACCEL_3AXIS 127L
+#undef com_phidgets_WeightSensorPhidget_PHIDID_SPATIAL_ACCEL_GYRO_COMPASS
+#define com_phidgets_WeightSensorPhidget_PHIDID_SPATIAL_ACCEL_GYRO_COMPASS 51L
+#undef com_phidgets_WeightSensorPhidget_PHIDID_TEMPERATURESENSOR
+#define com_phidgets_WeightSensorPhidget_PHIDID_TEMPERATURESENSOR 112L
+#undef com_phidgets_WeightSensorPhidget_PHIDID_TEMPERATURESENSOR_4
+#define com_phidgets_WeightSensorPhidget_PHIDID_TEMPERATURESENSOR_4 50L
+#undef com_phidgets_WeightSensorPhidget_PHIDID_TEXTLCD_2x20_w_8_8_8
+#define com_phidgets_WeightSensorPhidget_PHIDID_TEXTLCD_2x20_w_8_8_8 381L
+#undef com_phidgets_WeightSensorPhidget_PHIDID_TEXTLCD_ADAPTER
+#define com_phidgets_WeightSensorPhidget_PHIDID_TEXTLCD_ADAPTER 61L
+#undef com_phidgets_WeightSensorPhidget_PHIDID_UNIPOLAR_STEPPER_4MOTOR
+#define com_phidgets_WeightSensorPhidget_PHIDID_UNIPOLAR_STEPPER_4MOTOR 122L
+#undef com_phidgets_WeightSensorPhidget_PHIDID_ACCELEROMETER_2AXIS
+#define com_phidgets_WeightSensorPhidget_PHIDID_ACCELEROMETER_2AXIS 113L
+#undef com_phidgets_WeightSensorPhidget_PHIDID_INTERFACEKIT_0_8_8_w_LCD
+#define com_phidgets_WeightSensorPhidget_PHIDID_INTERFACEKIT_0_8_8_w_LCD 83L
+#undef com_phidgets_WeightSensorPhidget_PHIDID_INTERFACEKIT_4_8_8
+#define com_phidgets_WeightSensorPhidget_PHIDID_INTERFACEKIT_4_8_8 4L
+#undef com_phidgets_WeightSensorPhidget_PHIDID_RFID
+#define com_phidgets_WeightSensorPhidget_PHIDID_RFID 48L
+#undef com_phidgets_WeightSensorPhidget_PHIDID_SERVO_1MOTOR_OLD
+#define com_phidgets_WeightSensorPhidget_PHIDID_SERVO_1MOTOR_OLD 2L
+#undef com_phidgets_WeightSensorPhidget_PHIDID_SERVO_4MOTOR
+#define com_phidgets_WeightSensorPhidget_PHIDID_SERVO_4MOTOR 56L
+#undef com_phidgets_WeightSensorPhidget_PHIDID_SERVO_4MOTOR_OLD
+#define com_phidgets_WeightSensorPhidget_PHIDID_SERVO_4MOTOR_OLD 3L
+#undef com_phidgets_WeightSensorPhidget_PHIDID_TEXTLCD_2x20
+#define com_phidgets_WeightSensorPhidget_PHIDID_TEXTLCD_2x20 82L
+#undef com_phidgets_WeightSensorPhidget_PHIDID_TEXTLCD_2x20_w_0_8_8
+#define com_phidgets_WeightSensorPhidget_PHIDID_TEXTLCD_2x20_w_0_8_8 339L
+#undef com_phidgets_WeightSensorPhidget_PHIDID_TEXTLED_1x8
+#define com_phidgets_WeightSensorPhidget_PHIDID_TEXTLED_1x8 73L
+#undef com_phidgets_WeightSensorPhidget_PHIDID_TEXTLED_4x8
+#define com_phidgets_WeightSensorPhidget_PHIDID_TEXTLED_4x8 72L
+#undef com_phidgets_WeightSensorPhidget_PHIDID_WEIGHTSENSOR
+#define com_phidgets_WeightSensorPhidget_PHIDID_WEIGHTSENSOR 114L
+#undef com_phidgets_WeightSensorPhidget_PHIDCLASS_NOTHING
+#define com_phidgets_WeightSensorPhidget_PHIDCLASS_NOTHING 1L
+#undef com_phidgets_WeightSensorPhidget_PHIDCLASS_ACCELEROMETER
+#define com_phidgets_WeightSensorPhidget_PHIDCLASS_ACCELEROMETER 2L
+#undef com_phidgets_WeightSensorPhidget_PHIDCLASS_ADVANCEDSERVO
+#define com_phidgets_WeightSensorPhidget_PHIDCLASS_ADVANCEDSERVO 3L
+#undef com_phidgets_WeightSensorPhidget_PHIDCLASS_ANALOG
+#define com_phidgets_WeightSensorPhidget_PHIDCLASS_ANALOG 22L
+#undef com_phidgets_WeightSensorPhidget_PHIDCLASS_BRIDGE
+#define com_phidgets_WeightSensorPhidget_PHIDCLASS_BRIDGE 23L
+#undef com_phidgets_WeightSensorPhidget_PHIDCLASS_ENCODER
+#define com_phidgets_WeightSensorPhidget_PHIDCLASS_ENCODER 4L
+#undef com_phidgets_WeightSensorPhidget_PHIDCLASS_FREQUENCYCOUNTER
+#define com_phidgets_WeightSensorPhidget_PHIDCLASS_FREQUENCYCOUNTER 21L
+#undef com_phidgets_WeightSensorPhidget_PHIDCLASS_GPS
+#define com_phidgets_WeightSensorPhidget_PHIDCLASS_GPS 5L
+#undef com_phidgets_WeightSensorPhidget_PHIDCLASS_INTERFACEKIT
+#define com_phidgets_WeightSensorPhidget_PHIDCLASS_INTERFACEKIT 7L
+#undef com_phidgets_WeightSensorPhidget_PHIDCLASS_LED
+#define com_phidgets_WeightSensorPhidget_PHIDCLASS_LED 8L
+#undef com_phidgets_WeightSensorPhidget_PHIDCLASS_MOTORCONTROL
+#define com_phidgets_WeightSensorPhidget_PHIDCLASS_MOTORCONTROL 9L
+#undef com_phidgets_WeightSensorPhidget_PHIDCLASS_PHSENSOR
+#define com_phidgets_WeightSensorPhidget_PHIDCLASS_PHSENSOR 10L
+#undef com_phidgets_WeightSensorPhidget_PHIDCLASS_RFID
+#define com_phidgets_WeightSensorPhidget_PHIDCLASS_RFID 11L
+#undef com_phidgets_WeightSensorPhidget_PHIDCLASS_SERVO
+#define com_phidgets_WeightSensorPhidget_PHIDCLASS_SERVO 12L
+#undef com_phidgets_WeightSensorPhidget_PHIDCLASS_STEPPER
+#define com_phidgets_WeightSensorPhidget_PHIDCLASS_STEPPER 13L
+#undef com_phidgets_WeightSensorPhidget_PHIDCLASS_TEMPERATURESENSOR
+#define com_phidgets_WeightSensorPhidget_PHIDCLASS_TEMPERATURESENSOR 14L
+#undef com_phidgets_WeightSensorPhidget_PHIDCLASS_TEXTLCD
+#define com_phidgets_WeightSensorPhidget_PHIDCLASS_TEXTLCD 15L
+#undef com_phidgets_WeightSensorPhidget_PHIDCLASS_TEXTLED
+#define com_phidgets_WeightSensorPhidget_PHIDCLASS_TEXTLED 16L
+#undef com_phidgets_WeightSensorPhidget_PHIDCLASS_WEIGHTSENSOR
+#define com_phidgets_WeightSensorPhidget_PHIDCLASS_WEIGHTSENSOR 17L
+/*
+ * Class: com_phidgets_WeightSensorPhidget
+ * Method: create
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL Java_com_phidgets_WeightSensorPhidget_create
+ (JNIEnv *, jclass);
+
+/*
+ * Class: com_phidgets_WeightSensorPhidget
+ * Method: getWeight
+ * Signature: ()D
+ */
+JNIEXPORT jdouble JNICALL Java_com_phidgets_WeightSensorPhidget_getWeight
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_WeightSensorPhidget
+ * Method: setWeightChangeTrigger
+ * Signature: (D)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_WeightSensorPhidget_setWeightChangeTrigger
+ (JNIEnv *, jobject, jdouble);
+
+/*
+ * Class: com_phidgets_WeightSensorPhidget
+ * Method: getWeightChangeTrigger
+ * Signature: ()D
+ */
+JNIEXPORT jdouble JNICALL Java_com_phidgets_WeightSensorPhidget_getWeightChangeTrigger
+ (JNIEnv *, jobject);
+
+/*
+ * Class: com_phidgets_WeightSensorPhidget
+ * Method: enableWeightChangeEvents
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_com_phidgets_WeightSensorPhidget_enableWeightChangeEvents
+ (JNIEnv *, jobject, jboolean);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/Java/phidget_jni.c b/Java/phidget_jni.c
new file mode 100644
index 0000000..1ec7ca6
--- /dev/null
+++ b/Java/phidget_jni.c
@@ -0,0 +1,156 @@
+#include "../stdafx.h"
+#include <stdlib.h>
+#include "../cphidget.h"
+#include "phidget_jni.h"
+#include <stdio.h>
+
+JavaVM *ph_vm = 0;
+
+jclass phidget_class;
+jmethodID phidget_cons;
+
+jclass ph_exception_class;
+jmethodID ph_exception_cons;
+
+jclass attachEvent_class;
+jmethodID attachEvent_cons;
+
+jclass detachEvent_class;
+jmethodID detachEvent_cons;
+
+jclass errorEvent_class;
+jmethodID errorEvent_cons;
+
+jclass serverConnectEvent_class;
+jmethodID serverConnectEvent_cons;
+
+jclass serverDisconnectEvent_class;
+jmethodID serverDisconnectEvent_cons;
+
+jint JNICALL
+JNI_OnLoad(JavaVM *vm, void *reserved)
+{
+ JNIEnv *env;
+ jint version = 0;
+ jint result;
+
+ ph_vm = vm;
+
+ result = (*vm)->GetEnv(vm, (void **)&env, JNI_VERSION_1_4);
+
+ if(result == JNI_EDETACHED)
+ if ((*vm)->AttachCurrentThread(vm, (JNIEnvPtr)&env, NULL))
+ JNI_ABORT_STDERR("Couldn't Attach Thread");
+
+ if(!(version = (*env)->GetVersion(env)))
+ JNI_ABORT_STDERR("Couldn't get version");
+ LOG(PHIDGET_LOG_DEBUG,"JNI Version: %08x",version);
+
+ //Load all Phidget classes, and needed methods and fields...
+ //Phidget
+ if (!(phidget_class = (*env)->FindClass(env, "com/phidgets/Phidget")))
+ JNI_ABORT_STDERR("");
+ if (!(phidget_class = (jclass)(*env)->NewGlobalRef(env, phidget_class)))
+ JNI_ABORT_STDERR("");
+ if (!(phidget_cons = (*env)->GetMethodID(env, phidget_class, "<init>", "(J)V")))
+ JNI_ABORT_STDERR("");
+
+ //PhidgetException
+ if (!(ph_exception_class = (*env)->FindClass(env, "com/phidgets/PhidgetException")))
+ JNI_ABORT_STDERR("Coulnd't FindClass com/phidgets/PhidgetException");
+ if (!(ph_exception_class = (jclass)(*env)->NewGlobalRef(env, ph_exception_class)))
+ JNI_ABORT_STDERR("Couldn't create global ref ph_exception_class");
+ if (!(ph_exception_cons = (*env)->GetMethodID(env, ph_exception_class, "<init>", "(ILjava/lang/String;)V")))
+ JNI_ABORT_STDERR("Couldn't get Method ID <init> from ph_exception_class");
+
+ //AttachEvent
+ if (!(attachEvent_class = (*env)->FindClass(env, "com/phidgets/event/AttachEvent")))
+ JNI_ABORT_STDERR("Coulnd't FindClass com/phidgets/AttachEvent");
+ if (!(attachEvent_class = (jclass)(*env)->NewGlobalRef(env, attachEvent_class)))
+ JNI_ABORT_STDERR("Couldn't create global ref attachEvent_class");
+ if (!(attachEvent_cons = (*env)->GetMethodID(env, attachEvent_class, "<init>", "(Lcom/phidgets/Phidget;)V")))
+ JNI_ABORT_STDERR("Couldn't get method ID <init> from attachEvent_class");
+
+ //DetachEvent
+ if (!(detachEvent_class = (*env)->FindClass(env, "com/phidgets/event/DetachEvent")))
+ JNI_ABORT_STDERR("Coulnd't FindClass com/phidgets/DetachEvent");
+ if (!(detachEvent_class = (jclass)(*env)->NewGlobalRef(env, detachEvent_class)))
+ JNI_ABORT_STDERR("Couldn't create global ref detachEvent_class");
+ if (!(detachEvent_cons = (*env)->GetMethodID(env, detachEvent_class, "<init>", "(Lcom/phidgets/Phidget;)V")))
+ JNI_ABORT_STDERR("Couldn't get method ID <init> from detachEvent_class");
+
+ //ErrorEvent
+ if (!(errorEvent_class = (*env)->FindClass(env, "com/phidgets/event/ErrorEvent")))
+ JNI_ABORT_STDERR("Coulnd't FindClass com/phidgets/ErrorEvent");
+ if (!(errorEvent_class = (jclass)(*env)->NewGlobalRef(env, errorEvent_class)))
+ JNI_ABORT_STDERR("Couldn't create global ref errorEvent_class");
+ if (!(errorEvent_cons = (*env)->GetMethodID(env, errorEvent_class, "<init>", "(Lcom/phidgets/Phidget;Lcom/phidgets/PhidgetException;)V")))
+ JNI_ABORT_STDERR("Couldn't get method ID <init> from errorEvent_class");
+
+ //ServerConnectEvent
+ if (!(serverConnectEvent_class = (*env)->FindClass(env, "com/phidgets/event/ServerConnectEvent")))
+ JNI_ABORT_STDERR("Couldn't FindClass com/phidgets/ServerConnectEvent");
+ if (!(serverConnectEvent_class = (jclass)(*env)->NewGlobalRef(env, serverConnectEvent_class)))
+ JNI_ABORT_STDERR("Couldn't create global ref serverConnectEvent_class");
+ if (!(serverConnectEvent_cons = (*env)->GetMethodID(env, serverConnectEvent_class, "<init>", "(Ljava/lang/Object;)V")))
+ JNI_ABORT_STDERR("Couldn't get method ID <init> from serverConnectEvent_class");
+
+ //ServerDisconnectEvent
+ if (!(serverDisconnectEvent_class = (*env)->FindClass(env, "com/phidgets/event/ServerDisconnectEvent")))
+ JNI_ABORT_STDERR("Couldn't FindClass com/phidgets/ServerDisconnectEvent");
+ if (!(serverDisconnectEvent_class = (jclass)(*env)->NewGlobalRef(env, serverDisconnectEvent_class)))
+ JNI_ABORT_STDERR("Couldn't create global ref serverDisconnectEvent_class");
+ if (!(serverDisconnectEvent_cons = (*env)->GetMethodID(env, serverDisconnectEvent_class, "<init>", "(Ljava/lang/Object;)V")))
+ JNI_ABORT_STDERR("Couldn't get method ID <init> from serverDisconnectEvent_class");
+
+ com_phidgets_Phidget_OnLoad(env);
+ com_phidgets_Manager_OnLoad(env);
+ com_phidgets_Dictionary_OnLoad(env);
+ com_phidgets_DictionaryKeyListener_OnLoad(env);
+ com_phidgets_AccelerometerPhidget_OnLoad(env);
+ com_phidgets_AdvancedServoPhidget_OnLoad(env);
+ com_phidgets_AnalogPhidget_OnLoad(env);
+ com_phidgets_BridgePhidget_OnLoad(env);
+ com_phidgets_EncoderPhidget_OnLoad(env);
+ com_phidgets_FrequencyCounterPhidget_OnLoad(env);
+ com_phidgets_GPSPhidget_OnLoad(env);
+ com_phidgets_InterfaceKitPhidget_OnLoad(env);
+ com_phidgets_IRPhidget_OnLoad(env);
+ com_phidgets_LEDPhidget_OnLoad(env);
+ com_phidgets_MotorControlPhidget_OnLoad(env);
+ com_phidgets_PHSensorPhidget_OnLoad(env);
+ com_phidgets_RFIDPhidget_OnLoad(env);
+ com_phidgets_ServoPhidget_OnLoad(env);
+ com_phidgets_SpatialPhidget_OnLoad(env);
+ com_phidgets_StepperPhidget_OnLoad(env);
+ com_phidgets_TemperatureSensorPhidget_OnLoad(env);
+ com_phidgets_TextLCDPhidget_OnLoad(env);
+ com_phidgets_TextLEDPhidget_OnLoad(env);
+ com_phidgets_WeightSensorPhidget_OnLoad(env);
+
+#ifdef _ANDROID
+ if(com_phidgets_usb_Phidget_OnLoad(env) && com_phidgets_usb_Manager_OnLoad(env))
+ AndroidUsbJarAvailable = PTRUE;
+ else
+ AndroidUsbJarAvailable = PFALSE;
+#endif
+
+ return JNI_VERSION_1_4;
+}
+
+jlong
+updateGlobalRef(JNIEnv *env, jobject obj, jfieldID fid, jboolean b)
+{
+ /*
+ * Manages the global reference held by phidget21 to the handler
+ * target.
+ */
+ jlong gr;
+
+ if ((gr = (*env)->GetLongField(env, obj, fid)) != 0)
+ (*env)->DeleteGlobalRef(env, (jobject)(uintptr_t)gr);
+ gr = b ? (jlong)(uintptr_t)(*env)->NewGlobalRef(env, obj) : 0;
+ (*env)->SetLongField(env, obj, fid, gr);
+
+ return gr;
+}
diff --git a/Java/phidget_jni.h b/Java/phidget_jni.h
new file mode 100644
index 0000000..2325fd0
--- /dev/null
+++ b/Java/phidget_jni.h
@@ -0,0 +1,322 @@
+#ifndef PHIDGET_JNI_H
+#define PHIDGET_JNI_H
+
+#include <jni.h>
+
+#ifdef _ANDROID
+#define JNIEnvPtr const struct JNINativeInterface ***
+#else
+#define JNIEnvPtr void **
+#endif
+
+extern JavaVM *ph_vm;
+
+extern jclass phidget_class;
+extern jmethodID phidget_cons;
+
+extern jclass ph_exception_class;
+extern jmethodID ph_exception_cons;
+
+extern jclass attachEvent_class;
+extern jmethodID attachEvent_cons;
+
+extern jclass detachEvent_class;
+extern jmethodID detachEvent_cons;
+
+extern jclass errorEvent_class;
+extern jmethodID errorEvent_cons;
+
+extern jclass serverConnectEvent_class;
+extern jmethodID serverConnectEvent_cons;
+
+extern jclass serverDisconnectEvent_class;
+extern jmethodID serverDisconnectEvent_cons;
+
+void com_phidgets_Phidget_OnLoad(JNIEnv *);
+void com_phidgets_AccelerometerPhidget_OnLoad(JNIEnv *);
+void com_phidgets_AdvancedServoPhidget_OnLoad(JNIEnv *);
+void com_phidgets_AnalogPhidget_OnLoad(JNIEnv *);
+void com_phidgets_BridgePhidget_OnLoad(JNIEnv *);
+void com_phidgets_EncoderPhidget_OnLoad(JNIEnv *);
+void com_phidgets_FrequencyCounterPhidget_OnLoad(JNIEnv *);
+void com_phidgets_GPSPhidget_OnLoad(JNIEnv *);
+void com_phidgets_InterfaceKitPhidget_OnLoad(JNIEnv *);
+void com_phidgets_IRPhidget_OnLoad(JNIEnv *);
+void com_phidgets_LEDPhidget_OnLoad(JNIEnv *);
+void com_phidgets_MotorControlPhidget_OnLoad(JNIEnv *);
+void com_phidgets_PHSensorPhidget_OnLoad(JNIEnv *);
+void com_phidgets_RFIDPhidget_OnLoad(JNIEnv *);
+void com_phidgets_ServoPhidget_OnLoad(JNIEnv *);
+void com_phidgets_SpatialPhidget_OnLoad(JNIEnv *);
+void com_phidgets_StepperPhidget_OnLoad(JNIEnv *);
+void com_phidgets_TemperatureSensorPhidget_OnLoad(JNIEnv *);
+void com_phidgets_TextLCDPhidget_OnLoad(JNIEnv *);
+void com_phidgets_TextLEDPhidget_OnLoad(JNIEnv *);
+void com_phidgets_WeightSensorPhidget_OnLoad(JNIEnv *);
+void com_phidgets_Manager_OnLoad(JNIEnv *);
+void com_phidgets_Dictionary_OnLoad(JNIEnv *);
+void com_phidgets_DictionaryKeyListener_OnLoad(JNIEnv *);
+
+#ifdef _ANDROID
+extern int AndroidUsbJarAvailable;
+int com_phidgets_usb_Manager_OnLoad(JNIEnv *);
+int com_phidgets_usb_Phidget_OnLoad(JNIEnv *);
+#endif
+
+jlong updateGlobalRef(JNIEnv *env, jobject obj, jfieldID fid, jboolean b);
+
+#define JNI_ABORT_STDERR(...) \
+do { \
+ LOG_STDERR(PHIDGET_LOG_CRITICAL, __VA_ARGS__); \
+ (*env)->ExceptionDescribe(env); \
+ (*env)->ExceptionClear(env); \
+ abort(); \
+} while(0)
+
+#define EVENT_VARS(event, Event) static jmethodID event##Event_cons; \
+static jmethodID fire##Event##_mid; \
+static jclass event##Event_class; \
+static jfieldID native##Event##Handler_fid;
+
+#define JNI_LOAD(name, Pname) \
+extern jfieldID handle_fid; \
+static jclass name##_class; \
+void com_phidgets_##Pname##Phidget_OnLoad(JNIEnv *env) \
+{ \
+ if (!(name##_class = (*env)->FindClass(env, "com/phidgets/" #Pname "Phidget"))) \
+ JNI_ABORT_STDERR("Couldn't FindClass com/phidgets/" #Pname "Phidget"); \
+ if (!(name##_class = (jclass)(*env)->NewGlobalRef(env, name##_class))) \
+ JNI_ABORT_STDERR("Couldn't create NewGlobalRef " #name "_class"); \
+
+#define EVENT_VAR_SETUP(name, event, Event, parameters, returntype) \
+ if (!(event##Event_class = (*env)->FindClass(env, "com/phidgets/event/" #Event "Event"))) \
+ JNI_ABORT_STDERR("Couldn't FindClass com/phidgets/event/" #Event "Event"); \
+ if (!(event##Event_class = (jclass)(*env)->NewGlobalRef(env, event##Event_class))) \
+ JNI_ABORT_STDERR("Couldn't create global ref " #event "Event_class"); \
+ if (!(fire##Event##_mid = (*env)->GetMethodID(env, name##_class, "fire" #Event , "(Lcom/phidgets/event/" #Event "Event;)" #returntype ))) \
+ JNI_ABORT_STDERR("Please install the latest Phidget Library. Couldn't get method ID fire" #Event); \
+ if (!(event##Event_cons = (*env)->GetMethodID(env, event##Event_class, "<init>", "(Lcom/phidgets/Phidget;" #parameters ")" #returntype ))) \
+ JNI_ABORT_STDERR("Couldn't get method ID <init> from " #event "Event_class"); \
+ if (!(native##Event##Handler_fid = (*env)->GetFieldID(env, name##_class, "native" #Event "Handler", "J"))) \
+ JNI_ABORT_STDERR("Couldn't get Field ID native" #Event "Handler from " #name "_class");
+
+#define PH_THROW(errno) { \
+ jobject eobj; \
+ jstring edesc; \
+ \
+ if (!(edesc = (*env)->NewStringUTF(env, CPhidget_strerror(errno)))) \
+ JNI_ABORT_STDERR("Couldn't get NewStringUTF"); \
+ if (!(eobj = (*env)->NewObject(env, ph_exception_class, ph_exception_cons, errno, edesc))) \
+ JNI_ABORT_STDERR("Couldn't get NewObject ph_exception_class"); \
+ (*env)->Throw(env, (jthrowable)eobj); \
+}
+
+#define JNI_INDEXED_SETFUNC(pname, fname, lfname, type) \
+JNIEXPORT void JNICALL Java_com_phidgets_##pname##Phidget_set##fname(JNIEnv *env, jobject obj, jint index, type v) \
+{ \
+ CPhidget##pname##Handle h = (CPhidget##pname##Handle)(uintptr_t)(*env)->GetLongField(env, obj, handle_fid); \
+ int error; \
+ if ((error = CPhidget##pname##_set##lfname(h, index, v))) \
+ PH_THROW(error); \
+}
+
+#define JNI_SETFUNC(pname, fname, lfname, type) \
+JNIEXPORT void JNICALL Java_com_phidgets_##pname##Phidget_set##fname(JNIEnv *env, jobject obj, type v) \
+{ \
+ CPhidget##pname##Handle h = (CPhidget##pname##Handle)(uintptr_t) \
+ (*env)->GetLongField(env, obj, handle_fid); \
+ int error; \
+ if ((error = CPhidget##pname##_set##lfname(h, v))) \
+ PH_THROW(error); \
+}
+
+#define JNI_INDEXED_GETFUNC(pname, fname, lfname, type) \
+JNIEXPORT type JNICALL Java_com_phidgets_##pname##Phidget_get##fname(JNIEnv *env, jobject obj, jint index) \
+{ \
+ CPhidget##pname##Handle h = (CPhidget##pname##Handle)(uintptr_t) \
+ (*env)->GetLongField(env, obj, handle_fid); \
+ int error; \
+ type v; \
+ if ((error = CPhidget##pname##_get##lfname(h, index, &v))) \
+ PH_THROW(error); \
+ return v; \
+}
+
+#define JNI_INDEXED_GETFUNCBOOL(pname, fname, lfname) \
+JNIEXPORT jboolean JNICALL Java_com_phidgets_##pname##Phidget_get##fname(JNIEnv *env, jobject obj, jint index) \
+{ \
+ CPhidget##pname##Handle h = (CPhidget##pname##Handle)(uintptr_t) \
+ (*env)->GetLongField(env, obj, handle_fid); \
+ int error; \
+ int v; \
+ if ((error = CPhidget##pname##_get##lfname(h, index, &v))) \
+ PH_THROW(error); \
+ if (v) return 1; \
+ return 0; \
+}
+
+#define JNI_GETFUNC(pname, fname, lfname, type) \
+JNIEXPORT type JNICALL Java_com_phidgets_##pname##Phidget_get##fname (JNIEnv *env, jobject obj) \
+{ \
+ CPhidget##pname##Handle h = (CPhidget##pname##Handle)(uintptr_t) \
+ (*env)->GetLongField( env, obj, handle_fid); \
+ int error; \
+ type no; \
+ if ((error = CPhidget##pname##_get##lfname(h, &no))) \
+ PH_THROW(error); \
+ return no; \
+}
+
+#define JNI_GETFUNCBOOL(pname, fname, lfname) \
+JNIEXPORT jboolean JNICALL Java_com_phidgets_##pname##Phidget_get##fname (JNIEnv *env, jobject obj) \
+{ \
+ CPhidget##pname##Handle h = (CPhidget##pname##Handle)(uintptr_t) \
+ (*env)->GetLongField( env, obj, handle_fid); \
+ int error; \
+ int no; \
+ if ((error = CPhidget##pname##_get##lfname(h, &no))) \
+ PH_THROW(error); \
+ if(no) return 1; \
+ return 0; \
+}
+
+#define JNI_CREATE(Pname) \
+JNIEXPORT jlong JNICALL Java_com_phidgets_##Pname##Phidget_create(JNIEnv *env, jclass cls) \
+{ \
+ CPhidget##Pname##Handle phid; \
+ int error; \
+ if ((error = CPhidget##Pname##_create(&phid)) != EPHIDGET_OK) { \
+ PH_THROW(error); \
+ return 0; \
+ } \
+ return (jlong)(uintptr_t)phid; \
+}
+
+#define EVENT_HANDLER(pname, event, Event, cphidgetSetHandlerFunc, type) \
+static int CCONV event##_handler(CPhidget##pname##Handle h, void *arg, type); \
+JNIEXPORT void JNICALL Java_com_phidgets_##pname##Phidget_enable##Event##Events(JNIEnv *env, jobject obj, jboolean b) \
+{ \
+ jlong gr = updateGlobalRef(env, obj, native##Event##Handler_fid, b); \
+ CPhidget##pname##Handle h = (CPhidget##pname##Handle)(uintptr_t) \
+ (*env)->GetLongField(env, obj, handle_fid); \
+ cphidgetSetHandlerFunc(h, b ? event##_handler : 0, \
+ (void *)(uintptr_t)gr); \
+} \
+\
+static int CCONV event##_handler(CPhidget##pname##Handle h, void *arg, type v) \
+{ \
+ JNIEnv *env; \
+ jobject obj; \
+ jobject event##Ev; \
+\
+ if ((*ph_vm)->AttachCurrentThread(ph_vm, (JNIEnvPtr)&env, NULL)) \
+ JNI_ABORT_STDERR("Couldn't AttachCurrentThread"); \
+\
+ obj = (jobject)arg; \
+\
+ if (!(event##Ev = (*env)->NewObject(env, event##Event_class, event##Event_cons, obj, v))) \
+ return -1; \
+ (*env)->CallVoidMethod(env, obj, fire##Event##_mid, event##Ev); \
+ (*env)->DeleteLocalRef(env, event##Ev); \
+ (*ph_vm)->DetachCurrentThread(ph_vm); \
+\
+ return 0; \
+}
+
+#define EVENT_HANDLER_INDEXED(pname, event, Event, cphidgetSetHandlerFunc, type) \
+static int CCONV event##_handler(CPhidget##pname##Handle h, void *arg, int, type); \
+JNIEXPORT void JNICALL Java_com_phidgets_##pname##Phidget_enable##Event##Events(JNIEnv *env, jobject obj, jboolean b) \
+{ \
+ jlong gr = updateGlobalRef(env, obj, native##Event##Handler_fid, b); \
+ CPhidget##pname##Handle h = (CPhidget##pname##Handle)(uintptr_t) \
+ (*env)->GetLongField(env, obj, handle_fid); \
+ cphidgetSetHandlerFunc(h, b ? event##_handler : 0, \
+ (void *)(uintptr_t)gr); \
+} \
+\
+static int CCONV event##_handler(CPhidget##pname##Handle h, void *arg, int index, type v) \
+{ \
+ JNIEnv *env; \
+ jobject obj; \
+ jobject event##Ev; \
+\
+ if ((*ph_vm)->AttachCurrentThread(ph_vm, (JNIEnvPtr)&env, NULL)) \
+ JNI_ABORT_STDERR("Couldn't AttachCurrentThread"); \
+\
+ obj = (jobject)arg; \
+\
+ if (!(event##Ev = (*env)->NewObject(env, event##Event_class, event##Event_cons, obj, index, v))) \
+ return -1; \
+ (*env)->CallVoidMethod(env, obj, fire##Event##_mid, event##Ev); \
+ (*env)->DeleteLocalRef(env, event##Ev); \
+ (*ph_vm)->DetachCurrentThread(ph_vm); \
+\
+ return 0; \
+}
+
+#define EVENT_HANDLER_INDEXED2(pname, event, Event, cphidgetSetHandlerFunc, type, type2) \
+static int CCONV event##_handler(CPhidget##pname##Handle h, void *arg, int, type, type2); \
+JNIEXPORT void JNICALL Java_com_phidgets_##pname##Phidget_enable##Event##Events(JNIEnv *env, jobject obj, jboolean b) \
+{ \
+ jlong gr = updateGlobalRef(env, obj, native##Event##Handler_fid, b); \
+ CPhidget##pname##Handle h = (CPhidget##pname##Handle)(uintptr_t) \
+ (*env)->GetLongField(env, obj, handle_fid); \
+ cphidgetSetHandlerFunc(h, b ? event##_handler : 0, \
+ (void *)(uintptr_t)gr); \
+} \
+\
+static int CCONV event##_handler(CPhidget##pname##Handle h, void *arg, int index, type v, type2 w) \
+{ \
+ JNIEnv *env; \
+ jobject obj; \
+ jobject event##Ev; \
+\
+ if ((*ph_vm)->AttachCurrentThread(ph_vm, (JNIEnvPtr)&env, NULL)) \
+ JNI_ABORT_STDERR("Couldn't AttachCurrentThread"); \
+\
+ obj = (jobject)arg; \
+\
+ if (!(event##Ev = (*env)->NewObject(env, event##Event_class, \
+ event##Event_cons, obj, index, v, w))) \
+ return -1; \
+ (*env)->CallVoidMethod(env, obj, fire##Event##_mid, event##Ev); \
+ (*env)->DeleteLocalRef(env, event##Ev); \
+ (*ph_vm)->DetachCurrentThread(ph_vm); \
+\
+ return 0; \
+}
+
+#define EVENT_HANDLER_3(pname, event, Event, cphidgetSetHandlerFunc, type, type2, type3) \
+static int CCONV event##_handler(CPhidget##pname##Handle h, void *arg, type, type2, type3); \
+JNIEXPORT void JNICALL Java_com_phidgets_##pname##Phidget_enable##Event##Events(JNIEnv *env, jobject obj, jboolean b) \
+{ \
+ jlong gr = updateGlobalRef(env, obj, native##Event##Handler_fid, b); \
+ CPhidget##pname##Handle h = (CPhidget##pname##Handle)(uintptr_t) \
+ (*env)->GetLongField(env, obj, handle_fid); \
+ cphidgetSetHandlerFunc(h, b ? event##_handler : 0, \
+ (void *)(uintptr_t)gr); \
+} \
+\
+static int CCONV event##_handler(CPhidget##pname##Handle h, void *arg, type v, type2 w, type3 x) \
+{ \
+ JNIEnv *env; \
+ jobject obj; \
+ jobject event##Ev; \
+\
+ if ((*ph_vm)->AttachCurrentThread(ph_vm, (JNIEnvPtr)&env, NULL)) \
+ JNI_ABORT_STDERR("Couldn't AttachCurrentThread"); \
+\
+ obj = (jobject)arg; \
+\
+ if (!(event##Ev = (*env)->NewObject(env, event##Event_class, \
+ event##Event_cons, obj, v, w, x))) \
+ return -1; \
+ (*env)->CallVoidMethod(env, obj, fire##Event##_mid, event##Ev); \
+ (*env)->DeleteLocalRef(env, event##Ev); \
+ (*ph_vm)->DetachCurrentThread(ph_vm); \
+\
+ return 0; \
+}
+
+
+#endif
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..793dbd8
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,376 @@
+## Process this file with automake to produce Makefile.in
+
+AM_CFLAGS = -I$(top_srcdir) -I$(top_srcdir)/utils -I$(top_srcdir)/dict -I$(top_srcdir)/linux -I$(top_srcdir)/include -D_LINUX
+
+lib_LTLIBRARIES = libphidget21.la
+
+# Rules for unpdating the libtool version:
+# 1. Programs using the previous version may use the new version as drop-in replacement,
+# and programs using the new version can also work with the previous one. In other words,
+# no recompiling nor relinking is needed. In this case, bump revision only, don't touch current nor age.
+# 2. Programs using the previous version may use the new version as drop-in replacement,
+# but programs using the new version may use APIs not present in the previous one. In other words,
+# a program linking against the new version may fail with “unresolved symbolsâ€
+# if linking against the old version at runtime: set revision to 0, bump current and age.
+# 3. Programs may need to be changed, recompiled, relinked in order to use the new version.
+# Bump current, set revision and age to 0.
+libphidget21_la_LDFLAGS = -version-info 0:0:0
+
+libphidget21_la_SOURCES = cphidget.c \
+ cphidget.h \
+ cphidgetmacros.h \
+ cphidgetattr.h \
+ cusb.h \
+ stdafx.h \
+ cphidgetconstantsinternal.h \
+ cphidgetaccelerometer.c \
+ cphidgetaccelerometer.h \
+ cphidgetadvancedservo.c \
+ cphidgetadvancedservo.h \
+ cphidgetanalog.c \
+ cphidgetanalog.h \
+ cphidgetbridge.c \
+ cphidgetbridge.h \
+ cphidgetencoder.c \
+ cphidgetencoder.h \
+ cphidgetfrequencycounter.c \
+ cphidgetfrequencycounter.h \
+ cphidgetgps.c \
+ cphidgetgps.h \
+ cphidgetinterfacekit.c \
+ cphidgetinterfacekit.h \
+ cphidgetir.c \
+ cphidgetir.h \
+ cphidgetled.c \
+ cphidgetled.h \
+ cphidgetmotorcontrol.c \
+ cphidgetmotorcontrol.h \
+ cphidgetphsensor.c \
+ cphidgetphsensor.h \
+ cphidgetrfid.c \
+ cphidgetrfid.h \
+ cphidgetservo.c \
+ cphidgetservo.h \
+ cphidgetspatial.c \
+ cphidgetspatial.h \
+ cphidgetstepper.c \
+ cphidgetstepper.h \
+ cphidgettemperaturesensor.c \
+ cphidgettemperaturesensor.h \
+ cphidgettextlcd.c \
+ cphidgettextlcd.h \
+ cphidgettextled.c \
+ cphidgettextled.h \
+ cphidgetweightsensor.c \
+ cphidgetweightsensor.h \
+ cphidgetmanager.c \
+ cphidgetmanager.h \
+ cphidgetdictionary.c \
+ cphidgetdictionary.h \
+ cphidgetgeneric.c \
+ cphidgetgeneric.h \
+ cphidgetsbc.c \
+ cphidgetsbc.h \
+ clog.c \
+ clog.h \
+ csocketevents.c \
+ csocketevents.h \
+ csocketopen.c \
+ csocket.h \
+ cphidgetconstants.c \
+ cphidgetconstants.h \
+ cphidgetlist.c \
+ cphidgetlist.h \
+ cthread.c \
+ cthread.h \
+ phidget21.c \
+ phidget21int.h \
+ linux/cusblinux.c \
+ dict/pdict.c \
+ dict/pdict.h \
+ dict/pdictclient.c \
+ dict/pdictclient.h \
+ dict/pdict-impl.h \
+ utils/md5.c \
+ utils/md5.h \
+ utils/utils.c \
+ utils/utils.h \
+ utils/ptree.c \
+ utils/ptree.h \
+ utils/plist.c \
+ utils/plist.h \
+ cppheader \
+ cppfooter
+
+include_HEADERS = phidget21.h
+
+CLEANFILES = phidget21.h phidget21matlab.h phidget21.jar Java/com/phidgets/*.class Java/com/phidgets/event/*.class
+
+distclean-local:
+ -rm -rf examples/.deps examples/Makefile
+
+EXTRA_DIST = examples/ifkit.c \
+ examples/Makefile.am \
+ examples/Makefile.in \
+ examples/manager.c \
+ examples/phidgetsbclist.c \
+ examples/README \
+ udev/99-phidgets.rules \
+ hotplug/phidgets.usermap \
+ hotplug/phidgets \
+ version.sh \
+ Java/com/phidgets/DictionaryKeyListener.java \
+ Java/com/phidgets/TextLCDPhidget.java \
+ Java/com/phidgets/SpatialEventData.java \
+ Java/com/phidgets/StepperPhidget.java \
+ Java/com/phidgets/ServoPhidget.java \
+ Java/com/phidgets/PHSensorPhidget.java \
+ Java/com/phidgets/AccelerometerPhidget.java \
+ Java/com/phidgets/SpatialPhidget.java \
+ Java/com/phidgets/AdvancedServoPhidget.java \
+ Java/com/phidgets/EncoderPhidget.java \
+ Java/com/phidgets/MotorControlPhidget.java \
+ Java/com/phidgets/IRLearnedCode.java \
+ Java/com/phidgets/IRCodeInfo.java \
+ Java/com/phidgets/InterfaceKitPhidget.java \
+ Java/com/phidgets/TemperatureSensorPhidget.java \
+ Java/com/phidgets/WeightSensorPhidget.java \
+ Java/com/phidgets/TextLEDPhidget.java \
+ Java/com/phidgets/IRCode.java \
+ Java/com/phidgets/Manager.java \
+ Java/com/phidgets/PhidgetException.java \
+ Java/com/phidgets/IRPhidget.java \
+ Java/com/phidgets/RFIDPhidget.java \
+ Java/com/phidgets/LEDPhidget.java \
+ Java/com/phidgets/Dictionary.java \
+ Java/com/phidgets/event/ServoPositionChangeListener.java \
+ Java/com/phidgets/event/AccelerationChangeEvent.java \
+ Java/com/phidgets/event/AttachListener.java \
+ Java/com/phidgets/event/StepperVelocityChangeEvent.java \
+ Java/com/phidgets/event/CodeEvent.java \
+ Java/com/phidgets/event/ErrorEvent.java \
+ Java/com/phidgets/event/TemperatureChangeEvent.java \
+ Java/com/phidgets/event/DetachListener.java \
+ Java/com/phidgets/event/LearnListener.java \
+ Java/com/phidgets/event/ServoVelocityChangeEvent.java \
+ Java/com/phidgets/event/PHChangeListener.java \
+ Java/com/phidgets/event/RawDataListener.java \
+ Java/com/phidgets/event/CurrentChangeListener.java \
+ Java/com/phidgets/event/TagGainEvent.java \
+ Java/com/phidgets/event/StepperPositionChangeEvent.java \
+ Java/com/phidgets/event/WeightChangeListener.java \
+ Java/com/phidgets/event/InputChangeEvent.java \
+ Java/com/phidgets/event/TagLossListener.java \
+ Java/com/phidgets/event/ServerDisconnectEvent.java \
+ Java/com/phidgets/event/TemperatureChangeListener.java \
+ Java/com/phidgets/event/SpatialDataListener.java \
+ Java/com/phidgets/event/SensorChangeEvent.java \
+ Java/com/phidgets/event/CodeListener.java \
+ Java/com/phidgets/event/ServerConnectEvent.java \
+ Java/com/phidgets/event/StepperPositionChangeListener.java \
+ Java/com/phidgets/event/SpatialDataEvent.java \
+ Java/com/phidgets/event/AttachEvent.java \
+ Java/com/phidgets/event/EncoderPositionChangeListener.java \
+ Java/com/phidgets/event/EncoderPositionChangeEvent.java \
+ Java/com/phidgets/event/DetachEvent.java \
+ Java/com/phidgets/event/OutputChangeListener.java \
+ Java/com/phidgets/event/TagGainListener.java \
+ Java/com/phidgets/event/KeyRemovalListener.java \
+ Java/com/phidgets/event/KeyChangeEvent.java \
+ Java/com/phidgets/event/KeyRemovalEvent.java \
+ Java/com/phidgets/event/OutputChangeEvent.java \
+ Java/com/phidgets/event/StepperVelocityChangeListener.java \
+ Java/com/phidgets/event/ServerDisconnectListener.java \
+ Java/com/phidgets/event/ErrorListener.java \
+ Java/com/phidgets/event/SensorChangeListener.java \
+ Java/com/phidgets/event/PHChangeEvent.java \
+ Java/com/phidgets/event/LearnEvent.java \
+ Java/com/phidgets/event/WeightChangeEvent.java \
+ Java/com/phidgets/event/MotorVelocityChangeListener.java \
+ Java/com/phidgets/event/TagLossEvent.java \
+ Java/com/phidgets/event/KeyChangeListener.java \
+ Java/com/phidgets/event/ServerConnectListener.java \
+ Java/com/phidgets/event/AccelerationChangeListener.java \
+ Java/com/phidgets/event/RawDataEvent.java \
+ Java/com/phidgets/event/InputChangeListener.java \
+ Java/com/phidgets/event/ServoPositionChangeEvent.java \
+ Java/com/phidgets/event/CurrentChangeEvent.java \
+ Java/com/phidgets/event/ServoVelocityChangeListener.java \
+ Java/com/phidgets/event/MotorVelocityChangeEvent.java \
+ Java/com/phidgets/event/CurrentUpdateEvent.java \
+ Java/com/phidgets/event/CurrentUpdateListener.java \
+ Java/com/phidgets/event/BackEMFUpdateEvent.java \
+ Java/com/phidgets/event/BackEMFUpdateListener.java \
+ Java/com/phidgets/event/EncoderPositionUpdateEvent.java \
+ Java/com/phidgets/event/EncoderPositionUpdateListener.java \
+ Java/com/phidgets/event/SensorUpdateEvent.java \
+ Java/com/phidgets/event/SensorUpdateListener.java \
+ Java/com/phidgets/AnalogPhidget.java \
+ Java/com/phidgets/FrequencyCounterPhidget.java \
+ Java/com/phidgets/event/GPSPositionFixStatusChangeEvent.java \
+ Java/com/phidgets/event/GPSPositionFixStatusChangeListener.java \
+ Java/com/phidgets/event/FrequencyCounterCountListener.java \
+ Java/com/phidgets/event/GPSPositionChangeEvent.java \
+ Java/com/phidgets/event/GPSPositionChangeListener.java \
+ Java/com/phidgets/event/FrequencyCounterCountEvent.java \
+ Java/com/phidgets/GPSPhidget.java \
+ Java/com/phidgets/BridgePhidget.java \
+ Java/com/phidgets/event/BridgeDataEvent.java \
+ Java/com/phidgets/event/BridgeDataListener.java \
+ Java/com/phidgets/macros/BridgePhidget.jm \
+ Java/com/phidgets/Phidget.java
+
+if ZEROCONF
+libphidget21_la_SOURCES += zeroconf.h
+else
+AM_CFLAGS += -DNO_ZEROCONF
+endif
+
+if INTERNAL_UNICONV
+libphidget21_la_SOURCES += utils/cvtutf.c
+libphidget21_la_SOURCES += utils/cvtutf.h
+AM_CFLAGS += -DUSE_INTERNAL_UNICONV
+endif
+
+if ZEROCONF_AVAHI
+libphidget21_la_SOURCES += linux/zeroconf_avahi.c \
+ linux/avahi-client/client.h \
+ linux/avahi-client/lookup.h \
+ linux/avahi-client/publish.h \
+ linux/avahi-common/address.h \
+ linux/avahi-common/alternative.h \
+ linux/avahi-common/cdecl.h \
+ linux/avahi-common/defs.h \
+ linux/avahi-common/domain.h \
+ linux/avahi-common/error.h \
+ linux/avahi-common/gccmacro.h \
+ linux/avahi-common/llist.h \
+ linux/avahi-common/malloc.h \
+ linux/avahi-common/rlist.h \
+ linux/avahi-common/simple-watch.h \
+ linux/avahi-common/strlst.h \
+ linux/avahi-common/thread-watch.h \
+ linux/avahi-common/timeval.h \
+ linux/avahi-common/watch.h
+endif
+
+if ZEROCONF_BONJOUR
+libphidget21_la_SOURCES += zeroconf.c \
+ include/dns_sd.h
+endif
+
+if ZEROCONF_LOOKUP
+libphidget21_la_SOURCES += zeroconf_lookup.c
+AM_CFLAGS += -DZEROCONF_LOOKUP
+endif
+
+if LABVIEW
+libphidget21_la_SOURCES += labview/phidget_labview.c \
+ labview/phidget_labview.h
+LABVIEW_CINTOOLS_PATH ?= /usr/local/natinst/LabVIEW-8.5/cintools
+AM_CFLAGS += -DCOMPILE_PHIDGETS_LABVIEW -I$(LABVIEW_CINTOOLS_PATH)
+AM_CFLAGS += -L$(LABVIEW_CINTOOLS_PATH) -Wl,-rpath,$(LABVIEW_CINTOOLS_PATH) -llv
+endif
+
+if DEBUG
+AM_CFLAGS += -D_DEBUG -DDEBUG
+endif
+
+if JNI
+AM_CFLAGS += -I$(top_srcdir)/include/jni -I$(top_srcdir)/include/jni/linux
+libphidget21_la_SOURCES += Java/com_phidgets_Phidget.c \
+ Java/com_phidgets_Phidget.h \
+ Java/com_phidgets_AccelerometerPhidget.c \
+ Java/com_phidgets_AccelerometerPhidget.h \
+ Java/com_phidgets_AdvancedServoPhidget.c \
+ Java/com_phidgets_AdvancedServoPhidget.h \
+ Java/com_phidgets_AnalogPhidget.c \
+ Java/com_phidgets_AnalogPhidget.h \
+ Java/com_phidgets_BridgePhidget.c \
+ Java/com_phidgets_BridgePhidget.h \
+ Java/com_phidgets_EncoderPhidget.c \
+ Java/com_phidgets_EncoderPhidget.h \
+ Java/com_phidgets_FrequencyCounterPhidget.c \
+ Java/com_phidgets_FrequencyCounterPhidget.h \
+ Java/com_phidgets_GPSPhidget.c \
+ Java/com_phidgets_GPSPhidget.h \
+ Java/com_phidgets_InterfaceKitPhidget.c \
+ Java/com_phidgets_InterfaceKitPhidget.h \
+ Java/com_phidgets_IRPhidget.c \
+ Java/com_phidgets_IRPhidget.h \
+ Java/com_phidgets_LEDPhidget.c \
+ Java/com_phidgets_LEDPhidget.h \
+ Java/com_phidgets_MotorControlPhidget.c \
+ Java/com_phidgets_MotorControlPhidget.h \
+ Java/com_phidgets_PHSensorPhidget.c \
+ Java/com_phidgets_PHSensorPhidget.h \
+ Java/com_phidgets_RFIDPhidget.c \
+ Java/com_phidgets_RFIDPhidget.h \
+ Java/com_phidgets_ServoPhidget.c \
+ Java/com_phidgets_ServoPhidget.h \
+ Java/com_phidgets_SpatialPhidget.c \
+ Java/com_phidgets_SpatialPhidget.h \
+ Java/com_phidgets_StepperPhidget.c \
+ Java/com_phidgets_StepperPhidget.h \
+ Java/com_phidgets_TemperatureSensorPhidget.c \
+ Java/com_phidgets_TemperatureSensorPhidget.h \
+ Java/com_phidgets_TextLCDPhidget.c \
+ Java/com_phidgets_TextLCDPhidget.h \
+ Java/com_phidgets_TextLEDPhidget.c \
+ Java/com_phidgets_TextLEDPhidget.h \
+ Java/com_phidgets_Manager.c \
+ Java/com_phidgets_Manager.h \
+ Java/com_phidgets_Dictionary.c \
+ Java/com_phidgets_Dictionary.h \
+ Java/com_phidgets_DictionaryKeyListener.c \
+ Java/com_phidgets_DictionaryKeyListener.h \
+ Java/com_phidgets_WeightSensorPhidget.c \
+ Java/com_phidgets_WeightSensorPhidget.h \
+ Java/phidget_jni.c \
+ Java/phidget_jni.h \
+ include/jni/jawt.h \
+ include/jni/jni.h \
+ include/jni/jvmdi.h \
+ include/jni/jvmpi.h \
+ include/jni/linux/jawt_md.h \
+ include/jni/linux/jni_md.h
+endif
+
+if RUN_LDCONFIG
+install-exec-hook:
+ -$(LDCONFIG)
+endif
+
+install-data-hook:
+ if [ -e phidget21.jar ]; then install --owner=root --mode=755 -d $(DESTDIR)/usr/share/java; install --owner=root --mode=644 phidget21.jar $(DESTDIR)/usr/share/java; fi
+
+phidget21.h:
+ @echo "Making $@"
+ @cat cppheader > $@
+ @$(CC) -g -E -P $(PHIDGET21FLAGS) -D_LINUX -DEXTERNALPROTO -DREMOVE_DEPRECATED phidget21int.h | sed -e "s/extern \"C\" //g" >> $@
+ @cat cphidgetconstants.h >> $@
+ @cat cppfooter >> $@
+
+phidget21matlab.h:
+ @echo "Making $@"
+ @echo "/*" > $@
+ @echo " * Phidget21 Header for Matlab" >> $@
+ @echo " * -All pointers to structs have been changed to long, as Matlab seems" >> $@
+ @echo " * to be unhappy with either the undefined stucts or the double pointers." >> $@
+ @echo " */" >> $@
+ @$(CC) -g -E -P -D_LINUX -DEXTERNALPROTO -DREMOVE_DEPRECATED phidget21int.h | sed -e "s/extern \"C\" //g" | sed -e "s/struct [a-zA-Z_]* \*/long /" >> $@
+ @cat cphidgetconstants.h >> $@
+
+phidget21.jar:
+ @echo "Making $@"
+ @cd Java ; javac com/phidgets/*.java com/phidgets/event/*.java
+ @cd Java ; jar cf ../$@ com/phidgets/event/*.class com/phidgets/*.class
+
+deb:
+ @echo "Making Debian Packages"
+ @cp debian/changelog.template debian/changelog
+ @sed -i s/"VERSION"/"$(PACKAGE_VERSION)"/ debian/changelog
+ @sed -i s/"DATE"/"$(shell date +"%a, %d %b %Y %T %z")"/ debian/changelog
+ @if [ -z "$(DPKG_ARCH)" ]; then dpkg-buildpackage -us -uc; else dpkg-buildpackage -us -uc -a$(DPKG_ARCH); fi
+
+jni: all
diff --git a/Makefile.in b/Makefile.in
new file mode 100644
index 0000000..486ed1a
--- /dev/null
+++ b/Makefile.in
@@ -0,0 +1,1475 @@
+# Makefile.in generated by automake 1.11 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+@ZEROCONF_TRUE@am__append_1 = zeroconf.h
+@ZEROCONF_FALSE@am__append_2 = -DNO_ZEROCONF
+@INTERNAL_UNICONV_TRUE@am__append_3 = utils/cvtutf.c utils/cvtutf.h
+@INTERNAL_UNICONV_TRUE@am__append_4 = -DUSE_INTERNAL_UNICONV
+@ZEROCONF_AVAHI_TRUE@am__append_5 = linux/zeroconf_avahi.c \
+@ZEROCONF_AVAHI_TRUE@ linux/avahi-client/client.h \
+@ZEROCONF_AVAHI_TRUE@ linux/avahi-client/lookup.h \
+@ZEROCONF_AVAHI_TRUE@ linux/avahi-client/publish.h \
+@ZEROCONF_AVAHI_TRUE@ linux/avahi-common/address.h \
+@ZEROCONF_AVAHI_TRUE@ linux/avahi-common/alternative.h \
+@ZEROCONF_AVAHI_TRUE@ linux/avahi-common/cdecl.h \
+@ZEROCONF_AVAHI_TRUE@ linux/avahi-common/defs.h \
+@ZEROCONF_AVAHI_TRUE@ linux/avahi-common/domain.h \
+@ZEROCONF_AVAHI_TRUE@ linux/avahi-common/error.h \
+@ZEROCONF_AVAHI_TRUE@ linux/avahi-common/gccmacro.h \
+@ZEROCONF_AVAHI_TRUE@ linux/avahi-common/llist.h \
+@ZEROCONF_AVAHI_TRUE@ linux/avahi-common/malloc.h \
+@ZEROCONF_AVAHI_TRUE@ linux/avahi-common/rlist.h \
+@ZEROCONF_AVAHI_TRUE@ linux/avahi-common/simple-watch.h \
+@ZEROCONF_AVAHI_TRUE@ linux/avahi-common/strlst.h \
+@ZEROCONF_AVAHI_TRUE@ linux/avahi-common/thread-watch.h \
+@ZEROCONF_AVAHI_TRUE@ linux/avahi-common/timeval.h \
+@ZEROCONF_AVAHI_TRUE@ linux/avahi-common/watch.h
+
+@ZEROCONF_BONJOUR_TRUE@am__append_6 = zeroconf.c \
+@ZEROCONF_BONJOUR_TRUE@ include/dns_sd.h
+
+@ZEROCONF_LOOKUP_TRUE@am__append_7 = zeroconf_lookup.c
+@ZEROCONF_LOOKUP_TRUE@am__append_8 = -DZEROCONF_LOOKUP
+@LABVIEW_TRUE@am__append_9 = labview/phidget_labview.c \
+@LABVIEW_TRUE@ labview/phidget_labview.h
+
+@LABVIEW_TRUE@am__append_10 = -DCOMPILE_PHIDGETS_LABVIEW \
+@LABVIEW_TRUE@ -I$(LABVIEW_CINTOOLS_PATH) \
+@LABVIEW_TRUE@ -L$(LABVIEW_CINTOOLS_PATH) \
+@LABVIEW_TRUE@ -Wl,-rpath,$(LABVIEW_CINTOOLS_PATH) -llv
+@DEBUG_TRUE@am__append_11 = -D_DEBUG -DDEBUG
+@JNI_TRUE@am__append_12 = -I$(top_srcdir)/include/jni -I$(top_srcdir)/include/jni/linux
+@JNI_TRUE@am__append_13 = Java/com_phidgets_Phidget.c \
+@JNI_TRUE@ Java/com_phidgets_Phidget.h \
+@JNI_TRUE@ Java/com_phidgets_AccelerometerPhidget.c \
+@JNI_TRUE@ Java/com_phidgets_AccelerometerPhidget.h \
+@JNI_TRUE@ Java/com_phidgets_AdvancedServoPhidget.c \
+@JNI_TRUE@ Java/com_phidgets_AdvancedServoPhidget.h \
+@JNI_TRUE@ Java/com_phidgets_AnalogPhidget.c \
+@JNI_TRUE@ Java/com_phidgets_AnalogPhidget.h \
+@JNI_TRUE@ Java/com_phidgets_BridgePhidget.c \
+@JNI_TRUE@ Java/com_phidgets_BridgePhidget.h \
+@JNI_TRUE@ Java/com_phidgets_EncoderPhidget.c \
+@JNI_TRUE@ Java/com_phidgets_EncoderPhidget.h \
+@JNI_TRUE@ Java/com_phidgets_FrequencyCounterPhidget.c \
+@JNI_TRUE@ Java/com_phidgets_FrequencyCounterPhidget.h \
+@JNI_TRUE@ Java/com_phidgets_GPSPhidget.c \
+@JNI_TRUE@ Java/com_phidgets_GPSPhidget.h \
+@JNI_TRUE@ Java/com_phidgets_InterfaceKitPhidget.c \
+@JNI_TRUE@ Java/com_phidgets_InterfaceKitPhidget.h \
+@JNI_TRUE@ Java/com_phidgets_IRPhidget.c \
+@JNI_TRUE@ Java/com_phidgets_IRPhidget.h \
+@JNI_TRUE@ Java/com_phidgets_LEDPhidget.c \
+@JNI_TRUE@ Java/com_phidgets_LEDPhidget.h \
+@JNI_TRUE@ Java/com_phidgets_MotorControlPhidget.c \
+@JNI_TRUE@ Java/com_phidgets_MotorControlPhidget.h \
+@JNI_TRUE@ Java/com_phidgets_PHSensorPhidget.c \
+@JNI_TRUE@ Java/com_phidgets_PHSensorPhidget.h \
+@JNI_TRUE@ Java/com_phidgets_RFIDPhidget.c \
+@JNI_TRUE@ Java/com_phidgets_RFIDPhidget.h \
+@JNI_TRUE@ Java/com_phidgets_ServoPhidget.c \
+@JNI_TRUE@ Java/com_phidgets_ServoPhidget.h \
+@JNI_TRUE@ Java/com_phidgets_SpatialPhidget.c \
+@JNI_TRUE@ Java/com_phidgets_SpatialPhidget.h \
+@JNI_TRUE@ Java/com_phidgets_StepperPhidget.c \
+@JNI_TRUE@ Java/com_phidgets_StepperPhidget.h \
+@JNI_TRUE@ Java/com_phidgets_TemperatureSensorPhidget.c \
+@JNI_TRUE@ Java/com_phidgets_TemperatureSensorPhidget.h \
+@JNI_TRUE@ Java/com_phidgets_TextLCDPhidget.c \
+@JNI_TRUE@ Java/com_phidgets_TextLCDPhidget.h \
+@JNI_TRUE@ Java/com_phidgets_TextLEDPhidget.c \
+@JNI_TRUE@ Java/com_phidgets_TextLEDPhidget.h \
+@JNI_TRUE@ Java/com_phidgets_Manager.c \
+@JNI_TRUE@ Java/com_phidgets_Manager.h \
+@JNI_TRUE@ Java/com_phidgets_Dictionary.c \
+@JNI_TRUE@ Java/com_phidgets_Dictionary.h \
+@JNI_TRUE@ Java/com_phidgets_DictionaryKeyListener.c \
+@JNI_TRUE@ Java/com_phidgets_DictionaryKeyListener.h \
+@JNI_TRUE@ Java/com_phidgets_WeightSensorPhidget.c \
+@JNI_TRUE@ Java/com_phidgets_WeightSensorPhidget.h \
+@JNI_TRUE@ Java/phidget_jni.c \
+@JNI_TRUE@ Java/phidget_jni.h \
+@JNI_TRUE@ include/jni/jawt.h \
+@JNI_TRUE@ include/jni/jni.h \
+@JNI_TRUE@ include/jni/jvmdi.h \
+@JNI_TRUE@ include/jni/jvmpi.h \
+@JNI_TRUE@ include/jni/linux/jawt_md.h \
+@JNI_TRUE@ include/jni/linux/jni_md.h
+
+subdir = .
+DIST_COMMON = README $(am__configure_deps) $(include_HEADERS) \
+ $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
+ $(top_srcdir)/configure AUTHORS COPYING ChangeLog INSTALL NEWS \
+ config.guess config.sub depcomp install-sh ltmain.sh missing
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
+ configure.lineno config.status.lineno
+mkinstalldirs = $(install_sh) -d
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(includedir)"
+LTLIBRARIES = $(lib_LTLIBRARIES)
+libphidget21_la_LIBADD =
+am__libphidget21_la_SOURCES_DIST = cphidget.c cphidget.h \
+ cphidgetmacros.h cphidgetattr.h cusb.h stdafx.h \
+ cphidgetconstantsinternal.h cphidgetaccelerometer.c \
+ cphidgetaccelerometer.h cphidgetadvancedservo.c \
+ cphidgetadvancedservo.h cphidgetanalog.c cphidgetanalog.h \
+ cphidgetbridge.c cphidgetbridge.h cphidgetencoder.c \
+ cphidgetencoder.h cphidgetfrequencycounter.c \
+ cphidgetfrequencycounter.h cphidgetgps.c cphidgetgps.h \
+ cphidgetinterfacekit.c cphidgetinterfacekit.h cphidgetir.c \
+ cphidgetir.h cphidgetled.c cphidgetled.h \
+ cphidgetmotorcontrol.c cphidgetmotorcontrol.h \
+ cphidgetphsensor.c cphidgetphsensor.h cphidgetrfid.c \
+ cphidgetrfid.h cphidgetservo.c cphidgetservo.h \
+ cphidgetspatial.c cphidgetspatial.h cphidgetstepper.c \
+ cphidgetstepper.h cphidgettemperaturesensor.c \
+ cphidgettemperaturesensor.h cphidgettextlcd.c \
+ cphidgettextlcd.h cphidgettextled.c cphidgettextled.h \
+ cphidgetweightsensor.c cphidgetweightsensor.h \
+ cphidgetmanager.c cphidgetmanager.h cphidgetdictionary.c \
+ cphidgetdictionary.h cphidgetgeneric.c cphidgetgeneric.h \
+ cphidgetsbc.c cphidgetsbc.h clog.c clog.h csocketevents.c \
+ csocketevents.h csocketopen.c csocket.h cphidgetconstants.c \
+ cphidgetconstants.h cphidgetlist.c cphidgetlist.h cthread.c \
+ cthread.h phidget21.c phidget21int.h linux/cusblinux.c \
+ dict/pdict.c dict/pdict.h dict/pdictclient.c \
+ dict/pdictclient.h dict/pdict-impl.h utils/md5.c utils/md5.h \
+ utils/utils.c utils/utils.h utils/ptree.c utils/ptree.h \
+ utils/plist.c utils/plist.h cppheader cppfooter zeroconf.h \
+ utils/cvtutf.c utils/cvtutf.h linux/zeroconf_avahi.c \
+ linux/avahi-client/client.h linux/avahi-client/lookup.h \
+ linux/avahi-client/publish.h linux/avahi-common/address.h \
+ linux/avahi-common/alternative.h linux/avahi-common/cdecl.h \
+ linux/avahi-common/defs.h linux/avahi-common/domain.h \
+ linux/avahi-common/error.h linux/avahi-common/gccmacro.h \
+ linux/avahi-common/llist.h linux/avahi-common/malloc.h \
+ linux/avahi-common/rlist.h linux/avahi-common/simple-watch.h \
+ linux/avahi-common/strlst.h linux/avahi-common/thread-watch.h \
+ linux/avahi-common/timeval.h linux/avahi-common/watch.h \
+ zeroconf.c include/dns_sd.h zeroconf_lookup.c \
+ labview/phidget_labview.c labview/phidget_labview.h \
+ Java/com_phidgets_Phidget.c Java/com_phidgets_Phidget.h \
+ Java/com_phidgets_AccelerometerPhidget.c \
+ Java/com_phidgets_AccelerometerPhidget.h \
+ Java/com_phidgets_AdvancedServoPhidget.c \
+ Java/com_phidgets_AdvancedServoPhidget.h \
+ Java/com_phidgets_AnalogPhidget.c \
+ Java/com_phidgets_AnalogPhidget.h \
+ Java/com_phidgets_BridgePhidget.c \
+ Java/com_phidgets_BridgePhidget.h \
+ Java/com_phidgets_EncoderPhidget.c \
+ Java/com_phidgets_EncoderPhidget.h \
+ Java/com_phidgets_FrequencyCounterPhidget.c \
+ Java/com_phidgets_FrequencyCounterPhidget.h \
+ Java/com_phidgets_GPSPhidget.c Java/com_phidgets_GPSPhidget.h \
+ Java/com_phidgets_InterfaceKitPhidget.c \
+ Java/com_phidgets_InterfaceKitPhidget.h \
+ Java/com_phidgets_IRPhidget.c Java/com_phidgets_IRPhidget.h \
+ Java/com_phidgets_LEDPhidget.c Java/com_phidgets_LEDPhidget.h \
+ Java/com_phidgets_MotorControlPhidget.c \
+ Java/com_phidgets_MotorControlPhidget.h \
+ Java/com_phidgets_PHSensorPhidget.c \
+ Java/com_phidgets_PHSensorPhidget.h \
+ Java/com_phidgets_RFIDPhidget.c \
+ Java/com_phidgets_RFIDPhidget.h \
+ Java/com_phidgets_ServoPhidget.c \
+ Java/com_phidgets_ServoPhidget.h \
+ Java/com_phidgets_SpatialPhidget.c \
+ Java/com_phidgets_SpatialPhidget.h \
+ Java/com_phidgets_StepperPhidget.c \
+ Java/com_phidgets_StepperPhidget.h \
+ Java/com_phidgets_TemperatureSensorPhidget.c \
+ Java/com_phidgets_TemperatureSensorPhidget.h \
+ Java/com_phidgets_TextLCDPhidget.c \
+ Java/com_phidgets_TextLCDPhidget.h \
+ Java/com_phidgets_TextLEDPhidget.c \
+ Java/com_phidgets_TextLEDPhidget.h Java/com_phidgets_Manager.c \
+ Java/com_phidgets_Manager.h Java/com_phidgets_Dictionary.c \
+ Java/com_phidgets_Dictionary.h \
+ Java/com_phidgets_DictionaryKeyListener.c \
+ Java/com_phidgets_DictionaryKeyListener.h \
+ Java/com_phidgets_WeightSensorPhidget.c \
+ Java/com_phidgets_WeightSensorPhidget.h Java/phidget_jni.c \
+ Java/phidget_jni.h include/jni/jawt.h include/jni/jni.h \
+ include/jni/jvmdi.h include/jni/jvmpi.h \
+ include/jni/linux/jawt_md.h include/jni/linux/jni_md.h
+am__objects_1 =
+@INTERNAL_UNICONV_TRUE@am__objects_2 = cvtutf.lo
+@ZEROCONF_AVAHI_TRUE@am__objects_3 = zeroconf_avahi.lo
+@ZEROCONF_BONJOUR_TRUE@am__objects_4 = zeroconf.lo
+@ZEROCONF_LOOKUP_TRUE@am__objects_5 = zeroconf_lookup.lo
+@LABVIEW_TRUE@am__objects_6 = phidget_labview.lo
+@JNI_TRUE@am__objects_7 = com_phidgets_Phidget.lo \
+@JNI_TRUE@ com_phidgets_AccelerometerPhidget.lo \
+@JNI_TRUE@ com_phidgets_AdvancedServoPhidget.lo \
+@JNI_TRUE@ com_phidgets_AnalogPhidget.lo \
+@JNI_TRUE@ com_phidgets_BridgePhidget.lo \
+@JNI_TRUE@ com_phidgets_EncoderPhidget.lo \
+@JNI_TRUE@ com_phidgets_FrequencyCounterPhidget.lo \
+@JNI_TRUE@ com_phidgets_GPSPhidget.lo \
+@JNI_TRUE@ com_phidgets_InterfaceKitPhidget.lo \
+@JNI_TRUE@ com_phidgets_IRPhidget.lo com_phidgets_LEDPhidget.lo \
+@JNI_TRUE@ com_phidgets_MotorControlPhidget.lo \
+@JNI_TRUE@ com_phidgets_PHSensorPhidget.lo \
+@JNI_TRUE@ com_phidgets_RFIDPhidget.lo \
+@JNI_TRUE@ com_phidgets_ServoPhidget.lo \
+@JNI_TRUE@ com_phidgets_SpatialPhidget.lo \
+@JNI_TRUE@ com_phidgets_StepperPhidget.lo \
+@JNI_TRUE@ com_phidgets_TemperatureSensorPhidget.lo \
+@JNI_TRUE@ com_phidgets_TextLCDPhidget.lo \
+@JNI_TRUE@ com_phidgets_TextLEDPhidget.lo \
+@JNI_TRUE@ com_phidgets_Manager.lo com_phidgets_Dictionary.lo \
+@JNI_TRUE@ com_phidgets_DictionaryKeyListener.lo \
+@JNI_TRUE@ com_phidgets_WeightSensorPhidget.lo phidget_jni.lo
+am_libphidget21_la_OBJECTS = cphidget.lo cphidgetaccelerometer.lo \
+ cphidgetadvancedservo.lo cphidgetanalog.lo cphidgetbridge.lo \
+ cphidgetencoder.lo cphidgetfrequencycounter.lo cphidgetgps.lo \
+ cphidgetinterfacekit.lo cphidgetir.lo cphidgetled.lo \
+ cphidgetmotorcontrol.lo cphidgetphsensor.lo cphidgetrfid.lo \
+ cphidgetservo.lo cphidgetspatial.lo cphidgetstepper.lo \
+ cphidgettemperaturesensor.lo cphidgettextlcd.lo \
+ cphidgettextled.lo cphidgetweightsensor.lo cphidgetmanager.lo \
+ cphidgetdictionary.lo cphidgetgeneric.lo cphidgetsbc.lo \
+ clog.lo csocketevents.lo csocketopen.lo cphidgetconstants.lo \
+ cphidgetlist.lo cthread.lo phidget21.lo cusblinux.lo pdict.lo \
+ pdictclient.lo md5.lo utils.lo ptree.lo plist.lo \
+ $(am__objects_1) $(am__objects_2) $(am__objects_3) \
+ $(am__objects_4) $(am__objects_5) $(am__objects_6) \
+ $(am__objects_7)
+libphidget21_la_OBJECTS = $(am_libphidget21_la_OBJECTS)
+AM_V_lt = $(am__v_lt_$(V))
+am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY))
+am__v_lt_0 = --silent
+libphidget21_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(AM_CFLAGS) $(CFLAGS) $(libphidget21_la_LDFLAGS) $(LDFLAGS) \
+ -o $@
+DEFAULT_INCLUDES = -I.@am__isrc@
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_$(V))
+am__v_CC_ = $(am__v_CC_$(AM_DEFAULT_VERBOSITY))
+am__v_CC_0 = @echo " CC " $@;
+AM_V_at = $(am__v_at_$(V))
+am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY))
+am__v_at_0 = @
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_$(V))
+am__v_CCLD_ = $(am__v_CCLD_$(AM_DEFAULT_VERBOSITY))
+am__v_CCLD_0 = @echo " CCLD " $@;
+AM_V_GEN = $(am__v_GEN_$(V))
+am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY))
+am__v_GEN_0 = @echo " GEN " $@;
+SOURCES = $(libphidget21_la_SOURCES)
+DIST_SOURCES = $(am__libphidget21_la_SOURCES_DIST)
+HEADERS = $(include_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+distdir = $(PACKAGE)-$(VERSION)
+top_distdir = $(distdir)
+am__remove_distdir = \
+ { test ! -d "$(distdir)" \
+ || { find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \
+ && rm -fr "$(distdir)"; }; }
+DIST_ARCHIVES = $(distdir).tar.gz
+GZIP_ENV = --best
+distuninstallcheck_listfiles = find . -type f -print
+distcleancheck_listfiles = find . -type f -print
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDCONFIG = @LDCONFIG@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+AM_CFLAGS = -I$(top_srcdir) -I$(top_srcdir)/utils -I$(top_srcdir)/dict \
+ -I$(top_srcdir)/linux -I$(top_srcdir)/include -D_LINUX \
+ $(am__append_2) $(am__append_4) $(am__append_8) \
+ $(am__append_10) $(am__append_11) $(am__append_12)
+lib_LTLIBRARIES = libphidget21.la
+
+# Rules for unpdating the libtool version:
+# 1. Programs using the previous version may use the new version as drop-in replacement,
+# and programs using the new version can also work with the previous one. In other words,
+# no recompiling nor relinking is needed. In this case, bump revision only, don't touch current nor age.
+# 2. Programs using the previous version may use the new version as drop-in replacement,
+# but programs using the new version may use APIs not present in the previous one. In other words,
+# a program linking against the new version may fail with “unresolved symbolsâ€
+# if linking against the old version at runtime: set revision to 0, bump current and age.
+# 3. Programs may need to be changed, recompiled, relinked in order to use the new version.
+# Bump current, set revision and age to 0.
+libphidget21_la_LDFLAGS = -version-info 0:0:0
+libphidget21_la_SOURCES = cphidget.c cphidget.h cphidgetmacros.h \
+ cphidgetattr.h cusb.h stdafx.h cphidgetconstantsinternal.h \
+ cphidgetaccelerometer.c cphidgetaccelerometer.h \
+ cphidgetadvancedservo.c cphidgetadvancedservo.h \
+ cphidgetanalog.c cphidgetanalog.h cphidgetbridge.c \
+ cphidgetbridge.h cphidgetencoder.c cphidgetencoder.h \
+ cphidgetfrequencycounter.c cphidgetfrequencycounter.h \
+ cphidgetgps.c cphidgetgps.h cphidgetinterfacekit.c \
+ cphidgetinterfacekit.h cphidgetir.c cphidgetir.h cphidgetled.c \
+ cphidgetled.h cphidgetmotorcontrol.c cphidgetmotorcontrol.h \
+ cphidgetphsensor.c cphidgetphsensor.h cphidgetrfid.c \
+ cphidgetrfid.h cphidgetservo.c cphidgetservo.h \
+ cphidgetspatial.c cphidgetspatial.h cphidgetstepper.c \
+ cphidgetstepper.h cphidgettemperaturesensor.c \
+ cphidgettemperaturesensor.h cphidgettextlcd.c \
+ cphidgettextlcd.h cphidgettextled.c cphidgettextled.h \
+ cphidgetweightsensor.c cphidgetweightsensor.h \
+ cphidgetmanager.c cphidgetmanager.h cphidgetdictionary.c \
+ cphidgetdictionary.h cphidgetgeneric.c cphidgetgeneric.h \
+ cphidgetsbc.c cphidgetsbc.h clog.c clog.h csocketevents.c \
+ csocketevents.h csocketopen.c csocket.h cphidgetconstants.c \
+ cphidgetconstants.h cphidgetlist.c cphidgetlist.h cthread.c \
+ cthread.h phidget21.c phidget21int.h linux/cusblinux.c \
+ dict/pdict.c dict/pdict.h dict/pdictclient.c \
+ dict/pdictclient.h dict/pdict-impl.h utils/md5.c utils/md5.h \
+ utils/utils.c utils/utils.h utils/ptree.c utils/ptree.h \
+ utils/plist.c utils/plist.h cppheader cppfooter \
+ $(am__append_1) $(am__append_3) $(am__append_5) \
+ $(am__append_6) $(am__append_7) $(am__append_9) \
+ $(am__append_13)
+include_HEADERS = phidget21.h
+CLEANFILES = phidget21.h phidget21matlab.h phidget21.jar Java/com/phidgets/*.class Java/com/phidgets/event/*.class
+EXTRA_DIST = examples/ifkit.c \
+ examples/Makefile.am \
+ examples/Makefile.in \
+ examples/manager.c \
+ examples/phidgetsbclist.c \
+ examples/README \
+ udev/99-phidgets.rules \
+ hotplug/phidgets.usermap \
+ hotplug/phidgets \
+ version.sh \
+ Java/com/phidgets/DictionaryKeyListener.java \
+ Java/com/phidgets/TextLCDPhidget.java \
+ Java/com/phidgets/SpatialEventData.java \
+ Java/com/phidgets/StepperPhidget.java \
+ Java/com/phidgets/ServoPhidget.java \
+ Java/com/phidgets/PHSensorPhidget.java \
+ Java/com/phidgets/AccelerometerPhidget.java \
+ Java/com/phidgets/SpatialPhidget.java \
+ Java/com/phidgets/AdvancedServoPhidget.java \
+ Java/com/phidgets/EncoderPhidget.java \
+ Java/com/phidgets/MotorControlPhidget.java \
+ Java/com/phidgets/IRLearnedCode.java \
+ Java/com/phidgets/IRCodeInfo.java \
+ Java/com/phidgets/InterfaceKitPhidget.java \
+ Java/com/phidgets/TemperatureSensorPhidget.java \
+ Java/com/phidgets/WeightSensorPhidget.java \
+ Java/com/phidgets/TextLEDPhidget.java \
+ Java/com/phidgets/IRCode.java \
+ Java/com/phidgets/Manager.java \
+ Java/com/phidgets/PhidgetException.java \
+ Java/com/phidgets/IRPhidget.java \
+ Java/com/phidgets/RFIDPhidget.java \
+ Java/com/phidgets/LEDPhidget.java \
+ Java/com/phidgets/Dictionary.java \
+ Java/com/phidgets/event/ServoPositionChangeListener.java \
+ Java/com/phidgets/event/AccelerationChangeEvent.java \
+ Java/com/phidgets/event/AttachListener.java \
+ Java/com/phidgets/event/StepperVelocityChangeEvent.java \
+ Java/com/phidgets/event/CodeEvent.java \
+ Java/com/phidgets/event/ErrorEvent.java \
+ Java/com/phidgets/event/TemperatureChangeEvent.java \
+ Java/com/phidgets/event/DetachListener.java \
+ Java/com/phidgets/event/LearnListener.java \
+ Java/com/phidgets/event/ServoVelocityChangeEvent.java \
+ Java/com/phidgets/event/PHChangeListener.java \
+ Java/com/phidgets/event/RawDataListener.java \
+ Java/com/phidgets/event/CurrentChangeListener.java \
+ Java/com/phidgets/event/TagGainEvent.java \
+ Java/com/phidgets/event/StepperPositionChangeEvent.java \
+ Java/com/phidgets/event/WeightChangeListener.java \
+ Java/com/phidgets/event/InputChangeEvent.java \
+ Java/com/phidgets/event/TagLossListener.java \
+ Java/com/phidgets/event/ServerDisconnectEvent.java \
+ Java/com/phidgets/event/TemperatureChangeListener.java \
+ Java/com/phidgets/event/SpatialDataListener.java \
+ Java/com/phidgets/event/SensorChangeEvent.java \
+ Java/com/phidgets/event/CodeListener.java \
+ Java/com/phidgets/event/ServerConnectEvent.java \
+ Java/com/phidgets/event/StepperPositionChangeListener.java \
+ Java/com/phidgets/event/SpatialDataEvent.java \
+ Java/com/phidgets/event/AttachEvent.java \
+ Java/com/phidgets/event/EncoderPositionChangeListener.java \
+ Java/com/phidgets/event/EncoderPositionChangeEvent.java \
+ Java/com/phidgets/event/DetachEvent.java \
+ Java/com/phidgets/event/OutputChangeListener.java \
+ Java/com/phidgets/event/TagGainListener.java \
+ Java/com/phidgets/event/KeyRemovalListener.java \
+ Java/com/phidgets/event/KeyChangeEvent.java \
+ Java/com/phidgets/event/KeyRemovalEvent.java \
+ Java/com/phidgets/event/OutputChangeEvent.java \
+ Java/com/phidgets/event/StepperVelocityChangeListener.java \
+ Java/com/phidgets/event/ServerDisconnectListener.java \
+ Java/com/phidgets/event/ErrorListener.java \
+ Java/com/phidgets/event/SensorChangeListener.java \
+ Java/com/phidgets/event/PHChangeEvent.java \
+ Java/com/phidgets/event/LearnEvent.java \
+ Java/com/phidgets/event/WeightChangeEvent.java \
+ Java/com/phidgets/event/MotorVelocityChangeListener.java \
+ Java/com/phidgets/event/TagLossEvent.java \
+ Java/com/phidgets/event/KeyChangeListener.java \
+ Java/com/phidgets/event/ServerConnectListener.java \
+ Java/com/phidgets/event/AccelerationChangeListener.java \
+ Java/com/phidgets/event/RawDataEvent.java \
+ Java/com/phidgets/event/InputChangeListener.java \
+ Java/com/phidgets/event/ServoPositionChangeEvent.java \
+ Java/com/phidgets/event/CurrentChangeEvent.java \
+ Java/com/phidgets/event/ServoVelocityChangeListener.java \
+ Java/com/phidgets/event/MotorVelocityChangeEvent.java \
+ Java/com/phidgets/event/CurrentUpdateEvent.java \
+ Java/com/phidgets/event/CurrentUpdateListener.java \
+ Java/com/phidgets/event/BackEMFUpdateEvent.java \
+ Java/com/phidgets/event/BackEMFUpdateListener.java \
+ Java/com/phidgets/event/EncoderPositionUpdateEvent.java \
+ Java/com/phidgets/event/EncoderPositionUpdateListener.java \
+ Java/com/phidgets/event/SensorUpdateEvent.java \
+ Java/com/phidgets/event/SensorUpdateListener.java \
+ Java/com/phidgets/AnalogPhidget.java \
+ Java/com/phidgets/FrequencyCounterPhidget.java \
+ Java/com/phidgets/event/GPSPositionFixStatusChangeEvent.java \
+ Java/com/phidgets/event/GPSPositionFixStatusChangeListener.java \
+ Java/com/phidgets/event/FrequencyCounterCountListener.java \
+ Java/com/phidgets/event/GPSPositionChangeEvent.java \
+ Java/com/phidgets/event/GPSPositionChangeListener.java \
+ Java/com/phidgets/event/FrequencyCounterCountEvent.java \
+ Java/com/phidgets/GPSPhidget.java \
+ Java/com/phidgets/BridgePhidget.java \
+ Java/com/phidgets/event/BridgeDataEvent.java \
+ Java/com/phidgets/event/BridgeDataListener.java \
+ Java/com/phidgets/macros/BridgePhidget.jm \
+ Java/com/phidgets/Phidget.java
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+am--refresh:
+ @:
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ echo ' cd $(srcdir) && $(AUTOMAKE) --gnu'; \
+ $(am__cd) $(srcdir) && $(AUTOMAKE) --gnu \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ echo ' $(SHELL) ./config.status'; \
+ $(SHELL) ./config.status;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ $(SHELL) ./config.status --recheck
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ $(am__cd) $(srcdir) && $(AUTOCONF)
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
+$(am__aclocal_m4_deps):
+install-libLTLIBRARIES: $(lib_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)"
+ @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \
+ }
+
+uninstall-libLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \
+ done
+
+clean-libLTLIBRARIES:
+ -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
+ @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libphidget21.la: $(libphidget21_la_OBJECTS) $(libphidget21_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(libphidget21_la_LINK) -rpath $(libdir) $(libphidget21_la_OBJECTS) $(libphidget21_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clog.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/com_phidgets_AccelerometerPhidget.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/com_phidgets_AdvancedServoPhidget.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/com_phidgets_AnalogPhidget.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/com_phidgets_BridgePhidget.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/com_phidgets_Dictionary.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/com_phidgets_DictionaryKeyListener.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/com_phidgets_EncoderPhidget.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/com_phidgets_FrequencyCounterPhidget.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/com_phidgets_GPSPhidget.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/com_phidgets_IRPhidget.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/com_phidgets_InterfaceKitPhidget.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/com_phidgets_LEDPhidget.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/com_phidgets_Manager.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/com_phidgets_MotorControlPhidget.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/com_phidgets_PHSensorPhidget.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/com_phidgets_Phidget.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/com_phidgets_RFIDPhidget.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/com_phidgets_ServoPhidget.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/com_phidgets_SpatialPhidget.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/com_phidgets_StepperPhidget.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/com_phidgets_TemperatureSensorPhidget.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/com_phidgets_TextLCDPhidget.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/com_phidgets_TextLEDPhidget.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/com_phidgets_WeightSensorPhidget.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cphidget.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cphidgetaccelerometer.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cphidgetadvancedservo.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cphidgetanalog.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cphidgetbridge.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cphidgetconstants.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cphidgetdictionary.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cphidgetencoder.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cphidgetfrequencycounter.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cphidgetgeneric.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cphidgetgps.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cphidgetinterfacekit.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cphidgetir.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cphidgetled.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cphidgetlist.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cphidgetmanager.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cphidgetmotorcontrol.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cphidgetphsensor.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cphidgetrfid.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cphidgetsbc.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cphidgetservo.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cphidgetspatial.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cphidgetstepper.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cphidgettemperaturesensor.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cphidgettextlcd.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cphidgettextled.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cphidgetweightsensor.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/csocketevents.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/csocketopen.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cthread.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cusblinux.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cvtutf.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/md5.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pdict.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pdictclient.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/phidget21.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/phidget_jni.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/phidget_labview.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plist.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ptree.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utils.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zeroconf.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zeroconf_avahi.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zeroconf_lookup.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+cusblinux.lo: linux/cusblinux.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cusblinux.lo -MD -MP -MF $(DEPDIR)/cusblinux.Tpo -c -o cusblinux.lo `test -f 'linux/cusblinux.c' || echo '$(srcdir)/'`linux/cusblinux.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cusblinux.Tpo $(DEPDIR)/cusblinux.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='linux/cusblinux.c' object='cusblinux.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cusblinux.lo `test -f 'linux/cusblinux.c' || echo '$(srcdir)/'`linux/cusblinux.c
+
+pdict.lo: dict/pdict.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT pdict.lo -MD -MP -MF $(DEPDIR)/pdict.Tpo -c -o pdict.lo `test -f 'dict/pdict.c' || echo '$(srcdir)/'`dict/pdict.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pdict.Tpo $(DEPDIR)/pdict.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='dict/pdict.c' object='pdict.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o pdict.lo `test -f 'dict/pdict.c' || echo '$(srcdir)/'`dict/pdict.c
+
+pdictclient.lo: dict/pdictclient.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT pdictclient.lo -MD -MP -MF $(DEPDIR)/pdictclient.Tpo -c -o pdictclient.lo `test -f 'dict/pdictclient.c' || echo '$(srcdir)/'`dict/pdictclient.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pdictclient.Tpo $(DEPDIR)/pdictclient.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='dict/pdictclient.c' object='pdictclient.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o pdictclient.lo `test -f 'dict/pdictclient.c' || echo '$(srcdir)/'`dict/pdictclient.c
+
+md5.lo: utils/md5.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT md5.lo -MD -MP -MF $(DEPDIR)/md5.Tpo -c -o md5.lo `test -f 'utils/md5.c' || echo '$(srcdir)/'`utils/md5.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/md5.Tpo $(DEPDIR)/md5.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='utils/md5.c' object='md5.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o md5.lo `test -f 'utils/md5.c' || echo '$(srcdir)/'`utils/md5.c
+
+utils.lo: utils/utils.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT utils.lo -MD -MP -MF $(DEPDIR)/utils.Tpo -c -o utils.lo `test -f 'utils/utils.c' || echo '$(srcdir)/'`utils/utils.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/utils.Tpo $(DEPDIR)/utils.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='utils/utils.c' object='utils.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o utils.lo `test -f 'utils/utils.c' || echo '$(srcdir)/'`utils/utils.c
+
+ptree.lo: utils/ptree.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ptree.lo -MD -MP -MF $(DEPDIR)/ptree.Tpo -c -o ptree.lo `test -f 'utils/ptree.c' || echo '$(srcdir)/'`utils/ptree.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ptree.Tpo $(DEPDIR)/ptree.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='utils/ptree.c' object='ptree.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ptree.lo `test -f 'utils/ptree.c' || echo '$(srcdir)/'`utils/ptree.c
+
+plist.lo: utils/plist.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT plist.lo -MD -MP -MF $(DEPDIR)/plist.Tpo -c -o plist.lo `test -f 'utils/plist.c' || echo '$(srcdir)/'`utils/plist.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/plist.Tpo $(DEPDIR)/plist.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='utils/plist.c' object='plist.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o plist.lo `test -f 'utils/plist.c' || echo '$(srcdir)/'`utils/plist.c
+
+cvtutf.lo: utils/cvtutf.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cvtutf.lo -MD -MP -MF $(DEPDIR)/cvtutf.Tpo -c -o cvtutf.lo `test -f 'utils/cvtutf.c' || echo '$(srcdir)/'`utils/cvtutf.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cvtutf.Tpo $(DEPDIR)/cvtutf.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='utils/cvtutf.c' object='cvtutf.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cvtutf.lo `test -f 'utils/cvtutf.c' || echo '$(srcdir)/'`utils/cvtutf.c
+
+zeroconf_avahi.lo: linux/zeroconf_avahi.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT zeroconf_avahi.lo -MD -MP -MF $(DEPDIR)/zeroconf_avahi.Tpo -c -o zeroconf_avahi.lo `test -f 'linux/zeroconf_avahi.c' || echo '$(srcdir)/'`linux/zeroconf_avahi.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/zeroconf_avahi.Tpo $(DEPDIR)/zeroconf_avahi.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='linux/zeroconf_avahi.c' object='zeroconf_avahi.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o zeroconf_avahi.lo `test -f 'linux/zeroconf_avahi.c' || echo '$(srcdir)/'`linux/zeroconf_avahi.c
+
+phidget_labview.lo: labview/phidget_labview.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT phidget_labview.lo -MD -MP -MF $(DEPDIR)/phidget_labview.Tpo -c -o phidget_labview.lo `test -f 'labview/phidget_labview.c' || echo '$(srcdir)/'`labview/phidget_labview.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/phidget_labview.Tpo $(DEPDIR)/phidget_labview.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='labview/phidget_labview.c' object='phidget_labview.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o phidget_labview.lo `test -f 'labview/phidget_labview.c' || echo '$(srcdir)/'`labview/phidget_labview.c
+
+com_phidgets_Phidget.lo: Java/com_phidgets_Phidget.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT com_phidgets_Phidget.lo -MD -MP -MF $(DEPDIR)/com_phidgets_Phidget.Tpo -c -o com_phidgets_Phidget.lo `test -f 'Java/com_phidgets_Phidget.c' || echo '$(srcdir)/'`Java/com_phidgets_Phidget.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/com_phidgets_Phidget.Tpo $(DEPDIR)/com_phidgets_Phidget.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='Java/com_phidgets_Phidget.c' object='com_phidgets_Phidget.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o com_phidgets_Phidget.lo `test -f 'Java/com_phidgets_Phidget.c' || echo '$(srcdir)/'`Java/com_phidgets_Phidget.c
+
+com_phidgets_AccelerometerPhidget.lo: Java/com_phidgets_AccelerometerPhidget.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT com_phidgets_AccelerometerPhidget.lo -MD -MP -MF $(DEPDIR)/com_phidgets_AccelerometerPhidget.Tpo -c -o com_phidgets_AccelerometerPhidget.lo `test -f 'Java/com_phidgets_AccelerometerPhidget.c' || echo '$(srcdir)/'`Java/com_phidgets_AccelerometerPhidget.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/com_phidgets_AccelerometerPhidget.Tpo $(DEPDIR)/com_phidgets_AccelerometerPhidget.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='Java/com_phidgets_AccelerometerPhidget.c' object='com_phidgets_AccelerometerPhidget.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o com_phidgets_AccelerometerPhidget.lo `test -f 'Java/com_phidgets_AccelerometerPhidget.c' || echo '$(srcdir)/'`Java/com_phidgets_AccelerometerPhidget.c
+
+com_phidgets_AdvancedServoPhidget.lo: Java/com_phidgets_AdvancedServoPhidget.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT com_phidgets_AdvancedServoPhidget.lo -MD -MP -MF $(DEPDIR)/com_phidgets_AdvancedServoPhidget.Tpo -c -o com_phidgets_AdvancedServoPhidget.lo `test -f 'Java/com_phidgets_AdvancedServoPhidget.c' || echo '$(srcdir)/'`Java/com_phidgets_AdvancedServoPhidget.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/com_phidgets_AdvancedServoPhidget.Tpo $(DEPDIR)/com_phidgets_AdvancedServoPhidget.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='Java/com_phidgets_AdvancedServoPhidget.c' object='com_phidgets_AdvancedServoPhidget.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o com_phidgets_AdvancedServoPhidget.lo `test -f 'Java/com_phidgets_AdvancedServoPhidget.c' || echo '$(srcdir)/'`Java/com_phidgets_AdvancedServoPhidget.c
+
+com_phidgets_AnalogPhidget.lo: Java/com_phidgets_AnalogPhidget.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT com_phidgets_AnalogPhidget.lo -MD -MP -MF $(DEPDIR)/com_phidgets_AnalogPhidget.Tpo -c -o com_phidgets_AnalogPhidget.lo `test -f 'Java/com_phidgets_AnalogPhidget.c' || echo '$(srcdir)/'`Java/com_phidgets_AnalogPhidget.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/com_phidgets_AnalogPhidget.Tpo $(DEPDIR)/com_phidgets_AnalogPhidget.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='Java/com_phidgets_AnalogPhidget.c' object='com_phidgets_AnalogPhidget.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o com_phidgets_AnalogPhidget.lo `test -f 'Java/com_phidgets_AnalogPhidget.c' || echo '$(srcdir)/'`Java/com_phidgets_AnalogPhidget.c
+
+com_phidgets_BridgePhidget.lo: Java/com_phidgets_BridgePhidget.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT com_phidgets_BridgePhidget.lo -MD -MP -MF $(DEPDIR)/com_phidgets_BridgePhidget.Tpo -c -o com_phidgets_BridgePhidget.lo `test -f 'Java/com_phidgets_BridgePhidget.c' || echo '$(srcdir)/'`Java/com_phidgets_BridgePhidget.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/com_phidgets_BridgePhidget.Tpo $(DEPDIR)/com_phidgets_BridgePhidget.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='Java/com_phidgets_BridgePhidget.c' object='com_phidgets_BridgePhidget.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o com_phidgets_BridgePhidget.lo `test -f 'Java/com_phidgets_BridgePhidget.c' || echo '$(srcdir)/'`Java/com_phidgets_BridgePhidget.c
+
+com_phidgets_EncoderPhidget.lo: Java/com_phidgets_EncoderPhidget.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT com_phidgets_EncoderPhidget.lo -MD -MP -MF $(DEPDIR)/com_phidgets_EncoderPhidget.Tpo -c -o com_phidgets_EncoderPhidget.lo `test -f 'Java/com_phidgets_EncoderPhidget.c' || echo '$(srcdir)/'`Java/com_phidgets_EncoderPhidget.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/com_phidgets_EncoderPhidget.Tpo $(DEPDIR)/com_phidgets_EncoderPhidget.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='Java/com_phidgets_EncoderPhidget.c' object='com_phidgets_EncoderPhidget.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o com_phidgets_EncoderPhidget.lo `test -f 'Java/com_phidgets_EncoderPhidget.c' || echo '$(srcdir)/'`Java/com_phidgets_EncoderPhidget.c
+
+com_phidgets_FrequencyCounterPhidget.lo: Java/com_phidgets_FrequencyCounterPhidget.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT com_phidgets_FrequencyCounterPhidget.lo -MD -MP -MF $(DEPDIR)/com_phidgets_FrequencyCounterPhidget.Tpo -c -o com_phidgets_FrequencyCounterPhidget.lo `test -f 'Java/com_phidgets_FrequencyCounterPhidget.c' || echo '$(srcdir)/'`Java/com_phidgets_FrequencyCounterPhidget.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/com_phidgets_FrequencyCounterPhidget.Tpo $(DEPDIR)/com_phidgets_FrequencyCounterPhidget.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='Java/com_phidgets_FrequencyCounterPhidget.c' object='com_phidgets_FrequencyCounterPhidget.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o com_phidgets_FrequencyCounterPhidget.lo `test -f 'Java/com_phidgets_FrequencyCounterPhidget.c' || echo '$(srcdir)/'`Java/com_phidgets_FrequencyCounterPhidget.c
+
+com_phidgets_GPSPhidget.lo: Java/com_phidgets_GPSPhidget.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT com_phidgets_GPSPhidget.lo -MD -MP -MF $(DEPDIR)/com_phidgets_GPSPhidget.Tpo -c -o com_phidgets_GPSPhidget.lo `test -f 'Java/com_phidgets_GPSPhidget.c' || echo '$(srcdir)/'`Java/com_phidgets_GPSPhidget.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/com_phidgets_GPSPhidget.Tpo $(DEPDIR)/com_phidgets_GPSPhidget.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='Java/com_phidgets_GPSPhidget.c' object='com_phidgets_GPSPhidget.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o com_phidgets_GPSPhidget.lo `test -f 'Java/com_phidgets_GPSPhidget.c' || echo '$(srcdir)/'`Java/com_phidgets_GPSPhidget.c
+
+com_phidgets_InterfaceKitPhidget.lo: Java/com_phidgets_InterfaceKitPhidget.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT com_phidgets_InterfaceKitPhidget.lo -MD -MP -MF $(DEPDIR)/com_phidgets_InterfaceKitPhidget.Tpo -c -o com_phidgets_InterfaceKitPhidget.lo `test -f 'Java/com_phidgets_InterfaceKitPhidget.c' || echo '$(srcdir)/'`Java/com_phidgets_InterfaceKitPhidget.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/com_phidgets_InterfaceKitPhidget.Tpo $(DEPDIR)/com_phidgets_InterfaceKitPhidget.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='Java/com_phidgets_InterfaceKitPhidget.c' object='com_phidgets_InterfaceKitPhidget.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o com_phidgets_InterfaceKitPhidget.lo `test -f 'Java/com_phidgets_InterfaceKitPhidget.c' || echo '$(srcdir)/'`Java/com_phidgets_InterfaceKitPhidget.c
+
+com_phidgets_IRPhidget.lo: Java/com_phidgets_IRPhidget.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT com_phidgets_IRPhidget.lo -MD -MP -MF $(DEPDIR)/com_phidgets_IRPhidget.Tpo -c -o com_phidgets_IRPhidget.lo `test -f 'Java/com_phidgets_IRPhidget.c' || echo '$(srcdir)/'`Java/com_phidgets_IRPhidget.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/com_phidgets_IRPhidget.Tpo $(DEPDIR)/com_phidgets_IRPhidget.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='Java/com_phidgets_IRPhidget.c' object='com_phidgets_IRPhidget.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o com_phidgets_IRPhidget.lo `test -f 'Java/com_phidgets_IRPhidget.c' || echo '$(srcdir)/'`Java/com_phidgets_IRPhidget.c
+
+com_phidgets_LEDPhidget.lo: Java/com_phidgets_LEDPhidget.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT com_phidgets_LEDPhidget.lo -MD -MP -MF $(DEPDIR)/com_phidgets_LEDPhidget.Tpo -c -o com_phidgets_LEDPhidget.lo `test -f 'Java/com_phidgets_LEDPhidget.c' || echo '$(srcdir)/'`Java/com_phidgets_LEDPhidget.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/com_phidgets_LEDPhidget.Tpo $(DEPDIR)/com_phidgets_LEDPhidget.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='Java/com_phidgets_LEDPhidget.c' object='com_phidgets_LEDPhidget.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o com_phidgets_LEDPhidget.lo `test -f 'Java/com_phidgets_LEDPhidget.c' || echo '$(srcdir)/'`Java/com_phidgets_LEDPhidget.c
+
+com_phidgets_MotorControlPhidget.lo: Java/com_phidgets_MotorControlPhidget.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT com_phidgets_MotorControlPhidget.lo -MD -MP -MF $(DEPDIR)/com_phidgets_MotorControlPhidget.Tpo -c -o com_phidgets_MotorControlPhidget.lo `test -f 'Java/com_phidgets_MotorControlPhidget.c' || echo '$(srcdir)/'`Java/com_phidgets_MotorControlPhidget.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/com_phidgets_MotorControlPhidget.Tpo $(DEPDIR)/com_phidgets_MotorControlPhidget.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='Java/com_phidgets_MotorControlPhidget.c' object='com_phidgets_MotorControlPhidget.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o com_phidgets_MotorControlPhidget.lo `test -f 'Java/com_phidgets_MotorControlPhidget.c' || echo '$(srcdir)/'`Java/com_phidgets_MotorControlPhidget.c
+
+com_phidgets_PHSensorPhidget.lo: Java/com_phidgets_PHSensorPhidget.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT com_phidgets_PHSensorPhidget.lo -MD -MP -MF $(DEPDIR)/com_phidgets_PHSensorPhidget.Tpo -c -o com_phidgets_PHSensorPhidget.lo `test -f 'Java/com_phidgets_PHSensorPhidget.c' || echo '$(srcdir)/'`Java/com_phidgets_PHSensorPhidget.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/com_phidgets_PHSensorPhidget.Tpo $(DEPDIR)/com_phidgets_PHSensorPhidget.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='Java/com_phidgets_PHSensorPhidget.c' object='com_phidgets_PHSensorPhidget.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o com_phidgets_PHSensorPhidget.lo `test -f 'Java/com_phidgets_PHSensorPhidget.c' || echo '$(srcdir)/'`Java/com_phidgets_PHSensorPhidget.c
+
+com_phidgets_RFIDPhidget.lo: Java/com_phidgets_RFIDPhidget.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT com_phidgets_RFIDPhidget.lo -MD -MP -MF $(DEPDIR)/com_phidgets_RFIDPhidget.Tpo -c -o com_phidgets_RFIDPhidget.lo `test -f 'Java/com_phidgets_RFIDPhidget.c' || echo '$(srcdir)/'`Java/com_phidgets_RFIDPhidget.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/com_phidgets_RFIDPhidget.Tpo $(DEPDIR)/com_phidgets_RFIDPhidget.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='Java/com_phidgets_RFIDPhidget.c' object='com_phidgets_RFIDPhidget.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o com_phidgets_RFIDPhidget.lo `test -f 'Java/com_phidgets_RFIDPhidget.c' || echo '$(srcdir)/'`Java/com_phidgets_RFIDPhidget.c
+
+com_phidgets_ServoPhidget.lo: Java/com_phidgets_ServoPhidget.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT com_phidgets_ServoPhidget.lo -MD -MP -MF $(DEPDIR)/com_phidgets_ServoPhidget.Tpo -c -o com_phidgets_ServoPhidget.lo `test -f 'Java/com_phidgets_ServoPhidget.c' || echo '$(srcdir)/'`Java/com_phidgets_ServoPhidget.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/com_phidgets_ServoPhidget.Tpo $(DEPDIR)/com_phidgets_ServoPhidget.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='Java/com_phidgets_ServoPhidget.c' object='com_phidgets_ServoPhidget.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o com_phidgets_ServoPhidget.lo `test -f 'Java/com_phidgets_ServoPhidget.c' || echo '$(srcdir)/'`Java/com_phidgets_ServoPhidget.c
+
+com_phidgets_SpatialPhidget.lo: Java/com_phidgets_SpatialPhidget.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT com_phidgets_SpatialPhidget.lo -MD -MP -MF $(DEPDIR)/com_phidgets_SpatialPhidget.Tpo -c -o com_phidgets_SpatialPhidget.lo `test -f 'Java/com_phidgets_SpatialPhidget.c' || echo '$(srcdir)/'`Java/com_phidgets_SpatialPhidget.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/com_phidgets_SpatialPhidget.Tpo $(DEPDIR)/com_phidgets_SpatialPhidget.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='Java/com_phidgets_SpatialPhidget.c' object='com_phidgets_SpatialPhidget.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o com_phidgets_SpatialPhidget.lo `test -f 'Java/com_phidgets_SpatialPhidget.c' || echo '$(srcdir)/'`Java/com_phidgets_SpatialPhidget.c
+
+com_phidgets_StepperPhidget.lo: Java/com_phidgets_StepperPhidget.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT com_phidgets_StepperPhidget.lo -MD -MP -MF $(DEPDIR)/com_phidgets_StepperPhidget.Tpo -c -o com_phidgets_StepperPhidget.lo `test -f 'Java/com_phidgets_StepperPhidget.c' || echo '$(srcdir)/'`Java/com_phidgets_StepperPhidget.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/com_phidgets_StepperPhidget.Tpo $(DEPDIR)/com_phidgets_StepperPhidget.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='Java/com_phidgets_StepperPhidget.c' object='com_phidgets_StepperPhidget.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o com_phidgets_StepperPhidget.lo `test -f 'Java/com_phidgets_StepperPhidget.c' || echo '$(srcdir)/'`Java/com_phidgets_StepperPhidget.c
+
+com_phidgets_TemperatureSensorPhidget.lo: Java/com_phidgets_TemperatureSensorPhidget.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT com_phidgets_TemperatureSensorPhidget.lo -MD -MP -MF $(DEPDIR)/com_phidgets_TemperatureSensorPhidget.Tpo -c -o com_phidgets_TemperatureSensorPhidget.lo `test -f 'Java/com_phidgets_TemperatureSensorPhidget.c' || echo '$(srcdir)/'`Java/com_phidgets_TemperatureSensorPhidget.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/com_phidgets_TemperatureSensorPhidget.Tpo $(DEPDIR)/com_phidgets_TemperatureSensorPhidget.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='Java/com_phidgets_TemperatureSensorPhidget.c' object='com_phidgets_TemperatureSensorPhidget.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o com_phidgets_TemperatureSensorPhidget.lo `test -f 'Java/com_phidgets_TemperatureSensorPhidget.c' || echo '$(srcdir)/'`Java/com_phidgets_TemperatureSensorPhidget.c
+
+com_phidgets_TextLCDPhidget.lo: Java/com_phidgets_TextLCDPhidget.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT com_phidgets_TextLCDPhidget.lo -MD -MP -MF $(DEPDIR)/com_phidgets_TextLCDPhidget.Tpo -c -o com_phidgets_TextLCDPhidget.lo `test -f 'Java/com_phidgets_TextLCDPhidget.c' || echo '$(srcdir)/'`Java/com_phidgets_TextLCDPhidget.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/com_phidgets_TextLCDPhidget.Tpo $(DEPDIR)/com_phidgets_TextLCDPhidget.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='Java/com_phidgets_TextLCDPhidget.c' object='com_phidgets_TextLCDPhidget.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o com_phidgets_TextLCDPhidget.lo `test -f 'Java/com_phidgets_TextLCDPhidget.c' || echo '$(srcdir)/'`Java/com_phidgets_TextLCDPhidget.c
+
+com_phidgets_TextLEDPhidget.lo: Java/com_phidgets_TextLEDPhidget.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT com_phidgets_TextLEDPhidget.lo -MD -MP -MF $(DEPDIR)/com_phidgets_TextLEDPhidget.Tpo -c -o com_phidgets_TextLEDPhidget.lo `test -f 'Java/com_phidgets_TextLEDPhidget.c' || echo '$(srcdir)/'`Java/com_phidgets_TextLEDPhidget.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/com_phidgets_TextLEDPhidget.Tpo $(DEPDIR)/com_phidgets_TextLEDPhidget.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='Java/com_phidgets_TextLEDPhidget.c' object='com_phidgets_TextLEDPhidget.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o com_phidgets_TextLEDPhidget.lo `test -f 'Java/com_phidgets_TextLEDPhidget.c' || echo '$(srcdir)/'`Java/com_phidgets_TextLEDPhidget.c
+
+com_phidgets_Manager.lo: Java/com_phidgets_Manager.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT com_phidgets_Manager.lo -MD -MP -MF $(DEPDIR)/com_phidgets_Manager.Tpo -c -o com_phidgets_Manager.lo `test -f 'Java/com_phidgets_Manager.c' || echo '$(srcdir)/'`Java/com_phidgets_Manager.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/com_phidgets_Manager.Tpo $(DEPDIR)/com_phidgets_Manager.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='Java/com_phidgets_Manager.c' object='com_phidgets_Manager.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o com_phidgets_Manager.lo `test -f 'Java/com_phidgets_Manager.c' || echo '$(srcdir)/'`Java/com_phidgets_Manager.c
+
+com_phidgets_Dictionary.lo: Java/com_phidgets_Dictionary.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT com_phidgets_Dictionary.lo -MD -MP -MF $(DEPDIR)/com_phidgets_Dictionary.Tpo -c -o com_phidgets_Dictionary.lo `test -f 'Java/com_phidgets_Dictionary.c' || echo '$(srcdir)/'`Java/com_phidgets_Dictionary.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/com_phidgets_Dictionary.Tpo $(DEPDIR)/com_phidgets_Dictionary.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='Java/com_phidgets_Dictionary.c' object='com_phidgets_Dictionary.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o com_phidgets_Dictionary.lo `test -f 'Java/com_phidgets_Dictionary.c' || echo '$(srcdir)/'`Java/com_phidgets_Dictionary.c
+
+com_phidgets_DictionaryKeyListener.lo: Java/com_phidgets_DictionaryKeyListener.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT com_phidgets_DictionaryKeyListener.lo -MD -MP -MF $(DEPDIR)/com_phidgets_DictionaryKeyListener.Tpo -c -o com_phidgets_DictionaryKeyListener.lo `test -f 'Java/com_phidgets_DictionaryKeyListener.c' || echo '$(srcdir)/'`Java/com_phidgets_DictionaryKeyListener.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/com_phidgets_DictionaryKeyListener.Tpo $(DEPDIR)/com_phidgets_DictionaryKeyListener.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='Java/com_phidgets_DictionaryKeyListener.c' object='com_phidgets_DictionaryKeyListener.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o com_phidgets_DictionaryKeyListener.lo `test -f 'Java/com_phidgets_DictionaryKeyListener.c' || echo '$(srcdir)/'`Java/com_phidgets_DictionaryKeyListener.c
+
+com_phidgets_WeightSensorPhidget.lo: Java/com_phidgets_WeightSensorPhidget.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT com_phidgets_WeightSensorPhidget.lo -MD -MP -MF $(DEPDIR)/com_phidgets_WeightSensorPhidget.Tpo -c -o com_phidgets_WeightSensorPhidget.lo `test -f 'Java/com_phidgets_WeightSensorPhidget.c' || echo '$(srcdir)/'`Java/com_phidgets_WeightSensorPhidget.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/com_phidgets_WeightSensorPhidget.Tpo $(DEPDIR)/com_phidgets_WeightSensorPhidget.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='Java/com_phidgets_WeightSensorPhidget.c' object='com_phidgets_WeightSensorPhidget.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o com_phidgets_WeightSensorPhidget.lo `test -f 'Java/com_phidgets_WeightSensorPhidget.c' || echo '$(srcdir)/'`Java/com_phidgets_WeightSensorPhidget.c
+
+phidget_jni.lo: Java/phidget_jni.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT phidget_jni.lo -MD -MP -MF $(DEPDIR)/phidget_jni.Tpo -c -o phidget_jni.lo `test -f 'Java/phidget_jni.c' || echo '$(srcdir)/'`Java/phidget_jni.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/phidget_jni.Tpo $(DEPDIR)/phidget_jni.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='Java/phidget_jni.c' object='phidget_jni.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o phidget_jni.lo `test -f 'Java/phidget_jni.c' || echo '$(srcdir)/'`Java/phidget_jni.c
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+distclean-libtool:
+ -rm -f libtool config.lt
+install-includeHEADERS: $(include_HEADERS)
+ @$(NORMAL_INSTALL)
+ test -z "$(includedir)" || $(MKDIR_P) "$(DESTDIR)$(includedir)"
+ @list='$(include_HEADERS)'; test -n "$(includedir)" || list=; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(includedir)'"; \
+ $(INSTALL_HEADER) $$files "$(DESTDIR)$(includedir)" || exit $$?; \
+ done
+
+uninstall-includeHEADERS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(include_HEADERS)'; test -n "$(includedir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ test -n "$$files" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(includedir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(includedir)" && rm -f $$files
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ $(am__remove_distdir)
+ test -d "$(distdir)" || mkdir "$(distdir)"
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+ -test -n "$(am__skip_mode_fix)" \
+ || find "$(distdir)" -type d ! -perm -777 -exec chmod a+rwx {} \; -o \
+ ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \
+ ! -type d ! -perm -400 -exec chmod a+r {} \; -o \
+ ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \
+ || chmod -R a+r "$(distdir)"
+dist-gzip: distdir
+ tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
+ $(am__remove_distdir)
+
+dist-bzip2: distdir
+ tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2
+ $(am__remove_distdir)
+
+dist-lzma: distdir
+ tardir=$(distdir) && $(am__tar) | lzma -9 -c >$(distdir).tar.lzma
+ $(am__remove_distdir)
+
+dist-xz: distdir
+ tardir=$(distdir) && $(am__tar) | xz -c >$(distdir).tar.xz
+ $(am__remove_distdir)
+
+dist-tarZ: distdir
+ tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z
+ $(am__remove_distdir)
+
+dist-shar: distdir
+ shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz
+ $(am__remove_distdir)
+
+dist-zip: distdir
+ -rm -f $(distdir).zip
+ zip -rq $(distdir).zip $(distdir)
+ $(am__remove_distdir)
+
+dist dist-all: distdir
+ tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
+ $(am__remove_distdir)
+
+# This target untars the dist file and tries a VPATH configuration. Then
+# it guarantees that the distribution is self-contained by making another
+# tarfile.
+distcheck: dist
+ case '$(DIST_ARCHIVES)' in \
+ *.tar.gz*) \
+ GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | $(am__untar) ;;\
+ *.tar.bz2*) \
+ bunzip2 -c $(distdir).tar.bz2 | $(am__untar) ;;\
+ *.tar.lzma*) \
+ unlzma -c $(distdir).tar.lzma | $(am__untar) ;;\
+ *.tar.xz*) \
+ xz -dc $(distdir).tar.xz | $(am__untar) ;;\
+ *.tar.Z*) \
+ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\
+ *.shar.gz*) \
+ GZIP=$(GZIP_ENV) gunzip -c $(distdir).shar.gz | unshar ;;\
+ *.zip*) \
+ unzip $(distdir).zip ;;\
+ esac
+ chmod -R a-w $(distdir); chmod a+w $(distdir)
+ mkdir $(distdir)/_build
+ mkdir $(distdir)/_inst
+ chmod a-w $(distdir)
+ test -d $(distdir)/_build || exit 0; \
+ dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \
+ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \
+ && am__cwd=`pwd` \
+ && $(am__cd) $(distdir)/_build \
+ && ../configure --srcdir=.. --prefix="$$dc_install_base" \
+ $(DISTCHECK_CONFIGURE_FLAGS) \
+ && $(MAKE) $(AM_MAKEFLAGS) \
+ && $(MAKE) $(AM_MAKEFLAGS) dvi \
+ && $(MAKE) $(AM_MAKEFLAGS) check \
+ && $(MAKE) $(AM_MAKEFLAGS) install \
+ && $(MAKE) $(AM_MAKEFLAGS) installcheck \
+ && $(MAKE) $(AM_MAKEFLAGS) uninstall \
+ && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \
+ distuninstallcheck \
+ && chmod -R a-w "$$dc_install_base" \
+ && ({ \
+ (cd ../.. && umask 077 && mkdir "$$dc_destdir") \
+ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \
+ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \
+ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \
+ distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \
+ } || { rm -rf "$$dc_destdir"; exit 1; }) \
+ && rm -rf "$$dc_destdir" \
+ && $(MAKE) $(AM_MAKEFLAGS) dist \
+ && rm -rf $(DIST_ARCHIVES) \
+ && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \
+ && cd "$$am__cwd" \
+ || exit 1
+ $(am__remove_distdir)
+ @(echo "$(distdir) archives ready for distribution: "; \
+ list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \
+ sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x'
+distuninstallcheck:
+ @$(am__cd) '$(distuninstallcheck_dir)' \
+ && test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \
+ || { echo "ERROR: files left after uninstall:" ; \
+ if test -n "$(DESTDIR)"; then \
+ echo " (check DESTDIR support)"; \
+ fi ; \
+ $(distuninstallcheck_listfiles) ; \
+ exit 1; } >&2
+distcleancheck: distclean
+ @if test '$(srcdir)' = . ; then \
+ echo "ERROR: distcleancheck can only run from a VPATH build" ; \
+ exit 1 ; \
+ fi
+ @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \
+ || { echo "ERROR: files left in build directory after distclean:" ; \
+ $(distcleancheck_listfiles) ; \
+ exit 1; } >&2
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(HEADERS)
+installdirs:
+ for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(includedir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+@RUN_LDCONFIG_FALSE@install-exec-hook:
+clean: clean-am
+
+clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f $(am__CONFIG_DISTCLEAN_FILES)
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-libtool distclean-local distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-includeHEADERS
+ @$(NORMAL_INSTALL)
+ $(MAKE) $(AM_MAKEFLAGS) install-data-hook
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-libLTLIBRARIES
+ @$(NORMAL_INSTALL)
+ $(MAKE) $(AM_MAKEFLAGS) install-exec-hook
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f $(am__CONFIG_DISTCLEAN_FILES)
+ -rm -rf $(top_srcdir)/autom4te.cache
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-includeHEADERS uninstall-libLTLIBRARIES
+
+.MAKE: install-am install-data-am install-exec-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am am--refresh check check-am clean \
+ clean-generic clean-libLTLIBRARIES clean-libtool ctags dist \
+ dist-all dist-bzip2 dist-gzip dist-lzma dist-shar dist-tarZ \
+ dist-xz dist-zip distcheck distclean distclean-compile \
+ distclean-generic distclean-libtool distclean-local \
+ distclean-tags distcleancheck distdir distuninstallcheck dvi \
+ dvi-am html html-am info info-am install install-am \
+ install-data install-data-am install-data-hook install-dvi \
+ install-dvi-am install-exec install-exec-am install-exec-hook \
+ install-html install-html-am install-includeHEADERS \
+ install-info install-info-am install-libLTLIBRARIES \
+ install-man install-pdf install-pdf-am install-ps \
+ install-ps-am install-strip installcheck installcheck-am \
+ installdirs maintainer-clean maintainer-clean-generic \
+ mostlyclean mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool pdf pdf-am ps ps-am tags uninstall \
+ uninstall-am uninstall-includeHEADERS uninstall-libLTLIBRARIES
+
+
+distclean-local:
+ -rm -rf examples/.deps examples/Makefile
+@LABVIEW_TRUE@LABVIEW_CINTOOLS_PATH ?= /usr/local/natinst/LabVIEW-8.5/cintools
+
+@RUN_LDCONFIG_TRUE@install-exec-hook:
+@RUN_LDCONFIG_TRUE@ -$(LDCONFIG)
+
+install-data-hook:
+ if [ -e phidget21.jar ]; then install --owner=root --mode=755 -d $(DESTDIR)/usr/share/java; install --owner=root --mode=644 phidget21.jar $(DESTDIR)/usr/share/java; fi
+
+phidget21.h:
+ @echo "Making $@"
+ @cat cppheader > $@
+ @$(CC) -g -E -P $(PHIDGET21FLAGS) -D_LINUX -DEXTERNALPROTO -DREMOVE_DEPRECATED phidget21int.h | sed -e "s/extern \"C\" //g" >> $@
+ @cat cphidgetconstants.h >> $@
+ @cat cppfooter >> $@
+
+phidget21matlab.h:
+ @echo "Making $@"
+ @echo "/*" > $@
+ @echo " * Phidget21 Header for Matlab" >> $@
+ @echo " * -All pointers to structs have been changed to long, as Matlab seems" >> $@
+ @echo " * to be unhappy with either the undefined stucts or the double pointers." >> $@
+ @echo " */" >> $@
+ @$(CC) -g -E -P -D_LINUX -DEXTERNALPROTO -DREMOVE_DEPRECATED phidget21int.h | sed -e "s/extern \"C\" //g" | sed -e "s/struct [a-zA-Z_]* \*/long /" >> $@
+ @cat cphidgetconstants.h >> $@
+
+phidget21.jar:
+ @echo "Making $@"
+ @cd Java ; javac com/phidgets/*.java com/phidgets/event/*.java
+ @cd Java ; jar cf ../$@ com/phidgets/event/*.class com/phidgets/*.class
+
+deb:
+ @echo "Making Debian Packages"
+ @cp debian/changelog.template debian/changelog
+ @sed -i s/"VERSION"/"$(PACKAGE_VERSION)"/ debian/changelog
+ @sed -i s/"DATE"/"$(shell date +"%a, %d %b %Y %T %z")"/ debian/changelog
+ @if [ -z "$(DPKG_ARCH)" ]; then dpkg-buildpackage -us -uc; else dpkg-buildpackage -us -uc -a$(DPKG_ARCH); fi
+
+jni: all
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/NEWS b/NEWS
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/NEWS
diff --git a/README b/README
new file mode 100644
index 0000000..af610ab
--- /dev/null
+++ b/README
@@ -0,0 +1,160 @@
+ Phidgets for Linux
+ Version 2.1.8, 22 February 2011
+
+Installation
+============
+
+ ./configure; make; make install
+
+ This installs the library libphidget21.so and the header phidget21.h.
+Java support is compiled in by default, as well as support for Avahi
+zeroconf if it is available.
+
+ *Note: USB devices are by default only usable by root in Linux.
+ Install udev/hotplug scripts to use Phidgets from a normal
+ user account (see below).
+
+Requirements
+============
+
+libusb 0.1
+
+ This is generally already installed. The libusb dev files may need to
+be installed - this is usually a package called libusb-dev.
+
+ Some embedded systems / older distros may need to manually set up
+the userspace USB device tree. Usually this is handled by udev and
+exists in /dev/bus/usb. This can also be handled by mounting usbfs in
+fstab, which shows up in /proc/bus/usb.
+
+Options
+=======
+
+ Configure options:
+
+ To disable Java support:
+
+ ./configure --disable-jni
+
+ To use mdnsresponder instead of avahi for zeroconf:
+
+ ./configure --enable-zeroconf=bonjour
+
+ To disable zeroconf completely:
+
+ ./configure --disable-zeroconf
+
+ To use built-ins for .local lookup:
+
+ ./configure --enable-zeroconf-lookup
+
+ To enable LabVIEW support:
+
+ ./configure --enable-labview
+ make LABVIEW_CINTOOLS_PATH=/usr/local/natinst/LabVIEW-2010/cintools
+
+ Note: replace 'LabVIEW-2010' with your version
+
+Usage
+=====
+
+ Compile your projects with -lphidget21 and include phidget21.h in the
+source file.
+
+Java
+====
+
+ Java support is compiled in by default - 'make jni' is no longer
+required. This support is provided via JNI extentions compiled into
+libphidget21.so.
+
+ To disable Java support, configure with the --disable-jni option.
+
+ The libphidget21.so install path may need to be manually specified
+in order for Java to find the library, there are two ways to do this;
+either specify in an environment variable:
+
+ LD_LIBRARY_PATH=/usr/lib
+
+ Or specify on the Java command line:
+
+ java -Djava.library.path=/usr/lib some_java_app
+
+ Note that the /usr install prefix can be changed during the configure
+step by specifying --prefix.
+
+ phidget21.jar is the java half of the Phidgets->Java interface. This
+library can be downloaded from the website, or built from source:
+
+ make phidget21.jar
+
+ You must use a phidget21.jar that was built from the same phidget21
+library as you have installed or you will get errors.
+
+Hotplug / udev
+==============
+
+ On linux, by default, USB devices are not writeable by anybody but
+root.
+
+ On modern systems (kernel > 2.6.7), this is solved with a udev
+ruleset. This is the ideal solution.
+
+ On older systems, this can be solved with a hotplug script.
+
+udev
+====
+
+ The udev rules file will make all phidgets world writeable (mode 666)
+as soon as they are attached. Note that some systems may already have
+generic USB rulesets defined. The udev rules are run in order from
+smallest to largest number - the Phidgets rules, at number 99, should
+be high enough so that any USB rules will be overridden.
+
+ To Install:
+
+ cp udev/99-phidgets.rules /etc/udev/rules.d
+
+Hotplug
+=======
+
+ A hotplug script has been included that will make phidgets writeable
+when the are plugged in.
+
+ Because of this, there can sometimes be an issue accessing/opening a
+device as soon as it is plugged in, before the hotplug script has run to
+make it accesible. In this case you will see an error 4: "A phidget
+matching the type and or serial number could not be found."
+
+ Never rely on the hotplug scripts it you're using the phidget manager
+to open or access devices as soon as they appear as this will sometimes
+fail.
+
+ To Install:
+
+ cp hotplug/* /etc/hotplug/usb
+ chmod 755 /etc/hotplug/usb/phidgets
+
+Examples
+========
+
+ There are three examples in the examples directory. manager is just a
+simple program that will list all phidgets attached to the system, as
+they are plugged in or removed. ifkit connects to an interface kit and
+displays changes, while setting outputs. phidgetsbclist lists all SBCs
+on the network (requires seroconf support).
+
+ There is also a seperate download avialable with C examples for most
+phidgets, on the phdigets.com website.
+
+FreeBSD
+=======
+
+ The library has been tested with FreeBSD 8.1 and found to work.
+The configure/make/make install can be run unmodified.
+
+ When compiling binaries that include libphidget21, the -pthread
+flag must be passed to the compiler, because the threading functions
+are part of the C library, unlike on Linux.
+
+ gcc example.c -lphidget21 -pthread -o example \ No newline at end of file
diff --git a/aclocal.m4 b/aclocal.m4
new file mode 100644
index 0000000..dc5cc1a
--- /dev/null
+++ b/aclocal.m4
@@ -0,0 +1,8943 @@
+# generated automatically by aclocal 1.11 -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+# 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+m4_ifndef([AC_AUTOCONF_VERSION],
+ [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
+m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.64],,
+[m4_warning([this file was generated for autoconf 2.64.
+You have another version of autoconf. It may work, but is not guaranteed to.
+If you have problems, you may need to regenerate the build system entirely.
+To do so, use the procedure documented by the package, typically `autoreconf'.])])
+
+# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*-
+#
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005,
+# 2006, 2007, 2008 Free Software Foundation, Inc.
+# Written by Gordon Matzigkeit, 1996
+#
+# This file is free software; the Free Software Foundation gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+
+m4_define([_LT_COPYING], [dnl
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005,
+# 2006, 2007, 2008 Free Software Foundation, Inc.
+# Written by Gordon Matzigkeit, 1996
+#
+# This file is part of GNU Libtool.
+#
+# GNU Libtool is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# As a special exception to the GNU General Public License,
+# if you distribute this file as part of a program or library that
+# is built using GNU Libtool, you may include this file under the
+# same distribution terms that you use for the rest of that program.
+#
+# GNU Libtool is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Libtool; see the file COPYING. If not, a copy
+# can be downloaded from http://www.gnu.org/licenses/gpl.html, or
+# obtained by writing to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+])
+
+# serial 56 LT_INIT
+
+
+# LT_PREREQ(VERSION)
+# ------------------
+# Complain and exit if this libtool version is less that VERSION.
+m4_defun([LT_PREREQ],
+[m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1,
+ [m4_default([$3],
+ [m4_fatal([Libtool version $1 or higher is required],
+ 63)])],
+ [$2])])
+
+
+# _LT_CHECK_BUILDDIR
+# ------------------
+# Complain if the absolute build directory name contains unusual characters
+m4_defun([_LT_CHECK_BUILDDIR],
+[case `pwd` in
+ *\ * | *\ *)
+ AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;;
+esac
+])
+
+
+# LT_INIT([OPTIONS])
+# ------------------
+AC_DEFUN([LT_INIT],
+[AC_PREREQ([2.58])dnl We use AC_INCLUDES_DEFAULT
+AC_BEFORE([$0], [LT_LANG])dnl
+AC_BEFORE([$0], [LT_OUTPUT])dnl
+AC_BEFORE([$0], [LTDL_INIT])dnl
+m4_require([_LT_CHECK_BUILDDIR])dnl
+
+dnl Autoconf doesn't catch unexpanded LT_ macros by default:
+m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl
+m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl
+dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4
+dnl unless we require an AC_DEFUNed macro:
+AC_REQUIRE([LTOPTIONS_VERSION])dnl
+AC_REQUIRE([LTSUGAR_VERSION])dnl
+AC_REQUIRE([LTVERSION_VERSION])dnl
+AC_REQUIRE([LTOBSOLETE_VERSION])dnl
+m4_require([_LT_PROG_LTMAIN])dnl
+
+dnl Parse OPTIONS
+_LT_SET_OPTIONS([$0], [$1])
+
+# This can be used to rebuild libtool when needed
+LIBTOOL_DEPS="$ltmain"
+
+# Always use our own libtool.
+LIBTOOL='$(SHELL) $(top_builddir)/libtool'
+AC_SUBST(LIBTOOL)dnl
+
+_LT_SETUP
+
+# Only expand once:
+m4_define([LT_INIT])
+])# LT_INIT
+
+# Old names:
+AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT])
+AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_PROG_LIBTOOL], [])
+dnl AC_DEFUN([AM_PROG_LIBTOOL], [])
+
+
+# _LT_CC_BASENAME(CC)
+# -------------------
+# Calculate cc_basename. Skip known compiler wrappers and cross-prefix.
+m4_defun([_LT_CC_BASENAME],
+[for cc_temp in $1""; do
+ case $cc_temp in
+ compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;;
+ distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;;
+ \-*) ;;
+ *) break;;
+ esac
+done
+cc_basename=`$ECHO "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
+])
+
+
+# _LT_FILEUTILS_DEFAULTS
+# ----------------------
+# It is okay to use these file commands and assume they have been set
+# sensibly after `m4_require([_LT_FILEUTILS_DEFAULTS])'.
+m4_defun([_LT_FILEUTILS_DEFAULTS],
+[: ${CP="cp -f"}
+: ${MV="mv -f"}
+: ${RM="rm -f"}
+])# _LT_FILEUTILS_DEFAULTS
+
+
+# _LT_SETUP
+# ---------
+m4_defun([_LT_SETUP],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_CANONICAL_BUILD])dnl
+_LT_DECL([], [host_alias], [0], [The host system])dnl
+_LT_DECL([], [host], [0])dnl
+_LT_DECL([], [host_os], [0])dnl
+dnl
+_LT_DECL([], [build_alias], [0], [The build system])dnl
+_LT_DECL([], [build], [0])dnl
+_LT_DECL([], [build_os], [0])dnl
+dnl
+AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([LT_PATH_LD])dnl
+AC_REQUIRE([LT_PATH_NM])dnl
+dnl
+AC_REQUIRE([AC_PROG_LN_S])dnl
+test -z "$LN_S" && LN_S="ln -s"
+_LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl
+dnl
+AC_REQUIRE([LT_CMD_MAX_LEN])dnl
+_LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl
+_LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl
+dnl
+m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_CHECK_SHELL_FEATURES])dnl
+m4_require([_LT_CMD_RELOAD])dnl
+m4_require([_LT_CHECK_MAGIC_METHOD])dnl
+m4_require([_LT_CMD_OLD_ARCHIVE])dnl
+m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl
+
+_LT_CONFIG_LIBTOOL_INIT([
+# See if we are running on zsh, and set the options which allow our
+# commands through without removal of \ escapes INIT.
+if test -n "\${ZSH_VERSION+set}" ; then
+ setopt NO_GLOB_SUBST
+fi
+])
+if test -n "${ZSH_VERSION+set}" ; then
+ setopt NO_GLOB_SUBST
+fi
+
+_LT_CHECK_OBJDIR
+
+m4_require([_LT_TAG_COMPILER])dnl
+_LT_PROG_ECHO_BACKSLASH
+
+case $host_os in
+aix3*)
+ # AIX sometimes has problems with the GCC collect2 program. For some
+ # reason, if we set the COLLECT_NAMES environment variable, the problems
+ # vanish in a puff of smoke.
+ if test "X${COLLECT_NAMES+set}" != Xset; then
+ COLLECT_NAMES=
+ export COLLECT_NAMES
+ fi
+ ;;
+esac
+
+# Sed substitution that helps us do robust quoting. It backslashifies
+# metacharacters that are still active within double-quoted strings.
+sed_quote_subst='s/\([["`$\\]]\)/\\\1/g'
+
+# Same as above, but do not quote variable references.
+double_quote_subst='s/\([["`\\]]\)/\\\1/g'
+
+# Sed substitution to delay expansion of an escaped shell variable in a
+# double_quote_subst'ed string.
+delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
+
+# Sed substitution to delay expansion of an escaped single quote.
+delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g'
+
+# Sed substitution to avoid accidental globbing in evaled expressions
+no_glob_subst='s/\*/\\\*/g'
+
+# Global variables:
+ofile=libtool
+can_build_shared=yes
+
+# All known linkers require a `.a' archive for static linking (except MSVC,
+# which needs '.lib').
+libext=a
+
+with_gnu_ld="$lt_cv_prog_gnu_ld"
+
+old_CC="$CC"
+old_CFLAGS="$CFLAGS"
+
+# Set sane defaults for various variables
+test -z "$CC" && CC=cc
+test -z "$LTCC" && LTCC=$CC
+test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS
+test -z "$LD" && LD=ld
+test -z "$ac_objext" && ac_objext=o
+
+_LT_CC_BASENAME([$compiler])
+
+# Only perform the check for file, if the check method requires it
+test -z "$MAGIC_CMD" && MAGIC_CMD=file
+case $deplibs_check_method in
+file_magic*)
+ if test "$file_magic_cmd" = '$MAGIC_CMD'; then
+ _LT_PATH_MAGIC
+ fi
+ ;;
+esac
+
+# Use C for the default configuration in the libtool script
+LT_SUPPORTED_TAG([CC])
+_LT_LANG_C_CONFIG
+_LT_LANG_DEFAULT_CONFIG
+_LT_CONFIG_COMMANDS
+])# _LT_SETUP
+
+
+# _LT_PROG_LTMAIN
+# ---------------
+# Note that this code is called both from `configure', and `config.status'
+# now that we use AC_CONFIG_COMMANDS to generate libtool. Notably,
+# `config.status' has no value for ac_aux_dir unless we are using Automake,
+# so we pass a copy along to make sure it has a sensible value anyway.
+m4_defun([_LT_PROG_LTMAIN],
+[m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl
+_LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir'])
+ltmain="$ac_aux_dir/ltmain.sh"
+])# _LT_PROG_LTMAIN
+
+
+
+# So that we can recreate a full libtool script including additional
+# tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS
+# in macros and then make a single call at the end using the `libtool'
+# label.
+
+
+# _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS])
+# ----------------------------------------
+# Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later.
+m4_define([_LT_CONFIG_LIBTOOL_INIT],
+[m4_ifval([$1],
+ [m4_append([_LT_OUTPUT_LIBTOOL_INIT],
+ [$1
+])])])
+
+# Initialize.
+m4_define([_LT_OUTPUT_LIBTOOL_INIT])
+
+
+# _LT_CONFIG_LIBTOOL([COMMANDS])
+# ------------------------------
+# Register COMMANDS to be passed to AC_CONFIG_COMMANDS later.
+m4_define([_LT_CONFIG_LIBTOOL],
+[m4_ifval([$1],
+ [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS],
+ [$1
+])])])
+
+# Initialize.
+m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS])
+
+
+# _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS])
+# -----------------------------------------------------
+m4_defun([_LT_CONFIG_SAVE_COMMANDS],
+[_LT_CONFIG_LIBTOOL([$1])
+_LT_CONFIG_LIBTOOL_INIT([$2])
+])
+
+
+# _LT_FORMAT_COMMENT([COMMENT])
+# -----------------------------
+# Add leading comment marks to the start of each line, and a trailing
+# full-stop to the whole comment if one is not present already.
+m4_define([_LT_FORMAT_COMMENT],
+[m4_ifval([$1], [
+m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])],
+ [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.])
+)])
+
+
+
+
+
+# _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?])
+# -------------------------------------------------------------------
+# CONFIGNAME is the name given to the value in the libtool script.
+# VARNAME is the (base) name used in the configure script.
+# VALUE may be 0, 1 or 2 for a computed quote escaped value based on
+# VARNAME. Any other value will be used directly.
+m4_define([_LT_DECL],
+[lt_if_append_uniq([lt_decl_varnames], [$2], [, ],
+ [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name],
+ [m4_ifval([$1], [$1], [$2])])
+ lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3])
+ m4_ifval([$4],
+ [lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])])
+ lt_dict_add_subkey([lt_decl_dict], [$2],
+ [tagged?], [m4_ifval([$5], [yes], [no])])])
+])
+
+
+# _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION])
+# --------------------------------------------------------
+m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])])
+
+
+# lt_decl_tag_varnames([SEPARATOR], [VARNAME1...])
+# ------------------------------------------------
+m4_define([lt_decl_tag_varnames],
+[_lt_decl_filter([tagged?], [yes], $@)])
+
+
+# _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..])
+# ---------------------------------------------------------
+m4_define([_lt_decl_filter],
+[m4_case([$#],
+ [0], [m4_fatal([$0: too few arguments: $#])],
+ [1], [m4_fatal([$0: too few arguments: $#: $1])],
+ [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)],
+ [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)],
+ [lt_dict_filter([lt_decl_dict], $@)])[]dnl
+])
+
+
+# lt_decl_quote_varnames([SEPARATOR], [VARNAME1...])
+# --------------------------------------------------
+m4_define([lt_decl_quote_varnames],
+[_lt_decl_filter([value], [1], $@)])
+
+
+# lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...])
+# ---------------------------------------------------
+m4_define([lt_decl_dquote_varnames],
+[_lt_decl_filter([value], [2], $@)])
+
+
+# lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...])
+# ---------------------------------------------------
+m4_define([lt_decl_varnames_tagged],
+[m4_assert([$# <= 2])dnl
+_$0(m4_quote(m4_default([$1], [[, ]])),
+ m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]),
+ m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))])
+m4_define([_lt_decl_varnames_tagged],
+[m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])])
+
+
+# lt_decl_all_varnames([SEPARATOR], [VARNAME1...])
+# ------------------------------------------------
+m4_define([lt_decl_all_varnames],
+[_$0(m4_quote(m4_default([$1], [[, ]])),
+ m4_if([$2], [],
+ m4_quote(lt_decl_varnames),
+ m4_quote(m4_shift($@))))[]dnl
+])
+m4_define([_lt_decl_all_varnames],
+[lt_join($@, lt_decl_varnames_tagged([$1],
+ lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl
+])
+
+
+# _LT_CONFIG_STATUS_DECLARE([VARNAME])
+# ------------------------------------
+# Quote a variable value, and forward it to `config.status' so that its
+# declaration there will have the same value as in `configure'. VARNAME
+# must have a single quote delimited value for this to work.
+m4_define([_LT_CONFIG_STATUS_DECLARE],
+[$1='`$ECHO "X$][$1" | $Xsed -e "$delay_single_quote_subst"`'])
+
+
+# _LT_CONFIG_STATUS_DECLARATIONS
+# ------------------------------
+# We delimit libtool config variables with single quotes, so when
+# we write them to config.status, we have to be sure to quote all
+# embedded single quotes properly. In configure, this macro expands
+# each variable declared with _LT_DECL (and _LT_TAGDECL) into:
+#
+# <var>='`$ECHO "X$<var>" | $Xsed -e "$delay_single_quote_subst"`'
+m4_defun([_LT_CONFIG_STATUS_DECLARATIONS],
+[m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames),
+ [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])])
+
+
+# _LT_LIBTOOL_TAGS
+# ----------------
+# Output comment and list of tags supported by the script
+m4_defun([_LT_LIBTOOL_TAGS],
+[_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl
+available_tags="_LT_TAGS"dnl
+])
+
+
+# _LT_LIBTOOL_DECLARE(VARNAME, [TAG])
+# -----------------------------------
+# Extract the dictionary values for VARNAME (optionally with TAG) and
+# expand to a commented shell variable setting:
+#
+# # Some comment about what VAR is for.
+# visible_name=$lt_internal_name
+m4_define([_LT_LIBTOOL_DECLARE],
+[_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1],
+ [description])))[]dnl
+m4_pushdef([_libtool_name],
+ m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl
+m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])),
+ [0], [_libtool_name=[$]$1],
+ [1], [_libtool_name=$lt_[]$1],
+ [2], [_libtool_name=$lt_[]$1],
+ [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl
+m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl
+])
+
+
+# _LT_LIBTOOL_CONFIG_VARS
+# -----------------------
+# Produce commented declarations of non-tagged libtool config variables
+# suitable for insertion in the LIBTOOL CONFIG section of the `libtool'
+# script. Tagged libtool config variables (even for the LIBTOOL CONFIG
+# section) are produced by _LT_LIBTOOL_TAG_VARS.
+m4_defun([_LT_LIBTOOL_CONFIG_VARS],
+[m4_foreach([_lt_var],
+ m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)),
+ [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])])
+
+
+# _LT_LIBTOOL_TAG_VARS(TAG)
+# -------------------------
+m4_define([_LT_LIBTOOL_TAG_VARS],
+[m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames),
+ [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])])
+
+
+# _LT_TAGVAR(VARNAME, [TAGNAME])
+# ------------------------------
+m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])])
+
+
+# _LT_CONFIG_COMMANDS
+# -------------------
+# Send accumulated output to $CONFIG_STATUS. Thanks to the lists of
+# variables for single and double quote escaping we saved from calls
+# to _LT_DECL, we can put quote escaped variables declarations
+# into `config.status', and then the shell code to quote escape them in
+# for loops in `config.status'. Finally, any additional code accumulated
+# from calls to _LT_CONFIG_LIBTOOL_INIT is expanded.
+m4_defun([_LT_CONFIG_COMMANDS],
+[AC_PROVIDE_IFELSE([LT_OUTPUT],
+ dnl If the libtool generation code has been placed in $CONFIG_LT,
+ dnl instead of duplicating it all over again into config.status,
+ dnl then we will have config.status run $CONFIG_LT later, so it
+ dnl needs to know what name is stored there:
+ [AC_CONFIG_COMMANDS([libtool],
+ [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])],
+ dnl If the libtool generation code is destined for config.status,
+ dnl expand the accumulated commands and init code now:
+ [AC_CONFIG_COMMANDS([libtool],
+ [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])])
+])#_LT_CONFIG_COMMANDS
+
+
+# Initialize.
+m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT],
+[
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+sed_quote_subst='$sed_quote_subst'
+double_quote_subst='$double_quote_subst'
+delay_variable_subst='$delay_variable_subst'
+_LT_CONFIG_STATUS_DECLARATIONS
+LTCC='$LTCC'
+LTCFLAGS='$LTCFLAGS'
+compiler='$compiler_DEFAULT'
+
+# Quote evaled strings.
+for var in lt_decl_all_varnames([[ \
+]], lt_decl_quote_varnames); do
+ case \`eval \\\\\$ECHO "X\\\\\$\$var"\` in
+ *[[\\\\\\\`\\"\\\$]]*)
+ eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"X\\\$\$var\\" | \\\$Xsed -e \\"\\\$sed_quote_subst\\"\\\`\\\\\\""
+ ;;
+ *)
+ eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
+ ;;
+ esac
+done
+
+# Double-quote double-evaled strings.
+for var in lt_decl_all_varnames([[ \
+]], lt_decl_dquote_varnames); do
+ case \`eval \\\\\$ECHO "X\\\\\$\$var"\` in
+ *[[\\\\\\\`\\"\\\$]]*)
+ eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"X\\\$\$var\\" | \\\$Xsed -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\""
+ ;;
+ *)
+ eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
+ ;;
+ esac
+done
+
+# Fix-up fallback echo if it was mangled by the above quoting rules.
+case \$lt_ECHO in
+*'\\\[$]0 --fallback-echo"')dnl "
+ lt_ECHO=\`\$ECHO "X\$lt_ECHO" | \$Xsed -e 's/\\\\\\\\\\\\\\\[$]0 --fallback-echo"\[$]/\[$]0 --fallback-echo"/'\`
+ ;;
+esac
+
+_LT_OUTPUT_LIBTOOL_INIT
+])
+
+
+# LT_OUTPUT
+# ---------
+# This macro allows early generation of the libtool script (before
+# AC_OUTPUT is called), incase it is used in configure for compilation
+# tests.
+AC_DEFUN([LT_OUTPUT],
+[: ${CONFIG_LT=./config.lt}
+AC_MSG_NOTICE([creating $CONFIG_LT])
+cat >"$CONFIG_LT" <<_LTEOF
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate a libtool stub with the current configuration.
+
+lt_cl_silent=false
+SHELL=\${CONFIG_SHELL-$SHELL}
+_LTEOF
+
+cat >>"$CONFIG_LT" <<\_LTEOF
+AS_SHELL_SANITIZE
+_AS_PREPARE
+
+exec AS_MESSAGE_FD>&1
+exec AS_MESSAGE_LOG_FD>>config.log
+{
+ echo
+ AS_BOX([Running $as_me.])
+} >&AS_MESSAGE_LOG_FD
+
+lt_cl_help="\
+\`$as_me' creates a local libtool stub from the current configuration,
+for use in further configure time tests before the real libtool is
+generated.
+
+Usage: $[0] [[OPTIONS]]
+
+ -h, --help print this help, then exit
+ -V, --version print version number, then exit
+ -q, --quiet do not print progress messages
+ -d, --debug don't remove temporary files
+
+Report bugs to <bug-libtool@gnu.org>."
+
+lt_cl_version="\
+m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl
+m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION])
+configured by $[0], generated by m4_PACKAGE_STRING.
+
+Copyright (C) 2008 Free Software Foundation, Inc.
+This config.lt script is free software; the Free Software Foundation
+gives unlimited permision to copy, distribute and modify it."
+
+while test $[#] != 0
+do
+ case $[1] in
+ --version | --v* | -V )
+ echo "$lt_cl_version"; exit 0 ;;
+ --help | --h* | -h )
+ echo "$lt_cl_help"; exit 0 ;;
+ --debug | --d* | -d )
+ debug=: ;;
+ --quiet | --q* | --silent | --s* | -q )
+ lt_cl_silent=: ;;
+
+ -*) AC_MSG_ERROR([unrecognized option: $[1]
+Try \`$[0] --help' for more information.]) ;;
+
+ *) AC_MSG_ERROR([unrecognized argument: $[1]
+Try \`$[0] --help' for more information.]) ;;
+ esac
+ shift
+done
+
+if $lt_cl_silent; then
+ exec AS_MESSAGE_FD>/dev/null
+fi
+_LTEOF
+
+cat >>"$CONFIG_LT" <<_LTEOF
+_LT_OUTPUT_LIBTOOL_COMMANDS_INIT
+_LTEOF
+
+cat >>"$CONFIG_LT" <<\_LTEOF
+AC_MSG_NOTICE([creating $ofile])
+_LT_OUTPUT_LIBTOOL_COMMANDS
+AS_EXIT(0)
+_LTEOF
+chmod +x "$CONFIG_LT"
+
+# configure is writing to config.log, but config.lt does its own redirection,
+# appending to config.log, which fails on DOS, as config.log is still kept
+# open by configure. Here we exec the FD to /dev/null, effectively closing
+# config.log, so it can be properly (re)opened and appended to by config.lt.
+if test "$no_create" != yes; then
+ lt_cl_success=:
+ test "$silent" = yes &&
+ lt_config_lt_args="$lt_config_lt_args --quiet"
+ exec AS_MESSAGE_LOG_FD>/dev/null
+ $SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false
+ exec AS_MESSAGE_LOG_FD>>config.log
+ $lt_cl_success || AS_EXIT(1)
+fi
+])# LT_OUTPUT
+
+
+# _LT_CONFIG(TAG)
+# ---------------
+# If TAG is the built-in tag, create an initial libtool script with a
+# default configuration from the untagged config vars. Otherwise add code
+# to config.status for appending the configuration named by TAG from the
+# matching tagged config vars.
+m4_defun([_LT_CONFIG],
+[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+_LT_CONFIG_SAVE_COMMANDS([
+ m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl
+ m4_if(_LT_TAG, [C], [
+ # See if we are running on zsh, and set the options which allow our
+ # commands through without removal of \ escapes.
+ if test -n "${ZSH_VERSION+set}" ; then
+ setopt NO_GLOB_SUBST
+ fi
+
+ cfgfile="${ofile}T"
+ trap "$RM \"$cfgfile\"; exit 1" 1 2 15
+ $RM "$cfgfile"
+
+ cat <<_LT_EOF >> "$cfgfile"
+#! $SHELL
+
+# `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services.
+# Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+# NOTE: Changes made to this file will be lost: look at ltmain.sh.
+#
+_LT_COPYING
+_LT_LIBTOOL_TAGS
+
+# ### BEGIN LIBTOOL CONFIG
+_LT_LIBTOOL_CONFIG_VARS
+_LT_LIBTOOL_TAG_VARS
+# ### END LIBTOOL CONFIG
+
+_LT_EOF
+
+ case $host_os in
+ aix3*)
+ cat <<\_LT_EOF >> "$cfgfile"
+# AIX sometimes has problems with the GCC collect2 program. For some
+# reason, if we set the COLLECT_NAMES environment variable, the problems
+# vanish in a puff of smoke.
+if test "X${COLLECT_NAMES+set}" != Xset; then
+ COLLECT_NAMES=
+ export COLLECT_NAMES
+fi
+_LT_EOF
+ ;;
+ esac
+
+ _LT_PROG_LTMAIN
+
+ # We use sed instead of cat because bash on DJGPP gets confused if
+ # if finds mixed CR/LF and LF-only lines. Since sed operates in
+ # text mode, it properly converts lines to CR/LF. This bash problem
+ # is reportedly fixed, but why not run on old versions too?
+ sed '/^# Generated shell functions inserted here/q' "$ltmain" >> "$cfgfile" \
+ || (rm -f "$cfgfile"; exit 1)
+
+ _LT_PROG_XSI_SHELLFNS
+
+ sed -n '/^# Generated shell functions inserted here/,$p' "$ltmain" >> "$cfgfile" \
+ || (rm -f "$cfgfile"; exit 1)
+
+ mv -f "$cfgfile" "$ofile" ||
+ (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile")
+ chmod +x "$ofile"
+],
+[cat <<_LT_EOF >> "$ofile"
+
+dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded
+dnl in a comment (ie after a #).
+# ### BEGIN LIBTOOL TAG CONFIG: $1
+_LT_LIBTOOL_TAG_VARS(_LT_TAG)
+# ### END LIBTOOL TAG CONFIG: $1
+_LT_EOF
+])dnl /m4_if
+],
+[m4_if([$1], [], [
+ PACKAGE='$PACKAGE'
+ VERSION='$VERSION'
+ TIMESTAMP='$TIMESTAMP'
+ RM='$RM'
+ ofile='$ofile'], [])
+])dnl /_LT_CONFIG_SAVE_COMMANDS
+])# _LT_CONFIG
+
+
+# LT_SUPPORTED_TAG(TAG)
+# ---------------------
+# Trace this macro to discover what tags are supported by the libtool
+# --tag option, using:
+# autoconf --trace 'LT_SUPPORTED_TAG:$1'
+AC_DEFUN([LT_SUPPORTED_TAG], [])
+
+
+# C support is built-in for now
+m4_define([_LT_LANG_C_enabled], [])
+m4_define([_LT_TAGS], [])
+
+
+# LT_LANG(LANG)
+# -------------
+# Enable libtool support for the given language if not already enabled.
+AC_DEFUN([LT_LANG],
+[AC_BEFORE([$0], [LT_OUTPUT])dnl
+m4_case([$1],
+ [C], [_LT_LANG(C)],
+ [C++], [_LT_LANG(CXX)],
+ [Java], [_LT_LANG(GCJ)],
+ [Fortran 77], [_LT_LANG(F77)],
+ [Fortran], [_LT_LANG(FC)],
+ [Windows Resource], [_LT_LANG(RC)],
+ [m4_ifdef([_LT_LANG_]$1[_CONFIG],
+ [_LT_LANG($1)],
+ [m4_fatal([$0: unsupported language: "$1"])])])dnl
+])# LT_LANG
+
+
+# _LT_LANG(LANGNAME)
+# ------------------
+m4_defun([_LT_LANG],
+[m4_ifdef([_LT_LANG_]$1[_enabled], [],
+ [LT_SUPPORTED_TAG([$1])dnl
+ m4_append([_LT_TAGS], [$1 ])dnl
+ m4_define([_LT_LANG_]$1[_enabled], [])dnl
+ _LT_LANG_$1_CONFIG($1)])dnl
+])# _LT_LANG
+
+
+# _LT_LANG_DEFAULT_CONFIG
+# -----------------------
+m4_defun([_LT_LANG_DEFAULT_CONFIG],
+[AC_PROVIDE_IFELSE([AC_PROG_CXX],
+ [LT_LANG(CXX)],
+ [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])])
+
+AC_PROVIDE_IFELSE([AC_PROG_F77],
+ [LT_LANG(F77)],
+ [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])])
+
+AC_PROVIDE_IFELSE([AC_PROG_FC],
+ [LT_LANG(FC)],
+ [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])])
+
+dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal
+dnl pulling things in needlessly.
+AC_PROVIDE_IFELSE([AC_PROG_GCJ],
+ [LT_LANG(GCJ)],
+ [AC_PROVIDE_IFELSE([A][M_PROG_GCJ],
+ [LT_LANG(GCJ)],
+ [AC_PROVIDE_IFELSE([LT_PROG_GCJ],
+ [LT_LANG(GCJ)],
+ [m4_ifdef([AC_PROG_GCJ],
+ [m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])])
+ m4_ifdef([A][M_PROG_GCJ],
+ [m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])])
+ m4_ifdef([LT_PROG_GCJ],
+ [m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])])
+
+AC_PROVIDE_IFELSE([LT_PROG_RC],
+ [LT_LANG(RC)],
+ [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])])
+])# _LT_LANG_DEFAULT_CONFIG
+
+# Obsolete macros:
+AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)])
+AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)])
+AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)])
+AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_CXX], [])
+dnl AC_DEFUN([AC_LIBTOOL_F77], [])
+dnl AC_DEFUN([AC_LIBTOOL_FC], [])
+dnl AC_DEFUN([AC_LIBTOOL_GCJ], [])
+
+
+# _LT_TAG_COMPILER
+# ----------------
+m4_defun([_LT_TAG_COMPILER],
+[AC_REQUIRE([AC_PROG_CC])dnl
+
+_LT_DECL([LTCC], [CC], [1], [A C compiler])dnl
+_LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl
+_LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl
+_LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+])# _LT_TAG_COMPILER
+
+
+# _LT_COMPILER_BOILERPLATE
+# ------------------------
+# Check for compiler boilerplate output or warnings with
+# the simple compiler test code.
+m4_defun([_LT_COMPILER_BOILERPLATE],
+[m4_require([_LT_DECL_SED])dnl
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_compile_test_code" >conftest.$ac_ext
+eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_compiler_boilerplate=`cat conftest.err`
+$RM conftest*
+])# _LT_COMPILER_BOILERPLATE
+
+
+# _LT_LINKER_BOILERPLATE
+# ----------------------
+# Check for linker boilerplate output or warnings with
+# the simple link test code.
+m4_defun([_LT_LINKER_BOILERPLATE],
+[m4_require([_LT_DECL_SED])dnl
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_link_test_code" >conftest.$ac_ext
+eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_linker_boilerplate=`cat conftest.err`
+$RM -r conftest*
+])# _LT_LINKER_BOILERPLATE
+
+# _LT_REQUIRED_DARWIN_CHECKS
+# -------------------------
+m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[
+ case $host_os in
+ rhapsody* | darwin*)
+ AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:])
+ AC_CHECK_TOOL([NMEDIT], [nmedit], [:])
+ AC_CHECK_TOOL([LIPO], [lipo], [:])
+ AC_CHECK_TOOL([OTOOL], [otool], [:])
+ AC_CHECK_TOOL([OTOOL64], [otool64], [:])
+ _LT_DECL([], [DSYMUTIL], [1],
+ [Tool to manipulate archived DWARF debug symbol files on Mac OS X])
+ _LT_DECL([], [NMEDIT], [1],
+ [Tool to change global to local symbols on Mac OS X])
+ _LT_DECL([], [LIPO], [1],
+ [Tool to manipulate fat objects and archives on Mac OS X])
+ _LT_DECL([], [OTOOL], [1],
+ [ldd/readelf like tool for Mach-O binaries on Mac OS X])
+ _LT_DECL([], [OTOOL64], [1],
+ [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4])
+
+ AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod],
+ [lt_cv_apple_cc_single_mod=no
+ if test -z "${LT_MULTI_MODULE}"; then
+ # By default we will add the -single_module flag. You can override
+ # by either setting the environment variable LT_MULTI_MODULE
+ # non-empty at configure time, or by adding -multi_module to the
+ # link flags.
+ rm -rf libconftest.dylib*
+ echo "int foo(void){return 1;}" > conftest.c
+ echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
+-dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD
+ $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
+ -dynamiclib -Wl,-single_module conftest.c 2>conftest.err
+ _lt_result=$?
+ if test -f libconftest.dylib && test ! -s conftest.err && test $_lt_result = 0; then
+ lt_cv_apple_cc_single_mod=yes
+ else
+ cat conftest.err >&AS_MESSAGE_LOG_FD
+ fi
+ rm -rf libconftest.dylib*
+ rm -f conftest.*
+ fi])
+ AC_CACHE_CHECK([for -exported_symbols_list linker flag],
+ [lt_cv_ld_exported_symbols_list],
+ [lt_cv_ld_exported_symbols_list=no
+ save_LDFLAGS=$LDFLAGS
+ echo "_main" > conftest.sym
+ LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym"
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])],
+ [lt_cv_ld_exported_symbols_list=yes],
+ [lt_cv_ld_exported_symbols_list=no])
+ LDFLAGS="$save_LDFLAGS"
+ ])
+ case $host_os in
+ rhapsody* | darwin1.[[012]])
+ _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;;
+ darwin1.*)
+ _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;;
+ darwin*) # darwin 5.x on
+ # if running on 10.5 or later, the deployment target defaults
+ # to the OS version, if on x86, and 10.4, the deployment
+ # target defaults to 10.4. Don't you love it?
+ case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in
+ 10.0,*86*-darwin8*|10.0,*-darwin[[91]]*)
+ _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;;
+ 10.[[012]]*)
+ _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;;
+ 10.*)
+ _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;;
+ esac
+ ;;
+ esac
+ if test "$lt_cv_apple_cc_single_mod" = "yes"; then
+ _lt_dar_single_mod='$single_module'
+ fi
+ if test "$lt_cv_ld_exported_symbols_list" = "yes"; then
+ _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym'
+ else
+ _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ fi
+ if test "$DSYMUTIL" != ":"; then
+ _lt_dsymutil='~$DSYMUTIL $lib || :'
+ else
+ _lt_dsymutil=
+ fi
+ ;;
+ esac
+])
+
+
+# _LT_DARWIN_LINKER_FEATURES
+# --------------------------
+# Checks for linker and compiler features on darwin
+m4_defun([_LT_DARWIN_LINKER_FEATURES],
+[
+ m4_require([_LT_REQUIRED_DARWIN_CHECKS])
+ _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+ _LT_TAGVAR(hardcode_direct, $1)=no
+ _LT_TAGVAR(hardcode_automatic, $1)=yes
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
+ _LT_TAGVAR(whole_archive_flag_spec, $1)=''
+ _LT_TAGVAR(link_all_deplibs, $1)=yes
+ _LT_TAGVAR(allow_undefined_flag, $1)="$_lt_dar_allow_undefined"
+ case $cc_basename in
+ ifort*) _lt_dar_can_shared=yes ;;
+ *) _lt_dar_can_shared=$GCC ;;
+ esac
+ if test "$_lt_dar_can_shared" = "yes"; then
+ output_verbose_link_cmd=echo
+ _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}"
+ _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}"
+ _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}"
+ _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}"
+ m4_if([$1], [CXX],
+[ if test "$lt_cv_apple_cc_single_mod" != "yes"; then
+ _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dsymutil}"
+ _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dar_export_syms}${_lt_dsymutil}"
+ fi
+],[])
+ else
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+])
+
+# _LT_SYS_MODULE_PATH_AIX
+# -----------------------
+# Links a minimal program and checks the executable
+# for the system default hardcoded library path. In most cases,
+# this is /usr/lib:/lib, but when the MPI compilers are used
+# the location of the communication and MPI libs are included too.
+# If we don't find anything, use the default library path according
+# to the aix ld manual.
+m4_defun([_LT_SYS_MODULE_PATH_AIX],
+[m4_require([_LT_DECL_SED])dnl
+AC_LINK_IFELSE(AC_LANG_PROGRAM,[
+lt_aix_libpath_sed='
+ /Import File Strings/,/^$/ {
+ /^0/ {
+ s/^0 *\(.*\)$/\1/
+ p
+ }
+ }'
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then
+ aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+fi],[])
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+])# _LT_SYS_MODULE_PATH_AIX
+
+
+# _LT_SHELL_INIT(ARG)
+# -------------------
+m4_define([_LT_SHELL_INIT],
+[ifdef([AC_DIVERSION_NOTICE],
+ [AC_DIVERT_PUSH(AC_DIVERSION_NOTICE)],
+ [AC_DIVERT_PUSH(NOTICE)])
+$1
+AC_DIVERT_POP
+])# _LT_SHELL_INIT
+
+
+# _LT_PROG_ECHO_BACKSLASH
+# -----------------------
+# Add some code to the start of the generated configure script which
+# will find an echo command which doesn't interpret backslashes.
+m4_defun([_LT_PROG_ECHO_BACKSLASH],
+[_LT_SHELL_INIT([
+# Check that we are running under the correct shell.
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+case X$lt_ECHO in
+X*--fallback-echo)
+ # Remove one level of quotation (which was required for Make).
+ ECHO=`echo "$lt_ECHO" | sed 's,\\\\\[$]\\[$]0,'[$]0','`
+ ;;
+esac
+
+ECHO=${lt_ECHO-echo}
+if test "X[$]1" = X--no-reexec; then
+ # Discard the --no-reexec flag, and continue.
+ shift
+elif test "X[$]1" = X--fallback-echo; then
+ # Avoid inline document here, it may be left over
+ :
+elif test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' ; then
+ # Yippee, $ECHO works!
+ :
+else
+ # Restart under the correct shell.
+ exec $SHELL "[$]0" --no-reexec ${1+"[$]@"}
+fi
+
+if test "X[$]1" = X--fallback-echo; then
+ # used as fallback echo
+ shift
+ cat <<_LT_EOF
+[$]*
+_LT_EOF
+ exit 0
+fi
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+if test -z "$lt_ECHO"; then
+ if test "X${echo_test_string+set}" != Xset; then
+ # find a string as large as possible, as long as the shell can cope with it
+ for cmd in 'sed 50q "[$]0"' 'sed 20q "[$]0"' 'sed 10q "[$]0"' 'sed 2q "[$]0"' 'echo test'; do
+ # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ...
+ if { echo_test_string=`eval $cmd`; } 2>/dev/null &&
+ { test "X$echo_test_string" = "X$echo_test_string"; } 2>/dev/null
+ then
+ break
+ fi
+ done
+ fi
+
+ if test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' &&
+ echo_testing_string=`{ $ECHO "$echo_test_string"; } 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ :
+ else
+ # The Solaris, AIX, and Digital Unix default echo programs unquote
+ # backslashes. This makes it impossible to quote backslashes using
+ # echo "$something" | sed 's/\\/\\\\/g'
+ #
+ # So, first we look for a working echo in the user's PATH.
+
+ lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+ for dir in $PATH /usr/ucb; do
+ IFS="$lt_save_ifs"
+ if (test -f $dir/echo || test -f $dir/echo$ac_exeext) &&
+ test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' &&
+ echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ ECHO="$dir/echo"
+ break
+ fi
+ done
+ IFS="$lt_save_ifs"
+
+ if test "X$ECHO" = Xecho; then
+ # We didn't find a better echo, so look for alternatives.
+ if test "X`{ print -r '\t'; } 2>/dev/null`" = 'X\t' &&
+ echo_testing_string=`{ print -r "$echo_test_string"; } 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ # This shell has a builtin print -r that does the trick.
+ ECHO='print -r'
+ elif { test -f /bin/ksh || test -f /bin/ksh$ac_exeext; } &&
+ test "X$CONFIG_SHELL" != X/bin/ksh; then
+ # If we have ksh, try running configure again with it.
+ ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh}
+ export ORIGINAL_CONFIG_SHELL
+ CONFIG_SHELL=/bin/ksh
+ export CONFIG_SHELL
+ exec $CONFIG_SHELL "[$]0" --no-reexec ${1+"[$]@"}
+ else
+ # Try using printf.
+ ECHO='printf %s\n'
+ if test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' &&
+ echo_testing_string=`{ $ECHO "$echo_test_string"; } 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ # Cool, printf works
+ :
+ elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` &&
+ test "X$echo_testing_string" = 'X\t' &&
+ echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL
+ export CONFIG_SHELL
+ SHELL="$CONFIG_SHELL"
+ export SHELL
+ ECHO="$CONFIG_SHELL [$]0 --fallback-echo"
+ elif echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` &&
+ test "X$echo_testing_string" = 'X\t' &&
+ echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ ECHO="$CONFIG_SHELL [$]0 --fallback-echo"
+ else
+ # maybe with a smaller string...
+ prev=:
+
+ for cmd in 'echo test' 'sed 2q "[$]0"' 'sed 10q "[$]0"' 'sed 20q "[$]0"' 'sed 50q "[$]0"'; do
+ if { test "X$echo_test_string" = "X`eval $cmd`"; } 2>/dev/null
+ then
+ break
+ fi
+ prev="$cmd"
+ done
+
+ if test "$prev" != 'sed 50q "[$]0"'; then
+ echo_test_string=`eval $prev`
+ export echo_test_string
+ exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "[$]0" ${1+"[$]@"}
+ else
+ # Oops. We lost completely, so just stick with echo.
+ ECHO=echo
+ fi
+ fi
+ fi
+ fi
+ fi
+fi
+
+# Copy echo and quote the copy suitably for passing to libtool from
+# the Makefile, instead of quoting the original, which is used later.
+lt_ECHO=$ECHO
+if test "X$lt_ECHO" = "X$CONFIG_SHELL [$]0 --fallback-echo"; then
+ lt_ECHO="$CONFIG_SHELL \\\$\[$]0 --fallback-echo"
+fi
+
+AC_SUBST(lt_ECHO)
+])
+_LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts])
+_LT_DECL([], [ECHO], [1],
+ [An echo program that does not interpret backslashes])
+])# _LT_PROG_ECHO_BACKSLASH
+
+
+# _LT_ENABLE_LOCK
+# ---------------
+m4_defun([_LT_ENABLE_LOCK],
+[AC_ARG_ENABLE([libtool-lock],
+ [AS_HELP_STRING([--disable-libtool-lock],
+ [avoid locking (might break parallel builds)])])
+test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes
+
+# Some flags need to be propagated to the compiler or linker for good
+# libtool support.
+case $host in
+ia64-*-hpux*)
+ # Find out which ABI we are using.
+ echo 'int i;' > conftest.$ac_ext
+ if AC_TRY_EVAL(ac_compile); then
+ case `/usr/bin/file conftest.$ac_objext` in
+ *ELF-32*)
+ HPUX_IA64_MODE="32"
+ ;;
+ *ELF-64*)
+ HPUX_IA64_MODE="64"
+ ;;
+ esac
+ fi
+ rm -rf conftest*
+ ;;
+*-*-irix6*)
+ # Find out which ABI we are using.
+ echo '[#]line __oline__ "configure"' > conftest.$ac_ext
+ if AC_TRY_EVAL(ac_compile); then
+ if test "$lt_cv_prog_gnu_ld" = yes; then
+ case `/usr/bin/file conftest.$ac_objext` in
+ *32-bit*)
+ LD="${LD-ld} -melf32bsmip"
+ ;;
+ *N32*)
+ LD="${LD-ld} -melf32bmipn32"
+ ;;
+ *64-bit*)
+ LD="${LD-ld} -melf64bmip"
+ ;;
+ esac
+ else
+ case `/usr/bin/file conftest.$ac_objext` in
+ *32-bit*)
+ LD="${LD-ld} -32"
+ ;;
+ *N32*)
+ LD="${LD-ld} -n32"
+ ;;
+ *64-bit*)
+ LD="${LD-ld} -64"
+ ;;
+ esac
+ fi
+ fi
+ rm -rf conftest*
+ ;;
+
+x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \
+s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
+ # Find out which ABI we are using.
+ echo 'int i;' > conftest.$ac_ext
+ if AC_TRY_EVAL(ac_compile); then
+ case `/usr/bin/file conftest.o` in
+ *32-bit*)
+ case $host in
+ x86_64-*kfreebsd*-gnu)
+ LD="${LD-ld} -m elf_i386_fbsd"
+ ;;
+ x86_64-*linux*)
+ LD="${LD-ld} -m elf_i386"
+ ;;
+ ppc64-*linux*|powerpc64-*linux*)
+ LD="${LD-ld} -m elf32ppclinux"
+ ;;
+ s390x-*linux*)
+ LD="${LD-ld} -m elf_s390"
+ ;;
+ sparc64-*linux*)
+ LD="${LD-ld} -m elf32_sparc"
+ ;;
+ esac
+ ;;
+ *64-bit*)
+ case $host in
+ x86_64-*kfreebsd*-gnu)
+ LD="${LD-ld} -m elf_x86_64_fbsd"
+ ;;
+ x86_64-*linux*)
+ LD="${LD-ld} -m elf_x86_64"
+ ;;
+ ppc*-*linux*|powerpc*-*linux*)
+ LD="${LD-ld} -m elf64ppc"
+ ;;
+ s390*-*linux*|s390*-*tpf*)
+ LD="${LD-ld} -m elf64_s390"
+ ;;
+ sparc*-*linux*)
+ LD="${LD-ld} -m elf64_sparc"
+ ;;
+ esac
+ ;;
+ esac
+ fi
+ rm -rf conftest*
+ ;;
+
+*-*-sco3.2v5*)
+ # On SCO OpenServer 5, we need -belf to get full-featured binaries.
+ SAVE_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -belf"
+ AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf,
+ [AC_LANG_PUSH(C)
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no])
+ AC_LANG_POP])
+ if test x"$lt_cv_cc_needs_belf" != x"yes"; then
+ # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
+ CFLAGS="$SAVE_CFLAGS"
+ fi
+ ;;
+sparc*-*solaris*)
+ # Find out which ABI we are using.
+ echo 'int i;' > conftest.$ac_ext
+ if AC_TRY_EVAL(ac_compile); then
+ case `/usr/bin/file conftest.o` in
+ *64-bit*)
+ case $lt_cv_prog_gnu_ld in
+ yes*) LD="${LD-ld} -m elf64_sparc" ;;
+ *)
+ if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then
+ LD="${LD-ld} -64"
+ fi
+ ;;
+ esac
+ ;;
+ esac
+ fi
+ rm -rf conftest*
+ ;;
+esac
+
+need_locks="$enable_libtool_lock"
+])# _LT_ENABLE_LOCK
+
+
+# _LT_CMD_OLD_ARCHIVE
+# -------------------
+m4_defun([_LT_CMD_OLD_ARCHIVE],
+[AC_CHECK_TOOL(AR, ar, false)
+test -z "$AR" && AR=ar
+test -z "$AR_FLAGS" && AR_FLAGS=cru
+_LT_DECL([], [AR], [1], [The archiver])
+_LT_DECL([], [AR_FLAGS], [1])
+
+AC_CHECK_TOOL(STRIP, strip, :)
+test -z "$STRIP" && STRIP=:
+_LT_DECL([], [STRIP], [1], [A symbol stripping program])
+
+AC_CHECK_TOOL(RANLIB, ranlib, :)
+test -z "$RANLIB" && RANLIB=:
+_LT_DECL([], [RANLIB], [1],
+ [Commands used to install an old-style archive])
+
+# Determine commands to create old-style static archives.
+old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs'
+old_postinstall_cmds='chmod 644 $oldlib'
+old_postuninstall_cmds=
+
+if test -n "$RANLIB"; then
+ case $host_os in
+ openbsd*)
+ old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib"
+ ;;
+ *)
+ old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib"
+ ;;
+ esac
+ old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib"
+fi
+_LT_DECL([], [old_postinstall_cmds], [2])
+_LT_DECL([], [old_postuninstall_cmds], [2])
+_LT_TAGDECL([], [old_archive_cmds], [2],
+ [Commands used to build an old-style archive])
+])# _LT_CMD_OLD_ARCHIVE
+
+
+# _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS,
+# [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE])
+# ----------------------------------------------------------------
+# Check whether the given compiler option works
+AC_DEFUN([_LT_COMPILER_OPTION],
+[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_DECL_SED])dnl
+AC_CACHE_CHECK([$1], [$2],
+ [$2=no
+ m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4])
+ echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+ lt_compiler_flag="$3"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ # The option is referenced via a variable to avoid confusing sed.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD)
+ (eval "$lt_compile" 2>conftest.err)
+ ac_status=$?
+ cat conftest.err >&AS_MESSAGE_LOG_FD
+ echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
+ if (exit $ac_status) && test -s "$ac_outfile"; then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings other than the usual output.
+ $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+ $2=yes
+ fi
+ fi
+ $RM conftest*
+])
+
+if test x"[$]$2" = xyes; then
+ m4_if([$5], , :, [$5])
+else
+ m4_if([$6], , :, [$6])
+fi
+])# _LT_COMPILER_OPTION
+
+# Old name:
+AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], [])
+
+
+# _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS,
+# [ACTION-SUCCESS], [ACTION-FAILURE])
+# ----------------------------------------------------
+# Check whether the given linker option works
+AC_DEFUN([_LT_LINKER_OPTION],
+[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_DECL_SED])dnl
+AC_CACHE_CHECK([$1], [$2],
+ [$2=no
+ save_LDFLAGS="$LDFLAGS"
+ LDFLAGS="$LDFLAGS $3"
+ echo "$lt_simple_link_test_code" > conftest.$ac_ext
+ if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+ # The linker can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ if test -s conftest.err; then
+ # Append any errors to the config.log.
+ cat conftest.err 1>&AS_MESSAGE_LOG_FD
+ $ECHO "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if diff conftest.exp conftest.er2 >/dev/null; then
+ $2=yes
+ fi
+ else
+ $2=yes
+ fi
+ fi
+ $RM -r conftest*
+ LDFLAGS="$save_LDFLAGS"
+])
+
+if test x"[$]$2" = xyes; then
+ m4_if([$4], , :, [$4])
+else
+ m4_if([$5], , :, [$5])
+fi
+])# _LT_LINKER_OPTION
+
+# Old name:
+AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], [])
+
+
+# LT_CMD_MAX_LEN
+#---------------
+AC_DEFUN([LT_CMD_MAX_LEN],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+# find the maximum length of command line arguments
+AC_MSG_CHECKING([the maximum length of command line arguments])
+AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl
+ i=0
+ teststring="ABCD"
+
+ case $build_os in
+ msdosdjgpp*)
+ # On DJGPP, this test can blow up pretty badly due to problems in libc
+ # (any single argument exceeding 2000 bytes causes a buffer overrun
+ # during glob expansion). Even if it were fixed, the result of this
+ # check would be larger than it should be.
+ lt_cv_sys_max_cmd_len=12288; # 12K is about right
+ ;;
+
+ gnu*)
+ # Under GNU Hurd, this test is not required because there is
+ # no limit to the length of command line arguments.
+ # Libtool will interpret -1 as no limit whatsoever
+ lt_cv_sys_max_cmd_len=-1;
+ ;;
+
+ cygwin* | mingw* | cegcc*)
+ # On Win9x/ME, this test blows up -- it succeeds, but takes
+ # about 5 minutes as the teststring grows exponentially.
+ # Worse, since 9x/ME are not pre-emptively multitasking,
+ # you end up with a "frozen" computer, even though with patience
+ # the test eventually succeeds (with a max line length of 256k).
+ # Instead, let's just punt: use the minimum linelength reported by
+ # all of the supported platforms: 8192 (on NT/2K/XP).
+ lt_cv_sys_max_cmd_len=8192;
+ ;;
+
+ amigaos*)
+ # On AmigaOS with pdksh, this test takes hours, literally.
+ # So we just punt and use a minimum line length of 8192.
+ lt_cv_sys_max_cmd_len=8192;
+ ;;
+
+ netbsd* | freebsd* | openbsd* | darwin* | dragonfly*)
+ # This has been around since 386BSD, at least. Likely further.
+ if test -x /sbin/sysctl; then
+ lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax`
+ elif test -x /usr/sbin/sysctl; then
+ lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax`
+ else
+ lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs
+ fi
+ # And add a safety zone
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
+ ;;
+
+ interix*)
+ # We know the value 262144 and hardcode it with a safety zone (like BSD)
+ lt_cv_sys_max_cmd_len=196608
+ ;;
+
+ osf*)
+ # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure
+ # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not
+ # nice to cause kernel panics so lets avoid the loop below.
+ # First set a reasonable default.
+ lt_cv_sys_max_cmd_len=16384
+ #
+ if test -x /sbin/sysconfig; then
+ case `/sbin/sysconfig -q proc exec_disable_arg_limit` in
+ *1*) lt_cv_sys_max_cmd_len=-1 ;;
+ esac
+ fi
+ ;;
+ sco3.2v5*)
+ lt_cv_sys_max_cmd_len=102400
+ ;;
+ sysv5* | sco5v6* | sysv4.2uw2*)
+ kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null`
+ if test -n "$kargmax"; then
+ lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'`
+ else
+ lt_cv_sys_max_cmd_len=32768
+ fi
+ ;;
+ *)
+ lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null`
+ if test -n "$lt_cv_sys_max_cmd_len"; then
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
+ else
+ # Make teststring a little bigger before we do anything with it.
+ # a 1K string should be a reasonable start.
+ for i in 1 2 3 4 5 6 7 8 ; do
+ teststring=$teststring$teststring
+ done
+ SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}}
+ # If test is not a shell built-in, we'll probably end up computing a
+ # maximum length that is only half of the actual maximum length, but
+ # we can't tell.
+ while { test "X"`$SHELL [$]0 --fallback-echo "X$teststring$teststring" 2>/dev/null` \
+ = "XX$teststring$teststring"; } >/dev/null 2>&1 &&
+ test $i != 17 # 1/2 MB should be enough
+ do
+ i=`expr $i + 1`
+ teststring=$teststring$teststring
+ done
+ # Only check the string length outside the loop.
+ lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1`
+ teststring=
+ # Add a significant safety factor because C++ compilers can tack on
+ # massive amounts of additional arguments before passing them to the
+ # linker. It appears as though 1/2 is a usable value.
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2`
+ fi
+ ;;
+ esac
+])
+if test -n $lt_cv_sys_max_cmd_len ; then
+ AC_MSG_RESULT($lt_cv_sys_max_cmd_len)
+else
+ AC_MSG_RESULT(none)
+fi
+max_cmd_len=$lt_cv_sys_max_cmd_len
+_LT_DECL([], [max_cmd_len], [0],
+ [What is the maximum length of a command?])
+])# LT_CMD_MAX_LEN
+
+# Old name:
+AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], [])
+
+
+# _LT_HEADER_DLFCN
+# ----------------
+m4_defun([_LT_HEADER_DLFCN],
+[AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl
+])# _LT_HEADER_DLFCN
+
+
+# _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE,
+# ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING)
+# ----------------------------------------------------------------
+m4_defun([_LT_TRY_DLOPEN_SELF],
+[m4_require([_LT_HEADER_DLFCN])dnl
+if test "$cross_compiling" = yes; then :
+ [$4]
+else
+ lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+ lt_status=$lt_dlunknown
+ cat > conftest.$ac_ext <<_LT_EOF
+[#line __oline__ "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+# define LT_DLGLOBAL RTLD_GLOBAL
+#else
+# ifdef DL_GLOBAL
+# define LT_DLGLOBAL DL_GLOBAL
+# else
+# define LT_DLGLOBAL 0
+# endif
+#endif
+
+/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+ find out it does not work in some platform. */
+#ifndef LT_DLLAZY_OR_NOW
+# ifdef RTLD_LAZY
+# define LT_DLLAZY_OR_NOW RTLD_LAZY
+# else
+# ifdef DL_LAZY
+# define LT_DLLAZY_OR_NOW DL_LAZY
+# else
+# ifdef RTLD_NOW
+# define LT_DLLAZY_OR_NOW RTLD_NOW
+# else
+# ifdef DL_NOW
+# define LT_DLLAZY_OR_NOW DL_NOW
+# else
+# define LT_DLLAZY_OR_NOW 0
+# endif
+# endif
+# endif
+# endif
+#endif
+
+void fnord() { int i=42;}
+int main ()
+{
+ void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+ int status = $lt_dlunknown;
+
+ if (self)
+ {
+ if (dlsym (self,"fnord")) status = $lt_dlno_uscore;
+ else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore;
+ /* dlclose (self); */
+ }
+ else
+ puts (dlerror ());
+
+ return status;
+}]
+_LT_EOF
+ if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then
+ (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null
+ lt_status=$?
+ case x$lt_status in
+ x$lt_dlno_uscore) $1 ;;
+ x$lt_dlneed_uscore) $2 ;;
+ x$lt_dlunknown|x*) $3 ;;
+ esac
+ else :
+ # compilation failed
+ $3
+ fi
+fi
+rm -fr conftest*
+])# _LT_TRY_DLOPEN_SELF
+
+
+# LT_SYS_DLOPEN_SELF
+# ------------------
+AC_DEFUN([LT_SYS_DLOPEN_SELF],
+[m4_require([_LT_HEADER_DLFCN])dnl
+if test "x$enable_dlopen" != xyes; then
+ enable_dlopen=unknown
+ enable_dlopen_self=unknown
+ enable_dlopen_self_static=unknown
+else
+ lt_cv_dlopen=no
+ lt_cv_dlopen_libs=
+
+ case $host_os in
+ beos*)
+ lt_cv_dlopen="load_add_on"
+ lt_cv_dlopen_libs=
+ lt_cv_dlopen_self=yes
+ ;;
+
+ mingw* | pw32* | cegcc*)
+ lt_cv_dlopen="LoadLibrary"
+ lt_cv_dlopen_libs=
+ ;;
+
+ cygwin*)
+ lt_cv_dlopen="dlopen"
+ lt_cv_dlopen_libs=
+ ;;
+
+ darwin*)
+ # if libdl is installed we need to link against it
+ AC_CHECK_LIB([dl], [dlopen],
+ [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],[
+ lt_cv_dlopen="dyld"
+ lt_cv_dlopen_libs=
+ lt_cv_dlopen_self=yes
+ ])
+ ;;
+
+ *)
+ AC_CHECK_FUNC([shl_load],
+ [lt_cv_dlopen="shl_load"],
+ [AC_CHECK_LIB([dld], [shl_load],
+ [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld"],
+ [AC_CHECK_FUNC([dlopen],
+ [lt_cv_dlopen="dlopen"],
+ [AC_CHECK_LIB([dl], [dlopen],
+ [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],
+ [AC_CHECK_LIB([svld], [dlopen],
+ [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"],
+ [AC_CHECK_LIB([dld], [dld_link],
+ [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld"])
+ ])
+ ])
+ ])
+ ])
+ ])
+ ;;
+ esac
+
+ if test "x$lt_cv_dlopen" != xno; then
+ enable_dlopen=yes
+ else
+ enable_dlopen=no
+ fi
+
+ case $lt_cv_dlopen in
+ dlopen)
+ save_CPPFLAGS="$CPPFLAGS"
+ test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H"
+
+ save_LDFLAGS="$LDFLAGS"
+ wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\"
+
+ save_LIBS="$LIBS"
+ LIBS="$lt_cv_dlopen_libs $LIBS"
+
+ AC_CACHE_CHECK([whether a program can dlopen itself],
+ lt_cv_dlopen_self, [dnl
+ _LT_TRY_DLOPEN_SELF(
+ lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes,
+ lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross)
+ ])
+
+ if test "x$lt_cv_dlopen_self" = xyes; then
+ wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\"
+ AC_CACHE_CHECK([whether a statically linked program can dlopen itself],
+ lt_cv_dlopen_self_static, [dnl
+ _LT_TRY_DLOPEN_SELF(
+ lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes,
+ lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross)
+ ])
+ fi
+
+ CPPFLAGS="$save_CPPFLAGS"
+ LDFLAGS="$save_LDFLAGS"
+ LIBS="$save_LIBS"
+ ;;
+ esac
+
+ case $lt_cv_dlopen_self in
+ yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;;
+ *) enable_dlopen_self=unknown ;;
+ esac
+
+ case $lt_cv_dlopen_self_static in
+ yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;;
+ *) enable_dlopen_self_static=unknown ;;
+ esac
+fi
+_LT_DECL([dlopen_support], [enable_dlopen], [0],
+ [Whether dlopen is supported])
+_LT_DECL([dlopen_self], [enable_dlopen_self], [0],
+ [Whether dlopen of programs is supported])
+_LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0],
+ [Whether dlopen of statically linked programs is supported])
+])# LT_SYS_DLOPEN_SELF
+
+# Old name:
+AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], [])
+
+
+# _LT_COMPILER_C_O([TAGNAME])
+# ---------------------------
+# Check to see if options -c and -o are simultaneously supported by compiler.
+# This macro does not hard code the compiler like AC_PROG_CC_C_O.
+m4_defun([_LT_COMPILER_C_O],
+[m4_require([_LT_DECL_SED])dnl
+m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_TAG_COMPILER])dnl
+AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext],
+ [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)],
+ [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no
+ $RM -r conftest 2>/dev/null
+ mkdir conftest
+ cd conftest
+ mkdir out
+ echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ lt_compiler_flag="-o out/conftest2.$ac_objext"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD)
+ (eval "$lt_compile" 2>out/conftest.err)
+ ac_status=$?
+ cat out/conftest.err >&AS_MESSAGE_LOG_FD
+ echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
+ if (exit $ac_status) && test -s out/conftest2.$ac_objext
+ then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp
+ $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+ if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+ _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes
+ fi
+ fi
+ chmod u+w . 2>&AS_MESSAGE_LOG_FD
+ $RM conftest*
+ # SGI C++ compiler will create directory out/ii_files/ for
+ # template instantiation
+ test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files
+ $RM out/* && rmdir out
+ cd ..
+ $RM -r conftest
+ $RM conftest*
+])
+_LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1],
+ [Does compiler simultaneously support -c and -o options?])
+])# _LT_COMPILER_C_O
+
+
+# _LT_COMPILER_FILE_LOCKS([TAGNAME])
+# ----------------------------------
+# Check to see if we can do hard links to lock some files if needed
+m4_defun([_LT_COMPILER_FILE_LOCKS],
+[m4_require([_LT_ENABLE_LOCK])dnl
+m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+_LT_COMPILER_C_O([$1])
+
+hard_links="nottested"
+if test "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != no; then
+ # do not overwrite the value of need_locks provided by the user
+ AC_MSG_CHECKING([if we can lock with hard links])
+ hard_links=yes
+ $RM conftest*
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ touch conftest.a
+ ln conftest.a conftest.b 2>&5 || hard_links=no
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ AC_MSG_RESULT([$hard_links])
+ if test "$hard_links" = no; then
+ AC_MSG_WARN([`$CC' does not support `-c -o', so `make -j' may be unsafe])
+ need_locks=warn
+ fi
+else
+ need_locks=no
+fi
+_LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?])
+])# _LT_COMPILER_FILE_LOCKS
+
+
+# _LT_CHECK_OBJDIR
+# ----------------
+m4_defun([_LT_CHECK_OBJDIR],
+[AC_CACHE_CHECK([for objdir], [lt_cv_objdir],
+[rm -f .libs 2>/dev/null
+mkdir .libs 2>/dev/null
+if test -d .libs; then
+ lt_cv_objdir=.libs
+else
+ # MS-DOS does not allow filenames that begin with a dot.
+ lt_cv_objdir=_libs
+fi
+rmdir .libs 2>/dev/null])
+objdir=$lt_cv_objdir
+_LT_DECL([], [objdir], [0],
+ [The name of the directory that contains temporary libtool files])dnl
+m4_pattern_allow([LT_OBJDIR])dnl
+AC_DEFINE_UNQUOTED(LT_OBJDIR, "$lt_cv_objdir/",
+ [Define to the sub-directory in which libtool stores uninstalled libraries.])
+])# _LT_CHECK_OBJDIR
+
+
+# _LT_LINKER_HARDCODE_LIBPATH([TAGNAME])
+# --------------------------------------
+# Check hardcoding attributes.
+m4_defun([_LT_LINKER_HARDCODE_LIBPATH],
+[AC_MSG_CHECKING([how to hardcode library paths into programs])
+_LT_TAGVAR(hardcode_action, $1)=
+if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" ||
+ test -n "$_LT_TAGVAR(runpath_var, $1)" ||
+ test "X$_LT_TAGVAR(hardcode_automatic, $1)" = "Xyes" ; then
+
+ # We can hardcode non-existent directories.
+ if test "$_LT_TAGVAR(hardcode_direct, $1)" != no &&
+ # If the only mechanism to avoid hardcoding is shlibpath_var, we
+ # have to relink, otherwise we might link with an installed library
+ # when we should be linking with a yet-to-be-installed one
+ ## test "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" != no &&
+ test "$_LT_TAGVAR(hardcode_minus_L, $1)" != no; then
+ # Linking always hardcodes the temporary library directory.
+ _LT_TAGVAR(hardcode_action, $1)=relink
+ else
+ # We can link without hardcoding, and we can hardcode nonexisting dirs.
+ _LT_TAGVAR(hardcode_action, $1)=immediate
+ fi
+else
+ # We cannot hardcode anything, or else we can only hardcode existing
+ # directories.
+ _LT_TAGVAR(hardcode_action, $1)=unsupported
+fi
+AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)])
+
+if test "$_LT_TAGVAR(hardcode_action, $1)" = relink ||
+ test "$_LT_TAGVAR(inherit_rpath, $1)" = yes; then
+ # Fast installation is not supported
+ enable_fast_install=no
+elif test "$shlibpath_overrides_runpath" = yes ||
+ test "$enable_shared" = no; then
+ # Fast installation is not necessary
+ enable_fast_install=needless
+fi
+_LT_TAGDECL([], [hardcode_action], [0],
+ [How to hardcode a shared library path into an executable])
+])# _LT_LINKER_HARDCODE_LIBPATH
+
+
+# _LT_CMD_STRIPLIB
+# ----------------
+m4_defun([_LT_CMD_STRIPLIB],
+[m4_require([_LT_DECL_EGREP])
+striplib=
+old_striplib=
+AC_MSG_CHECKING([whether stripping libraries is possible])
+if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then
+ test -z "$old_striplib" && old_striplib="$STRIP --strip-debug"
+ test -z "$striplib" && striplib="$STRIP --strip-unneeded"
+ AC_MSG_RESULT([yes])
+else
+# FIXME - insert some real tests, host_os isn't really good enough
+ case $host_os in
+ darwin*)
+ if test -n "$STRIP" ; then
+ striplib="$STRIP -x"
+ old_striplib="$STRIP -S"
+ AC_MSG_RESULT([yes])
+ else
+ AC_MSG_RESULT([no])
+ fi
+ ;;
+ *)
+ AC_MSG_RESULT([no])
+ ;;
+ esac
+fi
+_LT_DECL([], [old_striplib], [1], [Commands to strip libraries])
+_LT_DECL([], [striplib], [1])
+])# _LT_CMD_STRIPLIB
+
+
+# _LT_SYS_DYNAMIC_LINKER([TAG])
+# -----------------------------
+# PORTME Fill in your ld.so characteristics
+m4_defun([_LT_SYS_DYNAMIC_LINKER],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+m4_require([_LT_DECL_EGREP])dnl
+m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_DECL_OBJDUMP])dnl
+m4_require([_LT_DECL_SED])dnl
+AC_MSG_CHECKING([dynamic linker characteristics])
+m4_if([$1],
+ [], [
+if test "$GCC" = yes; then
+ case $host_os in
+ darwin*) lt_awk_arg="/^libraries:/,/LR/" ;;
+ *) lt_awk_arg="/^libraries:/" ;;
+ esac
+ lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+ if $ECHO "$lt_search_path_spec" | $GREP ';' >/dev/null ; then
+ # if the path contains ";" then we assume it to be the separator
+ # otherwise default to the standard path separator (i.e. ":") - it is
+ # assumed that no part of a normal pathname contains ";" but that should
+ # okay in the real world where ";" in dirpaths is itself problematic.
+ lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED -e 's/;/ /g'`
+ else
+ lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+ fi
+ # Ok, now we have the path, separated by spaces, we can step through it
+ # and add multilib dir if necessary.
+ lt_tmp_lt_search_path_spec=
+ lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null`
+ for lt_sys_path in $lt_search_path_spec; do
+ if test -d "$lt_sys_path/$lt_multi_os_dir"; then
+ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir"
+ else
+ test -d "$lt_sys_path" && \
+ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path"
+ fi
+ done
+ lt_search_path_spec=`$ECHO $lt_tmp_lt_search_path_spec | awk '
+BEGIN {RS=" "; FS="/|\n";} {
+ lt_foo="";
+ lt_count=0;
+ for (lt_i = NF; lt_i > 0; lt_i--) {
+ if ($lt_i != "" && $lt_i != ".") {
+ if ($lt_i == "..") {
+ lt_count++;
+ } else {
+ if (lt_count == 0) {
+ lt_foo="/" $lt_i lt_foo;
+ } else {
+ lt_count--;
+ }
+ }
+ }
+ }
+ if (lt_foo != "") { lt_freq[[lt_foo]]++; }
+ if (lt_freq[[lt_foo]] == 1) { print lt_foo; }
+}'`
+ sys_lib_search_path_spec=`$ECHO $lt_search_path_spec`
+else
+ sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+fi])
+library_names_spec=
+libname_spec='lib$name'
+soname_spec=
+shrext_cmds=".so"
+postinstall_cmds=
+postuninstall_cmds=
+finish_cmds=
+finish_eval=
+shlibpath_var=
+shlibpath_overrides_runpath=unknown
+version_type=none
+dynamic_linker="$host_os ld.so"
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
+need_lib_prefix=unknown
+hardcode_into_libs=no
+
+# when you set need_version to no, make sure it does not cause -set_version
+# flags to be left without arguments
+need_version=unknown
+
+case $host_os in
+aix3*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a'
+ shlibpath_var=LIBPATH
+
+ # AIX 3 has no versioning support, so we append a major version to the name.
+ soname_spec='${libname}${release}${shared_ext}$major'
+ ;;
+
+aix[[4-9]]*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ hardcode_into_libs=yes
+ if test "$host_cpu" = ia64; then
+ # AIX 5 supports IA64
+ library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ else
+ # With GCC up to 2.95.x, collect2 would create an import file
+ # for dependence libraries. The import file would start with
+ # the line `#! .'. This would cause the generated library to
+ # depend on `.', always an invalid library. This was fixed in
+ # development snapshots of GCC prior to 3.0.
+ case $host_os in
+ aix4 | aix4.[[01]] | aix4.[[01]].*)
+ if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
+ echo ' yes '
+ echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then
+ :
+ else
+ can_build_shared=no
+ fi
+ ;;
+ esac
+ # AIX (on Power*) has no versioning support, so currently we can not hardcode correct
+ # soname into executable. Probably we can add versioning support to
+ # collect2, so additional links can be useful in future.
+ if test "$aix_use_runtimelinking" = yes; then
+ # If using run time linking (on AIX 4.2 or later) use lib<name>.so
+ # instead of lib<name>.a to let people know that these are not
+ # typical AIX shared libraries.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ else
+ # We preserve .a as extension for shared libraries through AIX4.2
+ # and later when we are not doing run time linking.
+ library_names_spec='${libname}${release}.a $libname.a'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ fi
+ shlibpath_var=LIBPATH
+ fi
+ ;;
+
+amigaos*)
+ case $host_cpu in
+ powerpc)
+ # Since July 2007 AmigaOS4 officially supports .so libraries.
+ # When compiling the executable, add -use-dynld -Lsobjs: to the compileline.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ ;;
+ m68k)
+ library_names_spec='$libname.ixlibrary $libname.a'
+ # Create ${libname}_ixlibrary.a entries in /sys/libs.
+ finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$ECHO "X$lib" | $Xsed -e '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
+ ;;
+ esac
+ ;;
+
+beos*)
+ library_names_spec='${libname}${shared_ext}'
+ dynamic_linker="$host_os ld.so"
+ shlibpath_var=LIBRARY_PATH
+ ;;
+
+bsdi[[45]]*)
+ version_type=linux
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+ sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+ # the default ld.so.conf also contains /usr/contrib/lib and
+ # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
+ # libtool to hard-code these into programs
+ ;;
+
+cygwin* | mingw* | pw32* | cegcc*)
+ version_type=windows
+ shrext_cmds=".dll"
+ need_version=no
+ need_lib_prefix=no
+
+ case $GCC,$host_os in
+ yes,cygwin* | yes,mingw* | yes,pw32* | yes,cegcc*)
+ library_names_spec='$libname.dll.a'
+ # DLL is installed to $(libdir)/../bin by postinstall_cmds
+ postinstall_cmds='base_file=`basename \${file}`~
+ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~
+ dldir=$destdir/`dirname \$dlpath`~
+ test -d \$dldir || mkdir -p \$dldir~
+ $install_prog $dir/$dlname \$dldir/$dlname~
+ chmod a+x \$dldir/$dlname~
+ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then
+ eval '\''$striplib \$dldir/$dlname'\'' || exit \$?;
+ fi'
+ postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+ dlpath=$dir/\$dldll~
+ $RM \$dlpath'
+ shlibpath_overrides_runpath=yes
+
+ case $host_os in
+ cygwin*)
+ # Cygwin DLLs use 'cyg' prefix rather than 'lib'
+ soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}'
+ sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib"
+ ;;
+ mingw* | cegcc*)
+ # MinGW DLLs use traditional 'lib' prefix
+ soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}'
+ sys_lib_search_path_spec=`$CC -print-search-dirs | $GREP "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+ if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then
+ # It is most probably a Windows format PATH printed by
+ # mingw gcc, but we are running on Cygwin. Gcc prints its search
+ # path with ; separators, and with drive letters. We can handle the
+ # drive letters (cygwin fileutils understands them), so leave them,
+ # especially as we might pass files found there to a mingw objdump,
+ # which wouldn't understand a cygwinified path. Ahh.
+ sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+ else
+ sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+ fi
+ ;;
+ pw32*)
+ # pw32 DLLs use 'pw' prefix rather than 'lib'
+ library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}'
+ ;;
+ esac
+ ;;
+
+ *)
+ library_names_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext} $libname.lib'
+ ;;
+ esac
+ dynamic_linker='Win32 ld.exe'
+ # FIXME: first we should search . and the directory the executable is in
+ shlibpath_var=PATH
+ ;;
+
+darwin* | rhapsody*)
+ dynamic_linker="$host_os dyld"
+ version_type=darwin
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext'
+ soname_spec='${libname}${release}${major}$shared_ext'
+ shlibpath_overrides_runpath=yes
+ shlibpath_var=DYLD_LIBRARY_PATH
+ shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
+m4_if([$1], [],[
+ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"])
+ sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
+ ;;
+
+dgux*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+freebsd1*)
+ dynamic_linker=no
+ ;;
+
+freebsd* | dragonfly*)
+ # DragonFly does not have aout. When/if they implement a new
+ # versioning mechanism, adjust this.
+ if test -x /usr/bin/objformat; then
+ objformat=`/usr/bin/objformat`
+ else
+ case $host_os in
+ freebsd[[123]]*) objformat=aout ;;
+ *) objformat=elf ;;
+ esac
+ fi
+ version_type=freebsd-$objformat
+ case $version_type in
+ freebsd-elf*)
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+ need_version=no
+ need_lib_prefix=no
+ ;;
+ freebsd-*)
+ library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix'
+ need_version=yes
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY_PATH
+ case $host_os in
+ freebsd2*)
+ shlibpath_overrides_runpath=yes
+ ;;
+ freebsd3.[[01]]* | freebsdelf3.[[01]]*)
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+ freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \
+ freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1)
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+ *) # from 4.6 on, and DragonFly
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+ esac
+ ;;
+
+gnu*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ hardcode_into_libs=yes
+ ;;
+
+hpux9* | hpux10* | hpux11*)
+ # Give a soname corresponding to the major version so that dld.sl refuses to
+ # link against other versions.
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ case $host_cpu in
+ ia64*)
+ shrext_cmds='.so'
+ hardcode_into_libs=yes
+ dynamic_linker="$host_os dld.so"
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ if test "X$HPUX_IA64_MODE" = X32; then
+ sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
+ else
+ sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
+ fi
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ ;;
+ hppa*64*)
+ shrext_cmds='.sl'
+ hardcode_into_libs=yes
+ dynamic_linker="$host_os dld.sl"
+ shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
+ shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ ;;
+ *)
+ shrext_cmds='.sl'
+ dynamic_linker="$host_os dld.sl"
+ shlibpath_var=SHLIB_PATH
+ shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ ;;
+ esac
+ # HP-UX runs *really* slowly unless shared libraries are mode 555.
+ postinstall_cmds='chmod 555 $lib'
+ ;;
+
+interix[[3-9]]*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+
+irix5* | irix6* | nonstopux*)
+ case $host_os in
+ nonstopux*) version_type=nonstopux ;;
+ *)
+ if test "$lt_cv_prog_gnu_ld" = yes; then
+ version_type=linux
+ else
+ version_type=irix
+ fi ;;
+ esac
+ need_lib_prefix=no
+ need_version=no
+ soname_spec='${libname}${release}${shared_ext}$major'
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}'
+ case $host_os in
+ irix5* | nonstopux*)
+ libsuff= shlibsuff=
+ ;;
+ *)
+ case $LD in # libtool.m4 will add one of these switches to LD
+ *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
+ libsuff= shlibsuff= libmagic=32-bit;;
+ *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
+ libsuff=32 shlibsuff=N32 libmagic=N32;;
+ *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
+ libsuff=64 shlibsuff=64 libmagic=64-bit;;
+ *) libsuff= shlibsuff= libmagic=never-match;;
+ esac
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
+ sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
+ hardcode_into_libs=yes
+ ;;
+
+# No shared lib support for Linux oldld, aout, or coff.
+linux*oldld* | linux*aout* | linux*coff*)
+ dynamic_linker=no
+ ;;
+
+# This must be Linux ELF.
+linux* | k*bsd*-gnu)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ # Some binutils ld are patched to set DT_RUNPATH
+ save_LDFLAGS=$LDFLAGS
+ save_libdir=$libdir
+ eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \
+ LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\""
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])],
+ [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null],
+ [shlibpath_overrides_runpath=yes])])
+ LDFLAGS=$save_LDFLAGS
+ libdir=$save_libdir
+
+ # This implies no fast_install, which is unacceptable.
+ # Some rework will be needed to allow for fast_install
+ # before this can be enabled.
+ hardcode_into_libs=yes
+
+ # Append ld.so.conf contents to the search path
+ if test -f /etc/ld.so.conf; then
+ lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '`
+ sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
+ fi
+
+ # We used to test for /lib/ld.so.1 and disable shared libraries on
+ # powerpc, because MkLinux only supported shared libraries with the
+ # GNU dynamic linker. Since this was broken with cross compilers,
+ # most powerpc-linux boxes support dynamic linking these days and
+ # people can always --disable-shared, the test was removed, and we
+ # assume the GNU/Linux dynamic linker is in use.
+ dynamic_linker='GNU/Linux ld.so'
+ ;;
+
+netbsdelf*-gnu)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ dynamic_linker='NetBSD ld.elf_so'
+ ;;
+
+netbsd*)
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ dynamic_linker='NetBSD (a.out) ld.so'
+ else
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ dynamic_linker='NetBSD ld.elf_so'
+ fi
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+
+newsos6)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ ;;
+
+*nto* | *qnx*)
+ version_type=qnx
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ dynamic_linker='ldqnx.so'
+ ;;
+
+openbsd*)
+ version_type=sunos
+ sys_lib_dlsearch_path_spec="/usr/lib"
+ need_lib_prefix=no
+ # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs.
+ case $host_os in
+ openbsd3.3 | openbsd3.3.*) need_version=yes ;;
+ *) need_version=no ;;
+ esac
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ case $host_os in
+ openbsd2.[[89]] | openbsd2.[[89]].*)
+ shlibpath_overrides_runpath=no
+ ;;
+ *)
+ shlibpath_overrides_runpath=yes
+ ;;
+ esac
+ else
+ shlibpath_overrides_runpath=yes
+ fi
+ ;;
+
+os2*)
+ libname_spec='$name'
+ shrext_cmds=".dll"
+ need_lib_prefix=no
+ library_names_spec='$libname${shared_ext} $libname.a'
+ dynamic_linker='OS/2 ld.exe'
+ shlibpath_var=LIBPATH
+ ;;
+
+osf3* | osf4* | osf5*)
+ version_type=osf
+ need_lib_prefix=no
+ need_version=no
+ soname_spec='${libname}${release}${shared_ext}$major'
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+ sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
+ ;;
+
+rdos*)
+ dynamic_linker=no
+ ;;
+
+solaris*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ # ldd complains unless libraries are executable
+ postinstall_cmds='chmod +x $lib'
+ ;;
+
+sunos4*)
+ version_type=sunos
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ if test "$with_gnu_ld" = yes; then
+ need_lib_prefix=no
+ fi
+ need_version=yes
+ ;;
+
+sysv4 | sysv4.3*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ case $host_vendor in
+ sni)
+ shlibpath_overrides_runpath=no
+ need_lib_prefix=no
+ runpath_var=LD_RUN_PATH
+ ;;
+ siemens)
+ need_lib_prefix=no
+ ;;
+ motorola)
+ need_lib_prefix=no
+ need_version=no
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
+ ;;
+ esac
+ ;;
+
+sysv4*MP*)
+ if test -d /usr/nec ;then
+ version_type=linux
+ library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}'
+ soname_spec='$libname${shared_ext}.$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ fi
+ ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+ version_type=freebsd-elf
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ if test "$with_gnu_ld" = yes; then
+ sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
+ else
+ sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
+ case $host_os in
+ sco3.2v5*)
+ sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
+ ;;
+ esac
+ fi
+ sys_lib_dlsearch_path_spec='/usr/lib'
+ ;;
+
+tpf*)
+ # TPF is a cross-target only. Preferred cross-host = GNU/Linux.
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+
+uts4*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+*)
+ dynamic_linker=no
+ ;;
+esac
+AC_MSG_RESULT([$dynamic_linker])
+test "$dynamic_linker" = no && can_build_shared=no
+
+variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+if test "$GCC" = yes; then
+ variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+fi
+
+if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then
+ sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec"
+fi
+if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then
+ sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec"
+fi
+
+_LT_DECL([], [variables_saved_for_relink], [1],
+ [Variables whose values should be saved in libtool wrapper scripts and
+ restored at link time])
+_LT_DECL([], [need_lib_prefix], [0],
+ [Do we need the "lib" prefix for modules?])
+_LT_DECL([], [need_version], [0], [Do we need a version for libraries?])
+_LT_DECL([], [version_type], [0], [Library versioning type])
+_LT_DECL([], [runpath_var], [0], [Shared library runtime path variable])
+_LT_DECL([], [shlibpath_var], [0],[Shared library path variable])
+_LT_DECL([], [shlibpath_overrides_runpath], [0],
+ [Is shlibpath searched before the hard-coded library search path?])
+_LT_DECL([], [libname_spec], [1], [Format of library name prefix])
+_LT_DECL([], [library_names_spec], [1],
+ [[List of archive names. First name is the real one, the rest are links.
+ The last name is the one that the linker finds with -lNAME]])
+_LT_DECL([], [soname_spec], [1],
+ [[The coded name of the library, if different from the real name]])
+_LT_DECL([], [postinstall_cmds], [2],
+ [Command to use after installation of a shared archive])
+_LT_DECL([], [postuninstall_cmds], [2],
+ [Command to use after uninstallation of a shared archive])
+_LT_DECL([], [finish_cmds], [2],
+ [Commands used to finish a libtool library installation in a directory])
+_LT_DECL([], [finish_eval], [1],
+ [[As "finish_cmds", except a single script fragment to be evaled but
+ not shown]])
+_LT_DECL([], [hardcode_into_libs], [0],
+ [Whether we should hardcode library paths into libraries])
+_LT_DECL([], [sys_lib_search_path_spec], [2],
+ [Compile-time system search path for libraries])
+_LT_DECL([], [sys_lib_dlsearch_path_spec], [2],
+ [Run-time system search path for libraries])
+])# _LT_SYS_DYNAMIC_LINKER
+
+
+# _LT_PATH_TOOL_PREFIX(TOOL)
+# --------------------------
+# find a file program which can recognize shared library
+AC_DEFUN([_LT_PATH_TOOL_PREFIX],
+[m4_require([_LT_DECL_EGREP])dnl
+AC_MSG_CHECKING([for $1])
+AC_CACHE_VAL(lt_cv_path_MAGIC_CMD,
+[case $MAGIC_CMD in
+[[\\/*] | ?:[\\/]*])
+ lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path.
+ ;;
+*)
+ lt_save_MAGIC_CMD="$MAGIC_CMD"
+ lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+dnl $ac_dummy forces splitting on constant user-supplied paths.
+dnl POSIX.2 word splitting is done only on the output of word expansions,
+dnl not every word. This closes a longstanding sh security hole.
+ ac_dummy="m4_if([$2], , $PATH, [$2])"
+ for ac_dir in $ac_dummy; do
+ IFS="$lt_save_ifs"
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$1; then
+ lt_cv_path_MAGIC_CMD="$ac_dir/$1"
+ if test -n "$file_magic_test_file"; then
+ case $deplibs_check_method in
+ "file_magic "*)
+ file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
+ MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+ if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+ $EGREP "$file_magic_regex" > /dev/null; then
+ :
+ else
+ cat <<_LT_EOF 1>&2
+
+*** Warning: the command libtool uses to detect shared libraries,
+*** $file_magic_cmd, produces output that libtool cannot recognize.
+*** The result is that libtool may fail to recognize shared libraries
+*** as such. This will affect the creation of libtool libraries that
+*** depend on shared libraries, but programs linked with such libtool
+*** libraries will work regardless of this problem. Nevertheless, you
+*** may want to report the problem to your system manager and/or to
+*** bug-libtool@gnu.org
+
+_LT_EOF
+ fi ;;
+ esac
+ fi
+ break
+ fi
+ done
+ IFS="$lt_save_ifs"
+ MAGIC_CMD="$lt_save_MAGIC_CMD"
+ ;;
+esac])
+MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+if test -n "$MAGIC_CMD"; then
+ AC_MSG_RESULT($MAGIC_CMD)
+else
+ AC_MSG_RESULT(no)
+fi
+_LT_DECL([], [MAGIC_CMD], [0],
+ [Used to examine libraries when file_magic_cmd begins with "file"])dnl
+])# _LT_PATH_TOOL_PREFIX
+
+# Old name:
+AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], [])
+
+
+# _LT_PATH_MAGIC
+# --------------
+# find a file program which can recognize a shared library
+m4_defun([_LT_PATH_MAGIC],
+[_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH)
+if test -z "$lt_cv_path_MAGIC_CMD"; then
+ if test -n "$ac_tool_prefix"; then
+ _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH)
+ else
+ MAGIC_CMD=:
+ fi
+fi
+])# _LT_PATH_MAGIC
+
+
+# LT_PATH_LD
+# ----------
+# find the pathname to the GNU or non-GNU linker
+AC_DEFUN([LT_PATH_LD],
+[AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_CANONICAL_BUILD])dnl
+m4_require([_LT_DECL_SED])dnl
+m4_require([_LT_DECL_EGREP])dnl
+
+AC_ARG_WITH([gnu-ld],
+ [AS_HELP_STRING([--with-gnu-ld],
+ [assume the C compiler uses GNU ld @<:@default=no@:>@])],
+ [test "$withval" = no || with_gnu_ld=yes],
+ [with_gnu_ld=no])dnl
+
+ac_prog=ld
+if test "$GCC" = yes; then
+ # Check if gcc -print-prog-name=ld gives a path.
+ AC_MSG_CHECKING([for ld used by $CC])
+ case $host in
+ *-*-mingw*)
+ # gcc leaves a trailing carriage return which upsets mingw
+ ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+ *)
+ ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+ esac
+ case $ac_prog in
+ # Accept absolute paths.
+ [[\\/]]* | ?:[[\\/]]*)
+ re_direlt='/[[^/]][[^/]]*/\.\./'
+ # Canonicalize the pathname of ld
+ ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'`
+ while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do
+ ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"`
+ done
+ test -z "$LD" && LD="$ac_prog"
+ ;;
+ "")
+ # If it fails, then pretend we aren't using GCC.
+ ac_prog=ld
+ ;;
+ *)
+ # If it is relative, then search for the first ld in PATH.
+ with_gnu_ld=unknown
+ ;;
+ esac
+elif test "$with_gnu_ld" = yes; then
+ AC_MSG_CHECKING([for GNU ld])
+else
+ AC_MSG_CHECKING([for non-GNU ld])
+fi
+AC_CACHE_VAL(lt_cv_path_LD,
+[if test -z "$LD"; then
+ lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+ for ac_dir in $PATH; do
+ IFS="$lt_save_ifs"
+ test -z "$ac_dir" && ac_dir=.
+ if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+ lt_cv_path_LD="$ac_dir/$ac_prog"
+ # Check to see if the program is GNU ld. I'd rather use --version,
+ # but apparently some variants of GNU ld only accept -v.
+ # Break only if it was the GNU/non-GNU ld that we prefer.
+ case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in
+ *GNU* | *'with BFD'*)
+ test "$with_gnu_ld" != no && break
+ ;;
+ *)
+ test "$with_gnu_ld" != yes && break
+ ;;
+ esac
+ fi
+ done
+ IFS="$lt_save_ifs"
+else
+ lt_cv_path_LD="$LD" # Let the user override the test with a path.
+fi])
+LD="$lt_cv_path_LD"
+if test -n "$LD"; then
+ AC_MSG_RESULT($LD)
+else
+ AC_MSG_RESULT(no)
+fi
+test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH])
+_LT_PATH_LD_GNU
+AC_SUBST([LD])
+
+_LT_TAGDECL([], [LD], [1], [The linker used to build libraries])
+])# LT_PATH_LD
+
+# Old names:
+AU_ALIAS([AM_PROG_LD], [LT_PATH_LD])
+AU_ALIAS([AC_PROG_LD], [LT_PATH_LD])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AM_PROG_LD], [])
+dnl AC_DEFUN([AC_PROG_LD], [])
+
+
+# _LT_PATH_LD_GNU
+#- --------------
+m4_defun([_LT_PATH_LD_GNU],
+[AC_CACHE_CHECK([if the linker ($LD) is GNU ld], lt_cv_prog_gnu_ld,
+[# I'd rather use --version here, but apparently some GNU lds only accept -v.
+case `$LD -v 2>&1 </dev/null` in
+*GNU* | *'with BFD'*)
+ lt_cv_prog_gnu_ld=yes
+ ;;
+*)
+ lt_cv_prog_gnu_ld=no
+ ;;
+esac])
+with_gnu_ld=$lt_cv_prog_gnu_ld
+])# _LT_PATH_LD_GNU
+
+
+# _LT_CMD_RELOAD
+# --------------
+# find reload flag for linker
+# -- PORTME Some linkers may need a different reload flag.
+m4_defun([_LT_CMD_RELOAD],
+[AC_CACHE_CHECK([for $LD option to reload object files],
+ lt_cv_ld_reload_flag,
+ [lt_cv_ld_reload_flag='-r'])
+reload_flag=$lt_cv_ld_reload_flag
+case $reload_flag in
+"" | " "*) ;;
+*) reload_flag=" $reload_flag" ;;
+esac
+reload_cmds='$LD$reload_flag -o $output$reload_objs'
+case $host_os in
+ darwin*)
+ if test "$GCC" = yes; then
+ reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs'
+ else
+ reload_cmds='$LD$reload_flag -o $output$reload_objs'
+ fi
+ ;;
+esac
+_LT_DECL([], [reload_flag], [1], [How to create reloadable object files])dnl
+_LT_DECL([], [reload_cmds], [2])dnl
+])# _LT_CMD_RELOAD
+
+
+# _LT_CHECK_MAGIC_METHOD
+# ----------------------
+# how to check for library dependencies
+# -- PORTME fill in with the dynamic library characteristics
+m4_defun([_LT_CHECK_MAGIC_METHOD],
+[m4_require([_LT_DECL_EGREP])
+m4_require([_LT_DECL_OBJDUMP])
+AC_CACHE_CHECK([how to recognize dependent libraries],
+lt_cv_deplibs_check_method,
+[lt_cv_file_magic_cmd='$MAGIC_CMD'
+lt_cv_file_magic_test_file=
+lt_cv_deplibs_check_method='unknown'
+# Need to set the preceding variable on all platforms that support
+# interlibrary dependencies.
+# 'none' -- dependencies not supported.
+# `unknown' -- same as none, but documents that we really don't know.
+# 'pass_all' -- all dependencies passed with no checks.
+# 'test_compile' -- check by making test program.
+# 'file_magic [[regex]]' -- check by looking for files in library path
+# which responds to the $file_magic_cmd with a given extended regex.
+# If you have `file' or equivalent on your system and you're not sure
+# whether `pass_all' will *always* work, you probably want this one.
+
+case $host_os in
+aix[[4-9]]*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+beos*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+bsdi[[45]]*)
+ lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)'
+ lt_cv_file_magic_cmd='/usr/bin/file -L'
+ lt_cv_file_magic_test_file=/shlib/libc.so
+ ;;
+
+cygwin*)
+ # func_win32_libid is a shell function defined in ltmain.sh
+ lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
+ lt_cv_file_magic_cmd='func_win32_libid'
+ ;;
+
+mingw* | pw32*)
+ # Base MSYS/MinGW do not provide the 'file' command needed by
+ # func_win32_libid shell function, so use a weaker test based on 'objdump',
+ # unless we find 'file', for example because we are cross-compiling.
+ if ( file / ) >/dev/null 2>&1; then
+ lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
+ lt_cv_file_magic_cmd='func_win32_libid'
+ else
+ lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?'
+ lt_cv_file_magic_cmd='$OBJDUMP -f'
+ fi
+ ;;
+
+cegcc)
+ # use the weaker test based on 'objdump'. See mingw*.
+ lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?'
+ lt_cv_file_magic_cmd='$OBJDUMP -f'
+ ;;
+
+darwin* | rhapsody*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+freebsd* | dragonfly*)
+ if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
+ case $host_cpu in
+ i*86 )
+ # Not sure whether the presence of OpenBSD here was a mistake.
+ # Let's accept both of them until this is cleared up.
+ lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library'
+ lt_cv_file_magic_cmd=/usr/bin/file
+ lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
+ ;;
+ esac
+ else
+ lt_cv_deplibs_check_method=pass_all
+ fi
+ ;;
+
+gnu*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+hpux10.20* | hpux11*)
+ lt_cv_file_magic_cmd=/usr/bin/file
+ case $host_cpu in
+ ia64*)
+ lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64'
+ lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so
+ ;;
+ hppa*64*)
+ [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]']
+ lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl
+ ;;
+ *)
+ lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]].[[0-9]]) shared library'
+ lt_cv_file_magic_test_file=/usr/lib/libc.sl
+ ;;
+ esac
+ ;;
+
+interix[[3-9]]*)
+ # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here
+ lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$'
+ ;;
+
+irix5* | irix6* | nonstopux*)
+ case $LD in
+ *-32|*"-32 ") libmagic=32-bit;;
+ *-n32|*"-n32 ") libmagic=N32;;
+ *-64|*"-64 ") libmagic=64-bit;;
+ *) libmagic=never-match;;
+ esac
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+# This must be Linux ELF.
+linux* | k*bsd*-gnu)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+netbsd* | netbsdelf*-gnu)
+ if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
+ lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$'
+ else
+ lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$'
+ fi
+ ;;
+
+newos6*)
+ lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)'
+ lt_cv_file_magic_cmd=/usr/bin/file
+ lt_cv_file_magic_test_file=/usr/lib/libnls.so
+ ;;
+
+*nto* | *qnx*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+openbsd*)
+ if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$'
+ else
+ lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$'
+ fi
+ ;;
+
+osf3* | osf4* | osf5*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+rdos*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+solaris*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+sysv4 | sysv4.3*)
+ case $host_vendor in
+ motorola)
+ lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]'
+ lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*`
+ ;;
+ ncr)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+ sequent)
+ lt_cv_file_magic_cmd='/bin/file'
+ lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )'
+ ;;
+ sni)
+ lt_cv_file_magic_cmd='/bin/file'
+ lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib"
+ lt_cv_file_magic_test_file=/lib/libc.so
+ ;;
+ siemens)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+ pc)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+ esac
+ ;;
+
+tpf*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+esac
+])
+file_magic_cmd=$lt_cv_file_magic_cmd
+deplibs_check_method=$lt_cv_deplibs_check_method
+test -z "$deplibs_check_method" && deplibs_check_method=unknown
+
+_LT_DECL([], [deplibs_check_method], [1],
+ [Method to check whether dependent libraries are shared objects])
+_LT_DECL([], [file_magic_cmd], [1],
+ [Command to use when deplibs_check_method == "file_magic"])
+])# _LT_CHECK_MAGIC_METHOD
+
+
+# LT_PATH_NM
+# ----------
+# find the pathname to a BSD- or MS-compatible name lister
+AC_DEFUN([LT_PATH_NM],
+[AC_REQUIRE([AC_PROG_CC])dnl
+AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM,
+[if test -n "$NM"; then
+ # Let the user override the test.
+ lt_cv_path_NM="$NM"
+else
+ lt_nm_to_check="${ac_tool_prefix}nm"
+ if test -n "$ac_tool_prefix" && test "$build" = "$host"; then
+ lt_nm_to_check="$lt_nm_to_check nm"
+ fi
+ for lt_tmp_nm in $lt_nm_to_check; do
+ lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+ for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do
+ IFS="$lt_save_ifs"
+ test -z "$ac_dir" && ac_dir=.
+ tmp_nm="$ac_dir/$lt_tmp_nm"
+ if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then
+ # Check to see if the nm accepts a BSD-compat flag.
+ # Adding the `sed 1q' prevents false positives on HP-UX, which says:
+ # nm: unknown option "B" ignored
+ # Tru64's nm complains that /dev/null is an invalid object file
+ case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in
+ */dev/null* | *'Invalid file or object type'*)
+ lt_cv_path_NM="$tmp_nm -B"
+ break
+ ;;
+ *)
+ case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in
+ */dev/null*)
+ lt_cv_path_NM="$tmp_nm -p"
+ break
+ ;;
+ *)
+ lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but
+ continue # so that we can try to find one that supports BSD flags
+ ;;
+ esac
+ ;;
+ esac
+ fi
+ done
+ IFS="$lt_save_ifs"
+ done
+ : ${lt_cv_path_NM=no}
+fi])
+if test "$lt_cv_path_NM" != "no"; then
+ NM="$lt_cv_path_NM"
+else
+ # Didn't find any BSD compatible name lister, look for dumpbin.
+ AC_CHECK_TOOLS(DUMPBIN, ["dumpbin -symbols" "link -dump -symbols"], :)
+ AC_SUBST([DUMPBIN])
+ if test "$DUMPBIN" != ":"; then
+ NM="$DUMPBIN"
+ fi
+fi
+test -z "$NM" && NM=nm
+AC_SUBST([NM])
+_LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl
+
+AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface],
+ [lt_cv_nm_interface="BSD nm"
+ echo "int some_variable = 0;" > conftest.$ac_ext
+ (eval echo "\"\$as_me:__oline__: $ac_compile\"" >&AS_MESSAGE_LOG_FD)
+ (eval "$ac_compile" 2>conftest.err)
+ cat conftest.err >&AS_MESSAGE_LOG_FD
+ (eval echo "\"\$as_me:__oline__: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD)
+ (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
+ cat conftest.err >&AS_MESSAGE_LOG_FD
+ (eval echo "\"\$as_me:__oline__: output\"" >&AS_MESSAGE_LOG_FD)
+ cat conftest.out >&AS_MESSAGE_LOG_FD
+ if $GREP 'External.*some_variable' conftest.out > /dev/null; then
+ lt_cv_nm_interface="MS dumpbin"
+ fi
+ rm -f conftest*])
+])# LT_PATH_NM
+
+# Old names:
+AU_ALIAS([AM_PROG_NM], [LT_PATH_NM])
+AU_ALIAS([AC_PROG_NM], [LT_PATH_NM])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AM_PROG_NM], [])
+dnl AC_DEFUN([AC_PROG_NM], [])
+
+
+# LT_LIB_M
+# --------
+# check for math library
+AC_DEFUN([LT_LIB_M],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+LIBM=
+case $host in
+*-*-beos* | *-*-cygwin* | *-*-pw32* | *-*-darwin*)
+ # These system don't have libm, or don't need it
+ ;;
+*-ncr-sysv4.3*)
+ AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw")
+ AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm")
+ ;;
+*)
+ AC_CHECK_LIB(m, cos, LIBM="-lm")
+ ;;
+esac
+AC_SUBST([LIBM])
+])# LT_LIB_M
+
+# Old name:
+AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_CHECK_LIBM], [])
+
+
+# _LT_COMPILER_NO_RTTI([TAGNAME])
+# -------------------------------
+m4_defun([_LT_COMPILER_NO_RTTI],
+[m4_require([_LT_TAG_COMPILER])dnl
+
+_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=
+
+if test "$GCC" = yes; then
+ _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin'
+
+ _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions],
+ lt_cv_prog_compiler_rtti_exceptions,
+ [-fno-rtti -fno-exceptions], [],
+ [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"])
+fi
+_LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1],
+ [Compiler flag to turn off builtin functions])
+])# _LT_COMPILER_NO_RTTI
+
+
+# _LT_CMD_GLOBAL_SYMBOLS
+# ----------------------
+m4_defun([_LT_CMD_GLOBAL_SYMBOLS],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([LT_PATH_NM])dnl
+AC_REQUIRE([LT_PATH_LD])dnl
+m4_require([_LT_DECL_SED])dnl
+m4_require([_LT_DECL_EGREP])dnl
+m4_require([_LT_TAG_COMPILER])dnl
+
+# Check for command to grab the raw symbol name followed by C symbol from nm.
+AC_MSG_CHECKING([command to parse $NM output from $compiler object])
+AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe],
+[
+# These are sane defaults that work on at least a few old systems.
+# [They come from Ultrix. What could be older than Ultrix?!! ;)]
+
+# Character class describing NM global symbol codes.
+symcode='[[BCDEGRST]]'
+
+# Regexp to match symbols that can be accessed directly from C.
+sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)'
+
+# Define system-specific variables.
+case $host_os in
+aix*)
+ symcode='[[BCDT]]'
+ ;;
+cygwin* | mingw* | pw32* | cegcc*)
+ symcode='[[ABCDGISTW]]'
+ ;;
+hpux*)
+ if test "$host_cpu" = ia64; then
+ symcode='[[ABCDEGRST]]'
+ fi
+ ;;
+irix* | nonstopux*)
+ symcode='[[BCDEGRST]]'
+ ;;
+osf*)
+ symcode='[[BCDEGQRST]]'
+ ;;
+solaris*)
+ symcode='[[BDRT]]'
+ ;;
+sco3.2v5*)
+ symcode='[[DT]]'
+ ;;
+sysv4.2uw2*)
+ symcode='[[DT]]'
+ ;;
+sysv5* | sco5v6* | unixware* | OpenUNIX*)
+ symcode='[[ABDT]]'
+ ;;
+sysv4)
+ symcode='[[DFNSTU]]'
+ ;;
+esac
+
+# If we're using GNU nm, then use its standard symbol codes.
+case `$NM -V 2>&1` in
+*GNU* | *'with BFD'*)
+ symcode='[[ABCDGIRSTW]]' ;;
+esac
+
+# Transform an extracted symbol line into a proper C declaration.
+# Some systems (esp. on ia64) link data and code symbols differently,
+# so use this general approach.
+lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'"
+
+# Transform an extracted symbol line into symbol name and symbol address
+lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p'"
+lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \(lib[[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"lib\2\", (void *) \&\2},/p'"
+
+# Handle CRLF in mingw tool chain
+opt_cr=
+case $build_os in
+mingw*)
+ opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp
+ ;;
+esac
+
+# Try without a prefix underscore, then with it.
+for ac_symprfx in "" "_"; do
+
+ # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol.
+ symxfrm="\\1 $ac_symprfx\\2 \\2"
+
+ # Write the raw and C identifiers.
+ if test "$lt_cv_nm_interface" = "MS dumpbin"; then
+ # Fake it for dumpbin and say T for any non-static function
+ # and D for any global variable.
+ # Also find C++ and __fastcall symbols from MSVC++,
+ # which start with @ or ?.
+ lt_cv_sys_global_symbol_pipe="$AWK ['"\
+" {last_section=section; section=\$ 3};"\
+" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\
+" \$ 0!~/External *\|/{next};"\
+" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\
+" {if(hide[section]) next};"\
+" {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\
+" {split(\$ 0, a, /\||\r/); split(a[2], s)};"\
+" s[1]~/^[@?]/{print s[1], s[1]; next};"\
+" s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\
+" ' prfx=^$ac_symprfx]"
+ else
+ lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'"
+ fi
+
+ # Check to see that the pipe works correctly.
+ pipe_works=no
+
+ rm -f conftest*
+ cat > conftest.$ac_ext <<_LT_EOF
+#ifdef __cplusplus
+extern "C" {
+#endif
+char nm_test_var;
+void nm_test_func(void);
+void nm_test_func(void){}
+#ifdef __cplusplus
+}
+#endif
+int main(){nm_test_var='a';nm_test_func();return(0);}
+_LT_EOF
+
+ if AC_TRY_EVAL(ac_compile); then
+ # Now try to grab the symbols.
+ nlist=conftest.nm
+ if AC_TRY_EVAL(NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) && test -s "$nlist"; then
+ # Try sorting and uniquifying the output.
+ if sort "$nlist" | uniq > "$nlist"T; then
+ mv -f "$nlist"T "$nlist"
+ else
+ rm -f "$nlist"T
+ fi
+
+ # Make sure that we snagged all the symbols we need.
+ if $GREP ' nm_test_var$' "$nlist" >/dev/null; then
+ if $GREP ' nm_test_func$' "$nlist" >/dev/null; then
+ cat <<_LT_EOF > conftest.$ac_ext
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+_LT_EOF
+ # Now generate the symbol file.
+ eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext'
+
+ cat <<_LT_EOF >> conftest.$ac_ext
+
+/* The mapping between symbol names and symbols. */
+const struct {
+ const char *name;
+ void *address;
+}
+lt__PROGRAM__LTX_preloaded_symbols[[]] =
+{
+ { "@PROGRAM@", (void *) 0 },
+_LT_EOF
+ $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext
+ cat <<\_LT_EOF >> conftest.$ac_ext
+ {0, (void *) 0}
+};
+
+/* This works around a problem in FreeBSD linker */
+#ifdef FREEBSD_WORKAROUND
+static const void *lt_preloaded_setup() {
+ return lt__PROGRAM__LTX_preloaded_symbols;
+}
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+_LT_EOF
+ # Now try linking the two files.
+ mv conftest.$ac_objext conftstm.$ac_objext
+ lt_save_LIBS="$LIBS"
+ lt_save_CFLAGS="$CFLAGS"
+ LIBS="conftstm.$ac_objext"
+ CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)"
+ if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then
+ pipe_works=yes
+ fi
+ LIBS="$lt_save_LIBS"
+ CFLAGS="$lt_save_CFLAGS"
+ else
+ echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD
+ fi
+ else
+ echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD
+ fi
+ else
+ echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD
+ fi
+ else
+ echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD
+ cat conftest.$ac_ext >&5
+ fi
+ rm -rf conftest* conftst*
+
+ # Do not use the global_symbol_pipe unless it works.
+ if test "$pipe_works" = yes; then
+ break
+ else
+ lt_cv_sys_global_symbol_pipe=
+ fi
+done
+])
+if test -z "$lt_cv_sys_global_symbol_pipe"; then
+ lt_cv_sys_global_symbol_to_cdecl=
+fi
+if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then
+ AC_MSG_RESULT(failed)
+else
+ AC_MSG_RESULT(ok)
+fi
+
+_LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1],
+ [Take the output of nm and produce a listing of raw symbols and C names])
+_LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1],
+ [Transform the output of nm in a proper C declaration])
+_LT_DECL([global_symbol_to_c_name_address],
+ [lt_cv_sys_global_symbol_to_c_name_address], [1],
+ [Transform the output of nm in a C name address pair])
+_LT_DECL([global_symbol_to_c_name_address_lib_prefix],
+ [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1],
+ [Transform the output of nm in a C name address pair when lib prefix is needed])
+]) # _LT_CMD_GLOBAL_SYMBOLS
+
+
+# _LT_COMPILER_PIC([TAGNAME])
+# ---------------------------
+m4_defun([_LT_COMPILER_PIC],
+[m4_require([_LT_TAG_COMPILER])dnl
+_LT_TAGVAR(lt_prog_compiler_wl, $1)=
+_LT_TAGVAR(lt_prog_compiler_pic, $1)=
+_LT_TAGVAR(lt_prog_compiler_static, $1)=
+
+AC_MSG_CHECKING([for $compiler option to produce PIC])
+m4_if([$1], [CXX], [
+ # C++ specific cases for pic, static, wl, etc.
+ if test "$GXX" = yes; then
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+
+ case $host_os in
+ aix*)
+ # All AIX code is PIC.
+ if test "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ fi
+ ;;
+
+ amigaos*)
+ case $host_cpu in
+ powerpc)
+ # see comment about AmigaOS4 .so support
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ ;;
+ m68k)
+ # FIXME: we need at least 68020 code to build shared libraries, but
+ # adding the `-m68020' flag to GCC prevents building anything better,
+ # like `-m68040'.
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4'
+ ;;
+ esac
+ ;;
+
+ beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+ # PIC is the default for these OSes.
+ ;;
+ mingw* | cygwin* | os2* | pw32* | cegcc*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ # Although the cygwin gcc ignores -fPIC, still need this for old-style
+ # (--disable-auto-import) libraries
+ m4_if([$1], [GCJ], [],
+ [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
+ ;;
+ darwin* | rhapsody*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
+ ;;
+ *djgpp*)
+ # DJGPP does not support shared libraries at all
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)=
+ ;;
+ interix[[3-9]]*)
+ # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+ # Instead, we relocate shared libraries at runtime.
+ ;;
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic
+ fi
+ ;;
+ hpux*)
+ # PIC is the default for 64-bit PA HP-UX, but not for 32-bit
+ # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag
+ # sets the default TLS model and affects inlining.
+ case $host_cpu in
+ hppa*64*)
+ ;;
+ *)
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ ;;
+ esac
+ ;;
+ *qnx* | *nto*)
+ # QNX uses GNU C++, but need to define -shared option too, otherwise
+ # it will coredump.
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
+ ;;
+ *)
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ ;;
+ esac
+ else
+ case $host_os in
+ aix[[4-9]]*)
+ # All AIX code is PIC.
+ if test "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ else
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp'
+ fi
+ ;;
+ chorus*)
+ case $cc_basename in
+ cxch68*)
+ # Green Hills C++ Compiler
+ # _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a"
+ ;;
+ esac
+ ;;
+ dgux*)
+ case $cc_basename in
+ ec++*)
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ ;;
+ ghcx*)
+ # Green Hills C++ Compiler
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ freebsd* | dragonfly*)
+ # FreeBSD uses GNU C++
+ ;;
+ hpux9* | hpux10* | hpux11*)
+ case $cc_basename in
+ CC*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive'
+ if test "$host_cpu" != ia64; then
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
+ fi
+ ;;
+ aCC*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive'
+ case $host_cpu in
+ hppa*64*|ia64*)
+ # +Z the default
+ ;;
+ *)
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
+ ;;
+ esac
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ interix*)
+ # This is c89, which is MS Visual C++ (no shared libs)
+ # Anyone wants to do a port?
+ ;;
+ irix5* | irix6* | nonstopux*)
+ case $cc_basename in
+ CC*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+ # CC pic flag -KPIC is the default.
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ linux* | k*bsd*-gnu)
+ case $cc_basename in
+ KCC*)
+ # KAI C++ Compiler
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ ;;
+ ecpc* )
+ # old Intel C++ for x86_64 which still supported -KPIC.
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+ ;;
+ icpc* )
+ # Intel C++, used to be incompatible with GCC.
+ # ICC 10 doesn't accept -KPIC any more.
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+ ;;
+ pgCC* | pgcpp*)
+ # Portland Group C++ compiler
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+ cxx*)
+ # Compaq C++
+ # Make sure the PIC flag is empty. It appears that all Alpha
+ # Linux and Compaq Tru64 Unix objects are PIC.
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)=
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+ ;;
+ xlc* | xlC*)
+ # IBM XL 8.0 on PPC
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink'
+ ;;
+ *)
+ case `$CC -V 2>&1 | sed 5q` in
+ *Sun\ C*)
+ # Sun C++ 5.9
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ lynxos*)
+ ;;
+ m88k*)
+ ;;
+ mvs*)
+ case $cc_basename in
+ cxx*)
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ netbsd* | netbsdelf*-gnu)
+ ;;
+ *qnx* | *nto*)
+ # QNX uses GNU C++, but need to define -shared option too, otherwise
+ # it will coredump.
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
+ ;;
+ osf3* | osf4* | osf5*)
+ case $cc_basename in
+ KCC*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,'
+ ;;
+ RCC*)
+ # Rational C++ 2.4.1
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+ ;;
+ cxx*)
+ # Digital/Compaq C++
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ # Make sure the PIC flag is empty. It appears that all Alpha
+ # Linux and Compaq Tru64 Unix objects are PIC.
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)=
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ psos*)
+ ;;
+ solaris*)
+ case $cc_basename in
+ CC*)
+ # Sun C++ 4.2, 5.x and Centerline C++
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
+ ;;
+ gcx*)
+ # Green Hills C++ Compiler
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ sunos4*)
+ case $cc_basename in
+ CC*)
+ # Sun C++ 4.x
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+ lcc*)
+ # Lucid
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+ case $cc_basename in
+ CC*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+ esac
+ ;;
+ tandem*)
+ case $cc_basename in
+ NCC*)
+ # NonStop-UX NCC 3.20
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ vxworks*)
+ ;;
+ *)
+ _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+ ;;
+ esac
+ fi
+],
+[
+ if test "$GCC" = yes; then
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+
+ case $host_os in
+ aix*)
+ # All AIX code is PIC.
+ if test "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ fi
+ ;;
+
+ amigaos*)
+ case $host_cpu in
+ powerpc)
+ # see comment about AmigaOS4 .so support
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ ;;
+ m68k)
+ # FIXME: we need at least 68020 code to build shared libraries, but
+ # adding the `-m68020' flag to GCC prevents building anything better,
+ # like `-m68040'.
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4'
+ ;;
+ esac
+ ;;
+
+ beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+ # PIC is the default for these OSes.
+ ;;
+
+ mingw* | cygwin* | pw32* | os2* | cegcc*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ # Although the cygwin gcc ignores -fPIC, still need this for old-style
+ # (--disable-auto-import) libraries
+ m4_if([$1], [GCJ], [],
+ [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
+ ;;
+
+ darwin* | rhapsody*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
+ ;;
+
+ hpux*)
+ # PIC is the default for 64-bit PA HP-UX, but not for 32-bit
+ # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag
+ # sets the default TLS model and affects inlining.
+ case $host_cpu in
+ hppa*64*)
+ # +Z the default
+ ;;
+ *)
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ ;;
+ esac
+ ;;
+
+ interix[[3-9]]*)
+ # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+ # Instead, we relocate shared libraries at runtime.
+ ;;
+
+ msdosdjgpp*)
+ # Just because we use GCC doesn't mean we suddenly get shared libraries
+ # on systems that don't support them.
+ _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+ enable_shared=no
+ ;;
+
+ *nto* | *qnx*)
+ # QNX uses GNU C++, but need to define -shared option too, otherwise
+ # it will coredump.
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic
+ fi
+ ;;
+
+ *)
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ ;;
+ esac
+ else
+ # PORTME Check for flag to pass linker flags through the system compiler.
+ case $host_os in
+ aix*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ if test "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ else
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp'
+ fi
+ ;;
+
+ mingw* | cygwin* | pw32* | os2* | cegcc*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ m4_if([$1], [GCJ], [],
+ [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
+ ;;
+
+ hpux9* | hpux10* | hpux11*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+ # not for PA HP-UX.
+ case $host_cpu in
+ hppa*64*|ia64*)
+ # +Z the default
+ ;;
+ *)
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
+ ;;
+ esac
+ # Is there a better lt_prog_compiler_static that works with the bundled CC?
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive'
+ ;;
+
+ irix5* | irix6* | nonstopux*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ # PIC (with -KPIC) is the default.
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+ ;;
+
+ linux* | k*bsd*-gnu)
+ case $cc_basename in
+ # old Intel for x86_64 which still supported -KPIC.
+ ecc*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+ ;;
+ # icc used to be incompatible with GCC.
+ # ICC 10 doesn't accept -KPIC any more.
+ icc* | ifort*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+ ;;
+ # Lahey Fortran 8.1.
+ lf95*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='--static'
+ ;;
+ pgcc* | pgf77* | pgf90* | pgf95*)
+ # Portland Group compilers (*not* the Pentium gcc compiler,
+ # which looks to be a dead project)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+ ccc*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ # All Alpha code is PIC.
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+ ;;
+ xl*)
+ # IBM XL C 8.0/Fortran 10.1 on PPC
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink'
+ ;;
+ *)
+ case `$CC -V 2>&1 | sed 5q` in
+ *Sun\ C*)
+ # Sun C 5.9
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ ;;
+ *Sun\ F*)
+ # Sun Fortran 8.3 passes all unrecognized flags to the linker
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)=''
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+
+ newsos6)
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+
+ *nto* | *qnx*)
+ # QNX uses GNU C++, but need to define -shared option too, otherwise
+ # it will coredump.
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
+ ;;
+
+ osf3* | osf4* | osf5*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ # All OSF/1 code is PIC.
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+ ;;
+
+ rdos*)
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+ ;;
+
+ solaris*)
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ case $cc_basename in
+ f77* | f90* | f95*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';;
+ *)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';;
+ esac
+ ;;
+
+ sunos4*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+
+ sysv4 | sysv4.2uw2* | sysv4.3*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec ;then
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ fi
+ ;;
+
+ sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+
+ unicos*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+ ;;
+
+ uts4*)
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+
+ *)
+ _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+ ;;
+ esac
+ fi
+])
+case $host_os in
+ # For platforms which do not support PIC, -DPIC is meaningless:
+ *djgpp*)
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)=
+ ;;
+ *)
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])"
+ ;;
+esac
+AC_MSG_RESULT([$_LT_TAGVAR(lt_prog_compiler_pic, $1)])
+_LT_TAGDECL([wl], [lt_prog_compiler_wl], [1],
+ [How to pass a linker flag through the compiler])
+
+#
+# Check to make sure the PIC flag actually works.
+#
+if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then
+ _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works],
+ [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)],
+ [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [],
+ [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in
+ "" | " "*) ;;
+ *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;;
+ esac],
+ [_LT_TAGVAR(lt_prog_compiler_pic, $1)=
+ _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no])
+fi
+_LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1],
+ [Additional compiler flags for building library objects])
+
+#
+# Check to make sure the static flag actually works.
+#
+wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\"
+_LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works],
+ _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1),
+ $lt_tmp_static_flag,
+ [],
+ [_LT_TAGVAR(lt_prog_compiler_static, $1)=])
+_LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1],
+ [Compiler flag to prevent dynamic linking])
+])# _LT_COMPILER_PIC
+
+
+# _LT_LINKER_SHLIBS([TAGNAME])
+# ----------------------------
+# See if the linker supports building shared libraries.
+m4_defun([_LT_LINKER_SHLIBS],
+[AC_REQUIRE([LT_PATH_LD])dnl
+AC_REQUIRE([LT_PATH_NM])dnl
+m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_DECL_EGREP])dnl
+m4_require([_LT_DECL_SED])dnl
+m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl
+m4_require([_LT_TAG_COMPILER])dnl
+AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries])
+m4_if([$1], [CXX], [
+ _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+ case $host_os in
+ aix[[4-9]]*)
+ # If we're using GNU nm, then we don't want the "-C" option.
+ # -C means demangle to AIX nm, but means don't demangle with GNU nm
+ if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
+ _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
+ else
+ _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
+ fi
+ ;;
+ pw32*)
+ _LT_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds"
+ ;;
+ cygwin* | mingw* | cegcc*)
+ _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;/^.*[[ ]]__nm__/s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols'
+ ;;
+ linux* | k*bsd*-gnu)
+ _LT_TAGVAR(link_all_deplibs, $1)=no
+ ;;
+ *)
+ _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+ ;;
+ esac
+ _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*']
+], [
+ runpath_var=
+ _LT_TAGVAR(allow_undefined_flag, $1)=
+ _LT_TAGVAR(always_export_symbols, $1)=no
+ _LT_TAGVAR(archive_cmds, $1)=
+ _LT_TAGVAR(archive_expsym_cmds, $1)=
+ _LT_TAGVAR(compiler_needs_object, $1)=no
+ _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)=
+ _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+ _LT_TAGVAR(hardcode_automatic, $1)=no
+ _LT_TAGVAR(hardcode_direct, $1)=no
+ _LT_TAGVAR(hardcode_direct_absolute, $1)=no
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
+ _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)=
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=
+ _LT_TAGVAR(hardcode_minus_L, $1)=no
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
+ _LT_TAGVAR(inherit_rpath, $1)=no
+ _LT_TAGVAR(link_all_deplibs, $1)=unknown
+ _LT_TAGVAR(module_cmds, $1)=
+ _LT_TAGVAR(module_expsym_cmds, $1)=
+ _LT_TAGVAR(old_archive_from_new_cmds, $1)=
+ _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)=
+ _LT_TAGVAR(thread_safe_flag_spec, $1)=
+ _LT_TAGVAR(whole_archive_flag_spec, $1)=
+ # include_expsyms should be a list of space-separated symbols to be *always*
+ # included in the symbol list
+ _LT_TAGVAR(include_expsyms, $1)=
+ # exclude_expsyms can be an extended regexp of symbols to exclude
+ # it will be wrapped by ` (' and `)$', so one must not match beginning or
+ # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc',
+ # as well as any symbol that contains `d'.
+ _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*']
+ # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
+ # platforms (ab)use it in PIC code, but their linkers get confused if
+ # the symbol is explicitly referenced. Since portable code cannot
+ # rely on this symbol name, it's probably fine to never include it in
+ # preloaded symbol tables.
+ # Exclude shared library initialization/finalization symbols.
+dnl Note also adjust exclude_expsyms for C++ above.
+ extract_expsyms_cmds=
+
+ case $host_os in
+ cygwin* | mingw* | pw32* | cegcc*)
+ # FIXME: the MSVC++ port hasn't been tested in a loooong time
+ # When not using gcc, we currently assume that we are using
+ # Microsoft Visual C++.
+ if test "$GCC" != yes; then
+ with_gnu_ld=no
+ fi
+ ;;
+ interix*)
+ # we just hope/assume this is gcc and not c89 (= MSVC++)
+ with_gnu_ld=yes
+ ;;
+ openbsd*)
+ with_gnu_ld=no
+ ;;
+ linux* | k*bsd*-gnu)
+ _LT_TAGVAR(link_all_deplibs, $1)=no
+ ;;
+ esac
+
+ _LT_TAGVAR(ld_shlibs, $1)=yes
+ if test "$with_gnu_ld" = yes; then
+ # If archive_cmds runs LD, not CC, wlarc should be empty
+ wlarc='${wl}'
+
+ # Set some defaults for GNU ld with shared library support. These
+ # are reset later if shared libraries are not supported. Putting them
+ # here allows them to be overridden if necessary.
+ runpath_var=LD_RUN_PATH
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+ # ancient GNU ld didn't support --whole-archive et. al.
+ if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then
+ _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+ else
+ _LT_TAGVAR(whole_archive_flag_spec, $1)=
+ fi
+ supports_anon_versioning=no
+ case `$LD -v 2>&1` in
+ *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11
+ *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
+ *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...
+ *\ 2.11.*) ;; # other 2.11 versions
+ *) supports_anon_versioning=yes ;;
+ esac
+
+ # See if GNU ld supports shared libraries.
+ case $host_os in
+ aix[[3-9]]*)
+ # On AIX/PPC, the GNU linker is very broken
+ if test "$host_cpu" != ia64; then
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ cat <<_LT_EOF 1>&2
+
+*** Warning: the GNU linker, at least up to release 2.9.1, is reported
+*** to be unable to reliably create shared libraries on AIX.
+*** Therefore, libtool is disabling shared libraries support. If you
+*** really care for shared libraries, you may want to modify your PATH
+*** so that a non-GNU linker is found, and then restart.
+
+_LT_EOF
+ fi
+ ;;
+
+ amigaos*)
+ case $host_cpu in
+ powerpc)
+ # see comment about AmigaOS4 .so support
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)=''
+ ;;
+ m68k)
+ _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes
+ ;;
+ esac
+ ;;
+
+ beos*)
+ if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+ _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+ # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+ # support --undefined. This deserves some investigation. FIXME
+ _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ else
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+
+ cygwin* | mingw* | pw32* | cegcc*)
+ # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless,
+ # as there is no search path for DLLs.
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+ _LT_TAGVAR(always_export_symbols, $1)=no
+ _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+ _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols'
+
+ if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ # If the export-symbols file already is a .def file (1st line
+ # is EXPORTS), use it as is; otherwise, prepend...
+ _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+ cp $export_symbols $output_objdir/$soname.def;
+ else
+ echo EXPORTS > $output_objdir/$soname.def;
+ cat $export_symbols >> $output_objdir/$soname.def;
+ fi~
+ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ else
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+
+ interix[[3-9]]*)
+ _LT_TAGVAR(hardcode_direct, $1)=no
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+ # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+ # Instead, shared libraries are loaded at an image base (0x10000000 by
+ # default) and relocated if they conflict, which is a slow very memory
+ # consuming and fragmenting process. To avoid this, we pick a random,
+ # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+ # time. Moving up from 0x10000000 also allows more sbrk(2) space.
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ ;;
+
+ gnu* | linux* | tpf* | k*bsd*-gnu)
+ tmp_diet=no
+ if test "$host_os" = linux-dietlibc; then
+ case $cc_basename in
+ diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn)
+ esac
+ fi
+ if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \
+ && test "$tmp_diet" = no
+ then
+ tmp_addflag=
+ tmp_sharedflag='-shared'
+ case $cc_basename,$host_cpu in
+ pgcc*) # Portland Group C compiler
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive'
+ tmp_addflag=' $pic_flag'
+ ;;
+ pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive'
+ tmp_addflag=' $pic_flag -Mnomain' ;;
+ ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64
+ tmp_addflag=' -i_dynamic' ;;
+ efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64
+ tmp_addflag=' -i_dynamic -nofor_main' ;;
+ ifc* | ifort*) # Intel Fortran compiler
+ tmp_addflag=' -nofor_main' ;;
+ lf95*) # Lahey Fortran 8.1
+ _LT_TAGVAR(whole_archive_flag_spec, $1)=
+ tmp_sharedflag='--shared' ;;
+ xl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below)
+ tmp_sharedflag='-qmkshrobj'
+ tmp_addflag= ;;
+ esac
+ case `$CC -V 2>&1 | sed 5q` in
+ *Sun\ C*) # Sun C 5.9
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive'
+ _LT_TAGVAR(compiler_needs_object, $1)=yes
+ tmp_sharedflag='-G' ;;
+ *Sun\ F*) # Sun Fortran 8.3
+ tmp_sharedflag='-G' ;;
+ esac
+ _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+
+ if test "x$supports_anon_versioning" = xyes; then
+ _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~
+ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+ echo "local: *; };" >> $output_objdir/$libname.ver~
+ $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'
+ fi
+
+ case $cc_basename in
+ xlf*)
+ # IBM XL Fortran 10.1 on PPC cannot create shared libs itself
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
+ _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='-rpath $libdir'
+ _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $compiler_flags -soname $soname -o $lib'
+ if test "x$supports_anon_versioning" = xyes; then
+ _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~
+ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+ echo "local: *; };" >> $output_objdir/$libname.ver~
+ $LD -shared $libobjs $deplibs $compiler_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib'
+ fi
+ ;;
+ esac
+ else
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+
+ netbsd* | netbsdelf*-gnu)
+ if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+ _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
+ wlarc=
+ else
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ fi
+ ;;
+
+ solaris*)
+ if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ cat <<_LT_EOF 1>&2
+
+*** Warning: The releases 2.8.* of the GNU linker cannot reliably
+*** create shared libraries on Solaris systems. Therefore, libtool
+*** is disabling shared libraries support. We urge you to upgrade GNU
+*** binutils to release 2.9.1 or newer. Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+ elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+
+ sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
+ case `$LD -v 2>&1` in
+ *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*)
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ cat <<_LT_EOF 1>&2
+
+*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not
+*** reliably create shared libraries on SCO systems. Therefore, libtool
+*** is disabling shared libraries support. We urge you to upgrade GNU
+*** binutils to release 2.16.91.0.3 or newer. Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+ ;;
+ *)
+ # For security reasons, it is highly recommended that you always
+ # use absolute paths for naming shared libraries, and exclude the
+ # DT_RUNPATH tag from executables and libraries. But doing so
+ # requires that you compile everything twice, which is a pain.
+ if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+ esac
+ ;;
+
+ sunos4*)
+ _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ wlarc=
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ *)
+ if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+ esac
+
+ if test "$_LT_TAGVAR(ld_shlibs, $1)" = no; then
+ runpath_var=
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)=
+ _LT_TAGVAR(whole_archive_flag_spec, $1)=
+ fi
+ else
+ # PORTME fill in a description of your system's linker (not GNU ld)
+ case $host_os in
+ aix3*)
+ _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+ _LT_TAGVAR(always_export_symbols, $1)=yes
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
+ # Note: this linker hardcodes the directories in LIBPATH if there
+ # are no directories specified by -L.
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes
+ if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then
+ # Neither direct hardcoding nor static linking is supported with a
+ # broken collect2.
+ _LT_TAGVAR(hardcode_direct, $1)=unsupported
+ fi
+ ;;
+
+ aix[[4-9]]*)
+ if test "$host_cpu" = ia64; then
+ # On IA64, the linker does run time linking by default, so we don't
+ # have to do anything special.
+ aix_use_runtimelinking=no
+ exp_sym_flag='-Bexport'
+ no_entry_flag=""
+ else
+ # If we're using GNU nm, then we don't want the "-C" option.
+ # -C means demangle to AIX nm, but means don't demangle with GNU nm
+ if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
+ _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
+ else
+ _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
+ fi
+ aix_use_runtimelinking=no
+
+ # Test if we are trying to use run time linking or normal
+ # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+ # need to do runtime linking.
+ case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*)
+ for ld_flag in $LDFLAGS; do
+ if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
+ aix_use_runtimelinking=yes
+ break
+ fi
+ done
+ ;;
+ esac
+
+ exp_sym_flag='-bexport'
+ no_entry_flag='-bnoentry'
+ fi
+
+ # When large executables or shared objects are built, AIX ld can
+ # have problems creating the table of contents. If linking a library
+ # or program results in "error TOC overflow" add -mminimal-toc to
+ # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not
+ # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+ _LT_TAGVAR(archive_cmds, $1)=''
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=':'
+ _LT_TAGVAR(link_all_deplibs, $1)=yes
+ _LT_TAGVAR(file_list_spec, $1)='${wl}-f,'
+
+ if test "$GCC" = yes; then
+ case $host_os in aix4.[[012]]|aix4.[[012]].*)
+ # We only want to do this on AIX 4.2 and lower, the check
+ # below for broken collect2 doesn't work under 4.3+
+ collect2name=`${CC} -print-prog-name=collect2`
+ if test -f "$collect2name" &&
+ strings "$collect2name" | $GREP resolve_lib_name >/dev/null
+ then
+ # We have reworked collect2
+ :
+ else
+ # We have old collect2
+ _LT_TAGVAR(hardcode_direct, $1)=unsupported
+ # It fails to find uninstalled libraries when the uninstalled
+ # path is not listed in the libpath. Setting hardcode_minus_L
+ # to unsupported forces relinking
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=
+ fi
+ ;;
+ esac
+ shared_flag='-shared'
+ if test "$aix_use_runtimelinking" = yes; then
+ shared_flag="$shared_flag "'${wl}-G'
+ fi
+ _LT_TAGVAR(link_all_deplibs, $1)=no
+ else
+ # not using gcc
+ if test "$host_cpu" = ia64; then
+ # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+ # chokes on -Wl,-G. The following line is correct:
+ shared_flag='-G'
+ else
+ if test "$aix_use_runtimelinking" = yes; then
+ shared_flag='${wl}-G'
+ else
+ shared_flag='${wl}-bM:SRE'
+ fi
+ fi
+ fi
+
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall'
+ # It seems that -bexpall does not export symbols beginning with
+ # underscore (_), so it is better to generate a list of symbols to export.
+ _LT_TAGVAR(always_export_symbols, $1)=yes
+ if test "$aix_use_runtimelinking" = yes; then
+ # Warning - without using the other runtime loading flags (-brtl),
+ # -berok will link without error, but may produce a broken library.
+ _LT_TAGVAR(allow_undefined_flag, $1)='-berok'
+ # Determine the default libpath from the value encoded in an
+ # empty executable.
+ _LT_SYS_MODULE_PATH_AIX
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then $ECHO "X${wl}${allow_undefined_flag}" | $Xsed; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+ else
+ if test "$host_cpu" = ia64; then
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib'
+ _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs"
+ _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
+ else
+ # Determine the default libpath from the value encoded in an
+ # empty executable.
+ _LT_SYS_MODULE_PATH_AIX
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
+ # Warning - without using the other run time loading flags,
+ # -berok will link without error, but may produce a broken library.
+ _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok'
+ _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok'
+ # Exported symbols can be pulled into shared objects from archives
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience'
+ _LT_TAGVAR(archive_cmds_need_lc, $1)=yes
+ # This is similar to how AIX traditionally builds its shared libraries.
+ _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+ fi
+ fi
+ ;;
+
+ amigaos*)
+ case $host_cpu in
+ powerpc)
+ # see comment about AmigaOS4 .so support
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)=''
+ ;;
+ m68k)
+ _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes
+ ;;
+ esac
+ ;;
+
+ bsdi[[45]]*)
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic
+ ;;
+
+ cygwin* | mingw* | pw32* | cegcc*)
+ # When not using gcc, we currently assume that we are using
+ # Microsoft Visual C++.
+ # hardcode_libdir_flag_spec is actually meaningless, as there is
+ # no search path for DLLs.
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
+ _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+ # Tell ltmain to make .lib files, not .a files.
+ libext=lib
+ # Tell ltmain to make .dll files, not .so files.
+ shrext_cmds=".dll"
+ # FIXME: Setting linknames here is a bad hack.
+ _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `$ECHO "X$deplibs" | $Xsed -e '\''s/ -lc$//'\''` -link -dll~linknames='
+ # The linker will automatically build a .lib file if we build a DLL.
+ _LT_TAGVAR(old_archive_from_new_cmds, $1)='true'
+ # FIXME: Should let the user specify the lib program.
+ _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs'
+ _LT_TAGVAR(fix_srcfile_path, $1)='`cygpath -w "$srcfile"`'
+ _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+ ;;
+
+ darwin* | rhapsody*)
+ _LT_DARWIN_LINKER_FEATURES($1)
+ ;;
+
+ dgux*)
+ _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ freebsd1*)
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+
+ # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
+ # support. Future versions do this automatically, but an explicit c++rt0.o
+ # does not break anything, and helps significantly (at the cost of a little
+ # extra space).
+ freebsd2.2*)
+ _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ # Unfortunately, older versions of FreeBSD 2 do not have this feature.
+ freebsd2*)
+ _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
+ freebsd* | dragonfly*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ hpux9*)
+ if test "$GCC" = yes; then
+ _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+ else
+ _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+ fi
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+ ;;
+
+ hpux10*)
+ if test "$GCC" = yes -a "$with_gnu_ld" = no; then
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
+ fi
+ if test "$with_gnu_ld" = no; then
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+ _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes
+ fi
+ ;;
+
+ hpux11*)
+ if test "$GCC" = yes -a "$with_gnu_ld" = no; then
+ case $host_cpu in
+ hppa*64*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ ia64*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ else
+ case $host_cpu in
+ hppa*64*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ ia64*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ fi
+ if test "$with_gnu_ld" = no; then
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ case $host_cpu in
+ hppa*64*|ia64*)
+ _LT_TAGVAR(hardcode_direct, $1)=no
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+ *)
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes
+ ;;
+ esac
+ fi
+ ;;
+
+ irix5* | irix6* | nonstopux*)
+ if test "$GCC" = yes; then
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ # Try to use the -exported_symbol ld option, if it does not
+ # work, assume that -exports_file does not work either and
+ # implicitly export all symbols.
+ save_LDFLAGS="$LDFLAGS"
+ LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null"
+ AC_LINK_IFELSE(int foo(void) {},
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib'
+ )
+ LDFLAGS="$save_LDFLAGS"
+ else
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib'
+ fi
+ _LT_TAGVAR(archive_cmds_need_lc, $1)='no'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+ _LT_TAGVAR(inherit_rpath, $1)=yes
+ _LT_TAGVAR(link_all_deplibs, $1)=yes
+ ;;
+
+ netbsd* | netbsdelf*-gnu)
+ if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+ _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out
+ else
+ _LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF
+ fi
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ newsos6)
+ _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ *nto* | *qnx*)
+ ;;
+
+ openbsd*)
+ if test -f /usr/libexec/ld.so; then
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+ if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+ else
+ case $host_os in
+ openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*)
+ _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+ ;;
+ *)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+ ;;
+ esac
+ fi
+ else
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+
+ os2*)
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes
+ _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+ _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$ECHO DATA >> $output_objdir/$libname.def~$ECHO " SINGLE NONSHARED" >> $output_objdir/$libname.def~$ECHO EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def'
+ _LT_TAGVAR(old_archive_from_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def'
+ ;;
+
+ osf3*)
+ if test "$GCC" = yes; then
+ _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ else
+ _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib'
+ fi
+ _LT_TAGVAR(archive_cmds_need_lc, $1)='no'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+ ;;
+
+ osf4* | osf5*) # as osf3* with the addition of -msym flag
+ if test "$GCC" = yes; then
+ _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+ else
+ _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~
+ $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp'
+
+ # Both c and cxx compiler support -rpath directly
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
+ fi
+ _LT_TAGVAR(archive_cmds_need_lc, $1)='no'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+ ;;
+
+ solaris*)
+ _LT_TAGVAR(no_undefined_flag, $1)=' -z defs'
+ if test "$GCC" = yes; then
+ wlarc='${wl}'
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+ $CC -shared ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
+ else
+ case `$CC -V 2>&1` in
+ *"Compilers 5.0"*)
+ wlarc=''
+ _LT_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp'
+ ;;
+ *)
+ wlarc='${wl}'
+ _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+ $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
+ ;;
+ esac
+ fi
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ case $host_os in
+ solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
+ *)
+ # The compiler driver will combine and reorder linker options,
+ # but understands `-z linker_flag'. GCC discards it without `$wl',
+ # but is careful enough not to reorder.
+ # Supported since Solaris 2.6 (maybe 2.5.1?)
+ if test "$GCC" = yes; then
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract'
+ else
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract'
+ fi
+ ;;
+ esac
+ _LT_TAGVAR(link_all_deplibs, $1)=yes
+ ;;
+
+ sunos4*)
+ if test "x$host_vendor" = xsequent; then
+ # Use $CC to link under sequent, because it throws in some extra .o
+ # files that make .init and .fini sections work.
+ _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
+ fi
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ sysv4)
+ case $host_vendor in
+ sni)
+ _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true???
+ ;;
+ siemens)
+ ## LD is ld it makes a PLAMLIB
+ ## CC just makes a GrossModule.
+ _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags'
+ _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs'
+ _LT_TAGVAR(hardcode_direct, $1)=no
+ ;;
+ motorola)
+ _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie
+ ;;
+ esac
+ runpath_var='LD_RUN_PATH'
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ sysv4.3*)
+ _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport'
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ runpath_var=LD_RUN_PATH
+ hardcode_runpath_var=yes
+ _LT_TAGVAR(ld_shlibs, $1)=yes
+ fi
+ ;;
+
+ sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*)
+ _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'
+ _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ runpath_var='LD_RUN_PATH'
+
+ if test "$GCC" = yes; then
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ fi
+ ;;
+
+ sysv5* | sco3.2v5* | sco5v6*)
+ # Note: We can NOT use -z defs as we might desire, because we do not
+ # link with -lc, and that would cause any symbols used from libc to
+ # always be unresolved, which means just about no library would
+ # ever link correctly. If we're not using GNU ld we use -z text
+ # though, which does catch some bad symbols but isn't as heavy-handed
+ # as -z defs.
+ _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'
+ _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs'
+ _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=':'
+ _LT_TAGVAR(link_all_deplibs, $1)=yes
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport'
+ runpath_var='LD_RUN_PATH'
+
+ if test "$GCC" = yes; then
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ fi
+ ;;
+
+ uts4*)
+ _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ *)
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+
+ if test x$host_vendor = xsni; then
+ case $host in
+ sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Blargedynsym'
+ ;;
+ esac
+ fi
+ fi
+])
+AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)])
+test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no
+
+_LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld
+
+_LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl
+_LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl
+_LT_DECL([], [extract_expsyms_cmds], [2],
+ [The commands to extract the exported symbol list from a shared archive])
+
+#
+# Do we need to explicitly link libc?
+#
+case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in
+x|xyes)
+ # Assume -lc should be added
+ _LT_TAGVAR(archive_cmds_need_lc, $1)=yes
+
+ if test "$enable_shared" = yes && test "$GCC" = yes; then
+ case $_LT_TAGVAR(archive_cmds, $1) in
+ *'~'*)
+ # FIXME: we may have to deal with multi-command sequences.
+ ;;
+ '$CC '*)
+ # Test whether the compiler implicitly links with -lc since on some
+ # systems, -lgcc has to come before -lc. If gcc already passes -lc
+ # to ld, don't add -lc before -lgcc.
+ AC_MSG_CHECKING([whether -lc should be explicitly linked in])
+ $RM conftest*
+ echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ if AC_TRY_EVAL(ac_compile) 2>conftest.err; then
+ soname=conftest
+ lib=conftest
+ libobjs=conftest.$ac_objext
+ deplibs=
+ wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1)
+ pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1)
+ compiler_flags=-v
+ linker_flags=-v
+ verstring=
+ output_objdir=.
+ libname=conftest
+ lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1)
+ _LT_TAGVAR(allow_undefined_flag, $1)=
+ if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1)
+ then
+ _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+ else
+ _LT_TAGVAR(archive_cmds_need_lc, $1)=yes
+ fi
+ _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag
+ else
+ cat conftest.err 1>&5
+ fi
+ $RM conftest*
+ AC_MSG_RESULT([$_LT_TAGVAR(archive_cmds_need_lc, $1)])
+ ;;
+ esac
+ fi
+ ;;
+esac
+
+_LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0],
+ [Whether or not to add -lc for building shared libraries])
+_LT_TAGDECL([allow_libtool_libs_with_static_runtimes],
+ [enable_shared_with_static_runtimes], [0],
+ [Whether or not to disallow shared libs when runtime libs are static])
+_LT_TAGDECL([], [export_dynamic_flag_spec], [1],
+ [Compiler flag to allow reflexive dlopens])
+_LT_TAGDECL([], [whole_archive_flag_spec], [1],
+ [Compiler flag to generate shared objects directly from archives])
+_LT_TAGDECL([], [compiler_needs_object], [1],
+ [Whether the compiler copes with passing no objects directly])
+_LT_TAGDECL([], [old_archive_from_new_cmds], [2],
+ [Create an old-style archive from a shared archive])
+_LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2],
+ [Create a temporary old-style archive to link instead of a shared archive])
+_LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive])
+_LT_TAGDECL([], [archive_expsym_cmds], [2])
+_LT_TAGDECL([], [module_cmds], [2],
+ [Commands used to build a loadable module if different from building
+ a shared archive.])
+_LT_TAGDECL([], [module_expsym_cmds], [2])
+_LT_TAGDECL([], [with_gnu_ld], [1],
+ [Whether we are building with GNU ld or not])
+_LT_TAGDECL([], [allow_undefined_flag], [1],
+ [Flag that allows shared libraries with undefined symbols to be built])
+_LT_TAGDECL([], [no_undefined_flag], [1],
+ [Flag that enforces no undefined symbols])
+_LT_TAGDECL([], [hardcode_libdir_flag_spec], [1],
+ [Flag to hardcode $libdir into a binary during linking.
+ This must work even if $libdir does not exist])
+_LT_TAGDECL([], [hardcode_libdir_flag_spec_ld], [1],
+ [[If ld is used when linking, flag to hardcode $libdir into a binary
+ during linking. This must work even if $libdir does not exist]])
+_LT_TAGDECL([], [hardcode_libdir_separator], [1],
+ [Whether we need a single "-rpath" flag with a separated argument])
+_LT_TAGDECL([], [hardcode_direct], [0],
+ [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes
+ DIR into the resulting binary])
+_LT_TAGDECL([], [hardcode_direct_absolute], [0],
+ [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes
+ DIR into the resulting binary and the resulting library dependency is
+ "absolute", i.e impossible to change by setting ${shlibpath_var} if the
+ library is relocated])
+_LT_TAGDECL([], [hardcode_minus_L], [0],
+ [Set to "yes" if using the -LDIR flag during linking hardcodes DIR
+ into the resulting binary])
+_LT_TAGDECL([], [hardcode_shlibpath_var], [0],
+ [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR
+ into the resulting binary])
+_LT_TAGDECL([], [hardcode_automatic], [0],
+ [Set to "yes" if building a shared library automatically hardcodes DIR
+ into the library and all subsequent libraries and executables linked
+ against it])
+_LT_TAGDECL([], [inherit_rpath], [0],
+ [Set to yes if linker adds runtime paths of dependent libraries
+ to runtime path list])
+_LT_TAGDECL([], [link_all_deplibs], [0],
+ [Whether libtool must link a program against all its dependency libraries])
+_LT_TAGDECL([], [fix_srcfile_path], [1],
+ [Fix the shell variable $srcfile for the compiler])
+_LT_TAGDECL([], [always_export_symbols], [0],
+ [Set to "yes" if exported symbols are required])
+_LT_TAGDECL([], [export_symbols_cmds], [2],
+ [The commands to list exported symbols])
+_LT_TAGDECL([], [exclude_expsyms], [1],
+ [Symbols that should not be listed in the preloaded symbols])
+_LT_TAGDECL([], [include_expsyms], [1],
+ [Symbols that must always be exported])
+_LT_TAGDECL([], [prelink_cmds], [2],
+ [Commands necessary for linking programs (against libraries) with templates])
+_LT_TAGDECL([], [file_list_spec], [1],
+ [Specify filename containing input files])
+dnl FIXME: Not yet implemented
+dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1],
+dnl [Compiler flag to generate thread safe objects])
+])# _LT_LINKER_SHLIBS
+
+
+# _LT_LANG_C_CONFIG([TAG])
+# ------------------------
+# Ensure that the configuration variables for a C compiler are suitably
+# defined. These variables are subsequently used by _LT_CONFIG to write
+# the compiler configuration to `libtool'.
+m4_defun([_LT_LANG_C_CONFIG],
+[m4_require([_LT_DECL_EGREP])dnl
+lt_save_CC="$CC"
+AC_LANG_PUSH(C)
+
+# Source file extension for C test sources.
+ac_ext=c
+
+# Object file extension for compiled C test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="int some_variable = 0;"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='int main(){return(0);}'
+
+_LT_TAG_COMPILER
+# Save the default compiler, since it gets overwritten when the other
+# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP.
+compiler_DEFAULT=$CC
+
+# save warnings/boilerplate of simple test code
+_LT_COMPILER_BOILERPLATE
+_LT_LINKER_BOILERPLATE
+
+if test -n "$compiler"; then
+ _LT_COMPILER_NO_RTTI($1)
+ _LT_COMPILER_PIC($1)
+ _LT_COMPILER_C_O($1)
+ _LT_COMPILER_FILE_LOCKS($1)
+ _LT_LINKER_SHLIBS($1)
+ _LT_SYS_DYNAMIC_LINKER($1)
+ _LT_LINKER_HARDCODE_LIBPATH($1)
+ LT_SYS_DLOPEN_SELF
+ _LT_CMD_STRIPLIB
+
+ # Report which library types will actually be built
+ AC_MSG_CHECKING([if libtool supports shared libraries])
+ AC_MSG_RESULT([$can_build_shared])
+
+ AC_MSG_CHECKING([whether to build shared libraries])
+ test "$can_build_shared" = "no" && enable_shared=no
+
+ # On AIX, shared libraries and static libraries use the same namespace, and
+ # are all built from PIC.
+ case $host_os in
+ aix3*)
+ test "$enable_shared" = yes && enable_static=no
+ if test -n "$RANLIB"; then
+ archive_cmds="$archive_cmds~\$RANLIB \$lib"
+ postinstall_cmds='$RANLIB $lib'
+ fi
+ ;;
+
+ aix[[4-9]]*)
+ if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
+ test "$enable_shared" = yes && enable_static=no
+ fi
+ ;;
+ esac
+ AC_MSG_RESULT([$enable_shared])
+
+ AC_MSG_CHECKING([whether to build static libraries])
+ # Make sure either enable_shared or enable_static is yes.
+ test "$enable_shared" = yes || enable_static=yes
+ AC_MSG_RESULT([$enable_static])
+
+ _LT_CONFIG($1)
+fi
+AC_LANG_POP
+CC="$lt_save_CC"
+])# _LT_LANG_C_CONFIG
+
+
+# _LT_PROG_CXX
+# ------------
+# Since AC_PROG_CXX is broken, in that it returns g++ if there is no c++
+# compiler, we have our own version here.
+m4_defun([_LT_PROG_CXX],
+[
+pushdef([AC_MSG_ERROR], [_lt_caught_CXX_error=yes])
+AC_PROG_CXX
+if test -n "$CXX" && ( test "X$CXX" != "Xno" &&
+ ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) ||
+ (test "X$CXX" != "Xg++"))) ; then
+ AC_PROG_CXXCPP
+else
+ _lt_caught_CXX_error=yes
+fi
+popdef([AC_MSG_ERROR])
+])# _LT_PROG_CXX
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([_LT_PROG_CXX], [])
+
+
+# _LT_LANG_CXX_CONFIG([TAG])
+# --------------------------
+# Ensure that the configuration variables for a C++ compiler are suitably
+# defined. These variables are subsequently used by _LT_CONFIG to write
+# the compiler configuration to `libtool'.
+m4_defun([_LT_LANG_CXX_CONFIG],
+[AC_REQUIRE([_LT_PROG_CXX])dnl
+m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_DECL_EGREP])dnl
+
+AC_LANG_PUSH(C++)
+_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+_LT_TAGVAR(allow_undefined_flag, $1)=
+_LT_TAGVAR(always_export_symbols, $1)=no
+_LT_TAGVAR(archive_expsym_cmds, $1)=
+_LT_TAGVAR(compiler_needs_object, $1)=no
+_LT_TAGVAR(export_dynamic_flag_spec, $1)=
+_LT_TAGVAR(hardcode_direct, $1)=no
+_LT_TAGVAR(hardcode_direct_absolute, $1)=no
+_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
+_LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)=
+_LT_TAGVAR(hardcode_libdir_separator, $1)=
+_LT_TAGVAR(hardcode_minus_L, $1)=no
+_LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
+_LT_TAGVAR(hardcode_automatic, $1)=no
+_LT_TAGVAR(inherit_rpath, $1)=no
+_LT_TAGVAR(module_cmds, $1)=
+_LT_TAGVAR(module_expsym_cmds, $1)=
+_LT_TAGVAR(link_all_deplibs, $1)=unknown
+_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+_LT_TAGVAR(no_undefined_flag, $1)=
+_LT_TAGVAR(whole_archive_flag_spec, $1)=
+_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+
+# Source file extension for C++ test sources.
+ac_ext=cpp
+
+# Object file extension for compiled C++ test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# No sense in running all these tests if we already determined that
+# the CXX compiler isn't working. Some variables (like enable_shared)
+# are currently assumed to apply to all compilers on this platform,
+# and will be corrupted by setting them based on a non-working compiler.
+if test "$_lt_caught_CXX_error" != yes; then
+ # Code to be used in simple compile tests
+ lt_simple_compile_test_code="int some_variable = 0;"
+
+ # Code to be used in simple link tests
+ lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }'
+
+ # ltmain only uses $CC for tagged configurations so make sure $CC is set.
+ _LT_TAG_COMPILER
+
+ # save warnings/boilerplate of simple test code
+ _LT_COMPILER_BOILERPLATE
+ _LT_LINKER_BOILERPLATE
+
+ # Allow CC to be a program name with arguments.
+ lt_save_CC=$CC
+ lt_save_LD=$LD
+ lt_save_GCC=$GCC
+ GCC=$GXX
+ lt_save_with_gnu_ld=$with_gnu_ld
+ lt_save_path_LD=$lt_cv_path_LD
+ if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then
+ lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx
+ else
+ $as_unset lt_cv_prog_gnu_ld
+ fi
+ if test -n "${lt_cv_path_LDCXX+set}"; then
+ lt_cv_path_LD=$lt_cv_path_LDCXX
+ else
+ $as_unset lt_cv_path_LD
+ fi
+ test -z "${LDCXX+set}" || LD=$LDCXX
+ CC=${CXX-"c++"}
+ compiler=$CC
+ _LT_TAGVAR(compiler, $1)=$CC
+ _LT_CC_BASENAME([$compiler])
+
+ if test -n "$compiler"; then
+ # We don't want -fno-exception when compiling C++ code, so set the
+ # no_builtin_flag separately
+ if test "$GXX" = yes; then
+ _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin'
+ else
+ _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=
+ fi
+
+ if test "$GXX" = yes; then
+ # Set up default GNU C++ configuration
+
+ LT_PATH_LD
+
+ # Check if GNU C++ uses GNU ld as the underlying linker, since the
+ # archiving commands below assume that GNU ld is being used.
+ if test "$with_gnu_ld" = yes; then
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+
+ # If archive_cmds runs LD, not CC, wlarc should be empty
+ # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to
+ # investigate it a little bit more. (MM)
+ wlarc='${wl}'
+
+ # ancient GNU ld didn't support --whole-archive et. al.
+ if eval "`$CC -print-prog-name=ld` --help 2>&1" |
+ $GREP 'no-whole-archive' > /dev/null; then
+ _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+ else
+ _LT_TAGVAR(whole_archive_flag_spec, $1)=
+ fi
+ else
+ with_gnu_ld=no
+ wlarc=
+
+ # A generic and very simple default shared library creation
+ # command for GNU C++ for the case where it uses the native
+ # linker, instead of GNU ld. If possible, this setting should
+ # overridden to take advantage of the native linker features on
+ # the platform it is being used on.
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
+ fi
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"'
+
+ else
+ GXX=no
+ with_gnu_ld=no
+ wlarc=
+ fi
+
+ # PORTME: fill in a description of your system's C++ link characteristics
+ AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries])
+ _LT_TAGVAR(ld_shlibs, $1)=yes
+ case $host_os in
+ aix3*)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ aix[[4-9]]*)
+ if test "$host_cpu" = ia64; then
+ # On IA64, the linker does run time linking by default, so we don't
+ # have to do anything special.
+ aix_use_runtimelinking=no
+ exp_sym_flag='-Bexport'
+ no_entry_flag=""
+ else
+ aix_use_runtimelinking=no
+
+ # Test if we are trying to use run time linking or normal
+ # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+ # need to do runtime linking.
+ case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*)
+ for ld_flag in $LDFLAGS; do
+ case $ld_flag in
+ *-brtl*)
+ aix_use_runtimelinking=yes
+ break
+ ;;
+ esac
+ done
+ ;;
+ esac
+
+ exp_sym_flag='-bexport'
+ no_entry_flag='-bnoentry'
+ fi
+
+ # When large executables or shared objects are built, AIX ld can
+ # have problems creating the table of contents. If linking a library
+ # or program results in "error TOC overflow" add -mminimal-toc to
+ # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not
+ # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+ _LT_TAGVAR(archive_cmds, $1)=''
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=':'
+ _LT_TAGVAR(link_all_deplibs, $1)=yes
+ _LT_TAGVAR(file_list_spec, $1)='${wl}-f,'
+
+ if test "$GXX" = yes; then
+ case $host_os in aix4.[[012]]|aix4.[[012]].*)
+ # We only want to do this on AIX 4.2 and lower, the check
+ # below for broken collect2 doesn't work under 4.3+
+ collect2name=`${CC} -print-prog-name=collect2`
+ if test -f "$collect2name" &&
+ strings "$collect2name" | $GREP resolve_lib_name >/dev/null
+ then
+ # We have reworked collect2
+ :
+ else
+ # We have old collect2
+ _LT_TAGVAR(hardcode_direct, $1)=unsupported
+ # It fails to find uninstalled libraries when the uninstalled
+ # path is not listed in the libpath. Setting hardcode_minus_L
+ # to unsupported forces relinking
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=
+ fi
+ esac
+ shared_flag='-shared'
+ if test "$aix_use_runtimelinking" = yes; then
+ shared_flag="$shared_flag "'${wl}-G'
+ fi
+ else
+ # not using gcc
+ if test "$host_cpu" = ia64; then
+ # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+ # chokes on -Wl,-G. The following line is correct:
+ shared_flag='-G'
+ else
+ if test "$aix_use_runtimelinking" = yes; then
+ shared_flag='${wl}-G'
+ else
+ shared_flag='${wl}-bM:SRE'
+ fi
+ fi
+ fi
+
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall'
+ # It seems that -bexpall does not export symbols beginning with
+ # underscore (_), so it is better to generate a list of symbols to
+ # export.
+ _LT_TAGVAR(always_export_symbols, $1)=yes
+ if test "$aix_use_runtimelinking" = yes; then
+ # Warning - without using the other runtime loading flags (-brtl),
+ # -berok will link without error, but may produce a broken library.
+ _LT_TAGVAR(allow_undefined_flag, $1)='-berok'
+ # Determine the default libpath from the value encoded in an empty
+ # executable.
+ _LT_SYS_MODULE_PATH_AIX
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
+
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then $ECHO "X${wl}${allow_undefined_flag}" | $Xsed; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+ else
+ if test "$host_cpu" = ia64; then
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib'
+ _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs"
+ _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
+ else
+ # Determine the default libpath from the value encoded in an
+ # empty executable.
+ _LT_SYS_MODULE_PATH_AIX
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
+ # Warning - without using the other run time loading flags,
+ # -berok will link without error, but may produce a broken library.
+ _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok'
+ _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok'
+ # Exported symbols can be pulled into shared objects from archives
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience'
+ _LT_TAGVAR(archive_cmds_need_lc, $1)=yes
+ # This is similar to how AIX traditionally builds its shared
+ # libraries.
+ _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+ fi
+ fi
+ ;;
+
+ beos*)
+ if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+ _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+ # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+ # support --undefined. This deserves some investigation. FIXME
+ _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ else
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+
+ chorus*)
+ case $cc_basename in
+ *)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+ ;;
+
+ cygwin* | mingw* | pw32* | cegcc*)
+ # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless,
+ # as there is no search path for DLLs.
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+ _LT_TAGVAR(always_export_symbols, $1)=no
+ _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+
+ if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ # If the export-symbols file already is a .def file (1st line
+ # is EXPORTS), use it as is; otherwise, prepend...
+ _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+ cp $export_symbols $output_objdir/$soname.def;
+ else
+ echo EXPORTS > $output_objdir/$soname.def;
+ cat $export_symbols >> $output_objdir/$soname.def;
+ fi~
+ $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ else
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+ darwin* | rhapsody*)
+ _LT_DARWIN_LINKER_FEATURES($1)
+ ;;
+
+ dgux*)
+ case $cc_basename in
+ ec++*)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ ghcx*)
+ # Green Hills C++ Compiler
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+ ;;
+
+ freebsd[[12]]*)
+ # C++ shared libraries reported to be fairly broken before
+ # switch to ELF
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+
+ freebsd-elf*)
+ _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+ ;;
+
+ freebsd* | dragonfly*)
+ # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF
+ # conventions
+ _LT_TAGVAR(ld_shlibs, $1)=yes
+ ;;
+
+ gnu*)
+ ;;
+
+ hpux9*)
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH,
+ # but as the default
+ # location of the library.
+
+ case $cc_basename in
+ CC*)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ aCC*)
+ _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed'
+ ;;
+ *)
+ if test "$GXX" = yes; then
+ _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+ else
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+ esac
+ ;;
+
+ hpux10*|hpux11*)
+ if test $with_gnu_ld = no; then
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ case $host_cpu in
+ hppa*64*|ia64*)
+ ;;
+ *)
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+ ;;
+ esac
+ fi
+ case $host_cpu in
+ hppa*64*|ia64*)
+ _LT_TAGVAR(hardcode_direct, $1)=no
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+ *)
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH,
+ # but as the default
+ # location of the library.
+ ;;
+ esac
+
+ case $cc_basename in
+ CC*)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ aCC*)
+ case $host_cpu in
+ hppa*64*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ ia64*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ *)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ esac
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed'
+ ;;
+ *)
+ if test "$GXX" = yes; then
+ if test $with_gnu_ld = no; then
+ case $host_cpu in
+ hppa*64*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ ia64*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ *)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ esac
+ fi
+ else
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+ esac
+ ;;
+
+ interix[[3-9]]*)
+ _LT_TAGVAR(hardcode_direct, $1)=no
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+ # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+ # Instead, shared libraries are loaded at an image base (0x10000000 by
+ # default) and relocated if they conflict, which is a slow very memory
+ # consuming and fragmenting process. To avoid this, we pick a random,
+ # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+ # time. Moving up from 0x10000000 also allows more sbrk(2) space.
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ ;;
+ irix5* | irix6*)
+ case $cc_basename in
+ CC*)
+ # SGI C++
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib'
+
+ # Archives containing C++ object files must be created using
+ # "CC -ar", where "CC" is the IRIX C++ compiler. This is
+ # necessary to make sure instantiated templates are included
+ # in the archive.
+ _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs'
+ ;;
+ *)
+ if test "$GXX" = yes; then
+ if test "$with_gnu_ld" = no; then
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ else
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` -o $lib'
+ fi
+ fi
+ _LT_TAGVAR(link_all_deplibs, $1)=yes
+ ;;
+ esac
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+ _LT_TAGVAR(inherit_rpath, $1)=yes
+ ;;
+
+ linux* | k*bsd*-gnu)
+ case $cc_basename in
+ KCC*)
+ # Kuck and Associates, Inc. (KAI) C++ Compiler
+
+ # KCC will only create a shared library if the output file
+ # ends with ".so" (or ".sl" for HP-UX), so rename the library
+ # to its proper name (with version) after linking.
+ _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib'
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed'
+
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+
+ # Archives containing C++ object files must be created using
+ # "CC -Bstatic", where "CC" is the KAI C++ compiler.
+ _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs'
+ ;;
+ icpc* | ecpc* )
+ # Intel C++
+ with_gnu_ld=yes
+ # version 8.0 and above of icpc choke on multiply defined symbols
+ # if we add $predep_objects and $postdep_objects, however 7.1 and
+ # earlier do not add the objects themselves.
+ case `$CC -V 2>&1` in
+ *"Version 7."*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ ;;
+ *) # Version 8.0 or newer
+ tmp_idyn=
+ case $host_cpu in
+ ia64*) tmp_idyn=' -i_dynamic';;
+ esac
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ ;;
+ esac
+ _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive'
+ ;;
+ pgCC* | pgcpp*)
+ # Portland Group C++ compiler
+ case `$CC -V` in
+ *pgCC\ [[1-5]]* | *pgcpp\ [[1-5]]*)
+ _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~
+ rm -rf $tpldir~
+ $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~
+ compile_command="$compile_command `find $tpldir -name \*.o | $NL2SP`"'
+ _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~
+ rm -rf $tpldir~
+ $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~
+ $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | $NL2SP`~
+ $RANLIB $oldlib'
+ _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~
+ rm -rf $tpldir~
+ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~
+ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~
+ rm -rf $tpldir~
+ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~
+ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib'
+ ;;
+ *) # Version 6 will use weak symbols
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib'
+ ;;
+ esac
+
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir'
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive'
+ ;;
+ cxx*)
+ # Compaq C++
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols'
+
+ runpath_var=LD_RUN_PATH
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`$ECHO "X$templist" | $Xsed -e "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed'
+ ;;
+ xl*)
+ # IBM XL 8.0 on PPC, with GNU ld
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+ _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ if test "x$supports_anon_versioning" = xyes; then
+ _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~
+ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+ echo "local: *; };" >> $output_objdir/$libname.ver~
+ $CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'
+ fi
+ ;;
+ *)
+ case `$CC -V 2>&1 | sed 5q` in
+ *Sun\ C*)
+ # Sun C++ 5.9
+ _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs'
+ _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive'
+ _LT_TAGVAR(compiler_needs_object, $1)=yes
+
+ # Not sure whether something based on
+ # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1
+ # would be better.
+ output_verbose_link_cmd='echo'
+
+ # Archives containing C++ object files must be created using
+ # "CC -xar", where "CC" is the Sun C++ compiler. This is
+ # necessary to make sure instantiated templates are included
+ # in the archive.
+ _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs'
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+
+ lynxos*)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+
+ m88k*)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+
+ mvs*)
+ case $cc_basename in
+ cxx*)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+ ;;
+
+ netbsd*)
+ if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+ _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags'
+ wlarc=
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ fi
+ # Workaround some broken pre-1.5 toolchains
+ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"'
+ ;;
+
+ *nto* | *qnx*)
+ _LT_TAGVAR(ld_shlibs, $1)=yes
+ ;;
+
+ openbsd2*)
+ # C++ shared libraries are fairly broken
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+
+ openbsd*)
+ if test -f /usr/libexec/ld.so; then
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib'
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+ _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+ fi
+ output_verbose_link_cmd=echo
+ else
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+
+ osf3* | osf4* | osf5*)
+ case $cc_basename in
+ KCC*)
+ # Kuck and Associates, Inc. (KAI) C++ Compiler
+
+ # KCC will only create a shared library if the output file
+ # ends with ".so" (or ".sl" for HP-UX), so rename the library
+ # to its proper name (with version) after linking.
+ _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ # Archives containing C++ object files must be created using
+ # the KAI C++ compiler.
+ case $host in
+ osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;;
+ *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;;
+ esac
+ ;;
+ RCC*)
+ # Rational C++ 2.4.1
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ cxx*)
+ case $host in
+ osf3*)
+ _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && $ECHO "X${wl}-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+ ;;
+ *)
+ _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~
+ echo "-hidden">> $lib.exp~
+ $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname ${wl}-input ${wl}$lib.exp `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib~
+ $RM $lib.exp'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
+ ;;
+ esac
+
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`$ECHO "X$templist" | $Xsed -e "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed'
+ ;;
+ *)
+ if test "$GXX" = yes && test "$with_gnu_ld" = no; then
+ _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
+ case $host in
+ osf3*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ ;;
+ *)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ ;;
+ esac
+
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"'
+
+ else
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+ esac
+ ;;
+
+ psos*)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+
+ sunos4*)
+ case $cc_basename in
+ CC*)
+ # Sun C++ 4.x
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ lcc*)
+ # Lucid
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+ ;;
+
+ solaris*)
+ case $cc_basename in
+ CC*)
+ # Sun C++ 4.2, 5.x and Centerline C++
+ _LT_TAGVAR(archive_cmds_need_lc,$1)=yes
+ _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs'
+ _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+ $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
+
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ case $host_os in
+ solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
+ *)
+ # The compiler driver will combine and reorder linker options,
+ # but understands `-z linker_flag'.
+ # Supported since Solaris 2.6 (maybe 2.5.1?)
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract'
+ ;;
+ esac
+ _LT_TAGVAR(link_all_deplibs, $1)=yes
+
+ output_verbose_link_cmd='echo'
+
+ # Archives containing C++ object files must be created using
+ # "CC -xar", where "CC" is the Sun C++ compiler. This is
+ # necessary to make sure instantiated templates are included
+ # in the archive.
+ _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs'
+ ;;
+ gcx*)
+ # Green Hills C++ Compiler
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+
+ # The C++ compiler must be used to create the archive.
+ _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs'
+ ;;
+ *)
+ # GNU C++ compiler with Solaris linker
+ if test "$GXX" = yes && test "$with_gnu_ld" = no; then
+ _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs'
+ if $CC --version | $GREP -v '^2\.7' > /dev/null; then
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+ $CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"'
+ else
+ # g++ 2.7 appears to require `-G' NOT `-shared' on this
+ # platform.
+ _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+ $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"'
+ fi
+
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir'
+ case $host_os in
+ solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
+ *)
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract'
+ ;;
+ esac
+ fi
+ ;;
+ esac
+ ;;
+
+ sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*)
+ _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'
+ _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ runpath_var='LD_RUN_PATH'
+
+ case $cc_basename in
+ CC*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ ;;
+
+ sysv5* | sco3.2v5* | sco5v6*)
+ # Note: We can NOT use -z defs as we might desire, because we do not
+ # link with -lc, and that would cause any symbols used from libc to
+ # always be unresolved, which means just about no library would
+ # ever link correctly. If we're not using GNU ld we use -z text
+ # though, which does catch some bad symbols but isn't as heavy-handed
+ # as -z defs.
+ _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'
+ _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs'
+ _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=':'
+ _LT_TAGVAR(link_all_deplibs, $1)=yes
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport'
+ runpath_var='LD_RUN_PATH'
+
+ case $cc_basename in
+ CC*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ ;;
+
+ tandem*)
+ case $cc_basename in
+ NCC*)
+ # NonStop-UX NCC 3.20
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+ ;;
+
+ vxworks*)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+
+ *)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+
+ AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)])
+ test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no
+
+ _LT_TAGVAR(GCC, $1)="$GXX"
+ _LT_TAGVAR(LD, $1)="$LD"
+
+ ## CAVEAT EMPTOR:
+ ## There is no encapsulation within the following macros, do not change
+ ## the running order or otherwise move them around unless you know exactly
+ ## what you are doing...
+ _LT_SYS_HIDDEN_LIBDEPS($1)
+ _LT_COMPILER_PIC($1)
+ _LT_COMPILER_C_O($1)
+ _LT_COMPILER_FILE_LOCKS($1)
+ _LT_LINKER_SHLIBS($1)
+ _LT_SYS_DYNAMIC_LINKER($1)
+ _LT_LINKER_HARDCODE_LIBPATH($1)
+
+ _LT_CONFIG($1)
+ fi # test -n "$compiler"
+
+ CC=$lt_save_CC
+ LDCXX=$LD
+ LD=$lt_save_LD
+ GCC=$lt_save_GCC
+ with_gnu_ld=$lt_save_with_gnu_ld
+ lt_cv_path_LDCXX=$lt_cv_path_LD
+ lt_cv_path_LD=$lt_save_path_LD
+ lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld
+ lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld
+fi # test "$_lt_caught_CXX_error" != yes
+
+AC_LANG_POP
+])# _LT_LANG_CXX_CONFIG
+
+
+# _LT_SYS_HIDDEN_LIBDEPS([TAGNAME])
+# ---------------------------------
+# Figure out "hidden" library dependencies from verbose
+# compiler output when linking a shared library.
+# Parse the compiler output and extract the necessary
+# objects, libraries and library flags.
+m4_defun([_LT_SYS_HIDDEN_LIBDEPS],
+[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+# Dependencies to place before and after the object being linked:
+_LT_TAGVAR(predep_objects, $1)=
+_LT_TAGVAR(postdep_objects, $1)=
+_LT_TAGVAR(predeps, $1)=
+_LT_TAGVAR(postdeps, $1)=
+_LT_TAGVAR(compiler_lib_search_path, $1)=
+
+dnl we can't use the lt_simple_compile_test_code here,
+dnl because it contains code intended for an executable,
+dnl not a library. It's possible we should let each
+dnl tag define a new lt_????_link_test_code variable,
+dnl but it's only used here...
+m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF
+int a;
+void foo (void) { a = 0; }
+_LT_EOF
+], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF
+class Foo
+{
+public:
+ Foo (void) { a = 0; }
+private:
+ int a;
+};
+_LT_EOF
+], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF
+ subroutine foo
+ implicit none
+ integer*4 a
+ a=0
+ return
+ end
+_LT_EOF
+], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF
+ subroutine foo
+ implicit none
+ integer a
+ a=0
+ return
+ end
+_LT_EOF
+], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF
+public class foo {
+ private int a;
+ public void bar (void) {
+ a = 0;
+ }
+};
+_LT_EOF
+])
+dnl Parse the compiler output and extract the necessary
+dnl objects, libraries and library flags.
+if AC_TRY_EVAL(ac_compile); then
+ # Parse the compiler output and extract the necessary
+ # objects, libraries and library flags.
+
+ # Sentinel used to keep track of whether or not we are before
+ # the conftest object file.
+ pre_test_object_deps_done=no
+
+ for p in `eval "$output_verbose_link_cmd"`; do
+ case $p in
+
+ -L* | -R* | -l*)
+ # Some compilers place space between "-{L,R}" and the path.
+ # Remove the space.
+ if test $p = "-L" ||
+ test $p = "-R"; then
+ prev=$p
+ continue
+ else
+ prev=
+ fi
+
+ if test "$pre_test_object_deps_done" = no; then
+ case $p in
+ -L* | -R*)
+ # Internal compiler library paths should come after those
+ # provided the user. The postdeps already come after the
+ # user supplied libs so there is no need to process them.
+ if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then
+ _LT_TAGVAR(compiler_lib_search_path, $1)="${prev}${p}"
+ else
+ _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} ${prev}${p}"
+ fi
+ ;;
+ # The "-l" case would never come before the object being
+ # linked, so don't bother handling this case.
+ esac
+ else
+ if test -z "$_LT_TAGVAR(postdeps, $1)"; then
+ _LT_TAGVAR(postdeps, $1)="${prev}${p}"
+ else
+ _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} ${prev}${p}"
+ fi
+ fi
+ ;;
+
+ *.$objext)
+ # This assumes that the test object file only shows up
+ # once in the compiler output.
+ if test "$p" = "conftest.$objext"; then
+ pre_test_object_deps_done=yes
+ continue
+ fi
+
+ if test "$pre_test_object_deps_done" = no; then
+ if test -z "$_LT_TAGVAR(predep_objects, $1)"; then
+ _LT_TAGVAR(predep_objects, $1)="$p"
+ else
+ _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p"
+ fi
+ else
+ if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then
+ _LT_TAGVAR(postdep_objects, $1)="$p"
+ else
+ _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p"
+ fi
+ fi
+ ;;
+
+ *) ;; # Ignore the rest.
+
+ esac
+ done
+
+ # Clean up.
+ rm -f a.out a.exe
+else
+ echo "libtool.m4: error: problem compiling $1 test program"
+fi
+
+$RM -f confest.$objext
+
+# PORTME: override above test on systems where it is broken
+m4_if([$1], [CXX],
+[case $host_os in
+interix[[3-9]]*)
+ # Interix 3.5 installs completely hosed .la files for C++, so rather than
+ # hack all around it, let's just trust "g++" to DTRT.
+ _LT_TAGVAR(predep_objects,$1)=
+ _LT_TAGVAR(postdep_objects,$1)=
+ _LT_TAGVAR(postdeps,$1)=
+ ;;
+
+linux*)
+ case `$CC -V 2>&1 | sed 5q` in
+ *Sun\ C*)
+ # Sun C++ 5.9
+
+ # The more standards-conforming stlport4 library is
+ # incompatible with the Cstd library. Avoid specifying
+ # it if it's in CXXFLAGS. Ignore libCrun as
+ # -library=stlport4 depends on it.
+ case " $CXX $CXXFLAGS " in
+ *" -library=stlport4 "*)
+ solaris_use_stlport4=yes
+ ;;
+ esac
+
+ if test "$solaris_use_stlport4" != yes; then
+ _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun'
+ fi
+ ;;
+ esac
+ ;;
+
+solaris*)
+ case $cc_basename in
+ CC*)
+ # The more standards-conforming stlport4 library is
+ # incompatible with the Cstd library. Avoid specifying
+ # it if it's in CXXFLAGS. Ignore libCrun as
+ # -library=stlport4 depends on it.
+ case " $CXX $CXXFLAGS " in
+ *" -library=stlport4 "*)
+ solaris_use_stlport4=yes
+ ;;
+ esac
+
+ # Adding this requires a known-good setup of shared libraries for
+ # Sun compiler versions before 5.6, else PIC objects from an old
+ # archive will be linked into the output, leading to subtle bugs.
+ if test "$solaris_use_stlport4" != yes; then
+ _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun'
+ fi
+ ;;
+ esac
+ ;;
+esac
+])
+
+case " $_LT_TAGVAR(postdeps, $1) " in
+*" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;;
+esac
+ _LT_TAGVAR(compiler_lib_search_dirs, $1)=
+if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then
+ _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | ${SED} -e 's! -L! !g' -e 's!^ !!'`
+fi
+_LT_TAGDECL([], [compiler_lib_search_dirs], [1],
+ [The directories searched by this compiler when creating a shared library])
+_LT_TAGDECL([], [predep_objects], [1],
+ [Dependencies to place before and after the objects being linked to
+ create a shared library])
+_LT_TAGDECL([], [postdep_objects], [1])
+_LT_TAGDECL([], [predeps], [1])
+_LT_TAGDECL([], [postdeps], [1])
+_LT_TAGDECL([], [compiler_lib_search_path], [1],
+ [The library search path used internally by the compiler when linking
+ a shared library])
+])# _LT_SYS_HIDDEN_LIBDEPS
+
+
+# _LT_PROG_F77
+# ------------
+# Since AC_PROG_F77 is broken, in that it returns the empty string
+# if there is no fortran compiler, we have our own version here.
+m4_defun([_LT_PROG_F77],
+[
+pushdef([AC_MSG_ERROR], [_lt_disable_F77=yes])
+AC_PROG_F77
+if test -z "$F77" || test "X$F77" = "Xno"; then
+ _lt_disable_F77=yes
+fi
+popdef([AC_MSG_ERROR])
+])# _LT_PROG_F77
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([_LT_PROG_F77], [])
+
+
+# _LT_LANG_F77_CONFIG([TAG])
+# --------------------------
+# Ensure that the configuration variables for a Fortran 77 compiler are
+# suitably defined. These variables are subsequently used by _LT_CONFIG
+# to write the compiler configuration to `libtool'.
+m4_defun([_LT_LANG_F77_CONFIG],
+[AC_REQUIRE([_LT_PROG_F77])dnl
+AC_LANG_PUSH(Fortran 77)
+
+_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+_LT_TAGVAR(allow_undefined_flag, $1)=
+_LT_TAGVAR(always_export_symbols, $1)=no
+_LT_TAGVAR(archive_expsym_cmds, $1)=
+_LT_TAGVAR(export_dynamic_flag_spec, $1)=
+_LT_TAGVAR(hardcode_direct, $1)=no
+_LT_TAGVAR(hardcode_direct_absolute, $1)=no
+_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
+_LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)=
+_LT_TAGVAR(hardcode_libdir_separator, $1)=
+_LT_TAGVAR(hardcode_minus_L, $1)=no
+_LT_TAGVAR(hardcode_automatic, $1)=no
+_LT_TAGVAR(inherit_rpath, $1)=no
+_LT_TAGVAR(module_cmds, $1)=
+_LT_TAGVAR(module_expsym_cmds, $1)=
+_LT_TAGVAR(link_all_deplibs, $1)=unknown
+_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+_LT_TAGVAR(no_undefined_flag, $1)=
+_LT_TAGVAR(whole_archive_flag_spec, $1)=
+_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+
+# Source file extension for f77 test sources.
+ac_ext=f
+
+# Object file extension for compiled f77 test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# No sense in running all these tests if we already determined that
+# the F77 compiler isn't working. Some variables (like enable_shared)
+# are currently assumed to apply to all compilers on this platform,
+# and will be corrupted by setting them based on a non-working compiler.
+if test "$_lt_disable_F77" != yes; then
+ # Code to be used in simple compile tests
+ lt_simple_compile_test_code="\
+ subroutine t
+ return
+ end
+"
+
+ # Code to be used in simple link tests
+ lt_simple_link_test_code="\
+ program t
+ end
+"
+
+ # ltmain only uses $CC for tagged configurations so make sure $CC is set.
+ _LT_TAG_COMPILER
+
+ # save warnings/boilerplate of simple test code
+ _LT_COMPILER_BOILERPLATE
+ _LT_LINKER_BOILERPLATE
+
+ # Allow CC to be a program name with arguments.
+ lt_save_CC="$CC"
+ lt_save_GCC=$GCC
+ CC=${F77-"f77"}
+ compiler=$CC
+ _LT_TAGVAR(compiler, $1)=$CC
+ _LT_CC_BASENAME([$compiler])
+ GCC=$G77
+ if test -n "$compiler"; then
+ AC_MSG_CHECKING([if libtool supports shared libraries])
+ AC_MSG_RESULT([$can_build_shared])
+
+ AC_MSG_CHECKING([whether to build shared libraries])
+ test "$can_build_shared" = "no" && enable_shared=no
+
+ # On AIX, shared libraries and static libraries use the same namespace, and
+ # are all built from PIC.
+ case $host_os in
+ aix3*)
+ test "$enable_shared" = yes && enable_static=no
+ if test -n "$RANLIB"; then
+ archive_cmds="$archive_cmds~\$RANLIB \$lib"
+ postinstall_cmds='$RANLIB $lib'
+ fi
+ ;;
+ aix[[4-9]]*)
+ if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
+ test "$enable_shared" = yes && enable_static=no
+ fi
+ ;;
+ esac
+ AC_MSG_RESULT([$enable_shared])
+
+ AC_MSG_CHECKING([whether to build static libraries])
+ # Make sure either enable_shared or enable_static is yes.
+ test "$enable_shared" = yes || enable_static=yes
+ AC_MSG_RESULT([$enable_static])
+
+ _LT_TAGVAR(GCC, $1)="$G77"
+ _LT_TAGVAR(LD, $1)="$LD"
+
+ ## CAVEAT EMPTOR:
+ ## There is no encapsulation within the following macros, do not change
+ ## the running order or otherwise move them around unless you know exactly
+ ## what you are doing...
+ _LT_COMPILER_PIC($1)
+ _LT_COMPILER_C_O($1)
+ _LT_COMPILER_FILE_LOCKS($1)
+ _LT_LINKER_SHLIBS($1)
+ _LT_SYS_DYNAMIC_LINKER($1)
+ _LT_LINKER_HARDCODE_LIBPATH($1)
+
+ _LT_CONFIG($1)
+ fi # test -n "$compiler"
+
+ GCC=$lt_save_GCC
+ CC="$lt_save_CC"
+fi # test "$_lt_disable_F77" != yes
+
+AC_LANG_POP
+])# _LT_LANG_F77_CONFIG
+
+
+# _LT_PROG_FC
+# -----------
+# Since AC_PROG_FC is broken, in that it returns the empty string
+# if there is no fortran compiler, we have our own version here.
+m4_defun([_LT_PROG_FC],
+[
+pushdef([AC_MSG_ERROR], [_lt_disable_FC=yes])
+AC_PROG_FC
+if test -z "$FC" || test "X$FC" = "Xno"; then
+ _lt_disable_FC=yes
+fi
+popdef([AC_MSG_ERROR])
+])# _LT_PROG_FC
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([_LT_PROG_FC], [])
+
+
+# _LT_LANG_FC_CONFIG([TAG])
+# -------------------------
+# Ensure that the configuration variables for a Fortran compiler are
+# suitably defined. These variables are subsequently used by _LT_CONFIG
+# to write the compiler configuration to `libtool'.
+m4_defun([_LT_LANG_FC_CONFIG],
+[AC_REQUIRE([_LT_PROG_FC])dnl
+AC_LANG_PUSH(Fortran)
+
+_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+_LT_TAGVAR(allow_undefined_flag, $1)=
+_LT_TAGVAR(always_export_symbols, $1)=no
+_LT_TAGVAR(archive_expsym_cmds, $1)=
+_LT_TAGVAR(export_dynamic_flag_spec, $1)=
+_LT_TAGVAR(hardcode_direct, $1)=no
+_LT_TAGVAR(hardcode_direct_absolute, $1)=no
+_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
+_LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)=
+_LT_TAGVAR(hardcode_libdir_separator, $1)=
+_LT_TAGVAR(hardcode_minus_L, $1)=no
+_LT_TAGVAR(hardcode_automatic, $1)=no
+_LT_TAGVAR(inherit_rpath, $1)=no
+_LT_TAGVAR(module_cmds, $1)=
+_LT_TAGVAR(module_expsym_cmds, $1)=
+_LT_TAGVAR(link_all_deplibs, $1)=unknown
+_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+_LT_TAGVAR(no_undefined_flag, $1)=
+_LT_TAGVAR(whole_archive_flag_spec, $1)=
+_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+
+# Source file extension for fc test sources.
+ac_ext=${ac_fc_srcext-f}
+
+# Object file extension for compiled fc test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# No sense in running all these tests if we already determined that
+# the FC compiler isn't working. Some variables (like enable_shared)
+# are currently assumed to apply to all compilers on this platform,
+# and will be corrupted by setting them based on a non-working compiler.
+if test "$_lt_disable_FC" != yes; then
+ # Code to be used in simple compile tests
+ lt_simple_compile_test_code="\
+ subroutine t
+ return
+ end
+"
+
+ # Code to be used in simple link tests
+ lt_simple_link_test_code="\
+ program t
+ end
+"
+
+ # ltmain only uses $CC for tagged configurations so make sure $CC is set.
+ _LT_TAG_COMPILER
+
+ # save warnings/boilerplate of simple test code
+ _LT_COMPILER_BOILERPLATE
+ _LT_LINKER_BOILERPLATE
+
+ # Allow CC to be a program name with arguments.
+ lt_save_CC="$CC"
+ lt_save_GCC=$GCC
+ CC=${FC-"f95"}
+ compiler=$CC
+ GCC=$ac_cv_fc_compiler_gnu
+
+ _LT_TAGVAR(compiler, $1)=$CC
+ _LT_CC_BASENAME([$compiler])
+
+ if test -n "$compiler"; then
+ AC_MSG_CHECKING([if libtool supports shared libraries])
+ AC_MSG_RESULT([$can_build_shared])
+
+ AC_MSG_CHECKING([whether to build shared libraries])
+ test "$can_build_shared" = "no" && enable_shared=no
+
+ # On AIX, shared libraries and static libraries use the same namespace, and
+ # are all built from PIC.
+ case $host_os in
+ aix3*)
+ test "$enable_shared" = yes && enable_static=no
+ if test -n "$RANLIB"; then
+ archive_cmds="$archive_cmds~\$RANLIB \$lib"
+ postinstall_cmds='$RANLIB $lib'
+ fi
+ ;;
+ aix[[4-9]]*)
+ if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
+ test "$enable_shared" = yes && enable_static=no
+ fi
+ ;;
+ esac
+ AC_MSG_RESULT([$enable_shared])
+
+ AC_MSG_CHECKING([whether to build static libraries])
+ # Make sure either enable_shared or enable_static is yes.
+ test "$enable_shared" = yes || enable_static=yes
+ AC_MSG_RESULT([$enable_static])
+
+ _LT_TAGVAR(GCC, $1)="$ac_cv_fc_compiler_gnu"
+ _LT_TAGVAR(LD, $1)="$LD"
+
+ ## CAVEAT EMPTOR:
+ ## There is no encapsulation within the following macros, do not change
+ ## the running order or otherwise move them around unless you know exactly
+ ## what you are doing...
+ _LT_SYS_HIDDEN_LIBDEPS($1)
+ _LT_COMPILER_PIC($1)
+ _LT_COMPILER_C_O($1)
+ _LT_COMPILER_FILE_LOCKS($1)
+ _LT_LINKER_SHLIBS($1)
+ _LT_SYS_DYNAMIC_LINKER($1)
+ _LT_LINKER_HARDCODE_LIBPATH($1)
+
+ _LT_CONFIG($1)
+ fi # test -n "$compiler"
+
+ GCC=$lt_save_GCC
+ CC="$lt_save_CC"
+fi # test "$_lt_disable_FC" != yes
+
+AC_LANG_POP
+])# _LT_LANG_FC_CONFIG
+
+
+# _LT_LANG_GCJ_CONFIG([TAG])
+# --------------------------
+# Ensure that the configuration variables for the GNU Java Compiler compiler
+# are suitably defined. These variables are subsequently used by _LT_CONFIG
+# to write the compiler configuration to `libtool'.
+m4_defun([_LT_LANG_GCJ_CONFIG],
+[AC_REQUIRE([LT_PROG_GCJ])dnl
+AC_LANG_SAVE
+
+# Source file extension for Java test sources.
+ac_ext=java
+
+# Object file extension for compiled Java test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="class foo {}"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }'
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+_LT_TAG_COMPILER
+
+# save warnings/boilerplate of simple test code
+_LT_COMPILER_BOILERPLATE
+_LT_LINKER_BOILERPLATE
+
+# Allow CC to be a program name with arguments.
+lt_save_CC="$CC"
+lt_save_GCC=$GCC
+GCC=yes
+CC=${GCJ-"gcj"}
+compiler=$CC
+_LT_TAGVAR(compiler, $1)=$CC
+_LT_TAGVAR(LD, $1)="$LD"
+_LT_CC_BASENAME([$compiler])
+
+# GCJ did not exist at the time GCC didn't implicitly link libc in.
+_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+
+_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+
+if test -n "$compiler"; then
+ _LT_COMPILER_NO_RTTI($1)
+ _LT_COMPILER_PIC($1)
+ _LT_COMPILER_C_O($1)
+ _LT_COMPILER_FILE_LOCKS($1)
+ _LT_LINKER_SHLIBS($1)
+ _LT_LINKER_HARDCODE_LIBPATH($1)
+
+ _LT_CONFIG($1)
+fi
+
+AC_LANG_RESTORE
+
+GCC=$lt_save_GCC
+CC="$lt_save_CC"
+])# _LT_LANG_GCJ_CONFIG
+
+
+# _LT_LANG_RC_CONFIG([TAG])
+# -------------------------
+# Ensure that the configuration variables for the Windows resource compiler
+# are suitably defined. These variables are subsequently used by _LT_CONFIG
+# to write the compiler configuration to `libtool'.
+m4_defun([_LT_LANG_RC_CONFIG],
+[AC_REQUIRE([LT_PROG_RC])dnl
+AC_LANG_SAVE
+
+# Source file extension for RC test sources.
+ac_ext=rc
+
+# Object file extension for compiled RC test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }'
+
+# Code to be used in simple link tests
+lt_simple_link_test_code="$lt_simple_compile_test_code"
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+_LT_TAG_COMPILER
+
+# save warnings/boilerplate of simple test code
+_LT_COMPILER_BOILERPLATE
+_LT_LINKER_BOILERPLATE
+
+# Allow CC to be a program name with arguments.
+lt_save_CC="$CC"
+lt_save_GCC=$GCC
+GCC=
+CC=${RC-"windres"}
+compiler=$CC
+_LT_TAGVAR(compiler, $1)=$CC
+_LT_CC_BASENAME([$compiler])
+_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes
+
+if test -n "$compiler"; then
+ :
+ _LT_CONFIG($1)
+fi
+
+GCC=$lt_save_GCC
+AC_LANG_RESTORE
+CC="$lt_save_CC"
+])# _LT_LANG_RC_CONFIG
+
+
+# LT_PROG_GCJ
+# -----------
+AC_DEFUN([LT_PROG_GCJ],
+[m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ],
+ [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ],
+ [AC_CHECK_TOOL(GCJ, gcj,)
+ test "x${GCJFLAGS+set}" = xset || GCJFLAGS="-g -O2"
+ AC_SUBST(GCJFLAGS)])])[]dnl
+])
+
+# Old name:
+AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([LT_AC_PROG_GCJ], [])
+
+
+# LT_PROG_RC
+# ----------
+AC_DEFUN([LT_PROG_RC],
+[AC_CHECK_TOOL(RC, windres,)
+])
+
+# Old name:
+AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([LT_AC_PROG_RC], [])
+
+
+# _LT_DECL_EGREP
+# --------------
+# If we don't have a new enough Autoconf to choose the best grep
+# available, choose the one first in the user's PATH.
+m4_defun([_LT_DECL_EGREP],
+[AC_REQUIRE([AC_PROG_EGREP])dnl
+AC_REQUIRE([AC_PROG_FGREP])dnl
+test -z "$GREP" && GREP=grep
+_LT_DECL([], [GREP], [1], [A grep program that handles long lines])
+_LT_DECL([], [EGREP], [1], [An ERE matcher])
+_LT_DECL([], [FGREP], [1], [A literal string matcher])
+dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too
+AC_SUBST([GREP])
+])
+
+
+# _LT_DECL_OBJDUMP
+# --------------
+# If we don't have a new enough Autoconf to choose the best objdump
+# available, choose the one first in the user's PATH.
+m4_defun([_LT_DECL_OBJDUMP],
+[AC_CHECK_TOOL(OBJDUMP, objdump, false)
+test -z "$OBJDUMP" && OBJDUMP=objdump
+_LT_DECL([], [OBJDUMP], [1], [An object symbol dumper])
+AC_SUBST([OBJDUMP])
+])
+
+
+# _LT_DECL_SED
+# ------------
+# Check for a fully-functional sed program, that truncates
+# as few characters as possible. Prefer GNU sed if found.
+m4_defun([_LT_DECL_SED],
+[AC_PROG_SED
+test -z "$SED" && SED=sed
+Xsed="$SED -e 1s/^X//"
+_LT_DECL([], [SED], [1], [A sed program that does not truncate output])
+_LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"],
+ [Sed that helps us avoid accidentally triggering echo(1) options like -n])
+])# _LT_DECL_SED
+
+m4_ifndef([AC_PROG_SED], [
+# NOTE: This macro has been submitted for inclusion into #
+# GNU Autoconf as AC_PROG_SED. When it is available in #
+# a released version of Autoconf we should remove this #
+# macro and use it instead. #
+
+m4_defun([AC_PROG_SED],
+[AC_MSG_CHECKING([for a sed that does not truncate output])
+AC_CACHE_VAL(lt_cv_path_SED,
+[# Loop through the user's path and test for sed and gsed.
+# Then use that list of sed's as ones to test for truncation.
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for lt_ac_prog in sed gsed; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then
+ lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext"
+ fi
+ done
+ done
+done
+IFS=$as_save_IFS
+lt_ac_max=0
+lt_ac_count=0
+# Add /usr/xpg4/bin/sed as it is typically found on Solaris
+# along with /bin/sed that truncates output.
+for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do
+ test ! -f $lt_ac_sed && continue
+ cat /dev/null > conftest.in
+ lt_ac_count=0
+ echo $ECHO_N "0123456789$ECHO_C" >conftest.in
+ # Check for GNU sed and select it if it is found.
+ if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then
+ lt_cv_path_SED=$lt_ac_sed
+ break
+ fi
+ while true; do
+ cat conftest.in conftest.in >conftest.tmp
+ mv conftest.tmp conftest.in
+ cp conftest.in conftest.nl
+ echo >>conftest.nl
+ $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break
+ cmp -s conftest.out conftest.nl || break
+ # 10000 chars as input seems more than enough
+ test $lt_ac_count -gt 10 && break
+ lt_ac_count=`expr $lt_ac_count + 1`
+ if test $lt_ac_count -gt $lt_ac_max; then
+ lt_ac_max=$lt_ac_count
+ lt_cv_path_SED=$lt_ac_sed
+ fi
+ done
+done
+])
+SED=$lt_cv_path_SED
+AC_SUBST([SED])
+AC_MSG_RESULT([$SED])
+])#AC_PROG_SED
+])#m4_ifndef
+
+# Old name:
+AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([LT_AC_PROG_SED], [])
+
+
+# _LT_CHECK_SHELL_FEATURES
+# ------------------------
+# Find out whether the shell is Bourne or XSI compatible,
+# or has some other useful features.
+m4_defun([_LT_CHECK_SHELL_FEATURES],
+[AC_MSG_CHECKING([whether the shell understands some XSI constructs])
+# Try some XSI features
+xsi_shell=no
+( _lt_dummy="a/b/c"
+ test "${_lt_dummy##*/},${_lt_dummy%/*},"${_lt_dummy%"$_lt_dummy"}, \
+ = c,a/b,, \
+ && eval 'test $(( 1 + 1 )) -eq 2 \
+ && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \
+ && xsi_shell=yes
+AC_MSG_RESULT([$xsi_shell])
+_LT_CONFIG_LIBTOOL_INIT([xsi_shell='$xsi_shell'])
+
+AC_MSG_CHECKING([whether the shell understands "+="])
+lt_shell_append=no
+( foo=bar; set foo baz; eval "$[1]+=\$[2]" && test "$foo" = barbaz ) \
+ >/dev/null 2>&1 \
+ && lt_shell_append=yes
+AC_MSG_RESULT([$lt_shell_append])
+_LT_CONFIG_LIBTOOL_INIT([lt_shell_append='$lt_shell_append'])
+
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+ lt_unset=unset
+else
+ lt_unset=false
+fi
+_LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl
+
+# test EBCDIC or ASCII
+case `echo X|tr X '\101'` in
+ A) # ASCII based system
+ # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr
+ lt_SP2NL='tr \040 \012'
+ lt_NL2SP='tr \015\012 \040\040'
+ ;;
+ *) # EBCDIC based system
+ lt_SP2NL='tr \100 \n'
+ lt_NL2SP='tr \r\n \100\100'
+ ;;
+esac
+_LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl
+_LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl
+])# _LT_CHECK_SHELL_FEATURES
+
+
+# _LT_PROG_XSI_SHELLFNS
+# ---------------------
+# Bourne and XSI compatible variants of some useful shell functions.
+m4_defun([_LT_PROG_XSI_SHELLFNS],
+[case $xsi_shell in
+ yes)
+ cat << \_LT_EOF >> "$cfgfile"
+
+# func_dirname file append nondir_replacement
+# Compute the dirname of FILE. If nonempty, add APPEND to the result,
+# otherwise set result to NONDIR_REPLACEMENT.
+func_dirname ()
+{
+ case ${1} in
+ */*) func_dirname_result="${1%/*}${2}" ;;
+ * ) func_dirname_result="${3}" ;;
+ esac
+}
+
+# func_basename file
+func_basename ()
+{
+ func_basename_result="${1##*/}"
+}
+
+# func_dirname_and_basename file append nondir_replacement
+# perform func_basename and func_dirname in a single function
+# call:
+# dirname: Compute the dirname of FILE. If nonempty,
+# add APPEND to the result, otherwise set result
+# to NONDIR_REPLACEMENT.
+# value returned in "$func_dirname_result"
+# basename: Compute filename of FILE.
+# value retuned in "$func_basename_result"
+# Implementation must be kept synchronized with func_dirname
+# and func_basename. For efficiency, we do not delegate to
+# those functions but instead duplicate the functionality here.
+func_dirname_and_basename ()
+{
+ case ${1} in
+ */*) func_dirname_result="${1%/*}${2}" ;;
+ * ) func_dirname_result="${3}" ;;
+ esac
+ func_basename_result="${1##*/}"
+}
+
+# func_stripname prefix suffix name
+# strip PREFIX and SUFFIX off of NAME.
+# PREFIX and SUFFIX must not contain globbing or regex special
+# characters, hashes, percent signs, but SUFFIX may contain a leading
+# dot (in which case that matches only a dot).
+func_stripname ()
+{
+ # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are
+ # positional parameters, so assign one to ordinary parameter first.
+ func_stripname_result=${3}
+ func_stripname_result=${func_stripname_result#"${1}"}
+ func_stripname_result=${func_stripname_result%"${2}"}
+}
+
+# func_opt_split
+func_opt_split ()
+{
+ func_opt_split_opt=${1%%=*}
+ func_opt_split_arg=${1#*=}
+}
+
+# func_lo2o object
+func_lo2o ()
+{
+ case ${1} in
+ *.lo) func_lo2o_result=${1%.lo}.${objext} ;;
+ *) func_lo2o_result=${1} ;;
+ esac
+}
+
+# func_xform libobj-or-source
+func_xform ()
+{
+ func_xform_result=${1%.*}.lo
+}
+
+# func_arith arithmetic-term...
+func_arith ()
+{
+ func_arith_result=$(( $[*] ))
+}
+
+# func_len string
+# STRING may not start with a hyphen.
+func_len ()
+{
+ func_len_result=${#1}
+}
+
+_LT_EOF
+ ;;
+ *) # Bourne compatible functions.
+ cat << \_LT_EOF >> "$cfgfile"
+
+# func_dirname file append nondir_replacement
+# Compute the dirname of FILE. If nonempty, add APPEND to the result,
+# otherwise set result to NONDIR_REPLACEMENT.
+func_dirname ()
+{
+ # Extract subdirectory from the argument.
+ func_dirname_result=`$ECHO "X${1}" | $Xsed -e "$dirname"`
+ if test "X$func_dirname_result" = "X${1}"; then
+ func_dirname_result="${3}"
+ else
+ func_dirname_result="$func_dirname_result${2}"
+ fi
+}
+
+# func_basename file
+func_basename ()
+{
+ func_basename_result=`$ECHO "X${1}" | $Xsed -e "$basename"`
+}
+
+dnl func_dirname_and_basename
+dnl A portable version of this function is already defined in general.m4sh
+dnl so there is no need for it here.
+
+# func_stripname prefix suffix name
+# strip PREFIX and SUFFIX off of NAME.
+# PREFIX and SUFFIX must not contain globbing or regex special
+# characters, hashes, percent signs, but SUFFIX may contain a leading
+# dot (in which case that matches only a dot).
+# func_strip_suffix prefix name
+func_stripname ()
+{
+ case ${2} in
+ .*) func_stripname_result=`$ECHO "X${3}" \
+ | $Xsed -e "s%^${1}%%" -e "s%\\\\${2}\$%%"`;;
+ *) func_stripname_result=`$ECHO "X${3}" \
+ | $Xsed -e "s%^${1}%%" -e "s%${2}\$%%"`;;
+ esac
+}
+
+# sed scripts:
+my_sed_long_opt='1s/^\(-[[^=]]*\)=.*/\1/;q'
+my_sed_long_arg='1s/^-[[^=]]*=//'
+
+# func_opt_split
+func_opt_split ()
+{
+ func_opt_split_opt=`$ECHO "X${1}" | $Xsed -e "$my_sed_long_opt"`
+ func_opt_split_arg=`$ECHO "X${1}" | $Xsed -e "$my_sed_long_arg"`
+}
+
+# func_lo2o object
+func_lo2o ()
+{
+ func_lo2o_result=`$ECHO "X${1}" | $Xsed -e "$lo2o"`
+}
+
+# func_xform libobj-or-source
+func_xform ()
+{
+ func_xform_result=`$ECHO "X${1}" | $Xsed -e 's/\.[[^.]]*$/.lo/'`
+}
+
+# func_arith arithmetic-term...
+func_arith ()
+{
+ func_arith_result=`expr "$[@]"`
+}
+
+# func_len string
+# STRING may not start with a hyphen.
+func_len ()
+{
+ func_len_result=`expr "$[1]" : ".*" 2>/dev/null || echo $max_cmd_len`
+}
+
+_LT_EOF
+esac
+
+case $lt_shell_append in
+ yes)
+ cat << \_LT_EOF >> "$cfgfile"
+
+# func_append var value
+# Append VALUE to the end of shell variable VAR.
+func_append ()
+{
+ eval "$[1]+=\$[2]"
+}
+_LT_EOF
+ ;;
+ *)
+ cat << \_LT_EOF >> "$cfgfile"
+
+# func_append var value
+# Append VALUE to the end of shell variable VAR.
+func_append ()
+{
+ eval "$[1]=\$$[1]\$[2]"
+}
+
+_LT_EOF
+ ;;
+ esac
+])
+
+# Helper functions for option handling. -*- Autoconf -*-
+#
+# Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc.
+# Written by Gary V. Vaughan, 2004
+#
+# This file is free software; the Free Software Foundation gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+
+# serial 6 ltoptions.m4
+
+# This is to help aclocal find these macros, as it can't see m4_define.
+AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])])
+
+
+# _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME)
+# ------------------------------------------
+m4_define([_LT_MANGLE_OPTION],
+[[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])])
+
+
+# _LT_SET_OPTION(MACRO-NAME, OPTION-NAME)
+# ---------------------------------------
+# Set option OPTION-NAME for macro MACRO-NAME, and if there is a
+# matching handler defined, dispatch to it. Other OPTION-NAMEs are
+# saved as a flag.
+m4_define([_LT_SET_OPTION],
+[m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl
+m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]),
+ _LT_MANGLE_DEFUN([$1], [$2]),
+ [m4_warning([Unknown $1 option `$2'])])[]dnl
+])
+
+
+# _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET])
+# ------------------------------------------------------------
+# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
+m4_define([_LT_IF_OPTION],
+[m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])])
+
+
+# _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET)
+# -------------------------------------------------------
+# Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME
+# are set.
+m4_define([_LT_UNLESS_OPTIONS],
+[m4_foreach([_LT_Option], m4_split(m4_normalize([$2])),
+ [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option),
+ [m4_define([$0_found])])])[]dnl
+m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3
+])[]dnl
+])
+
+
+# _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST)
+# ----------------------------------------
+# OPTION-LIST is a space-separated list of Libtool options associated
+# with MACRO-NAME. If any OPTION has a matching handler declared with
+# LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about
+# the unknown option and exit.
+m4_defun([_LT_SET_OPTIONS],
+[# Set options
+m4_foreach([_LT_Option], m4_split(m4_normalize([$2])),
+ [_LT_SET_OPTION([$1], _LT_Option)])
+
+m4_if([$1],[LT_INIT],[
+ dnl
+ dnl Simply set some default values (i.e off) if boolean options were not
+ dnl specified:
+ _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no
+ ])
+ _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no
+ ])
+ dnl
+ dnl If no reference was made to various pairs of opposing options, then
+ dnl we run the default mode handler for the pair. For example, if neither
+ dnl `shared' nor `disable-shared' was passed, we enable building of shared
+ dnl archives by default:
+ _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED])
+ _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC])
+ _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC])
+ _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install],
+ [_LT_ENABLE_FAST_INSTALL])
+ ])
+])# _LT_SET_OPTIONS
+
+
+
+# _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME)
+# -----------------------------------------
+m4_define([_LT_MANGLE_DEFUN],
+[[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])])
+
+
+# LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE)
+# -----------------------------------------------
+m4_define([LT_OPTION_DEFINE],
+[m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl
+])# LT_OPTION_DEFINE
+
+
+# dlopen
+# ------
+LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes
+])
+
+AU_DEFUN([AC_LIBTOOL_DLOPEN],
+[_LT_SET_OPTION([LT_INIT], [dlopen])
+AC_DIAGNOSE([obsolete],
+[$0: Remove this warning and the call to _LT_SET_OPTION when you
+put the `dlopen' option into LT_INIT's first parameter.])
+])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], [])
+
+
+# win32-dll
+# ---------
+# Declare package support for building win32 dll's.
+LT_OPTION_DEFINE([LT_INIT], [win32-dll],
+[enable_win32_dll=yes
+
+case $host in
+*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-cegcc*)
+ AC_CHECK_TOOL(AS, as, false)
+ AC_CHECK_TOOL(DLLTOOL, dlltool, false)
+ AC_CHECK_TOOL(OBJDUMP, objdump, false)
+ ;;
+esac
+
+test -z "$AS" && AS=as
+_LT_DECL([], [AS], [0], [Assembler program])dnl
+
+test -z "$DLLTOOL" && DLLTOOL=dlltool
+_LT_DECL([], [DLLTOOL], [0], [DLL creation program])dnl
+
+test -z "$OBJDUMP" && OBJDUMP=objdump
+_LT_DECL([], [OBJDUMP], [0], [Object dumper program])dnl
+])# win32-dll
+
+AU_DEFUN([AC_LIBTOOL_WIN32_DLL],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+_LT_SET_OPTION([LT_INIT], [win32-dll])
+AC_DIAGNOSE([obsolete],
+[$0: Remove this warning and the call to _LT_SET_OPTION when you
+put the `win32-dll' option into LT_INIT's first parameter.])
+])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], [])
+
+
+# _LT_ENABLE_SHARED([DEFAULT])
+# ----------------------------
+# implement the --enable-shared flag, and supports the `shared' and
+# `disable-shared' LT_INIT options.
+# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'.
+m4_define([_LT_ENABLE_SHARED],
+[m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl
+AC_ARG_ENABLE([shared],
+ [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@],
+ [build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])],
+ [p=${PACKAGE-default}
+ case $enableval in
+ yes) enable_shared=yes ;;
+ no) enable_shared=no ;;
+ *)
+ enable_shared=no
+ # Look at the argument we got. We use all the common list separators.
+ lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+ for pkg in $enableval; do
+ IFS="$lt_save_ifs"
+ if test "X$pkg" = "X$p"; then
+ enable_shared=yes
+ fi
+ done
+ IFS="$lt_save_ifs"
+ ;;
+ esac],
+ [enable_shared=]_LT_ENABLE_SHARED_DEFAULT)
+
+ _LT_DECL([build_libtool_libs], [enable_shared], [0],
+ [Whether or not to build shared libraries])
+])# _LT_ENABLE_SHARED
+
+LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])])
+LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])])
+
+# Old names:
+AC_DEFUN([AC_ENABLE_SHARED],
+[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared])
+])
+
+AC_DEFUN([AC_DISABLE_SHARED],
+[_LT_SET_OPTION([LT_INIT], [disable-shared])
+])
+
+AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)])
+AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AM_ENABLE_SHARED], [])
+dnl AC_DEFUN([AM_DISABLE_SHARED], [])
+
+
+
+# _LT_ENABLE_STATIC([DEFAULT])
+# ----------------------------
+# implement the --enable-static flag, and support the `static' and
+# `disable-static' LT_INIT options.
+# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'.
+m4_define([_LT_ENABLE_STATIC],
+[m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl
+AC_ARG_ENABLE([static],
+ [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@],
+ [build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])],
+ [p=${PACKAGE-default}
+ case $enableval in
+ yes) enable_static=yes ;;
+ no) enable_static=no ;;
+ *)
+ enable_static=no
+ # Look at the argument we got. We use all the common list separators.
+ lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+ for pkg in $enableval; do
+ IFS="$lt_save_ifs"
+ if test "X$pkg" = "X$p"; then
+ enable_static=yes
+ fi
+ done
+ IFS="$lt_save_ifs"
+ ;;
+ esac],
+ [enable_static=]_LT_ENABLE_STATIC_DEFAULT)
+
+ _LT_DECL([build_old_libs], [enable_static], [0],
+ [Whether or not to build static libraries])
+])# _LT_ENABLE_STATIC
+
+LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])])
+LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])])
+
+# Old names:
+AC_DEFUN([AC_ENABLE_STATIC],
+[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static])
+])
+
+AC_DEFUN([AC_DISABLE_STATIC],
+[_LT_SET_OPTION([LT_INIT], [disable-static])
+])
+
+AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)])
+AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AM_ENABLE_STATIC], [])
+dnl AC_DEFUN([AM_DISABLE_STATIC], [])
+
+
+
+# _LT_ENABLE_FAST_INSTALL([DEFAULT])
+# ----------------------------------
+# implement the --enable-fast-install flag, and support the `fast-install'
+# and `disable-fast-install' LT_INIT options.
+# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'.
+m4_define([_LT_ENABLE_FAST_INSTALL],
+[m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl
+AC_ARG_ENABLE([fast-install],
+ [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@],
+ [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])],
+ [p=${PACKAGE-default}
+ case $enableval in
+ yes) enable_fast_install=yes ;;
+ no) enable_fast_install=no ;;
+ *)
+ enable_fast_install=no
+ # Look at the argument we got. We use all the common list separators.
+ lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+ for pkg in $enableval; do
+ IFS="$lt_save_ifs"
+ if test "X$pkg" = "X$p"; then
+ enable_fast_install=yes
+ fi
+ done
+ IFS="$lt_save_ifs"
+ ;;
+ esac],
+ [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT)
+
+_LT_DECL([fast_install], [enable_fast_install], [0],
+ [Whether or not to optimize for fast installation])dnl
+])# _LT_ENABLE_FAST_INSTALL
+
+LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])])
+LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])])
+
+# Old names:
+AU_DEFUN([AC_ENABLE_FAST_INSTALL],
+[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install])
+AC_DIAGNOSE([obsolete],
+[$0: Remove this warning and the call to _LT_SET_OPTION when you put
+the `fast-install' option into LT_INIT's first parameter.])
+])
+
+AU_DEFUN([AC_DISABLE_FAST_INSTALL],
+[_LT_SET_OPTION([LT_INIT], [disable-fast-install])
+AC_DIAGNOSE([obsolete],
+[$0: Remove this warning and the call to _LT_SET_OPTION when you put
+the `disable-fast-install' option into LT_INIT's first parameter.])
+])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], [])
+dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], [])
+
+
+# _LT_WITH_PIC([MODE])
+# --------------------
+# implement the --with-pic flag, and support the `pic-only' and `no-pic'
+# LT_INIT options.
+# MODE is either `yes' or `no'. If omitted, it defaults to `both'.
+m4_define([_LT_WITH_PIC],
+[AC_ARG_WITH([pic],
+ [AS_HELP_STRING([--with-pic],
+ [try to use only PIC/non-PIC objects @<:@default=use both@:>@])],
+ [pic_mode="$withval"],
+ [pic_mode=default])
+
+test -z "$pic_mode" && pic_mode=m4_default([$1], [default])
+
+_LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl
+])# _LT_WITH_PIC
+
+LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])])
+LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])])
+
+# Old name:
+AU_DEFUN([AC_LIBTOOL_PICMODE],
+[_LT_SET_OPTION([LT_INIT], [pic-only])
+AC_DIAGNOSE([obsolete],
+[$0: Remove this warning and the call to _LT_SET_OPTION when you
+put the `pic-only' option into LT_INIT's first parameter.])
+])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_PICMODE], [])
+
+
+m4_define([_LTDL_MODE], [])
+LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive],
+ [m4_define([_LTDL_MODE], [nonrecursive])])
+LT_OPTION_DEFINE([LTDL_INIT], [recursive],
+ [m4_define([_LTDL_MODE], [recursive])])
+LT_OPTION_DEFINE([LTDL_INIT], [subproject],
+ [m4_define([_LTDL_MODE], [subproject])])
+
+m4_define([_LTDL_TYPE], [])
+LT_OPTION_DEFINE([LTDL_INIT], [installable],
+ [m4_define([_LTDL_TYPE], [installable])])
+LT_OPTION_DEFINE([LTDL_INIT], [convenience],
+ [m4_define([_LTDL_TYPE], [convenience])])
+
+# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*-
+#
+# Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc.
+# Written by Gary V. Vaughan, 2004
+#
+# This file is free software; the Free Software Foundation gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+
+# serial 6 ltsugar.m4
+
+# This is to help aclocal find these macros, as it can't see m4_define.
+AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])])
+
+
+# lt_join(SEP, ARG1, [ARG2...])
+# -----------------------------
+# Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their
+# associated separator.
+# Needed until we can rely on m4_join from Autoconf 2.62, since all earlier
+# versions in m4sugar had bugs.
+m4_define([lt_join],
+[m4_if([$#], [1], [],
+ [$#], [2], [[$2]],
+ [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])])
+m4_define([_lt_join],
+[m4_if([$#$2], [2], [],
+ [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])])
+
+
+# lt_car(LIST)
+# lt_cdr(LIST)
+# ------------
+# Manipulate m4 lists.
+# These macros are necessary as long as will still need to support
+# Autoconf-2.59 which quotes differently.
+m4_define([lt_car], [[$1]])
+m4_define([lt_cdr],
+[m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])],
+ [$#], 1, [],
+ [m4_dquote(m4_shift($@))])])
+m4_define([lt_unquote], $1)
+
+
+# lt_append(MACRO-NAME, STRING, [SEPARATOR])
+# ------------------------------------------
+# Redefine MACRO-NAME to hold its former content plus `SEPARATOR'`STRING'.
+# Note that neither SEPARATOR nor STRING are expanded; they are appended
+# to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked).
+# No SEPARATOR is output if MACRO-NAME was previously undefined (different
+# than defined and empty).
+#
+# This macro is needed until we can rely on Autoconf 2.62, since earlier
+# versions of m4sugar mistakenly expanded SEPARATOR but not STRING.
+m4_define([lt_append],
+[m4_define([$1],
+ m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])])
+
+
+
+# lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...])
+# ----------------------------------------------------------
+# Produce a SEP delimited list of all paired combinations of elements of
+# PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list
+# has the form PREFIXmINFIXSUFFIXn.
+# Needed until we can rely on m4_combine added in Autoconf 2.62.
+m4_define([lt_combine],
+[m4_if(m4_eval([$# > 3]), [1],
+ [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl
+[[m4_foreach([_Lt_prefix], [$2],
+ [m4_foreach([_Lt_suffix],
+ ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[,
+ [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])])
+
+
+# lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ])
+# -----------------------------------------------------------------------
+# Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited
+# by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ.
+m4_define([lt_if_append_uniq],
+[m4_ifdef([$1],
+ [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1],
+ [lt_append([$1], [$2], [$3])$4],
+ [$5])],
+ [lt_append([$1], [$2], [$3])$4])])
+
+
+# lt_dict_add(DICT, KEY, VALUE)
+# -----------------------------
+m4_define([lt_dict_add],
+[m4_define([$1($2)], [$3])])
+
+
+# lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE)
+# --------------------------------------------
+m4_define([lt_dict_add_subkey],
+[m4_define([$1($2:$3)], [$4])])
+
+
+# lt_dict_fetch(DICT, KEY, [SUBKEY])
+# ----------------------------------
+m4_define([lt_dict_fetch],
+[m4_ifval([$3],
+ m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]),
+ m4_ifdef([$1($2)], [m4_defn([$1($2)])]))])
+
+
+# lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE])
+# -----------------------------------------------------------------
+m4_define([lt_if_dict_fetch],
+[m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4],
+ [$5],
+ [$6])])
+
+
+# lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...])
+# --------------------------------------------------------------
+m4_define([lt_dict_filter],
+[m4_if([$5], [], [],
+ [lt_join(m4_quote(m4_default([$4], [[, ]])),
+ lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]),
+ [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl
+])
+
+# ltversion.m4 -- version numbers -*- Autoconf -*-
+#
+# Copyright (C) 2004 Free Software Foundation, Inc.
+# Written by Scott James Remnant, 2004
+#
+# This file is free software; the Free Software Foundation gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+
+# Generated from ltversion.in.
+
+# serial 3012 ltversion.m4
+# This file is part of GNU Libtool
+
+m4_define([LT_PACKAGE_VERSION], [2.2.6])
+m4_define([LT_PACKAGE_REVISION], [1.3012])
+
+AC_DEFUN([LTVERSION_VERSION],
+[macro_version='2.2.6'
+macro_revision='1.3012'
+_LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?])
+_LT_DECL(, macro_revision, 0)
+])
+
+# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*-
+#
+# Copyright (C) 2004, 2005, 2007 Free Software Foundation, Inc.
+# Written by Scott James Remnant, 2004.
+#
+# This file is free software; the Free Software Foundation gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+
+# serial 4 lt~obsolete.m4
+
+# These exist entirely to fool aclocal when bootstrapping libtool.
+#
+# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN)
+# which have later been changed to m4_define as they aren't part of the
+# exported API, or moved to Autoconf or Automake where they belong.
+#
+# The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN
+# in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us
+# using a macro with the same name in our local m4/libtool.m4 it'll
+# pull the old libtool.m4 in (it doesn't see our shiny new m4_define
+# and doesn't know about Autoconf macros at all.)
+#
+# So we provide this file, which has a silly filename so it's always
+# included after everything else. This provides aclocal with the
+# AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything
+# because those macros already exist, or will be overwritten later.
+# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6.
+#
+# Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here.
+# Yes, that means every name once taken will need to remain here until
+# we give up compatibility with versions before 1.7, at which point
+# we need to keep only those names which we still refer to.
+
+# This is to help aclocal find these macros, as it can't see m4_define.
+AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])])
+
+m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])])
+m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])])
+m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])])
+m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])])
+m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])])
+m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])])
+m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])])
+m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])])
+m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])])
+m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])])
+m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])])
+m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])])
+m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])])
+m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])])
+m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])])
+m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])])
+m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])])
+m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])])
+m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])])
+m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])])
+m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])])
+m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])])
+m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])])
+m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])])
+m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])])
+m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])])
+m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])])
+m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])])
+m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])])
+m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])])
+m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])])
+m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])])
+m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])])
+m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])])
+m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])])
+m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])])
+m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])])
+m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])])
+m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])])
+m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])])
+m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])])
+m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])])
+m4_ifndef([AC_LIBTOOL_RC], [AC_DEFUN([AC_LIBTOOL_RC])])
+m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])])
+m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])])
+m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])])
+m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])])
+m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])])
+m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])])
+m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])])
+m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])])
+m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])])
+m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])])
+m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])])
+m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])])
+
+# Copyright (C) 2002, 2003, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_AUTOMAKE_VERSION(VERSION)
+# ----------------------------
+# Automake X.Y traces this macro to ensure aclocal.m4 has been
+# generated from the m4 files accompanying Automake X.Y.
+# (This private macro should not be called outside this file.)
+AC_DEFUN([AM_AUTOMAKE_VERSION],
+[am__api_version='1.11'
+dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
+dnl require some minimum version. Point them to the right macro.
+m4_if([$1], [1.11], [],
+ [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
+])
+
+# _AM_AUTOCONF_VERSION(VERSION)
+# -----------------------------
+# aclocal traces this macro to find the Autoconf version.
+# This is a private macro too. Using m4_define simplifies
+# the logic in aclocal, which can simply ignore this definition.
+m4_define([_AM_AUTOCONF_VERSION], [])
+
+# AM_SET_CURRENT_AUTOMAKE_VERSION
+# -------------------------------
+# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
+# This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
+AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
+[AM_AUTOMAKE_VERSION([1.11])dnl
+m4_ifndef([AC_AUTOCONF_VERSION],
+ [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
+_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
+
+# AM_AUX_DIR_EXPAND -*- Autoconf -*-
+
+# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets
+# $ac_aux_dir to `$srcdir/foo'. In other projects, it is set to
+# `$srcdir', `$srcdir/..', or `$srcdir/../..'.
+#
+# Of course, Automake must honor this variable whenever it calls a
+# tool from the auxiliary directory. The problem is that $srcdir (and
+# therefore $ac_aux_dir as well) can be either absolute or relative,
+# depending on how configure is run. This is pretty annoying, since
+# it makes $ac_aux_dir quite unusable in subdirectories: in the top
+# source directory, any form will work fine, but in subdirectories a
+# relative path needs to be adjusted first.
+#
+# $ac_aux_dir/missing
+# fails when called from a subdirectory if $ac_aux_dir is relative
+# $top_srcdir/$ac_aux_dir/missing
+# fails if $ac_aux_dir is absolute,
+# fails when called from a subdirectory in a VPATH build with
+# a relative $ac_aux_dir
+#
+# The reason of the latter failure is that $top_srcdir and $ac_aux_dir
+# are both prefixed by $srcdir. In an in-source build this is usually
+# harmless because $srcdir is `.', but things will broke when you
+# start a VPATH build or use an absolute $srcdir.
+#
+# So we could use something similar to $top_srcdir/$ac_aux_dir/missing,
+# iff we strip the leading $srcdir from $ac_aux_dir. That would be:
+# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"`
+# and then we would define $MISSING as
+# MISSING="\${SHELL} $am_aux_dir/missing"
+# This will work as long as MISSING is not called from configure, because
+# unfortunately $(top_srcdir) has no meaning in configure.
+# However there are other variables, like CC, which are often used in
+# configure, and could therefore not use this "fixed" $ac_aux_dir.
+#
+# Another solution, used here, is to always expand $ac_aux_dir to an
+# absolute PATH. The drawback is that using absolute paths prevent a
+# configured tree to be moved without reconfiguration.
+
+AC_DEFUN([AM_AUX_DIR_EXPAND],
+[dnl Rely on autoconf to set up CDPATH properly.
+AC_PREREQ([2.50])dnl
+# expand $ac_aux_dir to an absolute path
+am_aux_dir=`cd $ac_aux_dir && pwd`
+])
+
+# AM_CONDITIONAL -*- Autoconf -*-
+
+# Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005, 2006, 2008
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 9
+
+# AM_CONDITIONAL(NAME, SHELL-CONDITION)
+# -------------------------------------
+# Define a conditional.
+AC_DEFUN([AM_CONDITIONAL],
+[AC_PREREQ(2.52)dnl
+ ifelse([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])],
+ [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl
+AC_SUBST([$1_TRUE])dnl
+AC_SUBST([$1_FALSE])dnl
+_AM_SUBST_NOTMAKE([$1_TRUE])dnl
+_AM_SUBST_NOTMAKE([$1_FALSE])dnl
+m4_define([_AM_COND_VALUE_$1], [$2])dnl
+if $2; then
+ $1_TRUE=
+ $1_FALSE='#'
+else
+ $1_TRUE='#'
+ $1_FALSE=
+fi
+AC_CONFIG_COMMANDS_PRE(
+[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then
+ AC_MSG_ERROR([[conditional "$1" was never defined.
+Usually this means the macro was only invoked conditionally.]])
+fi])])
+
+# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2009
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 10
+
+# There are a few dirty hacks below to avoid letting `AC_PROG_CC' be
+# written in clear, in which case automake, when reading aclocal.m4,
+# will think it sees a *use*, and therefore will trigger all it's
+# C support machinery. Also note that it means that autoscan, seeing
+# CC etc. in the Makefile, will ask for an AC_PROG_CC use...
+
+
+# _AM_DEPENDENCIES(NAME)
+# ----------------------
+# See how the compiler implements dependency checking.
+# NAME is "CC", "CXX", "GCJ", or "OBJC".
+# We try a few techniques and use that to set a single cache variable.
+#
+# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was
+# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular
+# dependency, and given that the user is not expected to run this macro,
+# just rely on AC_PROG_CC.
+AC_DEFUN([_AM_DEPENDENCIES],
+[AC_REQUIRE([AM_SET_DEPDIR])dnl
+AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl
+AC_REQUIRE([AM_MAKE_INCLUDE])dnl
+AC_REQUIRE([AM_DEP_TRACK])dnl
+
+ifelse([$1], CC, [depcc="$CC" am_compiler_list=],
+ [$1], CXX, [depcc="$CXX" am_compiler_list=],
+ [$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'],
+ [$1], UPC, [depcc="$UPC" am_compiler_list=],
+ [$1], GCJ, [depcc="$GCJ" am_compiler_list='gcc3 gcc'],
+ [depcc="$$1" am_compiler_list=])
+
+AC_CACHE_CHECK([dependency style of $depcc],
+ [am_cv_$1_dependencies_compiler_type],
+[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+ # We make a subdir and do the tests there. Otherwise we can end up
+ # making bogus files that we don't know about and never remove. For
+ # instance it was reported that on HP-UX the gcc test will end up
+ # making a dummy file named `D' -- because `-MD' means `put the output
+ # in D'.
+ mkdir conftest.dir
+ # Copy depcomp to subdir because otherwise we won't find it if we're
+ # using a relative directory.
+ cp "$am_depcomp" conftest.dir
+ cd conftest.dir
+ # We will build objects and dependencies in a subdirectory because
+ # it helps to detect inapplicable dependency modes. For instance
+ # both Tru64's cc and ICC support -MD to output dependencies as a
+ # side effect of compilation, but ICC will put the dependencies in
+ # the current directory while Tru64 will put them in the object
+ # directory.
+ mkdir sub
+
+ am_cv_$1_dependencies_compiler_type=none
+ if test "$am_compiler_list" = ""; then
+ am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp`
+ fi
+ am__universal=false
+ m4_case([$1], [CC],
+ [case " $depcc " in #(
+ *\ -arch\ *\ -arch\ *) am__universal=true ;;
+ esac],
+ [CXX],
+ [case " $depcc " in #(
+ *\ -arch\ *\ -arch\ *) am__universal=true ;;
+ esac])
+
+ for depmode in $am_compiler_list; do
+ # Setup a source with many dependencies, because some compilers
+ # like to wrap large dependency lists on column 80 (with \), and
+ # we should not choose a depcomp mode which is confused by this.
+ #
+ # We need to recreate these files for each test, as the compiler may
+ # overwrite some of them when testing with obscure command lines.
+ # This happens at least with the AIX C compiler.
+ : > sub/conftest.c
+ for i in 1 2 3 4 5 6; do
+ echo '#include "conftst'$i'.h"' >> sub/conftest.c
+ # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with
+ # Solaris 8's {/usr,}/bin/sh.
+ touch sub/conftst$i.h
+ done
+ echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+ # We check with `-c' and `-o' for the sake of the "dashmstdout"
+ # mode. It turns out that the SunPro C++ compiler does not properly
+ # handle `-M -o', and we need to detect this. Also, some Intel
+ # versions had trouble with output in subdirs
+ am__obj=sub/conftest.${OBJEXT-o}
+ am__minus_obj="-o $am__obj"
+ case $depmode in
+ gcc)
+ # This depmode causes a compiler race in universal mode.
+ test "$am__universal" = false || continue
+ ;;
+ nosideeffect)
+ # after this tag, mechanisms are not by side-effect, so they'll
+ # only be used when explicitly requested
+ if test "x$enable_dependency_tracking" = xyes; then
+ continue
+ else
+ break
+ fi
+ ;;
+ msvisualcpp | msvcmsys)
+ # This compiler won't grok `-c -o', but also, the minuso test has
+ # not run yet. These depmodes are late enough in the game, and
+ # so weak that their functioning should not be impacted.
+ am__obj=conftest.${OBJEXT-o}
+ am__minus_obj=
+ ;;
+ none) break ;;
+ esac
+ if depmode=$depmode \
+ source=sub/conftest.c object=$am__obj \
+ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
+ >/dev/null 2>conftest.err &&
+ grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
+ ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+ # icc doesn't choke on unknown options, it will just issue warnings
+ # or remarks (even with -Werror). So we grep stderr for any message
+ # that says an option was ignored or not supported.
+ # When given -MP, icc 7.0 and 7.1 complain thusly:
+ # icc: Command line warning: ignoring option '-M'; no argument required
+ # The diagnosis changed in icc 8.0:
+ # icc: Command line remark: option '-MP' not supported
+ if (grep 'ignoring option' conftest.err ||
+ grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+ am_cv_$1_dependencies_compiler_type=$depmode
+ break
+ fi
+ fi
+ done
+
+ cd ..
+ rm -rf conftest.dir
+else
+ am_cv_$1_dependencies_compiler_type=none
+fi
+])
+AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type])
+AM_CONDITIONAL([am__fastdep$1], [
+ test "x$enable_dependency_tracking" != xno \
+ && test "$am_cv_$1_dependencies_compiler_type" = gcc3])
+])
+
+
+# AM_SET_DEPDIR
+# -------------
+# Choose a directory name for dependency files.
+# This macro is AC_REQUIREd in _AM_DEPENDENCIES
+AC_DEFUN([AM_SET_DEPDIR],
+[AC_REQUIRE([AM_SET_LEADING_DOT])dnl
+AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl
+])
+
+
+# AM_DEP_TRACK
+# ------------
+AC_DEFUN([AM_DEP_TRACK],
+[AC_ARG_ENABLE(dependency-tracking,
+[ --disable-dependency-tracking speeds up one-time build
+ --enable-dependency-tracking do not reject slow dependency extractors])
+if test "x$enable_dependency_tracking" != xno; then
+ am_depcomp="$ac_aux_dir/depcomp"
+ AMDEPBACKSLASH='\'
+fi
+AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno])
+AC_SUBST([AMDEPBACKSLASH])dnl
+_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl
+])
+
+# Generate code to set up dependency tracking. -*- Autoconf -*-
+
+# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2008
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+#serial 5
+
+# _AM_OUTPUT_DEPENDENCY_COMMANDS
+# ------------------------------
+AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
+[{
+ # Autoconf 2.62 quotes --file arguments for eval, but not when files
+ # are listed without --file. Let's play safe and only enable the eval
+ # if we detect the quoting.
+ case $CONFIG_FILES in
+ *\'*) eval set x "$CONFIG_FILES" ;;
+ *) set x $CONFIG_FILES ;;
+ esac
+ shift
+ for mf
+ do
+ # Strip MF so we end up with the name of the file.
+ mf=`echo "$mf" | sed -e 's/:.*$//'`
+ # Check whether this is an Automake generated Makefile or not.
+ # We used to match only the files named `Makefile.in', but
+ # some people rename them; so instead we look at the file content.
+ # Grep'ing the first line is not enough: some people post-process
+ # each Makefile.in and add a new line on top of each file to say so.
+ # Grep'ing the whole file is not good either: AIX grep has a line
+ # limit of 2048, but all sed's we know have understand at least 4000.
+ if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then
+ dirpart=`AS_DIRNAME("$mf")`
+ else
+ continue
+ fi
+ # Extract the definition of DEPDIR, am__include, and am__quote
+ # from the Makefile without running `make'.
+ DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
+ test -z "$DEPDIR" && continue
+ am__include=`sed -n 's/^am__include = //p' < "$mf"`
+ test -z "am__include" && continue
+ am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
+ # When using ansi2knr, U may be empty or an underscore; expand it
+ U=`sed -n 's/^U = //p' < "$mf"`
+ # Find all dependency output files, they are included files with
+ # $(DEPDIR) in their names. We invoke sed twice because it is the
+ # simplest approach to changing $(DEPDIR) to its actual value in the
+ # expansion.
+ for file in `sed -n "
+ s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
+ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do
+ # Make sure the directory exists.
+ test -f "$dirpart/$file" && continue
+ fdir=`AS_DIRNAME(["$file"])`
+ AS_MKDIR_P([$dirpart/$fdir])
+ # echo "creating $dirpart/$file"
+ echo '# dummy' > "$dirpart/$file"
+ done
+ done
+}
+])# _AM_OUTPUT_DEPENDENCY_COMMANDS
+
+
+# AM_OUTPUT_DEPENDENCY_COMMANDS
+# -----------------------------
+# This macro should only be invoked once -- use via AC_REQUIRE.
+#
+# This code is only required when automatic dependency tracking
+# is enabled. FIXME. This creates each `.P' file that we will
+# need in order to bootstrap the dependency handling code.
+AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],
+[AC_CONFIG_COMMANDS([depfiles],
+ [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS],
+ [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"])
+])
+
+# Do all the work for Automake. -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+# 2005, 2006, 2008, 2009 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 16
+
+# This macro actually does too much. Some checks are only needed if
+# your package does certain things. But this isn't really a big deal.
+
+# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE])
+# AM_INIT_AUTOMAKE([OPTIONS])
+# -----------------------------------------------
+# The call with PACKAGE and VERSION arguments is the old style
+# call (pre autoconf-2.50), which is being phased out. PACKAGE
+# and VERSION should now be passed to AC_INIT and removed from
+# the call to AM_INIT_AUTOMAKE.
+# We support both call styles for the transition. After
+# the next Automake release, Autoconf can make the AC_INIT
+# arguments mandatory, and then we can depend on a new Autoconf
+# release and drop the old call support.
+AC_DEFUN([AM_INIT_AUTOMAKE],
+[AC_PREREQ([2.62])dnl
+dnl Autoconf wants to disallow AM_ names. We explicitly allow
+dnl the ones we care about.
+m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl
+AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl
+AC_REQUIRE([AC_PROG_INSTALL])dnl
+if test "`cd $srcdir && pwd`" != "`pwd`"; then
+ # Use -I$(srcdir) only when $(srcdir) != ., so that make's output
+ # is not polluted with repeated "-I."
+ AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl
+ # test to see if srcdir already configured
+ if test -f $srcdir/config.status; then
+ AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
+ fi
+fi
+
+# test whether we have cygpath
+if test -z "$CYGPATH_W"; then
+ if (cygpath --version) >/dev/null 2>/dev/null; then
+ CYGPATH_W='cygpath -w'
+ else
+ CYGPATH_W=echo
+ fi
+fi
+AC_SUBST([CYGPATH_W])
+
+# Define the identity of the package.
+dnl Distinguish between old-style and new-style calls.
+m4_ifval([$2],
+[m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl
+ AC_SUBST([PACKAGE], [$1])dnl
+ AC_SUBST([VERSION], [$2])],
+[_AM_SET_OPTIONS([$1])dnl
+dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT.
+m4_if(m4_ifdef([AC_PACKAGE_NAME], 1)m4_ifdef([AC_PACKAGE_VERSION], 1), 11,,
+ [m4_fatal([AC_INIT should be called with package and version arguments])])dnl
+ AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl
+ AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl
+
+_AM_IF_OPTION([no-define],,
+[AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package])
+ AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl
+
+# Some tools Automake needs.
+AC_REQUIRE([AM_SANITY_CHECK])dnl
+AC_REQUIRE([AC_ARG_PROGRAM])dnl
+AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version})
+AM_MISSING_PROG(AUTOCONF, autoconf)
+AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version})
+AM_MISSING_PROG(AUTOHEADER, autoheader)
+AM_MISSING_PROG(MAKEINFO, makeinfo)
+AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
+AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl
+AC_REQUIRE([AM_PROG_MKDIR_P])dnl
+# We need awk for the "check" target. The system "awk" is bad on
+# some platforms.
+AC_REQUIRE([AC_PROG_AWK])dnl
+AC_REQUIRE([AC_PROG_MAKE_SET])dnl
+AC_REQUIRE([AM_SET_LEADING_DOT])dnl
+_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])],
+ [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])],
+ [_AM_PROG_TAR([v7])])])
+_AM_IF_OPTION([no-dependencies],,
+[AC_PROVIDE_IFELSE([AC_PROG_CC],
+ [_AM_DEPENDENCIES(CC)],
+ [define([AC_PROG_CC],
+ defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_CXX],
+ [_AM_DEPENDENCIES(CXX)],
+ [define([AC_PROG_CXX],
+ defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_OBJC],
+ [_AM_DEPENDENCIES(OBJC)],
+ [define([AC_PROG_OBJC],
+ defn([AC_PROG_OBJC])[_AM_DEPENDENCIES(OBJC)])])dnl
+])
+_AM_IF_OPTION([silent-rules], [AC_REQUIRE([AM_SILENT_RULES])])dnl
+dnl The `parallel-tests' driver may need to know about EXEEXT, so add the
+dnl `am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This macro
+dnl is hooked onto _AC_COMPILER_EXEEXT early, see below.
+AC_CONFIG_COMMANDS_PRE(dnl
+[m4_provide_if([_AM_COMPILER_EXEEXT],
+ [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl
+])
+
+dnl Hook into `_AC_COMPILER_EXEEXT' early to learn its expansion. Do not
+dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further
+dnl mangled by Autoconf and run in a shell conditional statement.
+m4_define([_AC_COMPILER_EXEEXT],
+m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])])
+
+
+# When config.status generates a header, we must update the stamp-h file.
+# This file resides in the same directory as the config header
+# that is generated. The stamp files are numbered to have different names.
+
+# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the
+# loop where config.status creates the headers, so we can generate
+# our stamp files there.
+AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK],
+[# Compute $1's index in $config_headers.
+_am_arg=$1
+_am_stamp_count=1
+for _am_header in $config_headers :; do
+ case $_am_header in
+ $_am_arg | $_am_arg:* )
+ break ;;
+ * )
+ _am_stamp_count=`expr $_am_stamp_count + 1` ;;
+ esac
+done
+echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count])
+
+# Copyright (C) 2001, 2003, 2005, 2008 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_INSTALL_SH
+# ------------------
+# Define $install_sh.
+AC_DEFUN([AM_PROG_INSTALL_SH],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+if test x"${install_sh}" != xset; then
+ case $am_aux_dir in
+ *\ * | *\ *)
+ install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;;
+ *)
+ install_sh="\${SHELL} $am_aux_dir/install-sh"
+ esac
+fi
+AC_SUBST(install_sh)])
+
+# Copyright (C) 2003, 2005 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 2
+
+# Check whether the underlying file-system supports filenames
+# with a leading dot. For instance MS-DOS doesn't.
+AC_DEFUN([AM_SET_LEADING_DOT],
+[rm -rf .tst 2>/dev/null
+mkdir .tst 2>/dev/null
+if test -d .tst; then
+ am__leading_dot=.
+else
+ am__leading_dot=_
+fi
+rmdir .tst 2>/dev/null
+AC_SUBST([am__leading_dot])])
+
+# Check to see how 'make' treats includes. -*- Autoconf -*-
+
+# Copyright (C) 2001, 2002, 2003, 2005, 2009 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 4
+
+# AM_MAKE_INCLUDE()
+# -----------------
+# Check to see how make treats includes.
+AC_DEFUN([AM_MAKE_INCLUDE],
+[am_make=${MAKE-make}
+cat > confinc << 'END'
+am__doit:
+ @echo this is the am__doit target
+.PHONY: am__doit
+END
+# If we don't find an include directive, just comment out the code.
+AC_MSG_CHECKING([for style of include used by $am_make])
+am__include="#"
+am__quote=
+_am_result=none
+# First try GNU make style include.
+echo "include confinc" > confmf
+# Ignore all kinds of additional output from `make'.
+case `$am_make -s -f confmf 2> /dev/null` in #(
+*the\ am__doit\ target*)
+ am__include=include
+ am__quote=
+ _am_result=GNU
+ ;;
+esac
+# Now try BSD make style include.
+if test "$am__include" = "#"; then
+ echo '.include "confinc"' > confmf
+ case `$am_make -s -f confmf 2> /dev/null` in #(
+ *the\ am__doit\ target*)
+ am__include=.include
+ am__quote="\""
+ _am_result=BSD
+ ;;
+ esac
+fi
+AC_SUBST([am__include])
+AC_SUBST([am__quote])
+AC_MSG_RESULT([$_am_result])
+rm -f confinc confmf
+])
+
+# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*-
+
+# Copyright (C) 1997, 1999, 2000, 2001, 2003, 2004, 2005, 2008
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 6
+
+# AM_MISSING_PROG(NAME, PROGRAM)
+# ------------------------------
+AC_DEFUN([AM_MISSING_PROG],
+[AC_REQUIRE([AM_MISSING_HAS_RUN])
+$1=${$1-"${am_missing_run}$2"}
+AC_SUBST($1)])
+
+
+# AM_MISSING_HAS_RUN
+# ------------------
+# Define MISSING if not defined so far and test if it supports --run.
+# If it does, set am_missing_run to use it, otherwise, to nothing.
+AC_DEFUN([AM_MISSING_HAS_RUN],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+AC_REQUIRE_AUX_FILE([missing])dnl
+if test x"${MISSING+set}" != xset; then
+ case $am_aux_dir in
+ *\ * | *\ *)
+ MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;;
+ *)
+ MISSING="\${SHELL} $am_aux_dir/missing" ;;
+ esac
+fi
+# Use eval to expand $SHELL
+if eval "$MISSING --run true"; then
+ am_missing_run="$MISSING --run "
+else
+ am_missing_run=
+ AC_MSG_WARN([`missing' script is too old or missing])
+fi
+])
+
+# Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_MKDIR_P
+# ---------------
+# Check for `mkdir -p'.
+AC_DEFUN([AM_PROG_MKDIR_P],
+[AC_PREREQ([2.60])dnl
+AC_REQUIRE([AC_PROG_MKDIR_P])dnl
+dnl Automake 1.8 to 1.9.6 used to define mkdir_p. We now use MKDIR_P,
+dnl while keeping a definition of mkdir_p for backward compatibility.
+dnl @MKDIR_P@ is magic: AC_OUTPUT adjusts its value for each Makefile.
+dnl However we cannot define mkdir_p as $(MKDIR_P) for the sake of
+dnl Makefile.ins that do not define MKDIR_P, so we do our own
+dnl adjustment using top_builddir (which is defined more often than
+dnl MKDIR_P).
+AC_SUBST([mkdir_p], ["$MKDIR_P"])dnl
+case $mkdir_p in
+ [[\\/$]]* | ?:[[\\/]]*) ;;
+ */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;;
+esac
+])
+
+# Helper functions for option handling. -*- Autoconf -*-
+
+# Copyright (C) 2001, 2002, 2003, 2005, 2008 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 4
+
+# _AM_MANGLE_OPTION(NAME)
+# -----------------------
+AC_DEFUN([_AM_MANGLE_OPTION],
+[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])])
+
+# _AM_SET_OPTION(NAME)
+# ------------------------------
+# Set option NAME. Presently that only means defining a flag for this option.
+AC_DEFUN([_AM_SET_OPTION],
+[m4_define(_AM_MANGLE_OPTION([$1]), 1)])
+
+# _AM_SET_OPTIONS(OPTIONS)
+# ----------------------------------
+# OPTIONS is a space-separated list of Automake options.
+AC_DEFUN([_AM_SET_OPTIONS],
+[m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])])
+
+# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET])
+# -------------------------------------------
+# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
+AC_DEFUN([_AM_IF_OPTION],
+[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])
+
+# Check to make sure that the build environment is sane. -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005, 2008
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 5
+
+# AM_SANITY_CHECK
+# ---------------
+AC_DEFUN([AM_SANITY_CHECK],
+[AC_MSG_CHECKING([whether build environment is sane])
+# Just in case
+sleep 1
+echo timestamp > conftest.file
+# Reject unsafe characters in $srcdir or the absolute working directory
+# name. Accept space and tab only in the latter.
+am_lf='
+'
+case `pwd` in
+ *[[\\\"\#\$\&\'\`$am_lf]]*)
+ AC_MSG_ERROR([unsafe absolute working directory name]);;
+esac
+case $srcdir in
+ *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*)
+ AC_MSG_ERROR([unsafe srcdir value: `$srcdir']);;
+esac
+
+# Do `set' in a subshell so we don't clobber the current shell's
+# arguments. Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+ set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null`
+ if test "$[*]" = "X"; then
+ # -L didn't work.
+ set X `ls -t "$srcdir/configure" conftest.file`
+ fi
+ rm -f conftest.file
+ if test "$[*]" != "X $srcdir/configure conftest.file" \
+ && test "$[*]" != "X conftest.file $srcdir/configure"; then
+
+ # If neither matched, then we have a broken ls. This can happen
+ # if, for instance, CONFIG_SHELL is bash and it inherits a
+ # broken ls alias from the environment. This has actually
+ # happened. Such a system could not be considered "sane".
+ AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken
+alias in your environment])
+ fi
+
+ test "$[2]" = conftest.file
+ )
+then
+ # Ok.
+ :
+else
+ AC_MSG_ERROR([newly created file is older than distributed files!
+Check your system clock])
+fi
+AC_MSG_RESULT(yes)])
+
+# Copyright (C) 2009 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 1
+
+# AM_SILENT_RULES([DEFAULT])
+# --------------------------
+# Enable less verbose build rules; with the default set to DEFAULT
+# (`yes' being less verbose, `no' or empty being verbose).
+AC_DEFUN([AM_SILENT_RULES],
+[AC_ARG_ENABLE([silent-rules],
+[ --enable-silent-rules less verbose build output (undo: `make V=1')
+ --disable-silent-rules verbose build output (undo: `make V=0')])
+case $enable_silent_rules in
+yes) AM_DEFAULT_VERBOSITY=0;;
+no) AM_DEFAULT_VERBOSITY=1;;
+*) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);;
+esac
+AC_SUBST([AM_DEFAULT_VERBOSITY])dnl
+AM_BACKSLASH='\'
+AC_SUBST([AM_BACKSLASH])dnl
+_AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl
+])
+
+# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_INSTALL_STRIP
+# ---------------------
+# One issue with vendor `install' (even GNU) is that you can't
+# specify the program used to strip binaries. This is especially
+# annoying in cross-compiling environments, where the build's strip
+# is unlikely to handle the host's binaries.
+# Fortunately install-sh will honor a STRIPPROG variable, so we
+# always use install-sh in `make install-strip', and initialize
+# STRIPPROG with the value of the STRIP variable (set by the user).
+AC_DEFUN([AM_PROG_INSTALL_STRIP],
+[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
+# Installed binaries are usually stripped using `strip' when the user
+# run `make install-strip'. However `strip' might not be the right
+# tool to use in cross-compilation environments, therefore Automake
+# will honor the `STRIP' environment variable to overrule this program.
+dnl Don't test for $cross_compiling = yes, because it might be `maybe'.
+if test "$cross_compiling" != no; then
+ AC_CHECK_TOOL([STRIP], [strip], :)
+fi
+INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
+AC_SUBST([INSTALL_STRIP_PROGRAM])])
+
+# Copyright (C) 2006, 2008 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 2
+
+# _AM_SUBST_NOTMAKE(VARIABLE)
+# ---------------------------
+# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in.
+# This macro is traced by Automake.
+AC_DEFUN([_AM_SUBST_NOTMAKE])
+
+# AM_SUBST_NOTMAKE(VARIABLE)
+# ---------------------------
+# Public sister of _AM_SUBST_NOTMAKE.
+AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)])
+
+# Check how to create a tarball. -*- Autoconf -*-
+
+# Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 2
+
+# _AM_PROG_TAR(FORMAT)
+# --------------------
+# Check how to create a tarball in format FORMAT.
+# FORMAT should be one of `v7', `ustar', or `pax'.
+#
+# Substitute a variable $(am__tar) that is a command
+# writing to stdout a FORMAT-tarball containing the directory
+# $tardir.
+# tardir=directory && $(am__tar) > result.tar
+#
+# Substitute a variable $(am__untar) that extract such
+# a tarball read from stdin.
+# $(am__untar) < result.tar
+AC_DEFUN([_AM_PROG_TAR],
+[# Always define AMTAR for backward compatibility.
+AM_MISSING_PROG([AMTAR], [tar])
+m4_if([$1], [v7],
+ [am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'],
+ [m4_case([$1], [ustar],, [pax],,
+ [m4_fatal([Unknown tar format])])
+AC_MSG_CHECKING([how to create a $1 tar archive])
+# Loop over all known methods to create a tar archive until one works.
+_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none'
+_am_tools=${am_cv_prog_tar_$1-$_am_tools}
+# Do not fold the above two line into one, because Tru64 sh and
+# Solaris sh will not grok spaces in the rhs of `-'.
+for _am_tool in $_am_tools
+do
+ case $_am_tool in
+ gnutar)
+ for _am_tar in tar gnutar gtar;
+ do
+ AM_RUN_LOG([$_am_tar --version]) && break
+ done
+ am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"'
+ am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"'
+ am__untar="$_am_tar -xf -"
+ ;;
+ plaintar)
+ # Must skip GNU tar: if it does not support --format= it doesn't create
+ # ustar tarball either.
+ (tar --version) >/dev/null 2>&1 && continue
+ am__tar='tar chf - "$$tardir"'
+ am__tar_='tar chf - "$tardir"'
+ am__untar='tar xf -'
+ ;;
+ pax)
+ am__tar='pax -L -x $1 -w "$$tardir"'
+ am__tar_='pax -L -x $1 -w "$tardir"'
+ am__untar='pax -r'
+ ;;
+ cpio)
+ am__tar='find "$$tardir" -print | cpio -o -H $1 -L'
+ am__tar_='find "$tardir" -print | cpio -o -H $1 -L'
+ am__untar='cpio -i -H $1 -d'
+ ;;
+ none)
+ am__tar=false
+ am__tar_=false
+ am__untar=false
+ ;;
+ esac
+
+ # If the value was cached, stop now. We just wanted to have am__tar
+ # and am__untar set.
+ test -n "${am_cv_prog_tar_$1}" && break
+
+ # tar/untar a dummy directory, and stop if the command works
+ rm -rf conftest.dir
+ mkdir conftest.dir
+ echo GrepMe > conftest.dir/file
+ AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar])
+ rm -rf conftest.dir
+ if test -s conftest.tar; then
+ AM_RUN_LOG([$am__untar <conftest.tar])
+ grep GrepMe conftest.dir/file >/dev/null 2>&1 && break
+ fi
+done
+rm -rf conftest.dir
+
+AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool])
+AC_MSG_RESULT([$am_cv_prog_tar_$1])])
+AC_SUBST([am__tar])
+AC_SUBST([am__untar])
+]) # _AM_PROG_TAR
+
diff --git a/clog.c b/clog.c
new file mode 100644
index 0000000..4999291
--- /dev/null
+++ b/clog.c
@@ -0,0 +1,176 @@
+#include "stdafx.h"
+#include "clog.h"
+
+static FILE *logFile = NULL;
+static CPhidgetLog_level logging_level = 0;
+
+/* Protects logFile, logging_level - thread safe */
+int logLockInitialized = PFALSE;
+CThread_mutex_t logLock;
+
+static const char *
+logLevelToStr(CPhidgetLog_level l)
+{
+ switch (l) {
+ case PHIDGET_LOG_CRITICAL:
+ return "CRIT";
+ case PHIDGET_LOG_ERROR:
+ return "ERR";
+ case PHIDGET_LOG_WARNING:
+ return "WARN";
+ case PHIDGET_LOG_DEBUG:
+ return "DEBUG";
+ case PHIDGET_LOG_INFO:
+ return "INFO";
+ case PHIDGET_LOG_VERBOSE:
+ return "VERBOSE";
+ }
+ return "???";
+}
+
+PHIDGET21_API int CCONV CPhidget_enableLogging(CPhidgetLog_level level, const char *outputFile)
+{
+ if(!logLockInitialized)
+ {
+ CThread_mutex_init(&logLock);
+ logLockInitialized = PTRUE;
+ }
+ CThread_mutex_lock(&logLock);
+ logging_level = level;
+ if(outputFile == NULL)
+ logFile = NULL;
+ else
+ {
+ logFile = fopen(outputFile,"a");
+#ifndef _WINDOWS
+ if(!logFile)
+ {
+ CThread_mutex_unlock(&logLock);
+ switch(errno)
+ {
+ case EACCES:
+ LOG(PHIDGET_LOG_WARNING, "Permission denied for specified logfile. Logging to stdout.");
+ break;
+ defualt:
+ LOG(PHIDGET_LOG_WARNING, "Logfile fopen failed with code: %d",errno);
+ }
+ CThread_mutex_lock(&logLock);
+ }
+#endif
+ }
+ CThread_mutex_unlock(&logLock);
+ LOG(PHIDGET_LOG_INFO, "Enabling logging");
+ return EPHIDGET_OK;
+}
+
+PHIDGET21_API int CCONV CPhidget_disableLogging()
+{
+ if(!logLockInitialized)
+ {
+ CThread_mutex_init(&logLock);
+ logLockInitialized = PTRUE;
+ }
+ LOG(PHIDGET_LOG_INFO, "Disabling logging");
+ CThread_mutex_lock(&logLock);
+ if(logFile!=NULL && logFile!=stdout && logFile!=stderr)
+ fclose(logFile);
+ logFile = NULL;
+ logging_level = 0;
+ CThread_mutex_unlock(&logLock);
+ return EPHIDGET_OK;
+}
+
+//if outputting to a file, it is designed to be CSV compliant
+//only print out debug logs in debug library
+PHIDGET21_API int CCONV CPhidget_log(CPhidgetLog_level level, const char *msg, const char *fmt, ...)
+{
+ size_t threadID = 0;
+ int logToStderr = (int)level & LOG_TO_STDERR;
+ va_list va;
+ level = level & 0xFF;
+#ifdef DEBUG
+ if(level <= logging_level || level == PHIDGET_LOG_DEBUG || logToStderr)
+#else
+ if((level <= logging_level && level != PHIDGET_LOG_DEBUG) || logToStderr)
+#endif
+ {
+ if(!logLockInitialized)
+ {
+ CThread_mutex_init(&logLock);
+ logLockInitialized = PTRUE;
+ }
+ CThread_mutex_lock(&logLock);
+ if (!logFile)
+ logFile = stdout;
+#ifdef WINCE
+ if(logToStderr)
+ fprintf(stderr, "%s: ",logLevelToStr(level));
+ else if(logFile==stdout)
+ fprintf(logFile, "%s: ",logLevelToStr(level));
+ else
+ fprintf(logFile, "%d,\"%s\",%s,\"", threadID, msg, logLevelToStr(level));
+ va_start(va, fmt);
+ if(logToStderr)
+ {
+ vfprintf(stderr, fmt, va);
+ va_end(va);
+ fprintf(stderr, "\n");
+ fflush(stderr);
+ }
+ else
+ {
+ vfprintf(logFile, fmt, va);
+ va_end(va);
+ if(logFile==stdout)
+ fprintf(logFile, "\n");
+ else
+ fprintf(logFile, "\"\n");
+ fflush(logFile);
+ }
+#else //!WINCE
+ {
+ char date[50];
+ struct tm *tmp;
+ time_t t;
+ time(&t);
+ #ifndef _WINDOWS
+ struct tm tm;
+ localtime_r(&t, &tm);
+ tmp = &tm;
+ threadID = (size_t)pthread_self();
+ #else
+ tmp = localtime(&t);
+ threadID = (size_t)GetCurrentThreadId();
+ #endif
+ if (!strftime(date, sizeof (date), "%c", tmp))
+ strncpy(date, "?", sizeof (date));
+ if(logToStderr)
+ fprintf(stderr, "%s: ",logLevelToStr(level));
+ else if(logFile==stdout)
+ fprintf(logFile, "%s: ",logLevelToStr(level));
+ else
+ fprintf(logFile, "%s,%d,\"%s\",%s,\"", date, (int)threadID, msg, logLevelToStr(level));
+ va_start(va, fmt);
+ if(logToStderr)
+ {
+ vfprintf(stderr, fmt, va);
+ va_end(va);
+ fprintf(stderr, "\n");
+ fflush(stderr);
+ }
+ else
+ {
+ vfprintf(logFile, fmt, va);
+ va_end(va);
+ if(logFile==stdout)
+ fprintf(logFile, "\n");
+ else
+ fprintf(logFile, "\"\n");
+ fflush(logFile);
+ }
+ }
+#endif
+ CThread_mutex_unlock(&logLock);
+ }
+ return EPHIDGET_OK;
+}
diff --git a/clog.h b/clog.h
new file mode 100644
index 0000000..93cdb30
--- /dev/null
+++ b/clog.h
@@ -0,0 +1,50 @@
+#ifndef _CLOG
+#define _CLOG
+
+/** \defgroup phidlog Phidget Logging
+ * Logging is provided mainly for debugging purposes. Enabling logging will output internal library
+ * information that can be used to find bugs with the help of Phidgetd Inc. Alternatively, the user
+ * can enable and write to the log for their own uses.
+ * @{
+ */
+
+typedef enum {
+ PHIDGET_LOG_CRITICAL = 1, /**< Really important errors that can't be recovered. Usually followed by an abort() */
+ PHIDGET_LOG_ERROR, /**< Errors that are recovered from. */
+ PHIDGET_LOG_WARNING, /**< Warning's about weird things that aren't neccesarily wrong. */
+ PHIDGET_LOG_DEBUG, /**< Should only be used during development - only shows up in the debug library. */
+ PHIDGET_LOG_INFO, /**< Info about the going on's in the library. */
+ PHIDGET_LOG_VERBOSE /**< Everything, including very common messages. */
+} CPhidgetLog_level;
+
+/**
+ * Enables logging.
+ * @param level The highest level of logging to output. All lower levels will also be output.
+ * @param outputFile File to output log to. This should be a full pathname, not a relative pathname. Specify NULL to output to stdout.
+ */
+PHIDGET21_API int CCONV CPhidget_enableLogging(CPhidgetLog_level level, const char *outputFile);
+/**
+ * Disables logging.
+ */
+PHIDGET21_API int CCONV CPhidget_disableLogging();
+/**
+ * Appends a message to the log.
+ * @param level The level at which to log the message.
+ * @param id An arbitrary identifier.
+ * @param message The message (printf style).
+ */
+PHIDGET21_API int CCONV CPhidget_log(CPhidgetLog_level level, const char *id, const char *message, ...);
+
+#ifndef EXTERNALPROTO
+
+#define LOG_TO_STDERR 0x8000
+#define STRINGIFY(x) #x
+#define TOSTRING(x) STRINGIFY(x)
+#define LOG(level, ...) CPhidget_log(level, __FILE__ "(" TOSTRING(__LINE__) ")", __VA_ARGS__)
+#define LOG_STDERR(level, ...) CPhidget_log(LOG_TO_STDERR|level, __FILE__ "(" TOSTRING(__LINE__) ")", __VA_ARGS__)
+
+#endif
+
+/** @} */
+
+#endif
diff --git a/config.guess b/config.guess
new file mode 100755
index 0000000..da83314
--- /dev/null
+++ b/config.guess
@@ -0,0 +1,1561 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
+# Free Software Foundation, Inc.
+
+timestamp='2009-04-27'
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+# 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+
+# Originally written by Per Bothner <per@bothner.com>.
+# Please send patches to <config-patches@gnu.org>. Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# This script attempts to guess a canonical system name similar to
+# config.sub. If it succeeds, it prints the system name on stdout, and
+# exits with 0. Otherwise, it exits with 1.
+#
+# The plan is that this can be called by configure scripts if you
+# don't specify an explicit build system type.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION]
+
+Output the configuration name of the system \`$me' is run on.
+
+Operation modes:
+ -h, --help print this help, then exit
+ -t, --time-stamp print date of last modification, then exit
+ -v, --version print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
+2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+ case $1 in
+ --time-stamp | --time* | -t )
+ echo "$timestamp" ; exit ;;
+ --version | -v )
+ echo "$version" ; exit ;;
+ --help | --h* | -h )
+ echo "$usage"; exit ;;
+ -- ) # Stop option processing
+ shift; break ;;
+ - ) # Use stdin as input.
+ break ;;
+ -* )
+ echo "$me: invalid option $1$help" >&2
+ exit 1 ;;
+ * )
+ break ;;
+ esac
+done
+
+if test $# != 0; then
+ echo "$me: too many arguments$help" >&2
+ exit 1
+fi
+
+trap 'exit 1' 1 2 15
+
+# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
+# compiler to aid in system detection is discouraged as it requires
+# temporary files to be created and, as you can see below, it is a
+# headache to deal with in a portable fashion.
+
+# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
+# use `HOST_CC' if defined, but it is deprecated.
+
+# Portable tmp directory creation inspired by the Autoconf team.
+
+set_cc_for_build='
+trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
+trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
+: ${TMPDIR=/tmp} ;
+ { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
+ { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
+ { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
+ { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
+dummy=$tmp/dummy ;
+tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
+case $CC_FOR_BUILD,$HOST_CC,$CC in
+ ,,) echo "int x;" > $dummy.c ;
+ for c in cc gcc c89 c99 ; do
+ if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
+ CC_FOR_BUILD="$c"; break ;
+ fi ;
+ done ;
+ if test x"$CC_FOR_BUILD" = x ; then
+ CC_FOR_BUILD=no_compiler_found ;
+ fi
+ ;;
+ ,,*) CC_FOR_BUILD=$CC ;;
+ ,*,*) CC_FOR_BUILD=$HOST_CC ;;
+esac ; set_cc_for_build= ;'
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi@noc.rutgers.edu 1994-08-24)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+ PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+ *:NetBSD:*:*)
+ # NetBSD (nbsd) targets should (where applicable) match one or
+ # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
+ # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently
+ # switched to ELF, *-*-netbsd* would select the old
+ # object file format. This provides both forward
+ # compatibility and a consistent mechanism for selecting the
+ # object file format.
+ #
+ # Note: NetBSD doesn't particularly care about the vendor
+ # portion of the name. We always set it to "unknown".
+ sysctl="sysctl -n hw.machine_arch"
+ UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
+ /usr/sbin/$sysctl 2>/dev/null || echo unknown)`
+ case "${UNAME_MACHINE_ARCH}" in
+ armeb) machine=armeb-unknown ;;
+ arm*) machine=arm-unknown ;;
+ sh3el) machine=shl-unknown ;;
+ sh3eb) machine=sh-unknown ;;
+ sh5el) machine=sh5le-unknown ;;
+ *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
+ esac
+ # The Operating System including object format, if it has switched
+ # to ELF recently, or will in the future.
+ case "${UNAME_MACHINE_ARCH}" in
+ arm*|i386|m68k|ns32k|sh3*|sparc|vax)
+ eval $set_cc_for_build
+ if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep __ELF__ >/dev/null
+ then
+ # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
+ # Return netbsd for either. FIX?
+ os=netbsd
+ else
+ os=netbsdelf
+ fi
+ ;;
+ *)
+ os=netbsd
+ ;;
+ esac
+ # The OS release
+ # Debian GNU/NetBSD machines have a different userland, and
+ # thus, need a distinct triplet. However, they do not need
+ # kernel version information, so it can be replaced with a
+ # suitable tag, in the style of linux-gnu.
+ case "${UNAME_VERSION}" in
+ Debian*)
+ release='-gnu'
+ ;;
+ *)
+ release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+ ;;
+ esac
+ # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
+ # contains redundant information, the shorter form:
+ # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
+ echo "${machine}-${os}${release}"
+ exit ;;
+ *:OpenBSD:*:*)
+ UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
+ echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
+ exit ;;
+ *:ekkoBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
+ exit ;;
+ *:SolidBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE}
+ exit ;;
+ macppc:MirBSD:*:*)
+ echo powerpc-unknown-mirbsd${UNAME_RELEASE}
+ exit ;;
+ *:MirBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
+ exit ;;
+ alpha:OSF1:*:*)
+ case $UNAME_RELEASE in
+ *4.0)
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+ ;;
+ *5.*)
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
+ ;;
+ esac
+ # According to Compaq, /usr/sbin/psrinfo has been available on
+ # OSF/1 and Tru64 systems produced since 1995. I hope that
+ # covers most systems running today. This code pipes the CPU
+ # types through head -n 1, so we only detect the type of CPU 0.
+ ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1`
+ case "$ALPHA_CPU_TYPE" in
+ "EV4 (21064)")
+ UNAME_MACHINE="alpha" ;;
+ "EV4.5 (21064)")
+ UNAME_MACHINE="alpha" ;;
+ "LCA4 (21066/21068)")
+ UNAME_MACHINE="alpha" ;;
+ "EV5 (21164)")
+ UNAME_MACHINE="alphaev5" ;;
+ "EV5.6 (21164A)")
+ UNAME_MACHINE="alphaev56" ;;
+ "EV5.6 (21164PC)")
+ UNAME_MACHINE="alphapca56" ;;
+ "EV5.7 (21164PC)")
+ UNAME_MACHINE="alphapca57" ;;
+ "EV6 (21264)")
+ UNAME_MACHINE="alphaev6" ;;
+ "EV6.7 (21264A)")
+ UNAME_MACHINE="alphaev67" ;;
+ "EV6.8CB (21264C)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.8AL (21264B)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.8CX (21264D)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.9A (21264/EV69A)")
+ UNAME_MACHINE="alphaev69" ;;
+ "EV7 (21364)")
+ UNAME_MACHINE="alphaev7" ;;
+ "EV7.9 (21364A)")
+ UNAME_MACHINE="alphaev79" ;;
+ esac
+ # A Pn.n version is a patched version.
+ # A Vn.n version is a released version.
+ # A Tn.n version is a released field test version.
+ # A Xn.n version is an unreleased experimental baselevel.
+ # 1.2 uses "1.2" for uname -r.
+ echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ exit ;;
+ Alpha\ *:Windows_NT*:*)
+ # How do we know it's Interix rather than the generic POSIX subsystem?
+ # Should we change UNAME_MACHINE based on the output of uname instead
+ # of the specific Alpha model?
+ echo alpha-pc-interix
+ exit ;;
+ 21064:Windows_NT:50:3)
+ echo alpha-dec-winnt3.5
+ exit ;;
+ Amiga*:UNIX_System_V:4.0:*)
+ echo m68k-unknown-sysv4
+ exit ;;
+ *:[Aa]miga[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-unknown-amigaos
+ exit ;;
+ *:[Mm]orph[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-unknown-morphos
+ exit ;;
+ *:OS/390:*:*)
+ echo i370-ibm-openedition
+ exit ;;
+ *:z/VM:*:*)
+ echo s390-ibm-zvmoe
+ exit ;;
+ *:OS400:*:*)
+ echo powerpc-ibm-os400
+ exit ;;
+ arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+ echo arm-acorn-riscix${UNAME_RELEASE}
+ exit ;;
+ arm:riscos:*:*|arm:RISCOS:*:*)
+ echo arm-unknown-riscos
+ exit ;;
+ SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+ echo hppa1.1-hitachi-hiuxmpp
+ exit ;;
+ Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
+ # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+ if test "`(/bin/universe) 2>/dev/null`" = att ; then
+ echo pyramid-pyramid-sysv3
+ else
+ echo pyramid-pyramid-bsd
+ fi
+ exit ;;
+ NILE*:*:*:dcosx)
+ echo pyramid-pyramid-svr4
+ exit ;;
+ DRS?6000:unix:4.0:6*)
+ echo sparc-icl-nx6
+ exit ;;
+ DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
+ case `/usr/bin/uname -p` in
+ sparc) echo sparc-icl-nx7; exit ;;
+ esac ;;
+ s390x:SunOS:*:*)
+ echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ sun4H:SunOS:5.*:*)
+ echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+ echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
+ eval $set_cc_for_build
+ SUN_ARCH="i386"
+ # If there is a compiler, see if it is configured for 64-bit objects.
+ # Note that the Sun cc does not turn __LP64__ into 1 like gcc does.
+ # This test works for both compilers.
+ if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
+ if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \
+ (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
+ grep IS_64BIT_ARCH >/dev/null
+ then
+ SUN_ARCH="x86_64"
+ fi
+ fi
+ echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ sun4*:SunOS:6*:*)
+ # According to config.sub, this is the proper way to canonicalize
+ # SunOS6. Hard to guess exactly what SunOS6 will be like, but
+ # it's likely to be more like Solaris than SunOS4.
+ echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ sun4*:SunOS:*:*)
+ case "`/usr/bin/arch -k`" in
+ Series*|S4*)
+ UNAME_RELEASE=`uname -v`
+ ;;
+ esac
+ # Japanese Language versions have a version number like `4.1.3-JL'.
+ echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+ exit ;;
+ sun3*:SunOS:*:*)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ exit ;;
+ sun*:*:4.2BSD:*)
+ UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+ test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
+ case "`/bin/arch`" in
+ sun3)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ ;;
+ sun4)
+ echo sparc-sun-sunos${UNAME_RELEASE}
+ ;;
+ esac
+ exit ;;
+ aushp:SunOS:*:*)
+ echo sparc-auspex-sunos${UNAME_RELEASE}
+ exit ;;
+ # The situation for MiNT is a little confusing. The machine name
+ # can be virtually everything (everything which is not
+ # "atarist" or "atariste" at least should have a processor
+ # > m68000). The system name ranges from "MiNT" over "FreeMiNT"
+ # to the lowercase version "mint" (or "freemint"). Finally
+ # the system name "TOS" denotes a system which is actually not
+ # MiNT. But MiNT is downward compatible to TOS, so this should
+ # be no problem.
+ atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit ;;
+ atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit ;;
+ *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit ;;
+ milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+ echo m68k-milan-mint${UNAME_RELEASE}
+ exit ;;
+ hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+ echo m68k-hades-mint${UNAME_RELEASE}
+ exit ;;
+ *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+ echo m68k-unknown-mint${UNAME_RELEASE}
+ exit ;;
+ m68k:machten:*:*)
+ echo m68k-apple-machten${UNAME_RELEASE}
+ exit ;;
+ powerpc:machten:*:*)
+ echo powerpc-apple-machten${UNAME_RELEASE}
+ exit ;;
+ RISC*:Mach:*:*)
+ echo mips-dec-mach_bsd4.3
+ exit ;;
+ RISC*:ULTRIX:*:*)
+ echo mips-dec-ultrix${UNAME_RELEASE}
+ exit ;;
+ VAX*:ULTRIX*:*:*)
+ echo vax-dec-ultrix${UNAME_RELEASE}
+ exit ;;
+ 2020:CLIX:*:* | 2430:CLIX:*:*)
+ echo clipper-intergraph-clix${UNAME_RELEASE}
+ exit ;;
+ mips:*:*:UMIPS | mips:*:*:RISCos)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+#ifdef __cplusplus
+#include <stdio.h> /* for printf() prototype */
+ int main (int argc, char *argv[]) {
+#else
+ int main (argc, argv) int argc; char *argv[]; {
+#endif
+ #if defined (host_mips) && defined (MIPSEB)
+ #if defined (SYSTYPE_SYSV)
+ printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_SVR4)
+ printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+ printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+ #endif
+ #endif
+ exit (-1);
+ }
+EOF
+ $CC_FOR_BUILD -o $dummy $dummy.c &&
+ dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` &&
+ SYSTEM_NAME=`$dummy $dummyarg` &&
+ { echo "$SYSTEM_NAME"; exit; }
+ echo mips-mips-riscos${UNAME_RELEASE}
+ exit ;;
+ Motorola:PowerMAX_OS:*:*)
+ echo powerpc-motorola-powermax
+ exit ;;
+ Motorola:*:4.3:PL8-*)
+ echo powerpc-harris-powermax
+ exit ;;
+ Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
+ echo powerpc-harris-powermax
+ exit ;;
+ Night_Hawk:Power_UNIX:*:*)
+ echo powerpc-harris-powerunix
+ exit ;;
+ m88k:CX/UX:7*:*)
+ echo m88k-harris-cxux7
+ exit ;;
+ m88k:*:4*:R4*)
+ echo m88k-motorola-sysv4
+ exit ;;
+ m88k:*:3*:R3*)
+ echo m88k-motorola-sysv3
+ exit ;;
+ AViiON:dgux:*:*)
+ # DG/UX returns AViiON for all architectures
+ UNAME_PROCESSOR=`/usr/bin/uname -p`
+ if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
+ then
+ if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
+ [ ${TARGET_BINARY_INTERFACE}x = x ]
+ then
+ echo m88k-dg-dgux${UNAME_RELEASE}
+ else
+ echo m88k-dg-dguxbcs${UNAME_RELEASE}
+ fi
+ else
+ echo i586-dg-dgux${UNAME_RELEASE}
+ fi
+ exit ;;
+ M88*:DolphinOS:*:*) # DolphinOS (SVR3)
+ echo m88k-dolphin-sysv3
+ exit ;;
+ M88*:*:R3*:*)
+ # Delta 88k system running SVR3
+ echo m88k-motorola-sysv3
+ exit ;;
+ XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+ echo m88k-tektronix-sysv3
+ exit ;;
+ Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+ echo m68k-tektronix-bsd
+ exit ;;
+ *:IRIX*:*:*)
+ echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+ exit ;;
+ ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+ echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id
+ exit ;; # Note that: echo "'`uname -s`'" gives 'AIX '
+ i*86:AIX:*:*)
+ echo i386-ibm-aix
+ exit ;;
+ ia64:AIX:*:*)
+ if [ -x /usr/bin/oslevel ] ; then
+ IBM_REV=`/usr/bin/oslevel`
+ else
+ IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+ fi
+ echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
+ exit ;;
+ *:AIX:2:3)
+ if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <sys/systemcfg.h>
+
+ main()
+ {
+ if (!__power_pc())
+ exit(1);
+ puts("powerpc-ibm-aix3.2.5");
+ exit(0);
+ }
+EOF
+ if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy`
+ then
+ echo "$SYSTEM_NAME"
+ else
+ echo rs6000-ibm-aix3.2.5
+ fi
+ elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+ echo rs6000-ibm-aix3.2.4
+ else
+ echo rs6000-ibm-aix3.2
+ fi
+ exit ;;
+ *:AIX:*:[456])
+ IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
+ if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
+ IBM_ARCH=rs6000
+ else
+ IBM_ARCH=powerpc
+ fi
+ if [ -x /usr/bin/oslevel ] ; then
+ IBM_REV=`/usr/bin/oslevel`
+ else
+ IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+ fi
+ echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+ exit ;;
+ *:AIX:*:*)
+ echo rs6000-ibm-aix
+ exit ;;
+ ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+ echo romp-ibm-bsd4.4
+ exit ;;
+ ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and
+ echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to
+ exit ;; # report: romp-ibm BSD 4.3
+ *:BOSX:*:*)
+ echo rs6000-bull-bosx
+ exit ;;
+ DPX/2?00:B.O.S.:*:*)
+ echo m68k-bull-sysv3
+ exit ;;
+ 9000/[34]??:4.3bsd:1.*:*)
+ echo m68k-hp-bsd
+ exit ;;
+ hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+ echo m68k-hp-bsd4.4
+ exit ;;
+ 9000/[34678]??:HP-UX:*:*)
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ case "${UNAME_MACHINE}" in
+ 9000/31? ) HP_ARCH=m68000 ;;
+ 9000/[34]?? ) HP_ARCH=m68k ;;
+ 9000/[678][0-9][0-9])
+ if [ -x /usr/bin/getconf ]; then
+ sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+ sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+ case "${sc_cpu_version}" in
+ 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
+ 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+ 532) # CPU_PA_RISC2_0
+ case "${sc_kernel_bits}" in
+ 32) HP_ARCH="hppa2.0n" ;;
+ 64) HP_ARCH="hppa2.0w" ;;
+ '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20
+ esac ;;
+ esac
+ fi
+ if [ "${HP_ARCH}" = "" ]; then
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+
+ #define _HPUX_SOURCE
+ #include <stdlib.h>
+ #include <unistd.h>
+
+ int main ()
+ {
+ #if defined(_SC_KERNEL_BITS)
+ long bits = sysconf(_SC_KERNEL_BITS);
+ #endif
+ long cpu = sysconf (_SC_CPU_VERSION);
+
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+ case CPU_PA_RISC2_0:
+ #if defined(_SC_KERNEL_BITS)
+ switch (bits)
+ {
+ case 64: puts ("hppa2.0w"); break;
+ case 32: puts ("hppa2.0n"); break;
+ default: puts ("hppa2.0"); break;
+ } break;
+ #else /* !defined(_SC_KERNEL_BITS) */
+ puts ("hppa2.0"); break;
+ #endif
+ default: puts ("hppa1.0"); break;
+ }
+ exit (0);
+ }
+EOF
+ (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
+ test -z "$HP_ARCH" && HP_ARCH=hppa
+ fi ;;
+ esac
+ if [ ${HP_ARCH} = "hppa2.0w" ]
+ then
+ eval $set_cc_for_build
+
+ # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
+ # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler
+ # generating 64-bit code. GNU and HP use different nomenclature:
+ #
+ # $ CC_FOR_BUILD=cc ./config.guess
+ # => hppa2.0w-hp-hpux11.23
+ # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
+ # => hppa64-hp-hpux11.23
+
+ if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |
+ grep __LP64__ >/dev/null
+ then
+ HP_ARCH="hppa2.0w"
+ else
+ HP_ARCH="hppa64"
+ fi
+ fi
+ echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+ exit ;;
+ ia64:HP-UX:*:*)
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ echo ia64-hp-hpux${HPUX_REV}
+ exit ;;
+ 3050*:HI-UX:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <unistd.h>
+ int
+ main ()
+ {
+ long cpu = sysconf (_SC_CPU_VERSION);
+ /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+ true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct
+ results, however. */
+ if (CPU_IS_PA_RISC (cpu))
+ {
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+ default: puts ("hppa-hitachi-hiuxwe2"); break;
+ }
+ }
+ else if (CPU_IS_HP_MC68K (cpu))
+ puts ("m68k-hitachi-hiuxwe2");
+ else puts ("unknown-hitachi-hiuxwe2");
+ exit (0);
+ }
+EOF
+ $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` &&
+ { echo "$SYSTEM_NAME"; exit; }
+ echo unknown-hitachi-hiuxwe2
+ exit ;;
+ 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+ echo hppa1.1-hp-bsd
+ exit ;;
+ 9000/8??:4.3bsd:*:*)
+ echo hppa1.0-hp-bsd
+ exit ;;
+ *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+ echo hppa1.0-hp-mpeix
+ exit ;;
+ hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+ echo hppa1.1-hp-osf
+ exit ;;
+ hp8??:OSF1:*:*)
+ echo hppa1.0-hp-osf
+ exit ;;
+ i*86:OSF1:*:*)
+ if [ -x /usr/sbin/sysversion ] ; then
+ echo ${UNAME_MACHINE}-unknown-osf1mk
+ else
+ echo ${UNAME_MACHINE}-unknown-osf1
+ fi
+ exit ;;
+ parisc*:Lites*:*:*)
+ echo hppa1.1-hp-lites
+ exit ;;
+ C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+ echo c1-convex-bsd
+ exit ;;
+ C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit ;;
+ C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+ echo c34-convex-bsd
+ exit ;;
+ C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+ echo c38-convex-bsd
+ exit ;;
+ C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+ echo c4-convex-bsd
+ exit ;;
+ CRAY*Y-MP:*:*:*)
+ echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*[A-Z]90:*:*:*)
+ echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
+ -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*TS:*:*:*)
+ echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*T3E:*:*:*)
+ echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*SV1:*:*:*)
+ echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ *:UNICOS/mp:*:*)
+ echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
+ FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+ echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit ;;
+ 5000:UNIX_System_V:4.*:*)
+ FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
+ echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit ;;
+ i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+ echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+ exit ;;
+ sparc*:BSD/OS:*:*)
+ echo sparc-unknown-bsdi${UNAME_RELEASE}
+ exit ;;
+ *:BSD/OS:*:*)
+ echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+ exit ;;
+ *:FreeBSD:*:*)
+ case ${UNAME_MACHINE} in
+ pc98)
+ echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+ amd64)
+ echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+ *)
+ echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+ esac
+ exit ;;
+ i*:CYGWIN*:*)
+ echo ${UNAME_MACHINE}-pc-cygwin
+ exit ;;
+ *:MINGW*:*)
+ echo ${UNAME_MACHINE}-pc-mingw32
+ exit ;;
+ i*:windows32*:*)
+ # uname -m includes "-pc" on this system.
+ echo ${UNAME_MACHINE}-mingw32
+ exit ;;
+ i*:PW*:*)
+ echo ${UNAME_MACHINE}-pc-pw32
+ exit ;;
+ *:Interix*:[3456]*)
+ case ${UNAME_MACHINE} in
+ x86)
+ echo i586-pc-interix${UNAME_RELEASE}
+ exit ;;
+ EM64T | authenticamd | genuineintel)
+ echo x86_64-unknown-interix${UNAME_RELEASE}
+ exit ;;
+ IA64)
+ echo ia64-unknown-interix${UNAME_RELEASE}
+ exit ;;
+ esac ;;
+ [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
+ echo i${UNAME_MACHINE}-pc-mks
+ exit ;;
+ i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
+ # How do we know it's Interix rather than the generic POSIX subsystem?
+ # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
+ # UNAME_MACHINE based on the output of uname instead of i386?
+ echo i586-pc-interix
+ exit ;;
+ i*:UWIN*:*)
+ echo ${UNAME_MACHINE}-pc-uwin
+ exit ;;
+ amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
+ echo x86_64-unknown-cygwin
+ exit ;;
+ p*:CYGWIN*:*)
+ echo powerpcle-unknown-cygwin
+ exit ;;
+ prep*:SunOS:5.*:*)
+ echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ *:GNU:*:*)
+ # the GNU system
+ echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+ exit ;;
+ *:GNU/*:*:*)
+ # other systems with GNU libc and userland
+ echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu
+ exit ;;
+ i*86:Minix:*:*)
+ echo ${UNAME_MACHINE}-pc-minix
+ exit ;;
+ arm*:Linux:*:*)
+ eval $set_cc_for_build
+ if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep -q __ARM_EABI__
+ then
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ else
+ echo ${UNAME_MACHINE}-unknown-linux-gnueabi
+ fi
+ exit ;;
+ avr32*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ cris:Linux:*:*)
+ echo cris-axis-linux-gnu
+ exit ;;
+ crisv32:Linux:*:*)
+ echo crisv32-axis-linux-gnu
+ exit ;;
+ frv:Linux:*:*)
+ echo frv-unknown-linux-gnu
+ exit ;;
+ ia64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ m32r*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ m68*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ mips:Linux:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #undef CPU
+ #undef mips
+ #undef mipsel
+ #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+ CPU=mipsel
+ #else
+ #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+ CPU=mips
+ #else
+ CPU=
+ #endif
+ #endif
+EOF
+ eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
+ /^CPU/{
+ s: ::g
+ p
+ }'`"
+ test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
+ ;;
+ mips64:Linux:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #undef CPU
+ #undef mips64
+ #undef mips64el
+ #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+ CPU=mips64el
+ #else
+ #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+ CPU=mips64
+ #else
+ CPU=
+ #endif
+ #endif
+EOF
+ eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
+ /^CPU/{
+ s: ::g
+ p
+ }'`"
+ test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
+ ;;
+ or32:Linux:*:*)
+ echo or32-unknown-linux-gnu
+ exit ;;
+ ppc:Linux:*:*)
+ echo powerpc-unknown-linux-gnu
+ exit ;;
+ ppc64:Linux:*:*)
+ echo powerpc64-unknown-linux-gnu
+ exit ;;
+ alpha:Linux:*:*)
+ case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+ EV5) UNAME_MACHINE=alphaev5 ;;
+ EV56) UNAME_MACHINE=alphaev56 ;;
+ PCA56) UNAME_MACHINE=alphapca56 ;;
+ PCA57) UNAME_MACHINE=alphapca56 ;;
+ EV6) UNAME_MACHINE=alphaev6 ;;
+ EV67) UNAME_MACHINE=alphaev67 ;;
+ EV68*) UNAME_MACHINE=alphaev68 ;;
+ esac
+ objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null
+ if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
+ echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
+ exit ;;
+ padre:Linux:*:*)
+ echo sparc-unknown-linux-gnu
+ exit ;;
+ parisc:Linux:*:* | hppa:Linux:*:*)
+ # Look for CPU level
+ case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
+ PA7*) echo hppa1.1-unknown-linux-gnu ;;
+ PA8*) echo hppa2.0-unknown-linux-gnu ;;
+ *) echo hppa-unknown-linux-gnu ;;
+ esac
+ exit ;;
+ parisc64:Linux:*:* | hppa64:Linux:*:*)
+ echo hppa64-unknown-linux-gnu
+ exit ;;
+ s390:Linux:*:* | s390x:Linux:*:*)
+ echo ${UNAME_MACHINE}-ibm-linux
+ exit ;;
+ sh64*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ sh*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ sparc:Linux:*:* | sparc64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ vax:Linux:*:*)
+ echo ${UNAME_MACHINE}-dec-linux-gnu
+ exit ;;
+ x86_64:Linux:*:*)
+ echo x86_64-unknown-linux-gnu
+ exit ;;
+ xtensa*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ i*86:Linux:*:*)
+ # The BFD linker knows what the default object file format is, so
+ # first see if it will tell us. cd to the root directory to prevent
+ # problems with other programs or directories called `ld' in the path.
+ # Set LC_ALL=C to ensure ld outputs messages in English.
+ ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \
+ | sed -ne '/supported targets:/!d
+ s/[ ][ ]*/ /g
+ s/.*supported targets: *//
+ s/ .*//
+ p'`
+ case "$ld_supported_targets" in
+ elf32-i386)
+ TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu"
+ ;;
+ a.out-i386-linux)
+ echo "${UNAME_MACHINE}-pc-linux-gnuaout"
+ exit ;;
+ "")
+ # Either a pre-BFD a.out linker (linux-gnuoldld) or
+ # one that does not give us useful --help.
+ echo "${UNAME_MACHINE}-pc-linux-gnuoldld"
+ exit ;;
+ esac
+ # Determine whether the default compiler is a.out or elf
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <features.h>
+ #ifdef __ELF__
+ # ifdef __GLIBC__
+ # if __GLIBC__ >= 2
+ LIBC=gnu
+ # else
+ LIBC=gnulibc1
+ # endif
+ # else
+ LIBC=gnulibc1
+ # endif
+ #else
+ #if defined(__INTEL_COMPILER) || defined(__PGI) || defined(__SUNPRO_C) || defined(__SUNPRO_CC)
+ LIBC=gnu
+ #else
+ LIBC=gnuaout
+ #endif
+ #endif
+ #ifdef __dietlibc__
+ LIBC=dietlibc
+ #endif
+EOF
+ eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
+ /^LIBC/{
+ s: ::g
+ p
+ }'`"
+ test x"${LIBC}" != x && {
+ echo "${UNAME_MACHINE}-pc-linux-${LIBC}"
+ exit
+ }
+ test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; }
+ ;;
+ i*86:DYNIX/ptx:4*:*)
+ # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
+ # earlier versions are messed up and put the nodename in both
+ # sysname and nodename.
+ echo i386-sequent-sysv4
+ exit ;;
+ i*86:UNIX_SV:4.2MP:2.*)
+ # Unixware is an offshoot of SVR4, but it has its own version
+ # number series starting with 2...
+ # I am not positive that other SVR4 systems won't match this,
+ # I just have to hope. -- rms.
+ # Use sysv4.2uw... so that sysv4* matches it.
+ echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+ exit ;;
+ i*86:OS/2:*:*)
+ # If we were able to find `uname', then EMX Unix compatibility
+ # is probably installed.
+ echo ${UNAME_MACHINE}-pc-os2-emx
+ exit ;;
+ i*86:XTS-300:*:STOP)
+ echo ${UNAME_MACHINE}-unknown-stop
+ exit ;;
+ i*86:atheos:*:*)
+ echo ${UNAME_MACHINE}-unknown-atheos
+ exit ;;
+ i*86:syllable:*:*)
+ echo ${UNAME_MACHINE}-pc-syllable
+ exit ;;
+ i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
+ echo i386-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ i*86:*DOS:*:*)
+ echo ${UNAME_MACHINE}-pc-msdosdjgpp
+ exit ;;
+ i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
+ UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
+ if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+ echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
+ else
+ echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
+ fi
+ exit ;;
+ i*86:*:5:[678]*)
+ # UnixWare 7.x, OpenUNIX and OpenServer 6.
+ case `/bin/uname -X | grep "^Machine"` in
+ *486*) UNAME_MACHINE=i486 ;;
+ *Pentium) UNAME_MACHINE=i586 ;;
+ *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
+ esac
+ echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+ exit ;;
+ i*86:*:3.2:*)
+ if test -f /usr/options/cb.name; then
+ UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+ echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+ elif /bin/uname -X 2>/dev/null >/dev/null ; then
+ UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
+ (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
+ (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
+ && UNAME_MACHINE=i586
+ (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
+ && UNAME_MACHINE=i686
+ (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
+ && UNAME_MACHINE=i686
+ echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+ else
+ echo ${UNAME_MACHINE}-pc-sysv32
+ fi
+ exit ;;
+ pc:*:*:*)
+ # Left here for compatibility:
+ # uname -m prints for DJGPP always 'pc', but it prints nothing about
+ # the processor, so we play safe by assuming i586.
+ # Note: whatever this is, it MUST be the same as what config.sub
+ # prints for the "djgpp" host, or else GDB configury will decide that
+ # this is a cross-build.
+ echo i586-pc-msdosdjgpp
+ exit ;;
+ Intel:Mach:3*:*)
+ echo i386-pc-mach3
+ exit ;;
+ paragon:*:*:*)
+ echo i860-intel-osf1
+ exit ;;
+ i860:*:4.*:*) # i860-SVR4
+ if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+ echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+ else # Add other i860-SVR4 vendors below as they are discovered.
+ echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4
+ fi
+ exit ;;
+ mini*:CTIX:SYS*5:*)
+ # "miniframe"
+ echo m68010-convergent-sysv
+ exit ;;
+ mc68k:UNIX:SYSTEM5:3.51m)
+ echo m68k-convergent-sysv
+ exit ;;
+ M680?0:D-NIX:5.3:*)
+ echo m68k-diab-dnix
+ exit ;;
+ M68*:*:R3V[5678]*:*)
+ test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
+ 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
+ OS_REL=''
+ test -r /etc/.relid \
+ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+ /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+ 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && { echo i486-ncr-sysv4; exit; } ;;
+ NCR*:*:4.2:* | MPRAS*:*:4.2:*)
+ OS_REL='.3'
+ test -r /etc/.relid \
+ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+ /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+ && { echo i586-ncr-sysv4.3${OS_REL}; exit; }
+ /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \
+ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+ m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+ echo m68k-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ mc68030:UNIX_System_V:4.*:*)
+ echo m68k-atari-sysv4
+ exit ;;
+ TSUNAMI:LynxOS:2.*:*)
+ echo sparc-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ rs6000:LynxOS:2.*:*)
+ echo rs6000-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*)
+ echo powerpc-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ SM[BE]S:UNIX_SV:*:*)
+ echo mips-dde-sysv${UNAME_RELEASE}
+ exit ;;
+ RM*:ReliantUNIX-*:*:*)
+ echo mips-sni-sysv4
+ exit ;;
+ RM*:SINIX-*:*:*)
+ echo mips-sni-sysv4
+ exit ;;
+ *:SINIX-*:*:*)
+ if uname -p 2>/dev/null >/dev/null ; then
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ echo ${UNAME_MACHINE}-sni-sysv4
+ else
+ echo ns32k-sni-sysv
+ fi
+ exit ;;
+ PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+ # says <Richard.M.Bartel@ccMail.Census.GOV>
+ echo i586-unisys-sysv4
+ exit ;;
+ *:UNIX_System_V:4*:FTX*)
+ # From Gerald Hewes <hewes@openmarket.com>.
+ # How about differentiating between stratus architectures? -djm
+ echo hppa1.1-stratus-sysv4
+ exit ;;
+ *:*:*:FTX*)
+ # From seanf@swdc.stratus.com.
+ echo i860-stratus-sysv4
+ exit ;;
+ i*86:VOS:*:*)
+ # From Paul.Green@stratus.com.
+ echo ${UNAME_MACHINE}-stratus-vos
+ exit ;;
+ *:VOS:*:*)
+ # From Paul.Green@stratus.com.
+ echo hppa1.1-stratus-vos
+ exit ;;
+ mc68*:A/UX:*:*)
+ echo m68k-apple-aux${UNAME_RELEASE}
+ exit ;;
+ news*:NEWS-OS:6*:*)
+ echo mips-sony-newsos6
+ exit ;;
+ R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
+ if [ -d /usr/nec ]; then
+ echo mips-nec-sysv${UNAME_RELEASE}
+ else
+ echo mips-unknown-sysv${UNAME_RELEASE}
+ fi
+ exit ;;
+ BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
+ echo powerpc-be-beos
+ exit ;;
+ BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only.
+ echo powerpc-apple-beos
+ exit ;;
+ BePC:BeOS:*:*) # BeOS running on Intel PC compatible.
+ echo i586-pc-beos
+ exit ;;
+ BePC:Haiku:*:*) # Haiku running on Intel PC compatible.
+ echo i586-pc-haiku
+ exit ;;
+ SX-4:SUPER-UX:*:*)
+ echo sx4-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-5:SUPER-UX:*:*)
+ echo sx5-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-6:SUPER-UX:*:*)
+ echo sx6-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-7:SUPER-UX:*:*)
+ echo sx7-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-8:SUPER-UX:*:*)
+ echo sx8-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-8R:SUPER-UX:*:*)
+ echo sx8r-nec-superux${UNAME_RELEASE}
+ exit ;;
+ Power*:Rhapsody:*:*)
+ echo powerpc-apple-rhapsody${UNAME_RELEASE}
+ exit ;;
+ *:Rhapsody:*:*)
+ echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+ exit ;;
+ *:Darwin:*:*)
+ UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
+ case $UNAME_PROCESSOR in
+ unknown) UNAME_PROCESSOR=powerpc ;;
+ esac
+ echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
+ exit ;;
+ *:procnto*:*:* | *:QNX:[0123456789]*:*)
+ UNAME_PROCESSOR=`uname -p`
+ if test "$UNAME_PROCESSOR" = "x86"; then
+ UNAME_PROCESSOR=i386
+ UNAME_MACHINE=pc
+ fi
+ echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
+ exit ;;
+ *:QNX:*:4*)
+ echo i386-pc-qnx
+ exit ;;
+ NSE-?:NONSTOP_KERNEL:*:*)
+ echo nse-tandem-nsk${UNAME_RELEASE}
+ exit ;;
+ NSR-?:NONSTOP_KERNEL:*:*)
+ echo nsr-tandem-nsk${UNAME_RELEASE}
+ exit ;;
+ *:NonStop-UX:*:*)
+ echo mips-compaq-nonstopux
+ exit ;;
+ BS2000:POSIX*:*:*)
+ echo bs2000-siemens-sysv
+ exit ;;
+ DS/*:UNIX_System_V:*:*)
+ echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
+ exit ;;
+ *:Plan9:*:*)
+ # "uname -m" is not consistent, so use $cputype instead. 386
+ # is converted to i386 for consistency with other x86
+ # operating systems.
+ if test "$cputype" = "386"; then
+ UNAME_MACHINE=i386
+ else
+ UNAME_MACHINE="$cputype"
+ fi
+ echo ${UNAME_MACHINE}-unknown-plan9
+ exit ;;
+ *:TOPS-10:*:*)
+ echo pdp10-unknown-tops10
+ exit ;;
+ *:TENEX:*:*)
+ echo pdp10-unknown-tenex
+ exit ;;
+ KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+ echo pdp10-dec-tops20
+ exit ;;
+ XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+ echo pdp10-xkl-tops20
+ exit ;;
+ *:TOPS-20:*:*)
+ echo pdp10-unknown-tops20
+ exit ;;
+ *:ITS:*:*)
+ echo pdp10-unknown-its
+ exit ;;
+ SEI:*:*:SEIUX)
+ echo mips-sei-seiux${UNAME_RELEASE}
+ exit ;;
+ *:DragonFly:*:*)
+ echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+ exit ;;
+ *:*VMS:*:*)
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ case "${UNAME_MACHINE}" in
+ A*) echo alpha-dec-vms ; exit ;;
+ I*) echo ia64-dec-vms ; exit ;;
+ V*) echo vax-dec-vms ; exit ;;
+ esac ;;
+ *:XENIX:*:SysV)
+ echo i386-pc-xenix
+ exit ;;
+ i*86:skyos:*:*)
+ echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//'
+ exit ;;
+ i*86:rdos:*:*)
+ echo ${UNAME_MACHINE}-pc-rdos
+ exit ;;
+ i*86:AROS:*:*)
+ echo ${UNAME_MACHINE}-pc-aros
+ exit ;;
+esac
+
+#echo '(No uname command or uname output not recognized.)' 1>&2
+#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
+
+eval $set_cc_for_build
+cat >$dummy.c <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+ /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed,
+ I don't know.... */
+ printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+ printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+ "4"
+#else
+ ""
+#endif
+ ); exit (0);
+#endif
+#endif
+
+#if defined (__arm) && defined (__acorn) && defined (__unix)
+ printf ("arm-acorn-riscix\n"); exit (0);
+#endif
+
+#if defined (hp300) && !defined (hpux)
+ printf ("m68k-hp-bsd\n"); exit (0);
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+ int version;
+ version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+ if (version < 4)
+ printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+ else
+ printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
+ exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+ printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+ printf ("ns32k-encore-mach\n"); exit (0);
+#else
+ printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+ printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+ printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+ printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+ struct utsname un;
+
+ uname(&un);
+
+ if (strncmp(un.version, "V2", 2) == 0) {
+ printf ("i386-sequent-ptx2\n"); exit (0);
+ }
+ if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+ printf ("i386-sequent-ptx1\n"); exit (0);
+ }
+ printf ("i386-sequent-ptx\n"); exit (0);
+
+#endif
+
+#if defined (vax)
+# if !defined (ultrix)
+# include <sys/param.h>
+# if defined (BSD)
+# if BSD == 43
+ printf ("vax-dec-bsd4.3\n"); exit (0);
+# else
+# if BSD == 199006
+ printf ("vax-dec-bsd4.3reno\n"); exit (0);
+# else
+ printf ("vax-dec-bsd\n"); exit (0);
+# endif
+# endif
+# else
+ printf ("vax-dec-bsd\n"); exit (0);
+# endif
+# else
+ printf ("vax-dec-ultrix\n"); exit (0);
+# endif
+#endif
+
+#if defined (alliant) && defined (i860)
+ printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+ exit (1);
+}
+EOF
+
+$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` &&
+ { echo "$SYSTEM_NAME"; exit; }
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; }
+
+# Convex versions that predate uname can use getsysinfo(1)
+
+if [ -x /usr/convex/getsysinfo ]
+then
+ case `getsysinfo -f cpu_type` in
+ c1*)
+ echo c1-convex-bsd
+ exit ;;
+ c2*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit ;;
+ c34*)
+ echo c34-convex-bsd
+ exit ;;
+ c38*)
+ echo c38-convex-bsd
+ exit ;;
+ c4*)
+ echo c4-convex-bsd
+ exit ;;
+ esac
+fi
+
+cat >&2 <<EOF
+$0: unable to guess system type
+
+This script, last modified $timestamp, has failed to recognize
+the operating system you are using. It is advised that you
+download the most up to date version of the config scripts from
+
+ http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
+and
+ http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
+
+If the version you run ($0) is already up to date, please
+send the following data and any information you think might be
+pertinent to <config-patches@gnu.org> in order to provide the needed
+information to handle your system.
+
+config.guess timestamp = $timestamp
+
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null`
+
+hostinfo = `(hostinfo) 2>/dev/null`
+/bin/universe = `(/bin/universe) 2>/dev/null`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null`
+/bin/arch = `(/bin/arch) 2>/dev/null`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
+
+UNAME_MACHINE = ${UNAME_MACHINE}
+UNAME_RELEASE = ${UNAME_RELEASE}
+UNAME_SYSTEM = ${UNAME_SYSTEM}
+UNAME_VERSION = ${UNAME_VERSION}
+EOF
+
+exit 1
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/config.sub b/config.sub
new file mode 100755
index 0000000..a39437d
--- /dev/null
+++ b/config.sub
@@ -0,0 +1,1686 @@
+#! /bin/sh
+# Configuration validation subroutine script.
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
+# Free Software Foundation, Inc.
+
+timestamp='2009-04-17'
+
+# This file is (in principle) common to ALL GNU software.
+# The presence of a machine in this file suggests that SOME GNU software
+# can handle that machine. It does not imply ALL GNU software can.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+# 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+
+# Please send patches to <config-patches@gnu.org>. Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support. The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION] CPU-MFR-OPSYS
+ $0 [OPTION] ALIAS
+
+Canonicalize a configuration name.
+
+Operation modes:
+ -h, --help print this help, then exit
+ -t, --time-stamp print date of last modification, then exit
+ -v, --version print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
+2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+ case $1 in
+ --time-stamp | --time* | -t )
+ echo "$timestamp" ; exit ;;
+ --version | -v )
+ echo "$version" ; exit ;;
+ --help | --h* | -h )
+ echo "$usage"; exit ;;
+ -- ) # Stop option processing
+ shift; break ;;
+ - ) # Use stdin as input.
+ break ;;
+ -* )
+ echo "$me: invalid option $1$help"
+ exit 1 ;;
+
+ *local*)
+ # First pass through any local machine types.
+ echo $1
+ exit ;;
+
+ * )
+ break ;;
+ esac
+done
+
+case $# in
+ 0) echo "$me: missing argument$help" >&2
+ exit 1;;
+ 1) ;;
+ *) echo "$me: too many arguments$help" >&2
+ exit 1;;
+esac
+
+# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
+# Here we must recognize all the valid KERNEL-OS combinations.
+maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
+case $maybe_os in
+ nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \
+ uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \
+ kopensolaris*-gnu* | \
+ storm-chaos* | os2-emx* | rtmk-nova*)
+ os=-$maybe_os
+ basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+ ;;
+ *)
+ basic_machine=`echo $1 | sed 's/-[^-]*$//'`
+ if [ $basic_machine != $1 ]
+ then os=`echo $1 | sed 's/.*-/-/'`
+ else os=; fi
+ ;;
+esac
+
+### Let's recognize common machines as not being operating systems so
+### that things like config.sub decstation-3100 work. We also
+### recognize some manufacturers as not being operating systems, so we
+### can provide default operating systems below.
+case $os in
+ -sun*os*)
+ # Prevent following clause from handling this invalid input.
+ ;;
+ -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
+ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
+ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
+ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
+ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
+ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
+ -apple | -axis | -knuth | -cray)
+ os=
+ basic_machine=$1
+ ;;
+ -sim | -cisco | -oki | -wec | -winbond)
+ os=
+ basic_machine=$1
+ ;;
+ -scout)
+ ;;
+ -wrs)
+ os=-vxworks
+ basic_machine=$1
+ ;;
+ -chorusos*)
+ os=-chorusos
+ basic_machine=$1
+ ;;
+ -chorusrdb)
+ os=-chorusrdb
+ basic_machine=$1
+ ;;
+ -hiux*)
+ os=-hiuxwe2
+ ;;
+ -sco6)
+ os=-sco5v6
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco5)
+ os=-sco3.2v5
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco4)
+ os=-sco3.2v4
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco3.2.[4-9]*)
+ os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco3.2v[4-9]*)
+ # Don't forget version if it is 3.2v4 or newer.
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco5v6*)
+ # Don't forget version if it is 3.2v4 or newer.
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco*)
+ os=-sco3.2v2
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -udk*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -isc)
+ os=-isc2.2
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -clix*)
+ basic_machine=clipper-intergraph
+ ;;
+ -isc*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -lynx*)
+ os=-lynxos
+ ;;
+ -ptx*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
+ ;;
+ -windowsnt*)
+ os=`echo $os | sed -e 's/windowsnt/winnt/'`
+ ;;
+ -psos*)
+ os=-psos
+ ;;
+ -mint | -mint[0-9]*)
+ basic_machine=m68k-atari
+ os=-mint
+ ;;
+esac
+
+# Decode aliases for certain CPU-COMPANY combinations.
+case $basic_machine in
+ # Recognize the basic CPU types without company name.
+ # Some are omitted here because they have special meanings below.
+ 1750a | 580 \
+ | a29k \
+ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
+ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
+ | am33_2.0 \
+ | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
+ | bfin \
+ | c4x | clipper \
+ | d10v | d30v | dlx | dsp16xx \
+ | fido | fr30 | frv \
+ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+ | i370 | i860 | i960 | ia64 \
+ | ip2k | iq2000 \
+ | lm32 \
+ | m32c | m32r | m32rle | m68000 | m68k | m88k \
+ | maxq | mb | microblaze | mcore | mep | metag \
+ | mips | mipsbe | mipseb | mipsel | mipsle \
+ | mips16 \
+ | mips64 | mips64el \
+ | mips64octeon | mips64octeonel \
+ | mips64orion | mips64orionel \
+ | mips64r5900 | mips64r5900el \
+ | mips64vr | mips64vrel \
+ | mips64vr4100 | mips64vr4100el \
+ | mips64vr4300 | mips64vr4300el \
+ | mips64vr5000 | mips64vr5000el \
+ | mips64vr5900 | mips64vr5900el \
+ | mipsisa32 | mipsisa32el \
+ | mipsisa32r2 | mipsisa32r2el \
+ | mipsisa64 | mipsisa64el \
+ | mipsisa64r2 | mipsisa64r2el \
+ | mipsisa64sb1 | mipsisa64sb1el \
+ | mipsisa64sr71k | mipsisa64sr71kel \
+ | mipstx39 | mipstx39el \
+ | mn10200 | mn10300 \
+ | moxie \
+ | mt \
+ | msp430 \
+ | nios | nios2 \
+ | ns16k | ns32k \
+ | or32 \
+ | pdp10 | pdp11 | pj | pjl \
+ | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
+ | pyramid \
+ | score \
+ | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
+ | sh64 | sh64le \
+ | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
+ | sparcv8 | sparcv9 | sparcv9b | sparcv9v \
+ | spu | strongarm \
+ | tahoe | thumb | tic4x | tic80 | tron \
+ | v850 | v850e \
+ | we32k \
+ | x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \
+ | z8k | z80)
+ basic_machine=$basic_machine-unknown
+ ;;
+ m6811 | m68hc11 | m6812 | m68hc12)
+ # Motorola 68HC11/12.
+ basic_machine=$basic_machine-unknown
+ os=-none
+ ;;
+ m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
+ ;;
+ ms1)
+ basic_machine=mt-unknown
+ ;;
+
+ # We use `pc' rather than `unknown'
+ # because (1) that's what they normally are, and
+ # (2) the word "unknown" tends to confuse beginning users.
+ i*86 | x86_64)
+ basic_machine=$basic_machine-pc
+ ;;
+ # Object if more than one company name word.
+ *-*-*)
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
+ ;;
+ # Recognize the basic CPU types with company name.
+ 580-* \
+ | a29k-* \
+ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
+ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
+ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
+ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \
+ | avr-* | avr32-* \
+ | bfin-* | bs2000-* \
+ | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
+ | clipper-* | craynv-* | cydra-* \
+ | d10v-* | d30v-* | dlx-* \
+ | elxsi-* \
+ | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
+ | h8300-* | h8500-* \
+ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+ | i*86-* | i860-* | i960-* | ia64-* \
+ | ip2k-* | iq2000-* \
+ | lm32-* \
+ | m32c-* | m32r-* | m32rle-* \
+ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
+ | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \
+ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
+ | mips16-* \
+ | mips64-* | mips64el-* \
+ | mips64octeon-* | mips64octeonel-* \
+ | mips64orion-* | mips64orionel-* \
+ | mips64r5900-* | mips64r5900el-* \
+ | mips64vr-* | mips64vrel-* \
+ | mips64vr4100-* | mips64vr4100el-* \
+ | mips64vr4300-* | mips64vr4300el-* \
+ | mips64vr5000-* | mips64vr5000el-* \
+ | mips64vr5900-* | mips64vr5900el-* \
+ | mipsisa32-* | mipsisa32el-* \
+ | mipsisa32r2-* | mipsisa32r2el-* \
+ | mipsisa64-* | mipsisa64el-* \
+ | mipsisa64r2-* | mipsisa64r2el-* \
+ | mipsisa64sb1-* | mipsisa64sb1el-* \
+ | mipsisa64sr71k-* | mipsisa64sr71kel-* \
+ | mipstx39-* | mipstx39el-* \
+ | mmix-* \
+ | mt-* \
+ | msp430-* \
+ | nios-* | nios2-* \
+ | none-* | np1-* | ns16k-* | ns32k-* \
+ | orion-* \
+ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
+ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
+ | pyramid-* \
+ | romp-* | rs6000-* \
+ | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
+ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
+ | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
+ | sparclite-* \
+ | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \
+ | tahoe-* | thumb-* \
+ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* | tile-* \
+ | tron-* \
+ | v850-* | v850e-* | vax-* \
+ | we32k-* \
+ | x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \
+ | xstormy16-* | xtensa*-* \
+ | ymp-* \
+ | z8k-* | z80-*)
+ ;;
+ # Recognize the basic CPU types without company name, with glob match.
+ xtensa*)
+ basic_machine=$basic_machine-unknown
+ ;;
+ # Recognize the various machine names and aliases which stand
+ # for a CPU type and a company and sometimes even an OS.
+ 386bsd)
+ basic_machine=i386-unknown
+ os=-bsd
+ ;;
+ 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+ basic_machine=m68000-att
+ ;;
+ 3b*)
+ basic_machine=we32k-att
+ ;;
+ a29khif)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ abacus)
+ basic_machine=abacus-unknown
+ ;;
+ adobe68k)
+ basic_machine=m68010-adobe
+ os=-scout
+ ;;
+ alliant | fx80)
+ basic_machine=fx80-alliant
+ ;;
+ altos | altos3068)
+ basic_machine=m68k-altos
+ ;;
+ am29k)
+ basic_machine=a29k-none
+ os=-bsd
+ ;;
+ amd64)
+ basic_machine=x86_64-pc
+ ;;
+ amd64-*)
+ basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ amdahl)
+ basic_machine=580-amdahl
+ os=-sysv
+ ;;
+ amiga | amiga-*)
+ basic_machine=m68k-unknown
+ ;;
+ amigaos | amigados)
+ basic_machine=m68k-unknown
+ os=-amigaos
+ ;;
+ amigaunix | amix)
+ basic_machine=m68k-unknown
+ os=-sysv4
+ ;;
+ apollo68)
+ basic_machine=m68k-apollo
+ os=-sysv
+ ;;
+ apollo68bsd)
+ basic_machine=m68k-apollo
+ os=-bsd
+ ;;
+ aros)
+ basic_machine=i386-pc
+ os=-aros
+ ;;
+ aux)
+ basic_machine=m68k-apple
+ os=-aux
+ ;;
+ balance)
+ basic_machine=ns32k-sequent
+ os=-dynix
+ ;;
+ blackfin)
+ basic_machine=bfin-unknown
+ os=-linux
+ ;;
+ blackfin-*)
+ basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'`
+ os=-linux
+ ;;
+ c90)
+ basic_machine=c90-cray
+ os=-unicos
+ ;;
+ cegcc)
+ basic_machine=arm-unknown
+ os=-cegcc
+ ;;
+ convex-c1)
+ basic_machine=c1-convex
+ os=-bsd
+ ;;
+ convex-c2)
+ basic_machine=c2-convex
+ os=-bsd
+ ;;
+ convex-c32)
+ basic_machine=c32-convex
+ os=-bsd
+ ;;
+ convex-c34)
+ basic_machine=c34-convex
+ os=-bsd
+ ;;
+ convex-c38)
+ basic_machine=c38-convex
+ os=-bsd
+ ;;
+ cray | j90)
+ basic_machine=j90-cray
+ os=-unicos
+ ;;
+ craynv)
+ basic_machine=craynv-cray
+ os=-unicosmp
+ ;;
+ cr16)
+ basic_machine=cr16-unknown
+ os=-elf
+ ;;
+ crds | unos)
+ basic_machine=m68k-crds
+ ;;
+ crisv32 | crisv32-* | etraxfs*)
+ basic_machine=crisv32-axis
+ ;;
+ cris | cris-* | etrax*)
+ basic_machine=cris-axis
+ ;;
+ crx)
+ basic_machine=crx-unknown
+ os=-elf
+ ;;
+ da30 | da30-*)
+ basic_machine=m68k-da30
+ ;;
+ decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
+ basic_machine=mips-dec
+ ;;
+ decsystem10* | dec10*)
+ basic_machine=pdp10-dec
+ os=-tops10
+ ;;
+ decsystem20* | dec20*)
+ basic_machine=pdp10-dec
+ os=-tops20
+ ;;
+ delta | 3300 | motorola-3300 | motorola-delta \
+ | 3300-motorola | delta-motorola)
+ basic_machine=m68k-motorola
+ ;;
+ delta88)
+ basic_machine=m88k-motorola
+ os=-sysv3
+ ;;
+ dicos)
+ basic_machine=i686-pc
+ os=-dicos
+ ;;
+ djgpp)
+ basic_machine=i586-pc
+ os=-msdosdjgpp
+ ;;
+ dpx20 | dpx20-*)
+ basic_machine=rs6000-bull
+ os=-bosx
+ ;;
+ dpx2* | dpx2*-bull)
+ basic_machine=m68k-bull
+ os=-sysv3
+ ;;
+ ebmon29k)
+ basic_machine=a29k-amd
+ os=-ebmon
+ ;;
+ elxsi)
+ basic_machine=elxsi-elxsi
+ os=-bsd
+ ;;
+ encore | umax | mmax)
+ basic_machine=ns32k-encore
+ ;;
+ es1800 | OSE68k | ose68k | ose | OSE)
+ basic_machine=m68k-ericsson
+ os=-ose
+ ;;
+ fx2800)
+ basic_machine=i860-alliant
+ ;;
+ genix)
+ basic_machine=ns32k-ns
+ ;;
+ gmicro)
+ basic_machine=tron-gmicro
+ os=-sysv
+ ;;
+ go32)
+ basic_machine=i386-pc
+ os=-go32
+ ;;
+ h3050r* | hiux*)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ h8300hms)
+ basic_machine=h8300-hitachi
+ os=-hms
+ ;;
+ h8300xray)
+ basic_machine=h8300-hitachi
+ os=-xray
+ ;;
+ h8500hms)
+ basic_machine=h8500-hitachi
+ os=-hms
+ ;;
+ harris)
+ basic_machine=m88k-harris
+ os=-sysv3
+ ;;
+ hp300-*)
+ basic_machine=m68k-hp
+ ;;
+ hp300bsd)
+ basic_machine=m68k-hp
+ os=-bsd
+ ;;
+ hp300hpux)
+ basic_machine=m68k-hp
+ os=-hpux
+ ;;
+ hp3k9[0-9][0-9] | hp9[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hp9k2[0-9][0-9] | hp9k31[0-9])
+ basic_machine=m68000-hp
+ ;;
+ hp9k3[2-9][0-9])
+ basic_machine=m68k-hp
+ ;;
+ hp9k6[0-9][0-9] | hp6[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hp9k7[0-79][0-9] | hp7[0-79][0-9])
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k78[0-9] | hp78[0-9])
+ # FIXME: really hppa2.0-hp
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
+ # FIXME: really hppa2.0-hp
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[0-9][13679] | hp8[0-9][13679])
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[0-9][0-9] | hp8[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hppa-next)
+ os=-nextstep3
+ ;;
+ hppaosf)
+ basic_machine=hppa1.1-hp
+ os=-osf
+ ;;
+ hppro)
+ basic_machine=hppa1.1-hp
+ os=-proelf
+ ;;
+ i370-ibm* | ibm*)
+ basic_machine=i370-ibm
+ ;;
+# I'm not sure what "Sysv32" means. Should this be sysv3.2?
+ i*86v32)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv32
+ ;;
+ i*86v4*)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv4
+ ;;
+ i*86v)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv
+ ;;
+ i*86sol2)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-solaris2
+ ;;
+ i386mach)
+ basic_machine=i386-mach
+ os=-mach
+ ;;
+ i386-vsta | vsta)
+ basic_machine=i386-unknown
+ os=-vsta
+ ;;
+ iris | iris4d)
+ basic_machine=mips-sgi
+ case $os in
+ -irix*)
+ ;;
+ *)
+ os=-irix4
+ ;;
+ esac
+ ;;
+ isi68 | isi)
+ basic_machine=m68k-isi
+ os=-sysv
+ ;;
+ m68knommu)
+ basic_machine=m68k-unknown
+ os=-linux
+ ;;
+ m68knommu-*)
+ basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'`
+ os=-linux
+ ;;
+ m88k-omron*)
+ basic_machine=m88k-omron
+ ;;
+ magnum | m3230)
+ basic_machine=mips-mips
+ os=-sysv
+ ;;
+ merlin)
+ basic_machine=ns32k-utek
+ os=-sysv
+ ;;
+ mingw32)
+ basic_machine=i386-pc
+ os=-mingw32
+ ;;
+ mingw32ce)
+ basic_machine=arm-unknown
+ os=-mingw32ce
+ ;;
+ miniframe)
+ basic_machine=m68000-convergent
+ ;;
+ *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
+ basic_machine=m68k-atari
+ os=-mint
+ ;;
+ mips3*-*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
+ ;;
+ mips3*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
+ ;;
+ monitor)
+ basic_machine=m68k-rom68k
+ os=-coff
+ ;;
+ morphos)
+ basic_machine=powerpc-unknown
+ os=-morphos
+ ;;
+ msdos)
+ basic_machine=i386-pc
+ os=-msdos
+ ;;
+ ms1-*)
+ basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
+ ;;
+ mvs)
+ basic_machine=i370-ibm
+ os=-mvs
+ ;;
+ ncr3000)
+ basic_machine=i486-ncr
+ os=-sysv4
+ ;;
+ netbsd386)
+ basic_machine=i386-unknown
+ os=-netbsd
+ ;;
+ netwinder)
+ basic_machine=armv4l-rebel
+ os=-linux
+ ;;
+ news | news700 | news800 | news900)
+ basic_machine=m68k-sony
+ os=-newsos
+ ;;
+ news1000)
+ basic_machine=m68030-sony
+ os=-newsos
+ ;;
+ news-3600 | risc-news)
+ basic_machine=mips-sony
+ os=-newsos
+ ;;
+ necv70)
+ basic_machine=v70-nec
+ os=-sysv
+ ;;
+ next | m*-next )
+ basic_machine=m68k-next
+ case $os in
+ -nextstep* )
+ ;;
+ -ns2*)
+ os=-nextstep2
+ ;;
+ *)
+ os=-nextstep3
+ ;;
+ esac
+ ;;
+ nh3000)
+ basic_machine=m68k-harris
+ os=-cxux
+ ;;
+ nh[45]000)
+ basic_machine=m88k-harris
+ os=-cxux
+ ;;
+ nindy960)
+ basic_machine=i960-intel
+ os=-nindy
+ ;;
+ mon960)
+ basic_machine=i960-intel
+ os=-mon960
+ ;;
+ nonstopux)
+ basic_machine=mips-compaq
+ os=-nonstopux
+ ;;
+ np1)
+ basic_machine=np1-gould
+ ;;
+ nsr-tandem)
+ basic_machine=nsr-tandem
+ ;;
+ op50n-* | op60c-*)
+ basic_machine=hppa1.1-oki
+ os=-proelf
+ ;;
+ openrisc | openrisc-*)
+ basic_machine=or32-unknown
+ ;;
+ os400)
+ basic_machine=powerpc-ibm
+ os=-os400
+ ;;
+ OSE68000 | ose68000)
+ basic_machine=m68000-ericsson
+ os=-ose
+ ;;
+ os68k)
+ basic_machine=m68k-none
+ os=-os68k
+ ;;
+ pa-hitachi)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ paragon)
+ basic_machine=i860-intel
+ os=-osf
+ ;;
+ parisc)
+ basic_machine=hppa-unknown
+ os=-linux
+ ;;
+ parisc-*)
+ basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'`
+ os=-linux
+ ;;
+ pbd)
+ basic_machine=sparc-tti
+ ;;
+ pbb)
+ basic_machine=m68k-tti
+ ;;
+ pc532 | pc532-*)
+ basic_machine=ns32k-pc532
+ ;;
+ pc98)
+ basic_machine=i386-pc
+ ;;
+ pc98-*)
+ basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentium | p5 | k5 | k6 | nexgen | viac3)
+ basic_machine=i586-pc
+ ;;
+ pentiumpro | p6 | 6x86 | athlon | athlon_*)
+ basic_machine=i686-pc
+ ;;
+ pentiumii | pentium2 | pentiumiii | pentium3)
+ basic_machine=i686-pc
+ ;;
+ pentium4)
+ basic_machine=i786-pc
+ ;;
+ pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
+ basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentiumpro-* | p6-* | 6x86-* | athlon-*)
+ basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
+ basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentium4-*)
+ basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pn)
+ basic_machine=pn-gould
+ ;;
+ power) basic_machine=power-ibm
+ ;;
+ ppc) basic_machine=powerpc-unknown
+ ;;
+ ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppcle | powerpclittle | ppc-le | powerpc-little)
+ basic_machine=powerpcle-unknown
+ ;;
+ ppcle-* | powerpclittle-*)
+ basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppc64) basic_machine=powerpc64-unknown
+ ;;
+ ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppc64le | powerpc64little | ppc64-le | powerpc64-little)
+ basic_machine=powerpc64le-unknown
+ ;;
+ ppc64le-* | powerpc64little-*)
+ basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ps2)
+ basic_machine=i386-ibm
+ ;;
+ pw32)
+ basic_machine=i586-unknown
+ os=-pw32
+ ;;
+ rdos)
+ basic_machine=i386-pc
+ os=-rdos
+ ;;
+ rom68k)
+ basic_machine=m68k-rom68k
+ os=-coff
+ ;;
+ rm[46]00)
+ basic_machine=mips-siemens
+ ;;
+ rtpc | rtpc-*)
+ basic_machine=romp-ibm
+ ;;
+ s390 | s390-*)
+ basic_machine=s390-ibm
+ ;;
+ s390x | s390x-*)
+ basic_machine=s390x-ibm
+ ;;
+ sa29200)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ sb1)
+ basic_machine=mipsisa64sb1-unknown
+ ;;
+ sb1el)
+ basic_machine=mipsisa64sb1el-unknown
+ ;;
+ sde)
+ basic_machine=mipsisa32-sde
+ os=-elf
+ ;;
+ sei)
+ basic_machine=mips-sei
+ os=-seiux
+ ;;
+ sequent)
+ basic_machine=i386-sequent
+ ;;
+ sh)
+ basic_machine=sh-hitachi
+ os=-hms
+ ;;
+ sh5el)
+ basic_machine=sh5le-unknown
+ ;;
+ sh64)
+ basic_machine=sh64-unknown
+ ;;
+ sparclite-wrs | simso-wrs)
+ basic_machine=sparclite-wrs
+ os=-vxworks
+ ;;
+ sps7)
+ basic_machine=m68k-bull
+ os=-sysv2
+ ;;
+ spur)
+ basic_machine=spur-unknown
+ ;;
+ st2000)
+ basic_machine=m68k-tandem
+ ;;
+ stratus)
+ basic_machine=i860-stratus
+ os=-sysv4
+ ;;
+ sun2)
+ basic_machine=m68000-sun
+ ;;
+ sun2os3)
+ basic_machine=m68000-sun
+ os=-sunos3
+ ;;
+ sun2os4)
+ basic_machine=m68000-sun
+ os=-sunos4
+ ;;
+ sun3os3)
+ basic_machine=m68k-sun
+ os=-sunos3
+ ;;
+ sun3os4)
+ basic_machine=m68k-sun
+ os=-sunos4
+ ;;
+ sun4os3)
+ basic_machine=sparc-sun
+ os=-sunos3
+ ;;
+ sun4os4)
+ basic_machine=sparc-sun
+ os=-sunos4
+ ;;
+ sun4sol2)
+ basic_machine=sparc-sun
+ os=-solaris2
+ ;;
+ sun3 | sun3-*)
+ basic_machine=m68k-sun
+ ;;
+ sun4)
+ basic_machine=sparc-sun
+ ;;
+ sun386 | sun386i | roadrunner)
+ basic_machine=i386-sun
+ ;;
+ sv1)
+ basic_machine=sv1-cray
+ os=-unicos
+ ;;
+ symmetry)
+ basic_machine=i386-sequent
+ os=-dynix
+ ;;
+ t3e)
+ basic_machine=alphaev5-cray
+ os=-unicos
+ ;;
+ t90)
+ basic_machine=t90-cray
+ os=-unicos
+ ;;
+ tic54x | c54x*)
+ basic_machine=tic54x-unknown
+ os=-coff
+ ;;
+ tic55x | c55x*)
+ basic_machine=tic55x-unknown
+ os=-coff
+ ;;
+ tic6x | c6x*)
+ basic_machine=tic6x-unknown
+ os=-coff
+ ;;
+ tile*)
+ basic_machine=tile-unknown
+ os=-linux-gnu
+ ;;
+ tx39)
+ basic_machine=mipstx39-unknown
+ ;;
+ tx39el)
+ basic_machine=mipstx39el-unknown
+ ;;
+ toad1)
+ basic_machine=pdp10-xkl
+ os=-tops20
+ ;;
+ tower | tower-32)
+ basic_machine=m68k-ncr
+ ;;
+ tpf)
+ basic_machine=s390x-ibm
+ os=-tpf
+ ;;
+ udi29k)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ ultra3)
+ basic_machine=a29k-nyu
+ os=-sym1
+ ;;
+ v810 | necv810)
+ basic_machine=v810-nec
+ os=-none
+ ;;
+ vaxv)
+ basic_machine=vax-dec
+ os=-sysv
+ ;;
+ vms)
+ basic_machine=vax-dec
+ os=-vms
+ ;;
+ vpp*|vx|vx-*)
+ basic_machine=f301-fujitsu
+ ;;
+ vxworks960)
+ basic_machine=i960-wrs
+ os=-vxworks
+ ;;
+ vxworks68)
+ basic_machine=m68k-wrs
+ os=-vxworks
+ ;;
+ vxworks29k)
+ basic_machine=a29k-wrs
+ os=-vxworks
+ ;;
+ w65*)
+ basic_machine=w65-wdc
+ os=-none
+ ;;
+ w89k-*)
+ basic_machine=hppa1.1-winbond
+ os=-proelf
+ ;;
+ xbox)
+ basic_machine=i686-pc
+ os=-mingw32
+ ;;
+ xps | xps100)
+ basic_machine=xps100-honeywell
+ ;;
+ ymp)
+ basic_machine=ymp-cray
+ os=-unicos
+ ;;
+ z8k-*-coff)
+ basic_machine=z8k-unknown
+ os=-sim
+ ;;
+ z80-*-coff)
+ basic_machine=z80-unknown
+ os=-sim
+ ;;
+ none)
+ basic_machine=none-none
+ os=-none
+ ;;
+
+# Here we handle the default manufacturer of certain CPU types. It is in
+# some cases the only manufacturer, in others, it is the most popular.
+ w89k)
+ basic_machine=hppa1.1-winbond
+ ;;
+ op50n)
+ basic_machine=hppa1.1-oki
+ ;;
+ op60c)
+ basic_machine=hppa1.1-oki
+ ;;
+ romp)
+ basic_machine=romp-ibm
+ ;;
+ mmix)
+ basic_machine=mmix-knuth
+ ;;
+ rs6000)
+ basic_machine=rs6000-ibm
+ ;;
+ vax)
+ basic_machine=vax-dec
+ ;;
+ pdp10)
+ # there are many clones, so DEC is not a safe bet
+ basic_machine=pdp10-unknown
+ ;;
+ pdp11)
+ basic_machine=pdp11-dec
+ ;;
+ we32k)
+ basic_machine=we32k-att
+ ;;
+ sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele)
+ basic_machine=sh-unknown
+ ;;
+ sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
+ basic_machine=sparc-sun
+ ;;
+ cydra)
+ basic_machine=cydra-cydrome
+ ;;
+ orion)
+ basic_machine=orion-highlevel
+ ;;
+ orion105)
+ basic_machine=clipper-highlevel
+ ;;
+ mac | mpw | mac-mpw)
+ basic_machine=m68k-apple
+ ;;
+ pmac | pmac-mpw)
+ basic_machine=powerpc-apple
+ ;;
+ *-unknown)
+ # Make sure to match an already-canonicalized machine name.
+ ;;
+ *)
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $basic_machine in
+ *-digital*)
+ basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
+ ;;
+ *-commodore*)
+ basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
+ ;;
+ *)
+ ;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if [ x"$os" != x"" ]
+then
+case $os in
+ # First match some system type aliases
+ # that might get confused with valid system types.
+ # -solaris* is a basic system type, with this one exception.
+ -solaris1 | -solaris1.*)
+ os=`echo $os | sed -e 's|solaris1|sunos4|'`
+ ;;
+ -solaris)
+ os=-solaris2
+ ;;
+ -svr4*)
+ os=-sysv4
+ ;;
+ -unixware*)
+ os=-sysv4.2uw
+ ;;
+ -gnu/linux*)
+ os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
+ ;;
+ # First accept the basic system types.
+ # The portable systems comes first.
+ # Each alternative MUST END IN A *, to match a version number.
+ # -sysv* is not here because it comes later, after sysvr4.
+ -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
+ | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
+ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
+ | -kopensolaris* \
+ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+ | -aos* | -aros* \
+ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
+ | -openbsd* | -solidbsd* \
+ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
+ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+ | -chorusos* | -chorusrdb* | -cegcc* \
+ | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+ | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \
+ | -uxpv* | -beos* | -mpeix* | -udk* \
+ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
+ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
+ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
+ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
+ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
+ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
+ | -skyos* | -haiku* | -rdos* | -toppers* | -drops*)
+ # Remember, each alternative MUST END IN *, to match a version number.
+ ;;
+ -qnx*)
+ case $basic_machine in
+ x86-* | i*86-*)
+ ;;
+ *)
+ os=-nto$os
+ ;;
+ esac
+ ;;
+ -nto-qnx*)
+ ;;
+ -nto*)
+ os=`echo $os | sed -e 's|nto|nto-qnx|'`
+ ;;
+ -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
+ | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \
+ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
+ ;;
+ -mac*)
+ os=`echo $os | sed -e 's|mac|macos|'`
+ ;;
+ -linux-dietlibc)
+ os=-linux-dietlibc
+ ;;
+ -linux*)
+ os=`echo $os | sed -e 's|linux|linux-gnu|'`
+ ;;
+ -sunos5*)
+ os=`echo $os | sed -e 's|sunos5|solaris2|'`
+ ;;
+ -sunos6*)
+ os=`echo $os | sed -e 's|sunos6|solaris3|'`
+ ;;
+ -opened*)
+ os=-openedition
+ ;;
+ -os400*)
+ os=-os400
+ ;;
+ -wince*)
+ os=-wince
+ ;;
+ -osfrose*)
+ os=-osfrose
+ ;;
+ -osf*)
+ os=-osf
+ ;;
+ -utek*)
+ os=-bsd
+ ;;
+ -dynix*)
+ os=-bsd
+ ;;
+ -acis*)
+ os=-aos
+ ;;
+ -atheos*)
+ os=-atheos
+ ;;
+ -syllable*)
+ os=-syllable
+ ;;
+ -386bsd)
+ os=-bsd
+ ;;
+ -ctix* | -uts*)
+ os=-sysv
+ ;;
+ -nova*)
+ os=-rtmk-nova
+ ;;
+ -ns2 )
+ os=-nextstep2
+ ;;
+ -nsk*)
+ os=-nsk
+ ;;
+ # Preserve the version number of sinix5.
+ -sinix5.*)
+ os=`echo $os | sed -e 's|sinix|sysv|'`
+ ;;
+ -sinix*)
+ os=-sysv4
+ ;;
+ -tpf*)
+ os=-tpf
+ ;;
+ -triton*)
+ os=-sysv3
+ ;;
+ -oss*)
+ os=-sysv3
+ ;;
+ -svr4)
+ os=-sysv4
+ ;;
+ -svr3)
+ os=-sysv3
+ ;;
+ -sysvr4)
+ os=-sysv4
+ ;;
+ # This must come after -sysvr4.
+ -sysv*)
+ ;;
+ -ose*)
+ os=-ose
+ ;;
+ -es1800*)
+ os=-ose
+ ;;
+ -xenix)
+ os=-xenix
+ ;;
+ -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+ os=-mint
+ ;;
+ -aros*)
+ os=-aros
+ ;;
+ -kaos*)
+ os=-kaos
+ ;;
+ -zvmoe)
+ os=-zvmoe
+ ;;
+ -dicos*)
+ os=-dicos
+ ;;
+ -none)
+ ;;
+ *)
+ # Get rid of the `-' at the beginning of $os.
+ os=`echo $os | sed 's/[^-]*-//'`
+ echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+else
+
+# Here we handle the default operating systems that come with various machines.
+# The value should be what the vendor currently ships out the door with their
+# machine or put another way, the most popular os provided with the machine.
+
+# Note that if you're going to try to match "-MANUFACTURER" here (say,
+# "-sun"), then you have to tell the case statement up towards the top
+# that MANUFACTURER isn't an operating system. Otherwise, code above
+# will signal an error saying that MANUFACTURER isn't an operating
+# system, and we'll never get to this point.
+
+case $basic_machine in
+ score-*)
+ os=-elf
+ ;;
+ spu-*)
+ os=-elf
+ ;;
+ *-acorn)
+ os=-riscix1.2
+ ;;
+ arm*-rebel)
+ os=-linux
+ ;;
+ arm*-semi)
+ os=-aout
+ ;;
+ c4x-* | tic4x-*)
+ os=-coff
+ ;;
+ # This must come before the *-dec entry.
+ pdp10-*)
+ os=-tops20
+ ;;
+ pdp11-*)
+ os=-none
+ ;;
+ *-dec | vax-*)
+ os=-ultrix4.2
+ ;;
+ m68*-apollo)
+ os=-domain
+ ;;
+ i386-sun)
+ os=-sunos4.0.2
+ ;;
+ m68000-sun)
+ os=-sunos3
+ # This also exists in the configure program, but was not the
+ # default.
+ # os=-sunos4
+ ;;
+ m68*-cisco)
+ os=-aout
+ ;;
+ mep-*)
+ os=-elf
+ ;;
+ mips*-cisco)
+ os=-elf
+ ;;
+ mips*-*)
+ os=-elf
+ ;;
+ or32-*)
+ os=-coff
+ ;;
+ *-tti) # must be before sparc entry or we get the wrong os.
+ os=-sysv3
+ ;;
+ sparc-* | *-sun)
+ os=-sunos4.1.1
+ ;;
+ *-be)
+ os=-beos
+ ;;
+ *-haiku)
+ os=-haiku
+ ;;
+ *-ibm)
+ os=-aix
+ ;;
+ *-knuth)
+ os=-mmixware
+ ;;
+ *-wec)
+ os=-proelf
+ ;;
+ *-winbond)
+ os=-proelf
+ ;;
+ *-oki)
+ os=-proelf
+ ;;
+ *-hp)
+ os=-hpux
+ ;;
+ *-hitachi)
+ os=-hiux
+ ;;
+ i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+ os=-sysv
+ ;;
+ *-cbm)
+ os=-amigaos
+ ;;
+ *-dg)
+ os=-dgux
+ ;;
+ *-dolphin)
+ os=-sysv3
+ ;;
+ m68k-ccur)
+ os=-rtu
+ ;;
+ m88k-omron*)
+ os=-luna
+ ;;
+ *-next )
+ os=-nextstep
+ ;;
+ *-sequent)
+ os=-ptx
+ ;;
+ *-crds)
+ os=-unos
+ ;;
+ *-ns)
+ os=-genix
+ ;;
+ i370-*)
+ os=-mvs
+ ;;
+ *-next)
+ os=-nextstep3
+ ;;
+ *-gould)
+ os=-sysv
+ ;;
+ *-highlevel)
+ os=-bsd
+ ;;
+ *-encore)
+ os=-bsd
+ ;;
+ *-sgi)
+ os=-irix
+ ;;
+ *-siemens)
+ os=-sysv4
+ ;;
+ *-masscomp)
+ os=-rtu
+ ;;
+ f30[01]-fujitsu | f700-fujitsu)
+ os=-uxpv
+ ;;
+ *-rom68k)
+ os=-coff
+ ;;
+ *-*bug)
+ os=-coff
+ ;;
+ *-apple)
+ os=-macos
+ ;;
+ *-atari*)
+ os=-mint
+ ;;
+ *)
+ os=-none
+ ;;
+esac
+fi
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer. We pick the logical manufacturer.
+vendor=unknown
+case $basic_machine in
+ *-unknown)
+ case $os in
+ -riscix*)
+ vendor=acorn
+ ;;
+ -sunos*)
+ vendor=sun
+ ;;
+ -aix*)
+ vendor=ibm
+ ;;
+ -beos*)
+ vendor=be
+ ;;
+ -hpux*)
+ vendor=hp
+ ;;
+ -mpeix*)
+ vendor=hp
+ ;;
+ -hiux*)
+ vendor=hitachi
+ ;;
+ -unos*)
+ vendor=crds
+ ;;
+ -dgux*)
+ vendor=dg
+ ;;
+ -luna*)
+ vendor=omron
+ ;;
+ -genix*)
+ vendor=ns
+ ;;
+ -mvs* | -opened*)
+ vendor=ibm
+ ;;
+ -os400*)
+ vendor=ibm
+ ;;
+ -ptx*)
+ vendor=sequent
+ ;;
+ -tpf*)
+ vendor=ibm
+ ;;
+ -vxsim* | -vxworks* | -windiss*)
+ vendor=wrs
+ ;;
+ -aux*)
+ vendor=apple
+ ;;
+ -hms*)
+ vendor=hitachi
+ ;;
+ -mpw* | -macos*)
+ vendor=apple
+ ;;
+ -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+ vendor=atari
+ ;;
+ -vos*)
+ vendor=stratus
+ ;;
+ esac
+ basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
+ ;;
+esac
+
+echo $basic_machine$os
+exit
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/configure b/configure
new file mode 100755
index 0000000..d543cd9
--- /dev/null
+++ b/configure
@@ -0,0 +1,13760 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.64 for Phidget21 C Library 2.1.8.20120216.
+#
+# Report bugs to <support@phidgets.com>.
+#
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
+# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software
+# Foundation, Inc.
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='print -r --'
+ as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='printf %s\n'
+ as_echo_n='printf %s'
+else
+ if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+ as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+ as_echo_n='/usr/ucb/echo -n'
+ else
+ as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+ as_echo_n_body='eval
+ arg=$1;
+ case $arg in #(
+ *"$as_nl"*)
+ expr "X$arg" : "X\\(.*\\)$as_nl";
+ arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+ esac;
+ expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+ '
+ export as_echo_n_body
+ as_echo_n='sh -c $as_echo_n_body as_echo'
+ fi
+ export as_echo_body
+ as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ PATH_SEPARATOR=:
+ (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+ (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+ PATH_SEPARATOR=';'
+ }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+case $0 in #((
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there. '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+if test "x$CONFIG_SHELL" = x; then
+ as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '\${1+\"\$@\"}'='\"\$@\"'
+ setopt NO_GLOB_SUBST
+else
+ case \`(set -o) 2>/dev/null\` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+"
+ as_required="as_fn_return () { (exit \$1); }
+as_fn_success () { as_fn_return 0; }
+as_fn_failure () { as_fn_return 1; }
+as_fn_ret_success () { return 0; }
+as_fn_ret_failure () { return 1; }
+
+exitcode=0
+as_fn_success || { exitcode=1; echo as_fn_success failed.; }
+as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
+as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
+as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
+if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
+
+else
+ exitcode=1; echo positional parameters were not saved.
+fi
+test x\$exitcode = x0 || exit 1"
+ as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
+ as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
+ eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
+ test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1
+test \$(( 1 + 1 )) = 2 || exit 1"
+ if (eval "$as_required") 2>/dev/null; then :
+ as_have_required=yes
+else
+ as_have_required=no
+fi
+ if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then :
+
+else
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_found=false
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ as_found=:
+ case $as_dir in #(
+ /*)
+ for as_base in sh bash ksh sh5; do
+ # Try only shells that exist, to save several forks.
+ as_shell=$as_dir/$as_base
+ if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+ { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ CONFIG_SHELL=$as_shell as_have_required=yes
+ if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ break 2
+fi
+fi
+ done;;
+ esac
+ as_found=false
+done
+$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
+ { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then :
+ CONFIG_SHELL=$SHELL as_have_required=yes
+fi; }
+IFS=$as_save_IFS
+
+
+ if test "x$CONFIG_SHELL" != x; then :
+ # We cannot yet assume a decent shell, so we have to provide a
+ # neutralization value for shells without unset; and this also
+ # works around shells that cannot unset nonexistent variables.
+ BASH_ENV=/dev/null
+ ENV=/dev/null
+ (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+ export CONFIG_SHELL
+ exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"}
+fi
+
+ if test x$as_have_required = xno; then :
+ $as_echo "$0: This script requires a shell more modern than all"
+ $as_echo "$0: the shells that I found on your system."
+ if test x${ZSH_VERSION+set} = xset ; then
+ $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
+ $as_echo "$0: be upgraded to zsh 4.3.4 or later."
+ else
+ $as_echo "$0: Please tell bug-autoconf@gnu.org and
+$0: support@phidgets.com about your system, including any
+$0: error possibly output before this message. Then install
+$0: a modern shell, or manually run the script under such a
+$0: shell if you do have one."
+ fi
+ exit 1
+fi
+fi
+fi
+SHELL=${CONFIG_SHELL-/bin/sh}
+export SHELL
+# Unset more variables known to interfere with behavior of common tools.
+CLICOLOR_FORCE= GREP_OPTIONS=
+unset CLICOLOR_FORCE GREP_OPTIONS
+
+## --------------------- ##
+## M4sh Shell Functions. ##
+## --------------------- ##
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+ { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+ return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+ set +e
+ as_fn_set_status $1
+ exit $1
+} # as_fn_exit
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || eval $as_mkdir_p || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || as_fn_error "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+ eval 'as_fn_append ()
+ {
+ eval $1+=\$2
+ }'
+else
+ as_fn_append ()
+ {
+ eval $1=\$$1\$2
+ }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+ eval 'as_fn_arith ()
+ {
+ as_val=$(( $* ))
+ }'
+else
+ as_fn_arith ()
+ {
+ as_val=`expr "$@" || test $? -eq 1`
+ }
+fi # as_fn_arith
+
+
+# as_fn_error ERROR [LINENO LOG_FD]
+# ---------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with status $?, using 1 if that was 0.
+as_fn_error ()
+{
+ as_status=$?; test $as_status -eq 0 && as_status=1
+ if test "$3"; then
+ as_lineno=${as_lineno-"$2"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ $as_echo "$as_me:${as_lineno-$LINENO}: error: $1" >&$3
+ fi
+ $as_echo "$as_me: error: $1" >&2
+ as_fn_exit $as_status
+} # as_fn_error
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+
+ as_lineno_1=$LINENO as_lineno_1a=$LINENO
+ as_lineno_2=$LINENO as_lineno_2a=$LINENO
+ eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" &&
+ test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {
+ # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-)
+ sed -n '
+ p
+ /[$]LINENO/=
+ ' <$as_myself |
+ sed '
+ s/[$]LINENO.*/&-/
+ t lineno
+ b
+ :lineno
+ N
+ :loop
+ s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+ t loop
+ s/-\n.*//
+ ' >$as_me.lineno &&
+ chmod +x "$as_me.lineno" ||
+ { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
+
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensitive to this).
+ . "./$as_me.lineno"
+ # Exit status is that of the last command.
+ exit
+}
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+ case `echo 'xy\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ xy) ECHO_C='\c';;
+ *) echo `echo ksh88 bug on AIX 6.1` > /dev/null
+ ECHO_T=' ';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+ if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -p'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -p'
+ elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+ else
+ as_ln_s='cp -p'
+ fi
+else
+ as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p='mkdir -p "$as_dir"'
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+ as_test_x='test -x'
+else
+ if ls -dL / >/dev/null 2>&1; then
+ as_ls_L_option=L
+ else
+ as_ls_L_option=
+ fi
+ as_test_x='
+ eval sh -c '\''
+ if test -d "$1"; then
+ test -d "$1/.";
+ else
+ case $1 in #(
+ -*)set "./$1";;
+ esac;
+ case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #((
+ ???[sx]*):;;*)false;;esac;fi
+ '\'' sh
+ '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+
+# Check that we are running under the correct shell.
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+case X$lt_ECHO in
+X*--fallback-echo)
+ # Remove one level of quotation (which was required for Make).
+ ECHO=`echo "$lt_ECHO" | sed 's,\\\\\$\\$0,'$0','`
+ ;;
+esac
+
+ECHO=${lt_ECHO-echo}
+if test "X$1" = X--no-reexec; then
+ # Discard the --no-reexec flag, and continue.
+ shift
+elif test "X$1" = X--fallback-echo; then
+ # Avoid inline document here, it may be left over
+ :
+elif test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' ; then
+ # Yippee, $ECHO works!
+ :
+else
+ # Restart under the correct shell.
+ exec $SHELL "$0" --no-reexec ${1+"$@"}
+fi
+
+if test "X$1" = X--fallback-echo; then
+ # used as fallback echo
+ shift
+ cat <<_LT_EOF
+$*
+_LT_EOF
+ exit 0
+fi
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+if test -z "$lt_ECHO"; then
+ if test "X${echo_test_string+set}" != Xset; then
+ # find a string as large as possible, as long as the shell can cope with it
+ for cmd in 'sed 50q "$0"' 'sed 20q "$0"' 'sed 10q "$0"' 'sed 2q "$0"' 'echo test'; do
+ # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ...
+ if { echo_test_string=`eval $cmd`; } 2>/dev/null &&
+ { test "X$echo_test_string" = "X$echo_test_string"; } 2>/dev/null
+ then
+ break
+ fi
+ done
+ fi
+
+ if test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' &&
+ echo_testing_string=`{ $ECHO "$echo_test_string"; } 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ :
+ else
+ # The Solaris, AIX, and Digital Unix default echo programs unquote
+ # backslashes. This makes it impossible to quote backslashes using
+ # echo "$something" | sed 's/\\/\\\\/g'
+ #
+ # So, first we look for a working echo in the user's PATH.
+
+ lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+ for dir in $PATH /usr/ucb; do
+ IFS="$lt_save_ifs"
+ if (test -f $dir/echo || test -f $dir/echo$ac_exeext) &&
+ test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' &&
+ echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ ECHO="$dir/echo"
+ break
+ fi
+ done
+ IFS="$lt_save_ifs"
+
+ if test "X$ECHO" = Xecho; then
+ # We didn't find a better echo, so look for alternatives.
+ if test "X`{ print -r '\t'; } 2>/dev/null`" = 'X\t' &&
+ echo_testing_string=`{ print -r "$echo_test_string"; } 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ # This shell has a builtin print -r that does the trick.
+ ECHO='print -r'
+ elif { test -f /bin/ksh || test -f /bin/ksh$ac_exeext; } &&
+ test "X$CONFIG_SHELL" != X/bin/ksh; then
+ # If we have ksh, try running configure again with it.
+ ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh}
+ export ORIGINAL_CONFIG_SHELL
+ CONFIG_SHELL=/bin/ksh
+ export CONFIG_SHELL
+ exec $CONFIG_SHELL "$0" --no-reexec ${1+"$@"}
+ else
+ # Try using printf.
+ ECHO='printf %s\n'
+ if test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' &&
+ echo_testing_string=`{ $ECHO "$echo_test_string"; } 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ # Cool, printf works
+ :
+ elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` &&
+ test "X$echo_testing_string" = 'X\t' &&
+ echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL
+ export CONFIG_SHELL
+ SHELL="$CONFIG_SHELL"
+ export SHELL
+ ECHO="$CONFIG_SHELL $0 --fallback-echo"
+ elif echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` &&
+ test "X$echo_testing_string" = 'X\t' &&
+ echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ ECHO="$CONFIG_SHELL $0 --fallback-echo"
+ else
+ # maybe with a smaller string...
+ prev=:
+
+ for cmd in 'echo test' 'sed 2q "$0"' 'sed 10q "$0"' 'sed 20q "$0"' 'sed 50q "$0"'; do
+ if { test "X$echo_test_string" = "X`eval $cmd`"; } 2>/dev/null
+ then
+ break
+ fi
+ prev="$cmd"
+ done
+
+ if test "$prev" != 'sed 50q "$0"'; then
+ echo_test_string=`eval $prev`
+ export echo_test_string
+ exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "$0" ${1+"$@"}
+ else
+ # Oops. We lost completely, so just stick with echo.
+ ECHO=echo
+ fi
+ fi
+ fi
+ fi
+ fi
+fi
+
+# Copy echo and quote the copy suitably for passing to libtool from
+# the Makefile, instead of quoting the original, which is used later.
+lt_ECHO=$ECHO
+if test "X$lt_ECHO" = "X$CONFIG_SHELL $0 --fallback-echo"; then
+ lt_ECHO="$CONFIG_SHELL \\\$\$0 --fallback-echo"
+fi
+
+
+
+
+exec 7<&0 </dev/null 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_clean_files=
+ac_config_libobj_dir=.
+LIBOBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+
+# Identity of this package.
+PACKAGE_NAME='Phidget21 C Library'
+PACKAGE_TARNAME='libphidget'
+PACKAGE_VERSION='2.1.8.20120216'
+PACKAGE_STRING='Phidget21 C Library 2.1.8.20120216'
+PACKAGE_BUGREPORT='support@phidgets.com'
+PACKAGE_URL='www.phidgets.com'
+
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+# endif
+#endif
+#ifdef HAVE_STRING_H
+# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+# include <memory.h>
+# endif
+# include <string.h>
+#endif
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+ac_unique_file="cphidgetir.h"
+ac_default_prefix=/usr
+ac_subst_vars='am__EXEEXT_FALSE
+am__EXEEXT_TRUE
+LTLIBOBJS
+LIBOBJS
+INTERNAL_UNICONV_FALSE
+INTERNAL_UNICONV_TRUE
+RUN_LDCONFIG_FALSE
+RUN_LDCONFIG_TRUE
+LABVIEW_FALSE
+LABVIEW_TRUE
+ZEROCONF_LOOKUP_FALSE
+ZEROCONF_LOOKUP_TRUE
+ZEROCONF_FALSE
+ZEROCONF_TRUE
+ZEROCONF_BONJOUR_FALSE
+ZEROCONF_BONJOUR_TRUE
+ZEROCONF_AVAHI_FALSE
+ZEROCONF_AVAHI_TRUE
+DEBUG_FALSE
+DEBUG_TRUE
+JNI_FALSE
+JNI_TRUE
+LDCONFIG
+AM_BACKSLASH
+AM_DEFAULT_VERBOSITY
+CPP
+OTOOL64
+OTOOL
+LIPO
+NMEDIT
+DSYMUTIL
+lt_ECHO
+RANLIB
+AR
+OBJDUMP
+LN_S
+NM
+ac_ct_DUMPBIN
+DUMPBIN
+LD
+FGREP
+EGREP
+GREP
+SED
+am__fastdepCC_FALSE
+am__fastdepCC_TRUE
+CCDEPMODE
+AMDEPBACKSLASH
+AMDEP_FALSE
+AMDEP_TRUE
+am__quote
+am__include
+DEPDIR
+OBJEXT
+EXEEXT
+ac_ct_CC
+CPPFLAGS
+LDFLAGS
+CFLAGS
+CC
+host_os
+host_vendor
+host_cpu
+host
+build_os
+build_vendor
+build_cpu
+build
+LIBTOOL
+am__untar
+am__tar
+AMTAR
+am__leading_dot
+SET_MAKE
+AWK
+mkdir_p
+MKDIR_P
+INSTALL_STRIP_PROGRAM
+STRIP
+install_sh
+MAKEINFO
+AUTOHEADER
+AUTOMAKE
+AUTOCONF
+ACLOCAL
+VERSION
+PACKAGE
+CYGPATH_W
+am__isrc
+INSTALL_DATA
+INSTALL_SCRIPT
+INSTALL_PROGRAM
+target_alias
+host_alias
+build_alias
+LIBS
+ECHO_T
+ECHO_N
+ECHO_C
+DEFS
+mandir
+localedir
+libdir
+psdir
+pdfdir
+dvidir
+htmldir
+infodir
+docdir
+oldincludedir
+includedir
+localstatedir
+sharedstatedir
+sysconfdir
+datadir
+datarootdir
+libexecdir
+sbindir
+bindir
+program_transform_name
+prefix
+exec_prefix
+PACKAGE_URL
+PACKAGE_BUGREPORT
+PACKAGE_STRING
+PACKAGE_VERSION
+PACKAGE_TARNAME
+PACKAGE_NAME
+PATH_SEPARATOR
+SHELL'
+ac_subst_files=''
+ac_user_opts='
+enable_option_checking
+enable_shared
+enable_static
+with_pic
+enable_fast_install
+enable_dependency_tracking
+with_gnu_ld
+enable_libtool_lock
+enable_silent_rules
+enable_jni
+enable_debug
+enable_zeroconf
+enable_zeroconf_lookup
+enable_labview
+enable_ldconfig
+'
+ ac_precious_vars='build_alias
+host_alias
+target_alias
+CC
+CFLAGS
+LDFLAGS
+LIBS
+CPPFLAGS
+CPP
+LDCONFIG'
+
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+ac_unrecognized_opts=
+ac_unrecognized_sep=
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
+
+ac_prev=
+ac_dashdash=
+for ac_option
+do
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval $ac_prev=\$ac_option
+ ac_prev=
+ continue
+ fi
+
+ case $ac_option in
+ *=*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+ *) ac_optarg=yes ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case $ac_dashdash$ac_option in
+ --)
+ ac_dashdash=yes ;;
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir=$ac_optarg ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build_alias ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build_alias=$ac_optarg ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file=$ac_optarg ;;
+
+ --config-cache | -C)
+ cache_file=config.cache ;;
+
+ -datadir | --datadir | --datadi | --datad)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=*)
+ datadir=$ac_optarg ;;
+
+ -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+ | --dataroo | --dataro | --datar)
+ ac_prev=datarootdir ;;
+ -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+ datarootdir=$ac_optarg ;;
+
+ -disable-* | --disable-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error "invalid feature name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"enable_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval enable_$ac_useropt=no ;;
+
+ -docdir | --docdir | --docdi | --doc | --do)
+ ac_prev=docdir ;;
+ -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+ docdir=$ac_optarg ;;
+
+ -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+ ac_prev=dvidir ;;
+ -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+ dvidir=$ac_optarg ;;
+
+ -enable-* | --enable-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error "invalid feature name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"enable_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval enable_$ac_useropt=\$ac_optarg ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix=$ac_optarg ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he | -h)
+ ac_init_help=long ;;
+ -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+ ac_init_help=recursive ;;
+ -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+ ac_init_help=short ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host_alias ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host_alias=$ac_optarg ;;
+
+ -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+ ac_prev=htmldir ;;
+ -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+ | --ht=*)
+ htmldir=$ac_optarg ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir=$ac_optarg ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir=$ac_optarg ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir=$ac_optarg ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir=$ac_optarg ;;
+
+ -localedir | --localedir | --localedi | --localed | --locale)
+ ac_prev=localedir ;;
+ -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+ localedir=$ac_optarg ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst | --locals)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+ localstatedir=$ac_optarg ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir=$ac_optarg ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c | -n)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir=$ac_optarg ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix=$ac_optarg ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix=$ac_optarg ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix=$ac_optarg ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name=$ac_optarg ;;
+
+ -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+ ac_prev=pdfdir ;;
+ -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+ pdfdir=$ac_optarg ;;
+
+ -psdir | --psdir | --psdi | --psd | --ps)
+ ac_prev=psdir ;;
+ -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+ psdir=$ac_optarg ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir=$ac_optarg ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir=$ac_optarg ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site=$ac_optarg ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir=$ac_optarg ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir=$ac_optarg ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target_alias ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target_alias=$ac_optarg ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers | -V)
+ ac_init_version=: ;;
+
+ -with-* | --with-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error "invalid package name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"with_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval with_$ac_useropt=\$ac_optarg ;;
+
+ -without-* | --without-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error "invalid package name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"with_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval with_$ac_useropt=no ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes=$ac_optarg ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries=$ac_optarg ;;
+
+ -*) as_fn_error "unrecognized option: \`$ac_option'
+Try \`$0 --help' for more information."
+ ;;
+
+ *=*)
+ ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+ # Reject names that are not valid shell variable names.
+ case $ac_envvar in #(
+ '' | [0-9]* | *[!_$as_cr_alnum]* )
+ as_fn_error "invalid variable name: \`$ac_envvar'" ;;
+ esac
+ eval $ac_envvar=\$ac_optarg
+ export $ac_envvar ;;
+
+ *)
+ # FIXME: should be removed in autoconf 3.0.
+ $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+ expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+ : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+ as_fn_error "missing argument to $ac_option"
+fi
+
+if test -n "$ac_unrecognized_opts"; then
+ case $enable_option_checking in
+ no) ;;
+ fatal) as_fn_error "unrecognized options: $ac_unrecognized_opts" ;;
+ *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
+ esac
+fi
+
+# Check all directory arguments for consistency.
+for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
+ datadir sysconfdir sharedstatedir localstatedir includedir \
+ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+ libdir localedir mandir
+do
+ eval ac_val=\$$ac_var
+ # Remove trailing slashes.
+ case $ac_val in
+ */ )
+ ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`
+ eval $ac_var=\$ac_val;;
+ esac
+ # Be sure to have absolute directory names.
+ case $ac_val in
+ [\\/$]* | ?:[\\/]* ) continue;;
+ NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+ esac
+ as_fn_error "expected an absolute directory name for --$ac_var: $ac_val"
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+ if test "x$build_alias" = x; then
+ cross_compiling=maybe
+ $as_echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host.
+ If a cross compiler is detected then cross compile mode will be used." >&2
+ elif test "x$build_alias" != "x$host_alias"; then
+ cross_compiling=yes
+ fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+ as_fn_error "working directory cannot be determined"
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+ as_fn_error "pwd does not report name of working directory"
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then the parent directory.
+ ac_confdir=`$as_dirname -- "$as_myself" ||
+$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_myself" : 'X\(//\)[^/]' \| \
+ X"$as_myself" : 'X\(//\)$' \| \
+ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_myself" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ srcdir=$ac_confdir
+ if test ! -r "$srcdir/$ac_unique_file"; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r "$srcdir/$ac_unique_file"; then
+ test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+ as_fn_error "cannot find sources ($ac_unique_file) in $srcdir"
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+ cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error "$ac_msg"
+ pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+ srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+ eval ac_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_env_${ac_var}_value=\$${ac_var}
+ eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat <<_ACEOF
+\`configure' configures Phidget21 C Library 2.1.8.20120216 to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE. See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+ -h, --help display this help and exit
+ --help=short display options specific to this package
+ --help=recursive display the short help of all the included packages
+ -V, --version display version information and exit
+ -q, --quiet, --silent do not print \`checking...' messages
+ --cache-file=FILE cache test results in FILE [disabled]
+ -C, --config-cache alias for \`--cache-file=config.cache'
+ -n, --no-create do not create output files
+ --srcdir=DIR find the sources in DIR [configure dir or \`..']
+
+Installation directories:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+ --bindir=DIR user executables [EPREFIX/bin]
+ --sbindir=DIR system admin executables [EPREFIX/sbin]
+ --libexecdir=DIR program executables [EPREFIX/libexec]
+ --sysconfdir=DIR read-only single-machine data [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data [PREFIX/var]
+ --libdir=DIR object code libraries [EPREFIX/lib]
+ --includedir=DIR C header files [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc [/usr/include]
+ --datarootdir=DIR read-only arch.-independent data root [PREFIX/share]
+ --datadir=DIR read-only architecture-independent data [DATAROOTDIR]
+ --infodir=DIR info documentation [DATAROOTDIR/info]
+ --localedir=DIR locale-dependent data [DATAROOTDIR/locale]
+ --mandir=DIR man documentation [DATAROOTDIR/man]
+ --docdir=DIR documentation root [DATAROOTDIR/doc/libphidget]
+ --htmldir=DIR html documentation [DOCDIR]
+ --dvidir=DIR dvi documentation [DOCDIR]
+ --pdfdir=DIR pdf documentation [DOCDIR]
+ --psdir=DIR ps documentation [DOCDIR]
+_ACEOF
+
+ cat <<\_ACEOF
+
+Program names:
+ --program-prefix=PREFIX prepend PREFIX to installed program names
+ --program-suffix=SUFFIX append SUFFIX to installed program names
+ --program-transform-name=PROGRAM run sed PROGRAM on installed program names
+
+System types:
+ --build=BUILD configure for building on BUILD [guessed]
+ --host=HOST cross-compile to build programs to run on HOST [BUILD]
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+ case $ac_init_help in
+ short | recursive ) echo "Configuration of Phidget21 C Library 2.1.8.20120216:";;
+ esac
+ cat <<\_ACEOF
+
+Optional Features:
+ --disable-option-checking ignore unrecognized --enable/--with options
+ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
+ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --enable-shared[=PKGS] build shared libraries [default=yes]
+ --enable-static[=PKGS] build static libraries [default=yes]
+ --enable-fast-install[=PKGS]
+ optimize for fast installation [default=yes]
+ --disable-dependency-tracking speeds up one-time build
+ --enable-dependency-tracking do not reject slow dependency extractors
+ --disable-libtool-lock avoid locking (might break parallel builds)
+ --enable-silent-rules less verbose build output (undo: `make V=1')
+ --disable-silent-rules verbose build output (undo: `make V=0')
+ --enable-jni Compile in Java support
+ --enable-debug Turn on debugging
+ --enable-zeroconf Turn on zeroconf, choose avahi or bonjour
+ --enable-zeroconf-lookup Turn on zeroconf lookup
+ --enable-labview Turn on Labview support
+ --disable-ldconfig do not update dynamic linker cache using ldconfig
+
+Optional Packages:
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --with-pic try to use only PIC/non-PIC objects [default=use
+ both]
+ --with-gnu-ld assume the C compiler uses GNU ld [default=no]
+
+Some influential environment variables:
+ CC C compiler command
+ CFLAGS C compiler flags
+ LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
+ nonstandard directory <lib dir>
+ LIBS libraries to pass to the linker, e.g. -l<library>
+ CPPFLAGS C/C++/Objective C preprocessor flags, e.g. -I<include dir> if
+ you have headers in a nonstandard directory <include dir>
+ CPP C preprocessor
+ LDCONFIG ldconfig utility
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+Report bugs to <support@phidgets.com>.
+Phidget21 C Library home page: <www.phidgets.com>.
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+ # If there are subdirs, report their specific --help.
+ for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+ test -d "$ac_dir" ||
+ { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } ||
+ continue
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+ cd "$ac_dir" || { ac_status=$?; continue; }
+ # Check for guested configure.
+ if test -f "$ac_srcdir/configure.gnu"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+ elif test -f "$ac_srcdir/configure"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure" --help=recursive
+ else
+ $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+ fi || ac_status=$?
+ cd "$ac_pwd" || { ac_status=$?; break; }
+ done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+ cat <<\_ACEOF
+Phidget21 C Library configure 2.1.8.20120216
+generated by GNU Autoconf 2.64
+
+Copyright (C) 2009 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+ exit
+fi
+
+## ------------------------ ##
+## Autoconf initialization. ##
+## ------------------------ ##
+
+# ac_fn_c_try_compile LINENO
+# --------------------------
+# Try to compile conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_compile ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ rm -f conftest.$ac_objext
+ if { { ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compile") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+ return $ac_retval
+
+} # ac_fn_c_try_compile
+
+# ac_fn_c_try_link LINENO
+# -----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_link ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ rm -f conftest.$ac_objext conftest$ac_exeext
+ if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext && {
+ test "$cross_compiling" = yes ||
+ $as_test_x conftest$ac_exeext
+ }; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
+ # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
+ # interfere with the next link command; also delete a directory that is
+ # left behind by Apple's compiler. We do this before executing the actions.
+ rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+ eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+ return $ac_retval
+
+} # ac_fn_c_try_link
+
+# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES
+# -------------------------------------------------------
+# Tests whether HEADER exists and can be compiled using the include files in
+# INCLUDES, setting the cache variable VAR accordingly.
+ac_fn_c_check_header_compile ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ eval "$3=yes"
+else
+ eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+
+} # ac_fn_c_check_header_compile
+
+# ac_fn_c_try_cpp LINENO
+# ----------------------
+# Try to preprocess conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_cpp ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ if { { ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+ return $ac_retval
+
+} # ac_fn_c_try_cpp
+
+# ac_fn_c_try_run LINENO
+# ----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes
+# that executables *can* be run.
+ac_fn_c_try_run ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && { ac_try='./conftest$ac_exeext'
+ { { case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: program exited with status $ac_status" >&5
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=$ac_status
+fi
+ rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+ eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+ return $ac_retval
+
+} # ac_fn_c_try_run
+
+# ac_fn_c_check_func LINENO FUNC VAR
+# ----------------------------------
+# Tests whether FUNC exists, setting the cache variable VAR accordingly
+ac_fn_c_check_func ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+/* Define $2 to an innocuous variant, in case <limits.h> declares $2.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define $2 innocuous_$2
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $2 (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $2
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $2 ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined __stub_$2 || defined __stub___$2
+choke me
+#endif
+
+int
+main ()
+{
+return $2 ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ eval "$3=yes"
+else
+ eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+
+} # ac_fn_c_check_func
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by Phidget21 C Library $as_me 2.1.8.20120216, which was
+generated by GNU Autoconf 2.64. Invocation command line was
+
+ $ $0 $@
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown`
+
+/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown`
+/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown`
+/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ $as_echo "PATH: $as_dir"
+ done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+ for ac_arg
+ do
+ case $ac_arg in
+ -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ continue ;;
+ *\'*)
+ ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ case $ac_pass in
+ 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
+ 2)
+ as_fn_append ac_configure_args1 " '$ac_arg'"
+ if test $ac_must_keep_next = true; then
+ ac_must_keep_next=false # Got value, back to normal.
+ else
+ case $ac_arg in
+ *=* | --config-cache | -C | -disable-* | --disable-* \
+ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+ | -with-* | --with-* | -without-* | --without-* | --x)
+ case "$ac_configure_args0 " in
+ "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+ esac
+ ;;
+ -* ) ac_must_keep_next=true ;;
+ esac
+ fi
+ as_fn_append ac_configure_args " '$ac_arg'"
+ ;;
+ esac
+ done
+done
+{ ac_configure_args0=; unset ac_configure_args0;}
+{ ac_configure_args1=; unset ac_configure_args1;}
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log. We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+ # Save into config.log some information that might help in debugging.
+ {
+ echo
+
+ cat <<\_ASBOX
+## ---------------- ##
+## Cache variables. ##
+## ---------------- ##
+_ASBOX
+ echo
+ # The following way of writing the cache mishandles newlines in values,
+(
+ for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+ *) { eval $ac_var=; unset $ac_var;} ;;
+ esac ;;
+ esac
+ done
+ (set) 2>&1 |
+ case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ sed -n \
+ "s/'\''/'\''\\\\'\'''\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+ ;; #(
+ *)
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+)
+ echo
+
+ cat <<\_ASBOX
+## ----------------- ##
+## Output variables. ##
+## ----------------- ##
+_ASBOX
+ echo
+ for ac_var in $ac_subst_vars
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ $as_echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+
+ if test -n "$ac_subst_files"; then
+ cat <<\_ASBOX
+## ------------------- ##
+## File substitutions. ##
+## ------------------- ##
+_ASBOX
+ echo
+ for ac_var in $ac_subst_files
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ $as_echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+ fi
+
+ if test -s confdefs.h; then
+ cat <<\_ASBOX
+## ----------- ##
+## confdefs.h. ##
+## ----------- ##
+_ASBOX
+ echo
+ cat confdefs.h
+ echo
+ fi
+ test "$ac_signal" != 0 &&
+ $as_echo "$as_me: caught signal $ac_signal"
+ $as_echo "$as_me: exit $exit_status"
+ } >&5
+ rm -f core *.core core.conftest.* &&
+ rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+ exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+ trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+$as_echo "/* confdefs.h */" > confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_URL "$PACKAGE_URL"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer an explicitly selected file to automatically selected ones.
+ac_site_file1=NONE
+ac_site_file2=NONE
+if test -n "$CONFIG_SITE"; then
+ ac_site_file1=$CONFIG_SITE
+elif test "x$prefix" != xNONE; then
+ ac_site_file1=$prefix/share/config.site
+ ac_site_file2=$prefix/etc/config.site
+else
+ ac_site_file1=$ac_default_prefix/share/config.site
+ ac_site_file2=$ac_default_prefix/etc/config.site
+fi
+for ac_site_file in "$ac_site_file1" "$ac_site_file2"
+do
+ test "x$ac_site_file" = xNONE && continue
+ if test -r "$ac_site_file"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
+$as_echo "$as_me: loading site script $ac_site_file" >&6;}
+ sed 's/^/| /' "$ac_site_file" >&5
+ . "$ac_site_file"
+ fi
+done
+
+if test -r "$cache_file"; then
+ # Some versions of bash will fail to source /dev/null (special
+ # files actually), so we avoid doing that.
+ if test -f "$cache_file"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
+$as_echo "$as_me: loading cache $cache_file" >&6;}
+ case $cache_file in
+ [\\/]* | ?:[\\/]* ) . "$cache_file";;
+ *) . "./$cache_file";;
+ esac
+ fi
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
+$as_echo "$as_me: creating cache $cache_file" >&6;}
+ >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+ eval ac_old_set=\$ac_cv_env_${ac_var}_set
+ eval ac_new_set=\$ac_env_${ac_var}_set
+ eval ac_old_val=\$ac_cv_env_${ac_var}_value
+ eval ac_new_val=\$ac_env_${ac_var}_value
+ case $ac_old_set,$ac_new_set in
+ set,)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,set)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,);;
+ *)
+ if test "x$ac_old_val" != "x$ac_new_val"; then
+ # differences in whitespace do not lead to failure.
+ ac_old_val_w=`echo x $ac_old_val`
+ ac_new_val_w=`echo x $ac_new_val`
+ if test "$ac_old_val_w" != "$ac_new_val_w"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
+$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+ ac_cache_corrupted=:
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
+$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
+ eval $ac_var=\$ac_old_val
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5
+$as_echo "$as_me: former value: \`$ac_old_val'" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5
+$as_echo "$as_me: current value: \`$ac_new_val'" >&2;}
+ fi;;
+ esac
+ # Pass precious variables to config.status.
+ if test "$ac_new_set" = set; then
+ case $ac_new_val in
+ *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *) ac_arg=$ac_var=$ac_new_val ;;
+ esac
+ case " $ac_configure_args " in
+ *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy.
+ *) as_fn_append ac_configure_args " '$ac_arg'" ;;
+ esac
+ fi
+done
+if $ac_cache_corrupted; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
+$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+ as_fn_error "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
+fi
+## -------------------- ##
+## Main body of script. ##
+## -------------------- ##
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+am__api_version='1.11'
+
+ac_aux_dir=
+for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do
+ for ac_t in install-sh install.sh shtool; do
+ if test -f "$ac_dir/$ac_t"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/$ac_t -c"
+ break 2
+ fi
+ done
+done
+if test -z "$ac_aux_dir"; then
+ as_fn_error "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5
+fi
+
+# These three variables are undocumented and unsupported,
+# and are intended to be withdrawn in a future Autoconf release.
+# They can cause serious problems if a builder's source tree is in a directory
+# whose full name contains unusual characters.
+ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var.
+ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var.
+ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var.
+
+
+# Find a good install program. We prefer a C program (faster),
+# so one script is as good as another. But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# OS/2's system install, which has a completely different semantic
+# ./install, which can be erroneously created by make from ./install.sh.
+# Reject install programs that cannot install multiple files.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5
+$as_echo_n "checking for a BSD-compatible install... " >&6; }
+if test -z "$INSTALL"; then
+if test "${ac_cv_path_install+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ # Account for people who put trailing slashes in PATH elements.
+case $as_dir/ in #((
+ ./ | .// | /[cC]/* | \
+ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+ ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \
+ /usr/ucb/* ) ;;
+ *)
+ # OSF1 and SCO ODT 3.0 have their own names for install.
+ # Don't use installbsd from OSF since it installs stuff as root
+ # by default.
+ for ac_prog in ginstall scoinst install; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then
+ if test $ac_prog = install &&
+ grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ # AIX install. It has an incompatible calling convention.
+ :
+ elif test $ac_prog = install &&
+ grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ # program-specific install script used by HP pwplus--don't use.
+ :
+ else
+ rm -rf conftest.one conftest.two conftest.dir
+ echo one > conftest.one
+ echo two > conftest.two
+ mkdir conftest.dir
+ if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" &&
+ test -s conftest.one && test -s conftest.two &&
+ test -s conftest.dir/conftest.one &&
+ test -s conftest.dir/conftest.two
+ then
+ ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+ break 3
+ fi
+ fi
+ fi
+ done
+ done
+ ;;
+esac
+
+ done
+IFS=$as_save_IFS
+
+rm -rf conftest.one conftest.two conftest.dir
+
+fi
+ if test "${ac_cv_path_install+set}" = set; then
+ INSTALL=$ac_cv_path_install
+ else
+ # As a last resort, use the slow shell script. Don't cache a
+ # value for INSTALL within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the value is a relative name.
+ INSTALL=$ac_install_sh
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5
+$as_echo "$INSTALL" >&6; }
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5
+$as_echo_n "checking whether build environment is sane... " >&6; }
+# Just in case
+sleep 1
+echo timestamp > conftest.file
+# Reject unsafe characters in $srcdir or the absolute working directory
+# name. Accept space and tab only in the latter.
+am_lf='
+'
+case `pwd` in
+ *[\\\"\#\$\&\'\`$am_lf]*)
+ as_fn_error "unsafe absolute working directory name" "$LINENO" 5;;
+esac
+case $srcdir in
+ *[\\\"\#\$\&\'\`$am_lf\ \ ]*)
+ as_fn_error "unsafe srcdir value: \`$srcdir'" "$LINENO" 5;;
+esac
+
+# Do `set' in a subshell so we don't clobber the current shell's
+# arguments. Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+ set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null`
+ if test "$*" = "X"; then
+ # -L didn't work.
+ set X `ls -t "$srcdir/configure" conftest.file`
+ fi
+ rm -f conftest.file
+ if test "$*" != "X $srcdir/configure conftest.file" \
+ && test "$*" != "X conftest.file $srcdir/configure"; then
+
+ # If neither matched, then we have a broken ls. This can happen
+ # if, for instance, CONFIG_SHELL is bash and it inherits a
+ # broken ls alias from the environment. This has actually
+ # happened. Such a system could not be considered "sane".
+ as_fn_error "ls -t appears to fail. Make sure there is not a broken
+alias in your environment" "$LINENO" 5
+ fi
+
+ test "$2" = conftest.file
+ )
+then
+ # Ok.
+ :
+else
+ as_fn_error "newly created file is older than distributed files!
+Check your system clock" "$LINENO" 5
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+test "$program_prefix" != NONE &&
+ program_transform_name="s&^&$program_prefix&;$program_transform_name"
+# Use a double $ so make ignores it.
+test "$program_suffix" != NONE &&
+ program_transform_name="s&\$&$program_suffix&;$program_transform_name"
+# Double any \ or $.
+# By default was `s,x,x', remove it if useless.
+ac_script='s/[\\$]/&&/g;s/;s,x,x,$//'
+program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"`
+
+# expand $ac_aux_dir to an absolute path
+am_aux_dir=`cd $ac_aux_dir && pwd`
+
+if test x"${MISSING+set}" != xset; then
+ case $am_aux_dir in
+ *\ * | *\ *)
+ MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;;
+ *)
+ MISSING="\${SHELL} $am_aux_dir/missing" ;;
+ esac
+fi
+# Use eval to expand $SHELL
+if eval "$MISSING --run true"; then
+ am_missing_run="$MISSING --run "
+else
+ am_missing_run=
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`missing' script is too old or missing" >&5
+$as_echo "$as_me: WARNING: \`missing' script is too old or missing" >&2;}
+fi
+
+if test x"${install_sh}" != xset; then
+ case $am_aux_dir in
+ *\ * | *\ *)
+ install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;;
+ *)
+ install_sh="\${SHELL} $am_aux_dir/install-sh"
+ esac
+fi
+
+# Installed binaries are usually stripped using `strip' when the user
+# run `make install-strip'. However `strip' might not be the right
+# tool to use in cross-compilation environments, therefore Automake
+# will honor the `STRIP' environment variable to overrule this program.
+if test "$cross_compiling" != no; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
+set dummy ${ac_tool_prefix}strip; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_STRIP+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$STRIP"; then
+ ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_STRIP="${ac_tool_prefix}strip"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+STRIP=$ac_cv_prog_STRIP
+if test -n "$STRIP"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5
+$as_echo "$STRIP" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_STRIP"; then
+ ac_ct_STRIP=$STRIP
+ # Extract the first word of "strip", so it can be a program name with args.
+set dummy strip; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_STRIP"; then
+ ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_STRIP="strip"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
+if test -n "$ac_ct_STRIP"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5
+$as_echo "$ac_ct_STRIP" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_STRIP" = x; then
+ STRIP=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ STRIP=$ac_ct_STRIP
+ fi
+else
+ STRIP="$ac_cv_prog_STRIP"
+fi
+
+fi
+INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5
+$as_echo_n "checking for a thread-safe mkdir -p... " >&6; }
+if test -z "$MKDIR_P"; then
+ if test "${ac_cv_path_mkdir+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in mkdir gmkdir; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; } || continue
+ case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #(
+ 'mkdir (GNU coreutils) '* | \
+ 'mkdir (coreutils) '* | \
+ 'mkdir (fileutils) '4.1*)
+ ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext
+ break 3;;
+ esac
+ done
+ done
+ done
+IFS=$as_save_IFS
+
+fi
+
+ if test "${ac_cv_path_mkdir+set}" = set; then
+ MKDIR_P="$ac_cv_path_mkdir -p"
+ else
+ # As a last resort, use the slow shell script. Don't cache a
+ # value for MKDIR_P within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the value is a relative name.
+ test -d ./--version && rmdir ./--version
+ MKDIR_P="$ac_install_sh -d"
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5
+$as_echo "$MKDIR_P" >&6; }
+
+mkdir_p="$MKDIR_P"
+case $mkdir_p in
+ [\\/$]* | ?:[\\/]*) ;;
+ */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;;
+esac
+
+for ac_prog in gawk mawk nawk awk
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_AWK+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$AWK"; then
+ ac_cv_prog_AWK="$AWK" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_AWK="$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+AWK=$ac_cv_prog_AWK
+if test -n "$AWK"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5
+$as_echo "$AWK" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$AWK" && break
+done
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5
+$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; }
+set x ${MAKE-make}
+ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'`
+if { as_var=ac_cv_prog_make_${ac_make}_set; eval "test \"\${$as_var+set}\" = set"; }; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat >conftest.make <<\_ACEOF
+SHELL = /bin/sh
+all:
+ @echo '@@@%%%=$(MAKE)=@@@%%%'
+_ACEOF
+# GNU make sometimes prints "make[1]: Entering...", which would confuse us.
+case `${MAKE-make} -f conftest.make 2>/dev/null` in
+ *@@@%%%=?*=@@@%%%*)
+ eval ac_cv_prog_make_${ac_make}_set=yes;;
+ *)
+ eval ac_cv_prog_make_${ac_make}_set=no;;
+esac
+rm -f conftest.make
+fi
+if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ SET_MAKE=
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+rm -rf .tst 2>/dev/null
+mkdir .tst 2>/dev/null
+if test -d .tst; then
+ am__leading_dot=.
+else
+ am__leading_dot=_
+fi
+rmdir .tst 2>/dev/null
+
+if test "`cd $srcdir && pwd`" != "`pwd`"; then
+ # Use -I$(srcdir) only when $(srcdir) != ., so that make's output
+ # is not polluted with repeated "-I."
+ am__isrc=' -I$(srcdir)'
+ # test to see if srcdir already configured
+ if test -f $srcdir/config.status; then
+ as_fn_error "source directory already configured; run \"make distclean\" there first" "$LINENO" 5
+ fi
+fi
+
+# test whether we have cygpath
+if test -z "$CYGPATH_W"; then
+ if (cygpath --version) >/dev/null 2>/dev/null; then
+ CYGPATH_W='cygpath -w'
+ else
+ CYGPATH_W=echo
+ fi
+fi
+
+
+# Define the identity of the package.
+ PACKAGE='libphidget'
+ VERSION='2.1.8.20120216'
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE "$PACKAGE"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define VERSION "$VERSION"
+_ACEOF
+
+# Some tools Automake needs.
+
+ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"}
+
+
+AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"}
+
+
+AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"}
+
+
+AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"}
+
+
+MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"}
+
+# We need awk for the "check" target. The system "awk" is bad on
+# some platforms.
+# Always define AMTAR for backward compatibility.
+
+AMTAR=${AMTAR-"${am_missing_run}tar"}
+
+am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'
+
+
+
+
+
+
+case `pwd` in
+ *\ * | *\ *)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5
+$as_echo "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;;
+esac
+
+
+
+macro_version='2.2.6'
+macro_revision='1.3012'
+
+
+
+
+
+
+
+
+
+
+
+
+
+ltmain="$ac_aux_dir/ltmain.sh"
+
+# Make sure we can run config.sub.
+$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
+ as_fn_error "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5
+$as_echo_n "checking build system type... " >&6; }
+if test "${ac_cv_build+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_build_alias=$build_alias
+test "x$ac_build_alias" = x &&
+ ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"`
+test "x$ac_build_alias" = x &&
+ as_fn_error "cannot guess build type; you must specify one" "$LINENO" 5
+ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` ||
+ as_fn_error "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5
+$as_echo "$ac_cv_build" >&6; }
+case $ac_cv_build in
+*-*-*) ;;
+*) as_fn_error "invalid value of canonical build" "$LINENO" 5;;
+esac
+build=$ac_cv_build
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_build
+shift
+build_cpu=$1
+build_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+build_os=$*
+IFS=$ac_save_IFS
+case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5
+$as_echo_n "checking host system type... " >&6; }
+if test "${ac_cv_host+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test "x$host_alias" = x; then
+ ac_cv_host=$ac_cv_build
+else
+ ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` ||
+ as_fn_error "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5
+$as_echo "$ac_cv_host" >&6; }
+case $ac_cv_host in
+*-*-*) ;;
+*) as_fn_error "invalid value of canonical host" "$LINENO" 5;;
+esac
+host=$ac_cv_host
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_host
+shift
+host_cpu=$1
+host_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+host_os=$*
+IFS=$ac_save_IFS
+case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
+
+
+DEPDIR="${am__leading_dot}deps"
+
+ac_config_commands="$ac_config_commands depfiles"
+
+
+am_make=${MAKE-make}
+cat > confinc << 'END'
+am__doit:
+ @echo this is the am__doit target
+.PHONY: am__doit
+END
+# If we don't find an include directive, just comment out the code.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5
+$as_echo_n "checking for style of include used by $am_make... " >&6; }
+am__include="#"
+am__quote=
+_am_result=none
+# First try GNU make style include.
+echo "include confinc" > confmf
+# Ignore all kinds of additional output from `make'.
+case `$am_make -s -f confmf 2> /dev/null` in #(
+*the\ am__doit\ target*)
+ am__include=include
+ am__quote=
+ _am_result=GNU
+ ;;
+esac
+# Now try BSD make style include.
+if test "$am__include" = "#"; then
+ echo '.include "confinc"' > confmf
+ case `$am_make -s -f confmf 2> /dev/null` in #(
+ *the\ am__doit\ target*)
+ am__include=.include
+ am__quote="\""
+ _am_result=BSD
+ ;;
+ esac
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5
+$as_echo "$_am_result" >&6; }
+rm -f confinc confmf
+
+# Check whether --enable-dependency-tracking was given.
+if test "${enable_dependency_tracking+set}" = set; then :
+ enableval=$enable_dependency_tracking;
+fi
+
+if test "x$enable_dependency_tracking" != xno; then
+ am_depcomp="$ac_aux_dir/depcomp"
+ AMDEPBACKSLASH='\'
+fi
+ if test "x$enable_dependency_tracking" != xno; then
+ AMDEP_TRUE=
+ AMDEP_FALSE='#'
+else
+ AMDEP_TRUE='#'
+ AMDEP_FALSE=
+fi
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CC="${ac_tool_prefix}gcc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_CC="gcc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+else
+ CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CC="${ac_tool_prefix}cc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ fi
+fi
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# != 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+ fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in cl.exe
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$CC" && break
+ done
+fi
+if test -z "$CC"; then
+ ac_ct_CC=$CC
+ for ac_prog in cl.exe
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_CC="$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$ac_ct_CC" && break
+done
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+fi
+
+fi
+
+
+test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error "no acceptable C compiler found in \$PATH
+See \`config.log' for more details." "$LINENO" 5; }
+
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+ { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ sed '10a\
+... rest of stderr output deleted ...
+ 10q' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ rm -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+done
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdio.h>
+int
+main ()
+{
+FILE *f = fopen ("conftest.out", "w");
+ return ferror (f) || fclose (f) != 0;
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out conftest.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
+$as_echo_n "checking for C compiler default output file name... " >&6; }
+ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+
+# The possible output files:
+ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"
+
+ac_rmfiles=
+for ac_file in $ac_files
+do
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+ * ) ac_rmfiles="$ac_rmfiles $ac_file";;
+ esac
+done
+rm -f $ac_rmfiles
+
+if { { ac_try="$ac_link_default"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link_default") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
+ # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
+# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
+# in a Makefile. We should not override ac_cv_exeext if it was cached,
+# so that the user can short-circuit this test for compilers unknown to
+# Autoconf.
+for ac_file in $ac_files ''
+do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )
+ ;;
+ [ab].out )
+ # We found the default executable, but exeext='' is most
+ # certainly right.
+ break;;
+ *.* )
+ if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+ then :; else
+ ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ fi
+ # We set ac_cv_exeext here because the later test for it is not
+ # safe: cross compilers may not add the suffix if given an `-o'
+ # argument, so we may need to know it at that point already.
+ # Even if this section looks crufty: it has the advantage of
+ # actually working.
+ break;;
+ * )
+ break;;
+ esac
+done
+test "$ac_cv_exeext" = no && ac_cv_exeext=
+
+else
+ ac_file=''
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
+$as_echo "$ac_file" >&6; }
+if test -z "$ac_file"; then :
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+{ as_fn_set_status 77
+as_fn_error "C compiler cannot create executables
+See \`config.log' for more details." "$LINENO" 5; }; }
+fi
+ac_exeext=$ac_cv_exeext
+
+# Check that the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
+$as_echo_n "checking whether the C compiler works... " >&6; }
+# If not cross compiling, check that we can run a simple program.
+if test "$cross_compiling" != yes; then
+ if { ac_try='./$ac_file'
+ { { case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }; then
+ cross_compiling=no
+ else
+ if test "$cross_compiling" = maybe; then
+ cross_compiling=yes
+ else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error "cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." "$LINENO" 5; }
+ fi
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out conftest.out
+ac_clean_files=$ac_clean_files_save
+# Check that the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
+$as_echo_n "checking whether we are cross compiling... " >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
+$as_echo "$cross_compiling" >&6; }
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
+$as_echo_n "checking for suffix of executables... " >&6; }
+if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
+ # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+ *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ break;;
+ * ) break;;
+ esac
+done
+else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error "cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." "$LINENO" 5; }
+fi
+rm -f conftest$ac_cv_exeext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
+$as_echo "$ac_cv_exeext" >&6; }
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
+$as_echo_n "checking for suffix of object files... " >&6; }
+if test "${ac_cv_objext+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { { ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compile") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
+ for ac_file in conftest.o conftest.obj conftest.*; do
+ test -f "$ac_file" || continue;
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;
+ *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+ break;;
+ esac
+done
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error "cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." "$LINENO" 5; }
+fi
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
+$as_echo "$ac_cv_objext" >&6; }
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
+$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
+if test "${ac_cv_c_compiler_gnu+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_compiler_gnu=yes
+else
+ ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+$as_echo "$ac_cv_c_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+ GCC=yes
+else
+ GCC=
+fi
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+$as_echo_n "checking whether $CC accepts -g... " >&6; }
+if test "${ac_cv_prog_cc_g+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_save_c_werror_flag=$ac_c_werror_flag
+ ac_c_werror_flag=yes
+ ac_cv_prog_cc_g=no
+ CFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_g=yes
+else
+ CFLAGS=""
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+ ac_c_werror_flag=$ac_save_c_werror_flag
+ CFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+$as_echo "$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+ CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-g"
+ fi
+else
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
+$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
+if test "${ac_cv_prog_cc_c89+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+ char **p;
+ int i;
+{
+ return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+ char *s;
+ va_list v;
+ va_start (v,p);
+ s = g (p, va_arg (v,int));
+ va_end (v);
+ return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
+ function prototypes and stuff, but not '\xHH' hex character constants.
+ These don't provoke an error unfortunately, instead are silently treated
+ as 'x'. The following induces an error, until -std is added to get
+ proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an
+ array size at least. It's necessary to write '\x00'==0 to get something
+ that's true only with -std. */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+ inside strings and character constants. */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
+ ;
+ return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+ CC="$ac_save_CC $ac_arg"
+ if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_c89=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext
+ test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+ x)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+$as_echo "none needed" >&6; } ;;
+ xno)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+$as_echo "unsupported" >&6; } ;;
+ *)
+ CC="$CC $ac_cv_prog_cc_c89"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+if test "x$ac_cv_prog_cc_c89" != xno; then :
+
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+depcc="$CC" am_compiler_list=
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5
+$as_echo_n "checking dependency style of $depcc... " >&6; }
+if test "${am_cv_CC_dependencies_compiler_type+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+ # We make a subdir and do the tests there. Otherwise we can end up
+ # making bogus files that we don't know about and never remove. For
+ # instance it was reported that on HP-UX the gcc test will end up
+ # making a dummy file named `D' -- because `-MD' means `put the output
+ # in D'.
+ mkdir conftest.dir
+ # Copy depcomp to subdir because otherwise we won't find it if we're
+ # using a relative directory.
+ cp "$am_depcomp" conftest.dir
+ cd conftest.dir
+ # We will build objects and dependencies in a subdirectory because
+ # it helps to detect inapplicable dependency modes. For instance
+ # both Tru64's cc and ICC support -MD to output dependencies as a
+ # side effect of compilation, but ICC will put the dependencies in
+ # the current directory while Tru64 will put them in the object
+ # directory.
+ mkdir sub
+
+ am_cv_CC_dependencies_compiler_type=none
+ if test "$am_compiler_list" = ""; then
+ am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp`
+ fi
+ am__universal=false
+ case " $depcc " in #(
+ *\ -arch\ *\ -arch\ *) am__universal=true ;;
+ esac
+
+ for depmode in $am_compiler_list; do
+ # Setup a source with many dependencies, because some compilers
+ # like to wrap large dependency lists on column 80 (with \), and
+ # we should not choose a depcomp mode which is confused by this.
+ #
+ # We need to recreate these files for each test, as the compiler may
+ # overwrite some of them when testing with obscure command lines.
+ # This happens at least with the AIX C compiler.
+ : > sub/conftest.c
+ for i in 1 2 3 4 5 6; do
+ echo '#include "conftst'$i'.h"' >> sub/conftest.c
+ # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with
+ # Solaris 8's {/usr,}/bin/sh.
+ touch sub/conftst$i.h
+ done
+ echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+ # We check with `-c' and `-o' for the sake of the "dashmstdout"
+ # mode. It turns out that the SunPro C++ compiler does not properly
+ # handle `-M -o', and we need to detect this. Also, some Intel
+ # versions had trouble with output in subdirs
+ am__obj=sub/conftest.${OBJEXT-o}
+ am__minus_obj="-o $am__obj"
+ case $depmode in
+ gcc)
+ # This depmode causes a compiler race in universal mode.
+ test "$am__universal" = false || continue
+ ;;
+ nosideeffect)
+ # after this tag, mechanisms are not by side-effect, so they'll
+ # only be used when explicitly requested
+ if test "x$enable_dependency_tracking" = xyes; then
+ continue
+ else
+ break
+ fi
+ ;;
+ msvisualcpp | msvcmsys)
+ # This compiler won't grok `-c -o', but also, the minuso test has
+ # not run yet. These depmodes are late enough in the game, and
+ # so weak that their functioning should not be impacted.
+ am__obj=conftest.${OBJEXT-o}
+ am__minus_obj=
+ ;;
+ none) break ;;
+ esac
+ if depmode=$depmode \
+ source=sub/conftest.c object=$am__obj \
+ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
+ >/dev/null 2>conftest.err &&
+ grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
+ ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+ # icc doesn't choke on unknown options, it will just issue warnings
+ # or remarks (even with -Werror). So we grep stderr for any message
+ # that says an option was ignored or not supported.
+ # When given -MP, icc 7.0 and 7.1 complain thusly:
+ # icc: Command line warning: ignoring option '-M'; no argument required
+ # The diagnosis changed in icc 8.0:
+ # icc: Command line remark: option '-MP' not supported
+ if (grep 'ignoring option' conftest.err ||
+ grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+ am_cv_CC_dependencies_compiler_type=$depmode
+ break
+ fi
+ fi
+ done
+
+ cd ..
+ rm -rf conftest.dir
+else
+ am_cv_CC_dependencies_compiler_type=none
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5
+$as_echo "$am_cv_CC_dependencies_compiler_type" >&6; }
+CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type
+
+ if
+ test "x$enable_dependency_tracking" != xno \
+ && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then
+ am__fastdepCC_TRUE=
+ am__fastdepCC_FALSE='#'
+else
+ am__fastdepCC_TRUE='#'
+ am__fastdepCC_FALSE=
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5
+$as_echo_n "checking for a sed that does not truncate output... " >&6; }
+if test "${ac_cv_path_SED+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/
+ for ac_i in 1 2 3 4 5 6 7; do
+ ac_script="$ac_script$as_nl$ac_script"
+ done
+ echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed
+ { ac_script=; unset ac_script;}
+ if test -z "$SED"; then
+ ac_path_SED_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in sed gsed; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_SED="$as_dir/$ac_prog$ac_exec_ext"
+ { test -f "$ac_path_SED" && $as_test_x "$ac_path_SED"; } || continue
+# Check for GNU ac_path_SED and select it if it is found.
+ # Check for GNU $ac_path_SED
+case `"$ac_path_SED" --version 2>&1` in
+*GNU*)
+ ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;;
+*)
+ ac_count=0
+ $as_echo_n 0123456789 >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ $as_echo '' >> "conftest.nl"
+ "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
+ if test $ac_count -gt ${ac_path_SED_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_SED="$ac_path_SED"
+ ac_path_SED_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+ $ac_path_SED_found && break 3
+ done
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_SED"; then
+ as_fn_error "no acceptable sed could be found in \$PATH" "$LINENO" 5
+ fi
+else
+ ac_cv_path_SED=$SED
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5
+$as_echo "$ac_cv_path_SED" >&6; }
+ SED="$ac_cv_path_SED"
+ rm -f conftest.sed
+
+test -z "$SED" && SED=sed
+Xsed="$SED -e 1s/^X//"
+
+
+
+
+
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
+$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
+if test "${ac_cv_path_GREP+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -z "$GREP"; then
+ ac_path_GREP_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in grep ggrep; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
+ { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue
+# Check for GNU ac_path_GREP and select it if it is found.
+ # Check for GNU $ac_path_GREP
+case `"$ac_path_GREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+*)
+ ac_count=0
+ $as_echo_n 0123456789 >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ $as_echo 'GREP' >> "conftest.nl"
+ "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
+ if test $ac_count -gt ${ac_path_GREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_GREP="$ac_path_GREP"
+ ac_path_GREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+ $ac_path_GREP_found && break 3
+ done
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_GREP"; then
+ as_fn_error "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ fi
+else
+ ac_cv_path_GREP=$GREP
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
+$as_echo "$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
+$as_echo_n "checking for egrep... " >&6; }
+if test "${ac_cv_path_EGREP+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
+ then ac_cv_path_EGREP="$GREP -E"
+ else
+ if test -z "$EGREP"; then
+ ac_path_EGREP_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in egrep; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
+ { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue
+# Check for GNU ac_path_EGREP and select it if it is found.
+ # Check for GNU $ac_path_EGREP
+case `"$ac_path_EGREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
+*)
+ ac_count=0
+ $as_echo_n 0123456789 >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ $as_echo 'EGREP' >> "conftest.nl"
+ "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
+ if test $ac_count -gt ${ac_path_EGREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_EGREP="$ac_path_EGREP"
+ ac_path_EGREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+ $ac_path_EGREP_found && break 3
+ done
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_EGREP"; then
+ as_fn_error "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ fi
+else
+ ac_cv_path_EGREP=$EGREP
+fi
+
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
+$as_echo "$ac_cv_path_EGREP" >&6; }
+ EGREP="$ac_cv_path_EGREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5
+$as_echo_n "checking for fgrep... " >&6; }
+if test "${ac_cv_path_FGREP+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1
+ then ac_cv_path_FGREP="$GREP -F"
+ else
+ if test -z "$FGREP"; then
+ ac_path_FGREP_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in fgrep; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_FGREP="$as_dir/$ac_prog$ac_exec_ext"
+ { test -f "$ac_path_FGREP" && $as_test_x "$ac_path_FGREP"; } || continue
+# Check for GNU ac_path_FGREP and select it if it is found.
+ # Check for GNU $ac_path_FGREP
+case `"$ac_path_FGREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_found=:;;
+*)
+ ac_count=0
+ $as_echo_n 0123456789 >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ $as_echo 'FGREP' >> "conftest.nl"
+ "$ac_path_FGREP" FGREP < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
+ if test $ac_count -gt ${ac_path_FGREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_FGREP="$ac_path_FGREP"
+ ac_path_FGREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+ $ac_path_FGREP_found && break 3
+ done
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_FGREP"; then
+ as_fn_error "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ fi
+else
+ ac_cv_path_FGREP=$FGREP
+fi
+
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5
+$as_echo "$ac_cv_path_FGREP" >&6; }
+ FGREP="$ac_cv_path_FGREP"
+
+
+test -z "$GREP" && GREP=grep
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# Check whether --with-gnu-ld was given.
+if test "${with_gnu_ld+set}" = set; then :
+ withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes
+else
+ with_gnu_ld=no
+fi
+
+ac_prog=ld
+if test "$GCC" = yes; then
+ # Check if gcc -print-prog-name=ld gives a path.
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5
+$as_echo_n "checking for ld used by $CC... " >&6; }
+ case $host in
+ *-*-mingw*)
+ # gcc leaves a trailing carriage return which upsets mingw
+ ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+ *)
+ ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+ esac
+ case $ac_prog in
+ # Accept absolute paths.
+ [\\/]* | ?:[\\/]*)
+ re_direlt='/[^/][^/]*/\.\./'
+ # Canonicalize the pathname of ld
+ ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'`
+ while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do
+ ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"`
+ done
+ test -z "$LD" && LD="$ac_prog"
+ ;;
+ "")
+ # If it fails, then pretend we aren't using GCC.
+ ac_prog=ld
+ ;;
+ *)
+ # If it is relative, then search for the first ld in PATH.
+ with_gnu_ld=unknown
+ ;;
+ esac
+elif test "$with_gnu_ld" = yes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5
+$as_echo_n "checking for GNU ld... " >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5
+$as_echo_n "checking for non-GNU ld... " >&6; }
+fi
+if test "${lt_cv_path_LD+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -z "$LD"; then
+ lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+ for ac_dir in $PATH; do
+ IFS="$lt_save_ifs"
+ test -z "$ac_dir" && ac_dir=.
+ if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+ lt_cv_path_LD="$ac_dir/$ac_prog"
+ # Check to see if the program is GNU ld. I'd rather use --version,
+ # but apparently some variants of GNU ld only accept -v.
+ # Break only if it was the GNU/non-GNU ld that we prefer.
+ case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in
+ *GNU* | *'with BFD'*)
+ test "$with_gnu_ld" != no && break
+ ;;
+ *)
+ test "$with_gnu_ld" != yes && break
+ ;;
+ esac
+ fi
+ done
+ IFS="$lt_save_ifs"
+else
+ lt_cv_path_LD="$LD" # Let the user override the test with a path.
+fi
+fi
+
+LD="$lt_cv_path_LD"
+if test -n "$LD"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LD" >&5
+$as_echo "$LD" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+test -z "$LD" && as_fn_error "no acceptable ld found in \$PATH" "$LINENO" 5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5
+$as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; }
+if test "${lt_cv_prog_gnu_ld+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ # I'd rather use --version here, but apparently some GNU lds only accept -v.
+case `$LD -v 2>&1 </dev/null` in
+*GNU* | *'with BFD'*)
+ lt_cv_prog_gnu_ld=yes
+ ;;
+*)
+ lt_cv_prog_gnu_ld=no
+ ;;
+esac
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_gnu_ld" >&5
+$as_echo "$lt_cv_prog_gnu_ld" >&6; }
+with_gnu_ld=$lt_cv_prog_gnu_ld
+
+
+
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5
+$as_echo_n "checking for BSD- or MS-compatible name lister (nm)... " >&6; }
+if test "${lt_cv_path_NM+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$NM"; then
+ # Let the user override the test.
+ lt_cv_path_NM="$NM"
+else
+ lt_nm_to_check="${ac_tool_prefix}nm"
+ if test -n "$ac_tool_prefix" && test "$build" = "$host"; then
+ lt_nm_to_check="$lt_nm_to_check nm"
+ fi
+ for lt_tmp_nm in $lt_nm_to_check; do
+ lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+ for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do
+ IFS="$lt_save_ifs"
+ test -z "$ac_dir" && ac_dir=.
+ tmp_nm="$ac_dir/$lt_tmp_nm"
+ if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then
+ # Check to see if the nm accepts a BSD-compat flag.
+ # Adding the `sed 1q' prevents false positives on HP-UX, which says:
+ # nm: unknown option "B" ignored
+ # Tru64's nm complains that /dev/null is an invalid object file
+ case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in
+ */dev/null* | *'Invalid file or object type'*)
+ lt_cv_path_NM="$tmp_nm -B"
+ break
+ ;;
+ *)
+ case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in
+ */dev/null*)
+ lt_cv_path_NM="$tmp_nm -p"
+ break
+ ;;
+ *)
+ lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but
+ continue # so that we can try to find one that supports BSD flags
+ ;;
+ esac
+ ;;
+ esac
+ fi
+ done
+ IFS="$lt_save_ifs"
+ done
+ : ${lt_cv_path_NM=no}
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5
+$as_echo "$lt_cv_path_NM" >&6; }
+if test "$lt_cv_path_NM" != "no"; then
+ NM="$lt_cv_path_NM"
+else
+ # Didn't find any BSD compatible name lister, look for dumpbin.
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in "dumpbin -symbols" "link -dump -symbols"
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_DUMPBIN+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$DUMPBIN"; then
+ ac_cv_prog_DUMPBIN="$DUMPBIN" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+DUMPBIN=$ac_cv_prog_DUMPBIN
+if test -n "$DUMPBIN"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5
+$as_echo "$DUMPBIN" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$DUMPBIN" && break
+ done
+fi
+if test -z "$DUMPBIN"; then
+ ac_ct_DUMPBIN=$DUMPBIN
+ for ac_prog in "dumpbin -symbols" "link -dump -symbols"
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_DUMPBIN+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_DUMPBIN"; then
+ ac_cv_prog_ac_ct_DUMPBIN="$ac_ct_DUMPBIN" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_DUMPBIN="$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN
+if test -n "$ac_ct_DUMPBIN"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5
+$as_echo "$ac_ct_DUMPBIN" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$ac_ct_DUMPBIN" && break
+done
+
+ if test "x$ac_ct_DUMPBIN" = x; then
+ DUMPBIN=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ DUMPBIN=$ac_ct_DUMPBIN
+ fi
+fi
+
+
+ if test "$DUMPBIN" != ":"; then
+ NM="$DUMPBIN"
+ fi
+fi
+test -z "$NM" && NM=nm
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5
+$as_echo_n "checking the name lister ($NM) interface... " >&6; }
+if test "${lt_cv_nm_interface+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ lt_cv_nm_interface="BSD nm"
+ echo "int some_variable = 0;" > conftest.$ac_ext
+ (eval echo "\"\$as_me:4385: $ac_compile\"" >&5)
+ (eval "$ac_compile" 2>conftest.err)
+ cat conftest.err >&5
+ (eval echo "\"\$as_me:4388: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
+ (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
+ cat conftest.err >&5
+ (eval echo "\"\$as_me:4391: output\"" >&5)
+ cat conftest.out >&5
+ if $GREP 'External.*some_variable' conftest.out > /dev/null; then
+ lt_cv_nm_interface="MS dumpbin"
+ fi
+ rm -f conftest*
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5
+$as_echo "$lt_cv_nm_interface" >&6; }
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5
+$as_echo_n "checking whether ln -s works... " >&6; }
+LN_S=$as_ln_s
+if test "$LN_S" = "ln -s"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5
+$as_echo "no, using $LN_S" >&6; }
+fi
+
+# find the maximum length of command line arguments
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5
+$as_echo_n "checking the maximum length of command line arguments... " >&6; }
+if test "${lt_cv_sys_max_cmd_len+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ i=0
+ teststring="ABCD"
+
+ case $build_os in
+ msdosdjgpp*)
+ # On DJGPP, this test can blow up pretty badly due to problems in libc
+ # (any single argument exceeding 2000 bytes causes a buffer overrun
+ # during glob expansion). Even if it were fixed, the result of this
+ # check would be larger than it should be.
+ lt_cv_sys_max_cmd_len=12288; # 12K is about right
+ ;;
+
+ gnu*)
+ # Under GNU Hurd, this test is not required because there is
+ # no limit to the length of command line arguments.
+ # Libtool will interpret -1 as no limit whatsoever
+ lt_cv_sys_max_cmd_len=-1;
+ ;;
+
+ cygwin* | mingw* | cegcc*)
+ # On Win9x/ME, this test blows up -- it succeeds, but takes
+ # about 5 minutes as the teststring grows exponentially.
+ # Worse, since 9x/ME are not pre-emptively multitasking,
+ # you end up with a "frozen" computer, even though with patience
+ # the test eventually succeeds (with a max line length of 256k).
+ # Instead, let's just punt: use the minimum linelength reported by
+ # all of the supported platforms: 8192 (on NT/2K/XP).
+ lt_cv_sys_max_cmd_len=8192;
+ ;;
+
+ amigaos*)
+ # On AmigaOS with pdksh, this test takes hours, literally.
+ # So we just punt and use a minimum line length of 8192.
+ lt_cv_sys_max_cmd_len=8192;
+ ;;
+
+ netbsd* | freebsd* | openbsd* | darwin* | dragonfly*)
+ # This has been around since 386BSD, at least. Likely further.
+ if test -x /sbin/sysctl; then
+ lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax`
+ elif test -x /usr/sbin/sysctl; then
+ lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax`
+ else
+ lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs
+ fi
+ # And add a safety zone
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
+ ;;
+
+ interix*)
+ # We know the value 262144 and hardcode it with a safety zone (like BSD)
+ lt_cv_sys_max_cmd_len=196608
+ ;;
+
+ osf*)
+ # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure
+ # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not
+ # nice to cause kernel panics so lets avoid the loop below.
+ # First set a reasonable default.
+ lt_cv_sys_max_cmd_len=16384
+ #
+ if test -x /sbin/sysconfig; then
+ case `/sbin/sysconfig -q proc exec_disable_arg_limit` in
+ *1*) lt_cv_sys_max_cmd_len=-1 ;;
+ esac
+ fi
+ ;;
+ sco3.2v5*)
+ lt_cv_sys_max_cmd_len=102400
+ ;;
+ sysv5* | sco5v6* | sysv4.2uw2*)
+ kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null`
+ if test -n "$kargmax"; then
+ lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[ ]//'`
+ else
+ lt_cv_sys_max_cmd_len=32768
+ fi
+ ;;
+ *)
+ lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null`
+ if test -n "$lt_cv_sys_max_cmd_len"; then
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
+ else
+ # Make teststring a little bigger before we do anything with it.
+ # a 1K string should be a reasonable start.
+ for i in 1 2 3 4 5 6 7 8 ; do
+ teststring=$teststring$teststring
+ done
+ SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}}
+ # If test is not a shell built-in, we'll probably end up computing a
+ # maximum length that is only half of the actual maximum length, but
+ # we can't tell.
+ while { test "X"`$SHELL $0 --fallback-echo "X$teststring$teststring" 2>/dev/null` \
+ = "XX$teststring$teststring"; } >/dev/null 2>&1 &&
+ test $i != 17 # 1/2 MB should be enough
+ do
+ i=`expr $i + 1`
+ teststring=$teststring$teststring
+ done
+ # Only check the string length outside the loop.
+ lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1`
+ teststring=
+ # Add a significant safety factor because C++ compilers can tack on
+ # massive amounts of additional arguments before passing them to the
+ # linker. It appears as though 1/2 is a usable value.
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2`
+ fi
+ ;;
+ esac
+
+fi
+
+if test -n $lt_cv_sys_max_cmd_len ; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5
+$as_echo "$lt_cv_sys_max_cmd_len" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5
+$as_echo "none" >&6; }
+fi
+max_cmd_len=$lt_cv_sys_max_cmd_len
+
+
+
+
+
+
+: ${CP="cp -f"}
+: ${MV="mv -f"}
+: ${RM="rm -f"}
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands some XSI constructs" >&5
+$as_echo_n "checking whether the shell understands some XSI constructs... " >&6; }
+# Try some XSI features
+xsi_shell=no
+( _lt_dummy="a/b/c"
+ test "${_lt_dummy##*/},${_lt_dummy%/*},"${_lt_dummy%"$_lt_dummy"}, \
+ = c,a/b,, \
+ && eval 'test $(( 1 + 1 )) -eq 2 \
+ && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \
+ && xsi_shell=yes
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $xsi_shell" >&5
+$as_echo "$xsi_shell" >&6; }
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands \"+=\"" >&5
+$as_echo_n "checking whether the shell understands \"+=\"... " >&6; }
+lt_shell_append=no
+( foo=bar; set foo baz; eval "$1+=\$2" && test "$foo" = barbaz ) \
+ >/dev/null 2>&1 \
+ && lt_shell_append=yes
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_shell_append" >&5
+$as_echo "$lt_shell_append" >&6; }
+
+
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+ lt_unset=unset
+else
+ lt_unset=false
+fi
+
+
+
+
+
+# test EBCDIC or ASCII
+case `echo X|tr X '\101'` in
+ A) # ASCII based system
+ # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr
+ lt_SP2NL='tr \040 \012'
+ lt_NL2SP='tr \015\012 \040\040'
+ ;;
+ *) # EBCDIC based system
+ lt_SP2NL='tr \100 \n'
+ lt_NL2SP='tr \r\n \100\100'
+ ;;
+esac
+
+
+
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5
+$as_echo_n "checking for $LD option to reload object files... " >&6; }
+if test "${lt_cv_ld_reload_flag+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ lt_cv_ld_reload_flag='-r'
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5
+$as_echo "$lt_cv_ld_reload_flag" >&6; }
+reload_flag=$lt_cv_ld_reload_flag
+case $reload_flag in
+"" | " "*) ;;
+*) reload_flag=" $reload_flag" ;;
+esac
+reload_cmds='$LD$reload_flag -o $output$reload_objs'
+case $host_os in
+ darwin*)
+ if test "$GCC" = yes; then
+ reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs'
+ else
+ reload_cmds='$LD$reload_flag -o $output$reload_objs'
+ fi
+ ;;
+esac
+
+
+
+
+
+
+
+
+
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args.
+set dummy ${ac_tool_prefix}objdump; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_OBJDUMP+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$OBJDUMP"; then
+ ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+OBJDUMP=$ac_cv_prog_OBJDUMP
+if test -n "$OBJDUMP"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5
+$as_echo "$OBJDUMP" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_OBJDUMP"; then
+ ac_ct_OBJDUMP=$OBJDUMP
+ # Extract the first word of "objdump", so it can be a program name with args.
+set dummy objdump; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_OBJDUMP+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_OBJDUMP"; then
+ ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_OBJDUMP="objdump"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP
+if test -n "$ac_ct_OBJDUMP"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5
+$as_echo "$ac_ct_OBJDUMP" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_OBJDUMP" = x; then
+ OBJDUMP="false"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ OBJDUMP=$ac_ct_OBJDUMP
+ fi
+else
+ OBJDUMP="$ac_cv_prog_OBJDUMP"
+fi
+
+test -z "$OBJDUMP" && OBJDUMP=objdump
+
+
+
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5
+$as_echo_n "checking how to recognize dependent libraries... " >&6; }
+if test "${lt_cv_deplibs_check_method+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ lt_cv_file_magic_cmd='$MAGIC_CMD'
+lt_cv_file_magic_test_file=
+lt_cv_deplibs_check_method='unknown'
+# Need to set the preceding variable on all platforms that support
+# interlibrary dependencies.
+# 'none' -- dependencies not supported.
+# `unknown' -- same as none, but documents that we really don't know.
+# 'pass_all' -- all dependencies passed with no checks.
+# 'test_compile' -- check by making test program.
+# 'file_magic [[regex]]' -- check by looking for files in library path
+# which responds to the $file_magic_cmd with a given extended regex.
+# If you have `file' or equivalent on your system and you're not sure
+# whether `pass_all' will *always* work, you probably want this one.
+
+case $host_os in
+aix[4-9]*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+beos*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+bsdi[45]*)
+ lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)'
+ lt_cv_file_magic_cmd='/usr/bin/file -L'
+ lt_cv_file_magic_test_file=/shlib/libc.so
+ ;;
+
+cygwin*)
+ # func_win32_libid is a shell function defined in ltmain.sh
+ lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
+ lt_cv_file_magic_cmd='func_win32_libid'
+ ;;
+
+mingw* | pw32*)
+ # Base MSYS/MinGW do not provide the 'file' command needed by
+ # func_win32_libid shell function, so use a weaker test based on 'objdump',
+ # unless we find 'file', for example because we are cross-compiling.
+ if ( file / ) >/dev/null 2>&1; then
+ lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
+ lt_cv_file_magic_cmd='func_win32_libid'
+ else
+ lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?'
+ lt_cv_file_magic_cmd='$OBJDUMP -f'
+ fi
+ ;;
+
+cegcc)
+ # use the weaker test based on 'objdump'. See mingw*.
+ lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?'
+ lt_cv_file_magic_cmd='$OBJDUMP -f'
+ ;;
+
+darwin* | rhapsody*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+freebsd* | dragonfly*)
+ if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
+ case $host_cpu in
+ i*86 )
+ # Not sure whether the presence of OpenBSD here was a mistake.
+ # Let's accept both of them until this is cleared up.
+ lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library'
+ lt_cv_file_magic_cmd=/usr/bin/file
+ lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
+ ;;
+ esac
+ else
+ lt_cv_deplibs_check_method=pass_all
+ fi
+ ;;
+
+gnu*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+hpux10.20* | hpux11*)
+ lt_cv_file_magic_cmd=/usr/bin/file
+ case $host_cpu in
+ ia64*)
+ lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64'
+ lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so
+ ;;
+ hppa*64*)
+ lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]'
+ lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl
+ ;;
+ *)
+ lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9].[0-9]) shared library'
+ lt_cv_file_magic_test_file=/usr/lib/libc.sl
+ ;;
+ esac
+ ;;
+
+interix[3-9]*)
+ # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here
+ lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$'
+ ;;
+
+irix5* | irix6* | nonstopux*)
+ case $LD in
+ *-32|*"-32 ") libmagic=32-bit;;
+ *-n32|*"-n32 ") libmagic=N32;;
+ *-64|*"-64 ") libmagic=64-bit;;
+ *) libmagic=never-match;;
+ esac
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+# This must be Linux ELF.
+linux* | k*bsd*-gnu)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+netbsd* | netbsdelf*-gnu)
+ if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
+ lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$'
+ else
+ lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$'
+ fi
+ ;;
+
+newos6*)
+ lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)'
+ lt_cv_file_magic_cmd=/usr/bin/file
+ lt_cv_file_magic_test_file=/usr/lib/libnls.so
+ ;;
+
+*nto* | *qnx*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+openbsd*)
+ if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$'
+ else
+ lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$'
+ fi
+ ;;
+
+osf3* | osf4* | osf5*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+rdos*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+solaris*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+sysv4 | sysv4.3*)
+ case $host_vendor in
+ motorola)
+ lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]'
+ lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*`
+ ;;
+ ncr)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+ sequent)
+ lt_cv_file_magic_cmd='/bin/file'
+ lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )'
+ ;;
+ sni)
+ lt_cv_file_magic_cmd='/bin/file'
+ lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib"
+ lt_cv_file_magic_test_file=/lib/libc.so
+ ;;
+ siemens)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+ pc)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+ esac
+ ;;
+
+tpf*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+esac
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5
+$as_echo "$lt_cv_deplibs_check_method" >&6; }
+file_magic_cmd=$lt_cv_file_magic_cmd
+deplibs_check_method=$lt_cv_deplibs_check_method
+test -z "$deplibs_check_method" && deplibs_check_method=unknown
+
+
+
+
+
+
+
+
+
+
+
+
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ar; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_AR+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$AR"; then
+ ac_cv_prog_AR="$AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_AR="${ac_tool_prefix}ar"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+AR=$ac_cv_prog_AR
+if test -n "$AR"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5
+$as_echo "$AR" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_AR"; then
+ ac_ct_AR=$AR
+ # Extract the first word of "ar", so it can be a program name with args.
+set dummy ar; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_AR+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_AR"; then
+ ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_AR="ar"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_AR=$ac_cv_prog_ac_ct_AR
+if test -n "$ac_ct_AR"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5
+$as_echo "$ac_ct_AR" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_AR" = x; then
+ AR="false"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ AR=$ac_ct_AR
+ fi
+else
+ AR="$ac_cv_prog_AR"
+fi
+
+test -z "$AR" && AR=ar
+test -z "$AR_FLAGS" && AR_FLAGS=cru
+
+
+
+
+
+
+
+
+
+
+
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
+set dummy ${ac_tool_prefix}strip; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_STRIP+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$STRIP"; then
+ ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_STRIP="${ac_tool_prefix}strip"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+STRIP=$ac_cv_prog_STRIP
+if test -n "$STRIP"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5
+$as_echo "$STRIP" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_STRIP"; then
+ ac_ct_STRIP=$STRIP
+ # Extract the first word of "strip", so it can be a program name with args.
+set dummy strip; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_STRIP"; then
+ ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_STRIP="strip"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
+if test -n "$ac_ct_STRIP"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5
+$as_echo "$ac_ct_STRIP" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_STRIP" = x; then
+ STRIP=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ STRIP=$ac_ct_STRIP
+ fi
+else
+ STRIP="$ac_cv_prog_STRIP"
+fi
+
+test -z "$STRIP" && STRIP=:
+
+
+
+
+
+
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_RANLIB+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$RANLIB"; then
+ ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+RANLIB=$ac_cv_prog_RANLIB
+if test -n "$RANLIB"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
+$as_echo "$RANLIB" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_RANLIB"; then
+ ac_ct_RANLIB=$RANLIB
+ # Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_RANLIB"; then
+ ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_RANLIB="ranlib"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
+if test -n "$ac_ct_RANLIB"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5
+$as_echo "$ac_ct_RANLIB" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_RANLIB" = x; then
+ RANLIB=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ RANLIB=$ac_ct_RANLIB
+ fi
+else
+ RANLIB="$ac_cv_prog_RANLIB"
+fi
+
+test -z "$RANLIB" && RANLIB=:
+
+
+
+
+
+
+# Determine commands to create old-style static archives.
+old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs'
+old_postinstall_cmds='chmod 644 $oldlib'
+old_postuninstall_cmds=
+
+if test -n "$RANLIB"; then
+ case $host_os in
+ openbsd*)
+ old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib"
+ ;;
+ *)
+ old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib"
+ ;;
+ esac
+ old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib"
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+
+
+# Check for command to grab the raw symbol name followed by C symbol from nm.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5
+$as_echo_n "checking command to parse $NM output from $compiler object... " >&6; }
+if test "${lt_cv_sys_global_symbol_pipe+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+
+# These are sane defaults that work on at least a few old systems.
+# [They come from Ultrix. What could be older than Ultrix?!! ;)]
+
+# Character class describing NM global symbol codes.
+symcode='[BCDEGRST]'
+
+# Regexp to match symbols that can be accessed directly from C.
+sympat='\([_A-Za-z][_A-Za-z0-9]*\)'
+
+# Define system-specific variables.
+case $host_os in
+aix*)
+ symcode='[BCDT]'
+ ;;
+cygwin* | mingw* | pw32* | cegcc*)
+ symcode='[ABCDGISTW]'
+ ;;
+hpux*)
+ if test "$host_cpu" = ia64; then
+ symcode='[ABCDEGRST]'
+ fi
+ ;;
+irix* | nonstopux*)
+ symcode='[BCDEGRST]'
+ ;;
+osf*)
+ symcode='[BCDEGQRST]'
+ ;;
+solaris*)
+ symcode='[BDRT]'
+ ;;
+sco3.2v5*)
+ symcode='[DT]'
+ ;;
+sysv4.2uw2*)
+ symcode='[DT]'
+ ;;
+sysv5* | sco5v6* | unixware* | OpenUNIX*)
+ symcode='[ABDT]'
+ ;;
+sysv4)
+ symcode='[DFNSTU]'
+ ;;
+esac
+
+# If we're using GNU nm, then use its standard symbol codes.
+case `$NM -V 2>&1` in
+*GNU* | *'with BFD'*)
+ symcode='[ABCDGIRSTW]' ;;
+esac
+
+# Transform an extracted symbol line into a proper C declaration.
+# Some systems (esp. on ia64) link data and code symbols differently,
+# so use this general approach.
+lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'"
+
+# Transform an extracted symbol line into symbol name and symbol address
+lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (void *) \&\2},/p'"
+lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \(lib[^ ]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"lib\2\", (void *) \&\2},/p'"
+
+# Handle CRLF in mingw tool chain
+opt_cr=
+case $build_os in
+mingw*)
+ opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp
+ ;;
+esac
+
+# Try without a prefix underscore, then with it.
+for ac_symprfx in "" "_"; do
+
+ # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol.
+ symxfrm="\\1 $ac_symprfx\\2 \\2"
+
+ # Write the raw and C identifiers.
+ if test "$lt_cv_nm_interface" = "MS dumpbin"; then
+ # Fake it for dumpbin and say T for any non-static function
+ # and D for any global variable.
+ # Also find C++ and __fastcall symbols from MSVC++,
+ # which start with @ or ?.
+ lt_cv_sys_global_symbol_pipe="$AWK '"\
+" {last_section=section; section=\$ 3};"\
+" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\
+" \$ 0!~/External *\|/{next};"\
+" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\
+" {if(hide[section]) next};"\
+" {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\
+" {split(\$ 0, a, /\||\r/); split(a[2], s)};"\
+" s[1]~/^[@?]/{print s[1], s[1]; next};"\
+" s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\
+" ' prfx=^$ac_symprfx"
+ else
+ lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'"
+ fi
+
+ # Check to see that the pipe works correctly.
+ pipe_works=no
+
+ rm -f conftest*
+ cat > conftest.$ac_ext <<_LT_EOF
+#ifdef __cplusplus
+extern "C" {
+#endif
+char nm_test_var;
+void nm_test_func(void);
+void nm_test_func(void){}
+#ifdef __cplusplus
+}
+#endif
+int main(){nm_test_var='a';nm_test_func();return(0);}
+_LT_EOF
+
+ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ # Now try to grab the symbols.
+ nlist=conftest.nm
+ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist\""; } >&5
+ (eval $NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && test -s "$nlist"; then
+ # Try sorting and uniquifying the output.
+ if sort "$nlist" | uniq > "$nlist"T; then
+ mv -f "$nlist"T "$nlist"
+ else
+ rm -f "$nlist"T
+ fi
+
+ # Make sure that we snagged all the symbols we need.
+ if $GREP ' nm_test_var$' "$nlist" >/dev/null; then
+ if $GREP ' nm_test_func$' "$nlist" >/dev/null; then
+ cat <<_LT_EOF > conftest.$ac_ext
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+_LT_EOF
+ # Now generate the symbol file.
+ eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext'
+
+ cat <<_LT_EOF >> conftest.$ac_ext
+
+/* The mapping between symbol names and symbols. */
+const struct {
+ const char *name;
+ void *address;
+}
+lt__PROGRAM__LTX_preloaded_symbols[] =
+{
+ { "@PROGRAM@", (void *) 0 },
+_LT_EOF
+ $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext
+ cat <<\_LT_EOF >> conftest.$ac_ext
+ {0, (void *) 0}
+};
+
+/* This works around a problem in FreeBSD linker */
+#ifdef FREEBSD_WORKAROUND
+static const void *lt_preloaded_setup() {
+ return lt__PROGRAM__LTX_preloaded_symbols;
+}
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+_LT_EOF
+ # Now try linking the two files.
+ mv conftest.$ac_objext conftstm.$ac_objext
+ lt_save_LIBS="$LIBS"
+ lt_save_CFLAGS="$CFLAGS"
+ LIBS="conftstm.$ac_objext"
+ CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag"
+ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && test -s conftest${ac_exeext}; then
+ pipe_works=yes
+ fi
+ LIBS="$lt_save_LIBS"
+ CFLAGS="$lt_save_CFLAGS"
+ else
+ echo "cannot find nm_test_func in $nlist" >&5
+ fi
+ else
+ echo "cannot find nm_test_var in $nlist" >&5
+ fi
+ else
+ echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5
+ fi
+ else
+ echo "$progname: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ fi
+ rm -rf conftest* conftst*
+
+ # Do not use the global_symbol_pipe unless it works.
+ if test "$pipe_works" = yes; then
+ break
+ else
+ lt_cv_sys_global_symbol_pipe=
+ fi
+done
+
+fi
+
+if test -z "$lt_cv_sys_global_symbol_pipe"; then
+ lt_cv_sys_global_symbol_to_cdecl=
+fi
+if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5
+$as_echo "failed" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5
+$as_echo "ok" >&6; }
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# Check whether --enable-libtool-lock was given.
+if test "${enable_libtool_lock+set}" = set; then :
+ enableval=$enable_libtool_lock;
+fi
+
+test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes
+
+# Some flags need to be propagated to the compiler or linker for good
+# libtool support.
+case $host in
+ia64-*-hpux*)
+ # Find out which ABI we are using.
+ echo 'int i;' > conftest.$ac_ext
+ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ case `/usr/bin/file conftest.$ac_objext` in
+ *ELF-32*)
+ HPUX_IA64_MODE="32"
+ ;;
+ *ELF-64*)
+ HPUX_IA64_MODE="64"
+ ;;
+ esac
+ fi
+ rm -rf conftest*
+ ;;
+*-*-irix6*)
+ # Find out which ABI we are using.
+ echo '#line 5597 "configure"' > conftest.$ac_ext
+ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ if test "$lt_cv_prog_gnu_ld" = yes; then
+ case `/usr/bin/file conftest.$ac_objext` in
+ *32-bit*)
+ LD="${LD-ld} -melf32bsmip"
+ ;;
+ *N32*)
+ LD="${LD-ld} -melf32bmipn32"
+ ;;
+ *64-bit*)
+ LD="${LD-ld} -melf64bmip"
+ ;;
+ esac
+ else
+ case `/usr/bin/file conftest.$ac_objext` in
+ *32-bit*)
+ LD="${LD-ld} -32"
+ ;;
+ *N32*)
+ LD="${LD-ld} -n32"
+ ;;
+ *64-bit*)
+ LD="${LD-ld} -64"
+ ;;
+ esac
+ fi
+ fi
+ rm -rf conftest*
+ ;;
+
+x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \
+s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
+ # Find out which ABI we are using.
+ echo 'int i;' > conftest.$ac_ext
+ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ case `/usr/bin/file conftest.o` in
+ *32-bit*)
+ case $host in
+ x86_64-*kfreebsd*-gnu)
+ LD="${LD-ld} -m elf_i386_fbsd"
+ ;;
+ x86_64-*linux*)
+ LD="${LD-ld} -m elf_i386"
+ ;;
+ ppc64-*linux*|powerpc64-*linux*)
+ LD="${LD-ld} -m elf32ppclinux"
+ ;;
+ s390x-*linux*)
+ LD="${LD-ld} -m elf_s390"
+ ;;
+ sparc64-*linux*)
+ LD="${LD-ld} -m elf32_sparc"
+ ;;
+ esac
+ ;;
+ *64-bit*)
+ case $host in
+ x86_64-*kfreebsd*-gnu)
+ LD="${LD-ld} -m elf_x86_64_fbsd"
+ ;;
+ x86_64-*linux*)
+ LD="${LD-ld} -m elf_x86_64"
+ ;;
+ ppc*-*linux*|powerpc*-*linux*)
+ LD="${LD-ld} -m elf64ppc"
+ ;;
+ s390*-*linux*|s390*-*tpf*)
+ LD="${LD-ld} -m elf64_s390"
+ ;;
+ sparc*-*linux*)
+ LD="${LD-ld} -m elf64_sparc"
+ ;;
+ esac
+ ;;
+ esac
+ fi
+ rm -rf conftest*
+ ;;
+
+*-*-sco3.2v5*)
+ # On SCO OpenServer 5, we need -belf to get full-featured binaries.
+ SAVE_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -belf"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5
+$as_echo_n "checking whether the C compiler needs -belf... " >&6; }
+if test "${lt_cv_cc_needs_belf+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ lt_cv_cc_needs_belf=yes
+else
+ lt_cv_cc_needs_belf=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5
+$as_echo "$lt_cv_cc_needs_belf" >&6; }
+ if test x"$lt_cv_cc_needs_belf" != x"yes"; then
+ # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
+ CFLAGS="$SAVE_CFLAGS"
+ fi
+ ;;
+sparc*-*solaris*)
+ # Find out which ABI we are using.
+ echo 'int i;' > conftest.$ac_ext
+ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ case `/usr/bin/file conftest.o` in
+ *64-bit*)
+ case $lt_cv_prog_gnu_ld in
+ yes*) LD="${LD-ld} -m elf64_sparc" ;;
+ *)
+ if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then
+ LD="${LD-ld} -64"
+ fi
+ ;;
+ esac
+ ;;
+ esac
+ fi
+ rm -rf conftest*
+ ;;
+esac
+
+need_locks="$enable_libtool_lock"
+
+
+ case $host_os in
+ rhapsody* | darwin*)
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args.
+set dummy ${ac_tool_prefix}dsymutil; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_DSYMUTIL+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$DSYMUTIL"; then
+ ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+DSYMUTIL=$ac_cv_prog_DSYMUTIL
+if test -n "$DSYMUTIL"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5
+$as_echo "$DSYMUTIL" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_DSYMUTIL"; then
+ ac_ct_DSYMUTIL=$DSYMUTIL
+ # Extract the first word of "dsymutil", so it can be a program name with args.
+set dummy dsymutil; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_DSYMUTIL+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_DSYMUTIL"; then
+ ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_DSYMUTIL="dsymutil"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL
+if test -n "$ac_ct_DSYMUTIL"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5
+$as_echo "$ac_ct_DSYMUTIL" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_DSYMUTIL" = x; then
+ DSYMUTIL=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ DSYMUTIL=$ac_ct_DSYMUTIL
+ fi
+else
+ DSYMUTIL="$ac_cv_prog_DSYMUTIL"
+fi
+
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args.
+set dummy ${ac_tool_prefix}nmedit; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_NMEDIT+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$NMEDIT"; then
+ ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+NMEDIT=$ac_cv_prog_NMEDIT
+if test -n "$NMEDIT"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5
+$as_echo "$NMEDIT" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_NMEDIT"; then
+ ac_ct_NMEDIT=$NMEDIT
+ # Extract the first word of "nmedit", so it can be a program name with args.
+set dummy nmedit; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_NMEDIT+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_NMEDIT"; then
+ ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_NMEDIT="nmedit"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT
+if test -n "$ac_ct_NMEDIT"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5
+$as_echo "$ac_ct_NMEDIT" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_NMEDIT" = x; then
+ NMEDIT=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ NMEDIT=$ac_ct_NMEDIT
+ fi
+else
+ NMEDIT="$ac_cv_prog_NMEDIT"
+fi
+
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}lipo", so it can be a program name with args.
+set dummy ${ac_tool_prefix}lipo; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_LIPO+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$LIPO"; then
+ ac_cv_prog_LIPO="$LIPO" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_LIPO="${ac_tool_prefix}lipo"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+LIPO=$ac_cv_prog_LIPO
+if test -n "$LIPO"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5
+$as_echo "$LIPO" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_LIPO"; then
+ ac_ct_LIPO=$LIPO
+ # Extract the first word of "lipo", so it can be a program name with args.
+set dummy lipo; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_LIPO+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_LIPO"; then
+ ac_cv_prog_ac_ct_LIPO="$ac_ct_LIPO" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_LIPO="lipo"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO
+if test -n "$ac_ct_LIPO"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5
+$as_echo "$ac_ct_LIPO" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_LIPO" = x; then
+ LIPO=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ LIPO=$ac_ct_LIPO
+ fi
+else
+ LIPO="$ac_cv_prog_LIPO"
+fi
+
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}otool", so it can be a program name with args.
+set dummy ${ac_tool_prefix}otool; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_OTOOL+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$OTOOL"; then
+ ac_cv_prog_OTOOL="$OTOOL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_OTOOL="${ac_tool_prefix}otool"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+OTOOL=$ac_cv_prog_OTOOL
+if test -n "$OTOOL"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5
+$as_echo "$OTOOL" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_OTOOL"; then
+ ac_ct_OTOOL=$OTOOL
+ # Extract the first word of "otool", so it can be a program name with args.
+set dummy otool; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_OTOOL+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_OTOOL"; then
+ ac_cv_prog_ac_ct_OTOOL="$ac_ct_OTOOL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_OTOOL="otool"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL
+if test -n "$ac_ct_OTOOL"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5
+$as_echo "$ac_ct_OTOOL" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_OTOOL" = x; then
+ OTOOL=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ OTOOL=$ac_ct_OTOOL
+ fi
+else
+ OTOOL="$ac_cv_prog_OTOOL"
+fi
+
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}otool64", so it can be a program name with args.
+set dummy ${ac_tool_prefix}otool64; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_OTOOL64+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$OTOOL64"; then
+ ac_cv_prog_OTOOL64="$OTOOL64" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+OTOOL64=$ac_cv_prog_OTOOL64
+if test -n "$OTOOL64"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5
+$as_echo "$OTOOL64" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_OTOOL64"; then
+ ac_ct_OTOOL64=$OTOOL64
+ # Extract the first word of "otool64", so it can be a program name with args.
+set dummy otool64; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_OTOOL64+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_OTOOL64"; then
+ ac_cv_prog_ac_ct_OTOOL64="$ac_ct_OTOOL64" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_OTOOL64="otool64"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64
+if test -n "$ac_ct_OTOOL64"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5
+$as_echo "$ac_ct_OTOOL64" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_OTOOL64" = x; then
+ OTOOL64=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ OTOOL64=$ac_ct_OTOOL64
+ fi
+else
+ OTOOL64="$ac_cv_prog_OTOOL64"
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5
+$as_echo_n "checking for -single_module linker flag... " >&6; }
+if test "${lt_cv_apple_cc_single_mod+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ lt_cv_apple_cc_single_mod=no
+ if test -z "${LT_MULTI_MODULE}"; then
+ # By default we will add the -single_module flag. You can override
+ # by either setting the environment variable LT_MULTI_MODULE
+ # non-empty at configure time, or by adding -multi_module to the
+ # link flags.
+ rm -rf libconftest.dylib*
+ echo "int foo(void){return 1;}" > conftest.c
+ echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
+-dynamiclib -Wl,-single_module conftest.c" >&5
+ $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
+ -dynamiclib -Wl,-single_module conftest.c 2>conftest.err
+ _lt_result=$?
+ if test -f libconftest.dylib && test ! -s conftest.err && test $_lt_result = 0; then
+ lt_cv_apple_cc_single_mod=yes
+ else
+ cat conftest.err >&5
+ fi
+ rm -rf libconftest.dylib*
+ rm -f conftest.*
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5
+$as_echo "$lt_cv_apple_cc_single_mod" >&6; }
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5
+$as_echo_n "checking for -exported_symbols_list linker flag... " >&6; }
+if test "${lt_cv_ld_exported_symbols_list+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ lt_cv_ld_exported_symbols_list=no
+ save_LDFLAGS=$LDFLAGS
+ echo "_main" > conftest.sym
+ LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ lt_cv_ld_exported_symbols_list=yes
+else
+ lt_cv_ld_exported_symbols_list=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ LDFLAGS="$save_LDFLAGS"
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5
+$as_echo "$lt_cv_ld_exported_symbols_list" >&6; }
+ case $host_os in
+ rhapsody* | darwin1.[012])
+ _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;;
+ darwin1.*)
+ _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;;
+ darwin*) # darwin 5.x on
+ # if running on 10.5 or later, the deployment target defaults
+ # to the OS version, if on x86, and 10.4, the deployment
+ # target defaults to 10.4. Don't you love it?
+ case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in
+ 10.0,*86*-darwin8*|10.0,*-darwin[91]*)
+ _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;;
+ 10.[012]*)
+ _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;;
+ 10.*)
+ _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;;
+ esac
+ ;;
+ esac
+ if test "$lt_cv_apple_cc_single_mod" = "yes"; then
+ _lt_dar_single_mod='$single_module'
+ fi
+ if test "$lt_cv_ld_exported_symbols_list" = "yes"; then
+ _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym'
+ else
+ _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ fi
+ if test "$DSYMUTIL" != ":"; then
+ _lt_dsymutil='~$DSYMUTIL $lib || :'
+ else
+ _lt_dsymutil=
+ fi
+ ;;
+ esac
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
+$as_echo_n "checking how to run the C preprocessor... " >&6; }
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+ CPP=
+fi
+if test -z "$CPP"; then
+ if test "${ac_cv_prog_CPP+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ # Double quotes because CPP needs to be expanded
+ for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+ do
+ ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+ # Broken: success on invalid input.
+continue
+else
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+ break
+fi
+
+ done
+ ac_cv_prog_CPP=$CPP
+
+fi
+ CPP=$ac_cv_prog_CPP
+else
+ ac_cv_prog_CPP=$CPP
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
+$as_echo "$CPP" >&6; }
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+ # Broken: success on invalid input.
+continue
+else
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+
+else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error "C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." "$LINENO" 5; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
+$as_echo_n "checking for ANSI C header files... " >&6; }
+if test "${ac_cv_header_stdc+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_header_stdc=yes
+else
+ ac_cv_header_stdc=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+ # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "memchr" >/dev/null 2>&1; then :
+
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "free" >/dev/null 2>&1; then :
+
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+ if test "$cross_compiling" = yes; then :
+ :
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ctype.h>
+#include <stdlib.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+ (('a' <= (c) && (c) <= 'i') \
+ || ('j' <= (c) && (c) <= 'r') \
+ || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+ int i;
+ for (i = 0; i < 256; i++)
+ if (XOR (islower (i), ISLOWER (i))
+ || toupper (i) != TOUPPER (i))
+ return 2;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+
+else
+ ac_cv_header_stdc=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5
+$as_echo "$ac_cv_header_stdc" >&6; }
+if test $ac_cv_header_stdc = yes; then
+
+$as_echo "#define STDC_HEADERS 1" >>confdefs.h
+
+fi
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+ inttypes.h stdint.h unistd.h
+do :
+ as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
+"
+eval as_val=\$$as_ac_Header
+ if test "x$as_val" = x""yes; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+for ac_header in dlfcn.h
+do :
+ ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default
+"
+if test "x$ac_cv_header_dlfcn_h" = x""yes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_DLFCN_H 1
+_ACEOF
+
+fi
+
+done
+
+
+
+# Set options
+
+
+
+ enable_dlopen=no
+
+
+ enable_win32_dll=no
+
+
+ # Check whether --enable-shared was given.
+if test "${enable_shared+set}" = set; then :
+ enableval=$enable_shared; p=${PACKAGE-default}
+ case $enableval in
+ yes) enable_shared=yes ;;
+ no) enable_shared=no ;;
+ *)
+ enable_shared=no
+ # Look at the argument we got. We use all the common list separators.
+ lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+ for pkg in $enableval; do
+ IFS="$lt_save_ifs"
+ if test "X$pkg" = "X$p"; then
+ enable_shared=yes
+ fi
+ done
+ IFS="$lt_save_ifs"
+ ;;
+ esac
+else
+ enable_shared=yes
+fi
+
+
+
+
+
+
+
+
+
+ # Check whether --enable-static was given.
+if test "${enable_static+set}" = set; then :
+ enableval=$enable_static; p=${PACKAGE-default}
+ case $enableval in
+ yes) enable_static=yes ;;
+ no) enable_static=no ;;
+ *)
+ enable_static=no
+ # Look at the argument we got. We use all the common list separators.
+ lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+ for pkg in $enableval; do
+ IFS="$lt_save_ifs"
+ if test "X$pkg" = "X$p"; then
+ enable_static=yes
+ fi
+ done
+ IFS="$lt_save_ifs"
+ ;;
+ esac
+else
+ enable_static=yes
+fi
+
+
+
+
+
+
+
+
+
+
+# Check whether --with-pic was given.
+if test "${with_pic+set}" = set; then :
+ withval=$with_pic; pic_mode="$withval"
+else
+ pic_mode=default
+fi
+
+
+test -z "$pic_mode" && pic_mode=default
+
+
+
+
+
+
+
+ # Check whether --enable-fast-install was given.
+if test "${enable_fast_install+set}" = set; then :
+ enableval=$enable_fast_install; p=${PACKAGE-default}
+ case $enableval in
+ yes) enable_fast_install=yes ;;
+ no) enable_fast_install=no ;;
+ *)
+ enable_fast_install=no
+ # Look at the argument we got. We use all the common list separators.
+ lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+ for pkg in $enableval; do
+ IFS="$lt_save_ifs"
+ if test "X$pkg" = "X$p"; then
+ enable_fast_install=yes
+ fi
+ done
+ IFS="$lt_save_ifs"
+ ;;
+ esac
+else
+ enable_fast_install=yes
+fi
+
+
+
+
+
+
+
+
+
+
+
+# This can be used to rebuild libtool when needed
+LIBTOOL_DEPS="$ltmain"
+
+# Always use our own libtool.
+LIBTOOL='$(SHELL) $(top_builddir)/libtool'
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+test -z "$LN_S" && LN_S="ln -s"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+if test -n "${ZSH_VERSION+set}" ; then
+ setopt NO_GLOB_SUBST
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5
+$as_echo_n "checking for objdir... " >&6; }
+if test "${lt_cv_objdir+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ rm -f .libs 2>/dev/null
+mkdir .libs 2>/dev/null
+if test -d .libs; then
+ lt_cv_objdir=.libs
+else
+ # MS-DOS does not allow filenames that begin with a dot.
+ lt_cv_objdir=_libs
+fi
+rmdir .libs 2>/dev/null
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5
+$as_echo "$lt_cv_objdir" >&6; }
+objdir=$lt_cv_objdir
+
+
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define LT_OBJDIR "$lt_cv_objdir/"
+_ACEOF
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+case $host_os in
+aix3*)
+ # AIX sometimes has problems with the GCC collect2 program. For some
+ # reason, if we set the COLLECT_NAMES environment variable, the problems
+ # vanish in a puff of smoke.
+ if test "X${COLLECT_NAMES+set}" != Xset; then
+ COLLECT_NAMES=
+ export COLLECT_NAMES
+ fi
+ ;;
+esac
+
+# Sed substitution that helps us do robust quoting. It backslashifies
+# metacharacters that are still active within double-quoted strings.
+sed_quote_subst='s/\(["`$\\]\)/\\\1/g'
+
+# Same as above, but do not quote variable references.
+double_quote_subst='s/\(["`\\]\)/\\\1/g'
+
+# Sed substitution to delay expansion of an escaped shell variable in a
+# double_quote_subst'ed string.
+delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
+
+# Sed substitution to delay expansion of an escaped single quote.
+delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g'
+
+# Sed substitution to avoid accidental globbing in evaled expressions
+no_glob_subst='s/\*/\\\*/g'
+
+# Global variables:
+ofile=libtool
+can_build_shared=yes
+
+# All known linkers require a `.a' archive for static linking (except MSVC,
+# which needs '.lib').
+libext=a
+
+with_gnu_ld="$lt_cv_prog_gnu_ld"
+
+old_CC="$CC"
+old_CFLAGS="$CFLAGS"
+
+# Set sane defaults for various variables
+test -z "$CC" && CC=cc
+test -z "$LTCC" && LTCC=$CC
+test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS
+test -z "$LD" && LD=ld
+test -z "$ac_objext" && ac_objext=o
+
+for cc_temp in $compiler""; do
+ case $cc_temp in
+ compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+ distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+ \-*) ;;
+ *) break;;
+ esac
+done
+cc_basename=`$ECHO "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
+
+
+# Only perform the check for file, if the check method requires it
+test -z "$MAGIC_CMD" && MAGIC_CMD=file
+case $deplibs_check_method in
+file_magic*)
+ if test "$file_magic_cmd" = '$MAGIC_CMD'; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5
+$as_echo_n "checking for ${ac_tool_prefix}file... " >&6; }
+if test "${lt_cv_path_MAGIC_CMD+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $MAGIC_CMD in
+[\\/*] | ?:[\\/]*)
+ lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path.
+ ;;
+*)
+ lt_save_MAGIC_CMD="$MAGIC_CMD"
+ lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+ ac_dummy="/usr/bin$PATH_SEPARATOR$PATH"
+ for ac_dir in $ac_dummy; do
+ IFS="$lt_save_ifs"
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/${ac_tool_prefix}file; then
+ lt_cv_path_MAGIC_CMD="$ac_dir/${ac_tool_prefix}file"
+ if test -n "$file_magic_test_file"; then
+ case $deplibs_check_method in
+ "file_magic "*)
+ file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
+ MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+ if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+ $EGREP "$file_magic_regex" > /dev/null; then
+ :
+ else
+ cat <<_LT_EOF 1>&2
+
+*** Warning: the command libtool uses to detect shared libraries,
+*** $file_magic_cmd, produces output that libtool cannot recognize.
+*** The result is that libtool may fail to recognize shared libraries
+*** as such. This will affect the creation of libtool libraries that
+*** depend on shared libraries, but programs linked with such libtool
+*** libraries will work regardless of this problem. Nevertheless, you
+*** may want to report the problem to your system manager and/or to
+*** bug-libtool@gnu.org
+
+_LT_EOF
+ fi ;;
+ esac
+ fi
+ break
+ fi
+ done
+ IFS="$lt_save_ifs"
+ MAGIC_CMD="$lt_save_MAGIC_CMD"
+ ;;
+esac
+fi
+
+MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+if test -n "$MAGIC_CMD"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5
+$as_echo "$MAGIC_CMD" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+
+
+
+if test -z "$lt_cv_path_MAGIC_CMD"; then
+ if test -n "$ac_tool_prefix"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for file" >&5
+$as_echo_n "checking for file... " >&6; }
+if test "${lt_cv_path_MAGIC_CMD+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $MAGIC_CMD in
+[\\/*] | ?:[\\/]*)
+ lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path.
+ ;;
+*)
+ lt_save_MAGIC_CMD="$MAGIC_CMD"
+ lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+ ac_dummy="/usr/bin$PATH_SEPARATOR$PATH"
+ for ac_dir in $ac_dummy; do
+ IFS="$lt_save_ifs"
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/file; then
+ lt_cv_path_MAGIC_CMD="$ac_dir/file"
+ if test -n "$file_magic_test_file"; then
+ case $deplibs_check_method in
+ "file_magic "*)
+ file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
+ MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+ if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+ $EGREP "$file_magic_regex" > /dev/null; then
+ :
+ else
+ cat <<_LT_EOF 1>&2
+
+*** Warning: the command libtool uses to detect shared libraries,
+*** $file_magic_cmd, produces output that libtool cannot recognize.
+*** The result is that libtool may fail to recognize shared libraries
+*** as such. This will affect the creation of libtool libraries that
+*** depend on shared libraries, but programs linked with such libtool
+*** libraries will work regardless of this problem. Nevertheless, you
+*** may want to report the problem to your system manager and/or to
+*** bug-libtool@gnu.org
+
+_LT_EOF
+ fi ;;
+ esac
+ fi
+ break
+ fi
+ done
+ IFS="$lt_save_ifs"
+ MAGIC_CMD="$lt_save_MAGIC_CMD"
+ ;;
+esac
+fi
+
+MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+if test -n "$MAGIC_CMD"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5
+$as_echo "$MAGIC_CMD" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ else
+ MAGIC_CMD=:
+ fi
+fi
+
+ fi
+ ;;
+esac
+
+# Use C for the default configuration in the libtool script
+
+lt_save_CC="$CC"
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+# Source file extension for C test sources.
+ac_ext=c
+
+# Object file extension for compiled C test sources.
+objext=o
+objext=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="int some_variable = 0;"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='int main(){return(0);}'
+
+
+
+
+
+
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+
+# Save the default compiler, since it gets overwritten when the other
+# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP.
+compiler_DEFAULT=$CC
+
+# save warnings/boilerplate of simple test code
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_compile_test_code" >conftest.$ac_ext
+eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_compiler_boilerplate=`cat conftest.err`
+$RM conftest*
+
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_link_test_code" >conftest.$ac_ext
+eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_linker_boilerplate=`cat conftest.err`
+$RM -r conftest*
+
+
+if test -n "$compiler"; then
+
+lt_prog_compiler_no_builtin_flag=
+
+if test "$GCC" = yes; then
+ lt_prog_compiler_no_builtin_flag=' -fno-builtin'
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5
+$as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; }
+if test "${lt_cv_prog_compiler_rtti_exceptions+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ lt_cv_prog_compiler_rtti_exceptions=no
+ ac_outfile=conftest.$ac_objext
+ echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+ lt_compiler_flag="-fno-rtti -fno-exceptions"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ # The option is referenced via a variable to avoid confusing sed.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:7123: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>conftest.err)
+ ac_status=$?
+ cat conftest.err >&5
+ echo "$as_me:7127: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s "$ac_outfile"; then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings other than the usual output.
+ $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+ lt_cv_prog_compiler_rtti_exceptions=yes
+ fi
+ fi
+ $RM conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5
+$as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; }
+
+if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then
+ lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions"
+else
+ :
+fi
+
+fi
+
+
+
+
+
+
+ lt_prog_compiler_wl=
+lt_prog_compiler_pic=
+lt_prog_compiler_static=
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5
+$as_echo_n "checking for $compiler option to produce PIC... " >&6; }
+
+ if test "$GCC" = yes; then
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_static='-static'
+
+ case $host_os in
+ aix*)
+ # All AIX code is PIC.
+ if test "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ lt_prog_compiler_static='-Bstatic'
+ fi
+ ;;
+
+ amigaos*)
+ case $host_cpu in
+ powerpc)
+ # see comment about AmigaOS4 .so support
+ lt_prog_compiler_pic='-fPIC'
+ ;;
+ m68k)
+ # FIXME: we need at least 68020 code to build shared libraries, but
+ # adding the `-m68020' flag to GCC prevents building anything better,
+ # like `-m68040'.
+ lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4'
+ ;;
+ esac
+ ;;
+
+ beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+ # PIC is the default for these OSes.
+ ;;
+
+ mingw* | cygwin* | pw32* | os2* | cegcc*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ # Although the cygwin gcc ignores -fPIC, still need this for old-style
+ # (--disable-auto-import) libraries
+ lt_prog_compiler_pic='-DDLL_EXPORT'
+ ;;
+
+ darwin* | rhapsody*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ lt_prog_compiler_pic='-fno-common'
+ ;;
+
+ hpux*)
+ # PIC is the default for 64-bit PA HP-UX, but not for 32-bit
+ # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag
+ # sets the default TLS model and affects inlining.
+ case $host_cpu in
+ hppa*64*)
+ # +Z the default
+ ;;
+ *)
+ lt_prog_compiler_pic='-fPIC'
+ ;;
+ esac
+ ;;
+
+ interix[3-9]*)
+ # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+ # Instead, we relocate shared libraries at runtime.
+ ;;
+
+ msdosdjgpp*)
+ # Just because we use GCC doesn't mean we suddenly get shared libraries
+ # on systems that don't support them.
+ lt_prog_compiler_can_build_shared=no
+ enable_shared=no
+ ;;
+
+ *nto* | *qnx*)
+ # QNX uses GNU C++, but need to define -shared option too, otherwise
+ # it will coredump.
+ lt_prog_compiler_pic='-fPIC -shared'
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ lt_prog_compiler_pic=-Kconform_pic
+ fi
+ ;;
+
+ *)
+ lt_prog_compiler_pic='-fPIC'
+ ;;
+ esac
+ else
+ # PORTME Check for flag to pass linker flags through the system compiler.
+ case $host_os in
+ aix*)
+ lt_prog_compiler_wl='-Wl,'
+ if test "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ lt_prog_compiler_static='-Bstatic'
+ else
+ lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp'
+ fi
+ ;;
+
+ mingw* | cygwin* | pw32* | os2* | cegcc*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ lt_prog_compiler_pic='-DDLL_EXPORT'
+ ;;
+
+ hpux9* | hpux10* | hpux11*)
+ lt_prog_compiler_wl='-Wl,'
+ # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+ # not for PA HP-UX.
+ case $host_cpu in
+ hppa*64*|ia64*)
+ # +Z the default
+ ;;
+ *)
+ lt_prog_compiler_pic='+Z'
+ ;;
+ esac
+ # Is there a better lt_prog_compiler_static that works with the bundled CC?
+ lt_prog_compiler_static='${wl}-a ${wl}archive'
+ ;;
+
+ irix5* | irix6* | nonstopux*)
+ lt_prog_compiler_wl='-Wl,'
+ # PIC (with -KPIC) is the default.
+ lt_prog_compiler_static='-non_shared'
+ ;;
+
+ linux* | k*bsd*-gnu)
+ case $cc_basename in
+ # old Intel for x86_64 which still supported -KPIC.
+ ecc*)
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_pic='-KPIC'
+ lt_prog_compiler_static='-static'
+ ;;
+ # icc used to be incompatible with GCC.
+ # ICC 10 doesn't accept -KPIC any more.
+ icc* | ifort*)
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_pic='-fPIC'
+ lt_prog_compiler_static='-static'
+ ;;
+ # Lahey Fortran 8.1.
+ lf95*)
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_pic='--shared'
+ lt_prog_compiler_static='--static'
+ ;;
+ pgcc* | pgf77* | pgf90* | pgf95*)
+ # Portland Group compilers (*not* the Pentium gcc compiler,
+ # which looks to be a dead project)
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_pic='-fpic'
+ lt_prog_compiler_static='-Bstatic'
+ ;;
+ ccc*)
+ lt_prog_compiler_wl='-Wl,'
+ # All Alpha code is PIC.
+ lt_prog_compiler_static='-non_shared'
+ ;;
+ xl*)
+ # IBM XL C 8.0/Fortran 10.1 on PPC
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_pic='-qpic'
+ lt_prog_compiler_static='-qstaticlink'
+ ;;
+ *)
+ case `$CC -V 2>&1 | sed 5q` in
+ *Sun\ C*)
+ # Sun C 5.9
+ lt_prog_compiler_pic='-KPIC'
+ lt_prog_compiler_static='-Bstatic'
+ lt_prog_compiler_wl='-Wl,'
+ ;;
+ *Sun\ F*)
+ # Sun Fortran 8.3 passes all unrecognized flags to the linker
+ lt_prog_compiler_pic='-KPIC'
+ lt_prog_compiler_static='-Bstatic'
+ lt_prog_compiler_wl=''
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+
+ newsos6)
+ lt_prog_compiler_pic='-KPIC'
+ lt_prog_compiler_static='-Bstatic'
+ ;;
+
+ *nto* | *qnx*)
+ # QNX uses GNU C++, but need to define -shared option too, otherwise
+ # it will coredump.
+ lt_prog_compiler_pic='-fPIC -shared'
+ ;;
+
+ osf3* | osf4* | osf5*)
+ lt_prog_compiler_wl='-Wl,'
+ # All OSF/1 code is PIC.
+ lt_prog_compiler_static='-non_shared'
+ ;;
+
+ rdos*)
+ lt_prog_compiler_static='-non_shared'
+ ;;
+
+ solaris*)
+ lt_prog_compiler_pic='-KPIC'
+ lt_prog_compiler_static='-Bstatic'
+ case $cc_basename in
+ f77* | f90* | f95*)
+ lt_prog_compiler_wl='-Qoption ld ';;
+ *)
+ lt_prog_compiler_wl='-Wl,';;
+ esac
+ ;;
+
+ sunos4*)
+ lt_prog_compiler_wl='-Qoption ld '
+ lt_prog_compiler_pic='-PIC'
+ lt_prog_compiler_static='-Bstatic'
+ ;;
+
+ sysv4 | sysv4.2uw2* | sysv4.3*)
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_pic='-KPIC'
+ lt_prog_compiler_static='-Bstatic'
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec ;then
+ lt_prog_compiler_pic='-Kconform_pic'
+ lt_prog_compiler_static='-Bstatic'
+ fi
+ ;;
+
+ sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_pic='-KPIC'
+ lt_prog_compiler_static='-Bstatic'
+ ;;
+
+ unicos*)
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_can_build_shared=no
+ ;;
+
+ uts4*)
+ lt_prog_compiler_pic='-pic'
+ lt_prog_compiler_static='-Bstatic'
+ ;;
+
+ *)
+ lt_prog_compiler_can_build_shared=no
+ ;;
+ esac
+ fi
+
+case $host_os in
+ # For platforms which do not support PIC, -DPIC is meaningless:
+ *djgpp*)
+ lt_prog_compiler_pic=
+ ;;
+ *)
+ lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC"
+ ;;
+esac
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_prog_compiler_pic" >&5
+$as_echo "$lt_prog_compiler_pic" >&6; }
+
+
+
+
+
+
+#
+# Check to make sure the PIC flag actually works.
+#
+if test -n "$lt_prog_compiler_pic"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5
+$as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; }
+if test "${lt_cv_prog_compiler_pic_works+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ lt_cv_prog_compiler_pic_works=no
+ ac_outfile=conftest.$ac_objext
+ echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+ lt_compiler_flag="$lt_prog_compiler_pic -DPIC"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ # The option is referenced via a variable to avoid confusing sed.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:7462: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>conftest.err)
+ ac_status=$?
+ cat conftest.err >&5
+ echo "$as_me:7466: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s "$ac_outfile"; then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings other than the usual output.
+ $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+ lt_cv_prog_compiler_pic_works=yes
+ fi
+ fi
+ $RM conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5
+$as_echo "$lt_cv_prog_compiler_pic_works" >&6; }
+
+if test x"$lt_cv_prog_compiler_pic_works" = xyes; then
+ case $lt_prog_compiler_pic in
+ "" | " "*) ;;
+ *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;;
+ esac
+else
+ lt_prog_compiler_pic=
+ lt_prog_compiler_can_build_shared=no
+fi
+
+fi
+
+
+
+
+
+
+#
+# Check to make sure the static flag actually works.
+#
+wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5
+$as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; }
+if test "${lt_cv_prog_compiler_static_works+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ lt_cv_prog_compiler_static_works=no
+ save_LDFLAGS="$LDFLAGS"
+ LDFLAGS="$LDFLAGS $lt_tmp_static_flag"
+ echo "$lt_simple_link_test_code" > conftest.$ac_ext
+ if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+ # The linker can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ if test -s conftest.err; then
+ # Append any errors to the config.log.
+ cat conftest.err 1>&5
+ $ECHO "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if diff conftest.exp conftest.er2 >/dev/null; then
+ lt_cv_prog_compiler_static_works=yes
+ fi
+ else
+ lt_cv_prog_compiler_static_works=yes
+ fi
+ fi
+ $RM -r conftest*
+ LDFLAGS="$save_LDFLAGS"
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5
+$as_echo "$lt_cv_prog_compiler_static_works" >&6; }
+
+if test x"$lt_cv_prog_compiler_static_works" = xyes; then
+ :
+else
+ lt_prog_compiler_static=
+fi
+
+
+
+
+
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5
+$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; }
+if test "${lt_cv_prog_compiler_c_o+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ lt_cv_prog_compiler_c_o=no
+ $RM -r conftest 2>/dev/null
+ mkdir conftest
+ cd conftest
+ mkdir out
+ echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ lt_compiler_flag="-o out/conftest2.$ac_objext"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:7567: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>out/conftest.err)
+ ac_status=$?
+ cat out/conftest.err >&5
+ echo "$as_me:7571: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s out/conftest2.$ac_objext
+ then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp
+ $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+ if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+ lt_cv_prog_compiler_c_o=yes
+ fi
+ fi
+ chmod u+w . 2>&5
+ $RM conftest*
+ # SGI C++ compiler will create directory out/ii_files/ for
+ # template instantiation
+ test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files
+ $RM out/* && rmdir out
+ cd ..
+ $RM -r conftest
+ $RM conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5
+$as_echo "$lt_cv_prog_compiler_c_o" >&6; }
+
+
+
+
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5
+$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; }
+if test "${lt_cv_prog_compiler_c_o+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ lt_cv_prog_compiler_c_o=no
+ $RM -r conftest 2>/dev/null
+ mkdir conftest
+ cd conftest
+ mkdir out
+ echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ lt_compiler_flag="-o out/conftest2.$ac_objext"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:7622: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>out/conftest.err)
+ ac_status=$?
+ cat out/conftest.err >&5
+ echo "$as_me:7626: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s out/conftest2.$ac_objext
+ then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp
+ $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+ if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+ lt_cv_prog_compiler_c_o=yes
+ fi
+ fi
+ chmod u+w . 2>&5
+ $RM conftest*
+ # SGI C++ compiler will create directory out/ii_files/ for
+ # template instantiation
+ test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files
+ $RM out/* && rmdir out
+ cd ..
+ $RM -r conftest
+ $RM conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5
+$as_echo "$lt_cv_prog_compiler_c_o" >&6; }
+
+
+
+
+hard_links="nottested"
+if test "$lt_cv_prog_compiler_c_o" = no && test "$need_locks" != no; then
+ # do not overwrite the value of need_locks provided by the user
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5
+$as_echo_n "checking if we can lock with hard links... " >&6; }
+ hard_links=yes
+ $RM conftest*
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ touch conftest.a
+ ln conftest.a conftest.b 2>&5 || hard_links=no
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5
+$as_echo "$hard_links" >&6; }
+ if test "$hard_links" = no; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5
+$as_echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;}
+ need_locks=warn
+ fi
+else
+ need_locks=no
+fi
+
+
+
+
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5
+$as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; }
+
+ runpath_var=
+ allow_undefined_flag=
+ always_export_symbols=no
+ archive_cmds=
+ archive_expsym_cmds=
+ compiler_needs_object=no
+ enable_shared_with_static_runtimes=no
+ export_dynamic_flag_spec=
+ export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+ hardcode_automatic=no
+ hardcode_direct=no
+ hardcode_direct_absolute=no
+ hardcode_libdir_flag_spec=
+ hardcode_libdir_flag_spec_ld=
+ hardcode_libdir_separator=
+ hardcode_minus_L=no
+ hardcode_shlibpath_var=unsupported
+ inherit_rpath=no
+ link_all_deplibs=unknown
+ module_cmds=
+ module_expsym_cmds=
+ old_archive_from_new_cmds=
+ old_archive_from_expsyms_cmds=
+ thread_safe_flag_spec=
+ whole_archive_flag_spec=
+ # include_expsyms should be a list of space-separated symbols to be *always*
+ # included in the symbol list
+ include_expsyms=
+ # exclude_expsyms can be an extended regexp of symbols to exclude
+ # it will be wrapped by ` (' and `)$', so one must not match beginning or
+ # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc',
+ # as well as any symbol that contains `d'.
+ exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'
+ # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
+ # platforms (ab)use it in PIC code, but their linkers get confused if
+ # the symbol is explicitly referenced. Since portable code cannot
+ # rely on this symbol name, it's probably fine to never include it in
+ # preloaded symbol tables.
+ # Exclude shared library initialization/finalization symbols.
+ extract_expsyms_cmds=
+
+ case $host_os in
+ cygwin* | mingw* | pw32* | cegcc*)
+ # FIXME: the MSVC++ port hasn't been tested in a loooong time
+ # When not using gcc, we currently assume that we are using
+ # Microsoft Visual C++.
+ if test "$GCC" != yes; then
+ with_gnu_ld=no
+ fi
+ ;;
+ interix*)
+ # we just hope/assume this is gcc and not c89 (= MSVC++)
+ with_gnu_ld=yes
+ ;;
+ openbsd*)
+ with_gnu_ld=no
+ ;;
+ linux* | k*bsd*-gnu)
+ link_all_deplibs=no
+ ;;
+ esac
+
+ ld_shlibs=yes
+ if test "$with_gnu_ld" = yes; then
+ # If archive_cmds runs LD, not CC, wlarc should be empty
+ wlarc='${wl}'
+
+ # Set some defaults for GNU ld with shared library support. These
+ # are reset later if shared libraries are not supported. Putting them
+ # here allows them to be overridden if necessary.
+ runpath_var=LD_RUN_PATH
+ hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+ export_dynamic_flag_spec='${wl}--export-dynamic'
+ # ancient GNU ld didn't support --whole-archive et. al.
+ if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then
+ whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+ else
+ whole_archive_flag_spec=
+ fi
+ supports_anon_versioning=no
+ case `$LD -v 2>&1` in
+ *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11
+ *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
+ *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...
+ *\ 2.11.*) ;; # other 2.11 versions
+ *) supports_anon_versioning=yes ;;
+ esac
+
+ # See if GNU ld supports shared libraries.
+ case $host_os in
+ aix[3-9]*)
+ # On AIX/PPC, the GNU linker is very broken
+ if test "$host_cpu" != ia64; then
+ ld_shlibs=no
+ cat <<_LT_EOF 1>&2
+
+*** Warning: the GNU linker, at least up to release 2.9.1, is reported
+*** to be unable to reliably create shared libraries on AIX.
+*** Therefore, libtool is disabling shared libraries support. If you
+*** really care for shared libraries, you may want to modify your PATH
+*** so that a non-GNU linker is found, and then restart.
+
+_LT_EOF
+ fi
+ ;;
+
+ amigaos*)
+ case $host_cpu in
+ powerpc)
+ # see comment about AmigaOS4 .so support
+ archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds=''
+ ;;
+ m68k)
+ archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_minus_L=yes
+ ;;
+ esac
+ ;;
+
+ beos*)
+ if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+ allow_undefined_flag=unsupported
+ # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+ # support --undefined. This deserves some investigation. FIXME
+ archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ else
+ ld_shlibs=no
+ fi
+ ;;
+
+ cygwin* | mingw* | pw32* | cegcc*)
+ # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless,
+ # as there is no search path for DLLs.
+ hardcode_libdir_flag_spec='-L$libdir'
+ allow_undefined_flag=unsupported
+ always_export_symbols=no
+ enable_shared_with_static_runtimes=yes
+ export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols'
+
+ if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
+ archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ # If the export-symbols file already is a .def file (1st line
+ # is EXPORTS), use it as is; otherwise, prepend...
+ archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+ cp $export_symbols $output_objdir/$soname.def;
+ else
+ echo EXPORTS > $output_objdir/$soname.def;
+ cat $export_symbols >> $output_objdir/$soname.def;
+ fi~
+ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ else
+ ld_shlibs=no
+ fi
+ ;;
+
+ interix[3-9]*)
+ hardcode_direct=no
+ hardcode_shlibpath_var=no
+ hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
+ export_dynamic_flag_spec='${wl}-E'
+ # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+ # Instead, shared libraries are loaded at an image base (0x10000000 by
+ # default) and relocated if they conflict, which is a slow very memory
+ # consuming and fragmenting process. To avoid this, we pick a random,
+ # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+ # time. Moving up from 0x10000000 also allows more sbrk(2) space.
+ archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ archive_expsym_cmds='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ ;;
+
+ gnu* | linux* | tpf* | k*bsd*-gnu)
+ tmp_diet=no
+ if test "$host_os" = linux-dietlibc; then
+ case $cc_basename in
+ diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn)
+ esac
+ fi
+ if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \
+ && test "$tmp_diet" = no
+ then
+ tmp_addflag=
+ tmp_sharedflag='-shared'
+ case $cc_basename,$host_cpu in
+ pgcc*) # Portland Group C compiler
+ whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive'
+ tmp_addflag=' $pic_flag'
+ ;;
+ pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers
+ whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive'
+ tmp_addflag=' $pic_flag -Mnomain' ;;
+ ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64
+ tmp_addflag=' -i_dynamic' ;;
+ efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64
+ tmp_addflag=' -i_dynamic -nofor_main' ;;
+ ifc* | ifort*) # Intel Fortran compiler
+ tmp_addflag=' -nofor_main' ;;
+ lf95*) # Lahey Fortran 8.1
+ whole_archive_flag_spec=
+ tmp_sharedflag='--shared' ;;
+ xl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below)
+ tmp_sharedflag='-qmkshrobj'
+ tmp_addflag= ;;
+ esac
+ case `$CC -V 2>&1 | sed 5q` in
+ *Sun\ C*) # Sun C 5.9
+ whole_archive_flag_spec='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive'
+ compiler_needs_object=yes
+ tmp_sharedflag='-G' ;;
+ *Sun\ F*) # Sun Fortran 8.3
+ tmp_sharedflag='-G' ;;
+ esac
+ archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+
+ if test "x$supports_anon_versioning" = xyes; then
+ archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~
+ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+ echo "local: *; };" >> $output_objdir/$libname.ver~
+ $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'
+ fi
+
+ case $cc_basename in
+ xlf*)
+ # IBM XL Fortran 10.1 on PPC cannot create shared libs itself
+ whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive'
+ hardcode_libdir_flag_spec=
+ hardcode_libdir_flag_spec_ld='-rpath $libdir'
+ archive_cmds='$LD -shared $libobjs $deplibs $compiler_flags -soname $soname -o $lib'
+ if test "x$supports_anon_versioning" = xyes; then
+ archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~
+ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+ echo "local: *; };" >> $output_objdir/$libname.ver~
+ $LD -shared $libobjs $deplibs $compiler_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib'
+ fi
+ ;;
+ esac
+ else
+ ld_shlibs=no
+ fi
+ ;;
+
+ netbsd* | netbsdelf*-gnu)
+ if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+ archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
+ wlarc=
+ else
+ archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ fi
+ ;;
+
+ solaris*)
+ if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then
+ ld_shlibs=no
+ cat <<_LT_EOF 1>&2
+
+*** Warning: The releases 2.8.* of the GNU linker cannot reliably
+*** create shared libraries on Solaris systems. Therefore, libtool
+*** is disabling shared libraries support. We urge you to upgrade GNU
+*** binutils to release 2.9.1 or newer. Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+ elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+ archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ ld_shlibs=no
+ fi
+ ;;
+
+ sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
+ case `$LD -v 2>&1` in
+ *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*)
+ ld_shlibs=no
+ cat <<_LT_EOF 1>&2
+
+*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not
+*** reliably create shared libraries on SCO systems. Therefore, libtool
+*** is disabling shared libraries support. We urge you to upgrade GNU
+*** binutils to release 2.16.91.0.3 or newer. Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+ ;;
+ *)
+ # For security reasons, it is highly recommended that you always
+ # use absolute paths for naming shared libraries, and exclude the
+ # DT_RUNPATH tag from executables and libraries. But doing so
+ # requires that you compile everything twice, which is a pain.
+ if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+ hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+ archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ ld_shlibs=no
+ fi
+ ;;
+ esac
+ ;;
+
+ sunos4*)
+ archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ wlarc=
+ hardcode_direct=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ *)
+ if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+ archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ ld_shlibs=no
+ fi
+ ;;
+ esac
+
+ if test "$ld_shlibs" = no; then
+ runpath_var=
+ hardcode_libdir_flag_spec=
+ export_dynamic_flag_spec=
+ whole_archive_flag_spec=
+ fi
+ else
+ # PORTME fill in a description of your system's linker (not GNU ld)
+ case $host_os in
+ aix3*)
+ allow_undefined_flag=unsupported
+ always_export_symbols=yes
+ archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
+ # Note: this linker hardcodes the directories in LIBPATH if there
+ # are no directories specified by -L.
+ hardcode_minus_L=yes
+ if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then
+ # Neither direct hardcoding nor static linking is supported with a
+ # broken collect2.
+ hardcode_direct=unsupported
+ fi
+ ;;
+
+ aix[4-9]*)
+ if test "$host_cpu" = ia64; then
+ # On IA64, the linker does run time linking by default, so we don't
+ # have to do anything special.
+ aix_use_runtimelinking=no
+ exp_sym_flag='-Bexport'
+ no_entry_flag=""
+ else
+ # If we're using GNU nm, then we don't want the "-C" option.
+ # -C means demangle to AIX nm, but means don't demangle with GNU nm
+ if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
+ export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
+ else
+ export_symbols_cmds='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
+ fi
+ aix_use_runtimelinking=no
+
+ # Test if we are trying to use run time linking or normal
+ # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+ # need to do runtime linking.
+ case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*)
+ for ld_flag in $LDFLAGS; do
+ if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
+ aix_use_runtimelinking=yes
+ break
+ fi
+ done
+ ;;
+ esac
+
+ exp_sym_flag='-bexport'
+ no_entry_flag='-bnoentry'
+ fi
+
+ # When large executables or shared objects are built, AIX ld can
+ # have problems creating the table of contents. If linking a library
+ # or program results in "error TOC overflow" add -mminimal-toc to
+ # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not
+ # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+ archive_cmds=''
+ hardcode_direct=yes
+ hardcode_direct_absolute=yes
+ hardcode_libdir_separator=':'
+ link_all_deplibs=yes
+ file_list_spec='${wl}-f,'
+
+ if test "$GCC" = yes; then
+ case $host_os in aix4.[012]|aix4.[012].*)
+ # We only want to do this on AIX 4.2 and lower, the check
+ # below for broken collect2 doesn't work under 4.3+
+ collect2name=`${CC} -print-prog-name=collect2`
+ if test -f "$collect2name" &&
+ strings "$collect2name" | $GREP resolve_lib_name >/dev/null
+ then
+ # We have reworked collect2
+ :
+ else
+ # We have old collect2
+ hardcode_direct=unsupported
+ # It fails to find uninstalled libraries when the uninstalled
+ # path is not listed in the libpath. Setting hardcode_minus_L
+ # to unsupported forces relinking
+ hardcode_minus_L=yes
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_libdir_separator=
+ fi
+ ;;
+ esac
+ shared_flag='-shared'
+ if test "$aix_use_runtimelinking" = yes; then
+ shared_flag="$shared_flag "'${wl}-G'
+ fi
+ link_all_deplibs=no
+ else
+ # not using gcc
+ if test "$host_cpu" = ia64; then
+ # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+ # chokes on -Wl,-G. The following line is correct:
+ shared_flag='-G'
+ else
+ if test "$aix_use_runtimelinking" = yes; then
+ shared_flag='${wl}-G'
+ else
+ shared_flag='${wl}-bM:SRE'
+ fi
+ fi
+ fi
+
+ export_dynamic_flag_spec='${wl}-bexpall'
+ # It seems that -bexpall does not export symbols beginning with
+ # underscore (_), so it is better to generate a list of symbols to export.
+ always_export_symbols=yes
+ if test "$aix_use_runtimelinking" = yes; then
+ # Warning - without using the other runtime loading flags (-brtl),
+ # -berok will link without error, but may produce a broken library.
+ allow_undefined_flag='-berok'
+ # Determine the default libpath from the value encoded in an
+ # empty executable.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+lt_aix_libpath_sed='
+ /Import File Strings/,/^$/ {
+ /^0/ {
+ s/^0 *\(.*\)$/\1/
+ p
+ }
+ }'
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then
+ aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+fi
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+
+ hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath"
+ archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then $ECHO "X${wl}${allow_undefined_flag}" | $Xsed; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+ else
+ if test "$host_cpu" = ia64; then
+ hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib'
+ allow_undefined_flag="-z nodefs"
+ archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
+ else
+ # Determine the default libpath from the value encoded in an
+ # empty executable.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+lt_aix_libpath_sed='
+ /Import File Strings/,/^$/ {
+ /^0/ {
+ s/^0 *\(.*\)$/\1/
+ p
+ }
+ }'
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then
+ aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+fi
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+
+ hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath"
+ # Warning - without using the other run time loading flags,
+ # -berok will link without error, but may produce a broken library.
+ no_undefined_flag=' ${wl}-bernotok'
+ allow_undefined_flag=' ${wl}-berok'
+ # Exported symbols can be pulled into shared objects from archives
+ whole_archive_flag_spec='$convenience'
+ archive_cmds_need_lc=yes
+ # This is similar to how AIX traditionally builds its shared libraries.
+ archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+ fi
+ fi
+ ;;
+
+ amigaos*)
+ case $host_cpu in
+ powerpc)
+ # see comment about AmigaOS4 .so support
+ archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds=''
+ ;;
+ m68k)
+ archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_minus_L=yes
+ ;;
+ esac
+ ;;
+
+ bsdi[45]*)
+ export_dynamic_flag_spec=-rdynamic
+ ;;
+
+ cygwin* | mingw* | pw32* | cegcc*)
+ # When not using gcc, we currently assume that we are using
+ # Microsoft Visual C++.
+ # hardcode_libdir_flag_spec is actually meaningless, as there is
+ # no search path for DLLs.
+ hardcode_libdir_flag_spec=' '
+ allow_undefined_flag=unsupported
+ # Tell ltmain to make .lib files, not .a files.
+ libext=lib
+ # Tell ltmain to make .dll files, not .so files.
+ shrext_cmds=".dll"
+ # FIXME: Setting linknames here is a bad hack.
+ archive_cmds='$CC -o $lib $libobjs $compiler_flags `$ECHO "X$deplibs" | $Xsed -e '\''s/ -lc$//'\''` -link -dll~linknames='
+ # The linker will automatically build a .lib file if we build a DLL.
+ old_archive_from_new_cmds='true'
+ # FIXME: Should let the user specify the lib program.
+ old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs'
+ fix_srcfile_path='`cygpath -w "$srcfile"`'
+ enable_shared_with_static_runtimes=yes
+ ;;
+
+ darwin* | rhapsody*)
+
+
+ archive_cmds_need_lc=no
+ hardcode_direct=no
+ hardcode_automatic=yes
+ hardcode_shlibpath_var=unsupported
+ whole_archive_flag_spec=''
+ link_all_deplibs=yes
+ allow_undefined_flag="$_lt_dar_allow_undefined"
+ case $cc_basename in
+ ifort*) _lt_dar_can_shared=yes ;;
+ *) _lt_dar_can_shared=$GCC ;;
+ esac
+ if test "$_lt_dar_can_shared" = "yes"; then
+ output_verbose_link_cmd=echo
+ archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}"
+ module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}"
+ archive_expsym_cmds="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}"
+ module_expsym_cmds="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}"
+
+ else
+ ld_shlibs=no
+ fi
+
+ ;;
+
+ dgux*)
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_shlibpath_var=no
+ ;;
+
+ freebsd1*)
+ ld_shlibs=no
+ ;;
+
+ # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
+ # support. Future versions do this automatically, but an explicit c++rt0.o
+ # does not break anything, and helps significantly (at the cost of a little
+ # extra space).
+ freebsd2.2*)
+ archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
+ hardcode_libdir_flag_spec='-R$libdir'
+ hardcode_direct=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ # Unfortunately, older versions of FreeBSD 2 do not have this feature.
+ freebsd2*)
+ archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct=yes
+ hardcode_minus_L=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
+ freebsd* | dragonfly*)
+ archive_cmds='$CC -shared -o $lib $libobjs $deplibs $compiler_flags'
+ hardcode_libdir_flag_spec='-R$libdir'
+ hardcode_direct=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ hpux9*)
+ if test "$GCC" = yes; then
+ archive_cmds='$RM $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+ else
+ archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+ fi
+ hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+ hardcode_libdir_separator=:
+ hardcode_direct=yes
+
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ hardcode_minus_L=yes
+ export_dynamic_flag_spec='${wl}-E'
+ ;;
+
+ hpux10*)
+ if test "$GCC" = yes -a "$with_gnu_ld" = no; then
+ archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
+ fi
+ if test "$with_gnu_ld" = no; then
+ hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+ hardcode_libdir_flag_spec_ld='+b $libdir'
+ hardcode_libdir_separator=:
+ hardcode_direct=yes
+ hardcode_direct_absolute=yes
+ export_dynamic_flag_spec='${wl}-E'
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ hardcode_minus_L=yes
+ fi
+ ;;
+
+ hpux11*)
+ if test "$GCC" = yes -a "$with_gnu_ld" = no; then
+ case $host_cpu in
+ hppa*64*)
+ archive_cmds='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ ia64*)
+ archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ else
+ case $host_cpu in
+ hppa*64*)
+ archive_cmds='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ ia64*)
+ archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ fi
+ if test "$with_gnu_ld" = no; then
+ hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+ hardcode_libdir_separator=:
+
+ case $host_cpu in
+ hppa*64*|ia64*)
+ hardcode_direct=no
+ hardcode_shlibpath_var=no
+ ;;
+ *)
+ hardcode_direct=yes
+ hardcode_direct_absolute=yes
+ export_dynamic_flag_spec='${wl}-E'
+
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ hardcode_minus_L=yes
+ ;;
+ esac
+ fi
+ ;;
+
+ irix5* | irix6* | nonstopux*)
+ if test "$GCC" = yes; then
+ archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ # Try to use the -exported_symbol ld option, if it does not
+ # work, assume that -exports_file does not work either and
+ # implicitly export all symbols.
+ save_LDFLAGS="$LDFLAGS"
+ LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+int foo(void) {}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib'
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ LDFLAGS="$save_LDFLAGS"
+ else
+ archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib'
+ archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib'
+ fi
+ archive_cmds_need_lc='no'
+ hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator=:
+ inherit_rpath=yes
+ link_all_deplibs=yes
+ ;;
+
+ netbsd* | netbsdelf*-gnu)
+ if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+ archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out
+ else
+ archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF
+ fi
+ hardcode_libdir_flag_spec='-R$libdir'
+ hardcode_direct=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ newsos6)
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct=yes
+ hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator=:
+ hardcode_shlibpath_var=no
+ ;;
+
+ *nto* | *qnx*)
+ ;;
+
+ openbsd*)
+ if test -f /usr/libexec/ld.so; then
+ hardcode_direct=yes
+ hardcode_shlibpath_var=no
+ hardcode_direct_absolute=yes
+ if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols'
+ hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
+ export_dynamic_flag_spec='${wl}-E'
+ else
+ case $host_os in
+ openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*)
+ archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_libdir_flag_spec='-R$libdir'
+ ;;
+ *)
+ archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+ hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
+ ;;
+ esac
+ fi
+ else
+ ld_shlibs=no
+ fi
+ ;;
+
+ os2*)
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_minus_L=yes
+ allow_undefined_flag=unsupported
+ archive_cmds='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$ECHO DATA >> $output_objdir/$libname.def~$ECHO " SINGLE NONSHARED" >> $output_objdir/$libname.def~$ECHO EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def'
+ old_archive_from_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def'
+ ;;
+
+ osf3*)
+ if test "$GCC" = yes; then
+ allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*'
+ archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ else
+ allow_undefined_flag=' -expect_unresolved \*'
+ archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib'
+ fi
+ archive_cmds_need_lc='no'
+ hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator=:
+ ;;
+
+ osf4* | osf5*) # as osf3* with the addition of -msym flag
+ if test "$GCC" = yes; then
+ allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*'
+ archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+ else
+ allow_undefined_flag=' -expect_unresolved \*'
+ archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib'
+ archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~
+ $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp'
+
+ # Both c and cxx compiler support -rpath directly
+ hardcode_libdir_flag_spec='-rpath $libdir'
+ fi
+ archive_cmds_need_lc='no'
+ hardcode_libdir_separator=:
+ ;;
+
+ solaris*)
+ no_undefined_flag=' -z defs'
+ if test "$GCC" = yes; then
+ wlarc='${wl}'
+ archive_cmds='$CC -shared ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+ $CC -shared ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
+ else
+ case `$CC -V 2>&1` in
+ *"Compilers 5.0"*)
+ wlarc=''
+ archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp'
+ ;;
+ *)
+ wlarc='${wl}'
+ archive_cmds='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+ $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
+ ;;
+ esac
+ fi
+ hardcode_libdir_flag_spec='-R$libdir'
+ hardcode_shlibpath_var=no
+ case $host_os in
+ solaris2.[0-5] | solaris2.[0-5].*) ;;
+ *)
+ # The compiler driver will combine and reorder linker options,
+ # but understands `-z linker_flag'. GCC discards it without `$wl',
+ # but is careful enough not to reorder.
+ # Supported since Solaris 2.6 (maybe 2.5.1?)
+ if test "$GCC" = yes; then
+ whole_archive_flag_spec='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract'
+ else
+ whole_archive_flag_spec='-z allextract$convenience -z defaultextract'
+ fi
+ ;;
+ esac
+ link_all_deplibs=yes
+ ;;
+
+ sunos4*)
+ if test "x$host_vendor" = xsequent; then
+ # Use $CC to link under sequent, because it throws in some extra .o
+ # files that make .init and .fini sections work.
+ archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
+ fi
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_direct=yes
+ hardcode_minus_L=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ sysv4)
+ case $host_vendor in
+ sni)
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct=yes # is this really true???
+ ;;
+ siemens)
+ ## LD is ld it makes a PLAMLIB
+ ## CC just makes a GrossModule.
+ archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags'
+ reload_cmds='$CC -r -o $output$reload_objs'
+ hardcode_direct=no
+ ;;
+ motorola)
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct=no #Motorola manual says yes, but my tests say they lie
+ ;;
+ esac
+ runpath_var='LD_RUN_PATH'
+ hardcode_shlibpath_var=no
+ ;;
+
+ sysv4.3*)
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_shlibpath_var=no
+ export_dynamic_flag_spec='-Bexport'
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_shlibpath_var=no
+ runpath_var=LD_RUN_PATH
+ hardcode_runpath_var=yes
+ ld_shlibs=yes
+ fi
+ ;;
+
+ sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*)
+ no_undefined_flag='${wl}-z,text'
+ archive_cmds_need_lc=no
+ hardcode_shlibpath_var=no
+ runpath_var='LD_RUN_PATH'
+
+ if test "$GCC" = yes; then
+ archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ fi
+ ;;
+
+ sysv5* | sco3.2v5* | sco5v6*)
+ # Note: We can NOT use -z defs as we might desire, because we do not
+ # link with -lc, and that would cause any symbols used from libc to
+ # always be unresolved, which means just about no library would
+ # ever link correctly. If we're not using GNU ld we use -z text
+ # though, which does catch some bad symbols but isn't as heavy-handed
+ # as -z defs.
+ no_undefined_flag='${wl}-z,text'
+ allow_undefined_flag='${wl}-z,nodefs'
+ archive_cmds_need_lc=no
+ hardcode_shlibpath_var=no
+ hardcode_libdir_flag_spec='${wl}-R,$libdir'
+ hardcode_libdir_separator=':'
+ link_all_deplibs=yes
+ export_dynamic_flag_spec='${wl}-Bexport'
+ runpath_var='LD_RUN_PATH'
+
+ if test "$GCC" = yes; then
+ archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ fi
+ ;;
+
+ uts4*)
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_shlibpath_var=no
+ ;;
+
+ *)
+ ld_shlibs=no
+ ;;
+ esac
+
+ if test x$host_vendor = xsni; then
+ case $host in
+ sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+ export_dynamic_flag_spec='${wl}-Blargedynsym'
+ ;;
+ esac
+ fi
+ fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5
+$as_echo "$ld_shlibs" >&6; }
+test "$ld_shlibs" = no && can_build_shared=no
+
+with_gnu_ld=$with_gnu_ld
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#
+# Do we need to explicitly link libc?
+#
+case "x$archive_cmds_need_lc" in
+x|xyes)
+ # Assume -lc should be added
+ archive_cmds_need_lc=yes
+
+ if test "$enable_shared" = yes && test "$GCC" = yes; then
+ case $archive_cmds in
+ *'~'*)
+ # FIXME: we may have to deal with multi-command sequences.
+ ;;
+ '$CC '*)
+ # Test whether the compiler implicitly links with -lc since on some
+ # systems, -lgcc has to come before -lc. If gcc already passes -lc
+ # to ld, don't add -lc before -lgcc.
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5
+$as_echo_n "checking whether -lc should be explicitly linked in... " >&6; }
+ $RM conftest*
+ echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } 2>conftest.err; then
+ soname=conftest
+ lib=conftest
+ libobjs=conftest.$ac_objext
+ deplibs=
+ wl=$lt_prog_compiler_wl
+ pic_flag=$lt_prog_compiler_pic
+ compiler_flags=-v
+ linker_flags=-v
+ verstring=
+ output_objdir=.
+ libname=conftest
+ lt_save_allow_undefined_flag=$allow_undefined_flag
+ allow_undefined_flag=
+ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5
+ (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ then
+ archive_cmds_need_lc=no
+ else
+ archive_cmds_need_lc=yes
+ fi
+ allow_undefined_flag=$lt_save_allow_undefined_flag
+ else
+ cat conftest.err 1>&5
+ fi
+ $RM conftest*
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $archive_cmds_need_lc" >&5
+$as_echo "$archive_cmds_need_lc" >&6; }
+ ;;
+ esac
+ fi
+ ;;
+esac
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5
+$as_echo_n "checking dynamic linker characteristics... " >&6; }
+
+if test "$GCC" = yes; then
+ case $host_os in
+ darwin*) lt_awk_arg="/^libraries:/,/LR/" ;;
+ *) lt_awk_arg="/^libraries:/" ;;
+ esac
+ lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+ if $ECHO "$lt_search_path_spec" | $GREP ';' >/dev/null ; then
+ # if the path contains ";" then we assume it to be the separator
+ # otherwise default to the standard path separator (i.e. ":") - it is
+ # assumed that no part of a normal pathname contains ";" but that should
+ # okay in the real world where ";" in dirpaths is itself problematic.
+ lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED -e 's/;/ /g'`
+ else
+ lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+ fi
+ # Ok, now we have the path, separated by spaces, we can step through it
+ # and add multilib dir if necessary.
+ lt_tmp_lt_search_path_spec=
+ lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null`
+ for lt_sys_path in $lt_search_path_spec; do
+ if test -d "$lt_sys_path/$lt_multi_os_dir"; then
+ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir"
+ else
+ test -d "$lt_sys_path" && \
+ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path"
+ fi
+ done
+ lt_search_path_spec=`$ECHO $lt_tmp_lt_search_path_spec | awk '
+BEGIN {RS=" "; FS="/|\n";} {
+ lt_foo="";
+ lt_count=0;
+ for (lt_i = NF; lt_i > 0; lt_i--) {
+ if ($lt_i != "" && $lt_i != ".") {
+ if ($lt_i == "..") {
+ lt_count++;
+ } else {
+ if (lt_count == 0) {
+ lt_foo="/" $lt_i lt_foo;
+ } else {
+ lt_count--;
+ }
+ }
+ }
+ }
+ if (lt_foo != "") { lt_freq[lt_foo]++; }
+ if (lt_freq[lt_foo] == 1) { print lt_foo; }
+}'`
+ sys_lib_search_path_spec=`$ECHO $lt_search_path_spec`
+else
+ sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+fi
+library_names_spec=
+libname_spec='lib$name'
+soname_spec=
+shrext_cmds=".so"
+postinstall_cmds=
+postuninstall_cmds=
+finish_cmds=
+finish_eval=
+shlibpath_var=
+shlibpath_overrides_runpath=unknown
+version_type=none
+dynamic_linker="$host_os ld.so"
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
+need_lib_prefix=unknown
+hardcode_into_libs=no
+
+# when you set need_version to no, make sure it does not cause -set_version
+# flags to be left without arguments
+need_version=unknown
+
+case $host_os in
+aix3*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a'
+ shlibpath_var=LIBPATH
+
+ # AIX 3 has no versioning support, so we append a major version to the name.
+ soname_spec='${libname}${release}${shared_ext}$major'
+ ;;
+
+aix[4-9]*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ hardcode_into_libs=yes
+ if test "$host_cpu" = ia64; then
+ # AIX 5 supports IA64
+ library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ else
+ # With GCC up to 2.95.x, collect2 would create an import file
+ # for dependence libraries. The import file would start with
+ # the line `#! .'. This would cause the generated library to
+ # depend on `.', always an invalid library. This was fixed in
+ # development snapshots of GCC prior to 3.0.
+ case $host_os in
+ aix4 | aix4.[01] | aix4.[01].*)
+ if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
+ echo ' yes '
+ echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then
+ :
+ else
+ can_build_shared=no
+ fi
+ ;;
+ esac
+ # AIX (on Power*) has no versioning support, so currently we can not hardcode correct
+ # soname into executable. Probably we can add versioning support to
+ # collect2, so additional links can be useful in future.
+ if test "$aix_use_runtimelinking" = yes; then
+ # If using run time linking (on AIX 4.2 or later) use lib<name>.so
+ # instead of lib<name>.a to let people know that these are not
+ # typical AIX shared libraries.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ else
+ # We preserve .a as extension for shared libraries through AIX4.2
+ # and later when we are not doing run time linking.
+ library_names_spec='${libname}${release}.a $libname.a'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ fi
+ shlibpath_var=LIBPATH
+ fi
+ ;;
+
+amigaos*)
+ case $host_cpu in
+ powerpc)
+ # Since July 2007 AmigaOS4 officially supports .so libraries.
+ # When compiling the executable, add -use-dynld -Lsobjs: to the compileline.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ ;;
+ m68k)
+ library_names_spec='$libname.ixlibrary $libname.a'
+ # Create ${libname}_ixlibrary.a entries in /sys/libs.
+ finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$ECHO "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
+ ;;
+ esac
+ ;;
+
+beos*)
+ library_names_spec='${libname}${shared_ext}'
+ dynamic_linker="$host_os ld.so"
+ shlibpath_var=LIBRARY_PATH
+ ;;
+
+bsdi[45]*)
+ version_type=linux
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+ sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+ # the default ld.so.conf also contains /usr/contrib/lib and
+ # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
+ # libtool to hard-code these into programs
+ ;;
+
+cygwin* | mingw* | pw32* | cegcc*)
+ version_type=windows
+ shrext_cmds=".dll"
+ need_version=no
+ need_lib_prefix=no
+
+ case $GCC,$host_os in
+ yes,cygwin* | yes,mingw* | yes,pw32* | yes,cegcc*)
+ library_names_spec='$libname.dll.a'
+ # DLL is installed to $(libdir)/../bin by postinstall_cmds
+ postinstall_cmds='base_file=`basename \${file}`~
+ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~
+ dldir=$destdir/`dirname \$dlpath`~
+ test -d \$dldir || mkdir -p \$dldir~
+ $install_prog $dir/$dlname \$dldir/$dlname~
+ chmod a+x \$dldir/$dlname~
+ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then
+ eval '\''$striplib \$dldir/$dlname'\'' || exit \$?;
+ fi'
+ postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+ dlpath=$dir/\$dldll~
+ $RM \$dlpath'
+ shlibpath_overrides_runpath=yes
+
+ case $host_os in
+ cygwin*)
+ # Cygwin DLLs use 'cyg' prefix rather than 'lib'
+ soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+ sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib"
+ ;;
+ mingw* | cegcc*)
+ # MinGW DLLs use traditional 'lib' prefix
+ soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+ sys_lib_search_path_spec=`$CC -print-search-dirs | $GREP "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+ if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then
+ # It is most probably a Windows format PATH printed by
+ # mingw gcc, but we are running on Cygwin. Gcc prints its search
+ # path with ; separators, and with drive letters. We can handle the
+ # drive letters (cygwin fileutils understands them), so leave them,
+ # especially as we might pass files found there to a mingw objdump,
+ # which wouldn't understand a cygwinified path. Ahh.
+ sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+ else
+ sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+ fi
+ ;;
+ pw32*)
+ # pw32 DLLs use 'pw' prefix rather than 'lib'
+ library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+ ;;
+ esac
+ ;;
+
+ *)
+ library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib'
+ ;;
+ esac
+ dynamic_linker='Win32 ld.exe'
+ # FIXME: first we should search . and the directory the executable is in
+ shlibpath_var=PATH
+ ;;
+
+darwin* | rhapsody*)
+ dynamic_linker="$host_os dyld"
+ version_type=darwin
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext'
+ soname_spec='${libname}${release}${major}$shared_ext'
+ shlibpath_overrides_runpath=yes
+ shlibpath_var=DYLD_LIBRARY_PATH
+ shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
+
+ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"
+ sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
+ ;;
+
+dgux*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+freebsd1*)
+ dynamic_linker=no
+ ;;
+
+freebsd* | dragonfly*)
+ # DragonFly does not have aout. When/if they implement a new
+ # versioning mechanism, adjust this.
+ if test -x /usr/bin/objformat; then
+ objformat=`/usr/bin/objformat`
+ else
+ case $host_os in
+ freebsd[123]*) objformat=aout ;;
+ *) objformat=elf ;;
+ esac
+ fi
+ version_type=freebsd-$objformat
+ case $version_type in
+ freebsd-elf*)
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+ need_version=no
+ need_lib_prefix=no
+ ;;
+ freebsd-*)
+ library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix'
+ need_version=yes
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY_PATH
+ case $host_os in
+ freebsd2*)
+ shlibpath_overrides_runpath=yes
+ ;;
+ freebsd3.[01]* | freebsdelf3.[01]*)
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+ freebsd3.[2-9]* | freebsdelf3.[2-9]* | \
+ freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1)
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+ *) # from 4.6 on, and DragonFly
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+ esac
+ ;;
+
+gnu*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ hardcode_into_libs=yes
+ ;;
+
+hpux9* | hpux10* | hpux11*)
+ # Give a soname corresponding to the major version so that dld.sl refuses to
+ # link against other versions.
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ case $host_cpu in
+ ia64*)
+ shrext_cmds='.so'
+ hardcode_into_libs=yes
+ dynamic_linker="$host_os dld.so"
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ if test "X$HPUX_IA64_MODE" = X32; then
+ sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
+ else
+ sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
+ fi
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ ;;
+ hppa*64*)
+ shrext_cmds='.sl'
+ hardcode_into_libs=yes
+ dynamic_linker="$host_os dld.sl"
+ shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
+ shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ ;;
+ *)
+ shrext_cmds='.sl'
+ dynamic_linker="$host_os dld.sl"
+ shlibpath_var=SHLIB_PATH
+ shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ ;;
+ esac
+ # HP-UX runs *really* slowly unless shared libraries are mode 555.
+ postinstall_cmds='chmod 555 $lib'
+ ;;
+
+interix[3-9]*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+
+irix5* | irix6* | nonstopux*)
+ case $host_os in
+ nonstopux*) version_type=nonstopux ;;
+ *)
+ if test "$lt_cv_prog_gnu_ld" = yes; then
+ version_type=linux
+ else
+ version_type=irix
+ fi ;;
+ esac
+ need_lib_prefix=no
+ need_version=no
+ soname_spec='${libname}${release}${shared_ext}$major'
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}'
+ case $host_os in
+ irix5* | nonstopux*)
+ libsuff= shlibsuff=
+ ;;
+ *)
+ case $LD in # libtool.m4 will add one of these switches to LD
+ *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
+ libsuff= shlibsuff= libmagic=32-bit;;
+ *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
+ libsuff=32 shlibsuff=N32 libmagic=N32;;
+ *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
+ libsuff=64 shlibsuff=64 libmagic=64-bit;;
+ *) libsuff= shlibsuff= libmagic=never-match;;
+ esac
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
+ sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
+ hardcode_into_libs=yes
+ ;;
+
+# No shared lib support for Linux oldld, aout, or coff.
+linux*oldld* | linux*aout* | linux*coff*)
+ dynamic_linker=no
+ ;;
+
+# This must be Linux ELF.
+linux* | k*bsd*-gnu)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ # Some binutils ld are patched to set DT_RUNPATH
+ save_LDFLAGS=$LDFLAGS
+ save_libdir=$libdir
+ eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \
+ LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\""
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then :
+ shlibpath_overrides_runpath=yes
+fi
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ LDFLAGS=$save_LDFLAGS
+ libdir=$save_libdir
+
+ # This implies no fast_install, which is unacceptable.
+ # Some rework will be needed to allow for fast_install
+ # before this can be enabled.
+ hardcode_into_libs=yes
+
+ # Append ld.so.conf contents to the search path
+ if test -f /etc/ld.so.conf; then
+ lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '`
+ sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
+ fi
+
+ # We used to test for /lib/ld.so.1 and disable shared libraries on
+ # powerpc, because MkLinux only supported shared libraries with the
+ # GNU dynamic linker. Since this was broken with cross compilers,
+ # most powerpc-linux boxes support dynamic linking these days and
+ # people can always --disable-shared, the test was removed, and we
+ # assume the GNU/Linux dynamic linker is in use.
+ dynamic_linker='GNU/Linux ld.so'
+ ;;
+
+netbsdelf*-gnu)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ dynamic_linker='NetBSD ld.elf_so'
+ ;;
+
+netbsd*)
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ dynamic_linker='NetBSD (a.out) ld.so'
+ else
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ dynamic_linker='NetBSD ld.elf_so'
+ fi
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+
+newsos6)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ ;;
+
+*nto* | *qnx*)
+ version_type=qnx
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ dynamic_linker='ldqnx.so'
+ ;;
+
+openbsd*)
+ version_type=sunos
+ sys_lib_dlsearch_path_spec="/usr/lib"
+ need_lib_prefix=no
+ # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs.
+ case $host_os in
+ openbsd3.3 | openbsd3.3.*) need_version=yes ;;
+ *) need_version=no ;;
+ esac
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ case $host_os in
+ openbsd2.[89] | openbsd2.[89].*)
+ shlibpath_overrides_runpath=no
+ ;;
+ *)
+ shlibpath_overrides_runpath=yes
+ ;;
+ esac
+ else
+ shlibpath_overrides_runpath=yes
+ fi
+ ;;
+
+os2*)
+ libname_spec='$name'
+ shrext_cmds=".dll"
+ need_lib_prefix=no
+ library_names_spec='$libname${shared_ext} $libname.a'
+ dynamic_linker='OS/2 ld.exe'
+ shlibpath_var=LIBPATH
+ ;;
+
+osf3* | osf4* | osf5*)
+ version_type=osf
+ need_lib_prefix=no
+ need_version=no
+ soname_spec='${libname}${release}${shared_ext}$major'
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+ sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
+ ;;
+
+rdos*)
+ dynamic_linker=no
+ ;;
+
+solaris*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ # ldd complains unless libraries are executable
+ postinstall_cmds='chmod +x $lib'
+ ;;
+
+sunos4*)
+ version_type=sunos
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ if test "$with_gnu_ld" = yes; then
+ need_lib_prefix=no
+ fi
+ need_version=yes
+ ;;
+
+sysv4 | sysv4.3*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ case $host_vendor in
+ sni)
+ shlibpath_overrides_runpath=no
+ need_lib_prefix=no
+ runpath_var=LD_RUN_PATH
+ ;;
+ siemens)
+ need_lib_prefix=no
+ ;;
+ motorola)
+ need_lib_prefix=no
+ need_version=no
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
+ ;;
+ esac
+ ;;
+
+sysv4*MP*)
+ if test -d /usr/nec ;then
+ version_type=linux
+ library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}'
+ soname_spec='$libname${shared_ext}.$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ fi
+ ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+ version_type=freebsd-elf
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ if test "$with_gnu_ld" = yes; then
+ sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
+ else
+ sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
+ case $host_os in
+ sco3.2v5*)
+ sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
+ ;;
+ esac
+ fi
+ sys_lib_dlsearch_path_spec='/usr/lib'
+ ;;
+
+tpf*)
+ # TPF is a cross-target only. Preferred cross-host = GNU/Linux.
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+
+uts4*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+*)
+ dynamic_linker=no
+ ;;
+esac
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5
+$as_echo "$dynamic_linker" >&6; }
+test "$dynamic_linker" = no && can_build_shared=no
+
+variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+if test "$GCC" = yes; then
+ variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+fi
+
+if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then
+ sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec"
+fi
+if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then
+ sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec"
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5
+$as_echo_n "checking how to hardcode library paths into programs... " >&6; }
+hardcode_action=
+if test -n "$hardcode_libdir_flag_spec" ||
+ test -n "$runpath_var" ||
+ test "X$hardcode_automatic" = "Xyes" ; then
+
+ # We can hardcode non-existent directories.
+ if test "$hardcode_direct" != no &&
+ # If the only mechanism to avoid hardcoding is shlibpath_var, we
+ # have to relink, otherwise we might link with an installed library
+ # when we should be linking with a yet-to-be-installed one
+ ## test "$_LT_TAGVAR(hardcode_shlibpath_var, )" != no &&
+ test "$hardcode_minus_L" != no; then
+ # Linking always hardcodes the temporary library directory.
+ hardcode_action=relink
+ else
+ # We can link without hardcoding, and we can hardcode nonexisting dirs.
+ hardcode_action=immediate
+ fi
+else
+ # We cannot hardcode anything, or else we can only hardcode existing
+ # directories.
+ hardcode_action=unsupported
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5
+$as_echo "$hardcode_action" >&6; }
+
+if test "$hardcode_action" = relink ||
+ test "$inherit_rpath" = yes; then
+ # Fast installation is not supported
+ enable_fast_install=no
+elif test "$shlibpath_overrides_runpath" = yes ||
+ test "$enable_shared" = no; then
+ # Fast installation is not necessary
+ enable_fast_install=needless
+fi
+
+
+
+
+
+
+ if test "x$enable_dlopen" != xyes; then
+ enable_dlopen=unknown
+ enable_dlopen_self=unknown
+ enable_dlopen_self_static=unknown
+else
+ lt_cv_dlopen=no
+ lt_cv_dlopen_libs=
+
+ case $host_os in
+ beos*)
+ lt_cv_dlopen="load_add_on"
+ lt_cv_dlopen_libs=
+ lt_cv_dlopen_self=yes
+ ;;
+
+ mingw* | pw32* | cegcc*)
+ lt_cv_dlopen="LoadLibrary"
+ lt_cv_dlopen_libs=
+ ;;
+
+ cygwin*)
+ lt_cv_dlopen="dlopen"
+ lt_cv_dlopen_libs=
+ ;;
+
+ darwin*)
+ # if libdl is installed we need to link against it
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5
+$as_echo_n "checking for dlopen in -ldl... " >&6; }
+if test "${ac_cv_lib_dl_dlopen+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldl $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_dl_dlopen=yes
+else
+ ac_cv_lib_dl_dlopen=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5
+$as_echo "$ac_cv_lib_dl_dlopen" >&6; }
+if test "x$ac_cv_lib_dl_dlopen" = x""yes; then :
+ lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"
+else
+
+ lt_cv_dlopen="dyld"
+ lt_cv_dlopen_libs=
+ lt_cv_dlopen_self=yes
+
+fi
+
+ ;;
+
+ *)
+ ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load"
+if test "x$ac_cv_func_shl_load" = x""yes; then :
+ lt_cv_dlopen="shl_load"
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5
+$as_echo_n "checking for shl_load in -ldld... " >&6; }
+if test "${ac_cv_lib_dld_shl_load+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldld $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char shl_load ();
+int
+main ()
+{
+return shl_load ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_dld_shl_load=yes
+else
+ ac_cv_lib_dld_shl_load=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5
+$as_echo "$ac_cv_lib_dld_shl_load" >&6; }
+if test "x$ac_cv_lib_dld_shl_load" = x""yes; then :
+ lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld"
+else
+ ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen"
+if test "x$ac_cv_func_dlopen" = x""yes; then :
+ lt_cv_dlopen="dlopen"
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5
+$as_echo_n "checking for dlopen in -ldl... " >&6; }
+if test "${ac_cv_lib_dl_dlopen+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldl $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_dl_dlopen=yes
+else
+ ac_cv_lib_dl_dlopen=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5
+$as_echo "$ac_cv_lib_dl_dlopen" >&6; }
+if test "x$ac_cv_lib_dl_dlopen" = x""yes; then :
+ lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5
+$as_echo_n "checking for dlopen in -lsvld... " >&6; }
+if test "${ac_cv_lib_svld_dlopen+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lsvld $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_svld_dlopen=yes
+else
+ ac_cv_lib_svld_dlopen=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5
+$as_echo "$ac_cv_lib_svld_dlopen" >&6; }
+if test "x$ac_cv_lib_svld_dlopen" = x""yes; then :
+ lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5
+$as_echo_n "checking for dld_link in -ldld... " >&6; }
+if test "${ac_cv_lib_dld_dld_link+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldld $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dld_link ();
+int
+main ()
+{
+return dld_link ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_dld_dld_link=yes
+else
+ ac_cv_lib_dld_dld_link=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5
+$as_echo "$ac_cv_lib_dld_dld_link" >&6; }
+if test "x$ac_cv_lib_dld_dld_link" = x""yes; then :
+ lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld"
+fi
+
+
+fi
+
+
+fi
+
+
+fi
+
+
+fi
+
+
+fi
+
+ ;;
+ esac
+
+ if test "x$lt_cv_dlopen" != xno; then
+ enable_dlopen=yes
+ else
+ enable_dlopen=no
+ fi
+
+ case $lt_cv_dlopen in
+ dlopen)
+ save_CPPFLAGS="$CPPFLAGS"
+ test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H"
+
+ save_LDFLAGS="$LDFLAGS"
+ wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\"
+
+ save_LIBS="$LIBS"
+ LIBS="$lt_cv_dlopen_libs $LIBS"
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5
+$as_echo_n "checking whether a program can dlopen itself... " >&6; }
+if test "${lt_cv_dlopen_self+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test "$cross_compiling" = yes; then :
+ lt_cv_dlopen_self=cross
+else
+ lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+ lt_status=$lt_dlunknown
+ cat > conftest.$ac_ext <<_LT_EOF
+#line 10005 "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+# define LT_DLGLOBAL RTLD_GLOBAL
+#else
+# ifdef DL_GLOBAL
+# define LT_DLGLOBAL DL_GLOBAL
+# else
+# define LT_DLGLOBAL 0
+# endif
+#endif
+
+/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+ find out it does not work in some platform. */
+#ifndef LT_DLLAZY_OR_NOW
+# ifdef RTLD_LAZY
+# define LT_DLLAZY_OR_NOW RTLD_LAZY
+# else
+# ifdef DL_LAZY
+# define LT_DLLAZY_OR_NOW DL_LAZY
+# else
+# ifdef RTLD_NOW
+# define LT_DLLAZY_OR_NOW RTLD_NOW
+# else
+# ifdef DL_NOW
+# define LT_DLLAZY_OR_NOW DL_NOW
+# else
+# define LT_DLLAZY_OR_NOW 0
+# endif
+# endif
+# endif
+# endif
+#endif
+
+void fnord() { int i=42;}
+int main ()
+{
+ void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+ int status = $lt_dlunknown;
+
+ if (self)
+ {
+ if (dlsym (self,"fnord")) status = $lt_dlno_uscore;
+ else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore;
+ /* dlclose (self); */
+ }
+ else
+ puts (dlerror ());
+
+ return status;
+}
+_LT_EOF
+ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then
+ (./conftest; exit; ) >&5 2>/dev/null
+ lt_status=$?
+ case x$lt_status in
+ x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;;
+ x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;;
+ x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;;
+ esac
+ else :
+ # compilation failed
+ lt_cv_dlopen_self=no
+ fi
+fi
+rm -fr conftest*
+
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5
+$as_echo "$lt_cv_dlopen_self" >&6; }
+
+ if test "x$lt_cv_dlopen_self" = xyes; then
+ wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5
+$as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; }
+if test "${lt_cv_dlopen_self_static+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test "$cross_compiling" = yes; then :
+ lt_cv_dlopen_self_static=cross
+else
+ lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+ lt_status=$lt_dlunknown
+ cat > conftest.$ac_ext <<_LT_EOF
+#line 10101 "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+# define LT_DLGLOBAL RTLD_GLOBAL
+#else
+# ifdef DL_GLOBAL
+# define LT_DLGLOBAL DL_GLOBAL
+# else
+# define LT_DLGLOBAL 0
+# endif
+#endif
+
+/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+ find out it does not work in some platform. */
+#ifndef LT_DLLAZY_OR_NOW
+# ifdef RTLD_LAZY
+# define LT_DLLAZY_OR_NOW RTLD_LAZY
+# else
+# ifdef DL_LAZY
+# define LT_DLLAZY_OR_NOW DL_LAZY
+# else
+# ifdef RTLD_NOW
+# define LT_DLLAZY_OR_NOW RTLD_NOW
+# else
+# ifdef DL_NOW
+# define LT_DLLAZY_OR_NOW DL_NOW
+# else
+# define LT_DLLAZY_OR_NOW 0
+# endif
+# endif
+# endif
+# endif
+#endif
+
+void fnord() { int i=42;}
+int main ()
+{
+ void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+ int status = $lt_dlunknown;
+
+ if (self)
+ {
+ if (dlsym (self,"fnord")) status = $lt_dlno_uscore;
+ else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore;
+ /* dlclose (self); */
+ }
+ else
+ puts (dlerror ());
+
+ return status;
+}
+_LT_EOF
+ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then
+ (./conftest; exit; ) >&5 2>/dev/null
+ lt_status=$?
+ case x$lt_status in
+ x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;;
+ x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;;
+ x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;;
+ esac
+ else :
+ # compilation failed
+ lt_cv_dlopen_self_static=no
+ fi
+fi
+rm -fr conftest*
+
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5
+$as_echo "$lt_cv_dlopen_self_static" >&6; }
+ fi
+
+ CPPFLAGS="$save_CPPFLAGS"
+ LDFLAGS="$save_LDFLAGS"
+ LIBS="$save_LIBS"
+ ;;
+ esac
+
+ case $lt_cv_dlopen_self in
+ yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;;
+ *) enable_dlopen_self=unknown ;;
+ esac
+
+ case $lt_cv_dlopen_self_static in
+ yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;;
+ *) enable_dlopen_self_static=unknown ;;
+ esac
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+striplib=
+old_striplib=
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5
+$as_echo_n "checking whether stripping libraries is possible... " >&6; }
+if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then
+ test -z "$old_striplib" && old_striplib="$STRIP --strip-debug"
+ test -z "$striplib" && striplib="$STRIP --strip-unneeded"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+# FIXME - insert some real tests, host_os isn't really good enough
+ case $host_os in
+ darwin*)
+ if test -n "$STRIP" ; then
+ striplib="$STRIP -x"
+ old_striplib="$STRIP -S"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ fi
+ ;;
+ *)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ ;;
+ esac
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+ # Report which library types will actually be built
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5
+$as_echo_n "checking if libtool supports shared libraries... " >&6; }
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5
+$as_echo "$can_build_shared" >&6; }
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5
+$as_echo_n "checking whether to build shared libraries... " >&6; }
+ test "$can_build_shared" = "no" && enable_shared=no
+
+ # On AIX, shared libraries and static libraries use the same namespace, and
+ # are all built from PIC.
+ case $host_os in
+ aix3*)
+ test "$enable_shared" = yes && enable_static=no
+ if test -n "$RANLIB"; then
+ archive_cmds="$archive_cmds~\$RANLIB \$lib"
+ postinstall_cmds='$RANLIB $lib'
+ fi
+ ;;
+
+ aix[4-9]*)
+ if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
+ test "$enable_shared" = yes && enable_static=no
+ fi
+ ;;
+ esac
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5
+$as_echo "$enable_shared" >&6; }
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5
+$as_echo_n "checking whether to build static libraries... " >&6; }
+ # Make sure either enable_shared or enable_static is yes.
+ test "$enable_shared" = yes || enable_static=yes
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5
+$as_echo "$enable_static" >&6; }
+
+
+
+
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+CC="$lt_save_CC"
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ac_config_commands="$ac_config_commands libtool"
+
+
+
+
+# Only expand once:
+
+
+
+# Check whether --enable-silent-rules was given.
+if test "${enable_silent_rules+set}" = set; then :
+ enableval=$enable_silent_rules;
+fi
+
+case $enable_silent_rules in
+yes) AM_DEFAULT_VERBOSITY=0;;
+no) AM_DEFAULT_VERBOSITY=1;;
+*) AM_DEFAULT_VERBOSITY=0;;
+esac
+AM_BACKSLASH='\'
+
+
+# Install in /usr
+
+
+# Checks for programs.
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CC="${ac_tool_prefix}gcc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_CC="gcc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+else
+ CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CC="${ac_tool_prefix}cc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ fi
+fi
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# != 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+ fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in cl.exe
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$CC" && break
+ done
+fi
+if test -z "$CC"; then
+ ac_ct_CC=$CC
+ for ac_prog in cl.exe
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_CC="$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$ac_ct_CC" && break
+done
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+fi
+
+fi
+
+
+test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error "no acceptable C compiler found in \$PATH
+See \`config.log' for more details." "$LINENO" 5; }
+
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+ { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ sed '10a\
+... rest of stderr output deleted ...
+ 10q' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ rm -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+done
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
+$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
+if test "${ac_cv_c_compiler_gnu+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_compiler_gnu=yes
+else
+ ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+$as_echo "$ac_cv_c_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+ GCC=yes
+else
+ GCC=
+fi
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+$as_echo_n "checking whether $CC accepts -g... " >&6; }
+if test "${ac_cv_prog_cc_g+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_save_c_werror_flag=$ac_c_werror_flag
+ ac_c_werror_flag=yes
+ ac_cv_prog_cc_g=no
+ CFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_g=yes
+else
+ CFLAGS=""
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+ ac_c_werror_flag=$ac_save_c_werror_flag
+ CFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+$as_echo "$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+ CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-g"
+ fi
+else
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
+$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
+if test "${ac_cv_prog_cc_c89+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+ char **p;
+ int i;
+{
+ return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+ char *s;
+ va_list v;
+ va_start (v,p);
+ s = g (p, va_arg (v,int));
+ va_end (v);
+ return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
+ function prototypes and stuff, but not '\xHH' hex character constants.
+ These don't provoke an error unfortunately, instead are silently treated
+ as 'x'. The following induces an error, until -std is added to get
+ proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an
+ array size at least. It's necessary to write '\x00'==0 to get something
+ that's true only with -std. */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+ inside strings and character constants. */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
+ ;
+ return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+ CC="$ac_save_CC $ac_arg"
+ if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_c89=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext
+ test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+ x)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+$as_echo "none needed" >&6; } ;;
+ xno)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+$as_echo "unsupported" >&6; } ;;
+ *)
+ CC="$CC $ac_cv_prog_cc_c89"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+if test "x$ac_cv_prog_cc_c89" != xno; then :
+
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+depcc="$CC" am_compiler_list=
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5
+$as_echo_n "checking dependency style of $depcc... " >&6; }
+if test "${am_cv_CC_dependencies_compiler_type+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+ # We make a subdir and do the tests there. Otherwise we can end up
+ # making bogus files that we don't know about and never remove. For
+ # instance it was reported that on HP-UX the gcc test will end up
+ # making a dummy file named `D' -- because `-MD' means `put the output
+ # in D'.
+ mkdir conftest.dir
+ # Copy depcomp to subdir because otherwise we won't find it if we're
+ # using a relative directory.
+ cp "$am_depcomp" conftest.dir
+ cd conftest.dir
+ # We will build objects and dependencies in a subdirectory because
+ # it helps to detect inapplicable dependency modes. For instance
+ # both Tru64's cc and ICC support -MD to output dependencies as a
+ # side effect of compilation, but ICC will put the dependencies in
+ # the current directory while Tru64 will put them in the object
+ # directory.
+ mkdir sub
+
+ am_cv_CC_dependencies_compiler_type=none
+ if test "$am_compiler_list" = ""; then
+ am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp`
+ fi
+ am__universal=false
+ case " $depcc " in #(
+ *\ -arch\ *\ -arch\ *) am__universal=true ;;
+ esac
+
+ for depmode in $am_compiler_list; do
+ # Setup a source with many dependencies, because some compilers
+ # like to wrap large dependency lists on column 80 (with \), and
+ # we should not choose a depcomp mode which is confused by this.
+ #
+ # We need to recreate these files for each test, as the compiler may
+ # overwrite some of them when testing with obscure command lines.
+ # This happens at least with the AIX C compiler.
+ : > sub/conftest.c
+ for i in 1 2 3 4 5 6; do
+ echo '#include "conftst'$i'.h"' >> sub/conftest.c
+ # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with
+ # Solaris 8's {/usr,}/bin/sh.
+ touch sub/conftst$i.h
+ done
+ echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+ # We check with `-c' and `-o' for the sake of the "dashmstdout"
+ # mode. It turns out that the SunPro C++ compiler does not properly
+ # handle `-M -o', and we need to detect this. Also, some Intel
+ # versions had trouble with output in subdirs
+ am__obj=sub/conftest.${OBJEXT-o}
+ am__minus_obj="-o $am__obj"
+ case $depmode in
+ gcc)
+ # This depmode causes a compiler race in universal mode.
+ test "$am__universal" = false || continue
+ ;;
+ nosideeffect)
+ # after this tag, mechanisms are not by side-effect, so they'll
+ # only be used when explicitly requested
+ if test "x$enable_dependency_tracking" = xyes; then
+ continue
+ else
+ break
+ fi
+ ;;
+ msvisualcpp | msvcmsys)
+ # This compiler won't grok `-c -o', but also, the minuso test has
+ # not run yet. These depmodes are late enough in the game, and
+ # so weak that their functioning should not be impacted.
+ am__obj=conftest.${OBJEXT-o}
+ am__minus_obj=
+ ;;
+ none) break ;;
+ esac
+ if depmode=$depmode \
+ source=sub/conftest.c object=$am__obj \
+ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
+ >/dev/null 2>conftest.err &&
+ grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
+ ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+ # icc doesn't choke on unknown options, it will just issue warnings
+ # or remarks (even with -Werror). So we grep stderr for any message
+ # that says an option was ignored or not supported.
+ # When given -MP, icc 7.0 and 7.1 complain thusly:
+ # icc: Command line warning: ignoring option '-M'; no argument required
+ # The diagnosis changed in icc 8.0:
+ # icc: Command line remark: option '-MP' not supported
+ if (grep 'ignoring option' conftest.err ||
+ grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+ am_cv_CC_dependencies_compiler_type=$depmode
+ break
+ fi
+ fi
+ done
+
+ cd ..
+ rm -rf conftest.dir
+else
+ am_cv_CC_dependencies_compiler_type=none
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5
+$as_echo "$am_cv_CC_dependencies_compiler_type" >&6; }
+CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type
+
+ if
+ test "x$enable_dependency_tracking" != xno \
+ && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then
+ am__fastdepCC_TRUE=
+ am__fastdepCC_FALSE='#'
+else
+ am__fastdepCC_TRUE='#'
+ am__fastdepCC_FALSE=
+fi
+
+
+
+
+
+# Extract the first word of "ldconfig", so it can be a program name with args.
+set dummy ldconfig; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_path_LDCONFIG+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $LDCONFIG in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_LDCONFIG="$LDCONFIG" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /sbin /usr/sbin $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_path_LDCONFIG="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ test -z "$ac_cv_path_LDCONFIG" && ac_cv_path_LDCONFIG="true"
+ ;;
+esac
+fi
+LDCONFIG=$ac_cv_path_LDCONFIG
+if test -n "$LDCONFIG"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LDCONFIG" >&5
+$as_echo "$LDCONFIG" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+
+# Checks for libraries.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing dlopen" >&5
+$as_echo_n "checking for library containing dlopen... " >&6; }
+if test "${ac_cv_search_dlopen+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' dl; do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ fi
+ if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_search_dlopen=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext
+ if test "${ac_cv_search_dlopen+set}" = set; then :
+ break
+fi
+done
+if test "${ac_cv_search_dlopen+set}" = set; then :
+
+else
+ ac_cv_search_dlopen=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_dlopen" >&5
+$as_echo "$ac_cv_search_dlopen" >&6; }
+ac_res=$ac_cv_search_dlopen
+if test "$ac_res" != no; then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+else
+ as_fn_error "Missing libdl!" "$LINENO" 5
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing sqrt" >&5
+$as_echo_n "checking for library containing sqrt... " >&6; }
+if test "${ac_cv_search_sqrt+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char sqrt ();
+int
+main ()
+{
+return sqrt ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' m; do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ fi
+ if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_search_sqrt=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext
+ if test "${ac_cv_search_sqrt+set}" = set; then :
+ break
+fi
+done
+if test "${ac_cv_search_sqrt+set}" = set; then :
+
+else
+ ac_cv_search_sqrt=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_sqrt" >&5
+$as_echo "$ac_cv_search_sqrt" >&6; }
+ac_res=$ac_cv_search_sqrt
+if test "$ac_res" != no; then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+else
+ as_fn_error "Missing libm!" "$LINENO" 5
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing pthread_join" >&5
+$as_echo_n "checking for library containing pthread_join... " >&6; }
+if test "${ac_cv_search_pthread_join+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char pthread_join ();
+int
+main ()
+{
+return pthread_join ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' pthread; do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ fi
+ if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_search_pthread_join=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext
+ if test "${ac_cv_search_pthread_join+set}" = set; then :
+ break
+fi
+done
+if test "${ac_cv_search_pthread_join+set}" = set; then :
+
+else
+ ac_cv_search_pthread_join=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_pthread_join" >&5
+$as_echo "$ac_cv_search_pthread_join" >&6; }
+ac_res=$ac_cv_search_pthread_join
+if test "$ac_res" != no; then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+else
+ as_fn_error "Missing libpthread!" "$LINENO" 5
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing usb_find_busses" >&5
+$as_echo_n "checking for library containing usb_find_busses... " >&6; }
+if test "${ac_cv_search_usb_find_busses+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char usb_find_busses ();
+int
+main ()
+{
+return usb_find_busses ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' usb; do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ fi
+ if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_search_usb_find_busses=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext
+ if test "${ac_cv_search_usb_find_busses+set}" = set; then :
+ break
+fi
+done
+if test "${ac_cv_search_usb_find_busses+set}" = set; then :
+
+else
+ ac_cv_search_usb_find_busses=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_usb_find_busses" >&5
+$as_echo "$ac_cv_search_usb_find_busses" >&6; }
+ac_res=$ac_cv_search_usb_find_busses
+if test "$ac_res" != no; then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+else
+ as_fn_error "Missing libusb!" "$LINENO" 5
+fi
+
+# we need iconv - if it's not available in libc, look for the 'libiconv' function from libiconv.so
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing iconv" >&5
+$as_echo_n "checking for library containing iconv... " >&6; }
+if test "${ac_cv_search_iconv+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char iconv ();
+int
+main ()
+{
+return iconv ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' iconv; do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ fi
+ if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_search_iconv=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext
+ if test "${ac_cv_search_iconv+set}" = set; then :
+ break
+fi
+done
+if test "${ac_cv_search_iconv+set}" = set; then :
+
+else
+ ac_cv_search_iconv=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_iconv" >&5
+$as_echo "$ac_cv_search_iconv" >&6; }
+ac_res=$ac_cv_search_iconv
+if test "$ac_res" != no; then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing libiconv" >&5
+$as_echo_n "checking for library containing libiconv... " >&6; }
+if test "${ac_cv_search_libiconv+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char libiconv ();
+int
+main ()
+{
+return libiconv ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' iconv; do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ fi
+ if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_search_libiconv=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext
+ if test "${ac_cv_search_libiconv+set}" = set; then :
+ break
+fi
+done
+if test "${ac_cv_search_libiconv+set}" = set; then :
+
+else
+ ac_cv_search_libiconv=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_libiconv" >&5
+$as_echo "$ac_cv_search_libiconv" >&6; }
+ac_res=$ac_cv_search_libiconv
+if test "$ac_res" != no; then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+else
+ internaluniconv=true
+fi
+
+fi
+
+
+# Check whether --enable-jni was given.
+if test "${enable_jni+set}" = set; then :
+ enableval=$enable_jni; case "${enableval}" in
+ yes) jni=true ;;
+ no) jni=false ;;
+ *) as_fn_error "bad value ${enableval} for --enable-jni" "$LINENO" 5 ;;
+esac
+else
+ jni=true
+fi
+
+ if test x$jni = xtrue; then
+ JNI_TRUE=
+ JNI_FALSE='#'
+else
+ JNI_TRUE='#'
+ JNI_FALSE=
+fi
+
+
+# Check whether --enable-debug was given.
+if test "${enable_debug+set}" = set; then :
+ enableval=$enable_debug; case "${enableval}" in
+ yes) debug=true ;;
+ no) debug=false ;;
+ *) as_fn_error "bad value ${enableval} for --enable-debug" "$LINENO" 5 ;;
+esac
+else
+ debug=false
+fi
+
+ if test x$debug = xtrue; then
+ DEBUG_TRUE=
+ DEBUG_FALSE='#'
+else
+ DEBUG_TRUE='#'
+ DEBUG_FALSE=
+fi
+
+
+# Check whether --enable-zeroconf was given.
+if test "${enable_zeroconf+set}" = set; then :
+ enableval=$enable_zeroconf; case "${enableval}" in
+ yes) zeroconf=avahi ;;
+ avahi) zeroconf=avahi ;;
+ bonjour) zeroconf=bonjour ;;
+ no) zeroconf=false ;;
+ *) as_fn_error "bad value ${enableval} for --enable-zeroconf" "$LINENO" 5 ;;
+esac
+else
+ zeroconf=avahi
+fi
+
+ if test x$zeroconf = xavahi; then
+ ZEROCONF_AVAHI_TRUE=
+ ZEROCONF_AVAHI_FALSE='#'
+else
+ ZEROCONF_AVAHI_TRUE='#'
+ ZEROCONF_AVAHI_FALSE=
+fi
+
+ if test x$zeroconf = xbonjour; then
+ ZEROCONF_BONJOUR_TRUE=
+ ZEROCONF_BONJOUR_FALSE='#'
+else
+ ZEROCONF_BONJOUR_TRUE='#'
+ ZEROCONF_BONJOUR_FALSE=
+fi
+
+ if test x$zeroconf != xfalse; then
+ ZEROCONF_TRUE=
+ ZEROCONF_FALSE='#'
+else
+ ZEROCONF_TRUE='#'
+ ZEROCONF_FALSE=
+fi
+
+
+# Check whether --enable-zeroconf-lookup was given.
+if test "${enable_zeroconf_lookup+set}" = set; then :
+ enableval=$enable_zeroconf_lookup; case "${enableval}" in
+ yes) zeroconflookup=true ;;
+ no) zeroconflookup=false ;;
+ *) as_fn_error "bad value ${enableval} for --enable-zeroconf-lookup" "$LINENO" 5 ;;
+esac
+else
+ zeroconflookup=false
+fi
+
+ if test x$zeroconflookup = xtrue; then
+ ZEROCONF_LOOKUP_TRUE=
+ ZEROCONF_LOOKUP_FALSE='#'
+else
+ ZEROCONF_LOOKUP_TRUE='#'
+ ZEROCONF_LOOKUP_FALSE=
+fi
+
+
+# Check whether --enable-labview was given.
+if test "${enable_labview+set}" = set; then :
+ enableval=$enable_labview; case "${enableval}" in
+ yes) labview=true ;;
+ no) labview=false ;;
+ *) as_fn_error "bad value ${enableval} for --enable-labview" "$LINENO" 5 ;;
+esac
+else
+ labview=false
+fi
+
+ if test x$labview = xtrue; then
+ LABVIEW_TRUE=
+ LABVIEW_FALSE='#'
+else
+ LABVIEW_TRUE='#'
+ LABVIEW_FALSE=
+fi
+
+
+# Check whether --enable-ldconfig was given.
+if test "${enable_ldconfig+set}" = set; then :
+ enableval=$enable_ldconfig;
+else
+ enable_ldconfig="yes"
+fi
+
+ if test "${enable_ldconfig}" = "yes"; then
+ RUN_LDCONFIG_TRUE=
+ RUN_LDCONFIG_FALSE='#'
+else
+ RUN_LDCONFIG_TRUE='#'
+ RUN_LDCONFIG_FALSE=
+fi
+
+
+ if test x$internaluniconv = xtrue; then
+ INTERNAL_UNICONV_TRUE=
+ INTERNAL_UNICONV_FALSE='#'
+else
+ INTERNAL_UNICONV_TRUE='#'
+ INTERNAL_UNICONV_FALSE=
+fi
+
+
+ac_config_files="$ac_config_files Makefile examples/Makefile"
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems. If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, we kill variables containing newlines.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(
+ for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+ *) { eval $ac_var=; unset $ac_var;} ;;
+ esac ;;
+ esac
+ done
+
+ (set) 2>&1 |
+ case $as_nl`(ac_space=' '; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ # `set' does not quote correctly, so add quotes: double-quote
+ # substitution turns \\\\ into \\, and sed turns \\ into \.
+ sed -n \
+ "s/'/'\\\\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+ ;; #(
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+) |
+ sed '
+ /^ac_cv_env_/b end
+ t clear
+ :clear
+ s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+ t end
+ s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+ :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+ if test -w "$cache_file"; then
+ test "x$cache_file" != "x/dev/null" &&
+ { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
+$as_echo "$as_me: updating cache $cache_file" >&6;}
+ cat confcache >$cache_file
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
+$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+ fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Transform confdefs.h into DEFS.
+# Protect against shell expansion while executing Makefile rules.
+# Protect against Makefile macro expansion.
+#
+# If the first sed substitution is executed (which looks for macros that
+# take arguments), then branch to the quote section. Otherwise,
+# look for a macro that doesn't take arguments.
+ac_script='
+:mline
+/\\$/{
+ N
+ s,\\\n,,
+ b mline
+}
+t clear
+:clear
+s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g
+t quote
+s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g
+t quote
+b any
+:quote
+s/[ `~#$^&*(){}\\|;'\''"<>?]/\\&/g
+s/\[/\\&/g
+s/\]/\\&/g
+s/\$/$$/g
+H
+:any
+${
+ g
+ s/^\n//
+ s/\n/ /g
+ p
+}
+'
+DEFS=`sed -n "$ac_script" confdefs.h`
+
+
+ac_libobjs=
+ac_ltlibobjs=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+ # 1. Remove the extension, and $U if already installed.
+ ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+ ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
+ # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR
+ # will be set to the directory where LIBOBJS objects are built.
+ as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+ as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+ if test -n "$EXEEXT"; then
+ am__EXEEXT_TRUE=
+ am__EXEEXT_FALSE='#'
+else
+ am__EXEEXT_TRUE='#'
+ am__EXEEXT_FALSE=
+fi
+
+if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then
+ as_fn_error "conditional \"AMDEP\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then
+ as_fn_error "conditional \"am__fastdepCC\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then
+ as_fn_error "conditional \"am__fastdepCC\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${JNI_TRUE}" && test -z "${JNI_FALSE}"; then
+ as_fn_error "conditional \"JNI\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${DEBUG_TRUE}" && test -z "${DEBUG_FALSE}"; then
+ as_fn_error "conditional \"DEBUG\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ZEROCONF_AVAHI_TRUE}" && test -z "${ZEROCONF_AVAHI_FALSE}"; then
+ as_fn_error "conditional \"ZEROCONF_AVAHI\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ZEROCONF_BONJOUR_TRUE}" && test -z "${ZEROCONF_BONJOUR_FALSE}"; then
+ as_fn_error "conditional \"ZEROCONF_BONJOUR\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ZEROCONF_TRUE}" && test -z "${ZEROCONF_FALSE}"; then
+ as_fn_error "conditional \"ZEROCONF\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ZEROCONF_LOOKUP_TRUE}" && test -z "${ZEROCONF_LOOKUP_FALSE}"; then
+ as_fn_error "conditional \"ZEROCONF_LOOKUP\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${LABVIEW_TRUE}" && test -z "${LABVIEW_FALSE}"; then
+ as_fn_error "conditional \"LABVIEW\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${RUN_LDCONFIG_TRUE}" && test -z "${RUN_LDCONFIG_FALSE}"; then
+ as_fn_error "conditional \"RUN_LDCONFIG\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${INTERNAL_UNICONV_TRUE}" && test -z "${INTERNAL_UNICONV_FALSE}"; then
+ as_fn_error "conditional \"INTERNAL_UNICONV\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+
+: ${CONFIG_STATUS=./config.status}
+ac_write_fail=0
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
+$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
+as_write_fail=0
+cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+
+SHELL=\${CONFIG_SHELL-$SHELL}
+export SHELL
+_ASEOF
+cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='print -r --'
+ as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='printf %s\n'
+ as_echo_n='printf %s'
+else
+ if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+ as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+ as_echo_n='/usr/ucb/echo -n'
+ else
+ as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+ as_echo_n_body='eval
+ arg=$1;
+ case $arg in #(
+ *"$as_nl"*)
+ expr "X$arg" : "X\\(.*\\)$as_nl";
+ arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+ esac;
+ expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+ '
+ export as_echo_n_body
+ as_echo_n='sh -c $as_echo_n_body as_echo'
+ fi
+ export as_echo_body
+ as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ PATH_SEPARATOR=:
+ (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+ (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+ PATH_SEPARATOR=';'
+ }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+case $0 in #((
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there. '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+
+# as_fn_error ERROR [LINENO LOG_FD]
+# ---------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with status $?, using 1 if that was 0.
+as_fn_error ()
+{
+ as_status=$?; test $as_status -eq 0 && as_status=1
+ if test "$3"; then
+ as_lineno=${as_lineno-"$2"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ $as_echo "$as_me:${as_lineno-$LINENO}: error: $1" >&$3
+ fi
+ $as_echo "$as_me: error: $1" >&2
+ as_fn_exit $as_status
+} # as_fn_error
+
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+ return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+ set +e
+ as_fn_set_status $1
+ exit $1
+} # as_fn_exit
+
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+ { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+ eval 'as_fn_append ()
+ {
+ eval $1+=\$2
+ }'
+else
+ as_fn_append ()
+ {
+ eval $1=\$$1\$2
+ }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+ eval 'as_fn_arith ()
+ {
+ as_val=$(( $* ))
+ }'
+else
+ as_fn_arith ()
+ {
+ as_val=`expr "$@" || test $? -eq 1`
+ }
+fi # as_fn_arith
+
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+ case `echo 'xy\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ xy) ECHO_C='\c';;
+ *) echo `echo ksh88 bug on AIX 6.1` > /dev/null
+ ECHO_T=' ';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+ if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -p'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -p'
+ elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+ else
+ as_ln_s='cp -p'
+ fi
+else
+ as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || eval $as_mkdir_p || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || as_fn_error "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p='mkdir -p "$as_dir"'
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+ as_test_x='test -x'
+else
+ if ls -dL / >/dev/null 2>&1; then
+ as_ls_L_option=L
+ else
+ as_ls_L_option=
+ fi
+ as_test_x='
+ eval sh -c '\''
+ if test -d "$1"; then
+ test -d "$1/.";
+ else
+ case $1 in #(
+ -*)set "./$1";;
+ esac;
+ case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #((
+ ???[sx]*):;;*)false;;esac;fi
+ '\'' sh
+ '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+## ----------------------------------- ##
+## Main body of $CONFIG_STATUS script. ##
+## ----------------------------------- ##
+_ASEOF
+test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# Save the log message, to keep $0 and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by Phidget21 C Library $as_me 2.1.8.20120216, which was
+generated by GNU Autoconf 2.64. Invocation command line was
+
+ CONFIG_FILES = $CONFIG_FILES
+ CONFIG_HEADERS = $CONFIG_HEADERS
+ CONFIG_LINKS = $CONFIG_LINKS
+ CONFIG_COMMANDS = $CONFIG_COMMANDS
+ $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+case $ac_config_files in *"
+"*) set x $ac_config_files; shift; ac_config_files=$*;;
+esac
+
+
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+# Files that config.status was made for.
+config_files="$ac_config_files"
+config_commands="$ac_config_commands"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ac_cs_usage="\
+\`$as_me' instantiates files and other configuration actions
+from templates according to the current configuration. Unless the files
+and actions are specified as TAGs, all are instantiated by default.
+
+Usage: $0 [OPTION]... [TAG]...
+
+ -h, --help print this help, then exit
+ -V, --version print version number and configuration settings, then exit
+ -q, --quiet, --silent
+ do not print progress messages
+ -d, --debug don't remove temporary files
+ --recheck update $as_me by reconfiguring in the same conditions
+ --file=FILE[:TEMPLATE]
+ instantiate the configuration file FILE
+
+Configuration files:
+$config_files
+
+Configuration commands:
+$config_commands
+
+Report bugs to <support@phidgets.com>.
+Phidget21 C Library home page: <www.phidgets.com>."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_cs_version="\\
+Phidget21 C Library config.status 2.1.8.20120216
+configured by $0, generated by GNU Autoconf 2.64,
+ with options \\"`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
+
+Copyright (C) 2009 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+INSTALL='$INSTALL'
+MKDIR_P='$MKDIR_P'
+AWK='$AWK'
+test -n "\$AWK" || AWK=awk
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# The default lists apply if the user does not specify any file.
+ac_need_defaults=:
+while test $# != 0
+do
+ case $1 in
+ --*=*)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+ ac_shift=:
+ ;;
+ *)
+ ac_option=$1
+ ac_optarg=$2
+ ac_shift=shift
+ ;;
+ esac
+
+ case $ac_option in
+ # Handling of the options.
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ ac_cs_recheck=: ;;
+ --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+ $as_echo "$ac_cs_version"; exit ;;
+ --debug | --debu | --deb | --de | --d | -d )
+ debug=: ;;
+ --file | --fil | --fi | --f )
+ $ac_shift
+ case $ac_optarg in
+ *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ as_fn_append CONFIG_FILES " '$ac_optarg'"
+ ac_need_defaults=false;;
+ --he | --h | --help | --hel | -h )
+ $as_echo "$ac_cs_usage"; exit ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil | --si | --s)
+ ac_cs_silent=: ;;
+
+ # This is an error.
+ -*) as_fn_error "unrecognized option: \`$1'
+Try \`$0 --help' for more information." ;;
+
+ *) as_fn_append ac_config_targets " $1"
+ ac_need_defaults=false ;;
+
+ esac
+ shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+ exec 6>/dev/null
+ ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+if \$ac_cs_recheck; then
+ set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+ shift
+ \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
+ CONFIG_SHELL='$SHELL'
+ export CONFIG_SHELL
+ exec "\$@"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+exec 5>>config.log
+{
+ echo
+ sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+ $as_echo "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+#
+# INIT-COMMANDS
+#
+AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"
+
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+sed_quote_subst='$sed_quote_subst'
+double_quote_subst='$double_quote_subst'
+delay_variable_subst='$delay_variable_subst'
+macro_version='`$ECHO "X$macro_version" | $Xsed -e "$delay_single_quote_subst"`'
+macro_revision='`$ECHO "X$macro_revision" | $Xsed -e "$delay_single_quote_subst"`'
+enable_shared='`$ECHO "X$enable_shared" | $Xsed -e "$delay_single_quote_subst"`'
+enable_static='`$ECHO "X$enable_static" | $Xsed -e "$delay_single_quote_subst"`'
+pic_mode='`$ECHO "X$pic_mode" | $Xsed -e "$delay_single_quote_subst"`'
+enable_fast_install='`$ECHO "X$enable_fast_install" | $Xsed -e "$delay_single_quote_subst"`'
+host_alias='`$ECHO "X$host_alias" | $Xsed -e "$delay_single_quote_subst"`'
+host='`$ECHO "X$host" | $Xsed -e "$delay_single_quote_subst"`'
+host_os='`$ECHO "X$host_os" | $Xsed -e "$delay_single_quote_subst"`'
+build_alias='`$ECHO "X$build_alias" | $Xsed -e "$delay_single_quote_subst"`'
+build='`$ECHO "X$build" | $Xsed -e "$delay_single_quote_subst"`'
+build_os='`$ECHO "X$build_os" | $Xsed -e "$delay_single_quote_subst"`'
+SED='`$ECHO "X$SED" | $Xsed -e "$delay_single_quote_subst"`'
+Xsed='`$ECHO "X$Xsed" | $Xsed -e "$delay_single_quote_subst"`'
+GREP='`$ECHO "X$GREP" | $Xsed -e "$delay_single_quote_subst"`'
+EGREP='`$ECHO "X$EGREP" | $Xsed -e "$delay_single_quote_subst"`'
+FGREP='`$ECHO "X$FGREP" | $Xsed -e "$delay_single_quote_subst"`'
+LD='`$ECHO "X$LD" | $Xsed -e "$delay_single_quote_subst"`'
+NM='`$ECHO "X$NM" | $Xsed -e "$delay_single_quote_subst"`'
+LN_S='`$ECHO "X$LN_S" | $Xsed -e "$delay_single_quote_subst"`'
+max_cmd_len='`$ECHO "X$max_cmd_len" | $Xsed -e "$delay_single_quote_subst"`'
+ac_objext='`$ECHO "X$ac_objext" | $Xsed -e "$delay_single_quote_subst"`'
+exeext='`$ECHO "X$exeext" | $Xsed -e "$delay_single_quote_subst"`'
+lt_unset='`$ECHO "X$lt_unset" | $Xsed -e "$delay_single_quote_subst"`'
+lt_SP2NL='`$ECHO "X$lt_SP2NL" | $Xsed -e "$delay_single_quote_subst"`'
+lt_NL2SP='`$ECHO "X$lt_NL2SP" | $Xsed -e "$delay_single_quote_subst"`'
+reload_flag='`$ECHO "X$reload_flag" | $Xsed -e "$delay_single_quote_subst"`'
+reload_cmds='`$ECHO "X$reload_cmds" | $Xsed -e "$delay_single_quote_subst"`'
+OBJDUMP='`$ECHO "X$OBJDUMP" | $Xsed -e "$delay_single_quote_subst"`'
+deplibs_check_method='`$ECHO "X$deplibs_check_method" | $Xsed -e "$delay_single_quote_subst"`'
+file_magic_cmd='`$ECHO "X$file_magic_cmd" | $Xsed -e "$delay_single_quote_subst"`'
+AR='`$ECHO "X$AR" | $Xsed -e "$delay_single_quote_subst"`'
+AR_FLAGS='`$ECHO "X$AR_FLAGS" | $Xsed -e "$delay_single_quote_subst"`'
+STRIP='`$ECHO "X$STRIP" | $Xsed -e "$delay_single_quote_subst"`'
+RANLIB='`$ECHO "X$RANLIB" | $Xsed -e "$delay_single_quote_subst"`'
+old_postinstall_cmds='`$ECHO "X$old_postinstall_cmds" | $Xsed -e "$delay_single_quote_subst"`'
+old_postuninstall_cmds='`$ECHO "X$old_postuninstall_cmds" | $Xsed -e "$delay_single_quote_subst"`'
+old_archive_cmds='`$ECHO "X$old_archive_cmds" | $Xsed -e "$delay_single_quote_subst"`'
+CC='`$ECHO "X$CC" | $Xsed -e "$delay_single_quote_subst"`'
+CFLAGS='`$ECHO "X$CFLAGS" | $Xsed -e "$delay_single_quote_subst"`'
+compiler='`$ECHO "X$compiler" | $Xsed -e "$delay_single_quote_subst"`'
+GCC='`$ECHO "X$GCC" | $Xsed -e "$delay_single_quote_subst"`'
+lt_cv_sys_global_symbol_pipe='`$ECHO "X$lt_cv_sys_global_symbol_pipe" | $Xsed -e "$delay_single_quote_subst"`'
+lt_cv_sys_global_symbol_to_cdecl='`$ECHO "X$lt_cv_sys_global_symbol_to_cdecl" | $Xsed -e "$delay_single_quote_subst"`'
+lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "X$lt_cv_sys_global_symbol_to_c_name_address" | $Xsed -e "$delay_single_quote_subst"`'
+lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "X$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $Xsed -e "$delay_single_quote_subst"`'
+objdir='`$ECHO "X$objdir" | $Xsed -e "$delay_single_quote_subst"`'
+SHELL='`$ECHO "X$SHELL" | $Xsed -e "$delay_single_quote_subst"`'
+ECHO='`$ECHO "X$ECHO" | $Xsed -e "$delay_single_quote_subst"`'
+MAGIC_CMD='`$ECHO "X$MAGIC_CMD" | $Xsed -e "$delay_single_quote_subst"`'
+lt_prog_compiler_no_builtin_flag='`$ECHO "X$lt_prog_compiler_no_builtin_flag" | $Xsed -e "$delay_single_quote_subst"`'
+lt_prog_compiler_wl='`$ECHO "X$lt_prog_compiler_wl" | $Xsed -e "$delay_single_quote_subst"`'
+lt_prog_compiler_pic='`$ECHO "X$lt_prog_compiler_pic" | $Xsed -e "$delay_single_quote_subst"`'
+lt_prog_compiler_static='`$ECHO "X$lt_prog_compiler_static" | $Xsed -e "$delay_single_quote_subst"`'
+lt_cv_prog_compiler_c_o='`$ECHO "X$lt_cv_prog_compiler_c_o" | $Xsed -e "$delay_single_quote_subst"`'
+need_locks='`$ECHO "X$need_locks" | $Xsed -e "$delay_single_quote_subst"`'
+DSYMUTIL='`$ECHO "X$DSYMUTIL" | $Xsed -e "$delay_single_quote_subst"`'
+NMEDIT='`$ECHO "X$NMEDIT" | $Xsed -e "$delay_single_quote_subst"`'
+LIPO='`$ECHO "X$LIPO" | $Xsed -e "$delay_single_quote_subst"`'
+OTOOL='`$ECHO "X$OTOOL" | $Xsed -e "$delay_single_quote_subst"`'
+OTOOL64='`$ECHO "X$OTOOL64" | $Xsed -e "$delay_single_quote_subst"`'
+libext='`$ECHO "X$libext" | $Xsed -e "$delay_single_quote_subst"`'
+shrext_cmds='`$ECHO "X$shrext_cmds" | $Xsed -e "$delay_single_quote_subst"`'
+extract_expsyms_cmds='`$ECHO "X$extract_expsyms_cmds" | $Xsed -e "$delay_single_quote_subst"`'
+archive_cmds_need_lc='`$ECHO "X$archive_cmds_need_lc" | $Xsed -e "$delay_single_quote_subst"`'
+enable_shared_with_static_runtimes='`$ECHO "X$enable_shared_with_static_runtimes" | $Xsed -e "$delay_single_quote_subst"`'
+export_dynamic_flag_spec='`$ECHO "X$export_dynamic_flag_spec" | $Xsed -e "$delay_single_quote_subst"`'
+whole_archive_flag_spec='`$ECHO "X$whole_archive_flag_spec" | $Xsed -e "$delay_single_quote_subst"`'
+compiler_needs_object='`$ECHO "X$compiler_needs_object" | $Xsed -e "$delay_single_quote_subst"`'
+old_archive_from_new_cmds='`$ECHO "X$old_archive_from_new_cmds" | $Xsed -e "$delay_single_quote_subst"`'
+old_archive_from_expsyms_cmds='`$ECHO "X$old_archive_from_expsyms_cmds" | $Xsed -e "$delay_single_quote_subst"`'
+archive_cmds='`$ECHO "X$archive_cmds" | $Xsed -e "$delay_single_quote_subst"`'
+archive_expsym_cmds='`$ECHO "X$archive_expsym_cmds" | $Xsed -e "$delay_single_quote_subst"`'
+module_cmds='`$ECHO "X$module_cmds" | $Xsed -e "$delay_single_quote_subst"`'
+module_expsym_cmds='`$ECHO "X$module_expsym_cmds" | $Xsed -e "$delay_single_quote_subst"`'
+with_gnu_ld='`$ECHO "X$with_gnu_ld" | $Xsed -e "$delay_single_quote_subst"`'
+allow_undefined_flag='`$ECHO "X$allow_undefined_flag" | $Xsed -e "$delay_single_quote_subst"`'
+no_undefined_flag='`$ECHO "X$no_undefined_flag" | $Xsed -e "$delay_single_quote_subst"`'
+hardcode_libdir_flag_spec='`$ECHO "X$hardcode_libdir_flag_spec" | $Xsed -e "$delay_single_quote_subst"`'
+hardcode_libdir_flag_spec_ld='`$ECHO "X$hardcode_libdir_flag_spec_ld" | $Xsed -e "$delay_single_quote_subst"`'
+hardcode_libdir_separator='`$ECHO "X$hardcode_libdir_separator" | $Xsed -e "$delay_single_quote_subst"`'
+hardcode_direct='`$ECHO "X$hardcode_direct" | $Xsed -e "$delay_single_quote_subst"`'
+hardcode_direct_absolute='`$ECHO "X$hardcode_direct_absolute" | $Xsed -e "$delay_single_quote_subst"`'
+hardcode_minus_L='`$ECHO "X$hardcode_minus_L" | $Xsed -e "$delay_single_quote_subst"`'
+hardcode_shlibpath_var='`$ECHO "X$hardcode_shlibpath_var" | $Xsed -e "$delay_single_quote_subst"`'
+hardcode_automatic='`$ECHO "X$hardcode_automatic" | $Xsed -e "$delay_single_quote_subst"`'
+inherit_rpath='`$ECHO "X$inherit_rpath" | $Xsed -e "$delay_single_quote_subst"`'
+link_all_deplibs='`$ECHO "X$link_all_deplibs" | $Xsed -e "$delay_single_quote_subst"`'
+fix_srcfile_path='`$ECHO "X$fix_srcfile_path" | $Xsed -e "$delay_single_quote_subst"`'
+always_export_symbols='`$ECHO "X$always_export_symbols" | $Xsed -e "$delay_single_quote_subst"`'
+export_symbols_cmds='`$ECHO "X$export_symbols_cmds" | $Xsed -e "$delay_single_quote_subst"`'
+exclude_expsyms='`$ECHO "X$exclude_expsyms" | $Xsed -e "$delay_single_quote_subst"`'
+include_expsyms='`$ECHO "X$include_expsyms" | $Xsed -e "$delay_single_quote_subst"`'
+prelink_cmds='`$ECHO "X$prelink_cmds" | $Xsed -e "$delay_single_quote_subst"`'
+file_list_spec='`$ECHO "X$file_list_spec" | $Xsed -e "$delay_single_quote_subst"`'
+variables_saved_for_relink='`$ECHO "X$variables_saved_for_relink" | $Xsed -e "$delay_single_quote_subst"`'
+need_lib_prefix='`$ECHO "X$need_lib_prefix" | $Xsed -e "$delay_single_quote_subst"`'
+need_version='`$ECHO "X$need_version" | $Xsed -e "$delay_single_quote_subst"`'
+version_type='`$ECHO "X$version_type" | $Xsed -e "$delay_single_quote_subst"`'
+runpath_var='`$ECHO "X$runpath_var" | $Xsed -e "$delay_single_quote_subst"`'
+shlibpath_var='`$ECHO "X$shlibpath_var" | $Xsed -e "$delay_single_quote_subst"`'
+shlibpath_overrides_runpath='`$ECHO "X$shlibpath_overrides_runpath" | $Xsed -e "$delay_single_quote_subst"`'
+libname_spec='`$ECHO "X$libname_spec" | $Xsed -e "$delay_single_quote_subst"`'
+library_names_spec='`$ECHO "X$library_names_spec" | $Xsed -e "$delay_single_quote_subst"`'
+soname_spec='`$ECHO "X$soname_spec" | $Xsed -e "$delay_single_quote_subst"`'
+postinstall_cmds='`$ECHO "X$postinstall_cmds" | $Xsed -e "$delay_single_quote_subst"`'
+postuninstall_cmds='`$ECHO "X$postuninstall_cmds" | $Xsed -e "$delay_single_quote_subst"`'
+finish_cmds='`$ECHO "X$finish_cmds" | $Xsed -e "$delay_single_quote_subst"`'
+finish_eval='`$ECHO "X$finish_eval" | $Xsed -e "$delay_single_quote_subst"`'
+hardcode_into_libs='`$ECHO "X$hardcode_into_libs" | $Xsed -e "$delay_single_quote_subst"`'
+sys_lib_search_path_spec='`$ECHO "X$sys_lib_search_path_spec" | $Xsed -e "$delay_single_quote_subst"`'
+sys_lib_dlsearch_path_spec='`$ECHO "X$sys_lib_dlsearch_path_spec" | $Xsed -e "$delay_single_quote_subst"`'
+hardcode_action='`$ECHO "X$hardcode_action" | $Xsed -e "$delay_single_quote_subst"`'
+enable_dlopen='`$ECHO "X$enable_dlopen" | $Xsed -e "$delay_single_quote_subst"`'
+enable_dlopen_self='`$ECHO "X$enable_dlopen_self" | $Xsed -e "$delay_single_quote_subst"`'
+enable_dlopen_self_static='`$ECHO "X$enable_dlopen_self_static" | $Xsed -e "$delay_single_quote_subst"`'
+old_striplib='`$ECHO "X$old_striplib" | $Xsed -e "$delay_single_quote_subst"`'
+striplib='`$ECHO "X$striplib" | $Xsed -e "$delay_single_quote_subst"`'
+
+LTCC='$LTCC'
+LTCFLAGS='$LTCFLAGS'
+compiler='$compiler_DEFAULT'
+
+# Quote evaled strings.
+for var in SED \
+GREP \
+EGREP \
+FGREP \
+LD \
+NM \
+LN_S \
+lt_SP2NL \
+lt_NL2SP \
+reload_flag \
+OBJDUMP \
+deplibs_check_method \
+file_magic_cmd \
+AR \
+AR_FLAGS \
+STRIP \
+RANLIB \
+CC \
+CFLAGS \
+compiler \
+lt_cv_sys_global_symbol_pipe \
+lt_cv_sys_global_symbol_to_cdecl \
+lt_cv_sys_global_symbol_to_c_name_address \
+lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \
+SHELL \
+ECHO \
+lt_prog_compiler_no_builtin_flag \
+lt_prog_compiler_wl \
+lt_prog_compiler_pic \
+lt_prog_compiler_static \
+lt_cv_prog_compiler_c_o \
+need_locks \
+DSYMUTIL \
+NMEDIT \
+LIPO \
+OTOOL \
+OTOOL64 \
+shrext_cmds \
+export_dynamic_flag_spec \
+whole_archive_flag_spec \
+compiler_needs_object \
+with_gnu_ld \
+allow_undefined_flag \
+no_undefined_flag \
+hardcode_libdir_flag_spec \
+hardcode_libdir_flag_spec_ld \
+hardcode_libdir_separator \
+fix_srcfile_path \
+exclude_expsyms \
+include_expsyms \
+file_list_spec \
+variables_saved_for_relink \
+libname_spec \
+library_names_spec \
+soname_spec \
+finish_eval \
+old_striplib \
+striplib; do
+ case \`eval \\\\\$ECHO "X\\\\\$\$var"\` in
+ *[\\\\\\\`\\"\\\$]*)
+ eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"X\\\$\$var\\" | \\\$Xsed -e \\"\\\$sed_quote_subst\\"\\\`\\\\\\""
+ ;;
+ *)
+ eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
+ ;;
+ esac
+done
+
+# Double-quote double-evaled strings.
+for var in reload_cmds \
+old_postinstall_cmds \
+old_postuninstall_cmds \
+old_archive_cmds \
+extract_expsyms_cmds \
+old_archive_from_new_cmds \
+old_archive_from_expsyms_cmds \
+archive_cmds \
+archive_expsym_cmds \
+module_cmds \
+module_expsym_cmds \
+export_symbols_cmds \
+prelink_cmds \
+postinstall_cmds \
+postuninstall_cmds \
+finish_cmds \
+sys_lib_search_path_spec \
+sys_lib_dlsearch_path_spec; do
+ case \`eval \\\\\$ECHO "X\\\\\$\$var"\` in
+ *[\\\\\\\`\\"\\\$]*)
+ eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"X\\\$\$var\\" | \\\$Xsed -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\""
+ ;;
+ *)
+ eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
+ ;;
+ esac
+done
+
+# Fix-up fallback echo if it was mangled by the above quoting rules.
+case \$lt_ECHO in
+*'\\\$0 --fallback-echo"') lt_ECHO=\`\$ECHO "X\$lt_ECHO" | \$Xsed -e 's/\\\\\\\\\\\\\\\$0 --fallback-echo"\$/\$0 --fallback-echo"/'\`
+ ;;
+esac
+
+ac_aux_dir='$ac_aux_dir'
+xsi_shell='$xsi_shell'
+lt_shell_append='$lt_shell_append'
+
+# See if we are running on zsh, and set the options which allow our
+# commands through without removal of \ escapes INIT.
+if test -n "\${ZSH_VERSION+set}" ; then
+ setopt NO_GLOB_SUBST
+fi
+
+
+ PACKAGE='$PACKAGE'
+ VERSION='$VERSION'
+ TIMESTAMP='$TIMESTAMP'
+ RM='$RM'
+ ofile='$ofile'
+
+
+
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+ case $ac_config_target in
+ "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;;
+ "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;;
+ "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+ "examples/Makefile") CONFIG_FILES="$CONFIG_FILES examples/Makefile" ;;
+
+ *) as_fn_error "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
+ esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used. Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+ test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+ test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands
+fi
+
+# Have a temporary directory for convenience. Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+ tmp=
+ trap 'exit_status=$?
+ { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status
+' 0
+ trap 'as_fn_exit 1' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+ tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+ test -n "$tmp" && test -d "$tmp"
+} ||
+{
+ tmp=./conf$$-$RANDOM
+ (umask 077 && mkdir "$tmp")
+} || as_fn_error "cannot create a temporary directory in ." "$LINENO" 5
+
+# Set up the scripts for CONFIG_FILES section.
+# No need to generate them if there are no CONFIG_FILES.
+# This happens for instance with `./config.status config.h'.
+if test -n "$CONFIG_FILES"; then
+
+
+ac_cr=`echo X | tr X '\015'`
+# On cygwin, bash can eat \r inside `` if the user requested igncr.
+# But we know of no other shell where ac_cr would be empty at this
+# point, so we can use a bashism as a fallback.
+if test "x$ac_cr" = x; then
+ eval ac_cr=\$\'\\r\'
+fi
+ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null`
+if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
+ ac_cs_awk_cr='\r'
+else
+ ac_cs_awk_cr=$ac_cr
+fi
+
+echo 'BEGIN {' >"$tmp/subs1.awk" &&
+_ACEOF
+
+
+{
+ echo "cat >conf$$subs.awk <<_ACEOF" &&
+ echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' &&
+ echo "_ACEOF"
+} >conf$$subs.sh ||
+ as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5
+ac_delim_num=`echo "$ac_subst_vars" | grep -c '$'`
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+ . ./conf$$subs.sh ||
+ as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5
+
+ ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X`
+ if test $ac_delim_n = $ac_delim_num; then
+ break
+ elif $ac_last_try; then
+ as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5
+ else
+ ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+ fi
+done
+rm -f conf$$subs.sh
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+cat >>"\$tmp/subs1.awk" <<\\_ACAWK &&
+_ACEOF
+sed -n '
+h
+s/^/S["/; s/!.*/"]=/
+p
+g
+s/^[^!]*!//
+:repl
+t repl
+s/'"$ac_delim"'$//
+t delim
+:nl
+h
+s/\(.\{148\}\).*/\1/
+t more1
+s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/
+p
+n
+b repl
+:more1
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t nl
+:delim
+h
+s/\(.\{148\}\).*/\1/
+t more2
+s/["\\]/\\&/g; s/^/"/; s/$/"/
+p
+b
+:more2
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t delim
+' <conf$$subs.awk | sed '
+/^[^""]/{
+ N
+ s/\n//
+}
+' >>$CONFIG_STATUS || ac_write_fail=1
+rm -f conf$$subs.awk
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACAWK
+cat >>"\$tmp/subs1.awk" <<_ACAWK &&
+ for (key in S) S_is_set[key] = 1
+ FS = ""
+
+}
+{
+ line = $ 0
+ nfields = split(line, field, "@")
+ substed = 0
+ len = length(field[1])
+ for (i = 2; i < nfields; i++) {
+ key = field[i]
+ keylen = length(key)
+ if (S_is_set[key]) {
+ value = S[key]
+ line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)
+ len += length(value) + length(field[++i])
+ substed = 1
+ } else
+ len += 1 + keylen
+ }
+
+ print line
+}
+
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
+ sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
+else
+ cat
+fi < "$tmp/subs1.awk" > "$tmp/subs.awk" \
+ || as_fn_error "could not setup config files machinery" "$LINENO" 5
+_ACEOF
+
+# VPATH may cause trouble with some makes, so we remove $(srcdir),
+# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=/{
+s/:*\$(srcdir):*/:/
+s/:*\${srcdir}:*/:/
+s/:*@srcdir@:*/:/
+s/^\([^=]*=[ ]*\):*/\1/
+s/:*$//
+s/^[^=]*=[ ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+fi # test -n "$CONFIG_FILES"
+
+
+eval set X " :F $CONFIG_FILES :C $CONFIG_COMMANDS"
+shift
+for ac_tag
+do
+ case $ac_tag in
+ :[FHLC]) ac_mode=$ac_tag; continue;;
+ esac
+ case $ac_mode$ac_tag in
+ :[FHL]*:*);;
+ :L* | :C*:*) as_fn_error "invalid tag \`$ac_tag'" "$LINENO" 5;;
+ :[FH]-) ac_tag=-:-;;
+ :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+ esac
+ ac_save_IFS=$IFS
+ IFS=:
+ set x $ac_tag
+ IFS=$ac_save_IFS
+ shift
+ ac_file=$1
+ shift
+
+ case $ac_mode in
+ :L) ac_source=$1;;
+ :[FH])
+ ac_file_inputs=
+ for ac_f
+ do
+ case $ac_f in
+ -) ac_f="$tmp/stdin";;
+ *) # Look for the file first in the build tree, then in the source tree
+ # (if the path is not absolute). The absolute path cannot be DOS-style,
+ # because $ac_f cannot contain `:'.
+ test -f "$ac_f" ||
+ case $ac_f in
+ [\\/$]*) false;;
+ *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+ esac ||
+ as_fn_error "cannot find input file: \`$ac_f'" "$LINENO" 5;;
+ esac
+ case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+ as_fn_append ac_file_inputs " '$ac_f'"
+ done
+
+ # Let's still pretend it is `configure' which instantiates (i.e., don't
+ # use $as_me), people would be surprised to read:
+ # /* config.h. Generated by config.status. */
+ configure_input='Generated from '`
+ $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+ `' by configure.'
+ if test x"$ac_file" != x-; then
+ configure_input="$ac_file. $configure_input"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
+$as_echo "$as_me: creating $ac_file" >&6;}
+ fi
+ # Neutralize special characters interpreted by sed in replacement strings.
+ case $configure_input in #(
+ *\&* | *\|* | *\\* )
+ ac_sed_conf_input=`$as_echo "$configure_input" |
+ sed 's/[\\\\&|]/\\\\&/g'`;; #(
+ *) ac_sed_conf_input=$configure_input;;
+ esac
+
+ case $ac_tag in
+ *:-:* | *:-) cat >"$tmp/stdin" \
+ || as_fn_error "could not create $ac_file" "$LINENO" 5 ;;
+ esac
+ ;;
+ esac
+
+ ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ac_file" : 'X\(//\)[^/]' \| \
+ X"$ac_file" : 'X\(//\)$' \| \
+ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$ac_file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ as_dir="$ac_dir"; as_fn_mkdir_p
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+ case $ac_mode in
+ :F)
+ #
+ # CONFIG_FILE
+ #
+
+ case $INSTALL in
+ [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+ *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;;
+ esac
+ ac_MKDIR_P=$MKDIR_P
+ case $MKDIR_P in
+ [\\/$]* | ?:[\\/]* ) ;;
+ */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;;
+ esac
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+ac_sed_dataroot='
+/datarootdir/ {
+ p
+ q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p'
+case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ ac_datarootdir_hack='
+ s&@datadir@&$datadir&g
+ s&@docdir@&$docdir&g
+ s&@infodir@&$infodir&g
+ s&@localedir@&$localedir&g
+ s&@mandir@&$mandir&g
+ s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
+_ACEOF
+
+# Neutralize VPATH when `$srcdir' = `.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_sed_extra="$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s|@configure_input@|$ac_sed_conf_input|;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@top_build_prefix@&$ac_top_build_prefix&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+s&@INSTALL@&$ac_INSTALL&;t t
+s&@MKDIR_P@&$ac_MKDIR_P&;t t
+$ac_datarootdir_hack
+"
+eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$tmp/subs.awk" >$tmp/out \
+ || as_fn_error "could not create $ac_file" "$LINENO" 5
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+ { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } &&
+ { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } &&
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined." >&5
+$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined." >&2;}
+
+ rm -f "$tmp/stdin"
+ case $ac_file in
+ -) cat "$tmp/out" && rm -f "$tmp/out";;
+ *) rm -f "$ac_file" && mv "$tmp/out" "$ac_file";;
+ esac \
+ || as_fn_error "could not create $ac_file" "$LINENO" 5
+ ;;
+
+
+ :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5
+$as_echo "$as_me: executing $ac_file commands" >&6;}
+ ;;
+ esac
+
+
+ case $ac_file$ac_mode in
+ "depfiles":C) test x"$AMDEP_TRUE" != x"" || {
+ # Autoconf 2.62 quotes --file arguments for eval, but not when files
+ # are listed without --file. Let's play safe and only enable the eval
+ # if we detect the quoting.
+ case $CONFIG_FILES in
+ *\'*) eval set x "$CONFIG_FILES" ;;
+ *) set x $CONFIG_FILES ;;
+ esac
+ shift
+ for mf
+ do
+ # Strip MF so we end up with the name of the file.
+ mf=`echo "$mf" | sed -e 's/:.*$//'`
+ # Check whether this is an Automake generated Makefile or not.
+ # We used to match only the files named `Makefile.in', but
+ # some people rename them; so instead we look at the file content.
+ # Grep'ing the first line is not enough: some people post-process
+ # each Makefile.in and add a new line on top of each file to say so.
+ # Grep'ing the whole file is not good either: AIX grep has a line
+ # limit of 2048, but all sed's we know have understand at least 4000.
+ if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then
+ dirpart=`$as_dirname -- "$mf" ||
+$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$mf" : 'X\(//\)[^/]' \| \
+ X"$mf" : 'X\(//\)$' \| \
+ X"$mf" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$mf" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ else
+ continue
+ fi
+ # Extract the definition of DEPDIR, am__include, and am__quote
+ # from the Makefile without running `make'.
+ DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
+ test -z "$DEPDIR" && continue
+ am__include=`sed -n 's/^am__include = //p' < "$mf"`
+ test -z "am__include" && continue
+ am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
+ # When using ansi2knr, U may be empty or an underscore; expand it
+ U=`sed -n 's/^U = //p' < "$mf"`
+ # Find all dependency output files, they are included files with
+ # $(DEPDIR) in their names. We invoke sed twice because it is the
+ # simplest approach to changing $(DEPDIR) to its actual value in the
+ # expansion.
+ for file in `sed -n "
+ s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
+ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do
+ # Make sure the directory exists.
+ test -f "$dirpart/$file" && continue
+ fdir=`$as_dirname -- "$file" ||
+$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$file" : 'X\(//\)[^/]' \| \
+ X"$file" : 'X\(//\)$' \| \
+ X"$file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ as_dir=$dirpart/$fdir; as_fn_mkdir_p
+ # echo "creating $dirpart/$file"
+ echo '# dummy' > "$dirpart/$file"
+ done
+ done
+}
+ ;;
+ "libtool":C)
+
+ # See if we are running on zsh, and set the options which allow our
+ # commands through without removal of \ escapes.
+ if test -n "${ZSH_VERSION+set}" ; then
+ setopt NO_GLOB_SUBST
+ fi
+
+ cfgfile="${ofile}T"
+ trap "$RM \"$cfgfile\"; exit 1" 1 2 15
+ $RM "$cfgfile"
+
+ cat <<_LT_EOF >> "$cfgfile"
+#! $SHELL
+
+# `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services.
+# Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+# NOTE: Changes made to this file will be lost: look at ltmain.sh.
+#
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005,
+# 2006, 2007, 2008 Free Software Foundation, Inc.
+# Written by Gordon Matzigkeit, 1996
+#
+# This file is part of GNU Libtool.
+#
+# GNU Libtool is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# As a special exception to the GNU General Public License,
+# if you distribute this file as part of a program or library that
+# is built using GNU Libtool, you may include this file under the
+# same distribution terms that you use for the rest of that program.
+#
+# GNU Libtool is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Libtool; see the file COPYING. If not, a copy
+# can be downloaded from http://www.gnu.org/licenses/gpl.html, or
+# obtained by writing to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+
+# The names of the tagged configurations supported by this script.
+available_tags=""
+
+# ### BEGIN LIBTOOL CONFIG
+
+# Which release of libtool.m4 was used?
+macro_version=$macro_version
+macro_revision=$macro_revision
+
+# Whether or not to build shared libraries.
+build_libtool_libs=$enable_shared
+
+# Whether or not to build static libraries.
+build_old_libs=$enable_static
+
+# What type of objects to build.
+pic_mode=$pic_mode
+
+# Whether or not to optimize for fast installation.
+fast_install=$enable_fast_install
+
+# The host system.
+host_alias=$host_alias
+host=$host
+host_os=$host_os
+
+# The build system.
+build_alias=$build_alias
+build=$build
+build_os=$build_os
+
+# A sed program that does not truncate output.
+SED=$lt_SED
+
+# Sed that helps us avoid accidentally triggering echo(1) options like -n.
+Xsed="\$SED -e 1s/^X//"
+
+# A grep program that handles long lines.
+GREP=$lt_GREP
+
+# An ERE matcher.
+EGREP=$lt_EGREP
+
+# A literal string matcher.
+FGREP=$lt_FGREP
+
+# A BSD- or MS-compatible name lister.
+NM=$lt_NM
+
+# Whether we need soft or hard links.
+LN_S=$lt_LN_S
+
+# What is the maximum length of a command?
+max_cmd_len=$max_cmd_len
+
+# Object file suffix (normally "o").
+objext=$ac_objext
+
+# Executable file suffix (normally "").
+exeext=$exeext
+
+# whether the shell understands "unset".
+lt_unset=$lt_unset
+
+# turn spaces into newlines.
+SP2NL=$lt_lt_SP2NL
+
+# turn newlines into spaces.
+NL2SP=$lt_lt_NL2SP
+
+# How to create reloadable object files.
+reload_flag=$lt_reload_flag
+reload_cmds=$lt_reload_cmds
+
+# An object symbol dumper.
+OBJDUMP=$lt_OBJDUMP
+
+# Method to check whether dependent libraries are shared objects.
+deplibs_check_method=$lt_deplibs_check_method
+
+# Command to use when deplibs_check_method == "file_magic".
+file_magic_cmd=$lt_file_magic_cmd
+
+# The archiver.
+AR=$lt_AR
+AR_FLAGS=$lt_AR_FLAGS
+
+# A symbol stripping program.
+STRIP=$lt_STRIP
+
+# Commands used to install an old-style archive.
+RANLIB=$lt_RANLIB
+old_postinstall_cmds=$lt_old_postinstall_cmds
+old_postuninstall_cmds=$lt_old_postuninstall_cmds
+
+# A C compiler.
+LTCC=$lt_CC
+
+# LTCC compiler flags.
+LTCFLAGS=$lt_CFLAGS
+
+# Take the output of nm and produce a listing of raw symbols and C names.
+global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe
+
+# Transform the output of nm in a proper C declaration.
+global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl
+
+# Transform the output of nm in a C name address pair.
+global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address
+
+# Transform the output of nm in a C name address pair when lib prefix is needed.
+global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix
+
+# The name of the directory that contains temporary libtool files.
+objdir=$objdir
+
+# Shell to use when invoking shell scripts.
+SHELL=$lt_SHELL
+
+# An echo program that does not interpret backslashes.
+ECHO=$lt_ECHO
+
+# Used to examine libraries when file_magic_cmd begins with "file".
+MAGIC_CMD=$MAGIC_CMD
+
+# Must we lock files when doing compilation?
+need_locks=$lt_need_locks
+
+# Tool to manipulate archived DWARF debug symbol files on Mac OS X.
+DSYMUTIL=$lt_DSYMUTIL
+
+# Tool to change global to local symbols on Mac OS X.
+NMEDIT=$lt_NMEDIT
+
+# Tool to manipulate fat objects and archives on Mac OS X.
+LIPO=$lt_LIPO
+
+# ldd/readelf like tool for Mach-O binaries on Mac OS X.
+OTOOL=$lt_OTOOL
+
+# ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4.
+OTOOL64=$lt_OTOOL64
+
+# Old archive suffix (normally "a").
+libext=$libext
+
+# Shared library suffix (normally ".so").
+shrext_cmds=$lt_shrext_cmds
+
+# The commands to extract the exported symbol list from a shared archive.
+extract_expsyms_cmds=$lt_extract_expsyms_cmds
+
+# Variables whose values should be saved in libtool wrapper scripts and
+# restored at link time.
+variables_saved_for_relink=$lt_variables_saved_for_relink
+
+# Do we need the "lib" prefix for modules?
+need_lib_prefix=$need_lib_prefix
+
+# Do we need a version for libraries?
+need_version=$need_version
+
+# Library versioning type.
+version_type=$version_type
+
+# Shared library runtime path variable.
+runpath_var=$runpath_var
+
+# Shared library path variable.
+shlibpath_var=$shlibpath_var
+
+# Is shlibpath searched before the hard-coded library search path?
+shlibpath_overrides_runpath=$shlibpath_overrides_runpath
+
+# Format of library name prefix.
+libname_spec=$lt_libname_spec
+
+# List of archive names. First name is the real one, the rest are links.
+# The last name is the one that the linker finds with -lNAME
+library_names_spec=$lt_library_names_spec
+
+# The coded name of the library, if different from the real name.
+soname_spec=$lt_soname_spec
+
+# Command to use after installation of a shared archive.
+postinstall_cmds=$lt_postinstall_cmds
+
+# Command to use after uninstallation of a shared archive.
+postuninstall_cmds=$lt_postuninstall_cmds
+
+# Commands used to finish a libtool library installation in a directory.
+finish_cmds=$lt_finish_cmds
+
+# As "finish_cmds", except a single script fragment to be evaled but
+# not shown.
+finish_eval=$lt_finish_eval
+
+# Whether we should hardcode library paths into libraries.
+hardcode_into_libs=$hardcode_into_libs
+
+# Compile-time system search path for libraries.
+sys_lib_search_path_spec=$lt_sys_lib_search_path_spec
+
+# Run-time system search path for libraries.
+sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec
+
+# Whether dlopen is supported.
+dlopen_support=$enable_dlopen
+
+# Whether dlopen of programs is supported.
+dlopen_self=$enable_dlopen_self
+
+# Whether dlopen of statically linked programs is supported.
+dlopen_self_static=$enable_dlopen_self_static
+
+# Commands to strip libraries.
+old_striplib=$lt_old_striplib
+striplib=$lt_striplib
+
+
+# The linker used to build libraries.
+LD=$lt_LD
+
+# Commands used to build an old-style archive.
+old_archive_cmds=$lt_old_archive_cmds
+
+# A language specific compiler.
+CC=$lt_compiler
+
+# Is the compiler the GNU compiler?
+with_gcc=$GCC
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag
+
+# How to pass a linker flag through the compiler.
+wl=$lt_lt_prog_compiler_wl
+
+# Additional compiler flags for building library objects.
+pic_flag=$lt_lt_prog_compiler_pic
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag=$lt_lt_prog_compiler_static
+
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o=$lt_lt_cv_prog_compiler_c_o
+
+# Whether or not to add -lc for building shared libraries.
+build_libtool_need_lc=$archive_cmds_need_lc
+
+# Whether or not to disallow shared libs when runtime libs are static.
+allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec=$lt_export_dynamic_flag_spec
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec=$lt_whole_archive_flag_spec
+
+# Whether the compiler copes with passing no objects directly.
+compiler_needs_object=$lt_compiler_needs_object
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=$lt_old_archive_from_new_cmds
+
+# Create a temporary old-style archive to link instead of a shared archive.
+old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds
+
+# Commands used to build a shared archive.
+archive_cmds=$lt_archive_cmds
+archive_expsym_cmds=$lt_archive_expsym_cmds
+
+# Commands used to build a loadable module if different from building
+# a shared archive.
+module_cmds=$lt_module_cmds
+module_expsym_cmds=$lt_module_expsym_cmds
+
+# Whether we are building with GNU ld or not.
+with_gnu_ld=$lt_with_gnu_ld
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=$lt_allow_undefined_flag
+
+# Flag that enforces no undefined symbols.
+no_undefined_flag=$lt_no_undefined_flag
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist
+hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec
+
+# If ld is used when linking, flag to hardcode \$libdir into a binary
+# during linking. This must work even if \$libdir does not exist.
+hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld
+
+# Whether we need a single "-rpath" flag with a separated argument.
+hardcode_libdir_separator=$lt_hardcode_libdir_separator
+
+# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes
+# DIR into the resulting binary.
+hardcode_direct=$hardcode_direct
+
+# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes
+# DIR into the resulting binary and the resulting library dependency is
+# "absolute",i.e impossible to change by setting \${shlibpath_var} if the
+# library is relocated.
+hardcode_direct_absolute=$hardcode_direct_absolute
+
+# Set to "yes" if using the -LDIR flag during linking hardcodes DIR
+# into the resulting binary.
+hardcode_minus_L=$hardcode_minus_L
+
+# Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR
+# into the resulting binary.
+hardcode_shlibpath_var=$hardcode_shlibpath_var
+
+# Set to "yes" if building a shared library automatically hardcodes DIR
+# into the library and all subsequent libraries and executables linked
+# against it.
+hardcode_automatic=$hardcode_automatic
+
+# Set to yes if linker adds runtime paths of dependent libraries
+# to runtime path list.
+inherit_rpath=$inherit_rpath
+
+# Whether libtool must link a program against all its dependency libraries.
+link_all_deplibs=$link_all_deplibs
+
+# Fix the shell variable \$srcfile for the compiler.
+fix_srcfile_path=$lt_fix_srcfile_path
+
+# Set to "yes" if exported symbols are required.
+always_export_symbols=$always_export_symbols
+
+# The commands to list exported symbols.
+export_symbols_cmds=$lt_export_symbols_cmds
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms=$lt_exclude_expsyms
+
+# Symbols that must always be exported.
+include_expsyms=$lt_include_expsyms
+
+# Commands necessary for linking programs (against libraries) with templates.
+prelink_cmds=$lt_prelink_cmds
+
+# Specify filename containing input files.
+file_list_spec=$lt_file_list_spec
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=$hardcode_action
+
+# ### END LIBTOOL CONFIG
+
+_LT_EOF
+
+ case $host_os in
+ aix3*)
+ cat <<\_LT_EOF >> "$cfgfile"
+# AIX sometimes has problems with the GCC collect2 program. For some
+# reason, if we set the COLLECT_NAMES environment variable, the problems
+# vanish in a puff of smoke.
+if test "X${COLLECT_NAMES+set}" != Xset; then
+ COLLECT_NAMES=
+ export COLLECT_NAMES
+fi
+_LT_EOF
+ ;;
+ esac
+
+
+ltmain="$ac_aux_dir/ltmain.sh"
+
+
+ # We use sed instead of cat because bash on DJGPP gets confused if
+ # if finds mixed CR/LF and LF-only lines. Since sed operates in
+ # text mode, it properly converts lines to CR/LF. This bash problem
+ # is reportedly fixed, but why not run on old versions too?
+ sed '/^# Generated shell functions inserted here/q' "$ltmain" >> "$cfgfile" \
+ || (rm -f "$cfgfile"; exit 1)
+
+ case $xsi_shell in
+ yes)
+ cat << \_LT_EOF >> "$cfgfile"
+
+# func_dirname file append nondir_replacement
+# Compute the dirname of FILE. If nonempty, add APPEND to the result,
+# otherwise set result to NONDIR_REPLACEMENT.
+func_dirname ()
+{
+ case ${1} in
+ */*) func_dirname_result="${1%/*}${2}" ;;
+ * ) func_dirname_result="${3}" ;;
+ esac
+}
+
+# func_basename file
+func_basename ()
+{
+ func_basename_result="${1##*/}"
+}
+
+# func_dirname_and_basename file append nondir_replacement
+# perform func_basename and func_dirname in a single function
+# call:
+# dirname: Compute the dirname of FILE. If nonempty,
+# add APPEND to the result, otherwise set result
+# to NONDIR_REPLACEMENT.
+# value returned in "$func_dirname_result"
+# basename: Compute filename of FILE.
+# value retuned in "$func_basename_result"
+# Implementation must be kept synchronized with func_dirname
+# and func_basename. For efficiency, we do not delegate to
+# those functions but instead duplicate the functionality here.
+func_dirname_and_basename ()
+{
+ case ${1} in
+ */*) func_dirname_result="${1%/*}${2}" ;;
+ * ) func_dirname_result="${3}" ;;
+ esac
+ func_basename_result="${1##*/}"
+}
+
+# func_stripname prefix suffix name
+# strip PREFIX and SUFFIX off of NAME.
+# PREFIX and SUFFIX must not contain globbing or regex special
+# characters, hashes, percent signs, but SUFFIX may contain a leading
+# dot (in which case that matches only a dot).
+func_stripname ()
+{
+ # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are
+ # positional parameters, so assign one to ordinary parameter first.
+ func_stripname_result=${3}
+ func_stripname_result=${func_stripname_result#"${1}"}
+ func_stripname_result=${func_stripname_result%"${2}"}
+}
+
+# func_opt_split
+func_opt_split ()
+{
+ func_opt_split_opt=${1%%=*}
+ func_opt_split_arg=${1#*=}
+}
+
+# func_lo2o object
+func_lo2o ()
+{
+ case ${1} in
+ *.lo) func_lo2o_result=${1%.lo}.${objext} ;;
+ *) func_lo2o_result=${1} ;;
+ esac
+}
+
+# func_xform libobj-or-source
+func_xform ()
+{
+ func_xform_result=${1%.*}.lo
+}
+
+# func_arith arithmetic-term...
+func_arith ()
+{
+ func_arith_result=$(( $* ))
+}
+
+# func_len string
+# STRING may not start with a hyphen.
+func_len ()
+{
+ func_len_result=${#1}
+}
+
+_LT_EOF
+ ;;
+ *) # Bourne compatible functions.
+ cat << \_LT_EOF >> "$cfgfile"
+
+# func_dirname file append nondir_replacement
+# Compute the dirname of FILE. If nonempty, add APPEND to the result,
+# otherwise set result to NONDIR_REPLACEMENT.
+func_dirname ()
+{
+ # Extract subdirectory from the argument.
+ func_dirname_result=`$ECHO "X${1}" | $Xsed -e "$dirname"`
+ if test "X$func_dirname_result" = "X${1}"; then
+ func_dirname_result="${3}"
+ else
+ func_dirname_result="$func_dirname_result${2}"
+ fi
+}
+
+# func_basename file
+func_basename ()
+{
+ func_basename_result=`$ECHO "X${1}" | $Xsed -e "$basename"`
+}
+
+
+# func_stripname prefix suffix name
+# strip PREFIX and SUFFIX off of NAME.
+# PREFIX and SUFFIX must not contain globbing or regex special
+# characters, hashes, percent signs, but SUFFIX may contain a leading
+# dot (in which case that matches only a dot).
+# func_strip_suffix prefix name
+func_stripname ()
+{
+ case ${2} in
+ .*) func_stripname_result=`$ECHO "X${3}" \
+ | $Xsed -e "s%^${1}%%" -e "s%\\\\${2}\$%%"`;;
+ *) func_stripname_result=`$ECHO "X${3}" \
+ | $Xsed -e "s%^${1}%%" -e "s%${2}\$%%"`;;
+ esac
+}
+
+# sed scripts:
+my_sed_long_opt='1s/^\(-[^=]*\)=.*/\1/;q'
+my_sed_long_arg='1s/^-[^=]*=//'
+
+# func_opt_split
+func_opt_split ()
+{
+ func_opt_split_opt=`$ECHO "X${1}" | $Xsed -e "$my_sed_long_opt"`
+ func_opt_split_arg=`$ECHO "X${1}" | $Xsed -e "$my_sed_long_arg"`
+}
+
+# func_lo2o object
+func_lo2o ()
+{
+ func_lo2o_result=`$ECHO "X${1}" | $Xsed -e "$lo2o"`
+}
+
+# func_xform libobj-or-source
+func_xform ()
+{
+ func_xform_result=`$ECHO "X${1}" | $Xsed -e 's/\.[^.]*$/.lo/'`
+}
+
+# func_arith arithmetic-term...
+func_arith ()
+{
+ func_arith_result=`expr "$@"`
+}
+
+# func_len string
+# STRING may not start with a hyphen.
+func_len ()
+{
+ func_len_result=`expr "$1" : ".*" 2>/dev/null || echo $max_cmd_len`
+}
+
+_LT_EOF
+esac
+
+case $lt_shell_append in
+ yes)
+ cat << \_LT_EOF >> "$cfgfile"
+
+# func_append var value
+# Append VALUE to the end of shell variable VAR.
+func_append ()
+{
+ eval "$1+=\$2"
+}
+_LT_EOF
+ ;;
+ *)
+ cat << \_LT_EOF >> "$cfgfile"
+
+# func_append var value
+# Append VALUE to the end of shell variable VAR.
+func_append ()
+{
+ eval "$1=\$$1\$2"
+}
+
+_LT_EOF
+ ;;
+ esac
+
+
+ sed -n '/^# Generated shell functions inserted here/,$p' "$ltmain" >> "$cfgfile" \
+ || (rm -f "$cfgfile"; exit 1)
+
+ mv -f "$cfgfile" "$ofile" ||
+ (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile")
+ chmod +x "$ofile"
+
+ ;;
+
+ esac
+done # for ac_tag
+
+
+as_fn_exit 0
+_ACEOF
+ac_clean_files=$ac_clean_files_save
+
+test $ac_write_fail = 0 ||
+ as_fn_error "write failure creating $CONFIG_STATUS" "$LINENO" 5
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded. So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status. When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+ ac_cs_success=:
+ ac_config_status_args=
+ test "$silent" = yes &&
+ ac_config_status_args="$ac_config_status_args --quiet"
+ exec 5>/dev/null
+ $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+ exec 5>>config.log
+ # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+ # would make configure fail if this is the last instruction.
+ $ac_cs_success || as_fn_exit $?
+fi
+if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
+$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
+fi
+
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 0000000..559e4da
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,94 @@
+# -*- Autoconf -*-
+# Process this file with autoconf to produce a configure script.
+
+AC_INIT([Phidget21 C Library],m4_esyscmd([./version.sh]),[support@phidgets.com],[libphidget],[www.phidgets.com])
+AM_INIT_AUTOMAKE([-Wall])
+AC_CONFIG_MACRO_DIR([m4])
+LT_INIT
+AC_CONFIG_SRCDIR([cphidgetir.h])
+m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])])
+
+# Install in /usr
+AC_PREFIX_DEFAULT([/usr])
+
+# Checks for programs.
+AC_PROG_CC
+AC_PROG_LIBTOOL
+
+AC_ARG_VAR([LDCONFIG], [ldconfig utility])
+AC_PATH_PROG([LDCONFIG], [ldconfig], [true], [/sbin /usr/sbin $PATH])
+
+# Checks for libraries.
+AC_SEARCH_LIBS([dlopen], [dl], [],
+ AC_MSG_ERROR([Missing libdl!]))
+AC_SEARCH_LIBS([sqrt], [m], [],
+ AC_MSG_ERROR([Missing libm!]))
+AC_SEARCH_LIBS([pthread_join], [pthread], [],
+ AC_MSG_ERROR([Missing libpthread!]))
+AC_SEARCH_LIBS([usb_find_busses], [usb], [],
+ AC_MSG_ERROR([Missing libusb!]))
+# we need iconv - if it's not available in libc, look for the 'libiconv' function from libiconv.so
+AC_SEARCH_LIBS([iconv], [iconv], [],
+ AC_SEARCH_LIBS([libiconv], [iconv], [],
+ [internaluniconv=true]))
+
+AC_ARG_ENABLE([jni],
+[ --enable-jni Compile in Java support],
+[case "${enableval}" in
+ yes) jni=true ;;
+ no) jni=false ;;
+ *) AC_MSG_ERROR([bad value ${enableval} for --enable-jni]) ;;
+esac],[jni=true])
+AM_CONDITIONAL([JNI], [test x$jni = xtrue])
+
+AC_ARG_ENABLE([debug],
+[ --enable-debug Turn on debugging],
+[case "${enableval}" in
+ yes) debug=true ;;
+ no) debug=false ;;
+ *) AC_MSG_ERROR([bad value ${enableval} for --enable-debug]) ;;
+esac],[debug=false])
+AM_CONDITIONAL([DEBUG], [test x$debug = xtrue])
+
+AC_ARG_ENABLE([zeroconf],
+[ --enable-zeroconf Turn on zeroconf, choose avahi or bonjour],
+[case "${enableval}" in
+ yes) zeroconf=avahi ;;
+ avahi) zeroconf=avahi ;;
+ bonjour) zeroconf=bonjour ;;
+ no) zeroconf=false ;;
+ *) AC_MSG_ERROR([bad value ${enableval} for --enable-zeroconf]) ;;
+esac],[zeroconf=avahi])
+AM_CONDITIONAL([ZEROCONF_AVAHI], [test x$zeroconf = xavahi])
+AM_CONDITIONAL([ZEROCONF_BONJOUR], [test x$zeroconf = xbonjour])
+AM_CONDITIONAL([ZEROCONF], [test x$zeroconf != xfalse])
+
+AC_ARG_ENABLE([zeroconf-lookup],
+[ --enable-zeroconf-lookup Turn on zeroconf lookup],
+[case "${enableval}" in
+ yes) zeroconflookup=true ;;
+ no) zeroconflookup=false ;;
+ *) AC_MSG_ERROR([bad value ${enableval} for --enable-zeroconf-lookup]) ;;
+esac],[zeroconflookup=false])
+AM_CONDITIONAL([ZEROCONF_LOOKUP], [test x$zeroconflookup = xtrue])
+
+AC_ARG_ENABLE([labview],
+[ --enable-labview Turn on Labview support],
+[case "${enableval}" in
+ yes) labview=true ;;
+ no) labview=false ;;
+ *) AC_MSG_ERROR([bad value ${enableval} for --enable-labview]) ;;
+esac],[labview=false])
+AM_CONDITIONAL([LABVIEW], [test x$labview = xtrue])
+
+AC_ARG_ENABLE([ldconfig],
+[AS_HELP_STRING([--disable-ldconfig],[do not update dynamic linker cache using ldconfig])],
+,
+[enable_ldconfig="yes"])
+AM_CONDITIONAL([RUN_LDCONFIG], [test "${enable_ldconfig}" = "yes"])
+
+AM_CONDITIONAL([INTERNAL_UNICONV], [test x$internaluniconv = xtrue])
+
+AC_CONFIG_FILES([Makefile
+ examples/Makefile])
+AC_OUTPUT
diff --git a/cphidget.c b/cphidget.c
new file mode 100644
index 0000000..d8d5cb3
--- /dev/null
+++ b/cphidget.c
@@ -0,0 +1,1637 @@
+#include "stdafx.h"
+#include "cphidget.h"
+#include "cusb.h"
+#include "csocket.h"
+#include "cthread.h"
+#include "cphidgetlist.h"
+#include "utils.h"
+
+int print_debug_messages = FALSE;
+
+CPhidgetListHandle ActiveDevices = 0;
+CPhidgetListHandle AttachedDevices = 0;
+
+/* Protects ActiveDevices and AttachedDevices */
+int phidgetLocksInitialized = PFALSE;
+CThread_mutex_t activeDevicesLock;
+CThread_mutex_t attachedDevicesLock;
+
+char
+translate_bool_to_ascii(char value)
+{
+ switch (value) {
+ case PTRUE:
+ return '1';
+ case PFALSE:
+ return '0';
+ }
+ return '?';
+}
+
+int CCONV phidget_type_to_id(const char *name)
+{
+ int i;
+ for(i=0;i<PHIDGET_DEVICE_CLASS_COUNT;i++)
+ {
+ if(Phid_DeviceName[i] != NULL)
+ {
+ if(!strcmp(Phid_DeviceName[i],name))
+ return i;
+ }
+ }
+ return -1;
+}
+
+//returns ms
+double timestampdiff(CPhidget_Timestamp time1, CPhidget_Timestamp time2)
+{
+ return ((time1.seconds * 1000) + (double)(time1.microseconds / 1000.0)) - ((time2.seconds * 1000) + (double)(time2.microseconds / 1000.0));
+}
+
+double timeSince(TIME *start)
+{
+#ifdef _WINDOWS
+ TIME now;
+ FILETIME nowft, oldft, resft;
+ ULARGE_INTEGER nowul, oldul, resul;
+ double duration;
+ GetSystemTime(&now);
+ SystemTimeToFileTime(&now, &nowft);
+ SystemTimeToFileTime(start, &oldft);
+
+ nowul.HighPart = nowft.dwHighDateTime;
+ nowul.LowPart = nowft.dwLowDateTime;
+ oldul.HighPart = oldft.dwHighDateTime;
+ oldul.LowPart = oldft.dwLowDateTime;
+
+ resul.HighPart = nowul.HighPart - oldul.HighPart;
+ resul.LowPart = nowul.LowPart - oldul.LowPart;
+
+ resft.dwHighDateTime = resul.HighPart;
+ resft.dwLowDateTime = resul.LowPart;
+
+ duration = (double)(resft.dwLowDateTime/10000000.0);
+#else
+ struct timeval now;
+ gettimeofday(&now, NULL);
+ double duration = (now.tv_sec - start->tv_sec) + (double)((now.tv_usec-start->tv_usec)/1000000.0);
+#endif
+ return duration;
+}
+
+void setTimeNow(TIME *now)
+{
+ #ifdef _WINDOWS
+ GetSystemTime(now);
+ #else
+ gettimeofday(now,NULL);
+ #endif
+}
+
+/* The is a void pointer that gets malloced only of some platforms */
+void CPhidgetFHandle_free(void *arg)
+{
+ #if defined(_MACOSX) || defined(WINCE)
+ return;
+ #else
+ free(arg); arg = NULL;
+ return;
+ #endif
+}
+
+//Two different Phidget Handles that refer to the same Physical Phidget
+int CCONV CPhidget_areEqual(void *arg1, void *arg2)
+{
+ CPhidgetHandle phid1 = (CPhidgetHandle)arg1;
+ CPhidgetHandle phid2 = (CPhidgetHandle)arg2;
+
+ if(!phid1 || !phid2)
+ return PFALSE;
+
+ // If they are not the same device class
+ if(phid2->deviceID != phid1->deviceID)
+ return PFALSE;
+
+ // If they both have a device id, but they are different
+ if(phid1->deviceIDSpec && phid2->deviceIDSpec && (phid2->deviceIDSpec != phid1->deviceIDSpec))
+ return PFALSE;
+
+ // Neither device is marked as PHIDGETOPEN_ANY
+ if(phid1->specificDevice && phid2->specificDevice)
+ {
+ // If one is open serial and the other is open label
+ if(phid1->specificDevice == PHIDGETOPEN_SERIAL && phid2->specificDevice == PHIDGETOPEN_LABEL ||
+ phid1->specificDevice == PHIDGETOPEN_LABEL && phid2->specificDevice == PHIDGETOPEN_SERIAL)
+ return PFALSE;
+
+ // If one is open serial but they have different serials
+ if((phid1->specificDevice == PHIDGETOPEN_SERIAL || phid2->specificDevice == PHIDGETOPEN_SERIAL) &&
+ phid2->serialNumber != phid1->serialNumber)
+ return PFALSE;
+
+ // If one is open label but they have different labels
+ if((phid1->specificDevice == PHIDGETOPEN_LABEL || phid2->specificDevice == PHIDGETOPEN_LABEL) &&
+ strncmp(phid1->label, phid2->label, MAX_LABEL_STORAGE-1))
+ return PFALSE;
+ }
+
+ return PTRUE;
+
+ //OLD
+ /*if(
+ (
+ (phid1->specificDevice == 0 || phid2->specificDevice == 0)?1:(phid2->serialNumber == phid1->serialNumber))
+ &&
+ (
+ (phid1->deviceIDSpec == 0 || phid2->deviceIDSpec == 0)?1:(phid2->deviceIDSpec == phid1->deviceIDSpec)
+ ) &&
+ (phid2->deviceID == phid1->deviceID))
+ return 1;
+ return 0;*/
+}
+
+//Two different Phidget Handles that refer to the same Physical Phidget - more stringent
+// Same serial, device class and device id
+int CCONV CPhidget_areExtraEqual(void *arg1, void *arg2)
+{
+ CPhidgetHandle phid1 = (CPhidgetHandle)arg1;
+ CPhidgetHandle phid2 = (CPhidgetHandle)arg2;
+
+ if(!phid1 || !phid2)
+ return PFALSE;
+
+ if(
+ (phid2->serialNumber == phid1->serialNumber) &&
+ (phid2->deviceIDSpec == phid1->deviceIDSpec) &&
+ (phid2->deviceID == phid1->deviceID)
+ )
+ return PTRUE;
+ return PFALSE;
+}
+
+//Two identical Phidget Handles (same pointer)
+int CCONV CPhidgetHandle_areEqual(void *arg1, void *arg2)
+{
+ if(arg1 == arg2) return 1;
+ return 0;
+}
+
+void CPhidgetErrorEvent_free(void *arg)
+{
+ free(((void **)arg)[0]);
+ free(arg);
+}
+
+void CCONV CPhidget_free(void *arg)
+{
+ CPhidgetHandle phid = (CPhidgetHandle)arg;
+ if (!phid)
+ return;
+
+ //Call device specific free function if it exists
+ if(phid->fptrFree)
+ phid->fptrFree(phid);
+
+ //this is only malloc-ed on windows and linux, not wince or mac
+#if (defined(_WINDOWS) && !defined(WINCE)) || defined(_LINUX) || defined(_ANDROID)
+ if (phid->CPhidgetFHandle) {
+ CPhidgetFHandle_free(phid->CPhidgetFHandle); phid->CPhidgetFHandle = NULL;
+ }
+#endif
+
+ CThread_mutex_destroy(&phid->lock);
+ CThread_mutex_destroy(&phid->openCloseLock);
+ CThread_mutex_destroy(&phid->writelock);
+ CThread_mutex_destroy(&phid->outputLock);
+ CThread_destroy_event(&phid->writeAvailableEvent);
+ CThread_destroy_event(&phid->writtenEvent);
+
+ CList_emptyList((CListHandle *)&phid->errEventList, PTRUE, CPhidgetErrorEvent_free);
+
+ free(phid); phid = NULL;
+ return;
+}
+
+int CCONV CPhidget_create(CPhidgetHandle *phid)
+{
+ CPhidgetHandle temp_phid;
+
+ TESTPTR(phid)
+
+ if(!(temp_phid = malloc(sizeof(CPhidget))))
+ return EPHIDGET_NOMEMORY;
+ ZEROMEM(temp_phid, sizeof(CPhidget));
+
+ CThread_mutex_init(&temp_phid->lock);
+ CThread_mutex_init(&temp_phid->openCloseLock);
+ CThread_mutex_init(&temp_phid->writelock);
+ CThread_mutex_init(&temp_phid->outputLock);
+ CThread_create_event(&temp_phid->writeAvailableEvent);
+ CThread_create_event(&temp_phid->writtenEvent);
+
+ CPhidget_clearStatusFlag(&temp_phid->status, PHIDGET_ATTACHED_FLAG, &temp_phid->lock);
+
+ *phid = temp_phid;
+
+ return EPHIDGET_OK;
+}
+
+const char *CPhidget_strerror(int error)
+{
+ if ((error < 0) || (error >= PHIDGET_ERROR_CODE_COUNT))
+ return Phid_UnknownErrorDescription;
+
+ return Phid_ErrorDescriptions[error];
+}
+
+int CPhidget_statusFlagIsSet(int status, int flag)
+{
+ if(status & flag) return PTRUE;
+ return PFALSE;
+}
+
+//status is a flags variable
+int CPhidget_setStatusFlag(int *status, int flag, CThread_mutex_t *lock)
+{
+ TESTPTR(status)
+
+ if(lock != NULL) CThread_mutex_lock(lock);
+ *status |= flag;
+ if(lock != NULL) CThread_mutex_unlock(lock);
+
+ return EPHIDGET_OK;
+}
+
+int CPhidget_clearStatusFlag(int *status, int flag, CThread_mutex_t *lock)
+{
+ TESTPTR(status)
+
+ if(lock != NULL) CThread_mutex_lock(lock);
+ *status &= (~flag);
+ if(lock != NULL) CThread_mutex_unlock(lock);
+
+ return EPHIDGET_OK;
+}
+
+int CPhidget_read(CPhidgetHandle phid)
+{
+ int result = EPHIDGET_OK;
+
+ TESTPTR(phid)
+
+ if (CPhidget_statusFlagIsSet(phid->status, PHIDGET_ATTACHED_FLAG)
+ || CPhidget_statusFlagIsSet(phid->status, PHIDGET_ATTACHING_FLAG)) {
+ result = CUSBReadPacket((CPhidgetHandle)phid,
+ phid->lastReadPacket);
+ if (result) return result;
+ if (phid->fptrData)
+ result= phid->fptrData((CPhidgetHandle)phid,
+ phid->lastReadPacket, phid->inputReportByteLength);
+ return result;
+ }
+ return EPHIDGET_NOTATTACHED;
+}
+
+
+int CPhidget_write(CPhidgetHandle phid)
+{
+ unsigned char buffer[MAX_OUT_PACKET_SIZE];
+ unsigned int len;
+ int result = EPHIDGET_OK;
+
+ TESTPTR(phid)
+
+ ZEROMEM(buffer, sizeof(buffer));
+
+ CThread_reset_event(&phid->writeAvailableEvent);
+
+ len = MAX_OUT_PACKET_SIZE;
+ if ((result = phid->fptrGetPacket((CPhidgetHandle)phid, buffer, &len))
+ != EPHIDGET_OK)
+ goto fail;
+ // XXX len ignored
+ if ((result = CUSBSendPacket((CPhidgetHandle)phid, buffer)) !=
+ EPHIDGET_OK)
+ goto fail;
+fail:
+ /*
+ * under all circumstances (especially failure), signal
+ * waiting writers to loop around and check device status.
+ */
+ CThread_set_event(&phid->writtenEvent);
+ return result;
+}
+//Begin exported functions
+int CCONV
+CPhidget_open(CPhidgetHandle phid, int serialNumber)
+{
+ int result = 0;
+ TESTPTR(phid)
+ if (serialNumber < -1)
+ return EPHIDGET_INVALIDARG;
+
+#if defined(_IPHONE)
+ return EPHIDGET_UNSUPPORTED;
+#endif
+
+#if defined(_ANDROID)
+ if(!ANDROID_USB_GOOD)
+ return EPHIDGET_UNSUPPORTED;
+#endif
+
+ CThread_mutex_lock(&phid->openCloseLock);
+ if (CPhidget_statusFlagIsSet(phid->status, PHIDGET_OPENED_FLAG))
+ {
+ LOG(PHIDGET_LOG_WARNING, "Open was called on an already opened Phidget handle.");
+ CThread_mutex_unlock(&phid->openCloseLock);
+ return EPHIDGET_OK;
+ }
+
+ if (serialNumber == -1)
+ phid->specificDevice = PHIDGETOPEN_ANY;
+ else
+ phid->specificDevice = PHIDGETOPEN_SERIAL;
+ phid->serialNumber = serialNumber;
+
+ result = RegisterLocalDevice(phid);
+
+ CPhidget_setStatusFlag(&phid->status, PHIDGET_OPENED_FLAG, &phid->lock);
+ CThread_mutex_unlock(&phid->openCloseLock);
+
+ return result;
+}
+
+int CCONV
+CPhidget_openLabel(CPhidgetHandle phid, const char *label)
+{
+ int result = 0;
+ TESTPTR(phid)
+
+#if defined(_IPHONE)
+ return EPHIDGET_UNSUPPORTED;
+#endif
+
+#if defined(_ANDROID)
+ if(!ANDROID_USB_GOOD)
+ return EPHIDGET_UNSUPPORTED;
+#endif
+
+ if(label != NULL && ((result = encodeLabelString(label, NULL, NULL)) != EPHIDGET_OK))
+ return result;
+
+ CThread_mutex_lock(&phid->openCloseLock);
+ if (CPhidget_statusFlagIsSet(phid->status, PHIDGET_OPENED_FLAG))
+ {
+ LOG(PHIDGET_LOG_WARNING, "Open was called on an already opened Phidget handle.");
+ CThread_mutex_unlock(&phid->openCloseLock);
+ return EPHIDGET_OK;
+ }
+
+ if (label == NULL)
+ phid->specificDevice = PHIDGETOPEN_ANY;
+ else
+ {
+ phid->specificDevice = PHIDGETOPEN_LABEL;
+ memcpy(phid->label, label, strlen(label)+1);
+ }
+
+ result = RegisterLocalDevice(phid);
+
+ CPhidget_setStatusFlag(&phid->status, PHIDGET_OPENED_FLAG, &phid->lock);
+ CThread_mutex_unlock(&phid->openCloseLock);
+
+ return result;
+}
+
+int CCONV
+CPhidget_close(CPhidgetHandle phid)
+{
+ int result = EPHIDGET_OK;
+
+ char key[1024], val[6];
+
+ TESTPTR(phid)
+
+ CThread_mutex_lock(&phid->openCloseLock);
+ if (!CPhidget_statusFlagIsSet(phid->status, PHIDGET_OPENED_FLAG))
+ {
+ //Could be .NET finalizer - always calls close even if already called.
+ LOG(PHIDGET_LOG_INFO, "Close was called on an already closed Phidget handle.");
+ CThread_mutex_unlock(&phid->openCloseLock);
+ return EPHIDGET_OK;
+ }
+
+ //Call device specific close function if it exists
+ if(phid->fptrClose)
+ phid->fptrClose(phid);
+
+ if(CPhidget_statusFlagIsSet(phid->status, PHIDGET_REMOTE_FLAG))
+ {
+ CThread_mutex_lock(&phid->lock);
+ if(CPhidget_statusFlagIsSet(phid->status, PHIDGET_SERVER_CONNECTED_FLAG))
+ {
+ struct sockaddr_storage name;
+ char addr[200], *a;
+ socklen_t namelen = sizeof(name);
+ int port, e;
+
+ if(getsockname(phid->networkInfo->server->socket, (struct sockaddr *)&name, &namelen) != 0)
+ {
+#ifndef _WINDOWS
+ LOG(PHIDGET_LOG_WARNING,"getsockname: %s", strerror(errno));
+#else
+ LOG(PHIDGET_LOG_WARNING,"getsockname: WSA Error %d", WSAGetLastError());
+#endif
+ goto netdone;
+ }
+ if((e = getnameinfo((struct sockaddr *)&name, namelen, addr, sizeof(addr), NULL, 0, NI_NUMERICHOST)) != 0)
+ {
+ LOG(PHIDGET_LOG_WARNING,"getnameinfo: %s", gai_strerror(e));
+ goto netdone;
+ }
+ port = (int)((struct sockaddr_in *)&name)->sin_port;
+ escape(addr, strlen(addr), &a);
+
+ if(phid->specificDevice == PHIDGETOPEN_SERIAL)
+ snprintf(key, sizeof(key), "/PCK/Client/%s/%d%05d/%s/%d", a, phid->networkInfo->uniqueConnectionID, port, Phid_DeviceName[phid->deviceID], phid->serialNumber);
+ else if(phid->specificDevice == PHIDGETOPEN_LABEL)
+ {
+ char *l;
+ escape(phid->label, strlen(phid->label), &l);
+ snprintf(key, sizeof(key), "/PCK/Client/%s/%d%05d/%s/-1/%s", a, phid->networkInfo->uniqueConnectionID, port, Phid_DeviceName[phid->deviceID], l);
+ free(l);
+ }
+ else
+ snprintf(key, sizeof(key), "/PCK/Client/%s/%d%05d/%s", a, phid->networkInfo->uniqueConnectionID, port, Phid_DeviceName[phid->deviceID]);
+ snprintf(val, sizeof(val), "Close");
+ free(a);
+ //don't care about errors on this, so we don't add the error handler - just close already!
+ pdc_async_set(phid->networkInfo->server->pdcs, key, val, (int)strlen(val), PTRUE, NULL, NULL);
+ }
+netdone:
+ CThread_mutex_unlock(&phid->lock);
+
+ result = unregisterRemotePhidget(phid);
+
+ phid->keyCount = 0;
+ }
+ else
+ {
+ if(!phidgetLocksInitialized)
+ {
+ CThread_mutex_init(&activeDevicesLock);
+ CThread_mutex_init(&attachedDevicesLock);
+ phidgetLocksInitialized = PTRUE;
+ }
+ CThread_mutex_lock(&activeDevicesLock);
+ CList_removeFromList((CListHandle *)&ActiveDevices, phid, CPhidget_areEqual, FALSE, NULL);
+ CThread_mutex_unlock(&activeDevicesLock);
+ if (CPhidget_statusFlagIsSet(phid->status, PHIDGET_ATTACHED_FLAG)) {
+ phid->writeStopFlag = PTRUE;
+ CThread_join(&phid->writeThread); //join before closing because we want to wait for outstanding writes to complete
+ result = CUSBCloseHandle(phid);
+ CThread_join(&phid->readThread);
+ }
+
+ if(phid->specificDevice == PHIDGETOPEN_ANY_ATTACHED)
+ {
+ phid->specificDevice = PHIDGETOPEN_ANY;
+ phid->serialNumber = -1;
+ }
+
+ //if there are no more active phidgets or managers, wait for the central thread to exit
+ if(!ActiveDevices && !ActivePhidgetManagers)
+ {
+ JoinCentralThread();
+ }
+ }
+ CPhidget_clearStatusFlag(&phid->status, PHIDGET_OPENED_FLAG, &phid->lock);
+
+ CThread_mutex_unlock(&phid->openCloseLock);
+ return result;
+}
+
+//TODO: maybe this should take (CPhidgetHandle *) so that we can nulify the pointer
+// (and handle multiple calls to CPhidget_delete)
+int CCONV
+CPhidget_delete(CPhidgetHandle phid)
+{
+ CPhidget_free(phid);
+ return EPHIDGET_OK;
+}
+
+int CCONV
+CPhidget_set_OnDetach_Handler(CPhidgetHandle phid,
+ int(CCONV *fptr)(CPhidgetHandle, void *), void *userPtr)
+{
+ TESTPTR(phid)
+ phid->fptrDetach = fptr;
+ phid->fptrDetachptr = userPtr;
+ return EPHIDGET_OK;
+}
+
+int CCONV
+CPhidget_set_OnAttach_Handler(CPhidgetHandle phid,
+ int(CCONV *fptr)(CPhidgetHandle, void *), void *userPtr)
+{
+ TESTPTR(phid)
+ phid->fptrAttach = fptr;
+ phid->fptrAttachptr = userPtr;
+ return EPHIDGET_OK;
+}
+
+int CCONV
+CPhidget_set_OnError_Handler(CPhidgetHandle phid,
+ int (CCONV *fptr) (CPhidgetHandle, void *, int, const char *), void *userPtr)
+{
+ TESTPTR(phid)
+ phid->fptrError = fptr;
+ phid->fptrErrorptr = userPtr;
+ return EPHIDGET_OK;
+}
+int CCONV CPhidget_set_OnServerConnect_Handler(CPhidgetHandle phid, int (CCONV *fptr)(CPhidgetHandle phid, void *userPtr), void *userPtr)
+{
+ TESTPTR(phid)
+ phid->fptrServerConnect = fptr;
+ phid->fptrServerConnectptr = userPtr;
+ return EPHIDGET_OK;
+}
+int CCONV CPhidget_set_OnServerDisconnect_Handler(CPhidgetHandle phid, int (CCONV *fptr)(CPhidgetHandle phid, void *userPtr), void *userPtr)
+{
+ TESTPTR(phid)
+ phid->fptrServerDisconnect = fptr;
+ phid->fptrServerDisconnectptr = userPtr;
+ return EPHIDGET_OK;
+}
+
+int CCONV
+CPhidget_getDeviceName(CPhidgetHandle phid, const char **buffer)
+{
+ TESTPTRS(phid, buffer)
+ if (!CPhidget_statusFlagIsSet(phid->status, PHIDGET_ATTACHED_FLAG)
+ && !CPhidget_statusFlagIsSet(phid->status, PHIDGET_DETACHING_FLAG))
+ return EPHIDGET_NOTATTACHED;
+
+ *buffer = (char *)phid->deviceDef->pdd_name;
+ return EPHIDGET_OK;
+}
+
+int CCONV
+CPhidget_getSerialNumber(CPhidgetHandle phid, int *serialNumber)
+{
+ TESTPTRS(phid, serialNumber)
+ if (!CPhidget_statusFlagIsSet(phid->status, PHIDGET_ATTACHED_FLAG)
+ && !CPhidget_statusFlagIsSet(phid->status, PHIDGET_DETACHING_FLAG))
+ return EPHIDGET_NOTATTACHED;
+
+ *serialNumber = phid->serialNumber;
+ return EPHIDGET_OK;
+}
+
+int CCONV
+CPhidget_getDeviceVersion(CPhidgetHandle phid, int *devVer)
+{
+ TESTPTRS(phid, devVer)
+ if (!CPhidget_statusFlagIsSet(phid->status, PHIDGET_ATTACHED_FLAG)
+ && !CPhidget_statusFlagIsSet(phid->status, PHIDGET_DETACHING_FLAG))
+ return EPHIDGET_NOTATTACHED;
+
+ *devVer = phid->deviceVersion;
+ return EPHIDGET_OK;
+}
+
+/* for now this just returns the attached bit of the status variable - this function should probably be renamed*/
+// This CAN be called on closed devices, this should NOT be called internally as it is confusing
+int CCONV
+CPhidget_getDeviceStatus(CPhidgetHandle phid, int *status)
+{
+ TESTPTRS(phid, status)
+
+ *status = CPhidget_statusFlagIsSet(phid->status, PHIDGET_ATTACHED_FLAG);
+ return EPHIDGET_OK;
+}
+
+/* for now this just returns the attached bit of the status variable */
+int CCONV
+CPhidget_getServerStatus(CPhidgetHandle phid, int *status)
+{
+ TESTPTRS(phid, status)
+
+ if (!CPhidget_statusFlagIsSet(phid->status, PHIDGET_REMOTE_FLAG))
+ return EPHIDGET_UNSUPPORTED;
+
+ CThread_mutex_lock(&phid->lock);
+ if(CPhidget_statusFlagIsSet(phid->status, PHIDGET_SERVER_CONNECTED_FLAG))
+ if(phid->networkInfo->server)
+ *status = CPhidget_statusFlagIsSet(phid->networkInfo->server->status, PHIDGETSOCKET_CONNECTED_FLAG);
+ else
+ *status = PFALSE;
+ else
+ *status = PFALSE;
+ CThread_mutex_unlock(&phid->lock);
+
+ return EPHIDGET_OK;
+}
+
+
+int CCONV
+CPhidget_getLibraryVersion(const char **buffer)
+{
+ TESTPTR(buffer)
+ *buffer = LibraryVersion;
+ return EPHIDGET_OK;
+}
+
+int CCONV
+CPhidget_getDeviceType(CPhidgetHandle phid, const char **buffer)
+{
+ TESTPTRS(phid, buffer)
+ if (!CPhidget_statusFlagIsSet(phid->status, PHIDGET_ATTACHED_FLAG)
+ && !CPhidget_statusFlagIsSet(phid->status, PHIDGET_DETACHING_FLAG))
+ return EPHIDGET_NOTATTACHED;
+
+ *buffer = (char *)Phid_DeviceName[phid->deviceID];
+ return EPHIDGET_OK;
+}
+
+int CCONV
+CPhidget_getDeviceID(CPhidgetHandle phid, CPhidget_DeviceID *deviceID)
+{
+ TESTPTRS(phid, deviceID)
+ if (!CPhidget_statusFlagIsSet(phid->status, PHIDGET_ATTACHED_FLAG)
+ && !CPhidget_statusFlagIsSet(phid->status, PHIDGET_DETACHING_FLAG))
+ return EPHIDGET_NOTATTACHED;
+
+ *deviceID = phid->deviceIDSpec;
+ return EPHIDGET_OK;
+}
+
+int CCONV
+CPhidget_getDeviceClass(CPhidgetHandle phid, CPhidget_DeviceClass *deviceClass)
+{
+ TESTPTRS(phid, deviceClass)
+ if (!CPhidget_statusFlagIsSet(phid->status, PHIDGET_ATTACHED_FLAG)
+ && !CPhidget_statusFlagIsSet(phid->status, PHIDGET_DETACHING_FLAG))
+ return EPHIDGET_NOTATTACHED;
+
+ *deviceClass = phid->deviceID;
+ return EPHIDGET_OK;
+}
+
+int CCONV
+CPhidget_getDeviceLabel(CPhidgetHandle phid, const char **buffer)
+{
+ TESTPTRS(phid, buffer)
+ if (!CPhidget_statusFlagIsSet(phid->status, PHIDGET_ATTACHED_FLAG)
+ && !CPhidget_statusFlagIsSet(phid->status, PHIDGET_DETACHING_FLAG))
+ return EPHIDGET_NOTATTACHED;
+
+ *buffer = (char *)phid->label;
+ return EPHIDGET_OK;
+}
+
+int CCONV
+CPhidget_setDeviceLabel(CPhidgetHandle phid, const char *buffer)
+{
+ int ret = EPHIDGET_OK;
+ TESTPTRS(phid, buffer)
+ if (!CPhidget_statusFlagIsSet(phid->status, PHIDGET_ATTACHED_FLAG))
+ return EPHIDGET_NOTATTACHED;
+
+ if(CPhidget_statusFlagIsSet(phid->status, PHIDGET_REMOTE_FLAG))
+ {
+ char key[1024];
+
+ if((ret = encodeLabelString(buffer, NULL, NULL)) != EPHIDGET_OK)
+ return ret;
+
+ snprintf(key, sizeof(key), "/PCK/%s/%d/Label", phid->deviceType, phid->serialNumber);
+ CThread_mutex_lock(&phid->lock);
+ if(!CPhidget_statusFlagIsSet(phid->status, PHIDGET_SERVER_CONNECTED_FLAG))
+ {
+ CThread_mutex_unlock(&phid->lock);
+ return EPHIDGET_NETWORK_NOTCONNECTED;
+ }
+ pdc_async_set(phid->networkInfo->server->pdcs, key, buffer, (int)strlen(buffer), PFALSE, internal_async_network_error_handler, phid);
+ CThread_mutex_unlock(&phid->lock);
+ return EPHIDGET_OK;
+ }
+ else
+ {
+
+#if defined(_WINDOWS) && !defined(WINCE)
+ //setLabel not supported on Windows only (Windows CE does support it)
+ return EPHIDGET_UNSUPPORTED;
+#else
+ int len;
+ char buffer2[(MAX_LABEL_SIZE * 2) + 2];
+ ZEROMEM(buffer2, (MAX_LABEL_SIZE * 2) + 2);
+
+ len = (MAX_LABEL_SIZE * 2);
+ if((ret = encodeLabelString(buffer, &buffer2[2], &len)) == EPHIDGET_OK)
+ {
+ //length of descriptor
+ buffer2[0] = len+2;
+ //type of descriptor (string)
+ buffer2[1] = 3;
+
+ //make sure we're not trying to set a label that will match the wrap-around bug when read back
+ if(labelHasWrapError(phid->serialNumber, buffer2) == PTRUE)
+ {
+ LOG(PHIDGET_LOG_WARNING, "Can't set a label that would match the wraparound bug.");
+ return EPHIDGET_INVALIDARG;
+ }
+
+ if ((ret = CUSBSetLabel(phid, buffer2)) == EPHIDGET_OK)
+ {
+ int triedUTF8 = PFALSE;
+
+ refresh:
+ //read back the label and compare it
+ if ((ret = CUSBRefreshLabelString(phid)) == EPHIDGET_OK)
+ {
+ CPhidgetHandle foundPhidget;
+
+ //label read back didn't match
+ if(strcmp(buffer, phid->label))
+ {
+ //label descriptor is longer then 16 bytes and the first 7 bytes back match;
+ // almost certainly this is a problem with the wrap around bug.
+ if(buffer2[0] > 16 && !strncmp(buffer, phid->label, 7) && triedUTF8 == PFALSE)
+ {
+ //try setting the label as UTF-8 with 0xFFFF header - we can encode up to 12 bytes
+ if(strlen(buffer) <= 12)
+ {
+ LOG(PHIDGET_LOG_INFO, "Trying to setLabel as UTF-8 because of wrap around bug.");
+
+ //only try this once
+ triedUTF8 = PTRUE;
+
+ strcpy(&buffer2[4], buffer);
+ buffer2[0] = strlen(buffer) + 4;
+ buffer2[2] = 0xFF;
+ buffer2[3] = 0xFF;
+
+ if ((ret = CUSBSetLabel(phid, buffer2)) == EPHIDGET_OK)
+ {
+ //go check it
+ goto refresh;
+ }
+ else //setLabel failed
+ {
+ LOG(PHIDGET_LOG_ERROR, "Something unexpected happened trying to set the label (UTF-8). Try again.");
+ goto clearlabel;
+ }
+ }
+ else //label is too long to be stored, but we have tried to write the label, so we need to clear out anything stored
+ {
+ ret = EPHIDGET_INVALIDARG;
+ LOG(PHIDGET_LOG_ERROR, "This device supports 12-bytes UTF-8 labels. Try again with a shorter string, or pure ASCII.");
+ goto clearlabel;
+ }
+ }
+ else //label doesn't match and it doesn't look like the wrap around error
+ {
+ ret = EPHIDGET_UNEXPECTED;
+ LOG(PHIDGET_LOG_ERROR, "set label doesn't match read back label: \"%s\" vs. \"%s\"", buffer, phid->label);
+ goto clearlabel;
+ }
+ }
+ else //label matches, we're good
+ {
+ //update label in PhidgetManager
+ CThread_mutex_lock(&attachedDevicesLock);
+ if(CList_findInList((CListHandle)AttachedDevices, phid, CPhidget_areEqual, (void **)&foundPhidget) == EPHIDGET_OK)
+ {
+ strcpy(foundPhidget->label, buffer);
+ }
+ CThread_mutex_unlock(&attachedDevicesLock);
+ }
+ }
+ else
+ {
+ LOG(PHIDGET_LOG_ERROR, "Was unable to read back the label after setting.");
+ goto clearlabel;
+ }
+ }
+ else
+ {
+ LOG(PHIDGET_LOG_ERROR, "Something unexpected happened trying to set the label. Try again.");
+ return ret;
+ }
+ }
+ else
+ {
+ LOG(PHIDGET_LOG_ERROR, "Error encoding label string, not setting label.");
+ return ret;
+ }
+
+ //Success!
+ return EPHIDGET_OK;
+
+ //if a setLabel succeeded, but then we got an error verifying, then we should just clear the label so there's nothing funky in there.
+ clearlabel:
+ LOG(PHIDGET_LOG_INFO, "Clearing label because of an error during set.");
+ ZEROMEM(buffer2, (MAX_LABEL_SIZE * 2) + 2);
+ buffer2[0] = 2;
+ buffer2[1] = 3;
+ CUSBSetLabel(phid, buffer2);
+ return ret;
+#endif
+ }
+}
+
+int CCONV
+CPhidget_getServerID(CPhidgetHandle phid, const char **buffer)
+{
+ TESTPTRS(phid, buffer)
+
+#ifdef USE_ZEROCONF
+ if (!CPhidget_statusFlagIsSet(phid->status, PHIDGET_REMOTE_FLAG))
+ return EPHIDGET_UNSUPPORTED;
+
+ CThread_mutex_lock(&phid->lock);
+
+ if(!phid->networkInfo->mdns) //not mDNS - not yet supported
+ {
+ CThread_mutex_unlock(&phid->lock);
+ return EPHIDGET_UNSUPPORTED;
+ }
+
+ //refresh ONLY if connected - otherwise it might block
+ if(CPhidget_statusFlagIsSet(phid->status, PHIDGET_SERVER_CONNECTED_FLAG))
+ {
+ if(refreshZeroconfPhidget(phid))
+ {
+ CThread_mutex_unlock(&phid->lock);
+ return EPHIDGET_NETWORK;
+ }
+ }
+ if(phid->networkInfo->zeroconf_server_id)
+ {
+ *buffer = (char *)phid->networkInfo->zeroconf_server_id;
+ }
+ else if(phid->networkInfo->requested_serverID)
+ {
+ *buffer = (char *)phid->networkInfo->requested_serverID;
+ }
+ else
+ {
+ CThread_mutex_unlock(&phid->lock);
+ return EPHIDGET_UNEXPECTED;
+ }
+
+ CThread_mutex_unlock(&phid->lock);
+ return EPHIDGET_OK;
+#else
+ return EPHIDGET_UNSUPPORTED;
+#endif
+}
+
+int CCONV
+CPhidget_getServerAddress(CPhidgetHandle phid, const char **ipAddr, int *port)
+{
+ TESTPTRS(phid, ipAddr)
+ TESTPTR(port)
+
+ if (!CPhidget_statusFlagIsSet(phid->status, PHIDGET_REMOTE_FLAG))
+ return EPHIDGET_UNSUPPORTED;
+
+ CThread_mutex_lock(&phid->lock);
+#ifdef USE_ZEROCONF
+ if(phid->networkInfo->mdns)
+ {
+ //Look it up again new EVERY time!
+ if(getZeroconfHostPort(phid->networkInfo))
+ {
+ CThread_mutex_unlock(&phid->lock);
+ return EPHIDGET_NETWORK;
+ }
+ if(!phid->networkInfo->zeroconf_host || !phid->networkInfo->zeroconf_port)
+ {
+ CThread_mutex_unlock(&phid->lock);
+ return EPHIDGET_UNEXPECTED;
+ }
+ *ipAddr = (char *)phid->networkInfo->zeroconf_host;
+ *port = strtol(phid->networkInfo->zeroconf_port, NULL, 10);
+ }
+ else
+#endif
+ {
+ if(CPhidget_statusFlagIsSet(phid->status, PHIDGET_SERVER_CONNECTED_FLAG))
+ {
+ if(!phid->networkInfo->server->address || !phid->networkInfo->server->port)
+ {
+ CThread_mutex_unlock(&phid->lock);
+ return EPHIDGET_UNEXPECTED;
+ }
+ *ipAddr = (char *)phid->networkInfo->server->address;
+ *port = strtol(phid->networkInfo->server->port, NULL, 10);
+ }
+ else
+ {
+ *ipAddr = (char *)phid->networkInfo->requested_address;
+ *port = strtol(phid->networkInfo->requested_port, NULL, 10);
+ }
+ }
+ CThread_mutex_unlock(&phid->lock);
+ return EPHIDGET_OK;
+}
+
+int CCONV CPhidget_getErrorDescription(int ErrorCode, const char **buf)
+{
+ TESTPTR(buf)
+ if ((ErrorCode < 0) || (ErrorCode >= PHIDGET_ERROR_CODE_COUNT)) {
+ *buf = CPhidget_strerror(EPHIDGET_INVALID);
+ return EPHIDGET_INVALID;
+ }
+ *buf = CPhidget_strerror(ErrorCode);
+ return EPHIDGET_OK;
+}
+
+//expect 6 bytes of data
+int CCONV CPhidget_calibrate(CPhidgetHandle phid, unsigned char Offset, unsigned char *data)
+{
+ int result;
+ unsigned char buffer[8];
+ TESTPTR(phid)
+ if (!CPhidget_statusFlagIsSet(phid->status, PHIDGET_ATTACHED_FLAG))
+ return EPHIDGET_NOTATTACHED;
+
+ ZEROMEM(buffer, sizeof(buffer));
+
+ buffer[0] = 0x74;
+ buffer[1] = Offset;
+ buffer[2] = data[0];
+ buffer[3] = data[1];
+ buffer[4] = data[2];
+ buffer[5] = data[3];
+ buffer[6] = data[4];
+ buffer[7] = data[5];
+
+ if ((result = CUSBSendPacket((CPhidgetHandle)phid, buffer)) != EPHIDGET_OK)
+ return result;
+
+ return EPHIDGET_OK;
+}
+
+int CCONV CPhidget_calibrate_gain2offset(CPhidgetHandle phid, int Index, unsigned short offset, unsigned long gain1, unsigned long gain2)
+{
+ int result;
+ unsigned char buffer[8];
+ TESTPTR(phid)
+ if (!CPhidget_statusFlagIsSet(phid->status, PHIDGET_ATTACHED_FLAG))
+ return EPHIDGET_NOTATTACHED;
+
+ ZEROMEM(buffer, sizeof(buffer));
+
+ buffer[0] = 0x73;
+
+ buffer[1] = 0 + Index;
+ buffer[2] = (unsigned char)(offset >> 8);
+ if ((result = CUSBSendPacket((CPhidgetHandle)phid, buffer)) != EPHIDGET_OK)
+ return result;
+
+ buffer[1] = 1 + Index;
+ buffer[2] = (unsigned char)(offset & 0xff);
+ if ((result = CUSBSendPacket((CPhidgetHandle)phid, buffer)) != EPHIDGET_OK)
+ return result;
+
+ buffer[1] = 2 + Index;
+ buffer[2] = (unsigned char)(gain1 >> 16);
+ if ((result = CUSBSendPacket((CPhidgetHandle)phid, buffer)) != EPHIDGET_OK)
+ return result;
+
+ buffer[1] = 3 + Index;
+ buffer[2] = (unsigned char)(gain1 >> 8);
+ if ((result = CUSBSendPacket((CPhidgetHandle)phid, buffer)) != EPHIDGET_OK)
+ return result;
+
+ buffer[1] = 4 + Index;
+ buffer[2] = (unsigned char)(gain1);
+ if ((result = CUSBSendPacket((CPhidgetHandle)phid, buffer)) != EPHIDGET_OK)
+ return result;
+
+ buffer[1] = 5 + Index;
+ buffer[2] = (unsigned char)(gain2 >> 16);
+ if ((result = CUSBSendPacket((CPhidgetHandle)phid, buffer)) != EPHIDGET_OK)
+ return result;
+
+ buffer[1] = 6 + Index;
+ buffer[2] = (unsigned char)(gain2 >> 8);
+ if ((result = CUSBSendPacket((CPhidgetHandle)phid, buffer)) != EPHIDGET_OK)
+ return result;
+
+ buffer[1] = 7 + Index;
+ buffer[2] = (unsigned char)(gain2);
+ if ((result = CUSBSendPacket((CPhidgetHandle)phid, buffer)) != EPHIDGET_OK)
+ return result;
+
+ return EPHIDGET_OK;
+}
+
+int CCONV CPhidget_calibrate_gainoffset(CPhidgetHandle phid, int Index, unsigned short offset, unsigned long gain)
+{
+ //BL:Not sure what this does
+ int result;
+ unsigned char buffer[8];
+ TESTPTR(phid)
+ if (!CPhidget_statusFlagIsSet(phid->status, PHIDGET_ATTACHED_FLAG))
+ return EPHIDGET_NOTATTACHED;
+
+ ZEROMEM(buffer, sizeof(buffer));
+
+ buffer[0] = 0x72;
+
+ //BL: Index can overflow byte
+ buffer[1] = 0 + Index;
+ buffer[2] = (unsigned char)(offset >> 8);
+ if ((result = CUSBSendPacket((CPhidgetHandle)phid, buffer)) != EPHIDGET_OK)
+ return result;
+
+ buffer[1] = 1 + Index;
+ buffer[2] = (unsigned char)(offset & 0xff);
+ if ((result = CUSBSendPacket((CPhidgetHandle)phid, buffer)) != EPHIDGET_OK)
+ return result;
+
+ buffer[1] = 2 + Index;
+ buffer[2] = (unsigned char)(gain >> 16);
+ if ((result = CUSBSendPacket((CPhidgetHandle)phid, buffer)) != EPHIDGET_OK)
+ return result;
+
+ buffer[1] = 3 + Index;
+ buffer[2] = (unsigned char)(gain >> 8);
+ if ((result = CUSBSendPacket((CPhidgetHandle)phid, buffer)) != EPHIDGET_OK)
+ return result;
+
+ buffer[1] = 4 + Index;
+ buffer[2] = (unsigned char)(gain);
+ if ((result = CUSBSendPacket((CPhidgetHandle)phid, buffer)) != EPHIDGET_OK)
+ return result;
+
+ return EPHIDGET_OK;
+}
+
+//0 ms = infinite timeout - note that it only checks the attach variable every 10ms
+int CCONV CPhidget_waitForAttachment(CPhidgetHandle phid, int milliseconds)
+{
+ //BL: Should this use constants for infinite timeout rather than just 0?
+ long duration = 0;
+ TIME start;
+
+#ifdef _WINDOWS
+ TIME now;
+ FILETIME nowft, oldft, resft;
+ ULARGE_INTEGER nowul, oldul, resul;
+#else
+ struct timeval now;
+#endif
+
+ TESTPTR(phid)
+ if(milliseconds)
+ {
+#ifdef _WINDOWS
+ GetSystemTime(&start);
+#else
+ gettimeofday(&start,NULL);
+#endif
+ }
+
+ while(!CPhidget_statusFlagIsSet(phid->status, PHIDGET_ATTACHED_FLAG))
+ {
+ if(!CPhidget_statusFlagIsSet(phid->status, PHIDGET_OPENED_FLAG))
+ return EPHIDGET_CLOSED;
+ if(milliseconds)
+ {
+#ifdef _WINDOWS
+ GetSystemTime(&now);
+ SystemTimeToFileTime(&now, &nowft);
+ SystemTimeToFileTime(&start, &oldft);
+
+ nowul.HighPart = nowft.dwHighDateTime;
+ nowul.LowPart = nowft.dwLowDateTime;
+ oldul.HighPart = oldft.dwHighDateTime;
+ oldul.LowPart = oldft.dwLowDateTime;
+
+ resul.HighPart = nowul.HighPart - oldul.HighPart;
+ resul.LowPart = nowul.LowPart - oldul.LowPart;
+
+ resft.dwHighDateTime = resul.HighPart;
+ resft.dwLowDateTime = resul.LowPart;
+
+ duration = (resft.dwLowDateTime/10000);
+#else
+ gettimeofday(&now, NULL);
+ duration = (now.tv_sec - start.tv_sec)*1000 + ((now.tv_usec-start.tv_usec)/1000);
+#endif
+ if(duration > milliseconds)
+ return EPHIDGET_TIMEOUT;
+ }
+ SLEEP(10);
+ }
+ return EPHIDGET_OK;
+}
+
+void throw_error_event(CPhidgetHandle phid, const char *error, int errcode)
+{
+ //BL:didn't add checking here since don't want to mess with error propagation. Should?
+ if(phid && phid->fptrError)
+ {
+ phid->fptrError(phid, phid->fptrErrorptr, errcode, error);
+ return;
+ }
+ LOG(PHIDGET_LOG_WARNING,"Got an async error: %d: %s\n\tTip: Set up an error handler to catch this properly.", errcode, error);
+ //abort();
+}
+
+int findActiveDevice(CPhidgetHandle attachedDevice)
+{
+ int result;
+ CPhidgetList *activeDevice;
+ CPhidgetList *matches = 0;
+
+ CThread_mutex_lock(&activeDevicesLock);
+
+ /* First search for an active device that matches this specific attached device
+ * (specific serial number of specific label
+ */
+ for (activeDevice=ActiveDevices; activeDevice; activeDevice = activeDevice->next)
+ {
+ /* Don't bother with devices that are already associated with an attached Phidget */
+ if(!CPhidget_statusFlagIsSet(activeDevice->phid->status, PHIDGET_ATTACHED_FLAG))
+ {
+ /* Check device ID (Phidget class) */
+ if(activeDevice->phid->deviceID == attachedDevice->deviceID)
+ {
+ /* Check for either openLabel with matching label, or openSerial with matching serial */
+ if((
+ activeDevice->phid->specificDevice == PHIDGETOPEN_SERIAL
+ && (activeDevice->phid->serialNumber == attachedDevice->serialNumber)
+ ) || (
+ activeDevice->phid->specificDevice == PHIDGETOPEN_LABEL
+ && !strncmp(activeDevice->phid->label, attachedDevice->label, MAX_LABEL_STORAGE-1)
+ ))
+ {
+ /* add to match list */
+ CList_addToList((CListHandle *)&matches, activeDevice->phid, CPhidgetHandle_areEqual);
+ }
+ }
+ }
+ }
+
+ /* If we didn't find a specific match, then check is we have any 'openany' active devices
+ * that match the device type
+ */
+ for (activeDevice=ActiveDevices; activeDevice; activeDevice = activeDevice->next)
+ {
+ /* Don't bother with devices that are already associated with an attached Phidget */
+ if(!CPhidget_statusFlagIsSet(activeDevice->phid->status, PHIDGET_ATTACHED_FLAG))
+ {
+ /* Check device ID (Phidget class) */
+ if(activeDevice->phid->deviceID == attachedDevice->deviceID)
+ {
+ /* Make sure this is an openAny device */
+ if(activeDevice->phid->specificDevice == PHIDGETOPEN_ANY)
+ {
+ /* add to match list */
+ CList_addToList((CListHandle *)&matches, activeDevice->phid, CPhidgetHandle_areEqual);
+ }
+ }
+ }
+ }
+
+ CThread_mutex_unlock(&activeDevicesLock);
+
+ /* we create a list of possible matches and try to open them till we get success
+ * this is so we can unlock activeDevicesLock before calling attachActiveDevice.
+ */
+
+ /* Found a match, try to associate this Phidget with the actual Phidget and open it.
+ * This should send the attach event, set the PHIDGET_ATTACHED_FLAG flag to true,
+ * star the read and write threads and send out initial events
+ */
+ result = EPHIDGET_NOTFOUND;
+ for (activeDevice=matches; activeDevice; activeDevice = activeDevice->next)
+ {
+ /* Prevent close from being called during attachActiveDevice */
+ CThread_mutex_lock(&activeDevice->phid->openCloseLock);
+ if(attachActiveDevice(activeDevice->phid, attachedDevice) == EPHIDGET_OK)
+ result = EPHIDGET_OK;
+ CThread_mutex_unlock(&activeDevice->phid->openCloseLock);
+
+ /* if successfull, stop looking. */
+ if(result == EPHIDGET_OK)
+ break;
+ }
+ //free list
+ CList_emptyList((CListHandle *)&matches, PFALSE, NULL);
+
+ return result;
+}
+
+int findActiveDevices()
+{
+ CPhidgetList *attachedDevice;
+ int result = 0;
+
+ CThread_mutex_lock(&attachedDevicesLock);
+
+ for (attachedDevice=AttachedDevices; attachedDevice; attachedDevice = attachedDevice->next)
+ {
+ result = findActiveDevice(attachedDevice->phid);
+ }
+
+ CThread_mutex_unlock(&attachedDevicesLock);
+
+ return result;
+}
+
+//active device is in the list of devices waiting for connections, attachedDevice is the device that was just plugged in
+int attachActiveDevice(CPhidgetHandle activeDevice, CPhidgetHandle attachedDevice)
+{
+ int result = 0;
+ TESTPTRS(activeDevice, attachedDevice)
+
+ if(!CPhidget_statusFlagIsSet(activeDevice->status, PHIDGET_OPENED_FLAG))
+ return EPHIDGET_UNEXPECTED;
+
+#ifdef _WINDOWS
+#ifndef WINCE
+ //open uses this so it doesn't have to enumerate all devices - but ONLY ON WINDOWS!
+ activeDevice->CPhidgetFHandle = malloc(wcslen(attachedDevice->CPhidgetFHandle)*sizeof(WCHAR)+10);
+ wcsncpy((WCHAR *)activeDevice->CPhidgetFHandle, attachedDevice->CPhidgetFHandle, wcslen(attachedDevice->CPhidgetFHandle)+1);
+ activeDevice->deviceIDSpec = attachedDevice->deviceIDSpec;
+ activeDevice->deviceDef = attachedDevice->deviceDef;
+#endif
+#endif
+
+#ifdef _ANDROID
+ //Android also uses the file handle to open the device
+ activeDevice->CPhidgetFHandle = strdup(attachedDevice->CPhidgetFHandle);
+ activeDevice->deviceIDSpec = attachedDevice->deviceIDSpec;
+ activeDevice->deviceDef = attachedDevice->deviceDef;
+#endif
+
+ if(activeDevice->specificDevice == PHIDGETOPEN_ANY)
+ {
+ activeDevice->specificDevice = PHIDGETOPEN_ANY_ATTACHED;
+ }
+ activeDevice->serialNumber = attachedDevice->serialNumber;
+
+ if ((result = CUSBOpenHandle(activeDevice)) !=
+ EPHIDGET_OK) {
+ LOG(PHIDGET_LOG_WARNING,"unable to open active device: %d", result);
+ if(activeDevice->specificDevice == PHIDGETOPEN_ANY_ATTACHED)
+ {
+ activeDevice->specificDevice = PHIDGETOPEN_ANY;
+ activeDevice->serialNumber = -1;
+ }
+ activeDevice->deviceIDSpec = 0;
+ return result;
+ }
+
+ CThread_mutex_lock(&activeDevice->lock);
+ CPhidget_setStatusFlag(&activeDevice->status, PHIDGET_ATTACHING_FLAG, NULL);
+ if((result = activeDevice->fptrInit((CPhidgetHandle)activeDevice)))
+ {
+ CPhidget_clearStatusFlag(&activeDevice->status, PHIDGET_ATTACHING_FLAG, NULL);
+ CThread_mutex_unlock(&activeDevice->lock);
+ if(activeDevice->specificDevice == PHIDGETOPEN_ANY_ATTACHED)
+ {
+ activeDevice->specificDevice = PHIDGETOPEN_ANY;
+ activeDevice->serialNumber = -1;
+ }
+ LOG(PHIDGET_LOG_ERROR, "Device Initialization functions failed: %d", result);
+ if(result == EPHIDGET_BADVERSION)
+ {
+ if (activeDevice->fptrError)
+ activeDevice->fptrError((CPhidgetHandle)activeDevice, activeDevice->fptrErrorptr, EEPHIDGET_BADVERSION, "This Phidget requires a newer library - please upgrade.");
+ }
+ CUSBCloseHandle(activeDevice);
+ return result;
+ }
+
+ //make sure the write events are in a good state
+ activeDevice->writeStopFlag = FALSE;
+ CThread_reset_event(&activeDevice->writtenEvent);
+ CThread_reset_event(&activeDevice->writeAvailableEvent);
+
+ //set phidget as attached
+ CPhidget_clearStatusFlag(&activeDevice->status, PHIDGET_ATTACHING_FLAG, NULL);
+ CPhidget_setStatusFlag(&activeDevice->status, PHIDGET_ATTACHED_FLAG, NULL);
+
+ //Start write thread
+ if (CThread_create(&activeDevice->writeThread,
+ WriteThreadFunction, activeDevice)) {
+ LOG(PHIDGET_LOG_WARNING,"unable to create write thread");
+ CPhidget_clearStatusFlag(&activeDevice->status, PHIDGET_ATTACHED_FLAG, NULL);
+ CThread_mutex_unlock(&activeDevice->lock);
+ CUSBCloseHandle(activeDevice);
+ if(activeDevice->specificDevice == PHIDGETOPEN_ANY_ATTACHED)
+ {
+ activeDevice->specificDevice = PHIDGETOPEN_ANY;
+ activeDevice->serialNumber = -1;
+ }
+ return EPHIDGET_UNEXPECTED;
+ }
+ activeDevice->writeThread.thread_status = TRUE;
+
+ CThread_mutex_unlock(&activeDevice->lock);
+
+ //Attach event
+ if (activeDevice->fptrAttach)
+ {
+ //printf("Throwing read thread\n");
+ activeDevice->fptrAttach(activeDevice,
+ activeDevice->fptrAttachptr);
+ }
+
+ activeDevice->fptrEvents((CPhidgetHandle)activeDevice);
+
+ //Start read thread
+ //We start this after the attach event returns so that we can guarantee no data events
+ CThread_mutex_lock(&activeDevice->lock);
+ if (CThread_create(&activeDevice->readThread,
+ ReadThreadFunction, activeDevice)) {
+ LOG(PHIDGET_LOG_WARNING,"unable to create read thread");
+ CPhidget_clearStatusFlag(&activeDevice->status, PHIDGET_ATTACHED_FLAG, NULL);
+ CThread_mutex_unlock(&activeDevice->lock);
+ activeDevice->writeStopFlag = PTRUE;
+ CThread_join(&activeDevice->writeThread); //join before closing because we want to wait for outstanding writes to complete
+ CUSBCloseHandle(activeDevice);
+ if(activeDevice->specificDevice == PHIDGETOPEN_ANY_ATTACHED)
+ {
+ activeDevice->specificDevice = PHIDGETOPEN_ANY;
+ activeDevice->serialNumber = -1;
+ }
+ return EPHIDGET_UNEXPECTED;
+ }
+ activeDevice->readThread.thread_status = TRUE;
+ CThread_mutex_unlock(&activeDevice->lock);
+
+ return EPHIDGET_OK;
+}
+
+double round_double(double x, int decimals)
+{
+ return (double)((double)round(x * (double)(pow(10, decimals))) / (double)(pow(10, decimals)));
+}
+
+//Verifies that the UTF-8 label will fit in 20 UTF-16 bytes
+//Also gives you a handle to the output label - since we had to make it anyways...
+int encodeLabelString(const char *buffer, char *out, int *outLen)
+{
+ int len;
+ char buffer2[(MAX_LABEL_SIZE * 2)];
+
+#ifdef USE_INTERNAL_UNICONV
+ unsigned char *utf8label = (unsigned char *)buffer;
+ unsigned char *utf8labelEnd = utf8label + strlen(buffer);
+ unichar *utf16label = (unichar *)buffer2;
+ unichar *utf16labelEnd = utf16label + (MAX_LABEL_SIZE);
+ ConversionResult resp;
+
+ resp = NSConvertUTF8toUTF16(&utf8label, utf8labelEnd, &utf16label, utf16labelEnd);
+
+ if(resp != ok)
+ {
+ switch(resp)
+ {
+ case sourceExhausted:
+ LOG (PHIDGET_LOG_WARNING, "source exhausted error.");
+ break;
+ case targetExhausted:
+ LOG (PHIDGET_LOG_WARNING, "target exhausted error.");
+ break;
+ default:
+ LOG (PHIDGET_LOG_WARNING, "unexpected error.");
+ return EPHIDGET_UNEXPECTED;
+ }
+ return EPHIDGET_INVALIDARG;
+ }
+ len = (size_t)utf16label - (size_t)buffer2;
+
+#else
+
+ #ifndef _WINDOWS
+ //Mac and Linux compatible UTF-8 to UTF-16LE conversion
+ char *utf8label = (char *)buffer;
+ char *utf16label = buffer2;
+ size_t inBytes = strlen(buffer); // Up to MAX_LABEL_STORAGE bytes read
+ size_t outBytes = (MAX_LABEL_SIZE * 2); //UTF-16 characters are two bytes each.
+ iconv_t conv;
+ size_t resp;
+
+ conv= iconv_open("UTF-16LE", "UTF-8");
+ if (conv == (iconv_t)(-1))
+ return EPHIDGET_UNEXPECTED;
+
+ resp = iconv(conv, &utf8label, &inBytes, (char **)&utf16label, &outBytes);
+
+ iconv_close(conv);
+
+ if (resp == (size_t) -1) {
+ switch (errno) {
+ case EILSEQ:
+ case EINVAL:
+ LOG (PHIDGET_LOG_WARNING, "Malformed UTF8 string used for label.");
+ break;
+ case E2BIG:
+ LOG (PHIDGET_LOG_WARNING, "Label string is too long.");
+ break;
+ default:
+ LOG (PHIDGET_LOG_ERROR, "Unexpected error in parsing label string: %s.", strerror (errno));
+ return EPHIDGET_UNEXPECTED;
+ }
+ return EPHIDGET_INVALIDARG;
+ }
+ //length of descriptor = string length in bytes plus header (buffer[0] and buffer[1])
+ len = ((MAX_LABEL_SIZE * 2)-outBytes);
+ #else
+ //Windows compatible UTF-8 to UTF-16LE conversion
+ int ret = EPHIDGET_OK;
+ int charsWritten=0;
+ wchar_t *outLabel = (wchar_t *)buffer2;
+ //don't try to convert a nothing string
+ if(strlen(buffer) > 0)
+ {
+ charsWritten = MultiByteToWideChar(CP_UTF8, 0, buffer, strlen(buffer), outLabel, MAX_LABEL_SIZE);
+
+ //Error
+ if(!charsWritten)
+ {
+ switch (GetLastError())
+ {
+ case ERROR_INSUFFICIENT_BUFFER:
+ LOG(PHIDGET_LOG_WARNING, "Label string is too long.");
+ break;
+ case ERROR_NO_UNICODE_TRANSLATION:
+ LOG (PHIDGET_LOG_WARNING, "Malformed UTF8 string used for label.");
+ break;
+ case ERROR_INVALID_PARAMETER:
+ default:
+ LOG (PHIDGET_LOG_ERROR, "Unexpected error in parsing label string.");
+ return EPHIDGET_UNEXPECTED;
+ }
+ return EPHIDGET_INVALIDARG;
+ }
+ }
+
+ len = charsWritten*2;
+ #endif
+
+#endif
+
+ if(out && outLen)
+ {
+ if(len <= *outLen)
+ *outLen = len;
+ memcpy(out, buffer2, *outLen);
+ }
+ return EPHIDGET_OK;
+}
+
+//detect if this label descriptor exhibits the wraparound error
+//ie bytes 16-21 will match bytes 0-5 of the serial number string descriptor
+int labelHasWrapError(int serialNumber, char *labelBuf)
+{
+ char errorBytes[6];
+ char serialString[8];
+ int serialLen;
+ int compareSize;
+ int i;
+
+ //only applies when the label descriptor is > 16 bytes
+ if(labelBuf[0] <= 16)
+ return PFALSE;
+
+ //only applies when the first 7 digits are ascii (set by old label functions)
+ for(i=3; i<16; i+=2)
+ if(labelBuf[i] != 0x00)
+ return PFALSE;
+
+ ZEROMEM(errorBytes, 6);
+
+ //construct the 1st 6 bytes of the serial number descriptor
+ snprintf(serialString, 8, "%d", serialNumber);
+ serialLen = strlen(serialString);
+
+ errorBytes[0] = serialLen * 2 + 2; //length
+ errorBytes[1] = 0x03; //type
+
+ //serial number 1st digit
+ if(serialLen>=1)
+ errorBytes[2] = serialString[0];
+ else
+ errorBytes[2] = 0x00;
+ errorBytes[3] = 0x00;
+
+ //serial number 2nd digit
+ if(serialLen>=2)
+ errorBytes[4] = serialString[1];
+ else
+ errorBytes[4] = 0x00;
+ errorBytes[5] = 0x00;
+
+ //compare the end of the label buffer with the string descriptor
+ compareSize = labelBuf[0] - 16;
+ if(!strncmp(&labelBuf[16], errorBytes, compareSize))
+ return PTRUE;
+
+ return PFALSE;
+}
+
+//takes the label string buffer from the USB device and outputs a UTF-8 version
+int decodeLabelString(char *labelBuf, char *out, int serialNumber)
+{
+ //out NEEDS to be zeroed out, or we'll end up with a UTF-8 string with no terminating NULL
+ ZEROMEM(out, MAX_LABEL_STORAGE);
+
+ //this returns true only if our descriptor is > 16 bytes and has the error, so we truncate
+ if (labelHasWrapError(serialNumber, labelBuf))
+ {
+ int i;
+ for(i=16;i<labelBuf[0];i++)
+ labelBuf[i] = 0x00;
+ labelBuf[0] = 16;
+ LOG(PHIDGET_LOG_WARNING, "Detected getLabel error - label is being truncated to first 7 characters. Please setLabel again to correct this.");
+ }
+
+ //check if the label is stored as UTF-8 directly
+ if(labelBuf[0] > 4 && labelBuf[2] == (char)0xFF && labelBuf[3] == (char)0xFF)
+ {
+ LOG(PHIDGET_LOG_DEBUG, "Found a wrap-around bug style label.");
+ memcpy(out, &labelBuf[4], labelBuf[0]-4);
+ out[labelBuf[0]-4] = '\0';
+ }
+ //otherwise it's stored as UTF-16LE
+ else
+ {
+#ifdef USE_INTERNAL_UNICONV
+ unsigned char *utf8label = (unsigned char *)out;
+ unsigned char *utf8labelEnd = utf8label + MAX_LABEL_STORAGE;
+ unichar *utf16label = (unichar *)&labelBuf[2];
+ unichar *utf16labelEnd = utf16label + ((labelBuf[0]-2) / 2);
+ ConversionResult resp;
+ resp = NSConvertUTF16toUTF8(&utf16label, utf16labelEnd, &utf8label, utf8labelEnd);
+
+ if(resp != ok)
+ {
+ switch(resp)
+ {
+ case sourceExhausted:
+ LOG (PHIDGET_LOG_WARNING, "source exhausted error.");
+ break;
+ case targetExhausted:
+ LOG (PHIDGET_LOG_WARNING, "target exhausted error.");
+ break;
+ default:
+ LOG (PHIDGET_LOG_WARNING, "unexpected error.");
+ return EPHIDGET_UNEXPECTED;
+ }
+ return EPHIDGET_INVALIDARG;
+ }
+
+#else
+
+ #ifndef _WINDOWS
+ char *utf16label = &labelBuf[2];
+ char *utf8label = (char *)out;
+ size_t inBytes = labelBuf[0]-2; // Up to MAX_LABEL_STORAGE bytes read
+ size_t outBytes = (MAX_LABEL_STORAGE); //UTF-16 characters are two bytes each.
+ iconv_t conv;
+ size_t resp;
+ conv= iconv_open("UTF-8", "UTF-16LE");
+ if (conv == (iconv_t)(-1))
+ return EPHIDGET_UNEXPECTED;
+
+ resp = iconv(conv, &utf16label, &inBytes, &utf8label, &outBytes);
+
+ iconv_close(conv);
+
+ if (resp == (size_t) -1) {
+ switch (errno) {
+ case EILSEQ:
+ case EINVAL:
+ case E2BIG:
+ default:
+ LOG (PHIDGET_LOG_ERROR, "Unexpected error converting label to UTF-8: %s.", strerror (errno));
+ return EPHIDGET_UNEXPECTED;
+ }
+ }
+ #else
+ //labelData in NULL terminated
+ int bytesWritten = WideCharToMultiByte(CP_UTF8, 0, (wchar_t *)&labelBuf[2], -1, out, MAX_LABEL_STORAGE+1, NULL, NULL);
+
+ //Error
+ if(!bytesWritten)
+ {
+ LOG(PHIDGET_LOG_ERROR, "Unable to convert label to UTF-8!");
+ return EPHIDGET_UNEXPECTED;
+ }
+ #endif
+#endif
+ }
+
+ return EPHIDGET_OK;
+}
diff --git a/cphidget.h b/cphidget.h
new file mode 100644
index 0000000..7962026
--- /dev/null
+++ b/cphidget.h
@@ -0,0 +1,396 @@
+#ifndef __CPHIDGET
+#define __CPHIDGET
+
+/** \defgroup phidcommon Phidget Common
+ * Calls common to all Phidgets. See the programming manual for more specific API details, supported functionality, units, etc.
+ * @{
+ */
+
+/**
+ * A phidget handle.
+ */
+typedef struct _CPhidget *CPhidgetHandle;
+
+/**
+ * Timestamp structure - usually initialized to 0.
+ */
+typedef struct _CPhidget_Timestamp {
+ int seconds; /**< Number of seconds since timing began */
+ int microseconds; /**< Number of microseconds since last second passed - range is 0 - 999999 */
+} CPhidget_Timestamp, *CPhidget_TimestampHandle;
+
+#include "cphidgetattr.h"
+#ifndef EXTERNALPROTO
+
+#ifndef _WINDOWS
+/**
+ * Platform independent 64-bit integer.
+ */
+typedef long long __int64;
+#endif
+
+#include "cphidgetconstantsinternal.h"
+#include "cphidgetconstants.h"
+#include "cthread.h"
+
+typedef enum {EVENTMODE_DATARATE=1, EVENTMODE_CHANGETRIGGER} CPhidget_EventMode;
+
+typedef struct _CPhidget CPhidget;
+//This is for a socket - one of these can be referenced by several phidgets!
+typedef struct __CPhidgetSocketClient {
+ int socket;
+ char *port;
+ char *address;
+ void *pdcs;
+ int status;
+ CThread_mutex_t lock; /* protects server status */
+ CThread_mutex_t pdc_lock; /* protects synchronous pdc functions */
+ CThread auth_thread;
+ CThread auth_error_thread;
+ /* Heartbeat Vars */
+ TIME lastHeartbeatTime;
+ unsigned char waitingForHeartbeat;
+ int heartbeatCount;
+ double avgHeartbeatTime;
+ int avgHeartbeatTimeCount;
+ int heartbeat_listen_id;
+ int runningEvent;
+} CPhidgetSocketClient, *CPhidgetSocketClientHandle;
+
+typedef struct __CPhidgetSocketClientList
+{
+ struct __CPhidgetSocketClientList *next;
+ CPhidgetSocketClientHandle client;
+} CPhidgetSocketClientList, *CPhidgetSocketClientListHandle;
+
+typedef struct __CPhidgetRemote {
+ CPhidgetSocketClientHandle server; //can be NULL if not yet connected to a server
+ char *requested_port; //only !NULL if not zeroconf
+ char *requested_address; //only !NULL if not zeroconf
+ char *requested_serverID; //only !NULL if zeroconf
+ char *password; //can be NULL - will be used if needed for connecting to remote Phidgets
+ int listen_id;
+ int mdns; //true if mdns, false if not
+ char *zeroconf_name; //for use before a connection is active
+ char *zeroconf_domain; //for use before a connection is active
+ char *zeroconf_type; //for use before a connection is active
+ char *zeroconf_host;
+ char *zeroconf_port;
+ char *zeroconf_ipaddr;
+ char *zeroconf_server_id; //for use before a connection is active
+ int zeroconf_interface;
+ int zeroconf_auth; //for use before a connection is active
+ void *zeroconf_ref; //service ref for mdns host/port lookups
+ int cancelSocket;
+ CThread_mutex_t zeroconf_ref_lock; /* protects zeroconf_ref */
+ int uniqueConnectionID;
+} CPhidgetRemote, *CPhidgetRemoteHandle;
+
+typedef struct __CPhidgetRemoteList
+{
+ struct __CPhidgetRemoteList *next;
+ CPhidgetRemoteHandle networkInfo;
+} CPhidgetRemoteList, *CPhidgetRemoteListHandle;
+
+typedef struct {
+ CPhidget_DeviceID pdd_sdid;
+ CPhidget_DeviceClass pdd_did;
+ int pdd_vid;
+ int pdd_pid;
+ int pdd_iid;
+ CPhidgetAttr pdd_attr;
+ const char *pdd_name;
+} CPhidgetDeviceDef;
+
+struct _CPhidget {
+ CPhidgetRemoteHandle networkInfo; //NULL if local, !NULL if remote
+ int(CCONV *fptrError)(CPhidgetHandle , void *, int, const char *);
+ void *fptrErrorptr;
+ int(CCONV *fptrServerConnect)(CPhidgetHandle , void *);
+ void *fptrServerConnectptr;
+ int(CCONV *fptrServerDisconnect)(CPhidgetHandle , void *);
+ void *fptrServerDisconnectptr;
+ CThread_mutex_t lock; /* protects status */
+ int status;
+ CThread_mutex_t openCloseLock; /* protects status */
+ int keyCount; //counts key during network open
+ int initKeys; //number of initial keys during network open
+ CThread_mutex_t writelock; /* protects write - exclusive */
+ CThread readThread;
+ CThread writeThread;
+ HANDLE deviceHandle;
+#ifdef _WINDOWS
+ OVERLAPPED asyncRead;
+ BOOL readPending;
+ EVENT closeReadEvent;
+ OVERLAPPED asyncWrite;
+ unsigned char inbuf[MAX_IN_PACKET_SIZE+1];
+#endif
+ int specificDevice;
+ CPhidget_DeviceClass deviceID;
+ CPhidget_DeviceID deviceIDSpec;
+ const CPhidgetDeviceDef *deviceDef;
+ //int Phid_Device_Def_index;
+ int deviceVersion;
+ unsigned short ProductID;
+ unsigned short VendorID;
+ int serialNumber;
+ const char *deviceType;
+ unsigned short outputReportByteLength;
+ unsigned short inputReportByteLength;
+ char label[MAX_LABEL_STORAGE];
+ char *escapedLabel; //for webservice
+ int(CCONV *fptrInit)(CPhidgetHandle);
+ int(CCONV *fptrClear)(CPhidgetHandle);
+ int(CCONV *fptrEvents)(CPhidgetHandle);
+ int(CCONV *fptrClose)(CPhidgetHandle);
+ int(CCONV *fptrFree)(CPhidgetHandle);
+ int(CCONV *fptrData)(CPhidgetHandle, unsigned char *buffer, int length);
+ int(CCONV *fptrGetPacket)(CPhidgetHandle, unsigned char *buffer,
+ unsigned int *length);
+ unsigned char lastReadPacket[MAX_IN_PACKET_SIZE];
+ unsigned char awdc_enabled;
+ void *dnsServiceRef;
+ void *errEventList;
+#if defined(_MACOSX) && !defined(_IPHONE)
+ io_object_t CPhidgetFHandle;
+#else
+ void *CPhidgetFHandle;
+#endif
+#ifdef _LINUX
+ int tryAgainCounter;
+#endif
+#if !defined(_WINDOWS) || defined(WINCE)
+ unsigned char interruptOutEndpoint;
+#endif
+ CThread_mutex_t outputLock; /* device-specific code responsible */
+ EVENT writeAvailableEvent; /* device-specific code sets w/o OLL held */
+ EVENT writtenEvent; /* device-specific code clears w/OLL held */
+ int writeStopFlag; /* set when closing */
+ int(CCONV *fptrAttach)(CPhidgetHandle , void *);
+ void *fptrAttachptr;
+ int(CCONV *fptrDetach)(CPhidgetHandle , void *);
+ void *fptrDetachptr;
+ CPhidgetAttr attr;
+};
+
+struct _CPhidgetList
+{
+ struct _CPhidgetList *next;
+ CPhidgetHandle phid;
+} typedef CPhidgetList, *CPhidgetListHandle;
+
+extern const char LibraryVersion[];
+extern const char *Phid_DeviceName[PHIDGET_DEVICE_CLASS_COUNT];
+extern const char Phid_UnknownErrorDescription[];
+extern const char *Phid_ErrorDescriptions[PHIDGET_ERROR_CODE_COUNT];
+
+extern CPhidgetList *ActiveDevices;
+extern CPhidgetList *AttachedDevices;
+extern int phidgetLocksInitialized;
+extern CThread_mutex_t activeDevicesLock, attachedDevicesLock;
+
+extern const CPhidgetDeviceDef Phid_Device_Def[];
+
+void CPhidgetFHandle_free(void *arg);
+int CPhidget_read(CPhidgetHandle phid);
+int CPhidget_write(CPhidgetHandle phid);
+int CPhidget_statusFlagIsSet(int status, int flag);
+int CPhidget_setStatusFlag(int *status, int flag, CThread_mutex_t *lock);
+int CPhidget_clearStatusFlag(int *status, int flag, CThread_mutex_t *lock);
+char translate_bool_to_ascii(char value);
+const char *CPhidget_strerror(int error);
+void throw_error_event(CPhidgetHandle phid, const char *error, int errcode);
+int findActiveDevice(CPhidgetHandle attachedDevice);
+int findActiveDevices();
+int attachActiveDevice(CPhidgetHandle activeDevice, CPhidgetHandle attachedDevice);
+double timestampdiff(CPhidget_Timestamp time1, CPhidget_Timestamp time2);
+double timeSince(TIME *start);
+void setTimeNow(TIME *now);
+int encodeLabelString(const char *buffer, char *out, int *outLen);
+int decodeLabelString(char *labelBuf, char *out, int serialNumber);
+int labelHasWrapError(int serialNumber, char *labelBuf);
+void CPhidgetErrorEvent_free(void *arg);
+
+PHIDGET21_API int CCONV CPhidget_areEqual(void *arg1, void *arg2);
+PHIDGET21_API int CCONV CPhidget_areExtraEqual(void *arg1, void *arg2);
+PHIDGET21_API int CCONV CPhidgetHandle_areEqual(void *arg1, void *arg2);
+PHIDGET21_API void CCONV CPhidget_free(void *arg);
+PHIDGET21_API int CCONV phidget_type_to_id(const char *Type);
+PHIDGET21_API int CCONV CPhidget_create(CPhidgetHandle *phid);
+
+PHIDGET21_API int CCONV CPhidget_calibrate_gainoffset(CPhidgetHandle phid, int index, unsigned short offset, unsigned long gain);
+
+#endif
+#include "cphidgetmacros.h"
+
+/**
+ * Opens a Phidget.
+ * @param phid A phidget handle.
+ * @param serialNumber Serial number. Specify -1 to open any.
+ */
+PHIDGET21_API int CCONV CPhidget_open(CPhidgetHandle phid, int serialNumber);
+/**
+ * Opens a Phidget by label.
+ * @param phid A phidget handle.
+ * @param label Label string. Labels can be up to 10 characters (UTF-8 encoding). Specify NULL to open any.
+ */
+PHIDGET21_API int CCONV CPhidget_openLabel(CPhidgetHandle phid, const char *label);
+/**
+ * Closes a Phidget.
+ * @param phid An opened phidget handle.
+ */
+PHIDGET21_API int CCONV CPhidget_close(CPhidgetHandle phid);
+/**
+ * Frees a Phidget handle.
+ * @param phid A closed phidget handle.
+ */
+PHIDGET21_API int CCONV CPhidget_delete(CPhidgetHandle phid);
+/**
+ * Sets a detach handler callback function. This is called when this Phidget is unplugged from the system.
+ * @param phid A phidget handle.
+ * @param fptr Callback function pointer.
+ * @param userPtr A pointer for use by the user - this value is passed back into the callback function.
+ */
+PHIDGET21_API int CCONV CPhidget_set_OnDetach_Handler(CPhidgetHandle phid, int(CCONV *fptr)(CPhidgetHandle phid, void *userPtr), void *userPtr);
+/**
+ * Sets an attach handler callback function. This is called when this Phidget is plugged into the system, and is ready for use.
+ * @param phid A phidget handle.
+ * @param fptr Callback function pointer.
+ * @param userPtr A pointer for use by the user - this value is passed back into the callback function.
+ */
+PHIDGET21_API int CCONV CPhidget_set_OnAttach_Handler(CPhidgetHandle phid, int(CCONV *fptr)(CPhidgetHandle phid, void *userPtr), void *userPtr);
+/**
+ * Sets a server connect handler callback function. This is used for opening Phidgets remotely, and is called when a connection to the sever has been made.
+ * @param phid A phidget handle.
+ * @param fptr Callback function pointer.
+ * @param userPtr A pointer for use by the user - this value is passed back into the callback function.
+ */
+PHIDGET21_API int CCONV CPhidget_set_OnServerConnect_Handler(CPhidgetHandle phid, int (CCONV *fptr)(CPhidgetHandle phid, void *userPtr), void *userPtr);
+/**
+ * Sets a server disconnect handler callback function. This is used for opening Phidgets remotely, and is called when a connection to the server has been lost.
+ * @param phid A phidget handle.
+ * @param fptr Callback function pointer.
+ * @param userPtr A pointer for use by the user - this value is passed back into the callback function.
+ */
+PHIDGET21_API int CCONV CPhidget_set_OnServerDisconnect_Handler(CPhidgetHandle phid, int (CCONV *fptr)(CPhidgetHandle phid, void *userPtr), void *userPtr);
+/**
+ * Sets the error handler callback function. This is called when an asynchronous error occurs.
+ * @param phid A phidget handle.
+ * @param fptr Callback function pointer.
+ * @param userPtr A pointer for use by the user - this value is passed back into the callback function.
+ */
+PHIDGET21_API int CCONV CPhidget_set_OnError_Handler(CPhidgetHandle phid, int(CCONV *fptr)(CPhidgetHandle phid, void *userPtr, int errorCode, const char *errorString), void *userPtr);
+/**
+ * Gets the specific name of a Phidget.
+ * @param phid An attached phidget handle.
+ * @param deviceName A pointer which will be set to point to a char array containing the device name.
+ */
+PHIDGET21_API int CCONV CPhidget_getDeviceName(CPhidgetHandle phid, const char **deviceName);
+/**
+ * Gets the serial number of a Phidget.
+ * @param phid An attached phidget handle.
+ * @param serialNumber An int pointer for returning the serial number.
+ */
+PHIDGET21_API int CCONV CPhidget_getSerialNumber(CPhidgetHandle phid, int *serialNumber);
+/**
+ * Gets the firmware version of a Phidget.
+ * @param phid An attached phidget handle.
+ * @param deviceVersion An int pointer for returning the device version.
+ */
+PHIDGET21_API int CCONV CPhidget_getDeviceVersion(CPhidgetHandle phid, int *deviceVersion);
+/**
+ * Gets the attached status of a Phidget.
+ * @param phid A phidget handle.
+ * @param deviceStatus An int pointer for returning the device status. Possible codes are \ref PHIDGET_ATTACHED and \ref PHIDGET_NOTATTACHED.
+ */
+PHIDGET21_API int CCONV CPhidget_getDeviceStatus(CPhidgetHandle phid, int *deviceStatus);
+/**
+ * Gets the library version. This contains a version number and a build date.
+ * @param libraryVersion A pointer which will be set to point to a char array containing the library version string.
+ */
+PHIDGET21_API int CCONV CPhidget_getLibraryVersion(const char **libraryVersion);
+/**
+ * Gets the type (class) of a Phidget.
+ * @param phid An attached phidget handle.
+ * @param deviceType A pointer which will be set to a char array containing the device type string.
+ */
+PHIDGET21_API int CCONV CPhidget_getDeviceType(CPhidgetHandle phid, const char **deviceType);
+/**
+ * Gets the label of a Phidget.
+ * @param phid An attached phidget handle.
+ * @param deviceLabel A pointer which will be set to a char array containing the device label string.
+ */
+PHIDGET21_API int CCONV CPhidget_getDeviceLabel(CPhidgetHandle phid, const char **deviceLabel);
+/**
+ * Sets the label of a Phidget. Note that this is nut supported on very old Phidgets, and not yet supported in Windows.
+ * @param phid An attached phidget handle.
+ * @param deviceLabel A string containing the label to be set.
+ */
+PHIDGET21_API int CCONV CPhidget_setDeviceLabel(CPhidgetHandle phid, const char *deviceLabel);
+/**
+ * Gets the description for an error code.
+ * @param errorCode The error code to get the description of.
+ * @param errorString A pointer which will be set to a char array containing the error description string.
+ */
+PHIDGET21_API int CCONV CPhidget_getErrorDescription(int errorCode, const char **errorString);
+/**
+ * Waits for attachment to happen. This can be called wirght after calling \ref CPhidget_open, as an alternative to using the attach handler.
+ * @param phid An opened phidget handle.
+ * @param milliseconds Time to wait for the attachment. Specify 0 to wait forever.
+ */
+PHIDGET21_API int CCONV CPhidget_waitForAttachment(CPhidgetHandle phid, int milliseconds);
+/**
+ * Gets the server ID of a remotely opened Phidget. This will fail if the Phidget was opened locally.
+ * @param phid A connected phidget handle.
+ * @param serverID A pointer which will be set to a char array containing the server ID string.
+ */
+PHIDGET21_API int CCONV CPhidget_getServerID(CPhidgetHandle phid, const char **serverID);
+/**
+ * Gets the address and port of a remotely opened Phidget. This will fail if the Phidget was opened locally.
+ * @param phid A connected phidget handle.
+ * @param address A pointer which will be set to a char array containing the address string.
+ * @param port An int pointer for returning the port number.
+ */
+PHIDGET21_API int CCONV CPhidget_getServerAddress(CPhidgetHandle phid, const char **address, int *port);
+/**
+ * Gets the connected to server status of a remotely opened Phidget. This will fail if the Phidget was opened locally.
+ * @param phid An opened phidget handle.
+ * @param serverStatus An int pointer for returning the server status. Possible codes are \ref PHIDGET_ATTACHED and \ref PHIDGET_NOTATTACHED.
+ */
+PHIDGET21_API int CCONV CPhidget_getServerStatus(CPhidgetHandle phid, int *serverStatus);
+/**
+ * Gets the device ID of a Phidget.
+ * @param phid An attached phidget handle.
+ * @param deviceID The device ID constant.
+ */
+PHIDGET21_API int CCONV CPhidget_getDeviceID(CPhidgetHandle phid, CPhidget_DeviceID *deviceID);
+/**
+ * Gets the class of a Phidget.
+ * @param phid An attached phidget handle.
+ * @param deviceClass The device class constant.
+ */
+PHIDGET21_API int CCONV CPhidget_getDeviceClass(CPhidgetHandle phid, CPhidget_DeviceClass *deviceClass);
+
+#ifdef _MACOSX
+/**
+ * Sets the phidgets sleep handler callback function. This is called when the system is going to sleep, right before
+ * all Phidgets become inaccessible.
+ * @param phid A phidget handle.
+ * @param fptr Callback function pointer.
+ * @param userPtr A pointer for use by the user - this value is passed back into the callback function.
+ */
+PHIDGET21_API int CCONV CPhidget_set_OnWillSleep_Handler(int(CCONV *fptr)(void *userPtr), void *userPtr);
+/**
+ * Sets the phidgets wakeup handler callback function. This is called when the system wakes up from sleep, after the Phidgets are
+ * accessible once again.
+ * @param phid A phidget handle.
+ * @param fptr Callback function pointer.
+ * @param userPtr A pointer for use by the user - this value is passed back into the callback function.
+ */
+PHIDGET21_API int CCONV CPhidget_set_OnWakeup_Handler(int(CCONV *fptr)(void *userPtr), void *userPtr);
+#endif
+
+/** @} */
+
+#endif
diff --git a/cphidgetaccelerometer.c b/cphidgetaccelerometer.c
new file mode 100644
index 0000000..4977de2
--- /dev/null
+++ b/cphidgetaccelerometer.c
@@ -0,0 +1,258 @@
+#include "stdafx.h"
+#include "cphidgetaccelerometer.h"
+#include "cusb.h"
+#include "math.h"
+#include "csocket.h"
+#include "cthread.h"
+
+// === Internal Functions === //
+
+//clearVars - sets all device variables to unknown state
+CPHIDGETCLEARVARS(Accelerometer)
+ int i = 0;
+
+ phid->accelerationMax = PUNI_DBL;
+ phid->accelerationMin = PUNI_DBL;
+
+ for (i = 0; i<ACCEL_MAXAXES; i++)
+ {
+ phid->axis[i] = PUNI_DBL;
+ phid->axisLastTrigger[i] = PUNK_DBL;
+ phid->axisChangeTrigger[i] = PUNI_DBL;
+ }
+ return EPHIDGET_OK;
+}
+
+//initAfterOpen - sets up the initial state of an object, reading in packets from the device if needed
+// used during attach initialization - on every attach
+CPHIDGETINIT(Accelerometer)
+ int i = 0;
+
+ TESTPTR(phid);
+
+ //Setup max/min values
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_ACCELEROMETER_2AXIS:
+ if (phid->phid.deviceVersion < 200)
+ {
+ phid->accelerationMax = 2.1;
+ phid->accelerationMin = -2.1;
+ }
+ else if ((phid->phid.deviceVersion >= 200) && (phid->phid.deviceVersion < 300))
+ {
+ phid->accelerationMax = 10.1;
+ phid->accelerationMin = -10.1;
+ }
+ else if ((phid->phid.deviceVersion >= 300) && (phid->phid.deviceVersion < 400))
+ {
+ phid->accelerationMax = 5.1;
+ phid->accelerationMin = -5.1;
+ }
+ else
+ return EPHIDGET_BADVERSION;
+ break;
+ case PHIDID_ACCELEROMETER_3AXIS:
+ if ((phid->phid.deviceVersion >= 400) && (phid->phid.deviceVersion < 500))
+ {
+ phid->accelerationMax = 3.1;
+ phid->accelerationMin = -3.1;
+ }
+ else
+ return EPHIDGET_BADVERSION;
+ break;
+ default:
+ return EPHIDGET_UNEXPECTED;
+ }
+
+ //initialize triggers, set data arrays to unknown
+ for (i = 0; i<phid->phid.attr.accelerometer.numAxis; i++)
+ {
+ phid->axis[i] = PUNK_DBL;
+ phid->axisLastTrigger[i] = PUNK_DBL;
+ phid->axisChangeTrigger[i] = 0.001;
+ }
+
+ //issue one read
+ CPhidget_read((CPhidgetHandle)phid);
+
+ return EPHIDGET_OK;
+}
+
+//dataInput - parses device packets
+CPHIDGETDATA(Accelerometer)
+ int i = 0;
+ double axis[ACCEL_MAXAXES];
+
+ if (length<0) return EPHIDGET_INVALIDARG;
+ TESTPTR(phid);
+ TESTPTR(buffer);
+
+ ZEROMEM(axis, sizeof(axis));
+
+ //Parse device packets - store data locally
+ switch(phidG->deviceIDSpec)
+ {
+ case PHIDID_ACCELEROMETER_2AXIS:
+ if (phidG->deviceVersion < 200)
+ {
+ int data = 0;
+ data = (signed short)((unsigned short)buffer[0]+((unsigned short)buffer[1]<<8));
+ axis[0] = round_double((((double)data-16384) / 2000), 4);
+ data = (signed short)((unsigned short)buffer[2]+((unsigned short)buffer[3]<<8));
+ axis[1] = round_double((((double)data-16384) / 2000), 4);
+ }
+ else if ((phidG->deviceVersion >= 200) && (phidG->deviceVersion < 300))
+ {
+ int data = 0;
+ data = (signed short)((unsigned short)buffer[0]+((unsigned short)buffer[1]<<8));
+ axis[0] = round_double((((double)data-16384) / 650), 4);
+ data = (signed short)((unsigned short)buffer[2]+((unsigned short)buffer[3]<<8));
+ axis[1] = round_double((((double)data-16384) / 650), 4);
+ }
+ else if ((phidG->deviceVersion >= 300) && (phidG->deviceVersion < 400))
+ {
+ int data = 0;
+ data = ((unsigned short)buffer[0]+((unsigned short)buffer[1]<<8));
+ axis[0] = round_double((((double)(data-32768)) / 4000), 5);
+ data = ((unsigned short)buffer[2]+((unsigned short)buffer[3]<<8));
+ axis[1] = round_double((((double)(data-32768)) / 4000), 5);
+ }
+ else
+ return EPHIDGET_UNEXPECTED;
+ break;
+ case PHIDID_ACCELEROMETER_3AXIS:
+ if ((phidG->deviceVersion >= 400) && (phidG->deviceVersion < 500))
+ {
+ int data = 0;
+ data = ((unsigned short)buffer[0]+((unsigned short)buffer[1]<<8));
+ axis[0] = round_double((((double)(data-32768)) / 6553.6), 5);
+ data = ((unsigned short)buffer[2]+((unsigned short)buffer[3]<<8));
+ axis[1] = round_double((((double)(data-32768)) / 6553.6), 5);
+ data = ((unsigned short)buffer[4]+((unsigned short)buffer[5]<<8));
+ axis[2] = round_double((((double)(data-32768)) / 6553.6), 5);
+ }
+ else
+ return EPHIDGET_UNEXPECTED;
+ break;
+ default:
+ return EPHIDGET_UNEXPECTED;
+ }
+
+ //Make sure values are within defined range, and store to structure
+ for (i = 0; i<phid->phid.attr.accelerometer.numAxis; i++)
+ {
+ if(axis[i] > phid->accelerationMax) axis[i] = phid->accelerationMax;
+ if(axis[i] < phid->accelerationMin) axis[i] = phid->accelerationMin;
+ phid->axis[i] = axis[i];
+ }
+
+ //send out any events that exceed or match the trigger
+ for (i = 0; i<phid->phid.attr.accelerometer.numAxis; i++)
+ {
+ if (fabs(phid->axis[i] - phid->axisLastTrigger[i]) >= phid->axisChangeTrigger[i]
+ || phid->axisLastTrigger[i] == PUNK_DBL)
+ {
+ FIRE(AccelerationChange, i, phid->axis[i]);
+ phid->axisLastTrigger[i] = phid->axis[i];
+ }
+ }
+
+ return EPHIDGET_OK;
+}
+
+//eventsAfterOpen - sends out an event for all valid data, used during attach initialization
+CPHIDGETINITEVENTS(Accelerometer)
+
+ for (i = 0; i<phid->phid.attr.accelerometer.numAxis; i++)
+ {
+ if(phid->axis[i] != PUNK_DBL)
+ {
+ FIRE(AccelerationChange, i, phid->axis[i]);
+ phid->axisLastTrigger[i] = phid->axis[i];
+ }
+ }
+
+ return EPHIDGET_OK;
+}
+
+//getPacket - not used for accelerometer
+CGETPACKET(Accelerometer)
+ return EPHIDGET_UNEXPECTED;
+}
+
+// === Exported Functions === //
+
+//create and initialize a device structure
+CCREATE(Accelerometer, PHIDCLASS_ACCELEROMETER)
+
+//event setup functions
+CFHANDLE(Accelerometer, AccelerationChange, int, double)
+
+CGET(Accelerometer,AxisCount,int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_ACCELEROMETER)
+ TESTATTACHED
+
+ MASGN(phid.attr.accelerometer.numAxis)
+}
+
+CGETINDEX(Accelerometer,Acceleration,double)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_ACCELEROMETER)
+ TESTATTACHED
+ TESTINDEX(phid.attr.accelerometer.numAxis)
+ TESTMASGN(axis[Index], PUNK_DBL)
+
+ MASGN(axis[Index])
+}
+
+CGETINDEX(Accelerometer,AccelerationMax,double)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_ACCELEROMETER)
+ TESTATTACHED
+ TESTINDEX(phid.attr.accelerometer.numAxis)
+ TESTMASGN(accelerationMax, PUNK_DBL)
+
+ MASGN(accelerationMax)
+}
+
+CGETINDEX(Accelerometer,AccelerationMin,double)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_ACCELEROMETER)
+ TESTATTACHED
+ TESTINDEX(phid.attr.accelerometer.numAxis)
+ TESTMASGN(accelerationMin, PUNK_DBL)
+
+ MASGN(accelerationMin)
+}
+
+CGETINDEX(Accelerometer,AccelerationChangeTrigger,double)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_ACCELEROMETER)
+ TESTATTACHED
+ TESTINDEX(phid.attr.accelerometer.numAxis)
+ TESTMASGN(axisChangeTrigger[Index], PUNK_DBL)
+
+ MASGN(axisChangeTrigger[Index])
+}
+CSETINDEX(Accelerometer,AccelerationChangeTrigger,double)
+ TESTPTR(phid)
+ TESTDEVICETYPE(PHIDCLASS_ACCELEROMETER)
+ TESTATTACHED
+ TESTINDEX(phid.attr.accelerometer.numAxis)
+ TESTRANGE(0, phid->accelerationMax - phid->accelerationMin)
+
+ if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
+ ADDNETWORKKEYINDEXED(Trigger, "%lE", axisChangeTrigger);
+ else
+ phid->axisChangeTrigger[Index] = newVal;
+
+ return EPHIDGET_OK;
+}
+
+// === Deprecated Functions === //
+
+CGET(Accelerometer,NumAxis,int)
+ return CPhidgetAccelerometer_getAxisCount(phid, pVal);
+}
diff --git a/cphidgetaccelerometer.h b/cphidgetaccelerometer.h
new file mode 100644
index 0000000..7b4cdd7
--- /dev/null
+++ b/cphidgetaccelerometer.h
@@ -0,0 +1,85 @@
+#ifndef __CPHIDGETACCELEROMETER
+#define __CPHIDGETACCELEROMETER
+#include "cphidget.h"
+
+/** \defgroup phidaccel Phidget Accelerometer
+ * \ingroup phidgets
+ * Calls specific to the Phidget Accelerometer. See the product manual for more specific API details, supported functionality, units, etc.
+ * @{
+ */
+
+DPHANDLE(Accelerometer)
+CHDRSTANDARD(Accelerometer)
+
+/**
+ * Gets the number of acceleration axes supported by this accelerometer.
+ * @param phid An attached phidget accelerometer handle.
+ * @param count The axis count.
+ */
+CHDRGET(Accelerometer,AxisCount,int *count)
+
+/**
+ * Gets the current acceleration of an axis.
+ * @param phid An attached phidget accelerometer handle.
+ * @param index The acceleration index.
+ * @param acceleration The acceleration.
+ */
+CHDRGETINDEX(Accelerometer,Acceleration,double *acceleration)
+/**
+ * Gets the maximum accleration supported by an axis.
+ * @param phid An attached phidget accelerometer handle.
+ * @param index The acceleration index
+ * @param max The maximum acceleration
+ */
+CHDRGETINDEX(Accelerometer,AccelerationMax,double *max)
+/**
+ * Gets the minimum acceleraiton supported by an axis.
+ * @param phid An attached phidget accelerometer handle.
+ * @param index The acceleration index
+ * @param min The minimum acceleraion
+ */
+CHDRGETINDEX(Accelerometer,AccelerationMin,double *min)
+/**
+ * Sets an acceleration change event handler. This is called when the acceleration changes by more then the change trigger.
+ * @param phid A phidget accelerometer handle.
+ * @param fptr Callback function pointer.
+ * @param userPtr A pointer for use by the user - this value is passed back into the callback function.
+ */
+CHDREVENTINDEX(Accelerometer,AccelerationChange,double acceleration)
+/**
+ * Gets the change trigger for an axis.
+ * @param phid An attached phidget accelerometer handle.
+ * @param index The acceleration index
+ * @param trigger The change trigger.
+ */
+CHDRGETINDEX(Accelerometer,AccelerationChangeTrigger,double *trigger)
+/**
+ * Sets the change trigger for an axis.
+ * @param phid An attached phidget accelerometer handle.
+ * @param index The acceleration index
+ * @param trigger The change trigger.
+ */
+CHDRSETINDEX(Accelerometer,AccelerationChangeTrigger,double trigger)
+
+#ifndef REMOVE_DEPRECATED
+DEP_CHDRGET("Deprecated - use CPhidgetAccelerometer_getAxisCount",Accelerometer,NumAxis,int *)
+#endif
+
+#ifndef EXTERNALPROTO
+#define ACCEL_MAXAXES 3
+struct _CPhidgetAccelerometer {
+ CPhidget phid;
+ int (CCONV *fptrAccelerationChange)(CPhidgetAccelerometerHandle, void *, int, double);
+ void *fptrAccelerationChangeptr;
+
+ double axis[ACCEL_MAXAXES];
+ double axisChangeTrigger[ACCEL_MAXAXES];
+ double axisLastTrigger[ACCEL_MAXAXES];
+
+ double accelerationMax, accelerationMin;
+} typedef CPhidgetAccelerometerInfo;
+#endif
+
+/** @} */
+
+#endif
diff --git a/cphidgetadvancedservo.c b/cphidgetadvancedservo.c
new file mode 100644
index 0000000..12419cb
--- /dev/null
+++ b/cphidgetadvancedservo.c
@@ -0,0 +1,923 @@
+#include "stdafx.h"
+#include "cphidgetadvancedservo.h"
+#include "cusb.h"
+#include "csocket.h"
+#include "cthread.h"
+
+// === Internal Functions === //
+static int CPhidgetAdvancedServo_makePacket(CPhidgetAdvancedServoHandle phid, unsigned char *buffer, int Index);
+
+//clearVars - sets all device variables to unknown state
+CPHIDGETCLEARVARS(AdvancedServo)
+ int i = 0;
+
+ phid->motorPositionMaxLimit = PUNI_DBL;
+ phid->motorPositionMinLimit = PUNI_DBL;
+ phid->velocityMaxLimit = PUNI_DBL;
+ phid->velocityMin = PUNI_DBL;
+ phid->accelerationMax = PUNI_DBL;
+ phid->accelerationMin = PUNI_DBL;
+ phid->PGoodErrState = PFALSE;
+
+ for (i = 0; i<ADVSERVO_MAXSERVOS; i++)
+ {
+ phid->motorVelocityEcho[i] = PUNI_DBL;
+ phid->motorPositionEcho[i] = PUNI_DBL;
+ phid->motorSensedCurrent[i] = PUNI_DBL;
+ phid->motorSpeedRampingStateEcho[i] = PUNI_BOOL;
+ phid->motorStoppedState[i] = PUNI_BOOL;
+ phid->motorEngagedStateEcho[i] = PUNI_BOOL;
+ phid->packetCounterEcho[i] = PUNK_INT;
+
+ phid->motorPosition[i] = PUNK_DBL;
+ phid->motorAcceleration[i] = PUNK_DBL;
+ phid->motorVelocity[i] = PUNK_DBL;
+ phid->motorSpeedRampingState[i] = PUNK_BOOL;
+ phid->motorEngagedState[i] = PUNK_BOOL;
+ phid->packetCounter[i] = PUNK_INT;
+
+ phid->velocityMax[i] = PUNI_DBL;
+ phid->motorPositionMax[i] = PUNI_DBL;
+ phid->motorPositionMin[i] = PUNI_DBL;
+
+ phid->servoParams[i].state = PUNI_BOOL;
+ }
+ return EPHIDGET_OK;
+}
+
+//initAfterOpen - sets up the initial state of an object, reading in packets from the device if needed
+// used during attach initialization - on every attach
+CPHIDGETINIT(AdvancedServo)
+ int i = 0, result = 0, readcount = 100;
+ unsigned char buffer[8];
+
+ TESTPTR(phid);
+ ZEROMEM(buffer, 8);
+
+ //Make sure no old writes are still pending
+ phid->outputPacketLen = 0;
+
+ //Setup max/min values
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_ADVANCEDSERVO_8MOTOR:
+ case PHIDID_ADVANCEDSERVO_1MOTOR:
+ if ((phid->phid.deviceVersion >= 100) && (phid->phid.deviceVersion < 400))
+ {
+ phid->motorPositionMaxLimit = 32768/12.0;
+ phid->motorPositionMinLimit = 1/12.0;
+ phid->velocityMaxLimit = (50/12.0) * 16384; //68266.67 us/s
+ phid->velocityMin = 0;
+ phid->accelerationMax = (50/12.0) / 0.02 * 16384; //3413333.33 us/s^2
+ phid->accelerationMin = (50/12.0) / 0.02; //min velocity over time integration increment - 208.33 us/s^2
+
+ phid->PGoodErrState = PFALSE;
+ }
+ else
+ return EPHIDGET_BADVERSION;
+ break;
+ default:
+ return EPHIDGET_UNEXPECTED;
+ }
+
+ //initialize triggers, set data arrays to unknown
+ for (i = 0; i<phid->phid.attr.advancedservo.numMotors; i++)
+ {
+ phid->motorVelocityEcho[i] = PUNK_DBL;
+ phid->motorPositionEcho[i] = PUNK_DBL;
+ phid->motorSensedCurrent[i] = PUNK_DBL;
+ phid->motorSpeedRampingStateEcho[i] = PUNK_BOOL;
+ phid->motorStoppedState[i] = PUNK_BOOL;
+ phid->motorEngagedStateEcho[i] = PUNK_BOOL;
+ phid->packetCounterEcho[i] = PUNK_INT;
+ phid->packetCounter[i] = PUNK_INT;
+ //Using this for historical reasons
+ phid->servoParams[i] = Phid_Servo_Types[getServoParameterIndex(PHIDGET_SERVO_DEFAULT)];
+ }
+
+ //read in initial state - only one packet needed
+ CPhidget_read((CPhidgetHandle)phid);
+
+ //At this point, we can only recover (maybe) the position, speed ramping, engaged state.
+ for (i = 0; i<phid->phid.attr.advancedservo.numMotors; i++)
+ {
+ phid->motorPosition[i] = phid->motorPositionEcho[i];
+ phid->motorAcceleration[i] = PUNK_DBL;
+ phid->motorVelocity[i] = PUNK_DBL;
+ phid->motorSpeedRampingState[i] = phid->motorSpeedRampingStateEcho[i];
+ phid->motorEngagedState[i] = phid->motorEngagedStateEcho[i];
+ phid->packetCounter[i] = phid->packetCounterEcho[i];
+
+ if(phid->motorStoppedState[i] == PUNK_BOOL)
+ {
+ if(phid->motorVelocityEcho[i] == 0 || phid->motorEngagedStateEcho[i] == PFALSE)
+ phid->motorStoppedState[i] = PTRUE;
+ else
+ phid->motorStoppedState[i] = PFALSE;
+ }
+ }
+
+ //we need to set the min/max positions for each motor according to the servo settings
+ for (i = 0; i<phid->phid.attr.advancedservo.numMotors; i++)
+ {
+ phid->velocityMax[i] = phid->servoParams[i].max_us_per_s;
+
+ phid->motorPositionMin[i] = phid->servoParams[i].min_us;
+ if(phid->servoParams[i].max_us > phid->motorPositionMaxLimit)
+ phid->motorPositionMax[i] = phid->motorPositionMaxLimit;
+ else
+ phid->motorPositionMax[i] = phid->servoParams[i].max_us;
+
+ if((result = CPhidgetAdvancedServo_makePacket(phid, buffer, i + ADVSERVO_MINMAX_PACKET)))
+ return result;
+ if ((result = CUSBSendPacket((CPhidgetHandle)phid, buffer)))
+ return result;
+ }
+
+ //read till the packet counters are in sync (max of 100 reads)
+ while(1)
+ {
+ int again = PFALSE;
+ for (i = 0; i<phid->phid.attr.advancedservo.numMotors; i++)
+ {
+ if(phid->packetCounter[i] != phid->packetCounterEcho[i])
+ again = PTRUE;
+ }
+ if(again)
+ CPhidget_read((CPhidgetHandle)phid);
+ else
+ break;
+
+ readcount--;
+ if(readcount == 0)
+ return EPHIDGET_UNEXPECTED;
+ }
+
+ return EPHIDGET_OK;
+}
+
+//dataInput - parses device packets
+CPHIDGETDATA(AdvancedServo)
+ int i=0;
+
+ unsigned char speedRamping[ADVSERVO_MAXSERVOS], motorEngaged[ADVSERVO_MAXSERVOS], motorDone[ADVSERVO_MAXSERVOS], justStopped[ADVSERVO_MAXSERVOS];
+ double velocity[ADVSERVO_MAXSERVOS], position[ADVSERVO_MAXSERVOS], current[ADVSERVO_MAXSERVOS];
+ double lastVelocity[ADVSERVO_MAXSERVOS], lastPosition[ADVSERVO_MAXSERVOS], lastCurrent[ADVSERVO_MAXSERVOS];
+ int pwmEcho[ADVSERVO_MAXSERVOS];
+ char error_buffer[128];
+
+ if (length < 0) return EPHIDGET_INVALIDARG;
+ TESTPTR(phid);
+ TESTPTR(buffer);
+
+ //Parse device packets - store data locally
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_ADVANCEDSERVO_8MOTOR:
+ if ((phid->phid.deviceVersion >= 100) && (phid->phid.deviceVersion < 200))
+ {
+ for (i = 0; i < phid->phid.attr.advancedservo.numMotors; i++)
+ {
+ phid->packetCounterEcho[i] = buffer[0+(i*7)] & 0x0F;
+ motorEngaged[i] = (buffer[0+(i*7)] & MOTOR_DISABLED_ADVSERVO) ? PFALSE : PTRUE;
+ speedRamping[i] = (buffer[0+(i*7)] & NO_RAMPING_FLAG_ADVSERVO) ? PFALSE : PTRUE;
+ motorDone[i] = (buffer[0+(i*7)] & MOTOR_DONE_ADVSERVO) ? PTRUE : PFALSE;
+
+ pwmEcho[i] = (unsigned short)(buffer[1+(i*7)] << 8) + (unsigned char)(buffer[2+(i*7)]);
+ position[i] = pwmEcho[i]/12.0;
+
+ velocity[i] = (signed short)(buffer[3+(i*7)] << 8) + (unsigned char)(buffer[4+(i*7)]);
+ velocity[i] = round_double(((velocity[i]/16384.0)*phid->velocityMaxLimit), 2);
+
+ current[i] = (unsigned short)(buffer[5+(i*7)] << 8) + (unsigned char)(buffer[6+(i*7)]);
+ current[i] = round_double(((50.0/11.0) * (current[i]/16384.0)), 4);
+ }
+ }
+ //overcurrent detect
+ else if ((phid->phid.deviceVersion >= 200) && (phid->phid.deviceVersion < 300))
+ {
+ unsigned char powerGoodEcho;
+
+ for (i = 0; i < phid->phid.attr.advancedservo.numMotors; i++)
+ {
+ phid->packetCounterEcho[i] = buffer[0+(i*7)] & 0x0F;
+ motorEngaged[i] = (buffer[0+(i*7)] & MOTOR_DISABLED_ADVSERVO) ? PFALSE : PTRUE;
+ speedRamping[i] = (buffer[0+(i*7)] & NO_RAMPING_FLAG_ADVSERVO) ? PFALSE : PTRUE;
+ motorDone[i] = (buffer[0+(i*7)] & MOTOR_DONE_ADVSERVO) ? PTRUE : PFALSE;
+
+ pwmEcho[i] = (unsigned short)(buffer[1+(i*7)] << 8) + (unsigned char)(buffer[2+(i*7)]);
+ position[i] = pwmEcho[i]/12.0;
+
+ velocity[i] = (signed short)(buffer[3+(i*7)] << 8) + (unsigned char)(buffer[4+(i*7)]);
+ velocity[i] = round_double(((velocity[i]/16384.0)*phid->velocityMaxLimit), 2);
+
+ current[i] = (unsigned short)(buffer[5+(i*7)] << 8) + (unsigned char)(buffer[6+(i*7)]);
+ current[i] = round_double(((50.0/11.0) * (current[i]/16384.0)), 4);
+ }
+
+ //PowerGood
+ if(buffer[56] & ADVSERVO_PGOOD_FLAG)
+ {
+ phid->PGoodErrState = PFALSE;
+ powerGoodEcho = PTRUE;
+ }
+ else
+ {
+ powerGoodEcho = PFALSE;
+ }
+
+ if(!powerGoodEcho && phid->PGoodErrState == PFALSE)
+ {
+ phid->PGoodErrState = PTRUE;
+ FIRE_ERROR(EEPHIDGET_BADPOWER, "Bad power supply detected - undervoltage or overcurrent.");
+ }
+ }
+ //different current sense formula
+ else if ((phid->phid.deviceVersion >= 300) && (phid->phid.deviceVersion < 400))
+ {
+ unsigned char powerGoodEcho;
+
+ for (i = 0; i < phid->phid.attr.advancedservo.numMotors; i++)
+ {
+ phid->packetCounterEcho[i] = buffer[0+(i*7)] & 0x0F;
+ motorEngaged[i] = (buffer[0+(i*7)] & MOTOR_DISABLED_ADVSERVO) ? PFALSE : PTRUE;
+ speedRamping[i] = (buffer[0+(i*7)] & NO_RAMPING_FLAG_ADVSERVO) ? PFALSE : PTRUE;
+ motorDone[i] = (buffer[0+(i*7)] & MOTOR_DONE_ADVSERVO) ? PTRUE : PFALSE;
+
+ pwmEcho[i] = (unsigned short)(buffer[1+(i*7)] << 8) + (unsigned char)(buffer[2+(i*7)]);
+ position[i] = pwmEcho[i]/12.0;
+
+ velocity[i] = (signed short)(buffer[3+(i*7)] << 8) + (unsigned char)(buffer[4+(i*7)]);
+ velocity[i] = round_double(((velocity[i]/16384.0)*phid->velocityMaxLimit), 2);
+
+ current[i] = (unsigned short)(buffer[5+(i*7)] << 8) + (unsigned char)(buffer[6+(i*7)]);
+ current[i] = round_double((((5.0/11.0)/0.022) * (current[i]/16384.0)), 4);
+ }
+
+ //PowerGood
+ if(buffer[56] & ADVSERVO_PGOOD_FLAG)
+ {
+ phid->PGoodErrState = PFALSE;
+ powerGoodEcho = PTRUE;
+ }
+ else
+ {
+ powerGoodEcho = PFALSE;
+ }
+
+ if(!powerGoodEcho && phid->PGoodErrState == PFALSE)
+ {
+ phid->PGoodErrState = PTRUE;
+ FIRE_ERROR(EEPHIDGET_BADPOWER, "Bad power supply detected - undervoltage or overcurrent.");
+ }
+ }
+ else
+ return EPHIDGET_UNEXPECTED;
+ break;
+ case PHIDID_ADVANCEDSERVO_1MOTOR:
+ if ((phid->phid.deviceVersion >= 100) && (phid->phid.deviceVersion < 200))
+ {
+ phid->packetCounterEcho[i] = buffer[0] & 0x0F;
+ motorEngaged[i] = (buffer[0] & MOTOR_DISABLED_ADVSERVO) ? PFALSE : PTRUE;
+ speedRamping[i] = (buffer[0] & NO_RAMPING_FLAG_ADVSERVO) ? PFALSE : PTRUE;
+ motorDone[i] = (buffer[0] & MOTOR_DONE_ADVSERVO) ? PTRUE : PFALSE;
+
+ pwmEcho[i] = (unsigned short)(buffer[1] << 8) + (unsigned char)(buffer[2]);
+ position[i] = pwmEcho[i]/12.0;
+
+ velocity[i] = (signed short)(buffer[3] << 8) + (unsigned char)(buffer[4]);
+ velocity[i] = round_double(((velocity[i]/16384.0)*phid->velocityMaxLimit), 2);
+
+ current[i] = (unsigned short)(buffer[5] << 8) + (unsigned char)(buffer[6]);
+ current[i] = round_double((current[i]/2068.0), 4);
+ }
+ else
+ return EPHIDGET_UNEXPECTED;
+ break;
+ default:
+ return EPHIDGET_UNEXPECTED;
+ }
+
+ //Make sure values are within defined range, and store to structure
+ for (i = 0; i < phid->phid.attr.advancedservo.numMotors; i++)
+ {
+ lastPosition[i] = phid->motorPositionEcho[i];
+ lastVelocity[i] = phid->motorVelocityEcho[i];
+ lastCurrent[i] = phid->motorSensedCurrent[i];
+
+ if(position[i] > phid->motorPositionMaxLimit || position[i] < phid->motorPositionMinLimit)
+ phid->motorPositionEcho[i] = PUNK_DBL;
+ else
+ phid->motorPositionEcho[i] = position[i];
+ if(velocity[i] > phid->velocityMaxLimit || velocity[i] < -phid->velocityMaxLimit)
+ LOG(PHIDGET_LOG_WARNING, "Phidget advanced servo recieved out of range velocity data: %lE", velocity[i]);
+ else
+ phid->motorVelocityEcho[i] = velocity[i];
+
+ phid->motorSensedCurrent[i] = current[i];
+
+ phid->motorSpeedRampingStateEcho[i] = speedRamping[i];
+ phid->motorEngagedStateEcho[i] = motorEngaged[i];
+ }
+
+ //make sure phid->motorStoppedState isn't updated until the other data is filled in
+ CThread_mutex_lock(&phid->phid.writelock);
+ for (i = 0; i < phid->phid.attr.stepper.numMotors; i++)
+ {
+ int pwm = round(phid->motorPosition[i] * 12.0);
+ //if we are up to date, and the motor is done, set stopped to true - this is the only place that this gets set true;
+ justStopped[i] = PFALSE;
+ if(phid->packetCounter[i] == phid->packetCounterEcho[i] && motorDone[i] == PTRUE
+ && ((pwmEcho[i] == pwm && phid->motorVelocityEcho[i] == 0) || phid->motorEngagedStateEcho[i] == PFALSE))
+ {
+ if(phid->motorStoppedState[i] == PFALSE)
+ justStopped[i] = PTRUE;
+ phid->motorStoppedState[i] = PTRUE;
+ }
+ else if(motorDone[i] == PFALSE)
+ phid->motorStoppedState[i] = PFALSE;
+ }
+ CThread_mutex_unlock(&phid->phid.writelock);
+
+ //send out any events for changed data
+ //only send a position event if the motor is engaged
+ for (i = 0; i < phid->phid.attr.advancedservo.numMotors; i++)
+ {
+ if(phid->motorPositionEcho[i] != PUNK_DBL && phid->motorEngagedStateEcho[i] == PTRUE
+ && (phid->motorPositionEcho[i] != lastPosition[i] || justStopped[i] == PTRUE) )
+ FIRE(PositionChange, i, servo_us_to_degrees(phid->servoParams[i], phid->motorPositionEcho[i], PTRUE));
+
+ if(phid->motorVelocityEcho[i] != PUNK_DBL && phid->motorVelocityEcho[i] != lastVelocity[i])
+ FIRE(VelocityChange, i, servo_us_to_degrees_vel(phid->servoParams[i], phid->motorVelocityEcho[i], PTRUE));
+
+ if(phid->motorSensedCurrent[i] != PUNK_DBL && phid->motorSensedCurrent[i] != lastCurrent[i])
+ FIRE(CurrentChange, i, phid->motorSensedCurrent[i]);
+ }
+
+ return EPHIDGET_OK;
+}
+
+//eventsAfterOpen - sends out an event for all valid data, used during attach initialization
+CPHIDGETINITEVENTS(AdvancedServo)
+
+ for (i = 0; i<phid->phid.attr.advancedservo.numMotors; i++)
+ {
+ if(phid->motorSensedCurrent[i] != PUNK_DBL)
+ FIRE(CurrentChange, i, phid->motorSensedCurrent[i]);
+ if(phid->motorVelocityEcho[i] != PUNK_DBL)
+ FIRE(VelocityChange, i, servo_us_to_degrees_vel(phid->servoParams[i], phid->motorVelocityEcho[i], PTRUE));
+ if(phid->motorPositionEcho[i] != PUNK_DBL && phid->motorEngagedStateEcho[i] == PTRUE)
+ FIRE(PositionChange, i, servo_us_to_degrees(phid->servoParams[i], phid->motorPositionEcho[i], PTRUE));
+ }
+
+ return EPHIDGET_OK;
+}
+
+//getPacket - used by write thread to get the next packet to send to device
+CGETPACKET_BUF(AdvancedServo)
+
+//sendpacket - sends a packet to the device asynchronously, blocking if the 1-packet queue is full
+CSENDPACKET_BUF(AdvancedServo)
+
+//makePacket - constructs a packet using current device state
+CMAKEPACKETINDEXED(AdvancedServo)
+ int pwm = 0, velocity = 0, accel = 0, minpwm=0, maxpwm=0;
+ unsigned char flags = 0;
+
+ int packet_type = Index & 0x10;
+ Index = Index & 0x07;
+
+ TESTPTRS(phid, buffer);
+
+ if(phid->packetCounter[Index] == PUNK_INT)
+ phid->packetCounter[Index] = 0;
+
+ phid->packetCounter[Index]++;
+ phid->packetCounter[Index] &= 0x0F;
+
+ phid->motorStoppedState[Index] = PFALSE;
+
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_ADVANCEDSERVO_8MOTOR:
+ case PHIDID_ADVANCEDSERVO_1MOTOR:
+ if ((phid->phid.deviceVersion >= 100) && (phid->phid.deviceVersion < 400))
+ {
+
+ if(phid->motorSpeedRampingState[Index] == PUNK_BOOL)
+ phid->motorSpeedRampingState[Index] = PTRUE;
+ if(phid->motorEngagedState[Index] == PUNK_BOOL)
+ phid->motorEngagedState[Index] = PFALSE; //note motors are not engaged by default
+
+ if(phid->motorSpeedRampingState[Index] == PFALSE)
+ flags |= NO_RAMPING_FLAG_ADVSERVO;
+
+ if(phid->motorEngagedState[Index] == PFALSE)
+ flags |= MOTOR_DISABLED_ADVSERVO;
+
+ //2-bit index, 2-bit packet type, 4-bit counter
+ buffer[0] = (Index << 5) | packet_type | phid->packetCounter[Index];
+ buffer[1] = flags;
+
+ switch(packet_type)
+ {
+ case ADVSERVO_NORMAL_PACKET:
+ //have to make sure that everything to be sent has some sort of default value if the user hasn't set a value
+ if(phid->motorPosition[Index] == PUNK_DBL)
+ phid->motorPosition[Index] = round((phid->motorPositionMax[Index] - phid->motorPositionMin[Index])/2); //mid-range valid posn (much better then 0)
+ if(phid->motorVelocity[Index] == PUNK_DBL)
+ {
+ if(phid->servoParams[Index].servoType == PHIDGET_SERVO_DEFAULT)
+ phid->motorVelocity[Index] = 128/12.0*316;//historical reasons
+ else
+ phid->motorVelocity[Index] = phid->servoParams[Index].max_us_per_s; //max speed of the servo Phidgets sells (0.19sec/60 degrees at 4.8V) //TODO: could bump this because it's 5V
+ }
+ if(phid->motorAcceleration[Index] == PUNK_DBL)
+ phid->motorAcceleration[Index] = phid->accelerationMax / 2; //mid-level acceleration
+ pwm = round(phid->motorPosition[Index] * 12.0);
+ velocity = round((phid->motorVelocity[Index] / phid->velocityMaxLimit) * 16384);
+ accel = round((phid->motorAcceleration[Index] / phid->accelerationMax) * 16384);
+
+ buffer[2] = (unsigned char)((pwm >> 8) & 0xff);
+ buffer[3] = (unsigned char)(pwm & 0xff);
+ buffer[4] = (unsigned char)((velocity >> 8) & 0xff);
+ buffer[5] = (unsigned char)(velocity & 0xff);
+ buffer[6] = (unsigned char)((accel >> 8) & 0xff);
+ buffer[7] = (unsigned char)(accel & 0xff);
+ break;
+ case ADVSERVO_MINMAX_PACKET:
+ minpwm = round(phid->motorPositionMin[Index] * 12.0);
+ maxpwm = round(phid->motorPositionMax[Index] * 12.0);
+
+ buffer[2] = (unsigned char)((minpwm >> 8) & 0xff);
+ buffer[3] = (unsigned char)(minpwm & 0xff);
+ buffer[4] = (unsigned char)((maxpwm >> 8) & 0xff);
+ buffer[5] = (unsigned char)(maxpwm & 0xff);
+ buffer[6] = 0;
+ buffer[7] = 0;
+ break;
+ default:
+ return EPHIDGET_UNEXPECTED;
+ }
+ }
+ else
+ return EPHIDGET_UNEXPECTED;
+ break;
+ default:
+ return EPHIDGET_UNEXPECTED;
+ }
+
+ return EPHIDGET_OK;
+}
+
+// === Servo Definitions === //
+/* Updating this list:
+ * -update the list in AS3 - AS3 has it's own version of all these numbers
+ * -updated constants/enums in .NET, COM, Java (2 files), AS3 (3 files), AppleScript
+ * -don't updated webservice version - webservice sends everything in us, and one message for servo params.
+ */
+const CPhidgetServoParameters Phid_Servo_Types[] = {
+ {PHIDGET_SERVO_DEFAULT, 23 * 128/12.0, 243 * 128/12.0, 128/12.0, 50/12.0*16384}, //245.3us(0)-2592us(220), 10.666us/degree, max vel
+ {PHIDGET_SERVO_RAW_us_MODE, 0, 10000, 1, 50/12.0*16384}, //0us-MAXus, 1us/us, max vel
+ {PHIDGET_SERVO_HITEC_HS322HD, 630, 2310, 1680/180.0, 1680/180.0*316},//180 degrees, 316deg/s
+ {PHIDGET_SERVO_HITEC_HS5245MG, 765, 2185, 1420/145.0, 1420/145.0*400},//145 degrees, 400deg/s
+ {PHIDGET_SERVO_HITEC_805BB, 650, 2350, 1700/180.0, 1700/180.0*316},//180 degrees, 316deg/s
+ {PHIDGET_SERVO_HITEC_HS422, 650, 2450, 1800/180.0, 1800/180.0*286},//180 degrees, 286deg/s
+ {PHIDGET_SERVO_TOWERPRO_MG90, 485, 2335, 1850/175.0, 1850/175.0*545},//175 degrees, 545deg/s
+ {PHIDGET_SERVO_HITEC_HSR1425CR, 1300, 1740, 440/100.0, 50/12.0*16384}, //"100" degrees (stopped at 50), max vel
+ {PHIDGET_SERVO_HITEC_HS785HB, 700, 2550, 1850/2880.0, 1850/2880.0*225},//2881 degrees, 225deg/s
+ {PHIDGET_SERVO_HITEC_HS485HB, 580, 2400, 1820/180.0, 1820/180.0*272},//180 degrees, 272deg/s
+ {PHIDGET_SERVO_HITEC_HS645MG, 580, 2330, 1750/180.0, 1750/180.0*300},//180 degrees, 300deg/s
+ {PHIDGET_SERVO_HITEC_815BB, 980, 2050, 1070/180.0, 1070/180.0*250},//180 degrees, 250deg/s
+ {PHIDGET_SERVO_FIRGELLI_L12_30_50_06_R, 1000, 2000, 1000/30.0, 1000/30.0*23}, //30mm, 23mm/s
+ {PHIDGET_SERVO_FIRGELLI_L12_50_100_06_R,1000, 2000, 1000/50.0, 1000/50.0*12}, //50mm, 12mm/s
+ {PHIDGET_SERVO_FIRGELLI_L12_50_210_06_R,1000, 2000, 1000/50.0, 1000/50.0*5}, //50mm, 5mm/s
+ {PHIDGET_SERVO_FIRGELLI_L12_100_50_06_R,1000, 2000, 1000/100.0, 1000/100.0*23}, //100mm, 23mm/s
+ {PHIDGET_SERVO_FIRGELLI_L12_100_100_06_R,1000, 2000, 1000/100.0, 1000/100.0*12}, //100mm, 12mm/s
+ {PHIDGET_SERVO_SPRINGRC_SM_S2313M, 535, 2210, 1675/180.0, 1675/180.0*600},//180 degrees, 600deg/s
+ {PHIDGET_SERVO_SPRINGRC_SM_S3317M, 565, 2365, 1800/180.0, 1800/180.0*375},//180 degrees, 375deg/s
+ {PHIDGET_SERVO_SPRINGRC_SM_S3317SR, 1125, 1745, 620/100.0, 50/12.0*16384}, //"100" degrees (stopped at 50 (1435)), max vel
+ {PHIDGET_SERVO_SPRINGRC_SM_S4303R, 1050, 1950, 910/100.0, 50/12.0*16384}, //"100" degrees (stopped at 50 (1495)), max vel
+ {PHIDGET_SERVO_SPRINGRC_SM_S4315M, 630, 2370, 1740/180.0, 1740/180.0*285},//180 degrees, 285deg/s
+ {PHIDGET_SERVO_SPRINGRC_SM_S4315R, 1150, 1800, 650/100.0, 50/12.0*16384}, //"100" degrees (stopped at 50 (1475)), max vel
+ {PHIDGET_SERVO_SPRINGRC_SM_S4505B, 665, 2280, 1615/180.0, 1615/180.0*400},//180 degrees, 400deg/s
+ {PHIDGET_SERVO_USER_DEFINED,0,0,0,0},
+ {0,0,0,0,0}//null
+};
+
+int getServoParameterIndex(CPhidget_ServoType type)
+{
+ int i=0;
+ while(Phid_Servo_Types[i].servoType)
+ {
+ if(Phid_Servo_Types[i].servoType == type)
+ return i;
+ i++;
+ }
+ return 0;
+}
+double servo_us_to_degrees(CPhidgetServoParameters params, double us, unsigned char round)
+{
+ if(round)
+ return round_double((us - params.min_us) / params.us_per_degree, 3);
+ return (us - params.min_us) / params.us_per_degree;
+}
+double servo_degrees_to_us(CPhidgetServoParameters params, double degrees)
+{
+ return (degrees + (params.min_us / params.us_per_degree)) * params.us_per_degree;
+}
+double servo_us_to_degrees_vel(CPhidgetServoParameters params, double us, unsigned char round)
+{
+ if(round)
+ return round_double(us / params.us_per_degree, 3);
+ return us / params.us_per_degree;
+}
+double servo_degrees_to_us_vel(CPhidgetServoParameters params, double degrees)
+{
+ return degrees * params.us_per_degree;
+}
+
+// === Exported Functions === //
+
+//create and initialize a device structure
+CCREATE(AdvancedServo, PHIDCLASS_ADVANCEDSERVO)
+
+//event setup functions
+CFHANDLE(AdvancedServo, PositionChange, int, double)
+CFHANDLE(AdvancedServo, VelocityChange, int, double)
+CFHANDLE(AdvancedServo, CurrentChange, int, double)
+
+CGET(AdvancedServo,MotorCount,int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_ADVANCEDSERVO)
+ TESTATTACHED
+
+ MASGN(phid.attr.advancedservo.numMotors);
+}
+
+CGETINDEX(AdvancedServo,Acceleration,double)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_ADVANCEDSERVO)
+ TESTATTACHED
+ TESTINDEX(phid.attr.advancedservo.numMotors)
+ TESTMASGN(motorAcceleration[Index], PUNK_DBL)
+
+ *pVal = servo_us_to_degrees_vel(phid->servoParams[Index], phid->motorAcceleration[Index], PTRUE);
+ return EPHIDGET_OK;
+}
+CSETINDEX(AdvancedServo,Acceleration,double)
+ TESTPTR(phid)
+ TESTDEVICETYPE(PHIDCLASS_ADVANCEDSERVO)
+ TESTATTACHED
+ TESTINDEX(phid.attr.advancedservo.numMotors)
+ TESTRANGE(servo_us_to_degrees_vel(phid->servoParams[Index], phid->accelerationMin, PFALSE),
+ servo_us_to_degrees_vel(phid->servoParams[Index], phid->accelerationMax, PFALSE))
+
+ newVal = servo_degrees_to_us_vel(phid->servoParams[Index], newVal);
+
+ if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
+ ADDNETWORKKEYINDEXED(Acceleration, "%lE", motorAcceleration);
+ else
+ SENDPACKETINDEXED(AdvancedServo, motorAcceleration[Index], Index + ADVSERVO_NORMAL_PACKET);
+
+ return EPHIDGET_OK;
+}
+
+CGETINDEX(AdvancedServo,AccelerationMax,double)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_ADVANCEDSERVO)
+ TESTATTACHED
+ TESTINDEX(phid.attr.advancedservo.numMotors)
+ TESTMASGN(accelerationMax, PUNK_DBL)
+
+ *pVal = servo_us_to_degrees_vel(phid->servoParams[Index], phid->accelerationMax, PTRUE);
+ return EPHIDGET_OK;
+}
+
+CGETINDEX(AdvancedServo,AccelerationMin,double)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_ADVANCEDSERVO)
+ TESTATTACHED
+ TESTINDEX(phid.attr.advancedservo.numMotors)
+ TESTMASGN(accelerationMin, PUNK_DBL)
+
+ *pVal = servo_us_to_degrees_vel(phid->servoParams[Index], phid->accelerationMin, PTRUE);
+ return EPHIDGET_OK;
+}
+
+CGETINDEX(AdvancedServo,VelocityLimit,double)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_ADVANCEDSERVO)
+ TESTATTACHED
+ TESTINDEX(phid.attr.advancedservo.numMotors)
+ TESTMASGN(motorVelocity[Index], PUNK_DBL)
+
+ *pVal = servo_us_to_degrees_vel(phid->servoParams[Index], phid->motorVelocity[Index], PTRUE);
+ return EPHIDGET_OK;
+}
+CSETINDEX(AdvancedServo,VelocityLimit,double)
+ TESTPTR(phid)
+ TESTDEVICETYPE(PHIDCLASS_ADVANCEDSERVO)
+ TESTATTACHED
+ TESTINDEX(phid.attr.advancedservo.numMotors)
+ TESTRANGE(servo_us_to_degrees_vel(phid->servoParams[Index], phid->velocityMin, PTRUE)-0.5,
+ servo_us_to_degrees_vel(phid->servoParams[Index], phid->velocityMax[Index]+0.5, PTRUE))
+
+ newVal = servo_degrees_to_us_vel(phid->servoParams[Index], newVal);
+
+ if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
+ ADDNETWORKKEYINDEXED(VelocityLimit, "%lE", motorVelocity);
+ else
+ SENDPACKETINDEXED(AdvancedServo, motorVelocity[Index], Index + ADVSERVO_NORMAL_PACKET);
+
+ return EPHIDGET_OK;
+}
+
+CGETINDEX(AdvancedServo,Velocity,double)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_ADVANCEDSERVO)
+ TESTATTACHED
+ TESTINDEX(phid.attr.advancedservo.numMotors)
+ TESTMASGN(motorVelocityEcho[Index], PUNK_DBL)
+
+ *pVal = servo_us_to_degrees_vel(phid->servoParams[Index], phid->motorVelocityEcho[Index], PTRUE);
+ return EPHIDGET_OK;
+}
+
+CGETINDEX(AdvancedServo,VelocityMax,double)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_ADVANCEDSERVO)
+ TESTATTACHED
+ TESTINDEX(phid.attr.advancedservo.numMotors)
+ TESTMASGN(velocityMax[Index], PUNK_DBL)
+
+ *pVal = servo_us_to_degrees_vel(phid->servoParams[Index], phid->velocityMax[Index], PTRUE);
+ return EPHIDGET_OK;
+}
+
+CGETINDEX(AdvancedServo,VelocityMin,double)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_ADVANCEDSERVO)
+ TESTATTACHED
+ TESTINDEX(phid.attr.advancedservo.numMotors)
+ TESTMASGN(velocityMin, PUNK_DBL)
+
+ *pVal = servo_us_to_degrees_vel(phid->servoParams[Index], phid->velocityMin, PTRUE);
+ return EPHIDGET_OK;
+}
+
+CGETINDEX(AdvancedServo,Position,double)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_ADVANCEDSERVO)
+ TESTATTACHED
+ TESTINDEX(phid.attr.advancedservo.numMotors)
+ TESTMASGN(motorPositionEcho[Index], PUNK_DBL)
+
+ //send unknown if the motor is not engaged
+ if(phid->motorEngagedStateEcho[Index] != PTRUE) {*pVal = PUNK_DBL; return EPHIDGET_UNKNOWNVAL;}
+
+ *pVal = servo_us_to_degrees(phid->servoParams[Index], phid->motorPositionEcho[Index], PTRUE);
+ return EPHIDGET_OK;
+}
+CSETINDEX(AdvancedServo,Position,double)
+ TESTPTR(phid)
+ TESTDEVICETYPE(PHIDCLASS_ADVANCEDSERVO)
+ TESTATTACHED
+ TESTINDEX(phid.attr.advancedservo.numMotors)
+ TESTRANGE(servo_us_to_degrees(phid->servoParams[Index], phid->motorPositionMin[Index], PTRUE)-0.5,
+ servo_us_to_degrees(phid->servoParams[Index], phid->motorPositionMax[Index], PTRUE)+0.5)
+
+ newVal = servo_degrees_to_us(phid->servoParams[Index], newVal);
+
+ if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
+ ADDNETWORKKEYINDEXED(Position, "%lE", motorPosition);
+ else
+ SENDPACKETINDEXED(AdvancedServo, motorPosition[Index], Index + ADVSERVO_NORMAL_PACKET);
+
+ return EPHIDGET_OK;
+}
+
+CGETINDEX(AdvancedServo,PositionMax,double)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_ADVANCEDSERVO)
+ TESTATTACHED
+ TESTINDEX(phid.attr.advancedservo.numMotors)
+ TESTMASGN(motorPositionMax[Index], PUNK_DBL)
+
+ *pVal = servo_us_to_degrees(phid->servoParams[Index], phid->motorPositionMax[Index], PTRUE);
+ return EPHIDGET_OK;
+}
+CSETINDEX(AdvancedServo,PositionMax,double)
+ TESTPTR(phid)
+ TESTDEVICETYPE(PHIDCLASS_ADVANCEDSERVO)
+ TESTATTACHED
+ TESTINDEX(phid.attr.advancedservo.numMotors)
+ newVal = servo_degrees_to_us(phid->servoParams[Index], newVal);
+ TESTRANGE(phid->motorPositionMin[Index], phid->motorPositionMaxLimit+0.5)
+
+ if(phid->motorPosition[Index] > newVal && phid->motorPosition[Index] != PUNK_DBL)
+ phid->motorPosition[Index] = newVal;
+
+ if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
+ ADDNETWORKKEYINDEXED(PositionMax, "%lE", motorPositionMax);
+ else
+ SENDPACKETINDEXED(AdvancedServo, motorPositionMax[Index], Index + ADVSERVO_MINMAX_PACKET);
+
+ return EPHIDGET_OK;
+}
+
+CGETINDEX(AdvancedServo,PositionMin,double)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_ADVANCEDSERVO)
+ TESTATTACHED
+ TESTINDEX(phid.attr.advancedservo.numMotors)
+ TESTMASGN(motorPositionMin[Index], PUNK_DBL)
+
+ *pVal = servo_us_to_degrees(phid->servoParams[Index], phid->motorPositionMin[Index], PTRUE);
+ return EPHIDGET_OK;
+}
+CSETINDEX(AdvancedServo,PositionMin,double)
+ TESTPTR(phid)
+ TESTDEVICETYPE(PHIDCLASS_ADVANCEDSERVO)
+ TESTATTACHED
+ TESTINDEX(phid.attr.advancedservo.numMotors)
+ newVal = servo_degrees_to_us(phid->servoParams[Index], newVal);
+ TESTRANGE(phid->motorPositionMinLimit-0.5, phid->motorPositionMax[Index])
+
+ if(phid->motorPosition[Index] < newVal && phid->motorPosition[Index] != PUNK_DBL)
+ phid->motorPosition[Index] = newVal;
+
+ if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
+ ADDNETWORKKEYINDEXED(PositionMin, "%lE", motorPositionMin);
+ else
+ SENDPACKETINDEXED(AdvancedServo, motorPositionMin[Index], Index + ADVSERVO_MINMAX_PACKET);
+
+ return EPHIDGET_OK;
+}
+
+CGETINDEX(AdvancedServo,Current,double)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_ADVANCEDSERVO)
+ TESTATTACHED
+ TESTINDEX(phid.attr.advancedservo.numMotors)
+ TESTMASGN(motorSensedCurrent[Index], PUNK_DBL)
+
+ MASGN(motorSensedCurrent[Index])
+}
+
+CGETINDEX(AdvancedServo,SpeedRampingOn,int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_ADVANCEDSERVO)
+ TESTATTACHED
+ TESTINDEX(phid.attr.advancedservo.numMotors)
+ TESTMASGN(motorSpeedRampingStateEcho[Index], PUNK_BOOL)
+
+ MASGN(motorSpeedRampingStateEcho[Index]);
+}
+CSETINDEX(AdvancedServo,SpeedRampingOn,int)
+ TESTPTR(phid)
+ TESTDEVICETYPE(PHIDCLASS_ADVANCEDSERVO)
+ TESTATTACHED
+ TESTINDEX(phid.attr.advancedservo.numMotors)
+ TESTRANGE(PFALSE, PTRUE)
+
+ if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
+ ADDNETWORKKEYINDEXED(SpeedRampingOn, "%d", motorSpeedRampingState);
+ else
+ SENDPACKETINDEXED(AdvancedServo, motorSpeedRampingState[Index], Index + ADVSERVO_NORMAL_PACKET);
+
+ return EPHIDGET_OK;
+}
+
+CGETINDEX(AdvancedServo,Engaged,int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_ADVANCEDSERVO)
+ TESTATTACHED
+ TESTINDEX(phid.attr.advancedservo.numMotors)
+ TESTMASGN(motorEngagedStateEcho[Index], PUNK_BOOL)
+
+ MASGN(motorEngagedStateEcho[Index])
+}
+CSETINDEX(AdvancedServo,Engaged,int)
+ TESTPTR(phid)
+ TESTDEVICETYPE(PHIDCLASS_ADVANCEDSERVO)
+ TESTATTACHED
+ TESTINDEX(phid.attr.advancedservo.numMotors)
+ TESTRANGE(PFALSE, PTRUE)
+
+ if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
+ ADDNETWORKKEYINDEXED(Engaged, "%d", motorEngagedState);
+ else
+ SENDPACKETINDEXED(AdvancedServo, motorEngagedState[Index], Index + ADVSERVO_NORMAL_PACKET);
+
+ return EPHIDGET_OK;
+}
+
+int setupNewAdvancedServoParams(CPhidgetAdvancedServoHandle phid, int Index, CPhidgetServoParameters params)
+{
+ int ret;
+ char newVal[256];
+
+ //Only let raw us mode set the position to 0 - servo mode forces the use of engaged
+ if(params.servoType == PHIDGET_SERVO_RAW_us_MODE)
+ phid->motorPositionMinLimit = 0;
+ else
+ phid->motorPositionMinLimit = 1/12.0;
+
+ phid->velocityMax[Index] = params.max_us_per_s;
+
+ if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
+ {
+ //TODO: make sure webservice sends along motorPositionMinLimit and velocityMax which may have changed
+ sprintf(newVal, "%d,%lE,%lE,%lE,%lE", params.servoType, params.min_us, params.max_us, params.us_per_degree, params.max_us_per_s);
+ ADDNETWORKKEYINDEXED(ServoParameters, "%s", servoParamString);
+ }
+
+ phid->servoParams[Index] = params;
+
+ //set max velocity, adjust velocityLimit if needed
+ if(phid->motorVelocity[Index] > phid->velocityMax[Index])
+ {
+ if((ret = CPhidgetAdvancedServo_setVelocityLimit(phid, Index, servo_us_to_degrees_vel(params, phid->velocityMax[Index], PFALSE))))
+ return ret;
+ }
+
+ //Set the max/min
+ //make sure we don't set mac higher then the limit
+ if(params.max_us > phid->motorPositionMaxLimit)
+ {
+ if((ret = CPhidgetAdvancedServo_setPositionMax(phid, Index, servo_us_to_degrees(params, phid->motorPositionMaxLimit, PFALSE))))
+ return ret;
+ }
+ else
+ {
+ if((ret = CPhidgetAdvancedServo_setPositionMax(phid, Index, servo_us_to_degrees(params, params.max_us, PFALSE))))
+ return ret;
+ }
+
+ if((ret = CPhidgetAdvancedServo_setPositionMin(phid, Index, servo_us_to_degrees(params, params.min_us, PFALSE))))
+ return ret;
+
+
+ return EPHIDGET_OK;
+}
+
+CGETINDEX(AdvancedServo,ServoType,CPhidget_ServoType)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_ADVANCEDSERVO)
+ TESTATTACHED
+ TESTINDEX(phid.attr.advancedservo.numMotors)
+
+ MASGN(servoParams[Index].servoType)
+}
+CSETINDEX(AdvancedServo,ServoType,CPhidget_ServoType)
+ TESTPTR(phid)
+ TESTDEVICETYPE(PHIDCLASS_ADVANCEDSERVO)
+ TESTATTACHED
+ TESTINDEX(phid.attr.advancedservo.numMotors)
+ //can't set to User defined with this function
+ TESTRANGE(PHIDGET_SERVO_DEFAULT, PHIDGET_SERVO_USER_DEFINED-1)
+
+ setupNewAdvancedServoParams(phid, Index, Phid_Servo_Types[getServoParameterIndex(newVal)]);
+
+ return EPHIDGET_OK;
+}
+
+PHIDGET21_API int CCONV CPhidgetAdvancedServo_setServoParameters(CPhidgetAdvancedServoHandle phid, int Index, double min_us, double max_us, double degrees, double velocity_max)
+{
+ CPhidgetServoParameters params;
+ TESTPTR(phid)
+ TESTDEVICETYPE(PHIDCLASS_ADVANCEDSERVO)
+ TESTATTACHED
+ TESTINDEX(phid.attr.advancedservo.numMotors)
+
+ //Sanity checking of the values
+ if(min_us < phid->motorPositionMinLimit)
+ return EPHIDGET_INVALIDARG;
+ if(max_us > phid->motorPositionMaxLimit)
+ return EPHIDGET_INVALIDARG;
+ if(max_us <= min_us)
+ return EPHIDGET_INVALIDARG;
+ if(degrees <= 0 || degrees > 1440)
+ return EPHIDGET_INVALIDARG;
+ if(velocity_max <= 0 || velocity_max > phid->velocityMaxLimit)
+ return EPHIDGET_INVALIDARG;
+
+ params.servoType = PHIDGET_SERVO_USER_DEFINED;
+ params.min_us = min_us;
+ params.max_us = max_us;
+ params.us_per_degree = (max_us - min_us)/degrees;
+ params.max_us_per_s = params.us_per_degree*velocity_max;
+
+ return setupNewAdvancedServoParams(phid, Index, params);
+}
+
+CGETINDEX(AdvancedServo,Stopped,int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_ADVANCEDSERVO)
+ TESTATTACHED
+ TESTINDEX(phid.attr.advancedservo.numMotors)
+ TESTMASGN(motorStoppedState[Index], PUNK_BOOL)
+
+ MASGN(motorStoppedState[Index])
+}
diff --git a/cphidgetadvancedservo.h b/cphidgetadvancedservo.h
new file mode 100644
index 0000000..23b3954
--- /dev/null
+++ b/cphidgetadvancedservo.h
@@ -0,0 +1,335 @@
+#ifndef __CPHIDGETADVANCEDSERVO
+#define __CPHIDGETADVANCEDSERVO
+#include "cphidget.h"
+
+/** \defgroup phidadvservo Phidget Advanced Servo
+ * \ingroup phidgets
+ * Calls specific to the Phidget Advanced Servo. See the product manual for more specific API details, supported functionality, units, etc.
+ * @{
+ */
+
+DPHANDLE(AdvancedServo)
+CHDRSTANDARD(AdvancedServo)
+
+
+/**
+ * The Phidget Servo Type sets the relationship of degrees to PCM width
+ */
+typedef enum {
+ PHIDGET_SERVO_DEFAULT = 1, /**< Default - This is what the servo API been historically used, originally based on the Futaba FP-S148 */
+ PHIDGET_SERVO_RAW_us_MODE, /**< Raw us mode - all position, velocity, acceleration functions are specified in microseconds rather then degrees */
+ PHIDGET_SERVO_HITEC_HS322HD, /**< HiTec HS-322HD Standard Servo */
+ PHIDGET_SERVO_HITEC_HS5245MG, /**< HiTec HS-5245MG Digital Mini Servo */
+ PHIDGET_SERVO_HITEC_805BB, /**< HiTec HS-805BB Mega Quarter Scale Servo */
+ PHIDGET_SERVO_HITEC_HS422, /**< HiTec HS-422 Standard Servo */
+ PHIDGET_SERVO_TOWERPRO_MG90, /**< Tower Pro MG90 Micro Servo */
+ PHIDGET_SERVO_HITEC_HSR1425CR, /**< HiTec HSR-1425CR Continuous Rotation Servo */
+ PHIDGET_SERVO_HITEC_HS785HB, /**< HiTec HS-785HB Sail Winch Servo */
+ PHIDGET_SERVO_HITEC_HS485HB, /**< HiTec HS-485HB Deluxe Servo */
+ PHIDGET_SERVO_HITEC_HS645MG, /**< HiTec HS-645MG Ultra Torque Servo */
+ PHIDGET_SERVO_HITEC_815BB, /**< HiTec HS-815BB Mega Sail Servo */
+ PHIDGET_SERVO_FIRGELLI_L12_30_50_06_R, /**< Firgelli L12 Linear Actuator 30mm 50:1*/
+ PHIDGET_SERVO_FIRGELLI_L12_50_100_06_R, /**< Firgelli L12 Linear Actuator 50mm 100:1*/
+ PHIDGET_SERVO_FIRGELLI_L12_50_210_06_R, /**< Firgelli L12 Linear Actuator 50mm 210:1*/
+ PHIDGET_SERVO_FIRGELLI_L12_100_50_06_R, /**< Firgelli L12 Linear Actuator 100mm 50:1*/
+ PHIDGET_SERVO_FIRGELLI_L12_100_100_06_R,/**< Firgelli L12 Linear Actuator 100mm 100:1*/
+ PHIDGET_SERVO_SPRINGRC_SM_S2313M, /**< SpringRC SM-S2313M Micro Servo*/
+ PHIDGET_SERVO_SPRINGRC_SM_S3317M, /**< SpringRC SM-S3317M Small Servo*/
+ PHIDGET_SERVO_SPRINGRC_SM_S3317SR, /**< SpringRC SM-S3317SR Small Continuous Rotation Servo*/
+ PHIDGET_SERVO_SPRINGRC_SM_S4303R, /**< SpringRC SM-S4303R Standard Continuous Rotation Servo*/
+ PHIDGET_SERVO_SPRINGRC_SM_S4315M, /**< SpringRC SM-S4315M High Torque Servo*/
+ PHIDGET_SERVO_SPRINGRC_SM_S4315R, /**< SpringRC SM-S4315R High Torque Continuous Rotation Servo*/
+ PHIDGET_SERVO_SPRINGRC_SM_S4505B, /**< SpringRC SM-S4505B Standard Servo*/
+ PHIDGET_SERVO_USER_DEFINED
+} CPhidget_ServoType;
+
+/**
+ * Gets the number of motors supported by this controller
+ * @param phid An attached phidget advanced servo handle.
+ * @param count The motor count.
+ */
+CHDRGET(AdvancedServo,MotorCount,int *count)
+
+/**
+ * Gets the last set acceleration for a motor.
+ * @param phid An attached phidget advanced servo handle
+ * @param index The motor index.
+ * @param acceleration The acceleration
+ */
+CHDRGETINDEX(AdvancedServo,Acceleration,double *acceleration)
+/**
+ * Sets the acceleration for a motor.
+ * @param phid An attached phidget advanced servo handle
+ * @param index The motor index.
+ * @param acceleration The acceleration
+ */
+CHDRSETINDEX(AdvancedServo,Acceleration,double acceleration)
+/**
+ * Gets the maximum acceleration supported by a motor
+ * @param phid An attached phidget advanced servo handle
+ * @param index The motor index.
+ * @param max The maximum acceleration.
+ */
+CHDRGETINDEX(AdvancedServo,AccelerationMax,double *max)
+/**
+ * Gets the minimum acceleration supported by a motor.
+ * @param phid An attached phidget advanced servo handle
+ * @param index The motor index.
+ * @param min The minimum acceleration
+ */
+CHDRGETINDEX(AdvancedServo,AccelerationMin,double *min)
+
+//set velocity
+/**
+ * Gets the last set velocity limit for a motor.
+ * @param phid An attached phidget advanced servo handle
+ * @param index The motor index.
+ * @param limit The velocity limit.
+ */
+CHDRGETINDEX(AdvancedServo,VelocityLimit,double *limit)
+/**
+ * Sets the velocity limit for a motor.
+ * @param phid An attached phidget advanced servo handle
+ * @param index The motor index.
+ * @param limit The velocity limit.
+ */
+CHDRSETINDEX(AdvancedServo,VelocityLimit,double limit)
+//Actual velocity
+/**
+ * Gets the current velocity of a motor.
+ * @param phid An attached phidget advanced servo handle
+ * @param index The motor index.
+ * @param velocity The current velocity.
+ */
+CHDRGETINDEX(AdvancedServo,Velocity,double *velocity)
+/**
+ * Gets the maximum velocity that can be set for a motor.
+ * @param phid An attached phidget advanced servo handle
+ * @param index The motor index.
+ * @param max The maximum velocity
+ */
+CHDRGETINDEX(AdvancedServo,VelocityMax,double *max)
+/**
+ * Gets the minimum velocity that can be set for a motor.
+ * @param phid An attached phidget advanced servo handle
+ * @param index The motor index.
+ * @param min The minimum velocity.
+ */
+CHDRGETINDEX(AdvancedServo,VelocityMin,double *min)
+/**
+ * Sets a velocity change event handler. This is called when the velocity changes.
+ * @param phid An attached phidget advanced servo handle
+ * @param fptr Callback function pointer.
+ * @param userPtr A pointer for use by the user - this value is passed back into the callback function.
+ */
+CHDREVENTINDEX(AdvancedServo,VelocityChange,double velocity)
+
+/**
+ * Gets the current position of a motor.
+ * @param phid An attached phidget advanced servo handle
+ * @param index The motor index.
+ * @param position The position.
+ */
+CHDRGETINDEX(AdvancedServo,Position,double *position)
+/**
+ * Sets the position of a motor.
+ * @param phid An attached phidget advanced servo handle
+ * @param index The motor index.
+ * @param position The position.
+ */
+CHDRSETINDEX(AdvancedServo,Position,double position)
+/**
+ * Gets the maximum position that a motor can go to.
+ * @param phid An attached phidget advanced servo handle
+ * @param index The motor index.
+ * @param max The maximum position.
+ */
+CHDRGETINDEX(AdvancedServo,PositionMax,double *max)
+/**
+ * Sets the maximum position that a motor can go to.
+ * @param phid An attached phidget advanced servo handle
+ * @param index The motor index.
+ * @param max The Maximum position.
+ */
+CHDRSETINDEX(AdvancedServo,PositionMax,double max)
+/**
+ * Gets the minimum position that a motor can go to.
+ * @param phid An attached phidget advanced servo handle
+ * @param index The motor index.
+ * @param min The minimum position
+ */
+CHDRGETINDEX(AdvancedServo,PositionMin,double *min)
+/**
+ * Sets the minimum position that a motor can go to.
+ * @param phid An attached phidget advanced servo handle
+ * @param index The motor index.
+ * @param min The minimum position
+ */
+CHDRSETINDEX(AdvancedServo,PositionMin,double min)
+/**
+ * Sets a position change event handler. This is called when the position changes.
+ * @param phid An attached phidget advanced servo handle
+ * @param fptr Callback function pointer.
+ * @param userPtr A pointer for use by the user - this value is passed back into the callback function.
+ */
+CHDREVENTINDEX(AdvancedServo,PositionChange,double position)
+
+/**
+ * Gets the current current draw for a motor.
+ * @param phid An attached phidget advanced servo handle
+ * @param index The motor index.
+ * @param current The current.
+ */
+CHDRGETINDEX(AdvancedServo,Current,double *current)
+/**
+ * Sets a current change event handler. This is called when the current draw changes.
+ * @param phid An attached phidget advanced servo handle
+ * @param fptr Callback function pointer.
+ * @param userPtr A pointer for use by the user - this value is passed back into the callback function.
+ */
+CHDREVENTINDEX(AdvancedServo,CurrentChange,double current)
+
+/**
+ * Gets the speed ramping state for a motor. This is whether or not velocity and acceleration are used.
+ * @param phid An attached phidget advanced servo handle
+ * @param index The motor index.
+ * @param rampingState The speed ramping state. Possible values are \ref PTRUE and \ref PFALSE.
+ */
+CHDRGETINDEX(AdvancedServo,SpeedRampingOn,int *rampingState)
+/**
+ * Sets the speed ramping state for a motor. This is whether or not velocity and acceleration are used.
+ * @param phid An attached phidget advanced servo handle
+ * @param index The motor index.
+ * @param rampingState The speed ramping state. Possible values are \ref PTRUE and \ref PFALSE.
+ */
+CHDRSETINDEX(AdvancedServo,SpeedRampingOn,int rampingState)
+/**
+ * Gets the engaged state of a motor. This is whether the motor is powered or not.
+ * @param phid An attached phidget advanced servo handle
+ * @param index The motor index.
+ * @param engagedState The engaged state. Possible values are \ref PTRUE and \ref PFALSE.
+ */
+CHDRGETINDEX(AdvancedServo,Engaged,int *engagedState)
+/**
+ * Sets the engaged state of a motor. This is whether the motor is powered or not.
+ * @param phid An attached phidget advanced servo handle
+ * @param index The motor index.
+ * @param engagedState The engaged state. Possible values are \ref PTRUE and \ref PFALSE.
+ */
+CHDRSETINDEX(AdvancedServo,Engaged,int engagedState)
+/**
+ * Gets the stopped state of a motor. This is true when the motor is not moving and there are no outstanding commands.
+ * @param phid An attached phidget advanced servo handle
+ * @param index The motor index.
+ * @param stoppedState The stopped state. Possible values are \ref PTRUE and \ref PFALSE.
+ */
+CHDRGETINDEX(AdvancedServo,Stopped,int *stoppedState)
+/**
+ * Gets the servo type of a motor.
+ * @param phid An attached phidget advanced servo handle
+ * @param index The motor index.
+ * @param servoType The servo type.
+ */
+CHDRGETINDEX(AdvancedServo,ServoType,CPhidget_ServoType *servoType)
+/**
+ * Sets the servo type of a motor.
+ * @param phid An attached phidget advanced servo handle
+ * @param index The motor index.
+ * @param servoType The servo type.
+ */
+CHDRSETINDEX(AdvancedServo,ServoType,CPhidget_ServoType servoType)
+/**
+ * Sets the servo parameters of a motor.
+ * @param phid An attached phidget advanced servo handle
+ * @param index The motor index.
+ * @param min_us The minimum supported PCM in microseconds.
+ * @param max_us The maximum supported PCM in microseconds.
+ * @param degrees The degrees of rotation defined by the given PCM range.
+ * @param velocity_max The maximum velocity in degrees/second.
+ */
+CHDRSETINDEX(AdvancedServo,ServoParameters,double min_us,double max_us,double degrees,double velocity_max)
+
+#ifndef EXTERNALPROTO
+#define ADVSERVO_MAXSERVOS 8
+
+#define ADVSERVO_NORMAL_PACKET 0x00
+#define ADVSERVO_MINMAX_PACKET 0x10
+
+//Flags - need to match those defined in firmware
+#define MOTOR_DONE_ADVSERVO 0x20
+#define MOTOR_DISABLED_ADVSERVO 0x40
+#define NO_RAMPING_FLAG_ADVSERVO 0x80
+
+#define ADVSERVO_PGOOD_FLAG 0x01
+
+//Define the parameters for several servo motors
+struct _CPhidgetServoParameters
+{
+ CPhidget_ServoType servoType;
+ double min_us;
+ double max_us;
+ double us_per_degree;
+ double max_us_per_s; //velocity in us notation
+ unsigned char state;
+} typedef CPhidgetServoParameters, *CPhidgetServoParametersHandle;
+
+extern const CPhidgetServoParameters Phid_Servo_Types[];
+int getServoParameterIndex(CPhidget_ServoType type);
+PHIDGET21_API double CCONV servo_us_to_degrees(CPhidgetServoParameters params, double us, unsigned char round);
+PHIDGET21_API double CCONV servo_degrees_to_us(CPhidgetServoParameters params, double degrees);
+PHIDGET21_API double CCONV servo_us_to_degrees_vel(CPhidgetServoParameters params, double us, unsigned char round);
+PHIDGET21_API double CCONV servo_degrees_to_us_vel(CPhidgetServoParameters params, double degrees);
+
+PHIDGET21_API int CCONV setupNewAdvancedServoParams(CPhidgetAdvancedServoHandle phid, int Index, CPhidgetServoParameters newVal);
+
+struct _CPhidgetAdvancedServo {
+ CPhidget phid;
+
+ int (CCONV *fptrPositionChange)(CPhidgetAdvancedServoHandle, void *, int, double);
+ int (CCONV *fptrVelocityChange)(CPhidgetAdvancedServoHandle, void *, int, double);
+ int (CCONV *fptrCurrentChange)(CPhidgetAdvancedServoHandle, void *, int, double);
+
+ void *fptrPositionChangeptr;
+ void *fptrVelocityChangeptr;
+ void *fptrCurrentChangeptr;
+
+ //all data is stored as microseconds
+
+ //data from the device
+ double motorVelocityEcho[ADVSERVO_MAXSERVOS];
+ double motorPositionEcho[ADVSERVO_MAXSERVOS];
+ double motorSensedCurrent[ADVSERVO_MAXSERVOS];
+ unsigned char motorSpeedRampingStateEcho[ADVSERVO_MAXSERVOS];
+ unsigned char motorEngagedStateEcho[ADVSERVO_MAXSERVOS];
+ unsigned char motorStoppedState[ADVSERVO_MAXSERVOS];
+ int packetCounterEcho[ADVSERVO_MAXSERVOS];
+
+ //data from the user
+ double motorPosition[ADVSERVO_MAXSERVOS];
+ double motorAcceleration[ADVSERVO_MAXSERVOS];
+ double motorVelocity[ADVSERVO_MAXSERVOS];
+ unsigned char motorSpeedRampingState[ADVSERVO_MAXSERVOS];
+ unsigned char motorEngagedState[ADVSERVO_MAXSERVOS];
+ int packetCounter[ADVSERVO_MAXSERVOS];
+ double motorPositionMax[ADVSERVO_MAXSERVOS];
+ double motorPositionMin[ADVSERVO_MAXSERVOS];
+
+ double velocityMax[ADVSERVO_MAXSERVOS], velocityMin;
+ double velocityMaxLimit;
+ double accelerationMax, accelerationMin;
+ double motorPositionMaxLimit, motorPositionMinLimit;
+
+ unsigned char PGoodErrState;
+
+ CPhidgetServoParameters servoParams[ADVSERVO_MAXSERVOS];
+ char *servoParamString[ADVSERVO_MAXSERVOS];
+
+ unsigned char outputPacket[8];
+ unsigned int outputPacketLen;
+} typedef CPhidgetAdvancedServoInfo;
+
+#endif
+
+/** @} */
+
+#endif
diff --git a/cphidgetanalog.c b/cphidgetanalog.c
new file mode 100644
index 0000000..d0defaa
--- /dev/null
+++ b/cphidgetanalog.c
@@ -0,0 +1,424 @@
+#include "stdafx.h"
+#include "cphidgetanalog.h"
+#include "cusb.h"
+#include "csocket.h"
+#include "cthread.h"
+
+// === Internal Functions === //
+
+//clearVars - sets all device variables to unknown state
+CPHIDGETCLEARVARS(Analog)
+ int i = 0;
+
+ for(i=0;i<ANALOG_MAXOUTPUTS;i++)
+ {
+ phid->changedVoltage[i] = PUNK_BOOL;
+ phid->nextVoltage[i] = PUNK_DBL;
+
+ phid->changedEnabled[i] = PUNK_BOOL;
+ phid->nextEnabled[i] = PUNK_BOOL;
+
+ phid->enabled[i] = PUNK_BOOL;
+ phid->voltage[i] = PUNK_DBL;
+
+ phid->voltageEcho[i] = PUNI_DBL;
+ phid->enabledEcho[i] = PUNI_BOOL;
+ }
+ phid->voltageMax = PUNI_DBL;
+ phid->voltageMin = PUNI_DBL;
+
+ return EPHIDGET_OK;
+}
+
+//initAfterOpen - sets up the initial state of an object, reading in packets from the device if needed
+// used during attach initialization - on every attach
+CPHIDGETINIT(Analog)
+ int i = 0;
+
+ TESTPTR(phid);
+
+ //set data arrays to unknown
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_ANALOG_4OUTPUT:
+ if ((phid->phid.deviceVersion >= 100) && (phid->phid.deviceVersion < 200))
+ {
+ for(i=0;i<phid->phid.attr.analog.numAnalogOutputs;i++)
+ {
+ phid->changedVoltage[i] = PFALSE;
+ phid->nextVoltage[i] = PUNK_DBL;
+
+ phid->changedEnabled[i] = PFALSE;
+ phid->nextEnabled[i] = PUNK_BOOL;
+
+ phid->enabled[i] = PUNK_BOOL;
+ phid->voltage[i] = PUNK_DBL;
+
+ phid->voltageEcho[i] = PUNK_DBL;
+ phid->enabledEcho[i] = PUNK_BOOL;
+
+ phid->lastOvercurrent[i] = PFALSE;
+ }
+ phid->voltageMax = 10;
+ phid->voltageMin = -10;
+
+ phid->lastTsd = PFALSE;
+ }
+ else
+ return EPHIDGET_BADVERSION;
+ break;
+ default:
+ return EPHIDGET_UNEXPECTED;
+ }
+ phid->controlPacketWaiting = PFALSE;
+
+ //issue a read - fill in data
+ CPhidget_read((CPhidgetHandle)phid);
+ for(i=0;i<phid->phid.attr.analog.numAnalogOutputs;i++)
+ {
+ phid->voltage[i] = phid->voltageEcho[i];
+ phid->enabled[i] = phid->enabledEcho[i];
+ }
+
+ return EPHIDGET_OK;
+}
+
+//dataInput - parses device packets
+CPHIDGETDATA(Analog)
+ int i = 0;
+ char error_buffer[128];
+ unsigned char overcurrent[ANALOG_MAXOUTPUTS] = {PFALSE};
+ unsigned char tsd = PFALSE;
+ int iVoltage;
+
+ if (length < 0) return EPHIDGET_INVALIDARG;
+ TESTPTR(phid);
+ TESTPTR(buffer);
+
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_ANALOG_4OUTPUT:
+ if ((phid->phid.deviceVersion >= 100) && (phid->phid.deviceVersion < 200))
+ {
+ // Bit--> | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
+ //Byte 0 | oc[3] | oc[2] | oc[1] | oc[0] | en[3] | en[2] | en[1] | en[0] |
+ //Byte 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | TSD |
+ //Byte 2 | voltage[0] bits 3-0 | 0 | 0 | 0 | 0 |
+ //Byte 3 | voltage[0] bits 11-4 |
+ //Byte 4 | voltage[1] bits 3-0 | 0 | 0 | 0 | 0 |
+ //Byte 5 | voltage[1] bits 11-4 |
+ //Byte 6 | voltage[2] bits 3-0 | 0 | 0 | 0 | 0 |
+ //Byte 7 | voltage[2] bits 11-4 |
+ //Byte 8 | voltage[3] bits 3-0 | 0 | 0 | 0 | 0 |
+ //Byte 9 | voltage[3] bits 11-4 |
+ for (i = 0; i < phid->phid.attr.analog.numAnalogOutputs; i++)
+ {
+ iVoltage = (((signed char)buffer[i*2 + 3]) << 4) + (buffer[i*2 + 2] >> 4);
+ phid->voltageEcho[i] = round_double((iVoltage * 10 / 2047.0), 3);
+ phid->enabledEcho[i] = (buffer[0] & (0x01 << i)) ? PTRUE : PFALSE;
+ overcurrent[i] = (buffer[0] & (0x10 << i)) ? PTRUE : PFALSE;
+ }
+ tsd = buffer[1];
+ }
+ else
+ return EPHIDGET_UNEXPECTED;
+ break;
+ default:
+ return EPHIDGET_UNEXPECTED;
+ }
+
+ for (i = 0; i < phid->phid.attr.analog.numAnalogOutputs; i++)
+ {
+ if(overcurrent[i] && !phid->lastOvercurrent[i])
+ {
+ FIRE_ERROR(EEPHIDGET_OVERCURRENT, "Output %d is trying to draw > 20mA - possible short circuit.", i);
+ }
+ else if(!overcurrent[i] && phid->lastOvercurrent[i])
+ {
+ FIRE_ERROR(EEPHIDGET_OK, "Output %d overcurrent state ended.", i);
+ }
+ phid->lastOvercurrent[i] = overcurrent[i];
+ }
+ if(tsd && !phid->lastTsd)
+ {
+ FIRE_ERROR(EEPHIDGET_OVERTEMP, "Thermal shutdown detected. All outputs have been disabled.");
+ }
+ else if(!tsd && phid->lastTsd)
+ {
+ FIRE_ERROR(EEPHIDGET_OK, "Thermal shutdown state ended.");
+ }
+ phid->lastTsd = tsd;
+
+ return EPHIDGET_OK;
+}
+
+//eventsAfterOpen - sends out an event for all valid data, used during attach initialization - not used
+CPHIDGETINITEVENTS(Analog)
+ phid = 0;
+ return EPHIDGET_OK;
+}
+
+//getPacket - used by write thread to get the next packet to send to device
+CGETPACKET(Analog)
+ int i = 0;
+ int iVoltage;
+
+ CPhidgetAnalogHandle phid = (CPhidgetAnalogHandle)phidG;
+
+ TESTPTRS(phid, buf)
+ TESTPTR(lenp)
+
+ if (*lenp < phid->phid.outputReportByteLength)
+ return EPHIDGET_INVALIDARG;
+
+ CThread_mutex_lock(&phid->phid.outputLock);
+
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_ANALOG_4OUTPUT:
+ if ((phid->phid.deviceVersion >= 100) && (phid->phid.deviceVersion < 200))
+ {
+ // Bit--> | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
+ //Byte 0 | voltage[0] bits 3-0 | en[3] | en[2] | en[1] | en[0] |
+ //Byte 1 | voltage[0] bits 11-4 |
+ //Byte 2 | voltage[1] bits 3-0 | 0 | 0 | 0 | 0 |
+ //Byte 3 | voltage[1] bits 11-4 |
+ //Byte 4 | voltage[2] bits 3-0 | 0 | 0 | 0 | 0 |
+ //Byte 5 | voltage[2] bits 11-4 |
+ //Byte 6 | voltage[3] bits 3-0 | 0 | 0 | 0 | 0 |
+ //Byte 7 | voltage[3] bits 11-4 |
+ for (i = 0; i < phid->phid.attr.analog.numAnalogOutputs; i++)
+ {
+ if (phid->changedVoltage[i]) {
+ phid->voltage[i] = phid->nextVoltage[i];
+ phid->changedVoltage[i] = PFALSE;
+ phid->nextVoltage[i] = PUNK_DBL;
+ }
+ if (phid->changedEnabled[i]) {
+ phid->enabled[i] = phid->nextEnabled[i];
+ phid->changedEnabled[i] = PFALSE;
+ phid->nextEnabled[i] = PUNK_BOOL;
+ }
+ //fill in buffer
+ iVoltage = round(phid->voltage[i] * 2047 / 10.0);
+ buf[i*2] = iVoltage << 4;
+ buf[i*2 + 1] = iVoltage >> 4;
+ if(phid->enabled[i])
+ buf[0] |= 1<<i;
+ }
+ }
+ else
+ return EPHIDGET_UNEXPECTED;
+ break;
+ default:
+ return EPHIDGET_UNEXPECTED;
+ }
+
+ *lenp = phid->phid.outputReportByteLength;
+
+ CThread_mutex_unlock(&phid->phid.outputLock);
+
+ return EPHIDGET_OK;
+}
+
+//sends a packet to the device asynchronously, blocking if the 1-packet queue is full
+// -every channel has its own 1 state mini-queue
+static int CCONV CPhidgetAnalog_sendPacket_setVoltage(CPhidgetAnalogHandle phid, unsigned int index, double voltage)
+{
+ int waitReturn;
+ CThread_mutex_lock(&phid->phid.writelock);
+again:
+ if (!CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_ATTACHED_FLAG))
+ {
+ CThread_mutex_unlock(&phid->phid.writelock);
+ return EPHIDGET_NOTATTACHED;
+ }
+ CThread_mutex_lock(&phid->phid.outputLock);
+ //if we have already requested a change on this channel
+ if (phid->changedVoltage[index]) {
+ //and it was different then this time
+ if (phid->nextVoltage[index] != voltage) {
+ CThread_mutex_unlock(&phid->phid.outputLock);
+ //then wait for it to get written
+ waitReturn = CThread_wait_on_event(&phid->phid.writtenEvent, 2500);
+ switch(waitReturn)
+ {
+ case WAIT_OBJECT_0:
+ break;
+ case WAIT_ABANDONED:
+ CThread_mutex_unlock(&phid->phid.writelock);
+ return EPHIDGET_UNEXPECTED;
+ case WAIT_TIMEOUT:
+ CThread_mutex_unlock(&phid->phid.writelock);
+ return EPHIDGET_TIMEOUT;
+ }
+ //and try again
+ goto again;
+ } else {
+ CThread_mutex_unlock(&phid->phid.outputLock);
+ CThread_mutex_unlock(&phid->phid.writelock);
+ return EPHIDGET_OK;
+ }
+ //otherwise
+ } else {
+ //if it's different then current, queue it up
+ if (phid->voltage[index] != voltage) {
+ phid->changedVoltage[index] = PTRUE;
+ phid->nextVoltage[index] = voltage;
+ CThread_reset_event(&phid->phid.writtenEvent);
+ CThread_mutex_unlock(&phid->phid.outputLock);
+ CThread_set_event(&phid->phid.writeAvailableEvent);
+ }
+ //if it's the same, just return
+ else
+ {
+ CThread_mutex_unlock(&phid->phid.outputLock);
+ CThread_mutex_unlock(&phid->phid.writelock);
+ return EPHIDGET_OK;
+ }
+ }
+ CThread_mutex_unlock(&phid->phid.writelock);
+ return EPHIDGET_OK;
+}
+
+//sends a packet to the device asynchronously, blocking if the 1-packet queue is full
+// -every channel has its own 1 state mini-queue
+static int CCONV CPhidgetAnalog_sendPacket_setEnabled(CPhidgetAnalogHandle phid, unsigned int index, int enabled)
+{
+ int waitReturn;
+ CThread_mutex_lock(&phid->phid.writelock);
+again:
+ if (!CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_ATTACHED_FLAG))
+ {
+ CThread_mutex_unlock(&phid->phid.writelock);
+ return EPHIDGET_NOTATTACHED;
+ }
+ CThread_mutex_lock(&phid->phid.outputLock);
+ //if we have already requested a change on this channel
+ if (phid->changedEnabled[index]) {
+ //and it was different then this time
+ if (phid->nextEnabled[index] != enabled) {
+ CThread_mutex_unlock(&phid->phid.outputLock);
+ //then wait for it to get written
+ waitReturn = CThread_wait_on_event(&phid->phid.writtenEvent, 2500);
+ switch(waitReturn)
+ {
+ case WAIT_OBJECT_0:
+ break;
+ case WAIT_ABANDONED:
+ CThread_mutex_unlock(&phid->phid.writelock);
+ return EPHIDGET_UNEXPECTED;
+ case WAIT_TIMEOUT:
+ CThread_mutex_unlock(&phid->phid.writelock);
+ return EPHIDGET_TIMEOUT;
+ }
+ //and try again
+ goto again;
+ } else {
+ CThread_mutex_unlock(&phid->phid.outputLock);
+ CThread_mutex_unlock(&phid->phid.writelock);
+ return EPHIDGET_OK;
+ }
+ //otherwise
+ } else {
+ //if it's different then current, queue it up
+ if (phid->enabled[index] != enabled) {
+ phid->changedEnabled[index] = PTRUE;
+ phid->nextEnabled[index] = enabled;
+ CThread_reset_event(&phid->phid.writtenEvent);
+ CThread_mutex_unlock(&phid->phid.outputLock);
+ CThread_set_event(&phid->phid.writeAvailableEvent);
+ }
+ //if it's the same, just return
+ else
+ {
+ CThread_mutex_unlock(&phid->phid.outputLock);
+ CThread_mutex_unlock(&phid->phid.writelock);
+ return EPHIDGET_OK;
+ }
+ }
+ CThread_mutex_unlock(&phid->phid.writelock);
+ return EPHIDGET_OK;
+}
+
+// === Exported Functions === //
+
+//create and initialize a device structure
+CCREATE(Analog, PHIDCLASS_ANALOG)
+
+CGET(Analog,OutputCount,int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_ANALOG)
+ TESTATTACHED
+
+ MASGN(phid.attr.analog.numAnalogOutputs)
+}
+
+CGETINDEX(Analog,Voltage,double)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_ANALOG)
+ TESTATTACHED
+ TESTINDEX(phid.attr.analog.numAnalogOutputs)
+ TESTMASGN(voltageEcho[Index], PUNK_DBL)
+
+ MASGN(voltageEcho[Index])
+}
+
+CSETINDEX(Analog,Voltage,double)
+ TESTPTR(phid)
+ TESTDEVICETYPE(PHIDCLASS_ANALOG)
+ TESTATTACHED
+ TESTRANGE(phid->voltageMin, phid->voltageMax)
+ TESTINDEX(phid.attr.analog.numAnalogOutputs)
+
+ if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
+ ADDNETWORKKEYINDEXED(Voltage, "%lf", voltage);
+ else
+ return CPhidgetAnalog_sendPacket_setVoltage(phid, Index, newVal);
+
+ return EPHIDGET_OK;
+}
+
+CGETINDEX(Analog,VoltageMax,double)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_ANALOG)
+ TESTATTACHED
+ TESTINDEX(phid.attr.analog.numAnalogOutputs)
+ TESTMASGN(voltageMax, PUNK_DBL)
+
+ MASGN(voltageMax)
+}
+
+CGETINDEX(Analog,VoltageMin,double)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_ANALOG)
+ TESTATTACHED
+ TESTINDEX(phid.attr.analog.numAnalogOutputs)
+ TESTMASGN(voltageMin, PUNK_DBL)
+
+ MASGN(voltageMin)
+}
+
+CGETINDEX(Analog,Enabled,int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_ANALOG)
+ TESTATTACHED
+ TESTINDEX(phid.attr.analog.numAnalogOutputs)
+ TESTMASGN(enabledEcho[Index], PUNK_BOOL)
+
+ MASGN(enabledEcho[Index])
+}
+CSETINDEX(Analog,Enabled,int)
+ TESTPTR(phid)
+ TESTDEVICETYPE(PHIDCLASS_ANALOG)
+ TESTATTACHED
+ TESTRANGE(PFALSE, PTRUE)
+ TESTINDEX(phid.attr.analog.numAnalogOutputs)
+
+ if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
+ ADDNETWORKKEYINDEXED(Enabled, "%d", enabled);
+ else
+ return CPhidgetAnalog_sendPacket_setEnabled(phid, Index, newVal);
+
+ return EPHIDGET_OK;
+}
diff --git a/cphidgetanalog.h b/cphidgetanalog.h
new file mode 100644
index 0000000..84e259f
--- /dev/null
+++ b/cphidgetanalog.h
@@ -0,0 +1,97 @@
+#ifndef __CPHIDGETANALOG
+#define __CPHIDGETANALOG
+#include "cphidget.h"
+
+/** \defgroup phidanalog Phidget Analog
+ * \ingroup phidgets
+ * Calls specific to the Phidget Analog. See the product manual for more specific API details, supported functionality, units, etc.
+ * @{
+ */
+
+DPHANDLE(Analog)
+CHDRSTANDARD(Analog)
+
+/**
+ * Gets the number of outputs supported by this phidget analog.
+ * @param phid An attached phidget analog handle.
+ * @param count The axis count.
+ */
+CHDRGET(Analog,OutputCount,int *count)
+/**
+ * Gets the currently set voltage for an output, in V.
+ * @param phid An attached phidget analog handle.
+ * @param index The output index.
+ * @param voltage The voltage.
+ */
+CHDRGETINDEX(Analog,Voltage,double *voltage)
+/**
+ * Sets the voltage of an output, in V.
+ * @param phid An attached phidget analog handle.
+ * @param index The otuput index.
+ * @param voltage The output voltage.
+ */
+CHDRSETINDEX(Analog,Voltage,double voltage)
+/**
+ * Gets the maximum settable output voltage, in V.
+ * @param phid An attached phidget analog handle.
+ * @param index The output index.
+ * @param max The max voltage.
+ */
+CHDRGETINDEX(Analog,VoltageMax,double *max)
+/**
+ * Gets the minimum settable output voltage, in V.
+ * @param phid An attached phidget analog handle.
+ * @param index The output index.
+ * @param min The min voltage.
+ */
+CHDRGETINDEX(Analog,VoltageMin,double *min)
+/**
+ * Sets the enabled state for an output.
+ * @param phid An attached phidget analog handle.
+ * @param index The output index.
+ * @param enabledState The enabled state. Possible values are \ref PTRUE and \ref PFALSE.
+ */
+CHDRSETINDEX(Analog,Enabled,int enabledState)
+/**
+ * Gets the enabled state for an output.
+ * @param phid An attached phidget analog handle.
+ * @param index The output index.
+ * @param enabledState The enabled state. Possible values are \ref PTRUE and \ref PFALSE.
+ */
+CHDRGETINDEX(Analog,Enabled,int *enabledState)
+
+#ifndef EXTERNALPROTO
+
+#define ANALOG_MAXOUTPUTS 4
+
+struct _CPhidgetAnalog
+{
+ CPhidget phid;
+
+ double voltage[ANALOG_MAXOUTPUTS];
+ unsigned char enabled[ANALOG_MAXOUTPUTS];
+
+ double voltageEcho[ANALOG_MAXOUTPUTS];
+ unsigned char enabledEcho[ANALOG_MAXOUTPUTS];
+
+ double voltageMax, voltageMin;
+
+ double nextVoltage[ANALOG_MAXOUTPUTS];
+ double lastVoltage[ANALOG_MAXOUTPUTS];
+ unsigned char changedVoltage[ANALOG_MAXOUTPUTS];
+
+ unsigned char nextEnabled[ANALOG_MAXOUTPUTS];
+ unsigned char lastEnabled[ANALOG_MAXOUTPUTS];
+ unsigned char changedEnabled[ANALOG_MAXOUTPUTS];
+
+ unsigned char lastOvercurrent[ANALOG_MAXOUTPUTS];
+ unsigned char lastTsd;
+
+ unsigned char controlPacketWaiting;
+ unsigned char lastOutputPacket;
+} typedef CPhidgetAnalogInfo;
+
+#endif
+
+/** @} */
+#endif
diff --git a/cphidgetattr.h b/cphidgetattr.h
new file mode 100644
index 0000000..c1b33f6
--- /dev/null
+++ b/cphidgetattr.h
@@ -0,0 +1,261 @@
+#ifndef __CPHIDGETATTR
+#define __CPHIDGETATTR
+
+#ifndef EXTERNALPROTO
+typedef struct {
+ int numAxis;
+} CPhidgetAccelerometerAttr;
+
+typedef struct {
+ int numMotors;
+} CPhidgetAdvancedServoAttr;
+
+typedef struct {
+ int numEncoders;
+ int numInputs;
+} CPhidgetEncoderAttr;
+
+typedef struct {
+ int dummy;
+} CPhidgetGPSAttr;
+
+typedef struct {
+ int numSensors;
+ int numInputs;
+ int numOutputs;
+} CPhidgetInterfaceKitAttr;
+
+typedef struct {
+ int numLEDs;
+} CPhidgetLEDAttr;
+
+typedef struct {
+ int numMotors;
+ int numInputs;
+ int numEncoders;
+ int numSensors;
+} CPhidgetMotorControlAttr;
+
+typedef struct {
+ int dummy;
+} CPhidgetPHSensorAttr;
+
+typedef struct {
+ int numOutputs;
+} CPhidgetRFIDAttr;
+
+typedef struct {
+ int numMotors;
+} CPhidgetServoAttr;
+
+typedef struct {
+ int numMotors;
+ int numInputs;
+} CPhidgetStepperAttr;
+
+typedef struct {
+ int numTempInputs;
+} CPhidgetTemperatureSensorAttr;
+
+typedef struct {
+ int numRows;
+ int numColumns;
+ int numScreens;
+} CPhidgetTextLCDAttr;
+
+typedef struct {
+ int numRows;
+ int numColumns;
+} CPhidgetTextLEDAttr;
+
+typedef struct {
+ int dummy;
+} CPhidgetWeightSensorAttr;
+
+typedef struct {
+ int dummy;
+} CPhidgetIRAttr;
+
+typedef struct {
+ int numAccelAxes;
+ int numGyroAxes;
+ int numCompassAxes;
+} CPhidgetSpatialAttr;
+
+typedef struct {
+ int numFreqInputs;
+} CPhidgetFrequencyCounterAttr;
+
+typedef struct {
+ int numAnalogOutputs;
+} CPhidgetAnalogAttr;
+
+typedef struct {
+ int numBridgeInputs;
+} CPhidgetBridgeAttr;
+
+typedef struct {
+ int dummy1;
+ int dummy2;
+ int dummy3;
+ int dummy4;
+} CPhidgetDummyAttr;
+
+typedef union {
+ CPhidgetDummyAttr dummy; /* field for unnamed initializers */
+ CPhidgetAccelerometerAttr accelerometer;
+ CPhidgetAdvancedServoAttr advancedservo;
+ CPhidgetAnalogAttr analog;
+ CPhidgetBridgeAttr bridge;
+ CPhidgetEncoderAttr encoder;
+ CPhidgetFrequencyCounterAttr frequencycounter;
+ CPhidgetGPSAttr gps;
+ CPhidgetInterfaceKitAttr ifkit;
+ CPhidgetIRAttr ir;
+ CPhidgetLEDAttr led;
+ CPhidgetMotorControlAttr motorcontrol;
+ CPhidgetPHSensorAttr phsensor;
+ CPhidgetRFIDAttr rfid;
+ CPhidgetServoAttr servo;
+ CPhidgetSpatialAttr spatial;
+ CPhidgetStepperAttr stepper;
+ CPhidgetTemperatureSensorAttr temperaturesensor;
+ CPhidgetTextLCDAttr textlcd;
+ CPhidgetTextLEDAttr textled;
+ CPhidgetWeightSensorAttr weightsensor;
+} CPhidgetAttr;
+#endif
+
+/** \addtogroup phidconst
+ * @{
+ */
+#ifndef EXTERNALPROTO
+/* Device Class - valid class numbers start at 2, 1 is used for a 'NOTHING' device */
+/* If we change the order of this list, or add to it:
+ * -increment webservice protocol version (don't bother for prototypes)
+ * -change name list in cphidgetconstants.c
+ * -update .NET, Flash, COM, Java, Python, etc.
+ * -update function pointer lists in csocketevents.c (phidget21) and eventhandlers.c (webservice)
+ * -update PHIDGET_DEVICE_CLASS_COUNT
+ * -should not change the values of the enums
+ */
+#endif
+/**
+ * Phidget device class uniquely identifies a class of Phidgets.
+ */
+typedef enum {
+ PHIDCLASS_ACCELEROMETER = 2, /**< Phidget Accelerometer */
+ PHIDCLASS_ADVANCEDSERVO = 3, /**< Phidget Advanced Servo */
+ PHIDCLASS_ANALOG = 22, /**< Phidget Analog */
+ PHIDCLASS_BRIDGE = 23, /**< Phidget Bridge */
+ PHIDCLASS_ENCODER = 4, /**< Phidget Encoder */
+ PHIDCLASS_FREQUENCYCOUNTER = 21, /**< Phidget Frequency Counter */
+ PHIDCLASS_GPS = 5, /**< Phidget GPS */
+ PHIDCLASS_INTERFACEKIT = 7, /**< Phidget Interface Kit */
+ PHIDCLASS_IR = 19, /**< Phidget IR */
+ PHIDCLASS_LED = 8, /**< Phidget LED */
+ PHIDCLASS_MOTORCONTROL = 9, /**< Phidget Motor Control */
+ PHIDCLASS_PHSENSOR = 10, /**< Phidget PH Sensor */
+ PHIDCLASS_RFID = 11, /**< Phidget RFID */
+ PHIDCLASS_SERVO = 12, /**< Phidget Servo */
+ PHIDCLASS_SPATIAL = 20, /**< Phidget Spatial */
+ PHIDCLASS_STEPPER = 13, /**< Phidget Stepper */
+ PHIDCLASS_TEMPERATURESENSOR = 14, /**< Phidget Temperature Sensor */
+ PHIDCLASS_TEXTLCD = 15, /**< Phidget TextLCD */
+ PHIDCLASS_TEXTLED = 16, /**< Phidget TextLED */
+ PHIDCLASS_WEIGHTSENSOR = 17, /**< Phidget Weight Sensor */
+#if defined(DEBUG) || !defined(EXTERNALPROTO)
+ PHIDCLASS_NOTHING = 1, /**< Nothing */
+ PHIDCLASS_GENERIC = 18 /**< Phidget Generic */
+#endif
+} CPhidget_DeviceClass;
+
+#ifndef EXTERNALPROTO
+/* Device ID - valid id numbers start at 2, 1 is used for a 'NOTHING' device
+ * This list can be re-ordered, as long as the values are not changed - we order the list alphabetically
+ * Device IDs are the 1-digit interface number following by 2-digit USB PID, in hex.
+ * except for some special cases (very old phidgets)
+ */
+/* If we add or remove from this list:
+ * -increment webservice protocol version (don't bother for prototypes)
+ * -update Phid_Device_Def list
+ * -update Flash, .NET, Java, Python?
+ * -update PHIDGET_DEVICE_COUNT
+ */
+#endif
+/**
+ * Phidget device id uniquely identifies a specific type of Phidget.
+ */
+typedef enum {
+
+ /* These are all current devices */
+ PHIDID_ACCELEROMETER_3AXIS = 0x07E, /**< Phidget 3-axis Accelerometer (1059) */
+ PHIDID_ADVANCEDSERVO_1MOTOR = 0x082, /**< Phidget 1 Motor Advanced Servo (1066) */
+ PHIDID_ADVANCEDSERVO_8MOTOR = 0x03A, /**< Phidget 8 Motor Advanced Servo (1061) */
+ PHIDID_ANALOG_4OUTPUT = 0x037, /**< Phidget Analog 4-output (1002) */
+ PHIDID_BIPOLAR_STEPPER_1MOTOR = 0x07B, /**< Phidget 1 Motor Bipolar Stepper Controller with 4 Digital Inputs (1063) */
+ PHIDID_BRIDGE_4INPUT = 0x03B, /**< Phidget Bridge 4-input (1046) */
+ PHIDID_ENCODER_1ENCODER_1INPUT = 0x04B, /**< Phidget Encoder - Mechanical (1052) */
+ PHIDID_ENCODER_HS_1ENCODER = 0x080, /**< Phidget High Speed Encoder (1057) */
+ PHIDID_ENCODER_HS_4ENCODER_4INPUT = 0x04F, /**< Phidget High Speed Encoder - 4 Encoder (1047) */
+ PHIDID_FREQUENCYCOUNTER_2INPUT = 0x035, /**< Phidget Frequency Counter 2-input (1054) */
+ PHIDID_GPS = 0x079, /**< Phidget GPS (1040) */
+ PHIDID_INTERFACEKIT_0_0_4 = 0x040, /**< Phidget Interface Kit 0/0/4 (1014) */
+ PHIDID_INTERFACEKIT_0_0_8 = 0x081, /**< Phidget Interface Kit 0/0/8 (1017) */
+ PHIDID_INTERFACEKIT_0_16_16 = 0x044, /**< Phidget Interface Kit 0/16/16 (1012) */
+ PHIDID_INTERFACEKIT_2_2_2 = 0x036, /**< Phidget Interface Kit 2/2/2 (1011) */
+ PHIDID_INTERFACEKIT_8_8_8 = 0x045, /**< Phidget Interface Kit 8/8/8 (1013, 1018, 1019) */
+ PHIDID_INTERFACEKIT_8_8_8_w_LCD = 0x07D, /**< Phidget Interface Kit 8/8/8 with TextLCD (1201, 1202, 1203) */
+ PHIDID_IR = 0x04D, /**< Phidget IR Receiver Transmitter (1055) */
+ PHIDID_LED_64_ADV = 0x04C, /**< Phidget LED 64 Advanced (1031) */
+ PHIDID_LINEAR_TOUCH = 0x076, /**< Phidget Linear Touch (1015) */
+ PHIDID_MOTORCONTROL_1MOTOR = 0x03E, /**< Phidget 1 Motor Motor Controller (1065) */
+ PHIDID_MOTORCONTROL_HC_2MOTOR = 0x059, /**< Phidget 2 Motor High Current Motor Controller (1064) */
+ PHIDID_RFID_2OUTPUT = 0x031, /**< Phidget RFID with Digital Outputs and Onboard LED (1023) */
+ PHIDID_ROTARY_TOUCH = 0x077, /**< Phidget Rotary Touch (1016) */
+ PHIDID_SPATIAL_ACCEL_3AXIS = 0x07F, /**< Phidget Spatial 3-axis accel (1049, 1041, 1043) */
+ PHIDID_SPATIAL_ACCEL_GYRO_COMPASS = 0x033, /**< Phidget Spatial 3/3/3 (1056, 1042, 1044) */
+ PHIDID_TEMPERATURESENSOR = 0x070, /**< Phidget Temperature Sensor (1051) */
+ PHIDID_TEMPERATURESENSOR_4 = 0x032, /**< Phidget Temperature Sensor 4-input (1048) */
+ PHIDID_TEMPERATURESENSOR_IR = 0x03C, /**< Phidget Temperature Sensor IR (1045) */
+ PHIDID_TEXTLCD_2x20_w_8_8_8 = 0x17D, /**< Phidget TextLCD with Interface Kit 8/8/8 (1201, 1202, 1203) */
+ PHIDID_TEXTLCD_ADAPTER = 0x03D, /**< Phidget TextLCD Adapter (1204) */
+ PHIDID_UNIPOLAR_STEPPER_4MOTOR = 0x07A, /**< Phidget 4 Motor Unipolar Stepper Controller (1062) */
+
+ /* These are all past devices (no longer sold) */
+ PHIDID_ACCELEROMETER_2AXIS = 0x071, /**< Phidget 2-axis Accelerometer (1053, 1054) */
+ PHIDID_INTERFACEKIT_0_8_8_w_LCD = 0x053, /**< Phidget Interface Kit 0/8/8 with TextLCD (1219, 1220, 1221) */
+ PHIDID_INTERFACEKIT_4_8_8 = 4, /**< Phidget Interface Kit 4/8/8 */
+ PHIDID_LED_64 = 0x04A, /**< Phidget LED 64 (1030) */
+ PHIDID_MOTORCONTROL_LV_2MOTOR_4INPUT = 0x058, /**< Phidget 2 Motor Low Voltage Motor Controller with 4 Digital Inputs (1060) */
+ PHIDID_PHSENSOR = 0x074, /**< Phidget PH Sensor (1058) */
+ PHIDID_RFID = 0x030, /**< Phidget RFID without Digital Outputs */
+ PHIDID_SERVO_1MOTOR = 0x039, /**< Phidget 1 Motor Servo Controller (1000) */
+ PHIDID_SERVO_1MOTOR_OLD = 2, /**< Phidget 1 Motor Servo Controller - Old Version */
+ PHIDID_SERVO_4MOTOR = 0x038, /**< Phidget 4 Motor Servo Controller (1001) */
+ PHIDID_SERVO_4MOTOR_OLD = 3, /**< Phidget 4 Motor Servo Controller - Old Version */
+ PHIDID_TEXTLCD_2x20 = 0x052, /**< Phidget TextLCD without Interface Kit (1210) */
+ PHIDID_TEXTLCD_2x20_w_0_8_8 = 0x153, /**< Phidget TextLCD with Interface Kit 0/8/8 (1219, 1220, 1221) */
+ PHIDID_TEXTLED_1x8 = 0x049, /**< Phidget TextLED 1x8 */
+ PHIDID_TEXTLED_4x8 = 0x048, /**< Phidget TextLED 4x8 (1040) */
+ PHIDID_WEIGHTSENSOR = 0x072, /**< Phidget Weight Sensor (1050) */
+
+#if defined(DEBUG) || !defined(EXTERNALPROTO)
+ /* Nothing device */
+ PHIDID_NOTHING = 1,
+
+ /* never released to general public */
+ PHIDID_INTERFACEKIT_0_5_7 = 0x051,
+ PHIDID_TEXTLCD_2x20_CUSTOM = 0x151,
+ PHIDID_INTERFACEKIT_2_8_8 = 5, /**< Phidget Interface Kit 2/8/8 */
+
+ /* These are unreleased or prototype devices */
+ PHIDID_RFID_2OUTPUT_ADVANCED = 0x034, /**< Phidget RFID with R/W support (1024) */
+
+ /* This is for internal prototyping */
+ PHIDID_GENERIC = 0x099
+#endif
+} CPhidget_DeviceID;
+/** @} */
+#endif
+
diff --git a/cphidgetbridge.c b/cphidgetbridge.c
new file mode 100644
index 0000000..fe3211d
--- /dev/null
+++ b/cphidgetbridge.c
@@ -0,0 +1,446 @@
+#include <string.h>
+#include <assert.h>
+#include "stdafx.h"
+#include "cphidgetbridge.h"
+#include "cusb.h"
+#include "csocket.h"
+#include "cthread.h"
+
+// === Internal Functions === //
+
+//clearVars - sets all device variables to unknown state
+CPHIDGETCLEARVARS(Bridge)
+ int i = 0;
+
+ for (i = 0; i<BRIDGE_MAXINPUTS; i++)
+ {
+ phid->bridgeMin[i] = PUNI_DBL;
+ phid->bridgeMax[i] = PUNI_DBL;
+ phid->enabledEcho[i] = PUNI_BOOL;
+ phid->gainEcho[i] = PHIDGET_BRIDGE_GAIN_UNKNOWN;
+ phid->bridgeValue[i] = PUNI_DBL;
+
+ phid->enabled[i] = PUNK_BOOL;
+ phid->gain[i] = PHIDGET_BRIDGE_GAIN_UNKNOWN;
+ }
+ phid->dataRateEcho = PUNI_INT;
+ phid->dataRateMin = PUNI_INT;
+ phid->dataRateMax = PUNI_INT;
+
+ return EPHIDGET_OK;
+}
+
+//initAfterOpen - sets up the initial state of an object, reading in packets from the device if needed
+// used during attach initialization - on every attach
+CPHIDGETINIT(Bridge)
+ int i;
+ TESTPTR(phid);
+
+ //Make sure no old writes are still pending
+ phid->outputPacketLen = 0;
+
+ //Setup max/min values
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_BRIDGE_4INPUT:
+ if ((phid->phid.deviceVersion >= 100) && (phid->phid.deviceVersion < 200))
+ {
+ phid->dataRateMin = 1000;
+ phid->dataRateMax = 8;
+ }
+ else
+ return EPHIDGET_BADVERSION;
+ break;
+ default:
+ return EPHIDGET_UNEXPECTED;
+ }
+
+ for (i = 0; i<phid->phid.attr.bridge.numBridgeInputs; i++)
+ {
+ phid->bridgeMin[i] = PUNK_DBL;
+ phid->bridgeMax[i] = PUNK_DBL;
+ phid->bridgeValue[i] = PUNK_DBL;
+ phid->enabledEcho[i] = PUNK_BOOL;
+ phid->gainEcho[i] = PHIDGET_BRIDGE_GAIN_UNKNOWN;
+ phid->outOfRange[i] = PFALSE;
+ phid->lastOutOfRange[i] = PFALSE;
+ }
+ phid->dataRateEcho = PUNK_INT;
+
+ //read in initial state - read until it returns 0
+ while(CPhidget_read((CPhidgetHandle)phid)) SLEEP(8);
+
+ //recover what we can, set others to unknown
+ for (i = 0; i<phid->phid.attr.bridge.numBridgeInputs; i++)
+ {
+ phid->enabled[i] = phid->enabledEcho[i];
+ phid->gain[i] = phid->gainEcho[i];
+ }
+ phid->dataRate = phid->dataRateEcho;
+
+ return EPHIDGET_OK;
+}
+
+//dataInput - parses device packets
+CPHIDGETDATA(Bridge)
+ int i = 0;
+ int bridgeRawVal;
+ double bridgeVal;
+ int dataRateRaw;
+ double gain;
+ int roundingFactor = 0;
+ unsigned char err = PFALSE;
+ char error_buffer[200];
+ double bridgeval[BRIDGE_MAXINPUTS];
+
+ if (length < 0) return EPHIDGET_INVALIDARG;
+ TESTPTR(phid);
+ TESTPTR(buffer);
+
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_BRIDGE_4INPUT:
+ if ((phid->phid.deviceVersion >= 100) && (phid->phid.deviceVersion < 200))
+ {
+ //Output Data Rate (Hz) = dataRateRaw * 8
+ dataRateRaw = ((buffer[4] & 0x03) << 8) + buffer[5];
+ //in ms
+ phid->dataRateEcho = dataRateRaw * 8;
+
+ for (i = 0; i<phid->phid.attr.bridge.numBridgeInputs; i++)
+ {
+ //gain
+ switch(buffer[(i/2)+2] >> (i%2?0:4) & 0x0F)
+ {
+ case 0x00:
+ phid->gainEcho[i] = PHIDGET_BRIDGE_GAIN_1;
+ gain = 1;
+ roundingFactor = 5;
+ break;
+ case 0x03:
+ phid->gainEcho[i] = PHIDGET_BRIDGE_GAIN_8;
+ gain = 8;
+ roundingFactor = 6;
+ break;
+ case 0x04:
+ phid->gainEcho[i] = PHIDGET_BRIDGE_GAIN_16;
+ gain = 16;
+ roundingFactor = 7;
+ break;
+ case 0x05:
+ phid->gainEcho[i] = PHIDGET_BRIDGE_GAIN_32;
+ gain = 32;
+ roundingFactor = 7;
+ break;
+ case 0x06:
+ phid->gainEcho[i] = PHIDGET_BRIDGE_GAIN_64;
+ gain = 64;
+ roundingFactor = 7;
+ break;
+ case 0x07:
+ phid->gainEcho[i] = PHIDGET_BRIDGE_GAIN_128;
+ gain = 128;
+ roundingFactor = 8;
+ break;
+ }
+
+ if(gain == 1)
+ {
+ phid->bridgeMax[i] = 1000;
+ phid->bridgeMin[i] = -1000;
+ }
+ else
+ {
+ //with PGA, allow +-99.5%, because if doesn't clamp properly
+ phid->bridgeMax[i] = 995/gain;
+ phid->bridgeMin[i] = -995/gain;
+ }
+
+ phid->enabledEcho[i] = (buffer[0] & (0x01 << i)) ? PTRUE : PFALSE;
+ if(phid->enabledEcho[i] && (buffer[0] & (0x10 << i))) //enabled and have data
+ {
+ bridgeRawVal = (buffer[i*3 + 6] << 16) + (buffer[i*3 + 7] << 8) + buffer[i*3 + 8];
+ bridgeVal = round_double(((bridgeRawVal - 0x800000) / (double)0x800000) * 1000.0 / (double)gain, roundingFactor);
+
+ err = (buffer[1] & (0x01 << i)) ? PTRUE : PFALSE;
+
+ if(err || bridgeVal > phid->bridgeMax[i] || bridgeVal < phid->bridgeMin[i])
+ {
+ bridgeval[i] = PUNK_DBL;
+
+ if(!phid->lastOutOfRange[i])
+ {
+ if(bridgeVal > phid->bridgeMax[i])
+ {
+ FIRE_ERROR(EEPHIDGET_OUTOFRANGE, "Overrange condition detected on input %d, try lowering the gain.",i);
+ }
+ else if(bridgeVal < phid->bridgeMin[i])
+ {
+ FIRE_ERROR(EEPHIDGET_OUTOFRANGE, "Underrange condition detected on input %d, try lowering the gain.",i);
+ }
+ }
+ phid->lastOutOfRange[i] = PTRUE;
+ }
+ else
+ {
+ if(phid->lastOutOfRange[i])
+ {
+ FIRE_ERROR(EEPHIDGET_OUTOFRANGE, "Input %d out of range state ended.", i);
+ }
+ phid->lastOutOfRange[i] = PFALSE;
+
+ bridgeval[i] = bridgeVal;
+ }
+ }
+ else if(!phid->enabledEcho[i])
+ {
+ bridgeval[i] = PUNK_DBL;
+ }
+ else
+ bridgeval[i] = PUNI_DBL;
+ }
+ }
+ else
+ return EPHIDGET_UNEXPECTED;
+ break;
+ default:
+ return EPHIDGET_UNEXPECTED;
+ }
+
+ for (i = 0; i<phid->phid.attr.bridge.numBridgeInputs; i++)
+ {
+ if (bridgeval[i] != PUNI_DBL)
+ {
+ phid->bridgeValue[i] = bridgeval[i];
+ }
+ }
+
+ //Send out events
+ for (i = 0; i<phid->phid.attr.bridge.numBridgeInputs; i++)
+ {
+ if (bridgeval[i] != PUNI_DBL &&phid->bridgeValue[i] != PUNK_DBL)
+ {
+ FIRE(BridgeData, i, phid->bridgeValue[i]);
+ }
+ }
+
+ return EPHIDGET_OK;
+}
+
+//eventsAfterOpen - sends out an event for all valid data, used during attach initialization
+CPHIDGETINITEVENTS(Bridge)
+
+ for (i = 0; i<phid->phid.attr.bridge.numBridgeInputs; i++)
+ {
+ if (phid->bridgeValue[i] != PUNK_DBL)
+ {
+ FIRE(BridgeData, i, phid->bridgeValue[i]);
+ }
+ }
+
+ return EPHIDGET_OK;
+}
+
+//getPacket - used by write thread to get the next packet to send to device
+CGETPACKET_BUF(Bridge)
+
+//sendpacket - sends a packet to the device asynchronously, blocking if the 1-packet queue is full
+CSENDPACKET_BUF(Bridge)
+
+//makePacket - constructs a packet using current device state
+CMAKEPACKET(Bridge)
+ TESTPTRS(phid, buffer);
+
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_BRIDGE_4INPUT:
+ if ((phid->phid.deviceVersion >= 100) && (phid->phid.deviceVersion < 200))
+ {
+ int i;
+ int dataRateRaw;
+ int gainRaw;
+
+ //ms->raw
+ dataRateRaw = phid->dataRate / 8;
+
+ buffer[0] = 0;
+ buffer[1] = 0;
+ buffer[2] = 0;
+ for (i = 0; i<phid->phid.attr.bridge.numBridgeInputs; i++)
+ {
+ if(phid->enabled[i])
+ buffer[0] |= (0x01<<i);
+
+ switch(phid->gain[i])
+ {
+ case PHIDGET_BRIDGE_GAIN_1:
+ case PHIDGET_BRIDGE_GAIN_UNKNOWN:
+ gainRaw = 0x00;
+ break;
+ case PHIDGET_BRIDGE_GAIN_8:
+ gainRaw = 0x03;
+ break;
+ case PHIDGET_BRIDGE_GAIN_16:
+ gainRaw = 0x04;
+ break;
+ case PHIDGET_BRIDGE_GAIN_32:
+ gainRaw = 0x05;
+ break;
+ case PHIDGET_BRIDGE_GAIN_64:
+ gainRaw = 0x06;
+ break;
+ case PHIDGET_BRIDGE_GAIN_128:
+ gainRaw = 0x07;
+ break;
+ }
+ buffer[(i/2)+1] |= gainRaw << (i%2?0:4);
+ }
+ buffer[3] = dataRateRaw & 0xFF;
+ buffer[4] = (dataRateRaw >> 8) & 0x03;
+
+ }
+ else
+ return EPHIDGET_UNEXPECTED;
+ break;
+ default:
+ return EPHIDGET_UNEXPECTED;
+ }
+
+ return EPHIDGET_OK;
+}
+
+// === Exported Functions === //
+
+//create and initialize a device structure
+CCREATE(Bridge, PHIDCLASS_BRIDGE)
+
+//event setup functions
+CFHANDLE(Bridge, BridgeData, int, double)
+
+CGET(Bridge,InputCount,int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_BRIDGE)
+ TESTATTACHED
+
+ MASGN(phid.attr.bridge.numBridgeInputs)
+}
+
+CGETINDEX(Bridge,BridgeValue,double)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_BRIDGE)
+ TESTATTACHED
+ TESTINDEX(phid.attr.bridge.numBridgeInputs)
+ TESTMASGN(bridgeValue[Index], PUNK_DBL)
+
+ MASGN(bridgeValue[Index])
+}
+
+CGETINDEX(Bridge,BridgeMax,double)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_BRIDGE)
+ TESTATTACHED
+ TESTINDEX(phid.attr.bridge.numBridgeInputs)
+ TESTMASGN(bridgeMax[Index], PUNK_DBL)
+
+ MASGN(bridgeMax[Index])
+}
+
+CGETINDEX(Bridge,BridgeMin,double)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_BRIDGE)
+ TESTATTACHED
+ TESTINDEX(phid.attr.bridge.numBridgeInputs)
+ TESTMASGN(bridgeMin[Index], PUNK_DBL)
+
+ MASGN(bridgeMin[Index])
+}
+
+CGETINDEX(Bridge,Enabled,int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_BRIDGE)
+ TESTATTACHED
+ TESTINDEX(phid.attr.bridge.numBridgeInputs)
+ TESTMASGN(enabledEcho[Index], PUNK_BOOL)
+
+ MASGN(enabledEcho[Index])
+}
+CSETINDEX(Bridge,Enabled,int)
+ TESTPTR(phid)
+ TESTDEVICETYPE(PHIDCLASS_BRIDGE)
+ TESTATTACHED
+ TESTRANGE(PFALSE, PTRUE)
+ TESTINDEX(phid.attr.bridge.numBridgeInputs)
+
+ if(newVal == PFALSE) phid->bridgeValue[Index] = PUNK_DBL;
+
+ if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
+ ADDNETWORKKEYINDEXED(Enabled, "%d", enabled);
+ else
+ SENDPACKET(Bridge, enabled[Index]);
+
+ return EPHIDGET_OK;
+}
+
+CGETINDEX(Bridge,Gain,CPhidgetBridge_Gain)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_BRIDGE)
+ TESTATTACHED
+ TESTINDEX(phid.attr.bridge.numBridgeInputs)
+ TESTMASGN(gainEcho[Index], PHIDGET_BRIDGE_GAIN_UNKNOWN)
+
+ MASGN(gainEcho[Index])
+}
+CSETINDEX(Bridge,Gain,CPhidgetBridge_Gain)
+ TESTPTR(phid)
+ TESTDEVICETYPE(PHIDCLASS_BRIDGE)
+ TESTATTACHED
+ TESTRANGE(PHIDGET_BRIDGE_GAIN_1, PHIDGET_BRIDGE_GAIN_128)
+ TESTINDEX(phid.attr.bridge.numBridgeInputs)
+
+ if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
+ ADDNETWORKKEYINDEXED(Gain, "%d", gain);
+ else
+ SENDPACKET(Bridge, gain[Index]);
+
+ return EPHIDGET_OK;
+}
+
+CSET(Bridge,DataRate,int)
+ TESTPTR(phid)
+ TESTDEVICETYPE(PHIDCLASS_BRIDGE)
+ TESTATTACHED
+ TESTRANGE(phid->dataRateMax, phid->dataRateMin)
+
+ if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
+ ADDNETWORKKEY(DataRate, "%d", dataRate);
+ else
+ SENDPACKET(Bridge, dataRate);
+
+ return EPHIDGET_OK;
+}
+CGET(Bridge,DataRate,int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_BRIDGE)
+ TESTATTACHED
+ TESTMASGN(dataRateEcho, PUNK_INT)
+
+ MASGN(dataRateEcho)
+}
+
+CGET(Bridge,DataRateMax,int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_BRIDGE)
+ TESTATTACHED
+ TESTMASGN(dataRateMax, PUNK_INT)
+
+ MASGN(dataRateMax)
+}
+
+CGET(Bridge,DataRateMin,int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_BRIDGE)
+ TESTATTACHED
+ TESTMASGN(dataRateMin, PUNK_INT)
+
+ MASGN(dataRateMin)
+}
diff --git a/cphidgetbridge.h b/cphidgetbridge.h
new file mode 100644
index 0000000..596ac61
--- /dev/null
+++ b/cphidgetbridge.h
@@ -0,0 +1,145 @@
+#ifndef __CPHIDGETBRIDGE
+#define __CPHIDGETBRIDGE
+#include "cphidget.h"
+
+/** \defgroup phidbridge Phidget Bridge
+ * \ingroup phidgets
+ * Calls specific to the Phidget Bridge. See the product manual for more specific API details, supported functionality, units, etc.
+ * @{
+ */
+
+/**
+ * List of gains supported by the PhidgetBridge.
+ */
+typedef enum {
+ PHIDGET_BRIDGE_GAIN_1 = 1, /**< Gain of 1. */
+ PHIDGET_BRIDGE_GAIN_8, /**< Gain of 8. */
+ PHIDGET_BRIDGE_GAIN_16, /**< Gain of 16. */
+ PHIDGET_BRIDGE_GAIN_32, /**< Gain of 32. */
+ PHIDGET_BRIDGE_GAIN_64, /**< Gain of 64. */
+ PHIDGET_BRIDGE_GAIN_128, /**< Gain of 128. */
+ PHIDGET_BRIDGE_GAIN_UNKNOWN /**< Unknown Gain. */
+} CPhidgetBridge_Gain;
+
+DPHANDLE(Bridge)
+CHDRSTANDARD(Bridge)
+
+/**
+ * Gets the number of inputs supported by this phidget bridge.
+ * @param phid An attached phidget bridge handle.
+ * @param count The input count.
+ */
+CHDRGET(Bridge,InputCount,int *count)
+/**
+ * Gets the current value of a bridge input, in mV/V.
+ * @param phid An attached phidget bridge handle.
+ * @param index The input index.
+ * @param value The value.
+ */
+CHDRGETINDEX(Bridge,BridgeValue,double *value)
+/**
+ * Gets the maximum value supported by a bridge input, in mV/V. This is affected by Gain.
+ * @param phid An attached phidget bridge handle.
+ * @param index The input index.
+ * @param max The max value.
+ */
+CHDRGETINDEX(Bridge,BridgeMax,double *max)
+/**
+ * Gets the minimum value supported by a bridge input, in mV/V. This is affected by Gain.
+ * @param phid An attached phidget bridge handle.
+ * @param index The input index.
+ * @param min The min value.
+ */
+CHDRGETINDEX(Bridge,BridgeMin,double *min)
+/**
+ * Gets the enabled state for an input.
+ * @param phid An attached phidget bridge handle.
+ * @param index The input index.
+ * @param enabledState The enabled state.
+ */
+CHDRSETINDEX(Bridge,Enabled,int enabledState)
+/**
+ * Sets the enabled state for an input.
+ * @param phid An attached phidget bridge handle.
+ * @param index The input index.
+ * @param enabledState The enabled state.
+ */
+CHDRGETINDEX(Bridge,Enabled,int *enabledState)
+/**
+ * Gets the the Gain for an input.
+ * @param phid An attached phidget bridge handle.
+ * @param index The input index.
+ * @param gain The gain.
+ */
+CHDRGETINDEX(Bridge,Gain, CPhidgetBridge_Gain *gain)
+/**
+ * Sets the the Gain for an input.
+ * @param phid An attached phidget bridge handle.
+ * @param index The input index.
+ * @param gain The gain.
+ */
+CHDRSETINDEX(Bridge,Gain, CPhidgetBridge_Gain gain)
+/**
+ * Gets the the data rate for the Phidget Bridge, in milliseconds.
+ * @param phid An attached phidget bridge handle.
+ * @param milliseconds The data rate.
+ */
+CHDRGET(Bridge,DataRate, int *milliseconds)
+/**
+ * Sets the the data rate for the Phidget Bridge, in milliseconds.
+ * @param phid An attached phidget bridge handle.
+ * @param milliseconds The data rate.
+ */
+CHDRSET(Bridge,DataRate, int milliseconds)
+/**
+ * Gets the the maximum data rate for the Phidget Bridge, in milliseconds.
+ * @param phid An attached phidget bridge handle.
+ * @param max The max data rate.
+ */
+CHDRGET(Bridge,DataRateMax, int *max)
+/**
+ * Gets the the minimum data rate for the Phidget Bridge, in milliseconds.
+ * @param phid An attached phidget bridge handle.
+ * @param min The min data rate.
+ */
+CHDRGET(Bridge,DataRateMin, int *min)
+/**
+ * Sets a bridge data event handler. This is called at a set rate as defined by data rate.
+ * @param phid A phidget bridge handle.
+ * @param fptr Callback function pointer.
+ * @param userPtr A pointer for use by the user - this value is passed back into the callback function.
+ */
+CHDREVENTINDEX(Bridge,BridgeData,double value)
+
+#ifndef EXTERNALPROTO
+#define BRIDGE_MAXINPUTS 4
+struct _CPhidgetBridge {
+ CPhidget phid;
+ int (CCONV *fptrBridgeData)(CPhidgetBridgeHandle, void *, int, double);
+ void *fptrBridgeDataptr;
+
+ unsigned char enabled[BRIDGE_MAXINPUTS];
+ CPhidgetBridge_Gain gain[BRIDGE_MAXINPUTS];
+ int dataRate;
+
+ double bridgeValue[BRIDGE_MAXINPUTS];
+ unsigned char enabledEcho[BRIDGE_MAXINPUTS];
+ CPhidgetBridge_Gain gainEcho[BRIDGE_MAXINPUTS];
+ int dataRateEcho;
+
+ int dataRateMin, dataRateMax;
+ double bridgeMin[BRIDGE_MAXINPUTS], bridgeMax[BRIDGE_MAXINPUTS];
+
+ unsigned char outOfRange[BRIDGE_MAXINPUTS], lastOutOfRange[BRIDGE_MAXINPUTS];
+
+ //for PWS
+ double lastBridgeMin[BRIDGE_MAXINPUTS], lastBridgeMax[BRIDGE_MAXINPUTS];
+
+ unsigned char outputPacket[8];
+ unsigned int outputPacketLen;
+} typedef CPhidgetBridgeInfo;
+#endif
+
+/** @} */
+
+#endif
diff --git a/cphidgetconstants.c b/cphidgetconstants.c
new file mode 100644
index 0000000..95b36e9
--- /dev/null
+++ b/cphidgetconstants.c
@@ -0,0 +1,153 @@
+#include "stdafx.h"
+#include "cphidgetconstantsinternal.h"
+#include "cphidgetconstants.h"
+
+const char *Phid_ErrorDescriptions[PHIDGET_ERROR_CODE_COUNT] = {
+"Function completed successfully.",
+"A Phidget matching the type and or serial number could not be found.",
+"Memory could not be allocated.",
+"Unexpected Error. Contact Phidgets Inc. for support.",
+"Invalid argument passed to function.",
+"Phidget not physically attached.",
+"Read/Write operation was interrupted.",
+"The Error Code is not defined.",
+"Network Error.",
+"Value is Unknown (State not yet received from device, or not yet set by user).",
+"Authorization Failed.",
+"Not Supported.",
+"Duplicated request.",
+"Given timeout has been exceeded.",
+"Index out of Bounds.",
+"A non-null error code was returned from an event handler.",
+"A connection to the server does not exist.",
+"Function is not applicable for this device.",
+"Phidget handle was closed.",
+"Webservice and Client protocol versions don't match. Update both to newest release."};
+
+const char Phid_UnknownErrorDescription[] = "Unknown Error Code.";
+
+/* enum starts a 1 so we need a blank for 0
+ * Don't reorder this list */
+const char *Phid_DeviceName[PHIDGET_DEVICE_CLASS_COUNT] = {
+"ERROR",
+"Uninitialized Phidget Handle",
+"PhidgetAccelerometer",
+"PhidgetAdvancedServo",
+"PhidgetEncoder",
+"PhidgetGPS",
+"ERROR", //Old Gyro
+"PhidgetInterfaceKit",
+"PhidgetLED",
+"PhidgetMotorControl",
+"PhidgetPHSensor",
+"PhidgetRFID",
+"PhidgetServo",
+"PhidgetStepper",
+"PhidgetTemperatureSensor",
+"PhidgetTextLCD",
+"PhidgetTextLED",
+"PhidgetWeightSensor",
+"PhidgetGeneric",
+"PhidgetIR",
+"PhidgetSpatial",
+"PhidgetFrequencyCounter",
+"PhidgetAnalog",
+"PhidgetBridge"};
+
+#ifdef DEBUG
+const char LibraryVersion[] = "Phidget21 Debug - Version 2.1.8 - Built " __DATE__
+ " " __TIME__;
+#else
+const char LibraryVersion[] = "Phidget21 - Version 2.1.8 - Built " __DATE__
+ " " __TIME__;
+#endif
+
+#ifndef _MSC_EXTENSIONS
+#define UFINTS(name, initializer...) .name = { initializer }
+#else
+#define UFINTS(name, ...) { __VA_ARGS__ }
+#endif
+
+#define UNUSED_DEVICE(pid) PHIDCLASS_NOTHING, 0x6C2, pid, 0, { UFINTS(dummy, 0, 0, 0) }, ""
+
+// We own Product IDs 0x30 - 0xAF (48-175)
+// This needs to start with the device id = 1 invalid device and end in NULL
+// This list could be re-ordered, but we leave it in product-id order.
+const CPhidgetDeviceDef Phid_Device_Def[PHIDGET_DEVICE_COUNT+1] = {
+{ PHIDID_NOTHING, PHIDCLASS_NOTHING, 0x000, 0x00, 0, { UFINTS(dummy, 0, 0, 0 ) }, "Uninitialized Phidget Handle"}, //1 start for list logic
+
+/* Very old devices - we don't own these product IDs so don't allocate anymore!! We maintain support for these devices */
+{ PHIDID_SERVO_1MOTOR_OLD, PHIDCLASS_SERVO, 0x925, 0x8101, 0, { UFINTS(servo, 1 ) }, "Phidget Servo Controller 1-motor"}, //Original 1000
+{ PHIDID_SERVO_4MOTOR_OLD, PHIDCLASS_SERVO, 0x925, 0x8104, 0, { UFINTS(servo, 4 ) }, "Phidget Servo Controller 4-motor"}, //Original 1001
+{ PHIDID_INTERFACEKIT_2_8_8, PHIDCLASS_INTERFACEKIT, 0x925, 0x8200, 0, { UFINTS(ifkit, 2, 8, 8 ) }, "Phidget InterfaceKit 2/8/8"}, //ORIGINAL Original Ifkit
+{ PHIDID_INTERFACEKIT_4_8_8, PHIDCLASS_INTERFACEKIT, 0x925, 0x8201, 0, { UFINTS(ifkit, 4, 8, 8 ) }, "Phidget InterfaceKit 4/8/8"}, //Original Ifkit
+
+//Pid 0x8500 (Vid 0x925): PhidgetPower
+
+/* Valid product IDs */
+{ PHIDID_RFID, PHIDCLASS_RFID, 0x6C2, 0x30, 0, { UFINTS(rfid, 0 ) }, "Phidget RFID"},
+{ PHIDID_RFID_2OUTPUT, PHIDCLASS_RFID, 0x6C2, 0x31, 0, { UFINTS(rfid, 2 ) }, "Phidget RFID 2-output"},
+{ PHIDID_TEMPERATURESENSOR_4, PHIDCLASS_TEMPERATURESENSOR,0x6C2, 0x32, 0, { UFINTS(temperaturesensor, 4 ) }, "Phidget Temperature Sensor 4-input"},
+{ PHIDID_SPATIAL_ACCEL_GYRO_COMPASS, PHIDCLASS_SPATIAL, 0x6C2, 0x33, 0, { UFINTS(spatial, 3, 3, 3 ) }, "Phidget Spatial 3/3/3"},
+{ PHIDID_RFID_2OUTPUT_ADVANCED, PHIDCLASS_RFID, 0x6C2, 0x34, 0, { UFINTS(rfid, 2 ) }, "Phidget RFID 2-output Advanced"},
+{ PHIDID_FREQUENCYCOUNTER_2INPUT, PHIDCLASS_FREQUENCYCOUNTER, 0x6C2, 0x35, 0, { UFINTS(frequencycounter, 2 ) }, "Phidget Frequency Counter 2-input"},
+{ PHIDID_INTERFACEKIT_2_2_2, PHIDCLASS_INTERFACEKIT, 0x6C2, 0x36, 0, { UFINTS(ifkit, 2, 2, 2 ) }, "Phidget InterfaceKit 2/2/2"},
+{ PHIDID_ANALOG_4OUTPUT, PHIDCLASS_ANALOG, 0x6C2, 0x37, 0, { UFINTS(analog, 4 ) }, "Phidget Analog 4-output"},
+{ PHIDID_SERVO_4MOTOR, PHIDCLASS_SERVO, 0x6C2, 0x38, 0, { UFINTS(servo, 4 ) }, "Phidget Servo Controller 4-motor"},
+{ PHIDID_SERVO_1MOTOR, PHIDCLASS_SERVO, 0x6C2, 0x39, 0, { UFINTS(servo, 1 ) }, "Phidget Servo Controller 1-motor"},
+{ PHIDID_ADVANCEDSERVO_8MOTOR, PHIDCLASS_ADVANCEDSERVO, 0x6C2, 0x3A, 0, { UFINTS(advancedservo, 8 ) }, "Phidget Advanced Servo Controller 8-motor"},
+{ PHIDID_BRIDGE_4INPUT, PHIDCLASS_BRIDGE, 0x6C2, 0x3B, 0, { UFINTS(bridge, 4 ) }, "Phidget Bridge 4-input"},
+{ PHIDID_TEMPERATURESENSOR_IR, PHIDCLASS_TEMPERATURESENSOR,0x6C2, 0x3C, 0, { UFINTS(temperaturesensor, 1 ) }, "Phidget Temperature Sensor IR"},
+{ PHIDID_TEXTLCD_ADAPTER, PHIDCLASS_TEXTLCD, 0x6C2, 0x3D, 0, { UFINTS(textlcd, 0, 0, 2 ) }, "Phidget TextLCD Adapter"},
+{ PHIDID_MOTORCONTROL_1MOTOR, PHIDCLASS_MOTORCONTROL, 0x6C2, 0x3E, 0, { UFINTS(motorcontrol, 1, 2, 1, 2) }, "Phidget Motor Controller 1-motor"},
+
+{ PHIDID_INTERFACEKIT_0_0_4, PHIDCLASS_INTERFACEKIT, 0x6C2, 0x40, 0, { UFINTS(ifkit, 0, 0, 4 ) }, "Phidget InterfaceKit 0/0/4"},
+
+{ PHIDID_INTERFACEKIT_0_16_16, PHIDCLASS_INTERFACEKIT, 0x6C2, 0x44, 0, { UFINTS(ifkit, 0, 16, 16 ) }, "Phidget InterfaceKit 0/16/16"},
+{ PHIDID_INTERFACEKIT_8_8_8, PHIDCLASS_INTERFACEKIT, 0x6C2, 0x45, 0, { UFINTS(ifkit, 8, 8, 8 ) }, "Phidget InterfaceKit 8/8/8"},
+
+{ PHIDID_TEXTLED_4x8, PHIDCLASS_TEXTLED, 0x6C2, 0x48, 0, { UFINTS(textled, 4, 8 ) }, "Phidget TextLED 4x8"},
+{ PHIDID_TEXTLED_1x8, PHIDCLASS_TEXTLED, 0x6C2, 0x49, 0, { UFINTS(textled, 1, 8 ) }, "Phidget TextLED 1x8"},
+{ PHIDID_LED_64, PHIDCLASS_LED, 0x6C2, 0x4A, 0, { UFINTS(led, 64 ) }, "Phidget LED 64"},
+{ PHIDID_ENCODER_1ENCODER_1INPUT, PHIDCLASS_ENCODER, 0x6C2, 0x4B, 0, { UFINTS(encoder, 1, 1 ) }, "Phidget Encoder 1-encoder 1-input"},
+{ PHIDID_LED_64_ADV, PHIDCLASS_LED, 0x6C2, 0x4C, 0, { UFINTS(led, 64 ) }, "Phidget LED 64 Advanced"},
+{ PHIDID_IR, PHIDCLASS_IR, 0x6C2, 0x4D, 0, { UFINTS(ir, 0 ) }, "Phidget IR Receiver Transmitter"},
+
+{ PHIDID_ENCODER_HS_4ENCODER_4INPUT, PHIDCLASS_ENCODER, 0x6C2, 0x4F, 0, { UFINTS(encoder, 4, 4 ) }, "Phidget High Speed Encoder 4-input"},
+
+{ PHIDID_INTERFACEKIT_0_5_7, PHIDCLASS_INTERFACEKIT, 0x6C2, 0x51, 0, { UFINTS(ifkit, 0, 5, 7 ) }, "Phidget InterfaceKit 0/5/7"}, //with TextLCD - Spain
+{ PHIDID_TEXTLCD_2x20_CUSTOM, PHIDCLASS_TEXTLCD, 0x6C2, 0x51, 0, { UFINTS(textlcd, 2, 20, 1 ) }, "Phidget TextLCD Custom"}, //with 0/5/7 - Spain
+{ PHIDID_TEXTLCD_2x20, PHIDCLASS_TEXTLCD, 0x6C2, 0x52, 0, { UFINTS(textlcd, 2, 20, 1 ) }, "Phidget TextLCD"}, //no ifkit part
+{ PHIDID_INTERFACEKIT_0_8_8_w_LCD, PHIDCLASS_INTERFACEKIT, 0x6C2, 0x53, 0, { UFINTS(ifkit, 0, 8, 8 ) }, "Phidget InterfaceKit 0/8/8"}, //with TextLCD
+{ PHIDID_TEXTLCD_2x20_w_0_8_8, PHIDCLASS_TEXTLCD, 0x6C2, 0x53, 0, { UFINTS(textlcd, 2, 20, 1 ) }, "Phidget TextLCD"}, //with 0/8/8
+
+{ PHIDID_MOTORCONTROL_LV_2MOTOR_4INPUT, PHIDCLASS_MOTORCONTROL, 0x6C2, 0x58, 0, { UFINTS(motorcontrol, 2, 4, 0, 0) }, "Phidget Low Voltage Motor Controller 2-motor 4-input"},
+{ PHIDID_MOTORCONTROL_HC_2MOTOR, PHIDCLASS_MOTORCONTROL, 0x6C2, 0x59, 0, { UFINTS(motorcontrol, 2, 0, 0, 0) }, "Phidget High Current Motor Controller 2-motor"},
+
+//Pid 0x60: PhidgetInterfaceKit 0/32/32
+
+{ PHIDID_TEMPERATURESENSOR, PHIDCLASS_TEMPERATURESENSOR,0x6C2, 0x70, 0, { UFINTS(temperaturesensor, 1 ) }, "Phidget Temperature Sensor"},
+{ PHIDID_ACCELEROMETER_2AXIS, PHIDCLASS_ACCELEROMETER, 0x6C2, 0x71, 0, { UFINTS(accelerometer, 2 ) }, "Phidget Accelerometer 2-axis"},
+{ PHIDID_WEIGHTSENSOR, PHIDCLASS_WEIGHTSENSOR, 0x6C2, 0x72, 0, { UFINTS(weightsensor, 0 ) }, "Phidget Weight Sensor"},
+
+{ PHIDID_PHSENSOR, PHIDCLASS_PHSENSOR, 0x6C2, 0x74, 0, { UFINTS(phsensor, 0 ) }, "Phidget PH Sensor"},
+
+{ PHIDID_LINEAR_TOUCH, PHIDCLASS_INTERFACEKIT, 0x6C2, 0x76, 0, { UFINTS(ifkit, 1, 2 ) }, "Phidget Touch Slider"},
+{ PHIDID_ROTARY_TOUCH, PHIDCLASS_INTERFACEKIT, 0x6C2, 0x77, 0, { UFINTS(ifkit, 1, 2 ) }, "Phidget Touch Rotation"},
+
+{ PHIDID_GPS, PHIDCLASS_GPS, 0x6C2, 0x79, 0, { UFINTS(gps, 1 ) }, "Phidget GPS"},
+{ PHIDID_UNIPOLAR_STEPPER_4MOTOR, PHIDCLASS_STEPPER, 0x6C2, 0x7A, 0, { UFINTS(stepper, 4 ) }, "Phidget Unipolar Stepper Controller 4-motor"},
+{ PHIDID_BIPOLAR_STEPPER_1MOTOR, PHIDCLASS_STEPPER, 0x6C2, 0x7B, 0, { UFINTS(stepper, 1, 4 ) }, "Phidget Bipolar Stepper Controller 1-motor"},
+
+{ PHIDID_INTERFACEKIT_8_8_8_w_LCD, PHIDCLASS_INTERFACEKIT, 0x6C2, 0x7D, 0, { UFINTS(ifkit, 8, 8, 8 ) }, "Phidget InterfaceKit 8/8/8"}, //with TextLCD
+{ PHIDID_TEXTLCD_2x20_w_8_8_8, PHIDCLASS_TEXTLCD, 0x6C2, 0x7D, 1, { UFINTS(textlcd, 2, 20, 1 ) }, "Phidget TextLCD"}, //with 8/8/8
+{ PHIDID_ACCELEROMETER_3AXIS, PHIDCLASS_ACCELEROMETER, 0x6C2, 0x7E, 0, { UFINTS(accelerometer, 3 ) }, "Phidget Accelerometer 3-axis"},
+{ PHIDID_SPATIAL_ACCEL_3AXIS, PHIDCLASS_SPATIAL, 0x6C2, 0x7F, 0, { UFINTS(spatial, 3, 0, 0 ) }, "Phidget Spatial 0/0/3"},
+{ PHIDID_ENCODER_HS_1ENCODER, PHIDCLASS_ENCODER, 0x6C2, 0x80, 0, { UFINTS(encoder, 1 ) }, "Phidget High Speed Encoder 1-encoder"},
+{ PHIDID_INTERFACEKIT_0_0_8, PHIDCLASS_INTERFACEKIT, 0x6C2, 0x81, 0, { UFINTS(ifkit, 0, 0, 8 ) }, "Phidget InterfaceKit 0/0/8"},
+{ PHIDID_ADVANCEDSERVO_1MOTOR, PHIDCLASS_ADVANCEDSERVO, 0x6C2, 0x82, 0, { UFINTS(advancedservo, 1 ) }, "Phidget Advanced Servo Controller 1-motor"},
+
+{ PHIDID_GENERIC, PHIDCLASS_GENERIC, 0x6C2, 0x99, 0, { UFINTS(dummy, 0, 0, 0 ) }, "Phidget Generic Device"}, //generic device - used for prototyping
+
+{ 0 } //ending null
+};
diff --git a/cphidgetconstants.h b/cphidgetconstants.h
new file mode 100644
index 0000000..8383c19
--- /dev/null
+++ b/cphidgetconstants.h
@@ -0,0 +1,88 @@
+#ifndef CPHIDGET_CONSTANTS
+#define CPHIDGET_CONSTANTS
+
+/** \defgroup phidconst Phidget Constants
+ * Various constants used throughout the library.
+ * @{
+ */
+
+/** \name Phidget States
+ * Returned by getStatus() functions
+ * @{
+ */
+#define PHIDGET_ATTACHED 0x1 /**< Phidget attached */
+#define PHIDGET_NOTATTACHED 0x0 /**< Phidget not attached */
+/** @} */
+
+//Adding error codes: Update .NET, COM, Python, Java
+/** \name Phidget Error Codes
+ * Returned by all C API calls
+ * @{
+ */
+#define PHIDGET_ERROR_CODE_COUNT 20
+#define EPHIDGET_OK 0 /**< Function completed successfully. */
+#define EPHIDGET_NOTFOUND 1 /**< Phidget not found. "A Phidget matching the type and or serial number could not be found." */
+#define EPHIDGET_NOMEMORY 2 /**< No memory. "Memory could not be allocated." */
+#define EPHIDGET_UNEXPECTED 3 /**< Unexpected. "Unexpected Error. Contact Phidgets Inc. for support." */
+#define EPHIDGET_INVALIDARG 4 /**< Invalid argument. "Invalid argument passed to function." */
+#define EPHIDGET_NOTATTACHED 5 /**< Phidget not attached. "Phidget not physically attached." */
+#define EPHIDGET_INTERRUPTED 6 /**< Interrupted. "Read/Write operation was interrupted." This code is not currently used. */
+#define EPHIDGET_INVALID 7 /**< Invalid error code. "The Error Code is not defined." */
+#define EPHIDGET_NETWORK 8 /**< Network. "Network Error." */
+#define EPHIDGET_UNKNOWNVAL 9 /**< Value unknown. "Value is Unknown (State not yet received from device, or not yet set by user)." */
+#define EPHIDGET_BADPASSWORD 10 /**< Authorization exception. "No longer used. Replaced by EEPHIDGET_BADPASSWORD" */
+#define EPHIDGET_UNSUPPORTED 11 /**< Unsupported. "Not Supported." */
+#define EPHIDGET_DUPLICATE 12 /**< Duplicate request. "Duplicated request." */
+#define EPHIDGET_TIMEOUT 13 /**< Timeout. "Given timeout has been exceeded." */
+#define EPHIDGET_OUTOFBOUNDS 14 /**< Out of bounds. "Index out of Bounds." */
+#define EPHIDGET_EVENT 15 /**< Event. "A non-null error code was returned from an event handler." This code is not currently used. */
+#define EPHIDGET_NETWORK_NOTCONNECTED 16 /**< Network not connected. "A connection to the server does not exist." */
+#define EPHIDGET_WRONGDEVICE 17 /**< Wrong device. "Function is not applicable for this device." */
+#define EPHIDGET_CLOSED 18 /**< Phidget Closed. "Phidget handle was closed." */
+#define EPHIDGET_BADVERSION 19 /**< Version Mismatch. "No longer used. Replaced by EEPHIDGET_BADVERSION" */
+/** @} */
+
+//Adding error codes: Update .NET, COM, Python, Java
+/** \name Phidget Error Event Codes
+ * Returned in the Phidget error event
+ * @{
+ */
+#define EEPHIDGET_EVENT_ERROR(code) (0x8000 + code)
+
+
+//Library errors
+#define EEPHIDGET_NETWORK EEPHIDGET_EVENT_ERROR(0x0001) /**< Network Error (asynchronous). */
+#define EEPHIDGET_BADPASSWORD EEPHIDGET_EVENT_ERROR(0x0002) /**< Authorization Failed. */
+#define EEPHIDGET_BADVERSION EEPHIDGET_EVENT_ERROR(0x0003) /**< Webservice and Client protocol versions don't match. Update to newest release. */
+
+//Errors streamed back from firmware
+#define EEPHIDGET_OK EEPHIDGET_EVENT_ERROR(0x1000) /**< An error state has ended - see description for details. */
+#define EEPHIDGET_OVERRUN EEPHIDGET_EVENT_ERROR(0x1002) /**< A sampling overrun happend in firmware. */
+#define EEPHIDGET_PACKETLOST EEPHIDGET_EVENT_ERROR(0x1003) /**< One or more packets were lost. */
+#define EEPHIDGET_WRAP EEPHIDGET_EVENT_ERROR(0x1004) /**< A variable has wrapped around. */
+#define EEPHIDGET_OVERTEMP EEPHIDGET_EVENT_ERROR(0x1005) /**< Overtemperature condition detected. */
+#define EEPHIDGET_OVERCURRENT EEPHIDGET_EVENT_ERROR(0x1006) /**< Overcurrent condition detected. */
+#define EEPHIDGET_OUTOFRANGE EEPHIDGET_EVENT_ERROR(0x1007) /**< Out of range condition detected. */
+#define EEPHIDGET_BADPOWER EEPHIDGET_EVENT_ERROR(0x1008) /**< Power supply problem detected. */
+
+/** @} */
+
+/** \name Phidget Unknown Constants
+ * Data values will be set to these constants when a call fails with \ref EPHIDGET_UNKNOWNVAL.
+ * @{
+ */
+#define PUNK_BOOL 0x02 /**< Unknown Boolean (unsigned char) */
+#define PUNK_SHRT 0x7FFF /**< Unknown Short (16-bit) */
+#define PUNK_INT 0x7FFFFFFF /**< Unknown Integer (32-bit) */
+#define PUNK_INT64 0x7FFFFFFFFFFFFFFFLL /**< Unknown Integer (64-bit) */
+#define PUNK_DBL 1e300 /**< Unknown Double */
+#define PUNK_FLT 1e30 /**< Unknown Float */
+/** @} */
+
+#define PFALSE 0x00 /**< False. Used for boolean values. */
+#define PTRUE 0x01 /**< True. Used for boolean values. */
+
+/** @} */
+
+#endif
+
diff --git a/cphidgetconstantsinternal.h b/cphidgetconstantsinternal.h
new file mode 100644
index 0000000..5659bec
--- /dev/null
+++ b/cphidgetconstantsinternal.h
@@ -0,0 +1,130 @@
+#ifndef CPHIDGET_CONSTANTS_INTERNAL
+#define CPHIDGET_CONSTANTS_INTERNAL
+
+//internal status representation via flags - for Phidget, Manager, Dictionary
+/*
+ * PHIDGET_ATTACHED_FLAG
+ * true: Phidget is attached to computer, and you can call all commands on this handle
+ * false: Phidget is not ready to handle calls yet - might be not connected,
+ * in proccess of connecting, just disconnected, not initialized, etc.
+ * This flag is returend externally to users.
+ */
+#define PHIDGET_ATTACHED_FLAG 0x01
+/*
+ * PHIDGET_DETACHING_FLAG
+ * true: Phidget has just been detached, but the detach code is still running
+ * false: Any other time
+ * There are two types of funtions - those that communicate with devices and those that
+ * return cached info - the second class should succedd if this is true and PHIDGET_ATTACHED_FLAG is false,
+ * so we can get device info in the detach handler.
+ */
+#define PHIDGET_DETACHING_FLAG 0x02
+/*
+ * PHIDGET_USB_ERROR_FLAG
+ * true: Phidget has encountered a USB error bad enough to require a detach
+ * false: Any other time
+ * The base thread will notice this error code and detach the device. If it is ok, it will
+ * be picked up next iteration and an attach will occur.
+ */
+#define PHIDGET_USB_ERROR_FLAG 0x04
+/*
+ * PHIDGET_ATTACHING_FLAG
+ * true: Phidget is attached to computer, but initialization is still in progress
+ * false: any other time
+ * This is used internally only
+ */
+#define PHIDGET_ATTACHING_FLAG 0x08
+/*
+ * PHIDGET_OPENED_FLAG
+ * true: open has been called on the handle
+ * false: open has not yet been called, or close has been called.
+ * This is used internally only
+ */
+#define PHIDGET_OPENED_FLAG 0x10
+/*
+ * PHIDGET_SERVER_CONNECTED_FLAG
+ * true: networkInfo->server is valid and connected
+ * false: networkInfo should not be considered valid
+ * This is used internally only
+ */
+#define PHIDGET_SERVER_CONNECTED_FLAG 0x20
+/*
+ * PHIDGET_REMOTE_FLAG
+ * true: This was opened with _remote and networkInfo is valid
+ * false: networkInfo is not valid - not opened or opened non-remote
+ * This is used internally only
+ */
+#define PHIDGET_REMOTE_FLAG 0x40
+/*
+ * PHIDGET_INERROREVENT_FLAG
+ * true: an error event is being run
+ * false: not
+ * This is used internally only
+ */
+#define PHIDGET_INERROREVENT_FLAG 0x80
+
+
+//internal status representation via flags - for socket
+/*
+ * PHIDGETSOCKET_CONNECTED_FLAG
+ * true: Socket is connected, authorization succeeded and listeners and reports are set up.
+ * false: Socket is not ready
+ * This flag is returned externally to users.
+ */
+#define PHIDGETSOCKET_CONNECTED_FLAG 0x01
+/*
+ * PHIDGETSOCKET_CONNECTING_FLAG
+ * true: connecting is being set up
+ * false: not
+ * This leads to either PHIDGETSOCKET_CONNECTED_FLAG, PHIDGETSOCKET_AUTHERROR_FLAG, or PHIDGETSOCKET_CONNECTIONERROR_FLAG
+ * This is used internally only
+ */
+#define PHIDGETSOCKET_CONNECTING_FLAG 0x02
+/*
+ * PHIDGETSOCKET_CONNECTIONERROR_FLAG
+ * true: a connection (socket) error occured
+ * false: a socket error did not occur
+ * This could happen any time, generally, we got a bad response from a socket, or a timeout
+ * This is used internally only
+ */
+#define PHIDGETSOCKET_CONNECTIONERROR_FLAG 0x04
+/*
+ * PHIDGETSOCKET_AUTHERROR_FLAG
+ * true: authorization with server failed
+ * false: authorization didn't fail (yet)
+ * This is a password error
+ * This is used internally only
+ */
+#define PHIDGETSOCKET_AUTHERROR_FLAG 0x08
+
+
+/* Internal error codes - start at 0x8000 */
+#define EPHIDGET_TRYAGAIN 0x8000
+
+/* 10 characters UTF-8, so up to 4 bytes per character */
+#define MAX_LABEL_SIZE 10
+#define MAX_LABEL_STORAGE MAX_LABEL_SIZE*4+1
+
+#define MAX_IN_PACKET_SIZE 64
+#define MAX_OUT_PACKET_SIZE 32
+
+#define PHIDGETOPEN_ANY 0x00
+#define PHIDGETOPEN_SERIAL 0x01
+#define PHIDGETOPEN_ANY_ATTACHED 0x02
+#define PHIDGETOPEN_LABEL 0x04
+
+/* Uninitialized values - for webservice */
+#define PUNI_BOOL 0x03
+#define PUNI_INT 0x7FFFFFFE
+#define PUNI_INT64 0x7FFFFFFFFFFFFFFELL
+#define PUNI_DBL 1e250
+#define PUNI_FLT 1e25
+
+
+// this needs to reflect the size of Phid_DeviceName
+#define PHIDGET_DEVICE_CLASS_COUNT 24
+// this needs to reflect the size of Phid_Device_Def (not including the null end)
+#define PHIDGET_DEVICE_COUNT 54
+
+#endif
+
diff --git a/cphidgetdictionary.c b/cphidgetdictionary.c
new file mode 100644
index 0000000..ba9bbd9
--- /dev/null
+++ b/cphidgetdictionary.c
@@ -0,0 +1,328 @@
+/*
+ * cphidgetdictionary.c
+ * Phidget21
+ *
+ * Created by Patrick McNeil on 02/10/06.
+ * Copyright 2006 Phidgets Inc. All rights reserved.
+ *
+ */
+
+#include "stdafx.h"
+#include "cphidgetdictionary.h"
+#include "csocket.h"
+#include "csocketevents.h"
+#include "cphidgetlist.h"
+#include "cphidgetmanager.h"
+
+int CPhidgetDictionary_areEqual(void *arg1, void *arg2)
+{
+ if(arg1 == arg2) return 1;
+ return 0;
+}
+
+void CPhidgetDictionary_free(void *arg)
+{
+ CPhidgetDictionaryHandle dict = arg;
+
+ if(!dict)
+ return;
+
+ CThread_mutex_lock(&dict->listenersLock);
+ CList_emptyList((CListHandle *)&dict->listeners, PTRUE, CPhidgetDictionaryListener_free);
+ CThread_mutex_unlock(&dict->listenersLock);
+
+ CThread_mutex_destroy(&dict->lock);
+ CThread_mutex_destroy(&dict->listenersLock);
+ CThread_mutex_destroy(&dict->openCloseLock);
+
+ free(dict); dict = NULL;
+}
+
+int CPhidgetDictionaryListener_areEqual(void *arg1, void *arg2)
+{
+ if(arg1 == arg2) return 1;
+ return 0;
+}
+
+void CPhidgetDictionaryListener_free(void *arg)
+{
+ CPhidgetDictionaryListenerHandle dict = arg;
+
+ if(!dict)
+ return;
+ free(dict); dict = NULL;
+}
+
+int CCONV CPhidgetDictionary_create(CPhidgetDictionaryHandle *dict)
+{
+ CPhidgetDictionaryHandle dicttemp = 0;
+
+ TESTPTR(dict)
+
+ if(!(dicttemp = (CPhidgetDictionaryHandle)malloc(sizeof(CPhidgetDictionary))))
+ return EPHIDGET_NOMEMORY;
+ ZEROMEM(dicttemp, sizeof(CPhidgetDictionary));
+
+ CThread_mutex_init(&dicttemp->lock);
+ CThread_mutex_init(&dicttemp->listenersLock);
+ CThread_mutex_init(&dicttemp->openCloseLock);
+
+ *dict = dicttemp;
+ return EPHIDGET_OK;
+}
+
+int CCONV CPhidgetDictionary_close(CPhidgetDictionaryHandle dict)
+{
+ int result = EPHIDGET_OK;
+ TESTPTR(dict)
+
+ CThread_mutex_lock(&dict->openCloseLock);
+ if (!CPhidget_statusFlagIsSet(dict->status, PHIDGET_OPENED_FLAG))
+ {
+ LOG(PHIDGET_LOG_WARNING, "Close was called on an already closed Dictionary handle.");
+ CThread_mutex_unlock(&dict->openCloseLock);
+ return EPHIDGET_OK;
+ }
+
+ if((result = unregisterRemoteDictionary(dict)) != EPHIDGET_OK)
+ {
+ CThread_mutex_unlock(&dict->openCloseLock);
+ return result;
+ }
+
+ CPhidget_clearStatusFlag(&dict->status, PHIDGET_OPENED_FLAG, &dict->lock);
+ CThread_mutex_unlock(&dict->openCloseLock);
+ return EPHIDGET_OK;
+}
+
+int CCONV CPhidgetDictionary_delete(CPhidgetDictionaryHandle dict)
+{
+ CPhidgetDictionary_free(dict);
+ return EPHIDGET_OK;
+}
+
+int CCONV CPhidgetDictionary_getServerID(CPhidgetDictionaryHandle dict, const char **serverID)
+{
+ return CPhidget_getServerID((CPhidgetHandle)dict, serverID);
+}
+int CCONV CPhidgetDictionary_getServerAddress(CPhidgetDictionaryHandle dict, const char **address, int *port)
+{
+ return CPhidget_getServerAddress((CPhidgetHandle)dict, address, port);
+}
+int CCONV CPhidgetDictionary_getServerStatus(CPhidgetDictionaryHandle dict, int *status)
+{
+ return CPhidget_getServerStatus((CPhidgetHandle)dict, status);
+}
+
+int CCONV CPhidgetDictionary_set_OnError_Handler(CPhidgetDictionaryHandle dict,
+ int(CCONV *fptr)(CPhidgetDictionaryHandle, void *, int, const char *), void *userPtr)
+{
+ TESTPTR(dict)
+ dict->fptrError = fptr;
+ dict->fptrErrorptr = userPtr;
+ return EPHIDGET_OK;
+}
+
+/* Async add - errors returned to a registered error handler */
+int CCONV CPhidgetDictionary_addKey(CPhidgetDictionaryHandle dict, const char *key, const char *val, int persistent)
+{
+ TESTPTR(dict)
+ TESTPTRS(key, val)
+
+ CThread_mutex_lock(&dict->lock);
+ if(!CPhidget_statusFlagIsSet(dict->status, PHIDGET_SERVER_CONNECTED_FLAG))
+ {
+ CThread_mutex_unlock(&dict->lock);
+ return EPHIDGET_NETWORK_NOTCONNECTED;
+ }
+
+ pdc_async_set(dict->networkInfo->server->pdcs, key, val, (int)strlen(val), persistent?0:1, internal_async_network_error_handler, dict);
+
+ CThread_mutex_unlock(&dict->lock);
+
+ return EPHIDGET_OK;
+}
+
+int CCONV CPhidgetDictionary_removeKey(CPhidgetDictionaryHandle dict, const char *pattern)
+{
+// int result;
+// char err[1024];
+ TESTPTRS(dict, pattern)
+
+ CThread_mutex_lock(&dict->lock);
+ if(!CPhidget_statusFlagIsSet(dict->status, PHIDGET_SERVER_CONNECTED_FLAG))
+ {
+ CThread_mutex_unlock(&dict->lock);
+ return EPHIDGET_NETWORK_NOTCONNECTED;
+ }
+
+// CThread_mutex_lock(&dict->networkInfo->server->pdc_lock);
+// result = pdc_remove(dict->networkInfo->server->pdcs, pattern, err, sizeof(err));
+// CThread_mutex_unlock(&dict->networkInfo->server->pdc_lock);
+
+ pdc_async_remove(dict->networkInfo->server->pdcs, pattern, internal_async_network_error_handler, dict);
+
+ CThread_mutex_unlock(&dict->lock);
+
+// if(result == 0) return EPHIDGET_UNEXPECTED;
+ return EPHIDGET_OK;
+}
+
+int CCONV CPhidgetDictionary_getKey(CPhidgetDictionaryHandle dict, const char *key, char *val, int vallen)
+{
+ int result, size;
+ char err[1024], *keywrap;
+ TESTPTRS(dict, key)
+ TESTPTR(val)
+
+ CThread_mutex_lock(&dict->lock);
+ if(!CPhidget_statusFlagIsSet(dict->status, PHIDGET_SERVER_CONNECTED_FLAG))
+ {
+ CThread_mutex_unlock(&dict->lock);
+ return EPHIDGET_NETWORK_NOTCONNECTED;
+ }
+
+ //The get command returns a list of keys - since we want just a single key, lets wrap in ^ and $
+ //other reg exp tags are allowed and will be honoured
+ size = (int)strlen(key);
+ keywrap = (char *)malloc(size+3);
+ snprintf(keywrap, size+3, "^%s$",key);
+
+ CThread_mutex_lock(&dict->networkInfo->server->pdc_lock);
+ if(!dict->networkInfo->server->pdcs)
+ result = EPHIDGET_NETWORK_NOTCONNECTED;
+ else
+ result = pdc_get(dict->networkInfo->server->pdcs, keywrap, val, vallen, err, sizeof(err));
+ CThread_mutex_unlock(&dict->networkInfo->server->pdc_lock);
+
+ free(keywrap);
+
+ CThread_mutex_unlock(&dict->lock);
+
+ if(result == 0) return EPHIDGET_UNEXPECTED;
+ return EPHIDGET_OK;
+}
+
+void dict_event_handler(const char *key, const char *val, unsigned int len, pdict_reason_t reason, void *ptr)
+{
+ CPhidgetDictionaryListenerHandle listener = ptr;
+
+ if(!listener) return;
+
+ if(listener->fptr)
+ listener->fptr(listener->dict, listener->userPtr, key, val, (CPhidgetDictionary_keyChangeReason)reason);
+ return;
+}
+
+int CCONV CPhidgetDictionary_set_OnServerConnect_Handler(CPhidgetDictionaryHandle dict, int (CCONV *fptr)(CPhidgetDictionaryHandle dict, void *userPtr), void *userPtr)
+{
+ TESTPTR(dict)
+ dict->fptrServerConnect = fptr;
+ dict->fptrServerConnectptr = userPtr;
+ return EPHIDGET_OK;
+}
+int CCONV CPhidgetDictionary_set_OnServerDisconnect_Handler(CPhidgetDictionaryHandle dict, int (CCONV *fptr)(CPhidgetDictionaryHandle dict, void *userPtr), void *userPtr)
+{
+ TESTPTR(dict)
+ dict->fptrServerDisconnect = fptr;
+ dict->fptrServerDisconnectptr = userPtr;
+ return EPHIDGET_OK;
+}
+
+int CCONV CPhidgetDictionary_set_OnKeyChange_Handler(CPhidgetDictionaryHandle dict, CPhidgetDictionaryListenerHandle *dictlistener, const char *pattern,
+ int(CCONV *fptr)(CPhidgetDictionaryHandle dict, void *userPtr, const char *key, const char *val, CPhidgetDictionary_keyChangeReason reason),
+ void *userPtr)
+{
+ CPhidgetDictionaryListenerHandle dict_listener;
+ char errdesc[1024];
+ int result;
+
+ TESTPTRS(dict, pattern)
+ TESTPTR(dictlistener)
+
+ CThread_mutex_lock(&dict->lock);
+ if(!CPhidget_statusFlagIsSet(dict->status, PHIDGET_SERVER_CONNECTED_FLAG))
+ {
+ CThread_mutex_unlock(&dict->lock);
+ return EPHIDGET_NETWORK_NOTCONNECTED;
+ }
+
+ if(!(dict_listener = malloc(sizeof(CPhidgetDictionaryListener))))
+ {
+ CThread_mutex_unlock(&dict->lock);
+ return EPHIDGET_NOMEMORY;
+ }
+ ZEROMEM(dict_listener, sizeof(CPhidgetDictionaryListener));
+
+ dict_listener->dict = dict;
+ dict_listener->fptr = fptr;
+ dict_listener->userPtr = userPtr;
+
+ CThread_mutex_lock(&dict->networkInfo->server->pdc_lock);
+ if (!(dict_listener->listen_id = pdc_listen(dict->networkInfo->server->pdcs, pattern, dict_event_handler, dict_listener, errdesc, sizeof (errdesc))))
+ {
+ LOG(PHIDGET_LOG_DEBUG,"pdc_listen: %s", errdesc);
+ free(dict_listener);
+ CThread_mutex_unlock(&dict->networkInfo->server->pdc_lock);
+ CThread_mutex_unlock(&dict->lock);
+ return EPHIDGET_UNEXPECTED;
+ }
+ CThread_mutex_unlock(&dict->networkInfo->server->pdc_lock);
+
+ CThread_mutex_lock(&dict->listenersLock);
+ if((result = CList_addToList((CListHandle *)&dict->listeners, dict_listener, CPhidgetDictionaryListener_areEqual)))
+ {
+ CThread_mutex_unlock(&dict->listenersLock);
+ CThread_mutex_lock(&dict->networkInfo->server->pdc_lock);
+ pdc_ignore(dict->networkInfo->server->pdcs, dict_listener->listen_id, NULL, 0);
+ CThread_mutex_unlock(&dict->networkInfo->server->pdc_lock);
+ free(dict_listener);
+ CThread_mutex_unlock(&dict->lock);
+ return result;
+ }
+ CThread_mutex_unlock(&dict->listenersLock);
+ CThread_mutex_unlock(&dict->lock);
+
+ *dictlistener = dict_listener;
+
+ return EPHIDGET_OK;
+}
+
+//This can be called even when not connected to a server
+int CCONV CPhidgetDictionary_remove_OnKeyChange_Handler(CPhidgetDictionaryListenerHandle keylistener)
+{
+ int result = 0;
+ char errdesc[1024];
+ CPhidgetDictionaryHandle dict;
+
+ TESTPTR(keylistener)
+ dict = keylistener->dict;
+
+ CThread_mutex_lock(&dict->lock);
+
+ if(CPhidget_statusFlagIsSet(dict->status, PHIDGET_SERVER_CONNECTED_FLAG))
+ {
+ CThread_mutex_lock(&dict->networkInfo->server->pdc_lock);
+ if(!(result = pdc_ignore(dict->networkInfo->server->pdcs, keylistener->listen_id, errdesc, sizeof (errdesc))))
+ {
+ LOG(PHIDGET_LOG_WARNING,"pdc_ignore: %s",errdesc);
+ CThread_mutex_unlock(&dict->networkInfo->server->pdc_lock);
+ CThread_mutex_unlock(&dict->lock);
+ return EPHIDGET_UNEXPECTED;
+ }
+ CThread_mutex_unlock(&dict->networkInfo->server->pdc_lock);
+ }
+
+ CThread_mutex_lock(&dict->listenersLock);
+ if((result = CList_removeFromList((CListHandle *)&dict->listeners, keylistener,
+ CPhidgetDictionaryListener_areEqual, PTRUE, CPhidgetDictionaryListener_free)))
+ {
+ CThread_mutex_unlock(&dict->listenersLock);
+ CThread_mutex_unlock(&dict->lock);
+ return result;
+ }
+ CThread_mutex_unlock(&dict->listenersLock);
+ CThread_mutex_unlock(&dict->lock);
+
+ return EPHIDGET_OK;
+}
diff --git a/cphidgetdictionary.h b/cphidgetdictionary.h
new file mode 100644
index 0000000..8ea17e9
--- /dev/null
+++ b/cphidgetdictionary.h
@@ -0,0 +1,178 @@
+#ifndef __CPHIDGETDICTIONARY
+#define __CPHIDGETDICTIONARY
+#include "cphidget.h"
+
+/** \defgroup phiddict Phidget Dictionary
+ * Calls specific to the Phidget Dictionary.
+ * @{
+ */
+
+/**
+ * Possible reasons for a key event.
+ */
+typedef enum {
+ PHIDGET_DICTIONARY_VALUE_CHANGED = 1, /**< The value of an existing key/value pair changed. */
+ PHIDGET_DICTIONARY_ENTRY_ADDED, /**< A new key/value pair was added. */
+ PHIDGET_DICTIONARY_ENTRY_REMOVING, /**< A key is being removed. */
+ PHIDGET_DICTIONARY_CURRENT_VALUE /**< Initial state received once a handler was added. */
+} CPhidgetDictionary_keyChangeReason;
+
+/**
+ * A Phidget Dictionary handle.
+ */
+DPHANDLE(Dictionary)
+/**
+ * A Dictionary key listener handle.
+ */
+DPHANDLE(DictionaryListener)
+
+#ifndef EXTERNALPROTO
+
+typedef struct _CPhidgetDictionaryListener
+{
+ CPhidgetDictionaryHandle dict;
+ int(CCONV *fptr)(CPhidgetDictionaryHandle dict, void *userPtr, const char *key, const char *val, CPhidgetDictionary_keyChangeReason reason);
+ void *userPtr;
+ int listen_id;
+} CPhidgetDictionaryListener;
+
+typedef struct _CPhidgetDictionaryListenerList
+{
+ struct _CPhidgetDictionaryListenerList *next;
+ CPhidgetDictionaryListenerHandle listener;
+} CPhidgetDictionaryListenerList, *CPhidgetDictionaryListenerListHandle;
+
+typedef struct _CPhidgetDictionary
+{
+ CPhidgetRemoteHandle networkInfo;
+ int(CCONV *fptrError)(CPhidgetDictionaryHandle , void *, int, const char *);
+ void *fptrErrorptr;
+ int(CCONV *fptrServerConnect)(CPhidgetDictionaryHandle , void *);
+ void *fptrServerConnectptr;
+ int(CCONV *fptrServerDisconnect)(CPhidgetDictionaryHandle , void *);
+ void *fptrServerDisconnectptr;
+ CThread_mutex_t lock; /* protects status */
+ int status;
+ CThread_mutex_t openCloseLock; /* protects open / close */
+ CPhidgetDictionaryListenerListHandle listeners;
+ CThread_mutex_t listenersLock; /* protects listeners */
+} CPhidgetDictionary;
+
+typedef struct _CPhidgetDictionaryList
+{
+ struct _CPhidgetDictionaryList *next;
+ CPhidgetDictionaryHandle dict;
+} CPhidgetDictionaryList, *CPhidgetDictionaryListHandle;
+
+int CPhidgetDictionary_areEqual(void *arg1, void *arg2);
+void CPhidgetDictionary_free(void *arg);
+int CPhidgetDictionaryListener_areEqual(void *arg1, void *arg2);
+void CPhidgetDictionaryListener_free(void *arg);
+
+#endif
+/**
+ * Creates a Phidget Dictionary handle.
+ * @param dict A pointer to an unallocated phidget dictionary handle.
+ */
+PHIDGET21_API int CCONV CPhidgetDictionary_create(CPhidgetDictionaryHandle *dict);
+/**
+ * Closes the connection to a Phidget Dictionary.
+ * @param dict An opened phidget dictionary handle.
+ */
+PHIDGET21_API int CCONV CPhidgetDictionary_close(CPhidgetDictionaryHandle dict);
+/**
+ * Frees a Phidget Dictionary handle.
+ * @param dict A closed dictionary handle.
+ */
+PHIDGET21_API int CCONV CPhidgetDictionary_delete(CPhidgetDictionaryHandle dict);
+/**
+ * Sets the error handler callback function. This is called when an asynchronous error occurs.
+ * @param dict A phidget dictionary handle.
+ * @param fptr Callback function pointer.
+ * @param userPtr A pointer for use by the user - this value is passed back into the callback function.
+ */
+PHIDGET21_API int CCONV CPhidgetDictionary_set_OnError_Handler(CPhidgetDictionaryHandle dict,
+ int(CCONV *fptr)(CPhidgetDictionaryHandle, void *userPtr, int errorCode, const char *errorString), void *userPtr);
+/**
+ * Adds a key/value pair to the dictionary. Or, changes an existing key's value.
+ * @param dict A connected dictionary handle.
+ * @param key The key value.
+ * @param value The value value.
+ * @param persistent Whether the key stays in the dictionary after disconnection.
+ */
+PHIDGET21_API int CCONV CPhidgetDictionary_addKey(CPhidgetDictionaryHandle dict, const char *key, const char *value, int persistent);
+/**
+ * Removes a set of keys from the dictionary.
+ * @param dict A connected dictionary handle.
+ * @param pattern A regular expression representing th eset of keys to remove.
+ */
+PHIDGET21_API int CCONV CPhidgetDictionary_removeKey(CPhidgetDictionaryHandle dict, const char *pattern);
+/**
+ * Callback function for KeyChange events.
+ * @param dict Dictionary from which this event originated.
+ * @param userPtr User defined data.
+ * @param key Key value.
+ * @param value Value value.
+ * @param reason Reason for KeyChange event.
+ */
+typedef int(CCONV *CPhidgetDictionary_OnKeyChange_Function)(CPhidgetDictionaryHandle dict, void *userPtr,
+ const char *key, const char *value, CPhidgetDictionary_keyChangeReason reason);
+/**
+ * Adds a key listener to an opened dictionary. Note that this should only be called after the connection to the
+ * dictionary has been made - unlike all other events.
+ * @param dict A connected dictionary handle.
+ * @param dictlistener A pointer to an unallocated dictionary key listener handle.
+ * @param pattern A regular expression representing the set of keys to monitor.
+ * @param fptr Callback function pointer.
+ * @param userPtr A pointer for use by the user - this value is passed back into the callback function.
+ */
+PHIDGET21_API int CCONV CPhidgetDictionary_set_OnKeyChange_Handler(CPhidgetDictionaryHandle dict, CPhidgetDictionaryListenerHandle *dictlistener, const char *pattern,
+ CPhidgetDictionary_OnKeyChange_Function fptr, void *userPtr);
+/**
+ * Removes a key listener.
+ * @param dictlistener The dictionary key listener created by \ref CPhidgetDictionary_set_OnKeyChange_Handler
+ */
+PHIDGET21_API int CCONV CPhidgetDictionary_remove_OnKeyChange_Handler(CPhidgetDictionaryListenerHandle dictlistener);
+/**
+ * Gets a key value. If more then one key matches, only the first value is returned.
+ * @param dict A phidget dictionary handle.
+ * @param key A key value to look up.
+ * @param value A user array for the value to be stored in. Set to NULL if the key does not exist.
+ * @param valuelen Length of the value array.
+ */
+PHIDGET21_API int CCONV CPhidgetDictionary_getKey(CPhidgetDictionaryHandle dict, const char *key, char *value, int valuelen);
+/**
+ * Sets a server connect handler callback function. This is called when a connection to the sever has been made.
+ * @param dict A phidget dictionary handle.
+ * @param fptr Callback function pointer.
+ * @param userPtr A pointer for use by the user - this value is passed back into the callback function.
+ */
+PHIDGET21_API int CCONV CPhidgetDictionary_set_OnServerConnect_Handler(CPhidgetDictionaryHandle dict, int (CCONV *fptr)(CPhidgetDictionaryHandle dict, void *userPtr), void *userPtr);
+/**
+ * Sets a server disconnect handler callback function. This is called when a connection to the server has been lost.
+ * @param dict A phidget dictionary handle.
+ * @param fptr Callback function pointer.
+ * @param userPtr A pointer for use by the user - this value is passed back into the callback function.
+ */
+PHIDGET21_API int CCONV CPhidgetDictionary_set_OnServerDisconnect_Handler(CPhidgetDictionaryHandle dict, int (CCONV *fptr)(CPhidgetDictionaryHandle dict, void *userPtr), void *userPtr);
+/**
+ * Gets the server ID.
+ * @param dict A connected dictionary handle.
+ * @param serverID A pointer which will be set to a char array containing the server ID string.
+ */
+PHIDGET21_API int CCONV CPhidgetDictionary_getServerID(CPhidgetDictionaryHandle dict, const char **serverID);
+/**
+ * Gets the address and port.
+ * @param dict A connected dictionary handle.
+ * @param address A pointer which will be set to a char array containing the address string.
+ * @param port An int pointer for returning the port number.
+ */
+PHIDGET21_API int CCONV CPhidgetDictionary_getServerAddress(CPhidgetDictionaryHandle dict, const char **address, int *port);
+/**
+ * Gets the connected to server status.
+ * @param dict An opened dictionary handle.
+ * @param serverStatus An int pointer for returning the server status. Possible codes are \ref PHIDGET_ATTACHED and \ref PHIDGET_NOTATTACHED.
+ */
+PHIDGET21_API int CCONV CPhidgetDictionary_getServerStatus(CPhidgetDictionaryHandle dict, int *serverStatus);
+/** @} */
+#endif
diff --git a/cphidgetencoder.c b/cphidgetencoder.c
new file mode 100644
index 0000000..3c1991f
--- /dev/null
+++ b/cphidgetencoder.c
@@ -0,0 +1,455 @@
+#include "stdafx.h"
+#include "cphidgetencoder.h"
+#include <stdio.h>
+#include "cusb.h"
+#include "csocket.h"
+#include "cthread.h"
+
+// === Internal Functions === //
+
+//clearVars - sets all device variables to unknown state
+CPHIDGETCLEARVARS(Encoder)
+ int i = 0;
+ for (i = 0; i<ENCODER_MAXINPUTS; i++)
+ {
+ phid->inputState[i] = PUNK_BOOL;
+ }
+ for (i = 0; i<ENCODER_MAXENCODERS; i++)
+ {
+ phid->encoderPosition[i] = 0;
+ phid->encoderTimeStamp[i] = PUNK_INT;
+ phid->indexPosition[i] = PUNK_INT;
+ phid->enableStateEcho[i] = PUNI_BOOL;
+ }
+ return EPHIDGET_OK;
+}
+
+//initAfterOpen - sets up the initial state of an object, reading in packets from the device if needed
+// used during attach initialization - on every attach
+CPHIDGETINIT(Encoder)
+ int i = 0;
+ unsigned char buffer[8] = { 0 };
+ int result;
+
+ TESTPTR(phid);
+
+ //Make sure no old writes are still pending
+ phid->outputPacketLen = 0;
+
+ //set data arrays to unknown, initial states
+ for (i = 0; i<phid->phid.attr.encoder.numInputs; i++)
+ {
+ phid->inputState[i] = PUNK_BOOL;
+ }
+ for (i = 0; i<phid->phid.attr.encoder.numEncoders; i++)
+ {
+ phid->encoderPosition[i] = 0; //position set to zero on each attach
+ phid->encoderTimeStamp[i] = PUNK_INT;
+ phid->indexPosition[i] = PUNK_INT;
+ switch(phid->phid.deviceIDSpec) {
+ case PHIDID_ENCODER_HS_4ENCODER_4INPUT:
+ phid->enableState[i] = PUNK_BOOL;
+ phid->enableStateEcho[i] = PUNK_BOOL;
+ break;
+ case PHIDID_ENCODER_1ENCODER_1INPUT:
+ case PHIDID_ENCODER_HS_1ENCODER:
+ phid->enableState[i] = PTRUE;
+ phid->enableStateEcho[i] = PTRUE;
+ break;
+ default:
+ break;
+ }
+ }
+
+ //send out any initial pre-read packets
+ switch(phid->phid.deviceIDSpec) {
+ case PHIDID_ENCODER_1ENCODER_1INPUT:
+ if (phid->phid.deviceVersion <= 100)
+ {
+ ZEROMEM(buffer,8);
+ LOG(PHIDGET_LOG_INFO,"Sending workaround startup packet");
+ if ((result = CUSBSendPacket((CPhidgetHandle)phid, buffer)) != EPHIDGET_OK)
+ return result;
+ }
+ break;
+ case PHIDID_ENCODER_HS_1ENCODER:
+ case PHIDID_ENCODER_HS_4ENCODER_4INPUT:
+ default:
+ break;
+ }
+
+ //issue a read on the 4-input HS to get enable states
+ switch(phid->phid.deviceIDSpec) {
+ case PHIDID_ENCODER_HS_4ENCODER_4INPUT:
+ if (phid->phid.deviceVersion >= 100 && phid->phid.deviceVersion < 200)
+ {
+ CPhidget_read((CPhidgetHandle)phid);
+ }
+ break;
+ case PHIDID_ENCODER_1ENCODER_1INPUT:
+ case PHIDID_ENCODER_HS_1ENCODER:
+ default:
+ break;
+ }
+
+ //fill in enabled states
+ for (i = 0; i<phid->phid.attr.encoder.numEncoders; i++)
+ {
+ phid->enableState[i] = phid->enableStateEcho[i];
+ }
+
+ return EPHIDGET_OK;
+}
+
+//dataInput - parses device packets
+CPHIDGETDATA(Encoder)
+ int i=0,j=0;
+
+ unsigned char input[ENCODER_MAXINPUTS];
+ unsigned char indexTrue[ENCODER_MAXINPUTS];
+ unsigned char enabledEcho[ENCODER_MAXINPUTS];
+ short positionChange[ENCODER_MAXENCODERS];
+ short indexChange[ENCODER_MAXENCODERS];
+ int packetTime[ENCODER_MAXENCODERS];
+ int curTime[ENCODER_MAXENCODERS];
+ unsigned short timeChange = 0, timeStamp = 0;
+ int timeChangeInt[ENCODER_MAXENCODERS];
+
+ unsigned char lastInputState[ENCODER_MAXINPUTS];
+
+ if (length<0) return EPHIDGET_INVALIDARG;
+ TESTPTR(phid);
+ TESTPTR(buffer);
+
+ ZEROMEM(input, sizeof(input));
+ ZEROMEM(positionChange, sizeof(positionChange));
+ ZEROMEM(lastInputState, sizeof(lastInputState));
+ ZEROMEM(indexTrue, sizeof(indexTrue));
+ ZEROMEM(indexChange, sizeof(indexChange));
+ ZEROMEM(packetTime, sizeof(packetTime));
+ ZEROMEM(curTime, sizeof(curTime));
+ ZEROMEM(timeChangeInt, sizeof(timeChangeInt));
+
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_ENCODER_1ENCODER_1INPUT:
+ /* OLD version here... */
+ if (phid->phid.deviceVersion < 110)
+ {
+ if (buffer[1] & 0x04)
+ input[0] = PFALSE;
+ else
+ input[0] = PTRUE;
+
+ positionChange[0] = (signed char)buffer[2];
+
+ timeStamp = (((unsigned short)buffer[4]) << 8) + buffer[3];
+ }
+ /* NEW version 1-encoder = 1.10+*/
+ else if (phid->phid.deviceVersion >= 110 && phid->phid.deviceVersion < 300)
+ {
+ if (buffer[1] & 0x01)
+ input[0] = PFALSE;
+ else
+ input[0] = PTRUE;
+
+ positionChange[0] = (signed char)buffer[4];
+
+ timeStamp = (((unsigned short)buffer[3]) << 8) + buffer[2];
+ }
+ else
+ return EPHIDGET_UNEXPECTED;
+ break;
+ case PHIDID_ENCODER_HS_1ENCODER:
+ /* high speed encoder */
+ if (phid->phid.deviceVersion >= 300 && phid->phid.deviceVersion < 400) {
+
+ //this will work for 8 inputs before we need to change the protocol
+ //currently no high-speed encoder has any inputs
+ for (i = 0, j = 1; i < (phid->phid.attr.encoder.numInputs); i++, j<<=1)
+ {
+ if (buffer[1] & j)
+ input[i] = PFALSE;
+ else
+ input[i] = PTRUE;
+ }
+
+ //this will work for two encoders before we need to change the protocol
+ for(i=0;i<phid->phid.attr.encoder.numEncoders;i++) {
+ positionChange[i] = (((unsigned short)buffer[2*i+5]) << 8) + buffer[2*i+4];
+ }
+
+ timeStamp = (((unsigned short)buffer[3]) << 8) + buffer[2];
+ }
+ else
+ return EPHIDGET_UNEXPECTED;
+ break;
+ case PHIDID_ENCODER_HS_4ENCODER_4INPUT:
+ /* high speed encoder 4 input, with enable and index */
+ if (phid->phid.deviceVersion >= 100 && phid->phid.deviceVersion < 200)
+ {
+ //this will work for two encoders before we need to change the protocol
+ for(i=0;i<phid->phid.attr.encoder.numEncoders;i++) {
+ positionChange[i] = (((unsigned short)buffer[10*i+0]) << 8) + buffer[10*i+1] - 0x7fff;
+ indexChange[i] = (((unsigned short)buffer[10*i+2]) << 8) + buffer[10*i+3] - 0x7fff;
+ packetTime[i] = (((int)buffer[10*i+4]) << 16) + (((unsigned short)buffer[10*i+5]) << 8) + buffer[10*i+6];
+ curTime[i] = (((unsigned short)buffer[10*i+7]) << 8) + buffer[10*i+8];
+ indexTrue[i] = (buffer[10*i+9] & 0x01) ? PTRUE : PFALSE;
+ enabledEcho[i] = (buffer[10*i+9] & 0x02) ? PTRUE : PFALSE;
+ if (buffer[10*i+9] & 0x04)
+ input[i] = PFALSE;
+ else
+ input[i] = PTRUE;
+ }
+ }
+ else
+ return EPHIDGET_UNEXPECTED;
+ break;
+ default:
+ return EPHIDGET_UNEXPECTED;
+ }
+
+ //Make sure values are within defined range, and store to structure
+ for (i = 0; i < phid->phid.attr.encoder.numInputs; i++)
+ {
+ lastInputState[i] = phid->inputState[i];
+ phid->inputState[i] = input[i];
+ }
+ for(i=0; i < phid->phid.attr.encoder.numEncoders; i++)
+ {
+ //check for over/undershoots
+ if((positionChange[i] > 0 && (phid->encoderPosition[i] + positionChange[i]) < phid->encoderPosition[i])
+ || (positionChange[i] < 0 && (phid->encoderPosition[i] + positionChange[i]) > phid->encoderPosition[i]))
+ {
+ char error_buffer[50];
+ FIRE_ERROR(EEPHIDGET_WRAP, "Encoder %d position is wrapping around.", i);
+ }
+
+ phid->encoderPosition[i] += positionChange[i];
+
+ //Different timing stuff for different devices
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_ENCODER_1ENCODER_1INPUT:
+ case PHIDID_ENCODER_HS_1ENCODER:
+ //this handles wraparounds because we're using unsigned shorts
+ timeChange = (timeStamp - phid->encoderTimeStamp[i]);
+
+ //TODO: this misses the case where timeChange > 65 seconds - we would need to add timing to the library
+ if (timeChange > 30000 || phid->encoderTimeStamp[i] == PUNK_INT)
+ timeChangeInt[i] = PUNK_INT;
+ else
+ timeChangeInt[i] = timeChange;
+
+ phid->encoderTimeStamp[i] = timeStamp;
+ break;
+ case PHIDID_ENCODER_HS_4ENCODER_4INPUT:
+ //timing
+ if (phid->encoderTimeStamp[i] == PUNK_INT)
+ phid->encoderTimeStamp[i] = 0;
+
+ phid->encoderTimeStamp[i] += packetTime[i];
+
+ if(positionChange[i] != 0)
+ {
+ timeChangeInt[i] = phid->encoderTimeStamp[i] - curTime[i];
+ // convert 1/12,000,000 to microseconds
+ timeChangeInt[i] = round(timeChangeInt[i] / 12.0);
+
+ phid->encoderTimeStamp[i] = curTime[i];
+ }
+ //index
+ if(indexTrue[i])
+ phid->indexPosition[i] = phid->encoderPosition[i] - indexChange[i];
+ //enabled echo
+ phid->enableStateEcho[i] = enabledEcho[i];
+ break;
+ default:
+ return EPHIDGET_UNEXPECTED;
+ }
+ }
+
+ //send out any events for changed data
+ for (i = 0; i < phid->phid.attr.encoder.numInputs; i++)
+ {
+ if(phid->inputState[i] != lastInputState[i])
+ FIRE(InputChange, i, phid->inputState[i]);
+ }
+ for(i=0; i < phid->phid.attr.encoder.numEncoders; i++)
+ {
+ if(positionChange[i] != 0)
+ FIRE(PositionChange, i, timeChangeInt[i], positionChange[i]);
+ }
+
+ return EPHIDGET_OK;
+}
+
+//eventsAfterOpen - sends out an event for all valid data, used during attach initialization
+CPHIDGETINITEVENTS(Encoder)
+
+ for (i = 0; i < phid->phid.attr.encoder.numInputs; i++)
+ {
+ if (phid->inputState[i] != PUNK_BOOL)
+ {
+ FIRE(InputChange, i, phid->inputState[i]);
+ }
+ }
+ return EPHIDGET_OK;
+}
+
+//getPacket - used by write thread to get the next packet to send to device
+CGETPACKET_BUF(Encoder)
+
+//sendpacket - sends a packet to the device asynchronously, blocking if the 1-packet queue is full
+CSENDPACKET_BUF(Encoder)
+
+//makePacket - constructs a packet using current device state
+CMAKEPACKET(Encoder)
+ int i = 0, j = 0;
+
+ TESTPTRS(phid, buffer);
+
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_ENCODER_HS_4ENCODER_4INPUT:
+ if ((phid->phid.deviceVersion >= 100) && (phid->phid.deviceVersion < 200))
+ {
+ //have to make sure that everything to be sent has some sort of default value if the user hasn't set a value
+ for (i = 0; i<phid->phid.attr.encoder.numEncoders; i++)
+ {
+ if (phid->enableState[i] == PUNK_BOOL)
+ phid->enableState[i] = PFALSE;
+ }
+
+ //construct the packet
+ for (i = 0, j = 1; i < phid->phid.attr.encoder.numEncoders; i++, j<<=1)
+ {
+ if (phid->enableState[i])
+ buffer[0] |= j;
+ }
+ }
+ else
+ return EPHIDGET_UNEXPECTED;
+ break;
+ case PHIDID_ENCODER_HS_1ENCODER:
+ case PHIDID_ENCODER_1ENCODER_1INPUT:
+ return EPHIDGET_UNSUPPORTED; //these versions don't have OUT packets
+ default:
+ return EPHIDGET_UNEXPECTED;
+ }
+ return EPHIDGET_OK;
+}
+
+// === Exported Functions === //
+
+//create and initialize a device structure
+CCREATE(Encoder, PHIDCLASS_ENCODER)
+
+//event setup functions
+CFHANDLE(Encoder, InputChange, int, int)
+CFHANDLE(Encoder, PositionChange, int, int, int)
+
+CGET(Encoder,InputCount,int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_ENCODER)
+ TESTATTACHED
+
+ MASGN(phid.attr.encoder.numInputs)
+}
+
+CGETINDEX(Encoder,InputState,int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_ENCODER)
+ TESTATTACHED
+ TESTINDEX(phid.attr.encoder.numInputs)
+ TESTMASGN(inputState[Index], PUNK_BOOL)
+
+ MASGN(inputState[Index])
+}
+
+CGET(Encoder,EncoderCount,int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_ENCODER)
+ TESTATTACHED
+
+ MASGN(phid.attr.encoder.numEncoders)
+}
+
+CGETINDEX(Encoder,Position,int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_ENCODER)
+ TESTATTACHED
+ TESTINDEX(phid.attr.encoder.numEncoders)
+
+ MASGN(encoderPosition[Index])
+}
+CSETINDEX(Encoder,Position,int)
+ TESTPTR(phid)
+ TESTDEVICETYPE(PHIDCLASS_ENCODER)
+ TESTATTACHED
+ TESTINDEX(phid.attr.encoder.numEncoders)
+
+ if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
+ ADDNETWORKKEYINDEXED(ResetPosition, "%d", encoderPosition);
+ else
+ phid->encoderPosition[Index] = newVal;
+
+ return EPHIDGET_OK;
+}
+
+CGETINDEX(Encoder,IndexPosition,int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_ENCODER)
+ TESTATTACHED
+ TESTINDEX(phid.attr.encoder.numEncoders)
+ TESTMASGN(indexPosition[Index], PUNK_INT)
+
+ MASGN(indexPosition[Index])
+}
+
+CGETINDEX(Encoder,Enabled,int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_ENCODER)
+ TESTATTACHED
+ TESTINDEX(phid.attr.encoder.numEncoders)
+ TESTMASGN(enableStateEcho[Index], PUNK_BOOL)
+
+ MASGN(enableStateEcho[Index])
+}
+CSETINDEX(Encoder,Enabled,int)
+ TESTPTR(phid)
+ TESTDEVICETYPE(PHIDCLASS_ENCODER)
+ TESTATTACHED
+
+ //Only supported on the new 4-encoder board
+ switch(phid->phid.deviceIDSpec) {
+ case PHIDID_ENCODER_HS_4ENCODER_4INPUT:
+ TESTINDEX(phid.attr.encoder.numEncoders)
+ TESTRANGE(PFALSE, PTRUE)
+ if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
+ ADDNETWORKKEYINDEXED(Enabled, "%d", enableState);
+ else
+ SENDPACKET(Encoder, enableState[Index]);
+ return EPHIDGET_OK;
+ case PHIDID_ENCODER_1ENCODER_1INPUT:
+ case PHIDID_ENCODER_HS_1ENCODER:
+ default:
+ return EPHIDGET_UNSUPPORTED;
+ }
+
+}
+
+// === Deprecated Functions === //
+
+CGETINDEX(Encoder,EncoderPosition,int)
+ return CPhidgetEncoder_getPosition(phid, Index, pVal);
+}
+CSETINDEX(Encoder,EncoderPosition,int)
+ return CPhidgetEncoder_setPosition(phid, Index, newVal);
+}
+CGET(Encoder,NumInputs,int)
+ return CPhidgetEncoder_getInputCount(phid, pVal);
+}
+CGET(Encoder,NumEncoders,int)
+ return CPhidgetEncoder_getEncoderCount(phid, pVal);
+}
diff --git a/cphidgetencoder.h b/cphidgetencoder.h
new file mode 100644
index 0000000..c706a92
--- /dev/null
+++ b/cphidgetencoder.h
@@ -0,0 +1,121 @@
+#ifndef __CPHIDGETENCODER
+#define __CPHIDGETENCODER
+#include "cphidget.h"
+
+/** \defgroup phidenc Phidget Encoder
+ * \ingroup phidgets
+ * Calls specific to the Phidget Encoder. See the product manual for more specific API details, supported functionality, units, etc.
+ * @{
+ */
+
+DPHANDLE(Encoder)
+CHDRSTANDARD(Encoder)
+
+/**
+ * Gets the number of digital inputs supported by this board.
+ * @param phid An attached phidget encoder handle
+ * @param count The input count.
+ */
+CHDRGET(Encoder,InputCount,int *count)
+/**
+ * Gets the state of a digital input.
+ * @param phid An attached phidget encoder handle
+ * @param index The input index.
+ * @param inputState The input state. Possible values are \ref PTRUE and \ref PFALSE.
+ */
+CHDRGETINDEX(Encoder,InputState,int *inputState)
+/**
+ * Sets an input change handler. This is called when a digital input changes.
+ * @param phid An attached phidget encoder handle
+ * @param fptr Callback function pointer.
+ * @param userPtr A pointer for use by the user - this value is passed back into the callback function.
+ */
+CHDREVENTINDEX(Encoder,InputChange,int inputState)
+/**
+ * Gets the number of encoder inputs supported by this board.
+ * @param phid An attached phidget encoder handle
+ * @param count The encoder input count.
+ */
+CHDRGET(Encoder,EncoderCount,int *count)
+/**
+ * Gets the current position of an encoder.
+ * @param phid An attached phidget encoder handle
+ * @param index The encoder input index.
+ * @param position The current position
+ */
+CHDRGETINDEX(Encoder,Position,int *position)
+/**
+ * Sets the current position of an encoder.
+ * @param phid An attached phidget encoder handle
+ * @param index The encoder input index.
+ * @param position The new position
+ */
+CHDRSETINDEX(Encoder,Position,int position)
+/**
+ * Sets an encoder change handler. This is called when an encoder position changes.
+ * @param phid An attached phidget encoder handle
+ * @param fptr Callback function pointer. Note that positionChange is a relative not absolute change and time is the time
+ * in ms since the last position change event.
+ * @param userPtr A pointer for use by the user - this value is passed back into the callback function.
+ */
+CHDREVENTINDEX(Encoder,PositionChange,int time,int positionChange)
+/**
+ * Gets the position of the last index pulse, as referenced to \ref CPhidgetEncoder_getPosition.
+ * This will return EPHIDGET_UNKNOWN if there hasn't been an index event, or if the encoder doesn't support index.
+ * @param phid An attached phidget encoder handle
+ * @param index The encoder index.
+ * @param position The index position.
+ */
+CHDRGETINDEX(Encoder,IndexPosition,int *position)
+/**
+ * Gets the enabled state of an encoder. This is whether the encoder is powered or not.
+ * @param phid An attached phidget encoder handle
+ * @param index The encoder index.
+ * @param enabledState The enabled state. Possible values are \ref PTRUE and \ref PFALSE.
+ */
+CHDRGETINDEX(Encoder,Enabled,int *enabledState)
+/**
+ * Sets the enabled state of an encoder. This is whether the encoder is powered or not.
+ * @param phid An attached phidget encoder handle
+ * @param index The encoder index.
+ * @param enabledState The enabled state. Possible values are \ref PTRUE and \ref PFALSE.
+ */
+CHDRSETINDEX(Encoder,Enabled,int enabledState)
+
+#ifndef REMOVE_DEPRECATED
+DEP_CHDRGETINDEX("Deprecated - use CPhidgetEncoder_getPosition",Encoder,EncoderPosition,int *)
+DEP_CHDRSETINDEX("Deprecated - use CPhidgetEncoder_setPosition",Encoder,EncoderPosition,int)
+DEP_CHDRGET("Deprecated - use CPhidgetEncoder_getInputCount",Encoder,NumInputs,int *)
+DEP_CHDRGET("Deprecated - use CPhidgetEncoder_getEncoderCount",Encoder,NumEncoders,int *)
+#endif
+
+#ifndef EXTERNALPROTO
+#define ENCODER_MAXENCODERS 4
+#define ENCODER_MAXINPUTS 4
+struct _CPhidgetEncoder {
+ CPhidget phid;
+
+ int (CCONV *fptrInputChange) (CPhidgetEncoderHandle, void *, int, int);
+ void *fptrInputChangeptr;
+ int (CCONV *fptrPositionChange) (CPhidgetEncoderHandle, void *, int, int, int);
+ void *fptrPositionChangeptr;
+
+ unsigned char inputState[ENCODER_MAXINPUTS];
+
+ int encoderPosition[ENCODER_MAXENCODERS];
+ int encoderTimeStamp[ENCODER_MAXENCODERS];
+
+ unsigned char enableState[ENCODER_MAXENCODERS];
+ unsigned char enableStateEcho[ENCODER_MAXENCODERS];
+
+ int indexPosition[ENCODER_MAXENCODERS];
+
+ unsigned char outputPacket[8];
+ unsigned int outputPacketLen;
+
+} typedef CPhidgetEncoderInfo;
+#endif
+
+/** @} */
+
+#endif
diff --git a/cphidgetfrequencycounter.c b/cphidgetfrequencycounter.c
new file mode 100644
index 0000000..ba950dd
--- /dev/null
+++ b/cphidgetfrequencycounter.c
@@ -0,0 +1,393 @@
+#include "stdafx.h"
+#include "cphidgetfrequencycounter.h"
+#include <math.h>
+#include "cusb.h"
+#include "csocket.h"
+#include "cthread.h"
+
+// === Internal Functions === //
+
+//clearVars - sets all device variables to unknown state
+CPHIDGETCLEARVARS(FrequencyCounter)
+ int i = 0;
+
+ //initialize triggers, set data arrays to unknown
+ for (i = 0; i<FREQCOUNTER_MAXINPUTS; i++)
+ {
+ phid->timeout[i] = PUNI_INT;
+ phid->frequency[i] = PUNI_INT;
+ phid->filterEcho[i] = PHIDGET_FREQUENCYCOUNTER_FILTERTYPE_UNKNOWN;
+ phid->enabledEcho[i] = PUNI_BOOL;
+
+ phid->totalCount[i] = 0;
+ phid->totalTime[i] = 0;
+
+ phid->countsGood[i] = PFALSE;
+ }
+
+ return EPHIDGET_OK;
+}
+
+//initAfterOpen - sets up the initial state of an object, reading in packets from the device if needed
+// used during attach initialization - on every attach
+CPHIDGETINIT(FrequencyCounter)
+ int i;
+
+ TESTPTR(phid);
+
+ //initialize triggers, set data arrays to unknown
+ for (i = 0; i<phid->phid.attr.frequencycounter.numFreqInputs; i++)
+ {
+ phid->timeout[i] = 1000000; //1 second (in microseconds) - detect down to 1Hz
+
+ phid->frequency[i] = PUNK_INT;
+ phid->filterEcho[i] = PHIDGET_FREQUENCYCOUNTER_FILTERTYPE_UNKNOWN;
+ phid->enabledEcho[i] = PUNK_BOOL;
+ }
+ phid->lastPacketCount = PUNK_INT;
+
+ //issue one read
+ CPhidget_read((CPhidgetHandle)phid);
+
+ //fill in enabledState and filterType, set other things to 0
+ for (i = 0; i<phid->phid.attr.frequencycounter.numFreqInputs; i++)
+ {
+ phid->filter[i] = phid->filterEcho[i];
+ phid->enabled[i] = phid->enabledEcho[i];
+
+ phid->totalTicksSinceLastCount[i] = PUNK_INT;
+
+ phid->totalCount[i] = 0;
+ phid->totalTime[i] = 0;
+ }
+ phid->lastPacketCount = PUNK_INT;
+
+ return EPHIDGET_OK;
+}
+
+//dataInput - parses device packets
+CPHIDGETDATA(FrequencyCounter)
+ int i, packetCount;
+ int ticks, ticksAtLastCount[FREQCOUNTER_MAXINPUTS], counts[FREQCOUNTER_MAXINPUTS];
+ char error_buffer[127];
+
+ //Setup max/min values
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_FREQUENCYCOUNTER_2INPUT:
+ if(phid->phid.deviceVersion < 200)
+ {
+ ticks = buffer[0] + (buffer[1] << 8);
+
+ counts[0] = buffer[2] + (buffer[3] << 8) + (buffer[4] << 16);
+ ticksAtLastCount[0] = buffer[5] + (buffer[6] << 8);
+
+ counts[1] = buffer[7] + (buffer[8] << 8) + (buffer[9] << 16);
+ ticksAtLastCount[1] = buffer[10] + (buffer[11] << 8);
+
+ //Filter type echo
+ if(buffer[12] & FREQCOUNTER_FLAG_CH0_LOGIC)
+ phid->filterEcho[0] = PHIDGET_FREQUENCYCOUNTER_FILTERTYPE_LOGIC_LEVEL;
+ else
+ phid->filterEcho[0] = PHIDGET_FREQUENCYCOUNTER_FILTERTYPE_ZERO_CROSSING;
+ if(buffer[12] & FREQCOUNTER_FLAG_CH1_LOGIC)
+ phid->filterEcho[1] = PHIDGET_FREQUENCYCOUNTER_FILTERTYPE_LOGIC_LEVEL;
+ else
+ phid->filterEcho[1] = PHIDGET_FREQUENCYCOUNTER_FILTERTYPE_ZERO_CROSSING;
+
+ //Enabled state echo
+ if(buffer[12] & FREQCOUNTER_FLAG_CH0_ENABLE)
+ phid->enabledEcho[0] = PTRUE;
+ else
+ phid->enabledEcho[0] = PFALSE;
+ if(buffer[12] & FREQCOUNTER_FLAG_CH1_ENABLE)
+ phid->enabledEcho[1] = PTRUE;
+ else
+ phid->enabledEcho[1] = PFALSE;
+
+ packetCount = (buffer[12] & 0xF0) >> 4;
+ }
+ else
+ return EPHIDGET_UNEXPECTED;
+ break;
+ default:
+ return EPHIDGET_UNEXPECTED;
+ }
+
+ if((phid->lastPacketCount != PUNK_INT) && ((phid->lastPacketCount+1)&0x0F) != packetCount)
+ {
+ FIRE_ERROR_NOQUEUE(EEPHIDGET_PACKETLOST, "One or more data packets were lost");
+ }
+ phid->lastPacketCount = packetCount;
+
+ for(i=0;i<phid->phid.attr.frequencycounter.numFreqInputs; i++)
+ {
+ if(phid->enabledEcho[i] == PTRUE && phid->enabled[i] == PTRUE)
+ {
+ CThread_mutex_lock(&phid->resetlock);
+ phid->totalTime[i] += (ticks * FREQCOUNTER_MICROSECONDS_PER_TICK);
+ phid->totalCount[i] += counts[i];
+ CThread_mutex_unlock(&phid->resetlock);
+
+ if (counts[i] == 0)
+ {
+ //Do not accumulate if timed out
+ if (phid->totalTicksSinceLastCount[i] != PUNK_INT)
+ phid->totalTicksSinceLastCount[i] += ticks;
+
+ //only accumulate counts up to timeOut
+ if ((phid->totalTicksSinceLastCount[i] * FREQCOUNTER_MICROSECONDS_PER_TICK) > phid->timeout[i])
+ {
+ phid->frequency[i] = 0;
+
+ //Fire one event with 0 counts to indicate that the Timeout has elapsed and frequency is now 0
+ FIRE(Count, i, (phid->totalTicksSinceLastCount[i] * FREQCOUNTER_MICROSECONDS_PER_TICK), 0);
+ phid->totalTicksSinceLastCount[i] = PUNK_INT;
+ }
+ }
+ else
+ {
+ //1st count(s) since a timeout (or 1st read packet since opening)
+ //don't try to calculate frequency because we don't to the 'ticks at first count'
+ if (phid->totalTicksSinceLastCount[i] == PUNK_INT)
+ {
+ phid->totalTicksSinceLastCount[i] = ticks - ticksAtLastCount[i];
+ }
+ else
+ {
+ int countTimeSpan = (phid->totalTicksSinceLastCount[i] + ticksAtLastCount[i]) * FREQCOUNTER_MICROSECONDS_PER_TICK; //in microseconds
+ phid->frequency[i] = (double)((double)counts[i] / ((double)countTimeSpan / 1000000.0));
+
+ FIRE(Count, i, countTimeSpan, counts[i]);
+
+ phid->totalTicksSinceLastCount[i] = ticks - ticksAtLastCount[i];
+ }
+ }
+ }
+ else
+ phid->frequency[i] = PUNK_DBL;
+ }
+
+ return EPHIDGET_OK;
+}
+
+//eventsAfterOpen - sends out an event for all valid data, used during attach initialization
+CPHIDGETINITEVENTS(FrequencyCounter)
+ phid = 0;
+ return EPHIDGET_OK;
+}
+
+//Extra things to do during a free
+//This is run before the other things that free does
+int CPhidgetFrequencyCounter_free(CPhidgetHandle phidG)
+{
+ CPhidgetFrequencyCounterHandle phid = (CPhidgetFrequencyCounterHandle)phidG;
+ CThread_mutex_destroy(&phid->resetlock);
+ return EPHIDGET_OK;
+}
+
+//getPacket - used by write thread to get the next packet to send to device
+CGETPACKET_BUF(FrequencyCounter)
+
+//sendpacket - sends a packet to the device asynchronously, blocking if the 1-packet queue is full
+CSENDPACKET_BUF(FrequencyCounter)
+
+//makePacket - constructs a packet using current device state
+CMAKEPACKET(FrequencyCounter)
+ TESTPTRS(phid, buffer);
+
+ //Setup max/min values
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_FREQUENCYCOUNTER_2INPUT:
+ if(phid->phid.deviceVersion < 200)
+ {
+ buffer[0] = 0;
+ if(phid->enabled[0] == PTRUE)
+ buffer[0] |= FREQCOUNTER_FLAG_CH0_ENABLE;
+ else
+ phid->enabled[0] = PFALSE;
+ if(phid->filter[0] == PHIDGET_FREQUENCYCOUNTER_FILTERTYPE_LOGIC_LEVEL)
+ buffer[0] |= FREQCOUNTER_FLAG_CH0_LOGIC;
+ else
+ phid->filter[0] = PHIDGET_FREQUENCYCOUNTER_FILTERTYPE_ZERO_CROSSING;
+
+ if(phid->enabled[1] == PTRUE)
+ buffer[0] |= FREQCOUNTER_FLAG_CH1_ENABLE;
+ else
+ phid->enabled[1] = PFALSE;
+ if(phid->filter[1] == PHIDGET_FREQUENCYCOUNTER_FILTERTYPE_LOGIC_LEVEL)
+ buffer[0] |= FREQCOUNTER_FLAG_CH1_LOGIC;
+ else
+ phid->filter[1] = PHIDGET_FREQUENCYCOUNTER_FILTERTYPE_ZERO_CROSSING;
+ }
+ else
+ return EPHIDGET_UNEXPECTED;
+ break;
+ default:
+ return EPHIDGET_UNEXPECTED;
+ }
+ return EPHIDGET_OK;
+}
+
+// === Exported Functions === //
+
+//create and initialize a device structure
+CCREATE_EXTRA(FrequencyCounter, PHIDCLASS_FREQUENCYCOUNTER)
+ CThread_mutex_init(&phid->resetlock);
+ phid->phid.fptrFree = CPhidgetFrequencyCounter_free;
+ return EPHIDGET_OK;
+}
+
+//event setup functions
+CFHANDLE(FrequencyCounter, Count, int, int, int)
+
+CGET(FrequencyCounter,FrequencyInputCount,int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_FREQUENCYCOUNTER)
+ TESTATTACHED
+
+ MASGN(phid.attr.frequencycounter.numFreqInputs)
+}
+
+CGETINDEX(FrequencyCounter,Frequency,double)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_FREQUENCYCOUNTER)
+ TESTATTACHED
+ TESTINDEX(phid.attr.frequencycounter.numFreqInputs)
+ TESTMASGN(frequency[Index], PUNK_DBL)
+
+ MASGN(frequency[Index])
+}
+
+CGETINDEX(FrequencyCounter,TotalTime,__int64)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_FREQUENCYCOUNTER)
+ TESTATTACHED
+ TESTINDEX(phid.attr.frequencycounter.numFreqInputs)
+
+ MASGN(totalTime[Index])
+}
+
+CGETINDEX(FrequencyCounter,TotalCount,__int64)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_FREQUENCYCOUNTER)
+ TESTATTACHED
+ TESTINDEX(phid.attr.frequencycounter.numFreqInputs)
+
+ MASGN(totalCount[Index])
+}
+
+CGETINDEX(FrequencyCounter,TotalTime32,int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_FREQUENCYCOUNTER)
+ TESTATTACHED
+ TESTINDEX(phid.attr.frequencycounter.numFreqInputs)
+
+ *pVal = (int)phid->totalTime[Index]; return EPHIDGET_OK;
+}
+
+CGETINDEX(FrequencyCounter,TotalCount32,int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_FREQUENCYCOUNTER)
+ TESTATTACHED
+ TESTINDEX(phid.attr.frequencycounter.numFreqInputs)
+
+ *pVal = (int)phid->totalCount[Index]; return EPHIDGET_OK;
+}
+
+CGETINDEX(FrequencyCounter,Timeout,int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_FREQUENCYCOUNTER)
+ TESTATTACHED
+ TESTINDEX(phid.attr.frequencycounter.numFreqInputs)
+
+ MASGN(timeout[Index])
+}
+CSETINDEX(FrequencyCounter,Timeout,int)
+ TESTPTR(phid)
+ TESTDEVICETYPE(PHIDCLASS_FREQUENCYCOUNTER)
+ TESTATTACHED
+ TESTRANGE(100000, 100000000) //0.1-100 seconds
+ TESTINDEX(phid.attr.frequencycounter.numFreqInputs)
+
+ if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
+ ADDNETWORKKEYINDEXED(Timeout, "%d", timeout);
+ else
+ SENDPACKET(FrequencyCounter, timeout[Index]);
+
+ return EPHIDGET_OK;
+}
+
+CGETINDEX(FrequencyCounter,Enabled,int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_FREQUENCYCOUNTER)
+ TESTATTACHED
+ TESTINDEX(phid.attr.frequencycounter.numFreqInputs)
+ TESTMASGN(enabledEcho[Index], PUNK_BOOL)
+
+ MASGN(enabledEcho[Index])
+}
+CSETINDEX(FrequencyCounter,Enabled,int)
+ TESTPTR(phid)
+ TESTDEVICETYPE(PHIDCLASS_FREQUENCYCOUNTER)
+ TESTATTACHED
+ TESTRANGE(PFALSE, PTRUE)
+ TESTINDEX(phid.attr.frequencycounter.numFreqInputs)
+
+ if(newVal == PFALSE) phid->frequency[Index] = PUNK_DBL;
+
+ if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
+ ADDNETWORKKEYINDEXED(Enabled, "%d", enabled);
+ else
+ SENDPACKET(FrequencyCounter, enabled[Index]);
+
+ return EPHIDGET_OK;
+}
+
+CGETINDEX(FrequencyCounter,Filter,CPhidgetFrequencyCounter_FilterType)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_FREQUENCYCOUNTER)
+ TESTATTACHED
+ TESTINDEX(phid.attr.frequencycounter.numFreqInputs)
+ TESTMASGN(filterEcho[Index], PHIDGET_FREQUENCYCOUNTER_FILTERTYPE_UNKNOWN)
+
+ MASGN(filterEcho[Index])
+}
+CSETINDEX(FrequencyCounter,Filter,CPhidgetFrequencyCounter_FilterType)
+ TESTPTR(phid)
+ TESTDEVICETYPE(PHIDCLASS_FREQUENCYCOUNTER)
+ TESTATTACHED
+ TESTRANGE(PHIDGET_FREQUENCYCOUNTER_FILTERTYPE_ZERO_CROSSING, PHIDGET_FREQUENCYCOUNTER_FILTERTYPE_LOGIC_LEVEL)
+ TESTINDEX(phid.attr.frequencycounter.numFreqInputs)
+
+ if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
+ ADDNETWORKKEYINDEXED(Filter, "%d", filter);
+ else
+ SENDPACKET(FrequencyCounter, filter[Index]);
+
+ return EPHIDGET_OK;
+}
+
+PHIDGET21_API int CCONV CPhidgetFrequencyCounter_reset(CPhidgetFrequencyCounterHandle phid, int Index)
+{
+ TESTPTR(phid)
+ TESTDEVICETYPE(PHIDCLASS_FREQUENCYCOUNTER)
+ TESTATTACHED
+ TESTINDEX(phid.attr.frequencycounter.numFreqInputs)
+
+ if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
+ {
+ int newVal = phid->flip[Index]^1;
+ ADDNETWORKKEYINDEXED(Reset, "%d", flip);
+ }
+ else
+ {
+ CThread_mutex_lock(&phid->resetlock);
+ phid->totalCount[Index] = 0;
+ phid->totalTime[Index] = 0;
+ CThread_mutex_unlock(&phid->resetlock);
+ }
+
+ return EPHIDGET_OK;
+}
diff --git a/cphidgetfrequencycounter.h b/cphidgetfrequencycounter.h
new file mode 100644
index 0000000..2cefdf8
--- /dev/null
+++ b/cphidgetfrequencycounter.h
@@ -0,0 +1,154 @@
+#ifndef __CPHIDGETFREQUENCYCOUNTER
+#define __CPHIDGETFREQUENCYCOUNTER
+#include "cphidget.h"
+
+/** \defgroup phidfreq Phidget Frequency Counter
+ * \ingroup phidgets
+ * Calls specific to the Phidget Frequency Counter. See the product manual for more specific API details, supported functionality, units, etc.
+ *
+ * @{
+ */
+
+/**
+ * Filter Types supported by the frequency counter.
+ */
+typedef enum {
+ PHIDGET_FREQUENCYCOUNTER_FILTERTYPE_ZERO_CROSSING = 1, /**< Zero crossing signal filter. */
+ PHIDGET_FREQUENCYCOUNTER_FILTERTYPE_LOGIC_LEVEL, /**< Logic level signal filter. */
+ PHIDGET_FREQUENCYCOUNTER_FILTERTYPE_UNKNOWN /**< Filter type unknown. */
+} CPhidgetFrequencyCounter_FilterType;
+
+DPHANDLE(FrequencyCounter)
+CHDRSTANDARD(FrequencyCounter)
+
+/**
+ * Gets the number of inputs supported by this phidget frequency counter.
+ * @param phid An attached phidget frequency counter handle.
+ * @param count The input count.
+ */
+CHDRGET(FrequencyCounter,FrequencyInputCount,int *count)
+/**
+ * Gets the measured frequency of an input, in Hz.
+ * @param phid An attached phidget frequency counter handle.
+ * @param index The input index.
+ * @param frequency The frequency.
+ */
+CHDRGETINDEX(FrequencyCounter,Frequency,double *frequency)
+/**
+ * Gets the total time that has passed since the last reset on this input, in microseconds.
+ * @param phid An attached phidget frequency counter handle.
+ * @param index The input index.
+ * @param time The time.
+ */
+CHDRGETINDEX(FrequencyCounter,TotalTime,__int64 *time)
+/**
+ * Gets the total number of ticks that have happened since the last reset on this input.
+ * @param phid An attached phidget frequency counter handle.
+ * @param index The input index.
+ * @param count The tick count.
+ */
+CHDRGETINDEX(FrequencyCounter,TotalCount,__int64 *count)
+/**
+ * Gets the timeout value for an input, in microseconds. This controls the lowest measurable frequency.
+ * @param phid An attached phidget frequency counter handle.
+ * @param index The input index.
+ * @param timeout The timeout.
+ */
+CHDRSETINDEX(FrequencyCounter,Timeout,int timeout)
+/**
+ * Sets the timeout value for an input, in microseconds.
+ * @param phid An attached phidget frequency counter handle.
+ * @param index The input index.
+ * @param timeout The timeout.
+ */
+CHDRGETINDEX(FrequencyCounter,Timeout,int *timeout)
+/**
+ * Gets the enabled state for an input.
+ * @param phid An attached phidget frequency counter handle.
+ * @param index The input index.
+ * @param enabledState The enabled state.
+ */
+CHDRSETINDEX(FrequencyCounter,Enabled,int enabledState)
+/**
+ * Sets the enabled state for an input.
+ * @param phid An attached phidget frequency counter handle.
+ * @param index The input index.
+ * @param enabledState The enabled state.
+ */
+CHDRGETINDEX(FrequencyCounter,Enabled,int *enabledState)
+/**
+ * Gets the filter type for an input.
+ * @param phid An attached phidget frequency counter handle.
+ * @param index The input index.
+ * @param filter The filter type.
+ */
+CHDRSETINDEX(FrequencyCounter,Filter,CPhidgetFrequencyCounter_FilterType filter)
+/**
+ * Sets the filter type for an input.
+ * @param phid An attached phidget frequency counter handle.
+ * @param index The input index.
+ * @param filter The filter type.
+ */
+CHDRGETINDEX(FrequencyCounter,Filter,CPhidgetFrequencyCounter_FilterType *filter)
+/**
+ * Resets total count and total time for an input.
+ * @param phid An attached phidget frequency counter handle.
+ * @param index The input index.
+ */
+PHIDGET21_API int CCONV CPhidgetFrequencyCounter_reset(CPhidgetFrequencyCounterHandle phid, int index);
+/**
+ * Sets a count event handler. This is called when ticks have been counted on an input, or when the timeout has passed.
+ * @param phid A phidget frequency counter handle.
+ * @param fptr Callback function pointer.
+ * @param userPtr A pointer for use by the user - this value is passed back into the callback function.
+ */
+CHDREVENTINDEX(FrequencyCounter,Count,int time,int counts)
+
+#ifndef EXTERNALPROTO
+CHDRGETINDEX(FrequencyCounter,TotalTime32,int *time)
+CHDRGETINDEX(FrequencyCounter,TotalCount32,int *count)
+#define FREQCOUNTER_MAXINPUTS 2
+
+#define FREQCOUNTER_TICKS_PER_SEC 100000
+#define FREQCOUNTER_MICROSECONDS_PER_TICK (1000000 / FREQCOUNTER_TICKS_PER_SEC)
+
+//OUT packet flags
+#define FREQCOUNTER_FLAG_CH1_LOGIC 0x01
+#define FREQCOUNTER_FLAG_CH0_LOGIC 0x02
+#define FREQCOUNTER_FLAG_CH1_ENABLE 0x04
+#define FREQCOUNTER_FLAG_CH0_ENABLE 0x08
+
+struct _CPhidgetFrequencyCounter {
+ CPhidget phid;
+
+ int (CCONV *fptrCount)(CPhidgetFrequencyCounterHandle, void *, int, int, int);
+ void *fptrCountptr;
+
+ int timeout[FREQCOUNTER_MAXINPUTS]; //microseconds
+ CPhidgetFrequencyCounter_FilterType filter[FREQCOUNTER_MAXINPUTS];
+ unsigned char enabled[FREQCOUNTER_MAXINPUTS];
+
+ CPhidgetFrequencyCounter_FilterType filterEcho[FREQCOUNTER_MAXINPUTS];
+ unsigned char enabledEcho[FREQCOUNTER_MAXINPUTS];
+
+ double frequency[FREQCOUNTER_MAXINPUTS]; //Hz
+ int totalTicksSinceLastCount[FREQCOUNTER_MAXINPUTS]; //ticks
+
+ __int64 totalCount[FREQCOUNTER_MAXINPUTS];
+ __int64 totalTime[FREQCOUNTER_MAXINPUTS]; //microseconds
+
+ int flip[FREQCOUNTER_MAXINPUTS];
+ int lastPacketCount;
+
+ CThread_mutex_t resetlock; /* protects reset */
+
+ int countsGood[FREQCOUNTER_MAXINPUTS]; //for webservice
+
+ unsigned char outputPacket[8];
+ unsigned int outputPacketLen;
+} typedef CPhidgetFrequencyCounterInfo;
+#endif
+
+/** @} */
+
+#endif
diff --git a/cphidgetgeneric.c b/cphidgetgeneric.c
new file mode 100644
index 0000000..4534355
--- /dev/null
+++ b/cphidgetgeneric.c
@@ -0,0 +1,119 @@
+#include "stdafx.h"
+#include "cphidgetgeneric.h"
+#include "cusb.h"
+#include "csocket.h"
+#include "cthread.h"
+
+// === Internal Functions === //
+
+//clearVars - sets all device variables to unknown state
+CPHIDGETCLEARVARS(Generic)
+ ZEROMEM(phid->lastPacket, MAX_IN_PACKET_SIZE);
+
+ return EPHIDGET_OK;
+}
+
+//initAfterOpen - sets up the initial state of an object, reading in packets from the device if needed
+// used during attach initialization - on every attach
+CPHIDGETINIT(Generic)
+ TESTPTR(phid);
+
+ //Make sure no old writes are still pending
+ phid->outputPacketLen = 0;
+
+ ZEROMEM(phid->lastPacket, MAX_IN_PACKET_SIZE);
+
+ phid->out = phid->phid.outputReportByteLength;
+ phid->in = phid->phid.inputReportByteLength;
+
+
+#ifdef _WINDOWS
+ phid->out--;
+ phid->in--;
+#endif
+
+ return EPHIDGET_OK;
+}
+
+//dataInput - parses device packets
+CPHIDGETDATA(Generic)
+ if (length<0) return EPHIDGET_INVALIDARG;
+ TESTPTR(phid);
+ TESTPTR(buffer);
+
+#ifdef _WINDOWS
+ length--;
+#endif
+
+ FIRE(Packet, buffer, length);
+ memcpy(phid->lastPacket, buffer, length);
+
+ return EPHIDGET_OK;
+}
+
+//eventsAfterOpen - sends out an event for all valid data, used during attach initialization
+CPHIDGETINITEVENTS(Generic)
+ TESTPTR(phid);
+ return EPHIDGET_OK;
+}
+
+//getPacket - used by write thread to get the next packet to send to device
+CGETPACKET_BUF(Generic)
+
+//sendpacket - sends a packet to the device asynchronously, blocking if the 1-packet queue is full
+CSENDPACKET_BUF(Generic)
+
+// === Exported Functions === //
+
+//create and initialize a device structure
+CCREATE(Generic, PHIDCLASS_GENERIC)
+
+//event setup functions
+CFHANDLE(Generic, Packet,const unsigned char *, int)
+
+CGET(Generic,INPacketLength,int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_GENERIC)
+ TESTATTACHED
+ MASGN(in)
+}
+
+CGET(Generic,OUTPacketLength,int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_GENERIC)
+ TESTATTACHED
+ MASGN(out)
+}
+
+int CCONV
+CPhidgetGeneric_setPacket(CPhidgetGenericHandle phid, unsigned char *packet, int length)
+{
+ int ret = 0;
+
+ TESTPTR(phid)
+ TESTDEVICETYPE(PHIDCLASS_GENERIC)
+ TESTATTACHED
+
+ if(length!=phid->out)
+ return EPHIDGET_INVALIDARG;
+
+ CThread_mutex_lock(&phid->phid.writelock);
+ ret = CPhidgetGeneric_sendpacket(phid, packet);
+ CThread_mutex_unlock(&phid->phid.writelock);
+ if(ret) return ret;
+
+ return EPHIDGET_OK;
+}
+
+int CCONV
+CPhidgetGeneric_getLastPacket(CPhidgetGenericHandle phid, const unsigned char **packet, int *length)
+{
+ TESTPTRS(phid, packet)
+ TESTPTR(length)
+ TESTDEVICETYPE(PHIDCLASS_GENERIC)
+ TESTATTACHED
+
+ *packet = phid->lastPacket;
+ *length = phid->in;
+ return EPHIDGET_OK;
+}
diff --git a/cphidgetgeneric.h b/cphidgetgeneric.h
new file mode 100644
index 0000000..55fab44
--- /dev/null
+++ b/cphidgetgeneric.h
@@ -0,0 +1,35 @@
+#ifndef __CPHIDGETGENERIC
+#define __CPHIDGETGENERIC
+#include "cphidget.h"
+
+DPHANDLE(Generic)
+CHDRSTANDARD(Generic)
+
+CHDRGET(Generic,INPacketLength,int *length)
+CHDRGET(Generic,OUTPacketLength,int *length)
+
+CHDRGET(Generic,LastPacket,const unsigned char **packet, int *length)
+CHDRSET(Generic,Packet,unsigned char *packet, int length)
+CHDREVENT(Generic,Packet,const unsigned char *packet, int length)
+
+#ifndef EXTERNALPROTO
+struct _CPhidgetGeneric {
+ CPhidget phid;
+
+ int (CCONV *fptrPacket)(CPhidgetGenericHandle, void *, const unsigned char *, int);
+ void *fptrPacketptr;
+
+ unsigned char lastPacket[MAX_IN_PACKET_SIZE];
+
+ unsigned char buffer[MAX_OUT_PACKET_SIZE];
+
+ int in, out;
+
+ unsigned char outputPacket[MAX_OUT_PACKET_SIZE];
+ unsigned int outputPacketLen;
+} typedef CPhidgetGenericInfo;
+#endif
+
+/** @} */
+
+#endif
diff --git a/cphidgetgps.c b/cphidgetgps.c
new file mode 100644
index 0000000..8215107
--- /dev/null
+++ b/cphidgetgps.c
@@ -0,0 +1,586 @@
+#include "stdafx.h"
+#include "cphidgetgps.h"
+#include "cusb.h"
+#include "csocket.h"
+#include "cthread.h"
+#include <math.h>
+
+// === Internal Functions === //
+static int checkcrc(char *data, int crc);
+static int parse_NMEA_data(char *data, CPhidgetGPSInfo *phid);
+static int parse_GPS_packets(CPhidgetGPSInfo *phid);
+
+//clearVars - sets all device variables to unknown state
+CPHIDGETCLEARVARS(GPS)
+ TESTPTR(phid);
+
+ phid->fix = PUNI_BOOL;
+
+ phid->heading = PUNK_DBL;
+ phid->velocity = PUNK_DBL;
+ phid->altitude = PUNK_DBL;
+ phid->latitude = PUNK_DBL;
+ phid->longitude = PUNK_DBL;
+
+ phid->haveTime = PUNK_BOOL;
+ phid->haveDate = PUNK_BOOL;
+
+ return EPHIDGET_OK;
+}
+
+//initAfterOpen - sets up the initial state of an object, reading in packets from the device if needed
+// used during attach initialization - on every attach
+CPHIDGETINIT(GPS)
+ unsigned char buffer[8] = { 0 };
+ int readtries;
+ TESTPTR(phid);
+
+ phid->sckbuf_read=0;
+ phid->sckbuf_write=0;
+ ZEROMEM(phid->sckbuf, 256);
+
+ phid->lastFix = PUNK_BOOL;
+ phid->lastLatitude = PUNK_DBL;
+ phid->lastLongitude = PUNK_DBL;
+ phid->lastAltitude = PUNK_DBL;
+
+ phid->fix = PUNK_BOOL;
+ phid->heading = PUNK_DBL;
+ phid->velocity = PUNK_DBL;
+ phid->altitude = PUNK_DBL;
+ phid->latitude = PUNK_DBL;
+ phid->longitude = PUNK_DBL;
+
+ phid->haveTime = PUNK_BOOL;
+ phid->haveDate = PUNK_BOOL;
+
+ //clean out the NMEA sentences
+ ZEROMEM(&phid->GPSData, sizeof(NMEAData));
+
+ //Examples for sending data. buffer[0] is dataLength, other spots are data
+ // continue in multiple packets if needed. Wait for ACK between sends
+ //set factory defaults and reboot
+ /*buffer[0]=0x02;buffer[1]=0x04;buffer[2]=0x01;
+ CUSBSendPacket((CPhidgetHandle)phid, buffer);*/
+ //set 10Hz update rate
+ /*buffer[0]=0x03;buffer[1]=0x0e;buffer[2]=0x0a;buffer[3]=0x00;
+ CUSBSendPacket((CPhidgetHandle)phid, buffer);*/
+ //Get Ephemeris
+ /*buffer[0]=0x02;buffer[1]=0x30;buffer[2]=0x00;
+ CUSBSendPacket((CPhidgetHandle)phid, buffer);*/
+ //Enable WAAS
+ buffer[0]=0x03;buffer[1]=0x37;buffer[2]=0x01;buffer[2]=0x01;
+ CUSBSendPacket((CPhidgetHandle)phid, buffer);
+ //Query WAAS
+ /*buffer[0]=0x01;buffer[1]=0x38;
+ CUSBSendPacket((CPhidgetHandle)phid, buffer);*/
+
+ //read some initial data - rate is 10Hz so we shouldn't have to wait long
+ //This ensures we have recieved at least one GGA and one RMC
+ readtries = 30; //250ms
+ while((phid->fix==PUNK_BOOL || phid->haveTime==PUNK_BOOL || phid->haveDate==PUNK_BOOL) && readtries)
+ {
+ CPhidget_read((CPhidgetHandle)phid);
+ readtries--;
+ }
+ if(phid->fix==PUNK_BOOL)
+ phid->fix=PFALSE;
+
+ return EPHIDGET_OK;
+}
+
+//dataInput - parses device packets
+CPHIDGETDATA(GPS)
+ int i=0;
+
+ if (length < 0) return EPHIDGET_INVALIDARG;
+ TESTPTR(phid);
+ TESTPTR(buffer);
+
+ //LOG(PHIDGET_LOG_DEBUG, "GPS Packet size: %d", buffer[0]);
+
+ /* stick it in a buffer */
+ for (i=0; i<buffer[0]; i++)
+ {
+ phid->sckbuf[phid->sckbuf_write++] = buffer[i+1];
+ }
+ parse_GPS_packets(phid);
+
+ return EPHIDGET_OK;
+}
+
+//eventsAfterOpen - sends out an event for all valid data, used during attach initialization
+CPHIDGETINITEVENTS(GPS)
+ if(phid->fix != PUNK_BOOL)
+ FIRE(PositionFixStatusChange, phid->fix);
+ if (phid->fix == PTRUE && (phid->latitude != PUNK_DBL || phid->longitude != PUNK_DBL || phid->altitude != PUNK_DBL))
+ FIRE(PositionChange, phid->latitude, phid->longitude, phid->altitude);
+ return EPHIDGET_OK;
+}
+
+//getPacket - not used for GPS
+CGETPACKET(GPS)
+ return EPHIDGET_UNEXPECTED;
+}
+
+/* checks a CRC */
+static int checkcrc(char *data, int crc) {
+ unsigned int i=0;
+ unsigned char check=0;
+ for(i=1;i<strlen(data);i++)
+ check^=data[i];
+ if(check == crc)
+ return 0;
+ return 1;
+}
+
+/* this parses a full NMEA sentence */
+static int parse_NMEA_data(char *data, CPhidgetGPSInfo *phid) {
+ char *dataarray[50];
+ int numfields = 0;
+ int i,j,crc=0;
+ double dintpart, decpart;
+ int intpart;
+ double tempD;
+
+ //LOG(PHIDGET_LOG_DEBUG,"%s\n",data);
+
+ /* fist check CRC if there is one */
+ j = (int)strlen(data);
+ for(i=0;i<j;i++) {
+ if(data[i] == '*') {
+ crc = strtol(data+i+1,NULL,16);
+ data[i] = '\0';
+ if(checkcrc(data, crc))
+ {
+ /* This will usually be caused by blocking in an event handler, which causes some packets to be dropped.
+ Safe to ignore. */
+ LOG(PHIDGET_LOG_WARNING,"CRC Error parsing NMEA sentence.");
+ return 1;
+ }
+ break;
+ }
+ }
+
+ /* seperate out by commas */
+ dataarray[0] = data;
+ j = (int)strlen(data);
+ for(i=0;i<j;i++) {
+ if(data[i] == ',') {
+ numfields++;
+ dataarray[numfields] = data+i+1;
+ data[i] = '\0';
+ }
+ }
+
+ if(strlen(dataarray[0]) != 6)
+ {
+ LOG(PHIDGET_LOG_WARNING,"Bad sentence type.");
+ return 1;
+ }
+
+ /* find the type of sentence */
+ if(!strncmp("GGA",dataarray[0]+3,3)) {
+
+ //time: HHMMSS.milliseconds
+ if(strlen(dataarray[1]) >= 6) {
+ decpart = modf(strtod(dataarray[1], NULL), &dintpart);
+ intpart = (int)dintpart;
+ phid->GPSData.GGA.time.tm_hour = (short)(intpart/10000);
+ phid->GPSData.GGA.time.tm_min = (short)(intpart/100%100);
+ phid->GPSData.GGA.time.tm_sec = (short)(intpart%100);
+ phid->GPSData.GGA.time.tm_ms = (short)round(decpart*1000);
+ phid->haveTime = PTRUE;
+ }
+ else
+ phid->haveTime = PFALSE;
+
+ /* convert lat/long to signed decimal degree format */
+ if(strlen(dataarray[2])) {
+ tempD = (int)(strtol(dataarray[2], NULL, 10) / 100) + (strtod((dataarray[2]+2),NULL) / 60);
+ if(dataarray[3][0] == 'S')
+ phid->GPSData.GGA.latitude = -tempD;
+ else
+ phid->GPSData.GGA.latitude = tempD;
+ }
+ else
+ phid->GPSData.GGA.latitude = 0;
+
+ if(strlen(dataarray[4])) {
+ tempD = (int)(strtol(dataarray[4], NULL, 10) / 100) + (strtod((dataarray[4]+3),NULL) / 60);
+ if(dataarray[5][0] == 'W')
+ phid->GPSData.GGA.longitude = -tempD;
+ else
+ phid->GPSData.GGA.longitude = tempD;
+ }
+ else
+ phid->GPSData.GGA.longitude = 0;
+
+ phid->GPSData.GGA.fixQuality = (short)strtol(dataarray[6],NULL,10);
+ phid->GPSData.GGA.numSatellites = (short)strtol(dataarray[7],NULL,10);
+ phid->GPSData.GGA.horizontalDilution = strtod(dataarray[8],NULL);
+
+ phid->GPSData.GGA.altitude = strtod(dataarray[9],NULL);
+ phid->GPSData.GGA.heightOfGeoid = strtod(dataarray[11],NULL);
+
+ //Set local variables for getters/events
+ phid->fix = (phid->GPSData.GGA.fixQuality == 0) ? PFALSE : PTRUE;
+ if(phid->fix)
+ {
+ phid->altitude = phid->GPSData.GGA.altitude;
+ phid->latitude = phid->GPSData.GGA.latitude;
+ phid->longitude = phid->GPSData.GGA.longitude;
+ }
+ else
+ {
+ phid->altitude = PUNK_DBL;
+ phid->latitude = PUNK_DBL;
+ phid->longitude = PUNK_DBL;
+ }
+
+ //Fix status changed
+ if(phid->fix != phid->lastFix)
+ {
+ FIRE(PositionFixStatusChange, phid->fix);
+ phid->lastFix = phid->fix;
+ }
+
+ /* only sends event if the fix is valid, and position has changed a bit */
+ if (phid->fix == PTRUE
+ && (phid->latitude != phid->lastLatitude || phid->longitude != phid->lastLongitude || phid->altitude != phid->lastAltitude)
+ )
+ {
+ FIRE(PositionChange, phid->latitude, phid->longitude, phid->altitude);
+ phid->lastLatitude = phid->latitude;
+ phid->lastLongitude = phid->longitude;
+ phid->lastAltitude = phid->altitude;
+ }
+ }
+ else if(!strncmp("GSA",dataarray[0]+3,3)) {
+ phid->GPSData.GSA.mode = dataarray[1][0];
+ phid->GPSData.GSA.fixType = (short)strtol(dataarray[2],NULL,10);
+ for(i=0;i<12;i++)
+ phid->GPSData.GSA.satUsed[i] = (short)strtol(dataarray[i+3],NULL,10);
+ phid->GPSData.GSA.posnDilution = strtod(dataarray[15],NULL);
+ phid->GPSData.GSA.horizDilution = strtod(dataarray[16],NULL);
+ phid->GPSData.GSA.vertDilution = strtod(dataarray[17],NULL);
+ }
+ else if(!strncmp("GSV",dataarray[0]+3,3)) {
+ int numSentences, sentenceNumber, numSats;
+
+ numSentences = strtol(dataarray[1],NULL,10);
+ sentenceNumber = strtol(dataarray[2],NULL,10);
+ numSats = strtol(dataarray[3],NULL,10);
+
+ phid->GPSData.GSV.satsInView = (short)numSats;
+ for(i=0;i<(numSentences==sentenceNumber?numSats-(4*(numSentences-1)):4);i++) {
+ phid->GPSData.GSV.satInfo[i+((sentenceNumber-1)*4)].ID = (short)strtol(dataarray[4+(i*4)],NULL,10);
+ phid->GPSData.GSV.satInfo[i+((sentenceNumber-1)*4)].elevation = (short)strtol(dataarray[5+(i*4)],NULL,10);
+ phid->GPSData.GSV.satInfo[i+((sentenceNumber-1)*4)].azimuth = strtol(dataarray[6+(i*4)],NULL,10);
+ phid->GPSData.GSV.satInfo[i+((sentenceNumber-1)*4)].SNR = (short)strtol(dataarray[7+(i*4)],NULL,10);
+ }
+ }
+ else if(!strncmp("RMC",dataarray[0]+3,3)) {
+ if(strlen(dataarray[1])>=6) {
+ decpart = modf(strtod(dataarray[1], NULL), &dintpart);
+ intpart = (int)dintpart;
+ phid->GPSData.RMC.time.tm_hour = (short)(intpart/10000);
+ phid->GPSData.RMC.time.tm_min = (short)(intpart/100%100);
+ phid->GPSData.RMC.time.tm_sec = (short)(intpart%100);
+ phid->GPSData.RMC.time.tm_ms = (short)round(decpart*1000);
+ }
+
+ phid->GPSData.RMC.status = dataarray[2][0];
+
+ /* convert lat/long to signed decimal degree format */
+ if(strlen(dataarray[3])) {
+ tempD = (int)(strtol(dataarray[3], NULL, 10) / 100) + (strtod((dataarray[3]+2),NULL) / 60);
+ if(dataarray[4][0] == 'S')
+ phid->GPSData.RMC.latitude = -tempD;
+ else
+ phid->GPSData.RMC.latitude = tempD;
+ }
+ else
+ phid->GPSData.RMC.latitude = 0;
+
+ if(strlen(dataarray[5])) {
+ tempD = (int)(strtol(dataarray[5], NULL, 10) / 100) + (strtod((dataarray[5]+3),NULL) / 60);
+ if(dataarray[6][0] == 'W')
+ phid->GPSData.RMC.longitude = -tempD;
+ else
+ phid->GPSData.RMC.longitude = tempD;
+ }
+ else
+ phid->GPSData.RMC.longitude = 0;
+
+ phid->GPSData.RMC.speedKnots = strtod(dataarray[7],NULL);
+ phid->GPSData.RMC.heading = strtod(dataarray[8],NULL);
+
+ if(strlen(dataarray[9])>=6) {
+ intpart = strtol(dataarray[9], NULL, 10);
+ phid->GPSData.RMC.date.tm_mday = (short)(intpart/10000);
+ phid->GPSData.RMC.date.tm_mon = (short)(intpart/100%100);
+ phid->GPSData.RMC.date.tm_year = (short)(intpart%100) + 2000; //2-digit year, add 2000 years
+ phid->haveDate = PTRUE;
+ }
+ else
+ phid->haveDate = PFALSE;
+
+ tempD = strtod(dataarray[10],NULL);
+ if(dataarray[11][0] == 'W')
+ phid->GPSData.RMC.magneticVariation = -tempD;
+ else
+ phid->GPSData.RMC.magneticVariation = tempD;
+
+ phid->GPSData.RMC.mode = dataarray[12][0];
+
+ if(phid->GPSData.RMC.status == 'A')
+ {
+ phid->velocity = phid->GPSData.RMC.speedKnots * 1.852; //convert to km/h
+ phid->heading = phid->GPSData.RMC.heading;
+ }
+ else
+ {
+ phid->velocity = PUNK_DBL;
+ phid->heading = PUNK_DBL;
+ }
+ }
+ else if(!strncmp("VTG",dataarray[0]+3,3)) {
+ phid->GPSData.VTG.trueHeading = strtod(dataarray[1],NULL);
+ phid->GPSData.VTG.magneticHeading = strtod(dataarray[3],NULL);
+ phid->GPSData.VTG.speedKnots = strtod(dataarray[5],NULL);
+ phid->GPSData.VTG.speed = strtod(dataarray[7],NULL);
+ phid->GPSData.VTG.mode = dataarray[9][0];
+ }
+ else {
+ LOG(PHIDGET_LOG_INFO,"Unrecognized sentence type: %s", dataarray[0]+3);
+ }
+
+ return 0;
+}
+
+/* this parses a full sentence */
+static int parse_SkyTraq_response(unsigned char *data, CPhidgetGPSInfo *phid) {
+ int msgLength = data[3];
+ int crc = data[msgLength + 4];
+ int i, crccheck=0;
+ char buffer[256];
+
+ for(i=0;i<msgLength;i++)
+ {
+ crccheck^=data[i+4];
+ }
+ if(crc != crccheck)
+ {
+ LOG(PHIDGET_LOG_WARNING,"CRC Error parsing SkyTraq response.");
+ return -1;
+ }
+
+ switch(data[4])
+ {
+ case 0x83: //ACK
+ LOG(PHIDGET_LOG_INFO, "SkyTraq ACK: 0x%02x", data[5]);
+ break;
+ case 0x84: //NACK
+ LOG(PHIDGET_LOG_INFO, "SkyTraq NACK: 0x%02x", data[5]);
+ break;
+ default:
+ LOG(PHIDGET_LOG_INFO, "Got a SkyTraq message: 0x%02x", data[4]);
+ buffer[0]=0;
+ for(i=0;i<msgLength-1;i++)
+ {
+ if(i%8==0 && i!=0)
+ {
+ LOG(PHIDGET_LOG_INFO, "%s", buffer);
+ buffer[0]=0;
+ }
+ sprintf(buffer+strlen(buffer)," 0x%02x", data[i+5]);
+ }
+ if(buffer[0])
+ LOG(PHIDGET_LOG_INFO, "%s", buffer);
+ }
+
+ return 0;
+}
+
+/* this parses out the packets */
+static int parse_GPS_packets(CPhidgetGPSInfo *phid) {
+
+ unsigned char current_queuesize, msgsize, temp;
+ int result, i=0;
+
+ do {
+ result = 0;
+ /* Not known if packetsize is valid yet... */
+
+ /* advance read ptr to '$' or 0xa0 */
+ i=0;
+ while ((i < 255) && (phid->sckbuf_read != phid->sckbuf_write))
+ {
+ if(phid->sckbuf[phid->sckbuf_read] == '$' || phid->sckbuf[phid->sckbuf_read] == 0xa0)
+ break;
+ i++;
+ phid->sckbuf_read++;
+ }
+
+ current_queuesize = phid->sckbuf_write - phid->sckbuf_read;
+
+ //response msg from skytraq - size is in posn 3
+ if(phid->sckbuf[phid->sckbuf_read] == 0xa0)
+ {
+ unsigned char tempbuffer[256];
+ if(current_queuesize < 4)
+ break;
+ msgsize = 7 + phid->sckbuf[(unsigned char)(phid->sckbuf_read + 3)];
+ if(current_queuesize < msgsize)
+ break;
+
+ for (i = 0; i<msgsize; i++)
+ tempbuffer[i] = phid->sckbuf[phid->sckbuf_read++];
+
+ /* We know that we have at least a full sentence here... look for another */
+ result=1;
+
+ /* here we'll actually parse this sentence */
+ if(parse_SkyTraq_response(tempbuffer, phid))
+ {
+ LOG(PHIDGET_LOG_WARNING,"Error parsing SkyTraq response.");
+ }
+ }
+ else //NMEA/Other
+ {
+ char tempbuffer[256];
+ /* find the end of the sentence */
+ temp = phid->sckbuf_read;
+ msgsize = 0;
+ for (i=0; i < current_queuesize; i++,temp++)
+ {
+ if(phid->sckbuf[temp] == '\n') {
+ msgsize = i;
+ break;
+ }
+ }
+ if(!msgsize) break; //couldn't find it
+
+ for (i = 0; i<msgsize; i++)
+ tempbuffer[i] = phid->sckbuf[phid->sckbuf_read++];
+ tempbuffer[i] = 0;
+
+ /* We know that we have at least a full sentence here... look for another */
+ result=1;
+
+ //NMEA - always starts with '$GP'
+ if (current_queuesize >= 6 && tempbuffer[1] == 'G' && tempbuffer[2] == 'P')
+ {
+
+ /* here we'll actually parse this sentence */
+ if(parse_NMEA_data(tempbuffer, phid))
+ {
+ LOG(PHIDGET_LOG_WARNING,"Error parsing NMEA sentence.");
+ }
+ }
+ else //Something else that starts with a '$'
+ {
+ LOG(PHIDGET_LOG_INFO, "GPS Message: %s", tempbuffer);
+ }
+ }
+ }
+ while(result);
+
+ return 0;
+}
+
+// === Exported Functions === //
+
+//create and initialize a device structure
+CCREATE(GPS, PHIDCLASS_GPS)
+
+//event setup functions
+CFHANDLE(GPS, PositionChange, double, double, double)
+CFHANDLE(GPS, PositionFixStatusChange, int)
+
+CGET(GPS,Latitude,double)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_GPS)
+ TESTATTACHED
+ TESTMASGN(latitude, PUNK_DBL)
+
+ MASGN(latitude)
+}
+
+CGET(GPS,Longitude,double)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_GPS)
+ TESTATTACHED
+ TESTMASGN(longitude, PUNK_DBL)
+
+ MASGN(longitude)
+}
+
+CGET(GPS,Altitude,double)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_GPS)
+ TESTATTACHED
+ TESTMASGN(altitude, PUNK_DBL)
+
+ MASGN(altitude)
+}
+
+CGET(GPS,Time,GPSTime)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_GPS)
+ TESTATTACHED
+ if(phid->haveTime == PUNK_BOOL)
+ return EPHIDGET_UNKNOWNVAL;
+
+ MASGN(GPSData.GGA.time)
+}
+
+CGET(GPS,Date,GPSDate)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_GPS)
+ TESTATTACHED
+ if(phid->haveDate == PUNK_BOOL)
+ return EPHIDGET_UNKNOWNVAL;
+
+ MASGN(GPSData.RMC.date)
+}
+
+CGET(GPS,NMEAData,NMEAData)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_GPS)
+ TESTATTACHED
+
+ //Not uspported over webservice
+ if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
+ return EPHIDGET_UNSUPPORTED;
+
+ MASGN(GPSData)
+}
+
+CGET(GPS,Heading,double)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_GPS)
+ TESTATTACHED
+ TESTMASGN(heading, PUNK_DBL)
+
+ MASGN(heading)
+}
+
+CGET(GPS,Velocity,double)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_GPS)
+ TESTATTACHED
+ TESTMASGN(velocity, PUNK_DBL)
+
+ MASGN(velocity)
+}
+
+CGET(GPS,PositionFixStatus,int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_GPS)
+ TESTATTACHED
+ TESTMASGN(fix, PUNK_BOOL)
+
+ MASGN(fix)
+}
diff --git a/cphidgetgps.h b/cphidgetgps.h
new file mode 100644
index 0000000..c3fa97b
--- /dev/null
+++ b/cphidgetgps.h
@@ -0,0 +1,231 @@
+#ifndef __CPHIDGETGPS
+#define __CPHIDGETGPS
+#include "cphidget.h"
+
+/** \defgroup phidgps Phidget GPS
+ * \ingroup phidgets
+ * Calls specific to the Phidget GPS. See the product manual for more specific API details, supported functionality, units, etc.
+ * @{
+ */
+
+/**
+ * GPS Time in UTC.
+ */
+struct __GPSTime
+{
+ short tm_ms; /**< Milliseconds. */
+ short tm_sec; /**< Seconds. */
+ short tm_min; /**< Minutes. */
+ short tm_hour; /**< Hours. */
+} typedef GPSTime;
+/**
+ * GPS Date in UTC.
+ */
+struct __GPSDate
+{
+ short tm_mday; /**< Day of the month (1-31). */
+ short tm_mon; /**< Month (1-12). */
+ short tm_year; /**< Year. */
+} typedef GPSDate;
+
+/**
+ * Satellite info - used in GSV sentence.
+ */
+struct __GPSSatInfo
+{
+ short ID;
+ short elevation;
+ int azimuth;
+ short SNR;
+} typedef GPSSatInfo;
+
+/**
+ * NMEA GGA Sentence
+ */
+struct __GPGGA
+{
+ GPSTime time;
+ double latitude;
+ double longitude;
+ short fixQuality;
+ short numSatellites;
+ double horizontalDilution;
+ double altitude;
+ double heightOfGeoid;
+} typedef GPGGA;
+
+/**
+ * NMEA GSA Sentence
+ */
+struct __GPGSA
+{
+ char mode;
+ /* A = auto
+ * M = forced */
+ short fixType;
+ /* 1 = no fix
+ * 2 = 2D
+ * 3 = 3D */
+ short satUsed[12];
+ /* IDs of used sats in no real order, 0 means nothing */
+ double posnDilution;
+ double horizDilution;
+ double vertDilution;
+} typedef GPGSA;
+
+/**
+ * NMEA GSV Sentence
+ */
+struct __GPGSV
+{
+ short satsInView;
+ GPSSatInfo satInfo[12];
+} typedef GPGSV;
+
+/**
+ * NMEA RMC Sentence
+ */
+struct __GPRMC
+{
+ GPSTime time;
+ char status;
+ double latitude;
+ double longitude;
+ double speedKnots;
+ double heading;
+ GPSDate date;
+ double magneticVariation;
+ char mode;
+} typedef GPRMC;
+
+/**
+ * NMEA VTG Sentence
+ */
+struct __GPVTG
+{
+ double trueHeading;
+ double magneticHeading;
+ double speedKnots;
+ double speed; //km/hour
+ char mode;
+} typedef GPVTG;
+
+/**
+ * NMEA Data Structure. Contains a set of supported NMEA sentences.
+ */
+struct __NMEAData
+{
+ GPGGA GGA; /**< GPS Fix and position data. */
+ GPGSA GSA; /**< GPS DOP and active satellites. */
+ GPGSV GSV; /**< Detailed satellite information. */
+ GPRMC RMC; /**< Recommended minimum data. */
+ GPVTG VTG; /**< Heading and Speed over the Ground. */
+} typedef NMEAData;
+
+DPHANDLE(GPS)
+CHDRSTANDARD(GPS)
+
+/**
+ * Gets the current latitude.
+ * @param phid An attached phidget gps handle.
+ * @param latitude The latitude.
+ */
+CHDRGET(GPS,Latitude,double *latitude)
+/**
+ * Gets the current longitude.
+ * @param phid An attached phidget gps handle.
+ * @param longitude The longitude.
+ */
+CHDRGET(GPS,Longitude,double *longitude)
+/**
+ * Gets the current altitude, in meters.
+ * @param phid An attached phidget gps handle.
+ * @param altitude The altitude.
+ */
+CHDRGET(GPS,Altitude,double *altitude)
+/**
+ * Gets the current heading, in degrees.
+ * @param phid An attached phidget gps handle.
+ * @param heading The heading.
+ */
+CHDRGET(GPS,Heading,double *heading)
+/**
+ * Gets the current velocity, in km/h.
+ * @param phid An attached phidget gps handle.
+ * @param velocity The velocity.
+ */
+CHDRGET(GPS,Velocity,double *velocity)
+/**
+ * Gets the current GPS time, in UTC.
+ * @param phid An attached phidget gps handle.
+ * @param time The GPS time.
+ */
+CHDRGET(GPS,Time,GPSTime *time)
+/**
+ * Gets the current GPS date, in UTC
+ * @param phid An attached phidget gps handle.
+ * @param date The GPS date.
+ */
+CHDRGET(GPS,Date,GPSDate *date)
+/**
+ * Gets the position fix status.
+ * @param phid An attached phidget gps handle.
+ * @param fixStatus The fix status.
+ */
+CHDRGET(GPS,PositionFixStatus,int *fixStatus)
+/**
+ * Gets Raw NMEA Data. This function is only available in the C API,
+ * and cannot be used over the webservice.
+ * The NMEA data reference points to a structure which is updated
+ * dynamically as data comes in - if you wish to work with the data
+ * statically, you must make a local copy. This should be done from within
+ * a position change event handler to avoid the structure changing as
+ * you read it.
+ * @param phid An attached phidget gps handle.
+ * @param data The NMEA Data.
+ */
+CHDRGET(GPS,NMEAData,NMEAData *data)
+
+/**
+ * Sets a position change event handler. This is called when any of latitude, longitude, or altitude change.
+ * @param phid A phidget gps handle.
+ * @param fptr Callback function pointer.
+ * @param userPtr A pointer for use by the user - this value is passed back into the callback function.
+ */
+CHDREVENT(GPS,PositionChange,double latitude,double longitude,double altitude)
+/**
+ * Sets a position fix status change event handler. This is called when a position fix is aquired or lost.
+ * @param phid A phidget gps handle.
+ * @param fptr Callback function pointer.
+ * @param userPtr A pointer for use by the user - this value is passed back into the callback function.
+ */
+CHDREVENT(GPS,PositionFixStatusChange,int status)
+
+#ifndef EXTERNALPROTO
+
+struct _CPhidgetGPS {
+ CPhidget phid;
+
+ int (CCONV *fptrPositionChange)(CPhidgetGPSHandle, void *, double latitude, double longitude, double altitude);
+ void *fptrPositionChangeptr;
+ int (CCONV *fptrPositionFixStatusChange)(CPhidgetGPSHandle, void *, int status);
+ void *fptrPositionFixStatusChangeptr;
+
+ NMEAData GPSData;
+
+ double heading, velocity, altitude, latitude, longitude;
+ unsigned char fix;
+
+ unsigned char haveTime, haveDate;
+
+ double lastLongitude, lastLatitude, lastAltitude;
+ unsigned char lastFix;
+
+ unsigned char sckbuf[256];
+ unsigned char sckbuf_write, sckbuf_read;
+} typedef CPhidgetGPSInfo;
+#endif
+
+/** @} */
+
+#endif
diff --git a/cphidgetinterfacekit.c b/cphidgetinterfacekit.c
new file mode 100644
index 0000000..4eaa594
--- /dev/null
+++ b/cphidgetinterfacekit.c
@@ -0,0 +1,1426 @@
+#include "stdafx.h"
+#include "cphidgetinterfacekit.h"
+#include "cusb.h"
+#include "csocket.h"
+#include "cthread.h"
+
+// === Internal Functions === //
+
+static int CPhidgetInterfaceKit_getPacket(CPhidgetHandle, unsigned char *, unsigned int *);
+
+//clearVars - sets all device variables to unknown state
+CPHIDGETCLEARVARS(InterfaceKit)
+ int i = 0;
+
+ phid->ratiometric = PUNI_BOOL;
+ phid->ratiometricEcho = PUNK_BOOL;
+ phid->lastChangedOutput = PUNK_INT;
+ phid->fullStateEcho = PUNK_BOOL;
+ phid->ratiometricSwitching = 0;
+ phid->dataRateMin = PUNI_INT;
+ phid->dataRateMax = PUNI_INT;
+ phid->interruptRate = PUNI_INT;
+
+ for (i = 0; i<IFKIT_MAXINPUTS; i++)
+ phid->physicalState[i] = PUNI_BOOL;
+ for (i = 0; i<IFKIT_MAXSENSORS; i++)
+ {
+ phid->sensorChangeTrigger[i] = PUNI_INT;
+ phid->sensorRawValue[i] = PUNI_INT;
+ phid->sensorValue[i] = PUNI_INT;
+ phid->sensorLastValue[i] = PUNK_INT;
+ phid->dataRate[i] = PUNI_INT;
+ }
+ for (i = 0; i<IFKIT_MAXOUTPUTS; i++)
+ {
+ phid->nextOutputStates[i] = PUNK_BOOL;
+ phid->outputEchoStates[i] = PUNI_BOOL;
+ phid->outputStates[i] = PUNK_BOOL;
+ phid->changedOutputs[i] = PUNK_BOOL;
+ }
+
+ return EPHIDGET_OK;
+}
+
+//initAfterOpen - sets up the initial state of an object, reading in packets from the device if needed
+// used during attach initialization - on every attach
+CPHIDGETINIT(InterfaceKit)
+ int i = 0, j = 0;
+ int readtries = 0;
+ unsigned char buffer[8] = { 0 };
+ unsigned int len = 8;
+ int result;
+
+ TESTPTR(phid);
+
+ //init device specific attrs
+ phid->phid.awdc_enabled = FALSE;
+ phid->fullStateEcho = FALSE;
+ phid->maxDataPerPacket = phid->phid.attr.ifkit.numSensors;
+ phid->ratiometricSwitching = 0;
+ phid->lastPacketCount = -1;
+ phid->dataSinceAttach = 0;
+ switch(phid->phid.deviceIDSpec) {
+ case PHIDID_INTERFACEKIT_8_8_8:
+ if (phid->phid.deviceVersion < 900) {
+ phid->interruptRate = 16;
+ phid->dataRateMin = IFKIT_MIN_DATA_RATE/phid->interruptRate*phid->interruptRate;
+ phid->dataRateMax = 16; //actual data rate
+ }
+ if (phid->phid.deviceVersion >= 821 && phid->phid.deviceVersion < 900) {
+ phid->phid.awdc_enabled = PTRUE;
+ phid->fullStateEcho = TRUE;
+ }
+ if (phid->phid.deviceVersion >= 900 && phid->phid.deviceVersion < 1000) {
+ phid->phid.awdc_enabled = PTRUE; //To help with pre v902 bug (see firmware)
+ phid->fullStateEcho = TRUE;
+ phid->interruptRate = 8;
+ phid->dataRateMin = IFKIT_MIN_DATA_RATE/phid->interruptRate*phid->interruptRate;
+ phid->dataRateMax = 1; //actual data rate
+ phid->maxDataPerPacket = 36;
+ }
+ break;
+ case PHIDID_INTERFACEKIT_8_8_8_w_LCD:
+ if (phid->phid.deviceVersion < 200) {
+ phid->interruptRate = 16;
+ phid->dataRateMin = IFKIT_MIN_DATA_RATE/phid->interruptRate*phid->interruptRate;
+ phid->dataRateMax = 16; //actual data rate
+ }
+ if (phid->phid.deviceVersion >= 120 && phid->phid.deviceVersion < 200) {
+ phid->phid.awdc_enabled = PTRUE;
+ phid->fullStateEcho = TRUE;
+ }
+ if (phid->phid.deviceVersion >= 200 && phid->phid.deviceVersion < 300) {
+ phid->phid.awdc_enabled = PTRUE; //To help with pre v902 bug (see firmware)
+ phid->fullStateEcho = TRUE;
+ phid->interruptRate = 8;
+ phid->dataRateMin = IFKIT_MIN_DATA_RATE/phid->interruptRate*phid->interruptRate;
+ phid->dataRateMax = 1; //actual data rate
+ phid->maxDataPerPacket = 36;
+ }
+ break;
+ case PHIDID_INTERFACEKIT_2_2_2:
+ if (phid->phid.deviceVersion < 200) {
+ phid->fullStateEcho = TRUE;
+ phid->interruptRate = 8;
+ phid->dataRateMin = IFKIT_MIN_DATA_RATE/phid->interruptRate*phid->interruptRate;
+ phid->dataRateMax = 1; //actual data rate
+ phid->maxDataPerPacket = 16; //TODO: check this
+ }
+ break;
+ case PHIDID_INTERFACEKIT_0_0_4:
+ if (phid->phid.deviceVersion >= 704 && phid->phid.deviceVersion < 800)
+ phid->fullStateEcho = TRUE;
+ break;
+ case PHIDID_INTERFACEKIT_0_0_8:
+ phid->fullStateEcho = TRUE;
+ break;
+ case PHIDID_INTERFACEKIT_0_16_16:
+ if (phid->phid.deviceVersion >= 601 && phid->phid.deviceVersion < 700)
+ phid->fullStateEcho = TRUE;
+ break;
+ case PHIDID_ROTARY_TOUCH:
+ case PHIDID_LINEAR_TOUCH:
+ case PHIDID_INTERFACEKIT_0_5_7:
+ case PHIDID_INTERFACEKIT_0_8_8_w_LCD:
+ case PHIDID_INTERFACEKIT_4_8_8:
+ default:
+ break;
+ }
+
+ //initialize triggers, set data arrays to unknown
+ phid->ratiometric = PUNK_BOOL;
+ phid->ratiometricEcho = PUNK_BOOL;
+ for (j = 0; j<phid->phid.attr.ifkit.numInputs; j++)
+ phid->physicalState[j] = PUNK_BOOL;
+ for (j = 0; j<phid->phid.attr.ifkit.numSensors; j++)
+ {
+ switch(phid->phid.deviceIDSpec) {
+ case PHIDID_ROTARY_TOUCH:
+ case PHIDID_LINEAR_TOUCH:
+ //minimum change is 7-8, so we want full accuracy - 10 would not make sense
+ phid->sensorChangeTrigger[j] = 1;
+ break;
+ default:
+ phid->sensorChangeTrigger[j] = 10;
+ break;
+ }
+ //Only the new devices go into dataRate event mode by default
+ //default mode is change trigger
+ phid->eventMode[j] = EVENTMODE_CHANGETRIGGER;
+ phid->dataRate[j] = phid->interruptRate;
+ switch(phid->phid.deviceIDSpec) {
+ case PHIDID_INTERFACEKIT_8_8_8:
+ if (phid->phid.deviceVersion >= 900 && phid->phid.deviceVersion < 1000) {
+ phid->eventMode[j] = EVENTMODE_DATARATE;
+ }
+ break;
+ case PHIDID_INTERFACEKIT_8_8_8_w_LCD:
+ if (phid->phid.deviceVersion >= 200 && phid->phid.deviceVersion < 300) {
+ phid->eventMode[j] = EVENTMODE_DATARATE;
+ }
+ break;
+ case PHIDID_INTERFACEKIT_2_2_2:
+ if (phid->phid.deviceVersion < 200) {
+ phid->eventMode[j] = EVENTMODE_DATARATE;
+ }
+ break;
+ default:
+ break;
+ }
+ phid->sensorRawValue[j] = PUNK_INT;
+ phid->sensorValue[j] = PUNK_INT;
+ phid->sensorLastValue[j] = PUNK_INT;
+ phid->sensorRawValueAccumulator[j] = 0;
+ phid->sensorRawValueAccumulatorCount[j] = 0;
+ }
+ for (j = 0; j<phid->phid.attr.ifkit.numOutputs; j++)
+ {
+ phid->nextOutputStates[j] = PUNK_BOOL;
+ phid->outputEchoStates[j] = PUNK_BOOL;
+ phid->changedOutputs[j] = PFALSE;
+ }
+ phid->lastChangedOutput = 0;
+
+ //send out any initial pre-read packets
+ switch(phid->phid.deviceIDSpec) {
+ case PHIDID_ROTARY_TOUCH:
+ {
+ //performs initial calibration
+ buffer[0] = 0x01;
+ if ((result = CUSBSendPacket((CPhidgetHandle)phid, buffer)) != EPHIDGET_OK)
+ return result;
+ }
+ break;
+ case PHIDID_LINEAR_TOUCH:
+ {
+ //performs initial calibration
+ buffer[0] = 0x01;
+ if ((result = CUSBSendPacket((CPhidgetHandle)phid, buffer)) != EPHIDGET_OK)
+ return result;
+ SLEEP(100);
+ buffer[0] = 0x02;
+ if ((result = CUSBSendPacket((CPhidgetHandle)phid, buffer)) != EPHIDGET_OK)
+ return result;
+ }
+ break;
+ case PHIDID_INTERFACEKIT_4_8_8:
+ if (phid->phid.deviceVersion <= 100)
+ {
+ ZEROMEM(buffer,8);
+ LOG(PHIDGET_LOG_INFO,"Sending workaround startup packet");
+ if ((result = CUSBSendPacket((CPhidgetHandle)phid, buffer)) != EPHIDGET_OK)
+ return result;
+ }
+ break;
+ case PHIDID_INTERFACEKIT_8_8_8:
+ case PHIDID_INTERFACEKIT_8_8_8_w_LCD:
+ case PHIDID_INTERFACEKIT_2_2_2:
+ case PHIDID_INTERFACEKIT_0_0_4:
+ case PHIDID_INTERFACEKIT_0_0_8:
+ case PHIDID_INTERFACEKIT_0_16_16:
+ case PHIDID_INTERFACEKIT_0_5_7:
+ case PHIDID_INTERFACEKIT_0_8_8_w_LCD:
+ default:
+ break;
+ }
+
+ //read in device state - don't issue reads on devices that block
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_INTERFACEKIT_0_16_16:
+ case PHIDID_INTERFACEKIT_0_0_8:
+ case PHIDID_INTERFACEKIT_0_0_4:
+ if(phid->fullStateEcho)
+ CPhidget_read((CPhidgetHandle)phid);
+ break;
+ case PHIDID_INTERFACEKIT_8_8_8:
+ case PHIDID_INTERFACEKIT_8_8_8_w_LCD:
+ case PHIDID_INTERFACEKIT_2_2_2:
+ case PHIDID_INTERFACEKIT_4_8_8:
+ readtries = 4;
+ while(readtries-- > 0)
+ {
+ CPhidget_read((CPhidgetHandle)phid);
+ for (i = 0; i<phid->phid.attr.ifkit.numSensors; i++)
+ if(phid->sensorValue[i] == PUNK_INT)
+ break;
+ if(i==phid->phid.attr.ifkit.numSensors) break;
+ }
+ break;
+ case PHIDID_LINEAR_TOUCH:
+ case PHIDID_ROTARY_TOUCH:
+ CPhidget_read((CPhidgetHandle)phid); //clear any bad data...
+ CPhidget_read((CPhidgetHandle)phid);
+ break;
+ //these only send data on a change - so we have no way of knowing initial state, or even state at all, until an input changes state
+ case PHIDID_INTERFACEKIT_0_8_8_w_LCD:
+ case PHIDID_INTERFACEKIT_0_5_7:
+ default:
+ break;
+ }
+
+ //initialize outputs
+ for (j = 0; j<phid->phid.attr.ifkit.numOutputs; j++) {
+ phid->outputStates[j] = phid->outputEchoStates[j];
+ }
+
+ //send out any initial post-read packets
+ switch(phid->phid.deviceIDSpec) {
+ case PHIDID_INTERFACEKIT_8_8_8:
+ case PHIDID_INTERFACEKIT_8_8_8_w_LCD:
+ if ((phid->phid.deviceVersion < 200 && phid->phid.deviceIDSpec == PHIDID_INTERFACEKIT_8_8_8_w_LCD)
+ || (phid->phid.deviceVersion < 900 && phid->phid.deviceIDSpec == PHIDID_INTERFACEKIT_8_8_8))
+ {
+ //always turn on ratiometric because there is no way to read it's state from the device, and most
+ // sensors need ratiometric
+ // set this in post read because the outputs are set in the same packet as ratiometric, and we want to preserve their state.
+ phid->ratiometric = PTRUE;
+ if ((result = CPhidgetInterfaceKit_getPacket((CPhidgetHandle)phid, (unsigned char *)&buffer, &len)) != EPHIDGET_OK)
+ return result;
+ if ((result = CUSBSendPacket((CPhidgetHandle)phid, buffer)) != EPHIDGET_OK)
+ return result;
+ }
+ //newer versions send back their ratiometric state, and default to ratiometric enabled.
+ break;
+ case PHIDID_INTERFACEKIT_2_2_2:
+ case PHIDID_ROTARY_TOUCH:
+ case PHIDID_LINEAR_TOUCH:
+ case PHIDID_INTERFACEKIT_0_0_4:
+ case PHIDID_INTERFACEKIT_0_0_8:
+ case PHIDID_INTERFACEKIT_0_16_16:
+ case PHIDID_INTERFACEKIT_0_5_7:
+ case PHIDID_INTERFACEKIT_0_8_8_w_LCD:
+ case PHIDID_INTERFACEKIT_4_8_8:
+ default:
+ break;
+ }
+
+ return EPHIDGET_OK;
+}
+
+//dataInput - parses device packets
+CPHIDGETDATA(InterfaceKit)
+ int j = 0, i = 0, k = 0;
+
+ unsigned char outputState[IFKIT_MAXOUTPUTS], lastOutputState[IFKIT_MAXOUTPUTS];
+ unsigned char inputState[IFKIT_MAXINPUTS], lastInputState[IFKIT_MAXINPUTS];
+ int sensorValue[IFKIT_MAXSENSORS][IFKIT_MAX_DATA_PER_PACKET];
+ int sensorRawValue[IFKIT_MAXSENSORS][IFKIT_MAX_DATA_PER_PACKET];
+ int sensorDataCount[IFKIT_MAXSENSORS];
+ unsigned char ratiometricEcho = PUNK_BOOL;
+
+ if (length<0) return EPHIDGET_INVALIDARG;
+ TESTPTR(phid);
+ TESTPTR(buffer);
+
+ if(CPhidget_statusFlagIsSet(((CPhidgetHandle)phid)->status, PHIDGET_ATTACHED_FLAG))
+ if(phid->dataSinceAttach < 100)
+ phid->dataSinceAttach++;
+
+ for (j = 0; j<phid->phid.attr.ifkit.numInputs; j++)
+ {
+ inputState[j] = PUNK_BOOL;
+ lastInputState[j] = phid->physicalState[j];
+ }
+ for (j = 0; j<phid->phid.attr.ifkit.numSensors; j++)
+ {
+ for(i=0;i<IFKIT_MAX_DATA_PER_PACKET;i++)
+ {
+ sensorRawValue[j][i] = PUNK_INT;
+ sensorValue[j][i] = PUNK_INT;
+ }
+ sensorDataCount[j] = 0;
+ }
+ for (j = 0; j<phid->phid.attr.ifkit.numOutputs; j++)
+ {
+ outputState[j] = PUNK_BOOL;
+ lastOutputState[j] = phid->outputEchoStates[j];
+ }
+
+ //Parse device packets - store data locally
+ switch (phid->phid.deviceIDSpec)
+ {
+ case PHIDID_INTERFACEKIT_4_8_8:
+ //Sensors
+ sensorRawValue[0][0] = ((unsigned char)buffer[3] + ((unsigned char)buffer[2] & 0x0f) * 256);
+ sensorDataCount[0]++;
+ sensorRawValue[1][0] = ((unsigned char)buffer[1] + ((unsigned char)buffer[2] & 0xf0) * 16);
+ sensorDataCount[1]++;
+ sensorRawValue[2][0] = ((unsigned char)buffer[6] + ((unsigned char)buffer[5] & 0x0f) * 256);
+ sensorDataCount[2]++;
+ sensorRawValue[3][0] = ((unsigned char)buffer[4] + ((unsigned char)buffer[5] & 0xf0) * 16);
+ sensorDataCount[3]++;
+
+ for (i = 0; i<phid->phid.attr.ifkit.numSensors; i++)
+ sensorValue[i][0] = round((double)sensorRawValue[i][0] / 4.095);
+
+ //Inputs
+ for (i = 0, j = 0x80; i < 4; i++, j >>= 1)
+ {
+ if ((buffer[0] & j) != 0)
+ inputState[i] = PFALSE;
+ else
+ inputState[i] = PTRUE;
+ }
+ for (i = 4, j = 0x01; i < 8; i++, j <<= 1)
+ {
+ if ((buffer[0] & j) != 0)
+ inputState[i] = PFALSE;
+ else
+ inputState[i] = PTRUE;
+ }
+
+ break;
+ case PHIDID_INTERFACEKIT_0_16_16:
+ //Inputs
+ for (k = 0; k<2; k++)
+ {
+ for (i = 0, j = 0x01; i<8; i++, j <<= 1)
+ {
+ if ((buffer[k] & j) == 0)
+ inputState[i+k*8] = PFALSE;
+ else
+ inputState[i+k*8] = PTRUE;
+ }
+ }
+
+ //Outputs
+ if (phid->fullStateEcho)
+ {
+ if(phid->phid.deviceVersion == 601) //top 8 bits are flipped
+ {
+ for (i = 0, j = 0x01; i<8; i++, j <<= 1)
+ {
+ if ((buffer[2] & j) == 0)
+ outputState[i] = PFALSE;
+ else
+ outputState[i] = PTRUE;
+ }
+ for (i = 7, j = 0x01; i>=0; i--, j <<= 1)
+ {
+ if ((buffer[3] & j) == 0)
+ outputState[i+8] = PFALSE;
+ else
+ outputState[i+8] = PTRUE;
+ }
+ }
+ else
+ {
+ for (k = 0; k<2; k++)
+ {
+ for (i = 0, j = 0x01; i<8; i++, j <<= 1)
+ {
+ if ((buffer[k+2] & j) == 0)
+ outputState[i+k*8] = PFALSE;
+ else
+ outputState[i+k*8] = PTRUE;
+ }
+ }
+ }
+ }
+
+ break;
+ case PHIDID_INTERFACEKIT_8_8_8:
+ case PHIDID_INTERFACEKIT_8_8_8_w_LCD:
+ case PHIDID_INTERFACEKIT_2_2_2:
+ if ((phid->phid.deviceVersion < 200 && phid->phid.deviceIDSpec == PHIDID_INTERFACEKIT_8_8_8_w_LCD)
+ || (phid->phid.deviceVersion < 900 && phid->phid.deviceIDSpec == PHIDID_INTERFACEKIT_8_8_8))
+ {
+ //Inputs
+ for (i = 0, j = 0x01; i < phid->phid.attr.ifkit.numInputs; i++, j <<= 1)
+ {
+ if (buffer[1] & j)
+ inputState[i] = PFALSE;
+ else
+ inputState[i] = PTRUE;
+ }
+
+ //there are two types of packets
+ if (!(buffer[0] & 0x01))
+ {
+ //Sensors
+ sensorRawValue[0][0] = ((unsigned char)buffer[2] + ((unsigned char)buffer[3] & 0x0f) * 256);
+ sensorDataCount[0]++;
+ sensorRawValue[1][0] = ((unsigned char)buffer[4] + ((unsigned char)buffer[3] & 0xf0) * 16);
+ sensorDataCount[1]++;
+ sensorRawValue[2][0] = ((unsigned char)buffer[5] + ((unsigned char)buffer[6] & 0x0f) * 256);
+ sensorDataCount[2]++;
+ sensorRawValue[3][0] = ((unsigned char)buffer[7] + ((unsigned char)buffer[6] & 0xf0) * 16);
+ sensorDataCount[3]++;
+ for (i = 0; i<4; i++)
+ sensorValue[i][0] = round((double)sensorRawValue[i][0] / 4.095);
+
+ //Outputs
+ if (phid->fullStateEcho)
+ {
+ for (i = 0, j = 0x10; i<4; i++, j <<= 1)
+ {
+ if ((buffer[0] & j) == 0)
+ outputState[i] = PFALSE;
+ else
+ outputState[i] = PTRUE;
+ }
+ }
+ }
+ else
+ {
+ //Sensors
+ sensorRawValue[4][0] = ((unsigned char)buffer[2] + ((unsigned char)buffer[3] & 0x0f) * 256);
+ sensorDataCount[4]++;
+ sensorRawValue[5][0] = ((unsigned char)buffer[4] + ((unsigned char)buffer[3] & 0xf0) * 16);
+ sensorDataCount[5]++;
+ sensorRawValue[6][0] = ((unsigned char)buffer[5] + ((unsigned char)buffer[6] & 0x0f) * 256);
+ sensorDataCount[6]++;
+ sensorRawValue[7][0] = ((unsigned char)buffer[7] + ((unsigned char)buffer[6] & 0xf0) * 16);
+ sensorDataCount[7]++;
+ for (i = 4; i<8; i++)
+ sensorValue[i][0] = round((double)sensorRawValue[i][0] / 4.095);
+
+ //Outputs
+ if (phid->fullStateEcho)
+ {
+ for (i = 4, j = 0x10; i<8; i++, j <<= 1)
+ {
+ if ((buffer[0] & j) == 0)
+ outputState[i] = PFALSE;
+ else
+ outputState[i] = PTRUE;
+ }
+ }
+ }
+ break;
+ }
+ else if((phid->phid.deviceVersion >= 900 && phid->phid.deviceVersion < 1000 && phid->phid.deviceIDSpec == PHIDID_INTERFACEKIT_8_8_8)
+ || (phid->phid.deviceVersion >= 200 && phid->phid.deviceVersion < 300 && phid->phid.deviceIDSpec == PHIDID_INTERFACEKIT_8_8_8_w_LCD)
+ || (phid->phid.deviceIDSpec == PHIDID_INTERFACEKIT_2_2_2))
+ {
+ int overrunBits, overrunPtr, countPtr, packetCount, channelCount[IFKIT_MAXSENSORS], overrunCount[IFKIT_MAXSENSORS];
+ unsigned char overcurrentFlag = 0;
+ int datacount = 0;
+ int flip, bufindx;
+ char error_buffer[127];
+
+ //counters, etc.
+ packetCount = (buffer[0] >> 6) & 0x03;
+ overcurrentFlag = (buffer[0] >> 5) & 0x01;
+ ratiometricEcho = (buffer[0] >> 4) & 0x01;
+ overrunBits = buffer[0] & 0x0f;
+
+ //Inputs
+ for (i = 0, j = 0x01; i < phid->phid.attr.ifkit.numInputs; i++, j <<= 1)
+ {
+ if (buffer[1] & j)
+ inputState[i] = PFALSE;
+ else
+ inputState[i] = PTRUE;
+ }
+
+ //Outputs
+ for (i = 0, j = 0x01; i < phid->phid.attr.ifkit.numOutputs; i++, j <<= 1)
+ {
+ if ((buffer[2] & j) == 0)
+ outputState[i] = PFALSE;
+ else
+ outputState[i] = PTRUE;
+ }
+
+ //Sensors
+ //Overruns
+ overrunPtr = 3;
+ for (i = 0; i<phid->phid.attr.ifkit.numSensors; i++)
+ {
+ overrunCount[i] = 0;
+ }
+ if(overrunBits & 0x01)
+ {
+ overrunCount[0] = buffer[overrunPtr] >> 4;
+ overrunCount[1] = buffer[overrunPtr] & 0x0f;
+ overrunPtr++;
+ }
+ if(overrunBits & 0x02)
+ {
+ overrunCount[2] = buffer[overrunPtr] >> 4;
+ overrunCount[3] = buffer[overrunPtr] & 0x0f;
+ overrunPtr++;
+ }
+ if(overrunBits & 0x04)
+ {
+ overrunCount[4] = buffer[overrunPtr] >> 4;
+ overrunCount[5] = buffer[overrunPtr] & 0x0f;
+ overrunPtr++;
+ }
+ if(overrunBits & 0x08)
+ {
+ overrunCount[6] = buffer[overrunPtr] >> 4;
+ overrunCount[7] = buffer[overrunPtr] & 0x0f;
+ overrunPtr++;
+ }
+
+ //Counts
+ countPtr = overrunPtr;
+ for (i = 0; i<phid->phid.attr.ifkit.numSensors; i++)
+ {
+ if(i%2)
+ {
+ channelCount[i] = buffer[countPtr] & 0x0F;
+ countPtr++;
+ }
+ else
+ {
+ channelCount[i] = buffer[countPtr] >> 4;
+ }
+ datacount+=channelCount[i];
+ }
+
+ //Data
+ j=0;
+ flip = 0;
+ bufindx = countPtr;
+ while(datacount>0)
+ {
+ for (i = 0; i<phid->phid.attr.ifkit.numSensors; i++)
+ {
+ if(channelCount[i]>j)
+ {
+ if(!flip)
+ {
+ sensorRawValue[i][j] = ((unsigned char)buffer[bufindx] + (((unsigned char)buffer[bufindx+1] & 0xf0) << 4));
+ bufindx+=2;
+ }
+ else
+ {
+ sensorRawValue[i][j] = ((unsigned char)buffer[bufindx] + (((unsigned char)buffer[bufindx-1] & 0x0f) << 8));
+ bufindx++;
+ }
+ //compensating for resistors, etc. - on earlier versions, this was done in Firmware.
+ sensorRawValue[i][j] = round(sensorRawValue[i][j] * 1.001);
+ if(sensorRawValue[i][j] > 0xfff)
+ sensorRawValue[i][j] = 0xfff;
+ sensorValue[i][j] = round((double)sensorRawValue[i][j] / 4.095);
+ sensorDataCount[i]++;
+ flip^=0x01;
+ datacount--;
+ }
+ }
+ j++;
+ }
+ if(datacount < 0)
+ LOG(PHIDGET_LOG_DEBUG, "Datacount error");
+
+ //Send out some errors - overruns/lost packets
+ for (i = 0; i<phid->phid.attr.ifkit.numSensors; i++)
+ {
+ if(overrunCount[i])
+ {
+ if(phid->dataSinceAttach >= 10)
+ {
+ FIRE_ERROR_NOQUEUE(EEPHIDGET_OVERRUN, "Channel %d: %d sample overrun detected.", i, overrunCount[i]);
+ }
+ }
+ }
+ if((phid->lastPacketCount >= 0) && ((phid->lastPacketCount+1)&0x03) != packetCount)
+ {
+ FIRE_ERROR_NOQUEUE(EEPHIDGET_PACKETLOST, "One or more data packets were lost");
+ }
+ if(overcurrentFlag)
+ {
+ FIRE_ERROR(EEPHIDGET_OVERCURRENT, "Analog input overcurrent detected.");
+ }
+
+ phid->lastPacketCount = packetCount;
+
+ break;
+ }
+ else
+ return EPHIDGET_UNEXPECTED;
+ case PHIDID_INTERFACEKIT_0_5_7:
+ //Inputs
+ for (i = 0, j = 0x01; i<5; i++, j <<= 1)
+ {
+ if ((buffer[0] & j) == 0)
+ inputState[i] = PFALSE;
+ else
+ inputState[i] = PTRUE;
+ }
+ break;
+ case PHIDID_INTERFACEKIT_0_8_8_w_LCD:
+ //Inputs
+ for (i = 0, j = 0x01; i<8; i++, j <<= 1)
+ {
+ if ((buffer[0] & j) == 0)
+ inputState[i] = PFALSE;
+ else
+ inputState[i] = PTRUE;
+ }
+ break;
+ case PHIDID_INTERFACEKIT_0_0_4:
+ case PHIDID_INTERFACEKIT_0_0_8:
+ //Outputs
+ if (phid->fullStateEcho)
+ {
+ for (i = 0, j = 0x01; i < phid->phid.attr.ifkit.numOutputs; i++, j <<= 1)
+ {
+ if ((buffer[0] & j) == 0)
+ outputState[i] = PFALSE;
+ else
+ outputState[i] = PTRUE;
+ }
+ }
+ break;
+ case PHIDID_ROTARY_TOUCH:
+ case PHIDID_LINEAR_TOUCH:
+ //Top bit of buffer[0] indicates a touch
+ if (buffer[0] & 0x80) //touch detected
+ {
+ inputState[0] = PTRUE;
+ inputState[1] = PTRUE;
+
+ sensorRawValue[0][0] = buffer[0] & 0x7f;
+ sensorDataCount[0]++;
+ sensorValue[0][0] = (int)((double)sensorRawValue[0][0] * 7.875);
+ }
+ else //no touch detected
+ {
+ //set sensorValue back to unknown
+ phid->sensorRawValue[0] = PUNK_INT;
+ phid->sensorValue[0] = PUNK_INT;
+
+ //Touch
+ inputState[0] = PFALSE;
+
+ //Proximity
+ if (buffer[0] & 0x01)
+ inputState[1] = PTRUE;
+ else
+ inputState[1] = PFALSE;
+ }
+ break;
+ default:
+ return EPHIDGET_UNEXPECTED;
+ }
+
+ //this is set after the sensor data, so users can poll ratiometric after changing it, to know when to to read sensors.
+ if(ratiometricEcho != PUNK_BOOL)
+ {
+ if(phid->ratiometric == PUNK_BOOL)
+ phid->ratiometric = ratiometricEcho;
+
+ if(phid->ratiometricSwitching > 0 && ratiometricEcho == phid->ratiometric)
+ phid->ratiometricSwitching--;
+ if(!phid->ratiometricSwitching)
+ phid->ratiometricEcho = ratiometricEcho;
+ }
+ //Don't do any skipping unless ratiometric state is echoed back
+ else
+ {
+ if(phid->ratiometricSwitching > 0)
+ phid->ratiometricSwitching = 0;
+ }
+
+ //Make sure values are within defined range, and store to structure
+ if(!phid->ratiometricSwitching)
+ {
+ for (i = 0; i<phid->phid.attr.ifkit.numSensors; i++)
+ {
+ int rawSensorAccumulate = 0, sensorAccumulate = 0, sensorAccumulateCount = 0;
+ for(j=0; j<sensorDataCount[i]; j++)
+ {
+ if(sensorValue[i][j] != PUNK_INT && sensorRawValue[i][j] != PUNK_INT)
+ {
+ rawSensorAccumulate += sensorRawValue[i][j];
+ if(sensorValue[i][j] < 0) sensorValue[i][j] = 0;
+ if(sensorValue[i][j] > 1000) sensorValue[i][j] = 1000;
+ sensorAccumulate += sensorValue[i][j];
+ sensorAccumulateCount++;
+ }
+ }
+ if(sensorAccumulateCount > 0)
+ {
+ phid->sensorRawValue[i] = round(rawSensorAccumulate / (double)sensorAccumulateCount);
+ phid->sensorValue[i] = round(sensorAccumulate / (double)sensorAccumulateCount);
+ }
+ }
+ }
+ for (i = 0; i<phid->phid.attr.ifkit.numInputs; i++)
+ {
+ if(inputState[i] != PUNK_BOOL)
+ phid->physicalState[i] = inputState[i];
+ }
+ for (i = 0; i<phid->phid.attr.ifkit.numOutputs; i++)
+ {
+ if(outputState[i] != PUNK_BOOL)
+ {
+ phid->outputEchoStates[i] = outputState[i];
+ CThread_mutex_lock(&phid->phid.outputLock);
+ if (phid->outputStates[i] == PUNK_BOOL)
+ phid->outputStates[i] = outputState[i];
+ CThread_mutex_unlock(&phid->phid.outputLock);
+ }
+ }
+
+ //send out any events for changed data
+ //only if not switching ratiometric
+ if(!phid->ratiometricSwitching)
+ {
+ for (i = 0; i < phid->phid.attr.ifkit.numSensors; i++)
+ {
+ if(sensorDataCount[i] > 0)
+ {
+ switch(phid->eventMode[i])
+ {
+ case EVENTMODE_CHANGETRIGGER:
+ if(phid->sensorValue[i] != PUNK_INT)
+ {
+ if (abs(phid->sensorLastValue[i] - phid->sensorValue[i]) >= phid->sensorChangeTrigger[i]
+ || (phid->sensorLastValue[i] == PUNK_INT))
+ {
+ FIRE(SensorChange, i, phid->sensorValue[i]);
+ phid->sensorLastValue[i] = phid->sensorValue[i];
+ }
+ }
+ break;
+ case EVENTMODE_DATARATE:
+ {
+ //Case 1: datarate > interrupt rate, just send out all data that came in
+ if(phid->dataRate[i] <= phid->interruptRate)
+ {
+ for(j=0;j<sensorDataCount[i];j++)
+ {
+ //we still follow the changeTrigger rules
+ if (abs(phid->sensorLastValue[i] - phid->sensorValue[i]) >= phid->sensorChangeTrigger[i]
+ || (phid->sensorLastValue[i] == PUNK_INT))
+ {
+ FIRE(SensorChange, i, sensorValue[i][j]);
+ phid->sensorLastValue[i] = sensorValue[i][j];
+ }
+ }
+ }
+ //Case 2: data is sent out slower then interrupt rate, so we need to accumulate the data and send it out only sometimes.
+ else
+ {
+ int dataPerEvent = phid->dataRate[i] / phid->interruptRate;
+ phid->sensorRawValueAccumulator[i] += phid->sensorValue[i];
+ phid->sensorRawValueAccumulatorCount[i]++;
+ if(phid->sensorRawValueAccumulatorCount[i] == dataPerEvent)
+ {
+ int eventVal = round(phid->sensorRawValueAccumulator[i] / (double)phid->sensorRawValueAccumulatorCount[i]);
+ //we still follow the changeTrigger rules
+ if (abs(phid->sensorLastValue[i] - eventVal) >= phid->sensorChangeTrigger[i]
+ || (phid->sensorLastValue[i] == PUNK_INT))
+ {
+ FIRE(SensorChange, i, eventVal);
+ phid->sensorLastValue[i] = eventVal;
+ }
+ phid->sensorRawValueAccumulator[i]=0;
+ phid->sensorRawValueAccumulatorCount[i]=0;
+ }
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ }
+ for (i = 0; i < phid->phid.attr.ifkit.numInputs; i++)
+ {
+ if(phid->physicalState[i] != PUNK_BOOL && phid->physicalState[i] != lastInputState[i])
+ FIRE(InputChange, i, phid->physicalState[i]);
+ }
+ for (i = 0; i < phid->phid.attr.ifkit.numOutputs; i++)
+ {
+ if (phid->outputEchoStates[i] != PUNK_BOOL && phid->outputEchoStates[i] != lastOutputState[i])
+ FIRE(OutputChange, i, phid->outputEchoStates[i]);
+ }
+
+ return EPHIDGET_OK;
+}
+
+//eventsAfterOpen - sends out an event for all valid data, used during attach initialization
+CPHIDGETINITEVENTS(InterfaceKit)
+
+ for (i = 0; i < phid->phid.attr.ifkit.numInputs; i++)
+ {
+ if (phid->physicalState[i] != PUNK_BOOL)
+ {
+ FIRE(InputChange, i, phid->physicalState[i]);
+ }
+ }
+ for (i = 0; i < phid->phid.attr.ifkit.numOutputs; i++)
+ {
+ if (phid->outputEchoStates[i] != PUNK_BOOL)
+ {
+ FIRE(OutputChange, i, phid->outputEchoStates[i]);
+ }
+ }
+ for (i = 0; i < phid->phid.attr.ifkit.numSensors; i++)
+ {
+ if (phid->sensorValue[i] != PUNK_INT)
+ {
+ FIRE(SensorChange, i, phid->sensorValue[i]);
+ }
+ }
+
+ return EPHIDGET_OK;
+}
+
+//getPacket - used by write thread to get the next packet to send to device
+CGETPACKET(InterfaceKit)
+ int i, j, k;
+
+ CPhidgetInterfaceKitHandle phid = (CPhidgetInterfaceKitHandle)phidG;
+
+ TESTPTRS(phid, buf)
+ TESTPTR(lenp)
+
+ if (*lenp < phid->phid.outputReportByteLength)
+ return EPHIDGET_INVALIDARG;
+
+ ZEROMEM(buf, *lenp)
+
+ CThread_mutex_lock(&phid->phid.outputLock);
+
+ for (i = 0; i < phid->phid.attr.ifkit.numOutputs; i++)
+ {
+ //Checks for queued up output changes, and propagates them into the output packet
+ if(phid->changedOutputs[i]) {
+ phid->outputStates[i] = phid->nextOutputStates[i];
+ phid->changedOutputs[i] = 0;
+ phid->nextOutputStates[i] = PUNK_BOOL;
+ }
+ //set unknown outputs to false
+ if(phid->outputStates[i] == PUNK_BOOL)
+ phid->outputStates[i] = PFALSE;
+ //set output echoes to output states for non-echoing devices
+ if (!phid->fullStateEcho)
+ phid->outputEchoStates[i] = phid->outputStates[i];
+ }
+
+ //fill in the buffer and length
+ switch(phid->phid.deviceIDSpec) {
+ case PHIDID_INTERFACEKIT_4_8_8:
+ {
+ unsigned const char phid488_lookup[8] = {0x00, 0x01, 0x02, 0x03, 0x07, 0x06, 0x05, 0x04};
+ buf[0] = phid488_lookup[phid->lastChangedOutput];
+ if (phid->outputStates[phid->lastChangedOutput])
+ buf[0] |= 0x08;
+ }
+ break;
+ case PHIDID_INTERFACEKIT_0_16_16:
+ for (k = 0; k<2; k++)
+ {
+ for (i = 0, j = 1; i<8; i++, j <<= 1)
+ {
+ if (phid->outputStates[k * 8 + i])
+ buf[k] |= j;
+ }
+ }
+ break;
+ case PHIDID_INTERFACEKIT_8_8_8:
+ case PHIDID_INTERFACEKIT_8_8_8_w_LCD:
+ case PHIDID_INTERFACEKIT_2_2_2:
+ if(phid->ratiometric == PUNK_BOOL)
+ phid->ratiometric = PTRUE;
+ if ((phid->phid.deviceVersion < 200 && phid->phid.deviceIDSpec == PHIDID_INTERFACEKIT_8_8_8_w_LCD)
+ || (phid->phid.deviceVersion < 900 && phid->phid.deviceIDSpec == PHIDID_INTERFACEKIT_8_8_8))
+ {
+ for (k = 0, j = 1; k<8; k++, j <<= 1)
+ {
+ if (phid->outputStates[k])
+ buf[0] |= j;
+ }
+ buf[3] = (char)phid->ratiometric;
+ }
+ //Newer version with dataRate
+ else if((phid->phid.deviceVersion >= 900 && phid->phid.deviceVersion < 1000 && phid->phid.deviceIDSpec == PHIDID_INTERFACEKIT_8_8_8)
+ || (phid->phid.deviceVersion >= 200 && phid->phid.deviceVersion < 300 && phid->phid.deviceIDSpec == PHIDID_INTERFACEKIT_8_8_8_w_LCD)
+ || (phid->phid.deviceIDSpec == PHIDID_INTERFACEKIT_2_2_2))
+ {
+ for (k = 0, j = 1; k<phid->phid.attr.ifkit.numOutputs; k++, j <<= 1)
+ {
+ //outputs
+ if (phid->outputStates[k])
+ buf[0] |= j;
+ }
+ for (k = 0, j = 1; k<phid->phid.attr.ifkit.numSensors; k++, j <<= 1)
+ {
+ //datarate
+ int datarate = (phid->dataRate[k] > phid->interruptRate ? phid->interruptRate : phid->dataRate[k]);
+ datarate--; //so that 8ms fits in 3 bits
+ //odd ones are shifted
+ if(k%2) datarate <<= 4;
+ buf[k/2+1] |= datarate;
+ }
+ buf[k/2+1] = (char)phid->ratiometric;
+ }
+
+ break;
+ case PHIDID_INTERFACEKIT_0_0_4:
+ case PHIDID_INTERFACEKIT_0_0_8:
+ for (k = 0, j = 1; k < phid->phid.attr.ifkit.numOutputs; k++, j <<= 1)
+ {
+ if (phid->outputStates[k])
+ buf[0] |= j;
+ }
+ break;
+ case PHIDID_INTERFACEKIT_0_5_7:
+ case PHIDID_INTERFACEKIT_0_8_8_w_LCD:
+ for (i = 0, j=1; i<8; i++, j <<= 1)
+ {
+ if (phid->outputStates[i])
+ buf[0] |= j;
+ }
+ buf[7] = 0x10; /* Signal an output */
+ break;
+ case PHIDID_ROTARY_TOUCH:
+ case PHIDID_LINEAR_TOUCH:
+ break;
+ default:
+ return EPHIDGET_UNEXPECTED;
+ }
+
+ *lenp = phid->phid.outputReportByteLength;
+
+ CThread_mutex_unlock(&phid->phid.outputLock);
+
+ return EPHIDGET_OK;
+}
+
+//sendpacket - sends a packet to the device asynchronously, blocking if the 1-packet queue is full
+// adds output data to the packet in the queue if possible to combine up to numoutput calls to setoutput into one sent packet
+static int CCONV CPhidgetInterfaceKit_sendpacket(CPhidgetInterfaceKitHandle phid,
+ unsigned int Index, unsigned int newVal)
+{
+ int waitReturn;
+
+ CThread_mutex_lock(&phid->phid.writelock);
+ phid->lastChangedOutput = Index;
+
+again:
+ if (!CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_ATTACHED_FLAG))
+ {
+ CThread_mutex_unlock(&phid->phid.writelock);
+ return EPHIDGET_NOTATTACHED;
+ }
+ CThread_mutex_lock(&phid->phid.outputLock);
+ if (phid->changedOutputs[Index]) {
+ if (phid->nextOutputStates[Index] != newVal) {
+ CThread_mutex_unlock(&phid->phid.outputLock);
+ waitReturn = CThread_wait_on_event(&phid->phid.writtenEvent, 2500);
+ switch(waitReturn)
+ {
+ case WAIT_OBJECT_0:
+ break;
+ case WAIT_ABANDONED:
+ CThread_mutex_unlock(&phid->phid.writelock);
+ return EPHIDGET_UNEXPECTED;
+ case WAIT_TIMEOUT:
+ CThread_mutex_unlock(&phid->phid.writelock);
+ return EPHIDGET_TIMEOUT;
+ }
+ goto again;
+ } else {
+ CThread_mutex_unlock(&phid->phid.outputLock);
+ CThread_mutex_unlock(&phid->phid.writelock);
+ return EPHIDGET_OK;
+ }
+ } else {
+ if (phid->outputStates[Index] == newVal) {
+ CThread_mutex_unlock(&phid->phid.outputLock);
+ CThread_mutex_unlock(&phid->phid.writelock);
+ return EPHIDGET_OK;
+ }
+ phid->changedOutputs[Index] = PTRUE;
+ phid->nextOutputStates[Index] = newVal;
+ CThread_reset_event(&phid->phid.writtenEvent);
+ CThread_mutex_unlock(&phid->phid.outputLock);
+ CThread_set_event(&phid->phid.writeAvailableEvent);
+ }
+
+ //send output events for devices that don't echo
+ if (!(phid->fullStateEcho)) {
+ if (phid->outputEchoStates[Index] != (unsigned char)newVal)
+ {
+ phid->outputEchoStates[Index] = (unsigned char)newVal;
+ FIRE(OutputChange, Index, newVal);
+ }
+ }
+
+ CThread_mutex_unlock(&phid->phid.writelock);
+
+ return EPHIDGET_OK;
+}
+
+// === Exported Functions === //
+
+//create and initialize a device structure
+CCREATE(InterfaceKit, PHIDCLASS_INTERFACEKIT)
+
+//event setup functions
+CFHANDLE(InterfaceKit, InputChange, int, int)
+CFHANDLE(InterfaceKit, OutputChange, int, int)
+CFHANDLE(InterfaceKit, SensorChange, int, int)
+
+CGET(InterfaceKit, InputCount, int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_INTERFACEKIT)
+ TESTATTACHED
+
+ MASGN(phid.attr.ifkit.numInputs)
+}
+
+CGETINDEX(InterfaceKit, InputState, int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_INTERFACEKIT)
+ TESTATTACHED
+ TESTINDEX(phid.attr.ifkit.numInputs)
+ TESTMASGN(physicalState[Index], PUNK_BOOL)
+
+ MASGN(physicalState[Index])
+}
+
+CGET(InterfaceKit, OutputCount, int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_INTERFACEKIT)
+ TESTATTACHED
+
+ MASGN(phid.attr.ifkit.numOutputs)
+}
+
+CGETINDEX(InterfaceKit, OutputState, int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_INTERFACEKIT)
+ TESTATTACHED
+ TESTINDEX(phid.attr.ifkit.numOutputs)
+ TESTMASGN(outputEchoStates[Index], PUNK_BOOL)
+
+ MASGN(outputEchoStates[Index])
+}
+CSETINDEX(InterfaceKit, OutputState, int)
+ TESTPTR(phid)
+ TESTDEVICETYPE(PHIDCLASS_INTERFACEKIT)
+ TESTATTACHED
+ TESTRANGE(PFALSE, PTRUE)
+ TESTINDEX(phid.attr.ifkit.numOutputs)
+
+ if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
+ ADDNETWORKKEYINDEXED(Output, "%d", nextOutputStates);
+ else
+ return CPhidgetInterfaceKit_sendpacket(phid, Index, newVal);
+
+ return EPHIDGET_OK;
+}
+
+CGET(InterfaceKit, SensorCount, int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_INTERFACEKIT)
+ TESTATTACHED
+
+ MASGN(phid.attr.ifkit.numSensors)
+}
+
+CGETINDEX(InterfaceKit, SensorValue, int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_INTERFACEKIT)
+ TESTATTACHED
+ TESTINDEX(phid.attr.ifkit.numSensors)
+ TESTMASGN(sensorValue[Index], PUNK_INT)
+
+ MASGN(sensorValue[Index])
+}
+
+CGETINDEX(InterfaceKit, SensorRawValue, int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_INTERFACEKIT)
+ TESTATTACHED
+ TESTINDEX(phid.attr.ifkit.numSensors)
+ TESTMASGN(sensorRawValue[Index], PUNK_INT)
+
+ MASGN(sensorRawValue[Index])
+}
+
+CGETINDEX(InterfaceKit, SensorChangeTrigger, int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_INTERFACEKIT)
+ TESTATTACHED
+ TESTINDEX(phid.attr.ifkit.numSensors)
+ TESTMASGN(sensorChangeTrigger[Index], PUNK_INT)
+
+ MASGN(sensorChangeTrigger[Index])
+}
+CSETINDEX(InterfaceKit,SensorChangeTrigger,int)
+ TESTPTR(phid)
+ TESTDEVICETYPE(PHIDCLASS_INTERFACEKIT)
+ TESTATTACHED
+ TESTINDEX(phid.attr.ifkit.numSensors)
+ TESTRANGE(0, 1000)
+
+ if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
+ ADDNETWORKKEYINDEXED(Trigger, "%d", sensorChangeTrigger);
+ else
+ {
+ //setting this to 0 is usually done when data rate mode is wanted
+ if(newVal != 0)
+ phid->eventMode[Index] = EVENTMODE_CHANGETRIGGER;
+ phid->sensorChangeTrigger[Index] = newVal;
+ }
+
+ return EPHIDGET_OK;
+}
+
+CGET(InterfaceKit, Ratiometric, int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_INTERFACEKIT)
+ TESTATTACHED
+
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_INTERFACEKIT_8_8_8:
+ case PHIDID_INTERFACEKIT_8_8_8_w_LCD:
+ case PHIDID_INTERFACEKIT_2_2_2:
+ if ((phid->phid.deviceVersion < 200 && phid->phid.deviceIDSpec == PHIDID_INTERFACEKIT_8_8_8_w_LCD)
+ || (phid->phid.deviceVersion < 900 && phid->phid.deviceIDSpec == PHIDID_INTERFACEKIT_8_8_8))
+ {
+ TESTMASGN(ratiometric, PUNK_BOOL)
+ MASGN(ratiometric)
+ }
+ else if((phid->phid.deviceVersion >= 900 && phid->phid.deviceVersion < 1000 && phid->phid.deviceIDSpec == PHIDID_INTERFACEKIT_8_8_8)
+ || (phid->phid.deviceVersion >= 200 && phid->phid.deviceVersion < 300 && phid->phid.deviceIDSpec == PHIDID_INTERFACEKIT_8_8_8_w_LCD)
+ || (phid->phid.deviceIDSpec == PHIDID_INTERFACEKIT_2_2_2))
+ {
+ TESTMASGN(ratiometricEcho, PUNK_BOOL)
+ MASGN(ratiometricEcho)
+ }
+ else
+ return EPHIDGET_UNEXPECTED;
+ case PHIDID_INTERFACEKIT_0_5_7:
+ case PHIDID_INTERFACEKIT_0_8_8_w_LCD:
+ case PHIDID_INTERFACEKIT_4_8_8:
+ case PHIDID_INTERFACEKIT_0_0_4:
+ case PHIDID_INTERFACEKIT_0_0_8:
+ case PHIDID_INTERFACEKIT_0_16_16:
+ case PHIDID_ROTARY_TOUCH:
+ case PHIDID_LINEAR_TOUCH:
+ return EPHIDGET_UNSUPPORTED;
+ default:
+ return EPHIDGET_UNEXPECTED;
+ }
+}
+CSET(InterfaceKit, Ratiometric, int)
+ TESTPTR(phid)
+ TESTDEVICETYPE(PHIDCLASS_INTERFACEKIT)
+ TESTATTACHED
+
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_INTERFACEKIT_8_8_8:
+ case PHIDID_INTERFACEKIT_8_8_8_w_LCD:
+ case PHIDID_INTERFACEKIT_2_2_2:
+ TESTRANGE(PFALSE, PTRUE)
+
+ if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
+ ADDNETWORKKEY(Ratiometric, "%d", ratiometric);
+ else
+ {
+ //this just signals the write thread that a write is available
+ CThread_mutex_lock(&phid->phid.writelock);
+ CThread_mutex_lock(&phid->phid.outputLock);
+ phid->ratiometric = newVal;
+ phid->ratiometricSwitching = 2; //this causes one data packet to be skipped for devices that echo ratiometric
+ CThread_mutex_unlock(&phid->phid.outputLock);
+ CThread_set_event(&phid->phid.writeAvailableEvent);
+ CThread_mutex_unlock(&phid->phid.writelock);
+ }
+ break;
+ case PHIDID_INTERFACEKIT_0_5_7:
+ case PHIDID_INTERFACEKIT_0_8_8_w_LCD:
+ case PHIDID_INTERFACEKIT_4_8_8:
+ case PHIDID_INTERFACEKIT_0_0_4:
+ case PHIDID_INTERFACEKIT_0_0_8:
+ case PHIDID_INTERFACEKIT_0_16_16:
+ case PHIDID_ROTARY_TOUCH:
+ case PHIDID_LINEAR_TOUCH:
+ return EPHIDGET_UNSUPPORTED;
+ default:
+ return EPHIDGET_UNEXPECTED;
+ }
+
+ return EPHIDGET_OK;
+}
+
+
+CSETINDEX(InterfaceKit,DataRate,int)
+ TESTPTR(phid)
+ TESTDEVICETYPE(PHIDCLASS_INTERFACEKIT)
+ TESTATTACHED
+
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_INTERFACEKIT_8_8_8:
+ case PHIDID_INTERFACEKIT_8_8_8_w_LCD:
+ case PHIDID_INTERFACEKIT_2_2_2:
+ {
+ int i, dataPerPacket = 0;
+ TESTINDEX(phid.attr.ifkit.numSensors)
+ TESTRANGE(phid->dataRateMax, phid->dataRateMin)
+
+ //make sure it's a power of 2, or 1
+ if(newVal < phid->interruptRate)
+ {
+ int temp = phid->dataRateMax;
+ unsigned char good = FALSE;
+ while(temp <= newVal)
+ {
+ if(temp == newVal)
+ {
+ good = TRUE;
+ break;
+ }
+ temp *= 2;
+ }
+ if(!good)
+ return EPHIDGET_INVALIDARG;
+ }
+ //make sure it's divisible by interruptRate
+ else
+ {
+ if(newVal%phid->interruptRate)
+ return EPHIDGET_INVALIDARG;
+ }
+
+ //make sure we're not asking for too much data per packet
+ for(i=0;i<phid->phid.attr.ifkit.numSensors;i++)
+ {
+ if(i==Index)
+ dataPerPacket+=phid->interruptRate/newVal;
+ else
+ dataPerPacket+=phid->interruptRate/phid->dataRate[i];
+ }
+ if(dataPerPacket > phid->maxDataPerPacket)
+ {
+ return EPHIDGET_INVALIDARG;
+ }
+
+ if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
+ ADDNETWORKKEYINDEXED(DataRate, "%d", dataRate);
+ else
+ {
+ //this just signals the write thread that a write is available
+ CThread_mutex_lock(&phid->phid.writelock);
+ CThread_mutex_lock(&phid->phid.outputLock);
+ phid->eventMode[Index] = EVENTMODE_DATARATE;
+ phid->dataRate[Index] = newVal;
+ phid->sensorRawValueAccumulator[Index] = 0;
+ phid->sensorRawValueAccumulatorCount[Index] = 0;
+ CThread_mutex_unlock(&phid->phid.outputLock);
+ CThread_set_event(&phid->phid.writeAvailableEvent);
+ CThread_mutex_unlock(&phid->phid.writelock);
+ }
+ }
+ break;
+ case PHIDID_INTERFACEKIT_0_5_7:
+ case PHIDID_INTERFACEKIT_0_8_8_w_LCD:
+ case PHIDID_INTERFACEKIT_4_8_8:
+ case PHIDID_INTERFACEKIT_0_0_4:
+ case PHIDID_INTERFACEKIT_0_0_8:
+ case PHIDID_INTERFACEKIT_0_16_16:
+ case PHIDID_ROTARY_TOUCH:
+ case PHIDID_LINEAR_TOUCH:
+ return EPHIDGET_UNSUPPORTED;
+ default:
+ return EPHIDGET_UNEXPECTED;
+ }
+
+ return EPHIDGET_OK;
+}
+CGETINDEX(InterfaceKit,DataRate,int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_INTERFACEKIT)
+ TESTATTACHED
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_INTERFACEKIT_8_8_8:
+ case PHIDID_INTERFACEKIT_8_8_8_w_LCD:
+ case PHIDID_INTERFACEKIT_2_2_2:
+ TESTINDEX(phid.attr.ifkit.numSensors)
+ TESTMASGN(dataRate[Index], PUNK_INT)
+ MASGN(dataRate[Index])
+ case PHIDID_INTERFACEKIT_0_5_7:
+ case PHIDID_INTERFACEKIT_0_8_8_w_LCD:
+ case PHIDID_INTERFACEKIT_4_8_8:
+ case PHIDID_INTERFACEKIT_0_0_4:
+ case PHIDID_INTERFACEKIT_0_0_8:
+ case PHIDID_INTERFACEKIT_0_16_16:
+ case PHIDID_ROTARY_TOUCH:
+ case PHIDID_LINEAR_TOUCH:
+ return EPHIDGET_UNSUPPORTED;
+ default:
+ return EPHIDGET_UNEXPECTED;
+ }
+}
+
+CGETINDEX(InterfaceKit,DataRateMax,int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_INTERFACEKIT)
+ TESTATTACHED
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_INTERFACEKIT_8_8_8:
+ case PHIDID_INTERFACEKIT_8_8_8_w_LCD:
+ case PHIDID_INTERFACEKIT_2_2_2:
+ TESTINDEX(phid.attr.ifkit.numSensors)
+ TESTMASGN(dataRateMax, PUNK_INT)
+ MASGN(dataRateMax)
+ case PHIDID_INTERFACEKIT_0_5_7:
+ case PHIDID_INTERFACEKIT_0_8_8_w_LCD:
+ case PHIDID_INTERFACEKIT_4_8_8:
+ case PHIDID_INTERFACEKIT_0_0_4:
+ case PHIDID_INTERFACEKIT_0_0_8:
+ case PHIDID_INTERFACEKIT_0_16_16:
+ case PHIDID_ROTARY_TOUCH:
+ case PHIDID_LINEAR_TOUCH:
+ return EPHIDGET_UNSUPPORTED;
+ default:
+ return EPHIDGET_UNEXPECTED;
+ }
+}
+
+CGETINDEX(InterfaceKit,DataRateMin,int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_INTERFACEKIT)
+ TESTATTACHED
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_INTERFACEKIT_8_8_8:
+ case PHIDID_INTERFACEKIT_8_8_8_w_LCD:
+ case PHIDID_INTERFACEKIT_2_2_2:
+ TESTINDEX(phid.attr.ifkit.numSensors)
+ TESTMASGN(dataRateMin, PUNK_INT)
+ MASGN(dataRateMin)
+ case PHIDID_INTERFACEKIT_0_5_7:
+ case PHIDID_INTERFACEKIT_0_8_8_w_LCD:
+ case PHIDID_INTERFACEKIT_4_8_8:
+ case PHIDID_INTERFACEKIT_0_0_4:
+ case PHIDID_INTERFACEKIT_0_0_8:
+ case PHIDID_INTERFACEKIT_0_16_16:
+ case PHIDID_ROTARY_TOUCH:
+ case PHIDID_LINEAR_TOUCH:
+ return EPHIDGET_UNSUPPORTED;
+ default:
+ return EPHIDGET_UNEXPECTED;
+ }
+}
+
+// === Deprecated Functions === //
+
+CGET(InterfaceKit, NumInputs, int)
+ return CPhidgetInterfaceKit_getInputCount(phid, pVal);
+}
+CGET(InterfaceKit, NumOutputs, int)
+ return CPhidgetInterfaceKit_getOutputCount(phid, pVal);
+}
+CGET(InterfaceKit, NumSensors, int)
+ return CPhidgetInterfaceKit_getSensorCount(phid, pVal);
+}
diff --git a/cphidgetinterfacekit.h b/cphidgetinterfacekit.h
new file mode 100644
index 0000000..b4024cf
--- /dev/null
+++ b/cphidgetinterfacekit.h
@@ -0,0 +1,219 @@
+#ifndef __CPHIDGETINTERFACEKIT
+#define __CPHIDGETINTERFACEKIT
+#include "cphidget.h"
+
+/** \defgroup phidifkit Phidget InterfaceKit
+ * \ingroup phidgets
+ * Calls specific to the Phidget InterfaceKit. See the product manual for more specific API details, supported functionality, units, etc.
+ * @{
+ */
+
+DPHANDLE(InterfaceKit)
+CHDRSTANDARD(InterfaceKit)
+
+/**
+ * Gets the number of digital inputs supported by this board.
+ * @param phid An attached phidget interface kit handle.
+ * @param count The ditial input count.
+ */
+CHDRGET(InterfaceKit, InputCount, int *count)
+/**
+ * Gets the state of a digital input.
+ * @param phid An attached phidget interface kit handle.
+ * @param index The input index.
+ * @param inputState The input state. Possible values are \ref PTRUE and \ref PFALSE.
+ */
+CHDRGETINDEX(InterfaceKit, InputState, int *inputState)
+/**
+ * Set a digital input change handler. This is called when a digital input changes.
+ * @param phid An attached phidget interface kit handle.
+ * @param fptr Callback function pointer.
+ * @param userPtr A pointer for use by the user - this value is passed back into the callback function.
+ */
+CHDREVENTINDEX(InterfaceKit, InputChange, int inputState)
+
+/**
+ * Gets the number of digital outputs supported by this board.
+ * @param phid An attached phidget interface kit handle.
+ * @param count The output count.
+ */
+CHDRGET(InterfaceKit, OutputCount, int *count)
+/**
+ * Gets the state of a digital output.
+ * @param phid An attached phidget interface kit handle.
+ * @param index The output index.
+ * @param outputState The output state. Possible values are \ref PTRUE and \ref PFALSE.
+ */
+CHDRGETINDEX(InterfaceKit, OutputState, int *outputState)
+/**
+ * Sets the state of a digital output.
+ * @param phid An attached phidget interface kit handle.
+ * @param index The otuput index.
+ * @param outputState The output state. Possible values are \ref PTRUE and \ref PFALSE.
+ */
+CHDRSETINDEX(InterfaceKit, OutputState, int outputState)
+/**
+ * Set a digital output change handler. This is called when a digital output changes.
+ * @param phid An attached phidget interface kit handle.
+ * @param fptr Callback function pointer.
+ * @param userPtr A pointer for use by the user - this value is passed back into the callback function.
+ */
+CHDREVENTINDEX(InterfaceKit, OutputChange, int outputState)
+
+/**
+ * Gets the number of sensor (analog) inputs supported by this board.
+ * @param phid An attached phidget interface kit handle.
+ * @param count The sensor input count.
+ */
+CHDRGET(InterfaceKit, SensorCount, int *count)
+/**
+ * Gets a sensor value (0-1000).
+ * @param phid An attached phidget interface kit handle.
+ * @param index The sensor index.
+ * @param sensorValue The sensor value.
+ */
+CHDRGETINDEX(InterfaceKit, SensorValue, int *sensorValue)
+/**
+ * Gets a sensor raw value (12-bit).
+ * @param phid An attached phidget interface kit handle.
+ * @param index The sensor index.
+ * @param sensorRawValue The sensor value.
+ */
+CHDRGETINDEX(InterfaceKit, SensorRawValue, int *sensorRawValue)
+/**
+ * Set a sensor change handler. This is called when a sensor value changes by more then the change trigger.
+ * @param phid An attached phidget interface kit handle.
+ * @param fptr Callback function pointer.
+ * @param userPtr A pointer for use by the user - this value is passed back into the callback function.
+ */
+CHDREVENTINDEX(InterfaceKit, SensorChange, int sensorValue)
+/**
+ * Gets a sensor change trigger.
+ * @param phid An attached phidget interface kit handle.
+ * @param index The sensor index.
+ * @param trigger The change trigger.
+ */
+CHDRGETINDEX(InterfaceKit, SensorChangeTrigger, int *trigger)
+/**
+ * Sets a sensor change trigger.
+ * @param phid An attached phidget interface kit handle.
+ * @param index The sensor index.
+ * @param trigger The change trigger.
+ */
+CHDRSETINDEX(InterfaceKit, SensorChangeTrigger, int trigger)
+/**
+ * Gets the ratiometric state for this board.
+ * @param phid An attached phidget interface kit handle.
+ * @param ratiometric The ratiometric state. Possible values are \ref PTRUE and \ref PFALSE.
+ */
+CHDRGET(InterfaceKit, Ratiometric, int *ratiometric)
+/**
+ * Sets the ratiometric state for this board.
+ * @param phid An attached phidget interface kit handle.
+ * @param ratiometric The ratiometric state. Possible values are \ref PTRUE and \ref PFALSE.
+ */
+CHDRSET(InterfaceKit, Ratiometric, int ratiometric)
+
+//This is the event rate
+//since we're not going to run an extra thread, the accuracy of the data rate is limited by the interrupt endpoint data rate (>=8ms)
+/**
+ * Gets the Data Rate for an analog input.
+ * @param phid An attached phidget interface kit handle.
+ * @param index The sensor index.
+ * @param milliseconds Data rate in ms.
+ */
+CHDRGETINDEX(InterfaceKit, DataRate, int *milliseconds)
+/**
+ * Sets the Data Rate for an analog input.
+ * @param phid An attached phidget interface kit handle.
+ * @param index The sensor index.
+ * @param milliseconds Data rate in ms.
+ */
+CHDRSETINDEX(InterfaceKit, DataRate, int milliseconds)
+/**
+ * Gets the maximum supported data rate for an analog input
+ * @param phid An attached phidget interface kit handle.
+ * @param index The sensor index.
+ * @param max Data rate in ms.
+ */
+CHDRGETINDEX(InterfaceKit, DataRateMax, int *max)
+/**
+ * Gets the minimum supported data rate for an analog input
+ * @param phid An attached phidget interface kit handle.
+ * @param index The sensor index.
+ * @param min Data rate in ms.
+ */
+CHDRGETINDEX(InterfaceKit, DataRateMin, int *min)
+
+#ifndef REMOVE_DEPRECATED
+DEP_CHDRGET("Deprecated - use CPhidgetInterfaceKit_getInputCount",InterfaceKit, NumInputs, int *)
+DEP_CHDRGET("Deprecated - use CPhidgetInterfaceKit_getOutputCount",InterfaceKit, NumOutputs, int *)
+DEP_CHDRGET("Deprecated - use CPhidgetInterfaceKit_getSensorCount",InterfaceKit, NumSensors, int *)
+#endif
+
+#ifndef EXTERNALPROTO
+#define IFKIT_MAXINPUTS 32
+#define IFKIT_MAXOUTPUTS 32
+#define IFKIT_MAXSENSORS 8
+
+#define IFKIT_MAXSENSORCHANGE 1000 //BL: Had to check for this, might as well use a define
+
+//usually it is <=8, but could be bigger if a packet gets missed.
+#define IFKIT_MAX_DATA_PER_PACKET 16
+//in milliseconds - this is the fastest hardware rate of any device
+#define IFKIT_MAX_DATA_RATE 1
+//1 second is the longest between events that we support
+#define IFKIT_MIN_DATA_RATE 1000
+//add 200ms for timing differences (late events, etc) - should be plenty
+#define IFKIT_DATA_BUFFER_SIZE ((IFKIT_MIN_DATA_RATE + 200)/IFKIT_MAX_DATA_RATE)
+
+struct _CPhidgetInterfaceKit {
+ CPhidget phid;
+
+ int (CCONV *fptrOutputChange)(CPhidgetInterfaceKitHandle, void *, int, int);
+ int (CCONV *fptrInputChange)(CPhidgetInterfaceKitHandle, void *, int, int);
+ int (CCONV *fptrSensorChange)(CPhidgetInterfaceKitHandle, void *, int, int);
+
+ void *fptrOutputChangeptr;
+ void *fptrInputChangeptr;
+ void *fptrSensorChangeptr;
+
+ unsigned char ratiometric;
+ unsigned char ratiometricEcho;
+ unsigned char ratiometricSwitching;
+
+ // output fields all protected by outputLock
+ unsigned char outputStates[IFKIT_MAXOUTPUTS];
+ unsigned char nextOutputStates[IFKIT_MAXOUTPUTS];
+ unsigned char changedOutputs[IFKIT_MAXOUTPUTS];
+ int lastChangedOutput;
+
+ unsigned char outputEchoStates[IFKIT_MAXOUTPUTS]; // Values returned from the device
+ unsigned char physicalState[IFKIT_MAXINPUTS];
+
+ int sensorChangeTrigger[IFKIT_MAXSENSORS];
+ int sensorRawValue[IFKIT_MAXSENSORS];
+ int sensorValue[IFKIT_MAXSENSORS];
+ int sensorLastValue[IFKIT_MAXSENSORS];
+
+ int sensorRawValueAccumulator[IFKIT_MAXSENSORS];
+ int sensorRawValueAccumulatorCount[IFKIT_MAXSENSORS];
+
+ int dataRate[IFKIT_MAXSENSORS];
+ int interruptRate;
+ int dataRateMax, dataRateMin;
+
+ int lastPacketCount;
+ int maxDataPerPacket;
+
+ int dataSinceAttach;
+
+ CPhidget_EventMode eventMode[IFKIT_MAXSENSORS];
+
+ unsigned char fullStateEcho;
+} typedef CPhidgetInterfaceKitInfo;
+#endif
+
+/** @} */
+
+#endif
diff --git a/cphidgetir.c b/cphidgetir.c
new file mode 100644
index 0000000..dc58dd1
--- /dev/null
+++ b/cphidgetir.c
@@ -0,0 +1,1889 @@
+#include "stdafx.h"
+#include "cphidgetir.h"
+#include "cusb.h"
+#include "csocket.h"
+#include "cthread.h"
+#include "utils/utils.h"
+
+// === Internal Functions === //
+static int analyze_data(CPhidgetIRHandle phid, int trailgap_needed);
+static int learn_data(CPhidgetIRHandle phid);
+#define ABS(x) ((x) < 0 ? -(x) : (x))
+#define pdiff(a, b) ( ABS((a) - (b)) / (double)( ((a) + (b)) / 2.0 ) )
+
+//clearVars - sets all device variables to unknown state
+CPHIDGETCLEARVARS(IR)
+ TESTPTR(phid);
+
+ //set data to unknown
+ phid->polarity = PUNK_BOOL;
+ phid->lastCodeKnown = PFALSE;
+ phid->lastRepeat = PUNK_BOOL;
+ phid->lastLearnedCodeKnown = PFALSE;
+ phid->lastGap = PUNK_BOOL;
+
+ ZEROMEM(&phid->lastCodeInfo, sizeof(phid->lastCodeInfo));
+ ZEROMEM(&phid->lastLearnedCodeInfo, sizeof(phid->lastLearnedCodeInfo));
+
+ //reset data pointers
+ phid->dataReadPtr = 0;
+ phid->dataWritePtr = 0;
+ phid->userReadPtr = 0;
+ phid->learnReadPtr = 0;
+
+ phid->rawDataSendWSCounter = PUNK_INT;
+
+ return EPHIDGET_OK;
+}
+
+//initAfterOpen - sets up the initial state of an object, reading in packets from the device if needed
+// used during attach initialization - on every attach
+CPHIDGETINIT(IR)
+ TESTPTR(phid);
+
+ //Make sure no old writes are still pending
+ phid->outputPacketLen = 0;
+
+ //set data to unknown
+ phid->polarity = PUNK_BOOL;
+ phid->lastCodeKnown = PFALSE;
+ phid->lastRepeat = PUNK_BOOL;
+ phid->lastLearnedCodeKnown = PFALSE;
+ phid->lastGap = PUNK_BOOL;
+
+ ZEROMEM(&phid->lastCodeInfo, sizeof(phid->lastCodeInfo));
+ ZEROMEM(&phid->lastLearnedCodeInfo, sizeof(phid->lastLearnedCodeInfo));
+
+ //reset data pointers
+ phid->dataReadPtr = 0;
+ phid->dataWritePtr = 0;
+ phid->userReadPtr = 0;
+ phid->learnReadPtr = 0;
+
+ phid->delayCode = PTRUE;
+
+ #ifdef _WINDOWS
+ GetSystemTime(&phid->lastDataTime);
+ #else
+ gettimeofday(&phid->lastDataTime,NULL);
+ #endif
+
+ phid->rawDataSendWSCounter = 1;
+ ZEROMEM(&phid->rawDataSendWSKeys, sizeof(int)*100);
+
+ return EPHIDGET_OK;
+}
+
+//dataInput - parses device packets
+CPHIDGETDATA(IR)
+ int i, dataLength, us;
+ int data[IR_MAX_DATA_PER_PACKET];
+
+ if (length<0) return EPHIDGET_INVALIDARG;
+ TESTPTR(phid);
+ TESTPTR(buffer);
+
+ //Parse device packets - store data locally
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_IR:
+ if ((phid->phid.deviceVersion >= 100) && (phid->phid.deviceVersion < 200))
+ {
+ //move IR data into local storage
+ dataLength = buffer[0];
+ for(i = 1; i <= dataLength; i++)
+ {
+ us = (((buffer[i * 2 - 1] & 0x7F) << 8) + buffer[i * 2]) * 10; //us
+
+ //this means it's over the length we can measure
+ if(us >= IR_MAX_DATA_us)
+ us = PUNK_INT;
+
+ if(phid->polarity == PUNK_BOOL)
+ {
+ //first time, set it
+ phid->polarity = buffer[i * 2 - 1] & 0x80;
+
+ //if the us is not PUNK_INT, we have to add a PUNK_INT
+ //otherwise we can't recognize the first code
+ if(us != PUNK_INT)
+ {
+ phid->dataBuffer[phid->dataWritePtr] = PUNK_INT;
+
+ phid->dataWritePtr++;
+ phid->dataWritePtr &= IR_DATA_ARRAY_MASK;
+ }
+ }
+ else
+ {
+ //switch it each time
+ phid->polarity ^= 0x80;
+ }
+
+ data[i-1] = us;
+ phid->dataBuffer[phid->dataWritePtr] = us;
+
+ phid->dataWritePtr++;
+ phid->dataWritePtr &= IR_DATA_ARRAY_MASK;
+
+ //if we run into data that hasn't been read... too bad, we overwrite it and adjust the read pointer
+ if(phid->dataWritePtr == phid->dataReadPtr)
+ {
+ phid->dataReadPtr++;
+ phid->dataReadPtr &= IR_DATA_ARRAY_MASK;
+ }
+
+ //make sure it's right
+ if(phid->polarity != (buffer[i * 2 - 1] & 0x80))
+ {
+ LOG(PHIDGET_LOG_ERROR, "IR data has gotten out of sync!");
+ //invalidate the buffer
+ phid->dataReadPtr = phid->dataWritePtr;
+ phid->userReadPtr = phid->dataWritePtr;
+ phid->polarity ^= 0x80;
+ }
+ }
+ }
+ else
+ return EPHIDGET_UNEXPECTED;
+ break;
+ default:
+ return EPHIDGET_UNEXPECTED;
+ }
+
+ if(dataLength > 0)
+ {
+ #ifdef _WINDOWS
+ GetSystemTime(&phid->lastDataTime);
+ #else
+ gettimeofday(&phid->lastDataTime,NULL);
+ #endif
+ phid->delayCode = PTRUE;
+
+ //send out raw data event
+ FIRE(RawData, data, dataLength);
+
+ //analyze data
+ analyze_data(phid, PTRUE);
+ learn_data(phid);
+ }
+ else
+ {
+ #ifdef _WINDOWS
+ TIME now;
+ FILETIME nowft, oldft, resft;
+ ULARGE_INTEGER nowul, oldul, resul;
+ double duration;
+ GetSystemTime(&now);
+ SystemTimeToFileTime(&now, &nowft);
+ SystemTimeToFileTime(&phid->lastDataTime, &oldft);
+
+ nowul.HighPart = nowft.dwHighDateTime;
+ nowul.LowPart = nowft.dwLowDateTime;
+ oldul.HighPart = oldft.dwHighDateTime;
+ oldul.LowPart = oldft.dwLowDateTime;
+
+ resul.HighPart = nowul.HighPart - oldul.HighPart;
+ resul.LowPart = nowul.LowPart - oldul.LowPart;
+
+ resft.dwHighDateTime = resul.HighPart;
+ resft.dwLowDateTime = resul.LowPart;
+
+ duration = (double)(resft.dwLowDateTime/10000000.0);
+ #else
+ struct timeval now;
+ gettimeofday(&now, NULL);
+ double duration = (now.tv_sec - phid->lastDataTime.tv_sec) + (double)((now.tv_usec-phid->lastDataTime.tv_usec)/1000000.0);
+ #endif
+ if(duration > IR_MAX_GAP_LENGTH/1000000 && phid->delayCode)
+ {
+ //didn't get any data, so try and look at what we do have
+ //run this if we haven't had data for > MAX_GAP
+ analyze_data(phid, PFALSE);
+ phid->delayCode = PFALSE;
+ }
+ if(duration > 0.3) //300 ms for learning
+ {
+ //didn't get any data, so try and look at what we do have
+ learn_data(phid);
+ }
+ }
+
+ return EPHIDGET_OK;
+}
+
+//eventsAfterOpen - sends out an event for all valid data, used during attach initialization
+CPHIDGETINITEVENTS(IR)
+ TESTPTR(phid);
+ return EPHIDGET_OK;
+}
+
+//getPacket - used by write thread to get the next packet to send to device
+CGETPACKET_BUF(IR)
+
+//sendpacket - sends a packet to the device asynchronously, blocking if the 1-packet queue is full
+CSENDPACKET_BUF(IR)
+
+static int sendRAWData(CPhidgetIRHandle phid, int *data, int length, int carrier, int dutyCycle, int gap)
+{
+ unsigned char buffer[10];
+ int i, j, result;
+
+ if(length > 0xff)
+ return EPHIDGET_INVALIDARG;
+
+ CThread_mutex_lock(&phid->phid.writelock);
+
+ buffer[0] = IR_DEFINEDATA_PACKET;
+ buffer[1] = (length >> 8) & 0xff;
+ buffer[2] = length & 0xff;
+ buffer[3] = (unsigned char)round(((double)(1 / (double)carrier) * 1600000.0 - 1)); //period
+ buffer[4] = (unsigned char)round((((double)(1 / (double)carrier) * 1600000.0 - 1) * ((double)dutyCycle/100.0))); //pulse width
+ buffer[5] = (unsigned char)(round(gap/10.0) >> 8) & 0xff;
+ buffer[6] = (unsigned char)round(gap/10.0) & 0xff;
+ //can leave this out to receive while we transmit - TESTING ONLY!
+ buffer[7] = IR_STOP_RX_WHILE_TX_FLAG;
+
+ if ((result = CPhidgetIR_sendpacket(phid, buffer)) != EPHIDGET_OK)
+ {
+ CThread_mutex_unlock(&phid->phid.writelock);
+ return result;
+ }
+
+ for (i = 0; i < length; i++)
+ {
+ j = i % 8;
+ buffer[j] = data[i];
+ if (j == 7 || i == (length-1))
+ {
+ if ((result = CPhidgetIR_sendpacket(phid, buffer)) != EPHIDGET_OK)
+ {
+ CThread_mutex_unlock(&phid->phid.writelock);
+ return result;
+ }
+ }
+ }
+
+ CThread_mutex_unlock(&phid->phid.writelock);
+
+ return EPHIDGET_OK;
+}
+
+//Note that data is sent to board as 10's of us's
+#define TIME_TO_PACKET(data, length, index, us) \
+ do{ \
+ if ((index + 2) >= length) \
+ return EPHIDGET_NOMEMORY; \
+ if ((us) > 327670) \
+ return EPHIDGET_INVALIDARG; \
+ if((us) > 1270) /*1270 == 0x7f << 1*/ \
+ data[index++] = ((round((us)/10) >> 8) | 0x80); \
+ data[index++] = round((us)/10) & 0xff; \
+ *time += (us); \
+ } while(0)
+
+//returned data must start and end with pulses
+static int RawTimeDataToRawData(int *rawTimeData, int rawTimeDataLength, int *rawData, int *rawDataLength, int *time)
+{
+ int i=0, j;
+
+ for(j=0;j<rawTimeDataLength;j++)
+ {
+ TIME_TO_PACKET(rawData, *rawDataLength, i, rawTimeData[j]);
+ }
+
+ *rawDataLength = i;
+
+ return EPHIDGET_OK;
+}
+
+//returned data must start and end with pulses
+static int codeInfoToRawData(unsigned char *code, CPhidgetIR_CodeInfo codeInfo, int *rawData, int *rawDataLength, int *time, unsigned char repeat)
+{
+ int i, j, k, lastbit;
+ *time = 0;
+ //special repeat code - simple!
+ if(repeat && codeInfo.repeat[0])
+ {
+ i = 0;
+ j = 0;
+ while(codeInfo.repeat[j])
+ {
+ if(i >= *rawDataLength)
+ return EPHIDGET_NOMEMORY;
+
+ TIME_TO_PACKET(rawData, *rawDataLength, i, codeInfo.repeat[j]);
+ j++;
+ }
+ }
+ //actually do some work
+ else
+ {
+ i = 0;
+ if(codeInfo.header[0])
+ {
+ TIME_TO_PACKET(rawData, *rawDataLength, i, codeInfo.header[0]);
+ TIME_TO_PACKET(rawData, *rawDataLength, i, codeInfo.header[1]);
+ }
+
+ switch(codeInfo.encoding)
+ {
+ case PHIDGET_IR_ENCODING_SPACE:
+ case PHIDGET_IR_ENCODING_PULSE:
+ //k needs to be ie 1 for 15 bit codes, 0 for 16 bit codes, 7 for 9 bit codes...
+ //because code[0] is MSB and may have less then 8 bit, where all other elements do have 8 bits
+ for(j = codeInfo.bitCount-1, k = (8 - (codeInfo.bitCount % 8) ) % 8; j >= 0; j--, k++)
+ {
+ if(code[k/8] & (1 << (j % 8)))
+ {
+ TIME_TO_PACKET(rawData, *rawDataLength, i, codeInfo.one[0]);
+ TIME_TO_PACKET(rawData, *rawDataLength, i, codeInfo.one[1]);
+ }
+ else
+ {
+ TIME_TO_PACKET(rawData, *rawDataLength, i, codeInfo.zero[0]);
+ TIME_TO_PACKET(rawData, *rawDataLength, i, codeInfo.zero[1]);
+ }
+ }
+
+ //add trail pulse for space encoding, delete last space for pulse encoding
+ if(codeInfo.encoding == PHIDGET_IR_ENCODING_SPACE)
+ {
+ TIME_TO_PACKET(rawData, *rawDataLength, i, codeInfo.trail);
+ }
+ else
+ {
+ if(code[0] & 0x01)
+ {
+ if(codeInfo.one[1] > 1270)
+ i--;
+ i--;
+ *time -= codeInfo.one[1];
+ }
+ else
+ {
+ if(codeInfo.zero[1] > 1270)
+ i--;
+ i--;
+ *time -= codeInfo.zero[1];
+ }
+ }
+
+ break;
+ case PHIDGET_IR_ENCODING_BIPHASE:
+ case PHIDGET_IR_ENCODING_RC5:
+ case PHIDGET_IR_ENCODING_RC6:
+ //this uses space-pulse for 0 and pulse-space for 1, and has the long bit-6 (trailer bit)
+
+ //1st bit is a special case
+ j = codeInfo.bitCount-1;
+ k = (8 - (codeInfo.bitCount % 8) ) % 8;
+ if(code[k/8] & (1 << (j % 8)))
+ {
+ if(codeInfo.encoding == PHIDGET_IR_ENCODING_RC6)
+ TIME_TO_PACKET(rawData, *rawDataLength, i, codeInfo.one[0]);
+ lastbit = 1;
+ }
+ else
+ {
+ if(codeInfo.encoding != PHIDGET_IR_ENCODING_RC6)
+ TIME_TO_PACKET(rawData, *rawDataLength, i, codeInfo.zero[0]);
+ lastbit = 0;
+ }
+
+ //now do the rest of the bits - each time trough, we do the last hald of the last bit and the first half of this bit
+ for(j--, k++; j >= 0; j--, k++)
+ {
+ int bit = codeInfo.bitCount - j - 1;
+ //1
+ if(code[k/8] & (1 << (j % 8)))
+ {
+ if(lastbit)
+ {
+ if(codeInfo.encoding == PHIDGET_IR_ENCODING_RC6 && bit == 5)
+ TIME_TO_PACKET(rawData, *rawDataLength, i, codeInfo.one[1] * 2);
+ else
+ TIME_TO_PACKET(rawData, *rawDataLength, i, codeInfo.one[1]);
+
+ if(codeInfo.encoding == PHIDGET_IR_ENCODING_RC6 && bit == 4)
+ TIME_TO_PACKET(rawData, *rawDataLength, i, codeInfo.one[0] * 2);
+ else
+ TIME_TO_PACKET(rawData, *rawDataLength, i, codeInfo.one[0]);
+ }
+ else
+ {
+ if(codeInfo.encoding == PHIDGET_IR_ENCODING_RC6 && bit == 4)
+ TIME_TO_PACKET(rawData, *rawDataLength, i, codeInfo.zero[1] + codeInfo.one[0] * 2);
+ else if(codeInfo.encoding == PHIDGET_IR_ENCODING_RC6 && bit == 5)
+ TIME_TO_PACKET(rawData, *rawDataLength, i, codeInfo.zero[1] * 2 + codeInfo.one[0]);
+ else
+ TIME_TO_PACKET(rawData, *rawDataLength, i, codeInfo.zero[1] + codeInfo.one[0]);
+ }
+
+ lastbit = 1;
+ }
+ //0
+ else
+ {
+ if(lastbit)
+ {
+ if(codeInfo.encoding == PHIDGET_IR_ENCODING_RC6 && bit == 4)
+ TIME_TO_PACKET(rawData, *rawDataLength, i, codeInfo.one[1] + codeInfo.zero[0] * 2);
+ else if(codeInfo.encoding == PHIDGET_IR_ENCODING_RC6 && bit == 5)
+ TIME_TO_PACKET(rawData, *rawDataLength, i, codeInfo.one[1] * 2 + codeInfo.zero[0]);
+ else
+ TIME_TO_PACKET(rawData, *rawDataLength, i, codeInfo.one[1] + codeInfo.zero[0]);
+ }
+ else
+ {
+ if(codeInfo.encoding == PHIDGET_IR_ENCODING_RC6 && bit == 5)
+ TIME_TO_PACKET(rawData, *rawDataLength, i, codeInfo.zero[1] * 2);
+ else
+ TIME_TO_PACKET(rawData, *rawDataLength, i, codeInfo.zero[1]);
+
+ if(codeInfo.encoding == PHIDGET_IR_ENCODING_RC6 && bit == 4)
+ TIME_TO_PACKET(rawData, *rawDataLength, i, codeInfo.zero[0] * 2);
+ else
+ TIME_TO_PACKET(rawData, *rawDataLength, i, codeInfo.zero[0]);
+ }
+
+ lastbit = 0;
+ }
+ }
+
+ //finish up the data stream if we need to add a last pulse
+ if(lastbit && codeInfo.encoding != PHIDGET_IR_ENCODING_RC6)
+ TIME_TO_PACKET(rawData, *rawDataLength, i, codeInfo.one[1]);
+ if(!lastbit && codeInfo.encoding == PHIDGET_IR_ENCODING_RC6)
+ TIME_TO_PACKET(rawData, *rawDataLength, i, codeInfo.zero[1]);
+
+ break;
+ //case PHIDGET_IR_ENCODING_RAW:
+ case PHIDGET_IR_ENCODING_UNKNOWN:
+ default:
+ return EPHIDGET_INVALIDARG;
+ }
+ }
+
+ *rawDataLength = i;
+
+ return EPHIDGET_OK;
+}
+
+static int CCONV_CDECL compare_int(const void *arg1, const void *arg2 )
+{
+ int *int1 = (int *)arg1;
+ int *int2 = (int *)arg2;
+ return *int1 - *int2;
+}
+
+//figure out the different times and their average values
+//we'll need to use max error (30%?)
+//we're going to keep track of average diff, and when we find a diff > 5xAvg, or > 20% switch to next section
+//must have at least a 10% difference between lengths
+//also if we find too many different times, error
+static int get_times(int *timesin, int incount, int *timesout, int *timesoutcount, int *outcount)
+{
+ int edge = 0, i = 0, j = 0, k = 0;
+ double avgDiff = 0, diffSum = 0;
+ for (i = 1; i < incount; i++)
+ {
+ double diff = pdiff(timesin[i], timesin[i-1]);
+
+ if (((avgDiff > 0) && (diff > (avgDiff * 10.0)) && diff > 0.1) || diff > 0.2)
+ {
+ //we've found a boundary
+ //find average of all lower values
+ double avg = 0;
+ for (j = edge; j < i; j++)
+ avg += timesin[j];
+ avg /= (double)(i - edge);
+ timesout[k] = round(avg);
+ timesoutcount[k++] = (i - edge);
+
+ if((k+1) > *outcount)
+ return EPHIDGET_OUTOFBOUNDS;
+
+ edge = i;
+ diffSum = 0;
+ avgDiff = 0;
+ }
+ else
+ {
+ diffSum += diff;
+ avgDiff = diffSum / (i - edge);
+ }
+ }
+ //get the last section...
+ avgDiff = 0;
+ for (j = edge; j < incount; j++)
+ avgDiff += timesin[j];
+ avgDiff /= (double)(incount - edge);
+ timesoutcount[k] = (incount - edge);
+ timesout[k++] = round(avgDiff);
+
+ *outcount = k;
+ return EPHIDGET_OK;
+}
+
+#define COUNT_TIMES(highlow, index) \
+ if(highlow##s[index] == data[i] || !highlow##s[index]) \
+ { \
+ highlow##s[index] = data[i]; \
+ highlow##Counts[index]++; \
+ if(highlow##count < index+1) \
+ highlow##count=index+1; \
+ continue; \
+ }
+
+#define ORDER_TIMES(highlow, index) \
+ if(highlow##s[index+1] && (highlow##s[index+1] < highlow##s[index])) \
+ { \
+ int temp = highlow##Counts[index]; \
+ highlow##Counts[index] = highlow##Counts[index+1]; \
+ highlow##Counts[index+1] = temp; \
+ temp = highlow##s[index]; \
+ highlow##s[index] = highlow##s[index+1]; \
+ highlow##s[index+1] = temp; \
+ }
+
+//we can count on data having at most two high and two low lengths (except for RC-6)
+//the first entry in data is a pulse, and the last is a pulse
+//outlength will be in bits, but it should be specified in bytes (array size)
+static int decode_data(int *data, int inlength, unsigned char *decoded_data, int *outlength, CPhidgetIR_CodeInfoHandle codeInfo)
+{
+ int i, highcount = 0, lowcount = 0, bitcount = 0, j = 0, n = 0;
+ //room for 4
+ int highs[5] = {0, 0, 0, 0, 0}, highCounts[5] = {0, 0, 0, 0, 0}, lows[5] = {0, 0, 0, 0, 0}, lowCounts[5] = {0, 0, 0, 0, 0};
+ unsigned char decode_temp[IR_MAX_CODE_DATA_LENGTH];
+
+
+ ZEROMEM(decode_temp, IR_MAX_CODE_DATA_LENGTH);
+ //get the numbers - only allow up to four each of high/low!!
+ for(i = 0; i < inlength; i++)
+ {
+ if(!(i%2))
+ {
+ COUNT_TIMES(high, 0)
+ COUNT_TIMES(high, 1)
+ COUNT_TIMES(high, 2)
+ COUNT_TIMES(high, 3)
+
+ goto errorexit;
+ }
+ else
+ {
+ COUNT_TIMES(low, 0)
+ COUNT_TIMES(low, 1)
+ COUNT_TIMES(low, 2)
+ COUNT_TIMES(low, 3)
+
+ goto errorexit;
+ }
+
+ //LOG(PHIDGET_LOG_DEBUG, "%07d,",data[i]);
+ }
+
+ //this sorts them
+ for(i = 0; i < 5; i++)
+ {
+ ORDER_TIMES(high, 0)
+ ORDER_TIMES(high, 1)
+ ORDER_TIMES(high, 2)
+ ORDER_TIMES(high, 3)
+ ORDER_TIMES(low, 0)
+ ORDER_TIMES(low, 1)
+ ORDER_TIMES(low, 2)
+ ORDER_TIMES(low, 3)
+ }
+ //sanity checks
+ if(lowcount == 0 || highcount == 0)
+ goto errorexit;
+
+ //figure out the encoding
+ //Bi-phase
+ //either one high or two highs and one is twice the other (10% error)
+ //and either one low or two lows and one is twice the other (10% error)
+ //make sure that lows and highs are same length (30% error)
+ if
+ (
+ (
+ (highcount == 1) &&
+ (lowcount == 1) &&
+ (pdiff(highs[0], lows[0]) < 0.3)
+ ) ||
+ (
+ (highcount == 1) &&
+ (lowcount >= 2) &&
+ (pdiff(highs[0], lows[0]) < 0.3) &&
+ (pdiff(lows[1] / 2.0, lows[0]) < 0.1)
+ ) ||
+ (
+ (highcount >= 2) &&
+ (lowcount == 1) &&
+ (pdiff(highs[0], lows[0]) < 0.3) &&
+ (pdiff(highs[1] / 2.0, highs[0]) < 0.1)
+ ) ||
+ (
+ (highcount >= 2) &&
+ (lowcount >= 2) &&
+ (pdiff(highs[0], lows[0]) < 0.3) &&
+ (pdiff(highs[1], lows[1]) < 0.3) &&
+ (pdiff(highs[1] / 2.0, highs[0]) < 0.1) &&
+ (pdiff(lows[1] / 2.0, lows[0]) < 0.1)
+ )
+ )
+ {
+ //could also be RC-5 or RC-6
+ codeInfo->encoding = PHIDGET_IR_ENCODING_BIPHASE;
+ goto biphase;
+ }
+ //check for some special RC-6 cases
+ //there will always be either 2 or 3 of high/low
+ //there will always be a short high pulse
+ else if (
+ (
+ //1x, 2x, 3x high, 2x low
+ (highcount == 3) &&
+ (lowcount == 1) &&
+ (pdiff(highs[1], lows[0]) < 0.3) &&
+ (pdiff(highs[2] / 3.0, highs[0]) < 0.1)
+ ) ||
+ (
+ //1x + 3x high, 1x, 2x, 3x low
+ (highcount == 2) &&
+ (lowcount == 3) &&
+ (pdiff(highs[0], lows[0]) < 0.3) &&
+ (pdiff(highs[1], lows[2]) < 0.3) &&
+ (pdiff(lows[1] / 2.0, lows[0]) < 0.1) &&
+ (pdiff(lows[2] / 3.0, lows[0]) < 0.1)
+ ) ||
+ (
+ //1x, 2x, 3x high, 2x, 3x low
+ (highcount == 3) &&
+ (lowcount == 2) &&
+ (pdiff(highs[2], lows[1]) < 0.3) &&
+ (pdiff(highs[1], lows[0]) < 0.3) &&
+ (pdiff(highs[1] / 2.0, highs[0]) < 0.1) &&
+ (pdiff(highs[2] / 2.0, highs[1]) < 0.1)
+ )
+ )
+ {
+ //RC-6 mode 0 always starts with bit0 == 1 (444us pulse - 444us space)
+ //header is 2.666us pulse - 889us space
+ //bit4 == toggle bit, and had double bit time (889us - 889us)
+ //full length is 21 bits
+ //trailing gap (signal free time) is 2.666us
+ codeInfo->encoding = PHIDGET_IR_ENCODING_RC6;
+ goto biphase;
+ }
+ else
+ {
+ goto notbiphase;
+ }
+
+biphase:
+ {
+ int bit, startspace = 0, halfbit = 0, rc6temp = 0;
+
+ //find pulse short pulse width - do an average if possible
+ int pulse = lows[0];
+ if(pdiff(lows[0], highs[0]) < 0.3)
+ {
+ pulse = round((lows[0]+highs[0]) / 2.0);
+ }
+ else if(highs[0] < pulse)
+ pulse = highs[0];
+
+
+ codeInfo->one[0] = pulse;
+ codeInfo->one[1] = pulse;
+ codeInfo->zero[0] = pulse;
+ codeInfo->zero[1] = pulse;
+
+ //make sure 1st pulse is short
+ if(pdiff(data[0], pulse) > 0.3)
+ goto notbiphase;
+
+ //it's biphase! now decode..
+ //note that there may be an 'invisible' starting space
+ //- we can see this if the first long pulse is on an even i
+ //note this could cause trouble for RC-6 when there isn't a 2x pulse before the TR bit,
+ // or even for normal biphase/RC-5 when there isn't a 2x at all
+ //default is 1 - this should be good for all but RC-6
+ startspace = 1;
+ for(i=0; i<inlength; i++)
+ {
+ //found a double pulse
+ if(pdiff(data[i] / 2.0, pulse) < 0.3)
+ {
+ if(!(i%2))
+ startspace = 1;
+ else
+ startspace = 0;
+
+ break;
+ }
+ }
+
+ //actually decode, we assume that the first bit is always 1
+ //we are starting on the second pulse/space (first pulse/space is always short)
+ bitcount = 0;
+ bit = 1;
+ halfbit = 1;
+ for(i = 1-startspace; i < inlength; i++)
+ {
+ //when bit is not changing we will set decode_temp bits twice - no worries there
+ decode_temp[bitcount/8] |= bit << (bitcount % 8);
+
+ //found a triple pulse - this had better be RC-6
+ if(pdiff(data[i] / 3.0, pulse) < 0.2)
+ {
+ if(!halfbit || (bitcount != 3 && bitcount != 4))
+ {
+ goto notbiphase;
+ }
+ if(rc6temp == 0)
+ rc6temp = 1;
+ else
+ rc6temp = 0;
+ bit ^= 1;
+ bitcount++;
+ codeInfo->encoding = PHIDGET_IR_ENCODING_RC6;
+ }
+ //found a double pulse
+ else if(pdiff(data[i] / 2.0, pulse) < 0.2)
+ {
+ //probably this is PDM or PWM, but it could also be RC-6
+ if(!halfbit)
+ {
+ //check for RC-6
+ if(bitcount==4)
+ {
+ halfbit ^= 1;
+ rc6temp = 1;
+ codeInfo->encoding = PHIDGET_IR_ENCODING_RC6;
+ }
+ else
+ goto notbiphase;
+ }
+ else
+ {
+ if(rc6temp == 1)
+ {
+ rc6temp = 0;
+ halfbit ^= 1;
+ }
+ else
+ {
+ bit ^= 1;
+ }
+ bitcount++;
+ }
+ }
+ else
+ {
+ if(halfbit)
+ bitcount++;
+ halfbit ^= 1;
+ }
+ }
+ decode_temp[bitcount/8] |= bit << (bitcount % 8);
+ if((halfbit && !bit) || (!startspace && bit))
+ bitcount++;
+
+ //success, presumably
+ //see if it's RC-5 - 889 pulse time
+ //TODO also check data length, etc.
+ if(pdiff(pulse, 889) < 0.2
+ && codeInfo->encoding != PHIDGET_IR_ENCODING_RC6
+ && startspace)
+ {
+ codeInfo->encoding = PHIDGET_IR_ENCODING_RC5;
+ }
+
+ //TODO: if RC-6, make sure data length, bit times, etc. match, otherwise, it's not biphase!
+
+ goto done;
+ }
+
+notbiphase:
+ //make sure it's zeroed - we may have started filling it in in the biphase section
+ ZEROMEM(decode_temp, IR_MAX_CODE_DATA_LENGTH);
+ //Pulse Distance Modulation (PDM) - most common (NEC, etc.)
+ //should be a trailing pulse that we just ignore for now - it just lets us get the trailing space width
+ if(highcount == 1 && lowcount == 2)
+ {
+ int dataTimeZero = lows[1], dataTimeOne = lows[0];
+ if(lows[1] > lows[0])
+ {
+ dataTimeZero = lows[0];
+ dataTimeOne = lows[1];
+ }
+ //get the data
+ bitcount = 0;
+ for (i = 0; i < (inlength-1); i+=2)
+ {
+ if (data[i + 1] == dataTimeOne)
+ decode_temp[bitcount/8] |= (1 << (bitcount % 8));
+ bitcount++;
+ }
+
+ codeInfo->one[0] = highs[0];
+ codeInfo->one[1] = dataTimeOne;
+ codeInfo->zero[0] = highs[0];
+ codeInfo->zero[1] = dataTimeZero;
+
+ codeInfo->trail = data[inlength-1];
+ codeInfo->encoding = PHIDGET_IR_ENCODING_SPACE;
+ }
+ //PWM (SIRC)
+ //in PWM, we take the trailing pulse to be a bit
+ else if(highcount == 2 && lowcount == 1)
+ {
+ int dataTimeZero = highs[1], dataTimeOne = highs[0];
+ if(highs[1] > highs[0])
+ {
+ dataTimeZero = highs[0];
+ dataTimeOne = highs[1];
+ }
+ //get the data
+ bitcount = 0;
+ for (i = 0; i < inlength; i+=2)
+ {
+ if (data[i] == dataTimeOne)
+ decode_temp[bitcount/8] |= (1 << (bitcount % 8));
+ bitcount++;
+ }
+
+ codeInfo->one[0] = dataTimeOne;
+ codeInfo->one[1] = lows[0];
+ codeInfo->zero[0] = dataTimeZero;
+ codeInfo->zero[1] = lows[0];
+
+ codeInfo->encoding = PHIDGET_IR_ENCODING_PULSE;
+ }
+ else
+ goto errorexit;
+
+done:
+ //check size of output buffer
+ if(*outlength < ((bitcount / 8) + ((bitcount % 8) ? 1 : 0)))
+ goto errorexit;
+
+ //limit - code have to be >= 4-bit
+ if(bitcount < 4)
+ goto errorexit;
+
+ codeInfo->bitCount = bitcount;
+ *outlength = (bitcount / 8) + ((bitcount % 8) ? 1 : 0);
+
+ //data is LSB first now, lets flip it to MSB first - we don't change the Byte order though, just the bit order in the bytes
+ n = bitcount;
+
+ ZEROMEM(decoded_data, *outlength);
+ for(i = 0, j = bitcount-1, n = (*outlength * 8) - 1; i < bitcount; i++, j--, n--)
+ decoded_data[n/8] |= ( ( decode_temp[j/8] & (1 << (j%8)) ) ? (0x01 << (i%8)) : 0);
+
+ return EPHIDGET_OK;
+
+errorexit:
+ codeInfo->encoding = PHIDGET_IR_ENCODING_UNKNOWN;
+ return EPHIDGET_UNEXPECTED;
+}
+
+//uses the data array
+static int dataTime(int *data, int *time, int ptr, int endptr)
+{
+ int i;
+ int length = endptr - ptr;
+ if(length < 0)
+ length += IR_DATA_ARRAY_SIZE;
+ *time = 0;
+ for(i = 0; i < length; i++)
+ {
+ *time += data[ptr];
+ ptr=(ptr+1)&IR_DATA_ARRAY_MASK;
+ }
+ return EPHIDGET_OK;
+}
+
+//uses the data array
+static int compareDataArrays(int *data, int ptr1, int ptr2, int endptr1, int endptr2, double maxpdiff)
+{
+ int i;
+
+ int length1 = endptr1 - ptr1;
+ int length2 = endptr2 - ptr2;
+
+ if(length1 < 0)
+ length1 += IR_DATA_ARRAY_SIZE;
+ if(length2 < 0)
+ length2 += IR_DATA_ARRAY_SIZE;
+
+ if(length1 != length2)
+ return PFALSE;
+
+ for(i = 0; i < length1; i++)
+ {
+ if(pdiff(data[ptr1], data[ptr2]) > maxpdiff)
+ return PFALSE;
+
+ ptr1=(ptr1+1)&IR_DATA_ARRAY_MASK;
+ ptr2=(ptr2+1)&IR_DATA_ARRAY_MASK;
+ }
+ return PTRUE;
+}
+
+//this tries to lean a code
+//we read staring at a long gap (PUNK_INT) until the next long gap, or time > 1 second
+//need at least 1 code and 3 repeats to figure out the code completely
+static int learn_data(CPhidgetIRHandle phid)
+{
+ int dataReader, dataWriter, highcount, lowcount, high_low, i, decodedcount = IR_MAX_CODE_DATA_LENGTH;
+ int highs[IR_DATA_ARRAY_SIZE/2], lows[IR_DATA_ARRAY_SIZE/2], code_data[IR_DATA_ARRAY_SIZE];
+ unsigned char decoded_data[IR_MAX_CODE_DATA_LENGTH];
+ int highFinalscount=20, lowFinalscount=20;
+ int highFinals[20], lowFinals[20];
+ int highFinalsCounts[20], lowFinalsCounts[20];
+ //CPhidgetIR_Encoding encoding;
+ unsigned char hasHeader = PFALSE;
+
+ CPhidgetIR_CodeInfo codeInfo;
+
+ //keeps track of packets in the data stream
+ int dataPackets[50];
+ int dataPacketsCounter = 0;
+
+ int timecounter = 0;
+
+ //int oldLearPtr = phid->learnReadPtr;
+ int readToPtr;
+
+ //setup codeInfo with defaults
+ ZEROMEM(&codeInfo, sizeof(codeInfo));
+ codeInfo.carrierFrequency = 38000;
+ codeInfo.encoding = PHIDGET_IR_ENCODING_UNKNOWN;
+ codeInfo.length = PHIDGET_IR_LENGTH_UNKNOWN;
+ //codeInfo.maxPdiff = 0.30;
+ codeInfo.min_repeat = 1;
+ codeInfo.dutyCycle = 50;
+
+ //we have to have a BIG gap to start
+ while(phid->dataBuffer[phid->learnReadPtr] < PUNK_INT)
+ {
+ //nothing to analyze yet
+ if(phid->learnReadPtr == phid->dataWritePtr)
+ return EPHIDGET_OK;
+
+ phid->learnReadPtr++;
+ phid->learnReadPtr &= IR_DATA_ARRAY_MASK;
+ }
+
+ //nothing to analyze yet
+ if(phid->learnReadPtr == phid->dataWritePtr)
+ return EPHIDGET_OK;
+
+ dataReader = ((phid->learnReadPtr+1) & IR_DATA_ARRAY_MASK);
+
+ //nothing to analyze yet
+ if(dataReader == phid->dataWritePtr)
+ return EPHIDGET_OK;
+
+ readToPtr = dataReader;
+ //when read pointer != write pointer, there is new data to read
+ //read pointer should point at first spot that's probably a gap
+ while(phid->dataBuffer[readToPtr] != PUNK_INT)
+ {
+ //back up to last gap if we run into write pointer, or have > 1 sec. of data
+ if(readToPtr == phid->dataWritePtr || timecounter >= 2000000)
+ {
+ while(phid->dataBuffer[readToPtr] < IR_MIN_GAP_LENGTH)
+ {
+ //nothing to analyze yet
+ if(readToPtr == dataReader)
+ return EPHIDGET_OK;
+
+ readToPtr--;
+ readToPtr &= IR_DATA_ARRAY_MASK;
+ }
+ goto analyze_step_one;
+ }
+
+ timecounter += phid->dataBuffer[readToPtr];
+
+ readToPtr++;
+ readToPtr &= IR_DATA_ARRAY_MASK;
+ }
+
+ //we should have at least enough data for one set plus its gap
+analyze_step_one:
+
+ //this grabs everything, including the gaps
+ highcount = 0;
+ lowcount = 0;
+ high_low = 1;
+ while(dataReader != readToPtr)
+ {
+ //add data to high/low arrays
+ //we start with a high pulse
+ if(high_low == 1)
+ highs[highcount++] = phid->dataBuffer[dataReader];
+ else
+ lows[lowcount++] = phid->dataBuffer[dataReader];
+
+ high_low ^= 1;
+ dataReader = ((dataReader + 1) & IR_DATA_ARRAY_MASK);
+ }
+
+ //nothing to analyze yet
+ if(highcount == 0 && lowcount == 0)
+ goto advance_exit;
+
+ //not enough data
+ if((highcount+lowcount) < 10)
+ goto advance_exit;
+
+ //sort the high/low arrays and extract their components
+ qsort(highs, highcount, sizeof(int), compare_int);
+ qsort(lows, lowcount, sizeof(int), compare_int);
+
+ get_times(highs, highcount, highFinals, highFinalsCounts, &highFinalscount);
+ get_times(lows, lowcount, lowFinals, lowFinalsCounts, &lowFinalscount);
+
+
+ //go back through the data buffer and fill in dataBufferNormalized, doesn't include any gap data
+ dataWriter = ((phid->learnReadPtr+1) & IR_DATA_ARRAY_MASK);
+ high_low = 1;
+ dataPackets[dataPacketsCounter++] = dataWriter;
+ while(dataWriter != dataReader)
+ {
+ //high time
+ if (high_low)
+ {
+ int newtime = highFinals[0];
+ double matchPercent = 1;
+ for(i = 0; i<highFinalscount; i++)
+ {
+ //within 30% - we should never miss any...
+ double diff = pdiff(phid->dataBuffer[dataWriter], highFinals[i]);
+ if (diff <= 0.30 && diff < matchPercent)
+ {
+ newtime = highFinals[i];
+ matchPercent = diff;
+ }
+ }
+ phid->dataBufferNormalized[dataWriter] = newtime;
+ }
+ //low time
+ else
+ {
+ int newtime = lowFinals[0];
+ double matchPercent = 1;
+ for(i = 0; i<lowFinalscount; i++)
+ {
+ //within 30% - we should never miss any...
+ double diff = pdiff(phid->dataBuffer[dataWriter], lowFinals[i]);
+ if (diff <= 0.30 && diff < matchPercent)
+ {
+ newtime = lowFinals[i];
+ matchPercent = diff;
+ }
+ }
+ phid->dataBufferNormalized[dataWriter] = newtime;
+
+ if(newtime >= IR_MIN_GAP_LENGTH)
+ dataPackets[dataPacketsCounter++] = ((dataWriter + 1) & IR_DATA_ARRAY_MASK);
+ }
+
+ high_low ^= 1;
+ dataWriter = ((dataWriter + 1) & IR_DATA_ARRAY_MASK);
+ }
+
+ //at this point we have the data normalized, need to break off the first packet, figure out the gap, repeat, etc.
+ //first make sure we have a data packet and at least 3 repeat packets.
+
+ //not enough data
+ if(dataPacketsCounter < 5)
+ goto advance_exit;
+
+ //strip the header - if 1st pulse and/or the 1st space is unique, we assume first pulse/space is a header
+ //won't be unique because we have the repeats included now...
+ dataReader = dataPackets[0];
+ for(i=0;i<highFinalscount;i++)
+ if(phid->dataBufferNormalized[dataReader] == highFinals[i] && (highFinalsCounts[i] == 1 || highFinalsCounts[i] == dataPacketsCounter))
+ {
+ dataReader = (dataReader + 2) & IR_DATA_ARRAY_MASK;
+ hasHeader = PTRUE;
+ codeInfo.header[0] = phid->dataBufferNormalized[dataPackets[0]];
+ codeInfo.header[1] = phid->dataBufferNormalized[(dataPackets[0] + 1) & IR_DATA_ARRAY_MASK];
+ }
+
+ //put the code data into the code array
+ i=0;
+ //include the trailing bit!
+ //dataWriter = ((dataWriter - 1) & IR_DATA_ARRAY_MASK);
+ while(dataPackets[1] != dataReader)
+ {
+ code_data[i++] = phid->dataBufferNormalized[dataReader];
+ dataReader = ((dataReader + 1) & IR_DATA_ARRAY_MASK);
+ }
+
+ //no gap for decoding
+ i--;
+ //try to decode
+ if(decode_data(code_data, i, decoded_data, &decodedcount, &codeInfo))
+ {
+ //couldn't find the encoding
+ goto exit;
+ }
+
+ //get gap time
+ {
+ int time1 = 0, time2 = 0;
+ codeInfo.length = PHIDGET_IR_LENGTH_CONSTANT;
+ dataTime(phid->dataBufferNormalized, &time1, dataPackets[0], dataPackets[1]);
+ for(i=1; i<(dataPacketsCounter-1); i++)
+ {
+ dataTime(phid->dataBufferNormalized, &time2, dataPackets[i], dataPackets[i+1]);
+ if(pdiff(time1, time2) > 0.3)
+ codeInfo.length = PHIDGET_IR_LENGTH_VARIABLE;
+ }
+ if(codeInfo.length == PHIDGET_IR_LENGTH_CONSTANT)
+ {
+ codeInfo.gap = time1;
+ }
+ else
+ {
+ int constgap = PTRUE;
+ for(i=1; i<(dataPacketsCounter-1); i++)
+ {
+ if(phid->dataBufferNormalized[dataPackets[i]-1] != phid->dataBufferNormalized[dataPackets[i+1]-1])
+ constgap = PFALSE;
+ }
+ if(constgap)
+ codeInfo.gap = phid->dataBufferNormalized[dataPackets[1]-1];
+ else
+ {
+ //not constant length and no constant gap - no sense!
+ LOG(PHIDGET_LOG_DEBUG, "Couldn't figure out the gap");
+ goto exit;
+ }
+ }
+ }
+
+ //figure out repeat/toggle
+ //first two don't match, so there may be some sort of repeat code or toggling
+ if(compareDataArrays(phid->dataBufferNormalized, dataPackets[0], dataPackets[1], dataPackets[1], dataPackets[2], 0.3) != PTRUE)
+ {
+ int j;
+ //packet 1 and 2 match - looks like a repeat code
+ if(compareDataArrays(phid->dataBufferNormalized, dataPackets[1], dataPackets[2], dataPackets[2], dataPackets[3], 0.3) == PTRUE)
+ {
+ //See if the 'repeat code' is just the same code without the header (don't compare gaps)
+ if(codeInfo.header[0] && compareDataArrays(
+ phid->dataBufferNormalized, (dataPackets[0]+2) & IR_DATA_ARRAY_MASK, dataPackets[1],
+ (dataPackets[1]-1) & IR_DATA_ARRAY_MASK, (dataPackets[2]-1) & IR_DATA_ARRAY_MASK, 0.3)
+ )
+ {
+ LOG(PHIDGET_LOG_DEBUG, "No repeat code, just repeating without the header.");
+ codeInfo.repeat[0] = 0;
+ }
+ else
+ {
+ for(i = dataPackets[1], j = 0; i != dataPackets[2]; i = (i+1) & IR_DATA_ARRAY_MASK, j++)
+ {
+ //Make sure we don't go over the length of the repeat array!
+ if(j >= IR_MAX_REPEAT_LENGTH)
+ {
+ LOG(PHIDGET_LOG_DEBUG, "Couldn't figure out the repeat code");
+ goto exit;
+ }
+ codeInfo.repeat[j] = phid->dataBufferNormalized[i];
+ }
+ //don't include the gap
+ codeInfo.repeat[j-1] = 0;
+ }
+ }
+ //packets 0 and 2 match and 1 and 3 match - looks like a two packet data sequence, with some toggleing.
+ else if(compareDataArrays(phid->dataBufferNormalized, dataPackets[0], dataPackets[2], dataPackets[1], dataPackets[3], 0.3) == PTRUE
+ && compareDataArrays(phid->dataBufferNormalized, dataPackets[1], dataPackets[3], dataPackets[2], dataPackets[4], 0.3) == PTRUE)
+ {
+ int decodedcount2 = IR_MAX_CODE_DATA_LENGTH;
+ int code_data2[IR_DATA_ARRAY_SIZE];
+ unsigned char decoded_data2[IR_MAX_CODE_DATA_LENGTH];
+ CPhidgetIR_CodeInfo codeInfo2;
+ ZEROMEM(&codeInfo2, sizeof(codeInfo2));
+
+ dataReader = dataPackets[1];
+ //header
+ if(codeInfo.header[0])
+ dataReader = (dataReader + 2) & IR_DATA_ARRAY_MASK;
+ //put the code data into the code array
+ i=0;
+ //include the trailing bit!
+ //dataWriter = ((dataWriter - 1) & IR_DATA_ARRAY_MASK);
+ while(dataPackets[2] != dataReader)
+ {
+ code_data2[i++] = phid->dataBufferNormalized[dataReader];
+ dataReader = ((dataReader + 1) & IR_DATA_ARRAY_MASK);
+ }
+
+ //no gap for decoding
+ i--;
+ //try to decode
+ if(decode_data(code_data2, i, decoded_data2, &decodedcount2, &codeInfo2))
+ {
+ goto exit;
+ }
+
+ if(codeInfo.encoding == codeInfo2.encoding &&
+ codeInfo.bitCount == codeInfo2.bitCount &&
+ decodedcount == decodedcount2)
+ {
+ for(i=0;i<decodedcount2;i++)
+ {
+ codeInfo.toggle_mask[i] = decoded_data[i] ^ decoded_data2[i];
+ }
+ codeInfo.min_repeat = 2;
+ }
+ else
+ {
+ LOG(PHIDGET_LOG_DEBUG, "Couldn't figure out the repeat code");
+ goto exit;
+ }
+ }
+ else
+ {
+ LOG(PHIDGET_LOG_DEBUG, "Couldn't figure out the repeat code");
+ goto exit;
+ }
+ }
+
+ //send the event
+ FIRE(Learn, decoded_data, decodedcount, &codeInfo);
+
+ //store to last code
+ ZEROMEM(phid->lastLearnedCode, sizeof(phid->lastLearnedCode));
+ memcpy(phid->lastLearnedCode, decoded_data, decodedcount);
+ phid->lastLearnedCodeInfo = codeInfo;
+ phid->lastLearnedCodeKnown = PTRUE;
+
+exit:
+
+ //adjust the learn read pointer
+ phid->learnReadPtr = readToPtr;
+
+ //Done
+ return EPHIDGET_OK;
+
+advance_exit:
+ //not enough data, and readToPtr == PUNK_INT, so we can't expect any more data, and increment learnPtr
+ if(phid->dataBuffer[readToPtr] == PUNK_INT)
+ phid->learnReadPtr = readToPtr;
+
+ return EPHIDGET_OK;
+}
+
+//for now this just tries to get a data code
+static int analyze_data(CPhidgetIRHandle phid, int trailgap_needed)
+{
+ int dataReader, dataWriter, highcount, lowcount, high_low, i, decodedcount = IR_MAX_CODE_DATA_LENGTH;
+ int highs[IR_DATA_ARRAY_SIZE/2], lows[IR_DATA_ARRAY_SIZE/2], code_data[IR_DATA_ARRAY_SIZE];
+ unsigned char decoded_data[IR_MAX_CODE_DATA_LENGTH];
+ int highFinalscount=20, lowFinalscount=20;
+ int highFinals[20], lowFinals[20];
+ int highFinalsCounts[20], lowFinalsCounts[20];
+ CPhidgetIR_CodeInfo codeInfo;
+ ZEROMEM(&codeInfo, sizeof(codeInfo));
+
+ //when read pointer != write pointer, there is new data to read
+ //read pointer should point at first spot that's probably a gap
+ while(phid->dataBuffer[phid->dataReadPtr] < IR_MIN_GAP_LENGTH)
+ {
+ //nothing to analyze yet
+ if(phid->dataReadPtr == phid->dataWritePtr)
+ return EPHIDGET_OK;
+
+ phid->dataReadPtr++;
+ phid->dataReadPtr &= IR_DATA_ARRAY_MASK;
+ }
+
+ //nothing to analyze yet
+ if(phid->dataReadPtr == phid->dataWritePtr)
+ return EPHIDGET_OK;
+
+ dataReader = ((phid->dataReadPtr+1) & IR_DATA_ARRAY_MASK);
+
+ //nothing to analyze yet
+ if(dataReader == phid->dataWritePtr)
+ return EPHIDGET_OK;
+
+//analyze_step_one:
+ //gets the data up to the first probable gap
+ highcount = 0;
+ lowcount = 0;
+ high_low = 1;
+ while(dataReader != phid->dataWritePtr)
+ {
+ //go till we find the next likely gap (long low pulse)
+ if((phid->dataBuffer[dataReader] >= IR_MIN_GAP_LENGTH) && (high_low == 0))
+ goto analyze_step_two;
+
+ //add data to high/low arrays
+ //we start with a high pulse
+ if(high_low == 1)
+ highs[highcount++] = phid->dataBuffer[dataReader];
+ else
+ lows[lowcount++] = phid->dataBuffer[dataReader];
+
+ high_low ^= 1;
+ dataReader = ((dataReader + 1) & IR_DATA_ARRAY_MASK);
+ }
+
+ //hit the write pointer before finding a gap
+ if(trailgap_needed)
+ return EPHIDGET_OK;
+
+analyze_step_two:
+
+ //nothing to analyze yet
+ if(highcount == 0 && lowcount == 0)
+ return EPHIDGET_OK;
+
+ phid->lastGap = phid->dataBuffer[phid->dataReadPtr];
+ //should be one more high then low
+ if((highcount - 1) != lowcount)
+ {
+ LOG(PHIDGET_LOG_INFO, "Unexpected number of high/low pulses between gaps");
+ return EPHIDGET_UNEXPECTED;
+ }
+
+ //sort the high/low arrays and extract their components
+ qsort(highs, highcount, sizeof(int), compare_int);
+ qsort(lows, lowcount, sizeof(int), compare_int);
+
+ get_times(highs, highcount, highFinals, highFinalsCounts, &highFinalscount);
+ get_times(lows, lowcount, lowFinals, lowFinalsCounts, &lowFinalscount);
+
+ //go back through the data buffer and fills in dataBufferNormalized, doesn't include any gap data
+ dataWriter = ((phid->dataReadPtr+1) & IR_DATA_ARRAY_MASK);
+ high_low = 1;
+ while(dataWriter != dataReader)
+ {
+ //high time
+ if (high_low)
+ {
+ int newtime = highFinals[0];
+ double matchPercent = 1;
+ for(i = 0; i<highFinalscount; i++)
+ {
+ //within 30% - we should never miss any...
+ double diff = pdiff(phid->dataBuffer[dataWriter], highFinals[i]);
+ if (diff <= 0.30 && diff < matchPercent)
+ {
+ newtime = highFinals[i];
+ matchPercent = diff;
+ }
+ }
+ phid->dataBufferNormalized[dataWriter] = newtime;
+ }
+ //low time
+ else
+ {
+ int newtime = lowFinals[0];
+ double matchPercent = 1;
+ for(i = 0; i<lowFinalscount; i++)
+ {
+ //within 30% - we should never miss any...
+ double diff = pdiff(phid->dataBuffer[dataWriter], lowFinals[i]);
+ if (diff <= 0.30 && diff < matchPercent)
+ {
+ newtime = lowFinals[i];
+ matchPercent = diff;
+ }
+ }
+ phid->dataBufferNormalized[dataWriter] = newtime;
+ }
+
+ high_low ^= 1;
+ dataWriter = ((dataWriter + 1) & IR_DATA_ARRAY_MASK);
+ }
+
+ //strip the header - if 1st pulse and/or the 1st space is unique, we assume first pulse/space is a header
+ dataReader = (phid->dataReadPtr + 1) & IR_DATA_ARRAY_MASK;
+ for(i=0;i<highFinalscount;i++)
+ if(phid->dataBufferNormalized[dataReader] == highFinals[i] && highFinalsCounts[i] == 1)
+ {
+ dataReader = (phid->dataReadPtr + 3) & IR_DATA_ARRAY_MASK;
+ }
+
+ //put the code data into the code array
+ i=0;
+ //include the trailing bit!
+ //dataWriter = ((dataWriter - 1) & IR_DATA_ARRAY_MASK);
+ while(dataWriter != dataReader)
+ {
+ code_data[i++] = phid->dataBufferNormalized[dataReader];
+ dataReader = ((dataReader + 1) & IR_DATA_ARRAY_MASK);
+ }
+
+ //adjust the read pointer
+ phid->dataReadPtr = dataReader;
+
+ //try to decode
+ if(!decode_data(code_data, i, decoded_data, &decodedcount, &codeInfo))
+ {
+ //repeat logic
+ int repeat = PFALSE;
+ if(!memcmp(phid->lastCode, decoded_data, decodedcount)
+ && phid->lastGap <= IR_MAX_GAP_LENGTH && phid->lastGap >= IR_MIN_GAP_LENGTH
+ && phid->lastCodeInfo.bitCount == codeInfo.bitCount
+ && phid->lastCodeInfo.encoding == codeInfo.encoding)
+ repeat = PTRUE;
+
+ //send out the code event!
+ FIRE(Code, decoded_data, decodedcount, codeInfo.bitCount, repeat);
+ //LOG(PHIDGET_LOG_DEBUG, "Encoding: %d",encoding);
+
+ //store to last code
+ ZEROMEM(phid->lastCode, sizeof(phid->lastCode));
+ memcpy(phid->lastCode, decoded_data, decodedcount);
+ phid->lastCodeInfo.bitCount = codeInfo.bitCount;
+ phid->lastCodeInfo.encoding = codeInfo.encoding;
+ phid->lastRepeat = repeat;
+ phid->lastCodeKnown = PTRUE;
+ //TODO: add header
+ }
+ //probably a repeat code (ie NEC code)
+ else if((i == 1 || i == 3) && phid->lastCodeKnown && phid->lastGap <= IR_MAX_GAP_LENGTH && phid->lastGap >= IR_MIN_GAP_LENGTH)
+ {
+ int dataSize = (phid->lastCodeInfo.bitCount / 8) + ((phid->lastCodeInfo.bitCount % 8) ? 1 : 0);
+ //send out the code event!
+ FIRE(Code, phid->lastCode, dataSize, phid->lastCodeInfo.bitCount, PTRUE);
+ }
+
+ //Done
+ return EPHIDGET_OK;
+}
+
+PHIDGET21_API int CCONV codeInfoToString(CPhidgetIR_CodeInfoHandle codeInfo, char *string)
+{
+ int i;
+ unsigned char *codeInfoBytes = (unsigned char *)codeInfo;
+ for(i=0;i<sizeof(CPhidgetIR_CodeInfo);i++)
+ {
+ sprintf(string+(i*2), "%02x", codeInfoBytes[i]);
+ }
+ return EPHIDGET_OK;
+}
+
+PHIDGET21_API int CCONV stringToCodeInfo(char *string, CPhidgetIR_CodeInfoHandle codeInfo)
+{
+ int i;
+ unsigned char *codeInfoBytes = (unsigned char *)codeInfo;
+
+ if(strlen(string) < 2*sizeof(CPhidgetIR_CodeInfo))
+ return EPHIDGET_INVALIDARG;
+
+ for(i=0;i<sizeof(CPhidgetIR_CodeInfo);i++)
+ {
+ codeInfoBytes[i] = (hexval(string[i*2])<<4)+hexval(string[i*2+1]);
+ }
+ return EPHIDGET_OK;
+}
+
+
+
+// === Exported Functions === //
+
+//create and initialize a device structure
+CCREATE(IR, PHIDCLASS_IR)
+
+//event setup functions
+CFHANDLE(IR, Code, unsigned char *data, int dataLength, int bitCount, int repeat)
+CFHANDLE(IR, RawData, int *data, int dataLength)
+CFHANDLE(IR, Learn, unsigned char *data, int dataLength, CPhidgetIR_CodeInfoHandle codeInfo)
+
+PHIDGET21_API int CCONV CPhidgetIR_Transmit(CPhidgetIRHandle phid, unsigned char *data, CPhidgetIR_CodeInfoHandle codeInfo)
+{
+ int retval;
+ int dataSize;
+ TESTPTRS(phid, codeInfo)
+ TESTPTR(data)
+ TESTDEVICETYPE(PHIDCLASS_IR)
+ TESTATTACHED
+
+ if(!codeInfo->bitCount || codeInfo->bitCount > IR_MAX_CODE_BIT_COUNT)
+ return EPHIDGET_INVALIDARG;
+
+ //TODO: we're choosing arbitrary 10kHz - 1MHz range here
+ if((codeInfo->carrierFrequency && codeInfo->carrierFrequency < 10000) || codeInfo->carrierFrequency > 1000000)
+ return EPHIDGET_INVALIDARG;
+
+ //duty cycle between 10% and 50% - never allow higher then 50%
+ if((codeInfo->dutyCycle && codeInfo->dutyCycle < 10) || codeInfo->dutyCycle > 50)
+ return EPHIDGET_INVALIDARG;
+
+ //default encoding
+ if(!codeInfo->encoding)
+ codeInfo->encoding = PHIDGET_IR_ENCODING_SPACE;
+ if(!codeInfo->length)
+ codeInfo->length = PHIDGET_IR_LENGTH_CONSTANT;
+
+ //fill in other defaults based on encoding
+ switch(codeInfo->encoding)
+ {
+ case PHIDGET_IR_ENCODING_SPACE:
+ //we'll default to NEC coding
+ if(!codeInfo->zero[0] && !codeInfo->one[0])
+ {
+ codeInfo->zero[0] = 560;
+ codeInfo->zero[1] = 560;
+ codeInfo->one[0] = 560;
+ codeInfo->one[1] = 1680;
+ if(!codeInfo->header[0])
+ {
+ codeInfo->header[0] = 9000;
+ codeInfo->header[1] = 4500;
+ }
+ if(!codeInfo->repeat)
+ {
+ codeInfo->repeat[0] = 9000;
+ codeInfo->repeat[1] = 2250;
+ codeInfo->repeat[2] = 560;
+ }
+ if(!codeInfo->trail)
+ codeInfo->trail = 560;
+ if(!codeInfo->gap)
+ codeInfo->gap = 110000;
+ if(!codeInfo->carrierFrequency)
+ codeInfo->carrierFrequency = 38000;
+ }
+ if(!codeInfo->trail)
+ return EPHIDGET_INVALIDARG;
+ break;
+ case PHIDGET_IR_ENCODING_PULSE:
+ //default to SONY coding
+ if(!codeInfo->zero[0] && !codeInfo->one[0])
+ {
+ codeInfo->zero[0] = 600;
+ codeInfo->zero[1] = 600;
+ codeInfo->one[0] = 1200;
+ codeInfo->one[1] = 600;
+ if(!codeInfo->header[0])
+ {
+ codeInfo->header[0] = 2400;
+ codeInfo->header[1] = 600;
+ }
+ if(!codeInfo->gap)
+ codeInfo->gap = 45000;
+ if(!codeInfo->carrierFrequency)
+ codeInfo->carrierFrequency = 40000;
+ }
+ break;
+ case PHIDGET_IR_ENCODING_BIPHASE:
+ //no default here..
+ break;
+ case PHIDGET_IR_ENCODING_RC5:
+ if(!codeInfo->zero[0] && !codeInfo->one[0])
+ {
+ codeInfo->zero[0] = 889;
+ codeInfo->zero[1] = 889;
+ codeInfo->one[0] = 889;
+ codeInfo->one[1] = 889;
+ if(!codeInfo->gap)
+ codeInfo->gap = 114000;
+ if(!codeInfo->carrierFrequency)
+ codeInfo->carrierFrequency = 36000;
+ }
+ break;
+ case PHIDGET_IR_ENCODING_RC6:
+ if(!codeInfo->zero[0] && !codeInfo->one[0])
+ {
+ codeInfo->zero[0] = 444;
+ codeInfo->zero[1] = 444;
+ codeInfo->one[0] = 444;
+ codeInfo->one[1] = 444;
+ if(!codeInfo->header[0])
+ {
+ codeInfo->header[0] = 2666;
+ codeInfo->header[1] = 889;
+ }
+ if(!codeInfo->gap)
+ codeInfo->gap = 105000;
+ if(!codeInfo->carrierFrequency)
+ codeInfo->carrierFrequency = 36000;
+ }
+ break;
+ case PHIDGET_IR_ENCODING_UNKNOWN:
+ default:
+ return EPHIDGET_INVALIDARG;
+ }
+
+ //fill in defaults for things that the user didn't specify
+ if(!codeInfo->carrierFrequency)
+ codeInfo->carrierFrequency = 38000;
+ if(!codeInfo->dutyCycle)
+ codeInfo->dutyCycle = 33;
+ if(!codeInfo->min_repeat)
+ codeInfo->min_repeat = 1;
+
+ //make sure that other things are filled in
+ if(!codeInfo->zero[0])
+ return EPHIDGET_INVALIDARG;
+ if(!codeInfo->one[0])
+ return EPHIDGET_INVALIDARG;
+ if(!codeInfo->gap)
+ return EPHIDGET_INVALIDARG;
+
+ dataSize = (codeInfo->bitCount / 8) + ((codeInfo->bitCount % 8) ? 1 : 0);
+ if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
+ {
+ char *newVal = (char *)malloc(1024);
+ ZEROMEM(newVal, 1024);
+ //add codeInfo data
+ codeInfoToString(codeInfo, newVal);
+ //now add transmit data
+ byteArrayToString(data, dataSize, newVal+sizeof(CPhidgetIR_CodeInfo)*2);
+ ADDNETWORKKEY(Transmit, "%s", tempString);
+ free(newVal);
+ }
+ else
+ {
+ int time, i;
+ int dataSize = (codeInfo->bitCount / 8) + ((codeInfo->bitCount % 8) ? 1 : 0);
+ int dataBuffer[IR_DATA_ARRAY_SIZE];
+ int dataBufferLength = IR_DATA_ARRAY_SIZE * sizeof(int);
+ int repcount = codeInfo->min_repeat;
+ unsigned char datatemp[IR_MAX_CODE_DATA_LENGTH];
+
+ memcpy(datatemp, data, dataSize);
+
+ //send out the number of times required
+ while(repcount--)
+ {
+ //convert code into raw data array and send
+ dataBufferLength = IR_DATA_ARRAY_SIZE * sizeof(int);
+ if((retval = codeInfoToRawData(datatemp, *codeInfo, dataBuffer, &dataBufferLength, &time, PFALSE)) != EPHIDGET_OK)
+ return retval;
+
+ if(codeInfo->length == PHIDGET_IR_LENGTH_CONSTANT)
+ time = codeInfo->gap - time;
+ else
+ time = codeInfo->gap;
+
+ if((retval = sendRAWData(phid, dataBuffer, dataBufferLength, codeInfo->carrierFrequency, codeInfo->dutyCycle, time)) != EPHIDGET_OK)
+ return retval;
+
+ memcpy(phid->lastSentCode, datatemp, dataSize);
+
+ //toggle data
+ for(i=0;i<dataSize;i++)
+ datatemp[i] = datatemp[i] ^ codeInfo->toggle_mask[i];
+ }
+
+ //got here? success in sending
+ phid->lastSentCodeInfo = *codeInfo;
+ }
+
+ return EPHIDGET_OK;
+}
+
+PHIDGET21_API int CCONV CPhidgetIR_TransmitRaw(CPhidgetIRHandle phid, int *data, int dataLength, int carrierFrequency, int dutyCycle, int gap)
+{
+ int retval, time=0;
+ int rawData[IR_DATA_ARRAY_SIZE];
+ int rawDataLength = IR_DATA_ARRAY_SIZE;
+ TESTPTR(phid)
+ TESTDEVICETYPE(PHIDCLASS_IR)
+ TESTATTACHED
+
+ //needs to be uneven - start and end in a pulse
+ if((dataLength % 2) != 1)
+ return EPHIDGET_INVALIDARG;
+
+ //TODO: we're choosing arbitrary 10kHz - 1MHz range here
+ if((carrierFrequency && carrierFrequency < 10000) || carrierFrequency > 1000000)
+ return EPHIDGET_INVALIDARG;
+
+ //duty cycle between 10% and 50% - never allow higher then 50%
+ if((dutyCycle && dutyCycle < 10) || dutyCycle > 50)
+ return EPHIDGET_INVALIDARG;
+
+ //defaults
+ if(!carrierFrequency)
+ carrierFrequency = 38000;
+ if(!dutyCycle)
+ dutyCycle = 33;
+
+ if(dataLength>(1000/5))
+ return EPHIDGET_INVALIDARG;
+
+ if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
+ {
+ char *newVal = (char *)malloc(1024);
+ ZEROMEM(newVal, 1024);
+ wordArrayToString(data, dataLength, newVal);
+ sprintf(newVal+dataLength*5, ",%d,%d,%d", carrierFrequency, dutyCycle, gap);
+ ADDNETWORKKEY(TransmitRaw, "%s", tempString);
+ free(newVal);
+ }
+ else
+ {
+ if((retval = RawTimeDataToRawData(data, dataLength, rawData, &rawDataLength, &time)) != EPHIDGET_OK)
+ return retval;
+ if((retval = sendRAWData(phid, rawData, rawDataLength, carrierFrequency ? carrierFrequency : 38000, dutyCycle ? dutyCycle : 33, gap)) != EPHIDGET_OK)
+ return retval;
+ }
+
+ return EPHIDGET_OK;
+}
+
+PHIDGET21_API int CCONV CPhidgetIR_TransmitRepeat(CPhidgetIRHandle phid)
+{
+ int retval;
+ int dataSize;
+ TESTPTR(phid)
+ TESTDEVICETYPE(PHIDCLASS_IR)
+ TESTATTACHED
+
+ if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
+ {
+ int newVal = phid->flip^1;
+ ADDNETWORKKEY(Repeat, "%d", flip);
+ SLEEP(25);//make sure we limit the repeat rate
+ }
+ else
+ {
+ dataSize = (phid->lastSentCodeInfo.bitCount / 8) + ((phid->lastSentCodeInfo.bitCount % 8) ? 1 : 0);
+ //assume that last code is valid
+ if(dataSize > 0)
+ {
+ int dataBuffer[IR_DATA_ARRAY_SIZE];
+ int dataBufferLength = IR_DATA_ARRAY_SIZE * sizeof(int);
+ int time, i;
+ unsigned char datatemp[IR_MAX_CODE_DATA_LENGTH];
+
+ //get last data sent
+ memcpy(datatemp, phid->lastSentCode, dataSize);
+
+ //toggle data
+ for(i=0;i<dataSize;i++)
+ datatemp[i] = datatemp[i] ^ phid->lastSentCodeInfo.toggle_mask[i];
+
+ //construct the last code into a repeat code
+ dataBufferLength = IR_DATA_ARRAY_SIZE * sizeof(int);
+ if((retval = codeInfoToRawData(datatemp, phid->lastSentCodeInfo, dataBuffer, &dataBufferLength, &time, PTRUE)) != EPHIDGET_OK)
+ return retval;
+
+ if(phid->lastSentCodeInfo.length == PHIDGET_IR_LENGTH_CONSTANT)
+ time = phid->lastSentCodeInfo.gap - time;
+ else
+ time = phid->lastSentCodeInfo.gap;
+
+ //send the data
+ if((retval = sendRAWData(phid, dataBuffer, dataBufferLength, phid->lastSentCodeInfo.carrierFrequency, phid->lastSentCodeInfo.dutyCycle, time)) != EPHIDGET_OK)
+ return retval;
+
+ //store last sent code
+ memcpy(phid->lastSentCode, datatemp, dataSize);
+ }
+ else
+ {
+ LOG(PHIDGET_LOG_WARNING, "Can't send a repeat until a code has been transmitted");
+ return EPHIDGET_UNKNOWNVAL;
+ }
+ }
+
+ return EPHIDGET_OK;
+}
+
+//make sure that our raw data starts with a high and ends with a low
+PHIDGET21_API int CCONV CPhidgetIR_getRawData(CPhidgetIRHandle phid, int *data, int *dataLength)
+{
+ int i;
+ TESTPTR(phid)
+ TESTDEVICETYPE(PHIDCLASS_IR)
+ TESTATTACHED
+
+ //make sure length is even so we only send out data with starting space and ending pulse
+ if((*dataLength % 2) == 1)
+ (*dataLength)--;
+
+ for(i=0;i<*dataLength;i++)
+ {
+ if(phid->userReadPtr == phid->dataWritePtr)
+ break;
+
+ data[i] = phid->dataBuffer[phid->userReadPtr];
+ phid->userReadPtr = (phid->userReadPtr + 1) & IR_DATA_ARRAY_MASK;
+ }
+
+ //make sure i is even so that we don't end with a pulse
+ if((i % 2) == 1)
+ {
+ //negate the pulse if we added it
+ i--;
+ phid->userReadPtr = (phid->userReadPtr - 1) & IR_DATA_ARRAY_MASK;
+ }
+
+ *dataLength = i;
+
+ return EPHIDGET_OK;
+}
+
+PHIDGET21_API int CCONV CPhidgetIR_getLastCode(CPhidgetIRHandle phid, unsigned char *data, int *dataLength, int *bitCount)
+{
+ TESTPTR(phid)
+ TESTDEVICETYPE(PHIDCLASS_IR)
+ TESTATTACHED
+
+ if(!phid->lastCodeKnown)
+ return EPHIDGET_UNKNOWNVAL;
+
+ {
+ int dataSize = (phid->lastCodeInfo.bitCount / 8) + ((phid->lastCodeInfo.bitCount % 8) ? 1 : 0);
+
+ *bitCount = phid->lastCodeInfo.bitCount;
+
+ if(*dataLength < dataSize)
+ {
+ *dataLength = dataSize;
+ return EPHIDGET_NOMEMORY;
+ }
+ *dataLength = dataSize;
+
+ memcpy(data, phid->lastCode, dataSize);
+ }
+
+ return EPHIDGET_OK;
+
+}
+
+PHIDGET21_API int CCONV CPhidgetIR_getLastLearnedCode(CPhidgetIRHandle phid, unsigned char *data, int *dataLength, CPhidgetIR_CodeInfo *codeInfo)
+{
+ TESTPTR(phid)
+ TESTDEVICETYPE(PHIDCLASS_IR)
+ TESTATTACHED
+
+ if(!phid->lastLearnedCodeKnown)
+ return EPHIDGET_UNKNOWNVAL;
+
+ {
+ int dataSize = (phid->lastLearnedCodeInfo.bitCount / 8) + ((phid->lastLearnedCodeInfo.bitCount % 8) ? 1 : 0);
+
+ if(*dataLength < dataSize)
+ {
+ *dataLength = dataSize;
+ return EPHIDGET_NOMEMORY;
+ }
+ *dataLength = dataSize;
+
+ memcpy(data, phid->lastLearnedCode, dataSize);
+
+ *codeInfo = phid->lastLearnedCodeInfo;
+ }
+
+ return EPHIDGET_OK;
+}
diff --git a/cphidgetir.h b/cphidgetir.h
new file mode 100644
index 0000000..6ee3e79
--- /dev/null
+++ b/cphidgetir.h
@@ -0,0 +1,203 @@
+#ifndef __CPHIDGETIR
+#define __CPHIDGETIR
+#include "cphidget.h"
+
+/** \defgroup phidIR Phidget IR
+ * \ingroup phidgets
+ * Calls specific to the Phidget IR. See the product manual for more specific API details, supported functionality, units, etc.
+ * @{
+ */
+
+DPHANDLE(IR)
+CHDRSTANDARD(IR)
+
+//This needs to be evenly divisible by 8
+#define IR_MAX_CODE_BIT_COUNT 128 /**< Maximum bit count for sent / received data */
+#define IR_MAX_CODE_DATA_LENGTH (IR_MAX_CODE_BIT_COUNT / 8) /**< Maximum array size needed to hold the longest code */
+#define IR_MAX_REPEAT_LENGTH 26 /**< Maximum array size for a repeat code */
+
+/**
+ * The PhidgetIR supports these data encodings.
+ */
+typedef enum {
+ PHIDGET_IR_ENCODING_UNKNOWN = 1, /**< Unknown - the default value */
+ PHIDGET_IR_ENCODING_SPACE, /**< Space encoding, or Pulse Distance Modulation */
+ PHIDGET_IR_ENCODING_PULSE, /**< Pulse encoding, or Pulse Width Modulation */
+ PHIDGET_IR_ENCODING_BIPHASE, /**< Bi-Phase, or Manchester encoding */
+ PHIDGET_IR_ENCODING_RC5, /**< RC5 - a type of Bi-Phase encoding */
+ PHIDGET_IR_ENCODING_RC6 /**< RC6 - a type of Bi-Phase encoding */
+} CPhidgetIR_Encoding;
+
+/**
+ * The PhidgetIR supports these encoding lengths
+ */
+typedef enum {
+ PHIDGET_IR_LENGTH_UNKNOWN = 1, /**< Unknown - the default value */
+ PHIDGET_IR_LENGTH_CONSTANT, /**< Constant - the bitstream + gap length is constant */
+ PHIDGET_IR_LENGTH_VARIABLE /**< Variable - the bitstream has a variable length with a constant gap */
+} CPhidgetIR_Length;
+
+//If you modify this, it's NEEDS to be modified in .NET and Flash!!!
+/**
+ * The PhidgetIR CodeInfo structure contains all information needed to transmit a code, apart from the actual code data.
+ * Some values can be set to null to select defaults. See the product manual for more information.
+ */
+typedef struct _CPhidgetIR_CodeInfo
+{
+ int bitCount; /**< Number of bits in the code */
+ CPhidgetIR_Encoding encoding; /**< Encoding used to encode the data */
+ CPhidgetIR_Length length; /**< Constan or Variable length encoding */
+ int gap; /**< Gap time in us */
+ int trail; /**< Trail time in us - can be 0 for none */
+ int header[2]; /**< Header pulse and space - can be 0 for none */
+ int one[2]; /**< Pulse and Space times to represent a '1' bit, in us */
+ int zero[2]; /**< Pulse and Space times to represent a '0' bit, in us */
+ int repeat[IR_MAX_REPEAT_LENGTH]; /**< A series or pulse and space times to represent the repeat code. Start and end with pulses and null terminate. Set to 0 for none. */
+ int min_repeat; /**< Minium number of times to repeat a code on transmit */
+ unsigned char toggle_mask[IR_MAX_CODE_DATA_LENGTH]; /**< Bit toggles, which are applied to the code after each transmit */
+ int carrierFrequency; /**< Carrier frequency in Hz - defaults to 38kHz */
+ int dutyCycle; /**< Duty Cycle in percent (10-50). Defaults to 33 */
+} CPhidgetIR_CodeInfo, *CPhidgetIR_CodeInfoHandle;
+
+/**
+ * Transmits a code according to the settings in a CodeInto structure
+ * @param phid An attached phidget ir handle.
+ * @param data The code to send. Data is transmitted MSBit first. MSByte is in array index 0. LSBit is right justified, so MSBit may be in bit positions 0-7 in array index 0 depending on the bit count.
+ * @param codeInfo The CodeInfo structure specifying to to send the code. Anything left as null to select default is filled in for the user.
+ */
+PHIDGET21_API int CCONV CPhidgetIR_Transmit(CPhidgetIRHandle phid, unsigned char *data, CPhidgetIR_CodeInfoHandle codeInfo);
+/**
+ * Transmits a repeat of the last transmited code. Depending of the CodeInfo structure, this may be a retransmission of the code itself,
+ * or there may be a special repeat code.
+ * @param phid An attached phidget ir handle.
+ */
+PHIDGET21_API int CCONV CPhidgetIR_TransmitRepeat(CPhidgetIRHandle phid);
+/**
+ * Transmits RAW data as a series of pulses and spaces.
+ * @param phid An attached phidget ir handle.
+ * @param data The data to send. The array must start and end with a pulse and each element is a positive time in us.
+ * @param length The length of the data array. Maximum length is 1024, but streams should be kept much shorter, ie. < 100ms between gaps.
+ * @param carrierFrequency The Carrier Frequency in Hz. leave as 0 for default.
+ * @param dutyCycle The Duty Cycle (10-50). Leave as 0 for default.
+ * @param gap The gap time in us. This guarantees a gap time (no transmitting) after the data is sent, but can be set to 0.
+ */
+PHIDGET21_API int CCONV CPhidgetIR_TransmitRaw(CPhidgetIRHandle phid, int *data, int length, int carrierFrequency, int dutyCycle, int gap);
+/**
+ * Read any available raw data. This should be polled continuously (every 20ms) to avoid missing data. Read data always starts with a space and ends with a pulse.
+ * @param phid An attached phidget ir handle.
+ * @param data A user array for raw data to be written into.
+ * @param dataLength The maximum ammount of data to read. This is set to the actual ammount of data read.
+ */
+PHIDGET21_API int CCONV CPhidgetIR_getRawData(CPhidgetIRHandle phid, int *data, int *dataLength);
+/**
+ * Gets the last code that was received.
+ * @param phid An attached phidget ir handle.
+ * @param data A user array to store the code data in.
+ * @param dataLength Length of the user array - should be at least IR_MAX_CODE_DATA_LENGTH. This is set to the ammount of data actually written to the array.
+ * @param bitCount set to the bit count of the code.
+ */
+PHIDGET21_API int CCONV CPhidgetIR_getLastCode(CPhidgetIRHandle phid, unsigned char *data, int *dataLength, int *bitCount);
+/**
+ * Gets the last code that was learned.
+ * @param phid An attached phidget ir handle.
+ * @param data A user array to store the code data in.
+ * @param dataLength Length of the user array - should be at least IR_MAX_CODE_DATA_LENGTH. This is set to the ammount of data actually written to the array.
+ * @param codeInfo The CodeInfo structure for the learned code.
+ */
+PHIDGET21_API int CCONV CPhidgetIR_getLastLearnedCode(CPhidgetIRHandle phid, unsigned char *data, int *dataLength, CPhidgetIR_CodeInfo *codeInfo);
+/**
+ * Set a Code handler. This is called when a code has been received that could be automatically decoded.
+ * Data is return as an array with MSB in index 0. Bit count and a repeat flag are also returned.
+ * Repeats are detected as either the same code repeated in < 100ms or as a special repeat code.
+ * @param phid An attached phidget ir handle.
+ * @param fptr Callback function pointer.
+ * @param userPtr A pointer for use by the user - this value is passed back into the callback function.
+ */
+CHDREVENT(IR, Code, unsigned char *data, int dataLength, int bitCount, int repeat)
+/**
+ * Set a Learn handler. This is called when a code has been received for long enough to be learned.
+ * The returned CodeInfo structure can be used to retransmit the same code.
+ * @param phid An attached phidget ir handle.
+ * @param fptr Callback function pointer.
+ * @param userPtr A pointer for use by the user - this value is passed back into the callback function.
+ */
+CHDREVENT(IR, Learn, unsigned char *data, int dataLength, CPhidgetIR_CodeInfoHandle codeInfo)
+/**
+ * Set a Raw Data handler. This is called when raw data has been read from the device. Raw data always starts with a space and ends with a pulse.
+ * @param phid An attached phidget ir handle.
+ * @param fptr Callback function pointer.
+ * @param userPtr A pointer for use by the user - this value is passed back into the callback function.
+ */
+CHDREVENT(IR, RawData, int *data, int dataLength)
+
+#ifndef EXTERNALPROTO
+PHIDGET21_API int CCONV codeInfoToString(CPhidgetIR_CodeInfoHandle codeInfo, char *string);
+PHIDGET21_API int CCONV stringToCodeInfo(char *string, CPhidgetIR_CodeInfoHandle codeInfo);
+
+#define IR_MAX_DATA_PER_PACKET 31
+
+#define IR_DATA_ARRAY_SIZE 2048
+#define IR_DATA_ARRAY_MASK 0x7ff
+
+//for transmitting / receiving raw data
+#define IR_MAX_DATA_us 327670
+
+//this is just actual gap, not the gap that includes data
+#define IR_MAX_GAP_LENGTH 100000 //us
+#define IR_MIN_GAP_LENGTH 20000 //us
+
+#define IR_DEFINEDATA_PACKET 0
+
+#define IR_STOP_RX_WHILE_TX_FLAG 0x01
+
+#define IR_RAW_DATA_WS_KEYS_MAX 100
+
+struct _CPhidgetIR {
+ CPhidget phid;
+
+ int (CCONV *fptrCode)(CPhidgetIRHandle, void *, unsigned char *, int, int, int); //data, length, bitCount, repeat
+ int (CCONV *fptrRawData)(CPhidgetIRHandle, void *, int *, int);
+ int (CCONV *fptrLearn)(CPhidgetIRHandle, void *, unsigned char *, int, CPhidgetIR_CodeInfoHandle); //needs > 1 sec. of continuous data - for learning
+
+ void *fptrCodeptr;
+ void *fptrRawDataptr;
+ void *fptrLearnptr;
+
+ int dataBuffer[IR_DATA_ARRAY_SIZE];
+ int dataBufferNormalized[IR_DATA_ARRAY_SIZE];
+ int dataReadPtr, dataWritePtr;
+ int userReadPtr; //for the getRawData function
+ int learnReadPtr; //for the learning function
+
+ unsigned char polarity;
+
+ unsigned char lastCodeKnown;
+ unsigned char lastCode[IR_MAX_CODE_BIT_COUNT/8];
+ CPhidgetIR_CodeInfo lastCodeInfo;
+ unsigned char lastRepeat;
+ int lastGap;
+
+ unsigned char lastLearnedCodeKnown;
+ unsigned char lastLearnedCode[IR_MAX_CODE_BIT_COUNT/8];
+ CPhidgetIR_CodeInfo lastLearnedCodeInfo;
+
+ unsigned char lastSentCode[IR_MAX_CODE_BIT_COUNT/8];
+ CPhidgetIR_CodeInfo lastSentCodeInfo;
+
+ TIME lastDataTime;
+
+ unsigned char delayCode;
+
+ char *tempString;
+ int flip;
+
+ int rawDataSendWSCounter, rawDataSendWSKeys[IR_RAW_DATA_WS_KEYS_MAX];
+
+ unsigned char outputPacket[8];
+ unsigned int outputPacketLen;
+} typedef CPhidgetIRInfo;
+#endif
+
+/** @} */
+
+#endif
diff --git a/cphidgetled.c b/cphidgetled.c
new file mode 100644
index 0000000..4bcbfc6
--- /dev/null
+++ b/cphidgetled.c
@@ -0,0 +1,669 @@
+#include "stdafx.h"
+#include "cphidgetled.h"
+#include "cusb.h"
+#include "csocket.h"
+#include "cthread.h"
+
+// === Internal Functions === //
+
+//clearVars - sets all device variables to unknown state
+CPHIDGETCLEARVARS(LED)
+ int i = 0;
+
+ phid->changeRequests=PUNK_BOOL;
+
+ for(i=0;i<LED_MAXLEDS;i++)
+ {
+ phid->changedLED_Power[i] = PUNK_BOOL;
+ phid->LED_Power[i] = PUNI_INT;
+ phid->nextLED_Power[i] = PUNK_INT;
+
+ phid->LED_PowerEcho[i] = PUNK_INT;
+ phid->outputEnabledEcho[i] = PUNK_BOOL;
+ phid->ledOpenDetectEcho[i] = PUNK_BOOL;
+
+ phid->lastLED_Power[i] = PUNK_INT;
+ }
+ phid->voltage = PHIDGET_LED_VOLTAGE_2_75V;
+ phid->currentLimit = PHIDGET_LED_CURRENT_LIMIT_20mA;
+ phid->faultEcho = PUNK_BOOL;
+ phid->TSDCount=0;
+ phid->PGoodErrState = PFALSE;
+ phid->powerGoodEcho = PUNK_BOOL;
+ phid->outputEnableEcho = PUNK_BOOL;
+ phid->currentLimitEcho = -1;
+ phid->voltageEcho = -1;
+
+ return EPHIDGET_OK;
+}
+
+//initAfterOpen - sets up the initial state of an object, reading in packets from the device if needed
+// used during attach initialization - on every attach
+CPHIDGETINIT(LED)
+ int i = 0;
+
+ TESTPTR(phid);
+
+ //set data arrays to unknown
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_LED_64:
+ for(i=0;i<phid->phid.attr.led.numLEDs;i++)
+ {
+ phid->changedLED_Power[i] = PFALSE;
+ phid->LED_Power[i] = PUNK_INT;
+ phid->nextLED_Power[i] = PUNK_INT;
+ }
+ break;
+ case PHIDID_LED_64_ADV:
+ if ((phid->phid.deviceVersion >= 100) && (phid->phid.deviceVersion < 200))
+ {
+ for(i=0;i<phid->phid.attr.led.numLEDs;i++)
+ {
+ phid->changedLED_Power[i] = PFALSE;
+ phid->LED_Power[i] = PUNK_INT;
+ phid->nextLED_Power[i] = PUNK_INT;
+
+ phid->LED_PowerEcho[i] = PUNK_INT;
+ phid->outputEnabledEcho[i] = PUNK_BOOL;
+ phid->ledOpenDetectEcho[i] = PUNK_BOOL;
+
+ phid->lastLED_Power[i] = PUNK_INT;
+ }
+ phid->voltage = PHIDGET_LED_VOLTAGE_2_75V;
+ phid->currentLimit = PHIDGET_LED_CURRENT_LIMIT_20mA;
+
+ phid->faultEcho = PUNK_BOOL;
+ phid->powerGoodEcho = PUNK_BOOL;
+ phid->PGoodErrState = PFALSE;
+ phid->outputEnableEcho = PUNK_BOOL;
+ phid->voltageEcho = -1;
+ phid->currentLimitEcho = -1;
+
+ phid->TSDCount=0;
+ phid->TSDClearCount = 0;
+ phid->lastOutputPacket = 0;
+ }
+ else
+ return EPHIDGET_BADVERSION;
+ break;
+ default:
+ return EPHIDGET_UNEXPECTED;
+ }
+ phid->changeRequests=0;
+ phid->controlPacketWaiting = PFALSE;
+
+ //issue a read - fill in data
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_LED_64_ADV:
+ //need two reads to get the full state
+ CPhidget_read((CPhidgetHandle)phid);
+ CPhidget_read((CPhidgetHandle)phid);
+ for(i=0;i<phid->phid.attr.led.numLEDs;i++)
+ {
+ if(phid->outputEnabledEcho[i] == PTRUE)
+ phid->LED_Power[i] = phid->LED_PowerEcho[i];
+ else
+ phid->LED_Power[i] = 0;
+
+ phid->lastLED_Power[i] = phid->LED_PowerEcho[i];
+ }
+ if(phid->voltageEcho != -1)
+ phid->voltage = phid->voltageEcho;
+ if(phid->currentLimitEcho != -1)
+ phid->currentLimit = phid->currentLimitEcho;
+ break;
+ case PHIDID_LED_64:
+ default:
+ break;
+ }
+
+ return EPHIDGET_OK;
+}
+
+//dataInput - parses device packets
+CPHIDGETDATA(LED)
+ int i = 0;
+ char error_buffer[50];
+
+ if (length < 0) return EPHIDGET_INVALIDARG;
+ TESTPTR(phid);
+ TESTPTR(buffer);
+
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_LED_64_ADV:
+ if ((phid->phid.deviceVersion >= 100) && (phid->phid.deviceVersion < 200))
+ {
+ switch(buffer[0] & 0x80)
+ {
+ case LED64_IN_LOW_PACKET:
+ //PowerGood
+ if(buffer[0] & LED64_PGOOD_FLAG)
+ {
+ phid->PGoodErrState = PFALSE;
+ phid->powerGoodEcho = PTRUE;
+ }
+ else
+ {
+ phid->powerGoodEcho = PFALSE;
+ }
+
+ //all outputs enabled (power on/off)
+ if(buffer[0] & LED64_OE_FLAG)
+ phid->outputEnableEcho = PTRUE;
+ else
+ phid->outputEnableEcho = PFALSE;
+
+ //fault
+ if(buffer[0] & LED64_FAULT_FLAG)
+ phid->faultEcho = PTRUE;
+ else
+ phid->faultEcho = PFALSE;
+
+ //current limit
+ if(buffer[0] & LED64_CURSELA_FLAG)
+ {
+ if(buffer[0] & LED64_CURSELB_FLAG)
+ phid->currentLimitEcho = PHIDGET_LED_CURRENT_LIMIT_80mA;
+ else
+ phid->currentLimitEcho = PHIDGET_LED_CURRENT_LIMIT_40mA;
+ }
+ else if (buffer[0] & LED64_CURSELB_FLAG)
+ phid->currentLimitEcho = PHIDGET_LED_CURRENT_LIMIT_60mA;
+ else
+ phid->currentLimitEcho = PHIDGET_LED_CURRENT_LIMIT_20mA;
+
+ //voltage
+ if(buffer[0] & LED64_PWRSELA_FLAG)
+ {
+ if(buffer[0] & LED64_PWRSELB_FLAG)
+ phid->voltageEcho = PHIDGET_LED_VOLTAGE_5_0V;
+ else
+ phid->voltageEcho = PHIDGET_LED_VOLTAGE_2_75V;
+ }
+ else if (buffer[0] & LED64_PWRSELB_FLAG)
+ phid->voltageEcho = PHIDGET_LED_VOLTAGE_3_9V;
+ else
+ phid->voltageEcho = PHIDGET_LED_VOLTAGE_1_7V;
+
+ for(i=0;i<phid->phid.attr.led.numLEDs;i++)
+ {
+ phid->outputEnabledEcho[i] = (buffer[(i/8)+1] & (1 << (i%8))) ? 1 : 0;
+ phid->ledOpenDetectEcho[i] = (buffer[(i/8)+9] & (1 << (i%8))) ? 1 : 0;
+ }
+
+ //1st 24 LED powers
+ for(i=0;i<24;i++)
+ {
+ double ledPowerTemp;
+ ledPowerTemp = ((double)buffer[i+17] / 127.0) * 100.0;
+ phid->LED_PowerEcho[i] = round(ledPowerTemp);
+ }
+
+ //We can guess that the fault is a TSD if there is no LOD
+ if(phid->faultEcho)
+ {
+ phid->TSDCount++;
+ phid->TSDClearCount = 30; //500ms of no faults before we clear it
+
+ for(i=0;i<phid->phid.attr.led.numLEDs;i++)
+ {
+ if(phid->ledOpenDetectEcho[i])
+ phid->TSDCount = 0;
+ }
+
+ //send out some error events on faults
+ //TODO: we could also send LED Open Detect?
+
+ //we have counted three fault flags with no LODs - TSD - only one error event is thrown until this is cleared
+ //less then 3 counts, and it could be a false positive
+ //if outputs are not enabled then the fault should be guaranteed as a TSD
+ if(phid->TSDCount == 3 || (phid->TSDCount < 3 && phid->outputEnableEcho == PFALSE))
+ {
+ phid->TSDCount = 3;
+ FIRE_ERROR(EEPHIDGET_OVERTEMP, "Thermal Shutdown detected.");
+ }
+ }
+ else
+ {
+ if(phid->TSDClearCount > 0)
+ phid->TSDClearCount--;
+ else
+ phid->TSDCount=0;
+ }
+
+ if(!phid->powerGoodEcho && phid->PGoodErrState == PFALSE)
+ {
+ phid->PGoodErrState = PTRUE;
+ FIRE_ERROR(EEPHIDGET_BADPOWER, "Bad power supply detected.");
+ }
+
+ break;
+ case LED64_IN_HIGH_PACKET:
+
+ //last 40 LED powers
+ for(i=24;i<phid->phid.attr.led.numLEDs;i++)
+ {
+ double ledPowerTemp;
+ ledPowerTemp = ((double)buffer[i-23] / 127.0) * 100.0;
+ phid->LED_PowerEcho[i] = round(ledPowerTemp);
+ }
+
+ break;
+ }
+ }
+ else
+ return EPHIDGET_UNEXPECTED;
+ break;
+ case PHIDID_LED_64:
+ default:
+ return EPHIDGET_UNEXPECTED;
+ }
+
+ return EPHIDGET_OK;
+}
+
+//eventsAfterOpen - sends out an event for all valid data, used during attach initialization - not used
+CPHIDGETINITEVENTS(LED)
+ phid = 0;
+ return EPHIDGET_OK;
+}
+
+//getPacket - used by write thread to get the next packet to send to device
+CGETPACKET(LED)
+ int i = 0;
+ int numLeds = 0;
+
+ CPhidgetLEDHandle phid = (CPhidgetLEDHandle)phidG;
+
+ TESTPTRS(phid, buf)
+ TESTPTR(lenp)
+
+ if (*lenp < phid->phid.outputReportByteLength)
+ return EPHIDGET_INVALIDARG;
+
+ CThread_mutex_lock(&phid->phid.outputLock);
+
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_LED_64:
+ if ((phid->phid.deviceVersion >= 100) && (phid->phid.deviceVersion < 300))
+ {
+
+ //construct the packet, with up to 4 LED sets
+ for (i = 0; i < phid->phid.attr.led.numLEDs; i++)
+ {
+ if (phid->changedLED_Power[i] && numLeds < 4) {
+ phid->LED_Power[i] = phid->nextLED_Power[i];
+ phid->changedLED_Power[i] = PFALSE;
+ phid->nextLED_Power[i] = PUNK_INT;
+ buf[numLeds*2] = i;
+ //0-100 -> 0-63
+ buf[numLeds*2+1] = (unsigned char)round((phid->LED_Power[i] / 100.0) * 63.0);
+ numLeds++;
+ phid->changeRequests--;
+ }
+ }
+
+ //fill up any remaining buffer space with valid data - sending 0's will mess things up
+ for(numLeds=numLeds;numLeds<4;numLeds++)
+ {
+ buf[numLeds*2] = buf[(numLeds-1)*2];
+ buf[numLeds*2+1] = buf[(numLeds-1)*2+1];
+ }
+ }
+ else
+ return EPHIDGET_UNEXPECTED;
+ break;
+ case PHIDID_LED_64_ADV:
+ if ((phid->phid.deviceVersion >= 100) && (phid->phid.deviceVersion < 200))
+ {
+ //control packet
+ if(phid->controlPacketWaiting)
+ {
+
+ buf[0] = LED64_CONTROL_PACKET;
+
+ buf[1] = 0;
+
+ switch(phid->currentLimit)
+ {
+ case PHIDGET_LED_CURRENT_LIMIT_20mA:
+ break;
+ case PHIDGET_LED_CURRENT_LIMIT_40mA:
+ buf[1] |= LED64_CURSELA_FLAG;
+ break;
+ case PHIDGET_LED_CURRENT_LIMIT_60mA:
+ buf[1] |= LED64_CURSELB_FLAG;
+ break;
+ case PHIDGET_LED_CURRENT_LIMIT_80mA:
+ buf[1] |= (LED64_CURSELA_FLAG | LED64_CURSELB_FLAG);
+ break;
+ }
+
+ switch(phid->voltage)
+ {
+ case PHIDGET_LED_VOLTAGE_1_7V:
+ break;
+ case PHIDGET_LED_VOLTAGE_2_75V:
+ buf[1] |= LED64_PWRSELA_FLAG;
+ break;
+ case PHIDGET_LED_VOLTAGE_3_9V:
+ buf[1] |= LED64_PWRSELB_FLAG;
+ break;
+ case PHIDGET_LED_VOLTAGE_5_0V:
+ buf[1] |= (LED64_PWRSELA_FLAG | LED64_PWRSELB_FLAG);
+ break;
+ }
+
+ phid->controlPacketWaiting = PFALSE;
+ }
+ //LED packet
+ else
+ {
+ int bright_packet = PFALSE;
+ int output_upper = PFALSE;
+ int output_lower = PFALSE;
+ //decide if we need to use a normal brightness packet, or if we can use a high efficiency output packet
+ for (i = 0; i < phid->phid.attr.led.numLEDs; i++)
+ {
+ if(phid->changedLED_Power[i])
+ {
+ if((phid->nextLED_Power[i] != phid->lastLED_Power[i]) && phid->nextLED_Power[i] != 0)
+ bright_packet = PTRUE;
+ else
+ {
+ if(i<32)
+ output_lower = PTRUE;
+ else
+ output_upper = PTRUE;
+ }
+ }
+ }
+
+ //only sends brightness changes - not changes between 0 and a brightness
+ if(bright_packet)
+ {
+ //construct the packet, with up to 4 LED sets
+ for (i = 0; i < phid->phid.attr.led.numLEDs; i++)
+ {
+ if (phid->changedLED_Power[i] && numLeds < 4 && phid->nextLED_Power[i] != 0) {
+ phid->LED_Power[i] = phid->nextLED_Power[i];
+ phid->lastLED_Power[i] = phid->nextLED_Power[i];
+ phid->changedLED_Power[i] = PFALSE;
+ phid->nextLED_Power[i] = PUNK_INT;
+ buf[numLeds*2] = i;
+ //0-100 -> 0-127
+ buf[numLeds*2+1] = (unsigned char)round((phid->LED_Power[i] / 100.0) * 127.0);
+ if(buf[numLeds*2+1])
+ buf[numLeds*2+1] |= 0x80; //this turns the LED on when set brightness > 0;
+ numLeds++;
+ phid->changeRequests--;
+ }
+ }
+
+ //fill up any remaining buffer space with valid data - sending 0's will mess things up
+ //this just replicates data - doesn't send anything
+ for(numLeds=numLeds;numLeds<4;numLeds++)
+ {
+ buf[numLeds*2] = buf[(numLeds-1)*2];
+ buf[numLeds*2+1] = buf[(numLeds-1)*2+1];
+ }
+ }
+ else
+ {
+ //send lower packet
+ if((phid->lastOutputPacket == 0 && output_lower) || (phid->lastOutputPacket != 0 && !output_upper))
+ {
+ buf[0] = LED64_OUTLOW_PACKET;
+ for(i = 0;i<32;i++)
+ {
+ if(phid->changedLED_Power[i])
+ {
+ phid->changeRequests--;
+ phid->LED_Power[i] = phid->nextLED_Power[i];
+ phid->changedLED_Power[i] = PFALSE;
+ phid->nextLED_Power[i] = PUNK_INT;
+ }
+ if(phid->LED_Power[i] > 0)
+ buf[i/8 + 1] |= (1 << (i%8));
+ }
+ phid->lastOutputPacket = 1;
+ }
+ //send upper packet
+ else
+ {
+ buf[0] = LED64_OUTHIGH_PACKET;
+ for(i = 32;i<64;i++)
+ {
+ if(phid->changedLED_Power[i])
+ {
+ phid->changeRequests--;
+ phid->LED_Power[i] = phid->nextLED_Power[i];
+ phid->changedLED_Power[i] = PFALSE;
+ phid->nextLED_Power[i] = PUNK_INT;
+ }
+ if(phid->LED_Power[i] > 0)
+ buf[i/8 - 3] |= (1 << (i%8));
+ }
+ phid->lastOutputPacket = 0;
+ }
+ }
+ }
+ }
+ else
+ return EPHIDGET_UNEXPECTED;
+ break;
+ default:
+ return EPHIDGET_UNEXPECTED;
+ }
+
+ //if there are still pending sets, signal the event again (which will tell write thread to call this funciton again)
+ if(phid->changeRequests)
+ CThread_set_event(&phid->phid.writeAvailableEvent);
+
+ *lenp = phid->phid.outputReportByteLength;
+
+ CThread_mutex_unlock(&phid->phid.outputLock);
+
+ return EPHIDGET_OK;
+}
+
+//sendpacket - sends a packet to the device asynchronously, blocking if the 1-packet queue is full
+// -every LED has its own 1 state mini-queue
+static int CCONV CPhidgetLED_sendpacket(CPhidgetLEDHandle phid,
+ unsigned int index, unsigned int power)
+{
+ int waitReturn;
+ CThread_mutex_lock(&phid->phid.writelock);
+again:
+ if (!CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_ATTACHED_FLAG))
+ {
+ CThread_mutex_unlock(&phid->phid.writelock);
+ return EPHIDGET_NOTATTACHED;
+ }
+ CThread_mutex_lock(&phid->phid.outputLock);
+ //if we have already requested a change on this LED
+ if (phid->changedLED_Power[index]) {
+ //and it was different then this time
+ if (phid->nextLED_Power[index] != power) {
+ CThread_mutex_unlock(&phid->phid.outputLock);
+ //then wait for it to get written
+ waitReturn = CThread_wait_on_event(&phid->phid.writtenEvent, 2500);
+ switch(waitReturn)
+ {
+ case WAIT_OBJECT_0:
+ break;
+ case WAIT_ABANDONED:
+ CThread_mutex_unlock(&phid->phid.writelock);
+ return EPHIDGET_UNEXPECTED;
+ case WAIT_TIMEOUT:
+ CThread_mutex_unlock(&phid->phid.writelock);
+ return EPHIDGET_TIMEOUT;
+ }
+ //and try again
+ goto again;
+ } else {
+ CThread_mutex_unlock(&phid->phid.outputLock);
+ CThread_mutex_unlock(&phid->phid.writelock);
+ return EPHIDGET_OK;
+ }
+ //otherwise
+ } else {
+ //if it's different then current, queue it up
+ if (phid->LED_Power[index] != power) {
+ phid->changeRequests++;
+ phid->changedLED_Power[index] = PTRUE;
+ phid->nextLED_Power[index] = power;
+ CThread_reset_event(&phid->phid.writtenEvent);
+ CThread_mutex_unlock(&phid->phid.outputLock);
+ CThread_set_event(&phid->phid.writeAvailableEvent);
+ }
+ //if it's the same, just return
+ else
+ {
+ CThread_mutex_unlock(&phid->phid.outputLock);
+ CThread_mutex_unlock(&phid->phid.writelock);
+ return EPHIDGET_OK;
+ }
+ }
+ CThread_mutex_unlock(&phid->phid.writelock);
+ return EPHIDGET_OK;
+}
+
+// === Exported Functions === //
+
+//create and initialize a device structure
+CCREATE(LED, PHIDCLASS_LED)
+
+CGET(LED,LEDCount,int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_LED)
+ TESTATTACHED
+
+ MASGN(phid.attr.led.numLEDs)
+}
+
+CGETINDEX(LED,DiscreteLED,int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_LED)
+ TESTATTACHED
+ TESTINDEX(phid.attr.led.numLEDs)
+ TESTMASGN(LED_Power[Index], PUNK_INT)
+
+ MASGN(LED_Power[Index])
+}
+CSETINDEX(LED,DiscreteLED,int)
+ TESTPTR(phid)
+ TESTDEVICETYPE(PHIDCLASS_LED)
+ TESTATTACHED
+ TESTINDEX(phid.attr.led.numLEDs)
+ TESTRANGE(0, 100)
+
+ if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
+ ADDNETWORKKEYINDEXED(Brightness, "%d", LED_Power);
+ else
+ return CPhidgetLED_sendpacket(phid, Index, newVal);
+
+ return EPHIDGET_OK;
+}
+
+CGET(LED,CurrentLimit,CPhidgetLED_CurrentLimit)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_LED)
+ TESTATTACHED
+
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_LED_64_ADV:
+ MASGN(currentLimitEcho)
+ case PHIDID_LED_64:
+ default:
+ return EPHIDGET_UNSUPPORTED;
+ }
+}
+CSET(LED,CurrentLimit,CPhidgetLED_CurrentLimit)
+ TESTPTR(phid)
+ TESTDEVICETYPE(PHIDCLASS_LED)
+ TESTATTACHED
+
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_LED_64_ADV:
+
+ TESTRANGE(PHIDGET_LED_CURRENT_LIMIT_20mA, PHIDGET_LED_CURRENT_LIMIT_80mA)
+
+ if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
+ ADDNETWORKKEY(CurrentLimit, "%d", currentLimit);
+ else
+ {
+ CThread_mutex_lock(&phid->phid.writelock);
+ CThread_mutex_lock(&phid->phid.outputLock);
+ phid->currentLimit = newVal;
+ phid->controlPacketWaiting = PTRUE;
+ CThread_mutex_unlock(&phid->phid.outputLock);
+ CThread_set_event(&phid->phid.writeAvailableEvent);
+ CThread_mutex_unlock(&phid->phid.writelock);
+ }
+ break;
+ case PHIDID_LED_64:
+ default:
+ return EPHIDGET_UNSUPPORTED;
+ }
+
+ return EPHIDGET_OK;
+}
+
+CGET(LED,Voltage,CPhidgetLED_Voltage)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_LED)
+ TESTATTACHED
+
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_LED_64_ADV:
+ MASGN(voltageEcho)
+ case PHIDID_LED_64:
+ default:
+ return EPHIDGET_UNSUPPORTED;
+ }
+}
+CSET(LED,Voltage,CPhidgetLED_Voltage)
+ TESTPTR(phid)
+ TESTDEVICETYPE(PHIDCLASS_LED)
+ TESTATTACHED
+
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_LED_64_ADV:
+
+ TESTRANGE(PHIDGET_LED_CURRENT_LIMIT_20mA, PHIDGET_LED_CURRENT_LIMIT_80mA)
+
+ if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
+ ADDNETWORKKEY(Voltage, "%d", voltage);
+ else
+ {
+ CThread_mutex_lock(&phid->phid.writelock);
+ CThread_mutex_lock(&phid->phid.outputLock);
+ phid->voltage = newVal;
+ phid->controlPacketWaiting = PTRUE;
+ CThread_mutex_unlock(&phid->phid.outputLock);
+ CThread_set_event(&phid->phid.writeAvailableEvent);
+ CThread_mutex_unlock(&phid->phid.writelock);
+ }
+ break;
+ case PHIDID_LED_64:
+ default:
+ return EPHIDGET_UNSUPPORTED;
+ }
+
+ return EPHIDGET_OK;
+}
+
+// === Deprecated Functions === //
+
+CGET(LED,NumLEDs,int)
+ return CPhidgetLED_getLEDCount(phid, pVal);
+}
diff --git a/cphidgetled.h b/cphidgetled.h
new file mode 100644
index 0000000..c6d7b4e
--- /dev/null
+++ b/cphidgetled.h
@@ -0,0 +1,137 @@
+#ifndef __CPHIDGETLED
+#define __CPHIDGETLED
+#include "cphidget.h"
+
+/** \defgroup phidled Phidget LED
+ * \ingroup phidgets
+ * Calls specific to the Phidget LED. See the product manual for more specific API details, supported functionality, units, etc.
+ * @{
+ */
+
+DPHANDLE(LED)
+CHDRSTANDARD(LED)
+
+/**
+ * The Phidget LED supports these current limits
+ */
+typedef enum {
+ PHIDGET_LED_CURRENT_LIMIT_20mA = 1, /**< 20mA */
+ PHIDGET_LED_CURRENT_LIMIT_40mA, /**< 40mA */
+ PHIDGET_LED_CURRENT_LIMIT_60mA, /**< 60mA */
+ PHIDGET_LED_CURRENT_LIMIT_80mA /**< 80mA */
+} CPhidgetLED_CurrentLimit;
+/**
+ * The Phidget LED supports these voltages
+ */
+typedef enum {
+ PHIDGET_LED_VOLTAGE_1_7V = 1, /**< 1.7V */
+ PHIDGET_LED_VOLTAGE_2_75V, /**< 2.75V */
+ PHIDGET_LED_VOLTAGE_3_9V, /**< 3.9V */
+ PHIDGET_LED_VOLTAGE_5_0V /**< 5.0V */
+} CPhidgetLED_Voltage;
+
+/**
+ * Gets the number of LEDs supported by this board.
+ * @param phid An attached phidget LED handle.
+ * @param count The led count.
+ */
+CHDRGET(LED,LEDCount,int *count)
+/**
+ * Gets the brightness of an LED.
+ * @param phid An attached phidget LED handle.
+ * @param index The LED index.
+ * @param brightness The LED brightness (0-100).
+ */
+CHDRGETINDEX(LED,DiscreteLED,int *brightness)
+/**
+ * Sets the brightness of an LED.
+ * @param phid An attached phidget LED handle.
+ * @param index The LED index.
+ * @param brightness The LED brightness (0-100).
+ */
+CHDRSETINDEX(LED,DiscreteLED,int brightness)
+/**
+ * Gets the current limit. This is for all ouputs.
+ * @param phid An attached phidget LED handle.
+ * @param currentLimit The Current Limit.
+ */
+CHDRGET(LED,CurrentLimit,CPhidgetLED_CurrentLimit *currentLimit)
+/**
+ * Sets the current limit. This is for all ouputs.
+ * @param phid An attached phidget LED handle.
+ * @param currentLimit The Current Limit.
+ */
+CHDRSET(LED,CurrentLimit,CPhidgetLED_CurrentLimit currentLimit)
+/**
+ * Gets the output voltate. This is for all ouputs.
+ * @param phid An attached phidget LED handle.
+ * @param voltage The Output Voltage.
+ */
+CHDRGET(LED,Voltage,CPhidgetLED_Voltage *voltage)
+/**
+ * Sets the output voltage. This is for all ouputs.
+ * @param phid An attached phidget LED handle.
+ * @param voltage The Output Voltage.
+ */
+CHDRSET(LED,Voltage,CPhidgetLED_Voltage voltage)
+
+#ifndef REMOVE_DEPRECATED
+DEP_CHDRGET("Deprecated - use CPhidgetLED_getLEDCount",LED,NumLEDs,int *)
+#endif
+
+#ifndef EXTERNALPROTO
+
+#define LED_MAXLEDS 64
+
+//OUT Packet Types
+#define LED64_NORMAL_PACKET 0x00
+#define LED64_CONTROL_PACKET 0x40
+#define LED64_OUTLOW_PACKET 0x80
+#define LED64_OUTHIGH_PACKET 0xc0
+
+//IN Packet Types
+#define LED64_IN_LOW_PACKET 0x00
+#define LED64_IN_HIGH_PACKET 0x80
+
+//Flags
+#define LED64_PGOOD_FLAG 0x01
+#define LED64_CURSELA_FLAG 0x02
+#define LED64_CURSELB_FLAG 0x04
+#define LED64_PWRSELA_FLAG 0x08
+#define LED64_PWRSELB_FLAG 0x10
+#define LED64_FAULT_FLAG 0x20
+#define LED64_OE_FLAG 0x40
+
+struct _CPhidgetLED
+{
+ CPhidget phid;
+
+ int LED_Power[LED_MAXLEDS];
+ CPhidgetLED_Voltage voltage;
+ CPhidgetLED_CurrentLimit currentLimit;
+
+ int nextLED_Power[LED_MAXLEDS];
+ int lastLED_Power[LED_MAXLEDS];
+ unsigned char changedLED_Power[LED_MAXLEDS];
+ unsigned char changeRequests;
+
+ int LED_PowerEcho[LED_MAXLEDS];
+ unsigned char outputEnabledEcho[LED_MAXLEDS];
+ unsigned char ledOpenDetectEcho[LED_MAXLEDS];
+ unsigned char powerGoodEcho;
+ unsigned char outputEnableEcho;
+ unsigned char faultEcho;
+ CPhidgetLED_Voltage voltageEcho;
+ CPhidgetLED_CurrentLimit currentLimitEcho;
+
+ unsigned char TSDCount, TSDClearCount, PGoodErrState;
+
+ unsigned char controlPacketWaiting;
+ unsigned char lastOutputPacket;
+
+} typedef CPhidgetLEDInfo;
+
+#endif
+
+/** @} */
+#endif
diff --git a/cphidgetlist.c b/cphidgetlist.c
new file mode 100644
index 0000000..ed5bea1
--- /dev/null
+++ b/cphidgetlist.c
@@ -0,0 +1,148 @@
+#include "stdafx.h"
+#include "cphidgetlist.h"
+
+/* Adds an element to a list - Duplicates are not allowed.
+ * Return: EPHIDGET_OK on success
+ * EPHIDGET_DUPLICATE if the element already exists in the list
+ */
+int CList_addToList(CListHandle *list, void *element,
+ int (*compare_fptr)(void *element1, void *element2))
+{
+ int result = 0;
+ CListHandle trav = 0, newentry = 0;
+
+ TESTPTRS(list, element)
+
+ /* The very first thing we do is make sure none of these already exist in the list */
+ result = CList_findInList(*list, element, compare_fptr, NULL);
+ switch (result) {
+ case EPHIDGET_OK:
+ return EPHIDGET_DUPLICATE;
+ case EPHIDGET_NOTFOUND:
+ break;
+ default:
+ return result;
+ }
+
+ newentry = (CListHandle)malloc(sizeof(CList));
+ if (!newentry) return EPHIDGET_NOMEMORY;
+ ZEROMEM(newentry, sizeof(CList));
+
+ newentry->next = 0;
+ newentry->element = element;
+
+ if (!*list)
+ *list = newentry;
+ else
+ {
+ for (trav = *list; trav->next; trav = trav->next);
+ trav->next = newentry;
+ }
+ return EPHIDGET_OK;
+}
+
+/* this returns success even if the element is not found in the list
+ * this also removes duplicates.
+ *
+ * but! if we find in the list the exact element, rather then just a match, we need to free it after!
+ * interating, or the compare function will croak!
+ */
+int CList_removeFromList(CListHandle *list, void *element,
+ int (*compare_fptr)(void *element1, void *element2),
+ int freeDevice, void (*free_fptr)(void *element))
+{
+ CListHandle traverse = 0, last = 0;
+ int freeElement = PFALSE;
+
+ TESTPTRS(list, element)
+
+ for (traverse=*list; traverse; traverse = traverse->next) {
+ if(compare_fptr(element, traverse->element)) {
+ if(traverse == *list) {
+ *list = traverse->next;
+ if(freeDevice && traverse->element)
+ {
+ // don't free element in the middle of iterating!
+ if(traverse->element == element)
+ freeElement=PTRUE;
+ else
+ free_fptr(traverse->element);
+ traverse->element = 0;
+ }
+ free(traverse); traverse = NULL;
+ traverse=*list;
+ break;
+ }
+ else {
+ last->next=traverse->next;
+ if(freeDevice && traverse->element)
+ {
+ // don't free element in the middle of iterating!
+ if(traverse->element == element)
+ freeElement=PTRUE;
+ else
+ free_fptr(traverse->element);
+ traverse->element = 0;
+ }
+ free(traverse); traverse = NULL;
+ traverse=last;
+ }
+ }
+ last = traverse;
+ }
+
+ /* element itself was found in the list, and we want it freed - free it here */
+ if(freeElement)
+ free_fptr(element);
+
+ return EPHIDGET_OK;
+}
+
+/* this takes any list, and frees all of the list element,
+ and can also free the elements that they point to */
+int CList_emptyList(CListHandle *list, int freeDevices, void (*free_fptr)(void *element))
+{
+ CListHandle last = 0, traverse = 0;
+
+ TESTPTR(list)
+
+ last = 0;
+ for(traverse = *list; traverse; last = traverse, traverse = traverse->next)
+ {
+ if(traverse->element && freeDevices)
+ {
+ free_fptr(traverse->element);
+ traverse->element = 0;
+ }
+ if(last)
+ {
+ free(last); last = NULL;
+ }
+ }
+ if(last)
+ {
+ free(last); last = NULL;
+ }
+
+ *list = 0;
+
+ return EPHIDGET_OK;
+}
+
+/* returns EPHIDGET_OK if the device is in the list */
+int CList_findInList(CListHandle list, void *element,
+ int (*compare_fptr)(void *element1, void *element2), void **found_element)
+{
+ CListHandle trav = 0;
+
+ TESTPTR(element)
+
+ for (trav=list; trav; trav = trav->next) {
+ if(compare_fptr(element, trav->element)) {
+ if(found_element) *found_element = trav->element;
+ return EPHIDGET_OK;
+ }
+ }
+ return EPHIDGET_NOTFOUND;
+}
+
diff --git a/cphidgetlist.h b/cphidgetlist.h
new file mode 100644
index 0000000..249e2f6
--- /dev/null
+++ b/cphidgetlist.h
@@ -0,0 +1,19 @@
+#ifndef __CPHIDGETLIST
+#define __CPHIDGETLIST
+
+typedef struct _CList
+{
+ struct _CList *next;
+ void *element;
+} CList, *CListHandle;
+
+int CList_addToList(CListHandle *list, void *element,
+ int (*compare_fptr)(void *element1, void *element2));
+int CList_removeFromList(CListHandle *list, void *element,
+ int (*compare_fptr)(void *element1, void *element2),
+ int freeDevice, void (*free_fptr)(void *element));
+int CList_emptyList(CListHandle *list, int freeDevices, void (*free_fptr)(void *element));
+int CList_findInList(CListHandle list, void *element,
+ int (*compare_fptr)(void *element1, void *element2), void **found_element);
+
+#endif
diff --git a/cphidgetmacros.h b/cphidgetmacros.h
new file mode 100644
index 0000000..f228c9c
--- /dev/null
+++ b/cphidgetmacros.h
@@ -0,0 +1,316 @@
+#ifndef _CPHIDGET_MACROS
+#define _CPHIDGET_MACROS
+
+#define PHANDLE(pname) CPhidget##pname##Handle
+
+#define DPHANDLE(pname) typedef struct _CPhidget##pname *CPhidget##pname##Handle; /**< A Phidget pname handle*/
+
+//Regular Versions
+#define CHDRSTANDARD(pname) \
+/** Creates a Phidget pname handle. @param phid A pointer to an unallocated Phidget pname handle. */ \
+PHIDGET21_API int CCONV CPhidget##pname##_create(CPhidget##pname##Handle *phid);
+
+#define CHDREVENTINDEX(pname,param,...) PHIDGET21_API int CCONV CPhidget##pname##_set_On##param##_Handler(PHANDLE(pname) phid, int (CCONV *fptr)(PHANDLE(pname) phid, void *userPtr, int index, __VA_ARGS__), void *userPtr);
+#define CHDREVENT(pname,param,...) PHIDGET21_API int CCONV CPhidget##pname##_set_On##param##_Handler(PHANDLE(pname) phid, int (CCONV *fptr)(PHANDLE(pname) phid, void *userPtr, __VA_ARGS__), void *userPtr);
+
+#define CHDRGET(pname,propname,...) PHIDGET21_API int CCONV CPhidget##pname##_get##propname(PHANDLE(pname) phid, __VA_ARGS__);
+#define CHDRSET(pname,propname,...) PHIDGET21_API int CCONV CPhidget##pname##_set##propname(PHANDLE(pname) phid, __VA_ARGS__);
+
+#define CHDRGETINDEX(pname,propname,...) PHIDGET21_API int CCONV CPhidget##pname##_get##propname(PHANDLE(pname) phid, int index, __VA_ARGS__);
+#define CHDRSETINDEX(pname,propname,...) PHIDGET21_API int CCONV CPhidget##pname##_set##propname(PHANDLE(pname) phid, int index, __VA_ARGS__);
+
+//Versions for Deprecation
+
+#define DEP_CHDREVENTINDEX(depmsg,pname,param,...) DEPRECATE_WIN(depmsg) PHIDGET21_API int CCONV CPhidget##pname##_set_On##param##_Handler(PHANDLE(pname), int (CCONV *fptr)(PHANDLE(pname), void *userPtr, int index, __VA_ARGS__), void *userPtr) DEPRECATE_GCC ;
+#define DEP_CHDREVENT(depmsg,pname,param,...) DEPRECATE_WIN(depmsg) PHIDGET21_API int CCONV CPhidget##pname##_set_On##param##_Handler(PHANDLE(pname), int (CCONV *fptr)(PHANDLE(pname), void *userPtr, __VA_ARGS__), void *userPtr) DEPRECATE_GCC ;
+
+#define DEP_CHDRGET(depmsg,pname,propname,...) DEPRECATE_WIN(depmsg) PHIDGET21_API int CCONV CPhidget##pname##_get##propname(PHANDLE(pname),__VA_ARGS__) DEPRECATE_GCC ;
+#define DEP_CHDRSET(depmsg,pname,propname,...) DEPRECATE_WIN(depmsg) PHIDGET21_API int CCONV CPhidget##pname##_set##propname(PHANDLE(pname), __VA_ARGS__) DEPRECATE_GCC ;
+
+#define DEP_CHDRGETINDEX(depmsg,pname,propname,...) DEPRECATE_WIN(depmsg) PHIDGET21_API int CCONV CPhidget##pname##_get##propname(PHANDLE(pname), int index, __VA_ARGS__) DEPRECATE_GCC ;
+#define DEP_CHDRSETINDEX(depmsg,pname,propname,...) DEPRECATE_WIN(depmsg) PHIDGET21_API int CCONV CPhidget##pname##_set##propname(PHANDLE(pname), int index, __VA_ARGS__) DEPRECATE_GCC ;
+
+
+#define TESTPTR(phidname) if (!phidname) return EPHIDGET_INVALIDARG;
+#define TESTPTRS(vname1,vname2) if ((!vname1) || (!vname2)) return EPHIDGET_INVALIDARG;
+#define TESTINDEX(vname1) if (Index >= phid->vname1 || Index < 0) return EPHIDGET_OUTOFBOUNDS;
+#define TESTMASGN(vname1, check) if(phid->vname1 == check) { *pVal = check; return EPHIDGET_UNKNOWNVAL; }
+#define TESTRANGE(min, max) if(newVal < (min) || newVal > (max)) return EPHIDGET_INVALIDARG;
+#define TESTDEVICETYPE(def) if (phid->phid.deviceID != def) return EPHIDGET_WRONGDEVICE;
+#define TESTATTACHED if (!CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_ATTACHED_FLAG)) return EPHIDGET_NOTATTACHED;
+#define MASGN(vname1) { *pVal = phid->vname1; return EPHIDGET_OK; }
+
+#define CFHANDLE(pname,param, ...) \
+PHIDGET21_API int CCONV CPhidget##pname##_set_On##param##_Handler(CPhidget##pname##Handle phidA, int (CCONV *fptr)(CPhidget##pname##Handle, void *userPtr, __VA_ARGS__ ), void *userPtr) \
+{ \
+ CPhidget##pname##Info *phid = (CPhidget##pname##Info *)phidA; \
+ TESTPTR(phid); \
+ phid->fptr##param = fptr; \
+ phid->fptr##param##ptr = userPtr; \
+ return EPHIDGET_OK; \
+}
+
+#define CPHIDGETDATA(pname) static int CPhidget##pname##_dataInput(CPhidgetHandle phidG, unsigned char *buffer, int length) \
+{ \
+ CPhidget##pname##Handle phid = (CPhidget##pname##Handle)phidG;
+
+#define FIRE(ename, ...) \
+if (phid->fptr##ename) \
+ if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_ATTACHED_FLAG)) \
+ phid->fptr##ename(phid, phid->fptr##ename##ptr, __VA_ARGS__)
+
+#define QUEUE_ERROR_EVENT(ecode, buf) \
+else \
+{ \
+ void **args = malloc(sizeof(void *)*2); \
+ if(args) \
+ { \
+ args[0] = strdup(buf); \
+ args[1] = (void *)(size_t)ecode; \
+ if(args[0]) \
+ { \
+ if(CList_addToList((CListHandle *)&((CPhidgetHandle)phid)->errEventList, args, CPhidgetHandle_areEqual)!=EPHIDGET_OK) \
+ { \
+ free(args[0]); \
+ free(args); \
+ } \
+ } \
+ else \
+ free(args); \
+ } \
+}
+
+#define FIRE_ERROR_BUF_INT(ecode, buf) \
+if(CPhidget_statusFlagIsSet(((CPhidgetHandle)phid)->status, PHIDGET_ATTACHED_FLAG)) \
+{ \
+ if (((CPhidgetHandle)phid)->fptrError) \
+ ((CPhidgetHandle)phid)->fptrError((CPhidgetHandle)phid, ((CPhidgetHandle)phid)->fptrErrorptr, ecode, buf); \
+} \
+
+#define FIRE_ERROR_BUF(ecode, buf) \
+FIRE_ERROR_BUF_INT(ecode, buf) \
+QUEUE_ERROR_EVENT(ecode, buf)
+
+#define FIRE_ERROR(ecode, ...) \
+snprintf(error_buffer,sizeof(error_buffer), __VA_ARGS__); \
+FIRE_ERROR_BUF_INT(ecode, error_buffer) \
+QUEUE_ERROR_EVENT(ecode, error_buffer)
+
+#define FIRE_ERROR_NOQUEUE(ecode, ...) \
+snprintf(error_buffer,sizeof(error_buffer), __VA_ARGS__); \
+FIRE_ERROR_BUF_INT(ecode, error_buffer)
+
+#define CGETINDEX(pname,propname,proptype) \
+PHIDGET21_API int CCONV CPhidget##pname##_get##propname(CPhidget##pname##Handle phid, int Index, proptype *pVal) {
+
+#define CGET(pname,propname,proptype) \
+PHIDGET21_API int CCONV CPhidget##pname##_get##propname(CPhidget##pname##Handle phid, proptype *pVal) {
+
+#define CSETINDEX(pname,propname,proptype) \
+PHIDGET21_API int CCONV CPhidget##pname##_set##propname(CPhidget##pname##Handle phid, int Index, proptype newVal) {
+
+#define CSET(pname,propname,proptype) \
+PHIDGET21_API int CCONV CPhidget##pname##_set##propname(CPhidget##pname##Handle phid, proptype newVal) {
+
+#define CPHIDGETCLEARVARS(pname) \
+static int CPhidget##pname##_clearVars(CPhidgetHandle phidG) \
+{ \
+ CPhidget##pname##Handle phid = (CPhidget##pname##Handle)phidG;
+
+#define CPHIDGETINIT(pname) \
+static int CPhidget##pname##_initAfterOpen(CPhidgetHandle phidG) \
+{ \
+ CPhidget##pname##Handle phid = (CPhidget##pname##Handle)phidG;
+
+#define CPHIDGETINITEVENTS(pname) \
+static int CPhidget##pname##_eventsAfterOpen(CPhidgetHandle phidG) \
+{ \
+ CPhidget##pname##Handle phid = (CPhidget##pname##Handle)phidG; \
+ int i = 0; \
+ CListHandle traverse = phidG->errEventList; \
+ for (; traverse; traverse = traverse->next) { \
+ if (phidG->fptrError) \
+ phidG->fptrError(phidG, phidG->fptrErrorptr, (int)*(int *)(&((void **)traverse->element)[1]), (char *)((void **)traverse->element)[0]); \
+ } \
+ CList_emptyList((CListHandle *)&phidG->errEventList, PTRUE, CPhidgetErrorEvent_free); \
+ i = 0;
+
+#define CSENDPACKET_BUF(pname) \
+static int CPhidget##pname##_sendpacket(CPhidget##pname##Handle phid, \
+ const unsigned char *buf) \
+{ \
+ int waitReturn; \
+ TESTPTRS(phid, buf) \
+again: \
+ if (!CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_ATTACHED_FLAG)) \
+ return EPHIDGET_NOTATTACHED; \
+ CThread_mutex_lock(&phid->phid.outputLock); \
+ if (phid->outputPacketLen) { \
+ CThread_mutex_unlock(&phid->phid.outputLock); \
+ waitReturn = CThread_wait_on_event(&phid->phid.writtenEvent, 1500); \
+ switch(waitReturn) \
+ { \
+ case WAIT_OBJECT_0: \
+ break; \
+ case WAIT_ABANDONED: \
+ return EPHIDGET_UNEXPECTED; \
+ case WAIT_TIMEOUT: \
+ return EPHIDGET_TIMEOUT; \
+ } \
+ goto again; \
+ } \
+ memcpy(phid->outputPacket, buf, phid->phid.outputReportByteLength); \
+ phid->outputPacketLen = phid->phid.outputReportByteLength; \
+ CThread_reset_event(&phid->phid.writtenEvent); \
+ CThread_mutex_unlock(&phid->phid.outputLock); \
+ CThread_set_event(&phid->phid.writeAvailableEvent); \
+ return 0; \
+}
+
+#define CMAKEPACKET(pname) \
+static int CPhidget##pname##_makePacket(CPhidget##pname##Handle phid, \
+ unsigned char *buffer) \
+{
+
+#define SENDPACKET(pname, propname) \
+ do{ \
+ unsigned char *buffer; \
+ int ret = 0; \
+ if(!(buffer = malloc(phid->phid.outputReportByteLength))) return EPHIDGET_NOMEMORY; \
+ ZEROMEM(buffer, phid->phid.outputReportByteLength); \
+ CThread_mutex_lock(&phid->phid.writelock); \
+ phid->propname = newVal; \
+ if((ret = CPhidget##pname##_makePacket(phid, buffer))) goto done; \
+ if((ret = CPhidget##pname##_sendpacket(phid, buffer))) goto done; \
+done: \
+ CThread_mutex_unlock(&phid->phid.writelock); \
+ free(buffer); \
+ if(ret) return ret; \
+ }while(0)
+
+#define CMAKEPACKETINDEXED(pname) \
+static int CPhidget##pname##_makePacket(CPhidget##pname##Handle phid, \
+ unsigned char *buffer, int Index) \
+{
+
+#define SENDPACKETINDEXED(pname, propname, index) \
+ do{ \
+ unsigned char *buffer; \
+ int ret = 0; \
+ if(!(buffer = malloc(phid->phid.outputReportByteLength))) return EPHIDGET_NOMEMORY; \
+ ZEROMEM(buffer, phid->phid.outputReportByteLength); \
+ CThread_mutex_lock(&phid->phid.writelock); \
+ phid->propname = newVal; \
+ if((ret = CPhidget##pname##_makePacket(phid, buffer, index))) goto done; \
+ if((ret = CPhidget##pname##_sendpacket(phid, buffer))) goto done; \
+done: \
+ CThread_mutex_unlock(&phid->phid.writelock); \
+ free(buffer); \
+ if(ret) return ret; \
+ }while(0)
+
+
+#define CGETPACKET(pname) \
+static int CPhidget##pname##_getPacket(CPhidgetHandle phidG, \
+ unsigned char *buf, unsigned int *lenp) \
+{
+
+#define CGETPACKET_BUF(pname) \
+static int CPhidget##pname##_getPacket(CPhidgetHandle phidG, \
+ unsigned char *buf, unsigned int *lenp) \
+{ \
+ CPhidget##pname##Handle phid = (CPhidget##pname##Handle)phidG; \
+ TESTPTRS(phid, buf) \
+ TESTPTR(lenp) \
+ CThread_mutex_lock(&phid->phid.outputLock); \
+ if (*lenp < phid->outputPacketLen) { \
+ CThread_mutex_unlock(&phid->phid.outputLock); \
+ return EPHIDGET_INVALIDARG; \
+ } \
+ memcpy(buf, phid->outputPacket, *lenp = phid->outputPacketLen); \
+ phid->outputPacketLen = 0; \
+ CThread_mutex_unlock(&phid->phid.outputLock); \
+ return EPHIDGET_OK; \
+}
+
+#define CCREATE_INT(pname,pdef) \
+ CPhidget##pname##Handle phid; \
+ TESTPTR(phidp) \
+ if (!(phid = (CPhidget##pname##Handle)malloc(sizeof (*phid)))) \
+ return EPHIDGET_NOMEMORY; \
+ ZEROMEM(phid, sizeof(*phid)); \
+ phid->phid.deviceID = pdef; \
+ phid->phid.fptrInit = CPhidget##pname##_initAfterOpen; \
+ phid->phid.fptrClear = CPhidget##pname##_clearVars; \
+ phid->phid.fptrEvents = CPhidget##pname##_eventsAfterOpen; \
+ phid->phid.fptrData = CPhidget##pname##_dataInput; \
+ phid->phid.fptrGetPacket = CPhidget##pname##_getPacket; \
+ CThread_mutex_init(&phid->phid.lock); \
+ CThread_mutex_init(&phid->phid.openCloseLock); \
+ CThread_mutex_init(&phid->phid.writelock); \
+ CThread_mutex_init(&phid->phid.outputLock); \
+ CPhidget_clearStatusFlag(&phid->phid.status, PHIDGET_ATTACHED_FLAG, &(&phid->phid)->lock); \
+ CThread_create_event(&phid->phid.writeAvailableEvent); \
+ CThread_create_event(&phid->phid.writtenEvent); \
+ *phidp = phid;
+
+#define CCREATE(pname,pdef) int CCONV CPhidget##pname##_create(CPhidget##pname##Handle *phidp) \
+{ \
+ CCREATE_INT(pname,pdef) \
+ return EPHIDGET_OK; \
+}
+
+#define CCREATE_EXTRA(pname,pdef) int CCONV CPhidget##pname##_create(CPhidget##pname##Handle *phidp) \
+{ \
+ CCREATE_INT(pname,pdef)
+
+#define ADDNETWORKKEYINDEXED(kname, valType, propname) \
+do{ \
+ char key[1024], val[1024]; \
+ CThread_mutex_lock(&phid->phid.lock); \
+ phid->propname[Index] = newVal; \
+ if(!CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_SERVER_CONNECTED_FLAG)) { \
+ CThread_mutex_unlock(&phid->phid.lock); \
+ return EPHIDGET_NETWORK_NOTCONNECTED; } \
+ snprintf(key, (unsigned int)sizeof(key), "/PCK/%s/%d/" #kname "/%d", phid->phid.deviceType, phid->phid.serialNumber, Index); \
+ snprintf(val, (int)sizeof(val), valType, newVal); \
+ pdc_async_set(phid->phid.networkInfo->server->pdcs, key, val, (int)strlen(val), PFALSE, internal_async_network_error_handler, &phid->phid); \
+ CThread_mutex_unlock(&phid->phid.lock); \
+}while(0)
+
+#define ADDNETWORKKEY(kname, valType, propname) \
+do{ \
+ char key[1024], val[1024]; \
+ CThread_mutex_lock(&phid->phid.lock); \
+ phid->propname = newVal; \
+ if(!CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_SERVER_CONNECTED_FLAG)) { \
+ CThread_mutex_unlock(&phid->phid.lock); \
+ return EPHIDGET_NETWORK_NOTCONNECTED; } \
+ snprintf(key, sizeof(key), "/PCK/%s/%d/" #kname , phid->phid.deviceType, phid->phid.serialNumber); \
+ snprintf(val, sizeof(val), valType, newVal); \
+ pdc_async_set(phid->phid.networkInfo->server->pdcs, key, val, (int)strlen(val), PFALSE, internal_async_network_error_handler, &phid->phid); \
+ CThread_mutex_unlock(&phid->phid.lock); \
+}while(0)
+
+/* used in csocketevents.c */
+#define PWC_SETKEYS(pname) \
+int phidget##pname##_set(CPhidgetHandle arg, const char *setThing, int index, const char *state, pdict_reason_t reason) \
+{ \
+ int ret = EPHIDGET_OK; \
+ CPhidget##pname##Handle phid = (CPhidget##pname##Handle)arg;
+
+#define GET_DOUBLE_VAL double value = strtod(state, NULL)
+#define GET_INT_VAL int value = strtol(state, NULL, 10)
+#define GET_INT64_VAL __int64 value = strtoll(state, NULL, 10)
+
+#define INC_KEYCOUNT(var, unktype) if(phid->var == unktype) phid->phid.keyCount++;
+#define KEYNAME(name) !strncmp(setThing, name, sizeof(name))
+#define CHKINDEX(atr, def) (index < phid->phid.attr.atr?phid->phid.attr.atr:def)
+
+#define PWC_BAD_SETTYPE(pname) \
+ do { \
+ ret = EPHIDGET_INVALIDARG; \
+ LOG(PHIDGET_LOG_DEBUG,"Bad setType for " #pname ": %s", setThing); \
+ }while(0)
+
+#endif
diff --git a/cphidgetmanager.c b/cphidgetmanager.c
new file mode 100644
index 0000000..eecdb04
--- /dev/null
+++ b/cphidgetmanager.c
@@ -0,0 +1,492 @@
+
+#include "stdafx.h"
+#include "cphidgetmanager.h"
+#include "cphidget.h"
+#include "cthread.h"
+#include "cusb.h"
+#include "cphidgetlist.h"
+#include "csocket.h"
+
+/* A list of local Phidget Managers */
+CPhidgetManagerListHandle localPhidgetManagers = NULL;
+int ActivePhidgetManagers = 0;
+
+/* Protects localPhidgetManagers */
+int managerLockInitialized = PFALSE;
+CThread_mutex_t managerLock;
+
+int CPhidgetManager_areEqual(void *arg1, void *arg2)
+{
+ if(arg1 == arg2) return 1;
+ return 0;
+}
+
+void CPhidgetManager_free(void *arg)
+{
+ CPhidgetManagerHandle phidm = (CPhidgetManagerHandle)arg;
+ if(!phidm) return;
+
+ if(CPhidget_statusFlagIsSet(phidm->status, PHIDGET_REMOTE_FLAG))
+ {
+ CList_emptyList((CListHandle *)&phidm->AttachedPhidgets, PTRUE, CPhidget_free);
+ }
+
+ CThread_mutex_destroy(&phidm->lock);
+ CThread_mutex_destroy(&phidm->openCloseLock);
+
+ free(phidm); phidm = NULL;
+ return;
+}
+
+int CCONV CPhidgetManager_set_OnError_Handler(CPhidgetManagerHandle phidm,
+ int(CCONV *fptr)(CPhidgetManagerHandle, void *, int, const char *), void *userPtr)
+{
+ TESTPTR(phidm)
+ phidm->fptrError = fptr;
+ phidm->fptrErrorptr = userPtr;
+ return EPHIDGET_OK;
+}
+
+/* The internal event handlers for PhidgetManager - these should be called directly from the usb functions...
+ * these run in the context of the central thread
+ * if AddDevice returns EPHIDGET_DUPLICATE, the user callback is not run (good)
+ */
+int CPhidgetAttachEvent(CPhidgetHandle phid) {
+ int result = 0;
+ CPhidgetManagerList *trav2 = 0;
+ TESTPTR(phid)
+ result = CList_addToList((CListHandle *)&AttachedDevices, phid, CPhidget_areEqual);
+ if(result == EPHIDGET_DUPLICATE)
+ {
+ return EPHIDGET_OK;
+ }
+ else if(result)
+ {
+ return result;
+ }
+
+ for(trav2 = localPhidgetManagers; trav2; trav2 = trav2->next)
+ {
+ if (trav2->phidm->fptrAttachChange && trav2->phidm->state == PHIDGETMANAGER_ACTIVE)
+ {
+ //So we can access AttachedDevices from within the manager atach event
+ CThread_mutex_unlock(&attachedDevicesLock);
+ trav2->phidm->fptrAttachChange((CPhidgetHandle)phid, trav2->phidm->fptrAttachChangeptr);
+ CThread_mutex_lock(&attachedDevicesLock);
+ }
+ }
+
+ return findActiveDevice(phid);
+}
+
+int CPhidgetDetachEvent(CPhidgetHandle phid) {
+ int result = 0;
+ CPhidgetList *trav = 0;
+ CPhidgetManagerList *trav2 = 0;
+ CPhidgetHandle travPhid = 0;
+ TESTPTR(phid)
+ CPhidget_clearStatusFlag(&phid->status, PHIDGET_ATTACHED_FLAG, NULL);
+ CPhidget_setStatusFlag(&phid->status, PHIDGET_DETACHING_FLAG, NULL);
+
+ CList_removeFromList((CListHandle *)&AttachedDevices, phid, CPhidget_areExtraEqual, FALSE, NULL);
+ for(trav2 = localPhidgetManagers; trav2; trav2 = trav2->next)
+ {
+ if (trav2->phidm->fptrDetachChange && trav2->phidm->state == PHIDGETMANAGER_ACTIVE)
+ {
+ //So we can access AttachedDevices from within the manager atach event
+ CThread_mutex_unlock(&attachedDevicesLock);
+ trav2->phidm->fptrDetachChange((CPhidgetHandle)phid, trav2->phidm->fptrDetachChangeptr);
+ CThread_mutex_lock(&attachedDevicesLock);
+ }
+ }
+ CPhidget_clearStatusFlag(&phid->status, PHIDGET_DETACHING_FLAG, NULL);
+
+ CThread_mutex_lock(&activeDevicesLock);
+ for (trav=ActiveDevices; trav; trav = trav->next)
+ {
+ if((CPhidget_areExtraEqual(phid, trav->phid) && CPhidget_statusFlagIsSet(trav->phid->status, PHIDGET_ATTACHED_FLAG))
+ || CPhidgetHandle_areEqual(phid, trav->phid))
+ {
+ CPhidget_setStatusFlag(&trav->phid->status, PHIDGET_DETACHING_FLAG, &trav->phid->lock);
+ if(trav->phid->specificDevice == PHIDGETOPEN_ANY_ATTACHED)
+ trav->phid->specificDevice = PHIDGETOPEN_ANY;
+
+ trav->phid->writeStopFlag = PTRUE;
+ CThread_set_event(&trav->phid->writeAvailableEvent); //if it's waiting on this event - signal NOW
+
+ result = CUSBCloseHandle(trav->phid);
+ CThread_join(&trav->phid->writeThread);
+ CThread_join(&trav->phid->readThread);
+
+ //because trav can be freed during the detach call, don't use it in or after the call
+ travPhid = trav->phid;
+ CThread_mutex_unlock(&activeDevicesLock);
+ if (travPhid->fptrDetach)
+ travPhid->fptrDetach((CPhidgetHandle)travPhid, travPhid->fptrDetachptr);
+
+ travPhid->deviceIDSpec = 0;
+
+#if !defined(_MACOSX) && !defined(WINCE)
+ CPhidgetFHandle_free(travPhid->CPhidgetFHandle);
+ travPhid->CPhidgetFHandle = NULL;
+#endif
+
+ CPhidget_clearStatusFlag(&travPhid->status, PHIDGET_DETACHING_FLAG, &travPhid->lock);
+ CPhidget_clearStatusFlag(&travPhid->status, PHIDGET_USB_ERROR_FLAG, &travPhid->lock);
+ goto found_to_detach;
+ }
+
+ }
+ CThread_mutex_unlock(&activeDevicesLock);
+
+found_to_detach:
+ CPhidget_free(phid);
+
+ return result;
+}
+
+// sends out any initial attach events for new managers
+static int sendInitialEvents()
+{
+ CPhidgetManagerList *managerList = 0;
+ CPhidgetList *phidList = 0;
+
+ for(managerList = localPhidgetManagers; managerList; managerList = managerList->next)
+ {
+ if (managerList->phidm->state == PHIDGETMANAGER_ACTIVATING)
+ {
+ managerList->phidm->state = PHIDGETMANAGER_ACTIVE;
+
+ if (managerList->phidm->fptrAttachChange)
+ {
+ for (phidList=AttachedDevices; phidList; phidList = phidList->next)
+ {
+ //So we can access AttachedDevices from within the manager atach event
+ CThread_mutex_unlock(&attachedDevicesLock);
+ managerList->phidm->fptrAttachChange((CPhidgetHandle)(phidList->phid), managerList->phidm->fptrAttachChangeptr);
+ CThread_mutex_lock(&attachedDevicesLock);
+ }
+ }
+ }
+ }
+
+ return EPHIDGET_OK;
+}
+
+int CPhidgetManager_poll()
+{
+ CPhidgetList *curList = 0, *detachList = 0;
+ CPhidgetList *trav = 0;
+ CPhidgetHandle foundPhidget;
+
+ if(!managerLockInitialized)
+ {
+ CThread_mutex_init(&managerLock);
+ managerLockInitialized = PTRUE;
+ }
+
+ CThread_mutex_lock(&managerLock);
+ CThread_mutex_lock(&attachedDevicesLock);
+
+ sendInitialEvents();
+
+ CUSBBuildList(&curList);
+
+
+ for (trav=AttachedDevices; trav; trav = trav->next)
+ {
+ if(CList_findInList((CListHandle)curList, trav->phid, CPhidget_areExtraEqual, NULL) == EPHIDGET_NOTFOUND)
+ {
+ CList_addToList((CListHandle *)&detachList, trav->phid, CPhidget_areEqual);
+ }
+ }
+ for (trav=curList; trav; trav = trav->next)
+ {
+ if(CList_findInList((CListHandle)AttachedDevices, trav->phid, CPhidget_areExtraEqual, NULL) ==
+ EPHIDGET_NOTFOUND)
+ {
+ CPhidgetAttachEvent(trav->phid);
+ }
+
+ //if PHIDGET_USB_ERROR_FLAG is set, cycle device through a detach
+ //if it's ok, it will re-attach
+
+ CThread_mutex_lock(&activeDevicesLock);
+ if(CList_findInList((CListHandle)ActiveDevices, trav->phid, CPhidget_areEqual, (void **)&foundPhidget) == EPHIDGET_OK)
+ {
+ if(CPhidget_statusFlagIsSet(foundPhidget->status, PHIDGET_ATTACHED_FLAG))
+ {
+ if(CPhidget_statusFlagIsSet(foundPhidget->status, PHIDGET_USB_ERROR_FLAG))
+ {
+ LOG(PHIDGET_LOG_WARNING,"PHIDGET_USB_ERROR_FLAG is set - cycling device through a detach");
+ CList_addToList((CListHandle *)&detachList, trav->phid, CPhidget_areEqual);
+ }
+ }
+ }
+ CThread_mutex_unlock(&activeDevicesLock);
+ }
+ for (trav=detachList; trav; trav = trav->next)
+ {
+ CPhidgetDetachEvent(trav->phid);
+ }
+ CList_emptyList((CListHandle *)&detachList, FALSE, NULL);
+ CList_emptyList((CListHandle *)&curList, FALSE, NULL);
+
+ CThread_mutex_unlock(&attachedDevicesLock);
+ CThread_mutex_unlock(&managerLock);
+ return EPHIDGET_OK;
+}
+
+int CCONV CPhidgetManager_create(CPhidgetManagerHandle *phidm)
+{
+ CPhidgetManagerHandle phidmtemp = 0;
+
+ TESTPTR(phidm)
+ if(!(phidmtemp = (CPhidgetManagerHandle)malloc(sizeof(CPhidgetManager))))
+ return EPHIDGET_NOMEMORY;
+ ZEROMEM(phidmtemp, sizeof(CPhidgetManager));
+
+ phidmtemp->state = PHIDGETMANAGER_INACTIVE;
+
+ if(!managerLockInitialized)
+ {
+ CThread_mutex_init(&managerLock);
+ managerLockInitialized = PTRUE;
+ }
+
+ CThread_mutex_init(&phidmtemp->lock);
+ CThread_mutex_init(&phidmtemp->openCloseLock);
+
+ *phidm = phidmtemp;
+ return EPHIDGET_OK;
+}
+
+int CCONV CPhidgetManager_close(CPhidgetManagerHandle phidm)
+{
+ TESTPTR(phidm)
+
+ CThread_mutex_lock(&phidm->openCloseLock);
+ if (!CPhidget_statusFlagIsSet(phidm->status, PHIDGET_OPENED_FLAG))
+ {
+ LOG(PHIDGET_LOG_WARNING, "Close was called on an already closed Manager handle.");
+ CThread_mutex_unlock(&phidm->openCloseLock);
+ return EPHIDGET_OK;
+ }
+
+ if(phidm->state == PHIDGETMANAGER_ACTIVE || phidm->state == PHIDGETMANAGER_ACTIVATING)
+ {
+ phidm->state = PHIDGETMANAGER_INACTIVE;
+ CPhidget_clearStatusFlag(&phidm->status, PHIDGET_ATTACHED_FLAG, &phidm->lock);
+ if(CPhidget_statusFlagIsSet(phidm->status, PHIDGET_REMOTE_FLAG))
+ {
+ //Only free the list phidgets if this is an openRemoteIP - not for openRemote
+ int freeList = phidm->networkInfo->mdns ? PFALSE : PTRUE;
+ unregisterRemoteManager(phidm);
+
+ CList_emptyList((CListHandle *)&phidm->AttachedPhidgets, freeList, CPhidget_free);
+ }
+ else
+ {
+ CThread_mutex_lock(&managerLock);
+ ActivePhidgetManagers--;
+ CList_removeFromList((CListHandle *)&localPhidgetManagers, phidm, CPhidgetManager_areEqual, PFALSE, NULL);
+ CThread_mutex_unlock(&managerLock);
+ }
+ }
+
+ //if there are no more active phidgets or managers, wait for the central thread to exit
+ if(!ActiveDevices && !ActivePhidgetManagers)
+ {
+ JoinCentralThread();
+ }
+
+ CPhidget_clearStatusFlag(&phidm->status, PHIDGET_OPENED_FLAG, &phidm->lock);
+ CThread_mutex_unlock(&phidm->openCloseLock);
+ return EPHIDGET_OK;
+}
+
+int CCONV CPhidgetManager_delete(CPhidgetManagerHandle phidm)
+{
+ CPhidgetManager_free(phidm);
+ return EPHIDGET_OK;
+}
+
+int CCONV CPhidgetManager_getServerID(CPhidgetManagerHandle phidm, const char **serverID)
+{
+ return CPhidget_getServerID((CPhidgetHandle)phidm, serverID);
+}
+int CCONV CPhidgetManager_getServerAddress(CPhidgetManagerHandle phidm, const char **address, int *port)
+{
+ return CPhidget_getServerAddress((CPhidgetHandle)phidm, address, port);
+}
+int CCONV CPhidgetManager_getServerStatus(CPhidgetManagerHandle phidm, int *status)
+{
+ return CPhidget_getServerStatus((CPhidgetHandle)phidm, status);
+}
+
+int CCONV CPhidgetManager_open(CPhidgetManagerHandle phidm)
+{
+ int result = EPHIDGET_OK;
+
+ TESTPTR(phidm)
+
+#if defined(_IPHONE)
+ return EPHIDGET_UNSUPPORTED;
+#endif
+
+#if defined(_ANDROID)
+ if(!ANDROID_USB_GOOD)
+ return EPHIDGET_UNSUPPORTED;
+#endif
+
+ CThread_mutex_lock(&phidm->openCloseLock);
+ if (CPhidget_statusFlagIsSet(phidm->status, PHIDGET_OPENED_FLAG))
+ {
+ LOG(PHIDGET_LOG_WARNING, "Open was called on an already opened Manager handle.");
+ CThread_mutex_unlock(&phidm->openCloseLock);
+ return EPHIDGET_OK;
+ }
+
+ if(!phidgetLocksInitialized)
+ {
+ CThread_mutex_init(&activeDevicesLock);
+ CThread_mutex_init(&attachedDevicesLock);
+ phidgetLocksInitialized = PTRUE;
+ }
+
+ if(phidm->state == PHIDGETMANAGER_INACTIVE)
+ {
+ CThread_mutex_lock(&managerLock);
+
+ CList_addToList((CListHandle *)&localPhidgetManagers, phidm, CPhidgetManager_areEqual);
+
+#ifdef _MACOSX
+ phidm->state = PHIDGETMANAGER_ACTIVE;
+#else
+ phidm->state = PHIDGETMANAGER_ACTIVATING;
+#endif
+
+ CPhidget_setStatusFlag(&phidm->status, PHIDGET_ATTACHED_FLAG, &phidm->lock);
+
+ ActivePhidgetManagers++;
+
+ CThread_mutex_unlock(&managerLock);
+
+ result = StartCentralThread();
+ }
+
+ CPhidget_setStatusFlag(&phidm->status, PHIDGET_OPENED_FLAG, &phidm->lock);
+ CThread_mutex_unlock(&phidm->openCloseLock);
+ return result;
+}
+
+int CCONV CPhidgetManager_set_OnAttach_Handler(CPhidgetManagerHandle phidm, int (CCONV *fptr)(CPhidgetHandle phid, void *userPtr), void *userPtr)
+{
+ TESTPTR(phidm)
+ phidm->fptrAttachChange = fptr;
+ phidm->fptrAttachChangeptr = userPtr;
+ return EPHIDGET_OK;
+}
+int CCONV CPhidgetManager_set_OnDetach_Handler(CPhidgetManagerHandle phidm, int (CCONV *fptr)(CPhidgetHandle phid, void *userPtr), void *userPtr)
+{
+ TESTPTR(phidm)
+ phidm->fptrDetachChange = fptr;
+ phidm->fptrDetachChangeptr = userPtr;
+ return EPHIDGET_OK;
+}
+int CCONV CPhidgetManager_set_OnServerConnect_Handler(CPhidgetManagerHandle phidm, int (CCONV *fptr)(CPhidgetManagerHandle phidm, void *userPtr), void *userPtr)
+{
+ TESTPTR(phidm)
+ phidm->fptrServerConnect = fptr;
+ phidm->fptrServerConnectptr = userPtr;
+ return EPHIDGET_OK;
+}
+int CCONV CPhidgetManager_set_OnServerDisconnect_Handler(CPhidgetManagerHandle phidm, int (CCONV *fptr)(CPhidgetManagerHandle phidm, void *userPtr), void *userPtr)
+{
+ TESTPTR(phidm)
+ phidm->fptrServerDisconnect = fptr;
+ phidm->fptrServerDisconnectptr = userPtr;
+ return EPHIDGET_OK;
+}
+
+int CCONV CPhidgetManager_freeAttachedDevicesArray(CPhidgetHandle phidArray[])
+{
+ if(!phidArray) return EPHIDGET_OK;
+ free(phidArray); phidArray = NULL;
+ return EPHIDGET_OK;
+}
+
+int CCONV CPhidgetManager_getAttachedDevices(CPhidgetManagerHandle phidm, CPhidgetHandle *phidArray[], int *count)
+{
+ CPhidgetList *trav = 0;
+ int i = 0;
+
+ TESTPTRS(phidArray, count)
+ TESTPTR(phidm)
+
+ *count = 0;
+ if(CPhidget_statusFlagIsSet(phidm->status, PHIDGET_REMOTE_FLAG))
+ {
+ for (trav=phidm->AttachedPhidgets; trav; trav = trav->next)
+ {
+ if (CPhidget_statusFlagIsSet(trav->phid->status, PHIDGET_ATTACHED_FLAG))
+ (*count)++;
+ }
+
+ if(*count==0)
+ {
+ *phidArray = NULL;
+ }
+ else
+ {
+ *phidArray = (CPhidgetHandle *)malloc(sizeof(**phidArray) * *count);
+ if (!*phidArray)
+ return EPHIDGET_NOMEMORY;
+ ZEROMEM(*phidArray, sizeof(**phidArray) * *count);
+
+ for (trav=phidm->AttachedPhidgets, i=0; trav; trav = trav->next)
+ {
+ if (CPhidget_statusFlagIsSet(trav->phid->status, PHIDGET_ATTACHED_FLAG))
+ {
+ (*phidArray)[i] = trav->phid;
+ i++;
+ }
+ }
+ }
+ }
+ else
+ {
+ CThread_mutex_lock(&attachedDevicesLock);
+ for (trav=AttachedDevices; trav; trav = trav->next)
+ {
+ if (CPhidget_statusFlagIsSet(trav->phid->status, PHIDGET_ATTACHED_FLAG))
+ (*count)++;
+ }
+ if(*count==0)
+ {
+ *phidArray = NULL;
+ }
+ else
+ {
+ *phidArray = (CPhidgetHandle *)malloc(sizeof(**phidArray) * *count);
+ if (!*phidArray)
+ {
+ CThread_mutex_unlock(&attachedDevicesLock);
+ return EPHIDGET_NOMEMORY;
+ }
+ ZEROMEM(*phidArray, sizeof(**phidArray) * *count);
+
+ for (trav=AttachedDevices, i=0; trav; trav = trav->next)
+ {
+ if (CPhidget_statusFlagIsSet(trav->phid->status, PHIDGET_ATTACHED_FLAG))
+ {
+ (*phidArray)[i] = trav->phid;
+ i++;
+ }
+ }
+ }
+
+ CThread_mutex_unlock(&attachedDevicesLock);
+ }
+ return EPHIDGET_OK;
+}
diff --git a/cphidgetmanager.h b/cphidgetmanager.h
new file mode 100644
index 0000000..fedc008
--- /dev/null
+++ b/cphidgetmanager.h
@@ -0,0 +1,153 @@
+#ifndef __CPHIDGETMANAGER
+#define __CPHIDGETMANAGER
+#include "cphidget.h"
+
+/** \defgroup phidmanager Phidget Manager
+ * Calls specific to the Phidget Manager. The Phidget Manager allows enumeration of all connected devices and notification of device
+ * attach and detach events.
+ * @{
+ */
+
+/**
+ * A Phidget Manager handle.
+ */
+DPHANDLE(Manager)
+
+#ifndef EXTERNALPROTO
+
+typedef enum
+{
+ PHIDGETMANAGER_INACTIVE = 1,
+ PHIDGETMANAGER_ACTIVE,
+ PHIDGETMANAGER_ACTIVATING
+} CPhidgetManagerState;
+
+typedef struct _CPhidgetManager
+{
+ CPhidgetRemoteHandle networkInfo;
+ int(CCONV *fptrError)(CPhidgetManagerHandle , void *, int, const char *);
+ void *fptrErrorptr;
+ int(CCONV *fptrServerConnect)(CPhidgetManagerHandle , void *);
+ void *fptrServerConnectptr;
+ int(CCONV *fptrServerDisconnect)(CPhidgetManagerHandle , void *);
+ void *fptrServerDisconnectptr;
+ CThread_mutex_t lock; /* protects status */
+ int status;
+ CThread_mutex_t openCloseLock; /* protects open / close */
+ CPhidgetManagerState state;
+ CPhidgetList *AttachedPhidgets;
+ int (CCONV *fptrAttachChange)(CPhidgetHandle phid, void *userPtr);
+ void *fptrAttachChangeptr;
+ int (CCONV *fptrDetachChange)(CPhidgetHandle phid, void *userPtr);
+ void *fptrDetachChangeptr;
+} CPhidgetManager;
+
+typedef struct _CPhidgetManagerList
+{
+ struct _CPhidgetManagerList *next;
+ CPhidgetManager *phidm;
+} CPhidgetManagerList, *CPhidgetManagerListHandle;
+
+extern CPhidgetManagerListHandle localPhidgetManagers;
+extern int ActivePhidgetManagers;
+
+int CPhidgetManager_poll();
+int CPhidgetAttachEvent(CPhidgetHandle phid);
+int CPhidgetDetachEvent(CPhidgetHandle phid);
+
+int CPhidgetManager_areEqual(void *arg1, void *arg2);
+void CPhidgetManager_free(void *arg);
+#endif
+
+/**
+ * Creates a Phidget Manager handle.
+ * @param phidm A pointer to an empty phidget manager handle.
+ */
+PHIDGET21_API int CCONV CPhidgetManager_create(CPhidgetManagerHandle *phidm);
+/**
+ * Opens a Phidget Manager.
+ * @param phidm A phidget manager handle.
+ */
+PHIDGET21_API int CCONV CPhidgetManager_open(CPhidgetManagerHandle phidm);
+/**
+ * Closes a Phidget Manager.
+ * @param phidm An opened phidget manager handle.
+ */
+PHIDGET21_API int CCONV CPhidgetManager_close(CPhidgetManagerHandle phidm);
+/**
+ * Frees a Phidget Manager handle.
+ * @param phidm A closed phidget manager handle.
+ */
+PHIDGET21_API int CCONV CPhidgetManager_delete(CPhidgetManagerHandle phidm);
+/**
+ * Sets an attach handler callback function. This is called when a Phidget is plugged into the system.
+ * @param phidm A phidget manager handle.
+ * @param fptr Callback function pointer.
+ * @param userPtr A pointer for use by the user - this value is passed back into the callback function.
+ */
+PHIDGET21_API int CCONV CPhidgetManager_set_OnAttach_Handler(CPhidgetManagerHandle phidm, int (CCONV *fptr)(CPhidgetHandle phid, void *userPtr), void *userPtr);
+/**
+ * Sets a detach handler callback function. This is called when a Phidget is unplugged from the system.
+ * @param phidm A phidget manager handle.
+ * @param fptr Callback function pointer.
+ * @param userPtr A pointer for use by the user - this value is passed back into the callback function.
+ */
+PHIDGET21_API int CCONV CPhidgetManager_set_OnDetach_Handler(CPhidgetManagerHandle phidm, int (CCONV *fptr)(CPhidgetHandle phid, void *userPtr), void *userPtr);
+/**
+ * Gets a list of all currently attached Phidgets. When you are finished with the list, free it with CPhidgetManager_freeAttachedDevicesArray.
+ * @param phidm An opened phidget manager handle.
+ * @param phidArray An empty pointer for returning the list of Phidgets. Note that this list is created internally, you don't need to pass in a array.
+ * @param count An int pointer for returning the list size
+ */
+PHIDGET21_API int CCONV CPhidgetManager_getAttachedDevices(CPhidgetManagerHandle phidm, CPhidgetHandle *phidArray[], int *count);
+/**
+ * Frees the array that is allocated when CPhidgetManager_getAttachedDevices is called. Since the array is malloced internally to the library, it
+ * should also be freed internally to the library.
+ * @param phidArray An array of CPhidgetHandles.
+ */
+PHIDGET21_API int CCONV CPhidgetManager_freeAttachedDevicesArray(CPhidgetHandle phidArray[]);
+/**
+ * Sets the error handler callback function. This is called when an asynchronous error occurs.
+ * @param phidm A phidget manager handle.
+ * @param fptr Callback function pointer.
+ * @param userPtr A pointer for use by the user - this value is passed back into the callback function.
+ */
+PHIDGET21_API int CCONV CPhidgetManager_set_OnError_Handler(CPhidgetManagerHandle phidm, int(CCONV *fptr)(CPhidgetManagerHandle phidm, void *userPtr, int errorCode, const char *errorString), void *userPtr);
+/**
+ * Sets a server connect handler callback function. This is used for opening Phidget Managers remotely, and is called when a connection to the sever has been made.
+ * @param phidm A phidget manager handle.
+ * @param fptr Callback function pointer.
+ * @param userPtr A pointer for use by the user - this value is passed back into the callback function.
+ */
+PHIDGET21_API int CCONV CPhidgetManager_set_OnServerConnect_Handler(CPhidgetManagerHandle phidm, int (CCONV *fptr)(CPhidgetManagerHandle phidm, void *userPtr), void *userPtr);
+/**
+ * Sets a server disconnect handler callback function. This is used for opening Phidget Managers remotely, and is called when a connection to the server has been lost.
+ * @param phidm A phidget manager handle.
+ * @param fptr Callback function pointer.
+ * @param userPtr A pointer for use by the user - this value is passed back into the callback function.
+ */
+PHIDGET21_API int CCONV CPhidgetManager_set_OnServerDisconnect_Handler(CPhidgetManagerHandle phidm, int (CCONV *fptr)(CPhidgetManagerHandle phidm, void *userPtr), void *userPtr);
+/**
+ * Gets the server ID of a remotely opened Phidget Manager. This will fail if the manager was opened locally.
+ * @param phidm A connected phidget manager handle.
+ * @param serverID A pointer which will be set to a char array containing the server ID string.
+ */
+PHIDGET21_API int CCONV CPhidgetManager_getServerID(CPhidgetManagerHandle phidm, const char **serverID);
+/**
+ * Gets the address and port of a remotely opened Phidget Manager. This will fail if the manager was opened locally.
+ * @param phidm A connected phidget manager handle.
+ * @param address A pointer which will be set to a char array containing the address string.
+ * @param port An int pointer for returning the port number.
+ */
+PHIDGET21_API int CCONV CPhidgetManager_getServerAddress(CPhidgetManagerHandle phidm, const char **address, int *port);
+/**
+ * Gets the connected to server status of a remotely opened Phidget Manager. This will fail if the manager was opened locally.
+ * @param phidm An opened phidget manager handle.
+ * @param serverStatus An int pointer for returning the server status. Possible codes are \ref PHIDGET_ATTACHED and \ref PHIDGET_NOTATTACHED.
+ */
+PHIDGET21_API int CCONV CPhidgetManager_getServerStatus(CPhidgetManagerHandle phidm, int *serverStatus);
+
+/** @} */
+
+#endif
+
diff --git a/cphidgetmotorcontrol.c b/cphidgetmotorcontrol.c
new file mode 100644
index 0000000..73b1363
--- /dev/null
+++ b/cphidgetmotorcontrol.c
@@ -0,0 +1,1022 @@
+#include <string.h>
+#include <assert.h>
+#include "stdafx.h"
+#include "cphidgetmotorcontrol.h"
+#include "cusb.h"
+#include "csocket.h"
+#include "cthread.h"
+
+// === Internal Functions === //
+
+//clearVars - sets all device variables to unknown state
+CPHIDGETCLEARVARS(MotorControl)
+ int i = 0;
+
+ phid->accelerationMax = PUNI_DBL;
+ phid->accelerationMin = PUNI_DBL;
+
+ for (i = 0; i<MOTORCONTROL_MAXINPUTS; i++)
+ {
+ phid->inputState[i] = PUNI_BOOL;
+ }
+ for (i = 0; i<MOTORCONTROL_MAXMOTORS; i++)
+ {
+ phid->motorSpeedEcho[i] = PUNI_DBL;
+ phid->motorSensedCurrent[i] = PUNI_DBL;
+ phid->motorSensedBackEMF[i] = PUNI_DBL;
+ phid->motorSetSpeedEcho[i] = PUNK_DBL;
+ phid->motorAccelerationEcho[i] = PUNI_DBL;
+ phid->motorBrakingEcho[i] = PUNI_DBL;
+ phid->backEMFSensingStateEcho[i] = PUNI_BOOL;
+
+ phid->motorSpeed[i] = PUNK_DBL;
+ phid->motorAcceleration[i] = PUNK_DBL;
+ phid->motorBraking[i] = PUNK_DBL;
+ phid->backEMFSensingState[i] = PUNK_BOOL;
+ phid->motorErrors[i] = 0;
+ }
+ phid->supplyVoltage = PUNI_DBL;
+ for(i = 0; i<MOTORCONTROL_MAXENCODERS; i++)
+ {
+ phid->encoderPositionEcho[i] = 0;
+ phid->encoderTimeStamp[i] = 0;
+ phid->encoderPositionDelta[i] = 0;
+ }
+ for(i = 0; i<MOTORCONTROL_MAXSENSORS; i++)
+ {
+ phid->sensorRawValue[i] = PUNI_INT;
+ phid->sensorValue[i] = PUNI_INT;
+ }
+ phid->ratiometricEcho = PUNI_BOOL;
+ phid->ratiometric = PUNK_BOOL;
+
+ return EPHIDGET_OK;
+}
+
+//initAfterOpen - sets up the initial state of an object, reading in packets from the device if needed
+// used during attach initialization - on every attach
+CPHIDGETINIT(MotorControl)
+ int i = 0;
+ int readtries = 0;
+
+ TESTPTR(phid);
+
+ //Make sure no old writes are still pending
+ phid->outputPacketLen = 0;
+
+ //Setup max/min values
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_MOTORCONTROL_LV_2MOTOR_4INPUT:
+ case PHIDID_MOTORCONTROL_HC_2MOTOR:
+ if ((phid->phid.deviceVersion >= 100) && (phid->phid.deviceVersion < 200))
+ {
+ phid->accelerationMax = 100;
+ phid->accelerationMin = round_double((1.0 / 10.23), 2);
+ }
+ else
+ return EPHIDGET_BADVERSION;
+ break;
+ case PHIDID_MOTORCONTROL_1MOTOR:
+ if ((phid->phid.deviceVersion >= 100) && (phid->phid.deviceVersion < 200))
+ {
+ phid->accelerationMax = 100/0.016; //0-100 in 16ms
+ phid->accelerationMin = round_double(100/4.08, 2); //0-100 in 4.08 seconds
+ }
+ else
+ return EPHIDGET_BADVERSION;
+ break;
+ default:
+ return EPHIDGET_UNEXPECTED;
+ }
+
+ //initialize triggers, set data arrays to unknown
+ for (i = 0; i<phid->phid.attr.motorcontrol.numInputs; i++)
+ {
+ phid->inputState[i] = PUNK_BOOL;
+ }
+ for (i = 0; i<phid->phid.attr.motorcontrol.numMotors; i++)
+ {
+ phid->motorSpeedEcho[i] = PUNK_DBL;
+ phid->motorSensedCurrent[i] = PUNK_DBL;
+ phid->motorSensedBackEMF[i] = PUNK_DBL;
+ phid->motorSetSpeedEcho[i] = PUNK_DBL;
+ phid->motorAccelerationEcho[i] = PUNK_DBL;
+ //set some defaults for devices that don't support these
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_MOTORCONTROL_LV_2MOTOR_4INPUT:
+ case PHIDID_MOTORCONTROL_HC_2MOTOR:
+ phid->motorBrakingEcho[i] = 0;
+ phid->backEMFSensingStateEcho[i] = PFALSE;
+ break;
+ case PHIDID_MOTORCONTROL_1MOTOR:
+ phid->motorBrakingEcho[i] = PUNK_DBL;
+ phid->backEMFSensingStateEcho[i] = PUNK_BOOL;
+ break;
+ default:
+ break;
+ }
+ phid->motorErrors[i] = 0;
+ }
+ phid->supplyVoltage = PUNK_DBL;
+ phid->lastVoltage = PUNK_DBL;
+ for(i = 0; i<phid->phid.attr.motorcontrol.numEncoders; i++)
+ {
+ phid->encoderPositionEcho[i] = 0;
+ phid->encoderTimeStamp[i] = 0;
+ phid->encoderPositionDelta[i] = 0;
+ }
+ for(i = 0; i<phid->phid.attr.motorcontrol.numSensors; i++)
+ {
+ phid->sensorRawValue[i] = PUNK_INT;
+ phid->sensorValue[i] = PUNK_INT;
+ }
+ phid->ratiometricEcho = PUNK_BOOL;
+
+ phid->lastPacketCount = PUNK_INT;
+
+ //read in initial state
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_MOTORCONTROL_LV_2MOTOR_4INPUT:
+ case PHIDID_MOTORCONTROL_1MOTOR:
+ readtries = 1;
+ break;
+ case PHIDID_MOTORCONTROL_HC_2MOTOR:
+ readtries = phid->phid.attr.motorcontrol.numMotors * 2;
+ break;
+ default:
+ return EPHIDGET_UNEXPECTED;
+ }
+ while(readtries-- > 0)
+ {
+ CPhidget_read((CPhidgetHandle)phid);
+ for (i = 0; i<phid->phid.attr.motorcontrol.numMotors; i++)
+ if(phid->motorSpeedEcho[i] == PUNK_DBL)
+ break;
+ if(i==phid->phid.attr.motorcontrol.numMotors) break;
+ }
+
+ //recover what we can, set others to unknown
+ for (i = 0; i<phid->phid.attr.motorcontrol.numMotors; i++)
+ {
+ if(phid->motorSetSpeedEcho[i] != PUNK_DBL)
+ phid->motorSpeed[i] = phid->motorSetSpeedEcho[i];
+ else
+ phid->motorSpeed[i] = phid->motorSpeedEcho[i];
+ phid->motorAcceleration[i] = phid->motorAccelerationEcho[i];
+ phid->motorBraking[i] = phid->motorBrakingEcho[i];
+ phid->backEMFSensingState[i] = phid->backEMFSensingStateEcho[i];
+ }
+ for(i = 0; i<phid->phid.attr.motorcontrol.numEncoders; i++)
+ {
+ phid->encoderPositionDelta[i] = phid->encoderPositionEcho[i];
+ }
+ phid->ratiometric = phid->ratiometricEcho;
+
+ return EPHIDGET_OK;
+}
+
+//dataInput - parses device packets
+CPHIDGETDATA(MotorControl)
+ int i = 0, j = 0;
+
+ if (length < 0) return EPHIDGET_INVALIDARG;
+ TESTPTR(phid);
+ TESTPTR(buffer);
+
+ switch(phid->phid.deviceIDSpec)
+ {
+ /* Original Motor controller */
+ case PHIDID_MOTORCONTROL_LV_2MOTOR_4INPUT:
+ if ((phid->phid.deviceVersion >= 100) && (phid->phid.deviceVersion < 200))
+ {
+ double speed[MOTORCONTROL_MAXMOTORS];
+ double lastSpeed[MOTORCONTROL_MAXMOTORS];
+ unsigned char input[MOTORCONTROL_MAXINPUTS];
+ unsigned char lastInputState[MOTORCONTROL_MAXINPUTS];
+ unsigned char error[MOTORCONTROL_MAXINPUTS];
+
+ ZEROMEM(speed, sizeof(speed));
+ ZEROMEM(lastSpeed, sizeof(lastSpeed));
+ ZEROMEM(input, sizeof(input));
+ ZEROMEM(lastInputState, sizeof(lastInputState));
+ ZEROMEM(error, sizeof(error));
+
+ //Parse device packet - store data locally
+ for (i = 0, j = 1; i < phid->phid.attr.motorcontrol.numInputs; i++, j<<=1)
+ {
+ if (buffer[0] & j)
+ input[i] = PTRUE;
+ else
+ input[i] = PFALSE;
+ }
+ for (i = 0, j = 1; i < phid->phid.attr.motorcontrol.numMotors; i++, j<<=1)
+ {
+ speed[i] = (char)buffer[4 + i];
+ speed[i] = round_double(((speed[i] * 100) / 127.0), 2);
+
+ //errors
+ if (buffer[1] & j)
+ {
+ error[i] = PTRUE;
+ }
+ }
+
+ //Make sure values are within defined range, and store to structure
+ for (i = 0; i < phid->phid.attr.motorcontrol.numInputs; i++)
+ {
+ lastInputState[i] = phid->inputState[i];
+ phid->inputState[i] = input[i];
+ }
+ for (i = 0; i<phid->phid.attr.motorcontrol.numMotors; i++)
+ {
+ lastSpeed[i] = phid->motorSpeedEcho[i];
+ phid->motorSpeedEcho[i] = speed[i];
+ }
+
+ //send out any events for changed data
+ for (i = 0; i < phid->phid.attr.motorcontrol.numInputs; i++)
+ {
+ if(phid->inputState[i] != PUNK_BOOL && phid->inputState[i] != lastInputState[i])
+ FIRE(InputChange, i, phid->inputState[i]);
+ }
+ for (i = 0; i<phid->phid.attr.motorcontrol.numMotors; i++)
+ {
+ if(phid->motorSpeedEcho[i] != PUNK_DBL && phid->motorSpeedEcho[i] != lastSpeed[i])
+ {
+ FIRE(VelocityChange, i, phid->motorSpeedEcho[i]);
+ //Deprecated
+ FIRE(MotorChange, i, phid->motorSpeedEcho[i]);
+ }
+ if(error[i])
+ {
+ char error_buffer[50];
+ FIRE_ERROR(EEPHIDGET_OVERCURRENT, "Motor %d exceeded 1.5 Amp current limit.", i);
+ }
+ }
+
+ }
+ else
+ return EPHIDGET_UNEXPECTED;
+ break;
+ /* HC motor controller - packets are indexed */
+ case PHIDID_MOTORCONTROL_HC_2MOTOR:
+ if ((phid->phid.deviceVersion >= 100) && (phid->phid.deviceVersion < 200))
+ {
+ int index = 0;
+ int error[MOTORCONTROL_MAXINPUTS];
+ double speed = 0, current = 0;
+ double lastSpeed = 0, lastCurrent = 0;
+
+ ZEROMEM(error, sizeof(error));
+
+ //Parse device packet - store data locally
+ index = buffer[3];
+
+ speed = (signed char)buffer[4];
+ speed = round_double(((speed * 100) / 127.0), 2);
+
+ //NOTE: current sense is only accurate at +100 and -100 velocity
+ current = (unsigned int)(((unsigned char)buffer[6] << 8) | (unsigned char)buffer[7]);
+ current -= 5;
+ if(current < 0) current = 0;
+ current /= 51.2; //volts
+ current = (current * 11370) / 1500; //amps
+
+ if (!(buffer[1] & 0x10)) error[0] |= 0x01;
+ if (!(buffer[1] & 0x20)) error[1] |= 0x01;
+ if (!(buffer[1] & 0x40)) error[0] |= 0x02;
+ if (!(buffer[1] & 0x80)) error[1] |= 0x02;
+
+ //Make sure values are within defined range, and store to structure
+ lastSpeed = phid->motorSpeedEcho[index];
+ phid->motorSpeedEcho[index] = speed;
+ lastCurrent = phid->motorSensedCurrent[index];
+ phid->motorSensedCurrent[index] = current;
+
+ //send out any events for changed data
+ if(phid->motorSpeedEcho[index] != PUNK_DBL && phid->motorSpeedEcho[index] != lastSpeed)
+ {
+ FIRE(VelocityChange, index, phid->motorSpeedEcho[index]);
+ //Deprecated
+ FIRE(MotorChange, index, phid->motorSpeedEcho[index]);
+ }
+ if(phid->motorSensedCurrent[index] != PUNK_DBL && phid->motorSensedCurrent[index] != lastCurrent)
+ FIRE(CurrentChange, index, phid->motorSensedCurrent[index]);
+ if(phid->motorSensedCurrent[index] != PUNK_DBL)
+ FIRE(CurrentUpdate, index, phid->motorSensedCurrent[index]);
+ for (i = 0; i<phid->phid.attr.motorcontrol.numMotors; i++)
+ {
+ char error_buffer[50];
+ //There are two error conditions - but as far as I can tell they both mean the same thing
+ if(error[i])
+ {
+ FIRE_ERROR(EEPHIDGET_OVERTEMP, "Motor %d overtemperature or short detected.", i);
+ }
+ }
+ }
+ else
+ return EPHIDGET_UNEXPECTED;
+ break;
+ /* 1-Motor controller with encoder and sensor inputs */
+ case PHIDID_MOTORCONTROL_1MOTOR:
+ if ((phid->phid.deviceVersion >= 100) && (phid->phid.deviceVersion < 200))
+ {
+ int i=0,j=0;
+ double speed = 0, current = 0, backEmf = 0, backEmfPos = 0, backEmfNeg = 0, supplyVoltage = 0, setSpeed = 0, setAccel = 0, setBraking = 0;
+ double lastSpeed = 0, lastCurrent = 0;
+ int encoderPos = 0, timeChangeInt = 0;
+ unsigned short encoderTimeChange = 0, encoderTime = 0;
+ int packetCount = 0;
+ unsigned char ratioEn = 0, dir = 0, bEMFValid = 0, bEMFenabled = 0, lowVoltageErr = 0, overTempErr = 0, setDir = 0;
+ int sensor[MOTORCONTROL_MAXSENSORS], sensorRaw[MOTORCONTROL_MAXSENSORS];
+ unsigned char input[MOTORCONTROL_MAXINPUTS];
+ unsigned char lastInputState[MOTORCONTROL_MAXINPUTS];
+ int encoderPositionChange = 0;
+ char error_buffer[128];
+ ZEROMEM(sensorRaw, sizeof(sensorRaw));
+ ZEROMEM(sensor, sizeof(sensor));
+ ZEROMEM(input, sizeof(input));
+ ZEROMEM(lastInputState, sizeof(lastInputState));
+
+ //Read in data
+ for (i = 0, j = 1; i < phid->phid.attr.motorcontrol.numInputs; i++, j<<=1)
+ {
+ if (buffer[0] & j)
+ input[i] = PTRUE;
+ else
+ input[i] = PFALSE;
+ }
+
+ overTempErr = ((buffer[1] & 0x01) ? PTRUE : PFALSE);
+ lowVoltageErr = ((buffer[1] & 0x02) ? PTRUE : PFALSE);
+ bEMFValid = ((buffer[1] & 0x04) ? PTRUE : PFALSE);
+ dir = ((buffer[1] & 0x08) ? PTRUE : PFALSE);
+ ratioEn = ((buffer[1] & 0x10) ? PTRUE : PFALSE);
+ bEMFenabled = ((buffer[1] & 0x20) ? PTRUE : PFALSE);
+ setDir = ((buffer[1] & 0x40) ? PTRUE : PFALSE);
+
+ for (i = 0; i < phid->phid.attr.motorcontrol.numSensors; i++)
+ {
+ sensorRaw[i] = ((unsigned char)buffer[i*2 + 4] << 8) + (unsigned char)buffer[i*2 + 5];
+ sensorRaw[i] = round(sensorRaw[i] * 1.001);
+ if(sensorRaw[i] > 0xfff)
+ sensorRaw[i] = 0xfff;
+ sensor[i] = round((double)sensorRaw[i] / 4.095);
+ }
+
+ //TODO: check this calculation
+ current = (unsigned int)(((unsigned char)buffer[2] << 8) + (unsigned char)buffer[3]);
+ current = ((current * 5) / 4096.0); //voltage on adc
+ current = (current / 150.0); //Current through resistor (0.24% of current through motor)
+ current = round_double(current / 0.0024, 3); //Normalized Current
+
+ backEmfPos = (unsigned int)(((unsigned char)buffer[10] << 8) + (unsigned char)buffer[11]);
+ backEmfNeg = (unsigned int)(((unsigned char)buffer[12] << 8) + (unsigned char)buffer[13]);
+ backEmf = backEmfPos - backEmfNeg;
+ backEmf = round_double(((backEmf * 80) / 4096.0), 3);
+
+ supplyVoltage = (unsigned int)(((unsigned char)buffer[8] << 8) + (unsigned char)buffer[9]);
+ supplyVoltage = round_double(((supplyVoltage * 80) / 2048.0), 3); //80v full scale on ADC
+
+ //LOG(PHIDGET_LOG_DEBUG, "Supply Voltage: %0.3lf", supplyVoltage);
+
+ speed = ((unsigned char)buffer[20] / 255.0) * 100.0;
+ if(!dir)
+ speed = -speed;
+
+ setSpeed = ((unsigned char)buffer[21] / 255.0) * 100.0;
+ if(!setDir)
+ setSpeed = -setSpeed;
+
+ setAccel = ((unsigned char)buffer[22] / 255.0) * phid->accelerationMax;
+ setBraking = ((unsigned char)buffer[23] / 255.0) * 100.0;
+
+ packetCount = (unsigned char)buffer[24];
+
+ encoderPos = (signed int)(((unsigned char)buffer[14] << 24)
+ + ((unsigned char)buffer[15] << 16)
+ + ((unsigned char)buffer[16] << 8)
+ + (unsigned char)buffer[17]);
+
+ encoderTime = (unsigned int)(((unsigned char)buffer[18] << 8) + (unsigned char)buffer[19]);
+
+ //Do stuff with the data
+ //Make sure values are within defined range, and store to structure
+ for (i = 0; i < phid->phid.attr.motorcontrol.numInputs; i++)
+ {
+ lastInputState[i] = phid->inputState[i];
+ phid->inputState[i] = input[i];
+ }
+
+ lastSpeed = phid->motorSpeedEcho[0];
+ phid->motorSpeedEcho[0] = speed;
+
+ lastCurrent = phid->motorSensedCurrent[0];
+ phid->motorSensedCurrent[0] = current;
+
+ phid->motorSetSpeedEcho[0] = setSpeed;
+ phid->motorAccelerationEcho[0] = setAccel;
+ phid->motorBrakingEcho[0] = setBraking;
+
+ if(bEMFValid)
+ phid->motorSensedBackEMF[0] = backEmf;
+ if(!bEMFenabled)
+ phid->motorSensedBackEMF[0] = PUNK_DBL;
+ phid->backEMFSensingStateEcho[0] = bEMFenabled;
+
+ phid->supplyVoltage = supplyVoltage;
+
+ //check for over/undershoots on encoder
+ if(((int)(phid->encoderPositionEcho[0] - phid->encoderPositionDelta[0]) > 2000000000
+ && (int)(encoderPos - phid->encoderPositionDelta[0]) < -2000000000)
+ || ((int)(phid->encoderPositionEcho[0] - phid->encoderPositionDelta[0]) < -2000000000
+ && (int)(encoderPos - phid->encoderPositionDelta[0]) > 2000000000))
+ {
+ char error_buffer[50];
+ FIRE_ERROR(EEPHIDGET_WRAP, "Encoder position is wrapping around.");
+ }
+
+ encoderPositionChange = encoderPos - phid->encoderPositionEcho[0];
+ phid->encoderPositionEcho[0] = encoderPos;
+
+ //this handles wraparounds because we're using unsigned shorts
+ encoderTimeChange = (encoderTime - phid->encoderTimeStamp[0]);
+
+ //timeout is 20 seconds
+ if (encoderTimeChange > 60000 || phid->encoderTimeStamp[0] == PUNK_INT)
+ timeChangeInt = PUNK_INT;
+ else
+ timeChangeInt = encoderTimeChange;
+
+ phid->encoderTimeStamp[0] = encoderTime;
+
+ for (i = 0; i < phid->phid.attr.motorcontrol.numSensors; i++)
+ {
+ phid->sensorValue[i] = sensor[i];
+ phid->sensorRawValue[i] = sensorRaw[i];
+ }
+ phid->ratiometricEcho = ratioEn;
+
+ //Send out events
+ for (i = 0; i < phid->phid.attr.motorcontrol.numInputs; i++)
+ {
+ if(phid->inputState[i] != PUNK_BOOL && phid->inputState[i] != lastInputState[i])
+ FIRE(InputChange, i, phid->inputState[i]);
+ }
+ if(phid->motorSpeedEcho[0] != PUNK_DBL && phid->motorSpeedEcho[0] != lastSpeed)
+ {
+ FIRE(VelocityChange, 0, phid->motorSpeedEcho[0]);
+ //Deprecated
+ FIRE(MotorChange, 0, phid->motorSpeedEcho[0]);
+ }
+ if(phid->motorSensedCurrent[0] != PUNK_DBL && phid->motorSensedCurrent[0] != lastCurrent)
+ FIRE(CurrentChange, 0, phid->motorSensedCurrent[0]);
+
+ if(phid->motorSensedCurrent[0] != PUNK_DBL)
+ FIRE(CurrentUpdate, 0, phid->motorSensedCurrent[0]);
+
+ for (i = 0; i < phid->phid.attr.motorcontrol.numSensors; i++)
+ FIRE(SensorUpdate, i, phid->sensorValue[i]);
+
+ if(encoderPositionChange != 0)
+ FIRE(EncoderPositionChange, 0, timeChangeInt, encoderPositionChange);
+ FIRE(EncoderPositionUpdate, 0, encoderPositionChange);
+
+ if(bEMFValid)
+ FIRE(BackEMFUpdate, 0, backEmf);
+
+ //Error Events:
+
+ //This is true when MC33931 status pin is LOW (active)
+ // could be under-voltage lockout, over-temperature, or short-circuit
+ // over-temperature and short-circuit conditions need to be cleared by toggling D1 or D2
+ if(overTempErr && !(phid->motorErrors[0] & MOTORCONTROL_ERRORFLAG_OVERTEMP))
+ {
+ phid->motorErrors[0] |= MOTORCONTROL_ERRORFLAG_OVERTEMP;
+ FIRE_ERROR(EEPHIDGET_OVERTEMP, "Over-temperature / Short-circuit condition detected.");
+ }
+ else if(!overTempErr && (phid->motorErrors[0] & MOTORCONTROL_ERRORFLAG_OVERTEMP))
+ {
+ phid->motorErrors[0] &= ~MOTORCONTROL_ERRORFLAG_OVERTEMP;
+ FIRE_ERROR(EEPHIDGET_OK, "Over-temperature / Short-circuit condition ended.");
+ }
+ //if supply voltage is >5v, then we have likely already recovered from this error. This happens when the power is first plugged in
+ //This error happens when the power supply voltage falls, not when it starts low
+ if(lowVoltageErr && supplyVoltage < 5 && !(phid->motorErrors[0] & MOTORCONTROL_ERRORFLAG_UNDERVOLTAGE_LOCKOUT))
+ {
+ phid->motorErrors[0] |= MOTORCONTROL_ERRORFLAG_UNDERVOLTAGE_LOCKOUT;
+ FIRE_ERROR(EEPHIDGET_BADPOWER, "Under-voltage Lockout condition detected. Supply voltage is %0.2lfv", supplyVoltage);
+ }
+ else if(!lowVoltageErr && (phid->motorErrors[0] & MOTORCONTROL_ERRORFLAG_UNDERVOLTAGE_LOCKOUT))
+ {
+ phid->motorErrors[0] &= ~MOTORCONTROL_ERRORFLAG_UNDERVOLTAGE_LOCKOUT;
+ FIRE_ERROR(EEPHIDGET_OK, "Under-voltage Lockout condition ended.");
+ }
+ //Errors I detect - not error flags from the Motor Control IC:
+ if(supplyVoltage < 1 && !(phid->motorErrors[0] & MOTORCONTROL_ERRORFLAG_NOPOWER))
+ {
+ phid->motorErrors[0] |= MOTORCONTROL_ERRORFLAG_NOPOWER;
+ FIRE_ERROR(EEPHIDGET_BADPOWER, "Power supply is unplugged or non-functional. Supply voltage is %0.2lfv", supplyVoltage);
+ }
+ else if(supplyVoltage <= 7 && !(phid->motorErrors[0] & MOTORCONTROL_ERRORFLAG_LOWPOWER))
+ {
+ phid->motorErrors[0] |= MOTORCONTROL_ERRORFLAG_LOWPOWER;
+ FIRE_ERROR(EEPHIDGET_BADPOWER, "Power supply voltage is too low. Supply voltage is %0.2lfv", supplyVoltage);
+ }
+ if(supplyVoltage >= 40 && !(phid->motorErrors[0] & MOTORCONTROL_ERRORFLAG_DANGERPOWER))
+ {
+ phid->motorErrors[0] |= MOTORCONTROL_ERRORFLAG_DANGERPOWER;
+ FIRE_ERROR(EEPHIDGET_BADPOWER, "DANGER: Over-voltage condition, braking motor. Supply voltage is %0.2lfv", supplyVoltage);
+ }
+ else if(supplyVoltage >= 34 && !(phid->motorErrors[0] & MOTORCONTROL_ERRORFLAG_HIGHPOWER))
+ {
+ phid->motorErrors[0] |= MOTORCONTROL_ERRORFLAG_HIGHPOWER;
+ FIRE_ERROR(EEPHIDGET_BADPOWER, "Power supply voltage is too high. Supply voltage is %0.2lfv", supplyVoltage);
+ }
+ if(supplyVoltage > 7.5 && supplyVoltage < 33
+ && (phid->motorErrors[0] & (MOTORCONTROL_ERRORFLAG_NOPOWER | MOTORCONTROL_ERRORFLAG_LOWPOWER | MOTORCONTROL_ERRORFLAG_HIGHPOWER | MOTORCONTROL_ERRORFLAG_DANGERPOWER)))
+ {
+ phid->motorErrors[0] &= ~(MOTORCONTROL_ERRORFLAG_NOPOWER | MOTORCONTROL_ERRORFLAG_LOWPOWER | MOTORCONTROL_ERRORFLAG_HIGHPOWER | MOTORCONTROL_ERRORFLAG_DANGERPOWER);
+ FIRE_ERROR(EEPHIDGET_OK, "Power supply voltage has returned to valid range. Supply voltage is %0.2lfv", supplyVoltage);
+ }
+
+ if((phid->lastPacketCount != PUNK_INT) && ((phid->lastPacketCount+1)&0xFF) != packetCount)
+ {
+ FIRE_ERROR_NOQUEUE(EEPHIDGET_PACKETLOST, "One or more data packets were lost");
+ }
+ phid->lastPacketCount = packetCount;
+ }
+ else
+ return EPHIDGET_UNEXPECTED;
+ break;
+ default:
+ return EPHIDGET_UNEXPECTED;
+
+ }
+
+ return EPHIDGET_OK;
+}
+
+//eventsAfterOpen - sends out an event for all valid data, used during attach initialization
+CPHIDGETINITEVENTS(MotorControl)
+
+ for (i = 0; i<phid->phid.attr.motorcontrol.numInputs; i++)
+ {
+ if(phid->inputState[i] != PUNK_BOOL)
+ FIRE(InputChange, i, phid->inputState[i]);
+ }
+ for (i = 0; i<phid->phid.attr.motorcontrol.numMotors; i++)
+ {
+ if(phid->motorSpeedEcho[i] != PUNK_DBL)
+ {
+ FIRE(VelocityChange, i, phid->motorSpeedEcho[i]);
+ //Deprecated
+ FIRE(MotorChange, i, phid->motorSpeedEcho[i]);
+ }
+ if(phid->motorSensedCurrent[i] != PUNK_DBL && phid->motorSensedCurrent[i] != PUNI_DBL)
+ FIRE(CurrentChange, i, phid->motorSensedCurrent[i]);
+ }
+
+ //Note: don't send BackEMFUpdate, SensorUpdate, CurrentUpdate events - they come at a set rate.
+
+ return EPHIDGET_OK;
+}
+
+//getPacket - used by write thread to get the next packet to send to device
+CGETPACKET_BUF(MotorControl)
+
+//sendpacket - sends a packet to the device asynchronously, blocking if the 1-packet queue is full
+CSENDPACKET_BUF(MotorControl)
+
+//makePacket - constructs a packet using current device state
+CMAKEPACKETINDEXED(MotorControl)
+ int velocity = 0, accel = 0, braking = 0;
+ unsigned char dir = 0;
+
+ TESTPTRS(phid, buffer);
+
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_MOTORCONTROL_LV_2MOTOR_4INPUT:
+ case PHIDID_MOTORCONTROL_HC_2MOTOR:
+ if ((phid->phid.deviceVersion >= 100) && (phid->phid.deviceVersion < 200))
+ {
+ //have to make sure that everything to be sent has some sort of default value if the user hasn't set a value
+ if(phid->motorSpeed[Index] == PUNK_DBL)
+ phid->motorSpeed[Index] = 0; //not moving
+ if(phid->motorAcceleration[Index] == PUNK_DBL)
+ phid->motorAcceleration[Index] = phid->accelerationMax / 2; //mid-range
+
+ velocity = (int)round((phid->motorSpeed[Index] * 127.0) / 100.0);
+ accel = (int)round(phid->motorAcceleration[Index] * 10.23);
+
+ buffer[0] = (unsigned char)Index;
+ buffer[1] = (unsigned char)(velocity & 0xff);
+ buffer[2] = (unsigned char)((accel >> 8) & 0x0f);
+ buffer[3] = (unsigned char)(accel & 0xff);
+ }
+ else
+ return EPHIDGET_UNEXPECTED;
+ break;
+ case PHIDID_MOTORCONTROL_1MOTOR:
+ if ((phid->phid.deviceVersion >= 100) && (phid->phid.deviceVersion < 200))
+ {
+ //have to make sure that everything to be sent has some sort of default value if the user hasn't set a value
+ if(phid->motorSpeed[Index] == PUNK_DBL)
+ phid->motorSpeed[Index] = 0; //not moving
+ if(phid->motorBraking[Index] == PUNK_DBL)
+ phid->motorBraking[Index] = 0; //not braking
+ if(phid->motorAcceleration[Index] == PUNK_DBL)
+ phid->motorAcceleration[Index] = phid->accelerationMax / 2; //mid-range
+ if(phid->motorSpeed[Index] >= 0)
+ {
+ velocity = (int)round((phid->motorSpeed[Index] * 255.0) / 100.0);
+ dir = 1;
+ }
+ else
+ {
+ velocity = (int)round((-phid->motorSpeed[Index] * 255.0) / 100.0);
+ dir = 0;
+ }
+ accel = (int)round((phid->motorAcceleration[Index] / phid->accelerationMax) * 255);
+ braking = (int)round((phid->motorBraking[Index] * 255.0) / 100.0);
+ if(phid->ratiometric == PUNK_BOOL)
+ phid->ratiometric = PTRUE;
+ if(phid->backEMFSensingState[0] == PUNK_BOOL)
+ phid->backEMFSensingState[0] = PFALSE;
+
+ buffer[0] = (unsigned char)(dir | (phid->ratiometric==PTRUE?0x04:0x00) | (phid->backEMFSensingState[0]==PTRUE?0x02:0x00));
+ buffer[1] = (unsigned char)(velocity & 0xff);
+ buffer[2] = (unsigned char)(accel & 0xff);
+ buffer[3] = (unsigned char)(braking & 0xff);
+ }
+ else
+ return EPHIDGET_UNEXPECTED;
+ break;
+ default:
+ return EPHIDGET_UNEXPECTED;
+ }
+
+ return EPHIDGET_OK;
+}
+
+// === Exported Functions === //
+
+//create and initialize a device structure
+CCREATE(MotorControl, PHIDCLASS_MOTORCONTROL)
+
+//event setup functions
+CFHANDLE(MotorControl, InputChange, int, int)
+CFHANDLE(MotorControl, VelocityChange, int, double)
+CFHANDLE(MotorControl, CurrentChange, int, double)
+CFHANDLE(MotorControl, EncoderPositionChange, int, int, int)
+CFHANDLE(MotorControl, EncoderPositionUpdate, int, int)
+CFHANDLE(MotorControl, BackEMFUpdate, int, double)
+CFHANDLE(MotorControl, SensorUpdate, int, int)
+CFHANDLE(MotorControl, CurrentUpdate, int, double)
+
+CGET(MotorControl,MotorCount,int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_MOTORCONTROL)
+ TESTATTACHED
+
+ MASGN(phid.attr.motorcontrol.numMotors)
+}
+
+CGETINDEX(MotorControl,Velocity,double)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_MOTORCONTROL)
+ TESTATTACHED
+ TESTINDEX(phid.attr.motorcontrol.numMotors)
+ TESTMASGN(motorSpeedEcho[Index], PUNK_DBL)
+
+ MASGN(motorSpeedEcho[Index])
+}
+CSETINDEX(MotorControl,Velocity,double)
+ TESTPTR(phid)
+ TESTDEVICETYPE(PHIDCLASS_MOTORCONTROL)
+ TESTATTACHED
+ TESTINDEX(phid.attr.motorcontrol.numMotors)
+ TESTRANGE(-100, 100)
+
+ if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
+ ADDNETWORKKEYINDEXED(Velocity, "%lE", motorSpeed);
+ else
+ SENDPACKETINDEXED(MotorControl, motorSpeed[Index], Index);
+
+ return EPHIDGET_OK;
+}
+
+CGETINDEX(MotorControl,Acceleration,double)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_MOTORCONTROL)
+ TESTATTACHED
+ TESTINDEX(phid.attr.motorcontrol.numMotors)
+ TESTMASGN(motorAcceleration[Index], PUNK_DBL)
+
+ MASGN(motorAcceleration[Index])
+}
+CSETINDEX(MotorControl,Acceleration,double)
+ TESTPTR(phid)
+ TESTDEVICETYPE(PHIDCLASS_MOTORCONTROL)
+ TESTATTACHED
+ TESTINDEX(phid.attr.motorcontrol.numMotors)
+ TESTRANGE(phid->accelerationMin, phid->accelerationMax)
+
+ if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
+ ADDNETWORKKEYINDEXED(Acceleration, "%lE", motorAcceleration);
+ else
+ SENDPACKETINDEXED(MotorControl, motorAcceleration[Index], Index);
+
+ return EPHIDGET_OK;
+}
+
+CGETINDEX(MotorControl,AccelerationMax,double)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_MOTORCONTROL)
+ TESTATTACHED
+ TESTINDEX(phid.attr.motorcontrol.numMotors)
+ TESTMASGN(accelerationMax, PUNK_DBL)
+
+ MASGN(accelerationMax)
+}
+
+CGETINDEX(MotorControl,AccelerationMin,double)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_MOTORCONTROL)
+ TESTATTACHED
+ TESTINDEX(phid.attr.motorcontrol.numMotors)
+ TESTMASGN(accelerationMin, PUNK_DBL)
+
+ MASGN(accelerationMin)
+}
+
+CGETINDEX(MotorControl,Current,double)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_MOTORCONTROL)
+ TESTATTACHED
+
+ //Only supported on HC/1-motor
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_MOTORCONTROL_LV_2MOTOR_4INPUT:
+ return EPHIDGET_UNSUPPORTED;
+ case PHIDID_MOTORCONTROL_HC_2MOTOR:
+ case PHIDID_MOTORCONTROL_1MOTOR:
+ TESTINDEX(phid.attr.motorcontrol.numMotors)
+ TESTMASGN(motorSensedCurrent[Index], PUNK_DBL)
+ MASGN(motorSensedCurrent[Index])
+ default:
+ return EPHIDGET_UNEXPECTED;
+ }
+}
+
+CGETINDEX(MotorControl,BackEMFSensingState,int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_MOTORCONTROL)
+ TESTATTACHED
+ TESTINDEX(phid.attr.motorcontrol.numMotors)
+ TESTMASGN(backEMFSensingStateEcho[Index], PUNK_BOOL)
+
+ //Note: will return false on devices that don't support backEMF sensing
+ MASGN(backEMFSensingStateEcho[Index])
+}
+CSETINDEX(MotorControl,BackEMFSensingState,int)
+ TESTPTR(phid)
+ TESTDEVICETYPE(PHIDCLASS_MOTORCONTROL)
+ TESTATTACHED
+ TESTINDEX(phid.attr.motorcontrol.numMotors)
+ TESTRANGE(PFALSE, PTRUE)
+
+ //Only supported on 1-motor
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_MOTORCONTROL_LV_2MOTOR_4INPUT:
+ case PHIDID_MOTORCONTROL_HC_2MOTOR:
+ return EPHIDGET_UNSUPPORTED;
+ case PHIDID_MOTORCONTROL_1MOTOR:
+ if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
+ ADDNETWORKKEYINDEXED(BackEMFState, "%d", backEMFSensingState);
+ else
+ SENDPACKETINDEXED(MotorControl, backEMFSensingState[Index], Index);
+ break;
+ default:
+ return EPHIDGET_UNEXPECTED;
+ }
+
+ return EPHIDGET_OK;
+}
+
+CGETINDEX(MotorControl,BackEMF,double)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_MOTORCONTROL)
+ TESTATTACHED
+
+ //Only supported on 1-motor
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_MOTORCONTROL_LV_2MOTOR_4INPUT:
+ case PHIDID_MOTORCONTROL_HC_2MOTOR:
+ return EPHIDGET_UNSUPPORTED;
+ case PHIDID_MOTORCONTROL_1MOTOR:
+ TESTINDEX(phid.attr.motorcontrol.numMotors)
+ TESTMASGN(motorSensedBackEMF[Index], PUNK_DBL)
+ MASGN(motorSensedBackEMF[Index])
+ default:
+ return EPHIDGET_UNEXPECTED;
+ }
+}
+
+CGET(MotorControl,SupplyVoltage,double)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_MOTORCONTROL)
+ TESTATTACHED
+
+ //Only supported on 1-motor
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_MOTORCONTROL_LV_2MOTOR_4INPUT:
+ case PHIDID_MOTORCONTROL_HC_2MOTOR:
+ return EPHIDGET_UNSUPPORTED;
+ case PHIDID_MOTORCONTROL_1MOTOR:
+ TESTMASGN(supplyVoltage, PUNK_DBL)
+ MASGN(supplyVoltage)
+ default:
+ return EPHIDGET_UNEXPECTED;
+ }
+}
+
+CGETINDEX(MotorControl,Braking,double)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_MOTORCONTROL)
+ TESTATTACHED
+ TESTINDEX(phid.attr.motorcontrol.numMotors)
+ TESTMASGN(motorBrakingEcho[Index], PUNK_DBL)
+
+ MASGN(motorBrakingEcho[Index])
+}
+CSETINDEX(MotorControl,Braking,double)
+ TESTPTR(phid)
+ TESTDEVICETYPE(PHIDCLASS_MOTORCONTROL)
+ TESTATTACHED
+ TESTINDEX(phid.attr.motorcontrol.numMotors)
+ TESTRANGE(0, 100)
+
+ //Only supported on 1-motor
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_MOTORCONTROL_LV_2MOTOR_4INPUT:
+ case PHIDID_MOTORCONTROL_HC_2MOTOR:
+ return EPHIDGET_UNSUPPORTED;
+ case PHIDID_MOTORCONTROL_1MOTOR:
+ if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
+ ADDNETWORKKEYINDEXED(Braking, "%lE", motorBraking);
+ else
+ SENDPACKETINDEXED(MotorControl, motorBraking[Index], Index);
+ break;
+ default:
+ return EPHIDGET_UNEXPECTED;
+ }
+
+ return EPHIDGET_OK;
+}
+
+CGET(MotorControl,InputCount,int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_MOTORCONTROL)
+ TESTATTACHED
+
+ MASGN(phid.attr.motorcontrol.numInputs)
+}
+
+CGETINDEX(MotorControl,InputState,int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_MOTORCONTROL)
+ TESTATTACHED
+ TESTINDEX(phid.attr.motorcontrol.numInputs)
+ TESTMASGN(inputState[Index], PUNK_BOOL)
+
+ MASGN(inputState[Index])
+}
+
+CGET(MotorControl,EncoderCount,int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_MOTORCONTROL)
+ TESTATTACHED
+
+ MASGN(phid.attr.motorcontrol.numEncoders)
+}
+
+CGETINDEX(MotorControl,EncoderPosition,int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_MOTORCONTROL)
+ TESTATTACHED
+ TESTINDEX(phid.attr.motorcontrol.numEncoders)
+
+ *pVal = (phid->encoderPositionEcho[Index] - phid->encoderPositionDelta[Index]);
+ return EPHIDGET_OK;
+}
+CSETINDEX(MotorControl,EncoderPosition,int)
+ TESTPTR(phid)
+ TESTDEVICETYPE(PHIDCLASS_MOTORCONTROL)
+ TESTATTACHED
+ TESTINDEX(phid.attr.motorcontrol.numEncoders)
+
+ if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
+ {
+ //newVal = phid->encoderPositionEcho[Index] + newVal;
+ ADDNETWORKKEYINDEXED(ResetEncoderPosition, "%d", encoderPositionDelta);
+ }
+ else
+ phid->encoderPositionDelta[Index] = phid->encoderPositionEcho[Index] + newVal;
+
+ return EPHIDGET_OK;
+}
+
+CGET(MotorControl, SensorCount, int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_MOTORCONTROL)
+ TESTATTACHED
+
+ MASGN(phid.attr.motorcontrol.numSensors)
+}
+
+CGETINDEX(MotorControl, SensorValue, int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_MOTORCONTROL)
+ TESTATTACHED
+ TESTINDEX(phid.attr.motorcontrol.numSensors)
+ TESTMASGN(sensorValue[Index], PUNK_INT)
+
+ MASGN(sensorValue[Index])
+}
+
+CGETINDEX(MotorControl, SensorRawValue, int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_MOTORCONTROL)
+ TESTATTACHED
+ TESTINDEX(phid.attr.motorcontrol.numSensors)
+ TESTMASGN(sensorRawValue[Index], PUNK_INT)
+
+ MASGN(sensorRawValue[Index])
+}
+CGET(MotorControl, Ratiometric, int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_MOTORCONTROL)
+ TESTATTACHED
+
+ //Only supported on 1-motor
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_MOTORCONTROL_LV_2MOTOR_4INPUT:
+ case PHIDID_MOTORCONTROL_HC_2MOTOR:
+ return EPHIDGET_UNSUPPORTED;
+ case PHIDID_MOTORCONTROL_1MOTOR:
+ TESTMASGN(ratiometricEcho, PUNK_BOOL)
+ MASGN(ratiometricEcho)
+ default:
+ return EPHIDGET_UNEXPECTED;
+ }
+}
+CSET(MotorControl, Ratiometric, int)
+ TESTPTR(phid)
+ TESTDEVICETYPE(PHIDCLASS_MOTORCONTROL)
+ TESTATTACHED
+
+ //Only supported on 1-motor
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_MOTORCONTROL_LV_2MOTOR_4INPUT:
+ case PHIDID_MOTORCONTROL_HC_2MOTOR:
+ return EPHIDGET_UNSUPPORTED;
+ case PHIDID_MOTORCONTROL_1MOTOR:
+ if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
+ ADDNETWORKKEY(Ratiometric, "%d", ratiometric);
+ else
+ SENDPACKETINDEXED(MotorControl, ratiometric, 0);
+ break;
+ default:
+ return EPHIDGET_UNEXPECTED;
+ }
+
+ return EPHIDGET_OK;
+}
+
+// === Deprecated Functions === //
+
+CFHANDLE(MotorControl, MotorChange, int, double)
+CGETINDEX(MotorControl,MotorSpeed,double)
+ return CPhidgetMotorControl_getVelocity(phid, Index, pVal);
+}
+CSETINDEX(MotorControl,MotorSpeed,double)
+ return CPhidgetMotorControl_setVelocity(phid, Index, newVal);
+}
+CGET(MotorControl,NumMotors,int)
+ return CPhidgetMotorControl_getMotorCount(phid, pVal);
+}
+CGET(MotorControl,NumInputs,int)
+ return CPhidgetMotorControl_getInputCount(phid, pVal);
+}
diff --git a/cphidgetmotorcontrol.h b/cphidgetmotorcontrol.h
new file mode 100644
index 0000000..0373e31
--- /dev/null
+++ b/cphidgetmotorcontrol.h
@@ -0,0 +1,331 @@
+#ifndef __CPHIDGETMOTORCONTROL
+#define __CPHIDGETMOTORCONTROL
+#include "cphidget.h"
+
+/** \defgroup phidmotorcontrol Phidget Motor Control
+ * \ingroup phidgets
+ * Calls specific to the Phidget Motor Control. See the product manual for more specific API details, supported functionality, units, etc.
+ * @{
+ */
+
+DPHANDLE(MotorControl)
+CHDRSTANDARD(MotorControl)
+
+/**
+ * Gets the number of motors supported by this controller.
+ * @param phid An attached phidget motor control handle.
+ * @param count The motor count.
+ */
+CHDRGET(MotorControl,MotorCount,int *count)
+
+/**
+ * Gets the current velocity of a motor.
+ * @param phid An attached phidget motor control handle.
+ * @param index The motor index.
+ * @param velocity The current velocity.
+ */
+CHDRGETINDEX(MotorControl,Velocity,double *velocity)
+/**
+ * Sets the velocity of a motor.
+ * @param phid An attached phidget motor control handle.
+ * @param index The motor index.
+ * @param velocity The velocity.
+ */
+CHDRSETINDEX(MotorControl,Velocity,double velocity)
+/**
+ * Sets a velocity change event handler. This is called when the velocity changes.
+ * @param phid An attached phidget motor control handle.
+ * @param fptr Callback function pointer.
+ * @param userPtr A pointer for use by the user - this value is passed back into the callback function.
+ */
+CHDREVENTINDEX(MotorControl,VelocityChange,double velocity)
+
+/**
+ * Gets the last set acceleration of a motor.
+ * @param phid An attached phidget motor control handle.
+ * @param index The motor index.
+ * @param acceleration The acceleration.
+ */
+CHDRGETINDEX(MotorControl,Acceleration,double *acceleration)
+/**
+ * Sets the last set acceleration of a motor.
+ * @param phid An attached phidget motor control handle.
+ * @param index The motor index.
+ * @param acceleration The acceleration.
+ */
+CHDRSETINDEX(MotorControl,Acceleration,double acceleration)
+/**
+ * Gets the maximum acceleration supported by a motor
+ * @param phid An attached phidget motor control handle
+ * @param index The motor index.
+ * @param max The maximum acceleration.
+ */
+CHDRGETINDEX(MotorControl,AccelerationMax,double *max)
+/**
+ * Gets the minimum acceleration supported by a motor.
+ * @param phid An attached phidget motor control handle
+ * @param index The motor index.
+ * @param min The minimum acceleration
+ */
+CHDRGETINDEX(MotorControl,AccelerationMin,double *min)
+
+
+/**
+ * Gets the current current draw for a motor.
+ * @param phid An attached phidget motor control handle
+ * @param index The motor index.
+ * @param current The current.
+ */
+CHDRGETINDEX(MotorControl,Current,double *current)
+/**
+ * Sets a current change event handler. This is called when the current draw changes.
+ * @param phid An attached phidget motor control handle
+ * @param fptr Callback function pointer.
+ * @param userPtr A pointer for use by the user - this value is passed back into the callback function.
+ */
+CHDREVENTINDEX(MotorControl,CurrentChange,double current)
+
+/**
+ * Gets the number of digital inputs supported by this board.
+ * @param phid An attached phidget motor control handle.
+ * @param count The ditial input count.
+ */
+CHDRGET(MotorControl,InputCount,int *count)
+/**
+ * Gets the state of a digital input.
+ * @param phid An attached phidget motor control handle.
+ * @param index The input index.
+ * @param inputState The input state. Possible values are \ref PTRUE and \ref PFALSE.
+ */
+CHDRGETINDEX(MotorControl,InputState,int *inputState)
+/**
+ * Set a digital input change handler. This is called when a digital input changes.
+ * @param phid An attached phidget motor control handle.
+ * @param fptr Callback function pointer.
+ * @param userPtr A pointer for use by the user - this value is passed back into the callback function.
+ */
+CHDREVENTINDEX(MotorControl,InputChange,int inputState)
+
+/**
+ * Gets the number of encoder inputs supported by this board.
+ * @param phid An attached phidget motor control handle.
+ * @param count The encoder input count.
+ */
+CHDRGET(MotorControl,EncoderCount,int *count)
+/**
+ * Gets the position of an encoder. This position starts at 0 every time the phidget is opened.
+ * @param phid An attached phidget motor control handle.
+ * @param index The encoder index.
+ * @param position The encoder position.
+ */
+CHDRGETINDEX(MotorControl,EncoderPosition,int *position)
+/**
+ * Sets the encoder position. This can be used to set the position to a known value, and should only be called when the encoder is not moving.
+ * @param phid An attached phidget motor control handle.
+ * @param index The encoder index.
+ * @param position The encoder position.
+ */
+CHDRSETINDEX(MotorControl,EncoderPosition,int position)
+/**
+ * Set an encoder position change handler. This is called when the encoder position changes.
+ * @param phid An attached phidget motor control handle.
+ * @param fptr Callback function pointer.
+ * @param userPtr A pointer for use by the user - this value is passed back into the callback function.
+ */
+CHDREVENTINDEX(MotorControl,EncoderPositionChange,int time,int positionChange)
+/**
+ * Set an encoder position update handler. This is called at a constant rate; every 8ms, whether the encoder position has changed or not.
+ * @param phid An attached phidget motor control handle.
+ * @param fptr Callback function pointer.
+ * @param userPtr A pointer for use by the user - this value is passed back into the callback function.
+ */
+CHDREVENTINDEX(MotorControl,EncoderPositionUpdate,int positionChange)
+
+/**
+ * Gets the Back EMF sensing state for a motor.
+ * @param phid An attached phidget motor control handle.
+ * @param index The motor index.
+ * @param bEMFState The back EMF sensing state.
+ */
+CHDRGETINDEX(MotorControl,BackEMFSensingState,int *bEMFState)
+/**
+ * Sets the Back EMF sensing state for a motor.
+ * @param phid An attached phidget motor control handle.
+ * @param index The motor index.
+ * @param bEMFState The back EMF sensing state.
+ */
+CHDRSETINDEX(MotorControl,BackEMFSensingState,int bEMFState)
+/**
+ * Gets the Back EMF voltage for a motor.
+ * @param phid An attached phidget motor control handle.
+ * @param index The motor index.
+ * @param voltage The back EMF voltage, in volts.
+ */
+CHDRGETINDEX(MotorControl,BackEMF,double *voltage)
+/**
+ * Set a back EMF update handler. This is called at a constant rate; every 16ms, when back EMF sensing is enabled for that motor.
+ * @param phid An attached phidget motor control handle.
+ * @param fptr Callback function pointer.
+ * @param userPtr A pointer for use by the user - this value is passed back into the callback function.
+ */
+CHDREVENTINDEX(MotorControl,BackEMFUpdate,double voltage)
+
+/**
+ * Gets the Supply voltage for the motors. This could be higher then the actual supply voltage.
+ * @param phid An attached phidget motor control handle.
+ * @param supplyVoltage The supply voltage, in volts.
+ */
+CHDRGET(MotorControl,SupplyVoltage,double *supplyVoltage)
+
+/**
+ * Gets the Braking value for a motor.
+ * @param phid An attached phidget motor control handle.
+ * @param index The motor index.
+ * @param braking The braking value, in percent.
+ */
+CHDRGETINDEX(MotorControl,Braking,double *braking)
+/**
+ * Sets the Braking value for a motor. This is applied when velocity is 0. Default is 0%.
+ * @param phid An attached phidget motor control handle.
+ * @param index The motor index.
+ * @param braking The braking value, in percent.
+ */
+CHDRSETINDEX(MotorControl,Braking,double braking)
+
+/**
+ * Gets the number of sensor inputs supported by this board.
+ * @param phid An attached phidget motor control handle.
+ * @param count The sensor input count.
+ */
+CHDRGET(MotorControl, SensorCount, int *count)
+/**
+ * Gets the value of a sensor.
+ * @param phid An attached phidget motor control handle.
+ * @param index The sensor index.
+ * @param sensorValue The sensor value, range: 0-1000.
+ */
+CHDRGETINDEX(MotorControl, SensorValue, int *sensorValue)
+/**
+ * Gets the raw value of a sensor (12-bit).
+ * @param phid An attached phidget motor control handle.
+ * @param index The sensor index.
+ * @param sensorRawValue The sensor value, range: 0-4096.
+ */
+CHDRGETINDEX(MotorControl, SensorRawValue, int *sensorRawValue)
+/**
+ * Set a sensor update handler. This is called at a constant rate; every 8ms.
+ * @param phid An attached phidget motor control handle.
+ * @param fptr Callback function pointer.
+ * @param userPtr A pointer for use by the user - this value is passed back into the callback function.
+ */
+CHDREVENTINDEX(MotorControl, SensorUpdate, int sensorValue)
+/**
+ * Gets the ratiometric state.
+ * @param phid An attached phidget motor control handle.
+ * @param ratiometric The ratiometric state.
+ */
+CHDRGET(MotorControl, Ratiometric, int *ratiometric)
+/**
+ * Sets the ratiometric state. This control the voltage reference used for sampling the analog sensors.
+ * @param phid An attached phidget motor control handle.
+ * @param ratiometric The ratiometric state.
+ */
+CHDRSET(MotorControl, Ratiometric, int ratiometric)
+
+/**
+ * Set a current update handler. This is called at a constant rate; every 8ms.
+ * @param phid An attached phidget motor control handle.
+ * @param fptr Callback function pointer.
+ * @param userPtr A pointer for use by the user - this value is passed back into the callback function.
+ */
+CHDREVENTINDEX(MotorControl,CurrentUpdate,double current)
+
+#ifndef REMOVE_DEPRECATED
+DEP_CHDRGET("Deprecated - use CPhidgetMotorControl_getMotorCount",MotorControl,NumMotors,int *)
+DEP_CHDRGET("Deprecated - use CPhidgetMotorControl_getInputCount",MotorControl,NumInputs,int *)
+DEP_CHDRGETINDEX("Deprecated - use CPhidgetMotorControl_getVelocity",MotorControl,MotorSpeed,double *)
+DEP_CHDRSETINDEX("Deprecated - use CPhidgetMotorControl_setVelocity",MotorControl,MotorSpeed,double)
+DEP_CHDREVENTINDEX("Deprecated - use CPhidgetMotorControl_set_OnVelocityChange_Handler",MotorControl,MotorChange,double motorSpeed)
+#endif
+
+#ifndef EXTERNALPROTO
+#define MOTORCONTROL_MAXMOTORS 2
+#define MOTORCONTROL_MAXINPUTS 4
+#define MOTORCONTROL_MAXENCODERS 1
+#define MOTORCONTROL_MAXSENSORS 2
+
+#define MOTORCONTROL_ERRORFLAG_OVERTEMP 0x0001
+#define MOTORCONTROL_ERRORFLAG_UNDERVOLTAGE_LOCKOUT 0x0002
+#define MOTORCONTROL_ERRORFLAG_NOPOWER 0x0004
+#define MOTORCONTROL_ERRORFLAG_LOWPOWER 0x0008
+#define MOTORCONTROL_ERRORFLAG_HIGHPOWER 0x0010
+#define MOTORCONTROL_ERRORFLAG_DANGERPOWER 0x0020
+
+struct _CPhidgetMotorControl {
+ CPhidget phid;
+
+ int (CCONV *fptrVelocityChange)(CPhidgetMotorControlHandle, void *, int, double);
+ int (CCONV *fptrInputChange)(CPhidgetMotorControlHandle, void *, int, int);
+ int (CCONV *fptrCurrentChange)(CPhidgetMotorControlHandle, void *, int, double);
+ int (CCONV *fptrEncoderPositionChange)(CPhidgetMotorControlHandle, void *, int, int, int);
+ int (CCONV *fptrEncoderPositionUpdate)(CPhidgetMotorControlHandle, void *, int, int);
+ int (CCONV *fptrBackEMFUpdate)(CPhidgetMotorControlHandle, void *, int, double);
+ int (CCONV *fptrSensorUpdate)(CPhidgetMotorControlHandle, void *, int, int);
+ int (CCONV *fptrCurrentUpdate)(CPhidgetMotorControlHandle, void *, int, double);
+
+ void *fptrInputChangeptr;
+ void *fptrVelocityChangeptr;
+ void *fptrCurrentChangeptr;
+ void *fptrEncoderPositionChangeptr;
+ void *fptrEncoderPositionUpdateptr;
+ void *fptrBackEMFUpdateptr;
+ void *fptrSensorUpdateptr;
+ void *fptrCurrentUpdateptr;
+
+ //Deprecated
+ int (CCONV *fptrMotorChange)(CPhidgetMotorControlHandle, void *, int, double);
+ void *fptrMotorChangeptr;
+
+ //Returned from the device
+ unsigned char inputState[MOTORCONTROL_MAXINPUTS];
+ double motorSpeedEcho[MOTORCONTROL_MAXMOTORS];
+ double motorSensedCurrent[MOTORCONTROL_MAXMOTORS];
+ double motorSensedBackEMF[MOTORCONTROL_MAXMOTORS];
+ unsigned char backEMFSensingStateEcho[MOTORCONTROL_MAXMOTORS];
+ double motorSetSpeedEcho[MOTORCONTROL_MAXMOTORS];
+ double motorAccelerationEcho[MOTORCONTROL_MAXMOTORS];
+ double motorBrakingEcho[MOTORCONTROL_MAXMOTORS];
+ double supplyVoltage;
+ int encoderPositionEcho[MOTORCONTROL_MAXENCODERS];
+ int encoderTimeStamp[MOTORCONTROL_MAXENCODERS];
+ unsigned char ratiometricEcho;
+ int sensorRawValue[MOTORCONTROL_MAXSENSORS];
+ int sensorValue[MOTORCONTROL_MAXSENSORS];
+
+ int lastPacketCount;
+
+ //Local set data
+ double motorSpeed[MOTORCONTROL_MAXMOTORS];
+ double motorAcceleration[MOTORCONTROL_MAXMOTORS];
+ unsigned char backEMFSensingState[MOTORCONTROL_MAXMOTORS];
+ double motorBraking[MOTORCONTROL_MAXMOTORS];
+ unsigned char ratiometric;
+
+ int encoderPositionDelta[MOTORCONTROL_MAXENCODERS];
+ unsigned short motorErrors[MOTORCONTROL_MAXMOTORS];
+
+ //Constants
+ double accelerationMax, accelerationMin;
+
+ //for Webservice
+ double lastVoltage;
+ int encoderPositionUpdates[MOTORCONTROL_MAXENCODERS];
+
+ unsigned char outputPacket[8];
+ unsigned int outputPacketLen;
+} typedef CPhidgetMotorControlInfo;
+#endif
+
+/** @} */
+
+#endif
diff --git a/cphidgetphsensor.c b/cphidgetphsensor.c
new file mode 100644
index 0000000..751f530
--- /dev/null
+++ b/cphidgetphsensor.c
@@ -0,0 +1,241 @@
+#include "stdafx.h"
+#include "cphidgetphsensor.h"
+#include <math.h>
+#include "cusb.h"
+#include "csocket.h"
+#include "cthread.h"
+
+// === Internal Functions === //
+
+static double calculate_ph(double Vad, double temperature);
+
+//clearVars - sets all device variables to unknown state
+CPHIDGETCLEARVARS(PHSensor)
+
+ phid->phMax = PUNI_DBL;
+ phid->phMin = PUNI_DBL;
+ phid->potentialMax = PUNI_DBL;
+ phid->potentialMin = PUNI_DBL;
+
+ phid->Temperature = PUNI_DBL;
+ phid->PH = PUNI_DBL;
+ phid->PHLastTrigger = PUNK_DBL;
+ phid->Potential = PUNI_DBL;
+ phid->PHChangeTrigger = PUNI_DBL;
+
+ return EPHIDGET_OK;
+}
+
+//initAfterOpen - sets up the initial state of an object, reading in packets from the device if needed
+// used during attach initialization - on every attach
+CPHIDGETINIT(PHSensor)
+ TESTPTR(phid);
+
+ phid->Temperature = 20; //20 degrees celcius default
+
+ //Setup max/min values
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_PHSENSOR:
+ if ((phid->phid.deviceVersion >= 100) && (phid->phid.deviceVersion < 200))
+ {
+ phid->phMax = round_double(calculate_ph((65535.0 / 13104.0), phid->Temperature), 4);
+ phid->phMin = round_double(calculate_ph(0, phid->Temperature), 4);
+ phid->potentialMax = round_double(((2.5) / 4.745) * 1000.0, 2);
+ phid->potentialMin = round_double(((2.5 - (65535.0 / 13104.0)) / 4.745) * 1000.0, 2);
+ }
+ else
+ return EPHIDGET_BADVERSION;
+ break;
+ default:
+ return EPHIDGET_UNEXPECTED;
+ }
+
+ //initialize triggers, set data arrays to unknown
+ phid->PH = PUNK_DBL;
+ phid->PHLastTrigger = PUNK_DBL;
+ phid->Potential = PUNK_DBL;
+ phid->PHChangeTrigger = 0.05;
+
+ //issue one read
+ CPhidget_read((CPhidgetHandle)phid);
+
+ return EPHIDGET_OK;
+}
+
+//dataInput - parses device packets
+CPHIDGETDATA(PHSensor)
+ double PH = 0, Potential = 0;
+
+ if (length<0) return EPHIDGET_INVALIDARG;
+ TESTPTR(phid);
+ TESTPTR(buffer);
+
+ //Parse device packets - store data locally
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_PHSENSOR:
+ if ((phid->phid.deviceVersion >= 100) && (phid->phid.deviceVersion < 200))
+ {
+ double Vad = 0, E = 0;
+
+ Vad = ((double)((unsigned short)buffer[0]+((unsigned short)buffer[1]<<8))) / 13104.0;
+ PH = round_double(calculate_ph(Vad, phid->Temperature), 4);
+
+ E = (2.5 - Vad) / 4.745;
+ Potential = round_double((E * 1000.0), 2);
+ }
+ else
+ return EPHIDGET_UNEXPECTED;
+ break;
+ default:
+ return EPHIDGET_UNEXPECTED;
+ }
+
+ //Make sure values are within defined range, and store to structure
+ if(PH < phid->phMin || PH > phid->phMax)
+ phid->PH = PUNK_DBL;
+ else
+ phid->PH = PH;
+ if(Potential < phid->potentialMin || Potential > phid->potentialMax)
+ phid->Potential = PUNK_DBL;
+ else
+ phid->Potential = Potential;
+
+ //send out any events that exceed or match the trigger
+ if ((fabs(phid->PH - phid->PHLastTrigger) >= phid->PHChangeTrigger || phid->PHLastTrigger == PUNK_DBL)
+ && phid->PH != PUNK_DBL)
+ {
+ FIRE(PHChange, phid->PH);
+ phid->PHLastTrigger = phid->PH;
+ }
+
+ return EPHIDGET_OK;
+}
+
+//eventsAfterOpen - sends out an event for all valid data, used during attach initialization
+CPHIDGETINITEVENTS(PHSensor)
+ if (phid->PH != PUNK_DBL)
+ {
+ FIRE(PHChange, phid->PH);
+ phid->PHLastTrigger = phid->PH;
+ }
+ return EPHIDGET_OK;
+}
+
+//getPacket - not used for PHSensor
+CGETPACKET(PHSensor)
+ return EPHIDGET_UNEXPECTED;
+}
+
+static double calculate_ph(double Vad, double temperature)
+{
+ double E, E0, C, T;
+ const double R=8.31441, N=1, F=96484.6;
+ T=(273.15)+temperature;
+ C = 2.3 * ((R*T)/(N*F));
+ E0 = 7*C;
+ E = (2.5 - Vad) / 4.745;
+ return ((E0 - E) / C);
+}
+
+// === Exported Functions === //
+
+//create and initialize a device structure
+CCREATE(PHSensor, PHIDCLASS_PHSENSOR)
+
+//event setup functions
+CFHANDLE(PHSensor, PHChange, double)
+
+CGET(PHSensor,PH,double)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_PHSENSOR)
+ TESTATTACHED
+ TESTMASGN(PH, PUNK_DBL)
+
+ MASGN(PH)
+}
+
+CGET(PHSensor,PHMax,double)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_PHSENSOR)
+ TESTATTACHED
+ TESTMASGN(phMax, PUNK_DBL)
+
+ MASGN(phMax)
+}
+
+CGET(PHSensor,PHMin,double)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_PHSENSOR)
+ TESTATTACHED
+ TESTMASGN(phMin, PUNK_DBL)
+
+ MASGN(phMin)
+}
+
+CGET(PHSensor,PHChangeTrigger,double)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_PHSENSOR)
+ TESTATTACHED
+ TESTMASGN(PHChangeTrigger, PUNK_DBL)
+
+ MASGN(PHChangeTrigger)
+}
+CSET(PHSensor,PHChangeTrigger,double)
+ TESTPTR(phid)
+ TESTDEVICETYPE(PHIDCLASS_PHSENSOR)
+ TESTATTACHED
+ TESTRANGE(0, phid->phMax - phid->phMin)
+
+ if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
+ ADDNETWORKKEY(Trigger, "%lE", PHChangeTrigger);
+ else
+ phid->PHChangeTrigger = newVal;
+
+ return EPHIDGET_OK;
+}
+
+CGET(PHSensor,Potential,double)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_PHSENSOR)
+ TESTATTACHED
+ TESTMASGN(Potential, PUNK_DBL)
+
+ MASGN(Potential)
+}
+
+CGET(PHSensor,PotentialMax,double)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_PHSENSOR)
+ TESTATTACHED
+ TESTMASGN(potentialMax, PUNK_DBL)
+
+ MASGN(potentialMax)
+}
+
+CGET(PHSensor,PotentialMin,double)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_PHSENSOR)
+ TESTATTACHED
+ TESTMASGN(potentialMin, PUNK_DBL)
+
+ MASGN(potentialMin)
+}
+
+CSET(PHSensor,Temperature,double)
+ TESTPTR(phid)
+ TESTDEVICETYPE(PHIDCLASS_PHSENSOR)
+ TESTATTACHED
+ TESTRANGE(-273.15, 5000) //arbitrary but reasonable range
+
+ if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
+ ADDNETWORKKEY(Temperature, "%lE", Temperature);
+ else
+ phid->Temperature = newVal;
+
+ phid->phMax = round_double(calculate_ph((65535.0 / 13104.0), phid->Temperature), 4);
+ phid->phMin = round_double(calculate_ph(0, phid->Temperature), 4);
+
+ return EPHIDGET_OK;
+}
diff --git a/cphidgetphsensor.h b/cphidgetphsensor.h
new file mode 100644
index 0000000..90d7a0a
--- /dev/null
+++ b/cphidgetphsensor.h
@@ -0,0 +1,99 @@
+#ifndef __CPHIDGETPHSENSOR
+#define __CPHIDGETPHSENSOR
+#include "cphidget.h"
+
+/** \defgroup phidph Phidget PH Sensor
+ * \ingroup phidgets
+ * Calls specific to the Phidget PH Sensor. See the product manual for more specific API details, supported functionality, units, etc.
+ * @{
+ */
+
+DPHANDLE(PHSensor)
+CHDRSTANDARD(PHSensor)
+
+/**
+ * Gets the sensed PH.
+ * @param phid An attached phidget ph sensor handle.
+ * @param ph The PH.
+ */
+CHDRGET(PHSensor,PH,double *ph)
+/**
+ * Gets the maximum PH that the sensor could report.
+ * @param phid An attached phidget ph sensor handle.
+ * @param max The maximum PH.
+ */
+CHDRGET(PHSensor,PHMax,double *max)
+/**
+ * Gets the minimum PH that the sensor could report.
+ * @param phid An attached phidget ph sensor handle.
+ * @param min The minimum PH.
+ */
+CHDRGET(PHSensor,PHMin,double *min)
+/**
+ * Set a PH change handler. This is called when the PH changes by more then the change trigger.
+ * @param phid An attached phidget ph sensor handle.
+ * @param fptr Callback function pointer.
+ * @param userPtr A pointer for use by the user - this value is passed back into the callback function.
+ */
+CHDREVENT(PHSensor,PHChange,double ph)
+/**
+ * Gets the PH change trigger.
+ * @param phid An attached phidget ph sensor handle.
+ * @param trigger The change trigger.
+ */
+CHDRGET(PHSensor,PHChangeTrigger,double *trigger)
+/**
+ * Sets the PH change trigger.
+ * @param phid An attached phidget ph sensor handle.
+ * @param trigger The change trigger.
+ */
+CHDRSET(PHSensor,PHChangeTrigger,double trigger)
+
+/**
+ * Gets the sensed potential.
+ * @param phid An attached phidget ph sensor handle.
+ * @param potential The potential.
+ */
+CHDRGET(PHSensor,Potential,double *potential)
+/**
+ * Gets the maximum potential that can be sensed.
+ * @param phid An attached phidget ph sensor handle.
+ * @param max The maximum potential.
+ */
+CHDRGET(PHSensor,PotentialMax,double *max)
+/**
+ * Gets the minimum potential that can be sensed.
+ * @param phid An attached phidget ph sensor handle.
+ * @param min The minimum potential.
+ */
+CHDRGET(PHSensor,PotentialMin,double *min)
+
+/**
+ * Sets the temperature to be used for PH calculations.
+ * @param phid An attached phidget ph sensor handle.
+ * @param temperature The temperature (degrees celcius). By default this is 20.
+ */
+CHDRSET(PHSensor,Temperature,double temperature)
+
+#ifndef EXTERNALPROTO
+struct _CPhidgetPHSensor {
+ CPhidget phid;
+
+ int (CCONV *fptrPHChange)(CPhidgetPHSensorHandle, void *, double);
+
+ void *fptrPHChangeptr;
+
+ double PH, Potential;
+ double PHLastTrigger;
+ double PHChangeTrigger;
+
+ double Temperature;
+
+ double phMax, phMin;
+ double potentialMax, potentialMin;
+} typedef CPhidgetPHSensorInfo;
+#endif
+
+/** @} */
+
+#endif
diff --git a/cphidgetrfid.c b/cphidgetrfid.c
new file mode 100644
index 0000000..04e0358
--- /dev/null
+++ b/cphidgetrfid.c
@@ -0,0 +1,2791 @@
+#include "stdafx.h"
+#include "cphidgetrfid.h"
+#include "stdio.h"
+#include "cusb.h"
+#include "csocket.h"
+#include "cthread.h"
+
+// === Internal Functions === //
+CThread_func_return_t tagTimerThreadFunction(CThread_func_arg_t userPtr);
+
+static int analyze_data(CPhidgetRFIDHandle phid);
+static int analyze_data_AC(CPhidgetRFIDHandle phid);
+static int sendRAWData(CPhidgetRFIDHandle phid, unsigned char *data, int bitlength);
+static int advancedTagEventForOldReaders(CPhidgetRFIDHandle phid, unsigned char *data);
+
+//Hitag S Commands
+static int HitagS_UID_REQUEST(CPhidgetRFIDHandle phid);
+static int HitagS_AC_SEQUENCE(CPhidgetRFIDHandle phid, CPhidgetRFID_HitagACHandle ac);
+
+#define ABS(x) ((x) < 0 ? -(x) : (x))
+#define pdiff(a, b) ( ABS((a) - (b)) / (double)( ((a) + (b)) / 2.0 ) )
+
+int CPhidgetRFID_Tag_areEqual(void *arg1, void *arg2)
+{
+ CPhidgetRFID_TagHandle tag1 = (CPhidgetRFID_TagHandle)arg1;
+ CPhidgetRFID_TagHandle tag2 = (CPhidgetRFID_TagHandle)arg2;
+
+ if(!tag1 || !tag2)
+ return PFALSE;
+
+ if(!strcmp(tag1->tagString, tag2->tagString)
+ && tag1->tagInfo.tagType == tag2->tagInfo.tagType
+ && tag1->tagInfo.bitRate == tag2->tagInfo.bitRate
+ && tag1->tagInfo.encoding == tag2->tagInfo.encoding)
+ return PTRUE;
+ else
+ return PFALSE;
+}
+
+void CPhidgetRFID_Tag_free(void *arg)
+{
+ CPhidgetRFID_TagHandle tag = (CPhidgetRFID_TagHandle)arg;
+
+ if(!tag)
+ return;
+
+ free(tag); tag = NULL;
+ return;
+}
+
+int CPhidgetRFID_HitagAC_areEqual(void *arg1, void *arg2)
+{
+ CPhidgetRFID_HitagACHandle ac1 = (CPhidgetRFID_HitagACHandle)arg1;
+ CPhidgetRFID_HitagACHandle ac2 = (CPhidgetRFID_HitagACHandle)arg2;
+
+ if(!ac1 || !ac2)
+ return PFALSE;
+
+ if(!memcmp(ac1->uid, ac2->uid, 4)
+ && ac1->colPos == ac2->colPos)
+ return PTRUE;
+ else
+ return PFALSE;
+}
+
+void CPhidgetRFID_HitagAC_free(void *arg)
+{
+ CPhidgetRFID_HitagACHandle ac = (CPhidgetRFID_HitagACHandle)arg;
+
+ if(!ac)
+ return;
+
+ free(ac); ac = NULL;
+ return;
+}
+
+//clearVars - sets all device variables to unknown state
+CPHIDGETCLEARVARS(RFID)
+ int i = 0;
+
+ phid->antennaEchoState = PUNI_BOOL;
+ phid->ledEchoState = PUNI_BOOL;
+ phid->tagPresent = PUNI_BOOL;
+ phid->fullStateEcho = PUNK_BOOL;
+ phid->ledState = PUNK_BOOL;
+ phid->antennaState = PUNK_BOOL;
+ phid->lastTagValid = PUNI_BOOL;
+
+ for (i = 0; i<RFID_MAXOUTPUTS; i++)
+ {
+ phid->outputEchoState[i] = PUNI_BOOL;
+ }
+
+ return EPHIDGET_OK;
+}
+
+//initAfterOpen - sets up the initial state of an object, reading in packets from the device if needed
+// used during attach initialization - on every attach
+CPHIDGETINIT(RFID)
+ int i = 0;
+ unsigned char buffer[8] = { 0 };
+ int result;
+ TESTPTR(phid);
+
+ //Make sure no old writes are still pending
+ phid->outputPacketLen = 0;
+
+ //setup anything device specific
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_RFID:
+ if (phid->phid.deviceVersion < 200)
+ {
+ phid->fullStateEcho = PFALSE;
+ phid->antennaEchoState = PTRUE;
+ }
+ else
+ return EPHIDGET_BADVERSION;
+ break;
+ case PHIDID_RFID_2OUTPUT: //2-output RFID
+ if ((phid->phid.deviceVersion >= 200) && (phid->phid.deviceVersion < 201))
+ {
+ phid->antennaEchoState = PUNK_BOOL;
+ phid->fullStateEcho = PFALSE;
+ }
+ else if ((phid->phid.deviceVersion >= 201) && (phid->phid.deviceVersion < 300))
+ {
+ phid->antennaEchoState = PUNK_BOOL;
+ phid->fullStateEcho = PTRUE;
+ }
+ else
+ return EPHIDGET_BADVERSION;
+ break;
+ case PHIDID_RFID_2OUTPUT_ADVANCED: //2-output RFID (Advanced)
+ if ((phid->phid.deviceVersion >= 100) && (phid->phid.deviceVersion < 200))
+ {
+ phid->antennaEchoState = PUNK_BOOL;
+ phid->fullStateEcho = PTRUE;
+ }
+ else
+ return EPHIDGET_BADVERSION;
+ break;
+ default:
+ return EPHIDGET_UNEXPECTED;
+ }
+
+ //set data arrays to unknown
+ for (i = 0; i<phid->phid.attr.rfid.numOutputs; i++)
+ {
+ phid->outputEchoState[i] = PUNK_BOOL;
+ }
+ phid->ledEchoState = PUNK_BOOL;
+ phid->tagPresent = PUNK_BOOL;
+ ZEROMEM(phid->lastTag, 10);
+ phid->tagEventPending = PFALSE;
+
+ phid->frequencyEcho = PUNK_INT;
+ phid->pregapClocksEcho = PUNK_INT;
+ phid->postgapClocksEcho = PUNK_INT;
+ phid->zeroClocksEcho = PUNK_INT;
+ phid->oneClocksEcho = PUNK_INT;
+ phid->spaceClocksEcho = PUNK_INT;
+ phid->_4097ConfEcho = PUNK_INT;
+
+ phid->dataReadPtr = 0;
+ phid->dataWritePtr = 0;
+ phid->dataReadACPtr = 0;
+ phid->userReadPtr = 0;
+ phid->manReadPtr = 0;
+ phid->manEventReadPtr = 0;
+ phid->manWritePtr = 0;
+ phid->biphaseReadPtr = 0;
+ phid->biphaseWritePtr = 0;
+
+ phid->ACCodingOK = PFALSE;
+
+ phid->tagAdvancedCount = PUNK_INT;
+
+ phid->polling = PTRUE;
+
+ CThread_mutex_lock(&phid->tagthreadlock);
+ if(phid->tagAdvancedList)
+ CList_emptyList((CListHandle *)&phid->tagAdvancedList, PTRUE, CPhidgetRFID_Tag_free);
+ phid->tagAdvancedList = NULL;
+ CThread_mutex_unlock(&phid->tagthreadlock);
+ phid->lastTagAdvanced.tagString[0] = '\0';
+
+ phid->one = phid->two = phid->oneCount = phid->twoCount = 0;
+
+ phid->manLockedIn = 0;
+ phid->biphaseLockedIn = 0;
+ phid->manShortChange = 0;
+ phid->biphaseShortChange = 0;
+
+ //This needs to always have a valid time
+#ifdef _WINDOWS
+ GetSystemTime(&phid->lastDataTime);
+#else
+ gettimeofday(&phid->lastDataTime,NULL);
+#endif
+
+ //send out any initial pre-read packets
+ switch(phid->phid.deviceIDSpec) {
+ case PHIDID_RFID:
+ if (phid->phid.deviceVersion <= 103)
+ {
+ ZEROMEM(buffer,8);
+ LOG(PHIDGET_LOG_INFO,"Sending workaround startup packet");
+ if ((result = CUSBSendPacket((CPhidgetHandle)phid, buffer)) != EPHIDGET_OK)
+ return result;
+ }
+ break;
+ case PHIDID_RFID_2OUTPUT:
+ default:
+ break;
+ }
+
+ //issue a read for devices that return output data
+ if(phid->fullStateEcho)
+ {
+ int readtries = 16; //should guarentee a packet with output data - even if a tag is present
+ while(readtries-- > 0)
+ {
+ CPhidget_read((CPhidgetHandle)phid);
+ if(phid->outputEchoState[0] != PUNK_BOOL)
+ break;
+ }
+ //one more read guarantees that if there is a tag present, we will see it - output packets only happen every 255ms
+ CPhidget_read((CPhidgetHandle)phid);
+ }
+
+ //if the antenna is on, and tagPresent is unknown, then it is false
+ if(phid->antennaEchoState == PTRUE && phid->tagPresent == PUNK_BOOL)
+ phid->tagPresent = PFALSE;
+
+ //if the antenna is on, and tagCount is unknown, then it is false
+ if(phid->antennaEchoState == PTRUE && phid->tagAdvancedCount == PUNK_INT)
+ phid->tagAdvancedCount = 0;
+
+ //recover what we can - if anything isn't filled out, it's PUNK anyways
+ for (i = 0; i<phid->phid.attr.rfid.numOutputs; i++)
+ {
+ phid->outputState[i] = phid->outputEchoState[i];
+ }
+ phid->antennaState = phid->antennaEchoState;
+ phid->ledState = phid->ledEchoState;
+
+ phid->pregapClocks = phid->pregapClocksEcho;
+ phid->postgapClocks = phid->postgapClocksEcho;
+ phid->zeroClocks = phid->zeroClocksEcho;
+ phid->oneClocks = phid->oneClocksEcho;
+ phid->spaceClocks = phid->spaceClocksEcho;
+ phid->_4097Conf = phid->_4097ConfEcho;
+
+ //make sure the tagTimerThread isn't running
+ if (phid->tagTimerThread.thread_status == PTRUE)
+ {
+ phid->tagTimerThread.thread_status = PFALSE;
+ CThread_join(&phid->tagTimerThread);
+ }
+
+ return EPHIDGET_OK;
+}
+
+//dataInput - parses device packets
+CPHIDGETDATA(RFID)
+ int i = 0, j = 0;
+ unsigned char newTag = PFALSE, newOutputs = PFALSE;
+ unsigned char tagData[5];
+ unsigned char outputs[RFID_MAXOUTPUTS];
+ unsigned char lastOutputs[RFID_MAXOUTPUTS];
+ unsigned char antennaState = 0, ledState = 0;
+ unsigned char gotData = PFALSE;
+
+ if (length<0) return EPHIDGET_INVALIDARG;
+ TESTPTR(phid);
+ TESTPTR(buffer);
+
+ ZEROMEM(tagData, sizeof(tagData));
+ ZEROMEM(outputs, sizeof(outputs));
+ ZEROMEM(lastOutputs, sizeof(lastOutputs));
+
+ //Parse device packets - store data locally
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_RFID:
+ if (phid->phid.deviceVersion < 200)
+ {
+ gotData = PTRUE;
+ CThread_mutex_lock(&phid->tagthreadlock);
+ setTimeNow(&phid->lastTagTime);
+ advancedTagEventForOldReaders(phid, buffer+1);
+ if(!memcmp(phid->lastTag, buffer+1, 5) && phid->tagPresent == PTRUE)
+ newTag = PFALSE;
+ else if(!memcmp("\0\0\0\0\0", buffer+1, 5))
+ newTag = PFALSE;
+ else
+ {
+ memcpy(tagData, buffer+1, 5);
+ newTag = PTRUE;
+ }
+ CThread_mutex_unlock(&phid->tagthreadlock);
+ }
+ else
+ return EPHIDGET_UNEXPECTED;
+ break;
+ case PHIDID_RFID_2OUTPUT:
+ if ((phid->phid.deviceVersion >= 200) && (phid->phid.deviceVersion < 300))
+ {
+ switch(buffer[0])
+ {
+ case RFID_PACKET_TAG:
+ gotData = PTRUE;
+ CThread_mutex_lock(&phid->tagthreadlock);
+ setTimeNow(&phid->lastTagTime);
+ advancedTagEventForOldReaders(phid, buffer+1);
+ if(!memcmp(phid->lastTag, buffer+1, 5) && phid->tagPresent == PTRUE)
+ newTag = PFALSE;
+ else if(!memcmp("\0\0\0\0\0", buffer+1, 5))
+ newTag = PFALSE;
+ else
+ {
+ memcpy(tagData, buffer+1, 5);
+ newTag = PTRUE;
+ }
+ CThread_mutex_unlock(&phid->tagthreadlock);
+
+ break;
+ case RFID_PACKET_OUTPUT_ECHO:
+ if(phid->fullStateEcho)
+ {
+ newOutputs = PTRUE;
+
+ for (i = 0, j = 0x01; i < phid->phid.attr.rfid.numOutputs; i++, j<<=1)
+ {
+ if (buffer[1] & j)
+ outputs[i] = PTRUE;
+ else
+ outputs[i] = PFALSE;
+ }
+
+ if(buffer[1] & RFID_LED_FLAG)
+ ledState = PTRUE;
+ else
+ ledState = PFALSE;
+
+ if(buffer[1] & RFID_ANTENNA_FLAG)
+ antennaState = PTRUE;
+ else
+ antennaState = PFALSE;
+ }
+ break;
+ default:
+ return EPHIDGET_UNEXPECTED;
+ }
+ }
+ else
+ return EPHIDGET_UNEXPECTED;
+ break;
+ // RFID with decoding in software and write support
+ case PHIDID_RFID_2OUTPUT_ADVANCED:
+ if ((phid->phid.deviceVersion >= 100) && (phid->phid.deviceVersion < 200))
+ {
+ int dataLength = 0;
+ int data[RFID_MAX_DATA_PER_PACKET];
+ switch(buffer[0] & 0x80)
+ {
+ case RFID_READ_DATA_IN_PACKET:
+ gotData = PTRUE;
+ phid->frequencyEcho = buffer[1] * 1000;
+
+ //move RFID data into local storage
+ dataLength = buffer[0];
+ for(i = 0; i < dataLength; i++)
+ {
+ data[i] = buffer[i+2];
+ phid->dataBuffer[phid->dataWritePtr] = buffer[i+2];
+
+ phid->dataWritePtr++;
+ phid->dataWritePtr &= RFID_DATA_ARRAY_MASK;
+
+ //if we run into data that hasn't been read... too bad, we overwrite it and adjust the read pointer
+ if(phid->dataWritePtr == phid->dataReadPtr)
+ {
+ phid->dataReadPtr++;
+ phid->dataReadPtr &= RFID_DATA_ARRAY_MASK;
+ }
+ if(phid->dataWritePtr == phid->dataReadACPtr)
+ {
+ phid->dataReadACPtr++;
+ phid->dataReadACPtr &= RFID_DATA_ARRAY_MASK;
+ }
+ }
+
+ break;
+ case RFID_ECHO_IN_PACKET:
+ newOutputs = PTRUE;
+ phid->frequencyEcho = buffer[1] * 1000;
+
+ //LOG(PHIDGET_LOG_DEBUG, "Frequency: %d", phid->frequencyEcho);
+
+ phid->pregapClocksEcho = buffer[2];
+ phid->postgapClocksEcho = buffer[3];
+ phid->zeroClocksEcho = buffer[4];
+ phid->oneClocksEcho = buffer[5];
+ phid->spaceClocksEcho = buffer[6];
+
+ for (i = 0, j = 0x01; i < phid->phid.attr.rfid.numOutputs; i++, j<<=1)
+ {
+ if (buffer[7] & j)
+ outputs[i] = PTRUE;
+ else
+ outputs[i] = PFALSE;
+ }
+
+ if(buffer[7] & RFID_LED_FLAG)
+ ledState = PTRUE;
+ else
+ ledState = PFALSE;
+
+ if(buffer[7] & RFID_ANTENNA_FLAG)
+ antennaState = PTRUE;
+ else
+ antennaState = PFALSE;
+
+ phid->_4097ConfEcho = buffer[8];
+
+ //space in data
+ if(buffer[9])
+ {
+ //Manchester event with space
+ unsigned char manEventData[1];
+ manEventData[0] = PUNK_BOOL;
+
+ FIRE(ManchesterData, manEventData, 1);
+
+ //Add a space in the buffer - only if it's not already a space
+ phid->dataBuffer[phid->dataWritePtr] = PUNK_INT;
+ phid->dataWritePtr++;
+ phid->dataWritePtr &= RFID_DATA_ARRAY_MASK;
+
+ //if we run into data that hasn't been read... too bad, we overwrite it and adjust the read pointer
+ if(phid->dataWritePtr == phid->dataReadPtr)
+ {
+ phid->dataReadPtr++;
+ phid->dataReadPtr &= RFID_DATA_ARRAY_MASK;
+ }
+ if(phid->dataWritePtr == phid->dataReadACPtr)
+ {
+ phid->dataReadACPtr++;
+ phid->dataReadACPtr &= RFID_DATA_ARRAY_MASK;
+ }
+ dataLength = 1;
+ data[0] = PUNK_INT;
+ }
+ else
+ gotData = PTRUE;
+
+ break;
+ default:
+ return EPHIDGET_UNEXPECTED;
+ }
+
+ if(dataLength)
+ {
+ //send out raw data event
+ FIRE(RawData, data, dataLength);
+
+ //analyze data
+ analyze_data(phid);
+ if(phid->ACCodingOK)
+ analyze_data_AC(phid);
+ else
+ phid->dataReadACPtr = phid->dataWritePtr;
+ }
+ }
+ else
+ return EPHIDGET_UNEXPECTED;
+ break;
+ default:
+ return EPHIDGET_UNEXPECTED;
+ }
+
+ if(gotData)
+ setTimeNow(&phid->lastDataTime);
+
+ //Make sure values are within defined range, and store to structure
+ if(newOutputs)
+ {
+ for (i = 0; i < phid->phid.attr.rfid.numOutputs; i++)
+ {
+ lastOutputs[i] = phid->outputEchoState[i];
+ phid->outputEchoState[i] = outputs[i];
+ }
+ phid->ledEchoState = ledState;
+ phid->antennaEchoState = antennaState;
+ }
+ CThread_mutex_lock(&phid->tagthreadlock);
+ if(newTag && !phid->tagEventPending)
+ {
+ memcpy(phid->pendingTag, tagData, 5);
+ phid->tagEventPending = PTRUE;
+ CThread_set_event(&phid->tagAvailableEvent);
+ }
+ CThread_mutex_unlock(&phid->tagthreadlock);
+
+ //Events
+ if(newOutputs)
+ {
+ for (i = 0; i < phid->phid.attr.rfid.numOutputs; i++)
+ {
+ if(lastOutputs[i] != phid->outputEchoState[i])
+ FIRE(OutputChange, i, phid->outputEchoState[i]);
+ }
+ }
+
+ return EPHIDGET_OK;
+}
+
+//eventsAfterOpen - sends out an event for all valid data, used during attach initialization
+CPHIDGETINITEVENTS(RFID)
+
+ if(phid->fullStateEcho)
+ {
+ for (i = 0; i < phid->phid.attr.rfid.numOutputs; i++)
+ {
+ if(phid->outputEchoState[i] != PUNK_BOOL)
+ FIRE(OutputChange, i, phid->outputEchoState[i]);
+ }
+ }
+
+ //Initial tag events are sent from the tagTimerThread
+
+ //Don't start the tag thread if this is a networked Phidget
+ CThread_mutex_lock(&phid->phid.lock);
+ if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_ATTACHED_FLAG))
+ {
+ if(!CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
+ {
+ CThread_mutex_unlock(&phid->phid.lock);
+ //Start the tagTimerThread - do it here because we are about to start the read thread, and that will keep it active
+ phid->tagTimerThread.thread_status = PTRUE;
+ if (CThread_create(&phid->tagTimerThread, tagTimerThreadFunction, phid))
+ {
+ phid->tagTimerThread.thread_status = PFALSE;
+ return EPHIDGET_UNEXPECTED;
+ }
+ }
+ //For remote - if there is a tag present, send the tag event here
+ else
+ {
+ CThread_mutex_unlock(&phid->phid.lock);
+ if(phid->tagPresent == PTRUE)
+ FIRE(Tag, phid->lastTag);
+ }
+ }
+ else
+ {
+ CThread_mutex_unlock(&phid->phid.lock);
+ return EPHIDGET_NOTATTACHED;
+ }
+
+ return EPHIDGET_OK;
+}
+
+//Extra things to do during a close
+//This is run before the other things that close does
+int CPhidgetRFID_close(CPhidgetHandle phidG)
+{
+ CPhidgetRFIDHandle phid = (CPhidgetRFIDHandle)phidG;
+ //make sure the tagTimerThread isn't running
+ if (phid->tagTimerThread.thread_status == PTRUE)
+ {
+ phid->tagTimerThread.thread_status = PFALSE;
+ CThread_join(&phid->tagTimerThread);
+ }
+ return EPHIDGET_OK;
+}
+
+//Extra things to do during a free
+//This is run before the other things that free does
+int CPhidgetRFID_free(CPhidgetHandle phidG)
+{
+ CPhidgetRFIDHandle phid = (CPhidgetRFIDHandle)phidG;
+ CThread_mutex_destroy(&phid->tagthreadlock);
+ CThread_destroy_event(&phid->tagAvailableEvent);
+ CThread_destroy_event(&phid->respEvent);
+ CThread_destroy_event(&phid->respEvent2);
+ return EPHIDGET_OK;
+}
+
+//getPacket - used by write thread to get the next packet to send to device
+CGETPACKET_BUF(RFID)
+
+//sendpacket - sends a packet to the device asynchronously, blocking if the 1-packet queue is full
+CSENDPACKET_BUF(RFID)
+
+//makePacket - constructs a packet using current device state
+CMAKEPACKET(RFID)
+ int i = 0, j = 0;
+
+ TESTPTRS(phid, buffer);
+
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_RFID_2OUTPUT: //4-output RFID
+ if ((phid->phid.deviceVersion >= 200) && (phid->phid.deviceVersion < 300))
+ {
+ //have to make sure that everything to be sent has some sort of default value if the user hasn't set a value
+ for (i = 0; i < phid->phid.attr.rfid.numOutputs; i++)
+ {
+ if (phid->outputState[i] == PUNK_BOOL)
+ phid->outputState[i] = PFALSE;
+ }
+ if(phid->antennaState == PUNK_BOOL)
+ phid->antennaState = PFALSE;
+ if(phid->ledState == PUNK_BOOL)
+ phid->ledState = PFALSE;
+
+ //construct the packet
+ for (i = 0, j = 1; i < phid->phid.attr.rfid.numOutputs; i++, j<<=1)
+ {
+ if (phid->outputState[i])
+ buffer[0] |= j;
+ }
+ if(phid->ledState == PTRUE)
+ buffer[0] |= RFID_LED_FLAG;
+ if(phid->antennaState == PTRUE)
+ buffer[0] |= RFID_ANTENNA_FLAG;
+ }
+ else
+ return EPHIDGET_UNEXPECTED;
+ break;
+ case PHIDID_RFID_2OUTPUT_ADVANCED: //4-output RFID Advanced
+ if ((phid->phid.deviceVersion >= 100) && (phid->phid.deviceVersion < 200))
+ {
+ //have to make sure that everything to be sent has some sort of default value if the user hasn't set a value
+ for (i = 0; i < phid->phid.attr.rfid.numOutputs; i++)
+ {
+ if (phid->outputState[i] == PUNK_BOOL)
+ phid->outputState[i] = PFALSE;
+ }
+ if(phid->antennaState == PUNK_BOOL)
+ phid->antennaState = PFALSE;
+ if(phid->ledState == PUNK_BOOL)
+ phid->ledState = PFALSE;
+
+ //construct the packet
+ for (i = 0, j = 1; i < phid->phid.attr.rfid.numOutputs; i++, j<<=1)
+ {
+ if (phid->outputState[i])
+ buffer[7] |= j;
+ }
+ if(phid->ledState == PTRUE)
+ buffer[7] |= RFID_LED_FLAG;
+ if(phid->antennaState == PTRUE)
+ buffer[7] |= RFID_ANTENNA_FLAG;
+
+ //TODO: make sure these are actually all valid
+ buffer[0] = RFID_CONTROL_OUT_PACKET;
+ buffer[1] = phid->pregapClocks;
+ buffer[2] = phid->postgapClocks;
+ buffer[3] = phid->zeroClocks;
+ buffer[4] = phid->oneClocks;
+ buffer[5] = phid->spaceClocks;
+ buffer[6] = phid->_4097Conf;
+ }
+ else
+ return EPHIDGET_UNEXPECTED;
+ break;
+ case PHIDID_RFID:
+ return EPHIDGET_UNSUPPORTED; //this version does not have outputs
+ default:
+ return EPHIDGET_UNEXPECTED;
+ }
+ return EPHIDGET_OK;
+}
+
+//if the time since last tag read > 200ms, fire tagLost event
+//NOTE: blocking in data events for too long will cause tagLost events
+CThread_func_return_t tagTimerThreadFunction(CThread_func_arg_t userPtr)
+{
+ CPhidgetRFIDHandle phid = (CPhidgetRFIDHandle)userPtr;
+ CPhidgetRFID_TagList *trav = 0, *tagLostList = 0, *tagFoundList = 0;
+
+ if(!phid) return (CThread_func_return_t)EPHIDGET_INVALIDARG;
+
+ LOG(PHIDGET_LOG_INFO,"tagTimerThread running");
+
+ //Set this before creation
+ //phid->tagTimerThread.thread_status = PTRUE;
+
+ while (CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_ATTACHED_FLAG) && phid->tagTimerThread.thread_status == PTRUE)
+ {
+ //sleeps for up to 50ms, but can be signalled externally to return immediately
+ CThread_wait_on_event(&phid->tagAvailableEvent, 50);
+ CThread_reset_event(&phid->tagAvailableEvent);
+
+ //Tag events
+ //Old-style
+ if(phid->tagEventPending)
+ {
+ phid->tagPresent = PTRUE;
+ FIRE(Tag, phid->pendingTag);
+ CThread_mutex_lock(&phid->tagthreadlock);
+ setTimeNow(&phid->lastTagTime);
+
+ //so they can access the last tag from this tag event
+ memcpy(phid->lastTag, phid->pendingTag, 5);
+ phid->tagEventPending = PFALSE;
+ CThread_mutex_unlock(&phid->tagthreadlock);
+ }
+ //New-style
+ CThread_mutex_lock(&phid->tagthreadlock);
+ for (trav=phid->tagAdvancedList; trav; trav = trav->next)
+ {
+ if(trav->tag->tagEventPending == PTRUE)
+ CList_addToList((CListHandle *)&tagFoundList, trav->tag, CPhidgetRFID_Tag_areEqual);
+ }
+ for (trav=tagFoundList; trav; trav = trav->next)
+ {
+ if(phid->tagAdvancedCount == PUNK_INT)
+ phid->tagAdvancedCount = 0;
+ phid->tagAdvancedCount++;
+
+ CThread_mutex_unlock(&phid->tagthreadlock);
+ FIRE(TagAdvanced, trav->tag->tagString, &trav->tag->tagInfo);
+ CThread_mutex_lock(&phid->tagthreadlock);
+ setTimeNow(&trav->tag->lastTagTime);
+
+ //so they can access the last tag from this tag event
+ memcpy(&phid->lastTagAdvanced, trav->tag, sizeof(CPhidgetRFID_Tag));
+ trav->tag->tagEventPending = PFALSE;
+ }
+ CList_emptyList((CListHandle *)&tagFoundList, PFALSE, NULL);
+ CThread_mutex_unlock(&phid->tagthreadlock);
+
+ //TAG Lost events
+ //Old-style
+ if(phid->tagPresent != PFALSE)
+ {
+ /* check for tag lost */
+
+ CThread_mutex_lock(&phid->tagthreadlock);
+ if(timeSince(&phid->lastTagTime) > 0.2)
+ {
+ if (phid->tagPresent == PTRUE) {
+ phid->tagPresent = PFALSE;
+ CThread_mutex_unlock(&phid->tagthreadlock);
+ FIRE(TagLost, phid->lastTag);
+ CThread_mutex_lock(&phid->tagthreadlock);
+ }
+ else if(phid->antennaEchoState == PTRUE) //could be PUNK_BOOL - don't send event, just set to PFALSE (but only if the antenna is on)
+ phid->tagPresent = PFALSE;
+ }
+ CThread_mutex_unlock(&phid->tagthreadlock);
+ }
+ //New-style
+ if(phid->tagAdvancedCount != 0)
+ {
+ if(phid->tagAdvancedCount != PUNK_INT)
+ {
+ CThread_mutex_lock(&phid->tagthreadlock);
+ for (trav=phid->tagAdvancedList; trav; trav = trav->next)
+ {
+ if((timeSince(&trav->tag->lastTagTime) > 0.2 && trav->tag->tagInfo.tagType != PHIDGET_RFID_TAG_HITAGS)
+ || (timeSince(&trav->tag->lastTagTime) > 0.5 && trav->tag->tagInfo.tagType == PHIDGET_RFID_TAG_HITAGS))
+ CList_addToList((CListHandle *)&tagLostList, trav->tag, CPhidgetRFID_Tag_areEqual);
+ }
+ for (trav=tagLostList; trav; trav = trav->next)
+ {
+ CList_removeFromList((CListHandle *)&phid->tagAdvancedList, trav->tag, CPhidgetRFID_Tag_areEqual, PFALSE, NULL);
+ phid->tagAdvancedCount--;
+ CThread_mutex_unlock(&phid->tagthreadlock);
+ FIRE(TagLostAdvanced, trav->tag->tagString, &trav->tag->tagInfo);
+ CThread_mutex_lock(&phid->tagthreadlock);
+ }
+ CList_emptyList((CListHandle *)&tagLostList, PTRUE, CPhidgetRFID_Tag_free);
+ CThread_mutex_unlock(&phid->tagthreadlock);
+ }
+ else if(phid->antennaEchoState == PTRUE)
+ phid->tagAdvancedCount = 0;
+ }
+
+ //Actively look for tags if we haven't gotten data for a while (Hitag)
+ if(phid->antennaEchoState == PTRUE && phid->polling == PTRUE)
+ {
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_RFID_2OUTPUT_ADVANCED: //2-output RFID Advanced
+ if ((phid->phid.deviceVersion >= 100) && (phid->phid.deviceVersion < 200))
+ {
+ CThread_mutex_lock(&phid->tagthreadlock);
+ if(timeSince(&phid->hitagReqTime) > 0.1) //100ms
+ {
+ if(timeSince(&phid->lastDataTime) > 0.1) //100ms
+ {
+ HitagS_UID_REQUEST(phid);
+ }
+ }
+ CThread_mutex_unlock(&phid->tagthreadlock);
+ }
+ else
+ return (CThread_func_return_t)EPHIDGET_UNEXPECTED;
+ break;
+ //Cannot send data
+ case PHIDID_RFID_2OUTPUT:
+ case PHIDID_RFID:
+ break;
+ default:
+ return (CThread_func_return_t)EPHIDGET_UNEXPECTED;
+ }
+ }
+ }
+
+ LOG(PHIDGET_LOG_INFO,"tagTimerThread exiting normally");
+ phid->tagTimerThread.thread_status = FALSE;
+ return (CThread_func_return_t)EPHIDGET_OK;
+}
+
+static int sendRAWData(CPhidgetRFIDHandle phid, unsigned char *data, int bitlength)
+{
+ unsigned char buffer[10];
+ int i, j, result, bits;
+
+ int length = bitlength/8 + (bitlength%8 ? 1 : 0);
+
+ if(length > 0xff)
+ return EPHIDGET_INVALIDARG;
+
+ bits = 0;
+ for (i = 0, j = 1; i < length; i++, j++)
+ {
+ buffer[j] = data[i];
+ if(bitlength < 8)
+ {
+ bits += bitlength;
+ bitlength = 0;
+ }
+ else
+ {
+ bits += 8;
+ bitlength -= 8;
+ }
+ if (j == 7 || i == (length-1))
+ {
+ buffer[0] = RFID_WRITE_DATA_OUT_PACKET | bits;
+ if ((result = CPhidgetRFID_sendpacket(phid, buffer)) != EPHIDGET_OK)
+ {
+ return result;
+ }
+ j = 0;
+ bits = 0;
+ }
+ }
+
+ return EPHIDGET_OK;
+}
+
+static void resetHitagACBuffer(CPhidgetRFIDHandle phid)
+{
+ phid->dataReadACPtr = phid->dataWritePtr;
+ phid->ACCodingOK = PTRUE;
+}
+
+//Hitag CRC
+#define CRC_PRESET 0xFF
+#define CRC_POLYNOM 0x1D
+static void calc_crc_hitag(unsigned char * crc,
+ unsigned char data,
+ unsigned char Bitcount)
+{
+ *crc ^= data; //crc = crc (exor) data
+ do
+ {
+ if( *crc & 0x80 ) // if (MSB-CRC == 1)
+ {
+ *crc<<=1; // CRC = CRC Bit-shift left
+ *crc ^= CRC_POLYNOM; // CRC = CRC (exor) CRC_POLYNOM
+ }
+ else
+ *crc<<=1; // CRC = CRC Bit-shift left
+ } while(--Bitcount);
+}
+static unsigned char hitagCRC8(unsigned char *data, int dataBits)
+{
+ unsigned char crc;
+ int i;
+ int dataLength = dataBits / 8;
+ if(dataBits%8 != 0)
+ dataLength++;
+ crc = CRC_PRESET; /* initialize crc algorithm */
+
+ for(i=0; i<dataLength; i++)
+ {
+ calc_crc_hitag(&crc, data[i], ((dataBits > 8) ? 8 : dataBits));
+ dataBits -= 8;
+ }
+
+ return crc;
+}
+
+static int HitagS_WRITE(CPhidgetRFIDHandle phid, int page, unsigned char *data, unsigned char blockWrite)
+{
+ int res;
+ unsigned char buf[] = {0,0,0};
+ unsigned char crc;
+
+ buf[0] = (blockWrite ? 0x90 : 0x80) | page >> 4;
+ buf[1] = page << 4;
+ crc = hitagCRC8(buf, 12);
+ buf[1] |= crc >> 4;
+ buf[2] = crc << 4;
+
+ //make sure it's been at least 50ms since last hitag request
+ CThread_mutex_lock(&phid->tagthreadlock);
+ while(timeSince(&phid->hitagReqTime) < 0.01) //50ms
+ SLEEP(10);
+
+ phid->hitagState = RFID_HITAG_STATE_WRITE;
+ phid->hitagOffset = page;
+
+ phid->manShortChange=0;
+ phid->manLockedIn = 1;
+ phid->manReadPtr = phid->manWritePtr;
+
+ //Send a Hitag S AC Sequence Command
+ res = CPhidgetRFID_writeRaw(phid, buf, 20, 9, 9, 9, 13, 19);
+
+ //Don't send it again for at least 100ms
+ setTimeNow(&phid->hitagReqTime);
+ CThread_mutex_unlock(&phid->tagthreadlock);
+
+ //Wait for ACK
+
+ //Send page data
+
+ return res;
+}
+
+static int HitagS_READ(CPhidgetRFIDHandle phid, int page, unsigned char blockRead)
+{
+ int res;
+ unsigned char buf[] = {0,0,0};
+ unsigned char crc;
+
+ buf[0] = (blockRead ? 0xD0 : 0xC0) | page >> 4;
+ buf[1] = page << 4;
+ crc = hitagCRC8(buf, 12);
+ buf[1] |= crc >> 4;
+ buf[2] = crc << 4;
+
+ //make sure it's been at least 50ms since last hitag request
+ CThread_mutex_lock(&phid->tagthreadlock);
+ while(timeSince(&phid->hitagReqTime) < 0.01) //50ms
+ SLEEP(10);
+
+ phid->hitagState = RFID_HITAG_STATE_READ;
+ phid->hitagOffset = page;
+
+ phid->manShortChange=0;
+ phid->manLockedIn = 1;
+ phid->manReadPtr = phid->manWritePtr;
+
+ //Send a Hitag S AC Sequence Command
+ res = CPhidgetRFID_writeRaw(phid, buf, 20, 9, 9, 9, 13, 19);
+
+ //Don't send it again for at least 100ms
+ setTimeNow(&phid->hitagReqTime);
+ CThread_mutex_unlock(&phid->tagthreadlock);
+
+ return res;
+}
+
+static int HitagS_SELECT(CPhidgetRFIDHandle phid, unsigned char *UID)
+{
+ int res;
+ unsigned char buf[] = {0,0,0,0,0,0};
+ unsigned char crc;
+ int k,i;
+
+ if(!UID)
+ return EPHIDGET_INVALIDARG;
+ if(strlen((char *)UID)!=8)
+ return EPHIDGET_INVALIDARG;
+
+ for(i=0,k=5;i<32;i++,k++)
+ {
+ buf[k/8] |= ((hexval(UID[i/4]) >> (3-(i%4))) & 0x01) << (7-(k%8));
+ }
+ crc = hitagCRC8(buf, 37);
+ for(i=0;i<8;i++,k++)
+ {
+ buf[k/8] |= (crc >> (7-(i%8))) << (7-(k%8));
+ }
+
+ //make sure it's been at least 50ms since last hitag request
+ CThread_mutex_lock(&phid->tagthreadlock);
+ while(timeSince(&phid->hitagReqTime) < 0.05) //50ms
+ SLEEP(10);
+
+ phid->hitagState = RFID_HITAG_STATE_SELECT;
+
+ phid->manShortChange=0;
+ phid->manLockedIn = 1;
+ phid->manReadPtr = phid->manWritePtr;
+
+ //Send a Hitag S AC Sequence Command
+ res = CPhidgetRFID_writeRaw(phid, buf, k, 9, 9, 9, 13, 19);
+
+ //Don't send it again for at least 100ms
+ setTimeNow(&phid->hitagReqTime);
+ CThread_mutex_unlock(&phid->tagthreadlock);
+
+ return res;
+}
+static int HitagS_UID_REQUEST(CPhidgetRFIDHandle phid)
+{
+ int res;
+ //Send a Hitag S UID Request Command
+ unsigned char buf[] = { 0xC0 };
+
+ //make sure it's been at least 50ms since last hitag request
+ CThread_mutex_lock(&phid->tagthreadlock);
+ while(timeSince(&phid->hitagReqTime) < 0.05) //50ms
+ SLEEP(10);
+
+ phid->hitagState = RFID_HITAG_STATE_UID_REQUEST;
+
+ //Empty AC List
+ if(phid->hitagACList)
+ CList_emptyList((CListHandle *)&phid->hitagACList, PTRUE, CPhidgetRFID_HitagAC_free);
+ phid->hitagACList = NULL;
+
+ resetHitagACBuffer(phid);
+ res = CPhidgetRFID_writeRaw(phid, buf, 5, 9, 9, 9, 13, 19);
+
+ //Don't send it again for at least 100ms
+ setTimeNow(&phid->hitagReqTime);
+ CThread_mutex_unlock(&phid->tagthreadlock);
+
+ return res;
+}
+static int HitagS_AC_SEQUENCE(CPhidgetRFIDHandle phid, CPhidgetRFID_HitagACHandle ac)
+{
+ int res;
+ unsigned char buf[] = {0,0,0,0,0,0};
+ unsigned char crc;
+ int k,i;
+
+ buf[0] = (ac->colPos) << 3;
+ for(i=0,k=5;i<ac->colPos;i++,k++)
+ {
+ buf[k/8] |= (ac->uid[i/8] >> (7-(i%8))) << (7-(k%8));
+ }
+ crc = hitagCRC8(buf, ac->colPos+5);
+ for(i=0;i<8;i++,k++)
+ {
+ buf[k/8] |= (crc >> (7-(i%8))) << (7-(k%8));
+ }
+
+ //make sure it's been at least 50ms since last hitag request
+ CThread_mutex_lock(&phid->tagthreadlock);
+ while(timeSince(&phid->hitagReqTime) < 0.05) //50ms
+ SLEEP(10);
+
+ memcpy(&phid->lastHitagAC, ac, sizeof(CPhidgetRFID_HitagAC));
+
+ //Send a Hitag S AC Sequence Command
+ phid->hitagState = RFID_HITAG_STATE_AC_SEQUENCE;
+
+ resetHitagACBuffer(phid);
+ res = CPhidgetRFID_writeRaw(phid, buf, k, 9, 9, 9, 13, 19);
+
+ //Don't send it again for at least 100ms
+ setTimeNow(&phid->hitagReqTime);
+ CThread_mutex_unlock(&phid->tagthreadlock);
+
+ return res;
+}
+
+static int decodeEM4102(CPhidgetRFIDHandle phid, unsigned char *data, int *startPtr, int *endPtr, CPhidgetRFID_TagHandle tag)
+{
+ int i, foundStart, k, j;
+ int myReadPtr = *startPtr;
+ int em4103data[64];
+ unsigned char decodedData[5];
+ int bytesInQueue;
+ //Look for the starting pattern of 9 Ones
+start:
+ bytesInQueue = *endPtr - myReadPtr;
+ if(myReadPtr > *endPtr)
+ bytesInQueue += RFID_DATA_ARRAY_SIZE;
+
+ while(myReadPtr != *endPtr)
+ {
+ if(bytesInQueue < 64)
+ return EPHIDGET_NOTFOUND;
+ foundStart = 1;
+
+ for(i=0;i<9;i++)
+ {
+ if(data[(myReadPtr + i) & RFID_DATA_ARRAY_MASK] != 1)
+ {
+ foundStart = 0;
+ break;
+ }
+ }
+ if(foundStart)
+ break;
+
+ myReadPtr++;
+ myReadPtr &= RFID_DATA_ARRAY_MASK;
+
+ bytesInQueue--;
+ }
+
+ //Got here? - We found the start pattern
+ //Now decode the EM4102 data
+ for(i=0;i<64;i++)
+ {
+ em4103data[i] = data[(myReadPtr + i) & RFID_DATA_ARRAY_MASK];
+ }
+
+ //last bit should be zero (stop bit)
+ if(em4103data[63] != 0)
+ goto tryagain;
+
+ //row Parity
+ for(i=0;i<10;i++)
+ {
+ int rowParity = 0;
+ for(k=0;k<4;k++)
+ rowParity ^= em4103data[9+i*5+k];
+ if(rowParity != em4103data[9+i*5+k])
+ goto tryagain;
+ }
+ //column parity
+ for(i=0;i<4;i++)
+ {
+ int colParity = 0;
+ for(k=0;k<10;k++)
+ colParity ^= em4103data[9+i+k*5];
+ if(colParity != em4103data[9+i+k*5])
+ goto tryagain;
+ }
+
+ //We're good! Strip out data
+ memset(decodedData, 0, 5);
+ for(i=0,j=9;i<5;i++)
+ {
+ for(k=7;k>=4;k--,j++)
+ decodedData[i] |= em4103data[j] << k;
+ j++; //skip row parity bit
+ for(k=3;k>=0;k--,j++)
+ decodedData[i] |= em4103data[j] << k;
+ j++; //skip row parity bit
+ }
+
+ //Old style Tag event for EM4102
+ CThread_mutex_lock(&phid->tagthreadlock);
+ setTimeNow(&phid->lastTagTime);
+ if((memcmp(phid->lastTag, decodedData, 5) || phid->tagPresent == PFALSE)
+ && memcmp("\0\0\0\0\0", decodedData, 5)
+ && !phid->tagEventPending)
+ {
+ memcpy(phid->pendingTag, decodedData, 5);
+ phid->tagEventPending = PTRUE;
+ CThread_set_event(&phid->tagAvailableEvent);
+ }
+ CThread_mutex_unlock(&phid->tagthreadlock);
+
+ //Update the tag struct for the advanced tag event
+ snprintf(tag->tagString, 255, "%02x%02x%02x%02x%02x",decodedData[0],decodedData[1],decodedData[2],decodedData[3],decodedData[4]);
+ tag->tagInfo.tagType = PHIDGET_RFID_TAG_EM4102;
+
+ //update master read pointer
+ (*startPtr)+=64;
+ (*startPtr) &= RFID_DATA_ARRAY_MASK;
+ return EPHIDGET_OK;
+
+tryagain:
+ myReadPtr++;
+ myReadPtr &= RFID_DATA_ARRAY_MASK;
+ goto start;
+}
+
+//ISO11785 CRC
+void
+CRC_16_CCITT_update(unsigned short *crc, unsigned char x)
+{
+ unsigned short crc_new = (unsigned char)((*crc) >> 8) | ((*crc) << 8);
+ crc_new ^= x;
+ crc_new ^= (unsigned char)(crc_new & 0xff) >> 4;
+ crc_new ^= crc_new << 12;
+ crc_new ^= (crc_new & 0xff) << 5;
+ (*crc) = crc_new;
+}
+
+static int decodeISO11785(CPhidgetRFIDHandle phid, unsigned char *data, int *startPtr, int *endPtr, CPhidgetRFID_TagHandle tag)
+{
+ int i, foundStart, k;
+ int myReadPtr = *startPtr;
+ unsigned char iso11785data[8];
+ unsigned char iso11785dataReversed[8];
+ unsigned short iso11785checksum;
+ int bytesInQueue;
+ unsigned short crc = 0x0000;
+ //Look for the starting pattern of 10 zeroes and 1 one
+start:
+ bytesInQueue = *endPtr - myReadPtr;
+ if(myReadPtr > *endPtr)
+ bytesInQueue += RFID_DATA_ARRAY_SIZE;
+
+ while(myReadPtr != *endPtr)
+ {
+ //full sequence is 128 bits
+ if(bytesInQueue < 128)
+ return EPHIDGET_NOTFOUND;
+ foundStart = 1;
+
+ for(i=0;i<10;i++)
+ {
+ if(data[(myReadPtr + i) & RFID_DATA_ARRAY_MASK] != 0)
+ {
+ foundStart = 0;
+ break;
+ }
+ }
+ if(data[(myReadPtr + 10) & RFID_DATA_ARRAY_MASK] != 1)
+ {
+ foundStart = 0;
+ }
+ if(foundStart)
+ break;
+
+ myReadPtr++;
+ myReadPtr &= RFID_DATA_ARRAY_MASK;
+
+ bytesInQueue--;
+ }
+
+ //advance past header
+ myReadPtr += 11;
+ myReadPtr &= RFID_DATA_ARRAY_MASK;
+
+ //Got here? - We found the start pattern
+ //Now decode the ISO11785 data
+ //every block of 8 is followed by a '1'
+ memset(iso11785data, 0, 8);
+ memset(iso11785dataReversed, 0, 8);
+ for(i=0,k=0;i<64;i++,k++)
+ {
+ if(i>0 && i%8 == 0)
+ {
+ if(data[(myReadPtr + k) & RFID_DATA_ARRAY_MASK] != 1) goto tryagain;
+ k++;
+ }
+ iso11785data[i/8] |= data[(myReadPtr + k) & RFID_DATA_ARRAY_MASK] << (7-(i%8));
+ iso11785dataReversed[7-(i/8)] |= data[(myReadPtr + k) & RFID_DATA_ARRAY_MASK] << (i%8);
+ }
+ if(data[(myReadPtr + k) & RFID_DATA_ARRAY_MASK] != 1) goto tryagain;
+ k++;
+
+ //Now the checksum
+ iso11785checksum = 0;
+ for(i=0;i<16;i++,k++)
+ {
+ if(i>0 && i%8 == 0)
+ {
+ if(data[(myReadPtr + k) & RFID_DATA_ARRAY_MASK] != 1) goto tryagain;
+ k++;
+ }
+ iso11785checksum |= data[(myReadPtr + k) & RFID_DATA_ARRAY_MASK] << (15-i);
+ }
+ if(data[(myReadPtr + k) & RFID_DATA_ARRAY_MASK] != 1) goto tryagain;
+ k++;
+
+ //TODO: there is also a 24 bit trailer which can contain extra info
+
+ //Checksum
+ crc = 0x0000;
+ for(i=0;i<8;i++)
+ {
+ CRC_16_CCITT_update(&crc, iso11785data[i]);
+ }
+
+ if(crc != iso11785checksum)
+ {
+ //FAIL
+ goto tryagain;
+ }
+
+ //We're good!
+ //Parse out the different sections
+ {
+ //These are not used for now
+ //unsigned char animal = iso11785dataReversed[0] & 0x80 ? PTRUE : PFALSE; //1 bit - bit 0
+ //unsigned char extraData = iso11785dataReversed[1] & 0x01 ? PTRUE : PFALSE; //1 bit - bit 15
+ unsigned short countryCode = (iso11785dataReversed[2] << 2 | iso11785dataReversed[3] >> 6) & 0x3ff; //10 bit - bits 16-26
+ unsigned long long UID = (
+ (((__uint64)iso11785dataReversed[3]) << 32) +
+ (((__uint64)iso11785dataReversed[4]) << 24) +
+ (((__uint64)iso11785dataReversed[5]) << 16) +
+ (((__uint64)iso11785dataReversed[6]) << 8) +
+ ((__uint64)iso11785dataReversed[7])) & 0x3FFFFFFFFFll;// 38 bit - bits 27-63
+
+ snprintf(tag->tagString, 255, "%03d%012lld",countryCode, UID);
+ tag->tagInfo.tagType = PHIDGET_RFID_TAG_ISO11784;
+ }
+
+ //update master read pointer
+ (*startPtr) += 128;
+ (*startPtr) &= RFID_DATA_ARRAY_MASK;
+ return EPHIDGET_OK;
+
+tryagain:
+ myReadPtr++;
+ myReadPtr &= RFID_DATA_ARRAY_MASK;
+ goto start;
+}
+
+static int decodeHitagUID(CPhidgetRFIDHandle phid, unsigned char *data, int bytesInQueue, CPhidgetRFID_TagHandle tag, int *collisionPos)
+{
+ int i, k;
+ int myReadPtr = 0;
+ unsigned int HitagUID;
+ int sofBits = 3;
+ int expectedBytes = 0;
+
+ if(phid->hitagState == RFID_HITAG_STATE_UID_REQUEST)
+ expectedBytes = 35;
+ else if(phid->hitagState == RFID_HITAG_STATE_AC_SEQUENCE)
+ expectedBytes = 35 - phid->lastHitagAC.colPos;
+
+ *collisionPos = -1;
+
+ //UID is 32 bits, plus SOF == '111'
+ if(bytesInQueue != expectedBytes)
+ return EPHIDGET_NOTFOUND;
+
+ //verify SOF
+ for(i=0;i<sofBits;i++)
+ {
+ if(data[(myReadPtr + i) & RFID_DATA_ARRAY_MASK] != 1)
+ return EPHIDGET_NOTFOUND;
+ }
+
+ //advance past SOF
+ myReadPtr += sofBits;
+ myReadPtr &= RFID_DATA_ARRAY_MASK;
+
+ HitagUID = 0;
+
+ //if AC Sequence, read in bits from last AC
+ for(k=0;k<(32-(expectedBytes-sofBits));k++)
+ {
+ HitagUID |= (phid->lastHitagAC.uid[k/8] >> (7-(k%8))) << (31-k);
+ }
+
+ for(i=0;i<(expectedBytes-sofBits);k++,i++)
+ {
+ //check for a collision
+ if(data[(myReadPtr + i) & RFID_DATA_ARRAY_MASK] == PUNK_BOOL)
+ {
+ *collisionPos = k;
+ return EPHIDGET_NOTFOUND;
+ }
+ HitagUID |= data[(myReadPtr + i) & RFID_DATA_ARRAY_MASK] << (31-k);
+ }
+
+ //We're good!
+ snprintf(tag->tagString, 255, "%08x",HitagUID);
+ tag->tagInfo.tagType = PHIDGET_RFID_TAG_HITAGS;
+
+ return EPHIDGET_OK;
+}
+
+static int decodeHitagACKResponse(CPhidgetRFIDHandle phid, unsigned char *data, int *startPtr, int *endPtr)
+{
+ int myReadPtr = *startPtr;
+ int bytesInQueue;
+ int i;
+ int sofBits = 5; //SOF is really 6-bit but we only see it as 5-bit
+ int expectedBytes = 7;
+
+ bytesInQueue = *endPtr - myReadPtr;
+ if(myReadPtr > *endPtr)
+ bytesInQueue += RFID_DATA_ARRAY_SIZE;
+
+ //printf("maybe(read).. %d\n", bytesInQueue);
+ //print_buffer(data, *startPtr, *endPtr);
+
+ if(bytesInQueue != expectedBytes)
+ return EPHIDGET_NOTFOUND;
+
+ //verify SOF
+ for(i=0;i<sofBits;i++)
+ {
+ if(data[(myReadPtr + i) & RFID_DATA_ARRAY_MASK] != 1)
+ {
+ phid->respStatus = EPHIDGET_NOTFOUND;
+ goto done;
+ }
+ }
+
+ //Data should be '01'
+ if(data[(myReadPtr + 5) & RFID_DATA_ARRAY_MASK] != 0
+ || data[(myReadPtr + 6) & RFID_DATA_ARRAY_MASK] != 1)
+ {
+ phid->respStatus = EPHIDGET_NOTFOUND;
+ goto done;
+ }
+
+ phid->respStatus = EPHIDGET_OK;
+done:
+ CThread_set_event(&phid->respEvent);
+ return phid->respStatus;
+}
+
+static int decodeHitagReadResponse(CPhidgetRFIDHandle phid, unsigned char *data, int *startPtr, int *endPtr)
+{
+ int myReadPtr = *startPtr;
+ int bytesInQueue;
+ unsigned char buf[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+ int i,k;
+ int sofBits = 5; //SOF is really 6-bit but we only see it as 5-bit
+ int expectedBytes = 141;
+ unsigned char crcExpected = 0, crcFound = 0;
+ CPhidgetRFID_TagHandle tag = phid->respData;
+
+ bytesInQueue = *endPtr - myReadPtr;
+ if(myReadPtr > *endPtr)
+ bytesInQueue += RFID_DATA_ARRAY_SIZE;
+
+ //printf("maybe(read).. %d\n", bytesInQueue);
+ //print_buffer(data, *startPtr, *endPtr);
+
+ if(bytesInQueue != expectedBytes)
+ return EPHIDGET_NOTFOUND;
+
+ //verify SOF
+ for(i=0;i<sofBits;i++)
+ {
+ if(data[(myReadPtr + i) & RFID_DATA_ARRAY_MASK] != 1)
+ {
+ phid->respStatus = EPHIDGET_NOTFOUND;
+ goto done;
+ }
+ }
+
+ //advance past SOF
+ myReadPtr += sofBits;
+ myReadPtr &= RFID_DATA_ARRAY_MASK;
+
+ for(k=0;k<128;k++)
+ {
+ buf[k/8] |= data[(myReadPtr + k) & RFID_DATA_ARRAY_MASK] << (7-(k%8));
+ }
+ for(i=0;i<8;k++,i++)
+ {
+ crcFound |= data[(myReadPtr + k) & RFID_DATA_ARRAY_MASK] << (7-i);
+ }
+ crcExpected = hitagCRC8(buf, 128);
+
+ if(crcFound != crcExpected)
+ {
+ LOG(PHIDGET_LOG_WARNING, "Hitag Read response has bad CRC (%02x, %02x)",crcFound, crcExpected);
+ phid->respStatus = EPHIDGET_NOTFOUND;
+ goto done;
+ }
+
+ //We're good! transfer Read data
+ memcpy(tag->tagData + phid->hitagOffset * 4, buf, 16);
+ tag->tagDataValid = PTRUE;
+
+ //update timer
+ setTimeNow(&tag->lastTagTime);
+
+ phid->respStatus = EPHIDGET_OK;
+done:
+ CThread_set_event(&phid->respEvent);
+ return phid->respStatus;
+}
+
+static int decodeHitagSelectResponse(CPhidgetRFIDHandle phid, unsigned char *data, int *startPtr, int *endPtr)
+{
+ int myReadPtr = *startPtr;
+ int bytesInQueue;
+ unsigned char buf[] = {0,0,0,0};
+ int i,k;
+ int sofBits = 5; //SOF is really 6-bit but we only see it as 5-bit
+ int expectedBytes = 45;
+ unsigned char crcExpected = 0, crcFound = 0;
+ CPhidgetRFID_TagHandle tag = phid->respData;
+
+ bytesInQueue = *endPtr - myReadPtr;
+ if(myReadPtr > *endPtr)
+ bytesInQueue += RFID_DATA_ARRAY_SIZE;
+
+ //printf("maybe.. %d\n", bytesInQueue);
+ //print_buffer(data, *startPtr, *endPtr);
+
+ if(bytesInQueue != expectedBytes)
+ return EPHIDGET_NOTFOUND;
+
+ //verify SOF
+ for(i=0;i<sofBits;i++)
+ {
+ if(data[(myReadPtr + i) & RFID_DATA_ARRAY_MASK] != 1)
+ {
+ phid->respStatus = EPHIDGET_NOTFOUND;
+ goto done;
+ }
+ }
+
+ //advance past SOF
+ myReadPtr += sofBits;
+ myReadPtr &= RFID_DATA_ARRAY_MASK;
+
+ for(k=0;k<32;k++)
+ {
+ buf[k/8] |= data[(myReadPtr + k) & RFID_DATA_ARRAY_MASK] << (7-(k%8));
+ }
+ for(i=0;i<8;k++,i++)
+ {
+ crcFound |= data[(myReadPtr + k) & RFID_DATA_ARRAY_MASK] << (7-i);
+ }
+ crcExpected = hitagCRC8(buf, 32);
+
+ if(crcFound != crcExpected)
+ {
+ LOG(PHIDGET_LOG_WARNING, "Hitag Select response has bad CRC (%02x, %02x)",crcFound, crcExpected);
+ phid->respStatus = EPHIDGET_NOTFOUND;
+ goto done;
+ }
+
+ //We're good! fill in structure
+ //Memory size
+ switch(buf[0] & 0x03)
+ {
+ case 0x00:
+ tag->tagOptions.memSize = 32;
+ break;
+ case 0x01:
+ tag->tagOptions.memSize = 256;
+ break;
+ case 0x02:
+ tag->tagOptions.memSize = 2048;
+ break;
+ case 0x03:
+ default:
+ phid->respStatus = EPHIDGET_UNEXPECTED;
+ goto done;
+ }
+ //AUT bit
+ if(buf[1] & 0x80)
+ tag->tagOptions.encrypted = PTRUE;
+ else
+ tag->tagOptions.encrypted = PFALSE;
+ //LCON bit
+ if(buf[1] & 0x02)
+ tag->tagOptions.writable = PFALSE;
+ else
+ tag->tagOptions.writable = PTRUE;
+
+ tag->tagOptionsValid = PTRUE;
+
+ //update timer
+ setTimeNow(&tag->lastTagTime);
+
+ phid->respStatus = EPHIDGET_OK;
+done:
+ CThread_set_event(&phid->respEvent);
+ return phid->respStatus;
+}
+
+static int add_biphase_data(CPhidgetRFIDHandle phid, int readToPtr, int shortClocks, int longClocks)
+{
+ int myReadPtr = phid->dataReadPtr;
+ while(myReadPtr != readToPtr)
+ {
+ int clocks = phid->dataBuffer[myReadPtr] & 0x7F;
+ //int polarity = (phid->dataBuffer[myReadPtr] & 0x80) ? 1 : 0;
+
+ //1
+ if (pdiff(clocks, longClocks) < 0.3) {
+
+ phid->biphaseBuffer[phid->biphaseWritePtr] = 1;
+
+ phid->biphaseWritePtr++;
+ phid->biphaseWritePtr &= RFID_DATA_ARRAY_MASK;
+
+ if(phid->biphaseWritePtr == phid->biphaseReadPtr)
+ {
+ phid->biphaseReadPtr++;
+ phid->biphaseReadPtr &= RFID_DATA_ARRAY_MASK;
+ }
+
+ phid->biphaseLockedIn = 1;
+ phid->biphaseShortChange = 0;
+ }
+ else if (pdiff(clocks, shortClocks) < 0.3) {
+ if (phid->biphaseLockedIn && phid->biphaseShortChange) {
+ phid->biphaseBuffer[phid->biphaseWritePtr] = 0;
+
+ phid->biphaseWritePtr++;
+ phid->biphaseWritePtr &= RFID_DATA_ARRAY_MASK;
+
+ if(phid->biphaseWritePtr == phid->biphaseReadPtr)
+ {
+ phid->biphaseReadPtr++;
+ phid->biphaseReadPtr &= RFID_DATA_ARRAY_MASK;
+ }
+
+ phid->biphaseShortChange=0;
+ }
+ else
+ phid->biphaseShortChange=1;
+ }
+ else {
+ phid->biphaseLockedIn = 0;
+ //invalid
+ phid->biphaseReadPtr = phid->biphaseWritePtr;
+ //This is not BiPhase encoded data
+ return EPHIDGET_NOTFOUND;
+ }
+
+ myReadPtr++;
+ myReadPtr &= RFID_DATA_ARRAY_MASK;
+ }
+ return EPHIDGET_OK;
+}
+
+static int add_manchester_data(CPhidgetRFIDHandle phid, int readToPtr, int shortClocks, int longClocks)
+{
+ int myReadPtr = phid->dataReadPtr;
+ while(myReadPtr != readToPtr)
+ {
+ int clocks = phid->dataBuffer[myReadPtr] & 0x7F;
+ int polarity = (phid->dataBuffer[myReadPtr] & 0x80) ? 1 : 0;
+
+ if (pdiff(clocks, longClocks) < 0.3) {
+
+ if (polarity)
+ phid->manBuffer[phid->manWritePtr] = 1;
+ else
+ phid->manBuffer[phid->manWritePtr] = 0;
+
+ phid->manWritePtr++;
+ phid->manWritePtr &= RFID_DATA_ARRAY_MASK;
+
+ if(phid->manWritePtr == phid->manReadPtr)
+ {
+ phid->manReadPtr++;
+ phid->manReadPtr &= RFID_DATA_ARRAY_MASK;
+ }
+
+ if(phid->manWritePtr == phid->manEventReadPtr)
+ {
+ phid->manEventReadPtr++;
+ phid->manEventReadPtr &= RFID_DATA_ARRAY_MASK;
+ }
+
+ phid->manLockedIn = 1;
+ phid->manShortChange = 0;
+ }
+ else if (pdiff(clocks, shortClocks) < 0.3) {
+ if (phid->manLockedIn && phid->manShortChange) {
+ if (polarity)
+ phid->manBuffer[phid->manWritePtr] = 1;
+ else
+ phid->manBuffer[phid->manWritePtr] = 0;
+
+ phid->manWritePtr++;
+ phid->manWritePtr &= RFID_DATA_ARRAY_MASK;
+
+ if(phid->manWritePtr == phid->manReadPtr)
+ {
+ phid->manReadPtr++;
+ phid->manReadPtr &= RFID_DATA_ARRAY_MASK;
+ }
+
+ if(phid->manWritePtr == phid->manEventReadPtr)
+ {
+ phid->manEventReadPtr++;
+ phid->manEventReadPtr &= RFID_DATA_ARRAY_MASK;
+ }
+
+ phid->manShortChange=0;
+ }
+ else
+ phid->manShortChange=1;
+ }
+ else {
+ phid->manLockedIn = 0;
+ //invalid
+ phid->manReadPtr = phid->manEventReadPtr = phid->manWritePtr;
+ //This is not Manchester encoded data
+ return EPHIDGET_NOTFOUND;
+ }
+
+ myReadPtr++;
+ myReadPtr &= RFID_DATA_ARRAY_MASK;
+ }
+ return EPHIDGET_OK;
+}
+
+//Anti-Collision coding for Hitag S
+static int decodeACdata(CPhidgetRFIDHandle phid, unsigned char *acBuffer, int *acBufferSize, int readToPtr, int shortClocks, int longClocks)
+{
+ int myReadPtr = phid->dataReadACPtr;
+ int clocks1 = 0;
+ int polarity1 = 0;
+ int clocks2 = 0;
+ int clocks = 0;
+ int polarity2 = 0;
+ int i;
+ int bytesToRead;
+ int lastIndex = 0;
+ int acWritePtr = 0;
+ unsigned char acBitLocation = 0;
+
+ if(phid->hitagState == RFID_HITAG_STATE_UID_REQUEST)
+ lastIndex = 34;
+ else if(phid->hitagState == RFID_HITAG_STATE_AC_SEQUENCE)
+ lastIndex = 34 - phid->lastHitagAC.colPos;
+
+ if(*acBufferSize < lastIndex+1)
+ goto fail;
+
+ //if the first pulse is low, we need to add a high pulse before it
+ if(!(phid->dataBuffer[phid->dataReadACPtr] & 0x80))
+ {
+ myReadPtr--;
+ myReadPtr &= RFID_DATA_ARRAY_MASK;
+ phid->dataBuffer[myReadPtr] = (shortClocks/2) | 0x80;
+ }
+
+ bytesToRead = readToPtr - myReadPtr;
+ if(readToPtr < myReadPtr)
+ bytesToRead += RFID_DATA_ARRAY_SIZE;
+
+ bytesToRead &= 0xFFFE; //make LSB == 0
+
+ //if(bytesToRead > lastIndex * 2)
+ // goto fail;
+
+ for(i=0;i<bytesToRead;i+=2)
+ {
+ clocks1 = phid->dataBuffer[myReadPtr] & 0x7F;
+ polarity1 = (phid->dataBuffer[myReadPtr] & 0x80) ? 1 : 0;
+ clocks2 = phid->dataBuffer[(myReadPtr+1) & RFID_DATA_ARRAY_MASK] & 0x7F;
+ polarity2 = (phid->dataBuffer[(myReadPtr+1) & RFID_DATA_ARRAY_MASK] & 0x80) ? 1 : 0;
+
+ clocks = clocks1 + clocks2;
+
+ if(polarity1 != 1 || polarity2 != 0)
+ goto fail;
+
+ //the first pulse can be long
+ if (pdiff(clocks, shortClocks) < 0.2 || acWritePtr == 0)
+ {
+ if(acBitLocation == 1)
+ {
+ acBuffer[acWritePtr] = PTRUE;
+
+ acWritePtr++;
+ }
+ acBitLocation ^= 1;
+ }
+ else if(pdiff(clocks, longClocks) < 0.2)
+ {
+ if(acBitLocation == 1)
+ {
+ //Sometimes we get a too short ending pulse
+ if(acWritePtr == lastIndex && myReadPtr == ((readToPtr-1) & RFID_DATA_ARRAY_MASK))
+ {
+ acBuffer[acWritePtr] = PTRUE;
+ acWritePtr++;
+ }
+ else
+ goto fail;
+ }
+ else
+ {
+ if(pdiff(clocks1, clocks2) > 0.5)
+ acBuffer[acWritePtr] = PUNK_BOOL;
+ else
+ acBuffer[acWritePtr] = PFALSE;
+
+ acWritePtr++;
+
+ acBitLocation = 0;
+ }
+ }
+ else
+ goto fail;
+
+ if(acWritePtr > lastIndex)
+ goto fail;
+
+ myReadPtr+=2;
+ myReadPtr &= RFID_DATA_ARRAY_MASK;
+ }
+
+ //last low pulse won't be seen because we idle low
+ if(acWritePtr == lastIndex && myReadPtr == ((readToPtr-1) & RFID_DATA_ARRAY_MASK))
+ {
+ clocks = phid->dataBuffer[myReadPtr] & 0x7F;
+ polarity1 = (phid->dataBuffer[myReadPtr] & 0x80) ? 1 : 0;
+
+ if(polarity1 != 1)
+ goto fail;
+
+ if(pdiff(clocks, shortClocks/2) < 0.4)
+ {
+ if(acBitLocation==1)
+ {
+ acBuffer[acWritePtr] = PTRUE;
+ acWritePtr++;
+ }
+ //there should still be more data
+ else
+ acBitLocation ^= 1;
+ }
+ else if(pdiff(clocks, longClocks/2) < 0.3)
+ {
+ if(acBitLocation==1)
+ goto fail;
+
+ acBuffer[acWritePtr] = PFALSE;
+ acWritePtr++;
+ }
+ else if(pdiff(clocks, (longClocks/4)*3) < 0.25)
+ {
+ if(acBitLocation==1)
+ goto fail;
+
+ acBuffer[acWritePtr] = PUNK_BOOL;
+ acWritePtr++;
+ }
+ else
+ goto fail;
+ }
+ else
+ goto fail;
+
+ *acBufferSize = acWritePtr;
+ return EPHIDGET_OK;
+
+fail:
+ //printf("beep2\n");
+
+ acBitLocation = 0;
+
+ //This is not AC encoded data
+ return EPHIDGET_NOTFOUND;
+}
+
+//NOTE: tag is a local variable, we need to make a copy of it before adding it to lists, etc.
+static int advanced_tag_event(CPhidgetRFIDHandle phid, CPhidgetRFID_TagHandle tagPtr, int lock)
+{
+ CPhidgetRFID_TagHandle tag;
+ //Add to the tag list here, remove from the tag list in the tagTimerThreadFunction
+ if(lock)
+ CThread_mutex_lock(&phid->tagthreadlock);
+ if(CList_findInList((CListHandle)phid->tagAdvancedList, tagPtr, CPhidgetRFID_Tag_areEqual, (void**)&tag) == EPHIDGET_NOTFOUND)
+ {
+ //make a copy
+ tag = (CPhidgetRFID_TagHandle)malloc(sizeof(*tag));
+ memcpy(tag, tagPtr, sizeof(*tag));
+ tag->tagEventPending = PTRUE;
+ CThread_set_event(&phid->tagAvailableEvent);
+ CList_addToList((CListHandle *)&phid->tagAdvancedList, tag, CPhidgetRFID_Tag_areEqual);
+ }
+
+ setTimeNow(&tag->lastTagTime);
+ if(lock)
+ CThread_mutex_unlock(&phid->tagthreadlock);
+
+ return EPHIDGET_OK;
+}
+
+//Analyses streaming data in Manchester or Biphase coding
+static int analyze_data(CPhidgetRFIDHandle phid)
+{
+ int bytesToRead = 0, bytesRead = 0;
+ int temp, one, two;
+ int myReadPtr;
+ CPhidgetRFID_Tag tag;
+
+ //read till we have real data
+start:
+ while(phid->dataReadPtr != phid->dataWritePtr)
+ {
+ if(phid->dataBuffer[phid->dataReadPtr] == PUNK_INT)
+ {
+ phid->dataReadPtr++;
+ phid->dataReadPtr &= RFID_DATA_ARRAY_MASK;
+ phid->atGap = PTRUE;
+
+ phid->one = phid->two = phid->oneCount = phid->twoCount = 0;
+ }
+ else
+ break;
+ }
+ myReadPtr = phid->dataReadPtr;
+
+ //Make sure we have enough data to do something useful with..
+ bytesToRead = phid->dataWritePtr - phid->dataReadPtr;
+ if(phid->dataReadPtr > phid->dataWritePtr)
+ bytesToRead += RFID_DATA_ARRAY_SIZE;
+
+ if(bytesToRead < 32 && phid->atGap)
+ return EPHIDGET_OK;
+
+ //then read till we have a space or run out of data - figure out data rate
+ one = two = 0;
+ bytesRead = 0;
+ while(myReadPtr != phid->dataWritePtr)
+ {
+ if(phid->dataBuffer[myReadPtr] == PUNK_INT)
+ break;
+
+ if(phid->one == 0)
+ {
+ phid->one = phid->dataBuffer[myReadPtr] & 0x7F;
+ phid->oneCount++;
+ }
+ else
+ {
+ temp = round((double)((double)phid->one / (double)phid->oneCount));
+ if(pdiff(temp, phid->dataBuffer[myReadPtr] & 0x7F) < 0.3)
+ {
+ phid->one += phid->dataBuffer[myReadPtr] & 0x7F;
+ phid->oneCount++;
+ }
+ else
+ {
+ if(phid->two == 0)
+ {
+ temp = round((double)((double)phid->one / (double)phid->oneCount));
+ if(pdiff(temp * 2, phid->dataBuffer[myReadPtr] & 0x7F) < 0.3
+ || pdiff(temp / 2, phid->dataBuffer[myReadPtr] & 0x7F) < 0.3)
+ {
+ phid->two = phid->dataBuffer[myReadPtr] & 0x7F;
+ phid->twoCount++;
+ }
+ else
+ {
+ goto update_readPtr_restart;
+ }
+ }
+ else
+ {
+ temp = round((double)((double)phid->two / (double)phid->twoCount));
+ if(pdiff(temp, phid->dataBuffer[myReadPtr] & 0x7F) < 0.3)
+ {
+ phid->two += phid->dataBuffer[myReadPtr] & 0x7F;
+ phid->twoCount++;
+ }
+ else
+ {
+ goto update_readPtr_restart;
+ }
+ }
+ }
+ }
+
+ myReadPtr++;
+ myReadPtr &= RFID_DATA_ARRAY_MASK;
+ bytesRead++;
+ }
+
+ if(bytesRead < bytesToRead)
+ {
+ goto update_readPtr_restart;
+ }
+
+ //don't let the one and two counters get too big
+ if(phid->oneCount >= RFID_DATA_ARRAY_SIZE)
+ {
+ phid->one = round((double)((double)phid->one / 2.0));
+ phid->oneCount = phid->oneCount / 2;
+ }
+ if(phid->twoCount >= RFID_DATA_ARRAY_SIZE)
+ {
+ phid->two = round((double)((double)phid->two / 2.0));
+ phid->twoCount = phid->twoCount / 2;
+ }
+
+ if(phid->one)
+ one = round((double)((double)phid->one / (double)phid->oneCount));
+ if(phid->two)
+ two = round((double)((double)phid->two / (double)phid->twoCount));
+
+ //Order them by size
+ if(two < one)
+ {
+ temp = two;
+ two = one;
+ one = temp;
+ }
+
+ //printf("One: %3d Two: %3d Bytes: %4d\n",one, two, bytesToRead);
+
+ ZEROMEM(&tag, sizeof(CPhidgetRFID_Tag));
+ //Normalize the data rate we supply to the user to be a power of 2
+ //TODO: are there any tags which use a bitrate that's not a power of two?
+ //Yes - Q5 can have an arbitrary data rate
+ temp=1;
+ tag.tagInfo.bitRate = two;
+ while(temp<two)
+ {
+ temp*=2;
+ if(pdiff(temp, two) < 0.3)
+ {
+ tag.tagInfo.bitRate = temp;
+ break;
+ }
+ }
+ if(tag.tagInfo.bitRate == 128)
+ printf("hmm\n"); //TODO: are we actually going to do something about this?
+
+ //Shift data into Manchester and Biphase decoders, update read ptr
+ if(phid->hitagState == RFID_HITAG_STATE_SELECT
+ || phid->hitagState == RFID_HITAG_STATE_READ
+ || phid->hitagState == RFID_HITAG_STATE_WRITE)
+ {
+ if(phid->manReadPtr == phid->manWritePtr)
+ {
+ //may have to advance one to make things work
+ if(phid->dataBuffer[phid->dataReadPtr] & 0x80 && pdiff(phid->dataBuffer[phid->dataReadPtr] & 0x7F, 16) < 0.3)
+ phid->dataReadPtr = ((phid->dataReadPtr + 1) & RFID_DATA_ARRAY_MASK);
+ }
+ }
+ if(!add_manchester_data(phid, myReadPtr, one, two))
+ {
+ unsigned char manEventData[RFID_DATA_ARRAY_SIZE];
+ int manEventDataWritePtr = 0;
+
+ tag.tagInfo.encoding = PHIDGET_RFID_ENCODING_MANCHESTER;
+
+ //Manchester data event
+ while(phid->manEventReadPtr != phid->manWritePtr)
+ {
+ manEventData[manEventDataWritePtr++] = phid->manBuffer[phid->manEventReadPtr];
+ phid->manEventReadPtr++;
+ phid->manEventReadPtr&=RFID_DATA_ARRAY_MASK;
+ }
+ if(manEventDataWritePtr)
+ FIRE(ManchesterData, manEventData, manEventDataWritePtr);
+
+ if(phid->hitagState == RFID_HITAG_STATE_SELECT)
+ {
+ //try to decode a Hitag SELECT response
+ decodeHitagSelectResponse(phid, phid->manBuffer, &phid->manReadPtr, &phid->manWritePtr);
+ }
+ if(phid->hitagState == RFID_HITAG_STATE_READ)
+ {
+ //try to decode a Hitag READ response
+ decodeHitagReadResponse(phid, phid->manBuffer, &phid->manReadPtr, &phid->manWritePtr);
+ }
+ if(phid->hitagState == RFID_HITAG_STATE_WRITE)
+ {
+ //try to decode a Hitag WRITE response
+ decodeHitagACKResponse(phid, phid->manBuffer, &phid->manReadPtr, &phid->manWritePtr);
+ }
+ if(!decodeEM4102(phid, phid->manBuffer, &phid->manReadPtr, &phid->manWritePtr, &tag))
+ advanced_tag_event(phid, &tag, PTRUE);
+ if(!decodeISO11785(phid, phid->manBuffer, &phid->manReadPtr, &phid->manWritePtr, &tag))
+ advanced_tag_event(phid, &tag, PTRUE);
+ }
+ else
+ {
+ //Manchester event with space
+ unsigned char manEventData[1];
+ manEventData[0] = PUNK_BOOL;
+ phid->manEventReadPtr = phid->manWritePtr;
+
+ FIRE(ManchesterData, manEventData, 1);
+ }
+ if(!add_biphase_data(phid, myReadPtr, one, two))
+ {
+ tag.tagInfo.encoding = PHIDGET_RFID_ENCODING_BIPHASE;
+ if(!decodeEM4102(phid, phid->biphaseBuffer, &phid->biphaseReadPtr, &phid->biphaseWritePtr, &tag))
+ advanced_tag_event(phid, &tag, PTRUE);
+ if(!decodeISO11785(phid, phid->biphaseBuffer, &phid->biphaseReadPtr, &phid->biphaseWritePtr, &tag))
+ advanced_tag_event(phid, &tag, PTRUE);
+ }
+
+ //update read pointer
+ phid->dataReadPtr = myReadPtr;
+ phid->atGap = PFALSE;
+
+ return EPHIDGET_OK;
+
+ //ran into a bad pulse length or a gap - reset stuff
+update_readPtr_restart:
+ phid->one = phid->two = phid->oneCount = phid->twoCount = 0;
+ phid->dataReadPtr = myReadPtr;
+ phid->atGap = PTRUE;
+ phid->manReadPtr = 0;
+ phid->manEventReadPtr = 0;
+ phid->manWritePtr = 0;
+ phid->biphaseReadPtr = 0;
+ phid->biphaseWritePtr = 0;
+ goto start;
+}
+
+//Analyses data for Hitag AC coding
+static int analyze_data_AC(CPhidgetRFIDHandle phid)
+{
+ int bytesToRead = 0;
+ unsigned int myReadPtr;
+ CPhidgetRFID_Tag tag;
+ unsigned char acBuffer[64];
+ int acBufferSize = 64;
+
+ ZEROMEM(&tag, sizeof(CPhidgetRFID_Tag));
+
+ //read till we have real data
+ while(phid->dataReadACPtr != phid->dataWritePtr)
+ {
+ if(phid->dataBuffer[phid->dataReadACPtr] == PUNK_INT)
+ {
+ phid->dataReadACPtr++;
+ phid->dataReadACPtr &= RFID_DATA_ARRAY_MASK;
+ }
+ else
+ break;
+ }
+ myReadPtr = phid->dataReadACPtr;
+
+ if(phid->dataReadACPtr == phid->dataWritePtr)
+ return EPHIDGET_OK;
+
+ //read till we find the next gap
+ while(myReadPtr != phid->dataWritePtr)
+ {
+ if(phid->dataBuffer[myReadPtr] != PUNK_INT)
+ {
+ myReadPtr++;
+ myReadPtr &= RFID_DATA_ARRAY_MASK;
+ }
+ else
+ break;
+ }
+
+ if(myReadPtr == phid->dataWritePtr)
+ return EPHIDGET_OK;
+
+ //We should now have a set of data between two gaps
+
+ //Make sure we have enough data to do something useful with..
+ bytesToRead = myReadPtr - phid->dataReadACPtr;
+ if(phid->dataReadACPtr > myReadPtr)
+ bytesToRead += RFID_DATA_ARRAY_SIZE;
+
+ if(!decodeACdata(phid, acBuffer, &acBufferSize, myReadPtr, 32, 64))
+ {
+ int collision = -1;
+
+ phid->ACCodingOK = PFALSE;
+
+ //printf("%d ",phid->acWritePtr);
+ tag.tagInfo.encoding = PHIDGET_RFID_ENCODING_AC;
+ tag.tagInfo.bitRate = 64;
+ if(!decodeHitagUID(phid, acBuffer, acBufferSize, &tag, &collision))
+ {
+ advanced_tag_event(phid, &tag, PTRUE);
+ //TODO: select tag?
+ //printf("Got Hitag Tag: %s\n",tag.tagString);
+
+ //Any pending AC commands?
+ if(phid->hitagACList)
+ {
+ CPhidgetRFID_HitagACHandle ac = phid->hitagACList[0].hitagAC;
+ HitagS_AC_SEQUENCE(phid, ac);
+ CList_removeFromList((CListHandle *)&phid->hitagACList, ac, CPhidgetRFID_HitagAC_areEqual, PTRUE, CPhidgetRFID_HitagAC_free);
+ }
+ }
+ else if(collision != -1)
+ {
+ int k;
+ CPhidgetRFID_HitagACHandle ac = (CPhidgetRFID_HitagACHandle)malloc(sizeof(CPhidgetRFID_HitagAC));
+ ZEROMEM(ac, sizeof(CPhidgetRFID_HitagAC));
+ //printf("Got Hitag Collision: %d\n",collision);
+
+ for(k=0;k<collision;k++)
+ {
+ ac->uid[k/8] |= acBuffer[k+3] << (7-(k%8));
+ }
+ //choose 1 for the collision position
+ ac->uid[k/8] |= 1 << (7-(k%8));
+
+ ac->colPos = collision+1;
+
+ HitagS_AC_SEQUENCE(phid, ac);
+
+ //add AC with 0 to queue
+ ac->uid[k/8] &= ~(1 << (7-(k%8)));
+ CList_addToList((CListHandle *)&phid->hitagACList, ac, CPhidgetRFID_HitagAC_areEqual);
+ }
+ }
+
+ //update read pointer
+ phid->dataReadACPtr = myReadPtr;
+
+ return EPHIDGET_OK;
+}
+
+static int advancedTagEventForOldReaders(CPhidgetRFIDHandle phid, unsigned char *data)
+{
+ CPhidgetRFID_Tag tag;
+ ZEROMEM(&tag, sizeof(CPhidgetRFID_Tag));
+ tag.tagInfo.bitRate = 64;
+ tag.tagInfo.encoding = PHIDGET_RFID_ENCODING_MANCHESTER;
+ snprintf(tag.tagString, 255, "%02x%02x%02x%02x%02x",data[0],data[1],data[2],data[3],data[4]);
+ tag.tagInfo.tagType = PHIDGET_RFID_TAG_EM4102;
+ return advanced_tag_event(phid, &tag, PFALSE);
+}
+
+
+// === Exported Functions === //
+
+//create and initialize a device structure
+CCREATE_EXTRA(RFID, PHIDCLASS_RFID)
+ CThread_mutex_init(&phid->tagthreadlock);
+ CThread_create_event(&phid->tagAvailableEvent);
+ CThread_create_event(&phid->respEvent);
+ CThread_create_event(&phid->respEvent2);
+ phid->phid.fptrClose = CPhidgetRFID_close;
+ phid->phid.fptrFree = CPhidgetRFID_free;
+ return EPHIDGET_OK;
+}
+
+//event setup functions
+CFHANDLE(RFID, OutputChange, int, int)
+CFHANDLE(RFID, Tag, unsigned char *)
+CFHANDLE(RFID, TagLost, unsigned char *)
+CFHANDLE(RFID, ManchesterData, unsigned char *data, int dataLength)
+CFHANDLE(RFID, RawData, int *data, int dataLength)
+CFHANDLE(RFID, TagAdvanced, char *tagString, CPhidgetRFID_TagInfoHandle tagInfo)
+CFHANDLE(RFID, TagLostAdvanced, char *tagString, CPhidgetRFID_TagInfoHandle tagInfo)
+
+CGET(RFID,OutputCount,int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_RFID)
+ TESTATTACHED
+
+ MASGN(phid.attr.rfid.numOutputs)
+}
+
+CGETINDEX(RFID,OutputState,int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_RFID)
+ TESTATTACHED
+ TESTINDEX(phid.attr.rfid.numOutputs)
+ TESTMASGN(outputState[Index], PUNK_BOOL)
+
+ MASGN(outputState[Index])
+}
+CSETINDEX(RFID,OutputState,int)
+ TESTPTR(phid)
+ TESTDEVICETYPE(PHIDCLASS_RFID)
+ TESTATTACHED
+ TESTRANGE(PFALSE, PTRUE)
+ TESTINDEX(phid.attr.rfid.numOutputs)
+
+ if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
+ ADDNETWORKKEYINDEXED(Output, "%d", outputState);
+ else
+ {
+ SENDPACKET(RFID, outputState[Index]);
+ //echo back output state if the device doesn't
+ //do it here because this is after the packet has been sent off - so blocking in this event will not delay the output
+ if (!(phid->fullStateEcho))
+ {
+ if (phid->outputEchoState[Index] == PUNK_BOOL || phid->outputEchoState[Index] != newVal)
+ {
+ phid->outputEchoState[Index] = newVal;
+ FIRE(OutputChange, Index, newVal);
+ }
+ }
+ }
+
+ return EPHIDGET_OK;
+}
+
+CGET(RFID,AntennaOn,int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_RFID)
+ TESTATTACHED
+ TESTMASGN(antennaEchoState, PUNK_BOOL)
+
+ MASGN(antennaEchoState)
+}
+CSET(RFID,AntennaOn,int)
+ TESTPTR(phid)
+ TESTDEVICETYPE(PHIDCLASS_RFID)
+ TESTATTACHED
+
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_RFID_2OUTPUT:
+ TESTRANGE(PFALSE, PTRUE)
+
+ if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
+ ADDNETWORKKEY(AntennaOn, "%d", antennaState);
+ else
+ {
+ SENDPACKET(RFID, antennaState);
+ //echo back state if the device doesn't
+ if (!(phid->fullStateEcho))
+ phid->antennaEchoState = newVal;
+ }
+ return EPHIDGET_OK;
+ case PHIDID_RFID_2OUTPUT_ADVANCED:
+ if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
+ ADDNETWORKKEY(AntennaOn, "%d", antennaState);
+ else
+ {
+ unsigned char *buffer;
+ int ret = 0;
+ if(!(buffer = malloc(phid->phid.outputReportByteLength))) return EPHIDGET_NOMEMORY;
+ ZEROMEM(buffer, phid->phid.outputReportByteLength);
+ CThread_mutex_lock(&phid->phid.writelock);
+
+ phid->antennaState = newVal;
+ if(newVal)
+ {
+ phid->_4097Conf = RFID_4097_AmpDemod | RFID_4097_Active | RFID_4097_DataOut | RFID_4097_IntPLL | RFID_4097_FastStart | RFID_4097_Gain960;
+ //phid->_4097Conf = RFID_4097_AmpDemod | RFID_4097_Active | RFID_4097_DataOut | RFID_4097_IntPLL | RFID_4097_FastStart | RFID_4097_Gain120;
+ }
+ else
+ {
+ phid->_4097Conf = RFID_4097_PowerDown;
+ }
+
+ if((ret = CPhidgetRFID_makePacket(phid, buffer))) goto done2;
+ if((ret = CPhidgetRFID_sendpacket(phid, buffer))) goto done2;
+ done2:
+ CThread_mutex_unlock(&phid->phid.writelock);
+ free(buffer);
+ if(ret) return ret;
+ }
+ return EPHIDGET_OK;
+ case PHIDID_RFID:
+ default:
+ return EPHIDGET_UNSUPPORTED;
+ }
+}
+
+CGET(RFID,LEDOn,int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_RFID)
+ TESTATTACHED
+
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_RFID_2OUTPUT:
+ case PHIDID_RFID_2OUTPUT_ADVANCED:
+ TESTMASGN(ledEchoState, PUNK_BOOL)
+ MASGN(ledEchoState)
+ case PHIDID_RFID:
+ default:
+ return EPHIDGET_UNSUPPORTED;
+ }
+}
+CSET(RFID,LEDOn,int)
+ TESTPTR(phid)
+ TESTDEVICETYPE(PHIDCLASS_RFID)
+ TESTATTACHED
+
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_RFID_2OUTPUT:
+ case PHIDID_RFID_2OUTPUT_ADVANCED:
+ TESTRANGE(PFALSE, PTRUE)
+
+ if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
+ ADDNETWORKKEY(LEDOn, "%d", ledState);
+ else
+ {
+ SENDPACKET(RFID, ledState);
+ //echo back state if the device doesn't
+ if (!(phid->fullStateEcho))
+ phid->ledEchoState = newVal;
+ }
+ return EPHIDGET_OK;
+ case PHIDID_RFID:
+ default:
+ return EPHIDGET_UNSUPPORTED;
+ }
+}
+
+CSET(RFID,PollingOn,int)
+ TESTPTR(phid)
+ TESTDEVICETYPE(PHIDCLASS_RFID)
+ TESTATTACHED
+
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_RFID_2OUTPUT_ADVANCED:
+ phid->polling = newVal;
+ return EPHIDGET_OK;
+ case PHIDID_RFID_2OUTPUT:
+ case PHIDID_RFID:
+ default:
+ return EPHIDGET_UNSUPPORTED;
+ }
+}
+CGET(RFID, LastTag, unsigned char)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_RFID)
+ TESTATTACHED
+
+ //if it's all 0's - it's not yet available
+ if(!memcmp("\0\0\0\0\0", phid->lastTag, 5))
+ return EPHIDGET_UNKNOWNVAL;
+
+ memcpy(pVal, phid->lastTag, 5);
+
+ return EPHIDGET_OK;
+}
+
+CGET(RFID, TagStatus, int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_RFID)
+ TESTATTACHED
+
+ if(phid->tagPresent == PUNK_BOOL && phid->tagAdvancedCount == PUNK_INT)
+ {
+ *pVal = PUNK_BOOL;
+ return EPHIDGET_UNKNOWNVAL;
+ }
+
+ if(phid->tagPresent == PTRUE || (phid->tagAdvancedCount > 0 && phid->tagAdvancedCount != PUNK_INT))
+ *pVal = PTRUE;
+ else
+ *pVal = PFALSE;
+
+ return EPHIDGET_OK;
+}
+
+PHIDGET21_API int CCONV CPhidgetRFID_writeRaw(CPhidgetRFIDHandle phid, unsigned char *data, int bitlength, int pregap, int space, int postgap, int zero, int one)
+{
+ int retval;
+ TESTPTR(phid)
+ TESTDEVICETYPE(PHIDCLASS_RFID)
+ TESTATTACHED
+ if(pregap < (2) || pregap > (255)) return EPHIDGET_INVALIDARG;
+ if(space < (2) || space > (255)) return EPHIDGET_INVALIDARG;
+ if(postgap < (2) || postgap > (255)) return EPHIDGET_INVALIDARG;
+ if(zero < (5) || zero > (255)) return EPHIDGET_INVALIDARG;
+ if(one < (5) || one > (255)) return EPHIDGET_INVALIDARG;
+
+ if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
+ ;//ADDNETWORKKEYINDEXED(Acceleration, "%lE", motorAcceleration); //TODO
+ else
+ {
+ unsigned char *buffer;
+ int ret = 0;
+ if(!(buffer = malloc(phid->phid.outputReportByteLength))) return EPHIDGET_NOMEMORY;
+ ZEROMEM(buffer, phid->phid.outputReportByteLength);
+ CThread_mutex_lock(&phid->phid.writelock);
+
+ phid->pregapClocks = pregap;
+ phid->postgapClocks = postgap;
+ phid->spaceClocks = space;
+ phid->zeroClocks = zero;
+ phid->oneClocks = one;
+
+ //Send timing
+ if((ret = CPhidgetRFID_makePacket(phid, buffer))) goto done2;
+ if((ret = CPhidgetRFID_sendpacket(phid, buffer))) goto done2;
+
+ //send data
+ if((retval = sendRAWData(phid, data, bitlength))) goto done2;
+
+ done2:
+ CThread_mutex_unlock(&phid->phid.writelock);
+ free(buffer);
+ if(ret) return ret;
+ }
+
+ return EPHIDGET_OK;
+}
+
+PHIDGET21_API int CCONV CPhidgetRFID_getRawData(CPhidgetRFIDHandle phid, int *data, int *dataLength)
+{
+ int i;
+ TESTPTR(phid)
+ TESTDEVICETYPE(PHIDCLASS_RFID)
+ TESTATTACHED
+
+ //make sure length is even so we only send out data with starting space and ending pulse
+ if((*dataLength % 2) == 1)
+ (*dataLength)--;
+
+ for(i=0;i<*dataLength;i++)
+ {
+ if(phid->userReadPtr == phid->dataWritePtr)
+ break;
+
+ data[i] = phid->dataBuffer[phid->userReadPtr];
+ phid->userReadPtr = (phid->userReadPtr + 1) & RFID_DATA_ARRAY_MASK;
+ }
+
+ //make sure i is even so that we don't end with a pulse
+ if((i % 2) == 1)
+ {
+ //negate the pulse if we added it
+ i--;
+ phid->userReadPtr = (phid->userReadPtr - 1) & RFID_DATA_ARRAY_MASK;
+ }
+
+ *dataLength = i;
+
+ return EPHIDGET_OK;
+}
+
+PHIDGET21_API int CCONV CPhidgetRFID_getTagOptions(CPhidgetRFIDHandle phid, char *tagString, CPhidgetRFID_TagOptionsHandle options)
+{
+ int ret = EPHIDGET_OK, wait_return = 0;
+ CPhidgetRFID_TagList *trav = 0;
+ CPhidgetRFID_TagHandle tag = 0;
+ TESTPTRS(phid,tagString)
+ TESTPTR(options)
+ TESTDEVICETYPE(PHIDCLASS_RFID)
+ TESTATTACHED
+
+ //1st find it in the list - not there? can't get options.
+ CThread_mutex_lock(&phid->tagthreadlock);
+ for (trav=phid->tagAdvancedList; trav; trav = trav->next)
+ {
+ if(!strcmp(trav->tag->tagString, tagString))
+ tag = trav->tag;
+ }
+ if(!tag)
+ {
+ CThread_mutex_unlock(&phid->tagthreadlock);
+ return EPHIDGET_NOTFOUND;
+ }
+
+ //Do we need to poll for the options? yes for Hitag
+ if(!tag->tagOptionsValid)
+ {
+ switch(tag->tagInfo.tagType)
+ {
+ case PHIDGET_RFID_TAG_HITAGS:
+ CThread_mutex_unlock(&phid->tagthreadlock);
+
+ phid->respData = tag;
+ CThread_reset_event(&phid->respEvent);
+ HitagS_SELECT(phid, (unsigned char *)tagString);
+
+ wait_return = CThread_wait_on_event(&phid->respEvent, 500);
+ switch (wait_return) {
+ case WAIT_TIMEOUT:
+ ret = EPHIDGET_TIMEOUT;
+ break;
+ case WAIT_OBJECT_0:
+ ret = phid->respStatus;
+ break;
+ default:
+ ret = EPHIDGET_UNEXPECTED;
+ break;
+ }
+
+ CThread_reset_event(&phid->respEvent);
+
+ CThread_mutex_lock(&phid->tagthreadlock);
+ break;
+ case PHIDGET_RFID_TAG_ISO11784:
+ break;
+ case PHIDGET_RFID_TAG_EM4102:
+ break;
+ default:
+ CThread_mutex_unlock(&phid->tagthreadlock);
+ return EPHIDGET_UNEXPECTED;
+ }
+ }
+ //copy over options
+ memcpy(options, &tag->tagOptions, sizeof(CPhidgetRFID_TagOptions));
+
+ CThread_mutex_unlock(&phid->tagthreadlock);
+ return ret;
+}
+
+PHIDGET21_API int CCONV CPhidgetRFID_read(CPhidgetRFIDHandle phid, char *tagString, unsigned char *data, int *dataLength, char *password)
+{
+ int ret = EPHIDGET_OK, wait_return = 0, i;
+ CPhidgetRFID_TagList *trav = 0;
+ CPhidgetRFID_TagHandle tag = 0;
+ CPhidgetRFID_TagOptions options;
+ TESTPTRS(phid,tagString)
+ TESTPTR(data)
+ TESTDEVICETYPE(PHIDCLASS_RFID)
+ TESTATTACHED
+
+ //1st find it in the list - not there? can't get options.
+ CThread_mutex_lock(&phid->tagthreadlock);
+ for (trav=phid->tagAdvancedList; trav; trav = trav->next)
+ {
+ if(!strcmp(trav->tag->tagString, tagString))
+ tag = trav->tag;
+ }
+ if(!tag)
+ {
+ CThread_mutex_unlock(&phid->tagthreadlock);
+ return EPHIDGET_NOTFOUND;
+ }
+
+ switch(tag->tagInfo.tagType)
+ {
+ case PHIDGET_RFID_TAG_HITAGS:
+ if(tag->tagOptions.memSize == 32)
+ {
+ ret = EPHIDGET_UNSUPPORTED;
+ break;
+ }
+ //Do we need to select the tag first?
+ if(!tag->tagOptionsValid)
+ {
+ CThread_mutex_unlock(&phid->tagthreadlock);
+ if((ret = CPhidgetRFID_getTagOptions(phid, tagString, &options)))
+ return ret;
+ CThread_mutex_lock(&phid->tagthreadlock);
+ }
+
+ //Now do the reads
+ if(!tag->tagDataValid)
+ {
+ CThread_mutex_unlock(&phid->tagthreadlock);
+ phid->respData = tag;
+ CThread_reset_event(&phid->respEvent);
+ //reading blocks - 4 pages/block, 32 bits/page
+ for(i=0;i<tag->tagOptions.memSize/32;i+=4)
+ {
+ HitagS_READ(phid, i, PTRUE);
+
+ wait_return = CThread_wait_on_event(&phid->respEvent, 500);
+ switch (wait_return) {
+ case WAIT_TIMEOUT:
+ return EPHIDGET_TIMEOUT;
+ case WAIT_OBJECT_0:
+ if((ret = phid->respStatus))
+ return ret;
+ break;
+ default:
+ return EPHIDGET_UNEXPECTED;
+ }
+
+ CThread_reset_event(&phid->respEvent);
+ }
+
+ CThread_mutex_lock(&phid->tagthreadlock);
+ }
+ //copy over data - ignore 1st 8 bytes, it's UID and configuration
+ //TODO: if Authentication is turned on, we lose even more space
+ if(*dataLength > tag->tagOptions.memSize/8 - 8)
+ *dataLength = tag->tagOptions.memSize/8 - 8;
+ memcpy(data, tag->tagData + 8, *dataLength);
+
+ break;
+ case PHIDGET_RFID_TAG_ISO11784:
+ ret = EPHIDGET_UNSUPPORTED;
+ break;
+ case PHIDGET_RFID_TAG_EM4102:
+ ret = EPHIDGET_UNSUPPORTED;
+ break;
+ default:
+ ret = EPHIDGET_UNEXPECTED;
+ break;
+ }
+
+ CThread_mutex_unlock(&phid->tagthreadlock);
+ return ret;
+}
+
+PHIDGET21_API int CCONV CPhidgetRFID_write(CPhidgetRFIDHandle phid, char *tagString, unsigned char *data, int dataLength, int offset, char *password)
+{
+ int ret = EPHIDGET_OK, wait_return = 0, i, writePage, writeSize;
+ CPhidgetRFID_TagList *trav = 0;
+ CPhidgetRFID_TagHandle tag = 0;
+ CPhidgetRFID_TagOptions options;
+ unsigned char readData[256];
+ int readDataSize = 256;
+ TESTPTRS(phid,tagString)
+ TESTPTR(data)
+ TESTDEVICETYPE(PHIDCLASS_RFID)
+ TESTATTACHED
+
+ //1st find it in the list - not there? can't get options.
+ CThread_mutex_lock(&phid->tagthreadlock);
+ for (trav=phid->tagAdvancedList; trav; trav = trav->next)
+ {
+ if(!strcmp(trav->tag->tagString, tagString))
+ tag = trav->tag;
+ }
+ if(!tag)
+ {
+ CThread_mutex_unlock(&phid->tagthreadlock);
+ return EPHIDGET_NOTFOUND;
+ }
+
+ switch(tag->tagInfo.tagType)
+ {
+ case PHIDGET_RFID_TAG_HITAGS:
+
+ if(tag->tagOptions.memSize == 32)
+ {
+ ret = EPHIDGET_UNSUPPORTED;
+ break;
+ }
+ //Do we need to select the tag first?
+ if(!tag->tagOptionsValid)
+ {
+ CThread_mutex_unlock(&phid->tagthreadlock);
+ if((ret = CPhidgetRFID_getTagOptions(phid, tagString, &options)))
+ return ret;
+ CThread_mutex_lock(&phid->tagthreadlock);
+ }
+
+ if(offset+dataLength > (tag->tagOptions.memSize/8)-8)
+ return EPHIDGET_INVALIDARG;
+
+ //Need to read in the tag first
+ CThread_mutex_unlock(&phid->tagthreadlock);
+ if((ret = CPhidgetRFID_read(phid, tagString, readData, &readDataSize, password)))
+ return ret;
+ CThread_mutex_lock(&phid->tagthreadlock);
+
+ //Now do the writes
+ CThread_mutex_unlock(&phid->tagthreadlock);
+ phid->respData = tag;
+ CThread_reset_event(&phid->respEvent);
+
+ //need to start the write on a page border
+ //these are in pages (4 bytes)
+ writePage = offset/4;
+ writeSize = dataLength/4 + (dataLength%4 ? 1 : 0) + offset%4;
+
+ //replace what the user wants to write
+ memcpy(readData+offset, data, dataLength);
+
+ for(i=writePage;i<writePage+writeSize;i+=(i%4 ? i%4 : 4))
+ {
+ HitagS_WRITE(phid, i, readData+i, PTRUE);
+
+ wait_return = CThread_wait_on_event(&phid->respEvent, 500);
+ switch (wait_return) {
+ case WAIT_TIMEOUT:
+ return EPHIDGET_TIMEOUT;
+ case WAIT_OBJECT_0:
+ if((ret = phid->respStatus))
+ return ret;
+ break;
+ default:
+ return EPHIDGET_UNEXPECTED;
+ }
+
+ CThread_reset_event(&phid->respEvent);
+ }
+
+ CThread_mutex_lock(&phid->tagthreadlock);
+
+ break;
+ case PHIDGET_RFID_TAG_ISO11784:
+ ret = EPHIDGET_UNSUPPORTED;
+ break;
+ case PHIDGET_RFID_TAG_EM4102:
+ ret = EPHIDGET_UNSUPPORTED;
+ break;
+ default:
+ ret = EPHIDGET_UNEXPECTED;
+ break;
+ }
+
+ CThread_mutex_unlock(&phid->tagthreadlock);
+ return ret;
+}
+
+// === Deprecated Functions === //
+
+CGET(RFID,NumOutputs,int)
+ return CPhidgetRFID_getOutputCount(phid, pVal);
+}
diff --git a/cphidgetrfid.h b/cphidgetrfid.h
new file mode 100644
index 0000000..f056dd3
--- /dev/null
+++ b/cphidgetrfid.h
@@ -0,0 +1,331 @@
+#ifndef __CPHIDGETRFID
+#define __CPHIDGETRFID
+#include "cphidget.h"
+
+/** \defgroup phidrfid Phidget RFID
+ * \ingroup phidgets
+ * Calls specific to the Phidget RFID. See the product manual for more specific API details, supported functionality, units, etc.
+ * @{
+ */
+
+DPHANDLE(RFID)
+CHDRSTANDARD(RFID)
+
+/**
+ * Gets the number of outputs supported by this board.
+ * @param phid An attached phidget rfid handle.
+ * @param count The output count.
+ */
+CHDRGET(RFID,OutputCount,int *count)
+/**
+ * Gets the state of an output.
+ * @param phid An attached phidget rfid handle.
+ * @param index The output index.
+ * @param outputState The output state. Possible values are \ref PTRUE and \ref PFALSE.
+ */
+CHDRGETINDEX(RFID,OutputState,int *outputState)
+/**
+ * Sets the state of an output.
+ * @param phid An attached phidget rfid handle.
+ * @param index The output index.
+ * @param outputState The output state. Possible values are \ref PTRUE and \ref PFALSE.
+ */
+CHDRSETINDEX(RFID,OutputState,int outputState)
+/**
+ * Set an output change handler. This is called when an output changes.
+ * @param phid An attached phidget rfid handle.
+ * @param fptr Callback function pointer.
+ * @param userPtr A pointer for use by the user - this value is passed back into the callback function.
+ */
+CHDREVENTINDEX(RFID,OutputChange,int outputState)
+
+/**
+ * Gets the state of the antenna.
+ * @param phid An attached phidget rfid handle.
+ * @param antennaState The antenna state. Possible values are \ref PTRUE and \ref PFALSE.
+ */
+CHDRGET(RFID,AntennaOn,int *antennaState)
+/**
+ * Sets the state of the antenna. Note that the antenna must be enabled before tags will be read.
+ * @param phid An attached phidget rfid handle.
+ * @param antennaState The antenna state. Possible values are \ref PTRUE and \ref PFALSE.
+ */
+CHDRSET(RFID,AntennaOn,int antennaState)
+/**
+ * Gets the state of the onboard LED.
+ * @param phid An attached phidget rfid handle.
+ * @param LEDState The LED state. Possible values are \ref PTRUE and \ref PFALSE.
+ */
+CHDRGET(RFID,LEDOn,int *LEDState)
+/**
+ * Sets the state of the onboard LED.
+ * @param phid An attached phidget rfid handle.
+ * @param LEDState The LED state. Possible values are \ref PTRUE and \ref PFALSE.
+ */
+CHDRSET(RFID,LEDOn,int LEDState)
+
+/**
+ * Gets the last tag read by the reader. This tag may or may not still be on the reader.
+ * @param phid An attached phidget rfid handle.
+ * @param tag The tag. This must be an unsigned char array of size 5.
+ */
+CHDRGET(RFID,LastTag,unsigned char *tag)
+/**
+ * Gets the tag present status. This is whether or not a tag is being read by the reader.
+ * @param phid An attached phidget rfid handle.
+ * @param status The tag status. Possible values are \ref PTRUE and \ref PFALSE.
+ */
+CHDRGET(RFID,TagStatus,int *status)
+/**
+ * Set a tag handler. This is called when a tag is first detected by the reader.
+ * @param phid An attached phidget rfid handle.
+ * @param fptr Callback function pointer.
+ * @param userPtr A pointer for use by the user - this value is passed back into the callback function.
+ */
+CHDREVENT(RFID,Tag,unsigned char *tag)
+/**
+ * Set a tag lost handler. This is called when a tag is no longer detected by the reader.
+ * @param phid An attached phidget rfid handle.
+ * @param fptr Callback function pointer.
+ * @param userPtr A pointer for use by the user - this value is passed back into the callback function.
+ */
+CHDREVENT(RFID,TagLost,unsigned char *tag)
+
+#ifndef REMOVE_DEPRECATED
+DEP_CHDRGET("Deprecated - use CPhidgetRFID_getOutputCount",RFID,NumOutputs,int *)
+#endif
+
+//These are for a prototype device - hide until it's released
+#if !defined(EXTERNALPROTO) || defined(DEBUG)
+
+typedef enum {
+ PHIDGET_RFID_ENCODING_MANCHESTER = 1,
+ PHIDGET_RFID_ENCODING_BIPHASE,
+ PHIDGET_RFID_ENCODING_AC
+} CPhidgetRFID_Encoding;
+
+typedef enum {
+ PHIDGET_RFID_TAG_ISO11784 = 1,
+ PHIDGET_RFID_TAG_EM4102,
+ PHIDGET_RFID_TAG_HITAGS
+} CPhidgetRFID_TagType;
+
+typedef struct _CPhidgetRFID_TagInfo
+{
+ int bitRate;
+ CPhidgetRFID_TagType tagType;
+ CPhidgetRFID_Encoding encoding;
+} CPhidgetRFID_TagInfo, *CPhidgetRFID_TagInfoHandle;
+
+typedef struct _CPhidgetRFID_TagOptions
+{
+ unsigned char writable;
+ unsigned char encrypted;
+ int memSize;
+} CPhidgetRFID_TagOptions, *CPhidgetRFID_TagOptionsHandle;
+
+
+CHDRSET(RFID,PollingOn,int pollingState)
+
+PHIDGET21_API int CCONV CPhidgetRFID_writeRaw(CPhidgetRFIDHandle phid, unsigned char *data, int bitlength, int pregap, int space, int postgap, int zero, int one);
+PHIDGET21_API int CCONV CPhidgetRFID_getRawData(CPhidgetRFIDHandle phid, int *data, int *dataLength);
+
+PHIDGET21_API int CCONV CPhidgetRFID_getTagOptions(CPhidgetRFIDHandle phid, char *tagString, CPhidgetRFID_TagOptionsHandle options);
+PHIDGET21_API int CCONV CPhidgetRFID_read(CPhidgetRFIDHandle phid, char *tagString, unsigned char *data, int *dataLength, char *password);
+PHIDGET21_API int CCONV CPhidgetRFID_write(CPhidgetRFIDHandle phid, char *tagString, unsigned char *data, int dataLength, int offset, char *password);
+
+CHDREVENT(RFID, RawData, int *data, int dataLength)
+CHDREVENT(RFID, ManchesterData, unsigned char *data, int dataLength)
+CHDREVENT(RFID, TagAdvanced, char *tagString, CPhidgetRFID_TagInfoHandle tagInfo)
+CHDREVENT(RFID, TagLostAdvanced, char *tagString, CPhidgetRFID_TagInfoHandle tagInfo)
+
+#endif
+
+#ifndef EXTERNALPROTO
+
+#define RFID_PACKET_TAG 0
+#define RFID_PACKET_OUTPUT_ECHO 1
+
+#define RFID_LED_FLAG 0x04
+#define RFID_ANTENNA_FLAG 0x08
+
+//RFID Advanced Constants
+#define RFID_WRITE_DATA_OUT_PACKET 0x00
+#define RFID_CONTROL_OUT_PACKET 0x80
+
+#define RFID_READ_DATA_IN_PACKET 0x00
+#define RFID_ECHO_IN_PACKET 0x80
+
+//4097 constants
+#define RFID_4097_AmpDemod 0x00 //Amplitude demodulation
+#define RFID_4097_PhaseDemod 0x01 //Phase demodulation
+
+#define RFID_4097_PowerDown 0x00
+#define RFID_4097_Active 0x02
+
+#define RFID_4097_DataOut 0x00 //DATA_OUT is data from the rfid card
+#define RFID_4097_ClkOut 0x04 //DATA_OUT is the internal clock/32
+
+#define RFID_4097_IntPLL 0x00
+#define RFID_4097_ExtClk 0x08
+
+#define RFID_4097_FastStart 0x10
+
+#define RFID_4097_Gain960 0x40
+#define RFID_4097_Gain480 0x00
+#define RFID_4097_Gain240 0x60
+#define RFID_4097_Gain120 0x20
+
+#define RFID_4097_TestMode 0x80
+
+#define RFID_MAX_DATA_PER_PACKET 62
+
+#define RFID_DATA_ARRAY_SIZE 2048
+#define RFID_DATA_ARRAY_MASK 0x7ff
+
+#define RFID_MAXOUTPUTS 2
+
+typedef enum _CPhidgetRFID_Hitag_State
+{
+ RFID_HITAG_STATE_NONE = 0,
+ RFID_HITAG_STATE_UID_REQUEST,
+ RFID_HITAG_STATE_AC_SEQUENCE,
+ RFID_HITAG_STATE_SELECT,
+ RFID_HITAG_STATE_READ,
+ RFID_HITAG_STATE_WRITE
+
+} CPhidgetRFID_Hitag_State;
+
+typedef struct _CPhidgetRFID_Tag
+{
+ char tagString[256];
+ CPhidgetRFID_TagInfo tagInfo;
+ TIME lastTagTime;
+ unsigned char tagEventPending;
+ unsigned char tagOptionsValid;
+ CPhidgetRFID_TagOptions tagOptions;
+ unsigned char tagDataValid;
+ unsigned char tagData[256];
+} CPhidgetRFID_Tag, *CPhidgetRFID_TagHandle;
+
+typedef struct _CPhidgetRFID_TagList
+{
+ struct _CPhidgetRFID_TagList *next;
+ CPhidgetRFID_TagHandle tag;
+} CPhidgetRFID_TagList, *CPhidgetRFID_TagListHandle;
+
+typedef struct _CPhidgetRFID_HitagAC
+{
+ unsigned char uid[4];
+ int colPos;
+} CPhidgetRFID_HitagAC, *CPhidgetRFID_HitagACHandle;
+
+typedef struct _CPhidgetRFID_HitagACList
+{
+ struct _CPhidgetRFID_HitagACList *next;
+ CPhidgetRFID_HitagACHandle hitagAC;
+} CPhidgetRFID_HitagACList, *CPhidgetRFID_HitagACListHandle;
+
+struct _CPhidgetRFID {
+ CPhidget phid;
+
+ int (CCONV *fptrOutputChange)(CPhidgetRFIDHandle, void *, int, int);
+ int (CCONV *fptrTag)(CPhidgetRFIDHandle, void *, unsigned char *);
+ int (CCONV *fptrTagLost)(CPhidgetRFIDHandle, void *, unsigned char *);
+ int (CCONV *fptrRawData)(CPhidgetRFIDHandle, void *, int *, int);
+ int (CCONV *fptrManchesterData)(CPhidgetRFIDHandle, void *, unsigned char *, int);
+ int (CCONV *fptrTagAdvanced)(CPhidgetRFIDHandle, void *, char *, CPhidgetRFID_TagInfoHandle);
+ int (CCONV *fptrTagLostAdvanced)(CPhidgetRFIDHandle, void *, char *, CPhidgetRFID_TagInfoHandle);
+
+ void *fptrOutputChangeptr;
+ void *fptrTagptr;
+ void *fptrTagLostptr;
+ void *fptrRawDataptr;
+ void *fptrManchesterDataptr;
+ void *fptrTagAdvancedptr;
+ void *fptrTagLostAdvancedptr;
+
+ // Values returned from the device
+ unsigned char outputEchoState[RFID_MAXOUTPUTS];
+ unsigned char antennaEchoState;
+ unsigned char ledEchoState;
+
+ unsigned char outputState[RFID_MAXOUTPUTS];
+ unsigned char antennaState;
+ unsigned char ledState;
+
+ unsigned char lastTag[5];
+ unsigned char lastTagValid;
+ TIME lastTagTime;
+ unsigned char tagPresent;
+ //unsigned char tagEvent;
+ unsigned char pendingTag[5];
+ unsigned char tagEventPending;
+
+ EVENT tagAvailableEvent;
+
+ void *respData;
+ int respStatus;
+ EVENT respEvent;
+ EVENT respEvent2;
+
+ //Advanced Tag Events
+ int tagAdvancedCount;
+ CThread_mutex_t tagthreadlock; /* protects tag thread access to things */
+ CPhidgetRFID_TagListHandle tagAdvancedList;
+ CPhidgetRFID_Tag lastTagAdvanced;
+ TIME lastDataTime;
+ TIME hitagReqTime;
+
+ unsigned char ACCodingOK;
+
+ unsigned char fullStateEcho;
+
+ CThread tagTimerThread;
+
+ //RFID Advanced stuff
+ int spaceClocks, pregapClocks, postgapClocks, oneClocks, zeroClocks;
+ int spaceClocksEcho, pregapClocksEcho, postgapClocksEcho, oneClocksEcho, zeroClocksEcho;
+ int _4097Conf, _4097ConfEcho;
+ int frequencyEcho;
+
+ int dataBuffer[RFID_DATA_ARRAY_SIZE];
+ int dataBufferNormalized[RFID_DATA_ARRAY_SIZE];
+ unsigned int dataReadPtr, dataWritePtr, dataReadACPtr;
+ unsigned int userReadPtr; //for the getRawData function
+
+ unsigned char manBuffer[RFID_DATA_ARRAY_SIZE];
+ int manReadPtr, manWritePtr;
+
+ unsigned char biphaseBuffer[RFID_DATA_ARRAY_SIZE];
+ int biphaseReadPtr, biphaseWritePtr;
+
+ unsigned char manLockedIn;
+ unsigned char manShortChange;
+
+ unsigned char biphaseLockedIn;
+ unsigned char biphaseShortChange;
+
+ int one, two;
+ int oneCount, twoCount;
+
+ CPhidgetRFID_Hitag_State hitagState;
+ int hitagOffset;
+
+ //Hitag AC queue
+ CPhidgetRFID_HitagACListHandle hitagACList;
+ CPhidgetRFID_HitagAC lastHitagAC;
+
+ unsigned char atGap, polling;
+
+ unsigned char outputPacket[8];
+ unsigned int outputPacketLen;
+
+ int manEventReadPtr;
+
+} typedef CPhidgetRFIDInfo;
+#endif
+
+/** @} */
+
+#endif
diff --git a/cphidgetsbc.c b/cphidgetsbc.c
new file mode 100644
index 0000000..3b6b94f
--- /dev/null
+++ b/cphidgetsbc.c
@@ -0,0 +1,255 @@
+#include "stdafx.h"
+#include "cphidgetsbc.h"
+#include "cphidget.h"
+#include "cthread.h"
+#include "cphidgetlist.h"
+#include "csocket.h"
+#include "zeroconf.h"
+
+//PhidgetSBCManager
+
+//Private
+void CPhidgetSBCManager_free(void *arg)
+{
+ CPhidgetSBCManagerHandle sbcm = (CPhidgetSBCManagerHandle)arg;
+
+ if(!sbcm) return;
+ free(sbcm); sbcm = NULL;
+ return;
+}
+
+//Public
+int CCONV CPhidgetSBCManager_create(CPhidgetSBCManagerHandle *sbcm)
+{
+ CPhidgetSBCManagerHandle sbcmtemp = 0;
+
+ TESTPTR(sbcm)
+ if(!(sbcmtemp = (CPhidgetSBCManagerHandle)malloc(sizeof(CPhidgetSBCManager))))
+ return EPHIDGET_NOMEMORY;
+ ZEROMEM(sbcmtemp, sizeof(CPhidgetSBCManager));
+
+ *sbcm = sbcmtemp;
+ return EPHIDGET_OK;
+}
+
+int CCONV CPhidgetSBCManager_stop(CPhidgetSBCManagerHandle sbcm)
+{
+ TESTPTR(sbcm)
+
+ if(sbcm->state == PHIDGETMANAGER_ACTIVE)
+ {
+ sbcm->state = PHIDGETMANAGER_INACTIVE;
+ unregisterSBCManager(sbcm);
+ }
+
+ return EPHIDGET_OK;
+}
+
+int CCONV CPhidgetSBCManager_delete(CPhidgetSBCManagerHandle sbcm)
+{
+ CPhidgetSBCManager_free(sbcm);
+ return EPHIDGET_OK;
+}
+
+int CCONV CPhidgetSBCManager_set_OnAttach_Handler(CPhidgetSBCManagerHandle sbcm, int (CCONV *fptr)(CPhidgetSBCHandle sbc, void *userPtr), void *userPtr)
+{
+ TESTPTR(sbcm)
+ sbcm->fptrAttachChange = fptr;
+ sbcm->fptrAttachChangeptr = userPtr;
+ return EPHIDGET_OK;
+}
+
+int CCONV CPhidgetSBCManager_set_OnDetach_Handler(CPhidgetSBCManagerHandle sbcm, int (CCONV *fptr)(CPhidgetSBCHandle sbc, void *userPtr), void *userPtr)
+{
+ TESTPTR(sbcm)
+ sbcm->fptrDetachChange = fptr;
+ sbcm->fptrDetachChangeptr = userPtr;
+ return EPHIDGET_OK;
+}
+
+int CCONV CPhidgetSBCManager_set_OnError_Handler(CPhidgetSBCManagerHandle sbcm,
+ int(CCONV *fptr)(CPhidgetSBCManagerHandle, void *, int, const char *), void *userPtr)
+{
+ TESTPTR(sbcm)
+ sbcm->fptrError = fptr;
+ sbcm->fptrErrorptr = userPtr;
+ return EPHIDGET_OK;
+}
+
+int CCONV CPhidgetSBCManager_getAttachedSBCs(CPhidgetSBCManagerHandle sbcm, CPhidgetSBCHandle *sbcArray[], int *count)
+{
+ TESTPTRS(sbcArray, count)
+ TESTPTR(sbcm)
+
+ return EPHIDGET_UNSUPPORTED;
+}
+
+
+//PhidgetSBC
+
+//Private
+int CCONV CPhidgetSBC_areExtraEqual(void *arg1, void *arg2)
+{
+ CPhidgetSBCHandle sbc1 = (CPhidgetSBCHandle)arg1;
+ CPhidgetSBCHandle sbc2 = (CPhidgetSBCHandle)arg2;
+
+ TESTPTRS(sbc1, sbc2)
+
+ if(!strcmp(sbc1->mac, sbc2->mac)
+ && !strcmp(sbc1->fversion, sbc2->fversion)
+ && sbc1->hversion == sbc2->hversion
+ && !strcmp(sbc1->hostname?sbc1->hostname:"", sbc2->hostname?sbc2->hostname:""))
+ return PTRUE;
+ return PFALSE;
+}
+
+int CCONV CPhidgetSBC_areEqual(void *arg1, void *arg2)
+{
+ CPhidgetSBCHandle sbc1 = (CPhidgetSBCHandle)arg1;
+ CPhidgetSBCHandle sbc2 = (CPhidgetSBCHandle)arg2;
+
+ if(!sbc1 || !sbc2)
+ return PFALSE;
+
+ if(!strcmp(sbc1->mac, sbc2->mac))
+ return PTRUE;
+ return PFALSE;
+}
+
+void CCONV CPhidgetSBC_free(void *arg)
+{
+ CPhidgetSBCHandle sbc = (CPhidgetSBCHandle)arg;
+ if (!sbc)
+ return;
+
+ CPhidgetRemote_free(sbc->networkInfo);
+
+ free(sbc); sbc = NULL;
+ return;
+}
+
+//Public
+int CCONV CPhidgetSBC_create(CPhidgetSBCHandle *sbc)
+{
+ CPhidgetSBCHandle sbctemp = 0;
+
+ TESTPTR(sbc)
+ if(!(sbctemp = (CPhidgetSBCHandle)malloc(sizeof(CPhidgetSBC))))
+ return EPHIDGET_NOMEMORY;
+ ZEROMEM(sbctemp, sizeof(CPhidgetSBC));
+
+ // Version 1 doesn't support hostname variable
+ sbctemp->txtver = 1;
+
+ *sbc = sbctemp;
+ return EPHIDGET_OK;
+}
+
+int CCONV CPhidgetSBC_delete(CPhidgetSBCHandle sbc)
+{
+ CPhidgetSBC_free(sbc); sbc = NULL;
+ return EPHIDGET_OK;
+}
+
+int CCONV CPhidgetSBC_getFirmwareVersion(CPhidgetSBCHandle sbc, const char **version)
+{
+ TESTPTRS(sbc, version)
+
+ *version = (char *)sbc->fversion;
+ return EPHIDGET_OK;
+}
+
+int CCONV CPhidgetSBC_getHardwareVersion(CPhidgetSBCHandle sbc, int *version)
+{
+ TESTPTRS(sbc, version)
+
+ *version = sbc->hversion;
+ return EPHIDGET_OK;
+}
+
+int CCONV CPhidgetSBC_getMacAddress(CPhidgetSBCHandle sbc, const char **mac)
+{
+ TESTPTRS(sbc, mac)
+
+ *mac = (char *)sbc->mac;
+ return EPHIDGET_OK;
+}
+
+int CCONV CPhidgetSBC_getDeviceName(CPhidgetSBCHandle sbc, const char **name)
+{
+ TESTPTRS(sbc, name)
+
+ *name = (char *)sbc->deviceName;
+ return EPHIDGET_OK;
+}
+
+int CCONV CPhidgetSBC_getHostname(CPhidgetSBCHandle sbc, const char **hostname)
+{
+ TESTPTRS(sbc, hostname)
+
+#ifdef USE_ZEROCONF
+ if(sbc->txtver >= 2)
+ {
+ refreshZeroconfSBC(sbc);
+ *hostname = (char *)sbc->hostname;
+ return EPHIDGET_OK;
+ }
+ else
+#endif
+ {
+ *hostname = NULL;
+ return EPHIDGET_UNSUPPORTED;
+ }
+}
+
+int CCONV CPhidgetSBC_getAddress(CPhidgetSBCHandle sbc, const char **ipAddr)
+{
+ TESTPTRS(sbc, ipAddr)
+ if (!sbc->networkInfo)
+ return EPHIDGET_NETWORK_NOTCONNECTED;
+ if(!sbc->networkInfo->mdns) //not mdns
+ {
+ return EPHIDGET_UNEXPECTED;
+ }
+#ifdef USE_ZEROCONF
+ if(getZeroconfHostPort(sbc->networkInfo))
+ return EPHIDGET_NETWORK;
+ if(!sbc->networkInfo->zeroconf_host)
+ {
+ return EPHIDGET_NETWORK;
+ }
+ *ipAddr = (char *)sbc->networkInfo->zeroconf_host;
+ return EPHIDGET_OK;
+#else
+ return EPHIDGET_UNEXPECTED;
+#endif
+}
+
+int CCONV CPhidgetSBC_getIPAddressList(CPhidgetSBCHandle sbc, long *list, unsigned int *size)
+{
+ const char *addr;
+ struct hostent *addr_lookup;
+ CPhidgetSBC_getAddress(sbc, &addr);
+ /* this will resolve to an IP address, including .local hostnames (for SBC, because it can't resolve .local hostnames on its own) */
+#ifdef ZEROCONF_LOOKUP
+ addr_lookup = mdns_gethostbyname(addr);
+#else
+ addr_lookup = gethostbyname(addr);
+#endif
+ if (addr_lookup == NULL)
+ {
+ return EPHIDGET_UNKNOWNVAL;
+ }
+ else
+ {
+ unsigned int i = 0;
+ while ( addr_lookup -> h_addr_list[i] != NULL && i<*size) {
+ struct in_addr inaddr = *(( struct in_addr*)( addr_lookup -> h_addr_list[i]));
+ list[i] = inaddr.s_addr;
+ i++;
+ }
+ *size = i;
+ }
+
+ return EPHIDGET_OK;
+} \ No newline at end of file
diff --git a/cphidgetsbc.h b/cphidgetsbc.h
new file mode 100644
index 0000000..99f162e
--- /dev/null
+++ b/cphidgetsbc.h
@@ -0,0 +1,71 @@
+#ifndef __CPHIDGETSBC
+#define __CPHIDGETSBC
+#include "cphidget.h"
+#include "cphidgetmanager.h"
+
+DPHANDLE(SBC)
+DPHANDLE(SBCManager)
+
+#ifndef EXTERNALPROTO
+
+typedef struct _CPhidgetSBC
+{
+ CPhidgetRemoteHandle networkInfo;
+ int txtver;
+ char fversion[13];
+ short hversion;
+ char mac[18];
+ char hostname[129];
+ char deviceName[255];
+} CPhidgetSBC;
+
+typedef struct _CPhidgetSBCList
+{
+ struct _CPhidgetSBCList *next;
+ CPhidgetSBC *sbc;
+} CPhidgetSBCList, *CPhidgetSBCListHandle;
+
+typedef struct _CPhidgetSBCManager
+{
+ int mdns; //true if mdns, false if not
+ int(CCONV *fptrError)(CPhidgetSBCManagerHandle , void *, int, const char *);
+ void *fptrErrorptr;
+ CPhidgetManagerState state;
+ int (CCONV *fptrAttachChange)(CPhidgetSBCHandle sbc, void *userPtr);
+ void *fptrAttachChangeptr;
+ int (CCONV *fptrDetachChange)(CPhidgetSBCHandle sbc, void *userPtr);
+ void *fptrDetachChangeptr;
+} CPhidgetSBCManager;
+
+typedef struct _CPhidgetSBCManagerList
+{
+ struct _CPhidgetSBCManagerList *next;
+ CPhidgetSBCManager *sbcm;
+} CPhidgetSBCManagerList, *CPhidgetSBCManagerListHandle;
+
+int CCONV CPhidgetSBC_areEqual(void *arg1, void *arg2);
+int CCONV CPhidgetSBC_areExtraEqual(void *arg1, void *arg2);
+void CCONV CPhidgetSBC_free(void *arg);
+int CCONV CPhidgetSBC_create(CPhidgetSBCHandle *sbc);
+int CCONV CPhidgetSBC_delete(CPhidgetSBCHandle sbc);
+
+#endif
+
+PHIDGET21_API int CCONV CPhidgetSBCManager_create(CPhidgetSBCManagerHandle *sbcm);
+PHIDGET21_API int CCONV CPhidgetSBCManager_start(CPhidgetSBCManagerHandle sbcm);
+PHIDGET21_API int CCONV CPhidgetSBCManager_stop(CPhidgetSBCManagerHandle sbcm);
+PHIDGET21_API int CCONV CPhidgetSBCManager_delete(CPhidgetSBCManagerHandle sbcm);
+PHIDGET21_API int CCONV CPhidgetSBCManager_set_OnAttach_Handler(CPhidgetSBCManagerHandle sbcm, int (CCONV *fptr)(CPhidgetSBCHandle sbc, void *userPtr), void *userPtr);
+PHIDGET21_API int CCONV CPhidgetSBCManager_set_OnDetach_Handler(CPhidgetSBCManagerHandle sbcm, int (CCONV *fptr)(CPhidgetSBCHandle sbc, void *userPtr), void *userPtr);
+PHIDGET21_API int CCONV CPhidgetSBCManager_getAttachedSBCs(CPhidgetSBCManagerHandle sbcm, CPhidgetSBCHandle *sbcArray[], int *count);
+PHIDGET21_API int CCONV CPhidgetSBCManager_set_OnError_Handler(CPhidgetSBCManagerHandle sbcm, int(CCONV *fptr)(CPhidgetSBCManagerHandle sbcm, void *userPtr, int errorCode, const char *errorString), void *userPtr);
+
+PHIDGET21_API int CCONV CPhidgetSBC_getFirmwareVersion(CPhidgetSBCHandle sbc, const char **firmwareVersion);
+PHIDGET21_API int CCONV CPhidgetSBC_getHardwareVersion(CPhidgetSBCHandle sbc, int *hardwareVersion);
+PHIDGET21_API int CCONV CPhidgetSBC_getMacAddress(CPhidgetSBCHandle sbc, const char **macAddress);
+PHIDGET21_API int CCONV CPhidgetSBC_getAddress(CPhidgetSBCHandle sbc, const char **ipAddr);
+PHIDGET21_API int CCONV CPhidgetSBC_getHostname(CPhidgetSBCHandle sbc, const char **hostname);
+PHIDGET21_API int CCONV CPhidgetSBC_getDeviceName(CPhidgetSBCHandle sbc, const char **name);
+
+#endif
+
diff --git a/cphidgetservo.c b/cphidgetservo.c
new file mode 100644
index 0000000..f0c0fb8
--- /dev/null
+++ b/cphidgetservo.c
@@ -0,0 +1,541 @@
+#include "stdafx.h"
+#include "cphidgetservo.h"
+#include "cusb.h"
+#include "csocket.h"
+#include "cthread.h"
+
+// === Internal Functions === //
+
+//clearVars - sets all device variables to unknown state
+CPHIDGETCLEARVARS(Servo)
+ int i = 0;
+
+ phid->motorPositionMaxLimit = PUNI_DBL;
+ phid->motorPositionMinLimit = PUNI_DBL;
+ phid->fullStateEcho = PUNK_BOOL;
+
+ for (i = 0; i<SERVO_MAXSERVOS; i++)
+ {
+ phid->motorPositionMax[i] = PUNI_DBL;
+ phid->motorPositionMin[i] = PUNI_DBL;
+ phid->motorPosition[i] = PUNK_DBL;
+ phid->motorEngagedState[i] = PUNK_BOOL;
+ phid->motorPositionEcho[i] = PUNI_DBL;
+ phid->motorEngagedStateEcho[i] = PUNI_BOOL;
+ phid->servoParams[i].state = PUNI_BOOL;
+ }
+
+ return EPHIDGET_OK;
+}
+
+//initAfterOpen - sets up the initial state of an object, reading in packets from the device if needed
+// used during attach initialization - on every attach
+CPHIDGETINIT(Servo)
+ int i = 0;
+
+ TESTPTR(phid);
+
+ //Make sure no old writes are still pending
+ phid->outputPacketLen = 0;
+
+ //Setup max/min values
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_SERVO_1MOTOR:
+ case PHIDID_SERVO_4MOTOR:
+ if (phid->phid.deviceVersion == 200)
+ {
+ phid->motorPositionMaxLimit = 2550;
+ phid->motorPositionMinLimit = 1;
+ phid->fullStateEcho = PFALSE;
+ }
+ else if ((phid->phid.deviceVersion >= 300) && (phid->phid.deviceVersion < 313))
+ {
+ phid->motorPositionMaxLimit = 4095;
+ phid->motorPositionMinLimit = 1;
+ phid->fullStateEcho = PFALSE;
+ }
+ else if ((phid->phid.deviceVersion >= 313) && (phid->phid.deviceVersion < 400))
+ {
+ phid->motorPositionMaxLimit = 4095;
+ phid->motorPositionMinLimit = 1;
+ phid->fullStateEcho = PTRUE;
+ }
+ else
+ return EPHIDGET_BADVERSION;
+ break;
+ case PHIDID_SERVO_1MOTOR_OLD:
+ case PHIDID_SERVO_4MOTOR_OLD:
+ if (phid->phid.deviceVersion == 200)
+ {
+ phid->motorPositionMaxLimit = 2550;
+ phid->motorPositionMinLimit = 1;
+ phid->fullStateEcho = PFALSE;
+ }
+ else
+ return EPHIDGET_BADVERSION;
+ break;
+ default:
+ return EPHIDGET_UNEXPECTED;
+ }
+
+ for (i = 0; i<phid->phid.attr.servo.numMotors; i++)
+ {
+ //set data arrays to unknown
+ phid->motorPositionEcho[i] = PUNK_DBL;
+ phid->motorEngagedStateEcho[i] = PUNK_BOOL;
+ //init servo type and max/min
+ phid->servoParams[i] = Phid_Servo_Types[getServoParameterIndex(PHIDGET_SERVO_DEFAULT)];
+ if(phid->servoParams[i].max_us > phid->motorPositionMaxLimit)
+ phid->motorPositionMax[i] = phid->motorPositionMaxLimit;
+ else
+ phid->motorPositionMax[i] = phid->servoParams[i].max_us;
+ phid->motorPositionMin[i] = phid->servoParams[i].min_us;
+ }
+
+ //issue a read for devices that return output data
+ if(phid->fullStateEcho)
+ {
+ CPhidget_read((CPhidgetHandle)phid);
+ }
+
+ //recover what we can - if anything isn't filled out, it's PUNK anyways
+ for (i = 0; i<phid->phid.attr.servo.numMotors; i++)
+ {
+ phid->motorPosition[i] = phid->motorPositionEcho[i];
+ phid->motorEngagedState[i] = phid->motorEngagedStateEcho[i];
+ }
+
+ return EPHIDGET_OK;
+}
+
+//dataInput - parses device packets
+CPHIDGETDATA(Servo)
+ int i = 0;
+ double position[SERVO_MAXSERVOS];
+ double lastPosition[SERVO_MAXSERVOS];
+
+ if (length<0) return EPHIDGET_INVALIDARG;
+ TESTPTR(phid);
+ TESTPTR(buffer);
+
+ ZEROMEM(position, sizeof(position));
+ ZEROMEM(lastPosition, sizeof(lastPosition));
+
+ //Parse device packets - store data locally
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_SERVO_1MOTOR:
+ if ((phid->phid.deviceVersion >= 313) && (phid->phid.deviceVersion < 400))
+ {
+ position[0] = (((unsigned short)buffer[0]) << 5) + buffer[1];
+ }
+ else
+ return EPHIDGET_UNEXPECTED;
+ break;
+ case PHIDID_SERVO_4MOTOR:
+ if ((phid->phid.deviceVersion >= 313) && (phid->phid.deviceVersion < 400))
+ {
+ for (i = 0; i < phid->phid.attr.servo.numMotors; i++)
+ {
+ position[i] = (((unsigned short)buffer[i*2]) << 5) + buffer[(i*2) + 1];
+ }
+ }
+ else
+ return EPHIDGET_UNEXPECTED;
+ break;
+ case PHIDID_SERVO_1MOTOR_OLD:
+ case PHIDID_SERVO_4MOTOR_OLD:
+ return EPHIDGET_UNSUPPORTED;
+ default:
+ return EPHIDGET_UNEXPECTED;
+ }
+
+ //Make sure values are within defined range, and store to structure
+ for (i = 0; i < phid->phid.attr.servo.numMotors; i++)
+ {
+ lastPosition[i] = phid->motorPositionEcho[i];
+ if(position[i] > phid->motorPositionMaxLimit || position[i] < phid->motorPositionMinLimit)
+ {
+ if(position[i] == 0)
+ phid->motorEngagedStateEcho[i] = PFALSE;
+ else
+ phid->motorEngagedStateEcho[i] = PUNK_BOOL;
+ phid->motorPositionEcho[i] = PUNK_DBL;
+ }
+ else
+ {
+ phid->motorPositionEcho[i] = position[i];
+ phid->motorEngagedStateEcho[i] = PTRUE;
+ }
+ }
+
+ //send out any events for changed data
+ for (i = 0; i < phid->phid.attr.servo.numMotors; i++)
+ {
+ if(phid->motorPositionEcho[i] != PUNK_DBL && phid->motorPositionEcho[i] != lastPosition[i] && phid->motorEngagedStateEcho[i] == PTRUE)
+ {
+ FIRE(PositionChange, i, servo_us_to_degrees(phid->servoParams[i], phid->motorPositionEcho[i], PTRUE));
+ //Deprecated
+ FIRE(MotorPositionChange, i, servo_us_to_degrees(phid->servoParams[i], phid->motorPositionEcho[i], PTRUE));
+ }
+ }
+
+ return EPHIDGET_OK;
+}
+
+//eventsAfterOpen - sends out an event for all valid data, used during attach initialization
+CPHIDGETINITEVENTS(Servo)
+
+ for (i = 0; i < phid->phid.attr.servo.numMotors; i++)
+ {
+ if(phid->motorPositionEcho[i] != PUNK_DBL && phid->motorEngagedStateEcho[i] == PTRUE)
+ {
+ FIRE(PositionChange, i, servo_us_to_degrees(phid->servoParams[i], phid->motorPositionEcho[i], PTRUE));
+ //Deprecated
+ FIRE(MotorPositionChange, i, servo_us_to_degrees(phid->servoParams[i], phid->motorPositionEcho[i], PTRUE));
+ }
+ }
+
+ return EPHIDGET_OK;
+}
+
+//getPacket - used by write thread to get the next packet to send to device
+CGETPACKET_BUF(Servo)
+
+//sendpacket - sends a packet to the device asynchronously, blocking if the 1-packet queue is full
+CSENDPACKET_BUF(Servo)
+
+//makePacket - constructs a packet using current device state
+CMAKEPACKETINDEXED(Servo)
+ int i = 0;
+
+ TESTPTRS(phid, buffer);
+
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_SERVO_1MOTOR:
+ if (phid->phid.deviceVersion == 200) //this version may not exist in this product id
+ {
+ buffer[0] = 0;
+ if(phid->motorPosition[0] == PUNK_DBL || phid->motorEngagedState[0] == PFALSE)
+ buffer[1] = 0;
+ else
+ buffer[1] = (unsigned char)round(phid->motorPosition[Index] / 10.0);
+ }
+ else if ((phid->phid.deviceVersion >= 300) && (phid->phid.deviceVersion < 400))
+ {
+ int microsecondPulse = 0;
+
+ if(phid->motorPosition[0] == PUNK_DBL || phid->motorEngagedState[0] == PFALSE)
+ microsecondPulse = 0;
+ else
+ microsecondPulse = round(phid->motorPosition[0]);
+
+ buffer[0] = (unsigned char)(microsecondPulse & 0xFF);
+ buffer[1] = (unsigned char)(microsecondPulse >> 8);
+ }
+ else
+ return EPHIDGET_UNEXPECTED;
+ break;
+ case PHIDID_SERVO_4MOTOR:
+ if (phid->phid.deviceVersion == 200) //this version may not exist in this product id
+ {
+ if (Index == 0) buffer[0] = 2;
+ if (Index == 1) buffer[0] = 3;
+ if (Index == 2) buffer[0] = 0;
+ if (Index == 3) buffer[0] = 1;
+ if(phid->motorPosition[Index] == PUNK_DBL || phid->motorEngagedState[Index] == PFALSE)
+ buffer[1] = 0;
+ else
+ buffer[1] = (unsigned char)round(phid->motorPosition[Index]/10.0);
+ }
+ else if ((phid->phid.deviceVersion >= 300) && (phid->phid.deviceVersion < 400))
+ {
+ int microsecondPulse[4];
+
+ ZEROMEM(microsecondPulse, sizeof(microsecondPulse));
+
+ for (i = 0; i<phid->phid.attr.servo.numMotors; i++)
+ {
+ if(phid->motorPosition[i] == PUNK_DBL || phid->motorEngagedState[i] == PFALSE)
+ {
+ microsecondPulse[i] = 0;
+ phid->motorEngagedState[i] = PFALSE;
+ if (!(phid->fullStateEcho))
+ phid->motorEngagedStateEcho[i] = PFALSE;
+ }
+ else
+ {
+ microsecondPulse[i] = round(phid->motorPosition[i]);
+ phid->motorEngagedState[i] = PTRUE;
+ if (!(phid->fullStateEcho))
+ phid->motorEngagedStateEcho[i] = PTRUE;
+ }
+ }
+
+ buffer[0] = (unsigned char)(microsecondPulse[0] & 0xFF);
+ buffer[1] = (unsigned char)((microsecondPulse[0] >> 8) & 0x0F);
+
+ buffer[2] = (unsigned char)(microsecondPulse[1] & 0xFF);
+ buffer[1] |= (unsigned char)((microsecondPulse[1] >> 4) & 0xF0);
+
+ buffer[3] = (unsigned char)(microsecondPulse[2] & 0xFF);
+ buffer[4] = (unsigned char)((microsecondPulse[2] >> 8) & 0x0F);
+
+ buffer[5] = (unsigned char)(microsecondPulse[3] & 0xFF);
+ buffer[4] |= (unsigned char)((microsecondPulse[3] >> 4) & 0xF0);
+ }
+ else
+ return EPHIDGET_UNEXPECTED;
+ break;
+ case PHIDID_SERVO_1MOTOR_OLD:
+ if (phid->phid.deviceVersion == 200)
+ {
+ buffer[0] = 0;
+ if(phid->motorPosition[0] == PUNK_DBL || phid->motorEngagedState[0] == PFALSE)
+ buffer[1] = (unsigned char)0;
+ else
+ buffer[1] = (unsigned char)round(phid->motorPosition[Index]/10.0);
+ }
+ else
+ return EPHIDGET_UNEXPECTED;
+ break;
+ case PHIDID_SERVO_4MOTOR_OLD:
+ if (phid->phid.deviceVersion == 200)
+ {
+ if (Index == 0) buffer[0] = 2;
+ if (Index == 1) buffer[0] = 3;
+ if (Index == 2) buffer[0] = 0;
+ if (Index == 3) buffer[0] = 1;
+ if(phid->motorPosition[Index] == PUNK_DBL || phid->motorEngagedState[Index] == PFALSE)
+ buffer[1] = (unsigned char)0;
+ else
+ buffer[1] = (unsigned char)round(phid->motorPosition[Index]/10.0);
+ }
+ else
+ return EPHIDGET_UNEXPECTED;
+ break;
+ default:
+ return EPHIDGET_UNEXPECTED;
+ }
+
+ return EPHIDGET_OK;
+}
+
+// === Exported Functions === //
+
+//create and initialize a device structure
+CCREATE(Servo, PHIDCLASS_SERVO)
+
+//event setup functions
+CFHANDLE(Servo, PositionChange, int, double)
+
+CGET(Servo,MotorCount,int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_SERVO)
+ TESTATTACHED
+
+ MASGN(phid.attr.servo.numMotors)
+}
+
+CGETINDEX(Servo,Position,double)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_SERVO)
+ TESTATTACHED
+ TESTINDEX(phid.attr.servo.numMotors)
+ TESTMASGN(motorPositionEcho[Index], PUNK_DBL)
+
+ if(phid->motorEngagedStateEcho[Index] != PTRUE) {*pVal = PUNK_DBL; return EPHIDGET_UNKNOWNVAL;}
+
+ *pVal = servo_us_to_degrees(phid->servoParams[Index], phid->motorPositionEcho[Index], PTRUE);
+ return EPHIDGET_OK;
+}
+CSETINDEX(Servo,Position,double)
+ TESTPTR(phid)
+ TESTDEVICETYPE(PHIDCLASS_SERVO)
+ TESTATTACHED
+ TESTINDEX(phid.attr.servo.numMotors)
+ TESTRANGE(servo_us_to_degrees(phid->servoParams[Index], phid->motorPositionMin[Index], PFALSE),
+ servo_us_to_degrees(phid->servoParams[Index], phid->motorPositionMax[Index], PFALSE))
+
+ newVal = servo_degrees_to_us(phid->servoParams[Index], newVal);
+
+ //Note: setting a position will always engage a servo
+ if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
+ {
+ if(phid->motorEngagedState[Index] != PTRUE)
+ CPhidgetServo_setEngaged(phid, Index, PTRUE);
+ ADDNETWORKKEYINDEXED(Position, "%lE", motorPosition);
+ }
+ else
+ {
+ phid->motorEngagedState[Index] = PTRUE;
+ SENDPACKETINDEXED(Servo, motorPosition[Index], Index);
+ if (!(phid->fullStateEcho))
+ {
+ phid->motorEngagedStateEcho[Index] = PTRUE;
+ if (phid->motorPositionEcho[Index] == PUNK_BOOL || phid->motorPositionEcho[Index] != newVal)
+ {
+ phid->motorPositionEcho[Index] = newVal;
+ {
+ FIRE(PositionChange, Index, servo_us_to_degrees(phid->servoParams[Index], newVal, PTRUE));
+ //Deprecated
+ FIRE(MotorPositionChange, Index, servo_us_to_degrees(phid->servoParams[Index], newVal, PTRUE));
+ }
+ }
+ }
+ }
+
+ return EPHIDGET_OK;
+}
+
+CGETINDEX(Servo,PositionMax,double)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_SERVO)
+ TESTATTACHED
+ TESTINDEX(phid.attr.servo.numMotors)
+ TESTMASGN(motorPositionMax[Index], PUNK_DBL)
+
+ *pVal = servo_us_to_degrees(phid->servoParams[Index], phid->motorPositionMax[Index], PFALSE);
+ return EPHIDGET_OK;
+}
+
+CGETINDEX(Servo,PositionMin,double)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_SERVO)
+ TESTATTACHED
+ TESTINDEX(phid.attr.servo.numMotors)
+ TESTMASGN(motorPositionMin[Index], PUNK_DBL)
+
+ *pVal = servo_us_to_degrees(phid->servoParams[Index], phid->motorPositionMin[Index], PFALSE);
+ return EPHIDGET_OK;
+}
+
+CGETINDEX(Servo,Engaged,int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_SERVO)
+ TESTATTACHED
+ TESTINDEX(phid.attr.servo.numMotors)
+ TESTMASGN(motorEngagedStateEcho[Index], PUNK_BOOL)
+
+ MASGN(motorEngagedStateEcho[Index])
+}
+CSETINDEX(Servo,Engaged,int)
+ TESTPTR(phid)
+ TESTDEVICETYPE(PHIDCLASS_SERVO)
+ TESTATTACHED
+ TESTINDEX(phid.attr.servo.numMotors)
+ TESTRANGE(PFALSE, PTRUE)
+
+ if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
+ ADDNETWORKKEYINDEXED(Engaged, "%d", motorEngagedState);
+ else
+ SENDPACKETINDEXED(Servo, motorEngagedState[Index], Index);
+
+ return EPHIDGET_OK;
+}
+
+int setupNewServoParams(CPhidgetServoHandle phid, int Index, CPhidgetServoParameters params)
+{
+ char newVal[256];
+
+ //Only let raw us mode set the position to 0 - servo mode forces the use of engaged
+ if(params.servoType == PHIDGET_SERVO_RAW_us_MODE)
+ phid->motorPositionMinLimit = 0;
+ else
+ phid->motorPositionMinLimit = 1;
+
+ //Set the max/min
+ //make sure we don't set mac higher then the limit
+ if(params.max_us > phid->motorPositionMaxLimit)
+ phid->motorPositionMax[Index] = phid->motorPositionMaxLimit;
+ else
+ phid->motorPositionMax[Index] = params.max_us;
+
+ phid->motorPositionMin[Index] = params.min_us;
+
+ if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
+ {
+ //make sure webservice sends along motorPositionMinLimit which may have changed
+ sprintf(newVal, "%d,%lE,%lE,%lE", params.servoType, params.min_us, params.max_us, params.us_per_degree);
+ ADDNETWORKKEYINDEXED(ServoParameters, "%s", servoParamString);
+ }
+
+ phid->servoParams[Index] = params;
+
+ return EPHIDGET_OK;
+}
+
+CGETINDEX(Servo,ServoType,CPhidget_ServoType)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_SERVO)
+ TESTATTACHED
+ TESTINDEX(phid.attr.servo.numMotors)
+
+ MASGN(servoParams[Index].servoType)
+}
+
+CSETINDEX(Servo,ServoType,CPhidget_ServoType)
+ TESTPTR(phid)
+ TESTDEVICETYPE(PHIDCLASS_SERVO)
+ TESTATTACHED
+ TESTINDEX(phid.attr.servo.numMotors)
+ //can't set to User defined with this function
+ TESTRANGE(PHIDGET_SERVO_DEFAULT, PHIDGET_SERVO_USER_DEFINED-1)
+
+ setupNewServoParams(phid, Index, Phid_Servo_Types[getServoParameterIndex(newVal)]);
+
+ return EPHIDGET_OK;
+}
+
+PHIDGET21_API int CCONV CPhidgetServo_setServoParameters(CPhidgetServoHandle phid, int Index, double min_us, double max_us, double degrees)
+{
+ CPhidgetServoParameters params;
+ TESTPTR(phid)
+ TESTDEVICETYPE(PHIDCLASS_SERVO)
+ TESTATTACHED
+ TESTINDEX(phid.attr.servo.numMotors)
+
+ //Sanity checking of the values
+ if(min_us < phid->motorPositionMinLimit)
+ return EPHIDGET_INVALIDARG;
+ if(max_us > phid->motorPositionMaxLimit)
+ return EPHIDGET_INVALIDARG;
+ if(max_us <= min_us)
+ return EPHIDGET_INVALIDARG;
+ if(degrees <= 0 || degrees > 1440)
+ return EPHIDGET_INVALIDARG;
+
+ params.servoType = PHIDGET_SERVO_USER_DEFINED;
+ params.min_us = min_us;
+ params.max_us = max_us;
+ params.us_per_degree = (max_us - min_us)/degrees;
+
+ return setupNewServoParams(phid, Index, params);
+}
+
+// === Deprecated Functions === //
+
+CFHANDLE(Servo, MotorPositionChange, int, double)
+CGET(Servo,NumMotors,int)
+ return CPhidgetServo_getMotorCount(phid, pVal);
+}
+CGETINDEX(Servo,MotorPosition,double)
+ return CPhidgetServo_getPosition(phid, Index, pVal);
+}
+CSETINDEX(Servo,MotorPosition,double)
+ return CPhidgetServo_setPosition(phid, Index, newVal);
+}
+CGETINDEX(Servo,MotorPositionMax,double)
+ return CPhidgetServo_getPositionMax(phid, Index, pVal);
+}
+CGETINDEX(Servo,MotorPositionMin,double)
+ return CPhidgetServo_getPositionMin(phid, Index, pVal);
+}
+CGETINDEX(Servo,MotorOn,int)
+ return CPhidgetServo_getEngaged(phid, Index, pVal);
+}
+CSETINDEX(Servo,MotorOn,int)
+ return CPhidgetServo_setEngaged(phid, Index, newVal);
+}
diff --git a/cphidgetservo.h b/cphidgetservo.h
new file mode 100644
index 0000000..d0e9a97
--- /dev/null
+++ b/cphidgetservo.h
@@ -0,0 +1,142 @@
+#ifndef __CPHIDGETSERVO
+#define __CPHIDGETSERVO
+#include "cphidget.h"
+#include "cphidgetadvancedservo.h"
+
+/** \defgroup phidservo Phidget Servo
+ * \ingroup phidgets
+ * Calls specific to the Phidget Servo. See the product manual for more specific API details, supported functionality, units, etc.
+ * @{
+ */
+
+DPHANDLE(Servo)
+CHDRSTANDARD(Servo)
+
+/**
+ * Gets the number of motors supported by this controller.
+ * @param phid An attached phidget servo handle.
+ * @param count The motor count.
+ */
+CHDRGET(Servo,MotorCount,int *count)
+
+/**
+ * Gets the current position of a motor.
+ * @param phid An attached phidget servo handle.
+ * @param index The motor index.
+ * @param position The motor position.
+ */
+CHDRGETINDEX(Servo,Position,double *position)
+/**
+ * Sets the current position of a motor.
+ * @param phid An attached phidget servo handle.
+ * @param index The motor index.
+ * @param position The motor position.
+ */
+CHDRSETINDEX(Servo,Position,double position)
+/**
+ * Gets the maximum position that a motor can be set to.
+ * @param phid An attached phidget servo handle.
+ * @param index The motor index.
+ * @param max The maximum position.
+ */
+CHDRGETINDEX(Servo,PositionMax,double *max)
+/**
+ * Gets the minimum position that a motor can be set to.
+ * @param phid An attached phidget servo handle.
+ * @param index The motor index.
+ * @param min The minimum position.
+ */
+CHDRGETINDEX(Servo,PositionMin,double *min)
+/**
+ * Sets a position change event handler. This is called when the position changes.
+ * @param phid An attached phidget servo handle
+ * @param fptr Callback function pointer.
+ * @param userPtr A pointer for use by the user - this value is passed back into the callback function.
+ */
+CHDREVENTINDEX(Servo,PositionChange,double position)
+/**
+ * Gets the engaged state of a motor. This is whether the motor is powered or not.
+ * @param phid An attached phidget servo handle
+ * @param index The motor index.
+ * @param engagedState The engaged state. Possible values are \ref PTRUE and \ref PFALSE.
+ */
+CHDRGETINDEX(Servo,Engaged,int *engagedState)
+/**
+ * Sets the engaged state of a motor. This is whether the motor is powered or not.
+ * @param phid An attached phidget servo handle
+ * @param index The motor index.
+ * @param engagedState The engaged state. Possible values are \ref PTRUE and \ref PFALSE.
+ */
+CHDRSETINDEX(Servo,Engaged,int engagedState)
+/**
+ * Gets the servo type of a motor.
+ * @param phid An attached phidget advanced servo handle
+ * @param index The motor index.
+ * @param servoType The servo type.
+ */
+CHDRGETINDEX(Servo,ServoType,CPhidget_ServoType *servoType)
+/**
+ * Sets the servo type of a motor.
+ * @param phid An attached phidget advanced servo handle
+ * @param index The motor index.
+ * @param servoType The servo type.
+ */
+CHDRSETINDEX(Servo,ServoType,CPhidget_ServoType servoType)
+/**
+ * Sets the servo parameters of a motor.
+ * @param phid An attached phidget advanced servo handle
+ * @param index The motor index.
+ * @param min_us The minimum supported PCM in microseconds.
+ * @param max_us The maximum supported PCM in microseconds.
+ * @param degrees The degrees of rotation defined by the given PCM range.
+ */
+CHDRSETINDEX(Servo,ServoParameters,double min_us,double max_us,double degrees)
+
+#ifndef REMOVE_DEPRECATED
+DEP_CHDRGET("Deprecated - use CPhidgetServo_getMotorCount",Servo,NumMotors,int *)
+DEP_CHDRSETINDEX("Deprecated - use CPhidgetServo_setPosition",Servo,MotorPosition,double)
+DEP_CHDRGETINDEX("Deprecated - use CPhidgetServo_getPosition",Servo,MotorPosition,double *)
+DEP_CHDRGETINDEX("Deprecated - use CPhidgetServo_getPositionMax",Servo,MotorPositionMax,double *)
+DEP_CHDRGETINDEX("Deprecated - use CPhidgetServo_getPositionMin",Servo,MotorPositionMin,double *)
+DEP_CHDREVENTINDEX("Deprecated - use CPhidgetServo_set_OnPositionChange_Handler",Servo,MotorPositionChange,double motorPosition)
+DEP_CHDRSETINDEX("Deprecated - use CPhidgetServo_setEngaged",Servo,MotorOn,int)
+DEP_CHDRGETINDEX("Deprecated - use CPhidgetServo_getEngaged",Servo,MotorOn,int *)
+#endif
+
+#ifndef EXTERNALPROTO
+
+PHIDGET21_API int CCONV setupNewServoParams(CPhidgetServoHandle phid, int Index, CPhidgetServoParameters params);
+
+#define SERVO_MAXSERVOS 4
+struct _CPhidgetServo {
+ CPhidget phid;
+
+ int (CCONV *fptrPositionChange)(CPhidgetServoHandle, void *, int, double);
+ void *fptrPositionChangeptr;
+
+ //Deprecated
+ int (CCONV *fptrMotorPositionChange)(CPhidgetServoHandle, void *, int, double);
+ void *fptrMotorPositionChangeptr;
+
+ double motorPositionEcho[SERVO_MAXSERVOS];
+ unsigned char motorEngagedStateEcho[SERVO_MAXSERVOS];
+
+ double motorPosition[SERVO_MAXSERVOS];
+ unsigned char motorEngagedState[SERVO_MAXSERVOS];
+
+ unsigned char fullStateEcho;
+
+ double motorPositionMax[SERVO_MAXSERVOS], motorPositionMin[SERVO_MAXSERVOS];
+ double motorPositionMaxLimit, motorPositionMinLimit;
+
+ CPhidgetServoParameters servoParams[ADVSERVO_MAXSERVOS];
+ char *servoParamString[ADVSERVO_MAXSERVOS];
+
+ unsigned char outputPacket[8];
+ unsigned int outputPacketLen;
+} typedef CPhidgetServoInfo;
+#endif
+
+/** @} */
+
+#endif
diff --git a/cphidgetspatial.c b/cphidgetspatial.c
new file mode 100644
index 0000000..41a8048
--- /dev/null
+++ b/cphidgetspatial.c
@@ -0,0 +1,1382 @@
+#include "stdafx.h"
+#include "cphidgetspatial.h"
+#include "cusb.h"
+#include "math.h"
+#include "csocket.h"
+#include "cthread.h"
+
+// === Internal Functions === //
+static double getCorrectedField(CPhidgetSpatialHandle phid, double fields[], int axis);
+
+//clearVars - sets all device variables to unknown state
+CPHIDGETCLEARVARS(Spatial)
+ int i = 0;
+
+ phid->dataRateMin = PUNI_INT;
+ phid->dataRate = PUNI_INT;
+ phid->dataRateMax = PUNI_INT;
+
+ phid->accelerationMax = PUNI_DBL;
+ phid->accelerationMin = PUNI_DBL;
+ phid->angularRateMax = PUNI_DBL;
+ phid->angularRateMin = PUNI_DBL;
+ phid->magneticFieldMax = PUNI_DBL;
+ phid->magneticFieldMin = PUNI_DBL;
+ phid->interruptRate = PUNI_INT;
+
+ phid->spatialDataNetwork = PUNI_BOOL;
+
+ for (i = 0; i<SPATIAL_MAX_ACCELAXES; i++)
+ {
+ phid->accelAxis[i] = PUNI_DBL;
+ }
+ for (i = 0; i<SPATIAL_MAX_GYROAXES; i++)
+ {
+ phid->gyroAxis[i] = PUNI_DBL;
+ }
+ for (i = 0; i<SPATIAL_MAX_COMPASSAXES; i++)
+ {
+ phid->compassAxis[i] = PUNI_DBL;
+ }
+ return EPHIDGET_OK;
+}
+
+//initAfterOpen - sets up the initial state of an object, reading in packets from the device if needed
+// used during attach initialization - on every attach
+CPHIDGETINIT(Spatial)
+ int i = 0;
+
+ TESTPTR(phid);
+
+ //Setup max/min values
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_SPATIAL_ACCEL_3AXIS:
+ if (phid->phid.deviceVersion < 200)
+ {
+ phid->accelerationMax = 5.1;
+ phid->accelerationMin = -5.1;
+ phid->interruptRate = 8;
+ phid->dataRateMin = SPATIAL_MIN_DATA_RATE;
+ phid->dataRate = phid->interruptRate;
+ phid->dataRateMax = 1; //actual data rate
+ phid->angularRateMax = 0;
+ phid->angularRateMin = 0;
+ phid->magneticFieldMax = 0;
+ phid->magneticFieldMin = 0;
+ phid->calDataValid = PFALSE;
+ }
+ else
+ return EPHIDGET_BADVERSION;
+ break;
+ case PHIDID_SPATIAL_ACCEL_GYRO_COMPASS:
+ if (phid->phid.deviceVersion < 300)
+ {
+ phid->accelerationMax = 5.1;
+ phid->accelerationMin = -5.1;
+ phid->interruptRate = 8;
+ phid->dataRateMin = SPATIAL_MIN_DATA_RATE;
+ phid->dataRate = phid->interruptRate;
+ phid->dataRateMax = 4; //actual data rate
+ phid->angularRateMax = 400.1;
+ phid->angularRateMin = -400.1;
+ phid->magneticFieldMax = 4.1;
+ phid->magneticFieldMin = -4.1;
+ phid->userMagField = 1.0;
+ phid->calDataValid = PFALSE;
+ }
+ // 1042 (Digital 3/3/3)
+ else if (phid->phid.deviceVersion >= 300 && phid->phid.deviceVersion < 400)
+ {
+ phid->accelerationMax = 5.1;
+ phid->accelerationMin = -5.1;
+ phid->interruptRate = 8;
+ phid->dataRateMin = SPATIAL_MIN_DATA_RATE;
+ phid->dataRate = phid->interruptRate;
+ phid->dataRateMax = 4; //actual data rate
+ phid->angularRateMax = 400.1;
+ phid->angularRateMin = -400.1;
+ phid->magneticFieldMax = 4.1;
+ phid->magneticFieldMin = -4.1;
+ phid->userMagField = 1.0;
+ phid->calDataValid = PFALSE;
+ }
+ // 1044 (1056 Replacement)
+ else if (phid->phid.deviceVersion >= 400 && phid->phid.deviceVersion < 500)
+ {
+ phid->accelerationMax = 5.1;
+ phid->accelerationMin = -5.1;
+ phid->interruptRate = 4;
+ phid->dataRateMin = SPATIAL_MIN_DATA_RATE;
+ phid->dataRate = 8;//phid->interruptRate;
+ phid->dataRateMax = 4; //actual data rate
+ phid->angularRateMax = 400.1;
+ phid->angularRateMin = -400.1;
+ phid->magneticFieldMax = 10.1;
+ phid->magneticFieldMin = -10.1;
+ phid->userMagField = 1.0;
+ phid->calDataValid = PFALSE;
+ }
+ else
+ return EPHIDGET_BADVERSION;
+ break;
+ default:
+ return EPHIDGET_UNEXPECTED;
+ }
+
+ //initialize triggers, set data arrays to unknown
+ for (i = 0; i<phid->phid.attr.spatial.numAccelAxes; i++)
+ {
+ phid->accelAxis[i] = PUNK_DBL;
+ phid->accelGain1[i] = PUNK_DBL;
+ phid->accelGain2[i] = PUNK_DBL;
+ phid->accelOffset[i] = PUNK_INT;
+ }
+ for (i = 0; i<phid->phid.attr.spatial.numGyroAxes; i++)
+ {
+ phid->gyroAxis[i] = PUNK_DBL;
+ phid->gryoCorrection[i] = 0;
+ phid->gyroGain1[i] = PUNK_DBL;
+ phid->gyroGain2[i] = PUNK_DBL;
+ phid->gyroOffset[i] = PUNK_INT;
+ }
+ for (i = 0; i<phid->phid.attr.spatial.numCompassAxes; i++)
+ {
+ phid->compassAxis[i] = PUNK_DBL;
+ phid->userCompassGain[i] = 1.0;
+ }
+ phid->bufferReadPtr = 0;
+ phid->bufferWritePtr = 0;
+ phid->timestamp.seconds = 0;
+ phid->timestamp.microseconds = 0;
+ phid->lastEventTime.seconds = 0;
+ phid->lastEventTime.microseconds = 0;
+ phid->latestDataTime.seconds = 0;
+ phid->latestDataTime.microseconds = 0;
+
+ phid->lastTimeCounterValid = PFALSE;
+ phid->doZeroGyro = PFALSE;
+
+ //get calibration values
+ switch(phid->phid.deviceIDSpec) {
+ case PHIDID_SPATIAL_ACCEL_3AXIS:
+ // 1041, 1043 - no streamed calibration values
+ if (phid->phid.deviceVersion >= 200)
+ break;
+ case PHIDID_SPATIAL_ACCEL_GYRO_COMPASS:
+ // 1042, 1044 - no streamed calibration values
+ if (phid->phid.deviceVersion >= 300)
+ break;
+ else
+ {
+ unsigned char buffer[8] = { 0 };
+ int result;
+ int readCount = 125; // up to 1 second of data - should be PLENTY
+ //ask for calibration values
+ buffer[0] = SPATIAL_READCALIB;
+ if ((result = CUSBSendPacket((CPhidgetHandle)phid, buffer)) != EPHIDGET_OK)
+ return result;
+ while(phid->calDataValid == PFALSE && readCount--)
+ {
+ //note that Windows queues up to 32 packets, so we need to read at least this many to get the calibration packet
+ CPhidget_read((CPhidgetHandle)phid);
+ }
+ if(!phid->calDataValid)
+ return EPHIDGET_UNEXPECTED;
+ }
+ break;
+ default:
+ break;
+ }
+
+ //issue one read
+ //this should fill in the data because the dataRate is the interrupt rate
+ CPhidget_read((CPhidgetHandle)phid);
+
+ return EPHIDGET_OK;
+}
+
+//dataInput - parses device packets
+CPHIDGETDATA(Spatial)
+ int i = 0, j = 0, count = 0, dataRate = phid->dataRate, cal;
+ unsigned char doneGyroZero = PFALSE;
+ double accelAvg[SPATIAL_MAX_ACCELAXES], angularRateAvg[SPATIAL_MAX_ACCELAXES], magneticFieldAvg[SPATIAL_MAX_ACCELAXES], magneticFieldCorr[SPATIAL_MAX_ACCELAXES];
+ CPhidgetSpatial_SpatialEventDataHandle *eventData;
+
+ ZEROMEM(accelAvg, sizeof(accelAvg));
+ ZEROMEM(angularRateAvg, sizeof(angularRateAvg));
+ ZEROMEM(magneticFieldAvg, sizeof(magneticFieldAvg));
+
+ if (length<0) return EPHIDGET_INVALIDARG;
+ TESTPTR(phid);
+ TESTPTR(buffer);
+
+ //Parse device packets - store data locally
+ switch(phidG->deviceIDSpec)
+ {
+ case PHIDID_SPATIAL_ACCEL_3AXIS:
+ if (phid->phid.deviceVersion < 200)
+ {
+ int data;
+ double accelUncalib[3] = {0,0,0};
+ int time;
+
+ //top 2 bits in buffer[0] are packet type
+ switch(buffer[0] & 0xc0)
+ {
+ case SPATIAL_PACKET_DATA:
+ if(phid->calDataValid)
+ {
+ count = buffer[0] / 3;
+ if(count == 0)
+ goto done;
+
+ //this timestamp is for the latest data
+ time = ((unsigned short)buffer[1]<<8) + (unsigned short)buffer[2];
+ if(phid->lastTimeCounterValid)
+ {
+ //0-255 ms
+ int timechange = (unsigned short)((unsigned short)time - (unsigned short)phid->lastTimeCounter);
+ timechange *= 1000; //us
+
+ phid->timestamp.seconds = phid->timestamp.seconds + (phid->timestamp.microseconds + timechange) / 1000000;
+ phid->timestamp.microseconds = (phid->timestamp.microseconds + timechange) % 1000000;
+ }
+ else
+ {
+ phid->lastTimeCounterValid = PTRUE;
+ }
+ phid->lastTimeCounter = time;
+
+ //add data to data buffer
+ for(i=0;i<count;i++)
+ {
+ //LIS344ALH - Vdd/15 V/g - 0x1fff/15 = 0x222 (546.06666666666666666666666666667)
+ for(j=0;j<3;j++)
+ {
+ data = ((unsigned short)buffer[3 + j * 2 + i * 6]<<8) + (unsigned short)buffer[4 + j * 2 + i * 6];
+ accelUncalib[j] = ((double)data - 0x0fff) / 546.066667;
+ }
+ accelUncalib[1] = -accelUncalib[1]; //reverse Y-axis
+ //Apply offsets
+ for(j=0;j<3;j++)
+ {
+ accelUncalib[j] -= phid->accelOffset[j];
+ }
+ //X
+ if(accelUncalib[0] > 0)
+ phid->dataBuffer[phid->bufferWritePtr].acceleration[0] = accelUncalib[0] * phid->accelGain1[0] + accelUncalib[1] * phid->accelFactor1[0] + accelUncalib[2] * phid->accelFactor2[0];
+ else
+ phid->dataBuffer[phid->bufferWritePtr].acceleration[0] = accelUncalib[0] * phid->accelGain2[0] + accelUncalib[1] * phid->accelFactor1[0] + accelUncalib[2] * phid->accelFactor2[0];
+ //Y
+ if(accelUncalib[1] > 0)
+ phid->dataBuffer[phid->bufferWritePtr].acceleration[1] = accelUncalib[1] * phid->accelGain1[1] + accelUncalib[0] * phid->accelFactor1[1] + accelUncalib[2] * phid->accelFactor2[1];
+ else
+ phid->dataBuffer[phid->bufferWritePtr].acceleration[1] = accelUncalib[1] * phid->accelGain2[1] + accelUncalib[0] * phid->accelFactor1[1] + accelUncalib[2] * phid->accelFactor2[1];
+ //Z
+ if(accelUncalib[2] > 0)
+ phid->dataBuffer[phid->bufferWritePtr].acceleration[2] = accelUncalib[2] * phid->accelGain1[2] + accelUncalib[0] * phid->accelFactor1[2] + accelUncalib[1] * phid->accelFactor2[2];
+ else
+ phid->dataBuffer[phid->bufferWritePtr].acceleration[2] = accelUncalib[2] * phid->accelGain2[2] + accelUncalib[0] * phid->accelFactor1[2] + accelUncalib[1] * phid->accelFactor2[2];
+
+
+ phid->latestDataTime.seconds = phid->timestamp.seconds + (phid->timestamp.microseconds + (i + 1) * phid->dataRateMax * 1000) / 1000000;
+ phid->latestDataTime.microseconds = (phid->timestamp.microseconds + (i + 1) * phid->dataRateMax * 1000) % 1000000;
+
+ phid->dataBuffer[phid->bufferWritePtr].timestamp = phid->latestDataTime;
+
+ phid->bufferWritePtr++;
+ if(phid->bufferWritePtr >= SPATIAL_DATA_BUFFER_SIZE)
+ phid->bufferWritePtr = 0;
+ }
+ }
+ break;
+ case SPATIAL_PACKET_CALIB:
+ for (i = 0; i<phid->phid.attr.spatial.numAccelAxes; i++)
+ {
+ cal = ((unsigned short)buffer[i*7 + 1]<<4) + ((unsigned short)buffer[i*7 + 2]>>4);
+ phid->accelGain1[i] = cal / (4096/0.4) + 0.8;
+ cal = (((unsigned short)buffer[i*7 + 2]<<8) & 0x0F00) | ((unsigned short)buffer[i*7 + 3]);
+ phid->accelGain2[i] = cal / (4096/0.4) + 0.8;
+ cal = (unsigned short)((unsigned short)buffer[i*7 + 4]<<8) + (unsigned short)buffer[i*7 + 5];
+ phid->accelOffset[i] = cal / (65535 / 1.0) - 0.5;
+ cal = (unsigned char)buffer[i*7 + 6];
+ phid->accelFactor1[i] = cal / (256 / 0.2) - 0.1;
+ cal = (unsigned char)buffer[i*7 + 7];
+ phid->accelFactor2[i] = cal / (256 / 0.2) - 0.1;
+ //LOG(PHIDGET_LOG_INFO, "Accel(%d) Calib: %1.4lf, %1.4lf, %1.4lf, %1.4lf, %1.4lf", i,
+ // phid->accelGain1[i], phid->accelGain2[i], phid->accelOffset[i], phid->accelFactor1[i], phid->accelFactor2[i]);
+ }
+ phid->calDataValid = PTRUE;
+ break;
+ }
+ }
+ else
+ return EPHIDGET_UNEXPECTED;
+ break;
+ case PHIDID_SPATIAL_ACCEL_GYRO_COMPASS:
+ if (phidG->deviceVersion < 300)
+ {
+ //top 2 bits in buffer[0] are packet type
+ switch(buffer[0])
+ {
+ case SPATIAL_PACKET_DATA:
+ if(phid->calDataValid)
+ {
+ int data;
+ double accelUncalib[3] = {0,0,0};
+ double gyroUncalib[3] = {0,0,0};
+ int time;
+
+ count = (buffer[1] & 0x1f) / 9;
+ if(count == 0)
+ goto done;
+
+ //this timestamp is for the latest data
+ time = ((unsigned short)buffer[2]<<8) + (unsigned short)buffer[3];
+ if(phid->lastTimeCounterValid)
+ {
+ //0-255 ms
+ int timechange = (unsigned short)((unsigned short)time - (unsigned short)phid->lastTimeCounter);
+ timechange *= 1000; //us
+
+ phid->timestamp.seconds = phid->timestamp.seconds + (phid->timestamp.microseconds + timechange) / 1000000;
+ phid->timestamp.microseconds = (phid->timestamp.microseconds + timechange) % 1000000;
+ }
+ else
+ {
+ phid->lastTimeCounterValid = PTRUE;
+ }
+ phid->lastTimeCounter = time;
+
+ //add data to data buffer
+ for(i=0;i<count;i++)
+ {
+ //LIS344ALH - Vdd/15 V/g - 0xffff/15 = 0x1111 (4369.0)
+ for(j=0;j<3;j++)
+ {
+ data = ((unsigned short)buffer[4 + j * 2 + i * 18]<<8) + (unsigned short)buffer[5 + j * 2 + i * 18];
+ accelUncalib[j] = ((double)data - 0x7fff) / 4369.0;
+ }
+ accelUncalib[1] = -accelUncalib[1]; //reverse Y-axis
+ //Apply offsets
+ for(j=0;j<3;j++)
+ {
+ accelUncalib[j] -= phid->accelOffset[j];
+ }
+ //X
+ if(accelUncalib[0] > 0)
+ phid->dataBuffer[phid->bufferWritePtr].acceleration[0] = accelUncalib[0] * phid->accelGain1[0] + accelUncalib[1] * phid->accelFactor1[0] + accelUncalib[2] * phid->accelFactor2[0];
+ else
+ phid->dataBuffer[phid->bufferWritePtr].acceleration[0] = accelUncalib[0] * phid->accelGain2[0] + accelUncalib[1] * phid->accelFactor1[0] + accelUncalib[2] * phid->accelFactor2[0];
+ //Y
+ if(accelUncalib[1] > 0)
+ phid->dataBuffer[phid->bufferWritePtr].acceleration[1] = accelUncalib[1] * phid->accelGain1[1] + accelUncalib[0] * phid->accelFactor1[1] + accelUncalib[2] * phid->accelFactor2[1];
+ else
+ phid->dataBuffer[phid->bufferWritePtr].acceleration[1] = accelUncalib[1] * phid->accelGain2[1] + accelUncalib[0] * phid->accelFactor1[1] + accelUncalib[2] * phid->accelFactor2[1];
+ //Z
+ if(accelUncalib[2] > 0)
+ phid->dataBuffer[phid->bufferWritePtr].acceleration[2] = accelUncalib[2] * phid->accelGain1[2] + accelUncalib[0] * phid->accelFactor1[2] + accelUncalib[1] * phid->accelFactor2[2];
+ else
+ phid->dataBuffer[phid->bufferWritePtr].acceleration[2] = accelUncalib[2] * phid->accelGain2[2] + accelUncalib[0] * phid->accelFactor1[2] + accelUncalib[1] * phid->accelFactor2[2];
+
+ //ADC ref is 0-3.3V - 50.355uV/bit, gyro zero rate is 1.23V, 2.5mV/deg/s - these voltages are fixed, non-ratiometric to Vref
+ // 1 / 0.000050355 = 19859 (1V)
+ // 1.23 * 19859 = 24427
+ // 0.0025 * 19859 = 49.6477bits/deg/s
+ for(j=0;j<3;j++)
+ {
+ data = ((unsigned short)buffer[10 + j * 2 + i * 18]<<8) + (unsigned short)buffer[11 + j * 2 + i * 18];
+ if(j==1)
+ gyroUncalib[j] = ((double)(data-24427) + phid->gyroOffset[j]) / 49.6477;
+ else
+ gyroUncalib[j] = ((double)-(data-24427) + phid->gyroOffset[j]) / 49.6477; //reverse X/Z-axis
+ }
+ //0 - we multiply these by their gains so revered axes will still appear positive and get the correct gain
+ if((gyroUncalib[0] * phid->gyroGain1[0]) > 0)
+ phid->dataBuffer[phid->bufferWritePtr].angularRate[0] = gyroUncalib[0] * phid->gyroGain1[0] - gyroUncalib[1] * phid->gyroFactor1[0] - gyroUncalib[2] * phid->gyroFactor2[0];
+ else
+ phid->dataBuffer[phid->bufferWritePtr].angularRate[0] = gyroUncalib[0] * phid->gyroGain2[0] - gyroUncalib[1] * phid->gyroFactor1[0] - gyroUncalib[2] * phid->gyroFactor2[0];
+ //1
+ if((gyroUncalib[1] * phid->gyroGain1[1]) > 0)
+ phid->dataBuffer[phid->bufferWritePtr].angularRate[1] = gyroUncalib[1] * phid->gyroGain1[1] - gyroUncalib[0] * phid->gyroFactor1[1] - gyroUncalib[2] * phid->gyroFactor2[1];
+ else
+ phid->dataBuffer[phid->bufferWritePtr].angularRate[1] = gyroUncalib[1] * phid->gyroGain2[1] - gyroUncalib[0] * phid->gyroFactor1[1] - gyroUncalib[2] * phid->gyroFactor2[1];
+ //2
+ if((gyroUncalib[2] * phid->gyroGain1[2]) > 0)
+ phid->dataBuffer[phid->bufferWritePtr].angularRate[2] = gyroUncalib[2] * phid->gyroGain1[2] - gyroUncalib[0] * phid->gyroFactor1[2] - gyroUncalib[1] * phid->gyroFactor2[2];
+ else
+ phid->dataBuffer[phid->bufferWritePtr].angularRate[2] = gyroUncalib[2] * phid->gyroGain2[2] - gyroUncalib[0] * phid->gyroFactor1[2] - gyroUncalib[1] * phid->gyroFactor2[2];
+
+ //checks if compass data is valid
+ //Note: we miss ~7 samples (28ms) every second while the compass is callibrating
+ if(buffer[1] & (0x80 >> i))
+ {
+ //ADC 50.355uV/bit (0-3.3V)
+ //ideal compass midpoint is 0x7FFF (32767) (1.65V)
+ //valid range for zero field offset is: 0.825V - 2.475V (16384-49151) (+-16384)
+ // Note that this may be less (~3x) because the Gain is less, but I'm not sure. (+-5460)
+ //valid output voltage range is defined as 0.165V - 3.135V (3277-62258),
+ // so we can't really trust values outside of this, though we do seem to get valid data...
+ //ideal sensitivity is 250mV/gauss (ext. resistor), valid range is 195 - 305
+ // 1 / 0.000050355 = 19859 (1Volt)
+ // 0.250 * 19859 = 4964.75 bits/gauss (1.0 gain) (ideal) - valid range is (3861-6068) (+-1103)
+ //We have defined the compass gain multiplier to be based on 6500bits/gauss to keep the math resonable,
+ // so we must use that value here. Implications?
+ //The largest range we can guarantee is:
+ // 16384-3277/6068 = +-2.16 gauss or, more likely: +-3.96 gauss
+ // Ideal is: 32767-3277/4964.75 = +-5.94 gauss
+ // we can tell from the incoming data whether it's valid or not,
+ // we'll probably have more range in one dirrection then the other because of offset.
+ for(j=0;j<phid->phid.attr.spatial.numCompassAxes; j++)
+ {
+ data = ((unsigned short)buffer[16 + i * 18 + j * 2]<<8) + (unsigned short)buffer[17 + i * 18 + j * 2];
+ //if we are not within (3277-62258), data is not valid
+ if(data < 3277)
+ {
+ phid->dataBuffer[phid->bufferWritePtr].magneticField[j] = phid->magneticFieldMin;
+ break;
+ }
+ if(data > 62258)
+ {
+ phid->dataBuffer[phid->bufferWritePtr].magneticField[j] = phid->magneticFieldMax;
+ break;
+ }
+
+ //if gain or offset don't make sense, throw out data
+ //if(phid->compassGain[j] > 6068 || phid->compassGain[j] < 3861 ||
+ if(phid->compassGain[j] > 6068 || phid->compassGain[j] < 2500 || //lower gains seem to be common
+ phid->compassOffset[j] > 5460 || phid->compassOffset[j] < -5460)
+ {
+ if(data > 32767)
+ phid->dataBuffer[phid->bufferWritePtr].magneticField[j] = phid->magneticFieldMax;
+ else
+ phid->dataBuffer[phid->bufferWritePtr].magneticField[j] = phid->magneticFieldMin;
+ break;
+ }
+
+ //Convert ADC to Gauss
+ phid->dataBuffer[phid->bufferWritePtr].magneticField[j] =
+ -((double)data - 0x7fff - phid->compassOffset[j]) / phid->compassGain[j];
+
+ //constrain to max/min
+ //ie if field is 4.02 and max is 4.1, make it 4.1, since real max is 4.0
+ if(phid->dataBuffer[phid->bufferWritePtr].magneticField[j] > (phid->magneticFieldMax - 0.1))
+ phid->dataBuffer[phid->bufferWritePtr].magneticField[j] = phid->magneticFieldMax;
+ if(phid->dataBuffer[phid->bufferWritePtr].magneticField[j] < (phid->magneticFieldMin + 0.1))
+ phid->dataBuffer[phid->bufferWritePtr].magneticField[j] = phid->magneticFieldMin;
+ }
+
+ }
+ else
+ {
+ phid->dataBuffer[phid->bufferWritePtr].magneticField[0] = PUNK_DBL;
+ phid->dataBuffer[phid->bufferWritePtr].magneticField[1] = PUNK_DBL;
+ phid->dataBuffer[phid->bufferWritePtr].magneticField[2] = PUNK_DBL;
+ }
+
+ phid->latestDataTime.seconds = phid->timestamp.seconds + (phid->timestamp.microseconds + (i + 1) * phid->dataRateMax * 1000) / 1000000;
+ phid->latestDataTime.microseconds = (phid->timestamp.microseconds + (i + 1) * phid->dataRateMax * 1000) % 1000000;
+
+ phid->dataBuffer[phid->bufferWritePtr].timestamp = phid->latestDataTime;
+
+ phid->bufferWritePtr++;
+ if(phid->bufferWritePtr >= SPATIAL_DATA_BUFFER_SIZE)
+ phid->bufferWritePtr = 0;
+ }
+ }
+ break;
+ case SPATIAL_PACKET_CALIB:
+ for (i = 0; i<phid->phid.attr.spatial.numAccelAxes; i++)
+ {
+ cal = ((unsigned short)buffer[i*7 + 1]<<4) + ((unsigned short)buffer[i*7 + 2]>>4);
+ phid->accelGain1[i] = cal / (4096/0.4) + 0.8;
+ cal = (((unsigned short)buffer[i*7 + 2]<<8) & 0x0F00) | ((unsigned short)buffer[i*7 + 3]);
+ phid->accelGain2[i] = cal / (4096/0.4) + 0.8;
+ cal = (unsigned short)((unsigned short)buffer[i*7 + 4]<<8) + (unsigned short)buffer[i*7 + 5];
+ phid->accelOffset[i] = cal / (65535 / 1.0) - 0.5;
+ cal = (unsigned char)buffer[i*7 + 6];
+ phid->accelFactor1[i] = cal / (256 / 0.2) - 0.1;
+ cal = (unsigned char)buffer[i*7 + 7];
+ phid->accelFactor2[i] = cal / (256 / 0.2) - 0.1;
+ //LOG(PHIDGET_LOG_INFO, "Accel(%d) Calib: %1.4lf, %1.4lf, %1.4lf, %1.4lf, %1.4lf", i,
+ // phid->accelGain1[i], phid->accelGain2[i], phid->accelOffset[i], phid->accelFactor1[i], phid->accelFactor2[i]);
+ }
+ for (j=0; j<phid->phid.attr.spatial.numGyroAxes; i++,j++)
+ {
+ if (phidG->deviceVersion < 200)
+ {
+ cal = ((unsigned short)buffer[i*7 + 1]<<4) + ((unsigned short)buffer[i*7 + 2]>>4);
+ phid->gyroGain1[j] = cal / (4096/0.4) + 0.8;
+ cal = (((unsigned short)buffer[i*7 + 2]<<8) & 0x0F00) | ((unsigned short)buffer[i*7 + 3]);
+ phid->gyroGain2[j] = cal / (4096/0.4) + 0.8;
+ }
+ //Allow for negative gains
+ else if (phidG->deviceVersion >= 200 && phidG->deviceVersion < 300)
+ {
+ cal = ((signed short)((signed char)buffer[i*7 + 1])<<4) + ((unsigned short)buffer[i*7 + 2]>>4);
+ phid->gyroGain1[j] = cal / (4096/0.4) + (cal > 0 ? 0.9 : -0.9);
+ cal = ((((unsigned short)buffer[i*7 + 2]<<8) & 0x0F00) | ((unsigned short)buffer[i*7 + 3]) ) << 4;
+ cal = (signed short)cal >> 4;
+ phid->gyroGain2[j] = cal / (4096/0.4) + (cal > 0 ? 0.9 : -0.9);
+ }
+ cal = (signed short)((unsigned short)buffer[i*7 + 4]<<8) + (unsigned short)buffer[i*7 + 5];
+ phid->gyroOffset[j] = cal;
+ cal = (unsigned char)buffer[i*7 + 6];
+ phid->gyroFactor1[j] = cal / (256 / 0.1) - 0.05;
+ cal = (unsigned char)buffer[i*7 + 7];
+ phid->gyroFactor2[j] = cal / (256 / 0.1) - 0.05;
+
+//Zero out calibrations
+#if 0
+ phid->gyroGain1[j] = 1;
+ phid->gyroGain2[j] = 1;
+ phid->gyroOffset[j] = 0;
+ phid->gyroFactor1[j] = 0;
+ phid->gyroFactor2[j] = 0;
+#endif
+
+ LOG(PHIDGET_LOG_VERBOSE, "Gyro(%d) Calib: %1.4lf, %1.4lf, %1.4lf, %1.4lf, %1.4lf", j,
+ phid->gyroGain1[j], phid->gyroGain2[j], phid->gyroOffset[j], phid->gyroFactor1[j], phid->gyroFactor2[j]);
+ }
+ for(j=0;j<phid->phid.attr.spatial.numCompassAxes; j++)
+ {
+ phid->compassOffset[j] = (signed short)((unsigned short)buffer[j*4 + 49]<<8) + (unsigned short)buffer[j*4 + 50];
+ phid->compassGain[j] = ((unsigned short)buffer[j*4 + 51]<<8) + (unsigned short)buffer[j*4 + 52];
+ //phid->compassGain[j] = 4964;
+ }
+ //LOG(PHIDGET_LOG_INFO, "Compass Gain: %d, %d, %d", phid->compassGain[0], phid->compassGain[1], phid->compassGain[2]);
+ //LOG(PHIDGET_LOG_INFO, "Compass Offset: %d, %d, %d", phid->compassOffset[0], phid->compassOffset[1], phid->compassOffset[2]);
+ phid->calDataValid = PTRUE;
+ break;
+ }
+ }
+ // 1044 (1056 Replacement) and 1042 (low-cost 3/3/3)
+ else if (phidG->deviceVersion >= 300 && phidG->deviceVersion < 500)
+ { //top 2 bits in buffer[0] are packet type
+ switch(buffer[0])
+ {
+ case SPATIAL_PACKET_DATA:
+ {
+ int data;
+ int time;
+
+ count = buffer[1] & 0x03;
+ if(count == 0)
+ goto done;
+
+ //this timestamp is for the latest data
+ time = ((unsigned short)buffer[2]<<8) + (unsigned short)buffer[3];
+ //LOG(PHIDGET_LOG_DEBUG, "TimeStamp: %6d",time);
+ if(phid->lastTimeCounterValid)
+ {
+ //1-255 ms
+ int timechange = (unsigned short)((unsigned short)time - (unsigned short)phid->lastTimeCounter);
+ timechange *= 1000; //us
+
+ if(timechange > 500000)
+ LOG(PHIDGET_LOG_DEBUG, "Timechange: %d",timechange);
+
+ phid->timestamp.seconds = phid->timestamp.seconds + (phid->timestamp.microseconds + timechange) / 1000000;
+ phid->timestamp.microseconds = (phid->timestamp.microseconds + timechange) % 1000000;
+ }
+ else
+ {
+ phid->lastTimeCounterValid = PTRUE;
+ }
+ phid->lastTimeCounter = time;
+
+ //add data to data buffer
+ for(i=0;i<count;i++)
+ {
+ //digital accel
+ if(buffer[1] & (0x08 >> i))
+ {
+ LOG(PHIDGET_LOG_DEBUG, "digital accel");
+ //+-8g resolution is 1g/1024/bit
+ for(j=0;j<3;j++)
+ {
+ short accelData =
+ (signed short)((unsigned short)buffer[4 + j * 2 + i * 18]<<8) + (unsigned short)buffer[5 + j * 2 + i * 18];
+
+ if(j==0)
+ phid->dataBuffer[phid->bufferWritePtr].acceleration[j] = -((double)accelData / 1024.0);
+ else
+ phid->dataBuffer[phid->bufferWritePtr].acceleration[j] = (double)accelData / 1024.0;
+ }
+ }
+ //analog accel
+ else
+ {
+ //KXR94-2050 - 660 mV/g (VCC/5) - 0xffff/5 = 0x3333 (13107.0)
+ for(j=0;j<3;j++)
+ {
+ data = ((unsigned short)buffer[4 + j * 2 + i * 18]<<8) + (unsigned short)buffer[5 + j * 2 + i * 18];
+ if(j==2)
+ phid->dataBuffer[phid->bufferWritePtr].acceleration[j] = ((double)data - 0x7fff) / 13107;
+ else
+ phid->dataBuffer[phid->bufferWritePtr].acceleration[j] = -((double)data - 0x7fff) / 13107;
+ }
+ phid->dataBuffer[phid->bufferWritePtr].acceleration[1] = -phid->dataBuffer[phid->bufferWritePtr].acceleration[1]; //reverse Y-axis
+ }
+
+ //digital gyro
+ if(buffer[1] & (0x20 >> i))
+ {
+ LOG(PHIDGET_LOG_DEBUG, "digital gyro");
+ //2000dps
+ // 0.07 dps/digit
+ for(j=0;j<3;j++)
+ {
+ short gyroData =
+ (signed short)((unsigned short)buffer[10 + j * 2 + i * 18]<<8) + (unsigned short)buffer[11 + j * 2 + i * 18];
+
+ phid->dataBuffer[phid->bufferWritePtr].angularRate[j] = (double)gyroData * 0.07;
+ }
+ }
+ //analog gyro
+ else
+ {
+ //ADC ref is 0-3.3V - 50.355uV/bit, gyro zero rate is 1.5V, X/Y: 2.5mV/deg/s Z: 3.572mV/deg/s
+ // these voltages are fixed, non-ratiometric to Vref
+ // 1 / 0.000050355 = 19859 (1V)
+ // 1.5 * 19859 = 29789
+ // 0.0025 * 19859 = 49.6477bits/deg/s
+ // 0.003572 * 19859 = 70.936348bits/deg/s
+ for(j=0;j<3;j++)
+ {
+ data = ((unsigned short)buffer[10 + j * 2 + i * 18]<<8) + (unsigned short)buffer[11 + j * 2 + i * 18];
+ if(j==0)
+ phid->dataBuffer[phid->bufferWritePtr].angularRate[j] = ((double)-(data-29789)) / 49.6477; //reverse X-axis
+ else if(j==2)
+ phid->dataBuffer[phid->bufferWritePtr].angularRate[j] = ((double)-(data-29789)) / 70.936348; //reverse Z-axis
+ else
+ phid->dataBuffer[phid->bufferWritePtr].angularRate[j] = ((double)(data-29789)) / 49.6477;
+ }
+ }
+
+ //LOG(PHIDGET_LOG_DEBUG, "ADC Values: %1.3lf, %1.3lf, %1.3lf, %1.3lf, %1.3lf, %1.3lf", dataTrack[0], dataTrack[1], dataTrack[2], dataTrack[3], dataTrack[4], dataTrack[5]);
+
+ //checks if compass data is valid
+ if(buffer[1] & (0x80 >> i))
+ {
+ for(j=0;j<phid->phid.attr.spatial.numCompassAxes; j++)
+ {
+ short magData =
+ (signed short)((unsigned short)buffer[16 + i * 18 + j * 2]<<8) + (unsigned short)buffer[17 + i * 18 + j * 2];
+
+ //each bit is 0.1 uT
+
+
+ //Convert to Gauss (divide by 1000)
+ if(j==1)
+ phid->dataBuffer[phid->bufferWritePtr].magneticField[j] = -(magData / 1000.0);
+ else
+ phid->dataBuffer[phid->bufferWritePtr].magneticField[j] = magData / 1000.0;
+
+ //constrain to max/min
+ //ie if field is 4.02 and max is 4.1, make it 4.1, since real max is 4.0
+ if(phid->dataBuffer[phid->bufferWritePtr].magneticField[j] > (phid->magneticFieldMax - 0.1))
+ phid->dataBuffer[phid->bufferWritePtr].magneticField[j] = phid->magneticFieldMax;
+ if(phid->dataBuffer[phid->bufferWritePtr].magneticField[j] < (phid->magneticFieldMin + 0.1))
+ phid->dataBuffer[phid->bufferWritePtr].magneticField[j] = phid->magneticFieldMin;
+ }
+
+ }
+ else
+ {
+ phid->dataBuffer[phid->bufferWritePtr].magneticField[0] = PUNK_DBL;
+ phid->dataBuffer[phid->bufferWritePtr].magneticField[1] = PUNK_DBL;
+ phid->dataBuffer[phid->bufferWritePtr].magneticField[2] = PUNK_DBL;
+ }
+
+ phid->latestDataTime.seconds = phid->timestamp.seconds + (phid->timestamp.microseconds + (i + 1) * phid->dataRateMax * 1000) / 1000000;
+ phid->latestDataTime.microseconds = (phid->timestamp.microseconds + (i + 1) * phid->dataRateMax * 1000) % 1000000;
+
+ //LOG(PHIDGET_LOG_DEBUG, "Time: %d:%d",phid->latestDataTime.seconds,phid->latestDataTime.microseconds);
+
+ phid->dataBuffer[phid->bufferWritePtr].timestamp = phid->latestDataTime;
+
+ phid->bufferWritePtr++;
+ if(phid->bufferWritePtr >= SPATIAL_DATA_BUFFER_SIZE)
+ phid->bufferWritePtr = 0;
+ }
+
+ break;
+ }
+ }
+ }
+ else
+ return EPHIDGET_UNEXPECTED;
+ break;
+ default:
+ return EPHIDGET_UNEXPECTED;
+ }
+
+ if(phid->doZeroGyro)
+ {
+ //done
+ if(timestampdiff(phid->latestDataTime, phid->dataBuffer[phid->gyroZeroReadPtr].timestamp) >= SPATIAL_ZERO_GYRO_TIME)
+ {
+ double gryoCorrectionTemp[SPATIAL_MAX_GYROAXES] = {0,0,0};
+ int gryoCorrectionCount = 0;
+
+ while(phid->gyroZeroReadPtr != phid->bufferWritePtr)
+ {
+ for (i = 0; i<phid->phid.attr.spatial.numGyroAxes; i++)
+ {
+ gryoCorrectionTemp[i] += phid->dataBuffer[phid->gyroZeroReadPtr].angularRate[i];
+ }
+
+ phid->gyroZeroReadPtr++;
+ if(phid->gyroZeroReadPtr >= SPATIAL_DATA_BUFFER_SIZE)
+ phid->gyroZeroReadPtr = 0;
+
+ gryoCorrectionCount++;
+ }
+
+ for (i = 0; i<phid->phid.attr.spatial.numGyroAxes; i++)
+ {
+ phid->gryoCorrection[i] = gryoCorrectionTemp[i] / (double)gryoCorrectionCount;
+ }
+
+ doneGyroZero = PTRUE;
+ }
+ }
+
+ //see if it's time for an event
+ if(timestampdiff(phid->latestDataTime, phid->lastEventTime) >= dataRate)
+ {
+ CPhidget_Timestamp tempTime;
+ //int lastPtr;
+ int accelCounter[SPATIAL_MAX_ACCELAXES], angularRateCounter[SPATIAL_MAX_ACCELAXES], magneticFieldCounter[SPATIAL_MAX_ACCELAXES];
+
+ int dataPerEvent = 0;
+
+ int multipleDataPerEvent = PFALSE;
+
+ if(dataRate < phid->interruptRate)
+ multipleDataPerEvent = PTRUE;
+
+ //max of 16 data per event
+ eventData = malloc(16 * sizeof(CPhidgetSpatial_SpatialEventDataHandle));
+
+ for(j=0;;j++)
+ {
+ //makes sure we read all data
+ if(phid->bufferReadPtr == phid->bufferWritePtr || j>=16)
+ {
+ dataPerEvent = j;
+ break;
+ }
+
+ eventData[j] = malloc(sizeof(CPhidgetSpatial_SpatialEventData));
+ ZEROMEM(accelCounter, sizeof(accelCounter));
+ ZEROMEM(angularRateCounter, sizeof(angularRateCounter));
+ ZEROMEM(magneticFieldCounter, sizeof(magneticFieldCounter));
+
+ tempTime = phid->dataBuffer[phid->bufferReadPtr].timestamp;
+
+ //average data for each stage
+ while(phid->bufferReadPtr != phid->bufferWritePtr &&
+ (!multipleDataPerEvent || timestampdiff(phid->dataBuffer[phid->bufferReadPtr].timestamp, tempTime) < dataRate))
+ {
+ for (i = 0; i<phid->phid.attr.spatial.numAccelAxes; i++)
+ {
+ if(phid->dataBuffer[phid->bufferReadPtr].acceleration[i] != PUNK_DBL)
+ {
+ if(phid->dataBuffer[phid->bufferReadPtr].acceleration[i] > phid->accelerationMax)
+ phid->dataBuffer[phid->bufferReadPtr].acceleration[i] = phid->accelerationMax;
+ if(phid->dataBuffer[phid->bufferReadPtr].acceleration[i] < phid->accelerationMin)
+ phid->dataBuffer[phid->bufferReadPtr].acceleration[i] = phid->accelerationMin;
+ accelAvg[i] += phid->dataBuffer[phid->bufferReadPtr].acceleration[i];
+ accelCounter[i]++;
+ }
+ }
+ for (i = 0; i<phid->phid.attr.spatial.numGyroAxes; i++)
+ {
+ if(phid->dataBuffer[phid->bufferReadPtr].angularRate[i] != PUNK_DBL)
+ {
+ double rate = phid->dataBuffer[phid->bufferReadPtr].angularRate[i] - phid->gryoCorrection[i];
+
+ if(rate > phid->angularRateMax)
+ angularRateAvg[i] += phid->angularRateMax;
+ else if(rate < phid->angularRateMin)
+ angularRateAvg[i] += phid->angularRateMin;
+ else
+ angularRateAvg[i] += rate;
+ angularRateCounter[i]++;
+ }
+ }
+ for (i = 0; i<phid->phid.attr.spatial.numCompassAxes; i++)
+ {
+ if(phid->dataBuffer[phid->bufferReadPtr].magneticField[i] != PUNK_DBL)
+ {
+ if(phid->dataBuffer[phid->bufferReadPtr].magneticField[i] > phid->magneticFieldMax)
+ phid->dataBuffer[phid->bufferReadPtr].magneticField[i] = phid->magneticFieldMax;
+ if(phid->dataBuffer[phid->bufferReadPtr].magneticField[i] < phid->magneticFieldMin)
+ phid->dataBuffer[phid->bufferReadPtr].magneticField[i] = phid->magneticFieldMin;
+ magneticFieldAvg[i] += phid->dataBuffer[phid->bufferReadPtr].magneticField[i];
+ magneticFieldCounter[i]++;
+ }
+ }
+
+ //lastPtr = phid->bufferReadPtr;
+
+ phid->bufferReadPtr++;
+ if(phid->bufferReadPtr >= SPATIAL_DATA_BUFFER_SIZE)
+ phid->bufferReadPtr = 0;
+ }
+
+ for (i = 0; i<phid->phid.attr.spatial.numAccelAxes; i++)
+ {
+ if(accelCounter[i] > 0)
+ eventData[j]->acceleration[i] = round_double(accelAvg[i] / (double)accelCounter[i], 5);
+ else
+ eventData[j]->acceleration[i] = PUNK_DBL;
+ accelAvg[i] = 0;
+ }
+ for (i = 0; i<phid->phid.attr.spatial.numGyroAxes; i++)
+ {
+ if(angularRateCounter[i] > 0)
+ {
+ if(phid->doZeroGyro && !doneGyroZero)
+ eventData[j]->angularRate[i] = 0;
+ else
+ eventData[j]->angularRate[i] = round_double(angularRateAvg[i] / (double)angularRateCounter[i], 5);
+ }
+ else
+ eventData[j]->angularRate[i] = PUNK_DBL;
+ angularRateAvg[i] = 0;
+ }
+ for (i = 0; i<phid->phid.attr.spatial.numCompassAxes; i++)
+ {
+ if(magneticFieldCounter[i] > 0)
+ eventData[j]->magneticField[i] = round_double(magneticFieldAvg[i] / (double)magneticFieldCounter[i], 5);
+ else
+ eventData[j]->magneticField[i] = PUNK_DBL;
+ magneticFieldAvg[i] = 0;
+ }
+ eventData[j]->timestamp = tempTime;
+ }
+
+ //correct magnetic field data in the event structure
+ for( j = 0; j < dataPerEvent; j++)
+ {
+ for (i = 0; i<phid->phid.attr.spatial.numCompassAxes; i++)
+ {
+ magneticFieldCorr[i] = eventData[j]->magneticField[i];
+ }
+ for (i = 0; i<phid->phid.attr.spatial.numCompassAxes; i++)
+ {
+ if(eventData[j]->magneticField[i] != PUNK_DBL)
+ {
+ eventData[j]->magneticField[i] = getCorrectedField(phid, magneticFieldCorr, i);
+ }
+ }
+ }
+
+ //store to local structure
+ ZEROMEM(accelCounter, sizeof(accelCounter));
+ ZEROMEM(angularRateCounter, sizeof(angularRateCounter));
+ ZEROMEM(magneticFieldCounter, sizeof(magneticFieldCounter));
+ for( j = 0; j < dataPerEvent; j++)
+ {
+ for (i = 0; i<phid->phid.attr.spatial.numAccelAxes; i++)
+ {
+ if(eventData[j]->acceleration[i] != PUNK_DBL)
+ {
+ accelAvg[i] += eventData[j]->acceleration[i];
+ accelCounter[i]++;
+ }
+ }
+ for (i = 0; i<phid->phid.attr.spatial.numGyroAxes; i++)
+ {
+ if(eventData[j]->angularRate[i] != PUNK_DBL)
+ {
+ angularRateAvg[i] += eventData[j]->angularRate[i];
+ angularRateCounter[i]++;
+ }
+ }
+ for (i = 0; i<phid->phid.attr.spatial.numCompassAxes; i++)
+ {
+ if(eventData[j]->magneticField[i] != PUNK_DBL)
+ {
+ magneticFieldAvg[i] += eventData[j]->magneticField[i];
+ magneticFieldCounter[i]++;
+ }
+ }
+ }
+
+ //Set local get data to averages
+ for (i = 0; i<phid->phid.attr.spatial.numAccelAxes; i++)
+ {
+ if(accelCounter[i] > 0)
+ phid->accelAxis[i] = round_double(accelAvg[i] / (double)accelCounter[i], 5);
+ else
+ phid->accelAxis[i] = PUNK_DBL;
+ }
+ for (i = 0; i<phid->phid.attr.spatial.numGyroAxes; i++)
+ {
+ if(angularRateCounter[i] > 0)
+ {
+ if(phid->doZeroGyro && !doneGyroZero)
+ phid->gyroAxis[i] = 0;
+ else
+ phid->gyroAxis[i] = round_double(angularRateAvg[i] / (double)angularRateCounter[i], 5);
+ }
+ else
+ phid->gyroAxis[i] = PUNK_DBL;
+ }
+ for (i = 0; i<phid->phid.attr.spatial.numCompassAxes; i++)
+ {
+ if(magneticFieldCounter[i] > 0)
+ phid->compassAxis[i] = round_double(magneticFieldAvg[i] / (double)magneticFieldCounter[i], 5);
+ else
+ phid->compassAxis[i] = PUNK_DBL;
+ }
+
+ //send out any events
+ FIRE(SpatialData, eventData, dataPerEvent);
+
+ phid->lastEventTime = phid->latestDataTime;
+
+ for(i=0;i<dataPerEvent;i++)
+ free(eventData[i]);
+ free(eventData);
+ }
+done:
+
+ //this will signal the zero function to return;
+ if(doneGyroZero)
+ phid->doZeroGyro = PFALSE;
+
+ return EPHIDGET_OK;
+}
+
+//eventsAfterOpen - sends out an event for all valid data, used during attach initialization
+CPHIDGETINITEVENTS(Spatial)
+ TESTPTR(phid);
+ //don't need to worry, because the interrupts come at a set rate
+ return EPHIDGET_OK;
+}
+
+//getPacket - not used for spatial
+CGETPACKET(Spatial)
+ return EPHIDGET_UNEXPECTED;
+}
+
+static double getCorrectedField(CPhidgetSpatialHandle phid, double fields[], int axis)
+{
+ switch(axis)
+ {
+ case 0:
+ return phid->userMagField *
+ (phid->userCompassGain[0] * (fields[0] - phid->userCompassOffset[0])
+ + phid->userCompassTransform[0] * (fields[1] - phid->userCompassOffset[1])
+ + phid->userCompassTransform[1] * (fields[2] - phid->userCompassOffset[2]));
+ case 1:
+ return phid->userMagField *
+ (phid->userCompassGain[1] * (fields[1] - phid->userCompassOffset[1])
+ + phid->userCompassTransform[2] * (fields[0] - phid->userCompassOffset[0])
+ + phid->userCompassTransform[3] * (fields[2] - phid->userCompassOffset[2]));
+ case 2:
+ return phid->userMagField *
+ (phid->userCompassGain[2] * (fields[2] - phid->userCompassOffset[2])
+ + phid->userCompassTransform[4] * (fields[0] - phid->userCompassOffset[0])
+ + phid->userCompassTransform[5] * (fields[1] - phid->userCompassOffset[1]));
+ default:
+ return 0;
+ }
+}
+
+// === Exported Functions === //
+
+//create and initialize a device structure
+CCREATE(Spatial, PHIDCLASS_SPATIAL)
+
+//event setup functions
+CFHANDLE(Spatial, SpatialData, CPhidgetSpatial_SpatialEventDataHandle *, int)
+
+CGET(Spatial,AccelerationAxisCount,int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_SPATIAL)
+ TESTATTACHED
+
+ MASGN(phid.attr.spatial.numAccelAxes)
+}
+CGET(Spatial,GyroAxisCount,int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_SPATIAL)
+ TESTATTACHED
+
+ MASGN(phid.attr.spatial.numGyroAxes)
+}
+CGET(Spatial,CompassAxisCount,int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_SPATIAL)
+ TESTATTACHED
+
+ MASGN(phid.attr.spatial.numCompassAxes)
+}
+
+CGETINDEX(Spatial,Acceleration,double)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_SPATIAL)
+ TESTATTACHED
+ TESTINDEX(phid.attr.spatial.numAccelAxes)
+ TESTMASGN(accelAxis[Index], PUNK_DBL)
+
+ MASGN(accelAxis[Index])
+}
+
+CGETINDEX(Spatial,AccelerationMax,double)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_SPATIAL)
+ TESTATTACHED
+ TESTINDEX(phid.attr.spatial.numAccelAxes)
+ TESTMASGN(accelerationMax, PUNK_DBL)
+
+ MASGN(accelerationMax)
+}
+
+CGETINDEX(Spatial,AccelerationMin,double)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_SPATIAL)
+ TESTATTACHED
+ TESTINDEX(phid.attr.spatial.numAccelAxes)
+ TESTMASGN(accelerationMin, PUNK_DBL)
+
+ MASGN(accelerationMin)
+}
+
+CGETINDEX(Spatial,AngularRate,double)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_SPATIAL)
+ TESTATTACHED
+
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_SPATIAL_ACCEL_GYRO_COMPASS:
+ TESTINDEX(phid.attr.spatial.numGyroAxes)
+ TESTMASGN(gyroAxis[Index], PUNK_DBL)
+ MASGN(gyroAxis[Index])
+ case PHIDID_SPATIAL_ACCEL_3AXIS:
+ default:
+ return EPHIDGET_UNSUPPORTED;
+ }
+}
+
+CGETINDEX(Spatial,AngularRateMax,double)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_SPATIAL)
+ TESTATTACHED
+
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_SPATIAL_ACCEL_GYRO_COMPASS:
+ TESTINDEX(phid.attr.spatial.numGyroAxes)
+ TESTMASGN(angularRateMax, PUNK_DBL)
+ MASGN(angularRateMax)
+ case PHIDID_SPATIAL_ACCEL_3AXIS:
+ default:
+ return EPHIDGET_UNSUPPORTED;
+ }
+}
+
+CGETINDEX(Spatial,AngularRateMin,double)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_SPATIAL)
+ TESTATTACHED
+
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_SPATIAL_ACCEL_GYRO_COMPASS:
+ TESTINDEX(phid.attr.spatial.numGyroAxes)
+ TESTMASGN(angularRateMin, PUNK_DBL)
+ MASGN(angularRateMin)
+ case PHIDID_SPATIAL_ACCEL_3AXIS:
+ default:
+ return EPHIDGET_UNSUPPORTED;
+ }
+}
+
+CGETINDEX(Spatial,MagneticField,double)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_SPATIAL)
+ TESTATTACHED
+
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_SPATIAL_ACCEL_GYRO_COMPASS:
+ TESTINDEX(phid.attr.spatial.numCompassAxes)
+ TESTMASGN(compassAxis[Index], PUNK_DBL)
+ MASGN(compassAxis[Index])
+ case PHIDID_SPATIAL_ACCEL_3AXIS:
+ default:
+ return EPHIDGET_UNSUPPORTED;
+ }
+}
+
+CGETINDEX(Spatial,MagneticFieldMax,double)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_SPATIAL)
+ TESTATTACHED
+
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_SPATIAL_ACCEL_GYRO_COMPASS:
+ TESTINDEX(phid.attr.spatial.numCompassAxes)
+ TESTMASGN(magneticFieldMax, PUNK_DBL)
+ MASGN(magneticFieldMax)
+ case PHIDID_SPATIAL_ACCEL_3AXIS:
+ default:
+ return EPHIDGET_UNSUPPORTED;
+ }
+}
+
+CGETINDEX(Spatial,MagneticFieldMin,double)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_SPATIAL)
+ TESTATTACHED
+
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_SPATIAL_ACCEL_GYRO_COMPASS:
+ TESTINDEX(phid.attr.spatial.numCompassAxes)
+ TESTMASGN(magneticFieldMin, PUNK_DBL)
+ MASGN(magneticFieldMin)
+ case PHIDID_SPATIAL_ACCEL_3AXIS:
+ default:
+ return EPHIDGET_UNSUPPORTED;
+ }
+}
+
+CSET(Spatial,DataRate,int)
+ TESTPTR(phid)
+ TESTDEVICETYPE(PHIDCLASS_SPATIAL)
+ TESTATTACHED
+ TESTRANGE(phid->dataRateMax, phid->dataRateMin)
+
+ //make sure it's a power of 2, or 1
+ if(newVal < phid->interruptRate)
+ {
+ int temp = phid->dataRateMax;
+ unsigned char good = FALSE;
+ while(temp <= newVal)
+ {
+ if(temp == newVal)
+ {
+ good = TRUE;
+ break;
+ }
+ temp *= 2;
+ }
+ if(!good)
+ return EPHIDGET_INVALIDARG;
+ }
+ //make sure it's divisible by interruptRate
+ else
+ {
+ if(newVal%phid->interruptRate)
+ return EPHIDGET_INVALIDARG;
+ }
+
+ if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
+ ADDNETWORKKEY(DataRate, "%d", dataRate);
+ else
+ phid->dataRate = newVal;
+
+ return EPHIDGET_OK;
+}
+CGET(Spatial,DataRate,int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_SPATIAL)
+ TESTATTACHED
+ TESTMASGN(dataRate, PUNK_INT)
+
+ MASGN(dataRate)
+}
+
+CGET(Spatial,DataRateMax,int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_SPATIAL)
+ TESTATTACHED
+ TESTMASGN(dataRateMax, PUNK_INT)
+
+ MASGN(dataRateMax)
+}
+
+CGET(Spatial,DataRateMin,int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_SPATIAL)
+ TESTATTACHED
+ TESTMASGN(dataRateMin, PUNK_INT)
+
+ MASGN(dataRateMin)
+}
+
+PHIDGET21_API int CCONV CPhidgetSpatial_zeroGyro(CPhidgetSpatialHandle phid)
+{
+ TESTPTR(phid)
+ TESTDEVICETYPE(PHIDCLASS_SPATIAL)
+ TESTATTACHED
+ if(phid->phid.attr.spatial.numGyroAxes==0)
+ return EPHIDGET_UNSUPPORTED;
+
+ if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
+ {
+ int newVal = phid->flip^1;
+ ADDNETWORKKEY(ZeroGyro, "%d", flip);
+ }
+ else
+ {
+ if(!phid->doZeroGyro)
+ {
+ phid->gyroZeroReadPtr = phid->bufferReadPtr;
+ phid->doZeroGyro = PTRUE;
+ }
+ }
+
+ return EPHIDGET_OK;
+}
+
+PHIDGET21_API int CCONV CPhidgetSpatial_resetCompassCorrectionParameters(
+ CPhidgetSpatialHandle phid)
+{
+ TESTPTR(phid)
+ TESTDEVICETYPE(PHIDCLASS_SPATIAL)
+ TESTATTACHED
+
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_SPATIAL_ACCEL_GYRO_COMPASS:
+ if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
+ {
+ char newVal[1024];
+ sprintf(newVal, "1,0,0,0,1,1,1,0,0,0,0,0,0");
+ ADDNETWORKKEY(CompassCorrectionParams, "%s", compassCorrectionParamsString);
+ }
+ else
+ {
+ phid->userMagField = 1;
+
+ phid->userCompassOffset[0] = 0;
+ phid->userCompassOffset[1] = 0;
+ phid->userCompassOffset[2] = 0;
+
+ phid->userCompassGain[0] = 1;
+ phid->userCompassGain[1] = 1;
+ phid->userCompassGain[2] = 1;
+
+ phid->userCompassTransform[0] = 0;
+ phid->userCompassTransform[1] = 0;
+ phid->userCompassTransform[2] = 0;
+ phid->userCompassTransform[3] = 0;
+ phid->userCompassTransform[4] = 0;
+ phid->userCompassTransform[5] = 0;
+ }
+ return EPHIDGET_OK;
+ case PHIDID_SPATIAL_ACCEL_3AXIS:
+ default:
+ return EPHIDGET_UNSUPPORTED;
+ }
+}
+PHIDGET21_API int CCONV CPhidgetSpatial_setCompassCorrectionParameters(
+ CPhidgetSpatialHandle phid,
+ double magField,
+ double offset0, double offset1, double offset2,
+ double gain0, double gain1, double gain2,
+ double T0, double T1, double T2, double T3, double T4, double T5)
+{
+ TESTPTR(phid)
+ TESTDEVICETYPE(PHIDCLASS_SPATIAL)
+ TESTATTACHED
+
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_SPATIAL_ACCEL_GYRO_COMPASS:
+ //Magnetic Field 0.1-1000
+ if(magField < 0.1 || magField > 1000)
+ return EPHIDGET_INVALIDARG;
+ //Offsets need to be 0+-5.0
+ if(offset0 < -5 || offset0 > 5)
+ return EPHIDGET_INVALIDARG;
+ if(offset1 < -5 || offset1 > 5)
+ return EPHIDGET_INVALIDARG;
+ if(offset2 < -5 || offset2 > 5)
+ return EPHIDGET_INVALIDARG;
+ //Gains need to be 0-15.0
+ if(gain0 < 0 || gain0 > 15)
+ return EPHIDGET_INVALIDARG;
+ if(gain1 < 0 || gain1 > 15)
+ return EPHIDGET_INVALIDARG;
+ if(gain2 < 0 || gain2 > 15)
+ return EPHIDGET_INVALIDARG;
+ //T params 0+-5.0
+ if(T0 < -5 || T0 > 5)
+ return EPHIDGET_INVALIDARG;
+ if(T1 < -5 || T1 > 5)
+ return EPHIDGET_INVALIDARG;
+ if(T2 < -5 || T2 > 5)
+ return EPHIDGET_INVALIDARG;
+ if(T3 < -5 || T3 > 5)
+ return EPHIDGET_INVALIDARG;
+ if(T4 < -5 || T4 > 5)
+ return EPHIDGET_INVALIDARG;
+ if(T5 < -5 || T5 > 5)
+ return EPHIDGET_INVALIDARG;
+
+ if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
+ {
+ char newVal[1024];
+ sprintf(newVal, "%lE,%lE,%lE,%lE,%lE,%lE,%lE,%lE,%lE,%lE,%lE,%lE,%lE",
+ magField, offset0, offset1, offset2, gain0, gain1, gain2, T0, T1, T2, T3, T4, T5);
+ ADDNETWORKKEY(CompassCorrectionParams, "%s", compassCorrectionParamsString);
+ }
+ else
+ {
+ phid->userMagField = magField;
+
+ phid->userCompassOffset[0] = offset0;
+ phid->userCompassOffset[1] = offset1;
+ phid->userCompassOffset[2] = offset2;
+
+ phid->userCompassGain[0] = gain0;
+ phid->userCompassGain[1] = gain1;
+ phid->userCompassGain[2] = gain2;
+
+ phid->userCompassTransform[0] = T0;
+ phid->userCompassTransform[1] = T1;
+ phid->userCompassTransform[2] = T2;
+ phid->userCompassTransform[3] = T3;
+ phid->userCompassTransform[4] = T4;
+ phid->userCompassTransform[5] = T5;
+ }
+
+ return EPHIDGET_OK;
+ case PHIDID_SPATIAL_ACCEL_3AXIS:
+ default:
+ return EPHIDGET_UNSUPPORTED;
+ }
+}
+
+//Maybe add these later
+/*
+CGET(Spatial,GyroHeading,double)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_SPATIAL)
+ TESTATTACHED
+ TESTMASGN(gyroHeading, PUNK_DBL)
+
+ MASGN(gyroHeading)
+}
+
+CGET(Spatial,CompassHeading,double)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_SPATIAL)
+ TESTATTACHED
+ TESTMASGN(compassHeading, PUNK_DBL)
+
+ MASGN(compassHeading)
+}*/
diff --git a/cphidgetspatial.h b/cphidgetspatial.h
new file mode 100644
index 0000000..8d9fdb7
--- /dev/null
+++ b/cphidgetspatial.h
@@ -0,0 +1,256 @@
+#ifndef __CPHIDGETSPATIAL
+#define __CPHIDGETSPATIAL
+#include "cphidget.h"
+
+/** \defgroup phidspatial Phidget Spatial
+ * \ingroup phidgets
+ * Calls specific to the Phidget Spatial. See the product manual for more specific API details, supported functionality, units, etc.
+ * @{
+ */
+
+DPHANDLE(Spatial)
+CHDRSTANDARD(Spatial)
+
+/**
+ * Timestamped position data returned by the \ref CPhidgetSpatial_set_OnSpatialData_Handler event.
+ */
+typedef struct _CPhidgetSpatial_SpatialEventData
+{
+ double acceleration[3]; /**< Acceleration data for up to 3 axes. */
+ double angularRate[3]; /**< Angular rate data (Gyroscope) for up to 3 axes */
+ double magneticField[3]; /**< Magnetic field data (Compass) for up to 3 axes */
+ CPhidget_Timestamp timestamp; /**< Hardware timestamp */
+} CPhidgetSpatial_SpatialEventData, *CPhidgetSpatial_SpatialEventDataHandle;
+
+/**
+ * Gets the number of acceleration axes supplied by this board.
+ * @param phid An attached phidget spatial handle.
+ * @param count The number of acceleration axes.
+ */
+CHDRGET(Spatial,AccelerationAxisCount,int *count)
+/**
+ * Gets the number of gyroscope axes supplied by this board.
+ * @param phid An attached phidget spatial handle.
+ * @param count The number of gyro axes.
+ */
+CHDRGET(Spatial,GyroAxisCount,int *count)
+/**
+ * Gets the number of compass axes supplied by this board.
+ * @param phid An attached phidget spatial handle.
+ * @param count The number of compass axes.
+ */
+CHDRGET(Spatial,CompassAxisCount,int *count)
+
+/**
+ * Gets the current acceleration of an axis.
+ * @param phid An attached phidget spatial handle.
+ * @param index The acceleration index.
+ * @param acceleration The acceleration in gs.
+ */
+CHDRGETINDEX(Spatial,Acceleration,double *acceleration)
+/**
+ * Gets the maximum accleration supported by an axis.
+ * @param phid An attached phidget spatial handle.
+ * @param index The acceleration index
+ * @param max The maximum acceleration
+ */
+CHDRGETINDEX(Spatial,AccelerationMax,double *max)
+/**
+ * Gets the minimum acceleration supported by an axis.
+ * @param phid An attached phidget spatial handle.
+ * @param index The acceleration index
+ * @param min The minimum acceleration
+ */
+CHDRGETINDEX(Spatial,AccelerationMin,double *min)
+
+/**
+ * Gets the current angular rate of an axis.
+ * @param phid An attached phidget spatial handle.
+ * @param index The angular rate index.
+ * @param angularRate The angular rate in degrees/second.
+ */
+CHDRGETINDEX(Spatial,AngularRate,double *angularRate)
+/**
+ * Gets the maximum angular rate supported by an axis.
+ * @param phid An attached phidget spatial handle.
+ * @param index The angular rate index
+ * @param max The maximum angular rate
+ */
+CHDRGETINDEX(Spatial,AngularRateMax,double *max)
+/**
+ * Gets the minimum angular rate supported by an axis.
+ * @param phid An attached phidget spatial handle.
+ * @param index The angular rate index
+ * @param min The minimum angular rate
+ */
+CHDRGETINDEX(Spatial,AngularRateMin,double *min)
+
+/**
+ * Gets the current magnetic field stregth of an axis.
+ * @param phid An attached phidget spatial handle.
+ * @param index The magnetic field index.
+ * @param magneticField The magnetic field strength in Gauss.
+ */
+CHDRGETINDEX(Spatial,MagneticField,double *magneticField)
+/**
+ * Gets the maximum magnetic field stregth supported by an axis.
+ * @param phid An attached phidget spatial handle.
+ * @param index The magnetic field index
+ * @param max The maximum magnetic field stregth
+ */
+CHDRGETINDEX(Spatial,MagneticFieldMax,double *max)
+/**
+ * Gets the minimum magnetic field stregth supported by an axis.
+ * @param phid An attached phidget spatial handle.
+ * @param index The magnetic field index
+ * @param min The minimum magnetic field stregth
+ */
+CHDRGETINDEX(Spatial,MagneticFieldMin,double *min)
+
+/**
+ * Zeroes the gyroscope. This takes about two seconds and the gyro zxes will report 0 during the process.
+ * This should only be called when the board is not moving.
+ * @param phid An attached phidget spatial handle.
+ */
+PHIDGET21_API int CCONV CPhidgetSpatial_zeroGyro(CPhidgetSpatialHandle phid);
+
+/**
+ * Get the data rate.
+ * @param phid An attached phidget spatial handle.
+ * @param milliseconds The data rate in milliseconds.
+ */
+CHDRGET(Spatial, DataRate, int *milliseconds)
+/**
+ * Sets the data rate. Note that data at rates faster then 8ms will be delivered to events as an array of data.
+ * @param phid An attached phidget spatial handle.
+ * @param milliseconds The data rate in milliseconds.
+ */
+CHDRSET(Spatial, DataRate, int milliseconds)
+/**
+ * Gets the maximum supported data rate.
+ * @param phid An attached phidget spatial handle.
+ * @param max Data rate in ms.
+ */
+CHDRGET(Spatial, DataRateMax, int *max)
+/**
+ * Gets the minimum supported data rate.
+ * @param phid An attached phidget spatial handle.
+ * @param min Data rate in ms.
+ */
+CHDRGET(Spatial, DataRateMin, int *min)
+
+/**
+ * Sets the compass correction factors. This can be used to correcting any sensor errors, including hard and soft iron offsets and sensor error factors.
+ * @param phid An attached phidget spatial handle.
+ * @param magField Local magnetic field strength.
+ * @param offset0 Axis 0 offset correction.
+ * @param offset1 Axis 1 offset correction.
+ * @param offset2 Axis 2 offset correction.
+ * @param gain0 Axis 0 gain correction.
+ * @param gain1 Axis 1 gain correction.
+ * @param gain2 Axis 2 gain correction.
+ * @param T0 Non-orthogonality correction factor 0.
+ * @param T1 Non-orthogonality correction factor 1.
+ * @param T2 Non-orthogonality correction factor 2.
+ * @param T3 Non-orthogonality correction factor 3.
+ * @param T4 Non-orthogonality correction factor 4.
+ * @param T5 Non-orthogonality correction factor 5.
+ */
+CHDRSET(Spatial, CompassCorrectionParameters, double magField, double offset0, double offset1, double offset2, double gain0, double gain1, double gain2, double T0, double T1, double T2, double T3, double T4, double T5)
+/**
+ * Resets the compass correction factors. Magnetic field data will be presented directly as reported by the sensor.
+ * @param phid An attached phidget spatial handle.
+ */
+PHIDGET21_API int CCONV CPhidgetSpatial_resetCompassCorrectionParameters(CPhidgetSpatialHandle phid);
+
+/**
+ * Set a Data event handler. This is called at /ref CPhidgetSpatial_getDataRate, up to 8ms, for faster then 8ms data, multiple
+ * sets of data are supplied in a single event.
+ * @param phid An attached phidget spatial handle.
+ * @param fptr Callback function pointer.
+ * @param userPtr A pointer for use by the user - this value is passed back into the callback function.
+ */
+CHDREVENT(Spatial,SpatialData,CPhidgetSpatial_SpatialEventDataHandle *data, int dataCount)
+
+#ifndef EXTERNALPROTO
+
+#define SPATIAL_MAX_ACCELAXES 3
+#define SPATIAL_MAX_GYROAXES 3
+#define SPATIAL_MAX_COMPASSAXES 3
+
+//in milliseconds - this is the fastest hardware rate of any device
+#define SPATIAL_MAX_DATA_RATE 1
+//1 second is the longest between events that we support
+#define SPATIAL_MIN_DATA_RATE 1000
+//add 200ms for timing differences (late events, etc) - should be plenty
+#define SPATIAL_DATA_BUFFER_SIZE ((SPATIAL_MIN_DATA_RATE + 200)/SPATIAL_MAX_DATA_RATE)
+//1 second of data to zero the gyro - make sure DATA_BUFFER_SIZE is big enough to hold this much data
+#define SPATIAL_ZERO_GYRO_TIME 2000
+
+//packet types
+//IN
+#define SPATIAL_PACKET_DATA 0x00
+#define SPATIAL_PACKET_CALIB 0x80
+//OUT
+#define SPATIAL_READCALIB 0x01
+
+struct _CPhidgetSpatial {
+ CPhidget phid;
+ int (CCONV *fptrSpatialData)(CPhidgetSpatialHandle, void *, CPhidgetSpatial_SpatialEventDataHandle *, int);
+ void *fptrSpatialDataptr;
+
+ double accelAxis[SPATIAL_MAX_ACCELAXES];
+ double gyroAxis[SPATIAL_MAX_GYROAXES];
+ double compassAxis[SPATIAL_MAX_COMPASSAXES];
+
+ double gryoCorrection[SPATIAL_MAX_GYROAXES];
+ unsigned char doZeroGyro;
+ int gyroZeroReadPtr;
+
+ CPhidgetSpatial_SpatialEventData dataBuffer[SPATIAL_DATA_BUFFER_SIZE];
+ int bufferReadPtr, bufferWritePtr;
+
+ double accelerationMax, accelerationMin;
+ double angularRateMax, angularRateMin;
+ double magneticFieldMax, magneticFieldMin;
+
+ unsigned char calDataValid;
+
+ double accelGain1[SPATIAL_MAX_ACCELAXES];
+ double accelGain2[SPATIAL_MAX_ACCELAXES];
+ double accelOffset[SPATIAL_MAX_ACCELAXES];
+ double accelFactor1[SPATIAL_MAX_ACCELAXES];
+ double accelFactor2[SPATIAL_MAX_ACCELAXES];
+
+ double gyroGain1[SPATIAL_MAX_GYROAXES];
+ double gyroGain2[SPATIAL_MAX_GYROAXES];
+ double gyroOffset[SPATIAL_MAX_GYROAXES];
+ double gyroFactor1[SPATIAL_MAX_GYROAXES];
+ double gyroFactor2[SPATIAL_MAX_GYROAXES];
+
+ int compassGain[SPATIAL_MAX_COMPASSAXES];
+ int compassOffset[SPATIAL_MAX_COMPASSAXES];
+
+ double userMagField;
+ double userCompassGain[SPATIAL_MAX_COMPASSAXES];
+ double userCompassOffset[SPATIAL_MAX_COMPASSAXES];
+ double userCompassTransform[SPATIAL_MAX_COMPASSAXES*(SPATIAL_MAX_COMPASSAXES-1)];
+
+ CPhidget_Timestamp timestamp, lastEventTime, latestDataTime;
+
+ unsigned char lastTimeCounterValid;
+ int lastTimeCounter;
+ int flip;
+
+ char *compassCorrectionParamsString;
+ unsigned char spatialDataNetwork;
+
+ int dataRate, interruptRate;
+ int dataRateMax, dataRateMin;
+
+} typedef CPhidgetSpatialInfo;
+#endif
+
+/** @} */
+
+#endif
diff --git a/cphidgetstepper.c b/cphidgetstepper.c
new file mode 100644
index 0000000..5b7ead2
--- /dev/null
+++ b/cphidgetstepper.c
@@ -0,0 +1,933 @@
+#include "stdafx.h"
+#include "cphidgetstepper.h"
+#include "cusb.h"
+#include "csocket.h"
+#include "cthread.h"
+
+// === Internal Functions === //
+
+//clearVars - sets all device variables to unknown state
+CPHIDGETCLEARVARS(Stepper)
+ int i = 0;
+
+ phid->motorSpeedMax = PUNI_DBL;
+ phid->motorSpeedMin = PUNI_DBL;
+ phid->accelerationMax = PUNI_DBL;
+ phid->accelerationMin = PUNI_DBL;
+ phid->motorPositionMax = PUNI_INT64;
+ phid->motorPositionMin = PUNI_INT64;
+ phid->currentMax = PUNI_DBL;
+ phid->currentMin = PUNI_DBL;
+
+ for (i = 0; i<STEPPER_MAXINPUTS; i++)
+ {
+ phid->inputState[i] = PUNI_BOOL;
+ }
+
+ for (i = 0; i<STEPPER_MAXSTEPPERS; i++)
+ {
+ phid->motorSpeedEcho[i] = PUNI_DBL;
+ phid->motorPositionEcho[i] = PUNI_INT64;
+ phid->motorSensedCurrent[i] = PUNI_DBL;
+ phid->motorEngagedStateEcho[i] = PUNI_BOOL;
+ phid->motorStoppedState[i] = PUNI_BOOL;
+ phid->packetCounterEcho[i] = PUNK_INT;
+
+ phid->motorPosition[i] = PUNI_INT64;
+ phid->motorPositionReset[i] = PUNK_INT64;
+ phid->motorEngagedState[i] = PUNK_BOOL;
+ phid->motorAcceleration[i] = PUNK_DBL;
+ phid->motorSpeed[i] = PUNK_DBL;
+ phid->motorCurrentLimit[i] = PUNK_DBL;
+ phid->packetCounter[i] = PUNK_INT;
+ }
+ return EPHIDGET_OK;
+}
+
+//initAfterOpen - sets up the initial state of an object, reading in packets from the device if needed
+// used during attach initialization - on every attach
+CPHIDGETINIT(Stepper)
+ int i = 0;
+
+ TESTPTR(phid);
+
+ //Make sure no old writes are still pending
+ phid->outputPacketLen = 0;
+
+ //Setup max/min values
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_UNIPOLAR_STEPPER_4MOTOR:
+ if ((phid->phid.deviceVersion >= 100) && (phid->phid.deviceVersion < 200))
+ {
+ phid->microSteps = 2;
+ phid->motorSpeedMax = ((phid->microSteps * 0x100) - 1) * 0.75;
+ phid->motorSpeedMin = 0;
+ phid->accelerationMax = (250 * (0.75 * 0.75)) * 0x3f;
+ phid->accelerationMin = (250 * (0.75 * 0.75));
+ phid->motorPositionMax = 0x7FFFFFFFFFLL;
+ phid->motorPositionMin = -0x7FFFFFFFFFLL;
+ phid->currentMax = PUNK_DBL;
+ phid->currentMin = PUNK_DBL;
+ }
+ else
+ return EPHIDGET_BADVERSION;
+ break;
+ case PHIDID_BIPOLAR_STEPPER_1MOTOR:
+ if ((phid->phid.deviceVersion >= 100) && (phid->phid.deviceVersion < 200))
+ {
+ phid->microSteps = 16;
+ phid->motorSpeedMax = 8 * phid->microSteps * 0x100; //0x8000
+ phid->motorSpeedMin = 0;
+ phid->accelerationMax = 4000 * 0xff;
+ phid->accelerationMin = 4000;
+ phid->motorPositionMax = 0x7FFFFFFFFFLL;
+ phid->motorPositionMin = -0x7FFFFFFFFFLL;
+ phid->currentMax = 2.492;
+ phid->currentMin = 0.0542;
+ }
+ else
+ return EPHIDGET_BADVERSION;
+ break;
+ default:
+ return EPHIDGET_UNEXPECTED;
+ }
+
+ //set data arrays to unknown
+ for (i = 0; i<phid->phid.attr.stepper.numInputs; i++)
+ {
+ phid->inputState[i] = PUNK_BOOL;
+ }
+ for (i = 0; i<phid->phid.attr.stepper.numMotors; i++)
+ {
+ phid->motorSpeedEcho[i] = PUNK_DBL;
+ phid->motorPositionEcho[i] = PUNK_INT64;
+ phid->motorSensedCurrent[i] = PUNK_DBL;
+ phid->motorEngagedStateEcho[i] = PUNK_BOOL;
+ phid->motorStoppedState[i] = PUNK_BOOL;
+ phid->packetCounterEcho[i] = PUNK_INT;
+ phid->packetCounter[i] = PUNK_INT;
+ }
+
+ //read in initial state - only one packet needed
+ CPhidget_read((CPhidgetHandle)phid);
+
+ //At this point, we can only recover (maybe) the position, engaged state, set others to unknown
+ for (i = 0; i<phid->phid.attr.advancedservo.numMotors; i++)
+ {
+ phid->motorPosition[i] = phid->motorPositionEcho[i];
+ phid->motorEngagedState[i] = phid->motorEngagedStateEcho[i];
+ phid->motorAcceleration[i] = PUNK_DBL;
+ phid->motorSpeed[i] = PUNK_DBL;
+ phid->motorCurrentLimit[i] = PUNK_DBL;
+ phid->packetCounter[i] = phid->packetCounterEcho[i];
+
+ if(phid->motorStoppedState[i] == PUNK_BOOL)
+ {
+ if(phid->motorSpeedEcho[i] == 0 || phid->motorEngagedStateEcho[i] == PFALSE)
+ phid->motorStoppedState[i] = PTRUE;
+ else
+ phid->motorStoppedState[i] = PFALSE;
+ }
+ }
+
+ return EPHIDGET_OK;
+}
+
+//dataInput - parses device packets
+CPHIDGETDATA(Stepper)
+ int i = 0, j = 0;
+
+ double speed[STEPPER_MAXSTEPPERS], current[STEPPER_MAXSTEPPERS];
+ double lastSpeed[STEPPER_MAXSTEPPERS], lastCurrent[STEPPER_MAXSTEPPERS];
+ __int64 position[STEPPER_MAXSTEPPERS], lastPosition[STEPPER_MAXSTEPPERS];
+ unsigned char input[STEPPER_MAXINPUTS], lastInput[STEPPER_MAXINPUTS];
+ unsigned char motorEngaged[STEPPER_MAXSTEPPERS], motorDone[STEPPER_MAXSTEPPERS], justStopped[STEPPER_MAXSTEPPERS];
+
+ if (length < 0) return EPHIDGET_INVALIDARG;
+ TESTPTR(phid);
+ TESTPTR(buffer);
+
+ ZEROMEM(input, sizeof(input));
+ ZEROMEM(lastInput, sizeof(lastInput));
+
+ //Parse device packets - store data locally
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_UNIPOLAR_STEPPER_4MOTOR:
+ if ((phid->phid.deviceVersion >= 100) && (phid->phid.deviceVersion < 200))
+ {
+ for (i = 0; i < phid->phid.attr.stepper.numMotors; i++)
+ {
+ phid->packetCounterEcho[i] = buffer[0+(i*9)] & 0x0F;
+ motorEngaged[i] = (buffer[0+(i*9)] & MOTOR_DISABLED_STEPPER) ? PFALSE : PTRUE;
+ motorDone[i] = (buffer[0+(i*9)] & MOTOR_DONE_STEPPER) ? PTRUE : PFALSE;
+
+ speed[i] = (double)((signed short)((buffer[1+(i*9)] << 8) | buffer[2+(i*9)]));
+ speed[i] = (double)((speed[i] / 511.0) * phid->motorSpeedMax);
+
+ position[i] = ((((__int64)(signed char)buffer[3+(i*9)]) << 40) +
+ (((__uint64)buffer[4+(i*9)]) << 32) +
+ (((__uint64)buffer[5+(i*9)]) << 24) +
+ (((__uint64)buffer[6+(i*9)]) << 16) +
+ (((__uint64)buffer[7+(i*9)]) << 8) +
+ ((__uint64)buffer[8+(i*9)]));
+
+ position[i] -= 0x20; //round
+ position[i] >>= 6;
+
+ //current is not returned
+ current[i] = PUNK_DBL;
+ }
+ }
+ else
+ return EPHIDGET_UNEXPECTED;
+ break;
+ case PHIDID_BIPOLAR_STEPPER_1MOTOR:
+ if ((phid->phid.deviceVersion >= 100) && (phid->phid.deviceVersion < 200))
+ {
+ double Vad;
+ phid->packetCounterEcho[0] = buffer[0] & 0x0F;
+ motorEngaged[0] = (buffer[0] & MOTOR_DISABLED_STEPPER) ? PFALSE : PTRUE;
+ motorDone[0] = (buffer[0] & MOTOR_DONE_STEPPER) ? PTRUE : PFALSE;
+
+ speed[0] = (double)((signed short)((buffer[1] << 8) | buffer[2]));
+ speed[0] = (double)((speed[i] / 4096.0) * phid->motorSpeedMax);
+
+ position[0] = ((((__int64)(signed char)buffer[3]) << 40) +
+ (((__uint64)buffer[4]) << 32) +
+ (((__uint64)buffer[5]) << 24) +
+ (((__uint64)buffer[6]) << 16) +
+ (((__uint64)buffer[7]) << 8) +
+ ((__uint64)buffer[8]));
+
+ position[0] -= 0x04; //round
+ position[0] >>= 3;
+
+ for (i = 0, j=0x01; i<phid->phid.attr.stepper.numInputs; i++, j<<=1)
+ {
+ if ((buffer[9] & j))
+ input[i] = PFALSE;
+ else
+ input[i] = PTRUE;
+ }
+
+ //value is 0-4.16 v in 8 bits
+ //(4.16 = (Vbandgap + 1.6) * 2, min 4.096v, max 4.224v according to bandgap voltage min, max)
+ //ie +-1.5% error
+ Vad = (((unsigned char)buffer[10] * 4.16 ) / 255.0); // The voltage sensed, to a max of 4.16v
+ current[0] = round_double((Vad / (BIPOLAR_STEPPER_CURRENT_SENSE_GAIN * BIPOLAR_STEPPER_CURRENT_LIMIT_Rs)), 3);
+ }
+ else
+ return EPHIDGET_UNEXPECTED;
+ break;
+ default:
+ return EPHIDGET_UNEXPECTED;
+ }
+
+ //Make sure values are within defined range, and store to structure
+ for (i = 0; i < phid->phid.attr.stepper.numMotors; i++)
+ {
+ lastPosition[i] = phid->motorPositionEcho[i];
+ lastSpeed[i] = phid->motorSpeedEcho[i];
+ lastCurrent[i] = phid->motorSensedCurrent[i];
+
+ if(position[i] > phid->motorPositionMax || position[i] < phid->motorPositionMin)
+ phid->motorPositionEcho[i] = PUNK_INT64;
+ else
+ phid->motorPositionEcho[i] = position[i];
+
+ if(speed[i] > phid->motorSpeedMax || speed[i] < -phid->motorSpeedMax)
+ LOG(PHIDGET_LOG_WARNING, "Phidget stepper recieved out of range speed data: %lE", speed[i]);
+ else
+ phid->motorSpeedEcho[i] = speed[i];
+
+ phid->motorSensedCurrent[i] = current[i];
+
+ phid->motorEngagedStateEcho[i] = motorEngaged[i];
+ }
+
+ for (i = 0; i < phid->phid.attr.stepper.numInputs; i++)
+ {
+ lastInput[i] = phid->inputState[i];
+ phid->inputState[i] = input[i];
+ }
+
+ //make sure phid->motorStoppedState isn't updated until the other data is filled in
+ CThread_mutex_lock(&phid->phid.writelock);
+ for (i = 0; i < phid->phid.attr.stepper.numMotors; i++)
+ {
+ //if we are up to date, and the motor is done, set stopped to true - this is the only place that this gets set true;
+ justStopped[i] = PFALSE;
+ if(phid->packetCounter[i] == phid->packetCounterEcho[i] && motorDone[i] == PTRUE
+ && ((phid->motorPositionEcho[i] == phid->motorPosition[i] && phid->motorSpeedEcho[i] == 0) || phid->motorEngagedStateEcho[i] == PFALSE))
+ {
+ if(phid->motorStoppedState[i] == PFALSE)
+ justStopped[i] = PTRUE;
+ phid->motorStoppedState[i] = PTRUE;
+ }
+ else if(motorDone[i] == PFALSE)
+ phid->motorStoppedState[i] = PFALSE;
+ }
+ //LOG(PHIDGET_LOG_VERBOSE, " ECHO: %d %d %d %d",phid->packetCounterEcho[0],phid->packetCounterEcho[1],phid->packetCounterEcho[2],phid->packetCounterEcho[3]);
+ CThread_mutex_unlock(&phid->phid.writelock);
+
+ //send out any events for changed data
+ for (i = 0; i < phid->phid.attr.stepper.numInputs; i++)
+ {
+ if(phid->inputState[i] != PUNK_BOOL && phid->inputState[i] != lastInput[i])
+ FIRE(InputChange, i, phid->inputState[i]);
+ }
+
+ for (i = 0; i < phid->phid.attr.stepper.numMotors; i++)
+ {
+ if(phid->motorPositionEcho[i] != PUNK_INT64 && phid->motorEngagedStateEcho[i] == PTRUE
+ && (phid->motorPositionEcho[i] != lastPosition[i] || justStopped[i] == PTRUE) )
+ {
+ FIRE(PositionChange, i, phid->motorPositionEcho[i]);
+ FIRE(PositionChange32, i, (int)phid->motorPositionEcho[i]);
+ }
+
+ if(phid->motorSpeedEcho[i] != PUNK_DBL && phid->motorSpeedEcho[i] != lastSpeed[i])
+ FIRE(VelocityChange, i, phid->motorSpeedEcho[i]);
+
+ if(phid->motorSensedCurrent[i] != PUNK_DBL && phid->motorSensedCurrent[i] != lastCurrent[i])
+ FIRE(CurrentChange, i, phid->motorSensedCurrent[i]);
+ }
+
+ return EPHIDGET_OK;
+}
+
+//eventsAfterOpen - sends out an event for all valid data, used during attach initialization
+CPHIDGETINITEVENTS(Stepper)
+
+ for (i = 0; i<phid->phid.attr.stepper.numInputs; i++)
+ {
+ if(phid->inputState[i] != PUNK_BOOL)
+ FIRE(InputChange, i, phid->inputState[i]);
+ }
+ for (i = 0; i<phid->phid.attr.stepper.numMotors; i++)
+ {
+ if(phid->motorSensedCurrent[i] != PUNK_DBL)
+ FIRE(CurrentChange, i, phid->motorSensedCurrent[i]);
+ if(phid->motorSpeedEcho[i] != PUNK_DBL)
+ FIRE(VelocityChange, i, phid->motorSpeedEcho[i]);
+ if(phid->motorPositionEcho[i] != PUNK_INT64 && phid->motorEngagedStateEcho[i] == PTRUE)
+ {
+ FIRE(PositionChange, i, phid->motorPositionEcho[i]);
+ FIRE(PositionChange32, i, (int)phid->motorPositionEcho[i]);
+ }
+ }
+
+ return EPHIDGET_OK;
+}
+
+//getPacket - used by write thread to get the next packet to send to device
+CGETPACKET_BUF(Stepper)
+
+//sendpacket - sends a packet to the device asynchronously, blocking if the 1-packet queue is full
+CSENDPACKET_BUF(Stepper)
+
+//makePacket - constructs a packet using current device state
+CMAKEPACKETINDEXED(Stepper)
+ unsigned char accel = 0, flags = 0;
+ unsigned short speed = 0;
+ __int64 position = 0;
+
+ int packet_type = Index & 0x30;
+ Index = Index & 0x0F;
+
+ TESTPTRS(phid, buffer);
+
+ if(phid->packetCounter[Index] == PUNK_INT)
+ phid->packetCounter[Index] = 0;
+
+ phid->packetCounter[Index]++;
+ phid->packetCounter[Index] &= 0x0F;
+ phid->motorStoppedState[Index] = PFALSE;
+
+ //LOG(PHIDGET_LOG_VERBOSE, " OUT %d: %d",Index, phid->packetCounter[Index]);
+
+ //have to make sure that everything to be sent has some sort of default value if the user hasn't set a value
+ if(phid->motorEngagedState[Index] == PUNK_BOOL)
+ phid->motorEngagedState[Index] = PFALSE; //note motors are not engaged by default
+
+ if(phid->motorEngagedState[Index] == PFALSE)
+ flags |= MOTOR_DISABLED_STEPPER;
+
+ switch(packet_type)
+ {
+ case STEPPER_POSITION_PACKET:
+ break;
+ case STEPPER_VEL_ACCEL_PACKET:
+ if(phid->motorSpeed[Index] == PUNK_DBL)
+ phid->motorSpeed[Index] = phid->motorSpeedMax / 2;
+ if(phid->motorAcceleration[Index] == PUNK_DBL)
+ phid->motorAcceleration[Index] = phid->accelerationMax / 2; //mid-level acceleration
+ break;
+ case STEPPER_RESET_PACKET:
+ phid->motorPosition[Index] = phid->motorPositionReset[Index];
+ break;
+ default:
+ return EPHIDGET_UNEXPECTED;
+ }
+
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_UNIPOLAR_STEPPER_4MOTOR:
+ if ((phid->phid.deviceVersion >= 100) && (phid->phid.deviceVersion < 200))
+ {
+ //2-bit index, 2-bit packet type, 4-bit counter
+ buffer[0] = (Index << 6) | packet_type | phid->packetCounter[Index];
+ //flags
+ buffer[1] = flags;
+
+ switch(packet_type)
+ {
+ case STEPPER_POSITION_PACKET:
+ position = phid->motorPosition[Index] << 6;
+ position += 0x20;
+
+ //48-bit position
+ buffer[2] = (unsigned char)(position >> 40);
+ buffer[3] = (unsigned char)(position >> 32);
+ buffer[4] = (unsigned char)(position >> 24);
+ buffer[5] = (unsigned char)(position >> 16);
+ buffer[6] = (unsigned char)(position >> 8);
+ buffer[7] = (unsigned char)(position);
+ break;
+ case STEPPER_VEL_ACCEL_PACKET:
+ accel = (unsigned char)round((phid->motorAcceleration[Index]/phid->accelerationMax) * 63.0);
+ speed = (unsigned short)round((phid->motorSpeed[Index]/phid->motorSpeedMax) * 511.0);
+
+ //6-bit acceleration
+ buffer[2] = accel;
+ //9-bit speed
+ buffer[3] = speed >> 8;
+ buffer[4] = speed & 0xFF;
+ //not used
+ buffer[5] = 0;
+ buffer[6] = 0;
+ buffer[7] = 0;
+ break;
+ case STEPPER_RESET_PACKET:
+ position = phid->motorPositionReset[Index] << 6;
+ position += 0x20;
+
+ //48-bit position
+ buffer[2] = (unsigned char)(position >> 40);
+ buffer[3] = (unsigned char)(position >> 32);
+ buffer[4] = (unsigned char)(position >> 24);
+ buffer[5] = (unsigned char)(position >> 16);
+ buffer[6] = (unsigned char)(position >> 8);
+ buffer[7] = (unsigned char)(position);
+ break;
+ default:
+ return EPHIDGET_UNEXPECTED;
+ }
+ }
+ else
+ return EPHIDGET_UNEXPECTED;
+ break;
+ case PHIDID_BIPOLAR_STEPPER_1MOTOR:
+ if ((phid->phid.deviceVersion >= 100) && (phid->phid.deviceVersion < 200))
+ {
+ unsigned char currentLimit = 0;
+ double Vref;
+
+ //2-bit index, 2-bit packet type, 4-bit counter
+ buffer[0] = (Index << 6) | packet_type | phid->packetCounter[Index];
+ //flags
+ buffer[1] = flags;
+
+ switch(packet_type)
+ {
+ case STEPPER_POSITION_PACKET:
+ position = phid->motorPosition[Index] << 3;
+ position += 0x04;
+
+ //48-bit position
+ buffer[2] = (unsigned char)(position >> 40);
+ buffer[3] = (unsigned char)(position >> 32);
+ buffer[4] = (unsigned char)(position >> 24);
+ buffer[5] = (unsigned char)(position >> 16);
+ buffer[6] = (unsigned char)(position >> 8);
+ buffer[7] = (unsigned char)(position);
+ break;
+ case STEPPER_VEL_ACCEL_PACKET:
+ if(phid->motorCurrentLimit[Index] == PUNK_DBL)
+ phid->motorCurrentLimit[Index] = 0.50; //choose 500mA - should at least work for the most part
+
+ accel = (unsigned char)round((phid->motorAcceleration[Index]/phid->accelerationMax) * 255.0);
+ speed = (unsigned short)round((phid->motorSpeed[Index]/phid->motorSpeedMax) * 4096.0);
+
+ // highest Vref is 3v (2.5A limit as defined by stepping chip)
+ // The 8 is defined by the stepping chip - (ItripMAX = Vref/8Rs)
+ Vref = phid->motorCurrentLimit[Index] * 8 * BIPOLAR_STEPPER_CURRENT_LIMIT_Rs;
+ // DAC output is 0-63 = 0-4.16v, highest value is 45 (3v)
+ // 2.08 = Vbandgap * 1.6
+ currentLimit = (unsigned char)round( (((Vref - 2.08)/2.08) * 32) + 31 );
+
+ //8-bit acceleration
+ buffer[2] = accel;
+ //12-bit speed
+ buffer[3] = speed >> 8;
+ buffer[4] = speed & 0xFF;
+ //6-bit current limit
+ buffer[5] = currentLimit;
+ //not used
+ buffer[6] = 0;
+ buffer[7] = 0;
+ break;
+ case STEPPER_RESET_PACKET:
+ position = phid->motorPositionReset[Index] << 3;
+ position += 0x04;
+
+ //48-bit position
+ buffer[2] = (unsigned char)(position >> 40);
+ buffer[3] = (unsigned char)(position >> 32);
+ buffer[4] = (unsigned char)(position >> 24);
+ buffer[5] = (unsigned char)(position >> 16);
+ buffer[6] = (unsigned char)(position >> 8);
+ buffer[7] = (unsigned char)(position);
+ break;
+ default:
+ return EPHIDGET_UNEXPECTED;
+ }
+ }
+ else
+ return EPHIDGET_UNEXPECTED;
+ break;
+ default:
+ return EPHIDGET_UNEXPECTED;
+ }
+
+ return EPHIDGET_OK;
+}
+
+// === Exported Functions === //
+
+//create and initialize a device structure
+CCREATE(Stepper, PHIDCLASS_STEPPER)
+
+//event setup functions
+CFHANDLE(Stepper, InputChange, int, int)
+CFHANDLE(Stepper, PositionChange, int, __int64)
+CFHANDLE(Stepper, PositionChange32, int, int)
+CFHANDLE(Stepper, VelocityChange, int, double)
+CFHANDLE(Stepper, CurrentChange, int, double)
+
+CGET(Stepper,InputCount,int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_STEPPER)
+ TESTATTACHED
+
+ MASGN(phid.attr.stepper.numInputs)
+}
+
+CGETINDEX(Stepper,InputState,int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_STEPPER)
+ TESTATTACHED
+ TESTINDEX(phid.attr.stepper.numInputs)
+ TESTMASGN(inputState[Index], PUNK_BOOL)
+
+ MASGN(inputState[Index])
+}
+
+CGET(Stepper,MotorCount,int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_STEPPER)
+ TESTATTACHED
+
+ MASGN(phid.attr.stepper.numMotors)
+}
+CGETINDEX(Stepper,Acceleration,double)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_STEPPER)
+ TESTATTACHED
+ TESTINDEX(phid.attr.stepper.numMotors)
+ TESTMASGN(motorAcceleration[Index], PUNK_DBL)
+
+ MASGN(motorAcceleration[Index])
+}
+CSETINDEX(Stepper,Acceleration,double)
+ TESTPTR(phid)
+ TESTINDEX(phid.attr.stepper.numMotors)
+ TESTDEVICETYPE(PHIDCLASS_STEPPER)
+ TESTATTACHED
+ TESTRANGE(phid->accelerationMin, phid->accelerationMax)
+
+ if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
+ ADDNETWORKKEYINDEXED(Acceleration, "%lE", motorAcceleration);
+ else
+ SENDPACKETINDEXED(Stepper, motorAcceleration[Index], Index + STEPPER_VEL_ACCEL_PACKET);
+
+ return EPHIDGET_OK;
+}
+
+CGETINDEX(Stepper,AccelerationMax,double)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_STEPPER)
+ TESTATTACHED
+ TESTINDEX(phid.attr.stepper.numMotors)
+ TESTMASGN(accelerationMax, PUNK_DBL)
+
+ MASGN(accelerationMax)
+}
+
+CGETINDEX(Stepper,AccelerationMin,double)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_STEPPER)
+ TESTATTACHED
+ TESTINDEX(phid.attr.stepper.numMotors)
+ TESTMASGN(accelerationMin, PUNK_DBL)
+
+ MASGN(accelerationMin)
+}
+
+CGETINDEX(Stepper,Velocity,double)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_STEPPER)
+ TESTATTACHED
+ TESTINDEX(phid.attr.stepper.numMotors)
+ TESTMASGN(motorSpeedEcho[Index], PUNK_DBL)
+
+ MASGN(motorSpeedEcho[Index])
+}
+
+CGETINDEX(Stepper,VelocityLimit,double)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_STEPPER)
+ TESTATTACHED
+ TESTINDEX(phid.attr.stepper.numMotors)
+ TESTMASGN(motorSpeed[Index], PUNK_DBL)
+
+ MASGN(motorSpeed[Index])
+}
+CSETINDEX(Stepper,VelocityLimit,double)
+ TESTPTR(phid)
+ TESTDEVICETYPE(PHIDCLASS_STEPPER)
+ TESTATTACHED
+ TESTINDEX(phid.attr.stepper.numMotors)
+ TESTRANGE(phid->motorSpeedMin, phid->motorSpeedMax)
+
+ if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
+ ADDNETWORKKEYINDEXED(VelocityLimit, "%lE", motorSpeed);
+ else
+ SENDPACKETINDEXED(Stepper, motorSpeed[Index], Index + STEPPER_VEL_ACCEL_PACKET);
+
+ return EPHIDGET_OK;
+}
+
+CGETINDEX(Stepper,VelocityMax,double)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_STEPPER)
+ TESTATTACHED
+ TESTINDEX(phid.attr.stepper.numMotors)
+ TESTMASGN(motorSpeedMax, PUNK_DBL)
+
+ MASGN(motorSpeedMax)
+}
+
+CGETINDEX(Stepper,VelocityMin,double)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_STEPPER)
+ TESTATTACHED
+ TESTINDEX(phid.attr.stepper.numMotors)
+ TESTMASGN(motorSpeedMin, PUNK_DBL)
+
+ MASGN(motorSpeedMin)
+}
+
+CGETINDEX(Stepper,TargetPosition,__int64)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_STEPPER)
+ TESTATTACHED
+ TESTINDEX(phid.attr.stepper.numMotors)
+ TESTMASGN(motorPosition[Index], PUNK_INT64)
+
+ MASGN(motorPosition[Index])
+}
+CSETINDEX(Stepper,TargetPosition,__int64)
+ TESTPTR(phid)
+ TESTDEVICETYPE(PHIDCLASS_STEPPER)
+ TESTATTACHED
+ TESTINDEX(phid.attr.stepper.numMotors)
+ TESTRANGE(phid->motorPositionMin, phid->motorPositionMax)
+
+ if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
+ ADDNETWORKKEYINDEXED(TargetPosition, "%lld", motorPosition);
+ else
+ SENDPACKETINDEXED(Stepper, motorPosition[Index], Index + STEPPER_POSITION_PACKET);
+
+ return EPHIDGET_OK;
+}
+
+CGETINDEX(Stepper,CurrentPosition,__int64)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_STEPPER)
+ TESTATTACHED
+ TESTINDEX(phid.attr.stepper.numMotors)
+ TESTMASGN(motorPositionEcho[Index], PUNK_INT64)
+
+ MASGN(motorPositionEcho[Index])
+}
+CSETINDEX(Stepper,CurrentPosition,__int64)
+ TESTPTR(phid)
+ TESTDEVICETYPE(PHIDCLASS_STEPPER)
+ TESTATTACHED
+ TESTINDEX(phid.attr.stepper.numMotors)
+ TESTRANGE(phid->motorPositionMin, phid->motorPositionMax)
+
+ if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
+ ADDNETWORKKEYINDEXED(CurrentPosition, "%lld", motorPositionReset);
+ else
+ SENDPACKETINDEXED(Stepper, motorPositionReset[Index], Index + STEPPER_RESET_PACKET);
+
+ return EPHIDGET_OK;
+}
+
+CGETINDEX(Stepper,PositionMax,__int64)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_STEPPER)
+ TESTATTACHED
+ TESTINDEX(phid.attr.stepper.numMotors)
+ TESTMASGN(motorPositionMax, PUNK_INT64)
+
+ MASGN(motorPositionMax)
+}
+
+CGETINDEX(Stepper,PositionMin,__int64)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_STEPPER)
+ TESTATTACHED
+ TESTINDEX(phid.attr.stepper.numMotors)
+ TESTMASGN(motorPositionMin, PUNK_INT64)
+
+ MASGN(motorPositionMin)
+}
+CGETINDEX(Stepper,TargetPosition32,int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_STEPPER)
+ TESTATTACHED
+ TESTINDEX(phid.attr.stepper.numMotors)
+ TESTMASGN(motorPosition[Index], PUNK_INT)
+
+ *pVal = (int)phid->motorPosition[Index]; return EPHIDGET_OK;
+}
+CSETINDEX(Stepper,TargetPosition32,int)
+ TESTPTR(phid)
+ TESTDEVICETYPE(PHIDCLASS_STEPPER)
+ TESTATTACHED
+ TESTINDEX(phid.attr.stepper.numMotors)
+ TESTRANGE(phid->motorPositionMin, phid->motorPositionMax)
+
+ if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
+ ADDNETWORKKEYINDEXED(TargetPosition, "%d", motorPosition);
+ else
+ SENDPACKETINDEXED(Stepper, motorPosition[Index], Index + STEPPER_POSITION_PACKET);
+
+ return EPHIDGET_OK;
+}
+
+CGETINDEX(Stepper,CurrentPosition32,int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_STEPPER)
+ TESTATTACHED
+ TESTINDEX(phid.attr.stepper.numMotors)
+ TESTMASGN(motorPositionEcho[Index], PUNK_INT)
+
+ *pVal = (int)phid->motorPositionEcho[Index]; return EPHIDGET_OK;
+}
+CSETINDEX(Stepper,CurrentPosition32,int)
+ TESTPTR(phid)
+ TESTDEVICETYPE(PHIDCLASS_STEPPER)
+ TESTATTACHED
+ TESTINDEX(phid.attr.stepper.numMotors)
+ TESTRANGE(phid->motorPositionMin, phid->motorPositionMax)
+
+ if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
+ ADDNETWORKKEYINDEXED(CurrentPosition, "%d", motorPositionReset);
+ else
+ SENDPACKETINDEXED(Stepper, motorPositionReset[Index], Index + STEPPER_RESET_PACKET);
+
+ return EPHIDGET_OK;
+}
+
+CGETINDEX(Stepper,PositionMax32,int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_STEPPER)
+ TESTATTACHED
+ TESTINDEX(phid.attr.stepper.numMotors)
+
+ *pVal = -(PUNK_INT-1); return EPHIDGET_OK;
+}
+
+CGETINDEX(Stepper,PositionMin32,int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_STEPPER)
+ TESTATTACHED
+ TESTINDEX(phid.attr.stepper.numMotors)
+
+ *pVal = (PUNK_INT-1); return EPHIDGET_OK;
+}
+
+CGETINDEX(Stepper,Current,double)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_STEPPER)
+ TESTATTACHED
+
+ //only the bipolar has current sense
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_BIPOLAR_STEPPER_1MOTOR:
+ TESTINDEX(phid.attr.stepper.numMotors)
+ if ((phid->phid.deviceVersion >= 100) && (phid->phid.deviceVersion < 200))
+ {
+ TESTMASGN(motorSensedCurrent[Index], PUNK_DBL)
+ MASGN(motorSensedCurrent[Index])
+ }
+ else
+ return EPHIDGET_UNEXPECTED;
+ break;
+ case PHIDID_UNIPOLAR_STEPPER_4MOTOR:
+ default:
+ return EPHIDGET_UNSUPPORTED;
+ }
+}
+
+CGETINDEX(Stepper,CurrentLimit,double)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_STEPPER)
+ TESTATTACHED
+
+ //only the bipolar has currentLimit
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_BIPOLAR_STEPPER_1MOTOR:
+ TESTINDEX(phid.attr.stepper.numMotors)
+ if ((phid->phid.deviceVersion >= 100) && (phid->phid.deviceVersion < 200))
+ {
+ TESTMASGN(motorCurrentLimit[Index], PUNK_DBL)
+ MASGN(motorCurrentLimit[Index])
+ }
+ else
+ return EPHIDGET_UNEXPECTED;
+ break;
+ case PHIDID_UNIPOLAR_STEPPER_4MOTOR:
+ default:
+ return EPHIDGET_UNSUPPORTED;
+ }
+}
+CSETINDEX(Stepper,CurrentLimit,double)
+ TESTPTR(phid)
+ TESTDEVICETYPE(PHIDCLASS_STEPPER)
+ TESTATTACHED
+
+ //only the bipolar has currentLimit
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_BIPOLAR_STEPPER_1MOTOR:
+ TESTINDEX(phid.attr.stepper.numMotors)
+ TESTRANGE(phid->currentMin, phid->currentMax)
+ if ((phid->phid.deviceVersion >= 100) && (phid->phid.deviceVersion < 200))
+ {
+ if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
+ ADDNETWORKKEYINDEXED(CurrentLimit, "%lE", motorCurrentLimit);
+ else
+ SENDPACKETINDEXED(Stepper, motorCurrentLimit[Index], Index + STEPPER_VEL_ACCEL_PACKET);
+ }
+ else
+ return EPHIDGET_UNEXPECTED;
+ break;
+ case PHIDID_UNIPOLAR_STEPPER_4MOTOR:
+ default:
+ return EPHIDGET_UNSUPPORTED;
+ }
+
+ return EPHIDGET_OK;
+}
+
+CGETINDEX(Stepper,CurrentMax,double)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_STEPPER)
+ TESTATTACHED
+
+ //only the bipolar has current
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_BIPOLAR_STEPPER_1MOTOR:
+ TESTINDEX(phid.attr.stepper.numMotors)
+ if ((phid->phid.deviceVersion >= 100) && (phid->phid.deviceVersion < 200))
+ {
+ TESTMASGN(currentMax, PUNK_DBL)
+ MASGN(currentMax)
+ }
+ else
+ return EPHIDGET_UNEXPECTED;
+ break;
+ case PHIDID_UNIPOLAR_STEPPER_4MOTOR:
+ default:
+ return EPHIDGET_UNSUPPORTED;
+ }
+}
+
+CGETINDEX(Stepper,CurrentMin,double)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_STEPPER)
+ TESTATTACHED
+
+ //only the bipolar has current
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_BIPOLAR_STEPPER_1MOTOR:
+ TESTINDEX(phid.attr.stepper.numMotors)
+ if ((phid->phid.deviceVersion >= 100) && (phid->phid.deviceVersion < 200))
+ {
+ TESTMASGN(currentMin, PUNK_DBL)
+ MASGN(currentMin)
+ }
+ else
+ return EPHIDGET_UNEXPECTED;
+ break;
+ case PHIDID_UNIPOLAR_STEPPER_4MOTOR:
+ default:
+ return EPHIDGET_UNSUPPORTED;
+ }
+}
+
+CGETINDEX(Stepper,Engaged,int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_STEPPER)
+ TESTATTACHED
+ TESTINDEX(phid.attr.stepper.numMotors)
+ TESTMASGN(motorEngagedStateEcho[Index], PUNK_BOOL)
+
+ MASGN(motorEngagedStateEcho[Index])
+}
+CSETINDEX(Stepper,Engaged,int)
+ TESTPTR(phid)
+ TESTDEVICETYPE(PHIDCLASS_STEPPER)
+ TESTATTACHED
+ TESTINDEX(phid.attr.stepper.numMotors)
+ TESTRANGE(PFALSE, PTRUE)
+
+ if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
+ ADDNETWORKKEYINDEXED(Engaged, "%d", motorEngagedState);
+ else
+ //hang off the STEPPER_VEL_ACCEL_PACKET because this will have the side effect of also setting these two states
+ SENDPACKETINDEXED(Stepper, motorEngagedState[Index], Index + STEPPER_VEL_ACCEL_PACKET);
+
+ return EPHIDGET_OK;
+}
+
+CGETINDEX(Stepper,Stopped,int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_STEPPER)
+ TESTATTACHED
+ TESTINDEX(phid.attr.stepper.numMotors)
+ TESTMASGN(motorStoppedState[Index], PUNK_BOOL)
+
+ MASGN(motorStoppedState[Index])
+}
diff --git a/cphidgetstepper.h b/cphidgetstepper.h
new file mode 100644
index 0000000..2fe59c4
--- /dev/null
+++ b/cphidgetstepper.h
@@ -0,0 +1,294 @@
+#ifndef __CPHIDGETSTEPPER
+#define __CPHIDGETSTEPPER
+#include "cphidget.h"
+
+/** \defgroup phidstepper Phidget Stepper
+ * \ingroup phidgets
+ * Calls specific to the Phidget Stepper. See the product manual for more specific API details, supported functionality, units, etc.
+ * @{
+ */
+
+DPHANDLE(Stepper)
+CHDRSTANDARD(Stepper)
+
+
+/**
+ * Gets the number of digital inputs supported by this board.
+ * @param phid An attached phidget stepper handle.
+ * @param count The ditial input count.
+ */
+CHDRGET(Stepper,InputCount,int *count)
+/**
+ * Gets the state of a digital input.
+ * @param phid An attached phidget stepper handle.
+ * @param index The input index.
+ * @param inputState The input state. Possible values are \ref PTRUE and \ref PFALSE.
+ */
+CHDRGETINDEX(Stepper,InputState,int *inputState)
+/**
+ * Set a digital input change handler. This is called when a digital input changes.
+ * @param phid An attached phidget stepper handle.
+ * @param fptr Callback function pointer.
+ * @param userPtr A pointer for use by the user - this value is passed back into the callback function.
+ */
+CHDREVENTINDEX(Stepper,InputChange,int inputState)
+
+/**
+ * Gets the number of motors supported by this controller
+ * @param phid An attached phidget stepper handle.
+ * @param count The motor count.
+ */
+CHDRGET(Stepper,MotorCount,int *count)
+
+/**
+ * Gets the last set acceleration for a motor.
+ * @param phid An attached phidget stepper handle
+ * @param index The motor index.
+ * @param acceleration The acceleration
+ */
+CHDRGETINDEX(Stepper,Acceleration,double *acceleration)
+/**
+ * Sets the acceleration for a motor.
+ * @param phid An attached phidget stepper handle
+ * @param index The motor index.
+ * @param acceleration The acceleration
+ */
+CHDRSETINDEX(Stepper,Acceleration,double acceleration)
+/**
+ * Gets the maximum acceleration supported by a motor
+ * @param phid An attached phidget stepper handle
+ * @param index The motor index.
+ * @param max The maximum acceleration.
+ */
+CHDRGETINDEX(Stepper,AccelerationMax,double *max)
+/**
+ * Gets the minimum acceleration supported by a motor.
+ * @param phid An attached phidget stepper handle
+ * @param index The motor index.
+ * @param min The minimum acceleration
+ */
+CHDRGETINDEX(Stepper,AccelerationMin,double *min)
+
+/**
+ * Gets the last set velocity limit for a motor.
+ * @param phid An attached phidget stepper handle
+ * @param index The motor index.
+ * @param limit The velocity limit.
+ */
+CHDRGETINDEX(Stepper,VelocityLimit,double *limit)
+/**
+ * Sets the velocity limit for a motor.
+ * @param phid An attached phidget stepper handle
+ * @param index The motor index.
+ * @param limit The velocity limit.
+ */
+CHDRSETINDEX(Stepper,VelocityLimit,double limit)
+/**
+ * Gets the current velocity of a motor.
+ * @param phid An attached phidget stepper handle
+ * @param index The motor index.
+ * @param velocity The current velocity.
+ */
+CHDRGETINDEX(Stepper,Velocity,double *velocity)
+/**
+ * Gets the maximum velocity that can be set for a motor.
+ * @param phid An attached phidget stepper handle
+ * @param index The motor index.
+ * @param max The maximum velocity
+ */
+CHDRGETINDEX(Stepper,VelocityMax,double *max)
+/**
+ * Gets the minimum velocity that can be set for a motor.
+ * @param phid An attached phidget stepper handle
+ * @param index The motor index.
+ * @param min The minimum velocity.
+ */
+CHDRGETINDEX(Stepper,VelocityMin,double *min)
+/**
+ * Sets a velocity change event handler. This is called when the velocity changes.
+ * @param phid An attached phidget stepper handle
+ * @param fptr Callback function pointer.
+ * @param userPtr A pointer for use by the user - this value is passed back into the callback function.
+ */
+CHDREVENTINDEX(Stepper,VelocityChange,double velocity)
+
+/**
+ * Gets the last set target position of a motor.
+ * @param phid An attached phidget stepper handle
+ * @param index The motor index.
+ * @param position The position.
+ */
+CHDRGETINDEX(Stepper,TargetPosition,__int64 *position)
+/**
+ * Sets the target position of a motor.
+ * @param phid An attached phidget stepper handle
+ * @param index The motor index.
+ * @param position The position.
+ */
+CHDRSETINDEX(Stepper,TargetPosition,__int64 position)
+/**
+ * Gets the current position of a motor.
+ * @param phid An attached phidget stepper handle
+ * @param index The motor index.
+ * @param position The position.
+ */
+CHDRGETINDEX(Stepper,CurrentPosition,__int64 *position)
+/**
+ * Sets the current position of a motor. This will not move the motor, just update the position value.
+ * @param phid An attached phidget stepper handle
+ * @param index The motor index.
+ * @param position The position.
+ */
+CHDRSETINDEX(Stepper,CurrentPosition,__int64 position)
+/**
+ * Gets the maximum position that a motor can go to.
+ * @param phid An attached phidget stepper handle
+ * @param index The motor index.
+ * @param max The maximum position.
+ */
+CHDRGETINDEX(Stepper,PositionMax,__int64 *max)
+/**
+ * Gets the minimum position that a motor can go to.
+ * @param phid An attached phidget stepper handle
+ * @param index The motor index.
+ * @param min The minimum position
+ */
+CHDRGETINDEX(Stepper,PositionMin,__int64 *min)
+/**
+ * Sets a position change event handler. This is called when the position changes.
+ * @param phid An attached phidget stepper handle
+ * @param fptr Callback function pointer.
+ * @param userPtr A pointer for use by the user - this value is passed back into the callback function.
+ */
+CHDREVENTINDEX(Stepper,PositionChange,__int64 position)
+
+/**
+ * Gets the current limit for a motor.
+ * @param phid An attached phidget stepper handle.
+ * @param index The motor index.
+ * @param limit The current limit.
+ */
+CHDRGETINDEX(Stepper,CurrentLimit,double *limit)
+/**
+ * Sets the current limit for a motor.
+ * @param phid An attached phidget stepper handle.
+ * @param index The motor index.
+ * @param limit The current limit.
+ */
+CHDRSETINDEX(Stepper,CurrentLimit,double limit)
+/**
+ * Gets the current current draw for a motor.
+ * @param phid An attached phidget stepper handle
+ * @param index The motor index.
+ * @param current The current.
+ */
+CHDRGETINDEX(Stepper,Current,double *current)
+/**
+ * Gets the maximum current limit.
+ * @param phid An attached phidget stepper handle
+ * @param index The motor index.
+ * @param max The maximum current limit.
+ */
+CHDRGETINDEX(Stepper,CurrentMax,double *max)
+/**
+ * Gets the minimum current limit.
+ * @param phid An attached phidget stepper handle
+ * @param index The motor index.
+ * @param min The minimum current limit.
+ */
+CHDRGETINDEX(Stepper,CurrentMin,double *min)
+/**
+ * Sets a current change event handler. This is called when the current draw changes.
+ * @param phid An attached phidget stepper handle
+ * @param fptr Callback function pointer.
+ * @param userPtr A pointer for use by the user - this value is passed back into the callback function.
+ */
+CHDREVENTINDEX(Stepper,CurrentChange,double current)
+
+/**
+ * Gets the engaged state of a motor. This is whether the motor is powered or not.
+ * @param phid An attached phidget stepper handle
+ * @param index The motor index.
+ * @param engagedState The engaged state. Possible values are \ref PTRUE and \ref PFALSE.
+ */
+CHDRGETINDEX(Stepper,Engaged,int *engagedState)
+/**
+ * Sets the engaged state of a motor. This is whether the motor is powered or not.
+ * @param phid An attached phidget stepper handle
+ * @param index The motor index.
+ * @param engagedState The engaged state. Possible values are \ref PTRUE and \ref PFALSE.
+ */
+CHDRSETINDEX(Stepper,Engaged,int engagedState)
+/**
+ * Gets the stopped state of a motor. This is true when the motor is not moving and there are no outstanding commands.
+ * @param phid An attached phidget stepper handle
+ * @param index The motor index.
+ * @param stoppedState The stopped state. Possible values are \ref PTRUE and \ref PFALSE.
+ */
+CHDRGETINDEX(Stepper,Stopped,int *stoppedState)
+
+#ifndef EXTERNALPROTO
+
+#define STEPPER_MAXSTEPPERS 8
+#define STEPPER_MAXINPUTS 8
+
+#define BIPOLAR_STEPPER_CURRENT_SENSE_GAIN 8.5
+#define BIPOLAR_STEPPER_CURRENT_LIMIT_Rs 0.150
+
+//flags - make sure these are in the upper 4 bits
+#define MOTOR_DONE_STEPPER 0x10
+#define MOTOR_DISABLED_STEPPER 0x20
+
+//packet types - room for one more
+#define STEPPER_POSITION_PACKET 0x00
+#define STEPPER_VEL_ACCEL_PACKET 0x10
+#define STEPPER_RESET_PACKET 0x20
+
+struct _CPhidgetStepper{
+ CPhidget phid;
+
+ int (CCONV *fptrPositionChange)(CPhidgetStepperHandle, void *, int, __int64);
+ int (CCONV *fptrPositionChange32)(CPhidgetStepperHandle, void *, int, int);
+ int (CCONV *fptrVelocityChange)(CPhidgetStepperHandle, void *, int, double);
+ int (CCONV *fptrCurrentChange)(CPhidgetStepperHandle, void *, int, double);
+ int (CCONV *fptrInputChange)(CPhidgetStepperHandle, void *, int, int);
+
+ void *fptrPositionChangeptr;
+ void *fptrPositionChange32ptr;
+ void *fptrInputChangeptr;
+ void *fptrCurrentChangeptr;
+ void *fptrVelocityChangeptr;
+
+ //data from the device
+ unsigned char inputState[STEPPER_MAXINPUTS];
+ __int64 motorPositionEcho[STEPPER_MAXSTEPPERS];
+ double motorSpeedEcho[STEPPER_MAXSTEPPERS];
+ double motorSensedCurrent[STEPPER_MAXSTEPPERS];
+ unsigned char motorEngagedStateEcho[STEPPER_MAXSTEPPERS];
+ unsigned char motorStoppedState[STEPPER_MAXSTEPPERS];
+ int packetCounterEcho[STEPPER_MAXSTEPPERS];
+
+ //data from the user
+ __int64 motorPosition[STEPPER_MAXSTEPPERS];
+ __int64 motorPositionReset[STEPPER_MAXSTEPPERS];
+ double motorAcceleration[STEPPER_MAXSTEPPERS];
+ double motorSpeed[STEPPER_MAXSTEPPERS];
+ double motorCurrentLimit[STEPPER_MAXSTEPPERS];
+ unsigned char motorEngagedState[STEPPER_MAXSTEPPERS];
+ int packetCounter[STEPPER_MAXSTEPPERS];
+
+ double motorSpeedMax, motorSpeedMin;
+ double accelerationMax, accelerationMin;
+ __int64 motorPositionMax, motorPositionMin;
+ double currentMax, currentMin;
+ int microSteps;
+
+ unsigned char outputPacket[8];
+ unsigned int outputPacketLen;
+} typedef CPhidgetStepperInfo;
+#endif
+
+/** @} */
+
+#endif
+
diff --git a/cphidgettemperaturesensor.c b/cphidgettemperaturesensor.c
new file mode 100644
index 0000000..2d92953
--- /dev/null
+++ b/cphidgettemperaturesensor.c
@@ -0,0 +1,1319 @@
+#include "stdafx.h"
+#include "cphidgettemperaturesensor.h"
+#include <math.h>
+#include "cusb.h"
+#include "csocket.h"
+#include "cthread.h"
+
+// === Internal Functions === //
+
+double lookup_voltage(double Tjunction, CPhidgetTemperatureSensor_ThermocoupleType type);
+double lookup_temperature(double Vthermocouple, CPhidgetTemperatureSensor_ThermocoupleType type);
+
+//Range on either side of 0 for the thermocouple tables
+// - this is difference is degrees Celcius between junction and tip temperature.
+// ie. if the board is at 100C, the lowest you could measure is -170C.
+const int thermocouple_table_range[5][2] =
+{
+ {0,0},//null
+ {-270, 1372}, //Type K
+ {-210, 1200}, //Type J
+ {-270, 1000}, //Type E
+ {-270, 400} //Type T
+};
+//Useful measurement range for each type of thermocouple
+// - this is the actual absolute temperature at the thermocouple tip, in degrees Celcius.
+//These ranges are "Maximum Useful Temperature Range" specified here: http://www.omega.com/techref/colorcodes.html
+const int thermocouple_useful_range[5][2] =
+{
+ {0,0},//null
+ {-200, 1250}, //Type K
+ {0, 750}, //Type J
+ {-200, 900}, //Type E
+ {-200, 350} //Type T
+};
+
+//clearVars - sets all device variables to unknown state
+CPHIDGETCLEARVARS(TemperatureSensor)
+ int i = 0;
+
+ phid->ambientTemperatureMax = PUNI_DBL;
+ phid->ambientTemperatureMin = PUNI_DBL;
+ phid->potentialMax = PUNI_DBL;
+ phid->potentialMin = PUNI_DBL;
+ phid->AmbientTemperature = PUNI_DBL;
+
+ for (i = 0; i<TEMPSENSOR_MAXSENSORS; i++)
+ {
+ phid->ThermocoupleType[i] = -1;
+ phid->temperatureMax[i] = PUNI_DBL;
+ phid->temperatureMin[i] = PUNI_DBL;
+ phid->Potential[i] = PUNI_DBL;
+ phid->Temperature[i] = PUNI_DBL;
+ phid->lastTrigger[i] = PUNK_DBL;
+ phid->TempChangeTrigger[i] = PUNI_DBL;
+ }
+
+ return EPHIDGET_OK;
+}
+
+//initAfterOpen - sets up the initial state of an object, reading in packets from the device if needed
+// used during attach initialization - on every attach
+CPHIDGETINIT(TemperatureSensor)
+ int i;
+
+ TESTPTR(phid);
+
+ //Setup max/min values
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_TEMPERATURESENSOR:
+ if(phid->phid.deviceVersion < 200)
+ {
+ for (i = 0; i<phid->phid.attr.temperaturesensor.numTempInputs; i++)
+ {
+ phid->ThermocoupleType[i] = PHIDGET_TEMPERATURE_SENSOR_K_TYPE;
+ phid->temperatureMax[i] = thermocouple_useful_range[PHIDGET_TEMPERATURE_SENSOR_K_TYPE][1];
+ phid->temperatureMin[i] = thermocouple_useful_range[PHIDGET_TEMPERATURE_SENSOR_K_TYPE][0];
+ }
+ phid->ambientTemperatureMax = 125;
+ phid->ambientTemperatureMin = -40;
+ }
+ else if(phid->phid.deviceVersion >= 200 && phid->phid.deviceVersion < 300)
+ {
+ for (i = 0; i<phid->phid.attr.temperaturesensor.numTempInputs; i++)
+ {
+ phid->ThermocoupleType[i] = PHIDGET_TEMPERATURE_SENSOR_K_TYPE;
+ phid->temperatureMax[i] = thermocouple_useful_range[PHIDGET_TEMPERATURE_SENSOR_K_TYPE][1];
+ phid->temperatureMin[i] = thermocouple_useful_range[PHIDGET_TEMPERATURE_SENSOR_K_TYPE][0];
+ }
+ phid->ambientTemperatureMax = 125;
+ phid->ambientTemperatureMin = -40;
+ phid->potentialMax = round_double((((5 / GAIN) * 1000.0) + OFFSET_200), 5);
+ phid->potentialMin = round_double(((((5 - (65535.0 / 13104.0)) / GAIN) * 1000.0) + OFFSET_200), 5);
+ }
+ else if(phid->phid.deviceVersion >= 300 && phid->phid.deviceVersion < 400)
+ {
+ for (i = 0; i<phid->phid.attr.temperaturesensor.numTempInputs; i++)
+ {
+ phid->ThermocoupleType[i] = PHIDGET_TEMPERATURE_SENSOR_K_TYPE;
+ phid->temperatureMax[i] = thermocouple_useful_range[PHIDGET_TEMPERATURE_SENSOR_K_TYPE][1];
+ phid->temperatureMin[i] = thermocouple_useful_range[PHIDGET_TEMPERATURE_SENSOR_K_TYPE][0];
+ }
+ phid->ambientTemperatureMax = 150;
+ phid->ambientTemperatureMin = -50;
+ phid->potentialMax = round_double((-((-OFFSET_300) / GAIN) * 1000.0), 5);
+ phid->potentialMin = round_double((-(((65535.0 / 13104.0) - OFFSET_300) / GAIN) * 1000.0), 5);
+ }
+ else if(phid->phid.deviceVersion >= 400 && phid->phid.deviceVersion < 500)
+ {
+ for (i = 0; i<phid->phid.attr.temperaturesensor.numTempInputs; i++)
+ {
+ phid->ThermocoupleType[i] = PHIDGET_TEMPERATURE_SENSOR_K_TYPE;
+ phid->temperatureMax[i] = thermocouple_useful_range[PHIDGET_TEMPERATURE_SENSOR_K_TYPE][1];
+ phid->temperatureMin[i] = thermocouple_useful_range[PHIDGET_TEMPERATURE_SENSOR_K_TYPE][0];
+ }
+ phid->ambientTemperatureMax = 150;
+ phid->ambientTemperatureMin = -55;
+ phid->potentialMin = round_double((((0.23 - PHIDID_TEMPERATURESENSOR_4_OFFSET) / PHIDID_TEMPERATURESENSOR_4_GAIN) * 1000.0), 5);
+ phid->potentialMax = round_double((((3.846 - PHIDID_TEMPERATURESENSOR_4_OFFSET) / PHIDID_TEMPERATURESENSOR_4_GAIN) * 1000.0), 5);
+ }
+ else
+ return EPHIDGET_BADVERSION;
+ break;
+ case PHIDID_TEMPERATURESENSOR_4:
+ if(phid->phid.deviceVersion >= 100 && phid->phid.deviceVersion < 200)
+ {
+ for (i = 0; i<phid->phid.attr.temperaturesensor.numTempInputs; i++)
+ {
+ phid->ThermocoupleType[i] = PHIDGET_TEMPERATURE_SENSOR_K_TYPE;
+ phid->temperatureMax[i] = thermocouple_useful_range[PHIDGET_TEMPERATURE_SENSOR_K_TYPE][1];
+ phid->temperatureMin[i] = thermocouple_useful_range[PHIDGET_TEMPERATURE_SENSOR_K_TYPE][0];
+ }
+ phid->ambientTemperatureMax = 150;
+ phid->ambientTemperatureMin = -55;
+ phid->potentialMin = round_double((((0.23 - PHIDID_TEMPERATURESENSOR_4_OFFSET) / PHIDID_TEMPERATURESENSOR_4_GAIN) * 1000.0), 5);
+ phid->potentialMax = round_double((((3.846 - PHIDID_TEMPERATURESENSOR_4_OFFSET) / PHIDID_TEMPERATURESENSOR_4_GAIN) * 1000.0), 5);
+ }
+ else
+ return EPHIDGET_BADVERSION;
+ break;
+ case PHIDID_TEMPERATURESENSOR_IR:
+ if(phid->phid.deviceVersion >= 100 && phid->phid.deviceVersion < 200)
+ {
+ for (i = 0; i<phid->phid.attr.temperaturesensor.numTempInputs; i++)
+ {
+ phid->temperatureMax[i] = 380;
+ phid->temperatureMin[i] = -70;
+ }
+ phid->ambientTemperatureMax = 125;
+ phid->ambientTemperatureMin = -40;
+ }
+ else
+ return EPHIDGET_BADVERSION;
+ break;
+ default:
+ return EPHIDGET_UNEXPECTED;
+ }
+
+ //initialize triggers, set data arrays to unknown
+ for (i = 0; i<phid->phid.attr.temperaturesensor.numTempInputs; i++)
+ {
+ phid->PotentialError[i] = PFALSE;
+ phid->TemperatureError[i] = PFALSE;
+ phid->Potential[i] = PUNK_DBL;
+ phid->Temperature[i] = PUNK_DBL;
+ phid->lastTrigger[i] = PUNK_DBL;
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_TEMPERATURESENSOR:
+ phid->TempChangeTrigger[i] = 0.5;
+ break;
+ case PHIDID_TEMPERATURESENSOR_4:
+ case PHIDID_TEMPERATURESENSOR_IR:
+ phid->TempChangeTrigger[i] = 0.1;
+ break;
+ default:
+ break;
+ }
+ }
+ phid->AmbientTemperature = PUNK_DBL;
+ phid->AmbientTemperatureError = PFALSE;
+
+ //issue one read
+ CPhidget_read((CPhidgetHandle)phid);
+
+ return EPHIDGET_OK;
+}
+
+//dataInput - parses device packets
+CPHIDGETDATA(TemperatureSensor)
+ int i = 0;
+ double Vad = 0, Vthermocouple = 0, VtempIC = 0, Temp;
+ double Temperature[TEMPSENSOR_MAXSENSORS] = {0}, Potential[TEMPSENSOR_MAXSENSORS] = {0}, AmbientTemperature = 0;
+ char error_buffer[200];
+
+ if (length<0) return EPHIDGET_INVALIDARG;
+ TESTPTR(phid);
+ TESTPTR(buffer);
+
+ ZEROMEM(Temperature, sizeof(Temperature));
+ ZEROMEM(Potential, sizeof(Potential));
+
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_TEMPERATURESENSOR:
+ /* OLD version */
+ if(phid->phid.deviceVersion < 200)
+ {
+ AmbientTemperature = (double)((short)buffer[2]);
+ Temperature[0] = (double)((signed short)((unsigned short)buffer[0]+((unsigned short)buffer[1]<<8)));
+ }
+ /* newer versions... calculate the temp here from Vad */
+ else if(phid->phid.deviceVersion >= 200 && phid->phid.deviceVersion < 300) {
+ //The ambient sensor reading from firmware isn't being sign-extended properly!
+ if(buffer[3] & 0x40)
+ buffer[3] |= 0x80;
+ if(buffer[3] & 0x30)
+ buffer[3] |= 0xf0;
+ AmbientTemperature = (double)((signed short)((unsigned short)buffer[2]+((unsigned short)buffer[3]<<8))) / 64.0;
+ printf("Ambient: 0x%02x%02x\n",buffer[3],buffer[2]);
+ Vad = ((double)((unsigned short)buffer[0]+((unsigned short)buffer[1]<<8))) / 13104.0;
+
+ Potential[0] = round_double(((((5 - Vad) / GAIN) * 1000.0) + OFFSET_200), 5);
+
+ //This is the potential at the thermocouple tip - with the junction potential eliminated
+ Vthermocouple = Potential[0] + lookup_voltage(AmbientTemperature, phid->ThermocoupleType[0]);
+ Temp = lookup_temperature(Vthermocouple, phid->ThermocoupleType[0]);
+ if(Temp != PUNK_DBL)
+ Temperature[0] = round_double(Temp, 3);
+ else
+ Temperature[0] = PUNK_DBL;
+
+ }
+ //upgrade to MCP3202 and AD22100
+ else if(phid->phid.deviceVersion >= 300 && phid->phid.deviceVersion < 400)
+ {
+ //Temp IC - absolute possible range: -61.1 - 161.16
+ VtempIC = ((double)((unsigned short)buffer[2]+((unsigned short)buffer[3]<<8))) / 13104.0;
+ AmbientTemperature = round_double(((VtempIC - 1.375)/0.0225), 3);
+
+ //Thermocouple
+ Vad = ((double)((unsigned short)buffer[0]+((unsigned short)buffer[1]<<8))) / 13104.0;
+ Potential[0] = round_double((-((Vad - OFFSET_300) / GAIN) * 1000.0), 5);
+
+ //This is the potential at the thermocouple tip - with the junction potential eliminated
+ Vthermocouple = Potential[0] + lookup_voltage(AmbientTemperature, phid->ThermocoupleType[0]);
+ Temp = lookup_temperature(Vthermocouple, phid->ThermocoupleType[0]);
+ if(Temp != PUNK_DBL)
+ Temperature[0] = round_double(Temp, 4);
+ else
+ Temperature[0] = PUNK_DBL;
+ }
+ else if(phid->phid.deviceVersion >= 400 && phid->phid.deviceVersion < 500)
+ {
+ //Temp IC - absolute possible range: -61.1 - 161.16
+ AmbientTemperature = round_double(((short)(((short)buffer[2] << 8) + (buffer[3])) / 128.0), 4);
+
+ //Thermocouple
+ Vad = ((double)((unsigned short)buffer[1]+((unsigned short)buffer[0]<<8))) / 16000.0;
+ Potential[0] = round_double((((Vad - PHIDID_TEMPERATURESENSOR_4_OFFSET) / PHIDID_TEMPERATURESENSOR_4_GAIN) * 1000.0), 5);
+
+ //This is the potential at the thermocouple tip - with the junction potential eliminated
+ Vthermocouple = Potential[0] + lookup_voltage(AmbientTemperature, phid->ThermocoupleType[0]);
+ Temp = lookup_temperature(Vthermocouple, phid->ThermocoupleType[0]);
+ if(Temp != PUNK_DBL)
+ Temperature[0] = round_double(Temp, 4);
+ else
+ Temperature[0] = PUNK_DBL;
+ }
+ else
+ return EPHIDGET_UNEXPECTED;
+ break;
+ case PHIDID_TEMPERATURESENSOR_4:
+ if(phid->phid.deviceVersion >= 100 && phid->phid.deviceVersion < 200)
+ {
+ //Temp IC - absolute possible range: -61.1 - 161.16
+ AmbientTemperature = round_double(((short)(((short)buffer[8] << 8) + (buffer[9])) / 128.0), 4);
+ for (i = 0; i<phid->phid.attr.temperaturesensor.numTempInputs; i++)
+ {
+ //Thermocouple
+ Vad = ((double)((unsigned short)buffer[1+2*i]+((unsigned short)buffer[0+2*i]<<8))) / 16000.0;
+ Potential[i] = round_double((((Vad - PHIDID_TEMPERATURESENSOR_4_OFFSET) / PHIDID_TEMPERATURESENSOR_4_GAIN) * 1000.0), 5);
+
+ //This is the potential at the thermocouple tip - with the junction potential eliminated
+ Vthermocouple = Potential[i] + lookup_voltage(AmbientTemperature, phid->ThermocoupleType[i]);
+ Temp = lookup_temperature(Vthermocouple, phid->ThermocoupleType[i]);
+ if(Temp != PUNK_DBL)
+ Temperature[i] = round_double(Temp, 4);
+ else
+ Temperature[i] = PUNK_DBL;
+ //LOG(PHIDGET_LOG_DEBUG, "Index: %d Val: %08x Potential: %0.6lf", i, ((unsigned short)buffer[1+2*i]+((unsigned short)buffer[0+2*i]<<8)), Potential[i]);
+ }
+ }
+ else
+ return EPHIDGET_UNEXPECTED;
+ break;
+ case PHIDID_TEMPERATURESENSOR_IR:
+ if(phid->phid.deviceVersion >= 100 && phid->phid.deviceVersion < 200)
+ {
+ //Temp IC - absolute possible range: -61.1 - 161.16
+ AmbientTemperature = round_double(((((short)buffer[3] << 8) + buffer[2]) * 0.02) - 273.15, 2);
+ Temperature[0] = round_double(((((short)buffer[1] << 8) + buffer[0]) * 0.02) - 273.15, 2);
+ }
+ else
+ return EPHIDGET_UNEXPECTED;
+ break;
+ default:
+ return EPHIDGET_UNEXPECTED;
+ }
+
+ //Make sure values are within defined range, and store to structure
+ if(AmbientTemperature > phid->ambientTemperatureMax)
+ {
+ phid->AmbientTemperature = PUNK_DBL;
+ if (phid->AmbientTemperatureError == PFALSE)
+ {
+ phid->AmbientTemperatureError = PTRUE;
+ FIRE_ERROR(EEPHIDGET_OUTOFRANGE, "Ambient sensor reported a temperature of %.4fC which is over the maximum of %.4fC.",
+ AmbientTemperature, phid->ambientTemperatureMax);
+ }
+ }
+ else if(AmbientTemperature < phid->ambientTemperatureMin)
+ {
+ phid->AmbientTemperature = PUNK_DBL;
+ if (phid->AmbientTemperatureError == PFALSE)
+ {
+ phid->AmbientTemperatureError = PTRUE;
+ FIRE_ERROR(EEPHIDGET_OUTOFRANGE, "Ambient sensor reported a temperature of %.4fC which is below the minimum of %.4fC.",
+ AmbientTemperature, phid->ambientTemperatureMin);
+ }
+ }
+ else
+ {
+ phid->AmbientTemperature = AmbientTemperature;
+ phid->AmbientTemperatureError = PFALSE;
+
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_TEMPERATURESENSOR:
+ if(phid->phid.deviceVersion < 200)
+ break; //OLD version just reports a temperature
+ case PHIDID_TEMPERATURESENSOR_4:
+ //Recalibrate min/max temperatures depending on ambient temperature
+ for (i = 0; i<phid->phid.attr.temperaturesensor.numTempInputs; i++)
+ {
+ if(lookup_voltage(thermocouple_useful_range[phid->ThermocoupleType[i]][1] - phid->AmbientTemperature, phid->ThermocoupleType[i]) > phid->potentialMax)
+ phid->temperatureMax[i] = (int)((lookup_temperature(phid->potentialMax, phid->ThermocoupleType[i]) + phid->AmbientTemperature) / 10) * 10;
+ if(lookup_voltage(thermocouple_useful_range[phid->ThermocoupleType[i]][0] - phid->AmbientTemperature, phid->ThermocoupleType[i]) < phid->potentialMin)
+ phid->temperatureMin[i] = (int)((lookup_temperature(phid->potentialMin, phid->ThermocoupleType[i]) + phid->AmbientTemperature) / 10) * 10;
+ }
+ break;
+ case PHIDID_TEMPERATURESENSOR_IR:
+ default:
+ break;
+ }
+ }
+
+ for (i = 0; i<phid->phid.attr.temperaturesensor.numTempInputs; i++)
+ {
+ //If ambient temperature was outside of allowed range, then calculated temperature will be wrong
+ if(phid->AmbientTemperature == PUNK_DBL)
+ {
+ phid->Temperature[i] = PUNK_DBL;
+ if (phid->TemperatureError[i] == PFALSE)
+ {
+ phid->TemperatureError[i] = PTRUE;
+ FIRE_ERROR(EEPHIDGET_OUTOFRANGE,
+ "Temperature %d cannot be calculated because the ambient temperature is unknown.",
+ i);
+ }
+ }
+ else if(Temperature[i] == PUNK_DBL)
+ {
+ phid->Temperature[i] = PUNK_DBL;
+ if (phid->TemperatureError[i] == PFALSE)
+ {
+ phid->TemperatureError[i] = PTRUE;
+ FIRE_ERROR(EEPHIDGET_OUTOFRANGE,
+ "Input %d reported an undefined temperature. Probably there is no thermocouple plugged in.",
+ i);
+ }
+ }
+ else if(Temperature[i] > phid->temperatureMax[i])
+ {
+ phid->Temperature[i] = PUNK_DBL;
+ if (phid->TemperatureError[i] == PFALSE)
+ {
+ phid->TemperatureError[i] = PTRUE;
+ FIRE_ERROR(EEPHIDGET_OUTOFRANGE,
+ "Input %d reported a temperature of %.4fC which is above the maximum of %.4fC.",
+ i, Temperature[i], phid->temperatureMax[i]);
+ }
+ }
+ else if(Temperature[i] < phid->temperatureMin[i])
+ {
+ phid->Temperature[i] = PUNK_DBL;
+ if (phid->TemperatureError[i] == PFALSE)
+ {
+ phid->TemperatureError[i] = PTRUE;
+ FIRE_ERROR(EEPHIDGET_OUTOFRANGE,
+ "Input %d reported a temperature of %.4fC which is below the minimum of %.4fC.",
+ i, Temperature[i], phid->temperatureMin[i]);
+ }
+ }
+ else
+ {
+ phid->Temperature[i] = Temperature[i];
+ phid->TemperatureError[i] = PFALSE;
+ }
+
+ //Potential only on the thermocouple versions
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_TEMPERATURESENSOR:
+ case PHIDID_TEMPERATURESENSOR_4:
+ if(Potential[i] > phid->potentialMax)
+ {
+ phid->Potential[i] = PUNK_DBL;
+ if (phid->PotentialError[i] == PFALSE)
+ {
+ phid->PotentialError[i] = PTRUE;
+ FIRE_ERROR(EEPHIDGET_OUTOFRANGE,
+ "Thermocouple %d reported a potential of %.4fmV which is above the maximum of %.4fmV.",
+ i, Potential[i], phid->potentialMax);
+ }
+ }
+ else if(Potential[i] < phid->potentialMin)
+ {
+ phid->Potential[i] = PUNK_DBL;
+ if (phid->PotentialError[i] == PFALSE)
+ {
+ phid->PotentialError[i] = PTRUE;
+ FIRE_ERROR(EEPHIDGET_OUTOFRANGE,
+ "Thermocouple %d reported a potential of %.4fmV which is below the minimum of %.4fmV.",
+ i, Potential[i], phid->potentialMin);
+ }
+ }
+ else
+ {
+ phid->Potential[i] = Potential[i];
+ phid->PotentialError[i] = PFALSE;
+ }
+ break;
+ case PHIDID_TEMPERATURESENSOR_IR:
+ default:
+ break;
+ }
+ }
+
+ //send out any events that exceed or match the trigger
+ for (i = 0; i<phid->phid.attr.temperaturesensor.numTempInputs; i++)
+ {
+ if ((fabs(phid->Temperature[i] - phid->lastTrigger[i]) >= phid->TempChangeTrigger[i] || phid->lastTrigger[i] == PUNK_DBL)
+ && phid->Temperature[i] != PUNK_DBL)
+ {
+ FIRE(TemperatureChange, i, phid->Temperature[i]);
+ phid->lastTrigger[i] = phid->Temperature[i];
+ }
+ }
+
+ return EPHIDGET_OK;
+}
+
+//eventsAfterOpen - sends out an event for all valid data, used during attach initialization
+CPHIDGETINITEVENTS(TemperatureSensor)
+
+ for (i = 0; i<phid->phid.attr.temperaturesensor.numTempInputs; i++)
+ {
+ if(phid->Temperature[i] != PUNK_DBL)
+ FIRE(TemperatureChange, i, phid->Temperature[i]);
+ }
+ return EPHIDGET_OK;
+}
+
+//getPacket - not used for TemperatureSensor
+CGETPACKET(TemperatureSensor)
+ return EPHIDGET_UNEXPECTED;
+}
+
+#define THERMOCOUPLE_TABLE_E_SIZE 1271
+//-270 to 1000 in degrees celcius increments
+const double thermocouple_table_e_type[THERMOCOUPLE_TABLE_E_SIZE] = {
+-9.835, -9.833, -9.831, -9.828, -9.825, -9.821, -9.817, -9.813, -9.808, -9.802,
+-9.797, -9.790, -9.784, -9.777, -9.770, -9.762, -9.754, -9.746, -9.737, -9.728,
+-9.718, -9.709, -9.698, -9.688, -9.677, -9.666, -9.654, -9.642, -9.630, -9.617,
+-9.604, -9.591, -9.577, -9.563, -9.548, -9.534, -9.519, -9.503, -9.487, -9.471,
+-9.455, -9.438, -9.421, -9.404, -9.386, -9.368, -9.350, -9.331, -9.313, -9.293,
+-9.274, -9.254, -9.234, -9.214, -9.193, -9.172, -9.151, -9.129, -9.107, -9.085,
+-9.063, -9.040, -9.017, -8.994, -8.971, -8.947, -8.923, -8.899, -8.874, -8.850,
+-8.825, -8.799, -8.774, -8.748, -8.722, -8.696, -8.669, -8.643, -8.616, -8.588,
+-8.561, -8.533, -8.505, -8.477, -8.449, -8.420, -8.391, -8.362, -8.333, -8.303,
+-8.273, -8.243, -8.213, -8.183, -8.152, -8.121, -8.090, -8.059, -8.027, -7.995,
+-7.963, -7.931, -7.899, -7.866, -7.833, -7.800, -7.767, -7.733, -7.700, -7.666,
+-7.632, -7.597, -7.563, -7.528, -7.493, -7.458, -7.423, -7.387, -7.351, -7.315,
+-7.279, -7.243, -7.206, -7.170, -7.133, -7.096, -7.058, -7.021, -6.983, -6.945,
+-6.907, -6.869, -6.831, -6.792, -6.753, -6.714, -6.675, -6.636, -6.596, -6.556,
+-6.516, -6.476, -6.436, -6.396, -6.355, -6.314, -6.273, -6.232, -6.191, -6.149,
+-6.107, -6.065, -6.023, -5.981, -5.939, -5.896, -5.853, -5.810, -5.767, -5.724,
+-5.681, -5.637, -5.593, -5.549, -5.505, -5.461, -5.417, -5.372, -5.327, -5.282,
+-5.237, -5.192, -5.147, -5.101, -5.055, -5.009, -4.963, -4.917, -4.871, -4.824,
+-4.777, -4.731, -4.684, -4.636, -4.589, -4.542, -4.494, -4.446, -4.398, -4.350,
+-4.302, -4.254, -4.205, -4.156, -4.107, -4.058, -4.009, -3.960, -3.911, -3.861,
+-3.811, -3.761, -3.711, -3.661, -3.611, -3.561, -3.510, -3.459, -3.408, -3.357,
+-3.306, -3.255, -3.204, -3.152, -3.100, -3.048, -2.996, -2.944, -2.892, -2.840,
+-2.787, -2.735, -2.682, -2.629, -2.576, -2.523, -2.469, -2.416, -2.362, -2.309,
+-2.255, -2.201, -2.147, -2.093, -2.038, -1.984, -1.929, -1.874, -1.820, -1.765,
+-1.709, -1.654, -1.599, -1.543, -1.488, -1.432, -1.376, -1.320, -1.264, -1.208,
+-1.152, -1.095, -1.039, -0.982, -0.925, -0.868, -0.811, -0.754, -0.697, -0.639,
+-0.582, -0.524, -0.466, -0.408, -0.350, -0.292, -0.234, -0.176, -0.117, -0.059,
+0.000, 0.059, 0.118, 0.176, 0.235, 0.294, 0.354, 0.413, 0.472, 0.532,
+0.591, 0.651, 0.711, 0.770, 0.830, 0.890, 0.950, 1.010, 1.071, 1.131,
+1.192, 1.252, 1.313, 1.373, 1.434, 1.495, 1.556, 1.617, 1.678, 1.740,
+1.801, 1.862, 1.924, 1.986, 2.047, 2.109, 2.171, 2.233, 2.295, 2.357,
+2.420, 2.482, 2.545, 2.607, 2.670, 2.733, 2.795, 2.858, 2.921, 2.984,
+3.048, 3.111, 3.174, 3.238, 3.301, 3.365, 3.429, 3.492, 3.556, 3.620,
+3.685, 3.749, 3.813, 3.877, 3.942, 4.006, 4.071, 4.136, 4.200, 4.265,
+4.330, 4.395, 4.460, 4.526, 4.591, 4.656, 4.722, 4.788, 4.853, 4.919,
+4.985, 5.051, 5.117, 5.183, 5.249, 5.315, 5.382, 5.448, 5.514, 5.581,
+5.648, 5.714, 5.781, 5.848, 5.915, 5.982, 6.049, 6.117, 6.184, 6.251,
+6.319, 6.386, 6.454, 6.522, 6.590, 6.658, 6.725, 6.794, 6.862, 6.930,
+6.998, 7.066, 7.135, 7.203, 7.272, 7.341, 7.409, 7.478, 7.547, 7.616,
+7.685, 7.754, 7.823, 7.892, 7.962, 8.031, 8.101, 8.170, 8.240, 8.309,
+8.379, 8.449, 8.519, 8.589, 8.659, 8.729, 8.799, 8.869, 8.940, 9.010,
+9.081, 9.151, 9.222, 9.292, 9.363, 9.434, 9.505, 9.576, 9.647, 9.718,
+9.789, 9.860, 9.931, 10.003, 10.074, 10.145, 10.217, 10.288, 10.360, 10.432,
+10.503, 10.575, 10.647, 10.719, 10.791, 10.863, 10.935, 11.007, 11.080, 11.152,
+11.224, 11.297, 11.369, 11.442, 11.514, 11.587, 11.660, 11.733, 11.805, 11.878,
+11.951, 12.024, 12.097, 12.170, 12.243, 12.317, 12.390, 12.463, 12.537, 12.610,
+12.684, 12.757, 12.831, 12.904, 12.978, 13.052, 13.126, 13.199, 13.273, 13.347,
+13.421, 13.495, 13.569, 13.644, 13.718, 13.792, 13.866, 13.941, 14.015, 14.090,
+14.164, 14.239, 14.313, 14.388, 14.463, 14.537, 14.612, 14.687, 14.762, 14.837,
+14.912, 14.987, 15.062, 15.137, 15.212, 15.287, 15.362, 15.438, 15.513, 15.588,
+15.664, 15.739, 15.815, 15.890, 15.966, 16.041, 16.117, 16.193, 16.269, 16.344,
+16.420, 16.496, 16.572, 16.648, 16.724, 16.800, 16.876, 16.952, 17.028, 17.104,
+17.181, 17.257, 17.333, 17.409, 17.486, 17.562, 17.639, 17.715, 17.792, 17.868,
+17.945, 18.021, 18.098, 18.175, 18.252, 18.328, 18.405, 18.482, 18.559, 18.636,
+18.713, 18.790, 18.867, 18.944, 19.021, 19.098, 19.175, 19.252, 19.330, 19.407,
+19.484, 19.561, 19.639, 19.716, 19.794, 19.871, 19.948, 20.026, 20.103, 20.181,
+20.259, 20.336, 20.414, 20.492, 20.569, 20.647, 20.725, 20.803, 20.880, 20.958,
+21.036, 21.114, 21.192, 21.270, 21.348, 21.426, 21.504, 21.582, 21.660, 21.739,
+21.817, 21.895, 21.973, 22.051, 22.130, 22.208, 22.286, 22.365, 22.443, 22.522,
+22.600, 22.678, 22.757, 22.835, 22.914, 22.993, 23.071, 23.150, 23.228, 23.307,
+23.386, 23.464, 23.543, 23.622, 23.701, 23.780, 23.858, 23.937, 24.016, 24.095,
+24.174, 24.253, 24.332, 24.411, 24.490, 24.569, 24.648, 24.727, 24.806, 24.885,
+24.964, 25.044, 25.123, 25.202, 25.281, 25.360, 25.440, 25.519, 25.598, 25.678,
+25.757, 25.836, 25.916, 25.995, 26.075, 26.154, 26.233, 26.313, 26.392, 26.472,
+26.552, 26.631, 26.711, 26.790, 26.870, 26.950, 27.029, 27.109, 27.189, 27.268,
+27.348, 27.428, 27.507, 27.587, 27.667, 27.747, 27.827, 27.907, 27.986, 28.066,
+28.146, 28.226, 28.306, 28.386, 28.466, 28.546, 28.626, 28.706, 28.786, 28.866,
+28.946, 29.026, 29.106, 29.186, 29.266, 29.346, 29.427, 29.507, 29.587, 29.667,
+29.747, 29.827, 29.908, 29.988, 30.068, 30.148, 30.229, 30.309, 30.389, 30.470,
+30.550, 30.630, 30.711, 30.791, 30.871, 30.952, 31.032, 31.112, 31.193, 31.273,
+31.354, 31.434, 31.515, 31.595, 31.676, 31.756, 31.837, 31.917, 31.998, 32.078,
+32.159, 32.239, 32.320, 32.400, 32.481, 32.562, 32.642, 32.723, 32.803, 32.884,
+32.965, 33.045, 33.126, 33.207, 33.287, 33.368, 33.449, 33.529, 33.610, 33.691,
+33.772, 33.852, 33.933, 34.014, 34.095, 34.175, 34.256, 34.337, 34.418, 34.498,
+34.579, 34.660, 34.741, 34.822, 34.902, 34.983, 35.064, 35.145, 35.226, 35.307,
+35.387, 35.468, 35.549, 35.630, 35.711, 35.792, 35.873, 35.954, 36.034, 36.115,
+36.196, 36.277, 36.358, 36.439, 36.520, 36.601, 36.682, 36.763, 36.843, 36.924,
+37.005, 37.086, 37.167, 37.248, 37.329, 37.410, 37.491, 37.572, 37.653, 37.734,
+37.815, 37.896, 37.977, 38.058, 38.139, 38.220, 38.300, 38.381, 38.462, 38.543,
+38.624, 38.705, 38.786, 38.867, 38.948, 39.029, 39.110, 39.191, 39.272, 39.353,
+39.434, 39.515, 39.596, 39.677, 39.758, 39.839, 39.920, 40.001, 40.082, 40.163,
+40.243, 40.324, 40.405, 40.486, 40.567, 40.648, 40.729, 40.810, 40.891, 40.972,
+41.053, 41.134, 41.215, 41.296, 41.377, 41.457, 41.538, 41.619, 41.700, 41.781,
+41.862, 41.943, 42.024, 42.105, 42.185, 42.266, 42.347, 42.428, 42.509, 42.590,
+42.671, 42.751, 42.832, 42.913, 42.994, 43.075, 43.156, 43.236, 43.317, 43.398,
+43.479, 43.560, 43.640, 43.721, 43.802, 43.883, 43.963, 44.044, 44.125, 44.206,
+44.286, 44.367, 44.448, 44.529, 44.609, 44.690, 44.771, 44.851, 44.932, 45.013,
+45.093, 45.174, 45.255, 45.335, 45.416, 45.497, 45.577, 45.658, 45.738, 45.819,
+45.900, 45.980, 46.061, 46.141, 46.222, 46.302, 46.383, 46.463, 46.544, 46.624,
+46.705, 46.785, 46.866, 46.946, 47.027, 47.107, 47.188, 47.268, 47.349, 47.429,
+47.509, 47.590, 47.670, 47.751, 47.831, 47.911, 47.992, 48.072, 48.152, 48.233,
+48.313, 48.393, 48.474, 48.554, 48.634, 48.715, 48.795, 48.875, 48.955, 49.035,
+49.116, 49.196, 49.276, 49.356, 49.436, 49.517, 49.597, 49.677, 49.757, 49.837,
+49.917, 49.997, 50.077, 50.157, 50.238, 50.318, 50.398, 50.478, 50.558, 50.638,
+50.718, 50.798, 50.878, 50.958, 51.038, 51.118, 51.197, 51.277, 51.357, 51.437,
+51.517, 51.597, 51.677, 51.757, 51.837, 51.916, 51.996, 52.076, 52.156, 52.236,
+52.315, 52.395, 52.475, 52.555, 52.634, 52.714, 52.794, 52.873, 52.953, 53.033,
+53.112, 53.192, 53.272, 53.351, 53.431, 53.510, 53.590, 53.670, 53.749, 53.829,
+53.908, 53.988, 54.067, 54.147, 54.226, 54.306, 54.385, 54.465, 54.544, 54.624,
+54.703, 54.782, 54.862, 54.941, 55.021, 55.100, 55.179, 55.259, 55.338, 55.417,
+55.497, 55.576, 55.655, 55.734, 55.814, 55.893, 55.972, 56.051, 56.131, 56.210,
+56.289, 56.368, 56.447, 56.526, 56.606, 56.685, 56.764, 56.843, 56.922, 57.001,
+57.080, 57.159, 57.238, 57.317, 57.396, 57.475, 57.554, 57.633, 57.712, 57.791,
+57.870, 57.949, 58.028, 58.107, 58.186, 58.265, 58.343, 58.422, 58.501, 58.580,
+58.659, 58.738, 58.816, 58.895, 58.974, 59.053, 59.131, 59.210, 59.289, 59.367,
+59.446, 59.525, 59.604, 59.682, 59.761, 59.839, 59.918, 59.997, 60.075, 60.154,
+60.232, 60.311, 60.390, 60.468, 60.547, 60.625, 60.704, 60.782, 60.860, 60.939,
+61.017, 61.096, 61.174, 61.253, 61.331, 61.409, 61.488, 61.566, 61.644, 61.723,
+61.801, 61.879, 61.958, 62.036, 62.114, 62.192, 62.271, 62.349, 62.427, 62.505,
+62.583, 62.662, 62.740, 62.818, 62.896, 62.974, 63.052, 63.130, 63.208, 63.286,
+63.364, 63.442, 63.520, 63.598, 63.676, 63.754, 63.832, 63.910, 63.988, 64.066,
+64.144, 64.222, 64.300, 64.377, 64.455, 64.533, 64.611, 64.689, 64.766, 64.844,
+64.922, 65.000, 65.077, 65.155, 65.233, 65.310, 65.388, 65.465, 65.543, 65.621,
+65.698, 65.776, 65.853, 65.931, 66.008, 66.086, 66.163, 66.241, 66.318, 66.396,
+66.473, 66.550, 66.628, 66.705, 66.782, 66.860, 66.937, 67.014, 67.092, 67.169,
+67.246, 67.323, 67.400, 67.478, 67.555, 67.632, 67.709, 67.786, 67.863, 67.940,
+68.017, 68.094, 68.171, 68.248, 68.325, 68.402, 68.479, 68.556, 68.633, 68.710,
+68.787, 68.863, 68.940, 69.017, 69.094, 69.171, 69.247, 69.324, 69.401, 69.477,
+69.554, 69.631, 69.707, 69.784, 69.860, 69.937, 70.013, 70.090, 70.166, 70.243,
+70.319, 70.396, 70.472, 70.548, 70.625, 70.701, 70.777, 70.854, 70.930, 71.006,
+71.082, 71.159, 71.235, 71.311, 71.387, 71.463, 71.539, 71.615, 71.692, 71.768,
+71.844, 71.920, 71.996, 72.072, 72.147, 72.223, 72.299, 72.375, 72.451, 72.527,
+72.603, 72.678, 72.754, 72.830, 72.906, 72.981, 73.057, 73.133, 73.208, 73.284,
+73.360, 73.435, 73.511, 73.586, 73.662, 73.738, 73.813, 73.889, 73.964, 74.040,
+74.115, 74.190, 74.266, 74.341, 74.417, 74.492, 74.567, 74.643, 74.718, 74.793,
+74.869, 74.944, 75.019, 75.095, 75.170, 75.245, 75.320, 75.395, 75.471, 75.546,
+75.621, 75.696, 75.771, 75.847, 75.922, 75.997, 76.072, 76.147, 76.223, 76.298,
+76.373};
+
+
+#define THERMOCOUPLE_TABLE_T_SIZE 671
+//-270 to 400 in degrees celcius increments
+const double thermocouple_table_t_type[THERMOCOUPLE_TABLE_T_SIZE] = {
+-6.258, -6.256, -6.255, -6.253, -6.251, -6.248, -6.245, -6.242, -6.239, -6.236,
+-6.232, -6.228, -6.223, -6.219, -6.214, -6.209, -6.204, -6.198, -6.193, -6.187,
+-6.180, -6.174, -6.167, -6.160, -6.153, -6.146, -6.138, -6.130, -6.122, -6.114,
+-6.105, -6.096, -6.087, -6.078, -6.068, -6.059, -6.049, -6.038, -6.028, -6.017,
+-6.007, -5.996, -5.985, -5.973, -5.962, -5.950, -5.938, -5.926, -5.914, -5.901,
+-5.888, -5.876, -5.863, -5.850, -5.836, -5.823, -5.809, -5.795, -5.782, -5.767,
+-5.753, -5.739, -5.724, -5.710, -5.695, -5.680, -5.665, -5.650, -5.634, -5.619,
+-5.603, -5.587, -5.571, -5.555, -5.539, -5.523, -5.506, -5.489, -5.473, -5.456,
+-5.439, -5.421, -5.404, -5.387, -5.369, -5.351, -5.334, -5.316, -5.297, -5.279,
+-5.261, -5.242, -5.224, -5.205, -5.186, -5.167, -5.148, -5.128, -5.109, -5.089,
+-5.070, -5.050, -5.030, -5.010, -4.989, -4.969, -4.949, -4.928, -4.907, -4.886,
+-4.865, -4.844, -4.823, -4.802, -4.780, -4.759, -4.737, -4.715, -4.693, -4.671,
+-4.648, -4.626, -4.604, -4.581, -4.558, -4.535, -4.512, -4.489, -4.466, -4.443,
+-4.419, -4.395, -4.372, -4.348, -4.324, -4.300, -4.275, -4.251, -4.226, -4.202,
+-4.177, -4.152, -4.127, -4.102, -4.077, -4.052, -4.026, -4.000, -3.975, -3.949,
+-3.923, -3.897, -3.871, -3.844, -3.818, -3.791, -3.765, -3.738, -3.711, -3.684,
+-3.657, -3.629, -3.602, -3.574, -3.547, -3.519, -3.491, -3.463, -3.435, -3.407,
+-3.379, -3.350, -3.322, -3.293, -3.264, -3.235, -3.206, -3.177, -3.148, -3.118,
+-3.089, -3.059, -3.030, -3.000, -2.970, -2.940, -2.910, -2.879, -2.849, -2.818,
+-2.788, -2.757, -2.726, -2.695, -2.664, -2.633, -2.602, -2.571, -2.539, -2.507,
+-2.476, -2.444, -2.412, -2.380, -2.348, -2.316, -2.283, -2.251, -2.218, -2.186,
+-2.153, -2.120, -2.087, -2.054, -2.021, -1.987, -1.954, -1.920, -1.887, -1.853,
+-1.819, -1.785, -1.751, -1.717, -1.683, -1.648, -1.614, -1.579, -1.545, -1.510,
+-1.475, -1.440, -1.405, -1.370, -1.335, -1.299, -1.264, -1.228, -1.192, -1.157,
+-1.121, -1.085, -1.049, -1.013, -0.976, -0.940, -0.904, -0.867, -0.830, -0.794,
+-0.757, -0.720, -0.683, -0.646, -0.608, -0.571, -0.534, -0.496, -0.459, -0.421,
+-0.383, -0.345, -0.307, -0.269, -0.231, -0.193, -0.154, -0.116, -0.077, -0.039,
+0.000, 0.039, 0.078, 0.117, 0.156, 0.195, 0.234, 0.273, 0.312, 0.352,
+0.391, 0.431, 0.470, 0.510, 0.549, 0.589, 0.629, 0.669, 0.709, 0.749,
+0.790, 0.830, 0.870, 0.911, 0.951, 0.992, 1.033, 1.074, 1.114, 1.155,
+1.196, 1.238, 1.279, 1.320, 1.362, 1.403, 1.445, 1.486, 1.528, 1.570,
+1.612, 1.654, 1.696, 1.738, 1.780, 1.823, 1.865, 1.908, 1.950, 1.993,
+2.036, 2.079, 2.122, 2.165, 2.208, 2.251, 2.294, 2.338, 2.381, 2.425,
+2.468, 2.512, 2.556, 2.600, 2.643, 2.687, 2.732, 2.776, 2.820, 2.864,
+2.909, 2.953, 2.998, 3.043, 3.087, 3.132, 3.177, 3.222, 3.267, 3.312,
+3.358, 3.403, 3.448, 3.494, 3.539, 3.585, 3.631, 3.677, 3.722, 3.768,
+3.814, 3.860, 3.907, 3.953, 3.999, 4.046, 4.092, 4.138, 4.185, 4.232,
+4.279, 4.325, 4.372, 4.419, 4.466, 4.513, 4.561, 4.608, 4.655, 4.702,
+4.750, 4.798, 4.845, 4.893, 4.941, 4.988, 5.036, 5.084, 5.132, 5.180,
+5.228, 5.277, 5.325, 5.373, 5.422, 5.470, 5.519, 5.567, 5.616, 5.665,
+5.714, 5.763, 5.812, 5.861, 5.910, 5.959, 6.008, 6.057, 6.107, 6.156,
+6.206, 6.255, 6.305, 6.355, 6.404, 6.454, 6.504, 6.554, 6.604, 6.654,
+6.704, 6.754, 6.805, 6.855, 6.905, 6.956, 7.006, 7.057, 7.107, 7.158,
+7.209, 7.260, 7.310, 7.361, 7.412, 7.463, 7.515, 7.566, 7.617, 7.668,
+7.720, 7.771, 7.823, 7.874, 7.926, 7.977, 8.029, 8.081, 8.133, 8.185,
+8.237, 8.289, 8.341, 8.393, 8.445, 8.497, 8.550, 8.602, 8.654, 8.707,
+8.759, 8.812, 8.865, 8.917, 8.970, 9.023, 9.076, 9.129, 9.182, 9.235,
+9.288, 9.341, 9.395, 9.448, 9.501, 9.555, 9.608, 9.662, 9.715, 9.769,
+9.822, 9.876, 9.930, 9.984, 10.038, 10.092, 10.146, 10.200, 10.254, 10.308,
+10.362, 10.417, 10.471, 10.525, 10.580, 10.634, 10.689, 10.743, 10.798, 10.853,
+10.907, 10.962, 11.017, 11.072, 11.127, 11.182, 11.237, 11.292, 11.347, 11.403,
+11.458, 11.513, 11.569, 11.624, 11.680, 11.735, 11.791, 11.846, 11.902, 11.958,
+12.013, 12.069, 12.125, 12.181, 12.237, 12.293, 12.349, 12.405, 12.461, 12.518,
+12.574, 12.630, 12.687, 12.743, 12.799, 12.856, 12.912, 12.969, 13.026, 13.082,
+13.139, 13.196, 13.253, 13.310, 13.366, 13.423, 13.480, 13.537, 13.595, 13.652,
+13.709, 13.766, 13.823, 13.881, 13.938, 13.995, 14.053, 14.110, 14.168, 14.226,
+14.283, 14.341, 14.399, 14.456, 14.514, 14.572, 14.630, 14.688, 14.746, 14.804,
+14.862, 14.920, 14.978, 15.036, 15.095, 15.153, 15.211, 15.270, 15.328, 15.386,
+15.445, 15.503, 15.562, 15.621, 15.679, 15.738, 15.797, 15.856, 15.914, 15.973,
+16.032, 16.091, 16.150, 16.209, 16.268, 16.327, 16.387, 16.446, 16.505, 16.564,
+16.624, 16.683, 16.742, 16.802, 16.861, 16.921, 16.980, 17.040, 17.100, 17.159,
+17.219, 17.279, 17.339, 17.399, 17.458, 17.518, 17.578, 17.638, 17.698, 17.759,
+17.819, 17.879, 17.939, 17.999, 18.060, 18.120, 18.180, 18.241, 18.301, 18.362,
+18.422, 18.483, 18.543, 18.604, 18.665, 18.725, 18.786, 18.847, 18.908, 18.969,
+19.030, 19.091, 19.152, 19.213, 19.274, 19.335, 19.396, 19.457, 19.518, 19.579,
+19.641, 19.702, 19.763, 19.825, 19.886, 19.947, 20.009, 20.070, 20.132, 20.193,
+20.255, 20.317, 20.378, 20.440, 20.502, 20.563, 20.625, 20.687, 20.748, 20.810,
+20.872};
+
+
+#define THERMOCOUPLE_TABLE_J_SIZE 1411
+//-210 to 1200 in degrees celcius increments
+const double thermocouple_table_j_type[THERMOCOUPLE_TABLE_J_SIZE] = {
+-8.095, -8.076, -8.057, -8.037, -8.017, -7.996, -7.976, -7.955, -7.934, -7.912,
+-7.890, -7.868, -7.846, -7.824, -7.801, -7.778, -7.755, -7.731, -7.707, -7.683,
+-7.659, -7.634, -7.610, -7.585, -7.559, -7.534, -7.508, -7.482, -7.456, -7.429,
+-7.403, -7.376, -7.348, -7.321, -7.293, -7.265, -7.237, -7.209, -7.181, -7.152,
+-7.123, -7.094, -7.064, -7.035, -7.005, -6.975, -6.944, -6.914, -6.883, -6.853,
+-6.821, -6.790, -6.759, -6.727, -6.695, -6.663, -6.631, -6.598, -6.566, -6.533,
+-6.500, -6.467, -6.433, -6.400, -6.366, -6.332, -6.298, -6.263, -6.229, -6.194,
+-6.159, -6.124, -6.089, -6.054, -6.018, -5.982, -5.946, -5.910, -5.874, -5.838,
+-5.801, -5.764, -5.727, -5.690, -5.653, -5.616, -5.578, -5.541, -5.503, -5.465,
+-5.426, -5.388, -5.350, -5.311, -5.272, -5.233, -5.194, -5.155, -5.116, -5.076,
+-5.037, -4.997, -4.957, -4.917, -4.877, -4.836, -4.796, -4.755, -4.714, -4.674,
+-4.633, -4.591, -4.550, -4.509, -4.467, -4.425, -4.384, -4.342, -4.300, -4.257,
+-4.215, -4.173, -4.130, -4.088, -4.045, -4.002, -3.959, -3.916, -3.872, -3.829,
+-3.786, -3.742, -3.698, -3.654, -3.610, -3.566, -3.522, -3.478, -3.434, -3.389,
+-3.344, -3.300, -3.255, -3.210, -3.165, -3.120, -3.075, -3.029, -2.984, -2.938,
+-2.893, -2.847, -2.801, -2.755, -2.709, -2.663, -2.617, -2.571, -2.524, -2.478,
+-2.431, -2.385, -2.338, -2.291, -2.244, -2.197, -2.150, -2.103, -2.055, -2.008,
+-1.961, -1.913, -1.865, -1.818, -1.770, -1.722, -1.674, -1.626, -1.578, -1.530,
+-1.482, -1.433, -1.385, -1.336, -1.288, -1.239, -1.190, -1.142, -1.093, -1.044,
+-0.995, -0.946, -0.896, -0.847, -0.798, -0.749, -0.699, -0.650, -0.600, -0.550,
+-0.501, -0.451, -0.401, -0.351, -0.301, -0.251, -0.201, -0.151, -0.101, -0.050,
+0.000, 0.050, 0.101, 0.151, 0.202, 0.253, 0.303, 0.354, 0.405, 0.456,
+0.507, 0.558, 0.609, 0.660, 0.711, 0.762, 0.814, 0.865, 0.916, 0.968,
+1.019, 1.071, 1.122, 1.174, 1.226, 1.277, 1.329, 1.381, 1.433, 1.485,
+1.537, 1.589, 1.641, 1.693, 1.745, 1.797, 1.849, 1.902, 1.954, 2.006,
+2.059, 2.111, 2.164, 2.216, 2.269, 2.322, 2.374, 2.427, 2.480, 2.532,
+2.585, 2.638, 2.691, 2.744, 2.797, 2.850, 2.903, 2.956, 3.009, 3.062,
+3.116, 3.169, 3.222, 3.275, 3.329, 3.382, 3.436, 3.489, 3.543, 3.596,
+3.650, 3.703, 3.757, 3.810, 3.864, 3.918, 3.971, 4.025, 4.079, 4.133,
+4.187, 4.240, 4.294, 4.348, 4.402, 4.456, 4.510, 4.564, 4.618, 4.672,
+4.726, 4.781, 4.835, 4.889, 4.943, 4.997, 5.052, 5.106, 5.160, 5.215,
+5.269, 5.323, 5.378, 5.432, 5.487, 5.541, 5.595, 5.650, 5.705, 5.759,
+5.814, 5.868, 5.923, 5.977, 6.032, 6.087, 6.141, 6.196, 6.251, 6.306,
+6.360, 6.415, 6.470, 6.525, 6.579, 6.634, 6.689, 6.744, 6.799, 6.854,
+6.909, 6.964, 7.019, 7.074, 7.129, 7.184, 7.239, 7.294, 7.349, 7.404,
+7.459, 7.514, 7.569, 7.624, 7.679, 7.734, 7.789, 7.844, 7.900, 7.955,
+8.010, 8.065, 8.120, 8.175, 8.231, 8.286, 8.341, 8.396, 8.452, 8.507,
+8.562, 8.618, 8.673, 8.728, 8.783, 8.839, 8.894, 8.949, 9.005, 9.060,
+9.115, 9.171, 9.226, 9.282, 9.337, 9.392, 9.448, 9.503, 9.559, 9.614,
+9.669, 9.725, 9.780, 9.836, 9.891, 9.947, 10.002, 10.057, 10.113, 10.168,
+10.224, 10.279, 10.335, 10.390, 10.446, 10.501, 10.557, 10.612, 10.668, 10.723,
+10.779, 10.834, 10.890, 10.945, 11.001, 11.056, 11.112, 11.167, 11.223, 11.278,
+11.334, 11.389, 11.445, 11.501, 11.556, 11.612, 11.667, 11.723, 11.778, 11.834,
+11.889, 11.945, 12.000, 12.056, 12.111, 12.167, 12.222, 12.278, 12.334, 12.389,
+12.445, 12.500, 12.556, 12.611, 12.667, 12.722, 12.778, 12.833, 12.889, 12.944,
+13.000, 13.056, 13.111, 13.167, 13.222, 13.278, 13.333, 13.389, 13.444, 13.500,
+13.555, 13.611, 13.666, 13.722, 13.777, 13.833, 13.888, 13.944, 13.999, 14.055,
+14.110, 14.166, 14.221, 14.277, 14.332, 14.388, 14.443, 14.499, 14.554, 14.609,
+14.665, 14.720, 14.776, 14.831, 14.887, 14.942, 14.998, 15.053, 15.109, 15.164,
+15.219, 15.275, 15.330, 15.386, 15.441, 15.496, 15.552, 15.607, 15.663, 15.718,
+15.773, 15.829, 15.884, 15.940, 15.995, 16.050, 16.106, 16.161, 16.216, 16.272,
+16.327, 16.383, 16.438, 16.493, 16.549, 16.604, 16.659, 16.715, 16.770, 16.825,
+16.881, 16.936, 16.991, 17.046, 17.102, 17.157, 17.212, 17.268, 17.323, 17.378,
+17.434, 17.489, 17.544, 17.599, 17.655, 17.710, 17.765, 17.820, 17.876, 17.931,
+17.986, 18.041, 18.097, 18.152, 18.207, 18.262, 18.318, 18.373, 18.428, 18.483,
+18.538, 18.594, 18.649, 18.704, 18.759, 18.814, 18.870, 18.925, 18.980, 19.035,
+19.090, 19.146, 19.201, 19.256, 19.311, 19.366, 19.422, 19.477, 19.532, 19.587,
+19.642, 19.697, 19.753, 19.808, 19.863, 19.918, 19.973, 20.028, 20.083, 20.139,
+20.194, 20.249, 20.304, 20.359, 20.414, 20.469, 20.525, 20.580, 20.635, 20.690,
+20.745, 20.800, 20.855, 20.911, 20.966, 21.021, 21.076, 21.131, 21.186, 21.241,
+21.297, 21.352, 21.407, 21.462, 21.517, 21.572, 21.627, 21.683, 21.738, 21.793,
+21.848, 21.903, 21.958, 22.014, 22.069, 22.124, 22.179, 22.234, 22.289, 22.345,
+22.400, 22.455, 22.510, 22.565, 22.620, 22.676, 22.731, 22.786, 22.841, 22.896,
+22.952, 23.007, 23.062, 23.117, 23.172, 23.228, 23.283, 23.338, 23.393, 23.449,
+23.504, 23.559, 23.614, 23.670, 23.725, 23.780, 23.835, 23.891, 23.946, 24.001,
+24.057, 24.112, 24.167, 24.223, 24.278, 24.333, 24.389, 24.444, 24.499, 24.555,
+24.610, 24.665, 24.721, 24.776, 24.832, 24.887, 24.943, 24.998, 25.053, 25.109,
+25.164, 25.220, 25.275, 25.331, 25.386, 25.442, 25.497, 25.553, 25.608, 25.664,
+25.720, 25.775, 25.831, 25.886, 25.942, 25.998, 26.053, 26.109, 26.165, 26.220,
+26.276, 26.332, 26.387, 26.443, 26.499, 26.555, 26.610, 26.666, 26.722, 26.778,
+26.834, 26.889, 26.945, 27.001, 27.057, 27.113, 27.169, 27.225, 27.281, 27.337,
+27.393, 27.449, 27.505, 27.561, 27.617, 27.673, 27.729, 27.785, 27.841, 27.897,
+27.953, 28.010, 28.066, 28.122, 28.178, 28.234, 28.291, 28.347, 28.403, 28.460,
+28.516, 28.572, 28.629, 28.685, 28.741, 28.798, 28.854, 28.911, 28.967, 29.024,
+29.080, 29.137, 29.194, 29.250, 29.307, 29.363, 29.420, 29.477, 29.534, 29.590,
+29.647, 29.704, 29.761, 29.818, 29.874, 29.931, 29.988, 30.045, 30.102, 30.159,
+30.216, 30.273, 30.330, 30.387, 30.444, 30.502, 30.559, 30.616, 30.673, 30.730,
+30.788, 30.845, 30.902, 30.960, 31.017, 31.074, 31.132, 31.189, 31.247, 31.304,
+31.362, 31.419, 31.477, 31.535, 31.592, 31.650, 31.708, 31.766, 31.823, 31.881,
+31.939, 31.997, 32.055, 32.113, 32.171, 32.229, 32.287, 32.345, 32.403, 32.461,
+32.519, 32.577, 32.636, 32.694, 32.752, 32.810, 32.869, 32.927, 32.985, 33.044,
+33.102, 33.161, 33.219, 33.278, 33.337, 33.395, 33.454, 33.513, 33.571, 33.630,
+33.689, 33.748, 33.807, 33.866, 33.925, 33.984, 34.043, 34.102, 34.161, 34.220,
+34.279, 34.338, 34.397, 34.457, 34.516, 34.575, 34.635, 34.694, 34.754, 34.813,
+34.873, 34.932, 34.992, 35.051, 35.111, 35.171, 35.230, 35.290, 35.350, 35.410,
+35.470, 35.530, 35.590, 35.650, 35.710, 35.770, 35.830, 35.890, 35.950, 36.010,
+36.071, 36.131, 36.191, 36.252, 36.312, 36.373, 36.433, 36.494, 36.554, 36.615,
+36.675, 36.736, 36.797, 36.858, 36.918, 36.979, 37.040, 37.101, 37.162, 37.223,
+37.284, 37.345, 37.406, 37.467, 37.528, 37.590, 37.651, 37.712, 37.773, 37.835,
+37.896, 37.958, 38.019, 38.081, 38.142, 38.204, 38.265, 38.327, 38.389, 38.450,
+38.512, 38.574, 38.636, 38.698, 38.760, 38.822, 38.884, 38.946, 39.008, 39.070,
+39.132, 39.194, 39.256, 39.318, 39.381, 39.443, 39.505, 39.568, 39.630, 39.693,
+39.755, 39.818, 39.880, 39.943, 40.005, 40.068, 40.131, 40.193, 40.256, 40.319,
+40.382, 40.445, 40.508, 40.570, 40.633, 40.696, 40.759, 40.822, 40.886, 40.949,
+41.012, 41.075, 41.138, 41.201, 41.265, 41.328, 41.391, 41.455, 41.518, 41.581,
+41.645, 41.708, 41.772, 41.835, 41.899, 41.962, 42.026, 42.090, 42.153, 42.217,
+42.281, 42.344, 42.408, 42.472, 42.536, 42.599, 42.663, 42.727, 42.791, 42.855,
+42.919, 42.983, 43.047, 43.111, 43.175, 43.239, 43.303, 43.367, 43.431, 43.495,
+43.559, 43.624, 43.688, 43.752, 43.817, 43.881, 43.945, 44.010, 44.074, 44.139,
+44.203, 44.267, 44.332, 44.396, 44.461, 44.525, 44.590, 44.655, 44.719, 44.784,
+44.848, 44.913, 44.977, 45.042, 45.107, 45.171, 45.236, 45.301, 45.365, 45.430,
+45.494, 45.559, 45.624, 45.688, 45.753, 45.818, 45.882, 45.947, 46.011, 46.076,
+46.141, 46.205, 46.270, 46.334, 46.399, 46.464, 46.528, 46.593, 46.657, 46.722,
+46.786, 46.851, 46.915, 46.980, 47.044, 47.109, 47.173, 47.238, 47.302, 47.367,
+47.431, 47.495, 47.560, 47.624, 47.688, 47.753, 47.817, 47.881, 47.946, 48.010,
+48.074, 48.138, 48.202, 48.267, 48.331, 48.395, 48.459, 48.523, 48.587, 48.651,
+48.715, 48.779, 48.843, 48.907, 48.971, 49.034, 49.098, 49.162, 49.226, 49.290,
+49.353, 49.417, 49.481, 49.544, 49.608, 49.672, 49.735, 49.799, 49.862, 49.926,
+49.989, 50.052, 50.116, 50.179, 50.243, 50.306, 50.369, 50.432, 50.495, 50.559,
+50.622, 50.685, 50.748, 50.811, 50.874, 50.937, 51.000, 51.063, 51.126, 51.188,
+51.251, 51.314, 51.377, 51.439, 51.502, 51.565, 51.627, 51.690, 51.752, 51.815,
+51.877, 51.940, 52.002, 52.064, 52.127, 52.189, 52.251, 52.314, 52.376, 52.438,
+52.500, 52.562, 52.624, 52.686, 52.748, 52.810, 52.872, 52.934, 52.996, 53.057,
+53.119, 53.181, 53.243, 53.304, 53.366, 53.427, 53.489, 53.550, 53.612, 53.673,
+53.735, 53.796, 53.857, 53.919, 53.980, 54.041, 54.102, 54.164, 54.225, 54.286,
+54.347, 54.408, 54.469, 54.530, 54.591, 54.652, 54.713, 54.773, 54.834, 54.895,
+54.956, 55.016, 55.077, 55.138, 55.198, 55.259, 55.319, 55.380, 55.440, 55.501,
+55.561, 55.622, 55.682, 55.742, 55.803, 55.863, 55.923, 55.983, 56.043, 56.104,
+56.164, 56.224, 56.284, 56.344, 56.404, 56.464, 56.524, 56.584, 56.643, 56.703,
+56.763, 56.823, 56.883, 56.942, 57.002, 57.062, 57.121, 57.181, 57.240, 57.300,
+57.360, 57.419, 57.479, 57.538, 57.597, 57.657, 57.716, 57.776, 57.835, 57.894,
+57.953, 58.013, 58.072, 58.131, 58.190, 58.249, 58.309, 58.368, 58.427, 58.486,
+58.545, 58.604, 58.663, 58.722, 58.781, 58.840, 58.899, 58.957, 59.016, 59.075,
+59.134, 59.193, 59.252, 59.310, 59.369, 59.428, 59.487, 59.545, 59.604, 59.663,
+59.721, 59.780, 59.838, 59.897, 59.956, 60.014, 60.073, 60.131, 60.190, 60.248,
+60.307, 60.365, 60.423, 60.482, 60.540, 60.599, 60.657, 60.715, 60.774, 60.832,
+60.890, 60.949, 61.007, 61.065, 61.123, 61.182, 61.240, 61.298, 61.356, 61.415,
+61.473, 61.531, 61.589, 61.647, 61.705, 61.763, 61.822, 61.880, 61.938, 61.996,
+62.054, 62.112, 62.170, 62.228, 62.286, 62.344, 62.402, 62.460, 62.518, 62.576,
+62.634, 62.692, 62.750, 62.808, 62.866, 62.924, 62.982, 63.040, 63.098, 63.156,
+63.214, 63.271, 63.329, 63.387, 63.445, 63.503, 63.561, 63.619, 63.677, 63.734,
+63.792, 63.850, 63.908, 63.966, 64.024, 64.081, 64.139, 64.197, 64.255, 64.313,
+64.370, 64.428, 64.486, 64.544, 64.602, 64.659, 64.717, 64.775, 64.833, 64.890,
+64.948, 65.006, 65.064, 65.121, 65.179, 65.237, 65.295, 65.352, 65.410, 65.468,
+65.525, 65.583, 65.641, 65.699, 65.756, 65.814, 65.872, 65.929, 65.987, 66.045,
+66.102, 66.160, 66.218, 66.275, 66.333, 66.391, 66.448, 66.506, 66.564, 66.621,
+66.679, 66.737, 66.794, 66.852, 66.910, 66.967, 67.025, 67.082, 67.140, 67.198,
+67.255, 67.313, 67.370, 67.428, 67.486, 67.543, 67.601, 67.658, 67.716, 67.773,
+67.831, 67.888, 67.946, 68.003, 68.061, 68.119, 68.176, 68.234, 68.291, 68.348,
+68.406, 68.463, 68.521, 68.578, 68.636, 68.693, 68.751, 68.808, 68.865, 68.923,
+68.980, 69.037, 69.095, 69.152, 69.209, 69.267, 69.324, 69.381, 69.439, 69.496,
+69.553};
+
+#define THERMOCOUPLE_TABLE_K_SIZE 1643
+//-270 to 1372 in degrees celcius increments
+const double thermocouple_table_k_type[THERMOCOUPLE_TABLE_K_SIZE] = {
+-6.458, -6.457, -6.456, -6.455, -6.453, -6.452, -6.450, -6.448, -6.446, -6.444,
+-6.441, -6.438, -6.435, -6.432, -6.429, -6.425, -6.421, -6.417, -6.413, -6.408,
+-6.404, -6.399, -6.393, -6.388, -6.382, -6.377, -6.370, -6.364, -6.358, -6.351,
+-6.344, -6.337, -6.329, -6.322, -6.314, -6.306, -6.297, -6.289, -6.280, -6.271,
+-6.262, -6.252, -6.243, -6.233, -6.223, -6.213, -6.202, -6.192, -6.181, -6.170,
+-6.158, -6.147, -6.135, -6.123, -6.111, -6.099, -6.087, -6.074, -6.061, -6.048,
+-6.035, -6.021, -6.007, -5.994, -5.980, -5.965, -5.951, -5.936, -5.922, -5.907,
+-5.891, -5.876, -5.861, -5.845, -5.829, -5.813, -5.797, -5.780, -5.763, -5.747,
+-5.730, -5.713, -5.695, -5.678, -5.660, -5.642, -5.624, -5.606, -5.588, -5.569,
+-5.550, -5.531, -5.512, -5.493, -5.474, -5.454, -5.435, -5.415, -5.395, -5.374,
+-5.354, -5.333, -5.313, -5.292, -5.271, -5.250, -5.228, -5.207, -5.185, -5.163,
+-5.141, -5.119, -5.097, -5.074, -5.052, -5.029, -5.006, -4.983, -4.960, -4.936,
+-4.913, -4.889, -4.865, -4.841, -4.817, -4.793, -4.768, -4.744, -4.719, -4.694,
+-4.669, -4.644, -4.618, -4.593, -4.567, -4.542, -4.516, -4.490, -4.463, -4.437,
+-4.411, -4.384, -4.357, -4.330, -4.303, -4.276, -4.249, -4.221, -4.194, -4.166,
+-4.138, -4.110, -4.082, -4.054, -4.025, -3.997, -3.968, -3.939, -3.911, -3.882,
+-3.852, -3.823, -3.794, -3.764, -3.734, -3.705, -3.675, -3.645, -3.614, -3.584,
+-3.554, -3.523, -3.492, -3.462, -3.431, -3.400, -3.368, -3.337, -3.306, -3.274,
+-3.243, -3.211, -3.179, -3.147, -3.115, -3.083, -3.050, -3.018, -2.986, -2.953,
+-2.920, -2.887, -2.854, -2.821, -2.788, -2.755, -2.721, -2.688, -2.654, -2.620,
+-2.587, -2.553, -2.519, -2.485, -2.450, -2.416, -2.382, -2.347, -2.312, -2.278,
+-2.243, -2.208, -2.173, -2.138, -2.103, -2.067, -2.032, -1.996, -1.961, -1.925,
+-1.889, -1.854, -1.818, -1.782, -1.745, -1.709, -1.673, -1.637, -1.600, -1.564,
+-1.527, -1.490, -1.453, -1.417, -1.380, -1.343, -1.305, -1.268, -1.231, -1.194,
+-1.156, -1.119, -1.081, -1.043, -1.006, -0.968, -0.930, -0.892, -0.854, -0.816,
+-0.778, -0.739, -0.701, -0.663, -0.624, -0.586, -0.547, -0.508, -0.470, -0.431,
+-0.392, -0.353, -0.314, -0.275, -0.236, -0.197, -0.157, -0.118, -0.079, -0.039,
+0.000, 0.039, 0.079, 0.119, 0.158, 0.198, 0.238, 0.277, 0.317, 0.357,
+0.397, 0.437, 0.477, 0.517, 0.557, 0.597, 0.637, 0.677, 0.718, 0.758,
+0.798, 0.838, 0.879, 0.919, 0.960, 1.000, 1.041, 1.081, 1.122, 1.163,
+1.203, 1.244, 1.285, 1.326, 1.366, 1.407, 1.448, 1.489, 1.530, 1.571,
+1.612, 1.653, 1.694, 1.735, 1.776, 1.817, 1.858, 1.899, 1.941, 1.982,
+2.023, 2.064, 2.106, 2.147, 2.188, 2.230, 2.271, 2.312, 2.354, 2.395,
+2.436, 2.478, 2.519, 2.561, 2.602, 2.644, 2.685, 2.727, 2.768, 2.810,
+2.851, 2.893, 2.934, 2.976, 3.017, 3.059, 3.100, 3.142, 3.184, 3.225,
+3.267, 3.308, 3.350, 3.391, 3.433, 3.474, 3.516, 3.557, 3.599, 3.640,
+3.682, 3.723, 3.765, 3.806, 3.848, 3.889, 3.931, 3.972, 4.013, 4.055,
+4.096, 4.138, 4.179, 4.220, 4.262, 4.303, 4.344, 4.385, 4.427, 4.468,
+4.509, 4.550, 4.591, 4.633, 4.674, 4.715, 4.756, 4.797, 4.838, 4.879,
+4.920, 4.961, 5.002, 5.043, 5.084, 5.124, 5.165, 5.206, 5.247, 5.288,
+5.328, 5.369, 5.410, 5.450, 5.491, 5.532, 5.572, 5.613, 5.653, 5.694,
+5.735, 5.775, 5.815, 5.856, 5.896, 5.937, 5.977, 6.017, 6.058, 6.098,
+6.138, 6.179, 6.219, 6.259, 6.299, 6.339, 6.380, 6.420, 6.460, 6.500,
+6.540, 6.580, 6.620, 6.660, 6.701, 6.741, 6.781, 6.821, 6.861, 6.901,
+6.941, 6.981, 7.021, 7.060, 7.100, 7.140, 7.180, 7.220, 7.260, 7.300,
+7.340, 7.380, 7.420, 7.460, 7.500, 7.540, 7.579, 7.619, 7.659, 7.699,
+7.739, 7.779, 7.819, 7.859, 7.899, 7.939, 7.979, 8.019, 8.059, 8.099,
+8.138, 8.178, 8.218, 8.258, 8.298, 8.338, 8.378, 8.418, 8.458, 8.499,
+8.539, 8.579, 8.619, 8.659, 8.699, 8.739, 8.779, 8.819, 8.860, 8.900,
+8.940, 8.980, 9.020, 9.061, 9.101, 9.141, 9.181, 9.222, 9.262, 9.302,
+9.343, 9.383, 9.423, 9.464, 9.504, 9.545, 9.585, 9.626, 9.666, 9.707,
+9.747, 9.788, 9.828, 9.869, 9.909, 9.950, 9.991, 10.031, 10.072, 10.113,
+10.153, 10.194, 10.235, 10.276, 10.316, 10.357, 10.398, 10.439, 10.480, 10.520,
+10.561, 10.602, 10.643, 10.684, 10.725, 10.766, 10.807, 10.848, 10.889, 10.930,
+10.971, 11.012, 11.053, 11.094, 11.135, 11.176, 11.217, 11.259, 11.300, 11.341,
+11.382, 11.423, 11.465, 11.506, 11.547, 11.588, 11.630, 11.671, 11.712, 11.753,
+11.795, 11.836, 11.877, 11.919, 11.960, 12.001, 12.043, 12.084, 12.126, 12.167,
+12.209, 12.250, 12.291, 12.333, 12.374, 12.416, 12.457, 12.499, 12.540, 12.582,
+12.624, 12.665, 12.707, 12.748, 12.790, 12.831, 12.873, 12.915, 12.956, 12.998,
+13.040, 13.081, 13.123, 13.165, 13.206, 13.248, 13.290, 13.331, 13.373, 13.415,
+13.457, 13.498, 13.540, 13.582, 13.624, 13.665, 13.707, 13.749, 13.791, 13.833,
+13.874, 13.916, 13.958, 14.000, 14.042, 14.084, 14.126, 14.167, 14.209, 14.251,
+14.293, 14.335, 14.377, 14.419, 14.461, 14.503, 14.545, 14.587, 14.629, 14.671,
+14.713, 14.755, 14.797, 14.839, 14.881, 14.923, 14.965, 15.007, 15.049, 15.091,
+15.133, 15.175, 15.217, 15.259, 15.301, 15.343, 15.385, 15.427, 15.469, 15.511,
+15.554, 15.596, 15.638, 15.680, 15.722, 15.764, 15.806, 15.849, 15.891, 15.933,
+15.975, 16.017, 16.059, 16.102, 16.144, 16.186, 16.228, 16.270, 16.313, 16.355,
+16.397, 16.439, 16.482, 16.524, 16.566, 16.608, 16.651, 16.693, 16.735, 16.778,
+16.820, 16.862, 16.904, 16.947, 16.989, 17.031, 17.074, 17.116, 17.158, 17.201,
+17.243, 17.285, 17.328, 17.370, 17.413, 17.455, 17.497, 17.540, 17.582, 17.624,
+17.667, 17.709, 17.752, 17.794, 17.837, 17.879, 17.921, 17.964, 18.006, 18.049,
+18.091, 18.134, 18.176, 18.218, 18.261, 18.303, 18.346, 18.388, 18.431, 18.473,
+18.516, 18.558, 18.601, 18.643, 18.686, 18.728, 18.771, 18.813, 18.856, 18.898,
+18.941, 18.983, 19.026, 19.068, 19.111, 19.154, 19.196, 19.239, 19.281, 19.324,
+19.366, 19.409, 19.451, 19.494, 19.537, 19.579, 19.622, 19.664, 19.707, 19.750,
+19.792, 19.835, 19.877, 19.920, 19.962, 20.005, 20.048, 20.090, 20.133, 20.175,
+20.218, 20.261, 20.303, 20.346, 20.389, 20.431, 20.474, 20.516, 20.559, 20.602,
+20.644, 20.687, 20.730, 20.772, 20.815, 20.857, 20.900, 20.943, 20.985, 21.028,
+21.071, 21.113, 21.156, 21.199, 21.241, 21.284, 21.326, 21.369, 21.412, 21.454,
+21.497, 21.540, 21.582, 21.625, 21.668, 21.710, 21.753, 21.796, 21.838, 21.881,
+21.924, 21.966, 22.009, 22.052, 22.094, 22.137, 22.179, 22.222, 22.265, 22.307,
+22.350, 22.393, 22.435, 22.478, 22.521, 22.563, 22.606, 22.649, 22.691, 22.734,
+22.776, 22.819, 22.862, 22.904, 22.947, 22.990, 23.032, 23.075, 23.117, 23.160,
+23.203, 23.245, 23.288, 23.331, 23.373, 23.416, 23.458, 23.501, 23.544, 23.586,
+23.629, 23.671, 23.714, 23.757, 23.799, 23.842, 23.884, 23.927, 23.970, 24.012,
+24.055, 24.097, 24.140, 24.182, 24.225, 24.267, 24.310, 24.353, 24.395, 24.438,
+24.480, 24.523, 24.565, 24.608, 24.650, 24.693, 24.735, 24.778, 24.820, 24.863,
+24.905, 24.948, 24.990, 25.033, 25.075, 25.118, 25.160, 25.203, 25.245, 25.288,
+25.330, 25.373, 25.415, 25.458, 25.500, 25.543, 25.585, 25.627, 25.670, 25.712,
+25.755, 25.797, 25.840, 25.882, 25.924, 25.967, 26.009, 26.052, 26.094, 26.136,
+26.179, 26.221, 26.263, 26.306, 26.348, 26.390, 26.433, 26.475, 26.517, 26.560,
+26.602, 26.644, 26.687, 26.729, 26.771, 26.814, 26.856, 26.898, 26.940, 26.983,
+27.025, 27.067, 27.109, 27.152, 27.194, 27.236, 27.278, 27.320, 27.363, 27.405,
+27.447, 27.489, 27.531, 27.574, 27.616, 27.658, 27.700, 27.742, 27.784, 27.826,
+27.869, 27.911, 27.953, 27.995, 28.037, 28.079, 28.121, 28.163, 28.205, 28.247,
+28.289, 28.332, 28.374, 28.416, 28.458, 28.500, 28.542, 28.584, 28.626, 28.668,
+28.710, 28.752, 28.794, 28.835, 28.877, 28.919, 28.961, 29.003, 29.045, 29.087,
+29.129, 29.171, 29.213, 29.255, 29.297, 29.338, 29.380, 29.422, 29.464, 29.506,
+29.548, 29.589, 29.631, 29.673, 29.715, 29.757, 29.798, 29.840, 29.882, 29.924,
+29.965, 30.007, 30.049, 30.090, 30.132, 30.174, 30.216, 30.257, 30.299, 30.341,
+30.382, 30.424, 30.466, 30.507, 30.549, 30.590, 30.632, 30.674, 30.715, 30.757,
+30.798, 30.840, 30.881, 30.923, 30.964, 31.006, 31.047, 31.089, 31.130, 31.172,
+31.213, 31.255, 31.296, 31.338, 31.379, 31.421, 31.462, 31.504, 31.545, 31.586,
+31.628, 31.669, 31.710, 31.752, 31.793, 31.834, 31.876, 31.917, 31.958, 32.000,
+32.041, 32.082, 32.124, 32.165, 32.206, 32.247, 32.289, 32.330, 32.371, 32.412,
+32.453, 32.495, 32.536, 32.577, 32.618, 32.659, 32.700, 32.742, 32.783, 32.824,
+32.865, 32.906, 32.947, 32.988, 33.029, 33.070, 33.111, 33.152, 33.193, 33.234,
+33.275, 33.316, 33.357, 33.398, 33.439, 33.480, 33.521, 33.562, 33.603, 33.644,
+33.685, 33.726, 33.767, 33.808, 33.848, 33.889, 33.930, 33.971, 34.012, 34.053,
+34.093, 34.134, 34.175, 34.216, 34.257, 34.297, 34.338, 34.379, 34.420, 34.460,
+34.501, 34.542, 34.582, 34.623, 34.664, 34.704, 34.745, 34.786, 34.826, 34.867,
+34.908, 34.948, 34.989, 35.029, 35.070, 35.110, 35.151, 35.192, 35.232, 35.273,
+35.313, 35.354, 35.394, 35.435, 35.475, 35.516, 35.556, 35.596, 35.637, 35.677,
+35.718, 35.758, 35.798, 35.839, 35.879, 35.920, 35.960, 36.000, 36.041, 36.081,
+36.121, 36.162, 36.202, 36.242, 36.282, 36.323, 36.363, 36.403, 36.443, 36.484,
+36.524, 36.564, 36.604, 36.644, 36.685, 36.725, 36.765, 36.805, 36.845, 36.885,
+36.925, 36.965, 37.006, 37.046, 37.086, 37.126, 37.166, 37.206, 37.246, 37.286,
+37.326, 37.366, 37.406, 37.446, 37.486, 37.526, 37.566, 37.606, 37.646, 37.686,
+37.725, 37.765, 37.805, 37.845, 37.885, 37.925, 37.965, 38.005, 38.044, 38.084,
+38.124, 38.164, 38.204, 38.243, 38.283, 38.323, 38.363, 38.402, 38.442, 38.482,
+38.522, 38.561, 38.601, 38.641, 38.680, 38.720, 38.760, 38.799, 38.839, 38.878,
+38.918, 38.958, 38.997, 39.037, 39.076, 39.116, 39.155, 39.195, 39.235, 39.274,
+39.314, 39.353, 39.393, 39.432, 39.471, 39.511, 39.550, 39.590, 39.629, 39.669,
+39.708, 39.747, 39.787, 39.826, 39.866, 39.905, 39.944, 39.984, 40.023, 40.062,
+40.101, 40.141, 40.180, 40.219, 40.259, 40.298, 40.337, 40.376, 40.415, 40.455,
+40.494, 40.533, 40.572, 40.611, 40.651, 40.690, 40.729, 40.768, 40.807, 40.846,
+40.885, 40.924, 40.963, 41.002, 41.042, 41.081, 41.120, 41.159, 41.198, 41.237,
+41.276, 41.315, 41.354, 41.393, 41.431, 41.470, 41.509, 41.548, 41.587, 41.626,
+41.665, 41.704, 41.743, 41.781, 41.820, 41.859, 41.898, 41.937, 41.976, 42.014,
+42.053, 42.092, 42.131, 42.169, 42.208, 42.247, 42.286, 42.324, 42.363, 42.402,
+42.440, 42.479, 42.518, 42.556, 42.595, 42.633, 42.672, 42.711, 42.749, 42.788,
+42.826, 42.865, 42.903, 42.942, 42.980, 43.019, 43.057, 43.096, 43.134, 43.173,
+43.211, 43.250, 43.288, 43.327, 43.365, 43.403, 43.442, 43.480, 43.518, 43.557,
+43.595, 43.633, 43.672, 43.710, 43.748, 43.787, 43.825, 43.863, 43.901, 43.940,
+43.978, 44.016, 44.054, 44.092, 44.130, 44.169, 44.207, 44.245, 44.283, 44.321,
+44.359, 44.397, 44.435, 44.473, 44.512, 44.550, 44.588, 44.626, 44.664, 44.702,
+44.740, 44.778, 44.816, 44.853, 44.891, 44.929, 44.967, 45.005, 45.043, 45.081,
+45.119, 45.157, 45.194, 45.232, 45.270, 45.308, 45.346, 45.383, 45.421, 45.459,
+45.497, 45.534, 45.572, 45.610, 45.647, 45.685, 45.723, 45.760, 45.798, 45.836,
+45.873, 45.911, 45.948, 45.986, 46.024, 46.061, 46.099, 46.136, 46.174, 46.211,
+46.249, 46.286, 46.324, 46.361, 46.398, 46.436, 46.473, 46.511, 46.548, 46.585,
+46.623, 46.660, 46.697, 46.735, 46.772, 46.809, 46.847, 46.884, 46.921, 46.958,
+46.995, 47.033, 47.070, 47.107, 47.144, 47.181, 47.218, 47.256, 47.293, 47.330,
+47.367, 47.404, 47.441, 47.478, 47.515, 47.552, 47.589, 47.626, 47.663, 47.700,
+47.737, 47.774, 47.811, 47.848, 47.884, 47.921, 47.958, 47.995, 48.032, 48.069,
+48.105, 48.142, 48.179, 48.216, 48.252, 48.289, 48.326, 48.363, 48.399, 48.436,
+48.473, 48.509, 48.546, 48.582, 48.619, 48.656, 48.692, 48.729, 48.765, 48.802,
+48.838, 48.875, 48.911, 48.948, 48.984, 49.021, 49.057, 49.093, 49.130, 49.166,
+49.202, 49.239, 49.275, 49.311, 49.348, 49.384, 49.420, 49.456, 49.493, 49.529,
+49.565, 49.601, 49.637, 49.674, 49.710, 49.746, 49.782, 49.818, 49.854, 49.890,
+49.926, 49.962, 49.998, 50.034, 50.070, 50.106, 50.142, 50.178, 50.214, 50.250,
+50.286, 50.322, 50.358, 50.393, 50.429, 50.465, 50.501, 50.537, 50.572, 50.608,
+50.644, 50.680, 50.715, 50.751, 50.787, 50.822, 50.858, 50.894, 50.929, 50.965,
+51.000, 51.036, 51.071, 51.107, 51.142, 51.178, 51.213, 51.249, 51.284, 51.320,
+51.355, 51.391, 51.426, 51.461, 51.497, 51.532, 51.567, 51.603, 51.638, 51.673,
+51.708, 51.744, 51.779, 51.814, 51.849, 51.885, 51.920, 51.955, 51.990, 52.025,
+52.060, 52.095, 52.130, 52.165, 52.200, 52.235, 52.270, 52.305, 52.340, 52.375,
+52.410, 52.445, 52.480, 52.515, 52.550, 52.585, 52.620, 52.654, 52.689, 52.724,
+52.759, 52.794, 52.828, 52.863, 52.898, 52.932, 52.967, 53.002, 53.037, 53.071,
+53.106, 53.140, 53.175, 53.210, 53.244, 53.279, 53.313, 53.348, 53.382, 53.417,
+53.451, 53.486, 53.520, 53.555, 53.589, 53.623, 53.658, 53.692, 53.727, 53.761,
+53.795, 53.830, 53.864, 53.898, 53.932, 53.967, 54.001, 54.035, 54.069, 54.104,
+54.138, 54.172, 54.206, 54.240, 54.274, 54.308, 54.343, 54.377, 54.411, 54.445,
+54.479, 54.513, 54.547, 54.581, 54.615, 54.649, 54.683, 54.717, 54.751, 54.785,
+54.819, 54.852, 54.886};
+
+double lookup_temperature(double Vthermocouple, CPhidgetTemperatureSensor_ThermocoupleType type)
+{
+ int i, size;
+ double temperature = PUNK_DBL;
+ const double *thermocouple_table;
+ int startingTemp = 0;
+
+ switch(type)
+ {
+ case PHIDGET_TEMPERATURE_SENSOR_K_TYPE:
+ size = THERMOCOUPLE_TABLE_K_SIZE;
+ thermocouple_table = thermocouple_table_k_type;
+ break;
+ case PHIDGET_TEMPERATURE_SENSOR_J_TYPE:
+ size = THERMOCOUPLE_TABLE_J_SIZE;
+ thermocouple_table = thermocouple_table_j_type;
+ break;
+ case PHIDGET_TEMPERATURE_SENSOR_E_TYPE:
+ size = THERMOCOUPLE_TABLE_E_SIZE;
+ thermocouple_table = thermocouple_table_e_type;
+ break;
+ case PHIDGET_TEMPERATURE_SENSOR_T_TYPE:
+ size = THERMOCOUPLE_TABLE_T_SIZE;
+ thermocouple_table = thermocouple_table_t_type;
+ break;
+ default:
+ return PUNK_DBL;
+ }
+ startingTemp = thermocouple_table_range[type][0];
+
+ //the voltage is too low
+ if(Vthermocouple < thermocouple_table[0])
+ return PUNK_DBL;
+
+ for(i=1;i<size;i++) {
+ if(thermocouple_table[i] > Vthermocouple) {
+ temperature = (double)(i+(startingTemp-1)) + ((Vthermocouple - thermocouple_table[i-1]) / (thermocouple_table[i] - thermocouple_table[i-1]));
+ break;
+ }
+ }
+
+ //if(Vthermocouple > thermocouple_table[size-1]) then temperature will still equal PUNK_DBL;
+ return temperature;
+}
+
+double lookup_voltage(double Tjunction, CPhidgetTemperatureSensor_ThermocoupleType type)
+{
+ double voltage;
+ const double *thermocouple_table;
+ int startingTemp = 0, size = 0;
+
+ switch(type)
+ {
+ case PHIDGET_TEMPERATURE_SENSOR_K_TYPE:
+ size = THERMOCOUPLE_TABLE_K_SIZE;
+ thermocouple_table = thermocouple_table_k_type;
+ break;
+ case PHIDGET_TEMPERATURE_SENSOR_J_TYPE:
+ size = THERMOCOUPLE_TABLE_J_SIZE;
+ thermocouple_table = thermocouple_table_j_type;
+ break;
+ case PHIDGET_TEMPERATURE_SENSOR_E_TYPE:
+ size = THERMOCOUPLE_TABLE_E_SIZE;
+ thermocouple_table = thermocouple_table_e_type;
+ break;
+ case PHIDGET_TEMPERATURE_SENSOR_T_TYPE:
+ size = THERMOCOUPLE_TABLE_T_SIZE;
+ thermocouple_table = thermocouple_table_t_type;
+ break;
+ default:
+ return 0;
+ }
+ startingTemp = thermocouple_table_range[type][0];
+
+ //Make sure we're not going to try looking outside of the arrays
+ if(((int)Tjunction-startingTemp) < 0)
+ return PUNK_DBL;
+ if(((int)Tjunction-(startingTemp-1)) >= size)
+ return PUNK_DBL;
+
+ voltage = thermocouple_table[(int)Tjunction-startingTemp] +
+ ((thermocouple_table[(int)Tjunction-(startingTemp-1)] - thermocouple_table[(int)Tjunction-startingTemp])
+ * (double)(Tjunction - (int)Tjunction));
+
+ return voltage;
+}
+
+// === Exported Functions === //
+
+//create and initialize a device structure
+CCREATE(TemperatureSensor, PHIDCLASS_TEMPERATURESENSOR)
+
+//event setup functions
+CFHANDLE(TemperatureSensor, TemperatureChange, int, double)
+
+CGET(TemperatureSensor,TemperatureInputCount,int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_TEMPERATURESENSOR)
+ TESTATTACHED
+
+ MASGN(phid.attr.temperaturesensor.numTempInputs)
+}
+
+CGETINDEX(TemperatureSensor,Temperature,double)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_TEMPERATURESENSOR)
+ TESTATTACHED
+ TESTINDEX(phid.attr.temperaturesensor.numTempInputs)
+ TESTMASGN(Temperature[Index], PUNK_DBL)
+
+ MASGN(Temperature[Index])
+}
+
+CGETINDEX(TemperatureSensor,TemperatureMax,double)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_TEMPERATURESENSOR)
+ TESTATTACHED
+ TESTINDEX(phid.attr.temperaturesensor.numTempInputs)
+ TESTMASGN(temperatureMax[Index], PUNK_DBL)
+
+ MASGN(temperatureMax[Index])
+}
+
+CGETINDEX(TemperatureSensor,TemperatureMin,double)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_TEMPERATURESENSOR)
+ TESTATTACHED
+ TESTINDEX(phid.attr.temperaturesensor.numTempInputs)
+ TESTMASGN(temperatureMin[Index], PUNK_DBL)
+
+ MASGN(temperatureMin[Index])
+}
+
+CGETINDEX(TemperatureSensor,TemperatureChangeTrigger,double)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_TEMPERATURESENSOR)
+ TESTATTACHED
+ TESTINDEX(phid.attr.temperaturesensor.numTempInputs)
+ TESTMASGN(TempChangeTrigger[Index], PUNK_DBL)
+
+ MASGN(TempChangeTrigger[Index])
+}
+CSETINDEX(TemperatureSensor,TemperatureChangeTrigger,double)
+ TESTPTR(phid)
+ TESTDEVICETYPE(PHIDCLASS_TEMPERATURESENSOR)
+ TESTATTACHED
+ TESTINDEX(phid.attr.temperaturesensor.numTempInputs)
+ TESTRANGE(0, phid->temperatureMax[Index] - phid->temperatureMin[Index])
+
+ if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
+ ADDNETWORKKEYINDEXED(Trigger, "%lE", TempChangeTrigger);
+ else
+ phid->TempChangeTrigger[Index] = newVal;
+
+ return EPHIDGET_OK;
+}
+
+CGETINDEX(TemperatureSensor,Potential,double)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_TEMPERATURESENSOR)
+ TESTATTACHED
+
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_TEMPERATURESENSOR:
+ if(phid->phid.deviceVersion < 200)
+ return EPHIDGET_UNSUPPORTED;
+ break;
+ case PHIDID_TEMPERATURESENSOR_IR:
+ return EPHIDGET_UNSUPPORTED;
+ default:
+ break;
+ }
+
+ TESTINDEX(phid.attr.temperaturesensor.numTempInputs)
+
+ TESTMASGN(Potential[Index], PUNK_DBL)
+
+ MASGN(Potential[Index])
+}
+
+CGETINDEX(TemperatureSensor,PotentialMax,double)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_TEMPERATURESENSOR)
+ TESTATTACHED
+
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_TEMPERATURESENSOR:
+ if(phid->phid.deviceVersion < 200)
+ return EPHIDGET_UNSUPPORTED;
+ break;
+ case PHIDID_TEMPERATURESENSOR_IR:
+ return EPHIDGET_UNSUPPORTED;
+ default:
+ break;
+ }
+
+ TESTINDEX(phid.attr.temperaturesensor.numTempInputs)
+
+ TESTMASGN(potentialMax, PUNK_DBL)
+
+ MASGN(potentialMax)
+}
+
+CGETINDEX(TemperatureSensor,PotentialMin,double)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_TEMPERATURESENSOR)
+ TESTATTACHED
+
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_TEMPERATURESENSOR:
+ if(phid->phid.deviceVersion < 200)
+ return EPHIDGET_UNSUPPORTED;
+ break;
+ case PHIDID_TEMPERATURESENSOR_IR:
+ return EPHIDGET_UNSUPPORTED;
+ default:
+ break;
+ }
+
+ TESTINDEX(phid.attr.temperaturesensor.numTempInputs)
+
+ TESTMASGN(potentialMin, PUNK_DBL)
+
+ MASGN(potentialMin)
+}
+
+CGET(TemperatureSensor,AmbientTemperature,double)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_TEMPERATURESENSOR)
+ TESTATTACHED
+ TESTMASGN(AmbientTemperature, PUNK_DBL)
+
+ MASGN(AmbientTemperature)
+}
+
+CGET(TemperatureSensor,AmbientTemperatureMax,double)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_TEMPERATURESENSOR)
+ TESTATTACHED
+ TESTMASGN(ambientTemperatureMax, PUNK_DBL)
+
+ MASGN(ambientTemperatureMax)
+}
+
+CGET(TemperatureSensor,AmbientTemperatureMin,double)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_TEMPERATURESENSOR)
+ TESTATTACHED
+ TESTMASGN(ambientTemperatureMin, PUNK_DBL)
+
+ MASGN(ambientTemperatureMin)
+}
+
+CGETINDEX(TemperatureSensor,ThermocoupleType, CPhidgetTemperatureSensor_ThermocoupleType)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_TEMPERATURESENSOR)
+ TESTATTACHED
+
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_TEMPERATURESENSOR_IR:
+ return EPHIDGET_UNSUPPORTED;
+ default:
+ break;
+ }
+
+ TESTINDEX(phid.attr.temperaturesensor.numTempInputs)
+
+ MASGN(ThermocoupleType[Index])
+}
+CSETINDEX(TemperatureSensor,ThermocoupleType, CPhidgetTemperatureSensor_ThermocoupleType)
+ TESTPTR(phid)
+ TESTDEVICETYPE(PHIDCLASS_TEMPERATURESENSOR)
+ TESTATTACHED
+
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_TEMPERATURESENSOR:
+ if(phid->phid.deviceVersion < 200)
+ return EPHIDGET_UNSUPPORTED;
+ break;
+ case PHIDID_TEMPERATURESENSOR_IR:
+ return EPHIDGET_UNSUPPORTED;
+ default:
+ break;
+ }
+
+ TESTINDEX(phid.attr.temperaturesensor.numTempInputs)
+ TESTRANGE(PHIDGET_TEMPERATURE_SENSOR_K_TYPE, PHIDGET_TEMPERATURE_SENSOR_T_TYPE)
+
+ if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
+ ADDNETWORKKEYINDEXED(ThermocoupleType, "%d", ThermocoupleType);
+ else
+ phid->ThermocoupleType[Index] = newVal;
+
+ phid->temperatureMax[Index] = thermocouple_useful_range[newVal][1];
+ phid->temperatureMin[Index] = thermocouple_useful_range[newVal][0];
+
+ //Make sure our max and min range is actually measurable at the current ambient temperature. This is updated as the ambient temperature
+ // change in the data polling function
+ if(phid->AmbientTemperature != PUNK_DBL)
+ {
+ if(lookup_voltage(phid->temperatureMax[Index] - phid->AmbientTemperature, newVal) > phid->potentialMax)
+ phid->temperatureMax[Index] = (int)((lookup_temperature(phid->potentialMax, newVal) + phid->AmbientTemperature) / 10) * 10;
+ if(lookup_voltage(phid->temperatureMin[Index] - phid->AmbientTemperature, newVal) < phid->potentialMin)
+ phid->temperatureMin[Index] = (int)((lookup_temperature(phid->potentialMin, newVal) + phid->AmbientTemperature) / 10) * 10;
+ }
+
+ return EPHIDGET_OK;
+}
+
+// === Deprecated Functions === //
+
+CGET(TemperatureSensor,NumTemperatureInputs,int)
+ return CPhidgetTemperatureSensor_getTemperatureInputCount(phid, pVal);
+}
diff --git a/cphidgettemperaturesensor.h b/cphidgettemperaturesensor.h
new file mode 100644
index 0000000..99f362e
--- /dev/null
+++ b/cphidgettemperaturesensor.h
@@ -0,0 +1,172 @@
+#ifndef __CPHIDGETTEMPERATURESENSOR
+#define __CPHIDGETTEMPERATURESENSOR
+#include "cphidget.h"
+
+/** \defgroup phidtemp Phidget Temperature Sensor
+ * \ingroup phidgets
+ * Calls specific to the Phidget Temperature Sensor. See the product manual for more specific API details, supported functionality, units, etc.
+ *
+ * All temperatures are in degrees celcius.
+ * @{
+ */
+
+DPHANDLE(TemperatureSensor)
+CHDRSTANDARD(TemperatureSensor)
+
+/**
+ * The Phidget Temperature Sensor supports these types of thermocouples.
+ */
+typedef enum {
+ PHIDGET_TEMPERATURE_SENSOR_K_TYPE = 1, /**< K-Type thermocouple */
+ PHIDGET_TEMPERATURE_SENSOR_J_TYPE, /**< J-Type thermocouple */
+ PHIDGET_TEMPERATURE_SENSOR_E_TYPE, /**< E-Type thermocouple */
+ PHIDGET_TEMPERATURE_SENSOR_T_TYPE /**< T-Type thermocouple */
+} CPhidgetTemperatureSensor_ThermocoupleType;
+
+/**
+ * Gets the number of thermocouple inputs supported by this board.
+ * @param phid An attached phidget themperature sensor handle.
+ * @param count The thermocouple input count.
+ */
+CHDRGET(TemperatureSensor,TemperatureInputCount,int *count)
+/**
+ * Gets the temperature measured by a thermocouple input.
+ * @param phid An attached phidget themperature sensor handle.
+ * @param index The thermocouple index.
+ * @param temperature The temperature.
+ */
+CHDRGETINDEX(TemperatureSensor,Temperature,double *temperature)
+/**
+ * Gets the maximum temperature that can be measured by a thermocouple input. This depends on the type of thermocouple attached, as well as the ambient temperature.
+ * @param phid An attached phidget themperature sensor handle.
+ * @param index The thermocouple index.
+ * @param max The maximum temperature.
+ */
+CHDRGETINDEX(TemperatureSensor,TemperatureMax,double *max)
+/**
+ * Gets the minimum temperature that can be measured by a thermocouple input. This depends on the type of thermocouple attached, as well as the ambient temperature.
+ * @param phid An attached phidget themperature sensor handle.
+ * @param index The thermocouple index.
+ * @param min The minimum temperature.
+ */
+CHDRGETINDEX(TemperatureSensor,TemperatureMin,double *min)
+/**
+ * Set a temperature change handler. This is called when the temperature changes by more then the change trigger.
+ * @param phid An attached phidget temperature sensor handle.
+ * @param fptr Callback function pointer.
+ * @param userPtr A pointer for use by the user - this value is passed back into the callback function.
+ */
+CHDREVENTINDEX(TemperatureSensor,TemperatureChange,double temperature)
+/**
+ * Gets the change trigger for a thermocouple input.
+ * @param phid An attached phidget themperature sensor handle.
+ * @param index The thermocouple index.
+ * @param trigger The change trigger.
+ */
+CHDRGETINDEX(TemperatureSensor,TemperatureChangeTrigger,double *trigger)
+/**
+ * Sets the change trigger for a thermocouple input.
+ * @param phid An attached phidget themperature sensor handle.
+ * @param index The thermocouple index.
+ * @param trigger The change trigger.
+ */
+CHDRSETINDEX(TemperatureSensor,TemperatureChangeTrigger,double trigger)
+
+/**
+ * Gets the currently sensed potential for a thermocouple input.
+ * @param phid An attached phidget themperature sensor handle.
+ * @param index The thermocouple index.
+ * @param potential The potential.
+ */
+CHDRGETINDEX(TemperatureSensor,Potential,double *potential)
+/**
+ * Gets the maximum potential that a thermocouple input can measure.
+ * @param phid An attached phidget themperature sensor handle.
+ * @param index The thermocouple index.
+ * @param max The maximum potential.
+ */
+CHDRGETINDEX(TemperatureSensor,PotentialMax,double *max)
+/**
+ * Gets the minimum potential that a thermocouple input can measure.
+ * @param phid An attached phidget themperature sensor handle.
+ * @param index The thermocouple index.
+ * @param min The minimum potential.
+ */
+CHDRGETINDEX(TemperatureSensor,PotentialMin,double *min)
+
+/**
+ * Gets the ambient (board) temperature.
+ * @param phid An attached phidget themperature sensor handle.
+ * @param ambient The ambient (board) temperature.
+ */
+CHDRGET(TemperatureSensor,AmbientTemperature,double *ambient)
+/**
+ * Gets the maximum temperature that the ambient onboard temperature sensor can measure.
+ * @param phid An attached phidget themperature sensor handle.
+ * @param max The maximum temperature.
+ */
+CHDRGET(TemperatureSensor,AmbientTemperatureMax,double *max)
+/**
+ * Gets the minimum temperature that the ambient onboard temperature sensor can measure.
+ * @param phid An attached phidget themperature sensor handle.
+ * @param min The minimum temperature.
+ */
+CHDRGET(TemperatureSensor,AmbientTemperatureMin,double *min)
+
+/**
+ * Gets the type of thermocouple set to be at a thermocouple input. By default this is K-Type.
+ * @param phid An attached phidget themperature sensor handle.
+ * @param index The thermocouple index.
+ * @param type The thermocouple type.
+ */
+CHDRGETINDEX(TemperatureSensor, ThermocoupleType, CPhidgetTemperatureSensor_ThermocoupleType *type)
+/**
+ * Sets the type of thermocouple plugged into a thermocouple input. By default this is K-Type.
+ * @param phid An attached phidget themperature sensor handle.
+ * @param index The thermocouple index.
+ * @param type The thermocouple type.
+ */
+CHDRSETINDEX(TemperatureSensor, ThermocoupleType, CPhidgetTemperatureSensor_ThermocoupleType type)
+
+#ifndef REMOVE_DEPRECATED
+DEP_CHDRGET("Deprecated - use CPhidgetTemepratureSensor_getTemperatureInputCount",TemperatureSensor,NumTemperatureInputs,int *)
+#endif
+
+#ifndef EXTERNALPROTO
+#define TEMPSENSOR_MAXSENSORS 8
+
+#define GAIN 85.0
+#define OFFSET_200 -6.5
+#define OFFSET_300 ((200.0/237.0)*5.0)
+
+#define PHIDID_TEMPERATURESENSOR_4_GAIN ((80 / 2.2) + 5)
+//using 53.6K + 10K offset resistors: VOffset = (4.096Vref * 10K) / (10K + 53.6K)
+#define PHIDID_TEMPERATURESENSOR_4_OFFSET (4.096 / 6.36)
+
+struct _CPhidgetTemperatureSensor {
+ CPhidget phid;
+
+ int (CCONV *fptrTemperatureChange)(CPhidgetTemperatureSensorHandle, void *, int, double);
+ void *fptrTemperatureChangeptr;
+
+ double AmbientTemperature;
+ double Temperature[TEMPSENSOR_MAXSENSORS];
+ double Potential[TEMPSENSOR_MAXSENSORS];
+
+ double lastTrigger[TEMPSENSOR_MAXSENSORS];
+
+ double TempChangeTrigger[TEMPSENSOR_MAXSENSORS];
+ CPhidgetTemperatureSensor_ThermocoupleType ThermocoupleType[TEMPSENSOR_MAXSENSORS];
+
+ double ambientTemperatureMax, ambientTemperatureMin;
+ double temperatureMax[TEMPSENSOR_MAXSENSORS], temperatureMin[TEMPSENSOR_MAXSENSORS];
+ double potentialMax, potentialMin;
+
+ unsigned char AmbientTemperatureError, TemperatureError[TEMPSENSOR_MAXSENSORS], PotentialError[TEMPSENSOR_MAXSENSORS];
+
+} typedef CPhidgetTemperatureSensorInfo;
+#endif
+
+/** @} */
+
+#endif
diff --git a/cphidgettextlcd.c b/cphidgettextlcd.c
new file mode 100644
index 0000000..c2433c5
--- /dev/null
+++ b/cphidgettextlcd.c
@@ -0,0 +1,1160 @@
+#include "stdafx.h"
+#include "cphidgettextlcd.h"
+#include "cusb.h"
+#include "csocket.h"
+#include "cthread.h"
+
+/*
+ Protocol Documentation
+
+ buffer[7] = packet type and screen number
+ Top 3 bits are screen number. [SSSCCCCC]
+ 0x01 - 0x07 = LCD command (data count)
+ 0x08 - 0x1F = Space for extra packet types:
+ 0x11 = Backlight, Brightness
+ buffer[0] = 0x00 for off, 0x01 for on
+ buffer[1] = 0x00 - 0xff (variable brightness where supported)
+ 0x12 = Contrast
+ buffer[0] = 0x00 - 0xff
+ 0x13 = Init
+ re-initializes a display - this can fix a display that's gone wonky, or bring up a display plugged in after power-up
+ anything else is ignored
+
+ HD44780-based Character-LCD
+ Documentation - http://home.iae.nl/users/pouweha/lcd/lcd0.shtml
+ http://www.doc.ic.ac.uk/~ih/doc/lcd/index.html
+
+ buffer[0-6] = LCD command / data
+ So sending a packet with any arbitrary set of LCD commands in 0-6 and the command length in 7 is how it works.
+ You can combine any number of commands / data in one packet - up to 7 bytes.
+ LCD commands - special characters:
+ 0x00 = escape the next character (can escape 0x00, 0x01, 0x02)
+ 0x01 = following is commands (clears RS)
+ 0x02 = following is data (sets RS)
+
+ Always leave in command mode (0x01) when you finish
+
+ So, we can send any command / data, but we can not read back anything (busy flag, CGRAM, DDRAM)
+
+ On our 2x20 display:
+ Display Data (DDRAM): Row 0 address 0x00-0x13, Row 1 address 0x40-0x53
+ Custom characters (CGRAM): 0x08-0x15 - don't use 0x00-0x07 because 0x00 will terminate displaystring early
+
+*/
+
+
+// === Internal Functions === //
+
+//clearVars - sets all device variables to unknown state
+CPHIDGETCLEARVARS(TextLCD)
+ int i;
+
+ for (i = 0; i<TEXTLCD_MAXSCREENS; i++)
+ {
+ //set data arrays to unknown
+ phid->cursorBlink[i] = PUNK_BOOL;
+ phid->cursorOn[i] = PUNK_BOOL;
+ phid->contrast[i] = PUNK_INT;
+ phid->backlight[i] = PUNK_BOOL;
+ phid->brightness[i] = PUNK_INT;
+ phid->contrastEcho[i] = PUNI_INT;
+ phid->backlightEcho[i] = PUNI_BOOL;
+ phid->brightnessEcho[i] = PUNI_INT;
+ phid->init[i] = 0;
+ phid->screenSize[i] = -1;
+ phid->rowCount[i] = PUNI_INT;
+ phid->columnCount[i] = PUNI_INT;
+ phid->cursorLocation[i] = 0;
+ phid->cursorColumn[i] = 0;
+ }
+
+ phid->currentScreen = 0;
+ phid->lastScreen = 0;
+
+ return EPHIDGET_OK;
+}
+
+//initAfterOpen - sets up the initial state of an object, reading in packets from the device if needed
+// used during attach initialization - on every attach
+CPHIDGETINIT(TextLCD)
+ int i;
+ unsigned char buffer[8] = {0};
+ int ret = EPHIDGET_OK;
+
+ TESTPTR(phid);
+
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_TEXTLCD_2x20:
+ case PHIDID_TEXTLCD_2x20_CUSTOM:
+ case PHIDID_TEXTLCD_2x20_w_0_8_8:
+ case PHIDID_TEXTLCD_2x20_w_8_8_8:
+ for (i = 0; i<phid->phid.attr.textlcd.numScreens; i++)
+ {
+ //set data arrays to unknown
+ phid->contrastEcho[i] = PUNK_INT;
+ phid->backlightEcho[i] = PUNK_BOOL;
+ phid->brightnessEcho[i] = PUNK_INT;
+ phid->screenSize[i] = PHIDGET_TEXTLCD_SCREEN_2x20;
+ phid->rowCount[i] = phid->phid.attr.textlcd.numRows;
+ phid->columnCount[i] = phid->phid.attr.textlcd.numColumns;
+ phid->cursorLocation[i] = 0;
+ phid->cursorColumn[i] = 0;
+ }
+ break;
+ case PHIDID_TEXTLCD_ADAPTER:
+ for (i = 0; i<phid->phid.attr.textlcd.numScreens; i++)
+ {
+ //set data arrays to unknown
+ phid->contrastEcho[i] = PUNK_INT;
+ phid->backlightEcho[i] = PUNK_BOOL;
+ phid->brightnessEcho[i] = PUNK_INT;
+ phid->screenSize[i] = PHIDGET_TEXTLCD_SCREEN_UNKNOWN;
+ phid->rowCount[i] = 0;
+ phid->columnCount[i] = 0;
+ phid->cursorLocation[i] = 0;
+ phid->cursorColumn[i] = 0;
+ }
+ break;
+ default:
+ return EPHIDGET_UNEXPECTED;
+ }
+
+ //Make sure no old writes are still pending
+ phid->outputPacketLen = 0;
+
+ phid->currentScreen = 0;
+ phid->lastScreen = 0;
+
+ phid->fullStateEcho = PFALSE;
+
+ //Device specific stuff
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_TEXTLCD_ADAPTER:
+ phid->fullStateEcho = PTRUE;
+ break;
+ case PHIDID_TEXTLCD_2x20:
+ case PHIDID_TEXTLCD_2x20_CUSTOM:
+ case PHIDID_TEXTLCD_2x20_w_0_8_8:
+ case PHIDID_TEXTLCD_2x20_w_8_8_8:
+ break;
+ default:
+ return EPHIDGET_UNEXPECTED;
+ }
+
+ //Make sure the TextLCD is in command mode! Also turn off cursor and cursor blink explicitly
+ for (i = 0; i<phid->phid.attr.textlcd.numScreens; i++)
+ {
+ buffer[0] = TEXTLCD_COMMAND_MODE;
+ buffer[1] = HD44780_DISPLAY_CNTRL | HD44780_DISPLAY_ON;
+ buffer[7] = 2 | TEXTLCD_SCREEN(i);
+ if ((ret = CUSBSendPacket((CPhidgetHandle)phid, buffer)) != EPHIDGET_OK)
+ return ret;
+
+ phid->cursorBlink[i] = 0;
+ phid->cursorOn[i] = 0;
+ }
+
+ //Issue a read if device supports state echo
+ if(phid->fullStateEcho)
+ CPhidget_read((CPhidgetHandle)phid);
+
+ //set everything to it's echo
+ for (i = 0; i<phid->phid.attr.textlcd.numScreens; i++)
+ {
+ phid->contrast[i] = phid->contrastEcho[i];
+ phid->backlight[i] = phid->backlightEcho[i];
+ phid->brightness[i] = phid->brightnessEcho[i];
+ }
+
+ return EPHIDGET_OK;
+}
+
+//dataInput - parses device packets
+CPHIDGETDATA(TextLCD)
+ int i;
+
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_TEXTLCD_ADAPTER:
+ {
+ for (i = 0; i<phid->phid.attr.textlcd.numScreens; i++)
+ {
+ phid->backlightEcho[i] = buffer[i];
+ phid->brightnessEcho[i] = buffer[i+2];
+ phid->contrastEcho[i] = buffer[i+4];
+ }
+ }
+ break;
+ case PHIDID_TEXTLCD_2x20_w_8_8_8:
+ case PHIDID_TEXTLCD_2x20:
+ case PHIDID_TEXTLCD_2x20_CUSTOM:
+ case PHIDID_TEXTLCD_2x20_w_0_8_8:
+ default:
+ return EPHIDGET_UNEXPECTED;
+ }
+ return EPHIDGET_OK;
+}
+
+//eventsAfterOpen - sends out an event for all valid data, used during attach initialization - not used
+CPHIDGETINITEVENTS(TextLCD)
+ phid=0;
+ return EPHIDGET_OK;
+}
+
+//getPacket - used by write thread to get the next packet to send to device
+CGETPACKET_BUF(TextLCD)
+
+//sendpacket - sends a packet to the device asynchronously, blocking if the 1-packet queue is full
+CSENDPACKET_BUF(TextLCD)
+
+//makePacket - constructs a packet using current device state
+CMAKEPACKETINDEXED(TextLCD)
+ int screen = phid->currentScreen;
+
+ TESTPTRS(phid, buffer)
+
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_TEXTLCD_2x20:
+ case PHIDID_TEXTLCD_2x20_CUSTOM:
+ case PHIDID_TEXTLCD_2x20_w_0_8_8:
+ case PHIDID_TEXTLCD_2x20_w_8_8_8:
+ case PHIDID_TEXTLCD_ADAPTER:
+ switch(Index)
+ {
+ case TEXTLCD_BACKLIGHT_PACKET: //backlight
+
+ //if unknown then this must have been called from setBrightness - they still need to enable the backlight
+ if (phid->backlight[screen] == PUNK_BOOL)
+ {
+ phid->backlight[screen] = PFALSE;
+ if(!phid->fullStateEcho)
+ phid->backlightEcho[screen] = phid->backlight[screen];
+ }
+
+ buffer[0] = phid->backlight[screen];
+
+ //Brightness where supported
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_TEXTLCD_2x20_w_8_8_8:
+ if (phid->phid.deviceVersion < 200)
+ break;
+ case PHIDID_TEXTLCD_ADAPTER:
+ //default the brightness to full
+ if (phid->brightness[screen] == PUNK_INT)
+ {
+ phid->brightness[screen] = 255;
+ if(!phid->fullStateEcho)
+ phid->brightnessEcho[screen] = phid->brightness[screen];
+ }
+ buffer[1] = phid->brightness[screen];
+ default:
+ break;
+ }
+
+ buffer[7] = TEXTLCD_BACKLIGHT_PACKET | TEXTLCD_SCREEN(screen);
+
+ break;
+ case TEXTLCD_CONTRAST_PACKET: //contrast
+ buffer[0] = (unsigned char)phid->contrast[screen];
+ buffer[7] = TEXTLCD_CONTRAST_PACKET | TEXTLCD_SCREEN(screen);
+
+ break;
+ case TEXTLCD_INIT_PACKET: //re-init a screen
+ if(phid->screenSize[screen] == PHIDGET_TEXTLCD_SCREEN_4x40 && screen == 0)
+ {
+ buffer[7] = TEXTLCD_INIT_PACKET | TEXTLCD_SCREEN(2); //screen '2' represents both screens 0 and 1, but ONLY for initialization!!
+ phid->cursorOn[1] = PFALSE;
+ phid->cursorBlink[1] = PFALSE;
+ phid->cursorColumn[1] = 0;
+ phid->cursorLocation[1] = 0;
+ }
+ else
+ buffer[7] = TEXTLCD_INIT_PACKET | TEXTLCD_SCREEN(screen);
+
+ phid->lastScreen = 0;
+ phid->cursorOn[screen] = PFALSE;
+ phid->cursorBlink[screen] = PFALSE;
+ phid->cursorColumn[screen] = 0;
+ phid->cursorLocation[screen] = 0;
+
+ break;
+ case TEXTLCD_CURSOR_PACKET: //LCD commands - Cursor
+
+ if (phid->cursorOn[screen] == PUNK_BOOL)
+ {
+ phid->cursorOn[screen] = PFALSE;
+ }
+
+ if (phid->cursorBlink[screen] == PUNK_BOOL)
+ {
+ phid->cursorBlink[screen] = PFALSE;
+ }
+
+ buffer[0] = HD44780_DISPLAY_CNTRL | HD44780_DISPLAY_ON;
+ //only actually turn on if the cursor is on-display
+ if((phid->screenSize[0] == PHIDGET_TEXTLCD_SCREEN_4x40 && screen == 0 && phid->cursorColumn[phid->lastScreen] < phid->columnCount[screen])
+ || (phid->cursorColumn[screen] < phid->columnCount[screen]))
+ {
+ if (phid->cursorOn[screen])
+ buffer[0] |= HD44780_CURSOR_ON;
+ if (phid->cursorBlink[screen])
+ buffer[0] |= HD44780_CURSOR_BLINK_ON;
+ }
+
+ //Special case - 4x40, rows 2 and 3
+ if(phid->screenSize[0] == PHIDGET_TEXTLCD_SCREEN_4x40 && screen == 0)
+ buffer[7] = 1 | TEXTLCD_SCREEN(phid->lastScreen);
+ else
+ buffer[7] = 1 | TEXTLCD_SCREEN(screen);
+
+ break;
+ default:
+ return EPHIDGET_UNEXPECTED;
+ }
+ break;
+ default:
+ return EPHIDGET_UNEXPECTED;
+ }
+
+ return EPHIDGET_OK;
+}
+
+/* deals with moving the cursor/blink between the 'screens' on a 4x40 setup
+ * make sure this is called from within a write lock
+ */
+//static int dealWithCursor(CPhidgetTextLCDHandle phid, int screen)
+//{
+// unsigned char buffer[8] = {0};
+// int ret = EPHIDGET_OK;
+//
+// //Switching between screens for special 4x40 case
+// if(phid->screenSize[0] == PHIDGET_TEXTLCD_SCREEN_4x40)
+// {
+// if(phid->cursorOn[0] == PTRUE || phid->cursorBlink[0] == PTRUE)
+// {
+// if(phid->lastScreen != screen)
+// {
+// buffer[0] = HD44780_DISPLAY_CNTRL | HD44780_DISPLAY_ON;
+// buffer[7] = 1 | TEXTLCD_SCREEN(phid->lastScreen);
+//
+// if ((ret = CPhidgetTextLCD_sendpacket(phid, buffer)) != EPHIDGET_OK)
+// return ret;
+//
+// buffer[0] = HD44780_DISPLAY_CNTRL | HD44780_DISPLAY_ON;
+// if (phid->cursorOn[0])
+// buffer[0] |= HD44780_CURSOR_ON;
+// if (phid->cursorBlink[0])
+// buffer[0] |= HD44780_CURSOR_BLINK_ON;
+// buffer[7] = 1 | TEXTLCD_SCREEN(screen);
+//
+// if ((ret = CPhidgetTextLCD_sendpacket(phid, buffer)) != EPHIDGET_OK)
+// return ret;
+// }
+// }
+// }
+//
+// phid->lastScreen = screen;
+// return ret;
+//}
+
+/*
+ * Returns DDRAM position for the requested row and col
+ * May change screen number for the special 4x40 case
+ */
+static int getScreenAndPos(CPhidgetTextLCDHandle phid, int *screen, int row, int col)
+{
+ int cols = phid->columnCount[*screen];
+ int pos = 0;
+
+ switch(row)
+ {
+ case 0:
+ pos = 0x00;
+ break;
+ case 1:
+ pos = 0x40;
+ break;
+ case 2:
+ if(cols == 16)
+ {
+ pos = 0x10;
+ }
+ else if(cols == 40)
+ {
+ pos = 0x00;
+ *screen = 1;
+ }
+ else
+ {
+ pos = 0x14;
+ }
+ break;
+ case 3:
+ if(cols == 16)
+ {
+ pos = 0x50;
+ }
+ else if(cols == 40)
+ {
+ pos = 0x40;
+ *screen = 1;
+ }
+ else
+ {
+ pos = 0x54;
+ }
+ break;
+ }
+
+ return pos+col;
+}
+
+// === Exported Functions === //
+
+//create and initialize a device structure
+CCREATE(TextLCD, PHIDCLASS_TEXTLCD)
+
+CGET(TextLCD,RowCount,int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_TEXTLCD)
+ TESTATTACHED
+
+ MASGN(rowCount[phid->currentScreen])
+}
+
+CGET(TextLCD,ColumnCount,int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_TEXTLCD)
+ TESTATTACHED
+
+ MASGN(columnCount[phid->currentScreen])
+}
+
+CGET(TextLCD,ScreenCount,int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_TEXTLCD)
+ TESTATTACHED
+
+ MASGN(phid.attr.textlcd.numScreens)
+}
+
+CGET(TextLCD,Backlight,int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_TEXTLCD)
+ TESTATTACHED
+ TESTMASGN(backlightEcho[phid->currentScreen], PUNK_BOOL)
+
+ MASGN(backlightEcho[phid->currentScreen])
+}
+CSET(TextLCD,Backlight,int)
+ int Index;
+ TESTPTR(phid)
+ TESTDEVICETYPE(PHIDCLASS_TEXTLCD)
+ TESTATTACHED
+ TESTRANGE(PFALSE, PTRUE)
+
+ Index = phid->currentScreen;
+
+ if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
+ ADDNETWORKKEYINDEXED(Backlight, "%d", backlight);
+ else
+ {
+ SENDPACKETINDEXED(TextLCD, backlight[Index], TEXTLCD_BACKLIGHT_PACKET);
+
+ if(!phid->fullStateEcho)
+ phid->backlightEcho[Index] = phid->backlight[Index];
+ }
+
+ return EPHIDGET_OK;
+}
+
+CGET(TextLCD,Brightness,int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_TEXTLCD)
+ TESTATTACHED
+
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_TEXTLCD_2x20_w_8_8_8:
+ if (phid->phid.deviceVersion < 200)
+ return EPHIDGET_UNSUPPORTED;
+ break;
+ case PHIDID_TEXTLCD_ADAPTER:
+ break;
+ case PHIDID_TEXTLCD_2x20:
+ case PHIDID_TEXTLCD_2x20_CUSTOM:
+ case PHIDID_TEXTLCD_2x20_w_0_8_8:
+ return EPHIDGET_UNSUPPORTED;
+ default:
+ return EPHIDGET_UNEXPECTED;
+ }
+
+ TESTMASGN(brightnessEcho[phid->currentScreen], PUNK_INT)
+
+ MASGN(brightnessEcho[phid->currentScreen])
+}
+CSET(TextLCD,Brightness,int)
+ int Index;
+ TESTPTR(phid)
+ TESTDEVICETYPE(PHIDCLASS_TEXTLCD)
+ TESTATTACHED
+
+ Index = phid->currentScreen;
+
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_TEXTLCD_2x20_w_8_8_8:
+ if (phid->phid.deviceVersion < 200)
+ return EPHIDGET_UNSUPPORTED;
+ break;
+ case PHIDID_TEXTLCD_ADAPTER:
+ break;
+ case PHIDID_TEXTLCD_2x20:
+ case PHIDID_TEXTLCD_2x20_CUSTOM:
+ case PHIDID_TEXTLCD_2x20_w_0_8_8:
+ return EPHIDGET_UNSUPPORTED;
+ default:
+ return EPHIDGET_UNEXPECTED;
+ }
+
+ TESTRANGE(0, 255)
+
+ if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
+ ADDNETWORKKEYINDEXED(Brightness, "%d", brightness);
+ else
+ {
+ SENDPACKETINDEXED(TextLCD, brightness[Index], TEXTLCD_BACKLIGHT_PACKET);
+
+ if(!phid->fullStateEcho)
+ phid->brightnessEcho[Index] = phid->brightness[Index];
+ }
+
+ return EPHIDGET_OK;
+}
+
+CGET(TextLCD,Contrast,int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_TEXTLCD)
+ TESTATTACHED
+ TESTMASGN(contrastEcho[phid->currentScreen], PUNK_INT)
+
+ MASGN(contrastEcho[phid->currentScreen])
+}
+CSET(TextLCD,Contrast,int)
+ int Index;
+ TESTPTR(phid)
+ TESTDEVICETYPE(PHIDCLASS_TEXTLCD)
+ TESTATTACHED
+ TESTRANGE(0, 255)
+
+ Index = phid->currentScreen;
+
+ if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
+ ADDNETWORKKEYINDEXED(Contrast, "%d", contrast);
+ else
+ {
+ SENDPACKETINDEXED(TextLCD, contrast[Index], TEXTLCD_CONTRAST_PACKET);
+
+ if(!phid->fullStateEcho)
+ phid->contrastEcho[Index] = phid->contrast[Index];
+ }
+
+ return EPHIDGET_OK;
+}
+
+CGET(TextLCD,CursorOn,int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_TEXTLCD)
+ TESTATTACHED
+ TESTMASGN(cursorOn[phid->currentScreen], PUNK_BOOL)
+
+ MASGN(cursorOn[phid->currentScreen])
+}
+CSET(TextLCD,CursorOn,int)
+ int Index;
+ TESTPTR(phid)
+ TESTDEVICETYPE(PHIDCLASS_TEXTLCD)
+ TESTATTACHED
+ TESTRANGE(PFALSE, PTRUE)
+
+ Index = phid->currentScreen;
+
+ if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
+ ADDNETWORKKEYINDEXED(CursorOn, "%d", cursorOn);
+ else
+ SENDPACKETINDEXED(TextLCD, cursorOn[Index], TEXTLCD_CURSOR_PACKET);
+
+ return EPHIDGET_OK;
+}
+
+CGET(TextLCD,CursorBlink,int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_TEXTLCD)
+ TESTATTACHED
+ TESTMASGN(cursorBlink[phid->currentScreen], PUNK_BOOL)
+
+ MASGN(cursorBlink[phid->currentScreen])
+}
+CSET(TextLCD,CursorBlink,int)
+ int Index;
+ TESTPTR(phid)
+ TESTDEVICETYPE(PHIDCLASS_TEXTLCD)
+ TESTATTACHED
+ TESTRANGE(PFALSE, PTRUE)
+
+ Index = phid->currentScreen;
+
+ if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
+ ADDNETWORKKEYINDEXED(CursorBlink, "%d", cursorBlink);
+ else
+ SENDPACKETINDEXED(TextLCD, cursorBlink[Index], TEXTLCD_CURSOR_PACKET);
+
+ return EPHIDGET_OK;
+}
+
+CGET(TextLCD,Screen,int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_TEXTLCD)
+ TESTATTACHED
+
+ MASGN(currentScreen)
+}
+CSET(TextLCD,Screen,int)
+ TESTPTR(phid)
+ TESTDEVICETYPE(PHIDCLASS_TEXTLCD)
+ TESTATTACHED
+ TESTRANGE(0, phid->phid.attr.textlcd.numScreens)
+
+ //This prevents a screen size change during a multi-packet write
+ CThread_mutex_lock(&phid->phid.writelock);
+ phid->currentScreen = newVal;
+ CThread_mutex_unlock(&phid->phid.writelock);
+
+ return EPHIDGET_OK;
+}
+
+CGET(TextLCD,ScreenSize,CPhidgetTextLCD_ScreenSize)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_TEXTLCD)
+ TESTATTACHED
+ TESTMASGN(screenSize[phid->currentScreen], PHIDGET_TEXTLCD_SCREEN_UNKNOWN)
+
+ MASGN(screenSize[phid->currentScreen])
+}
+CSET(TextLCD,ScreenSize,CPhidgetTextLCD_ScreenSize)
+ int otherScreen;
+ int screen;
+
+ TESTPTR(phid)
+ TESTDEVICETYPE(PHIDCLASS_TEXTLCD)
+ TESTATTACHED
+
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_TEXTLCD_ADAPTER:
+ break;
+ case PHIDID_TEXTLCD_2x20_w_8_8_8:
+ case PHIDID_TEXTLCD_2x20:
+ case PHIDID_TEXTLCD_2x20_CUSTOM:
+ case PHIDID_TEXTLCD_2x20_w_0_8_8:
+ return EPHIDGET_UNSUPPORTED;
+ default:
+ return EPHIDGET_UNEXPECTED;
+ }
+
+ TESTRANGE(PHIDGET_TEXTLCD_SCREEN_NONE, PHIDGET_TEXTLCD_SCREEN_4x40)
+
+ screen = phid->currentScreen;
+
+ otherScreen = 1;
+ if(screen == 1)
+ otherScreen = 0;
+
+ switch(newVal)
+ {
+ case PHIDGET_TEXTLCD_SCREEN_NONE:
+ phid->rowCount[screen] = 0;
+ phid->columnCount[screen] = 0;
+ break;
+ case PHIDGET_TEXTLCD_SCREEN_1x8:
+ phid->rowCount[screen] = 1;
+ phid->columnCount[screen] = 8;
+ break;
+ case PHIDGET_TEXTLCD_SCREEN_2x8:
+ phid->rowCount[screen] = 2;
+ phid->columnCount[screen] = 8;
+ break;
+ case PHIDGET_TEXTLCD_SCREEN_1x16:
+ phid->rowCount[screen] = 1;
+ phid->columnCount[screen] = 16;
+ break;
+ case PHIDGET_TEXTLCD_SCREEN_2x16:
+ phid->rowCount[screen] = 2;
+ phid->columnCount[screen] = 16;
+ break;
+ case PHIDGET_TEXTLCD_SCREEN_4x16:
+ phid->rowCount[screen] = 4;
+ phid->columnCount[screen] = 16;
+ break;
+ case PHIDGET_TEXTLCD_SCREEN_2x20:
+ phid->rowCount[screen] = 2;
+ phid->columnCount[screen] = 20;
+ break;
+ case PHIDGET_TEXTLCD_SCREEN_4x20:
+ phid->rowCount[screen] = 4;
+ phid->columnCount[screen] = 20;
+ break;
+ case PHIDGET_TEXTLCD_SCREEN_2x24:
+ phid->rowCount[screen] = 2;
+ phid->columnCount[screen] = 24;
+ break;
+ case PHIDGET_TEXTLCD_SCREEN_1x40:
+ phid->rowCount[screen] = 1;
+ phid->columnCount[screen] = 40;
+ break;
+ case PHIDGET_TEXTLCD_SCREEN_2x40:
+ phid->rowCount[screen] = 2;
+ phid->columnCount[screen] = 40;
+ break;
+ case PHIDGET_TEXTLCD_SCREEN_4x40:
+ //Only supported on screen 0
+ if(screen != 0)
+ return EPHIDGET_UNSUPPORTED;
+
+ phid->rowCount[screen] = 4;
+ phid->columnCount[screen] = 40;
+
+ //sets other screen to none
+ phid->rowCount[otherScreen] = 0;
+ phid->columnCount[otherScreen] = 0;
+ //set screen size
+ if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
+ {
+ int newVal = PHIDGET_TEXTLCD_SCREEN_NONE;
+ int Index = otherScreen;
+ ADDNETWORKKEYINDEXED(ScreenSize, "%d", screenSize);
+ }
+ else
+ {
+ phid->screenSize[otherScreen] = PHIDGET_TEXTLCD_SCREEN_NONE;
+ }
+ break;
+ default:
+ return EPHIDGET_UNEXPECTED;
+ }
+
+ phid->lastScreen = 0;
+
+ //can't have a 4x40 with anything other then NONE
+ if(phid->screenSize[otherScreen] == PHIDGET_TEXTLCD_SCREEN_4x40 && newVal != PHIDGET_TEXTLCD_SCREEN_NONE)
+ {
+ //sets other screen to none
+ phid->rowCount[otherScreen] = 0;
+ phid->columnCount[otherScreen] = 0;
+ //set screen size
+ if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
+ {
+ int newVal = PHIDGET_TEXTLCD_SCREEN_NONE;
+ int Index = otherScreen;
+ ADDNETWORKKEYINDEXED(ScreenSize, "%d", screenSize);
+ }
+ else
+ {
+ phid->screenSize[otherScreen] = PHIDGET_TEXTLCD_SCREEN_NONE;
+ }
+ }
+
+ //set screen size
+ if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
+ {
+ int Index = screen;
+ ADDNETWORKKEYINDEXED(ScreenSize, "%d", screenSize);
+ }
+ else
+ {
+ phid->screenSize[screen] = newVal;
+ }
+
+ return EPHIDGET_OK;
+}
+
+
+PHIDGET21_API int CCONV CPhidgetTextLCD_setDisplayCharacter (CPhidgetTextLCDHandle phid, int Row, int Column, unsigned char Character)
+{
+ unsigned char buffer[8] = {0};
+ int ret = EPHIDGET_OK;
+ int screen, screenEnable, pos, buf_ptr;
+
+ TESTPTR(phid)
+ TESTDEVICETYPE(PHIDCLASS_TEXTLCD)
+ TESTATTACHED
+
+ screen = screenEnable = phid->currentScreen;
+
+ if (Row >= phid->rowCount[screen] || Row < 0) return EPHIDGET_OUTOFBOUNDS;
+ if (Column >= phid->columnCount[screen] || Column < 0) return EPHIDGET_OUTOFBOUNDS;
+
+ if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
+ {
+ char newVal = Character;
+ //int Index = (Row + 1) * (Column + 1);
+ int Index = (Column << 16) + (Row << 8) + screen;
+ ADDNETWORKKEYINDEXED(DisplayCharacter, "%c", chars[screen]);
+ }
+ else
+ {
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_TEXTLCD_2x20:
+ case PHIDID_TEXTLCD_2x20_CUSTOM:
+ case PHIDID_TEXTLCD_2x20_w_0_8_8:
+ case PHIDID_TEXTLCD_2x20_w_8_8_8:
+ case PHIDID_TEXTLCD_ADAPTER:
+
+ CThread_mutex_lock(&phid->phid.writelock);
+
+ pos = getScreenAndPos(phid, &screenEnable, Row, Column);
+ phid->cursorLocation[screenEnable] = pos + 1;
+ phid->cursorColumn[screenEnable] = Column + 1;
+ buf_ptr = 0;
+ //turn off cursor if it's on
+ if(phid->cursorOn[screen] == PTRUE || phid->cursorBlink[screen] == PTRUE)
+ {
+ if(phid->screenSize[screen] == PHIDGET_TEXTLCD_SCREEN_4x40 && screen == 0 && screenEnable != phid->lastScreen)
+ {
+ //4x40 and the cursor is on on the other screen, need to turn it off in it's own packet
+ buffer[0] = HD44780_DISPLAY_CNTRL | HD44780_DISPLAY_ON;
+ buffer[7] = 1 | TEXTLCD_SCREEN(phid->lastScreen);
+
+ if ((ret = CPhidgetTextLCD_sendpacket(phid, buffer)) != EPHIDGET_OK)
+ goto done;
+ }
+ else
+ buffer[buf_ptr++] = HD44780_DISPLAY_CNTRL | HD44780_DISPLAY_ON; /* disable cursors */
+ }
+
+ buffer[buf_ptr++] = pos | HD44780_SET_DDRAM_ADDR; /* Address */
+ buffer[buf_ptr++] = TEXTLCD_DATA_MODE;
+ //escape if needed
+ if(Character == 0x00 || Character == 0x01 || Character == 0x02)
+ buffer[buf_ptr++] = TEXTLCD_ESCAPE_CHAR;
+ buffer[buf_ptr++] = Character;
+ buffer[buf_ptr++] = TEXTLCD_COMMAND_MODE; //always leave in command mode
+ //turn cursor back on if we turned it off
+ if(phid->cursorOn[screen] == PTRUE || phid->cursorBlink[screen] == PTRUE)
+ {
+ if(phid->cursorColumn[screenEnable] < phid->columnCount[screen])
+ {
+ buffer[buf_ptr] = HD44780_DISPLAY_CNTRL | HD44780_DISPLAY_ON; /* enable cursors */
+ if(phid->screenSize[0] == PHIDGET_TEXTLCD_SCREEN_4x40)
+ {
+ if (phid->cursorOn[0])
+ buffer[buf_ptr] |= HD44780_CURSOR_ON;
+ if (phid->cursorBlink[0])
+ buffer[buf_ptr] |= HD44780_CURSOR_BLINK_ON;
+ }
+ else
+ {
+ if (phid->cursorOn[screenEnable])
+ buffer[buf_ptr] |= HD44780_CURSOR_ON;
+ if (phid->cursorBlink[screenEnable])
+ buffer[buf_ptr] |= HD44780_CURSOR_BLINK_ON;
+ }
+ buf_ptr++;
+ }
+ }
+ //don't need to set DDRAM position it's already right
+ //at most, we're sending 7 bytes, so it's safe for one packet
+ buffer[7] = buf_ptr | TEXTLCD_SCREEN(screenEnable);
+
+ if((ret = CPhidgetTextLCD_sendpacket(phid, buffer)) != EPHIDGET_OK)
+ goto done;
+
+ //so we know what screen we last wrote to
+ phid->lastScreen = screenEnable;
+done:
+ CThread_mutex_unlock(&phid->phid.writelock);
+ break;
+ default:
+ return EPHIDGET_UNEXPECTED;
+ }
+ }
+ return ret;
+}
+
+PHIDGET21_API int CCONV CPhidgetTextLCD_setCustomCharacter (CPhidgetTextLCDHandle phid, int Index, int Val1, int Val2)
+{
+ unsigned char buffer[8] = {0};
+ int ret = EPHIDGET_OK;
+ char newVal[50];
+ int screen;
+
+ TESTPTR(phid)
+ TESTDEVICETYPE(PHIDCLASS_TEXTLCD)
+ TESTATTACHED
+
+ screen = phid->currentScreen;
+
+ if ((Index < 8) || (Index > 15)) return EPHIDGET_INVALIDARG;
+
+ if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
+ {
+ Index = (Index << 8) + screen;
+ sprintf(newVal, "%d,%d", Val1, Val2);
+ ADDNETWORKKEYINDEXED(CustomCharacter, "%s", customs[screen]);
+ }
+ else
+ {
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_TEXTLCD_2x20:
+ case PHIDID_TEXTLCD_2x20_CUSTOM:
+ case PHIDID_TEXTLCD_2x20_w_0_8_8:
+ case PHIDID_TEXTLCD_2x20_w_8_8_8:
+ case PHIDID_TEXTLCD_ADAPTER:
+
+ //actual index is 0-7
+ Index -= 8;
+
+ CThread_mutex_lock(&phid->phid.writelock);
+again:
+ //buffer[0] = TEXTLCD_COMMAND_MODE;
+
+ buffer[0] = HD44780_DISPLAY_CNTRL | HD44780_DISPLAY_ON; /* disable cursors */
+ buffer[1] = HD44780_SET_CGRAM_ADDR | TEXTLCD_CGRAM_ADDR(Index); /* set CGRAM address */
+ buffer[2] = TEXTLCD_DATA_MODE;
+ buffer[3] = (Val1 & 0x1F) | 0x80;
+ buffer[4] = ((Val1 >> 5) & 0x1F) | 0x80;
+ buffer[5] = ((Val1 >> 10) & 0x1F) | 0x80;
+ buffer[6] = ((Val1 >> 15) & 0x1F) | 0x80;
+ buffer[7] = 7 | TEXTLCD_SCREEN(screen);
+
+ if ((ret = CPhidgetTextLCD_sendpacket(phid, buffer)) != EPHIDGET_OK)
+ goto done;
+
+ buffer[0] = (Val2 & 0x1F) | 0x80;
+ buffer[1] = ((Val2 >> 5) & 0x1F) | 0x80;
+ buffer[2] = ((Val2 >> 10) & 0x1F) | 0x80;
+ buffer[3] = ((Val2 >> 15) & 0x1F) | 0x80;
+ buffer[4] = TEXTLCD_COMMAND_MODE;
+ buffer[5] = phid->cursorLocation[screen] | HD44780_SET_DDRAM_ADDR; /* reset DDRAM address for cursors */
+ buffer[6] = HD44780_DISPLAY_CNTRL | HD44780_DISPLAY_ON; /* enable cursors */
+ if(phid->screenSize[0] == PHIDGET_TEXTLCD_SCREEN_4x40 && phid->cursorColumn[screen] < phid->columnCount[0])
+ {
+ // for 4x40, only re-enable a cursor if we're on the last written to screen
+ if(screen == phid->lastScreen)
+ {
+ if (phid->cursorOn[0])
+ buffer[6] |= HD44780_CURSOR_ON;
+ if (phid->cursorBlink[0])
+ buffer[6] |= HD44780_CURSOR_BLINK_ON;
+ }
+ }
+ else if(phid->cursorColumn[screen] < phid->columnCount[screen])
+ {
+ if (phid->cursorOn[screen])
+ buffer[6] |= HD44780_CURSOR_ON;
+ if (phid->cursorBlink[screen])
+ buffer[6] |= HD44780_CURSOR_BLINK_ON;
+ }
+ buffer[7] = 7 | TEXTLCD_SCREEN(screen);
+
+ if ((ret = CPhidgetTextLCD_sendpacket(phid, buffer)) != EPHIDGET_OK)
+ goto done;
+
+ /* for 4x40, we need to set these characters on screen 1 as well */
+ if(phid->screenSize[0] == PHIDGET_TEXTLCD_SCREEN_4x40 && screen==0)
+ {
+ screen = 1;
+ goto again;
+ }
+done:
+ CThread_mutex_unlock(&phid->phid.writelock);
+ break;
+ default:
+ return EPHIDGET_UNEXPECTED;
+ }
+ }
+
+ return ret;
+}
+
+//0x00 is the escape character
+//escape 0x01 and 0x02 because these are interpreted as special commands by the firmware
+//we don't have to worry about 0x00 in the input string because that would end the string.
+static void escapeLcdString(char *string, char *buffer, int *buf_ptr)
+{
+ unsigned int ui;
+ size_t len = strlen(string);
+
+ //Escape 0x01, 0x02
+ for (ui = 0; ui<len; ui++)
+ {
+ if ((string[ui] == 0x01) || (string[ui] == 0x02))
+ buffer[(*buf_ptr)++] = TEXTLCD_ESCAPE_CHAR;
+ buffer[(*buf_ptr)++] = string[ui];
+ }
+}
+
+CSETINDEX(TextLCD, DisplayString, char *)
+ int i, j, buf_ptr, ret = EPHIDGET_OK;
+ size_t len;
+ unsigned char form_buffer[250] = {0};
+ unsigned char buffer[8] = {0};
+ int screen, screenEnable, pos;
+
+ TESTPTR(phid)
+ TESTDEVICETYPE(PHIDCLASS_TEXTLCD)
+ TESTATTACHED
+
+ len = strlen(newVal);
+ screen = screenEnable = phid->currentScreen;
+
+ TESTINDEX(rowCount[screen])
+
+ if (len > (size_t)phid->columnCount[screen]) return EPHIDGET_INVALIDARG;
+
+ if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
+ {
+ Index = (Index << 8) + screen;
+ ADDNETWORKKEYINDEXED(DisplayString, "%s", strings[screen]);
+ }
+ else
+ {
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_TEXTLCD_2x20:
+ case PHIDID_TEXTLCD_2x20_CUSTOM:
+ case PHIDID_TEXTLCD_2x20_w_0_8_8:
+ case PHIDID_TEXTLCD_2x20_w_8_8_8:
+ case PHIDID_TEXTLCD_ADAPTER:
+ CThread_mutex_lock(&phid->phid.writelock);
+
+ //DDRAM address of start of selected row
+ pos = getScreenAndPos(phid, &screenEnable, Index, 0);
+ phid->cursorLocation[screenEnable] = pos + len;
+ phid->cursorColumn[screenEnable] = len;
+
+ buf_ptr = 0;
+ form_buffer[buf_ptr++] = TEXTLCD_COMMAND_MODE; /* Command Mode */
+
+ //turn off cursor if it's on
+ if(phid->cursorOn[screen] == PTRUE || phid->cursorBlink[screen] == PTRUE)
+ {
+ if(phid->screenSize[screen] == PHIDGET_TEXTLCD_SCREEN_4x40 && screen == 0 && screenEnable != phid->lastScreen)
+ {
+ //4x40 and the cursor is on on the other screen, need to turn it off in it's own packet
+ buffer[0] = HD44780_DISPLAY_CNTRL | HD44780_DISPLAY_ON;
+ buffer[7] = 1 | TEXTLCD_SCREEN(phid->lastScreen);
+
+ if ((ret = CPhidgetTextLCD_sendpacket(phid, buffer)) != EPHIDGET_OK)
+ goto done;
+ }
+ else
+ form_buffer[buf_ptr++] = HD44780_DISPLAY_CNTRL | HD44780_DISPLAY_ON; /* disable cursors */
+ }
+
+ form_buffer[buf_ptr++] = pos | HD44780_SET_DDRAM_ADDR; /* Set DDRAM Address */
+ form_buffer[buf_ptr++] = TEXTLCD_DATA_MODE; /* Data Mode */
+
+ /* get escaped string */
+ escapeLcdString(newVal, (char *)form_buffer, &buf_ptr);
+
+ /* fill rest of the row with spaces */
+ for (i = 0; i < (phid->columnCount[screen] - (int)len); i++)
+ form_buffer[buf_ptr++] = ' ';
+
+ form_buffer[buf_ptr++] = TEXTLCD_COMMAND_MODE; /* Command Mode */
+ form_buffer[buf_ptr++] = phid->cursorLocation[screenEnable] | HD44780_SET_DDRAM_ADDR; /* Set DDRAM Address so cursor appears in the right place */
+
+ /* re-enable the cursors if we need to */
+ if((phid->cursorOn[screen] == PTRUE || phid->cursorBlink[screen] == PTRUE)
+ && phid->cursorColumn[screenEnable] < phid->columnCount[screen])
+ {
+ unsigned char cursorData = HD44780_DISPLAY_CNTRL | HD44780_DISPLAY_ON;
+ if (phid->cursorOn[screen])
+ cursorData |= HD44780_CURSOR_ON;
+ if (phid->cursorBlink[screen])
+ cursorData |= HD44780_CURSOR_BLINK_ON;
+ form_buffer[buf_ptr++] = cursorData;
+ }
+
+ /* we have to send the whole form_buffer, 7 bytes at a time */
+ for (i = 0; i<buf_ptr; i+=7)
+ {
+ /* zero out packet */
+ ZEROMEM(buffer, 8);
+
+ /* data length for this packet */
+ len = ( ((buf_ptr - i) > 7) ? 7 : (buf_ptr - i) );
+
+ /* fill in data */
+ for (j = 0; j < (int)len; j++)
+ buffer[j] = form_buffer[i + j];
+
+ /* choose screen and data length */
+ buffer[7] = (unsigned char)len | TEXTLCD_SCREEN(screenEnable);
+
+ /* send to device */
+ if ((ret = CPhidgetTextLCD_sendpacket(phid, buffer)) != EPHIDGET_OK)
+ goto done;
+ }
+
+ //so we know what screen we last wrote to
+ phid->lastScreen = screenEnable;
+
+done:
+ CThread_mutex_unlock(&phid->phid.writelock);
+ break;
+ default:
+ return EPHIDGET_UNEXPECTED;
+ }
+ }
+ return ret;
+}
+
+PHIDGET21_API int CCONV CPhidgetTextLCD_initialize(CPhidgetTextLCDHandle phid)
+{
+ int Index, newVal=1;
+ TESTPTR(phid)
+ TESTDEVICETYPE(PHIDCLASS_TEXTLCD)
+ TESTATTACHED
+
+ Index = phid->currentScreen;
+
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_TEXTLCD_ADAPTER:
+ break;
+ case PHIDID_TEXTLCD_2x20:
+ case PHIDID_TEXTLCD_2x20_CUSTOM:
+ case PHIDID_TEXTLCD_2x20_w_0_8_8:
+ case PHIDID_TEXTLCD_2x20_w_8_8_8:
+ return EPHIDGET_UNSUPPORTED;
+ default:
+ return EPHIDGET_UNEXPECTED;
+ }
+
+ if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
+ {
+ int newVal = phid->init[Index]^1;
+ ADDNETWORKKEYINDEXED(Init, "%d", init);
+ }
+ else
+ SENDPACKETINDEXED(TextLCD, init[Index], TEXTLCD_INIT_PACKET);
+
+ return EPHIDGET_OK;
+}
+
+// === Deprecated Functions === //
+
+CGET(TextLCD,NumRows,int)
+ return CPhidgetTextLCD_getRowCount(phid, pVal);
+}
+CGET(TextLCD,NumColumns,int)
+ return CPhidgetTextLCD_getColumnCount(phid, pVal);
+}
diff --git a/cphidgettextlcd.h b/cphidgettextlcd.h
new file mode 100644
index 0000000..adc1e4d
--- /dev/null
+++ b/cphidgettextlcd.h
@@ -0,0 +1,237 @@
+#ifndef __CPHIDGETTEXTLCD
+#define __CPHIDGETTEXTLCD
+#include "cphidget.h"
+
+/** \defgroup phidtextlcd Phidget TextLCD
+ * \ingroup phidgets
+ * Calls specific to the Phidget Text LCD. See the product manual for more specific API details, supported functionality, units, etc.
+ * @{
+ */
+
+DPHANDLE(TextLCD)
+CHDRSTANDARD(TextLCD)
+
+/**
+ * Gets the number of rows supported by this display.
+ * @param phid An attached phidget text lcd handle.
+ * @param count The row count.
+ */
+CHDRGET(TextLCD,RowCount,int *count)
+/**
+ * Gets the number of columns per supported by this display.
+ * @param phid An attached phidget text lcd handle.
+ * @param count The Column count.
+ */
+CHDRGET(TextLCD,ColumnCount,int *count)
+
+/**
+ * Gets the state of the backlight.
+ * @param phid An attached phidget text lcd handle.
+ * @param backlightState The backlight state. Possible values are \ref PTRUE and \ref PFALSE.
+ */
+CHDRGET(TextLCD,Backlight,int *backlightState)
+/**
+ * Sets the state of the backlight.
+ * @param phid An attached phidget text lcd handle.
+ * @param backlightState The backlight state. Possible values are \ref PTRUE and \ref PFALSE.
+ */
+CHDRSET(TextLCD,Backlight,int backlightState)
+/**
+ * Gets the brightness of the backlight. Not supported on all TextLCDs
+ * @param phid An attached phidget text lcd handle.
+ * @param brightness The backlight brightness (0-255).
+ */
+CHDRGET(TextLCD,Brightness,int *brightness)
+/**
+ * Sets the brightness of the backlight. Not supported on all TextLCDs
+ * @param phid An attached phidget text lcd handle.
+ * @param brightness The backlight brightness (0-255).
+ */
+CHDRSET(TextLCD,Brightness,int brightness)
+/**
+ * Gets the last set contrast value.
+ * @param phid An attached phidget text lcd handle.
+ * @param contrast The contrast (0-255).
+ */
+CHDRGET(TextLCD,Contrast,int *contrast)
+/**
+ * Sets the last set contrast value.
+ * @param phid An attached phidget text lcd handle.
+ * @param contrast The contrast (0-255).
+ */
+CHDRSET(TextLCD,Contrast,int contrast)
+/**
+ * Gets the cursor visible state.
+ * @param phid An attached phidget text lcd handle.
+ * @param cursorState The state of the cursor.
+ */
+CHDRGET(TextLCD,CursorOn,int *cursorState)
+/**
+ * Sets the cursor visible state.
+ * @param phid An attached phidget text lcd handle.
+ * @param cursorState The state of the cursor.
+ */
+CHDRSET(TextLCD,CursorOn,int cursorState)
+/**
+ * Gets the cursor blink state.
+ * @param phid An attached phidget text lcd handle.
+ * @param cursorBlinkState The cursor blink state.
+ */
+CHDRGET(TextLCD,CursorBlink,int *cursorBlinkState)
+/**
+ * Sets the cursor blink state.
+ * @param phid An attached phidget text lcd handle.
+ * @param cursorBlinkState The cursor blink state.
+ */
+CHDRSET(TextLCD,CursorBlink,int cursorBlinkState)
+/**
+ * Sets a custom character. See the product manual for more information.
+ * @param phid An attached phidget text lcd handle.
+ * @param index The custom character index (8-15).
+ * @param var1 The first part of the custom character.
+ * @param var2 The second part of the custom character.
+ */
+CHDRSETINDEX(TextLCD,CustomCharacter,int var1,int var2)
+/**
+ * Sets a single character on the display.
+ * @param phid An attached phidget text lcd handle.
+ * @param index The row index.
+ * @param column The column index.
+ * @param character The character to display.
+ */
+CHDRSETINDEX(TextLCD,DisplayCharacter,int column,unsigned char character)
+/**
+ * Sets a row on the display.
+ * @param phid An attached phidget text lcd handle.
+ * @param index The row index.
+ * @param displayString The string to display. Make sure this is not longer then \ref CPhidgetTextLCD_getColumnCount.
+ */
+CHDRSETINDEX(TextLCD,DisplayString,char *displayString)
+
+/**
+ * The Phidget TextLCD Adapter supports these screen sizes
+ */
+typedef enum {
+ PHIDGET_TEXTLCD_SCREEN_NONE = 1,/**< no screen attached */
+ PHIDGET_TEXTLCD_SCREEN_1x8, /**< 1 row, 8 column screen */
+ PHIDGET_TEXTLCD_SCREEN_2x8, /**< 2 row, 8 column screen */
+ PHIDGET_TEXTLCD_SCREEN_1x16, /**< 1 row, 16 column screen */
+ PHIDGET_TEXTLCD_SCREEN_2x16, /**< 2 row, 16 column screen */
+ PHIDGET_TEXTLCD_SCREEN_4x16, /**< 4 row, 16 column screen */
+ PHIDGET_TEXTLCD_SCREEN_2x20, /**< 2 row, 20 column screen */
+ PHIDGET_TEXTLCD_SCREEN_4x20, /**< 4 row, 20 column screen */
+ PHIDGET_TEXTLCD_SCREEN_2x24, /**< 2 row, 24 column screen */
+ PHIDGET_TEXTLCD_SCREEN_1x40, /**< 1 row, 40 column screen */
+ PHIDGET_TEXTLCD_SCREEN_2x40, /**< 2 row, 40 column screen */
+ PHIDGET_TEXTLCD_SCREEN_4x40, /**< 4 row, 40 column screen (special case, requires both screen connections) */
+ PHIDGET_TEXTLCD_SCREEN_UNKNOWN
+} CPhidgetTextLCD_ScreenSize;
+
+/**
+ * Gets the number of Display supported by this TextLCD
+ * @param phid An attached phidget text lcd handle.
+ * @param count The Screen count.
+ */
+CHDRGET(TextLCD,ScreenCount,int *count)
+/**
+ * Gets the active screen.
+ * @param phid An attached phidget text lcd handle.
+ * @param screenIndex The active screen.
+ */
+CHDRGET(TextLCD,Screen,int *screenIndex)
+/**
+ * Sets the active screen. This is the screen that all subsequent API calls will apply to.
+ * @param phid An attached phidget text lcd handle.
+ * @param screenIndex The active screen.
+ */
+CHDRSET(TextLCD,Screen,int screenIndex)
+/**
+ * Gets the screen size.
+ * @param phid An attached phidget text lcd handle.
+ * @param screenSize The screen size.
+ */
+CHDRGET(TextLCD,ScreenSize,CPhidgetTextLCD_ScreenSize *screenSize)
+/**
+ * Sets the active screen size. Only supported on the TextLCD Adapter.
+ * @param phid An attached phidget text lcd handle.
+ * @param screenSize The screen size.
+ */
+CHDRSET(TextLCD,ScreenSize,CPhidgetTextLCD_ScreenSize screenSize)
+/**
+ * Initializes the active screen. Only supported on the TextLCD adapter.
+ * This should be called if a screen is attached after power up, or to clear the screen after
+ * setting the size.
+ * @param phid An attached phidget text lcd handle.
+ */
+PHIDGET21_API int CCONV CPhidgetTextLCD_initialize(CPhidgetTextLCDHandle phid);
+
+#ifndef REMOVE_DEPRECATED
+DEP_CHDRGET("Deprecated - use CPhidgetTextLCD_getRowCount",TextLCD,NumRows,int *)
+DEP_CHDRGET("Deprecated - use CPhidgetTextLCD_getColumnCount",TextLCD,NumColumns,int *)
+#endif
+
+#ifndef EXTERNALPROTO
+#define TEXTLCD_MAXROWS 2
+#define TEXTLCD_MAXCOLS 40
+#define TEXTLCD_MAXSCREENS 2
+
+#define TEXTLCD_CURSOR_PACKET 0x00
+#define TEXTLCD_BACKLIGHT_PACKET 0x11
+#define TEXTLCD_CONTRAST_PACKET 0x12
+#define TEXTLCD_INIT_PACKET 0x13
+
+#define TEXTLCD_SCREEN(x) (x << 5)
+#define TEXTLCD_CGRAM_ADDR(x) (x << 3) //each custom character takes 8 bytes of CGRAM storage
+
+#define TEXTLCD_ESCAPE_CHAR 0x00
+#define TEXTLCD_COMMAND_MODE 0x01
+#define TEXTLCD_DATA_MODE 0x02
+
+//HD44780 commands
+#define HD44780_CLEAR_DISPLAY 0x01
+#define HD44780_CURSOR_HOME 0x02
+
+//These are ORed together
+#define HD44780_DISPLAY_CNTRL 0x08
+#define HD44780_DISPLAY_ON 0x04
+#define HD44780_CURSOR_ON 0x02
+#define HD44780_CURSOR_BLINK_ON 0x01
+
+#define HD44780_SET_CGRAM_ADDR 0x40
+#define HD44780_SET_DDRAM_ADDR 0x80
+
+struct _CPhidgetTextLCD {
+ CPhidget phid;
+
+ int currentScreen;
+ int lastScreen;
+
+ unsigned char cursorOn[TEXTLCD_MAXSCREENS], cursorBlink[TEXTLCD_MAXSCREENS], backlight[TEXTLCD_MAXSCREENS];
+ int contrast[TEXTLCD_MAXSCREENS], brightness[TEXTLCD_MAXSCREENS];
+
+ int cursorLocation[TEXTLCD_MAXSCREENS], cursorColumn[TEXTLCD_MAXSCREENS];
+
+ unsigned char backlightEcho[TEXTLCD_MAXSCREENS];
+ int contrastEcho[TEXTLCD_MAXSCREENS], brightnessEcho[TEXTLCD_MAXSCREENS];
+
+ unsigned char fullStateEcho;
+
+ //used for network sets
+ char *customs[TEXTLCD_MAXSCREENS][16];
+ char chars[TEXTLCD_MAXSCREENS][TEXTLCD_MAXROWS * TEXTLCD_MAXCOLS];
+ char *strings[TEXTLCD_MAXSCREENS][TEXTLCD_MAXROWS];
+
+ //For TextLCD Adapter
+ int rowCount[TEXTLCD_MAXSCREENS], columnCount[TEXTLCD_MAXSCREENS];
+ CPhidgetTextLCD_ScreenSize screenSize[TEXTLCD_MAXSCREENS];
+
+ unsigned char init[TEXTLCD_MAXSCREENS];
+
+ unsigned char outputPacket[8];
+ unsigned int outputPacketLen;
+} typedef CPhidgetTextLCDInfo;
+#endif
+
+/** @} */
+
+#endif
diff --git a/cphidgettextled.c b/cphidgettextled.c
new file mode 100644
index 0000000..beacbc7
--- /dev/null
+++ b/cphidgettextled.c
@@ -0,0 +1,492 @@
+#include "stdafx.h"
+#include "cphidgettextled.h"
+#include "cusb.h"
+#include "csocket.h"
+#include "cthread.h"
+
+// === Internal Functions === //
+
+//clearVars - sets all device variables to unknown state
+CPHIDGETCLEARVARS(TextLED)
+
+ phid->brightness = PUNK_INT;
+
+ return EPHIDGET_OK;
+}
+
+//initAfterOpen - sets up the initial state of an object, reading in packets from the device if needed
+// used during attach initialization - on every attach
+CPHIDGETINIT(TextLED)
+ TESTPTR(phid);
+
+ //Make sure no old writes are still pending
+ phid->outputPacketLen = 0;
+
+ //set variables to unknown
+ phid->brightness = PUNK_INT;
+
+ return EPHIDGET_OK;
+}
+
+//dataInput - parses device packets - not used
+CPHIDGETDATA(TextLED)
+ phid = 0;
+ return EPHIDGET_OK;
+}
+
+//eventsAfterOpen - sends out an event for all valid data, used during attach initialization - not used
+CPHIDGETINITEVENTS(TextLED)
+ phid = 0;
+ return EPHIDGET_OK;
+}
+
+//getPacket - used by write thread to get the next packet to send to device
+CGETPACKET_BUF(TextLED)
+
+//sendpacket - sends a packet to the device asynchronously, blocking if the 1-packet queue is full
+CSENDPACKET_BUF(TextLED)
+
+const unsigned long LED_Brightness[33] = {
+ 0x00000000,
+ 0x00000001,
+ 0x00010001,
+ 0x01010001,
+
+ 0x01010101,
+ 0x01110101,
+ 0x01110111,
+ 0x11110111,
+
+ 0x11111111,
+ 0x11111115,
+ 0x11151115,
+ 0x15151115,
+
+ 0x15151515,
+ 0x55151515,
+ 0x55155515,
+ 0x55555515,
+
+ 0x55555555,
+ 0x55555557,
+ 0x55575557,
+ 0x57575557,
+
+ 0x57575757,
+ 0x77575757,
+ 0x77775757,
+ 0x77777757,
+
+ 0x77777777,
+ 0x7777777F,
+ 0x777F777F,
+ 0x7F7F777F,
+ 0x7F7F7F7F,
+
+ 0x7FFF7F7F,
+ 0x7FFF7FFF,
+ 0x7FFFFFFF,
+ 0xFFFFFFFF};
+
+//BL: Is this the same mapping as the LCD custom chars?
+const unsigned char LED_Translate[256] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00,
+ 0x7E, 0x42, 0x3B, 0x6B, 0x47, 0x6D, 0x7D, 0x4A,
+ 0x7F, 0x6F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+ 0x00, 0x5F, 0x7F, 0x3C, 0x73, 0x3D, 0x1D, 0x7C, /* A,B,C,D,E,F,G */
+ 0x57, 0x42, 0x72, 0x57, 0x34, 0x5E, 0x5E, 0x7E, /* H, I, J, K, L, M, N, O */
+ 0x1F, 0x7E, 0x5F, 0x6D, 0x1C, 0x76, 0x76, 0x76, /* P, Q, R, S, T, U, V, W */
+ 0x57, 0x67, 0x3B, 0x00, 0x00, 0x00, 0x00, 0x00, /* X, Y, Z */
+
+ 0x00, 0x5F, 0x7F, 0x3C, 0x73, 0x3D, 0x1D, 0x7C, /* A,B,C,D,E,F,G */
+ 0x57, 0x42, 0x72, 0x57, 0x34, 0x5E, 0x5E, 0x7E, /* H, I, J, K, L, M, N, O */
+ 0x1F, 0x7E, 0x5F, 0x6D, 0x1C, 0x76, 0x76, 0x76, /* P, Q, R, S, T, U, V, W */
+ 0x57, 0x67, 0x3B, 0x00, 0x00, 0x00, 0x00, 0x00, /* X, Y, Z */
+
+ 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
+ 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+ 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+ 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f};
+
+
+const unsigned char LEDV2_Table[512] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0 - 0x0F
+
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x10 - 0x1F
+
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x20 - 0x2F
+
+ 46, 177, 18, 48, 98, 131, 98, 178,
+ 70, 34, 108, 178, 108, 179, 48, 8,
+ 110, 179, 110, 178, 1, 4, 1, 8,
+ 16, 64, 0, 0, 128, 8, 110, 50, // 0x30 - 0x3F
+
+ 62, 147, 110, 35, 110, 179, 44, 129,
+ 46, 177, 108, 131, 108, 3, 44,179,
+ 78, 51, 33, 132, 34, 177, 20, 73,
+ 12, 129, 47, 53, 142, 113, 46, 177, // 0x40 - 0x4F
+
+ 110, 3, 110, 82, 110, 67, 108, 178,
+ 41,4, 70, 179, 20, 9, 6, 181,
+ 144, 72, 144, 4, 48, 136, 36, 129,
+ 128, 64, 34, 160, 0, 72, 0, 128, // 0x50 - 0x5F
+
+ 128, 0, 64, 179, 68, 179, 64, 131,
+ 2, 186, 64, 139, 108, 1, 18, 178,
+ 68, 35, 0, 4, 2, 112, 17, 68,
+ 4, 1, 64,55, 64,5, 64, 163, 204, 1, // 0x60 - 0x6F
+
+ 204, 8, 64, 1, 0, 0, 65, 6,
+ 0, 161, 0, 9, 0, 165, 144, 72,
+ 144, 8, 64, 136, 0, 0, 0, 0, // 0x70 - 0x7F
+
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x80 - 0x8F
+
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x90 - 0x9F
+
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xA0 - 0xAF
+
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xB0 - 0xBF
+
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xC0 - 0xCF
+
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xD0 - 0xDF
+
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xE0 - 0xEF
+
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; // 0xF0 - 0xFF
+
+
+/*
+A = 102, 35
+B = 110, 79
+C = 44, 129
+D = 46, 177
+E = 108,131
+F = 108, 3
+G = 44,179
+H = 78, 51
+I = 33, 132
+J = 34, 177
+K = 20, 73
+L = 12, 129
+M = 47, 53
+N = 142, 113
+O = 46, 177
+P = 110, 3
+Q = 110, 82
+R = 110, 67
+S = 108,178
+T = 41,4
+U = 66, 177
+V = 20, 9
+W = 6, 165
+X = 144, 72
+Y = 144, 4
+Z = 48, 136
+
+0 = 46,177
+1 = 18,48
+2 = 98, 131
+3 = 98,178
+4 = 70, 34
+5 = 108, 178
+6 = 108, 179
+7 = 48,136
+8 = 110, 179
+9 = 110,178
+
+a = 64, 179
+b = 68, 179
+c = 64, 131
+d = 2, 186
+e = 64, 139
+f = 108, 129
+g = 18, 178
+h = 68, 35
+i = 0, 04
+j = 2, 112
+k = 17, 68
+l = 4, 1
+m = 64,55
+n = 64,5
+o = 64, 163
+p = 204, 1
+q = 204, 8
+r = 64, 1
+s =
+t = 65, 6
+u = 0, 161
+v = 0, 9
+w = 0, 165
+x = 144, 72
+y = 144, 8
+z = 64, 136
+
+" = 3, 0
+] = 34, 160
+[ = 36, 129
+` = 128, 0
+' = 16, 0
+% = 24, 24
+
+*/
+
+//makePacket - constructs a packet using current device state
+CMAKEPACKETINDEXED(TextLED)
+ int brightness = 0;
+ char displayString[TEXTLED_MAXROWS][TEXTLED_MAXCOLS];
+ size_t length = 0;
+ int j, k, correction, result;
+ unsigned int ui;
+
+ correction = -1;
+
+ TESTPTRS(phid, buffer)
+
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_TEXTLED_1x8:
+ if ((phid->phid.deviceVersion >= 111) && (phid->phid.deviceVersion < 114))
+ {
+ switch(Index)
+ {
+ case TEXTLED_BRIGHTNESS_PACKET:
+ brightness = round((phid->brightness * 31) / 100.0);
+
+ buffer[0] = 0x1C | (0x04 << 5);
+ buffer[1] = (unsigned char)(LED_Brightness[brightness] & 0xff);
+ buffer[2] = (unsigned char)((LED_Brightness[brightness] >> 8) & 0xff);
+ buffer[3] = (unsigned char)((LED_Brightness[brightness] >> 16) & 0xff);
+ buffer[4] = (unsigned char)((LED_Brightness[brightness] >> 24) & 0xff);
+
+ break;
+ case TEXTLED_DISPLAYSTRING_PACKET + 0:
+ length = strlen(phid->displayStringPtr[0]);
+ correction = 0;
+
+ for (ui = 0; ui<=length; ui++)
+ {
+ displayString[0][ui] = LED_Translate[phid->displayStringPtr[0][ui + correction] & 0xff];
+ if (((phid->displayStringPtr[0][ui + correction] & 0xff) == 0x2E) && (ui > 0))
+ {
+ displayString[0][ui-1] |= 0x80;
+ correction++;
+ displayString[0][ui] = LED_Translate[phid->displayStringPtr[0][ui + correction] & 0xff];
+ }
+ }
+
+ //Takes 2 packets to set string, so we have to send the first one here manually
+
+ //3-bit character count, 5-bit position
+ buffer[0] = ((0x07 << 5) | 0x00); //7 characters at posn 0
+ memcpy(buffer+1, displayString[0], 7); //the first 7 characters
+ //send the first 7 characters
+ if ((result = CPhidgetTextLED_sendpacket(phid, buffer)) != EPHIDGET_OK)
+ {
+ return result;
+ }
+
+ //3-bit character count, 5-bit position
+ ZEROMEM(buffer, phid->phid.outputReportByteLength);
+ buffer[0] = ((0x01 << 5) | 0x07); //1 character at posn 7
+ memcpy(buffer+1, displayString[0]+7, 1); //the 8th character
+
+ break;
+ default:
+ return EPHIDGET_UNEXPECTED;
+ }
+ }
+ else
+ return EPHIDGET_UNEXPECTED;
+ break;
+ case PHIDID_TEXTLED_4x8:
+ if ((phid->phid.deviceVersion >= 200) && (phid->phid.deviceVersion < 300))
+ {
+ switch(Index)
+ {
+ case TEXTLED_BRIGHTNESS_PACKET:
+ brightness = round((phid->brightness * 63) / 100.0);
+
+ buffer[0] = 0x80;
+ buffer[1] = brightness;
+
+ break;
+ case TEXTLED_DISPLAYSTRING_PACKET + 0:
+ case TEXTLED_DISPLAYSTRING_PACKET + 1:
+ case TEXTLED_DISPLAYSTRING_PACKET + 2:
+ case TEXTLED_DISPLAYSTRING_PACKET + 3:
+ length = strlen(phid->displayStringPtr[Index]);
+ buffer[0] = (unsigned char)Index;
+
+ for (ui = 0, j = 1, k=8; ui<length; ui++)
+ {
+ /* Collapse decimal point into previous digit if possible */
+ if (phid->displayStringPtr[Index][ui] == '.')
+ {
+ if(buffer[7] & j)
+ {
+ k+=2;
+ j=j<<1;
+ }
+ buffer[7] |= j;
+ if (k == 8) k+=2;
+ }
+ else
+ {
+ buffer[k] = LEDV2_Table[((unsigned short)phid->displayStringPtr[Index][ui] << 1)];
+ buffer[k+1] = LEDV2_Table[(((unsigned short)phid->displayStringPtr[Index][ui] << 1) + 1)];
+ if (k != 8) j=j<<1;
+ k+=2;
+ }
+ }
+ break;
+ default:
+ return EPHIDGET_UNEXPECTED;
+ }
+ }
+ else
+ return EPHIDGET_UNEXPECTED;
+ break;
+ default:
+ return EPHIDGET_UNEXPECTED;
+ }
+
+ return EPHIDGET_OK;
+}
+
+// === Exported Functions === //
+
+//create and initialize a device structure
+CCREATE(TextLED, PHIDCLASS_TEXTLED)
+
+CGET(TextLED,RowCount,int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_TEXTLED)
+ TESTATTACHED
+
+ MASGN(phid.attr.textled.numRows)
+}
+CGET(TextLED,ColumnCount,int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_TEXTLED)
+ TESTATTACHED
+
+ MASGN(phid.attr.textled.numColumns)
+}
+
+CGET(TextLED,Brightness,int)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_TEXTLED)
+ TESTATTACHED
+ TESTMASGN(brightness, PUNK_INT)
+
+ MASGN(brightness)
+}
+CSET(TextLED,Brightness,int)
+ TESTPTR(phid)
+ TESTDEVICETYPE(PHIDCLASS_TEXTLED)
+ TESTATTACHED
+ TESTRANGE(0, 100)
+
+ if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
+ ADDNETWORKKEY(Brightness, "%d", brightness);
+ else
+ SENDPACKETINDEXED(TextLED, brightness, TEXTLED_BRIGHTNESS_PACKET);
+
+ return EPHIDGET_OK;
+}
+
+CSETINDEX(TextLED, DisplayString, char *)
+ size_t length = strlen(newVal);
+ int i = 0, length_temp = 0;
+ TESTPTR(phid)
+ TESTDEVICETYPE(PHIDCLASS_TEXTLED)
+ TESTATTACHED
+ TESTINDEX(phid.attr.textled.numRows)
+
+ //for the 4 row textled, periods don't count in the length
+ // unless the first char is a period, or there are two in a row
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_TEXTLED_4x8:
+ length_temp = (int)length;
+ for(i=1;i<length_temp;i++)
+ if(newVal[i] == '.' && newVal[i-1] != '.') length--;
+ break;
+ default:
+ break;
+ }
+ if (length > (size_t)phid->phid.attr.textled.numColumns) return EPHIDGET_INVALIDARG;
+
+ if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
+ ADDNETWORKKEYINDEXED(DisplayString, "%s", strings);
+ else
+ SENDPACKETINDEXED(TextLED, displayStringPtr[Index], TEXTLED_DISPLAYSTRING_PACKET + Index);
+
+ return EPHIDGET_OK;
+}
+
+// === Deprecated Functions === //
+
+CGET(TextLED,NumRows,int)
+ return CPhidgetTextLED_getRowCount(phid, pVal);
+}
+CGET(TextLED,NumColumns,int)
+ return CPhidgetTextLED_getColumnCount(phid, pVal);
+}
diff --git a/cphidgettextled.h b/cphidgettextled.h
new file mode 100644
index 0000000..b5304be
--- /dev/null
+++ b/cphidgettextled.h
@@ -0,0 +1,75 @@
+#ifndef __CPHIDGETTEXTLED
+#define __CPHIDGETTEXTLED
+#include "cphidget.h"
+
+/** \defgroup phidtextled Phidget TextLED
+ * \ingroup phidgets
+ * Calls specific to the Phidget Text LED. See the product manual for more specific API details, supported functionality, units, etc.
+ * @{
+ */
+
+DPHANDLE(TextLED)
+CHDRSTANDARD(TextLED)
+
+/**
+ * Gets the number of rows supported by this display.
+ * @param phid An attached phidget text led handle.
+ * @param count The row count.
+ */
+CHDRGET(TextLED,RowCount,int *count)
+/**
+ * Gets the number of columns per supported by this display.
+ * @param phid An attached phidget text led handle.
+ * @param count The Column count.
+ */
+CHDRGET(TextLED,ColumnCount,int *count)
+
+/**
+ * Gets the last set brightness value.
+ * @param phid An attached phidget text led handle.
+ * @param brightness The brightness (0-100).
+ */
+CHDRGET(TextLED,Brightness,int *brightness)
+/**
+ * Sets the last set brightness value.
+ * @param phid An attached phidget text led handle.
+ * @param brightness The brightness (0-100).
+ */
+CHDRSET(TextLED,Brightness,int brightness)
+
+/**
+ * Sets a row on the display.
+ * @param phid An attached phidget text led handle.
+ * @param index The row index.
+ * @param displayString The string to display. Make sure this is not longer then \ref CPhidgetTextLED_getColumnCount.
+ */
+CHDRSETINDEX(TextLED,DisplayString,char *displayString)
+
+#ifndef REMOVE_DEPRECATED
+DEP_CHDRGET("Deprecated - use CPhidgetTextLED_getRowCount",TextLED,NumRows,int *)
+DEP_CHDRGET("Deprecated - use CPhidgetTextLED_getColumnCount",TextLED,NumColumns,int *)
+#endif
+
+#ifndef EXTERNALPROTO
+#define TEXTLED_MAXROWS 4
+#define TEXTLED_MAXCOLS 8
+
+#define TEXTLED_BRIGHTNESS_PACKET -1
+#define TEXTLED_DISPLAYSTRING_PACKET 0
+
+struct _CPhidgetTextLED {
+ CPhidget phid;
+
+ char *displayStringPtr[TEXTLED_MAXROWS];
+ int brightness;
+
+ unsigned char outputPacket[24];
+ unsigned int outputPacketLen;
+
+ char *strings[TEXTLED_MAXROWS];
+} typedef CPhidgetTextLEDInfo;
+#endif
+
+/** @} */
+
+#endif
diff --git a/cphidgetweightsensor.c b/cphidgetweightsensor.c
new file mode 100644
index 0000000..7a54e2e
--- /dev/null
+++ b/cphidgetweightsensor.c
@@ -0,0 +1,116 @@
+#include "stdafx.h"
+#include "cphidgetweightsensor.h"
+#include "cusb.h"
+#include "csocket.h"
+#include "cthread.h"
+#include <math.h>
+
+// === Internal Functions === //
+
+//clearVars - sets all device variables to unknown state
+CPHIDGETCLEARVARS(WeightSensor)
+
+ phid->Weight = PUNI_DBL;
+ phid->lastweight = PUNK_DBL;
+ phid->WeightChangeTrigger = PUNI_DBL;
+
+ return EPHIDGET_OK;
+}
+
+//initAfterOpen - sets up the initial state of an object, reading in packets from the device if needed
+// used during attach initialization - on every attach
+CPHIDGETINIT(WeightSensor)
+ TESTPTR(phid);
+
+ //initialize triggers, set data arrays to unknown
+ phid->Weight = PUNK_DBL;
+ phid->lastweight = PUNK_DBL;
+ phid->WeightChangeTrigger = 0.1;
+
+ //issue one read
+ CPhidget_read((CPhidgetHandle)phid);
+
+ return EPHIDGET_OK;
+}
+
+//dataInput - parses device packets
+CPHIDGETDATA(WeightSensor)
+ double Weight = 0;
+
+ if (length<0) return EPHIDGET_INVALIDARG;
+ TESTPTR(phid);
+ TESTPTR(buffer);
+
+ //Parse device packets - store data locally
+ switch(phid->phid.deviceIDSpec)
+ {
+ case PHIDID_WEIGHTSENSOR:
+ Weight = (((double)((unsigned short)buffer[0]+((unsigned short)buffer[1]<<8))) / 100.0 ) - 40.0;
+ Weight = round_double(Weight, 2);
+ break;
+ default:
+ return EPHIDGET_UNEXPECTED;
+ }
+
+ //store to structure
+ phid->Weight = Weight;
+
+ //send out any events that exceed or match the trigger
+ if (fabs(phid->Weight - phid->lastweight) >= phid->WeightChangeTrigger || phid->lastweight == PUNK_DBL)
+ {
+ FIRE(WeightChange, phid->Weight);
+ phid->lastweight = phid->Weight;
+ }
+ return EPHIDGET_OK;
+}
+
+//eventsAfterOpen - sends out an event for all valid data, used during attach initialization
+CPHIDGETINITEVENTS(WeightSensor)
+ if (phid->Weight != PUNK_DBL)
+ {
+ FIRE(WeightChange, phid->Weight);
+ phid->lastweight = phid->Weight;
+ }
+ return EPHIDGET_OK;
+}
+
+//getPacket - not used for WeightSensor
+CGETPACKET(WeightSensor)
+ return EPHIDGET_UNEXPECTED;
+}
+
+// === Exported Functions === //
+
+//create and initialize a device structure
+CCREATE(WeightSensor, PHIDCLASS_WEIGHTSENSOR)
+
+//event setup functions
+CFHANDLE(WeightSensor, WeightChange, double)
+
+CGET(WeightSensor,Weight,double)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_WEIGHTSENSOR)
+ TESTATTACHED
+ TESTMASGN(Weight, PUNK_DBL)
+ MASGN(Weight)
+}
+
+CGET(WeightSensor,WeightChangeTrigger,double)
+ TESTPTRS(phid,pVal)
+ TESTDEVICETYPE(PHIDCLASS_WEIGHTSENSOR)
+ TESTATTACHED
+ TESTMASGN(WeightChangeTrigger, PUNK_DBL)
+ MASGN(WeightChangeTrigger)
+}
+CSET(WeightSensor,WeightChangeTrigger,double)
+ TESTPTR(phid)
+ TESTDEVICETYPE(PHIDCLASS_WEIGHTSENSOR)
+ TESTATTACHED
+ TESTRANGE(0, 300)
+ if(CPhidget_statusFlagIsSet(phid->phid.status, PHIDGET_REMOTE_FLAG))
+ ADDNETWORKKEY(Trigger, "%lE", WeightChangeTrigger);
+ else
+ phid->WeightChangeTrigger = newVal;
+ return EPHIDGET_OK;
+}
+
diff --git a/cphidgetweightsensor.h b/cphidgetweightsensor.h
new file mode 100644
index 0000000..863f76c
--- /dev/null
+++ b/cphidgetweightsensor.h
@@ -0,0 +1,56 @@
+#ifndef __CPHIDGETWEIGHTSENSOR
+#define __CPHIDGETWEIGHTSENSOR
+#include "cphidget.h"
+
+/** \defgroup phidweight Phidget Weight Sensor
+ * \ingroup phidgets
+ * Calls specific to the Phidget Weight Sensor. See the product manual for more specific API details, supported functionality, units, etc.
+ * @{
+ */
+
+DPHANDLE(WeightSensor)
+CHDRSTANDARD(WeightSensor)
+
+/**
+ * Gets the sensed weight.
+ * @param phid An attached phidget weight sensor handle.
+ * @param weight The weight.
+ */
+CHDRGET(WeightSensor,Weight,double *weight)
+/**
+ * Set a weight change handler. This is called when the weight changes by more then the change trigger.
+ * @param phid An attached phidget weight sensor handle.
+ * @param fptr Callback function pointer.
+ * @param userPtr A pointer for use by the user - this value is passed back into the callback function.
+ */
+CHDREVENT(WeightSensor,WeightChange,double weight)
+/**
+ * Gets the weight change trigger.
+ * @param phid An attached phidget weight sensor handle.
+ * @param trigger The change trigger.
+ */
+CHDRGET(WeightSensor,WeightChangeTrigger,double *trigger)
+/**
+ * Sets the weight change trigger.
+ * @param phid An attached phidget weight sensor handle.
+ * @param trigger The change trigger.
+ */
+CHDRSET(WeightSensor,WeightChangeTrigger,double trigger)
+
+#ifndef EXTERNALPROTO
+struct _CPhidgetWeightSensor {
+ CPhidget phid;
+
+ int (CCONV *fptrWeightChange)(CPhidgetWeightSensorHandle, void *, double);
+
+ void *fptrWeightChangeptr;
+
+ double Weight;
+ double lastweight;
+ double WeightChangeTrigger;
+} typedef CPhidgetWeightSensorInfo;
+#endif
+
+/** @} */
+
+#endif
diff --git a/cppfooter b/cppfooter
new file mode 100644
index 0000000..d4aa34d
--- /dev/null
+++ b/cppfooter
@@ -0,0 +1,3 @@
+#ifdef __cplusplus
+}
+#endif
diff --git a/cppheader b/cppheader
new file mode 100644
index 0000000..17885c1
--- /dev/null
+++ b/cppheader
@@ -0,0 +1,21 @@
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(__stdcall)
+ #define CCONV __stdcall
+#else
+ #if defined(__BORLANDC__) || defined(_MSC_VER)
+ #define CCONV __stdcall
+ #else
+ #define CCONV
+ #endif
+#endif
+
+#if !defined(__int64)
+#if !defined(__BORLANDC__) && !defined(_MSC_VER)
+typedef long long __int64;
+#endif
+#endif
+
+
diff --git a/csocket.h b/csocket.h
new file mode 100644
index 0000000..7d18b80
--- /dev/null
+++ b/csocket.h
@@ -0,0 +1,144 @@
+#ifndef __CSOCKET
+#define __CSOCKET
+
+#include "cphidget.h"
+#include "cphidgetmanager.h"
+#include "cphidgetdictionary.h"
+
+#ifndef EXTERNALPROTO
+
+#include "cphidgetsbc.h"
+
+extern CThread_mutex_t serverLock;
+extern CThread_mutex_t zeroconfPhidgetsLock;
+extern CPhidgetListHandle zeroconfPhidgets;
+extern CPhidgetRemoteListHandle zeroconfServers;
+extern CPhidgetListHandle zeroconfPhidgets;
+extern CPhidgetSBCListHandle zeroconfSBCs;
+extern CThread_mutex_t zeroconfServersLock;
+extern CThread_mutex_t zeroconfPhidgetsLock;
+extern CThread_mutex_t zeroconfSBCsLock;
+extern CPhidgetListHandle activeRemotePhidgets;
+extern CPhidgetManagerListHandle activeRemoteManagers;
+extern CPhidgetDictionaryListHandle activeRemoteDictionaries;
+extern CPhidgetSBCManagerListHandle activeSBCManagers;
+extern CThread_mutex_t activeRemotePhidgetsLock;
+extern CThread_mutex_t activeRemoteManagersLock;
+extern CThread_mutex_t activeRemoteDictionariesLock;
+extern CThread_mutex_t activeSBCManagersLock;
+extern CThread_mutex_t zeroconfInitLock;
+
+void internal_async_network_error_handler(const char *error, void *phid);
+int unregisterRemotePhidget(CPhidgetHandle phid);
+int unregisterRemoteDictionary(CPhidgetDictionaryHandle dict);
+int unregisterRemoteManager(CPhidgetManagerHandle phidm);
+int unregisterSBCManager(CPhidgetSBCManagerHandle sbcm);
+CThread_func_return_t DisconnectPhidgetThreadFunction(CThread_func_arg_t lpdwParam);
+int getZeroconfHostPort(CPhidgetRemoteHandle networkInfo);
+int refreshZeroconfPhidget(CPhidgetHandle phid);
+int refreshZeroconfSBC(CPhidgetSBCHandle sbc);
+int CCONV CPhidgetRemote_areEqual(void *arg1, void *arg2);
+void CCONV CPhidgetRemote_free(void *arg);
+int CCONV CPhidgetRemote_create(CPhidgetRemoteHandle *arg);
+
+PHIDGET21_API void CCONV CPhidgetSocketClient_free(void *arg);
+PHIDGET21_API int CCONV CPhidgetSocketClient_areEqual(void *arg1, void *arg2);
+PHIDGET21_API int CCONV CPhidgetSocketClient_create(CPhidgetSocketClientHandle *arg);
+
+#define SET_RUNNING_EVENT(phid) \
+ CThread_mutex_lock(&phid->lock); \
+ if(phid->networkInfo && phid->networkInfo->server) \
+ phid->networkInfo->server->runningEvent = PTRUE; \
+ CThread_mutex_unlock(&phid->lock);
+
+#define CLEAR_RUNNING_EVENT(phid) \
+ CThread_mutex_lock(&phid->lock); \
+ if(phid->networkInfo && phid->networkInfo->server) \
+ { \
+ setTimeNow(&phid->networkInfo->server->lastHeartbeatTime); \
+ phid->networkInfo->server->runningEvent = PFALSE; \
+ } \
+ CThread_mutex_unlock(&phid->lock);
+
+#endif
+
+/** \addtogroup phidcommon
+ * @{
+ */
+/**
+ * Opens a Phidget remotely by ServerID. Note that this requires Bonjour (mDNS) to be running on both the host and the server.
+ * @param phid A phidget handle.
+ * @param serial Serial number. Specify -1 to open any.
+ * @param serverID Server ID. Specify NULL to open any.
+ * @param password Password. Can be NULL if the server is running unsecured.
+ */
+PHIDGET21_API int CCONV CPhidget_openRemote(CPhidgetHandle phid, int serial, const char *serverID, const char *password);
+/**
+ * Opens a Phidget remotely by ServerID. Note that this requires Bonjour (mDNS) to be running on both the host and the server.
+ * @param phid A phidget handle.
+ * @param label Label string. Labels can be up to 10 characters (UTF-8 encoding). Specify NULL to open any.
+ * @param serverID Server ID. Specify NULL to open any.
+ * @param password Password. Can be NULL if the server is running unsecured.
+ */
+PHIDGET21_API int CCONV CPhidget_openLabelRemote(CPhidgetHandle phid, const char *label, const char *serverID, const char *password);
+/**
+ * Opens a Phidget remotely by address and port, with optional serial number.
+ * @param phid A phidget handle.
+ * @param serial Serial number. Specify -1 to open any.
+ * @param address Address. This can be a hostname or IP address.
+ * @param port Port number. Default is 5001.
+ * @param password Password. Can be NULL if the server is running unsecured.
+ */
+PHIDGET21_API int CCONV CPhidget_openRemoteIP(CPhidgetHandle phid, int serial, const char *address, int port, const char *password);
+/**
+ * Opens a Phidget remotely by address and port, with optional label.
+ * @param phid A phidget handle.
+ * @param label Label string. Labels can be up to 10 characters (UTF-8 encoding). Specify NULL to open any.
+ * @param address Address. This can be a hostname or IP address.
+ * @param port Port number. Default is 5001.
+ * @param password Password. Can be NULL if the server is running unsecured.
+ */
+PHIDGET21_API int CCONV CPhidget_openLabelRemoteIP(CPhidgetHandle phid, const char *label, const char *address, int port, const char *password);
+/** @} */
+
+/** \addtogroup phidmanager
+ * @{
+ */
+/**
+ * Opens a Phidget manager remotely by ServerID. Note that this requires Bonjour (mDNS) to be running on both the host and the server.
+ * @param phidm A phidget manager handle.
+ * @param serverID Server ID. Specify NULL to open any.
+ * @param password Password. Can be NULL if the server is running unsecured.
+ */
+PHIDGET21_API int CCONV CPhidgetManager_openRemote(CPhidgetManagerHandle phidm, const char *serverID, const char *password);
+/**
+ * Opens a Phidget manager remotely by address and port.
+ * @param phidm A phidget manager handle.
+ * @param address Address. This can be a hostname or IP address.
+ * @param port Port number. Default is 5001.
+ * @param password Password. Can be NULL if the server is running unsecured.
+ */
+PHIDGET21_API int CCONV CPhidgetManager_openRemoteIP(CPhidgetManagerHandle phidm, const char *address, int port, const char *password);
+/** @} */
+
+/** \addtogroup phiddict
+ * @{
+ */
+/**
+ * Opens a Phidget dictionary by ServerID. Note that this requires Bonjour (mDNS) to be running on both the host and the server.
+ * @param dict A phidget dictionary handle.
+ * @param serverID Server ID. Specify NULL to open any.
+ * @param password Password. Can be NULL if the server is running unsecured.
+ */
+PHIDGET21_API int CCONV CPhidgetDictionary_openRemote(CPhidgetDictionaryHandle dict, const char *serverID, const char *password);
+/**
+ * Opens a Phidget dictionary by address and port.
+ * @param dict A phidget dictionary handle.
+ * @param address Address. This can be a hostname or IP address.
+ * @param port Port number. Default is 5001.
+ * @param password Password. Can be NULL if the server is running unsecured.
+ */
+PHIDGET21_API int CCONV CPhidgetDictionary_openRemoteIP(CPhidgetDictionaryHandle dict, const char *address, int port, const char *password);
+/** @} */
+
+#endif
diff --git a/csocketevents.c b/csocketevents.c
new file mode 100644
index 0000000..9291994
--- /dev/null
+++ b/csocketevents.c
@@ -0,0 +1,2201 @@
+#include "stdafx.h"
+#include "csocket.h"
+#include "csocketevents.h"
+#include "utils/utils.h"
+#include "math.h"
+
+#include "cphidget.h"
+#include "cphidgetdictionary.h"
+#include "csocket.h"
+#include "clog.h"
+#include "cphidgetaccelerometer.h"
+#include "cphidgetadvancedservo.h"
+#include "cphidgetanalog.h"
+#include "cphidgetbridge.h"
+#include "cphidgetencoder.h"
+#include "cphidgetfrequencycounter.h"
+#include "cphidgetgps.h"
+#include "cphidgetinterfacekit.h"
+#include "cphidgetir.h"
+#include "cphidgetmanager.h"
+#include "cphidgetled.h"
+#include "cphidgetmotorcontrol.h"
+#include "cphidgetphsensor.h"
+#include "cphidgetrfid.h"
+#include "cphidgetservo.h"
+#include "cphidgetspatial.h"
+#include "cphidgetstepper.h"
+#include "cphidgettemperaturesensor.h"
+#include "cphidgettextlcd.h"
+#include "cphidgettextled.h"
+#include "cphidgetweightsensor.h"
+#include "cphidgetgeneric.h"
+
+regex_t phidgetsetex;
+regex_t managerex;
+regex_t managervalex;
+
+PWC_SETKEYS(Accelerometer)
+ if(KEYNAME("NumberOfAxes"))
+ {
+ GET_INT_VAL;
+ phid->phid.attr.accelerometer.numAxis = value;
+ phid->phid.keyCount++;
+ }
+ else if(KEYNAME("Acceleration"))
+ {
+ if(CHKINDEX(accelerometer.numAxis,ACCEL_MAXAXES))
+ {
+ GET_DOUBLE_VAL;
+ INC_KEYCOUNT(axis[index], PUNI_DBL)
+ phid->axis[index] = value;
+ if(value != PUNK_DBL)
+ FIRE(AccelerationChange, index, value);
+ }
+ else
+ ret = EPHIDGET_OUTOFBOUNDS;
+ }
+ else if(KEYNAME("AccelerationMin"))
+ {
+ GET_DOUBLE_VAL;
+ INC_KEYCOUNT(accelerationMin, PUNI_DBL)
+ phid->accelerationMin = value;
+ }
+ else if(KEYNAME("AccelerationMax"))
+ {
+ GET_DOUBLE_VAL;
+ INC_KEYCOUNT(accelerationMax, PUNI_DBL)
+ phid->accelerationMax = value;
+ }
+ else if(KEYNAME("Trigger"))
+ {
+ if(CHKINDEX(accelerometer.numAxis,ACCEL_MAXAXES))
+ {
+ GET_DOUBLE_VAL;
+ INC_KEYCOUNT(axisChangeTrigger[index], PUNI_DBL)
+ phid->axisChangeTrigger[index] = value;
+ }
+ else
+ ret = EPHIDGET_OUTOFBOUNDS;
+ }
+ else{
+ PWC_BAD_SETTYPE(Accelerometer);
+ }
+ return ret;
+}
+
+PWC_SETKEYS(AdvancedServo)
+ if(KEYNAME("NumberOfMotors"))
+ {
+ GET_INT_VAL;
+ phid->phid.attr.advancedservo.numMotors = value;
+ phid->phid.keyCount++;
+ }
+ else if(KEYNAME("Position"))
+ {
+ if(index < phid->phid.attr.advancedservo.numMotors?phid->phid.attr.advancedservo.numMotors:ADVSERVO_MAXSERVOS)
+ {
+ GET_DOUBLE_VAL;
+ INC_KEYCOUNT(motorPositionEcho[index], PUNI_DBL)
+ phid->motorPositionEcho[index] = value;
+ if(value != PUNK_DBL)
+ FIRE(PositionChange, index, servo_us_to_degrees(phid->servoParams[index], value, PTRUE));
+ }
+ else
+ ret = EPHIDGET_OUTOFBOUNDS;
+ }
+ else if(KEYNAME("PositionMin"))
+ {
+ GET_DOUBLE_VAL;
+ INC_KEYCOUNT(motorPositionMin[index], PUNI_DBL)
+ phid->motorPositionMin[index] = value;
+ }
+ else if(KEYNAME("PositionMax"))
+ {
+ GET_DOUBLE_VAL;
+ INC_KEYCOUNT(motorPositionMax[index], PUNI_DBL)
+ phid->motorPositionMax[index] = value;
+ }
+ else if(KEYNAME("PositionMinLimit"))
+ {
+ GET_DOUBLE_VAL;
+ INC_KEYCOUNT(motorPositionMinLimit, PUNI_DBL)
+ phid->motorPositionMinLimit = value;
+ }
+ else if(KEYNAME("PositionMaxLimit"))
+ {
+ GET_DOUBLE_VAL;
+ INC_KEYCOUNT(motorPositionMaxLimit, PUNI_DBL)
+ phid->motorPositionMaxLimit = value;
+ }
+ // initial acceleration limit always unknown so don't keyCount++
+ else if(KEYNAME("Acceleration"))
+ {
+ if(CHKINDEX(advancedservo.numMotors, ADVSERVO_MAXSERVOS))
+ {
+ GET_DOUBLE_VAL;
+ phid->motorAcceleration[index] = value;
+ }
+ else
+ ret = EPHIDGET_OUTOFBOUNDS;
+ }
+ else if(KEYNAME("AccelerationMax"))
+ {
+ GET_DOUBLE_VAL;
+ INC_KEYCOUNT(accelerationMax, PUNI_DBL)
+ phid->accelerationMax = value;
+ }
+ else if(KEYNAME("AccelerationMin"))
+ {
+ GET_DOUBLE_VAL;
+ INC_KEYCOUNT(accelerationMin, PUNI_DBL)
+ phid->accelerationMin = value;
+ }
+ else if(KEYNAME("Current"))
+ {
+ if(CHKINDEX(advancedservo.numMotors, ADVSERVO_MAXSERVOS))
+ {
+ GET_DOUBLE_VAL;
+ INC_KEYCOUNT(motorSensedCurrent[index], PUNI_DBL)
+ phid->motorSensedCurrent[index] = value;
+ if(value != PUNK_DBL)
+ FIRE(CurrentChange, index, value);
+ }
+ else
+ ret = EPHIDGET_OUTOFBOUNDS;
+ }
+ // initial velocity limit always unknown so don't keyCount++
+ else if(KEYNAME("VelocityLimit"))
+ {
+ if(CHKINDEX(advancedservo.numMotors, ADVSERVO_MAXSERVOS))
+ {
+ GET_DOUBLE_VAL;
+ phid->motorVelocity[index] = value;
+ }
+ else
+ ret = EPHIDGET_OUTOFBOUNDS;
+ }
+ else if(KEYNAME("Velocity"))
+ {
+ if(CHKINDEX(advancedservo.numMotors, ADVSERVO_MAXSERVOS))
+ {
+ GET_DOUBLE_VAL;
+ INC_KEYCOUNT(motorVelocityEcho[index], PUNI_DBL)
+ phid->motorVelocityEcho[index] = value;
+ if(value != PUNK_DBL)
+ FIRE(VelocityChange, index, servo_us_to_degrees_vel(phid->servoParams[index], value, PTRUE));
+ }
+ else
+ ret = EPHIDGET_OUTOFBOUNDS;
+ }
+ else if(KEYNAME("VelocityMax"))
+ {
+ if(CHKINDEX(advancedservo.numMotors, ADVSERVO_MAXSERVOS))
+ {
+ GET_DOUBLE_VAL;
+ INC_KEYCOUNT(velocityMax[index], PUNI_DBL)
+ phid->velocityMax[index] = value;
+ }
+ else
+ ret = EPHIDGET_OUTOFBOUNDS;
+ }
+ else if(KEYNAME("VelocityMaxLimit"))
+ {
+ GET_DOUBLE_VAL;
+ INC_KEYCOUNT(velocityMaxLimit, PUNI_DBL)
+ phid->velocityMaxLimit = value;
+ }
+ else if(KEYNAME("VelocityMin"))
+ {
+ GET_DOUBLE_VAL;
+ INC_KEYCOUNT(velocityMin, PUNI_DBL)
+ phid->velocityMin = value;
+ }
+ else if(KEYNAME("Engaged"))
+ {
+ if(CHKINDEX(advancedservo.numMotors, ADVSERVO_MAXSERVOS))
+ {
+ GET_INT_VAL;
+ INC_KEYCOUNT(motorEngagedStateEcho[index], PUNI_BOOL)
+ phid->motorEngagedStateEcho[index] = value;
+ }
+ else
+ ret = EPHIDGET_OUTOFBOUNDS;
+ }
+ else if(KEYNAME("SpeedRampingOn"))
+ {
+ if(CHKINDEX(advancedservo.numMotors, ADVSERVO_MAXSERVOS))
+ {
+ GET_INT_VAL;
+ INC_KEYCOUNT(motorSpeedRampingStateEcho[index], PUNI_BOOL)
+ phid->motorSpeedRampingStateEcho[index] = value;
+ }
+ else
+ ret = EPHIDGET_OUTOFBOUNDS;
+ }
+ else if(KEYNAME("Stopped"))
+ {
+ if(CHKINDEX(advancedservo.numMotors, ADVSERVO_MAXSERVOS))
+ {
+ GET_INT_VAL;
+ unsigned char lastStoppedState = phid->motorStoppedState[index];
+ INC_KEYCOUNT(motorStoppedState[index], PUNI_BOOL)
+ phid->motorStoppedState[index] = value;
+ //If changed, re-run position/velocity events, so the stopped change will be noticed
+ if(lastStoppedState != value)
+ {
+ if(phid->motorVelocityEcho[index] != PUNK_DBL)
+ FIRE(VelocityChange, index, servo_us_to_degrees_vel(phid->servoParams[index], phid->motorVelocityEcho[index], PTRUE));
+ if(phid->motorPositionEcho[index] != PUNK_DBL)
+ FIRE(PositionChange, index, servo_us_to_degrees(phid->servoParams[index], phid->motorPositionEcho[index], PTRUE));
+ }
+ }
+ else
+ ret = EPHIDGET_OUTOFBOUNDS;
+ }
+ else if(KEYNAME("ServoParameters"))
+ {
+ if(CHKINDEX(advancedservo.numMotors, ADVSERVO_MAXSERVOS))
+ {
+ CPhidgetServoParameters params;
+ char *endptr;
+ params.servoType = strtol(state, &endptr, 10);
+ params.min_us = strtod(endptr+1, &endptr);
+ params.max_us = strtod(endptr+1, &endptr);
+ params.us_per_degree = strtod(endptr+1, &endptr);
+ params.max_us_per_s = strtod(endptr+1, NULL);
+ params.state = PTRUE;
+
+ INC_KEYCOUNT(servoParams[index].state, PUNI_BOOL)
+
+ phid->servoParams[index] = params;
+ }
+ else
+ ret = EPHIDGET_OUTOFBOUNDS;
+ }
+ else{
+ PWC_BAD_SETTYPE(AdvancedServo);
+ }
+ return ret;
+}
+
+PWC_SETKEYS(Analog)
+ if(KEYNAME("NumberOfOutputs"))
+ {
+ GET_INT_VAL;
+ phid->phid.attr.analog.numAnalogOutputs = value;
+ phid->phid.keyCount++;
+ }
+ else if(KEYNAME("Voltage"))
+ {
+ if(CHKINDEX(analog.numAnalogOutputs, ANALOG_MAXOUTPUTS))
+ {
+ GET_DOUBLE_VAL;
+ INC_KEYCOUNT(voltageEcho[index], PUNI_DBL)
+ phid->voltageEcho[index] = value;
+ }
+ else
+ ret = EPHIDGET_OUTOFBOUNDS;
+ }
+ else if(KEYNAME("VoltageMin"))
+ {
+ GET_DOUBLE_VAL;
+ INC_KEYCOUNT(voltageMin, PUNI_DBL)
+ phid->voltageMin = value;
+ }
+ else if(KEYNAME("VoltageMax"))
+ {
+ GET_DOUBLE_VAL;
+ INC_KEYCOUNT(voltageMax, PUNI_DBL)
+ phid->voltageMax = value;
+ }
+ else if(KEYNAME("Enabled"))
+ {
+ if(CHKINDEX(analog.numAnalogOutputs, ANALOG_MAXOUTPUTS))
+ {
+ GET_INT_VAL;
+ INC_KEYCOUNT(enabledEcho[index], PUNI_BOOL)
+ phid->enabledEcho[index] = value;
+ }
+ else
+ ret = EPHIDGET_OUTOFBOUNDS;
+ }
+ else{
+ PWC_BAD_SETTYPE(Analog);
+ }
+ return ret;
+}
+
+PWC_SETKEYS(Bridge)
+ if(KEYNAME("NumberOfInputs"))
+ {
+ GET_INT_VAL;
+ phid->phid.attr.bridge.numBridgeInputs = value;
+ phid->phid.keyCount++;
+ }
+ else if(KEYNAME("DataRate"))
+ {
+ GET_INT_VAL;
+ INC_KEYCOUNT(dataRateEcho, PUNI_INT)
+ phid->dataRateEcho = value;
+ }
+ else if(KEYNAME("DataRateMin"))
+ {
+ GET_INT_VAL;
+ INC_KEYCOUNT(dataRateMin, PUNI_INT)
+ phid->dataRateMin = value;
+ }
+ else if(KEYNAME("DataRateMax"))
+ {
+ GET_INT_VAL;
+ INC_KEYCOUNT(dataRateMax, PUNI_INT)
+ phid->dataRateMax = value;
+ }
+ else if(KEYNAME("Enabled"))
+ {
+ if(CHKINDEX(bridge.numBridgeInputs, BRIDGE_MAXINPUTS))
+ {
+ GET_INT_VAL;
+ INC_KEYCOUNT(enabledEcho[index], PUNI_BOOL)
+ phid->enabledEcho[index] = value;
+ }
+ else
+ ret = EPHIDGET_OUTOFBOUNDS;
+ }
+ else if(KEYNAME("BridgeMax"))
+ {
+ if(CHKINDEX(bridge.numBridgeInputs, BRIDGE_MAXINPUTS))
+ {
+ GET_DOUBLE_VAL;
+ INC_KEYCOUNT(bridgeMax[index], PUNI_DBL)
+ phid->bridgeMax[index] = value;
+ }
+ else
+ ret = EPHIDGET_OUTOFBOUNDS;
+ }
+ else if(KEYNAME("BridgeMin"))
+ {
+ if(CHKINDEX(bridge.numBridgeInputs, BRIDGE_MAXINPUTS))
+ {
+ GET_DOUBLE_VAL;
+ INC_KEYCOUNT(bridgeMin[index], PUNI_DBL)
+ phid->bridgeMin[index] = value;
+ }
+ else
+ ret = EPHIDGET_OUTOFBOUNDS;
+ }
+ else if(KEYNAME("Gain"))
+ {
+ if(CHKINDEX(bridge.numBridgeInputs, BRIDGE_MAXINPUTS))
+ {
+ GET_INT_VAL;
+ INC_KEYCOUNT(gainEcho[index], PHIDGET_BRIDGE_GAIN_UNKNOWN)
+ phid->gainEcho[index] = value;
+ }
+ else
+ ret = EPHIDGET_OUTOFBOUNDS;
+ }
+ else if(KEYNAME("BridgeValue"))
+ {
+ if(CHKINDEX(bridge.numBridgeInputs, BRIDGE_MAXINPUTS))
+ {
+ GET_DOUBLE_VAL;
+ INC_KEYCOUNT(bridgeValue[index], PUNI_DBL)
+ phid->bridgeValue[index] = value;
+ if(value != PUNK_DBL)
+ FIRE(BridgeData, index, value);
+ }
+ else
+ ret = EPHIDGET_OUTOFBOUNDS;
+ }
+ else{
+ PWC_BAD_SETTYPE(Bridge);
+ }
+ return ret;
+}
+
+PWC_SETKEYS(Encoder)
+ if(KEYNAME("NumberOfEncoders"))
+ {
+ GET_INT_VAL;
+ phid->phid.attr.encoder.numEncoders = value;
+ phid->phid.keyCount++;
+ }
+ else if(KEYNAME("NumberOfInputs"))
+ {
+ GET_INT_VAL;
+ phid->phid.attr.encoder.numInputs = value;
+ phid->phid.keyCount++;
+ }
+ // initial Input is unknown so don't keyCount++
+ else if(KEYNAME("Input"))
+ {
+ if(CHKINDEX(encoder.numInputs, ENCODER_MAXINPUTS))
+ {
+ GET_INT_VAL;
+ phid->inputState[index] = value;
+ if(value != PUNK_BOOL)
+ FIRE(InputChange, index, value);
+ }
+ else
+ ret = EPHIDGET_OUTOFBOUNDS;
+ }
+ // initial Position is unknown so don't keyCount++
+ else if(KEYNAME("ResetPosition"))
+ {
+ if(CHKINDEX(encoder.numEncoders, ENCODER_MAXENCODERS))
+ {
+ GET_INT_VAL;
+ phid->encoderPosition[index] = value;
+ }
+ else
+ ret = EPHIDGET_OUTOFBOUNDS;
+ }
+ else if(KEYNAME("Position"))
+ {
+ if(CHKINDEX(encoder.numEncoders, ENCODER_MAXENCODERS))
+ {
+ char *endPtr;
+ int value = strtol(state, &endPtr, 10);
+ int posnchange = strtol(endPtr+1, &endPtr, 10);
+ int posn = strtol(endPtr+1, &endPtr, 10);
+
+ phid->encoderPosition[index] = posn;
+
+ FIRE(PositionChange, index, (unsigned short)value, posnchange);
+ }
+ else
+ ret = EPHIDGET_OUTOFBOUNDS;
+ }
+ else if(KEYNAME("IndexPosition"))
+ {
+ if(CHKINDEX(encoder.numEncoders, ENCODER_MAXENCODERS))
+ {
+ GET_INT_VAL;
+ phid->indexPosition[index] = value;
+ }
+ else
+ ret = EPHIDGET_OUTOFBOUNDS;
+ }
+ else if(KEYNAME("Enabled"))
+ {
+ if(CHKINDEX(encoder.numEncoders, ENCODER_MAXENCODERS))
+ {
+ GET_INT_VAL;
+ INC_KEYCOUNT(enableStateEcho[index], PUNI_BOOL)
+ phid->enableStateEcho[index] = value;
+ }
+ else
+ ret = EPHIDGET_OUTOFBOUNDS;
+ }
+ else{
+ PWC_BAD_SETTYPE(Encoder);
+ }
+ return ret;
+}
+
+PWC_SETKEYS(FrequencyCounter)
+ if(KEYNAME("NumberOfInputs"))
+ {
+ GET_INT_VAL;
+ phid->phid.attr.frequencycounter.numFreqInputs = value;
+ phid->phid.keyCount++;
+ }
+ else if(KEYNAME("Count") || KEYNAME("CountReset"))
+ {
+ if(CHKINDEX(frequencycounter.numFreqInputs, FREQCOUNTER_MAXINPUTS))
+ {
+ char *endPtr;
+ __int64 totTime = strtoll(state, &endPtr, 10);
+ __int64 totCount = strtoll(endPtr+1, &endPtr, 10);
+ double freq = strtod(endPtr+1, NULL);
+
+ int timeChange = (int)(totTime - phid->totalTime[index]);
+ int cntChange = (int)(totCount - phid->totalCount[index]);
+
+ INC_KEYCOUNT(frequency[index], PUNI_INT);
+
+ phid->totalTime[index] = totTime;
+ phid->totalCount[index] = totCount;
+ phid->frequency[index] = freq;
+
+ //no event on first time or reset
+ if(phid->countsGood[index] == PTRUE && KEYNAME("Count"))
+ {
+ FIRE(Count, index, timeChange, cntChange);
+ }
+
+ phid->countsGood[index] = PTRUE;
+ }
+ else
+ ret = EPHIDGET_OUTOFBOUNDS;
+ }
+ else if(KEYNAME("Enabled"))
+ {
+ if(CHKINDEX(frequencycounter.numFreqInputs, FREQCOUNTER_MAXINPUTS))
+ {
+ GET_INT_VAL;
+ INC_KEYCOUNT(enabledEcho[index], PUNI_BOOL)
+ phid->enabledEcho[index] = value;
+ }
+ else
+ ret = EPHIDGET_OUTOFBOUNDS;
+ }
+ else if(KEYNAME("Timeout"))
+ {
+ if(CHKINDEX(frequencycounter.numFreqInputs, FREQCOUNTER_MAXINPUTS))
+ {
+ GET_INT_VAL;
+ INC_KEYCOUNT(timeout[index], PUNI_INT)
+ phid->timeout[index] = value;
+ }
+ else
+ ret = EPHIDGET_OUTOFBOUNDS;
+ }
+ else if(KEYNAME("Filter"))
+ {
+ if(CHKINDEX(frequencycounter.numFreqInputs, FREQCOUNTER_MAXINPUTS))
+ {
+ GET_INT_VAL;
+ INC_KEYCOUNT(filterEcho[index], PHIDGET_FREQUENCYCOUNTER_FILTERTYPE_UNKNOWN)
+ phid->filterEcho[index] = value;
+ }
+ else
+ ret = EPHIDGET_OUTOFBOUNDS;
+ }
+ else{
+ PWC_BAD_SETTYPE(FrequencyCounter);
+ }
+ return ret;
+}
+
+PWC_SETKEYS(Generic)
+ phid = 0;
+ return ret;
+}
+
+PWC_SETKEYS(GPS)
+ if(KEYNAME("Position"))
+ {
+ char *endPtr;
+ double lat = strtod(state, &endPtr);
+ double lon = strtod(endPtr+1, &endPtr);
+ double alt = strtod(endPtr+1, NULL);
+ phid->latitude = lat;
+ phid->longitude = lon;
+ phid->altitude = alt;
+ FIRE(PositionChange, lat, lon, alt);
+ }
+ else if(KEYNAME("PositionFix"))
+ {
+ GET_INT_VAL;
+ INC_KEYCOUNT(fix, PUNI_BOOL)
+ phid->fix = value;
+ FIRE(PositionFixStatusChange, value);
+ }
+ else if(KEYNAME("Velocity"))
+ {
+ GET_DOUBLE_VAL;
+ phid->velocity = value;
+ }
+ else if(KEYNAME("Heading"))
+ {
+ GET_DOUBLE_VAL;
+ phid->heading = value;
+ }
+ else if(KEYNAME("DateTime"))
+ {
+ GPSTime time;
+ GPSDate date;
+ char *endPtr;
+ date.tm_year = (short)strtol(state, &endPtr, 10);
+ date.tm_mon = (short)strtol(endPtr+1, &endPtr, 10);
+ date.tm_mday = (short)strtol(endPtr+1, &endPtr, 10);
+ time.tm_hour = (short)strtol(endPtr+1, &endPtr, 10);
+ time.tm_min = (short)strtol(endPtr+1, &endPtr, 10);
+ time.tm_sec = (short)strtol(endPtr+1, &endPtr, 10);
+ time.tm_ms = (short)strtol(endPtr+1, NULL, 10);
+
+ phid->GPSData.GGA.time = time;
+ phid->haveTime = PTRUE;
+ phid->GPSData.RMC.date = date;
+ phid->haveDate = PTRUE;
+ }
+ else{
+ PWC_BAD_SETTYPE(GPS);
+ }
+ return ret;
+}
+
+PWC_SETKEYS(InterfaceKit)
+ if(KEYNAME("NumberOfSensors"))
+ {
+ GET_INT_VAL;
+ phid->phid.attr.ifkit.numSensors = value;
+ phid->phid.keyCount++;
+ }
+ else if(KEYNAME("NumberOfInputs"))
+ {
+ GET_INT_VAL;
+ phid->phid.attr.ifkit.numInputs = value;
+ phid->phid.keyCount++;
+ }
+ else if(KEYNAME("NumberOfOutputs"))
+ {
+ GET_INT_VAL;
+ phid->phid.attr.ifkit.numOutputs = value;
+ phid->phid.keyCount++;
+ }
+ else if(KEYNAME("Input"))
+ {
+ if(CHKINDEX(ifkit.numInputs, IFKIT_MAXINPUTS))
+ {
+ GET_INT_VAL;
+ INC_KEYCOUNT(physicalState[index], PUNI_BOOL)
+ phid->physicalState[index] = value;
+ if(value != PUNK_BOOL)
+ FIRE(InputChange, index, value);
+ }
+ else
+ ret = EPHIDGET_OUTOFBOUNDS;
+ }
+ else if(KEYNAME("Sensor"))
+ {
+ if(CHKINDEX(ifkit.numSensors, IFKIT_MAXSENSORS))
+ {
+ GET_INT_VAL;
+ INC_KEYCOUNT(sensorValue[index], PUNI_INT)
+ phid->sensorValue[index] = value;
+ if(value != PUNK_INT)
+ FIRE(SensorChange, index, value);
+ }
+ else
+ ret = EPHIDGET_OUTOFBOUNDS;
+ }
+ else if(KEYNAME("RawSensor"))
+ {
+ if(CHKINDEX(ifkit.numSensors, IFKIT_MAXSENSORS))
+ {
+ GET_INT_VAL;
+ INC_KEYCOUNT(sensorRawValue[index], PUNI_INT)
+ phid->sensorRawValue[index] = value;
+ }
+ else
+ ret = EPHIDGET_OUTOFBOUNDS;
+ }
+ else if(KEYNAME("Output"))
+ {
+ if(CHKINDEX(ifkit.numOutputs, IFKIT_MAXOUTPUTS))
+ {
+ GET_INT_VAL;
+ INC_KEYCOUNT(outputEchoStates[index], PUNI_BOOL)
+ phid->outputEchoStates[index] = value;
+ if(value != PUNK_BOOL)
+ FIRE(OutputChange, index, value);
+ }
+ else
+ ret = EPHIDGET_OUTOFBOUNDS;
+ }
+ else if(KEYNAME("Trigger"))
+ {
+ if(CHKINDEX(ifkit.numSensors, IFKIT_MAXSENSORS))
+ {
+ GET_INT_VAL;
+ INC_KEYCOUNT(sensorChangeTrigger[index], PUNI_INT)
+ phid->sensorChangeTrigger[index] = value;
+ }
+ else
+ ret = EPHIDGET_OUTOFBOUNDS;
+ }
+ else if(KEYNAME("DataRate"))
+ {
+ if(CHKINDEX(ifkit.numSensors, IFKIT_MAXSENSORS))
+ {
+ GET_INT_VAL;
+ INC_KEYCOUNT(dataRate[index], PUNI_INT)
+ phid->dataRate[index] = value;
+ }
+ else
+ ret = EPHIDGET_OUTOFBOUNDS;
+ }
+ else if(KEYNAME("DataRateMin"))
+ {
+ GET_INT_VAL;
+ INC_KEYCOUNT(dataRateMin, PUNI_INT)
+ phid->dataRateMin = value;
+ }
+ else if(KEYNAME("DataRateMax"))
+ {
+ GET_INT_VAL;
+ INC_KEYCOUNT(dataRateMax, PUNI_INT)
+ phid->dataRateMax = value;
+ }
+ else if(KEYNAME("InterruptRate"))
+ {
+ GET_INT_VAL;
+ INC_KEYCOUNT(interruptRate, PUNI_INT)
+ phid->interruptRate = value;
+ phid->maxDataPerPacket = phid->phid.attr.ifkit.numSensors?phid->phid.attr.ifkit.numSensors:IFKIT_MAXSENSORS;
+ }
+ else if(KEYNAME("Ratiometric"))
+ {
+ GET_INT_VAL;
+ INC_KEYCOUNT(ratiometric, PUNI_BOOL)
+ phid->ratiometric = value;
+ phid->ratiometricEcho = value;
+ }
+ else{
+ PWC_BAD_SETTYPE(InterfaceKit);
+ }
+ return ret;
+}
+
+PWC_SETKEYS(IR)
+ if(KEYNAME("Code"))
+ {
+ unsigned char data[IR_MAX_CODE_DATA_LENGTH];
+ int bitCount, repeat, length = IR_MAX_CODE_DATA_LENGTH;
+ char *endPtr;
+
+ //this will stop at the first ','
+ stringToByteArray((char *)state, data, &length);
+ bitCount = strtol(state+length*2+1, &endPtr, 10);
+ repeat = strtol(endPtr+1, &endPtr, 10);
+
+ //send out the code event!
+ FIRE(Code, data, length, bitCount, repeat);
+
+ //store to last code
+ ZEROMEM(phid->lastCode, sizeof(phid->lastCode));
+ memcpy(phid->lastCode, data, length);
+ phid->lastCodeInfo.bitCount = bitCount;
+ phid->lastRepeat = repeat;
+ phid->lastCodeKnown = PTRUE;
+ }
+ else if(KEYNAME("Learn"))
+ {
+ unsigned char data[IR_MAX_CODE_DATA_LENGTH];
+ CPhidgetIR_CodeInfo codeInfo;
+ int length=IR_MAX_CODE_DATA_LENGTH;
+
+ stringToCodeInfo((char *)state, &codeInfo);
+ stringToByteArray((char *)(state+sizeof(CPhidgetIR_CodeInfo)*2), data, &length);
+
+ //send the event
+ FIRE(Learn, data, length, &codeInfo);
+
+ //store to last code
+ ZEROMEM(phid->lastLearnedCode, sizeof(phid->lastLearnedCode));
+ memcpy(phid->lastLearnedCode, data, length);
+ phid->lastLearnedCodeInfo = codeInfo;
+ phid->lastLearnedCodeKnown = PTRUE;
+ }
+ else if(KEYNAME("RawData"))
+ {
+ //TODO:
+ //what about multiple clients?
+ // -if a faster client is getting all the data and acking it, then the slower client will end up missing chunks...
+ // -we are assuming that data comes in in the same order as it is sent, so we don't deal with out of order keys
+
+ //only respond to new raw data
+ if(reason != PDR_CURRENT_VALUE)
+ {
+ int i;
+ int data[IR_MAX_CODE_DATA_LENGTH];
+ char key[1024], val[1024];
+ int rawDataSendCnt, length = IR_MAX_CODE_DATA_LENGTH;
+ char *endPtr;
+
+ //this will stop at the first ','
+ stringToWordArray((char *)state, data, &length);
+ rawDataSendCnt = strtol(state+length*5+1, &endPtr, 10);
+
+ //send an ACK for this count
+ CThread_mutex_lock(&phid->phid.lock);
+ snprintf(key, sizeof(key), "/PCK/%s/%d/RawDataAck/%d", phid->phid.deviceType, phid->phid.serialNumber, index);
+ snprintf(val, sizeof(val), "%d", rawDataSendCnt);
+ pdc_async_set(phid->phid.networkInfo->server->pdcs, key, val, (int)strlen(val), PFALSE, internal_async_network_error_handler, &phid->phid);
+ CThread_mutex_unlock(&phid->phid.lock);
+
+ //see if we lost a packet
+ if(phid->rawDataSendWSCounter != PUNK_INT && phid->rawDataSendWSCounter + 1 != rawDataSendCnt)
+ {
+ char error_buffer[127];
+ FIRE_ERROR_NOQUEUE(EEPHIDGET_PACKETLOST, "A piece on PhidgetIR Raw Data was lost. Be careful if decoding RawData manually.");
+
+ //reset data pointers
+ phid->dataWritePtr = 0;
+ phid->userReadPtr = 0;
+ }
+ phid->rawDataSendWSCounter = rawDataSendCnt;
+
+ //send the event
+ FIRE(RawData, data, length);
+
+ //TODO: store the raw data array
+ for(i=0;i<length;i++)
+ {
+ phid->dataBuffer[phid->dataWritePtr] = data[i];
+
+ phid->dataWritePtr++;
+ phid->dataWritePtr &= IR_DATA_ARRAY_MASK;
+ //if we run into data that hasn't been read... too bad, we overwrite it and adjust the read pointer
+ if(phid->dataWritePtr == phid->userReadPtr)
+ {
+ phid->userReadPtr++;
+ phid->userReadPtr &= IR_DATA_ARRAY_MASK;
+ }
+ }
+
+ }
+ }
+ else{
+ PWC_BAD_SETTYPE(IR);
+ }
+ return ret;
+}
+
+PWC_SETKEYS(LED)
+ if(KEYNAME("NumberOfLEDs"))
+ {
+ GET_INT_VAL;
+ phid->phid.attr.led.numLEDs = value;
+ phid->phid.keyCount++;
+ }
+ // initial brightness is unknown so don't keyCount++
+ else if(KEYNAME("Brightness"))
+ {
+ if(CHKINDEX(led.numLEDs, LED_MAXLEDS))
+ {
+ GET_INT_VAL;
+ INC_KEYCOUNT(LED_Power[index], PUNI_INT)
+ phid->LED_Power[index] = value;
+ }
+ else
+ ret = EPHIDGET_OUTOFBOUNDS;
+ }
+ else if(KEYNAME("Voltage"))
+ {
+ GET_INT_VAL;
+ INC_KEYCOUNT(voltageEcho, -1)
+ phid->voltageEcho = value;
+ }
+ else if(KEYNAME("CurrentLimit"))
+ {
+ GET_INT_VAL;
+ INC_KEYCOUNT(currentLimitEcho, -1)
+ phid->currentLimitEcho = value;
+ }
+ else{
+ PWC_BAD_SETTYPE(LED);
+ }
+ return ret;
+}
+
+PWC_SETKEYS(MotorControl)
+ if(KEYNAME("NumberOfMotors"))
+ {
+ GET_INT_VAL;
+ phid->phid.attr.motorcontrol.numMotors = value;
+ phid->phid.keyCount++;
+ }
+ else if(KEYNAME("NumberOfInputs"))
+ {
+ GET_INT_VAL;
+ phid->phid.attr.motorcontrol.numInputs = value;
+ phid->phid.keyCount++;
+ }
+ else if(KEYNAME("NumberOfEncoders"))
+ {
+ GET_INT_VAL;
+ phid->phid.attr.motorcontrol.numEncoders = value;
+ phid->phid.keyCount++;
+ }
+ else if(KEYNAME("NumberOfSensors"))
+ {
+ GET_INT_VAL;
+ phid->phid.attr.motorcontrol.numSensors = value;
+ phid->phid.keyCount++;
+ }
+ else if(KEYNAME("Input"))
+ {
+ if(CHKINDEX(motorcontrol.numInputs, MOTORCONTROL_MAXINPUTS))
+ {
+ GET_INT_VAL;
+ INC_KEYCOUNT(inputState[index], PUNI_BOOL)
+ phid->inputState[index] = value;
+ if(value != PUNK_BOOL)
+ FIRE(InputChange, index, value);
+ }
+ else
+ ret = EPHIDGET_OUTOFBOUNDS;
+ }
+ else if(KEYNAME("Sensor"))
+ {
+ if(CHKINDEX(motorcontrol.numSensors, MOTORCONTROL_MAXSENSORS))
+ {
+ GET_INT_VAL;
+ INC_KEYCOUNT(sensorValue[index], PUNI_INT)
+ phid->sensorValue[index] = value;
+ if(value != PUNK_INT)
+ FIRE(SensorUpdate, index, value);
+ }
+ else
+ ret = EPHIDGET_OUTOFBOUNDS;
+ }
+ else if(KEYNAME("RawSensor"))
+ {
+ if(CHKINDEX(motorcontrol.numSensors, MOTORCONTROL_MAXSENSORS))
+ {
+ GET_INT_VAL;
+ INC_KEYCOUNT(sensorRawValue[index], PUNI_INT)
+ phid->sensorRawValue[index] = value;
+ }
+ else
+ ret = EPHIDGET_OUTOFBOUNDS;
+ }
+ else if(KEYNAME("Ratiometric"))
+ {
+ GET_INT_VAL;
+ INC_KEYCOUNT(ratiometricEcho, PUNI_BOOL)
+ phid->ratiometricEcho = value;
+ }
+ else if(KEYNAME("Braking"))
+ {
+ if(CHKINDEX(motorcontrol.numMotors, MOTORCONTROL_MAXMOTORS))
+ {
+ GET_DOUBLE_VAL;
+ INC_KEYCOUNT(motorBrakingEcho[index], PUNI_DBL)
+ phid->motorBrakingEcho[index] = value;
+ }
+ else
+ ret = EPHIDGET_OUTOFBOUNDS;
+ }
+ else if(KEYNAME("BackEMF"))
+ {
+ if(CHKINDEX(motorcontrol.numMotors, MOTORCONTROL_MAXMOTORS))
+ {
+ GET_DOUBLE_VAL;
+ INC_KEYCOUNT(motorSensedBackEMF[index], PUNI_DBL)
+ phid->motorSensedBackEMF[index] = value;
+ if(value != PUNK_DBL)
+ FIRE(BackEMFUpdate, index, value);
+ }
+ else
+ ret = EPHIDGET_OUTOFBOUNDS;
+ }
+ else if(KEYNAME("BackEMFState"))
+ {
+ if(CHKINDEX(motorcontrol.numMotors, MOTORCONTROL_MAXMOTORS))
+ {
+ GET_INT_VAL;
+ INC_KEYCOUNT(backEMFSensingStateEcho[index], PUNI_BOOL)
+ phid->backEMFSensingStateEcho[index] = value;
+ }
+ else
+ ret = EPHIDGET_OUTOFBOUNDS;
+ }
+ else if(KEYNAME("SupplyVoltage"))
+ {
+ GET_DOUBLE_VAL;
+ INC_KEYCOUNT(supplyVoltage, PUNI_DBL)
+ phid->supplyVoltage = value;
+ }
+ else if(KEYNAME("Velocity"))
+ {
+ if(CHKINDEX(motorcontrol.numMotors, MOTORCONTROL_MAXMOTORS))
+ {
+ GET_DOUBLE_VAL;
+ INC_KEYCOUNT(motorSpeedEcho[index], PUNI_DBL)
+ phid->motorSpeedEcho[index] = value;
+ if(value != PUNK_DBL)
+ FIRE(VelocityChange, index, value);
+ //Deprecated
+ if(value != PUNK_DBL)
+ FIRE(MotorChange, index, value);
+ }
+ else
+ ret = EPHIDGET_OUTOFBOUNDS;
+ }
+ else if(KEYNAME("Current"))
+ {
+ if(CHKINDEX(motorcontrol.numMotors, MOTORCONTROL_MAXMOTORS))
+ {
+ GET_DOUBLE_VAL;
+ INC_KEYCOUNT(motorSensedCurrent[index], PUNI_DBL)
+ phid->motorSensedCurrent[index] = value;
+ if(value != PUNK_DBL)
+ FIRE(CurrentChange, index, value);
+ }
+ else
+ ret = EPHIDGET_OUTOFBOUNDS;
+ }
+ else if(KEYNAME("CurrentUpdate"))
+ {
+ if(CHKINDEX(motorcontrol.numMotors, MOTORCONTROL_MAXMOTORS))
+ {
+ GET_DOUBLE_VAL;
+ phid->motorSensedCurrent[index] = value;
+ if(value != PUNK_DBL)
+ FIRE(CurrentUpdate, index, value);
+ }
+ else
+ ret = EPHIDGET_OUTOFBOUNDS;
+ }
+ // initial acceleration is unknown so don't keyCount++
+ else if(KEYNAME("Acceleration"))
+ {
+ if(CHKINDEX(motorcontrol.numMotors, MOTORCONTROL_MAXMOTORS))
+ {
+ GET_DOUBLE_VAL;
+ INC_KEYCOUNT(motorAccelerationEcho[index], PUNI_DBL)
+ phid->motorAccelerationEcho[index] = value;
+ phid->motorAcceleration[index] = value;
+ }
+ else
+ ret = EPHIDGET_OUTOFBOUNDS;
+ }
+ else if(KEYNAME("AccelerationMin"))
+ {
+ GET_DOUBLE_VAL;
+ INC_KEYCOUNT(accelerationMin, PUNI_DBL)
+ phid->accelerationMin = value;
+ }
+ else if(KEYNAME("AccelerationMax"))
+ {
+ GET_DOUBLE_VAL;
+ INC_KEYCOUNT(accelerationMax, PUNI_DBL)
+ phid->accelerationMax = value;
+ }
+ // initial Position is unknown so don't keyCount++
+ else if(KEYNAME("ResetEncoderPosition"))
+ {
+ if(CHKINDEX(motorcontrol.numEncoders, MOTORCONTROL_MAXENCODERS))
+ {
+ GET_INT_VAL;
+ phid->encoderPositionDelta[index] = value;
+ }
+ else
+ ret = EPHIDGET_OUTOFBOUNDS;
+ }
+ else if(KEYNAME("EncoderPosition"))
+ {
+ if(CHKINDEX(motorcontrol.numEncoders, MOTORCONTROL_MAXENCODERS))
+ {
+ char *endPtr;
+ int time = strtol(state, &endPtr, 10);
+ int posn = strtol(endPtr+1, NULL, 10);
+ int posnChange = posn - phid->encoderPositionEcho[index];
+ int encoderTimeChange = time - phid->encoderTimeStamp[index];
+
+ //timeout is 20 seconds
+ if (encoderTimeChange > 60000)
+ encoderTimeChange = PUNK_INT;
+
+ phid->encoderPositionEcho[index] = posn;
+ phid->encoderTimeStamp[index] = time;
+
+ FIRE(EncoderPositionChange, index, encoderTimeChange, posnChange);
+ }
+ else
+ ret = EPHIDGET_OUTOFBOUNDS;
+ }
+ else if(KEYNAME("EncoderPositionUpdate"))
+ {
+ if(CHKINDEX(motorcontrol.numEncoders, MOTORCONTROL_MAXENCODERS))
+ {
+ int posn = strtol(state, NULL, 10);
+ int posnChange = posn - phid->encoderPositionUpdates[index];
+
+ phid->encoderPositionUpdates[index] = posn;
+
+ FIRE(EncoderPositionUpdate, index, posnChange);
+ }
+ else
+ ret = EPHIDGET_OUTOFBOUNDS;
+ }
+ else{
+ PWC_BAD_SETTYPE(MotorControl);
+ }
+ return ret;
+}
+
+PWC_SETKEYS(PHSensor)
+ if(KEYNAME("PH"))
+ {
+ GET_DOUBLE_VAL;
+ INC_KEYCOUNT(PH, PUNI_DBL)
+ phid->PH = value;
+ if(value != PUNK_DBL)
+ FIRE(PHChange, value);
+ }
+ else if(KEYNAME("PHMin"))
+ {
+ GET_DOUBLE_VAL;
+ INC_KEYCOUNT(phMin, PUNI_DBL)
+ phid->phMin = value;
+ }
+ else if(KEYNAME("PHMax"))
+ {
+ GET_DOUBLE_VAL;
+ INC_KEYCOUNT(phMax, PUNI_DBL)
+ phid->phMax = value;
+ }
+ else if(KEYNAME("Trigger"))
+ {
+ GET_DOUBLE_VAL;
+ INC_KEYCOUNT(PHChangeTrigger, PUNI_DBL)
+ phid->PHChangeTrigger = value;
+ }
+ else if(KEYNAME("Potential"))
+ {
+ GET_DOUBLE_VAL;
+ INC_KEYCOUNT(Potential, PUNI_DBL)
+ phid->Potential = value;
+ }
+ else if(KEYNAME("PotentialMin"))
+ {
+ GET_DOUBLE_VAL;
+ INC_KEYCOUNT(potentialMin, PUNI_DBL)
+ phid->potentialMin = value;
+ }
+ else if(KEYNAME("PotentialMax"))
+ {
+ GET_DOUBLE_VAL;
+ INC_KEYCOUNT(potentialMax, PUNI_DBL)
+ phid->potentialMax = value;
+ }
+ else{
+ PWC_BAD_SETTYPE(PHSensor);
+ }
+ return ret;
+}
+
+PWC_SETKEYS(RFID)
+ if(KEYNAME("NumberOfOutputs"))
+ {
+ GET_INT_VAL;
+ phid->phid.attr.rfid.numOutputs = value;
+ phid->phid.keyCount++;
+ }
+ else if(KEYNAME("LastTag"))
+ {
+ unsigned char tagData[5];
+ INC_KEYCOUNT(lastTagValid, PUNI_BOOL)
+ phid->lastTagValid = PTRUE;
+
+ tagData[0] = (hexval(state[0])<<4)|hexval(state[1]);
+ tagData[1] = (hexval(state[2])<<4)|hexval(state[3]);
+ tagData[2] = (hexval(state[4])<<4)|hexval(state[5]);
+ tagData[3] = (hexval(state[6])<<4)|hexval(state[7]);
+ tagData[4] = (hexval(state[8])<<4)|hexval(state[9]);
+
+ memcpy(phid->lastTag, tagData, 5);
+ }
+ else if(KEYNAME("Tag"))
+ {
+ unsigned char tagData[5];
+ //always increment on tagPresent==PUNI_BOOL before setting it!
+ INC_KEYCOUNT(tagPresent, PUNI_BOOL)
+ phid->tagPresent = 1;
+
+ tagData[0] = (hexval(state[0])<<4)|hexval(state[1]);
+ tagData[1] = (hexval(state[2])<<4)|hexval(state[3]);
+ tagData[2] = (hexval(state[4])<<4)|hexval(state[5]);
+ tagData[3] = (hexval(state[6])<<4)|hexval(state[7]);
+ tagData[4] = (hexval(state[8])<<4)|hexval(state[9]);
+
+ FIRE(Tag, tagData);
+
+ memcpy(phid->lastTag, tagData, 5);
+ }
+ else if(KEYNAME("TagLoss"))
+ {
+ //always increment on tagPresent==PUNI_BOOL before setting it!
+ INC_KEYCOUNT(tagPresent, PUNI_BOOL)
+ phid->tagPresent = 0;
+ FIRE(TagLost, phid->lastTag);
+ }
+ else if(KEYNAME("TagState"))
+ {
+ GET_INT_VAL;
+ //always increment on tagPresent==PUNI_BOOL before setting it!
+ INC_KEYCOUNT(tagPresent, PUNI_BOOL)
+ phid->tagPresent = value;
+ }
+ else if(KEYNAME("Output"))
+ {
+ if(CHKINDEX(rfid.numOutputs, RFID_MAXOUTPUTS))
+ {
+ GET_INT_VAL;
+ INC_KEYCOUNT(outputEchoState[index], PUNI_BOOL)
+ phid->outputEchoState[index] = value;
+ if(value != PUNK_BOOL)
+ FIRE(OutputChange, index, value);
+ }
+ else
+ ret = EPHIDGET_OUTOFBOUNDS;
+ }
+ else if(KEYNAME("AntennaOn"))
+ {
+ GET_INT_VAL;
+ INC_KEYCOUNT(antennaEchoState, PUNI_BOOL)
+ phid->antennaEchoState = value;
+ }
+ else if(KEYNAME("LEDOn"))
+ {
+ GET_INT_VAL;
+ INC_KEYCOUNT(ledEchoState, PUNI_BOOL)
+ phid->ledEchoState = value;
+ }
+ else{
+ PWC_BAD_SETTYPE(RFID);
+ }
+ return ret;
+}
+
+PWC_SETKEYS(Servo)
+ if(KEYNAME("NumberOfMotors"))
+ {
+ GET_INT_VAL;
+ phid->phid.attr.led.numLEDs = value;
+ phid->phid.keyCount++;
+ }
+ else if(KEYNAME("Position"))
+ {
+ if(CHKINDEX(servo.numMotors, SERVO_MAXSERVOS))
+ {
+ GET_DOUBLE_VAL;
+ INC_KEYCOUNT(motorPositionEcho[index], PUNI_DBL)
+ phid->motorPositionEcho[index]= value;
+ if(value != PUNK_DBL)
+ FIRE(PositionChange, index, servo_us_to_degrees(phid->servoParams[index], value, PTRUE));
+ //Deprecated
+ if(value != PUNK_DBL)
+ FIRE(MotorPositionChange, index, servo_us_to_degrees(phid->servoParams[index], value, PTRUE));
+ }
+ else
+ ret = EPHIDGET_OUTOFBOUNDS;
+ }
+ else if(KEYNAME("Engaged"))
+ {
+ if(CHKINDEX(servo.numMotors, SERVO_MAXSERVOS))
+ {
+ GET_INT_VAL;
+ INC_KEYCOUNT(motorEngagedStateEcho[index], PUNI_BOOL)
+ phid->motorEngagedStateEcho[index] = value;
+ }
+ else
+ ret = EPHIDGET_OUTOFBOUNDS;
+ }
+ else if(KEYNAME("PositionMinLimit"))
+ {
+ GET_DOUBLE_VAL;
+ INC_KEYCOUNT(motorPositionMinLimit, PUNI_DBL)
+ phid->motorPositionMinLimit = value;
+ }
+ else if(KEYNAME("PositionMaxLimit"))
+ {
+ GET_DOUBLE_VAL;
+ INC_KEYCOUNT(motorPositionMaxLimit, PUNI_DBL)
+ phid->motorPositionMaxLimit = value;
+ }
+ else if(KEYNAME("ServoParameters"))
+ {
+ if(CHKINDEX(servo.numMotors, SERVO_MAXSERVOS))
+ {
+ CPhidgetServoParameters params;
+ char *endptr;
+ params.servoType = strtol(state, &endptr, 10);
+ params.min_us = strtod(endptr+1, &endptr);
+ params.max_us = strtod(endptr+1, &endptr);
+ params.us_per_degree = strtod(endptr+1, NULL);
+ params.state = PTRUE;
+
+ INC_KEYCOUNT(servoParams[index].state, PUNI_BOOL)
+
+ phid->servoParams[index] = params;
+
+ //Set the max/min
+ //make sure we don't set max higher then the limit
+ if(params.max_us > phid->motorPositionMaxLimit)
+ phid->motorPositionMax[index] = phid->motorPositionMaxLimit;
+ else
+ phid->motorPositionMax[index] = params.max_us;
+
+ phid->motorPositionMin[index] = params.min_us;
+ }
+ else
+ ret = EPHIDGET_OUTOFBOUNDS;
+ }
+ else{
+ PWC_BAD_SETTYPE(Servo);
+ }
+ return ret;
+}
+
+PWC_SETKEYS(Spatial)
+ if(KEYNAME("AccelerationAxisCount"))
+ {
+ GET_INT_VAL;
+ phid->phid.attr.spatial.numAccelAxes = value;
+ phid->phid.keyCount++;
+ }
+ else if(KEYNAME("GyroAxisCount"))
+ {
+ GET_INT_VAL;
+ phid->phid.attr.spatial.numGyroAxes = value;
+ phid->phid.keyCount++;
+ }
+ else if(KEYNAME("CompassAxisCount"))
+ {
+ GET_INT_VAL;
+ phid->phid.attr.spatial.numCompassAxes = value;
+ phid->phid.keyCount++;
+ }
+ else if(KEYNAME("DataRate"))
+ {
+ GET_INT_VAL;
+ INC_KEYCOUNT(dataRate, PUNI_INT)
+ phid->dataRate = value;
+ }
+ else if(KEYNAME("DataRateMin"))
+ {
+ GET_INT_VAL;
+ INC_KEYCOUNT(dataRateMin, PUNI_INT)
+ phid->dataRateMin = value;
+ }
+ else if(KEYNAME("DataRateMax"))
+ {
+ GET_INT_VAL;
+ INC_KEYCOUNT(dataRateMax, PUNI_INT)
+ phid->dataRateMax = value;
+ }
+ else if(KEYNAME("InterruptRate"))
+ {
+ GET_INT_VAL;
+ INC_KEYCOUNT(interruptRate, PUNI_INT)
+ phid->interruptRate = value;
+ }
+ else if(KEYNAME("AccelerationMin"))
+ {
+ GET_DOUBLE_VAL;
+ INC_KEYCOUNT(accelerationMin, PUNI_DBL)
+ phid->accelerationMin = value;
+ }
+ else if(KEYNAME("AccelerationMax"))
+ {
+ GET_DOUBLE_VAL;
+ INC_KEYCOUNT(accelerationMax, PUNI_DBL)
+ phid->accelerationMax = value;
+ }
+ else if(KEYNAME("AngularRateMin"))
+ {
+ GET_DOUBLE_VAL;
+ INC_KEYCOUNT(angularRateMin, PUNI_DBL)
+ phid->angularRateMin = value;
+ }
+ else if(KEYNAME("AngularRateMax"))
+ {
+ GET_DOUBLE_VAL;
+ INC_KEYCOUNT(angularRateMax, PUNI_DBL)
+ phid->angularRateMax = value;
+ }
+ else if(KEYNAME("MagneticFieldMin"))
+ {
+ GET_DOUBLE_VAL;
+ INC_KEYCOUNT(magneticFieldMin, PUNI_DBL)
+ phid->magneticFieldMin = value;
+ }
+ else if(KEYNAME("MagneticFieldMax"))
+ {
+ GET_DOUBLE_VAL;
+ INC_KEYCOUNT(magneticFieldMax, PUNI_DBL)
+ phid->magneticFieldMax = value;
+ }
+ else if(KEYNAME("SpatialData"))
+ {
+ CPhidgetSpatial_SpatialEventDataHandle eventData[1];
+ CPhidgetSpatial_SpatialEventData spatialData;
+ int i;
+ char *endptr = (char *)state-1;
+
+ INC_KEYCOUNT(spatialDataNetwork, PUNI_BOOL)
+ phid->spatialDataNetwork = PTRUE;
+
+ for(i=0;i<SPATIAL_MAX_ACCELAXES;i++)
+ {
+ phid->accelAxis[i] = spatialData.acceleration[i] = strtod(endptr+1, &endptr);
+ }
+ for(i=0;i<SPATIAL_MAX_GYROAXES;i++)
+ {
+ phid->gyroAxis[i] = spatialData.angularRate[i] = strtod(endptr+1, &endptr);
+ }
+ for(i=0;i<SPATIAL_MAX_COMPASSAXES;i++)
+ {
+ phid->compassAxis[i] = spatialData.magneticField[i] = strtod(endptr+1, &endptr);
+ }
+
+ spatialData.timestamp.seconds = strtol(endptr+1, &endptr, 10);
+ spatialData.timestamp.microseconds = strtol(endptr+1, NULL, 10);
+
+ eventData[0] = &spatialData;
+ FIRE(SpatialData, eventData, 1);
+ }
+ else{
+ PWC_BAD_SETTYPE(Spatial);
+ }
+ return ret;
+}
+
+PWC_SETKEYS(Stepper)
+ if(KEYNAME("NumberOfMotors"))
+ {
+ GET_INT_VAL;
+ phid->phid.attr.stepper.numMotors = value;
+ phid->phid.keyCount++;
+ }
+ else if(KEYNAME("NumberOfInputs"))
+ {
+ GET_INT_VAL;
+ phid->phid.attr.stepper.numInputs = value;
+ phid->phid.keyCount++;
+ }
+ else if(KEYNAME("Input"))
+ {
+ if(CHKINDEX(stepper.numInputs, STEPPER_MAXINPUTS))
+ {
+ GET_INT_VAL;
+ INC_KEYCOUNT(inputState[index], PUNI_BOOL)
+ phid->inputState[index] = value;
+ if(value != PUNK_BOOL)
+ FIRE(InputChange, index, value);
+ }
+ else
+ ret = EPHIDGET_OUTOFBOUNDS;
+ }
+ else if(KEYNAME("CurrentPosition"))
+ {
+ if(CHKINDEX(stepper.numMotors, STEPPER_MAXSTEPPERS))
+ {
+ GET_INT64_VAL;
+ INC_KEYCOUNT(motorPositionEcho[index], PUNI_INT64)
+ phid->motorPositionEcho[index] = value;
+ if(value != PUNK_INT64)
+ FIRE(PositionChange, index, value);
+ }
+ else
+ ret = EPHIDGET_OUTOFBOUNDS;
+ }
+ // initial target position isn't a keyCount++ sort of thing
+ else if(KEYNAME("TargetPosition"))
+ {
+ if(CHKINDEX(stepper.numMotors, STEPPER_MAXSTEPPERS))
+ {
+ GET_INT64_VAL;
+ INC_KEYCOUNT(motorPosition[index], PUNI_INT64)
+ phid->motorPosition[index] = value;
+ }
+ else
+ ret = EPHIDGET_OUTOFBOUNDS;
+ }
+ else if(KEYNAME("PositionMin"))
+ {
+ GET_INT64_VAL;
+ INC_KEYCOUNT(motorPositionMin, PUNI_INT64)
+ phid->motorPositionMin = value;
+ }
+ else if(KEYNAME("PositionMax"))
+ {
+ GET_INT64_VAL;
+ INC_KEYCOUNT(motorPositionMax, PUNI_INT64)
+ phid->motorPositionMax = value;
+ }
+ // initial acceleration is unknown so dont' keyCount++
+ else if(KEYNAME("Acceleration"))
+ {
+ if(CHKINDEX(stepper.numMotors, STEPPER_MAXSTEPPERS))
+ {
+ GET_DOUBLE_VAL;
+ phid->motorAcceleration[index] = value;
+ }
+ else
+ ret = EPHIDGET_OUTOFBOUNDS;
+ }
+ else if(KEYNAME("AccelerationMin"))
+ {
+ GET_DOUBLE_VAL;
+ INC_KEYCOUNT(accelerationMin, PUNI_DBL)
+ phid->accelerationMin = value;
+ }
+ else if(KEYNAME("AccelerationMax"))
+ {
+ GET_DOUBLE_VAL;
+ INC_KEYCOUNT(accelerationMax, PUNI_DBL)
+ phid->accelerationMax = value;
+ }
+ // initial current limit is unknown so dont' keyCount++
+ else if(KEYNAME("CurrentLimit"))
+ {
+ if(CHKINDEX(stepper.numMotors, STEPPER_MAXSTEPPERS))
+ {
+ GET_DOUBLE_VAL;
+ phid->motorCurrentLimit[index] = value;
+ }
+ else
+ ret = EPHIDGET_OUTOFBOUNDS;
+ }
+ else if(KEYNAME("Current"))
+ {
+ if(CHKINDEX(stepper.numMotors, STEPPER_MAXSTEPPERS))
+ {
+ GET_DOUBLE_VAL;
+ INC_KEYCOUNT(motorSensedCurrent[index], PUNI_DBL)
+ phid->motorSensedCurrent[index] = value;
+ if(value != PUNK_DBL)
+ FIRE(CurrentChange, index, value);
+ }
+ else
+ ret = EPHIDGET_OUTOFBOUNDS;
+ }
+ else if(KEYNAME("CurrentMin"))
+ {
+ GET_DOUBLE_VAL;
+ INC_KEYCOUNT(currentMin, PUNI_DBL)
+ phid->currentMin = value;
+ }
+ else if(KEYNAME("CurrentMax"))
+ {
+ GET_DOUBLE_VAL;
+ INC_KEYCOUNT(currentMax, PUNI_DBL)
+ phid->currentMax = value;
+ }
+ // initial velocity limit is unknown so dont' keyCount++
+ else if(KEYNAME("VelocityLimit"))
+ {
+ GET_DOUBLE_VAL;
+ phid->motorSpeed[index] = value;
+ }
+ else if(KEYNAME("Velocity"))
+ {
+ if(CHKINDEX(stepper.numMotors, STEPPER_MAXSTEPPERS))
+ {
+ GET_DOUBLE_VAL;
+ INC_KEYCOUNT(motorSpeedEcho[index], PUNI_DBL)
+ phid->motorSpeedEcho[index] = value;
+ if(value != PUNK_DBL)
+ FIRE(VelocityChange, index, value);
+ }
+ else
+ ret = EPHIDGET_OUTOFBOUNDS;
+ }
+ else if(KEYNAME("VelocityMin"))
+ {
+ GET_DOUBLE_VAL;
+ INC_KEYCOUNT(motorSpeedMin, PUNI_DBL)
+ phid->motorSpeedMin = value;
+ }
+ else if(KEYNAME("VelocityMax"))
+ {
+ GET_DOUBLE_VAL;
+ INC_KEYCOUNT(motorSpeedMax, PUNI_DBL)
+ phid->motorSpeedMax = value;
+ }
+ else if(KEYNAME("Engaged"))
+ {
+ if(CHKINDEX(stepper.numMotors, STEPPER_MAXSTEPPERS))
+ {
+ GET_INT_VAL;
+ INC_KEYCOUNT(motorEngagedStateEcho[index], PUNI_BOOL)
+ phid->motorEngagedStateEcho[index] = value;
+ }
+ else
+ ret = EPHIDGET_OUTOFBOUNDS;
+ }
+ else if(KEYNAME("Stopped"))
+ {
+ if(CHKINDEX(stepper.numMotors, STEPPER_MAXSTEPPERS))
+ {
+ GET_INT_VAL;
+ unsigned char lastStoppedState = phid->motorStoppedState[index];
+ INC_KEYCOUNT(motorStoppedState[index], PUNI_BOOL)
+ phid->motorStoppedState[index] = value;
+ //If changed, re-run position/velocity events, so the stopped change will be noticed
+ if(lastStoppedState != value)
+ {
+ if(phid->motorSpeedEcho[index] != PUNK_DBL)
+ FIRE(VelocityChange, index, phid->motorSpeedEcho[index]);
+ if(phid->motorPositionEcho[index] != PUNK_INT64)
+ FIRE(PositionChange, index, phid->motorPositionEcho[index]);
+ }
+ }
+ else
+ ret = EPHIDGET_OUTOFBOUNDS;
+ }
+ else{
+ PWC_BAD_SETTYPE(Stepper);
+ }
+ return ret;
+}
+
+PWC_SETKEYS(TemperatureSensor)
+ if(KEYNAME("NumberOfSensors"))
+ {
+ GET_INT_VAL;
+ phid->phid.attr.temperaturesensor.numTempInputs = value;
+ phid->phid.keyCount++;
+ }
+ else if(KEYNAME("Potential"))
+ {
+ if(CHKINDEX(temperaturesensor.numTempInputs, TEMPSENSOR_MAXSENSORS))
+ {
+ GET_DOUBLE_VAL;
+ INC_KEYCOUNT(Potential[index], PUNI_DBL)
+ phid->Potential[index] = value;
+ }
+ else
+ ret = EPHIDGET_OUTOFBOUNDS;
+ }
+ else if(KEYNAME("PotentialMin"))
+ {
+ GET_DOUBLE_VAL;
+ INC_KEYCOUNT(potentialMin, PUNI_DBL)
+ phid->potentialMin = value;
+ }
+ else if(KEYNAME("PotentialMax"))
+ {
+ GET_DOUBLE_VAL;
+ INC_KEYCOUNT(potentialMax, PUNI_DBL)
+ phid->potentialMax = value;
+ }
+ else if(KEYNAME("Temperature"))
+ {
+ if(CHKINDEX(temperaturesensor.numTempInputs, TEMPSENSOR_MAXSENSORS))
+ {
+ GET_DOUBLE_VAL;
+ INC_KEYCOUNT(Temperature[index], PUNI_DBL)
+ phid->Temperature[index] = value;
+ if(value != PUNK_DBL)
+ FIRE(TemperatureChange, index, value);
+ }
+ else
+ ret = EPHIDGET_OUTOFBOUNDS;
+ }
+ else if(KEYNAME("TemperatureMin"))
+ {
+ GET_DOUBLE_VAL;
+ INC_KEYCOUNT(temperatureMin[index], PUNI_DBL)
+ phid->temperatureMin[index] = value;
+ }
+ else if(KEYNAME("TemperatureMax"))
+ {
+ GET_DOUBLE_VAL;
+ INC_KEYCOUNT(temperatureMax[index], PUNI_DBL)
+ phid->temperatureMax[index] = value;
+ }
+ else if(KEYNAME("AmbientTemperature"))
+ {
+ GET_DOUBLE_VAL;
+ INC_KEYCOUNT(AmbientTemperature, PUNI_DBL)
+ phid->AmbientTemperature = value;
+ }
+ else if(KEYNAME("AmbientTemperatureMin"))
+ {
+ GET_DOUBLE_VAL;
+ INC_KEYCOUNT(ambientTemperatureMin, PUNI_DBL)
+ phid->ambientTemperatureMin = value;
+ }
+ else if(KEYNAME("AmbientTemperatureMax"))
+ {
+ GET_DOUBLE_VAL;
+ INC_KEYCOUNT(ambientTemperatureMax, PUNI_DBL)
+ phid->ambientTemperatureMax = value;
+ }
+ else if(KEYNAME("ThermocoupleType"))
+ {
+ GET_INT_VAL;
+ INC_KEYCOUNT(ThermocoupleType[index], -1)
+ phid->ThermocoupleType[index] = value;
+ }
+ else if(KEYNAME("Trigger"))
+ {
+ if(CHKINDEX(temperaturesensor.numTempInputs, TEMPSENSOR_MAXSENSORS))
+ {
+ GET_DOUBLE_VAL;
+ INC_KEYCOUNT(TempChangeTrigger[index], PUNI_DBL)
+ phid->TempChangeTrigger[index] = value;
+ }
+ else
+ ret = EPHIDGET_OUTOFBOUNDS;
+ }
+ else{
+ PWC_BAD_SETTYPE(TemperatureSensor);
+ }
+ return ret;
+}
+
+PWC_SETKEYS(TextLCD)
+ GET_INT_VAL;
+
+ if(KEYNAME("NumberOfRows"))
+ {
+ INC_KEYCOUNT(rowCount[index], PUNI_INT)
+ phid->rowCount[index] = value;
+ }
+ else if(KEYNAME("NumberOfColumns"))
+ {
+ INC_KEYCOUNT(columnCount[index], PUNI_INT)
+ phid->columnCount[index] = value;
+ }
+ else if(KEYNAME("NumberOfScreens"))
+ {
+ phid->phid.attr.textlcd.numScreens = value;
+ phid->phid.keyCount++;
+ }
+ else if(KEYNAME("Backlight"))
+ {
+ INC_KEYCOUNT(backlightEcho[index], PUNI_BOOL)
+ phid->backlightEcho[index] = (unsigned char)value;
+ }
+ else if(KEYNAME("CursorOn"))
+ {
+ phid->cursorOn[index] = (unsigned char)value;
+ }
+ else if(KEYNAME("CursorBlink"))
+ {
+ phid->cursorBlink[index] = (unsigned char)value;
+ }
+ else if(KEYNAME("Contrast"))
+ {
+ INC_KEYCOUNT(contrastEcho[index], PUNI_INT)
+ phid->contrastEcho[index] = (unsigned char)value;
+ }
+ else if(KEYNAME("Brightness"))
+ {
+ INC_KEYCOUNT(brightnessEcho[index], PUNI_INT)
+ phid->brightnessEcho[index] = (unsigned char)value;
+ }
+ else if(KEYNAME("ScreenSize"))
+ {
+ INC_KEYCOUNT(screenSize[index], -1)
+ phid->screenSize[index] = value;
+ }
+ else{
+ PWC_BAD_SETTYPE(TextLCD);
+ }
+ return ret;
+}
+
+PWC_SETKEYS(TextLED)
+ GET_INT_VAL;
+ if(KEYNAME("NumberOfRows"))
+ {
+ phid->phid.attr.textled.numRows = value;
+ phid->phid.keyCount++;
+ }
+ else if(KEYNAME("NumberOfColumns"))
+ {
+ phid->phid.attr.textled.numColumns = value;
+ phid->phid.keyCount++;
+ }
+ // this is unknown at attach, so no keyCount++
+ else if(KEYNAME("Brightness"))
+ {
+ phid->brightness = value;
+ }
+ else{
+ PWC_BAD_SETTYPE(TextLED);
+ }
+ return ret;
+}
+
+PWC_SETKEYS(WeightSensor)
+ if(KEYNAME("Weight"))
+ {
+ GET_DOUBLE_VAL;
+ INC_KEYCOUNT(Weight, PUNI_DBL)
+ phid->Weight = value;
+ if(value != PUNK_DBL)
+ FIRE(WeightChange, value);
+ }
+ else if(KEYNAME("Trigger"))
+ {
+ GET_DOUBLE_VAL;
+ INC_KEYCOUNT(WeightChangeTrigger, PUNI_DBL)
+ phid->WeightChangeTrigger = value;
+ }
+ else{
+ PWC_BAD_SETTYPE(WeightSensor);
+ }
+ return ret;
+}
+
+int(*fptrSet[PHIDGET_DEVICE_CLASS_COUNT])(CPhidgetHandle generic_phid, const char *setThing, int index, const char *state, pdict_reason_t reason) = {
+NULL,
+NULL,
+phidgetAccelerometer_set,
+phidgetAdvancedServo_set,
+phidgetEncoder_set,
+phidgetGPS_set,
+NULL,//old gyro,
+phidgetInterfaceKit_set,
+phidgetLED_set,
+phidgetMotorControl_set,
+phidgetPHSensor_set,
+phidgetRFID_set,
+phidgetServo_set,
+phidgetStepper_set,
+phidgetTemperatureSensor_set,
+phidgetTextLCD_set,
+phidgetTextLED_set,
+phidgetWeightSensor_set,
+phidgetGeneric_set,
+phidgetIR_set,
+phidgetSpatial_set,
+phidgetFrequencyCounter_set,
+phidgetAnalog_set,
+phidgetBridge_set};
+void network_phidget_event_handler(const char *key, const char *val, unsigned int len, pdict_reason_t reason, void *ptr)
+{
+ CPhidgetHandle phid = (CPhidgetHandle)ptr;
+ regmatch_t pmatch[7];
+ char *setThing = NULL;
+ char *index = NULL;
+ char *serial = NULL;
+ char *label = NULL, *l = NULL;
+ char errbuf[1024];
+
+ int serialNumber;
+
+ int res, ind = PUNK_INT, i, ret = EPHIDGET_OK;
+
+ if(!strncmp(val, "\001", 1) && len == 1)
+ {
+ memset((char *)val,0,1);
+ }
+
+
+ if(!CPhidget_statusFlagIsSet(phid->status, PHIDGET_SERVER_CONNECTED_FLAG))
+ {
+ LOG(PHIDGET_LOG_VERBOSE, "network_phidget_event_handler: key ignored: %s Value: %s",key,val);
+ }
+ else if(reason!=PDR_ENTRY_REMOVING || !strncmp(val, "Detached", sizeof("Detached")))
+ {
+ LOG(PHIDGET_LOG_VERBOSE, "network_phidget_event_handler: key: %s Value: %s",key,val);
+ if ((res = regexec(&phidgetsetex, key, 7, pmatch, 0)) != 0) {
+ LOG(PHIDGET_LOG_DEBUG,"Error in network_phidget_event_handler - pattern not met for key: \"%s\"",key);
+ return;
+ }
+ getmatchsub(key, &label, pmatch, 2);
+ getmatchsub(key, &serial, pmatch, 3);
+ getmatchsub(key, &setThing, pmatch, 4);
+ getmatchsub(key, &index, pmatch, 5);
+
+ if(l)
+ {
+ if (!unescape(l, &label, NULL))
+ {
+ LOG(PHIDGET_LOG_ERROR, "Error in unescape");
+ return;
+ }
+ }
+
+ serialNumber = strtol(serial, NULL, 10);
+
+ if(phid->specificDevice == PHIDGETOPEN_ANY && strncmp(val, "Detached", sizeof("Detached")))
+ {
+ phid->specificDevice = PHIDGETOPEN_ANY_ATTACHED;
+ phid->serialNumber = serialNumber;
+ }
+
+ if(phid->specificDevice == PHIDGETOPEN_LABEL && strncmp(val, "Detached", sizeof("Detached")))
+ {
+ phid->serialNumber = serialNumber;
+ }
+
+ if(serialNumber == phid->serialNumber && setThing)
+ {
+ if(KEYNAME("Label"))
+ {
+ strncpy(phid->label, val, MAX_LABEL_STORAGE);
+ phid->keyCount++;
+ }
+ else if(KEYNAME("InitKeys"))
+ {
+ phid->initKeys = strtol(val, NULL, 10);
+ phid->keyCount++;
+ }
+ else if(KEYNAME("Version"))
+ {
+ phid->deviceVersion = strtol(val, NULL, 10);
+ phid->keyCount++;
+ }
+ else if(KEYNAME("ID"))
+ {
+ phid->deviceIDSpec = strtol(val, NULL, 10);
+ phid->deviceType = Phid_DeviceName[phid->deviceID];
+ phid->keyCount++;
+
+ for(i = 1;i<PHIDGET_DEVICE_COUNT;i++)
+ {
+ if(Phid_Device_Def[i].pdd_sdid == phid->deviceIDSpec)
+ {
+ phid->deviceDef = &Phid_Device_Def[i];
+ phid->attr = Phid_Device_Def[i].pdd_attr;
+ break;
+ }
+ }
+ }
+ else if(KEYNAME("Name"))
+ {
+ phid->keyCount++;
+ }
+ else if(KEYNAME("Error"))
+ {
+ char *endptr;
+ int errcode = strtol(val, &endptr, 10);
+ char *errstr = endptr+1;
+ FIRE_ERROR_BUF(errcode, errstr);
+ }
+ else if(KEYNAME("Status"))
+ {
+ if(!strncmp(val, "Attached", sizeof("Attached")))
+ {
+ phid->keyCount++;
+ }
+ else if(!strncmp(val, "Detached", sizeof("Detached")))
+ {
+ CThread_mutex_lock(&phid->lock);
+ phid->keyCount = 0;
+ if(phid->specificDevice == PHIDGETOPEN_ANY_ATTACHED)
+ {
+ phid->specificDevice = PHIDGETOPEN_ANY;
+ }
+ CPhidget_clearStatusFlag(&phid->status, PHIDGET_ATTACHED_FLAG, NULL);
+ CPhidget_setStatusFlag(&phid->status, PHIDGET_DETACHING_FLAG, NULL);
+ CThread_mutex_unlock(&phid->lock);
+
+ if (phid->fptrDetach)
+ {
+ SET_RUNNING_EVENT(phid)
+ phid->fptrDetach((CPhidgetHandle)phid, phid->fptrDetachptr);
+ CLEAR_RUNNING_EVENT(phid)
+ }
+
+ //clear all variables
+ phid->fptrClear((CPhidgetHandle)phid);
+
+ //if mDNS & any server, disconnect
+#ifdef USE_ZEROCONF
+ CThread_mutex_lock(&phid->lock);
+ if(phid->networkInfo && !phid->networkInfo->requested_address && !phid->networkInfo->requested_serverID)
+ {
+ CThread DisconnectPhidgetThread;
+ CThread_mutex_unlock(&phid->lock);
+ CThread_mutex_lock(&zeroconfPhidgetsLock);
+ CList_removeFromList((CListHandle *)&zeroconfPhidgets, phid, CPhidget_areExtraEqual, TRUE, CPhidget_free);
+ CThread_mutex_unlock(&zeroconfPhidgetsLock);
+ CThread_create_detached(&DisconnectPhidgetThread, DisconnectPhidgetThreadFunction, phid);
+ }
+ CThread_mutex_unlock(&phid->lock);
+#endif
+
+ CPhidget_clearStatusFlag(&phid->status, PHIDGET_DETACHING_FLAG, NULL);
+
+ phid->deviceIDSpec = 0;
+ ZEROMEM(&phid->attr, sizeof(CPhidgetAttr));
+ if(phid->specificDevice != PHIDGETOPEN_LABEL)
+ ZEROMEM(phid->label, MAX_LABEL_STORAGE);
+ phid->deviceVersion = 0;
+ phid->initKeys = PUNK_INT;
+
+ }
+ else
+ {
+ throw_error_event(phid, "Bad Message type for Status set", EEPHIDGET_NETWORK);
+ }
+ }
+ else if(fptrSet[phid->deviceID] && setThing)
+ {
+ if(index)
+ ind = strtol(index, NULL, 10);
+
+ SET_RUNNING_EVENT(phid)
+ ret = fptrSet[phid->deviceID](phid, setThing, ind, val, reason);
+ CLEAR_RUNNING_EVENT(phid)
+ }
+
+ if((phid->initKeys != PUNK_INT)
+ && (phid->keyCount >= phid->initKeys)
+ && !CPhidget_statusFlagIsSet(phid->status, PHIDGET_ATTACHED_FLAG)
+ && CPhidget_statusFlagIsSet(phid->status, PHIDGET_OPENED_FLAG))
+ {
+ LOG(PHIDGET_LOG_VERBOSE, "Got all initkeys, run attach - %d/%d", phid->keyCount, phid->initKeys);
+
+ CPhidget_setStatusFlag(&phid->status, PHIDGET_ATTACHED_FLAG, &phid->lock);
+
+ SET_RUNNING_EVENT(phid)
+ if (phid->fptrAttach)
+ phid->fptrAttach(phid, phid->fptrAttachptr);
+ phid->fptrEvents((CPhidgetHandle)phid);
+ CLEAR_RUNNING_EVENT(phid)
+ }
+ else
+ LOG(PHIDGET_LOG_VERBOSE, "Accumulating initkeys for attach - %d/%d", phid->keyCount, phid->initKeys == PUNK_INT ? 0 : phid->initKeys);
+
+ //LOG(PHIDGET_LOG_DEBUG, "Message: %s(%s)=%s (%d of %d)", setThing, index, val, phid->keyCount, phid->initKeys);
+ }
+
+ free(setThing); setThing = NULL;
+ free(index); index = NULL;
+ free(serial); serial = NULL;
+ }
+
+ if(ret)
+ {
+ snprintf(errbuf, 1024, "Problem during Network set (Phidget): %s\n (Key:\"%s\", Val:\"%s\"", CPhidget_strerror(ret), key, val);
+ throw_error_event(phid, errbuf, EEPHIDGET_NETWORK);
+ }
+}
+
+void network_manager_event_handler(const char *key, const char *val, unsigned int vallen, pdict_reason_t reason, void *ptr)
+{
+ CPhidgetManagerHandle phidm = (CPhidgetManagerHandle)ptr;
+ regmatch_t keymatch[6], valmatch[6];
+ char *attachDetach = NULL;
+ char *deviceType = NULL;
+ char *serial = NULL;
+ char *version = NULL;
+ char *deviceIDSpec = NULL;
+ char *label = NULL;
+ char errbuf[1024];
+
+ int serialNumber;
+ CPhidgetHandle phid;
+
+ //BL:Changed to init Len before use
+ int len = 0;
+
+ int res, ret = EPHIDGET_OK;
+
+ int i;
+
+ if(!phidm) return;
+
+ if(!strncmp(val, "\001", 1) && (len == 1))
+ {
+ memset((char *)val,0,1);
+ }
+
+ if(reason!=PDR_ENTRY_REMOVING)
+ {
+ if ((res = regexec(&managerex, key, 3, keymatch, 0)) != 0) {
+ LOG(PHIDGET_LOG_DEBUG,"Error in network_manager_event_handler - key pattern not met");
+ return;
+ }
+ if ((res = regexec(&managervalex, val, 5, valmatch, 0)) != 0) {
+ LOG(PHIDGET_LOG_DEBUG,"Error in network_manager_event_handler - val pattern not met");
+ return;
+ }
+ getmatchsub(key, &deviceType, keymatch, 1);
+ getmatchsub(key, &serial, keymatch, 2);
+
+ getmatchsub(val, &attachDetach, valmatch, 1);
+ getmatchsub(val, &version, valmatch, 2);
+ getmatchsub(val, &deviceIDSpec, valmatch, 3);
+ getmatchsub(val, &label, valmatch, 4);
+
+ serialNumber = strtol(serial, NULL, 10);
+
+ if((CPhidget_create(&phid))) return;
+
+ phid->deviceID = phidget_type_to_id(deviceType);
+ phid->deviceType = Phid_DeviceName[phid->deviceID];
+ phid->serialNumber = serialNumber;
+ phid->deviceIDSpec = (unsigned short)strtol(deviceIDSpec, NULL, 10);
+ phid->deviceVersion = strtol(version, NULL, 10);
+ phid->specificDevice = PHIDGETOPEN_SERIAL; //so it actually compares the serial
+
+ for(i = 1;i<PHIDGET_DEVICE_COUNT;i++)
+ if(phid->deviceIDSpec == Phid_Device_Def[i].pdd_sdid) break;
+ phid->deviceDef = &Phid_Device_Def[i];
+ phid->attr = Phid_Device_Def[i].pdd_attr;
+
+ //so se can get address, etc. from devices.
+ phid->networkInfo = phidm->networkInfo;
+ CPhidget_setStatusFlag(&phid->status, PHIDGET_REMOTE_FLAG, &phid->lock);
+ CPhidget_setStatusFlag(&phid->status, PHIDGET_SERVER_CONNECTED_FLAG, &phid->lock);
+
+ if(label)
+ {
+ strncpy(phid->label, label, MAX_LABEL_STORAGE);
+ }
+
+ if(!strncmp(attachDetach, "Attached", sizeof("Attached")))
+ {
+ CPhidget_setStatusFlag(&phid->status, PHIDGET_ATTACHED_FLAG, &phid->lock);
+
+ CList_addToList((CListHandle *)&phidm->AttachedPhidgets, phid, CPhidget_areEqual);
+
+ if (phidm->fptrAttachChange && phidm->state == PHIDGETMANAGER_ACTIVE)
+ {
+ SET_RUNNING_EVENT(phidm)
+ phidm->fptrAttachChange((CPhidgetHandle)phid, phidm->fptrAttachChangeptr);
+ CLEAR_RUNNING_EVENT(phidm)
+ }
+ }
+
+ if(!strncmp(attachDetach, "Detached", sizeof("Detached")))
+ {
+ CPhidget_clearStatusFlag(&phid->status, PHIDGET_ATTACHED_FLAG, &phid->lock);
+ CPhidget_setStatusFlag(&phid->status, PHIDGET_DETACHING_FLAG, &phid->lock);
+ if(CList_findInList((CListHandle)phidm->AttachedPhidgets, phid, CPhidget_areEqual, NULL) == EPHIDGET_OK)
+ {
+ if (phidm->fptrDetachChange && phidm->state == PHIDGETMANAGER_ACTIVE)
+ {
+ SET_RUNNING_EVENT(phidm)
+ phidm->fptrDetachChange((CPhidgetHandle)phid, phidm->fptrDetachChangeptr);
+ CLEAR_RUNNING_EVENT(phid)
+ }
+
+ CList_removeFromList((CListHandle *)&phidm->AttachedPhidgets, phid, CPhidget_areEqual, PTRUE, CPhidget_free);
+ }
+ CPhidget_clearStatusFlag(&phid->status, PHIDGET_DETACHING_FLAG, &phid->lock);
+ CPhidget_free(phid); phid = NULL;
+ }
+
+ free(deviceType); deviceType = NULL;
+ free(label); label = NULL;
+ free(attachDetach); attachDetach = NULL;
+ free(serial); serial = NULL;
+ free(version); version = NULL;
+ free(deviceIDSpec); deviceIDSpec = NULL;
+ }
+
+ if(ret)
+ {
+ snprintf(errbuf, 1024, "Problem during Network set (Manager): %s\n (Key:\"%s\", Val:\"%s\"", CPhidget_strerror(ret), key, val);
+ throw_error_event((CPhidgetHandle)phidm, errbuf, EEPHIDGET_NETWORK);
+ }
+}
+
+void network_heartbeat_event_handler(const char *key, const char *val, unsigned int len, pdict_reason_t reason, void *ptr)
+{
+ CPhidgetSocketClientHandle server = (CPhidgetSocketClientHandle)ptr;
+ double duration = timeSince(&server->lastHeartbeatTime);
+
+ //Keeps a rolling average of the last 5 times
+ if(server->avgHeartbeatTimeCount > 5)
+ {
+ double avg = server->avgHeartbeatTime / server->avgHeartbeatTimeCount;
+ server->avgHeartbeatTime -= avg;
+ server->avgHeartbeatTimeCount--;
+ }
+ server->avgHeartbeatTime += duration;
+ server->avgHeartbeatTimeCount++;
+
+ server->heartbeatCount++;
+
+ setTimeNow(&server->lastHeartbeatTime);
+ server->waitingForHeartbeat = PFALSE;
+}
diff --git a/csocketevents.h b/csocketevents.h
new file mode 100644
index 0000000..d02b3d2
--- /dev/null
+++ b/csocketevents.h
@@ -0,0 +1,21 @@
+#ifndef __CSOCKETEVENTS
+#define __CSOCKETEVENTS
+
+#include "cphidget.h"
+#include "regex.h"
+#include "utils/utils.h"
+#include "cphidgetlist.h"
+#include "pdictclient.h"
+#ifdef USE_ZEROCONF
+#include "dns_sd.h"
+#endif
+
+extern regex_t phidgetsetex;
+extern regex_t managerex;
+extern regex_t managervalex;
+
+void network_phidget_event_handler(const char *key, const char *val, unsigned int len, pdict_reason_t reason, void *ptr);
+void network_manager_event_handler(const char *key, const char *val, unsigned int len, pdict_reason_t, void *ptr);
+void network_heartbeat_event_handler(const char *key, const char *val, unsigned int len, pdict_reason_t reason, void *ptr);
+
+#endif
diff --git a/csocketopen.c b/csocketopen.c
new file mode 100644
index 0000000..caaecfc
--- /dev/null
+++ b/csocketopen.c
@@ -0,0 +1,2641 @@
+#include "stdafx.h"
+#include "csocket.h"
+#include "csocketevents.h"
+#include "cphidgetlist.h"
+#include "cphidgetmanager.h"
+#include "cphidgetdictionary.h"
+#ifdef USE_ZEROCONF
+#include "zeroconf.h"
+#endif
+
+/*
+* Phidget WebService Protocol version history
+* 1.0 - Initial version
+*
+* 1.0.1
+* -first version to be enforced
+* -we changed around the device id numbers, so old webservice won't be able to talk to new
+*
+* 1.0.2
+* -Authorization is asynchronous, so we had to add Tags and now it's not compatible with old webservice
+* -Doesn't match the old version checking! So could be ugly for users, get an unexpected error rather then a version error
+* -Sends out all initial data, so it's just like opening locally
+* -supports interfacekit Raw sensor value
+* -supports labels on remoteIP managers
+*
+* 1.0.3
+* -supports servoType and setServoParameters for PhidgetServo and PhidgetAdvancedServo
+*
+* 1.0.4
+* -fixed RFID initialization - wasn't getting tag events if tag is on reader before open
+* -fixed RFID sometimes not attaching in Flash
+*
+* 1.0.5
+* -added dataRate for InterfaceKit
+*
+* 1.0.6
+* -added brightness for TextLCD
+* -support PhidgetSpatial
+* -support PhidgetIR
+* -1047 support (enable, index)
+*
+* 1.0.7
+* -1045 support
+* -1011 support
+* -1204 support
+* -explicitely respond to report messages on Windows, to force an immediate ACK, and circumvent Windows delayed ACKs
+*
+* 1.0.8
+* -stopped sending explicit ACK - caused trouble on slower links
+* -support for 1065, 1002, 1040, 1046, 1056
+* -support for error events
+*
+* 1.0.9
+* -support for openLabelRemote and openLabelRemoteIP
+*/
+const char *ws_protocol_ver = "1.0.9";
+
+/*void DNSServiceResolve_CallBack(
+ DNSServiceRef sdRef,
+ DNSServiceFlags flags,
+ uint32_t interfaceIndex,
+ DNSServiceErrorType errorCode,
+ const char *fullname,
+ const char *hosttarget,
+ uint16_t port,
+ uint16_t txtLen,
+ const unsigned char *txtRecord,
+ void *context);*/
+
+typedef struct _CServerInfo
+{
+ CPhidgetSocketClientHandle server;
+ CPhidgetListHandle phidgets;
+ CPhidgetManagerListHandle managers;
+ CPhidgetDictionaryListHandle dictionaries;
+} CServerInfo, *CServerInfoHandle;
+
+typedef struct _CServerList
+{
+ struct _CServerList *next;
+ CServerInfoHandle serverInfo;
+} CServerList, *CServerListHandle;
+
+CThread_func_return_t CentralRemoteThreadFunction(CThread_func_arg_t arg);
+static CThread CentralRemoteThread;
+CThread_mutex_t CentralRemoteThreadLock;
+int CentralRemoteThreadLockInitialized = PFALSE;
+
+static int connectionID = 0;
+
+// list of connected servers
+CServerListHandle servers = NULL;
+/* Protects servers */
+int serverLockInitialized = PFALSE;
+CThread_mutex_t serverLock;
+CThread_mutex_t serverLockLock;
+
+CPhidgetRemoteListHandle zeroconfServers = NULL;
+CPhidgetListHandle zeroconfPhidgets = NULL;
+CPhidgetSBCListHandle zeroconfSBCs = NULL;
+/* Protects zeroconf lists */
+int zeroconfListLockInitialized = PFALSE;
+CThread_mutex_t zeroconfServersLock;
+CThread_mutex_t zeroconfPhidgetsLock;
+CThread_mutex_t zeroconfSBCsLock;
+CThread_mutex_t zeroconfInitLock;
+
+//Lists of objects that we have called openRemote or openRemoteIP on
+//These may or may not actually be attached or connected
+CPhidgetListHandle activeRemotePhidgets = NULL;
+CPhidgetManagerListHandle activeRemoteManagers = NULL;
+CPhidgetSBCManagerListHandle activeSBCManagers = NULL;
+CPhidgetDictionaryListHandle activeRemoteDictionaries = NULL;
+/* Protects the lists */
+int activeRemoteLocksInitialized = PFALSE;
+CThread_mutex_t activeRemotePhidgetsLock;
+CThread_mutex_t activeRemoteManagersLock;
+CThread_mutex_t activeSBCManagersLock;
+CThread_mutex_t activeRemoteDictionariesLock;
+
+int NetworkInitialized = PFALSE;
+
+int inErrorEvent = PFALSE;
+
+int closeServer(CServerInfoHandle server, unsigned char force);
+
+
+
+#ifdef _WINDOWS
+int start_WSA_server()
+{
+ WORD wVersionRequested;
+ WSADATA wsaData;
+ int err;
+
+ wVersionRequested = MAKEWORD( 2, 2 );
+
+ LOG(PHIDGET_LOG_INFO, "Starting WSA...");
+
+ err = WSAStartup( wVersionRequested, &wsaData );
+ if ( err != 0 ) {
+ LOG(PHIDGET_LOG_ERROR,"Cannot start WSA");
+ return EPHIDGET_NETWORK;
+ }
+ LOG(PHIDGET_LOG_INFO, "Started WSA Successfully");
+ return EPHIDGET_OK;
+}
+#endif
+
+int CServerInfo_areEqual(void *arg1, void *arg2)
+{
+ CServerInfoHandle server1 = (CServerInfoHandle)arg1;
+ CServerInfoHandle server2 = (CServerInfoHandle)arg2;
+
+ LOG(PHIDGET_LOG_VERBOSE, "In CServerInfo_areEqual, comparing: 0x%x and 0x%x", arg1, arg2);
+
+ if(!server1 || !server2 || !server1->server || !server2->server)
+ return PFALSE;
+
+ return CPhidgetSocketClient_areEqual(server1->server, server2->server);
+}
+
+void CServerInfo_free(void *arg)
+{
+ CServerInfoHandle server = (CServerInfoHandle)arg;
+ LOG(PHIDGET_LOG_VERBOSE, "Freeing ServerInfo: 0x%x", arg);
+
+ if(!server)
+ return;
+ if(server->server)
+ CPhidgetSocketClient_free(server->server); server->server = NULL;
+ //CList_emptyList((CListHandle *)&server->listen_ids, PFALSE, NULL);
+
+ //empty the lists but don't free their objects
+ CList_emptyList((CListHandle *)&server->phidgets, PFALSE, NULL);
+ CList_emptyList((CListHandle *)&server->managers, PFALSE, NULL);
+ CList_emptyList((CListHandle *)&server->dictionaries, PFALSE, NULL);
+
+ free(server); server = NULL;
+ return;
+}
+
+typedef enum
+{
+ PHIDGET,
+ MANAGER,
+ DICTIONARY
+} ListElementType;
+
+static int addToServerInfoList(CServerInfoHandle newServerInfo, void *element, ListElementType type)
+{
+ switch(type)
+ {
+ case PHIDGET:
+ LOG(PHIDGET_LOG_VERBOSE, "Adding Phidget (0x%x) to server (0x%x)", element, newServerInfo);
+ return CList_addToList((CListHandle *)&newServerInfo->phidgets, element, CPhidgetHandle_areEqual);
+ case MANAGER:
+ LOG(PHIDGET_LOG_VERBOSE, "Adding Manager (0x%x) to server (0x%x)", element, newServerInfo);
+ return CList_addToList((CListHandle *)&newServerInfo->managers, element, CPhidgetManager_areEqual);
+ case DICTIONARY:
+ LOG(PHIDGET_LOG_VERBOSE, "Adding Dictionary (0x%x) to server (0x%x)", element, newServerInfo);
+ return CList_addToList((CListHandle *)&newServerInfo->dictionaries, element, CPhidgetDictionary_areEqual);
+ }
+ return EPHIDGET_UNEXPECTED;
+}
+
+static int removeFromServerInfoList(CServerInfoHandle newServerInfo, void *element, ListElementType type)
+{
+ switch(type)
+ {
+ case PHIDGET:
+ LOG(PHIDGET_LOG_VERBOSE, "Removing Phidget (0x%x) from server (0x%x)", element, newServerInfo);
+ return CList_removeFromList((CListHandle *)&newServerInfo->phidgets, element, CPhidgetHandle_areEqual, PFALSE, NULL);
+ case MANAGER:
+ LOG(PHIDGET_LOG_VERBOSE, "Removing Manager (0x%x) from server (0x%x)", element, newServerInfo);
+ return CList_removeFromList((CListHandle *)&newServerInfo->managers, element, CPhidgetManager_areEqual, PFALSE, NULL);
+ case DICTIONARY:
+ LOG(PHIDGET_LOG_VERBOSE, "Removing Dictionary (0x%x) from server (0x%x)", element, newServerInfo);
+ return CList_removeFromList((CListHandle *)&newServerInfo->dictionaries, element, CPhidgetDictionary_areEqual, PFALSE, NULL);
+ }
+ return EPHIDGET_UNEXPECTED;
+}
+
+int CCONV CPhidgetRemote_create(CPhidgetRemoteHandle *arg)
+{
+ CPhidgetRemoteHandle remote;
+
+ LOG(PHIDGET_LOG_VERBOSE, "Creating a new PhidgetRemote...");
+
+ if(!(remote = malloc(sizeof(CPhidgetRemote))))
+ return EPHIDGET_NOMEMORY;
+ ZEROMEM(remote, sizeof(CPhidgetRemote));
+
+ CThread_mutex_init(&remote->zeroconf_ref_lock);
+ remote->cancelSocket = INVALID_SOCKET;
+
+ remote->uniqueConnectionID = connectionID++;
+
+ *arg = remote;
+ LOG(PHIDGET_LOG_VERBOSE, "Created new PhidgetRemote: 0x%x",remote);
+
+ return EPHIDGET_OK;
+}
+
+void CCONV CPhidgetRemote_free(void *arg)
+{
+ CPhidgetRemoteHandle remote = (CPhidgetRemoteHandle)arg;
+
+ LOG(PHIDGET_LOG_VERBOSE, "Freeing PhidgetRemote: 0x%x",arg);
+
+ if(!remote) return;
+ if(remote->requested_port) free(remote->requested_port); remote->requested_port=NULL;
+ if(remote->requested_address) free(remote->requested_address); remote->requested_address=NULL;
+ if(remote->requested_serverID) free(remote->requested_serverID); remote->requested_serverID=NULL;
+ if(remote->password) free(remote->password); remote->password=NULL;
+
+ if(remote->zeroconf_name) free(remote->zeroconf_name); remote->zeroconf_name=NULL;
+ if(remote->zeroconf_domain) free(remote->zeroconf_domain); remote->zeroconf_domain=NULL;
+ if(remote->zeroconf_type) free(remote->zeroconf_type); remote->zeroconf_type=NULL;
+ if(remote->zeroconf_host) free(remote->zeroconf_host); remote->zeroconf_host=NULL;
+ if(remote->zeroconf_port) free(remote->zeroconf_port); remote->zeroconf_port=NULL;
+ if(remote->zeroconf_server_id) free(remote->zeroconf_server_id); remote->zeroconf_server_id=NULL;
+
+ CPhidgetSocketClient_free(remote->server);
+
+ CThread_mutex_destroy(&remote->zeroconf_ref_lock);
+
+ free(remote);
+
+ return;
+}
+
+int CCONV CPhidgetRemote_areEqual(void *arg1, void *arg2)
+{
+ CPhidgetRemoteHandle remote1 = (CPhidgetRemoteHandle)arg1;
+ CPhidgetRemoteHandle remote2 = (CPhidgetRemoteHandle)arg2;
+
+ LOG(PHIDGET_LOG_VERBOSE, "In CPhidgetRemote_areEqual, comparing: 0x%x and 0x%x", arg1, arg2);
+
+ if(!remote1 || !remote2)
+ return PFALSE;
+
+ if(remote1->zeroconf_name != NULL || remote2->zeroconf_name != NULL)
+ if((strcmp(remote1->zeroconf_name,remote2->zeroconf_name)))
+ return 0;
+
+ if(remote1->zeroconf_domain != NULL || remote2->zeroconf_domain != NULL)
+ if((strcmp(remote1->zeroconf_domain,remote2->zeroconf_domain)))
+ return 0;
+
+ if(remote1->zeroconf_type != NULL || remote2->zeroconf_type != NULL)
+ if((strcmp(remote1->zeroconf_type,remote2->zeroconf_type)))
+ return 0;
+
+ if(remote1->requested_port != NULL || remote2->requested_port != NULL)
+ if((strcmp(remote1->requested_port,remote2->requested_port)))
+ return 0;
+
+ if(remote1->requested_address != NULL || remote2->requested_address != NULL)
+ if((strcmp(remote1->requested_address,remote2->requested_address)))
+ return 0;
+
+ if(remote1->requested_serverID != NULL || remote2->requested_serverID != NULL)
+ if((strcmp(remote1->requested_serverID,remote2->requested_serverID)))
+ return 0;
+
+ return 1;
+}
+
+int CCONV CPhidgetSocketClient_create(CPhidgetSocketClientHandle *arg)
+{
+ CPhidgetSocketClientHandle socket_client;
+
+ LOG(PHIDGET_LOG_VERBOSE, "Creating a new PhidgetSocketClient...");
+
+ if(!(socket_client = malloc(sizeof(CPhidgetSocketClient))))
+ return EPHIDGET_NOMEMORY;
+ ZEROMEM(socket_client, sizeof(CPhidgetSocketClient));
+
+ CThread_mutex_init(&socket_client->lock);
+ CThread_mutex_init(&socket_client->pdc_lock);
+
+ CPhidget_clearStatusFlag(&socket_client->status, PHIDGETSOCKET_CONNECTED_FLAG, &socket_client->lock);
+
+ *arg = socket_client;
+ LOG(PHIDGET_LOG_VERBOSE, "Created new PhidgetSocketClient: 0x%x",socket_client);
+
+ return EPHIDGET_OK;
+}
+
+void CCONV CPhidgetSocketClient_free(void *arg)
+{
+ CPhidgetSocketClientHandle socket_client = (CPhidgetSocketClientHandle)arg;
+ LOG(PHIDGET_LOG_VERBOSE, "Freeing PhidgetSocketClient: 0x%x",arg);
+
+ if(!socket_client) return;
+ if(socket_client->port) free(socket_client->port); socket_client->port=NULL;
+ if(socket_client->address) free(socket_client->address); socket_client->address=NULL;
+ //if(socket_client->serverID) free(socket_client->serverID); socket_client->serverID=NULL;
+ if(socket_client->pdcs) free(socket_client->pdcs); socket_client->pdcs=NULL;
+
+ CThread_mutex_destroy(&socket_client->lock);
+ CThread_mutex_destroy(&socket_client->pdc_lock);
+
+ free(socket_client);
+
+ return;
+}
+
+int CCONV CPhidgetSocketClient_areEqual(void *arg1, void *arg2)
+{
+ CPhidgetSocketClientHandle socket1 = (CPhidgetSocketClientHandle)arg1;
+ CPhidgetSocketClientHandle socket2 = (CPhidgetSocketClientHandle)arg2;
+ LOG(PHIDGET_LOG_VERBOSE, "In CPhidgetSocketClient_areEqual, comparing: 0x%x and 0x%x", arg1, arg2);
+
+ if(!socket1 || !socket2 || !socket1->address || !socket2->address || !socket1->port || !socket2->port)
+ return PFALSE;
+
+ if(!(strcmp(socket1->address,socket2->address))
+ && !(strcmp(socket1->port, socket2->port)))
+ return 1;
+
+ return 0;
+}
+
+void internal_async_network_error_handler(const char *error, void *ptr)
+{
+ CPhidgetHandle phid = (CPhidgetHandle)ptr;
+ if(phid && phid->fptrError)
+ {
+ LOG(PHIDGET_LOG_VERBOSE,"Got an async network error: %s", error);
+ phid->fptrError(phid, phid->fptrErrorptr, EEPHIDGET_NETWORK, error);
+ }
+ else
+ {
+ LOG(PHIDGET_LOG_WARNING,"Got an async network error: %s\n\tTip: Set up an error handler to catch this properly.", error);
+ }
+}
+
+static int initialize_locks()
+{
+ LOG(PHIDGET_LOG_VERBOSE, "Initializing network locks...");
+ if(!CentralRemoteThreadLockInitialized)
+ {
+ CThread_mutex_init(&CentralRemoteThreadLock);
+ CentralRemoteThreadLockInitialized = PTRUE;
+ }
+ if(!serverLockInitialized)
+ {
+ CThread_mutex_init(&serverLock);
+ CThread_mutex_init(&serverLockLock);
+ serverLockInitialized = PTRUE;
+ }
+ if(!zeroconfListLockInitialized)
+ {
+ CThread_mutex_init(&zeroconfServersLock);
+ CThread_mutex_init(&zeroconfPhidgetsLock);
+ CThread_mutex_init(&zeroconfSBCsLock);
+ CThread_mutex_init(&zeroconfInitLock);
+ zeroconfListLockInitialized = PTRUE;
+ }
+ if(!activeRemoteLocksInitialized)
+ {
+ CThread_mutex_init(&activeRemotePhidgetsLock);
+ CThread_mutex_init(&activeRemoteManagersLock);
+ CThread_mutex_init(&activeRemoteDictionariesLock);
+ CThread_mutex_init(&activeSBCManagersLock);
+ activeRemoteLocksInitialized = PTRUE;
+ }
+ return EPHIDGET_OK;
+}
+
+int InitializeNetworking()
+{
+ int res;
+ const char *setpattern = "^/PSK/([a-zA-Z_0-9]*)/([a-zA-Z_0-9/.\\\\-]*)/([0-9]*)/([a-zA-Z_0-9]*)/?([a-zA-Z_0-9]*)/?([a-zA-Z_0-9]*)$";
+ const char *managerpattern = "^/PSK/List/([a-zA-Z_0-9]*)/([0-9]*)$";
+ const char *managervalpattern = "^([a-zA-Z]*) Version=([0-9]*) ID=([0-9]*) Label=(.*)$";
+
+ LOG(PHIDGET_LOG_VERBOSE, "Initializing Networking...");
+
+#ifdef _WINDOWS
+ if (start_WSA_server())
+ {
+ LOG(PHIDGET_LOG_WARNING,"Cannot start Windows Sockets");
+ return EPHIDGET_NETWORK;
+ }
+#endif
+
+ if (!pdc_init()) {
+ LOG(PHIDGET_LOG_ERROR, "Error running pdc_init, networking couldn't start.");
+ return EPHIDGET_UNEXPECTED;
+ }
+
+ if ((res = regcomp(&phidgetsetex, setpattern, REG_EXTENDED)) != 0) {
+ LOG_STDERR(PHIDGET_LOG_CRITICAL,"set command pattern compilation error %d", res);
+ abort();
+ }
+ if ((res = regcomp(&managerex, managerpattern, REG_EXTENDED)) != 0) {
+ LOG_STDERR(PHIDGET_LOG_CRITICAL,"set command pattern compilation error %d", res);
+ abort();
+ }
+ if ((res = regcomp(&managervalex, managervalpattern, REG_EXTENDED)) != 0) {
+ LOG_STDERR(PHIDGET_LOG_CRITICAL,"set command pattern compilation error %d", res);
+ abort();
+ }
+
+ NetworkInitialized = PTRUE;
+ LOG(PHIDGET_LOG_VERBOSE, "Networking initialized");
+
+ return EPHIDGET_OK;
+}
+
+void cleanup_after_socket(void *ptr)
+{
+ CPhidgetSocketClientHandle serverInfo = ptr;
+ CServerList *travServers;
+ CServerInfoHandle foundServer = NULL;
+ CPhidgetListHandle travPhidgets;
+ CPhidgetDictionaryListHandle travDicts;
+ CPhidgetManagerListHandle travManagers;
+
+ CPhidgetListHandle detachEvents = NULL;
+ CPhidgetListHandle disconnectEvents = NULL;
+
+ LOG(PHIDGET_LOG_VERBOSE, "Cleaning up after socket: 0x%x",ptr);
+
+ //wait for the threads to be done
+ while(serverInfo->auth_thread.thread_status == TRUE)
+ {
+ SLEEP(10);
+ }
+ while(serverInfo->auth_error_thread.thread_status == TRUE)
+ {
+ SLEEP(10);
+ }
+
+ /* For each Phidget associated with this server, send a detach event, and a disconnect event */
+ // We then get rid of the socket object everywhere
+ // If this is called because we already closed all the connections to this socket, no events will be raised because
+ // all the handles are already nulled...
+ CThread_mutex_lock(&serverLock);
+
+ for(travServers = servers; travServers; travServers = travServers->next)
+ {
+ if(travServers->serverInfo->server->socket == serverInfo->socket)
+ {
+ foundServer = travServers->serverInfo;
+ CPhidget_clearStatusFlag(&foundServer->server->status, PHIDGETSOCKET_CONNECTED_FLAG, &foundServer->server->lock);
+ for(travPhidgets = foundServer->phidgets; travPhidgets; travPhidgets = travPhidgets->next)
+ {
+ if(CPhidget_statusFlagIsSet(travPhidgets->phid->status, PHIDGET_ATTACHED_FLAG))
+ {
+ CPhidget_clearStatusFlag(&travPhidgets->phid->status, PHIDGET_ATTACHED_FLAG, &travPhidgets->phid->lock);
+ CPhidget_setStatusFlag(&travPhidgets->phid->status, PHIDGET_DETACHING_FLAG, &travPhidgets->phid->lock);
+ if(travPhidgets->phid->fptrDetach)
+ CList_addToList((CListHandle *)&detachEvents, travPhidgets->phid, CPhidget_areEqual);
+ }
+
+ CPhidget_clearStatusFlag(&travPhidgets->phid->status, PHIDGET_SERVER_CONNECTED_FLAG, &travPhidgets->phid->lock);
+ if(travPhidgets->phid->fptrServerDisconnect)
+ CList_addToList((CListHandle *)&disconnectEvents, travPhidgets->phid, CPhidgetHandle_areEqual);
+ }
+ for(travDicts = foundServer->dictionaries; travDicts; travDicts = travDicts->next)
+ {
+ CPhidget_clearStatusFlag(&travDicts->dict->status, PHIDGET_ATTACHED_FLAG, &travDicts->dict->lock);
+
+ CPhidget_clearStatusFlag(&travDicts->dict->status, PHIDGET_SERVER_CONNECTED_FLAG, &travDicts->dict->lock);
+ if(travDicts->dict->fptrServerDisconnect)
+ CList_addToList((CListHandle *)&disconnectEvents, travDicts->dict, CPhidgetHandle_areEqual);
+ }
+ for(travManagers = foundServer->managers; travManagers; travManagers = travManagers->next)
+ {
+ CPhidget_clearStatusFlag(&travManagers->phidm->status, PHIDGET_ATTACHED_FLAG, &travManagers->phidm->lock);
+
+ CPhidget_clearStatusFlag(&travManagers->phidm->status, PHIDGET_SERVER_CONNECTED_FLAG, &travManagers->phidm->lock);
+ if(travManagers->phidm->fptrServerDisconnect)
+ CList_addToList((CListHandle *)&disconnectEvents, travManagers->phidm, CPhidgetHandle_areEqual);
+ }
+ break;
+ }
+ }
+
+ for(travPhidgets = disconnectEvents; travPhidgets; travPhidgets = travPhidgets->next)
+ {
+ travPhidgets->phid->fptrServerDisconnect((CPhidgetHandle)travPhidgets->phid, travPhidgets->phid->fptrServerDisconnectptr);
+ //internal_async_network_error_handler("The Network Connection has been Closed", travPhidgets->phid);
+ }
+ for(travPhidgets = detachEvents; travPhidgets; travPhidgets = travPhidgets->next)
+ {
+ travPhidgets->phid->fptrDetach((CPhidgetHandle)travPhidgets->phid, travPhidgets->phid->fptrDetachptr);
+ CPhidget_clearStatusFlag(&travPhidgets->phid->status, PHIDGET_DETACHING_FLAG, &travPhidgets->phid->lock);
+ }
+
+ CList_emptyList((CListHandle *)&detachEvents, FALSE, NULL);
+ CList_emptyList((CListHandle *)&disconnectEvents, FALSE, NULL);
+
+ if(foundServer)
+ {
+ //need to null all servers in list
+ //do it herer so detach/disconnect handlers can call getAddress, etc.
+ for(travPhidgets = foundServer->phidgets; travPhidgets; travPhidgets = travPhidgets->next)
+ {
+ travPhidgets->phid->networkInfo->server = NULL;
+ }
+ for(travDicts = foundServer->dictionaries; travDicts; travDicts = travDicts->next)
+ {
+ travDicts->dict->networkInfo->server = NULL;
+ }
+ for(travManagers = foundServer->managers; travManagers; travManagers = travManagers->next)
+ {
+ travManagers->phidm->networkInfo->server = NULL;
+ }
+
+ //then remove from server list
+ CList_removeFromList((CListHandle *)&servers, foundServer, CServerInfo_areEqual, PTRUE, CServerInfo_free);
+ }
+ CThread_mutex_unlock(&serverLock);
+}
+
+int setupHeartbeat(CPhidgetSocketClientHandle server, pdc_listen_id_t *id)
+{
+ char errdesc[1024];
+ char listenKey[1024];
+
+ struct sockaddr_storage name;
+ char addr[200], *a;
+ socklen_t namelen = sizeof(name);
+ int port, e;
+
+ char key[1024], val[1024];
+
+ TESTPTR(server)
+ LOG(PHIDGET_LOG_VERBOSE, "Setting up heartbeat: 0x%x...",server);
+
+ if(getsockname(server->socket, (struct sockaddr *)&name, &namelen) != 0)
+ {
+ LOG(PHIDGET_LOG_ERROR,"getsockname: %s", strerror(errno));
+ return EPHIDGET_UNEXPECTED;
+ }
+ if((e = getnameinfo((struct sockaddr *)&name, namelen, addr, sizeof(addr), NULL, 0, NI_NUMERICHOST)) != 0)
+ {
+ LOG(PHIDGET_LOG_ERROR,"getnameinfo: %s", gai_strerror(e));
+ return EPHIDGET_UNEXPECTED;
+ }
+ port = (int)((struct sockaddr_in *)&name)->sin_port;
+ escape(addr, strlen(addr), &a);
+
+ LOG(PHIDGET_LOG_VERBOSE, "Heartbeat addr/port: %s/%d",addr,port);
+
+ //listen for heartbeat events
+ snprintf(listenKey, sizeof(listenKey), "/PCK/Heartbeat/%s/%d", a, port);
+ CThread_mutex_lock(&server->pdc_lock);
+ if (!(*id = pdc_listen(server->pdcs, listenKey, network_heartbeat_event_handler, server, errdesc, sizeof (errdesc))))
+ {
+ LOG(PHIDGET_LOG_ERROR,"pdc_listen: %s", errdesc);
+ CThread_mutex_unlock(&server->pdc_lock);
+ free(a);
+ return EPHIDGET_UNEXPECTED;
+ }
+ CThread_mutex_unlock(&server->pdc_lock);
+
+ snprintf(key, sizeof(key), "/PCK/Heartbeat/%s/%d", a, port);
+ free(a);
+ snprintf(val, sizeof(val), "%d", server->heartbeatCount);
+ setTimeNow(&server->lastHeartbeatTime);
+ server->waitingForHeartbeat = PTRUE;
+ pdc_async_set(server->pdcs, key, val, (int)strlen(val), PTRUE, NULL, NULL);
+
+ return EPHIDGET_OK;
+}
+
+int setupKeysAndListeners_phidget(CPhidgetHandle phid, pdc_listen_id_t *id)
+{
+ char errdesc[1024];
+ char listenKey[1024];
+
+ struct sockaddr_storage name;
+ char addr[200], *a;
+ socklen_t namelen = sizeof(name);
+ int port;
+ int e;
+
+ char key[1024], val[1024];
+
+ LOG(PHIDGET_LOG_VERBOSE, "Setting up keys and listeners for 0x%x",phid);
+
+ TESTPTR(phid)
+ TESTPTR(phid->networkInfo)
+ TESTPTR(phid->networkInfo->server)
+
+ //listen for everything to do with this specific phidget
+ if(phid->specificDevice == PHIDGETOPEN_SERIAL)
+ {
+ snprintf(listenKey, sizeof(listenKey), "^/PSK/%s/[a-zA-Z_0-9/.\\\\-]*/%d/", Phid_DeviceName[phid->deviceID], phid->serialNumber);
+ }
+ else if(phid->specificDevice == PHIDGETOPEN_LABEL)
+ {
+ char *l;
+ escape2(phid->label, strlen(phid->label), &l, PTRUE); //make sure the backslashes are escaped because this is a regex
+ snprintf(listenKey, sizeof(listenKey), "^/PSK/%s/%s/", Phid_DeviceName[phid->deviceID], l);
+ //LOG(PHIDGET_LOG_DEBUG, "Listening for: \"%s\"",listenKey);
+ }
+ else
+ {
+ snprintf(listenKey, sizeof(listenKey), "^/PSK/%s/", Phid_DeviceName[phid->deviceID]);
+ }
+
+ CThread_mutex_lock(&phid->networkInfo->server->pdc_lock);
+ if (!(*id = pdc_listen(phid->networkInfo->server->pdcs, listenKey, network_phidget_event_handler, phid, errdesc, sizeof (errdesc))))
+ {
+ LOG(PHIDGET_LOG_ERROR,"pdc_listen: %s", errdesc);
+ CThread_mutex_unlock(&phid->networkInfo->server->pdc_lock);
+ return EPHIDGET_UNEXPECTED;
+ }
+ CThread_mutex_unlock(&phid->networkInfo->server->pdc_lock);
+ //Open the remote device
+ //get socket info
+
+ if(getsockname(phid->networkInfo->server->socket, (struct sockaddr *)&name, &namelen) != 0)
+ {
+ LOG(PHIDGET_LOG_ERROR,"getsockname: %s", strerror(errno));
+ return EPHIDGET_UNEXPECTED;
+ }
+ if((e = getnameinfo((struct sockaddr *)&name, namelen, addr, sizeof(addr), NULL, 0, NI_NUMERICHOST)) != 0)
+ {
+ LOG(PHIDGET_LOG_ERROR,"getnameinfo: %s", gai_strerror(e));
+ return EPHIDGET_UNEXPECTED;
+ }
+ port = (int)((struct sockaddr_in *)&name)->sin_port;
+ escape(addr, strlen(addr), &a);
+
+ if(phid->specificDevice == PHIDGETOPEN_SERIAL)
+ {
+ snprintf(key, sizeof(key), "/PCK/Client/%s/%d%05d/%s/%d", a, phid->networkInfo->uniqueConnectionID, port,
+ Phid_DeviceName[phid->deviceID], phid->serialNumber);
+ }
+ else if(phid->specificDevice == PHIDGETOPEN_LABEL)
+ {
+ char *l;
+ escape(phid->label, strlen(phid->label), &l);
+ snprintf(key, sizeof(key), "/PCK/Client/%s/%d%05d/%s/-1/%s", a, phid->networkInfo->uniqueConnectionID, port,
+ Phid_DeviceName[phid->deviceID], l);
+ free(l);
+ }
+ else
+ {
+ snprintf(key, sizeof(key), "/PCK/Client/%s/%d%05d/%s", a, phid->networkInfo->uniqueConnectionID, port,
+ Phid_DeviceName[phid->deviceID]);
+ }
+ free(a);
+ snprintf(val, sizeof(val), "Open");
+ pdc_async_set(phid->networkInfo->server->pdcs, key, val, (int)strlen(val), PTRUE, internal_async_network_error_handler, phid);
+
+ return EPHIDGET_OK;
+}
+
+int setupKeysAndListeners_manager(CPhidgetManagerHandle phidm, pdc_listen_id_t *id)
+{
+ char errdesc[1024];
+ char listenKey[1024];
+
+ TESTPTR(phidm)
+ TESTPTR(phidm->networkInfo)
+ TESTPTR(phidm->networkInfo->server)
+
+ //listen for everything to do with the PhidgetManager
+ snprintf(listenKey, sizeof(listenKey), "^/PSK/List/");
+
+ CThread_mutex_lock(&phidm->networkInfo->server->pdc_lock);
+ if (!(*id = pdc_listen(phidm->networkInfo->server->pdcs, listenKey, network_manager_event_handler, phidm, errdesc, sizeof (errdesc))))
+ {
+ LOG(PHIDGET_LOG_ERROR,"pdc_listen: %s", errdesc);
+ CThread_mutex_unlock(&phidm->networkInfo->server->pdc_lock);
+ return EPHIDGET_UNEXPECTED;
+ }
+ CThread_mutex_unlock(&phidm->networkInfo->server->pdc_lock);
+
+ return EPHIDGET_OK;
+}
+
+typedef struct _AuthHandlerThreadData
+{
+ void *ptr;
+ void (*error)(const char *errdesc, void *arg);
+} AuthHandlerThreadData, *AuthHandlerThreadDataHandle;
+
+//An auth succeeded so now we mark this as a connected server, send out connect events, etc.
+CThread_func_return_t async_authorization_handler_thread(CThread_func_arg_t lpdwParam)
+{
+ AuthHandlerThreadDataHandle data = (AuthHandlerThreadDataHandle)lpdwParam;
+
+ CPhidgetListHandle travPhidgets;
+ CPhidgetDictionaryListHandle travDicts;
+ CPhidgetManagerListHandle travManagers;
+
+ CPhidgetListHandle connectEvents = NULL;
+ CPhidgetListHandle phidErrorEvents = NULL;
+ CPhidgetManagerListHandle managerErrorEvents = NULL;
+
+ char errdesc[1024];
+ CServerInfoHandle newServerInfo = (CServerInfoHandle)data->ptr;
+
+ //make sure that we can cancel this thread
+/*#ifndef _WINDOWS
+ int temp;
+ pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &temp);
+ pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &temp);
+#endif*/
+
+ //CThread_mutex_lock(&serverLockLock);
+ CThread_mutex_lock(&serverLock);
+
+ //close was called, pdcs isn't valid any longer
+ if(!newServerInfo->server->pdcs)
+ {
+ newServerInfo->server->auth_thread.thread_status = FALSE;
+
+ CThread_mutex_unlock(&serverLock);
+ return (CThread_func_return_t)0;
+ }
+
+ CThread_mutex_lock(&newServerInfo->server->pdc_lock);
+
+ //pdc_async_enable_periodic_reports(newServerInfo->server->pdcs, 10, NULL, NULL);
+ if(!pdc_enable_periodic_reports(newServerInfo->server->pdcs, 10, errdesc, sizeof(errdesc)))
+ {
+ LOG(PHIDGET_LOG_ERROR,"pdc_enable_periodic_reports: %s", errdesc);
+
+ //this will call back to async_authorization_error_handler - the whole server connection is now bad
+ if(data->error)
+ {
+ data->error(errdesc, data->ptr);
+ }
+
+ free(data);
+ CThread_mutex_unlock(&newServerInfo->server->pdc_lock);
+
+ newServerInfo->server->auth_thread.thread_status = FALSE;
+
+ CThread_mutex_unlock(&serverLock);
+ //CThread_mutex_unlock(&serverLockLock);
+
+ return (CThread_func_return_t)0;
+ }
+
+ free(data);
+ CThread_mutex_unlock(&newServerInfo->server->pdc_lock);
+
+ //set connected
+ CPhidget_setStatusFlag(&newServerInfo->server->status, PHIDGETSOCKET_CONNECTED_FLAG, &newServerInfo->server->lock);
+ CPhidget_clearStatusFlag(&newServerInfo->server->status, PHIDGETSOCKET_CONNECTING_FLAG, &newServerInfo->server->lock);
+
+ //Setup the heartbeat listener
+ setupHeartbeat(newServerInfo->server, &newServerInfo->server->heartbeat_listen_id);
+
+ //now run through all phids, managers, dicts in the list and connect them
+ for(travPhidgets = newServerInfo->phidgets; travPhidgets; travPhidgets = travPhidgets->next)
+ {
+ CPhidget_setStatusFlag(&travPhidgets->phid->status, PHIDGET_SERVER_CONNECTED_FLAG, &travPhidgets->phid->lock);
+ if(setupKeysAndListeners_phidget(travPhidgets->phid, &travPhidgets->phid->networkInfo->listen_id))
+ {
+ if(travPhidgets->phid->fptrError)
+ CList_addToList((CListHandle *)&phidErrorEvents, travPhidgets->phid, CPhidgetHandle_areEqual);
+ CPhidget_clearStatusFlag(&travPhidgets->phid->status, PHIDGET_SERVER_CONNECTED_FLAG, &travPhidgets->phid->lock);
+ //we have to remove this phid from the server list,
+ //and remove it's reference to the server, so that another connection attempt will be made.
+ travPhidgets->phid->networkInfo->server = NULL;
+ }
+ else
+ {
+ if(travPhidgets->phid->fptrServerConnect)
+ CList_addToList((CListHandle *)&connectEvents, travPhidgets->phid, CPhidgetHandle_areEqual);
+ }
+ }
+ for(travDicts = newServerInfo->dictionaries; travDicts; travDicts = travDicts->next)
+ {
+ CPhidget_setStatusFlag(&travDicts->dict->status, PHIDGET_SERVER_CONNECTED_FLAG, &travDicts->dict->lock);
+ CPhidget_setStatusFlag(&travDicts->dict->status, PHIDGET_ATTACHED_FLAG, &travDicts->dict->lock);
+ if(travDicts->dict->fptrServerConnect)
+ CList_addToList((CListHandle *)&connectEvents, travDicts->dict, CPhidgetHandle_areEqual);
+ }
+ for(travManagers = newServerInfo->managers; travManagers; travManagers = travManagers->next)
+ {
+ CPhidget_setStatusFlag(&travManagers->phidm->status, PHIDGET_SERVER_CONNECTED_FLAG, &travManagers->phidm->lock);
+ CPhidget_setStatusFlag(&travManagers->phidm->status, PHIDGET_ATTACHED_FLAG, &travManagers->phidm->lock);
+ if(setupKeysAndListeners_manager(travManagers->phidm, &travManagers->phidm->networkInfo->listen_id))
+ {
+ if(travManagers->phidm->fptrError)
+ CList_addToList((CListHandle *)&managerErrorEvents, travManagers->phidm, CPhidgetHandle_areEqual);
+ CPhidget_clearStatusFlag(&travManagers->phidm->status, PHIDGET_SERVER_CONNECTED_FLAG, &travManagers->phidm->lock);
+ CPhidget_clearStatusFlag(&travManagers->phidm->status, PHIDGET_ATTACHED_FLAG, &travManagers->phidm->lock);
+ travManagers->phidm->networkInfo->server = NULL;
+ }
+ else
+ {
+ if(travManagers->phidm->fptrServerConnect)
+ CList_addToList((CListHandle *)&connectEvents, travManagers->phidm, CPhidgetHandle_areEqual);
+ }
+ }
+
+ //do this here or it could interfere with close
+ for(travPhidgets = phidErrorEvents; travPhidgets; travPhidgets = travPhidgets->next)
+ {
+ removeFromServerInfoList(newServerInfo, travPhidgets->phid, PHIDGET);
+ }
+ for(travManagers = managerErrorEvents; travManagers; travManagers = travManagers->next)
+ {
+ removeFromServerInfoList(newServerInfo, travManagers->phidm, MANAGER);
+ }
+
+ //set this here so we can call close from events
+ newServerInfo->server->auth_thread.thread_status = FALSE;
+
+ CThread_mutex_unlock(&serverLock);
+ //CThread_mutex_unlock(&serverLockLock);
+
+ //send out events
+ for(travPhidgets = connectEvents; travPhidgets; travPhidgets = travPhidgets->next)
+ {
+ travPhidgets->phid->fptrServerConnect((CPhidgetHandle)travPhidgets->phid, travPhidgets->phid->fptrServerConnectptr);
+ }
+ CList_emptyList((CListHandle *)connectEvents, PFALSE, NULL);
+ for(travPhidgets = phidErrorEvents; travPhidgets; travPhidgets = travPhidgets->next)
+ {
+ travPhidgets->phid->fptrError((CPhidgetHandle)travPhidgets->phid, travPhidgets->phid->fptrErrorptr, EEPHIDGET_NETWORK,
+ "Error setting up phidget listeners from async_authorization_handler_thread");
+ }
+ CList_emptyList((CListHandle *)phidErrorEvents, PFALSE, NULL);
+ for(travManagers = managerErrorEvents; travManagers; travManagers = travManagers->next)
+ {
+ travManagers->phidm->fptrError((CPhidgetManagerHandle)travManagers->phidm, travManagers->phidm->fptrErrorptr, EEPHIDGET_NETWORK,
+ "Error setting up manager listeners from async_authorization_handler_thread");
+ }
+ CList_emptyList((CListHandle *)managerErrorEvents, PFALSE, NULL);
+ return (CThread_func_return_t)0;
+}
+
+//this is only called when an auth succeeds
+void async_authorization_handler(void *ptr, void (*error)(const char *errdesc, void *arg))
+{
+ //need to start a thread because we can't call synchronous network functions like pdc_enable_periodic_reports from this callback
+ //They will just deadlock
+ CServerInfoHandle newServerInfo = (CServerInfoHandle)ptr;
+ AuthHandlerThreadDataHandle data;
+ data = malloc(sizeof(AuthHandlerThreadData));
+ data->error = error;
+ data->ptr = ptr;
+
+ //we do need to keep track of this thread so we can kill it on close if needed
+ // - it's associated with the server, and there should only be one running per server at a time!
+ if(newServerInfo->server->auth_thread.m_ThreadHandle)
+ {
+ newServerInfo->server->auth_thread.thread_status = FALSE;
+ CThread_join(&newServerInfo->server->auth_thread);
+ }
+
+ newServerInfo->server->auth_thread.thread_status = TRUE;
+ CThread_create(&newServerInfo->server->auth_thread, async_authorization_handler_thread, data);
+}
+
+typedef struct _AuthErrorHandlerThreadData
+{
+ char *error;
+ void *ptr;
+} AuthErrorHandlerThreadData, *AuthErrorHandlerThreadDataHandle;
+
+CThread_func_return_t async_authorization_error_handler_thread(CThread_func_arg_t lpdwParam)
+{
+ AuthErrorHandlerThreadDataHandle data = (AuthErrorHandlerThreadDataHandle)lpdwParam;
+
+ CPhidgetListHandle travPhidgets;
+ CPhidgetDictionaryListHandle travDicts;
+ CPhidgetManagerListHandle travManagers;
+
+ CPhidgetListHandle errorEvents = NULL;
+
+ CServerInfoHandle newServerInfo = (CServerInfoHandle)data->ptr;
+
+ int errCode;
+
+ const char *badPassStr = "Authentication Failed";
+ const char *badVerStr = "Version Mismatch";
+
+ //make sure that we can cancel this thread
+/*#ifndef _WINDOWS
+ int temp;
+ pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &temp);
+ pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &temp);
+#endif*/
+
+ //CThread_mutex_lock(&serverLockLock);
+ CThread_mutex_lock(&serverLock);
+
+ if(strlen(data->error)>=strlen(badPassStr) && !strncmp(data->error, badPassStr, strlen(badPassStr)))
+ {
+ CPhidget_setStatusFlag(&newServerInfo->server->status, PHIDGETSOCKET_AUTHERROR_FLAG, &newServerInfo->server->lock);
+ errCode = EEPHIDGET_BADPASSWORD;
+ }
+ else if(strlen(data->error)>=strlen(badVerStr) && !strncmp(data->error, badVerStr, strlen(badVerStr)))
+ {
+ CPhidget_setStatusFlag(&newServerInfo->server->status, PHIDGETSOCKET_CONNECTIONERROR_FLAG, &newServerInfo->server->lock);
+ errCode = EEPHIDGET_BADVERSION;
+ }
+ else
+ {
+ //we can't assume that newServerInfo is even valid
+ //CPhidget_setStatusFlag(&newServerInfo->server->status, PHIDGETSOCKET_CONNECTIONERROR_FLAG, &newServerInfo->server->lock);
+ errCode = EEPHIDGET_NETWORK;
+ }
+
+ //for each in server list, do the error handler - don't do a disconnect handler
+ //also remove the socket reference from the devices, and clears the lists in the serverInfo so that closeServer works
+ //PHIDGET_INERROREVENT_FLAG is set so that things don't break if we call close in the error event
+ //(don't want findActiveDevices to use these until after the error event fire)
+ for(travPhidgets = newServerInfo->phidgets; travPhidgets; travPhidgets = travPhidgets->next)
+ {
+ if(travPhidgets->phid->fptrError)
+ {
+ CPhidget_setStatusFlag(&travPhidgets->phid->status, PHIDGET_INERROREVENT_FLAG, &travPhidgets->phid->lock);
+ CList_addToList((CListHandle *)&errorEvents, travPhidgets->phid, CPhidgetHandle_areEqual);
+ }
+ travPhidgets->phid->networkInfo->server = NULL;
+ }
+ for(travDicts = newServerInfo->dictionaries; travDicts; travDicts = travDicts->next)
+ {
+ if(travDicts->dict->fptrError)
+ {
+ CPhidget_setStatusFlag(&travDicts->dict->status, PHIDGET_INERROREVENT_FLAG, &travDicts->dict->lock);
+ CList_addToList((CListHandle *)&errorEvents, travDicts->dict, CPhidgetHandle_areEqual);
+ }
+ travDicts->dict->networkInfo->server = NULL;
+ }
+ for(travManagers = newServerInfo->managers; travManagers; travManagers = travManagers->next)
+ {
+ if(travManagers->phidm->fptrError)
+ {
+ CPhidget_setStatusFlag(&travManagers->phidm->status, PHIDGET_INERROREVENT_FLAG, &travManagers->phidm->lock);
+ CList_addToList((CListHandle *)&errorEvents, travManagers->phidm, CPhidgetHandle_areEqual);
+ }
+ travManagers->phidm->networkInfo->server = NULL;
+ }
+
+ CList_emptyList((CListHandle *)&newServerInfo->phidgets, PFALSE, NULL);
+ CList_emptyList((CListHandle *)&newServerInfo->managers, PFALSE, NULL);
+ CList_emptyList((CListHandle *)&newServerInfo->dictionaries, PFALSE, NULL);
+
+ //clear this here, so we don't mess things up with findActiveDevices trying to attach these
+ CPhidget_clearStatusFlag(&newServerInfo->server->status, PHIDGETSOCKET_CONNECTING_FLAG, &newServerInfo->server->lock);
+
+ //do this here so we don't attempt a join in closeServer
+ newServerInfo->server->auth_error_thread.thread_status = FALSE;
+
+ //now we call closserver explicitely - it doens't matter if they call close in the error event, as the server is already closed.
+ closeServer(newServerInfo, PFALSE);
+
+ CThread_mutex_unlock(&serverLock);
+ //CThread_mutex_unlock(&serverLockLock);
+
+
+ for(travPhidgets = errorEvents; travPhidgets; travPhidgets = travPhidgets->next)
+ {
+ //they can block, close the phidgets, delete it, etc. in the error event and that shouldn't break anything.
+ //This thread will just exit right away, and that will be that...
+ travPhidgets->phid->fptrError((CPhidgetHandle)travPhidgets->phid, travPhidgets->phid->fptrErrorptr, errCode, data->error);
+ CPhidget_clearStatusFlag(&travPhidgets->phid->status, PHIDGET_INERROREVENT_FLAG, &travPhidgets->phid->lock);
+ }
+ CList_emptyList((CListHandle *)&errorEvents, PFALSE, NULL);
+
+ free(data->error);
+ free(data);
+
+ return (CThread_func_return_t)0;
+}
+
+void async_authorization_error_handler(const char *error, void *ptr)
+{
+ //need to start a thread because we can't call synchronous netowrk functions from this callback
+ CServerInfoHandle newServerInfo = (CServerInfoHandle)ptr;
+ AuthErrorHandlerThreadDataHandle data;
+ data = malloc(sizeof(AuthErrorHandlerThreadData));
+ data->error = strdup(error);
+ data->ptr = ptr;
+
+ //we do need to keep track of this thread so we can kill it on close if needed
+ // - it's associated with the server, and there should only be one running per server at a time!
+ if(newServerInfo->server->auth_error_thread.m_ThreadHandle)
+ {
+ newServerInfo->server->auth_error_thread.thread_status = FALSE;
+ CThread_join(&newServerInfo->server->auth_error_thread);
+ }
+
+ newServerInfo->server->auth_error_thread.thread_status = TRUE;
+ CThread_create(&newServerInfo->server->auth_error_thread, async_authorization_error_handler_thread, data);
+}
+
+//This is only ever called once at a time
+int connectToServer(CPhidgetRemoteHandle remoteInfo, char *errdesc, int errlen, void *list_element, ListElementType type)
+{
+#ifdef ZEROCONF_LOOKUP
+ struct hostent * addr_lookup;
+ const char * addr_lookup_str;
+#endif
+ int result = EPHIDGET_OK;
+ CServerInfoHandle foundServer = NULL;
+ CServerInfoHandle newServerInfo;
+
+ LOG(PHIDGET_LOG_VERBOSE, "Connecting to server: 0x%x",remoteInfo);
+
+ //Initialize the network if not already done
+ if(!NetworkInitialized)
+ if((result = InitializeNetworking()))
+ return result;
+
+ //Creating a new server info object
+ if(!(newServerInfo = malloc(sizeof(CServerInfo))))
+ return EPHIDGET_NOMEMORY;
+ ZEROMEM(newServerInfo, sizeof(CServerInfo));
+ if((result = CPhidgetSocketClient_create(&newServerInfo->server)))
+ return result;
+
+ //openRemoteIP
+ if(remoteInfo->requested_address != NULL)
+ {
+ LOG(PHIDGET_LOG_VERBOSE, "Connect with openRemoteIP");
+ if(!(newServerInfo->server->address = strdup(remoteInfo->requested_address)))
+ return EPHIDGET_NOMEMORY;
+ if(!(newServerInfo->server->port = strdup(remoteInfo->requested_port)))
+ return EPHIDGET_NOMEMORY;
+ }
+ //openRemote
+#ifdef USE_ZEROCONF
+ else //seems we've found an mDNS server we want to connect to
+ {
+ LOG(PHIDGET_LOG_VERBOSE, "Connect with openRemote, need to do hostname lookup...");
+ if(getZeroconfHostPort(remoteInfo))
+ return EPHIDGET_NETWORK;
+ if(!(newServerInfo->server->address = strdup(remoteInfo->zeroconf_host)))
+ return EPHIDGET_NOMEMORY;
+ if(!(newServerInfo->server->port = strdup(remoteInfo->zeroconf_port)))
+ return EPHIDGET_NOMEMORY;
+ }
+#else
+ else
+ {
+ return EPHIDGET_INVALIDARG;
+ }
+#endif
+
+ LOG(PHIDGET_LOG_INFO, "Want to connect to server: %s:%s",newServerInfo->server->address,newServerInfo->server->port);
+
+ //check to see if there is already a connection to this server
+ result = CList_findInList((CListHandle)servers, newServerInfo, CServerInfo_areEqual, (void **)&foundServer);
+ switch(result)
+ {
+ case EPHIDGET_OK: //Found
+ LOG(PHIDGET_LOG_VERBOSE, "Found an active connection to this server: 0x%x",foundServer);
+ remoteInfo->server = foundServer->server;
+ CServerInfo_free(newServerInfo); newServerInfo = NULL;
+
+ //add device to list in serverInfo here
+ if((result = addToServerInfoList(foundServer, list_element, type)))
+ return result;
+
+ //if the server is already connected, register listeners, and send out connect event, etc.
+ // - otherwise, they will be registered when it connects
+ if(CPhidget_statusFlagIsSet(remoteInfo->server->status, PHIDGETSOCKET_CONNECTED_FLAG))
+ {
+ switch(type)
+ {
+ case PHIDGET:
+ {
+ CPhidgetHandle phid = (CPhidgetHandle)list_element;
+ CPhidget_setStatusFlag(&phid->status, PHIDGET_SERVER_CONNECTED_FLAG, &phid->lock);
+ if(setupKeysAndListeners_phidget(phid, &phid->networkInfo->listen_id))
+ {
+ CPhidget_clearStatusFlag(&phid->status, PHIDGET_SERVER_CONNECTED_FLAG, &phid->lock);
+ if(phid->fptrError)
+ phid->fptrError((CPhidgetHandle)phid, phid->fptrErrorptr, EEPHIDGET_NETWORK, "Error setting up phidget listeners from connectToServer.");
+ removeFromServerInfoList(foundServer, list_element, type);
+ remoteInfo->server = NULL;
+ }
+ else
+ {
+ if(phid->fptrServerConnect)
+ phid->fptrServerConnect((CPhidgetHandle)phid, phid->fptrServerConnectptr);
+ }
+ }
+ break;
+ case MANAGER:
+ {
+ CPhidgetManagerHandle phidm = (CPhidgetManagerHandle)list_element;
+ CPhidget_setStatusFlag(&phidm->status, PHIDGET_SERVER_CONNECTED_FLAG, &phidm->lock);
+ CPhidget_setStatusFlag(&phidm->status, PHIDGET_ATTACHED_FLAG, &phidm->lock);
+ if(setupKeysAndListeners_manager(phidm, &phidm->networkInfo->listen_id))
+ {
+ CPhidget_clearStatusFlag(&phidm->status, PHIDGET_SERVER_CONNECTED_FLAG, &phidm->lock);
+ CPhidget_clearStatusFlag(&phidm->status, PHIDGET_ATTACHED_FLAG, &phidm->lock);
+ if(phidm->fptrError)
+ phidm->fptrError((CPhidgetManagerHandle)phidm, phidm->fptrErrorptr, EEPHIDGET_NETWORK, "Error setting up manager listeners from connectToServer.");
+ removeFromServerInfoList(foundServer, list_element, type);
+ remoteInfo->server = NULL;
+ }
+ else
+ {
+ if(phidm->fptrServerConnect)
+ phidm->fptrServerConnect((CPhidgetManagerHandle)phidm, phidm->fptrServerConnectptr);
+ }
+ }
+ break;
+ case DICTIONARY:
+ {
+ CPhidgetDictionaryHandle dict = (CPhidgetDictionaryHandle)list_element;
+ CPhidget_setStatusFlag(&dict->status, PHIDGET_SERVER_CONNECTED_FLAG, &dict->lock);
+ CPhidget_setStatusFlag(&dict->status, PHIDGET_ATTACHED_FLAG, &dict->lock);
+ if(dict->fptrServerConnect)
+ dict->fptrServerConnect((CPhidgetDictionaryHandle)dict, dict->fptrServerConnectptr);
+ }
+ break;
+ }
+ }
+ break;
+ case EPHIDGET_NOTFOUND: //Not Found
+
+ LOG(PHIDGET_LOG_VERBOSE, "We need to create a new connection...");
+ //If the connection fails, this never even makes it into the server list, and the Phidget never sees it's server get initialized
+#ifdef ZEROCONF_LOOKUP
+
+ /* this will resolve to an IP address, including .local hostnames (for SBC, because it can't resolve .local hostnames on its own) */
+ LOG(PHIDGET_LOG_VERBOSE, "Looking up address using internal mdns_gethostbyname: %s",newServerInfo->server->address);
+ addr_lookup = mdns_gethostbyname(newServerInfo->server->address);
+ if (addr_lookup == NULL) {
+ /* didn't work, just use address */
+ addr_lookup_str = newServerInfo->server->address;
+ LOG(PHIDGET_LOG_VERBOSE, "Couldn't lookup address, using hostname");
+ }
+ else
+ {
+ if (addr_lookup->h_addr_list[0] != NULL)
+ {
+ addr_lookup_str = inet_ntoa( *( struct in_addr*)( addr_lookup -> h_addr_list[0]));
+ LOG(PHIDGET_LOG_VERBOSE, "Found this address: %s",addr_lookup_str);
+ }
+ else
+ {
+ addr_lookup_str = newServerInfo->server->address;
+ LOG(PHIDGET_LOG_VERBOSE, "Couldn't lookup address, tring with hostname anyways...");
+ }
+ }
+
+ if (!stream_server_connect(addr_lookup_str, newServerInfo->server->port, &newServerInfo->server->socket, &remoteInfo->cancelSocket, errdesc, errlen))
+ {
+#else
+ if (!stream_server_connect(newServerInfo->server->address, newServerInfo->server->port, &newServerInfo->server->socket, &remoteInfo->cancelSocket, errdesc, errlen))
+ {
+#endif
+ LOG(PHIDGET_LOG_ERROR,"connect(%s:%s): %s", newServerInfo->server->address, newServerInfo->server->port, errdesc);
+ CServerInfo_free(newServerInfo); newServerInfo = NULL;
+ if(errno==ECANCELED)
+ return EPHIDGET_INTERRUPTED;
+ return EPHIDGET_NETWORK;
+ }
+
+ LOG(PHIDGET_LOG_VERBOSE, "Connection was successfull.");
+
+ if (!(newServerInfo->server->pdcs = pdc_session_alloc(newServerInfo->server->socket, pu_read, newServerInfo->server->socket,
+ pu_write, pu_close, newServerInfo->server, cleanup_after_socket))) {
+ fflush(stderr);
+ CServerInfo_free(newServerInfo); newServerInfo = NULL;
+ return EPHIDGET_NOTFOUND;
+ }
+
+ //set authenticating state
+ CPhidget_setStatusFlag(&newServerInfo->server->status, PHIDGETSOCKET_CONNECTING_FLAG, &newServerInfo->server->lock);
+
+ //set server for this device to new server
+ remoteInfo->server = newServerInfo->server;
+
+ //add it to the list - note we are allowed to have connecting servers in the list!
+ if((result = CList_addToList((CListHandle *)&servers, newServerInfo, CServerInfo_areEqual)))
+ return result;
+
+ //add device to list in serverInfo here
+ if((result = addToServerInfoList(newServerInfo, list_element, type)))
+ return result;
+
+ //connection is made - start authorization - this should return as one of two callbacks - success or error
+ //TODO: have some sort of timeout for the connection to succeed or fail
+ pdc_async_authorize(newServerInfo->server->pdcs, ws_protocol_ver,
+ remoteInfo->password, async_authorization_handler,
+ async_authorization_error_handler, newServerInfo);
+
+ //Start looking for a timeout
+ setTimeNow(&newServerInfo->server->lastHeartbeatTime);
+ newServerInfo->server->waitingForHeartbeat = PTRUE;
+
+ break;
+ default:
+ return result;
+ }
+
+ LOG(PHIDGET_LOG_VERBOSE, "returning from end of connectToServer with successfull result.");
+ return EPHIDGET_OK;
+}
+
+int MonitorHeartbeats()
+{
+ CServerList *travServers;
+ CPhidgetSocketClientHandle server;
+
+ struct sockaddr_storage name;
+ char addr[200], *a;
+ socklen_t namelen = sizeof(name);
+ int port, e;
+
+ char key[1024], val[1024];
+
+ CThread_mutex_lock(&serverLockLock);
+ CThread_mutex_lock(&serverLock);
+
+start:
+ for(travServers = servers; travServers; travServers = travServers->next)
+ {
+ if(travServers->serverInfo && travServers->serverInfo->server)
+ {
+ server = travServers->serverInfo->server;
+
+ if(server->waitingForHeartbeat && !server->runningEvent)
+ {
+ //if we've been waiting too long, then signal disconnect
+ double waitTime = timeSince(&server->lastHeartbeatTime);
+ //if we haven't recieved any heartbeats, set the timeout high (4*4 = 16 seconds)
+ //This is so that really slow connections will get through the auth stage
+ double avgPingTime = ((server->avgHeartbeatTimeCount > 0) ? (server->avgHeartbeatTime / server->avgHeartbeatTimeCount) : 4.0);
+
+ //10 times the average ping time, or 2 seconds, whichever is larger
+ if(waitTime > (avgPingTime * 10) && waitTime > 2.0)
+ {
+ server->waitingForHeartbeat = PFALSE;
+ server->avgHeartbeatTime = 0;
+ server->avgHeartbeatTimeCount = 0;
+ //close the socket - this will filter detach events down the chain
+ closeServer(travServers->serverInfo, PTRUE);
+ //need to exit the loop because we removed the server from it!
+ goto start;
+ }
+ }
+ else
+ {
+ //new heartbeat every 2 seconds
+ if(timeSince(&server->lastHeartbeatTime) > 2.0)
+ {
+ if(getsockname(server->socket, (struct sockaddr *)&name, &namelen) != 0)
+ {
+ LOG(PHIDGET_LOG_ERROR,"getsockname: %s", strerror(errno));
+
+ CThread_mutex_unlock(&serverLock);
+ CThread_mutex_unlock(&serverLockLock);
+
+ return EPHIDGET_UNEXPECTED;
+ }
+ if((e = getnameinfo((struct sockaddr *)&name, namelen, addr, sizeof(addr), NULL, 0, NI_NUMERICHOST)) != 0)
+ {
+ LOG(PHIDGET_LOG_ERROR,"getnameinfo: %s", gai_strerror(e));
+
+ CThread_mutex_unlock(&serverLock);
+ CThread_mutex_unlock(&serverLockLock);
+
+ return EPHIDGET_UNEXPECTED;
+ }
+ port = (int)((struct sockaddr_in *)&name)->sin_port;
+ escape(addr, strlen(addr), &a);
+
+ snprintf(key, sizeof(key), "/PCK/Heartbeat/%s/%d", a, port);
+ free(a);
+ snprintf(val, sizeof(val), "%d", server->heartbeatCount);
+ server->waitingForHeartbeat = PTRUE;
+ setTimeNow(&server->lastHeartbeatTime);
+ pdc_async_set(server->pdcs, key, val, (int)strlen(val), PTRUE, NULL, NULL);
+ }
+ }
+ }
+ }
+
+ CThread_mutex_unlock(&serverLock);
+ CThread_mutex_unlock(&serverLockLock);
+
+ return EPHIDGET_OK;
+}
+
+// This will try to connect unconnected openRemoteIP devices and find any zeroconf matches
+int
+FindActiveRemoteDevices()
+{
+ CPhidgetList *activePhidTrav = 0, *zeroconfPhidTrav;
+ CPhidgetManagerList *activeManagerTrav;
+ CPhidgetDictionaryList *activeDictTrav;
+ CPhidgetRemoteList *zeroconfServerTrav;
+ int result = 0;
+ char errdesc[1024];
+ void *err_device = NULL;
+
+ errdesc[0] = '\0';
+
+ //Zeroconf Phidgets
+ CThread_mutex_lock(&activeRemotePhidgetsLock);
+ CThread_mutex_lock(&zeroconfPhidgetsLock);
+
+ for (zeroconfPhidTrav=zeroconfPhidgets; zeroconfPhidTrav; zeroconfPhidTrav = zeroconfPhidTrav->next)
+ {
+ //first look for specific serial numbers
+ for (activePhidTrav=activeRemotePhidgets; activePhidTrav; activePhidTrav = activePhidTrav->next)
+ {
+ if(!CPhidget_statusFlagIsSet(activePhidTrav->phid->status, PHIDGET_INERROREVENT_FLAG)
+ && activePhidTrav->phid->networkInfo->server == NULL
+ && ((activePhidTrav->phid->specificDevice == PHIDGETOPEN_SERIAL && (activePhidTrav->phid->serialNumber == zeroconfPhidTrav->phid->serialNumber))
+ || (activePhidTrav->phid->specificDevice == PHIDGETOPEN_LABEL && !strncmp(activePhidTrav->phid->label, zeroconfPhidTrav->phid->label, MAX_LABEL_STORAGE-1)))
+ && activePhidTrav->phid->deviceID == zeroconfPhidTrav->phid->deviceID
+ && activePhidTrav->phid->networkInfo->requested_address==NULL
+ && (activePhidTrav->phid->networkInfo->requested_serverID == NULL
+ || !strcmp(activePhidTrav->phid->networkInfo->requested_serverID,zeroconfPhidTrav->phid->networkInfo->zeroconf_server_id)))
+ {
+ CThread_mutex_lock(&serverLockLock);
+ CThread_mutex_lock(&serverLock);
+
+ free(activePhidTrav->phid->networkInfo->zeroconf_name); activePhidTrav->phid->networkInfo->zeroconf_name = strdup(zeroconfPhidTrav->phid->networkInfo->zeroconf_name);
+ free(activePhidTrav->phid->networkInfo->zeroconf_type); activePhidTrav->phid->networkInfo->zeroconf_type = strdup(zeroconfPhidTrav->phid->networkInfo->zeroconf_type);
+ free(activePhidTrav->phid->networkInfo->zeroconf_domain); activePhidTrav->phid->networkInfo->zeroconf_domain = strdup(zeroconfPhidTrav->phid->networkInfo->zeroconf_domain);
+ free(activePhidTrav->phid->networkInfo->zeroconf_server_id); activePhidTrav->phid->networkInfo->zeroconf_server_id = strdup(zeroconfPhidTrav->phid->networkInfo->zeroconf_server_id);
+
+ if((result = connectToServer(activePhidTrav->phid->networkInfo, errdesc, sizeof(errdesc), activePhidTrav->phid, PHIDGET)) != EPHIDGET_OK)
+ {
+ err_device = activePhidTrav->phid;
+ activePhidTrav->phid->networkInfo->server = NULL;
+ CThread_mutex_unlock(&serverLock);
+ CThread_mutex_unlock(&serverLockLock);
+ CThread_mutex_unlock(&zeroconfPhidgetsLock);
+ CThread_mutex_unlock(&activeRemotePhidgetsLock);
+ goto error_event;
+ }
+
+ CThread_mutex_unlock(&serverLock);
+ CThread_mutex_unlock(&serverLockLock);
+
+ goto next_zeroconf_phidget;
+ }
+ }
+
+ //then take care of -1 (any) serial numbers
+ for (activePhidTrav=activeRemotePhidgets; activePhidTrav; activePhidTrav = activePhidTrav->next)
+ {
+ if(!CPhidget_statusFlagIsSet(activePhidTrav->phid->status, PHIDGET_INERROREVENT_FLAG)
+ && !activePhidTrav->phid->networkInfo->server
+ && CPhidget_areEqual(activePhidTrav->phid, zeroconfPhidTrav->phid)
+ && activePhidTrav->phid->networkInfo->requested_address==NULL
+ && (activePhidTrav->phid->networkInfo->requested_serverID == NULL
+ || !strcmp(activePhidTrav->phid->networkInfo->requested_serverID,zeroconfPhidTrav->phid->networkInfo->zeroconf_server_id)))
+ {
+ CThread_mutex_lock(&serverLockLock);
+ CThread_mutex_lock(&serverLock);
+
+ free(activePhidTrav->phid->networkInfo->zeroconf_name); activePhidTrav->phid->networkInfo->zeroconf_name = strdup(zeroconfPhidTrav->phid->networkInfo->zeroconf_name);
+ free(activePhidTrav->phid->networkInfo->zeroconf_type); activePhidTrav->phid->networkInfo->zeroconf_type = strdup(zeroconfPhidTrav->phid->networkInfo->zeroconf_type);
+ free(activePhidTrav->phid->networkInfo->zeroconf_domain); activePhidTrav->phid->networkInfo->zeroconf_domain = strdup(zeroconfPhidTrav->phid->networkInfo->zeroconf_domain);
+ free(activePhidTrav->phid->networkInfo->zeroconf_server_id); activePhidTrav->phid->networkInfo->zeroconf_server_id = strdup(zeroconfPhidTrav->phid->networkInfo->zeroconf_server_id);
+
+ if((result = connectToServer(activePhidTrav->phid->networkInfo, errdesc, sizeof(errdesc), activePhidTrav->phid, PHIDGET)) != EPHIDGET_OK)
+ {
+ err_device = activePhidTrav->phid;
+ activePhidTrav->phid->networkInfo->server = NULL;
+ CThread_mutex_unlock(&serverLock);
+ CThread_mutex_unlock(&serverLockLock);
+ CThread_mutex_unlock(&zeroconfPhidgetsLock);
+ CThread_mutex_unlock(&activeRemotePhidgetsLock);
+ goto error_event;
+ }
+
+ CThread_mutex_unlock(&serverLock);
+ CThread_mutex_unlock(&serverLockLock);
+
+ goto next_zeroconf_phidget;
+ }
+ }
+next_zeroconf_phidget:;
+ }
+
+ CThread_mutex_unlock(&zeroconfPhidgetsLock);
+ CThread_mutex_unlock(&activeRemotePhidgetsLock);
+
+
+ //Zeroconf Dictionaries
+ CThread_mutex_lock(&activeRemoteDictionariesLock);
+ CThread_mutex_lock(&zeroconfServersLock);
+ for (zeroconfServerTrav=zeroconfServers; zeroconfServerTrav; zeroconfServerTrav = zeroconfServerTrav->next)
+ {
+ for (activeDictTrav=activeRemoteDictionaries; activeDictTrav; activeDictTrav = activeDictTrav->next)
+ {
+ if(!CPhidget_statusFlagIsSet(activeDictTrav->dict->status, PHIDGET_INERROREVENT_FLAG)
+ && !activeDictTrav->dict->networkInfo->server
+ && activeDictTrav->dict->networkInfo->requested_address==NULL
+ && (activeDictTrav->dict->networkInfo->requested_serverID == NULL
+ || !strcmp(activeDictTrav->dict->networkInfo->requested_serverID,zeroconfServerTrav->networkInfo->zeroconf_name)))
+ {
+ CThread_mutex_lock(&serverLockLock);
+ CThread_mutex_lock(&serverLock);
+ free(activeDictTrav->dict->networkInfo->zeroconf_name); activeDictTrav->dict->networkInfo->zeroconf_name = strdup(zeroconfServerTrav->networkInfo->zeroconf_name);
+ free(activeDictTrav->dict->networkInfo->zeroconf_type); activeDictTrav->dict->networkInfo->zeroconf_type = strdup(zeroconfServerTrav->networkInfo->zeroconf_type);
+ free(activeDictTrav->dict->networkInfo->zeroconf_domain); activeDictTrav->dict->networkInfo->zeroconf_domain = strdup(zeroconfServerTrav->networkInfo->zeroconf_domain);
+ free(activeDictTrav->dict->networkInfo->zeroconf_server_id); activeDictTrav->dict->networkInfo->zeroconf_server_id = strdup(zeroconfServerTrav->networkInfo->zeroconf_server_id);
+ if((result = connectToServer(activeDictTrav->dict->networkInfo, errdesc, sizeof(errdesc), activeDictTrav->dict, DICTIONARY)) != EPHIDGET_OK)
+ {
+ err_device = activeDictTrav->dict;
+ activeDictTrav->dict->networkInfo->server = NULL;
+ CThread_mutex_unlock(&serverLock);
+ CThread_mutex_unlock(&serverLockLock);
+ CThread_mutex_unlock(&zeroconfServersLock);
+ CThread_mutex_unlock(&activeRemoteDictionariesLock);
+ goto error_event;
+ }
+ CThread_mutex_unlock(&serverLock);
+ CThread_mutex_unlock(&serverLockLock);
+ }
+ }
+ }
+ CThread_mutex_unlock(&zeroconfServersLock);
+ CThread_mutex_unlock(&activeRemoteDictionariesLock);
+
+ //IP Phidgets
+ CThread_mutex_lock(&activeRemotePhidgetsLock);
+ for (activePhidTrav=activeRemotePhidgets; activePhidTrav; activePhidTrav = activePhidTrav->next)
+ {
+ if(activePhidTrav->phid->networkInfo->requested_address!=NULL)
+ {
+ if(!CPhidget_statusFlagIsSet(activePhidTrav->phid->status, PHIDGET_INERROREVENT_FLAG)
+ && !activePhidTrav->phid->networkInfo->server)
+ {
+ CThread_mutex_lock(&serverLockLock);
+ CThread_mutex_lock(&serverLock);
+ if((result = connectToServer(activePhidTrav->phid->networkInfo, errdesc, sizeof(errdesc), activePhidTrav->phid, PHIDGET)) != EPHIDGET_OK)
+ {
+ err_device = activePhidTrav->phid;
+ activePhidTrav->phid->networkInfo->server = NULL;
+ CThread_mutex_unlock(&serverLock);
+ CThread_mutex_unlock(&serverLockLock);
+ CThread_mutex_unlock(&activeRemotePhidgetsLock);
+ goto error_event;
+ }
+ CThread_mutex_unlock(&serverLock);
+ CThread_mutex_unlock(&serverLockLock);
+ }
+ }
+ }
+ CThread_mutex_unlock(&activeRemotePhidgetsLock);
+
+ //IP Managers
+ CThread_mutex_lock(&activeRemoteManagersLock);
+ for (activeManagerTrav=activeRemoteManagers; activeManagerTrav; activeManagerTrav = activeManagerTrav->next)
+ {
+ if(activeManagerTrav->phidm->networkInfo->requested_address!=NULL)
+ {
+ if(!CPhidget_statusFlagIsSet(activeManagerTrav->phidm->status, PHIDGET_INERROREVENT_FLAG)
+ && !activeManagerTrav->phidm->networkInfo->server )
+ {
+ CThread_mutex_lock(&serverLockLock);
+ CThread_mutex_lock(&serverLock);
+ if((result = connectToServer(activeManagerTrav->phidm->networkInfo, errdesc, sizeof(errdesc), activeManagerTrav->phidm, MANAGER)) != EPHIDGET_OK)
+ {
+ err_device = activeManagerTrav->phidm;
+ activeManagerTrav->phidm->networkInfo->server = NULL;
+ CThread_mutex_unlock(&serverLock);
+ CThread_mutex_unlock(&serverLockLock);
+ CThread_mutex_unlock(&activeRemoteManagersLock);
+ goto error_event;
+ }
+ CThread_mutex_unlock(&serverLock);
+ CThread_mutex_unlock(&serverLockLock);
+ }
+ }
+ }
+ CThread_mutex_unlock(&activeRemoteManagersLock);
+
+ //IP Dictionaries
+ CThread_mutex_lock(&activeRemoteDictionariesLock);
+ for (activeDictTrav=activeRemoteDictionaries; activeDictTrav; activeDictTrav = activeDictTrav->next)
+ {
+ if(activeDictTrav->dict->networkInfo->requested_address!=NULL)
+ {
+ if(!CPhidget_statusFlagIsSet(activeDictTrav->dict->status, PHIDGET_INERROREVENT_FLAG)
+ && !activeDictTrav->dict->networkInfo->server)
+ {
+ CThread_mutex_lock(&serverLockLock);
+ CThread_mutex_lock(&serverLock);
+ if((result = connectToServer(activeDictTrav->dict->networkInfo, errdesc, sizeof(errdesc), activeDictTrav->dict, DICTIONARY)) != EPHIDGET_OK)
+ {
+ err_device = activeDictTrav->dict;
+ activeDictTrav->dict->networkInfo->server = NULL;
+ CThread_mutex_unlock(&serverLock);
+ CThread_mutex_unlock(&serverLockLock);
+ CThread_mutex_unlock(&activeRemoteDictionariesLock);
+ goto error_event;
+ }
+ CThread_mutex_unlock(&serverLock);
+ CThread_mutex_unlock(&serverLockLock);
+ }
+ }
+ }
+ CThread_mutex_unlock(&activeRemoteDictionariesLock);
+
+ return result;
+
+ //send out any error events that have pilled up...
+ //send them out here so we can close, open, etc. from within the error event
+error_event:
+ //if the error did not originate in a pdc function, we'll fill in our own error description
+ if(errdesc[0] == '\0')
+ strncpy(errdesc, Phid_ErrorDescriptions[result], sizeof(errdesc));
+ //no error event for interrupted - this means that a connect was cancelled by a close
+ if(result != EPHIDGET_INTERRUPTED)
+ {
+ inErrorEvent = PTRUE;
+ throw_error_event(err_device, errdesc, EEPHIDGET_NETWORK);
+ inErrorEvent = PFALSE;
+ }
+ return result;
+}
+
+//shuts down the central remote thread - we should also make sure zeroconf gets shut down here if it's running
+int JoinCentralRemoteThread()
+{
+ if(CentralRemoteThread.m_ThreadHandle && !CThread_is_my_thread(CentralRemoteThread) && !inErrorEvent)
+ {
+ CThread_join(&CentralRemoteThread);
+ CentralRemoteThread.m_ThreadHandle = 0;
+ }
+#ifdef USE_ZEROCONF
+ if(!activeSBCManagers)
+ {
+ UninitializeZeroconf();//shut down zeroconf
+ }
+#endif
+ return EPHIDGET_OK;
+}
+
+int
+StartCentralRemoteThread()
+{
+ CThread_mutex_lock(&CentralRemoteThreadLock);
+#ifdef _WINDOWS
+ if (CentralRemoteThread.m_ThreadHandle) {
+ int threadStatus = 0;
+ int result = 0;
+ result = GetExitCodeThread(CentralRemoteThread.m_ThreadHandle,
+ (LPDWORD)&threadStatus);
+ if (result) {
+ if (threadStatus != STILL_ACTIVE) {
+ CloseHandle(CentralRemoteThread.m_ThreadHandle);
+ CentralRemoteThread.m_ThreadHandle = 0;
+ }
+ }
+ }
+#endif
+
+ if (!CentralRemoteThread.m_ThreadHandle ||
+ CentralRemoteThread.thread_status == FALSE)
+ {
+ if (CThread_create(&CentralRemoteThread, CentralRemoteThreadFunction, 0))
+ return EPHIDGET_UNEXPECTED;
+ CentralRemoteThread.thread_status = TRUE;
+ }
+ CThread_mutex_unlock(&CentralRemoteThreadLock);
+ return EPHIDGET_OK;
+}
+
+CThread_func_return_t CentralRemoteThreadFunction(CThread_func_arg_t lpdwParam)
+{
+ initialize_locks();
+ while(activeRemotePhidgets || activeRemoteManagers || activeRemoteDictionaries) {
+ FindActiveRemoteDevices(); //this looks for attached active devices and opens them
+ MonitorHeartbeats(); //sends out new heartbeats, detects when a server has gone down
+ SLEEP(250);
+ }
+ CentralRemoteThread.thread_status = FALSE;
+ return EPHIDGET_OK;
+}
+
+int RegisterRemotePhidget(CPhidgetHandle phid)
+{
+ int result = EPHIDGET_OK;
+
+ //clear all variables
+ phid->fptrClear((CPhidgetHandle)phid);
+ phid->initKeys = PUNK_INT;
+
+ CThread_mutex_lock(&activeRemotePhidgetsLock);
+
+ result = CList_addToList((CListHandle *)&activeRemotePhidgets, phid, CPhidgetHandle_areEqual);
+
+ if (result)
+ {
+ CThread_mutex_unlock(&activeRemotePhidgetsLock);
+ return result;
+ }
+ CThread_mutex_unlock(&activeRemotePhidgetsLock);
+
+ result = StartCentralRemoteThread();
+
+ return result;
+}
+
+int RegisterRemoteManager(CPhidgetManagerHandle phidm)
+{
+ int result = EPHIDGET_OK;
+
+ CThread_mutex_lock(&activeRemoteManagersLock);
+
+ result = CList_addToList((CListHandle *)&activeRemoteManagers, phidm, CPhidgetHandle_areEqual);
+
+ if (result)
+ {
+ CThread_mutex_unlock(&activeRemoteManagersLock);
+ return result;
+ }
+
+ CThread_mutex_unlock(&activeRemoteManagersLock);
+
+ result = StartCentralRemoteThread();
+
+ return result;
+}
+
+int RegisterRemoteDictionary(CPhidgetDictionaryHandle dict)
+{
+ int result = EPHIDGET_OK;
+
+ CThread_mutex_lock(&activeRemoteDictionariesLock);
+
+ if ((result = CList_addToList((CListHandle *)&activeRemoteDictionaries, dict, CPhidgetHandle_areEqual)) != EPHIDGET_OK)
+ {
+ CThread_mutex_unlock(&activeRemoteDictionariesLock);
+ return result;
+ }
+
+ CThread_mutex_unlock(&activeRemoteDictionariesLock);
+
+ result = StartCentralRemoteThread();
+
+ return result;
+}
+
+int RegisterSBCManager(CPhidgetSBCManagerHandle sbcm)
+{
+ int result = EPHIDGET_OK;
+
+ CThread_mutex_lock(&activeSBCManagersLock);
+
+ result = CList_addToList((CListHandle *)&activeSBCManagers, sbcm, CPhidgetHandle_areEqual);
+
+ if (result)
+ {
+ CThread_mutex_unlock(&activeSBCManagersLock);
+ return result;
+ }
+
+ CThread_mutex_unlock(&activeSBCManagersLock);
+
+ result = StartCentralRemoteThread();
+
+ return result;
+}
+
+// This will close a server connection (and cleanup the socket, etc) if there are no more
+// Phidgets, Managers, or Dictionaries in it's lists
+int closeServer(CServerInfoHandle server, unsigned char force)
+{
+ char errdesc[1024];
+ void *pdcs = server->server->pdcs;
+ //no more references to this server
+ if(((!server->phidgets && !server->dictionaries && !server->managers) || force) && pdcs)
+ {
+ wait_pending(server->server->pdcs);
+ CThread_mutex_lock(&server->server->pdc_lock);
+
+ //rather then calling quit - which can easily block, just close the socket!
+ if(pu_close(server->server->socket,errdesc,sizeof(errdesc)))
+ {
+ LOG(PHIDGET_LOG_ERROR,"pu_close: %s", errdesc);
+ }
+
+ CThread_mutex_unlock(&server->server->pdc_lock);
+ //We need to wait for the read thread to return
+ //unlock serverLock so it can be claimed in the cleanup function
+ //don't want the cleanup function to free pdcs while we're waiting on it..
+ //this is safe because we don't release serverLockLock, so the only thing that is able to claim serverLock is the cleanup function
+ server->server->pdcs = NULL;
+
+ CThread_mutex_unlock(&serverLock);
+
+ pdc_readthread_join(pdcs, NULL);
+
+ CThread_mutex_lock(&serverLock);
+
+ pdc_session_free(pdcs);
+ return EPHIDGET_CLOSED;
+ }
+ return EPHIDGET_OK;
+}
+
+int disconnectRemoteObject(void *object, size_t objectListOffset, int(*compareObjects)(void *, void *))
+{
+ int result = EPHIDGET_OK;
+ int closeRes;
+ CServerInfoHandle foundServer;
+ CServerInfo newServerInfo;
+
+ CPhidgetHandle phid = object;
+
+ CThread_mutex_lock(&serverLockLock);
+ CThread_mutex_lock(&serverLock);
+
+ if(phid->networkInfo->server)
+ {
+ newServerInfo.server = phid->networkInfo->server;
+
+ //check to see if there is already a connection to this server
+ result = CList_findInList((CListHandle)servers, &newServerInfo, CServerInfo_areEqual, (void **)&foundServer);
+ switch(result)
+ {
+ case EPHIDGET_OK: //Found
+
+ if((result = CList_removeFromList((CListHandle *)((size_t)foundServer + objectListOffset), phid, compareObjects, PFALSE, NULL)))
+ {
+ CThread_mutex_unlock(&serverLock);
+ CThread_mutex_unlock(&serverLockLock);
+ return result;
+ }
+
+ //stop reports for this Object
+ //async so it won't block if the connection is bad
+ if(phid->networkInfo->listen_id)
+ {
+ CThread_mutex_lock(&phid->networkInfo->server->pdc_lock);
+ pdc_ignore(foundServer->server->pdcs,phid->networkInfo->listen_id,NULL,0);
+ phid->networkInfo->listen_id = 0;
+ CThread_mutex_unlock(&phid->networkInfo->server->pdc_lock);
+ }
+
+ //closes if there are no more references
+ closeRes = closeServer(foundServer, PFALSE);
+ phid->networkInfo->server = NULL;
+
+ //Run error event for any async commands that didn't complete
+ if(closeRes != EPHIDGET_CLOSED && foundServer->server->pdcs)
+ cleanup_pending(foundServer->server->pdcs, object);
+
+ break;
+ case EPHIDGET_NOTFOUND: //Not Found - That's ok, just means it's already closed
+ phid->networkInfo->server = NULL;
+ CThread_mutex_unlock(&serverLock);
+ CThread_mutex_unlock(&serverLockLock);
+ return EPHIDGET_OK;
+ default:
+ phid->networkInfo->server = NULL;
+ CThread_mutex_unlock(&serverLock);
+ CThread_mutex_unlock(&serverLockLock);
+ return result;
+ }
+ }
+
+ CThread_mutex_unlock(&serverLock);
+ CThread_mutex_unlock(&serverLockLock);
+ return EPHIDGET_OK;
+}
+
+CThread_func_return_t DisconnectPhidgetThreadFunction(CThread_func_arg_t lpdwParam)
+{
+ CPhidgetHandle phid = (CPhidgetHandle)lpdwParam;
+
+ CPhidget_clearStatusFlag(&phid->status, PHIDGET_SERVER_CONNECTED_FLAG, &phid->lock);
+
+ if(phid->fptrServerDisconnect)
+ phid->fptrServerDisconnect((CPhidgetHandle)phid, phid->fptrServerDisconnectptr);
+
+ disconnectRemoteObject(phid, offsetof(CServerInfo, phidgets), CPhidgetHandle_areEqual);
+
+ return EPHIDGET_OK;
+}
+
+int unregisterRemotePhidget(CPhidgetHandle phid)
+{
+ int result = EPHIDGET_OK;
+
+ //cancel a pending connect
+ if(phid->networkInfo->cancelSocket != INVALID_SOCKET)
+ {
+ cancelConnect(phid->networkInfo->cancelSocket);
+ }
+#ifdef USE_ZEROCONF
+ cancelPendingZeroconfLookups(phid->networkInfo);
+#endif
+
+ CThread_mutex_lock(&activeRemotePhidgetsLock);
+
+ result = CList_removeFromList((CListHandle *)&activeRemotePhidgets, phid, CPhidgetHandle_areEqual, FALSE, NULL);
+
+ if (result)
+ {
+ CThread_mutex_unlock(&activeRemotePhidgetsLock);
+ return result;
+ }
+
+ CThread_mutex_unlock(&activeRemotePhidgetsLock);
+
+ CPhidget_clearStatusFlag(&phid->status, PHIDGET_SERVER_CONNECTED_FLAG, &phid->lock);
+ CPhidget_clearStatusFlag(&phid->status, PHIDGET_ATTACHED_FLAG, &phid->lock);
+
+ result = disconnectRemoteObject(phid, offsetof(CServerInfo, phidgets), CPhidgetHandle_areEqual);
+
+ CPhidget_clearStatusFlag(&phid->status, PHIDGET_REMOTE_FLAG, &phid->lock);
+
+ /* don't free this here - it may be referenced elsewhere! */
+ CThread_mutex_lock(&phid->lock);
+ phid->networkInfo->server = NULL;
+ CPhidgetRemote_free(phid->networkInfo);
+ phid->networkInfo = NULL;
+ CThread_mutex_unlock(&phid->lock);
+
+ if(!activeRemotePhidgets && !activeRemoteManagers && !activeRemoteDictionaries)
+ {
+ JoinCentralRemoteThread();
+ }
+
+ return result;
+}
+
+int unregisterRemoteManager(CPhidgetManagerHandle phidm)
+{
+ int result = EPHIDGET_OK;
+ CServerInfoHandle foundServer;
+ CServerInfo newServerInfo;
+ int closeRes;
+
+ //cancel a pending connect
+ if(phidm->networkInfo->cancelSocket != INVALID_SOCKET)
+ {
+ cancelConnect(phidm->networkInfo->cancelSocket);
+ }
+#ifdef USE_ZEROCONF
+ cancelPendingZeroconfLookups(phidm->networkInfo);
+#endif
+
+ CThread_mutex_lock(&activeRemoteManagersLock);
+
+ result = CList_removeFromList((CListHandle *)&activeRemoteManagers, phidm, CPhidgetHandle_areEqual, FALSE, NULL);
+
+ if (result)
+ {
+ CThread_mutex_unlock(&activeRemoteManagersLock);
+ return result;
+ }
+ CThread_mutex_unlock(&activeRemoteManagersLock);
+
+ CThread_mutex_lock(&serverLockLock);
+ CThread_mutex_lock(&serverLock);
+ if(phidm->networkInfo->server)
+ {
+ newServerInfo.server = phidm->networkInfo->server;
+
+ //check to see if there is already a connection to this server
+ result = CList_findInList((CListHandle)servers, &newServerInfo, CServerInfo_areEqual, (void **)&foundServer);
+ switch(result)
+ {
+ case EPHIDGET_OK: //Found
+
+ if((result = CList_removeFromList((CListHandle *)&foundServer->managers, phidm, CPhidgetManager_areEqual, PFALSE, NULL)))
+ {
+ CThread_mutex_unlock(&serverLock);
+ CThread_mutex_unlock(&serverLockLock);
+ return result;
+ }
+
+ CPhidget_clearStatusFlag(&phidm->status, PHIDGET_SERVER_CONNECTED_FLAG, &phidm->lock);
+ CPhidget_clearStatusFlag(&phidm->status, PHIDGET_ATTACHED_FLAG, &phidm->lock);
+
+ //stop reports
+ CThread_mutex_lock(&phidm->networkInfo->server->pdc_lock);
+ pdc_ignore(foundServer->server->pdcs,phidm->networkInfo->listen_id,NULL,0);
+ CThread_mutex_unlock(&phidm->networkInfo->server->pdc_lock);
+
+ closeRes = closeServer(foundServer, PFALSE);
+
+ CPhidget_clearStatusFlag(&phidm->status, PHIDGET_REMOTE_FLAG, &phidm->lock);
+
+ /* don't free this here - it may be referenced elsewhere! */
+ phidm->networkInfo->server = NULL;
+ CPhidgetRemote_free(phidm->networkInfo);
+ phidm->networkInfo = NULL;
+
+ //Run error event for any async commands that didn't complete
+ if(closeRes != EPHIDGET_CLOSED && foundServer->server->pdcs)
+ cleanup_pending(foundServer->server->pdcs, phidm);
+
+ break;
+ case EPHIDGET_NOTFOUND: //Not Found - That's ok, just means it's already closed
+ CThread_mutex_unlock(&serverLock);
+ CThread_mutex_unlock(&serverLockLock);
+ return EPHIDGET_OK;
+ default:
+ CThread_mutex_unlock(&serverLock);
+ CThread_mutex_unlock(&serverLockLock);
+ return result;
+ }
+ }
+ CThread_mutex_unlock(&serverLock);
+ CThread_mutex_unlock(&serverLockLock);
+
+ if(!activeRemotePhidgets && !activeRemoteManagers && !activeRemoteDictionaries)
+ {
+ JoinCentralRemoteThread();
+ }
+
+ return EPHIDGET_OK;
+}
+
+int unregisterRemoteDictionary(CPhidgetDictionaryHandle dict)
+{
+ int result = EPHIDGET_OK;
+ CServerInfoHandle foundServer;
+ CServerInfo newServerInfo;
+ CPhidgetDictionaryListenerListHandle trav;
+ int closeRes = EPHIDGET_OK;
+
+ //cancel a pending connect
+ if(dict->networkInfo->cancelSocket != INVALID_SOCKET)
+ {
+ cancelConnect(dict->networkInfo->cancelSocket);
+ }
+#ifdef USE_ZEROCONF
+ cancelPendingZeroconfLookups(dict->networkInfo);
+#endif
+
+ CThread_mutex_lock(&activeRemoteDictionariesLock);
+ if ((result = CList_removeFromList((CListHandle *)&activeRemoteDictionaries, dict, CPhidgetHandle_areEqual, FALSE, NULL)) != EPHIDGET_OK)
+ {
+ CThread_mutex_unlock(&activeRemoteDictionariesLock);
+ return result;
+ }
+ CThread_mutex_unlock(&activeRemoteDictionariesLock);
+
+ CThread_mutex_lock(&serverLockLock);
+ CThread_mutex_lock(&serverLock);
+ CThread_mutex_lock(&dict->lock);
+ if(dict->networkInfo && dict->networkInfo->server)
+ {
+ newServerInfo.server = dict->networkInfo->server;
+
+ //check to see if there is already a connection to this server
+ result = CList_findInList((CListHandle)servers, &newServerInfo, CServerInfo_areEqual, (void **)&foundServer);
+ switch(result)
+ {
+ case EPHIDGET_OK: //Found
+
+ if((result = CList_removeFromList((CListHandle *)&foundServer->dictionaries, dict, CPhidgetDictionary_areEqual, PFALSE, NULL)))
+ {
+ CThread_mutex_unlock(&dict->lock);
+ CThread_mutex_unlock(&serverLock);
+ CThread_mutex_unlock(&serverLockLock);
+ return result;
+ }
+
+ //stop reports, remove listeners
+ CThread_mutex_lock(&dict->listenersLock);
+ for(trav = dict->listeners; trav; trav = trav->next)
+ {
+ CThread_mutex_lock(&dict->networkInfo->server->pdc_lock);
+ pdc_ignore(foundServer->server->pdcs,trav->listener->listen_id,NULL,0);
+ CThread_mutex_unlock(&dict->networkInfo->server->pdc_lock);
+ }
+ CList_emptyList((CListHandle *)&dict->listeners, PTRUE, CPhidgetDictionaryListener_free);
+ CThread_mutex_unlock(&dict->listenersLock);
+
+ //closes connection if it's not used anymore
+ closeRes = closeServer(foundServer, PFALSE);
+
+ break;
+ case EPHIDGET_NOTFOUND: //Not Found - That's ok, just means it's already closed
+ break;
+ default: //ERROR
+ CThread_mutex_unlock(&dict->lock);
+ CThread_mutex_unlock(&serverLock);
+ CThread_mutex_unlock(&serverLockLock);
+ return result;
+ }
+ //if server needs to be freed it will already have been
+ CPhidget_clearStatusFlag(&dict->status, PHIDGET_SERVER_CONNECTED_FLAG, NULL);
+ dict->networkInfo->server = NULL;
+ CPhidget_clearStatusFlag(&dict->status, PHIDGET_ATTACHED_FLAG, NULL);
+
+ //Run error event for any async commands that didn't complete
+ if(closeRes != EPHIDGET_CLOSED && foundServer && foundServer->server && foundServer->server->pdcs)
+ cleanup_pending(foundServer->server->pdcs, dict);
+ }
+
+ CPhidgetRemote_free(dict->networkInfo);
+ dict->networkInfo = NULL;
+ CPhidget_clearStatusFlag(&dict->status, PHIDGET_REMOTE_FLAG, NULL);
+
+ CThread_mutex_unlock(&dict->lock);
+ CThread_mutex_unlock(&serverLock);
+ CThread_mutex_unlock(&serverLockLock);
+
+ if(!activeRemotePhidgets && !activeRemoteManagers && !activeRemoteDictionaries)
+ {
+ JoinCentralRemoteThread();
+ }
+
+ return EPHIDGET_OK;
+}
+
+int unregisterSBCManager(CPhidgetSBCManagerHandle sbcm)
+{
+ int result = EPHIDGET_OK;
+
+ CThread_mutex_lock(&activeSBCManagersLock);
+
+ result = CList_removeFromList((CListHandle *)&activeSBCManagers, sbcm, CPhidgetHandle_areEqual, FALSE, NULL);
+
+ if (result)
+ {
+ CThread_mutex_unlock(&activeSBCManagersLock);
+ return result;
+ }
+ CThread_mutex_unlock(&activeSBCManagersLock);
+
+#ifdef USE_ZEROCONF
+ if(!activeRemotePhidgets && !activeRemoteManagers && !activeRemoteDictionaries && !activeSBCManagers)
+ {
+ UninitializeZeroconf();//shut down zeroconf
+ }
+#endif
+
+ return EPHIDGET_OK;
+}
+
+int CCONV
+CPhidget_openRemoteIPMaster(CPhidgetHandle phid, const char *address,
+ int port, const char *password)
+{
+ int result = EPHIDGET_OK;
+ char portString[6];
+
+ if((result = CPhidgetRemote_create(&phid->networkInfo)))
+ {
+ CThread_mutex_unlock(&phid->openCloseLock);
+ return result;
+ }
+
+ if(password) {
+ if (strlen(password) > 255)
+ {
+ CThread_mutex_unlock(&phid->openCloseLock);
+ return EPHIDGET_INVALIDARG;
+ }
+ if (!(phid->networkInfo->password = strdup(password)))
+ {
+ CThread_mutex_unlock(&phid->openCloseLock);
+ return EPHIDGET_NOMEMORY;
+ }
+ }
+
+ snprintf(portString, sizeof(portString), "%d", port);
+ if(!(phid->networkInfo->requested_port = strdup(portString)))
+ {
+ CThread_mutex_unlock(&phid->openCloseLock);
+ return EPHIDGET_NOMEMORY;
+ }
+ if(!(phid->networkInfo->requested_address = strdup(address)))
+ {
+ CThread_mutex_unlock(&phid->openCloseLock);
+ return EPHIDGET_NOMEMORY;
+ }
+
+ initialize_locks();
+
+ CPhidget_setStatusFlag(&phid->status, PHIDGET_REMOTE_FLAG, &phid->lock);
+ CPhidget_setStatusFlag(&phid->status, PHIDGET_OPENED_FLAG, &phid->lock);
+
+ result = RegisterRemotePhidget(phid);
+
+ CThread_mutex_unlock(&phid->openCloseLock);
+
+ return result;
+}
+
+int CCONV
+CPhidget_openRemoteIP(CPhidgetHandle phid, int serialNumber, const char *address,
+ int port, const char *password)
+{
+ TESTPTR(phid)
+
+ if (serialNumber < -1)
+ return EPHIDGET_INVALIDARG;
+
+ CThread_mutex_lock(&phid->openCloseLock);
+ if (CPhidget_statusFlagIsSet(phid->status, PHIDGET_OPENED_FLAG))
+ {
+ LOG(PHIDGET_LOG_WARNING, "Open was called on an already opened Phidget handle.");
+ CThread_mutex_unlock(&phid->openCloseLock);
+ return EPHIDGET_OK;
+ }
+
+ if (serialNumber == -1)
+ phid->specificDevice = PHIDGETOPEN_ANY;
+ else
+ phid->specificDevice = PHIDGETOPEN_SERIAL;
+ phid->serialNumber = serialNumber;
+
+ return CPhidget_openRemoteIPMaster(phid, address, port, password);
+}
+
+int CCONV
+CPhidget_openLabelRemoteIP(CPhidgetHandle phid, const char *label, const char *address,
+ int port, const char *password)
+{
+ int result;
+ TESTPTR(phid)
+
+ if(label != NULL && ((result = encodeLabelString(label, NULL, NULL)) != EPHIDGET_OK))
+ return result;
+
+ CThread_mutex_lock(&phid->openCloseLock);
+ if (CPhidget_statusFlagIsSet(phid->status, PHIDGET_OPENED_FLAG))
+ {
+ LOG(PHIDGET_LOG_WARNING, "Open was called on an already opened Phidget handle.");
+ CThread_mutex_unlock(&phid->openCloseLock);
+ return EPHIDGET_OK;
+ }
+
+ if (label == NULL)
+ phid->specificDevice = PHIDGETOPEN_ANY;
+ else
+ {
+ phid->specificDevice = PHIDGETOPEN_LABEL;
+ memcpy(phid->label, label, strlen(label)+1);
+ }
+
+ return CPhidget_openRemoteIPMaster(phid, address, port, password);
+}
+
+int CCONV CPhidget_openRemoteMaster(CPhidgetHandle phid, const char *serverID, const char *password)
+{
+ int result = EPHIDGET_OK;
+
+ if((result = CPhidgetRemote_create(&phid->networkInfo)))
+ {
+ CThread_mutex_unlock(&phid->openCloseLock);
+ return result;
+ }
+
+ if(password) {
+ if (strlen(password) > 255)
+ {
+ CThread_mutex_unlock(&phid->openCloseLock);
+ return EPHIDGET_INVALIDARG;
+ }
+ if (!(phid->networkInfo->password = strdup(password)))
+ {
+ CThread_mutex_unlock(&phid->openCloseLock);
+ return EPHIDGET_NOMEMORY;
+ }
+ }
+ if(serverID)
+ {
+ if (!(phid->networkInfo->requested_serverID = strdup(serverID)))
+ {
+ CThread_mutex_unlock(&phid->openCloseLock);
+ return EPHIDGET_NOMEMORY;
+ }
+ }
+
+ phid->networkInfo->mdns = PTRUE;
+
+ CPhidget_setStatusFlag(&phid->status, PHIDGET_REMOTE_FLAG, &phid->lock);
+ CPhidget_setStatusFlag(&phid->status, PHIDGET_OPENED_FLAG, &phid->lock);
+
+ result = RegisterRemotePhidget(phid);
+
+ CThread_mutex_unlock(&phid->openCloseLock);
+
+ return result;
+}
+
+int CCONV CPhidget_openRemote(CPhidgetHandle phid, int serialNumber, const char *serverID, const char *password)
+{
+#ifdef USE_ZEROCONF
+ int result = EPHIDGET_OK;
+ TESTPTR(phid)
+
+ if (serialNumber < -1)
+ return EPHIDGET_INVALIDARG;
+
+ CThread_mutex_lock(&phid->openCloseLock);
+ initialize_locks();
+
+ if((result = InitializeZeroconf()))
+ {
+ CThread_mutex_unlock(&phid->openCloseLock);
+ if(result == EPHIDGET_TRYAGAIN)
+ return EPHIDGET_TIMEOUT;
+ return EPHIDGET_UNSUPPORTED;
+ }
+
+ if (CPhidget_statusFlagIsSet(phid->status, PHIDGET_OPENED_FLAG))
+ {
+ LOG(PHIDGET_LOG_WARNING, "Open was called on an already opened Phidget handle.");
+ CThread_mutex_unlock(&phid->openCloseLock);
+ return EPHIDGET_OK;
+ }
+
+ if (serialNumber == -1)
+ phid->specificDevice = PHIDGETOPEN_ANY;
+ else
+ phid->specificDevice = PHIDGETOPEN_SERIAL;
+ phid->serialNumber = serialNumber;
+
+ return CPhidget_openRemoteMaster(phid, serverID, password);
+#else
+ return EPHIDGET_UNSUPPORTED;
+#endif
+}
+
+int CCONV CPhidget_openLabelRemote(CPhidgetHandle phid, const char *label, const char *serverID, const char *password)
+{
+#ifdef USE_ZEROCONF
+ int result = EPHIDGET_OK;
+ TESTPTR(phid)
+
+ if(label != NULL && ((result = encodeLabelString(label, NULL, NULL)) != EPHIDGET_OK))
+ return result;
+
+ CThread_mutex_lock(&phid->openCloseLock);
+ initialize_locks();
+
+ if((result = InitializeZeroconf()))
+ {
+ CThread_mutex_unlock(&phid->openCloseLock);
+ if(result == EPHIDGET_TRYAGAIN)
+ return EPHIDGET_TIMEOUT;
+ return EPHIDGET_UNSUPPORTED;
+ }
+
+ if (CPhidget_statusFlagIsSet(phid->status, PHIDGET_OPENED_FLAG))
+ {
+ LOG(PHIDGET_LOG_WARNING, "Open was called on an already opened Phidget handle.");
+ CThread_mutex_unlock(&phid->openCloseLock);
+ return EPHIDGET_OK;
+ }
+
+ if (label == NULL)
+ phid->specificDevice = PHIDGETOPEN_ANY;
+ else
+ {
+ phid->specificDevice = PHIDGETOPEN_LABEL;
+ memcpy(phid->label, label, strlen(label)+1);
+ }
+
+ return CPhidget_openRemoteMaster(phid, serverID, password);
+#else
+ return EPHIDGET_UNSUPPORTED;
+#endif
+}
+
+int CCONV CPhidgetManager_openRemoteIP(CPhidgetManagerHandle phidm, const char *address,
+ int port, const char *password)
+{
+ int result = EPHIDGET_OK;
+ char portString[6];
+
+ TESTPTR(phidm)
+
+ CThread_mutex_lock(&phidm->openCloseLock);
+ if (CPhidget_statusFlagIsSet(phidm->status, PHIDGET_OPENED_FLAG))
+ {
+ LOG(PHIDGET_LOG_WARNING, "Open was called on an already opened Manager handle.");
+ CThread_mutex_unlock(&phidm->openCloseLock);
+ return EPHIDGET_OK;
+ }
+
+ if((result = CPhidgetRemote_create(&phidm->networkInfo)))
+ {
+ CThread_mutex_unlock(&phidm->openCloseLock);
+ return result;
+ }
+
+ if(password) {
+ if (strlen(password) > 255)
+ {
+ CThread_mutex_unlock(&phidm->openCloseLock);
+ return EPHIDGET_INVALIDARG;
+ }
+ if (!(phidm->networkInfo->password = strdup(password)))
+ {
+ CThread_mutex_unlock(&phidm->openCloseLock);
+ return EPHIDGET_NOMEMORY;
+ }
+ }
+
+ snprintf(portString, sizeof(portString), "%d", port);
+ if(!(phidm->networkInfo->requested_port = strdup(portString)))
+ {
+ CThread_mutex_unlock(&phidm->openCloseLock);
+ return EPHIDGET_NOMEMORY;
+ }
+ if(!(phidm->networkInfo->requested_address = strdup(address)))
+ {
+ CThread_mutex_unlock(&phidm->openCloseLock);
+ return EPHIDGET_NOMEMORY;
+ }
+
+ phidm->state = PHIDGETMANAGER_ACTIVE;
+
+ initialize_locks();
+
+ CPhidget_setStatusFlag(&phidm->status, PHIDGET_REMOTE_FLAG, &phidm->lock);
+ CPhidget_setStatusFlag(&phidm->status, PHIDGET_OPENED_FLAG, &phidm->lock);
+
+ result = RegisterRemoteManager(phidm);
+
+ CThread_mutex_unlock(&phidm->openCloseLock);
+
+ return result;
+}
+
+int CCONV CPhidgetManager_openRemote(CPhidgetManagerHandle phidm, const char *serverID, const char *password)
+{
+#ifdef USE_ZEROCONF
+ int result = EPHIDGET_OK;
+
+ CThread_mutex_lock(&phidm->openCloseLock);
+
+ initialize_locks();
+
+ if((result = InitializeZeroconf()))
+ {
+ CThread_mutex_unlock(&phidm->openCloseLock);
+ if(result == EPHIDGET_TRYAGAIN)
+ return EPHIDGET_TIMEOUT;
+ return EPHIDGET_UNSUPPORTED;
+ }
+
+ if (CPhidget_statusFlagIsSet(phidm->status, PHIDGET_OPENED_FLAG))
+ {
+ LOG(PHIDGET_LOG_WARNING, "Open was called on an already opened Manager handle.");
+ CThread_mutex_unlock(&phidm->openCloseLock);
+ return EPHIDGET_OK;
+ }
+
+ if((result = CPhidgetRemote_create(&phidm->networkInfo)))
+ {
+ CThread_mutex_unlock(&phidm->openCloseLock);
+ return result;
+ }
+
+ if(password) {
+ if (strlen(password) > 255)
+ {
+ CThread_mutex_unlock(&phidm->openCloseLock);
+ return EPHIDGET_INVALIDARG;
+ }
+ if (!(phidm->networkInfo->password = strdup(password)))
+ {
+ CThread_mutex_unlock(&phidm->openCloseLock);
+ return EPHIDGET_NOMEMORY;
+ }
+ }
+ if(serverID)
+ {
+ if (!(phidm->networkInfo->requested_serverID = strdup(serverID)))
+ {
+ CThread_mutex_unlock(&phidm->openCloseLock);
+ return EPHIDGET_NOMEMORY;
+ }
+ }
+
+ phidm->networkInfo->mdns = PTRUE;
+
+ //we're not connecting to anything, so - always active :)
+ phidm->state = PHIDGETMANAGER_ACTIVATING;
+
+ CPhidget_setStatusFlag(&phidm->status, PHIDGET_REMOTE_FLAG, &phidm->lock);
+ CPhidget_setStatusFlag(&phidm->status, PHIDGET_OPENED_FLAG, &phidm->lock);
+
+ result = RegisterRemoteManager(phidm);
+ if(!result)
+ {
+ CPhidgetListHandle trav;
+ CThread_mutex_lock(&zeroconfPhidgetsLock);
+ CThread_mutex_lock(&activeRemoteManagersLock);
+ for (trav=zeroconfPhidgets; trav; trav = trav->next)
+ {
+ if (phidm->fptrAttachChange)
+ phidm->fptrAttachChange((CPhidgetHandle)trav->phid, phidm->fptrAttachChangeptr);
+ }
+ phidm->state = PHIDGETMANAGER_ACTIVE;
+ CThread_mutex_unlock(&activeRemoteManagersLock);
+ CThread_mutex_unlock(&zeroconfPhidgetsLock);
+ }
+
+ CThread_mutex_unlock(&phidm->openCloseLock);
+ return result;
+#else
+ return EPHIDGET_UNSUPPORTED;
+#endif
+}
+
+int CCONV CPhidgetDictionary_openRemoteIP(CPhidgetDictionaryHandle dict, const char *address, int port, const char *password)
+{
+ int result = EPHIDGET_OK;
+ char portString[6];
+ TESTPTRS(dict,address)
+
+ CThread_mutex_lock(&dict->openCloseLock);
+ if (CPhidget_statusFlagIsSet(dict->status, PHIDGET_OPENED_FLAG))
+ {
+ LOG(PHIDGET_LOG_WARNING, "Open was called on an already opened Dictionary handle.");
+ CThread_mutex_unlock(&dict->openCloseLock);
+ return EPHIDGET_OK;
+ }
+
+ if((result = CPhidgetRemote_create(&dict->networkInfo)) != EPHIDGET_OK)
+ goto fail;
+
+ snprintf(portString, sizeof(portString), "%d", port);
+
+ if((dict->networkInfo->requested_port = strdup(portString)) == NULL
+ || (dict->networkInfo->requested_address = strdup(address)) == NULL)
+ {
+ result = EPHIDGET_NOMEMORY;
+ goto fail;
+ }
+
+ if(password)
+ {
+ if (strlen(password) > 255)
+ {
+ result = EPHIDGET_INVALIDARG;
+ goto fail;
+ }
+ if ((dict->networkInfo->password = strdup(password)) == NULL)
+ {
+ result = EPHIDGET_NOMEMORY;
+ goto fail;
+ }
+ }
+ else
+ {
+ dict->networkInfo->password = NULL;
+ }
+
+ initialize_locks();
+
+ CPhidget_setStatusFlag(&dict->status, PHIDGET_REMOTE_FLAG, &dict->lock);
+ CPhidget_setStatusFlag(&dict->status, PHIDGET_OPENED_FLAG, &dict->lock);
+
+ if((result = RegisterRemoteDictionary(dict)) != EPHIDGET_OK)
+ {
+ goto fail;
+ }
+
+ CThread_mutex_unlock(&dict->openCloseLock);
+
+ return EPHIDGET_OK;
+
+fail:
+ //This will free any memory allocated in this function.
+ CPhidget_clearStatusFlag(&dict->status, PHIDGET_REMOTE_FLAG, &dict->lock);
+ CPhidget_clearStatusFlag(&dict->status, PHIDGET_OPENED_FLAG, &dict->lock);
+ CPhidgetRemote_free(dict->networkInfo); dict->networkInfo = NULL;
+ CThread_mutex_unlock(&dict->openCloseLock);
+ return result;
+}
+
+/*
+ * dict needs to be valid - should be in opened state
+ * serverID can be NULL
+ * password can be NULL
+ */
+int CCONV CPhidgetDictionary_openRemote(CPhidgetDictionaryHandle dict, const char *serverID, const char *password)
+{
+#ifdef USE_ZEROCONF
+ int result = EPHIDGET_OK;
+ TESTPTR(dict)
+
+ CThread_mutex_lock(&dict->openCloseLock);
+
+ initialize_locks();
+
+ if((result = InitializeZeroconf()))
+ {
+ if(result == EPHIDGET_TRYAGAIN)
+ result = EPHIDGET_TIMEOUT;
+ else
+ result = EPHIDGET_UNSUPPORTED;
+ goto fail;
+ }
+
+ if (CPhidget_statusFlagIsSet(dict->status, PHIDGET_OPENED_FLAG))
+ {
+ LOG(PHIDGET_LOG_WARNING, "Open was called on an already opened Dictionary handle.");
+ CThread_mutex_unlock(&dict->openCloseLock);
+ return EPHIDGET_OK;
+ }
+
+ if((result = CPhidgetRemote_create(&dict->networkInfo)) != EPHIDGET_OK)
+ goto fail;
+
+ if(password)
+ {
+ if (strlen(password) > 255)
+ {
+ result = EPHIDGET_INVALIDARG;
+ goto fail;
+ }
+ if ((dict->networkInfo->password = strdup(password)) == NULL)
+ {
+ result = EPHIDGET_NOMEMORY;
+ goto fail;
+ }
+ }
+ if(serverID)
+ {
+ if ((dict->networkInfo->requested_serverID = strdup(serverID)) == NULL)
+ {
+ result = EPHIDGET_NOMEMORY;
+ goto fail;
+ }
+ }
+
+ dict->networkInfo->mdns = PTRUE;
+
+ CPhidget_setStatusFlag(&dict->status, PHIDGET_REMOTE_FLAG, &dict->lock);
+ CPhidget_setStatusFlag(&dict->status, PHIDGET_OPENED_FLAG, &dict->lock);
+
+ if((result = RegisterRemoteDictionary(dict)) != EPHIDGET_OK)
+ {
+ goto fail;
+ }
+
+ CThread_mutex_unlock(&dict->openCloseLock);
+ return EPHIDGET_OK;
+
+fail:
+ //This will free any memory allocated in this function.
+ CPhidget_clearStatusFlag(&dict->status, PHIDGET_REMOTE_FLAG, &dict->lock);
+ CPhidget_clearStatusFlag(&dict->status, PHIDGET_OPENED_FLAG, &dict->lock);
+ CPhidgetRemote_free(dict->networkInfo); dict->networkInfo = NULL;
+ CThread_mutex_unlock(&dict->openCloseLock);
+ return result;
+#else
+ return EPHIDGET_UNSUPPORTED;
+#endif
+}
+
+int CCONV CPhidgetSBCManager_start(CPhidgetSBCManagerHandle sbcm)
+{
+#ifdef USE_ZEROCONF
+ int result = EPHIDGET_OK;
+
+ initialize_locks();
+
+ if((result = InitializeZeroconf()))
+ {
+ if(result == EPHIDGET_TRYAGAIN)
+ return EPHIDGET_TIMEOUT;
+ return EPHIDGET_UNSUPPORTED;
+ }
+
+ sbcm->mdns = PTRUE;
+
+ //we're not connecting to anything, so - always active :)
+ sbcm->state = PHIDGETMANAGER_ACTIVE;
+
+ result = RegisterSBCManager(sbcm);
+ if(!result)
+ {
+ CPhidgetSBCListHandle trav;
+ CThread_mutex_lock(&zeroconfSBCsLock);
+ CThread_mutex_lock(&activeSBCManagersLock);
+ for (trav=zeroconfSBCs; trav; trav = trav->next)
+ {
+ if (sbcm->fptrAttachChange)
+ sbcm->fptrAttachChange((CPhidgetSBCHandle)trav->sbc, sbcm->fptrAttachChangeptr);
+ }
+ CThread_mutex_unlock(&activeSBCManagersLock);
+ CThread_mutex_unlock(&zeroconfSBCsLock);
+ }
+
+ return result;
+#else
+ return EPHIDGET_UNSUPPORTED;
+#endif
+}
diff --git a/cthread.c b/cthread.c
new file mode 100644
index 0000000..4ab5e8a
--- /dev/null
+++ b/cthread.c
@@ -0,0 +1,668 @@
+#include <assert.h>
+#include "stdafx.h"
+#include "cphidget.h"
+#include "cphidgetmanager.h"
+#include "cusb.h"
+#include "cphidgetlist.h"
+
+CThread_func_return_t CentralThreadFunction(CThread_func_arg_t arg);
+
+static CThread CentralThread;
+static int checkForDevicesEventInitialized = PFALSE;
+static EVENT checkForDevicesEvent;
+
+/* used by OSX to pause traffic during sleep */
+int pause_usb_traffic = PFALSE;
+int usb_write_paused = PFALSE;
+int usb_read_paused = PFALSE;
+
+#ifdef _MACOSX
+void macPeriodicTimerFunction(CFRunLoopTimerRef timer, void *Handle);
+void macFindActiveDevicesSource(void *nothing);
+CFRunLoopTimerRef timer = NULL;
+CFRunLoopSourceRef findActiveDevicesSource = NULL;
+#endif
+
+int
+StartCentralThread()
+{
+
+#ifdef _WINDOWS
+ if (CentralThread.m_ThreadHandle) {
+ int threadStatus = 0;
+ int result = 0;
+ result = GetExitCodeThread(CentralThread.m_ThreadHandle,
+ (LPDWORD)&threadStatus);
+ if (result) {
+ if (threadStatus != STILL_ACTIVE) {
+ CloseHandle(CentralThread.m_ThreadHandle);
+ CentralThread.m_ThreadHandle = 0;
+ }
+ }
+ }
+#endif
+
+ if(checkForDevicesEventInitialized == PFALSE)
+ {
+ checkForDevicesEventInitialized = PTRUE;
+ CThread_create_event(&checkForDevicesEvent);
+ }
+
+#ifdef _MACOSX
+ if(findActiveDevicesSource == NULL)
+ {
+ CFRunLoopSourceContext sourceContext = {0};
+ sourceContext.perform = macFindActiveDevicesSource;
+ findActiveDevicesSource = CFRunLoopSourceCreate(kCFAllocatorDefault, 0, &sourceContext);
+ }
+ if(timer == NULL)
+ timer = CFRunLoopTimerCreate(kCFAllocatorDefault, 0, 0.250, 0, 0, macPeriodicTimerFunction, NULL);
+#endif
+
+ //start the thread
+ if (!CentralThread.m_ThreadHandle || CentralThread.thread_status == FALSE)
+ {
+#ifdef _MACOSX
+ CentralThread.macInitDone = PFALSE;
+#endif
+ CThread_reset_event(&checkForDevicesEvent);
+
+ if (CThread_create(&CentralThread, CentralThreadFunction, 0))
+ return EPHIDGET_UNEXPECTED;
+ CentralThread.thread_status = TRUE;
+ }
+ //if it was already running, signal it to check for device matches NOW
+ else {
+#ifdef _MACOSX
+ //make sure mac thread stuff is initialized
+ while(!CentralThread.macInitDone)
+ SLEEP(10);
+ //run findActiveDevices in the context of the central thread
+ CFRunLoopSourceSignal(findActiveDevicesSource);
+ CFRunLoopWakeUp(CentralThread.runLoop);
+#else
+ //signal thread to poll and findActiveDevices
+ CThread_set_event(&checkForDevicesEvent);
+#endif
+ }
+ return EPHIDGET_OK;
+}
+
+int
+JoinCentralThread()
+{
+ if(CentralThread.m_ThreadHandle && !CThread_is_my_thread(CentralThread))
+ {
+#ifdef _MACOSX
+ while(!CentralThread.macInitDone)
+ SLEEP(10);
+ CPhidgetManager_teardownNotifications();
+
+ CFRunLoopRemoveTimer(CentralThread.runLoop, timer, kCFRunLoopDefaultMode);
+ CFRunLoopRemoveSource(CentralThread.runLoop, findActiveDevicesSource, kCFRunLoopDefaultMode);
+
+ CFRunLoopStop(CentralThread.runLoop);
+
+ CentralThread.macInitDone = PFALSE;
+#endif
+ CThread_join(&CentralThread);
+ CentralThread.m_ThreadHandle = 0;
+ }
+ return EPHIDGET_OK;
+}
+
+/*
+ * registers a device to recieve events and be polled by the central
+ * thread This needs to start the central thread if it's not yet
+ * running.
+*/
+int
+RegisterLocalDevice(CPhidgetHandle phid)
+{
+ int result;
+
+ TESTPTR(phid)
+
+ if(!phidgetLocksInitialized)
+ {
+ CThread_mutex_init(&activeDevicesLock);
+ CThread_mutex_init(&attachedDevicesLock);
+ phidgetLocksInitialized = PTRUE;
+ }
+ CThread_mutex_lock(&activeDevicesLock);
+
+ if(phid->specificDevice == PHIDGETOPEN_SERIAL || phid->specificDevice == PHIDGETOPEN_LABEL)
+ result = CList_addToList((CListHandle *)&ActiveDevices, phid, CPhidget_areEqual);
+ else
+ result = CList_addToList((CListHandle *)&ActiveDevices, phid, CPhidgetHandle_areEqual);
+
+ if (result)
+ {
+ CThread_mutex_unlock(&activeDevicesLock);
+ return result;
+ }
+ CThread_mutex_unlock(&activeDevicesLock);
+
+ result = StartCentralThread();
+ return result;
+}
+
+#ifdef _MACOSX
+//this is run every 250ms from the CentralThread runLoop
+void macPeriodicTimerFunction(CFRunLoopTimerRef timer, void *Handle) {
+ CPhidgetList *trav = 0;
+
+ //looks for any devices that have set PHIDGET_USB_ERROR_FLAG and reenumerate them
+ CThread_mutex_lock(&activeDevicesLock);
+ for (trav=ActiveDevices; trav; trav = trav->next)
+ {
+ if(CPhidget_statusFlagIsSet(trav->phid->status, PHIDGET_ATTACHED_FLAG))
+ {
+ if(CPhidget_statusFlagIsSet(trav->phid->status, PHIDGET_USB_ERROR_FLAG))
+ {
+ LOG(PHIDGET_LOG_WARNING,"PHIDGET_USB_ERROR_FLAG is set - cycling device through a reenumeration.");
+ reenumerateDevice(trav->phid);
+ }
+ }
+ }
+ CThread_mutex_unlock(&activeDevicesLock);
+
+ //need to always keep checking because a device could be opened by another app
+ //and we want to notice when it becomes accessible.
+ if(ActiveDevices) {
+ findActiveDevices(); //this looks for attached active devices and opens them
+ }
+
+ return;
+}
+
+//This is run when a new Phidget is registered when the CentralThread is already running
+void macFindActiveDevicesSource(void *nothing) {
+ if(ActiveDevices) {
+ findActiveDevices(); //this looks for attached active devices and opens them
+ }
+ return;
+}
+#endif
+
+//The central thread should stop itself when there are no more active devices...?
+//Or we can stop it in unregisterlocaldevice
+
+CThread_func_return_t CentralThreadFunction(CThread_func_arg_t lpdwParam)
+{
+#ifdef _MACOSX
+ CentralThread.runLoop = CFRunLoopGetCurrent();
+
+ //setup notifications of Phidget attach/detach
+ CPhidgetManager_setupNotifications(CentralThread.runLoop);
+
+ CFRunLoopAddTimer(CentralThread.runLoop, timer, kCFRunLoopDefaultMode);
+ CFRunLoopAddSource(CentralThread.runLoop, findActiveDevicesSource, kCFRunLoopDefaultMode);
+
+ CentralThread.macInitDone = PTRUE;
+
+ //start run loop - note that this blocks until JoinCentralThread() is called.
+ CFRunLoopRun();
+#else
+ //loop as long as there are active devices, or a phidget manager
+ while(ActiveDevices || ActivePhidgetManagers) {
+ CPhidgetManager_poll(); //this will update the list, as well as sending out attach and detach events
+ findActiveDevices(); //this looks for attached active devices and opens them
+
+ //Wait for signal of newly registered device, or 250ms
+ //we don't really care about the reason so we don't check the return value
+ CThread_wait_on_event(&checkForDevicesEvent, 250);
+ CThread_reset_event(&checkForDevicesEvent);
+ }
+#endif
+
+ //if we actually get here, it means there are no active devices, and no phidgetmanagers, so free up the
+ //last of the memory we are using, and exit the thread...
+ CThread_mutex_lock(&attachedDevicesLock);
+ CList_emptyList((CListHandle *)&AttachedDevices, TRUE, CPhidget_free);
+ CThread_mutex_unlock(&attachedDevicesLock);
+
+ LOG(PHIDGET_LOG_INFO,"Central Thread exiting");
+
+ CentralThread.thread_status = FALSE;
+ return EPHIDGET_OK;
+}
+
+//The read thread
+CThread_func_return_t ReadThreadFunction(CThread_func_arg_t lpdwParam)
+{
+ CPhidgetHandle phid = (CPhidgetHandle)lpdwParam;
+ int result = EPHIDGET_OK;
+ LOG(PHIDGET_LOG_INFO,"ReadThread running");
+
+ if (!phid)
+ {
+ LOG(PHIDGET_LOG_ERROR,"ReadThread exiting - Invalid device handle");
+ return (CThread_func_return_t)EPHIDGET_INVALIDARG;
+ }
+
+ //quit read thread if it's not needed
+ switch(phid->deviceID)
+ {
+ case PHIDCLASS_SERVO:
+ if(phid->deviceVersion < 313)
+ goto exit_not_needed;
+ break;
+ case PHIDCLASS_INTERFACEKIT:
+ if(phid->deviceIDSpec == PHIDID_INTERFACEKIT_0_0_4 && phid->deviceVersion < 704)
+ goto exit_not_needed;
+ break;
+ case PHIDCLASS_LED:
+ if(phid->deviceIDSpec == PHIDID_LED_64)
+ goto exit_not_needed;
+ break;
+ case PHIDCLASS_TEXTLCD:
+ if(phid->deviceIDSpec != PHIDID_TEXTLCD_ADAPTER)
+ goto exit_not_needed;
+ break;
+ case PHIDCLASS_TEXTLED:
+exit_not_needed:
+ LOG(PHIDGET_LOG_INFO,"ReadThread exiting normally (Not Needed for this device)");
+ goto exit;
+ default:
+ break;
+ }
+
+ while (CPhidget_statusFlagIsSet(phid->status, PHIDGET_ATTACHED_FLAG))
+ {
+ if(pause_usb_traffic)
+ {
+ usb_read_paused = PTRUE;
+ SLEEP(20);
+ continue;
+ }
+ else
+ usb_read_paused = PFALSE;
+
+ result=CPhidget_read(phid);
+
+ switch(result)
+ {
+ case EPHIDGET_OK:
+ case EPHIDGET_TRYAGAIN:
+ break;
+ case EPHIDGET_NOTATTACHED:
+ LOG(PHIDGET_LOG_INFO,"ReadThread exiting normally (Phidget detach detected in CPhidget_read)");
+ goto exit;
+ case EPHIDGET_INTERRUPTED:
+ LOG(PHIDGET_LOG_INFO,"ReadThread exiting normally (signaled by CPhidget_close)");
+ goto exit;
+ case EPHIDGET_TIMEOUT:
+ //Set the error flag for devices that should never have a USB timeout, then exit
+ //continue for devices where it is ok
+ switch(phid->deviceID)
+ {
+ case PHIDCLASS_INTERFACEKIT:
+ switch(phid->deviceIDSpec)
+ {
+ case PHIDID_INTERFACEKIT_0_16_16:
+ if(phid->deviceVersion >= 601)
+ goto timeout_not_ok;
+ else
+ goto timeout_ok;
+ case PHIDID_INTERFACEKIT_0_8_8_w_LCD:
+ goto timeout_ok;
+ default:
+ goto timeout_not_ok;
+ }
+ case PHIDCLASS_RFID:
+ if(phid->deviceVersion >= 201)
+ goto timeout_not_ok;
+ else
+ goto timeout_ok;
+ case PHIDCLASS_ENCODER:
+ if(phid->deviceIDSpec == PHIDID_ENCODER_HS_4ENCODER_4INPUT)
+ goto timeout_not_ok;
+ else
+ goto timeout_ok;
+ case PHIDCLASS_GENERIC:
+ goto timeout_ok;
+ default:
+ goto timeout_not_ok;
+ }
+ timeout_not_ok:
+ CPhidget_setStatusFlag(&phid->status, PHIDGET_USB_ERROR_FLAG, &phid->lock);
+ LOG(PHIDGET_LOG_ERROR,"ReadThread exiting - unexpected timeout (could be an ESD event)");
+ goto exit;
+ timeout_ok:
+ LOG(PHIDGET_LOG_VERBOSE,"CUSBReadPacket expected time out"); //verbose because it could happen a LOT
+ break;
+ case EPHIDGET_UNEXPECTED:
+ default:
+ LOG(PHIDGET_LOG_ERROR,"ReadThread exiting - CPhidget_read returned : %d",result);
+ CPhidget_setStatusFlag(&phid->status, PHIDGET_USB_ERROR_FLAG, &phid->lock);
+ goto exit;
+ }
+ }
+
+ LOG(PHIDGET_LOG_INFO,"ReadThread exiting normally (Phidget detached)");
+exit:
+ phid->readThread.thread_status = FALSE;
+ return (CThread_func_return_t)(size_t)result;
+}
+
+//The write thread
+CThread_func_return_t WriteThreadFunction(CThread_func_arg_t lpdwParam)
+{
+ CPhidgetHandle phid = (CPhidgetHandle)lpdwParam;
+ int result = EPHIDGET_OK, wait_return = 0;
+ LOG(PHIDGET_LOG_INFO,"WriteThread running");
+
+ if (!phid)
+ {
+ LOG(PHIDGET_LOG_ERROR,"WriteThread exiting - Invalid device handle");
+ return (CThread_func_return_t)EPHIDGET_INVALIDARG;
+ }
+
+ //quit write thread if it's not needed
+ switch(phid->deviceID)
+ {
+ case PHIDCLASS_INTERFACEKIT:
+ if(phid->deviceIDSpec == PHIDID_LINEAR_TOUCH
+ || phid->deviceIDSpec == PHIDID_ROTARY_TOUCH)
+ goto exit_not_needed;
+ break;
+ case PHIDCLASS_RFID:
+ if(phid->deviceIDSpec == PHIDID_RFID)
+ goto exit_not_needed;
+ break;
+ case PHIDCLASS_ENCODER:
+ if(phid->deviceIDSpec == PHIDID_ENCODER_1ENCODER_1INPUT
+ || phid->deviceIDSpec == PHIDID_ENCODER_HS_1ENCODER)
+ goto exit_not_needed;
+ break;
+ case PHIDCLASS_ACCELEROMETER:
+ case PHIDCLASS_TEMPERATURESENSOR:
+ case PHIDCLASS_PHSENSOR:
+ case PHIDCLASS_WEIGHTSENSOR:
+exit_not_needed:
+ LOG(PHIDGET_LOG_INFO,"WriteThread exiting normally (Not Needed for this device)");
+ goto exit;
+ default:
+ break;
+ }
+
+ while (CPhidget_statusFlagIsSet(phid->status, PHIDGET_ATTACHED_FLAG))
+ {
+ //if awdc_enabled is true, then we timeout in 200ms and do a write, otherwise no timeout
+ wait_return = CThread_wait_on_event(&phid->writeAvailableEvent, 200);
+ switch (wait_return) {
+ case WAIT_TIMEOUT:
+ //putting this in the timeout so actual writes are not missed.
+ if(phid->writeStopFlag)
+ {
+ LOG(PHIDGET_LOG_INFO,"WriteThread exiting normally (signaled by writeStopFlag)");
+ goto exit;
+ }
+ if(!phid->awdc_enabled) //only fall through to writting out if awdc is set
+ break;
+ case WAIT_OBJECT_0: //writeAvailable
+ if(pause_usb_traffic)
+ {
+ usb_write_paused = PTRUE;
+ break;
+ }
+ else
+ usb_write_paused = PFALSE;
+
+ if((result = CPhidget_write(phid)))
+ {
+ switch(result)
+ {
+ case EPHIDGET_NOTATTACHED:
+ LOG(PHIDGET_LOG_INFO,"WriteThread exiting normally (Phidget detach detected in CPhidget_write)");
+ break;
+ case EPHIDGET_INTERRUPTED:
+ LOG(PHIDGET_LOG_INFO,"WriteThread exiting normally (signaled by CPhidget_close)");
+ break;
+ case EPHIDGET_TIMEOUT:
+ LOG(PHIDGET_LOG_ERROR,"WriteThread exiting - unexpected timeout (could be an ESD event)");
+ CPhidget_setStatusFlag(&phid->status, PHIDGET_USB_ERROR_FLAG, &phid->lock);
+ break;
+ case EPHIDGET_UNEXPECTED:
+ default:
+ LOG(PHIDGET_LOG_ERROR,"WriteThread exiting - CPhidget_write returned : %d",result);
+ CPhidget_setStatusFlag(&phid->status, PHIDGET_USB_ERROR_FLAG, &phid->lock);
+ break;
+ }
+ goto exit;
+ }
+ break;
+ default:
+ LOG(PHIDGET_LOG_ERROR,"WriteThread exiting - wait on phid->writeAvailableEvent failed");
+ CPhidget_setStatusFlag(&phid->status, PHIDGET_USB_ERROR_FLAG, &phid->lock);
+ result = EPHIDGET_UNEXPECTED;
+ goto exit;
+ }
+ }
+ LOG(PHIDGET_LOG_INFO,"WriteThread exiting normally (Phidget detached)");
+
+exit:
+ phid->writeStopFlag = FALSE;
+ phid->writeThread.thread_status = FALSE;
+ return (CThread_func_return_t)(size_t)result;
+}
+
+int
+CThread_create(CThread *cp, CThread_func_t fp, CThread_func_arg_t arg)
+{
+#ifdef _WINDOWS
+ cp->m_ThreadHandle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)fp, arg, 0, &cp->m_ThreadIdentifier);
+ if(cp->m_ThreadHandle) return EPHIDGET_OK;
+ else return GetLastError();
+#else
+ return pthread_create(&cp->m_ThreadHandle, NULL, fp, arg);
+#endif
+}
+
+int
+CThread_create_detached(CThread *cp, CThread_func_t fp, CThread_func_arg_t arg)
+{
+#ifdef _WINDOWS
+ cp->m_ThreadHandle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)fp, arg, 0, &cp->m_ThreadIdentifier);
+ if(cp->m_ThreadHandle) return EPHIDGET_OK;
+ else return GetLastError();
+#else
+ pthread_attr_t attr;
+ int err;
+ if((err = pthread_attr_init(&attr)) == 0)
+ {
+ if((err = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED)) == 0)
+ {
+ return pthread_create(&cp->m_ThreadHandle, &attr, fp, arg);
+ }
+ else
+ {
+ LOG(PHIDGET_LOG_ERROR, "pthread_attr_setdetachstate failed with error: %d",err);
+ return err;
+ }
+ }
+ else
+ {
+ LOG(PHIDGET_LOG_ERROR, "pthread_attr_init failed with error: %d",err);
+ return err;
+ }
+#endif
+}
+
+int
+CThread_is_my_thread(CThread cp)
+{
+#ifdef _WINDOWS
+ return (cp.m_ThreadIdentifier == GetCurrentThreadId());
+#else
+ return pthread_equal(cp.m_ThreadHandle, pthread_self());
+#endif
+}
+
+void
+CThread_join(CThread *cp)
+{
+#ifdef _WINDOWS
+ DWORD ec;
+
+ while (GetExitCodeThread(cp->m_ThreadHandle, &ec) && ec == STILL_ACTIVE)
+ SLEEP(10);
+#else
+ if (cp->thread_status == TRUE)
+ pthread_join(cp->m_ThreadHandle, 0);
+#endif
+}
+
+/*void
+CThread_kill(CThread *cp)
+{
+#ifdef _WINDOWS
+ TerminateThread(cp->m_ThreadHandle, 0);
+#else
+ pthread_cancel(cp->m_ThreadHandle);
+#endif
+}*/
+
+int
+CThread_mutex_init(CThread_mutex_t *mp)
+{
+#ifdef _WINDOWS
+ InitializeCriticalSection(mp);
+ return 1;
+#else
+ return pthread_mutex_init(mp, NULL) == 0;
+#endif
+}
+
+int
+CThread_mutex_destroy(CThread_mutex_t *mp)
+{
+#ifdef _WINDOWS
+ DeleteCriticalSection(mp);
+ return 1;
+#else
+ return pthread_mutex_destroy(mp) == 0;
+#endif
+}
+
+void
+CThread_mutex_lock(CThread_mutex_t *mp)
+{
+#ifdef _WINDOWS
+ EnterCriticalSection(mp);
+#else
+ pthread_mutex_lock(mp);
+#endif
+}
+
+void
+CThread_mutex_unlock(CThread_mutex_t *mp)
+{
+#ifdef _WINDOWS
+ LeaveCriticalSection(mp);
+#else
+ pthread_mutex_unlock(mp);
+#endif
+}
+
+void CThread_create_event(EVENT *ev)
+{
+#ifdef _WINDOWS
+ *ev = CreateEvent(NULL, FALSE, FALSE, NULL);
+#else
+ pthread_mutex_init(&ev->mutex, NULL);
+ pthread_cond_init(&ev->condition, NULL);
+ ev->ready_to_go = PFALSE;
+#endif
+}
+
+int CThread_destroy_event(EVENT *ev)
+{
+#ifdef _WINDOWS
+ return CloseHandle(*ev);
+#else
+ if(pthread_mutex_destroy(&ev->mutex)) return 0;
+ if(pthread_cond_destroy(&ev->condition)) return 0;
+ return 1;
+#endif
+}
+
+int CThread_wait_on_event(EVENT *ev, EVENT_TIME time)
+{
+#ifdef _WINDOWS
+ return WaitForSingleObject(*ev, time);
+#else
+ int retval;
+ struct timespec timeout;
+ struct timeval now;
+
+ // Lock the mutex.
+ pthread_mutex_lock(&ev->mutex);
+
+ // If the predicate is already set, then the while loop is bypassed;
+ // otherwise, the thread sleeps until the predicate is set.
+ if(ev->ready_to_go == PFALSE)
+ {
+ if(time == INFINITE)
+ retval = pthread_cond_wait(&ev->condition, &ev->mutex);
+ else {
+ gettimeofday(&now,0);
+ timeout.tv_sec = now.tv_sec + time/1000;
+ timeout.tv_nsec = now.tv_usec*1000 + (time%1000 * 1000000);
+ if(timeout.tv_nsec >= 1000000000)
+ {
+ timeout.tv_sec++;
+ timeout.tv_nsec -= 1000000000;
+ }
+ retval = pthread_cond_timedwait(&ev->condition, &ev->mutex, &timeout);
+ }
+
+ switch(retval)
+ {
+ case ETIMEDOUT:
+ pthread_mutex_unlock(&ev->mutex);
+ return WAIT_TIMEOUT;
+ case 0:
+ pthread_mutex_unlock(&ev->mutex);
+ return WAIT_OBJECT_0;
+ case EINVAL:
+ pthread_mutex_unlock(&ev->mutex);
+ return WAIT_FAILED;
+ default:
+ pthread_mutex_unlock(&ev->mutex);
+ return WAIT_FAILED;
+ }
+ }
+ pthread_mutex_unlock(&ev->mutex);
+ return WAIT_OBJECT_0;
+#endif
+}
+
+void CThread_reset_event(EVENT *ev)
+{
+#ifdef _WINDOWS
+ ResetEvent(*ev);
+#else
+ // Reset the predicate and release the mutex.
+ pthread_mutex_lock(&ev->mutex);
+ ev->ready_to_go = PFALSE;
+ pthread_mutex_unlock(&ev->mutex);
+#endif
+}
+
+void CThread_set_event(EVENT *ev)
+{
+#ifdef _WINDOWS
+ SetEvent(*ev);
+#else
+ // At this point, there should be work for the other thread to do.
+ pthread_mutex_lock(&ev->mutex);
+ ev->ready_to_go = PTRUE;
+ // Signal the other thread to begin work.
+ pthread_cond_signal(&ev->condition);
+ pthread_mutex_unlock(&ev->mutex);
+
+#endif
+}
+
diff --git a/cthread.h b/cthread.h
new file mode 100644
index 0000000..c3af664
--- /dev/null
+++ b/cthread.h
@@ -0,0 +1,64 @@
+#ifndef __CTHREAD
+#define __CTHREAD
+
+#ifndef EXTERNALPROTO
+
+#ifdef _WINDOWS
+typedef void *CThread_thread_t;
+typedef DWORD CThread_func_return_t;
+typedef LPVOID CThread_func_arg_t;
+typedef CRITICAL_SECTION CThread_mutex_t;
+typedef HANDLE EVENT;
+typedef DWORD EVENT_TIME;
+#else
+
+typedef struct {
+ pthread_mutex_t mutex;
+ pthread_cond_t condition;
+ int ready_to_go;
+} UNIX_EVENT;
+
+typedef unsigned long EVENT_TIME;
+typedef UNIX_EVENT EVENT;
+typedef pthread_t CThread_thread_t;
+typedef void *CThread_func_return_t;
+typedef void *CThread_func_arg_t;
+typedef pthread_mutex_t CThread_mutex_t;
+#endif
+typedef CThread_func_return_t(* CThread_func_t)(CThread_func_arg_t);
+
+typedef struct {
+ CThread_thread_t m_ThreadHandle;
+ unsigned long m_ThreadIdentifier;
+ unsigned char thread_status;
+#ifdef _MACOSX
+ CFRunLoopRef runLoop;
+ unsigned char macInitDone;
+#endif
+} CThread;
+
+int CThread_create(CThread *cp, CThread_func_t fp, CThread_func_arg_t arg);
+int CThread_create_detached(CThread *cp, CThread_func_t fp, CThread_func_arg_t arg);
+void CThread_join(CThread *cp);
+//void CThread_kill(CThread *cp);
+int CThread_is_my_thread(CThread cp);
+int CThread_mutex_init(CThread_mutex_t *);
+int CThread_mutex_destroy(CThread_mutex_t *mp);
+void CThread_mutex_lock(CThread_mutex_t *mp);
+void CThread_mutex_unlock(CThread_mutex_t *mp);
+
+void CThread_set_event(EVENT *ev);
+void CThread_reset_event(EVENT *ev);
+int CThread_wait_on_event(EVENT *ev, EVENT_TIME time);
+void CThread_create_event(EVENT *ev);
+int CThread_destroy_event(EVENT *ev);
+
+int RegisterLocalDevice(CPhidgetHandle phid);
+int StartCentralThread();
+int JoinCentralThread();
+
+CThread_func_return_t ReadThreadFunction(CThread_func_arg_t arg);
+CThread_func_return_t WriteThreadFunction(CThread_func_arg_t arg);
+
+#endif
+#endif
diff --git a/cusb.h b/cusb.h
new file mode 100644
index 0000000..3c24a11
--- /dev/null
+++ b/cusb.h
@@ -0,0 +1,30 @@
+#ifndef __CUSB
+#define __CUSB
+
+#include "cphidget.h"
+#include "cphidgetlist.h"
+
+#ifndef EXTERNALPROTO
+int CUSBBuildList(CPhidgetList **curList);
+int CUSBOpenHandle(CPhidgetHandle phid);
+int CUSBCloseHandle(CPhidgetHandle phid);
+int CUSBSetLabel(CPhidgetHandle phid, char *buffer);
+void CUSBCleanup();
+int CUSBSetupNotifications();
+int CUSBRefreshLabelString(CPhidgetHandle phid);
+#if defined(_LINUX) && !defined(_ANDROID)
+int CUSBGetDeviceCapabilities(CPhidgetHandle phid, struct usb_device *dev,
+ struct usb_dev_handle *udev);
+#else
+int CUSBGetDeviceCapabilities(CPhidgetHandle phid, HANDLE DeviceHandle);
+#endif
+#endif
+
+PHIDGET21_API int CCONV CUSBReadPacket(CPhidgetHandle phidA, unsigned char *buffer);
+PHIDGET21_API int CCONV CUSBSendPacket(CPhidgetHandle phidA, unsigned char *buffer);
+
+#if defined(_ANDROID)
+#include "com_phidgets_usb_Manager.h"
+#endif
+
+#endif
diff --git a/depcomp b/depcomp
new file mode 100755
index 0000000..df8eea7
--- /dev/null
+++ b/depcomp
@@ -0,0 +1,630 @@
+#! /bin/sh
+# depcomp - compile a program generating dependencies as side-effects
+
+scriptversion=2009-04-28.21; # UTC
+
+# Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006, 2007, 2009 Free
+# Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Originally written by Alexandre Oliva <oliva@dcc.unicamp.br>.
+
+case $1 in
+ '')
+ echo "$0: No command. Try \`$0 --help' for more information." 1>&2
+ exit 1;
+ ;;
+ -h | --h*)
+ cat <<\EOF
+Usage: depcomp [--help] [--version] PROGRAM [ARGS]
+
+Run PROGRAMS ARGS to compile a file, generating dependencies
+as side-effects.
+
+Environment variables:
+ depmode Dependency tracking mode.
+ source Source file read by `PROGRAMS ARGS'.
+ object Object file output by `PROGRAMS ARGS'.
+ DEPDIR directory where to store dependencies.
+ depfile Dependency file to output.
+ tmpdepfile Temporary file to use when outputing dependencies.
+ libtool Whether libtool is used (yes/no).
+
+Report bugs to <bug-automake@gnu.org>.
+EOF
+ exit $?
+ ;;
+ -v | --v*)
+ echo "depcomp $scriptversion"
+ exit $?
+ ;;
+esac
+
+if test -z "$depmode" || test -z "$source" || test -z "$object"; then
+ echo "depcomp: Variables source, object and depmode must be set" 1>&2
+ exit 1
+fi
+
+# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po.
+depfile=${depfile-`echo "$object" |
+ sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`}
+tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
+
+rm -f "$tmpdepfile"
+
+# Some modes work just like other modes, but use different flags. We
+# parameterize here, but still list the modes in the big case below,
+# to make depend.m4 easier to write. Note that we *cannot* use a case
+# here, because this file can only contain one case statement.
+if test "$depmode" = hp; then
+ # HP compiler uses -M and no extra arg.
+ gccflag=-M
+ depmode=gcc
+fi
+
+if test "$depmode" = dashXmstdout; then
+ # This is just like dashmstdout with a different argument.
+ dashmflag=-xM
+ depmode=dashmstdout
+fi
+
+cygpath_u="cygpath -u -f -"
+if test "$depmode" = msvcmsys; then
+ # This is just like msvisualcpp but w/o cygpath translation.
+ # Just convert the backslash-escaped backslashes to single forward
+ # slashes to satisfy depend.m4
+ cygpath_u="sed s,\\\\\\\\,/,g"
+ depmode=msvisualcpp
+fi
+
+case "$depmode" in
+gcc3)
+## gcc 3 implements dependency tracking that does exactly what
+## we want. Yay! Note: for some reason libtool 1.4 doesn't like
+## it if -MD -MP comes after the -MF stuff. Hmm.
+## Unfortunately, FreeBSD c89 acceptance of flags depends upon
+## the command line argument order; so add the flags where they
+## appear in depend2.am. Note that the slowdown incurred here
+## affects only configure: in makefiles, %FASTDEP% shortcuts this.
+ for arg
+ do
+ case $arg in
+ -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;;
+ *) set fnord "$@" "$arg" ;;
+ esac
+ shift # fnord
+ shift # $arg
+ done
+ "$@"
+ stat=$?
+ if test $stat -eq 0; then :
+ else
+ rm -f "$tmpdepfile"
+ exit $stat
+ fi
+ mv "$tmpdepfile" "$depfile"
+ ;;
+
+gcc)
+## There are various ways to get dependency output from gcc. Here's
+## why we pick this rather obscure method:
+## - Don't want to use -MD because we'd like the dependencies to end
+## up in a subdir. Having to rename by hand is ugly.
+## (We might end up doing this anyway to support other compilers.)
+## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
+## -MM, not -M (despite what the docs say).
+## - Using -M directly means running the compiler twice (even worse
+## than renaming).
+ if test -z "$gccflag"; then
+ gccflag=-MD,
+ fi
+ "$@" -Wp,"$gccflag$tmpdepfile"
+ stat=$?
+ if test $stat -eq 0; then :
+ else
+ rm -f "$tmpdepfile"
+ exit $stat
+ fi
+ rm -f "$depfile"
+ echo "$object : \\" > "$depfile"
+ alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
+## The second -e expression handles DOS-style file names with drive letters.
+ sed -e 's/^[^:]*: / /' \
+ -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
+## This next piece of magic avoids the `deleted header file' problem.
+## The problem is that when a header file which appears in a .P file
+## is deleted, the dependency causes make to die (because there is
+## typically no way to rebuild the header). We avoid this by adding
+## dummy dependencies for each header file. Too bad gcc doesn't do
+## this for us directly.
+ tr ' ' '
+' < "$tmpdepfile" |
+## Some versions of gcc put a space before the `:'. On the theory
+## that the space means something, we add a space to the output as
+## well.
+## Some versions of the HPUX 10.20 sed can't process this invocation
+## correctly. Breaking it into two sed invocations is a workaround.
+ sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
+ rm -f "$tmpdepfile"
+ ;;
+
+hp)
+ # This case exists only to let depend.m4 do its work. It works by
+ # looking at the text of this script. This case will never be run,
+ # since it is checked for above.
+ exit 1
+ ;;
+
+sgi)
+ if test "$libtool" = yes; then
+ "$@" "-Wp,-MDupdate,$tmpdepfile"
+ else
+ "$@" -MDupdate "$tmpdepfile"
+ fi
+ stat=$?
+ if test $stat -eq 0; then :
+ else
+ rm -f "$tmpdepfile"
+ exit $stat
+ fi
+ rm -f "$depfile"
+
+ if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files
+ echo "$object : \\" > "$depfile"
+
+ # Clip off the initial element (the dependent). Don't try to be
+ # clever and replace this with sed code, as IRIX sed won't handle
+ # lines with more than a fixed number of characters (4096 in
+ # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines;
+ # the IRIX cc adds comments like `#:fec' to the end of the
+ # dependency line.
+ tr ' ' '
+' < "$tmpdepfile" \
+ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \
+ tr '
+' ' ' >> "$depfile"
+ echo >> "$depfile"
+
+ # The second pass generates a dummy entry for each header file.
+ tr ' ' '
+' < "$tmpdepfile" \
+ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
+ >> "$depfile"
+ else
+ # The sourcefile does not contain any dependencies, so just
+ # store a dummy comment line, to avoid errors with the Makefile
+ # "include basename.Plo" scheme.
+ echo "#dummy" > "$depfile"
+ fi
+ rm -f "$tmpdepfile"
+ ;;
+
+aix)
+ # The C for AIX Compiler uses -M and outputs the dependencies
+ # in a .u file. In older versions, this file always lives in the
+ # current directory. Also, the AIX compiler puts `$object:' at the
+ # start of each line; $object doesn't have directory information.
+ # Version 6 uses the directory in both cases.
+ dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
+ test "x$dir" = "x$object" && dir=
+ base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
+ if test "$libtool" = yes; then
+ tmpdepfile1=$dir$base.u
+ tmpdepfile2=$base.u
+ tmpdepfile3=$dir.libs/$base.u
+ "$@" -Wc,-M
+ else
+ tmpdepfile1=$dir$base.u
+ tmpdepfile2=$dir$base.u
+ tmpdepfile3=$dir$base.u
+ "$@" -M
+ fi
+ stat=$?
+
+ if test $stat -eq 0; then :
+ else
+ rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
+ exit $stat
+ fi
+
+ for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
+ do
+ test -f "$tmpdepfile" && break
+ done
+ if test -f "$tmpdepfile"; then
+ # Each line is of the form `foo.o: dependent.h'.
+ # Do two passes, one to just change these to
+ # `$object: dependent.h' and one to simply `dependent.h:'.
+ sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
+ # That's a tab and a space in the [].
+ sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
+ else
+ # The sourcefile does not contain any dependencies, so just
+ # store a dummy comment line, to avoid errors with the Makefile
+ # "include basename.Plo" scheme.
+ echo "#dummy" > "$depfile"
+ fi
+ rm -f "$tmpdepfile"
+ ;;
+
+icc)
+ # Intel's C compiler understands `-MD -MF file'. However on
+ # icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c
+ # ICC 7.0 will fill foo.d with something like
+ # foo.o: sub/foo.c
+ # foo.o: sub/foo.h
+ # which is wrong. We want:
+ # sub/foo.o: sub/foo.c
+ # sub/foo.o: sub/foo.h
+ # sub/foo.c:
+ # sub/foo.h:
+ # ICC 7.1 will output
+ # foo.o: sub/foo.c sub/foo.h
+ # and will wrap long lines using \ :
+ # foo.o: sub/foo.c ... \
+ # sub/foo.h ... \
+ # ...
+
+ "$@" -MD -MF "$tmpdepfile"
+ stat=$?
+ if test $stat -eq 0; then :
+ else
+ rm -f "$tmpdepfile"
+ exit $stat
+ fi
+ rm -f "$depfile"
+ # Each line is of the form `foo.o: dependent.h',
+ # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'.
+ # Do two passes, one to just change these to
+ # `$object: dependent.h' and one to simply `dependent.h:'.
+ sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile"
+ # Some versions of the HPUX 10.20 sed can't process this invocation
+ # correctly. Breaking it into two sed invocations is a workaround.
+ sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" |
+ sed -e 's/$/ :/' >> "$depfile"
+ rm -f "$tmpdepfile"
+ ;;
+
+hp2)
+ # The "hp" stanza above does not work with aCC (C++) and HP's ia64
+ # compilers, which have integrated preprocessors. The correct option
+ # to use with these is +Maked; it writes dependencies to a file named
+ # 'foo.d', which lands next to the object file, wherever that
+ # happens to be.
+ # Much of this is similar to the tru64 case; see comments there.
+ dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
+ test "x$dir" = "x$object" && dir=
+ base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
+ if test "$libtool" = yes; then
+ tmpdepfile1=$dir$base.d
+ tmpdepfile2=$dir.libs/$base.d
+ "$@" -Wc,+Maked
+ else
+ tmpdepfile1=$dir$base.d
+ tmpdepfile2=$dir$base.d
+ "$@" +Maked
+ fi
+ stat=$?
+ if test $stat -eq 0; then :
+ else
+ rm -f "$tmpdepfile1" "$tmpdepfile2"
+ exit $stat
+ fi
+
+ for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2"
+ do
+ test -f "$tmpdepfile" && break
+ done
+ if test -f "$tmpdepfile"; then
+ sed -e "s,^.*\.[a-z]*:,$object:," "$tmpdepfile" > "$depfile"
+ # Add `dependent.h:' lines.
+ sed -ne '2,${
+ s/^ *//
+ s/ \\*$//
+ s/$/:/
+ p
+ }' "$tmpdepfile" >> "$depfile"
+ else
+ echo "#dummy" > "$depfile"
+ fi
+ rm -f "$tmpdepfile" "$tmpdepfile2"
+ ;;
+
+tru64)
+ # The Tru64 compiler uses -MD to generate dependencies as a side
+ # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'.
+ # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
+ # dependencies in `foo.d' instead, so we check for that too.
+ # Subdirectories are respected.
+ dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
+ test "x$dir" = "x$object" && dir=
+ base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
+
+ if test "$libtool" = yes; then
+ # With Tru64 cc, shared objects can also be used to make a
+ # static library. This mechanism is used in libtool 1.4 series to
+ # handle both shared and static libraries in a single compilation.
+ # With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d.
+ #
+ # With libtool 1.5 this exception was removed, and libtool now
+ # generates 2 separate objects for the 2 libraries. These two
+ # compilations output dependencies in $dir.libs/$base.o.d and
+ # in $dir$base.o.d. We have to check for both files, because
+ # one of the two compilations can be disabled. We should prefer
+ # $dir$base.o.d over $dir.libs/$base.o.d because the latter is
+ # automatically cleaned when .libs/ is deleted, while ignoring
+ # the former would cause a distcleancheck panic.
+ tmpdepfile1=$dir.libs/$base.lo.d # libtool 1.4
+ tmpdepfile2=$dir$base.o.d # libtool 1.5
+ tmpdepfile3=$dir.libs/$base.o.d # libtool 1.5
+ tmpdepfile4=$dir.libs/$base.d # Compaq CCC V6.2-504
+ "$@" -Wc,-MD
+ else
+ tmpdepfile1=$dir$base.o.d
+ tmpdepfile2=$dir$base.d
+ tmpdepfile3=$dir$base.d
+ tmpdepfile4=$dir$base.d
+ "$@" -MD
+ fi
+
+ stat=$?
+ if test $stat -eq 0; then :
+ else
+ rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4"
+ exit $stat
+ fi
+
+ for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4"
+ do
+ test -f "$tmpdepfile" && break
+ done
+ if test -f "$tmpdepfile"; then
+ sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
+ # That's a tab and a space in the [].
+ sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
+ else
+ echo "#dummy" > "$depfile"
+ fi
+ rm -f "$tmpdepfile"
+ ;;
+
+#nosideeffect)
+ # This comment above is used by automake to tell side-effect
+ # dependency tracking mechanisms from slower ones.
+
+dashmstdout)
+ # Important note: in order to support this mode, a compiler *must*
+ # always write the preprocessed file to stdout, regardless of -o.
+ "$@" || exit $?
+
+ # Remove the call to Libtool.
+ if test "$libtool" = yes; then
+ while test "X$1" != 'X--mode=compile'; do
+ shift
+ done
+ shift
+ fi
+
+ # Remove `-o $object'.
+ IFS=" "
+ for arg
+ do
+ case $arg in
+ -o)
+ shift
+ ;;
+ $object)
+ shift
+ ;;
+ *)
+ set fnord "$@" "$arg"
+ shift # fnord
+ shift # $arg
+ ;;
+ esac
+ done
+
+ test -z "$dashmflag" && dashmflag=-M
+ # Require at least two characters before searching for `:'
+ # in the target name. This is to cope with DOS-style filenames:
+ # a dependency such as `c:/foo/bar' could be seen as target `c' otherwise.
+ "$@" $dashmflag |
+ sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile"
+ rm -f "$depfile"
+ cat < "$tmpdepfile" > "$depfile"
+ tr ' ' '
+' < "$tmpdepfile" | \
+## Some versions of the HPUX 10.20 sed can't process this invocation
+## correctly. Breaking it into two sed invocations is a workaround.
+ sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
+ rm -f "$tmpdepfile"
+ ;;
+
+dashXmstdout)
+ # This case only exists to satisfy depend.m4. It is never actually
+ # run, as this mode is specially recognized in the preamble.
+ exit 1
+ ;;
+
+makedepend)
+ "$@" || exit $?
+ # Remove any Libtool call
+ if test "$libtool" = yes; then
+ while test "X$1" != 'X--mode=compile'; do
+ shift
+ done
+ shift
+ fi
+ # X makedepend
+ shift
+ cleared=no eat=no
+ for arg
+ do
+ case $cleared in
+ no)
+ set ""; shift
+ cleared=yes ;;
+ esac
+ if test $eat = yes; then
+ eat=no
+ continue
+ fi
+ case "$arg" in
+ -D*|-I*)
+ set fnord "$@" "$arg"; shift ;;
+ # Strip any option that makedepend may not understand. Remove
+ # the object too, otherwise makedepend will parse it as a source file.
+ -arch)
+ eat=yes ;;
+ -*|$object)
+ ;;
+ *)
+ set fnord "$@" "$arg"; shift ;;
+ esac
+ done
+ obj_suffix=`echo "$object" | sed 's/^.*\././'`
+ touch "$tmpdepfile"
+ ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@"
+ rm -f "$depfile"
+ cat < "$tmpdepfile" > "$depfile"
+ sed '1,2d' "$tmpdepfile" | tr ' ' '
+' | \
+## Some versions of the HPUX 10.20 sed can't process this invocation
+## correctly. Breaking it into two sed invocations is a workaround.
+ sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
+ rm -f "$tmpdepfile" "$tmpdepfile".bak
+ ;;
+
+cpp)
+ # Important note: in order to support this mode, a compiler *must*
+ # always write the preprocessed file to stdout.
+ "$@" || exit $?
+
+ # Remove the call to Libtool.
+ if test "$libtool" = yes; then
+ while test "X$1" != 'X--mode=compile'; do
+ shift
+ done
+ shift
+ fi
+
+ # Remove `-o $object'.
+ IFS=" "
+ for arg
+ do
+ case $arg in
+ -o)
+ shift
+ ;;
+ $object)
+ shift
+ ;;
+ *)
+ set fnord "$@" "$arg"
+ shift # fnord
+ shift # $arg
+ ;;
+ esac
+ done
+
+ "$@" -E |
+ sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
+ -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' |
+ sed '$ s: \\$::' > "$tmpdepfile"
+ rm -f "$depfile"
+ echo "$object : \\" > "$depfile"
+ cat < "$tmpdepfile" >> "$depfile"
+ sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile"
+ rm -f "$tmpdepfile"
+ ;;
+
+msvisualcpp)
+ # Important note: in order to support this mode, a compiler *must*
+ # always write the preprocessed file to stdout.
+ "$@" || exit $?
+
+ # Remove the call to Libtool.
+ if test "$libtool" = yes; then
+ while test "X$1" != 'X--mode=compile'; do
+ shift
+ done
+ shift
+ fi
+
+ IFS=" "
+ for arg
+ do
+ case "$arg" in
+ -o)
+ shift
+ ;;
+ $object)
+ shift
+ ;;
+ "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI")
+ set fnord "$@"
+ shift
+ shift
+ ;;
+ *)
+ set fnord "$@" "$arg"
+ shift
+ shift
+ ;;
+ esac
+ done
+ "$@" -E 2>/dev/null |
+ sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile"
+ rm -f "$depfile"
+ echo "$object : \\" > "$depfile"
+ sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile"
+ echo " " >> "$depfile"
+ sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile"
+ rm -f "$tmpdepfile"
+ ;;
+
+msvcmsys)
+ # This case exists only to let depend.m4 do its work. It works by
+ # looking at the text of this script. This case will never be run,
+ # since it is checked for above.
+ exit 1
+ ;;
+
+none)
+ exec "$@"
+ ;;
+
+*)
+ echo "Unknown depmode $depmode" 1>&2
+ exit 1
+ ;;
+esac
+
+exit 0
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC"
+# time-stamp-end: "; # UTC"
+# End:
diff --git a/dict/pdict-impl.h b/dict/pdict-impl.h
new file mode 100644
index 0000000..2d1d92b
--- /dev/null
+++ b/dict/pdict-impl.h
@@ -0,0 +1,38 @@
+#ifndef _PDICT_IMPL_H_
+#define _PDICT_IMPL_H_
+
+#include "pdict.h"
+
+struct pdict_listener;
+
+/*
+ * Represents a dictionary entry.
+ * key and value strings, with a plist of listeners
+ */
+struct pdict_ent {
+ const char *pde_key;
+ const char *pde_val;
+ plist_node_t *pde_listeners;
+};
+
+typedef struct pdict_listener {
+ pdl_notify_func_t pdl_notify;
+ void *pdl_arg;
+} pdict_listener_t;
+
+typedef struct pdict_persistent_listener {
+ pdict_listener_t pdpl_l;
+ regex_t pdpl_regex;
+ int pdpl_new;
+} pdict_persistent_listener_t;
+
+/*
+ * A Phidget Dictionary
+ * contains a ptree of entries and a plist of persistent listeners
+ */
+struct pdict {
+ ptree_node_t *pd_ents;
+ plist_node_t *pd_persistent_listeners;
+};
+
+#endif
diff --git a/dict/pdict.c b/dict/pdict.c
new file mode 100644
index 0000000..04ac84c
--- /dev/null
+++ b/dict/pdict.c
@@ -0,0 +1,500 @@
+#include "../stdafx.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <regex.h>
+#if defined(_WINDOWS) && !defined(_CYGWIN)
+#include "wincompat.h"
+#endif
+#include "utils.h"
+#include "plist.h"
+#include "ptree.h"
+#include "pdict-impl.h"
+
+typedef struct pdict_ent pdict_ent_t;
+typedef int (*pdict_walk_int_func_t)(pdict_ent_t *pde, void *arg);
+
+static int _pdict_ent_add_persistent_change_listeners(pdict_t *pd,
+ pdict_ent_t *pde);
+static int _pdict_ent_add_persistent_change_listener(pdict_ent_t *pde,
+ pdict_persistent_listener_t *pl);
+static int _pdict_ent_remove_persistent_change_listener(pdict_ent_t *pde,
+ pdict_persistent_listener_t *pl);
+static void _pdict_ent_notify(pdict_ent_t *pde, int reason, const char *ov);
+static int _pdict_ent_add_change_listener(pdict_ent_t *pde,
+ pdl_notify_func_t notify, void *arg);
+static int _pdict_walk_int(pdict_t *pd, pdict_walk_int_func_t w, void *arg);
+static int _pdict_ent_remove_change_listener(pdict_ent_t *pde,
+ pdl_notify_func_t notify, void *a);
+
+pdict_t *
+pdict_alloc(void)
+{
+ pdict_t *pd;
+
+ if (!(pd = malloc(sizeof (*pd))))
+ return 0;
+ memset(pd, 0, sizeof (*pd));
+
+ return pd;
+}
+
+static int
+pdecmp(const void *sv, const void *dv)
+{
+ return strcmp(*(char **)sv, *(char **)dv);
+}
+
+static int
+pdict_ent_remove_change_listeners_cb(const void *v, const void *v0, void *a)
+{
+ free((void *)v); v = NULL;
+ return (1);
+}
+
+static int
+pdict_ent_remove_change_listeners(pdict_ent_t *pde)
+{
+ plist_walk(pde->pde_listeners, pdict_ent_remove_change_listeners_cb, 0);
+ plist_clear(&pde->pde_listeners);
+ return 1;
+}
+
+static int
+pdict_ent_listeners_copy_cb(const void *v, const void *v0, void *a)
+{
+ pdict_listener_t *pdl = (pdict_listener_t *)v;
+ pdict_ent_t *pde_ent_copy = a;
+
+ return _pdict_ent_add_change_listener(pde_ent_copy, pdl->pdl_notify, pdl->pdl_arg);
+}
+
+static void
+_pdict_ent_listeners_copy(pdict_ent_t *pde, pdict_ent_t *pde_copy)
+{
+ plist_walk(pde->pde_listeners, pdict_ent_listeners_copy_cb, pde_copy);
+}
+
+/*
+ * Sets or resets an entry to the dictionary, returning 0 on failure.
+ */
+int
+pdict_add(pdict_t *pd, const char *k, const char *v, const char **ovp)
+{
+ pdict_ent_t *n;
+ pdict_ent_t n_copy;
+ const char *ov;
+
+ if (!(k = strdup(k)))
+ return 0;
+ if (!(v = strdup(v))) {
+ free((void *)k); k = NULL;
+ return 0;
+ }
+ memset(&n_copy, 0, sizeof(pdict_ent_t));
+ if (ptree_contains((void *)&k, pd->pd_ents, pdecmp, (void *)&n)) {
+ free((void *)k); k = NULL;
+ ov = n->pde_val;
+ n->pde_val = v;
+
+ if (ovp)
+ *ovp = ov;
+ else {
+ free((void *)ov); ov = NULL;
+ }
+
+ //We copy n so that it's safe if it gets removed during a callback
+ if(n->pde_listeners)
+ {
+ n_copy.pde_key = strdup(n->pde_key);
+ n_copy.pde_val = strdup(n->pde_val);
+ _pdict_ent_listeners_copy(n, &n_copy);
+ _pdict_ent_notify(&n_copy, PDR_VALUE_CHANGED, ov);
+ pdict_ent_remove_change_listeners(&n_copy);
+ free((char *)n_copy.pde_key);
+ free((char *)n_copy.pde_val);
+ }
+ return 1;
+ }
+ if (!(n = malloc(sizeof (*n)))) {
+ free((void *)k); k = NULL;
+ free((void *)v); v = NULL;
+ return (0);
+ }
+ memset(n, 0, sizeof (*n));
+ n->pde_key = k;
+ n->pde_val = v;
+
+ //Add dict listeners to the dict entry object
+ if (!_pdict_ent_add_persistent_change_listeners(pd, n)) {
+ free((void *)k); k = NULL;
+ free((void *)v); v = NULL;
+ free(n); n = NULL;
+ return (0);
+ }
+ //Add the dict entry to the dict (replacing if there is a matching key).
+ if (!ptree_replace(n, &pd->pd_ents, pdecmp, NULL)) {
+ pdict_ent_remove_change_listeners(n);
+ free((void *)k); k = NULL;
+ free((void *)v); v = NULL;
+ free(n); n = NULL;
+ return (0);
+ }
+ //notify the listeners
+ if(n->pde_listeners)
+ {
+ n_copy.pde_key = strdup(n->pde_key);
+ n_copy.pde_val = strdup(n->pde_val);
+ _pdict_ent_listeners_copy(n, &n_copy);
+ _pdict_ent_notify(&n_copy, PDR_ENTRY_ADDED, n_copy.pde_val);
+ pdict_ent_remove_change_listeners(&n_copy);
+ free((char *)n_copy.pde_key);
+ free((char *)n_copy.pde_val);
+ }
+
+ if (ovp)
+ *ovp = NULL;
+
+ return 1;
+}
+
+int
+pdict_ent_remove(pdict_t *pd, const char *k, char **ovp)
+{
+ pdict_ent_t *n;
+
+ pu_log(PUL_VERB, 0, "Removing in key pdict_ent_remove: %s", k);
+
+ if (!ptree_remove((void *)&k, &pd->pd_ents, pdecmp, (void *)&n))
+ {
+ //pu_log(PUL_INFO, 0, "Failed to remove key in pdict_ent_remove: %s", k);
+ return 0;
+ }
+
+ _pdict_ent_notify(n, PDR_ENTRY_REMOVING, n->pde_val);
+
+ if (ovp)
+ *ovp = (char *)n->pde_val;
+ else {
+ free((void *)n->pde_val);
+ }
+ free((void *)n->pde_key);
+ pdict_ent_remove_change_listeners(n);
+ free(n);
+ return 1;
+}
+
+static int
+pdict_ent_remove_persistent_change_listener_cb(const void *pl, const void *v,
+ void *a)
+{
+ _pdict_ent_remove_persistent_change_listener((pdict_ent_t *)a,
+ (pdict_persistent_listener_t *)pl);
+ return 1;
+}
+
+static int
+pdict_ent_add_persistent_change_listener_cb(const void *lid, const void *pl,
+ void *a)
+{
+ return _pdict_ent_add_persistent_change_listener((pdict_ent_t *)a,
+ (pdict_persistent_listener_t *)pl);
+}
+
+static int
+_pdict_ent_add_persistent_change_listeners(pdict_t *pd, pdict_ent_t *pde)
+{
+ if (!plist_walk(pd->pd_persistent_listeners, pdict_ent_add_persistent_change_listener_cb, pde)) {
+ plist_walk(pd->pd_persistent_listeners, pdict_ent_remove_persistent_change_listener_cb, pde);
+ pu_log(PUL_WARN, 0, "Failed to add persistent change listener in _pdict_ent_add_persistent_change_listeners.");
+ return 0;
+ }
+ return 1;
+}
+
+static int
+pdict_ent_remove_persistent_change_listener_dcb(pdict_ent_t *pde, void *pl)
+{
+ return _pdict_ent_remove_persistent_change_listener(pde,
+ (pdict_persistent_listener_t *)pl);
+}
+
+static int
+pdict_ent_add_persistent_change_listener_dcb(pdict_ent_t *pde, void *pl)
+{
+ return _pdict_ent_add_persistent_change_listener(pde,
+ (pdict_persistent_listener_t *)pl);
+}
+
+static int
+_pdict_ent_add_persistent_change_listener(pdict_ent_t *pde,
+ pdict_persistent_listener_t *pdpl)
+{
+ int res;
+
+ if ((res = regexec(&pdpl->pdpl_regex, pde->pde_key, 0, NULL, 0)) != 0)
+ {
+ return res == REG_NOMATCH;
+ }
+ if (!_pdict_ent_add_change_listener(pde, pdpl->pdpl_l.pdl_notify, pdpl->pdpl_l.pdl_arg))
+ {
+ pu_log(PUL_WARN, 0, "Failed to add persistent change listener in _pdict_ent_add_persistent_change_listener.");
+ return 0;
+ }
+ if (pdpl->pdpl_new)
+ pdpl->pdpl_l.pdl_notify(pde->pde_key, pde->pde_val, PDR_CURRENT_VALUE, NULL, pdpl->pdpl_l.pdl_arg);
+ return 1;
+}
+
+static int
+_pdict_ent_remove_persistent_change_listener(pdict_ent_t *pde,
+ pdict_persistent_listener_t *pl)
+{
+ _pdict_ent_remove_change_listener(pde, pl->pdpl_l.pdl_notify,
+ pl->pdpl_l.pdl_arg);
+ return 1;
+}
+
+int
+pdict_remove_persistent_change_listener(pdict_t *pd, int id)
+{
+ pdict_persistent_listener_t *pdpl;
+
+ if (!plist_remove((void *)(size_t)id, &pd->pd_persistent_listeners, (void **)&pdpl) || !pdpl)
+ {
+ pu_log(PUL_WARN, 0, "Failed plist_remove in pdict_remove_persistent_change_listener.");
+ return 0;
+ }
+ if (!_pdict_walk_int(pd, pdict_ent_remove_persistent_change_listener_dcb, pdpl))
+ {
+ pu_log(PUL_WARN, 0, "Failed _pdict_walk_int in pdict_remove_persistent_change_listener.");
+ return 0;
+ }
+ regfree(&pdpl->pdpl_regex);
+ free(pdpl); pdpl = NULL;
+ return 1;
+}
+
+int
+pdict_add_persistent_change_listener(pdict_t *pd, const char *kpat,
+ pdl_notify_func_t notify, void *arg)
+{
+ pdict_persistent_listener_t *pl;
+ static int lid = 1;
+
+ if (!(pl = malloc(sizeof (*pl))))
+ return 0;
+ memset(pl, 0, sizeof (*pl));
+ pl->pdpl_l.pdl_notify = notify;
+ pl->pdpl_l.pdl_arg = arg;
+ if (regcomp(&pl->pdpl_regex, kpat, REG_EXTENDED | REG_NOSUB) != 0) {
+ // XXX todo: communicate error context is not libc
+ free(pl); pl = NULL;
+ pu_log(PUL_WARN, 0, "Failed regcomp in pdict_add_persistent_change_listener.");
+ return 0;
+ }
+
+ plist_add((void *)(size_t)lid, pl, &pd->pd_persistent_listeners);
+
+ pl->pdpl_new = 1;
+ if (!_pdict_walk_int(pd,
+ pdict_ent_add_persistent_change_listener_dcb, pl)) {
+ _pdict_walk_int(pd,
+ pdict_ent_remove_persistent_change_listener_dcb, pl);
+ plist_remove((void *)(size_t)lid, &pd->pd_persistent_listeners, NULL);
+ regfree(&pl->pdpl_regex);
+ free(pl); pl = NULL;
+ pu_log(PUL_WARN, 0, "Failed _pdict_walk_int in pdict_add_persistent_change_listener.");
+ return 0;
+ }
+ pl->pdpl_new = 0;
+ return lid++;
+}
+
+/*
+ * Return whether a given key is in the dictionary. If the given
+ * entry pointer is non-NULL, set it to the entry.
+ */
+static int
+_pdict_ent_lookup(pdict_t *pd, const char *k, pdict_ent_t **e)
+{
+ return ptree_contains((void *)&k, pd->pd_ents, pdecmp, (void **)e);
+}
+
+int
+pdict_ent_lookup(pdict_t *pd, const char *k, const char **v)
+{
+ pdict_ent_t *pde;
+
+ if (_pdict_ent_lookup(pd, k, &pde)) {
+ if (v)
+ *v = strdup(pde->pde_val);
+ return 1;
+ }
+ return 0;
+}
+
+static int
+pdict_ent_remove_change_listener_cb(const void *k, const void *v, void *a)
+{
+ pdict_listener_t *l = (pdict_listener_t *)k;
+ void **arg = (void **)a;
+
+ if (l->pdl_notify == (pdl_notify_func_t)arg[0] && l->pdl_arg == arg[1]) {
+ arg[2] = l;
+ return 0;
+ }
+ return 1;
+}
+
+static int
+_pdict_ent_remove_change_listener(pdict_ent_t *pde, pdl_notify_func_t notify,
+ void *a)
+{
+ void *arg[3];
+
+ arg[0] = (void *)notify;
+ arg[1] = a;
+ arg[2] = NULL;
+ plist_walk(pde->pde_listeners, pdict_ent_remove_change_listener_cb, arg);
+ if (arg[2]) {
+ plist_remove(arg[2], &pde->pde_listeners, NULL);
+ free(arg[2]); arg[2] = NULL;
+ return 1;
+ }
+ return 0;
+}
+
+static int
+_pdict_ent_add_change_listener(pdict_ent_t *pde, pdl_notify_func_t notify,
+ void *arg)
+{
+ pdict_listener_t *l;
+
+ if (!(l = malloc(sizeof (*l))))
+ return 0;
+ memset(l, 0, sizeof (*l));
+ l->pdl_notify = notify;
+ l->pdl_arg = arg;
+ if (!plist_add(l, 0, &pde->pde_listeners)) {
+ free(l); l = NULL;
+ pu_log(PUL_WARN, 0, "Failed plist_add in _pdict_ent_add_change_listener.");
+ return 0;
+ }
+
+ return 1;
+}
+
+int
+pdict_ent_add_change_listener(pdict_t *pd, const char *k,
+ pdl_notify_func_t notify, void *arg)
+{
+ pdict_ent_t *pde;
+
+ if (!_pdict_ent_lookup(pd, k, &pde))
+ return 0;
+ return _pdict_ent_add_change_listener(pde, notify, arg);
+}
+
+typedef struct {
+ pdict_ent_t *penca_pde;
+ pdict_reason_t penca_reason;
+ const char *penca_ov;
+} pdict_ent_notify_cb_args_t;
+
+static int
+pdict_ent_notify_cb(const void *v, const void *v0, void *a)
+{
+ pdict_listener_t *pdl = (pdict_listener_t *)v;
+ pdict_ent_notify_cb_args_t *penca = a;
+
+ pdl->pdl_notify(penca->penca_pde->pde_key, penca->penca_pde->pde_val,
+ penca->penca_reason, penca->penca_ov, pdl->pdl_arg);
+ return 1;
+}
+
+static void
+_pdict_ent_notify(pdict_ent_t *pde, int reason, const char *ov)
+{
+ pdict_ent_notify_cb_args_t penca = { pde, reason, ov };
+
+ plist_walk(pde->pde_listeners, pdict_ent_notify_cb, &penca);
+}
+
+static ptree_walk_res_t
+pdict_walk_int_cb(const void *v, int level, void *a, void *pwra)
+{
+ void **args = a;
+
+ return ((pdict_walk_int_func_t)args[0])((pdict_ent_t *)v, args[1]);
+}
+
+static ptree_walk_res_t
+pdict_walk_cb(const void *v, int level, void *a, void *pwra)
+{
+ pdict_ent_t *pde = (pdict_ent_t *)v;
+ void **args = a;
+
+ return ((pdict_walk_func_t)args[0])(pde->pde_key, pde->pde_val,
+ args[1]);
+}
+
+static int
+_pdict_walk_int(pdict_t *pd, pdict_walk_int_func_t w, void *arg)
+{
+ void *args[2] = { (void *)w, arg };
+
+ return ptree_walk(pd->pd_ents, PTREE_INORDER, pdict_walk_int_cb, pdecmp, args);
+}
+
+int
+pdict_walk(pdict_t *pd, pdict_walk_func_t w, void *arg)
+{
+ void *args[2] = { (void *)w, arg };
+
+ return ptree_walk(pd->pd_ents, PTREE_INORDER, pdict_walk_cb, NULL, args);
+}
+
+int
+pdict_ent_remove_change_listener(pdict_t *pd, const char *k,
+ pdl_notify_func_t nf, void *arg)
+{
+ pdict_ent_t *e;
+ int res;
+
+ if (!(res = _pdict_ent_lookup(pd, k, &e)))
+ return 0;
+ return _pdict_ent_remove_change_listener(e, nf, arg);
+}
+
+const char *
+pdict_reason_str(pdict_reason_t r)
+{
+ switch (r) {
+ case PDR_VALUE_CHANGED:
+ return "changed";
+ case PDR_ENTRY_ADDED:
+ return "added";
+ case PDR_ENTRY_REMOVING:
+ return "removing";
+ case PDR_CURRENT_VALUE:
+ return "current";
+ default:
+ return "?";
+ }
+}
+
+pdict_reason_t
+pdict_reason_from_str(const char *s)
+{
+ if (strcmp(s, "changed") == 0)
+ return PDR_VALUE_CHANGED;
+ if (strcmp(s, "current") == 0)
+ return PDR_CURRENT_VALUE;
+ if (strcmp(s, "added") == 0)
+ return PDR_ENTRY_ADDED;
+ if (strcmp(s, "removing") == 0)
+ return PDR_ENTRY_REMOVING;
+ return 0;
+}
diff --git a/dict/pdict.h b/dict/pdict.h
new file mode 100644
index 0000000..bdd8065
--- /dev/null
+++ b/dict/pdict.h
@@ -0,0 +1,70 @@
+#ifndef _PDICT_H_
+#define _PDICT_H_
+
+typedef enum {
+ PDR_VALUE_CHANGED = 1,
+ PDR_ENTRY_ADDED,
+ PDR_ENTRY_REMOVING,
+ PDR_CURRENT_VALUE
+} pdict_reason_t;
+
+/* The _t stands for typedef? */
+typedef struct pdict pdict_t;
+
+typedef void (*pdl_notify_func_t)(const char *k,
+ const char *v,
+ pdict_reason_t r,
+ const char *pde_oldval,
+ void *arg);
+
+typedef int (*pdict_walk_func_t)(const char *k,
+ const char *v,
+ void *arg);
+
+pdict_t *pdict_alloc(void);
+
+int pdict_add(pdict_t *pd,
+ const char *k,
+ const char *v,
+ const char **ovp);
+
+int pdict_add_persistent_change_listener(pdict_t *pd,
+ const char *kpat,
+ pdl_notify_func_t,
+ void *);
+
+int pdict_walk(pdict_t *pd,
+ pdict_walk_func_t,
+ void *arg);
+
+/*
+ * Return whether a given key is in the dictionary. If v is set, it
+ * will be set to point to a copy of the value, which must be freed by
+ * the caller.
+ */
+int pdict_ent_lookup(pdict_t *pd,
+ const char *k,
+ const char **v);
+
+int pdict_ent_add_change_listener(pdict_t *pd,
+ const char *k,
+ pdl_notify_func_t,
+ void *);
+
+int pdict_ent_remove_change_listener(pdict_t *pd,
+ const char *k,
+ pdl_notify_func_t,
+ void *);
+
+int pdict_remove_persistent_change_listener(pdict_t *pd,
+ int id);
+
+int pdict_ent_remove(pdict_t *pd,
+ const char *k,
+ char **ovp);
+
+const char *pdict_reason_str(pdict_reason_t);
+
+pdict_reason_t pdict_reason_from_str(const char *);
+
+#endif
diff --git a/dict/pdictclient.c b/dict/pdictclient.c
new file mode 100644
index 0000000..987d6bc
--- /dev/null
+++ b/dict/pdictclient.c
@@ -0,0 +1,1490 @@
+#include "../stdafx.h"
+#include <ctype.h>
+#include <stdlib.h>
+#include <stdio.h>
+#ifndef _MSC_EXTENSIONS
+#include <unistd.h>
+#endif
+#include <assert.h>
+#if !defined(_WINDOWS) || defined(_CYGWIN)
+#include <pthread.h>
+#include <signal.h>
+#else
+#include "wincompat.h"
+#endif
+#include "pdictclient.h"
+#include "ptree.h"
+#include "utils.h"
+#include "md5.h"
+
+/*
+ * TODO XXX:
+ * - notification arguments and reason
+ */
+
+#ifdef DEBUG_PROTOCOL
+int debug_protocol = 0;
+#endif
+
+#define ABORT() ((*(int *)0 = 1), abort())
+#define PENDING_PATTERN "report 200-lid([0-9]*) is pending, key (.*)" \
+ " latest value \".*\" \\((.*)\\)"
+
+extern const char *ws_protocol_ver;
+
+typedef struct result {
+ int r_tag;
+ void (*r_notify)(pdc_session_t *, struct result *, int code,
+ int final, const char *line);
+ void *r_arg;
+} result_t;
+
+struct pdc_session {
+ int pdcs_rfd;
+ int pdcs_wfd;
+ int (*pdcs_read)(int, void *, unsigned int, char *, int);
+ int (*pdcs_write)(int, const void *, unsigned int, char *, int);
+ int (*pdcs_close)(int, char *, int);
+ void (*pdcs_cleanup)(void *);
+ void *pdcs_cleanup_ptr;
+ ptree_node_t *pdcs_listeners;
+ char pdcs_readbuf[2048];
+ int pdcs_bufcur;
+ int pdcs_buflen;
+ pthread_mutex_t pdcs_listeners_lock;
+ pthread_mutex_t pdcs_pending_lock;
+ ptree_node_t *pdcs_pending;
+ pthread_t pdcs_resultreader;
+ char pdcs_resultreader_errdesc[2048];
+};
+
+typedef struct {
+ int l_id;
+ void (*l_cb)(const char *key, const char *val, unsigned int len,
+ pdict_reason_t, void *);
+ void *l_arg;
+} listener_t;
+
+typedef struct {
+ pthread_mutex_t grcba_lock;
+ pthread_cond_t grcba_cv;
+ int grcba_code;
+ int grcba_desired;
+ char *grcba_line;
+} getresult_cb_arg_t;
+
+typedef struct {
+ pthread_mutex_t grcba_lock;
+ pthread_cond_t grcba_cv;
+ int grcba_code;
+ int grcba_reply_len;
+ char *grcba_reply;
+ char *grcba_reply_ptr;
+} jgetresult_cb_arg_t;
+
+static int events;
+regex_t pendingex;
+static int initialized;
+
+static void *read_results(void *);
+static pdict_reason_t _pdict_reason_from_str(const char *s);
+static int cmd_timeout = 10000; //ms
+
+/*
+ * Stops the read thread and frees the pdc session
+ */
+void pdc_session_free(pdc_session_t *pdcs)
+{
+ if(pdcs)
+ {
+ //make sure the thread is not running...
+ pdc_readthread_join(pdcs, NULL);
+
+ //free
+ pthread_mutex_destroy(&pdcs->pdcs_pending_lock);
+ pthread_mutex_destroy(&pdcs->pdcs_listeners_lock);
+ free(pdcs); pdcs = NULL;
+ }
+ return;
+}
+
+/*
+ * Allocates a new pdc session and starts a thread reading on readfd
+ */
+pdc_session_t * CCONV
+pdc_session_alloc(int readfd, int(*readfunc)(int, void *, unsigned int, char *,
+ int), int writefd, int(*writefunc)(int, const void *, unsigned int, char *,
+ int), int (*closefunc)(int, char *, int), void *cleanupPtr, void (*cleanupFunc)(void *))
+{
+ pdc_session_t *pdcs;
+#ifndef _WINDOWS
+ sigset_t new, old;
+#endif
+#ifdef _WINDOWS
+ int opt = 1;
+ int ssoret;
+#endif
+
+ if (!initialized)
+ pdc_init();
+
+ if (!(pdcs = malloc(sizeof (*pdcs))))
+ return NULL;
+ memset(pdcs, 0, sizeof (*pdcs));
+ pdcs->pdcs_rfd = readfd;
+ pdcs->pdcs_read = readfunc;
+ pdcs->pdcs_wfd = writefd;
+ pdcs->pdcs_write = writefunc;
+ pdcs->pdcs_close = closefunc;
+ pdcs->pdcs_cleanup_ptr = cleanupPtr;
+ pdcs->pdcs_cleanup = cleanupFunc;
+ if (pthread_mutex_init(&pdcs->pdcs_pending_lock, 0) != 0
+ || pthread_mutex_init(&pdcs->pdcs_listeners_lock, 0) != 0) {
+ free(pdcs);
+ return NULL;
+ }
+#ifndef _WINDOWS
+ sigfillset(&new);
+ pthread_sigmask(SIG_BLOCK, &new, &old);
+#endif
+
+#ifdef _WINDOWS
+ //Disable Nagle
+ opt = TRUE;
+ ssoret = setsockopt(readfd, IPPROTO_TCP, TCP_NODELAY, (void *)&opt, sizeof (opt));
+ //set send buffer to 0 (send data right away)
+ opt = 0;
+ ssoret = setsockopt(readfd, SOL_SOCKET, SO_SNDBUF, (void *)&opt, sizeof (opt));
+#endif
+
+ if (pthread_create(&pdcs->pdcs_resultreader, 0, read_results, pdcs) !=
+ 0) {
+ pthread_mutex_destroy(&pdcs->pdcs_pending_lock);
+ pthread_mutex_destroy(&pdcs->pdcs_listeners_lock);
+ free(pdcs); pdcs = NULL;
+ return NULL;
+ }
+#ifdef _WINDOWS
+ //pthread_up_priority(pdcs->pdcs_resultreader);
+#endif
+#ifndef _WINDOWS
+ pthread_sigmask(SIG_SETMASK, &old, NULL);
+#endif
+
+ return pdcs;
+}
+
+/*
+ * Sets up regex for PENDING_PATTERN
+ */
+int CCONV
+pdc_init(void)
+{
+ int res;
+
+ if ((res = regcomp(&pendingex, PENDING_PATTERN, REG_EXTENDED)) != 0) {
+ LOG_STDERR(PHIDGET_LOG_CRITICAL, "pending report pattern compilation error %d", res);
+ ABORT();
+ }
+ initialized = 1;
+ return 1;
+}
+
+/*
+ * Compares 2 listener IDs
+ */
+static int
+lcmp(const void *sv, const void *tv)
+{
+ return ((const listener_t *)sv)->l_id - ((const listener_t *)tv)->l_id;
+}
+
+/*
+ * Compares 2 tag IDs
+ */
+static int
+tagcmp(const void *sv, const void *tv)
+{
+ return ((result_t *)sv)->r_tag - ((result_t *)tv)->r_tag;
+}
+
+/*
+ * Handles a report from the read thread
+ */
+static void
+handle_report(pdc_session_t *pdcs, char *line)
+{
+ regmatch_t pmatch[7];
+ listener_t *lp;
+ listener_t l;
+ char *idstr = NULL;
+ char *key = NULL;
+ char *val = NULL;
+ char *eoval = NULL; //end of val
+ char *soval = NULL; //start of val
+ char *reason_str = NULL;
+ pdict_reason_t r;
+ int res;
+ //char err[1024];
+
+ events++;
+
+//Disable this, I think it's causing bad problems!
+#if 0
+#ifdef _WINDOWS
+ //Send something back if we're on Windows, so this report gets ACKed right away
+ // otherwise, we face 200ms delayed ack -> clumps of events every 200ms
+ pdcs->pdcs_write(pdcs->pdcs_wfd, "report ack\n", strlen("report ack\n"), err, sizeof (err));
+#endif
+#endif
+
+ /* handle value without regex, due to crappy regex implementations */
+ /* val is bounded by double quotes */
+
+ if (!(val = strchr(line, '\"')))
+ goto ignore;
+ soval = ++val;
+ if (!(eoval = strchr(val, '\"')))
+ goto ignore;
+
+ /* end of val \" = NULL */
+ *eoval = '\0';
+
+ /* make sure there are no more double quotes */
+ if (strchr(eoval + 1, '\"') != NULL)
+ goto ignore;
+
+ /* create a copy of val, or undo my changes if there is not enough memory */
+ if (!(val = strdup(val))) {
+ *eoval = '\"';
+ pu_log(PUL_WARN, pdcs->pdcs_rfd,
+ "report dropped due to low memory");
+ goto ignore;
+ }
+
+ /* put back what I changed and shift anything after val to the start of val */
+ *eoval = '\"';
+ memmove(soval, eoval, strlen(eoval) + 1);
+
+ if ((res = regexec(&pendingex, line, 6, pmatch, 0)) != 0) {
+ignore:
+#ifdef DEBUG_PROTOCOL
+ pu_log(PUL_DEBUG, pdcs->pdcs_rfd,
+ "ignoring invalid report (see next line):");
+ pu_log(PUL_DEBUG, pdcs->pdcs_rfd, line);
+#endif
+ goto end;
+ }
+ if (!getmatchsub(line, &idstr, pmatch, 1) || !idstr)
+ {
+ goto end;
+ }
+ if (!getmatchsub(line, &key, pmatch, 2) || !key)
+ {
+ goto end;
+ }
+ if (!getmatchsub(line, &reason_str, pmatch, 3) || !reason_str ||
+ !(r = _pdict_reason_from_str(reason_str)))
+ {
+ goto end;
+ }
+ free(reason_str); reason_str = NULL;
+
+ l.l_id = atoi(idstr);
+ pthread_mutex_lock(&pdcs->pdcs_listeners_lock);
+ if (ptree_contains(&l, (ptree_node_t *)pdcs->pdcs_listeners, lcmp,
+ (void **)&lp) && lp->l_cb) {
+ char *ueval;
+ unsigned int uevlen;
+
+ pthread_mutex_unlock(&pdcs->pdcs_listeners_lock);
+ if (!unescape(val, &ueval, &uevlen)) {
+ /* XXX log */
+ goto end;
+ }
+ lp->l_cb(key, ueval, uevlen, r, lp->l_arg);
+ free(ueval);
+ }
+ else
+ {
+ pthread_mutex_unlock(&pdcs->pdcs_listeners_lock);
+ LOG(PHIDGET_LOG_WARNING, "No callback found for: %s",line);
+ }
+end:
+ free(val);
+ free(idstr);
+ free(key);
+}
+
+/*
+ * Called by read thread for any pending commands that didn't complete before the socket was closed.
+ */
+static ptree_walk_res_t
+finish_pending_async(const void *node, int level, void *arg, void *pwra)
+{
+ pdc_session_t *pdcs = arg;
+ result_t *r;
+ char msg[1024];
+
+ ptree_inorder_walk_remove(&pdcs->pdcs_pending, (void **)&r, pwra, tagcmp);
+ assert(node == r);
+
+ snprintf(msg, 1024, "Socket was closed before command T%d finished.",r->r_tag);
+
+ //notify frees r
+ if(r->r_notify)
+ r->r_notify(pdcs, r, 500, PTRUE, msg);
+
+ //free(r);
+
+ return PTREE_WALK_CONTINUE;
+}
+static ptree_walk_res_t
+free_node(const void *node, int level, void *arg, void *pwra)
+{
+ pdc_session_t *pdcs = arg;
+ void *ov;
+ ptree_inorder_walk_remove(&pdcs->pdcs_listeners, &ov, pwra, lcmp);
+ assert(node == ov);
+ free(ov);
+ return PTREE_WALK_CONTINUE;
+}
+
+/*
+ * Runs in a thread started by pdc_session_alloc
+ */
+static void *
+read_results(void *arg)
+{
+ pdc_session_t *pdcs = arg;
+ char *line = 0;
+ result_t *r;
+ result_t rk;
+ char *startp;
+ int linelen;
+ int final;
+ int tag;
+
+next:
+ if (line) {
+ free(line); line = NULL;
+ }
+ pdcs->pdcs_resultreader_errdesc[0] = 0;
+ if (!pd_getline((char *)pdcs->pdcs_readbuf, sizeof (pdcs->pdcs_readbuf),
+ &pdcs->pdcs_bufcur, &pdcs->pdcs_buflen, pdcs->pdcs_read, pdcs->pdcs_close,
+ pdcs->pdcs_rfd, &line, pdcs->pdcs_resultreader_errdesc,
+ sizeof (pdcs->pdcs_resultreader_errdesc)))
+ {
+ /* socket closed */
+ free(line); line=NULL;
+
+ //respond for any pending commands (failed)...
+ pthread_mutex_lock(&pdcs->pdcs_pending_lock);
+ ptree_walk(pdcs->pdcs_pending, PTREE_POSTORDER, finish_pending_async, tagcmp, pdcs);
+ assert(!pdcs->pdcs_pending);
+ //ptree_clear(&pdcs->pdcs_pending);
+ //pdcs->pdcs_pending = NULL;
+ pthread_mutex_unlock(&pdcs->pdcs_pending_lock);
+
+ //remove listeners
+ pthread_mutex_lock(&pdcs->pdcs_listeners_lock);
+ ptree_walk(pdcs->pdcs_listeners, PTREE_POSTORDER, free_node, lcmp, pdcs);
+ assert(!pdcs->pdcs_listeners);
+ pthread_mutex_unlock(&pdcs->pdcs_listeners_lock);
+ //ptree_clear(&pdcs->pdcs_listeners);
+
+ //do cleanup - this handles stuff outside on the dictionary code, etc.
+ if (pdcs->pdcs_cleanup)
+ pdcs->pdcs_cleanup(pdcs->pdcs_cleanup_ptr);
+ return (void *)(size_t)(-1 * errno); // XXX pdcs errno function
+ }
+
+ //LOG(PHIDGET_LOG_DEBUG, "read_results: %s",line);
+
+ if (line[0] == 'r') {
+ handle_report(pdcs, line);
+ goto next;
+ } else if (line[0] == 'T') {
+ tag = atoi(line + 1);
+ startp = strchr(line, ' ');
+ while (startp && *startp) {
+ if (isdigit(*startp))
+ goto notify;
+ startp++;
+ }
+ // XXX log malformed line
+ goto next;
+ } else {
+ startp = line;
+ tag = 0;
+ }
+notify:
+ if ((linelen = (int)strlen(line)) < 4) {
+ // XXX log malformed line
+ goto next;
+ }
+ final = (startp[3] == ' ');
+ pthread_mutex_lock(&pdcs->pdcs_pending_lock);
+ rk.r_tag = tag;
+ if (final) {
+ if (!ptree_remove(&rk, &pdcs->pdcs_pending, tagcmp,
+ (void **)&r)) {
+ //ABORT();
+ pthread_mutex_unlock(&pdcs->pdcs_pending_lock);
+ // XXX log unanticipated result
+ goto next;
+ }
+ } else {
+ if (!ptree_contains(&rk, pdcs->pdcs_pending, tagcmp,
+ (void **)&r)) {
+ //ABORT();
+ pthread_mutex_unlock(&pdcs->pdcs_pending_lock);
+ // XXX log unanticipated result
+ goto next;
+ }
+ }
+ pthread_mutex_unlock(&pdcs->pdcs_pending_lock);
+ r->r_notify(pdcs, r, atoi(startp), final, startp + 4);
+ r = NULL;
+ goto next;
+// return (void *)(0);
+}
+
+/*
+ * Callback from cmd
+ */
+static void
+getresult_cb(pdc_session_t *pdcs, result_t *r, int code, int final,
+ const char *line)
+{
+ getresult_cb_arg_t *grcba = r->r_arg;
+
+ if (final) {
+ if (pthread_mutex_lock(&grcba->grcba_lock))
+ abort();
+ grcba->grcba_code = code;
+ if (grcba->grcba_code != grcba->grcba_desired)
+ grcba->grcba_line = strdup(line);
+ if (pthread_mutex_unlock(&grcba->grcba_lock))
+ abort();
+ if (pthread_cond_signal(&grcba->grcba_cv))
+ abort();
+ }
+}
+
+/*
+ * Callback from jcmd
+ */
+static void
+jgetresult_cb(pdc_session_t *pdcs, result_t *r, int code, int final,
+ const char *line)
+{
+ jgetresult_cb_arg_t *grcba = r->r_arg;
+ int spaceleft = grcba->grcba_reply_len - (grcba->grcba_reply_ptr-grcba->grcba_reply);
+
+ if (pthread_mutex_lock(&grcba->grcba_lock))
+ abort();
+
+ if (final)
+ {
+ grcba->grcba_code = code;
+ }
+
+ //add more space if needed
+ if((size_t)spaceleft < strlen(line)+1)
+ {
+ int offset = grcba->grcba_reply_ptr-grcba->grcba_reply;
+ if(!(grcba->grcba_reply = (char *)realloc(grcba->grcba_reply, strlen(line) + offset + 100)))
+ {
+ LOG(PHIDGET_LOG_WARNING,"Couldn't realloc!");
+ return;
+ }
+ grcba->grcba_reply_len = strlen(line) + offset + 100;
+ grcba->grcba_reply_ptr = grcba->grcba_reply + offset;
+ spaceleft = grcba->grcba_reply_len - (grcba->grcba_reply_ptr-grcba->grcba_reply);
+ }
+
+ strncpy(grcba->grcba_reply_ptr, line,
+ spaceleft - 1);
+ if(!final)
+ grcba->grcba_reply_ptr[strlen(line)] = '\n';
+ grcba->grcba_reply_ptr+=(strlen(line)+1);
+
+ if (pthread_mutex_unlock(&grcba->grcba_lock))
+ abort();
+
+ if (final)
+ {
+ if (pthread_cond_signal(&grcba->grcba_cv))
+ abort();
+ }
+}
+
+static int wait_timeout(pthread_mutex_t *grcba_lock, pthread_cond_t *grcba_cv, int timeout_ms)
+{
+ int retval;
+#ifdef _WINDOWS
+ int timeout = timeout_ms;
+#else
+ struct timespec timeout;
+ struct timeval now;
+
+ // Lock the mutex.
+ //pthread_mutex_lock(&grcba->grcba_lock);
+
+ gettimeofday(&now,0);
+ timeout.tv_sec = now.tv_sec + timeout_ms/1000;
+ timeout.tv_nsec = now.tv_usec*1000 + (timeout_ms%1000 * 1000000);
+ if(timeout.tv_nsec >= 1000000000)
+ {
+ timeout.tv_sec++;
+ timeout.tv_nsec -= 1000000000;
+ }
+#endif
+ retval = pthread_cond_timedwait(grcba_cv, grcba_lock, &timeout);
+ //pthread_mutex_unlock(&grcba->grcba_lock);
+ return retval;
+}
+
+static int
+cmd(pdc_session_t *pdcs,
+ int desired,
+ const char *cmd,
+ char *errdesc,
+ int errlen)
+{
+ int len = (int)strlen(cmd);
+ getresult_cb_arg_t *grcba;
+ result_t r;
+ result_t *or;
+
+ if (!(grcba = malloc(sizeof (*grcba)))) {
+ if (errdesc)
+ (void) snprintf(errdesc, errlen, "%s", strerror(errno));
+ return 0;
+ }
+ r.r_tag = 0;
+ r.r_notify = getresult_cb;
+ r.r_arg = grcba;
+ memset(grcba, 0, sizeof (*grcba));
+ grcba->grcba_code = -1;
+ grcba->grcba_desired = desired;
+
+ if (pthread_mutex_init(&grcba->grcba_lock, NULL))
+ abort();
+ if (pthread_cond_init(&grcba->grcba_cv, 0))
+ abort();
+ if (pthread_mutex_lock(&pdcs->pdcs_pending_lock))
+ abort();
+ if (!ptree_replace(&r, &pdcs->pdcs_pending, tagcmp, (void **)&or)) {
+ pthread_mutex_destroy(&grcba->grcba_lock);
+ pthread_cond_destroy(&grcba->grcba_cv);
+ pthread_mutex_unlock(&pdcs->pdcs_pending_lock);
+ free(grcba); grcba = NULL;
+ if (errdesc)
+ (void) snprintf(errdesc, errlen,
+ "result replacement failure");
+ return 0;
+ }
+
+ // if or != NULL then pdcs_pending already contained a node with tag == r.r_tag
+ assert(!or);
+ if (pthread_mutex_lock(&grcba->grcba_lock))
+ abort();
+ if (pthread_mutex_unlock(&pdcs->pdcs_pending_lock))
+ abort();
+
+ if (!pdcs->pdcs_write(pdcs->pdcs_wfd, cmd, len, errdesc, errlen)) {
+ pthread_mutex_unlock(&grcba->grcba_lock);
+ pthread_mutex_lock(&pdcs->pdcs_pending_lock);
+ ptree_remove(&r, &pdcs->pdcs_pending, tagcmp, (void **)&or);
+ pthread_mutex_unlock(&pdcs->pdcs_pending_lock);
+ pthread_mutex_destroy(&grcba->grcba_lock);
+ pthread_cond_destroy(&grcba->grcba_cv);
+ free(grcba);
+ return 0;
+ }
+
+ while (grcba->grcba_code == -1)
+ {
+ int retval;
+ //5 second timeout
+ if((retval = wait_timeout(&grcba->grcba_lock, &grcba->grcba_cv, cmd_timeout)) != 0)
+ {
+ switch (retval)
+ {
+ case ETIMEDOUT:
+ default:
+ if (errdesc)
+ (void) snprintf(errdesc, errlen,"cmd: \"%s\" Timed out after %dms.",cmd,cmd_timeout);
+ pthread_mutex_lock(&pdcs->pdcs_pending_lock);
+ ptree_remove(&r, &pdcs->pdcs_pending, tagcmp, (void **)&or);
+ pthread_mutex_unlock(&pdcs->pdcs_pending_lock);
+ pthread_mutex_destroy(&grcba->grcba_lock);
+ pthread_cond_destroy(&grcba->grcba_cv);
+ if (grcba->grcba_line)
+ free(grcba->grcba_line);
+ free(grcba);
+ return 0; //Timeout
+ }
+ }
+ }
+
+ pthread_mutex_destroy(&grcba->grcba_lock);
+ pthread_cond_destroy(&grcba->grcba_cv);
+
+ if (grcba->grcba_code != desired)
+ {
+ if (errdesc)
+ (void) snprintf(errdesc, errlen, "protocol error: %d%s%s", grcba->grcba_code, grcba->grcba_line ? " " : "", grcba->grcba_line ? grcba->grcba_line : "");
+ if (grcba->grcba_line)
+ free(grcba->grcba_line);
+ free(grcba);
+ return 0;
+ }
+
+ if (grcba->grcba_line)
+ free(grcba->grcba_line);
+ free(grcba);
+ return 1;
+}
+
+/*
+ * jcmd is for a command that returns results, like getKey
+ */
+static int
+jcmd(pdc_session_t *pdcs,
+ const char *cmd,
+ int desired,
+ char **reply,
+ int replylen,
+ char *errdesc,
+ int errlen)
+{
+ int len = (int)strlen(cmd);
+ jgetresult_cb_arg_t *grcba;
+ result_t r;
+ result_t *or;
+
+ if (!(grcba = malloc(sizeof (*grcba)))) {
+ if (errdesc)
+ (void) snprintf(errdesc, errlen, "%s", strerror(errno));
+ return 0;
+ }
+ r.r_tag = 0;
+ r.r_notify = jgetresult_cb;
+ r.r_arg = grcba;
+ memset(grcba, 0, sizeof (*grcba));
+ grcba->grcba_code = -1;
+ grcba->grcba_reply = *reply;
+ grcba->grcba_reply_ptr = *reply;
+ grcba->grcba_reply_len = replylen;
+
+ if (pthread_mutex_init(&grcba->grcba_lock, NULL))
+ abort();
+ if (pthread_cond_init(&grcba->grcba_cv, 0))
+ abort();
+ if (pthread_mutex_lock(&pdcs->pdcs_pending_lock))
+ abort();
+ if (!ptree_replace(&r, &pdcs->pdcs_pending, tagcmp, (void **)&or)) {
+ pthread_mutex_destroy(&grcba->grcba_lock);
+ pthread_cond_destroy(&grcba->grcba_cv);
+ pthread_mutex_unlock(&pdcs->pdcs_pending_lock);
+ free(grcba); grcba = NULL;
+ if (errdesc)
+ (void) snprintf(errdesc, errlen,
+ "result replacement failure");
+ return 0;
+ }
+ // if or != NULL then pdcs_pending already contained a node with tag == r.r_tag
+ assert(!or);
+ if (pthread_mutex_lock(&grcba->grcba_lock))
+ abort();
+ if (pthread_mutex_unlock(&pdcs->pdcs_pending_lock))
+ abort();
+
+#ifndef _MSC_EXTENSIONS
+#ifdef DEBUG_PROTOCOL
+ if (debug_protocol) {
+ write(1, "L: ", 3);
+ write(1, cmd, len);
+ }
+#endif
+#endif
+ if (!pdcs->pdcs_write(pdcs->pdcs_wfd, cmd, len, errdesc, errlen)) {
+ pthread_mutex_lock(&pdcs->pdcs_pending_lock);
+ ptree_remove(&r, &pdcs->pdcs_pending, tagcmp, (void **)&or);
+ pthread_mutex_unlock(&pdcs->pdcs_pending_lock);
+ pthread_mutex_destroy(&grcba->grcba_lock);
+ pthread_cond_destroy(&grcba->grcba_cv);
+ free(grcba); grcba = NULL;
+ return 0;
+ }
+ while (grcba->grcba_code == -1)
+ {
+ int retval;
+ //5 second timeout
+ if((retval = wait_timeout(&grcba->grcba_lock, &grcba->grcba_cv, cmd_timeout)) != 0)
+ {
+ switch (retval)
+ {
+ case ETIMEDOUT:
+ default:
+ if (errdesc)
+ (void) snprintf(errdesc, errlen,"jcmd: \"%s\" Timed out after %dms.",cmd,cmd_timeout);
+ pthread_mutex_lock(&pdcs->pdcs_pending_lock);
+ ptree_remove(&r, &pdcs->pdcs_pending, tagcmp, (void **)&or);
+ pthread_mutex_unlock(&pdcs->pdcs_pending_lock);
+ pthread_mutex_destroy(&grcba->grcba_lock);
+ pthread_cond_destroy(&grcba->grcba_cv);
+ free(grcba); grcba = NULL;
+ return 0;
+ }
+ }
+ //if (pthread_cond_wait(&grcba->grcba_cv, &grcba->grcba_lock))
+ // abort();
+ }
+ pthread_mutex_destroy(&grcba->grcba_lock);
+ pthread_cond_destroy(&grcba->grcba_cv);
+ if (grcba->grcba_code != desired) {
+ if (errdesc)
+ (void) snprintf(errdesc, errlen,
+ "protocol error: %d%s%s", grcba->grcba_code,
+ grcba->grcba_reply ? " " : "", grcba->grcba_reply ?
+ grcba->grcba_reply : "");
+ *reply = grcba->grcba_reply;
+ free(grcba); grcba = NULL;
+ return 0;
+ }
+ *reply = grcba->grcba_reply;
+ free(grcba); grcba = NULL;
+ return 1;
+}
+
+//int CCONV
+//pdc_set(pdc_session_t *pdcs, const char *key, const char *val,
+// int len, int remove_on_close, char *errdesc, int errlen)
+//{
+// char *escval;
+// char *buf;
+// int res;
+//
+// if(val[0] == '\0')
+// {
+// if (!escape("\001", len, &escval)) {
+// if (errdesc)
+// (void) snprintf(errdesc, errlen, "%s", strerror(errno));
+// return 0;
+// }
+// }
+// else
+// {
+// if (!escape(val, len, &escval)) {
+// if (errdesc)
+// (void) snprintf(errdesc, errlen, "%s", strerror(errno));
+// return 0;
+// }
+// }
+// if ((len = pasprintf(&buf, "set %s=\"%s\"%s\n", key, escval,
+// remove_on_close ? " for session" : "")) < 0) {
+// free((void *)escval); escval = NULL;
+// if (errdesc)
+// (void) snprintf(errdesc, errlen, "%s", strerror(errno));
+// return 0;
+// }
+// res = cmd(pdcs, 200, buf, errdesc, errlen);
+// free((void *)escval); escval = NULL;
+// free(buf); buf = NULL;
+// return res;
+//}
+
+/*
+ * Returns a nonzero listen ID on success, 0 otherwise.
+ */
+pdc_listen_id_t CCONV
+pdc_listen(pdc_session_t *pdcs, const char *pattern,
+ void (*cb)(const char *, const char *, unsigned int, pdict_reason_t,
+ void *), void *arg, char *errdesc, int errlen)
+{
+ listener_t *l;
+ static int lid = 1;
+ char *buf;
+ int len;
+
+ if(!pdcs)
+ return 0;
+
+ if (!(l = malloc(sizeof (*l)))) {
+ if (errdesc)
+ (void) snprintf(errdesc, errlen, "%s", strerror(errno));
+ return 0;
+ }
+ l->l_id = lid;
+ l->l_cb = cb;
+ l->l_arg = arg;
+ if ((len = pasprintf(&buf, "listen \"%s\" lid%d\n", pattern, lid++)) < 0)
+ {
+ if (errdesc)
+ (void) snprintf(errdesc, errlen, "%s", strerror(errno));
+ return 0;
+ }
+
+ pthread_mutex_lock(&pdcs->pdcs_listeners_lock);
+ if (!ptree_replace(l, (ptree_node_t **)&pdcs->pdcs_listeners, lcmp, NULL)) {
+ free(buf); buf = NULL;
+ free(l); l = NULL;
+ if (errdesc)
+ (void) snprintf(errdesc, errlen, "%s", strerror(errno));
+ pthread_mutex_unlock(&pdcs->pdcs_listeners_lock);
+ return 0;
+ }
+ pthread_mutex_unlock(&pdcs->pdcs_listeners_lock);
+
+ if (!cmd(pdcs, 200, buf, errdesc, errlen)) {
+ free(buf); buf = NULL;
+ return 0;
+ }
+
+ free(buf); buf = NULL;
+ return l->l_id;
+}
+
+int CCONV
+pdc_enable_periodic_reports(pdc_session_t *pdcs, int periodms,
+ char *errdesc, int errlen)
+{
+ char *buf;
+ int res;
+ if(!pdcs)
+ return 0;
+
+ if (periodms <= 0) {
+ if (errdesc)
+ (void) snprintf(errdesc, errlen, "invalid period");
+ return 0;
+ }
+ if (pasprintf(&buf, "report %d report\n", periodms) < 0) {
+ if (errdesc)
+ (void) snprintf(errdesc, errlen, "%s", strerror(errno));
+ return 0;
+ }
+ res = cmd(pdcs, 200, buf, errdesc, errlen);
+ free(buf); buf = NULL;
+ return res;
+}
+
+int CCONV
+pdc_disable_periodic_reports(pdc_session_t *pdcs, char *errdesc,
+ int errlen)
+{
+ if(!pdcs)
+ return 0;
+ return cmd(pdcs, 200, "report 0 report\n", errdesc, errlen);
+}
+
+int CCONV
+pdc_flush(pdc_session_t *pdc, char *errdesc, int errlen)
+{
+ if(!pdc)
+ return 0;
+ return cmd(pdc, 200, "flush\n", errdesc, errlen);
+}
+
+int CCONV
+pdc_ignore(pdc_session_t *pdcs, pdc_listen_id_t id, char *errdesc,
+ int errlen)
+{
+ char *buf;
+ int res;
+
+ if(!pdcs)
+ return 0;
+
+ if (pasprintf(&buf, "ignore lid%d\n", id) < 0) {
+ if (errdesc)
+ (void) snprintf(errdesc, errlen, "%s", strerror(errno));
+ return 0;
+ }
+ res = cmd(pdcs, 200, buf, errdesc, errlen);
+ free(buf); buf = NULL;
+ return res;
+}
+
+//Async stuff starts here
+static void
+async_cmd_callback(pdc_session_t *pdcs, const char *cmd,
+ void (*r_notify)(pdc_session_t *, struct result *, int code,int final, const char *line), void *r_arg,
+ void (*error)(const char *errdesc, void *arg), void *arg);
+
+typedef struct {
+ int aca_desired;
+ void (*aca_error)(const char *errdesc, void *arg);
+ void *aca_error_arg;
+} async_cmd_arg_t;
+
+/*
+ * Default callback for async commands.
+ * If the code matches what we wanted, then we don't hear anything about it.
+ * Otherwise, we get the error callback.
+ */
+static void
+async_cmd_cb(pdc_session_t *pdcs, result_t *r, int code, int final,
+ const char *line)
+{
+ async_cmd_arg_t *aca;
+ char *buf;
+
+ assert(final);
+ aca = (async_cmd_arg_t *)r->r_arg;
+ if (aca->aca_desired != code) {
+ if (pasprintf(&buf, "protocol error: %s", line) > 0) {
+ if(aca->aca_error)
+ aca->aca_error(buf, aca->aca_error_arg);
+ free(buf); buf = NULL;
+ } else {
+ /* XXX warn about low-memory condition */
+ if(aca->aca_error)
+ aca->aca_error("protocol error (insufficient memory"
+ " to describe)", aca->aca_error_arg);
+ }
+ }
+ free(aca); aca = NULL;
+ free(r); r = NULL;
+}
+
+typedef struct {
+ void (*aaa_success)(void *arg, void (*error)(const char *errdesc, void *arg));
+ void (*aaa_error)(const char *errdesc, void *arg);
+ void *aaa_arg;
+ char *aaa_pass;
+} async_auth_arg_t;
+
+static void
+async_auth_cb(pdc_session_t *pdcs, result_t *r, int code, int final,
+ const char *line)
+{
+ async_auth_arg_t *aaa;
+
+ assert(final);
+ aaa = (async_auth_arg_t *)r->r_arg;
+
+ switch(code)
+ {
+ //Authentication needed
+ case 999:
+ {
+ int randomHash;
+ char buf[100];
+ md5_state_t state;
+ md5_byte_t digest[16];
+
+ int di;
+
+ randomHash = strtol(line, NULL, 0);
+
+ LOG(PHIDGET_LOG_DEBUG,"Got hash: %d",randomHash);
+
+ if(aaa->aaa_pass)
+ {
+ snprintf(buf,100,"%d%s",randomHash,aaa->aaa_pass);
+ }
+
+ md5_init(&state);
+ md5_append(&state, (const md5_byte_t *)buf, (int)strlen(buf));
+ md5_finish(&state, digest);
+
+ memset(buf, 0, sizeof(buf));
+
+ snprintf(buf, 5, "997 ");
+
+ for (di = 0; di < 16; ++di)
+ snprintf((buf+4) + di * 2, 3, "%02x", digest[di]);
+
+ buf[strlen(buf)] = '\n';
+
+ //send out the next async command
+ async_cmd_callback(pdcs, buf, async_auth_cb, aaa, aaa->aaa_error, aaa->aaa_arg);
+
+ goto exit_pending;
+ }
+ // Authentication failed
+ case 998:
+ LOG(PHIDGET_LOG_INFO,"Authentication Failed - bad password");
+ //send out the error event
+ if(aaa->aaa_error)
+ aaa->aaa_error("Authentication Failed - bad password", aaa->aaa_arg);
+ goto exit_done;
+ // Authentication is good, or not needed
+ case 996:
+ //make sure there is a verison - otherwise this is a really old webservice
+ {
+ char *versionstring = strstr(line, "version=");
+ if(!versionstring)
+ {
+ LOG(PHIDGET_LOG_ERROR,"Trying to connect to an old webservice. Webservice needs to be updated.");
+ //send out an error event
+ if(aaa->aaa_error)
+ aaa->aaa_error("Trying to connect to an old webservice. Webservice needs to be updated.", aaa->aaa_arg);
+ goto exit_done;
+ }
+ //It's good - this is the end of authentication
+ else
+ {
+ //send out auth_finished event
+ if(aaa->aaa_success)
+ aaa->aaa_success(aaa->aaa_arg, aaa->aaa_error);
+ }
+ }
+ goto exit_done;
+ // Version mismatch
+ case 994:
+ {
+ char buf[100];
+ snprintf(buf, sizeof(buf), "Version Mismatch; webservice:%s, expecting:%s",strlen(line)>24?(line+24):line,ws_protocol_ver);
+ LOG(PHIDGET_LOG_ERROR, buf);
+ //send out error event
+ if(aaa->aaa_error)
+ aaa->aaa_error(buf, aaa->aaa_arg);
+ }
+ goto exit_done;
+ case 500:
+ {
+ //callback an error
+ char buf[100];
+ snprintf(buf, sizeof(buf), "Network Error (probably a timeout occured): %s", line);
+ LOG(PHIDGET_LOG_ERROR, buf);
+ //send out error event
+ if(aaa->aaa_error)
+ aaa->aaa_error(buf, aaa->aaa_arg);
+ }
+ goto exit_done;
+ default:
+ //callback an error
+ if(aaa->aaa_error)
+ aaa->aaa_error("Unexpected response during authorization. Probably a version mismatch - upgrade the Webservice.", aaa->aaa_arg);
+ goto exit_done;
+ }
+
+exit_done:
+ free(aaa); aaa = NULL;
+exit_pending:
+ free(r); r = NULL;
+}
+
+/*
+ * Sends out an async command. Response comes back on the r_notify callback.
+ */
+static void
+async_cmd_callback(pdc_session_t *pdcs, const char *cmd,
+ void (*r_notify)(pdc_session_t *, struct result *, int code,int final, const char *line), void *r_arg,
+ void (*error)(const char *errdesc, void *arg), void *arg)
+{
+ static int tag = 1;
+ char errdesc[256];
+ result_t *r;
+ result_t *or;
+ char *buf;
+ int len;
+
+ if ((len = pasprintf(&buf, "T%d %s", tag, cmd)) < 0) {
+ if(error)
+ error(strerror(errno), arg);
+ return;
+ }
+ if (!(r = malloc(sizeof (*r)))) {
+ if(error)
+ error(strerror(errno), arg);
+ return;
+ }
+ /* add pending */
+ pthread_mutex_lock(&pdcs->pdcs_pending_lock);
+ r->r_tag = tag++;
+ r->r_notify = r_notify;
+ r->r_arg = r_arg;
+ ptree_replace(r, &pdcs->pdcs_pending, tagcmp, (void **)&or);
+ // if or != NULL then pdcs_pending already contained a node with tag == r.r_tag
+ assert(!or);
+
+ if (!pdcs->pdcs_write(pdcs->pdcs_wfd, buf, (int)strlen(buf), errdesc,
+ (unsigned int)sizeof (errdesc))) {
+ if(error)
+ error(errdesc, arg);
+ ptree_remove(r, &pdcs->pdcs_pending, tagcmp, (void **)&or);
+ if(r == or && r)
+ {
+ if(r->r_arg)
+ free(r->r_arg); r->r_arg = NULL;
+ free(r); r = NULL;
+ }
+ pthread_mutex_unlock(&pdcs->pdcs_pending_lock);
+ return;
+ }
+
+ pthread_mutex_unlock(&pdcs->pdcs_pending_lock);
+ free(buf); buf = NULL;
+}
+
+/*
+ * Sends out an async command. Errors come back on the error callback if desired does not match the response.
+ */
+static void
+async_cmd(pdc_session_t *pdcs, int desired, const char *cmd,
+ void (*error)(const char *errdesc, void *arg), void *arg)
+{
+ async_cmd_arg_t *aca;
+
+ if (!(aca = malloc(sizeof (*aca)))) {
+ if(error)
+ error(strerror(errno), arg);
+ return;
+ }
+
+ aca->aca_desired = desired;
+ aca->aca_error = error;
+ aca->aca_error_arg = arg;
+
+ async_cmd_callback(pdcs, cmd, async_cmd_cb, aca, error, arg);
+}
+
+typedef struct _pdc_session_and_arg_t{
+ pdc_session_t *pdcs;
+ void *r_arg;
+} pdc_session_and_arg_t;
+
+static ptree_walk_res_t
+clean_pending_async(const void *node, int level, void *arg, void *pwra)
+{
+ result_t *rk = (result_t *)node;
+ pdc_session_and_arg_t *a = (pdc_session_and_arg_t *)arg;
+ result_t *r;
+ char msg[1024];
+
+ if(rk->r_notify == &async_cmd_cb && ((async_cmd_arg_t *)rk->r_arg)->aca_error_arg == a->r_arg)
+ {
+ ptree_inorder_walk_remove(&a->pdcs->pdcs_pending, (void **)&r, pwra, tagcmp);
+ assert(rk == r);
+
+ snprintf(msg, 1024, "Socket was closed before command T%d finished.",r->r_tag);
+
+ //notify frees r
+ if(r->r_notify)
+ r->r_notify(a->pdcs, r, 500, PTRUE, msg);
+ }
+
+ return PTREE_WALK_CONTINUE;
+}
+
+static int
+async_pending_cmp(const void *arg, const void *tv)
+{
+ result_t *rk = (result_t *)tv;
+
+ if(rk->r_notify == &async_cmd_cb && ((async_cmd_arg_t *)rk->r_arg)->aca_error_arg == arg)
+ return 0;
+ return -1;
+}
+
+//If there are pending keys for this arg, then 1st wait up to 1 second for them to finish, then report the errors
+void
+cleanup_pending(pdc_session_t *pdcs, void *arg)
+{
+ int timeout = 500; //ms
+ pdc_session_and_arg_t a = {pdcs, arg};
+
+ pthread_mutex_lock(&pdcs->pdcs_pending_lock);
+ //TODO: Do this differently - can't use a different compare then the one used to add to the list!
+ while(ptree_contains(arg, pdcs->pdcs_pending, async_pending_cmp, NULL) && timeout>0)
+ {
+ pthread_mutex_unlock(&pdcs->pdcs_pending_lock);
+ SLEEP(10);
+ timeout-=10;
+ pthread_mutex_lock(&pdcs->pdcs_pending_lock);
+ }
+ if(timeout<=0)
+ {
+ ptree_walk(pdcs->pdcs_pending, PTREE_POSTORDER, clean_pending_async, tagcmp, &a);
+ }
+ pthread_mutex_unlock(&pdcs->pdcs_pending_lock);
+}
+
+//loop so long as there are any pending
+void
+wait_pending(pdc_session_t *pdcs)
+{
+ int timeout = 500; //ms
+
+ pthread_mutex_lock(&pdcs->pdcs_pending_lock);
+ while(pdcs->pdcs_pending && timeout>0)
+ {
+ pthread_mutex_unlock(&pdcs->pdcs_pending_lock);
+ SLEEP(10);
+ timeout-=10;
+ pthread_mutex_lock(&pdcs->pdcs_pending_lock);
+ }
+ pthread_mutex_unlock(&pdcs->pdcs_pending_lock);
+}
+
+void CCONV
+pdc_async_enable_periodic_reports(pdc_session_t *pdcs, int periodms,
+ void (*error)(const char *errdesc, void *arg),
+ void *arg)
+{
+ char *buf;
+
+ if(!pdcs)
+ return;
+
+ if (periodms <= 0) {
+ if (error)
+ error("invalid period", arg);
+ return;
+ }
+ if (pasprintf(&buf, "report %d report\n", periodms) < 0) {
+ if (error)
+ error(strerror(errno), arg);
+ return;
+ }
+ async_cmd(pdcs, 200, buf, error, arg);
+ free(buf); buf = NULL;
+}
+
+void CCONV
+pdc_async_disable_periodic_reports(pdc_session_t *pdcs, void (*error)(const char *errdesc, void *arg),
+ void *arg)
+{
+ if(!pdcs)
+ return;
+ async_cmd(pdcs, 200, "report 0 report\n", error, arg);
+}
+
+void CCONV
+pdc_async_set(pdc_session_t *pdcs, const char *key, const char *val,
+ int len, int remove_on_close, void (*error)(const char *errdesc, void *arg),
+ void *arg)
+{
+ char *escval;
+ char *buf;
+ if(!pdcs)
+ return;
+
+ if(val[0] == '\0')
+ {
+ if (!escape("\001", len, &escval)) {
+ if (error)
+ error(strerror(errno), arg);
+ return;
+ }
+ }
+ else
+ {
+ if (!escape(val, len, &escval)) {
+ if (error)
+ error(strerror(errno), arg);
+ return;
+ }
+ }
+ if (pasprintf(&buf, "set %s=\"%s\"%s\n", key, escval,
+ remove_on_close ? " for session" : "") < 0) {
+ free((void *)escval); escval = NULL;
+ if (error)
+ error(strerror(errno), arg);
+ return;
+ }
+ async_cmd(pdcs, 200, buf, error, arg);
+ free(buf); buf = NULL;
+ free((void *)escval); escval = NULL;
+}
+
+void CCONV
+pdc_async_ignore(pdc_session_t *pdcs, pdc_listen_id_t id,
+ void (*error)(const char *errdesc, void *arg), void *arg)
+{
+ char *buf;
+ if(!pdcs)
+ return;
+
+ if (pasprintf(&buf, "ignore lid%d\n", id) < 0) {
+ if (error)
+ error(strerror(errno), arg);
+ return;
+ }
+ async_cmd(pdcs, 200, buf, error, arg);
+ free(buf); buf = NULL;
+}
+
+void CCONV
+pdc_async_authorize(pdc_session_t *pdcs, const char *version, char *password,
+ void (*success) (void *arg, void (*error)(const char *errdesc, void *arg)),
+ void (*error)(const char *errdesc, void *arg), void *arg)
+{
+ char *buf;
+ async_auth_arg_t *aaa;
+
+ if(!pdcs)
+ return;
+
+ if (!(aaa = malloc(sizeof (*aaa)))) {
+ if(error)
+ error(strerror(errno), arg);
+ return;
+ }
+
+ aaa->aaa_success = success;
+ aaa->aaa_error = error;
+ aaa->aaa_arg = arg;
+ aaa->aaa_pass = password;
+
+ if (pasprintf(&buf, "995 authenticate, version=%s\n", version) < 0) {
+ if (error)
+ error(strerror(errno), arg);
+ return;
+ }
+
+ //200 is bogus - I want to get the callback on any response
+ async_cmd_callback(pdcs, buf, async_auth_cb, aaa, error, arg);
+ free(buf); buf = NULL;
+}
+
+void CCONV
+pdc_async_remove(pdc_session_t *pdcs, const char *pattern, void (*error)(const char *errdesc, void *arg), void *arg)
+{
+ char *buf;
+
+ if(!pdcs)
+ return;
+
+ if (pasprintf(&buf, "remove %s\n", pattern) < 0) {
+ if (error)
+ error(strerror(errno), arg);
+ return;
+ }
+ async_cmd(pdcs, 200, buf, error, arg);
+ free(buf); buf = NULL;
+}
+
+int CCONV
+pdc_quit(pdc_session_t *pdc, char *errdesc, int errlen)
+{
+ return cmd(pdc, 200, "quit\n", errdesc, errlen);
+}
+
+int CCONV
+pdc_remove(pdc_session_t *pdcs, const char *pattern, char *errdesc, int errlen)
+{
+ char *buf;
+ int res;
+
+ if(!pdcs)
+ return 0;
+
+ if (pasprintf(&buf, "remove %s\n", pattern) < 0) {
+ if (errdesc)
+ (void) snprintf(errdesc, errlen, "%s", strerror(errno));
+ return 0;
+ }
+ res = cmd(pdcs, 200, buf, errdesc, errlen);
+ free(buf); buf = NULL;
+ return res;
+}
+
+int CCONV
+pdc_get(pdc_session_t *pdcs, const char *key, char *val, int vallen, char *errdesc, int errlen)
+{
+ char *buf, *results;
+ int res, resultsize;
+
+ if(!pdcs)
+ return 0;
+
+ resultsize = vallen + 30;
+
+ results = (char *)malloc(resultsize);
+
+ if (pasprintf(&buf, "get %s\n", key) < 0) {
+ if (errdesc)
+ (void) snprintf(errdesc, errlen, "%s", strerror(errno));
+ free(results);
+ return 0;
+ }
+ res = jcmd(pdcs, buf, 200, &results, resultsize, errdesc, errlen);
+ if(res)
+ {
+ char *ueval, *eol, *resultval;
+ unsigned int uevlen;
+
+ if ((eol = strchr(results, '\n')))
+ {
+ eol[0] = '\0';
+ }
+ if(!(resultval = strstr(results, "value ")))
+ {
+ val[0] = 0;
+ goto end;
+ }
+ resultval += 6;
+
+ if (!unescape(resultval, &ueval, &uevlen)) {
+ /* XXX log */
+ goto end;
+ }
+ strncpy(val, ueval, vallen-1);
+ val[vallen-1]='\0';
+ free(ueval);
+ }
+
+end:
+ free(buf);
+ free(results);
+ return res;
+}
+
+static pdict_reason_t
+_pdict_reason_from_str(const char *s)
+{
+ if (strcmp(s, "changed") == 0)
+ return PDR_VALUE_CHANGED;
+ if (strcmp(s, "current") == 0)
+ return PDR_CURRENT_VALUE;
+ if (strcmp(s, "added") == 0)
+ return PDR_ENTRY_ADDED;
+ if (strcmp(s, "removing") == 0)
+ return PDR_ENTRY_REMOVING;
+ return 0;
+}
+
+int CCONV
+pdc_get_server_session_id(pdc_session_t *pdc, int *id, char *errdesc,
+ int errlen)
+{
+ char reply[80];
+ char *buf;
+ int res;
+
+ if(!pdc)
+ return 0;
+
+ if (pasprintf(&buf, "get session id\n") < 0) {
+ if (errdesc)
+ (void) snprintf(errdesc, errlen, "%s", strerror(errno));
+ return 0;
+ }
+ res = jcmd(pdc, buf, 200, (char **)&reply, sizeof (reply), errdesc, errlen);
+ free(buf); buf = NULL;
+
+ if (res && id)
+ *id = atoi(reply);
+ return res;
+}
+
+int CCONV
+pdc_readthread_join(pdc_session_t *pdcs, void **status)
+{
+ int res=0;
+ if(pdcs)
+ {
+ if(pdcs->pdcs_resultreader)
+ res = pthread_join(pdcs->pdcs_resultreader, status);
+ pdcs->pdcs_resultreader = 0;
+ }
+ return res;
+}
diff --git a/dict/pdictclient.h b/dict/pdictclient.h
new file mode 100644
index 0000000..1fa60d9
--- /dev/null
+++ b/dict/pdictclient.h
@@ -0,0 +1,128 @@
+#ifndef _PDICTCLIENT_H_
+#define _PDICTCLIENT_H_
+
+#include "pdict.h"
+
+typedef struct pdc_session pdc_session_t;
+typedef int pdc_listen_id_t;
+
+int CCONV pdc_init(void);
+
+pdc_session_t * CCONV
+pdc_session_alloc(int readfd,
+ int(*readfunc)(int, void *, unsigned int, char *, int),
+ int writefd,
+ int(*writefunc)(int, const void *, unsigned int, char *, int),
+ int(*closefunc)(int, char *, int),
+ void *cleanupPtr,
+ void (*cleanupFunc)(void *));
+
+void
+pdc_session_free(pdc_session_t *pdcs);
+
+//int CCONV pdc_set(pdc_session_t *pdcs, const char *key, const char *val, int len, int remove_on_close, char *errdesc, int errlen);
+void CCONV pdc_async_set(pdc_session_t *pdcs,
+ const char *key,
+ const char *val,
+ int len,
+ int remove_on_close,
+ void (*error)(const char *errdesc, void *arg),
+ void *arg);
+
+pdc_listen_id_t CCONV
+pdc_listen(pdc_session_t *pdcs,
+ const char *pattern,
+ void (*cb)(const char *, const char *, unsigned int, pdict_reason_t, void *),
+ void *ptr,
+ char *errdesc,
+ int errlen);
+
+int CCONV
+pdc_disable_periodic_reports(pdc_session_t *pdc,
+ char *errdesc,
+ int errlen);
+
+void CCONV
+pdc_async_disable_periodic_reports(pdc_session_t *pdc,
+ void (*error)(const char *errdesc, void *arg),
+ void *arg);
+
+int CCONV
+pdc_enable_periodic_reports(pdc_session_t *pdc,
+ int periodms,
+ char *errdesc,
+ int errlen);
+
+void CCONV
+pdc_async_enable_periodic_reports(pdc_session_t *pdc,
+ int periodms,
+ void (*error)(const char *errdesc, void *arg),
+ void *arg);
+
+int CCONV
+pdc_ignore(pdc_session_t *pdcs,
+ pdc_listen_id_t id,
+ char *errdesc,
+ int errlen);
+
+void CCONV
+pdc_async_ignore(pdc_session_t *pdcs,
+ pdc_listen_id_t id,
+ void (*error)(const char *errdesc, void *arg),
+ void *arg);
+
+int CCONV
+pdc_flush(pdc_session_t *pdc,
+ char *errdesc,
+ int errlen);
+
+int CCONV
+pdc_quit(pdc_session_t *pdc,
+ char *errdesc,
+ int errlen);
+
+int CCONV
+pdc_remove(pdc_session_t *pdc,
+ const char *pattern,
+ char *errdesc,
+ int errlen);
+
+void CCONV
+pdc_async_remove(pdc_session_t *pdcs,
+ const char *pattern,
+ void (*error)(const char *errdesc, void *arg),
+ void *arg);
+
+int CCONV
+pdc_get(pdc_session_t *pdcs,
+ const char *pattern,
+ char *results,
+ int resultslen,
+ char *errdesc,
+ int errlen);
+
+int CCONV
+pdc_get_server_session_id(pdc_session_t *pdc,
+ int *id,
+ char *errdesc,
+ int errlen);
+
+int CCONV
+pdc_readthread_join(pdc_session_t *pdcs,
+ void **status);
+
+void CCONV
+pdc_async_authorize(pdc_session_t *pdcs,
+ const char *version,
+ char *password,
+ void (*success) (void *arg, void (*error)(const char *errdesc, void *arg)),
+ void (*error)(const char *errdesc, void *arg),
+ void *arg);
+
+void
+cleanup_pending(pdc_session_t *pdcs, void *arg);
+
+void
+wait_pending(pdc_session_t *pdcs);
+
+#endif
diff --git a/examples/Makefile.am b/examples/Makefile.am
new file mode 100644
index 0000000..5de19aa
--- /dev/null
+++ b/examples/Makefile.am
@@ -0,0 +1,7 @@
+## Process this file with automake to produce Makefile.in
+
+noinst_PROGRAMS = ifkit \
+manager \
+phidgetsbclist
+
+AM_LDFLAGS = -lphidget21 \ No newline at end of file
diff --git a/examples/Makefile.in b/examples/Makefile.in
new file mode 100644
index 0000000..157dfd0
--- /dev/null
+++ b/examples/Makefile.in
@@ -0,0 +1,499 @@
+# Makefile.in generated by automake 1.11 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+noinst_PROGRAMS = ifkit$(EXEEXT) manager$(EXEEXT) \
+ phidgetsbclist$(EXEEXT)
+subdir = examples
+DIST_COMMON = README $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+PROGRAMS = $(noinst_PROGRAMS)
+ifkit_SOURCES = ifkit.c
+ifkit_OBJECTS = ifkit.$(OBJEXT)
+ifkit_LDADD = $(LDADD)
+AM_V_lt = $(am__v_lt_$(V))
+am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY))
+am__v_lt_0 = --silent
+manager_SOURCES = manager.c
+manager_OBJECTS = manager.$(OBJEXT)
+manager_LDADD = $(LDADD)
+phidgetsbclist_SOURCES = phidgetsbclist.c
+phidgetsbclist_OBJECTS = phidgetsbclist.$(OBJEXT)
+phidgetsbclist_LDADD = $(LDADD)
+DEFAULT_INCLUDES = -I.@am__isrc@
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_$(V))
+am__v_CC_ = $(am__v_CC_$(AM_DEFAULT_VERBOSITY))
+am__v_CC_0 = @echo " CC " $@;
+AM_V_at = $(am__v_at_$(V))
+am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY))
+am__v_at_0 = @
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_$(V))
+am__v_CCLD_ = $(am__v_CCLD_$(AM_DEFAULT_VERBOSITY))
+am__v_CCLD_0 = @echo " CCLD " $@;
+AM_V_GEN = $(am__v_GEN_$(V))
+am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY))
+am__v_GEN_0 = @echo " GEN " $@;
+SOURCES = ifkit.c manager.c phidgetsbclist.c
+DIST_SOURCES = ifkit.c manager.c phidgetsbclist.c
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDCONFIG = @LDCONFIG@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+AM_LDFLAGS = -lphidget21
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu examples/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu examples/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstPROGRAMS:
+ @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \
+ echo " rm -f" $$list; \
+ rm -f $$list || exit $$?; \
+ test -n "$(EXEEXT)" || exit 0; \
+ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f" $$list; \
+ rm -f $$list
+ifkit$(EXEEXT): $(ifkit_OBJECTS) $(ifkit_DEPENDENCIES)
+ @rm -f ifkit$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(ifkit_OBJECTS) $(ifkit_LDADD) $(LIBS)
+manager$(EXEEXT): $(manager_OBJECTS) $(manager_DEPENDENCIES)
+ @rm -f manager$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(manager_OBJECTS) $(manager_LDADD) $(LIBS)
+phidgetsbclist$(EXEEXT): $(phidgetsbclist_OBJECTS) $(phidgetsbclist_DEPENDENCIES)
+ @rm -f phidgetsbclist$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(phidgetsbclist_OBJECTS) $(phidgetsbclist_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ifkit.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/manager.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/phidgetsbclist.Po@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(PROGRAMS)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstPROGRAMS ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/examples/README b/examples/README
new file mode 100644
index 0000000..164da02
--- /dev/null
+++ b/examples/README
@@ -0,0 +1,13 @@
+Phidgets examples for Linux
+Version 2.1.4
+August 22, 2008
+--------------------------------------------------------------------------
+Included are two simple examples to get you started with Phidgets
+and linux in C.
+
+A full set of linux examples are available from www.phidets.com, as
+well as examples in many other languages.
+
+Also included here is the phidgetsbclist utility, which will list all
+of the PhidgetSBCs found on the network. This utility requires that
+Avahi be installed to work properly. \ No newline at end of file
diff --git a/examples/ifkit.c b/examples/ifkit.c
new file mode 100644
index 0000000..8eaded7
--- /dev/null
+++ b/examples/ifkit.c
@@ -0,0 +1,136 @@
+// InterfacekitTest.cpp : Defines the entry point for the console application.
+//
+
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <phidget21.h>
+
+void display_generic_properties(CPhidgetHandle phid)
+{
+ int sernum, version;
+ const char *deviceptr, *label;
+ CPhidget_getDeviceType(phid, &deviceptr);
+ CPhidget_getSerialNumber(phid, &sernum);
+ CPhidget_getDeviceVersion(phid, &version);
+ CPhidget_getDeviceLabel(phid, &label);
+
+ printf("%s\n", deviceptr);
+ printf("Version: %8d SerialNumber: %10d\n", version, sernum);
+ printf("Label: %s\n", label);
+ return;
+}
+
+
+int IFK_DetachHandler(CPhidgetHandle IFK, void *userptr)
+{
+ printf("Detach handler ran!\n");
+ return 0;
+}
+
+int IFK_ErrorHandler(CPhidgetHandle IFK, void *userptr, int ErrorCode, const char *ErrorString)
+{
+ printf("Error handler: %d, %s\n", ErrorCode, ErrorString);
+ return 0;
+}
+
+int IFK_OutputChangeHandler(CPhidgetInterfaceKitHandle IFK, void *userptr, int Index, int Value)
+{
+ printf("Output %d is %d\n", Index, Value);
+ return 0;
+}
+
+int IFK_InputChangeHandler(CPhidgetInterfaceKitHandle IFK, void *userptr, int Index, int Value)
+{
+ printf("Input %d is %d\n", Index, Value);
+ return 0;
+}
+
+int IFK_SensorChangeHandler(CPhidgetInterfaceKitHandle IFK, void *userptr, int Index, int Value)
+{
+ printf("Sensor %d is %d\n", Index, Value);
+ return 0;
+}
+
+
+int IFK_AttachHandler(CPhidgetHandle IFK, void *userptr)
+{
+ //CPhidgetInterfaceKit_setSensorChangeTrigger((CPhidgetInterfaceKitHandle)IFK, 0, 0);
+ printf("Attach handler ran!\n");
+ return 0;
+}
+
+int test_interfacekit()
+{
+ int numInputs, numOutputs, numSensors;
+ int err;
+ CPhidgetInterfaceKitHandle IFK = 0;
+
+ CPhidget_enableLogging(PHIDGET_LOG_VERBOSE, NULL);
+
+ CPhidgetInterfaceKit_create(&IFK);
+
+ CPhidgetInterfaceKit_set_OnInputChange_Handler(IFK, IFK_InputChangeHandler, NULL);
+ CPhidgetInterfaceKit_set_OnOutputChange_Handler(IFK, IFK_OutputChangeHandler, NULL);
+ CPhidgetInterfaceKit_set_OnSensorChange_Handler(IFK, IFK_SensorChangeHandler, NULL);
+ CPhidget_set_OnAttach_Handler((CPhidgetHandle)IFK, IFK_AttachHandler, NULL);
+ CPhidget_set_OnDetach_Handler((CPhidgetHandle)IFK, IFK_DetachHandler, NULL);
+ CPhidget_set_OnError_Handler((CPhidgetHandle)IFK, IFK_ErrorHandler, NULL);
+
+ CPhidget_open((CPhidgetHandle)IFK, -1);
+
+ //wait 5 seconds for attachment
+ if((err = CPhidget_waitForAttachment((CPhidgetHandle)IFK, 0)) != EPHIDGET_OK )
+ {
+ const char *errStr;
+ CPhidget_getErrorDescription(err, &errStr);
+ printf("Error waiting for attachment: (%d): %s\n",err,errStr);
+ goto exit;
+ }
+
+ display_generic_properties((CPhidgetHandle)IFK);
+ CPhidgetInterfaceKit_getOutputCount((CPhidgetInterfaceKitHandle)IFK, &numOutputs);
+ CPhidgetInterfaceKit_getInputCount((CPhidgetInterfaceKitHandle)IFK, &numInputs);
+ CPhidgetInterfaceKit_getSensorCount((CPhidgetInterfaceKitHandle)IFK, &numSensors);
+
+ CPhidgetInterfaceKit_setOutputState((CPhidgetInterfaceKitHandle)IFK, 0, 1);
+
+ printf("Sensors:%d Inputs:%d Outputs:%d\n", numSensors, numInputs, numOutputs);
+
+ //err = CPhidget_setDeviceLabel((CPhidgetHandle)IFK, "test");
+
+ while(1)
+ {
+ sleep(1);
+ }
+
+ while(1)
+ {
+ CPhidgetInterfaceKit_setOutputState(IFK, 7, 1);
+ CPhidgetInterfaceKit_setOutputState(IFK, 7, 0);
+ }
+
+ CPhidgetInterfaceKit_setOutputState(IFK, 0, 1);
+ sleep(1);
+ CPhidgetInterfaceKit_setOutputState(IFK, 0, 0);
+ sleep(1);
+ CPhidgetInterfaceKit_setOutputState(IFK, 0, 1);
+ sleep(1);
+ CPhidgetInterfaceKit_setOutputState(IFK, 0, 0);
+
+ sleep(5);
+
+exit:
+ CPhidget_close((CPhidgetHandle)IFK);
+ CPhidget_delete((CPhidgetHandle)IFK);
+
+ return 0;
+}
+
+int main(int argc, char* argv[])
+{
+ test_interfacekit();
+ return 0;
+}
+
diff --git a/examples/manager.c b/examples/manager.c
new file mode 100644
index 0000000..412b7de
--- /dev/null
+++ b/examples/manager.c
@@ -0,0 +1,73 @@
+/*
+* manager.cpp
+*
+* Patrick McNeil - July 19, 2005
+*
+* Simple program to list all Phidgets that are added and removed from the system
+*/
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include "phidget21.h"
+#include <signal.h>
+
+int something;
+static int exitMan = 0;
+
+void sighandler (int n)
+{
+ printf ("got a signal. exiting.\n");
+ exitMan = 1;
+}
+
+int gotAttach(CPhidgetHandle phid, void *ptr) {
+ const char *id, *label;
+ int serial, version;
+
+ //print out some info
+ CPhidget_getDeviceLabel(phid, &label);
+ CPhidget_getSerialNumber(phid, &serial);
+ CPhidget_getDeviceVersion(phid, &version);
+ CPhidget_getDeviceType(phid, &id);
+ printf("Device Added: %s, Serial: %d, Version: %d Label: %s\n",id,serial,version,label);
+
+ return 0;
+}
+
+int gotDetach(CPhidgetHandle phid, void *ptr) {
+ char *id;
+ int serial, version;
+
+ //print out some info
+ CPhidget_getSerialNumber(phid, &serial);
+ CPhidget_getDeviceVersion(phid, &version);
+ CPhidget_getDeviceType((CPhidgetHandle)phid,(const char **)&id);
+ printf("Device Removed: %s, Serial: %d, Version: %d\n",id,serial,version);
+
+ return 0;
+}
+
+
+int main()
+{
+ CPhidgetManagerHandle phidm;
+
+ //CPhidget_enableLogging(PHIDGET_LOG_VERBOSE, NULL);
+
+ CPhidgetManager_create(&phidm);
+ CPhidgetManager_set_OnAttach_Handler(phidm, gotAttach, NULL);
+ CPhidgetManager_set_OnDetach_Handler(phidm, gotDetach, NULL);
+ CPhidgetManager_open(phidm);
+
+ signal (SIGTERM, sighandler);
+ signal (SIGINT, sighandler);
+
+while(!exitMan)
+ sleep(5);
+
+ printf ("Removing resources.\n");
+ CPhidgetManager_close(phidm);
+ CPhidgetManager_delete(phidm);
+ return 0;
+}
diff --git a/examples/phidgetsbclist.c b/examples/phidgetsbclist.c
new file mode 100644
index 0000000..14a719e
--- /dev/null
+++ b/examples/phidgetsbclist.c
@@ -0,0 +1,104 @@
+/*
+ * phidgetsbclist.c
+ *
+ * Displays a dynamic list of PhidgetSBCs on the network.
+ *
+ * Created by Patrick Mcneil on 22/08/08.
+ * Copyright 2008 Phidgets Inc.. All rights reserved.
+ *
+ */
+
+#include <stdio.h>
+#include <phidget21.h>
+
+//Define these here because they are not in the standard .h file
+typedef struct _CPhidgetSBC *CPhidgetSBCHandle;
+typedef struct _CPhidgetSBCManager *CPhidgetSBCManagerHandle;
+int CPhidgetSBCManager_create(CPhidgetSBCManagerHandle *sbcm);
+int CPhidgetSBCManager_start(CPhidgetSBCManagerHandle sbcm);
+int CPhidgetSBCManager_stop(CPhidgetSBCManagerHandle sbcm);
+int CPhidgetSBCManager_delete(CPhidgetSBCManagerHandle sbcm);
+int CPhidgetSBCManager_set_OnAttach_Handler(CPhidgetSBCManagerHandle sbcm, int ( *fptr)(CPhidgetSBCHandle sbc, void *userPtr), void *userPtr);
+int CPhidgetSBCManager_set_OnDetach_Handler(CPhidgetSBCManagerHandle sbcm, int ( *fptr)(CPhidgetSBCHandle sbc, void *userPtr), void *userPtr);int CPhidgetSBCManager_set_OnError_Handler(CPhidgetSBCManagerHandle sbcm, int( *fptr)(CPhidgetSBCManagerHandle sbcm, void *userPtr, int errorCode, const char *errorString), void *userPtr);
+int CPhidgetSBC_getFirmwareVersion(CPhidgetSBCHandle sbc, const char **firmwareVersion);
+int CPhidgetSBC_getHardwareVersion(CPhidgetSBCHandle sbc, int *hardwareVersion);
+int CPhidgetSBC_getMacAddress(CPhidgetSBCHandle sbc, const char **macAddress);
+int CPhidgetSBC_getAddress(CPhidgetSBCHandle sbc, const char **ipAddr);
+int CPhidgetSBC_getHostname(CPhidgetSBCHandle sbc, const char **hostname);
+int CPhidgetSBC_getDeviceName(CPhidgetSBCHandle sbc, const char **name);
+
+
+int display_device_info(CPhidgetSBCHandle sbc)
+{
+ int hardwareVersion;
+ const char *firmwareVersion, *macAddress, *address, *hostname, *name;
+
+ CPhidgetSBC_getFirmwareVersion(sbc, &firmwareVersion);
+ CPhidgetSBC_getHardwareVersion(sbc, &hardwareVersion);
+ CPhidgetSBC_getMacAddress(sbc, &macAddress);
+ CPhidgetSBC_getHostname(sbc, &hostname);
+ CPhidgetSBC_getDeviceName(sbc, &name);
+ if(CPhidgetSBC_getAddress(sbc, &address) != EPHIDGET_OK)
+ address = NULL;
+
+ printf(" Device Name: %s\n",name);
+ printf(" MAC Address: %s\n",macAddress);
+ printf(" Address: %s\n",address?address:"(Unknown)");
+ printf(" Hostname: %s\n",hostname);
+ printf(" Hardware Version: %d\n",hardwareVersion);
+ printf(" Firmware Version: %s\n",firmwareVersion);
+
+ return 0;
+}
+
+int attach(CPhidgetSBCHandle sbc, void *userPtr)
+{
+ printf("===ATTACH===\n");
+ display_device_info(sbc);
+ return 0;
+}
+
+int detach(CPhidgetSBCHandle sbc, void *userPtr)
+{
+ printf("===DETACH===\n");
+ display_device_info(sbc);
+ return 0;
+}
+
+int error(CPhidgetSBCManagerHandle sbcm, void *userPtr, int errorCode, const char *errorString)
+{
+ printf("Error Event: (%d) %s\n", errorCode, errorString);
+ return 0;
+}
+
+int main(int argc, char *argv[])
+{
+ int result;
+ CPhidgetSBCManagerHandle sbcm;
+
+ CPhidgetSBCManager_create(&sbcm);
+
+ CPhidgetSBCManager_set_OnAttach_Handler(sbcm, attach, NULL);
+ CPhidgetSBCManager_set_OnDetach_Handler(sbcm, detach, NULL);
+ CPhidgetSBCManager_set_OnError_Handler(sbcm, error, NULL);
+
+ result = CPhidgetSBCManager_start(sbcm);
+
+ if(result != EPHIDGET_OK)
+ {
+ const char *err;
+ CPhidget_getErrorDescription(result, &err);
+ printf("Error: (%d) %s\n", result, err);
+ return 1;
+ }
+
+ printf("Press any key to end\n");
+ getchar();
+ printf("Closing...\n");
+
+ CPhidgetSBCManager_stop(sbcm);
+ CPhidgetSBCManager_delete(sbcm);
+
+ return 0;
+}
+
diff --git a/hotplug/phidgets b/hotplug/phidgets
new file mode 100644
index 0000000..f9fbb48
--- /dev/null
+++ b/hotplug/phidgets
@@ -0,0 +1,7 @@
+#!/bin/bash
+
+if [ "$ACTION" = "add" ] && [ -f "$DEVICE" ]
+then
+ chmod 666 "$DEVICE"
+fi
+
diff --git a/hotplug/phidgets.usermap b/hotplug/phidgets.usermap
new file mode 100644
index 0000000..cf70b59
--- /dev/null
+++ b/hotplug/phidgets.usermap
@@ -0,0 +1,134 @@
+# Very Old Phidgets
+phidgets 0x0003 0x0925 0x8201 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x0925 0x8101 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x0925 0x8104 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+
+# All current and future Phidgets
+phidgets 0x0003 0x06c2 0x0030 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x0031 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x0032 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x0033 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x0034 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x0035 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x0036 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x0037 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x0038 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x0039 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x003a 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x003b 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x003c 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x003d 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x003e 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x003f 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x0040 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x0041 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x0042 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x0043 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x0044 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x0045 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x0046 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x0047 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x0048 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x0049 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x004a 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x004b 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x004c 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x004d 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x004e 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x004f 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x0050 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x0051 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x0052 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x0053 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x0054 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x0055 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x0056 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x0057 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x0058 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x0059 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x005a 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x005b 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x005c 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x005d 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x005e 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x005f 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x0060 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x0061 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x0062 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x0063 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x0064 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x0065 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x0066 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x0067 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x0068 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x0069 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x006a 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x006b 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x006c 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x006d 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x006e 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x006f 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x0070 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x0071 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x0072 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x0073 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x0074 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x0075 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x0076 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x0077 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x0078 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x0079 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x007a 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x007b 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x007c 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x007d 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x007e 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x007f 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x0080 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x0081 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x0082 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x0083 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x0084 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x0085 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x0086 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x0087 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x0088 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x0089 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x008a 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x008b 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x008c 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x008d 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x008e 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x008f 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x0090 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x0091 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x0092 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x0093 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x0094 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x0095 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x0096 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x0097 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x0098 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x0099 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x009a 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x009b 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x009c 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x009d 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x009e 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x009f 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x00a0 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x00a1 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x00a2 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x00a3 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x00a4 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x00a5 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x00a6 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x00a7 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x00a8 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x00a9 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x00aa 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x00ab 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x00ac 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x00ad 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x00ae 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+phidgets 0x0003 0x06c2 0x00af 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000 \ No newline at end of file
diff --git a/include/dns_sd.h b/include/dns_sd.h
new file mode 100644
index 0000000..b6a2081
--- /dev/null
+++ b/include/dns_sd.h
@@ -0,0 +1,2359 @@
+/* -*- Mode: C; tab-width: 4 -*-
+ *
+ * Copyright (c) 2003-2004, Apple Computer, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/*! @header DNS Service Discovery
+ *
+ * @discussion This section describes the functions, callbacks, and data structures
+ * that make up the DNS Service Discovery API.
+ *
+ * The DNS Service Discovery API is part of Bonjour, Apple's implementation
+ * of zero-configuration networking (ZEROCONF).
+ *
+ * Bonjour allows you to register a network service, such as a
+ * printer or file server, so that it can be found by name or browsed
+ * for by service type and domain. Using Bonjour, applications can
+ * discover what services are available on the network, along with
+ * all the information -- such as name, IP address, and port --
+ * necessary to access a particular service.
+ *
+ * In effect, Bonjour combines the functions of a local DNS server and
+ * AppleTalk. Bonjour allows applications to provide user-friendly printer
+ * and server browsing, among other things, over standard IP networks.
+ * This behavior is a result of combining protocols such as multicast and
+ * DNS to add new functionality to the network (such as multicast DNS).
+ *
+ * Bonjour gives applications easy access to services over local IP
+ * networks without requiring the service or the application to support
+ * an AppleTalk or a Netbeui stack, and without requiring a DNS server
+ * for the local network.
+ */
+
+
+/* _DNS_SD_H contains the mDNSResponder version number for this header file, formatted as follows:
+ * Major part of the build number * 10000 +
+ * minor part of the build number * 100
+ * For example, Mac OS X 10.4.9 has mDNSResponder-108.4, which would be represented as
+ * version 1080400. This allows C code to do simple greater-than and less-than comparisons:
+ * e.g. an application that requires the DNSServiceGetProperty() call (new in mDNSResponder-126) can check:
+ *
+ * #if _DNS_SD_H+0 >= 1260000
+ * ... some C code that calls DNSServiceGetProperty() ...
+ * #endif
+ *
+ * The version defined in this header file symbol allows for compile-time
+ * checking, so that C code building with earlier versions of the header file
+ * can avoid compile errors trying to use functions that aren't even defined
+ * in those earlier versions. Similar checks may also be performed at run-time:
+ * => weak linking -- to avoid link failures if run with an earlier
+ * version of the library that's missing some desired symbol, or
+ * => DNSServiceGetProperty(DaemonVersion) -- to verify whether the running daemon
+ * ("system service" on Windows) meets some required minimum functionality level.
+ */
+
+#ifndef _DNS_SD_H
+#define _DNS_SD_H 2140308
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* standard calling convention under Win32 is __stdcall */
+/* Note: When compiling Intel EFI (Extensible Firmware Interface) under MS Visual Studio, the */
+/* _WIN32 symbol is defined by the compiler even though it's NOT compiling code for Windows32 */
+#if defined(_WIN32) && !defined(EFI32) && !defined(EFI64)
+#define DNSSD_API __stdcall
+#else
+#define DNSSD_API
+#endif
+
+/* stdint.h does not exist on FreeBSD 4.x; its types are defined in sys/types.h instead */
+#if defined(__FreeBSD__) && (__FreeBSD__ < 5)
+#include <sys/types.h>
+
+/* Likewise, on Sun, standard integer types are in sys/types.h */
+#elif defined(__sun__)
+#include <sys/types.h>
+
+/* EFI does not have stdint.h, or anything else equivalent */
+#elif defined(EFI32) || defined(EFI64) || defined(EFIX64)
+#include "Tiano.h"
+#if !defined(_STDINT_H_)
+typedef UINT8 uint8_t;
+typedef INT8 int8_t;
+typedef UINT16 uint16_t;
+typedef INT16 int16_t;
+typedef UINT32 uint32_t;
+typedef INT32 int32_t;
+#endif
+/* Windows has its own differences */
+#elif defined(_WIN32)
+#include <windows.h>
+#define _UNUSED
+#ifndef _MSL_STDINT_H
+typedef UINT8 uint8_t;
+typedef INT8 int8_t;
+typedef UINT16 uint16_t;
+typedef INT16 int16_t;
+typedef UINT32 uint32_t;
+typedef INT32 int32_t;
+#endif
+
+/* All other Posix platforms use stdint.h */
+#else
+#include <stdint.h>
+#endif
+
+/* DNSServiceRef, DNSRecordRef
+ *
+ * Opaque internal data types.
+ * Note: client is responsible for serializing access to these structures if
+ * they are shared between concurrent threads.
+ */
+
+typedef struct _DNSServiceRef_t *DNSServiceRef;
+typedef struct _DNSRecordRef_t *DNSRecordRef;
+
+struct sockaddr;
+
+/*! @enum General flags
+ * Most DNS-SD API functions and callbacks include a DNSServiceFlags parameter.
+ * As a general rule, any given bit in the 32-bit flags field has a specific fixed meaning,
+ * regardless of the function or callback being used. For any given function or callback,
+ * typically only a subset of the possible flags are meaningful, and all others should be zero.
+ * The discussion section for each API call describes which flags are valid for that call
+ * and callback. In some cases, for a particular call, it may be that no flags are currently
+ * defined, in which case the DNSServiceFlags parameter exists purely to allow future expansion.
+ * In all cases, developers should expect that in future releases, it is possible that new flag
+ * values will be defined, and write code with this in mind. For example, code that tests
+ * if (flags == kDNSServiceFlagsAdd) ...
+ * will fail if, in a future release, another bit in the 32-bit flags field is also set.
+ * The reliable way to test whether a particular bit is set is not with an equality test,
+ * but with a bitwise mask:
+ * if (flags & kDNSServiceFlagsAdd) ...
+ */
+enum
+ {
+ kDNSServiceFlagsMoreComing = 0x1,
+ /* MoreComing indicates to a callback that at least one more result is
+ * queued and will be delivered following immediately after this one.
+ * When the MoreComing flag is set, applications should not immediately
+ * update their UI, because this can result in a great deal of ugly flickering
+ * on the screen, and can waste a great deal of CPU time repeatedly updating
+ * the screen with content that is then immediately erased, over and over.
+ * Applications should wait until until MoreComing is not set, and then
+ * update their UI when no more changes are imminent.
+ * When MoreComing is not set, that doesn't mean there will be no more
+ * answers EVER, just that there are no more answers immediately
+ * available right now at this instant. If more answers become available
+ * in the future they will be delivered as usual.
+ */
+
+ kDNSServiceFlagsAdd = 0x2,
+ kDNSServiceFlagsDefault = 0x4,
+ /* Flags for domain enumeration and browse/query reply callbacks.
+ * "Default" applies only to enumeration and is only valid in
+ * conjunction with "Add". An enumeration callback with the "Add"
+ * flag NOT set indicates a "Remove", i.e. the domain is no longer
+ * valid.
+ */
+
+ kDNSServiceFlagsNoAutoRename = 0x8,
+ /* Flag for specifying renaming behavior on name conflict when registering
+ * non-shared records. By default, name conflicts are automatically handled
+ * by renaming the service. NoAutoRename overrides this behavior - with this
+ * flag set, name conflicts will result in a callback. The NoAutorename flag
+ * is only valid if a name is explicitly specified when registering a service
+ * (i.e. the default name is not used.)
+ */
+
+ kDNSServiceFlagsShared = 0x10,
+ kDNSServiceFlagsUnique = 0x20,
+ /* Flag for registering individual records on a connected
+ * DNSServiceRef. Shared indicates that there may be multiple records
+ * with this name on the network (e.g. PTR records). Unique indicates that the
+ * record's name is to be unique on the network (e.g. SRV records).
+ */
+
+ kDNSServiceFlagsBrowseDomains = 0x40,
+ kDNSServiceFlagsRegistrationDomains = 0x80,
+ /* Flags for specifying domain enumeration type in DNSServiceEnumerateDomains.
+ * BrowseDomains enumerates domains recommended for browsing, RegistrationDomains
+ * enumerates domains recommended for registration.
+ */
+
+ kDNSServiceFlagsLongLivedQuery = 0x100,
+ /* Flag for creating a long-lived unicast query for the DNSServiceQueryRecord call. */
+
+ kDNSServiceFlagsAllowRemoteQuery = 0x200,
+ /* Flag for creating a record for which we will answer remote queries
+ * (queries from hosts more than one hop away; hosts not directly connected to the local link).
+ */
+
+ kDNSServiceFlagsForceMulticast = 0x400,
+ /* Flag for signifying that a query or registration should be performed exclusively via multicast
+ * DNS, even for a name in a domain (e.g. foo.apple.com.) that would normally imply unicast DNS.
+ */
+
+ kDNSServiceFlagsForce = 0x800,
+ /* Flag for signifying a "stronger" variant of an operation.
+ * Currently defined only for DNSServiceReconfirmRecord(), where it forces a record to
+ * be removed from the cache immediately, instead of querying for a few seconds before
+ * concluding that the record is no longer valid and then removing it. This flag should
+ * be used with caution because if a service browsing PTR record is indeed still valid
+ * on the network, forcing its removal will result in a user-interface flap -- the
+ * discovered service instance will disappear, and then re-appear moments later.
+ */
+
+ kDNSServiceFlagsReturnIntermediates = 0x1000,
+ /* Flag for returning intermediate results.
+ * For example, if a query results in an authoritative NXDomain (name does not exist)
+ * then that result is returned to the client. However the query is not implicitly
+ * cancelled -- it remains active and if the answer subsequently changes
+ * (e.g. because a VPN tunnel is subsequently established) then that positive
+ * result will still be returned to the client.
+ * Similarly, if a query results in a CNAME record, then in addition to following
+ * the CNAME referral, the intermediate CNAME result is also returned to the client.
+ * When this flag is not set, NXDomain errors are not returned, and CNAME records
+ * are followed silently without informing the client of the intermediate steps.
+ * (In earlier builds this flag was briefly calledkDNSServiceFlagsReturnCNAME)
+ */
+
+ kDNSServiceFlagsNonBrowsable = 0x2000,
+ /* A service registered with the NonBrowsable flag set can be resolved using
+ * DNSServiceResolve(), but will not be discoverable using DNSServiceBrowse().
+ * This is for cases where the name is actually a GUID; it is found by other means;
+ * there is no end-user benefit to browsing to find a long list of opaque GUIDs.
+ * Using the NonBrowsable flag creates SRV+TXT without the cost of also advertising
+ * an associated PTR record.
+ */
+
+ kDNSServiceFlagsShareConnection = 0x4000,
+ /* For efficiency, clients that perform many concurrent operations may want to use a
+ * single Unix Domain Socket connection with the background daemon, instead of having a
+ * separate connection for each independent operation. To use this mode, clients first
+ * call DNSServiceCreateConnection(&MainRef) to initialize the main DNSServiceRef.
+ * For each subsequent operation that is to share that same connection, the client copies
+ * the MainRef, and then passes the address of that copy, setting the ShareConnection flag
+ * to tell the library that this DNSServiceRef is not a typical uninitialized DNSServiceRef;
+ * it's a copy of an existing DNSServiceRef whose connection information should be reused.
+ *
+ * For example:
+ *
+ * DNSServiceErrorType error;
+ * DNSServiceRef MainRef;
+ * error = DNSServiceCreateConnection(&MainRef);
+ * if (error) ...
+ * DNSServiceRef BrowseRef = MainRef; // Important: COPY the primary DNSServiceRef first...
+ * error = DNSServiceBrowse(&BrowseRef, kDNSServiceFlagsShareConnection, ...); // then use the copy
+ * if (error) ...
+ * ...
+ * DNSServiceRefDeallocate(BrowseRef); // Terminate the browse operation
+ * DNSServiceRefDeallocate(MainRef); // Terminate the shared connection
+ *
+ * Notes:
+ *
+ * 1. Collective kDNSServiceFlagsMoreComing flag
+ * When callbacks are invoked using a shared DNSServiceRef, the
+ * kDNSServiceFlagsMoreComing flag applies collectively to *all* active
+ * operations sharing the same parent DNSServiceRef. If the MoreComing flag is
+ * set it means that there are more results queued on this parent DNSServiceRef,
+ * but not necessarily more results for this particular callback function.
+ * The implication of this for client programmers is that when a callback
+ * is invoked with the MoreComing flag set, the code should update its
+ * internal data structures with the new result, and set a variable indicating
+ * that its UI needs to be updated. Then, later when a callback is eventually
+ * invoked with the MoreComing flag not set, the code should update *all*
+ * stale UI elements related to that shared parent DNSServiceRef that need
+ * updating, not just the UI elements related to the particular callback
+ * that happened to be the last one to be invoked.
+ *
+ * 2. Canceling operations and kDNSServiceFlagsMoreComing
+ * Whenever you cancel any operation for which you had deferred UI updates
+ * waiting because of a kDNSServiceFlagsMoreComing flag, you should perform
+ * those deferred UI updates. This is because, after cancelling the operation,
+ * you can no longer wait for a callback *without* MoreComing set, to tell
+ * you do perform your deferred UI updates (the operation has been canceled,
+ * so there will be no more callbacks). An implication of the collective
+ * kDNSServiceFlagsMoreComing flag for shared connections is that this
+ * guideline applies more broadly -- any time you cancel an operation on
+ * a shared connection, you should perform all deferred UI updates for all
+ * operations sharing that connection. This is because the MoreComing flag
+ * might have been referring to events coming for the operation you canceled,
+ * which will now not be coming because the operation has been canceled.
+ *
+ * 3. Only share DNSServiceRef's created with DNSServiceCreateConnection
+ * Calling DNSServiceCreateConnection(&ref) creates a special shareable DNSServiceRef.
+ * DNSServiceRef's created by other calls like DNSServiceBrowse() or DNSServiceResolve()
+ * cannot be shared by copying them and using kDNSServiceFlagsShareConnection.
+ *
+ * 4. Don't Double-Deallocate
+ * Calling DNSServiceRefDeallocate(ref) for a particular operation's DNSServiceRef terminates
+ * just that operation. Calling DNSServiceRefDeallocate(ref) for the main shared DNSServiceRef
+ * (the parent DNSServiceRef, originally created by DNSServiceCreateConnection(&ref))
+ * automatically terminates the shared connection and all operations that were still using it.
+ * After doing this, DO NOT then attempt to deallocate any remaining subordinate DNSServiceRef's.
+ * The memory used by those subordinate DNSServiceRef's has already been freed, so any attempt
+ * to do a DNSServiceRefDeallocate (or any other operation) on them will result in accesses
+ * to freed memory, leading to crashes or other equally undesirable results.
+ *
+ * 5. Thread Safety
+ * The dns_sd.h API does not presuppose any particular threading model, and consequently
+ * does no locking of its own (which would require linking some specific threading library).
+ * If client code calls API routines on the same DNSServiceRef concurrently
+ * from multiple threads, it is the client's responsibility to use a mutext
+ * lock or take similar appropriate precautions to serialize those calls.
+ */
+
+ kDNSServiceFlagsSuppressUnusable = 0x8000
+ /* Placeholder definition, for future use
+ */
+ };
+
+/* Possible protocols for DNSServiceNATPortMappingCreate(). */
+enum
+ {
+ kDNSServiceProtocol_IPv4 = 0x01,
+ kDNSServiceProtocol_IPv6 = 0x02,
+ /* 0x04 and 0x08 reserved for future internetwork protocols */
+
+ kDNSServiceProtocol_UDP = 0x10,
+ kDNSServiceProtocol_TCP = 0x20
+ /* 0x40 and 0x80 reserved for future transport protocols, e.g. SCTP [RFC 2960]
+ * or DCCP [RFC 4340]. If future NAT gateways are created that support port
+ * mappings for these protocols, new constants will be defined here.
+ */
+ };
+
+/*
+ * The values for DNS Classes and Types are listed in RFC 1035, and are available
+ * on every OS in its DNS header file. Unfortunately every OS does not have the
+ * same header file containing DNS Class and Type constants, and the names of
+ * the constants are not consistent. For example, BIND 8 uses "T_A",
+ * BIND 9 uses "ns_t_a", Windows uses "DNS_TYPE_A", etc.
+ * For this reason, these constants are also listed here, so that code using
+ * the DNS-SD programming APIs can use these constants, so that the same code
+ * can compile on all our supported platforms.
+ */
+
+enum
+ {
+ kDNSServiceClass_IN = 1 /* Internet */
+ };
+
+enum
+ {
+ kDNSServiceType_A = 1, /* Host address. */
+ kDNSServiceType_NS = 2, /* Authoritative server. */
+ kDNSServiceType_MD = 3, /* Mail destination. */
+ kDNSServiceType_MF = 4, /* Mail forwarder. */
+ kDNSServiceType_CNAME = 5, /* Canonical name. */
+ kDNSServiceType_SOA = 6, /* Start of authority zone. */
+ kDNSServiceType_MB = 7, /* Mailbox domain name. */
+ kDNSServiceType_MG = 8, /* Mail group member. */
+ kDNSServiceType_MR = 9, /* Mail rename name. */
+ kDNSServiceType_NULL = 10, /* Null resource record. */
+ kDNSServiceType_WKS = 11, /* Well known service. */
+ kDNSServiceType_PTR = 12, /* Domain name pointer. */
+ kDNSServiceType_HINFO = 13, /* Host information. */
+ kDNSServiceType_MINFO = 14, /* Mailbox information. */
+ kDNSServiceType_MX = 15, /* Mail routing information. */
+ kDNSServiceType_TXT = 16, /* One or more text strings (NOT "zero or more..."). */
+ kDNSServiceType_RP = 17, /* Responsible person. */
+ kDNSServiceType_AFSDB = 18, /* AFS cell database. */
+ kDNSServiceType_X25 = 19, /* X_25 calling address. */
+ kDNSServiceType_ISDN = 20, /* ISDN calling address. */
+ kDNSServiceType_RT = 21, /* Router. */
+ kDNSServiceType_NSAP = 22, /* NSAP address. */
+ kDNSServiceType_NSAP_PTR = 23, /* Reverse NSAP lookup (deprecated). */
+ kDNSServiceType_SIG = 24, /* Security signature. */
+ kDNSServiceType_KEY = 25, /* Security key. */
+ kDNSServiceType_PX = 26, /* X.400 mail mapping. */
+ kDNSServiceType_GPOS = 27, /* Geographical position (withdrawn). */
+ kDNSServiceType_AAAA = 28, /* IPv6 Address. */
+ kDNSServiceType_LOC = 29, /* Location Information. */
+ kDNSServiceType_NXT = 30, /* Next domain (security). */
+ kDNSServiceType_EID = 31, /* Endpoint identifier. */
+ kDNSServiceType_NIMLOC = 32, /* Nimrod Locator. */
+ kDNSServiceType_SRV = 33, /* Server Selection. */
+ kDNSServiceType_ATMA = 34, /* ATM Address */
+ kDNSServiceType_NAPTR = 35, /* Naming Authority PoinTeR */
+ kDNSServiceType_KX = 36, /* Key Exchange */
+ kDNSServiceType_CERT = 37, /* Certification record */
+ kDNSServiceType_A6 = 38, /* IPv6 Address (deprecated) */
+ kDNSServiceType_DNAME = 39, /* Non-terminal DNAME (for IPv6) */
+ kDNSServiceType_SINK = 40, /* Kitchen sink (experimental) */
+ kDNSServiceType_OPT = 41, /* EDNS0 option (meta-RR) */
+ kDNSServiceType_APL = 42, /* Address Prefix List */
+ kDNSServiceType_DS = 43, /* Delegation Signer */
+ kDNSServiceType_SSHFP = 44, /* SSH Key Fingerprint */
+ kDNSServiceType_IPSECKEY = 45, /* IPSECKEY */
+ kDNSServiceType_RRSIG = 46, /* RRSIG */
+ kDNSServiceType_NSEC = 47, /* Denial of Existence */
+ kDNSServiceType_DNSKEY = 48, /* DNSKEY */
+ kDNSServiceType_DHCID = 49, /* DHCP Client Identifier */
+ kDNSServiceType_NSEC3 = 50, /* Hashed Authenticated Denial of Existence */
+ kDNSServiceType_NSEC3PARAM= 51, /* Hashed Authenticated Denial of Existence */
+
+ kDNSServiceType_HIP = 55, /* Host Identity Protocol */
+
+ kDNSServiceType_SPF = 99, /* Sender Policy Framework for E-Mail */
+ kDNSServiceType_UINFO = 100, /* IANA-Reserved */
+ kDNSServiceType_UID = 101, /* IANA-Reserved */
+ kDNSServiceType_GID = 102, /* IANA-Reserved */
+ kDNSServiceType_UNSPEC = 103, /* IANA-Reserved */
+
+ kDNSServiceType_TKEY = 249, /* Transaction key */
+ kDNSServiceType_TSIG = 250, /* Transaction signature. */
+ kDNSServiceType_IXFR = 251, /* Incremental zone transfer. */
+ kDNSServiceType_AXFR = 252, /* Transfer zone of authority. */
+ kDNSServiceType_MAILB = 253, /* Transfer mailbox records. */
+ kDNSServiceType_MAILA = 254, /* Transfer mail agent records. */
+ kDNSServiceType_ANY = 255 /* Wildcard match. */
+ };
+
+/* possible error code values */
+enum
+ {
+ kDNSServiceErr_NoError = 0,
+ kDNSServiceErr_Unknown = -65537, /* 0xFFFE FFFF */
+ kDNSServiceErr_NoSuchName = -65538,
+ kDNSServiceErr_NoMemory = -65539,
+ kDNSServiceErr_BadParam = -65540,
+ kDNSServiceErr_BadReference = -65541,
+ kDNSServiceErr_BadState = -65542,
+ kDNSServiceErr_BadFlags = -65543,
+ kDNSServiceErr_Unsupported = -65544,
+ kDNSServiceErr_NotInitialized = -65545,
+ kDNSServiceErr_AlreadyRegistered = -65547,
+ kDNSServiceErr_NameConflict = -65548,
+ kDNSServiceErr_Invalid = -65549,
+ kDNSServiceErr_Firewall = -65550,
+ kDNSServiceErr_Incompatible = -65551, /* client library incompatible with daemon */
+ kDNSServiceErr_BadInterfaceIndex = -65552,
+ kDNSServiceErr_Refused = -65553,
+ kDNSServiceErr_NoSuchRecord = -65554,
+ kDNSServiceErr_NoAuth = -65555,
+ kDNSServiceErr_NoSuchKey = -65556,
+ kDNSServiceErr_NATTraversal = -65557,
+ kDNSServiceErr_DoubleNAT = -65558,
+ kDNSServiceErr_BadTime = -65559, /* Codes up to here existed in Tiger */
+ kDNSServiceErr_BadSig = -65560,
+ kDNSServiceErr_BadKey = -65561,
+ kDNSServiceErr_Transient = -65562,
+ kDNSServiceErr_ServiceNotRunning = -65563, /* Background daemon not running */
+ kDNSServiceErr_NATPortMappingUnsupported = -65564, /* NAT doesn't support NAT-PMP or UPnP */
+ kDNSServiceErr_NATPortMappingDisabled = -65565, /* NAT supports NAT-PMP or UPnP but it's disabled by the administrator */
+ kDNSServiceErr_NoRouter = -65566, /* No router currently configured (probably no network connectivity) */
+ kDNSServiceErr_PollingMode = -65567,
+ kDNSServiceErr_Timeout = -65568
+
+ /* mDNS Error codes are in the range
+ * FFFE FF00 (-65792) to FFFE FFFF (-65537) */
+ };
+
+/* Maximum length, in bytes, of a service name represented as a */
+/* literal C-String, including the terminating NULL at the end. */
+
+#define kDNSServiceMaxServiceName 64
+
+/* Maximum length, in bytes, of a domain name represented as an *escaped* C-String */
+/* including the final trailing dot, and the C-String terminating NULL at the end. */
+
+#define kDNSServiceMaxDomainName 1009
+
+/*
+ * Notes on DNS Name Escaping
+ * -- or --
+ * "Why is kDNSServiceMaxDomainName 1009, when the maximum legal domain name is 256 bytes?"
+ *
+ * All strings used in the DNS-SD APIs are UTF-8 strings. Apart from the exceptions noted below,
+ * the APIs expect the strings to be properly escaped, using the conventional DNS escaping rules:
+ *
+ * '\\' represents a single literal '\' in the name
+ * '\.' represents a single literal '.' in the name
+ * '\ddd', where ddd is a three-digit decimal value from 000 to 255,
+ * represents a single literal byte with that value.
+ * A bare unescaped '.' is a label separator, marking a boundary between domain and subdomain.
+ *
+ * The exceptions, that do not use escaping, are the routines where the full
+ * DNS name of a resource is broken, for convenience, into servicename/regtype/domain.
+ * In these routines, the "servicename" is NOT escaped. It does not need to be, since
+ * it is, by definition, just a single literal string. Any characters in that string
+ * represent exactly what they are. The "regtype" portion is, technically speaking,
+ * escaped, but since legal regtypes are only allowed to contain letters, digits,
+ * and hyphens, there is nothing to escape, so the issue is moot. The "domain"
+ * portion is also escaped, though most domains in use on the public Internet
+ * today, like regtypes, don't contain any characters that need to be escaped.
+ * As DNS-SD becomes more popular, rich-text domains for service discovery will
+ * become common, so software should be written to cope with domains with escaping.
+ *
+ * The servicename may be up to 63 bytes of UTF-8 text (not counting the C-String
+ * terminating NULL at the end). The regtype is of the form _service._tcp or
+ * _service._udp, where the "service" part is 1-14 characters, which may be
+ * letters, digits, or hyphens. The domain part of the three-part name may be
+ * any legal domain, providing that the resulting servicename+regtype+domain
+ * name does not exceed 256 bytes.
+ *
+ * For most software, these issues are transparent. When browsing, the discovered
+ * servicenames should simply be displayed as-is. When resolving, the discovered
+ * servicename/regtype/domain are simply passed unchanged to DNSServiceResolve().
+ * When a DNSServiceResolve() succeeds, the returned fullname is already in
+ * the correct format to pass to standard system DNS APIs such as res_query().
+ * For converting from servicename/regtype/domain to a single properly-escaped
+ * full DNS name, the helper function DNSServiceConstructFullName() is provided.
+ *
+ * The following (highly contrived) example illustrates the escaping process.
+ * Suppose you have an service called "Dr. Smith\Dr. Johnson", of type "_ftp._tcp"
+ * in subdomain "4th. Floor" of subdomain "Building 2" of domain "apple.com."
+ * The full (escaped) DNS name of this service's SRV record would be:
+ * Dr\.\032Smith\\Dr\.\032Johnson._ftp._tcp.4th\.\032Floor.Building\0322.apple.com.
+ */
+
+
+/*
+ * Constants for specifying an interface index
+ *
+ * Specific interface indexes are identified via a 32-bit unsigned integer returned
+ * by the if_nametoindex() family of calls.
+ *
+ * If the client passes 0 for interface index, that means "do the right thing",
+ * which (at present) means, "if the name is in an mDNS local multicast domain
+ * (e.g. 'local.', '254.169.in-addr.arpa.', '{8,9,A,B}.E.F.ip6.arpa.') then multicast
+ * on all applicable interfaces, otherwise send via unicast to the appropriate
+ * DNS server." Normally, most clients will use 0 for interface index to
+ * automatically get the default sensible behaviour.
+ *
+ * If the client passes a positive interface index, then for multicast names that
+ * indicates to do the operation only on that one interface. For unicast names the
+ * interface index is ignored unless kDNSServiceFlagsForceMulticast is also set.
+ *
+ * If the client passes kDNSServiceInterfaceIndexLocalOnly when registering
+ * a service, then that service will be found *only* by other local clients
+ * on the same machine that are browsing using kDNSServiceInterfaceIndexLocalOnly
+ * or kDNSServiceInterfaceIndexAny.
+ * If a client has a 'private' service, accessible only to other processes
+ * running on the same machine, this allows the client to advertise that service
+ * in a way such that it does not inadvertently appear in service lists on
+ * all the other machines on the network.
+ *
+ * If the client passes kDNSServiceInterfaceIndexLocalOnly when browsing
+ * then it will find *all* records registered on that same local machine.
+ * Clients explicitly wishing to discover *only* LocalOnly services can
+ * accomplish this by inspecting the interfaceIndex of each service reported
+ * to their DNSServiceBrowseReply() callback function, and discarding those
+ * where the interface index is not kDNSServiceInterfaceIndexLocalOnly.
+ */
+
+#define kDNSServiceInterfaceIndexAny 0
+#define kDNSServiceInterfaceIndexLocalOnly ((uint32_t)-1)
+#define kDNSServiceInterfaceIndexUnicast ((uint32_t)-2)
+
+typedef uint32_t DNSServiceFlags;
+typedef uint32_t DNSServiceProtocol;
+typedef int32_t DNSServiceErrorType;
+
+
+/*********************************************************************************************
+ *
+ * Version checking
+ *
+ *********************************************************************************************/
+
+/* DNSServiceGetProperty() Parameters:
+ *
+ * property: The requested property.
+ * Currently the only property defined is kDNSServiceProperty_DaemonVersion.
+ *
+ * result: Place to store result.
+ * For retrieving DaemonVersion, this should be the address of a uint32_t.
+ *
+ * size: Pointer to uint32_t containing size of the result location.
+ * For retrieving DaemonVersion, this should be sizeof(uint32_t).
+ * On return the uint32_t is updated to the size of the data returned.
+ * For DaemonVersion, the returned size is always sizeof(uint32_t), but
+ * future properties could be defined which return variable-sized results.
+ *
+ * return value: Returns kDNSServiceErr_NoError on success, or kDNSServiceErr_ServiceNotRunning
+ * if the daemon (or "system service" on Windows) is not running.
+ */
+
+DNSServiceErrorType DNSSD_API DNSServiceGetProperty
+ (
+ const char *property, /* Requested property (i.e. kDNSServiceProperty_DaemonVersion) */
+ void *result, /* Pointer to place to store result */
+ uint32_t *size /* size of result location */
+ );
+
+/*
+ * When requesting kDNSServiceProperty_DaemonVersion, the result pointer must point
+ * to a 32-bit unsigned integer, and the size parameter must be set to sizeof(uint32_t).
+ *
+ * On return, the 32-bit unsigned integer contains the version number, formatted as follows:
+ * Major part of the build number * 10000 +
+ * minor part of the build number * 100
+ *
+ * For example, Mac OS X 10.4.9 has mDNSResponder-108.4, which would be represented as
+ * version 1080400. This allows applications to do simple greater-than and less-than comparisons:
+ * e.g. an application that requires at least mDNSResponder-108.4 can check:
+ *
+ * if (version >= 1080400) ...
+ *
+ * Example usage:
+ *
+ * uint32_t version;
+ * uint32_t size = sizeof(version);
+ * DNSServiceErrorType err = DNSServiceGetProperty(kDNSServiceProperty_DaemonVersion, &version, &size);
+ * if (!err) printf("Bonjour version is %d.%d\n", version / 10000, version / 100 % 100);
+ */
+
+#define kDNSServiceProperty_DaemonVersion "DaemonVersion"
+
+
+/*********************************************************************************************
+ *
+ * Unix Domain Socket access, DNSServiceRef deallocation, and data processing functions
+ *
+ *********************************************************************************************/
+
+/* DNSServiceRefSockFD()
+ *
+ * Access underlying Unix domain socket for an initialized DNSServiceRef.
+ * The DNS Service Discovery implementation uses this socket to communicate between the client and
+ * the mDNSResponder daemon. The application MUST NOT directly read from or write to this socket.
+ * Access to the socket is provided so that it can be used as a kqueue event source, a CFRunLoop
+ * event source, in a select() loop, etc. When the underlying event management subsystem (kqueue/
+ * select/CFRunLoop etc.) indicates to the client that data is available for reading on the
+ * socket, the client should call DNSServiceProcessResult(), which will extract the daemon's
+ * reply from the socket, and pass it to the appropriate application callback. By using a run
+ * loop or select(), results from the daemon can be processed asynchronously. Alternatively,
+ * a client can choose to fork a thread and have it loop calling "DNSServiceProcessResult(ref);"
+ * If DNSServiceProcessResult() is called when no data is available for reading on the socket, it
+ * will block until data does become available, and then process the data and return to the caller.
+ * When data arrives on the socket, the client is responsible for calling DNSServiceProcessResult(ref)
+ * in a timely fashion -- if the client allows a large backlog of data to build up the daemon
+ * may terminate the connection.
+ *
+ * sdRef: A DNSServiceRef initialized by any of the DNSService calls.
+ *
+ * return value: The DNSServiceRef's underlying socket descriptor, or -1 on
+ * error.
+ */
+
+int DNSSD_API DNSServiceRefSockFD(DNSServiceRef sdRef);
+
+
+/* DNSServiceProcessResult()
+ *
+ * Read a reply from the daemon, calling the appropriate application callback. This call will
+ * block until the daemon's response is received. Use DNSServiceRefSockFD() in
+ * conjunction with a run loop or select() to determine the presence of a response from the
+ * server before calling this function to process the reply without blocking. Call this function
+ * at any point if it is acceptable to block until the daemon's response arrives. Note that the
+ * client is responsible for ensuring that DNSServiceProcessResult() is called whenever there is
+ * a reply from the daemon - the daemon may terminate its connection with a client that does not
+ * process the daemon's responses.
+ *
+ * sdRef: A DNSServiceRef initialized by any of the DNSService calls
+ * that take a callback parameter.
+ *
+ * return value: Returns kDNSServiceErr_NoError on success, otherwise returns
+ * an error code indicating the specific failure that occurred.
+ */
+
+DNSServiceErrorType DNSSD_API DNSServiceProcessResult(DNSServiceRef sdRef);
+
+
+/* DNSServiceRefDeallocate()
+ *
+ * Terminate a connection with the daemon and free memory associated with the DNSServiceRef.
+ * Any services or records registered with this DNSServiceRef will be deregistered. Any
+ * Browse, Resolve, or Query operations called with this reference will be terminated.
+ *
+ * Note: If the reference's underlying socket is used in a run loop or select() call, it should
+ * be removed BEFORE DNSServiceRefDeallocate() is called, as this function closes the reference's
+ * socket.
+ *
+ * Note: If the reference was initialized with DNSServiceCreateConnection(), any DNSRecordRefs
+ * created via this reference will be invalidated by this call - the resource records are
+ * deregistered, and their DNSRecordRefs may not be used in subsequent functions. Similarly,
+ * if the reference was initialized with DNSServiceRegister, and an extra resource record was
+ * added to the service via DNSServiceAddRecord(), the DNSRecordRef created by the Add() call
+ * is invalidated when this function is called - the DNSRecordRef may not be used in subsequent
+ * functions.
+ *
+ * Note: This call is to be used only with the DNSServiceRef defined by this API. It is
+ * not compatible with dns_service_discovery_ref objects defined in the legacy Mach-based
+ * DNSServiceDiscovery.h API.
+ *
+ * sdRef: A DNSServiceRef initialized by any of the DNSService calls.
+ *
+ */
+
+void DNSSD_API DNSServiceRefDeallocate(DNSServiceRef sdRef);
+
+
+/*********************************************************************************************
+ *
+ * Domain Enumeration
+ *
+ *********************************************************************************************/
+
+/* DNSServiceEnumerateDomains()
+ *
+ * Asynchronously enumerate domains available for browsing and registration.
+ *
+ * The enumeration MUST be cancelled via DNSServiceRefDeallocate() when no more domains
+ * are to be found.
+ *
+ * Note that the names returned are (like all of DNS-SD) UTF-8 strings,
+ * and are escaped using standard DNS escaping rules.
+ * (See "Notes on DNS Name Escaping" earlier in this file for more details.)
+ * A graphical browser displaying a hierarchical tree-structured view should cut
+ * the names at the bare dots to yield individual labels, then de-escape each
+ * label according to the escaping rules, and then display the resulting UTF-8 text.
+ *
+ * DNSServiceDomainEnumReply Callback Parameters:
+ *
+ * sdRef: The DNSServiceRef initialized by DNSServiceEnumerateDomains().
+ *
+ * flags: Possible values are:
+ * kDNSServiceFlagsMoreComing
+ * kDNSServiceFlagsAdd
+ * kDNSServiceFlagsDefault
+ *
+ * interfaceIndex: Specifies the interface on which the domain exists. (The index for a given
+ * interface is determined via the if_nametoindex() family of calls.)
+ *
+ * errorCode: Will be kDNSServiceErr_NoError (0) on success, otherwise indicates
+ * the failure that occurred (other parameters are undefined if errorCode is nonzero).
+ *
+ * replyDomain: The name of the domain.
+ *
+ * context: The context pointer passed to DNSServiceEnumerateDomains.
+ *
+ */
+
+typedef void (DNSSD_API *DNSServiceDomainEnumReply)
+ (
+ DNSServiceRef sdRef,
+ DNSServiceFlags flags,
+ uint32_t interfaceIndex,
+ DNSServiceErrorType errorCode,
+ const char *replyDomain,
+ void *context
+ );
+
+
+/* DNSServiceEnumerateDomains() Parameters:
+ *
+ * sdRef: A pointer to an uninitialized DNSServiceRef. If the call succeeds
+ * then it initializes the DNSServiceRef, returns kDNSServiceErr_NoError,
+ * and the enumeration operation will run indefinitely until the client
+ * terminates it by passing this DNSServiceRef to DNSServiceRefDeallocate().
+ *
+ * flags: Possible values are:
+ * kDNSServiceFlagsBrowseDomains to enumerate domains recommended for browsing.
+ * kDNSServiceFlagsRegistrationDomains to enumerate domains recommended
+ * for registration.
+ *
+ * interfaceIndex: If non-zero, specifies the interface on which to look for domains.
+ * (the index for a given interface is determined via the if_nametoindex()
+ * family of calls.) Most applications will pass 0 to enumerate domains on
+ * all interfaces. See "Constants for specifying an interface index" for more details.
+ *
+ * callBack: The function to be called when a domain is found or the call asynchronously
+ * fails.
+ *
+ * context: An application context pointer which is passed to the callback function
+ * (may be NULL).
+ *
+ * return value: Returns kDNSServiceErr_NoError on success (any subsequent, asynchronous
+ * errors are delivered to the callback), otherwise returns an error code indicating
+ * the error that occurred (the callback is not invoked and the DNSServiceRef
+ * is not initialized).
+ */
+
+DNSServiceErrorType DNSSD_API DNSServiceEnumerateDomains
+ (
+ DNSServiceRef *sdRef,
+ DNSServiceFlags flags,
+ uint32_t interfaceIndex,
+ DNSServiceDomainEnumReply callBack,
+ void *context /* may be NULL */
+ );
+
+
+/*********************************************************************************************
+ *
+ * Service Registration
+ *
+ *********************************************************************************************/
+
+/* Register a service that is discovered via Browse() and Resolve() calls.
+ *
+ * DNSServiceRegisterReply() Callback Parameters:
+ *
+ * sdRef: The DNSServiceRef initialized by DNSServiceRegister().
+ *
+ * flags: When a name is successfully registered, the callback will be
+ * invoked with the kDNSServiceFlagsAdd flag set. When Wide-Area
+ * DNS-SD is in use, it is possible for a single service to get
+ * more than one success callback (e.g. one in the "local" multicast
+ * DNS domain, and another in a wide-area unicast DNS domain).
+ * If a successfully-registered name later suffers a name conflict
+ * or similar problem and has to be deregistered, the callback will
+ * be invoked with the kDNSServiceFlagsAdd flag not set. The callback
+ * is *not* invoked in the case where the caller explicitly terminates
+ * the service registration by calling DNSServiceRefDeallocate(ref);
+ *
+ * errorCode: Will be kDNSServiceErr_NoError on success, otherwise will
+ * indicate the failure that occurred (including name conflicts,
+ * if the kDNSServiceFlagsNoAutoRename flag was used when registering.)
+ * Other parameters are undefined if errorCode is nonzero.
+ *
+ * name: The service name registered (if the application did not specify a name in
+ * DNSServiceRegister(), this indicates what name was automatically chosen).
+ *
+ * regtype: The type of service registered, as it was passed to the callout.
+ *
+ * domain: The domain on which the service was registered (if the application did not
+ * specify a domain in DNSServiceRegister(), this indicates the default domain
+ * on which the service was registered).
+ *
+ * context: The context pointer that was passed to the callout.
+ *
+ */
+
+typedef void (DNSSD_API *DNSServiceRegisterReply)
+ (
+ DNSServiceRef sdRef,
+ DNSServiceFlags flags,
+ DNSServiceErrorType errorCode,
+ const char *name,
+ const char *regtype,
+ const char *domain,
+ void *context
+ );
+
+
+/* DNSServiceRegister() Parameters:
+ *
+ * sdRef: A pointer to an uninitialized DNSServiceRef. If the call succeeds
+ * then it initializes the DNSServiceRef, returns kDNSServiceErr_NoError,
+ * and the registration will remain active indefinitely until the client
+ * terminates it by passing this DNSServiceRef to DNSServiceRefDeallocate().
+ *
+ * interfaceIndex: If non-zero, specifies the interface on which to register the service
+ * (the index for a given interface is determined via the if_nametoindex()
+ * family of calls.) Most applications will pass 0 to register on all
+ * available interfaces. See "Constants for specifying an interface index" for more details.
+ *
+ * flags: Indicates the renaming behavior on name conflict (most applications
+ * will pass 0). See flag definitions above for details.
+ *
+ * name: If non-NULL, specifies the service name to be registered.
+ * Most applications will not specify a name, in which case the computer
+ * name is used (this name is communicated to the client via the callback).
+ * If a name is specified, it must be 1-63 bytes of UTF-8 text.
+ * If the name is longer than 63 bytes it will be automatically truncated
+ * to a legal length, unless the NoAutoRename flag is set,
+ * in which case kDNSServiceErr_BadParam will be returned.
+ *
+ * regtype: The service type followed by the protocol, separated by a dot
+ * (e.g. "_ftp._tcp"). The service type must be an underscore, followed
+ * by 1-14 characters, which may be letters, digits, or hyphens.
+ * The transport protocol must be "_tcp" or "_udp". New service types
+ * should be registered at <http://www.dns-sd.org/ServiceTypes.html>.
+ *
+ * Additional subtypes of the primary service type (where a service
+ * type has defined subtypes) follow the primary service type in a
+ * comma-separated list, with no additional spaces, e.g.
+ * "_primarytype._tcp,_subtype1,_subtype2,_subtype3"
+ * Subtypes provide a mechanism for filtered browsing: A client browsing
+ * for "_primarytype._tcp" will discover all instances of this type;
+ * a client browsing for "_primarytype._tcp,_subtype2" will discover only
+ * those instances that were registered with "_subtype2" in their list of
+ * registered subtypes.
+ *
+ * The subtype mechanism can be illustrated with some examples using the
+ * dns-sd command-line tool:
+ *
+ * % dns-sd -R Simple _test._tcp "" 1001 &
+ * % dns-sd -R Better _test._tcp,HasFeatureA "" 1002 &
+ * % dns-sd -R Best _test._tcp,HasFeatureA,HasFeatureB "" 1003 &
+ *
+ * Now:
+ * % dns-sd -B _test._tcp # will find all three services
+ * % dns-sd -B _test._tcp,HasFeatureA # finds "Better" and "Best"
+ * % dns-sd -B _test._tcp,HasFeatureB # finds only "Best"
+ *
+ * domain: If non-NULL, specifies the domain on which to advertise the service.
+ * Most applications will not specify a domain, instead automatically
+ * registering in the default domain(s).
+ *
+ * host: If non-NULL, specifies the SRV target host name. Most applications
+ * will not specify a host, instead automatically using the machine's
+ * default host name(s). Note that specifying a non-NULL host does NOT
+ * create an address record for that host - the application is responsible
+ * for ensuring that the appropriate address record exists, or creating it
+ * via DNSServiceRegisterRecord().
+ *
+ * port: The port, in network byte order, on which the service accepts connections.
+ * Pass 0 for a "placeholder" service (i.e. a service that will not be discovered
+ * by browsing, but will cause a name conflict if another client tries to
+ * register that same name). Most clients will not use placeholder services.
+ *
+ * txtLen: The length of the txtRecord, in bytes. Must be zero if the txtRecord is NULL.
+ *
+ * txtRecord: The TXT record rdata. A non-NULL txtRecord MUST be a properly formatted DNS
+ * TXT record, i.e. <length byte> <data> <length byte> <data> ...
+ * Passing NULL for the txtRecord is allowed as a synonym for txtLen=1, txtRecord="",
+ * i.e. it creates a TXT record of length one containing a single empty string.
+ * RFC 1035 doesn't allow a TXT record to contain *zero* strings, so a single empty
+ * string is the smallest legal DNS TXT record.
+ * As with the other parameters, the DNSServiceRegister call copies the txtRecord
+ * data; e.g. if you allocated the storage for the txtRecord parameter with malloc()
+ * then you can safely free that memory right after the DNSServiceRegister call returns.
+ *
+ * callBack: The function to be called when the registration completes or asynchronously
+ * fails. The client MAY pass NULL for the callback - The client will NOT be notified
+ * of the default values picked on its behalf, and the client will NOT be notified of any
+ * asynchronous errors (e.g. out of memory errors, etc.) that may prevent the registration
+ * of the service. The client may NOT pass the NoAutoRename flag if the callback is NULL.
+ * The client may still deregister the service at any time via DNSServiceRefDeallocate().
+ *
+ * context: An application context pointer which is passed to the callback function
+ * (may be NULL).
+ *
+ * return value: Returns kDNSServiceErr_NoError on success (any subsequent, asynchronous
+ * errors are delivered to the callback), otherwise returns an error code indicating
+ * the error that occurred (the callback is never invoked and the DNSServiceRef
+ * is not initialized).
+ */
+
+DNSServiceErrorType DNSSD_API DNSServiceRegister
+ (
+ DNSServiceRef *sdRef,
+ DNSServiceFlags flags,
+ uint32_t interfaceIndex,
+ const char *name, /* may be NULL */
+ const char *regtype,
+ const char *domain, /* may be NULL */
+ const char *host, /* may be NULL */
+ uint16_t port,
+ uint16_t txtLen,
+ const void *txtRecord, /* may be NULL */
+ DNSServiceRegisterReply callBack, /* may be NULL */
+ void *context /* may be NULL */
+ );
+
+
+/* DNSServiceAddRecord()
+ *
+ * Add a record to a registered service. The name of the record will be the same as the
+ * registered service's name.
+ * The record can later be updated or deregistered by passing the RecordRef initialized
+ * by this function to DNSServiceUpdateRecord() or DNSServiceRemoveRecord().
+ *
+ * Note that the DNSServiceAddRecord/UpdateRecord/RemoveRecord are *NOT* thread-safe
+ * with respect to a single DNSServiceRef. If you plan to have multiple threads
+ * in your program simultaneously add, update, or remove records from the same
+ * DNSServiceRef, then it's the caller's responsibility to use a mutext lock
+ * or take similar appropriate precautions to serialize those calls.
+ *
+ * Parameters;
+ *
+ * sdRef: A DNSServiceRef initialized by DNSServiceRegister().
+ *
+ * RecordRef: A pointer to an uninitialized DNSRecordRef. Upon succesfull completion of this
+ * call, this ref may be passed to DNSServiceUpdateRecord() or DNSServiceRemoveRecord().
+ * If the above DNSServiceRef is passed to DNSServiceRefDeallocate(), RecordRef is also
+ * invalidated and may not be used further.
+ *
+ * flags: Currently ignored, reserved for future use.
+ *
+ * rrtype: The type of the record (e.g. kDNSServiceType_TXT, kDNSServiceType_SRV, etc)
+ *
+ * rdlen: The length, in bytes, of the rdata.
+ *
+ * rdata: The raw rdata to be contained in the added resource record.
+ *
+ * ttl: The time to live of the resource record, in seconds.
+ * Most clients should pass 0 to indicate that the system should
+ * select a sensible default value.
+ *
+ * return value: Returns kDNSServiceErr_NoError on success, otherwise returns an
+ * error code indicating the error that occurred (the RecordRef is not initialized).
+ */
+
+DNSServiceErrorType DNSSD_API DNSServiceAddRecord
+ (
+ DNSServiceRef sdRef,
+ DNSRecordRef *RecordRef,
+ DNSServiceFlags flags,
+ uint16_t rrtype,
+ uint16_t rdlen,
+ const void *rdata,
+ uint32_t ttl
+ );
+
+
+/* DNSServiceUpdateRecord
+ *
+ * Update a registered resource record. The record must either be:
+ * - The primary txt record of a service registered via DNSServiceRegister()
+ * - A record added to a registered service via DNSServiceAddRecord()
+ * - An individual record registered by DNSServiceRegisterRecord()
+ *
+ * Parameters:
+ *
+ * sdRef: A DNSServiceRef that was initialized by DNSServiceRegister()
+ * or DNSServiceCreateConnection().
+ *
+ * RecordRef: A DNSRecordRef initialized by DNSServiceAddRecord, or NULL to update the
+ * service's primary txt record.
+ *
+ * flags: Currently ignored, reserved for future use.
+ *
+ * rdlen: The length, in bytes, of the new rdata.
+ *
+ * rdata: The new rdata to be contained in the updated resource record.
+ *
+ * ttl: The time to live of the updated resource record, in seconds.
+ * Most clients should pass 0 to indicate that the system should
+ * select a sensible default value.
+ *
+ * return value: Returns kDNSServiceErr_NoError on success, otherwise returns an
+ * error code indicating the error that occurred.
+ */
+
+DNSServiceErrorType DNSSD_API DNSServiceUpdateRecord
+ (
+ DNSServiceRef sdRef,
+ DNSRecordRef RecordRef, /* may be NULL */
+ DNSServiceFlags flags,
+ uint16_t rdlen,
+ const void *rdata,
+ uint32_t ttl
+ );
+
+
+/* DNSServiceRemoveRecord
+ *
+ * Remove a record previously added to a service record set via DNSServiceAddRecord(), or deregister
+ * an record registered individually via DNSServiceRegisterRecord().
+ *
+ * Parameters:
+ *
+ * sdRef: A DNSServiceRef initialized by DNSServiceRegister() (if the
+ * record being removed was registered via DNSServiceAddRecord()) or by
+ * DNSServiceCreateConnection() (if the record being removed was registered via
+ * DNSServiceRegisterRecord()).
+ *
+ * recordRef: A DNSRecordRef initialized by a successful call to DNSServiceAddRecord()
+ * or DNSServiceRegisterRecord().
+ *
+ * flags: Currently ignored, reserved for future use.
+ *
+ * return value: Returns kDNSServiceErr_NoError on success, otherwise returns an
+ * error code indicating the error that occurred.
+ */
+
+DNSServiceErrorType DNSSD_API DNSServiceRemoveRecord
+ (
+ DNSServiceRef sdRef,
+ DNSRecordRef RecordRef,
+ DNSServiceFlags flags
+ );
+
+
+/*********************************************************************************************
+ *
+ * Service Discovery
+ *
+ *********************************************************************************************/
+
+/* Browse for instances of a service.
+ *
+ * DNSServiceBrowseReply() Parameters:
+ *
+ * sdRef: The DNSServiceRef initialized by DNSServiceBrowse().
+ *
+ * flags: Possible values are kDNSServiceFlagsMoreComing and kDNSServiceFlagsAdd.
+ * See flag definitions for details.
+ *
+ * interfaceIndex: The interface on which the service is advertised. This index should
+ * be passed to DNSServiceResolve() when resolving the service.
+ *
+ * errorCode: Will be kDNSServiceErr_NoError (0) on success, otherwise will
+ * indicate the failure that occurred. Other parameters are undefined if
+ * the errorCode is nonzero.
+ *
+ * serviceName: The discovered service name. This name should be displayed to the user,
+ * and stored for subsequent use in the DNSServiceResolve() call.
+ *
+ * regtype: The service type, which is usually (but not always) the same as was passed
+ * to DNSServiceBrowse(). One case where the discovered service type may
+ * not be the same as the requested service type is when using subtypes:
+ * The client may want to browse for only those ftp servers that allow
+ * anonymous connections. The client will pass the string "_ftp._tcp,_anon"
+ * to DNSServiceBrowse(), but the type of the service that's discovered
+ * is simply "_ftp._tcp". The regtype for each discovered service instance
+ * should be stored along with the name, so that it can be passed to
+ * DNSServiceResolve() when the service is later resolved.
+ *
+ * domain: The domain of the discovered service instance. This may or may not be the
+ * same as the domain that was passed to DNSServiceBrowse(). The domain for each
+ * discovered service instance should be stored along with the name, so that
+ * it can be passed to DNSServiceResolve() when the service is later resolved.
+ *
+ * context: The context pointer that was passed to the callout.
+ *
+ */
+
+typedef void (DNSSD_API *DNSServiceBrowseReply)
+ (
+ DNSServiceRef sdRef,
+ DNSServiceFlags flags,
+ uint32_t interfaceIndex,
+ DNSServiceErrorType errorCode,
+ const char *serviceName,
+ const char *regtype,
+ const char *replyDomain,
+ void *context
+ );
+
+
+/* DNSServiceBrowse() Parameters:
+ *
+ * sdRef: A pointer to an uninitialized DNSServiceRef. If the call succeeds
+ * then it initializes the DNSServiceRef, returns kDNSServiceErr_NoError,
+ * and the browse operation will run indefinitely until the client
+ * terminates it by passing this DNSServiceRef to DNSServiceRefDeallocate().
+ *
+ * flags: Currently ignored, reserved for future use.
+ *
+ * interfaceIndex: If non-zero, specifies the interface on which to browse for services
+ * (the index for a given interface is determined via the if_nametoindex()
+ * family of calls.) Most applications will pass 0 to browse on all available
+ * interfaces. See "Constants for specifying an interface index" for more details.
+ *
+ * regtype: The service type being browsed for followed by the protocol, separated by a
+ * dot (e.g. "_ftp._tcp"). The transport protocol must be "_tcp" or "_udp".
+ * A client may optionally specify a single subtype to perform filtered browsing:
+ * e.g. browsing for "_primarytype._tcp,_subtype" will discover only those
+ * instances of "_primarytype._tcp" that were registered specifying "_subtype"
+ * in their list of registered subtypes.
+ *
+ * domain: If non-NULL, specifies the domain on which to browse for services.
+ * Most applications will not specify a domain, instead browsing on the
+ * default domain(s).
+ *
+ * callBack: The function to be called when an instance of the service being browsed for
+ * is found, or if the call asynchronously fails.
+ *
+ * context: An application context pointer which is passed to the callback function
+ * (may be NULL).
+ *
+ * return value: Returns kDNSServiceErr_NoError on success (any subsequent, asynchronous
+ * errors are delivered to the callback), otherwise returns an error code indicating
+ * the error that occurred (the callback is not invoked and the DNSServiceRef
+ * is not initialized).
+ */
+
+DNSServiceErrorType DNSSD_API DNSServiceBrowse
+ (
+ DNSServiceRef *sdRef,
+ DNSServiceFlags flags,
+ uint32_t interfaceIndex,
+ const char *regtype,
+ const char *domain, /* may be NULL */
+ DNSServiceBrowseReply callBack,
+ void *context /* may be NULL */
+ );
+
+
+/* DNSServiceResolve()
+ *
+ * Resolve a service name discovered via DNSServiceBrowse() to a target host name, port number, and
+ * txt record.
+ *
+ * Note: Applications should NOT use DNSServiceResolve() solely for txt record monitoring - use
+ * DNSServiceQueryRecord() instead, as it is more efficient for this task.
+ *
+ * Note: When the desired results have been returned, the client MUST terminate the resolve by calling
+ * DNSServiceRefDeallocate().
+ *
+ * Note: DNSServiceResolve() behaves correctly for typical services that have a single SRV record
+ * and a single TXT record. To resolve non-standard services with multiple SRV or TXT records,
+ * DNSServiceQueryRecord() should be used.
+ *
+ * DNSServiceResolveReply Callback Parameters:
+ *
+ * sdRef: The DNSServiceRef initialized by DNSServiceResolve().
+ *
+ * flags: Possible values: kDNSServiceFlagsMoreComing
+ *
+ * interfaceIndex: The interface on which the service was resolved.
+ *
+ * errorCode: Will be kDNSServiceErr_NoError (0) on success, otherwise will
+ * indicate the failure that occurred. Other parameters are undefined if
+ * the errorCode is nonzero.
+ *
+ * fullname: The full service domain name, in the form <servicename>.<protocol>.<domain>.
+ * (This name is escaped following standard DNS rules, making it suitable for
+ * passing to standard system DNS APIs such as res_query(), or to the
+ * special-purpose functions included in this API that take fullname parameters.
+ * See "Notes on DNS Name Escaping" earlier in this file for more details.)
+ *
+ * hosttarget: The target hostname of the machine providing the service. This name can
+ * be passed to functions like gethostbyname() to identify the host's IP address.
+ *
+ * port: The port, in network byte order, on which connections are accepted for this service.
+ *
+ * txtLen: The length of the txt record, in bytes.
+ *
+ * txtRecord: The service's primary txt record, in standard txt record format.
+ *
+ * context: The context pointer that was passed to the callout.
+ *
+ * NOTE: In earlier versions of this header file, the txtRecord parameter was declared "const char *"
+ * This is incorrect, since it contains length bytes which are values in the range 0 to 255, not -128 to +127.
+ * Depending on your compiler settings, this change may cause signed/unsigned mismatch warnings.
+ * These should be fixed by updating your own callback function definition to match the corrected
+ * function signature using "const unsigned char *txtRecord". Making this change may also fix inadvertent
+ * bugs in your callback function, where it could have incorrectly interpreted a length byte with value 250
+ * as being -6 instead, with various bad consequences ranging from incorrect operation to software crashes.
+ * If you need to maintain portable code that will compile cleanly with both the old and new versions of
+ * this header file, you should update your callback function definition to use the correct unsigned value,
+ * and then in the place where you pass your callback function to DNSServiceResolve(), use a cast to eliminate
+ * the compiler warning, e.g.:
+ * DNSServiceResolve(sd, flags, index, name, regtype, domain, (DNSServiceResolveReply)MyCallback, context);
+ * This will ensure that your code compiles cleanly without warnings (and more importantly, works correctly)
+ * with both the old header and with the new corrected version.
+ *
+ */
+
+typedef void (DNSSD_API *DNSServiceResolveReply)
+ (
+ DNSServiceRef sdRef,
+ DNSServiceFlags flags,
+ uint32_t interfaceIndex,
+ DNSServiceErrorType errorCode,
+ const char *fullname,
+ const char *hosttarget,
+ uint16_t port,
+ uint16_t txtLen,
+ const unsigned char *txtRecord,
+ void *context
+ );
+
+
+/* DNSServiceResolve() Parameters
+ *
+ * sdRef: A pointer to an uninitialized DNSServiceRef. If the call succeeds
+ * then it initializes the DNSServiceRef, returns kDNSServiceErr_NoError,
+ * and the resolve operation will run indefinitely until the client
+ * terminates it by passing this DNSServiceRef to DNSServiceRefDeallocate().
+ *
+ * flags: Specifying kDNSServiceFlagsForceMulticast will cause query to be
+ * performed with a link-local mDNS query, even if the name is an
+ * apparently non-local name (i.e. a name not ending in ".local.")
+ *
+ * interfaceIndex: The interface on which to resolve the service. If this resolve call is
+ * as a result of a currently active DNSServiceBrowse() operation, then the
+ * interfaceIndex should be the index reported in the DNSServiceBrowseReply
+ * callback. If this resolve call is using information previously saved
+ * (e.g. in a preference file) for later use, then use interfaceIndex 0, because
+ * the desired service may now be reachable via a different physical interface.
+ * See "Constants for specifying an interface index" for more details.
+ *
+ * name: The name of the service instance to be resolved, as reported to the
+ * DNSServiceBrowseReply() callback.
+ *
+ * regtype: The type of the service instance to be resolved, as reported to the
+ * DNSServiceBrowseReply() callback.
+ *
+ * domain: The domain of the service instance to be resolved, as reported to the
+ * DNSServiceBrowseReply() callback.
+ *
+ * callBack: The function to be called when a result is found, or if the call
+ * asynchronously fails.
+ *
+ * context: An application context pointer which is passed to the callback function
+ * (may be NULL).
+ *
+ * return value: Returns kDNSServiceErr_NoError on success (any subsequent, asynchronous
+ * errors are delivered to the callback), otherwise returns an error code indicating
+ * the error that occurred (the callback is never invoked and the DNSServiceRef
+ * is not initialized).
+ */
+
+DNSServiceErrorType DNSSD_API DNSServiceResolve
+ (
+ DNSServiceRef *sdRef,
+ DNSServiceFlags flags,
+ uint32_t interfaceIndex,
+ const char *name,
+ const char *regtype,
+ const char *domain,
+ DNSServiceResolveReply callBack,
+ void *context /* may be NULL */
+ );
+
+
+/*********************************************************************************************
+ *
+ * Querying Individual Specific Records
+ *
+ *********************************************************************************************/
+
+/* DNSServiceQueryRecord
+ *
+ * Query for an arbitrary DNS record.
+ *
+ * DNSServiceQueryRecordReply() Callback Parameters:
+ *
+ * sdRef: The DNSServiceRef initialized by DNSServiceQueryRecord().
+ *
+ * flags: Possible values are kDNSServiceFlagsMoreComing and
+ * kDNSServiceFlagsAdd. The Add flag is NOT set for PTR records
+ * with a ttl of 0, i.e. "Remove" events.
+ *
+ * interfaceIndex: The interface on which the query was resolved (the index for a given
+ * interface is determined via the if_nametoindex() family of calls).
+ * See "Constants for specifying an interface index" for more details.
+ *
+ * errorCode: Will be kDNSServiceErr_NoError on success, otherwise will
+ * indicate the failure that occurred. Other parameters are undefined if
+ * errorCode is nonzero.
+ *
+ * fullname: The resource record's full domain name.
+ *
+ * rrtype: The resource record's type (e.g. kDNSServiceType_PTR, kDNSServiceType_SRV, etc)
+ *
+ * rrclass: The class of the resource record (usually kDNSServiceClass_IN).
+ *
+ * rdlen: The length, in bytes, of the resource record rdata.
+ *
+ * rdata: The raw rdata of the resource record.
+ *
+ * ttl: If the client wishes to cache the result for performance reasons,
+ * the TTL indicates how long the client may legitimately hold onto
+ * this result, in seconds. After the TTL expires, the client should
+ * consider the result no longer valid, and if it requires this data
+ * again, it should be re-fetched with a new query. Of course, this
+ * only applies to clients that cancel the asynchronous operation when
+ * they get a result. Clients that leave the asynchronous operation
+ * running can safely assume that the data remains valid until they
+ * get another callback telling them otherwise.
+ *
+ * context: The context pointer that was passed to the callout.
+ *
+ */
+
+typedef void (DNSSD_API *DNSServiceQueryRecordReply)
+ (
+ DNSServiceRef sdRef,
+ DNSServiceFlags flags,
+ uint32_t interfaceIndex,
+ DNSServiceErrorType errorCode,
+ const char *fullname,
+ uint16_t rrtype,
+ uint16_t rrclass,
+ uint16_t rdlen,
+ const void *rdata,
+ uint32_t ttl,
+ void *context
+ );
+
+
+/* DNSServiceQueryRecord() Parameters:
+ *
+ * sdRef: A pointer to an uninitialized DNSServiceRef. If the call succeeds
+ * then it initializes the DNSServiceRef, returns kDNSServiceErr_NoError,
+ * and the query operation will run indefinitely until the client
+ * terminates it by passing this DNSServiceRef to DNSServiceRefDeallocate().
+ *
+ * flags: kDNSServiceFlagsForceMulticast or kDNSServiceFlagsLongLivedQuery.
+ * Pass kDNSServiceFlagsLongLivedQuery to create a "long-lived" unicast
+ * query in a non-local domain. Without setting this flag, unicast queries
+ * will be one-shot - that is, only answers available at the time of the call
+ * will be returned. By setting this flag, answers (including Add and Remove
+ * events) that become available after the initial call is made will generate
+ * callbacks. This flag has no effect on link-local multicast queries.
+ *
+ * interfaceIndex: If non-zero, specifies the interface on which to issue the query
+ * (the index for a given interface is determined via the if_nametoindex()
+ * family of calls.) Passing 0 causes the name to be queried for on all
+ * interfaces. See "Constants for specifying an interface index" for more details.
+ *
+ * fullname: The full domain name of the resource record to be queried for.
+ *
+ * rrtype: The numerical type of the resource record to be queried for
+ * (e.g. kDNSServiceType_PTR, kDNSServiceType_SRV, etc)
+ *
+ * rrclass: The class of the resource record (usually kDNSServiceClass_IN).
+ *
+ * callBack: The function to be called when a result is found, or if the call
+ * asynchronously fails.
+ *
+ * context: An application context pointer which is passed to the callback function
+ * (may be NULL).
+ *
+ * return value: Returns kDNSServiceErr_NoError on success (any subsequent, asynchronous
+ * errors are delivered to the callback), otherwise returns an error code indicating
+ * the error that occurred (the callback is never invoked and the DNSServiceRef
+ * is not initialized).
+ */
+
+DNSServiceErrorType DNSSD_API DNSServiceQueryRecord
+ (
+ DNSServiceRef *sdRef,
+ DNSServiceFlags flags,
+ uint32_t interfaceIndex,
+ const char *fullname,
+ uint16_t rrtype,
+ uint16_t rrclass,
+ DNSServiceQueryRecordReply callBack,
+ void *context /* may be NULL */
+ );
+
+
+/*********************************************************************************************
+ *
+ * Unified lookup of both IPv4 and IPv6 addresses for a fully qualified hostname
+ *
+ *********************************************************************************************/
+
+/* DNSServiceGetAddrInfo
+ *
+ * Queries for the IP address of a hostname by using either Multicast or Unicast DNS.
+ *
+ * DNSServiceGetAddrInfoReply() parameters:
+ *
+ * sdRef: The DNSServiceRef initialized by DNSServiceGetAddrInfo().
+ *
+ * flags: Possible values are kDNSServiceFlagsMoreComing and
+ * kDNSServiceFlagsAdd.
+ *
+ * interfaceIndex: The interface to which the answers pertain.
+ *
+ * errorCode: Will be kDNSServiceErr_NoError on success, otherwise will
+ * indicate the failure that occurred. Other parameters are
+ * undefined if errorCode is nonzero.
+ *
+ * hostname: The fully qualified domain name of the host to be queried for.
+ *
+ * address: IPv4 or IPv6 address.
+ *
+ * ttl: If the client wishes to cache the result for performance reasons,
+ * the TTL indicates how long the client may legitimately hold onto
+ * this result, in seconds. After the TTL expires, the client should
+ * consider the result no longer valid, and if it requires this data
+ * again, it should be re-fetched with a new query. Of course, this
+ * only applies to clients that cancel the asynchronous operation when
+ * they get a result. Clients that leave the asynchronous operation
+ * running can safely assume that the data remains valid until they
+ * get another callback telling them otherwise.
+ *
+ * context: The context pointer that was passed to the callout.
+ *
+ */
+
+typedef void (DNSSD_API *DNSServiceGetAddrInfoReply)
+ (
+ DNSServiceRef sdRef,
+ DNSServiceFlags flags,
+ uint32_t interfaceIndex,
+ DNSServiceErrorType errorCode,
+ const char *hostname,
+ const struct sockaddr *address,
+ uint32_t ttl,
+ void *context
+ );
+
+
+/* DNSServiceGetAddrInfo() Parameters:
+ *
+ * sdRef: A pointer to an uninitialized DNSServiceRef. If the call succeeds then it
+ * initializes the DNSServiceRef, returns kDNSServiceErr_NoError, and the query
+ * begins and will last indefinitely until the client terminates the query
+ * by passing this DNSServiceRef to DNSServiceRefDeallocate().
+ *
+ * flags: kDNSServiceFlagsForceMulticast or kDNSServiceFlagsLongLivedQuery.
+ * Pass kDNSServiceFlagsLongLivedQuery to create a "long-lived" unicast
+ * query in a non-local domain. Without setting this flag, unicast queries
+ * will be one-shot - that is, only answers available at the time of the call
+ * will be returned. By setting this flag, answers (including Add and Remove
+ * events) that become available after the initial call is made will generate
+ * callbacks. This flag has no effect on link-local multicast queries.
+ *
+ * interfaceIndex: The interface on which to issue the query. Passing 0 causes the query to be
+ * sent on all active interfaces via Multicast or the primary interface via Unicast.
+ *
+ * protocol: Pass in kDNSServiceProtocol_IPv4 to look up IPv4 addresses, or kDNSServiceProtocol_IPv6
+ * to look up IPv6 addresses, or both to look up both kinds. If neither flag is
+ * set, the system will apply an intelligent heuristic, which is (currently)
+ * that it will attempt to look up both, except:
+ *
+ * * If "hostname" is a wide-area unicast DNS hostname (i.e. not a ".local." name)
+ * but this host has no routable IPv6 address, then the call will not try to
+ * look up IPv6 addresses for "hostname", since any addresses it found would be
+ * unlikely to be of any use anyway. Similarly, if this host has no routable
+ * IPv4 address, the call will not try to look up IPv4 addresses for "hostname".
+ *
+ * * If "hostname" is a link-local multicast DNS hostname (i.e. a ".local." name)
+ * but this host has no IPv6 address of any kind, then it will not try to look
+ * up IPv6 addresses for "hostname". Similarly, if this host has no IPv4 address
+ * of any kind, the call will not try to look up IPv4 addresses for "hostname".
+ *
+ * hostname: The fully qualified domain name of the host to be queried for.
+ *
+ * callBack: The function to be called when the query succeeds or fails asynchronously.
+ *
+ * context: An application context pointer which is passed to the callback function
+ * (may be NULL).
+ *
+ * return value: Returns kDNSServiceErr_NoError on success (any subsequent, asynchronous
+ * errors are delivered to the callback), otherwise returns an error code indicating
+ * the error that occurred.
+ */
+
+DNSServiceErrorType DNSSD_API DNSServiceGetAddrInfo
+ (
+ DNSServiceRef *sdRef,
+ DNSServiceFlags flags,
+ uint32_t interfaceIndex,
+ DNSServiceProtocol protocol,
+ const char *hostname,
+ DNSServiceGetAddrInfoReply callBack,
+ void *context /* may be NULL */
+ );
+
+
+/*********************************************************************************************
+ *
+ * Special Purpose Calls:
+ * DNSServiceCreateConnection(), DNSServiceRegisterRecord(), DNSServiceReconfirmRecord()
+ * (most applications will not use these)
+ *
+ *********************************************************************************************/
+
+/* DNSServiceCreateConnection()
+ *
+ * Create a connection to the daemon allowing efficient registration of
+ * multiple individual records.
+ *
+ * Parameters:
+ *
+ * sdRef: A pointer to an uninitialized DNSServiceRef. Deallocating
+ * the reference (via DNSServiceRefDeallocate()) severs the
+ * connection and deregisters all records registered on this connection.
+ *
+ * return value: Returns kDNSServiceErr_NoError on success, otherwise returns
+ * an error code indicating the specific failure that occurred (in which
+ * case the DNSServiceRef is not initialized).
+ */
+
+DNSServiceErrorType DNSSD_API DNSServiceCreateConnection(DNSServiceRef *sdRef);
+
+
+/* DNSServiceRegisterRecord
+ *
+ * Register an individual resource record on a connected DNSServiceRef.
+ *
+ * Note that name conflicts occurring for records registered via this call must be handled
+ * by the client in the callback.
+ *
+ * DNSServiceRegisterRecordReply() parameters:
+ *
+ * sdRef: The connected DNSServiceRef initialized by
+ * DNSServiceCreateConnection().
+ *
+ * RecordRef: The DNSRecordRef initialized by DNSServiceRegisterRecord(). If the above
+ * DNSServiceRef is passed to DNSServiceRefDeallocate(), this DNSRecordRef is
+ * invalidated, and may not be used further.
+ *
+ * flags: Currently unused, reserved for future use.
+ *
+ * errorCode: Will be kDNSServiceErr_NoError on success, otherwise will
+ * indicate the failure that occurred (including name conflicts.)
+ * Other parameters are undefined if errorCode is nonzero.
+ *
+ * context: The context pointer that was passed to the callout.
+ *
+ */
+
+ typedef void (DNSSD_API *DNSServiceRegisterRecordReply)
+ (
+ DNSServiceRef sdRef,
+ DNSRecordRef RecordRef,
+ DNSServiceFlags flags,
+ DNSServiceErrorType errorCode,
+ void *context
+ );
+
+
+/* DNSServiceRegisterRecord() Parameters:
+ *
+ * sdRef: A DNSServiceRef initialized by DNSServiceCreateConnection().
+ *
+ * RecordRef: A pointer to an uninitialized DNSRecordRef. Upon succesfull completion of this
+ * call, this ref may be passed to DNSServiceUpdateRecord() or DNSServiceRemoveRecord().
+ * (To deregister ALL records registered on a single connected DNSServiceRef
+ * and deallocate each of their corresponding DNSServiceRecordRefs, call
+ * DNSServiceRefDeallocate()).
+ *
+ * flags: Possible values are kDNSServiceFlagsShared or kDNSServiceFlagsUnique
+ * (see flag type definitions for details).
+ *
+ * interfaceIndex: If non-zero, specifies the interface on which to register the record
+ * (the index for a given interface is determined via the if_nametoindex()
+ * family of calls.) Passing 0 causes the record to be registered on all interfaces.
+ * See "Constants for specifying an interface index" for more details.
+ *
+ * fullname: The full domain name of the resource record.
+ *
+ * rrtype: The numerical type of the resource record (e.g. kDNSServiceType_PTR, kDNSServiceType_SRV, etc)
+ *
+ * rrclass: The class of the resource record (usually kDNSServiceClass_IN)
+ *
+ * rdlen: Length, in bytes, of the rdata.
+ *
+ * rdata: A pointer to the raw rdata, as it is to appear in the DNS record.
+ *
+ * ttl: The time to live of the resource record, in seconds.
+ * Most clients should pass 0 to indicate that the system should
+ * select a sensible default value.
+ *
+ * callBack: The function to be called when a result is found, or if the call
+ * asynchronously fails (e.g. because of a name conflict.)
+ *
+ * context: An application context pointer which is passed to the callback function
+ * (may be NULL).
+ *
+ * return value: Returns kDNSServiceErr_NoError on success (any subsequent, asynchronous
+ * errors are delivered to the callback), otherwise returns an error code indicating
+ * the error that occurred (the callback is never invoked and the DNSRecordRef is
+ * not initialized).
+ */
+
+DNSServiceErrorType DNSSD_API DNSServiceRegisterRecord
+ (
+ DNSServiceRef sdRef,
+ DNSRecordRef *RecordRef,
+ DNSServiceFlags flags,
+ uint32_t interfaceIndex,
+ const char *fullname,
+ uint16_t rrtype,
+ uint16_t rrclass,
+ uint16_t rdlen,
+ const void *rdata,
+ uint32_t ttl,
+ DNSServiceRegisterRecordReply callBack,
+ void *context /* may be NULL */
+ );
+
+
+/* DNSServiceReconfirmRecord
+ *
+ * Instruct the daemon to verify the validity of a resource record that appears
+ * to be out of date (e.g. because TCP connection to a service's target failed.)
+ * Causes the record to be flushed from the daemon's cache (as well as all other
+ * daemons' caches on the network) if the record is determined to be invalid.
+ * Use this routine conservatively. Reconfirming a record necessarily consumes
+ * network bandwidth, so this should not be done indiscriminately.
+ *
+ * Parameters:
+ *
+ * flags: Pass kDNSServiceFlagsForce to force immediate deletion of record,
+ * instead of after some number of reconfirmation queries have gone unanswered.
+ *
+ * interfaceIndex: Specifies the interface of the record in question.
+ * The caller must specify the interface.
+ * This API (by design) causes increased network traffic, so it requires
+ * the caller to be precise about which record should be reconfirmed.
+ * It is not possible to pass zero for the interface index to perform
+ * a "wildcard" reconfirmation, where *all* matching records are reconfirmed.
+ *
+ * fullname: The resource record's full domain name.
+ *
+ * rrtype: The resource record's type (e.g. kDNSServiceType_PTR, kDNSServiceType_SRV, etc)
+ *
+ * rrclass: The class of the resource record (usually kDNSServiceClass_IN).
+ *
+ * rdlen: The length, in bytes, of the resource record rdata.
+ *
+ * rdata: The raw rdata of the resource record.
+ *
+ */
+
+DNSServiceErrorType DNSSD_API DNSServiceReconfirmRecord
+ (
+ DNSServiceFlags flags,
+ uint32_t interfaceIndex,
+ const char *fullname,
+ uint16_t rrtype,
+ uint16_t rrclass,
+ uint16_t rdlen,
+ const void *rdata
+ );
+
+
+/*********************************************************************************************
+ *
+ * NAT Port Mapping
+ *
+ *********************************************************************************************/
+
+/* DNSServiceNATPortMappingCreate
+ *
+ * Request a port mapping in the NAT gateway, which maps a port on the local machine
+ * to an external port on the NAT.
+ *
+ * The port mapping will be renewed indefinitely until the client process exits, or
+ * explicitly terminates the port mapping request by calling DNSServiceRefDeallocate().
+ * The client callback will be invoked, informing the client of the NAT gateway's
+ * external IP address and the external port that has been allocated for this client.
+ * The client should then record this external IP address and port using whatever
+ * directory service mechanism it is using to enable peers to connect to it.
+ * (Clients advertising services using Wide-Area DNS-SD DO NOT need to use this API
+ * -- when a client calls DNSServiceRegister() NAT mappings are automatically created
+ * and the external IP address and port for the service are recorded in the global DNS.
+ * Only clients using some directory mechanism other than Wide-Area DNS-SD need to use
+ * this API to explicitly map their own ports.)
+ *
+ * It's possible that the client callback could be called multiple times, for example
+ * if the NAT gateway's IP address changes, or if a configuration change results in a
+ * different external port being mapped for this client. Over the lifetime of any long-lived
+ * port mapping, the client should be prepared to handle these notifications of changes
+ * in the environment, and should update its recorded address and/or port as appropriate.
+ *
+ * NOTE: There are two unusual aspects of how the DNSServiceNATPortMappingCreate API works,
+ * which were intentionally designed to help simplify client code:
+ *
+ * 1. It's not an error to request a NAT mapping when the machine is not behind a NAT gateway.
+ * In other NAT mapping APIs, if you request a NAT mapping and the machine is not behind a NAT
+ * gateway, then the API returns an error code -- it can't get you a NAT mapping if there's no
+ * NAT gateway. The DNSServiceNATPortMappingCreate API takes a different view. Working out
+ * whether or not you need a NAT mapping can be tricky and non-obvious, particularly on
+ * a machine with multiple active network interfaces. Rather than make every client recreate
+ * this logic for deciding whether a NAT mapping is required, the PortMapping API does that
+ * work for you. If the client calls the PortMapping API when the machine already has a
+ * routable public IP address, then instead of complaining about it and giving an error,
+ * the PortMapping API just invokes your callback, giving the machine's public address
+ * and your own port number. This means you don't need to write code to work out whether
+ * your client needs to call the PortMapping API -- just call it anyway, and if it wasn't
+ * necessary, no harm is done:
+ *
+ * - If the machine already has a routable public IP address, then your callback
+ * will just be invoked giving your own address and port.
+ * - If a NAT mapping is required and obtained, then your callback will be invoked
+ * giving you the external address and port.
+ * - If a NAT mapping is required but not obtained from the local NAT gateway,
+ * or the machine has no network connectivity, then your callback will be
+ * invoked giving zero address and port.
+ *
+ * 2. In other NAT mapping APIs, if a laptop computer is put to sleep and woken up on a new
+ * network, it's the client's job to notice this, and work out whether a NAT mapping
+ * is required on the new network, and make a new NAT mapping request if necessary.
+ * The DNSServiceNATPortMappingCreate API does this for you, automatically.
+ * The client just needs to make one call to the PortMapping API, and its callback will
+ * be invoked any time the mapping state changes. This property complements point (1) above.
+ * If the client didn't make a NAT mapping request just because it determined that one was
+ * not required at that particular moment in time, the client would then have to monitor
+ * for network state changes to determine if a NAT port mapping later became necessary.
+ * By unconditionally making a NAT mapping request, even when a NAT mapping not to be
+ * necessary, the PortMapping API will then begin monitoring network state changes on behalf of
+ * the client, and if a NAT mapping later becomes necessary, it will automatically create a NAT
+ * mapping and inform the client with a new callback giving the new address and port information.
+ *
+ * DNSServiceNATPortMappingReply() parameters:
+ *
+ * sdRef: The DNSServiceRef initialized by DNSServiceNATPortMappingCreate().
+ *
+ * flags: Currently unused, reserved for future use.
+ *
+ * interfaceIndex: The interface through which the NAT gateway is reached.
+ *
+ * errorCode: Will be kDNSServiceErr_NoError on success.
+ * Will be kDNSServiceErr_DoubleNAT when the NAT gateway is itself behind one or
+ * more layers of NAT, in which case the other parameters have the defined values.
+ * For other failures, will indicate the failure that occurred, and the other
+ * parameters are undefined.
+ *
+ * externalAddress: Four byte IPv4 address in network byte order.
+ *
+ * protocol: Will be kDNSServiceProtocol_UDP or kDNSServiceProtocol_TCP or both.
+ *
+ * internalPort: The port on the local machine that was mapped.
+ *
+ * externalPort: The actual external port in the NAT gateway that was mapped.
+ * This is likely to be different than the requested external port.
+ *
+ * ttl: The lifetime of the NAT port mapping created on the gateway.
+ * This controls how quickly stale mappings will be garbage-collected
+ * if the client machine crashes, suffers a power failure, is disconnected
+ * from the network, or suffers some other unfortunate demise which
+ * causes it to vanish without explicitly removing its NAT port mapping.
+ * It's possible that the ttl value will differ from the requested ttl value.
+ *
+ * context: The context pointer that was passed to the callout.
+ *
+ */
+
+typedef void (DNSSD_API *DNSServiceNATPortMappingReply)
+ (
+ DNSServiceRef sdRef,
+ DNSServiceFlags flags,
+ uint32_t interfaceIndex,
+ DNSServiceErrorType errorCode,
+ uint32_t externalAddress, /* four byte IPv4 address in network byte order */
+ DNSServiceProtocol protocol,
+ uint16_t internalPort,
+ uint16_t externalPort, /* may be different than the requested port */
+ uint32_t ttl, /* may be different than the requested ttl */
+ void *context
+ );
+
+
+/* DNSServiceNATPortMappingCreate() Parameters:
+ *
+ * sdRef: A pointer to an uninitialized DNSServiceRef. If the call succeeds then it
+ * initializes the DNSServiceRef, returns kDNSServiceErr_NoError, and the nat
+ * port mapping will last indefinitely until the client terminates the port
+ * mapping request by passing this DNSServiceRef to DNSServiceRefDeallocate().
+ *
+ * flags: Currently ignored, reserved for future use.
+ *
+ * interfaceIndex: The interface on which to create port mappings in a NAT gateway. Passing 0 causes
+ * the port mapping request to be sent on the primary interface.
+ *
+ * protocol: To request a port mapping, pass in kDNSServiceProtocol_UDP, or kDNSServiceProtocol_TCP,
+ * or (kDNSServiceProtocol_UDP | kDNSServiceProtocol_TCP) to map both.
+ * The local listening port number must also be specified in the internalPort parameter.
+ * To just discover the NAT gateway's external IP address, pass zero for protocol,
+ * internalPort, externalPort and ttl.
+ *
+ * internalPort: The port number in network byte order on the local machine which is listening for packets.
+ *
+ * externalPort: The requested external port in network byte order in the NAT gateway that you would
+ * like to map to the internal port. Pass 0 if you don't care which external port is chosen for you.
+ *
+ * ttl: The requested renewal period of the NAT port mapping, in seconds.
+ * If the client machine crashes, suffers a power failure, is disconnected from
+ * the network, or suffers some other unfortunate demise which causes it to vanish
+ * unexpectedly without explicitly removing its NAT port mappings, then the NAT gateway
+ * will garbage-collect old stale NAT port mappings when their lifetime expires.
+ * Requesting a short TTL causes such orphaned mappings to be garbage-collected
+ * more promptly, but consumes system resources and network bandwidth with
+ * frequent renewal packets to keep the mapping from expiring.
+ * Requesting a long TTL is more efficient on the network, but in the event of the
+ * client vanishing, stale NAT port mappings will not be garbage-collected as quickly.
+ * Most clients should pass 0 to use a system-wide default value.
+ *
+ * callBack: The function to be called when the port mapping request succeeds or fails asynchronously.
+ *
+ * context: An application context pointer which is passed to the callback function
+ * (may be NULL).
+ *
+ * return value: Returns kDNSServiceErr_NoError on success (any subsequent, asynchronous
+ * errors are delivered to the callback), otherwise returns an error code indicating
+ * the error that occurred.
+ *
+ * If you don't actually want a port mapped, and are just calling the API
+ * because you want to find out the NAT's external IP address (e.g. for UI
+ * display) then pass zero for protocol, internalPort, externalPort and ttl.
+ */
+
+DNSServiceErrorType DNSSD_API DNSServiceNATPortMappingCreate
+ (
+ DNSServiceRef *sdRef,
+ DNSServiceFlags flags,
+ uint32_t interfaceIndex,
+ DNSServiceProtocol protocol, /* TCP and/or UDP */
+ uint16_t internalPort, /* network byte order */
+ uint16_t externalPort, /* network byte order */
+ uint32_t ttl, /* time to live in seconds */
+ DNSServiceNATPortMappingReply callBack,
+ void *context /* may be NULL */
+ );
+
+
+/*********************************************************************************************
+ *
+ * General Utility Functions
+ *
+ *********************************************************************************************/
+
+/* DNSServiceConstructFullName()
+ *
+ * Concatenate a three-part domain name (as returned by the above callbacks) into a
+ * properly-escaped full domain name. Note that callbacks in the above functions ALREADY ESCAPE
+ * strings where necessary.
+ *
+ * Parameters:
+ *
+ * fullName: A pointer to a buffer that where the resulting full domain name is to be written.
+ * The buffer must be kDNSServiceMaxDomainName (1009) bytes in length to
+ * accommodate the longest legal domain name without buffer overrun.
+ *
+ * service: The service name - any dots or backslashes must NOT be escaped.
+ * May be NULL (to construct a PTR record name, e.g.
+ * "_ftp._tcp.apple.com.").
+ *
+ * regtype: The service type followed by the protocol, separated by a dot
+ * (e.g. "_ftp._tcp").
+ *
+ * domain: The domain name, e.g. "apple.com.". Literal dots or backslashes,
+ * if any, must be escaped, e.g. "1st\. Floor.apple.com."
+ *
+ * return value: Returns kDNSServiceErr_NoError (0) on success, kDNSServiceErr_BadParam on error.
+ *
+ */
+
+DNSServiceErrorType DNSSD_API DNSServiceConstructFullName
+ (
+ char *fullName,
+ const char *service, /* may be NULL */
+ const char *regtype,
+ const char *domain
+ );
+
+
+/*********************************************************************************************
+ *
+ * TXT Record Construction Functions
+ *
+ *********************************************************************************************/
+
+/*
+ * A typical calling sequence for TXT record construction is something like:
+ *
+ * Client allocates storage for TXTRecord data (e.g. declare buffer on the stack)
+ * TXTRecordCreate();
+ * TXTRecordSetValue();
+ * TXTRecordSetValue();
+ * TXTRecordSetValue();
+ * ...
+ * DNSServiceRegister( ... TXTRecordGetLength(), TXTRecordGetBytesPtr() ... );
+ * TXTRecordDeallocate();
+ * Explicitly deallocate storage for TXTRecord data (if not allocated on the stack)
+ */
+
+
+/* TXTRecordRef
+ *
+ * Opaque internal data type.
+ * Note: Represents a DNS-SD TXT record.
+ */
+
+typedef union _TXTRecordRef_t { char PrivateData[16]; char *ForceNaturalAlignment; } TXTRecordRef;
+
+
+/* TXTRecordCreate()
+ *
+ * Creates a new empty TXTRecordRef referencing the specified storage.
+ *
+ * If the buffer parameter is NULL, or the specified storage size is not
+ * large enough to hold a key subsequently added using TXTRecordSetValue(),
+ * then additional memory will be added as needed using malloc().
+ *
+ * On some platforms, when memory is low, malloc() may fail. In this
+ * case, TXTRecordSetValue() will return kDNSServiceErr_NoMemory, and this
+ * error condition will need to be handled as appropriate by the caller.
+ *
+ * You can avoid the need to handle this error condition if you ensure
+ * that the storage you initially provide is large enough to hold all
+ * the key/value pairs that are to be added to the record.
+ * The caller can precompute the exact length required for all of the
+ * key/value pairs to be added, or simply provide a fixed-sized buffer
+ * known in advance to be large enough.
+ * A no-value (key-only) key requires (1 + key length) bytes.
+ * A key with empty value requires (1 + key length + 1) bytes.
+ * A key with non-empty value requires (1 + key length + 1 + value length).
+ * For most applications, DNS-SD TXT records are generally
+ * less than 100 bytes, so in most cases a simple fixed-sized
+ * 256-byte buffer will be more than sufficient.
+ * Recommended size limits for DNS-SD TXT Records are discussed in
+ * <http://files.dns-sd.org/draft-cheshire-dnsext-dns-sd.txt>
+ *
+ * Note: When passing parameters to and from these TXT record APIs,
+ * the key name does not include the '=' character. The '=' character
+ * is the separator between the key and value in the on-the-wire
+ * packet format; it is not part of either the key or the value.
+ *
+ * txtRecord: A pointer to an uninitialized TXTRecordRef.
+ *
+ * bufferLen: The size of the storage provided in the "buffer" parameter.
+ *
+ * buffer: Optional caller-supplied storage used to hold the TXTRecord data.
+ * This storage must remain valid for as long as
+ * the TXTRecordRef.
+ */
+
+void DNSSD_API TXTRecordCreate
+ (
+ TXTRecordRef *txtRecord,
+ uint16_t bufferLen,
+ void *buffer
+ );
+
+
+/* TXTRecordDeallocate()
+ *
+ * Releases any resources allocated in the course of preparing a TXT Record
+ * using TXTRecordCreate()/TXTRecordSetValue()/TXTRecordRemoveValue().
+ * Ownership of the buffer provided in TXTRecordCreate() returns to the client.
+ *
+ * txtRecord: A TXTRecordRef initialized by calling TXTRecordCreate().
+ *
+ */
+
+void DNSSD_API TXTRecordDeallocate
+ (
+ TXTRecordRef *txtRecord
+ );
+
+
+/* TXTRecordSetValue()
+ *
+ * Adds a key (optionally with value) to a TXTRecordRef. If the "key" already
+ * exists in the TXTRecordRef, then the current value will be replaced with
+ * the new value.
+ * Keys may exist in four states with respect to a given TXT record:
+ * - Absent (key does not appear at all)
+ * - Present with no value ("key" appears alone)
+ * - Present with empty value ("key=" appears in TXT record)
+ * - Present with non-empty value ("key=value" appears in TXT record)
+ * For more details refer to "Data Syntax for DNS-SD TXT Records" in
+ * <http://files.dns-sd.org/draft-cheshire-dnsext-dns-sd.txt>
+ *
+ * txtRecord: A TXTRecordRef initialized by calling TXTRecordCreate().
+ *
+ * key: A null-terminated string which only contains printable ASCII
+ * values (0x20-0x7E), excluding '=' (0x3D). Keys should be
+ * 9 characters or fewer (not counting the terminating null).
+ *
+ * valueSize: The size of the value.
+ *
+ * value: Any binary value. For values that represent
+ * textual data, UTF-8 is STRONGLY recommended.
+ * For values that represent textual data, valueSize
+ * should NOT include the terminating null (if any)
+ * at the end of the string.
+ * If NULL, then "key" will be added with no value.
+ * If non-NULL but valueSize is zero, then "key=" will be
+ * added with empty value.
+ *
+ * return value: Returns kDNSServiceErr_NoError on success.
+ * Returns kDNSServiceErr_Invalid if the "key" string contains
+ * illegal characters.
+ * Returns kDNSServiceErr_NoMemory if adding this key would
+ * exceed the available storage.
+ */
+
+DNSServiceErrorType DNSSD_API TXTRecordSetValue
+ (
+ TXTRecordRef *txtRecord,
+ const char *key,
+ uint8_t valueSize, /* may be zero */
+ const void *value /* may be NULL */
+ );
+
+
+/* TXTRecordRemoveValue()
+ *
+ * Removes a key from a TXTRecordRef. The "key" must be an
+ * ASCII string which exists in the TXTRecordRef.
+ *
+ * txtRecord: A TXTRecordRef initialized by calling TXTRecordCreate().
+ *
+ * key: A key name which exists in the TXTRecordRef.
+ *
+ * return value: Returns kDNSServiceErr_NoError on success.
+ * Returns kDNSServiceErr_NoSuchKey if the "key" does not
+ * exist in the TXTRecordRef.
+ */
+
+DNSServiceErrorType DNSSD_API TXTRecordRemoveValue
+ (
+ TXTRecordRef *txtRecord,
+ const char *key
+ );
+
+
+/* TXTRecordGetLength()
+ *
+ * Allows you to determine the length of the raw bytes within a TXTRecordRef.
+ *
+ * txtRecord: A TXTRecordRef initialized by calling TXTRecordCreate().
+ *
+ * return value: Returns the size of the raw bytes inside a TXTRecordRef
+ * which you can pass directly to DNSServiceRegister() or
+ * to DNSServiceUpdateRecord().
+ * Returns 0 if the TXTRecordRef is empty.
+ */
+
+uint16_t DNSSD_API TXTRecordGetLength
+ (
+ const TXTRecordRef *txtRecord
+ );
+
+
+/* TXTRecordGetBytesPtr()
+ *
+ * Allows you to retrieve a pointer to the raw bytes within a TXTRecordRef.
+ *
+ * txtRecord: A TXTRecordRef initialized by calling TXTRecordCreate().
+ *
+ * return value: Returns a pointer to the raw bytes inside the TXTRecordRef
+ * which you can pass directly to DNSServiceRegister() or
+ * to DNSServiceUpdateRecord().
+ */
+
+const void * DNSSD_API TXTRecordGetBytesPtr
+ (
+ const TXTRecordRef *txtRecord
+ );
+
+
+/*********************************************************************************************
+ *
+ * TXT Record Parsing Functions
+ *
+ *********************************************************************************************/
+
+/*
+ * A typical calling sequence for TXT record parsing is something like:
+ *
+ * Receive TXT record data in DNSServiceResolve() callback
+ * if (TXTRecordContainsKey(txtLen, txtRecord, "key")) then do something
+ * val1ptr = TXTRecordGetValuePtr(txtLen, txtRecord, "key1", &len1);
+ * val2ptr = TXTRecordGetValuePtr(txtLen, txtRecord, "key2", &len2);
+ * ...
+ * memcpy(myval1, val1ptr, len1);
+ * memcpy(myval2, val2ptr, len2);
+ * ...
+ * return;
+ *
+ * If you wish to retain the values after return from the DNSServiceResolve()
+ * callback, then you need to copy the data to your own storage using memcpy()
+ * or similar, as shown in the example above.
+ *
+ * If for some reason you need to parse a TXT record you built yourself
+ * using the TXT record construction functions above, then you can do
+ * that using TXTRecordGetLength and TXTRecordGetBytesPtr calls:
+ * TXTRecordGetValue(TXTRecordGetLength(x), TXTRecordGetBytesPtr(x), key, &len);
+ *
+ * Most applications only fetch keys they know about from a TXT record and
+ * ignore the rest.
+ * However, some debugging tools wish to fetch and display all keys.
+ * To do that, use the TXTRecordGetCount() and TXTRecordGetItemAtIndex() calls.
+ */
+
+/* TXTRecordContainsKey()
+ *
+ * Allows you to determine if a given TXT Record contains a specified key.
+ *
+ * txtLen: The size of the received TXT Record.
+ *
+ * txtRecord: Pointer to the received TXT Record bytes.
+ *
+ * key: A null-terminated ASCII string containing the key name.
+ *
+ * return value: Returns 1 if the TXT Record contains the specified key.
+ * Otherwise, it returns 0.
+ */
+
+int DNSSD_API TXTRecordContainsKey
+ (
+ uint16_t txtLen,
+ const void *txtRecord,
+ const char *key
+ );
+
+
+/* TXTRecordGetValuePtr()
+ *
+ * Allows you to retrieve the value for a given key from a TXT Record.
+ *
+ * txtLen: The size of the received TXT Record
+ *
+ * txtRecord: Pointer to the received TXT Record bytes.
+ *
+ * key: A null-terminated ASCII string containing the key name.
+ *
+ * valueLen: On output, will be set to the size of the "value" data.
+ *
+ * return value: Returns NULL if the key does not exist in this TXT record,
+ * or exists with no value (to differentiate between
+ * these two cases use TXTRecordContainsKey()).
+ * Returns pointer to location within TXT Record bytes
+ * if the key exists with empty or non-empty value.
+ * For empty value, valueLen will be zero.
+ * For non-empty value, valueLen will be length of value data.
+ */
+
+const void * DNSSD_API TXTRecordGetValuePtr
+ (
+ uint16_t txtLen,
+ const void *txtRecord,
+ const char *key,
+ uint8_t *valueLen
+ );
+
+
+/* TXTRecordGetCount()
+ *
+ * Returns the number of keys stored in the TXT Record. The count
+ * can be used with TXTRecordGetItemAtIndex() to iterate through the keys.
+ *
+ * txtLen: The size of the received TXT Record.
+ *
+ * txtRecord: Pointer to the received TXT Record bytes.
+ *
+ * return value: Returns the total number of keys in the TXT Record.
+ *
+ */
+
+uint16_t DNSSD_API TXTRecordGetCount
+ (
+ uint16_t txtLen,
+ const void *txtRecord
+ );
+
+
+/* TXTRecordGetItemAtIndex()
+ *
+ * Allows you to retrieve a key name and value pointer, given an index into
+ * a TXT Record. Legal index values range from zero to TXTRecordGetCount()-1.
+ * It's also possible to iterate through keys in a TXT record by simply
+ * calling TXTRecordGetItemAtIndex() repeatedly, beginning with index zero
+ * and increasing until TXTRecordGetItemAtIndex() returns kDNSServiceErr_Invalid.
+ *
+ * On return:
+ * For keys with no value, *value is set to NULL and *valueLen is zero.
+ * For keys with empty value, *value is non-NULL and *valueLen is zero.
+ * For keys with non-empty value, *value is non-NULL and *valueLen is non-zero.
+ *
+ * txtLen: The size of the received TXT Record.
+ *
+ * txtRecord: Pointer to the received TXT Record bytes.
+ *
+ * itemIndex: An index into the TXT Record.
+ *
+ * keyBufLen: The size of the string buffer being supplied.
+ *
+ * key: A string buffer used to store the key name.
+ * On return, the buffer contains a null-terminated C string
+ * giving the key name. DNS-SD TXT keys are usually
+ * 9 characters or fewer. To hold the maximum possible
+ * key name, the buffer should be 256 bytes long.
+ *
+ * valueLen: On output, will be set to the size of the "value" data.
+ *
+ * value: On output, *value is set to point to location within TXT
+ * Record bytes that holds the value data.
+ *
+ * return value: Returns kDNSServiceErr_NoError on success.
+ * Returns kDNSServiceErr_NoMemory if keyBufLen is too short.
+ * Returns kDNSServiceErr_Invalid if index is greater than
+ * TXTRecordGetCount()-1.
+ */
+
+DNSServiceErrorType DNSSD_API TXTRecordGetItemAtIndex
+ (
+ uint16_t txtLen,
+ const void *txtRecord,
+ uint16_t itemIndex,
+ uint16_t keyBufLen,
+ char *key,
+ uint8_t *valueLen,
+ const void **value
+ );
+
+#ifdef __APPLE_API_PRIVATE
+
+/*
+ * Mac OS X specific functionality
+ * 3rd party clients of this API should not depend on future support or availability of this routine
+ */
+
+/* DNSServiceSetDefaultDomainForUser()
+ *
+ * Set the default domain for the caller's UID. Future browse and registration
+ * calls by this user that do not specify an explicit domain will browse and
+ * register in this wide-area domain in addition to .local. In addition, this
+ * domain will be returned as a Browse domain via domain enumeration calls.
+ *
+ * Parameters:
+ *
+ * flags: Pass kDNSServiceFlagsAdd to add a domain for a user. Call without
+ * this flag set to clear a previously added domain.
+ *
+ * domain: The domain to be used for the caller's UID.
+ *
+ * return value: Returns kDNSServiceErr_NoError on success, otherwise returns
+ * an error code indicating the error that occurred.
+ */
+
+DNSServiceErrorType DNSSD_API DNSServiceSetDefaultDomainForUser
+ (
+ DNSServiceFlags flags,
+ const char *domain
+ );
+
+/* Symbol defined to tell System Configuration Framework where to look in the Dynamic Store
+ * for the list of PrivateDNS domains that need to be handed off to mDNSResponder
+ * (the complete key is "State:/Network/PrivateDNS")
+ */
+#define kDNSServiceCompPrivateDNS "PrivateDNS"
+#define kDNSServiceCompMulticastDNS "MulticastDNS"
+
+#endif //__APPLE_API_PRIVATE
+
+/* Some C compiler cleverness. We can make the compiler check certain things for us,
+ * and report errors at compile-time if anything is wrong. The usual way to do this would
+ * be to use a run-time "if" statement or the conventional run-time "assert" mechanism, but
+ * then you don't find out what's wrong until you run the software. This way, if the assertion
+ * condition is false, the array size is negative, and the complier complains immediately.
+ */
+
+struct CompileTimeAssertionChecks_DNS_SD
+ {
+ char assert0[(sizeof(union _TXTRecordRef_t) == 16) ? 1 : -1];
+ };
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif /* _DNS_SD_H */
diff --git a/include/jni/jawt.h b/include/jni/jawt.h
new file mode 100644
index 0000000..b52cfcf
--- /dev/null
+++ b/include/jni/jawt.h
@@ -0,0 +1,278 @@
+/*
+ * @(#)jawt.h 1.9 03/01/23
+ *
+ * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
+ */
+
+#ifndef _JAVASOFT_JAWT_H_
+#define _JAVASOFT_JAWT_H_
+
+#include "jni.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * AWT native interface (new in JDK 1.3)
+ *
+ * The AWT native interface allows a native C or C++ application a means
+ * by which to access native structures in AWT. This is to facilitate moving
+ * legacy C and C++ applications to Java and to target the needs of the
+ * community who, at present, wish to do their own native rendering to canvases
+ * for performance reasons. Standard extensions such as Java3D also require a
+ * means to access the underlying native data structures of AWT.
+ *
+ * There may be future extensions to this API depending on demand.
+ *
+ * A VM does not have to implement this API in order to pass the JCK.
+ * It is recommended, however, that this API is implemented on VMs that support
+ * standard extensions, such as Java3D.
+ *
+ * Since this is a native API, any program which uses it cannot be considered
+ * 100% pure java.
+ */
+
+/*
+ * AWT Native Drawing Surface (JAWT_DrawingSurface).
+ *
+ * For each platform, there is a native drawing surface structure. This
+ * platform-specific structure can be found in jawt_md.h. It is recommended
+ * that additional platforms follow the same model. It is also recommended
+ * that VMs on Win32 and Solaris support the existing structures in jawt_md.h.
+ *
+ *******************
+ * EXAMPLE OF USAGE:
+ *******************
+ *
+ * In Win32, a programmer wishes to access the HWND of a canvas to perform
+ * native rendering into it. The programmer has declared the paint() method
+ * for their canvas subclass to be native:
+ *
+ *
+ * MyCanvas.java:
+ *
+ * import java.awt.*;
+ *
+ * public class MyCanvas extends Canvas {
+ *
+ * static {
+ * System.loadLibrary("mylib");
+ * }
+ *
+ * public native void paint(Graphics g);
+ * }
+ *
+ *
+ * myfile.c:
+ *
+ * #include "jawt_md.h"
+ * #include <assert.h>
+ *
+ * JNIEXPORT void JNICALL
+ * Java_MyCanvas_paint(JNIEnv* env, jobject canvas, jobject graphics)
+ * {
+ * JAWT awt;
+ * JAWT_DrawingSurface* ds;
+ * JAWT_DrawingSurfaceInfo* dsi;
+ * JAWT_Win32DrawingSurfaceInfo* dsi_win;
+ * jboolean result;
+ * jint lock;
+ *
+ * // Get the AWT
+ * awt.version = JAWT_VERSION_1_3;
+ * result = JAWT_GetAWT(env, &awt);
+ * assert(result != JNI_FALSE);
+ *
+ * // Get the drawing surface
+ * ds = awt.GetDrawingSurface(env, canvas);
+ * assert(ds != NULL);
+ *
+ * // Lock the drawing surface
+ * lock = ds->Lock(ds);
+ * assert((lock & JAWT_LOCK_ERROR) == 0);
+ *
+ * // Get the drawing surface info
+ * dsi = ds->GetDrawingSurfaceInfo(ds);
+ *
+ * // Get the platform-specific drawing info
+ * dsi_win = (JAWT_Win32DrawingSurfaceInfo*)dsi->platformInfo;
+ *
+ * //////////////////////////////
+ * // !!! DO PAINTING HERE !!! //
+ * //////////////////////////////
+ *
+ * // Free the drawing surface info
+ * ds->FreeDrawingSurfaceInfo(dsi);
+ *
+ * // Unlock the drawing surface
+ * ds->Unlock(ds);
+ *
+ * // Free the drawing surface
+ * awt.FreeDrawingSurface(ds);
+ * }
+ *
+ */
+
+/*
+ * JAWT_Rectangle
+ * Structure for a native rectangle.
+ */
+typedef struct jawt_Rectangle {
+ jint x;
+ jint y;
+ jint width;
+ jint height;
+} JAWT_Rectangle;
+
+struct jawt_DrawingSurface;
+
+/*
+ * JAWT_DrawingSurfaceInfo
+ * Structure for containing the underlying drawing information of a component.
+ */
+typedef struct jawt_DrawingSurfaceInfo {
+ /*
+ * Pointer to the platform-specific information. This can be safely
+ * cast to a JAWT_Win32DrawingSurfaceInfo on Windows or a
+ * JAWT_X11DrawingSurfaceInfo on Solaris. See jawt_md.h for details.
+ */
+ void* platformInfo;
+ /* Cached pointer to the underlying drawing surface */
+ struct jawt_DrawingSurface* ds;
+ /* Bounding rectangle of the drawing surface */
+ JAWT_Rectangle bounds;
+ /* Number of rectangles in the clip */
+ jint clipSize;
+ /* Clip rectangle array */
+ JAWT_Rectangle* clip;
+} JAWT_DrawingSurfaceInfo;
+
+#define JAWT_LOCK_ERROR 0x00000001
+#define JAWT_LOCK_CLIP_CHANGED 0x00000002
+#define JAWT_LOCK_BOUNDS_CHANGED 0x00000004
+#define JAWT_LOCK_SURFACE_CHANGED 0x00000008
+
+/*
+ * JAWT_DrawingSurface
+ * Structure for containing the underlying drawing information of a component.
+ * All operations on a JAWT_DrawingSurface MUST be performed from the same
+ * thread as the call to GetDrawingSurface.
+ */
+typedef struct jawt_DrawingSurface {
+ /*
+ * Cached reference to the Java environment of the calling thread.
+ * If Lock(), Unlock(), GetDrawingSurfaceInfo() or
+ * FreeDrawingSurfaceInfo() are called from a different thread,
+ * this data member should be set before calling those functions.
+ */
+ JNIEnv* env;
+ /* Cached reference to the target object */
+ jobject target;
+ /*
+ * Lock the surface of the target component for native rendering.
+ * When finished drawing, the surface must be unlocked with
+ * Unlock(). This function returns a bitmask with one or more of the
+ * following values:
+ *
+ * JAWT_LOCK_ERROR - When an error has occurred and the surface could not
+ * be locked.
+ *
+ * JAWT_LOCK_CLIP_CHANGED - When the clip region has changed.
+ *
+ * JAWT_LOCK_BOUNDS_CHANGED - When the bounds of the surface have changed.
+ *
+ * JAWT_LOCK_SURFACE_CHANGED - When the surface itself has changed
+ */
+ jint (JNICALL *Lock)
+ (struct jawt_DrawingSurface* ds);
+ /*
+ * Get the drawing surface info.
+ * The value returned may be cached, but the values may change if
+ * additional calls to Lock() or Unlock() are made.
+ * Lock() must be called before this can return a valid value.
+ * Returns NULL if an error has occurred.
+ * When finished with the returned value, FreeDrawingSurfaceInfo must be
+ * called.
+ */
+ JAWT_DrawingSurfaceInfo* (JNICALL *GetDrawingSurfaceInfo)
+ (struct jawt_DrawingSurface* ds);
+ /*
+ * Free the drawing surface info.
+ */
+ void (JNICALL *FreeDrawingSurfaceInfo)
+ (JAWT_DrawingSurfaceInfo* dsi);
+ /*
+ * Unlock the drawing surface of the target component for native rendering.
+ */
+ void (JNICALL *Unlock)
+ (struct jawt_DrawingSurface* ds);
+} JAWT_DrawingSurface;
+
+/*
+ * JAWT
+ * Structure for containing native AWT functions.
+ */
+typedef struct jawt {
+ /*
+ * Version of this structure. This must always be set before
+ * calling JAWT_GetAWT()
+ */
+ jint version;
+ /*
+ * Return a drawing surface from a target jobject. This value
+ * may be cached.
+ * Returns NULL if an error has occurred.
+ * Target must be a java.awt.Component (should be a Canvas
+ * or Window for native rendering).
+ * FreeDrawingSurface() must be called when finished with the
+ * returned JAWT_DrawingSurface.
+ */
+ JAWT_DrawingSurface* (JNICALL *GetDrawingSurface)
+ (JNIEnv* env, jobject target);
+ /*
+ * Free the drawing surface allocated in GetDrawingSurface.
+ */
+ void (JNICALL *FreeDrawingSurface)
+ (JAWT_DrawingSurface* ds);
+ /*
+ * Since 1.4
+ * Locks the entire AWT for synchronization purposes
+ */
+ void (JNICALL *Lock)(JNIEnv* env);
+ /*
+ * Since 1.4
+ * Unlocks the entire AWT for synchronization purposes
+ */
+ void (JNICALL *Unlock)(JNIEnv* env);
+ /*
+ * Since 1.4
+ * Returns a reference to a java.awt.Component from a native
+ * platform handle. On Windows, this corresponds to an HWND;
+ * on Solaris and Linux, this is a Drawable. For other platforms,
+ * see the appropriate machine-dependent header file for a description.
+ * The reference returned by this function is a local
+ * reference that is only valid in this environment.
+ * This function returns a NULL reference if no component could be
+ * found with matching platform information.
+ */
+ jobject (JNICALL *GetComponent)(JNIEnv* env, void* platformInfo);
+
+} JAWT;
+
+/*
+ * Get the AWT native structure. This function returns JNI_FALSE if
+ * an error occurs.
+ */
+_JNI_IMPORT_OR_EXPORT_
+jboolean JNICALL JAWT_GetAWT(JNIEnv* env, JAWT* awt);
+
+#define JAWT_VERSION_1_3 0x00010003
+#define JAWT_VERSION_1_4 0x00010004
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* !_JAVASOFT_JAWT_H_ */
diff --git a/include/jni/jni.h b/include/jni/jni.h
new file mode 100644
index 0000000..aaabe47
--- /dev/null
+++ b/include/jni/jni.h
@@ -0,0 +1,1951 @@
+/*
+ * @(#)jni.h 1.55 03/01/23
+ *
+ * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
+ */
+
+/*
+ * We used part of Netscape's Java Runtime Interface (JRI) as the starting
+ * point of our design and implementation.
+ */
+
+/******************************************************************************
+ * Java Runtime Interface
+ * Copyright (c) 1996 Netscape Communications Corporation. All rights reserved.
+ *****************************************************************************/
+
+#ifndef _JAVASOFT_JNI_H_
+#define _JAVASOFT_JNI_H_
+
+#include <stdio.h>
+#include <stdarg.h>
+
+/* jni_md.h contains the machine-dependent typedefs for jbyte, jint
+ and jlong */
+
+#include "jni_md.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * JNI Types
+ */
+
+#ifndef JNI_TYPES_ALREADY_DEFINED_IN_JNI_MD_H
+
+typedef unsigned char jboolean;
+typedef unsigned short jchar;
+typedef short jshort;
+typedef float jfloat;
+typedef double jdouble;
+
+typedef jint jsize;
+
+#ifdef __cplusplus
+
+class _jobject {};
+class _jclass : public _jobject {};
+class _jthrowable : public _jobject {};
+class _jstring : public _jobject {};
+class _jarray : public _jobject {};
+class _jbooleanArray : public _jarray {};
+class _jbyteArray : public _jarray {};
+class _jcharArray : public _jarray {};
+class _jshortArray : public _jarray {};
+class _jintArray : public _jarray {};
+class _jlongArray : public _jarray {};
+class _jfloatArray : public _jarray {};
+class _jdoubleArray : public _jarray {};
+class _jobjectArray : public _jarray {};
+
+typedef _jobject *jobject;
+typedef _jclass *jclass;
+typedef _jthrowable *jthrowable;
+typedef _jstring *jstring;
+typedef _jarray *jarray;
+typedef _jbooleanArray *jbooleanArray;
+typedef _jbyteArray *jbyteArray;
+typedef _jcharArray *jcharArray;
+typedef _jshortArray *jshortArray;
+typedef _jintArray *jintArray;
+typedef _jlongArray *jlongArray;
+typedef _jfloatArray *jfloatArray;
+typedef _jdoubleArray *jdoubleArray;
+typedef _jobjectArray *jobjectArray;
+
+#else
+
+struct _jobject;
+
+typedef struct _jobject *jobject;
+typedef jobject jclass;
+typedef jobject jthrowable;
+typedef jobject jstring;
+typedef jobject jarray;
+typedef jarray jbooleanArray;
+typedef jarray jbyteArray;
+typedef jarray jcharArray;
+typedef jarray jshortArray;
+typedef jarray jintArray;
+typedef jarray jlongArray;
+typedef jarray jfloatArray;
+typedef jarray jdoubleArray;
+typedef jarray jobjectArray;
+
+#endif
+
+typedef jobject jweak;
+
+typedef union jvalue {
+ jboolean z;
+ jbyte b;
+ jchar c;
+ jshort s;
+ jint i;
+ jlong j;
+ jfloat f;
+ jdouble d;
+ jobject l;
+} jvalue;
+
+struct _jfieldID;
+typedef struct _jfieldID *jfieldID;
+
+struct _jmethodID;
+typedef struct _jmethodID *jmethodID;
+
+#endif /* JNI_TYPES_ALREADY_DEFINED_IN_JNI_MD_H */
+
+/*
+ * jboolean constants
+ */
+
+#define JNI_FALSE 0
+#define JNI_TRUE 1
+
+/*
+ * possible return values for JNI functions.
+ */
+
+#define JNI_OK 0 /* success */
+#define JNI_ERR (-1) /* unknown error */
+#define JNI_EDETACHED (-2) /* thread detached from the VM */
+#define JNI_EVERSION (-3) /* JNI version error */
+#define JNI_ENOMEM (-4) /* not enough memory */
+#define JNI_EEXIST (-5) /* VM already created */
+#define JNI_EINVAL (-6) /* invalid arguments */
+
+/*
+ * used in ReleaseScalarArrayElements
+ */
+
+#define JNI_COMMIT 1
+#define JNI_ABORT 2
+
+/*
+ * used in RegisterNatives to describe native method name, signature,
+ * and function pointer.
+ */
+
+typedef struct {
+ char *name;
+ char *signature;
+ void *fnPtr;
+} JNINativeMethod;
+
+/*
+ * JNI Native Method Interface.
+ */
+
+struct JNINativeInterface_;
+
+struct JNIEnv_;
+
+#ifdef __cplusplus
+typedef JNIEnv_ JNIEnv;
+#else
+typedef const struct JNINativeInterface_ *JNIEnv;
+#endif
+
+/*
+ * JNI Invocation Interface.
+ */
+
+struct JNIInvokeInterface_;
+
+struct JavaVM_;
+
+#ifdef __cplusplus
+typedef JavaVM_ JavaVM;
+#else
+typedef const struct JNIInvokeInterface_ *JavaVM;
+#endif
+
+struct JNINativeInterface_ {
+ void *reserved0;
+ void *reserved1;
+ void *reserved2;
+
+ void *reserved3;
+ jint (JNICALL *GetVersion)(JNIEnv *env);
+
+ jclass (JNICALL *DefineClass)
+ (JNIEnv *env, const char *name, jobject loader, const jbyte *buf,
+ jsize len);
+ jclass (JNICALL *FindClass)
+ (JNIEnv *env, const char *name);
+
+ jmethodID (JNICALL *FromReflectedMethod)
+ (JNIEnv *env, jobject method);
+ jfieldID (JNICALL *FromReflectedField)
+ (JNIEnv *env, jobject field);
+
+ jobject (JNICALL *ToReflectedMethod)
+ (JNIEnv *env, jclass cls, jmethodID methodID, jboolean isStatic);
+
+ jclass (JNICALL *GetSuperclass)
+ (JNIEnv *env, jclass sub);
+ jboolean (JNICALL *IsAssignableFrom)
+ (JNIEnv *env, jclass sub, jclass sup);
+
+ jobject (JNICALL *ToReflectedField)
+ (JNIEnv *env, jclass cls, jfieldID fieldID, jboolean isStatic);
+
+ jint (JNICALL *Throw)
+ (JNIEnv *env, jthrowable obj);
+ jint (JNICALL *ThrowNew)
+ (JNIEnv *env, jclass clazz, const char *msg);
+ jthrowable (JNICALL *ExceptionOccurred)
+ (JNIEnv *env);
+ void (JNICALL *ExceptionDescribe)
+ (JNIEnv *env);
+ void (JNICALL *ExceptionClear)
+ (JNIEnv *env);
+ void (JNICALL *FatalError)
+ (JNIEnv *env, const char *msg);
+
+ jint (JNICALL *PushLocalFrame)
+ (JNIEnv *env, jint capacity);
+ jobject (JNICALL *PopLocalFrame)
+ (JNIEnv *env, jobject result);
+
+ jobject (JNICALL *NewGlobalRef)
+ (JNIEnv *env, jobject lobj);
+ void (JNICALL *DeleteGlobalRef)
+ (JNIEnv *env, jobject gref);
+ void (JNICALL *DeleteLocalRef)
+ (JNIEnv *env, jobject obj);
+ jboolean (JNICALL *IsSameObject)
+ (JNIEnv *env, jobject obj1, jobject obj2);
+ jobject (JNICALL *NewLocalRef)
+ (JNIEnv *env, jobject ref);
+ jint (JNICALL *EnsureLocalCapacity)
+ (JNIEnv *env, jint capacity);
+
+ jobject (JNICALL *AllocObject)
+ (JNIEnv *env, jclass clazz);
+ jobject (JNICALL *NewObject)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+ jobject (JNICALL *NewObjectV)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
+ jobject (JNICALL *NewObjectA)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+
+ jclass (JNICALL *GetObjectClass)
+ (JNIEnv *env, jobject obj);
+ jboolean (JNICALL *IsInstanceOf)
+ (JNIEnv *env, jobject obj, jclass clazz);
+
+ jmethodID (JNICALL *GetMethodID)
+ (JNIEnv *env, jclass clazz, const char *name, const char *sig);
+
+ jobject (JNICALL *CallObjectMethod)
+ (JNIEnv *env, jobject obj, jmethodID methodID, ...);
+ jobject (JNICALL *CallObjectMethodV)
+ (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
+ jobject (JNICALL *CallObjectMethodA)
+ (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue * args);
+
+ jboolean (JNICALL *CallBooleanMethod)
+ (JNIEnv *env, jobject obj, jmethodID methodID, ...);
+ jboolean (JNICALL *CallBooleanMethodV)
+ (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
+ jboolean (JNICALL *CallBooleanMethodA)
+ (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue * args);
+
+ jbyte (JNICALL *CallByteMethod)
+ (JNIEnv *env, jobject obj, jmethodID methodID, ...);
+ jbyte (JNICALL *CallByteMethodV)
+ (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
+ jbyte (JNICALL *CallByteMethodA)
+ (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
+
+ jchar (JNICALL *CallCharMethod)
+ (JNIEnv *env, jobject obj, jmethodID methodID, ...);
+ jchar (JNICALL *CallCharMethodV)
+ (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
+ jchar (JNICALL *CallCharMethodA)
+ (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
+
+ jshort (JNICALL *CallShortMethod)
+ (JNIEnv *env, jobject obj, jmethodID methodID, ...);
+ jshort (JNICALL *CallShortMethodV)
+ (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
+ jshort (JNICALL *CallShortMethodA)
+ (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
+
+ jint (JNICALL *CallIntMethod)
+ (JNIEnv *env, jobject obj, jmethodID methodID, ...);
+ jint (JNICALL *CallIntMethodV)
+ (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
+ jint (JNICALL *CallIntMethodA)
+ (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
+
+ jlong (JNICALL *CallLongMethod)
+ (JNIEnv *env, jobject obj, jmethodID methodID, ...);
+ jlong (JNICALL *CallLongMethodV)
+ (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
+ jlong (JNICALL *CallLongMethodA)
+ (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
+
+ jfloat (JNICALL *CallFloatMethod)
+ (JNIEnv *env, jobject obj, jmethodID methodID, ...);
+ jfloat (JNICALL *CallFloatMethodV)
+ (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
+ jfloat (JNICALL *CallFloatMethodA)
+ (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
+
+ jdouble (JNICALL *CallDoubleMethod)
+ (JNIEnv *env, jobject obj, jmethodID methodID, ...);
+ jdouble (JNICALL *CallDoubleMethodV)
+ (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
+ jdouble (JNICALL *CallDoubleMethodA)
+ (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
+
+ void (JNICALL *CallVoidMethod)
+ (JNIEnv *env, jobject obj, jmethodID methodID, ...);
+ void (JNICALL *CallVoidMethodV)
+ (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
+ void (JNICALL *CallVoidMethodA)
+ (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue * args);
+
+ jobject (JNICALL *CallNonvirtualObjectMethod)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
+ jobject (JNICALL *CallNonvirtualObjectMethodV)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ va_list args);
+ jobject (JNICALL *CallNonvirtualObjectMethodA)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ const jvalue * args);
+
+ jboolean (JNICALL *CallNonvirtualBooleanMethod)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
+ jboolean (JNICALL *CallNonvirtualBooleanMethodV)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ va_list args);
+ jboolean (JNICALL *CallNonvirtualBooleanMethodA)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ const jvalue * args);
+
+ jbyte (JNICALL *CallNonvirtualByteMethod)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
+ jbyte (JNICALL *CallNonvirtualByteMethodV)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ va_list args);
+ jbyte (JNICALL *CallNonvirtualByteMethodA)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ const jvalue *args);
+
+ jchar (JNICALL *CallNonvirtualCharMethod)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
+ jchar (JNICALL *CallNonvirtualCharMethodV)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ va_list args);
+ jchar (JNICALL *CallNonvirtualCharMethodA)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ const jvalue *args);
+
+ jshort (JNICALL *CallNonvirtualShortMethod)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
+ jshort (JNICALL *CallNonvirtualShortMethodV)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ va_list args);
+ jshort (JNICALL *CallNonvirtualShortMethodA)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ const jvalue *args);
+
+ jint (JNICALL *CallNonvirtualIntMethod)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
+ jint (JNICALL *CallNonvirtualIntMethodV)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ va_list args);
+ jint (JNICALL *CallNonvirtualIntMethodA)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ const jvalue *args);
+
+ jlong (JNICALL *CallNonvirtualLongMethod)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
+ jlong (JNICALL *CallNonvirtualLongMethodV)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ va_list args);
+ jlong (JNICALL *CallNonvirtualLongMethodA)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ const jvalue *args);
+
+ jfloat (JNICALL *CallNonvirtualFloatMethod)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
+ jfloat (JNICALL *CallNonvirtualFloatMethodV)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ va_list args);
+ jfloat (JNICALL *CallNonvirtualFloatMethodA)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ const jvalue *args);
+
+ jdouble (JNICALL *CallNonvirtualDoubleMethod)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
+ jdouble (JNICALL *CallNonvirtualDoubleMethodV)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ va_list args);
+ jdouble (JNICALL *CallNonvirtualDoubleMethodA)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ const jvalue *args);
+
+ void (JNICALL *CallNonvirtualVoidMethod)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
+ void (JNICALL *CallNonvirtualVoidMethodV)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ va_list args);
+ void (JNICALL *CallNonvirtualVoidMethodA)
+ (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
+ const jvalue * args);
+
+ jfieldID (JNICALL *GetFieldID)
+ (JNIEnv *env, jclass clazz, const char *name, const char *sig);
+
+ jobject (JNICALL *GetObjectField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID);
+ jboolean (JNICALL *GetBooleanField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID);
+ jbyte (JNICALL *GetByteField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID);
+ jchar (JNICALL *GetCharField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID);
+ jshort (JNICALL *GetShortField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID);
+ jint (JNICALL *GetIntField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID);
+ jlong (JNICALL *GetLongField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID);
+ jfloat (JNICALL *GetFloatField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID);
+ jdouble (JNICALL *GetDoubleField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID);
+
+ void (JNICALL *SetObjectField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID, jobject val);
+ void (JNICALL *SetBooleanField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID, jboolean val);
+ void (JNICALL *SetByteField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID, jbyte val);
+ void (JNICALL *SetCharField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID, jchar val);
+ void (JNICALL *SetShortField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID, jshort val);
+ void (JNICALL *SetIntField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID, jint val);
+ void (JNICALL *SetLongField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID, jlong val);
+ void (JNICALL *SetFloatField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID, jfloat val);
+ void (JNICALL *SetDoubleField)
+ (JNIEnv *env, jobject obj, jfieldID fieldID, jdouble val);
+
+ jmethodID (JNICALL *GetStaticMethodID)
+ (JNIEnv *env, jclass clazz, const char *name, const char *sig);
+
+ jobject (JNICALL *CallStaticObjectMethod)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+ jobject (JNICALL *CallStaticObjectMethodV)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
+ jobject (JNICALL *CallStaticObjectMethodA)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+
+ jboolean (JNICALL *CallStaticBooleanMethod)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+ jboolean (JNICALL *CallStaticBooleanMethodV)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
+ jboolean (JNICALL *CallStaticBooleanMethodA)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+
+ jbyte (JNICALL *CallStaticByteMethod)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+ jbyte (JNICALL *CallStaticByteMethodV)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
+ jbyte (JNICALL *CallStaticByteMethodA)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+
+ jchar (JNICALL *CallStaticCharMethod)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+ jchar (JNICALL *CallStaticCharMethodV)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
+ jchar (JNICALL *CallStaticCharMethodA)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+
+ jshort (JNICALL *CallStaticShortMethod)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+ jshort (JNICALL *CallStaticShortMethodV)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
+ jshort (JNICALL *CallStaticShortMethodA)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+
+ jint (JNICALL *CallStaticIntMethod)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+ jint (JNICALL *CallStaticIntMethodV)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
+ jint (JNICALL *CallStaticIntMethodA)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+
+ jlong (JNICALL *CallStaticLongMethod)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+ jlong (JNICALL *CallStaticLongMethodV)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
+ jlong (JNICALL *CallStaticLongMethodA)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+
+ jfloat (JNICALL *CallStaticFloatMethod)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+ jfloat (JNICALL *CallStaticFloatMethodV)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
+ jfloat (JNICALL *CallStaticFloatMethodA)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+
+ jdouble (JNICALL *CallStaticDoubleMethod)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+ jdouble (JNICALL *CallStaticDoubleMethodV)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
+ jdouble (JNICALL *CallStaticDoubleMethodA)
+ (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+
+ void (JNICALL *CallStaticVoidMethod)
+ (JNIEnv *env, jclass cls, jmethodID methodID, ...);
+ void (JNICALL *CallStaticVoidMethodV)
+ (JNIEnv *env, jclass cls, jmethodID methodID, va_list args);
+ void (JNICALL *CallStaticVoidMethodA)
+ (JNIEnv *env, jclass cls, jmethodID methodID, const jvalue * args);
+
+ jfieldID (JNICALL *GetStaticFieldID)
+ (JNIEnv *env, jclass clazz, const char *name, const char *sig);
+ jobject (JNICALL *GetStaticObjectField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID);
+ jboolean (JNICALL *GetStaticBooleanField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID);
+ jbyte (JNICALL *GetStaticByteField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID);
+ jchar (JNICALL *GetStaticCharField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID);
+ jshort (JNICALL *GetStaticShortField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID);
+ jint (JNICALL *GetStaticIntField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID);
+ jlong (JNICALL *GetStaticLongField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID);
+ jfloat (JNICALL *GetStaticFloatField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID);
+ jdouble (JNICALL *GetStaticDoubleField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID);
+
+ void (JNICALL *SetStaticObjectField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID, jobject value);
+ void (JNICALL *SetStaticBooleanField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID, jboolean value);
+ void (JNICALL *SetStaticByteField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID, jbyte value);
+ void (JNICALL *SetStaticCharField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID, jchar value);
+ void (JNICALL *SetStaticShortField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID, jshort value);
+ void (JNICALL *SetStaticIntField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID, jint value);
+ void (JNICALL *SetStaticLongField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID, jlong value);
+ void (JNICALL *SetStaticFloatField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID, jfloat value);
+ void (JNICALL *SetStaticDoubleField)
+ (JNIEnv *env, jclass clazz, jfieldID fieldID, jdouble value);
+
+ jstring (JNICALL *NewString)
+ (JNIEnv *env, const jchar *unicode, jsize len);
+ jsize (JNICALL *GetStringLength)
+ (JNIEnv *env, jstring str);
+ const jchar *(JNICALL *GetStringChars)
+ (JNIEnv *env, jstring str, jboolean *isCopy);
+ void (JNICALL *ReleaseStringChars)
+ (JNIEnv *env, jstring str, const jchar *chars);
+
+ jstring (JNICALL *NewStringUTF)
+ (JNIEnv *env, const char *utf);
+ jsize (JNICALL *GetStringUTFLength)
+ (JNIEnv *env, jstring str);
+ const char* (JNICALL *GetStringUTFChars)
+ (JNIEnv *env, jstring str, jboolean *isCopy);
+ void (JNICALL *ReleaseStringUTFChars)
+ (JNIEnv *env, jstring str, const char* chars);
+
+
+ jsize (JNICALL *GetArrayLength)
+ (JNIEnv *env, jarray array);
+
+ jobjectArray (JNICALL *NewObjectArray)
+ (JNIEnv *env, jsize len, jclass clazz, jobject init);
+ jobject (JNICALL *GetObjectArrayElement)
+ (JNIEnv *env, jobjectArray array, jsize index);
+ void (JNICALL *SetObjectArrayElement)
+ (JNIEnv *env, jobjectArray array, jsize index, jobject val);
+
+ jbooleanArray (JNICALL *NewBooleanArray)
+ (JNIEnv *env, jsize len);
+ jbyteArray (JNICALL *NewByteArray)
+ (JNIEnv *env, jsize len);
+ jcharArray (JNICALL *NewCharArray)
+ (JNIEnv *env, jsize len);
+ jshortArray (JNICALL *NewShortArray)
+ (JNIEnv *env, jsize len);
+ jintArray (JNICALL *NewIntArray)
+ (JNIEnv *env, jsize len);
+ jlongArray (JNICALL *NewLongArray)
+ (JNIEnv *env, jsize len);
+ jfloatArray (JNICALL *NewFloatArray)
+ (JNIEnv *env, jsize len);
+ jdoubleArray (JNICALL *NewDoubleArray)
+ (JNIEnv *env, jsize len);
+
+ jboolean * (JNICALL *GetBooleanArrayElements)
+ (JNIEnv *env, jbooleanArray array, jboolean *isCopy);
+ jbyte * (JNICALL *GetByteArrayElements)
+ (JNIEnv *env, jbyteArray array, jboolean *isCopy);
+ jchar * (JNICALL *GetCharArrayElements)
+ (JNIEnv *env, jcharArray array, jboolean *isCopy);
+ jshort * (JNICALL *GetShortArrayElements)
+ (JNIEnv *env, jshortArray array, jboolean *isCopy);
+ jint * (JNICALL *GetIntArrayElements)
+ (JNIEnv *env, jintArray array, jboolean *isCopy);
+ jlong * (JNICALL *GetLongArrayElements)
+ (JNIEnv *env, jlongArray array, jboolean *isCopy);
+ jfloat * (JNICALL *GetFloatArrayElements)
+ (JNIEnv *env, jfloatArray array, jboolean *isCopy);
+ jdouble * (JNICALL *GetDoubleArrayElements)
+ (JNIEnv *env, jdoubleArray array, jboolean *isCopy);
+
+ void (JNICALL *ReleaseBooleanArrayElements)
+ (JNIEnv *env, jbooleanArray array, jboolean *elems, jint mode);
+ void (JNICALL *ReleaseByteArrayElements)
+ (JNIEnv *env, jbyteArray array, jbyte *elems, jint mode);
+ void (JNICALL *ReleaseCharArrayElements)
+ (JNIEnv *env, jcharArray array, jchar *elems, jint mode);
+ void (JNICALL *ReleaseShortArrayElements)
+ (JNIEnv *env, jshortArray array, jshort *elems, jint mode);
+ void (JNICALL *ReleaseIntArrayElements)
+ (JNIEnv *env, jintArray array, jint *elems, jint mode);
+ void (JNICALL *ReleaseLongArrayElements)
+ (JNIEnv *env, jlongArray array, jlong *elems, jint mode);
+ void (JNICALL *ReleaseFloatArrayElements)
+ (JNIEnv *env, jfloatArray array, jfloat *elems, jint mode);
+ void (JNICALL *ReleaseDoubleArrayElements)
+ (JNIEnv *env, jdoubleArray array, jdouble *elems, jint mode);
+
+ void (JNICALL *GetBooleanArrayRegion)
+ (JNIEnv *env, jbooleanArray array, jsize start, jsize l, jboolean *buf);
+ void (JNICALL *GetByteArrayRegion)
+ (JNIEnv *env, jbyteArray array, jsize start, jsize len, jbyte *buf);
+ void (JNICALL *GetCharArrayRegion)
+ (JNIEnv *env, jcharArray array, jsize start, jsize len, jchar *buf);
+ void (JNICALL *GetShortArrayRegion)
+ (JNIEnv *env, jshortArray array, jsize start, jsize len, jshort *buf);
+ void (JNICALL *GetIntArrayRegion)
+ (JNIEnv *env, jintArray array, jsize start, jsize len, jint *buf);
+ void (JNICALL *GetLongArrayRegion)
+ (JNIEnv *env, jlongArray array, jsize start, jsize len, jlong *buf);
+ void (JNICALL *GetFloatArrayRegion)
+ (JNIEnv *env, jfloatArray array, jsize start, jsize len, jfloat *buf);
+ void (JNICALL *GetDoubleArrayRegion)
+ (JNIEnv *env, jdoubleArray array, jsize start, jsize len, jdouble *buf);
+
+ void (JNICALL *SetBooleanArrayRegion)
+ (JNIEnv *env, jbooleanArray array, jsize start, jsize l, const jboolean *buf);
+ void (JNICALL *SetByteArrayRegion)
+ (JNIEnv *env, jbyteArray array, jsize start, jsize len, const jbyte *buf);
+ void (JNICALL *SetCharArrayRegion)
+ (JNIEnv *env, jcharArray array, jsize start, jsize len, const jchar *buf);
+ void (JNICALL *SetShortArrayRegion)
+ (JNIEnv *env, jshortArray array, jsize start, jsize len, const jshort *buf);
+ void (JNICALL *SetIntArrayRegion)
+ (JNIEnv *env, jintArray array, jsize start, jsize len, const jint *buf);
+ void (JNICALL *SetLongArrayRegion)
+ (JNIEnv *env, jlongArray array, jsize start, jsize len, const jlong *buf);
+ void (JNICALL *SetFloatArrayRegion)
+ (JNIEnv *env, jfloatArray array, jsize start, jsize len, const jfloat *buf);
+ void (JNICALL *SetDoubleArrayRegion)
+ (JNIEnv *env, jdoubleArray array, jsize start, jsize len, const jdouble *buf);
+
+ jint (JNICALL *RegisterNatives)
+ (JNIEnv *env, jclass clazz, const JNINativeMethod *methods,
+ jint nMethods);
+ jint (JNICALL *UnregisterNatives)
+ (JNIEnv *env, jclass clazz);
+
+ jint (JNICALL *MonitorEnter)
+ (JNIEnv *env, jobject obj);
+ jint (JNICALL *MonitorExit)
+ (JNIEnv *env, jobject obj);
+
+ jint (JNICALL *GetJavaVM)
+ (JNIEnv *env, JavaVM **vm);
+
+ void (JNICALL *GetStringRegion)
+ (JNIEnv *env, jstring str, jsize start, jsize len, jchar *buf);
+ void (JNICALL *GetStringUTFRegion)
+ (JNIEnv *env, jstring str, jsize start, jsize len, char *buf);
+
+ void * (JNICALL *GetPrimitiveArrayCritical)
+ (JNIEnv *env, jarray array, jboolean *isCopy);
+ void (JNICALL *ReleasePrimitiveArrayCritical)
+ (JNIEnv *env, jarray array, void *carray, jint mode);
+
+ const jchar * (JNICALL *GetStringCritical)
+ (JNIEnv *env, jstring string, jboolean *isCopy);
+ void (JNICALL *ReleaseStringCritical)
+ (JNIEnv *env, jstring string, const jchar *cstring);
+
+ jweak (JNICALL *NewWeakGlobalRef)
+ (JNIEnv *env, jobject obj);
+ void (JNICALL *DeleteWeakGlobalRef)
+ (JNIEnv *env, jweak ref);
+
+ jboolean (JNICALL *ExceptionCheck)
+ (JNIEnv *env);
+
+ jobject (JNICALL *NewDirectByteBuffer)
+ (JNIEnv* env, void* address, jlong capacity);
+ void* (JNICALL *GetDirectBufferAddress)
+ (JNIEnv* env, jobject buf);
+ jlong (JNICALL *GetDirectBufferCapacity)
+ (JNIEnv* env, jobject buf);
+};
+
+/*
+ * We use inlined functions for C++ so that programmers can write:
+ *
+ * env->FindClass("java/lang/String")
+ *
+ * in C++ rather than:
+ *
+ * (*env)->FindClass(env, "java/lang/String")
+ *
+ * in C.
+ */
+
+struct JNIEnv_ {
+ const struct JNINativeInterface_ *functions;
+#ifdef __cplusplus
+
+ jint GetVersion() {
+ return functions->GetVersion(this);
+ }
+ jclass DefineClass(const char *name, jobject loader, const jbyte *buf,
+ jsize len) {
+ return functions->DefineClass(this, name, loader, buf, len);
+ }
+ jclass FindClass(const char *name) {
+ return functions->FindClass(this, name);
+ }
+ jmethodID FromReflectedMethod(jobject method) {
+ return functions->FromReflectedMethod(this,method);
+ }
+ jfieldID FromReflectedField(jobject field) {
+ return functions->FromReflectedField(this,field);
+ }
+
+ jobject ToReflectedMethod(jclass cls, jmethodID methodID, jboolean isStatic) {
+ return functions->ToReflectedMethod(this, cls, methodID, isStatic);
+ }
+
+ jclass GetSuperclass(jclass sub) {
+ return functions->GetSuperclass(this, sub);
+ }
+ jboolean IsAssignableFrom(jclass sub, jclass sup) {
+ return functions->IsAssignableFrom(this, sub, sup);
+ }
+
+ jobject ToReflectedField(jclass cls, jfieldID fieldID, jboolean isStatic) {
+ return functions->ToReflectedField(this,cls,fieldID,isStatic);
+ }
+
+ jint Throw(jthrowable obj) {
+ return functions->Throw(this, obj);
+ }
+ jint ThrowNew(jclass clazz, const char *msg) {
+ return functions->ThrowNew(this, clazz, msg);
+ }
+ jthrowable ExceptionOccurred() {
+ return functions->ExceptionOccurred(this);
+ }
+ void ExceptionDescribe() {
+ functions->ExceptionDescribe(this);
+ }
+ void ExceptionClear() {
+ functions->ExceptionClear(this);
+ }
+ void FatalError(const char *msg) {
+ functions->FatalError(this, msg);
+ }
+
+ jint PushLocalFrame(jint capacity) {
+ return functions->PushLocalFrame(this,capacity);
+ }
+ jobject PopLocalFrame(jobject result) {
+ return functions->PopLocalFrame(this,result);
+ }
+
+ jobject NewGlobalRef(jobject lobj) {
+ return functions->NewGlobalRef(this,lobj);
+ }
+ void DeleteGlobalRef(jobject gref) {
+ functions->DeleteGlobalRef(this,gref);
+ }
+ void DeleteLocalRef(jobject obj) {
+ functions->DeleteLocalRef(this, obj);
+ }
+
+ jboolean IsSameObject(jobject obj1, jobject obj2) {
+ return functions->IsSameObject(this,obj1,obj2);
+ }
+
+ jobject NewLocalRef(jobject ref) {
+ return functions->NewLocalRef(this,ref);
+ }
+ jint EnsureLocalCapacity(jint capacity) {
+ return functions->EnsureLocalCapacity(this,capacity);
+ }
+
+ jobject AllocObject(jclass clazz) {
+ return functions->AllocObject(this,clazz);
+ }
+ jobject NewObject(jclass clazz, jmethodID methodID, ...) {
+ va_list args;
+ jobject result;
+ va_start(args, methodID);
+ result = functions->NewObjectV(this,clazz,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jobject NewObjectV(jclass clazz, jmethodID methodID,
+ va_list args) {
+ return functions->NewObjectV(this,clazz,methodID,args);
+ }
+ jobject NewObjectA(jclass clazz, jmethodID methodID,
+ const jvalue *args) {
+ return functions->NewObjectA(this,clazz,methodID,args);
+ }
+
+ jclass GetObjectClass(jobject obj) {
+ return functions->GetObjectClass(this,obj);
+ }
+ jboolean IsInstanceOf(jobject obj, jclass clazz) {
+ return functions->IsInstanceOf(this,obj,clazz);
+ }
+
+ jmethodID GetMethodID(jclass clazz, const char *name,
+ const char *sig) {
+ return functions->GetMethodID(this,clazz,name,sig);
+ }
+
+ jobject CallObjectMethod(jobject obj, jmethodID methodID, ...) {
+ va_list args;
+ jobject result;
+ va_start(args,methodID);
+ result = functions->CallObjectMethodV(this,obj,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jobject CallObjectMethodV(jobject obj, jmethodID methodID,
+ va_list args) {
+ return functions->CallObjectMethodV(this,obj,methodID,args);
+ }
+ jobject CallObjectMethodA(jobject obj, jmethodID methodID,
+ const jvalue * args) {
+ return functions->CallObjectMethodA(this,obj,methodID,args);
+ }
+
+ jboolean CallBooleanMethod(jobject obj,
+ jmethodID methodID, ...) {
+ va_list args;
+ jboolean result;
+ va_start(args,methodID);
+ result = functions->CallBooleanMethodV(this,obj,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jboolean CallBooleanMethodV(jobject obj, jmethodID methodID,
+ va_list args) {
+ return functions->CallBooleanMethodV(this,obj,methodID,args);
+ }
+ jboolean CallBooleanMethodA(jobject obj, jmethodID methodID,
+ const jvalue * args) {
+ return functions->CallBooleanMethodA(this,obj,methodID, args);
+ }
+
+ jbyte CallByteMethod(jobject obj, jmethodID methodID, ...) {
+ va_list args;
+ jbyte result;
+ va_start(args,methodID);
+ result = functions->CallByteMethodV(this,obj,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jbyte CallByteMethodV(jobject obj, jmethodID methodID,
+ va_list args) {
+ return functions->CallByteMethodV(this,obj,methodID,args);
+ }
+ jbyte CallByteMethodA(jobject obj, jmethodID methodID,
+ const jvalue * args) {
+ return functions->CallByteMethodA(this,obj,methodID,args);
+ }
+
+ jchar CallCharMethod(jobject obj, jmethodID methodID, ...) {
+ va_list args;
+ jchar result;
+ va_start(args,methodID);
+ result = functions->CallCharMethodV(this,obj,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jchar CallCharMethodV(jobject obj, jmethodID methodID,
+ va_list args) {
+ return functions->CallCharMethodV(this,obj,methodID,args);
+ }
+ jchar CallCharMethodA(jobject obj, jmethodID methodID,
+ const jvalue * args) {
+ return functions->CallCharMethodA(this,obj,methodID,args);
+ }
+
+ jshort CallShortMethod(jobject obj, jmethodID methodID, ...) {
+ va_list args;
+ jshort result;
+ va_start(args,methodID);
+ result = functions->CallShortMethodV(this,obj,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jshort CallShortMethodV(jobject obj, jmethodID methodID,
+ va_list args) {
+ return functions->CallShortMethodV(this,obj,methodID,args);
+ }
+ jshort CallShortMethodA(jobject obj, jmethodID methodID,
+ const jvalue * args) {
+ return functions->CallShortMethodA(this,obj,methodID,args);
+ }
+
+ jint CallIntMethod(jobject obj, jmethodID methodID, ...) {
+ va_list args;
+ jint result;
+ va_start(args,methodID);
+ result = functions->CallIntMethodV(this,obj,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jint CallIntMethodV(jobject obj, jmethodID methodID,
+ va_list args) {
+ return functions->CallIntMethodV(this,obj,methodID,args);
+ }
+ jint CallIntMethodA(jobject obj, jmethodID methodID,
+ const jvalue * args) {
+ return functions->CallIntMethodA(this,obj,methodID,args);
+ }
+
+ jlong CallLongMethod(jobject obj, jmethodID methodID, ...) {
+ va_list args;
+ jlong result;
+ va_start(args,methodID);
+ result = functions->CallLongMethodV(this,obj,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jlong CallLongMethodV(jobject obj, jmethodID methodID,
+ va_list args) {
+ return functions->CallLongMethodV(this,obj,methodID,args);
+ }
+ jlong CallLongMethodA(jobject obj, jmethodID methodID,
+ const jvalue * args) {
+ return functions->CallLongMethodA(this,obj,methodID,args);
+ }
+
+ jfloat CallFloatMethod(jobject obj, jmethodID methodID, ...) {
+ va_list args;
+ jfloat result;
+ va_start(args,methodID);
+ result = functions->CallFloatMethodV(this,obj,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jfloat CallFloatMethodV(jobject obj, jmethodID methodID,
+ va_list args) {
+ return functions->CallFloatMethodV(this,obj,methodID,args);
+ }
+ jfloat CallFloatMethodA(jobject obj, jmethodID methodID,
+ const jvalue * args) {
+ return functions->CallFloatMethodA(this,obj,methodID,args);
+ }
+
+ jdouble CallDoubleMethod(jobject obj, jmethodID methodID, ...) {
+ va_list args;
+ jdouble result;
+ va_start(args,methodID);
+ result = functions->CallDoubleMethodV(this,obj,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jdouble CallDoubleMethodV(jobject obj, jmethodID methodID,
+ va_list args) {
+ return functions->CallDoubleMethodV(this,obj,methodID,args);
+ }
+ jdouble CallDoubleMethodA(jobject obj, jmethodID methodID,
+ const jvalue * args) {
+ return functions->CallDoubleMethodA(this,obj,methodID,args);
+ }
+
+ void CallVoidMethod(jobject obj, jmethodID methodID, ...) {
+ va_list args;
+ va_start(args,methodID);
+ functions->CallVoidMethodV(this,obj,methodID,args);
+ va_end(args);
+ }
+ void CallVoidMethodV(jobject obj, jmethodID methodID,
+ va_list args) {
+ functions->CallVoidMethodV(this,obj,methodID,args);
+ }
+ void CallVoidMethodA(jobject obj, jmethodID methodID,
+ const jvalue * args) {
+ functions->CallVoidMethodA(this,obj,methodID,args);
+ }
+
+ jobject CallNonvirtualObjectMethod(jobject obj, jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jobject result;
+ va_start(args,methodID);
+ result = functions->CallNonvirtualObjectMethodV(this,obj,clazz,
+ methodID,args);
+ va_end(args);
+ return result;
+ }
+ jobject CallNonvirtualObjectMethodV(jobject obj, jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallNonvirtualObjectMethodV(this,obj,clazz,
+ methodID,args);
+ }
+ jobject CallNonvirtualObjectMethodA(jobject obj, jclass clazz,
+ jmethodID methodID, const jvalue * args) {
+ return functions->CallNonvirtualObjectMethodA(this,obj,clazz,
+ methodID,args);
+ }
+
+ jboolean CallNonvirtualBooleanMethod(jobject obj, jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jboolean result;
+ va_start(args,methodID);
+ result = functions->CallNonvirtualBooleanMethodV(this,obj,clazz,
+ methodID,args);
+ va_end(args);
+ return result;
+ }
+ jboolean CallNonvirtualBooleanMethodV(jobject obj, jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallNonvirtualBooleanMethodV(this,obj,clazz,
+ methodID,args);
+ }
+ jboolean CallNonvirtualBooleanMethodA(jobject obj, jclass clazz,
+ jmethodID methodID, const jvalue * args) {
+ return functions->CallNonvirtualBooleanMethodA(this,obj,clazz,
+ methodID, args);
+ }
+
+ jbyte CallNonvirtualByteMethod(jobject obj, jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jbyte result;
+ va_start(args,methodID);
+ result = functions->CallNonvirtualByteMethodV(this,obj,clazz,
+ methodID,args);
+ va_end(args);
+ return result;
+ }
+ jbyte CallNonvirtualByteMethodV(jobject obj, jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallNonvirtualByteMethodV(this,obj,clazz,
+ methodID,args);
+ }
+ jbyte CallNonvirtualByteMethodA(jobject obj, jclass clazz,
+ jmethodID methodID, const jvalue * args) {
+ return functions->CallNonvirtualByteMethodA(this,obj,clazz,
+ methodID,args);
+ }
+
+ jchar CallNonvirtualCharMethod(jobject obj, jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jchar result;
+ va_start(args,methodID);
+ result = functions->CallNonvirtualCharMethodV(this,obj,clazz,
+ methodID,args);
+ va_end(args);
+ return result;
+ }
+ jchar CallNonvirtualCharMethodV(jobject obj, jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallNonvirtualCharMethodV(this,obj,clazz,
+ methodID,args);
+ }
+ jchar CallNonvirtualCharMethodA(jobject obj, jclass clazz,
+ jmethodID methodID, const jvalue * args) {
+ return functions->CallNonvirtualCharMethodA(this,obj,clazz,
+ methodID,args);
+ }
+
+ jshort CallNonvirtualShortMethod(jobject obj, jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jshort result;
+ va_start(args,methodID);
+ result = functions->CallNonvirtualShortMethodV(this,obj,clazz,
+ methodID,args);
+ va_end(args);
+ return result;
+ }
+ jshort CallNonvirtualShortMethodV(jobject obj, jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallNonvirtualShortMethodV(this,obj,clazz,
+ methodID,args);
+ }
+ jshort CallNonvirtualShortMethodA(jobject obj, jclass clazz,
+ jmethodID methodID, const jvalue * args) {
+ return functions->CallNonvirtualShortMethodA(this,obj,clazz,
+ methodID,args);
+ }
+
+ jint CallNonvirtualIntMethod(jobject obj, jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jint result;
+ va_start(args,methodID);
+ result = functions->CallNonvirtualIntMethodV(this,obj,clazz,
+ methodID,args);
+ va_end(args);
+ return result;
+ }
+ jint CallNonvirtualIntMethodV(jobject obj, jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallNonvirtualIntMethodV(this,obj,clazz,
+ methodID,args);
+ }
+ jint CallNonvirtualIntMethodA(jobject obj, jclass clazz,
+ jmethodID methodID, const jvalue * args) {
+ return functions->CallNonvirtualIntMethodA(this,obj,clazz,
+ methodID,args);
+ }
+
+ jlong CallNonvirtualLongMethod(jobject obj, jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jlong result;
+ va_start(args,methodID);
+ result = functions->CallNonvirtualLongMethodV(this,obj,clazz,
+ methodID,args);
+ va_end(args);
+ return result;
+ }
+ jlong CallNonvirtualLongMethodV(jobject obj, jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallNonvirtualLongMethodV(this,obj,clazz,
+ methodID,args);
+ }
+ jlong CallNonvirtualLongMethodA(jobject obj, jclass clazz,
+ jmethodID methodID, const jvalue * args) {
+ return functions->CallNonvirtualLongMethodA(this,obj,clazz,
+ methodID,args);
+ }
+
+ jfloat CallNonvirtualFloatMethod(jobject obj, jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jfloat result;
+ va_start(args,methodID);
+ result = functions->CallNonvirtualFloatMethodV(this,obj,clazz,
+ methodID,args);
+ va_end(args);
+ return result;
+ }
+ jfloat CallNonvirtualFloatMethodV(jobject obj, jclass clazz,
+ jmethodID methodID,
+ va_list args) {
+ return functions->CallNonvirtualFloatMethodV(this,obj,clazz,
+ methodID,args);
+ }
+ jfloat CallNonvirtualFloatMethodA(jobject obj, jclass clazz,
+ jmethodID methodID,
+ const jvalue * args) {
+ return functions->CallNonvirtualFloatMethodA(this,obj,clazz,
+ methodID,args);
+ }
+
+ jdouble CallNonvirtualDoubleMethod(jobject obj, jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jdouble result;
+ va_start(args,methodID);
+ result = functions->CallNonvirtualDoubleMethodV(this,obj,clazz,
+ methodID,args);
+ va_end(args);
+ return result;
+ }
+ jdouble CallNonvirtualDoubleMethodV(jobject obj, jclass clazz,
+ jmethodID methodID,
+ va_list args) {
+ return functions->CallNonvirtualDoubleMethodV(this,obj,clazz,
+ methodID,args);
+ }
+ jdouble CallNonvirtualDoubleMethodA(jobject obj, jclass clazz,
+ jmethodID methodID,
+ const jvalue * args) {
+ return functions->CallNonvirtualDoubleMethodA(this,obj,clazz,
+ methodID,args);
+ }
+
+ void CallNonvirtualVoidMethod(jobject obj, jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ va_start(args,methodID);
+ functions->CallNonvirtualVoidMethodV(this,obj,clazz,methodID,args);
+ va_end(args);
+ }
+ void CallNonvirtualVoidMethodV(jobject obj, jclass clazz,
+ jmethodID methodID,
+ va_list args) {
+ functions->CallNonvirtualVoidMethodV(this,obj,clazz,methodID,args);
+ }
+ void CallNonvirtualVoidMethodA(jobject obj, jclass clazz,
+ jmethodID methodID,
+ const jvalue * args) {
+ functions->CallNonvirtualVoidMethodA(this,obj,clazz,methodID,args);
+ }
+
+ jfieldID GetFieldID(jclass clazz, const char *name,
+ const char *sig) {
+ return functions->GetFieldID(this,clazz,name,sig);
+ }
+
+ jobject GetObjectField(jobject obj, jfieldID fieldID) {
+ return functions->GetObjectField(this,obj,fieldID);
+ }
+ jboolean GetBooleanField(jobject obj, jfieldID fieldID) {
+ return functions->GetBooleanField(this,obj,fieldID);
+ }
+ jbyte GetByteField(jobject obj, jfieldID fieldID) {
+ return functions->GetByteField(this,obj,fieldID);
+ }
+ jchar GetCharField(jobject obj, jfieldID fieldID) {
+ return functions->GetCharField(this,obj,fieldID);
+ }
+ jshort GetShortField(jobject obj, jfieldID fieldID) {
+ return functions->GetShortField(this,obj,fieldID);
+ }
+ jint GetIntField(jobject obj, jfieldID fieldID) {
+ return functions->GetIntField(this,obj,fieldID);
+ }
+ jlong GetLongField(jobject obj, jfieldID fieldID) {
+ return functions->GetLongField(this,obj,fieldID);
+ }
+ jfloat GetFloatField(jobject obj, jfieldID fieldID) {
+ return functions->GetFloatField(this,obj,fieldID);
+ }
+ jdouble GetDoubleField(jobject obj, jfieldID fieldID) {
+ return functions->GetDoubleField(this,obj,fieldID);
+ }
+
+ void SetObjectField(jobject obj, jfieldID fieldID, jobject val) {
+ functions->SetObjectField(this,obj,fieldID,val);
+ }
+ void SetBooleanField(jobject obj, jfieldID fieldID,
+ jboolean val) {
+ functions->SetBooleanField(this,obj,fieldID,val);
+ }
+ void SetByteField(jobject obj, jfieldID fieldID,
+ jbyte val) {
+ functions->SetByteField(this,obj,fieldID,val);
+ }
+ void SetCharField(jobject obj, jfieldID fieldID,
+ jchar val) {
+ functions->SetCharField(this,obj,fieldID,val);
+ }
+ void SetShortField(jobject obj, jfieldID fieldID,
+ jshort val) {
+ functions->SetShortField(this,obj,fieldID,val);
+ }
+ void SetIntField(jobject obj, jfieldID fieldID,
+ jint val) {
+ functions->SetIntField(this,obj,fieldID,val);
+ }
+ void SetLongField(jobject obj, jfieldID fieldID,
+ jlong val) {
+ functions->SetLongField(this,obj,fieldID,val);
+ }
+ void SetFloatField(jobject obj, jfieldID fieldID,
+ jfloat val) {
+ functions->SetFloatField(this,obj,fieldID,val);
+ }
+ void SetDoubleField(jobject obj, jfieldID fieldID,
+ jdouble val) {
+ functions->SetDoubleField(this,obj,fieldID,val);
+ }
+
+ jmethodID GetStaticMethodID(jclass clazz, const char *name,
+ const char *sig) {
+ return functions->GetStaticMethodID(this,clazz,name,sig);
+ }
+
+ jobject CallStaticObjectMethod(jclass clazz, jmethodID methodID,
+ ...) {
+ va_list args;
+ jobject result;
+ va_start(args,methodID);
+ result = functions->CallStaticObjectMethodV(this,clazz,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jobject CallStaticObjectMethodV(jclass clazz, jmethodID methodID,
+ va_list args) {
+ return functions->CallStaticObjectMethodV(this,clazz,methodID,args);
+ }
+ jobject CallStaticObjectMethodA(jclass clazz, jmethodID methodID,
+ const jvalue *args) {
+ return functions->CallStaticObjectMethodA(this,clazz,methodID,args);
+ }
+
+ jboolean CallStaticBooleanMethod(jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jboolean result;
+ va_start(args,methodID);
+ result = functions->CallStaticBooleanMethodV(this,clazz,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jboolean CallStaticBooleanMethodV(jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallStaticBooleanMethodV(this,clazz,methodID,args);
+ }
+ jboolean CallStaticBooleanMethodA(jclass clazz,
+ jmethodID methodID, const jvalue *args) {
+ return functions->CallStaticBooleanMethodA(this,clazz,methodID,args);
+ }
+
+ jbyte CallStaticByteMethod(jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jbyte result;
+ va_start(args,methodID);
+ result = functions->CallStaticByteMethodV(this,clazz,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jbyte CallStaticByteMethodV(jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallStaticByteMethodV(this,clazz,methodID,args);
+ }
+ jbyte CallStaticByteMethodA(jclass clazz,
+ jmethodID methodID, const jvalue *args) {
+ return functions->CallStaticByteMethodA(this,clazz,methodID,args);
+ }
+
+ jchar CallStaticCharMethod(jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jchar result;
+ va_start(args,methodID);
+ result = functions->CallStaticCharMethodV(this,clazz,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jchar CallStaticCharMethodV(jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallStaticCharMethodV(this,clazz,methodID,args);
+ }
+ jchar CallStaticCharMethodA(jclass clazz,
+ jmethodID methodID, const jvalue *args) {
+ return functions->CallStaticCharMethodA(this,clazz,methodID,args);
+ }
+
+ jshort CallStaticShortMethod(jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jshort result;
+ va_start(args,methodID);
+ result = functions->CallStaticShortMethodV(this,clazz,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jshort CallStaticShortMethodV(jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallStaticShortMethodV(this,clazz,methodID,args);
+ }
+ jshort CallStaticShortMethodA(jclass clazz,
+ jmethodID methodID, const jvalue *args) {
+ return functions->CallStaticShortMethodA(this,clazz,methodID,args);
+ }
+
+ jint CallStaticIntMethod(jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jint result;
+ va_start(args,methodID);
+ result = functions->CallStaticIntMethodV(this,clazz,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jint CallStaticIntMethodV(jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallStaticIntMethodV(this,clazz,methodID,args);
+ }
+ jint CallStaticIntMethodA(jclass clazz,
+ jmethodID methodID, const jvalue *args) {
+ return functions->CallStaticIntMethodA(this,clazz,methodID,args);
+ }
+
+ jlong CallStaticLongMethod(jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jlong result;
+ va_start(args,methodID);
+ result = functions->CallStaticLongMethodV(this,clazz,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jlong CallStaticLongMethodV(jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallStaticLongMethodV(this,clazz,methodID,args);
+ }
+ jlong CallStaticLongMethodA(jclass clazz,
+ jmethodID methodID, const jvalue *args) {
+ return functions->CallStaticLongMethodA(this,clazz,methodID,args);
+ }
+
+ jfloat CallStaticFloatMethod(jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jfloat result;
+ va_start(args,methodID);
+ result = functions->CallStaticFloatMethodV(this,clazz,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jfloat CallStaticFloatMethodV(jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallStaticFloatMethodV(this,clazz,methodID,args);
+ }
+ jfloat CallStaticFloatMethodA(jclass clazz,
+ jmethodID methodID, const jvalue *args) {
+ return functions->CallStaticFloatMethodA(this,clazz,methodID,args);
+ }
+
+ jdouble CallStaticDoubleMethod(jclass clazz,
+ jmethodID methodID, ...) {
+ va_list args;
+ jdouble result;
+ va_start(args,methodID);
+ result = functions->CallStaticDoubleMethodV(this,clazz,methodID,args);
+ va_end(args);
+ return result;
+ }
+ jdouble CallStaticDoubleMethodV(jclass clazz,
+ jmethodID methodID, va_list args) {
+ return functions->CallStaticDoubleMethodV(this,clazz,methodID,args);
+ }
+ jdouble CallStaticDoubleMethodA(jclass clazz,
+ jmethodID methodID, const jvalue *args) {
+ return functions->CallStaticDoubleMethodA(this,clazz,methodID,args);
+ }
+
+ void CallStaticVoidMethod(jclass cls, jmethodID methodID, ...) {
+ va_list args;
+ va_start(args,methodID);
+ functions->CallStaticVoidMethodV(this,cls,methodID,args);
+ va_end(args);
+ }
+ void CallStaticVoidMethodV(jclass cls, jmethodID methodID,
+ va_list args) {
+ functions->CallStaticVoidMethodV(this,cls,methodID,args);
+ }
+ void CallStaticVoidMethodA(jclass cls, jmethodID methodID,
+ const jvalue * args) {
+ functions->CallStaticVoidMethodA(this,cls,methodID,args);
+ }
+
+ jfieldID GetStaticFieldID(jclass clazz, const char *name,
+ const char *sig) {
+ return functions->GetStaticFieldID(this,clazz,name,sig);
+ }
+ jobject GetStaticObjectField(jclass clazz, jfieldID fieldID) {
+ return functions->GetStaticObjectField(this,clazz,fieldID);
+ }
+ jboolean GetStaticBooleanField(jclass clazz, jfieldID fieldID) {
+ return functions->GetStaticBooleanField(this,clazz,fieldID);
+ }
+ jbyte GetStaticByteField(jclass clazz, jfieldID fieldID) {
+ return functions->GetStaticByteField(this,clazz,fieldID);
+ }
+ jchar GetStaticCharField(jclass clazz, jfieldID fieldID) {
+ return functions->GetStaticCharField(this,clazz,fieldID);
+ }
+ jshort GetStaticShortField(jclass clazz, jfieldID fieldID) {
+ return functions->GetStaticShortField(this,clazz,fieldID);
+ }
+ jint GetStaticIntField(jclass clazz, jfieldID fieldID) {
+ return functions->GetStaticIntField(this,clazz,fieldID);
+ }
+ jlong GetStaticLongField(jclass clazz, jfieldID fieldID) {
+ return functions->GetStaticLongField(this,clazz,fieldID);
+ }
+ jfloat GetStaticFloatField(jclass clazz, jfieldID fieldID) {
+ return functions->GetStaticFloatField(this,clazz,fieldID);
+ }
+ jdouble GetStaticDoubleField(jclass clazz, jfieldID fieldID) {
+ return functions->GetStaticDoubleField(this,clazz,fieldID);
+ }
+
+ void SetStaticObjectField(jclass clazz, jfieldID fieldID,
+ jobject value) {
+ functions->SetStaticObjectField(this,clazz,fieldID,value);
+ }
+ void SetStaticBooleanField(jclass clazz, jfieldID fieldID,
+ jboolean value) {
+ functions->SetStaticBooleanField(this,clazz,fieldID,value);
+ }
+ void SetStaticByteField(jclass clazz, jfieldID fieldID,
+ jbyte value) {
+ functions->SetStaticByteField(this,clazz,fieldID,value);
+ }
+ void SetStaticCharField(jclass clazz, jfieldID fieldID,
+ jchar value) {
+ functions->SetStaticCharField(this,clazz,fieldID,value);
+ }
+ void SetStaticShortField(jclass clazz, jfieldID fieldID,
+ jshort value) {
+ functions->SetStaticShortField(this,clazz,fieldID,value);
+ }
+ void SetStaticIntField(jclass clazz, jfieldID fieldID,
+ jint value) {
+ functions->SetStaticIntField(this,clazz,fieldID,value);
+ }
+ void SetStaticLongField(jclass clazz, jfieldID fieldID,
+ jlong value) {
+ functions->SetStaticLongField(this,clazz,fieldID,value);
+ }
+ void SetStaticFloatField(jclass clazz, jfieldID fieldID,
+ jfloat value) {
+ functions->SetStaticFloatField(this,clazz,fieldID,value);
+ }
+ void SetStaticDoubleField(jclass clazz, jfieldID fieldID,
+ jdouble value) {
+ functions->SetStaticDoubleField(this,clazz,fieldID,value);
+ }
+
+ jstring NewString(const jchar *unicode, jsize len) {
+ return functions->NewString(this,unicode,len);
+ }
+ jsize GetStringLength(jstring str) {
+ return functions->GetStringLength(this,str);
+ }
+ const jchar *GetStringChars(jstring str, jboolean *isCopy) {
+ return functions->GetStringChars(this,str,isCopy);
+ }
+ void ReleaseStringChars(jstring str, const jchar *chars) {
+ functions->ReleaseStringChars(this,str,chars);
+ }
+
+ jstring NewStringUTF(const char *utf) {
+ return functions->NewStringUTF(this,utf);
+ }
+ jsize GetStringUTFLength(jstring str) {
+ return functions->GetStringUTFLength(this,str);
+ }
+ const char* GetStringUTFChars(jstring str, jboolean *isCopy) {
+ return functions->GetStringUTFChars(this,str,isCopy);
+ }
+ void ReleaseStringUTFChars(jstring str, const char* chars) {
+ functions->ReleaseStringUTFChars(this,str,chars);
+ }
+
+ jsize GetArrayLength(jarray array) {
+ return functions->GetArrayLength(this,array);
+ }
+
+ jobjectArray NewObjectArray(jsize len, jclass clazz,
+ jobject init) {
+ return functions->NewObjectArray(this,len,clazz,init);
+ }
+ jobject GetObjectArrayElement(jobjectArray array, jsize index) {
+ return functions->GetObjectArrayElement(this,array,index);
+ }
+ void SetObjectArrayElement(jobjectArray array, jsize index,
+ jobject val) {
+ functions->SetObjectArrayElement(this,array,index,val);
+ }
+
+ jbooleanArray NewBooleanArray(jsize len) {
+ return functions->NewBooleanArray(this,len);
+ }
+ jbyteArray NewByteArray(jsize len) {
+ return functions->NewByteArray(this,len);
+ }
+ jcharArray NewCharArray(jsize len) {
+ return functions->NewCharArray(this,len);
+ }
+ jshortArray NewShortArray(jsize len) {
+ return functions->NewShortArray(this,len);
+ }
+ jintArray NewIntArray(jsize len) {
+ return functions->NewIntArray(this,len);
+ }
+ jlongArray NewLongArray(jsize len) {
+ return functions->NewLongArray(this,len);
+ }
+ jfloatArray NewFloatArray(jsize len) {
+ return functions->NewFloatArray(this,len);
+ }
+ jdoubleArray NewDoubleArray(jsize len) {
+ return functions->NewDoubleArray(this,len);
+ }
+
+ jboolean * GetBooleanArrayElements(jbooleanArray array, jboolean *isCopy) {
+ return functions->GetBooleanArrayElements(this,array,isCopy);
+ }
+ jbyte * GetByteArrayElements(jbyteArray array, jboolean *isCopy) {
+ return functions->GetByteArrayElements(this,array,isCopy);
+ }
+ jchar * GetCharArrayElements(jcharArray array, jboolean *isCopy) {
+ return functions->GetCharArrayElements(this,array,isCopy);
+ }
+ jshort * GetShortArrayElements(jshortArray array, jboolean *isCopy) {
+ return functions->GetShortArrayElements(this,array,isCopy);
+ }
+ jint * GetIntArrayElements(jintArray array, jboolean *isCopy) {
+ return functions->GetIntArrayElements(this,array,isCopy);
+ }
+ jlong * GetLongArrayElements(jlongArray array, jboolean *isCopy) {
+ return functions->GetLongArrayElements(this,array,isCopy);
+ }
+ jfloat * GetFloatArrayElements(jfloatArray array, jboolean *isCopy) {
+ return functions->GetFloatArrayElements(this,array,isCopy);
+ }
+ jdouble * GetDoubleArrayElements(jdoubleArray array, jboolean *isCopy) {
+ return functions->GetDoubleArrayElements(this,array,isCopy);
+ }
+
+ void ReleaseBooleanArrayElements(jbooleanArray array,
+ jboolean *elems,
+ jint mode) {
+ functions->ReleaseBooleanArrayElements(this,array,elems,mode);
+ }
+ void ReleaseByteArrayElements(jbyteArray array,
+ jbyte *elems,
+ jint mode) {
+ functions->ReleaseByteArrayElements(this,array,elems,mode);
+ }
+ void ReleaseCharArrayElements(jcharArray array,
+ jchar *elems,
+ jint mode) {
+ functions->ReleaseCharArrayElements(this,array,elems,mode);
+ }
+ void ReleaseShortArrayElements(jshortArray array,
+ jshort *elems,
+ jint mode) {
+ functions->ReleaseShortArrayElements(this,array,elems,mode);
+ }
+ void ReleaseIntArrayElements(jintArray array,
+ jint *elems,
+ jint mode) {
+ functions->ReleaseIntArrayElements(this,array,elems,mode);
+ }
+ void ReleaseLongArrayElements(jlongArray array,
+ jlong *elems,
+ jint mode) {
+ functions->ReleaseLongArrayElements(this,array,elems,mode);
+ }
+ void ReleaseFloatArrayElements(jfloatArray array,
+ jfloat *elems,
+ jint mode) {
+ functions->ReleaseFloatArrayElements(this,array,elems,mode);
+ }
+ void ReleaseDoubleArrayElements(jdoubleArray array,
+ jdouble *elems,
+ jint mode) {
+ functions->ReleaseDoubleArrayElements(this,array,elems,mode);
+ }
+
+ void GetBooleanArrayRegion(jbooleanArray array,
+ jsize start, jsize len, jboolean *buf) {
+ functions->GetBooleanArrayRegion(this,array,start,len,buf);
+ }
+ void GetByteArrayRegion(jbyteArray array,
+ jsize start, jsize len, jbyte *buf) {
+ functions->GetByteArrayRegion(this,array,start,len,buf);
+ }
+ void GetCharArrayRegion(jcharArray array,
+ jsize start, jsize len, jchar *buf) {
+ functions->GetCharArrayRegion(this,array,start,len,buf);
+ }
+ void GetShortArrayRegion(jshortArray array,
+ jsize start, jsize len, jshort *buf) {
+ functions->GetShortArrayRegion(this,array,start,len,buf);
+ }
+ void GetIntArrayRegion(jintArray array,
+ jsize start, jsize len, jint *buf) {
+ functions->GetIntArrayRegion(this,array,start,len,buf);
+ }
+ void GetLongArrayRegion(jlongArray array,
+ jsize start, jsize len, jlong *buf) {
+ functions->GetLongArrayRegion(this,array,start,len,buf);
+ }
+ void GetFloatArrayRegion(jfloatArray array,
+ jsize start, jsize len, jfloat *buf) {
+ functions->GetFloatArrayRegion(this,array,start,len,buf);
+ }
+ void GetDoubleArrayRegion(jdoubleArray array,
+ jsize start, jsize len, jdouble *buf) {
+ functions->GetDoubleArrayRegion(this,array,start,len,buf);
+ }
+
+ void SetBooleanArrayRegion(jbooleanArray array, jsize start, jsize len,
+ const jboolean *buf) {
+ functions->SetBooleanArrayRegion(this,array,start,len,buf);
+ }
+ void SetByteArrayRegion(jbyteArray array, jsize start, jsize len,
+ const jbyte *buf) {
+ functions->SetByteArrayRegion(this,array,start,len,buf);
+ }
+ void SetCharArrayRegion(jcharArray array, jsize start, jsize len,
+ const jchar *buf) {
+ functions->SetCharArrayRegion(this,array,start,len,buf);
+ }
+ void SetShortArrayRegion(jshortArray array, jsize start, jsize len,
+ const jshort *buf) {
+ functions->SetShortArrayRegion(this,array,start,len,buf);
+ }
+ void SetIntArrayRegion(jintArray array, jsize start, jsize len,
+ const jint *buf) {
+ functions->SetIntArrayRegion(this,array,start,len,buf);
+ }
+ void SetLongArrayRegion(jlongArray array, jsize start, jsize len,
+ const jlong *buf) {
+ functions->SetLongArrayRegion(this,array,start,len,buf);
+ }
+ void SetFloatArrayRegion(jfloatArray array, jsize start, jsize len,
+ const jfloat *buf) {
+ functions->SetFloatArrayRegion(this,array,start,len,buf);
+ }
+ void SetDoubleArrayRegion(jdoubleArray array, jsize start, jsize len,
+ const jdouble *buf) {
+ functions->SetDoubleArrayRegion(this,array,start,len,buf);
+ }
+
+ jint RegisterNatives(jclass clazz, const JNINativeMethod *methods,
+ jint nMethods) {
+ return functions->RegisterNatives(this,clazz,methods,nMethods);
+ }
+ jint UnregisterNatives(jclass clazz) {
+ return functions->UnregisterNatives(this,clazz);
+ }
+
+ jint MonitorEnter(jobject obj) {
+ return functions->MonitorEnter(this,obj);
+ }
+ jint MonitorExit(jobject obj) {
+ return functions->MonitorExit(this,obj);
+ }
+
+ jint GetJavaVM(JavaVM **vm) {
+ return functions->GetJavaVM(this,vm);
+ }
+
+ void GetStringRegion(jstring str, jsize start, jsize len, jchar *buf) {
+ functions->GetStringRegion(this,str,start,len,buf);
+ }
+ void GetStringUTFRegion(jstring str, jsize start, jsize len, char *buf) {
+ functions->GetStringUTFRegion(this,str,start,len,buf);
+ }
+
+ void * GetPrimitiveArrayCritical(jarray array, jboolean *isCopy) {
+ return functions->GetPrimitiveArrayCritical(this,array,isCopy);
+ }
+ void ReleasePrimitiveArrayCritical(jarray array, void *carray, jint mode) {
+ functions->ReleasePrimitiveArrayCritical(this,array,carray,mode);
+ }
+
+ const jchar * GetStringCritical(jstring string, jboolean *isCopy) {
+ return functions->GetStringCritical(this,string,isCopy);
+ }
+ void ReleaseStringCritical(jstring string, const jchar *cstring) {
+ functions->ReleaseStringCritical(this,string,cstring);
+ }
+
+ jweak NewWeakGlobalRef(jobject obj) {
+ return functions->NewWeakGlobalRef(this,obj);
+ }
+ void DeleteWeakGlobalRef(jweak ref) {
+ functions->DeleteWeakGlobalRef(this,ref);
+ }
+
+ jboolean ExceptionCheck() {
+ return functions->ExceptionCheck(this);
+ }
+
+ jobject NewDirectByteBuffer(void* address, jlong capacity) {
+ return functions->NewDirectByteBuffer(this, address, capacity);
+ }
+ void* GetDirectBufferAddress(jobject buf) {
+ return functions->GetDirectBufferAddress(this, buf);
+ }
+ jlong GetDirectBufferCapacity(jobject buf) {
+ return functions->GetDirectBufferCapacity(this, buf);
+ }
+
+#endif /* __cplusplus */
+};
+
+typedef struct JavaVMOption {
+ char *optionString;
+ void *extraInfo;
+} JavaVMOption;
+
+typedef struct JavaVMInitArgs {
+ jint version;
+
+ jint nOptions;
+ JavaVMOption *options;
+ jboolean ignoreUnrecognized;
+} JavaVMInitArgs;
+
+typedef struct JavaVMAttachArgs {
+ jint version;
+
+ char *name;
+ jobject group;
+} JavaVMAttachArgs;
+
+/* These structures will be VM-specific. */
+
+typedef struct JDK1_1InitArgs {
+ jint version;
+
+ char **properties;
+ jint checkSource;
+ jint nativeStackSize;
+ jint javaStackSize;
+ jint minHeapSize;
+ jint maxHeapSize;
+ jint verifyMode;
+ char *classpath;
+
+ jint (JNICALL *vfprintf)(FILE *fp, const char *format, va_list args);
+ void (JNICALL *exit)(jint code);
+ void (JNICALL *abort)(void);
+
+ jint enableClassGC;
+ jint enableVerboseGC;
+ jint disableAsyncGC;
+ jint verbose;
+ jboolean debugging;
+ jint debugPort;
+} JDK1_1InitArgs;
+
+typedef struct JDK1_1AttachArgs {
+ void * __padding; /* C compilers don't allow empty structures. */
+} JDK1_1AttachArgs;
+
+#define JDK1_2
+#define JDK1_4
+
+/* End VM-specific. */
+
+struct JNIInvokeInterface_ {
+ void *reserved0;
+ void *reserved1;
+ void *reserved2;
+
+ jint (JNICALL *DestroyJavaVM)(JavaVM *vm);
+
+ jint (JNICALL *AttachCurrentThread)(JavaVM *vm, void **penv, void *args);
+
+ jint (JNICALL *DetachCurrentThread)(JavaVM *vm);
+
+ jint (JNICALL *GetEnv)(JavaVM *vm, void **penv, jint version);
+
+ jint (JNICALL *AttachCurrentThreadAsDaemon)(JavaVM *vm, void **penv, void *args);
+};
+
+struct JavaVM_ {
+ const struct JNIInvokeInterface_ *functions;
+#ifdef __cplusplus
+
+ jint DestroyJavaVM() {
+ return functions->DestroyJavaVM(this);
+ }
+ jint AttachCurrentThread(void **penv, void *args) {
+ return functions->AttachCurrentThread(this, penv, args);
+ }
+ jint DetachCurrentThread() {
+ return functions->DetachCurrentThread(this);
+ }
+
+ jint GetEnv(void **penv, jint version) {
+ return functions->GetEnv(this, penv, version);
+ }
+ jint AttachCurrentThreadAsDaemon(void **penv, void *args) {
+ return functions->AttachCurrentThreadAsDaemon(this, penv, args);
+ }
+#endif
+};
+
+#ifdef _JNI_IMPLEMENTATION_
+#define _JNI_IMPORT_OR_EXPORT_ JNIEXPORT
+#else
+#define _JNI_IMPORT_OR_EXPORT_ JNIIMPORT
+#endif
+_JNI_IMPORT_OR_EXPORT_ jint JNICALL
+JNI_GetDefaultJavaVMInitArgs(void *args);
+
+_JNI_IMPORT_OR_EXPORT_ jint JNICALL
+JNI_CreateJavaVM(JavaVM **pvm, void **penv, void *args);
+
+_JNI_IMPORT_OR_EXPORT_ jint JNICALL
+JNI_GetCreatedJavaVMs(JavaVM **, jsize, jsize *);
+
+/* Defined by native libraries. */
+JNIEXPORT jint JNICALL
+JNI_OnLoad(JavaVM *vm, void *reserved);
+
+JNIEXPORT void JNICALL
+JNI_OnUnload(JavaVM *vm, void *reserved);
+
+#define JNI_VERSION_1_1 0x00010001
+#define JNI_VERSION_1_2 0x00010002
+#define JNI_VERSION_1_4 0x00010004
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif /* __cplusplus */
+
+#endif /* !_JAVASOFT_JNI_H_ */
diff --git a/include/jni/jvmdi.h b/include/jni/jvmdi.h
new file mode 100644
index 0000000..7ad82b1
--- /dev/null
+++ b/include/jni/jvmdi.h
@@ -0,0 +1,1012 @@
+/*
+ * @(#)jvmdi.h 1.47 03/01/23
+ *
+ * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
+ */
+
+/*
+ * Java Virtual Machine Debug Interface
+ *
+ * Defines debugging functionality that a VM should provide.
+ *
+ * Should not overlap functionality in jni.h
+ */
+
+#ifndef _JAVASOFT_JVMDI_H_
+#define _JAVASOFT_JVMDI_H_
+
+#include "jni.h"
+
+#define JVMDI_VERSION_1 0x20010000
+#define JVMDI_VERSION_1_1 0x20010001
+#define JVMDI_VERSION_1_2 0x20010002
+#define JVMDI_VERSION_1_3 0x20010003
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef jobject jthread;
+
+typedef jobject jthreadGroup;
+
+struct _jframeID;
+typedef struct _jframeID *jframeID;
+
+ /* specifies program location "pc" - often byte code index */
+typedef jlong jlocation;
+
+ /* The jmethodID for methods that have been replaced */
+ /* via RedefineClasses - used when the implementation */
+ /* does not wish to retain replaced jmethodIDs */
+#define OBSOLETE_METHOD_ID ((jmethodID)(NULL))
+
+ /*
+ * Errors
+ */
+
+typedef jint jvmdiError;
+
+ /* no error */
+#define JVMDI_ERROR_NONE ((jvmdiError)0)
+
+ /*
+ * Errors on thread operations
+ */
+
+ /* invalid thread */
+#define JVMDI_ERROR_INVALID_THREAD ((jvmdiError)10)
+ /* invalid thread group */
+#define JVMDI_ERROR_INVALID_THREAD_GROUP ((jvmdiError)11)
+ /* invalid thread priority */
+#define JVMDI_ERROR_INVALID_PRIORITY ((jvmdiError)12)
+ /* thread not suspended */
+#define JVMDI_ERROR_THREAD_NOT_SUSPENDED ((jvmdiError)13)
+ /* thread already suspended */
+#define JVMDI_ERROR_THREAD_SUSPENDED ((jvmdiError)14)
+
+ /*
+ * Errors on object and class operations
+ */
+
+ /* invalid object (implementation not required to gracefully catch) */
+#define JVMDI_ERROR_INVALID_OBJECT ((jvmdiError)20)
+ /* invalid class (implementation not required to gracefully catch) */
+#define JVMDI_ERROR_INVALID_CLASS ((jvmdiError)21)
+ /* class not prepared */
+#define JVMDI_ERROR_CLASS_NOT_PREPARED ((jvmdiError)22)
+ /* invalid methodID (implementation not required to gracefully catch) */
+#define JVMDI_ERROR_INVALID_METHODID ((jvmdiError)23)
+ /* invalid location */
+#define JVMDI_ERROR_INVALID_LOCATION ((jvmdiError)24)
+ /* invalid fieldID (implementation not required to gracefully catch) */
+#define JVMDI_ERROR_INVALID_FIELDID ((jvmdiError)25)
+
+ /*
+ * Errors on frame operations
+ */
+
+ /* invalid frameID (implementation not required to gracefully catch) */
+#define JVMDI_ERROR_INVALID_FRAMEID ((jvmdiError)30)
+ /* there are no more frames on the stack */
+#define JVMDI_ERROR_NO_MORE_FRAMES ((jvmdiError)31)
+ /* operation cannot be performed on this frame */
+#define JVMDI_ERROR_OPAQUE_FRAME ((jvmdiError)32)
+ /* operation can only be performed on current frame */
+#define JVMDI_ERROR_NOT_CURRENT_FRAME ((jvmdiError)33)
+ /* type mismatch (implementation not required to gracefully catch) */
+#define JVMDI_ERROR_TYPE_MISMATCH ((jvmdiError)34)
+ /* invalid slot */
+#define JVMDI_ERROR_INVALID_SLOT ((jvmdiError)35)
+
+ /*
+ * Errors on set/clear/find operations
+ */
+
+ /* item already present */
+#define JVMDI_ERROR_DUPLICATE ((jvmdiError)40)
+ /* item not found */
+#define JVMDI_ERROR_NOT_FOUND ((jvmdiError)41)
+
+ /*
+ * Errors on monitor operations
+ */
+
+ /* invalid monitor */
+#define JVMDI_ERROR_INVALID_MONITOR ((jvmdiError)50)
+ /* wait, notify, notify all tried without entering monitor */
+#define JVMDI_ERROR_NOT_MONITOR_OWNER ((jvmdiError)51)
+ /* waiting thread interrupted */
+#define JVMDI_ERROR_INTERRUPT ((jvmdiError)52)
+
+ /*
+ * Class redefinition / operand stack errors
+ */
+
+ /* The equivalent of ClassFormatError */
+#define JVMDI_ERROR_INVALID_CLASS_FORMAT ((jvmdiError)60)
+ /* The equivalent of ClassCircularityError */
+#define JVMDI_ERROR_CIRCULAR_CLASS_DEFINITION ((jvmdiError)61)
+ /* The class bytes fail verification */
+#define JVMDI_ERROR_FAILS_VERIFICATION ((jvmdiError)62)
+ /* The new class version adds new methods */
+ /* and can_add_method is false */
+#define JVMDI_ERROR_ADD_METHOD_NOT_IMPLEMENTED ((jvmdiError)63)
+ /* The new class version changes fields */
+ /* and can_unrestrictedly_redefine_classes is false */
+#define JVMDI_ERROR_SCHEMA_CHANGE_NOT_IMPLEMENTED ((jvmdiError)64)
+ /* bci/operand stack/local var combination is not verifiably */
+ /* type safe */
+#define JVMDI_ERROR_INVALID_TYPESTATE ((jvmdiError)65)
+ /* A direct superclass is different for the new class */
+ /* version, or the set of directly implemented */
+ /* interfaces is different */
+ /* and can_unrestrictedly_redefine_classes is false */
+#define JVMDI_ERROR_HIERARCHY_CHANGE_NOT_IMPLEMENTED ((jvmdiError)66)
+ /* The new class version does not declare a method */
+ /* declared in the old class version */
+ /* and can_unrestrictedly_redefine_classes is false */
+#define JVMDI_ERROR_DELETE_METHOD_NOT_IMPLEMENTED ((jvmdiError)67)
+ /* A class file has a version number not supported */
+ /* by this VM. */
+#define JVMDI_ERROR_UNSUPPORTED_VERSION ((jvmdiError)68)
+ /* The class name defined in the new class file is */
+ /* different from the name in the old class object */
+#define JVMDI_ERROR_NAMES_DONT_MATCH ((jvmdiError)69)
+ /* The new class version has different modifiers and */
+ /* can_unrestrictedly_redefine_classes is false */
+#define JVMDI_ERROR_CLASS_MODIFIERS_CHANGE_NOT_IMPLEMENTED ((jvmdiError)70)
+ /* A method in the new class version has different modifiers */
+ /* than its counterpart in the old class version */
+ /* and can_unrestrictedly_redefine_classes is false */
+#define JVMDI_ERROR_METHOD_MODIFIERS_CHANGE_NOT_IMPLEMENTED ((jvmdiError)71)
+
+ /*
+ * Miscellaneous errors
+ */
+
+ /* Not yet implemented */
+#define JVMDI_ERROR_NOT_IMPLEMENTED ((jvmdiError)99)
+ /* null pointer */
+#define JVMDI_ERROR_NULL_POINTER ((jvmdiError)100)
+ /* information is absent */
+#define JVMDI_ERROR_ABSENT_INFORMATION ((jvmdiError)101)
+ /* invalid event type */
+#define JVMDI_ERROR_INVALID_EVENT_TYPE ((jvmdiError)102)
+ /* invalid argument */
+#define JVMDI_ERROR_ILLEGAL_ARGUMENT ((jvmdiError)103)
+
+ /*
+ * Universal errors. These errors may be returned by
+ * any JVMDI function, not just the ones for which they are listed
+ * below.
+ */
+
+ /* no more memory available for allocation */
+#define JVMDI_ERROR_OUT_OF_MEMORY ((jvmdiError)110)
+ /* debugging has not been enabled in this VM */
+#define JVMDI_ERROR_ACCESS_DENIED ((jvmdiError)111)
+ /* VM is dead (implementation not required to gracefully catch) */
+#define JVMDI_ERROR_VM_DEAD ((jvmdiError)112)
+ /* internal error */
+#define JVMDI_ERROR_INTERNAL ((jvmdiError)113)
+ /* Thread calling JVMDI function not attached to VM */
+#define JVMDI_ERROR_UNATTACHED_THREAD ((jvmdiError)115)
+
+
+ /*
+ * Threads
+ */
+
+ /* Thread status is unknown */
+#define JVMDI_THREAD_STATUS_UNKNOWN ((jint)-1)
+ /* Thread is waiting to die */
+#define JVMDI_THREAD_STATUS_ZOMBIE ((jint)0)
+ /* Thread is runnable */
+#define JVMDI_THREAD_STATUS_RUNNING ((jint)1)
+ /* Thread is sleeping - Thread.sleep() or JVM_Sleep() was called */
+#define JVMDI_THREAD_STATUS_SLEEPING ((jint)2)
+ /* Thread is waiting on a java monitor */
+#define JVMDI_THREAD_STATUS_MONITOR ((jint)3)
+ /* Thread is waiting - Thread.wait() or JVM_MonitorWait() was called */
+#define JVMDI_THREAD_STATUS_WAIT ((jint)4)
+
+ /* Thread is suspended - Thread.suspend(), JVM_Suspend() or
+ * JVMDI_Suspend was called */
+#define JVMDI_SUSPEND_STATUS_SUSPENDED ((jint)0x1)
+ /* Thread is at a breakpoint */
+#define JVMDI_SUSPEND_STATUS_BREAK ((jint)0x2)
+
+
+ /* Thread priority constants */
+#define JVMDI_THREAD_MIN_PRIORITY ((jint)1)
+#define JVMDI_THREAD_NORM_PRIORITY ((jint)5)
+#define JVMDI_THREAD_MAX_PRIORITY ((jint)10)
+
+typedef struct {
+ char *name;
+ jint priority;
+ jboolean is_daemon;
+ jthreadGroup thread_group;
+ jobject context_class_loader;
+} JVMDI_thread_info;
+
+typedef struct {
+ jthreadGroup parent;
+ char *name;
+ jint max_priority;
+ jboolean is_daemon;
+} JVMDI_thread_group_info;
+
+#define JVMDI_DISABLE ((jint) 0)
+#define JVMDI_ENABLE ((jint) 1)
+
+/*
+ * Initial function for debug threads created through JVMDI
+ */
+typedef void (*JVMDI_StartFunction)(void *);
+
+/*
+ * Type for debug monitors created through JVMDI
+ */
+typedef void *JVMDI_RawMonitor;
+
+#define JVMDI_MONITOR_WAIT_FOREVER ((jlong)(-1))
+
+/*
+ * Monitor information
+ */
+typedef struct {
+ jthread owner;
+ jint entry_count;
+ jint waiter_count;
+ jthread *waiters;
+} JVMDI_monitor_info;
+
+typedef struct {
+ jint owned_monitor_count;
+ jobject *owned_monitors;
+} JVMDI_owned_monitor_info;
+
+ /*
+ * Events
+ */
+
+ /* kind = JVMDI_EVENT_SINGLE_STEP */
+ typedef struct {
+ jthread thread;
+ jclass clazz;
+ jmethodID method;
+ jlocation location;
+ } JVMDI_single_step_event_data;
+
+ /* kind = JVMDI_EVENT_BREAKPOINT */
+ typedef struct {
+ jthread thread;
+ jclass clazz;
+ jmethodID method;
+ jlocation location;
+ } JVMDI_breakpoint_event_data;
+
+ /* kind = JVMDI_EVENT_FIELD_ACCESS */
+ typedef struct {
+ jthread thread;
+ jclass clazz;
+ jmethodID method;
+ jlocation location;
+ jclass field_clazz;
+ jobject object;
+ jfieldID field;
+ } JVMDI_field_access_event_data;
+
+ /* kind = JVMDI_EVENT_FIELD_MODIFICATION */
+ typedef struct {
+ jthread thread;
+ jclass clazz;
+ jmethodID method;
+ jlocation location;
+ jclass field_clazz;
+ jobject object;
+ jfieldID field;
+ char signature_type;
+ jvalue new_value;
+ } JVMDI_field_modification_event_data;
+
+ /* kind = JVMDI_EVENT_FRAME_POP */
+ /* kind = JVMDI_EVENT_METHOD_ENTRY */
+ /* kind = JVMDI_EVENT_METHOD_EXIT */
+ typedef struct {
+ jthread thread;
+ jclass clazz;
+ jmethodID method;
+ jframeID frame;
+ } JVMDI_frame_event_data;
+
+ /* kind = JVMDI_EVENT_EXCEPTION */
+ typedef struct {
+ jthread thread;
+ jclass clazz;
+ jmethodID method;
+ jlocation location;
+ jobject exception;
+ jclass catch_clazz;
+ jmethodID catch_method;
+ jlocation catch_location;
+ } JVMDI_exception_event_data;
+
+ /* kind = JVMDI_EVENT_EXCEPTION_CATCH */
+ typedef struct {
+ jthread thread;
+ jclass clazz;
+ jmethodID method;
+ jlocation location;
+ jobject exception;
+ } JVMDI_exception_catch_event_data;
+
+ /* kind = JVMDI_EVENT_USER_DEFINED */
+ typedef struct {
+ jobject object;
+ jint key;
+ } JVMDI_user_event_data;
+
+ /* kind = JVMDI_EVENT_THREAD_END or */
+ /* JVMDI_EVENT_THREAD_START */
+ typedef struct {
+ jthread thread;
+ } JVMDI_thread_change_event_data;
+
+ /* kind = JVMDI_EVENT_CLASS_LOAD, */
+ /* JVMDI_EVENT_CLASS_UNLOAD, or */
+ /* JVMDI_EVENT_CLASS_PREPARE */
+ typedef struct {
+ jthread thread;
+ jclass clazz;
+ } JVMDI_class_event_data;
+
+/* This stucture passes information about the event.
+ * location is the index of the last instruction executed.
+ */
+typedef struct {
+ jint kind; /* the discriminant */
+
+ union {
+ /* kind = JVMDI_EVENT_SINGLE_STEP */
+ JVMDI_single_step_event_data single_step;
+
+ /* kind = JVMDI_EVENT_BREAKPOINT */
+ JVMDI_breakpoint_event_data breakpoint;
+
+ /* kind = JVMDI_EVENT_FRAME_POP */
+ /* kind = JVMDI_EVENT_METHOD_ENTRY */
+ /* kind = JVMDI_EVENT_METHOD_EXIT */
+ JVMDI_frame_event_data frame;
+
+ /* kind = JVMDI_EVENT_FIELD_ACCESS */
+ JVMDI_field_access_event_data field_access;
+
+ /* kind = JVMDI_EVENT_FIELD_MODIFICATION */
+ JVMDI_field_modification_event_data field_modification;
+
+ /* kind = JVMDI_EVENT_EXCEPTION */
+ JVMDI_exception_event_data exception;
+
+ /* kind = JVMDI_EVENT_EXCEPTION_CATCH */
+ JVMDI_exception_catch_event_data exception_catch;
+
+ /* kind = JVMDI_EVENT_USER_DEFINED */
+ JVMDI_user_event_data user;
+
+ /* kind = JVMDI_EVENT_THREAD_END or */
+ /* JVMDI_EVENT_THREAD_START */
+ JVMDI_thread_change_event_data thread_change;
+
+ /* kind = JVMDI_EVENT_CLASS_LOAD, */
+ /* JVMDI_EVENT_CLASS_UNLOAD, or */
+ /* JVMDI_EVENT_CLASS_PREPARE */
+ JVMDI_class_event_data class_event;
+
+ /* kind = JVMDI_EVENT_VM_DEATH, JVMDI_EVENT_VM_INIT */
+ /* no additional fields */
+ } u;
+} JVMDI_Event;
+
+ /*** event kinds ***/
+#define JVMDI_EVENT_SINGLE_STEP ((jint)1)
+#define JVMDI_EVENT_BREAKPOINT ((jint)2)
+#define JVMDI_EVENT_FRAME_POP ((jint)3)
+#define JVMDI_EVENT_EXCEPTION ((jint)4)
+#define JVMDI_EVENT_USER_DEFINED ((jint)5)
+#define JVMDI_EVENT_THREAD_START ((jint)6)
+#define JVMDI_EVENT_THREAD_END ((jint)7)
+#define JVMDI_EVENT_CLASS_PREPARE ((jint)8)
+#define JVMDI_EVENT_CLASS_UNLOAD ((jint)9)
+#define JVMDI_EVENT_CLASS_LOAD ((jint)10)
+#define JVMDI_EVENT_FIELD_ACCESS ((jint)20)
+#define JVMDI_EVENT_FIELD_MODIFICATION ((jint)21)
+#define JVMDI_EVENT_EXCEPTION_CATCH ((jint)30)
+#define JVMDI_EVENT_METHOD_ENTRY ((jint)40)
+#define JVMDI_EVENT_METHOD_EXIT ((jint)41)
+#define JVMDI_EVENT_VM_INIT ((jint)90)
+#define JVMDI_EVENT_VM_DEATH ((jint)99)
+
+#define JVMDI_MAX_EVENT_TYPE_VAL ((jint)99)
+
+
+
+/* event handler hook */
+typedef void (*JVMDI_EventHook)(JNIEnv *env, JVMDI_Event *event);
+
+typedef jvmdiError (*JVMDI_AllocHook) (jlong size, jbyte** memPtr);
+typedef jvmdiError (*JVMDI_DeallocHook) (jbyte* buffer);
+
+/*
+ * Class states used in JVMDI_GetClassStatus
+ */
+#define JVMDI_CLASS_STATUS_VERIFIED ((jint)0x01)
+#define JVMDI_CLASS_STATUS_PREPARED ((jint)0x02)
+#define JVMDI_CLASS_STATUS_INITIALIZED ((jint)0x04)
+ /* Error prevents initialization */
+#define JVMDI_CLASS_STATUS_ERROR ((jint)0x08)
+
+/* structure for returning line number information
+ */
+typedef struct {
+ jlocation start_location;
+ jint line_number;
+} JVMDI_line_number_entry;
+
+
+/* structure for returning local variable information
+ */
+typedef struct {
+ jlocation start_location; /* variable valid start_location */
+ jint length; /* upto start_location+length */
+ char *name; /* name in UTF8 */
+ char *signature; /* type signature in UTF8 */
+ jint slot; /* variable slot, see JVMDI_GetLocal*() */
+} JVMDI_local_variable_entry;
+
+/* structure for returning exception handler information
+ */
+typedef struct {
+ jlocation start_location;
+ jlocation end_location;
+ jlocation handler_location;
+ jclass exception; /* if null, all exceptions */
+} JVMDI_exception_handler_entry;
+
+#define JVMDI_OPERAND_TYPE_REFERENCE ((jint)1)
+#define JVMDI_OPERAND_TYPE_INT ((jint)2)
+#define JVMDI_OPERAND_TYPE_FLOAT ((jint)3)
+#define JVMDI_OPERAND_TYPE_LONG0 ((jint)4) /* least sig. 32 bits */
+#define JVMDI_OPERAND_TYPE_LONG1 ((jint)5) /* most sig. 32 bits */
+#define JVMDI_OPERAND_TYPE_DOUBLE0 ((jint)6) /* least sig. 32 bits */
+#define JVMDI_OPERAND_TYPE_DOUBLE1 ((jint)7) /* most sig. 32 bits */
+#define JVMDI_OPERAND_TYPE_RETURN_ADDRESS ((jint)8)
+
+typedef struct {
+ jint word; /* 32 bit operand stack quantities */
+ jint type; /* type encoding of the operand word */
+ /* one of JVMDI_OPERAND_TYPE_* */
+} JVMDI_operand_stack_element;
+
+typedef struct {
+ jint instance_field_count; /* number of instance fields referencing obj */
+ struct JVMDI_instance_field {
+ jobject instance; /* instance referencing obj */
+ jfieldID field; /* field holding reference */
+ } *instance_fields; /* instanceField_count of them */
+
+ jint static_field_count; /* number of static fields referencing obj */
+ struct JVMDI_static_field {
+ jclass clazz; /* class referencing obj */
+ jfieldID static_field; /* field holding reference */
+ } *static_fields; /* static_field_count of them */
+
+ jint array_element_count; /* number of array elements referencing obj */
+ struct JVMDI_array_element {
+ jobjectArray array; /* array referencing obj */
+ jint index; /* index holding reference */
+ } *array_elements; /* array_element_count of them */
+
+ jint frame_slot_count; /* number of frame slots referencing obj */
+ struct JVMDI_frame_slot {
+ jthread thread; /* thread of the frame */
+ jframeID frame; /* frame referencing obj */
+ jint slot; /* slot holding reference */
+ } *frame_slots; /* frame_slot_count of them */
+} JVMDI_object_reference_info;
+
+/* structure for defining a class
+*/
+typedef struct {
+ jclass clazz; /* Class object for this class */
+ jint class_byte_count; /* number of bytes defining class (below) */
+ jbyte *class_bytes; /* bytes defining class (in JVM spec */
+ /* Class File Format) */
+} JVMDI_class_definition;
+
+ /* For backwards compatibility */
+#define can_change_schema can_unrestrictedly_redefine_classes
+
+typedef struct {
+ unsigned int can_watch_field_modification : 1;
+ unsigned int can_watch_field_access : 1;
+ unsigned int can_get_bytecodes : 1;
+ unsigned int can_get_synthetic_attribute : 1;
+ unsigned int can_get_owned_monitor_info : 1;
+ unsigned int can_get_current_contended_monitor : 1;
+ unsigned int can_get_monitor_info : 1;
+ unsigned int can_get_heap_info : 1;
+ unsigned int can_get_operand_stack : 1;
+ unsigned int can_set_operand_stack : 1;
+ unsigned int can_pop_frame : 1;
+ unsigned int can_get_class_definition : 1;
+ unsigned int can_redefine_classes : 1;
+ unsigned int can_add_method : 1;
+ unsigned int can_unrestrictedly_redefine_classes : 1;
+ unsigned int can_suspend_resume_thread_lists : 1;
+} JVMDI_capabilities;
+
+typedef struct JVMDI_Interface_1_ {
+ jvmdiError (JNICALL *SetEventHook)
+ (JVMDI_EventHook hook);
+ jvmdiError (JNICALL *SetEventNotificationMode)
+ (jint mode, jint eventType, jthread thread, ...);
+
+ jvmdiError (JNICALL *GetThreadStatus)
+ (jthread thread,
+ jint *threadStatusPtr, jint *suspendStatusPtr);
+ jvmdiError (JNICALL *GetAllThreads)
+ (jint *threadsCountPtr, jthread **threadsPtr);
+ jvmdiError (JNICALL *SuspendThread)
+ (jthread thread);
+ jvmdiError (JNICALL *ResumeThread)
+ (jthread thread);
+ jvmdiError (JNICALL *StopThread)
+ (jthread thread, jobject exception);
+ jvmdiError (JNICALL *InterruptThread)
+ (jthread thread);
+ jvmdiError (JNICALL *GetThreadInfo)
+ (jthread thread, JVMDI_thread_info *infoPtr);
+ jvmdiError (JNICALL *GetOwnedMonitorInfo)
+ (jthread thread, JVMDI_owned_monitor_info *infoPtr);
+ jvmdiError (JNICALL *GetCurrentContendedMonitor)
+ (jthread thread, jobject *monitor);
+ jvmdiError (JNICALL *RunDebugThread)
+ (jthread thread, JVMDI_StartFunction proc, void *arg,
+ int priority);
+
+ jvmdiError (JNICALL *GetTopThreadGroups)
+ (jint *groupCountPtr, jthreadGroup **groupsPtr);
+ jvmdiError (JNICALL *GetThreadGroupInfo)
+ (jthreadGroup group, JVMDI_thread_group_info *infoPtr);
+ jvmdiError (JNICALL *GetThreadGroupChildren)
+ (jthreadGroup group,
+ jint *threadCountPtr, jthread **threadsPtr,
+ jint *groupCountPtr, jthreadGroup **groupsPtr);
+
+ jvmdiError (JNICALL *GetFrameCount)
+ (jthread thread, jint *countPtr);
+ jvmdiError (JNICALL *GetCurrentFrame)
+ (jthread thread, jframeID *framePtr);
+ jvmdiError (JNICALL *GetCallerFrame)
+ (jframeID called, jframeID *framePtr);
+ jvmdiError (JNICALL *GetFrameLocation)
+ (jframeID frame, jclass *classPtr, jmethodID *methodPtr,
+ jlocation *locationPtr);
+ jvmdiError (JNICALL *NotifyFramePop)
+ (jframeID frame);
+ jvmdiError (JNICALL *GetLocalObject)
+ (jframeID frame, jint slot, jobject *valuePtr);
+ jvmdiError (JNICALL *GetLocalInt)
+ (jframeID frame, jint slot, jint *valuePtr);
+ jvmdiError (JNICALL *GetLocalLong)
+ (jframeID frame, jint slot, jlong *valuePtr);
+ jvmdiError (JNICALL *GetLocalFloat)
+ (jframeID frame, jint slot, jfloat *valuePtr);
+ jvmdiError (JNICALL *GetLocalDouble)
+ (jframeID frame, jint slot, jdouble *valuePtr);
+ jvmdiError (JNICALL *SetLocalObject)
+ (jframeID frame, jint slot, jobject value);
+ jvmdiError (JNICALL *SetLocalInt)
+ (jframeID frame, jint slot, jint value);
+ jvmdiError (JNICALL *SetLocalLong)
+ (jframeID frame, jint slot, jlong value);
+ jvmdiError (JNICALL *SetLocalFloat)
+ (jframeID frame, jint slot, jfloat value);
+ jvmdiError (JNICALL *SetLocalDouble)
+ (jframeID frame, jint slot, jdouble value);
+
+ jvmdiError (JNICALL *CreateRawMonitor)
+ (char *name, JVMDI_RawMonitor *monitorPtr);
+ jvmdiError (JNICALL *DestroyRawMonitor)
+ (JVMDI_RawMonitor monitor);
+ jvmdiError (JNICALL *RawMonitorEnter)
+ (JVMDI_RawMonitor monitor);
+ jvmdiError (JNICALL *RawMonitorExit)
+ (JVMDI_RawMonitor monitor);
+ jvmdiError (JNICALL *RawMonitorWait)
+ (JVMDI_RawMonitor monitor, jlong millis);
+ jvmdiError (JNICALL *RawMonitorNotify)
+ (JVMDI_RawMonitor monitor);
+ jvmdiError (JNICALL *RawMonitorNotifyAll)
+ (JVMDI_RawMonitor monitor);
+
+ jvmdiError (JNICALL *SetBreakpoint)
+ (jclass clazz, jmethodID method, jlocation location);
+ jvmdiError (JNICALL *ClearBreakpoint)
+ (jclass clazz, jmethodID method, jlocation location);
+ jvmdiError (JNICALL *ClearAllBreakpoints)
+ ();
+
+ jvmdiError (JNICALL *SetFieldAccessWatch)
+ (jclass clazz, jfieldID field);
+ jvmdiError (JNICALL *ClearFieldAccessWatch)
+ (jclass clazz, jfieldID field);
+ jvmdiError (JNICALL *SetFieldModificationWatch)
+ (jclass clazz, jfieldID field);
+ jvmdiError (JNICALL *ClearFieldModificationWatch)
+ (jclass clazz, jfieldID field);
+
+ jvmdiError (JNICALL *SetAllocationHooks)
+ (JVMDI_AllocHook ahook, JVMDI_DeallocHook dhook);
+ jvmdiError (JNICALL *Allocate)
+ (jlong size, jbyte** memPtr);
+ jvmdiError (JNICALL *Deallocate)
+ (jbyte* mem);
+
+ jvmdiError (JNICALL *GetClassSignature)
+ (jclass clazz, char **sigPtr);
+ jvmdiError (JNICALL *GetClassStatus)
+ (jclass clazz, jint *statusPtr);
+ jvmdiError (JNICALL *GetSourceFileName)
+ (jclass clazz, char **sourceNamePtr);
+ jvmdiError (JNICALL *GetClassModifiers)
+ (jclass clazz, jint *modifiersPtr);
+ jvmdiError (JNICALL *GetClassMethods)
+ (jclass clazz, jint *methodCountPtr, jmethodID **methodsPtr);
+ jvmdiError (JNICALL *GetClassFields)
+ (jclass clazz, jint *fieldCountPtr, jfieldID **fieldsPtr);
+ jvmdiError (JNICALL *GetImplementedInterfaces)
+ (jclass clazz, jint *interfaceCountPtr, jclass **interfacesPtr);
+ jvmdiError (JNICALL *IsInterface)
+ (jclass clazz, jboolean *isInterfacePtr);
+ jvmdiError (JNICALL *IsArrayClass)
+ (jclass clazz, jboolean *isArrayClassPtr);
+ jvmdiError (JNICALL *GetClassLoader)
+ (jclass clazz, jobject *classloaderPtr);
+
+ jvmdiError (JNICALL *GetObjectHashCode)
+ (jobject object, jint *hashCodePtr);
+ jvmdiError (JNICALL *GetMonitorInfo)
+ (jobject object, JVMDI_monitor_info *infoPtr);
+
+ jvmdiError (JNICALL *GetFieldName)
+ (jclass clazz, jfieldID field, char **namePtr, char **signaturePtr);
+ jvmdiError (JNICALL *GetFieldDeclaringClass)
+ (jclass clazz, jfieldID field, jclass *declaringClassPtr);
+ jvmdiError (JNICALL *GetFieldModifiers)
+ (jclass clazz, jfieldID field, jint *modifiersPtr);
+ jvmdiError (JNICALL *IsFieldSynthetic)
+ (jclass clazz, jfieldID field, jboolean *isSyntheticPtr);
+
+ jvmdiError (JNICALL *GetMethodName)
+ (jclass clazz, jmethodID method,
+ char **namePtr, char **signaturePtr);
+ jvmdiError (JNICALL *GetMethodDeclaringClass)
+ (jclass clazz, jmethodID method, jclass *declaringClassPtr);
+ jvmdiError (JNICALL *GetMethodModifiers)
+ (jclass clazz, jmethodID method, jint *modifiersPtr);
+ jvmdiError (JNICALL *GetMaxStack)
+ (jclass clazz, jmethodID method, jint *maxPtr);
+ jvmdiError (JNICALL *GetMaxLocals)
+ (jclass clazz, jmethodID method, jint *maxPtr);
+ jvmdiError (JNICALL *GetArgumentsSize)
+ (jclass clazz, jmethodID method, jint *sizePtr);
+ jvmdiError (JNICALL *GetLineNumberTable)
+ (jclass clazz, jmethodID method,
+ jint *entryCountPtr, JVMDI_line_number_entry **tablePtr);
+ jvmdiError (JNICALL *GetMethodLocation)
+ (jclass clazz, jmethodID method,
+ jlocation *startLocationPtr, jlocation *endLocationPtr);
+ jvmdiError (JNICALL *GetLocalVariableTable)
+ (jclass clazz, jmethodID method,
+ jint *entryCountPtr, JVMDI_local_variable_entry **tablePtr);
+ jvmdiError (JNICALL *GetExceptionHandlerTable)
+ (jclass clazz, jmethodID method,
+ jint *entryCountPtr, JVMDI_exception_handler_entry **tablePtr);
+ jvmdiError (JNICALL *GetThrownExceptions)
+ (jclass clazz, jmethodID method,
+ jint *exceptionCountPtr, jclass **exceptionsPtr);
+ jvmdiError (JNICALL *GetBytecodes)
+ (jclass clazz, jmethodID method,
+ jint *bytecodeCountPtr, jbyte **bytecodesPtr);
+ jvmdiError (JNICALL *IsMethodNative)
+ (jclass clazz, jmethodID method, jboolean *isNativePtr);
+ jvmdiError (JNICALL *IsMethodSynthetic)
+ (jclass clazz, jmethodID method, jboolean *isSyntheticPtr);
+
+ jvmdiError (JNICALL *GetLoadedClasses)
+ (jint *classCountPtr, jclass **classesPtr);
+ jvmdiError (JNICALL *GetClassLoaderClasses)
+ (jobject initiatingLoader, jint *classesCountPtr,
+ jclass **classesPtr);
+
+ jvmdiError (JNICALL *PopFrame)
+ (jthread thread);
+ jvmdiError (JNICALL *SetFrameLocation)
+ (jframeID frame, jlocation location);
+ jvmdiError (JNICALL *GetOperandStack)
+ (jframeID frame, jint *operandStackSizePtr,
+ JVMDI_operand_stack_element **operandStackPtr);
+ jvmdiError (JNICALL *SetOperandStack)
+ (jframeID frame, jint operandStackSize,
+ JVMDI_operand_stack_element *operandStack);
+ jvmdiError (JNICALL *AllInstances)
+ (jclass clazz, jint *instanceCountPtr, jobject **instancesPtr);
+ jvmdiError (JNICALL *References)
+ (jobject obj, JVMDI_object_reference_info *refs);
+ jvmdiError (JNICALL *GetClassDefinition)
+ (jclass clazz, JVMDI_class_definition *classDefPtr);
+ jvmdiError (JNICALL *RedefineClasses)
+ (jint classCount, JVMDI_class_definition *classDefs);
+
+ jvmdiError (JNICALL *GetVersionNumber)
+ (jint *versionPtr);
+ jvmdiError (JNICALL *GetCapabilities)
+ (JVMDI_capabilities *capabilitiesPtr);
+
+ jvmdiError (JNICALL *GetSourceDebugExtension)
+ (jclass clazz, char **sourceDebugExtension);
+ jvmdiError (JNICALL *IsMethodObsolete)
+ (jclass clazz, jmethodID method, jboolean *isObsoletePtr);
+
+ jvmdiError (JNICALL *SuspendThreadList)
+ (jint reqCount, jthread *reqList, jvmdiError *results);
+ jvmdiError (JNICALL *ResumeThreadList)
+ (jint reqCount, jthread *reqList, jvmdiError *results);
+} JVMDI_Interface_1;
+
+#ifndef NO_JVMDI_MACROS
+
+#define JVMDI_ERROR_DUPLICATE_BREAKPOINT JVMDI_ERROR_DUPLICATE
+#define JVMDI_ERROR_NO_SUCH_BREAKPOINT JVMDI_ERROR_NOT_FOUND
+#define JVMDI_ERROR_DUPLICATE_FRAME_POP JVMDI_ERROR_DUPLICATE
+
+
+static JVMDI_Interface_1 *jvmdi_interface = NULL;
+static JavaVM *j_vm;
+
+#ifdef __cplusplus
+#define SetJVMDIfromJNIEnv(a_env) ( (jvmdi_interface == NULL)? \
+ ((a_env)->GetJavaVM(&j_vm), \
+ (j_vm)->GetEnv((void **)&jvmdi_interface, \
+ JVMDI_VERSION_1)):0)
+#else
+#define SetJVMDIfromJNIEnv(a_env) ( (jvmdi_interface == NULL)? \
+ ((*a_env)->GetJavaVM(a_env, &j_vm), \
+ (*j_vm)->GetEnv(j_vm, (void **)&jvmdi_interface, \
+ JVMDI_VERSION_1)):0)
+#endif
+
+#define JVMDI_SetEventHook(a_env, a1) ( \
+ SetJVMDIfromJNIEnv(a_env), \
+ jvmdi_interface->SetEventHook(a1) )
+#define JVMDI_GetThreadStatus(a_env, a1, a2, a3) ( \
+ SetJVMDIfromJNIEnv(a_env), \
+ jvmdi_interface->GetThreadStatus(a1, a2, a3) )
+#define JVMDI_GetAllThreads(a_env, a1, a2) ( \
+ SetJVMDIfromJNIEnv(a_env), \
+ jvmdi_interface->GetAllThreads(a1, a2) )
+#define JVMDI_SuspendThread(a_env, a1) ( \
+ SetJVMDIfromJNIEnv(a_env), \
+ jvmdi_interface->SuspendThread(a1) )
+#define JVMDI_ResumeThread(a_env, a1) ( \
+ SetJVMDIfromJNIEnv(a_env), \
+ jvmdi_interface->ResumeThread(a1) )
+#define JVMDI_StopThread(a_env, a1, a2) ( \
+ SetJVMDIfromJNIEnv(a_env), \
+ jvmdi_interface->StopThread(a1, a2) )
+#define JVMDI_InterruptThread(a_env, a1) ( \
+ SetJVMDIfromJNIEnv(a_env), \
+ jvmdi_interface->InterruptThread(a1) )
+#define JVMDI_SetSingleStep(a_env, a1, a2) ( \
+ SetJVMDIfromJNIEnv(a_env), \
+ jvmdi_interface->SetEventNotificationMode( \
+ (a2) ? JVMDI_ENABLE : JVMDI_DISABLE, \
+ JVMDI_EVENT_SINGLE_STEP, a1) )
+#define JVMDI_GetThreadInfo(a_env, a1, a2) ( \
+ SetJVMDIfromJNIEnv(a_env), \
+ jvmdi_interface->GetThreadInfo(a1, a2) )
+#define JVMDI_RunDebugThread(a_env, a1, a2, a3, a4) ( \
+ SetJVMDIfromJNIEnv(a_env), \
+ jvmdi_interface->RunDebugThread(a1, a2, a3, a4) )
+#define JVMDI_GetTopThreadGroups(a_env, a1, a2) ( \
+ SetJVMDIfromJNIEnv(a_env), \
+ jvmdi_interface->GetTopThreadGroups(a1, a2) )
+#define JVMDI_GetThreadGroupInfo(a_env, a1, a2) ( \
+ SetJVMDIfromJNIEnv(a_env), \
+ jvmdi_interface->GetThreadGroupInfo(a1, a2) )
+#define JVMDI_GetThreadGroupChildren(a_env, a1, a2, a3, a4, a5) ( \
+ SetJVMDIfromJNIEnv(a_env), \
+ jvmdi_interface->GetThreadGroupChildren(a1, a2, a3, a4, a5) )
+#define JVMDI_GetCurrentFrame(a_env, a1, a2) ( \
+ SetJVMDIfromJNIEnv(a_env), \
+ jvmdi_interface->GetCurrentFrame(a1, a2) )
+#define JVMDI_GetCallerFrame(a_env, a1, a2) ( \
+ SetJVMDIfromJNIEnv(a_env), \
+ jvmdi_interface->GetCallerFrame(a1, a2) )
+#define JVMDI_GetFrameLocation(a_env, a1, a2, a3, a4) ( \
+ SetJVMDIfromJNIEnv(a_env), \
+ jvmdi_interface->GetFrameLocation(a1, a2, a3, a4) )
+#define JVMDI_NotifyFramePop(a_env, a1) ( \
+ SetJVMDIfromJNIEnv(a_env), \
+ jvmdi_interface->NotifyFramePop(a1) )
+#define JVMDI_GetLocalObject(a_env, a1, a2, a3) ( \
+ SetJVMDIfromJNIEnv(a_env), \
+ jvmdi_interface->GetLocalObject(a1, a2, a3) )
+#define JVMDI_GetLocalInt(a_env, a1, a2, a3) ( \
+ SetJVMDIfromJNIEnv(a_env), \
+ jvmdi_interface->GetLocalInt(a1, a2, a3) )
+#define JVMDI_GetLocalLong(a_env, a1, a2, a3) ( \
+ SetJVMDIfromJNIEnv(a_env), \
+ jvmdi_interface->GetLocalLong(a1, a2, a3) )
+#define JVMDI_GetLocalFloat(a_env, a1, a2, a3) ( \
+ SetJVMDIfromJNIEnv(a_env), \
+ jvmdi_interface->GetLocalFloat(a1, a2, a3) )
+#define JVMDI_GetLocalDouble(a_env, a1, a2, a3) ( \
+ SetJVMDIfromJNIEnv(a_env), \
+ jvmdi_interface->GetLocalDouble(a1, a2, a3) )
+#define JVMDI_SetLocalObject(a_env, a1, a2, a3) ( \
+ SetJVMDIfromJNIEnv(a_env), \
+ jvmdi_interface->SetLocalObject(a1, a2, a3) )
+#define JVMDI_SetLocalInt(a_env, a1, a2, a3) ( \
+ SetJVMDIfromJNIEnv(a_env), \
+ jvmdi_interface->SetLocalInt(a1, a2, a3) )
+#define JVMDI_SetLocalLong(a_env, a1, a2, a3) ( \
+ SetJVMDIfromJNIEnv(a_env), \
+ jvmdi_interface->SetLocalLong(a1, a2, a3) )
+#define JVMDI_SetLocalFloat(a_env, a1, a2, a3) ( \
+ SetJVMDIfromJNIEnv(a_env), \
+ jvmdi_interface->SetLocalFloat(a1, a2, a3) )
+#define JVMDI_SetLocalDouble(a_env, a1, a2, a3) ( \
+ SetJVMDIfromJNIEnv(a_env), \
+ jvmdi_interface->SetLocalDouble(a1, a2, a3) )
+#define JVMDI_CreateRawMonitor(a_env, a1, a2) ( \
+ SetJVMDIfromJNIEnv(a_env), \
+ jvmdi_interface->CreateRawMonitor(a1, a2) )
+#define JVMDI_DestroyRawMonitor(a_env, a1) ( \
+ SetJVMDIfromJNIEnv(a_env), \
+ jvmdi_interface->DestroyRawMonitor(a1) )
+#define JVMDI_RawMonitorEnter(a_env, a1) ( \
+ SetJVMDIfromJNIEnv(a_env), \
+ jvmdi_interface->RawMonitorEnter(a1) )
+#define JVMDI_RawMonitorExit(a_env, a1) ( \
+ SetJVMDIfromJNIEnv(a_env), \
+ jvmdi_interface->RawMonitorExit(a1) )
+#define JVMDI_RawMonitorWait(a_env, a1, a2) ( \
+ SetJVMDIfromJNIEnv(a_env), \
+ jvmdi_interface->RawMonitorWait(a1, a2) )
+#define JVMDI_RawMonitorNotify(a_env, a1) ( \
+ SetJVMDIfromJNIEnv(a_env), \
+ jvmdi_interface->RawMonitorNotify(a1) )
+#define JVMDI_RawMonitorNotifyAll(a_env, a1) ( \
+ SetJVMDIfromJNIEnv(a_env), \
+ jvmdi_interface->RawMonitorNotifyAll(a1) )
+#define JVMDI_SetBreakpoint(a_env, a1, a2, a3) ( \
+ SetJVMDIfromJNIEnv(a_env), \
+ jvmdi_interface->SetBreakpoint(a1, a2, a3) )
+#define JVMDI_ClearBreakpoint(a_env, a1, a2, a3) ( \
+ SetJVMDIfromJNIEnv(a_env), \
+ jvmdi_interface->ClearBreakpoint(a1, a2, a3) )
+#define JVMDI_ClearAllBreakpoints(a_env) ( \
+ SetJVMDIfromJNIEnv(a_env), \
+ jvmdi_interface->ClearAllBreakpoints() )
+#define JVMDI_SetAllocationHooks(a_env, a1, a2) ( \
+ SetJVMDIfromJNIEnv(a_env), \
+ jvmdi_interface->SetAllocationHooks(a1, a2) )
+#define JVMDI_Allocate(a_env, a1, a2) ( \
+ SetJVMDIfromJNIEnv(a_env), \
+ jvmdi_interface->Allocate(a1, a2) )
+#define JVMDI_Deallocate(a_env, a1) ( \
+ SetJVMDIfromJNIEnv(a_env), \
+ jvmdi_interface->Deallocate(a1) )
+#define JVMDI_GetClassSignature(a_env, a1, a2) ( \
+ SetJVMDIfromJNIEnv(a_env), \
+ jvmdi_interface->GetClassSignature(a1, a2) )
+#define JVMDI_GetClassStatus(a_env, a1, a2) ( \
+ SetJVMDIfromJNIEnv(a_env), \
+ jvmdi_interface->GetClassStatus(a1, a2) )
+#define JVMDI_GetSourceFileName(a_env, a1, a2) ( \
+ SetJVMDIfromJNIEnv(a_env), \
+ jvmdi_interface->GetSourceFileName(a1, a2) )
+#define JVMDI_GetClassModifiers(a_env, a1, a2) ( \
+ SetJVMDIfromJNIEnv(a_env), \
+ jvmdi_interface->GetClassModifiers(a1, a2) )
+#define JVMDI_GetClassMethods(a_env, a1, a2, a3) ( \
+ SetJVMDIfromJNIEnv(a_env), \
+ jvmdi_interface->GetClassMethods(a1, a2, a3) )
+#define JVMDI_GetClassFields(a_env, a1, a2, a3) ( \
+ SetJVMDIfromJNIEnv(a_env), \
+ jvmdi_interface->GetClassFields(a1, a2, a3) )
+#define JVMDI_GetImplementedInterfaces(a_env, a1, a2, a3) ( \
+ SetJVMDIfromJNIEnv(a_env), \
+ jvmdi_interface->GetImplementedInterfaces(a1, a2, a3) )
+#define JVMDI_IsInterface(a_env, a1, a2) ( \
+ SetJVMDIfromJNIEnv(a_env), \
+ jvmdi_interface->IsInterface(a1, a2) )
+#define JVMDI_IsArrayClass(a_env, a1, a2) ( \
+ SetJVMDIfromJNIEnv(a_env), \
+ jvmdi_interface->IsArrayClass(a1, a2) )
+#define JVMDI_ClassLoader(a_env, a1, a2) ( \
+ SetJVMDIfromJNIEnv(a_env), \
+ jvmdi_interface->GetClassLoader(a1, a2) )
+#define JVMDI_GetFieldName(a_env, a1, a2, a3, a4) ( \
+ SetJVMDIfromJNIEnv(a_env), \
+ jvmdi_interface->GetFieldName(a1, a2, a3, a4) )
+#define JVMDI_GetFieldDeclaringClass(a_env, a1, a2, a3) ( \
+ SetJVMDIfromJNIEnv(a_env), \
+ jvmdi_interface->GetFieldDeclaringClass(a1, a2, a3) )
+#define JVMDI_GetFieldModifiers(a_env, a1, a2, a3) ( \
+ SetJVMDIfromJNIEnv(a_env), \
+ jvmdi_interface->GetFieldModifiers(a1, a2, a3) )
+#define JVMDI_GetMethodName(a_env, a1, a2, a3, a4) ( \
+ SetJVMDIfromJNIEnv(a_env), \
+ jvmdi_interface->GetMethodName(a1, a2, a3, a4) )
+#define JVMDI_GetMethodDeclaringClass(a_env, a1, a2, a3) ( \
+ SetJVMDIfromJNIEnv(a_env), \
+ jvmdi_interface->GetMethodDeclaringClass(a1, a2, a3) )
+#define JVMDI_GetMethodModifiers(a_env, a1, a2, a3) ( \
+ SetJVMDIfromJNIEnv(a_env), \
+ jvmdi_interface->GetMethodModifiers(a1, a2, a3) )
+#define JVMDI_GetMaxStack(a_env, a1, a2, a3) ( \
+ SetJVMDIfromJNIEnv(a_env), \
+ jvmdi_interface->GetMaxStack(a1, a2, a3) )
+#define JVMDI_GetMaxLocals(a_env, a1, a2, a3) ( \
+ SetJVMDIfromJNIEnv(a_env), \
+ jvmdi_interface->GetMaxLocals(a1, a2, a3) )
+#define JVMDI_GetArgumentsSize(a_env, a1, a2, a3) ( \
+ SetJVMDIfromJNIEnv(a_env), \
+ jvmdi_interface->GetArgumentsSize(a1, a2, a3) )
+#define JVMDI_GetLineNumberTable(a_env, a1, a2, a3, a4) ( \
+ SetJVMDIfromJNIEnv(a_env), \
+ jvmdi_interface->GetLineNumberTable(a1, a2, a3, a4) )
+#define JVMDI_GetMethodLocation(a_env, a1, a2, a3, a4) ( \
+ SetJVMDIfromJNIEnv(a_env), \
+ jvmdi_interface->GetMethodLocation(a1, a2, a3, a4) )
+#define JVMDI_GetLocalVariableTable(a_env, a1, a2, a3, a4) ( \
+ SetJVMDIfromJNIEnv(a_env), \
+ jvmdi_interface->GetLocalVariableTable(a1, a2, a3, a4) )
+#define JVMDI_GetExceptionHandlerTable(a_env, a1, a2, a3, a4) ( \
+ SetJVMDIfromJNIEnv(a_env), \
+ jvmdi_interface->GetExceptionHandlerTable(a1, a2, a3, a4) )
+#define JVMDI_GetThrownExceptions(a_env, a1, a2, a3, a4) ( \
+ SetJVMDIfromJNIEnv(a_env), \
+ jvmdi_interface->GetThrownExceptions(a1, a2, a3, a4) )
+#define JVMDI_GetBytecodes(a_env, a1, a2, a3, a4) ( \
+ SetJVMDIfromJNIEnv(a_env), \
+ jvmdi_interface->GetBytecodes(a1, a2, a3, a4) )
+#define JVMDI_IsMethodNative(a_env, a1, a2, a3) ( \
+ SetJVMDIfromJNIEnv(a_env), \
+ jvmdi_interface->IsMethodNative(a1, a2, a3) )
+#define JVMDI_GetLoadedClasses(a_env, a1, a2) ( \
+ SetJVMDIfromJNIEnv(a_env), \
+ jvmdi_interface->GetLoadedClasses(a1, a2) )
+#define JVMDI_GetClassLoaderClasses(a_env, a1, a2, a3) ( \
+ SetJVMDIfromJNIEnv(a_env), \
+ jvmdi_interface->GetClassLoaderClasses(a1, a2, a3) )
+#define JVMDI_GetVersionNumber(a_env, a1) ( \
+ SetJVMDIfromJNIEnv(a_env), \
+ jvmdi_interface->GetVersionNumber(a1) )
+
+#endif /* !NO_JVMDI_MACROS */
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif /* __cplusplus */
+
+#endif /* !_JAVASOFT_JVMDI_H_ */
+
+
diff --git a/include/jni/jvmpi.h b/include/jni/jvmpi.h
new file mode 100644
index 0000000..57accd3
--- /dev/null
+++ b/include/jni/jvmpi.h
@@ -0,0 +1,642 @@
+/*
+ * @(#)jvmpi.h 1.27 03/01/23
+ *
+ * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
+ */
+
+#ifndef _JAVASOFT_JVMPI_H_
+#define _JAVASOFT_JVMPI_H_
+
+#include "jni.h"
+
+#define JVMPI_VERSION_1 ((jint)0x10000001) /* implied 0 for minor version */
+#define JVMPI_VERSION_1_1 ((jint)0x10000002)
+#define JVMPI_VERSION_1_2 ((jint)0x10000003)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ typedef void (*jvmpi_void_function_of_void)(void *);
+#ifdef __cplusplus
+}
+#endif
+
+/****************************************************************
+ * Profiler interface data structures.
+ ****************************************************************/
+/* identifier types. */
+struct _jobjectID;
+typedef struct _jobjectID * jobjectID; /* type of object ids */
+
+/* raw monitors */
+struct _JVMPI_RawMonitor;
+typedef struct _JVMPI_RawMonitor * JVMPI_RawMonitor;
+
+/* call frame */
+typedef struct {
+ jint lineno; /* line number in the source file */
+ jmethodID method_id; /* method executed in this frame */
+} JVMPI_CallFrame;
+
+/* call trace */
+typedef struct {
+ JNIEnv *env_id; /* Env where trace was recorded */
+ jint num_frames; /* number of frames in this trace */
+ JVMPI_CallFrame *frames; /* frames */
+} JVMPI_CallTrace;
+
+/* method */
+typedef struct {
+ char *method_name; /* name of method */
+ char *method_signature; /* signature of method */
+ jint start_lineno; /* -1 if native, abstract .. */
+ jint end_lineno; /* -1 if native, abstract .. */
+ jmethodID method_id; /* id assigned to this method */
+} JVMPI_Method;
+
+/* Field */
+typedef struct {
+ char *field_name; /* name of field */
+ char *field_signature; /* signature of field */
+} JVMPI_Field;
+
+/* line number info for a compiled method */
+typedef struct {
+ jint offset; /* offset from beginning of method */
+ jint lineno; /* lineno from beginning of src file */
+} JVMPI_Lineno;
+
+/* event */
+typedef struct {
+ jint event_type; /* event_type */
+ JNIEnv *env_id; /* env where this event occured */
+
+ union {
+ struct {
+ const char *class_name; /* class name */
+ char *source_name; /* name of source file */
+ jint num_interfaces; /* number of interfaces implemented */
+ jint num_methods; /* number of methods in the class */
+ JVMPI_Method *methods; /* methods */
+ jint num_static_fields; /* number of static fields */
+ JVMPI_Field *statics; /* static fields */
+ jint num_instance_fields; /* number of instance fields */
+ JVMPI_Field *instances; /* instance fields */
+ jobjectID class_id; /* id of the class object */
+ } class_load;
+
+ struct {
+ jobjectID class_id; /* id of the class object */
+ } class_unload;
+
+ struct {
+ unsigned char *class_data; /* content of class file */
+ jint class_data_len; /* class file length */
+ unsigned char *new_class_data; /* instrumented class file */
+ jint new_class_data_len; /* new class file length */
+ void * (*malloc_f)(unsigned int); /* memory allocation function */
+ } class_load_hook;
+
+ struct {
+ jint arena_id;
+ jobjectID class_id; /* id of object class */
+ jint is_array; /* JVMPI_NORMAL_OBJECT, ... */
+ jint size; /* size in number of bytes */
+ jobjectID obj_id; /* id assigned to this object */
+ } obj_alloc;
+
+ struct {
+ jobjectID obj_id; /* id of the object */
+ } obj_free;
+
+ struct {
+ jint arena_id; /* cur arena id */
+ jobjectID obj_id; /* cur object id */
+ jint new_arena_id; /* new arena id */
+ jobjectID new_obj_id; /* new object id */
+ } obj_move;
+
+ struct {
+ jint arena_id; /* id of arena */
+ const char *arena_name; /* name of arena */
+ } new_arena;
+
+ struct {
+ jint arena_id; /* id of arena */
+ } delete_arena;
+
+ struct {
+ char *thread_name; /* name of thread */
+ char *group_name; /* name of group */
+ char *parent_name; /* name of parent */
+ jobjectID thread_id; /* id of the thread object */
+ JNIEnv *thread_env_id;
+ } thread_start;
+
+ struct {
+ int dump_level; /* level of the heap dump info */
+ char *begin; /* where all the root records begin,
+ please see the heap dump buffer
+ format described below */
+ char *end; /* where the object records end. */
+ jint num_traces; /* number of thread traces,
+ 0 if dump level = JVMPI_DUMP_LEVEL_0 */
+ JVMPI_CallTrace *traces; /* thread traces collected during
+ heap dump */
+ } heap_dump;
+
+ struct {
+ jobjectID obj_id; /* object id */
+ jobject ref_id; /* id assigned to the globalref */
+ } jni_globalref_alloc;
+
+ struct {
+ jobject ref_id; /* id of the global ref */
+ } jni_globalref_free;
+
+ struct {
+ jmethodID method_id; /* method */
+ } method;
+
+ struct {
+ jmethodID method_id; /* id of method */
+ jobjectID obj_id; /* id of target object */
+ } method_entry2;
+
+ struct {
+ jmethodID method_id; /* id of compiled method */
+ void *code_addr; /* code start addr. in memory */
+ jint code_size; /* code size */
+ jint lineno_table_size; /* size of lineno table */
+ JVMPI_Lineno *lineno_table; /* lineno info */
+ } compiled_method_load;
+
+ struct {
+ jmethodID method_id; /* id of unloaded compiled method */
+ } compiled_method_unload;
+
+ struct {
+ jmethodID method_id; /* id of the method the instruction belongs to */
+ jint offset; /* instruction offset in the method's bytecode */
+ union {
+ struct {
+ jboolean is_true; /* whether true or false branch is taken */
+ } if_info;
+ struct {
+ jint key; /* top stack value used as an index */
+ jint low; /* min value of the index */
+ jint hi; /* max value of the index */
+ } tableswitch_info;
+ struct {
+ jint chosen_pair_index; /* actually chosen pair index (0-based)
+ * if chosen_pair_index == pairs_total then
+ * the 'default' branch is taken
+ */
+ jint pairs_total; /* total number of lookupswitch pairs */
+ } lookupswitch_info;
+ } u;
+ } instruction;
+
+ struct {
+ char *begin; /* beginning of dump buffer,
+ see below for format */
+ char *end; /* end of dump buffer */
+ jint num_traces; /* number of traces */
+ JVMPI_CallTrace *traces; /* traces of all threads */
+ jint *threads_status; /* status of all threads */
+ } monitor_dump;
+
+ struct {
+ const char *name; /* name of raw monitor */
+ JVMPI_RawMonitor id; /* id */
+ } raw_monitor;
+
+ struct {
+ jobjectID object; /* Java object */
+ } monitor;
+
+ struct {
+ jobjectID object; /* Java object */
+ jlong timeout; /* timeout period */
+ } monitor_wait;
+
+ struct {
+ jlong used_objects;
+ jlong used_object_space;
+ jlong total_object_space;
+ } gc_info;
+
+ struct {
+ jint data_len;
+ char *data;
+ } object_dump;
+ } u;
+} JVMPI_Event;
+
+/* interface functions */
+typedef struct {
+ jint version; /* JVMPI version */
+
+ /* ------interface implemented by the profiler------ */
+
+ /**
+ * Function called by the JVM to notify an event.
+ */
+ void (*NotifyEvent)(JVMPI_Event *event);
+
+ /* ------interface implemented by the JVM------ */
+
+ /**
+ * Function called by the profiler to enable/disable/send notification
+ * for a particular event type.
+ *
+ * event_type - event_type
+ * arg - event specific arg
+ *
+ * return JVMPI_NOT_AVAILABLE, JVMPI_SUCCESS or JVMPI_FAIL
+ */
+ jint (*EnableEvent)(jint event_type, void *arg);
+ jint (*DisableEvent)(jint event_type, void *arg);
+ jint (*RequestEvent)(jint event_type, void *arg);
+
+ /**
+ * Function called by the profiler to get a stack
+ * trace from the JVM.
+ *
+ * trace - trace data structure to be filled
+ * depth - maximum depth of the trace.
+ */
+ void (*GetCallTrace)(JVMPI_CallTrace *trace, jint depth);
+
+ /**
+ * Function called by profiler when it wants to exit/stop.
+ */
+ void (*ProfilerExit)(jint);
+
+ /**
+ * Utility functions provided by the JVM.
+ */
+ JVMPI_RawMonitor (*RawMonitorCreate)(char *lock_name);
+ void (*RawMonitorEnter)(JVMPI_RawMonitor lock_id);
+ void (*RawMonitorExit)(JVMPI_RawMonitor lock_id);
+ void (*RawMonitorWait)(JVMPI_RawMonitor lock_id, jlong ms);
+ void (*RawMonitorNotifyAll)(JVMPI_RawMonitor lock_id);
+ void (*RawMonitorDestroy)(JVMPI_RawMonitor lock_id);
+
+ /**
+ * Function called by the profiler to get the current thread's CPU time.
+ *
+ * return time in nanoseconds;
+ */
+ jlong (*GetCurrentThreadCpuTime)(void);
+
+ void (*SuspendThread)(JNIEnv *env);
+ void (*ResumeThread)(JNIEnv *env);
+ jint (*GetThreadStatus)(JNIEnv *env);
+ jboolean (*ThreadHasRun)(JNIEnv *env);
+
+ /* This function can be called safely only after JVMPI_EVENT_VM_INIT_DONE
+ notification by the JVM. */
+ jint (*CreateSystemThread)(char *name, jint priority, void (*f)(void *));
+
+ /* thread local storage access functions to avoid locking in time
+ critical functions */
+ void (*SetThreadLocalStorage)(JNIEnv *env_id, void *ptr);
+ void * (*GetThreadLocalStorage)(JNIEnv *env_id);
+
+ /* control GC */
+ void (*DisableGC)(void);
+ void (*EnableGC)(void);
+ void (*RunGC)(void);
+
+ jobjectID (*GetThreadObject)(JNIEnv *env);
+ jobjectID (*GetMethodClass)(jmethodID mid);
+
+ /* JNI <-> jobject conversions */
+ jobject (*jobjectID2jobject)(jobjectID jid);
+ jobjectID (*jobject2jobjectID)(jobject jobj);
+
+ void (*SuspendThreadList)
+ (jint reqCount, JNIEnv **reqList, jint *results);
+ void (*ResumeThreadList)
+ (jint reqCount, JNIEnv **reqList, jint *results);
+} JVMPI_Interface;
+
+/* type of argument passed to RequestEvent for heap dumps */
+typedef struct {
+ jint heap_dump_level;
+} JVMPI_HeapDumpArg;
+
+/**********************************************************************
+ * Constants and formats used in JVM Profiler Interface.
+ **********************************************************************/
+/*
+ * Event type constants.
+ */
+#define JVMPI_EVENT_METHOD_ENTRY ((jint)1)
+#define JVMPI_EVENT_METHOD_ENTRY2 ((jint)2)
+#define JVMPI_EVENT_METHOD_EXIT ((jint)3)
+
+#define JVMPI_EVENT_OBJECT_ALLOC ((jint)4)
+#define JVMPI_EVENT_OBJECT_FREE ((jint)5)
+#define JVMPI_EVENT_OBJECT_MOVE ((jint)6)
+
+#define JVMPI_EVENT_COMPILED_METHOD_LOAD ((jint)7)
+#define JVMPI_EVENT_COMPILED_METHOD_UNLOAD ((jint)8)
+
+#define JVMPI_EVENT_INSTRUCTION_START ((jint)9)
+
+#define JVMPI_EVENT_THREAD_START ((jint)33)
+#define JVMPI_EVENT_THREAD_END ((jint)34)
+
+#define JVMPI_EVENT_CLASS_LOAD_HOOK ((jint)35)
+
+#define JVMPI_EVENT_HEAP_DUMP ((jint)37)
+#define JVMPI_EVENT_JNI_GLOBALREF_ALLOC ((jint)38)
+#define JVMPI_EVENT_JNI_GLOBALREF_FREE ((jint)39)
+#define JVMPI_EVENT_JNI_WEAK_GLOBALREF_ALLOC ((jint)40)
+#define JVMPI_EVENT_JNI_WEAK_GLOBALREF_FREE ((jint)41)
+#define JVMPI_EVENT_CLASS_LOAD ((jint)42)
+#define JVMPI_EVENT_CLASS_UNLOAD ((jint)43)
+#define JVMPI_EVENT_DATA_DUMP_REQUEST ((jint)44)
+#define JVMPI_EVENT_DATA_RESET_REQUEST ((jint)45)
+
+#define JVMPI_EVENT_JVM_INIT_DONE ((jint)46)
+#define JVMPI_EVENT_JVM_SHUT_DOWN ((jint)47)
+
+#define JVMPI_EVENT_ARENA_NEW ((jint)48)
+#define JVMPI_EVENT_ARENA_DELETE ((jint)49)
+
+#define JVMPI_EVENT_OBJECT_DUMP ((jint)50)
+
+#define JVMPI_EVENT_RAW_MONITOR_CONTENDED_ENTER ((jint)51)
+#define JVMPI_EVENT_RAW_MONITOR_CONTENDED_ENTERED ((jint)52)
+#define JVMPI_EVENT_RAW_MONITOR_CONTENDED_EXIT ((jint)53)
+#define JVMPI_EVENT_MONITOR_CONTENDED_ENTER ((jint)54)
+#define JVMPI_EVENT_MONITOR_CONTENDED_ENTERED ((jint)55)
+#define JVMPI_EVENT_MONITOR_CONTENDED_EXIT ((jint)56)
+#define JVMPI_EVENT_MONITOR_WAIT ((jint)57)
+#define JVMPI_EVENT_MONITOR_WAITED ((jint)58)
+#define JVMPI_EVENT_MONITOR_DUMP ((jint)59)
+
+#define JVMPI_EVENT_GC_START ((jint)60)
+#define JVMPI_EVENT_GC_FINISH ((jint)61)
+
+#define JVMPI_MAX_EVENT_TYPE_VAL ((jint)61)
+
+/* old definitions, to be removed */
+#define JVMPI_EVENT_LOAD_COMPILED_METHOD ((jint)7)
+#define JVMPI_EVENT_UNLOAD_COMPILED_METHOD ((jint)8)
+#define JVMPI_EVENT_NEW_ARENA ((jint)48)
+#define JVMPI_EVENT_DELETE_ARENA ((jint)49)
+#define JVMPI_EVENT_DUMP_DATA_REQUEST ((jint)44)
+#define JVMPI_EVENT_RESET_DATA_REQUEST ((jint)45)
+#define JVMPI_EVENT_OBJ_ALLOC ((jint)4)
+#define JVMPI_EVENT_OBJ_FREE ((jint)5)
+#define JVMPI_EVENT_OBJ_MOVE ((jint)6)
+
+#define JVMPI_REQUESTED_EVENT ((jint)0x10000000)
+
+
+
+/*
+ * enabling/disabling event notification.
+ */
+/* results */
+#define JVMPI_SUCCESS ((jint)0)
+#define JVMPI_NOT_AVAILABLE ((jint)1)
+#define JVMPI_FAIL ((jint)-1)
+
+/*
+ * Thread status
+ */
+enum {
+ JVMPI_THREAD_RUNNABLE = 1,
+ JVMPI_THREAD_MONITOR_WAIT,
+ JVMPI_THREAD_CONDVAR_WAIT
+};
+
+#define JVMPI_THREAD_SUSPENDED 0x8000
+#define JVMPI_THREAD_INTERRUPTED 0x4000
+
+/*
+ * Thread priority
+ */
+#define JVMPI_MINIMUM_PRIORITY 1
+#define JVMPI_MAXIMUM_PRIORITY 10
+#define JVMPI_NORMAL_PRIORITY 5
+
+/*
+ * Object type constants.
+ */
+#define JVMPI_NORMAL_OBJECT ((jint)0)
+#define JVMPI_CLASS ((jint)2)
+#define JVMPI_BOOLEAN ((jint)4)
+#define JVMPI_CHAR ((jint)5)
+#define JVMPI_FLOAT ((jint)6)
+#define JVMPI_DOUBLE ((jint)7)
+#define JVMPI_BYTE ((jint)8)
+#define JVMPI_SHORT ((jint)9)
+#define JVMPI_INT ((jint)10)
+#define JVMPI_LONG ((jint)11)
+
+/*
+ * Monitor dump constants.
+ */
+
+#define JVMPI_MONITOR_JAVA 0x01
+#define JVMPI_MONITOR_RAW 0x02
+
+/*
+ * Heap dump constants.
+ */
+#define JVMPI_GC_ROOT_UNKNOWN 0xff
+#define JVMPI_GC_ROOT_JNI_GLOBAL 0x01
+#define JVMPI_GC_ROOT_JNI_LOCAL 0x02
+#define JVMPI_GC_ROOT_JAVA_FRAME 0x03
+#define JVMPI_GC_ROOT_NATIVE_STACK 0x04
+#define JVMPI_GC_ROOT_STICKY_CLASS 0x05
+#define JVMPI_GC_ROOT_THREAD_BLOCK 0x06
+#define JVMPI_GC_ROOT_MONITOR_USED 0x07
+#define JVMPI_GC_ROOT_THREAD_OBJ 0x08
+
+#define JVMPI_GC_CLASS_DUMP 0x20
+#define JVMPI_GC_INSTANCE_DUMP 0x21
+#define JVMPI_GC_OBJ_ARRAY_DUMP 0x22
+#define JVMPI_GC_PRIM_ARRAY_DUMP 0x23
+
+/*
+ * Dump levels
+ */
+#define JVMPI_DUMP_LEVEL_0 ((jint)0)
+#define JVMPI_DUMP_LEVEL_1 ((jint)1)
+#define JVMPI_DUMP_LEVEL_2 ((jint)2)
+
+/* Types used in dumps -
+ *
+ * u1: 1 byte
+ * u2: 2 bytes
+ * u4: 4 bytes
+ * u8: 8 bytes
+ *
+ * ty: u1 where:
+ * JVMPI_CLASS: object
+ * JVMPI_BOOLEAN: boolean
+ * JVMPI_CHAR: char
+ * JVMPI_FLOAT: float
+ * JVMPI_DOUBLE: double
+ * JVMPI_BYTE: byte
+ * JVMPI_SHORT: short
+ * JVMPI_INT: int
+ * JVMPI_LONG: long
+ *
+ * vl: values, exact type depends on the type of the value:
+ * JVMPI_BOOLEAN & JVMPI_BYTE: u1
+ * JVMPI_SHORT & JVMPI_CHAR: u2
+ * JVMPI_INT & JVMPI_FLOAT: u4
+ * JVMPI_LONG & JVMPI_DOUBLE: u8
+ * JVMPI_CLASS: jobjectID
+ */
+
+/* Format of the monitor dump buffer:
+ *
+ * u1 monitor type
+ *
+ * JVMPI_MONITOR_JAVA Java monitor
+ *
+ * jobjectID object
+ * JNIEnv * owner thread
+ * u4 entry count
+ * u4 # of threads waiting to enter
+ * [JNIEnv *]* threads waiting to enter
+ * u4 # of threads waiting to be notified
+ * [JNIEnv *]* threads waiting to be notified
+ *
+ * JVMPI_MONITOR_RAW raw monitor
+ *
+ * char * name
+ * JVMPI_RawMonitor raw monitor
+ * JNIEnv * owner thread
+ * u4 entry count
+ * u4 # of threads waiting to enter
+ * [JNIEnv *]* threads waiting to enter
+ * u4 # of threads waiting to be notified
+ * [JNIEnv *]* threads waiting to be notified
+ */
+
+/* Format of the heap dump buffer depends on the dump level
+ * specified in the JVMPI_HeapDumpArg passed to RequestEvent as arg.
+ * The default is JVMPI_DUMP_LEVEL_2.
+ *
+ * JVMPI_DUMP_LEVEL_0:
+ *
+ * u1 object type (JVMPI_CLASS ...)
+ * jobjectID object
+ *
+ * JVMPI_DUMP_LEVEL_1 and JVMPI_DUMP_LEVEL_2 use the following format:
+ * In the case of JVMPI_DUMP_LEVEL_1 the values of primitive fields in object
+ * instance dumps , the values of primitive statics in class dumps and the
+ * values of primitive arrays are excluded. JVMPI_DUMP_LEVEL_2 includes the
+ * primitive values.
+ *
+ * u1 record type
+ *
+ * JVMPI_GC_ROOT_UNKNOWN unknown root
+ *
+ * jobjectID object
+ *
+ * JVMPI_GC_ROOT_JNI_GLOBAL JNI global ref root
+ *
+ * jobjectID object
+ * jobject JNI global reference
+ *
+ * JVMPI_GC_ROOT_JNI_LOCAL JNI local ref
+ *
+ * jobjectID object
+ * JNIEnv * thread
+ * u4 frame # in stack trace (-1 for empty)
+ *
+ * JVMPI_GC_ROOT_JAVA_FRAME Java stack frame
+ *
+ * jobjectID object
+ * JNIEnv * thread
+ * u4 frame # in stack trace (-1 for empty)
+ *
+ * JVMPI_GC_ROOT_NATIVE_STACK Native stack
+ *
+ * jobjectID object
+ * JNIEnv * thread
+ *
+ * JVMPI_GC_ROOT_STICKY_CLASS System class
+ *
+ * jobjectID class object
+ *
+ * JVMPI_GC_ROOT_THREAD_BLOCK Reference from thread block
+ *
+ * jobjectID thread object
+ * JNIEnv * thread
+ *
+ * JVMPI_GC_ROOT_MONITOR_USED Busy monitor
+ *
+ * jobjectID object
+ *
+ * JVMPI_GC_CLASS_DUMP dump of a class object
+ *
+ * jobjectID class
+ * jobjectID super
+ * jobjectID class loader
+ * jobjectID signers
+ * jobjectID protection domain
+ * jobjectID class name
+ * void * reserved
+ *
+ * u4 instance size (in bytes)
+ *
+ * [jobjectID]* interfaces
+ *
+ * u2 size of constant pool
+ * [u2, constant pool index,
+ * ty, type,
+ * vl]* value
+ *
+ * [vl]* static field values
+ *
+ * JVMPI_GC_INSTANCE_DUMP dump of a normal object
+ *
+ * jobjectID object
+ * jobjectID class
+ * u4 number of bytes that follow
+ * [vl]* instance field values (class, followed
+ * by super, super's super ...)
+ *
+ * JVMPI_GC_OBJ_ARRAY_DUMP dump of an object array
+ *
+ * jobjectID array object
+ * u4 number of elements
+ * jobjectID element class
+ * [jobjectID]* elements
+ *
+ * JVMPI_GC_PRIM_ARRAY_DUMP dump of a primitive array
+ *
+ * jobjectID array object
+ * u4 number of elements
+ * ty element type
+ * [vl]* elements
+ *
+ */
+
+/* Format of the dump received in JVMPI_EVENT_OBJECT_DUMP:
+ * All the records have JVMPI_DUMP_LEVEL_2 information.
+ *
+ * u1 record type
+ *
+ * followed by a:
+ *
+ * JVMPI_GC_CLASS_DUMP,
+ * JVMPI_GC_INSTANCE_DUMP,
+ * JVMPI_GC_OBJ_ARRAY_DUMP, or
+ * JVMPI_GC_PRIM_ARRAY_DUMP record.
+ */
+
+#endif /* !_JAVASOFT_JVMPI_H_ */
diff --git a/include/jni/linux/jawt_md.h b/include/jni/linux/jawt_md.h
new file mode 100644
index 0000000..dbb13e2
--- /dev/null
+++ b/include/jni/linux/jawt_md.h
@@ -0,0 +1,43 @@
+/*
+ * @(#)jawt_md.h 1.10 03/01/23
+ *
+ * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
+ */
+
+#ifndef _JAVASOFT_JAWT_MD_H_
+#define _JAVASOFT_JAWT_MD_H_
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Intrinsic.h>
+#include "jawt.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * X11-specific declarations for AWT native interface.
+ * See notes in jawt.h for an example of use.
+ */
+typedef struct jawt_X11DrawingSurfaceInfo {
+ Drawable drawable;
+ Display* display;
+ VisualID visualID;
+ Colormap colormapID;
+ int depth;
+ /*
+ * Since 1.4
+ * Returns a pixel value from a set of RGB values.
+ * This is useful for paletted color (256 color) modes.
+ */
+ int (JNICALL *GetAWTColor)(JAWT_DrawingSurface* ds,
+ int r, int g, int b);
+} JAWT_X11DrawingSurfaceInfo;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !_JAVASOFT_JAWT_MD_H_ */
diff --git a/include/jni/linux/jni_md.h b/include/jni/linux/jni_md.h
new file mode 100644
index 0000000..9868531
--- /dev/null
+++ b/include/jni/linux/jni_md.h
@@ -0,0 +1,24 @@
+/*
+ * @(#)jni_md.h 1.17 03/01/23
+ *
+ * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
+ */
+
+#ifndef _JAVASOFT_JNI_MD_H_
+#define _JAVASOFT_JNI_MD_H_
+
+#define JNIEXPORT
+#define JNIIMPORT
+#define JNICALL
+
+typedef int jint;
+#ifdef _LP64 /* 64-bit Solaris */
+typedef long jlong;
+#else
+typedef long long jlong;
+#endif
+
+typedef signed char jbyte;
+
+#endif /* !_JAVASOFT_JNI_MD_H_ */
diff --git a/install-sh b/install-sh
new file mode 100755
index 0000000..6781b98
--- /dev/null
+++ b/install-sh
@@ -0,0 +1,520 @@
+#!/bin/sh
+# install - install a program, script, or datafile
+
+scriptversion=2009-04-28.21; # UTC
+
+# This originates from X11R5 (mit/util/scripts/install.sh), which was
+# later released in X11R6 (xc/config/util/install.sh) with the
+# following copyright and license.
+#
+# Copyright (C) 1994 X Consortium
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to
+# deal in the Software without restriction, including without limitation the
+# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+# sell copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
+# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+# Except as contained in this notice, the name of the X Consortium shall not
+# be used in advertising or otherwise to promote the sale, use or other deal-
+# ings in this Software without prior written authorization from the X Consor-
+# tium.
+#
+#
+# FSF changes to this file are in the public domain.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.
+
+nl='
+'
+IFS=" "" $nl"
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit=${DOITPROG-}
+if test -z "$doit"; then
+ doit_exec=exec
+else
+ doit_exec=$doit
+fi
+
+# Put in absolute file names if you don't have them in your path;
+# or use environment vars.
+
+chgrpprog=${CHGRPPROG-chgrp}
+chmodprog=${CHMODPROG-chmod}
+chownprog=${CHOWNPROG-chown}
+cmpprog=${CMPPROG-cmp}
+cpprog=${CPPROG-cp}
+mkdirprog=${MKDIRPROG-mkdir}
+mvprog=${MVPROG-mv}
+rmprog=${RMPROG-rm}
+stripprog=${STRIPPROG-strip}
+
+posix_glob='?'
+initialize_posix_glob='
+ test "$posix_glob" != "?" || {
+ if (set -f) 2>/dev/null; then
+ posix_glob=
+ else
+ posix_glob=:
+ fi
+ }
+'
+
+posix_mkdir=
+
+# Desired mode of installed file.
+mode=0755
+
+chgrpcmd=
+chmodcmd=$chmodprog
+chowncmd=
+mvcmd=$mvprog
+rmcmd="$rmprog -f"
+stripcmd=
+
+src=
+dst=
+dir_arg=
+dst_arg=
+
+copy_on_change=false
+no_target_directory=
+
+usage="\
+Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
+ or: $0 [OPTION]... SRCFILES... DIRECTORY
+ or: $0 [OPTION]... -t DIRECTORY SRCFILES...
+ or: $0 [OPTION]... -d DIRECTORIES...
+
+In the 1st form, copy SRCFILE to DSTFILE.
+In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
+In the 4th, create DIRECTORIES.
+
+Options:
+ --help display this help and exit.
+ --version display version info and exit.
+
+ -c (ignored)
+ -C install only if different (preserve the last data modification time)
+ -d create directories instead of installing files.
+ -g GROUP $chgrpprog installed files to GROUP.
+ -m MODE $chmodprog installed files to MODE.
+ -o USER $chownprog installed files to USER.
+ -s $stripprog installed files.
+ -t DIRECTORY install into DIRECTORY.
+ -T report an error if DSTFILE is a directory.
+
+Environment variables override the default commands:
+ CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
+ RMPROG STRIPPROG
+"
+
+while test $# -ne 0; do
+ case $1 in
+ -c) ;;
+
+ -C) copy_on_change=true;;
+
+ -d) dir_arg=true;;
+
+ -g) chgrpcmd="$chgrpprog $2"
+ shift;;
+
+ --help) echo "$usage"; exit $?;;
+
+ -m) mode=$2
+ case $mode in
+ *' '* | *' '* | *'
+'* | *'*'* | *'?'* | *'['*)
+ echo "$0: invalid mode: $mode" >&2
+ exit 1;;
+ esac
+ shift;;
+
+ -o) chowncmd="$chownprog $2"
+ shift;;
+
+ -s) stripcmd=$stripprog;;
+
+ -t) dst_arg=$2
+ shift;;
+
+ -T) no_target_directory=true;;
+
+ --version) echo "$0 $scriptversion"; exit $?;;
+
+ --) shift
+ break;;
+
+ -*) echo "$0: invalid option: $1" >&2
+ exit 1;;
+
+ *) break;;
+ esac
+ shift
+done
+
+if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
+ # When -d is used, all remaining arguments are directories to create.
+ # When -t is used, the destination is already specified.
+ # Otherwise, the last argument is the destination. Remove it from $@.
+ for arg
+ do
+ if test -n "$dst_arg"; then
+ # $@ is not empty: it contains at least $arg.
+ set fnord "$@" "$dst_arg"
+ shift # fnord
+ fi
+ shift # arg
+ dst_arg=$arg
+ done
+fi
+
+if test $# -eq 0; then
+ if test -z "$dir_arg"; then
+ echo "$0: no input file specified." >&2
+ exit 1
+ fi
+ # It's OK to call `install-sh -d' without argument.
+ # This can happen when creating conditional directories.
+ exit 0
+fi
+
+if test -z "$dir_arg"; then
+ trap '(exit $?); exit' 1 2 13 15
+
+ # Set umask so as not to create temps with too-generous modes.
+ # However, 'strip' requires both read and write access to temps.
+ case $mode in
+ # Optimize common cases.
+ *644) cp_umask=133;;
+ *755) cp_umask=22;;
+
+ *[0-7])
+ if test -z "$stripcmd"; then
+ u_plus_rw=
+ else
+ u_plus_rw='% 200'
+ fi
+ cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
+ *)
+ if test -z "$stripcmd"; then
+ u_plus_rw=
+ else
+ u_plus_rw=,u+rw
+ fi
+ cp_umask=$mode$u_plus_rw;;
+ esac
+fi
+
+for src
+do
+ # Protect names starting with `-'.
+ case $src in
+ -*) src=./$src;;
+ esac
+
+ if test -n "$dir_arg"; then
+ dst=$src
+ dstdir=$dst
+ test -d "$dstdir"
+ dstdir_status=$?
+ else
+
+ # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
+ # might cause directories to be created, which would be especially bad
+ # if $src (and thus $dsttmp) contains '*'.
+ if test ! -f "$src" && test ! -d "$src"; then
+ echo "$0: $src does not exist." >&2
+ exit 1
+ fi
+
+ if test -z "$dst_arg"; then
+ echo "$0: no destination specified." >&2
+ exit 1
+ fi
+
+ dst=$dst_arg
+ # Protect names starting with `-'.
+ case $dst in
+ -*) dst=./$dst;;
+ esac
+
+ # If destination is a directory, append the input filename; won't work
+ # if double slashes aren't ignored.
+ if test -d "$dst"; then
+ if test -n "$no_target_directory"; then
+ echo "$0: $dst_arg: Is a directory" >&2
+ exit 1
+ fi
+ dstdir=$dst
+ dst=$dstdir/`basename "$src"`
+ dstdir_status=0
+ else
+ # Prefer dirname, but fall back on a substitute if dirname fails.
+ dstdir=`
+ (dirname "$dst") 2>/dev/null ||
+ expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$dst" : 'X\(//\)[^/]' \| \
+ X"$dst" : 'X\(//\)$' \| \
+ X"$dst" : 'X\(/\)' \| . 2>/dev/null ||
+ echo X"$dst" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'
+ `
+
+ test -d "$dstdir"
+ dstdir_status=$?
+ fi
+ fi
+
+ obsolete_mkdir_used=false
+
+ if test $dstdir_status != 0; then
+ case $posix_mkdir in
+ '')
+ # Create intermediate dirs using mode 755 as modified by the umask.
+ # This is like FreeBSD 'install' as of 1997-10-28.
+ umask=`umask`
+ case $stripcmd.$umask in
+ # Optimize common cases.
+ *[2367][2367]) mkdir_umask=$umask;;
+ .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
+
+ *[0-7])
+ mkdir_umask=`expr $umask + 22 \
+ - $umask % 100 % 40 + $umask % 20 \
+ - $umask % 10 % 4 + $umask % 2
+ `;;
+ *) mkdir_umask=$umask,go-w;;
+ esac
+
+ # With -d, create the new directory with the user-specified mode.
+ # Otherwise, rely on $mkdir_umask.
+ if test -n "$dir_arg"; then
+ mkdir_mode=-m$mode
+ else
+ mkdir_mode=
+ fi
+
+ posix_mkdir=false
+ case $umask in
+ *[123567][0-7][0-7])
+ # POSIX mkdir -p sets u+wx bits regardless of umask, which
+ # is incompatible with FreeBSD 'install' when (umask & 300) != 0.
+ ;;
+ *)
+ tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
+ trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
+
+ if (umask $mkdir_umask &&
+ exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
+ then
+ if test -z "$dir_arg" || {
+ # Check for POSIX incompatibilities with -m.
+ # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
+ # other-writeable bit of parent directory when it shouldn't.
+ # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
+ ls_ld_tmpdir=`ls -ld "$tmpdir"`
+ case $ls_ld_tmpdir in
+ d????-?r-*) different_mode=700;;
+ d????-?--*) different_mode=755;;
+ *) false;;
+ esac &&
+ $mkdirprog -m$different_mode -p -- "$tmpdir" && {
+ ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
+ test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
+ }
+ }
+ then posix_mkdir=:
+ fi
+ rmdir "$tmpdir/d" "$tmpdir"
+ else
+ # Remove any dirs left behind by ancient mkdir implementations.
+ rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
+ fi
+ trap '' 0;;
+ esac;;
+ esac
+
+ if
+ $posix_mkdir && (
+ umask $mkdir_umask &&
+ $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
+ )
+ then :
+ else
+
+ # The umask is ridiculous, or mkdir does not conform to POSIX,
+ # or it failed possibly due to a race condition. Create the
+ # directory the slow way, step by step, checking for races as we go.
+
+ case $dstdir in
+ /*) prefix='/';;
+ -*) prefix='./';;
+ *) prefix='';;
+ esac
+
+ eval "$initialize_posix_glob"
+
+ oIFS=$IFS
+ IFS=/
+ $posix_glob set -f
+ set fnord $dstdir
+ shift
+ $posix_glob set +f
+ IFS=$oIFS
+
+ prefixes=
+
+ for d
+ do
+ test -z "$d" && continue
+
+ prefix=$prefix$d
+ if test -d "$prefix"; then
+ prefixes=
+ else
+ if $posix_mkdir; then
+ (umask=$mkdir_umask &&
+ $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
+ # Don't fail if two instances are running concurrently.
+ test -d "$prefix" || exit 1
+ else
+ case $prefix in
+ *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
+ *) qprefix=$prefix;;
+ esac
+ prefixes="$prefixes '$qprefix'"
+ fi
+ fi
+ prefix=$prefix/
+ done
+
+ if test -n "$prefixes"; then
+ # Don't fail if two instances are running concurrently.
+ (umask $mkdir_umask &&
+ eval "\$doit_exec \$mkdirprog $prefixes") ||
+ test -d "$dstdir" || exit 1
+ obsolete_mkdir_used=true
+ fi
+ fi
+ fi
+
+ if test -n "$dir_arg"; then
+ { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
+ { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
+ { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
+ test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
+ else
+
+ # Make a couple of temp file names in the proper directory.
+ dsttmp=$dstdir/_inst.$$_
+ rmtmp=$dstdir/_rm.$$_
+
+ # Trap to clean up those temp files at exit.
+ trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
+
+ # Copy the file name to the temp name.
+ (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
+
+ # and set any options; do chmod last to preserve setuid bits.
+ #
+ # If any of these fail, we abort the whole thing. If we want to
+ # ignore errors from any of these, just make sure not to ignore
+ # errors from the above "$doit $cpprog $src $dsttmp" command.
+ #
+ { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
+ { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
+ { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
+ { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
+
+ # If -C, don't bother to copy if it wouldn't change the file.
+ if $copy_on_change &&
+ old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` &&
+ new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` &&
+
+ eval "$initialize_posix_glob" &&
+ $posix_glob set -f &&
+ set X $old && old=:$2:$4:$5:$6 &&
+ set X $new && new=:$2:$4:$5:$6 &&
+ $posix_glob set +f &&
+
+ test "$old" = "$new" &&
+ $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
+ then
+ rm -f "$dsttmp"
+ else
+ # Rename the file to the real destination.
+ $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
+
+ # The rename failed, perhaps because mv can't rename something else
+ # to itself, or perhaps because mv is so ancient that it does not
+ # support -f.
+ {
+ # Now remove or move aside any old file at destination location.
+ # We try this two ways since rm can't unlink itself on some
+ # systems and the destination file might be busy for other
+ # reasons. In this case, the final cleanup might fail but the new
+ # file should still install successfully.
+ {
+ test ! -f "$dst" ||
+ $doit $rmcmd -f "$dst" 2>/dev/null ||
+ { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
+ { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
+ } ||
+ { echo "$0: cannot unlink or rename $dst" >&2
+ (exit 1); exit 1
+ }
+ } &&
+
+ # Now rename the file to the real destination.
+ $doit $mvcmd "$dsttmp" "$dst"
+ }
+ fi || exit 1
+
+ trap '' 0
+ fi
+done
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC"
+# time-stamp-end: "; # UTC"
+# End:
diff --git a/labview/phidget_labview.c b/labview/phidget_labview.c
new file mode 100644
index 0000000..380915b
--- /dev/null
+++ b/labview/phidget_labview.c
@@ -0,0 +1,429 @@
+#include "stdafx.h"
+
+#include "cphidget.h"
+#include "cphidgetmanager.h"
+#include "cphidgetdictionary.h"
+#include "cphidgetaccelerometer.h"
+#include "cphidgetadvancedservo.h"
+#include "cphidgetanalog.h"
+#include "cphidgetbridge.h"
+#include "cphidgetencoder.h"
+#include "cphidgetfrequencycounter.h"
+#include "cphidgetgps.h"
+#include "cphidgetinterfacekit.h"
+#include "cphidgetir.h"
+#include "cphidgetmanager.h"
+#include "cphidgetled.h"
+#include "cphidgetmotorcontrol.h"
+#include "cphidgetphsensor.h"
+#include "cphidgetrfid.h"
+#include "cphidgetservo.h"
+#include "cphidgetspatial.h"
+#include "cphidgetstepper.h"
+#include "cphidgettemperaturesensor.h"
+#include "cphidgettextlcd.h"
+#include "cphidgettextled.h"
+#include "cphidgetweightsensor.h"
+
+#include "csocket.h"
+
+#ifdef COMPILE_PHIDGETS_LABVIEW
+
+#include "phidget_labview.h"
+
+LV_CFHANDLE_0(, Attach, lvNothing)
+LV_CFHANDLE_0(, Detach, lvNothing)
+LV_CFHANDLE_0(, ServerConnect, lvNothing)
+LV_CFHANDLE_0(, ServerDisconnect, lvNothing)
+LV_CFHANDLE_BODY(, Error, lvError, void *userPtr, int val1, const char *val2)
+ data->val1 = val1;
+ data->val2=(LStrHandle)DSNewHandle(sizeof(int32)+255*sizeof(char));
+ memset(LStrBuf(*data->val2),'\0',255);
+ snprintf((char*)LStrBuf(*data->val2),255,"%s",val2);
+ LStrLen(*data->val2)=strlen(val2);
+
+ ret = PostLVUserEvent(ev, data);
+
+ DSDisposeHandle(data->val2);
+ DSDisposePtr(data);
+ return EPHIDGET_OK;
+}
+
+LV_CFHANDLE_2(Accelerometer, AccelerationChange, lvIndexedDouble, int, double)
+
+LV_CFHANDLE_2(AdvancedServo, PositionChange, lvIndexedDouble, int, double)
+LV_CFHANDLE_2(AdvancedServo, VelocityChange, lvIndexedDouble, int, double)
+LV_CFHANDLE_2(AdvancedServo, CurrentChange, lvIndexedDouble, int, double)
+
+LV_CFHANDLE_2(Bridge, BridgeData, lvIndexedDouble, int, double)
+
+LV_CFHANDLE_2(Encoder, InputChange, lvIndexedInt32, int, int)
+LV_CFHANDLE_3(Encoder, PositionChange, lvIndexedInt32Int32, int, int, int)
+
+LV_CFHANDLE_3(FrequencyCounter, Count, lvIndexedInt32Int32, int, int, int)
+
+LV_CFHANDLE_3(GPS, PositionChange, lvDoubleDoubleDouble, double, double, double)
+LV_CFHANDLE_1(GPS, PositionFixStatusChange, lvInt32, int)
+
+LV_CFHANDLE_2(InterfaceKit, InputChange, lvIndexedInt32, int, int)
+LV_CFHANDLE_2(InterfaceKit, OutputChange, lvIndexedInt32, int, int)
+LV_CFHANDLE_2(InterfaceKit, SensorChange, lvIndexedInt32, int, int)
+
+LV_CFHANDLE_BODY(IR, Code, lvIRCode, void *userPtr, unsigned char *val1, int val2, int val3, int val4)
+ data->val1=(lvArrUInt8DH)DSNewHandle(sizeof(int32)+val2*sizeof(uInt8));
+ (*(data->val1))->length = val2;
+ memcpy((*(data->val1))->data, val1, val2 * sizeof(uInt8));
+ data->val2 = val3;
+ data->val3 = val4;
+
+ ret = PostLVUserEvent(ev, data);
+
+ DSDisposeHandle(data->val1);
+ DSDisposePtr(data);
+ return EPHIDGET_OK;
+}
+LV_CFHANDLE_BODY(IR, RawData, lvInt32Array, void *userPtr, int *val1, int val2)
+ data->val1=(lvArrInt32DH)DSNewHandle(sizeof(int32)+val2*sizeof(int32));
+ (*(data->val1))->length = val2;
+ memcpy((*(data->val1))->data, val1, val2 * sizeof(int32));
+
+ ret = PostLVUserEvent(ev, data);
+
+ DSDisposeHandle(data->val1);
+ DSDisposePtr(data);
+ return EPHIDGET_OK;
+}
+LV_CFHANDLE_BODY(IR, Learn, lvIRLearn, void *userPtr, unsigned char *val1, int val2, CPhidgetIR_CodeInfoHandle val3)
+ data->val1=(lvArrUInt8DH)DSNewHandle(sizeof(int32)+val2*sizeof(uInt8));
+ (*(data->val1))->length = val2;
+ memcpy((*(data->val1))->data, val1, val2 * sizeof(uInt8));
+ data->val2 = *val3;
+
+ ret = PostLVUserEvent(ev, data);
+
+ DSDisposeHandle(data->val1);
+ DSDisposePtr(data);
+ return EPHIDGET_OK;
+}
+
+LV_CFHANDLE_2(MotorControl, InputChange, lvIndexedInt32, int, int)
+LV_CFHANDLE_2(MotorControl, VelocityChange, lvIndexedDouble, int, double)
+LV_CFHANDLE_2(MotorControl, CurrentChange, lvIndexedDouble, int, double)
+LV_CFHANDLE_3(MotorControl, EncoderPositionChange, lvIndexedInt32Int32, int, int, int)
+LV_CFHANDLE_2(MotorControl, EncoderPositionUpdate, lvIndexedInt32, int, int)
+LV_CFHANDLE_2(MotorControl, BackEMFUpdate, lvIndexedDouble, int, double)
+LV_CFHANDLE_2(MotorControl, SensorUpdate, lvIndexedInt32, int, int)
+LV_CFHANDLE_2(MotorControl, CurrentUpdate, lvIndexedDouble, int, double)
+
+LV_CFHANDLE_1(PHSensor, PHChange, lvDouble, double)
+
+LV_CFHANDLE_2(RFID, OutputChange, lvIndexedInt32, int, int)
+LV_CFHANDLE_BODY(RFID, Tag, lvUInt8Array, void *userPtr, unsigned char *val1)
+ data->val1=(lvArrUInt8DH)DSNewHandle(sizeof(int32)+5*sizeof(uInt8));
+ (*(data->val1))->length = 5;
+ memcpy((*(data->val1))->data, val1, 5 * sizeof(uInt8));
+
+ ret = PostLVUserEvent(ev, data);
+
+ DSDisposeHandle(data->val1);
+ DSDisposePtr(data);
+ return EPHIDGET_OK;
+}
+LV_CFHANDLE_BODY(RFID, TagLost, lvUInt8Array, void *userPtr, unsigned char *val1)
+ data->val1=(lvArrUInt8DH)DSNewHandle(sizeof(int32)+5*sizeof(uInt8));
+ (*(data->val1))->length = 5;
+ memcpy((*(data->val1))->data, val1, 5 * sizeof(uInt8));
+
+ ret = PostLVUserEvent(ev, data);
+
+ DSDisposeHandle(data->val1);
+ DSDisposePtr(data);
+ return EPHIDGET_OK;
+}
+LV_CFHANDLE_BODY(RFID, RawData, lvInt32Array, void *userPtr, int *val1, int val2)
+ data->val1=(lvArrInt32DH)DSNewHandle(sizeof(int32)+val2*sizeof(int32));
+ (*(data->val1))->length = val2;
+ memcpy((*(data->val1))->data, val1, val2 * sizeof(int32));
+
+ ret = PostLVUserEvent(ev, data);
+
+ DSDisposeHandle(data->val1);
+ DSDisposePtr(data);
+ return EPHIDGET_OK;
+}
+LV_CFHANDLE_BODY(RFID, TagAdvanced, lvRFIDTagAdvanced, void *userPtr, char *val1, CPhidgetRFID_TagInfoHandle val2)
+ data->val1=(LStrHandle)DSNewHandle(sizeof(int32)+255*sizeof(char));
+ memset(LStrBuf(*data->val1),'\0',255);
+ snprintf((char*)LStrBuf(*data->val1),255,"%s",val1);
+ LStrLen(*data->val1)=strlen(val1);
+ data->val2 = *val2;
+
+ ret = PostLVUserEvent(ev, data);
+
+ DSDisposeHandle(data->val1);
+ DSDisposePtr(data);
+ return EPHIDGET_OK;
+}
+LV_CFHANDLE_BODY(RFID, TagLostAdvanced, lvRFIDTagAdvanced, void *userPtr, char *val1, CPhidgetRFID_TagInfoHandle val2)
+ data->val1=(LStrHandle)DSNewHandle(sizeof(int32)+255*sizeof(char));
+ memset(LStrBuf(*data->val1),'\0',255);
+ snprintf((char*)LStrBuf(*data->val1),255,"%s",val1);
+ LStrLen(*data->val1)=strlen(val1);
+ data->val2 = *val2;
+
+ ret = PostLVUserEvent(ev, data);
+
+ DSDisposeHandle(data->val1);
+ DSDisposePtr(data);
+ return EPHIDGET_OK;
+}
+
+LV_CFHANDLE_2(Servo, PositionChange, lvIndexedDouble, int, double)
+
+LV_CFHANDLE_BODY(Spatial,SpatialData,lvSpatialData,void *userPtr,CPhidgetSpatial_SpatialEventDataHandle *val1,int val2)
+ DSDisposePtr(data);
+ {
+ int i;
+ for(i=0;i<val2;i++)
+ {
+ data = (lvSpatialData *)DSNewPtr(sizeof(lvSpatialData));
+ data->nothing = (int32)phid;
+#if 0
+ data->acceleration0 = val1[i]->acceleration[0];
+ data->acceleration1 = val1[i]->acceleration[1];
+ data->acceleration2 = val1[i]->acceleration[2];
+ data->angularRate0 = val1[i]->angularRate[0];
+ data->angularRate1 = val1[i]->angularRate[1];
+ data->angularRate2 = val1[i]->angularRate[2];
+ data->magneticField0 = val1[i]->magneticField[0];
+ data->magneticField1 = val1[i]->magneticField[1];
+ data->magneticField2 = val1[i]->magneticField[2];
+ data->microseconds = val1[i]->timestamp.microseconds;
+ data->seconds = val1[i]->timestamp.seconds;
+#else
+ data->val1 = *val1[i];
+#endif
+ ret = PostLVUserEvent(ev, data);
+ DSDisposePtr(data);
+ }
+ }
+ return EPHIDGET_OK;
+}
+
+LV_CFHANDLE_2(Stepper, InputChange, lvIndexedInt32, int, int)
+LV_CFHANDLE_2(Stepper, PositionChange, lvIndexedInt64, int, __int64)
+LV_CFHANDLE_2(Stepper, PositionChange32, lvIndexedInt32, int, int)
+LV_CFHANDLE_2(Stepper, VelocityChange, lvIndexedDouble, int, double)
+LV_CFHANDLE_2(Stepper, CurrentChange, lvIndexedDouble, int, double)
+
+LV_CFHANDLE_2(TemperatureSensor, TemperatureChange, lvIndexedDouble, int, double)
+
+LV_CFHANDLE_1(WeightSensor, WeightChange, lvDouble, double)
+
+//Manager
+
+int CCONV CPhidgetManager_OnAttach_LaviewHandler(CPhidgetHandle phid, void *userPtr);
+LABVIEW_EXPORT int CCONV CPhidgetManager_set_OnAttach_LabviewHandler(CPhidgetManagerHandle phidA, LVUserEventRef *lvEventRef)
+{
+ CPhidgetManagerHandle phid = (CPhidgetManagerHandle)phidA;
+ TESTPTR(phid);
+ if(!lvEventRef || !*lvEventRef)
+ {
+ phid->fptrAttachChange = NULL;
+ phid->fptrAttachChange = NULL;
+ }
+ else
+ {
+ phid->fptrAttachChangeptr = CPhidgetManager_OnAttach_LaviewHandler;
+ phid->fptrAttachChangeptr = lvEventRef;
+ }
+ return EPHIDGET_OK;
+}
+int CCONV CPhidgetManager_OnAttach_LaviewHandler(CPhidgetHandle phid, void *userPtr)
+{
+ LVUserEventRef ev = *(LVUserEventRef *)userPtr;
+ MgErr ret = 0;
+ lvManager *data;
+ data = (lvManager *)DSNewPtr(sizeof(lvManager));
+ data->val1 = (size_t)phid;
+ LV_CFHANDLE_END
+
+int CCONV CPhidgetManager_OnDetach_LaviewHandler(CPhidgetHandle phid, void *userPtr);
+LABVIEW_EXPORT int CCONV CPhidgetManager_set_OnDetach_LabviewHandler(CPhidgetManagerHandle phidA, LVUserEventRef *lvEventRef)
+{
+ CPhidgetManagerHandle phid = (CPhidgetManagerHandle)phidA;
+ TESTPTR(phid);
+ if(!lvEventRef || !*lvEventRef)
+ {
+ phid->fptrDetachChange = NULL;
+ phid->fptrDetachChange = NULL;
+ }
+ else
+ {
+ phid->fptrDetachChangeptr = CPhidgetManager_OnDetach_LaviewHandler;
+ phid->fptrDetachChangeptr = lvEventRef;
+ }
+ return EPHIDGET_OK;
+}
+int CCONV CPhidgetManager_OnDetach_LaviewHandler(CPhidgetHandle phid, void *userPtr)
+{
+ LVUserEventRef ev = *(LVUserEventRef *)userPtr;
+ MgErr ret = 0;
+ lvManager *data;
+ data = (lvManager *)DSNewPtr(sizeof(lvManager));
+ data->val1 = (size_t)phid;
+ LV_CFHANDLE_END
+
+LV_CFHANDLE_0(Manager, ServerConnect, lvNothing)
+LV_CFHANDLE_0(Manager, ServerDisconnect, lvNothing)
+LV_CFHANDLE_BODY(Manager, Error, lvError, void *userPtr, int val1, const char *val2)
+ data->val1 = val1;
+ data->val2=(LStrHandle)DSNewHandle(sizeof(int32)+255*sizeof(char));
+ memset(LStrBuf(*data->val2),'\0',255);
+ snprintf((char*)LStrBuf(*data->val2),255,"%s",val2);
+ LStrLen(*data->val2)=strlen(val2);
+
+ ret = PostLVUserEvent(ev, data);
+
+ DSDisposeHandle(data->val2);
+ DSDisposePtr(data);
+ return EPHIDGET_OK;
+}
+
+//Dictionary
+
+int CCONV CPhidgetDictionary_OnKeyChange_LaviewHandler(CPhidgetDictionaryHandle dict, void *userPtr, const char *key, const char *value, CPhidgetDictionary_keyChangeReason reason);
+LABVIEW_EXPORT int CCONV CPhidgetDictionary_set_OnKeyChange_LabviewHandler(CPhidgetDictionaryHandle dict, CPhidgetDictionaryListenerHandle *listen, const char *pattern, LVUserEventRef *lvEventRef)
+{
+ TESTPTR(dict);
+ if(lvEventRef && *lvEventRef)
+ CPhidgetDictionary_set_OnKeyChange_Handler(dict, listen, pattern, CPhidgetDictionary_OnKeyChange_LaviewHandler, lvEventRef);
+ else
+ return EPHIDGET_INVALIDARG;
+ return EPHIDGET_OK;
+}
+int CCONV CPhidgetDictionary_OnKeyChange_LaviewHandler(CPhidgetDictionaryHandle dict, void *userPtr, const char *key, const char *value, CPhidgetDictionary_keyChangeReason reason)
+{
+ LVUserEventRef ev = *(LVUserEventRef *)userPtr;
+ MgErr ret = 0;
+ lvDictionary *data;
+
+ data = (lvDictionary *)DSNewPtr(sizeof(lvDictionary));
+
+ //key
+ data->val1=(LStrHandle)DSNewHandle(sizeof(int32)+(strlen(key)+1)*sizeof(char));
+ memset(LStrBuf(*data->val1),'\0',(strlen(key)+1)*sizeof(char));
+ snprintf((char*)LStrBuf(*data->val1),(strlen(key)+1)*sizeof(char),"%s",key);
+ LStrLen(*data->val1)=strlen(key);
+
+ //value
+ data->val2=(LStrHandle)DSNewHandle(sizeof(int32)+(strlen(value)+1)*sizeof(char));
+ memset(LStrBuf(*data->val2),'\0',(strlen(value)+1)*sizeof(char));
+ snprintf((char*)LStrBuf(*data->val2),(strlen(value)+1)*sizeof(char),"%s",value);
+ LStrLen(*data->val2)=strlen(value);
+
+ data->val3 = reason;
+
+ ret = PostLVUserEvent(ev, data);
+
+ DSDisposeHandle(data->val1);
+ DSDisposeHandle(data->val2);
+ DSDisposePtr(data);
+
+ return EPHIDGET_OK;
+}
+LV_CFHANDLE_0(Dictionary, ServerConnect, lvNothing)
+LV_CFHANDLE_0(Dictionary, ServerDisconnect, lvNothing)
+LV_CFHANDLE_BODY(Dictionary, Error, lvError, void *userPtr, int val1, const char *val2)
+ data->val1 = val1;
+ data->val2=(LStrHandle)DSNewHandle(sizeof(int32)+255*sizeof(char));
+ memset(LStrBuf(*data->val2),'\0',255);
+ snprintf((char*)LStrBuf(*data->val2),255,"%s",val2);
+ LStrLen(*data->val2)=strlen(val2);
+
+ ret = PostLVUserEvent(ev, data);
+
+ DSDisposeHandle(data->val2);
+ DSDisposePtr(data);
+ return EPHIDGET_OK;
+}
+
+#else
+//On WindowsCE, we need stubs because they are in the exports.def file
+
+#define LV_NULL_FUNC(pname,param) int CCONV CPhidget##pname##_set_On##param##_LabviewHandler(CPhidget##pname##Handle phidA, void *lvEventRef) { return EPHIDGET_UNSUPPORTED; }
+
+LV_NULL_FUNC(, Attach)
+LV_NULL_FUNC(, Detach)
+LV_NULL_FUNC(, ServerConnect)
+LV_NULL_FUNC(, ServerDisconnect)
+LV_NULL_FUNC(, Error)
+
+LV_NULL_FUNC(Accelerometer, AccelerationChange)
+
+LV_NULL_FUNC(AdvancedServo, PositionChange)
+LV_NULL_FUNC(AdvancedServo, VelocityChange)
+LV_NULL_FUNC(AdvancedServo, CurrentChange)
+
+LV_NULL_FUNC(Bridge, BridgeData)
+
+LV_NULL_FUNC(Encoder, InputChange)
+LV_NULL_FUNC(Encoder, PositionChange)
+
+LV_NULL_FUNC(FrequencyCounter, Count)
+
+LV_NULL_FUNC(GPS, PositionChange)
+LV_NULL_FUNC(GPS, PositionFixStatusChange)
+
+LV_NULL_FUNC(InterfaceKit, InputChange)
+LV_NULL_FUNC(InterfaceKit, OutputChange)
+LV_NULL_FUNC(InterfaceKit, SensorChange)
+
+LV_NULL_FUNC(IR, Code)
+LV_NULL_FUNC(IR, RawData)
+LV_NULL_FUNC(IR, Learn)
+
+LV_NULL_FUNC(MotorControl, InputChange)
+LV_NULL_FUNC(MotorControl, VelocityChange)
+LV_NULL_FUNC(MotorControl, CurrentChange)
+LV_NULL_FUNC(MotorControl, EncoderPositionChange)
+LV_NULL_FUNC(MotorControl, EncoderPositionUpdate)
+LV_NULL_FUNC(MotorControl, BackEMFUpdate)
+LV_NULL_FUNC(MotorControl, SensorUpdate)
+LV_NULL_FUNC(MotorControl, CurrentUpdate)
+
+LV_NULL_FUNC(PHSensor, PHChange)
+
+LV_NULL_FUNC(RFID, OutputChange)
+LV_NULL_FUNC(RFID, Tag)
+LV_NULL_FUNC(RFID, TagLost)
+LV_NULL_FUNC(RFID, RawData)
+LV_NULL_FUNC(RFID, TagAdvanced)
+LV_NULL_FUNC(RFID, TagLostAdvanced)
+
+LV_NULL_FUNC(Servo, PositionChange)
+
+LV_NULL_FUNC(Spatial,SpatialData)
+
+LV_NULL_FUNC(Stepper, InputChange)
+LV_NULL_FUNC(Stepper, PositionChange)
+LV_NULL_FUNC(Stepper, PositionChange32)
+LV_NULL_FUNC(Stepper, VelocityChange)
+LV_NULL_FUNC(Stepper, CurrentChange)
+
+LV_NULL_FUNC(TemperatureSensor, TemperatureChange)
+
+LV_NULL_FUNC(WeightSensor, WeightChange)
+
+LV_NULL_FUNC(Manager, Attach)
+LV_NULL_FUNC(Manager, Detach)
+LV_NULL_FUNC(Manager, ServerConnect)
+LV_NULL_FUNC(Manager, ServerDisconnect)
+LV_NULL_FUNC(Manager, Error)
+
+LV_NULL_FUNC(Dictionary, KeyChange)
+LV_NULL_FUNC(Dictionary, ServerConnect)
+LV_NULL_FUNC(Dictionary, ServerDisconnect)
+LV_NULL_FUNC(Dictionary, Error)
+
+#endif
diff --git a/labview/phidget_labview.h b/labview/phidget_labview.h
new file mode 100644
index 0000000..fa96571
--- /dev/null
+++ b/labview/phidget_labview.h
@@ -0,0 +1,642 @@
+#ifndef __PHLABVIEW
+#define __PHLABVIEW
+#include "cphidget.h"
+
+#ifndef EXTERNALPROTO
+
+#ifdef _WINDOWS
+#include "windows/extcode.h"
+#elif _LINUX
+#include "extcode.h"
+#elif _MACOSX
+#include "macos/2010/extcode.h"
+#endif
+
+#else
+typedef unsigned int LVUserEventRef;
+#endif
+
+#ifdef _WINDOWS
+
+#define LABVIEW_STRUCT_PACK 1
+//#define LABVIEW_EXPORT __declspec(dllexport)
+#define LABVIEW_EXPORT
+
+#pragma pack(push)
+#pragma pack(show)
+
+#else
+
+#define LABVIEW_STRUCT_PACK 4
+#define LABVIEW_EXPORT
+
+#endif
+
+#define LV_CFHANDLE_BODY(pname,param,structtype, ...) \
+int CCONV CPhidget##pname##_On##param##_LaviewHandler(CPhidget##pname##Handle phid, __VA_ARGS__ ); \
+LABVIEW_EXPORT int CCONV CPhidget##pname##_set_On##param##_LabviewHandler(CPhidget##pname##Handle phidA, LVUserEventRef *lvEventRef) \
+{ \
+ CPhidget##pname##Handle phid = (CPhidget##pname##Handle)phidA; \
+ TESTPTR(phid); \
+ if(!lvEventRef || !*lvEventRef) \
+ { \
+ phid->fptr##param = NULL; \
+ phid->fptr##param##ptr = NULL; \
+ } \
+ else \
+ { \
+ phid->fptr##param = CPhidget##pname##_On##param##_LaviewHandler; \
+ phid->fptr##param##ptr = lvEventRef; \
+ } \
+ return EPHIDGET_OK; \
+} \
+int CCONV CPhidget##pname##_On##param##_LaviewHandler(CPhidget##pname##Handle phid, __VA_ARGS__ ) \
+{ \
+ LVUserEventRef ev = *(LVUserEventRef *)userPtr; \
+ MgErr ret = 0; \
+ structtype *data; \
+ data = (structtype *)DSNewPtr(sizeof(structtype)); \
+ data->nothing = (int32)phid; \
+
+#define LV_CFHANDLE_END \
+ ret = PostLVUserEvent(ev, data); \
+ DSDisposePtr(data); \
+ return EPHIDGET_OK; \
+}
+
+#define LV_CFHANDLE_0(pname,param,structtype) \
+ LV_CFHANDLE_BODY(pname,param,structtype,void *userPtr) \
+ LV_CFHANDLE_END
+
+#define LV_CFHANDLE_1(pname,param,structtype,datatype1) \
+ LV_CFHANDLE_BODY(pname,param,structtype,void *userPtr,datatype1 val1) \
+ data->val1 = val1; \
+ LV_CFHANDLE_END
+
+#define LV_CFHANDLE_2(pname,param,structtype,datatype1,datatype2) \
+ LV_CFHANDLE_BODY(pname,param,structtype,void *userPtr,datatype1 val1,datatype2 val2) \
+ data->val1 = val1; \
+ data->val2 = val2; \
+ LV_CFHANDLE_END
+
+#define LV_CFHANDLE_3(pname,param,structtype,datatype1,datatype2,datatype3) \
+ LV_CFHANDLE_BODY(pname,param,structtype,void *userPtr,datatype1 val1,datatype2 val2,datatype3 val3) \
+ data->val1 = val1; \
+ data->val2 = val2; \
+ data->val3 = val3; \
+ LV_CFHANDLE_END
+
+#define LV_CFHANDLE_4(pname,param,structtype,datatype1,datatype2,datatype3,datatype4) \
+ LV_CFHANDLE_BODY(pname,param,structtype,void *userPtr,datatype1 val1,datatype2 val2,datatype3 val3,datatype4 val4) \
+ data->val1 = val1; \
+ data->val2 = val2; \
+ data->val3 = val3; \
+ data->val4 = val4; \
+ LV_CFHANDLE_END
+
+#define LV_CHDREVENT(pname,param) LABVIEW_EXPORT int CCONV CPhidget##pname##_set_On##param##_LabviewHandler(CPhidget##pname##Handle phid, LVUserEventRef *lvEventRef);
+
+/** \defgroup phidlabview Phidget Labview Functions
+ * Calls specific to the Phidget Labview Support.
+ * @{
+ */
+
+/**
+ * Labview 1D int32 Array
+ */
+typedef struct {
+ int32 length; // Length of array
+ int32 data[1]; // Array
+} lvArrInt32, *lvArrInt32H, **lvArrInt32DH;
+
+/**
+ * Labview 1D uInt8 Array
+ */
+typedef struct {
+ int32 length; // Length of array
+ uInt8 data[1]; // Array
+} lvArrUInt8, *lvArrUInt8H, **lvArrUInt8DH;
+
+
+/* pack all of the following structures on Windows
+ * Note: Labview 64-bit seems to want double to be 8-byte aligned,
+ * but 32-bit wants them packed to presumably 4-byte
+ * ints, etc. need to be packed in close.
+ * mac/linux don't need anything special.
+ * http://zone.ni.com/reference/en-XX/help/371361G-01/lvconcepts/how_labview_stores_data_in_memory/
+ */
+#ifdef _WINDOWS
+#pragma pack(LABVIEW_STRUCT_PACK)
+#pragma pack(show)
+#endif
+
+/**
+ * Used for Labview events where only the event sender is returned
+ */
+typedef struct _lvNothing {
+ int32 nothing; /**< Not Used */
+} lvNothing;
+
+/**
+ * Used for Labview events that return an error code/string
+ */
+typedef struct _lvError {
+ int32 nothing; /**< Not Used */
+ int32 val1; /**< Error Code */
+ LStrHandle val2; /**< Error String */
+} lvError;
+
+/**
+ * Used for Labview events that return a double
+ */
+typedef struct _lvDouble {
+//Labview 64-bit windows wants doubles on 8-byte boundaries
+#ifdef _WINDOWS
+ size_t nothing; /**< Not Used */
+#else
+ int32 nothing; /**< Not Used */
+#endif
+ double val1; /**< Value */
+} lvDouble;
+
+/**
+ * Used for Labview events that return 3 doubles
+ */
+typedef struct _lvDoubleDoubleDouble {
+//Labview 64-bit windows wants doubles on 8-byte boundaries
+#ifdef _WINDOWS
+ size_t nothing; /**< Not Used */
+#else
+ int32 nothing; /**< Not Used */
+#endif
+ double val1; /**< Value 1 */
+ double val2; /**< Value 2 */
+ double val3; /**< Value 3 */
+} lvDoubleDoubleDouble;
+
+/**
+ * Used for Labview events that return an int32
+ */
+typedef struct _lvInt32 {
+ int32 nothing; /**< Not Used */
+ int32 val1; /**< Value */
+} lvInt32;
+
+/**
+ * Used for Labview events that return an indexed double
+ */
+typedef struct _lvIndexedDouble {
+ int32 nothing; /**< Not Used */
+ int32 val1; /**< Index */
+ double val2; /**< Value */
+} lvIndexedDouble;
+
+/**
+ * Used for Labview events that return an indexed int32
+ */
+typedef struct _lvIndexedInt32 {
+ int32 nothing; /**< Not Used */
+ int32 val1; /**< Index */
+ int32 val2; /**< Value */
+} lvIndexedInt32;
+
+/**
+ * Used for Labview events that return two indexed int32s
+ */
+typedef struct _lvIndexedInt32Int32 {
+ int32 nothing; /**< Not Used */
+ int32 val1; /**< Index */
+ int32 val2; /**< Value 1 */
+ int32 val3; /**< Value 2 */
+} lvIndexedInt32Int32;
+
+/**
+ * Used for Labview events that return an indexed int64
+ */
+typedef struct _lvIndexedInt64 {
+ int32 nothing; /**< Not Used */
+ int32 val1; /**< Index */
+ int64 val2; /**< Value */
+} lvIndexedInt64;
+
+/**
+ * Used for Labview events that return an int32 array
+ */
+typedef struct _lvInt32Array {
+ lvArrInt32DH val1; /**< Data */
+ int32 nothing; /**< Not Used */
+} lvInt32Array;
+
+/**
+ * Used for Labview events that return an uInt8 array
+ */
+typedef struct _lvUInt8Array {
+ lvArrUInt8DH val1; /**< Data */
+ int32 nothing; /**< Not Used */
+} lvUInt8Array;
+
+/**
+ * Used for Labview events that return an IR Code
+ */
+typedef struct _lvIRCode {
+ lvArrUInt8DH val1; /**< Code data */
+ int32 val2; /**< bit count */
+ int32 val3; /**< repeat */
+ int32 nothing; /**< Not Used */
+} lvIRCode;
+
+/**
+ * Used for Labview events that return IR Learn data
+ */
+typedef struct _lvIRLearn {
+ lvArrUInt8DH val1; /**< Code data */
+ CPhidgetIR_CodeInfo val2; /**< code parameters */
+ int32 nothing; /**< Not Used */
+} lvIRLearn;
+
+/**
+ * Used for Labview events that return an rfid tag (advanced)
+ */
+typedef struct _lvRFIDTagAdvanced {
+ int32 nothing; /**< Not Used */
+ LStrHandle val1; /**< Tag String */
+ CPhidgetRFID_TagInfo val2; /**< tag properties */
+} lvRFIDTagAdvanced;
+
+/**
+ * Used for Labview events that return spatial data
+ */
+typedef struct _lvSpatialData {
+//Labview 64-bit windows wants doubles on 8-byte boundaries
+#ifdef _WINDOWS
+ size_t nothing; /**< Not Used */
+#else
+ int32 nothing; /**< Not Used */
+#endif
+ CPhidgetSpatial_SpatialEventData val1; /**< Spatial Data */
+} lvSpatialData;
+
+
+/**
+ * Used for Labview manager attach and detach events
+ */
+typedef struct _lvManager {
+ __int64 val1; /**< Handle to a phidget */
+} lvManager;
+
+/**
+ * Used for Labview dictionary key change events
+ */
+typedef struct _lvDictionary {
+ LStrHandle val1; /**< key String */
+ LStrHandle val2; /**< value String */
+ CPhidgetDictionary_keyChangeReason val3; /**< key change reason */
+} lvDictionary;
+
+
+#ifdef _WINDOWS
+//Restore default packing
+#pragma pack(pop)
+#pragma pack(show)
+#endif
+
+/**
+ * Sets up a Labview event callback for the Attach event.
+ * Event callback returns an \ref _lvNothing.
+ * @param phid An attached phidget handle.
+ * @param lvEventRef Lavbiew user event ref
+ */
+LV_CHDREVENT(,Attach)
+/**
+ * Sets up a Labview event callback for the Detach event.
+ * Event callback returns an \ref _lvNothing.
+ * @param phid An attached phidget handle.
+ * @param lvEventRef Lavbiew user event ref
+ */
+LV_CHDREVENT(,Detach)
+/**
+ * Sets up a Labview event callback for the ServerConnect event.
+ * Event callback returns an \ref _lvNothing.
+ * @param phid An attached phidget handle.
+ * @param lvEventRef Lavbiew user event ref
+ */
+LV_CHDREVENT(,ServerConnect)
+/**
+ * Sets up a Labview event callback for the ServerDisconnect event.
+ * Event callback returns an \ref _lvNothing.
+ * @param phid An attached phidget handle.
+ * @param lvEventRef Lavbiew user event ref
+ */
+LV_CHDREVENT(,ServerDisconnect)
+/**
+ * Sets up a Labview event callback for the Error event.
+ * Event callback returns an \ref _lvError.
+ * @param phid An attached phidget handle.
+ * @param lvEventRef Lavbiew user event ref
+ */
+LV_CHDREVENT(,Error)
+
+/**
+ * Sets up a Labview event callback for the AccelerationChange event.
+ * Event callback returns an \ref _lvIndexedDouble.
+ * @param phid An attached phidget handle.
+ * @param lvEventRef Lavbiew user event ref
+ */
+LV_CHDREVENT(Accelerometer,AccelerationChange)
+
+/**
+ * Sets up a Labview event callback for the PositionChange event.
+ * Event callback returns an \ref _lvIndexedDouble.
+ * @param phid An attached phidget handle.
+ * @param lvEventRef Lavbiew user event ref
+ */
+LV_CHDREVENT(AdvancedServo, PositionChange)
+/**
+ * Sets up a Labview event callback for the VelocityChange event.
+ * Event callback returns an \ref _lvIndexedDouble.
+ * @param phid An attached phidget handle.
+ * @param lvEventRef Lavbiew user event ref
+ */
+LV_CHDREVENT(AdvancedServo, VelocityChange)
+/**
+ * Sets up a Labview event callback for the CurrentChange event.
+ * Event callback returns an \ref _lvIndexedDouble.
+ * @param phid An attached phidget handle.
+ * @param lvEventRef Lavbiew user event ref
+ */
+LV_CHDREVENT(AdvancedServo, CurrentChange)
+
+/**
+ * Sets up a Labview event callback for the BridgeData event.
+ * Event callback returns an \ref _lvIndexedDouble.
+ * @param phid An attached phidget handle.
+ * @param lvEventRef Lavbiew user event ref
+ */
+LV_CHDREVENT(Bridge, BridgeData)
+
+/**
+ * Sets up a Labview event callback for the InputChange event.
+ * Event callback returns an \ref _lvIndexedInt32.
+ * @param phid An attached phidget handle.
+ * @param lvEventRef Lavbiew user event ref
+ */
+LV_CHDREVENT(Encoder, InputChange)
+/**
+ * Sets up a Labview event callback for the PositionChange event.
+ * Event callback returns an \ref _lvIndexedInt32Int32.
+ * @param phid An attached phidget handle.
+ * @param lvEventRef Lavbiew user event ref
+ */
+LV_CHDREVENT(Encoder, PositionChange)
+
+/**
+ * Sets up a Labview event callback for the Count event.
+ * Event callback returns an \ref _lvIndexedInt32Int32.
+ * @param phid An attached phidget handle.
+ * @param lvEventRef Lavbiew user event ref
+ */
+LV_CHDREVENT(FrequencyCounter, Count)
+
+/**
+ * Sets up a Labview event callback for the PositionChange event.
+ * Event callback returns an \ref _lvDoubleDoubleDouble.
+ * @param phid An attached phidget handle.
+ * @param lvEventRef Lavbiew user event ref
+ */
+LV_CHDREVENT(GPS, PositionChange)
+/**
+ * Sets up a Labview event callback for the PositionFixStatusChange event.
+ * Event callback returns an \ref _lvInt32.
+ * @param phid An attached phidget handle.
+ * @param lvEventRef Lavbiew user event ref
+ */
+LV_CHDREVENT(GPS, PositionFixStatusChange)
+
+/**
+ * Sets up a Labview event callback for the InputChange event.
+ * Event callback returns an \ref _lvIndexedInt32.
+ * @param phid An attached phidget handle.
+ * @param lvEventRef Lavbiew user event ref
+ */
+LV_CHDREVENT(InterfaceKit, InputChange)
+/**
+ * Sets up a Labview event callback for the OutputChange event.
+ * Event callback returns an \ref _lvIndexedInt32.
+ * @param phid An attached phidget handle.
+ * @param lvEventRef Lavbiew user event ref
+ */
+LV_CHDREVENT(InterfaceKit, OutputChange)
+/**
+ * Sets up a Labview event callback for the SensorChange event.
+ * Event callback returns an \ref _lvIndexedInt32.
+ * @param phid An attached phidget handle.
+ * @param lvEventRef Lavbiew user event ref
+ */
+LV_CHDREVENT(InterfaceKit, SensorChange)
+
+/**
+ * Sets up a Labview event callback for the Code event.
+ * Event callback returns an \ref _lvIRCode.
+ * @param phid An attached phidget handle.
+ * @param lvEventRef Lavbiew user event ref
+ */
+LV_CHDREVENT(IR, Code)
+/**
+ * Sets up a Labview event callback for the RawData event.
+ * Event callback returns an \ref _lvIRRawData.
+ * @param phid An attached phidget handle.
+ * @param lvEventRef Lavbiew user event ref
+ */
+LV_CHDREVENT(IR, RawData)
+/**
+ * Sets up a Labview event callback for the Learn event.
+ * Event callback returns an \ref _lvIRLearn.
+ * @param phid An attached phidget handle.
+ * @param lvEventRef Lavbiew user event ref
+ */
+LV_CHDREVENT(IR, Learn)
+
+/**
+ * Sets up a Labview event callback for the InputChange event.
+ * Event callback returns an \ref _lvIndexedInt32.
+ * @param phid An attached phidget handle.
+ * @param lvEventRef Lavbiew user event ref
+ */
+LV_CHDREVENT(MotorControl, InputChange)
+/**
+ * Sets up a Labview event callback for the VelocityChange event.
+ * Event callback returns an \ref _lvIndexedDouble.
+ * @param phid An attached phidget handle.
+ * @param lvEventRef Lavbiew user event ref
+ */
+LV_CHDREVENT(MotorControl, VelocityChange)
+/**
+ * Sets up a Labview event callback for the CurrentChange event.
+ * Event callback returns an \ref _lvIndexedDouble.
+ * @param phid An attached phidget handle.
+ * @param lvEventRef Lavbiew user event ref
+ */
+LV_CHDREVENT(MotorControl, CurrentChange)
+/**
+ * Sets up a Labview event callback for the EncoderPositionChange event.
+ * Event callback returns an \ref _lvIndexedInt32Int32.
+ * @param phid An attached phidget handle.
+ * @param lvEventRef Lavbiew user event ref
+ */
+LV_CHDREVENT(MotorControl, EncoderPositionChange)
+/**
+ * Sets up a Labview event callback for the EncoderPositionUpdate event.
+ * Event callback returns an \ref _lvIndexedInt32.
+ * @param phid An attached phidget handle.
+ * @param lvEventRef Lavbiew user event ref
+ */
+LV_CHDREVENT(MotorControl, EncoderPositionUpdate)
+/**
+ * Sets up a Labview event callback for the BackEMFUpdate event.
+ * Event callback returns an \ref _lvIndexedDouble.
+ * @param phid An attached phidget handle.
+ * @param lvEventRef Lavbiew user event ref
+ */
+LV_CHDREVENT(MotorControl, BackEMFUpdate)
+/**
+ * Sets up a Labview event callback for the SensorUpdate event.
+ * Event callback returns an \ref _lvIndexedInt32.
+ * @param phid An attached phidget handle.
+ * @param lvEventRef Lavbiew user event ref
+ */
+LV_CHDREVENT(MotorControl, SensorUpdate)
+/**
+ * Sets up a Labview event callback for the CurrentUpdate event.
+ * Event callback returns an \ref _lvIndexedDouble.
+ * @param phid An attached phidget handle.
+ * @param lvEventRef Lavbiew user event ref
+ */
+LV_CHDREVENT(MotorControl, CurrentUpdate)
+
+/**
+ * Sets up a Labview event callback for the PHChange event.
+ * Event callback returns an \ref _lvDouble.
+ * @param phid An attached phidget handle.
+ * @param lvEventRef Lavbiew user event ref
+ */
+LV_CHDREVENT(PHSensor, PHChange)
+
+/**
+ * Sets up a Labview event callback for the OutputChange event.
+ * Event callback returns an \ref _lvIndexedInt32.
+ * @param phid An attached phidget handle.
+ * @param lvEventRef Lavbiew user event ref
+ */
+LV_CHDREVENT(RFID, OutputChange)
+/**
+ * Sets up a Labview event callback for the Tag event.
+ * Event callback returns an \ref _lvRFIDTag.
+ * @param phid An attached phidget handle.
+ * @param lvEventRef Lavbiew user event ref
+ */
+LV_CHDREVENT(RFID, Tag)
+/**
+ * Sets up a Labview event callback for the TagLost event.
+ * Event callback returns an \ref _lvRFIDTag.
+ * @param phid An attached phidget handle.
+ * @param lvEventRef Lavbiew user event ref
+ */
+LV_CHDREVENT(RFID, TagLost)
+/**
+ * Sets up a Labview event callback for the RawData event.
+ * Event callback returns an \ref _lvRFIDRawData.
+ * @param phid An attached phidget handle.
+ * @param lvEventRef Lavbiew user event ref
+ */
+LV_CHDREVENT(RFID, RawData)
+/**
+ * Sets up a Labview event callback for the TagAdvanced event.
+ * Event callback returns an \ref _lvRFIDTagAdvanced.
+ * @param phid An attached phidget handle.
+ * @param lvEventRef Lavbiew user event ref
+ */
+LV_CHDREVENT(RFID, TagAdvanced)
+/**
+ * Sets up a Labview event callback for the TagLostAdvanced event.
+ * Event callback returns an \ref _lvRFIDTagAdvanced.
+ * @param phid An attached phidget handle.
+ * @param lvEventRef Lavbiew user event ref
+ */
+LV_CHDREVENT(RFID, TagLostAdvanced)
+
+/**
+ * Sets up a Labview event callback for the PositionChange event.
+ * Event callback returns an \ref _lvIndexedDouble.
+ * @param phid An attached phidget handle.
+ * @param lvEventRef Lavbiew user event ref
+ */
+LV_CHDREVENT(Servo, PositionChange)
+
+/**
+ * Sets up a Labview event callback for the SpatialData event.
+ * Event callback returns an \ref _lvSpatialData.
+ * @param phid An attached phidget handle.
+ * @param lvEventRef Lavbiew user event ref
+ */
+LV_CHDREVENT(Spatial, SpatialData)
+
+/**
+ * Sets up a Labview event callback for the InputChange event.
+ * Event callback returns an \ref _lvIndexedInt32.
+ * @param phid An attached phidget handle.
+ * @param lvEventRef Lavbiew user event ref
+ */
+LV_CHDREVENT(Stepper, InputChange)
+/**
+ * Sets up a Labview event callback for the PositionChange event.
+ * Event callback returns an \ref _lvIndexedInt64.
+ * @param phid An attached phidget handle.
+ * @param lvEventRef Lavbiew user event ref
+ */
+LV_CHDREVENT(Stepper, PositionChange)
+LV_CHDREVENT(Stepper, PositionChange32)
+/**
+ * Sets up a Labview event callback for the VelocityChange event.
+ * Event callback returns an \ref _lvIndexedDouble.
+ * @param phid An attached phidget handle.
+ * @param lvEventRef Lavbiew user event ref
+ */
+LV_CHDREVENT(Stepper, VelocityChange)
+/**
+ * Sets up a Labview event callback for the CurrentChange event.
+ * Event callback returns an \ref _lvIndexedDouble.
+ * @param phid An attached phidget handle.
+ * @param lvEventRef Lavbiew user event ref
+ */
+LV_CHDREVENT(Stepper, CurrentChange)
+
+/**
+ * Sets up a Labview event callback for the TemperatureChange event.
+ * Event callback returns an \ref _lvIndexedDouble.
+ * @param phid An attached phidget handle.
+ * @param lvEventRef Lavbiew user event ref
+ */
+LV_CHDREVENT(TemperatureSensor, TemperatureChange)
+
+/**
+ * Sets up a Labview event callback for the WeightChange event.
+ * Event callback returns an \ref _lvDouble.
+ * @param phid An attached phidget handle.
+ * @param lvEventRef Lavbiew user event ref
+ */
+LV_CHDREVENT(WeightSensor, WeightChange)
+
+LV_CHDREVENT(Manager,Attach)
+LV_CHDREVENT(Manager,Detach)
+LV_CHDREVENT(Manager,ServerConnect)
+LV_CHDREVENT(Manager,ServerDisconnect)
+LV_CHDREVENT(Manager,Error)
+
+LABVIEW_EXPORT int CCONV CPhidgetDictionary_set_OnKeyChange_LabviewHandler(CPhidgetDictionaryHandle dict, CPhidgetDictionaryListenerHandle *listen, const char *pattern, LVUserEventRef *lvEventRef);
+LV_CHDREVENT(Dictionary,ServerConnect)
+LV_CHDREVENT(Dictionary,ServerDisconnect)
+LV_CHDREVENT(Dictionary,Error)
+
+/** @} */
+
+#endif
diff --git a/linux/avahi-client/client.h b/linux/avahi-client/client.h
new file mode 100644
index 0000000..52fccb8
--- /dev/null
+++ b/linux/avahi-client/client.h
@@ -0,0 +1,119 @@
+#ifndef fooclienthfoo
+#define fooclienthfoo
+
+/* $Id: client.h 1477 2007-05-09 19:45:54Z lennart $ */
+
+/***
+ This file is part of avahi.
+
+ avahi is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ avahi is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
+ Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with avahi; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA.
+***/
+
+#include <inttypes.h>
+
+#include <avahi-common/cdecl.h>
+#include <avahi-common/address.h>
+#include <avahi-common/strlst.h>
+#include <avahi-common/defs.h>
+#include <avahi-common/watch.h>
+#include <avahi-common/gccmacro.h>
+
+/** \file client.h Definitions and functions for the client API over D-Bus */
+
+AVAHI_C_DECL_BEGIN
+
+/** A connection context */
+typedef struct AvahiClient AvahiClient;
+
+/** States of a client object, a superset of AvahiServerState */
+typedef enum {
+ AVAHI_CLIENT_S_REGISTERING = AVAHI_SERVER_REGISTERING, /**< Server state: REGISTERING */
+ AVAHI_CLIENT_S_RUNNING = AVAHI_SERVER_RUNNING, /**< Server state: RUNNING */
+ AVAHI_CLIENT_S_COLLISION = AVAHI_SERVER_COLLISION, /**< Server state: COLLISION */
+ AVAHI_CLIENT_FAILURE = 100, /**< Some kind of error happened on the client side */
+ AVAHI_CLIENT_CONNECTING = 101 /**< We're still connecting. This state is only entered when AVAHI_CLIENT_NO_FAIL has been passed to avahi_client_new() and the daemon is not yet available. */
+} AvahiClientState;
+
+typedef enum {
+ AVAHI_CLIENT_IGNORE_USER_CONFIG = 1, /**< Don't read user configuration */
+ AVAHI_CLIENT_NO_FAIL = 2 /**< Don't fail if the daemon is not available when avahi_client_new() is called, instead enter AVAHI_CLIENT_CONNECTING state and wait for the daemon to appear */
+} AvahiClientFlags;
+
+/** The function prototype for the callback of an AvahiClient */
+typedef void (*AvahiClientCallback) (
+ AvahiClient *s,
+ AvahiClientState state /**< The new state of the client */,
+ void* userdata /**< The user data that was passed to avahi_client_new() */);
+
+/** @{ \name Construction and destruction */
+
+/** Creates a new client instance */
+AvahiClient* avahi_client_new (
+ const AvahiPoll *poll_api /**< The abstract event loop API to use */,
+ AvahiClientFlags flags /**< Some flags to modify the behaviour of the client library */,
+ AvahiClientCallback callback /**< A callback that is called whenever the state of the client changes. This may be NULL. Please note that this function is called for the first time from within the avahi_client_new() context! Thus, in the callback you should not make use of global variables that are initialized only after your call to avahi_client_new(). A common mistake is to store the AvahiClient pointer returned by avahi_client_new() in a global variable and assume that this global variable already contains the valid pointer when the callback is called for the first time. A work-around for this is to always use the AvahiClient pointer passed to the callback function instead of the global pointer. */,
+ void *userdata /**< Some arbitrary user data pointer that will be passed to the callback function */,
+ int *error /**< If creation of the client fails, this integer will contain the error cause. May be NULL if you aren't interested in the reason why avahi_client_new() failed. */);
+
+/** Free a client instance. This will automatically free all
+ * associated browser, resolve and entry group objects. All pointers
+ * to such objects become invalid! */
+void avahi_client_free(AvahiClient *client);
+
+/** @} */
+
+/** @{ \name Properties */
+
+/** Get the version of the server */
+const char* avahi_client_get_version_string (AvahiClient*);
+
+/** Get host name */
+const char* avahi_client_get_host_name (AvahiClient*);
+
+/** Set host name. \since 0.6.13 */
+int avahi_client_set_host_name(AvahiClient*, const char *name);
+
+/** Get domain name */
+const char* avahi_client_get_domain_name (AvahiClient*);
+
+/** Get FQDN domain name */
+const char* avahi_client_get_host_name_fqdn (AvahiClient*);
+
+/** Get state */
+AvahiClientState avahi_client_get_state(AvahiClient *client);
+
+/** @{ \name Error Handling */
+
+/** Get the last error number. See avahi_strerror() for converting this error code into a human readable string. */
+int avahi_client_errno (AvahiClient*);
+
+/** @} */
+
+/** \cond fulldocs */
+/** Return the local service cookie. returns AVAHI_SERVICE_COOKIE_INVALID on failure. */
+uint32_t avahi_client_get_local_service_cookie(AvahiClient *client);
+/** \endcond */
+
+/** @{ \name Libc NSS Support */
+
+/** Return 1 if gethostbyname() supports mDNS lookups, 0 otherwise. \since 0.6.5 */
+int avahi_nss_support(void);
+
+/** @} */
+
+AVAHI_C_DECL_END
+
+#endif
diff --git a/linux/avahi-client/lookup.h b/linux/avahi-client/lookup.h
new file mode 100644
index 0000000..c417fcf
--- /dev/null
+++ b/linux/avahi-client/lookup.h
@@ -0,0 +1,295 @@
+#ifndef fooclientlookuphfoo
+#define fooclientlookuphfoo
+
+/* $Id: lookup.h 1477 2007-05-09 19:45:54Z lennart $ */
+
+/***
+ This file is part of avahi.
+
+ avahi is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ avahi is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
+ Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with avahi; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA.
+***/
+
+#include <inttypes.h>
+
+#include <avahi-common/cdecl.h>
+#include <avahi-common/address.h>
+#include <avahi-common/strlst.h>
+#include <avahi-common/defs.h>
+#include <avahi-common/watch.h>
+#include <avahi-common/gccmacro.h>
+
+#include <avahi-client/client.h>
+
+/** \file avahi-client/lookup.h Lookup Client API */
+
+/** \example client-browse-services.c Example how to browse for DNS-SD
+ * services using the client interface to avahi-daemon. */
+
+AVAHI_C_DECL_BEGIN
+
+/** @{ \name Domain Browser */
+
+/** A domain browser object */
+typedef struct AvahiDomainBrowser AvahiDomainBrowser;
+
+/** The function prototype for the callback of an AvahiDomainBrowser */
+typedef void (*AvahiDomainBrowserCallback) (
+ AvahiDomainBrowser *b,
+ AvahiIfIndex interface,
+ AvahiProtocol protocol,
+ AvahiBrowserEvent event,
+ const char *domain,
+ AvahiLookupResultFlags flags,
+ void *userdata);
+
+/** Browse for domains on the local network */
+AvahiDomainBrowser* avahi_domain_browser_new (
+ AvahiClient *client,
+ AvahiIfIndex interface,
+ AvahiProtocol protocol,
+ const char *domain,
+ AvahiDomainBrowserType btype,
+ AvahiLookupFlags flags,
+ AvahiDomainBrowserCallback callback,
+ void *userdata);
+
+/** Get the parent client of an AvahiDomainBrowser object */
+AvahiClient* avahi_domain_browser_get_client (AvahiDomainBrowser *);
+
+/** Cleans up and frees an AvahiDomainBrowser object */
+int avahi_domain_browser_free (AvahiDomainBrowser *);
+
+/** @} */
+
+/** @{ \name Service Browser */
+
+/** A service browser object */
+typedef struct AvahiServiceBrowser AvahiServiceBrowser;
+
+/** The function prototype for the callback of an AvahiServiceBrowser */
+typedef void (*AvahiServiceBrowserCallback) (
+ AvahiServiceBrowser *b,
+ AvahiIfIndex interface,
+ AvahiProtocol protocol,
+ AvahiBrowserEvent event,
+ const char *name,
+ const char *type,
+ const char *domain,
+ AvahiLookupResultFlags flags,
+ void *userdata);
+
+/** Browse for services of a type on the local network */
+AvahiServiceBrowser* avahi_service_browser_new (
+ AvahiClient *client,
+ AvahiIfIndex interface,
+ AvahiProtocol protocol,
+ const char *type,
+ const char *domain,
+ AvahiLookupFlags flags,
+ AvahiServiceBrowserCallback callback,
+ void *userdata);
+
+/** Get the parent client of an AvahiServiceBrowser object */
+AvahiClient* avahi_service_browser_get_client (AvahiServiceBrowser *);
+
+/** Cleans up and frees an AvahiServiceBrowser object */
+int avahi_service_browser_free (AvahiServiceBrowser *);
+
+/** @} */
+
+/** \cond fulldocs */
+/** A service type browser object */
+typedef struct AvahiServiceTypeBrowser AvahiServiceTypeBrowser;
+
+/** The function prototype for the callback of an AvahiServiceTypeBrowser */
+typedef void (*AvahiServiceTypeBrowserCallback) (
+ AvahiServiceTypeBrowser *b,
+ AvahiIfIndex interface,
+ AvahiProtocol protocol,
+ AvahiBrowserEvent event,
+ const char *type,
+ const char *domain,
+ AvahiLookupResultFlags flags,
+ void *userdata);
+
+/** Browse for service types on the local network */
+AvahiServiceTypeBrowser* avahi_service_type_browser_new (
+ AvahiClient *client,
+ AvahiIfIndex interface,
+ AvahiProtocol protocol,
+ const char *domain,
+ AvahiLookupFlags flags,
+ AvahiServiceTypeBrowserCallback callback,
+ void *userdata);
+
+/** Get the parent client of an AvahiServiceTypeBrowser object */
+AvahiClient* avahi_service_type_browser_get_client (AvahiServiceTypeBrowser *);
+
+/** Cleans up and frees an AvahiServiceTypeBrowser object */
+int avahi_service_type_browser_free (AvahiServiceTypeBrowser *);
+
+/** \endcond */
+
+/** @{ \name Service Resolver */
+
+/** A service resolver object */
+typedef struct AvahiServiceResolver AvahiServiceResolver;
+
+/** The function prototype for the callback of an AvahiServiceResolver */
+typedef void (*AvahiServiceResolverCallback) (
+ AvahiServiceResolver *r,
+ AvahiIfIndex interface,
+ AvahiProtocol protocol,
+ AvahiResolverEvent event,
+ const char *name,
+ const char *type,
+ const char *domain,
+ const char *host_name,
+ const AvahiAddress *a,
+ uint16_t port,
+ AvahiStringList *txt,
+ AvahiLookupResultFlags flags,
+ void *userdata);
+
+/** Create a new service resolver object. Please make sure to pass all
+ * the service data you received via avahi_service_browser_new()'s
+ * callback function, especially interface and protocol. */
+AvahiServiceResolver * avahi_service_resolver_new(
+ AvahiClient *client,
+ AvahiIfIndex interface,
+ AvahiProtocol protocol,
+ const char *name,
+ const char *type,
+ const char *domain,
+ AvahiProtocol aprotocol,
+ AvahiLookupFlags flags,
+ AvahiServiceResolverCallback callback,
+ void *userdata);
+
+/** Get the parent client of an AvahiServiceResolver object */
+AvahiClient* avahi_service_resolver_get_client (AvahiServiceResolver *);
+
+/** Free a service resolver object */
+int avahi_service_resolver_free(AvahiServiceResolver *r);
+
+/** @} */
+
+/** \cond fulldocs */
+/** A service resolver object */
+typedef struct AvahiHostNameResolver AvahiHostNameResolver;
+
+/** The function prototype for the callback of an AvahiHostNameResolver */
+typedef void (*AvahiHostNameResolverCallback) (
+ AvahiHostNameResolver *r,
+ AvahiIfIndex interface,
+ AvahiProtocol protocol,
+ AvahiResolverEvent event,
+ const char *name,
+ const AvahiAddress *a,
+ AvahiLookupResultFlags flags,
+ void *userdata);
+
+/** Create a new hostname resolver object */
+AvahiHostNameResolver * avahi_host_name_resolver_new(
+ AvahiClient *client,
+ AvahiIfIndex interface,
+ AvahiProtocol protocol,
+ const char *name,
+ AvahiProtocol aprotocol,
+ AvahiLookupFlags flags,
+ AvahiHostNameResolverCallback callback,
+ void *userdata);
+
+/** Get the parent client of an AvahiHostNameResolver object */
+AvahiClient* avahi_host_name_resolver_get_client (AvahiHostNameResolver *);
+
+/** Free a hostname resolver object */
+int avahi_host_name_resolver_free(AvahiHostNameResolver *r);
+
+/** An address resolver object */
+typedef struct AvahiAddressResolver AvahiAddressResolver;
+
+/** The function prototype for the callback of an AvahiAddressResolver */
+typedef void (*AvahiAddressResolverCallback) (
+ AvahiAddressResolver *r,
+ AvahiIfIndex interface,
+ AvahiProtocol protocol,
+ AvahiResolverEvent event,
+ const AvahiAddress *a,
+ const char *name,
+ AvahiLookupResultFlags flags,
+ void *userdata);
+
+/** Create a new address resolver object from an AvahiAddress object */
+AvahiAddressResolver* avahi_address_resolver_new(
+ AvahiClient *client,
+ AvahiIfIndex interface,
+ AvahiProtocol protocol,
+ const AvahiAddress *a,
+ AvahiLookupFlags flags,
+ AvahiAddressResolverCallback callback,
+ void *userdata);
+
+/** Get the parent client of an AvahiAddressResolver object */
+AvahiClient* avahi_address_resolver_get_client (AvahiAddressResolver *);
+
+/** Free a AvahiAddressResolver resolver object */
+int avahi_address_resolver_free(AvahiAddressResolver *r);
+
+/** \endcond */
+
+/** @{ \name Record Browser */
+
+/** A record browser object */
+typedef struct AvahiRecordBrowser AvahiRecordBrowser;
+
+/** The function prototype for the callback of an AvahiRecordBrowser */
+typedef void (*AvahiRecordBrowserCallback) (
+ AvahiRecordBrowser *b,
+ AvahiIfIndex interface,
+ AvahiProtocol protocol,
+ AvahiBrowserEvent event,
+ const char *name,
+ uint16_t clazz,
+ uint16_t type,
+ const void *rdata,
+ size_t size,
+ AvahiLookupResultFlags flags,
+ void *userdata);
+
+/** Browse for records of a type on the local network */
+AvahiRecordBrowser* avahi_record_browser_new(
+ AvahiClient *client,
+ AvahiIfIndex interface,
+ AvahiProtocol protocol,
+ const char *name,
+ uint16_t clazz,
+ uint16_t type,
+ AvahiLookupFlags flags,
+ AvahiRecordBrowserCallback callback,
+ void *userdata);
+
+/** Get the parent client of an AvahiRecordBrowser object */
+AvahiClient* avahi_record_browser_get_client(AvahiRecordBrowser *);
+
+/** Cleans up and frees an AvahiRecordBrowser object */
+int avahi_record_browser_free(AvahiRecordBrowser *);
+
+/** @} */
+
+AVAHI_C_DECL_END
+
+#endif
diff --git a/linux/avahi-client/publish.h b/linux/avahi-client/publish.h
new file mode 100644
index 0000000..714a689
--- /dev/null
+++ b/linux/avahi-client/publish.h
@@ -0,0 +1,174 @@
+#ifndef fooclientpublishhfoo
+#define fooclientpublishhfoo
+
+/* $Id: publish.h 1502 2007-07-30 20:12:20Z lennart $ */
+
+/***
+ This file is part of avahi.
+
+ avahi is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ avahi is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
+ Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with avahi; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA.
+***/
+
+#include <inttypes.h>
+
+#include <avahi-common/cdecl.h>
+#include <avahi-common/address.h>
+#include <avahi-common/strlst.h>
+#include <avahi-common/defs.h>
+#include <avahi-common/watch.h>
+#include <avahi-common/gccmacro.h>
+
+#include <avahi-client/client.h>
+
+/** \file avahi-client/publish.h Publishing Client API */
+
+/** \example client-publish-service.c Example how to register a DNS-SD
+ * service using the client interface to avahi-daemon. It behaves like a network
+ * printer registering both an IPP and a BSD LPR service. */
+
+AVAHI_C_DECL_BEGIN
+
+/** An entry group object */
+typedef struct AvahiEntryGroup AvahiEntryGroup;
+
+/** The function prototype for the callback of an AvahiEntryGroup */
+typedef void (*AvahiEntryGroupCallback) (
+ AvahiEntryGroup *g,
+ AvahiEntryGroupState state /**< The new state of the entry group */,
+ void* userdata /* The arbitrary user data pointer originally passed to avahi_entry_group_new()*/);
+
+/** @{ \name Construction and destruction */
+
+/** Create a new AvahiEntryGroup object */
+AvahiEntryGroup* avahi_entry_group_new(
+ AvahiClient* c,
+ AvahiEntryGroupCallback callback /**< This callback is called whenever the state of this entry group changes. May not be NULL. Please note that this function is called for the first time from within the avahi_entry_group_new() context! Thus, in the callback you should not make use of global variables that are initialized only after your call to avahi_entry_group_new(). A common mistake is to store the AvahiEntryGroup pointer returned by avahi_entry_group_new() in a global variable and assume that this global variable already contains the valid pointer when the callback is called for the first time. A work-around for this is to always use the AvahiEntryGroup pointer passed to the callback function instead of the global pointer. */,
+ void *userdata /**< This arbitrary user data pointer will be passed to the callback functon */);
+
+/** Clean up and free an AvahiEntryGroup object */
+int avahi_entry_group_free (AvahiEntryGroup *);
+
+/** @} */
+
+/** @{ \name State */
+
+/** Commit an AvahiEntryGroup. The entries in the entry group are now registered on the network. Commiting empty entry groups is considered an error. */
+int avahi_entry_group_commit (AvahiEntryGroup*);
+
+/** Reset an AvahiEntryGroup. This takes effect immediately. */
+int avahi_entry_group_reset (AvahiEntryGroup*);
+
+/** Get an AvahiEntryGroup's state */
+int avahi_entry_group_get_state (AvahiEntryGroup*);
+
+/** Check if an AvahiEntryGroup is empty */
+int avahi_entry_group_is_empty (AvahiEntryGroup*);
+
+/** Get an AvahiEntryGroup's owning client instance */
+AvahiClient* avahi_entry_group_get_client (AvahiEntryGroup*);
+
+/** @} */
+
+/** @{ \name Adding and updating entries */
+
+/** Add a service. Takes a variable NULL terminated list of TXT record strings as last arguments. Please note that this service is not announced on the network before avahi_entry_group_commit() is called. */
+int avahi_entry_group_add_service(
+ AvahiEntryGroup *group,
+ AvahiIfIndex interface /**< The interface this service shall be announced on. We recommend to pass AVAHI_IF_UNSPEC here, to announce on all interfaces. */,
+ AvahiProtocol protocol /**< The protocol this service shall be announced with, i.e. MDNS over IPV4 or MDNS over IPV6. We recommend to pass AVAHI_PROTO_UNSPEC here, to announce this service on all protocols the daemon supports. */,
+ AvahiPublishFlags flags /**< Usually 0, unless you know what you do */,
+ const char *name /**< The name for the new service. Must be valid service name. i.e. a string shorter than 63 characters and valid UTF-8. May not be NULL. */,
+ const char *type /**< The service type for the new service, such as _http._tcp. May not be NULL. */,
+ const char *domain /**< The domain to register this domain in. We recommend to pass NULL here, to let the daemon decide */,
+ const char *host /**< The host this services is residing on. We recommend to pass NULL here, the daemon will than automatically insert the local host name in that case */,
+ uint16_t port /**< The IP port number of this service */,
+ ...) AVAHI_GCC_SENTINEL;
+
+/** Add a service, takes an AvahiStringList for TXT records. Arguments have the same meaning as for avahi_entry_group_add_service(). */
+int avahi_entry_group_add_service_strlst(
+ AvahiEntryGroup *group,
+ AvahiIfIndex interface,
+ AvahiProtocol protocol,
+ AvahiPublishFlags flags,
+ const char *name,
+ const char *type,
+ const char *domain,
+ const char *host,
+ uint16_t port,
+ AvahiStringList *txt /**< The TXT data for this service. You may free this object after calling this function, it is not referenced any further */);
+
+/** Add a subtype for a service. The service should already be existent in the entry group. You may add as many subtypes for a service as you wish. */
+int avahi_entry_group_add_service_subtype(
+ AvahiEntryGroup *group,
+ AvahiIfIndex interface /**< The interface this subtype shall be announced on. This should match the value passed for the original avahi_entry_group_add_service() call. */,
+ AvahiProtocol protocol /**< The protocol this subtype shall be announced with. This should match the value passed for the original avahi_entry_group_add_service() call. */,
+ AvahiPublishFlags flags /**< Only != 0 if you really know what you do */,
+ const char *name /**< The name of the service, as passed to avahi_entry_group_add_service(). May not be NULL. */,
+ const char *type /**< The type of the service, as passed to avahi_entry_group_add_service(). May not be NULL. */,
+ const char *domain /**< The domain this service resides is, as passed to avahi_entry_group_add_service(). May be NULL. */,
+ const char *subtype /**< The new subtype to register for the specified service. May not be NULL. */);
+
+/** Update a TXT record for an existing service. The service should already be existent in the entry group. */
+int avahi_entry_group_update_service_txt(
+ AvahiEntryGroup *g,
+ AvahiIfIndex interface /**< The interface this service is announced on. This should match the value passed to the original avahi_entry_group_add_service() call. */,
+ AvahiProtocol protocol /**< The protocol this service is announced with. This should match the value passed to the original avahi_entry_group_add_service() call. */,
+ AvahiPublishFlags flags /**< Only != 0 if you really know what you do */,
+ const char *name /**< The name of the service, as passed to avahi_entry_group_add_service(). May not be NULL. */,
+ const char *type /**< The type of the service, as passed to avahi_entry_group_add_service(). May not be NULL. */,
+ const char *domain /**< The domain this service resides is, as passed to avahi_entry_group_add_service(). May be NULL. */,
+ ...) AVAHI_GCC_SENTINEL;
+
+/** Update a TXT record for an existing service. Similar to avahi_entry_group_update_service_txt() but takes an AvahiStringList for the TXT strings, instead of a NULL terminated list of arguments. */
+int avahi_entry_group_update_service_txt_strlst(
+ AvahiEntryGroup *g,
+ AvahiIfIndex interface,
+ AvahiProtocol protocol,
+ AvahiPublishFlags flags,
+ const char *name,
+ const char *type,
+ const char *domain,
+ AvahiStringList *strlst);
+
+/** \cond fulldocs */
+/** Add a host/address pair */
+int avahi_entry_group_add_address(
+ AvahiEntryGroup *group,
+ AvahiIfIndex interface,
+ AvahiProtocol protocol,
+ AvahiPublishFlags flags,
+ const char *name /**< The FDQN of the new hostname to register */,
+ const AvahiAddress *a /**< The address this host name shall map to */);
+/** \endcond */
+
+/** Add an arbitrary record. I hope you know what you do. */
+int avahi_entry_group_add_record(
+ AvahiEntryGroup *group,
+ AvahiIfIndex interface,
+ AvahiProtocol protocol,
+ AvahiPublishFlags flags,
+ const char *name,
+ uint16_t clazz,
+ uint16_t type,
+ uint32_t ttl,
+ const void *rdata,
+ size_t size);
+
+/** @} */
+
+AVAHI_C_DECL_END
+
+#endif
diff --git a/linux/avahi-common/address.h b/linux/avahi-common/address.h
new file mode 100644
index 0000000..b6df0df
--- /dev/null
+++ b/linux/avahi-common/address.h
@@ -0,0 +1,121 @@
+#ifndef fooaddresshfoo
+#define fooaddresshfoo
+
+/* $Id: address.h 1477 2007-05-09 19:45:54Z lennart $ */
+
+/***
+ This file is part of avahi.
+
+ avahi is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ avahi is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
+ Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with avahi; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA.
+***/
+
+/** \file address.h Definitions and functions to manipulate IP addresses. */
+
+#include <inttypes.h>
+#include <sys/types.h>
+
+#include <avahi-common/cdecl.h>
+
+AVAHI_C_DECL_BEGIN
+
+/** Protocol family specification, takes the values AVAHI_PROTO_INET, AVAHI_PROTO_INET6, AVAHI_PROTO_UNSPEC */
+typedef int AvahiProtocol;
+
+/** Numeric network interface index. Takes OS dependent values and the special constant AVAHI_IF_UNSPEC */
+typedef int AvahiIfIndex;
+
+/** Values for AvahiProtocol */
+enum {
+ AVAHI_PROTO_INET = 0, /**< IPv4 */
+ AVAHI_PROTO_INET6 = 1, /**< IPv6 */
+ AVAHI_PROTO_UNSPEC = -1 /**< Unspecified/all protocol(s) */
+};
+
+/** Special values for AvahiIfIndex */
+enum {
+ AVAHI_IF_UNSPEC = -1 /**< Unspecified/all interface(s) */
+};
+
+/** Maximum size of an address in string form */
+#define AVAHI_ADDRESS_STR_MAX 40 /* IPv6 Max = 4*8 + 7 + 1 for NUL */
+
+/** Return TRUE if the specified interface index is valid */
+#define AVAHI_IF_VALID(ifindex) (((ifindex) >= 0) || ((ifindex) == AVAHI_IF_UNSPEC))
+
+/** Return TRUE if the specified protocol is valid */
+#define AVAHI_PROTO_VALID(protocol) (((protocol) == AVAHI_PROTO_INET) || ((protocol) == AVAHI_PROTO_INET6) || ((protocol) == AVAHI_PROTO_UNSPEC))
+
+/** An IPv4 address */
+typedef struct AvahiIPv4Address {
+ uint32_t address; /**< Address data in network byte order. */
+} AvahiIPv4Address;
+
+/** An IPv6 address */
+typedef struct AvahiIPv6Address {
+ uint8_t address[16]; /**< Address data */
+} AvahiIPv6Address;
+
+/** Protocol (address family) independent address structure */
+typedef struct AvahiAddress {
+ AvahiProtocol proto; /**< Address family */
+
+ union {
+ AvahiIPv6Address ipv6; /**< Address when IPv6 */
+ AvahiIPv4Address ipv4; /**< Address when IPv4 */
+ uint8_t data[1]; /**< Type independant data field */
+ } data;
+} AvahiAddress;
+
+/** @{ \name Comparison */
+
+/** Compare two addresses. Returns 0 when equal, a negative value when a < b, a positive value when a > b. */
+int avahi_address_cmp(const AvahiAddress *a, const AvahiAddress *b);
+
+/** @} */
+
+/** @{ \name String conversion */
+
+/** Convert the specified address *a to a human readable character string, use AVAHI_ADDRESS_STR_MAX to allocate an array of the right size */
+char *avahi_address_snprint(char *ret_s, size_t length, const AvahiAddress *a);
+
+/** Convert the specified human readable character string to an
+ * address structure. Set af to AVAHI_UNSPEC for automatic address
+ * family detection. */
+AvahiAddress *avahi_address_parse(const char *s, AvahiProtocol af, AvahiAddress *ret_addr);
+
+/** @} */
+
+/** \cond fulldocs */
+/** Generate the DNS reverse lookup name for an IPv4 or IPv6 address. */
+char* avahi_reverse_lookup_name(const AvahiAddress *a, char *ret_s, size_t length);
+/** \endcond */
+
+/** @{ \name Protocol/address family handling */
+
+/** Map AVAHI_PROTO_xxx constants to Unix AF_xxx constants */
+int avahi_proto_to_af(AvahiProtocol proto);
+
+/** Map Unix AF_xxx constants to AVAHI_PROTO_xxx constants */
+AvahiProtocol avahi_af_to_proto(int af);
+
+/** Return a textual representation of the specified protocol number. i.e. "IPv4", "IPv6" or "UNSPEC" */
+const char* avahi_proto_to_string(AvahiProtocol proto);
+
+/** @} */
+
+AVAHI_C_DECL_END
+
+#endif
diff --git a/linux/avahi-common/alternative.h b/linux/avahi-common/alternative.h
new file mode 100644
index 0000000..2d561be
--- /dev/null
+++ b/linux/avahi-common/alternative.h
@@ -0,0 +1,45 @@
+#ifndef fooalternativehfoo
+#define fooalternativehfoo
+
+/* $Id: alternative.h 874 2005-10-26 01:34:48Z lennart $ */
+
+/***
+ This file is part of avahi.
+
+ avahi is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ avahi is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
+ Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with avahi; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA.
+***/
+
+/** \file alternative.h Functions to find alternative names for hosts and services in the case of name collision */
+
+#include <avahi-common/cdecl.h>
+
+AVAHI_C_DECL_BEGIN
+
+/** Find an alternative for the specified host name. If called with an
+ * original host name, "2" is appended, Afterwards the number is
+ * increased on each call. (i.e. "foo" becomes "foo2" becomes "foo3"
+ * and so on.) avahi_free() the result. */
+char *avahi_alternative_host_name(const char *s);
+
+/** Find an alternative for the specified service name. If called with
+ * an original service name, " #2" is appended. Afterwards the number
+ * is increased on each call (i.e. "foo" becomes "foo #2" becomes "foo
+ * #3" and so on.) avahi_free() the result. */
+char *avahi_alternative_service_name(const char *s);
+
+AVAHI_C_DECL_END
+
+#endif
diff --git a/linux/avahi-common/cdecl.h b/linux/avahi-common/cdecl.h
new file mode 100644
index 0000000..516d825
--- /dev/null
+++ b/linux/avahi-common/cdecl.h
@@ -0,0 +1,40 @@
+#ifndef foocdeclhfoo
+#define foocdeclhfoo
+
+/* $Id: cdecl.h 872 2005-10-26 01:21:30Z lennart $ */
+
+/***
+ This file is part of avahi.
+
+ avahi is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ avahi is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
+ Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with avahi; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA.
+***/
+
+/** \file cdecl.h C++ compatibility */
+#ifdef __cplusplus
+/** If using C++ this macro enables C mode, otherwise does nothing */
+#define AVAHI_C_DECL_BEGIN extern "C" {
+/** If using C++ this macros switches back to C++ mode, otherwise does nothing */
+#define AVAHI_C_DECL_END }
+
+#else
+/** If using C++ this macro enables C mode, otherwise does nothing */
+#define AVAHI_C_DECL_BEGIN
+/** If using C++ this macros switches back to C++ mode, otherwise does nothing */
+#define AVAHI_C_DECL_END
+
+#endif
+
+#endif
diff --git a/linux/avahi-common/defs.h b/linux/avahi-common/defs.h
new file mode 100644
index 0000000..21807fc
--- /dev/null
+++ b/linux/avahi-common/defs.h
@@ -0,0 +1,354 @@
+#ifndef foodefshfoo
+#define foodefshfoo
+
+/* $Id: defs.h 1511 2007-08-12 15:41:45Z lennart $ */
+
+/***
+ This file is part of avahi.
+
+ avahi is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ avahi is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
+ Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with avahi; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA.
+***/
+
+/** \file defs.h Some common definitions */
+
+#include <avahi-common/cdecl.h>
+
+/** \mainpage
+ *
+ * \section choose_api Choosing an API
+ *
+ * Avahi provides three programming APIs for integration of
+ * mDNS/DNS-SD features into your C progams:
+ *
+ * \li <b>avahi-core</b>: an API for embedding a complete mDNS/DNS-SD stack
+ * into your software. This is intended for developers of embedded
+ * ampliances only. We dissuade from using this API in normal desktop
+ * applications since it is not a good idea to run multiple mDNS
+ * stacks simultaneously on the same host.
+ * \li <b>the D-Bus API</b>: an extensive D-Bus interface for browsing and
+ * registering mDNS/DNS-SD services using avahi-daemon. We recommend
+ * to use this API for software written in any language but
+ * C. (i.e. Python)
+ * \li <b>avahi-client</b>: a simplifying C wrapper around the D-Bus API. We
+ * recommend to use this API in C or C++ progams. The D-Bus internals
+ * are hidden completely.
+ *
+ * All three APIs are very similar, however avahi-core is the most powerful.
+ *
+ * In addition to the three APIs described above Avahi supports two
+ * compatibility libraries:
+ *
+ * \li <b>avahi-compat-libdns_sd</b>: the original Bonjour API as documented
+ * in the header file "dns_sd.h" by Apple Computer, Inc.
+ *
+ * \li <b>avahi-compat-howl</b>: the HOWL API as released with HOWL 0.9.8 by
+ * Porchdog Software.
+ *
+ * Please note that these compatibility layers are incomplete and
+ * generally a waste of resources. We strongly encourage everyone to
+ * use our native APIs for newly written programs and to port older
+ * programs to avahi-client!
+ *
+ * The native APIs (avahi-client and avahi-core) can be integrated
+ * into external event loops. We provide adapters for the following
+ * event loop implementations:
+ *
+ * \li <b>avahi-glib</b>: The GLIB main loop as used by GTk+/GNOME
+ *
+ * \li <b>avahi-qt</b>: The Qt main loop as used by Qt/KDE
+ *
+ * Finally, we provide a high-level Gtk+ GUI dialog called
+ * <b>avahi-ui</b> for user-friendly browsing for services.
+ *
+ * The doxygen-generated API documentation covers avahi-client
+ * (including its auxiliary APIs), the event loop adapters and
+ * avahi-ui. For the other APIs please consult the original
+ * documentation (for the compatibility APIs) or the header files.
+ *
+ * Please note that the doxygen-generated API documentation of the
+ * native Avahi API is not complete. A few definitions that are part
+ * of the Avahi API have been removed from this documentation, either
+ * because they are only relevant in a very few low-level applications
+ * or because they are considered obsolete. Please consult the C header
+ * files for all definitions that are part of the Avahi API. Please
+ * note that these hidden definitions are considered part of the Avahi
+ * API and will stay available in the API in the future.
+ *
+ * \section error_reporting Error Reporting
+ *
+ * Some notes on the Avahi error handling:
+ *
+ * - Error codes are negative integers and defined as AVAHI_ERR_xx
+ * - If a function returns some kind of non-negative integer value on
+ * success, a failure is indicated by returning the error code
+ * directly.
+ * - If a function returns a pointer of some kind on success, a
+ * failure is indicated by returning NULL
+ * - The last error number may be retrieved by calling
+ * avahi_client_errno()
+ * - Just like the libc errno variable the Avahi errno is NOT reset to
+ * AVAHI_OK if a function call succeeds.
+ * - You may convert a numeric error code into a human readable string
+ * using avahi_strerror()
+ * - The constructor function avahi_client_new() returns the error
+ * code in a call-by-reference argument
+ *
+ * \section event_loop Event Loop Abstraction
+ *
+ * Avahi uses a simple event loop abstraction laye. A table AvahiPoll
+ * which contains function pointers for user defined timeout and I/O
+ * condition event source implementations needs to be passed to
+ * avahi_client_new(). An adapter for this abstraction layer is
+ * available for the GLib main loop in the object AvahiGLibPoll. A
+ * simple stand-alone implementation is available under the name
+ * AvahiSimplePoll. An adpater for the Qt main loop is available from
+ * avahi_qt_poll_get().
+ *
+ * \section good_publish How to Register Services
+ *
+ * - Subscribe to server state changes. Pass a callback function
+ * pointer to avahi_client_new(). It will be called
+ * whenever the server state changes.
+ * - Only register your services when the server is in state
+ * AVAHI_SERVER_RUNNING. If you register your services in other server
+ * states they might not be accessible since the local host name might not necessarily
+ * be established.
+ * - Remove your services when the server enters
+ * AVAHI_SERVER_COLLISION or AVAHI_SERVER_REGISTERING state. Your
+ * services may no be reachable anymore since the local host name is
+ * no longer established or is currently in the process of being
+ * established.
+ * - When registering services, use the following algorithm:
+ * - Create a new entry group (i.e. avahi_entry_group_new())
+ * - Add your service(s)/additional RRs/subtypes (e.g. avahi_entry_group_add_service())
+ * - Commit the entry group (i.e. avahi_entry_group_commit())
+ * - Subscribe to entry group state changes.
+ * - If the entry group enters AVAHI_ENTRY_GROUP_COLLISION state the
+ * services of the entry group are automatically removed from the
+ * server. You may immediately add your services back to the entry
+ * group (but with new names, perhaps using
+ * avahi_alternative_service_name()) and commit again. Please do not
+ * free the entry group and create a new one. This would inhibit some
+ * traffic limiting algorithms in mDNS.
+ * - When you need to modify your services (i.e. change the TXT data
+ * or the port number), use the AVAHI_PUBLISH_UPDATE flag. Please do
+ * not free the entry group and create a new one. This would inhibit
+ * some traffic limiting algorithms in mDNS. When changing just the
+ * TXT data avahi_entry_group_update_txt() is a shortcut for
+ * AVAHI_PUBLISH_UPDATE. Please note that you cannot use
+ * AVAHI_PUBLISH_UPDATE when changing the service name! Renaming a
+ * DNS-SD service is identical to deleting and creating a new one, and
+ * that's exactly what you should do in that case. First call
+ * avahi_entry_group_reset() to remove it and than readd it normally.
+ *
+ * \section good_browse How to Browse for Services
+ *
+ * - For normal applications you need to call avahi_service_browser_new()
+ * for the service type you want to browse for. Use
+ * avahi_service_resolver_new() to acquire service data for a service
+ * name.
+ * - You can use avahi_domain_browser_new() to get a list of announced
+ * browsing domains. Please note that not all domains whith services
+ * on the LAN are mandatorily announced.
+ * - There is no need to subscribe to server state changes.
+ *
+ * \section daemon_dies How to Write a Client That Can Deal with Daemon Restarts
+ *
+ * With Avahi it is possible to write client applications that can
+ * deal with Avahi daemon restarts. To accomplish that make sure to
+ * pass AVAHI_CLIENT_NO_FAIL to avahi_client_new()'s flags
+ * parameter. That way avahi_client_new() will succeed even when the
+ * daemon is not running. In that case the object will enter
+ * AVAHI_CLIENT_CONNECTING state. As soon as the daemon becomes
+ * available the object will enter one of the AVAHI_CLIENT_S_xxx
+ * states. Make sure to not create browsers or entry groups before the
+ * client object has entered one of those states. As usual you will be
+ * informed about state changes with the callback function supplied to
+ * avahi_client_new(). If the client is forced to disconnect from the
+ * server it will enter AVAHI_CLIENT_FAILURE state with
+ * avahi_client_errno() == AVAHI_ERR_DISCONNECTED. Free the
+ * AvahiClient object in that case and reconnect to the server anew -
+ * again with passing AVAHI_CLIENT_NO_FAIL to avahi_client_new().
+ *
+ * We encourage to implement this in all software where service
+ * discovery is not an integral part of application. e.g. use it in
+ * all kinds of background daemons, but not in software like iChat
+ * compatible IM software.
+ *
+ * For now AVAHI_CLIENT_NO_FAIL cannot deal with D-Bus daemon restarts.
+ *
+ * \section domains How to Deal Properly with Browsing Domains
+ *
+ * Due to the introduction of wide-area DNS-SD the correct handling of
+ * domains becomes more important for Avahi enabled applications. All
+ * applications that offer the user a list of services discovered with
+ * Avahi should offer some kind of editable drop down box where the
+ * user can either enter his own domain or select one of those offered
+ * by AvahiDomainBrowser. The default domain to browse should be the
+ * one returned by avahi_client_get_domain_name(). The list of domains
+ * returned by AvahiDomainBrowser is assembled by the browsing domains
+ * configured in the daemon's configuration file, the domains
+ * announced inside the default domain, the domains set with the
+ * environment variable $AVAHI_BROWSE_DOMAINS (colon-seperated) on the
+ * client side and the domains set in the XDG configuration file
+ * ~/.config/avahi/browse-domains on the client side (seperated by
+ * newlines). File managers offering some kind of "Network
+ * Neighborhood" folder should show the entries of the default domain
+ * right inside that and offer subfolders for the browsing domains
+ * returned by AvahiDomainBrowser.
+ */
+
+AVAHI_C_DECL_BEGIN
+
+/** @{ \name States */
+
+/** States of a server object */
+typedef enum {
+ AVAHI_SERVER_INVALID, /**< Invalid state (initial) */
+ AVAHI_SERVER_REGISTERING, /**< Host RRs are being registered */
+ AVAHI_SERVER_RUNNING, /**< All host RRs have been established */
+ AVAHI_SERVER_COLLISION, /**< There is a collision with a host RR. All host RRs have been withdrawn, the user should set a new host name via avahi_server_set_host_name() */
+ AVAHI_SERVER_FAILURE /**< Some fatal failure happened, the server is unable to proceed */
+} AvahiServerState;
+
+/** States of an entry group object */
+typedef enum {
+ AVAHI_ENTRY_GROUP_UNCOMMITED, /**< The group has not yet been commited, the user must still call avahi_entry_group_commit() */
+ AVAHI_ENTRY_GROUP_REGISTERING, /**< The entries of the group are currently being registered */
+ AVAHI_ENTRY_GROUP_ESTABLISHED, /**< The entries have successfully been established */
+ AVAHI_ENTRY_GROUP_COLLISION, /**< A name collision for one of the entries in the group has been detected, the entries have been withdrawn */
+ AVAHI_ENTRY_GROUP_FAILURE /**< Some kind of failure happened, the entries have been withdrawn */
+} AvahiEntryGroupState;
+
+/** @} */
+
+/** @{ \name Flags */
+
+/** Some flags for publishing functions */
+typedef enum {
+ AVAHI_PUBLISH_UNIQUE = 1, /**< For raw records: The RRset is intended to be unique */
+ AVAHI_PUBLISH_NO_PROBE = 2, /**< For raw records: Though the RRset is intended to be unique no probes shall be sent */
+ AVAHI_PUBLISH_NO_ANNOUNCE = 4, /**< For raw records: Do not announce this RR to other hosts */
+ AVAHI_PUBLISH_ALLOW_MULTIPLE = 8, /**< For raw records: Allow multiple local records of this type, even if they are intended to be unique */
+/** \cond fulldocs */
+ AVAHI_PUBLISH_NO_REVERSE = 16, /**< For address records: don't create a reverse (PTR) entry */
+ AVAHI_PUBLISH_NO_COOKIE = 32, /**< For service records: do not implicitly add the local service cookie to TXT data */
+/** \endcond */
+ AVAHI_PUBLISH_UPDATE = 64, /**< Update existing records instead of adding new ones */
+/** \cond fulldocs */
+ AVAHI_PUBLISH_USE_WIDE_AREA = 128, /**< Register the record using wide area DNS (i.e. unicast DNS update) */
+ AVAHI_PUBLISH_USE_MULTICAST = 256 /**< Register the record using multicast DNS */
+/** \endcond */
+} AvahiPublishFlags;
+
+/** Some flags for lookup functions */
+typedef enum {
+/** \cond fulldocs */
+ AVAHI_LOOKUP_USE_WIDE_AREA = 1, /**< Force lookup via wide area DNS */
+ AVAHI_LOOKUP_USE_MULTICAST = 2, /**< Force lookup via multicast DNS */
+/** \endcond */
+ AVAHI_LOOKUP_NO_TXT = 4, /**< When doing service resolving, don't lookup TXT record */
+ AVAHI_LOOKUP_NO_ADDRESS = 8 /**< When doing service resolving, don't lookup A/AAAA record */
+} AvahiLookupFlags;
+
+/** Some flags for lookup callback functions */
+typedef enum {
+ AVAHI_LOOKUP_RESULT_CACHED = 1, /**< This response originates from the cache */
+ AVAHI_LOOKUP_RESULT_WIDE_AREA = 2, /**< This response originates from wide area DNS */
+ AVAHI_LOOKUP_RESULT_MULTICAST = 4, /**< This response originates from multicast DNS */
+ AVAHI_LOOKUP_RESULT_LOCAL = 8, /**< This record/service resides on and was announced by the local host. Only available in service and record browsers and only on AVAHI_BROWSER_NEW. */
+ AVAHI_LOOKUP_RESULT_OUR_OWN = 16, /**< This service belongs to the same local client as the browser object. Only available in avahi-client, and only for service browsers and only on AVAHI_BROWSER_NEW. */
+ AVAHI_LOOKUP_RESULT_STATIC = 32 /**< The returned data has been defined statically by some configuration option */
+} AvahiLookupResultFlags;
+
+/** @} */
+
+/** @{ \name Events */
+
+/** Type of callback event when browsing */
+typedef enum {
+ AVAHI_BROWSER_NEW, /**< The object is new on the network */
+ AVAHI_BROWSER_REMOVE, /**< The object has been removed from the network */
+ AVAHI_BROWSER_CACHE_EXHAUSTED, /**< One-time event, to notify the user that all entries from the caches have been send */
+ AVAHI_BROWSER_ALL_FOR_NOW, /**< One-time event, to notify the user that more records will probably not show up in the near future, i.e. all cache entries have been read and all static servers been queried */
+ AVAHI_BROWSER_FAILURE /**< Browsing failed due to some reason which can be retrieved using avahi_server_errno()/avahi_client_errno() */
+} AvahiBrowserEvent;
+
+/** Type of callback event when resolving */
+typedef enum {
+ AVAHI_RESOLVER_FOUND, /**< RR found, resolving successful */
+ AVAHI_RESOLVER_FAILURE /**< Resolving failed due to some reason which can be retrieved using avahi_server_errno()/avahi_client_errno() */
+} AvahiResolverEvent;
+
+/** @} */
+
+/** @{ \name Other definitions */
+
+/** The type of domain to browse for */
+typedef enum {
+ AVAHI_DOMAIN_BROWSER_BROWSE, /**< Browse for a list of available browsing domains */
+ AVAHI_DOMAIN_BROWSER_BROWSE_DEFAULT, /**< Browse for the default browsing domain */
+ AVAHI_DOMAIN_BROWSER_REGISTER, /**< Browse for a list of available registering domains */
+ AVAHI_DOMAIN_BROWSER_REGISTER_DEFAULT, /**< Browse for the default registering domain */
+ AVAHI_DOMAIN_BROWSER_BROWSE_LEGACY, /**< Legacy browse domain - see DNS-SD spec for more information */
+ AVAHI_DOMAIN_BROWSER_MAX
+} AvahiDomainBrowserType;
+
+/** @} */
+
+/** \cond fulldocs */
+/** For every service a special TXT item is implicitly added, which
+ * contains a random cookie which is private to the local daemon. This
+ * can be used by clients to determine if two services on two
+ * different subnets are effectively the same. */
+#define AVAHI_SERVICE_COOKIE "org.freedesktop.Avahi.cookie"
+
+/** In invalid cookie as special value */
+#define AVAHI_SERVICE_COOKIE_INVALID (0)
+/** \endcond fulldocs */
+
+/** @{ \name DNS RR definitions */
+
+/** DNS record types, see RFC 1035 */
+enum {
+ AVAHI_DNS_TYPE_A = 0x01,
+ AVAHI_DNS_TYPE_NS = 0x02,
+ AVAHI_DNS_TYPE_CNAME = 0x05,
+ AVAHI_DNS_TYPE_SOA = 0x06,
+ AVAHI_DNS_TYPE_PTR = 0x0C,
+ AVAHI_DNS_TYPE_HINFO = 0x0D,
+ AVAHI_DNS_TYPE_MX = 0x0F,
+ AVAHI_DNS_TYPE_TXT = 0x10,
+ AVAHI_DNS_TYPE_AAAA = 0x1C,
+ AVAHI_DNS_TYPE_SRV = 0x21
+};
+
+/** DNS record classes, see RFC 1035 */
+enum {
+ AVAHI_DNS_CLASS_IN = 0x01 /**< Probably the only class we will ever use */
+};
+
+/** @} */
+
+/** The default TTL for RRs which contain a host name of some kind. */
+#define AVAHI_DEFAULT_TTL_HOST_NAME (120)
+
+/** The default TTL for all other records. */
+#define AVAHI_DEFAULT_TTL (75*60)
+
+AVAHI_C_DECL_END
+
+#endif
diff --git a/linux/avahi-common/domain.h b/linux/avahi-common/domain.h
new file mode 100644
index 0000000..accbd60
--- /dev/null
+++ b/linux/avahi-common/domain.h
@@ -0,0 +1,131 @@
+#ifndef foodomainhfoo
+#define foodomainhfoo
+
+/* $Id: domain.h 1477 2007-05-09 19:45:54Z lennart $ */
+
+/***
+ This file is part of avahi.
+
+ avahi is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ avahi is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
+ Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with avahi; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA.
+***/
+
+/** \file domain.h Domain name handling functions */
+
+#include <inttypes.h>
+#include <sys/types.h>
+
+#include <avahi-common/cdecl.h>
+
+AVAHI_C_DECL_BEGIN
+
+/** The maximum length of a a fully escaped domain name C string. This
+ * is calculated like this: RFC1034 mandates maximum length of FQDNs
+ * is 255. The maximum label length is 63. To minimize the number of
+ * (non-escaped) dots, we comprise our maximum-length domain name of
+ * four labels á 63 characters plus three inner dots. Escaping the
+ * four labels quadruples their length at maximum. An escaped domain
+ * name has the therefore the maximum length of 63*4*4+3=1011. A
+ * trailing NUL and perhaps two unnecessary dots leading and trailing
+ * the string brings us to 1014. */
+#define AVAHI_DOMAIN_NAME_MAX 1014
+
+/** Maximum size of an unescaped label */
+#define AVAHI_LABEL_MAX 64
+
+/** @{ \name Normalization */
+
+/** Normalize a domain name into canonical form. This drops trailing
+ * dots and removes useless backslash escapes. */
+char *avahi_normalize_name(const char *s, char *ret_s, size_t size);
+
+/** Normalize a domain name into canonical form. This drops trailing
+ * dots and removes useless backslash escapes. avahi_free() the
+ * result! */
+char *avahi_normalize_name_strdup(const char *s);
+
+/** @} */
+
+/** @{ \name Comparison */
+
+/** Return 1 when the specified domain names are equal, 0 otherwise */
+int avahi_domain_equal(const char *a, const char *b);
+
+/** Return some kind of hash value for the domain, useful for using domains as hash table keys. */
+unsigned avahi_domain_hash(const char *name);
+
+/** @} */
+
+/** @{ \name Escaping */
+
+/** Read the first label from the textual domain name *name, unescape
+ * it and write it to dest, *name is changed to point to the next label*/
+char *avahi_unescape_label(const char **name, char *dest, size_t size);
+
+/** Escape the domain name in *src and write it to *ret_name */
+char *avahi_escape_label(const char* src, size_t src_length, char **ret_name, size_t *ret_size);
+
+/** @} */
+
+/** @{ \name Validity Checks */
+
+/** Return 1 when the specified string contains a valid generic DNS-SD
+ * service type (i.e. a series of words starting with "_"), 0
+ * otherwise */
+int avahi_is_valid_service_type_generic(const char *t);
+
+/** Return 1 when the specified string contains a valid strict DNS-SD
+ * service type (i.e. consisting of only two words, the latter being
+ * either _udp or _tcp), 0 otherwise */
+int avahi_is_valid_service_type_strict(const char *t);
+
+/** Return 1 when the specified string contains a valid DNS-SD service
+ * subtype, 0 otherwise */
+int avahi_is_valid_service_subtype(const char *t);
+
+/** Return 1 when the specified string contains a valid domain name, 0 otherwise */
+int avahi_is_valid_domain_name(const char *t);
+
+/** Return 1 when the specified string contains a valid DNS-SD service name, 0 otherwise */
+int avahi_is_valid_service_name(const char *t);
+
+/** Return 1 when the specified string contains a valid non-FQDN host name (i.e. without dots), 0 otherwise */
+int avahi_is_valid_host_name(const char *t);
+
+/** Return 1 when the specified string contains a valid FQDN host name (i.e. with more than one label and non-numerical), 0 otherwise. \since 0.6.9 */
+int avahi_is_valid_fqdn(const char *t);
+
+/** @} */
+
+/** @{ \name DNS-SD service name handling */
+
+/** Construct a valid complete DNS-SD service name from a name, a type and a domain */
+int avahi_service_name_join(char *p, size_t size, const char *name, const char *type, const char *domain);
+
+/** Split a full service name into name, type and domain */
+int avahi_service_name_split(const char *p, char *name, size_t name_size, char *type, size_t type_size, char *domain, size_t domain_size);
+
+/** @} */
+
+/** @{ \name DNS-SD Subtype handling */
+
+/** Return a pointer to the type section of a subtype i.e. _foo._sub._bar._tcp => _bar._tcp */
+const char *avahi_get_type_from_subtype(const char *t);
+
+/** @} */
+
+AVAHI_C_DECL_END
+
+#endif
diff --git a/linux/avahi-common/error.h b/linux/avahi-common/error.h
new file mode 100644
index 0000000..7d63282
--- /dev/null
+++ b/linux/avahi-common/error.h
@@ -0,0 +1,109 @@
+#ifndef fooerrorhfoo
+#define fooerrorhfoo
+
+/* $Id: error.h 1298 2006-08-31 17:26:29Z lennart $ */
+
+/***
+ This file is part of avahi.
+
+ avahi is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ avahi is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
+ Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with avahi; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA.
+***/
+
+/** \file error.h Error codes and auxiliary functions */
+
+#include <avahi-common/cdecl.h>
+
+AVAHI_C_DECL_BEGIN
+
+/** Error codes used by avahi */
+enum {
+ AVAHI_OK = 0, /**< OK */
+ AVAHI_ERR_FAILURE = -1, /**< Generic error code */
+ AVAHI_ERR_BAD_STATE = -2, /**< Object was in a bad state */
+ AVAHI_ERR_INVALID_HOST_NAME = -3, /**< Invalid host name */
+ AVAHI_ERR_INVALID_DOMAIN_NAME = -4, /**< Invalid domain name */
+ AVAHI_ERR_NO_NETWORK = -5, /**< No suitable network protocol available */
+ AVAHI_ERR_INVALID_TTL = -6, /**< Invalid DNS TTL */
+ AVAHI_ERR_IS_PATTERN = -7, /**< RR key is pattern */
+ AVAHI_ERR_COLLISION = -8, /**< Name collision */
+ AVAHI_ERR_INVALID_RECORD = -9, /**< Invalid RR */
+
+ AVAHI_ERR_INVALID_SERVICE_NAME = -10, /**< Invalid service name */
+ AVAHI_ERR_INVALID_SERVICE_TYPE = -11, /**< Invalid service type */
+ AVAHI_ERR_INVALID_PORT = -12, /**< Invalid port number */
+ AVAHI_ERR_INVALID_KEY = -13, /**< Invalid key */
+ AVAHI_ERR_INVALID_ADDRESS = -14, /**< Invalid address */
+ AVAHI_ERR_TIMEOUT = -15, /**< Timeout reached */
+ AVAHI_ERR_TOO_MANY_CLIENTS = -16, /**< Too many clients */
+ AVAHI_ERR_TOO_MANY_OBJECTS = -17, /**< Too many objects */
+ AVAHI_ERR_TOO_MANY_ENTRIES = -18, /**< Too many entries */
+ AVAHI_ERR_OS = -19, /**< OS error */
+
+ AVAHI_ERR_ACCESS_DENIED = -20, /**< Access denied */
+ AVAHI_ERR_INVALID_OPERATION = -21, /**< Invalid operation */
+ AVAHI_ERR_DBUS_ERROR = -22, /**< An unexpected D-Bus error occured */
+ AVAHI_ERR_DISCONNECTED = -23, /**< Daemon connection failed */
+ AVAHI_ERR_NO_MEMORY = -24, /**< Memory exhausted */
+ AVAHI_ERR_INVALID_OBJECT = -25, /**< The object passed to this function was invalid */
+ AVAHI_ERR_NO_DAEMON = -26, /**< Daemon not running */
+ AVAHI_ERR_INVALID_INTERFACE = -27, /**< Invalid interface */
+ AVAHI_ERR_INVALID_PROTOCOL = -28, /**< Invalid protocol */
+ AVAHI_ERR_INVALID_FLAGS = -29, /**< Invalid flags */
+
+ AVAHI_ERR_NOT_FOUND = -30, /**< Not found */
+ AVAHI_ERR_INVALID_CONFIG = -31, /**< Configuration error */
+ AVAHI_ERR_VERSION_MISMATCH = -32, /**< Verson mismatch */
+ AVAHI_ERR_INVALID_SERVICE_SUBTYPE = -33, /**< Invalid service subtype */
+ AVAHI_ERR_INVALID_PACKET = -34, /**< Invalid packet */
+ AVAHI_ERR_INVALID_DNS_ERROR = -35, /**< Invlaid DNS return code */
+ AVAHI_ERR_DNS_FORMERR = -36, /**< DNS Error: Form error */
+ AVAHI_ERR_DNS_SERVFAIL = -37, /**< DNS Error: Server Failure */
+ AVAHI_ERR_DNS_NXDOMAIN = -38, /**< DNS Error: No such domain */
+ AVAHI_ERR_DNS_NOTIMP = -39, /**< DNS Error: Not implemented */
+
+ AVAHI_ERR_DNS_REFUSED = -40, /**< DNS Error: Operation refused */
+ AVAHI_ERR_DNS_YXDOMAIN = -41,
+ AVAHI_ERR_DNS_YXRRSET = -42,
+ AVAHI_ERR_DNS_NXRRSET = -43,
+ AVAHI_ERR_DNS_NOTAUTH = -44, /**< DNS Error: Not authorized */
+ AVAHI_ERR_DNS_NOTZONE = -45,
+ AVAHI_ERR_INVALID_RDATA = -46, /**< Invalid RDATA */
+ AVAHI_ERR_INVALID_DNS_CLASS = -47, /**< Invalid DNS class */
+ AVAHI_ERR_INVALID_DNS_TYPE = -48, /**< Invalid DNS type */
+ AVAHI_ERR_NOT_SUPPORTED = -49, /**< Not supported */
+
+ AVAHI_ERR_NOT_PERMITTED = -50, /**< Operation not permitted */
+ AVAHI_ERR_INVALID_ARGUMENT = -51, /**< Invalid argument */
+ AVAHI_ERR_IS_EMPTY = -52, /**< Is empty */
+ AVAHI_ERR_NO_CHANGE = -53, /**< The requested operation is invalid because redundant */
+
+ /****
+ **** IF YOU ADD A NEW ERROR CODE HERE, PLEASE DON'T FORGET TO ADD
+ **** IT TO THE STRING ARRAY IN avahi_strerror() IN error.c AND
+ **** TO THE ARRAY IN dbus.c AND FINALLY TO dbus.h!
+ ****
+ **** Also remember to update the MAX value below.
+ ****/
+
+ AVAHI_ERR_MAX = -54
+};
+
+/** Return a human readable error string for the specified error code */
+const char *avahi_strerror(int error);
+
+AVAHI_C_DECL_END
+
+#endif
diff --git a/linux/avahi-common/gccmacro.h b/linux/avahi-common/gccmacro.h
new file mode 100644
index 0000000..c8d69ac
--- /dev/null
+++ b/linux/avahi-common/gccmacro.h
@@ -0,0 +1,67 @@
+#ifndef foogccmacrohfoo
+#define foogccmacrohfoo
+
+/* $Id: gccmacro.h 931 2005-11-06 15:00:43Z lennart $ */
+
+/***
+ This file is part of avahi.
+
+ avahi is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ avahi is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
+ Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with avahi; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA.
+***/
+
+/** \file gccmacro.h Defines some macros for GCC extensions */
+
+#include <avahi-common/cdecl.h>
+
+AVAHI_C_DECL_BEGIN
+
+#if defined(__GNUC__) && (__GNUC__ >= 4)
+#define AVAHI_GCC_SENTINEL __attribute__ ((sentinel))
+#else
+/** Macro for usage of GCC's sentinel compilation warnings */
+#define AVAHI_GCC_SENTINEL
+#endif
+
+#ifdef __GNUC__
+#define AVAHI_GCC_PRINTF_ATTR(a,b) __attribute__ ((format (printf, a, b)))
+#else
+/** Macro for usage of GCC's printf compilation warnings */
+#define AVAHI_GCC_PRINTF_ATTR(a,b)
+#endif
+
+/** Same as AVAHI_GCC_PRINTF_ATTR but hard coded to arguments 1 and 2 */
+#define AVAHI_GCC_PRINTF_ATTR12 AVAHI_GCC_PRINTF_ATTR(1,2)
+
+/** Same as AVAHI_GCC_PRINTF_ATTR but hard coded to arguments 2 and 3 */
+#define AVAHI_GCC_PRINTF_ATTR23 AVAHI_GCC_PRINTF_ATTR(2,3)
+
+#ifdef __GNUC__
+#define AVAHI_GCC_NORETURN __attribute__((noreturn))
+#else
+/** Macro for no-return functions */
+#define AVAHI_GCC_NORETURN
+#endif
+
+#ifdef __GNUC__
+#define AVAHI_GCC_UNUSED __attribute__ ((unused))
+#else
+/** Macro for not used parameter */
+#define AVAHI_GCC_UNUSED
+#endif
+
+AVAHI_C_DECL_END
+
+#endif
diff --git a/linux/avahi-common/llist.h b/linux/avahi-common/llist.h
new file mode 100644
index 0000000..ec69caa
--- /dev/null
+++ b/linux/avahi-common/llist.h
@@ -0,0 +1,77 @@
+#ifndef foollistfoo
+#define foollistfoo
+
+/* $Id: llist.h 872 2005-10-26 01:21:30Z lennart $ */
+
+/***
+ This file is part of avahi.
+
+ avahi is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ avahi is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
+ Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with avahi; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA.
+***/
+
+/** \file llist.h A simple macro based linked list implementation */
+
+#include <assert.h>
+
+#include <avahi-common/cdecl.h>
+
+AVAHI_C_DECL_BEGIN
+
+/** The head of the linked list. Use this in the structure that shall
+ * contain the head of the linked list */
+#define AVAHI_LLIST_HEAD(t,name) t *name
+
+/** The pointers in the linked list's items. Use this in the item structure */
+#define AVAHI_LLIST_FIELDS(t,name) t *name##_next, *name##_prev
+
+/** Initialize the list's head */
+#define AVAHI_LLIST_HEAD_INIT(t,head) do { (head) = NULL; } while(0)
+
+/** Initialize a list item */
+#define AVAHI_LLIST_INIT(t,name,item) do { \
+ t *_item = (item); \
+ assert(_item); \
+ _item->name##_prev = _item->name##_next = NULL; \
+ } while(0)
+
+/** Prepend an item to the list */
+#define AVAHI_LLIST_PREPEND(t,name,head,item) do { \
+ t **_head = &(head), *_item = (item); \
+ assert(_item); \
+ if ((_item->name##_next = *_head)) \
+ _item->name##_next->name##_prev = _item; \
+ _item->name##_prev = NULL; \
+ *_head = _item; \
+ } while (0)
+
+/** Remove an item from the list */
+#define AVAHI_LLIST_REMOVE(t,name,head,item) do { \
+ t **_head = &(head), *_item = (item); \
+ assert(_item); \
+ if (_item->name##_next) \
+ _item->name##_next->name##_prev = _item->name##_prev; \
+ if (_item->name##_prev) \
+ _item->name##_prev->name##_next = _item->name##_next; \
+ else {\
+ assert(*_head == _item); \
+ *_head = _item->name##_next; \
+ } \
+ _item->name##_next = _item->name##_prev = NULL; \
+ } while(0)
+
+AVAHI_C_DECL_END
+
+#endif
diff --git a/linux/avahi-common/malloc.h b/linux/avahi-common/malloc.h
new file mode 100644
index 0000000..d375cef
--- /dev/null
+++ b/linux/avahi-common/malloc.h
@@ -0,0 +1,98 @@
+#ifndef foomallochfoo
+#define foomallochfoo
+
+/* $Id: malloc.h 1477 2007-05-09 19:45:54Z lennart $ */
+
+/***
+ This file is part of avahi.
+
+ avahi is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ avahi is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
+ Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with avahi; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA.
+***/
+
+/** \file malloc.h Memory allocation */
+
+#include <sys/types.h>
+#include <stdarg.h>
+#include <limits.h>
+#include <assert.h>
+
+#include <avahi-common/cdecl.h>
+#include <avahi-common/gccmacro.h>
+
+AVAHI_C_DECL_BEGIN
+
+/** Allocate some memory, just like the libc malloc() */
+void *avahi_malloc(size_t size);
+
+/** Similar to avahi_malloc() but set the memory to zero */
+void *avahi_malloc0(size_t size);
+
+/** Free some memory */
+void avahi_free(void *p);
+
+/** Similar to libc's realloc() */
+void *avahi_realloc(void *p, size_t size);
+
+/** Internal helper for avahi_new() */
+static inline void* avahi_new_internal(unsigned n, size_t k) {
+ assert(n < INT_MAX/k);
+ return avahi_malloc(n*k);
+}
+
+/** Allocate n new structures of the specified type. */
+#define avahi_new(type, n) ((type*) avahi_new_internal((n), sizeof(type)))
+
+/** Internal helper for avahi_new0() */
+static inline void* avahi_new0_internal(unsigned n, size_t k) {
+ assert(n < INT_MAX/k);
+ return avahi_malloc0(n*k);
+}
+
+/** Same as avahi_new() but set the memory to zero */
+#define avahi_new0(type, n) ((type*) avahi_new0_internal((n), sizeof(type)))
+
+/** Just like libc's strdup() */
+char *avahi_strdup(const char *s);
+
+/** Just like libc's strndup() */
+char *avahi_strndup(const char *s, size_t l);
+
+/** Duplicate the given memory block into a new one allocated with avahi_malloc() */
+void *avahi_memdup(const void *s, size_t l);
+
+/** Wraps allocator functions */
+typedef struct AvahiAllocator {
+ void* (*malloc)(size_t size);
+ void (*free)(void *p);
+ void* (*realloc)(void *p, size_t size);
+ void* (*calloc)(size_t nmemb, size_t size); /**< May be NULL */
+} AvahiAllocator;
+
+/** Change the allocator. May be NULL to return to default (libc)
+ * allocators. The structure is not copied! */
+void avahi_set_allocator(const AvahiAllocator *a);
+
+/** Like sprintf() but store the result in a freshly allocated buffer. Free this with avahi_free() */
+char *avahi_strdup_printf(const char *fmt, ... ) AVAHI_GCC_PRINTF_ATTR12;
+
+/** \cond fulldocs */
+/** Same as avahi_strdup_printf() but take a va_list instead of varargs */
+char *avahi_strdup_vprintf(const char *fmt, va_list ap);
+/** \endcond */
+
+AVAHI_C_DECL_END
+
+#endif
diff --git a/linux/avahi-common/rlist.h b/linux/avahi-common/rlist.h
new file mode 100644
index 0000000..a418ca9
--- /dev/null
+++ b/linux/avahi-common/rlist.h
@@ -0,0 +1,51 @@
+#ifndef foorlistfoo
+#define foorlistfoo
+
+/* $Id: rlist.h 872 2005-10-26 01:21:30Z lennart $ */
+
+/***
+ This file is part of avahi.
+
+ avahi is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ avahi is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
+ Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with avahi; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA.
+***/
+
+/** \file rlist.h A simple linked list implementation */
+
+#include "llist.h"
+
+AVAHI_C_DECL_BEGIN
+
+/** A doubly linked list type */
+typedef struct AvahiRList AvahiRList;
+
+/** A doubly linked list type */
+struct AvahiRList {
+ AVAHI_LLIST_FIELDS(AvahiRList, rlist);
+ void *data;
+};
+
+/** Prepend a new item to the beginning of the list and return the new beginning */
+AvahiRList* avahi_rlist_prepend(AvahiRList *r, void *data);
+
+/** Remove the first occurence of the specified item from the list and return the new beginning */
+AvahiRList* avahi_rlist_remove(AvahiRList *r, void *data);
+
+/** Remove the specified item from the list and return the new beginning */
+AvahiRList* avahi_rlist_remove_by_link(AvahiRList *r, AvahiRList *n);
+
+AVAHI_C_DECL_END
+
+#endif
diff --git a/linux/avahi-common/simple-watch.h b/linux/avahi-common/simple-watch.h
new file mode 100644
index 0000000..50410f6
--- /dev/null
+++ b/linux/avahi-common/simple-watch.h
@@ -0,0 +1,87 @@
+#ifndef foosimplewatchhfoo
+#define foosimplewatchhfoo
+
+/* $Id: simple-watch.h 1151 2006-02-20 16:21:29Z lennart $ */
+
+/***
+ This file is part of avahi.
+
+ avahi is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ avahi is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
+ Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with avahi; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA.
+***/
+
+/** \file simple-watch.h Simple poll() based main loop implementation */
+
+#include <sys/poll.h>
+#include <avahi-common/cdecl.h>
+#include <avahi-common/watch.h>
+
+AVAHI_C_DECL_BEGIN
+
+/** A main loop object. Main loops of this type aren't very flexible
+ * since they only support a single wakeup type. Nevertheless it
+ * should suffice for small test and example applications. */
+typedef struct AvahiSimplePoll AvahiSimplePoll;
+
+/** Create a new main loop object */
+AvahiSimplePoll *avahi_simple_poll_new(void);
+
+/** Free a main loop object */
+void avahi_simple_poll_free(AvahiSimplePoll *s);
+
+/** Return the abstracted poll API object for this main loop
+ * object. The is will return the same pointer each time it is
+ * called. */
+const AvahiPoll* avahi_simple_poll_get(AvahiSimplePoll *s);
+
+/** Run a single main loop iteration of this main loop. If sleep_time
+is < 0 this will block until any of the registered events happens,
+then it will execute the attached callback function. If sleep_time is
+0 the routine just checks if any event is pending. If yes the attached
+callback function is called, otherwise the function returns
+immediately. If sleep_time > 0 the function will block for at most the
+specified time in msecs. Returns -1 on error, 0 on success and 1 if a
+quit request has been scheduled. Usually this function should be called
+in a loop until it returns a non-zero value*/
+int avahi_simple_poll_iterate(AvahiSimplePoll *s, int sleep_time);
+
+/** Request that the main loop quits. If this is called the next
+ call to avahi_simple_poll_iterate() will return 1 */
+void avahi_simple_poll_quit(AvahiSimplePoll *s);
+
+/** Prototype for a poll() type function */
+typedef int (*AvahiPollFunc)(struct pollfd *ufds, unsigned int nfds, int timeout, void *userdata);
+
+/** Replace the internally used poll() function. By default the system's poll() will be used */
+void avahi_simple_poll_set_func(AvahiSimplePoll *s, AvahiPollFunc func, void *userdata);
+
+/** The first stage of avahi_simple_poll_iterate(), use this function only if you know what you do */
+int avahi_simple_poll_prepare(AvahiSimplePoll *s, int timeout);
+
+/** The second stage of avahi_simple_poll_iterate(), use this function only if you know what you do */
+int avahi_simple_poll_run(AvahiSimplePoll *s);
+
+/** The third and final stage of avahi_simple_poll_iterate(), use this function only if you know what you do */
+int avahi_simple_poll_dispatch(AvahiSimplePoll *s);
+
+/** Call avahi_simple_poll_iterate() in a loop and return if it returns non-zero */
+int avahi_simple_poll_loop(AvahiSimplePoll *s);
+
+/** Wakeup the main loop. (for threaded environments) */
+void avahi_simple_poll_wakeup(AvahiSimplePoll *s);
+
+AVAHI_C_DECL_END
+
+#endif
diff --git a/linux/avahi-common/strlst.h b/linux/avahi-common/strlst.h
new file mode 100644
index 0000000..cddb75c
--- /dev/null
+++ b/linux/avahi-common/strlst.h
@@ -0,0 +1,182 @@
+#ifndef footxtlisthfoo
+#define footxtlisthfoo
+
+/* $Id: strlst.h 1477 2007-05-09 19:45:54Z lennart $ */
+
+/***
+ This file is part of avahi.
+
+ avahi is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ avahi is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
+ Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with avahi; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA.
+***/
+
+/** \file strlst.h Implementation of a data type to store lists of strings */
+
+#include <sys/types.h>
+#include <inttypes.h>
+#include <stdarg.h>
+
+#include <avahi-common/cdecl.h>
+#include <avahi-common/gccmacro.h>
+
+AVAHI_C_DECL_BEGIN
+
+/** Linked list of strings that can contain any number of binary
+ * characters, including NUL bytes. An empty list is created by
+ * assigning a NULL to a pointer to AvahiStringList. The string list
+ * is stored in reverse order, so that appending to the string list is
+ * effectively a prepending to the linked list. This object is used
+ * primarily for storing DNS TXT record data. */
+typedef struct AvahiStringList {
+ struct AvahiStringList *next; /**< Pointer to the next linked list element */
+ size_t size; /**< Size of text[] */
+ uint8_t text[1]; /**< Character data */
+} AvahiStringList;
+
+/** @{ \name Construction and destruction */
+
+/** Create a new string list by taking a variable list of NUL
+ * terminated strings. The strings are copied using g_strdup(). The
+ * argument list must be terminated by a NULL pointer. */
+AvahiStringList *avahi_string_list_new(const char *txt, ...) AVAHI_GCC_SENTINEL;
+
+/** \cond fulldocs */
+/** Same as avahi_string_list_new() but pass a va_list structure */
+AvahiStringList *avahi_string_list_new_va(va_list va);
+/** \endcond */
+
+/** Create a new string list from a string array. The strings are
+ * copied using g_strdup(). length should contain the length of the
+ * array, or -1 if the array is NULL terminated*/
+AvahiStringList *avahi_string_list_new_from_array(const char **array, int length);
+
+/** Free a string list */
+void avahi_string_list_free(AvahiStringList *l);
+
+/** @} */
+
+/** @{ \name Adding strings */
+
+/** Append a NUL terminated string to the specified string list. The
+ * passed string is copied using g_strdup(). Returns the new list
+ * start. */
+AvahiStringList *avahi_string_list_add(AvahiStringList *l, const char *text);
+
+/** Append a new NUL terminated formatted string to the specified string list */
+AvahiStringList *avahi_string_list_add_printf(AvahiStringList *l, const char *format, ...) AVAHI_GCC_PRINTF_ATTR23;
+
+/** \cond fulldocs */
+/** Append a new NUL terminated formatted string to the specified string list */
+AvahiStringList *avahi_string_list_add_vprintf(AvahiStringList *l, const char *format, va_list va);
+/** \endcond */
+
+/** Append an arbitrary length byte string to the list. Returns the
+ * new list start. */
+AvahiStringList *avahi_string_list_add_arbitrary(AvahiStringList *l, const uint8_t *text, size_t size);
+
+/** Append a new entry to the string list. The string is not filled
+with data. The caller should fill in string data afterwards by writing
+it to l->text, where l is the pointer returned by this function. This
+function exists solely to optimize a few operations where otherwise
+superfluous string copying would be necessary. */
+AvahiStringList*avahi_string_list_add_anonymous(AvahiStringList *l, size_t size);
+
+/** Same as avahi_string_list_add(), but takes a variable number of
+ * NUL terminated strings. The argument list must be terminated by a
+ * NULL pointer. Returns the new list start. */
+AvahiStringList *avahi_string_list_add_many(AvahiStringList *r, ...) AVAHI_GCC_SENTINEL;
+
+/** \cond fulldocs */
+/** Same as avahi_string_list_add_many(), but use a va_list
+ * structure. Returns the new list start. */
+AvahiStringList *avahi_string_list_add_many_va(AvahiStringList *r, va_list va);
+/** \endcond */
+
+/** @} */
+
+/** @{ \name String list operations */
+
+/** Convert the string list object to a single character string,
+ * seperated by spaces and enclosed in "". avahi_free() the result! This
+ * function doesn't work well with string that contain NUL bytes. */
+char* avahi_string_list_to_string(AvahiStringList *l);
+
+/** \cond fulldocs */
+/** Serialize the string list object in a way that is compatible with
+ * the storing of DNS TXT records. Strings longer than 255 bytes are truncated. */
+size_t avahi_string_list_serialize(AvahiStringList *l, void * data, size_t size);
+
+/** Inverse of avahi_string_list_serialize() */
+int avahi_string_list_parse(const void *data, size_t size, AvahiStringList **ret);
+/** \endcond */
+
+/** Compare to string lists */
+int avahi_string_list_equal(const AvahiStringList *a, const AvahiStringList *b);
+
+/** Copy a string list */
+AvahiStringList *avahi_string_list_copy(const AvahiStringList *l);
+
+/** Reverse the string list. */
+AvahiStringList* avahi_string_list_reverse(AvahiStringList *l);
+
+/** Return the number of elements in the string list */
+unsigned avahi_string_list_length(const AvahiStringList *l);
+
+/** @} */
+
+/** @{ \name Accessing items */
+
+/** Returns the next item in the string list */
+AvahiStringList *avahi_string_list_get_next(AvahiStringList *l);
+
+/** Returns the text for the current item */
+uint8_t *avahi_string_list_get_text(AvahiStringList *l);
+
+/** Returns the size of the current text */
+size_t avahi_string_list_get_size(AvahiStringList *l);
+
+/** @} */
+
+/** @{ \name DNS-SD TXT pair handling */
+
+/** Find the string list entry for the given DNS-SD TXT key */
+AvahiStringList *avahi_string_list_find(AvahiStringList *l, const char *key);
+
+/** Return the DNS-SD TXT key and value for the specified string list
+ * item. If size is not NULL it will be filled with the length of
+ * value. (for strings containing NUL bytes). If the entry doesn't
+ * contain a value *value will be set to NULL. You need to
+ * avahi_free() the strings returned in *key and *value. */
+int avahi_string_list_get_pair(AvahiStringList *l, char **key, char **value, size_t *size);
+
+/** Add a new DNS-SD TXT key value pair to the string list. value may
+ * be NULL in case you want to specify a key without a value */
+AvahiStringList *avahi_string_list_add_pair(AvahiStringList *l, const char *key, const char *value);
+
+/** Same as avahi_string_list_add_pair() but allow strings containing NUL bytes in *value. */
+AvahiStringList *avahi_string_list_add_pair_arbitrary(AvahiStringList *l, const char *key, const uint8_t *value, size_t size);
+
+/** @} */
+
+/** \cond fulldocs */
+/** Try to find a magic service cookie in the specified DNS-SD string
+ * list. Or return AVAHI_SERVICE_COOKIE_INVALID if none is found. */
+uint32_t avahi_string_list_get_service_cookie(AvahiStringList *l);
+/** \endcond */
+
+AVAHI_C_DECL_END
+
+#endif
+
diff --git a/linux/avahi-common/thread-watch.h b/linux/avahi-common/thread-watch.h
new file mode 100644
index 0000000..d5b3c86
--- /dev/null
+++ b/linux/avahi-common/thread-watch.h
@@ -0,0 +1,82 @@
+#ifndef foothreadedwatchhfoo
+#define foothreadedwatchhfoo
+
+/* $Id: thread-watch.h 1244 2006-08-06 11:53:01Z lennart $ */
+
+/***
+ This file is part of avahi.
+
+ avahi is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ avahi is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
+ Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with avahi; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA.
+***/
+
+/** \file thread-watch.h Threaded poll() based main loop implementation */
+
+#include <sys/poll.h>
+#include <avahi-common/cdecl.h>
+#include <avahi-common/watch.h>
+
+AVAHI_C_DECL_BEGIN
+
+/** A main loop object that runs an AvahiSimplePoll in its own thread. \since 0.6.4 */
+typedef struct AvahiThreadedPoll AvahiThreadedPoll;
+
+/** Create a new event loop object. This will allocate the internal
+ * AvahiSimplePoll, but will not start the helper thread. \since 0.6.4 */
+AvahiThreadedPoll *avahi_threaded_poll_new(void);
+
+/** Free an event loop object. Ths will stop the associated evet loop
+ * thread (if it is running). \since 0.6.4 */
+void avahi_threaded_poll_free(AvahiThreadedPoll *p);
+
+/** Return the abstracted poll API object for this event loop
+ * object. The will return the same pointer each time it is
+ * called. \since 0.6.4 */
+const AvahiPoll* avahi_threaded_poll_get(AvahiThreadedPoll *p);
+
+/** Start the event loop helper thread. After the thread has started
+ * you must make sure to access the event loop object
+ * (AvahiThreadedPoll, AvahiPoll and all its associated objects)
+ * synchronized, i.e. with proper locking. You may want to use
+ * avahi_threaded_poll_lock()/avahi_threaded_poll_unlock() for this,
+ * which will lock the the entire event loop. Please note that event
+ * loop callback functions are called from the event loop helper thread
+ * with that lock held, i.e. avahi_threaded_poll_lock() calls are not
+ * required from event callbacks. \since 0.6.4 */
+int avahi_threaded_poll_start(AvahiThreadedPoll *p);
+
+/** Request that the event loop quits and the associated thread
+ stops. Call this from outside the helper thread if you want to shut
+ it down. \since 0.6.4 */
+int avahi_threaded_poll_stop(AvahiThreadedPoll *p);
+
+/** Request that the event loop quits and the associated thread
+ stops. Call this from inside the helper thread if you want to shut it
+ down. \since 0.6.4 */
+void avahi_threaded_poll_quit(AvahiThreadedPoll *p);
+
+/** Lock the main loop object. Use this if you want to access the event
+ * loop objects (such as creating a new event source) from anything
+ * else but the event loop helper thread, i.e. from anything else but event
+ * loop callbacks \since 0.6.4 */
+void avahi_threaded_poll_lock(AvahiThreadedPoll *p);
+
+/** Unlock the event loop object, use this as counterpart to
+ * avahi_threaded_poll_lock() \since 0.6.4 */
+void avahi_threaded_poll_unlock(AvahiThreadedPoll *p);
+
+AVAHI_C_DECL_END
+
+#endif
diff --git a/linux/avahi-common/timeval.h b/linux/avahi-common/timeval.h
new file mode 100644
index 0000000..718b49e
--- /dev/null
+++ b/linux/avahi-common/timeval.h
@@ -0,0 +1,56 @@
+#ifndef footimevalhfoo
+#define footimevalhfoo
+
+/* $Id: timeval.h 1244 2006-08-06 11:53:01Z lennart $ */
+
+/***
+ This file is part of avahi.
+
+ avahi is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ avahi is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
+ Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with avahi; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA.
+***/
+
+/** \file timeval.h Functions to facilitate timeval handling */
+
+#include <inttypes.h>
+#include <sys/time.h>
+
+#include <avahi-common/cdecl.h>
+
+AVAHI_C_DECL_BEGIN
+
+/** A numeric data type for storing microsecond values. (signed 64bit integer) */
+typedef int64_t AvahiUsec;
+
+/** Compare two timeval structures and return a negative value when a < b, 0 when a == b and a positive value otherwise */
+int avahi_timeval_compare(const struct timeval *a, const struct timeval *b);
+
+/** Calculate the difference between two timeval structures as microsecond value */
+AvahiUsec avahi_timeval_diff(const struct timeval *a, const struct timeval *b);
+
+/** Add a number of microseconds to the specified timeval structure and return it. *a is modified. */
+struct timeval* avahi_timeval_add(struct timeval *a, AvahiUsec usec);
+
+/** Return the difference between the current time and *a. Positive if *a was earlier */
+AvahiUsec avahi_age(const struct timeval *a);
+
+/** Fill *tv with the current time plus "ms" milliseconds plus an
+ * extra jitter of "j" milliseconds. Pass 0 for j if you don't want
+ * the jitter */
+struct timeval *avahi_elapse_time(struct timeval *tv, unsigned ms, unsigned j);
+
+AVAHI_C_DECL_END
+
+#endif
diff --git a/linux/avahi-common/watch.h b/linux/avahi-common/watch.h
new file mode 100644
index 0000000..c9b71a8
--- /dev/null
+++ b/linux/avahi-common/watch.h
@@ -0,0 +1,99 @@
+#ifndef foowatchhfoo
+#define foowatchhfoo
+
+/* $Id: watch.h 1335 2006-11-19 08:04:07Z lathiat $ */
+
+/***
+ This file is part of avahi.
+
+ avahi is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ avahi is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
+ Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with avahi; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA.
+***/
+
+/** \file watch.h Simplistic main loop abstraction */
+
+#include <sys/poll.h>
+#include <sys/time.h>
+
+#include <avahi-common/cdecl.h>
+
+AVAHI_C_DECL_BEGIN
+
+/** An I/O watch object */
+typedef struct AvahiWatch AvahiWatch;
+
+/** A timeout watch object */
+typedef struct AvahiTimeout AvahiTimeout;
+
+/** An event polling abstraction object */
+typedef struct AvahiPoll AvahiPoll;
+
+/** Type of watch events */
+typedef enum {
+ AVAHI_WATCH_IN = POLLIN, /**< Input event */
+ AVAHI_WATCH_OUT = POLLOUT, /**< Output event */
+ AVAHI_WATCH_ERR = POLLERR, /**< Error event */
+ AVAHI_WATCH_HUP = POLLHUP /**< Hangup event */
+} AvahiWatchEvent;
+
+/** Called whenever an I/O event happens on an I/O watch */
+typedef void (*AvahiWatchCallback)(AvahiWatch *w, int fd, AvahiWatchEvent event, void *userdata);
+
+/** Called when the timeout is reached */
+typedef void (*AvahiTimeoutCallback)(AvahiTimeout *t, void *userdata);
+
+/** Defines an abstracted event polling API. This may be used to
+ connect Avahi to other main loops. This is losely based on Unix
+ poll(2). A consumer will call watch_new() for all file descriptors it
+ wants to listen for events on. In addition he can call timeout_new()
+ to define time based events .*/
+struct AvahiPoll {
+
+ /** Some abstract user data usable by the provider of the API */
+ void* userdata;
+
+ /** Create a new watch for the specified file descriptor and for
+ * the specified events. The API will call the callback function
+ * whenever any of the events happens. */
+ AvahiWatch* (*watch_new)(const AvahiPoll *api, int fd, AvahiWatchEvent event, AvahiWatchCallback callback, void *userdata);
+
+ /** Update the events to wait for. It is safe to call this function from an AvahiWatchCallback */
+ void (*watch_update)(AvahiWatch *w, AvahiWatchEvent event);
+
+ /** Return the events that happened. It is safe to call this function from an AvahiWatchCallback */
+ AvahiWatchEvent (*watch_get_events)(AvahiWatch *w);
+
+ /** Free a watch. It is safe to call this function from an AvahiWatchCallback */
+ void (*watch_free)(AvahiWatch *w);
+
+ /** Set a wakeup time for the polling loop. The API will call the
+ callback function when the absolute time *tv is reached. If tv is
+ NULL, the timeout is disabled. After the timeout expired the
+ callback function will be called and the timeout is disabled. You
+ can reenable it by calling timeout_update() */
+ AvahiTimeout* (*timeout_new)(const AvahiPoll *api, const struct timeval *tv, AvahiTimeoutCallback callback, void *userdata);
+
+ /** Update the absolute expiration time for a timeout, If tv is
+ * null, the timeout is disabled. It is safe to call this function from an AvahiTimeoutCallback */
+ void (*timeout_update)(AvahiTimeout *, const struct timeval *tv);
+
+ /** Free a timeout. It is safe to call this function from an AvahiTimeoutCallback */
+ void (*timeout_free)(AvahiTimeout *t);
+};
+
+AVAHI_C_DECL_END
+
+#endif
+
diff --git a/linux/cusblinux.c b/linux/cusblinux.c
new file mode 100644
index 0000000..3a12fca
--- /dev/null
+++ b/linux/cusblinux.c
@@ -0,0 +1,673 @@
+/*
+ * cusblinux.cpp
+ *
+ * Filled in by Daniel Risacher on 6/21/05
+ * Filled in more by Patrick McNeil on 6/27/05
+ * Copyright 2005 Phidgets Inc. All rights reserved.
+ *
+ */
+
+#include "stdafx.h"
+#include "cusb.h"
+
+int CUSBCloseHandle(CPhidgetHandle phid) {
+ int ret = 0;
+ int result = EPHIDGET_OK;
+
+ if (!phid)
+ return EPHIDGET_INVALIDARG;
+
+ CPhidget_clearStatusFlag(&phid->status, PHIDGET_ATTACHED_FLAG, &phid->lock);
+
+ if (phid->deviceHandle == NULL)
+ return EPHIDGET_NOTATTACHED;
+
+ CThread_join(&phid->readThread);
+
+ if((ret = usb_release_interface((usb_dev_handle *) phid->deviceHandle, phid->deviceDef->pdd_iid)) < 0)
+ {
+ switch(ret)
+ {
+ case -ENODEV:
+ //usb_release_interface called after the device was unplugged
+ LOG(PHIDGET_LOG_WARNING, "usb_release_interface called on unplugged device.");
+ break;
+ default:
+ LOG(PHIDGET_LOG_ERROR, "usb_release_interface failed with error code: %d \"%s\"", ret, strerror(-ret));
+ }
+ }
+
+ //if we notice that PHIDGET_USB_ERROR_FLAG is set, then reset this device before closing
+ //this gives us a better chance of getting it back if something has gone wrong.
+ if(CPhidget_statusFlagIsSet(phid->status, PHIDGET_USB_ERROR_FLAG))
+ {
+ LOG(PHIDGET_LOG_WARNING,"PHIDGET_USB_ERROR_FLAG is set - resetting device.");
+ if((ret = usb_reset((usb_dev_handle *) phid->deviceHandle)) < 0)
+ {
+ LOG(PHIDGET_LOG_ERROR, "usb_reset failed with error code: %d \"%s\"", ret, strerror(-ret));
+ result = EPHIDGET_UNEXPECTED;
+ }
+ }
+
+ if((ret = usb_close((usb_dev_handle *) phid->deviceHandle)) < 0)
+ {
+ LOG(PHIDGET_LOG_ERROR, "usb_close failed with error code: %d \"%s\"", ret, strerror(-ret));
+ result = EPHIDGET_UNEXPECTED;
+ }
+
+ phid->deviceHandle = NULL;
+
+ return result;
+}
+
+int CUSBSendPacket(CPhidgetHandle phid, unsigned char *buffer) {
+ int BytesWritten = 0;
+
+ if (!phid)
+ return EPHIDGET_INVALIDARG;
+
+ if (!CPhidget_statusFlagIsSet(phid->status, PHIDGET_ATTACHED_FLAG)
+ && !CPhidget_statusFlagIsSet(phid->status, PHIDGET_ATTACHING_FLAG))
+ return EPHIDGET_NOTATTACHED;
+
+ if (phid->deviceHandle == NULL)
+ {
+ LOG(PHIDGET_LOG_WARNING,"Handle for writing is not valid");
+ return EPHIDGET_UNEXPECTED;
+ }
+
+ if(phid->interruptOutEndpoint)
+ {
+ BytesWritten = usb_interrupt_write((usb_dev_handle *)phid->deviceHandle,
+ phid->deviceDef->pdd_iid+1,
+ (char *)buffer,
+ phid->outputReportByteLength, /* size */
+ 500); /* FIXME? timeout */
+ }
+ else
+ {
+ BytesWritten = usb_control_msg((usb_dev_handle *)phid->deviceHandle,
+ USB_ENDPOINT_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+ USB_REQ_SET_CONFIGURATION,
+ 0x0200, /* value */
+ phid->deviceDef->pdd_iid, /* index*/
+ (char *)buffer,
+ phid->outputReportByteLength, /* size */
+ 500); /* FIXME? timeout */
+ }
+
+ if(BytesWritten < 0)
+ {
+ switch(BytesWritten)
+ {
+ case -ETIMEDOUT: //important case?
+ return EPHIDGET_TIMEOUT;
+ case -ENODEV:
+ //device is gone - unplugged.
+ LOG(PHIDGET_LOG_INFO, "Device was unplugged - detach.");
+ return EPHIDGET_NOTATTACHED;
+ default:
+ LOG(PHIDGET_LOG_ERROR, "usb_control_msg failed with error code: %d \"%s\"", BytesWritten, strerror(-BytesWritten));
+ return EPHIDGET_UNEXPECTED;
+ }
+ }
+
+ if (BytesWritten != phid->outputReportByteLength)
+ {
+ LOG(PHIDGET_LOG_WARNING,"Failure in CUSBSendPacket - Report Length"
+ ": %d, bytes written: %d",
+ (int)phid->outputReportByteLength, (int)BytesWritten);
+ return EPHIDGET_UNEXPECTED;
+ }
+
+ return EPHIDGET_OK;
+}
+
+int CUSBSetLabel(CPhidgetHandle phid, char *buffer) {
+ int BytesWritten = 0;
+ int size = buffer[0];
+
+ if(size>22) return EPHIDGET_INVALID;
+
+ if (!phid)
+ return EPHIDGET_INVALIDARG;
+
+ if (!CPhidget_statusFlagIsSet(phid->status, PHIDGET_ATTACHED_FLAG)
+ && !CPhidget_statusFlagIsSet(phid->status, PHIDGET_ATTACHING_FLAG))
+ return EPHIDGET_NOTATTACHED;
+
+ if (phid->deviceHandle == NULL)
+ {
+ LOG(PHIDGET_LOG_WARNING,"Handle for writing is not valid");
+ return EPHIDGET_UNEXPECTED;
+ }
+
+ BytesWritten = usb_control_msg(phid->deviceHandle,
+ USB_ENDPOINT_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE,
+ USB_REQ_SET_DESCRIPTOR,
+ 0x0304, /* value */
+ 0x0409, /* index*/
+ (char *)buffer,
+ size, /* size */
+ 500); /* FIXME? timeout */
+
+ if(BytesWritten < 0)
+ {
+ switch(BytesWritten)
+ {
+ case -ETIMEDOUT: //important case?
+ default:
+ LOG(PHIDGET_LOG_INFO, "usb_control_msg failed with error code: %d \"%s\"", BytesWritten, strerror(-BytesWritten));
+ return EPHIDGET_UNSUPPORTED;
+ }
+ }
+
+ if (BytesWritten != size)
+ {
+ LOG(PHIDGET_LOG_WARNING,"Failure in CUSBSetLabel - Report Length"
+ ": %d, bytes written: %d",
+ size, (int)BytesWritten);
+ return EPHIDGET_UNEXPECTED;
+ }
+
+ return EPHIDGET_OK;
+}
+
+/* Buffer should be at least 8 bytes long */
+int CUSBReadPacket(CPhidgetHandle phid, unsigned char *buffer) {
+ int BytesRead = 0;
+
+ if (!phid)
+ return EPHIDGET_INVALIDARG;
+
+ if (!CPhidget_statusFlagIsSet(phid->status, PHIDGET_ATTACHED_FLAG)
+ && !CPhidget_statusFlagIsSet(phid->status, PHIDGET_ATTACHING_FLAG))
+ return EPHIDGET_NOTATTACHED;
+
+ if (phid->deviceHandle == NULL)
+ {
+ LOG(PHIDGET_LOG_WARNING,"Handle for writing is not valid");
+ return EPHIDGET_UNEXPECTED;
+ }
+
+ BytesRead = usb_interrupt_read((usb_dev_handle *)phid->deviceHandle,
+ phid->deviceDef->pdd_iid+1,
+ (char *)buffer,
+ phid->inputReportByteLength,
+ 500);
+
+ if (BytesRead < 0)
+ {
+ switch(BytesRead)
+ {
+ // A timeout occured, but we'll just try again
+ case -ETIMEDOUT:
+ LOG(PHIDGET_LOG_VERBOSE, "usb_interrupt_read timeout: %d \"%s\"", BytesRead, strerror(-BytesRead));
+ return EPHIDGET_TIMEOUT;
+ case -EBUSY:
+ //This happens when someone else calls claim_interface on this interface (a manager for ex.) - basically just wait until they release it.
+ //This will happen if an open occurs in another app which (for some reason) can steal the interface from this one.
+ LOG(PHIDGET_LOG_INFO, "Device is busy on Read - try again.");
+ return EPHIDGET_TRYAGAIN;
+ case -ENOSPC:
+ //This happens when too many Interrupt devices are plugged in (Phidgets, HID devices, etc.
+ LOG(PHIDGET_LOG_ERROR, "USB Interrupt bandwidth exceeded. Try distributing devices more evenly. Reads will continue, but data is being lost.");
+ goto tryagain;
+ case -ENODEV:
+ //device is gone - unplugged.
+ LOG(PHIDGET_LOG_INFO, "Device was unplugged - detach.");
+ return EPHIDGET_NOTATTACHED;
+ default:
+ LOG(PHIDGET_LOG_ERROR, "usb_interrupt_read returned: %d \"%s\"", BytesRead, strerror(-BytesRead));
+ goto tryagain;
+ }
+ }
+
+ if (BytesRead != phid->inputReportByteLength)
+ {
+ //Generally means the device was unplugged, but can mean that there is not enough Interrupt bandwidth
+ //We keep trying and we'll get data, just not all data
+ LOG(PHIDGET_LOG_WARNING,"Failure in CUSBReadPacket - Report Length"
+ ": %d, bytes read: %d. Probably trying to use too many Phidgets at once, and some data is being lost.",
+ (int)phid->inputReportByteLength, (int)BytesRead);
+ goto tryagain;
+ }
+
+ phid->tryAgainCounter = 0;
+ return EPHIDGET_OK;
+
+ //if we see too many tryagains in a row, then we assume something has actually gone wrong and reset the device
+tryagain:
+ phid->tryAgainCounter++;
+ if(phid->tryAgainCounter > 30) //this will be hit in < 1 second for all devices
+ {
+ LOG(PHIDGET_LOG_ERROR, "CUSBReadPacket returned EPHIDGET_TRYAGAIN too many times in a row - reset device.", BytesRead, strerror(-BytesRead));
+ phid->tryAgainCounter = 0;
+ return EPHIDGET_UNEXPECTED;
+ }
+ return EPHIDGET_TRYAGAIN;
+}
+
+static int getLabelString(CPhidgetHandle phid, struct usb_dev_handle *udev)
+{
+ int len = 0;
+ char labelBuf[22];
+ memset(labelBuf, 0, sizeof(labelBuf));
+
+ //Note that this returns the whole descriptor, including the length and type bytes
+ len = usb_get_string(udev, 4, 0, (char *)labelBuf, 22);
+
+ if(len < 0)
+ {
+ switch(len)
+ {
+ case -ETIMEDOUT: //important case?
+ default:
+ LOG(PHIDGET_LOG_INFO, "usb_get_string_simple failed in CUSBGetDeviceCapabilities with error code: %d \"%s\" while reading label - this probably just means the device doesn't support labels, so this is fine.", len, strerror(-len));
+ }
+ phid->label[0]='\0';
+ return EPHIDGET_OK;
+ }
+ else
+ return decodeLabelString(labelBuf, phid->label, phid->serialNumber);
+}
+
+int CUSBRefreshLabelString(CPhidgetHandle phid)
+{
+ return getLabelString(phid, (struct usb_dev_handle *)phid->deviceHandle);
+}
+
+int CUSBGetDeviceCapabilities(CPhidgetHandle phid, struct usb_device *dev, struct usb_dev_handle *udev) {
+ unsigned char buf[255];
+ int len = 0, i = 0;
+ struct usb_interface_descriptor *interfaceDesc;
+ struct usb_config_descriptor configDesc;
+
+ memset(buf, 0, sizeof(buf));
+
+// if(usb_device->config->interface->bNumEndpoints == 2)
+// {
+// LOG(PHIDGET_LOG_INFO, "Using Interrupt OUT endpoing to Host->Device communication.");
+// phid->interruptOutEndpoint = PTRUE;
+// }
+// else
+// {
+// LOG(PHIDGET_LOG_INFO, "Using Control endpoing to Host->Device communication.");
+// phid->interruptOutEndpoint = PFALSE;
+// }
+
+ //Get config descriptor
+ len = usb_get_descriptor(udev, USB_DT_CONFIG, 0, (void *)&configDesc, USB_DT_CONFIG_SIZE);
+
+ if(len == USB_DT_CONFIG_SIZE)
+ {
+ //Get the rest
+ len = usb_get_descriptor(udev, USB_DT_CONFIG, 0, (void *)buf, configDesc.wTotalLength);
+
+ if(len == configDesc.wTotalLength)
+ {
+ int i;
+ interfaceDesc = NULL;
+ struct usb_descriptor_header *currentDesc;
+
+ //Find the interface Descriptor
+ for(i=0;i<configDesc.wTotalLength-2;i+=currentDesc->bLength)
+ {
+ currentDesc = (struct usb_descriptor_header *)&buf[i];
+ if (currentDesc->bDescriptorType == USB_DT_INTERFACE)
+ {
+ interfaceDesc = (struct usb_interface_descriptor *)&buf[i];
+ if(interfaceDesc->bInterfaceNumber == phid->deviceDef->pdd_iid)
+ break;
+ else
+ interfaceDesc = NULL;
+ }
+ }
+
+ if(interfaceDesc == NULL)
+ {
+ LOG(PHIDGET_LOG_ERROR, "Couldn't find interface descriptor!");
+ return EPHIDGET_UNEXPECTED;
+ }
+
+ if(interfaceDesc->bNumEndpoints == 2)
+ {
+ LOG(PHIDGET_LOG_INFO, "Using Interrupt OUT Endpoint for Host->Device communication.");
+ phid->interruptOutEndpoint = PTRUE;
+ }
+ else
+ {
+ LOG(PHIDGET_LOG_INFO, "Using Control Endpoint for Host->Device communication.");
+ phid->interruptOutEndpoint = PFALSE;
+ }
+ }
+ else if (len < 0)
+ {
+ LOG(PHIDGET_LOG_ERROR, "usb_get_descriptor failed in CUSBGetDeviceCapabilities with error code: %d \"%s\"", len, strerror(-len));
+ return EPHIDGET_UNEXPECTED;
+ }
+ else
+ {
+ LOG(PHIDGET_LOG_ERROR, "Couldn't get interface descriptor in CUSBGetDeviceCapabilities");
+ return EPHIDGET_UNEXPECTED;
+ }
+ }
+ else if (len < 0)
+ {
+ LOG(PHIDGET_LOG_ERROR, "usb_get_descriptor failed in CUSBGetDeviceCapabilities with error code: %d \"%s\"", len, strerror(-len));
+ return EPHIDGET_UNEXPECTED;
+ }
+ else
+ {
+ LOG(PHIDGET_LOG_ERROR, "Couldn't get interface descriptor in CUSBGetDeviceCapabilities");
+ return EPHIDGET_UNEXPECTED;
+ }
+
+ //Get a HID descriptor
+ len = usb_control_msg(udev, USB_ENDPOINT_IN+1,
+ USB_REQ_GET_DESCRIPTOR,
+ (USB_DT_REPORT << 8) + 0, phid->deviceDef->pdd_iid, (char*)buf,
+ sizeof(buf), 500 /* ms timeout */);
+
+ if(len < 0)
+ {
+ switch(len)
+ {
+ case -ETIMEDOUT: //important case?
+ default:
+ LOG(PHIDGET_LOG_ERROR, "usb_control_msg failed in CUSBGetDeviceCapabilities with error code: %d \"%s\"", len, strerror(-len));
+ return EPHIDGET_UNEXPECTED;
+ }
+ }
+
+ if(len >= 10)
+ {
+ for(i=10;i<len;i++) {
+ if(buf[i]==0x81 && buf[i-2]==0x95)
+ phid->inputReportByteLength=buf[i-1];
+ else if(buf[i]==0x81 && buf[i-4]==0x95)
+ phid->inputReportByteLength=buf[i-3];
+ if(buf[i]==0x91 && buf[i-2]==0x95)
+ phid->outputReportByteLength=buf[i-1];
+ else if(buf[i]==0x91 && buf[i-4]==0x95)
+ phid->outputReportByteLength=buf[i-3];
+ }
+ }
+ else
+ {
+ LOG(PHIDGET_LOG_ERROR, "Couldn't get report lengths in CUSBGetDeviceCapabilities");
+ return EPHIDGET_UNEXPECTED;
+ }
+
+ return getLabelString(phid, udev);
+}
+
+/*
+ This needs to maintain a list of devices - it's used by the phidget manager for
+ keeping track of attach and detach events. (On Mac this is handled with
+ notifications, so this is not needed.) - PM
+*/
+int CUSBBuildList(CPhidgetList **curList) {
+ int MemberIndex, i, ret, found;
+ unsigned long Length;
+ CPhidgetList *traverse;
+ Length = 0;
+ MemberIndex = 0;
+ struct usb_bus *bus;
+ struct usb_device *dev;
+ usb_dev_handle *udev;
+ CPhidgetHandle phid;
+ char unique_name[1024];
+
+ TESTPTR(curList)
+
+ usb_init();
+ if((ret = usb_find_busses()) < 0)
+ {
+ LOG(PHIDGET_LOG_ERROR, "usb_find_busses failed with error code: %d \"%s\"", ret, strerror(-ret));
+ }
+ if((ret = usb_find_devices()) < 0)
+ {
+ LOG(PHIDGET_LOG_ERROR, "usb_find_devices failed with error code: %d \"%s\"", ret, strerror(-ret));
+ }
+
+ //search through all USB devices
+ for (bus = usb_busses; bus; bus = bus->next) {
+ for (dev = bus->devices; dev; dev = dev->next) {
+
+ snprintf(unique_name,1024,"%s%s",bus->dirname, dev->filename);
+
+ //LOG(PHIDGET_LOG_VERBOSE,"New Device: %s", unique_name);
+
+ found = PFALSE;
+ if (AttachedDevices) {
+ // we need to loop all the way through because composite devices will appear twice in the list with the same 'unique' name
+ for (traverse = AttachedDevices; traverse; traverse=traverse->next) {
+ if (!strcmp((char *)traverse->phid->CPhidgetFHandle, unique_name)) {
+ CList_addToList((CListHandle *)curList, traverse->phid, CPhidget_areEqual);
+ found = PTRUE;
+ }
+ }
+ if(found) goto next;
+ }
+
+
+ for (i = 1; i<PHIDGET_DEVICE_COUNT; i++) {
+ if ((dev->descriptor.idVendor == Phid_Device_Def[i].pdd_vid) &&
+ (dev->descriptor.idProduct == Phid_Device_Def[i].pdd_pid))
+ {
+ if (!(phid = (CPhidgetHandle)malloc(sizeof (*phid))))
+ return EPHIDGET_NOMEMORY;
+ ZEROMEM(phid, sizeof(*phid));
+
+ //LOG(PHIDGET_LOG_DEBUG,"New Device: %s",(char *)Phid_DeviceName[Phid_Device_Def[i].pdd_did]);
+
+ udev = usb_open(dev);
+ if(udev) {
+ if (dev->descriptor.bcdDevice < 0x100)
+ phid->deviceVersion = dev->descriptor.bcdDevice * 100;
+ else
+ phid->deviceVersion = ((dev->descriptor.bcdDevice >> 8) * 100) + ((dev->descriptor.bcdDevice & 0xff));
+ phid->deviceType = (char *)Phid_DeviceName[Phid_Device_Def[i].pdd_did];
+
+ CPhidget_setStatusFlag(&phid->status, PHIDGET_ATTACHED_FLAG, &phid->lock);
+ phid->deviceIDSpec = Phid_Device_Def[i].pdd_sdid;
+ phid->deviceDef = &Phid_Device_Def[i];
+ phid->deviceID = Phid_Device_Def[i].pdd_did;
+ phid->ProductID = dev->descriptor.idProduct;
+ phid->VendorID = dev->descriptor.idVendor;
+
+ if (dev->descriptor.iSerialNumber) {
+ char string[256];
+ memset(string, 0, 256);
+ if((ret = usb_get_string_simple(udev, dev->descriptor.iSerialNumber, string, sizeof(string))) < 0)
+ {
+ LOG(PHIDGET_LOG_ERROR, "usb_get_string_simple failed with error code: %d \"%s\"", ret, strerror(-ret));
+ LOG(PHIDGET_LOG_INFO, "This usually means you need to run as root");
+ if((ret = usb_close(udev)) < 0)
+ {
+ LOG(PHIDGET_LOG_ERROR, "usb_close failed with error code: %d \"%s\"", ret, strerror(-ret));
+ }
+ free(phid);
+ goto next;
+ }
+ else
+ {
+ phid->serialNumber = atol(string);
+ getLabelString(phid, udev);
+ }
+ }
+ phid->specificDevice = TRUE;
+ phid->attr = Phid_Device_Def[i].pdd_attr;
+
+ if(!(phid->CPhidgetFHandle = strdup(unique_name)))
+ return EPHIDGET_NOMEMORY;
+
+ LOG(PHIDGET_LOG_INFO, "New device in CUSBBuildList: %s", (char *)phid->CPhidgetFHandle);
+
+ if((ret = usb_close(udev)) < 0)
+ {
+ LOG(PHIDGET_LOG_ERROR, "usb_close failed with error code: %d \"%s\"", ret, strerror(-ret));
+ }
+ CList_addToList((CListHandle *)curList, phid, CPhidget_areEqual);
+ } //if(udev)
+ else
+ {
+ free(phid);
+ if((ret = usb_close(udev)) < 0)
+ {
+ LOG(PHIDGET_LOG_ERROR, "usb_close failed with error code: %d \"%s\"", ret, strerror(-ret));
+ }
+ }
+ } //vendor, product ids match
+ } /* iterate over phidget device table */
+next: ;
+ } /* iterate over USB devices */
+ } /* iterate over USB busses */
+ return EPHIDGET_OK;
+}
+
+void CUSBCleanup(void)
+{
+ ;
+}
+/*
+ CUSBOpenHandle takes a CPhidgetInfo structure, with
+ ProductID/VendorID/SerialNumber filled in.
+
+ Serial number is always filled in.
+*/
+int CUSBOpenHandle(CPhidgetHandle phid)
+{
+ int idVendor;
+ int idProduct;
+ int serial = 0;
+ int i,ret;
+ struct usb_bus *bus;
+ struct usb_device *dev;
+ usb_dev_handle *udev;
+
+ usb_init();
+ if((ret = usb_find_busses()) < 0)
+ {
+ LOG(PHIDGET_LOG_ERROR, "usb_find_busses failed with error code: %d \"%s\"", ret, strerror(-ret));
+ }
+ if((ret = usb_find_devices()) < 0)
+ {
+ LOG(PHIDGET_LOG_ERROR, "usb_find_devices failed with error code: %d \"%s\"", ret, strerror(-ret));
+ }
+
+ for (bus = usb_busses; bus; bus = bus->next) {
+ for (dev = bus->devices; dev; dev = dev->next) {
+ for (i = 1; i<PHIDGET_DEVICE_COUNT; i++) {
+ if (Phid_Device_Def[i].pdd_did == phid->deviceID) {
+ idVendor = Phid_Device_Def[i].pdd_vid;
+ idProduct = Phid_Device_Def[i].pdd_pid;
+ if ((dev->descriptor.idVendor == idVendor) && (dev->descriptor.idProduct == idProduct)) {
+ /* the vend/prod matches! */
+ udev = usb_open(dev);
+ if (udev) {
+ serial = -1;
+ if (dev->descriptor.iSerialNumber) {
+ char string[256];
+ if((ret = usb_get_string_simple(udev, dev->descriptor.iSerialNumber, string, sizeof(string))) < 0)
+ {
+ LOG(PHIDGET_LOG_WARNING, "usb_get_string_simple failed with error code: %d \"%s\"", ret, strerror(-ret));
+ LOG(PHIDGET_LOG_INFO, "This usually means you need to run as root");
+ if((ret = usb_close(udev)) < 0)
+ {
+ LOG(PHIDGET_LOG_ERROR, "usb_close failed with error code: %d \"%s\"", ret, strerror(-ret));
+ }
+ goto next;
+ }
+ else
+ {
+ serial = atol(string);
+ }
+ }
+ if (serial == phid->serialNumber) {
+ /* On Linux, the HID driver likes to claim Phidgets - we can disconnect it here.
+ Maybe the user has installed the kernel drivers for the interface kit or servo - disconnect them too (does this work)
+ Note this is Linux Only - PM
+ Note that we don't need to claim it if usbfs has it - this is what libusb uses. */
+#ifdef LIBUSB_HAS_DETACH_KERNEL_DRIVER_NP
+ char name[32];
+ if((ret = usb_get_driver_np(udev, Phid_Device_Def[i].pdd_iid, name, 32)) < 0)
+ {
+ LOG(PHIDGET_LOG_WARNING, "usb_get_driver_np failed with error code: %d \"%s\"", ret, strerror(-ret));
+ }
+ else
+ {
+ LOG(PHIDGET_LOG_INFO, "Kernel driver name: %s", name);
+ if(strncmp(name, "usbfs", 5)) //not usbfs
+ {
+ if((ret = usb_detach_kernel_driver_np(udev, Phid_Device_Def[i].pdd_iid)) < 0)
+ {
+ LOG(PHIDGET_LOG_WARNING, "usb_detach_kernel_driver_np failed with error code: %d \"%s\"", ret, strerror(-ret));
+ }
+ else
+ {
+ LOG(PHIDGET_LOG_INFO, "Successfully detached kernel driver: %s", name);
+ }
+ }
+ }
+#endif
+ if((ret = usb_claim_interface(udev, Phid_Device_Def[i].pdd_iid)) < 0)
+ {
+ LOG(PHIDGET_LOG_WARNING, "usb_claim_interface failed with error code: %d \"%s\"", ret, strerror(-ret));
+ if((ret = usb_close(udev)) < 0)
+ {
+ LOG(PHIDGET_LOG_ERROR, "usb_close failed with error code: %d \"%s\"", ret, strerror(-ret));
+ }
+ }
+ else
+ {
+ /* the serialnum is okay */
+
+ phid->deviceHandle = (HANDLE)udev;
+ phid->deviceIDSpec = Phid_Device_Def[i].pdd_sdid;
+ phid->deviceDef = &Phid_Device_Def[i];
+ phid->deviceType = (char *)Phid_DeviceName[Phid_Device_Def[i].pdd_did];
+
+ phid->ProductID = idProduct;
+ phid->VendorID = idVendor;
+ if (dev->descriptor.bcdDevice < 0x100)
+ phid->deviceVersion = dev->descriptor.bcdDevice * 100;
+ else
+ phid->deviceVersion = ((dev->descriptor.bcdDevice >> 8) * 100) + ((dev->descriptor.bcdDevice & 0xff));
+ phid->serialNumber = serial;
+
+ if((ret = CUSBGetDeviceCapabilities(phid, dev, udev)))
+ {
+ LOG(PHIDGET_LOG_ERROR, "CUSBGetDeviceCapabilities returned nonzero code: %d", ret);
+ }
+
+ phid->attr = Phid_Device_Def[i].pdd_attr;
+
+ return EPHIDGET_OK;
+ } /* usb_claim_interface */
+ } /* serial matches */
+ else
+ {
+ if((ret = usb_close(udev)) < 0)
+ {
+ LOG(PHIDGET_LOG_ERROR, "usb_close failed with error code: %d \"%s\"", ret, strerror(-ret));
+ }
+ }
+ } /* udev open */
+ else
+ {
+ if((ret = usb_close(udev)) < 0)
+ {
+ LOG(PHIDGET_LOG_ERROR, "usb_close failed with error code: %d \"%s\"", ret, strerror(-ret));
+ }
+ LOG(PHIDGET_LOG_WARNING, "usb_open failed - bad permission or what?");
+ }
+ } /* vendor/product match */
+ } /* deviceID matches in table */
+ } /* iterate over phidget device table */
+next: ;
+ } /* iterate over USB devices */
+ } /* iterate over USB busses */
+ return EPHIDGET_NOTFOUND;
+}
diff --git a/linux/zeroconf_avahi.c b/linux/zeroconf_avahi.c
new file mode 100644
index 0000000..98187bf
--- /dev/null
+++ b/linux/zeroconf_avahi.c
@@ -0,0 +1,1056 @@
+#include "stdafx.h"
+#include "csocket.h"
+#include "csocketevents.h"
+#include "cphidgetlist.h"
+#include "cphidgetmanager.h"
+#include "cphidgetdictionary.h"
+#include "cphidgetsbc.h"
+#include "zeroconf.h"
+
+#include "avahi-client/client.h"
+#include "avahi-client/lookup.h"
+
+#include "avahi-common/thread-watch.h"
+#include "avahi-common/malloc.h"
+#include "avahi-common/error.h"
+#include "avahi-common/domain.h"
+
+static int UninitializeZeroconf1(int lock);
+
+struct AvahiThreadedPoll {
+ void *simple_poll;
+ pthread_t thread_id;
+ pthread_mutex_t mutex;
+ int thread_running;
+ int retval;
+} ;
+
+#ifdef ZEROCONF_RUNTIME_LINKING
+typedef AvahiClient * (* avahi_client_new_type) (
+ const AvahiPoll *poll_api /**< The abstract event loop API to use */,
+ AvahiClientFlags flags /**< Some flags to modify the behaviour of the client library */,
+ AvahiClientCallback callback /**< A callback that is called whenever the state of the client changes. This may be NULL */,
+ void *userdata /**< Some arbitrary user data pointer that will be passed to the callback function */,
+ int *error /**< If creation of the client fails, this integer will contain the error cause. May be NULL if you aren't interested in the reason why avahi_client_new() failed. */);
+typedef void (* avahi_client_free_type)(AvahiClient *client);
+typedef const char * (* avahi_client_get_host_name_type) (AvahiClient *);
+typedef AvahiServiceBrowser * (* avahi_service_browser_new_type) (
+ AvahiClient *client,
+ AvahiIfIndex interface,
+ AvahiProtocol protocol,
+ const char *type,
+ const char *domain,
+ AvahiLookupFlags flags,
+ AvahiServiceBrowserCallback callback,
+ void *userdata);
+typedef AvahiServiceResolver * (* avahi_service_resolver_new_type)(
+ AvahiClient *client,
+ AvahiIfIndex interface,
+ AvahiProtocol protocol,
+ const char *name,
+ const char *type,
+ const char *domain,
+ AvahiProtocol aprotocol,
+ AvahiLookupFlags flags,
+ AvahiServiceResolverCallback callback,
+ void *userdata);
+typedef int (* avahi_service_resolver_free_type)(AvahiServiceResolver *r);
+typedef AvahiRecordBrowser * (* avahi_record_browser_new_type)(
+ AvahiClient *client,
+ AvahiIfIndex interface,
+ AvahiProtocol protocol,
+ const char *name,
+ uint16_t clazz,
+ uint16_t type,
+ AvahiLookupFlags flags,
+ AvahiRecordBrowserCallback callback,
+ void *userdata);
+typedef int (* avahi_record_browser_free_type)(AvahiRecordBrowser *);
+typedef int (* avahi_service_name_join_type)(char *p, size_t size, const char *name, const char *type, const char *domain);
+typedef const char *(* avahi_strerror_type)(int error);
+typedef int (* avahi_client_errno_type) (AvahiClient*);
+typedef AvahiThreadedPoll *(* avahi_threaded_poll_new_type)(void);
+typedef void (* avahi_threaded_poll_free_type)(AvahiThreadedPoll *p);
+typedef const AvahiPoll* (* avahi_threaded_poll_get_type)(AvahiThreadedPoll *p);
+typedef int (* avahi_threaded_poll_start_type)(AvahiThreadedPoll *p);
+typedef int (* avahi_threaded_poll_stop_type)(AvahiThreadedPoll *p);
+typedef void (* avahi_threaded_poll_quit_type)(AvahiThreadedPoll *p);
+typedef void (* avahi_threaded_poll_lock_type)(AvahiThreadedPoll *p);
+typedef void (* avahi_threaded_poll_unlock_type)(AvahiThreadedPoll *p);
+typedef const char *(* avahi_client_get_version_string_type)(AvahiClient *c);
+
+avahi_service_browser_new_type avahi_service_browser_new_ptr = NULL;
+avahi_service_resolver_new_type avahi_service_resolver_new_ptr = NULL;
+avahi_service_resolver_free_type avahi_service_resolver_free_ptr = NULL;
+avahi_record_browser_new_type avahi_record_browser_new_ptr = NULL;
+avahi_record_browser_free_type avahi_record_browser_free_ptr = NULL;
+avahi_service_name_join_type avahi_service_name_join_ptr = NULL;
+avahi_client_new_type avahi_client_new_ptr = NULL;
+avahi_client_free_type avahi_client_free_ptr = NULL;
+avahi_strerror_type avahi_strerror_ptr = NULL;
+avahi_client_errno_type avahi_client_errno_ptr = NULL;
+avahi_threaded_poll_new_type avahi_threaded_poll_new_ptr = NULL;
+avahi_threaded_poll_free_type avahi_threaded_poll_free_ptr = NULL;
+avahi_threaded_poll_get_type avahi_threaded_poll_get_ptr = NULL;
+avahi_threaded_poll_start_type avahi_threaded_poll_start_ptr = NULL;
+avahi_threaded_poll_stop_type avahi_threaded_poll_stop_ptr = NULL;
+avahi_threaded_poll_quit_type avahi_threaded_poll_quit_ptr = NULL;
+avahi_threaded_poll_lock_type avahi_threaded_poll_lock_ptr = NULL;
+avahi_threaded_poll_unlock_type avahi_threaded_poll_unlock_ptr = NULL;
+avahi_client_get_version_string_type avahi_client_get_version_string_ptr = NULL;
+#else
+#define avahi_service_browser_new_ptr avahi_service_browser_new
+#define avahi_service_resolver_new_ptr avahi_service_resolver_new
+#define avahi_service_resolver_free_ptr avahi_service_resolver_free
+#define avahi_record_browser_new_ptr avahi_record_browser_new
+#define avahi_record_browser_free_ptr avahi_record_browser_free
+#define avahi_service_name_join_ptr avahi_service_name_join
+#define avahi_client_new_ptr avahi_client_new
+#define avahi_client_free_ptr avahi_client_free
+#define avahi_strerror_ptr avahi_strerror
+#define avahi_client_errno_ptr avahi_client_errno
+#define avahi_threaded_poll_new_ptr avahi_threaded_poll_new
+#define avahi_threaded_poll_free_ptr avahi_threaded_poll_free
+#define avahi_threaded_poll_get_ptr avahi_threaded_poll_get
+#define avahi_threaded_poll_start_ptr avahi_threaded_poll_start
+#define avahi_threaded_poll_stop_ptr avahi_threaded_poll_stop
+#define avahi_threaded_poll_quit_ptr avahi_threaded_poll_quit
+#define avahi_threaded_poll_lock_ptr avahi_threaded_poll_lock
+#define avahi_threaded_poll_unlock_ptr avahi_threaded_poll_unlock
+#define avahi_client_get_version_string_ptr avahi_client_get_version_string
+#endif
+
+/*
+ * TXT record version - this should be 1 for a long time
+ * - only need to change if we really change the TXT record format
+ */
+const char *dnssd_txt_ver = "1";
+
+int Dns_sdInitialized = FALSE;
+
+static AvahiThreadedPoll *threaded_poll = NULL;
+static AvahiClient *client = NULL;
+
+static AvahiServiceBrowser *zeroconf_browse_sbc_ref = NULL;
+static AvahiServiceBrowser *zeroconf_browse_ws_ref = NULL;
+static AvahiServiceBrowser *zeroconf_browse_phidget_ref = NULL;
+
+//pthread_t dns_thread_ws, dns_thread_phid;
+
+void *avahiLibHandle = NULL;
+
+static void client_callback(AvahiClient *c, AvahiClientState state, AVAHI_GCC_UNUSED void * userdata) {
+ assert(c);
+
+ /* Called whenever the client or server state changes */
+
+ switch (state) {
+ case AVAHI_CLIENT_S_RUNNING:
+
+ /* The server has startup successfully and registered its host
+ * name on the network */
+ Dns_sdInitialized = TRUE;
+ break;
+
+ case AVAHI_CLIENT_FAILURE:
+
+ LOG(PHIDGET_LOG_ERROR, "Client failure: %s", avahi_strerror_ptr(avahi_client_errno_ptr(c)));
+ //avahi_threaded_poll_quit_ptr(threaded_poll);
+
+ break;
+
+ case AVAHI_CLIENT_S_COLLISION:
+
+ /* Let's drop our registered services. When the server is back
+ * in AVAHI_SERVER_RUNNING state we will register them
+ * again with the new host name. */
+
+ case AVAHI_CLIENT_S_REGISTERING:
+
+ /* The server records are now being established. This
+ * might be caused by a host name change. We need to wait
+ * for our own records to register until the host name is
+ * properly esatblished. */
+
+ //if (group)
+ // avahi_entry_group_reset_ptr(group);
+
+ break;
+
+ case AVAHI_CLIENT_CONNECTING:
+ break;
+ }
+}
+
+static uint8_t *InternalTXTRecordSearch
+ (
+ uint16_t txtLen,
+ const void *txtRecord,
+ const char *key,
+ unsigned long *keylen
+ )
+{
+ uint8_t *p = (uint8_t*)txtRecord;
+ uint8_t *e = p + txtLen;
+ *keylen = (unsigned long) strlen(key);
+ while (p<e)
+ {
+ uint8_t *x = p;
+ p += 1 + p[0];
+ if (p <= e && *keylen <= x[0] && !strncmp(key, (char*)x+1, *keylen))
+ if (*keylen == x[0] || x[1+*keylen] == '=') return(x);
+ }
+ return(NULL);
+}
+
+const void * TXTRecordGetValuePtr
+ (
+ uint16_t txtLen,
+ const void *txtRecord,
+ const char *key,
+ uint8_t *valueLen
+ )
+{
+ unsigned long keylen;
+ uint8_t *item = InternalTXTRecordSearch(txtLen, txtRecord, key, &keylen);
+ if (!item || item[0] <= keylen) return(NULL); // If key not found, or found with no value, return NULL
+ *valueLen = (uint8_t)(item[0] - (keylen + 1));
+ return (item + 1 + keylen + 1);
+}
+
+void PhidFromTXT(CPhidgetHandle phid, uint16_t txtLen, const char *txtRecord)
+{
+ int i = 0;
+ short txtver;
+
+ uint8_t valLen = 0;
+ const char *valPtr = NULL;
+
+ //txt version
+ if(!(valPtr = TXTRecordGetValuePtr(txtLen, txtRecord, "txtvers", &valLen))) return;
+ txtver = (short)strtol(valPtr, NULL, 10);
+
+ //Serial Number
+ if(!(valPtr = TXTRecordGetValuePtr(txtLen, txtRecord, "serial", &valLen))) return;
+ phid->serialNumber = strtol(valPtr, NULL, 10);
+ phid->specificDevice = PTRUE;
+
+ //version
+ if(!(valPtr = TXTRecordGetValuePtr(txtLen, txtRecord, "version", &valLen))) return;
+ phid->deviceVersion = strtol(valPtr, NULL, 10);
+
+ //label
+ if(!(valPtr = TXTRecordGetValuePtr(txtLen, txtRecord, "label", &valLen))) return;
+ if(valLen > MAX_LABEL_STORAGE-1) valLen = MAX_LABEL_STORAGE-1;
+ memcpy(phid->label, valPtr, valLen);
+ phid->label[valLen] = '\0';
+
+ //server_id
+ if(!(valPtr = TXTRecordGetValuePtr(txtLen, txtRecord, "server_id", &valLen))) return;
+ free(phid->networkInfo->zeroconf_server_id);
+ if(!(phid->networkInfo->zeroconf_server_id = malloc(valLen+1))) return;
+ ZEROMEM(phid->networkInfo->zeroconf_server_id, valLen+1);
+ memcpy(phid->networkInfo->zeroconf_server_id, valPtr, valLen);
+
+ // things added in version 2 of the txt
+ if(txtver >= 2)
+ {
+ //Device ID
+ if(!(valPtr = TXTRecordGetValuePtr(txtLen, txtRecord, "id", &valLen))) return;
+ phid->deviceIDSpec = strtol(valPtr, NULL, 10);
+
+ for(i = 1;i<PHIDGET_DEVICE_COUNT;i++)
+ if(phid->deviceIDSpec == Phid_Device_Def[i].pdd_sdid) break;
+ phid->deviceDef = &Phid_Device_Def[i];
+ phid->attr = Phid_Device_Def[i].pdd_attr;
+
+ //Device Class
+ if(!(valPtr = TXTRecordGetValuePtr(txtLen, txtRecord, "class", &valLen))) return;
+ phid->deviceID = strtol(valPtr, NULL, 10);
+ phid->deviceType = Phid_DeviceName[phid->deviceID];
+ }
+ //Old version uses string searching, but some devices have the same name with different IDs
+ else
+ {
+ char *name = NULL;
+ char *type = NULL;
+
+ //name
+ if(!(valPtr = TXTRecordGetValuePtr(txtLen, txtRecord, "name", &valLen))) return;
+ if(!(name = malloc(valLen+1))) return;
+ ZEROMEM(name, valLen+1);
+ memcpy(name, valPtr, valLen);
+ for(i = 0;i<PHIDGET_DEVICE_COUNT;i++)
+ {
+ if(!strcmp(name, Phid_Device_Def[i].pdd_name))
+ {
+ phid->deviceIDSpec = Phid_Device_Def[i].pdd_sdid;
+ phid->deviceDef = &Phid_Device_Def[i];
+ phid->attr = Phid_Device_Def[i].pdd_attr;
+ break;
+ }
+ }
+ free(name);
+
+ //type
+ if(!(valPtr = TXTRecordGetValuePtr(txtLen, txtRecord, "type", &valLen))) return;
+ if(!(type = malloc(valLen+1))) return;
+ ZEROMEM(type, valLen+1);
+ memcpy(type, valPtr, valLen);
+ phid->deviceID = phidget_type_to_id(type);
+ phid->deviceType = Phid_DeviceName[phid->deviceID];
+ free(type);
+ }
+
+ phid->networkInfo->mdns = PTRUE;
+
+}
+
+void SBCFromTXT(CPhidgetSBCHandle sbc, uint16_t txtLen, const char *txtRecord)
+{
+ char *hversion = NULL, *txtver = NULL;
+
+ uint8_t valLen = 0;
+ const char *valPtr = NULL;
+
+ //txt version
+ if(!(valPtr = TXTRecordGetValuePtr(txtLen, txtRecord, "txtvers", &valLen))) return;
+ if(!(txtver = malloc(valLen+1))) return;
+ ZEROMEM(txtver, valLen+1);
+ memcpy(txtver, valPtr, valLen);
+ sbc->txtver = (short)strtol(txtver, NULL, 10);
+ free(txtver);
+
+ //Firmware version
+ if(!(valPtr = TXTRecordGetValuePtr(txtLen, txtRecord, "fversion", &valLen))) return;
+ if(valLen > 12) valLen = 12;
+ memcpy(sbc->fversion, valPtr, valLen);
+ sbc->fversion[valLen] = '\0';
+
+ //Hardware version
+ if(!(valPtr = TXTRecordGetValuePtr(txtLen, txtRecord, "hversion", &valLen))) return;
+ if(!(hversion = malloc(valLen+1))) return;
+ ZEROMEM(hversion, valLen+1);
+ memcpy(hversion, valPtr, valLen);
+ sbc->hversion = (short)strtol(hversion, NULL, 10);
+ free(hversion);
+
+ // things added in version 2 of the txt
+ if(sbc->txtver >= 2)
+ {
+ //Hostname
+ if(!(valPtr = TXTRecordGetValuePtr(txtLen, txtRecord, "hostname", &valLen))) return;
+ if(valLen > 128) valLen = 128;
+ memcpy(sbc->hostname, valPtr, valLen);
+ sbc->hostname[valLen] = '\0';
+ }
+
+ // things added in version 3 of the txt
+ if(sbc->txtver >= 3)
+ {
+ //Device Name
+ if(!(valPtr = TXTRecordGetValuePtr(txtLen, txtRecord, "name", &valLen))) return;
+ if(valLen > 128) valLen = 128;
+ memcpy(sbc->deviceName, valPtr, valLen);
+ sbc->deviceName[valLen] = '\0';
+ }
+ else
+ {
+ sprintf(sbc->deviceName, "PhidgetSBC");
+ }
+}
+
+void DNSServiceResolve_CallBack(
+ AvahiServiceResolver *r,
+ AVAHI_GCC_UNUSED AvahiIfIndex interface,
+ AVAHI_GCC_UNUSED AvahiProtocol protocol,
+ AvahiResolverEvent event,
+ const char *name,
+ const char *type,
+ const char *domain,
+ const char *host_name,
+ const AvahiAddress *address,
+ uint16_t port,
+ AvahiStringList *txt,
+ AvahiLookupResultFlags flags,
+ AVAHI_GCC_UNUSED void* userdata)
+{
+
+ CPhidgetRemoteHandle networkInfo = (CPhidgetRemoteHandle)userdata;
+ switch (event) {
+ case AVAHI_RESOLVER_FAILURE:
+ LOG(PHIDGET_LOG_ERROR, "(Resolver) Failed to resolve service '%s' of type '%s' in domain '%s': %s", name, type, domain, avahi_strerror_ptr(avahi_client_errno_ptr(client)));
+ networkInfo->zeroconf_host = strdup("err");
+ break;
+ case AVAHI_RESOLVER_FOUND:
+ {
+ LOG(PHIDGET_LOG_INFO, "DNSServiceResolve_CallBack: %s",name);
+ networkInfo->zeroconf_host = strdup(host_name);
+ networkInfo->zeroconf_port = malloc(10);
+ snprintf(networkInfo->zeroconf_port, 9, "%d", port);
+ }
+ }
+
+ avahi_service_resolver_free_ptr(r);
+}
+
+void DNSServiceQueryRecord_Phidget_CallBack
+ (
+ AvahiRecordBrowser *b,
+ AvahiIfIndex interface,
+ AvahiProtocol protocol,
+ AvahiBrowserEvent event,
+ const char *name,
+ uint16_t clazz,
+ uint16_t type,
+ const void *rdata,
+ size_t size,
+ AvahiLookupResultFlags flags,
+ void *userdata
+ )
+{
+ CPhidgetHandle phid = (CPhidgetHandle)userdata;
+ CPhidgetManagerList *trav;
+
+ switch(event)
+ {
+ case AVAHI_BROWSER_NEW:
+ PhidFromTXT(phid, size, rdata);
+ LOG(PHIDGET_LOG_INFO, "DNSServiceQueryRecord_Phidget_CallBack: %s",name);
+ CThread_mutex_lock(&zeroconfPhidgetsLock);
+ CThread_mutex_lock(&activeRemoteManagersLock);
+
+ CPhidget_setStatusFlag(&phid->status, PHIDGET_ATTACHED_FLAG, &phid->lock);
+ CPhidget_setStatusFlag(&phid->status, PHIDGET_REMOTE_FLAG, &phid->lock);
+ CPhidget_setStatusFlag(&phid->status, PHIDGET_SERVER_CONNECTED_FLAG, &phid->lock);
+
+ //now add it
+ CList_addToList((CListHandle *)&zeroconfPhidgets, phid, CPhidget_areExtraEqual);
+ //managers
+ for (trav=activeRemoteManagers; trav; trav = trav->next)
+ {
+ if(trav->phidm->networkInfo->requested_address==NULL
+ && (trav->phidm->networkInfo->requested_serverID == NULL || !strcmp(trav->phidm->networkInfo->requested_serverID,phid->networkInfo->zeroconf_server_id)))
+ {
+ CList_addToList((CListHandle *)&trav->phidm->AttachedPhidgets, phid, CPhidget_areExtraEqual);
+
+ if (trav->phidm->fptrAttachChange && trav->phidm->state == PHIDGETMANAGER_ACTIVE)
+ trav->phidm->fptrAttachChange((CPhidgetHandle)phid, trav->phidm->fptrAttachChangeptr);
+ }
+ }
+ CThread_mutex_unlock(&activeRemoteManagersLock);
+ CThread_mutex_unlock(&zeroconfPhidgetsLock);
+ break;
+ case AVAHI_BROWSER_FAILURE:
+ LOG(PHIDGET_LOG_ERROR, "DNSServiceQueryRecord_Phidget_CallBack returned error: %s", avahi_strerror_ptr(avahi_client_errno_ptr(client)));
+ break;
+ case AVAHI_BROWSER_ALL_FOR_NOW:
+ avahi_record_browser_free_ptr(b);
+ case AVAHI_BROWSER_CACHE_EXHAUSTED:
+ LOG(PHIDGET_LOG_INFO, "DNSServiceQueryRecord_Phidget_CallBack %s", event == AVAHI_BROWSER_CACHE_EXHAUSTED ? "CACHE_EXHAUSTED" : "ALL_FOR_NOW");
+ break;
+ case AVAHI_BROWSER_REMOVE:
+ break;
+ }
+}
+
+void DNSServiceQueryRecord_SBC_CallBack
+(
+ AvahiRecordBrowser *b,
+ AvahiIfIndex interface,
+ AvahiProtocol protocol,
+ AvahiBrowserEvent event,
+ const char *name,
+ uint16_t clazz,
+ uint16_t type,
+ const void *rdata,
+ size_t size,
+ AvahiLookupResultFlags flags,
+ void *userdata
+ )
+{
+ CPhidgetSBCHandle sbc = (CPhidgetSBCHandle)userdata, found_sbc;
+ CPhidgetSBCManagerList *trav;
+
+ switch(event)
+ {
+ case AVAHI_BROWSER_NEW:
+ SBCFromTXT(sbc, size, rdata);
+ LOG(PHIDGET_LOG_INFO, "DNSServiceQueryRecord_SBC_CallBack: %s",name);
+ CThread_mutex_lock(&zeroconfSBCsLock);
+ CThread_mutex_lock(&activeSBCManagersLock);
+
+ //Check if it's in the list and if it's different, remove it to make way for the new one
+ // (Sometimes, we don't get a proper detach notification)
+ if(CList_findInList((CListHandle)zeroconfSBCs, sbc, CPhidgetSBC_areEqual, (void **)&found_sbc) == EPHIDGET_OK)
+ {
+ if(CPhidgetSBC_areExtraEqual(found_sbc, sbc) != PTRUE) //A version number has changed
+ {
+ //Remove from list - don't free until after detach event
+ CList_removeFromList((CListHandle *)&zeroconfSBCs, found_sbc, CPhidgetSBC_areEqual, PFALSE, NULL);
+
+ for (trav=activeSBCManagers; trav; trav = trav->next)
+ {
+ if (trav->sbcm->fptrDetachChange && trav->sbcm->state == PHIDGETMANAGER_ACTIVE)
+ trav->sbcm->fptrDetachChange((CPhidgetSBCHandle)found_sbc, trav->sbcm->fptrDetachChangeptr);
+ }
+
+ CPhidgetSBC_free(found_sbc);
+
+ //now we fall through and add back to new one
+ }
+ else //Nothing has changed, we didn't remove, don't add
+ {
+ CPhidgetSBC_free(sbc);
+ goto dontadd;
+ }
+ }
+
+ //now add it
+ CList_addToList((CListHandle *)&zeroconfSBCs, sbc, CPhidgetSBC_areEqual);
+
+ //send out events
+ for (trav=activeSBCManagers; trav; trav = trav->next)
+ {
+ if (trav->sbcm->fptrAttachChange && trav->sbcm->state == PHIDGETMANAGER_ACTIVE)
+ trav->sbcm->fptrAttachChange((CPhidgetSBCHandle)sbc, trav->sbcm->fptrAttachChangeptr);
+
+ }
+ dontadd:
+
+ CThread_mutex_unlock(&activeSBCManagersLock);
+ CThread_mutex_unlock(&zeroconfSBCsLock);
+ break;
+ case AVAHI_BROWSER_FAILURE:
+ LOG(PHIDGET_LOG_ERROR, "DNSServiceQueryRecord_SBC_CallBack returned error: %s", avahi_strerror_ptr(avahi_client_errno_ptr(client)));
+ break;
+ case AVAHI_BROWSER_ALL_FOR_NOW:
+ avahi_record_browser_free_ptr(b);
+ case AVAHI_BROWSER_CACHE_EXHAUSTED:
+ LOG(PHIDGET_LOG_INFO, "DNSServiceQueryRecord_SBC_CallBack %s", event == AVAHI_BROWSER_CACHE_EXHAUSTED ? "CACHE_EXHAUSTED" : "ALL_FOR_NOW");
+ break;
+ case AVAHI_BROWSER_REMOVE:
+ break;
+ }
+}
+
+void DNSServiceBrowse_Phidget_CallBack(
+ AvahiServiceBrowser *b,
+ AvahiIfIndex interface,
+ AvahiProtocol protocol,
+ AvahiBrowserEvent event,
+ const char *name,
+ const char *type,
+ const char *domain,
+ AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
+ void* userdata)
+{
+
+ CPhidgetHandle phid;
+ CPhidgetManagerList *trav;
+
+ int ret;
+
+ switch (event) {
+
+ case AVAHI_BROWSER_FAILURE:
+
+ LOG(PHIDGET_LOG_WARNING, "(Browser) %s", avahi_strerror_ptr(avahi_client_errno_ptr(client)));
+ avahi_threaded_poll_quit_ptr(threaded_poll);
+ return;
+
+ case AVAHI_BROWSER_NEW:
+ {
+ char fullname[AVAHI_DOMAIN_NAME_MAX];
+
+ if((CPhidget_create(&phid))) return;
+ if((CPhidgetRemote_create(&phid->networkInfo))) return;
+
+ phid->networkInfo->zeroconf_name = strdup(name);
+ phid->networkInfo->zeroconf_type = strdup(type);
+ phid->networkInfo->zeroconf_domain = strdup(domain);
+
+ LOG(PHIDGET_LOG_INFO, "(Browser) NEW: service '%s' of type '%s' in domain '%s'", name, type, domain);
+
+ if((ret = avahi_service_name_join_ptr(fullname, AVAHI_DOMAIN_NAME_MAX, name, type, domain)) != AVAHI_OK)
+ LOG(PHIDGET_LOG_ERROR, "Failed avahi_service_name_join_ptr '%s': %s", name, avahi_strerror_ptr(ret));
+
+ if(!(avahi_record_browser_new_ptr(client, interface, protocol, fullname, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_TXT, 0, DNSServiceQueryRecord_Phidget_CallBack, phid)))
+ LOG(PHIDGET_LOG_ERROR, "Failed to resolve service '%s': %s", name, avahi_strerror_ptr(avahi_client_errno_ptr(client)));
+ //gets added to list in callback
+ }
+ break;
+
+ case AVAHI_BROWSER_REMOVE:
+ {
+ if((CPhidget_create(&phid))) return;
+ if((CPhidgetRemote_create(&phid->networkInfo))) return;
+
+ phid->networkInfo->zeroconf_name = strdup(name);
+ phid->networkInfo->zeroconf_type = strdup(type);
+ phid->networkInfo->zeroconf_domain = strdup(domain);
+
+ LOG(PHIDGET_LOG_INFO, "(Browser) REMOVE: service '%s' of type '%s' in domain '%s'", name, type, domain);
+
+ //have to fill in phid manually from just the name
+ int i;
+ CPhidgetHandle found_phid;
+ char *name_copy = strdup(name);
+ for(i=0;i<strlen(name_copy);i++)
+ if(name_copy[i] == '(') break;
+ if(i<=1) return;
+ name_copy[strlen(name_copy)-1]='\0';
+ name_copy[i-1] = '\0';
+ phid->serialNumber = strtol(name_copy+i+1, NULL, 10);
+ phid->specificDevice = PTRUE;
+ for(i = 0;i<PHIDGET_DEVICE_COUNT;i++)
+ if(!strcmp(name_copy, Phid_Device_Def[i].pdd_name)) break;
+ phid->deviceIDSpec = 0;
+ phid->deviceDef = &Phid_Device_Def[i];
+ phid->attr = Phid_Device_Def[i].pdd_attr;
+ phid->deviceID = Phid_Device_Def[i].pdd_did;
+ phid->deviceType = Phid_DeviceName[phid->deviceID];
+ phid->networkInfo->mdns = PTRUE;
+
+ CThread_mutex_lock(&zeroconfPhidgetsLock);
+ CThread_mutex_lock(&activeRemoteManagersLock);
+
+ CPhidget_clearStatusFlag(&phid->status, PHIDGET_ATTACHED_FLAG, &phid->lock);
+ CPhidget_setStatusFlag(&phid->status, PHIDGET_DETACHING_FLAG, &phid->lock);
+
+ if(!CList_findInList((CListHandle)zeroconfPhidgets, phid, CPhidget_areEqual, (void **)&found_phid))
+ {
+ CPhidget_clearStatusFlag(&found_phid->status, PHIDGET_ATTACHED_FLAG, &found_phid->lock);
+ CPhidget_setStatusFlag(&found_phid->status, PHIDGET_DETACHING_FLAG, &found_phid->lock);
+ CPhidget_setStatusFlag(&found_phid->status, PHIDGET_REMOTE_FLAG, &found_phid->lock);
+ CPhidget_clearStatusFlag(&found_phid->status, PHIDGET_SERVER_CONNECTED_FLAG, &found_phid->lock);
+
+ CList_removeFromList((CListHandle *)&zeroconfPhidgets, found_phid, CPhidget_areExtraEqual, FALSE, NULL);
+ //managers
+ for (trav=activeRemoteManagers; trav; trav = trav->next)
+ {
+ if(trav->phidm->networkInfo->requested_address==NULL
+ && (trav->phidm->networkInfo->requested_serverID == NULL || !strcmp(trav->phidm->networkInfo->requested_serverID,found_phid->networkInfo->zeroconf_server_id)))
+ {
+ CList_removeFromList((CListHandle *)&trav->phidm->AttachedPhidgets, found_phid, CPhidget_areExtraEqual, PFALSE, NULL);
+
+ if (trav->phidm->fptrDetachChange && trav->phidm->state == PHIDGETMANAGER_ACTIVE)
+ trav->phidm->fptrDetachChange((CPhidgetHandle)found_phid, trav->phidm->fptrDetachChangeptr);
+ }
+ }
+ CPhidget_clearStatusFlag(&found_phid->status, PHIDGET_DETACHING_FLAG, &found_phid->lock);
+ CPhidgetRemote_free(found_phid->networkInfo);
+ CPhidget_free(found_phid);
+ }
+ CPhidgetRemote_free(phid->networkInfo);
+ CPhidget_free(phid);
+
+ CThread_mutex_unlock(&activeRemoteManagersLock);
+ CThread_mutex_unlock(&zeroconfPhidgetsLock);
+ free(name_copy);
+ }
+ break;
+
+ case AVAHI_BROWSER_ALL_FOR_NOW:
+ case AVAHI_BROWSER_CACHE_EXHAUSTED:
+ LOG(PHIDGET_LOG_INFO, "(Browser) %s", event == AVAHI_BROWSER_CACHE_EXHAUSTED ? "CACHE_EXHAUSTED" : "ALL_FOR_NOW");
+ break;
+ }
+}
+
+void DNSServiceBrowse_SBC_CallBack(
+ AvahiServiceBrowser *b,
+ AvahiIfIndex interface,
+ AvahiProtocol protocol,
+ AvahiBrowserEvent event,
+ const char *name,
+ const char *type,
+ const char *domain,
+ AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
+ void* userdata)
+{
+
+ CPhidgetSBCHandle sbc, found_sbc;
+ CPhidgetSBCManagerList *trav;
+ int ret;
+
+ switch (event) {
+
+ case AVAHI_BROWSER_FAILURE:
+
+ LOG(PHIDGET_LOG_WARNING, "(Browser) %s", avahi_strerror_ptr(avahi_client_errno_ptr(client)));
+ avahi_threaded_poll_quit_ptr(threaded_poll);
+ return;
+
+ case AVAHI_BROWSER_NEW:
+ {
+ char fullname[AVAHI_DOMAIN_NAME_MAX];
+
+ if((CPhidgetSBC_create(&sbc))) return;
+ if((CPhidgetRemote_create(&sbc->networkInfo))) return;
+
+ sbc->networkInfo->zeroconf_name = strdup(name);
+ sbc->networkInfo->zeroconf_type = strdup(type);
+ sbc->networkInfo->zeroconf_domain = strdup(domain);
+ sbc->networkInfo->mdns = PTRUE;
+
+ strncpy(sbc->mac, name+12, 18); //name == 'PhidgetSBC (??:??:??:??:??:??)'
+ sbc->mac[17] = '\0';
+
+ LOG(PHIDGET_LOG_INFO, "(Browser) NEW: service '%s' of type '%s' in domain '%s'", name, type, domain);
+
+ if((ret = avahi_service_name_join_ptr(fullname, AVAHI_DOMAIN_NAME_MAX, name, type, domain)) != AVAHI_OK)
+ LOG(PHIDGET_LOG_ERROR, "Failed avahi_service_name_join_ptr '%s': %s", name, avahi_strerror_ptr(ret));
+
+ if(!(avahi_record_browser_new_ptr(client, interface, protocol, fullname, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_TXT, 0, DNSServiceQueryRecord_SBC_CallBack, sbc)))
+ LOG(PHIDGET_LOG_ERROR, "Failed to resolve service '%s': %s", name, avahi_strerror_ptr(avahi_client_errno_ptr(client)));
+ //gets added to list in callback
+ }
+ break;
+
+ case AVAHI_BROWSER_REMOVE:
+ {
+ if((CPhidgetSBC_create(&sbc))) return;
+ if((CPhidgetRemote_create(&sbc->networkInfo))) return;
+
+ sbc->networkInfo->zeroconf_name = strdup(name);
+ sbc->networkInfo->zeroconf_type = strdup(type);
+ sbc->networkInfo->zeroconf_domain = strdup(domain);
+ sbc->networkInfo->mdns = PTRUE;
+
+ strncpy(sbc->mac, name+12, 18); //name == 'PhidgetSBC (??:??:??:??:??:??)'
+ sbc->mac[17] = '\0';
+
+ LOG(PHIDGET_LOG_INFO, "(Browser) REMOVE: service '%s' of type '%s' in domain '%s'", name, type, domain);
+
+
+ CThread_mutex_lock(&zeroconfSBCsLock);
+ CThread_mutex_lock(&activeSBCManagersLock);
+
+ if(CList_findInList((CListHandle)zeroconfSBCs, sbc, CPhidgetSBC_areEqual, (void **)&found_sbc) == EPHIDGET_OK)
+ {
+ CList_removeFromList((CListHandle *)&zeroconfSBCs, found_sbc, CPhidgetSBC_areEqual, PFALSE, NULL);
+ //managers
+ for (trav=activeSBCManagers; trav; trav = trav->next)
+ {
+ if (trav->sbcm->fptrDetachChange && trav->sbcm->state == PHIDGETMANAGER_ACTIVE)
+ trav->sbcm->fptrDetachChange((CPhidgetSBCHandle)found_sbc, trav->sbcm->fptrDetachChangeptr);
+ }
+ CPhidgetSBC_free(found_sbc);
+ }
+
+ CThread_mutex_unlock(&activeSBCManagersLock);
+ CThread_mutex_unlock(&zeroconfSBCsLock);
+
+ CPhidgetSBC_free(sbc);
+ }
+ break;
+
+ case AVAHI_BROWSER_ALL_FOR_NOW:
+ case AVAHI_BROWSER_CACHE_EXHAUSTED:
+ LOG(PHIDGET_LOG_INFO, "(Browser) %s", event == AVAHI_BROWSER_CACHE_EXHAUSTED ? "CACHE_EXHAUSTED" : "ALL_FOR_NOW");
+ break;
+ }
+}
+
+void DNSServiceBrowse_ws_CallBack(
+ AvahiServiceBrowser *b,
+ AvahiIfIndex interface,
+ AvahiProtocol protocol,
+ AvahiBrowserEvent event,
+ const char *name,
+ const char *type,
+ const char *domain,
+ AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
+ void* userdata)
+{
+
+ switch (event) {
+
+ case AVAHI_BROWSER_FAILURE:
+
+ LOG(PHIDGET_LOG_ERROR, "(Browser) %s", avahi_strerror_ptr(avahi_client_errno_ptr(client)));
+ //avahi_threaded_poll_quit_ptr(threaded_poll);
+ return;
+
+ case AVAHI_BROWSER_NEW:
+ {
+ CPhidgetRemoteHandle networkInfo;
+ if((CPhidgetRemote_create(&networkInfo))) return;
+
+ networkInfo->zeroconf_name = strdup(name);
+ networkInfo->zeroconf_server_id = strdup(name);
+ networkInfo->zeroconf_type = strdup(type);
+ networkInfo->zeroconf_domain = strdup(domain);
+
+ LOG(PHIDGET_LOG_INFO, "(Browser) NEW: service '%s' of type '%s' in domain '%s'", name, type, domain);
+
+ CThread_mutex_lock(&zeroconfServersLock);
+ CList_addToList((CListHandle *)&zeroconfServers, networkInfo, CPhidgetRemote_areEqual);
+ CThread_mutex_unlock(&zeroconfServersLock);
+ }
+ break;
+
+ case AVAHI_BROWSER_REMOVE:
+ {
+ CPhidgetRemoteHandle networkInfo;
+ if((CPhidgetRemote_create(&networkInfo))) return;
+
+ networkInfo->zeroconf_name = strdup(name);
+ networkInfo->zeroconf_server_id = strdup(name);
+ networkInfo->zeroconf_type = strdup(type);
+ networkInfo->zeroconf_domain = strdup(domain);
+ LOG(PHIDGET_LOG_INFO, "(Browser) REMOVE: service '%s' of type '%s' in domain '%s'", name, type, domain);
+
+ CThread_mutex_lock(&zeroconfServersLock);
+ CList_removeFromList((CListHandle *)&zeroconfServers, networkInfo, CPhidgetRemote_areEqual, TRUE, CPhidgetRemote_free);
+ CThread_mutex_unlock(&zeroconfServersLock);
+ }
+ break;
+
+ case AVAHI_BROWSER_ALL_FOR_NOW:
+ case AVAHI_BROWSER_CACHE_EXHAUSTED:
+ LOG(PHIDGET_LOG_INFO, "(Browser) %s", event == AVAHI_BROWSER_CACHE_EXHAUSTED ? "CACHE_EXHAUSTED" : "ALL_FOR_NOW");
+ break;
+ }
+}
+
+//Does nothing in Avahi
+int cancelPendingZeroconfLookups(CPhidgetRemoteHandle networkInfo)
+{
+ return EPHIDGET_OK;
+}
+
+int getZeroconfHostPort(CPhidgetRemoteHandle networkInfo)
+{
+ int timeout = 200; //2000ms
+
+ if(networkInfo->zeroconf_host) free(networkInfo->zeroconf_host);
+ networkInfo->zeroconf_host = NULL;
+ if(networkInfo->zeroconf_port) free(networkInfo->zeroconf_port);
+ networkInfo->zeroconf_port = NULL;
+
+ //lock the thread before accessing the client - nope, it messes up if this is from the same thread (via attach/detach)
+ //avahi_threaded_poll_lock_ptr(threaded_poll);
+ if (!(avahi_service_resolver_new_ptr(client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC,
+ networkInfo->zeroconf_name, //name
+ networkInfo->zeroconf_type, // service type
+ networkInfo->zeroconf_domain, //domain
+ AVAHI_PROTO_UNSPEC, 0, DNSServiceResolve_CallBack, networkInfo)))
+ {
+ LOG(PHIDGET_LOG_ERROR, "Failed to resolve service '%s': %s", networkInfo->zeroconf_name, avahi_strerror_ptr(avahi_client_errno_ptr(client)));
+ //avahi_threaded_poll_unlock_ptr(threaded_poll);
+ return EPHIDGET_UNEXPECTED;
+ }
+ //avahi_threaded_poll_unlock_ptr(threaded_poll);
+
+ while(!networkInfo->zeroconf_host)
+ {
+ usleep(10000);
+ timeout--;
+ if(!timeout)
+ {
+ LOG(PHIDGET_LOG_ERROR, "getZeroconfHostPort didn't work (timeout)");
+ return EPHIDGET_UNEXPECTED;
+ }
+ }
+
+ if(!strcmp(networkInfo->zeroconf_host, "err"))
+ {
+ LOG(PHIDGET_LOG_ERROR, "getZeroconfHostPort didn't work (error)");
+ free(networkInfo->zeroconf_host);
+ networkInfo->zeroconf_host = NULL;
+ return EPHIDGET_UNEXPECTED;
+ }
+
+ return EPHIDGET_OK;
+}
+
+int refreshZeroconfSBC(CPhidgetSBCHandle sbc)
+{
+ return EPHIDGET_OK;
+}
+
+int refreshZeroconfPhidget(CPhidgetHandle phid)
+{
+ return EPHIDGET_OK;
+}
+
+int InitializeZeroconf()
+{
+ int error;
+ //int ret = 1;
+ int timeout = 50; //500ms
+ const char *avahiVersion;
+
+ CThread_mutex_lock(&zeroconfInitLock);
+ if(Dns_sdInitialized)
+ {
+ CThread_mutex_unlock(&zeroconfInitLock);
+ return EPHIDGET_OK;
+ }
+
+#ifdef ZEROCONF_RUNTIME_LINKING
+
+ avahiLibHandle = dlopen("libavahi-client.so",RTLD_LAZY);
+ if(!avahiLibHandle)
+ {
+ avahiLibHandle = dlopen("libavahi-client.so.3",RTLD_LAZY);
+ }
+ if(!avahiLibHandle)
+ {
+ LOG(PHIDGET_LOG_WARNING, "dlopen failed with error: %s", dlerror());
+ LOG(PHIDGET_LOG_WARNING, "Assuming that zeroconf is not supported on this machine.");
+ CThread_mutex_unlock(&zeroconfInitLock);
+ return EPHIDGET_UNSUPPORTED;
+ }
+
+ //These are always in Avahi
+ if(!(avahi_client_get_version_string_ptr = (avahi_client_get_version_string_type)dlsym(avahiLibHandle, "avahi_client_get_version_string"))) goto dlsym_err;
+ if(!(avahi_service_browser_new_ptr = (avahi_service_browser_new_type)dlsym(avahiLibHandle, "avahi_service_browser_new"))) goto dlsym_err;
+ if(!(avahi_service_resolver_new_ptr = (avahi_service_resolver_new_type)dlsym(avahiLibHandle, "avahi_service_resolver_new"))) goto dlsym_err;
+ if(!(avahi_service_resolver_free_ptr = (avahi_service_resolver_free_type)dlsym(avahiLibHandle, "avahi_service_resolver_free"))) goto dlsym_err;
+ if(!(avahi_record_browser_new_ptr = (avahi_record_browser_new_type)dlsym(avahiLibHandle, "avahi_record_browser_new"))) goto dlsym_err;
+ if(!(avahi_record_browser_free_ptr = (avahi_record_browser_free_type)dlsym(avahiLibHandle, "avahi_record_browser_free"))) goto dlsym_err;
+ if(!(avahi_service_name_join_ptr = (avahi_service_name_join_type)dlsym(avahiLibHandle, "avahi_service_name_join"))) goto dlsym_err;
+ if(!(avahi_client_new_ptr = (avahi_client_new_type)dlsym(avahiLibHandle, "avahi_client_new"))) goto dlsym_err;
+ if(!(avahi_client_free_ptr = (avahi_client_free_type)dlsym(avahiLibHandle, "avahi_client_free"))) goto dlsym_err;
+ if(!(avahi_strerror_ptr = (avahi_strerror_type)dlsym(avahiLibHandle, "avahi_strerror"))) goto dlsym_err;
+ if(!(avahi_client_errno_ptr = (avahi_client_errno_type)dlsym(avahiLibHandle, "avahi_client_errno"))) goto dlsym_err;
+
+ //These are in Avahi > 0.6.4
+ if(!(avahi_threaded_poll_new_ptr = (avahi_threaded_poll_new_type)dlsym(avahiLibHandle, "avahi_threaded_poll_new"))) goto dlsym_err2;
+ if(!(avahi_threaded_poll_free_ptr = (avahi_threaded_poll_free_type)dlsym(avahiLibHandle, "avahi_threaded_poll_free"))) goto dlsym_err2;
+ if(!(avahi_threaded_poll_get_ptr = (avahi_threaded_poll_get_type)dlsym(avahiLibHandle, "avahi_threaded_poll_get"))) goto dlsym_err2;
+ if(!(avahi_threaded_poll_start_ptr = (avahi_threaded_poll_start_type)dlsym(avahiLibHandle, "avahi_threaded_poll_start"))) goto dlsym_err2;
+ if(!(avahi_threaded_poll_stop_ptr = (avahi_threaded_poll_stop_type)dlsym(avahiLibHandle, "avahi_threaded_poll_stop"))) goto dlsym_err2;
+ if(!(avahi_threaded_poll_quit_ptr = (avahi_threaded_poll_quit_type)dlsym(avahiLibHandle, "avahi_threaded_poll_quit"))) goto dlsym_err2;
+ if(!(avahi_threaded_poll_lock_ptr = (avahi_threaded_poll_lock_type)dlsym(avahiLibHandle, "avahi_threaded_poll_lock"))) goto dlsym_err2;
+ if(!(avahi_threaded_poll_unlock_ptr = (avahi_threaded_poll_unlock_type)dlsym(avahiLibHandle, "avahi_threaded_poll_unlock"))) goto dlsym_err2;
+
+ goto dlsym_good;
+
+dlsym_err:
+ LOG(PHIDGET_LOG_WARNING, "dlsym failed with error: %s", dlerror());
+ LOG(PHIDGET_LOG_WARNING, "Assuming that zeroconf is not supported on this machine.");
+ CThread_mutex_unlock(&zeroconfInitLock);
+ return EPHIDGET_UNSUPPORTED;
+
+ //Old avahi didn't have the thread functions
+dlsym_err2:
+ LOG(PHIDGET_LOG_WARNING, "dlsym failed with error: %s", dlerror());
+ LOG(PHIDGET_LOG_WARNING, "Avahi is too old, upgrade to at least version 0.6.4.");
+ LOG(PHIDGET_LOG_WARNING, "Zeroconf will not be used on this machine.");
+ CThread_mutex_unlock(&zeroconfInitLock);
+ return EPHIDGET_UNSUPPORTED;
+
+dlsym_good:
+
+#endif
+
+ /* Allocate main loop object */
+ if (!(threaded_poll = avahi_threaded_poll_new_ptr())) {
+ LOG(PHIDGET_LOG_ERROR, "Failed to create threaded poll object.");
+ CThread_mutex_unlock(&zeroconfInitLock);
+ return EPHIDGET_UNEXPECTED;
+ }
+
+ /* Allocate a new client */
+ client = avahi_client_new_ptr(avahi_threaded_poll_get_ptr(threaded_poll), 0, client_callback, NULL, &error);
+
+ /* Check wether creating the client object succeeded */
+ if (!client) {
+ LOG(PHIDGET_LOG_ERROR, "Failed to create client: %s", avahi_strerror_ptr(error));
+ CThread_mutex_unlock(&zeroconfInitLock);
+ return EPHIDGET_UNEXPECTED;
+ }
+
+ //get version
+ avahiVersion = avahi_client_get_version_string_ptr(client);
+
+ /* Create the service browsers */
+ if (!(zeroconf_browse_ws_ref = avahi_service_browser_new_ptr(client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, "_phidget_ws._tcp", NULL, 0, DNSServiceBrowse_ws_CallBack, client))) {
+ LOG(PHIDGET_LOG_ERROR, "Failed to create service browser: %s", avahi_strerror_ptr(avahi_client_errno_ptr(client)));
+ CThread_mutex_unlock(&zeroconfInitLock);
+ return EPHIDGET_UNEXPECTED;
+ }
+ if (!(zeroconf_browse_phidget_ref = avahi_service_browser_new_ptr(client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, "_phidget._tcp", NULL, 0, DNSServiceBrowse_Phidget_CallBack, client))) {
+ LOG(PHIDGET_LOG_ERROR, "Failed to create service browser: %s", avahi_strerror_ptr(avahi_client_errno_ptr(client)));
+ CThread_mutex_unlock(&zeroconfInitLock);
+ return EPHIDGET_UNEXPECTED;
+ }
+ if (!(zeroconf_browse_sbc_ref = avahi_service_browser_new_ptr(client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, "_phidget_sbc._tcp", NULL, 0, DNSServiceBrowse_SBC_CallBack, client))) {
+ LOG(PHIDGET_LOG_ERROR, "Failed to create service browser: %s", avahi_strerror_ptr(avahi_client_errno_ptr(client)));
+ CThread_mutex_unlock(&zeroconfInitLock);
+ return EPHIDGET_UNEXPECTED;
+ }
+
+ if(avahi_threaded_poll_start_ptr(threaded_poll))
+ {
+ LOG(PHIDGET_LOG_ERROR, "avahi_threaded_poll_start_ptr failed");
+ CThread_mutex_unlock(&zeroconfInitLock);
+ return EPHIDGET_UNEXPECTED;
+ }
+ //Thread is started successfully
+ else
+ {
+ //There is a bug in at least Avahi 0.6.16 (Debian Etch default) where thread_running is not set, so quit doesn't work!!!???!?!?!?!?!?!
+ //This is fixed in 0.6.24
+ //So I'll set it myself here
+ if(strcmp(avahiVersion, "avahi 0.6.24") < 0)
+ {
+ LOG(PHIDGET_LOG_INFO, "Fixing thread_running bug in avahi < 0.6.24");
+ threaded_poll->thread_running = 1;
+ }
+ }
+
+ while(!Dns_sdInitialized)
+ {
+ usleep(10000);
+ timeout--;
+ if(!timeout)
+ {
+ UninitializeZeroconf1(PFALSE);
+ LOG(PHIDGET_LOG_ERROR, "InitializeZeroconf Seems bad... Dns_sdInitialized wasn't set to true.");
+ CThread_mutex_unlock(&zeroconfInitLock);
+ return EPHIDGET_UNEXPECTED;
+ }
+ }
+
+ LOG(PHIDGET_LOG_INFO, "InitializeZeroconf Seems good... (%s)",avahiVersion);
+
+ CThread_mutex_unlock(&zeroconfInitLock);
+ return EPHIDGET_OK;
+
+}
+
+
+static int UninitializeZeroconf1(int lock)
+{
+ int ret;
+ /* Cleanup things */
+ if(lock)
+ CThread_mutex_lock(&zeroconfInitLock);
+ if(Dns_sdInitialized)
+ {
+ if (threaded_poll)
+ {
+ if((ret = avahi_threaded_poll_stop_ptr(threaded_poll)) == -1)
+ LOG(PHIDGET_LOG_WARNING, "avahi_threaded_poll_stop failed",ret);
+ avahi_client_free_ptr(client);
+ avahi_threaded_poll_free_ptr(threaded_poll);
+ threaded_poll = NULL;
+ client = NULL;
+ }
+ }
+
+ Dns_sdInitialized = FALSE;
+ if(lock)
+ CThread_mutex_unlock(&zeroconfInitLock);
+ return EPHIDGET_OK;
+}
+
+int UninitializeZeroconf()
+{
+ return UninitializeZeroconf1(PTRUE);
+}
diff --git a/ltmain.sh b/ltmain.sh
new file mode 100755
index 0000000..3506ead
--- /dev/null
+++ b/ltmain.sh
@@ -0,0 +1,8413 @@
+# Generated from ltmain.m4sh.
+
+# ltmain.sh (GNU libtool) 2.2.6
+# Written by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
+
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, 2007 2008 Free Software Foundation, Inc.
+# This is free software; see the source for copying conditions. There is NO
+# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+# GNU Libtool is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# As a special exception to the GNU General Public License,
+# if you distribute this file as part of a program or library that
+# is built using GNU Libtool, you may include this file under the
+# same distribution terms that you use for the rest of that program.
+#
+# GNU Libtool is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Libtool; see the file COPYING. If not, a copy
+# can be downloaded from http://www.gnu.org/licenses/gpl.html,
+# or obtained by writing to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+# Usage: $progname [OPTION]... [MODE-ARG]...
+#
+# Provide generalized library-building support services.
+#
+# --config show all configuration variables
+# --debug enable verbose shell tracing
+# -n, --dry-run display commands without modifying any files
+# --features display basic configuration information and exit
+# --mode=MODE use operation mode MODE
+# --preserve-dup-deps don't remove duplicate dependency libraries
+# --quiet, --silent don't print informational messages
+# --tag=TAG use configuration variables from tag TAG
+# -v, --verbose print informational messages (default)
+# --version print version information
+# -h, --help print short or long help message
+#
+# MODE must be one of the following:
+#
+# clean remove files from the build directory
+# compile compile a source file into a libtool object
+# execute automatically set library path, then run a program
+# finish complete the installation of libtool libraries
+# install install libraries or executables
+# link create a library or an executable
+# uninstall remove libraries from an installed directory
+#
+# MODE-ARGS vary depending on the MODE.
+# Try `$progname --help --mode=MODE' for a more detailed description of MODE.
+#
+# When reporting a bug, please describe a test case to reproduce it and
+# include the following information:
+#
+# host-triplet: $host
+# shell: $SHELL
+# compiler: $LTCC
+# compiler flags: $LTCFLAGS
+# linker: $LD (gnu? $with_gnu_ld)
+# $progname: (GNU libtool) 2.2.6 Debian-2.2.6a-4
+# automake: $automake_version
+# autoconf: $autoconf_version
+#
+# Report bugs to <bug-libtool@gnu.org>.
+
+PROGRAM=ltmain.sh
+PACKAGE=libtool
+VERSION="2.2.6 Debian-2.2.6a-4"
+TIMESTAMP=""
+package_revision=1.3012
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac
+fi
+BIN_SH=xpg4; export BIN_SH # for Tru64
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# NLS nuisances: We save the old values to restore during execute mode.
+# Only set LANG and LC_ALL to C if already set.
+# These must not be set unconditionally because not all systems understand
+# e.g. LANG=C (notably SCO).
+lt_user_locale=
+lt_safe_locale=
+for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES
+do
+ eval "if test \"\${$lt_var+set}\" = set; then
+ save_$lt_var=\$$lt_var
+ $lt_var=C
+ export $lt_var
+ lt_user_locale=\"$lt_var=\\\$save_\$lt_var; \$lt_user_locale\"
+ lt_safe_locale=\"$lt_var=C; \$lt_safe_locale\"
+ fi"
+done
+
+$lt_unset CDPATH
+
+
+
+
+
+: ${CP="cp -f"}
+: ${ECHO="echo"}
+: ${EGREP="/bin/grep -E"}
+: ${FGREP="/bin/grep -F"}
+: ${GREP="/bin/grep"}
+: ${LN_S="ln -s"}
+: ${MAKE="make"}
+: ${MKDIR="mkdir"}
+: ${MV="mv -f"}
+: ${RM="rm -f"}
+: ${SED="/bin/sed"}
+: ${SHELL="${CONFIG_SHELL-/bin/sh}"}
+: ${Xsed="$SED -e 1s/^X//"}
+
+# Global variables:
+EXIT_SUCCESS=0
+EXIT_FAILURE=1
+EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing.
+EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake.
+
+exit_status=$EXIT_SUCCESS
+
+# Make sure IFS has a sensible default
+lt_nl='
+'
+IFS=" $lt_nl"
+
+dirname="s,/[^/]*$,,"
+basename="s,^.*/,,"
+
+# func_dirname_and_basename file append nondir_replacement
+# perform func_basename and func_dirname in a single function
+# call:
+# dirname: Compute the dirname of FILE. If nonempty,
+# add APPEND to the result, otherwise set result
+# to NONDIR_REPLACEMENT.
+# value returned in "$func_dirname_result"
+# basename: Compute filename of FILE.
+# value retuned in "$func_basename_result"
+# Implementation must be kept synchronized with func_dirname
+# and func_basename. For efficiency, we do not delegate to
+# those functions but instead duplicate the functionality here.
+func_dirname_and_basename ()
+{
+ # Extract subdirectory from the argument.
+ func_dirname_result=`$ECHO "X${1}" | $Xsed -e "$dirname"`
+ if test "X$func_dirname_result" = "X${1}"; then
+ func_dirname_result="${3}"
+ else
+ func_dirname_result="$func_dirname_result${2}"
+ fi
+ func_basename_result=`$ECHO "X${1}" | $Xsed -e "$basename"`
+}
+
+# Generated shell functions inserted here.
+
+# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh
+# is ksh but when the shell is invoked as "sh" and the current value of
+# the _XPG environment variable is not equal to 1 (one), the special
+# positional parameter $0, within a function call, is the name of the
+# function.
+progpath="$0"
+
+# The name of this program:
+# In the unlikely event $progname began with a '-', it would play havoc with
+# func_echo (imagine progname=-n), so we prepend ./ in that case:
+func_dirname_and_basename "$progpath"
+progname=$func_basename_result
+case $progname in
+ -*) progname=./$progname ;;
+esac
+
+# Make sure we have an absolute path for reexecution:
+case $progpath in
+ [\\/]*|[A-Za-z]:\\*) ;;
+ *[\\/]*)
+ progdir=$func_dirname_result
+ progdir=`cd "$progdir" && pwd`
+ progpath="$progdir/$progname"
+ ;;
+ *)
+ save_IFS="$IFS"
+ IFS=:
+ for progdir in $PATH; do
+ IFS="$save_IFS"
+ test -x "$progdir/$progname" && break
+ done
+ IFS="$save_IFS"
+ test -n "$progdir" || progdir=`pwd`
+ progpath="$progdir/$progname"
+ ;;
+esac
+
+# Sed substitution that helps us do robust quoting. It backslashifies
+# metacharacters that are still active within double-quoted strings.
+Xsed="${SED}"' -e 1s/^X//'
+sed_quote_subst='s/\([`"$\\]\)/\\\1/g'
+
+# Same as above, but do not quote variable references.
+double_quote_subst='s/\(["`\\]\)/\\\1/g'
+
+# Re-`\' parameter expansions in output of double_quote_subst that were
+# `\'-ed in input to the same. If an odd number of `\' preceded a '$'
+# in input to double_quote_subst, that '$' was protected from expansion.
+# Since each input `\' is now two `\'s, look for any number of runs of
+# four `\'s followed by two `\'s and then a '$'. `\' that '$'.
+bs='\\'
+bs2='\\\\'
+bs4='\\\\\\\\'
+dollar='\$'
+sed_double_backslash="\
+ s/$bs4/&\\
+/g
+ s/^$bs2$dollar/$bs&/
+ s/\\([^$bs]\\)$bs2$dollar/\\1$bs2$bs$dollar/g
+ s/\n//g"
+
+# Standard options:
+opt_dry_run=false
+opt_help=false
+opt_quiet=false
+opt_verbose=false
+opt_warning=:
+
+# func_echo arg...
+# Echo program name prefixed message, along with the current mode
+# name if it has been set yet.
+func_echo ()
+{
+ $ECHO "$progname${mode+: }$mode: $*"
+}
+
+# func_verbose arg...
+# Echo program name prefixed message in verbose mode only.
+func_verbose ()
+{
+ $opt_verbose && func_echo ${1+"$@"}
+
+ # A bug in bash halts the script if the last line of a function
+ # fails when set -e is in force, so we need another command to
+ # work around that:
+ :
+}
+
+# func_error arg...
+# Echo program name prefixed message to standard error.
+func_error ()
+{
+ $ECHO "$progname${mode+: }$mode: "${1+"$@"} 1>&2
+}
+
+# func_warning arg...
+# Echo program name prefixed warning message to standard error.
+func_warning ()
+{
+ $opt_warning && $ECHO "$progname${mode+: }$mode: warning: "${1+"$@"} 1>&2
+
+ # bash bug again:
+ :
+}
+
+# func_fatal_error arg...
+# Echo program name prefixed message to standard error, and exit.
+func_fatal_error ()
+{
+ func_error ${1+"$@"}
+ exit $EXIT_FAILURE
+}
+
+# func_fatal_help arg...
+# Echo program name prefixed message to standard error, followed by
+# a help hint, and exit.
+func_fatal_help ()
+{
+ func_error ${1+"$@"}
+ func_fatal_error "$help"
+}
+help="Try \`$progname --help' for more information." ## default
+
+
+# func_grep expression filename
+# Check whether EXPRESSION matches any line of FILENAME, without output.
+func_grep ()
+{
+ $GREP "$1" "$2" >/dev/null 2>&1
+}
+
+
+# func_mkdir_p directory-path
+# Make sure the entire path to DIRECTORY-PATH is available.
+func_mkdir_p ()
+{
+ my_directory_path="$1"
+ my_dir_list=
+
+ if test -n "$my_directory_path" && test "$opt_dry_run" != ":"; then
+
+ # Protect directory names starting with `-'
+ case $my_directory_path in
+ -*) my_directory_path="./$my_directory_path" ;;
+ esac
+
+ # While some portion of DIR does not yet exist...
+ while test ! -d "$my_directory_path"; do
+ # ...make a list in topmost first order. Use a colon delimited
+ # list incase some portion of path contains whitespace.
+ my_dir_list="$my_directory_path:$my_dir_list"
+
+ # If the last portion added has no slash in it, the list is done
+ case $my_directory_path in */*) ;; *) break ;; esac
+
+ # ...otherwise throw away the child directory and loop
+ my_directory_path=`$ECHO "X$my_directory_path" | $Xsed -e "$dirname"`
+ done
+ my_dir_list=`$ECHO "X$my_dir_list" | $Xsed -e 's,:*$,,'`
+
+ save_mkdir_p_IFS="$IFS"; IFS=':'
+ for my_dir in $my_dir_list; do
+ IFS="$save_mkdir_p_IFS"
+ # mkdir can fail with a `File exist' error if two processes
+ # try to create one of the directories concurrently. Don't
+ # stop in that case!
+ $MKDIR "$my_dir" 2>/dev/null || :
+ done
+ IFS="$save_mkdir_p_IFS"
+
+ # Bail out if we (or some other process) failed to create a directory.
+ test -d "$my_directory_path" || \
+ func_fatal_error "Failed to create \`$1'"
+ fi
+}
+
+
+# func_mktempdir [string]
+# Make a temporary directory that won't clash with other running
+# libtool processes, and avoids race conditions if possible. If
+# given, STRING is the basename for that directory.
+func_mktempdir ()
+{
+ my_template="${TMPDIR-/tmp}/${1-$progname}"
+
+ if test "$opt_dry_run" = ":"; then
+ # Return a directory name, but don't create it in dry-run mode
+ my_tmpdir="${my_template}-$$"
+ else
+
+ # If mktemp works, use that first and foremost
+ my_tmpdir=`mktemp -d "${my_template}-XXXXXXXX" 2>/dev/null`
+
+ if test ! -d "$my_tmpdir"; then
+ # Failing that, at least try and use $RANDOM to avoid a race
+ my_tmpdir="${my_template}-${RANDOM-0}$$"
+
+ save_mktempdir_umask=`umask`
+ umask 0077
+ $MKDIR "$my_tmpdir"
+ umask $save_mktempdir_umask
+ fi
+
+ # If we're not in dry-run mode, bomb out on failure
+ test -d "$my_tmpdir" || \
+ func_fatal_error "cannot create temporary directory \`$my_tmpdir'"
+ fi
+
+ $ECHO "X$my_tmpdir" | $Xsed
+}
+
+
+# func_quote_for_eval arg
+# Aesthetically quote ARG to be evaled later.
+# This function returns two values: FUNC_QUOTE_FOR_EVAL_RESULT
+# is double-quoted, suitable for a subsequent eval, whereas
+# FUNC_QUOTE_FOR_EVAL_UNQUOTED_RESULT has merely all characters
+# which are still active within double quotes backslashified.
+func_quote_for_eval ()
+{
+ case $1 in
+ *[\\\`\"\$]*)
+ func_quote_for_eval_unquoted_result=`$ECHO "X$1" | $Xsed -e "$sed_quote_subst"` ;;
+ *)
+ func_quote_for_eval_unquoted_result="$1" ;;
+ esac
+
+ case $func_quote_for_eval_unquoted_result in
+ # Double-quote args containing shell metacharacters to delay
+ # word splitting, command substitution and and variable
+ # expansion for a subsequent eval.
+ # Many Bourne shells cannot handle close brackets correctly
+ # in scan sets, so we specify it separately.
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ func_quote_for_eval_result="\"$func_quote_for_eval_unquoted_result\""
+ ;;
+ *)
+ func_quote_for_eval_result="$func_quote_for_eval_unquoted_result"
+ esac
+}
+
+
+# func_quote_for_expand arg
+# Aesthetically quote ARG to be evaled later; same as above,
+# but do not quote variable references.
+func_quote_for_expand ()
+{
+ case $1 in
+ *[\\\`\"]*)
+ my_arg=`$ECHO "X$1" | $Xsed \
+ -e "$double_quote_subst" -e "$sed_double_backslash"` ;;
+ *)
+ my_arg="$1" ;;
+ esac
+
+ case $my_arg in
+ # Double-quote args containing shell metacharacters to delay
+ # word splitting and command substitution for a subsequent eval.
+ # Many Bourne shells cannot handle close brackets correctly
+ # in scan sets, so we specify it separately.
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ my_arg="\"$my_arg\""
+ ;;
+ esac
+
+ func_quote_for_expand_result="$my_arg"
+}
+
+
+# func_show_eval cmd [fail_exp]
+# Unless opt_silent is true, then output CMD. Then, if opt_dryrun is
+# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP
+# is given, then evaluate it.
+func_show_eval ()
+{
+ my_cmd="$1"
+ my_fail_exp="${2-:}"
+
+ ${opt_silent-false} || {
+ func_quote_for_expand "$my_cmd"
+ eval "func_echo $func_quote_for_expand_result"
+ }
+
+ if ${opt_dry_run-false}; then :; else
+ eval "$my_cmd"
+ my_status=$?
+ if test "$my_status" -eq 0; then :; else
+ eval "(exit $my_status); $my_fail_exp"
+ fi
+ fi
+}
+
+
+# func_show_eval_locale cmd [fail_exp]
+# Unless opt_silent is true, then output CMD. Then, if opt_dryrun is
+# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP
+# is given, then evaluate it. Use the saved locale for evaluation.
+func_show_eval_locale ()
+{
+ my_cmd="$1"
+ my_fail_exp="${2-:}"
+
+ ${opt_silent-false} || {
+ func_quote_for_expand "$my_cmd"
+ eval "func_echo $func_quote_for_expand_result"
+ }
+
+ if ${opt_dry_run-false}; then :; else
+ eval "$lt_user_locale
+ $my_cmd"
+ my_status=$?
+ eval "$lt_safe_locale"
+ if test "$my_status" -eq 0; then :; else
+ eval "(exit $my_status); $my_fail_exp"
+ fi
+ fi
+}
+
+
+
+
+
+# func_version
+# Echo version message to standard output and exit.
+func_version ()
+{
+ $SED -n '/^# '$PROGRAM' (GNU /,/# warranty; / {
+ s/^# //
+ s/^# *$//
+ s/\((C)\)[ 0-9,-]*\( [1-9][0-9]*\)/\1\2/
+ p
+ }' < "$progpath"
+ exit $?
+}
+
+# func_usage
+# Echo short help message to standard output and exit.
+func_usage ()
+{
+ $SED -n '/^# Usage:/,/# -h/ {
+ s/^# //
+ s/^# *$//
+ s/\$progname/'$progname'/
+ p
+ }' < "$progpath"
+ $ECHO
+ $ECHO "run \`$progname --help | more' for full usage"
+ exit $?
+}
+
+# func_help
+# Echo long help message to standard output and exit.
+func_help ()
+{
+ $SED -n '/^# Usage:/,/# Report bugs to/ {
+ s/^# //
+ s/^# *$//
+ s*\$progname*'$progname'*
+ s*\$host*'"$host"'*
+ s*\$SHELL*'"$SHELL"'*
+ s*\$LTCC*'"$LTCC"'*
+ s*\$LTCFLAGS*'"$LTCFLAGS"'*
+ s*\$LD*'"$LD"'*
+ s/\$with_gnu_ld/'"$with_gnu_ld"'/
+ s/\$automake_version/'"`(automake --version) 2>/dev/null |$SED 1q`"'/
+ s/\$autoconf_version/'"`(autoconf --version) 2>/dev/null |$SED 1q`"'/
+ p
+ }' < "$progpath"
+ exit $?
+}
+
+# func_missing_arg argname
+# Echo program name prefixed message to standard error and set global
+# exit_cmd.
+func_missing_arg ()
+{
+ func_error "missing argument for $1"
+ exit_cmd=exit
+}
+
+exit_cmd=:
+
+
+
+
+
+# Check that we have a working $ECHO.
+if test "X$1" = X--no-reexec; then
+ # Discard the --no-reexec flag, and continue.
+ shift
+elif test "X$1" = X--fallback-echo; then
+ # Avoid inline document here, it may be left over
+ :
+elif test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t'; then
+ # Yippee, $ECHO works!
+ :
+else
+ # Restart under the correct shell, and then maybe $ECHO will work.
+ exec $SHELL "$progpath" --no-reexec ${1+"$@"}
+fi
+
+if test "X$1" = X--fallback-echo; then
+ # used as fallback echo
+ shift
+ cat <<EOF
+$*
+EOF
+ exit $EXIT_SUCCESS
+fi
+
+magic="%%%MAGIC variable%%%"
+magic_exe="%%%MAGIC EXE variable%%%"
+
+# Global variables.
+# $mode is unset
+nonopt=
+execute_dlfiles=
+preserve_args=
+lo2o="s/\\.lo\$/.${objext}/"
+o2lo="s/\\.${objext}\$/.lo/"
+extracted_archives=
+extracted_serial=0
+
+opt_dry_run=false
+opt_duplicate_deps=false
+opt_silent=false
+opt_debug=:
+
+# If this variable is set in any of the actions, the command in it
+# will be execed at the end. This prevents here-documents from being
+# left over by shells.
+exec_cmd=
+
+# func_fatal_configuration arg...
+# Echo program name prefixed message to standard error, followed by
+# a configuration failure hint, and exit.
+func_fatal_configuration ()
+{
+ func_error ${1+"$@"}
+ func_error "See the $PACKAGE documentation for more information."
+ func_fatal_error "Fatal configuration error."
+}
+
+
+# func_config
+# Display the configuration for all the tags in this script.
+func_config ()
+{
+ re_begincf='^# ### BEGIN LIBTOOL'
+ re_endcf='^# ### END LIBTOOL'
+
+ # Default configuration.
+ $SED "1,/$re_begincf CONFIG/d;/$re_endcf CONFIG/,\$d" < "$progpath"
+
+ # Now print the configurations for the tags.
+ for tagname in $taglist; do
+ $SED -n "/$re_begincf TAG CONFIG: $tagname\$/,/$re_endcf TAG CONFIG: $tagname\$/p" < "$progpath"
+ done
+
+ exit $?
+}
+
+# func_features
+# Display the features supported by this script.
+func_features ()
+{
+ $ECHO "host: $host"
+ if test "$build_libtool_libs" = yes; then
+ $ECHO "enable shared libraries"
+ else
+ $ECHO "disable shared libraries"
+ fi
+ if test "$build_old_libs" = yes; then
+ $ECHO "enable static libraries"
+ else
+ $ECHO "disable static libraries"
+ fi
+
+ exit $?
+}
+
+# func_enable_tag tagname
+# Verify that TAGNAME is valid, and either flag an error and exit, or
+# enable the TAGNAME tag. We also add TAGNAME to the global $taglist
+# variable here.
+func_enable_tag ()
+{
+ # Global variable:
+ tagname="$1"
+
+ re_begincf="^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\$"
+ re_endcf="^# ### END LIBTOOL TAG CONFIG: $tagname\$"
+ sed_extractcf="/$re_begincf/,/$re_endcf/p"
+
+ # Validate tagname.
+ case $tagname in
+ *[!-_A-Za-z0-9,/]*)
+ func_fatal_error "invalid tag name: $tagname"
+ ;;
+ esac
+
+ # Don't test for the "default" C tag, as we know it's
+ # there but not specially marked.
+ case $tagname in
+ CC) ;;
+ *)
+ if $GREP "$re_begincf" "$progpath" >/dev/null 2>&1; then
+ taglist="$taglist $tagname"
+
+ # Evaluate the configuration. Be careful to quote the path
+ # and the sed script, to avoid splitting on whitespace, but
+ # also don't use non-portable quotes within backquotes within
+ # quotes we have to do it in 2 steps:
+ extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"`
+ eval "$extractedcf"
+ else
+ func_error "ignoring unknown tag $tagname"
+ fi
+ ;;
+ esac
+}
+
+# Parse options once, thoroughly. This comes as soon as possible in
+# the script to make things like `libtool --version' happen quickly.
+{
+
+ # Shorthand for --mode=foo, only valid as the first argument
+ case $1 in
+ clean|clea|cle|cl)
+ shift; set dummy --mode clean ${1+"$@"}; shift
+ ;;
+ compile|compil|compi|comp|com|co|c)
+ shift; set dummy --mode compile ${1+"$@"}; shift
+ ;;
+ execute|execut|execu|exec|exe|ex|e)
+ shift; set dummy --mode execute ${1+"$@"}; shift
+ ;;
+ finish|finis|fini|fin|fi|f)
+ shift; set dummy --mode finish ${1+"$@"}; shift
+ ;;
+ install|instal|insta|inst|ins|in|i)
+ shift; set dummy --mode install ${1+"$@"}; shift
+ ;;
+ link|lin|li|l)
+ shift; set dummy --mode link ${1+"$@"}; shift
+ ;;
+ uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u)
+ shift; set dummy --mode uninstall ${1+"$@"}; shift
+ ;;
+ esac
+
+ # Parse non-mode specific arguments:
+ while test "$#" -gt 0; do
+ opt="$1"
+ shift
+
+ case $opt in
+ --config) func_config ;;
+
+ --debug) preserve_args="$preserve_args $opt"
+ func_echo "enabling shell trace mode"
+ opt_debug='set -x'
+ $opt_debug
+ ;;
+
+ -dlopen) test "$#" -eq 0 && func_missing_arg "$opt" && break
+ execute_dlfiles="$execute_dlfiles $1"
+ shift
+ ;;
+
+ --dry-run | -n) opt_dry_run=: ;;
+ --features) func_features ;;
+ --finish) mode="finish" ;;
+
+ --mode) test "$#" -eq 0 && func_missing_arg "$opt" && break
+ case $1 in
+ # Valid mode arguments:
+ clean) ;;
+ compile) ;;
+ execute) ;;
+ finish) ;;
+ install) ;;
+ link) ;;
+ relink) ;;
+ uninstall) ;;
+
+ # Catch anything else as an error
+ *) func_error "invalid argument for $opt"
+ exit_cmd=exit
+ break
+ ;;
+ esac
+
+ mode="$1"
+ shift
+ ;;
+
+ --preserve-dup-deps)
+ opt_duplicate_deps=: ;;
+
+ --quiet|--silent) preserve_args="$preserve_args $opt"
+ opt_silent=:
+ ;;
+
+ --verbose| -v) preserve_args="$preserve_args $opt"
+ opt_silent=false
+ ;;
+
+ --tag) test "$#" -eq 0 && func_missing_arg "$opt" && break
+ preserve_args="$preserve_args $opt $1"
+ func_enable_tag "$1" # tagname is set here
+ shift
+ ;;
+
+ # Separate optargs to long options:
+ -dlopen=*|--mode=*|--tag=*)
+ func_opt_split "$opt"
+ set dummy "$func_opt_split_opt" "$func_opt_split_arg" ${1+"$@"}
+ shift
+ ;;
+
+ -\?|-h) func_usage ;;
+ --help) opt_help=: ;;
+ --version) func_version ;;
+
+ -*) func_fatal_help "unrecognized option \`$opt'" ;;
+
+ *) nonopt="$opt"
+ break
+ ;;
+ esac
+ done
+
+
+ case $host in
+ *cygwin* | *mingw* | *pw32* | *cegcc*)
+ # don't eliminate duplications in $postdeps and $predeps
+ opt_duplicate_compiler_generated_deps=:
+ ;;
+ *)
+ opt_duplicate_compiler_generated_deps=$opt_duplicate_deps
+ ;;
+ esac
+
+ # Having warned about all mis-specified options, bail out if
+ # anything was wrong.
+ $exit_cmd $EXIT_FAILURE
+}
+
+# func_check_version_match
+# Ensure that we are using m4 macros, and libtool script from the same
+# release of libtool.
+func_check_version_match ()
+{
+ if test "$package_revision" != "$macro_revision"; then
+ if test "$VERSION" != "$macro_version"; then
+ if test -z "$macro_version"; then
+ cat >&2 <<_LT_EOF
+$progname: Version mismatch error. This is $PACKAGE $VERSION, but the
+$progname: definition of this LT_INIT comes from an older release.
+$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION
+$progname: and run autoconf again.
+_LT_EOF
+ else
+ cat >&2 <<_LT_EOF
+$progname: Version mismatch error. This is $PACKAGE $VERSION, but the
+$progname: definition of this LT_INIT comes from $PACKAGE $macro_version.
+$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION
+$progname: and run autoconf again.
+_LT_EOF
+ fi
+ else
+ cat >&2 <<_LT_EOF
+$progname: Version mismatch error. This is $PACKAGE $VERSION, revision $package_revision,
+$progname: but the definition of this LT_INIT comes from revision $macro_revision.
+$progname: You should recreate aclocal.m4 with macros from revision $package_revision
+$progname: of $PACKAGE $VERSION and run autoconf again.
+_LT_EOF
+ fi
+
+ exit $EXIT_MISMATCH
+ fi
+}
+
+
+## ----------- ##
+## Main. ##
+## ----------- ##
+
+$opt_help || {
+ # Sanity checks first:
+ func_check_version_match
+
+ if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then
+ func_fatal_configuration "not configured to build any kind of library"
+ fi
+
+ test -z "$mode" && func_fatal_error "error: you must specify a MODE."
+
+
+ # Darwin sucks
+ eval std_shrext=\"$shrext_cmds\"
+
+
+ # Only execute mode is allowed to have -dlopen flags.
+ if test -n "$execute_dlfiles" && test "$mode" != execute; then
+ func_error "unrecognized option \`-dlopen'"
+ $ECHO "$help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ # Change the help message to a mode-specific one.
+ generic_help="$help"
+ help="Try \`$progname --help --mode=$mode' for more information."
+}
+
+
+# func_lalib_p file
+# True iff FILE is a libtool `.la' library or `.lo' object file.
+# This function is only a basic sanity check; it will hardly flush out
+# determined imposters.
+func_lalib_p ()
+{
+ test -f "$1" &&
+ $SED -e 4q "$1" 2>/dev/null \
+ | $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1
+}
+
+# func_lalib_unsafe_p file
+# True iff FILE is a libtool `.la' library or `.lo' object file.
+# This function implements the same check as func_lalib_p without
+# resorting to external programs. To this end, it redirects stdin and
+# closes it afterwards, without saving the original file descriptor.
+# As a safety measure, use it only where a negative result would be
+# fatal anyway. Works if `file' does not exist.
+func_lalib_unsafe_p ()
+{
+ lalib_p=no
+ if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then
+ for lalib_p_l in 1 2 3 4
+ do
+ read lalib_p_line
+ case "$lalib_p_line" in
+ \#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;;
+ esac
+ done
+ exec 0<&5 5<&-
+ fi
+ test "$lalib_p" = yes
+}
+
+# func_ltwrapper_script_p file
+# True iff FILE is a libtool wrapper script
+# This function is only a basic sanity check; it will hardly flush out
+# determined imposters.
+func_ltwrapper_script_p ()
+{
+ func_lalib_p "$1"
+}
+
+# func_ltwrapper_executable_p file
+# True iff FILE is a libtool wrapper executable
+# This function is only a basic sanity check; it will hardly flush out
+# determined imposters.
+func_ltwrapper_executable_p ()
+{
+ func_ltwrapper_exec_suffix=
+ case $1 in
+ *.exe) ;;
+ *) func_ltwrapper_exec_suffix=.exe ;;
+ esac
+ $GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1
+}
+
+# func_ltwrapper_scriptname file
+# Assumes file is an ltwrapper_executable
+# uses $file to determine the appropriate filename for a
+# temporary ltwrapper_script.
+func_ltwrapper_scriptname ()
+{
+ func_ltwrapper_scriptname_result=""
+ if func_ltwrapper_executable_p "$1"; then
+ func_dirname_and_basename "$1" "" "."
+ func_stripname '' '.exe' "$func_basename_result"
+ func_ltwrapper_scriptname_result="$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper"
+ fi
+}
+
+# func_ltwrapper_p file
+# True iff FILE is a libtool wrapper script or wrapper executable
+# This function is only a basic sanity check; it will hardly flush out
+# determined imposters.
+func_ltwrapper_p ()
+{
+ func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1"
+}
+
+
+# func_execute_cmds commands fail_cmd
+# Execute tilde-delimited COMMANDS.
+# If FAIL_CMD is given, eval that upon failure.
+# FAIL_CMD may read-access the current command in variable CMD!
+func_execute_cmds ()
+{
+ $opt_debug
+ save_ifs=$IFS; IFS='~'
+ for cmd in $1; do
+ IFS=$save_ifs
+ eval cmd=\"$cmd\"
+ func_show_eval "$cmd" "${2-:}"
+ done
+ IFS=$save_ifs
+}
+
+
+# func_source file
+# Source FILE, adding directory component if necessary.
+# Note that it is not necessary on cygwin/mingw to append a dot to
+# FILE even if both FILE and FILE.exe exist: automatic-append-.exe
+# behavior happens only for exec(3), not for open(2)! Also, sourcing
+# `FILE.' does not work on cygwin managed mounts.
+func_source ()
+{
+ $opt_debug
+ case $1 in
+ */* | *\\*) . "$1" ;;
+ *) . "./$1" ;;
+ esac
+}
+
+
+# func_infer_tag arg
+# Infer tagged configuration to use if any are available and
+# if one wasn't chosen via the "--tag" command line option.
+# Only attempt this if the compiler in the base compile
+# command doesn't match the default compiler.
+# arg is usually of the form 'gcc ...'
+func_infer_tag ()
+{
+ $opt_debug
+ if test -n "$available_tags" && test -z "$tagname"; then
+ CC_quoted=
+ for arg in $CC; do
+ func_quote_for_eval "$arg"
+ CC_quoted="$CC_quoted $func_quote_for_eval_result"
+ done
+ case $@ in
+ # Blanks in the command may have been stripped by the calling shell,
+ # but not from the CC environment variable when configure was run.
+ " $CC "* | "$CC "* | " `$ECHO $CC` "* | "`$ECHO $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$ECHO $CC_quoted` "* | "`$ECHO $CC_quoted` "*) ;;
+ # Blanks at the start of $base_compile will cause this to fail
+ # if we don't check for them as well.
+ *)
+ for z in $available_tags; do
+ if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then
+ # Evaluate the configuration.
+ eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`"
+ CC_quoted=
+ for arg in $CC; do
+ # Double-quote args containing other shell metacharacters.
+ func_quote_for_eval "$arg"
+ CC_quoted="$CC_quoted $func_quote_for_eval_result"
+ done
+ case "$@ " in
+ " $CC "* | "$CC "* | " `$ECHO $CC` "* | "`$ECHO $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$ECHO $CC_quoted` "* | "`$ECHO $CC_quoted` "*)
+ # The compiler in the base compile command matches
+ # the one in the tagged configuration.
+ # Assume this is the tagged configuration we want.
+ tagname=$z
+ break
+ ;;
+ esac
+ fi
+ done
+ # If $tagname still isn't set, then no tagged configuration
+ # was found and let the user know that the "--tag" command
+ # line option must be used.
+ if test -z "$tagname"; then
+ func_echo "unable to infer tagged configuration"
+ func_fatal_error "specify a tag with \`--tag'"
+# else
+# func_verbose "using $tagname tagged configuration"
+ fi
+ ;;
+ esac
+ fi
+}
+
+
+
+# func_write_libtool_object output_name pic_name nonpic_name
+# Create a libtool object file (analogous to a ".la" file),
+# but don't create it if we're doing a dry run.
+func_write_libtool_object ()
+{
+ write_libobj=${1}
+ if test "$build_libtool_libs" = yes; then
+ write_lobj=\'${2}\'
+ else
+ write_lobj=none
+ fi
+
+ if test "$build_old_libs" = yes; then
+ write_oldobj=\'${3}\'
+ else
+ write_oldobj=none
+ fi
+
+ $opt_dry_run || {
+ cat >${write_libobj}T <<EOF
+# $write_libobj - a libtool object file
+# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# Name of the PIC object.
+pic_object=$write_lobj
+
+# Name of the non-PIC object
+non_pic_object=$write_oldobj
+
+EOF
+ $MV "${write_libobj}T" "${write_libobj}"
+ }
+}
+
+# func_mode_compile arg...
+func_mode_compile ()
+{
+ $opt_debug
+ # Get the compilation command and the source file.
+ base_compile=
+ srcfile="$nonopt" # always keep a non-empty value in "srcfile"
+ suppress_opt=yes
+ suppress_output=
+ arg_mode=normal
+ libobj=
+ later=
+ pie_flag=
+
+ for arg
+ do
+ case $arg_mode in
+ arg )
+ # do not "continue". Instead, add this to base_compile
+ lastarg="$arg"
+ arg_mode=normal
+ ;;
+
+ target )
+ libobj="$arg"
+ arg_mode=normal
+ continue
+ ;;
+
+ normal )
+ # Accept any command-line options.
+ case $arg in
+ -o)
+ test -n "$libobj" && \
+ func_fatal_error "you cannot specify \`-o' more than once"
+ arg_mode=target
+ continue
+ ;;
+
+ -pie | -fpie | -fPIE)
+ pie_flag="$pie_flag $arg"
+ continue
+ ;;
+
+ -shared | -static | -prefer-pic | -prefer-non-pic)
+ later="$later $arg"
+ continue
+ ;;
+
+ -no-suppress)
+ suppress_opt=no
+ continue
+ ;;
+
+ -Xcompiler)
+ arg_mode=arg # the next one goes into the "base_compile" arg list
+ continue # The current "srcfile" will either be retained or
+ ;; # replaced later. I would guess that would be a bug.
+
+ -Wc,*)
+ func_stripname '-Wc,' '' "$arg"
+ args=$func_stripname_result
+ lastarg=
+ save_ifs="$IFS"; IFS=','
+ for arg in $args; do
+ IFS="$save_ifs"
+ func_quote_for_eval "$arg"
+ lastarg="$lastarg $func_quote_for_eval_result"
+ done
+ IFS="$save_ifs"
+ func_stripname ' ' '' "$lastarg"
+ lastarg=$func_stripname_result
+
+ # Add the arguments to base_compile.
+ base_compile="$base_compile $lastarg"
+ continue
+ ;;
+
+ *)
+ # Accept the current argument as the source file.
+ # The previous "srcfile" becomes the current argument.
+ #
+ lastarg="$srcfile"
+ srcfile="$arg"
+ ;;
+ esac # case $arg
+ ;;
+ esac # case $arg_mode
+
+ # Aesthetically quote the previous argument.
+ func_quote_for_eval "$lastarg"
+ base_compile="$base_compile $func_quote_for_eval_result"
+ done # for arg
+
+ case $arg_mode in
+ arg)
+ func_fatal_error "you must specify an argument for -Xcompile"
+ ;;
+ target)
+ func_fatal_error "you must specify a target with \`-o'"
+ ;;
+ *)
+ # Get the name of the library object.
+ test -z "$libobj" && {
+ func_basename "$srcfile"
+ libobj="$func_basename_result"
+ }
+ ;;
+ esac
+
+ # Recognize several different file suffixes.
+ # If the user specifies -o file.o, it is replaced with file.lo
+ case $libobj in
+ *.[cCFSifmso] | \
+ *.ada | *.adb | *.ads | *.asm | \
+ *.c++ | *.cc | *.ii | *.class | *.cpp | *.cxx | \
+ *.[fF][09]? | *.for | *.java | *.obj | *.sx)
+ func_xform "$libobj"
+ libobj=$func_xform_result
+ ;;
+ esac
+
+ case $libobj in
+ *.lo) func_lo2o "$libobj"; obj=$func_lo2o_result ;;
+ *)
+ func_fatal_error "cannot determine name of library object from \`$libobj'"
+ ;;
+ esac
+
+ func_infer_tag $base_compile
+
+ for arg in $later; do
+ case $arg in
+ -shared)
+ test "$build_libtool_libs" != yes && \
+ func_fatal_configuration "can not build a shared library"
+ build_old_libs=no
+ continue
+ ;;
+
+ -static)
+ build_libtool_libs=no
+ build_old_libs=yes
+ continue
+ ;;
+
+ -prefer-pic)
+ pic_mode=yes
+ continue
+ ;;
+
+ -prefer-non-pic)
+ pic_mode=no
+ continue
+ ;;
+ esac
+ done
+
+ func_quote_for_eval "$libobj"
+ test "X$libobj" != "X$func_quote_for_eval_result" \
+ && $ECHO "X$libobj" | $GREP '[]~#^*{};<>?"'"'"' &()|`$[]' \
+ && func_warning "libobj name \`$libobj' may not contain shell special characters."
+ func_dirname_and_basename "$obj" "/" ""
+ objname="$func_basename_result"
+ xdir="$func_dirname_result"
+ lobj=${xdir}$objdir/$objname
+
+ test -z "$base_compile" && \
+ func_fatal_help "you must specify a compilation command"
+
+ # Delete any leftover library objects.
+ if test "$build_old_libs" = yes; then
+ removelist="$obj $lobj $libobj ${libobj}T"
+ else
+ removelist="$lobj $libobj ${libobj}T"
+ fi
+
+ # On Cygwin there's no "real" PIC flag so we must build both object types
+ case $host_os in
+ cygwin* | mingw* | pw32* | os2* | cegcc*)
+ pic_mode=default
+ ;;
+ esac
+ if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then
+ # non-PIC code in shared libraries is not supported
+ pic_mode=default
+ fi
+
+ # Calculate the filename of the output object if compiler does
+ # not support -o with -c
+ if test "$compiler_c_o" = no; then
+ output_obj=`$ECHO "X$srcfile" | $Xsed -e 's%^.*/%%' -e 's%\.[^.]*$%%'`.${objext}
+ lockfile="$output_obj.lock"
+ else
+ output_obj=
+ need_locks=no
+ lockfile=
+ fi
+
+ # Lock this critical section if it is needed
+ # We use this script file to make the link, it avoids creating a new file
+ if test "$need_locks" = yes; then
+ until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do
+ func_echo "Waiting for $lockfile to be removed"
+ sleep 2
+ done
+ elif test "$need_locks" = warn; then
+ if test -f "$lockfile"; then
+ $ECHO "\
+*** ERROR, $lockfile exists and contains:
+`cat $lockfile 2>/dev/null`
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support \`-c' and \`-o' together. If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+ $opt_dry_run || $RM $removelist
+ exit $EXIT_FAILURE
+ fi
+ removelist="$removelist $output_obj"
+ $ECHO "$srcfile" > "$lockfile"
+ fi
+
+ $opt_dry_run || $RM $removelist
+ removelist="$removelist $lockfile"
+ trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15
+
+ if test -n "$fix_srcfile_path"; then
+ eval srcfile=\"$fix_srcfile_path\"
+ fi
+ func_quote_for_eval "$srcfile"
+ qsrcfile=$func_quote_for_eval_result
+
+ # Only build a PIC object if we are building libtool libraries.
+ if test "$build_libtool_libs" = yes; then
+ # Without this assignment, base_compile gets emptied.
+ fbsd_hideous_sh_bug=$base_compile
+
+ if test "$pic_mode" != no; then
+ command="$base_compile $qsrcfile $pic_flag"
+ else
+ # Don't build PIC code
+ command="$base_compile $qsrcfile"
+ fi
+
+ func_mkdir_p "$xdir$objdir"
+
+ if test -z "$output_obj"; then
+ # Place PIC objects in $objdir
+ command="$command -o $lobj"
+ fi
+
+ func_show_eval_locale "$command" \
+ 'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE'
+
+ if test "$need_locks" = warn &&
+ test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then
+ $ECHO "\
+*** ERROR, $lockfile contains:
+`cat $lockfile 2>/dev/null`
+
+but it should contain:
+$srcfile
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support \`-c' and \`-o' together. If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+ $opt_dry_run || $RM $removelist
+ exit $EXIT_FAILURE
+ fi
+
+ # Just move the object if needed, then go on to compile the next one
+ if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then
+ func_show_eval '$MV "$output_obj" "$lobj"' \
+ 'error=$?; $opt_dry_run || $RM $removelist; exit $error'
+ fi
+
+ # Allow error messages only from the first compilation.
+ if test "$suppress_opt" = yes; then
+ suppress_output=' >/dev/null 2>&1'
+ fi
+ fi
+
+ # Only build a position-dependent object if we build old libraries.
+ if test "$build_old_libs" = yes; then
+ if test "$pic_mode" != yes; then
+ # Don't build PIC code
+ command="$base_compile $qsrcfile$pie_flag"
+ else
+ command="$base_compile $qsrcfile $pic_flag"
+ fi
+ if test "$compiler_c_o" = yes; then
+ command="$command -o $obj"
+ fi
+
+ # Suppress compiler output if we already did a PIC compilation.
+ command="$command$suppress_output"
+ func_show_eval_locale "$command" \
+ '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE'
+
+ if test "$need_locks" = warn &&
+ test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then
+ $ECHO "\
+*** ERROR, $lockfile contains:
+`cat $lockfile 2>/dev/null`
+
+but it should contain:
+$srcfile
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support \`-c' and \`-o' together. If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+ $opt_dry_run || $RM $removelist
+ exit $EXIT_FAILURE
+ fi
+
+ # Just move the object if needed
+ if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then
+ func_show_eval '$MV "$output_obj" "$obj"' \
+ 'error=$?; $opt_dry_run || $RM $removelist; exit $error'
+ fi
+ fi
+
+ $opt_dry_run || {
+ func_write_libtool_object "$libobj" "$objdir/$objname" "$objname"
+
+ # Unlock the critical section if it was locked
+ if test "$need_locks" != no; then
+ removelist=$lockfile
+ $RM "$lockfile"
+ fi
+ }
+
+ exit $EXIT_SUCCESS
+}
+
+$opt_help || {
+test "$mode" = compile && func_mode_compile ${1+"$@"}
+}
+
+func_mode_help ()
+{
+ # We need to display help for each of the modes.
+ case $mode in
+ "")
+ # Generic help is extracted from the usage comments
+ # at the start of this file.
+ func_help
+ ;;
+
+ clean)
+ $ECHO \
+"Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE...
+
+Remove files from the build directory.
+
+RM is the name of the program to use to delete files associated with each FILE
+(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed
+to RM.
+
+If FILE is a libtool library, object or program, all the files associated
+with it are deleted. Otherwise, only FILE itself is deleted using RM."
+ ;;
+
+ compile)
+ $ECHO \
+"Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE
+
+Compile a source file into a libtool library object.
+
+This mode accepts the following additional options:
+
+ -o OUTPUT-FILE set the output file name to OUTPUT-FILE
+ -no-suppress do not suppress compiler output for multiple passes
+ -prefer-pic try to building PIC objects only
+ -prefer-non-pic try to building non-PIC objects only
+ -shared do not build a \`.o' file suitable for static linking
+ -static only build a \`.o' file suitable for static linking
+
+COMPILE-COMMAND is a command to be used in creating a \`standard' object file
+from the given SOURCEFILE.
+
+The output file name is determined by removing the directory component from
+SOURCEFILE, then substituting the C source code suffix \`.c' with the
+library object suffix, \`.lo'."
+ ;;
+
+ execute)
+ $ECHO \
+"Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]...
+
+Automatically set library path, then run a program.
+
+This mode accepts the following additional options:
+
+ -dlopen FILE add the directory containing FILE to the library path
+
+This mode sets the library path environment variable according to \`-dlopen'
+flags.
+
+If any of the ARGS are libtool executable wrappers, then they are translated
+into their corresponding uninstalled binary, and any of their required library
+directories are added to the library path.
+
+Then, COMMAND is executed, with ARGS as arguments."
+ ;;
+
+ finish)
+ $ECHO \
+"Usage: $progname [OPTION]... --mode=finish [LIBDIR]...
+
+Complete the installation of libtool libraries.
+
+Each LIBDIR is a directory that contains libtool libraries.
+
+The commands that this mode executes may require superuser privileges. Use
+the \`--dry-run' option if you just want to see what would be executed."
+ ;;
+
+ install)
+ $ECHO \
+"Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND...
+
+Install executables or libraries.
+
+INSTALL-COMMAND is the installation command. The first component should be
+either the \`install' or \`cp' program.
+
+The following components of INSTALL-COMMAND are treated specially:
+
+ -inst-prefix PREFIX-DIR Use PREFIX-DIR as a staging area for installation
+
+The rest of the components are interpreted as arguments to that command (only
+BSD-compatible install options are recognized)."
+ ;;
+
+ link)
+ $ECHO \
+"Usage: $progname [OPTION]... --mode=link LINK-COMMAND...
+
+Link object files or libraries together to form another library, or to
+create an executable program.
+
+LINK-COMMAND is a command using the C compiler that you would use to create
+a program from several object files.
+
+The following components of LINK-COMMAND are treated specially:
+
+ -all-static do not do any dynamic linking at all
+ -avoid-version do not add a version suffix if possible
+ -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime
+ -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols
+ -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3)
+ -export-symbols SYMFILE
+ try to export only the symbols listed in SYMFILE
+ -export-symbols-regex REGEX
+ try to export only the symbols matching REGEX
+ -LLIBDIR search LIBDIR for required installed libraries
+ -lNAME OUTPUT-FILE requires the installed library libNAME
+ -module build a library that can dlopened
+ -no-fast-install disable the fast-install mode
+ -no-install link a not-installable executable
+ -no-undefined declare that a library does not refer to external symbols
+ -o OUTPUT-FILE create OUTPUT-FILE from the specified objects
+ -objectlist FILE Use a list of object files found in FILE to specify objects
+ -precious-files-regex REGEX
+ don't remove output files matching REGEX
+ -release RELEASE specify package release information
+ -rpath LIBDIR the created library will eventually be installed in LIBDIR
+ -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries
+ -shared only do dynamic linking of libtool libraries
+ -shrext SUFFIX override the standard shared library file extension
+ -static do not do any dynamic linking of uninstalled libtool libraries
+ -static-libtool-libs
+ do not do any dynamic linking of libtool libraries
+ -version-info CURRENT[:REVISION[:AGE]]
+ specify library version info [each variable defaults to 0]
+ -weak LIBNAME declare that the target provides the LIBNAME interface
+
+All other options (arguments beginning with \`-') are ignored.
+
+Every other argument is treated as a filename. Files ending in \`.la' are
+treated as uninstalled libtool libraries, other files are standard or library
+object files.
+
+If the OUTPUT-FILE ends in \`.la', then a libtool library is created,
+only library objects (\`.lo' files) may be specified, and \`-rpath' is
+required, except when creating a convenience library.
+
+If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created
+using \`ar' and \`ranlib', or on Windows using \`lib'.
+
+If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file
+is created, otherwise an executable program is created."
+ ;;
+
+ uninstall)
+ $ECHO \
+"Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE...
+
+Remove libraries from an installation directory.
+
+RM is the name of the program to use to delete files associated with each FILE
+(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed
+to RM.
+
+If FILE is a libtool library, all the files associated with it are deleted.
+Otherwise, only FILE itself is deleted using RM."
+ ;;
+
+ *)
+ func_fatal_help "invalid operation mode \`$mode'"
+ ;;
+ esac
+
+ $ECHO
+ $ECHO "Try \`$progname --help' for more information about other modes."
+
+ exit $?
+}
+
+ # Now that we've collected a possible --mode arg, show help if necessary
+ $opt_help && func_mode_help
+
+
+# func_mode_execute arg...
+func_mode_execute ()
+{
+ $opt_debug
+ # The first argument is the command name.
+ cmd="$nonopt"
+ test -z "$cmd" && \
+ func_fatal_help "you must specify a COMMAND"
+
+ # Handle -dlopen flags immediately.
+ for file in $execute_dlfiles; do
+ test -f "$file" \
+ || func_fatal_help "\`$file' is not a file"
+
+ dir=
+ case $file in
+ *.la)
+ # Check to see that this really is a libtool archive.
+ func_lalib_unsafe_p "$file" \
+ || func_fatal_help "\`$lib' is not a valid libtool archive"
+
+ # Read the libtool library.
+ dlname=
+ library_names=
+ func_source "$file"
+
+ # Skip this library if it cannot be dlopened.
+ if test -z "$dlname"; then
+ # Warn if it was a shared library.
+ test -n "$library_names" && \
+ func_warning "\`$file' was not linked with \`-export-dynamic'"
+ continue
+ fi
+
+ func_dirname "$file" "" "."
+ dir="$func_dirname_result"
+
+ if test -f "$dir/$objdir/$dlname"; then
+ dir="$dir/$objdir"
+ else
+ if test ! -f "$dir/$dlname"; then
+ func_fatal_error "cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'"
+ fi
+ fi
+ ;;
+
+ *.lo)
+ # Just add the directory containing the .lo file.
+ func_dirname "$file" "" "."
+ dir="$func_dirname_result"
+ ;;
+
+ *)
+ func_warning "\`-dlopen' is ignored for non-libtool libraries and objects"
+ continue
+ ;;
+ esac
+
+ # Get the absolute pathname.
+ absdir=`cd "$dir" && pwd`
+ test -n "$absdir" && dir="$absdir"
+
+ # Now add the directory to shlibpath_var.
+ if eval "test -z \"\$$shlibpath_var\""; then
+ eval "$shlibpath_var=\"\$dir\""
+ else
+ eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\""
+ fi
+ done
+
+ # This variable tells wrapper scripts just to set shlibpath_var
+ # rather than running their programs.
+ libtool_execute_magic="$magic"
+
+ # Check if any of the arguments is a wrapper script.
+ args=
+ for file
+ do
+ case $file in
+ -*) ;;
+ *)
+ # Do a test to see if this is really a libtool program.
+ if func_ltwrapper_script_p "$file"; then
+ func_source "$file"
+ # Transform arg to wrapped name.
+ file="$progdir/$program"
+ elif func_ltwrapper_executable_p "$file"; then
+ func_ltwrapper_scriptname "$file"
+ func_source "$func_ltwrapper_scriptname_result"
+ # Transform arg to wrapped name.
+ file="$progdir/$program"
+ fi
+ ;;
+ esac
+ # Quote arguments (to preserve shell metacharacters).
+ func_quote_for_eval "$file"
+ args="$args $func_quote_for_eval_result"
+ done
+
+ if test "X$opt_dry_run" = Xfalse; then
+ if test -n "$shlibpath_var"; then
+ # Export the shlibpath_var.
+ eval "export $shlibpath_var"
+ fi
+
+ # Restore saved environment variables
+ for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES
+ do
+ eval "if test \"\${save_$lt_var+set}\" = set; then
+ $lt_var=\$save_$lt_var; export $lt_var
+ else
+ $lt_unset $lt_var
+ fi"
+ done
+
+ # Now prepare to actually exec the command.
+ exec_cmd="\$cmd$args"
+ else
+ # Display what would be done.
+ if test -n "$shlibpath_var"; then
+ eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\""
+ $ECHO "export $shlibpath_var"
+ fi
+ $ECHO "$cmd$args"
+ exit $EXIT_SUCCESS
+ fi
+}
+
+test "$mode" = execute && func_mode_execute ${1+"$@"}
+
+
+# func_mode_finish arg...
+func_mode_finish ()
+{
+ $opt_debug
+ libdirs="$nonopt"
+ admincmds=
+
+ if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then
+ for dir
+ do
+ libdirs="$libdirs $dir"
+ done
+
+ for libdir in $libdirs; do
+ if test -n "$finish_cmds"; then
+ # Do each command in the finish commands.
+ func_execute_cmds "$finish_cmds" 'admincmds="$admincmds
+'"$cmd"'"'
+ fi
+ if test -n "$finish_eval"; then
+ # Do the single finish_eval.
+ eval cmds=\"$finish_eval\"
+ $opt_dry_run || eval "$cmds" || admincmds="$admincmds
+ $cmds"
+ fi
+ done
+ fi
+
+ # Exit here if they wanted silent mode.
+ $opt_silent && exit $EXIT_SUCCESS
+
+ $ECHO "X----------------------------------------------------------------------" | $Xsed
+ $ECHO "Libraries have been installed in:"
+ for libdir in $libdirs; do
+ $ECHO " $libdir"
+ done
+ $ECHO
+ $ECHO "If you ever happen to want to link against installed libraries"
+ $ECHO "in a given directory, LIBDIR, you must either use libtool, and"
+ $ECHO "specify the full pathname of the library, or use the \`-LLIBDIR'"
+ $ECHO "flag during linking and do at least one of the following:"
+ if test -n "$shlibpath_var"; then
+ $ECHO " - add LIBDIR to the \`$shlibpath_var' environment variable"
+ $ECHO " during execution"
+ fi
+ if test -n "$runpath_var"; then
+ $ECHO " - add LIBDIR to the \`$runpath_var' environment variable"
+ $ECHO " during linking"
+ fi
+ if test -n "$hardcode_libdir_flag_spec"; then
+ libdir=LIBDIR
+ eval flag=\"$hardcode_libdir_flag_spec\"
+
+ $ECHO " - use the \`$flag' linker flag"
+ fi
+ if test -n "$admincmds"; then
+ $ECHO " - have your system administrator run these commands:$admincmds"
+ fi
+ if test -f /etc/ld.so.conf; then
+ $ECHO " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'"
+ fi
+ $ECHO
+
+ $ECHO "See any operating system documentation about shared libraries for"
+ case $host in
+ solaris2.[6789]|solaris2.1[0-9])
+ $ECHO "more information, such as the ld(1), crle(1) and ld.so(8) manual"
+ $ECHO "pages."
+ ;;
+ *)
+ $ECHO "more information, such as the ld(1) and ld.so(8) manual pages."
+ ;;
+ esac
+ $ECHO "X----------------------------------------------------------------------" | $Xsed
+ exit $EXIT_SUCCESS
+}
+
+test "$mode" = finish && func_mode_finish ${1+"$@"}
+
+
+# func_mode_install arg...
+func_mode_install ()
+{
+ $opt_debug
+ # There may be an optional sh(1) argument at the beginning of
+ # install_prog (especially on Windows NT).
+ if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh ||
+ # Allow the use of GNU shtool's install command.
+ $ECHO "X$nonopt" | $GREP shtool >/dev/null; then
+ # Aesthetically quote it.
+ func_quote_for_eval "$nonopt"
+ install_prog="$func_quote_for_eval_result "
+ arg=$1
+ shift
+ else
+ install_prog=
+ arg=$nonopt
+ fi
+
+ # The real first argument should be the name of the installation program.
+ # Aesthetically quote it.
+ func_quote_for_eval "$arg"
+ install_prog="$install_prog$func_quote_for_eval_result"
+
+ # We need to accept at least all the BSD install flags.
+ dest=
+ files=
+ opts=
+ prev=
+ install_type=
+ isdir=no
+ stripme=
+ for arg
+ do
+ if test -n "$dest"; then
+ files="$files $dest"
+ dest=$arg
+ continue
+ fi
+
+ case $arg in
+ -d) isdir=yes ;;
+ -f)
+ case " $install_prog " in
+ *[\\\ /]cp\ *) ;;
+ *) prev=$arg ;;
+ esac
+ ;;
+ -g | -m | -o)
+ prev=$arg
+ ;;
+ -s)
+ stripme=" -s"
+ continue
+ ;;
+ -*)
+ ;;
+ *)
+ # If the previous option needed an argument, then skip it.
+ if test -n "$prev"; then
+ prev=
+ else
+ dest=$arg
+ continue
+ fi
+ ;;
+ esac
+
+ # Aesthetically quote the argument.
+ func_quote_for_eval "$arg"
+ install_prog="$install_prog $func_quote_for_eval_result"
+ done
+
+ test -z "$install_prog" && \
+ func_fatal_help "you must specify an install program"
+
+ test -n "$prev" && \
+ func_fatal_help "the \`$prev' option requires an argument"
+
+ if test -z "$files"; then
+ if test -z "$dest"; then
+ func_fatal_help "no file or destination specified"
+ else
+ func_fatal_help "you must specify a destination"
+ fi
+ fi
+
+ # Strip any trailing slash from the destination.
+ func_stripname '' '/' "$dest"
+ dest=$func_stripname_result
+
+ # Check to see that the destination is a directory.
+ test -d "$dest" && isdir=yes
+ if test "$isdir" = yes; then
+ destdir="$dest"
+ destname=
+ else
+ func_dirname_and_basename "$dest" "" "."
+ destdir="$func_dirname_result"
+ destname="$func_basename_result"
+
+ # Not a directory, so check to see that there is only one file specified.
+ set dummy $files; shift
+ test "$#" -gt 1 && \
+ func_fatal_help "\`$dest' is not a directory"
+ fi
+ case $destdir in
+ [\\/]* | [A-Za-z]:[\\/]*) ;;
+ *)
+ for file in $files; do
+ case $file in
+ *.lo) ;;
+ *)
+ func_fatal_help "\`$destdir' must be an absolute directory name"
+ ;;
+ esac
+ done
+ ;;
+ esac
+
+ # This variable tells wrapper scripts just to set variables rather
+ # than running their programs.
+ libtool_install_magic="$magic"
+
+ staticlibs=
+ future_libdirs=
+ current_libdirs=
+ for file in $files; do
+
+ # Do each installation.
+ case $file in
+ *.$libext)
+ # Do the static libraries later.
+ staticlibs="$staticlibs $file"
+ ;;
+
+ *.la)
+ # Check to see that this really is a libtool archive.
+ func_lalib_unsafe_p "$file" \
+ || func_fatal_help "\`$file' is not a valid libtool archive"
+
+ library_names=
+ old_library=
+ relink_command=
+ func_source "$file"
+
+ # Add the libdir to current_libdirs if it is the destination.
+ if test "X$destdir" = "X$libdir"; then
+ case "$current_libdirs " in
+ *" $libdir "*) ;;
+ *) current_libdirs="$current_libdirs $libdir" ;;
+ esac
+ else
+ # Note the libdir as a future libdir.
+ case "$future_libdirs " in
+ *" $libdir "*) ;;
+ *) future_libdirs="$future_libdirs $libdir" ;;
+ esac
+ fi
+
+ func_dirname "$file" "/" ""
+ dir="$func_dirname_result"
+ dir="$dir$objdir"
+
+ if test -n "$relink_command"; then
+ # Determine the prefix the user has applied to our future dir.
+ inst_prefix_dir=`$ECHO "X$destdir" | $Xsed -e "s%$libdir\$%%"`
+
+ # Don't allow the user to place us outside of our expected
+ # location b/c this prevents finding dependent libraries that
+ # are installed to the same prefix.
+ # At present, this check doesn't affect windows .dll's that
+ # are installed into $libdir/../bin (currently, that works fine)
+ # but it's something to keep an eye on.
+ test "$inst_prefix_dir" = "$destdir" && \
+ func_fatal_error "error: cannot install \`$file' to a directory not ending in $libdir"
+
+ if test -n "$inst_prefix_dir"; then
+ # Stick the inst_prefix_dir data into the link command.
+ relink_command=`$ECHO "X$relink_command" | $Xsed -e "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"`
+ else
+ relink_command=`$ECHO "X$relink_command" | $Xsed -e "s%@inst_prefix_dir@%%"`
+ fi
+
+ func_warning "relinking \`$file'"
+ func_show_eval "$relink_command" \
+ 'func_fatal_error "error: relink \`$file'\'' with the above command before installing it"'
+ fi
+
+ # See the names of the shared library.
+ set dummy $library_names; shift
+ if test -n "$1"; then
+ realname="$1"
+ shift
+
+ srcname="$realname"
+ test -n "$relink_command" && srcname="$realname"T
+
+ # Install the shared library and build the symlinks.
+ func_show_eval "$install_prog $dir/$srcname $destdir/$realname" \
+ 'exit $?'
+ tstripme="$stripme"
+ case $host_os in
+ cygwin* | mingw* | pw32* | cegcc*)
+ case $realname in
+ *.dll.a)
+ tstripme=""
+ ;;
+ esac
+ ;;
+ esac
+ if test -n "$tstripme" && test -n "$striplib"; then
+ func_show_eval "$striplib $destdir/$realname" 'exit $?'
+ fi
+
+ if test "$#" -gt 0; then
+ # Delete the old symlinks, and create new ones.
+ # Try `ln -sf' first, because the `ln' binary might depend on
+ # the symlink we replace! Solaris /bin/ln does not understand -f,
+ # so we also need to try rm && ln -s.
+ for linkname
+ do
+ test "$linkname" != "$realname" \
+ && func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })"
+ done
+ fi
+
+ # Do each command in the postinstall commands.
+ lib="$destdir/$realname"
+ func_execute_cmds "$postinstall_cmds" 'exit $?'
+ fi
+
+ # Install the pseudo-library for information purposes.
+ func_basename "$file"
+ name="$func_basename_result"
+ instname="$dir/$name"i
+ func_show_eval "$install_prog $instname $destdir/$name" 'exit $?'
+
+ # Maybe install the static library, too.
+ test -n "$old_library" && staticlibs="$staticlibs $dir/$old_library"
+ ;;
+
+ *.lo)
+ # Install (i.e. copy) a libtool object.
+
+ # Figure out destination file name, if it wasn't already specified.
+ if test -n "$destname"; then
+ destfile="$destdir/$destname"
+ else
+ func_basename "$file"
+ destfile="$func_basename_result"
+ destfile="$destdir/$destfile"
+ fi
+
+ # Deduce the name of the destination old-style object file.
+ case $destfile in
+ *.lo)
+ func_lo2o "$destfile"
+ staticdest=$func_lo2o_result
+ ;;
+ *.$objext)
+ staticdest="$destfile"
+ destfile=
+ ;;
+ *)
+ func_fatal_help "cannot copy a libtool object to \`$destfile'"
+ ;;
+ esac
+
+ # Install the libtool object if requested.
+ test -n "$destfile" && \
+ func_show_eval "$install_prog $file $destfile" 'exit $?'
+
+ # Install the old object if enabled.
+ if test "$build_old_libs" = yes; then
+ # Deduce the name of the old-style object file.
+ func_lo2o "$file"
+ staticobj=$func_lo2o_result
+ func_show_eval "$install_prog \$staticobj \$staticdest" 'exit $?'
+ fi
+ exit $EXIT_SUCCESS
+ ;;
+
+ *)
+ # Figure out destination file name, if it wasn't already specified.
+ if test -n "$destname"; then
+ destfile="$destdir/$destname"
+ else
+ func_basename "$file"
+ destfile="$func_basename_result"
+ destfile="$destdir/$destfile"
+ fi
+
+ # If the file is missing, and there is a .exe on the end, strip it
+ # because it is most likely a libtool script we actually want to
+ # install
+ stripped_ext=""
+ case $file in
+ *.exe)
+ if test ! -f "$file"; then
+ func_stripname '' '.exe' "$file"
+ file=$func_stripname_result
+ stripped_ext=".exe"
+ fi
+ ;;
+ esac
+
+ # Do a test to see if this is really a libtool program.
+ case $host in
+ *cygwin* | *mingw*)
+ if func_ltwrapper_executable_p "$file"; then
+ func_ltwrapper_scriptname "$file"
+ wrapper=$func_ltwrapper_scriptname_result
+ else
+ func_stripname '' '.exe' "$file"
+ wrapper=$func_stripname_result
+ fi
+ ;;
+ *)
+ wrapper=$file
+ ;;
+ esac
+ if func_ltwrapper_script_p "$wrapper"; then
+ notinst_deplibs=
+ relink_command=
+
+ func_source "$wrapper"
+
+ # Check the variables that should have been set.
+ test -z "$generated_by_libtool_version" && \
+ func_fatal_error "invalid libtool wrapper script \`$wrapper'"
+
+ finalize=yes
+ for lib in $notinst_deplibs; do
+ # Check to see that each library is installed.
+ libdir=
+ if test -f "$lib"; then
+ func_source "$lib"
+ fi
+ libfile="$libdir/"`$ECHO "X$lib" | $Xsed -e 's%^.*/%%g'` ### testsuite: skip nested quoting test
+ if test -n "$libdir" && test ! -f "$libfile"; then
+ func_warning "\`$lib' has not been installed in \`$libdir'"
+ finalize=no
+ fi
+ done
+
+ relink_command=
+ func_source "$wrapper"
+
+ outputname=
+ if test "$fast_install" = no && test -n "$relink_command"; then
+ $opt_dry_run || {
+ if test "$finalize" = yes; then
+ tmpdir=`func_mktempdir`
+ func_basename "$file$stripped_ext"
+ file="$func_basename_result"
+ outputname="$tmpdir/$file"
+ # Replace the output file specification.
+ relink_command=`$ECHO "X$relink_command" | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g'`
+
+ $opt_silent || {
+ func_quote_for_expand "$relink_command"
+ eval "func_echo $func_quote_for_expand_result"
+ }
+ if eval "$relink_command"; then :
+ else
+ func_error "error: relink \`$file' with the above command before installing it"
+ $opt_dry_run || ${RM}r "$tmpdir"
+ continue
+ fi
+ file="$outputname"
+ else
+ func_warning "cannot relink \`$file'"
+ fi
+ }
+ else
+ # Install the binary that we compiled earlier.
+ file=`$ECHO "X$file$stripped_ext" | $Xsed -e "s%\([^/]*\)$%$objdir/\1%"`
+ fi
+ fi
+
+ # remove .exe since cygwin /usr/bin/install will append another
+ # one anyway
+ case $install_prog,$host in
+ */usr/bin/install*,*cygwin*)
+ case $file:$destfile in
+ *.exe:*.exe)
+ # this is ok
+ ;;
+ *.exe:*)
+ destfile=$destfile.exe
+ ;;
+ *:*.exe)
+ func_stripname '' '.exe' "$destfile"
+ destfile=$func_stripname_result
+ ;;
+ esac
+ ;;
+ esac
+ func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?'
+ $opt_dry_run || if test -n "$outputname"; then
+ ${RM}r "$tmpdir"
+ fi
+ ;;
+ esac
+ done
+
+ for file in $staticlibs; do
+ func_basename "$file"
+ name="$func_basename_result"
+
+ # Set up the ranlib parameters.
+ oldlib="$destdir/$name"
+
+ func_show_eval "$install_prog \$file \$oldlib" 'exit $?'
+
+ if test -n "$stripme" && test -n "$old_striplib"; then
+ func_show_eval "$old_striplib $oldlib" 'exit $?'
+ fi
+
+ # Do each command in the postinstall commands.
+ func_execute_cmds "$old_postinstall_cmds" 'exit $?'
+ done
+
+ test -n "$future_libdirs" && \
+ func_warning "remember to run \`$progname --finish$future_libdirs'"
+
+ if test -n "$current_libdirs"; then
+ # Maybe just do a dry run.
+ $opt_dry_run && current_libdirs=" -n$current_libdirs"
+ exec_cmd='$SHELL $progpath $preserve_args --finish$current_libdirs'
+ else
+ exit $EXIT_SUCCESS
+ fi
+}
+
+test "$mode" = install && func_mode_install ${1+"$@"}
+
+
+# func_generate_dlsyms outputname originator pic_p
+# Extract symbols from dlprefiles and create ${outputname}S.o with
+# a dlpreopen symbol table.
+func_generate_dlsyms ()
+{
+ $opt_debug
+ my_outputname="$1"
+ my_originator="$2"
+ my_pic_p="${3-no}"
+ my_prefix=`$ECHO "$my_originator" | sed 's%[^a-zA-Z0-9]%_%g'`
+ my_dlsyms=
+
+ if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
+ if test -n "$NM" && test -n "$global_symbol_pipe"; then
+ my_dlsyms="${my_outputname}S.c"
+ else
+ func_error "not configured to extract global symbols from dlpreopened files"
+ fi
+ fi
+
+ if test -n "$my_dlsyms"; then
+ case $my_dlsyms in
+ "") ;;
+ *.c)
+ # Discover the nlist of each of the dlfiles.
+ nlist="$output_objdir/${my_outputname}.nm"
+
+ func_show_eval "$RM $nlist ${nlist}S ${nlist}T"
+
+ # Parse the name list into a source file.
+ func_verbose "creating $output_objdir/$my_dlsyms"
+
+ $opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\
+/* $my_dlsyms - symbol resolution table for \`$my_outputname' dlsym emulation. */
+/* Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION */
+
+#ifdef __cplusplus
+extern \"C\" {
+#endif
+
+/* External symbol declarations for the compiler. */\
+"
+
+ if test "$dlself" = yes; then
+ func_verbose "generating symbol list for \`$output'"
+
+ $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist"
+
+ # Add our own program objects to the symbol list.
+ progfiles=`$ECHO "X$objs$old_deplibs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+ for progfile in $progfiles; do
+ func_verbose "extracting global C symbols from \`$progfile'"
+ $opt_dry_run || eval "$NM $progfile | $global_symbol_pipe >> '$nlist'"
+ done
+
+ if test -n "$exclude_expsyms"; then
+ $opt_dry_run || {
+ eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T'
+ eval '$MV "$nlist"T "$nlist"'
+ }
+ fi
+
+ if test -n "$export_symbols_regex"; then
+ $opt_dry_run || {
+ eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T'
+ eval '$MV "$nlist"T "$nlist"'
+ }
+ fi
+
+ # Prepare the list of exported symbols
+ if test -z "$export_symbols"; then
+ export_symbols="$output_objdir/$outputname.exp"
+ $opt_dry_run || {
+ $RM $export_symbols
+ eval "${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"'
+ case $host in
+ *cygwin* | *mingw* | *cegcc* )
+ eval "echo EXPORTS "'> "$output_objdir/$outputname.def"'
+ eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"'
+ ;;
+ esac
+ }
+ else
+ $opt_dry_run || {
+ eval "${SED} -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"'
+ eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T'
+ eval '$MV "$nlist"T "$nlist"'
+ case $host in
+ *cygwin | *mingw* | *cegcc* )
+ eval "echo EXPORTS "'> "$output_objdir/$outputname.def"'
+ eval 'cat "$nlist" >> "$output_objdir/$outputname.def"'
+ ;;
+ esac
+ }
+ fi
+ fi
+
+ for dlprefile in $dlprefiles; do
+ func_verbose "extracting global C symbols from \`$dlprefile'"
+ func_basename "$dlprefile"
+ name="$func_basename_result"
+ $opt_dry_run || {
+ eval '$ECHO ": $name " >> "$nlist"'
+ eval "$NM $dlprefile 2>/dev/null | $global_symbol_pipe >> '$nlist'"
+ }
+ done
+
+ $opt_dry_run || {
+ # Make sure we have at least an empty file.
+ test -f "$nlist" || : > "$nlist"
+
+ if test -n "$exclude_expsyms"; then
+ $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T
+ $MV "$nlist"T "$nlist"
+ fi
+
+ # Try sorting and uniquifying the output.
+ if $GREP -v "^: " < "$nlist" |
+ if sort -k 3 </dev/null >/dev/null 2>&1; then
+ sort -k 3
+ else
+ sort +2
+ fi |
+ uniq > "$nlist"S; then
+ :
+ else
+ $GREP -v "^: " < "$nlist" > "$nlist"S
+ fi
+
+ if test -f "$nlist"S; then
+ eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"'
+ else
+ $ECHO '/* NONE */' >> "$output_objdir/$my_dlsyms"
+ fi
+
+ $ECHO >> "$output_objdir/$my_dlsyms" "\
+
+/* The mapping between symbol names and symbols. */
+typedef struct {
+ const char *name;
+ void *address;
+} lt_dlsymlist;
+"
+ case $host in
+ *cygwin* | *mingw* | *cegcc* )
+ $ECHO >> "$output_objdir/$my_dlsyms" "\
+/* DATA imports from DLLs on WIN32 con't be const, because
+ runtime relocations are performed -- see ld's documentation
+ on pseudo-relocs. */"
+ lt_dlsym_const= ;;
+ *osf5*)
+ echo >> "$output_objdir/$my_dlsyms" "\
+/* This system does not cope well with relocations in const data */"
+ lt_dlsym_const= ;;
+ *)
+ lt_dlsym_const=const ;;
+ esac
+
+ $ECHO >> "$output_objdir/$my_dlsyms" "\
+extern $lt_dlsym_const lt_dlsymlist
+lt_${my_prefix}_LTX_preloaded_symbols[];
+$lt_dlsym_const lt_dlsymlist
+lt_${my_prefix}_LTX_preloaded_symbols[] =
+{\
+ { \"$my_originator\", (void *) 0 },"
+
+ case $need_lib_prefix in
+ no)
+ eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms"
+ ;;
+ *)
+ eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms"
+ ;;
+ esac
+ $ECHO >> "$output_objdir/$my_dlsyms" "\
+ {0, (void *) 0}
+};
+
+/* This works around a problem in FreeBSD linker */
+#ifdef FREEBSD_WORKAROUND
+static const void *lt_preloaded_setup() {
+ return lt_${my_prefix}_LTX_preloaded_symbols;
+}
+#endif
+
+#ifdef __cplusplus
+}
+#endif\
+"
+ } # !$opt_dry_run
+
+ pic_flag_for_symtable=
+ case "$compile_command " in
+ *" -static "*) ;;
+ *)
+ case $host in
+ # compiling the symbol table file with pic_flag works around
+ # a FreeBSD bug that causes programs to crash when -lm is
+ # linked before any other PIC object. But we must not use
+ # pic_flag when linking with -static. The problem exists in
+ # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1.
+ *-*-freebsd2*|*-*-freebsd3.0*|*-*-freebsdelf3.0*)
+ pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;;
+ *-*-hpux*)
+ pic_flag_for_symtable=" $pic_flag" ;;
+ *)
+ if test "X$my_pic_p" != Xno; then
+ pic_flag_for_symtable=" $pic_flag"
+ fi
+ ;;
+ esac
+ ;;
+ esac
+ symtab_cflags=
+ for arg in $LTCFLAGS; do
+ case $arg in
+ -pie | -fpie | -fPIE) ;;
+ *) symtab_cflags="$symtab_cflags $arg" ;;
+ esac
+ done
+
+ # Now compile the dynamic symbol file.
+ func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?'
+
+ # Clean up the generated files.
+ func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T"'
+
+ # Transform the symbol file into the correct name.
+ symfileobj="$output_objdir/${my_outputname}S.$objext"
+ case $host in
+ *cygwin* | *mingw* | *cegcc* )
+ if test -f "$output_objdir/$my_outputname.def"; then
+ compile_command=`$ECHO "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"`
+ finalize_command=`$ECHO "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"`
+ else
+ compile_command=`$ECHO "X$compile_command" | $Xsed -e "s%@SYMFILE@%$symfileobj%"`
+ finalize_command=`$ECHO "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$symfileobj%"`
+ fi
+ ;;
+ *)
+ compile_command=`$ECHO "X$compile_command" | $Xsed -e "s%@SYMFILE@%$symfileobj%"`
+ finalize_command=`$ECHO "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$symfileobj%"`
+ ;;
+ esac
+ ;;
+ *)
+ func_fatal_error "unknown suffix for \`$my_dlsyms'"
+ ;;
+ esac
+ else
+ # We keep going just in case the user didn't refer to
+ # lt_preloaded_symbols. The linker will fail if global_symbol_pipe
+ # really was required.
+
+ # Nullify the symbol file.
+ compile_command=`$ECHO "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"`
+ finalize_command=`$ECHO "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"`
+ fi
+}
+
+# func_win32_libid arg
+# return the library type of file 'arg'
+#
+# Need a lot of goo to handle *both* DLLs and import libs
+# Has to be a shell function in order to 'eat' the argument
+# that is supplied when $file_magic_command is called.
+func_win32_libid ()
+{
+ $opt_debug
+ win32_libid_type="unknown"
+ win32_fileres=`file -L $1 2>/dev/null`
+ case $win32_fileres in
+ *ar\ archive\ import\ library*) # definitely import
+ win32_libid_type="x86 archive import"
+ ;;
+ *ar\ archive*) # could be an import, or static
+ if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null |
+ $EGREP 'file format pe-i386(.*architecture: i386)?' >/dev/null ; then
+ win32_nmres=`eval $NM -f posix -A $1 |
+ $SED -n -e '
+ 1,100{
+ / I /{
+ s,.*,import,
+ p
+ q
+ }
+ }'`
+ case $win32_nmres in
+ import*) win32_libid_type="x86 archive import";;
+ *) win32_libid_type="x86 archive static";;
+ esac
+ fi
+ ;;
+ *DLL*)
+ win32_libid_type="x86 DLL"
+ ;;
+ *executable*) # but shell scripts are "executable" too...
+ case $win32_fileres in
+ *MS\ Windows\ PE\ Intel*)
+ win32_libid_type="x86 DLL"
+ ;;
+ esac
+ ;;
+ esac
+ $ECHO "$win32_libid_type"
+}
+
+
+
+# func_extract_an_archive dir oldlib
+func_extract_an_archive ()
+{
+ $opt_debug
+ f_ex_an_ar_dir="$1"; shift
+ f_ex_an_ar_oldlib="$1"
+ func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" 'exit $?'
+ if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then
+ :
+ else
+ func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib"
+ fi
+}
+
+
+# func_extract_archives gentop oldlib ...
+func_extract_archives ()
+{
+ $opt_debug
+ my_gentop="$1"; shift
+ my_oldlibs=${1+"$@"}
+ my_oldobjs=""
+ my_xlib=""
+ my_xabs=""
+ my_xdir=""
+
+ for my_xlib in $my_oldlibs; do
+ # Extract the objects.
+ case $my_xlib in
+ [\\/]* | [A-Za-z]:[\\/]*) my_xabs="$my_xlib" ;;
+ *) my_xabs=`pwd`"/$my_xlib" ;;
+ esac
+ func_basename "$my_xlib"
+ my_xlib="$func_basename_result"
+ my_xlib_u=$my_xlib
+ while :; do
+ case " $extracted_archives " in
+ *" $my_xlib_u "*)
+ func_arith $extracted_serial + 1
+ extracted_serial=$func_arith_result
+ my_xlib_u=lt$extracted_serial-$my_xlib ;;
+ *) break ;;
+ esac
+ done
+ extracted_archives="$extracted_archives $my_xlib_u"
+ my_xdir="$my_gentop/$my_xlib_u"
+
+ func_mkdir_p "$my_xdir"
+
+ case $host in
+ *-darwin*)
+ func_verbose "Extracting $my_xabs"
+ # Do not bother doing anything if just a dry run
+ $opt_dry_run || {
+ darwin_orig_dir=`pwd`
+ cd $my_xdir || exit $?
+ darwin_archive=$my_xabs
+ darwin_curdir=`pwd`
+ darwin_base_archive=`basename "$darwin_archive"`
+ darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true`
+ if test -n "$darwin_arches"; then
+ darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'`
+ darwin_arch=
+ func_verbose "$darwin_base_archive has multiple architectures $darwin_arches"
+ for darwin_arch in $darwin_arches ; do
+ func_mkdir_p "unfat-$$/${darwin_base_archive}-${darwin_arch}"
+ $LIPO -thin $darwin_arch -output "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" "${darwin_archive}"
+ cd "unfat-$$/${darwin_base_archive}-${darwin_arch}"
+ func_extract_an_archive "`pwd`" "${darwin_base_archive}"
+ cd "$darwin_curdir"
+ $RM "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}"
+ done # $darwin_arches
+ ## Okay now we've a bunch of thin objects, gotta fatten them up :)
+ darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$basename" | sort -u`
+ darwin_file=
+ darwin_files=
+ for darwin_file in $darwin_filelist; do
+ darwin_files=`find unfat-$$ -name $darwin_file -print | $NL2SP`
+ $LIPO -create -output "$darwin_file" $darwin_files
+ done # $darwin_filelist
+ $RM -rf unfat-$$
+ cd "$darwin_orig_dir"
+ else
+ cd $darwin_orig_dir
+ func_extract_an_archive "$my_xdir" "$my_xabs"
+ fi # $darwin_arches
+ } # !$opt_dry_run
+ ;;
+ *)
+ func_extract_an_archive "$my_xdir" "$my_xabs"
+ ;;
+ esac
+ my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | $NL2SP`
+ done
+
+ func_extract_archives_result="$my_oldobjs"
+}
+
+
+
+# func_emit_wrapper_part1 [arg=no]
+#
+# Emit the first part of a libtool wrapper script on stdout.
+# For more information, see the description associated with
+# func_emit_wrapper(), below.
+func_emit_wrapper_part1 ()
+{
+ func_emit_wrapper_part1_arg1=no
+ if test -n "$1" ; then
+ func_emit_wrapper_part1_arg1=$1
+ fi
+
+ $ECHO "\
+#! $SHELL
+
+# $output - temporary wrapper script for $objdir/$outputname
+# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION
+#
+# The $output program cannot be directly executed until all the libtool
+# libraries that it depends on are installed.
+#
+# This wrapper script should never be moved out of the build directory.
+# If it is, it will not operate correctly.
+
+# Sed substitution that helps us do robust quoting. It backslashifies
+# metacharacters that are still active within double-quoted strings.
+Xsed='${SED} -e 1s/^X//'
+sed_quote_subst='$sed_quote_subst'
+
+# Be Bourne compatible
+if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '\${1+\"\$@\"}'='\"\$@\"'
+ setopt NO_GLOB_SUBST
+else
+ case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac
+fi
+BIN_SH=xpg4; export BIN_SH # for Tru64
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+relink_command=\"$relink_command\"
+
+# This environment variable determines our operation mode.
+if test \"\$libtool_install_magic\" = \"$magic\"; then
+ # install mode needs the following variables:
+ generated_by_libtool_version='$macro_version'
+ notinst_deplibs='$notinst_deplibs'
+else
+ # When we are sourced in execute mode, \$file and \$ECHO are already set.
+ if test \"\$libtool_execute_magic\" != \"$magic\"; then
+ ECHO=\"$qecho\"
+ file=\"\$0\"
+ # Make sure echo works.
+ if test \"X\$1\" = X--no-reexec; then
+ # Discard the --no-reexec flag, and continue.
+ shift
+ elif test \"X\`{ \$ECHO '\t'; } 2>/dev/null\`\" = 'X\t'; then
+ # Yippee, \$ECHO works!
+ :
+ else
+ # Restart under the correct shell, and then maybe \$ECHO will work.
+ exec $SHELL \"\$0\" --no-reexec \${1+\"\$@\"}
+ fi
+ fi\
+"
+ $ECHO "\
+
+ # Find the directory that this script lives in.
+ thisdir=\`\$ECHO \"X\$file\" | \$Xsed -e 's%/[^/]*$%%'\`
+ test \"x\$thisdir\" = \"x\$file\" && thisdir=.
+
+ # Follow symbolic links until we get to the real thisdir.
+ file=\`ls -ld \"\$file\" | ${SED} -n 's/.*-> //p'\`
+ while test -n \"\$file\"; do
+ destdir=\`\$ECHO \"X\$file\" | \$Xsed -e 's%/[^/]*\$%%'\`
+
+ # If there was a directory component, then change thisdir.
+ if test \"x\$destdir\" != \"x\$file\"; then
+ case \"\$destdir\" in
+ [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;;
+ *) thisdir=\"\$thisdir/\$destdir\" ;;
+ esac
+ fi
+
+ file=\`\$ECHO \"X\$file\" | \$Xsed -e 's%^.*/%%'\`
+ file=\`ls -ld \"\$thisdir/\$file\" | ${SED} -n 's/.*-> //p'\`
+ done
+"
+}
+# end: func_emit_wrapper_part1
+
+# func_emit_wrapper_part2 [arg=no]
+#
+# Emit the second part of a libtool wrapper script on stdout.
+# For more information, see the description associated with
+# func_emit_wrapper(), below.
+func_emit_wrapper_part2 ()
+{
+ func_emit_wrapper_part2_arg1=no
+ if test -n "$1" ; then
+ func_emit_wrapper_part2_arg1=$1
+ fi
+
+ $ECHO "\
+
+ # Usually 'no', except on cygwin/mingw when embedded into
+ # the cwrapper.
+ WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_part2_arg1
+ if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then
+ # special case for '.'
+ if test \"\$thisdir\" = \".\"; then
+ thisdir=\`pwd\`
+ fi
+ # remove .libs from thisdir
+ case \"\$thisdir\" in
+ *[\\\\/]$objdir ) thisdir=\`\$ECHO \"X\$thisdir\" | \$Xsed -e 's%[\\\\/][^\\\\/]*$%%'\` ;;
+ $objdir ) thisdir=. ;;
+ esac
+ fi
+
+ # Try to get the absolute directory name.
+ absdir=\`cd \"\$thisdir\" && pwd\`
+ test -n \"\$absdir\" && thisdir=\"\$absdir\"
+"
+
+ if test "$fast_install" = yes; then
+ $ECHO "\
+ program=lt-'$outputname'$exeext
+ progdir=\"\$thisdir/$objdir\"
+
+ if test ! -f \"\$progdir/\$program\" ||
+ { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\
+ test \"X\$file\" != \"X\$progdir/\$program\"; }; then
+
+ file=\"\$\$-\$program\"
+
+ if test ! -d \"\$progdir\"; then
+ $MKDIR \"\$progdir\"
+ else
+ $RM \"\$progdir/\$file\"
+ fi"
+
+ $ECHO "\
+
+ # relink executable if necessary
+ if test -n \"\$relink_command\"; then
+ if relink_command_output=\`eval \$relink_command 2>&1\`; then :
+ else
+ $ECHO \"\$relink_command_output\" >&2
+ $RM \"\$progdir/\$file\"
+ exit 1
+ fi
+ fi
+
+ $MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null ||
+ { $RM \"\$progdir/\$program\";
+ $MV \"\$progdir/\$file\" \"\$progdir/\$program\"; }
+ $RM \"\$progdir/\$file\"
+ fi"
+ else
+ $ECHO "\
+ program='$outputname'
+ progdir=\"\$thisdir/$objdir\"
+"
+ fi
+
+ $ECHO "\
+
+ if test -f \"\$progdir/\$program\"; then"
+
+ # Export our shlibpath_var if we have one.
+ if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then
+ $ECHO "\
+ # Add our own library path to $shlibpath_var
+ $shlibpath_var=\"$temp_rpath\$$shlibpath_var\"
+
+ # Some systems cannot cope with colon-terminated $shlibpath_var
+ # The second colon is a workaround for a bug in BeOS R4 sed
+ $shlibpath_var=\`\$ECHO \"X\$$shlibpath_var\" | \$Xsed -e 's/::*\$//'\`
+
+ export $shlibpath_var
+"
+ fi
+
+ # fixup the dll searchpath if we need to.
+ if test -n "$dllsearchpath"; then
+ $ECHO "\
+ # Add the dll search path components to the executable PATH
+ PATH=$dllsearchpath:\$PATH
+"
+ fi
+
+ $ECHO "\
+ if test \"\$libtool_execute_magic\" != \"$magic\"; then
+ # Run the actual program with our arguments.
+"
+ case $host in
+ # Backslashes separate directories on plain windows
+ *-*-mingw | *-*-os2* | *-cegcc*)
+ $ECHO "\
+ exec \"\$progdir\\\\\$program\" \${1+\"\$@\"}
+"
+ ;;
+
+ *)
+ $ECHO "\
+ exec \"\$progdir/\$program\" \${1+\"\$@\"}
+"
+ ;;
+ esac
+ $ECHO "\
+ \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2
+ exit 1
+ fi
+ else
+ # The program doesn't exist.
+ \$ECHO \"\$0: error: \\\`\$progdir/\$program' does not exist\" 1>&2
+ \$ECHO \"This script is just a wrapper for \$program.\" 1>&2
+ $ECHO \"See the $PACKAGE documentation for more information.\" 1>&2
+ exit 1
+ fi
+fi\
+"
+}
+# end: func_emit_wrapper_part2
+
+
+# func_emit_wrapper [arg=no]
+#
+# Emit a libtool wrapper script on stdout.
+# Don't directly open a file because we may want to
+# incorporate the script contents within a cygwin/mingw
+# wrapper executable. Must ONLY be called from within
+# func_mode_link because it depends on a number of variables
+# set therein.
+#
+# ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR
+# variable will take. If 'yes', then the emitted script
+# will assume that the directory in which it is stored is
+# the $objdir directory. This is a cygwin/mingw-specific
+# behavior.
+func_emit_wrapper ()
+{
+ func_emit_wrapper_arg1=no
+ if test -n "$1" ; then
+ func_emit_wrapper_arg1=$1
+ fi
+
+ # split this up so that func_emit_cwrapperexe_src
+ # can call each part independently.
+ func_emit_wrapper_part1 "${func_emit_wrapper_arg1}"
+ func_emit_wrapper_part2 "${func_emit_wrapper_arg1}"
+}
+
+
+# func_to_host_path arg
+#
+# Convert paths to host format when used with build tools.
+# Intended for use with "native" mingw (where libtool itself
+# is running under the msys shell), or in the following cross-
+# build environments:
+# $build $host
+# mingw (msys) mingw [e.g. native]
+# cygwin mingw
+# *nix + wine mingw
+# where wine is equipped with the `winepath' executable.
+# In the native mingw case, the (msys) shell automatically
+# converts paths for any non-msys applications it launches,
+# but that facility isn't available from inside the cwrapper.
+# Similar accommodations are necessary for $host mingw and
+# $build cygwin. Calling this function does no harm for other
+# $host/$build combinations not listed above.
+#
+# ARG is the path (on $build) that should be converted to
+# the proper representation for $host. The result is stored
+# in $func_to_host_path_result.
+func_to_host_path ()
+{
+ func_to_host_path_result="$1"
+ if test -n "$1" ; then
+ case $host in
+ *mingw* )
+ lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g'
+ case $build in
+ *mingw* ) # actually, msys
+ # awkward: cmd appends spaces to result
+ lt_sed_strip_trailing_spaces="s/[ ]*\$//"
+ func_to_host_path_tmp1=`( cmd //c echo "$1" |\
+ $SED -e "$lt_sed_strip_trailing_spaces" ) 2>/dev/null || echo ""`
+ func_to_host_path_result=`echo "$func_to_host_path_tmp1" |\
+ $SED -e "$lt_sed_naive_backslashify"`
+ ;;
+ *cygwin* )
+ func_to_host_path_tmp1=`cygpath -w "$1"`
+ func_to_host_path_result=`echo "$func_to_host_path_tmp1" |\
+ $SED -e "$lt_sed_naive_backslashify"`
+ ;;
+ * )
+ # Unfortunately, winepath does not exit with a non-zero
+ # error code, so we are forced to check the contents of
+ # stdout. On the other hand, if the command is not
+ # found, the shell will set an exit code of 127 and print
+ # *an error message* to stdout. So we must check for both
+ # error code of zero AND non-empty stdout, which explains
+ # the odd construction:
+ func_to_host_path_tmp1=`winepath -w "$1" 2>/dev/null`
+ if test "$?" -eq 0 && test -n "${func_to_host_path_tmp1}"; then
+ func_to_host_path_result=`echo "$func_to_host_path_tmp1" |\
+ $SED -e "$lt_sed_naive_backslashify"`
+ else
+ # Allow warning below.
+ func_to_host_path_result=""
+ fi
+ ;;
+ esac
+ if test -z "$func_to_host_path_result" ; then
+ func_error "Could not determine host path corresponding to"
+ func_error " '$1'"
+ func_error "Continuing, but uninstalled executables may not work."
+ # Fallback:
+ func_to_host_path_result="$1"
+ fi
+ ;;
+ esac
+ fi
+}
+# end: func_to_host_path
+
+# func_to_host_pathlist arg
+#
+# Convert pathlists to host format when used with build tools.
+# See func_to_host_path(), above. This function supports the
+# following $build/$host combinations (but does no harm for
+# combinations not listed here):
+# $build $host
+# mingw (msys) mingw [e.g. native]
+# cygwin mingw
+# *nix + wine mingw
+#
+# Path separators are also converted from $build format to
+# $host format. If ARG begins or ends with a path separator
+# character, it is preserved (but converted to $host format)
+# on output.
+#
+# ARG is a pathlist (on $build) that should be converted to
+# the proper representation on $host. The result is stored
+# in $func_to_host_pathlist_result.
+func_to_host_pathlist ()
+{
+ func_to_host_pathlist_result="$1"
+ if test -n "$1" ; then
+ case $host in
+ *mingw* )
+ lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g'
+ # Remove leading and trailing path separator characters from
+ # ARG. msys behavior is inconsistent here, cygpath turns them
+ # into '.;' and ';.', and winepath ignores them completely.
+ func_to_host_pathlist_tmp2="$1"
+ # Once set for this call, this variable should not be
+ # reassigned. It is used in tha fallback case.
+ func_to_host_pathlist_tmp1=`echo "$func_to_host_pathlist_tmp2" |\
+ $SED -e 's|^:*||' -e 's|:*$||'`
+ case $build in
+ *mingw* ) # Actually, msys.
+ # Awkward: cmd appends spaces to result.
+ lt_sed_strip_trailing_spaces="s/[ ]*\$//"
+ func_to_host_pathlist_tmp2=`( cmd //c echo "$func_to_host_pathlist_tmp1" |\
+ $SED -e "$lt_sed_strip_trailing_spaces" ) 2>/dev/null || echo ""`
+ func_to_host_pathlist_result=`echo "$func_to_host_pathlist_tmp2" |\
+ $SED -e "$lt_sed_naive_backslashify"`
+ ;;
+ *cygwin* )
+ func_to_host_pathlist_tmp2=`cygpath -w -p "$func_to_host_pathlist_tmp1"`
+ func_to_host_pathlist_result=`echo "$func_to_host_pathlist_tmp2" |\
+ $SED -e "$lt_sed_naive_backslashify"`
+ ;;
+ * )
+ # unfortunately, winepath doesn't convert pathlists
+ func_to_host_pathlist_result=""
+ func_to_host_pathlist_oldIFS=$IFS
+ IFS=:
+ for func_to_host_pathlist_f in $func_to_host_pathlist_tmp1 ; do
+ IFS=$func_to_host_pathlist_oldIFS
+ if test -n "$func_to_host_pathlist_f" ; then
+ func_to_host_path "$func_to_host_pathlist_f"
+ if test -n "$func_to_host_path_result" ; then
+ if test -z "$func_to_host_pathlist_result" ; then
+ func_to_host_pathlist_result="$func_to_host_path_result"
+ else
+ func_to_host_pathlist_result="$func_to_host_pathlist_result;$func_to_host_path_result"
+ fi
+ fi
+ fi
+ IFS=:
+ done
+ IFS=$func_to_host_pathlist_oldIFS
+ ;;
+ esac
+ if test -z "$func_to_host_pathlist_result" ; then
+ func_error "Could not determine the host path(s) corresponding to"
+ func_error " '$1'"
+ func_error "Continuing, but uninstalled executables may not work."
+ # Fallback. This may break if $1 contains DOS-style drive
+ # specifications. The fix is not to complicate the expression
+ # below, but for the user to provide a working wine installation
+ # with winepath so that path translation in the cross-to-mingw
+ # case works properly.
+ lt_replace_pathsep_nix_to_dos="s|:|;|g"
+ func_to_host_pathlist_result=`echo "$func_to_host_pathlist_tmp1" |\
+ $SED -e "$lt_replace_pathsep_nix_to_dos"`
+ fi
+ # Now, add the leading and trailing path separators back
+ case "$1" in
+ :* ) func_to_host_pathlist_result=";$func_to_host_pathlist_result"
+ ;;
+ esac
+ case "$1" in
+ *: ) func_to_host_pathlist_result="$func_to_host_pathlist_result;"
+ ;;
+ esac
+ ;;
+ esac
+ fi
+}
+# end: func_to_host_pathlist
+
+# func_emit_cwrapperexe_src
+# emit the source code for a wrapper executable on stdout
+# Must ONLY be called from within func_mode_link because
+# it depends on a number of variable set therein.
+func_emit_cwrapperexe_src ()
+{
+ cat <<EOF
+
+/* $cwrappersource - temporary wrapper executable for $objdir/$outputname
+ Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION
+
+ The $output program cannot be directly executed until all the libtool
+ libraries that it depends on are installed.
+
+ This wrapper executable should never be moved out of the build directory.
+ If it is, it will not operate correctly.
+
+ Currently, it simply execs the wrapper *script* "$SHELL $output",
+ but could eventually absorb all of the scripts functionality and
+ exec $objdir/$outputname directly.
+*/
+EOF
+ cat <<"EOF"
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef _MSC_VER
+# include <direct.h>
+# include <process.h>
+# include <io.h>
+# define setmode _setmode
+#else
+# include <unistd.h>
+# include <stdint.h>
+# ifdef __CYGWIN__
+# include <io.h>
+# define HAVE_SETENV
+# ifdef __STRICT_ANSI__
+char *realpath (const char *, char *);
+int putenv (char *);
+int setenv (const char *, const char *, int);
+# endif
+# endif
+#endif
+#include <malloc.h>
+#include <stdarg.h>
+#include <assert.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+#if defined(PATH_MAX)
+# define LT_PATHMAX PATH_MAX
+#elif defined(MAXPATHLEN)
+# define LT_PATHMAX MAXPATHLEN
+#else
+# define LT_PATHMAX 1024
+#endif
+
+#ifndef S_IXOTH
+# define S_IXOTH 0
+#endif
+#ifndef S_IXGRP
+# define S_IXGRP 0
+#endif
+
+#ifdef _MSC_VER
+# define S_IXUSR _S_IEXEC
+# define stat _stat
+# ifndef _INTPTR_T_DEFINED
+# define intptr_t int
+# endif
+#endif
+
+#ifndef DIR_SEPARATOR
+# define DIR_SEPARATOR '/'
+# define PATH_SEPARATOR ':'
+#endif
+
+#if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \
+ defined (__OS2__)
+# define HAVE_DOS_BASED_FILE_SYSTEM
+# define FOPEN_WB "wb"
+# ifndef DIR_SEPARATOR_2
+# define DIR_SEPARATOR_2 '\\'
+# endif
+# ifndef PATH_SEPARATOR_2
+# define PATH_SEPARATOR_2 ';'
+# endif
+#endif
+
+#ifndef DIR_SEPARATOR_2
+# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR)
+#else /* DIR_SEPARATOR_2 */
+# define IS_DIR_SEPARATOR(ch) \
+ (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2))
+#endif /* DIR_SEPARATOR_2 */
+
+#ifndef PATH_SEPARATOR_2
+# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR)
+#else /* PATH_SEPARATOR_2 */
+# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2)
+#endif /* PATH_SEPARATOR_2 */
+
+#ifdef __CYGWIN__
+# define FOPEN_WB "wb"
+#endif
+
+#ifndef FOPEN_WB
+# define FOPEN_WB "w"
+#endif
+#ifndef _O_BINARY
+# define _O_BINARY 0
+#endif
+
+#define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type)))
+#define XFREE(stale) do { \
+ if (stale) { free ((void *) stale); stale = 0; } \
+} while (0)
+
+#undef LTWRAPPER_DEBUGPRINTF
+#if defined DEBUGWRAPPER
+# define LTWRAPPER_DEBUGPRINTF(args) ltwrapper_debugprintf args
+static void
+ltwrapper_debugprintf (const char *fmt, ...)
+{
+ va_list args;
+ va_start (args, fmt);
+ (void) vfprintf (stderr, fmt, args);
+ va_end (args);
+}
+#else
+# define LTWRAPPER_DEBUGPRINTF(args)
+#endif
+
+const char *program_name = NULL;
+
+void *xmalloc (size_t num);
+char *xstrdup (const char *string);
+const char *base_name (const char *name);
+char *find_executable (const char *wrapper);
+char *chase_symlinks (const char *pathspec);
+int make_executable (const char *path);
+int check_executable (const char *path);
+char *strendzap (char *str, const char *pat);
+void lt_fatal (const char *message, ...);
+void lt_setenv (const char *name, const char *value);
+char *lt_extend_str (const char *orig_value, const char *add, int to_end);
+void lt_opt_process_env_set (const char *arg);
+void lt_opt_process_env_prepend (const char *arg);
+void lt_opt_process_env_append (const char *arg);
+int lt_split_name_value (const char *arg, char** name, char** value);
+void lt_update_exe_path (const char *name, const char *value);
+void lt_update_lib_path (const char *name, const char *value);
+
+static const char *script_text_part1 =
+EOF
+
+ func_emit_wrapper_part1 yes |
+ $SED -e 's/\([\\"]\)/\\\1/g' \
+ -e 's/^/ "/' -e 's/$/\\n"/'
+ echo ";"
+ cat <<EOF
+
+static const char *script_text_part2 =
+EOF
+ func_emit_wrapper_part2 yes |
+ $SED -e 's/\([\\"]\)/\\\1/g' \
+ -e 's/^/ "/' -e 's/$/\\n"/'
+ echo ";"
+
+ cat <<EOF
+const char * MAGIC_EXE = "$magic_exe";
+const char * LIB_PATH_VARNAME = "$shlibpath_var";
+EOF
+
+ if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then
+ func_to_host_pathlist "$temp_rpath"
+ cat <<EOF
+const char * LIB_PATH_VALUE = "$func_to_host_pathlist_result";
+EOF
+ else
+ cat <<"EOF"
+const char * LIB_PATH_VALUE = "";
+EOF
+ fi
+
+ if test -n "$dllsearchpath"; then
+ func_to_host_pathlist "$dllsearchpath:"
+ cat <<EOF
+const char * EXE_PATH_VARNAME = "PATH";
+const char * EXE_PATH_VALUE = "$func_to_host_pathlist_result";
+EOF
+ else
+ cat <<"EOF"
+const char * EXE_PATH_VARNAME = "";
+const char * EXE_PATH_VALUE = "";
+EOF
+ fi
+
+ if test "$fast_install" = yes; then
+ cat <<EOF
+const char * TARGET_PROGRAM_NAME = "lt-$outputname"; /* hopefully, no .exe */
+EOF
+ else
+ cat <<EOF
+const char * TARGET_PROGRAM_NAME = "$outputname"; /* hopefully, no .exe */
+EOF
+ fi
+
+
+ cat <<"EOF"
+
+#define LTWRAPPER_OPTION_PREFIX "--lt-"
+#define LTWRAPPER_OPTION_PREFIX_LENGTH 5
+
+static const size_t opt_prefix_len = LTWRAPPER_OPTION_PREFIX_LENGTH;
+static const char *ltwrapper_option_prefix = LTWRAPPER_OPTION_PREFIX;
+
+static const char *dumpscript_opt = LTWRAPPER_OPTION_PREFIX "dump-script";
+
+static const size_t env_set_opt_len = LTWRAPPER_OPTION_PREFIX_LENGTH + 7;
+static const char *env_set_opt = LTWRAPPER_OPTION_PREFIX "env-set";
+ /* argument is putenv-style "foo=bar", value of foo is set to bar */
+
+static const size_t env_prepend_opt_len = LTWRAPPER_OPTION_PREFIX_LENGTH + 11;
+static const char *env_prepend_opt = LTWRAPPER_OPTION_PREFIX "env-prepend";
+ /* argument is putenv-style "foo=bar", new value of foo is bar${foo} */
+
+static const size_t env_append_opt_len = LTWRAPPER_OPTION_PREFIX_LENGTH + 10;
+static const char *env_append_opt = LTWRAPPER_OPTION_PREFIX "env-append";
+ /* argument is putenv-style "foo=bar", new value of foo is ${foo}bar */
+
+int
+main (int argc, char *argv[])
+{
+ char **newargz;
+ int newargc;
+ char *tmp_pathspec;
+ char *actual_cwrapper_path;
+ char *actual_cwrapper_name;
+ char *target_name;
+ char *lt_argv_zero;
+ intptr_t rval = 127;
+
+ int i;
+
+ program_name = (char *) xstrdup (base_name (argv[0]));
+ LTWRAPPER_DEBUGPRINTF (("(main) argv[0] : %s\n", argv[0]));
+ LTWRAPPER_DEBUGPRINTF (("(main) program_name : %s\n", program_name));
+
+ /* very simple arg parsing; don't want to rely on getopt */
+ for (i = 1; i < argc; i++)
+ {
+ if (strcmp (argv[i], dumpscript_opt) == 0)
+ {
+EOF
+ case "$host" in
+ *mingw* | *cygwin* )
+ # make stdout use "unix" line endings
+ echo " setmode(1,_O_BINARY);"
+ ;;
+ esac
+
+ cat <<"EOF"
+ printf ("%s", script_text_part1);
+ printf ("%s", script_text_part2);
+ return 0;
+ }
+ }
+
+ newargz = XMALLOC (char *, argc + 1);
+ tmp_pathspec = find_executable (argv[0]);
+ if (tmp_pathspec == NULL)
+ lt_fatal ("Couldn't find %s", argv[0]);
+ LTWRAPPER_DEBUGPRINTF (("(main) found exe (before symlink chase) at : %s\n",
+ tmp_pathspec));
+
+ actual_cwrapper_path = chase_symlinks (tmp_pathspec);
+ LTWRAPPER_DEBUGPRINTF (("(main) found exe (after symlink chase) at : %s\n",
+ actual_cwrapper_path));
+ XFREE (tmp_pathspec);
+
+ actual_cwrapper_name = xstrdup( base_name (actual_cwrapper_path));
+ strendzap (actual_cwrapper_path, actual_cwrapper_name);
+
+ /* wrapper name transforms */
+ strendzap (actual_cwrapper_name, ".exe");
+ tmp_pathspec = lt_extend_str (actual_cwrapper_name, ".exe", 1);
+ XFREE (actual_cwrapper_name);
+ actual_cwrapper_name = tmp_pathspec;
+ tmp_pathspec = 0;
+
+ /* target_name transforms -- use actual target program name; might have lt- prefix */
+ target_name = xstrdup (base_name (TARGET_PROGRAM_NAME));
+ strendzap (target_name, ".exe");
+ tmp_pathspec = lt_extend_str (target_name, ".exe", 1);
+ XFREE (target_name);
+ target_name = tmp_pathspec;
+ tmp_pathspec = 0;
+
+ LTWRAPPER_DEBUGPRINTF (("(main) libtool target name: %s\n",
+ target_name));
+EOF
+
+ cat <<EOF
+ newargz[0] =
+ XMALLOC (char, (strlen (actual_cwrapper_path) +
+ strlen ("$objdir") + 1 + strlen (actual_cwrapper_name) + 1));
+ strcpy (newargz[0], actual_cwrapper_path);
+ strcat (newargz[0], "$objdir");
+ strcat (newargz[0], "/");
+EOF
+
+ cat <<"EOF"
+ /* stop here, and copy so we don't have to do this twice */
+ tmp_pathspec = xstrdup (newargz[0]);
+
+ /* do NOT want the lt- prefix here, so use actual_cwrapper_name */
+ strcat (newargz[0], actual_cwrapper_name);
+
+ /* DO want the lt- prefix here if it exists, so use target_name */
+ lt_argv_zero = lt_extend_str (tmp_pathspec, target_name, 1);
+ XFREE (tmp_pathspec);
+ tmp_pathspec = NULL;
+EOF
+
+ case $host_os in
+ mingw*)
+ cat <<"EOF"
+ {
+ char* p;
+ while ((p = strchr (newargz[0], '\\')) != NULL)
+ {
+ *p = '/';
+ }
+ while ((p = strchr (lt_argv_zero, '\\')) != NULL)
+ {
+ *p = '/';
+ }
+ }
+EOF
+ ;;
+ esac
+
+ cat <<"EOF"
+ XFREE (target_name);
+ XFREE (actual_cwrapper_path);
+ XFREE (actual_cwrapper_name);
+
+ lt_setenv ("BIN_SH", "xpg4"); /* for Tru64 */
+ lt_setenv ("DUALCASE", "1"); /* for MSK sh */
+ lt_update_lib_path (LIB_PATH_VARNAME, LIB_PATH_VALUE);
+ lt_update_exe_path (EXE_PATH_VARNAME, EXE_PATH_VALUE);
+
+ newargc=0;
+ for (i = 1; i < argc; i++)
+ {
+ if (strncmp (argv[i], env_set_opt, env_set_opt_len) == 0)
+ {
+ if (argv[i][env_set_opt_len] == '=')
+ {
+ const char *p = argv[i] + env_set_opt_len + 1;
+ lt_opt_process_env_set (p);
+ }
+ else if (argv[i][env_set_opt_len] == '\0' && i + 1 < argc)
+ {
+ lt_opt_process_env_set (argv[++i]); /* don't copy */
+ }
+ else
+ lt_fatal ("%s missing required argument", env_set_opt);
+ continue;
+ }
+ if (strncmp (argv[i], env_prepend_opt, env_prepend_opt_len) == 0)
+ {
+ if (argv[i][env_prepend_opt_len] == '=')
+ {
+ const char *p = argv[i] + env_prepend_opt_len + 1;
+ lt_opt_process_env_prepend (p);
+ }
+ else if (argv[i][env_prepend_opt_len] == '\0' && i + 1 < argc)
+ {
+ lt_opt_process_env_prepend (argv[++i]); /* don't copy */
+ }
+ else
+ lt_fatal ("%s missing required argument", env_prepend_opt);
+ continue;
+ }
+ if (strncmp (argv[i], env_append_opt, env_append_opt_len) == 0)
+ {
+ if (argv[i][env_append_opt_len] == '=')
+ {
+ const char *p = argv[i] + env_append_opt_len + 1;
+ lt_opt_process_env_append (p);
+ }
+ else if (argv[i][env_append_opt_len] == '\0' && i + 1 < argc)
+ {
+ lt_opt_process_env_append (argv[++i]); /* don't copy */
+ }
+ else
+ lt_fatal ("%s missing required argument", env_append_opt);
+ continue;
+ }
+ if (strncmp (argv[i], ltwrapper_option_prefix, opt_prefix_len) == 0)
+ {
+ /* however, if there is an option in the LTWRAPPER_OPTION_PREFIX
+ namespace, but it is not one of the ones we know about and
+ have already dealt with, above (inluding dump-script), then
+ report an error. Otherwise, targets might begin to believe
+ they are allowed to use options in the LTWRAPPER_OPTION_PREFIX
+ namespace. The first time any user complains about this, we'll
+ need to make LTWRAPPER_OPTION_PREFIX a configure-time option
+ or a configure.ac-settable value.
+ */
+ lt_fatal ("Unrecognized option in %s namespace: '%s'",
+ ltwrapper_option_prefix, argv[i]);
+ }
+ /* otherwise ... */
+ newargz[++newargc] = xstrdup (argv[i]);
+ }
+ newargz[++newargc] = NULL;
+
+ LTWRAPPER_DEBUGPRINTF (("(main) lt_argv_zero : %s\n", (lt_argv_zero ? lt_argv_zero : "<NULL>")));
+ for (i = 0; i < newargc; i++)
+ {
+ LTWRAPPER_DEBUGPRINTF (("(main) newargz[%d] : %s\n", i, (newargz[i] ? newargz[i] : "<NULL>")));
+ }
+
+EOF
+
+ case $host_os in
+ mingw*)
+ cat <<"EOF"
+ /* execv doesn't actually work on mingw as expected on unix */
+ rval = _spawnv (_P_WAIT, lt_argv_zero, (const char * const *) newargz);
+ if (rval == -1)
+ {
+ /* failed to start process */
+ LTWRAPPER_DEBUGPRINTF (("(main) failed to launch target \"%s\": errno = %d\n", lt_argv_zero, errno));
+ return 127;
+ }
+ return rval;
+EOF
+ ;;
+ *)
+ cat <<"EOF"
+ execv (lt_argv_zero, newargz);
+ return rval; /* =127, but avoids unused variable warning */
+EOF
+ ;;
+ esac
+
+ cat <<"EOF"
+}
+
+void *
+xmalloc (size_t num)
+{
+ void *p = (void *) malloc (num);
+ if (!p)
+ lt_fatal ("Memory exhausted");
+
+ return p;
+}
+
+char *
+xstrdup (const char *string)
+{
+ return string ? strcpy ((char *) xmalloc (strlen (string) + 1),
+ string) : NULL;
+}
+
+const char *
+base_name (const char *name)
+{
+ const char *base;
+
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
+ /* Skip over the disk name in MSDOS pathnames. */
+ if (isalpha ((unsigned char) name[0]) && name[1] == ':')
+ name += 2;
+#endif
+
+ for (base = name; *name; name++)
+ if (IS_DIR_SEPARATOR (*name))
+ base = name + 1;
+ return base;
+}
+
+int
+check_executable (const char *path)
+{
+ struct stat st;
+
+ LTWRAPPER_DEBUGPRINTF (("(check_executable) : %s\n",
+ path ? (*path ? path : "EMPTY!") : "NULL!"));
+ if ((!path) || (!*path))
+ return 0;
+
+ if ((stat (path, &st) >= 0)
+ && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)))
+ return 1;
+ else
+ return 0;
+}
+
+int
+make_executable (const char *path)
+{
+ int rval = 0;
+ struct stat st;
+
+ LTWRAPPER_DEBUGPRINTF (("(make_executable) : %s\n",
+ path ? (*path ? path : "EMPTY!") : "NULL!"));
+ if ((!path) || (!*path))
+ return 0;
+
+ if (stat (path, &st) >= 0)
+ {
+ rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR);
+ }
+ return rval;
+}
+
+/* Searches for the full path of the wrapper. Returns
+ newly allocated full path name if found, NULL otherwise
+ Does not chase symlinks, even on platforms that support them.
+*/
+char *
+find_executable (const char *wrapper)
+{
+ int has_slash = 0;
+ const char *p;
+ const char *p_next;
+ /* static buffer for getcwd */
+ char tmp[LT_PATHMAX + 1];
+ int tmp_len;
+ char *concat_name;
+
+ LTWRAPPER_DEBUGPRINTF (("(find_executable) : %s\n",
+ wrapper ? (*wrapper ? wrapper : "EMPTY!") : "NULL!"));
+
+ if ((wrapper == NULL) || (*wrapper == '\0'))
+ return NULL;
+
+ /* Absolute path? */
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
+ if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':')
+ {
+ concat_name = xstrdup (wrapper);
+ if (check_executable (concat_name))
+ return concat_name;
+ XFREE (concat_name);
+ }
+ else
+ {
+#endif
+ if (IS_DIR_SEPARATOR (wrapper[0]))
+ {
+ concat_name = xstrdup (wrapper);
+ if (check_executable (concat_name))
+ return concat_name;
+ XFREE (concat_name);
+ }
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
+ }
+#endif
+
+ for (p = wrapper; *p; p++)
+ if (*p == '/')
+ {
+ has_slash = 1;
+ break;
+ }
+ if (!has_slash)
+ {
+ /* no slashes; search PATH */
+ const char *path = getenv ("PATH");
+ if (path != NULL)
+ {
+ for (p = path; *p; p = p_next)
+ {
+ const char *q;
+ size_t p_len;
+ for (q = p; *q; q++)
+ if (IS_PATH_SEPARATOR (*q))
+ break;
+ p_len = q - p;
+ p_next = (*q == '\0' ? q : q + 1);
+ if (p_len == 0)
+ {
+ /* empty path: current directory */
+ if (getcwd (tmp, LT_PATHMAX) == NULL)
+ lt_fatal ("getcwd failed");
+ tmp_len = strlen (tmp);
+ concat_name =
+ XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1);
+ memcpy (concat_name, tmp, tmp_len);
+ concat_name[tmp_len] = '/';
+ strcpy (concat_name + tmp_len + 1, wrapper);
+ }
+ else
+ {
+ concat_name =
+ XMALLOC (char, p_len + 1 + strlen (wrapper) + 1);
+ memcpy (concat_name, p, p_len);
+ concat_name[p_len] = '/';
+ strcpy (concat_name + p_len + 1, wrapper);
+ }
+ if (check_executable (concat_name))
+ return concat_name;
+ XFREE (concat_name);
+ }
+ }
+ /* not found in PATH; assume curdir */
+ }
+ /* Relative path | not found in path: prepend cwd */
+ if (getcwd (tmp, LT_PATHMAX) == NULL)
+ lt_fatal ("getcwd failed");
+ tmp_len = strlen (tmp);
+ concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1);
+ memcpy (concat_name, tmp, tmp_len);
+ concat_name[tmp_len] = '/';
+ strcpy (concat_name + tmp_len + 1, wrapper);
+
+ if (check_executable (concat_name))
+ return concat_name;
+ XFREE (concat_name);
+ return NULL;
+}
+
+char *
+chase_symlinks (const char *pathspec)
+{
+#ifndef S_ISLNK
+ return xstrdup (pathspec);
+#else
+ char buf[LT_PATHMAX];
+ struct stat s;
+ char *tmp_pathspec = xstrdup (pathspec);
+ char *p;
+ int has_symlinks = 0;
+ while (strlen (tmp_pathspec) && !has_symlinks)
+ {
+ LTWRAPPER_DEBUGPRINTF (("checking path component for symlinks: %s\n",
+ tmp_pathspec));
+ if (lstat (tmp_pathspec, &s) == 0)
+ {
+ if (S_ISLNK (s.st_mode) != 0)
+ {
+ has_symlinks = 1;
+ break;
+ }
+
+ /* search backwards for last DIR_SEPARATOR */
+ p = tmp_pathspec + strlen (tmp_pathspec) - 1;
+ while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p)))
+ p--;
+ if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p)))
+ {
+ /* no more DIR_SEPARATORS left */
+ break;
+ }
+ *p = '\0';
+ }
+ else
+ {
+ char *errstr = strerror (errno);
+ lt_fatal ("Error accessing file %s (%s)", tmp_pathspec, errstr);
+ }
+ }
+ XFREE (tmp_pathspec);
+
+ if (!has_symlinks)
+ {
+ return xstrdup (pathspec);
+ }
+
+ tmp_pathspec = realpath (pathspec, buf);
+ if (tmp_pathspec == 0)
+ {
+ lt_fatal ("Could not follow symlinks for %s", pathspec);
+ }
+ return xstrdup (tmp_pathspec);
+#endif
+}
+
+char *
+strendzap (char *str, const char *pat)
+{
+ size_t len, patlen;
+
+ assert (str != NULL);
+ assert (pat != NULL);
+
+ len = strlen (str);
+ patlen = strlen (pat);
+
+ if (patlen <= len)
+ {
+ str += len - patlen;
+ if (strcmp (str, pat) == 0)
+ *str = '\0';
+ }
+ return str;
+}
+
+static void
+lt_error_core (int exit_status, const char *mode,
+ const char *message, va_list ap)
+{
+ fprintf (stderr, "%s: %s: ", program_name, mode);
+ vfprintf (stderr, message, ap);
+ fprintf (stderr, ".\n");
+
+ if (exit_status >= 0)
+ exit (exit_status);
+}
+
+void
+lt_fatal (const char *message, ...)
+{
+ va_list ap;
+ va_start (ap, message);
+ lt_error_core (EXIT_FAILURE, "FATAL", message, ap);
+ va_end (ap);
+}
+
+void
+lt_setenv (const char *name, const char *value)
+{
+ LTWRAPPER_DEBUGPRINTF (("(lt_setenv) setting '%s' to '%s'\n",
+ (name ? name : "<NULL>"),
+ (value ? value : "<NULL>")));
+ {
+#ifdef HAVE_SETENV
+ /* always make a copy, for consistency with !HAVE_SETENV */
+ char *str = xstrdup (value);
+ setenv (name, str, 1);
+#else
+ int len = strlen (name) + 1 + strlen (value) + 1;
+ char *str = XMALLOC (char, len);
+ sprintf (str, "%s=%s", name, value);
+ if (putenv (str) != EXIT_SUCCESS)
+ {
+ XFREE (str);
+ }
+#endif
+ }
+}
+
+char *
+lt_extend_str (const char *orig_value, const char *add, int to_end)
+{
+ char *new_value;
+ if (orig_value && *orig_value)
+ {
+ int orig_value_len = strlen (orig_value);
+ int add_len = strlen (add);
+ new_value = XMALLOC (char, add_len + orig_value_len + 1);
+ if (to_end)
+ {
+ strcpy (new_value, orig_value);
+ strcpy (new_value + orig_value_len, add);
+ }
+ else
+ {
+ strcpy (new_value, add);
+ strcpy (new_value + add_len, orig_value);
+ }
+ }
+ else
+ {
+ new_value = xstrdup (add);
+ }
+ return new_value;
+}
+
+int
+lt_split_name_value (const char *arg, char** name, char** value)
+{
+ const char *p;
+ int len;
+ if (!arg || !*arg)
+ return 1;
+
+ p = strchr (arg, (int)'=');
+
+ if (!p)
+ return 1;
+
+ *value = xstrdup (++p);
+
+ len = strlen (arg) - strlen (*value);
+ *name = XMALLOC (char, len);
+ strncpy (*name, arg, len-1);
+ (*name)[len - 1] = '\0';
+
+ return 0;
+}
+
+void
+lt_opt_process_env_set (const char *arg)
+{
+ char *name = NULL;
+ char *value = NULL;
+
+ if (lt_split_name_value (arg, &name, &value) != 0)
+ {
+ XFREE (name);
+ XFREE (value);
+ lt_fatal ("bad argument for %s: '%s'", env_set_opt, arg);
+ }
+
+ lt_setenv (name, value);
+ XFREE (name);
+ XFREE (value);
+}
+
+void
+lt_opt_process_env_prepend (const char *arg)
+{
+ char *name = NULL;
+ char *value = NULL;
+ char *new_value = NULL;
+
+ if (lt_split_name_value (arg, &name, &value) != 0)
+ {
+ XFREE (name);
+ XFREE (value);
+ lt_fatal ("bad argument for %s: '%s'", env_prepend_opt, arg);
+ }
+
+ new_value = lt_extend_str (getenv (name), value, 0);
+ lt_setenv (name, new_value);
+ XFREE (new_value);
+ XFREE (name);
+ XFREE (value);
+}
+
+void
+lt_opt_process_env_append (const char *arg)
+{
+ char *name = NULL;
+ char *value = NULL;
+ char *new_value = NULL;
+
+ if (lt_split_name_value (arg, &name, &value) != 0)
+ {
+ XFREE (name);
+ XFREE (value);
+ lt_fatal ("bad argument for %s: '%s'", env_append_opt, arg);
+ }
+
+ new_value = lt_extend_str (getenv (name), value, 1);
+ lt_setenv (name, new_value);
+ XFREE (new_value);
+ XFREE (name);
+ XFREE (value);
+}
+
+void
+lt_update_exe_path (const char *name, const char *value)
+{
+ LTWRAPPER_DEBUGPRINTF (("(lt_update_exe_path) modifying '%s' by prepending '%s'\n",
+ (name ? name : "<NULL>"),
+ (value ? value : "<NULL>")));
+
+ if (name && *name && value && *value)
+ {
+ char *new_value = lt_extend_str (getenv (name), value, 0);
+ /* some systems can't cope with a ':'-terminated path #' */
+ int len = strlen (new_value);
+ while (((len = strlen (new_value)) > 0) && IS_PATH_SEPARATOR (new_value[len-1]))
+ {
+ new_value[len-1] = '\0';
+ }
+ lt_setenv (name, new_value);
+ XFREE (new_value);
+ }
+}
+
+void
+lt_update_lib_path (const char *name, const char *value)
+{
+ LTWRAPPER_DEBUGPRINTF (("(lt_update_lib_path) modifying '%s' by prepending '%s'\n",
+ (name ? name : "<NULL>"),
+ (value ? value : "<NULL>")));
+
+ if (name && *name && value && *value)
+ {
+ char *new_value = lt_extend_str (getenv (name), value, 0);
+ lt_setenv (name, new_value);
+ XFREE (new_value);
+ }
+}
+
+
+EOF
+}
+# end: func_emit_cwrapperexe_src
+
+# func_mode_link arg...
+func_mode_link ()
+{
+ $opt_debug
+ case $host in
+ *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*)
+ # It is impossible to link a dll without this setting, and
+ # we shouldn't force the makefile maintainer to figure out
+ # which system we are compiling for in order to pass an extra
+ # flag for every libtool invocation.
+ # allow_undefined=no
+
+ # FIXME: Unfortunately, there are problems with the above when trying
+ # to make a dll which has undefined symbols, in which case not
+ # even a static library is built. For now, we need to specify
+ # -no-undefined on the libtool link line when we can be certain
+ # that all symbols are satisfied, otherwise we get a static library.
+ allow_undefined=yes
+ ;;
+ *)
+ allow_undefined=yes
+ ;;
+ esac
+ libtool_args=$nonopt
+ base_compile="$nonopt $@"
+ compile_command=$nonopt
+ finalize_command=$nonopt
+
+ compile_rpath=
+ finalize_rpath=
+ compile_shlibpath=
+ finalize_shlibpath=
+ convenience=
+ old_convenience=
+ deplibs=
+ old_deplibs=
+ compiler_flags=
+ linker_flags=
+ dllsearchpath=
+ lib_search_path=`pwd`
+ inst_prefix_dir=
+ new_inherited_linker_flags=
+
+ avoid_version=no
+ dlfiles=
+ dlprefiles=
+ dlself=no
+ export_dynamic=no
+ export_symbols=
+ export_symbols_regex=
+ generated=
+ libobjs=
+ ltlibs=
+ module=no
+ no_install=no
+ objs=
+ non_pic_objects=
+ precious_files_regex=
+ prefer_static_libs=no
+ preload=no
+ prev=
+ prevarg=
+ release=
+ rpath=
+ xrpath=
+ perm_rpath=
+ temp_rpath=
+ thread_safe=no
+ vinfo=
+ vinfo_number=no
+ weak_libs=
+ single_module="${wl}-single_module"
+ func_infer_tag $base_compile
+
+ # We need to know -static, to get the right output filenames.
+ for arg
+ do
+ case $arg in
+ -shared)
+ test "$build_libtool_libs" != yes && \
+ func_fatal_configuration "can not build a shared library"
+ build_old_libs=no
+ break
+ ;;
+ -all-static | -static | -static-libtool-libs)
+ case $arg in
+ -all-static)
+ if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then
+ func_warning "complete static linking is impossible in this configuration"
+ fi
+ if test -n "$link_static_flag"; then
+ dlopen_self=$dlopen_self_static
+ fi
+ prefer_static_libs=yes
+ ;;
+ -static)
+ if test -z "$pic_flag" && test -n "$link_static_flag"; then
+ dlopen_self=$dlopen_self_static
+ fi
+ prefer_static_libs=built
+ ;;
+ -static-libtool-libs)
+ if test -z "$pic_flag" && test -n "$link_static_flag"; then
+ dlopen_self=$dlopen_self_static
+ fi
+ prefer_static_libs=yes
+ ;;
+ esac
+ build_libtool_libs=no
+ build_old_libs=yes
+ break
+ ;;
+ esac
+ done
+
+ # See if our shared archives depend on static archives.
+ test -n "$old_archive_from_new_cmds" && build_old_libs=yes
+
+ # Go through the arguments, transforming them on the way.
+ while test "$#" -gt 0; do
+ arg="$1"
+ shift
+ func_quote_for_eval "$arg"
+ qarg=$func_quote_for_eval_unquoted_result
+ func_append libtool_args " $func_quote_for_eval_result"
+
+ # If the previous option needs an argument, assign it.
+ if test -n "$prev"; then
+ case $prev in
+ output)
+ func_append compile_command " @OUTPUT@"
+ func_append finalize_command " @OUTPUT@"
+ ;;
+ esac
+
+ case $prev in
+ dlfiles|dlprefiles)
+ if test "$preload" = no; then
+ # Add the symbol object into the linking commands.
+ func_append compile_command " @SYMFILE@"
+ func_append finalize_command " @SYMFILE@"
+ preload=yes
+ fi
+ case $arg in
+ *.la | *.lo) ;; # We handle these cases below.
+ force)
+ if test "$dlself" = no; then
+ dlself=needless
+ export_dynamic=yes
+ fi
+ prev=
+ continue
+ ;;
+ self)
+ if test "$prev" = dlprefiles; then
+ dlself=yes
+ elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then
+ dlself=yes
+ else
+ dlself=needless
+ export_dynamic=yes
+ fi
+ prev=
+ continue
+ ;;
+ *)
+ if test "$prev" = dlfiles; then
+ dlfiles="$dlfiles $arg"
+ else
+ dlprefiles="$dlprefiles $arg"
+ fi
+ prev=
+ continue
+ ;;
+ esac
+ ;;
+ expsyms)
+ export_symbols="$arg"
+ test -f "$arg" \
+ || func_fatal_error "symbol file \`$arg' does not exist"
+ prev=
+ continue
+ ;;
+ expsyms_regex)
+ export_symbols_regex="$arg"
+ prev=
+ continue
+ ;;
+ framework)
+ case $host in
+ *-*-darwin*)
+ case "$deplibs " in
+ *" $qarg.ltframework "*) ;;
+ *) deplibs="$deplibs $qarg.ltframework" # this is fixed later
+ ;;
+ esac
+ ;;
+ esac
+ prev=
+ continue
+ ;;
+ inst_prefix)
+ inst_prefix_dir="$arg"
+ prev=
+ continue
+ ;;
+ objectlist)
+ if test -f "$arg"; then
+ save_arg=$arg
+ moreargs=
+ for fil in `cat "$save_arg"`
+ do
+# moreargs="$moreargs $fil"
+ arg=$fil
+ # A libtool-controlled object.
+
+ # Check to see that this really is a libtool object.
+ if func_lalib_unsafe_p "$arg"; then
+ pic_object=
+ non_pic_object=
+
+ # Read the .lo file
+ func_source "$arg"
+
+ if test -z "$pic_object" ||
+ test -z "$non_pic_object" ||
+ test "$pic_object" = none &&
+ test "$non_pic_object" = none; then
+ func_fatal_error "cannot find name of object for \`$arg'"
+ fi
+
+ # Extract subdirectory from the argument.
+ func_dirname "$arg" "/" ""
+ xdir="$func_dirname_result"
+
+ if test "$pic_object" != none; then
+ # Prepend the subdirectory the object is found in.
+ pic_object="$xdir$pic_object"
+
+ if test "$prev" = dlfiles; then
+ if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then
+ dlfiles="$dlfiles $pic_object"
+ prev=
+ continue
+ else
+ # If libtool objects are unsupported, then we need to preload.
+ prev=dlprefiles
+ fi
+ fi
+
+ # CHECK ME: I think I busted this. -Ossama
+ if test "$prev" = dlprefiles; then
+ # Preload the old-style object.
+ dlprefiles="$dlprefiles $pic_object"
+ prev=
+ fi
+
+ # A PIC object.
+ func_append libobjs " $pic_object"
+ arg="$pic_object"
+ fi
+
+ # Non-PIC object.
+ if test "$non_pic_object" != none; then
+ # Prepend the subdirectory the object is found in.
+ non_pic_object="$xdir$non_pic_object"
+
+ # A standard non-PIC object
+ func_append non_pic_objects " $non_pic_object"
+ if test -z "$pic_object" || test "$pic_object" = none ; then
+ arg="$non_pic_object"
+ fi
+ else
+ # If the PIC object exists, use it instead.
+ # $xdir was prepended to $pic_object above.
+ non_pic_object="$pic_object"
+ func_append non_pic_objects " $non_pic_object"
+ fi
+ else
+ # Only an error if not doing a dry-run.
+ if $opt_dry_run; then
+ # Extract subdirectory from the argument.
+ func_dirname "$arg" "/" ""
+ xdir="$func_dirname_result"
+
+ func_lo2o "$arg"
+ pic_object=$xdir$objdir/$func_lo2o_result
+ non_pic_object=$xdir$func_lo2o_result
+ func_append libobjs " $pic_object"
+ func_append non_pic_objects " $non_pic_object"
+ else
+ func_fatal_error "\`$arg' is not a valid libtool object"
+ fi
+ fi
+ done
+ else
+ func_fatal_error "link input file \`$arg' does not exist"
+ fi
+ arg=$save_arg
+ prev=
+ continue
+ ;;
+ precious_regex)
+ precious_files_regex="$arg"
+ prev=
+ continue
+ ;;
+ release)
+ release="-$arg"
+ prev=
+ continue
+ ;;
+ rpath | xrpath)
+ # We need an absolute path.
+ case $arg in
+ [\\/]* | [A-Za-z]:[\\/]*) ;;
+ *)
+ func_fatal_error "only absolute run-paths are allowed"
+ ;;
+ esac
+ if test "$prev" = rpath; then
+ case "$rpath " in
+ *" $arg "*) ;;
+ *) rpath="$rpath $arg" ;;
+ esac
+ else
+ case "$xrpath " in
+ *" $arg "*) ;;
+ *) xrpath="$xrpath $arg" ;;
+ esac
+ fi
+ prev=
+ continue
+ ;;
+ shrext)
+ shrext_cmds="$arg"
+ prev=
+ continue
+ ;;
+ weak)
+ weak_libs="$weak_libs $arg"
+ prev=
+ continue
+ ;;
+ xcclinker)
+ linker_flags="$linker_flags $qarg"
+ compiler_flags="$compiler_flags $qarg"
+ prev=
+ func_append compile_command " $qarg"
+ func_append finalize_command " $qarg"
+ continue
+ ;;
+ xcompiler)
+ compiler_flags="$compiler_flags $qarg"
+ prev=
+ func_append compile_command " $qarg"
+ func_append finalize_command " $qarg"
+ continue
+ ;;
+ xlinker)
+ linker_flags="$linker_flags $qarg"
+ compiler_flags="$compiler_flags $wl$qarg"
+ prev=
+ func_append compile_command " $wl$qarg"
+ func_append finalize_command " $wl$qarg"
+ continue
+ ;;
+ *)
+ eval "$prev=\"\$arg\""
+ prev=
+ continue
+ ;;
+ esac
+ fi # test -n "$prev"
+
+ prevarg="$arg"
+
+ case $arg in
+ -all-static)
+ if test -n "$link_static_flag"; then
+ # See comment for -static flag below, for more details.
+ func_append compile_command " $link_static_flag"
+ func_append finalize_command " $link_static_flag"
+ fi
+ continue
+ ;;
+
+ -allow-undefined)
+ # FIXME: remove this flag sometime in the future.
+ func_fatal_error "\`-allow-undefined' must not be used because it is the default"
+ ;;
+
+ -avoid-version)
+ avoid_version=yes
+ continue
+ ;;
+
+ -dlopen)
+ prev=dlfiles
+ continue
+ ;;
+
+ -dlpreopen)
+ prev=dlprefiles
+ continue
+ ;;
+
+ -export-dynamic)
+ export_dynamic=yes
+ continue
+ ;;
+
+ -export-symbols | -export-symbols-regex)
+ if test -n "$export_symbols" || test -n "$export_symbols_regex"; then
+ func_fatal_error "more than one -exported-symbols argument is not allowed"
+ fi
+ if test "X$arg" = "X-export-symbols"; then
+ prev=expsyms
+ else
+ prev=expsyms_regex
+ fi
+ continue
+ ;;
+
+ -framework)
+ prev=framework
+ continue
+ ;;
+
+ -inst-prefix-dir)
+ prev=inst_prefix
+ continue
+ ;;
+
+ # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:*
+ # so, if we see these flags be careful not to treat them like -L
+ -L[A-Z][A-Z]*:*)
+ case $with_gcc/$host in
+ no/*-*-irix* | /*-*-irix*)
+ func_append compile_command " $arg"
+ func_append finalize_command " $arg"
+ ;;
+ esac
+ continue
+ ;;
+
+ -L*)
+ func_stripname '-L' '' "$arg"
+ dir=$func_stripname_result
+ if test -z "$dir"; then
+ if test "$#" -gt 0; then
+ func_fatal_error "require no space between \`-L' and \`$1'"
+ else
+ func_fatal_error "need path for \`-L' option"
+ fi
+ fi
+ # We need an absolute path.
+ case $dir in
+ [\\/]* | [A-Za-z]:[\\/]*) ;;
+ *)
+ absdir=`cd "$dir" && pwd`
+ test -z "$absdir" && \
+ func_fatal_error "cannot determine absolute directory name of \`$dir'"
+ dir="$absdir"
+ ;;
+ esac
+ case "$deplibs " in
+ *" -L$dir "*) ;;
+ *)
+ deplibs="$deplibs -L$dir"
+ lib_search_path="$lib_search_path $dir"
+ ;;
+ esac
+ case $host in
+ *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*)
+ testbindir=`$ECHO "X$dir" | $Xsed -e 's*/lib$*/bin*'`
+ case :$dllsearchpath: in
+ *":$dir:"*) ;;
+ ::) dllsearchpath=$dir;;
+ *) dllsearchpath="$dllsearchpath:$dir";;
+ esac
+ case :$dllsearchpath: in
+ *":$testbindir:"*) ;;
+ ::) dllsearchpath=$testbindir;;
+ *) dllsearchpath="$dllsearchpath:$testbindir";;
+ esac
+ ;;
+ esac
+ continue
+ ;;
+
+ -l*)
+ if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then
+ case $host in
+ *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc*)
+ # These systems don't actually have a C or math library (as such)
+ continue
+ ;;
+ *-*-os2*)
+ # These systems don't actually have a C library (as such)
+ test "X$arg" = "X-lc" && continue
+ ;;
+ *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
+ # Do not include libc due to us having libc/libc_r.
+ test "X$arg" = "X-lc" && continue
+ ;;
+ *-*-rhapsody* | *-*-darwin1.[012])
+ # Rhapsody C and math libraries are in the System framework
+ deplibs="$deplibs System.ltframework"
+ continue
+ ;;
+ *-*-sco3.2v5* | *-*-sco5v6*)
+ # Causes problems with __ctype
+ test "X$arg" = "X-lc" && continue
+ ;;
+ *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*)
+ # Compiler inserts libc in the correct place for threads to work
+ test "X$arg" = "X-lc" && continue
+ ;;
+ esac
+ elif test "X$arg" = "X-lc_r"; then
+ case $host in
+ *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
+ # Do not include libc_r directly, use -pthread flag.
+ continue
+ ;;
+ esac
+ fi
+ deplibs="$deplibs $arg"
+ continue
+ ;;
+
+ -module)
+ module=yes
+ continue
+ ;;
+
+ # Tru64 UNIX uses -model [arg] to determine the layout of C++
+ # classes, name mangling, and exception handling.
+ # Darwin uses the -arch flag to determine output architecture.
+ -model|-arch|-isysroot)
+ compiler_flags="$compiler_flags $arg"
+ func_append compile_command " $arg"
+ func_append finalize_command " $arg"
+ prev=xcompiler
+ continue
+ ;;
+
+ -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe|-threads)
+ compiler_flags="$compiler_flags $arg"
+ func_append compile_command " $arg"
+ func_append finalize_command " $arg"
+ case "$new_inherited_linker_flags " in
+ *" $arg "*) ;;
+ * ) new_inherited_linker_flags="$new_inherited_linker_flags $arg" ;;
+ esac
+ continue
+ ;;
+
+ -multi_module)
+ single_module="${wl}-multi_module"
+ continue
+ ;;
+
+ -no-fast-install)
+ fast_install=no
+ continue
+ ;;
+
+ -no-install)
+ case $host in
+ *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*)
+ # The PATH hackery in wrapper scripts is required on Windows
+ # and Darwin in order for the loader to find any dlls it needs.
+ func_warning "\`-no-install' is ignored for $host"
+ func_warning "assuming \`-no-fast-install' instead"
+ fast_install=no
+ ;;
+ *) no_install=yes ;;
+ esac
+ continue
+ ;;
+
+ -no-undefined)
+ allow_undefined=no
+ continue
+ ;;
+
+ -objectlist)
+ prev=objectlist
+ continue
+ ;;
+
+ -o) prev=output ;;
+
+ -precious-files-regex)
+ prev=precious_regex
+ continue
+ ;;
+
+ -release)
+ prev=release
+ continue
+ ;;
+
+ -rpath)
+ prev=rpath
+ continue
+ ;;
+
+ -R)
+ prev=xrpath
+ continue
+ ;;
+
+ -R*)
+ func_stripname '-R' '' "$arg"
+ dir=$func_stripname_result
+ # We need an absolute path.
+ case $dir in
+ [\\/]* | [A-Za-z]:[\\/]*) ;;
+ *)
+ func_fatal_error "only absolute run-paths are allowed"
+ ;;
+ esac
+ case "$xrpath " in
+ *" $dir "*) ;;
+ *) xrpath="$xrpath $dir" ;;
+ esac
+ continue
+ ;;
+
+ -shared)
+ # The effects of -shared are defined in a previous loop.
+ continue
+ ;;
+
+ -shrext)
+ prev=shrext
+ continue
+ ;;
+
+ -static | -static-libtool-libs)
+ # The effects of -static are defined in a previous loop.
+ # We used to do the same as -all-static on platforms that
+ # didn't have a PIC flag, but the assumption that the effects
+ # would be equivalent was wrong. It would break on at least
+ # Digital Unix and AIX.
+ continue
+ ;;
+
+ -thread-safe)
+ thread_safe=yes
+ continue
+ ;;
+
+ -version-info)
+ prev=vinfo
+ continue
+ ;;
+
+ -version-number)
+ prev=vinfo
+ vinfo_number=yes
+ continue
+ ;;
+
+ -weak)
+ prev=weak
+ continue
+ ;;
+
+ -Wc,*)
+ func_stripname '-Wc,' '' "$arg"
+ args=$func_stripname_result
+ arg=
+ save_ifs="$IFS"; IFS=','
+ for flag in $args; do
+ IFS="$save_ifs"
+ func_quote_for_eval "$flag"
+ arg="$arg $wl$func_quote_for_eval_result"
+ compiler_flags="$compiler_flags $func_quote_for_eval_result"
+ done
+ IFS="$save_ifs"
+ func_stripname ' ' '' "$arg"
+ arg=$func_stripname_result
+ ;;
+
+ -Wl,*)
+ func_stripname '-Wl,' '' "$arg"
+ args=$func_stripname_result
+ arg=
+ save_ifs="$IFS"; IFS=','
+ for flag in $args; do
+ IFS="$save_ifs"
+ func_quote_for_eval "$flag"
+ arg="$arg $wl$func_quote_for_eval_result"
+ compiler_flags="$compiler_flags $wl$func_quote_for_eval_result"
+ linker_flags="$linker_flags $func_quote_for_eval_result"
+ done
+ IFS="$save_ifs"
+ func_stripname ' ' '' "$arg"
+ arg=$func_stripname_result
+ ;;
+
+ -Xcompiler)
+ prev=xcompiler
+ continue
+ ;;
+
+ -Xlinker)
+ prev=xlinker
+ continue
+ ;;
+
+ -XCClinker)
+ prev=xcclinker
+ continue
+ ;;
+
+ # -msg_* for osf cc
+ -msg_*)
+ func_quote_for_eval "$arg"
+ arg="$func_quote_for_eval_result"
+ ;;
+
+ # -64, -mips[0-9] enable 64-bit mode on the SGI compiler
+ # -r[0-9][0-9]* specifies the processor on the SGI compiler
+ # -xarch=*, -xtarget=* enable 64-bit mode on the Sun compiler
+ # +DA*, +DD* enable 64-bit mode on the HP compiler
+ # -q* pass through compiler args for the IBM compiler
+ # -m*, -t[45]*, -txscale* pass through architecture-specific
+ # compiler args for GCC
+ # -F/path gives path to uninstalled frameworks, gcc on darwin
+ # -p, -pg, --coverage, -fprofile-* pass through profiling flag for GCC
+ # @file GCC response files
+ -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \
+ -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*)
+ func_quote_for_eval "$arg"
+ arg="$func_quote_for_eval_result"
+ func_append compile_command " $arg"
+ func_append finalize_command " $arg"
+ compiler_flags="$compiler_flags $arg"
+ continue
+ ;;
+
+ # Some other compiler flag.
+ -* | +*)
+ func_quote_for_eval "$arg"
+ arg="$func_quote_for_eval_result"
+ ;;
+
+ *.$objext)
+ # A standard object.
+ objs="$objs $arg"
+ ;;
+
+ *.lo)
+ # A libtool-controlled object.
+
+ # Check to see that this really is a libtool object.
+ if func_lalib_unsafe_p "$arg"; then
+ pic_object=
+ non_pic_object=
+
+ # Read the .lo file
+ func_source "$arg"
+
+ if test -z "$pic_object" ||
+ test -z "$non_pic_object" ||
+ test "$pic_object" = none &&
+ test "$non_pic_object" = none; then
+ func_fatal_error "cannot find name of object for \`$arg'"
+ fi
+
+ # Extract subdirectory from the argument.
+ func_dirname "$arg" "/" ""
+ xdir="$func_dirname_result"
+
+ if test "$pic_object" != none; then
+ # Prepend the subdirectory the object is found in.
+ pic_object="$xdir$pic_object"
+
+ if test "$prev" = dlfiles; then
+ if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then
+ dlfiles="$dlfiles $pic_object"
+ prev=
+ continue
+ else
+ # If libtool objects are unsupported, then we need to preload.
+ prev=dlprefiles
+ fi
+ fi
+
+ # CHECK ME: I think I busted this. -Ossama
+ if test "$prev" = dlprefiles; then
+ # Preload the old-style object.
+ dlprefiles="$dlprefiles $pic_object"
+ prev=
+ fi
+
+ # A PIC object.
+ func_append libobjs " $pic_object"
+ arg="$pic_object"
+ fi
+
+ # Non-PIC object.
+ if test "$non_pic_object" != none; then
+ # Prepend the subdirectory the object is found in.
+ non_pic_object="$xdir$non_pic_object"
+
+ # A standard non-PIC object
+ func_append non_pic_objects " $non_pic_object"
+ if test -z "$pic_object" || test "$pic_object" = none ; then
+ arg="$non_pic_object"
+ fi
+ else
+ # If the PIC object exists, use it instead.
+ # $xdir was prepended to $pic_object above.
+ non_pic_object="$pic_object"
+ func_append non_pic_objects " $non_pic_object"
+ fi
+ else
+ # Only an error if not doing a dry-run.
+ if $opt_dry_run; then
+ # Extract subdirectory from the argument.
+ func_dirname "$arg" "/" ""
+ xdir="$func_dirname_result"
+
+ func_lo2o "$arg"
+ pic_object=$xdir$objdir/$func_lo2o_result
+ non_pic_object=$xdir$func_lo2o_result
+ func_append libobjs " $pic_object"
+ func_append non_pic_objects " $non_pic_object"
+ else
+ func_fatal_error "\`$arg' is not a valid libtool object"
+ fi
+ fi
+ ;;
+
+ *.$libext)
+ # An archive.
+ deplibs="$deplibs $arg"
+ old_deplibs="$old_deplibs $arg"
+ continue
+ ;;
+
+ *.la)
+ # A libtool-controlled library.
+
+ if test "$prev" = dlfiles; then
+ # This library was specified with -dlopen.
+ dlfiles="$dlfiles $arg"
+ prev=
+ elif test "$prev" = dlprefiles; then
+ # The library was specified with -dlpreopen.
+ dlprefiles="$dlprefiles $arg"
+ prev=
+ else
+ deplibs="$deplibs $arg"
+ fi
+ continue
+ ;;
+
+ # Some other compiler argument.
+ *)
+ # Unknown arguments in both finalize_command and compile_command need
+ # to be aesthetically quoted because they are evaled later.
+ func_quote_for_eval "$arg"
+ arg="$func_quote_for_eval_result"
+ ;;
+ esac # arg
+
+ # Now actually substitute the argument into the commands.
+ if test -n "$arg"; then
+ func_append compile_command " $arg"
+ func_append finalize_command " $arg"
+ fi
+ done # argument parsing loop
+
+ test -n "$prev" && \
+ func_fatal_help "the \`$prevarg' option requires an argument"
+
+ if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then
+ eval arg=\"$export_dynamic_flag_spec\"
+ func_append compile_command " $arg"
+ func_append finalize_command " $arg"
+ fi
+
+ oldlibs=
+ # calculate the name of the file, without its directory
+ func_basename "$output"
+ outputname="$func_basename_result"
+ libobjs_save="$libobjs"
+
+ if test -n "$shlibpath_var"; then
+ # get the directories listed in $shlibpath_var
+ eval shlib_search_path=\`\$ECHO \"X\${$shlibpath_var}\" \| \$Xsed -e \'s/:/ /g\'\`
+ else
+ shlib_search_path=
+ fi
+ eval sys_lib_search_path=\"$sys_lib_search_path_spec\"
+ eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\"
+
+ func_dirname "$output" "/" ""
+ output_objdir="$func_dirname_result$objdir"
+ # Create the object directory.
+ func_mkdir_p "$output_objdir"
+
+ # Determine the type of output
+ case $output in
+ "")
+ func_fatal_help "you must specify an output file"
+ ;;
+ *.$libext) linkmode=oldlib ;;
+ *.lo | *.$objext) linkmode=obj ;;
+ *.la) linkmode=lib ;;
+ *) linkmode=prog ;; # Anything else should be a program.
+ esac
+
+ specialdeplibs=
+
+ libs=
+ # Find all interdependent deplibs by searching for libraries
+ # that are linked more than once (e.g. -la -lb -la)
+ for deplib in $deplibs; do
+ if $opt_duplicate_deps ; then
+ case "$libs " in
+ *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+ esac
+ fi
+ libs="$libs $deplib"
+ done
+
+ if test "$linkmode" = lib; then
+ libs="$predeps $libs $compiler_lib_search_path $postdeps"
+
+ # Compute libraries that are listed more than once in $predeps
+ # $postdeps and mark them as special (i.e., whose duplicates are
+ # not to be eliminated).
+ pre_post_deps=
+ if $opt_duplicate_compiler_generated_deps; then
+ for pre_post_dep in $predeps $postdeps; do
+ case "$pre_post_deps " in
+ *" $pre_post_dep "*) specialdeplibs="$specialdeplibs $pre_post_deps" ;;
+ esac
+ pre_post_deps="$pre_post_deps $pre_post_dep"
+ done
+ fi
+ pre_post_deps=
+ fi
+
+ deplibs=
+ newdependency_libs=
+ newlib_search_path=
+ need_relink=no # whether we're linking any uninstalled libtool libraries
+ notinst_deplibs= # not-installed libtool libraries
+ notinst_path= # paths that contain not-installed libtool libraries
+
+ case $linkmode in
+ lib)
+ passes="conv dlpreopen link"
+ for file in $dlfiles $dlprefiles; do
+ case $file in
+ *.la) ;;
+ *)
+ func_fatal_help "libraries can \`-dlopen' only libtool libraries: $file"
+ ;;
+ esac
+ done
+ ;;
+ prog)
+ compile_deplibs=
+ finalize_deplibs=
+ alldeplibs=no
+ newdlfiles=
+ newdlprefiles=
+ passes="conv scan dlopen dlpreopen link"
+ ;;
+ *) passes="conv"
+ ;;
+ esac
+
+ for pass in $passes; do
+ # The preopen pass in lib mode reverses $deplibs; put it back here
+ # so that -L comes before libs that need it for instance...
+ if test "$linkmode,$pass" = "lib,link"; then
+ ## FIXME: Find the place where the list is rebuilt in the wrong
+ ## order, and fix it there properly
+ tmp_deplibs=
+ for deplib in $deplibs; do
+ tmp_deplibs="$deplib $tmp_deplibs"
+ done
+ deplibs="$tmp_deplibs"
+ fi
+
+ if test "$linkmode,$pass" = "lib,link" ||
+ test "$linkmode,$pass" = "prog,scan"; then
+ libs="$deplibs"
+ deplibs=
+ fi
+ if test "$linkmode" = prog; then
+ case $pass in
+ dlopen) libs="$dlfiles" ;;
+ dlpreopen) libs="$dlprefiles" ;;
+ link)
+ libs="$deplibs %DEPLIBS%"
+ test "X$link_all_deplibs" != Xno && libs="$libs $dependency_libs"
+ ;;
+ esac
+ fi
+ if test "$linkmode,$pass" = "lib,dlpreopen"; then
+ # Collect and forward deplibs of preopened libtool libs
+ for lib in $dlprefiles; do
+ # Ignore non-libtool-libs
+ dependency_libs=
+ case $lib in
+ *.la) func_source "$lib" ;;
+ esac
+
+ # Collect preopened libtool deplibs, except any this library
+ # has declared as weak libs
+ for deplib in $dependency_libs; do
+ deplib_base=`$ECHO "X$deplib" | $Xsed -e "$basename"`
+ case " $weak_libs " in
+ *" $deplib_base "*) ;;
+ *) deplibs="$deplibs $deplib" ;;
+ esac
+ done
+ done
+ libs="$dlprefiles"
+ fi
+ if test "$pass" = dlopen; then
+ # Collect dlpreopened libraries
+ save_deplibs="$deplibs"
+ deplibs=
+ fi
+
+ for deplib in $libs; do
+ lib=
+ found=no
+ case $deplib in
+ -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe|-threads)
+ if test "$linkmode,$pass" = "prog,link"; then
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ else
+ compiler_flags="$compiler_flags $deplib"
+ if test "$linkmode" = lib ; then
+ case "$new_inherited_linker_flags " in
+ *" $deplib "*) ;;
+ * ) new_inherited_linker_flags="$new_inherited_linker_flags $deplib" ;;
+ esac
+ fi
+ fi
+ continue
+ ;;
+ -l*)
+ if test "$linkmode" != lib && test "$linkmode" != prog; then
+ func_warning "\`-l' is ignored for archives/objects"
+ continue
+ fi
+ func_stripname '-l' '' "$deplib"
+ name=$func_stripname_result
+ if test "$linkmode" = lib; then
+ searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path"
+ else
+ searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path"
+ fi
+ for searchdir in $searchdirs; do
+ for search_ext in .la $std_shrext .so .a; do
+ # Search the libtool library
+ lib="$searchdir/lib${name}${search_ext}"
+ if test -f "$lib"; then
+ if test "$search_ext" = ".la"; then
+ found=yes
+ else
+ found=no
+ fi
+ break 2
+ fi
+ done
+ done
+ if test "$found" != yes; then
+ # deplib doesn't seem to be a libtool library
+ if test "$linkmode,$pass" = "prog,link"; then
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ else
+ deplibs="$deplib $deplibs"
+ test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs"
+ fi
+ continue
+ else # deplib is a libtool library
+ # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib,
+ # We need to do some special things here, and not later.
+ if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+ case " $predeps $postdeps " in
+ *" $deplib "*)
+ if func_lalib_p "$lib"; then
+ library_names=
+ old_library=
+ func_source "$lib"
+ for l in $old_library $library_names; do
+ ll="$l"
+ done
+ if test "X$ll" = "X$old_library" ; then # only static version available
+ found=no
+ func_dirname "$lib" "" "."
+ ladir="$func_dirname_result"
+ lib=$ladir/$old_library
+ if test "$linkmode,$pass" = "prog,link"; then
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ else
+ deplibs="$deplib $deplibs"
+ test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs"
+ fi
+ continue
+ fi
+ fi
+ ;;
+ *) ;;
+ esac
+ fi
+ fi
+ ;; # -l
+ *.ltframework)
+ if test "$linkmode,$pass" = "prog,link"; then
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ else
+ deplibs="$deplib $deplibs"
+ if test "$linkmode" = lib ; then
+ case "$new_inherited_linker_flags " in
+ *" $deplib "*) ;;
+ * ) new_inherited_linker_flags="$new_inherited_linker_flags $deplib" ;;
+ esac
+ fi
+ fi
+ continue
+ ;;
+ -L*)
+ case $linkmode in
+ lib)
+ deplibs="$deplib $deplibs"
+ test "$pass" = conv && continue
+ newdependency_libs="$deplib $newdependency_libs"
+ func_stripname '-L' '' "$deplib"
+ newlib_search_path="$newlib_search_path $func_stripname_result"
+ ;;
+ prog)
+ if test "$pass" = conv; then
+ deplibs="$deplib $deplibs"
+ continue
+ fi
+ if test "$pass" = scan; then
+ deplibs="$deplib $deplibs"
+ else
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ fi
+ func_stripname '-L' '' "$deplib"
+ newlib_search_path="$newlib_search_path $func_stripname_result"
+ ;;
+ *)
+ func_warning "\`-L' is ignored for archives/objects"
+ ;;
+ esac # linkmode
+ continue
+ ;; # -L
+ -R*)
+ if test "$pass" = link; then
+ func_stripname '-R' '' "$deplib"
+ dir=$func_stripname_result
+ # Make sure the xrpath contains only unique directories.
+ case "$xrpath " in
+ *" $dir "*) ;;
+ *) xrpath="$xrpath $dir" ;;
+ esac
+ fi
+ deplibs="$deplib $deplibs"
+ continue
+ ;;
+ *.la) lib="$deplib" ;;
+ *.$libext)
+ if test "$pass" = conv; then
+ deplibs="$deplib $deplibs"
+ continue
+ fi
+ case $linkmode in
+ lib)
+ # Linking convenience modules into shared libraries is allowed,
+ # but linking other static libraries is non-portable.
+ case " $dlpreconveniencelibs " in
+ *" $deplib "*) ;;
+ *)
+ valid_a_lib=no
+ case $deplibs_check_method in
+ match_pattern*)
+ set dummy $deplibs_check_method; shift
+ match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"`
+ if eval "\$ECHO \"X$deplib\"" 2>/dev/null | $Xsed -e 10q \
+ | $EGREP "$match_pattern_regex" > /dev/null; then
+ valid_a_lib=yes
+ fi
+ ;;
+ pass_all)
+ valid_a_lib=yes
+ ;;
+ esac
+ if test "$valid_a_lib" != yes; then
+ $ECHO
+ $ECHO "*** Warning: Trying to link with static lib archive $deplib."
+ $ECHO "*** I have the capability to make that library automatically link in when"
+ $ECHO "*** you link to this library. But I can only do this if you have a"
+ $ECHO "*** shared version of the library, which you do not appear to have"
+ $ECHO "*** because the file extensions .$libext of this argument makes me believe"
+ $ECHO "*** that it is just a static archive that I should not use here."
+ else
+ $ECHO
+ $ECHO "*** Warning: Linking the shared library $output against the"
+ $ECHO "*** static library $deplib is not portable!"
+ deplibs="$deplib $deplibs"
+ fi
+ ;;
+ esac
+ continue
+ ;;
+ prog)
+ if test "$pass" != link; then
+ deplibs="$deplib $deplibs"
+ else
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ fi
+ continue
+ ;;
+ esac # linkmode
+ ;; # *.$libext
+ *.lo | *.$objext)
+ if test "$pass" = conv; then
+ deplibs="$deplib $deplibs"
+ elif test "$linkmode" = prog; then
+ if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then
+ # If there is no dlopen support or we're linking statically,
+ # we need to preload.
+ newdlprefiles="$newdlprefiles $deplib"
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ else
+ newdlfiles="$newdlfiles $deplib"
+ fi
+ fi
+ continue
+ ;;
+ %DEPLIBS%)
+ alldeplibs=yes
+ continue
+ ;;
+ esac # case $deplib
+
+ if test "$found" = yes || test -f "$lib"; then :
+ else
+ func_fatal_error "cannot find the library \`$lib' or unhandled argument \`$deplib'"
+ fi
+
+ # Check to see that this really is a libtool archive.
+ func_lalib_unsafe_p "$lib" \
+ || func_fatal_error "\`$lib' is not a valid libtool archive"
+
+ func_dirname "$lib" "" "."
+ ladir="$func_dirname_result"
+
+ dlname=
+ dlopen=
+ dlpreopen=
+ libdir=
+ library_names=
+ old_library=
+ inherited_linker_flags=
+ # If the library was installed with an old release of libtool,
+ # it will not redefine variables installed, or shouldnotlink
+ installed=yes
+ shouldnotlink=no
+ avoidtemprpath=
+
+
+ # Read the .la file
+ func_source "$lib"
+
+ # Convert "-framework foo" to "foo.ltframework"
+ if test -n "$inherited_linker_flags"; then
+ tmp_inherited_linker_flags=`$ECHO "X$inherited_linker_flags" | $Xsed -e 's/-framework \([^ $]*\)/\1.ltframework/g'`
+ for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do
+ case " $new_inherited_linker_flags " in
+ *" $tmp_inherited_linker_flag "*) ;;
+ *) new_inherited_linker_flags="$new_inherited_linker_flags $tmp_inherited_linker_flag";;
+ esac
+ done
+ fi
+ dependency_libs=`$ECHO "X $dependency_libs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'`
+ if test "$linkmode,$pass" = "lib,link" ||
+ test "$linkmode,$pass" = "prog,scan" ||
+ { test "$linkmode" != prog && test "$linkmode" != lib; }; then
+ test -n "$dlopen" && dlfiles="$dlfiles $dlopen"
+ test -n "$dlpreopen" && dlprefiles="$dlprefiles $dlpreopen"
+ fi
+
+ if test "$pass" = conv; then
+ # Only check for convenience libraries
+ deplibs="$lib $deplibs"
+ if test -z "$libdir"; then
+ if test -z "$old_library"; then
+ func_fatal_error "cannot find name of link library for \`$lib'"
+ fi
+ # It is a libtool convenience library, so add in its objects.
+ convenience="$convenience $ladir/$objdir/$old_library"
+ old_convenience="$old_convenience $ladir/$objdir/$old_library"
+ tmp_libs=
+ for deplib in $dependency_libs; do
+ deplibs="$deplib $deplibs"
+ if $opt_duplicate_deps ; then
+ case "$tmp_libs " in
+ *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+ esac
+ fi
+ tmp_libs="$tmp_libs $deplib"
+ done
+ elif test "$linkmode" != prog && test "$linkmode" != lib; then
+ func_fatal_error "\`$lib' is not a convenience library"
+ fi
+ continue
+ fi # $pass = conv
+
+
+ # Get the name of the library we link against.
+ linklib=
+ for l in $old_library $library_names; do
+ linklib="$l"
+ done
+ if test -z "$linklib"; then
+ func_fatal_error "cannot find name of link library for \`$lib'"
+ fi
+
+ # This library was specified with -dlopen.
+ if test "$pass" = dlopen; then
+ if test -z "$libdir"; then
+ func_fatal_error "cannot -dlopen a convenience library: \`$lib'"
+ fi
+ if test -z "$dlname" ||
+ test "$dlopen_support" != yes ||
+ test "$build_libtool_libs" = no; then
+ # If there is no dlname, no dlopen support or we're linking
+ # statically, we need to preload. We also need to preload any
+ # dependent libraries so libltdl's deplib preloader doesn't
+ # bomb out in the load deplibs phase.
+ dlprefiles="$dlprefiles $lib $dependency_libs"
+ else
+ newdlfiles="$newdlfiles $lib"
+ fi
+ continue
+ fi # $pass = dlopen
+
+ # We need an absolute path.
+ case $ladir in
+ [\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;;
+ *)
+ abs_ladir=`cd "$ladir" && pwd`
+ if test -z "$abs_ladir"; then
+ func_warning "cannot determine absolute directory name of \`$ladir'"
+ func_warning "passing it literally to the linker, although it might fail"
+ abs_ladir="$ladir"
+ fi
+ ;;
+ esac
+ func_basename "$lib"
+ laname="$func_basename_result"
+
+ # Find the relevant object directory and library name.
+ if test "X$installed" = Xyes; then
+ if test ! -f "$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then
+ func_warning "library \`$lib' was moved."
+ dir="$ladir"
+ absdir="$abs_ladir"
+ libdir="$abs_ladir"
+ else
+ dir="$libdir"
+ absdir="$libdir"
+ fi
+ test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes
+ else
+ if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then
+ dir="$ladir"
+ absdir="$abs_ladir"
+ # Remove this search path later
+ notinst_path="$notinst_path $abs_ladir"
+ else
+ dir="$ladir/$objdir"
+ absdir="$abs_ladir/$objdir"
+ # Remove this search path later
+ notinst_path="$notinst_path $abs_ladir"
+ fi
+ fi # $installed = yes
+ func_stripname 'lib' '.la' "$laname"
+ name=$func_stripname_result
+
+ # This library was specified with -dlpreopen.
+ if test "$pass" = dlpreopen; then
+ if test -z "$libdir" && test "$linkmode" = prog; then
+ func_fatal_error "only libraries may -dlpreopen a convenience library: \`$lib'"
+ fi
+ # Prefer using a static library (so that no silly _DYNAMIC symbols
+ # are required to link).
+ if test -n "$old_library"; then
+ newdlprefiles="$newdlprefiles $dir/$old_library"
+ # Keep a list of preopened convenience libraries to check
+ # that they are being used correctly in the link pass.
+ test -z "$libdir" && \
+ dlpreconveniencelibs="$dlpreconveniencelibs $dir/$old_library"
+ # Otherwise, use the dlname, so that lt_dlopen finds it.
+ elif test -n "$dlname"; then
+ newdlprefiles="$newdlprefiles $dir/$dlname"
+ else
+ newdlprefiles="$newdlprefiles $dir/$linklib"
+ fi
+ fi # $pass = dlpreopen
+
+ if test -z "$libdir"; then
+ # Link the convenience library
+ if test "$linkmode" = lib; then
+ deplibs="$dir/$old_library $deplibs"
+ elif test "$linkmode,$pass" = "prog,link"; then
+ compile_deplibs="$dir/$old_library $compile_deplibs"
+ finalize_deplibs="$dir/$old_library $finalize_deplibs"
+ else
+ deplibs="$lib $deplibs" # used for prog,scan pass
+ fi
+ continue
+ fi
+
+
+ if test "$linkmode" = prog && test "$pass" != link; then
+ newlib_search_path="$newlib_search_path $ladir"
+ deplibs="$lib $deplibs"
+
+ linkalldeplibs=no
+ if test "$link_all_deplibs" != no || test -z "$library_names" ||
+ test "$build_libtool_libs" = no; then
+ linkalldeplibs=yes
+ fi
+
+ tmp_libs=
+ for deplib in $dependency_libs; do
+ case $deplib in
+ -L*) func_stripname '-L' '' "$deplib"
+ newlib_search_path="$newlib_search_path $func_stripname_result"
+ ;;
+ esac
+ # Need to link against all dependency_libs?
+ if test "$linkalldeplibs" = yes; then
+ deplibs="$deplib $deplibs"
+ else
+ # Need to hardcode shared library paths
+ # or/and link against static libraries
+ newdependency_libs="$deplib $newdependency_libs"
+ fi
+ if $opt_duplicate_deps ; then
+ case "$tmp_libs " in
+ *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+ esac
+ fi
+ tmp_libs="$tmp_libs $deplib"
+ done # for deplib
+ continue
+ fi # $linkmode = prog...
+
+ if test "$linkmode,$pass" = "prog,link"; then
+ if test -n "$library_names" &&
+ { { test "$prefer_static_libs" = no ||
+ test "$prefer_static_libs,$installed" = "built,yes"; } ||
+ test -z "$old_library"; }; then
+ # We need to hardcode the library path
+ if test -n "$shlibpath_var" && test -z "$avoidtemprpath" ; then
+ # Make sure the rpath contains only unique directories.
+ case "$temp_rpath:" in
+ *"$absdir:"*) ;;
+ *) temp_rpath="$temp_rpath$absdir:" ;;
+ esac
+ fi
+
+ # Hardcode the library path.
+ # Skip directories that are in the system default run-time
+ # search path.
+ case " $sys_lib_dlsearch_path " in
+ *" $absdir "*) ;;
+ *)
+ case "$compile_rpath " in
+ *" $absdir "*) ;;
+ *) compile_rpath="$compile_rpath $absdir"
+ esac
+ ;;
+ esac
+ case " $sys_lib_dlsearch_path " in
+ *" $libdir "*) ;;
+ *)
+ case "$finalize_rpath " in
+ *" $libdir "*) ;;
+ *) finalize_rpath="$finalize_rpath $libdir"
+ esac
+ ;;
+ esac
+ fi # $linkmode,$pass = prog,link...
+
+ if test "$alldeplibs" = yes &&
+ { test "$deplibs_check_method" = pass_all ||
+ { test "$build_libtool_libs" = yes &&
+ test -n "$library_names"; }; }; then
+ # We only need to search for static libraries
+ continue
+ fi
+ fi
+
+ link_static=no # Whether the deplib will be linked statically
+ use_static_libs=$prefer_static_libs
+ if test "$use_static_libs" = built && test "$installed" = yes; then
+ use_static_libs=no
+ fi
+ if test -n "$library_names" &&
+ { test "$use_static_libs" = no || test -z "$old_library"; }; then
+ case $host in
+ *cygwin* | *mingw* | *cegcc*)
+ # No point in relinking DLLs because paths are not encoded
+ notinst_deplibs="$notinst_deplibs $lib"
+ need_relink=no
+ ;;
+ *)
+ if test "$installed" = no; then
+ notinst_deplibs="$notinst_deplibs $lib"
+ need_relink=yes
+ fi
+ ;;
+ esac
+ # This is a shared library
+
+ # Warn about portability, can't link against -module's on some
+ # systems (darwin). Don't bleat about dlopened modules though!
+ dlopenmodule=""
+ for dlpremoduletest in $dlprefiles; do
+ if test "X$dlpremoduletest" = "X$lib"; then
+ dlopenmodule="$dlpremoduletest"
+ break
+ fi
+ done
+ if test -z "$dlopenmodule" && test "$shouldnotlink" = yes && test "$pass" = link; then
+ $ECHO
+ if test "$linkmode" = prog; then
+ $ECHO "*** Warning: Linking the executable $output against the loadable module"
+ else
+ $ECHO "*** Warning: Linking the shared library $output against the loadable module"
+ fi
+ $ECHO "*** $linklib is not portable!"
+ fi
+ if test "$linkmode" = lib &&
+ test "$hardcode_into_libs" = yes; then
+ # Hardcode the library path.
+ # Skip directories that are in the system default run-time
+ # search path.
+ case " $sys_lib_dlsearch_path " in
+ *" $absdir "*) ;;
+ *)
+ case "$compile_rpath " in
+ *" $absdir "*) ;;
+ *) compile_rpath="$compile_rpath $absdir"
+ esac
+ ;;
+ esac
+ case " $sys_lib_dlsearch_path " in
+ *" $libdir "*) ;;
+ *)
+ case "$finalize_rpath " in
+ *" $libdir "*) ;;
+ *) finalize_rpath="$finalize_rpath $libdir"
+ esac
+ ;;
+ esac
+ fi
+
+ if test -n "$old_archive_from_expsyms_cmds"; then
+ # figure out the soname
+ set dummy $library_names
+ shift
+ realname="$1"
+ shift
+ libname=`eval "\\$ECHO \"$libname_spec\""`
+ # use dlname if we got it. it's perfectly good, no?
+ if test -n "$dlname"; then
+ soname="$dlname"
+ elif test -n "$soname_spec"; then
+ # bleh windows
+ case $host in
+ *cygwin* | mingw* | *cegcc*)
+ func_arith $current - $age
+ major=$func_arith_result
+ versuffix="-$major"
+ ;;
+ esac
+ eval soname=\"$soname_spec\"
+ else
+ soname="$realname"
+ fi
+
+ # Make a new name for the extract_expsyms_cmds to use
+ soroot="$soname"
+ func_basename "$soroot"
+ soname="$func_basename_result"
+ func_stripname 'lib' '.dll' "$soname"
+ newlib=libimp-$func_stripname_result.a
+
+ # If the library has no export list, then create one now
+ if test -f "$output_objdir/$soname-def"; then :
+ else
+ func_verbose "extracting exported symbol list from \`$soname'"
+ func_execute_cmds "$extract_expsyms_cmds" 'exit $?'
+ fi
+
+ # Create $newlib
+ if test -f "$output_objdir/$newlib"; then :; else
+ func_verbose "generating import library for \`$soname'"
+ func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?'
+ fi
+ # make sure the library variables are pointing to the new library
+ dir=$output_objdir
+ linklib=$newlib
+ fi # test -n "$old_archive_from_expsyms_cmds"
+
+ if test "$linkmode" = prog || test "$mode" != relink; then
+ add_shlibpath=
+ add_dir=
+ add=
+ lib_linked=yes
+ case $hardcode_action in
+ immediate | unsupported)
+ if test "$hardcode_direct" = no; then
+ add="$dir/$linklib"
+ case $host in
+ *-*-sco3.2v5.0.[024]*) add_dir="-L$dir" ;;
+ *-*-sysv4*uw2*) add_dir="-L$dir" ;;
+ *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \
+ *-*-unixware7*) add_dir="-L$dir" ;;
+ *-*-darwin* )
+ # if the lib is a (non-dlopened) module then we can not
+ # link against it, someone is ignoring the earlier warnings
+ if /usr/bin/file -L $add 2> /dev/null |
+ $GREP ": [^:]* bundle" >/dev/null ; then
+ if test "X$dlopenmodule" != "X$lib"; then
+ $ECHO "*** Warning: lib $linklib is a module, not a shared library"
+ if test -z "$old_library" ; then
+ $ECHO
+ $ECHO "*** And there doesn't seem to be a static archive available"
+ $ECHO "*** The link will probably fail, sorry"
+ else
+ add="$dir/$old_library"
+ fi
+ elif test -n "$old_library"; then
+ add="$dir/$old_library"
+ fi
+ fi
+ esac
+ elif test "$hardcode_minus_L" = no; then
+ case $host in
+ *-*-sunos*) add_shlibpath="$dir" ;;
+ esac
+ add_dir="-L$dir"
+ add="-l$name"
+ elif test "$hardcode_shlibpath_var" = no; then
+ add_shlibpath="$dir"
+ add="-l$name"
+ else
+ lib_linked=no
+ fi
+ ;;
+ relink)
+ if test "$hardcode_direct" = yes &&
+ test "$hardcode_direct_absolute" = no; then
+ add="$dir/$linklib"
+ elif test "$hardcode_minus_L" = yes; then
+ add_dir="-L$dir"
+ # Try looking first in the location we're being installed to.
+ if test -n "$inst_prefix_dir"; then
+ case $libdir in
+ [\\/]*)
+ add_dir="$add_dir -L$inst_prefix_dir$libdir"
+ ;;
+ esac
+ fi
+ add="-l$name"
+ elif test "$hardcode_shlibpath_var" = yes; then
+ add_shlibpath="$dir"
+ add="-l$name"
+ else
+ lib_linked=no
+ fi
+ ;;
+ *) lib_linked=no ;;
+ esac
+
+ if test "$lib_linked" != yes; then
+ func_fatal_configuration "unsupported hardcode properties"
+ fi
+
+ if test -n "$add_shlibpath"; then
+ case :$compile_shlibpath: in
+ *":$add_shlibpath:"*) ;;
+ *) compile_shlibpath="$compile_shlibpath$add_shlibpath:" ;;
+ esac
+ fi
+ if test "$linkmode" = prog; then
+ test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs"
+ test -n "$add" && compile_deplibs="$add $compile_deplibs"
+ else
+ test -n "$add_dir" && deplibs="$add_dir $deplibs"
+ test -n "$add" && deplibs="$add $deplibs"
+ if test "$hardcode_direct" != yes &&
+ test "$hardcode_minus_L" != yes &&
+ test "$hardcode_shlibpath_var" = yes; then
+ case :$finalize_shlibpath: in
+ *":$libdir:"*) ;;
+ *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;;
+ esac
+ fi
+ fi
+ fi
+
+ if test "$linkmode" = prog || test "$mode" = relink; then
+ add_shlibpath=
+ add_dir=
+ add=
+ # Finalize command for both is simple: just hardcode it.
+ if test "$hardcode_direct" = yes &&
+ test "$hardcode_direct_absolute" = no; then
+ add="$libdir/$linklib"
+ elif test "$hardcode_minus_L" = yes; then
+ add_dir="-L$libdir"
+ add="-l$name"
+ elif test "$hardcode_shlibpath_var" = yes; then
+ case :$finalize_shlibpath: in
+ *":$libdir:"*) ;;
+ *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;;
+ esac
+ add="-l$name"
+ elif test "$hardcode_automatic" = yes; then
+ if test -n "$inst_prefix_dir" &&
+ test -f "$inst_prefix_dir$libdir/$linklib" ; then
+ add="$inst_prefix_dir$libdir/$linklib"
+ else
+ add="$libdir/$linklib"
+ fi
+ else
+ # We cannot seem to hardcode it, guess we'll fake it.
+ add_dir="-L$libdir"
+ # Try looking first in the location we're being installed to.
+ if test -n "$inst_prefix_dir"; then
+ case $libdir in
+ [\\/]*)
+ add_dir="$add_dir -L$inst_prefix_dir$libdir"
+ ;;
+ esac
+ fi
+ add="-l$name"
+ fi
+
+ if test "$linkmode" = prog; then
+ test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs"
+ test -n "$add" && finalize_deplibs="$add $finalize_deplibs"
+ else
+ test -n "$add_dir" && deplibs="$add_dir $deplibs"
+ test -n "$add" && deplibs="$add $deplibs"
+ fi
+ fi
+ elif test "$linkmode" = prog; then
+ # Here we assume that one of hardcode_direct or hardcode_minus_L
+ # is not unsupported. This is valid on all known static and
+ # shared platforms.
+ if test "$hardcode_direct" != unsupported; then
+ test -n "$old_library" && linklib="$old_library"
+ compile_deplibs="$dir/$linklib $compile_deplibs"
+ finalize_deplibs="$dir/$linklib $finalize_deplibs"
+ else
+ compile_deplibs="-l$name -L$dir $compile_deplibs"
+ finalize_deplibs="-l$name -L$dir $finalize_deplibs"
+ fi
+ elif test "$build_libtool_libs" = yes; then
+ # Not a shared library
+ if test "$deplibs_check_method" != pass_all; then
+ # We're trying link a shared library against a static one
+ # but the system doesn't support it.
+
+ # Just print a warning and add the library to dependency_libs so
+ # that the program can be linked against the static library.
+ $ECHO
+ $ECHO "*** Warning: This system can not link to static lib archive $lib."
+ $ECHO "*** I have the capability to make that library automatically link in when"
+ $ECHO "*** you link to this library. But I can only do this if you have a"
+ $ECHO "*** shared version of the library, which you do not appear to have."
+ if test "$module" = yes; then
+ $ECHO "*** But as you try to build a module library, libtool will still create "
+ $ECHO "*** a static module, that should work as long as the dlopening application"
+ $ECHO "*** is linked with the -dlopen flag to resolve symbols at runtime."
+ if test -z "$global_symbol_pipe"; then
+ $ECHO
+ $ECHO "*** However, this would only work if libtool was able to extract symbol"
+ $ECHO "*** lists from a program, using \`nm' or equivalent, but libtool could"
+ $ECHO "*** not find such a program. So, this module is probably useless."
+ $ECHO "*** \`nm' from GNU binutils and a full rebuild may help."
+ fi
+ if test "$build_old_libs" = no; then
+ build_libtool_libs=module
+ build_old_libs=yes
+ else
+ build_libtool_libs=no
+ fi
+ fi
+ else
+ deplibs="$dir/$old_library $deplibs"
+ link_static=yes
+ fi
+ fi # link shared/static library?
+
+ if test "$linkmode" = lib; then
+ if test -n "$dependency_libs" &&
+ { test "$hardcode_into_libs" != yes ||
+ test "$build_old_libs" = yes ||
+ test "$link_static" = yes; }; then
+ # Extract -R from dependency_libs
+ temp_deplibs=
+ for libdir in $dependency_libs; do
+ case $libdir in
+ -R*) func_stripname '-R' '' "$libdir"
+ temp_xrpath=$func_stripname_result
+ case " $xrpath " in
+ *" $temp_xrpath "*) ;;
+ *) xrpath="$xrpath $temp_xrpath";;
+ esac;;
+ *) temp_deplibs="$temp_deplibs $libdir";;
+ esac
+ done
+ dependency_libs="$temp_deplibs"
+ fi
+
+ newlib_search_path="$newlib_search_path $absdir"
+ # Link against this library
+ test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs"
+ # ... and its dependency_libs
+ tmp_libs=
+ for deplib in $dependency_libs; do
+ newdependency_libs="$deplib $newdependency_libs"
+ if $opt_duplicate_deps ; then
+ case "$tmp_libs " in
+ *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+ esac
+ fi
+ tmp_libs="$tmp_libs $deplib"
+ done
+
+ if test "$link_all_deplibs" != no; then
+ # Add the search paths of all dependency libraries
+ for deplib in $dependency_libs; do
+ path=
+ case $deplib in
+ -L*) path="$deplib" ;;
+ *.la)
+ func_dirname "$deplib" "" "."
+ dir="$func_dirname_result"
+ # We need an absolute path.
+ case $dir in
+ [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;;
+ *)
+ absdir=`cd "$dir" && pwd`
+ if test -z "$absdir"; then
+ func_warning "cannot determine absolute directory name of \`$dir'"
+ absdir="$dir"
+ fi
+ ;;
+ esac
+ if $GREP "^installed=no" $deplib > /dev/null; then
+ case $host in
+ *-*-darwin*)
+ depdepl=
+ eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib`
+ if test -n "$deplibrary_names" ; then
+ for tmp in $deplibrary_names ; do
+ depdepl=$tmp
+ done
+ if test -f "$absdir/$objdir/$depdepl" ; then
+ depdepl="$absdir/$objdir/$depdepl"
+ darwin_install_name=`${OTOOL} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'`
+ if test -z "$darwin_install_name"; then
+ darwin_install_name=`${OTOOL64} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'`
+ fi
+ compiler_flags="$compiler_flags ${wl}-dylib_file ${wl}${darwin_install_name}:${depdepl}"
+ linker_flags="$linker_flags -dylib_file ${darwin_install_name}:${depdepl}"
+ path=
+ fi
+ fi
+ ;;
+ *)
+ path="-L$absdir/$objdir"
+ ;;
+ esac
+ else
+ eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib`
+ test -z "$libdir" && \
+ func_fatal_error "\`$deplib' is not a valid libtool archive"
+ test "$absdir" != "$libdir" && \
+ func_warning "\`$deplib' seems to be moved"
+
+ path="-L$absdir"
+ fi
+ ;;
+ esac
+ case " $deplibs " in
+ *" $path "*) ;;
+ *) deplibs="$path $deplibs" ;;
+ esac
+ done
+ fi # link_all_deplibs != no
+ fi # linkmode = lib
+ done # for deplib in $libs
+ if test "$pass" = link; then
+ if test "$linkmode" = "prog"; then
+ compile_deplibs="$new_inherited_linker_flags $compile_deplibs"
+ finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs"
+ else
+ compiler_flags="$compiler_flags "`$ECHO "X $new_inherited_linker_flags" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'`
+ fi
+ fi
+ dependency_libs="$newdependency_libs"
+ if test "$pass" = dlpreopen; then
+ # Link the dlpreopened libraries before other libraries
+ for deplib in $save_deplibs; do
+ deplibs="$deplib $deplibs"
+ done
+ fi
+ if test "$pass" != dlopen; then
+ if test "$pass" != conv; then
+ # Make sure lib_search_path contains only unique directories.
+ lib_search_path=
+ for dir in $newlib_search_path; do
+ case "$lib_search_path " in
+ *" $dir "*) ;;
+ *) lib_search_path="$lib_search_path $dir" ;;
+ esac
+ done
+ newlib_search_path=
+ fi
+
+ if test "$linkmode,$pass" != "prog,link"; then
+ vars="deplibs"
+ else
+ vars="compile_deplibs finalize_deplibs"
+ fi
+ for var in $vars dependency_libs; do
+ # Add libraries to $var in reverse order
+ eval tmp_libs=\"\$$var\"
+ new_libs=
+ for deplib in $tmp_libs; do
+ # FIXME: Pedantically, this is the right thing to do, so
+ # that some nasty dependency loop isn't accidentally
+ # broken:
+ #new_libs="$deplib $new_libs"
+ # Pragmatically, this seems to cause very few problems in
+ # practice:
+ case $deplib in
+ -L*) new_libs="$deplib $new_libs" ;;
+ -R*) ;;
+ *)
+ # And here is the reason: when a library appears more
+ # than once as an explicit dependence of a library, or
+ # is implicitly linked in more than once by the
+ # compiler, it is considered special, and multiple
+ # occurrences thereof are not removed. Compare this
+ # with having the same library being listed as a
+ # dependency of multiple other libraries: in this case,
+ # we know (pedantically, we assume) the library does not
+ # need to be listed more than once, so we keep only the
+ # last copy. This is not always right, but it is rare
+ # enough that we require users that really mean to play
+ # such unportable linking tricks to link the library
+ # using -Wl,-lname, so that libtool does not consider it
+ # for duplicate removal.
+ case " $specialdeplibs " in
+ *" $deplib "*) new_libs="$deplib $new_libs" ;;
+ *)
+ case " $new_libs " in
+ *" $deplib "*) ;;
+ *) new_libs="$deplib $new_libs" ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ done
+ tmp_libs=
+ for deplib in $new_libs; do
+ case $deplib in
+ -L*)
+ case " $tmp_libs " in
+ *" $deplib "*) ;;
+ *) tmp_libs="$tmp_libs $deplib" ;;
+ esac
+ ;;
+ *) tmp_libs="$tmp_libs $deplib" ;;
+ esac
+ done
+ eval $var=\"$tmp_libs\"
+ done # for var
+ fi
+ # Last step: remove runtime libs from dependency_libs
+ # (they stay in deplibs)
+ tmp_libs=
+ for i in $dependency_libs ; do
+ case " $predeps $postdeps $compiler_lib_search_path " in
+ *" $i "*)
+ i=""
+ ;;
+ esac
+ if test -n "$i" ; then
+ tmp_libs="$tmp_libs $i"
+ fi
+ done
+ dependency_libs=$tmp_libs
+ done # for pass
+ if test "$linkmode" = prog; then
+ dlfiles="$newdlfiles"
+ fi
+ if test "$linkmode" = prog || test "$linkmode" = lib; then
+ dlprefiles="$newdlprefiles"
+ fi
+
+ case $linkmode in
+ oldlib)
+ if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
+ func_warning "\`-dlopen' is ignored for archives"
+ fi
+
+ case " $deplibs" in
+ *\ -l* | *\ -L*)
+ func_warning "\`-l' and \`-L' are ignored for archives" ;;
+ esac
+
+ test -n "$rpath" && \
+ func_warning "\`-rpath' is ignored for archives"
+
+ test -n "$xrpath" && \
+ func_warning "\`-R' is ignored for archives"
+
+ test -n "$vinfo" && \
+ func_warning "\`-version-info/-version-number' is ignored for archives"
+
+ test -n "$release" && \
+ func_warning "\`-release' is ignored for archives"
+
+ test -n "$export_symbols$export_symbols_regex" && \
+ func_warning "\`-export-symbols' is ignored for archives"
+
+ # Now set the variables for building old libraries.
+ build_libtool_libs=no
+ oldlibs="$output"
+ objs="$objs$old_deplibs"
+ ;;
+
+ lib)
+ # Make sure we only generate libraries of the form `libNAME.la'.
+ case $outputname in
+ lib*)
+ func_stripname 'lib' '.la' "$outputname"
+ name=$func_stripname_result
+ eval shared_ext=\"$shrext_cmds\"
+ eval libname=\"$libname_spec\"
+ ;;
+ *)
+ test "$module" = no && \
+ func_fatal_help "libtool library \`$output' must begin with \`lib'"
+
+ if test "$need_lib_prefix" != no; then
+ # Add the "lib" prefix for modules if required
+ func_stripname '' '.la' "$outputname"
+ name=$func_stripname_result
+ eval shared_ext=\"$shrext_cmds\"
+ eval libname=\"$libname_spec\"
+ else
+ func_stripname '' '.la' "$outputname"
+ libname=$func_stripname_result
+ fi
+ ;;
+ esac
+
+ if test -n "$objs"; then
+ if test "$deplibs_check_method" != pass_all; then
+ func_fatal_error "cannot build libtool library \`$output' from non-libtool objects on this host:$objs"
+ else
+ $ECHO
+ $ECHO "*** Warning: Linking the shared library $output against the non-libtool"
+ $ECHO "*** objects $objs is not portable!"
+ libobjs="$libobjs $objs"
+ fi
+ fi
+
+ test "$dlself" != no && \
+ func_warning "\`-dlopen self' is ignored for libtool libraries"
+
+ set dummy $rpath
+ shift
+ test "$#" -gt 1 && \
+ func_warning "ignoring multiple \`-rpath's for a libtool library"
+
+ install_libdir="$1"
+
+ oldlibs=
+ if test -z "$rpath"; then
+ if test "$build_libtool_libs" = yes; then
+ # Building a libtool convenience library.
+ # Some compilers have problems with a `.al' extension so
+ # convenience libraries should have the same extension an
+ # archive normally would.
+ oldlibs="$output_objdir/$libname.$libext $oldlibs"
+ build_libtool_libs=convenience
+ build_old_libs=yes
+ fi
+
+ test -n "$vinfo" && \
+ func_warning "\`-version-info/-version-number' is ignored for convenience libraries"
+
+ test -n "$release" && \
+ func_warning "\`-release' is ignored for convenience libraries"
+ else
+
+ # Parse the version information argument.
+ save_ifs="$IFS"; IFS=':'
+ set dummy $vinfo 0 0 0
+ shift
+ IFS="$save_ifs"
+
+ test -n "$7" && \
+ func_fatal_help "too many parameters to \`-version-info'"
+
+ # convert absolute version numbers to libtool ages
+ # this retains compatibility with .la files and attempts
+ # to make the code below a bit more comprehensible
+
+ case $vinfo_number in
+ yes)
+ number_major="$1"
+ number_minor="$2"
+ number_revision="$3"
+ #
+ # There are really only two kinds -- those that
+ # use the current revision as the major version
+ # and those that subtract age and use age as
+ # a minor version. But, then there is irix
+ # which has an extra 1 added just for fun
+ #
+ case $version_type in
+ darwin|linux|osf|windows|none)
+ func_arith $number_major + $number_minor
+ current=$func_arith_result
+ age="$number_minor"
+ revision="$number_revision"
+ ;;
+ freebsd-aout|freebsd-elf|sunos)
+ current="$number_major"
+ revision="$number_minor"
+ age="0"
+ ;;
+ irix|nonstopux)
+ func_arith $number_major + $number_minor
+ current=$func_arith_result
+ age="$number_minor"
+ revision="$number_minor"
+ lt_irix_increment=no
+ ;;
+ *)
+ func_fatal_configuration "$modename: unknown library version type \`$version_type'"
+ ;;
+ esac
+ ;;
+ no)
+ current="$1"
+ revision="$2"
+ age="$3"
+ ;;
+ esac
+
+ # Check that each of the things are valid numbers.
+ case $current in
+ 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
+ *)
+ func_error "CURRENT \`$current' must be a nonnegative integer"
+ func_fatal_error "\`$vinfo' is not valid version information"
+ ;;
+ esac
+
+ case $revision in
+ 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
+ *)
+ func_error "REVISION \`$revision' must be a nonnegative integer"
+ func_fatal_error "\`$vinfo' is not valid version information"
+ ;;
+ esac
+
+ case $age in
+ 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
+ *)
+ func_error "AGE \`$age' must be a nonnegative integer"
+ func_fatal_error "\`$vinfo' is not valid version information"
+ ;;
+ esac
+
+ if test "$age" -gt "$current"; then
+ func_error "AGE \`$age' is greater than the current interface number \`$current'"
+ func_fatal_error "\`$vinfo' is not valid version information"
+ fi
+
+ # Calculate the version variables.
+ major=
+ versuffix=
+ verstring=
+ case $version_type in
+ none) ;;
+
+ darwin)
+ # Like Linux, but with the current version available in
+ # verstring for coding it into the library header
+ func_arith $current - $age
+ major=.$func_arith_result
+ versuffix="$major.$age.$revision"
+ # Darwin ld doesn't like 0 for these options...
+ func_arith $current + 1
+ minor_current=$func_arith_result
+ xlcverstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision"
+ verstring="-compatibility_version $minor_current -current_version $minor_current.$revision"
+ ;;
+
+ freebsd-aout)
+ major=".$current"
+ versuffix=".$current.$revision";
+ ;;
+
+ freebsd-elf)
+ major=".$current"
+ versuffix=".$current"
+ ;;
+
+ irix | nonstopux)
+ if test "X$lt_irix_increment" = "Xno"; then
+ func_arith $current - $age
+ else
+ func_arith $current - $age + 1
+ fi
+ major=$func_arith_result
+
+ case $version_type in
+ nonstopux) verstring_prefix=nonstopux ;;
+ *) verstring_prefix=sgi ;;
+ esac
+ verstring="$verstring_prefix$major.$revision"
+
+ # Add in all the interfaces that we are compatible with.
+ loop=$revision
+ while test "$loop" -ne 0; do
+ func_arith $revision - $loop
+ iface=$func_arith_result
+ func_arith $loop - 1
+ loop=$func_arith_result
+ verstring="$verstring_prefix$major.$iface:$verstring"
+ done
+
+ # Before this point, $major must not contain `.'.
+ major=.$major
+ versuffix="$major.$revision"
+ ;;
+
+ linux)
+ func_arith $current - $age
+ major=.$func_arith_result
+ versuffix="$major.$age.$revision"
+ ;;
+
+ osf)
+ func_arith $current - $age
+ major=.$func_arith_result
+ versuffix=".$current.$age.$revision"
+ verstring="$current.$age.$revision"
+
+ # Add in all the interfaces that we are compatible with.
+ loop=$age
+ while test "$loop" -ne 0; do
+ func_arith $current - $loop
+ iface=$func_arith_result
+ func_arith $loop - 1
+ loop=$func_arith_result
+ verstring="$verstring:${iface}.0"
+ done
+
+ # Make executables depend on our current version.
+ verstring="$verstring:${current}.0"
+ ;;
+
+ qnx)
+ major=".$current"
+ versuffix=".$current"
+ ;;
+
+ sunos)
+ major=".$current"
+ versuffix=".$current.$revision"
+ ;;
+
+ windows)
+ # Use '-' rather than '.', since we only want one
+ # extension on DOS 8.3 filesystems.
+ func_arith $current - $age
+ major=$func_arith_result
+ versuffix="-$major"
+ ;;
+
+ *)
+ func_fatal_configuration "unknown library version type \`$version_type'"
+ ;;
+ esac
+
+ # Clear the version info if we defaulted, and they specified a release.
+ if test -z "$vinfo" && test -n "$release"; then
+ major=
+ case $version_type in
+ darwin)
+ # we can't check for "0.0" in archive_cmds due to quoting
+ # problems, so we reset it completely
+ verstring=
+ ;;
+ *)
+ verstring="0.0"
+ ;;
+ esac
+ if test "$need_version" = no; then
+ versuffix=
+ else
+ versuffix=".0.0"
+ fi
+ fi
+
+ # Remove version info from name if versioning should be avoided
+ if test "$avoid_version" = yes && test "$need_version" = no; then
+ major=
+ versuffix=
+ verstring=""
+ fi
+
+ # Check to see if the archive will have undefined symbols.
+ if test "$allow_undefined" = yes; then
+ if test "$allow_undefined_flag" = unsupported; then
+ func_warning "undefined symbols not allowed in $host shared libraries"
+ build_libtool_libs=no
+ build_old_libs=yes
+ fi
+ else
+ # Don't allow undefined symbols.
+ allow_undefined_flag="$no_undefined_flag"
+ fi
+
+ fi
+
+ func_generate_dlsyms "$libname" "$libname" "yes"
+ libobjs="$libobjs $symfileobj"
+ test "X$libobjs" = "X " && libobjs=
+
+ if test "$mode" != relink; then
+ # Remove our outputs, but don't remove object files since they
+ # may have been created when compiling PIC objects.
+ removelist=
+ tempremovelist=`$ECHO "$output_objdir/*"`
+ for p in $tempremovelist; do
+ case $p in
+ *.$objext | *.gcno)
+ ;;
+ $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*)
+ if test "X$precious_files_regex" != "X"; then
+ if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1
+ then
+ continue
+ fi
+ fi
+ removelist="$removelist $p"
+ ;;
+ *) ;;
+ esac
+ done
+ test -n "$removelist" && \
+ func_show_eval "${RM}r \$removelist"
+ fi
+
+ # Now set the variables for building old libraries.
+ if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then
+ oldlibs="$oldlibs $output_objdir/$libname.$libext"
+
+ # Transform .lo files to .o files.
+ oldobjs="$objs "`$ECHO "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e "$lo2o" | $NL2SP`
+ fi
+
+ # Eliminate all temporary directories.
+ #for path in $notinst_path; do
+ # lib_search_path=`$ECHO "X$lib_search_path " | $Xsed -e "s% $path % %g"`
+ # deplibs=`$ECHO "X$deplibs " | $Xsed -e "s% -L$path % %g"`
+ # dependency_libs=`$ECHO "X$dependency_libs " | $Xsed -e "s% -L$path % %g"`
+ #done
+
+ if test -n "$xrpath"; then
+ # If the user specified any rpath flags, then add them.
+ temp_xrpath=
+ for libdir in $xrpath; do
+ temp_xrpath="$temp_xrpath -R$libdir"
+ case "$finalize_rpath " in
+ *" $libdir "*) ;;
+ *) finalize_rpath="$finalize_rpath $libdir" ;;
+ esac
+ done
+ if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then
+ dependency_libs="$temp_xrpath $dependency_libs"
+ fi
+ fi
+
+ # Make sure dlfiles contains only unique files that won't be dlpreopened
+ old_dlfiles="$dlfiles"
+ dlfiles=
+ for lib in $old_dlfiles; do
+ case " $dlprefiles $dlfiles " in
+ *" $lib "*) ;;
+ *) dlfiles="$dlfiles $lib" ;;
+ esac
+ done
+
+ # Make sure dlprefiles contains only unique files
+ old_dlprefiles="$dlprefiles"
+ dlprefiles=
+ for lib in $old_dlprefiles; do
+ case "$dlprefiles " in
+ *" $lib "*) ;;
+ *) dlprefiles="$dlprefiles $lib" ;;
+ esac
+ done
+
+ if test "$build_libtool_libs" = yes; then
+ if test -n "$rpath"; then
+ case $host in
+ *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc*)
+ # these systems don't actually have a c library (as such)!
+ ;;
+ *-*-rhapsody* | *-*-darwin1.[012])
+ # Rhapsody C library is in the System framework
+ deplibs="$deplibs System.ltframework"
+ ;;
+ *-*-netbsd*)
+ # Don't link with libc until the a.out ld.so is fixed.
+ ;;
+ *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
+ # Do not include libc due to us having libc/libc_r.
+ ;;
+ *-*-sco3.2v5* | *-*-sco5v6*)
+ # Causes problems with __ctype
+ ;;
+ *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*)
+ # Compiler inserts libc in the correct place for threads to work
+ ;;
+ *)
+ # Add libc to deplibs on all other systems if necessary.
+ if test "$build_libtool_need_lc" = "yes"; then
+ deplibs="$deplibs -lc"
+ fi
+ ;;
+ esac
+ fi
+
+ # Transform deplibs into only deplibs that can be linked in shared.
+ name_save=$name
+ libname_save=$libname
+ release_save=$release
+ versuffix_save=$versuffix
+ major_save=$major
+ # I'm not sure if I'm treating the release correctly. I think
+ # release should show up in the -l (ie -lgmp5) so we don't want to
+ # add it in twice. Is that correct?
+ release=""
+ versuffix=""
+ major=""
+ newdeplibs=
+ droppeddeps=no
+ case $deplibs_check_method in
+ pass_all)
+ # Don't check for shared/static. Everything works.
+ # This might be a little naive. We might want to check
+ # whether the library exists or not. But this is on
+ # osf3 & osf4 and I'm not really sure... Just
+ # implementing what was already the behavior.
+ newdeplibs=$deplibs
+ ;;
+ test_compile)
+ # This code stresses the "libraries are programs" paradigm to its
+ # limits. Maybe even breaks it. We compile a program, linking it
+ # against the deplibs as a proxy for the library. Then we can check
+ # whether they linked in statically or dynamically with ldd.
+ $opt_dry_run || $RM conftest.c
+ cat > conftest.c <<EOF
+ int main() { return 0; }
+EOF
+ $opt_dry_run || $RM conftest
+ if $LTCC $LTCFLAGS -o conftest conftest.c $deplibs; then
+ ldd_output=`ldd conftest`
+ for i in $deplibs; do
+ case $i in
+ -l*)
+ func_stripname -l '' "$i"
+ name=$func_stripname_result
+ if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+ case " $predeps $postdeps " in
+ *" $i "*)
+ newdeplibs="$newdeplibs $i"
+ i=""
+ ;;
+ esac
+ fi
+ if test -n "$i" ; then
+ libname=`eval "\\$ECHO \"$libname_spec\""`
+ deplib_matches=`eval "\\$ECHO \"$library_names_spec\""`
+ set dummy $deplib_matches; shift
+ deplib_match=$1
+ if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
+ newdeplibs="$newdeplibs $i"
+ else
+ droppeddeps=yes
+ $ECHO
+ $ECHO "*** Warning: dynamic linker does not accept needed library $i."
+ $ECHO "*** I have the capability to make that library automatically link in when"
+ $ECHO "*** you link to this library. But I can only do this if you have a"
+ $ECHO "*** shared version of the library, which I believe you do not have"
+ $ECHO "*** because a test_compile did reveal that the linker did not use it for"
+ $ECHO "*** its dynamic dependency list that programs get resolved with at runtime."
+ fi
+ fi
+ ;;
+ *)
+ newdeplibs="$newdeplibs $i"
+ ;;
+ esac
+ done
+ else
+ # Error occurred in the first compile. Let's try to salvage
+ # the situation: Compile a separate program for each library.
+ for i in $deplibs; do
+ case $i in
+ -l*)
+ func_stripname -l '' "$i"
+ name=$func_stripname_result
+ $opt_dry_run || $RM conftest
+ if $LTCC $LTCFLAGS -o conftest conftest.c $i; then
+ ldd_output=`ldd conftest`
+ if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+ case " $predeps $postdeps " in
+ *" $i "*)
+ newdeplibs="$newdeplibs $i"
+ i=""
+ ;;
+ esac
+ fi
+ if test -n "$i" ; then
+ libname=`eval "\\$ECHO \"$libname_spec\""`
+ deplib_matches=`eval "\\$ECHO \"$library_names_spec\""`
+ set dummy $deplib_matches; shift
+ deplib_match=$1
+ if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
+ newdeplibs="$newdeplibs $i"
+ else
+ droppeddeps=yes
+ $ECHO
+ $ECHO "*** Warning: dynamic linker does not accept needed library $i."
+ $ECHO "*** I have the capability to make that library automatically link in when"
+ $ECHO "*** you link to this library. But I can only do this if you have a"
+ $ECHO "*** shared version of the library, which you do not appear to have"
+ $ECHO "*** because a test_compile did reveal that the linker did not use this one"
+ $ECHO "*** as a dynamic dependency that programs can get resolved with at runtime."
+ fi
+ fi
+ else
+ droppeddeps=yes
+ $ECHO
+ $ECHO "*** Warning! Library $i is needed by this library but I was not able to"
+ $ECHO "*** make it link in! You will probably need to install it or some"
+ $ECHO "*** library that it depends on before this library will be fully"
+ $ECHO "*** functional. Installing it before continuing would be even better."
+ fi
+ ;;
+ *)
+ newdeplibs="$newdeplibs $i"
+ ;;
+ esac
+ done
+ fi
+ ;;
+ file_magic*)
+ set dummy $deplibs_check_method; shift
+ file_magic_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"`
+ for a_deplib in $deplibs; do
+ case $a_deplib in
+ -l*)
+ func_stripname -l '' "$a_deplib"
+ name=$func_stripname_result
+ if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+ case " $predeps $postdeps " in
+ *" $a_deplib "*)
+ newdeplibs="$newdeplibs $a_deplib"
+ a_deplib=""
+ ;;
+ esac
+ fi
+ if test -n "$a_deplib" ; then
+ libname=`eval "\\$ECHO \"$libname_spec\""`
+ for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do
+ potential_libs=`ls $i/$libname[.-]* 2>/dev/null`
+ for potent_lib in $potential_libs; do
+ # Follow soft links.
+ if ls -lLd "$potent_lib" 2>/dev/null |
+ $GREP " -> " >/dev/null; then
+ continue
+ fi
+ # The statement above tries to avoid entering an
+ # endless loop below, in case of cyclic links.
+ # We might still enter an endless loop, since a link
+ # loop can be closed while we follow links,
+ # but so what?
+ potlib="$potent_lib"
+ while test -h "$potlib" 2>/dev/null; do
+ potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'`
+ case $potliblink in
+ [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";;
+ *) potlib=`$ECHO "X$potlib" | $Xsed -e 's,[^/]*$,,'`"$potliblink";;
+ esac
+ done
+ if eval $file_magic_cmd \"\$potlib\" 2>/dev/null |
+ $SED -e 10q |
+ $EGREP "$file_magic_regex" > /dev/null; then
+ newdeplibs="$newdeplibs $a_deplib"
+ a_deplib=""
+ break 2
+ fi
+ done
+ done
+ fi
+ if test -n "$a_deplib" ; then
+ droppeddeps=yes
+ $ECHO
+ $ECHO "*** Warning: linker path does not have real file for library $a_deplib."
+ $ECHO "*** I have the capability to make that library automatically link in when"
+ $ECHO "*** you link to this library. But I can only do this if you have a"
+ $ECHO "*** shared version of the library, which you do not appear to have"
+ $ECHO "*** because I did check the linker path looking for a file starting"
+ if test -z "$potlib" ; then
+ $ECHO "*** with $libname but no candidates were found. (...for file magic test)"
+ else
+ $ECHO "*** with $libname and none of the candidates passed a file format test"
+ $ECHO "*** using a file magic. Last file checked: $potlib"
+ fi
+ fi
+ ;;
+ *)
+ # Add a -L argument.
+ newdeplibs="$newdeplibs $a_deplib"
+ ;;
+ esac
+ done # Gone through all deplibs.
+ ;;
+ match_pattern*)
+ set dummy $deplibs_check_method; shift
+ match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"`
+ for a_deplib in $deplibs; do
+ case $a_deplib in
+ -l*)
+ func_stripname -l '' "$a_deplib"
+ name=$func_stripname_result
+ if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+ case " $predeps $postdeps " in
+ *" $a_deplib "*)
+ newdeplibs="$newdeplibs $a_deplib"
+ a_deplib=""
+ ;;
+ esac
+ fi
+ if test -n "$a_deplib" ; then
+ libname=`eval "\\$ECHO \"$libname_spec\""`
+ for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do
+ potential_libs=`ls $i/$libname[.-]* 2>/dev/null`
+ for potent_lib in $potential_libs; do
+ potlib="$potent_lib" # see symlink-check above in file_magic test
+ if eval "\$ECHO \"X$potent_lib\"" 2>/dev/null | $Xsed -e 10q | \
+ $EGREP "$match_pattern_regex" > /dev/null; then
+ newdeplibs="$newdeplibs $a_deplib"
+ a_deplib=""
+ break 2
+ fi
+ done
+ done
+ fi
+ if test -n "$a_deplib" ; then
+ droppeddeps=yes
+ $ECHO
+ $ECHO "*** Warning: linker path does not have real file for library $a_deplib."
+ $ECHO "*** I have the capability to make that library automatically link in when"
+ $ECHO "*** you link to this library. But I can only do this if you have a"
+ $ECHO "*** shared version of the library, which you do not appear to have"
+ $ECHO "*** because I did check the linker path looking for a file starting"
+ if test -z "$potlib" ; then
+ $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)"
+ else
+ $ECHO "*** with $libname and none of the candidates passed a file format test"
+ $ECHO "*** using a regex pattern. Last file checked: $potlib"
+ fi
+ fi
+ ;;
+ *)
+ # Add a -L argument.
+ newdeplibs="$newdeplibs $a_deplib"
+ ;;
+ esac
+ done # Gone through all deplibs.
+ ;;
+ none | unknown | *)
+ newdeplibs=""
+ tmp_deplibs=`$ECHO "X $deplibs" | $Xsed \
+ -e 's/ -lc$//' -e 's/ -[LR][^ ]*//g'`
+ if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+ for i in $predeps $postdeps ; do
+ # can't use Xsed below, because $i might contain '/'
+ tmp_deplibs=`$ECHO "X $tmp_deplibs" | $Xsed -e "s,$i,,"`
+ done
+ fi
+ if $ECHO "X $tmp_deplibs" | $Xsed -e 's/[ ]//g' |
+ $GREP . >/dev/null; then
+ $ECHO
+ if test "X$deplibs_check_method" = "Xnone"; then
+ $ECHO "*** Warning: inter-library dependencies are not supported in this platform."
+ else
+ $ECHO "*** Warning: inter-library dependencies are not known to be supported."
+ fi
+ $ECHO "*** All declared inter-library dependencies are being dropped."
+ droppeddeps=yes
+ fi
+ ;;
+ esac
+ versuffix=$versuffix_save
+ major=$major_save
+ release=$release_save
+ libname=$libname_save
+ name=$name_save
+
+ case $host in
+ *-*-rhapsody* | *-*-darwin1.[012])
+ # On Rhapsody replace the C library with the System framework
+ newdeplibs=`$ECHO "X $newdeplibs" | $Xsed -e 's/ -lc / System.ltframework /'`
+ ;;
+ esac
+
+ if test "$droppeddeps" = yes; then
+ if test "$module" = yes; then
+ $ECHO
+ $ECHO "*** Warning: libtool could not satisfy all declared inter-library"
+ $ECHO "*** dependencies of module $libname. Therefore, libtool will create"
+ $ECHO "*** a static module, that should work as long as the dlopening"
+ $ECHO "*** application is linked with the -dlopen flag."
+ if test -z "$global_symbol_pipe"; then
+ $ECHO
+ $ECHO "*** However, this would only work if libtool was able to extract symbol"
+ $ECHO "*** lists from a program, using \`nm' or equivalent, but libtool could"
+ $ECHO "*** not find such a program. So, this module is probably useless."
+ $ECHO "*** \`nm' from GNU binutils and a full rebuild may help."
+ fi
+ if test "$build_old_libs" = no; then
+ oldlibs="$output_objdir/$libname.$libext"
+ build_libtool_libs=module
+ build_old_libs=yes
+ else
+ build_libtool_libs=no
+ fi
+ else
+ $ECHO "*** The inter-library dependencies that have been dropped here will be"
+ $ECHO "*** automatically added whenever a program is linked with this library"
+ $ECHO "*** or is declared to -dlopen it."
+
+ if test "$allow_undefined" = no; then
+ $ECHO
+ $ECHO "*** Since this library must not contain undefined symbols,"
+ $ECHO "*** because either the platform does not support them or"
+ $ECHO "*** it was explicitly requested with -no-undefined,"
+ $ECHO "*** libtool will only create a static version of it."
+ if test "$build_old_libs" = no; then
+ oldlibs="$output_objdir/$libname.$libext"
+ build_libtool_libs=module
+ build_old_libs=yes
+ else
+ build_libtool_libs=no
+ fi
+ fi
+ fi
+ fi
+ # Done checking deplibs!
+ deplibs=$newdeplibs
+ fi
+ # Time to change all our "foo.ltframework" stuff back to "-framework foo"
+ case $host in
+ *-*-darwin*)
+ newdeplibs=`$ECHO "X $newdeplibs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'`
+ new_inherited_linker_flags=`$ECHO "X $new_inherited_linker_flags" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'`
+ deplibs=`$ECHO "X $deplibs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'`
+ ;;
+ esac
+
+ # move library search paths that coincide with paths to not yet
+ # installed libraries to the beginning of the library search list
+ new_libs=
+ for path in $notinst_path; do
+ case " $new_libs " in
+ *" -L$path/$objdir "*) ;;
+ *)
+ case " $deplibs " in
+ *" -L$path/$objdir "*)
+ new_libs="$new_libs -L$path/$objdir" ;;
+ esac
+ ;;
+ esac
+ done
+ for deplib in $deplibs; do
+ case $deplib in
+ -L*)
+ case " $new_libs " in
+ *" $deplib "*) ;;
+ *) new_libs="$new_libs $deplib" ;;
+ esac
+ ;;
+ *) new_libs="$new_libs $deplib" ;;
+ esac
+ done
+ deplibs="$new_libs"
+
+ # All the library-specific variables (install_libdir is set above).
+ library_names=
+ old_library=
+ dlname=
+
+ # Test again, we may have decided not to build it any more
+ if test "$build_libtool_libs" = yes; then
+ if test "$hardcode_into_libs" = yes; then
+ # Hardcode the library paths
+ hardcode_libdirs=
+ dep_rpath=
+ rpath="$finalize_rpath"
+ test "$mode" != relink && rpath="$compile_rpath$rpath"
+ for libdir in $rpath; do
+ if test -n "$hardcode_libdir_flag_spec"; then
+ if test -n "$hardcode_libdir_separator"; then
+ if test -z "$hardcode_libdirs"; then
+ hardcode_libdirs="$libdir"
+ else
+ # Just accumulate the unique libdirs.
+ case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
+ *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+ ;;
+ *)
+ hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
+ ;;
+ esac
+ fi
+ else
+ eval flag=\"$hardcode_libdir_flag_spec\"
+ dep_rpath="$dep_rpath $flag"
+ fi
+ elif test -n "$runpath_var"; then
+ case "$perm_rpath " in
+ *" $libdir "*) ;;
+ *) perm_rpath="$perm_rpath $libdir" ;;
+ esac
+ fi
+ done
+ # Substitute the hardcoded libdirs into the rpath.
+ if test -n "$hardcode_libdir_separator" &&
+ test -n "$hardcode_libdirs"; then
+ libdir="$hardcode_libdirs"
+ if test -n "$hardcode_libdir_flag_spec_ld"; then
+ eval dep_rpath=\"$hardcode_libdir_flag_spec_ld\"
+ else
+ eval dep_rpath=\"$hardcode_libdir_flag_spec\"
+ fi
+ fi
+ if test -n "$runpath_var" && test -n "$perm_rpath"; then
+ # We should set the runpath_var.
+ rpath=
+ for dir in $perm_rpath; do
+ rpath="$rpath$dir:"
+ done
+ eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var"
+ fi
+ test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs"
+ fi
+
+ shlibpath="$finalize_shlibpath"
+ test "$mode" != relink && shlibpath="$compile_shlibpath$shlibpath"
+ if test -n "$shlibpath"; then
+ eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var"
+ fi
+
+ # Get the real and link names of the library.
+ eval shared_ext=\"$shrext_cmds\"
+ eval library_names=\"$library_names_spec\"
+ set dummy $library_names
+ shift
+ realname="$1"
+ shift
+
+ if test -n "$soname_spec"; then
+ eval soname=\"$soname_spec\"
+ else
+ soname="$realname"
+ fi
+ if test -z "$dlname"; then
+ dlname=$soname
+ fi
+
+ lib="$output_objdir/$realname"
+ linknames=
+ for link
+ do
+ linknames="$linknames $link"
+ done
+
+ # Use standard objects if they are pic
+ test -z "$pic_flag" && libobjs=`$ECHO "X$libobjs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+ test "X$libobjs" = "X " && libobjs=
+
+ delfiles=
+ if test -n "$export_symbols" && test -n "$include_expsyms"; then
+ $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp"
+ export_symbols="$output_objdir/$libname.uexp"
+ delfiles="$delfiles $export_symbols"
+ fi
+
+ orig_export_symbols=
+ case $host_os in
+ cygwin* | mingw* | cegcc*)
+ if test -n "$export_symbols" && test -z "$export_symbols_regex"; then
+ # exporting using user supplied symfile
+ if test "x`$SED 1q $export_symbols`" != xEXPORTS; then
+ # and it's NOT already a .def file. Must figure out
+ # which of the given symbols are data symbols and tag
+ # them as such. So, trigger use of export_symbols_cmds.
+ # export_symbols gets reassigned inside the "prepare
+ # the list of exported symbols" if statement, so the
+ # include_expsyms logic still works.
+ orig_export_symbols="$export_symbols"
+ export_symbols=
+ always_export_symbols=yes
+ fi
+ fi
+ ;;
+ esac
+
+ # Prepare the list of exported symbols
+ if test -z "$export_symbols"; then
+ if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then
+ func_verbose "generating symbol list for \`$libname.la'"
+ export_symbols="$output_objdir/$libname.exp"
+ $opt_dry_run || $RM $export_symbols
+ cmds=$export_symbols_cmds
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ eval cmd=\"$cmd\"
+ func_len " $cmd"
+ len=$func_len_result
+ if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then
+ func_show_eval "$cmd" 'exit $?'
+ skipped_export=false
+ else
+ # The command line is too long to execute in one step.
+ func_verbose "using reloadable object file for export list..."
+ skipped_export=:
+ # Break out early, otherwise skipped_export may be
+ # set to false by a later but shorter cmd.
+ break
+ fi
+ done
+ IFS="$save_ifs"
+ if test -n "$export_symbols_regex" && test "X$skipped_export" != "X:"; then
+ func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"'
+ func_show_eval '$MV "${export_symbols}T" "$export_symbols"'
+ fi
+ fi
+ fi
+
+ if test -n "$export_symbols" && test -n "$include_expsyms"; then
+ tmp_export_symbols="$export_symbols"
+ test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols"
+ $opt_dry_run || eval '$ECHO "X$include_expsyms" | $Xsed | $SP2NL >> "$tmp_export_symbols"'
+ fi
+
+ if test "X$skipped_export" != "X:" && test -n "$orig_export_symbols"; then
+ # The given exports_symbols file has to be filtered, so filter it.
+ func_verbose "filter symbol list for \`$libname.la' to tag DATA exports"
+ # FIXME: $output_objdir/$libname.filter potentially contains lots of
+ # 's' commands which not all seds can handle. GNU sed should be fine
+ # though. Also, the filter scales superlinearly with the number of
+ # global variables. join(1) would be nice here, but unfortunately
+ # isn't a blessed tool.
+ $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter
+ delfiles="$delfiles $export_symbols $output_objdir/$libname.filter"
+ export_symbols=$output_objdir/$libname.def
+ $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols
+ fi
+
+ tmp_deplibs=
+ for test_deplib in $deplibs; do
+ case " $convenience " in
+ *" $test_deplib "*) ;;
+ *)
+ tmp_deplibs="$tmp_deplibs $test_deplib"
+ ;;
+ esac
+ done
+ deplibs="$tmp_deplibs"
+
+ if test -n "$convenience"; then
+ if test -n "$whole_archive_flag_spec" &&
+ test "$compiler_needs_object" = yes &&
+ test -z "$libobjs"; then
+ # extract the archives, so we have objects to list.
+ # TODO: could optimize this to just extract one archive.
+ whole_archive_flag_spec=
+ fi
+ if test -n "$whole_archive_flag_spec"; then
+ save_libobjs=$libobjs
+ eval libobjs=\"\$libobjs $whole_archive_flag_spec\"
+ test "X$libobjs" = "X " && libobjs=
+ else
+ gentop="$output_objdir/${outputname}x"
+ generated="$generated $gentop"
+
+ func_extract_archives $gentop $convenience
+ libobjs="$libobjs $func_extract_archives_result"
+ test "X$libobjs" = "X " && libobjs=
+ fi
+ fi
+
+ if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then
+ eval flag=\"$thread_safe_flag_spec\"
+ linker_flags="$linker_flags $flag"
+ fi
+
+ # Make a backup of the uninstalled library when relinking
+ if test "$mode" = relink; then
+ $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $?
+ fi
+
+ # Do each of the archive commands.
+ if test "$module" = yes && test -n "$module_cmds" ; then
+ if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then
+ eval test_cmds=\"$module_expsym_cmds\"
+ cmds=$module_expsym_cmds
+ else
+ eval test_cmds=\"$module_cmds\"
+ cmds=$module_cmds
+ fi
+ else
+ if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then
+ eval test_cmds=\"$archive_expsym_cmds\"
+ cmds=$archive_expsym_cmds
+ else
+ eval test_cmds=\"$archive_cmds\"
+ cmds=$archive_cmds
+ fi
+ fi
+
+ if test "X$skipped_export" != "X:" &&
+ func_len " $test_cmds" &&
+ len=$func_len_result &&
+ test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then
+ :
+ else
+ # The command line is too long to link in one step, link piecewise
+ # or, if using GNU ld and skipped_export is not :, use a linker
+ # script.
+
+ # Save the value of $output and $libobjs because we want to
+ # use them later. If we have whole_archive_flag_spec, we
+ # want to use save_libobjs as it was before
+ # whole_archive_flag_spec was expanded, because we can't
+ # assume the linker understands whole_archive_flag_spec.
+ # This may have to be revisited, in case too many
+ # convenience libraries get linked in and end up exceeding
+ # the spec.
+ if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then
+ save_libobjs=$libobjs
+ fi
+ save_output=$output
+ output_la=`$ECHO "X$output" | $Xsed -e "$basename"`
+
+ # Clear the reloadable object creation command queue and
+ # initialize k to one.
+ test_cmds=
+ concat_cmds=
+ objlist=
+ last_robj=
+ k=1
+
+ if test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "$with_gnu_ld" = yes; then
+ output=${output_objdir}/${output_la}.lnkscript
+ func_verbose "creating GNU ld script: $output"
+ $ECHO 'INPUT (' > $output
+ for obj in $save_libobjs
+ do
+ $ECHO "$obj" >> $output
+ done
+ $ECHO ')' >> $output
+ delfiles="$delfiles $output"
+ elif test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "X$file_list_spec" != X; then
+ output=${output_objdir}/${output_la}.lnk
+ func_verbose "creating linker input file list: $output"
+ : > $output
+ set x $save_libobjs
+ shift
+ firstobj=
+ if test "$compiler_needs_object" = yes; then
+ firstobj="$1 "
+ shift
+ fi
+ for obj
+ do
+ $ECHO "$obj" >> $output
+ done
+ delfiles="$delfiles $output"
+ output=$firstobj\"$file_list_spec$output\"
+ else
+ if test -n "$save_libobjs"; then
+ func_verbose "creating reloadable object files..."
+ output=$output_objdir/$output_la-${k}.$objext
+ eval test_cmds=\"$reload_cmds\"
+ func_len " $test_cmds"
+ len0=$func_len_result
+ len=$len0
+
+ # Loop over the list of objects to be linked.
+ for obj in $save_libobjs
+ do
+ func_len " $obj"
+ func_arith $len + $func_len_result
+ len=$func_arith_result
+ if test "X$objlist" = X ||
+ test "$len" -lt "$max_cmd_len"; then
+ func_append objlist " $obj"
+ else
+ # The command $test_cmds is almost too long, add a
+ # command to the queue.
+ if test "$k" -eq 1 ; then
+ # The first file doesn't have a previous command to add.
+ eval concat_cmds=\"$reload_cmds $objlist $last_robj\"
+ else
+ # All subsequent reloadable object files will link in
+ # the last one created.
+ eval concat_cmds=\"\$concat_cmds~$reload_cmds $objlist $last_robj~\$RM $last_robj\"
+ fi
+ last_robj=$output_objdir/$output_la-${k}.$objext
+ func_arith $k + 1
+ k=$func_arith_result
+ output=$output_objdir/$output_la-${k}.$objext
+ objlist=$obj
+ func_len " $last_robj"
+ func_arith $len0 + $func_len_result
+ len=$func_arith_result
+ fi
+ done
+ # Handle the remaining objects by creating one last
+ # reloadable object file. All subsequent reloadable object
+ # files will link in the last one created.
+ test -z "$concat_cmds" || concat_cmds=$concat_cmds~
+ eval concat_cmds=\"\${concat_cmds}$reload_cmds $objlist $last_robj\"
+ if test -n "$last_robj"; then
+ eval concat_cmds=\"\${concat_cmds}~\$RM $last_robj\"
+ fi
+ delfiles="$delfiles $output"
+
+ else
+ output=
+ fi
+
+ if ${skipped_export-false}; then
+ func_verbose "generating symbol list for \`$libname.la'"
+ export_symbols="$output_objdir/$libname.exp"
+ $opt_dry_run || $RM $export_symbols
+ libobjs=$output
+ # Append the command to create the export file.
+ test -z "$concat_cmds" || concat_cmds=$concat_cmds~
+ eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\"
+ if test -n "$last_robj"; then
+ eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\"
+ fi
+ fi
+
+ test -n "$save_libobjs" &&
+ func_verbose "creating a temporary reloadable object file: $output"
+
+ # Loop through the commands generated above and execute them.
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $concat_cmds; do
+ IFS="$save_ifs"
+ $opt_silent || {
+ func_quote_for_expand "$cmd"
+ eval "func_echo $func_quote_for_expand_result"
+ }
+ $opt_dry_run || eval "$cmd" || {
+ lt_exit=$?
+
+ # Restore the uninstalled library and exit
+ if test "$mode" = relink; then
+ ( cd "$output_objdir" && \
+ $RM "${realname}T" && \
+ $MV "${realname}U" "$realname" )
+ fi
+
+ exit $lt_exit
+ }
+ done
+ IFS="$save_ifs"
+
+ if test -n "$export_symbols_regex" && ${skipped_export-false}; then
+ func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"'
+ func_show_eval '$MV "${export_symbols}T" "$export_symbols"'
+ fi
+ fi
+
+ if ${skipped_export-false}; then
+ if test -n "$export_symbols" && test -n "$include_expsyms"; then
+ tmp_export_symbols="$export_symbols"
+ test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols"
+ $opt_dry_run || eval '$ECHO "X$include_expsyms" | $Xsed | $SP2NL >> "$tmp_export_symbols"'
+ fi
+
+ if test -n "$orig_export_symbols"; then
+ # The given exports_symbols file has to be filtered, so filter it.
+ func_verbose "filter symbol list for \`$libname.la' to tag DATA exports"
+ # FIXME: $output_objdir/$libname.filter potentially contains lots of
+ # 's' commands which not all seds can handle. GNU sed should be fine
+ # though. Also, the filter scales superlinearly with the number of
+ # global variables. join(1) would be nice here, but unfortunately
+ # isn't a blessed tool.
+ $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter
+ delfiles="$delfiles $export_symbols $output_objdir/$libname.filter"
+ export_symbols=$output_objdir/$libname.def
+ $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols
+ fi
+ fi
+
+ libobjs=$output
+ # Restore the value of output.
+ output=$save_output
+
+ if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then
+ eval libobjs=\"\$libobjs $whole_archive_flag_spec\"
+ test "X$libobjs" = "X " && libobjs=
+ fi
+ # Expand the library linking commands again to reset the
+ # value of $libobjs for piecewise linking.
+
+ # Do each of the archive commands.
+ if test "$module" = yes && test -n "$module_cmds" ; then
+ if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then
+ cmds=$module_expsym_cmds
+ else
+ cmds=$module_cmds
+ fi
+ else
+ if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then
+ cmds=$archive_expsym_cmds
+ else
+ cmds=$archive_cmds
+ fi
+ fi
+ fi
+
+ if test -n "$delfiles"; then
+ # Append the command to remove temporary files to $cmds.
+ eval cmds=\"\$cmds~\$RM $delfiles\"
+ fi
+
+ # Add any objects from preloaded convenience libraries
+ if test -n "$dlprefiles"; then
+ gentop="$output_objdir/${outputname}x"
+ generated="$generated $gentop"
+
+ func_extract_archives $gentop $dlprefiles
+ libobjs="$libobjs $func_extract_archives_result"
+ test "X$libobjs" = "X " && libobjs=
+ fi
+
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ eval cmd=\"$cmd\"
+ $opt_silent || {
+ func_quote_for_expand "$cmd"
+ eval "func_echo $func_quote_for_expand_result"
+ }
+ $opt_dry_run || eval "$cmd" || {
+ lt_exit=$?
+
+ # Restore the uninstalled library and exit
+ if test "$mode" = relink; then
+ ( cd "$output_objdir" && \
+ $RM "${realname}T" && \
+ $MV "${realname}U" "$realname" )
+ fi
+
+ exit $lt_exit
+ }
+ done
+ IFS="$save_ifs"
+
+ # Restore the uninstalled library and exit
+ if test "$mode" = relink; then
+ $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $?
+
+ if test -n "$convenience"; then
+ if test -z "$whole_archive_flag_spec"; then
+ func_show_eval '${RM}r "$gentop"'
+ fi
+ fi
+
+ exit $EXIT_SUCCESS
+ fi
+
+ # Create links to the real library.
+ for linkname in $linknames; do
+ if test "$realname" != "$linkname"; then
+ func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?'
+ fi
+ done
+
+ # If -module or -export-dynamic was specified, set the dlname.
+ if test "$module" = yes || test "$export_dynamic" = yes; then
+ # On all known operating systems, these are identical.
+ dlname="$soname"
+ fi
+ fi
+ ;;
+
+ obj)
+ if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
+ func_warning "\`-dlopen' is ignored for objects"
+ fi
+
+ case " $deplibs" in
+ *\ -l* | *\ -L*)
+ func_warning "\`-l' and \`-L' are ignored for objects" ;;
+ esac
+
+ test -n "$rpath" && \
+ func_warning "\`-rpath' is ignored for objects"
+
+ test -n "$xrpath" && \
+ func_warning "\`-R' is ignored for objects"
+
+ test -n "$vinfo" && \
+ func_warning "\`-version-info' is ignored for objects"
+
+ test -n "$release" && \
+ func_warning "\`-release' is ignored for objects"
+
+ case $output in
+ *.lo)
+ test -n "$objs$old_deplibs" && \
+ func_fatal_error "cannot build library object \`$output' from non-libtool objects"
+
+ libobj=$output
+ func_lo2o "$libobj"
+ obj=$func_lo2o_result
+ ;;
+ *)
+ libobj=
+ obj="$output"
+ ;;
+ esac
+
+ # Delete the old objects.
+ $opt_dry_run || $RM $obj $libobj
+
+ # Objects from convenience libraries. This assumes
+ # single-version convenience libraries. Whenever we create
+ # different ones for PIC/non-PIC, this we'll have to duplicate
+ # the extraction.
+ reload_conv_objs=
+ gentop=
+ # reload_cmds runs $LD directly, so let us get rid of
+ # -Wl from whole_archive_flag_spec and hope we can get by with
+ # turning comma into space..
+ wl=
+
+ if test -n "$convenience"; then
+ if test -n "$whole_archive_flag_spec"; then
+ eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\"
+ reload_conv_objs=$reload_objs\ `$ECHO "X$tmp_whole_archive_flags" | $Xsed -e 's|,| |g'`
+ else
+ gentop="$output_objdir/${obj}x"
+ generated="$generated $gentop"
+
+ func_extract_archives $gentop $convenience
+ reload_conv_objs="$reload_objs $func_extract_archives_result"
+ fi
+ fi
+
+ # Create the old-style object.
+ reload_objs="$objs$old_deplibs "`$ECHO "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}$'/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test
+
+ output="$obj"
+ func_execute_cmds "$reload_cmds" 'exit $?'
+
+ # Exit if we aren't doing a library object file.
+ if test -z "$libobj"; then
+ if test -n "$gentop"; then
+ func_show_eval '${RM}r "$gentop"'
+ fi
+
+ exit $EXIT_SUCCESS
+ fi
+
+ if test "$build_libtool_libs" != yes; then
+ if test -n "$gentop"; then
+ func_show_eval '${RM}r "$gentop"'
+ fi
+
+ # Create an invalid libtool object if no PIC, so that we don't
+ # accidentally link it into a program.
+ # $show "echo timestamp > $libobj"
+ # $opt_dry_run || eval "echo timestamp > $libobj" || exit $?
+ exit $EXIT_SUCCESS
+ fi
+
+ if test -n "$pic_flag" || test "$pic_mode" != default; then
+ # Only do commands if we really have different PIC objects.
+ reload_objs="$libobjs $reload_conv_objs"
+ output="$libobj"
+ func_execute_cmds "$reload_cmds" 'exit $?'
+ fi
+
+ if test -n "$gentop"; then
+ func_show_eval '${RM}r "$gentop"'
+ fi
+
+ exit $EXIT_SUCCESS
+ ;;
+
+ prog)
+ case $host in
+ *cygwin*) func_stripname '' '.exe' "$output"
+ output=$func_stripname_result.exe;;
+ esac
+ test -n "$vinfo" && \
+ func_warning "\`-version-info' is ignored for programs"
+
+ test -n "$release" && \
+ func_warning "\`-release' is ignored for programs"
+
+ test "$preload" = yes \
+ && test "$dlopen_support" = unknown \
+ && test "$dlopen_self" = unknown \
+ && test "$dlopen_self_static" = unknown && \
+ func_warning "\`LT_INIT([dlopen])' not used. Assuming no dlopen support."
+
+ case $host in
+ *-*-rhapsody* | *-*-darwin1.[012])
+ # On Rhapsody replace the C library is the System framework
+ compile_deplibs=`$ECHO "X $compile_deplibs" | $Xsed -e 's/ -lc / System.ltframework /'`
+ finalize_deplibs=`$ECHO "X $finalize_deplibs" | $Xsed -e 's/ -lc / System.ltframework /'`
+ ;;
+ esac
+
+ case $host in
+ *-*-darwin*)
+ # Don't allow lazy linking, it breaks C++ global constructors
+ # But is supposedly fixed on 10.4 or later (yay!).
+ if test "$tagname" = CXX ; then
+ case ${MACOSX_DEPLOYMENT_TARGET-10.0} in
+ 10.[0123])
+ compile_command="$compile_command ${wl}-bind_at_load"
+ finalize_command="$finalize_command ${wl}-bind_at_load"
+ ;;
+ esac
+ fi
+ # Time to change all our "foo.ltframework" stuff back to "-framework foo"
+ compile_deplibs=`$ECHO "X $compile_deplibs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'`
+ finalize_deplibs=`$ECHO "X $finalize_deplibs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'`
+ ;;
+ esac
+
+
+ # move library search paths that coincide with paths to not yet
+ # installed libraries to the beginning of the library search list
+ new_libs=
+ for path in $notinst_path; do
+ case " $new_libs " in
+ *" -L$path/$objdir "*) ;;
+ *)
+ case " $compile_deplibs " in
+ *" -L$path/$objdir "*)
+ new_libs="$new_libs -L$path/$objdir" ;;
+ esac
+ ;;
+ esac
+ done
+ for deplib in $compile_deplibs; do
+ case $deplib in
+ -L*)
+ case " $new_libs " in
+ *" $deplib "*) ;;
+ *) new_libs="$new_libs $deplib" ;;
+ esac
+ ;;
+ *) new_libs="$new_libs $deplib" ;;
+ esac
+ done
+ compile_deplibs="$new_libs"
+
+
+ compile_command="$compile_command $compile_deplibs"
+ finalize_command="$finalize_command $finalize_deplibs"
+
+ if test -n "$rpath$xrpath"; then
+ # If the user specified any rpath flags, then add them.
+ for libdir in $rpath $xrpath; do
+ # This is the magic to use -rpath.
+ case "$finalize_rpath " in
+ *" $libdir "*) ;;
+ *) finalize_rpath="$finalize_rpath $libdir" ;;
+ esac
+ done
+ fi
+
+ # Now hardcode the library paths
+ rpath=
+ hardcode_libdirs=
+ for libdir in $compile_rpath $finalize_rpath; do
+ if test -n "$hardcode_libdir_flag_spec"; then
+ if test -n "$hardcode_libdir_separator"; then
+ if test -z "$hardcode_libdirs"; then
+ hardcode_libdirs="$libdir"
+ else
+ # Just accumulate the unique libdirs.
+ case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
+ *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+ ;;
+ *)
+ hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
+ ;;
+ esac
+ fi
+ else
+ eval flag=\"$hardcode_libdir_flag_spec\"
+ rpath="$rpath $flag"
+ fi
+ elif test -n "$runpath_var"; then
+ case "$perm_rpath " in
+ *" $libdir "*) ;;
+ *) perm_rpath="$perm_rpath $libdir" ;;
+ esac
+ fi
+ case $host in
+ *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*)
+ testbindir=`${ECHO} "$libdir" | ${SED} -e 's*/lib$*/bin*'`
+ case :$dllsearchpath: in
+ *":$libdir:"*) ;;
+ ::) dllsearchpath=$libdir;;
+ *) dllsearchpath="$dllsearchpath:$libdir";;
+ esac
+ case :$dllsearchpath: in
+ *":$testbindir:"*) ;;
+ ::) dllsearchpath=$testbindir;;
+ *) dllsearchpath="$dllsearchpath:$testbindir";;
+ esac
+ ;;
+ esac
+ done
+ # Substitute the hardcoded libdirs into the rpath.
+ if test -n "$hardcode_libdir_separator" &&
+ test -n "$hardcode_libdirs"; then
+ libdir="$hardcode_libdirs"
+ eval rpath=\" $hardcode_libdir_flag_spec\"
+ fi
+ compile_rpath="$rpath"
+
+ rpath=
+ hardcode_libdirs=
+ for libdir in $finalize_rpath; do
+ if test -n "$hardcode_libdir_flag_spec"; then
+ if test -n "$hardcode_libdir_separator"; then
+ if test -z "$hardcode_libdirs"; then
+ hardcode_libdirs="$libdir"
+ else
+ # Just accumulate the unique libdirs.
+ case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
+ *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+ ;;
+ *)
+ hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
+ ;;
+ esac
+ fi
+ else
+ eval flag=\"$hardcode_libdir_flag_spec\"
+ rpath="$rpath $flag"
+ fi
+ elif test -n "$runpath_var"; then
+ case "$finalize_perm_rpath " in
+ *" $libdir "*) ;;
+ *) finalize_perm_rpath="$finalize_perm_rpath $libdir" ;;
+ esac
+ fi
+ done
+ # Substitute the hardcoded libdirs into the rpath.
+ if test -n "$hardcode_libdir_separator" &&
+ test -n "$hardcode_libdirs"; then
+ libdir="$hardcode_libdirs"
+ eval rpath=\" $hardcode_libdir_flag_spec\"
+ fi
+ finalize_rpath="$rpath"
+
+ if test -n "$libobjs" && test "$build_old_libs" = yes; then
+ # Transform all the library objects into standard objects.
+ compile_command=`$ECHO "X$compile_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+ finalize_command=`$ECHO "X$finalize_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+ fi
+
+ func_generate_dlsyms "$outputname" "@PROGRAM@" "no"
+
+ # template prelinking step
+ if test -n "$prelink_cmds"; then
+ func_execute_cmds "$prelink_cmds" 'exit $?'
+ fi
+
+ wrappers_required=yes
+ case $host in
+ *cygwin* | *mingw* )
+ if test "$build_libtool_libs" != yes; then
+ wrappers_required=no
+ fi
+ ;;
+ *cegcc)
+ # Disable wrappers for cegcc, we are cross compiling anyway.
+ wrappers_required=no
+ ;;
+ *)
+ if test "$need_relink" = no || test "$build_libtool_libs" != yes; then
+ wrappers_required=no
+ fi
+ ;;
+ esac
+ if test "$wrappers_required" = no; then
+ # Replace the output file specification.
+ compile_command=`$ECHO "X$compile_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'`
+ link_command="$compile_command$compile_rpath"
+
+ # We have no uninstalled library dependencies, so finalize right now.
+ exit_status=0
+ func_show_eval "$link_command" 'exit_status=$?'
+
+ # Delete the generated files.
+ if test -f "$output_objdir/${outputname}S.${objext}"; then
+ func_show_eval '$RM "$output_objdir/${outputname}S.${objext}"'
+ fi
+
+ exit $exit_status
+ fi
+
+ if test -n "$compile_shlibpath$finalize_shlibpath"; then
+ compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command"
+ fi
+ if test -n "$finalize_shlibpath"; then
+ finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command"
+ fi
+
+ compile_var=
+ finalize_var=
+ if test -n "$runpath_var"; then
+ if test -n "$perm_rpath"; then
+ # We should set the runpath_var.
+ rpath=
+ for dir in $perm_rpath; do
+ rpath="$rpath$dir:"
+ done
+ compile_var="$runpath_var=\"$rpath\$$runpath_var\" "
+ fi
+ if test -n "$finalize_perm_rpath"; then
+ # We should set the runpath_var.
+ rpath=
+ for dir in $finalize_perm_rpath; do
+ rpath="$rpath$dir:"
+ done
+ finalize_var="$runpath_var=\"$rpath\$$runpath_var\" "
+ fi
+ fi
+
+ if test "$no_install" = yes; then
+ # We don't need to create a wrapper script.
+ link_command="$compile_var$compile_command$compile_rpath"
+ # Replace the output file specification.
+ link_command=`$ECHO "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'`
+ # Delete the old output file.
+ $opt_dry_run || $RM $output
+ # Link the executable and exit
+ func_show_eval "$link_command" 'exit $?'
+ exit $EXIT_SUCCESS
+ fi
+
+ if test "$hardcode_action" = relink; then
+ # Fast installation is not supported
+ link_command="$compile_var$compile_command$compile_rpath"
+ relink_command="$finalize_var$finalize_command$finalize_rpath"
+
+ func_warning "this platform does not like uninstalled shared libraries"
+ func_warning "\`$output' will be relinked during installation"
+ else
+ if test "$fast_install" != no; then
+ link_command="$finalize_var$compile_command$finalize_rpath"
+ if test "$fast_install" = yes; then
+ relink_command=`$ECHO "X$compile_var$compile_command$compile_rpath" | $Xsed -e 's%@OUTPUT@%\$progdir/\$file%g'`
+ else
+ # fast_install is set to needless
+ relink_command=
+ fi
+ else
+ link_command="$compile_var$compile_command$compile_rpath"
+ relink_command="$finalize_var$finalize_command$finalize_rpath"
+ fi
+ fi
+
+ # Replace the output file specification.
+ link_command=`$ECHO "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'`
+
+ # Delete the old output files.
+ $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname
+
+ func_show_eval "$link_command" 'exit $?'
+
+ # Now create the wrapper script.
+ func_verbose "creating $output"
+
+ # Quote the relink command for shipping.
+ if test -n "$relink_command"; then
+ # Preserve any variables that may affect compiler behavior
+ for var in $variables_saved_for_relink; do
+ if eval test -z \"\${$var+set}\"; then
+ relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command"
+ elif eval var_value=\$$var; test -z "$var_value"; then
+ relink_command="$var=; export $var; $relink_command"
+ else
+ func_quote_for_eval "$var_value"
+ relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command"
+ fi
+ done
+ relink_command="(cd `pwd`; $relink_command)"
+ relink_command=`$ECHO "X$relink_command" | $Xsed -e "$sed_quote_subst"`
+ fi
+
+ # Quote $ECHO for shipping.
+ if test "X$ECHO" = "X$SHELL $progpath --fallback-echo"; then
+ case $progpath in
+ [\\/]* | [A-Za-z]:[\\/]*) qecho="$SHELL $progpath --fallback-echo";;
+ *) qecho="$SHELL `pwd`/$progpath --fallback-echo";;
+ esac
+ qecho=`$ECHO "X$qecho" | $Xsed -e "$sed_quote_subst"`
+ else
+ qecho=`$ECHO "X$ECHO" | $Xsed -e "$sed_quote_subst"`
+ fi
+
+ # Only actually do things if not in dry run mode.
+ $opt_dry_run || {
+ # win32 will think the script is a binary if it has
+ # a .exe suffix, so we strip it off here.
+ case $output in
+ *.exe) func_stripname '' '.exe' "$output"
+ output=$func_stripname_result ;;
+ esac
+ # test for cygwin because mv fails w/o .exe extensions
+ case $host in
+ *cygwin*)
+ exeext=.exe
+ func_stripname '' '.exe' "$outputname"
+ outputname=$func_stripname_result ;;
+ *) exeext= ;;
+ esac
+ case $host in
+ *cygwin* | *mingw* )
+ func_dirname_and_basename "$output" "" "."
+ output_name=$func_basename_result
+ output_path=$func_dirname_result
+ cwrappersource="$output_path/$objdir/lt-$output_name.c"
+ cwrapper="$output_path/$output_name.exe"
+ $RM $cwrappersource $cwrapper
+ trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15
+
+ func_emit_cwrapperexe_src > $cwrappersource
+
+ # The wrapper executable is built using the $host compiler,
+ # because it contains $host paths and files. If cross-
+ # compiling, it, like the target executable, must be
+ # executed on the $host or under an emulation environment.
+ $opt_dry_run || {
+ $LTCC $LTCFLAGS -o $cwrapper $cwrappersource
+ $STRIP $cwrapper
+ }
+
+ # Now, create the wrapper script for func_source use:
+ func_ltwrapper_scriptname $cwrapper
+ $RM $func_ltwrapper_scriptname_result
+ trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15
+ $opt_dry_run || {
+ # note: this script will not be executed, so do not chmod.
+ if test "x$build" = "x$host" ; then
+ $cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result
+ else
+ func_emit_wrapper no > $func_ltwrapper_scriptname_result
+ fi
+ }
+ ;;
+ * )
+ $RM $output
+ trap "$RM $output; exit $EXIT_FAILURE" 1 2 15
+
+ func_emit_wrapper no > $output
+ chmod +x $output
+ ;;
+ esac
+ }
+ exit $EXIT_SUCCESS
+ ;;
+ esac
+
+ # See if we need to build an old-fashioned archive.
+ for oldlib in $oldlibs; do
+
+ if test "$build_libtool_libs" = convenience; then
+ oldobjs="$libobjs_save $symfileobj"
+ addlibs="$convenience"
+ build_libtool_libs=no
+ else
+ if test "$build_libtool_libs" = module; then
+ oldobjs="$libobjs_save"
+ build_libtool_libs=no
+ else
+ oldobjs="$old_deplibs $non_pic_objects"
+ if test "$preload" = yes && test -f "$symfileobj"; then
+ oldobjs="$oldobjs $symfileobj"
+ fi
+ fi
+ addlibs="$old_convenience"
+ fi
+
+ if test -n "$addlibs"; then
+ gentop="$output_objdir/${outputname}x"
+ generated="$generated $gentop"
+
+ func_extract_archives $gentop $addlibs
+ oldobjs="$oldobjs $func_extract_archives_result"
+ fi
+
+ # Do each command in the archive commands.
+ if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then
+ cmds=$old_archive_from_new_cmds
+ else
+
+ # Add any objects from preloaded convenience libraries
+ if test -n "$dlprefiles"; then
+ gentop="$output_objdir/${outputname}x"
+ generated="$generated $gentop"
+
+ func_extract_archives $gentop $dlprefiles
+ oldobjs="$oldobjs $func_extract_archives_result"
+ fi
+
+ # POSIX demands no paths to be encoded in archives. We have
+ # to avoid creating archives with duplicate basenames if we
+ # might have to extract them afterwards, e.g., when creating a
+ # static archive out of a convenience library, or when linking
+ # the entirety of a libtool archive into another (currently
+ # not supported by libtool).
+ if (for obj in $oldobjs
+ do
+ func_basename "$obj"
+ $ECHO "$func_basename_result"
+ done | sort | sort -uc >/dev/null 2>&1); then
+ :
+ else
+ $ECHO "copying selected object files to avoid basename conflicts..."
+ gentop="$output_objdir/${outputname}x"
+ generated="$generated $gentop"
+ func_mkdir_p "$gentop"
+ save_oldobjs=$oldobjs
+ oldobjs=
+ counter=1
+ for obj in $save_oldobjs
+ do
+ func_basename "$obj"
+ objbase="$func_basename_result"
+ case " $oldobjs " in
+ " ") oldobjs=$obj ;;
+ *[\ /]"$objbase "*)
+ while :; do
+ # Make sure we don't pick an alternate name that also
+ # overlaps.
+ newobj=lt$counter-$objbase
+ func_arith $counter + 1
+ counter=$func_arith_result
+ case " $oldobjs " in
+ *[\ /]"$newobj "*) ;;
+ *) if test ! -f "$gentop/$newobj"; then break; fi ;;
+ esac
+ done
+ func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj"
+ oldobjs="$oldobjs $gentop/$newobj"
+ ;;
+ *) oldobjs="$oldobjs $obj" ;;
+ esac
+ done
+ fi
+ eval cmds=\"$old_archive_cmds\"
+
+ func_len " $cmds"
+ len=$func_len_result
+ if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then
+ cmds=$old_archive_cmds
+ else
+ # the command line is too long to link in one step, link in parts
+ func_verbose "using piecewise archive linking..."
+ save_RANLIB=$RANLIB
+ RANLIB=:
+ objlist=
+ concat_cmds=
+ save_oldobjs=$oldobjs
+ oldobjs=
+ # Is there a better way of finding the last object in the list?
+ for obj in $save_oldobjs
+ do
+ last_oldobj=$obj
+ done
+ eval test_cmds=\"$old_archive_cmds\"
+ func_len " $test_cmds"
+ len0=$func_len_result
+ len=$len0
+ for obj in $save_oldobjs
+ do
+ func_len " $obj"
+ func_arith $len + $func_len_result
+ len=$func_arith_result
+ func_append objlist " $obj"
+ if test "$len" -lt "$max_cmd_len"; then
+ :
+ else
+ # the above command should be used before it gets too long
+ oldobjs=$objlist
+ if test "$obj" = "$last_oldobj" ; then
+ RANLIB=$save_RANLIB
+ fi
+ test -z "$concat_cmds" || concat_cmds=$concat_cmds~
+ eval concat_cmds=\"\${concat_cmds}$old_archive_cmds\"
+ objlist=
+ len=$len0
+ fi
+ done
+ RANLIB=$save_RANLIB
+ oldobjs=$objlist
+ if test "X$oldobjs" = "X" ; then
+ eval cmds=\"\$concat_cmds\"
+ else
+ eval cmds=\"\$concat_cmds~\$old_archive_cmds\"
+ fi
+ fi
+ fi
+ func_execute_cmds "$cmds" 'exit $?'
+ done
+
+ test -n "$generated" && \
+ func_show_eval "${RM}r$generated"
+
+ # Now create the libtool archive.
+ case $output in
+ *.la)
+ old_library=
+ test "$build_old_libs" = yes && old_library="$libname.$libext"
+ func_verbose "creating $output"
+
+ # Preserve any variables that may affect compiler behavior
+ for var in $variables_saved_for_relink; do
+ if eval test -z \"\${$var+set}\"; then
+ relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command"
+ elif eval var_value=\$$var; test -z "$var_value"; then
+ relink_command="$var=; export $var; $relink_command"
+ else
+ func_quote_for_eval "$var_value"
+ relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command"
+ fi
+ done
+ # Quote the link command for shipping.
+ relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)"
+ relink_command=`$ECHO "X$relink_command" | $Xsed -e "$sed_quote_subst"`
+ if test "$hardcode_automatic" = yes ; then
+ relink_command=
+ fi
+
+ # Only create the output if not a dry run.
+ $opt_dry_run || {
+ for installed in no yes; do
+ if test "$installed" = yes; then
+ if test -z "$install_libdir"; then
+ break
+ fi
+ output="$output_objdir/$outputname"i
+ # Replace all uninstalled libtool libraries with the installed ones
+ newdependency_libs=
+ for deplib in $dependency_libs; do
+ case $deplib in
+ *.la)
+ func_basename "$deplib"
+ name="$func_basename_result"
+ eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib`
+ test -z "$libdir" && \
+ func_fatal_error "\`$deplib' is not a valid libtool archive"
+ newdependency_libs="$newdependency_libs $libdir/$name"
+ ;;
+ *) newdependency_libs="$newdependency_libs $deplib" ;;
+ esac
+ done
+ dependency_libs="$newdependency_libs"
+ newdlfiles=
+
+ for lib in $dlfiles; do
+ case $lib in
+ *.la)
+ func_basename "$lib"
+ name="$func_basename_result"
+ eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib`
+ test -z "$libdir" && \
+ func_fatal_error "\`$lib' is not a valid libtool archive"
+ newdlfiles="$newdlfiles $libdir/$name"
+ ;;
+ *) newdlfiles="$newdlfiles $lib" ;;
+ esac
+ done
+ dlfiles="$newdlfiles"
+ newdlprefiles=
+ for lib in $dlprefiles; do
+ case $lib in
+ *.la)
+ # Only pass preopened files to the pseudo-archive (for
+ # eventual linking with the app. that links it) if we
+ # didn't already link the preopened objects directly into
+ # the library:
+ func_basename "$lib"
+ name="$func_basename_result"
+ eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib`
+ test -z "$libdir" && \
+ func_fatal_error "\`$lib' is not a valid libtool archive"
+ newdlprefiles="$newdlprefiles $libdir/$name"
+ ;;
+ esac
+ done
+ dlprefiles="$newdlprefiles"
+ else
+ newdlfiles=
+ for lib in $dlfiles; do
+ case $lib in
+ [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;;
+ *) abs=`pwd`"/$lib" ;;
+ esac
+ newdlfiles="$newdlfiles $abs"
+ done
+ dlfiles="$newdlfiles"
+ newdlprefiles=
+ for lib in $dlprefiles; do
+ case $lib in
+ [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;;
+ *) abs=`pwd`"/$lib" ;;
+ esac
+ newdlprefiles="$newdlprefiles $abs"
+ done
+ dlprefiles="$newdlprefiles"
+ fi
+ $RM $output
+ # place dlname in correct position for cygwin
+ tdlname=$dlname
+ case $host,$output,$installed,$module,$dlname in
+ *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) tdlname=../bin/$dlname ;;
+ esac
+ $ECHO > $output "\
+# $outputname - a libtool library file
+# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# The name that we can dlopen(3).
+dlname='$tdlname'
+
+# Names of this library.
+library_names='$library_names'
+
+# The name of the static archive.
+old_library='$old_library'
+
+# Linker flags that can not go in dependency_libs.
+inherited_linker_flags='$new_inherited_linker_flags'
+
+# Libraries that this one depends upon.
+dependency_libs='$dependency_libs'
+
+# Names of additional weak libraries provided by this library
+weak_library_names='$weak_libs'
+
+# Version information for $libname.
+current=$current
+age=$age
+revision=$revision
+
+# Is this an already installed library?
+installed=$installed
+
+# Should we warn about portability when linking against -modules?
+shouldnotlink=$module
+
+# Files to dlopen/dlpreopen
+dlopen='$dlfiles'
+dlpreopen='$dlprefiles'
+
+# Directory that this library needs to be installed in:
+libdir='$install_libdir'"
+ if test "$installed" = no && test "$need_relink" = yes; then
+ $ECHO >> $output "\
+relink_command=\"$relink_command\""
+ fi
+ done
+ }
+
+ # Do a symbolic link so that the libtool archive can be found in
+ # LD_LIBRARY_PATH before the program is installed.
+ func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?'
+ ;;
+ esac
+ exit $EXIT_SUCCESS
+}
+
+{ test "$mode" = link || test "$mode" = relink; } &&
+ func_mode_link ${1+"$@"}
+
+
+# func_mode_uninstall arg...
+func_mode_uninstall ()
+{
+ $opt_debug
+ RM="$nonopt"
+ files=
+ rmforce=
+ exit_status=0
+
+ # This variable tells wrapper scripts just to set variables rather
+ # than running their programs.
+ libtool_install_magic="$magic"
+
+ for arg
+ do
+ case $arg in
+ -f) RM="$RM $arg"; rmforce=yes ;;
+ -*) RM="$RM $arg" ;;
+ *) files="$files $arg" ;;
+ esac
+ done
+
+ test -z "$RM" && \
+ func_fatal_help "you must specify an RM program"
+
+ rmdirs=
+
+ origobjdir="$objdir"
+ for file in $files; do
+ func_dirname "$file" "" "."
+ dir="$func_dirname_result"
+ if test "X$dir" = X.; then
+ objdir="$origobjdir"
+ else
+ objdir="$dir/$origobjdir"
+ fi
+ func_basename "$file"
+ name="$func_basename_result"
+ test "$mode" = uninstall && objdir="$dir"
+
+ # Remember objdir for removal later, being careful to avoid duplicates
+ if test "$mode" = clean; then
+ case " $rmdirs " in
+ *" $objdir "*) ;;
+ *) rmdirs="$rmdirs $objdir" ;;
+ esac
+ fi
+
+ # Don't error if the file doesn't exist and rm -f was used.
+ if { test -L "$file"; } >/dev/null 2>&1 ||
+ { test -h "$file"; } >/dev/null 2>&1 ||
+ test -f "$file"; then
+ :
+ elif test -d "$file"; then
+ exit_status=1
+ continue
+ elif test "$rmforce" = yes; then
+ continue
+ fi
+
+ rmfiles="$file"
+
+ case $name in
+ *.la)
+ # Possibly a libtool archive, so verify it.
+ if func_lalib_p "$file"; then
+ func_source $dir/$name
+
+ # Delete the libtool libraries and symlinks.
+ for n in $library_names; do
+ rmfiles="$rmfiles $objdir/$n"
+ done
+ test -n "$old_library" && rmfiles="$rmfiles $objdir/$old_library"
+
+ case "$mode" in
+ clean)
+ case " $library_names " in
+ # " " in the beginning catches empty $dlname
+ *" $dlname "*) ;;
+ *) rmfiles="$rmfiles $objdir/$dlname" ;;
+ esac
+ test -n "$libdir" && rmfiles="$rmfiles $objdir/$name $objdir/${name}i"
+ ;;
+ uninstall)
+ if test -n "$library_names"; then
+ # Do each command in the postuninstall commands.
+ func_execute_cmds "$postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1'
+ fi
+
+ if test -n "$old_library"; then
+ # Do each command in the old_postuninstall commands.
+ func_execute_cmds "$old_postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1'
+ fi
+ # FIXME: should reinstall the best remaining shared library.
+ ;;
+ esac
+ fi
+ ;;
+
+ *.lo)
+ # Possibly a libtool object, so verify it.
+ if func_lalib_p "$file"; then
+
+ # Read the .lo file
+ func_source $dir/$name
+
+ # Add PIC object to the list of files to remove.
+ if test -n "$pic_object" &&
+ test "$pic_object" != none; then
+ rmfiles="$rmfiles $dir/$pic_object"
+ fi
+
+ # Add non-PIC object to the list of files to remove.
+ if test -n "$non_pic_object" &&
+ test "$non_pic_object" != none; then
+ rmfiles="$rmfiles $dir/$non_pic_object"
+ fi
+ fi
+ ;;
+
+ *)
+ if test "$mode" = clean ; then
+ noexename=$name
+ case $file in
+ *.exe)
+ func_stripname '' '.exe' "$file"
+ file=$func_stripname_result
+ func_stripname '' '.exe' "$name"
+ noexename=$func_stripname_result
+ # $file with .exe has already been added to rmfiles,
+ # add $file without .exe
+ rmfiles="$rmfiles $file"
+ ;;
+ esac
+ # Do a test to see if this is a libtool program.
+ if func_ltwrapper_p "$file"; then
+ if func_ltwrapper_executable_p "$file"; then
+ func_ltwrapper_scriptname "$file"
+ relink_command=
+ func_source $func_ltwrapper_scriptname_result
+ rmfiles="$rmfiles $func_ltwrapper_scriptname_result"
+ else
+ relink_command=
+ func_source $dir/$noexename
+ fi
+
+ # note $name still contains .exe if it was in $file originally
+ # as does the version of $file that was added into $rmfiles
+ rmfiles="$rmfiles $objdir/$name $objdir/${name}S.${objext}"
+ if test "$fast_install" = yes && test -n "$relink_command"; then
+ rmfiles="$rmfiles $objdir/lt-$name"
+ fi
+ if test "X$noexename" != "X$name" ; then
+ rmfiles="$rmfiles $objdir/lt-${noexename}.c"
+ fi
+ fi
+ fi
+ ;;
+ esac
+ func_show_eval "$RM $rmfiles" 'exit_status=1'
+ done
+ objdir="$origobjdir"
+
+ # Try to remove the ${objdir}s in the directories where we deleted files
+ for dir in $rmdirs; do
+ if test -d "$dir"; then
+ func_show_eval "rmdir $dir >/dev/null 2>&1"
+ fi
+ done
+
+ exit $exit_status
+}
+
+{ test "$mode" = uninstall || test "$mode" = clean; } &&
+ func_mode_uninstall ${1+"$@"}
+
+test -z "$mode" && {
+ help="$generic_help"
+ func_fatal_help "you must specify a MODE"
+}
+
+test -z "$exec_cmd" && \
+ func_fatal_help "invalid operation mode \`$mode'"
+
+if test -n "$exec_cmd"; then
+ eval exec "$exec_cmd"
+ exit $EXIT_FAILURE
+fi
+
+exit $exit_status
+
+
+# The TAGs below are defined such that we never get into a situation
+# in which we disable both kinds of libraries. Given conflicting
+# choices, we go for a static library, that is the most portable,
+# since we can't tell whether shared libraries were disabled because
+# the user asked for that or because the platform doesn't support
+# them. This is particularly important on AIX, because we don't
+# support having both static and shared libraries enabled at the same
+# time on that platform, so we default to a shared-only configuration.
+# If a disable-shared tag is given, we'll fallback to a static-only
+# configuration. But we'll never go from static-only to shared-only.
+
+# ### BEGIN LIBTOOL TAG CONFIG: disable-shared
+build_libtool_libs=no
+build_old_libs=yes
+# ### END LIBTOOL TAG CONFIG: disable-shared
+
+# ### BEGIN LIBTOOL TAG CONFIG: disable-static
+build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac`
+# ### END LIBTOOL TAG CONFIG: disable-static
+
+# Local Variables:
+# mode:shell-script
+# sh-indentation:2
+# End:
+# vi:sw=2
+
diff --git a/missing b/missing
new file mode 100755
index 0000000..28055d2
--- /dev/null
+++ b/missing
@@ -0,0 +1,376 @@
+#! /bin/sh
+# Common stub for a few missing GNU programs while installing.
+
+scriptversion=2009-04-28.21; # UTC
+
+# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005, 2006,
+# 2008, 2009 Free Software Foundation, Inc.
+# Originally by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+if test $# -eq 0; then
+ echo 1>&2 "Try \`$0 --help' for more information"
+ exit 1
+fi
+
+run=:
+sed_output='s/.* --output[ =]\([^ ]*\).*/\1/p'
+sed_minuso='s/.* -o \([^ ]*\).*/\1/p'
+
+# In the cases where this matters, `missing' is being run in the
+# srcdir already.
+if test -f configure.ac; then
+ configure_ac=configure.ac
+else
+ configure_ac=configure.in
+fi
+
+msg="missing on your system"
+
+case $1 in
+--run)
+ # Try to run requested program, and just exit if it succeeds.
+ run=
+ shift
+ "$@" && exit 0
+ # Exit code 63 means version mismatch. This often happens
+ # when the user try to use an ancient version of a tool on
+ # a file that requires a minimum version. In this case we
+ # we should proceed has if the program had been absent, or
+ # if --run hadn't been passed.
+ if test $? = 63; then
+ run=:
+ msg="probably too old"
+ fi
+ ;;
+
+ -h|--h|--he|--hel|--help)
+ echo "\
+$0 [OPTION]... PROGRAM [ARGUMENT]...
+
+Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an
+error status if there is no known handling for PROGRAM.
+
+Options:
+ -h, --help display this help and exit
+ -v, --version output version information and exit
+ --run try to run the given command, and emulate it if it fails
+
+Supported PROGRAM values:
+ aclocal touch file \`aclocal.m4'
+ autoconf touch file \`configure'
+ autoheader touch file \`config.h.in'
+ autom4te touch the output file, or create a stub one
+ automake touch all \`Makefile.in' files
+ bison create \`y.tab.[ch]', if possible, from existing .[ch]
+ flex create \`lex.yy.c', if possible, from existing .c
+ help2man touch the output file
+ lex create \`lex.yy.c', if possible, from existing .c
+ makeinfo touch the output file
+ tar try tar, gnutar, gtar, then tar without non-portable flags
+ yacc create \`y.tab.[ch]', if possible, from existing .[ch]
+
+Version suffixes to PROGRAM as well as the prefixes \`gnu-', \`gnu', and
+\`g' are ignored when checking the name.
+
+Send bug reports to <bug-automake@gnu.org>."
+ exit $?
+ ;;
+
+ -v|--v|--ve|--ver|--vers|--versi|--versio|--version)
+ echo "missing $scriptversion (GNU Automake)"
+ exit $?
+ ;;
+
+ -*)
+ echo 1>&2 "$0: Unknown \`$1' option"
+ echo 1>&2 "Try \`$0 --help' for more information"
+ exit 1
+ ;;
+
+esac
+
+# normalize program name to check for.
+program=`echo "$1" | sed '
+ s/^gnu-//; t
+ s/^gnu//; t
+ s/^g//; t'`
+
+# Now exit if we have it, but it failed. Also exit now if we
+# don't have it and --version was passed (most likely to detect
+# the program). This is about non-GNU programs, so use $1 not
+# $program.
+case $1 in
+ lex*|yacc*)
+ # Not GNU programs, they don't have --version.
+ ;;
+
+ tar*)
+ if test -n "$run"; then
+ echo 1>&2 "ERROR: \`tar' requires --run"
+ exit 1
+ elif test "x$2" = "x--version" || test "x$2" = "x--help"; then
+ exit 1
+ fi
+ ;;
+
+ *)
+ if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
+ # We have it, but it failed.
+ exit 1
+ elif test "x$2" = "x--version" || test "x$2" = "x--help"; then
+ # Could not run --version or --help. This is probably someone
+ # running `$TOOL --version' or `$TOOL --help' to check whether
+ # $TOOL exists and not knowing $TOOL uses missing.
+ exit 1
+ fi
+ ;;
+esac
+
+# If it does not exist, or fails to run (possibly an outdated version),
+# try to emulate it.
+case $program in
+ aclocal*)
+ echo 1>&2 "\
+WARNING: \`$1' is $msg. You should only need it if
+ you modified \`acinclude.m4' or \`${configure_ac}'. You might want
+ to install the \`Automake' and \`Perl' packages. Grab them from
+ any GNU archive site."
+ touch aclocal.m4
+ ;;
+
+ autoconf*)
+ echo 1>&2 "\
+WARNING: \`$1' is $msg. You should only need it if
+ you modified \`${configure_ac}'. You might want to install the
+ \`Autoconf' and \`GNU m4' packages. Grab them from any GNU
+ archive site."
+ touch configure
+ ;;
+
+ autoheader*)
+ echo 1>&2 "\
+WARNING: \`$1' is $msg. You should only need it if
+ you modified \`acconfig.h' or \`${configure_ac}'. You might want
+ to install the \`Autoconf' and \`GNU m4' packages. Grab them
+ from any GNU archive site."
+ files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}`
+ test -z "$files" && files="config.h"
+ touch_files=
+ for f in $files; do
+ case $f in
+ *:*) touch_files="$touch_files "`echo "$f" |
+ sed -e 's/^[^:]*://' -e 's/:.*//'`;;
+ *) touch_files="$touch_files $f.in";;
+ esac
+ done
+ touch $touch_files
+ ;;
+
+ automake*)
+ echo 1>&2 "\
+WARNING: \`$1' is $msg. You should only need it if
+ you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'.
+ You might want to install the \`Automake' and \`Perl' packages.
+ Grab them from any GNU archive site."
+ find . -type f -name Makefile.am -print |
+ sed 's/\.am$/.in/' |
+ while read f; do touch "$f"; done
+ ;;
+
+ autom4te*)
+ echo 1>&2 "\
+WARNING: \`$1' is needed, but is $msg.
+ You might have modified some files without having the
+ proper tools for further handling them.
+ You can get \`$1' as part of \`Autoconf' from any GNU
+ archive site."
+
+ file=`echo "$*" | sed -n "$sed_output"`
+ test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
+ if test -f "$file"; then
+ touch $file
+ else
+ test -z "$file" || exec >$file
+ echo "#! /bin/sh"
+ echo "# Created by GNU Automake missing as a replacement of"
+ echo "# $ $@"
+ echo "exit 0"
+ chmod +x $file
+ exit 1
+ fi
+ ;;
+
+ bison*|yacc*)
+ echo 1>&2 "\
+WARNING: \`$1' $msg. You should only need it if
+ you modified a \`.y' file. You may need the \`Bison' package
+ in order for those modifications to take effect. You can get
+ \`Bison' from any GNU archive site."
+ rm -f y.tab.c y.tab.h
+ if test $# -ne 1; then
+ eval LASTARG="\${$#}"
+ case $LASTARG in
+ *.y)
+ SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'`
+ if test -f "$SRCFILE"; then
+ cp "$SRCFILE" y.tab.c
+ fi
+ SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'`
+ if test -f "$SRCFILE"; then
+ cp "$SRCFILE" y.tab.h
+ fi
+ ;;
+ esac
+ fi
+ if test ! -f y.tab.h; then
+ echo >y.tab.h
+ fi
+ if test ! -f y.tab.c; then
+ echo 'main() { return 0; }' >y.tab.c
+ fi
+ ;;
+
+ lex*|flex*)
+ echo 1>&2 "\
+WARNING: \`$1' is $msg. You should only need it if
+ you modified a \`.l' file. You may need the \`Flex' package
+ in order for those modifications to take effect. You can get
+ \`Flex' from any GNU archive site."
+ rm -f lex.yy.c
+ if test $# -ne 1; then
+ eval LASTARG="\${$#}"
+ case $LASTARG in
+ *.l)
+ SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'`
+ if test -f "$SRCFILE"; then
+ cp "$SRCFILE" lex.yy.c
+ fi
+ ;;
+ esac
+ fi
+ if test ! -f lex.yy.c; then
+ echo 'main() { return 0; }' >lex.yy.c
+ fi
+ ;;
+
+ help2man*)
+ echo 1>&2 "\
+WARNING: \`$1' is $msg. You should only need it if
+ you modified a dependency of a manual page. You may need the
+ \`Help2man' package in order for those modifications to take
+ effect. You can get \`Help2man' from any GNU archive site."
+
+ file=`echo "$*" | sed -n "$sed_output"`
+ test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
+ if test -f "$file"; then
+ touch $file
+ else
+ test -z "$file" || exec >$file
+ echo ".ab help2man is required to generate this page"
+ exit $?
+ fi
+ ;;
+
+ makeinfo*)
+ echo 1>&2 "\
+WARNING: \`$1' is $msg. You should only need it if
+ you modified a \`.texi' or \`.texinfo' file, or any other file
+ indirectly affecting the aspect of the manual. The spurious
+ call might also be the consequence of using a buggy \`make' (AIX,
+ DU, IRIX). You might want to install the \`Texinfo' package or
+ the \`GNU make' package. Grab either from any GNU archive site."
+ # The file to touch is that specified with -o ...
+ file=`echo "$*" | sed -n "$sed_output"`
+ test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
+ if test -z "$file"; then
+ # ... or it is the one specified with @setfilename ...
+ infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'`
+ file=`sed -n '
+ /^@setfilename/{
+ s/.* \([^ ]*\) *$/\1/
+ p
+ q
+ }' $infile`
+ # ... or it is derived from the source name (dir/f.texi becomes f.info)
+ test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info
+ fi
+ # If the file does not exist, the user really needs makeinfo;
+ # let's fail without touching anything.
+ test -f $file || exit 1
+ touch $file
+ ;;
+
+ tar*)
+ shift
+
+ # We have already tried tar in the generic part.
+ # Look for gnutar/gtar before invocation to avoid ugly error
+ # messages.
+ if (gnutar --version > /dev/null 2>&1); then
+ gnutar "$@" && exit 0
+ fi
+ if (gtar --version > /dev/null 2>&1); then
+ gtar "$@" && exit 0
+ fi
+ firstarg="$1"
+ if shift; then
+ case $firstarg in
+ *o*)
+ firstarg=`echo "$firstarg" | sed s/o//`
+ tar "$firstarg" "$@" && exit 0
+ ;;
+ esac
+ case $firstarg in
+ *h*)
+ firstarg=`echo "$firstarg" | sed s/h//`
+ tar "$firstarg" "$@" && exit 0
+ ;;
+ esac
+ fi
+
+ echo 1>&2 "\
+WARNING: I can't seem to be able to run \`tar' with the given arguments.
+ You may want to install GNU tar or Free paxutils, or check the
+ command line arguments."
+ exit 1
+ ;;
+
+ *)
+ echo 1>&2 "\
+WARNING: \`$1' is needed, and is $msg.
+ You might have modified some files without having the
+ proper tools for further handling them. Check the \`README' file,
+ it often tells you about the needed prerequisites for installing
+ this package. You may also peek at any GNU archive site, in case
+ some other package would contain this missing \`$1' program."
+ exit 1
+ ;;
+esac
+
+exit 0
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC"
+# time-stamp-end: "; # UTC"
+# End:
diff --git a/phidget21.c b/phidget21.c
new file mode 100644
index 0000000..2fe4b98
--- /dev/null
+++ b/phidget21.c
@@ -0,0 +1,38 @@
+// phidget21.c : Defines the entry point for the DLL application.
+//
+
+#include "stdafx.h"
+#include "phidget21int.h"
+#include "cthread.h"
+#include "cphidget.h"
+#include "cusb.h"
+
+#ifdef _WINDOWS
+#ifdef _MANAGED
+#pragma managed(push, off)
+#endif
+
+BOOL APIENTRY DllMain( HMODULE hModule,
+ DWORD ul_reason_for_call,
+ LPVOID lpReserved
+ )
+{
+ switch (ul_reason_for_call)
+ {
+ case DLL_PROCESS_ATTACH:
+ ActiveDevices = 0;
+ //inst = (HINSTANCE)hModule;
+ case DLL_THREAD_ATTACH:
+ case DLL_THREAD_DETACH:
+ case DLL_PROCESS_DETACH:
+ break;
+ }
+ return TRUE;
+}
+
+#ifdef _MANAGED
+#pragma managed(pop)
+#endif
+#endif
+
+
diff --git a/phidget21.h b/phidget21.h
new file mode 100644
index 0000000..363a29e
--- /dev/null
+++ b/phidget21.h
@@ -0,0 +1,793 @@
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(__stdcall)
+ #define CCONV __stdcall
+#else
+ #if defined(__BORLANDC__) || defined(_MSC_VER)
+ #define CCONV __stdcall
+ #else
+ #define CCONV
+ #endif
+#endif
+
+#if !defined(__int64)
+#if !defined(__BORLANDC__) && !defined(_MSC_VER)
+typedef long long __int64;
+#endif
+#endif
+
+
+typedef struct _CPhidget *CPhidgetHandle;
+typedef struct _CPhidget_Timestamp {
+ int seconds;
+ int microseconds;
+} CPhidget_Timestamp, *CPhidget_TimestampHandle;
+typedef enum {
+ PHIDCLASS_ACCELEROMETER = 2,
+ PHIDCLASS_ADVANCEDSERVO = 3,
+ PHIDCLASS_ANALOG = 22,
+ PHIDCLASS_BRIDGE = 23,
+ PHIDCLASS_ENCODER = 4,
+ PHIDCLASS_FREQUENCYCOUNTER = 21,
+ PHIDCLASS_GPS = 5,
+ PHIDCLASS_INTERFACEKIT = 7,
+ PHIDCLASS_IR = 19,
+ PHIDCLASS_LED = 8,
+ PHIDCLASS_MOTORCONTROL = 9,
+ PHIDCLASS_PHSENSOR = 10,
+ PHIDCLASS_RFID = 11,
+ PHIDCLASS_SERVO = 12,
+ PHIDCLASS_SPATIAL = 20,
+ PHIDCLASS_STEPPER = 13,
+ PHIDCLASS_TEMPERATURESENSOR = 14,
+ PHIDCLASS_TEXTLCD = 15,
+ PHIDCLASS_TEXTLED = 16,
+ PHIDCLASS_WEIGHTSENSOR = 17,
+} CPhidget_DeviceClass;
+typedef enum {
+ PHIDID_ACCELEROMETER_3AXIS = 0x07E,
+ PHIDID_ADVANCEDSERVO_1MOTOR = 0x082,
+ PHIDID_ADVANCEDSERVO_8MOTOR = 0x03A,
+ PHIDID_ANALOG_4OUTPUT = 0x037,
+ PHIDID_BIPOLAR_STEPPER_1MOTOR = 0x07B,
+ PHIDID_BRIDGE_4INPUT = 0x03B,
+ PHIDID_ENCODER_1ENCODER_1INPUT = 0x04B,
+ PHIDID_ENCODER_HS_1ENCODER = 0x080,
+ PHIDID_ENCODER_HS_4ENCODER_4INPUT = 0x04F,
+ PHIDID_FREQUENCYCOUNTER_2INPUT = 0x035,
+ PHIDID_GPS = 0x079,
+ PHIDID_INTERFACEKIT_0_0_4 = 0x040,
+ PHIDID_INTERFACEKIT_0_0_8 = 0x081,
+ PHIDID_INTERFACEKIT_0_16_16 = 0x044,
+ PHIDID_INTERFACEKIT_2_2_2 = 0x036,
+ PHIDID_INTERFACEKIT_8_8_8 = 0x045,
+ PHIDID_INTERFACEKIT_8_8_8_w_LCD = 0x07D,
+ PHIDID_IR = 0x04D,
+ PHIDID_LED_64_ADV = 0x04C,
+ PHIDID_LINEAR_TOUCH = 0x076,
+ PHIDID_MOTORCONTROL_1MOTOR = 0x03E,
+ PHIDID_MOTORCONTROL_HC_2MOTOR = 0x059,
+ PHIDID_RFID_2OUTPUT = 0x031,
+ PHIDID_ROTARY_TOUCH = 0x077,
+ PHIDID_SPATIAL_ACCEL_3AXIS = 0x07F,
+ PHIDID_SPATIAL_ACCEL_GYRO_COMPASS = 0x033,
+ PHIDID_TEMPERATURESENSOR = 0x070,
+ PHIDID_TEMPERATURESENSOR_4 = 0x032,
+ PHIDID_TEMPERATURESENSOR_IR = 0x03C,
+ PHIDID_TEXTLCD_2x20_w_8_8_8 = 0x17D,
+ PHIDID_TEXTLCD_ADAPTER = 0x03D,
+ PHIDID_UNIPOLAR_STEPPER_4MOTOR = 0x07A,
+ PHIDID_ACCELEROMETER_2AXIS = 0x071,
+ PHIDID_INTERFACEKIT_0_8_8_w_LCD = 0x053,
+ PHIDID_INTERFACEKIT_4_8_8 = 4,
+ PHIDID_LED_64 = 0x04A,
+ PHIDID_MOTORCONTROL_LV_2MOTOR_4INPUT = 0x058,
+ PHIDID_PHSENSOR = 0x074,
+ PHIDID_RFID = 0x030,
+ PHIDID_SERVO_1MOTOR = 0x039,
+ PHIDID_SERVO_1MOTOR_OLD = 2,
+ PHIDID_SERVO_4MOTOR = 0x038,
+ PHIDID_SERVO_4MOTOR_OLD = 3,
+ PHIDID_TEXTLCD_2x20 = 0x052,
+ PHIDID_TEXTLCD_2x20_w_0_8_8 = 0x153,
+ PHIDID_TEXTLED_1x8 = 0x049,
+ PHIDID_TEXTLED_4x8 = 0x048,
+ PHIDID_WEIGHTSENSOR = 0x072,
+} CPhidget_DeviceID;
+ int CPhidget_open(CPhidgetHandle phid, int serialNumber);
+ int CPhidget_openLabel(CPhidgetHandle phid, const char *label);
+ int CPhidget_close(CPhidgetHandle phid);
+ int CPhidget_delete(CPhidgetHandle phid);
+ int CPhidget_set_OnDetach_Handler(CPhidgetHandle phid, int( *fptr)(CPhidgetHandle phid, void *userPtr), void *userPtr);
+ int CPhidget_set_OnAttach_Handler(CPhidgetHandle phid, int( *fptr)(CPhidgetHandle phid, void *userPtr), void *userPtr);
+ int CPhidget_set_OnServerConnect_Handler(CPhidgetHandle phid, int ( *fptr)(CPhidgetHandle phid, void *userPtr), void *userPtr);
+ int CPhidget_set_OnServerDisconnect_Handler(CPhidgetHandle phid, int ( *fptr)(CPhidgetHandle phid, void *userPtr), void *userPtr);
+ int CPhidget_set_OnError_Handler(CPhidgetHandle phid, int( *fptr)(CPhidgetHandle phid, void *userPtr, int errorCode, const char *errorString), void *userPtr);
+ int CPhidget_getDeviceName(CPhidgetHandle phid, const char **deviceName);
+ int CPhidget_getSerialNumber(CPhidgetHandle phid, int *serialNumber);
+ int CPhidget_getDeviceVersion(CPhidgetHandle phid, int *deviceVersion);
+ int CPhidget_getDeviceStatus(CPhidgetHandle phid, int *deviceStatus);
+ int CPhidget_getLibraryVersion(const char **libraryVersion);
+ int CPhidget_getDeviceType(CPhidgetHandle phid, const char **deviceType);
+ int CPhidget_getDeviceLabel(CPhidgetHandle phid, const char **deviceLabel);
+ int CPhidget_setDeviceLabel(CPhidgetHandle phid, const char *deviceLabel);
+ int CPhidget_getErrorDescription(int errorCode, const char **errorString);
+ int CPhidget_waitForAttachment(CPhidgetHandle phid, int milliseconds);
+ int CPhidget_getServerID(CPhidgetHandle phid, const char **serverID);
+ int CPhidget_getServerAddress(CPhidgetHandle phid, const char **address, int *port);
+ int CPhidget_getServerStatus(CPhidgetHandle phid, int *serverStatus);
+ int CPhidget_getDeviceID(CPhidgetHandle phid, CPhidget_DeviceID *deviceID);
+ int CPhidget_getDeviceClass(CPhidgetHandle phid, CPhidget_DeviceClass *deviceClass);
+typedef enum {
+ PHIDGET_DICTIONARY_VALUE_CHANGED = 1,
+ PHIDGET_DICTIONARY_ENTRY_ADDED,
+ PHIDGET_DICTIONARY_ENTRY_REMOVING,
+ PHIDGET_DICTIONARY_CURRENT_VALUE
+} CPhidgetDictionary_keyChangeReason;
+typedef struct _CPhidgetDictionary *CPhidgetDictionaryHandle;
+typedef struct _CPhidgetDictionaryListener *CPhidgetDictionaryListenerHandle;
+ int CPhidgetDictionary_create(CPhidgetDictionaryHandle *dict);
+ int CPhidgetDictionary_close(CPhidgetDictionaryHandle dict);
+ int CPhidgetDictionary_delete(CPhidgetDictionaryHandle dict);
+ int CPhidgetDictionary_set_OnError_Handler(CPhidgetDictionaryHandle dict,
+ int( *fptr)(CPhidgetDictionaryHandle, void *userPtr, int errorCode, const char *errorString), void *userPtr);
+ int CPhidgetDictionary_addKey(CPhidgetDictionaryHandle dict, const char *key, const char *value, int persistent);
+ int CPhidgetDictionary_removeKey(CPhidgetDictionaryHandle dict, const char *pattern);
+
+typedef int( *CPhidgetDictionary_OnKeyChange_Function)(CPhidgetDictionaryHandle dict, void *userPtr,
+ const char *key, const char *value, CPhidgetDictionary_keyChangeReason reason);
+ int CPhidgetDictionary_set_OnKeyChange_Handler(CPhidgetDictionaryHandle dict, CPhidgetDictionaryListenerHandle *dictlistener, const char *pattern,
+ CPhidgetDictionary_OnKeyChange_Function fptr, void *userPtr);
+ int CPhidgetDictionary_remove_OnKeyChange_Handler(CPhidgetDictionaryListenerHandle dictlistener);
+ int CPhidgetDictionary_getKey(CPhidgetDictionaryHandle dict, const char *key, char *value, int valuelen);
+ int CPhidgetDictionary_set_OnServerConnect_Handler(CPhidgetDictionaryHandle dict, int ( *fptr)(CPhidgetDictionaryHandle dict, void *userPtr), void *userPtr);
+ int CPhidgetDictionary_set_OnServerDisconnect_Handler(CPhidgetDictionaryHandle dict, int ( *fptr)(CPhidgetDictionaryHandle dict, void *userPtr), void *userPtr);
+ int CPhidgetDictionary_getServerID(CPhidgetDictionaryHandle dict, const char **serverID);
+ int CPhidgetDictionary_getServerAddress(CPhidgetDictionaryHandle dict, const char **address, int *port);
+ int CPhidgetDictionary_getServerStatus(CPhidgetDictionaryHandle dict, int *serverStatus);
+typedef struct _CPhidgetManager *CPhidgetManagerHandle;
+ int CPhidgetManager_create(CPhidgetManagerHandle *phidm);
+ int CPhidgetManager_open(CPhidgetManagerHandle phidm);
+ int CPhidgetManager_close(CPhidgetManagerHandle phidm);
+ int CPhidgetManager_delete(CPhidgetManagerHandle phidm);
+ int CPhidgetManager_set_OnAttach_Handler(CPhidgetManagerHandle phidm, int ( *fptr)(CPhidgetHandle phid, void *userPtr), void *userPtr);
+ int CPhidgetManager_set_OnDetach_Handler(CPhidgetManagerHandle phidm, int ( *fptr)(CPhidgetHandle phid, void *userPtr), void *userPtr);
+ int CPhidgetManager_getAttachedDevices(CPhidgetManagerHandle phidm, CPhidgetHandle *phidArray[], int *count);
+ int CPhidgetManager_freeAttachedDevicesArray(CPhidgetHandle phidArray[]);
+ int CPhidgetManager_set_OnError_Handler(CPhidgetManagerHandle phidm, int( *fptr)(CPhidgetManagerHandle phidm, void *userPtr, int errorCode, const char *errorString), void *userPtr);
+ int CPhidgetManager_set_OnServerConnect_Handler(CPhidgetManagerHandle phidm, int ( *fptr)(CPhidgetManagerHandle phidm, void *userPtr), void *userPtr);
+ int CPhidgetManager_set_OnServerDisconnect_Handler(CPhidgetManagerHandle phidm, int ( *fptr)(CPhidgetManagerHandle phidm, void *userPtr), void *userPtr);
+ int CPhidgetManager_getServerID(CPhidgetManagerHandle phidm, const char **serverID);
+ int CPhidgetManager_getServerAddress(CPhidgetManagerHandle phidm, const char **address, int *port);
+
+
+
+
+
+ int CPhidgetManager_getServerStatus(CPhidgetManagerHandle phidm, int *serverStatus);
+ int CPhidget_openRemote(CPhidgetHandle phid, int serial, const char *serverID, const char *password);
+ int CPhidget_openLabelRemote(CPhidgetHandle phid, const char *label, const char *serverID, const char *password);
+ int CPhidget_openRemoteIP(CPhidgetHandle phid, int serial, const char *address, int port, const char *password);
+ int CPhidget_openLabelRemoteIP(CPhidgetHandle phid, const char *label, const char *address, int port, const char *password);
+ int CPhidgetManager_openRemote(CPhidgetManagerHandle phidm, const char *serverID, const char *password);
+ int CPhidgetManager_openRemoteIP(CPhidgetManagerHandle phidm, const char *address, int port, const char *password);
+ int CPhidgetDictionary_openRemote(CPhidgetDictionaryHandle dict, const char *serverID, const char *password);
+ int CPhidgetDictionary_openRemoteIP(CPhidgetDictionaryHandle dict, const char *address, int port, const char *password);
+typedef enum {
+ PHIDGET_LOG_CRITICAL = 1,
+ PHIDGET_LOG_ERROR,
+ PHIDGET_LOG_WARNING,
+ PHIDGET_LOG_DEBUG,
+ PHIDGET_LOG_INFO,
+ PHIDGET_LOG_VERBOSE
+} CPhidgetLog_level;
+ int CPhidget_enableLogging(CPhidgetLog_level level, const char *outputFile);
+ int CPhidget_disableLogging();
+ int CPhidget_log(CPhidgetLog_level level, const char *id, const char *message, ...);
+typedef struct _CPhidgetAccelerometer *CPhidgetAccelerometerHandle;
+ int CPhidgetAccelerometer_create(CPhidgetAccelerometerHandle *phid);
+ int CPhidgetAccelerometer_getAxisCount(CPhidgetAccelerometerHandle phid, int *count);
+ int CPhidgetAccelerometer_getAcceleration(CPhidgetAccelerometerHandle phid, int index, double *acceleration);
+ int CPhidgetAccelerometer_getAccelerationMax(CPhidgetAccelerometerHandle phid, int index, double *max);
+ int CPhidgetAccelerometer_getAccelerationMin(CPhidgetAccelerometerHandle phid, int index, double *min);
+ int CPhidgetAccelerometer_set_OnAccelerationChange_Handler(CPhidgetAccelerometerHandle phid, int ( *fptr)(CPhidgetAccelerometerHandle phid, void *userPtr, int index, double acceleration), void *userPtr);
+ int CPhidgetAccelerometer_getAccelerationChangeTrigger(CPhidgetAccelerometerHandle phid, int index, double *trigger);
+ int CPhidgetAccelerometer_setAccelerationChangeTrigger(CPhidgetAccelerometerHandle phid, int index, double trigger);
+typedef struct _CPhidgetAdvancedServo *CPhidgetAdvancedServoHandle;
+ int CPhidgetAdvancedServo_create(CPhidgetAdvancedServoHandle *phid);
+typedef enum {
+ PHIDGET_SERVO_DEFAULT = 1,
+ PHIDGET_SERVO_RAW_us_MODE,
+ PHIDGET_SERVO_HITEC_HS322HD,
+ PHIDGET_SERVO_HITEC_HS5245MG,
+ PHIDGET_SERVO_HITEC_805BB,
+ PHIDGET_SERVO_HITEC_HS422,
+ PHIDGET_SERVO_TOWERPRO_MG90,
+ PHIDGET_SERVO_HITEC_HSR1425CR,
+ PHIDGET_SERVO_HITEC_HS785HB,
+ PHIDGET_SERVO_HITEC_HS485HB,
+ PHIDGET_SERVO_HITEC_HS645MG,
+ PHIDGET_SERVO_HITEC_815BB,
+ PHIDGET_SERVO_FIRGELLI_L12_30_50_06_R,
+ PHIDGET_SERVO_FIRGELLI_L12_50_100_06_R,
+ PHIDGET_SERVO_FIRGELLI_L12_50_210_06_R,
+ PHIDGET_SERVO_FIRGELLI_L12_100_50_06_R,
+ PHIDGET_SERVO_FIRGELLI_L12_100_100_06_R,
+ PHIDGET_SERVO_SPRINGRC_SM_S2313M,
+ PHIDGET_SERVO_SPRINGRC_SM_S3317M,
+ PHIDGET_SERVO_SPRINGRC_SM_S3317SR,
+ PHIDGET_SERVO_SPRINGRC_SM_S4303R,
+ PHIDGET_SERVO_SPRINGRC_SM_S4315M,
+ PHIDGET_SERVO_SPRINGRC_SM_S4315R,
+ PHIDGET_SERVO_SPRINGRC_SM_S4505B,
+ PHIDGET_SERVO_USER_DEFINED
+} CPhidget_ServoType;
+ int CPhidgetAdvancedServo_getMotorCount(CPhidgetAdvancedServoHandle phid, int *count);
+ int CPhidgetAdvancedServo_getAcceleration(CPhidgetAdvancedServoHandle phid, int index, double *acceleration);
+ int CPhidgetAdvancedServo_setAcceleration(CPhidgetAdvancedServoHandle phid, int index, double acceleration);
+ int CPhidgetAdvancedServo_getAccelerationMax(CPhidgetAdvancedServoHandle phid, int index, double *max);
+ int CPhidgetAdvancedServo_getAccelerationMin(CPhidgetAdvancedServoHandle phid, int index, double *min);
+ int CPhidgetAdvancedServo_getVelocityLimit(CPhidgetAdvancedServoHandle phid, int index, double *limit);
+ int CPhidgetAdvancedServo_setVelocityLimit(CPhidgetAdvancedServoHandle phid, int index, double limit);
+ int CPhidgetAdvancedServo_getVelocity(CPhidgetAdvancedServoHandle phid, int index, double *velocity);
+ int CPhidgetAdvancedServo_getVelocityMax(CPhidgetAdvancedServoHandle phid, int index, double *max);
+ int CPhidgetAdvancedServo_getVelocityMin(CPhidgetAdvancedServoHandle phid, int index, double *min);
+ int CPhidgetAdvancedServo_set_OnVelocityChange_Handler(CPhidgetAdvancedServoHandle phid, int ( *fptr)(CPhidgetAdvancedServoHandle phid, void *userPtr, int index, double velocity), void *userPtr);
+ int CPhidgetAdvancedServo_getPosition(CPhidgetAdvancedServoHandle phid, int index, double *position);
+ int CPhidgetAdvancedServo_setPosition(CPhidgetAdvancedServoHandle phid, int index, double position);
+ int CPhidgetAdvancedServo_getPositionMax(CPhidgetAdvancedServoHandle phid, int index, double *max);
+ int CPhidgetAdvancedServo_setPositionMax(CPhidgetAdvancedServoHandle phid, int index, double max);
+ int CPhidgetAdvancedServo_getPositionMin(CPhidgetAdvancedServoHandle phid, int index, double *min);
+ int CPhidgetAdvancedServo_setPositionMin(CPhidgetAdvancedServoHandle phid, int index, double min);
+ int CPhidgetAdvancedServo_set_OnPositionChange_Handler(CPhidgetAdvancedServoHandle phid, int ( *fptr)(CPhidgetAdvancedServoHandle phid, void *userPtr, int index, double position), void *userPtr);
+ int CPhidgetAdvancedServo_getCurrent(CPhidgetAdvancedServoHandle phid, int index, double *current);
+ int CPhidgetAdvancedServo_set_OnCurrentChange_Handler(CPhidgetAdvancedServoHandle phid, int ( *fptr)(CPhidgetAdvancedServoHandle phid, void *userPtr, int index, double current), void *userPtr);
+ int CPhidgetAdvancedServo_getSpeedRampingOn(CPhidgetAdvancedServoHandle phid, int index, int *rampingState);
+ int CPhidgetAdvancedServo_setSpeedRampingOn(CPhidgetAdvancedServoHandle phid, int index, int rampingState);
+ int CPhidgetAdvancedServo_getEngaged(CPhidgetAdvancedServoHandle phid, int index, int *engagedState);
+ int CPhidgetAdvancedServo_setEngaged(CPhidgetAdvancedServoHandle phid, int index, int engagedState);
+ int CPhidgetAdvancedServo_getStopped(CPhidgetAdvancedServoHandle phid, int index, int *stoppedState);
+
+
+ int CPhidgetAdvancedServo_getServoType(CPhidgetAdvancedServoHandle phid, int index, CPhidget_ServoType *servoType);
+
+
+
+
+
+
+ int CPhidgetAdvancedServo_setServoType(CPhidgetAdvancedServoHandle phid, int index, CPhidget_ServoType servoType);
+ int CPhidgetAdvancedServo_setServoParameters(CPhidgetAdvancedServoHandle phid, int index, double min_us,double max_us,double degrees,double velocity_max);
+typedef struct _CPhidgetAnalog *CPhidgetAnalogHandle;
+ int CPhidgetAnalog_create(CPhidgetAnalogHandle *phid);
+ int CPhidgetAnalog_getOutputCount(CPhidgetAnalogHandle phid, int *count);
+ int CPhidgetAnalog_getVoltage(CPhidgetAnalogHandle phid, int index, double *voltage);
+ int CPhidgetAnalog_setVoltage(CPhidgetAnalogHandle phid, int index, double voltage);
+ int CPhidgetAnalog_getVoltageMax(CPhidgetAnalogHandle phid, int index, double *max);
+ int CPhidgetAnalog_getVoltageMin(CPhidgetAnalogHandle phid, int index, double *min);
+ int CPhidgetAnalog_setEnabled(CPhidgetAnalogHandle phid, int index, int enabledState);
+ int CPhidgetAnalog_getEnabled(CPhidgetAnalogHandle phid, int index, int *enabledState);
+typedef enum {
+ PHIDGET_BRIDGE_GAIN_1 = 1,
+ PHIDGET_BRIDGE_GAIN_8,
+ PHIDGET_BRIDGE_GAIN_16,
+ PHIDGET_BRIDGE_GAIN_32,
+ PHIDGET_BRIDGE_GAIN_64,
+ PHIDGET_BRIDGE_GAIN_128,
+ PHIDGET_BRIDGE_GAIN_UNKNOWN
+} CPhidgetBridge_Gain;
+typedef struct _CPhidgetBridge *CPhidgetBridgeHandle;
+ int CPhidgetBridge_create(CPhidgetBridgeHandle *phid);
+ int CPhidgetBridge_getInputCount(CPhidgetBridgeHandle phid, int *count);
+ int CPhidgetBridge_getBridgeValue(CPhidgetBridgeHandle phid, int index, double *value);
+ int CPhidgetBridge_getBridgeMax(CPhidgetBridgeHandle phid, int index, double *max);
+ int CPhidgetBridge_getBridgeMin(CPhidgetBridgeHandle phid, int index, double *min);
+ int CPhidgetBridge_setEnabled(CPhidgetBridgeHandle phid, int index, int enabledState);
+ int CPhidgetBridge_getEnabled(CPhidgetBridgeHandle phid, int index, int *enabledState);
+ int CPhidgetBridge_getGain(CPhidgetBridgeHandle phid, int index, CPhidgetBridge_Gain *gain);
+ int CPhidgetBridge_setGain(CPhidgetBridgeHandle phid, int index, CPhidgetBridge_Gain gain);
+ int CPhidgetBridge_getDataRate(CPhidgetBridgeHandle phid, int *milliseconds);
+ int CPhidgetBridge_setDataRate(CPhidgetBridgeHandle phid, int milliseconds);
+ int CPhidgetBridge_getDataRateMax(CPhidgetBridgeHandle phid, int *max);
+ int CPhidgetBridge_getDataRateMin(CPhidgetBridgeHandle phid, int *min);
+ int CPhidgetBridge_set_OnBridgeData_Handler(CPhidgetBridgeHandle phid, int ( *fptr)(CPhidgetBridgeHandle phid, void *userPtr, int index, double value), void *userPtr);
+typedef struct _CPhidgetEncoder *CPhidgetEncoderHandle;
+ int CPhidgetEncoder_create(CPhidgetEncoderHandle *phid);
+ int CPhidgetEncoder_getInputCount(CPhidgetEncoderHandle phid, int *count);
+ int CPhidgetEncoder_getInputState(CPhidgetEncoderHandle phid, int index, int *inputState);
+ int CPhidgetEncoder_set_OnInputChange_Handler(CPhidgetEncoderHandle phid, int ( *fptr)(CPhidgetEncoderHandle phid, void *userPtr, int index, int inputState), void *userPtr);
+ int CPhidgetEncoder_getEncoderCount(CPhidgetEncoderHandle phid, int *count);
+ int CPhidgetEncoder_getPosition(CPhidgetEncoderHandle phid, int index, int *position);
+ int CPhidgetEncoder_setPosition(CPhidgetEncoderHandle phid, int index, int position);
+ int CPhidgetEncoder_set_OnPositionChange_Handler(CPhidgetEncoderHandle phid, int ( *fptr)(CPhidgetEncoderHandle phid, void *userPtr, int index, int time,int positionChange), void *userPtr);
+ int CPhidgetEncoder_getIndexPosition(CPhidgetEncoderHandle phid, int index, int *position);
+ int CPhidgetEncoder_getEnabled(CPhidgetEncoderHandle phid, int index, int *enabledState);
+ int CPhidgetEncoder_setEnabled(CPhidgetEncoderHandle phid, int index, int enabledState);
+typedef enum {
+ PHIDGET_FREQUENCYCOUNTER_FILTERTYPE_ZERO_CROSSING = 1,
+ PHIDGET_FREQUENCYCOUNTER_FILTERTYPE_LOGIC_LEVEL,
+ PHIDGET_FREQUENCYCOUNTER_FILTERTYPE_UNKNOWN
+} CPhidgetFrequencyCounter_FilterType;
+typedef struct _CPhidgetFrequencyCounter *CPhidgetFrequencyCounterHandle;
+ int CPhidgetFrequencyCounter_create(CPhidgetFrequencyCounterHandle *phid);
+ int CPhidgetFrequencyCounter_getFrequencyInputCount(CPhidgetFrequencyCounterHandle phid, int *count);
+ int CPhidgetFrequencyCounter_getFrequency(CPhidgetFrequencyCounterHandle phid, int index, double *frequency);
+ int CPhidgetFrequencyCounter_getTotalTime(CPhidgetFrequencyCounterHandle phid, int index, __int64 *time);
+ int CPhidgetFrequencyCounter_getTotalCount(CPhidgetFrequencyCounterHandle phid, int index, __int64 *count);
+ int CPhidgetFrequencyCounter_setTimeout(CPhidgetFrequencyCounterHandle phid, int index, int timeout);
+ int CPhidgetFrequencyCounter_getTimeout(CPhidgetFrequencyCounterHandle phid, int index, int *timeout);
+ int CPhidgetFrequencyCounter_setEnabled(CPhidgetFrequencyCounterHandle phid, int index, int enabledState);
+ int CPhidgetFrequencyCounter_getEnabled(CPhidgetFrequencyCounterHandle phid, int index, int *enabledState);
+ int CPhidgetFrequencyCounter_setFilter(CPhidgetFrequencyCounterHandle phid, int index, CPhidgetFrequencyCounter_FilterType filter);
+ int CPhidgetFrequencyCounter_getFilter(CPhidgetFrequencyCounterHandle phid, int index, CPhidgetFrequencyCounter_FilterType *filter);
+ int CPhidgetFrequencyCounter_reset(CPhidgetFrequencyCounterHandle phid, int index);
+ int CPhidgetFrequencyCounter_set_OnCount_Handler(CPhidgetFrequencyCounterHandle phid, int ( *fptr)(CPhidgetFrequencyCounterHandle phid, void *userPtr, int index, int time,int counts), void *userPtr);
+struct __GPSTime
+{
+ short tm_ms;
+ short tm_sec;
+ short tm_min;
+ short tm_hour;
+} typedef GPSTime;
+struct __GPSDate
+{
+ short tm_mday;
+ short tm_mon;
+ short tm_year;
+} typedef GPSDate;
+struct __GPSSatInfo
+{
+ short ID;
+ short elevation;
+ int azimuth;
+ short SNR;
+} typedef GPSSatInfo;
+struct __GPGGA
+{
+ GPSTime time;
+ double latitude;
+ double longitude;
+ short fixQuality;
+ short numSatellites;
+ double horizontalDilution;
+ double altitude;
+ double heightOfGeoid;
+} typedef GPGGA;
+struct __GPGSA
+{
+ char mode;
+ short fixType;
+ short satUsed[12];
+ double posnDilution;
+ double horizDilution;
+ double vertDilution;
+} typedef GPGSA;
+struct __GPGSV
+{
+ short satsInView;
+ GPSSatInfo satInfo[12];
+} typedef GPGSV;
+struct __GPRMC
+{
+ GPSTime time;
+ char status;
+ double latitude;
+ double longitude;
+ double speedKnots;
+ double heading;
+ GPSDate date;
+ double magneticVariation;
+ char mode;
+} typedef GPRMC;
+struct __GPVTG
+{
+ double trueHeading;
+ double magneticHeading;
+ double speedKnots;
+ double speed;
+ char mode;
+} typedef GPVTG;
+struct __NMEAData
+{
+ GPGGA GGA;
+ GPGSA GSA;
+ GPGSV GSV;
+ GPRMC RMC;
+ GPVTG VTG;
+} typedef NMEAData;
+typedef struct _CPhidgetGPS *CPhidgetGPSHandle;
+ int CPhidgetGPS_create(CPhidgetGPSHandle *phid);
+ int CPhidgetGPS_getLatitude(CPhidgetGPSHandle phid, double *latitude);
+ int CPhidgetGPS_getLongitude(CPhidgetGPSHandle phid, double *longitude);
+ int CPhidgetGPS_getAltitude(CPhidgetGPSHandle phid, double *altitude);
+ int CPhidgetGPS_getHeading(CPhidgetGPSHandle phid, double *heading);
+ int CPhidgetGPS_getVelocity(CPhidgetGPSHandle phid, double *velocity);
+ int CPhidgetGPS_getTime(CPhidgetGPSHandle phid, GPSTime *time);
+ int CPhidgetGPS_getDate(CPhidgetGPSHandle phid, GPSDate *date);
+ int CPhidgetGPS_getPositionFixStatus(CPhidgetGPSHandle phid, int *fixStatus);
+ int CPhidgetGPS_getNMEAData(CPhidgetGPSHandle phid, NMEAData *data);
+ int CPhidgetGPS_set_OnPositionChange_Handler(CPhidgetGPSHandle phid, int ( *fptr)(CPhidgetGPSHandle phid, void *userPtr, double latitude,double longitude,double altitude), void *userPtr);
+ int CPhidgetGPS_set_OnPositionFixStatusChange_Handler(CPhidgetGPSHandle phid, int ( *fptr)(CPhidgetGPSHandle phid, void *userPtr, int status), void *userPtr);
+typedef struct _CPhidgetInterfaceKit *CPhidgetInterfaceKitHandle;
+ int CPhidgetInterfaceKit_create(CPhidgetInterfaceKitHandle *phid);
+ int CPhidgetInterfaceKit_getInputCount(CPhidgetInterfaceKitHandle phid, int *count);
+ int CPhidgetInterfaceKit_getInputState(CPhidgetInterfaceKitHandle phid, int index, int *inputState);
+ int CPhidgetInterfaceKit_set_OnInputChange_Handler(CPhidgetInterfaceKitHandle phid, int ( *fptr)(CPhidgetInterfaceKitHandle phid, void *userPtr, int index, int inputState), void *userPtr);
+ int CPhidgetInterfaceKit_getOutputCount(CPhidgetInterfaceKitHandle phid, int *count);
+ int CPhidgetInterfaceKit_getOutputState(CPhidgetInterfaceKitHandle phid, int index, int *outputState);
+ int CPhidgetInterfaceKit_setOutputState(CPhidgetInterfaceKitHandle phid, int index, int outputState);
+ int CPhidgetInterfaceKit_set_OnOutputChange_Handler(CPhidgetInterfaceKitHandle phid, int ( *fptr)(CPhidgetInterfaceKitHandle phid, void *userPtr, int index, int outputState), void *userPtr);
+ int CPhidgetInterfaceKit_getSensorCount(CPhidgetInterfaceKitHandle phid, int *count);
+ int CPhidgetInterfaceKit_getSensorValue(CPhidgetInterfaceKitHandle phid, int index, int *sensorValue);
+ int CPhidgetInterfaceKit_getSensorRawValue(CPhidgetInterfaceKitHandle phid, int index, int *sensorRawValue);
+ int CPhidgetInterfaceKit_set_OnSensorChange_Handler(CPhidgetInterfaceKitHandle phid, int ( *fptr)(CPhidgetInterfaceKitHandle phid, void *userPtr, int index, int sensorValue), void *userPtr);
+ int CPhidgetInterfaceKit_getSensorChangeTrigger(CPhidgetInterfaceKitHandle phid, int index, int *trigger);
+ int CPhidgetInterfaceKit_setSensorChangeTrigger(CPhidgetInterfaceKitHandle phid, int index, int trigger);
+ int CPhidgetInterfaceKit_getRatiometric(CPhidgetInterfaceKitHandle phid, int *ratiometric);
+ int CPhidgetInterfaceKit_setRatiometric(CPhidgetInterfaceKitHandle phid, int ratiometric);
+ int CPhidgetInterfaceKit_getDataRate(CPhidgetInterfaceKitHandle phid, int index, int *milliseconds);
+ int CPhidgetInterfaceKit_setDataRate(CPhidgetInterfaceKitHandle phid, int index, int milliseconds);
+ int CPhidgetInterfaceKit_getDataRateMax(CPhidgetInterfaceKitHandle phid, int index, int *max);
+ int CPhidgetInterfaceKit_getDataRateMin(CPhidgetInterfaceKitHandle phid, int index, int *min);
+typedef struct _CPhidgetIR *CPhidgetIRHandle;
+ int CPhidgetIR_create(CPhidgetIRHandle *phid);
+typedef enum {
+ PHIDGET_IR_ENCODING_UNKNOWN = 1,
+ PHIDGET_IR_ENCODING_SPACE,
+ PHIDGET_IR_ENCODING_PULSE,
+ PHIDGET_IR_ENCODING_BIPHASE,
+ PHIDGET_IR_ENCODING_RC5,
+ PHIDGET_IR_ENCODING_RC6
+} CPhidgetIR_Encoding;
+typedef enum {
+ PHIDGET_IR_LENGTH_UNKNOWN = 1,
+ PHIDGET_IR_LENGTH_CONSTANT,
+ PHIDGET_IR_LENGTH_VARIABLE
+} CPhidgetIR_Length;
+typedef struct _CPhidgetIR_CodeInfo
+{
+ int bitCount;
+ CPhidgetIR_Encoding encoding;
+ CPhidgetIR_Length length;
+ int gap;
+ int trail;
+ int header[2];
+ int one[2];
+ int zero[2];
+ int repeat[26];
+ int min_repeat;
+ unsigned char toggle_mask[(128 / 8)];
+ int carrierFrequency;
+ int dutyCycle;
+} CPhidgetIR_CodeInfo, *CPhidgetIR_CodeInfoHandle;
+ int CPhidgetIR_Transmit(CPhidgetIRHandle phid, unsigned char *data, CPhidgetIR_CodeInfoHandle codeInfo);
+ int CPhidgetIR_TransmitRepeat(CPhidgetIRHandle phid);
+ int CPhidgetIR_TransmitRaw(CPhidgetIRHandle phid, int *data, int length, int carrierFrequency, int dutyCycle, int gap);
+ int CPhidgetIR_getRawData(CPhidgetIRHandle phid, int *data, int *dataLength);
+ int CPhidgetIR_getLastCode(CPhidgetIRHandle phid, unsigned char *data, int *dataLength, int *bitCount);
+ int CPhidgetIR_getLastLearnedCode(CPhidgetIRHandle phid, unsigned char *data, int *dataLength, CPhidgetIR_CodeInfo *codeInfo);
+ int CPhidgetIR_set_OnCode_Handler(CPhidgetIRHandle phid, int ( *fptr)(CPhidgetIRHandle phid, void *userPtr, unsigned char *data, int dataLength, int bitCount, int repeat), void *userPtr);
+ int CPhidgetIR_set_OnLearn_Handler(CPhidgetIRHandle phid, int ( *fptr)(CPhidgetIRHandle phid, void *userPtr, unsigned char *data, int dataLength, CPhidgetIR_CodeInfoHandle codeInfo), void *userPtr);
+ int CPhidgetIR_set_OnRawData_Handler(CPhidgetIRHandle phid, int ( *fptr)(CPhidgetIRHandle phid, void *userPtr, int *data, int dataLength), void *userPtr);
+typedef struct _CPhidgetLED *CPhidgetLEDHandle;
+ int CPhidgetLED_create(CPhidgetLEDHandle *phid);
+typedef enum {
+ PHIDGET_LED_CURRENT_LIMIT_20mA = 1,
+ PHIDGET_LED_CURRENT_LIMIT_40mA,
+ PHIDGET_LED_CURRENT_LIMIT_60mA,
+ PHIDGET_LED_CURRENT_LIMIT_80mA
+} CPhidgetLED_CurrentLimit;
+typedef enum {
+ PHIDGET_LED_VOLTAGE_1_7V = 1,
+ PHIDGET_LED_VOLTAGE_2_75V,
+ PHIDGET_LED_VOLTAGE_3_9V,
+ PHIDGET_LED_VOLTAGE_5_0V
+} CPhidgetLED_Voltage;
+ int CPhidgetLED_getLEDCount(CPhidgetLEDHandle phid, int *count);
+ int CPhidgetLED_getDiscreteLED(CPhidgetLEDHandle phid, int index, int *brightness);
+ int CPhidgetLED_setDiscreteLED(CPhidgetLEDHandle phid, int index, int brightness);
+ int CPhidgetLED_getCurrentLimit(CPhidgetLEDHandle phid, CPhidgetLED_CurrentLimit *currentLimit);
+ int CPhidgetLED_setCurrentLimit(CPhidgetLEDHandle phid, CPhidgetLED_CurrentLimit currentLimit);
+ int CPhidgetLED_getVoltage(CPhidgetLEDHandle phid, CPhidgetLED_Voltage *voltage);
+ int CPhidgetLED_setVoltage(CPhidgetLEDHandle phid, CPhidgetLED_Voltage voltage);
+typedef struct _CPhidgetMotorControl *CPhidgetMotorControlHandle;
+ int CPhidgetMotorControl_create(CPhidgetMotorControlHandle *phid);
+ int CPhidgetMotorControl_getMotorCount(CPhidgetMotorControlHandle phid, int *count);
+ int CPhidgetMotorControl_getVelocity(CPhidgetMotorControlHandle phid, int index, double *velocity);
+ int CPhidgetMotorControl_setVelocity(CPhidgetMotorControlHandle phid, int index, double velocity);
+ int CPhidgetMotorControl_set_OnVelocityChange_Handler(CPhidgetMotorControlHandle phid, int ( *fptr)(CPhidgetMotorControlHandle phid, void *userPtr, int index, double velocity), void *userPtr);
+ int CPhidgetMotorControl_getAcceleration(CPhidgetMotorControlHandle phid, int index, double *acceleration);
+ int CPhidgetMotorControl_setAcceleration(CPhidgetMotorControlHandle phid, int index, double acceleration);
+ int CPhidgetMotorControl_getAccelerationMax(CPhidgetMotorControlHandle phid, int index, double *max);
+ int CPhidgetMotorControl_getAccelerationMin(CPhidgetMotorControlHandle phid, int index, double *min);
+ int CPhidgetMotorControl_getCurrent(CPhidgetMotorControlHandle phid, int index, double *current);
+ int CPhidgetMotorControl_set_OnCurrentChange_Handler(CPhidgetMotorControlHandle phid, int ( *fptr)(CPhidgetMotorControlHandle phid, void *userPtr, int index, double current), void *userPtr);
+ int CPhidgetMotorControl_getInputCount(CPhidgetMotorControlHandle phid, int *count);
+ int CPhidgetMotorControl_getInputState(CPhidgetMotorControlHandle phid, int index, int *inputState);
+ int CPhidgetMotorControl_set_OnInputChange_Handler(CPhidgetMotorControlHandle phid, int ( *fptr)(CPhidgetMotorControlHandle phid, void *userPtr, int index, int inputState), void *userPtr);
+ int CPhidgetMotorControl_getEncoderCount(CPhidgetMotorControlHandle phid, int *count);
+ int CPhidgetMotorControl_getEncoderPosition(CPhidgetMotorControlHandle phid, int index, int *position);
+ int CPhidgetMotorControl_setEncoderPosition(CPhidgetMotorControlHandle phid, int index, int position);
+ int CPhidgetMotorControl_set_OnEncoderPositionChange_Handler(CPhidgetMotorControlHandle phid, int ( *fptr)(CPhidgetMotorControlHandle phid, void *userPtr, int index, int time,int positionChange), void *userPtr);
+ int CPhidgetMotorControl_set_OnEncoderPositionUpdate_Handler(CPhidgetMotorControlHandle phid, int ( *fptr)(CPhidgetMotorControlHandle phid, void *userPtr, int index, int positionChange), void *userPtr);
+ int CPhidgetMotorControl_getBackEMFSensingState(CPhidgetMotorControlHandle phid, int index, int *bEMFState);
+ int CPhidgetMotorControl_setBackEMFSensingState(CPhidgetMotorControlHandle phid, int index, int bEMFState);
+ int CPhidgetMotorControl_getBackEMF(CPhidgetMotorControlHandle phid, int index, double *voltage);
+ int CPhidgetMotorControl_set_OnBackEMFUpdate_Handler(CPhidgetMotorControlHandle phid, int ( *fptr)(CPhidgetMotorControlHandle phid, void *userPtr, int index, double voltage), void *userPtr);
+ int CPhidgetMotorControl_getSupplyVoltage(CPhidgetMotorControlHandle phid, double *supplyVoltage);
+ int CPhidgetMotorControl_getBraking(CPhidgetMotorControlHandle phid, int index, double *braking);
+ int CPhidgetMotorControl_setBraking(CPhidgetMotorControlHandle phid, int index, double braking);
+ int CPhidgetMotorControl_getSensorCount(CPhidgetMotorControlHandle phid, int *count);
+ int CPhidgetMotorControl_getSensorValue(CPhidgetMotorControlHandle phid, int index, int *sensorValue);
+ int CPhidgetMotorControl_getSensorRawValue(CPhidgetMotorControlHandle phid, int index, int *sensorRawValue);
+ int CPhidgetMotorControl_set_OnSensorUpdate_Handler(CPhidgetMotorControlHandle phid, int ( *fptr)(CPhidgetMotorControlHandle phid, void *userPtr, int index, int sensorValue), void *userPtr);
+ int CPhidgetMotorControl_getRatiometric(CPhidgetMotorControlHandle phid, int *ratiometric);
+ int CPhidgetMotorControl_setRatiometric(CPhidgetMotorControlHandle phid, int ratiometric);
+ int CPhidgetMotorControl_set_OnCurrentUpdate_Handler(CPhidgetMotorControlHandle phid, int ( *fptr)(CPhidgetMotorControlHandle phid, void *userPtr, int index, double current), void *userPtr);
+typedef struct _CPhidgetPHSensor *CPhidgetPHSensorHandle;
+ int CPhidgetPHSensor_create(CPhidgetPHSensorHandle *phid);
+ int CPhidgetPHSensor_getPH(CPhidgetPHSensorHandle phid, double *ph);
+ int CPhidgetPHSensor_getPHMax(CPhidgetPHSensorHandle phid, double *max);
+ int CPhidgetPHSensor_getPHMin(CPhidgetPHSensorHandle phid, double *min);
+ int CPhidgetPHSensor_set_OnPHChange_Handler(CPhidgetPHSensorHandle phid, int ( *fptr)(CPhidgetPHSensorHandle phid, void *userPtr, double ph), void *userPtr);
+ int CPhidgetPHSensor_getPHChangeTrigger(CPhidgetPHSensorHandle phid, double *trigger);
+ int CPhidgetPHSensor_setPHChangeTrigger(CPhidgetPHSensorHandle phid, double trigger);
+ int CPhidgetPHSensor_getPotential(CPhidgetPHSensorHandle phid, double *potential);
+ int CPhidgetPHSensor_getPotentialMax(CPhidgetPHSensorHandle phid, double *max);
+ int CPhidgetPHSensor_getPotentialMin(CPhidgetPHSensorHandle phid, double *min);
+ int CPhidgetPHSensor_setTemperature(CPhidgetPHSensorHandle phid, double temperature);
+typedef struct _CPhidgetRFID *CPhidgetRFIDHandle;
+ int CPhidgetRFID_create(CPhidgetRFIDHandle *phid);
+ int CPhidgetRFID_getOutputCount(CPhidgetRFIDHandle phid, int *count);
+ int CPhidgetRFID_getOutputState(CPhidgetRFIDHandle phid, int index, int *outputState);
+ int CPhidgetRFID_setOutputState(CPhidgetRFIDHandle phid, int index, int outputState);
+ int CPhidgetRFID_set_OnOutputChange_Handler(CPhidgetRFIDHandle phid, int ( *fptr)(CPhidgetRFIDHandle phid, void *userPtr, int index, int outputState), void *userPtr);
+ int CPhidgetRFID_getAntennaOn(CPhidgetRFIDHandle phid, int *antennaState);
+ int CPhidgetRFID_setAntennaOn(CPhidgetRFIDHandle phid, int antennaState);
+ int CPhidgetRFID_getLEDOn(CPhidgetRFIDHandle phid, int *LEDState);
+ int CPhidgetRFID_setLEDOn(CPhidgetRFIDHandle phid, int LEDState);
+ int CPhidgetRFID_getLastTag(CPhidgetRFIDHandle phid, unsigned char *tag);
+ int CPhidgetRFID_getTagStatus(CPhidgetRFIDHandle phid, int *status);
+ int CPhidgetRFID_set_OnTag_Handler(CPhidgetRFIDHandle phid, int ( *fptr)(CPhidgetRFIDHandle phid, void *userPtr, unsigned char *tag), void *userPtr);
+ int CPhidgetRFID_set_OnTagLost_Handler(CPhidgetRFIDHandle phid, int ( *fptr)(CPhidgetRFIDHandle phid, void *userPtr, unsigned char *tag), void *userPtr);
+typedef struct _CPhidgetServo *CPhidgetServoHandle;
+ int CPhidgetServo_create(CPhidgetServoHandle *phid);
+ int CPhidgetServo_getMotorCount(CPhidgetServoHandle phid, int *count);
+ int CPhidgetServo_getPosition(CPhidgetServoHandle phid, int index, double *position);
+ int CPhidgetServo_setPosition(CPhidgetServoHandle phid, int index, double position);
+ int CPhidgetServo_getPositionMax(CPhidgetServoHandle phid, int index, double *max);
+ int CPhidgetServo_getPositionMin(CPhidgetServoHandle phid, int index, double *min);
+ int CPhidgetServo_set_OnPositionChange_Handler(CPhidgetServoHandle phid, int ( *fptr)(CPhidgetServoHandle phid, void *userPtr, int index, double position), void *userPtr);
+ int CPhidgetServo_getEngaged(CPhidgetServoHandle phid, int index, int *engagedState);
+ int CPhidgetServo_setEngaged(CPhidgetServoHandle phid, int index, int engagedState);
+ int CPhidgetServo_getServoType(CPhidgetServoHandle phid, int index, CPhidget_ServoType *servoType);
+ int CPhidgetServo_setServoType(CPhidgetServoHandle phid, int index, CPhidget_ServoType servoType);
+ int CPhidgetServo_setServoParameters(CPhidgetServoHandle phid, int index, double min_us,double max_us,double degrees);
+typedef struct _CPhidgetSpatial *CPhidgetSpatialHandle;
+ int CPhidgetSpatial_create(CPhidgetSpatialHandle *phid);
+typedef struct _CPhidgetSpatial_SpatialEventData
+{
+ double acceleration[3];
+ double angularRate[3];
+ double magneticField[3];
+ CPhidget_Timestamp timestamp;
+} CPhidgetSpatial_SpatialEventData, *CPhidgetSpatial_SpatialEventDataHandle;
+ int CPhidgetSpatial_getAccelerationAxisCount(CPhidgetSpatialHandle phid, int *count);
+ int CPhidgetSpatial_getGyroAxisCount(CPhidgetSpatialHandle phid, int *count);
+ int CPhidgetSpatial_getCompassAxisCount(CPhidgetSpatialHandle phid, int *count);
+ int CPhidgetSpatial_getAcceleration(CPhidgetSpatialHandle phid, int index, double *acceleration);
+ int CPhidgetSpatial_getAccelerationMax(CPhidgetSpatialHandle phid, int index, double *max);
+ int CPhidgetSpatial_getAccelerationMin(CPhidgetSpatialHandle phid, int index, double *min);
+ int CPhidgetSpatial_getAngularRate(CPhidgetSpatialHandle phid, int index, double *angularRate);
+ int CPhidgetSpatial_getAngularRateMax(CPhidgetSpatialHandle phid, int index, double *max);
+ int CPhidgetSpatial_getAngularRateMin(CPhidgetSpatialHandle phid, int index, double *min);
+ int CPhidgetSpatial_getMagneticField(CPhidgetSpatialHandle phid, int index, double *magneticField);
+ int CPhidgetSpatial_getMagneticFieldMax(CPhidgetSpatialHandle phid, int index, double *max);
+ int CPhidgetSpatial_getMagneticFieldMin(CPhidgetSpatialHandle phid, int index, double *min);
+ int CPhidgetSpatial_zeroGyro(CPhidgetSpatialHandle phid);
+ int CPhidgetSpatial_getDataRate(CPhidgetSpatialHandle phid, int *milliseconds);
+ int CPhidgetSpatial_setDataRate(CPhidgetSpatialHandle phid, int milliseconds);
+ int CPhidgetSpatial_getDataRateMax(CPhidgetSpatialHandle phid, int *max);
+ int CPhidgetSpatial_getDataRateMin(CPhidgetSpatialHandle phid, int *min);
+ int CPhidgetSpatial_setCompassCorrectionParameters(CPhidgetSpatialHandle phid, double magField, double offset0, double offset1, double offset2, double gain0, double gain1, double gain2, double T0, double T1, double T2, double T3, double T4, double T5);
+ int CPhidgetSpatial_resetCompassCorrectionParameters(CPhidgetSpatialHandle phid);
+ int CPhidgetSpatial_set_OnSpatialData_Handler(CPhidgetSpatialHandle phid, int ( *fptr)(CPhidgetSpatialHandle phid, void *userPtr, CPhidgetSpatial_SpatialEventDataHandle *data, int dataCount), void *userPtr);
+typedef struct _CPhidgetStepper *CPhidgetStepperHandle;
+ int CPhidgetStepper_create(CPhidgetStepperHandle *phid);
+ int CPhidgetStepper_getInputCount(CPhidgetStepperHandle phid, int *count);
+ int CPhidgetStepper_getInputState(CPhidgetStepperHandle phid, int index, int *inputState);
+ int CPhidgetStepper_set_OnInputChange_Handler(CPhidgetStepperHandle phid, int ( *fptr)(CPhidgetStepperHandle phid, void *userPtr, int index, int inputState), void *userPtr);
+ int CPhidgetStepper_getMotorCount(CPhidgetStepperHandle phid, int *count);
+ int CPhidgetStepper_getAcceleration(CPhidgetStepperHandle phid, int index, double *acceleration);
+ int CPhidgetStepper_setAcceleration(CPhidgetStepperHandle phid, int index, double acceleration);
+ int CPhidgetStepper_getAccelerationMax(CPhidgetStepperHandle phid, int index, double *max);
+ int CPhidgetStepper_getAccelerationMin(CPhidgetStepperHandle phid, int index, double *min);
+ int CPhidgetStepper_getVelocityLimit(CPhidgetStepperHandle phid, int index, double *limit);
+ int CPhidgetStepper_setVelocityLimit(CPhidgetStepperHandle phid, int index, double limit);
+ int CPhidgetStepper_getVelocity(CPhidgetStepperHandle phid, int index, double *velocity);
+ int CPhidgetStepper_getVelocityMax(CPhidgetStepperHandle phid, int index, double *max);
+ int CPhidgetStepper_getVelocityMin(CPhidgetStepperHandle phid, int index, double *min);
+ int CPhidgetStepper_set_OnVelocityChange_Handler(CPhidgetStepperHandle phid, int ( *fptr)(CPhidgetStepperHandle phid, void *userPtr, int index, double velocity), void *userPtr);
+ int CPhidgetStepper_getTargetPosition(CPhidgetStepperHandle phid, int index, __int64 *position);
+ int CPhidgetStepper_setTargetPosition(CPhidgetStepperHandle phid, int index, __int64 position);
+ int CPhidgetStepper_getCurrentPosition(CPhidgetStepperHandle phid, int index, __int64 *position);
+ int CPhidgetStepper_setCurrentPosition(CPhidgetStepperHandle phid, int index, __int64 position);
+ int CPhidgetStepper_getPositionMax(CPhidgetStepperHandle phid, int index, __int64 *max);
+ int CPhidgetStepper_getPositionMin(CPhidgetStepperHandle phid, int index, __int64 *min);
+ int CPhidgetStepper_set_OnPositionChange_Handler(CPhidgetStepperHandle phid, int ( *fptr)(CPhidgetStepperHandle phid, void *userPtr, int index, __int64 position), void *userPtr);
+ int CPhidgetStepper_getCurrentLimit(CPhidgetStepperHandle phid, int index, double *limit);
+ int CPhidgetStepper_setCurrentLimit(CPhidgetStepperHandle phid, int index, double limit);
+ int CPhidgetStepper_getCurrent(CPhidgetStepperHandle phid, int index, double *current);
+ int CPhidgetStepper_getCurrentMax(CPhidgetStepperHandle phid, int index, double *max);
+ int CPhidgetStepper_getCurrentMin(CPhidgetStepperHandle phid, int index, double *min);
+ int CPhidgetStepper_set_OnCurrentChange_Handler(CPhidgetStepperHandle phid, int ( *fptr)(CPhidgetStepperHandle phid, void *userPtr, int index, double current), void *userPtr);
+ int CPhidgetStepper_getEngaged(CPhidgetStepperHandle phid, int index, int *engagedState);
+ int CPhidgetStepper_setEngaged(CPhidgetStepperHandle phid, int index, int engagedState);
+ int CPhidgetStepper_getStopped(CPhidgetStepperHandle phid, int index, int *stoppedState);
+typedef struct _CPhidgetTemperatureSensor *CPhidgetTemperatureSensorHandle;
+ int CPhidgetTemperatureSensor_create(CPhidgetTemperatureSensorHandle *phid);
+typedef enum {
+ PHIDGET_TEMPERATURE_SENSOR_K_TYPE = 1,
+ PHIDGET_TEMPERATURE_SENSOR_J_TYPE,
+ PHIDGET_TEMPERATURE_SENSOR_E_TYPE,
+ PHIDGET_TEMPERATURE_SENSOR_T_TYPE
+} CPhidgetTemperatureSensor_ThermocoupleType;
+ int CPhidgetTemperatureSensor_getTemperatureInputCount(CPhidgetTemperatureSensorHandle phid, int *count);
+ int CPhidgetTemperatureSensor_getTemperature(CPhidgetTemperatureSensorHandle phid, int index, double *temperature);
+ int CPhidgetTemperatureSensor_getTemperatureMax(CPhidgetTemperatureSensorHandle phid, int index, double *max);
+ int CPhidgetTemperatureSensor_getTemperatureMin(CPhidgetTemperatureSensorHandle phid, int index, double *min);
+ int CPhidgetTemperatureSensor_set_OnTemperatureChange_Handler(CPhidgetTemperatureSensorHandle phid, int ( *fptr)(CPhidgetTemperatureSensorHandle phid, void *userPtr, int index, double temperature), void *userPtr);
+ int CPhidgetTemperatureSensor_getTemperatureChangeTrigger(CPhidgetTemperatureSensorHandle phid, int index, double *trigger);
+ int CPhidgetTemperatureSensor_setTemperatureChangeTrigger(CPhidgetTemperatureSensorHandle phid, int index, double trigger);
+ int CPhidgetTemperatureSensor_getPotential(CPhidgetTemperatureSensorHandle phid, int index, double *potential);
+ int CPhidgetTemperatureSensor_getPotentialMax(CPhidgetTemperatureSensorHandle phid, int index, double *max);
+ int CPhidgetTemperatureSensor_getPotentialMin(CPhidgetTemperatureSensorHandle phid, int index, double *min);
+ int CPhidgetTemperatureSensor_getAmbientTemperature(CPhidgetTemperatureSensorHandle phid, double *ambient);
+ int CPhidgetTemperatureSensor_getAmbientTemperatureMax(CPhidgetTemperatureSensorHandle phid, double *max);
+ int CPhidgetTemperatureSensor_getAmbientTemperatureMin(CPhidgetTemperatureSensorHandle phid, double *min);
+ int CPhidgetTemperatureSensor_getThermocoupleType(CPhidgetTemperatureSensorHandle phid, int index, CPhidgetTemperatureSensor_ThermocoupleType *type);
+ int CPhidgetTemperatureSensor_setThermocoupleType(CPhidgetTemperatureSensorHandle phid, int index, CPhidgetTemperatureSensor_ThermocoupleType type);
+typedef struct _CPhidgetTextLCD *CPhidgetTextLCDHandle;
+ int CPhidgetTextLCD_create(CPhidgetTextLCDHandle *phid);
+ int CPhidgetTextLCD_getRowCount(CPhidgetTextLCDHandle phid, int *count);
+ int CPhidgetTextLCD_getColumnCount(CPhidgetTextLCDHandle phid, int *count);
+ int CPhidgetTextLCD_getBacklight(CPhidgetTextLCDHandle phid, int *backlightState);
+ int CPhidgetTextLCD_setBacklight(CPhidgetTextLCDHandle phid, int backlightState);
+ int CPhidgetTextLCD_getBrightness(CPhidgetTextLCDHandle phid, int *brightness);
+ int CPhidgetTextLCD_setBrightness(CPhidgetTextLCDHandle phid, int brightness);
+ int CPhidgetTextLCD_getContrast(CPhidgetTextLCDHandle phid, int *contrast);
+ int CPhidgetTextLCD_setContrast(CPhidgetTextLCDHandle phid, int contrast);
+ int CPhidgetTextLCD_getCursorOn(CPhidgetTextLCDHandle phid, int *cursorState);
+ int CPhidgetTextLCD_setCursorOn(CPhidgetTextLCDHandle phid, int cursorState);
+ int CPhidgetTextLCD_getCursorBlink(CPhidgetTextLCDHandle phid, int *cursorBlinkState);
+ int CPhidgetTextLCD_setCursorBlink(CPhidgetTextLCDHandle phid, int cursorBlinkState);
+ int CPhidgetTextLCD_setCustomCharacter(CPhidgetTextLCDHandle phid, int index, int var1,int var2);
+ int CPhidgetTextLCD_setDisplayCharacter(CPhidgetTextLCDHandle phid, int index, int column,unsigned char character);
+ int CPhidgetTextLCD_setDisplayString(CPhidgetTextLCDHandle phid, int index, char *displayString);
+typedef enum {
+ PHIDGET_TEXTLCD_SCREEN_NONE = 1,
+ PHIDGET_TEXTLCD_SCREEN_1x8,
+ PHIDGET_TEXTLCD_SCREEN_2x8,
+ PHIDGET_TEXTLCD_SCREEN_1x16,
+ PHIDGET_TEXTLCD_SCREEN_2x16,
+ PHIDGET_TEXTLCD_SCREEN_4x16,
+ PHIDGET_TEXTLCD_SCREEN_2x20,
+ PHIDGET_TEXTLCD_SCREEN_4x20,
+ PHIDGET_TEXTLCD_SCREEN_2x24,
+ PHIDGET_TEXTLCD_SCREEN_1x40,
+ PHIDGET_TEXTLCD_SCREEN_2x40,
+ PHIDGET_TEXTLCD_SCREEN_4x40,
+ PHIDGET_TEXTLCD_SCREEN_UNKNOWN
+} CPhidgetTextLCD_ScreenSize;
+ int CPhidgetTextLCD_getScreenCount(CPhidgetTextLCDHandle phid, int *count);
+ int CPhidgetTextLCD_getScreen(CPhidgetTextLCDHandle phid, int *screenIndex);
+ int CPhidgetTextLCD_setScreen(CPhidgetTextLCDHandle phid, int screenIndex);
+ int CPhidgetTextLCD_getScreenSize(CPhidgetTextLCDHandle phid, CPhidgetTextLCD_ScreenSize *screenSize);
+ int CPhidgetTextLCD_setScreenSize(CPhidgetTextLCDHandle phid, CPhidgetTextLCD_ScreenSize screenSize);
+ int CPhidgetTextLCD_initialize(CPhidgetTextLCDHandle phid);
+typedef struct _CPhidgetTextLED *CPhidgetTextLEDHandle;
+ int CPhidgetTextLED_create(CPhidgetTextLEDHandle *phid);
+ int CPhidgetTextLED_getRowCount(CPhidgetTextLEDHandle phid, int *count);
+ int CPhidgetTextLED_getColumnCount(CPhidgetTextLEDHandle phid, int *count);
+ int CPhidgetTextLED_getBrightness(CPhidgetTextLEDHandle phid, int *brightness);
+ int CPhidgetTextLED_setBrightness(CPhidgetTextLEDHandle phid, int brightness);
+ int CPhidgetTextLED_setDisplayString(CPhidgetTextLEDHandle phid, int index, char *displayString);
+typedef struct _CPhidgetWeightSensor *CPhidgetWeightSensorHandle;
+ int CPhidgetWeightSensor_create(CPhidgetWeightSensorHandle *phid);
+ int CPhidgetWeightSensor_getWeight(CPhidgetWeightSensorHandle phid, double *weight);
+ int CPhidgetWeightSensor_set_OnWeightChange_Handler(CPhidgetWeightSensorHandle phid, int ( *fptr)(CPhidgetWeightSensorHandle phid, void *userPtr, double weight), void *userPtr);
+ int CPhidgetWeightSensor_getWeightChangeTrigger(CPhidgetWeightSensorHandle phid, double *trigger);
+ int CPhidgetWeightSensor_setWeightChangeTrigger(CPhidgetWeightSensorHandle phid, double trigger);
+#ifndef CPHIDGET_CONSTANTS
+#define CPHIDGET_CONSTANTS
+
+/** \defgroup phidconst Phidget Constants
+ * Various constants used throughout the library.
+ * @{
+ */
+
+/** \name Phidget States
+ * Returned by getStatus() functions
+ * @{
+ */
+#define PHIDGET_ATTACHED 0x1 /**< Phidget attached */
+#define PHIDGET_NOTATTACHED 0x0 /**< Phidget not attached */
+/** @} */
+
+//Adding error codes: Update .NET, COM, Python, Java
+/** \name Phidget Error Codes
+ * Returned by all C API calls
+ * @{
+ */
+#define PHIDGET_ERROR_CODE_COUNT 20
+#define EPHIDGET_OK 0 /**< Function completed successfully. */
+#define EPHIDGET_NOTFOUND 1 /**< Phidget not found. "A Phidget matching the type and or serial number could not be found." */
+#define EPHIDGET_NOMEMORY 2 /**< No memory. "Memory could not be allocated." */
+#define EPHIDGET_UNEXPECTED 3 /**< Unexpected. "Unexpected Error. Contact Phidgets Inc. for support." */
+#define EPHIDGET_INVALIDARG 4 /**< Invalid argument. "Invalid argument passed to function." */
+#define EPHIDGET_NOTATTACHED 5 /**< Phidget not attached. "Phidget not physically attached." */
+#define EPHIDGET_INTERRUPTED 6 /**< Interrupted. "Read/Write operation was interrupted." This code is not currently used. */
+#define EPHIDGET_INVALID 7 /**< Invalid error code. "The Error Code is not defined." */
+#define EPHIDGET_NETWORK 8 /**< Network. "Network Error." */
+#define EPHIDGET_UNKNOWNVAL 9 /**< Value unknown. "Value is Unknown (State not yet received from device, or not yet set by user)." */
+#define EPHIDGET_BADPASSWORD 10 /**< Authorization exception. "No longer used. Replaced by EEPHIDGET_BADPASSWORD" */
+#define EPHIDGET_UNSUPPORTED 11 /**< Unsupported. "Not Supported." */
+#define EPHIDGET_DUPLICATE 12 /**< Duplicate request. "Duplicated request." */
+#define EPHIDGET_TIMEOUT 13 /**< Timeout. "Given timeout has been exceeded." */
+#define EPHIDGET_OUTOFBOUNDS 14 /**< Out of bounds. "Index out of Bounds." */
+#define EPHIDGET_EVENT 15 /**< Event. "A non-null error code was returned from an event handler." This code is not currently used. */
+#define EPHIDGET_NETWORK_NOTCONNECTED 16 /**< Network not connected. "A connection to the server does not exist." */
+#define EPHIDGET_WRONGDEVICE 17 /**< Wrong device. "Function is not applicable for this device." */
+#define EPHIDGET_CLOSED 18 /**< Phidget Closed. "Phidget handle was closed." */
+#define EPHIDGET_BADVERSION 19 /**< Version Mismatch. "No longer used. Replaced by EEPHIDGET_BADVERSION" */
+/** @} */
+
+//Adding error codes: Update .NET, COM, Python, Java
+/** \name Phidget Error Event Codes
+ * Returned in the Phidget error event
+ * @{
+ */
+#define EEPHIDGET_EVENT_ERROR(code) (0x8000 + code)
+
+
+//Library errors
+#define EEPHIDGET_NETWORK EEPHIDGET_EVENT_ERROR(0x0001) /**< Network Error (asynchronous). */
+#define EEPHIDGET_BADPASSWORD EEPHIDGET_EVENT_ERROR(0x0002) /**< Authorization Failed. */
+#define EEPHIDGET_BADVERSION EEPHIDGET_EVENT_ERROR(0x0003) /**< Webservice and Client protocol versions don't match. Update to newest release. */
+
+//Errors streamed back from firmware
+#define EEPHIDGET_OK EEPHIDGET_EVENT_ERROR(0x1000) /**< An error state has ended - see description for details. */
+#define EEPHIDGET_OVERRUN EEPHIDGET_EVENT_ERROR(0x1002) /**< A sampling overrun happend in firmware. */
+#define EEPHIDGET_PACKETLOST EEPHIDGET_EVENT_ERROR(0x1003) /**< One or more packets were lost. */
+#define EEPHIDGET_WRAP EEPHIDGET_EVENT_ERROR(0x1004) /**< A variable has wrapped around. */
+#define EEPHIDGET_OVERTEMP EEPHIDGET_EVENT_ERROR(0x1005) /**< Overtemperature condition detected. */
+#define EEPHIDGET_OVERCURRENT EEPHIDGET_EVENT_ERROR(0x1006) /**< Overcurrent condition detected. */
+#define EEPHIDGET_OUTOFRANGE EEPHIDGET_EVENT_ERROR(0x1007) /**< Out of range condition detected. */
+#define EEPHIDGET_BADPOWER EEPHIDGET_EVENT_ERROR(0x1008) /**< Power supply problem detected. */
+
+/** @} */
+
+/** \name Phidget Unknown Constants
+ * Data values will be set to these constants when a call fails with \ref EPHIDGET_UNKNOWNVAL.
+ * @{
+ */
+#define PUNK_BOOL 0x02 /**< Unknown Boolean (unsigned char) */
+#define PUNK_SHRT 0x7FFF /**< Unknown Short (16-bit) */
+#define PUNK_INT 0x7FFFFFFF /**< Unknown Integer (32-bit) */
+#define PUNK_INT64 0x7FFFFFFFFFFFFFFFLL /**< Unknown Integer (64-bit) */
+#define PUNK_DBL 1e300 /**< Unknown Double */
+#define PUNK_FLT 1e30 /**< Unknown Float */
+/** @} */
+
+#define PFALSE 0x00 /**< False. Used for boolean values. */
+#define PTRUE 0x01 /**< True. Used for boolean values. */
+
+/** @} */
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/phidget21int.h b/phidget21int.h
new file mode 100644
index 0000000..d0d4547
--- /dev/null
+++ b/phidget21int.h
@@ -0,0 +1,135 @@
+#ifndef __PHIDGET21
+#define __PHIDGET21
+
+ /*! \mainpage Phidget21 C API Documentation
+ *
+ * Describes the Application Program Interface (API) for each Phidget device.
+ * The API can be used by a number of languages;
+ * this manual discusses use via C and the code examples reflect this.
+ *
+ * \section howto_sec How to use Phidgets
+ Phidgets are an easy to use set of building blocks for low cost sensing and control from your PC.
+ Using the Universal Serial Bus (USB) as the basis for all Phidgets, the complexity is managed behind
+ this easy to use and robust Application Program Interface (API) library.
+
+ The library was written originally for Windows, but has been ported to MacOS and Linux.
+ Although the library is written in C, the functions can be called from a number of languages including C, C++, Objective-C, Matlab, etc.
+ The full library source is not available for all platforms - however, the Linux distribution contains all platform independent code.
+
+ See the <a class="el" href="modules.html">Modules</a> section for the API documentation.
+
+ See \ref phidcommon for calls common to all phidgets.
+
+ Refer to the <a class="el" href="http://www.phidgets.com/information.php#products" target="_blank">Product manual</a> for your Phidget and the
+ <a class="el" href="http://www.phidgets.com/documentation/Programming_Manual.pdf" target="_blank">Programming Manual</a> for more detailed, language inspecific API documentation.
+ Also, there are a set of C/C++ examples available for download.
+
+ \section general_sec General Usage
+Phidgets in C are accessed/controlled via handles. Every Phidget has it's own Handle, as well as a generic Phidget handle. These handles are simply pointers
+from the user's perspective - internally, they point to structures. Almost every function in the API takes a Phidget handle as the first argument.
+
+phidget21.h contains the API calls for all Phidgets. It should be included in any programs which need to access the Phidget C Library from C/C++.
+
+Note that this file is not distributed in the source, this file is generated from the source using the C preproccessor. It is installed with the libraries.
+
+The first step is to create the handle. Every phidget has it's own _create function. This creates space for the structure internally and gives you a
+valid Handle for passing to all other Phidget functions.
+
+The next step is to register event handlers. These need to be registered now, because they only throw events in the future,
+and if they are registered later, you will miss events. Every Phidget event takes a Phidget handle, a function callback pointer and
+a user defined pointer, which is passed back from within the callback.
+
+The next step is to open the Phidget. This is done with either \ref CPhidget_open, \ref CPhidget_openRemote or \ref CPhidget_openRemoteIP, depending on whether you want
+to open the Phidget locally or over the network. Open returns right away (is asynchronous) so you have to either wait for the attach event,
+or call \ref CPhidget_waitForAttachment before using the handle further.
+
+The next step it to actually use the Phidget. Once attached, all functions can be called. Device specific handles should be cast to \ref CPhidgetHandle for use
+with the common API functions.
+
+Once finished, you should call first \ref CPhidget_close and then \ref CPhidget_delete to clean up the connection to the Phidget and the Handle before exiting.
+
+\section return_sec Return Codes
+Every Phidget function returns an int. A return code of 0 means success, anything else means failure. The failure codes are documented here: \ref phidconst.
+
+When a value is unknown, in addition to returning an error code, the pointer will be set to one of the unknonwn values documented here: \ref phidconst.
+ *
+ */
+
+/** \defgroup phidgets Specific Phidgets
+ */
+
+#ifdef _WINDOWS
+ #ifdef PHIDGET21_EXPORTS
+ #ifndef PHIDGET21_API
+ #define PHIDGET21_API
+ #endif
+ #else
+ #ifndef PHIDGET21_API
+ #define PHIDGET21_API __declspec(dllimport)
+ #endif
+ #endif
+ #ifndef CCONV
+ #define CCONV __stdcall
+ #endif
+ #ifndef DEPRECATE_WIN
+ #define DEPRECATE_WIN(depmsg) __declspec(deprecated( depmsg ))
+ #endif
+ #ifndef DEPRECATE_GCC
+ #define DEPRECATE_GCC
+ #endif
+
+#else
+ #ifndef PHIDGET21_API
+ #define PHIDGET21_API
+ #endif
+ #ifndef CCONV
+ #define CCONV
+ #endif
+ #ifndef DEPRECATE_GCC
+ #define DEPRECATE_GCC __attribute__ ((deprecated))
+ #endif
+ #ifndef DEPRECATE_WIN
+ #define DEPRECATE_WIN(depmsg)
+ #endif
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "cphidget.h"
+#include "cphidgetdictionary.h"
+#include "csocket.h"
+#include "clog.h"
+#include "cphidgetaccelerometer.h"
+#include "cphidgetadvancedservo.h"
+#include "cphidgetanalog.h"
+#include "cphidgetbridge.h"
+#include "cphidgetencoder.h"
+#include "cphidgetfrequencycounter.h"
+#include "cphidgetgps.h"
+#include "cphidgetinterfacekit.h"
+#include "cphidgetir.h"
+#include "cphidgetmanager.h"
+#include "cphidgetled.h"
+#include "cphidgetmotorcontrol.h"
+#include "cphidgetphsensor.h"
+#include "cphidgetrfid.h"
+#include "cphidgetservo.h"
+#include "cphidgetspatial.h"
+#include "cphidgetstepper.h"
+#include "cphidgettemperaturesensor.h"
+#include "cphidgettextlcd.h"
+#include "cphidgettextled.h"
+#include "cphidgetweightsensor.h"
+//Only include in the debug header
+#if defined(DEBUG) || !defined(EXTERNALPROTO)
+ #include "cphidgetgeneric.h"
+ #include "cphidgetsbc.h"
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/stdafx.h b/stdafx.h
new file mode 100644
index 0000000..fce61f2
--- /dev/null
+++ b/stdafx.h
@@ -0,0 +1,272 @@
+// stdafx.h : include file for standard system include files,
+// or project specific include files that are used frequently, but
+// are changed infrequently
+//
+
+#ifndef __STDAFX
+#define __STDAFX
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#ifdef WINCE
+ int errno;
+ #define strerror(err) "strerror() Not Supported in Windows CE"
+ #define abort() exit(1)
+ #define EAGAIN 35
+ #define EINTR 4
+#else
+ #include <sys/types.h>
+ #include <errno.h>
+#endif
+
+#define USE_PHIDGET21_LOGGING
+
+//use zeroconf
+#ifdef NO_ZEROCONF
+ #ifdef USE_ZEROCONF
+ #undef USE_ZEROCONF
+ #endif
+#else
+ #ifndef USE_ZEROCONF
+ #define USE_ZEROCONF
+ #endif
+#endif
+
+//iPhone, Android doesn't have libiconv
+#if defined(_IPHONE) || defined(_ANDROID)
+ #define USE_INTERNAL_UNICONV
+#endif
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#ifdef _WINDOWS
+// Defines & Include for Windows only
+
+ //On Windows (but not WinCE), compile in Labview functions
+ #ifndef WINCE
+ #ifndef COMPILE_PHIDGETS_LABVIEW
+ #define COMPILE_PHIDGETS_LABVIEW
+ #endif
+ #endif
+
+ //use runtime linking for zeroconf
+ #ifndef ZEROCONF_RUNTIME_LINKING
+ #define ZEROCONF_RUNTIME_LINKING
+ #endif
+
+ //On Windows (but not WinCE), compile in internal .local lookup (faster then letting Windows do it)
+ #ifndef WINCE
+ #ifndef ZEROCONF_LOOKUP
+ #define ZEROCONF_LOOKUP
+ #endif
+ #endif
+
+ // Modify the following defines if you have to target a platform prior to the ones specified below.
+ // Refer to MSDN for the latest info on corresponding values for different platforms.
+ #ifndef WINVER // Allow use of features specific to Windows XP or later.
+ #define WINVER 0x0500 // Change this to the appropriate value to target other versions of Windows.
+ #endif
+
+ #ifndef _WIN32_WINNT // Allow use of features specific to Windows XP or later.
+ #define _WIN32_WINNT 0x0500 // Change this to the appropriate value to target other versions of Windows.
+ #endif
+
+ #ifndef _WIN32_WINDOWS // Allow use of features specific to Windows 98 or later.
+ #define _WIN32_WINDOWS 0x0410 // Change this to the appropriate value to target Windows Me or later.
+ #endif
+
+ #ifndef _WIN32_IE // Allow use of features specific to IE 6.0 or later.
+ #define _WIN32_IE 0x0600 // Change this to the appropriate value to target other versions of IE.
+ #endif
+
+ #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
+ // Windows Header Files:
+ #ifndef _CYGWIN
+ #include <Winsock2.h>
+ #include <ws2tcpip.h>
+ #endif
+ #if !defined(WINCE) && defined(_MSC_EXTENSIONS)
+ #include <Wspiapi.h>
+ #endif
+
+ #include <windows.h>
+ #include <winbase.h>
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <time.h>
+ #include <assert.h>
+ #include <math.h>
+
+ #ifdef USE_INTERNAL_UNICONV
+ #include "cvtutf.h"
+ #else
+ #include <locale.h>
+ #endif
+
+ #ifdef _MSC_EXTENSIONS
+ #include "snprintf.h"
+ #endif
+ #ifndef _CYGWIN
+ #include "wincompat.h"
+ #endif
+
+ #define strdup _strdup
+ #define snprintf _snprintf
+
+ #define strtoll (__int64)_strtoi64
+
+ #define CCONV __stdcall
+ #define CCONV_CDECL __cdecl
+ #define SLEEP(dlay) Sleep(dlay);
+ #define ZEROMEM(var,size) ZeroMemory(var, size);
+
+ #ifdef PHIDGET21_EXPORTS
+ #ifndef PHIDGET21_API
+ #define PHIDGET21_API
+ #endif
+ #else
+ #ifndef PHIDGET21_API
+ #define PHIDGET21_API __declspec(dllimport)
+ #endif
+ #endif
+
+ typedef SYSTEMTIME TIME;
+ typedef unsigned __int64 __uint64;
+
+ typedef int ssize_t;
+
+ #define C_IN 1
+ #define NETDB_INTERNAL -1
+
+ #ifndef DEPRECATE_WIN
+ #define DEPRECATE_WIN(depmsg) __declspec(deprecated( depmsg ))
+ #endif
+ #ifndef DEPRECATE_GCC
+ #define DEPRECATE_GCC
+ #endif
+
+#ifndef ECANCELED
+#define ECANCELED 89
+#endif
+
+#else
+// Defines & Include for both Mac and Linux
+ #include <semaphore.h>
+ #include <time.h>
+ #include <stdio.h>
+ #include <stdarg.h>
+ #include <stdlib.h>
+ #include <string.h>
+ #include <pthread.h>
+ #include <errno.h>
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ #include <netinet/in.h>
+ #include <arpa/inet.h>
+ #include <arpa/nameser.h>
+ #include <netdb.h>
+ #include <unistd.h>
+ #include <sys/time.h>
+ #include <ctype.h>
+ #include <math.h>
+ #ifdef USE_INTERNAL_UNICONV
+ #include "cvtutf.h"
+ #else
+ #include <iconv.h>
+ #endif
+
+ #define CCONV
+ #define CCONV_CDECL
+ #define SLEEP(dlay) usleep(dlay*1000);
+ #define ZEROMEM(var,size) memset(var, 0, size);
+ #ifndef PHIDGET21_API
+ #define PHIDGET21_API
+ #endif
+ typedef void *HANDLE;
+ #define INFINITE 0xFFFFFFFF
+ typedef long *LPDWORD;
+ #define STILL_ACTIVE 0x00000103L
+ #define WAIT_TIMEOUT 258L
+ #define WAIT_ABANDONED 0x00000080
+ #define WAIT_OBJECT_0 0x00000000L
+ #define WAIT_FAILED 0xFFFFFFFF
+ typedef int SOCKET;
+ #define INVALID_SOCKET -1
+ #ifndef SOCKET_ERROR
+ #define SOCKET_ERROR -1
+ #endif
+ typedef void *OVERLAPPED;
+ //typedef long long __int64;
+ typedef unsigned long long __uint64;
+
+ typedef struct timeval TIME;
+
+ #ifndef DEPRECATE_GCC
+ #define DEPRECATE_GCC __attribute__ ((deprecated))
+ #endif
+ #ifndef DEPRECATE_WIN
+ #define DEPRECATE_WIN(depmsg)
+ #endif
+
+ #ifdef _MACOSX
+// Defines & Include for Mac only
+ #include <CoreFoundation/CoreFoundation.h>
+ #include <mach/mach.h>
+
+ #ifndef _IPHONE
+ #include <IOKit/IOKitLib.h>
+ #endif
+
+ //For Zeroconf Lookup - use the internal version on Mac because otherwise SBC lookups are VERY slow!
+ #define C_IN 1
+ #ifndef ZEROCONF_LOOKUP
+ #define ZEROCONF_LOOKUP
+ #endif
+
+ #elif _LINUX
+ // Defines & Include for Linux Only
+
+ // No libusb on Android
+ #ifndef _ANDROID
+ #include <usb.h>
+ #endif
+ #include <assert.h>
+ #include <dlfcn.h>
+
+ //use runtime linking for zeroconf
+ #ifndef ZEROCONF_RUNTIME_LINKING
+ #define ZEROCONF_RUNTIME_LINKING
+ #endif
+ #endif
+#endif
+
+#ifndef round
+#define round(x) ((x)>=0?(int)((x)+0.5):(int)((x)-0.5))
+#endif
+
+#ifndef MSG_NOSIGNAL
+#define MSG_NOSIGNAL 0
+#endif
+
+//#define round_double(x, decimals) (double)((double)round(x * (double)(pow(10, decimals))) / (double)(pow(10, decimals)))
+double round_double(double x, int decimals);
+int hexval(unsigned char c);
+
+#include "clog.h"
+#include "pdictclient.h"
+#include "cphidget.h"
+
+#ifdef DMALLOC
+#include "dmalloc.h"
+#endif
+
+#endif
+
+
diff --git a/udev/99-phidgets.rules b/udev/99-phidgets.rules
new file mode 100644
index 0000000..52074cc
--- /dev/null
+++ b/udev/99-phidgets.rules
@@ -0,0 +1,7 @@
+# Very old Phidgets
+SUBSYSTEMS=="usb", ACTION=="add", ATTRS{idVendor}=="0925", ATTRS{idProduct}=="8101", MODE="666"
+SUBSYSTEMS=="usb", ACTION=="add", ATTRS{idVendor}=="0925", ATTRS{idProduct}=="8104", MODE="666"
+SUBSYSTEMS=="usb", ACTION=="add", ATTRS{idVendor}=="0925", ATTRS{idProduct}=="8201", MODE="666"
+
+# All current and future Phidgets - Vendor = 0x06c2, Product = 0x0030 - 0x00af
+SUBSYSTEMS=="usb", ACTION=="add", ATTRS{idVendor}=="06c2", ATTRS{idProduct}=="00[3-a][0-f]", MODE="666"
diff --git a/utils/cvtutf.c b/utils/cvtutf.c
new file mode 100644
index 0000000..8110c74
--- /dev/null
+++ b/utils/cvtutf.c
@@ -0,0 +1,339 @@
+/* ================================================================ */
+/*
+File: ConvertUTF.C
+Author: Mark E. Davis
+Copyright (C) 1994 Taligent, Inc. All rights reserved.
+
+This code is copyrighted. Under the copyright laws, this code may not
+be copied, in whole or part, without prior written consent of Taligent.
+
+Taligent grants the right to use or reprint this code as long as this
+ENTIRE copyright notice is reproduced in the code or reproduction.
+The code is provided AS-IS, AND TALIGENT DISCLAIMS ALL WARRANTIES,
+EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN
+NO EVENT WILL TALIGENT BE LIABLE FOR ANY DAMAGES WHATSOEVER (INCLUDING,
+WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS, BUSINESS
+INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR OTHER PECUNIARY
+LOSS) ARISING OUT OF THE USE OR INABILITY TO USE THIS CODE, EVEN
+IF TALIGENT HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+BECAUSE SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF
+LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES, THE ABOVE
+LIMITATION MAY NOT APPLY TO YOU.
+
+RESTRICTED RIGHTS LEGEND: Use, duplication, or disclosure by the
+government is subject to restrictions as set forth in subparagraph
+(c)(l)(ii) of the Rights in Technical Data and Computer Software
+clause at DFARS 252.227-7013 and FAR 52.227-19.
+
+This code may be protected by one or more U.S. and International
+Patents.
+
+TRADEMARKS: Taligent and the Taligent Design Mark are registered
+trademarks of Taligent, Inc.
+*/
+/* ================================================================ */
+
+#include "cvtutf.h"
+
+/* ================================================================ */
+
+static const int halfShift = 10;
+static const UCS4 halfBase = 0x0010000UL;
+static const UCS4 halfMask = 0x3FFUL;
+static const UCS4 kSurrogateHighStart = 0xD800UL;
+static const UCS4 kSurrogateHighEnd = 0xDBFFUL;
+static const UCS4 kSurrogateLowStart = 0xDC00UL;
+static const UCS4 kSurrogateLowEnd = 0xDFFFUL;
+
+/* ================================================================ */
+
+ConversionResult
+ConvertUCS4toUTF16(UCS4** sourceStart, const UCS4* sourceEnd,
+ UTF16** targetStart, const UTF16* targetEnd)
+{
+ ConversionResult result = ok;
+ register UCS4* source = *sourceStart;
+ register UTF16* target = *targetStart;
+ while (source < sourceEnd) {
+ register UCS4 ch;
+ if (target >= targetEnd) {
+ result = targetExhausted; break;
+ };
+ ch = *source++;
+ if (ch <= kMaximumUCS2) {
+ *target++ = ch;
+ } else if (ch > kMaximumUTF16) {
+ *target++ = kReplacementCharacter;
+ } else {
+ if (target + 1 >= targetEnd) {
+ result = targetExhausted; break;
+ };
+ ch -= halfBase;
+ *target++ = (ch >> halfShift) + kSurrogateHighStart;
+ *target++ = (ch & halfMask) + kSurrogateLowStart;
+ };
+ };
+ *sourceStart = source;
+ *targetStart = target;
+ return result;
+};
+
+/* ================================================================ */
+
+ConversionResult ConvertUTF16toUCS4(UTF16** sourceStart, UTF16* sourceEnd,
+ UCS4** targetStart, const UCS4* targetEnd)
+{
+ ConversionResult result = ok;
+ register UTF16* source = *sourceStart;
+ register UCS4* target = *targetStart;
+ while (source < sourceEnd) {
+ register UCS4 ch;
+ ch = *source++;
+ if (ch >= kSurrogateHighStart &&
+ ch <= kSurrogateHighEnd &&
+ source < sourceEnd) {
+ register UCS4 ch2 = *source;
+ if (ch2 >= kSurrogateLowStart && ch2 <= kSurrogateLowEnd) {
+ ch = ((ch - kSurrogateHighStart) << halfShift)
+ + (ch2 - kSurrogateLowStart) + halfBase;
+ ++source;
+ };
+ };
+ if (target >= targetEnd) {
+ result = targetExhausted; break;
+ };
+ *target++ = ch;
+ };
+ *sourceStart = source;
+ *targetStart = target;
+ return result;
+};
+
+/* ================================================================ */
+
+static UCS4 offsetsFromUTF8[6] = {
+ 0x00000000UL, 0x00003080UL, 0x000E2080UL,
+ 0x03C82080UL, 0xFA082080UL, 0x82082080UL
+};
+static char bytesFromUTF8[256] = {
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5
+};
+
+static UTF8 firstByteMark[7] = {0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC};
+
+/* ================================================================ */
+/* This code is similar in effect to making successive calls on the
+mbtowc and wctomb routines in FSS-UTF. However, it is considerably
+different in code:
+* it is adapted to be consistent with UTF16,
+* the interface converts a whole buffer to avoid function-call overhead
+* constants have been gathered.
+* loops & conditionals have been removed as much as possible for
+efficiency, in favor of drop-through switch statements.
+*/
+
+/* ================================================================ */
+int NSConvertUTF16toUTF8(unichar **sourceStart,
+ const unichar *sourceEnd,
+ unsigned char **targetStart,
+ const unsigned char *targetEnd)
+{
+ ConversionResult result = ok;
+ register UTF16* source = *sourceStart;
+ register UTF8* target = *targetStart;
+ while (source < sourceEnd) {
+ register UCS4 ch;
+ register unsigned short bytesToWrite = 0;
+ register const UCS4 byteMask = 0xBF;
+ register const UCS4 byteMark = 0x80;
+ ch = *source++;
+ if (ch >= kSurrogateHighStart && ch <= kSurrogateHighEnd
+ && source < sourceEnd) {
+ register UCS4 ch2 = *source;
+ if (ch2 >= kSurrogateLowStart && ch2 <= kSurrogateLowEnd) {
+ ch = ((ch - kSurrogateHighStart) << halfShift)
+ + (ch2 - kSurrogateLowStart) + halfBase;
+ ++source;
+ };
+ };
+ if (ch < 0x80) { bytesToWrite = 1;
+ } else if (ch < 0x800) { bytesToWrite = 2;
+ } else if (ch < 0x10000) { bytesToWrite = 3;
+ } else if (ch < 0x200000) { bytesToWrite = 4;
+ } else if (ch < 0x4000000) { bytesToWrite = 5;
+ } else if (ch <= kMaximumUCS4){ bytesToWrite = 6;
+ } else { bytesToWrite = 2;
+ ch = kReplacementCharacter;
+ }; /* I wish there were a smart way to avoid this conditional */
+
+ target += bytesToWrite;
+ if (target > targetEnd) {
+ target -= bytesToWrite; result = targetExhausted; break;
+ };
+ switch (bytesToWrite) { /* note: code falls through cases! */
+ case 6: *--target = (ch | byteMark) & byteMask; ch >>= 6;
+ case 5: *--target = (ch | byteMark) & byteMask; ch >>= 6;
+ case 4: *--target = (ch | byteMark) & byteMask; ch >>= 6;
+ case 3: *--target = (ch | byteMark) & byteMask; ch >>= 6;
+ case 2: *--target = (ch | byteMark) & byteMask; ch >>= 6;
+ case 1: *--target = ch | firstByteMark[bytesToWrite];
+ };
+ target += bytesToWrite;
+ };
+ *sourceStart = source;
+ *targetStart = target;
+
+ return result;
+};
+
+/* ================================================================ */
+
+int NSConvertUTF8toUTF16(unsigned char **sourceStart, unsigned char *sourceEnd,
+ unichar **targetStart, const unichar *targetEnd)
+{
+ ConversionResult result = ok;
+ register UTF8 *source = *sourceStart;
+ register UTF16 *target = *targetStart;
+
+ while (source < sourceEnd) {
+ register UCS4 ch = 0;
+ register unsigned short extraBytesToWrite = bytesFromUTF8[*source];
+
+ if (source + extraBytesToWrite > sourceEnd) {
+ result = sourceExhausted; break;
+ };
+ switch(extraBytesToWrite) { /* note: code falls through cases! */
+ case 5: ch += *source++; ch <<= 6;
+ case 4: ch += *source++; ch <<= 6;
+ case 3: ch += *source++; ch <<= 6;
+ case 2: ch += *source++; ch <<= 6;
+ case 1: ch += *source++; ch <<= 6;
+ case 0: ch += *source++;
+ };
+ ch -= offsetsFromUTF8[extraBytesToWrite];
+
+ if (target >= targetEnd) {
+ result = targetExhausted; break;
+ };
+ if (ch <= kMaximumUCS2) {
+ *target++ = ch;
+ } else if (ch > kMaximumUTF16) {
+ *target++ = kReplacementCharacter;
+ } else {
+ if (target + 1 >= targetEnd) {
+ result = targetExhausted; break;
+ };
+ ch -= halfBase;
+ *target++ = (ch >> halfShift) + kSurrogateHighStart;
+ *target++ = (ch & halfMask) + kSurrogateLowStart;
+ };
+ };
+ *sourceStart = source;
+ *targetStart = target;
+
+ return result;
+};
+
+/* ================================================================ */
+ConversionResult ConvertUCS4toUTF8 ( UCS4** sourceStart, const UCS4* sourceEnd,
+ UTF8** targetStart, const UTF8* targetEnd)
+{
+ ConversionResult result = ok;
+ register UCS4* source = *sourceStart;
+ register UTF8* target = *targetStart;
+ while (source < sourceEnd) {
+ register UCS4 ch;
+ register unsigned short bytesToWrite = 0;
+ register const UCS4 byteMask = 0xBF;
+ register const UCS4 byteMark = 0x80;
+ ch = *source++;
+ if (ch >= kSurrogateHighStart && ch <= kSurrogateHighEnd
+ && source < sourceEnd) {
+ register UCS4 ch2 = *source;
+ if (ch2 >= kSurrogateLowStart && ch2 <= kSurrogateLowEnd) {
+ ch = ((ch - kSurrogateHighStart) << halfShift)
+ + (ch2 - kSurrogateLowStart) + halfBase;
+ ++source;
+ };
+ };
+ if (ch < 0x80) { bytesToWrite = 1;
+ } else if (ch < 0x800) { bytesToWrite = 2;
+ } else if (ch < 0x10000) { bytesToWrite = 3;
+ } else if (ch < 0x200000) { bytesToWrite = 4;
+ } else if (ch < 0x4000000) { bytesToWrite = 5;
+ } else if (ch <= kMaximumUCS4){ bytesToWrite = 6;
+ } else { bytesToWrite = 2;
+ ch = kReplacementCharacter;
+ }; /* I wish there were a smart way to avoid this conditional */
+
+ target += bytesToWrite;
+ if (target > targetEnd) {
+ target -= bytesToWrite; result = targetExhausted; break;
+ };
+ switch (bytesToWrite) { /* note: code falls through cases! */
+ case 6: *--target = (ch | byteMark) & byteMask; ch >>= 6;
+ case 5: *--target = (ch | byteMark) & byteMask; ch >>= 6;
+ case 4: *--target = (ch | byteMark) & byteMask; ch >>= 6;
+ case 3: *--target = (ch | byteMark) & byteMask; ch >>= 6;
+ case 2: *--target = (ch | byteMark) & byteMask; ch >>= 6;
+ case 1: *--target = ch | firstByteMark[bytesToWrite];
+ };
+ target += bytesToWrite;
+ };
+ *sourceStart = source;
+ *targetStart = target;
+ return result;
+};
+
+/* ================================================================ */
+
+ConversionResult ConvertUTF8toUCS4 (UTF8** sourceStart, UTF8* sourceEnd,
+ UCS4** targetStart, const UCS4* targetEnd)
+{
+ ConversionResult result = ok;
+ register UTF8* source = *sourceStart;
+ register UCS4* target = *targetStart;
+ while (source < sourceEnd) {
+ register UCS4 ch = 0;
+ register unsigned short extraBytesToWrite = bytesFromUTF8[*source];
+ if (source + extraBytesToWrite > sourceEnd) {
+ result = sourceExhausted; break;
+ };
+ switch(extraBytesToWrite) { /* note: code falls through cases! */
+ case 5: ch += *source++; ch <<= 6;
+ case 4: ch += *source++; ch <<= 6;
+ case 3: ch += *source++; ch <<= 6;
+ case 2: ch += *source++; ch <<= 6;
+ case 1: ch += *source++; ch <<= 6;
+ case 0: ch += *source++;
+ };
+ ch -= offsetsFromUTF8[extraBytesToWrite];
+
+ if (target >= targetEnd) {
+ result = targetExhausted; break;
+ };
+ if (ch <= kMaximumUCS2) {
+ *target++ = ch;
+ } else if (ch > kMaximumUCS4) {
+ *target++ = kReplacementCharacter;
+ } else {
+ if (target + 1 >= targetEnd) {
+ result = targetExhausted; break;
+ };
+ ch -= halfBase;
+ *target++ = (ch >> halfShift) + kSurrogateHighStart;
+ *target++ = (ch & halfMask) + kSurrogateLowStart;
+ };
+ };
+ *sourceStart = source;
+ *targetStart = target;
+ return result;
+};
diff --git a/utils/cvtutf.h b/utils/cvtutf.h
new file mode 100644
index 0000000..1d9f8ec
--- /dev/null
+++ b/utils/cvtutf.h
@@ -0,0 +1,110 @@
+/* ================================================================ */
+/*
+File: ConvertUTF.h
+Author: Mark E. Davis
+Copyright (C) 1994 Taligent, Inc. All rights reserved.
+
+This code is copyrighted. Under the copyright laws, this code may not
+be copied, in whole or part, without prior written consent of Taligent.
+
+Taligent grants the right to use or reprint this code as long as this
+ENTIRE copyright notice is reproduced in the code or reproduction.
+The code is provided AS-IS, AND TALIGENT DISCLAIMS ALL WARRANTIES,
+EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN
+NO EVENT WILL TALIGENT BE LIABLE FOR ANY DAMAGES WHATSOEVER (INCLUDING,
+WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS, BUSINESS
+INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR OTHER PECUNIARY
+LOSS) ARISING OUT OF THE USE OR INABILITY TO USE THIS CODE, EVEN
+IF TALIGENT HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+BECAUSE SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF
+LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES, THE ABOVE
+LIMITATION MAY NOT APPLY TO YOU.
+
+RESTRICTED RIGHTS LEGEND: Use, duplication, or disclosure by the
+government is subject to restrictions as set forth in subparagraph
+(c)(l)(ii) of the Rights in Technical Data and Computer Software
+clause at DFARS 252.227-7013 and FAR 52.227-19.
+
+This code may be protected by one or more U.S. and International
+Patents.
+
+TRADEMARKS: Taligent and the Taligent Design Mark are registered
+trademarks of Taligent, Inc.
+*/
+/* ================================================================ */
+
+#ifndef __cvtutf_H__
+#define __cvtutf_H__
+
+#include <stdio.h>
+#include <stdlib.h>
+// #include <types.h>
+#include <string.h>
+
+/* ================================================================ */
+/* The following 4 definitions are compiler-specific.
+ I would use wchar_t for UCS2/UTF16, except that the C standard
+ does not guarantee that it has at least 16 bits, so wchar_t is
+ no less portable than unsigned short!
+*/
+
+typedef unsigned long UCS4;
+typedef unsigned short UCS2;
+typedef unsigned short UTF16;
+typedef unsigned char UTF8;
+#define unichar UTF16
+
+//typedef enum {false, true} Boolean;
+
+static const UCS4 kReplacementCharacter = 0x0000FFFDUL;
+static const UCS4 kMaximumUCS2 = 0x0000FFFFUL;
+static const UCS4 kMaximumUTF16 = 0x0010FFFFUL;
+static const UCS4 kMaximumUCS4 = 0x7FFFFFFFUL;
+
+/* ================================================================ */
+/* Each of these routines converts the text between *sourceStart and
+sourceEnd, putting the result into the buffer between *targetStart and
+targetEnd. Note: the end pointers are *after* the last item: e.g.
+*(sourceEnd - 1) is the last item.
+
+ The return result indicates whether the conversion was successful,
+and if not, whether the problem was in the source or target buffers.
+
+ After the conversion, *sourceStart and *targetStart are both
+updated to point to the end of last text successfully converted in
+the respective buffers.
+*/
+
+typedef enum {
+ ok, /* conversion successful */
+ sourceExhausted, /* partial character in source, but hit end */
+ targetExhausted /* insuff. room in target for conversion */
+} ConversionResult;
+
+ConversionResult ConvertUCS4toUTF16 (
+ UCS4** sourceStart, const UCS4* sourceEnd,
+ UTF16** targetStart, const UTF16* targetEnd);
+
+ConversionResult ConvertUTF16toUCS4 (
+ UTF16** sourceStart, UTF16* sourceEnd,
+ UCS4** targetStart, const UCS4* targetEnd);
+
+int NSConvertUTF16toUTF8(unichar **sourceStart,
+ const unichar *sourceEnd,
+ unsigned char **targetStart,
+ const unsigned char *targetEnd);
+int NSConvertUTF8toUTF16(unsigned char **sourceStart, unsigned char *sourceEnd,
+ unichar **targetStart, const unichar *targetEnd);
+
+ConversionResult ConvertUCS4toUTF8 (
+ UCS4** sourceStart, const UCS4* sourceEnd,
+ UTF8** targetStart, const UTF8* targetEnd);
+
+ConversionResult ConvertUTF8toUCS4 (
+ UTF8** sourceStart, UTF8* sourceEnd,
+ UCS4** targetStart, const UCS4* targetEnd);
+
+/* ================================================================ */
+
+#endif /* __cvtutf_H__ */
diff --git a/utils/md5.c b/utils/md5.c
new file mode 100644
index 0000000..b0f715e
--- /dev/null
+++ b/utils/md5.c
@@ -0,0 +1,382 @@
+/*
+ Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved.
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ L. Peter Deutsch
+ ghost@aladdin.com
+
+ */
+/* $Id: md5.c 15582 2010-06-15 17:50:08Z patrick $ */
+/*
+ Independent implementation of MD5 (RFC 1321).
+
+ This code implements the MD5 Algorithm defined in RFC 1321, whose
+ text is available at
+ http://www.ietf.org/rfc/rfc1321.txt
+ The code is derived from the text of the RFC, including the test suite
+ (section A.5) but excluding the rest of Appendix A. It does not include
+ any code or documentation that is identified in the RFC as being
+ copyrighted.
+
+ The original and principal author of md5.c is L. Peter Deutsch
+ <ghost@aladdin.com>. Other authors are noted in the change history
+ that follows (in reverse chronological order):
+
+ 2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order
+ either statically or dynamically; added missing #include <string.h>
+ in library.
+ 2002-03-11 lpd Corrected argument list for main(), and added int return
+ type, in test program and T value program.
+ 2002-02-21 lpd Added missing #include <stdio.h> in test program.
+ 2000-07-03 lpd Patched to eliminate warnings about "constant is
+ unsigned in ANSI C, signed in traditional"; made test program
+ self-checking.
+ 1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
+ 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5).
+ 1999-05-03 lpd Original version.
+ */
+
+#include "../stdafx.h"
+#include "md5.h"
+#include <string.h>
+
+#undef BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */
+#ifdef ARCH_IS_BIG_ENDIAN
+# define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1)
+#else
+# define BYTE_ORDER 0
+#endif
+
+#define T_MASK ((md5_word_t)~0)
+#define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87)
+#define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9)
+#define T3 0x242070db
+#define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111)
+#define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050)
+#define T6 0x4787c62a
+#define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec)
+#define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe)
+#define T9 0x698098d8
+#define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850)
+#define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e)
+#define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841)
+#define T13 0x6b901122
+#define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c)
+#define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71)
+#define T16 0x49b40821
+#define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d)
+#define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf)
+#define T19 0x265e5a51
+#define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855)
+#define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2)
+#define T22 0x02441453
+#define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e)
+#define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437)
+#define T25 0x21e1cde6
+#define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829)
+#define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278)
+#define T28 0x455a14ed
+#define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa)
+#define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07)
+#define T31 0x676f02d9
+#define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375)
+#define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd)
+#define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e)
+#define T35 0x6d9d6122
+#define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3)
+#define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb)
+#define T38 0x4bdecfa9
+#define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f)
+#define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f)
+#define T41 0x289b7ec6
+#define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805)
+#define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a)
+#define T44 0x04881d05
+#define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6)
+#define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a)
+#define T47 0x1fa27cf8
+#define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a)
+#define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb)
+#define T50 0x432aff97
+#define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58)
+#define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6)
+#define T53 0x655b59c3
+#define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d)
+#define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82)
+#define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e)
+#define T57 0x6fa87e4f
+#define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f)
+#define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb)
+#define T60 0x4e0811a1
+#define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d)
+#define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca)
+#define T63 0x2ad7d2bb
+#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e)
+
+
+static void
+md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/)
+{
+ md5_word_t
+ a = pms->abcd[0], b = pms->abcd[1],
+ c = pms->abcd[2], d = pms->abcd[3];
+ md5_word_t t;
+#if BYTE_ORDER > 0
+ /* Define storage only for big-endian CPUs. */
+ md5_word_t X[16];
+#else
+ /* Define storage for little-endian or both types of CPUs. */
+ md5_word_t xbuf[16];
+ const md5_word_t *X;
+#endif
+
+ {
+#if BYTE_ORDER == 0
+ /*
+ * Determine dynamically whether this is a big-endian or
+ * little-endian machine, since we can use a more efficient
+ * algorithm on the latter.
+ */
+ static const int w = 1;
+
+ if (*((const md5_byte_t *)&w)) /* dynamic little-endian */
+#endif
+#if BYTE_ORDER <= 0 /* little-endian */
+ {
+ /*
+ * On little-endian machines, we can process properly aligned
+ * data without copying it.
+ */
+ if (!((data - (const md5_byte_t *)0) & 3)) {
+ /* data are properly aligned */
+ X = (const md5_word_t *)data;
+ } else {
+ /* not aligned */
+ memcpy(xbuf, data, 64);
+ X = xbuf;
+ }
+ }
+#endif
+#if BYTE_ORDER == 0
+ else /* dynamic big-endian */
+#endif
+#if BYTE_ORDER >= 0 /* big-endian */
+ {
+ /*
+ * On big-endian machines, we must arrange the bytes in the
+ * right order.
+ */
+ const md5_byte_t *xp = data;
+ int i;
+
+# if BYTE_ORDER == 0
+ X = xbuf; /* (dynamic only) */
+# else
+# define xbuf X /* (static only) */
+# endif
+ for (i = 0; i < 16; ++i, xp += 4)
+ xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
+ }
+#endif
+ }
+
+#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
+
+ /* Round 1. */
+ /* Let [abcd k s i] denote the operation
+ a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
+#define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
+#define SET(a, b, c, d, k, s, Ti)\
+ t = a + F(b,c,d) + X[k] + Ti;\
+ a = ROTATE_LEFT(t, s) + b
+ /* Do the following 16 operations. */
+ SET(a, b, c, d, 0, 7, T1);
+ SET(d, a, b, c, 1, 12, T2);
+ SET(c, d, a, b, 2, 17, T3);
+ SET(b, c, d, a, 3, 22, T4);
+ SET(a, b, c, d, 4, 7, T5);
+ SET(d, a, b, c, 5, 12, T6);
+ SET(c, d, a, b, 6, 17, T7);
+ SET(b, c, d, a, 7, 22, T8);
+ SET(a, b, c, d, 8, 7, T9);
+ SET(d, a, b, c, 9, 12, T10);
+ SET(c, d, a, b, 10, 17, T11);
+ SET(b, c, d, a, 11, 22, T12);
+ SET(a, b, c, d, 12, 7, T13);
+ SET(d, a, b, c, 13, 12, T14);
+ SET(c, d, a, b, 14, 17, T15);
+ SET(b, c, d, a, 15, 22, T16);
+#undef SET
+
+ /* Round 2. */
+ /* Let [abcd k s i] denote the operation
+ a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
+#define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
+#define SET(a, b, c, d, k, s, Ti)\
+ t = a + G(b,c,d) + X[k] + Ti;\
+ a = ROTATE_LEFT(t, s) + b
+ /* Do the following 16 operations. */
+ SET(a, b, c, d, 1, 5, T17);
+ SET(d, a, b, c, 6, 9, T18);
+ SET(c, d, a, b, 11, 14, T19);
+ SET(b, c, d, a, 0, 20, T20);
+ SET(a, b, c, d, 5, 5, T21);
+ SET(d, a, b, c, 10, 9, T22);
+ SET(c, d, a, b, 15, 14, T23);
+ SET(b, c, d, a, 4, 20, T24);
+ SET(a, b, c, d, 9, 5, T25);
+ SET(d, a, b, c, 14, 9, T26);
+ SET(c, d, a, b, 3, 14, T27);
+ SET(b, c, d, a, 8, 20, T28);
+ SET(a, b, c, d, 13, 5, T29);
+ SET(d, a, b, c, 2, 9, T30);
+ SET(c, d, a, b, 7, 14, T31);
+ SET(b, c, d, a, 12, 20, T32);
+#undef SET
+
+ /* Round 3. */
+ /* Let [abcd k s t] denote the operation
+ a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+#define SET(a, b, c, d, k, s, Ti)\
+ t = a + H(b,c,d) + X[k] + Ti;\
+ a = ROTATE_LEFT(t, s) + b
+ /* Do the following 16 operations. */
+ SET(a, b, c, d, 5, 4, T33);
+ SET(d, a, b, c, 8, 11, T34);
+ SET(c, d, a, b, 11, 16, T35);
+ SET(b, c, d, a, 14, 23, T36);
+ SET(a, b, c, d, 1, 4, T37);
+ SET(d, a, b, c, 4, 11, T38);
+ SET(c, d, a, b, 7, 16, T39);
+ SET(b, c, d, a, 10, 23, T40);
+ SET(a, b, c, d, 13, 4, T41);
+ SET(d, a, b, c, 0, 11, T42);
+ SET(c, d, a, b, 3, 16, T43);
+ SET(b, c, d, a, 6, 23, T44);
+ SET(a, b, c, d, 9, 4, T45);
+ SET(d, a, b, c, 12, 11, T46);
+ SET(c, d, a, b, 15, 16, T47);
+ SET(b, c, d, a, 2, 23, T48);
+#undef SET
+
+ /* Round 4. */
+ /* Let [abcd k s t] denote the operation
+ a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
+#define I(x, y, z) ((y) ^ ((x) | ~(z)))
+#define SET(a, b, c, d, k, s, Ti)\
+ t = a + I(b,c,d) + X[k] + Ti;\
+ a = ROTATE_LEFT(t, s) + b
+ /* Do the following 16 operations. */
+ SET(a, b, c, d, 0, 6, T49);
+ SET(d, a, b, c, 7, 10, T50);
+ SET(c, d, a, b, 14, 15, T51);
+ SET(b, c, d, a, 5, 21, T52);
+ SET(a, b, c, d, 12, 6, T53);
+ SET(d, a, b, c, 3, 10, T54);
+ SET(c, d, a, b, 10, 15, T55);
+ SET(b, c, d, a, 1, 21, T56);
+ SET(a, b, c, d, 8, 6, T57);
+ SET(d, a, b, c, 15, 10, T58);
+ SET(c, d, a, b, 6, 15, T59);
+ SET(b, c, d, a, 13, 21, T60);
+ SET(a, b, c, d, 4, 6, T61);
+ SET(d, a, b, c, 11, 10, T62);
+ SET(c, d, a, b, 2, 15, T63);
+ SET(b, c, d, a, 9, 21, T64);
+#undef SET
+
+ /* Then perform the following additions. (That is increment each
+ of the four registers by the value it had before this block
+ was started.) */
+ pms->abcd[0] += a;
+ pms->abcd[1] += b;
+ pms->abcd[2] += c;
+ pms->abcd[3] += d;
+}
+
+void
+md5_init(md5_state_t *pms)
+{
+ pms->count[0] = pms->count[1] = 0;
+ pms->abcd[0] = 0x67452301;
+ pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476;
+ pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301;
+ pms->abcd[3] = 0x10325476;
+}
+
+void
+md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes)
+{
+ const md5_byte_t *p = data;
+ int left = nbytes;
+ int offset = (pms->count[0] >> 3) & 63;
+ md5_word_t nbits = (md5_word_t)(nbytes << 3);
+
+ if (nbytes <= 0)
+ return;
+
+ /* Update the message length. */
+ pms->count[1] += nbytes >> 29;
+ pms->count[0] += nbits;
+ if (pms->count[0] < nbits)
+ pms->count[1]++;
+
+ /* Process an initial partial block. */
+ if (offset) {
+ int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
+
+ memcpy(pms->buf + offset, p, copy);
+ if (offset + copy < 64)
+ return;
+ p += copy;
+ left -= copy;
+ md5_process(pms, pms->buf);
+ }
+
+ /* Process full blocks. */
+ for (; left >= 64; p += 64, left -= 64)
+ md5_process(pms, p);
+
+ /* Process a final partial block. */
+ if (left)
+ memcpy(pms->buf, p, left);
+}
+
+void
+md5_finish(md5_state_t *pms, md5_byte_t digest[16])
+{
+ static const md5_byte_t pad[64] = {
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ };
+ md5_byte_t data[8];
+ int i;
+
+ /* Save the length before padding. */
+ for (i = 0; i < 8; ++i)
+ data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3));
+ /* Pad to 56 bytes mod 64. */
+ md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1);
+ /* Append the length. */
+ md5_append(pms, data, 8);
+ for (i = 0; i < 16; ++i)
+ digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3));
+}
diff --git a/utils/md5.h b/utils/md5.h
new file mode 100644
index 0000000..f944245
--- /dev/null
+++ b/utils/md5.h
@@ -0,0 +1,91 @@
+/*
+ Copyright (C) 1999, 2002 Aladdin Enterprises. All rights reserved.
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ L. Peter Deutsch
+ ghost@aladdin.com
+
+ */
+/* $Id: md5.h 15572 2010-06-15 17:23:44Z patrick $ */
+/*
+ Independent implementation of MD5 (RFC 1321).
+
+ This code implements the MD5 Algorithm defined in RFC 1321, whose
+ text is available at
+ http://www.ietf.org/rfc/rfc1321.txt
+ The code is derived from the text of the RFC, including the test suite
+ (section A.5) but excluding the rest of Appendix A. It does not include
+ any code or documentation that is identified in the RFC as being
+ copyrighted.
+
+ The original and principal author of md5.h is L. Peter Deutsch
+ <ghost@aladdin.com>. Other authors are noted in the change history
+ that follows (in reverse chronological order):
+
+ 2002-04-13 lpd Removed support for non-ANSI compilers; removed
+ references to Ghostscript; clarified derivation from RFC 1321;
+ now handles byte order either statically or dynamically.
+ 1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
+ 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5);
+ added conditionalization for C++ compilation from Martin
+ Purschke <purschke@bnl.gov>.
+ 1999-05-03 lpd Original version.
+ */
+
+#ifndef md5_INCLUDED
+# define md5_INCLUDED
+
+/*
+ * This package supports both compile-time and run-time determination of CPU
+ * byte order. If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be
+ * compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is
+ * defined as non-zero, the code will be compiled to run only on big-endian
+ * CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to
+ * run on either big- or little-endian CPUs, but will run slightly less
+ * efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined.
+ */
+
+typedef unsigned char md5_byte_t; /* 8-bit byte */
+typedef unsigned int md5_word_t; /* 32-bit word */
+
+/* Define the state of the MD5 Algorithm. */
+typedef struct md5_state_s {
+ md5_word_t count[2]; /* message length in bits, lsw first */
+ md5_word_t abcd[4]; /* digest buffer */
+ md5_byte_t buf[64]; /* accumulate block */
+} md5_state_t;
+
+//#ifdef __cplusplus
+//extern "C"
+//{
+//#endif
+
+/* Initialize the algorithm. */
+void md5_init(md5_state_t *pms);
+
+/* Append a string to the message. */
+void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes);
+
+/* Finish the message and return the digest. */
+void md5_finish(md5_state_t *pms, md5_byte_t digest[16]);
+
+//#ifdef __cplusplus
+//} /* end extern "C" */
+//#endif
+
+#endif /* md5_INCLUDED */
diff --git a/utils/plist.c b/utils/plist.c
new file mode 100644
index 0000000..daca93c
--- /dev/null
+++ b/utils/plist.c
@@ -0,0 +1,151 @@
+#include "../stdafx.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include "plist.h"
+
+/*
+ * A plist is a double-linked list of key-value pairs
+ * It can be circular or not.
+ */
+
+/*
+ * This is a node in a plist
+ */
+struct plist_node {
+ void *pn_key;
+ void *pn_value;
+ struct plist_node *pn_next;
+ struct plist_node *pn_prev;
+};
+
+/*
+ * Adds a new entry into a plist.
+ * if !*root it creates a node where prev and next point to itself
+ * else, inserts itself in the list before *root
+ * returns 1 on success, 0 on NOMEM failure.
+ */
+int
+plist_add(void *k, void *v, plist_node_t **root)
+{
+ plist_node_t *n;
+
+ if (!(n = malloc(sizeof (*n))))
+ return 0;
+ n->pn_key = k;
+ n->pn_value = v;
+ if (!*root) {
+ n->pn_next = n;
+ n->pn_prev = n;
+ *root = n;
+ } else {
+ n->pn_prev = (*root)->pn_prev;
+ n->pn_next = (*root);
+ (*root)->pn_prev->pn_next = n;
+ (*root)->pn_prev = n;
+ }
+ return 1;
+}
+
+/*
+ * traverse list until cur == *root or cur == 0, freeing each node
+ * (list could be either circular or not)
+ * note that the key and value pointers are still valid.
+ */
+void
+plist_clear(plist_node_t **root)
+{
+ plist_node_t *cur;
+ plist_node_t *fr;
+
+ cur = *root;
+ while (cur) {
+ fr = cur;
+ cur = cur->pn_next;
+ free(fr); fr = NULL;
+ if (cur == *root) {
+ *root = NULL;
+ return;
+ }
+ }
+}
+
+/*
+ * removes a node from a plist where the key pointer == k
+ * if ov is not null, it will point to the old value from the removed node
+ * This only removes the 1st occurance of k.
+ * returns 1 on success, 0 if k was not in the list
+ */
+int
+plist_remove(void *k, plist_node_t **rootp, void **ov)
+{
+ plist_node_t *cur;
+
+ cur = *rootp;
+ while (cur) {
+ if (cur->pn_key == k) {
+ if (ov)
+ *ov = cur->pn_value;
+ cur->pn_prev->pn_next = cur->pn_next;
+ cur->pn_next->pn_prev = cur->pn_prev;
+ if (cur->pn_next == cur)
+ *rootp = NULL;
+ else if (*rootp == cur)
+ *rootp = cur->pn_next;
+ free(cur); cur = NULL;
+ return 1;
+ }
+ cur = cur->pn_next;
+ if (cur == *rootp)
+ return 0;
+ }
+ return 0;
+}
+
+/*
+ * finds k in plist.
+ * if ov != 0, it will be set to the value pointer
+ * returns 1 when the key is found, 0 if not found.
+ */
+int
+plist_contains(void *k, plist_node_t *root, void **ov)
+{
+ plist_node_t *cur;
+
+ cur = root;
+ while (cur) {
+ if (cur->pn_key == k) {
+ if (ov)
+ *ov = cur->pn_value;
+ return 1;
+ }
+ cur = cur->pn_next;
+ if (cur == root)
+ return 0;
+ }
+ return 0;
+}
+
+/*
+ * traverses the plist from start, until we get back to start or next==0
+ * runs func with key, val, arg.
+ * if func returns 0, stops traversing and returns 0
+ * else returns 1 for success
+ */
+int
+plist_walk(plist_node_t *start, int (*func)(const void *k, const void *v,
+ void *arg), void *arg)
+{
+ plist_node_t *cur;
+ int res;
+
+ cur = start;
+ while (cur) {
+ if (!(res = func(cur->pn_key, cur->pn_value, arg)))
+ return res;
+ cur = cur->pn_next;
+ if (cur == start)
+ return 1;
+ }
+ return 1;
+}
diff --git a/utils/plist.h b/utils/plist.h
new file mode 100644
index 0000000..52207a7
--- /dev/null
+++ b/utils/plist.h
@@ -0,0 +1,13 @@
+#ifndef _PLIST_H_
+#define _PLIST_H_
+
+typedef struct plist_node plist_node_t;
+
+int plist_contains(void *k, plist_node_t *root, void **nodeval);
+int plist_remove(void *k, plist_node_t **root, void **ov);
+int plist_add(void *k, void *v, plist_node_t **root);
+void plist_clear(plist_node_t **root);
+int plist_walk(plist_node_t *start, int(*func)(const void *k, const void *v,
+ void *arg), void *arg);
+
+#endif
diff --git a/utils/ptree.c b/utils/ptree.c
new file mode 100644
index 0000000..f632e78
--- /dev/null
+++ b/utils/ptree.c
@@ -0,0 +1,460 @@
+#include "../stdafx.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include "ptree.h"
+
+//#define VERIFY_TREE
+
+struct ptree_node {
+ void *pn_value;
+ struct ptree_node *pn_parent;
+ struct ptree_node *pn_left;
+ struct ptree_node *pn_right;
+};
+
+static int
+_walk_to(void *v,
+ struct ptree_node **startp,
+ struct ptree_node ***pp,
+ int (*cmp)(const void *v1, const void *v2))
+{
+ struct ptree_node **nextp;
+ int c = -1;
+
+ nextp = startp;
+ while (*nextp)
+ {
+ c = cmp(v, (*nextp)->pn_value);
+ *startp = *nextp;
+ if (c == 0)
+ break;
+ if (c < 0)
+ nextp = &(*nextp)->pn_left;
+ else
+ nextp = &(*nextp)->pn_right;
+ if (pp)
+ *pp = nextp;
+ }
+
+ return c;
+}
+
+
+static ptree_walk_res_t
+_visit(struct ptree_node *pn,
+ int level,
+ void *arg1,
+ void *arg2)
+{
+ ptree_walk_res_t (*func)(const void *, int, void *, void *) = arg1;
+
+ return func(pn->pn_value, level, arg2, pn);
+}
+
+static ptree_node_t *
+_find_min(ptree_node_t *pn,
+ int *levelp)
+{
+ while (pn->pn_left)
+ {
+ pn = pn->pn_left;
+ if (levelp)
+ (*levelp)++;
+ }
+ return pn;
+}
+
+static ptree_node_t *
+_find_succ(ptree_node_t *pn,
+ int *levelp)
+{
+ if (pn->pn_right)
+ {
+ pn = pn->pn_right;
+ if (levelp)
+ (*levelp)++;
+ while (pn->pn_left)
+ {
+ pn = pn->pn_left;
+ if (levelp)
+ (*levelp)++;
+ }
+ }
+ else
+ {
+ while (pn->pn_parent && pn->pn_parent->pn_right == pn)
+ {
+ pn = pn->pn_parent;
+ if (levelp)
+ (*levelp)--;
+ }
+ pn = pn->pn_parent;
+ if (levelp)
+ (*levelp)--;
+ }
+
+ return pn;
+}
+
+static int
+_walk_int(struct ptree_node *pn,
+ ptree_order_t order,
+ int level,
+ ptree_walk_res_t (*func)(struct ptree_node *, int level, void *, void *),
+ void *arg1,
+ void *arg2)
+{
+ ptree_walk_res_t res;
+ ptree_node_t *next;
+
+ if (!pn)
+ return PTREE_WALK_CONTINUE;
+
+ if (order == PTREE_INORDER)
+ {
+ int nlevel;
+
+ pn = _find_min(pn, &level);
+ while (pn)
+ {
+ nlevel = level;
+ next = _find_succ(pn, &nlevel);
+ if ((res = func(pn, level, arg1, arg2)) != PTREE_WALK_CONTINUE)
+ return res;
+ level = nlevel;
+ if (level < 0)
+ level = 0;
+ pn = next;
+ }
+ return PTREE_WALK_CONTINUE;
+ }
+ if (order == PTREE_PREORDER && (res = func(pn, level, arg1, arg2)) != PTREE_WALK_CONTINUE)
+ return res;
+ if ((res = _walk_int(pn->pn_left, order, level + 1, func, arg1, arg2)) != PTREE_WALK_CONTINUE)
+ return res;
+ if ((res = _walk_int(pn->pn_right, order, level + 1, func, arg1, arg2)) != PTREE_WALK_CONTINUE)
+ return res;
+ if (order == PTREE_POSTORDER && (res = func(pn, level, arg1, arg2)) != PTREE_WALK_CONTINUE)
+ return res;
+ return PTREE_WALK_CONTINUE;
+}
+
+#ifdef VERIFY_TREE
+static ptree_walk_res_t
+_count(struct ptree_node *pn,
+ int level,
+ void *arg1,
+ void *arg2)
+{
+ int *counter = arg1;
+ (*counter)++;
+ return PTREE_WALK_CONTINUE;
+}
+
+//counts the number of nodes
+static int
+_count_nodes(ptree_node_t **rootp)
+{
+ int counter = 0;
+ _walk_int(*rootp, PTREE_INORDER, 0, _count, &counter, 0);
+ return counter;
+}
+
+static ptree_walk_res_t
+_verify_node(struct ptree_node *pn,
+ int level,
+ void *arg1,
+ void *arg2)
+{
+ int (*cmp)(const void *v1, const void *v2) = arg1;
+ struct ptree_node **prev_pn_p = (struct ptree_node **)arg2;
+ struct ptree_node *prev_pn = *prev_pn_p;
+
+ if(pn->pn_left != NULL && pn->pn_left->pn_parent != pn)
+ return PTREE_WALK_STOP;
+ if(pn->pn_right != NULL && pn->pn_right->pn_parent != pn)
+ return PTREE_WALK_STOP;
+
+ if(prev_pn != NULL)
+ {
+ //this value should always be greater then the last value
+ if(cmp(pn->pn_value, prev_pn->pn_value) <= 0)
+ return PTREE_WALK_STOP;
+ }
+ *prev_pn_p = pn;
+
+ return PTREE_WALK_CONTINUE;
+}
+
+//static int
+//pdecmp(const void *sv, const void *dv)
+//{
+// int res;
+//
+// char *str1 = *(char **)sv;
+// char *str2 = *(char **)dv;
+//
+// res = strcmp(str1, str2);
+//
+// if(res <= 0)
+// return res;
+//
+// return res;
+//}
+
+//Verifies that the tree is a valid Binary search tree
+static int
+_verify_tree(ptree_node_t **rootp, int (*cmp)(const void *v1, const void *v2))
+{
+ struct ptree_node *prev_pn = NULL;
+ if(_walk_int(*rootp, PTREE_INORDER, 0, _verify_node, cmp, &prev_pn) == PTREE_WALK_STOP)
+ return 0;
+ return 1;
+}
+#endif
+
+static void
+_remove_node(ptree_node_t **rootp,
+ ptree_node_t *pn,
+ void **oldval)
+{
+ ptree_node_t **pp;
+ ptree_node_t **predp;
+ ptree_node_t *pred;
+
+#ifdef VERIFY_TREE
+ int countStart = _count_nodes(rootp), countEnd=0;
+#endif
+
+ //Find pn in the tree
+ if (!pn->pn_parent)
+ {
+ assert(rootp && pn == *rootp);
+ pp = rootp;
+ }
+ else
+ {
+ if (pn->pn_parent->pn_left == pn)
+ pp = &pn->pn_parent->pn_left;
+ else
+ pp = &pn->pn_parent->pn_right;
+ }
+
+ //pp should now point at the location where pn is stored in the tree
+ assert(pp);
+
+ //Best case - only one child, on no children, just remove as in a list
+ if (!pn->pn_left)
+ {
+ *pp = pn->pn_right;
+ if (pn->pn_right)
+ pn->pn_right->pn_parent = pn->pn_parent;
+ }
+ else if (!pn->pn_right)
+ {
+ *pp = pn->pn_left;
+ if (pn->pn_left)
+ pn->pn_left->pn_parent = pn->pn_parent;
+ }
+
+ //Worst case: pn contains both left and right children
+ else
+ {
+ for (predp = &pn->pn_left; (*predp)->pn_right; )
+ predp = &(*predp)->pn_right;
+ pred = *predp;
+
+ //pred either has a left child or no child
+ if (pred->pn_parent->pn_left == pred)
+ pred->pn_parent->pn_left = pred->pn_left;
+ else
+ pred->pn_parent->pn_right = pred->pn_left;
+ if(pred->pn_left)
+ pred->pn_left->pn_parent = pred->pn_parent;
+
+ *pp = pred;
+
+ pred->pn_parent = pn->pn_parent;
+ pred->pn_left = pn->pn_left;
+ pred->pn_right = pn->pn_right;
+
+ if (pn->pn_left)
+ pn->pn_left->pn_parent = pred;
+ pn->pn_right->pn_parent = pred;
+ }
+
+ //Return the value of the removed node
+ if (oldval)
+ *oldval = pn->pn_value;
+
+ free(pn);
+
+#ifdef VERIFY_TREE
+ countEnd = _count_nodes(rootp);
+ countStart--;
+ assert(countEnd == countStart);
+#endif
+}
+
+int
+ptree_inorder_walk_remove(ptree_node_t **rootp,
+ void **oldval,
+ void *pn,
+ int (*cmp)(const void *v1, const void *v2))
+{
+ assert(pn);
+ if (!pn)
+ return 0;
+#ifdef VERIFY_TREE
+ assert(_verify_tree(rootp, cmp));
+#endif
+ _remove_node(rootp, pn, oldval);
+#ifdef VERIFY_TREE
+ assert(_verify_tree(rootp, cmp));
+#endif
+ return 1;
+}
+
+ptree_walk_res_t
+ptree_walk(ptree_node_t *start,
+ ptree_order_t order,
+ ptree_walk_res_t (*func)(const void *v1, int level, void *arg, void *ptree_inorder_walking_remove_arg),
+ int (*cmp)(const void *v1, const void *v2),
+ void *arg)
+{
+#ifdef VERIFY_TREE
+ ptree_node_t *start_p = start;
+ if(cmp != NULL)
+ assert(_verify_tree(&start_p, cmp));
+#endif
+
+ return _walk_int((struct ptree_node *)start, order, 0, _visit, (void *)func, arg);
+}
+
+ptree_walk_res_t
+ptree_clear_func(struct ptree_node *pn,
+ int level,
+ void *arg1,
+ void *arg2)
+{
+ free(pn); pn = NULL;
+
+ return PTREE_WALK_CONTINUE;
+}
+
+void
+ptree_clear(ptree_node_t **rootp)
+{
+ _walk_int(*rootp, PTREE_POSTORDER, 0, ptree_clear_func, 0, 0);
+ *rootp = 0;
+}
+
+int
+ptree_remove(void *v,
+ ptree_node_t **rootp,
+ int (*cmp)(const void *v1, const void *v2),
+ void **oldval)
+{
+ struct ptree_node *cur;
+
+#ifdef VERIFY_TREE
+ assert(_verify_tree(rootp, cmp));
+#endif
+
+ cur = *rootp;
+ if (_walk_to(v, &cur, NULL, cmp) != 0)
+ return 0;
+ _remove_node(rootp, cur, oldval);
+
+#ifdef VERIFY_TREE
+ assert(_verify_tree(rootp, cmp));
+#endif
+
+ return 1;
+}
+
+int
+ptree_replace(void *v,
+ ptree_node_t **rootp,
+ int (*cmp)(const void *v1, const void *v2),
+ void **oldval)
+{
+ struct ptree_node **parentpp;
+ struct ptree_node *parentp;
+ struct ptree_node *pn;
+ int c;
+
+#ifdef VERIFY_TREE
+ int countStart = _count_nodes(rootp), countEnd=0;
+#endif
+
+ parentp = *rootp;
+ parentpp = rootp;
+
+#ifdef VERIFY_TREE
+ assert(_verify_tree(rootp, cmp));
+#endif
+
+ //if we find v in the tree, replace it
+ if ((c = _walk_to(v, &parentp, &parentpp, cmp)) == 0)
+ {
+ if (oldval)
+ *oldval = parentp->pn_value;
+ parentp->pn_value = v;
+
+#ifdef VERIFY_TREE
+ assert(_verify_tree(rootp, cmp));
+#endif
+
+#ifdef VERIFY_TREE
+ countEnd = _count_nodes(rootp);
+ assert(countEnd == countStart);
+#endif
+
+ return 1;
+ }
+
+ //otherwise, add it to the tree
+ if (!(pn = malloc(sizeof (*pn))))
+ return 0;
+
+ memset(pn, 0, sizeof (*pn));
+ pn->pn_value = v;
+ pn->pn_parent = parentp;
+ *parentpp = pn;
+ if (oldval)
+ *oldval = 0;
+
+#ifdef VERIFY_TREE
+ assert(_verify_tree(rootp, cmp));
+#endif
+
+#ifdef VERIFY_TREE
+ countEnd = _count_nodes(rootp);
+ countStart++;
+ assert(countEnd == countStart);
+#endif
+
+ return 1;
+}
+
+int
+ptree_contains(void *v,
+ ptree_node_t *parentp,
+ int (*cmp)(const void *v1, const void *v2),
+ void **nodeval)
+{
+ int c;
+
+ if ((c = _walk_to(v, &parentp, NULL, cmp)) == 0)
+ {
+ if (nodeval)
+ *nodeval = parentp->pn_value;
+ return 1;
+ }
+ if (nodeval)
+ *nodeval = 0;
+ return 0;
+} \ No newline at end of file
diff --git a/utils/ptree.h b/utils/ptree.h
new file mode 100644
index 0000000..62166ac
--- /dev/null
+++ b/utils/ptree.h
@@ -0,0 +1,33 @@
+#ifndef _PTREE_H_
+#define _PTREE_H_
+
+typedef struct ptree_node ptree_node_t;
+
+typedef enum {
+ PTREE_PREORDER = 1,
+ PTREE_INORDER = 2,
+ PTREE_POSTORDER = 3
+} ptree_order_t;
+
+typedef enum {
+ PTREE_WALK_STOP = 0,
+ PTREE_WALK_CONTINUE = 1
+} ptree_walk_res_t;
+
+int ptree_contains(void *v, ptree_node_t *root, int(*)(const void *sv,
+ const void *tv), void **nodeval);
+int ptree_remove(void *v, ptree_node_t **root, int(*)(const void *sv,
+ const void *tv), void **oltval);
+int ptree_replace(void *v, ptree_node_t **root, int(*)(const void *sv,
+ const void *tv), void **oltval);
+void ptree_clear(ptree_node_t **root);
+ptree_walk_res_t
+ptree_walk(ptree_node_t *start,
+ ptree_order_t order,
+ ptree_walk_res_t (*func)(const void *v1, int level, void *arg, void *ptree_inorder_walking_remove_arg),
+ int (*cmp)(const void *v1, const void *v2),
+ void *arg);
+int ptree_inorder_walk_remove(ptree_node_t **rootp, void **oldval, void *piwra,
+ int (*cmp)(const void *v1, const void *v2));
+
+#endif
diff --git a/utils/utils.c b/utils/utils.c
new file mode 100644
index 0000000..57611f2
--- /dev/null
+++ b/utils/utils.c
@@ -0,0 +1,1223 @@
+#include "../stdafx.h"
+#include <ctype.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <regex.h>
+#include <assert.h>
+#if !defined(_WINDOWS) || defined(__CYGWIN__)
+#include <fcntl.h>
+#include <netdb.h>
+#include <netinet/in.h>
+//#include <arpa/inet.h>
+#include <sys/poll.h>
+#else
+#include "wincompat.h"
+#endif
+#if defined(__CYGWIN__) || defined(__MINGW32_VERSION)
+#include "getaddrinfo.h"
+#endif
+#ifndef _MSC_EXTENSIONS
+#include <unistd.h>
+#endif
+#include "utils.h"
+
+#if defined(_MACOSX) || defined(_LINUX)
+// Use IPv6 on Mac OS and Linux
+#define _ENABLE_IPv6
+#endif
+
+/* character escaping */
+#define PASSTHRU(c) (isalnum((unsigned char)c)/* || c == ' '*/ || c == '.' || c == '/' || c == ':' || c == '%')
+
+#ifndef _WINDOWS
+#define SET_ERRDESC(errdesc, errdesclen) (errdesc ? snprintf(errdesc, \
+ errdesclen, "%s", strerror(errno)) : 0);
+#else
+#define SET_ERRDESC(errdesc, errdesclen) wsa_set_errdesc(errdesc, errdesclen);
+#endif
+
+/* size of first buffer malloc; start small to exercise grow routines */
+#define FIRSTSIZE 128
+
+int logging_enabled = FALSE;
+#ifndef USE_PHIDGET21_LOGGING
+static FILE *log_stream = 0;
+static const char *log_pname = 0;
+#endif
+
+#if defined(_WINDOWS) && !defined(_CYGWIN)
+static void
+wsa_set_errdesc(char *errdesc, int len)
+{
+ int err;
+
+ if (!errdesc)
+ return;
+ switch (err = WSAGetLastError()) {
+ case 10038:
+ snprintf(errdesc, len, "Socket operation on non-socket");
+ return;
+ case 10061:
+ snprintf(errdesc, len, "Connection refused");
+ return;
+ default:
+ snprintf(errdesc, len, "WSA error %d", err);
+ return;
+ }
+}
+#endif
+
+
+/* Modified to work properly on ALL systems, not just UNIX */
+int
+pvasprintf(char **ret, const char *fmt, va_list ap)
+{
+ char *buf = NULL;
+ size_t bufsize = 0;
+ char *newbuf = NULL;
+ size_t nextsize = 0;
+ int outsize = 0;
+
+ bufsize = 0;
+ for (;;) {
+ if (bufsize == 0) {
+ if ((buf = (char *)malloc(FIRSTSIZE)) == NULL) {
+ *ret = NULL;
+ return -1;
+ }
+ bufsize = 1;
+ } else if ((newbuf = (char *)realloc(buf, nextsize)) != NULL) {
+ buf = newbuf;
+ bufsize = nextsize;
+ } else {
+ free(buf); buf = NULL;
+ *ret = NULL;
+ return -1;
+ }
+
+#ifdef _WINDOWS
+ outsize = _vsnprintf(buf, bufsize, fmt, ap);
+#else
+ {
+ va_list copy;
+ va_copy(copy, ap);
+ outsize = vsnprintf(buf, bufsize, fmt, copy);
+ va_end(copy);
+ }
+#endif
+
+ if (outsize == -1) {
+ /* Clear indication that output was truncated, but no
+ * clear indication of how big buffer needs to be, so
+ * simply double existing buffer size for next time.
+ */
+ nextsize = (int)bufsize * 2;
+
+ } else if (outsize == (int)bufsize) {
+ /* Output was truncated (since at least the \0 could
+ * not fit), but no indication of how big the buffer
+ * needs to be, so just double existing buffer size
+ * for next time.
+ */
+ nextsize = (int)bufsize * 2;
+
+ } else if (outsize > (int)bufsize) {
+ /* Output was truncated, but we were told exactly how
+ * big the buffer needs to be next time. Add two chars
+ * to the returned size. One for the \0, and one to
+ * prevent ambiguity in the next case below.
+ */
+ nextsize = outsize + 2;
+
+ } else if (outsize == (int)bufsize - 1) {
+ /* This is ambiguous. May mean that the output string
+ * exactly fits, but on some systems the output string
+ * may have been trucated. We can't tell.
+ * Just double the buffer size for next time.
+ */
+ nextsize = (int)bufsize * 2;
+
+ } else {
+ /* Output was not truncated */
+ break;
+ }
+ }
+ *ret = buf;
+ return (int)strlen(buf);
+}
+
+int
+pasprintf(char **ret, const char *fmt, ...)
+{
+ va_list args;
+ int outsize = 0;
+
+ va_start(args, fmt);
+ outsize = pvasprintf(ret, fmt, args);
+ va_end(args);
+
+ return outsize;
+}
+
+int
+pd_getline(char *buf, unsigned int bufsize, int *bufcur,
+ int *buflen, int(*readfunc)(int, void *, unsigned int, char *,
+ int), int(*closefunc)(int, char *, int), int readfd, char **line,
+ char *errdesc, int errlen)
+{
+ char *eol;
+ unsigned int srcsize;
+ int linelen;
+ int linesize = 1024;
+
+ linelen = 0;
+ if (!(*line = malloc(linesize))) {
+ /* no memory */
+ if (closefunc)
+ (void) closefunc(readfd, errdesc, errlen);
+ return 0;
+ }
+ **line = 0;
+
+top:
+ /* this loops until buf is empty, or we hit the end of a line */
+ while (*bufcur < *buflen) {
+
+ /* looking for eol - \n or \0
+ * eol points to the line ending \0, or NULL if line continues.
+ * srcsize set to number of chars to copy into line. */
+ if (!(eol = strchr(buf + *bufcur, '\n')))
+ {
+ if (!(eol = memchr(buf + *bufcur, '\0', *buflen - *bufcur)))
+ {
+ /* couldn't find '\n' or '\0' */
+ srcsize = *buflen - *bufcur;
+ }
+ else
+ {
+ /* found '\0' */
+ srcsize = eol - buf - *bufcur + 1;
+ }
+ }
+ else
+ {
+ /* found '\n' */
+ srcsize = eol - buf - *bufcur + 1;
+ /* change \n into \0 */
+ *eol = 0;
+ }
+
+ /* double size of *line until it's big enough for srcsize characters */
+ while ((int)srcsize > (linesize - linelen))
+ {
+ char *newline;
+
+ linesize *= 2;
+
+ if (!(newline = realloc(*line, linesize))) {
+ /* not enough memory */
+ free(*line);
+ *line = NULL;
+ if (closefunc)
+ (void) closefunc(readfd, errdesc, errlen);
+ return 0;
+ }
+
+ *line = newline;
+ }
+
+ /* copy buf into line and modify pointers */
+ memcpy(*line + linelen, buf + *bufcur, srcsize);
+ linelen += srcsize;
+ *bufcur += srcsize;
+
+ /* Are we at the end of the string? */
+ if (eol)
+ {
+ /* change the first \r into a \0
+ * This handles when they send \r\n but not \n\r */
+ if ((eol = strchr(*line, '\r')) != NULL)
+ *eol = 0;
+
+ /* This is the (only) happy return from this function */
+ return 1;
+ }
+ } //while (*bufcur < *buflen)
+
+ /* we get here when there wasn't the end of a string in the buffer */
+ *bufcur = 0;
+ /* read in some data */
+ if ((*buflen = readfunc(readfd, buf, bufsize - 1, errdesc, errlen)) <= 0)
+ {
+ /* read either errored, or the socket is closed */
+ free(*line);
+ *line = NULL;
+ if (closefunc)
+ (void) closefunc(readfd, errdesc, errlen);
+ return 0;
+ }
+ /* null terminate - so strchr knows when to stop */
+ buf[*buflen] = 0;
+ /* go process it */
+ goto top;
+}
+
+/*int
+pd_getline_simple(int fd, char **line)
+{
+int bufcur = 0;
+int buflen = 0;
+char buf[2];
+
+return pd_getline(buf, sizeof (buf), &bufcur, &buflen, pu_read, 0, fd,
+line, 0, 0);
+}*/
+
+int
+getmatchsub(const char *line, char **subp, const regmatch_t pmatch[], int n)
+{
+ int len;
+
+ len = (pmatch[n].rm_so >= 0) ? pmatch[n].rm_eo - pmatch[n].rm_so : 0;
+ if (subp) {
+ if (len) {
+ if (!(*subp = malloc(len + 1)))
+ return len;
+ memcpy(*subp, line + pmatch[n].rm_so, len);
+ subp[0][len] = 0;
+ } else {
+ *subp = NULL;
+ }
+ }
+
+ return len;
+}
+
+static int waitForConnect(int s, int cancel)
+{
+ int err;
+ fd_set readFDs;
+ fd_set writeFDs;
+ fd_set errorFDs;
+ int selectResult;
+ int maxFD = s;
+
+ FD_ZERO(&readFDs);
+ FD_ZERO(&writeFDs);
+ FD_ZERO(&errorFDs);
+
+ // We always want the cancel socket in the read FD set.
+#ifndef _WINDOWS
+ if (cancel >= 0)
+#else
+ if (cancel != INVALID_SOCKET)
+#endif
+ FD_SET(cancel, &readFDs);
+ FD_SET(s, &readFDs);
+ FD_SET(s, &writeFDs);
+ FD_SET(s, &errorFDs);
+
+#ifndef _WINDOWS
+ if (cancel >= 0 && cancel > s)
+#else
+ if (cancel != INVALID_SOCKET && cancel > s)
+#endif
+ maxFD = cancel;
+
+ // Do the select, looping while we get EINTR errors.
+ err = 0;
+ do {
+#ifndef _WINDOWS
+ selectResult = select(maxFD + 1, &readFDs, &writeFDs, NULL, NULL);
+#else
+ //Windows reports a failed connect in errorFDs
+ selectResult = select(maxFD + 1, &readFDs, &writeFDs, &errorFDs, NULL);
+#endif
+
+ if (selectResult < 0) {
+#ifndef _WINDOWS
+ err = errno;
+#else
+ err = WSAGetLastError();
+#endif
+ }
+ } while (err == EINTR);
+
+ if (err == 0) {
+ // We have an infinite timeout, so a result of 0 should be impossible,
+ // so assert that selectResult is positive.
+ assert(selectResult > 0);
+
+ // Check for cancellation first.
+#ifndef _WINDOWS
+ if (cancel >= 0)
+#else
+ if (cancel != INVALID_SOCKET)
+#endif
+ {
+ if ( FD_ISSET(cancel, &readFDs) ) {
+ err = ECANCELED;
+ }
+ }
+ }
+
+ return err;
+}
+
+int cancelConnect(int cancelSocket)
+{
+ int err;
+ ssize_t bytesWritten;
+ static const char kCancelMessage = 0;
+
+ err = 0;
+
+#ifndef _WINDOWS
+ bytesWritten = write(cancelSocket, &kCancelMessage, sizeof(kCancelMessage));
+#else
+ bytesWritten = send(cancelSocket, &kCancelMessage, sizeof(kCancelMessage), MSG_NOSIGNAL);
+#endif
+ if (bytesWritten < 0) {
+ err = errno;
+ }
+ return err;
+}
+
+int CCONV
+stream_server_connect(const char *dest, const char *svcname, int *fdp, int *cancelSocket, char *errdesc, int errdesclen)
+{
+ struct addrinfo hints, *res, *res0 = NULL;
+ int err, cancelled = 0;
+ SOCKET s = INVALID_SOCKET;
+ int tmpSock[2];
+ int cancelRecvSocket = INVALID_SOCKET;
+#ifdef _WINDOWS
+ u_long nNonBlocking = TRUE;
+#endif
+#ifdef _MACOSX
+ int opt;
+#endif
+
+ memset(&hints, 0, sizeof(hints));
+ //hints.ai_family = AF_INET;
+ hints.ai_family = PF_UNSPEC; //any family (including IPV6)
+ hints.ai_socktype = SOCK_STREAM;
+#ifndef WINCE
+ hints.ai_flags = AI_ADDRCONFIG;
+#endif
+
+ if ((err = getaddrinfo(dest, svcname, &hints, &res0)) != 0) {
+ if (errdesc)
+ snprintf(errdesc, errdesclen, "getaddrinfo: %s", gai_strerror(err));
+ freeaddrinfo(res0);
+ return 0;
+ }
+
+ //setup cancel socket
+ err = socketpair(AF_UNIX, SOCK_STREAM, 0, tmpSock);
+ if (err < 0) {
+ SET_ERRDESC(errdesc, errdesclen);
+ *cancelSocket = INVALID_SOCKET;
+ pu_log(PUL_WARN, 0, "Unable to create a cancel socket: %s",errdesc);
+ return 0;
+ } else {
+ *cancelSocket = tmpSock[0];
+ cancelRecvSocket = tmpSock[1];
+ }
+
+ for (res = res0; res; res = res->ai_next) {
+ if(cancelled)
+ break;
+
+ // sometimes on mac, we get 0.0.0.0 ??!! - just ignore it
+ // I think this is IPv6 - don't ignore...
+ //if(((struct sockaddr_in *)res->ai_addr)->sin_addr.s_addr == 0)
+ //{
+ // continue;
+ //}
+
+ s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
+#ifndef _WINDOWS
+ if (s < 0)
+#else
+ if (s == INVALID_SOCKET)
+#endif
+ {
+ SET_ERRDESC(errdesc, errdesclen);
+ continue;
+ }
+
+ //Make the socket non-blocking
+#ifndef _WINDOWS
+ if (fcntl(s, F_SETFL, O_NONBLOCK) < 0) {
+ SET_ERRDESC(errdesc, errdesclen);
+ s = INVALID_SOCKET;
+ continue;
+ }
+#else
+ if (ioctlsocket(s, FIONBIO, (u_long FAR *) & nNonBlocking))
+ {
+ s = INVALID_SOCKET;
+ continue;
+ }
+#endif
+
+ if((err = connect(s, res->ai_addr, (int) res->ai_addrlen)) != 0)
+ {
+ //Connection in progress - wait for completion or cancelation
+#ifndef _WINDOWS
+ if(errno == EINPROGRESS)
+#else
+ err = WSAGetLastError();
+ if(err == WSAEINPROGRESS || err == WSAEWOULDBLOCK)
+#endif
+ {
+ err = waitForConnect(s, cancelRecvSocket);
+
+ // Not cancelled, so must have either connected or failed.
+ // Check to see if we're connected by calling getpeername.
+ if (err == 0) {
+ socklen_t len = sizeof(struct sockaddr);
+ struct sockaddr name;
+ err = getpeername(s, &name, &len);
+
+ // The connection failed. Get the error associated with
+ // the connection attempt.
+ if (err < 0) {
+ char tmpErr;
+#ifdef _WINDOWS
+ err = WSAGetLastError();
+#endif
+ len = sizeof(tmpErr);
+ err = getsockopt(s, SOL_SOCKET, SO_ERROR, &tmpErr, &len);
+ if (err < 0) {
+#ifdef _WINDOWS
+ err = WSAGetLastError();
+#else
+ err = errno;
+#endif
+ } else {
+ assert(tmpErr != 0);
+ err = tmpErr;
+ }
+ }
+ //connection good
+ else
+ break;
+ }
+ //cancelled
+ else if(err==ECANCELED)
+ {
+ cancelled = 1;
+ }
+
+#ifdef _WINDOWS
+ WSASetLastError(err);
+#else
+ errno = err;
+#endif
+ }
+ //Error
+ SET_ERRDESC(errdesc, errdesclen);
+#ifndef _WINDOWS
+ close(s);
+#else
+ closesocket(s);
+#endif
+ s = INVALID_SOCKET;
+ continue;
+ }
+ break;
+ }
+
+ //cleanup cancel socket - not needed anymore
+ if (tmpSock[0] != -1)
+#ifndef _WINDOWS
+ close(tmpSock[0]);
+#else
+ closesocket(tmpSock[0]);
+#endif
+ if (tmpSock[1] != -1)
+#ifndef _WINDOWS
+ close(tmpSock[1]);
+#else
+ closesocket(tmpSock[1]);
+#endif
+ *cancelSocket = INVALID_SOCKET;
+
+#ifndef _WINDOWS
+ if (s < 0)
+#else
+ if (s == INVALID_SOCKET)
+#endif
+ {
+ SET_ERRDESC(errdesc, errdesclen);
+ freeaddrinfo(res0);
+ return 0;
+ }
+
+#ifdef _MACOSX
+ opt = 1;
+ setsockopt(s, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt));
+#endif
+ if (fdp)
+ *fdp = s;
+ freeaddrinfo(res0);
+ return 1;
+}
+
+
+#ifndef _ENABLE_IPv6
+/*
+* Accepts a TCP connection on a given port and invokes the given
+* callback to handle it. This is where the main server thread sits.
+* IPv4 Version
+*/
+int
+stream_server_accept(int port, void(*clfunc)(int fd, const char *addr,
+ int port), char *errdesc, int errdesclen)
+{
+ struct sockaddr_in sin = { 0 };
+ struct sockaddr_in cin = { 0 };
+ const int opt = 1;
+ socklen_t cl;
+ char *addr;
+ int fd;
+ int s;
+ int errcount=0;
+ //#ifdef _WINDOWS
+ // u_long nNonBlocking = TRUE;
+ //#endif
+
+ if (!(s = (int)socket(PF_INET, SOCK_STREAM, 0))) {
+ SET_ERRDESC(errdesc, errdesclen);
+ return 0;
+ }
+ setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void *)&opt, sizeof (opt));
+#ifdef _MACOSX
+ setsockopt(s, SOL_SOCKET, SO_NOSIGPIPE, (void *)&opt, sizeof (opt));
+#endif
+ sin.sin_family = AF_INET;
+ sin.sin_port = htons(port);
+ sin.sin_addr.s_addr = INADDR_ANY;
+ if (bind(s, (struct sockaddr *)&sin, sizeof (sin)) != 0) {
+ SET_ERRDESC(errdesc, errdesclen);
+ return 0;
+ }
+ if (listen(s, 5) != 0) {
+ SET_ERRDESC(errdesc, errdesclen);
+ return 0;
+ }
+ for (;;) {
+ cl = sizeof(cin);
+ while ((fd = (int)accept(s, (struct sockaddr *)&cin, &cl)) < 0 &&
+ errno == EAGAIN)
+ ;
+ if (fd < 0) {
+ SET_ERRDESC(errdesc, errdesclen);
+ pu_log(PUL_WARN, 0, "Error in stream_server_accept: %s",errdesc);
+ if(errcount < 10)
+ {
+ SLEEP(50);
+ continue;
+ }
+ else
+ {
+ pu_log(PUL_CRIT, 0, "Too many errors in stream_server_accept, exiting.");
+ return 0;
+ }
+ }
+ errcount = 0;
+ setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&opt, sizeof (opt));
+
+#ifdef _MACOSX
+ // otherwise we get SIGPIPEs that aren't important
+ setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&opt, sizeof (opt));
+#endif
+
+ addr = strdup(inet_ntoa(cin.sin_addr));
+ clfunc(fd, addr, ntohs(cin.sin_port));
+ free(addr); addr = NULL;
+ }
+ /*NOTREACHED*/
+}
+
+#else
+
+/*
+* Accepts a TCP connection on a given port and invokes the given
+* callback to handle it. This is where the main server thread sits.
+* IPv6 version! - doesn't work with Windows yet...
+*/
+int
+stream_server_accept(int port,
+ void(*clfunc)(int fd, const char *addr,int port),
+ char *errdesc,
+ int errdesclen)
+{
+ struct addrinfo *ai, *runp;
+ struct addrinfo hints;
+ int e, nfds;
+ char portStr[20];
+ struct pollfd *fds;
+ int opt;
+
+ // Get a list of interfaces to Bind to
+ memset(&hints, '\0', sizeof(hints));
+ hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG;
+ hints.ai_socktype = SOCK_STREAM;
+ //hints.ai_family = PF_UNSPEC;
+
+ snprintf(portStr, 20, "%d", port);
+ if((e = getaddrinfo(NULL, portStr, &hints, &ai)) != 0)
+ {
+ (errdesc ? snprintf(errdesc, errdesclen, "getaddrinfo: %s", gai_strerror(e)) : 0);
+ return 0;
+ }
+
+ // Malloc array
+ nfds = 0;
+ runp = ai;
+ while(runp)
+ {
+ nfds++;
+ runp = runp->ai_next;
+ }
+ fds = (struct pollfd *)malloc(nfds * sizeof(struct pollfd));
+
+ pu_log(PUL_INFO, 0, "Found %d interfaces to Bind to.", nfds);
+
+ // Bind to interfaces
+ for(nfds = 0, runp = ai; runp; runp = runp->ai_next)
+ {
+ pu_log(PUL_INFO, 0, "Setting up interface %d: Family:%d, Socktype:%d, Protocol:%d", nfds, runp->ai_family, runp->ai_socktype, runp->ai_protocol);
+
+ if((fds[nfds].fd = socket(runp->ai_family, runp->ai_socktype, runp->ai_protocol)) < 0)
+ {
+ pu_log(PUL_WARN, 0, "Error on socket: %s", strerror(errno));
+ continue;
+ }
+
+ fds[nfds].events = POLLIN;
+ opt = 1;
+ setsockopt(fds[nfds].fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
+#ifdef _MACOSX
+ opt = 1;
+ setsockopt(fds[nfds].fd, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt));
+#endif
+
+ if(bind(fds[nfds].fd, runp->ai_addr, runp->ai_addrlen) != 0)
+ {
+ if(errno != EADDRINUSE)
+ {
+ pu_log(PUL_WARN, 0, "Error on bind: %s", strerror(errno));
+ continue;
+ }
+ else
+ close(fds[nfds].fd);
+ }
+ else //bind was successfull
+ {
+ if(listen(fds[nfds].fd, SOMAXCONN) != 0)
+ {
+ pu_log(PUL_WARN, 0, "Error on listen: %s", strerror(errno));
+ continue;
+ }
+ else //listen was successfull
+ nfds++;
+ }
+
+ }
+ freeaddrinfo(ai);
+
+ // didn't bind to anything!
+ if(nfds == 0)
+ {
+ (errdesc ? snprintf(errdesc, errdesclen, "Couldn't bind to any interfaces!") : 0);
+ return 0;
+ }
+
+ while(1)
+ {
+ if(poll(fds, nfds, -1) > 0)
+ {
+ int i;
+ for(i = 0; i < nfds; i++)
+ {
+ if(fds[i].revents & POLLIN)
+ {
+ struct sockaddr_storage rem;
+ socklen_t remlen = sizeof(rem);
+ int fd;
+ char addr[200];
+
+ while((fd = accept(fds[i].fd, (struct sockaddr *) &rem, &remlen)) < 0 && errno == EAGAIN);
+
+ if(fd < 0)
+ {
+ SET_ERRDESC(errdesc, errdesclen);
+ return 0;
+ }
+
+ opt = 1;
+ setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&opt, sizeof (opt));
+#ifdef _MACOSX
+ opt = 1;
+ setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&opt, sizeof (opt));
+#endif
+
+ (void)getnameinfo((struct sockaddr *)&rem, remlen, addr, sizeof(addr), NULL, 0, NI_NUMERICHOST);
+ clfunc(fd, addr, ntohs(((struct sockaddr_in *)&rem)->sin_port));
+ }
+ }
+ }
+ }
+ /*NOTREACHED*/
+}
+#endif
+
+int
+pu_write(int fd, const void *buf, unsigned int len, char *errdesc, int edlen)
+{
+ //why a static mutex instead of a per-socket one???
+ //Why a mutex at all?? I'm oging to disable and see what happens...
+ //static pthread_mutex_t *writelock = 0;
+ int res = 0;
+ int olen = len;
+#ifdef _WINDOWS
+ int bytesSent = 0;
+ WSABUF DataBuf;
+#endif
+
+ if (fd == -1)
+ return len;
+
+ pu_log(PUL_VERB, 0, "Sending: \"%s\"",(char *)buf);
+
+ //if (!writelock) {
+ // if (!(writelock = malloc(sizeof (*writelock))))
+ // return 0;
+ // pthread_mutex_init(writelock, NULL);
+ //}
+ //pthread_mutex_lock(writelock);
+ do {
+ if (res > 0) {
+#ifdef _WINDOWS
+ (unsigned char *)buf += res;
+#else
+ buf += res;
+#endif
+ len -= res;
+ }
+ if (len)
+ {
+tryagain:
+#ifdef _WINDOWS
+ DataBuf.buf = (char *)buf;
+ DataBuf.len = len;
+
+ res = WSASend(fd, &DataBuf, 1, &bytesSent, 0, NULL, NULL);
+ if(res)
+ res = -1;
+ else
+ res = bytesSent;
+#else
+ res = send(fd, buf, len, MSG_NOSIGNAL);
+#endif
+ //Error
+ if(res == -1)
+ {
+#ifdef _WINDOWS
+ switch(WSAGetLastError())
+ {
+ //non-blocking, try again
+ case WSAEWOULDBLOCK:
+ SLEEP(10);
+ goto tryagain;
+ //any other error, don't try again
+ default:
+ break;
+ }
+#else
+ switch(errno)
+ {
+ //Interrupted, try again
+ case EINTR:
+ //non-blocking, try again
+ case EAGAIN:
+ SLEEP(10);
+ goto tryagain;
+ //any other error, don't try again
+ default:
+ break;
+ }
+#endif
+ }
+ }
+ else
+ res = olen;
+ } while (len && res >= 0);
+ //pthread_mutex_unlock(writelock);
+
+ if (res != olen) {
+ SET_ERRDESC(errdesc, edlen);
+ return 0;
+ } else
+ return 1;
+}
+
+int
+pu_read(int fd, void *buf, unsigned int len, char *errdesc, int edlen)
+{
+ int res=0;
+ if (fd == -1)
+ return 0;
+
+tryagain:
+ res = recv(fd, buf, len, 0);
+ //Error
+ if(res == -1)
+ {
+#ifdef _WINDOWS
+ switch(WSAGetLastError())
+ {
+ //non-blocking, try again
+ case WSAEWOULDBLOCK:
+ SLEEP(10);
+ goto tryagain;
+ //any other error, don't try again
+ default:
+ break;
+ }
+#else
+ switch(errno)
+ {
+ //Interrupted, try again
+ case EINTR:
+ //non-blocking, try again
+ case EAGAIN:
+ SLEEP(10);
+ goto tryagain;
+ //any other error, don't try again
+ default:
+ break;
+ }
+#endif
+ }
+ if (res <= 0) {
+ SET_ERRDESC(errdesc, edlen);
+ return 0;
+ } else
+ {
+ pu_log(PUL_VERB,0,"Recieved: \"%s\"", (char *)buf);
+ return res;
+ }
+}
+
+int
+pu_close(int fd, char *errdesc, int edlen)
+{
+ int res=0;
+ if(fd == -1) return 0;
+#ifndef _WINDOWS
+ res = close(fd);
+#else
+ res = closesocket(fd);
+#endif
+ SET_ERRDESC(errdesc, edlen);
+ return res;
+}
+
+// We want to use phidget21 logging not utils.c logging
+#ifndef USE_PHIDGET21_LOGGING
+static const char *
+pu_log_level_str(pu_log_level_t l)
+{
+ switch (l) {
+ case PUL_ERR:
+ return "ERR";
+ case PUL_CRIT:
+ return "CRIT";
+ case PUL_WARN:
+ return "WARN";
+ case PUL_INFO:
+ return "INFO";
+ case PUL_DEBUG:
+ return "DEBUG";
+ case PUL_VERB:
+ return "VERBOSE";
+ }
+ return "???";
+}
+
+void
+pu_log_stream(FILE *str)
+{
+ log_stream = str;
+}
+
+void
+pu_log_pname(const char *newname)
+{
+ log_pname = newname;
+}
+
+void
+pu_log(pu_log_level_t l, int s, const char *fmt, ...)
+{
+ static pthread_mutex_t logLock;
+ static int logLockInitialized = FALSE;
+ va_list va;
+
+ if(!logLockInitialized)
+ {
+ pthread_mutex_init(&logLock, NULL);
+ logLockInitialized = TRUE;
+ }
+ pthread_mutex_lock(&logLock);
+
+#ifndef DEBUG
+ if(logging_enabled)
+#endif
+ {
+#ifdef WINCE
+ if (!log_stream)
+ log_stream = stdout;
+ fprintf(log_stream, "%s%s%d/%s ", log_pname ? log_pname : "",
+ log_pname ? " " : "", s, pu_log_level_str(l));
+ va_start(va, fmt);
+ vfprintf(log_stream, fmt, va);
+ va_end(va);
+ fprintf(log_stream, "\n");
+ fflush(log_stream);
+#else
+ char date[50];
+ struct tm *tm;
+ time_t t;
+
+ if (!log_stream)
+ log_stream = stdout;
+
+ time(&t);
+ tm = localtime(&t);
+ if (!strftime(date, sizeof (date), "%c", tm))
+ strncpy(date, "?", sizeof (date));
+ fprintf(log_stream, "%s %s%s%d/%s ", date, log_pname ? log_pname :
+ "", log_pname ? " " : "", s, pu_log_level_str(l));
+ va_start(va, fmt);
+ vfprintf(log_stream, fmt, va);
+ va_end(va);
+ fprintf(log_stream, "\n");
+ fflush(log_stream);
+#endif
+ }
+ pthread_mutex_unlock(&logLock);
+}
+#else
+void
+pu_log(pu_log_level_t l, int s, const char *fmt, ...)
+{
+ CPhidgetLog_level level;
+ char msg[2048], id[10];
+ va_list va;
+
+ switch(l)
+ {
+ case PUL_ERR:
+ level = PHIDGET_LOG_ERROR;
+ break;
+ case PUL_CRIT:
+ level = PHIDGET_LOG_CRITICAL;
+ break;
+ case PUL_WARN:
+ level = PHIDGET_LOG_WARNING;
+ break;
+ case PUL_INFO:
+ level = PHIDGET_LOG_INFO;
+ break;
+ case PUL_DEBUG:
+ level = PHIDGET_LOG_DEBUG;
+ break;
+ case PUL_VERB:
+ default:
+ level = PHIDGET_LOG_VERBOSE;
+ break;
+ }
+
+ va_start(va, fmt);
+#ifdef WINCE
+ vsprintf(msg, fmt, va);
+#else
+ vsnprintf(msg, 2048, fmt, va);
+#endif
+ va_end(va);
+
+ snprintf(id, 10, "%d", s);
+ CPhidget_log(level, id, msg);
+}
+#endif
+
+int
+hexval(unsigned char c)
+{
+ if (isdigit(c))
+ return c - '0';
+ c = tolower(c);
+ if (c <= 'f' && c >= 'a')
+ return c - 'a' + 10;
+ return -1;
+}
+
+int
+unescape(const char *src, char **dstp, unsigned int *dlenp)
+{
+ char *dst;
+ size_t slen;
+ size_t dlen;
+ size_t i;
+
+ for (i = 0, dlen = 0, slen = strlen(src); i < slen; i++, dlen++)
+ if (src[i] == '\\')
+ i += 3;
+
+ if (!(dst = malloc(dlen + 1)))
+ return 0;
+ for (i = 0, dlen = 0, slen = strlen(src); i < slen; i++, dlen++)
+ if (src[i] == '\\') {
+ dst[dlen] = hexval((unsigned)src[i + 2]) * 16 +
+ hexval((unsigned)src[i + 3]);
+ i += 3;
+ } else
+ dst[dlen] = src[i];
+ if (dlenp)
+ *dlenp = (unsigned int)dlen;
+ dst[dlen] = 0;
+
+ *dstp = dst;
+ return 1;
+}
+
+static unsigned char
+hexchar(unsigned char c)
+{
+ if (c > 16)
+ return 'f';
+ if (c >= 10)
+ return c - 10 + 'a';
+ return c + '0';
+}
+
+
+int
+escape2(const char *src, unsigned int slen, char **dstp, int escbacks)
+{
+ char *dst;
+ size_t dlen;
+ size_t i;
+
+ if (!slen)
+ slen = (int)strlen(src);
+ for (i = 0, dlen = 0; i < slen; i++)
+ if (PASSTHRU(src[i]))
+ dlen++;
+ else
+ if(escbacks)
+ dlen += 6;
+ else
+ dlen += 4;
+
+ if (!(dst = malloc(dlen + 1)))
+ return 0;
+ for (i = 0, dlen = 0; i < slen; i++)
+ if (!PASSTHRU(src[i])) {
+ dst[dlen++] = '\\';
+ if(escbacks)
+ dst[dlen++] = '\\';
+ dst[dlen++] = 'x';
+ dst[dlen++] = hexchar((unsigned char)src[i] / 16);
+ dst[dlen++] = hexchar((unsigned char)src[i] % 16);
+ } else {
+ dst[dlen++] = src[i];
+ }
+ dst[dlen++] = 0;
+
+ *dstp = dst;
+ return 1;
+}
+
+int
+escape(const char *src, unsigned int slen, char **dstp)
+{
+ return escape2(src, slen, dstp, PFALSE);
+}
+
+int byteArrayToString(unsigned char *bytes, int length, char *string)
+{
+ int i;
+ for(i=0;i<length;i++)
+ {
+ sprintf(string+(i*2), "%02x", bytes[i]);
+ }
+ return EPHIDGET_OK;
+}
+
+int stringToByteArray(char *string, unsigned char *bytes, int *length)
+{
+ int i;
+
+ if(strlen(string) > (size_t)((*length)*2))
+ return EPHIDGET_INVALIDARG;
+
+ for(i=0;i<(int)strlen(string);i+=2)
+ {
+ if(hexval(string[i])==-1)
+ break;
+ if((i/2)>*length)
+ return EPHIDGET_INVALIDARG;
+ bytes[i/2] = (hexval(string[i])<<4)+hexval(string[i+1]);
+ }
+ *length = i/2;
+
+ return EPHIDGET_OK;
+}
+
+//up to 1048575 (0xFFFFF) per int (not full 32-bit!)
+//IR max is 327670
+int wordArrayToString(int *words, int length, char *string)
+{
+ int i;
+ for(i=0;i<length;i++)
+ {
+ if(words[i] > 0xFFFFF)
+ sprintf(string+(i*5), "fffff");
+ else
+ sprintf(string+(i*5), "%05x", words[i]);
+ }
+ return EPHIDGET_OK;
+}
+
+//up to 1048575 (0xFFFFF) per int (not full 32-bit!)
+int stringToWordArray(char *string, int *words, int *length)
+{
+ int i;
+
+ for(i=0;i<(int)strlen(string);i+=5)
+ {
+ if(hexval(string[i])==-1)
+ break;
+ if((i/5)>*length)
+ return EPHIDGET_INVALIDARG;
+ words[i/5] = (hexval(string[i])<<16)+
+ (hexval(string[i+1])<<12)+
+ (hexval(string[i+2])<<8)+
+ (hexval(string[i+3])<<4)+
+ hexval(string[i+4]);
+ if(words[i/5] == 0xfffff)
+ words[i/5] = PUNK_INT;
+ }
+ *length = i/5;
+
+ return EPHIDGET_OK;
+}
diff --git a/utils/utils.h b/utils/utils.h
new file mode 100644
index 0000000..cbc6309
--- /dev/null
+++ b/utils/utils.h
@@ -0,0 +1,49 @@
+#ifndef _UTILS_H_
+#define _UTILS_H_
+#include <regex.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+typedef enum {
+ PUL_ERR = 1,
+ PUL_CRIT,
+ PUL_WARN,
+ PUL_INFO,
+ PUL_DEBUG,
+ PUL_VERB
+} pu_log_level_t;
+
+int pasprintf(char **ret, const char *fmt, ...);
+int pvasprintf(char **ret, const char *fmt, va_list ap);
+
+int pd_getline(char *buf, unsigned int bufsize, int *bufcur, int *buflen,
+ int(*readfunc)(int, void *, unsigned int, char *errdesc, int errlen),
+ int(*closefunc)(int, char *errdesc, int errlen), int readfd,
+ char **line, char *errdesc, int errlen);
+//int pd_getline_simple(int fd, char **line);
+
+int getmatchsub(const char *line, char **subp, const regmatch_t pmatch[],
+ int n);
+int stream_server_accept(int port, void(*clfunc)(int fd, const char *addr,
+ int port), char *errdesc, int errlen);
+int CCONV stream_server_connect(const char *dest, const char *svcname,
+ int *fdp, int *cancelSocket, char *errdesc, int errdesclen);
+
+int pu_write(int fd, const void *buf, unsigned int len, char *errdesc,
+ int edlen);
+int pu_read(int fd, void *buf, unsigned int len, char *errdesc, int edlen);
+int pu_close(int fd, char *errdesc, int edlen);
+extern int logging_enabled;
+void pu_log_stream(FILE *);
+void pu_log(pu_log_level_t l, int s, const char *fmt, ...);
+int escape(const char *src, unsigned int srclen, char **dstp);
+int escape2(const char *src, unsigned int slen, char **dstp, int escbacks);
+int unescape(const char *src, char **dstp, unsigned int *dstlenp);
+int cancelConnect(int cancelSocket);
+
+int byteArrayToString(unsigned char *bytes, int length, char *string);
+int stringToByteArray(char *string, unsigned char *bytes, int *length);
+int wordArrayToString(int *words, int length, char *string);
+int stringToWordArray(char *string, int *words, int *length);
+
+#endif
diff --git a/version.sh b/version.sh
new file mode 100755
index 0000000..366dee6
--- /dev/null
+++ b/version.sh
@@ -0,0 +1,2 @@
+#!/bin/bash
+echo -n 2.1.8.20120216
diff --git a/zeroconf.c b/zeroconf.c
new file mode 100644
index 0000000..df72b91
--- /dev/null
+++ b/zeroconf.c
@@ -0,0 +1,1231 @@
+#include "stdafx.h"
+#include "csocket.h"
+#include "csocketevents.h"
+#include "cphidgetlist.h"
+#include "cphidgetmanager.h"
+#include "cphidgetdictionary.h"
+#include "cphidgetsbc.h"
+#include "zeroconf.h"
+#include "dns_sd.h"
+
+#ifdef ZEROCONF_RUNTIME_LINKING
+//function prototypes for run-time loaded library
+typedef DNSServiceErrorType (DNSSD_API * DNSServiceRegisterType)
+(DNSServiceRef *,DNSServiceFlags,uint32_t,const char *,
+ const char *,const char *,const char *,uint16_t,uint16_t,
+ const void *,DNSServiceRegisterReply,void *);
+typedef DNSServiceErrorType (DNSSD_API * DNSServiceProcessResultType) (DNSServiceRef);
+typedef void (DNSSD_API * DNSServiceRefDeallocateType) (DNSServiceRef);
+typedef DNSServiceErrorType (DNSSD_API * DNSServiceAddRecordType)
+(DNSServiceRef, DNSRecordRef *, DNSServiceFlags,
+ uint16_t, uint16_t, const void *, uint32_t);
+typedef DNSServiceErrorType (DNSSD_API * DNSServiceUpdateRecordType)
+(DNSServiceRef, DNSRecordRef, DNSServiceFlags,
+ uint16_t, const void *, uint32_t);
+typedef DNSServiceErrorType (DNSSD_API * DNSServiceRemoveRecordType)
+(DNSServiceRef, DNSRecordRef, DNSServiceFlags);
+typedef DNSServiceErrorType (DNSSD_API * DNSServiceBrowseType)
+(DNSServiceRef *, DNSServiceFlags, uint32_t, const char *,
+ const char *, DNSServiceBrowseReply, void *);
+typedef DNSServiceErrorType (DNSSD_API * DNSServiceResolveType)
+(DNSServiceRef *, DNSServiceFlags, uint32_t, const char *,
+ const char *, const char *, DNSServiceResolveReply,
+ void *context);
+typedef DNSServiceErrorType (DNSSD_API * DNSServiceQueryRecordType)
+(DNSServiceRef *, DNSServiceFlags, uint32_t, const char *,
+ uint16_t, uint16_t, DNSServiceQueryRecordReply, void *context);
+typedef int (DNSSD_API * DNSServiceConstructFullNameType)
+(char *, const char *, const char *, const char *);
+typedef int (DNSSD_API * DNSServiceRefSockFDType) (DNSServiceRef sdRef);
+#else
+#define DNSServiceRegisterPtr DNSServiceRegister
+#define DNSServiceProcessResultPtr DNSServiceProcessResult
+#define DNSServiceRefDeallocatePtr DNSServiceRefDeallocate
+#define DNSServiceAddRecordPtr DNSServiceAddRecord
+#define DNSServiceUpdateRecordPtr DNSServiceUpdateRecord
+#define DNSServiceRemoveRecordPtr DNSServiceRemoveRecord
+#define DNSServiceBrowsePtr DNSServiceBrowse
+#define DNSServiceResolvePtr DNSServiceResolve
+#define DNSServiceQueryRecordPtr DNSServiceQueryRecord
+#define DNSServiceConstructFullNamePtr DNSServiceConstructFullName
+#define DNSServiceRefSockFDPtr DNSServiceRefSockFD
+#endif
+
+int Dns_sdInitialized = FALSE;
+int Dns_sdBrowsing = FALSE;
+int stopBrowsing = FALSE;
+DNSServiceRef zeroconf_browse_ws_ref = NULL;
+DNSServiceRef zeroconf_browse_sbc_ref = NULL;
+DNSServiceRef zeroconf_browse_phidget_ref = NULL;
+
+pthread_t dns_thread = NULL;
+
+#ifdef ZEROCONF_RUNTIME_LINKING
+
+//DNS_SD functions
+DNSServiceRegisterType DNSServiceRegisterPtr = NULL;
+DNSServiceProcessResultType DNSServiceProcessResultPtr = NULL;
+DNSServiceRefDeallocateType DNSServiceRefDeallocatePtr = NULL;
+DNSServiceAddRecordType DNSServiceAddRecordPtr = NULL;
+DNSServiceUpdateRecordType DNSServiceUpdateRecordPtr = NULL;
+DNSServiceRemoveRecordType DNSServiceRemoveRecordPtr = NULL;
+DNSServiceBrowseType DNSServiceBrowsePtr = NULL;
+DNSServiceResolveType DNSServiceResolvePtr = NULL;
+DNSServiceQueryRecordType DNSServiceQueryRecordPtr = NULL;
+DNSServiceConstructFullNameType DNSServiceConstructFullNamePtr = NULL;
+DNSServiceRefSockFDType DNSServiceRefSockFDPtr = NULL;
+
+#ifdef _WINDOWS
+HMODULE dllHandle = NULL;
+#elif _LINUX
+void *libHandle = NULL;
+#endif
+#endif
+
+
+static uint8_t *InternalTXTRecordSearch
+(
+ uint16_t txtLen,
+ const void *txtRecord,
+ const char *key,
+ unsigned long *keylen
+ )
+{
+ uint8_t *p = (uint8_t*)txtRecord;
+ uint8_t *e = p + txtLen;
+ *keylen = (unsigned long) strlen(key);
+ while (p<e)
+ {
+ uint8_t *x = p;
+ p += 1 + p[0];
+ if (p <= e && *keylen <= x[0] && !strncmp(key, (char*)x+1, *keylen))
+ if (*keylen == x[0] || x[1+*keylen] == '=') return(x);
+ }
+ return(NULL);
+}
+
+const void * TXTRecordGetValuePtrPtr
+(
+ uint16_t txtLen,
+ const void *txtRecord,
+ const char *key,
+ uint8_t *valueLen
+ )
+{
+ unsigned long keylen;
+ uint8_t *item = InternalTXTRecordSearch(txtLen, txtRecord, key, &keylen);
+ if (!item || item[0] <= keylen) return(NULL); // If key not found, or found with no value, return NULL
+ *valueLen = (uint8_t)(item[0] - (keylen + 1));
+ return (item + 1 + keylen + 1);
+}
+
+int dns_callback_thread(void *ptr)
+{
+ int nfds;
+ fd_set readfds;
+ struct timeval tv;
+ int result;
+
+ int ws_fd = DNSServiceRefSockFDPtr(zeroconf_browse_ws_ref);
+ int sbc_fd = DNSServiceRefSockFDPtr(zeroconf_browse_sbc_ref);
+ int phidget_fd = DNSServiceRefSockFDPtr(zeroconf_browse_phidget_ref);
+
+ nfds = ws_fd;
+ if(sbc_fd>nfds)
+ nfds = sbc_fd;
+ if(phidget_fd > nfds)
+ nfds = phidget_fd;
+ nfds++;
+
+ while (!stopBrowsing)
+ {
+ FD_ZERO(&readfds);
+ FD_SET(ws_fd, &readfds);
+ FD_SET(sbc_fd, &readfds);
+ FD_SET(phidget_fd, &readfds);
+
+ //100ms
+ tv.tv_sec = 0;
+ tv.tv_usec = 100000;
+
+ result = select(nfds, &readfds, (fd_set*)NULL, (fd_set*)NULL, &tv);
+ if (result > 0)
+ {
+ DNSServiceErrorType err = kDNSServiceErr_NoError;
+ if (FD_ISSET(ws_fd, &readfds))
+ {
+ if ((err = DNSServiceProcessResultPtr(zeroconf_browse_ws_ref)) != kDNSServiceErr_NoError)
+ stopBrowsing = 1;
+ }
+ if (FD_ISSET(sbc_fd, &readfds))
+ {
+ if ((err = DNSServiceProcessResultPtr(zeroconf_browse_sbc_ref)) != kDNSServiceErr_NoError)
+ stopBrowsing = 1;
+ }
+ if (FD_ISSET(phidget_fd, &readfds))
+ {
+ if ((err = DNSServiceProcessResultPtr(zeroconf_browse_phidget_ref)) != kDNSServiceErr_NoError)
+ stopBrowsing = 1;
+ }
+ }
+ else if(result == SOCKET_ERROR)
+ {
+ LOG(PHIDGET_LOG_DEBUG, "select( ) returned %d errno %d %s\n", result, errno, strerror(errno));
+ if (errno != EINTR)
+ stopBrowsing = 1;
+ }
+ //result==0 means timeout, loop around again
+ }
+ return EPHIDGET_OK;
+}
+
+void PhidFromTXT(CPhidgetHandle phid, uint16_t txtLen, const char *txtRecord)
+{
+ int i = 0;
+ short txtver;
+ //char *label = NULL;
+ char temp[128];
+ //unsigned int labelLen = 0;
+
+ uint8_t valLen = 0;
+ const char *valPtr = NULL;
+
+ //txt version
+ if(!(valPtr = TXTRecordGetValuePtrPtr(txtLen, txtRecord, "txtvers", &valLen))) return;
+ memcpy(temp, valPtr, valLen);
+ temp[valLen] = '\0';
+ txtver = (short)strtol(temp, NULL, 10);
+
+ //Serial Number
+ if(!(valPtr = TXTRecordGetValuePtrPtr(txtLen, txtRecord, "serial", &valLen))) return;
+ memcpy(temp, valPtr, valLen);
+ temp[valLen] = '\0';
+ phid->serialNumber = strtol(temp, NULL, 10);
+ phid->specificDevice = PHIDGETOPEN_SERIAL;
+
+ //version
+ if(!(valPtr = TXTRecordGetValuePtrPtr(txtLen, txtRecord, "version", &valLen))) return;
+ memcpy(temp, valPtr, valLen);
+ temp[valLen] = '\0';
+ phid->deviceVersion = strtol(temp, NULL, 10);
+
+ //label
+ if(!(valPtr = TXTRecordGetValuePtrPtr(txtLen, txtRecord, "label", &valLen))) return;
+ if(valLen >= MAX_LABEL_STORAGE) valLen = MAX_LABEL_STORAGE-1;
+ memcpy(phid->label, valPtr, valLen);
+ phid->label[valLen] = '\0';
+ /* memcpy(temp, valPtr, valLen);
+ temp[valLen] = '\0';
+ unescape(temp, &label, &labelLen);
+ if(labelLen > MAX_LABEL_STORAGE-1) labelLen = MAX_LABEL_STORAGE-1;
+ memcpy(phid->label, label, labelLen);
+ phid->label[labelLen] = '\0';
+ free(label);*/
+
+ //server_id
+ if(!(valPtr = TXTRecordGetValuePtrPtr(txtLen, txtRecord, "server_id", &valLen))) return;
+ free(phid->networkInfo->zeroconf_server_id);
+ if(!(phid->networkInfo->zeroconf_server_id = malloc(valLen+1))) return;
+ ZEROMEM(phid->networkInfo->zeroconf_server_id, valLen+1);
+ memcpy(phid->networkInfo->zeroconf_server_id, valPtr, valLen);
+
+ // things added in version 2 of the txt
+ if(txtver >= 2)
+ {
+ //Device ID
+ if(!(valPtr = TXTRecordGetValuePtrPtr(txtLen, txtRecord, "id", &valLen))) return;
+ memcpy(temp, valPtr, valLen);
+ temp[valLen] = '\0';
+ phid->deviceIDSpec = strtol(temp, NULL, 10);
+
+ for(i = 1;i<PHIDGET_DEVICE_COUNT;i++)
+ if(phid->deviceIDSpec == Phid_Device_Def[i].pdd_sdid) break;
+ phid->deviceDef = &Phid_Device_Def[i];
+ phid->attr = Phid_Device_Def[i].pdd_attr;
+
+ //Device Class
+ if(!(valPtr = TXTRecordGetValuePtrPtr(txtLen, txtRecord, "class", &valLen))) return;
+ memcpy(temp, valPtr, valLen);
+ temp[valLen] = '\0';
+ phid->deviceID = strtol(temp, NULL, 10);
+ phid->deviceType = Phid_DeviceName[phid->deviceID];
+ }
+ //Old version uses string searching, but some devices have the same name with different IDs
+ else
+ {
+ char *name = NULL;
+ char *type = NULL;
+
+ //name
+ if(!(valPtr = TXTRecordGetValuePtrPtr(txtLen, txtRecord, "name", &valLen))) return;
+ if(!(name = malloc(valLen+1))) return;
+ ZEROMEM(name, valLen+1);
+ memcpy(name, valPtr, valLen);
+ for(i = 0;i<PHIDGET_DEVICE_COUNT;i++)
+ {
+ if(!strcmp(name, Phid_Device_Def[i].pdd_name))
+ {
+ phid->deviceIDSpec = Phid_Device_Def[i].pdd_sdid;
+ phid->deviceDef = &Phid_Device_Def[i];
+ phid->attr = Phid_Device_Def[i].pdd_attr;
+ break;
+ }
+ }
+ free(name);
+
+ //type
+ if(!(valPtr = TXTRecordGetValuePtrPtr(txtLen, txtRecord, "type", &valLen))) return;
+ if(!(type = malloc(valLen+1))) return;
+ ZEROMEM(type, valLen+1);
+ memcpy(type, valPtr, valLen);
+ phid->deviceID = phidget_type_to_id(type);
+ phid->deviceType = Phid_DeviceName[phid->deviceID];
+ free(type);
+ }
+
+ phid->networkInfo->mdns = PTRUE;
+
+}
+
+void DNSServiceQueryRecord_Phidget_CallBack
+(
+ DNSServiceRef DNSServiceRef,
+ DNSServiceFlags flags,
+ uint32_t interfaceIndex,
+ DNSServiceErrorType errorCode,
+ const char *fullname,
+ uint16_t rrtype,
+ uint16_t rrclass,
+ uint16_t rdlen,
+ const void *rdata,
+ uint32_t ttl,
+ void *context
+ )
+{
+ if (errorCode != kDNSServiceErr_NoError)
+ LOG(PHIDGET_LOG_ERROR, "DNSServiceQueryRecord_Phidget_CallBack returned error: %d\n", errorCode);
+ else
+ {
+ CPhidgetHandle phid = (CPhidgetHandle)context;
+ LOG(PHIDGET_LOG_INFO, "DNSServiceQueryRecord_Phidget_CallBack: %s (%d)",fullname,interfaceIndex);
+
+ PhidFromTXT(phid, rdlen, rdata);
+ }
+}
+
+void SBCFromTXT(CPhidgetSBCHandle sbc, uint16_t txtLen, const char *txtRecord)
+{
+ char *hversion = NULL, *txtver = NULL;
+
+ uint8_t valLen = 0;
+ const char *valPtr = NULL;
+
+ //txt version
+ if(!(valPtr = TXTRecordGetValuePtrPtr(txtLen, txtRecord, "txtvers", &valLen))) return;
+ if(!(txtver = malloc(valLen+1))) return;
+ ZEROMEM(txtver, valLen+1);
+ memcpy(txtver, valPtr, valLen);
+ sbc->txtver = (short)strtol(txtver, NULL, 10);
+ free(txtver);
+
+ //Firmware version
+ if(!(valPtr = TXTRecordGetValuePtrPtr(txtLen, txtRecord, "fversion", &valLen))) return;
+ if(valLen > 12) valLen = 12;
+ memcpy(sbc->fversion, valPtr, valLen);
+ sbc->fversion[valLen] = '\0';
+
+ //Hardware version
+ if(!(valPtr = TXTRecordGetValuePtrPtr(txtLen, txtRecord, "hversion", &valLen))) return;
+ if(!(hversion = malloc(valLen+1))) return;
+ ZEROMEM(hversion, valLen+1);
+ memcpy(hversion, valPtr, valLen);
+ sbc->hversion = (short)strtol(hversion, NULL, 10);
+ free(hversion);
+
+ // things added in version 2 of the txt
+ if(sbc->txtver >= 2)
+ {
+ //Hostname
+ if(!(valPtr = TXTRecordGetValuePtrPtr(txtLen, txtRecord, "hostname", &valLen))) return;
+ if(valLen > 128) valLen = 128;
+ memcpy(sbc->hostname, valPtr, valLen);
+ sbc->hostname[valLen] = '\0';
+ }
+ // things added in version 3 of the txt
+ if(sbc->txtver >= 3)
+ {
+ //Device Name
+ if(!(valPtr = TXTRecordGetValuePtrPtr(txtLen, txtRecord, "name", &valLen))) return;
+ if(valLen > 128) valLen = 128;
+ memcpy(sbc->deviceName, valPtr, valLen);
+ sbc->deviceName[valLen] = '\0';
+ }
+ else
+ {
+ sprintf(sbc->deviceName, "PhidgetSBC");
+ }
+}
+
+void DNSServiceQueryRecord_SBC_CallBack
+(
+ DNSServiceRef DNSServiceRef,
+ DNSServiceFlags flags,
+ uint32_t interfaceIndex,
+ DNSServiceErrorType errorCode,
+ const char *fullname,
+ uint16_t rrtype,
+ uint16_t rrclass,
+ uint16_t rdlen,
+ const void *rdata,
+ uint32_t ttl,
+ void *context
+ )
+{
+ if (errorCode != kDNSServiceErr_NoError)
+ LOG(PHIDGET_LOG_ERROR, "DNSServiceQueryRecord_sbc_CallBack returned error: %d\n", errorCode);
+ else
+ {
+ CPhidgetSBCHandle sbc = (CPhidgetSBCHandle)context;
+ LOG(PHIDGET_LOG_INFO, "DNSServiceQueryRecord_sbc_CallBack: %s (%d)",fullname,interfaceIndex);
+
+ SBCFromTXT(sbc, rdlen, rdata);
+ }
+}
+
+void DNSServiceBrowse_Phidget_CallBack(DNSServiceRef service,
+ DNSServiceFlags flags,
+ uint32_t interfaceIndex,
+ DNSServiceErrorType errorCode,
+ const char * name,
+ const char * type,
+ const char * domain,
+ void * context)
+{
+ if (errorCode != kDNSServiceErr_NoError)
+ LOG(PHIDGET_LOG_ERROR, "Dns_sd_BrowseCallBack returned error: %d\n", errorCode);
+ else
+ {
+ DNSServiceErrorType error;
+ DNSServiceRef serviceRef;
+ char fullname[kDNSServiceMaxDomainName];
+
+ CPhidgetHandle phid;
+ CPhidgetHandle found_phid;
+ CPhidgetManagerList *trav;
+
+ DNSServiceConstructFullNamePtr(fullname, name, type, domain);
+
+ LOG(PHIDGET_LOG_INFO, "DNSServiceBrowse_Phidget_CallBack: %s (%s, %s, %d)",name,type,domain,interfaceIndex);
+
+ if((CPhidget_create(&phid))) return;
+ if((CPhidgetRemote_create(&phid->networkInfo))) return;
+
+ phid->networkInfo->zeroconf_name = strdup(name);
+ phid->networkInfo->zeroconf_type = strdup(type);
+ phid->networkInfo->zeroconf_domain = strdup(domain);
+ phid->networkInfo->zeroconf_interface = interfaceIndex;
+
+ if(flags & kDNSServiceFlagsAdd)
+ {
+ error = DNSServiceQueryRecordPtr(&serviceRef, 0, interfaceIndex, fullname,
+ kDNSServiceType_TXT, kDNSServiceClass_IN, DNSServiceQueryRecord_Phidget_CallBack, phid);
+ if (error == kDNSServiceErr_NoError)
+ {
+ DNSServiceProcessResultPtr(serviceRef);
+ DNSServiceRefDeallocatePtr(serviceRef);
+ CThread_mutex_lock(&zeroconfPhidgetsLock);
+ CThread_mutex_lock(&activeRemoteManagersLock);
+
+ CPhidget_setStatusFlag(&phid->status, PHIDGET_ATTACHED_FLAG, &phid->lock);
+ CPhidget_setStatusFlag(&phid->status, PHIDGET_REMOTE_FLAG, &phid->lock);
+
+ if(CList_findInList((CListHandle)zeroconfPhidgets, phid, CPhidget_areExtraEqual, (void **)&found_phid) == EPHIDGET_OK)
+ {
+ //Only do a detach/attach cycle if something's different
+ if(found_phid->serialNumber == phid->serialNumber
+ && found_phid->deviceVersion == phid->deviceVersion
+ && !strcmp(found_phid->label, phid->label)
+ && !strcmp(found_phid->networkInfo->zeroconf_server_id, phid->networkInfo->zeroconf_server_id))
+ {
+ //prefer local. domain
+ if((strcmp(domain, found_phid->networkInfo->zeroconf_domain) != 0) && !(strcmp(domain, "local.")))
+ {
+ free(found_phid->networkInfo->zeroconf_domain);
+ found_phid->networkInfo->zeroconf_domain = phid->networkInfo->zeroconf_domain;
+ phid->networkInfo->zeroconf_domain = NULL;
+ }
+ CPhidgetRemote_free(phid->networkInfo);
+ CPhidget_free(phid);
+ CThread_mutex_unlock(&activeRemoteManagersLock);
+ CThread_mutex_unlock(&zeroconfPhidgetsLock);
+ return;
+ }
+
+ //set detaching status
+ CPhidget_clearStatusFlag(&found_phid->status, PHIDGET_ATTACHED_FLAG, &found_phid->lock);
+ CPhidget_setStatusFlag(&found_phid->status, PHIDGET_DETACHING_FLAG, &found_phid->lock);
+
+ //Remove from list - don't free until after detach event
+ CList_removeFromList((CListHandle *)&zeroconfPhidgets, found_phid, CPhidget_areExtraEqual, FALSE, NULL);
+
+ for (trav=activeRemoteManagers; trav; trav = trav->next)
+ {
+ if(trav->phidm->networkInfo->requested_address==NULL
+ && (trav->phidm->networkInfo->requested_serverID == NULL || !strcmp(trav->phidm->networkInfo->requested_serverID,found_phid->networkInfo->zeroconf_server_id)))
+ {
+ CList_removeFromList((CListHandle *)&trav->phidm->AttachedPhidgets, found_phid, CPhidget_areExtraEqual, PFALSE, NULL);
+
+ if (trav->phidm->fptrDetachChange && trav->phidm->state == PHIDGETMANAGER_ACTIVE)
+ trav->phidm->fptrDetachChange((CPhidgetHandle)found_phid, trav->phidm->fptrDetachChangeptr);
+ }
+ }
+ CPhidgetRemote_free(found_phid->networkInfo);
+ CPhidget_free(found_phid);
+ }
+
+ CPhidget_setStatusFlag(&phid->status, PHIDGET_SERVER_CONNECTED_FLAG, &phid->lock);
+
+ //now add it
+ CList_addToList((CListHandle *)&zeroconfPhidgets, phid, CPhidget_areExtraEqual);
+ //managers
+ for (trav=activeRemoteManagers; trav; trav = trav->next)
+ {
+ if(trav->phidm->networkInfo->requested_address==NULL
+ && (trav->phidm->networkInfo->requested_serverID == NULL || !strcmp(trav->phidm->networkInfo->requested_serverID,phid->networkInfo->zeroconf_server_id)))
+ {
+ CList_addToList((CListHandle *)&trav->phidm->AttachedPhidgets, phid, CPhidget_areExtraEqual);
+
+ if (trav->phidm->fptrAttachChange && trav->phidm->state == PHIDGETMANAGER_ACTIVE)
+ trav->phidm->fptrAttachChange((CPhidgetHandle)phid, trav->phidm->fptrAttachChangeptr);
+ }
+ }
+
+ CThread_mutex_unlock(&activeRemoteManagersLock);
+ CThread_mutex_unlock(&zeroconfPhidgetsLock);
+ }
+ else
+ LOG(PHIDGET_LOG_ERROR, "DNSServiceQueryRecordPtr returned error: %d\n", error);
+ }
+ else
+ {
+ //have to fill in phid manually from just the name
+ int i;
+ char *name_copy = strdup(name);
+ for(i=0;i<(int)strlen(name_copy);i++)
+ if(name_copy[i] == '(') break;
+ if(i<=1) return;
+ name_copy[strlen(name_copy)-1]='\0';
+ name_copy[i-1] = '\0';
+ phid->serialNumber = strtol(name_copy+i+1, NULL, 10);
+ //we need to set this so it checks the serial numbers for a match
+ phid->specificDevice = PHIDGETOPEN_SERIAL;
+ for(i = 0;i<PHIDGET_DEVICE_COUNT;i++)
+ if(!strcmp(name_copy, Phid_Device_Def[i].pdd_name)) break;
+ phid->deviceDef = &Phid_Device_Def[i];
+ //phid->deviceIDSpec = Phid_Device_Def[i].pdd_sdid;
+ phid->deviceIDSpec = 0; //Needs to be 0 because the name can be ambiguous (ie 1018/1200) - we will still match on serial/device class, which is enough for uniqueness
+ phid->attr = Phid_Device_Def[i].pdd_attr;
+ phid->deviceID = Phid_Device_Def[i].pdd_did;
+ phid->deviceType = Phid_DeviceName[phid->deviceID];
+ phid->networkInfo->mdns = PTRUE;
+
+ CThread_mutex_lock(&zeroconfPhidgetsLock);
+ CThread_mutex_lock(&activeRemoteManagersLock);
+
+ CPhidget_clearStatusFlag(&phid->status, PHIDGET_ATTACHED_FLAG, &phid->lock);
+ CPhidget_setStatusFlag(&phid->status, PHIDGET_DETACHING_FLAG, &phid->lock);
+
+ if(!CList_findInList((CListHandle)zeroconfPhidgets, phid, CPhidget_areEqual, (void **)&found_phid))
+ {
+ CPhidget_clearStatusFlag(&found_phid->status, PHIDGET_ATTACHED_FLAG, &found_phid->lock);
+ CPhidget_setStatusFlag(&found_phid->status, PHIDGET_DETACHING_FLAG, &found_phid->lock);
+ CPhidget_setStatusFlag(&found_phid->status, PHIDGET_REMOTE_FLAG, &found_phid->lock);
+ CPhidget_clearStatusFlag(&found_phid->status, PHIDGET_SERVER_CONNECTED_FLAG, &found_phid->lock);
+
+ CList_removeFromList((CListHandle *)&zeroconfPhidgets, found_phid, CPhidget_areExtraEqual, FALSE, NULL);
+ //managers
+ for (trav=activeRemoteManagers; trav; trav = trav->next)
+ {
+ if(trav->phidm->networkInfo->requested_address==NULL
+ && (trav->phidm->networkInfo->requested_serverID == NULL || !strcmp(trav->phidm->networkInfo->requested_serverID,found_phid->networkInfo->zeroconf_server_id)))
+ {
+ CList_removeFromList((CListHandle *)&trav->phidm->AttachedPhidgets, found_phid, CPhidget_areExtraEqual, PFALSE, NULL);
+
+ if (trav->phidm->fptrDetachChange && trav->phidm->state == PHIDGETMANAGER_ACTIVE)
+ trav->phidm->fptrDetachChange((CPhidgetHandle)found_phid, trav->phidm->fptrDetachChangeptr);
+ }
+ }
+ CPhidget_clearStatusFlag(&found_phid->status, PHIDGET_DETACHING_FLAG, &found_phid->lock);
+ CPhidgetRemote_free(found_phid->networkInfo);
+ CPhidget_free(found_phid);
+ }
+ CPhidgetRemote_free(phid->networkInfo);
+ CPhidget_free(phid);
+
+ CThread_mutex_unlock(&activeRemoteManagersLock);
+ CThread_mutex_unlock(&zeroconfPhidgetsLock);
+ free(name_copy);
+ }
+ }
+}
+
+void DNSServiceBrowse_sbc_CallBack(DNSServiceRef service,
+ DNSServiceFlags flags,
+ uint32_t interfaceIndex,
+ DNSServiceErrorType errorCode,
+ const char * name,
+ const char * type,
+ const char * domain,
+ void * context)
+{
+ if (errorCode != kDNSServiceErr_NoError)
+ LOG(PHIDGET_LOG_ERROR, "Dns_sbc_BrowseCallBack returned error: %d\n", errorCode);
+ else
+ {
+ DNSServiceErrorType error;
+ DNSServiceRef serviceRef;
+ char fullname[kDNSServiceMaxDomainName];
+
+ CPhidgetSBCHandle sbc;
+ CPhidgetSBCHandle found_sbc;
+ CPhidgetSBCManagerList *trav;
+
+ DNSServiceConstructFullNamePtr(fullname, name, type, domain);
+
+
+ if((CPhidgetSBC_create(&sbc))) return;
+ if((CPhidgetRemote_create(&sbc->networkInfo))) return;
+
+ sbc->networkInfo->zeroconf_name = strdup(name);
+ sbc->networkInfo->zeroconf_type = strdup(type);
+ sbc->networkInfo->zeroconf_domain = strdup(domain);
+ sbc->networkInfo->zeroconf_interface = interfaceIndex;
+ sbc->networkInfo->mdns = PTRUE;
+
+ strncpy(sbc->mac, name+12, 18); //name == 'PhidgetSBC (??:??:??:??:??:??)'
+ sbc->mac[17] = '\0';
+
+ if(flags & kDNSServiceFlagsAdd)
+ {
+ LOG(PHIDGET_LOG_INFO, "DNSServiceBrowse_sbc_CallBack (Add): %s",name);
+ error = DNSServiceQueryRecordPtr(&serviceRef, 0, interfaceIndex, fullname,
+ kDNSServiceType_TXT, kDNSServiceClass_IN, DNSServiceQueryRecord_SBC_CallBack, sbc);
+ if (error == kDNSServiceErr_NoError)
+ {
+ DNSServiceProcessResultPtr(serviceRef);
+ DNSServiceRefDeallocatePtr(serviceRef);
+
+ CThread_mutex_lock(&zeroconfSBCsLock);
+ CThread_mutex_lock(&activeSBCManagersLock);
+
+ //Check if it's in the list and if it's different, remove it to make way for the new one
+ // (Sometimes, we don't get a proper detach notification)
+ if(CList_findInList((CListHandle)zeroconfSBCs, sbc, CPhidgetSBC_areEqual, (void **)&found_sbc) == EPHIDGET_OK)
+ {
+ if(CPhidgetSBC_areExtraEqual(found_sbc, sbc) != PTRUE) //A version number has changed
+ {
+ //make sure zeroconf_ref is not pending
+ if(found_sbc->networkInfo)
+ {
+ CThread_mutex_lock(&found_sbc->networkInfo->zeroconf_ref_lock);
+ if(found_sbc->networkInfo->zeroconf_ref)
+ {
+ DNSServiceRefDeallocatePtr((DNSServiceRef)found_sbc->networkInfo->zeroconf_ref);
+ found_sbc->networkInfo->zeroconf_ref = NULL;
+ }
+ CThread_mutex_unlock(&found_sbc->networkInfo->zeroconf_ref_lock);
+ }
+
+ //Remove from list - don't free until after detach event
+ CList_removeFromList((CListHandle *)&zeroconfSBCs, found_sbc, CPhidgetSBC_areEqual, PFALSE, NULL);
+
+ for (trav=activeSBCManagers; trav; trav = trav->next)
+ {
+ if (trav->sbcm->fptrDetachChange && trav->sbcm->state == PHIDGETMANAGER_ACTIVE)
+ trav->sbcm->fptrDetachChange((CPhidgetSBCHandle)found_sbc, trav->sbcm->fptrDetachChangeptr);
+ }
+
+ CPhidgetSBC_free(found_sbc);
+
+ //now we fall through and add back to new one
+ }
+ else //Nothing has changed, we didn't remove, don't add
+ {
+ //prefer local. domain
+ if((strcmp(domain, found_sbc->networkInfo->zeroconf_domain) != 0) && !(strcmp(domain, "local.")))
+ {
+ free(found_sbc->networkInfo->zeroconf_domain);
+ found_sbc->networkInfo->zeroconf_domain = sbc->networkInfo->zeroconf_domain;
+ sbc->networkInfo->zeroconf_domain = NULL;
+ }
+ CPhidgetSBC_free(sbc);
+ goto dontadd;
+ }
+ }
+
+ //now add it
+ CList_addToList((CListHandle *)&zeroconfSBCs, sbc, CPhidgetSBC_areEqual);
+
+ //send out events
+ for (trav=activeSBCManagers; trav; trav = trav->next)
+ {
+ if (trav->sbcm->fptrAttachChange && trav->sbcm->state == PHIDGETMANAGER_ACTIVE)
+ trav->sbcm->fptrAttachChange((CPhidgetSBCHandle)sbc, trav->sbcm->fptrAttachChangeptr);
+
+ }
+ dontadd:
+
+ CThread_mutex_unlock(&activeSBCManagersLock);
+ CThread_mutex_unlock(&zeroconfSBCsLock);
+ }
+ else
+ LOG(PHIDGET_LOG_ERROR, "DNSServiceQueryRecordPtr returned error: %d\n", error);
+ }
+ else
+ {
+
+ LOG(PHIDGET_LOG_INFO, "DNSServiceBrowse_sbc_CallBack (Remove): %s",name);
+ CThread_mutex_lock(&zeroconfSBCsLock);
+ CThread_mutex_lock(&activeSBCManagersLock);
+
+ //make sure zeroconf_ref is not pending
+ if(sbc->networkInfo)
+ {
+ CThread_mutex_lock(&sbc->networkInfo->zeroconf_ref_lock);
+ if(sbc->networkInfo->zeroconf_ref)
+ {
+ DNSServiceRefDeallocatePtr((DNSServiceRef)sbc->networkInfo->zeroconf_ref);
+ sbc->networkInfo->zeroconf_ref = NULL;
+ }
+ CThread_mutex_unlock(&sbc->networkInfo->zeroconf_ref_lock);
+ }
+
+ if(CList_findInList((CListHandle)zeroconfSBCs, sbc, CPhidgetSBC_areEqual, (void **)&found_sbc) == EPHIDGET_OK)
+ {
+ CList_removeFromList((CListHandle *)&zeroconfSBCs, found_sbc, CPhidgetSBC_areEqual, PFALSE, NULL);
+ //managers
+ for (trav=activeSBCManagers; trav; trav = trav->next)
+ {
+ if (trav->sbcm->fptrDetachChange && trav->sbcm->state == PHIDGETMANAGER_ACTIVE)
+ trav->sbcm->fptrDetachChange((CPhidgetSBCHandle)found_sbc, trav->sbcm->fptrDetachChangeptr);
+ }
+ CPhidgetSBC_free(found_sbc);
+ }
+
+ CThread_mutex_unlock(&activeSBCManagersLock);
+ CThread_mutex_unlock(&zeroconfSBCsLock);
+
+ CPhidgetSBC_free(sbc);
+ }
+ }
+}
+
+void DNSServiceBrowse_ws_CallBack(DNSServiceRef service,
+ DNSServiceFlags flags,
+ uint32_t interfaceIndex,
+ DNSServiceErrorType errorCode,
+ const char * name,
+ const char * type,
+ const char * domain,
+ void * context)
+{
+ if (errorCode != kDNSServiceErr_NoError)
+ LOG(PHIDGET_LOG_ERROR, "DNSServiceBrowse_ws_CallBack returned error: %d\n", errorCode);
+ else
+ {
+ char fullname[kDNSServiceMaxDomainName];
+
+ CPhidgetRemoteHandle networkInfo;
+ if((CPhidgetRemote_create(&networkInfo))) return;
+
+ networkInfo->zeroconf_name = strdup(name);
+ networkInfo->zeroconf_server_id = strdup(name);
+ networkInfo->zeroconf_type = strdup(type);
+ networkInfo->zeroconf_domain = strdup(domain);
+ networkInfo->zeroconf_interface = interfaceIndex;
+
+ DNSServiceConstructFullNamePtr(fullname, name, type, domain);
+
+ LOG(PHIDGET_LOG_INFO, "DNSServiceBrowse_ws_CallBack: %s (%s, %s, %d)",name,type,domain,interfaceIndex);
+
+ CThread_mutex_lock(&zeroconfServersLock);
+ if(flags & kDNSServiceFlagsAdd)
+ {
+ if(CList_addToList((CListHandle *)&zeroconfServers, networkInfo, CPhidgetRemote_areEqual) != EPHIDGET_OK)
+ CPhidgetRemote_free(networkInfo);
+ }
+ else
+ {
+ CList_removeFromList((CListHandle *)&zeroconfServers, networkInfo, CPhidgetRemote_areEqual, TRUE, CPhidgetRemote_free);
+ }
+ CThread_mutex_unlock(&zeroconfServersLock);
+ }
+}
+
+int cancelPendingZeroconfLookups(CPhidgetRemoteHandle networkInfo)
+{
+ if(networkInfo->zeroconf_ref != NULL)
+ {
+ DNSServiceRefDeallocatePtr((DNSServiceRef)networkInfo->zeroconf_ref);
+ networkInfo->zeroconf_ref = NULL;
+ }
+ return EPHIDGET_OK;
+}
+
+
+void DNSServiceQueryRecord_CallBack
+(
+ DNSServiceRef DNSServiceRef,
+ DNSServiceFlags flags,
+ uint32_t interfaceIndex,
+ DNSServiceErrorType errorCode,
+ const char *fullname,
+ uint16_t rrtype,
+ uint16_t rrclass,
+ uint16_t rdlen,
+ const void *rdata,
+ uint32_t ttl,
+ void *context
+ )
+{
+
+ CPhidgetRemoteHandle networkInfo = (CPhidgetRemoteHandle)context;
+
+ if (errorCode != kDNSServiceErr_NoError)
+ {
+ LOG(PHIDGET_LOG_ERROR, "DNSServiceQueryRecord_CallBack returned error: %d\n", errorCode);
+ networkInfo->zeroconf_ipaddr = NULL;
+ }
+ else if(networkInfo->zeroconf_ipaddr == NULL)
+ {
+ if(rrtype == kDNSServiceType_A && rdlen == 4)
+ {
+ struct in_addr ip;
+ memcpy(&ip, rdata, 4);
+
+ networkInfo->zeroconf_ipaddr = strdup(inet_ntoa(ip));
+ }
+ //NOTE: Windows doesn't have inet_ntop
+ /*
+ else if(rrtype == kDNSServiceType_AAAA && rdlen == 16)
+ {
+ struct in6_addr ip;
+ memcpy(&ip, rdata, 16);
+
+ if((networkInfo->zeroconf_ipaddr = malloc(200)) != NULL)
+ {
+ networkInfo->zeroconf_ipaddr = strdup(inet_ntop(AF_INET6, &ip, networkInfo->zeroconf_ipaddr, 200));
+ }
+ }
+ */
+
+ LOG(PHIDGET_LOG_INFO, "DNSServiceQueryRecord_CallBack: %s (%s %d)",fullname, networkInfo->zeroconf_ipaddr, interfaceIndex);
+ }
+ else
+ LOG(PHIDGET_LOG_INFO, "DNSServiceQueryRecord_CallBack (extra, not used): %s (%d)",fullname, interfaceIndex);
+}
+
+int getZeroconfIPAddr(CPhidgetRemoteHandle networkInfo)
+{
+ DNSServiceErrorType error;
+
+ LOG(PHIDGET_LOG_VERBOSE, "Resolving IP Address for: %s, %s, %s, %s, %d",
+ networkInfo->zeroconf_name, //name
+ networkInfo->zeroconf_type, // service type
+ networkInfo->zeroconf_domain, //domain
+ networkInfo->zeroconf_host,
+ networkInfo->zeroconf_interface);
+
+ //already a lookup pending? cancel it and start a new one...
+ CThread_mutex_lock(&networkInfo->zeroconf_ref_lock);
+ if(networkInfo->zeroconf_ref != NULL)
+ {
+ DNSServiceRefDeallocatePtr((DNSServiceRef)networkInfo->zeroconf_ref);
+ networkInfo->zeroconf_ref = NULL;
+ }
+
+ free(networkInfo->zeroconf_ipaddr);
+ networkInfo->zeroconf_ipaddr = NULL;
+
+ error = DNSServiceQueryRecordPtr((DNSServiceRef *)&networkInfo->zeroconf_ref,
+ 0, // no flags
+ networkInfo->zeroconf_interface,
+ networkInfo->zeroconf_host, //hostname
+ kDNSServiceType_A, // IPv4 address for now..
+ kDNSServiceClass_IN, // service class
+ DNSServiceQueryRecord_CallBack,
+ networkInfo);
+ if (error != kDNSServiceErr_NoError)
+ {
+ LOG(PHIDGET_LOG_ERROR, "DNSServiceQueryRecordPtr returned error: %d\n", error);
+ networkInfo->zeroconf_ref = NULL;
+ CThread_mutex_unlock(&networkInfo->zeroconf_ref_lock);
+ return EPHIDGET_NETWORK;
+ }
+ else
+ {
+ DNSServiceProcessResultPtr((DNSServiceRef)networkInfo->zeroconf_ref);
+ DNSServiceRefDeallocatePtr((DNSServiceRef)networkInfo->zeroconf_ref);
+ networkInfo->zeroconf_ref = NULL;
+ CThread_mutex_unlock(&networkInfo->zeroconf_ref_lock);
+ LOG(PHIDGET_LOG_VERBOSE, "Successfull lookup: %s",networkInfo->zeroconf_host);
+ return EPHIDGET_OK;
+ }
+
+}
+
+void DNSServiceResolve_CallBack(
+ DNSServiceRef sdRef,
+ DNSServiceFlags flags,
+ uint32_t interfaceIndex,
+ DNSServiceErrorType errorCode,
+ const char *fullname,
+ const char *hosttarget,
+ uint16_t port,
+ uint16_t txtLen,
+ const unsigned char *txtRecord,
+ void *context)
+{
+ CPhidgetRemoteHandle networkInfo = (CPhidgetRemoteHandle)context;
+
+
+ if (errorCode != kDNSServiceErr_NoError)
+ {
+ LOG(PHIDGET_LOG_ERROR, "DNSServiceResolve_CallBack returned error: %d\n", errorCode);
+ networkInfo->zeroconf_host = NULL;
+ networkInfo->zeroconf_port = NULL;
+ }
+ else if(!networkInfo->zeroconf_host && !networkInfo->zeroconf_port)
+ {
+
+ LOG(PHIDGET_LOG_INFO, "DNSServiceResolve_CallBack: %s (%s:%d %d)",fullname, hosttarget, ntohs(port), interfaceIndex);
+
+ networkInfo->zeroconf_host = strdup(hosttarget);
+ networkInfo->zeroconf_port = malloc(10);
+ snprintf(networkInfo->zeroconf_port, 10, "%d", ntohs(port));
+ }
+ else
+ LOG(PHIDGET_LOG_INFO, "DNSServiceResolve_CallBack (extra, not used): %s (%s:%d %d)",fullname, hosttarget, ntohs(port), interfaceIndex);
+}
+
+int getZeroconfHostPort(CPhidgetRemoteHandle networkInfo)
+{
+ DNSServiceErrorType error;
+
+ LOG(PHIDGET_LOG_VERBOSE, "Resolving host:port for: %s, %s, %s",
+ networkInfo->zeroconf_name, //name
+ networkInfo->zeroconf_type, // service type
+ networkInfo->zeroconf_domain //domain
+ );
+
+ //already a lookup pending? cancel it and start a new one...
+ CThread_mutex_lock(&networkInfo->zeroconf_ref_lock);
+ if(networkInfo->zeroconf_ref != NULL)
+ {
+ DNSServiceRefDeallocatePtr((DNSServiceRef)networkInfo->zeroconf_ref);
+ networkInfo->zeroconf_ref = NULL;
+ }
+
+ free(networkInfo->zeroconf_host);
+ networkInfo->zeroconf_host = NULL;
+ free(networkInfo->zeroconf_port);
+ networkInfo->zeroconf_port = NULL;
+
+ error = DNSServiceResolvePtr((DNSServiceRef *)&networkInfo->zeroconf_ref,
+ 0, // no flags
+ 0, // all interfaces
+ //networkInfo->zeroconf_interface, // interface this service was discovered on
+ networkInfo->zeroconf_name, //name
+ networkInfo->zeroconf_type, // service type
+ networkInfo->zeroconf_domain, //domain
+ DNSServiceResolve_CallBack,
+ networkInfo); // no context
+ if (error != kDNSServiceErr_NoError)
+ {
+ LOG(PHIDGET_LOG_ERROR, "getZeroconfHostPort returned error: %d\n", error);
+ networkInfo->zeroconf_ref = NULL;
+ CThread_mutex_unlock(&networkInfo->zeroconf_ref_lock);
+ return EPHIDGET_NETWORK;
+ }
+ else
+ {
+ DNSServiceProcessResultPtr((DNSServiceRef)networkInfo->zeroconf_ref);
+ DNSServiceRefDeallocatePtr((DNSServiceRef)networkInfo->zeroconf_ref);
+ networkInfo->zeroconf_ref = NULL;
+ LOG(PHIDGET_LOG_VERBOSE, "Successfull host:port lookup: %s:%s",networkInfo->zeroconf_host,networkInfo->zeroconf_port);
+ CThread_mutex_unlock(&networkInfo->zeroconf_ref_lock);
+ //Don't bother - we aren't going to use it anyways
+ //This is just another way to lookup the IP address - from the DNS record
+ //getZeroconfIPAddr(networkInfo);
+ return EPHIDGET_OK;
+ }
+}
+
+int refreshZeroconf(CPhidgetRemoteHandle networkInfo, DNSServiceQueryRecordReply callBack, void *userPtr)
+{
+ DNSServiceErrorType error;
+ char fullname[kDNSServiceMaxDomainName];
+
+ LOG(PHIDGET_LOG_VERBOSE, "Refreshing zeroconf on: 0x%x",networkInfo);
+
+ //already a lookup pending? cancel it and start a new one...
+ CThread_mutex_lock(&networkInfo->zeroconf_ref_lock);
+
+ DNSServiceConstructFullNamePtr(fullname, networkInfo->zeroconf_name, networkInfo->zeroconf_type, networkInfo->zeroconf_domain);
+
+ if(networkInfo->zeroconf_ref != NULL)
+ {
+ DNSServiceRefDeallocatePtr((DNSServiceRef)networkInfo->zeroconf_ref);
+ networkInfo->zeroconf_ref = NULL;
+ }
+ error = DNSServiceQueryRecordPtr((DNSServiceRef *)&networkInfo->zeroconf_ref,
+ 0, // no flags
+ networkInfo->zeroconf_interface,
+ fullname, //name
+ kDNSServiceType_TXT, // service type
+ kDNSServiceClass_IN, // service class
+ callBack,
+ userPtr);
+ if (error != kDNSServiceErr_NoError)
+ {
+ LOG(PHIDGET_LOG_ERROR, "DNSServiceQueryRecordPtr returned error: %d\n", error);
+ networkInfo->zeroconf_ref = NULL;
+ CThread_mutex_unlock(&networkInfo->zeroconf_ref_lock);
+ return EPHIDGET_NETWORK;
+ }
+ else
+ {
+ DNSServiceProcessResultPtr((DNSServiceRef)networkInfo->zeroconf_ref);
+ DNSServiceRefDeallocatePtr((DNSServiceRef)networkInfo->zeroconf_ref);
+ networkInfo->zeroconf_ref = NULL;
+ CThread_mutex_unlock(&networkInfo->zeroconf_ref_lock);
+ LOG(PHIDGET_LOG_VERBOSE, "Successfull refresh.");
+ return EPHIDGET_OK;
+ }
+}
+
+int refreshZeroconfSBC(CPhidgetSBCHandle sbc)
+{
+ return refreshZeroconf(sbc->networkInfo, DNSServiceQueryRecord_SBC_CallBack, sbc);
+}
+
+int refreshZeroconfPhidget(CPhidgetHandle phid)
+{
+ return refreshZeroconf(phid->networkInfo, DNSServiceQueryRecord_Phidget_CallBack, phid);
+}
+
+int InitializeZeroconf()
+{
+ DNSServiceErrorType error;
+ CThread_mutex_lock(&zeroconfInitLock);
+ if(!Dns_sdInitialized)
+ {
+#ifdef ZEROCONF_RUNTIME_LINKING
+
+#ifdef _WINDOWS
+ if(!(dllHandle = LoadLibrary(L"dnssd.dll")))
+ {
+ DWORD error = GetLastError();
+ switch(error)
+ {
+ case ERROR_MOD_NOT_FOUND:
+ LOG(PHIDGET_LOG_DEBUG,"LoadLibrary failed - module could not be found");
+ break;
+ default:
+ LOG(PHIDGET_LOG_DEBUG,"LoadLibrary failed with error code: %d", error);
+ }
+ CThread_mutex_unlock(&zeroconfInitLock);
+ return EPHIDGET_UNEXPECTED;
+ }
+
+ // If the handle is valid, try to get the function address.
+ if (NULL != dllHandle)
+ {
+ //Get pointers to our functions using GetProcAddress:
+#ifdef WINCE
+ DNSServiceRegisterPtr = (DNSServiceRegisterType)GetProcAddress(dllHandle, L"DNSServiceRegister");
+ DNSServiceProcessResultPtr = (DNSServiceProcessResultType)GetProcAddress(dllHandle, L"DNSServiceProcessResult");
+ DNSServiceRefDeallocatePtr = (DNSServiceRefDeallocateType)GetProcAddress(dllHandle, L"DNSServiceRefDeallocate");
+ DNSServiceAddRecordPtr = (DNSServiceAddRecordType)GetProcAddress(dllHandle, L"DNSServiceAddRecord");
+ DNSServiceUpdateRecordPtr = (DNSServiceUpdateRecordType)GetProcAddress(dllHandle, L"DNSServiceUpdateRecord");
+ DNSServiceRemoveRecordPtr = (DNSServiceRemoveRecordType)GetProcAddress(dllHandle, L"DNSServiceRemoveRecord");
+ DNSServiceBrowsePtr = (DNSServiceBrowseType)GetProcAddress(dllHandle, L"DNSServiceBrowse");
+ DNSServiceResolvePtr = (DNSServiceResolveType)GetProcAddress(dllHandle, L"DNSServiceResolve");
+ DNSServiceQueryRecordPtr = (DNSServiceQueryRecordType)GetProcAddress(dllHandle, L"DNSServiceQueryRecord");
+ DNSServiceConstructFullNamePtr = (DNSServiceConstructFullNameType)GetProcAddress(dllHandle, L"DNSServiceConstructFullName");
+ DNSServiceRefSockFDPtr = (DNSServiceRefSockFDType)GetProcAddress(dllHandle, L"DNSServiceRefSockFD");
+#else
+ DNSServiceRegisterPtr = (DNSServiceRegisterType)GetProcAddress(dllHandle, "DNSServiceRegister");
+ DNSServiceProcessResultPtr = (DNSServiceProcessResultType)GetProcAddress(dllHandle, "DNSServiceProcessResult");
+ DNSServiceRefDeallocatePtr = (DNSServiceRefDeallocateType)GetProcAddress(dllHandle, "DNSServiceRefDeallocate");
+ DNSServiceAddRecordPtr = (DNSServiceAddRecordType)GetProcAddress(dllHandle, "DNSServiceAddRecord");
+ DNSServiceUpdateRecordPtr = (DNSServiceUpdateRecordType)GetProcAddress(dllHandle, "DNSServiceUpdateRecord");
+ DNSServiceRemoveRecordPtr = (DNSServiceRemoveRecordType)GetProcAddress(dllHandle, "DNSServiceRemoveRecord");
+ DNSServiceBrowsePtr = (DNSServiceBrowseType)GetProcAddress(dllHandle, "DNSServiceBrowse");
+ DNSServiceResolvePtr = (DNSServiceResolveType)GetProcAddress(dllHandle, "DNSServiceResolve");
+ DNSServiceQueryRecordPtr = (DNSServiceQueryRecordType)GetProcAddress(dllHandle, "DNSServiceQueryRecord");
+ DNSServiceConstructFullNamePtr = (DNSServiceConstructFullNameType)GetProcAddress(dllHandle, "DNSServiceConstructFullName");
+ DNSServiceRefSockFDPtr = (DNSServiceRefSockFDType)GetProcAddress(dllHandle, "DNSServiceRefSockFD");
+#endif
+
+ Dns_sdInitialized = (
+ NULL != DNSServiceRegisterPtr &&
+ NULL != DNSServiceProcessResultPtr &&
+ NULL != DNSServiceRefDeallocatePtr &&
+ NULL != DNSServiceAddRecordPtr &&
+ NULL != DNSServiceUpdateRecordPtr &&
+ NULL != DNSServiceRemoveRecordPtr &&
+ NULL != DNSServiceQueryRecordPtr &&
+ NULL != DNSServiceConstructFullNamePtr &&
+ NULL != DNSServiceRefSockFDPtr);
+ }
+
+ if(!Dns_sdInitialized)
+ {
+ LOG(PHIDGET_LOG_DEBUG,"InitializeZeroconf failed somehow...");
+ CThread_mutex_unlock(&zeroconfInitLock);
+ return EPHIDGET_UNSUPPORTED;
+ }
+
+#elif _LINUX
+ libHandle = dlopen("libdns_sd.so",RTLD_LAZY);
+ if(!libHandle)
+ {
+ LOG(PHIDGET_LOG_WARNING, "dlopen failed with error: %s", dlerror());
+ LOG(PHIDGET_LOG_WARNING, "Assuming that zeroconf is not supported on this machine.");
+ CThread_mutex_unlock(&zeroconfInitLock);
+ return EPHIDGET_UNSUPPORTED;
+ }
+
+ //Get pointers to our functions using dlsym:
+ if(!(DNSServiceRegisterPtr = (DNSServiceRegisterType)dlsym(libHandle, "DNSServiceRegister"))) goto dlsym_err;
+ if(!(DNSServiceProcessResultPtr = (DNSServiceProcessResultType)dlsym(libHandle, "DNSServiceProcessResult"))) goto dlsym_err;
+ if(!(DNSServiceRefDeallocatePtr = (DNSServiceRefDeallocateType)dlsym(libHandle, "DNSServiceRefDeallocate"))) goto dlsym_err;
+ if(!(DNSServiceAddRecordPtr = (DNSServiceAddRecordType)dlsym(libHandle, "DNSServiceAddRecord"))) goto dlsym_err;
+ if(!(DNSServiceUpdateRecordPtr = (DNSServiceUpdateRecordType)dlsym(libHandle, "DNSServiceUpdateRecord"))) goto dlsym_err;
+ if(!(DNSServiceRemoveRecordPtr = (DNSServiceRemoveRecordType)dlsym(libHandle, "DNSServiceRemoveRecord"))) goto dlsym_err;
+ if(!(DNSServiceBrowsePtr = (DNSServiceBrowseType)dlsym(libHandle, "DNSServiceBrowse"))) goto dlsym_err;
+ if(!(DNSServiceResolvePtr = (DNSServiceResolveType)dlsym(libHandle, "DNSServiceResolve"))) goto dlsym_err;
+ if(!(DNSServiceQueryRecordPtr = (DNSServiceQueryRecordType)dlsym(libHandle, "DNSServiceQueryRecord"))) goto dlsym_err;
+ if(!(DNSServiceConstructFullNamePtr = (DNSServiceConstructFullNameType)dlsym(libHandle, "DNSServiceConstructFullName"))) goto dlsym_err;
+ if(!(DNSServiceRefSockFDPtr = (DNSServiceRefSockFDType)dlsym(libHandle, "DNSServiceRefSockFD"))) goto dlsym_err;
+
+ goto dlsym_good;
+
+ dlsym_err:
+ LOG(PHIDGET_LOG_WARNING, "dlsym failed with error: %s", dlerror());
+ LOG(PHIDGET_LOG_WARNING, "Assuming that zeroconf is not supported on this machine.");
+ CThread_mutex_unlock(&zeroconfInitLock);
+ return EPHIDGET_UNSUPPORTED;
+
+ dlsym_good:
+ Dns_sdInitialized = TRUE;
+#endif
+
+#else
+ Dns_sdInitialized = TRUE;
+#endif
+ LOG(PHIDGET_LOG_DEBUG,"InitializeZeroconf - System supports zeroconf.");
+ }
+ if(!Dns_sdBrowsing)
+ {
+ error = DNSServiceBrowsePtr(&zeroconf_browse_ws_ref,
+ 0, // no flags
+ 0, // all network interfaces
+ "_phidget_ws._tcp", // service type
+ "", // default domains
+ DNSServiceBrowse_ws_CallBack, // call back function
+ NULL); // no context
+ if (error != kDNSServiceErr_NoError)
+ {
+ LOG(PHIDGET_LOG_ERROR,"DNSServiceBrowse on _phidget_ws._tcp failed: %d", error);
+ CThread_mutex_unlock(&zeroconfInitLock);
+ return EPHIDGET_TRYAGAIN;
+ }
+
+ error = DNSServiceBrowsePtr(&zeroconf_browse_sbc_ref,
+ 0, // no flags
+ 0, // all network interfaces
+ "_phidget_sbc._tcp", // service type
+ "", // default domains
+ DNSServiceBrowse_sbc_CallBack, // call back function
+ NULL); // no context
+ if (error != kDNSServiceErr_NoError)
+ {
+ LOG(PHIDGET_LOG_ERROR,"DNSServiceBrowse on _phidget_sbc._tcp failed: %d", error);
+ CThread_mutex_unlock(&zeroconfInitLock);
+ return EPHIDGET_TRYAGAIN;
+ }
+
+ error = DNSServiceBrowsePtr(&zeroconf_browse_phidget_ref,
+ 0, // no flags
+ 0, // all network interfaces
+ "_phidget._tcp", // service type
+ "", // default domains
+ DNSServiceBrowse_Phidget_CallBack, // call back function
+ NULL); // no context
+ if (error != kDNSServiceErr_NoError)
+ {
+ LOG(PHIDGET_LOG_ERROR,"DNSServiceBrowse on _phidget._tcp failed: %d", error);
+ CThread_mutex_unlock(&zeroconfInitLock);
+ return EPHIDGET_TRYAGAIN;
+ }
+
+ stopBrowsing = FALSE;
+ pthread_create(&dns_thread, NULL, (void *(*)(void *))dns_callback_thread,NULL);
+
+ Dns_sdBrowsing = PTRUE;
+ LOG(PHIDGET_LOG_DEBUG,"InitializeZeroconf - Zeroconf browsing active.");
+ }
+ CThread_mutex_unlock(&zeroconfInitLock);
+ return EPHIDGET_OK;
+}
+
+int UninitializeZeroconf()
+{
+ void *status;
+ CThread_mutex_lock(&zeroconfInitLock);
+ if(Dns_sdBrowsing)
+ {
+ stopBrowsing = TRUE;
+ if(dns_thread)
+ {
+ pthread_join(dns_thread, &status);
+ dns_thread = NULL;
+ }
+
+ if(zeroconf_browse_ws_ref)
+ {
+ DNSServiceRefDeallocatePtr(zeroconf_browse_ws_ref);
+ zeroconf_browse_ws_ref = NULL;
+ }
+ if(zeroconf_browse_sbc_ref)
+ {
+ DNSServiceRefDeallocatePtr(zeroconf_browse_sbc_ref);
+ zeroconf_browse_sbc_ref = NULL;
+ }
+ if(zeroconf_browse_phidget_ref)
+ {
+ DNSServiceRefDeallocatePtr(zeroconf_browse_phidget_ref);
+ zeroconf_browse_phidget_ref = NULL;
+ }
+
+ CThread_mutex_lock(&zeroconfPhidgetsLock);
+ CList_emptyList((CListHandle *)&zeroconfPhidgets, FALSE, NULL);
+ CThread_mutex_unlock(&zeroconfPhidgetsLock);
+
+ CThread_mutex_lock(&zeroconfSBCsLock);
+ CList_emptyList((CListHandle *)&zeroconfSBCs, FALSE, NULL);
+ CThread_mutex_unlock(&zeroconfSBCsLock);
+
+ CThread_mutex_lock(&zeroconfServersLock);
+ CList_emptyList((CListHandle *)&zeroconfServers, FALSE, NULL);
+ CThread_mutex_unlock(&zeroconfServersLock);
+
+ Dns_sdBrowsing = FALSE;
+ }
+ CThread_mutex_unlock(&zeroconfInitLock);
+ return EPHIDGET_OK;
+}
+
+
diff --git a/zeroconf.h b/zeroconf.h
new file mode 100644
index 0000000..d8cd4c5
--- /dev/null
+++ b/zeroconf.h
@@ -0,0 +1,19 @@
+#ifndef _ZEROCONF_H_
+#define _ZEROCONF_H_
+
+int getZeroconfHostPort(CPhidgetRemoteHandle networkInfo);
+int cancelPendingZeroconfLookups(CPhidgetRemoteHandle networkInfo);
+int refreshZeroconfSBC(CPhidgetSBCHandle sbc);
+int refreshZeroconfPhidget(CPhidgetHandle phid);
+int InitializeZeroconf();
+int UninitializeZeroconf();
+
+/* Internal version of .local lookups for SBC */
+#ifdef ZEROCONF_LOOKUP
+struct hostent *
+mdns_gethostbyname (const char *name);
+struct hostent *
+mdns_gethostbyname2 (const char *name, int af);
+#endif
+
+#endif
diff --git a/zeroconf_lookup.c b/zeroconf_lookup.c
new file mode 100644
index 0000000..0493284
--- /dev/null
+++ b/zeroconf_lookup.c
@@ -0,0 +1,1713 @@
+#include "stdafx.h"
+#include "csocket.h"
+#include "csocketevents.h"
+#include "cphidgetlist.h"
+#include "cphidgetmanager.h"
+#include "cphidgetdictionary.h"
+#include "cphidgetsbc.h"
+#include "zeroconf.h"
+#include "dns_sd.h"
+
+/*
+ This is all taken from mDNSResponderPosix's nss_mdns code
+ so we can lookup .local name manually under uClibc (PhidgetSBC)
+*/
+
+#ifdef ZEROCONF_LOOKUP
+
+#ifndef AF_LOCAL
+#define AF_LOCAL AF_UNIX
+#endif
+
+/* runtime linking of dns_sd functions */
+#ifdef ZEROCONF_RUNTIME_LINKING
+ typedef void (DNSSD_API * DNSServiceRefDeallocateType) (DNSServiceRef);
+ typedef DNSServiceErrorType (DNSSD_API * DNSServiceQueryRecordType)
+ (DNSServiceRef *, DNSServiceFlags, uint32_t, const char *,
+ uint16_t, uint16_t, DNSServiceQueryRecordReply, void *context);
+ typedef DNSServiceErrorType (DNSSD_API * DNSServiceProcessResultType) (DNSServiceRef);
+ typedef int (DNSSD_API * DNSServiceRefSockFDType) (DNSServiceRef sdRef);
+
+ extern DNSServiceRefDeallocateType DNSServiceRefDeallocatePtr;
+ extern DNSServiceQueryRecordType DNSServiceQueryRecordPtr;
+ extern DNSServiceProcessResultType DNSServiceProcessResultPtr;
+ extern DNSServiceRefSockFDType DNSServiceRefSockFDPtr;
+#else
+ #define DNSServiceRefDeallocatePtr DNSServiceRefDeallocate
+ #define DNSServiceQueryRecordPtr DNSServiceQueryRecord
+ #define DNSServiceProcessResultPtr DNSServiceProcessResult
+ #define DNSServiceRefSockFDPtr DNSServiceRefSockFD
+#endif
+
+
+//----------
+// Structs
+//----------
+
+typedef struct
+{
+ int value;
+ const char * name;
+ const char * comment;
+} table_entry_t;
+
+// Linked list of domains
+typedef struct domain_entry
+{
+ char * domain;
+ struct domain_entry * next;
+} domain_entry_t;
+
+// Config
+typedef struct
+{
+ domain_entry_t * domains;
+} config_t;
+
+
+//----------
+// Constants, Defines
+//----------
+
+#define k_hostname_maxlen 255
+#define k_aliases_max 15
+#define k_addrs_max 15
+// Maximum length of a single DNS label
+#define DNS_LABEL_MAXLEN 63
+// Maximum length of a DNS name
+#define DNS_NAME_MAXLEN 255
+#define CONF_LINE_SIZE 1024
+
+// Label entries longer than this are actually pointers.
+static const int k_label_maxlen = DNS_LABEL_MAXLEN;
+// 0 seconds, 500 milliseconds
+static const struct timeval k_select_time = { 0, 500000 };
+static const char * k_local_suffix = "local";
+static const char k_dns_separator = '.';
+static const table_entry_t k_table_af [] =
+ {
+ { AF_UNSPEC, NULL, NULL },
+ { AF_LOCAL, "LOCAL", NULL },
+ { AF_UNIX, "UNIX", NULL },
+ { AF_INET, "INET", NULL },
+ { AF_INET6, "INET6", NULL }
+ };
+static const int k_table_af_size = sizeof (k_table_af) / sizeof (* k_table_af);
+static const char * k_table_ns_class [] =
+ {
+ NULL,
+ "IN"
+ };
+static const int k_table_ns_class_size = sizeof (k_table_ns_class) / sizeof (* k_table_ns_class);
+static const char * k_table_ns_type [] =
+ {
+ NULL,
+ "A",
+ "NS",
+ "MD",
+ "MF",
+ "CNAME",
+ "SOA",
+ "MB",
+ "MG",
+ "MR",
+ "NULL",
+ "WKS",
+ "PTR",
+ "HINFO",
+ "MINFO",
+ "MX",
+ "TXT",
+ "RP",
+ "AFSDB",
+ "X25",
+ "ISDN",
+ "RT",
+ "NSAP",
+ NULL,
+ "SIG",
+ "KEY",
+ "PX",
+ "GPOS",
+ "AAAA",
+ "LOC",
+ "NXT",
+ "EID",
+ "NIMLOC",
+ "SRV",
+ "ATMA",
+ "NAPTR",
+ "KX",
+ "CERT",
+ "A6",
+ "DNAME",
+ "SINK",
+ "OPT"
+ };
+static const int k_table_ns_type_size = sizeof (k_table_ns_type) / sizeof (* k_table_ns_type);
+
+const char * k_conf_file = "/etc/nss_mdns.conf";
+const char k_comment_char = '#';
+const char * k_keyword_domain = "domain";
+const char * k_default_domains [] =
+ {
+ "local",
+ "254.169.in-addr.arpa",
+ "8.e.f.ip6.int",
+ "8.e.f.ip6.arpa",
+ "9.e.f.ip6.int",
+ "9.e.f.ip6.arpa",
+ "a.e.f.ip6.int",
+ "a.e.f.ip6.arpa",
+ "b.e.f.ip6.int",
+ "b.e.f.ip6.arpa",
+ // Always null terminated
+ NULL
+ };
+const config_t k_empty_config =
+ {
+ NULL
+ };
+
+//----------
+// Enums, Structs, Typedefs
+//----------
+
+/* Possible results of lookup using a nss_* function. */
+enum nss_status
+{
+ NSS_STATUS_TRYAGAIN = -2,
+ NSS_STATUS_UNAVAIL,
+ NSS_STATUS_NOTFOUND,
+ NSS_STATUS_SUCCESS,
+ NSS_STATUS_RETURN
+};
+
+enum
+{
+ // Format is broken. Usually because we ran out of data
+ // (according to rdata) before the labels said we should.
+ DNS_RDATA_TO_NAME_BAD_FORMAT = -1,
+ // The converted rdata is longer than the name buffer.
+ DNS_RDATA_TO_NAME_TOO_LONG = -2,
+ // The rdata contains a pointer.
+ DNS_RDATA_TO_NAME_PTR = -3,
+};
+
+enum
+{
+ CMP_DNS_SUFFIX_SUCCESS = 1,
+ CMP_DNS_SUFFIX_FAILURE = 0,
+ CMP_DNS_SUFFIX_BAD_NAME = 1,
+ CMP_DNS_SUFFIX_BAD_DOMAIN = -2
+};
+
+typedef enum nss_status nss_status;
+typedef struct hostent hostent;
+typedef int ns_type_t;
+typedef int ns_class_t;
+typedef int errcode_t;
+
+typedef void
+mdns_lookup_callback_t
+(
+ DNSServiceRef sdref,
+ DNSServiceFlags flags,
+ uint32_t interface_index,
+ DNSServiceErrorType error_code,
+ const char *fullname,
+ uint16_t rrtype,
+ uint16_t rrclass,
+ uint16_t rdlen,
+ const void *rdata,
+ uint32_t ttl,
+ void *context
+);
+
+typedef struct buf_header
+{
+ char hostname [k_hostname_maxlen + 1];
+ char * aliases [k_aliases_max + 1];
+ char * addrs [k_addrs_max + 1];
+} buf_header_t;
+
+typedef struct result_map
+{
+ int done;
+ nss_status status;
+ hostent * hostent;
+ buf_header_t * header;
+ int aliases_count;
+ int addrs_count;
+ char * buffer;
+ // Index for addresses - grow from low end
+ // Index points to first empty space
+ int addr_idx;
+ // Index for aliases - grow from high end
+ // Index points to lowest entry
+ int alias_idx;
+ int r_errno;
+ int r_h_errno;
+} result_map_t;
+
+// Context - tracks position in config file, used for error reporting
+typedef struct
+{
+ const char * filename;
+ int linenum;
+} config_file_context_t;
+
+
+//----------
+// Globals
+//----------
+
+static config_t * g_config = NULL;
+
+pthread_mutex_t g_config_mutex =
+#ifdef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
+ PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
+#else
+ PTHREAD_MUTEX_INITIALIZER;
+#endif
+
+mdns_lookup_callback_t mdns_lookup_callback;
+
+
+//----------
+// Prototypes
+//----------
+
+static int
+callback_body_ptr (
+ const char * fullname,
+ result_map_t * result,
+ int rdlen,
+ const void * rdata
+);
+
+static nss_status
+handle_events (DNSServiceRef sdref, result_map_t * result, const char * str);
+
+static nss_status
+mdns_lookup_name (
+ const char * fullname,
+ int af,
+ result_map_t * result
+);
+
+const char *
+ns_class_to_str (ns_class_t in);
+const char *
+ns_type_to_str (ns_type_t in);
+ns_type_t
+af_to_rr (int af);
+
+int
+dns_rdata_to_name (const char * rdata, int rdlen, char * name, int name_len);
+int
+cmp_dns_suffix (const char * name, const char * domain);
+
+static char *
+add_hostname_or_alias (result_map_t * result, const char * data, int len);
+static char *
+add_hostname_len (result_map_t * result, const char * fullname, int len);
+static char *
+add_alias_to_buffer (result_map_t * result, const char * data, int len);
+static char *
+add_hostname_or_alias (result_map_t * result, const char * data, int len);
+static void *
+add_address_to_buffer (result_map_t * result, const void * data, int len);
+static errcode_t
+add_domain (config_t * conf, const char * domain);
+
+static nss_status
+set_err_success (result_map_t * result);
+static nss_status
+set_err_buf_too_small (result_map_t * result);
+static nss_status
+set_err_internal_resource_full (result_map_t * result);
+static nss_status
+set_err (result_map_t * result, nss_status status, int err, int herr);
+static nss_status
+set_err_bad_hostname (result_map_t * result);
+static nss_status
+set_err_notfound (result_map_t * result);
+static nss_status
+set_err_mdns_failed (result_map_t * result);
+static nss_status
+set_err_system (result_map_t * result);
+
+static const char *
+is_applicable_name (
+ result_map_t * result,
+ const char * name,
+ char * lookup_name
+);
+int
+islocal (const char * name);
+
+static int
+contains_domain_suffix (const config_t * conf, const char * addr);
+static char *
+contains_alias (result_map_t * result, const char * alias);
+static void *
+contains_address (result_map_t * result, const void * data, int len);
+static int
+contains_domain (const config_t * conf, const char * domain);
+
+static int
+init_result (
+ result_map_t * result,
+ hostent * result_buf,
+ char * buf,
+ size_t buflen
+);
+errcode_t
+init_config ();
+static errcode_t
+load_config (config_t * conf);
+static errcode_t
+process_config_line (
+ config_t * conf,
+ char * line,
+ config_file_context_t * context
+);
+static errcode_t
+default_config (config_t * conf);
+int
+config_is_mdns_suffix (const char * name);
+
+static char *
+get_next_word (char * input, char **next);
+
+
+//Functions
+/*
+ Get next word (whitespace separated) from input string.
+ A null character is written into the first whitespace character following
+ the word.
+
+ Parameters
+ input
+ Input string. This string is modified by get_next_word.
+ next
+ If non-NULL and the result is non-NULL, a pointer to the
+ character following the end of the word (after the null)
+ is written to 'next'.
+ If no word is found, the original value is unchanged.
+ If the word extended to the end of the string, 'next' points
+ to the trailling NULL.
+ It is safe to pass 'str' as 'input' and '&str' as 'next'.
+ Returns
+ Pointer to the first non-whitespace character (and thus word) found.
+ if no word is found, returns NULL.
+ */
+static char *
+get_next_word (char * input, char **next)
+{
+ char * curr = input;
+ char * result;
+
+ while (isspace (*curr))
+ {
+ curr ++;
+ }
+
+ if (*curr == 0)
+ {
+ return NULL;
+ }
+
+ result = curr;
+ while (*curr && ! isspace (*curr))
+ {
+ curr++;
+ }
+ if (*curr)
+ {
+ *curr = 0;
+ if (next)
+ {
+ *next = curr+1;
+ }
+ }
+ else
+ {
+ if (next)
+ {
+ *next = curr;
+ }
+ }
+
+ return result;
+}
+static errcode_t
+add_domain (config_t * conf, const char * domain)
+{
+ if (! contains_domain (conf, domain))
+ {
+ domain_entry_t * d =
+ (domain_entry_t *) malloc (sizeof (domain_entry_t));
+ if (! d)
+ {
+ LOG(PHIDGET_LOG_ERROR,
+ "mdns: Can't allocate memory in nss_mdns:init_config, %s:%d",
+ __FILE__, __LINE__
+ );
+ return ENOMEM;
+ }
+
+ d->domain = strdup (domain);
+ if (! d->domain)
+ {
+ LOG(PHIDGET_LOG_ERROR,
+ "mdns: Can't allocate memory in nss_mdns:init_config, %s:%d",
+ __FILE__, __LINE__
+ );
+ free (d);
+ return ENOMEM;
+ }
+ d->next = conf->domains;
+ conf->domains = d;
+ }
+
+ return 0;
+}
+
+
+static int
+contains_domain (const config_t * conf, const char * domain)
+{
+ const domain_entry_t * curr = conf->domains;
+
+ while (curr != NULL)
+ {
+ if (strcasecmp (curr->domain, domain) == 0)
+ {
+ return 1;
+ }
+
+ curr = curr->next;
+ }
+
+ return 0;
+}
+static errcode_t
+default_config (config_t * conf)
+{
+ int i;
+ for (i = 0; k_default_domains [i]; i++)
+ {
+ int errcode =
+ add_domain (conf, k_default_domains [i]);
+ if (errcode)
+ {
+ // Something has gone (badly) wrong - let's bail
+ return errcode;
+ }
+ }
+
+ return 0;
+}
+/*
+ Parse a line of the configuration file.
+ For each keyword recognised, perform appropriate handling.
+ If the keyword is not recognised, print a message to syslog
+ and continue.
+
+ Returns
+ 0 success, or recoverable config file error
+ non-zero serious system error, processing aborted
+ */
+static errcode_t
+process_config_line (
+ config_t * conf,
+ char * line,
+ config_file_context_t * context
+)
+{
+ char * curr = line;
+ char * word;
+
+ word = get_next_word (curr, &curr);
+ if (! word || word [0] == k_comment_char)
+ {
+ // Nothing interesting on this line
+ return 0;
+ }
+
+ if (strcmp (word, k_keyword_domain) == 0)
+ {
+ word = get_next_word (curr, &curr);
+ if (word)
+ {
+ int errcode = add_domain (conf, word);
+ if (errcode)
+ {
+ // something badly wrong, bail
+ return errcode;
+ }
+
+ if (get_next_word (curr, NULL))
+ {
+ LOG(PHIDGET_LOG_WARNING,
+ "%s, line %d: ignored extra text found after domain",
+ context->filename,
+ context->linenum
+ );
+ }
+ }
+ else
+ {
+ LOG(PHIDGET_LOG_WARNING,
+ "%s, line %d: no domain specified",
+ context->filename,
+ context->linenum
+ );
+ }
+ }
+ else
+ {
+ LOG(PHIDGET_LOG_WARNING,
+ "%s, line %d: unknown keyword %s - skipping",
+ context->filename,
+ context->linenum,
+ word
+ );
+ }
+
+ return 0;
+}
+
+int
+cmp_dns_suffix (const char * name, const char * domain)
+{
+ const char * nametail;
+ const char * domaintail;
+
+ // Idiot checks
+ if (*name == 0 || *name == k_dns_separator)
+ {
+ // Name can't be empty or start with separator
+ return CMP_DNS_SUFFIX_BAD_NAME;
+ }
+
+ if (*domain == 0)
+ {
+ return CMP_DNS_SUFFIX_SUCCESS;
+ // trivially true
+ }
+
+ if (*domain == k_dns_separator)
+ {
+ // drop leading separator from domain
+ domain++;
+ if (*domain == k_dns_separator)
+ {
+ return CMP_DNS_SUFFIX_BAD_DOMAIN;
+ }
+ }
+
+ // Find ends of strings
+ for (nametail = name; *nametail; nametail++)
+ ;
+ for (domaintail = domain; *domaintail; domaintail++)
+ ;
+
+ // Shuffle back to last real character, and drop any trailing '.'
+ // while we're at it.
+ nametail --;
+ if (*nametail == k_dns_separator)
+ {
+ nametail --;
+ if (*nametail == k_dns_separator)
+ {
+ return CMP_DNS_SUFFIX_BAD_NAME;
+ }
+ }
+ domaintail --;
+ if (*domaintail == k_dns_separator)
+ {
+ domaintail --;
+ if (*domaintail == k_dns_separator)
+ {
+ return CMP_DNS_SUFFIX_BAD_DOMAIN;
+ }
+ }
+
+ // Compare.
+ while (
+ nametail >= name
+ && domaintail >= domain
+ && tolower(*nametail) == tolower(*domaintail))
+ {
+ nametail--;
+ domaintail--;
+ }
+
+ /* A successful finish will be one of the following:
+ (leading and trailing . ignored)
+
+ name : domain2.domain1
+ domain: domain2.domain1
+ ^
+
+ name : domain3.domain2.domain1
+ domain: domain2.domain1
+ ^
+ */
+ if (
+ domaintail < domain
+ && (nametail < name || *nametail == k_dns_separator)
+ )
+ {
+ return CMP_DNS_SUFFIX_SUCCESS;
+ }
+ else
+ {
+ return CMP_DNS_SUFFIX_FAILURE;
+ }
+}
+static errcode_t
+load_config (config_t * conf)
+{
+ FILE * cf;
+ char line [CONF_LINE_SIZE];
+ config_file_context_t context;
+
+ context.filename = k_conf_file;
+ context.linenum = 0;
+
+
+ cf = fopen (context.filename, "r");
+ if (! cf)
+ {
+ LOG(PHIDGET_LOG_INFO,
+ "mdns: Couldn't open nss_mdns configuration file %s, using default.",
+ context.filename
+ );
+ return default_config (conf);
+ }
+
+ while (fgets (line, CONF_LINE_SIZE, cf))
+ {
+ int errcode;
+ context.linenum++;
+ errcode = process_config_line (conf, line, &context);
+ if (errcode)
+ {
+ // Critical error, give up
+ return errcode;
+ }
+ }
+
+ return 0;
+}
+/*
+ Initialise the configuration from the config file.
+
+ Returns
+ 0 success
+ non-zero error code on failure
+ */
+errcode_t
+init_config ()
+{
+ if (g_config)
+ {
+ /*
+ Safe to test outside mutex.
+ If non-zero, initialisation is complete and g_config can be
+ safely used read-only. If zero, then we do proper mutex
+ testing before initialisation.
+ */
+ return 0;
+ }
+ else
+ {
+ int errcode = -1;
+ int presult;
+ config_t * temp_config;
+
+ // Acquire mutex
+#ifdef _WINDOWS
+ if(!g_config_mutex)
+ pthread_mutex_init(&g_config_mutex, 0);
+#endif
+ presult = pthread_mutex_lock (&g_config_mutex);
+ if (presult)
+ {
+ LOG(PHIDGET_LOG_ERROR,
+ "mdns: Fatal mutex lock error in nss_mdns:init_config, %s:%d: %d: %s",
+ __FILE__, __LINE__, presult, strerror (presult)
+ );
+ return presult;
+ }
+
+ // Test again now we have mutex, in case initialisation occurred while
+ // we were waiting
+ if (! g_config)
+ {
+ temp_config = (config_t *) malloc (sizeof (config_t));
+ if (temp_config)
+ {
+ // NOTE: This code will leak memory if initialisation fails
+ // repeatedly. This should only happen in the case of a memory
+ // error, so I'm not sure if it's a meaningful problem. - AW
+ *temp_config = k_empty_config;
+ errcode = load_config (temp_config);
+
+ if (! errcode)
+ {
+ g_config = temp_config;
+ }
+ }
+ else
+ {
+ LOG(PHIDGET_LOG_ERROR,
+ "mdns: Can't allocate memory in nss_mdns:init_config, %s:%d",
+ __FILE__, __LINE__
+ );
+ errcode = errno;
+ }
+ }
+
+ presult = pthread_mutex_unlock (&g_config_mutex);
+ if (presult)
+ {
+ LOG(PHIDGET_LOG_ERROR,
+ "mdns: Fatal mutex unlock error in nss_mdns:init_config, %s:%d: %d: %s",
+ __FILE__, __LINE__, presult, strerror (presult)
+ );
+ errcode = presult;
+ }
+
+ return errcode;
+ }
+}
+static int
+contains_domain_suffix (const config_t * conf, const char * addr)
+{
+ const domain_entry_t * curr = conf->domains;
+
+ while (curr != NULL)
+ {
+ if (cmp_dns_suffix (addr, curr->domain) > 0)
+ {
+ return 1;
+ }
+
+ curr = curr->next;
+ }
+
+ return 0;
+}
+int
+config_is_mdns_suffix (const char * name)
+{
+ int errcode = init_config ();
+ if (! errcode)
+ {
+ return contains_domain_suffix (g_config, name);
+ }
+ else
+ {
+ errno = errcode;
+ return -1;
+ }
+}
+static nss_status
+set_err_system (result_map_t * result)
+{
+ return set_err (result, NSS_STATUS_UNAVAIL, errno, NETDB_INTERNAL);
+}
+static int
+init_result (
+ result_map_t * result,
+ hostent * result_buf,
+ char * buf,
+ size_t buflen
+)
+{
+ if (buflen < sizeof (buf_header_t))
+ {
+ return ERANGE;
+ }
+
+ result->hostent = result_buf;
+ result->header = (buf_header_t *) buf;
+ result->header->hostname[0] = 0;
+ result->aliases_count = 0;
+ result->header->aliases[0] = NULL;
+ result->addrs_count = 0;
+ result->header->addrs[0] = NULL;
+ result->buffer = buf + sizeof (buf_header_t);
+ result->addr_idx = 0;
+ result->alias_idx = buflen - sizeof (buf_header_t);
+ result->done = 0;
+ set_err_notfound (result);
+
+ // Point hostent to the right buffers
+ result->hostent->h_name = result->header->hostname;
+ result->hostent->h_aliases = result->header->aliases;
+ result->hostent->h_addr_list = result->header->addrs;
+
+ return 0;
+}
+/*
+ Test whether name is applicable for mdns to process, and if so copy into
+ lookup_name buffer (if non-NULL).
+
+ Returns
+ Pointer to name to lookup up, if applicable, or NULL otherwise.
+ */
+static const char *
+is_applicable_name (
+ result_map_t * result,
+ const char * name,
+ char * lookup_name
+)
+{
+ int match = config_is_mdns_suffix (name);
+ if (match > 0)
+ {
+ if (lookup_name)
+ {
+ strncpy (lookup_name, name, k_hostname_maxlen + 1);
+ return lookup_name;
+ }
+ else
+ {
+ return name;
+ }
+ }
+ else
+ {
+ if (match < 0)
+ {
+ set_err_system (result);
+ }
+ return NULL;
+ }
+}
+
+int
+islocal (const char * name)
+{
+ return cmp_dns_suffix (name, k_local_suffix) > 0;
+}
+
+static nss_status
+set_err_mdns_failed (result_map_t * result)
+{
+ return set_err (result, NSS_STATUS_TRYAGAIN, EAGAIN, TRY_AGAIN);
+}
+static nss_status
+set_err_notfound (result_map_t * result)
+{
+ return set_err (result, NSS_STATUS_NOTFOUND, ENOENT, HOST_NOT_FOUND);
+}
+static char *
+contains_alias (result_map_t * result, const char * alias)
+{
+ int i;
+
+ for (i = 0; result->header->aliases [i]; i++)
+ {
+ if (strcmp (result->header->aliases [i], alias) == 0)
+ {
+ return result->header->aliases [i];
+ }
+ }
+
+ return NULL;
+}
+static nss_status
+set_err_bad_hostname (result_map_t * result)
+{
+ return set_err (result, NSS_STATUS_TRYAGAIN, ENOENT, NO_RECOVERY);
+}
+/*
+ Set the status in the result.
+
+ Parameters
+ result
+ Result structure to update
+ status
+ New nss_status value
+ err
+ New errno value
+ herr
+ New h_errno value
+
+ Returns
+ New status value
+ */
+static nss_status
+set_err (result_map_t * result, nss_status status, int err, int herr)
+{
+ result->status = status;
+ result->r_errno = err;
+ result->r_h_errno = herr;
+
+ return status;
+}
+static void *
+contains_address (result_map_t * result, const void * data, int len)
+{
+ int i;
+
+ // Idiot check
+ if (len != result->hostent->h_length)
+ {
+ LOG(PHIDGET_LOG_WARNING,
+ "mdns: Unexpected rdata length for address. Expected %d, got %d",
+ result->hostent->h_length,
+ len
+ );
+ // XXX And continue for now.
+ }
+
+ for (i = 0; result->header->addrs [i]; i++)
+ {
+ if (memcmp (result->header->addrs [i], data, len) == 0)
+ {
+ return result->header->addrs [i];
+ }
+ }
+
+ return NULL;
+}
+static nss_status
+set_err_internal_resource_full (result_map_t * result)
+{
+ return set_err (result, NSS_STATUS_RETURN, ERANGE, NO_RECOVERY);
+}
+static nss_status
+set_err_buf_too_small (result_map_t * result)
+{
+ return set_err (result, NSS_STATUS_TRYAGAIN, ERANGE, NETDB_INTERNAL);
+}
+static nss_status
+set_err_success (result_map_t * result)
+{
+ result->status = NSS_STATUS_SUCCESS;
+ return result->status;
+}
+static int
+callback_body_ptr (
+ const char * fullname,
+ result_map_t * result,
+ int rdlen,
+ const void * rdata
+)
+{
+ char result_name [k_hostname_maxlen + 1];
+ int rv;
+
+ // Fullname should be .in-addr.arpa or equivalent, which we're
+ // not interested in. Ignore it.
+
+ rv = dns_rdata_to_name (rdata, rdlen, result_name, k_hostname_maxlen);
+ if (rv < 0)
+ {
+ const char * errmsg;
+
+ switch (rv)
+ {
+ case DNS_RDATA_TO_NAME_BAD_FORMAT:
+ errmsg = "mdns: PTR '%s' result badly formatted ('%s...')";
+ break;
+
+ case DNS_RDATA_TO_NAME_TOO_LONG:
+ errmsg = "mdns: PTR '%s' result too long ('%s...')";
+ break;
+
+ case DNS_RDATA_TO_NAME_PTR:
+ errmsg = "mdns: PTR '%s' result contained pointer ('%s...')";
+ break;
+
+ default:
+ errmsg = "mdns: PTR '%s' result conversion failed ('%s...')";
+ }
+
+ LOG(PHIDGET_LOG_WARNING,
+ errmsg,
+ fullname,
+ result_name
+ );
+
+ return -1;
+ }
+
+ LOG(PHIDGET_LOG_DEBUG,
+ "mdns: PTR '%s' resolved to '%s'",
+ fullname,
+ result_name
+ );
+
+ // Data should be a hostname
+ if (!
+ add_hostname_or_alias (
+ result,
+ result_name,
+ rv
+ )
+ )
+ {
+ result->done = 1;
+ return -1;
+ }
+
+ return 0;
+}
+
+
+
+const char *
+ns_class_to_str (ns_class_t in)
+{
+ if (in < k_table_ns_class_size)
+ return k_table_ns_class [in];
+ else
+ return NULL;
+}
+
+
+const char *
+ns_type_to_str (ns_type_t in)
+{
+ if (in < k_table_ns_type_size)
+ return k_table_ns_type [in];
+ else
+ return NULL;
+}
+
+
+ns_type_t
+af_to_rr (int af)
+{
+ switch (af)
+ {
+ case AF_INET:
+ return kDNSServiceType_A;
+
+ case AF_INET6:
+ return kDNSServiceType_AAAA;
+
+ default:
+ //return ns_t_invalid;
+ return 0;
+ }
+}
+/*
+ Add fully qualified name as hostname or alias.
+
+ If hostname is not fully qualified this is not an error, but the data
+ returned may be not what the application wanted.
+
+ Parameter
+ result
+ Result structure to write to
+ data
+ Incoming alias (null terminated)
+ len
+ Length of data buffer (in bytes), including trailing null
+
+ Result
+ Pointer to start of newly written data,
+ or NULL on error
+ If alias or hostname already exists, returns pointer to that instead.
+ */
+static char *
+add_hostname_or_alias (result_map_t * result, const char * data, int len)
+{
+ char * hostname = result->hostent->h_name;
+
+ if (*hostname)
+ {
+ if (strcmp (hostname, data) == 0)
+ {
+ return hostname;
+ }
+ else
+ {
+ return add_alias_to_buffer (result, data, len);
+ }
+ }
+ else
+ {
+ return add_hostname_len (result, data, len);
+ }
+}
+
+/*
+ Add an address to the buffer.
+
+ Parameter
+ result
+ Result structure to write to
+ data
+ Incoming address data buffer
+ Must be 'int' aligned
+ len
+ Length of data buffer (in bytes)
+ Must match data alignment
+
+ Result
+ Pointer to start of newly written data,
+ or NULL on error.
+ If address already exists in buffer, returns pointer to that instead.
+ */
+static void *
+add_address_to_buffer (result_map_t * result, const void * data, int len)
+{
+ int new_addr;
+ void * start;
+ void * temp;
+
+ if ((temp = contains_address (result, data, len)))
+ {
+ return temp;
+ }
+
+ if (result->addrs_count >= k_addrs_max)
+ {
+ // Not enough addr slots
+ set_err_internal_resource_full (result);
+ LOG(PHIDGET_LOG_ERROR,
+ "mdns: Internal address buffer full; increase size"
+ );
+ return NULL;
+ }
+
+ // Idiot check
+ if (len != result->hostent->h_length)
+ {
+ LOG(PHIDGET_LOG_WARNING,
+ "mdns: Unexpected rdata length for address. Expected %d, got %d",
+ result->hostent->h_length,
+ len
+ );
+ // XXX And continue for now.
+ }
+
+ new_addr = result->addr_idx + len;
+
+ if (new_addr > result->alias_idx)
+ {
+ // Not enough room
+ set_err_buf_too_small (result);
+ LOG(PHIDGET_LOG_DEBUG,
+ "mdns: Ran out of buffer when adding address %d",
+ result->addrs_count + 1
+ );
+ return NULL;
+ }
+
+ start = result->buffer + result->addr_idx;
+ memcpy (start, data, len);
+ result->addr_idx = new_addr;
+ result->header->addrs [result->addrs_count] = start;
+ result->addrs_count ++;
+ result->header->addrs [result->addrs_count] = NULL;
+
+ return start;
+}
+
+/*
+ Wait on result of callback, and process it when it arrives.
+
+ Parameters
+ sdref
+ dns-sd reference
+ result
+ Initialised 'result' data structure.
+ str
+ lookup string, used for status/error reporting.
+ */
+static nss_status
+handle_events (DNSServiceRef sdref, result_map_t * result, const char * str)
+{
+ int dns_sd_fd = DNSServiceRefSockFDPtr(sdref);
+ int nfds = dns_sd_fd + 1;
+ fd_set readfds;
+ struct timeval tv;
+ int select_result;
+
+ while (! result->done)
+ {
+ FD_ZERO(&readfds);
+ FD_SET(dns_sd_fd, &readfds);
+
+ tv = k_select_time;
+
+ select_result =
+ select (nfds, &readfds, (fd_set*)NULL, (fd_set*)NULL, &tv);
+ if (select_result > 0)
+ {
+ if (FD_ISSET(dns_sd_fd, &readfds))
+ {
+ LOG(PHIDGET_LOG_DEBUG,
+ "mdns: Reply received for %s",
+ str
+ );
+ DNSServiceProcessResultPtr(sdref);
+ }
+ else
+ {
+ LOG(PHIDGET_LOG_WARNING,
+ "mdns: Unexpected return from select on lookup of %s",
+ str
+ );
+ }
+ }
+ else
+ {
+ // Terminate loop due to timer expiry
+ LOG(PHIDGET_LOG_DEBUG,
+ "mdns: %s not found - timer expired",
+ str
+ );
+ set_err_notfound (result);
+ break;
+ }
+ }
+
+ return result->status;
+}
+
+/*
+ Lookup a fully qualified hostname using the default record type
+ for the specified address family.
+
+ Parameters
+ fullname
+ Fully qualified hostname. If not fully qualified the code will
+ still 'work', but the lookup is unlikely to succeed.
+ af
+ Either AF_INET or AF_INET6. Other families are not supported.
+ result
+ Initialised 'result' data structure.
+ */
+static nss_status
+mdns_lookup_name (
+ const char * fullname,
+ int af,
+ result_map_t * result
+)
+{
+ // Lookup using mDNS.
+ DNSServiceErrorType errcode;
+ DNSServiceRef sdref;
+ ns_type_t rrtype;
+ nss_status status;
+
+ LOG(PHIDGET_LOG_DEBUG,
+ "mdns: Attempting lookup of %s",
+ fullname
+ );
+
+ switch (af)
+ {
+ case AF_INET:
+ rrtype = kDNSServiceType_A;
+ result->hostent->h_length = 4;
+ // Length of an A record
+ break;
+
+ case AF_INET6:
+ rrtype = kDNSServiceType_AAAA;
+ result->hostent->h_length = 16;
+ // Length of an AAAA record
+ break;
+
+ default:
+ LOG(PHIDGET_LOG_WARNING,
+ "mdns: Unsupported address family %d",
+ af
+ );
+ return set_err_bad_hostname (result);
+ }
+ result->hostent->h_addrtype = af;
+
+ errcode =
+ DNSServiceQueryRecordPtr (
+ &sdref,
+ kDNSServiceFlagsForceMulticast, // force multicast query
+ kDNSServiceInterfaceIndexAny, // all interfaces
+ fullname, // full name to query for
+ rrtype, // resource record type
+ kDNSServiceClass_IN, // internet class records
+ mdns_lookup_callback, // callback
+ result // Context - result buffer
+ );
+
+ if (errcode)
+ {
+ LOG(PHIDGET_LOG_WARNING,
+ "mdns: Failed to initialise lookup, error %d",
+ errcode
+ );
+ return set_err_mdns_failed (result);
+ }
+
+ status = handle_events (sdref, result, fullname);
+ DNSServiceRefDeallocatePtr (sdref);
+ return status;
+}
+
+/*
+ Examine incoming data and add to relevant fields in result structure.
+ This routine is called from DNSServiceProcessResult where appropriate.
+ */
+void
+mdns_lookup_callback
+(
+ DNSServiceRef sdref,
+ DNSServiceFlags flags,
+ uint32_t interface_index,
+ DNSServiceErrorType error_code,
+ const char *fullname,
+ uint16_t rrtype,
+ uint16_t rrclass,
+ uint16_t rdlen,
+ const void *rdata,
+ uint32_t ttl,
+ void *context
+)
+{
+ // A single record is received
+
+ result_map_t * result = (result_map_t *) context;
+
+ (void)sdref; // Unused
+ (void)interface_index; // Unused
+ (void)ttl; // Unused
+
+ if (! (flags & kDNSServiceFlagsMoreComing) )
+ {
+ result->done = 1;
+ }
+
+ if (error_code == kDNSServiceErr_NoError)
+ {
+ ns_type_t expected_rr_type =
+ af_to_rr (result->hostent->h_addrtype);
+
+ // Idiot check class
+ if (rrclass != C_IN)
+ {
+ LOG(PHIDGET_LOG_WARNING,
+ "mdns: Received bad RR class: expected %d (%s),"
+ " got %d (%s), RR type %d (%s)",
+ C_IN,
+ ns_class_to_str (C_IN),
+ rrclass,
+ ns_class_to_str (rrclass),
+ rrtype,
+ ns_type_to_str (rrtype)
+ );
+ return;
+ }
+
+ // If a PTR
+ if (rrtype == kDNSServiceType_PTR)
+ {
+ if (callback_body_ptr (fullname, result, rdlen, rdata) < 0)
+ return;
+ }
+ else if (rrtype == expected_rr_type)
+ {
+ if (!
+ add_hostname_or_alias (
+ result,
+ fullname,
+ strlen (fullname)
+ )
+ )
+ {
+ result->done = 1;
+ return;
+ // Abort on error
+ }
+
+ if (! add_address_to_buffer (result, rdata, rdlen) )
+ {
+ result->done = 1;
+ return;
+ // Abort on error
+ }
+ }
+ else
+ {
+ LOG(PHIDGET_LOG_WARNING,
+ "mdns: Received bad RR type: expected %d (%s),"
+ " got %d (%s)",
+ expected_rr_type,
+ ns_type_to_str (expected_rr_type),
+ rrtype,
+ ns_type_to_str (rrtype)
+ );
+ return;
+ }
+
+ if (result->status != NSS_STATUS_SUCCESS)
+ set_err_success (result);
+ }
+ else
+ {
+ // For now, dump message to syslog and continue
+ LOG(PHIDGET_LOG_WARNING,
+ "mdns: callback returned error %d",
+ error_code
+ );
+ }
+}
+
+int
+dns_rdata_to_name (const char * rdata, int rdlen, char * name, int name_len)
+{
+ int i = 0;
+ // Index into 'name'
+ const char * rdata_curr = rdata;
+
+ // drop any leading whitespace rubbish
+ while (isspace (*rdata_curr))
+ {
+ rdata_curr ++;
+ if (rdata_curr > rdata + rdlen)
+ {
+ return DNS_RDATA_TO_NAME_BAD_FORMAT;
+ }
+ }
+
+ /*
+ In RDATA, a DNS name is stored as a series of labels.
+ Each label consists of a length octet (max value 63)
+ followed by the data for that label.
+ The series is terminated with a length 0 octet.
+ A length octet beginning with bits 11 is a pointer to
+ somewhere else in the payload, but we don't support these
+ since we don't have access to the entire payload.
+
+ See RFC1034 section 3.1 and RFC1035 section 3.1.
+ */
+ while (1)
+ {
+ int term_len = *rdata_curr;
+ rdata_curr++;
+
+ if (term_len == 0)
+ {
+ break;
+ // 0 length record terminates label
+ }
+ else if (term_len > k_label_maxlen)
+ {
+ name [i] = 0;
+ return DNS_RDATA_TO_NAME_PTR;
+ }
+ else if (rdata_curr + term_len > rdata + rdlen)
+ {
+ name [i] = 0;
+ return DNS_RDATA_TO_NAME_BAD_FORMAT;
+ }
+
+ if (name_len < i + term_len + 1)
+ // +1 is separator
+ {
+ name [i] = 0;
+ return DNS_RDATA_TO_NAME_TOO_LONG;
+ }
+
+ memcpy (name + i, rdata_curr, term_len);
+
+ i += term_len;
+ rdata_curr += term_len;
+
+ name [i] = k_dns_separator;
+ i++;
+ }
+
+ name [i] = 0;
+ return i;
+}
+
+/*
+ Add fully qualified hostname to result.
+
+ Parameter
+ result
+ Result structure to write to
+ fullname
+ Fully qualified hostname
+
+ Result
+ Pointer to start of hostname buffer,
+ or NULL on error (usually hostname too long)
+ */
+
+static char *
+add_hostname_len (result_map_t * result, const char * fullname, int len)
+{
+ if (len >= k_hostname_maxlen)
+ {
+ set_err_bad_hostname (result);
+ LOG(PHIDGET_LOG_WARNING,
+ "mdns: Hostname too long '%.*s': len %d, max %d",
+ len,
+ fullname,
+ len,
+ k_hostname_maxlen
+ );
+ return NULL;
+ }
+
+ result->hostent->h_name =
+ strcpy (result->header->hostname, fullname);
+
+ return result->header->hostname;
+}
+/*
+ Add an alias to the buffer.
+
+ Parameter
+ result
+ Result structure to write to
+ data
+ Incoming alias (null terminated)
+ len
+ Length of data buffer (in bytes), including trailing null
+
+ Result
+ Pointer to start of newly written data,
+ or NULL on error
+ If alias already exists in buffer, returns pointer to that instead.
+ */
+static char *
+add_alias_to_buffer (result_map_t * result, const char * data, int len)
+{
+ int new_alias;
+ char * start;
+ char * temp;
+
+ if ((temp = contains_alias (result, data)))
+ {
+ return temp;
+ }
+
+ if (result->aliases_count >= k_aliases_max)
+ {
+ // Not enough alias slots
+ set_err_internal_resource_full (result);
+ LOG(PHIDGET_LOG_ERROR,
+ "mdns: Internal alias buffer full; increase size"
+ );
+ return NULL;
+ }
+
+ new_alias = result->alias_idx - len;
+
+ if (new_alias < result->addr_idx)
+ {
+ // Not enough room
+ set_err_buf_too_small (result);
+ LOG(PHIDGET_LOG_DEBUG,
+ "mdns: Ran out of buffer when adding alias %d",
+ result->aliases_count + 1
+ );
+ return NULL;
+ }
+
+ start = result->buffer + new_alias;
+ memcpy (start, data, len);
+ result->alias_idx = new_alias;
+ result->header->aliases [result->aliases_count] = start;
+ result->aliases_count ++;
+ result->header->aliases [result->aliases_count] = NULL;
+
+ return start;
+}
+
+
+
+/*
+ These are the exported gethostbyname functions
+ These will use regular gethostbyname for non .local hostnames,
+ and connect to the mdns daemon for looking up .local hostnames.
+*/
+struct hostent *
+mdns_gethostbyname (
+ const char *name
+)
+{
+ return mdns_gethostbyname2(name, AF_INET);
+}
+
+struct hostent *
+mdns_gethostbyname2 (
+ const char *name,
+ int af
+)
+{
+ hostent *result_buf;
+ char buf[1024];
+ size_t buflen=1024;
+ int errnop;
+ int h_errnop;
+
+ char lookup_name [k_hostname_maxlen + 1];
+ result_map_t result;
+ int err_status;
+
+ if(!islocal(name))
+#ifdef _WINDOWS
+ return (gethostbyname(name));
+#else
+ return (gethostbyname2(name, af));
+#endif
+
+ result_buf=malloc(sizeof(hostent));
+
+ // Initialize Zeroconf - does run time linking of dns-sd functions
+ // if it fails, return null
+ if(InitializeZeroconf())
+ return NULL;
+
+ // Initialise result
+ err_status = init_result (&result, result_buf, buf, buflen);
+ if (err_status)
+ {
+ errnop = err_status;
+ h_errnop = NETDB_INTERNAL;
+ return NULL;
+ }
+
+ if (is_applicable_name (&result, name, lookup_name))
+ {
+ // Try using mdns
+ nss_status rv;
+
+ LOG(PHIDGET_LOG_DEBUG,
+ "mdns: Local name: %s",
+ name
+ );
+
+ rv = mdns_lookup_name (name, af, &result);
+ if (rv == NSS_STATUS_SUCCESS)
+ {
+ return result_buf;
+ }
+ }
+
+ // Return current error status (defaults to NOT_FOUND)
+
+ errnop = result.r_errno;
+ h_errnop = result.r_h_errno;
+
+ return NULL;
+}
+
+#endif