Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(61)

Side by Side Diff: content/browser/device_orientation/accelerometer_mac.cc

Issue 9844020: Move the Sudden Motion Sensor library into third_party. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: DEPS: convert line endings Created 8 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « content/browser/device_orientation/accelerometer_mac.h ('k') | content/content_browser.gypi » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 //
5 // This file is based on the SMSLib library.
6 //
7 // SMSLib Sudden Motion Sensor Access Library
8 // Copyright (c) 2010 Suitable Systems
9 // All rights reserved.
10 //
11 // Developed by: Daniel Griscom
12 // Suitable Systems
13 // http://www.suitable.com
14 //
15 // Permission is hereby granted, free of charge, to any person obtaining a
16 // copy of this software and associated documentation files (the
17 // "Software"), to deal with the Software without restriction, including
18 // without limitation the rights to use, copy, modify, merge, publish,
19 // distribute, sublicense, and/or sell copies of the Software, and to
20 // permit persons to whom the Software is furnished to do so, subject to
21 // the following conditions:
22 //
23 // - Redistributions of source code must retain the above copyright notice,
24 // this list of conditions and the following disclaimers.
25 //
26 // - Redistributions in binary form must reproduce the above copyright
27 // notice, this list of conditions and the following disclaimers in the
28 // documentation and/or other materials provided with the distribution.
29 //
30 // - Neither the names of Suitable Systems nor the names of its
31 // contributors may be used to endorse or promote products derived from
32 // this Software without specific prior written permission.
33 //
34 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
35 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
36 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
37 // IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR
38 // ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
39 // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
40 // SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE.
41 //
42 // For more information about SMSLib, see
43 // <http://www.suitable.com/tools/smslib.html>
44 // or contact
45 // Daniel Griscom
46 // Suitable Systems
47 // 1 Centre Street, Suite 204
48 // Wakefield, MA 01880
49 // (781) 665-0053
50 4
51 #include "content/browser/device_orientation/accelerometer_mac.h" 5 #include "content/browser/device_orientation/accelerometer_mac.h"
52 6
53 #include <math.h> 7 #include <math.h>
54 #include <sys/sysctl.h>
55 8
56 #include "base/logging.h" 9 #include "base/logging.h"
57 #include "base/mac/scoped_cftyperef.h"
58 #include "base/memory/scoped_ptr.h"
59 #include "content/browser/device_orientation/orientation.h" 10 #include "content/browser/device_orientation/orientation.h"
11 #include "third_party/sudden_motion_sensor/sudden_motion_sensor_mac.h"
60 12
61 namespace device_orientation { 13 namespace device_orientation {
62 14
63 struct AccelerometerMac::GenericMacbookSensor {
64 // Name of device to be read.
65 const char* service_name;
66
67 // Number of bytes of the axis data.
68 int axis_size;
69
70 // Default calibration value for zero g.
71 float zero_g;
72
73 // Default calibration value for one g (negative when axis is inverted).
74 float one_g;
75
76 // Kernel function index.
77 unsigned int function;
78
79 // Size of the sensor record to be sent/received.
80 unsigned int record_size;
81 };
82
83 struct AccelerometerMac::AxisData {
84 // Location of the first byte representing the axis in the sensor data.
85 int index;
86
87 // Axis inversion flag. The value changes often between models.
88 bool inverted;
89 };
90
91 // Sudden Motion Sensor descriptor.
92 struct AccelerometerMac::SensorDescriptor {
93 // Prefix of model to be tested.
94 const char* model_name;
95
96 // Board id of model, or NULL if it doesn't matter.
97 const char* board_id;
98
99 // Axis-specific data (x,y,z order).
100 AxisData axis[3];
101 };
102
103 // Typical sensor parameters in MacBook models.
104 const AccelerometerMac::GenericMacbookSensor
105 AccelerometerMac::kGenericSensor = {
106 "SMCMotionSensor", 2,
107 0, 251,
108 5, 40
109 };
110
111 // Supported sensor descriptors. Add entries here to enhance compatibility.
112 // Tested in order; place more specific entries before more general ones. (All
113 // non-tested entries from SMSLib have been removed.)
114 const AccelerometerMac::SensorDescriptor
115 AccelerometerMac::kSupportedSensors[] = {
116 // Tested by tommyw on a 13" MacBook.
117 { "MacBook1,1", NULL, { { 0, true }, { 2, true }, { 4, false } } },
118
119 // Tested by S.Selz. (via avi) on a 13" MacBook.
120 { "MacBook2,1", NULL, { { 0, true }, { 2, false }, { 4, true } } },
121
122 // Tested by verhees on a 13" MacBook.
123 { "MacBook3,1", NULL, { { 0, true }, { 2, true }, { 4, false } } },
124
125 // Tested by adlr on a 13" MacBook.
126 { "MacBook4,1", NULL, { { 0, true }, { 2, true }, { 4, false } } },
127
128 // Tested by thakis on a 13" MacBook.
129 { "MacBook5,1", NULL, { { 0, true }, { 2, true }, { 4, false } } },
130
131 // Tested by Adam Gerson (via avi) on a 13" MacBook.
132 { "MacBook5,2", NULL, { { 0, false }, { 2, true }, { 4, true } } },
133
134 // Tested by tommyw on a 13" MacBook.
135 { "MacBook6,1", NULL, { { 0, true }, { 2, true }, { 4, false } } },
136
137 // Tested by avi on a 13" MacBook.
138 { "MacBook7,1", NULL, { { 0, true }, { 2, true }, { 4, false } } },
139
140 // Tested by crc on a 13" MacBook Air.
141 { "MacBookAir1,1", NULL, { { 0, true }, { 2, true }, { 4, false } } },
142
143 // Tested by sfiera, pjw on a 13" MacBook Air.
144 { "MacBookAir2,1", NULL, { { 0, true }, { 2, true }, { 4, false } } },
145
146 // Note:
147 // - MacBookAir3,1 (11" MacBook Air, late 2010)
148 // - MacBookAir3,2 (13" MacBook Air, late 2010)
149 // - MacBookAir4,1 (11" MacBook Air, mid 2011)
150 // - MacBookAir4,2 (13" MacBook Air, mid 2011)
151 // have no accelerometer sensors.
152
153 // Tested by crc on a 15" MacBook Pro.
154 { "MacBookPro1,1", NULL, { { 0, true }, { 2, true }, { 4, false } } },
155
156 // Tested by Raul Cuza (via avi) on a 17" MacBook Pro.
157 { "MacBookPro1,2", NULL, { { 0, true }, { 2, true }, { 4, false } } },
158
159 // Tested by L.V. (via avi) on a 17" MacBook Pro.
160 { "MacBookPro2,1", NULL, { { 0, true }, { 2, false }, { 4, true } } },
161
162 // Tested by leandrogracia on a 15" MacBook Pro.
163 { "MacBookPro2,2", NULL, { { 0, true }, { 2, true }, { 4, false } } },
164
165 // Tested by S.Som. (via avi) on a 17" MacBook Pro.
166 { "MacBookPro3,1", "Mac-F42388C8",
167 { { 0, true }, { 2, false }, { 4, true } } },
168
169 // Tested by leandrogracia on a 15" MacBook Pro.
170 { "MacBookPro3,1", NULL, { { 0, false }, { 2, true }, { 4, true } } },
171
172 // Tested by leandrogracia on a 15" MacBook Pro.
173 // Tested by Eric Shapiro (via avi) on a 17" MacBook Pro.
174 { "MacBookPro4,1", NULL, { { 0, true }, { 2, true }, { 4, false } } },
175
176 // Tested by leandrogracia on a 15" MacBook Pro.
177 { "MacBookPro5,1", NULL, { { 0, false }, { 2, false }, { 4, false } } },
178
179 // Tested by S.Selz. (via avi) on a 17" MacBook Pro.
180 { "MacBookPro5,2", NULL, { { 0, false }, { 2, false }, { 4, false } } },
181
182 // Tested by dmaclach on a 15" MacBook Pro.
183 { "MacBookPro5,3", NULL, { { 2, false }, { 0, false }, { 4, true } } },
184
185 // Tested by leandrogracia on a 15" MacBook Pro.
186 { "MacBookPro5,4", NULL, { { 0, false }, { 2, false }, { 4, false } } },
187
188 // Tested by leandrogracia on a 13" MacBook Pro.
189 { "MacBookPro5,5", NULL, { { 0, true }, { 2, true }, { 4, false } } },
190
191 // Tested by khom, leadpipe on a 17" MacBook Pro.
192 { "MacBookPro6,1", NULL, { { 0, false }, { 2, false }, { 4, false } } },
193
194 // Tested by leandrogracia on a 15" MacBook Pro.
195 { "MacBookPro6,2", NULL, { { 0, true }, { 2, false }, { 4, true } } },
196
197 // Tested by leandrogracia on a 13" MacBook Pro.
198 { "MacBookPro7,1", NULL, { { 0, true }, { 2, true }, { 4, false } } },
199
200 // Tested by avi on a 13" MacBook Pro.
201 { "MacBookPro8,1", NULL, { { 0, false }, { 2, false }, { 4, false } } },
202
203 // Tested by avi on a 15" MacBook Pro.
204 { "MacBookPro8,2", NULL, { { 0, false }, { 2, false }, { 4, false } } },
205
206 // Tested by avi on a 17" MacBook Pro.
207 { "MacBookPro8,3", NULL, { { 0, false }, { 2, false }, { 4, false } } },
208
209 // 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
211 // configuration may well have problems with inverted axes.
212 { "", NULL, { { 0, true }, { 2, true }, { 4, false } } }
213 };
214
215 // Create a AccelerometerMac object and return NULL if no valid sensor found. 15 // Create a AccelerometerMac object and return NULL if no valid sensor found.
216 DataFetcher* AccelerometerMac::Create() { 16 DataFetcher* AccelerometerMac::Create() {
217 scoped_ptr<AccelerometerMac> accelerometer(new AccelerometerMac); 17 scoped_ptr<AccelerometerMac> accelerometer(new AccelerometerMac);
218 return accelerometer->Init() ? accelerometer.release() : NULL; 18 return accelerometer->Init() ? accelerometer.release() : NULL;
219 } 19 }
220 20
221 AccelerometerMac::~AccelerometerMac() { 21 AccelerometerMac::~AccelerometerMac() {
222 IOServiceClose(io_connection_);
223 } 22 }
224 23
225 AccelerometerMac::AccelerometerMac() 24 AccelerometerMac::AccelerometerMac() {
226 : sensor_(NULL),
227 io_connection_(0) {
228 } 25 }
229 26
230 // Retrieve per-axis accelerometer values. 27 // Retrieve per-axis orientation values.
231 // 28 //
232 // Axes and angles are defined according to the W3C DeviceOrientation Draft. 29 // Axes and angles are defined according to the W3C DeviceOrientation Draft.
233 // See here: http://dev.w3.org/geo/api/spec-source-orientation.html 30 // See here: http://dev.w3.org/geo/api/spec-source-orientation.html
234 // 31 //
235 // Note: only beta and gamma angles are provided. Alpha is set to zero. 32 // Note: only beta and gamma angles are provided. Alpha is set to zero.
236 // 33 //
237 // Returns false in case of error or non-properly initialized object. 34 // Returns false in case of error.
238 // 35 //
239 bool AccelerometerMac::GetOrientation(Orientation* orientation) { 36 bool AccelerometerMac::GetOrientation(Orientation* orientation) {
240 DCHECK(sensor_); 37 DCHECK(sudden_motion_sensor_.get());
241 38
242 // Reset output record memory buffer. 39 // Retrieve per-axis calibrated values.
243 std::fill(output_record_.begin(), output_record_.end(), 0x00); 40 float axis_value[3];
244 41 if (!sudden_motion_sensor_->ReadSensorValues(axis_value))
245 // Read record data from memory.
246 const size_t kInputSize = kGenericSensor.record_size;
247 size_t output_size = kGenericSensor.record_size;
248
249 if (IOConnectCallStructMethod(io_connection_, kGenericSensor.function,
250 static_cast<const char *>(&input_record_[0]), kInputSize,
251 &output_record_[0], &output_size) != KERN_SUCCESS) {
252 return false; 42 return false;
253 }
254
255 // Calculate per-axis calibrated values.
256 float axis_value[3];
257
258 for (int i = 0; i < 3; ++i) {
259 int sensor_value = 0;
260 int size = kGenericSensor.axis_size;
261 int index = sensor_->axis[i].index;
262
263 // Important Note: Little endian is assumed as this code is Mac-only
264 // and PowerPC is currently not supported.
265 memcpy(&sensor_value, &output_record_[index], size);
266
267 sensor_value = ExtendSign(sensor_value, size);
268
269 // Correct value using the current calibration.
270 axis_value[i] = static_cast<float>(sensor_value - kGenericSensor.zero_g) /
271 kGenericSensor.one_g;
272
273 // Make sure we reject any NaN or infinite values.
274 if (!isfinite(axis_value[i]))
275 return false;
276
277 // Clamp value to the [-1, 1] range.
278 if (axis_value[i] < -1.0)
279 axis_value[i] = -1.0;
280 else if (axis_value[i] > 1.0)
281 axis_value[i] = 1.0;
282
283 // Apply axis inversion.
284 if (sensor_->axis[i].inverted)
285 axis_value[i] = -axis_value[i];
286 }
287 43
288 // Transform the accelerometer values to W3C draft angles. 44 // Transform the accelerometer values to W3C draft angles.
289 // 45 //
290 // Accelerometer values are just dot products of the sensor axes 46 // Accelerometer values are just dot products of the sensor axes
291 // by the gravity vector 'g' with the result for the z axis inverted. 47 // by the gravity vector 'g' with the result for the z axis inverted.
292 // 48 //
293 // To understand this transformation calculate the 3rd row of the z-x-y 49 // 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 50 // 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. 51 // affects to the result). Note that z-x-y matrix means R = Ry * Rx * Rz.
296 // Then, assume alpha = 0 and you get this: 52 // Then, assume alpha = 0 and you get this:
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
330 DCHECK_LT(orientation->gamma_, 90.0); 86 DCHECK_LT(orientation->gamma_, 90.0);
331 87
332 orientation->can_provide_alpha_ = false; 88 orientation->can_provide_alpha_ = false;
333 orientation->can_provide_beta_ = true; 89 orientation->can_provide_beta_ = true;
334 orientation->can_provide_gamma_ = true; 90 orientation->can_provide_gamma_ = true;
335 orientation->can_provide_absolute_ = false; 91 orientation->can_provide_absolute_ = false;
336 92
337 return true; 93 return true;
338 } 94 }
339 95
340 // Probe the local hardware looking for a supported sensor device
341 // and initialize an I/O connection to it.
342 bool AccelerometerMac::Init() { 96 bool AccelerometerMac::Init() {
343 // Request model name from the kernel. 97 sudden_motion_sensor_.reset(SuddenMotionSensor::Create());
344 char local_model[32]; // size from SMSLib 98 return sudden_motion_sensor_.get() != NULL;
345 size_t local_model_size = sizeof(local_model);
346 int params[2] = { CTL_HW, HW_MODEL };
347 if (sysctl(params, 2, local_model, &local_model_size, NULL, 0) != 0)
348 return NULL;
349
350 const SensorDescriptor* sensor_candidate = NULL;
351
352 // Look for the current model in the supported sensor list.
353 base::mac::ScopedCFTypeRef<CFDataRef> board_id_data;
354 const int kNumSensors = arraysize(kSupportedSensors);
355
356 for (int i = 0; i < kNumSensors; ++i) {
357 // Check if the supported sensor model name is a prefix
358 // of the local hardware model (empty names are accepted).
359 const char* p1 = kSupportedSensors[i].model_name;
360 for (const char* p2 = local_model; *p1 != '\0' && *p1 == *p2; ++p1, ++p2)
361 continue;
362 if (*p1 != '\0')
363 continue;
364
365 // Check the board id.
366 if (kSupportedSensors[i].board_id) {
367 if (!board_id_data.get()) {
368 CFMutableDictionaryRef dict =
369 IOServiceMatching("IOPlatformExpertDevice");
370 if (!dict)
371 continue;
372
373 io_service_t platform_expert =
374 IOServiceGetMatchingService(kIOMasterPortDefault, dict);
375 if (!platform_expert)
376 continue;
377
378 board_id_data.reset((CFDataRef)
379 IORegistryEntryCreateCFProperty(platform_expert,
380 CFSTR("board-id"),
381 kCFAllocatorDefault,
382 0));
383 IOObjectRelease(platform_expert);
384 if (!board_id_data.get())
385 continue;
386 }
387
388 if (strcmp(kSupportedSensors[i].board_id,
389 (const char*)CFDataGetBytePtr(board_id_data)) != 0) {
390 continue;
391 }
392 }
393
394 // Local hardware found in the supported sensor list.
395 sensor_candidate = &kSupportedSensors[i];
396
397 // Get a dictionary of the services matching to the one in the sensor.
398 CFMutableDictionaryRef dict =
399 IOServiceMatching(kGenericSensor.service_name);
400 if (!dict)
401 continue;
402
403 // Get the first matching service.
404 io_service_t device = IOServiceGetMatchingService(kIOMasterPortDefault,
405 dict);
406 if (!device)
407 continue;
408
409 // Try to open device.
410 kern_return_t result;
411 result = IOServiceOpen(device, mach_task_self(), 0, &io_connection_);
412 IOObjectRelease(device);
413 if (result != KERN_SUCCESS || io_connection_ == 0)
414 return false;
415
416 // Local sensor service confirmed by IOKit.
417 sensor_ = sensor_candidate;
418 break;
419 }
420
421 if (sensor_ == NULL)
422 return false;
423
424 // Allocate and initialize input/output records.
425 input_record_.resize(kGenericSensor.record_size, 0x01);
426 output_record_.resize(kGenericSensor.record_size, 0x00);
427
428 // Try to retrieve the current orientation.
429 Orientation test_orientation;
430 return GetOrientation(&test_orientation);
431 }
432
433 // 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) {
435 switch (size) {
436 case 1:
437 if (value & 0x00000080)
438 return value | 0xffffff00;
439 break;
440
441 case 2:
442 if (value & 0x00008000)
443 return value | 0xffff0000;
444 break;
445
446 case 3:
447 if (value & 0x00800000)
448 return value | 0xff000000;
449 break;
450
451 default:
452 LOG(FATAL) << "Invalid integer size for sign extension: " << size;
453 }
454
455 return value;
456 } 99 }
457 100
458 } // namespace device_orientation 101 } // namespace device_orientation
OLDNEW
« no previous file with comments | « content/browser/device_orientation/accelerometer_mac.h ('k') | content/content_browser.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698