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 |