понедельник, 19 ноября 2007 г.

LooxLight 2007-11-19

Подробнее о Looxlight (утилита для Fujitsu-Siemens Loox N560/C550) смотрите здесь.

Обновление!

Вот cab.
Вот исходники.

Добавил возможность блокрировать экран и клавиатуру. Раньше у меня стояло что-то-там-guard (screen guard или типа того). Но оно было глючное: иногда при разблокриовке весило кпк, при нажатии на кнопку suspend разблокировала экран, но при нажатии любой клавиши блокировало его обратно - выглядело это страшно, при нажатии на кнопки разблокировало экран и тутже блокировало обратно. Терпел. А вот недавно перепрошил КПК на новую версию WM5 (кстати стало побыстрее все рисоваться, а в каталог /windows так вообще мгновенно заходит (раньше 10сек)). После перепрошивки обнаружил, что жить без блокировки тяжело - батарея садится быстрее, кнопки нажимаются случайно, когда в кармане КПК лежит... И позавчера вечером не выдержал и решил написать сам. Ну как сказать, получилось вобщем-то. Отличается от прочих (пукнт 1.42) тем, что заточено чисто под Fujitsu-Siemens Loox N560/C550 (может конечно и на 720 заработает, дрова у них похожие), поэтому выключает и экран и клавиатуру в том числе и кнопку suspend(!!). Кстати, выключенный экран (при прослушивании музыки или аудиокниги) экономит более 50мА. С выключенным экраном заряжаться с USB должно быстрее.

Как установить:
Если КПК не Fujitsu-Siemens Loox N560/C550, то очень рекоменудю сделать backup! Если это Fujitsu-Siemens Loox N560/C550, то все равно рекомендую, хотя у меня и жены вроде ничего страшного не произошло пока. В любом случае, я ответственности никакой не несу. :) (Добполнение: У меня работает уже больше чем 2 года без проблем)

Скачать cab. Закинуть на кпк. Запустить установку. Установить. Подождать минуту для верности. Перезагрузить КПК (софтресет). Запустить LooxLight Control и поставить галочку напротив "Permit blocking". Ниже, напротив "Unblock by" два выпадающих списка. В них задается какими кнопками будет происходить РАЗБЛОКИРОВКА. Когда КПК будет заблокирована, эти две кнопки надо будет последовательно нажать. У меня это 2 и 3 кнопки. А по умолчанию почему-то стоит 2 и 4, ну и фик с ним. Теперь идем в Settings/Buttons и там вешаем LooxLight Control на ту кнопку, которой КПК будет БЛОКИРОВАТЬСЯ. У меня это долгое нажатие на кнопку 2. Готово. Можно тестировать.

При нажатии на первую из кнопок разблокировки, следующую нужно зажать в течении одной секунды. Во время ожидания клавиатура КПК будет подмигивать.

Как реализовано (в общих чертах):
С выключением экрана все просто. А вот с его блокировкой посложнее. LooxLight аттачит себя к gwes.exe. Находит в памяти keybddr.dll и правит в ней таблицу импортированных функций, а именно WaitForSingleObject. Эта функция вызывается нитями keybddr.dll для ожидания прерывания клавиатуры (0x10 и 0x2a), а также для ожидания срабатывания события suspend. Т.е. в таблице импорта keybddr.dll, LooxLight подменяет адрес WaitForSingleObject с адреса функции из библиотеки coredll.dll на собственную функцию. Получается, что в момент, когда keybddr инициирует ожидание нажатия, вызывается функция LooxLight'а, которая в свою очередь дергает оригинальную функцию. Если блокировка не включена, то результат сразу же возвращается в keybddr.dll. Иначе в результате проверяется пара адресов памяти на код нажатой клавиши. По нему решается, разблокировать ли экран или нет (грубо очень). Если нажатие нужно проигнорировать, то сообщаем OS о том, что мы обработали прерывание (InterruptDone) и вызываем оригинальный WaitForSingleObject - тоесть управление обратно в keybddr не передается, пока клавиатуру не разблокируется. Таким образом ни одной нажатие мимо нас в принципе не проходит. Ибо обработчик LooxLight находится первым в цепочке обработки прерывания клавиатуры.

