Reverse engineering Solos smart glasses
Протокол очков Solos
Очки 2018 г. с микродисплеем Kopin, продавались за $500, нашёл новые за $30 на eBay. Компания теперь делает только аудио-очки, документацию не даёт.
Как работает связь
Приложение Android передаёт картинку по Bluetooth:
- включаем «HCI snoop log» в Developer Options;
- ловим трафик Wireshark, выделяем пакеты, начинающиеся с
1d60; - повторная отправка этих пакетов воспроизводит изображение.
Формат пакета
1d60 05000000 1c4c0000 0200000001 00000000 ac01f000 [RLE-данные]
1d60– магия;0500…– режим рисования;1c4c0000– длина RLE-данных / 2 (little-endian);00000000– смещение x,y;ac01f000– ширина 428, высота 240;- далее RLE:
ff0000= 255 пикселей чёрного (0x0000 в 5-6-5 RGB),ad0000= 173 пикселя и т.д.
Управление
Питон-скрипт (pybluez) собирает кадр 428×240, кодирует RLE, шлёт пакетом 1d60… – очки мгновенно выводят картинку.
Комментарии (22)
- Участники обсуждают дешёвый Bluetooth-HUD-дисплей, который оказался неудавшимся продуктом 2018 г.
- Вопросы вызвали странная размерность поля length (в 16-битных словах) и безопасность острого экрана у глаза.
- Кто-то сравнивает устройство со смарт-часами, другие видят пользу для велосипеда/лыж/плавания, где HUD показывает мощность/пульс без отрыва взгляда.
- Пользователи делятся опытом Vufine, Engo 2 и ищут современные аналоги Google Glass.
- Идеи применения: навигация, уведомления, чтение книг в метро, «очки-фото» с камерой, автоматическое обновление картинок из cron-скриптов.
A Linux version of the Procmon Sysinternals tool
ProcMon-for-Linux — порт утилиты Sysinternals Process Monitor для Linux.
Позволяет в реальном времени наблюдать за системными вызовами (open, read, write, fork, exec и др.) и событиями ядра, фильтровать, сохранять и анализировать трейсы.
Ключевые возможности
- CLI-интерфейс, знакомые фильтры
pid,process,operation,path,result. - Форматы вывода: консоль, XML, CSV, JSON.
- Поддержка x86_64, ARM64; ядро ≥ 4.9.
- Сборка:
cmake,libsqlite3-dev,libncurses5-dev,libssl-dev,bcc-dev.
Установка
Ubuntu 20.04+
sudo apt install procmon
Или из исходников:
git clone https://github.com/microsoft/ProcMon-for-Linux
cd ProcMon-for-Linux
mkdir build && cd build
cmake ..
make
sudo make install
Быстрый старт
# отслеживать процесс firefox
sudo procmon -p $(pgrep firefox)
# сохранить лог в JSON
sudo procmon -p 1234 -o trace.json -f json
Лицензия
MIT.
Комментарии (45)
- Пользователи обсуждают ProcMon для Linux: кто-то рад, что не придётся опрашивать /proc, кто-то сомневается в целях проекта и его отличии от htop+strace.
- Интересуются совместимостью вывода с Windows-версией и поддержкой телеметрии, а также жалуются на старый INSTALL.md и ограниченные требования (Ubuntu 18.04).
- Некоторые считают утилиту TUI-обёрткой над strace, другие подчеркивают, что она использует eBPF и может следить за всеми процессами без замедления.
- Поднимаются темы «почему нужны сразу GCC и Clang» и «Microsoft всё больше делает инструменты для Linux».
We should have the ability to run any code we want on hardware we own 🔥 Горячее 💬 Длинная дискуссия
Ошибка всех споров о sideloading
Популярный аргумент: «Я должен запускать любой код на своём железе». Он верен, но в контексте обсуждения — пустой. Google ограничивает не аппарат, а программное обеспечение, поставляемое с ним. iPhone без iOS — уже не тот продукт, поэтому заставлять Apple менять iOS законодательно — значит подрывать его успех.
Критиковать нужно не ограничения ОС, а невозможность по-настоящему управлять железом. Производители обязаны предоставлять документацию и поддержку, чтобы можно было ставить альтернативные ОС: Android на iPhone, Linux на PS5.
Комментарии (1113)
- Смартфоны уже не просто гаджеты, а ключ к банкам, госуслугам и повседневной жизни; без аккаунта Apple/Google всё сложнее.
- Большинство сервисов (банки, Netflix и др.) требуют «доверенную» цепочку ПО и железа, поэтому альтернативные ОС фактически невозможны.
- Участники делятся на два лагеря: «открытое железо для всех» vs «безопасные, закрытые устройства для большинства».
- Поднимаются вопросы права собственности, лицензий, IP-законов и даже того, что в будущем мы будем арендовать, а не покупать устройства.
- Реалистичный выход: требовать от гос- и коммерческих сервисов полноценных веб-версий, чтобы не быть привязанным к конкретной ОС.
Installing UEFI Firmware on ARM SBCs
EDK2 UEFI на ROCK 5 ITX+
Плата ROCK 5 ITX+ (RK3588, 32 ГБ eMMC, два M.2, PoE) удобна, но слот microSD сбоку мешает быстро менять ОС. Вместо корпуса и удлинителя решено прошить SPI-память UEFI-фирмой EDK2-RK3588 и грузить образы с USB.
EDK2-RK3588
Проект поставляет PC-образный UEFI для плат на RK3588, обещая загрузку Windows, Linux, BSD и ESXi. На ROCK 5 ITX+ фирма не стартует ни с microSD, ни с eMMC — требуется запись во встроенный SPI-флеш.
Процесс
- Загружаем Armbian 25.2.2 Noble Gnome (kernel 6.1).
- В браузере скачиваем последний релиз
rock-5-itxс GitHub EDK2-RK3588. - Прошиваем SPI командой
rockchip_spi_update(предварительно сделав дамп оригинала). - Перезагружаемся, выбираем в UEFI нужный USB-накопитель и ставим любой ARM-дистрибутив.
Результат
Теперь ОС можно менять без открытия корпуса и вынимания карты — достаточно вставить флешку и выбрать её в меню UEFI.
Комментарии (34)
- U-Boot уже умеет достаточно UEFI, чтобы запускать Linux/BSD без родного прошивочного слоя.
- Участники хотят отказаться от «SD-карт-флешалок» и получить единый стандарт загрузки, но ARM-вендоры медленно внедряют SystemReady.
- Основные проблемы ARM: отсутствие единой среды загрузки и надёжного механизма авто-обнаружения железа; «ванильные» образы дистрибутивов почти никогда не стартуют без доработки.
- Кто-то предлагает усилить IEEE 1275/Open Firmware вместо UEFI, другие считают UEFI «безумием», но всё же лучше произвола каждого SoC.
- В RISC-V для серверов UEFI уже обязателен по спецификации, чего пока не скажешь о большинстве ARM-плат.
New Ruby Curl bindings with Fiber native support
- 0.9.11 – Ruby 3.2, libcurl 7.85+, исправлены утечки и сбои сборки.
- 0.9.10 – Ruby 2.7–3.1, Windows-CI,
Curl.postal,Curl::Easy#resolve. - 0.9.9 – Ruby 2.6+,
Curl::Multi#max_connects,on_redirect,CURLOPT_UNIX_SOCKET_PATH. - 0.9.8 – Ruby 2.5+,
CURLOPT_SSL_VERIFYHOST,CURLOPT_SSL_VERIFYPEER,Curl::Easy#close. - 0.9.7 – Ruby 2.4+,
CURLOPT_TCP_KEEPALIVE,CURLOPT_TCP_KEEPIDLE,CURLOPT_TCP_KEEPINTVL. - 0.9.6 – Ruby 2.3+,
CURLOPT_SSL_ENABLE_ALPN,CURLOPT_SSL_ENABLE_NPN,Curl::Easy#on_header. - 0.9.5 – Ruby 2.2+,
CURLOPT_SSL_FALSESTART,CURLOPT_SSL_VERIFYSTATUS,Curl::Easy#on_progress. - 0.9.4 – Ruby 2.1+,
CURLOPT_SSL_SESSIONID_CACHE,CURLOPT_SSL_OPTIONS,Curl::Easy#on_debug. - 0.9.3 – Ruby 2.0+,
CURLOPT_SSL_CIPHER_LIST,CURLOPT_SSL_VERSION,Curl::Easy#on_body. - 0.9.2 – Ruby 1.9+,
CURLOPT_SSLCERT,CURLOPT_SSLKEY,Curl::Easy#on_header. - 0.9.1 – Ruby 1.8+,
CURLOPT_SSL_VERIFYPEER,CURLOPT_SSL_VERIFYHOST,Curl::Easy#on_complete. - 0.9.0 – Первый релиз, поддержка Ruby 1.8, libcurl 7.10+.
Комментарии (2)
- Вышла Curb 1.2.0: добавлен Fiber-aware IO-scheduling и параллельная сборка на нескольких ядрах, что ускоряет установку.
- По умолчанию Curl.head теперь не ждёт тело ответа (CURLOPT_NOBODY=1), что разумнее для HEAD-запросов.
- @sdwolfz поздравил и спросил, в чём преимущество Curb перед Net::HTTP для обычных JSON REST-вызовов, кроме «меньше кода».
What to do with C++ modules? 💬 Длинная дискуссия
Краткий обзор проблемы C++ модулей
-
Главное требование
Если модули не ускоряют сборку минимум в 5 раз (желательно 10×) на реальных проектах, их нужно удалить из стандарта. Все остальные плюсы не стоят вложенных ресурсов. -
Что обещали vs. что получили
- Изначально: «уберём O(N²) из-за заголовков, компиляция станет мгновенной».
- Сейчас: упор сместился на «изоляцию сборки» (макросы, пространства имён). Это полезно, но редко встречается и не решает главную боль — медленную сборку каждый день.
-
Почему всё так плохо
- Модули приняли в C++20, несмотря на предупреждения о невозможности реализации.
- Реализация заняла >5 лет и всё ещё не готова.
- Стандарт не описывает, как именно компилятор и сборочная система должны взаимодействовать: имена файлов, каталоги, зависимости — всё на совести разработчиков.
- Компиляторные команды отказываются «превращаться в систему сборки» и блокируют любые предложения.
-
Итог
Проект превратился в «интеграционный ад». Пока нет массовых 5-10-кратных ускорений, дальнейшие инвестиции — просто затягивание «затратной ямы».
Комментарии (165)
- Участники сетуют: вместо простого «import = include без утечек контекста» получили громоздкий механизм, который мало кто использует.
- Старые пре-компил-хедеры 90-х и сторонние решения вроде zapcc уже давали 5× ускорение, но были проигнорированы стандартом.
- Модули обещали избавить от forward-declaration и макро-ifdef, но на практике вызывают лавину пересборок и несовместимы с большим объёмом существующего кода.
- Многие считают, что модули заточены под «большой тех» с кэшированными билдами, а малый бизнес и хобби-проекты «попали в пролёт».
- Итоговое настроение: «убейте модули, C++ всё сломали», «мир ушёл в Rust», но «на C++ всё ещё держится пол-мира, так что просто так не выкинешь».
Eternal Struggle 🔥 Горячее
Вечная борьба
сменить фон
Комментарии (125)
- Францис Дювивье «вайб-форкнул» симуляцию «Eternal Struggle» с ползунком скорости, чтобы фармить карму на HN.
- Суть: два шарика отскакивают в своих половинках круга; чем больше пространство, тем реже удар → самобалансирующаяся система.
- Пользователи заметили баги: шарики могут «протуннелировать» и захватить чужую сторону, ползунок скорости застревает на максимуме.
- Кто-то ускорил симуляцию до 20× и увидел разрушение границы; другие предложили счётчик процентов белого/чёрного.
- В комментариях всплывают ссылки на Pong Wars, Gold Wars и размышления о математике, философии Инь-Ян и 3D-версии.
Inverting the Xorshift128 random number generator
Xorshift128+ можно «перевернуть» за 226 операций, если даны два полных 64-битных вывода.
Math.random() в Node.js использует Xorshift128+, но отдаёт лишь 52 младших бита суммы новых состояний. CVE-2025-7783 показал, что при пяти последовательных выводах можно предсказать дальнейшие значения через z3. Автор решил проверить, достаточно ли меньше данных.
Алгоритм Xorshift128+
s1 = L
s0 = R
L = R
s1 ^= s1<<23 ^ s1>>17 ^ s0 ^ s0>>26
R = s1
Вывод: x = L + R (64 бита). В Math.random() старшие 12 бит теряются.
Обозначения
(L₀,R₀)– начальное состояние.(Lᵢ,Rᵢ)– состояние на шаге i.xᵢ = Lᵢ₊₁ + Rᵢ₊₁– вывод.
Суть атаки
- Зная
x₀, выражаемL₁ = x₀ - R₁. - Из уравнений Xorshift128+ получаем 64 линейных уравнения относительно 64 неизвестных битов
R₁. - Система решается за O(2²⁶) операций методом Гаусса по модулю 2.
Расширение до Math.random()
Нужны три вывода, чтобы восстановить недостающие 12 бит каждого. Сложность ≈ 2⁵⁰, но можно улучшить.
Код и приглашение
GitHub-репозиторий с реализацией; автор приглашает к оптимизации.
Комментарии (37)
- Xorshift128+ легко «взламывается» линейной алгеброй: достаточно 128 бит выхода и матричного решения над GF(2).
- SMT-солверы вроде Z3 удобны для «возьми-ограничения-дай-ответ», но плохо справляются с коллизиями хешей.
- Уязвимость CVE связана не с самим Math.random(), а с тем, что Node.js использовал его в криптоконтексте.
- Спор: стоит ли языкам по умолчанию давать криптостойкий RNG (например, ChaCha20), несмотря на потерю скорости; Go уже пошёл по этому пути.
- Предложено явно именовать небезопасные функции, например Math.RandomNotCrypto(), чтобы снизить случайное неправильное использование.
Code Is Debt
Код — это долг
«Что ты думаешь об ИИ-инструментах для программирования?»
Отвечаю примером двух компаний.
Они одинаковы по доходу и продукту, но первая живёт с 1 млн строк кода, вторая — с 100 тыс. Какая выгоднее?
Очевидно, та, что меньше. Меньше кода — быстрее понимать и менять. Код — это долг. ИИ, генерируя код, даёт тебе этот долг.
Брать ли его? Зависит. Долг бывает полезным или разрушительным, с процентами или без. Главное — иметь доступ к инструментам и использовать их ответственно.
Спасибо Ани Талахадзе за рецензию.
Комментарии (53)
- Участники спорят, можно ли считать количество строк кода (LOC) мерой технического долга: одни считают LOC бесполезной метрикой без учёта качества, другие — формой риска и обязательств.
- Подчёркивается, что «меньше кода» ≠ «лучше», если он нечитаем, плохо документирован и не поддерживается; главное — скорость понимания и изменения.
- AI-генерация кода ускоряет объём, но усиливает долг: код быстро появляется, но никто не понимает, кто за него отвечает, и как его отлаживать.
- Код описывается как актив, который амортизируется: чем больше кода, тем выше ежегодные «выплаты» на его поддержку и рефакторинг.
- Третьи сервисы и зависимости тоже создают долг: при смене условий или закрытии поставщика страдает бизнес.
How is Ultrassembler so fast?
Ultrassembler — библиотека RISC-V-ассемблера, встроенная в проект Chata.
В отличие от as и llvm-mc, она вызывается прямо из C++, без system() и временных файлов, что критично для встроенных систем.
Скорость
Тест на 16 тыс. инструкций:
- Ultrassembler ≈ 10× быстрее
as, 20× быстрееllvm-mc. - 1 RISC-V инструкция ≈ 1000 x86-инструкций (у конкурентов 10–20 тыс.).
Код на чистом C++; можно добавить ассемблерные вставки.
Ключевые оптимизации
Исключения
GCC-реализация «zero-overhead»: штрафа нет, пока исключений нет.
Ошибки встречаются редко и видны человеку, поэтому даже 1 с на обработку незаметна.
std::expected дал −10 %, так как нормальный путь стал дороже.
Быстрые структуры
2000+ RISC-V-инструкций требуют мгновенного поиска.
Вместо std::unordered_map используется perfect-hash таблица от gperf, генерирующая O(1) без коллизий.
Размер таблицы компактен, кэш-эффективен.
Парсинг
- Регистры идентифицируются по первым 2–3 символам через
switch. - Нет
std::string, толькоstd::string_viewи статические буферы. - Лексемы разбираются за один проход без регулярных выражений.
Кодогенерация
- Шаблоны на этапе компиляции формируют битовые маски инструкций.
- Варианты одной инструкции разворачиваются в
constexpr-таблицы, что убирает ветвления в рантайме.
Память
- Все выделения через стековые
std::array/std::string_view. - Нет
new/malloc, следовательно, нет аллокационных штрафов и кэш-промахов.
Платформенные трюки
[[likely]]/[[unlikely]]для подсказок ветвления.__builtin_expectтам, где компилятор не догадывается.- LTO + PGO дают ещё 5–7 %.
Итог
Ultrassembler показывает, что «низкоуровневый» C++ без искусственных ограничений может обгонять даже оптимизированные GNU-утилиты.
Комментарии (34)
- В обсуждении разобрали миф о «системном вызове при каждом росте контейнера» — реальные аллокаторы переиспользуют память и делают syscall лишь при нехватке.
- Участники напомнили, что исключения в C++ не «zero-overhead»; есть компромисс между временем и памятью, и g++ выбирает экономию места.
- Автор статьи подтвердил: пробовал хеширование, но дерево разбора оказалось быстрее; flex/bison тут не при чём, скорее gperf.
- Некоторые посоветовали LLVM C++ API, memory-mapped I/O и std::pmr для ускорения и упрощения кода.
- Большинство сходится: современные ассемблеры и так быстрые, задача скорее академическая, но как «посмотреть, насколько можно ускорить» — интересна.