1
0
mirror of https://bitbucket.org/librepilot/librepilot.git synced 2024-12-01 09:24:10 +01:00

Merge branch 'rel-15.02' into samguns/zh_CN_GCS

This commit is contained in:
samguns 2015-03-04 08:45:44 +08:00
commit 08564a739f
13 changed files with 11186 additions and 170 deletions

View File

@ -1,4 +1,4 @@
--- RELEASE-15.02 RC2 --- RELEASE-15.02 RC3
This release introduces major flight performance improvements, enhancements as well as bug fixes. Many enhancements have been made to reducing dead-time of the communication between the flight controller and ESCs. In our testing, we have found this to be not only the best flight performance so far in the OpenPilot project but the best flight performance of any project we have tested against. This is a recommended upgrade for everyone and the more skilled of a pilot you are, the more you will love this release. This release introduces major flight performance improvements, enhancements as well as bug fixes. Many enhancements have been made to reducing dead-time of the communication between the flight controller and ESCs. In our testing, we have found this to be not only the best flight performance so far in the OpenPilot project but the best flight performance of any project we have tested against. This is a recommended upgrade for everyone and the more skilled of a pilot you are, the more you will love this release.
A key improvement that helped achieve this was the addition of the PWMSync code path, this is now enabled by default. Some restrictions applies to CC3D/CC as it needs a compatible input method to enable PWMSync. Compatible input methods are PPM, S.Bus, DSM and OPLink. This release also introduces support for OneShot125 capable ESCs, such as the KISS ESCs and all ESCs supported in BLHeli V13 and above. Note that OneShot125 support has the same restrictions as PWMSync for CC and CC3D. A key improvement that helped achieve this was the addition of the PWMSync code path, this is now enabled by default. Some restrictions applies to CC3D/CC as it needs a compatible input method to enable PWMSync. Compatible input methods are PPM, S.Bus, DSM and OPLink. This release also introduces support for OneShot125 capable ESCs, such as the KISS ESCs and all ESCs supported in BLHeli V13 and above. Note that OneShot125 support has the same restrictions as PWMSync for CC and CC3D.
@ -15,6 +15,7 @@ Release Notes - OpenPilot - Version RELEASE-15.02
** Bug ** Bug
* [OP-969] - Input Configuration Wizard has scrollbars showing up and next/previous buttons are pushed down out of sight * [OP-969] - Input Configuration Wizard has scrollbars showing up and next/previous buttons are pushed down out of sight
* [OP-1034] - CCPM Config Widget crashes GCS if required boxes aren't set i.e. Channel set to None
* [OP-1466] - Gcs crashes on Helicopter config tab * [OP-1466] - Gcs crashes on Helicopter config tab
* [OP-1522] - Improve Robustness of OPLink radio * [OP-1522] - Improve Robustness of OPLink radio
* [OP-1601] - Still not enough ram on CC for gps to be usable * [OP-1601] - Still not enough ram on CC for gps to be usable
@ -34,9 +35,13 @@ Release Notes - OpenPilot - Version RELEASE-15.02
* [OP-1743] - cc3d fails to connect once "next " is loaded 2-23-15 * [OP-1743] - cc3d fails to connect once "next " is loaded 2-23-15
* [OP-1744] - Vehicle config wizard produces a bad configuration * [OP-1744] - Vehicle config wizard produces a bad configuration
* [OP-1754] - Vehicle Wizard bad config when setting PPM in and RapidESC out * [OP-1754] - Vehicle Wizard bad config when setting PPM in and RapidESC out
* [OP-1755] - Add additional path for cloudconfigs
* [OP-1758] - Upgrade hidapi for all OSs (except windows) to solve mac issue:Fix incorrect device list after device removal
** Improvement ** Improvement
* [OP-1519] - Auto Reboot of board when required by Wizard
* [OP-1576] - Remove tx resent accounting from OPlink * [OP-1576] - Remove tx resent accounting from OPlink
* [OP-1635] - Remove Quad H from wizard to avoid confusion with Quad X * [OP-1635] - Remove Quad H from wizard to avoid confusion with Quad X
* [OP-1650] - Reduce telemetry to improve OPLink * [OP-1650] - Reduce telemetry to improve OPLink
@ -46,7 +51,7 @@ Release Notes - OpenPilot - Version RELEASE-15.02
* [OP-1694] - Make package make rule non-nested * [OP-1694] - Make package make rule non-nested
* [OP-1698] - Add easy to set channel passtrough GCS functionality * [OP-1698] - Add easy to set channel passtrough GCS functionality
* [OP-1704] - Add support for sanity check custom hooks * [OP-1704] - Add support for sanity check custom hooks
* [OP-1755] - Add additional path for cloudconfigs * [OP-1759] - Hide CC3D non-supported options (GPSAssist)
** New Feature ** New Feature
* [OP-1723] - RCCar Forward/reverse support * [OP-1723] - RCCar Forward/reverse support
@ -61,6 +66,7 @@ Release Notes - OpenPilot - Version RELEASE-15.02
* [OP-1752] - Add Alarm sub status to SystemHealth * [OP-1752] - Add Alarm sub status to SystemHealth
--- RELEASE-15.01 --- Look Ma, No hands --- --- RELEASE-15.01 --- Look Ma, No hands ---
This release mainly focuses on a new feature, GPSAssist which is a new form of assisted control for multirotors. This release mainly focuses on a new feature, GPSAssist which is a new form of assisted control for multirotors.
Assisted Control provides assistance functions on top of existing flight modes. GPSAssist is the Assisted Control provides assistance functions on top of existing flight modes. GPSAssist is the

View File

