Сенсор внезапного движения
Очень давно, на всех носимых устройствах, оснащённых жёстким диском (ноута, смартфонах) появился сенсор внезапного движения. В жёстком диске считывающая головка находится, не касаясь, над поверхностью диска с данными. Если ноут резко поднять, головка может чиркнуть по поверхности диска и испортить его. Для этого нужен сенсор внезапного движения (акселерометр), он реагирует на ускорение в любую сторону и «паркует» головку — уводит её в зону, где она ничего не может повредить.
На ноутах с твёрдотельным накопителем (ССД), этого сенсора обычно не бывает — он там не нужен. Например, на моём Макбуке Эйр его не было, нет его и на 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).
Берём «Макбук» со стола, экран гаснет или блокируется
В предыдущей заметке я писал, что обнаружил сенсор внезапного движения у своего «Макбука». Решил извлечь практическую пользу из этого — написал программу на Си, которая отправляет ноут в спячку, стоит поднять его со стола:
// gcc -framework CoreFoundation -framework IOKit gethensleep.c -o getthensleep
// Evgeny Stepanischev May 2013
#include <IOKit/IOKitLib.h>
#include <CoreFoundation/CoreFoundation.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdbool.h>
#include <sys/param.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)
#define THRESHOLD 0.2
typedef struct {
int16_t x;
int16_t y;
int16_t z;
} ostruct;
void macSleep() {
io_registry_entry_t r = IORegistryEntryFromPath(
kIOMasterPortDefault,
"IOService:/IOResources/IODisplayWrangler"
);
if (r) {
IORegistryEntrySetCFProperty(r, CFSTR("IORequestIdle"), kCFBooleanTrue);
IOObjectRelease(r);
}
}
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);
int16_t prevz;
bool inited = false;
for(;;) {
errcode = IOConnectCallStructMethod(connect, 5, in, osize, out, &isize);
RETURNONFAIL(-5);
if (inited) {
float min = MIN(prevz, (*out).z);
float max = MAX(prevz, (*out).z);
if (max) {
float dev = 1 - min / max;
if (dev > THRESHOLD) {
macSleep();
}
}
} else {
inited = true;
}
prevz = (*out).z;
usleep(10000);
}
return 0;
}Порог срабатывания (0.2) я подобрал экспериментальным путём. Скомпилировать можно компилятором gcc (входит в XCode), строка компиляции указана первой в приведёном коде. Можно засунуть в автозагрузку и наслаждаться эффектом.
Кстати, если хотите, то можно вместо спячки заставить ноут заблокировать экран (т. е. показать экран логина), для этого надо вместо функции macSleep вызвать другую:
// нужно добавить ещё один ключ компиляции: -framework ApplicationServices
#include <ApplicationServices/ApplicationServices.h>
void macLock () {
CGSCreateLoginSession(NULL);
}Разрушенные церкви бугульминского района Татарстана
У меня есть хобби, о котором, возможно, многие успели забыть (на время холодов я сделал паузу) — люблю фотографировать полуразрушенные храмы и церкви. В них есть
Я в последние майские праздники ездил по некоторым кладбищам бавлинского и бугульминского районов Татарстана — искал могилы своих предков, заодно заехал в парочку разрушенных церквей.


Первая — церковь Вознесения, построенная в 1764 году на деньги П.И. Рычкова в селе Спасское (Бугульминский район), объект культурного наследия республиканского значения. Внутрь уже не попасть, церковь начали восстанавливать, но в один из пристроев вход ещё открыт. На стенах и вокруг здания в кустах есть интерсные восьмиугольники, увенчанные короной, в которых




На второй серии снимков — Храм Петра и Павла из села Ключёвка, я о нём уже писал