1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/hal/cocoa/CocoaSensor.mm Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,149 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this file, 1.6 + * You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 +#include "Hal.h" 1.8 +#include "nsITimer.h" 1.9 +#include "smslib.h" 1.10 +#include "nsComponentManagerUtils.h" 1.11 + 1.12 +#include <mach/mach.h> 1.13 +#include <cmath> 1.14 +#import <IOKit/IOKitLib.h> 1.15 + 1.16 +#define MEAN_GRAVITY 9.80665 1.17 +#define DEFAULT_SENSOR_POLL 100 1.18 +using namespace mozilla::hal; 1.19 +namespace mozilla { 1.20 +namespace hal_impl { 1.21 +static nsITimer* sUpdateTimer = nullptr; 1.22 +static bool sActiveSensors[NUM_SENSOR_TYPE]; 1.23 +static io_connect_t sDataPort = IO_OBJECT_NULL; 1.24 +static uint64_t sLastMean = -1; 1.25 +static float 1.26 +LMUvalueToLux(uint64_t aValue) 1.27 +{ 1.28 + //Conversion formula from regression. See Bug 793728. 1.29 + // -3*(10^-27)*x^4 + 2.6*(10^-19)*x^3 + -3.4*(10^-12)*x^2 + 3.9*(10^-5)*x - 0.19 1.30 + long double powerC4 = 1/pow((long double)10,27); 1.31 + long double powerC3 = 1/pow((long double)10,19); 1.32 + long double powerC2 = 1/pow((long double)10,12); 1.33 + long double powerC1 = 1/pow((long double)10,5); 1.34 + 1.35 + long double term4 = -3.0 * powerC4 * pow(aValue,4); 1.36 + long double term3 = 2.6 * powerC3 * pow(aValue,3); 1.37 + long double term2 = -3.4 * powerC2 * pow(aValue,2); 1.38 + long double term1 = 3.9 * powerC1 * aValue; 1.39 + 1.40 + float lux = ceil(static_cast<float>(term4 + term3 + term2 + term1 - 0.19)); 1.41 + return lux > 0 ? lux : 0; 1.42 +} 1.43 +void 1.44 +UpdateHandler(nsITimer *aTimer, void *aClosure) 1.45 +{ 1.46 + for (int i = 0; i < NUM_SENSOR_TYPE; i++) { 1.47 + if (!sActiveSensors[i]) { 1.48 + continue; 1.49 + } 1.50 + SensorType sensor = static_cast<SensorType>(i); 1.51 + InfallibleTArray<float> values; 1.52 + if (sensor == SENSOR_ACCELERATION) { 1.53 + sms_acceleration accel; 1.54 + smsGetData(&accel); 1.55 + 1.56 + values.AppendElement(accel.x * MEAN_GRAVITY); 1.57 + values.AppendElement(accel.y * MEAN_GRAVITY); 1.58 + values.AppendElement(accel.z * MEAN_GRAVITY); 1.59 + } else if (sensor == SENSOR_LIGHT && sDataPort != IO_OBJECT_NULL) { 1.60 + kern_return_t kr; 1.61 + uint32_t outputs = 2; 1.62 + uint64_t lightLMU[outputs]; 1.63 + 1.64 + kr = IOConnectCallMethod(sDataPort, 0, nil, 0, nil, 0, lightLMU, &outputs, nil, 0); 1.65 + if (kr == KERN_SUCCESS) { 1.66 + uint64_t mean = (lightLMU[0] + lightLMU[1]) / 2; 1.67 + if (mean == sLastMean) { 1.68 + continue; 1.69 + } 1.70 + sLastMean = mean; 1.71 + values.AppendElement(LMUvalueToLux(mean)); 1.72 + } else if (kr == kIOReturnBusy) { 1.73 + continue; 1.74 + } 1.75 + } 1.76 + 1.77 + hal::SensorData sdata(sensor, 1.78 + PR_Now(), 1.79 + values, 1.80 + hal::SENSOR_ACCURACY_UNKNOWN); 1.81 + hal::NotifySensorChange(sdata); 1.82 + } 1.83 +} 1.84 +void 1.85 +EnableSensorNotifications(SensorType aSensor) 1.86 +{ 1.87 + if (aSensor == SENSOR_ACCELERATION) { 1.88 + int result = smsStartup(nil, nil); 1.89 + 1.90 + if (result != SMS_SUCCESS) { 1.91 + return; 1.92 + } 1.93 + 1.94 + if (!smsLoadCalibration()) { 1.95 + return; 1.96 + } 1.97 + } else if (aSensor == SENSOR_LIGHT) { 1.98 + io_service_t serviceObject; 1.99 + serviceObject = IOServiceGetMatchingService(kIOMasterPortDefault, 1.100 + IOServiceMatching("AppleLMUController")); 1.101 + if (!serviceObject) { 1.102 + return; 1.103 + } 1.104 + kern_return_t kr; 1.105 + kr = IOServiceOpen(serviceObject, mach_task_self(), 0, &sDataPort); 1.106 + IOObjectRelease(serviceObject); 1.107 + if (kr != KERN_SUCCESS) { 1.108 + return; 1.109 + } 1.110 + } else { 1.111 + NS_WARNING("EnableSensorNotifications called on an unknown sensor type"); 1.112 + return; 1.113 + } 1.114 + sActiveSensors[aSensor] = true; 1.115 + 1.116 + if (!sUpdateTimer) { 1.117 + CallCreateInstance("@mozilla.org/timer;1", &sUpdateTimer); 1.118 + if (sUpdateTimer) { 1.119 + sUpdateTimer->InitWithFuncCallback(UpdateHandler, 1.120 + nullptr, 1.121 + DEFAULT_SENSOR_POLL, 1.122 + nsITimer::TYPE_REPEATING_SLACK); 1.123 + } 1.124 + } 1.125 +} 1.126 +void 1.127 +DisableSensorNotifications(SensorType aSensor) 1.128 +{ 1.129 + if (!sActiveSensors[aSensor] || (aSensor != SENSOR_ACCELERATION && aSensor != SENSOR_LIGHT)) { 1.130 + return; 1.131 + } 1.132 + 1.133 + sActiveSensors[aSensor] = false; 1.134 + 1.135 + if (aSensor == SENSOR_ACCELERATION) { 1.136 + smsShutdown(); 1.137 + } else if (aSensor == SENSOR_LIGHT) { 1.138 + IOServiceClose(sDataPort); 1.139 + } 1.140 + // If all sensors are disabled, cancel the update timer. 1.141 + if (sUpdateTimer) { 1.142 + for (int i = 0; i < NUM_SENSOR_TYPE; i++) { 1.143 + if (sActiveSensors[i]) { 1.144 + return; 1.145 + } 1.146 + } 1.147 + sUpdateTimer->Cancel(); 1.148 + NS_RELEASE(sUpdateTimer); 1.149 + } 1.150 +} 1.151 +} // hal_impl 1.152 +} // mozilla