@ -0,0 +1,2185 @@
{
"battery": "4S 1800mah",
"comment": "",
"controller": "CC3D",
"esc": "Sunrise 20A OPTO BLHeli 13.1",
"motor": "Sunnysky 2207 2100 KV",
"name": "ZMR 250",
"nick": "ehitaja",
"objects": [
{
"fields": [
{
"name": "VbarSensitivity",
"type": "float32",
"unit": "frac",
"values": [
{
"name": "Roll",
"value": 0.5
},
{
"name": "Pitch",
"value": 0.5
},
{
"name": "Yaw",
"value": 0.5
}
]
},
{
"name": "VbarRollPI",
"type": "float32",
"unit": "1/(deg/s)",
"values": [
{
"name": "Kp",
"value": 0.004999999888241291
},
{
"name": "Ki",
"value": 0.0020000000949949026
}
]
},
{
"name": "VbarPitchPI",
"type": "float32",
"unit": "1/(deg/s)",
"values": [
{
"name": "Kp",
"value": 0.004999999888241291
},
{
"name": "Ki",
"value": 0.0020000000949949026
}
]
},
{
"name": "VbarYawPI",
"type": "float32",
"unit": "1/(deg/s)",
"values": [
{
"name": "Kp",
"value": 0.004999999888241291
},
{
"name": "Ki",
"value": 0.0020000000949949026
}
]
},
{
"name": "VbarTau",
"type": "float32",
"unit": "sec",
"values": [
{
"name": "0",
"value": 0.5
}
]
},
{
"name": "GyroTau",
"type": "float32",
"unit": "",
"values": [
{
"name": "0",
"value": 0.0040000001899898052
}
]
},
{
"name": "DerivativeGamma",
"type": "float32",
"unit": "",
"values": [
{
"name": "0",
"value": 1
}
]
},
{
"name": "AxisLockKp",
"type": "float32",
"unit": "",
"values": [
{
"name": "0",
"value": 2.5
}
]
},
{
"name": "WeakLevelingKp",
"type": "float32",
"unit": "(deg/s)/deg",
"values": [
{
"name": "0",
"value": 0.10000000149011612
}
]
},
{
"name": "CruiseControlMaxPowerFactor",
"type": "float32",
"unit": "x",
"values": [
{
"name": "0",
"value": 3
}
]
},
{
"name": "CruiseControlPowerTrim",
"type": "float32",
"unit": "%",
"values": [
{
"name": "0",
"value": 100
}
]
},
{
"name": "CruiseControlPowerDelayComp",
"type": "float32",
"unit": "sec",
"values": [
{
"name": "0",
"value": 0.25
}
]
},
{
"name": "ScaleToAirspeed",
"type": "float32",
"unit": "m/s",
"values": [
{
"name": "0",
"value": 0
}
]
},
{
"name": "ScaleToAirspeedLimits",
"type": "float32",
"unit": "",
"values": [
{
"name": "Min",
"value": 0.05000000074505806
},
{
"name": "Max",
"value": 3
}
]
},
{
"name": "FlightModeMap",
"type": "enum",
"unit": "",
"values": [
{
"name": "0",
"value": "Bank1"
},
{
"name": "1",
"value": "Bank1"
},
{
"name": "2",
"value": "Bank1"
},
{
"name": "3",
"value": "Bank1"
},
{
"name": "4",
"value": "Bank1"
},
{
"name": "5",
"value": "Bank1"
}
]
},
{
"name": "VbarGyroSuppress",
"type": "int8",
"unit": "%",
"values": [
{
"name": "0",
"value": 30
}
]
},
{
"name": "VbarPiroComp",
"type": "enum",
"unit": "",
"values": [
{
"name": "0",
"value": "FALSE"
}
]
},
{
"name": "VbarMaxAngle",
"type": "uint8",
"unit": "deg",
"values": [
{
"name": "0",
"value": 10
}
]
},
{
"name": "DerivativeCutoff",
"type": "uint8",
"unit": "Hz",
"values": [
{
"name": "0",
"value": 20
}
]
},
{
"name": "MaxAxisLock",
"type": "uint8",
"unit": "deg",
"values": [
{
"name": "0",
"value": 30
}
]
},
{
"name": "MaxAxisLockRate",
"type": "uint8",
"unit": "deg/s",
"values": [
{
"name": "0",
"value": 2
}
]
},
{
"name": "MaxWeakLevelingRate",
"type": "uint8",
"unit": "deg/s",
"values": [
{
"name": "0",
"value": 5
}
]
},
{
"name": "RattitudeModeTransition",
"type": "uint8",
"unit": "%",
"values": [
{
"name": "0",
"value": 80
}
]
},
{
"name": "CruiseControlMinThrust",
"type": "int8",
"unit": "%",
"values": [
{
"name": "0",
"value": 5
}
]
},
{
"name": "CruiseControlMaxThrust",
"type": "uint8",
"unit": "%",
"values": [
{
"name": "0",
"value": 90
}
]
},
{
"name": "CruiseControlMaxAngle",
"type": "uint8",
"unit": "deg",
"values": [
{
"name": "0",
"value": 105
}
]
},
{
"name": "CruiseControlFlightModeSwitchPosEnable",
"type": "enum",
"unit": "",
"values": [
{
"name": "0",
"value": "FALSE"
},
{
"name": "1",
"value": "FALSE"
},
{
"name": "2",
"value": "FALSE"
},
{
"name": "3",
"value": "FALSE"
},
{
"name": "4",
"value": "FALSE"
},
{
"name": "5",
"value": "FALSE"
}
]
},
{
"name": "CruiseControlInvertedThrustReversing",
"type": "enum",
"unit": "",
"values": [
{
"name": "0",
"value": "Unreversed"
}
]
},
{
"name": "CruiseControlInvertedPowerOutput",
"type": "enum",
"unit": "",
"values": [
{
"name": "0",
"value": "Zero"
}
]
},
{
"name": "LowThrottleZeroIntegral",
"type": "enum",
"unit": "",
"values": [
{
"name": "0",
"value": "TRUE"
}
]
},
{
"name": "FlightModeAssistMap",
"type": "enum",
"unit": "",
"values": [
{
"name": "0",
"value": "None"
},
{
"name": "1",
"value": "None"
},
{
"name": "2",
"value": "None"
},
{
"name": "3",
"value": "None"
},
{
"name": "4",
"value": "None"
},
{
"name": "5",
"value": "None"
}
]
}
],
"id": "73603180",
"instance": 0,
"name": "StabilizationSettings",
"setting": true
},
{
"fields": [
{
"name": "ManualRate",
"type": "float32",
"unit": "degrees/sec",
"values": [
{
"name": "Roll",
"value": 420
},
{
"name": "Pitch",
"value": 400
},
{
"name": "Yaw",
"value": 310
}
]
},
{
"name": "MaximumRate",
"type": "float32",
"unit": "degrees/sec",
"values": [
{
"name": "Roll",
"value": 475
},
{
"name": "Pitch",
"value": 475
},
{
"name": "Yaw",
"value": 360
}
]
},
{
"name": "RollRatePID",
"type": "float32",
"unit": "",
"values": [
{
"name": "Kp",
"value": 0.0027000000700354576
},
{
"name": "Ki",
"value": 0.0070000002160668373
},
{
"name": "Kd",
"value": 3.9999998989515007e-05
},
{
"name": "ILimit",
"value": 0.30000001192092896
}
]
},
{
"name": "PitchRatePID",
"type": "float32",
"unit": "",
"values": [
{
"name": "Kp",
"value": 0.0032999999821186066
},
{
"name": "Ki",
"value": 0.012500000186264515
},
{
"name": "Kd",
"value": 5.999999848427251e-05
},
{
"name": "ILimit",
"value": 0.30000001192092896
}
]
},
{
"name": "YawRatePID",
"type": "float32",
"unit": "",
"values": [
{
"name": "Kp",
"value": 0.0075500002130866051
},
{
"name": "Ki",
"value": 0.011500000022351742
},
{
"name": "Kd",
"value": 4.9999998736893758e-05
},
{
"name": "ILimit",
"value": 0.30000001192092896
}
]
},
{
"name": "RollPI",
"type": "float32",
"unit": "",
"values": [
{
"name": "Kp",
"value": 3
},
{
"name": "Ki",
"value": 0
},
{
"name": "ILimit",
"value": 50
}
]
},
{
"name": "PitchPI",
"type": "float32",
"unit": "",
"values": [
{
"name": "Kp",
"value": 3.4000000953674316
},
{
"name": "Ki",
"value": 0
},
{
"name": "ILimit",
"value": 50
}
]
},
{
"name": "YawPI",
"type": "float32",
"unit": "",
"values": [
{
"name": "Kp",
"value": 2.5
},
{
"name": "Ki",
"value": 0
},
{
"name": "ILimit",
"value": 50
}
]
},
{
"name": "AcroInsanityFactor",
"type": "float32",
"unit": "percent",
"values": [
{
"name": "0",
"value": 0.41999998688697815
}
]
},
{
"name": "ThrustPIDScaleCurve",
"type": "float32",
"unit": "percent",
"values": [
{
"name": "0",
"value": 0.18856599926948547
},
{
"name": "25",
"value": 0.094283096492290497
},
{
"name": "50",
"value": 0
},
{
"name": "75",
"value": -0.10285499691963196
},
{
"name": "100",
"value": -0.20282800495624542
}
]
},
{
"name": "RollMax",
"type": "uint8",
"unit": "degrees",
"values": [
{
"name": "0",
"value": 80
}
]
},
{
"name": "PitchMax",
"type": "uint8",
"unit": "degrees",
"values": [
{
"name": "0",
"value": 80
}
]
},
{
"name": "YawMax",
"type": "uint8",
"unit": "degrees",
"values": [
{
"name": "0",
"value": 35
}
]
},
{
"name": "StickExpo",
"type": "int8",
"unit": "percent",
"values": [
{
"name": "Roll",
"value": 12
},
{
"name": "Pitch",
"value": 12
},
{
"name": "Yaw",
"value": 14
}
]
},
{
"name": "EnablePiroComp",
"type": "enum",
"unit": "",
"values": [
{
"name": "0",
"value": "FALSE"
}
]
},
{
"name": "EnableThrustPIDScaling",
"type": "enum",
"unit": "",
"values": [
{
"name": "0",
"value": "TRUE"
}
]
},
{
"name": "ThrustPIDScaleSource",
"type": "enum",
"unit": "",
"values": [
{
"name": "0",
"value": "ActuatorDesiredThrust"
}
]
},
{
"name": "ThrustPIDScaleTarget",
"type": "enum",
"unit": "",
"values": [
{
"name": "0",
"value": "PD"
}
]
},
{
"name": "ThrustPIDScaleAxes",
"type": "enum",
"unit": "",
"values": [
{
"name": "0",
"value": "Roll Pitch"
}
]
}
],
"id": "E8EBBD48",
"instance": 0,
"name": "StabilizationSettingsBank1",
"setting": true
},
{
"fields": [
{
"name": "ManualRate",
"type": "float32",
"unit": "degrees/sec",
"values": [
{
"name": "Roll",
"value": 400
},
{
"name": "Pitch",
"value": 400
},
{
"name": "Yaw",
"value": 220
}
]
},
{
"name": "MaximumRate",
"type": "float32",
"unit": "degrees/sec",
"values": [
{
"name": "Roll",
"value": 400
},
{
"name": "Pitch",
"value": 400
},
{
"name": "Yaw",
"value": 300
}
]
},
{
"name": "RollRatePID",
"type": "float32",
"unit": "",
"values": [
{
"name": "Kp",
"value": 0.0032999999821186066
},
{
"name": "Ki",
"value": 0.0076000001281499863
},
{
"name": "Kd",
"value": 3.600000127335079e-05
},
{
"name": "ILimit",
"value": 0.30000001192092896
}
]
},
{
"name": "PitchRatePID",
"type": "float32",
"unit": "",
"values": [
{
"name": "Kp",
"value": 0.0044999998062849045
},
{
"name": "Ki",
"value": 0.0093999998643994331
},
{
"name": "Kd",
"value": 4.5000000682193786e-05
},
{
"name": "ILimit",
"value": 0.30000001192092896
}
]
},
{
"name": "YawRatePID",
"type": "float32",
"unit": "",
"values": [
{
"name": "Kp",
"value": 0.0086000002920627594
},
{
"name": "Ki",
"value": 0.014299999922513962
},
{
"name": "Kd",
"value": 4.9999998736893758e-05
},
{
"name": "ILimit",
"value": 0.30000001192092896
}
]
},
{
"name": "RollPI",
"type": "float32",
"unit": "",
"values": [
{
"name": "Kp",
"value": 3
},
{
"name": "Ki",
"value": 0
},
{
"name": "ILimit",
"value": 50
}
]
},
{
"name": "PitchPI",
"type": "float32",
"unit": "",
"values": [
{
"name": "Kp",
"value": 3.4000000953674316
},
{
"name": "Ki",
"value": 0
},
{
"name": "ILimit",
"value": 50
}
]
},
{
"name": "YawPI",
"type": "float32",
"unit": "",
"values": [
{
"name": "Kp",
"value": 2.5
},
{
"name": "Ki",
"value": 0
},
{
"name": "ILimit",
"value": 50
}
]
},
{
"name": "AcroInsanityFactor",
"type": "float32",
"unit": "percent",
"values": [
{
"name": "0",
"value": 0.5
}
]
},
{
"name": "ThrustPIDScaleCurve",
"type": "float32",
"unit": "percent",
"values": [
{
"name": "0",
"value": 0.19285200536251068
},
{
"name": "25",
"value": 0.089997202157974243
},
{
"name": "50",
"value": 0
},
{
"name": "75",
"value": -0.085711203515529633
},
{
"name": "100",
"value": -0.18427999317646027
}
]
},
{
"name": "RollMax",
"type": "uint8",
"unit": "degrees",
"values": [
{
"name": "0",
"value": 55
}
]
},
{
"name": "PitchMax",
"type": "uint8",
"unit": "degrees",
"values": [
{
"name": "0",
"value": 55
}
]
},
{
"name": "YawMax",
"type": "uint8",
"unit": "degrees",
"values": [
{
"name": "0",
"value": 35
}
]
},
{
"name": "StickExpo",
"type": "int8",
"unit": "percent",
"values": [
{
"name": "Roll",
"value": 18
},
{
"name": "Pitch",
"value": 18
},
{
"name": "Yaw",
"value": -8
}
]
},
{
"name": "EnablePiroComp",
"type": "enum",
"unit": "",
"values": [
{
"name": "0",
"value": "FALSE"
}
]
},
{
"name": "EnableThrustPIDScaling",
"type": "enum",
"unit": "",
"values": [
{
"name": "0",
"value": "TRUE"
}
]
},
{
"name": "ThrustPIDScaleSource",
"type": "enum",
"unit": "",
"values": [
{
"name": "0",
"value": "ActuatorDesiredThrust"
}
]
},
{
"name": "ThrustPIDScaleTarget",
"type": "enum",
"unit": "",
"values": [
{
"name": "0",
"value": "PD"
}
]
},
{
"name": "ThrustPIDScaleAxes",
"type": "enum",
"unit": "",
"values": [
{
"name": "0",
"value": "Roll Pitch"
}
]
}
],
"id": "70E9539A",
"instance": 0,
"name": "StabilizationSettingsBank2",
"setting": true
},
{
"fields": [
{
"name": "ManualRate",
"type": "float32",
"unit": "degrees/sec",
"values": [
{
"name": "Roll",
"value": 220
},
{
"name": "Pitch",
"value": 220
},
{
"name": "Yaw",
"value": 220
}
]
},
{
"name": "MaximumRate",
"type": "float32",
"unit": "degrees/sec",
"values": [
{
"name": "Roll",
"value": 300
},
{
"name": "Pitch",
"value": 300
},
{
"name": "Yaw",
"value": 300
}
]
},
{
"name": "RollRatePID",
"type": "float32",
"unit": "",
"values": [
{
"name": "Kp",
"value": 0.0024999999441206455
},
{
"name": "Ki",
"value": 0.0040000001899898052
},
{
"name": "Kd",
"value": 1.9999999494757503e-05
},
{
"name": "ILimit",
"value": 0.30000001192092896
}
]
},
{
"name": "PitchRatePID",
"type": "float32",
"unit": "",
"values": [
{
"name": "Kp",
"value": 0.0024999999441206455
},
{
"name": "Ki",
"value": 0.0040000001899898052
},
{
"name": "Kd",
"value": 1.9999999494757503e-05
},
{
"name": "ILimit",
"value": 0.30000001192092896
}
]
},
{
"name": "YawRatePID",
"type": "float32",
"unit": "",
"values": [
{
"name": "Kp",
"value": 0.0062000001780688763
},
{
"name": "Ki",
"value": 0.0099999997764825821
},
{
"name": "Kd",
"value": 4.9999998736893758e-05
},
{
"name": "ILimit",
"value": 0.30000001192092896
}
]
},
{
"name": "RollPI",
"type": "float32",
"unit": "",
"values": [
{
"name": "Kp",
"value": 2.5
},
{
"name": "Ki",
"value": 0
},
{
"name": "ILimit",
"value": 50
}
]
},
{
"name": "PitchPI",
"type": "float32",
"unit": "",
"values": [
{
"name": "Kp",
"value": 2.5
},
{
"name": "Ki",
"value": 0
},
{
"name": "ILimit",
"value": 50
}
]
},
{
"name": "YawPI",
"type": "float32",
"unit": "",
"values": [
{
"name": "Kp",
"value": 2.5
},
{
"name": "Ki",
"value": 0
},
{
"name": "ILimit",
"value": 50
}
]
},
{
"name": "AcroInsanityFactor",
"type": "float32",
"unit": "percent",
"values": [
{
"name": "0",
"value": 0.5
}
]
},
{
"name": "ThrustPIDScaleCurve",
"type": "float32",
"unit": "percent",
"values": [
{
"name": "0",
"value": 0.30000001192092896
},
{
"name": "25",
"value": 0.15000000596046448
},
{
"name": "50",
"value": 0
},
{
"name": "75",
"value": -0.15000000596046448
},
{
"name": "100",
"value": -0.30000001192092896
}
]
},
{
"name": "RollMax",
"type": "uint8",
"unit": "degrees",
"values": [
{
"name": "0",
"value": 55
}
]
},
{
"name": "PitchMax",
"type": "uint8",
"unit": "degrees",
"values": [
{
"name": "0",
"value": 55
}
]
},
{
"name": "YawMax",
"type": "uint8",
"unit": "degrees",
"values": [
{
"name": "0",
"value": 35
}
]
},
{
"name": "StickExpo",
"type": "int8",
"unit": "percent",
"values": [
{
"name": "Roll",
"value": 0
},
{
"name": "Pitch",
"value": 0
},
{
"name": "Yaw",
"value": 0
}
]
},
{
"name": "EnablePiroComp",
"type": "enum",
"unit": "",
"values": [
{
"name": "0",
"value": "TRUE"
}
]
},
{
"name": "EnableThrustPIDScaling",
"type": "enum",
"unit": "",
"values": [
{
"name": "0",
"value": "FALSE"
}
]
},
{
"name": "ThrustPIDScaleSource",
"type": "enum",
"unit": "",
"values": [
{
"name": "0",
"value": "ActuatorDesiredThrust"
}
]
},
{
"name": "ThrustPIDScaleTarget",
"type": "enum",
"unit": "",
"values": [
{
"name": "0",
"value": "PID"
}
]
},
{
"name": "ThrustPIDScaleAxes",
"type": "enum",
"unit": "",
"values": [
{
"name": "0",
"value": "Roll Pitch"
}
]
}
],
"id": "C02DAA6A",
"instance": 0,
"name": "StabilizationSettingsBank3",
"setting": true
},
{
"fields": [
{
"name": "MaxAccel",
"type": "float32",
"unit": "units/sec",
"values": [
{
"name": "0",
"value": 1000
}
]
},
{
"name": "FeedForward",
"type": "float32",
"unit": "",
"values": [
{
"name": "0",
"value": 0
}
]
},
{
"name": "AccelTime",
"type": "float32",
"unit": "ms",
"values": [
{
"name": "0",
"value": 0
}
]
},
{
"name": "DecelTime",
"type": "float32",
"unit": "ms",
"values": [
{
"name": "0",
"value": 0
}
]
},
{
"name": "ThrottleCurve1",
"type": "float32",
"unit": "percent",
"values": [
{
"name": "0",
"value": 0
},
{
"name": "25",
"value": 0.22499999403953552
},
{
"name": "50",
"value": 0.44999998807907104
},
{
"name": "75",
"value": 0.67499995231628418
},
{
"name": "100",
"value": 0.89999997615814209
}
]
},
{
"name": "ThrottleCurve2",
"type": "float32",
"unit": "percent",
"values": [
{
"name": "0",
"value": 0
},
{
"name": "25",
"value": 0.22499999403953552
},
{
"name": "50",
"value": 0.44999998807907104
},
{
"name": "75",
"value": 0.67499995231628418
},
{
"name": "100",
"value": 0.89999997615814209
}
]
},
{
"name": "MixerValueRoll",
"type": "int8",
"unit": "percent",
"values": [
{
"name": "0",
"value": 50
}
]
},
{
"name": "MixerValuePitch",
"type": "int8",
"unit": "percent",
"values": [
{
"name": "0",
"value": 50
}
]
},
{
"name": "MixerValueYaw",
"type": "int8",
"unit": "percent",
"values": [
{
"name": "0",
"value": 50
}
]
},
{
"name": "Curve2Source",
"type": "enum",
"unit": "",
"values": [
{
"name": "0",
"value": "Throttle"
}
]
},
{
"name": "Mixer1Type",
"type": "enum",
"unit": "",
"values": [
{
"name": "0",
"value": "Motor"
}
]
},
{
"name": "Mixer1Vector",
"type": "int8",
"unit": "",
"values": [
{
"name": "ThrottleCurve1",
"value": 127
},
{
"name": "ThrottleCurve2",
"value": 0
},
{
"name": "Roll",
"value": 64
},
{
"name": "Pitch",
"value": 64
},
{
"name": "Yaw",
"value": -64
}
]
},
{
"name": "Mixer2Type",
"type": "enum",
"unit": "",
"values": [
{
"name": "0",
"value": "Motor"
}
]
},
{
"name": "Mixer2Vector",
"type": "int8",
"unit": "",
"values": [
{
"name": "ThrottleCurve1",
"value": 127
},
{
"name": "ThrottleCurve2",
"value": 0
},
{
"name": "Roll",
"value": -64
},
{
"name": "Pitch",
"value": 64
},
{
"name": "Yaw",
"value": 64
}
]
},
{
"name": "Mixer3Type",
"type": "enum",
"unit": "",
"values": [
{
"name": "0",
"value": "Motor"
}
]
},
{
"name": "Mixer3Vector",
"type": "int8",
"unit": "",
"values": [
{
"name": "ThrottleCurve1",
"value": 127
},
{
"name": "ThrottleCurve2",
"value": 0
},
{
"name": "Roll",
"value": -64
},
{
"name": "Pitch",
"value": -64
},
{
"name": "Yaw",
"value": -64
}
]
},
{
"name": "Mixer4Type",
"type": "enum",
"unit": "",
"values": [
{
"name": "0",
"value": "Motor"
}
]
},
{
"name": "Mixer4Vector",
"type": "int8",
"unit": "",
"values": [
{
"name": "ThrottleCurve1",
"value": 127
},
{
"name": "ThrottleCurve2",
"value": 0
},
{
"name": "Roll",
"value": 64
},
{
"name": "Pitch",
"value": -64
},
{
"name": "Yaw",
"value": 64
}
]
},
{
"name": "Mixer5Type",
"type": "enum",
"unit": "",
"values": [
{
"name": "0",
"value": "Disabled"
}
]
},
{
"name": "Mixer5Vector",
"type": "int8",
"unit": "",
"values": [
{
"name": "ThrottleCurve1",
"value": 0
},
{
"name": "ThrottleCurve2",
"value": 0
},
{
"name": "Roll",
"value": 0
},
{
"name": "Pitch",
"value": 0
},
{
"name": "Yaw",
"value": 0
}
]
},
{
"name": "Mixer6Type",
"type": "enum",
"unit": "",
"values": [
{
"name": "0",
"value": "Disabled"
}
]
},
{
"name": "Mixer6Vector",
"type": "int8",
"unit": "",
"values": [
{
"name": "ThrottleCurve1",
"value": 0
},
{
"name": "ThrottleCurve2",
"value": 0
},
{
"name": "Roll",
"value": 0
},
{
"name": "Pitch",
"value": 0
},
{
"name": "Yaw",
"value": 0
}
]
},
{
"name": "Mixer7Type",
"type": "enum",
"unit": "",
"values": [
{
"name": "0",
"value": "Disabled"
}
]
},
{
"name": "Mixer7Vector",
"type": "int8",
"unit": "",
"values": [
{
"name": "ThrottleCurve1",
"value": 0
},
{
"name": "ThrottleCurve2",
"value": 0
},
{
"name": "Roll",
"value": 0
},
{
"name": "Pitch",
"value": 0
},
{
"name": "Yaw",
"value": 0
}
]
},
{
"name": "Mixer8Type",
"type": "enum",
"unit": "",
"values": [
{
"name": "0",
"value": "Disabled"
}
]
},
{
"name": "Mixer8Vector",
"type": "int8",
"unit": "",
"values": [
{
"name": "ThrottleCurve1",
"value": 0
},
{
"name": "ThrottleCurve2",
"value": 0
},
{
"name": "Roll",
"value": 0
},
{
"name": "Pitch",
"value": 0
},
{
"name": "Yaw",
"value": 0
}
]
},
{
"name": "Mixer9Type",
"type": "enum",
"unit": "",
"values": [
{
"name": "0",
"value": "Disabled"
}
]
},
{
"name": "Mixer9Vector",
"type": "int8",
"unit": "",
"values": [
{
"name": "ThrottleCurve1",
"value": 0
},
{
"name": "ThrottleCurve2",
"value": 0
},
{
"name": "Roll",
"value": 0
},
{
"name": "Pitch",
"value": 0
},
{
"name": "Yaw",
"value": 0
}
]
},
{
"name": "Mixer10Type",
"type": "enum",
"unit": "",
"values": [
{
"name": "0",
"value": "Disabled"
}
]
},
{
"name": "Mixer10Vector",
"type": "int8",
"unit": "",
"values": [
{
"name": "ThrottleCurve1",
"value": 0
},
{
"name": "ThrottleCurve2",
"value": 0
},
{
"name": "Roll",
"value": 0
},
{
"name": "Pitch",
"value": 0
},
{
"name": "Yaw",
"value": 0
}
]
},
{
"name": "Mixer11Type",
"type": "enum",
"unit": "",
"values": [
{
"name": "0",
"value": "Disabled"
}
]
},
{
"name": "Mixer11Vector",
"type": "int8",
"unit": "",
"values": [
{
"name": "ThrottleCurve1",
"value": 0
},
{
"name": "ThrottleCurve2",
"value": 0
},
{
"name": "Roll",
"value": 0
},
{
"name": "Pitch",
"value": 0
},
{
"name": "Yaw",
"value": 0
}
]
},
{
"name": "Mixer12Type",
"type": "enum",
"unit": "",
"values": [
{
"name": "0",
"value": "Disabled"
}
]
},
{
"name": "Mixer12Vector",
"type": "int8",
"unit": "",
"values": [
{
"name": "ThrottleCurve1",
"value": 0
},
{
"name": "ThrottleCurve2",
"value": 0
},
{
"name": "Roll",
"value": 0
},
{
"name": "Pitch",
"value": 0
},
{
"name": "Yaw",
"value": 0
}
]
}
],
"id": "7BF2CFA8",
"instance": 0,
"name": "MixerSettings",
"setting": true
},
{
"fields": [
{
"name": "P",
"type": "float32",
"unit": "1^2",
"values": [
{
"name": "PositionNorth",
"value": 10
},
{
"name": "PositionEast",
"value": 10
},
{
"name": "PositionDown",
"value": 10
},
{
"name": "VelocityNorth",
"value": 1
},
{
"name": "VelocityEast",
"value": 1
},
{
"name": "VelocityDown",
"value": 1
},
{
"name": "AttitudeQ1",
"value": 0.0070000002160668373
},
{
"name": "AttitudeQ2",
"value": 0.0070000002160668373
},
{
"name": "AttitudeQ3",
"value": 0.0070000002160668373
},
{
"name": "AttitudeQ4",
"value": 0.0070000002160668373
},
{
"name": "GyroDriftX",
"value": 9.9999999747524271e-07
},
{
"name": "GyroDriftY",
"value": 9.9999999747524271e-07
},
{
"name": "GyroDriftZ",
"value": 9.9999999747524271e-07
}
]
},
{
"name": "Q",
"type": "float32",
"unit": "1^2",
"values": [
{
"name": "GyroX",
"value": 0.0099999997764825821
},
{
"name": "GyroY",
"value": 0.0099999997764825821
},
{
"name": "GyroZ",
"value": 0.0099999997764825821
},
{
"name": "AccelX",
"value": 0.0099999997764825821
},
{
"name": "AccelY",
"value": 0.0099999997764825821
},
{
"name": "AccelZ",
"value": 0.0099999997764825821
},
{
"name": "GyroDriftX",
"value": 9.9999999747524271e-07
},
{
"name": "GyroDriftY",
"value": 9.9999999747524271e-07
},
{
"name": "GyroDriftZ",
"value": 9.9999999747524271e-07
}
]
},
{
"name": "R",
"type": "float32",
"unit": "1^2",
"values": [
{
"name": "GPSPosNorth",
"value": 1
},
{
"name": "GPSPosEast",
"value": 1
},
{
"name": "GPSPosDown",
"value": 1000000
},
{
"name": "GPSVelNorth",
"value": 0.0010000000474974513
},
{
"name": "GPSVelEast",
"value": 0.0010000000474974513
},
{
"name": "GPSVelDown",
"value": 0.0010000000474974513
},
{
"name": "MagX",
"value": 10
},
{
"name": "MagY",
"value": 10
},
{
"name": "MagZ",
"value": 10
},
{
"name": "BaroZ",
"value": 0.0099999997764825821
}
]
},
{
"name": "FakeR",
"type": "float32",
"unit": "1^2",
"values": [
{
"name": "FakeGPSPosIndoor",
"value": 10
},
{
"name": "FakeGPSVelIndoor",
"value": 1
},
{
"name": "FakeGPSVelAirspeed",
"value": 1000
}
]
}
],
"id": "5E91213C",
"instance": 0,
"name": "EKFConfiguration",
"setting": true
}
],
"owner": "Roman",
"propeller": "5040",
"servo": "",
"size": "250",
"subtype": 2,
"type": 1,
"uuid": "{65b347bb-5e6d-466f-895e-5895b222d670}",
"weight": "630 with battery"
}

