hal/cocoa/CocoaSensor.mm

changeset 0
6474c204b198
     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

mercurial