четверг, 1 февраля 2007 г.

LooxLight


Я сделал это! Я написал свое второе приложение для PPC. LooxLight - это крошечное приложение, которое позволяет контролировать встроенные светодиоды на вашем FSC Pocket PC.

Фичи:

  • LooxLight позволяет управлять светодиодами: клавиатуры, wifi, bluetooth, gps, питания. Каждый светодиод может быть установлен в свое состояние. LooxLight может поддерживать любой светодиод в заданном состоянии или просто временно переключать из одного состояния в другое.
  • Сервис LooxLight занимает всего 3.5k памяти, когда загружен (можно и не загружать). LooxLight не грузит процессор: сервис делает только то, что требуется в те моменты, когда оно требуется и не более того (реагирует на изменение состояний светодиодов). LooxLight не разряжает батарею.
  • Работа из командной строки. Вы можете контролировать светодиоды из скриптов. Резидентная часть для этого не нужна. Например, "LooxLightCtrl +keyb sleep100 -keyb sleep100 +keyb" подмигнет вам подсветкой клавиатуры.
  • Протестировано на Fujitsu-Siemens Loox N560 и Fujitsu-Siemens Loox C550. Но ЕМНИП должно работать и на Loox 720 / Loox 718 .
  • Выложу исходники под GPL как только реализую все что хотел..

    ZIP архив с CAB'ом (17k).

    Что к чему в диалоге настройки.
    KBD озанчает KEYBOARD т.е. клавиатура, BTH сокращение от BLUETOOTH, PWR это POWER т.е. питание как вы догадались уже. Каждая строка с элементами управления озаглавлена названием светодиода.
    "On" кнопка просто включает светодиод, а "off" выключает. Blink означает мигать.
    "KEEP ON"/"KEEP OFF" подразумевает, что LooxLight будет восстанавливать состояние светодиода после того как какая либо другая программа установит его в ненужное состояние.

    Некоторые элементы управления отключены сейчас, потому, что еще не реализованы.

    Опции командной строки:
    LooxLightCtrl.exe ... , где opN:
  • stop - выключает резидентную часть
  • setup - говорит резидентной части прочитать настройки из registry
  • sleep123 - спать 123 миллисекунд (где 123 это любое положительное число)
  • flashlight - включает все светодиоды
  • +wifi - включает светодиод wifi
  • -wifi - выключает светодиод wifi
  • +bluetooth - включает светодиод bluetooth
  • -bluetooth - выключает светодиод bluetooth
  • +gps - включает светодиод gps
  • -gps - выключает светодиод gps
  • +keyboard - включает светодиод клавиатуры
  • -keyboard - выключает светодиод клавиатуры
  • +power - включает светодиод питания
  • -power - выключает светодиод питания
  • =power - включает светодиод питания в режим мерцания

    История создания:
    Однажды я нашел KeyLightC. Это была полезная программа, но в ней нельзя было включать-выключать отдельные светодиоды (а только все вместе и только выключать). Также там нужно было заново запускать KeyLightC как только какая-то программа поменяла состояние светодиода или просто после включения КПК. Я написал письмо Phill McManus. Я попросил его добавить опции +keyboard или -keyboard. Также я попросил его открыть исходники KeyLightC, чтобы я сам мог добавить эти фичи, если у него нет времени или желания. Но он не ответил. Тогда я начал мои собственные исследования прошивки. Прошло порядка 20 вечеров, прежде чем я нашел как управлять светодиодами правильным образом. Потом ушло порядка 10 вечеров, чтобы разобраться как писать под КПК и как пользоваться WinCE API. Потом ушло 3 дня, чтобы избавится от ужасного MS Visual Studio и мигрировать на mingw32ce под линух. И вообще, я ненавижу Win32 API за тонну подводных камней и неожиданностей.

    Планы:
  • Реализовать режим фонарик (не всегда темнота друг молодежи).
  • Доделать контроль светодиодов питания и GPS..
  • Реализовать контроль уровня подсветки.

    О прошивке Loox N560/C550.
    Я уже устал от этого поста. Опишу в другом попозже.

    Обратная связь:
    Было б прикольно увидеть комменты с пожеланиями, замечаниями и информацией у кого заработало (и на чем), а у кого нет (и на чем).

  • Новые версии программы здесь.
    Другая программа для уменьшения расхода заряда батареи описана здесь.

    воскресенье, 7 января 2007 г.

    Стиль

    Какой у меня в 1998 году был шизойдный стиль оформления программ :).
    int war::operator+=(String n)
    {
    war *o=this;

    aaa:
    if (o->next)
    {
    o=o->next;
    goto aaa;
    }
    else
    {
    o->next=new war(n);
    }
    return 1;
    }
    Сейчас бы написал так:
    int war::operator+= (String n) {
    war *cur = this;

    // Find last entry
    while (cur->next) {
    cur = cur->next;
    }

    cur->next = new war (n);
    }

    понедельник, 1 января 2007 г.

    Перечитывая спецификацию

    Джава как язык сдохнет под тяжестью собственной распухшей спецификации.

    Чем меньше в языке синтаксических конструкций тем язык красивее и логичнее. Например лямбда исчисление... красота. Хаскелл - можно реализовывать в терминах языка те фичи которые в других языках зашиты в сам язык. Язык форт - алфавит языка до ужаса прост и расширяем.

    Может в качестве хобби покомпилировать хаскелл в джава байт код? Есть ли смысл в таком?

    четверг, 28 декабря 2006 г.

    Впечатление о Motorola Pebl U6

    + цена 120$
    + bluetooth
    + gprs / edge
    + маленький
    + приятный
    + оригинальный
    + miniusb
    - интерфейс не логичен
    - как отправлять с телефона фалы я не нашел
    - эксплорера фс на самом телефоне тоже не нашел
    - бедный набор bluetooth сервисов
    - куда после пробывания новой симки и установки старой пррпали смс и телефонные номера набранные ранее - я не понимаю... и по этой причине вообще сижу без единого контакта...

    Цену телефон свою оправдывает. Если удастся синхронизировать телефон с кпк - будет вообще здорово.

    четверг, 14 декабря 2006 г.

    Восстановление после чистки

    Если вы обладатель КПК, то наверняка слышали про утилиты MemMaid или SKTools, а значит этот пост для вас. Если вы к тому-же не только слышали, но еще и пользуетесь, то это 100% для вас. Если вы не только пользуетесь одной из этих программ, но еще и по глупости полностью почистили Notification Queue и не знаете как заставить КПК работать - как раз об этом и пойдет речь.
    1. Почему это проблема? Notification queue (очередь уведомления, NQ) говорит КПК какое действие необходимо выполнить когда какое-то событие произошло. Например, если вы включаете КПК, то это событие AppRunAtWakeup (или типа того). КПК не будет ничего делать по событиям, если вы почистили NQ. Самое главное, что вы не сможете даже приконнектится своим КПК к ПК с помощью обычных USB, IR, RS232. Это означает, что вы не сможете синхронизировать ваш КПК с ПК, а также не сможете его поэксплорить с вашего большого компьютера.

    2. Как я могу это вылечить? Простой путь - это восстановить состояние КПК из резервной копии. Очень хорошо иметь такую свежую копию :)))).

    3. У меня нет резервной копии... не совсем так... есть, но она древняя, что я могу сделать в этом случае? Вы можете сделать аппаратный сброс (Hard Reset, XР). Но все же лучше восстановится из бэкапа, даже если он у вас древний.

    4. Я не хочу делать ХР или восстанавливаться из резервной копии! Да, я тоже. Тогда мы должны добавить события в NQ вручную.

    5. Какие события я должен добавить? Чтобы узнать список событий вы можете: сделать бэкап, сделать ХР, установить SKTools и записать список событий из очереди уведомления, затем восстановится из бэкапа. Или вы можете найти список для вашего КПК в интернете. В моем случае, я посмотрел на КПК моей жены. У нее КПК почти такой же как у меня (у нее C550, у меня N560).

    6. Как добавить события в NQ? SKTools - лучшее что я видел для этих целей.

    7. Мне нужно добавить "\windows\repllog.exe AppRunAfterRndisFnDetected", но SKTools не имеет события "AppRunAfterRndisFnDetected"! Да! Это сейчас основная проблема.
    Я потратил четыре дня, чтобы найти такую программу, которая бы позволяла мне добавить это событие. Но я не нашел. Не было такой программы. Поэтому я написал свою. Вот она: http://toril.ru/soft/akrndisadd.exe. Просто запустите ее на КПК. Она должна показать "True", если событие было успешно добавлено.

    8. Как я могу поместить эту программу на КПК, если я не могу посмотреть содержимое моего КПК с ПК, пока это событие не добавлю? Вы можете переместить программу с помощью Bluetooth, WIFI, MMC/SD/CF карты, инфракрасного порта или RS232 :).

    Исходники akrndisadd
    #include "stdafx.h"
    #include <windows.h>
    #include <commctrl.h>
    #include <notify.h>

    int _tmain(int argc, _TCHAR* argv[])
    {
    TCHAR *r = TEXT ("False");

    // This API is deprecated. I know.
    if (CeRunAppAtEvent (TEXT("\\windows\\repllog.exe"), 14L)) {
    r = TEXT ("True");
    };

    MessageBox (NULL, r, r, MB_OKCANCEL | MB_ICONEXCLAMATION);
    return 0;
    }

    четверг, 19 октября 2006 г.

    Устали ждать обновление Debian пакета?

    Оказывается в debian'е пакеты можно не только собирать из исходников, а еще эти исходники можно обновлять до upstream версии с сайта автора, а потом собирать deb пакет.

    akshaal@akshaal:/tmp% apt-get source libtorrent9
    Чтение списков пакетов... Готово
    Построение дерева зависимостей... Готово
    Нужно загрузить 472kB архивов с исходными текстами.
    Получено:1 http://debian.org.ua unstable/main libtorrent 0.10.2-1 (dsc) [634B]
    Получено:2 http://debian.org.ua unstable/main libtorrent 0.10.2-1 (tar) [453kB]
    Получено:3 http://debian.org.ua unstable/main libtorrent 0.10.2-1 (diff) [18,2kB]
    Получено 472kB за 3s (143kB/c)
    gpg: Подпись создана Чтв 21 Сен 2006 07:41:55 EEST ключом DSA с ID 1880283C
    gpg: Не могу проверить подпись: открытый ключ не найден
    dpkg-source: extracting libtorrent in libtorrent-0.10.2
    dpkg-source: unpacking libtorrent_0.10.2.orig.tar.gz
    dpkg-source: applying ./libtorrent_0.10.2-1.diff.gz

    akshaal@akshaal:/tmp% cd libtorrent-0.10.2

    akshaal@akshaal:/tmp/libtorrent-0.10.2% uscan
    libtorrent: Newer version (0.10.3) available on remote site:
    http://libtorrent.rakshasa.no/downloads/libtorrent-0.10.3.tar.gz
    (local version is 0.10.2)
    libtorrent: Successfully downloaded updated package libtorrent-0.10.3.tar.gz
    and symlinked libtorrent_0.10.3.orig.tar.gz to it

    akshaal@akshaal:/tmp/libtorrent-0.10.2% uupdate ../libtorrent-0.10.3.tar.gz
    New Release will be 0.10.3-1.
    -- Untarring the new sourcecode archive ../libtorrent-0.10.3.tar.gz
    Success! The diffs from version 0.10.2-1 worked fine.
    Remember: Your current directory is the OLD sourcearchive!
    Do a "cd ../libtorrent-0.10.3" to see the new package

    akshaal@akshaal:/tmp/libtorrent-0.10.2% cd ../libtorrent-0.10.3/

    akshaal@akshaal:/tmp/libtorrent-0.10.3% dpkg-buildpackage -rfakeroot -us -uc

    вторник, 17 октября 2006 г.

    JCA

    Допустим мы пишем JCA RA который поддерживает исходящие соединения к EIS. Все написали. Верифицировали. Продеплоили в GlassFish. Все OK. Теперь продеплоили какое-то приложение, чтобы протестировать соединение к EIS. Запускаем. А оно нам @#%!: "Exception in NamingManagerImpl copyMutableObject() ... java.io.NotSerializableException".
    Покопавшись мы выясняем, что падение происходит при копировании нашей имплементации java.resource.cci.ConnectionFactory интерфейса. А имеено в нашем классе ConnectionFactoryImpl есть не Serealizable поле, например ManagedConnectionFactory (содержащая сокет например). Убив N часов времени на поиски в гугле, выясняем, что GlassFish в JNDI помещает копии объектов! Наматерившись и решив, что разработчикам JNDI реализации виднее, мы делаем неугодное в ConnectionFactoryImpl поле transient'ым. А вдруг этот объект будет использоваться, только чтобы getReference вызвать? Хрен там. Повозившись еще, оказывается, что dependency injection отдает нам именно копию из JNDI у которой наше transient поле установленно в NULL!

    Даём GlassFish'у последний шанс. Читаем его исходники и оказывается, что не все объекты помещаются в JNDI в сереализованном виде. Так например Connector'ы должны помещаться не сереализованными! Хм, а как же оно определяет, что этот объект коннектор? А вот как:

    private boolean isConnector(String logicalJndiName){
    return (logicalJndiName.indexOf(EIS_STRING)!=-1);
    }
    где EIS_STRING = "/eis/".

    Короче, чтобы не иметь лишний геморрой: ConnectionFactory экземпляры должны помещаться в субконтексте /eis/ ! Если теперь поискать в гугле по словам "eis subcontext" то находятся рекомендации, а не требования!.

    Вообще, это частая ошибка, проявляется в виде NPE (null pointer exception) при вызове transient полей (activemq этим страдает). Мне кажется, в ConnectionFactoryImpl разумно вставить:

    /**
    * Ensure that managedConnectionFactory is not null.
    * @throws ResourceException if managedConnectionFactory is null.
    */
    protected void ensureManagedConnectionFactory () throws ResourceException {
    if (this.managedConnectionFactory == null) {
    throw new ResourceException (
    "No reference to managed connection factory exists."
    + " Either it is a bug of the RA or your JNDI resource"
    + " is not in the /eis/ subcontext");
    }

    и вызывать этот метод перед использованием this.managedConnectionFactory внутри ConnectionFactoryImpl.