View File

@ -116,8 +116,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>774</width> <width>1228</width>
<height>497</height> <height>669</height>
</rect> </rect>
</property> </property>
<layout class="QGridLayout" name="gridLayout"> <layout class="QGridLayout" name="gridLayout">
@ -274,8 +274,7 @@
</item> </item>
</layout> </layout>
</widget> </widget>
<widget class="QWidget" name="wizard"> <widget class="QWidget" name="wizard"/>
</widget>
</widget> </widget>
</item> </item>
</layout> </layout>
@ -491,8 +490,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>730</width> <width>1228</width>
<height>554</height> <height>669</height>
</rect> </rect>
</property> </property>
<layout class="QGridLayout" name="gridLayout_7" rowstretch="1,0,0,0"> <layout class="QGridLayout" name="gridLayout_7" rowstretch="1,0,0,0">
@ -1962,7 +1961,7 @@ font:bold;</string>
<string>objname:StabilizationSettings</string> <string>objname:StabilizationSettings</string>
<string>fieldname:FlightModeAssistMap</string> <string>fieldname:FlightModeAssistMap</string>
<string>index:0</string> <string>index:0</string>
<string>haslimits:no</string> <string>haslimits:yes</string>
<string>scale:1</string> <string>scale:1</string>
<string>buttongroup:16</string> <string>buttongroup:16</string>
</stringlist> </stringlist>
@ -1988,7 +1987,7 @@ font:bold;</string>
<string>objname:StabilizationSettings</string> <string>objname:StabilizationSettings</string>
<string>fieldname:FlightModeAssistMap</string> <string>fieldname:FlightModeAssistMap</string>
<string>index:1</string> <string>index:1</string>
<string>haslimits:no</string> <string>haslimits:yes</string>
<string>scale:1</string> <string>scale:1</string>
<string>buttongroup:16</string> <string>buttongroup:16</string>
</stringlist> </stringlist>
@ -2014,7 +2013,7 @@ font:bold;</string>
<string>objname:StabilizationSettings</string> <string>objname:StabilizationSettings</string>
<string>fieldname:FlightModeAssistMap</string> <string>fieldname:FlightModeAssistMap</string>
<string>index:2</string> <string>index:2</string>
<string>haslimits:no</string> <string>haslimits:yes</string>
<string>scale:1</string> <string>scale:1</string>
<string>buttongroup:16</string> <string>buttongroup:16</string>
</stringlist> </stringlist>
@ -2043,7 +2042,7 @@ font:bold;</string>
<string>objname:StabilizationSettings</string> <string>objname:StabilizationSettings</string>
<string>fieldname:FlightModeAssistMap</string> <string>fieldname:FlightModeAssistMap</string>
<string>index:3</string> <string>index:3</string>
<string>haslimits:no</string> <string>haslimits:yes</string>
<string>scale:1</string> <string>scale:1</string>
<string>buttongroup:16</string> <string>buttongroup:16</string>
</stringlist> </stringlist>
@ -2072,7 +2071,7 @@ font:bold;</string>
<string>objname:StabilizationSettings</string> <string>objname:StabilizationSettings</string>
<string>fieldname:FlightModeAssistMap</string> <string>fieldname:FlightModeAssistMap</string>
<string>index:4</string> <string>index:4</string>
<string>haslimits:no</string> <string>haslimits:yes</string>
<string>scale:1</string> <string>scale:1</string>
<string>buttongroup:16</string> <string>buttongroup:16</string>
</stringlist> </stringlist>
@ -2101,7 +2100,7 @@ font:bold;</string>
<string>objname:StabilizationSettings</string> <string>objname:StabilizationSettings</string>
<string>fieldname:FlightModeAssistMap</string> <string>fieldname:FlightModeAssistMap</string>
<string>index:5</string> <string>index:5</string>
<string>haslimits:no</string> <string>haslimits:yes</string>
<string>scale:1</string> <string>scale:1</string>
<string>buttongroup:16</string> <string>buttongroup:16</string>
</stringlist> </stringlist>
@ -2214,8 +2213,8 @@ font:bold;</string>
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>544</width> <width>1228</width>
<height>169</height> <height>669</height>
</rect> </rect>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_2"> <layout class="QVBoxLayout" name="verticalLayout_2">

