| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 // | 4 // |
| 5 // This file is based on the SMSLib library. | 5 // This file is based on the SMSLib library. |
| 6 // | 6 // |
| 7 // SMSLib Sudden Motion Sensor Access Library | 7 // SMSLib Sudden Motion Sensor Access Library |
| 8 // Copyright (c) 2010 Suitable Systems | 8 // Copyright (c) 2010 Suitable Systems |
| 9 // All rights reserved. | 9 // All rights reserved. |
| 10 // | 10 // |
| (...skipping 30 matching lines...) Expand all Loading... |
| 41 // | 41 // |
| 42 // For more information about SMSLib, see | 42 // For more information about SMSLib, see |
| 43 // <http://www.suitable.com/tools/smslib.html> | 43 // <http://www.suitable.com/tools/smslib.html> |
| 44 // or contact | 44 // or contact |
| 45 // Daniel Griscom | 45 // Daniel Griscom |
| 46 // Suitable Systems | 46 // Suitable Systems |
| 47 // 1 Centre Street, Suite 204 | 47 // 1 Centre Street, Suite 204 |
| 48 // Wakefield, MA 01880 | 48 // Wakefield, MA 01880 |
| 49 // (781) 665-0053 | 49 // (781) 665-0053 |
| 50 | 50 |
| 51 #include "content/browser/device_orientation/accelerometer_mac.h" | 51 #include "sudden_motion_sensor_mac.h" |
| 52 | 52 |
| 53 #include <math.h> | 53 #include <math.h> |
| 54 #include <sys/sysctl.h> | 54 #include <sys/sysctl.h> |
| 55 | 55 |
| 56 #include "base/logging.h" | 56 #include "base/logging.h" |
| 57 #include "base/mac/scoped_cftyperef.h" | 57 #include "base/mac/scoped_cftyperef.h" |
| 58 #include "base/memory/scoped_ptr.h" | 58 #include "base/memory/scoped_ptr.h" |
| 59 #include "content/browser/device_orientation/orientation.h" | |
| 60 | 59 |
| 61 namespace device_orientation { | 60 struct SuddenMotionSensor::GenericMacbookSensor { |
| 62 | |
| 63 struct AccelerometerMac::GenericMacbookSensor { | |
| 64 // Name of device to be read. | 61 // Name of device to be read. |
| 65 const char* service_name; | 62 const char* service_name; |
| 66 | 63 |
| 67 // Number of bytes of the axis data. | 64 // Number of bytes of the axis data. |
| 68 int axis_size; | 65 int axis_size; |
| 69 | 66 |
| 70 // Default calibration value for zero g. | 67 // Default calibration value for zero g. |
| 71 float zero_g; | 68 float zero_g; |
| 72 | 69 |
| 73 // Default calibration value for one g (negative when axis is inverted). | 70 // Default calibration value for one g (negative when axis is inverted). |
| 74 float one_g; | 71 float one_g; |
| 75 | 72 |
| 76 // Kernel function index. | 73 // Kernel function index. |
| 77 unsigned int function; | 74 unsigned int function; |
| 78 | 75 |
| 79 // Size of the sensor record to be sent/received. | 76 // Size of the sensor record to be sent/received. |
| 80 unsigned int record_size; | 77 unsigned int record_size; |
| 81 }; | 78 }; |
| 82 | 79 |
| 83 struct AccelerometerMac::AxisData { | 80 struct SuddenMotionSensor::AxisData { |
| 84 // Location of the first byte representing the axis in the sensor data. | 81 // Location of the first byte representing the axis in the sensor data. |
| 85 int index; | 82 int index; |
| 86 | 83 |
| 87 // Axis inversion flag. The value changes often between models. | 84 // Axis inversion flag. The value changes often between models. |
| 88 bool inverted; | 85 bool inverted; |
| 89 }; | 86 }; |
| 90 | 87 |
| 91 // Sudden Motion Sensor descriptor. | 88 // Sudden Motion Sensor descriptor. |
| 92 struct AccelerometerMac::SensorDescriptor { | 89 struct SuddenMotionSensor::SensorDescriptor { |
| 93 // Prefix of model to be tested. | 90 // Prefix of model to be tested. |
| 94 const char* model_name; | 91 const char* model_name; |
| 95 | 92 |
| 96 // Board id of model, or NULL if it doesn't matter. | 93 // Board id of model, or NULL if it doesn't matter. |
| 97 const char* board_id; | 94 const char* board_id; |
| 98 | 95 |
| 99 // Axis-specific data (x,y,z order). | 96 // Axis-specific data (x,y,z order). |
| 100 AxisData axis[3]; | 97 AxisData axis[3]; |
| 101 }; | 98 }; |
| 102 | 99 |
| 103 // Typical sensor parameters in MacBook models. | 100 // Typical sensor parameters in MacBook models. |
| 104 const AccelerometerMac::GenericMacbookSensor | 101 const SuddenMotionSensor::GenericMacbookSensor |
| 105 AccelerometerMac::kGenericSensor = { | 102 SuddenMotionSensor::kGenericSensor = { |
| 106 "SMCMotionSensor", 2, | 103 "SMCMotionSensor", 2, |
| 107 0, 251, | 104 0, 251, |
| 108 5, 40 | 105 5, 40 |
| 109 }; | 106 }; |
| 110 | 107 |
| 111 // Supported sensor descriptors. Add entries here to enhance compatibility. | 108 // Supported sensor descriptors. Add entries here to enhance compatibility. |
| 112 // Tested in order; place more specific entries before more general ones. (All | 109 // Tested in order; place more specific entries before more general ones. (All |
| 113 // non-tested entries from SMSLib have been removed.) | 110 // non-tested entries from SMSLib have been removed.) |
| 114 const AccelerometerMac::SensorDescriptor | 111 const SuddenMotionSensor::SensorDescriptor |
| 115 AccelerometerMac::kSupportedSensors[] = { | 112 SuddenMotionSensor::kSupportedSensors[] = { |
| 116 // Tested by tommyw on a 13" MacBook. | 113 // Tested by tommyw on a 13" MacBook. |
| 117 { "MacBook1,1", NULL, { { 0, true }, { 2, true }, { 4, false } } }, | 114 { "MacBook1,1", NULL, { { 0, true }, { 2, true }, { 4, false } } }, |
| 118 | 115 |
| 119 // Tested by S.Selz. (via avi) on a 13" MacBook. | 116 // Tested by S.Selz. (via avi) on a 13" MacBook. |
| 120 { "MacBook2,1", NULL, { { 0, true }, { 2, false }, { 4, true } } }, | 117 { "MacBook2,1", NULL, { { 0, true }, { 2, false }, { 4, true } } }, |
| 121 | 118 |
| 122 // Tested by verhees on a 13" MacBook. | 119 // Tested by verhees on a 13" MacBook. |
| 123 { "MacBook3,1", NULL, { { 0, true }, { 2, true }, { 4, false } } }, | 120 { "MacBook3,1", NULL, { { 0, true }, { 2, true }, { 4, false } } }, |
| 124 | 121 |
| 125 // Tested by adlr on a 13" MacBook. | 122 // Tested by adlr on a 13" MacBook. |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 205 | 202 |
| 206 // Tested by avi on a 17" MacBook Pro. | 203 // Tested by avi on a 17" MacBook Pro. |
| 207 { "MacBookPro8,3", NULL, { { 0, false }, { 2, false }, { 4, false } } }, | 204 { "MacBookPro8,3", NULL, { { 0, false }, { 2, false }, { 4, false } } }, |
| 208 | 205 |
| 209 // Generic MacBook accelerometer sensor data, to be used for future models | 206 // Generic MacBook accelerometer sensor data, to be used for future models |
| 210 // until they can be tested and their data entered. Note that this generic | 207 // until they can be tested and their data entered. Note that this generic |
| 211 // configuration may well have problems with inverted axes. | 208 // configuration may well have problems with inverted axes. |
| 212 { "", NULL, { { 0, true }, { 2, true }, { 4, false } } } | 209 { "", NULL, { { 0, true }, { 2, true }, { 4, false } } } |
| 213 }; | 210 }; |
| 214 | 211 |
| 215 // Create a AccelerometerMac object and return NULL if no valid sensor found. | 212 // Create a SuddenMotionSensor object and return NULL if no valid sensor found. |
| 216 DataFetcher* AccelerometerMac::Create() { | 213 SuddenMotionSensor* SuddenMotionSensor::Create() { |
| 217 scoped_ptr<AccelerometerMac> accelerometer(new AccelerometerMac); | 214 scoped_ptr<SuddenMotionSensor> accelerometer(new SuddenMotionSensor); |
| 218 return accelerometer->Init() ? accelerometer.release() : NULL; | 215 return accelerometer->Init() ? accelerometer.release() : NULL; |
| 219 } | 216 } |
| 220 | 217 |
| 221 AccelerometerMac::~AccelerometerMac() { | 218 SuddenMotionSensor::~SuddenMotionSensor() { |
| 222 IOServiceClose(io_connection_); | 219 IOServiceClose(io_connection_); |
| 223 } | 220 } |
| 224 | 221 |
| 225 AccelerometerMac::AccelerometerMac() | 222 SuddenMotionSensor::SuddenMotionSensor() |
| 226 : sensor_(NULL), | 223 : sensor_(NULL), |
| 227 io_connection_(0) { | 224 io_connection_(0) { |
| 228 } | 225 } |
| 229 | 226 |
| 230 // Retrieve per-axis accelerometer values. | 227 // Retrieve per-axis accelerometer values. |
| 231 // | 228 bool SuddenMotionSensor::ReadSensorValues(float axes[3]) { |
| 232 // Axes and angles are defined according to the W3C DeviceOrientation Draft. | |
| 233 // See here: http://dev.w3.org/geo/api/spec-source-orientation.html | |
| 234 // | |
| 235 // Note: only beta and gamma angles are provided. Alpha is set to zero. | |
| 236 // | |
| 237 // Returns false in case of error or non-properly initialized object. | |
| 238 // | |
| 239 bool AccelerometerMac::GetOrientation(Orientation* orientation) { | |
| 240 DCHECK(sensor_); | 229 DCHECK(sensor_); |
| 241 | 230 |
| 242 // Reset output record memory buffer. | 231 // Reset output record memory buffer. |
| 243 std::fill(output_record_.begin(), output_record_.end(), 0x00); | 232 std::fill(output_record_.begin(), output_record_.end(), 0x00); |
| 244 | 233 |
| 245 // Read record data from memory. | 234 // Read record data from memory. |
| 246 const size_t kInputSize = kGenericSensor.record_size; | 235 const size_t kInputSize = kGenericSensor.record_size; |
| 247 size_t output_size = kGenericSensor.record_size; | 236 size_t output_size = kGenericSensor.record_size; |
| 248 | 237 |
| 249 if (IOConnectCallStructMethod(io_connection_, kGenericSensor.function, | 238 if (IOConnectCallStructMethod(io_connection_, kGenericSensor.function, |
| (...skipping 28 matching lines...) Expand all Loading... |
| 278 if (axis_value[i] < -1.0) | 267 if (axis_value[i] < -1.0) |
| 279 axis_value[i] = -1.0; | 268 axis_value[i] = -1.0; |
| 280 else if (axis_value[i] > 1.0) | 269 else if (axis_value[i] > 1.0) |
| 281 axis_value[i] = 1.0; | 270 axis_value[i] = 1.0; |
| 282 | 271 |
| 283 // Apply axis inversion. | 272 // Apply axis inversion. |
| 284 if (sensor_->axis[i].inverted) | 273 if (sensor_->axis[i].inverted) |
| 285 axis_value[i] = -axis_value[i]; | 274 axis_value[i] = -axis_value[i]; |
| 286 } | 275 } |
| 287 | 276 |
| 288 // Transform the accelerometer values to W3C draft angles. | 277 axes[0] = axis_value[0]; |
| 289 // | 278 axes[1] = axis_value[1]; |
| 290 // Accelerometer values are just dot products of the sensor axes | 279 axes[2] = axis_value[2]; |
| 291 // by the gravity vector 'g' with the result for the z axis inverted. | |
| 292 // | |
| 293 // To understand this transformation calculate the 3rd row of the z-x-y | |
| 294 // Euler angles rotation matrix (because of the 'g' vector, only 3rd row | |
| 295 // affects to the result). Note that z-x-y matrix means R = Ry * Rx * Rz. | |
| 296 // Then, assume alpha = 0 and you get this: | |
| 297 // | |
| 298 // x_acc = sin(gamma) | |
| 299 // y_acc = - cos(gamma) * sin(beta) | |
| 300 // z_acc = cos(beta) * cos(gamma) | |
| 301 // | |
| 302 // After that the rest is just a bit of trigonometry. | |
| 303 // | |
| 304 // Also note that alpha can't be provided but it's assumed to be always zero. | |
| 305 // This is necessary in order to provide enough information to solve | |
| 306 // the equations. | |
| 307 // | |
| 308 const double kRad2deg = 180.0 / M_PI; | |
| 309 | |
| 310 orientation->alpha_ = 0.0; | |
| 311 orientation->beta_ = kRad2deg * atan2(-axis_value[1], axis_value[2]); | |
| 312 orientation->gamma_ = kRad2deg * asin(axis_value[0]); | |
| 313 orientation->absolute_ = false; | |
| 314 | |
| 315 // Make sure that the interval boundaries comply with the specification. At | |
| 316 // this point, beta is [-180, 180] and gamma is [-90, 90], but the spec has | |
| 317 // the upper bound open on both. | |
| 318 if (orientation->beta_ == 180.0) { | |
| 319 orientation->beta_ = -180.0; // -180 == 180 (upside-down) | |
| 320 } | |
| 321 if (orientation->gamma_ == 90.0) { | |
| 322 static double just_less_than_90 = nextafter(90, 0); | |
| 323 orientation->gamma_ = just_less_than_90; | |
| 324 } | |
| 325 | |
| 326 // At this point, DCHECKing is paranoia. Never hurts. | |
| 327 DCHECK_GE(orientation->beta_, -180.0); | |
| 328 DCHECK_LT(orientation->beta_, 180.0); | |
| 329 DCHECK_GE(orientation->gamma_, -90.0); | |
| 330 DCHECK_LT(orientation->gamma_, 90.0); | |
| 331 | |
| 332 orientation->can_provide_alpha_ = false; | |
| 333 orientation->can_provide_beta_ = true; | |
| 334 orientation->can_provide_gamma_ = true; | |
| 335 orientation->can_provide_absolute_ = false; | |
| 336 | 280 |
| 337 return true; | 281 return true; |
| 338 } | 282 } |
| 339 | 283 |
| 340 // Probe the local hardware looking for a supported sensor device | 284 // Probe the local hardware looking for a supported sensor device |
| 341 // and initialize an I/O connection to it. | 285 // and initialize an I/O connection to it. |
| 342 bool AccelerometerMac::Init() { | 286 bool SuddenMotionSensor::Init() { |
| 343 // Request model name from the kernel. | 287 // Request model name from the kernel. |
| 344 char local_model[32]; // size from SMSLib | 288 char local_model[32]; // size from SMSLib |
| 345 size_t local_model_size = sizeof(local_model); | 289 size_t local_model_size = sizeof(local_model); |
| 346 int params[2] = { CTL_HW, HW_MODEL }; | 290 int params[2] = { CTL_HW, HW_MODEL }; |
| 347 if (sysctl(params, 2, local_model, &local_model_size, NULL, 0) != 0) | 291 if (sysctl(params, 2, local_model, &local_model_size, NULL, 0) != 0) |
| 348 return NULL; | 292 return NULL; |
| 349 | 293 |
| 350 const SensorDescriptor* sensor_candidate = NULL; | 294 const SensorDescriptor* sensor_candidate = NULL; |
| 351 | 295 |
| 352 // Look for the current model in the supported sensor list. | 296 // Look for the current model in the supported sensor list. |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 419 } | 363 } |
| 420 | 364 |
| 421 if (sensor_ == NULL) | 365 if (sensor_ == NULL) |
| 422 return false; | 366 return false; |
| 423 | 367 |
| 424 // Allocate and initialize input/output records. | 368 // Allocate and initialize input/output records. |
| 425 input_record_.resize(kGenericSensor.record_size, 0x01); | 369 input_record_.resize(kGenericSensor.record_size, 0x01); |
| 426 output_record_.resize(kGenericSensor.record_size, 0x00); | 370 output_record_.resize(kGenericSensor.record_size, 0x00); |
| 427 | 371 |
| 428 // Try to retrieve the current orientation. | 372 // Try to retrieve the current orientation. |
| 429 Orientation test_orientation; | 373 float test_axes[3]; |
| 430 return GetOrientation(&test_orientation); | 374 return ReadSensorValues(test_axes); |
| 431 } | 375 } |
| 432 | 376 |
| 433 // Extend the sign of an integer of less than 32 bits to a 32-bit integer. | 377 // Extend the sign of an integer of less than 32 bits to a 32-bit integer. |
| 434 int AccelerometerMac::ExtendSign(int value, size_t size) { | 378 int SuddenMotionSensor::ExtendSign(int value, size_t size) { |
| 435 switch (size) { | 379 switch (size) { |
| 436 case 1: | 380 case 1: |
| 437 if (value & 0x00000080) | 381 if (value & 0x00000080) |
| 438 return value | 0xffffff00; | 382 return value | 0xffffff00; |
| 439 break; | 383 break; |
| 440 | 384 |
| 441 case 2: | 385 case 2: |
| 442 if (value & 0x00008000) | 386 if (value & 0x00008000) |
| 443 return value | 0xffff0000; | 387 return value | 0xffff0000; |
| 444 break; | 388 break; |
| 445 | 389 |
| 446 case 3: | 390 case 3: |
| 447 if (value & 0x00800000) | 391 if (value & 0x00800000) |
| 448 return value | 0xff000000; | 392 return value | 0xff000000; |
| 449 break; | 393 break; |
| 450 | 394 |
| 451 default: | 395 default: |
| 452 LOG(FATAL) << "Invalid integer size for sign extension: " << size; | 396 LOG(FATAL) << "Invalid integer size for sign extension: " << size; |
| 453 } | 397 } |
| 454 | 398 |
| 455 return value; | 399 return value; |
| 456 } | 400 } |
| 457 | |
| 458 } // namespace device_orientation | |
| OLD | NEW |