Chromium Code Reviews| 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 SuddenMotionSensor::kGenericSenso r = { |
|
Leandro Graciá Gil
2012/03/28 14:22:44
More than 80 chars.
hans
2012/03/28 14:57:55
Done.
| |
| 105 AccelerometerMac::kGenericSensor = { | |
| 106 "SMCMotionSensor", 2, | 102 "SMCMotionSensor", 2, |
| 107 0, 251, | 103 0, 251, |
| 108 5, 40 | 104 5, 40 |
| 109 }; | 105 }; |
| 110 | 106 |
| 111 // Supported sensor descriptors. Add entries here to enhance compatibility. | 107 // Supported sensor descriptors. Add entries here to enhance compatibility. |
| 112 // Tested in order; place more specific entries before more general ones. (All | 108 // Tested in order; place more specific entries before more general ones. (All |
| 113 // non-tested entries from SMSLib have been removed.) | 109 // non-tested entries from SMSLib have been removed.) |
| 114 const AccelerometerMac::SensorDescriptor | 110 const SuddenMotionSensor::SensorDescriptor |
| 115 AccelerometerMac::kSupportedSensors[] = { | 111 SuddenMotionSensor::kSupportedSensors[] = { |
| 116 // Tested by tommyw on a 13" MacBook. | 112 // Tested by tommyw on a 13" MacBook. |
| 117 { "MacBook1,1", NULL, { { 0, true }, { 2, true }, { 4, false } } }, | 113 { "MacBook1,1", NULL, { { 0, true }, { 2, true }, { 4, false } } }, |
| 118 | 114 |
| 119 // Tested by S.Selz. (via avi) on a 13" MacBook. | 115 // Tested by S.Selz. (via avi) on a 13" MacBook. |
| 120 { "MacBook2,1", NULL, { { 0, true }, { 2, false }, { 4, true } } }, | 116 { "MacBook2,1", NULL, { { 0, true }, { 2, false }, { 4, true } } }, |
| 121 | 117 |
| 122 // Tested by verhees on a 13" MacBook. | 118 // Tested by verhees on a 13" MacBook. |
| 123 { "MacBook3,1", NULL, { { 0, true }, { 2, true }, { 4, false } } }, | 119 { "MacBook3,1", NULL, { { 0, true }, { 2, true }, { 4, false } } }, |
| 124 | 120 |
| 125 // Tested by adlr on a 13" MacBook. | 121 // Tested by adlr on a 13" MacBook. |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 205 | 201 |
| 206 // Tested by avi on a 17" MacBook Pro. | 202 // Tested by avi on a 17" MacBook Pro. |
| 207 { "MacBookPro8,3", NULL, { { 0, false }, { 2, false }, { 4, false } } }, | 203 { "MacBookPro8,3", NULL, { { 0, false }, { 2, false }, { 4, false } } }, |
| 208 | 204 |
| 209 // Generic MacBook accelerometer sensor data, to be used for future models | 205 // 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 | 206 // until they can be tested and their data entered. Note that this generic |
| 211 // configuration may well have problems with inverted axes. | 207 // configuration may well have problems with inverted axes. |
| 212 { "", NULL, { { 0, true }, { 2, true }, { 4, false } } } | 208 { "", NULL, { { 0, true }, { 2, true }, { 4, false } } } |
| 213 }; | 209 }; |
| 214 | 210 |
| 215 // Create a AccelerometerMac object and return NULL if no valid sensor found. | 211 // Create a SuddenMotionSensor object and return NULL if no valid sensor found. |
| 216 DataFetcher* AccelerometerMac::Create() { | 212 SuddenMotionSensor* SuddenMotionSensor::Create() { |
| 217 scoped_ptr<AccelerometerMac> accelerometer(new AccelerometerMac); | 213 scoped_ptr<SuddenMotionSensor> accelerometer(new SuddenMotionSensor); |
| 218 return accelerometer->Init() ? accelerometer.release() : NULL; | 214 return accelerometer->Init() ? accelerometer.release() : NULL; |
| 219 } | 215 } |
| 220 | 216 |
| 221 AccelerometerMac::~AccelerometerMac() { | 217 SuddenMotionSensor::~SuddenMotionSensor() { |
| 222 IOServiceClose(io_connection_); | 218 IOServiceClose(io_connection_); |
| 223 } | 219 } |
| 224 | 220 |
| 225 AccelerometerMac::AccelerometerMac() | 221 SuddenMotionSensor::SuddenMotionSensor() |
| 226 : sensor_(NULL), | 222 : sensor_(NULL), |
| 227 io_connection_(0) { | 223 io_connection_(0) { |
| 228 } | 224 } |
| 229 | 225 |
| 230 // Retrieve per-axis accelerometer values. | 226 // Retrieve per-axis accelerometer values. |
| 231 // | 227 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_); | 228 DCHECK(sensor_); |
| 241 | 229 |
| 242 // Reset output record memory buffer. | 230 // Reset output record memory buffer. |
| 243 std::fill(output_record_.begin(), output_record_.end(), 0x00); | 231 std::fill(output_record_.begin(), output_record_.end(), 0x00); |
| 244 | 232 |
| 245 // Read record data from memory. | 233 // Read record data from memory. |
| 246 const size_t kInputSize = kGenericSensor.record_size; | 234 const size_t kInputSize = kGenericSensor.record_size; |
| 247 size_t output_size = kGenericSensor.record_size; | 235 size_t output_size = kGenericSensor.record_size; |
| 248 | 236 |
| 249 if (IOConnectCallStructMethod(io_connection_, kGenericSensor.function, | 237 if (IOConnectCallStructMethod(io_connection_, kGenericSensor.function, |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 278 if (axis_value[i] < -1.0) | 266 if (axis_value[i] < -1.0) |
| 279 axis_value[i] = -1.0; | 267 axis_value[i] = -1.0; |
| 280 else if (axis_value[i] > 1.0) | 268 else if (axis_value[i] > 1.0) |
| 281 axis_value[i] = 1.0; | 269 axis_value[i] = 1.0; |
| 282 | 270 |
| 283 // Apply axis inversion. | 271 // Apply axis inversion. |
| 284 if (sensor_->axis[i].inverted) | 272 if (sensor_->axis[i].inverted) |
| 285 axis_value[i] = -axis_value[i]; | 273 axis_value[i] = -axis_value[i]; |
| 286 } | 274 } |
| 287 | 275 |
| 288 // Transform the accelerometer values to W3C draft angles. | 276 axes[0] = axis_value[0]; |
| 289 // | 277 axes[1] = axis_value[1]; |
| 290 // Accelerometer values are just dot products of the sensor axes | 278 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 | 279 |
| 337 return true; | 280 return true; |
| 338 } | 281 } |
| 339 | 282 |
| 340 // Probe the local hardware looking for a supported sensor device | 283 // Probe the local hardware looking for a supported sensor device |
| 341 // and initialize an I/O connection to it. | 284 // and initialize an I/O connection to it. |
| 342 bool AccelerometerMac::Init() { | 285 bool SuddenMotionSensor::Init() { |
| 343 // Request model name from the kernel. | 286 // Request model name from the kernel. |
| 344 char local_model[32]; // size from SMSLib | 287 char local_model[32]; // size from SMSLib |
| 345 size_t local_model_size = sizeof(local_model); | 288 size_t local_model_size = sizeof(local_model); |
| 346 int params[2] = { CTL_HW, HW_MODEL }; | 289 int params[2] = { CTL_HW, HW_MODEL }; |
| 347 if (sysctl(params, 2, local_model, &local_model_size, NULL, 0) != 0) | 290 if (sysctl(params, 2, local_model, &local_model_size, NULL, 0) != 0) |
| 348 return NULL; | 291 return NULL; |
| 349 | 292 |
| 350 const SensorDescriptor* sensor_candidate = NULL; | 293 const SensorDescriptor* sensor_candidate = NULL; |
| 351 | 294 |
| 352 // Look for the current model in the supported sensor list. | 295 // Look for the current model in the supported sensor list. |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 419 } | 362 } |
| 420 | 363 |
| 421 if (sensor_ == NULL) | 364 if (sensor_ == NULL) |
| 422 return false; | 365 return false; |
| 423 | 366 |
| 424 // Allocate and initialize input/output records. | 367 // Allocate and initialize input/output records. |
| 425 input_record_.resize(kGenericSensor.record_size, 0x01); | 368 input_record_.resize(kGenericSensor.record_size, 0x01); |
| 426 output_record_.resize(kGenericSensor.record_size, 0x00); | 369 output_record_.resize(kGenericSensor.record_size, 0x00); |
| 427 | 370 |
| 428 // Try to retrieve the current orientation. | 371 // Try to retrieve the current orientation. |
| 429 Orientation test_orientation; | 372 float test_axes[3]; |
| 430 return GetOrientation(&test_orientation); | 373 return ReadSensorValues(test_axes); |
| 431 } | 374 } |
| 432 | 375 |
| 433 // Extend the sign of an integer of less than 32 bits to a 32-bit integer. | 376 // 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) { | 377 int SuddenMotionSensor::ExtendSign(int value, size_t size) { |
| 435 switch (size) { | 378 switch (size) { |
| 436 case 1: | 379 case 1: |
| 437 if (value & 0x00000080) | 380 if (value & 0x00000080) |
| 438 return value | 0xffffff00; | 381 return value | 0xffffff00; |
| 439 break; | 382 break; |
| 440 | 383 |
| 441 case 2: | 384 case 2: |
| 442 if (value & 0x00008000) | 385 if (value & 0x00008000) |
| 443 return value | 0xffff0000; | 386 return value | 0xffff0000; |
| 444 break; | 387 break; |
| 445 | 388 |
| 446 case 3: | 389 case 3: |
| 447 if (value & 0x00800000) | 390 if (value & 0x00800000) |
| 448 return value | 0xff000000; | 391 return value | 0xff000000; |
| 449 break; | 392 break; |
| 450 | 393 |
| 451 default: | 394 default: |
| 452 LOG(FATAL) << "Invalid integer size for sign extension: " << size; | 395 LOG(FATAL) << "Invalid integer size for sign extension: " << size; |
| 453 } | 396 } |
| 454 | 397 |
| 455 return value; | 398 return value; |
| 456 } | 399 } |
| 457 | |
| 458 } // namespace device_orientation | |
| OLD | NEW |