View File

@ -11,7 +11,7 @@
At the discretion of the user of this library, At the discretion of the user of this library,
this software may be licensed under the terms of the this software may be licensed under the terms of the
GNU Public License v3, a BSD-Style license, or the GNU General Public License v3, a BSD-Style license, or the
original HIDAPI license as outlined in the LICENSE.txt, original HIDAPI license as outlined in the LICENSE.txt,
LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt
files located at the root of the source distribution. files located at the root of the source distribution.
@ -218,7 +218,8 @@ extern "C" {
@returns @returns
This function returns the actual number of bytes read and This function returns the actual number of bytes read and
-1 on error. -1 on error. If no packet was available to be read within
the timeout period, this function returns 0.
*/ */
int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds); int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds);
@ -237,7 +238,8 @@ extern "C" {
@returns @returns
This function returns the actual number of bytes read and This function returns the actual number of bytes read and
-1 on error. -1 on error. If no packet was available to be read and
the handle is in non-blocking mode, this function returns 0.
*/ */
int HID_API_EXPORT HID_API_CALL hid_read(hid_device *device, unsigned char *data, size_t length); int HID_API_EXPORT HID_API_CALL hid_read(hid_device *device, unsigned char *data, size_t length);
@ -291,22 +293,26 @@ extern "C" {
/** @brief Get a feature report from a HID device. /** @brief Get a feature report from a HID device.
Make sure to set the first byte of @p data[] to the Report Set the first byte of @p data[] to the Report ID of the
ID of the report to be read. Make sure to allow space for report to be read. Make sure to allow space for this
this extra byte in @p data[]. extra byte in @p data[]. Upon return, the first byte will
still contain the Report ID, and the report data will
start in data[1].
@ingroup API @ingroup API
@param device A device handle returned from hid_open(). @param device A device handle returned from hid_open().
@param data A buffer to put the read data into, including @param data A buffer to put the read data into, including
the Report ID. Set the first byte of @p data[] to the the Report ID. Set the first byte of @p data[] to the
Report ID of the report to be read. Report ID of the report to be read, or set it to zero
if your device does not use numbered reports.
@param length The number of bytes to read, including an @param length The number of bytes to read, including an
extra byte for the report ID. The buffer can be longer extra byte for the report ID. The buffer can be longer
than the actual report. than the actual report.
@returns @returns
This function returns the number of bytes read and This function returns the number of bytes read plus
-1 on error. one for the report ID (which is still in the first
byte), or -1 on error.
*/ */
int HID_API_EXPORT HID_API_CALL hid_get_feature_report(hid_device *device, unsigned char *data, size_t length); int HID_API_EXPORT HID_API_CALL hid_get_feature_report(hid_device *device, unsigned char *data, size_t length);

View File

@ -14,7 +14,7 @@
At the discretion of the user of this library, At the discretion of the user of this library,
this software may be licensed under the terms of the this software may be licensed under the terms of the
GNU Public License v3, a BSD-Style license, or the GNU General Public License v3, a BSD-Style license, or the
original HIDAPI license as outlined in the LICENSE.txt, original HIDAPI license as outlined in the LICENSE.txt,
LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt
files located at the root of the source distribution. files located at the root of the source distribution.
@ -44,11 +44,74 @@
#include <wchar.h> #include <wchar.h>
/* GNU / LibUSB */ /* GNU / LibUSB */
#include "libusb.h" #include <libusb.h>
#include "iconv.h" #ifndef __ANDROID__
#include <iconv.h>
#endif
#include "../hidapi.h" #include "../hidapi.h"
#ifdef __ANDROID__
/* Barrier implementation because Android/Bionic don't have pthread_barrier.
This implementation came from Brent Priddy and was posted on
StackOverflow. It is used with his permission. */
typedef int pthread_barrierattr_t;
typedef struct pthread_barrier {
pthread_mutex_t mutex;
pthread_cond_t cond;
int count;
int trip_count;
} pthread_barrier_t;
static int pthread_barrier_init(pthread_barrier_t *barrier, const pthread_barrierattr_t *attr, unsigned int count)
{
if(count == 0) {
errno = EINVAL;
return -1;
}
if(pthread_mutex_init(&barrier->mutex, 0) < 0) {
return -1;
}
if(pthread_cond_init(&barrier->cond, 0) < 0) {
pthread_mutex_destroy(&barrier->mutex);
return -1;
}
barrier->trip_count = count;
barrier->count = 0;
return 0;
}
static int pthread_barrier_destroy(pthread_barrier_t *barrier)
{
pthread_cond_destroy(&barrier->cond);
pthread_mutex_destroy(&barrier->mutex);
return 0;
}
static int pthread_barrier_wait(pthread_barrier_t *barrier)
{
pthread_mutex_lock(&barrier->mutex);
++(barrier->count);
if(barrier->count >= barrier->trip_count)
{
barrier->count = 0;
pthread_cond_broadcast(&barrier->cond);
pthread_mutex_unlock(&barrier->mutex);
return 1;
}
else
{
pthread_cond_wait(&barrier->cond, &(barrier->mutex));
pthread_mutex_unlock(&barrier->mutex);
return 0;
}
}
#endif
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@ -105,6 +168,7 @@ struct hid_device_ {
pthread_cond_t condition; pthread_cond_t condition;
pthread_barrier_t barrier; /* Ensures correct startup sequence */ pthread_barrier_t barrier; /* Ensures correct startup sequence */
int shutdown_thread; int shutdown_thread;
int cancelled;
struct libusb_transfer *transfer; struct libusb_transfer *transfer;
/* List of received input reports. */ /* List of received input reports. */
@ -249,9 +313,9 @@ static int get_usage(uint8_t *report_descriptor, size_t size,
} }
#endif /* INVASIVE_GET_USAGE */ #endif /* INVASIVE_GET_USAGE */
#ifdef __FreeBSD__ #if defined(__FreeBSD__) && __FreeBSD__ < 10
/* The FreeBSD version of libusb doesn't have this funciton. In mainline /* The libusb version included in FreeBSD < 10 doesn't have this function. In
libusb, it's inlined in libusb.h. This function will bear a striking mainline libusb, it's inlined in libusb.h. This function will bear a striking
resemblence to that one, because there's about one way to code it. resemblence to that one, because there's about one way to code it.
Note that the data parameter is Unicode in UTF-16LE encoding. Note that the data parameter is Unicode in UTF-16LE encoding.
@ -325,8 +389,9 @@ static wchar_t *get_usb_string(libusb_device_handle *dev, uint8_t idx)
char buf[512]; char buf[512];
int len; int len;
wchar_t *str = NULL; wchar_t *str = NULL;
wchar_t wbuf[256];
#ifndef __ANDROID__ /* we don't use iconv on Android */
wchar_t wbuf[256];
/* iconv variables */ /* iconv variables */
iconv_t ic; iconv_t ic;
size_t inbytes; size_t inbytes;
@ -338,6 +403,7 @@ static wchar_t *get_usb_string(libusb_device_handle *dev, uint8_t idx)
char *inptr; char *inptr;
#endif #endif
char *outptr; char *outptr;
#endif
/* Determine which language to use. */ /* Determine which language to use. */
uint16_t lang; uint16_t lang;
@ -354,6 +420,25 @@ static wchar_t *get_usb_string(libusb_device_handle *dev, uint8_t idx)
if (len < 0) if (len < 0)
return NULL; return NULL;
#ifdef __ANDROID__
/* Bionic does not have iconv support nor wcsdup() function, so it
has to be done manually. The following code will only work for
code points that can be represented as a single UTF-16 character,
and will incorrectly convert any code points which require more
than one UTF-16 character.
Skip over the first character (2-bytes). */
len -= 2;
str = malloc((len / 2 + 1) * sizeof(wchar_t));
int i;
for (i = 0; i < len / 2; i++) {
str[i] = buf[i * 2 + 2] | (buf[i * 2 + 3] << 8);
}
str[len / 2] = 0x00000000;
#else
/* buf does not need to be explicitly NULL-terminated because /* buf does not need to be explicitly NULL-terminated because
it is only passed into iconv() which does not need it. */ it is only passed into iconv() which does not need it. */
@ -387,6 +472,8 @@ static wchar_t *get_usb_string(libusb_device_handle *dev, uint8_t idx)
err: err:
iconv_close(ic); iconv_close(ic);
#endif
return str; return str;
} }
@ -618,7 +705,8 @@ hid_device * hid_open(unsigned short vendor_id, unsigned short product_id, const
if (cur_dev->vendor_id == vendor_id && if (cur_dev->vendor_id == vendor_id &&
cur_dev->product_id == product_id) { cur_dev->product_id == product_id) {
if (serial_number) { if (serial_number) {
if (wcscmp(serial_number, cur_dev->serial_number) == 0) { if (cur_dev->serial_number &&
wcscmp(serial_number, cur_dev->serial_number) == 0) {
path_to_open = cur_dev->path; path_to_open = cur_dev->path;
break; break;
} }
@ -683,10 +771,12 @@ static void read_callback(struct libusb_transfer *transfer)
} }
else if (transfer->status == LIBUSB_TRANSFER_CANCELLED) { else if (transfer->status == LIBUSB_TRANSFER_CANCELLED) {
dev->shutdown_thread = 1; dev->shutdown_thread = 1;
dev->cancelled = 1;
return; return;
} }
else if (transfer->status == LIBUSB_TRANSFER_NO_DEVICE) { else if (transfer->status == LIBUSB_TRANSFER_NO_DEVICE) {
dev->shutdown_thread = 1; dev->shutdown_thread = 1;
dev->cancelled = 1;
return; return;
} }
else if (transfer->status == LIBUSB_TRANSFER_TIMED_OUT) { else if (transfer->status == LIBUSB_TRANSFER_TIMED_OUT) {
@ -701,6 +791,7 @@ static void read_callback(struct libusb_transfer *transfer)
if (res != 0) { if (res != 0) {
LOG("Unable to submit URB. libusb error code: %d\n", res); LOG("Unable to submit URB. libusb error code: %d\n", res);
dev->shutdown_thread = 1; dev->shutdown_thread = 1;
dev->cancelled = 1;
} }
} }
@ -750,10 +841,10 @@ static void *read_thread(void *param)
/* Cancel any transfer that may be pending. This call will fail /* Cancel any transfer that may be pending. This call will fail
if no transfers are pending, but that's OK. */ if no transfers are pending, but that's OK. */
if (libusb_cancel_transfer(dev->transfer) == 0) { libusb_cancel_transfer(dev->transfer);
/* The transfer was cancelled, so wait for its completion. */
libusb_handle_events(usb_context); while (!dev->cancelled)
} libusb_handle_events_completed(usb_context, &dev->cancelled);
/* Now that the read thread is stopping, Wake any threads which are /* Now that the read thread is stopping, Wake any threads which are
waiting on data (in hid_read_timeout()). Do this under a mutex to waiting on data (in hid_read_timeout()). Do this under a mutex to
@ -786,11 +877,11 @@ hid_device * HID_API_EXPORT hid_open_path(const char *path)
int d = 0; int d = 0;
int good_open = 0; int good_open = 0;
dev = new_hid_device();
if(hid_init() < 0) if(hid_init() < 0)
return NULL; return NULL;
dev = new_hid_device();
libusb_get_device_list(usb_context, &devs); libusb_get_device_list(usb_context, &devs);
while ((usb_dev = devs[d++]) != NULL) { while ((usb_dev = devs[d++]) != NULL) {
struct libusb_device_descriptor desc; struct libusb_device_descriptor desc;
@ -1205,9 +1296,9 @@ int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *dev, int string_index
} }
HID_API_EXPORT const wchar_t * HID_API_CALL hid_error(hid_device *dev __attribute__ ((unused))) HID_API_EXPORT const wchar_t * HID_API_CALL hid_error(hid_device *dev)
{ {
return NULL; return NULL;
} }

View File

@ -12,7 +12,7 @@
At the discretion of the user of this library, At the discretion of the user of this library,
this software may be licensed under the terms of the this software may be licensed under the terms of the
GNU Public License v3, a BSD-Style license, or the GNU General Public License v3, a BSD-Style license, or the
original HIDAPI license as outlined in the LICENSE.txt, original HIDAPI license as outlined in the LICENSE.txt,
LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt
files located at the root of the source distribution. files located at the root of the source distribution.
@ -80,6 +80,27 @@ struct hid_device_ {
static __u32 kernel_version = 0; static __u32 kernel_version = 0;
static __u32 detect_kernel_version(void)
{
struct utsname name;
int major, minor, release;
int ret;
uname(&name);
ret = sscanf(name.release, "%d.%d.%d", &major, &minor, &release);
if (ret == 3) {
return KERNEL_VERSION(major, minor, release);
}
ret = sscanf(name.release, "%d.%d", &major, &minor);
if (ret == 2) {
return KERNEL_VERSION(major, minor, 0);
}
printf("Couldn't determine kernel version from version string \"%s\"\n", name.release);
return 0;
}
static hid_device *new_hid_device(void) static hid_device *new_hid_device(void)
{ {
hid_device *dev = calloc(1, sizeof(hid_device)); hid_device *dev = calloc(1, sizeof(hid_device));
@ -345,6 +366,8 @@ int HID_API_EXPORT hid_init(void)
if (!locale) if (!locale)
setlocale(LC_CTYPE, ""); setlocale(LC_CTYPE, "");
kernel_version = detect_kernel_version();
return 0; return 0;
} }
@ -600,21 +623,6 @@ hid_device * HID_API_EXPORT hid_open_path(const char *path)
dev = new_hid_device(); dev = new_hid_device();
if (kernel_version == 0) {
struct utsname name;
int major, minor, release;
int ret;
uname(&name);
ret = sscanf(name.release, "%d.%d.%d", &major, &minor, &release);
if (ret == 3) {
kernel_version = major << 16 | minor << 8 | release;
//printf("Kernel Version: %d\n", kernel_version);
}
else {
printf("Couldn't sscanf() version string %s\n", name.release);
}
}
/* OPEN HERE */ /* OPEN HERE */
dev->device_handle = open(path, O_RDWR); dev->device_handle = open(path, O_RDWR);
@ -700,6 +708,7 @@ int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t
bytes_read = 0; bytes_read = 0;
if (bytes_read >= 0 && if (bytes_read >= 0 &&
kernel_version != 0 &&
kernel_version < KERNEL_VERSION(2,6,34) && kernel_version < KERNEL_VERSION(2,6,34) &&
dev->uses_numbered_reports) { dev->uses_numbered_reports) {
/* Work around a kernel bug. Chop off the first byte. */ /* Work around a kernel bug. Chop off the first byte. */

View File

@ -11,7 +11,7 @@
At the discretion of the user of this library, At the discretion of the user of this library,
this software may be licensed under the terms of the this software may be licensed under the terms of the
GNU Public License v3, a BSD-Style license, or the GNU General Public License v3, a BSD-Style license, or the
original HIDAPI license as outlined in the LICENSE.txt, original HIDAPI license as outlined in the LICENSE.txt,
LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt
files located at the root of the source distribution. files located at the root of the source distribution.
@ -24,7 +24,6 @@
#include <IOKit/hid/IOHIDManager.h> #include <IOKit/hid/IOHIDManager.h>
#include <IOKit/hid/IOHIDKeys.h> #include <IOKit/hid/IOHIDKeys.h>
#include <IOKit/IOKitLib.h>
#include <CoreFoundation/CoreFoundation.h> #include <CoreFoundation/CoreFoundation.h>
#include <wchar.h> #include <wchar.h>
#include <locale.h> #include <locale.h>
@ -265,6 +264,46 @@ static int get_string_property(IOHIDDeviceRef device, CFStringRef prop, wchar_t
} }
static int get_string_property_utf8(IOHIDDeviceRef device, CFStringRef prop, char *buf, size_t len)
{
CFStringRef str;
if (!len)
return 0;
str = IOHIDDeviceGetProperty(device, prop);
buf[0] = 0;
if (str) {
len--;
CFIndex str_len = CFStringGetLength(str);
CFRange range;
range.location = 0;
range.length = str_len;
CFIndex used_buf_len;
CFIndex chars_copied;
chars_copied = CFStringGetBytes(str,
range,
kCFStringEncodingUTF8,
(char)'?',
FALSE,
(UInt8*)buf,
len,
&used_buf_len);
if (used_buf_len == len)
buf[len] = 0; /* len is decremented above */
else
buf[used_buf_len] = 0;
return used_buf_len;
}
else
return 0;
}
static int get_serial_number(IOHIDDeviceRef device, wchar_t *buf, size_t len) static int get_serial_number(IOHIDDeviceRef device, wchar_t *buf, size_t len)
{ {
return get_string_property(device, CFSTR(kIOHIDSerialNumberKey), buf, len); return get_string_property(device, CFSTR(kIOHIDSerialNumberKey), buf, len);
@ -291,54 +330,33 @@ static wchar_t *dup_wcs(const wchar_t *s)
return ret; return ret;
} }
#if MAC_OS_X_VERSION_MIN_REQUIRED != MAC_OS_X_VERSION_10_5
#warning "hidapi must be compiled/linked with -mmacosx-version-min=10.5 if you want OS X 10.5 compatibility"
#endif
/* hidapi_IOHIDDeviceGetService() static int make_path(IOHIDDeviceRef device, char *buf, size_t len)
*
* Return the io_service_t corresponding to a given IOHIDDeviceRef, either by:
* - on OS X 10.6 and above, calling IOHIDDeviceGetService()
* - on OS X 10.5, extract it from the IOHIDDevice struct
*/
static io_service_t hidapi_IOHIDDeviceGetService(IOHIDDeviceRef device)
{ {
/* When compiled with '-mmacosx-version-min=10.5', IOHIDDeviceGetService() int res;
* is weakly linked in so we can decide to use it (or not) at runtime. unsigned short vid, pid;
*/ char transport[32];
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1060 int32_t location;
if (IOHIDDeviceGetService != NULL) {
/* OS X 10.6 and above: IOHIDDeviceGetService() exists */
return IOHIDDeviceGetService(device);
}
else
#endif
{
/* OS X 10.5: IOHIDDeviceGetService() doesn't exist.
* Be naughty and pull the service out of the IOHIDDevice.
* Tested and working on OS X 10.5.8 i386, x86_64, and ppc
*/
struct IOHIDDevice_internal {
/* The first field of the IOHIDDevice struct is a
* CFRuntimeBase (which is a private CF struct).
*
* a, b, and c are the 3 fields that make up a CFRuntimeBase.
* See http://opensource.apple.com/source/CF/CF-476.18/CFRuntime.h
*
* The second field of the IOHIDDevice is the io_service_t we're looking for.
*/
//CFRuntimeBase base;
uintptr_t a;
uint8_t b[4];
#if __LP64__
uint32_t c;
#endif
io_service_t service;
};
struct IOHIDDevice_internal *tmp = (struct IOHIDDevice_internal *)device;
return tmp->service; buf[0] = '\0';
}
res = get_string_property_utf8(
device, CFSTR(kIOHIDTransportKey),
transport, sizeof(transport));
if (!res)
return -1;
location = get_location_id(device);
vid = get_vendor_id(device);
pid = get_product_id(device);
res = snprintf(buf, len, "%s_%04hx_%04hx_%x",
transport, vid, pid, location);
buf[len-1] = '\0';
return res+1;
} }
/* Initialize the IOHIDManager. Return 0 for success and -1 for failure. */ /* Initialize the IOHIDManager. Return 0 for success and -1 for failure. */
@ -402,6 +420,7 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id,
process_pending_events(); process_pending_events();
/* Get a list of the Devices */ /* Get a list of the Devices */
IOHIDManagerSetDeviceMatching(hid_mgr, NULL);
CFSetRef device_set = IOHIDManagerCopyDevices(hid_mgr); CFSetRef device_set = IOHIDManagerCopyDevices(hid_mgr);
/* Convert the list into a C array so we can iterate easily. */ /* Convert the list into a C array so we can iterate easily. */
@ -415,6 +434,7 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id,
unsigned short dev_pid; unsigned short dev_pid;
#define BUF_LEN 256 #define BUF_LEN 256
wchar_t buf[BUF_LEN]; wchar_t buf[BUF_LEN];
char cbuf[BUF_LEN];
IOHIDDeviceRef dev = device_array[i]; IOHIDDeviceRef dev = device_array[i];
@ -428,9 +448,7 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id,
if ((vendor_id == 0x0 || vendor_id == dev_vid) && if ((vendor_id == 0x0 || vendor_id == dev_vid) &&
(product_id == 0x0 || product_id == dev_pid)) { (product_id == 0x0 || product_id == dev_pid)) {
struct hid_device_info *tmp; struct hid_device_info *tmp;
io_object_t iokit_dev; size_t len;
kern_return_t res;
io_string_t path;
/* VID/PID match. Create the record. */ /* VID/PID match. Create the record. */
tmp = malloc(sizeof(struct hid_device_info)); tmp = malloc(sizeof(struct hid_device_info));
@ -448,14 +466,8 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id,
/* Fill out the record */ /* Fill out the record */
cur_dev->next = NULL; cur_dev->next = NULL;
len = make_path(dev, cbuf, sizeof(cbuf));
/* Fill in the path (IOService plane) */ cur_dev->path = strdup(cbuf);
iokit_dev = hidapi_IOHIDDeviceGetService(dev);
res = IORegistryEntryGetPath(iokit_dev, kIOServicePlane, path);
if (res == KERN_SUCCESS)
cur_dev->path = strdup(path);
else
cur_dev->path = strdup("");
/* Serial Number */ /* Serial Number */
get_serial_number(dev, buf, BUF_LEN); get_serial_number(dev, buf, BUF_LEN);
@ -669,77 +681,76 @@ static void *read_thread(void *param)
return NULL; return NULL;
} }
/* hid_open_path()
*
* path must be a valid path to an IOHIDDevice in the IOService plane
* Example: "IOService:/AppleACPIPlatformExpert/PCI0@0/AppleACPIPCI/EHC1@1D,7/AppleUSBEHCI/PLAYSTATION(R)3 Controller@fd120000/IOUSBInterface@0/IOUSBHIDDriver"
*/
hid_device * HID_API_EXPORT hid_open_path(const char *path) hid_device * HID_API_EXPORT hid_open_path(const char *path)
{ {
int i;
hid_device *dev = NULL; hid_device *dev = NULL;
io_registry_entry_t entry = MACH_PORT_NULL; CFIndex num_devices;
dev = new_hid_device(); dev = new_hid_device();
/* Set up the HID Manager if it hasn't been done */ /* Set up the HID Manager if it hasn't been done */
if (hid_init() < 0) if (hid_init() < 0)
return NULL; return NULL;
/* Get the IORegistry entry for the given path */ /* give the IOHIDManager a chance to update itself */
entry = IORegistryEntryFromPath(kIOMasterPortDefault, path); process_pending_events();
if (entry == MACH_PORT_NULL) {
/* Path wasn't valid (maybe device was removed?) */
goto return_error;
}
/* Create an IOHIDDevice for the entry */ CFSetRef device_set = IOHIDManagerCopyDevices(hid_mgr);
dev->device_handle = IOHIDDeviceCreate(kCFAllocatorDefault, entry);
if (dev->device_handle == NULL) {
/* Error creating the HID device */
goto return_error;
}
/* Open the IOHIDDevice */ num_devices = CFSetGetCount(device_set);
IOReturn ret = IOHIDDeviceOpen(dev->device_handle, kIOHIDOptionsTypeSeizeDevice); IOHIDDeviceRef *device_array = calloc(num_devices, sizeof(IOHIDDeviceRef));
if (ret == kIOReturnSuccess) { CFSetGetValues(device_set, (const void **) device_array);
char str[32]; for (i = 0; i < num_devices; i++) {
char cbuf[BUF_LEN];
size_t len;
IOHIDDeviceRef os_dev = device_array[i];
/* Create the buffers for receiving data */ len = make_path(os_dev, cbuf, sizeof(cbuf));
dev->max_input_report_len = (CFIndex) get_max_report_length(dev->device_handle); if (!strcmp(cbuf, path)) {
dev->input_report_buf = calloc(dev->max_input_report_len, sizeof(uint8_t)); /* Matched Paths. Open this Device. */
IOReturn ret = IOHIDDeviceOpen(os_dev, kIOHIDOptionsTypeSeizeDevice);
if (ret == kIOReturnSuccess) {
char str[32];
/* Create the Run Loop Mode for this device. free(device_array);
printing the reference seems to work. */ CFRetain(os_dev);
sprintf(str, "HIDAPI_%p", dev->device_handle); CFRelease(device_set);
dev->run_loop_mode = dev->device_handle = os_dev;
CFStringCreateWithCString(NULL, str, kCFStringEncodingASCII);
/* Attach the device to a Run Loop */
IOHIDDeviceRegisterInputReportCallback(
dev->device_handle, dev->input_report_buf, dev->max_input_report_len,
&hid_report_callback, dev);
IOHIDDeviceRegisterRemovalCallback(dev->device_handle, hid_device_removal_callback, dev);
/* Start the read thread */ /* Create the buffers for receiving data */
pthread_create(&dev->thread, NULL, read_thread, dev); dev->max_input_report_len = (CFIndex) get_max_report_length(os_dev);
dev->input_report_buf = calloc(dev->max_input_report_len, sizeof(uint8_t));
/* Wait here for the read thread to be initialized. */ /* Create the Run Loop Mode for this device.
pthread_barrier_wait(&dev->barrier); printing the reference seems to work. */
sprintf(str, "HIDAPI_%p", os_dev);
IOObjectRelease(entry); dev->run_loop_mode =
return dev; CFStringCreateWithCString(NULL, str, kCFStringEncodingASCII);
}
else { /* Attach the device to a Run Loop */
goto return_error; IOHIDDeviceRegisterInputReportCallback(
os_dev, dev->input_report_buf, dev->max_input_report_len,
&hid_report_callback, dev);
IOHIDDeviceRegisterRemovalCallback(dev->device_handle, hid_device_removal_callback, dev);
/* Start the read thread */
pthread_create(&dev->thread, NULL, read_thread, dev);
/* Wait here for the read thread to be initialized. */
pthread_barrier_wait(&dev->barrier);
return dev;
}
else {
goto return_error;
}
}
} }
return_error: return_error:
if (dev->device_handle != NULL) free(device_array);
CFRelease(dev->device_handle); CFRelease(device_set);
if (entry != MACH_PORT_NULL)
IOObjectRelease(entry);
free_hid_device(dev); free_hid_device(dev);
return NULL; return NULL;
} }

View File

@ -49,7 +49,26 @@
<field name="FlightModeAssistMap" units="" type="enum" <field name="FlightModeAssistMap" units="" type="enum"
options="None,GPSAssist" options="None,GPSAssist"
elements="6" elements="6"
defaultvalue="None,None,None,None,None,None"/> defaultvalue="None,None,None,None,None,None"
limits="\
%0401NE:GPSAssist,\
%0402NE:GPSAssist;\
\
%0401NE:GPSAssist,\
%0402NE:GPSAssist;\
\
%0401NE:GPSAssist,\
%0402NE:GPSAssist;\
\
%0401NE:GPSAssist,\
%0402NE:GPSAssist;\
\
%0401NE:GPSAssist,\
%0402NE:GPSAssist;\
\
%0401NE:GPSAssist,\
%0402NE:GPSAssist;"
/>
<access gcs="readwrite" flight="readwrite"/> <access gcs="readwrite" flight="readwrite"/>
<telemetrygcs acked="true" updatemode="onchange" period="0"/> <telemetrygcs acked="true" updatemode="onchange" period="0"/>