Сенсор внезапного движения
Очень давно, на всех носимых устройствах, оснащённых жёстким диском (ноута, смартфонах) появился сенсор внезапного движения. В жёстком диске считывающая головка находится, не касаясь, над поверхностью диска с данными. Если ноут резко поднять, головка может чиркнуть по поверхности диска и испортить его. Для этого нужен сенсор внезапного движения (акселерометр), он реагирует на ускорение в любую сторону и «паркует» головку — уводит её в зону, где она ничего не может повредить.
На ноутах с твёрдотельным накопителем (ССД), этого сенсора обычно не бывает — он там не нужен. Например, на моём Макбуке Эйр его не было, нет его и на 15″ Макбуке Про с Ретиной моего друга, я специально смотрел — в этих ноутах нет жёстких дисков. В Макбуках Про предыдущей модели, без Ретины и с жёстким диском, сенсор, естественно, был.
Каково же было моё удивление, когда я обнаружил, после покупки Макбука Про 13″, что в сведениях о системе есть упомянутый сенсор:
Думаю, его просто забыли убрать, наверное это рудимент прежней модели Макбука. Но наличие сенсора не говорит о том, что он работает. Я сегодня потратил пару часов, чтобы разобраться как в Маке читают этот сенсор и написал вот такую программу на Си:
// MacbookPro (OS X 10.5+) SMS reading. Evgeny Stepanischev May 2013
// gcc -framework IOKit motion.c
#include <IOKit/IOKitLib.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define RETURNONFAIL(code) do { if (errcode != KERN_SUCCESS) {\
fprintf(stderr, "Error code: 0x%Xn", GETCODE(errcode));\
return code;\
} } while (0)
#define GETCODE(err) ((err)&0x3fff)
typedef struct {
int16_t x;
int16_t y;
int16_t z;
} ostruct;
int main() {
mach_port_t masterPort;
kern_return_t errcode;
io_iterator_t iterator;
io_object_t service;
io_connect_t connect;
void *in;
ostruct *out;
size_t osize = 40, isize = 40;
errcode = IOMasterPort(MACH_PORT_NULL, &masterPort);
RETURNONFAIL(-1);
CFMutableDictionaryRef matchingDictionary = IOServiceMatching("SMCMotionSensor");
errcode = IOServiceGetMatchingServices(masterPort, matchingDictionary, &iterator);
RETURNONFAIL(-2);
service = IOIteratorNext(iterator);
IOObjectRelease(iterator);
if (service == kIOReturnNoDevice) {
return -3;
}
errcode = IOServiceOpen(service, mach_task_self(), 0, &connect);
IOObjectRelease(service);
RETURNONFAIL(-4);
in = malloc(isize);
out = malloc(osize);
if (in == NULL || out == NULL) {
return -6;
}
memset(out, 0, osize);
memset(in, 1, isize);
errcode = IOConnectCallStructMethod(connect, 5, in, osize, out, &isize);
RETURNONFAIL(-5);
printf("%d, %d, %d\n", (*out).x, (*out).y, (*out).z);
return 0;
}
Программа выводит три числа: показатели наклона влево/вправо, назад/вперёд и показатель ускорения, который меняется, если ноут резко поднять или опустить.
Размер структуры 40 и второй параметр функции IOConnectCallStructMethod («5») — «магические» значения, первое — фиксированный размер буфера, который требуется функции, второе — номер вызываемой функции в ядре (SMCMotionSensor).
у меня на ноуте Fujitsu производитель заботливо положил на desktop PDF-ку с описанием процедуры отключения акселерометра, если используется SSD.
Комментарий для Sanja:
Эпл тоже рассказывает как это сделать: http://support.apple.com/kb/HT1935