Пока заметил, что если воткнуть КПК в крэдл, когда КПК заблокирована, то экран включается. Правда при этому клавиатура попрежнему заблокирована. Я думаю activesync что-то делает такое не хорошее, например вызывает ExtEscape - функция используемая для выключения/включения питания экрана. Или еще хуже. он дергает какое-то более общее API (варианты: вывести окно на передний план, послать уведомление, включить подсветку), которое как раз и и дергает ExtEscape. Вариантов лечения я вижу два:
1. Простой. Эпизодически запрашивать состояния питания на экран и если блокировка включена, а экран выключен - то выключать экран. Но я так не люблю по таймеру что-то делать. Да и мерцание будет, хоть и очень редко.
2. Сложный. Я уже попробовал пойти по этому пути - убил 3 часа и пока решил отложить. Смысл в том, что можно вклинится в какое-нибудь API какой-нибудь dll. Например можно было бы перехватить ExtEscape, но для этого нужно пробежаться по всем dll'кам в системе и каждую из них происнструментировать так же как и keybddr. Так я еще не пробовал, но есть подозрение, что может не сработать. Ибо у нас есть gwes.exe который и рулит GDI'ем. И если кто-то вызывает API у coredll, тот направляет его еще куда.. короче я к тому, что вызов ExtEscape из coredll может быть проскипан кодом, который напрямую работает с DeviceDriver'ом - а с ним напрямую, я так подозреваю, работает gwes. Было бы просто идиально вклинится в Display Driver. Когда кто-то дергает ExtEscape, тот в свою очередь вызывает DrvEscape callback у драйвера дисплея. Как это вообще работает. Когда gwes.exe грузит драйвер дисплея, он вызывает у него метод DrvDeviceEnable (или типа того). Передавая ему в качестве параметра структуру, которую драйвер должен заполнить. В этой структуре указатели на методы связаные с работой с дисплеем, в том числе и DrvEscape. После того, как драйвер заполнил эту структуру, далее gwes уже работает только с методами прописанными в этой структуре. Было бы клево, найти в памяти адрес этой структура и прописать свой DrvEscape туда. Но полазив по header'ам от wince я пока не нашел цепочку, чтобы добраться до туда. Может имея HDC можно по нему добраться? Но HDC - это указатель на C++ структуру и я этот путь пока не осилил. Другой вариант, изучать gwes.exe и посмотреть куда он копирует адрес заполненной структуры и плясать отсюда. Но блин, gwes.exe как-то криво разобрался IDA (или криво задампился). Все локальные переменные имеют совсем не те адреса, на какие ссылается код. Еще можно было бы посмотреть coredll.dll и как там работает ExtEscape и потыкаться оттуда, но coredll.dll у меня задамлпнного нет (это вообще вроде kernel сам). А дамп всей ОЗУ неплохо так разобранный во времена когда искал как управлять диодами я где-то посеял..

Вобщем я решил пока этот вопрос отложить. Посмотрим как оно будет анноить или нет.

--------
Будущие версии программы можно будет найти здесь.
Другая программа для уменьшения расхода заряда батареи описана здесь.

3 комментария:

  1. Здравствуйте, Akshaal,
    пользуюсь Вашей программой LooxLight. Довольна. Спасибо.
    Обращаюсь к Вам как к человеку, разбирающемуся в устройствах Loox. Проконсультируйте :), пожалуйста, по такому вопросу:
    Есть ли возможность уменьшить минимальный уровень подсветки экрана? Я читаю "по ночам и темноте" и это стало серьезным испытанием для моих глаз :(.
    Нигде не могу найти какой-нибудь подходящей программы. Закрадывается мысль, что это в принципе недостижимо.
    Спасибо заранее.
    (если такой вопрос здесь неуместен, приношу извинения - подскажите, как связаться с Вами другим способом).
    С уважением,
    Алеся

    ОтветитьУдалить
  2. Здравствуйте!
    Подскажите, можно ли как-то назначить на кнопку КПК включение и выключение подсветки клавиатуры? А то в темноте подсветка вовсе не лишняя )))

    ОтветитьУдалить
  3. Добрый день, пользуюсь LooxLight уже давно, спасибо, отличная, незаменимая программа. Перепрошил свой Loox n560 на WM6.1, прога перестала работать, на одном из форумов нашел портированную версию (fixed by Delta_77, 2010 August, 4pda.ru). Но блокировщика в нем нет, видимо не удалось адаптировать к WM6.1.
    Не могли бы вы попробовать сделать отдельной маленькую прожку - блокировщик? На новой прошивке уже достаточно давно, но этой проги сильно нехватает. Уже думал перепрошить обратно, но уж какт прикипел к новой WM6.

    ОтветитьУдалить