понедельник, 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 сам). А дамп всей ОЗУ неплохо так разобранный во времена когда искал как управлять диодами я где-то посеял..
Вобщем я решил пока этот вопрос отложить. Посмотрим как оно будет анноить или нет.
--------
Будущие версии программы можно будет найти здесь.
Другая программа для уменьшения расхода заряда батареи описана здесь.
Обновление!
Вот 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 сам). А дамп всей ОЗУ неплохо так разобранный во времена когда искал как управлять диодами я где-то посеял..
Вобщем я решил пока этот вопрос отложить. Посмотрим как оно будет анноить или нет.
--------
Будущие версии программы можно будет найти здесь.
Другая программа для уменьшения расхода заряда батареи описана здесь.
суббота, 17 ноября 2007 г.
iphone?
Прочитал недавно статью про iphone. Какой он там весь удобный и все такое. Заразился идеей о управлении КПК (WM5) с помощью одной руки и даже одного пальца. Для меня это актуально, так как пользуюсь КПК в метро. Поменял часть софта - менеджер задач и лоунчер. А с клавиатурой пришлось повозится. Перепробовал много вариантов. PocketCM уовлетворила почти всем, кроме того, что была глючная и не давала сделать такую раскладку какую я хочу. И вот я случайно наткнулся на eurokbd. Программа интересная тем, что opensource (хоть и слегка кривовато написана, но да ладно, дареному коню... спасибо автору огромное!). Подправил для нее раскладку, перерисовал скины, подправил исходники и вот, что получилось.
Картинко 1
Картинко 2
Картинко 3
Картинко 4
Первое, что нужно было сделать - придумать раскладку. Раскладка должна была быть такой, чтобы легко попадать по клавишам большим пальцем моей руки (держа КПК той же рукой). Qwerty не подходит. Был соблазн набросать как придется новую раскладку, но это абсолютно не аправданно. Решил сгенерировать оптимальный вариант с учетом частоты следования букв друг за другом. Написал на perl анализатор текста на входе которого текст, на выходе описание для graphwiz (буква -> буква [вес]). Вес являлся частотой появления комбинации букв. На основе такого описания graphwiz построил графики, расположив узлы таким образом, чтобы расстояния между элементами с наибольшими весами было наименьшее. Таким образом минимизируется время набор слов. На графиках линии связей между буквами убраны для простоты картинки.
Инглиш
Русский
Далее нарисовал скины. А саму eurokbd пришлось пропатчить, чтобы она активную кнопку подсвечивала белым фоном (а не черным как это жестко вбито в исходниках), а также не выводила меню переключения раскладки, а переключала ее сразу же с rus на lat и с lat на rus). Итого получилась очень удобная клавиатура! Несмотря на то, что раскладка не qwerty - привыкаешь ОЧЕНЬ быстро. Я уже не могу на стандартную мелкую смотреть без тошноты.
http://toril.ru/pda/eukbak.zip
Для интересующихся, скрипт на perl для анализа текста (textanal.pl):
#!/usr/bin/perl
# Akshaal (C) 2007
# Creates dot graph for link between characters
use warnings;
use strict;
use utf8;
use encoding 'utf8';
my %ass;
my $prev;
my %allow;
for (split '', "йцукенгшщзхъфывапролджэячсмитьбюё ") {
$allow{$_} = 1;
};
sub add ($) {
my $c = shift;
if (defined $prev) {
if (ord($prev) > ord($c)) {
$ass{"$prev$c"} ++;
} else {
$ass{"$c$prev"} ++;
}
}
$prev = $c;
}
# Calc weights
while (<>) {
chop;
for my $c (split '') {
$c = lc $c;
unless ($allow{$c}) {
$c = ' ';
}
add ($c);
}
add (' ');
}
# Create dot
print "graph D {\n";
for my $link (keys %ass) {
my $weight = $ass {$link};
my $a = substr $link, 0, 1;
my $b = substr $link, 1, 1;
print " \"$a\" -- \"$b\" [weight=$weight, style=invis];\n";
}
print "}\n";
А это патч на eurokbd:
--- eurokbd.cpp.old 2007-10-11 20:45:00.000000000 +0300
+++ eurokbd.cpp 2007-11-17 17:58:48.000000000 +0200
@@ -369,10 +369,12 @@
if(vk==_VK_MOD)
{
- if( m_subkeyCurrent!=SUBKEY_PARENT )
- {
- LoadConfig(m_subkeyCurrent->data.pw);
- }
+ if(0==wcscmp(m_pwCurrentConfigName.ptr(), L"rus"))
+ {
+ LoadConfig(L"lat");
+ } else {
+ LoadConfig(L"rus");
+ }
} else if(vk==_VK_FN)
{
// } else if(vk==_VK_CUT)
@@ -788,8 +790,8 @@
COLORREF bgColor, fgColor;
if( m_subkeyCurrent==p )
{
- fgColor = RGB(0xFF,0xFF,0xFF);
- bgColor = RGB(0x00,0x00,0x00);
+ bgColor = RGB(0xFF,0xFF,0xFF);
+ fgColor = RGB(0x00,0x00,0x00);
} else
{
fgColor = m_config->m_colors[p->group][0];
@@ -832,8 +834,8 @@
COLORREF bgColor, fgColor;
if( m_subkeyCurrent==SUBKEY_PARENT )
{
- fgColor = RGB(0xFF,0xFF,0xFF);
- bgColor = RGB(0x00,0x00,0x00);
+ bgColor = RGB(0xFF,0xFF,0xFF);
+ fgColor = RGB(0x00,0x00,0x00);
} else
{
fgColor = m_config->m_colors[m_keyCurrent->group][0];
@@ -987,43 +989,6 @@
}
if(m_hwndPop)
{
- // кнопка Mod
- if(m_keyCurrent->vk==_VK_MOD)
- {
- m_keyCurrent->subkeys.destroy();
-
- WIN32_FIND_DATA ffdata;
- WCHAR* pwMask = new WCHAR[wcslen(g_pwDllDir)+6+1];
- wcscpy(pwMask, g_pwDllDir);
- wcscat(pwMask, L"\\*.txt");
- //UINT iLenMask = wcslen(swMask);
- HANDLE hFind = FindFirstFile(pwMask, &ffdata);
- if( hFind!=INVALID_HANDLE_VALUE )
- {
- int i = 0;
- do
- {
- SUBKEYENTRY* psk = new SUBKEYENTRY;
- psk->vk = _VK_MOD;
- //psk->data.pw= new WCHAR[iLenMask-5+wcslen(ffdata.cFileName)+1];
- //wcscpy(psk->data.pw, swMask);
- //wcscpy(psk->data.pw+iLenMask-5, ffdata.cFileName);
- ffdata.cFileName[wcslen(ffdata.cFileName)-4] = '\0'; // trim .txt
- psk->data.pw= _wcsdup(ffdata.cFileName);
- psk->left = 0;
- psk->top = (i+1)*-16;
- psk->right = 80;
- psk->bottom = (i+0)*-16;
- psk->group = SK_GROUP_LATIN;
- psk->desc.pw= 0;
- m_keyCurrent->subkeys.add_first(psk);
- i ++;
- } while(FindNextFile(hFind, &ffdata));
- FindClose(hFind);
- }
- delete []pwMask;
- }
-
// кнопка Fn
if(m_keyCurrent->vk==_VK_FN)
{
@@ -1148,7 +1113,7 @@
// если нет обоев - рисуем кнопочку, если кнопка текущая - рисуем чёрную кнопочку
if(!m_hbmSkin || p==m_keyCurrent)
{
- COLORREF bgColor = p==m_keyCurrent ? RGB(0x00,0x00,0x00) : m_config->m_colors[p->group][1];
+ COLORREF bgColor = p==m_keyCurrent ? RGB(0xff,0xff,0xff) : m_config->m_colors[p->group][1];
CGdiObj>HBRUSH> hBrushBg2 = CreateSolidBrush(bgColor);
assert(hBrushBg2);
DrawButton(hdc, r0, hBrushBg2, hPenTL, hPenBR);
@@ -1158,13 +1123,13 @@
if (0!=p->data.pw)
{
SelectObject(hdc, m_hFontBig);
- COLORREF fgColor = p==m_keyCurrent ? RGB(0xFF,0xFF,0xFF) : m_config->m_colors[p->group][0];
+ COLORREF fgColor = p==m_keyCurrent ? RGB(0x00,0x00,0x00) : m_config->m_colors[p->group][0];
DrawText(hdc, p->data, &rText, DT_NOPREFIX | DT_BOTTOM | DT_LEFT, fgColor);
if (0!=p->desc.pw) // надстрочный знак
{
SelectObject(hdc, m_hFontIndex);
- COLORREF fgColor2 = p==m_keyCurrent ? RGB(0xFF,0xFF,0xFF) : m_config->m_colorDesc;
+ COLORREF fgColor2 = p==m_keyCurrent ? RGB(0x00,0x00,0x00) : m_config->m_colorDesc;
//if(0!=p->desc2.pw) // есть оба знака - надстрочный двинем чуть левее
// rText.right -= 7*m_vga;
DrawText(hdc, p->desc, &rText, DT_NOPREFIX | DT_RIGHT | DT_TOP, fgColor2);
@@ -1175,13 +1140,13 @@
{
rText.top += 4*m_vga;
SelectObject(hdc, m_hFontIndex);
- COLORREF fgColor2 = p==m_keyCurrent ? RGB(0xFF,0xFF,0xFF) : m_config->m_colorDesc2;
+ COLORREF fgColor2 = p==m_keyCurrent ? RGB(0x00,0x00,0x00) : m_config->m_colorDesc2;
DrawText(hdc, p->desc2, &rText, DT_NOPREFIX | DT_RIGHT | DT_TOP, fgColor2);
}
} else if (0!=p->desc.pw) // текст вроде 'Caps'
{
SelectObject(hdc, m_hFontSmall);
- COLORREF fgColor2 = p==m_keyCurrent ? RGB(0xFF,0xFF,0xFF) : m_config->m_colors[p->group][0];
+ COLORREF fgColor2 = p==m_keyCurrent ? RGB(0x00,0x00,0x00) : m_config->m_colors[p->group][0];
DrawText(hdc, p->desc, &rText, DT_NOPREFIX | DT_CENTER | DT_VCENTER, fgColor2);
}
}
@@ -1205,7 +1170,6 @@
{
m_keyCurrent = pKey;
if(0==m_nPopupDelay ||
- m_keyCurrent->vk==_VK_MOD ||
m_keyCurrent->vk==_VK_FN )
{
PopUp();
Долой стилус!
вторник, 23 октября 2007 г.
locale
Теперь так:
> echo $LANG
en_GB.UTF-8
Избавился еще от одной олдскульной вещи: локали в виде ru_RU.koi8-r. Пока пришлось заменить rxvt на rxvt-unicode-lite. Остальное вроде слега поднастроить и допилить. Centericq глючит (позицианирует курсор как будт-то вместо одного символа вставляются два (считает не символы а байты сволочь), но в пределах нормы, тем более, что в планах избавление от centericq. Рано или поздно это должно было случится.
> echo $LANG
en_GB.UTF-8
Избавился еще от одной олдскульной вещи: локали в виде ru_RU.koi8-r. Пока пришлось заменить rxvt на rxvt-unicode-lite. Остальное вроде слега поднастроить и допилить. Centericq глючит (позицианирует курсор как будт-то вместо одного символа вставляются два (считает не символы а байты сволочь), но в пределах нормы, тем более, что в планах избавление от centericq. Рано или поздно это должно было случится.
пятница, 19 октября 2007 г.
JSF & Facelets
В чем была суть проблемы:
Когда в facelet'ах мы создаем template или tag на основе template'а, мы можем передавать в него параметры. Например custom tag с именем link имеет параметр myCoolAction, а тушка определения тэга выглядит банально:
<h:commandLink action="#{myCoolAction}">
Мы пользуемся тэгом:
<customNs:link myCoolAction="hello">
И ожидаем, что это равносильно <h:commandLink action="hello">.
Но не тут-то было. Facelet'ы передает аргументы внутрь template'а заворачивая их в ValueExpression. Тоесть у action аттрибута значение на самом деле оказывается не типа String, а типа ValueExpression. Умный commandLink это просекает и решает, что раз это не string, то это биндинг! А как же? Что это может быть еще? И обламывается. Ибо после eval'а на ValueExpression он таки получает String, а не MethodExpression - как нужно для биндинга к методу. Вот такая вот фигня.
Мне удалось это вылечить написав на java другой custom tag, который берет ValueExpression и превращает его в MethodExpression возвращающий оригинальный ValueExpression. Костыль.
На самом деле, это не самое страшное в faceletах. Хотя признаюсь, без facelet'ов JSF хочется об стену убить.
Когда в facelet'ах мы создаем template или tag на основе template'а, мы можем передавать в него параметры. Например custom tag с именем link имеет параметр myCoolAction, а тушка определения тэга выглядит банально:
<h:commandLink action="#{myCoolAction}">
Мы пользуемся тэгом:
<customNs:link myCoolAction="hello">
И ожидаем, что это равносильно <h:commandLink action="hello">.
Но не тут-то было. Facelet'ы передает аргументы внутрь template'а заворачивая их в ValueExpression. Тоесть у action аттрибута значение на самом деле оказывается не типа String, а типа ValueExpression. Умный commandLink это просекает и решает, что раз это не string, то это биндинг! А как же? Что это может быть еще? И обламывается. Ибо после eval'а на ValueExpression он таки получает String, а не MethodExpression - как нужно для биндинга к методу. Вот такая вот фигня.
Мне удалось это вылечить написав на java другой custom tag, который берет ValueExpression и превращает его в MethodExpression возвращающий оригинальный ValueExpression. Костыль.
На самом деле, это не самое страшное в faceletах. Хотя признаюсь, без facelet'ов JSF хочется об стену убить.
пятница, 18 мая 2007 г.
Комбинации
Казалось бы просто, но это заняло у меня два часа, чтобы написать такую функцию. Но теперь я знаю истинную природу вещей!
combr :: [[a]] -> [[a]]
combr [l] = map (\x -> [x]) l
combr (l : tl) = concat $ map (\ll -> map (:ll) l) $ combr tl
print $ combr [[1,2], [3,4], [5,6,7]]
[[1,3,5],[2,3,5],[1,4,5],[2,4,5],[1,3,6],[2,3,6],[1,4,6],
[2,4,6],[1,3,7],[2,3,7],[1,4,7],[2,4,7]]
суббота, 7 апреля 2007 г.
Сломал
На второй день после покупки сломал dreambox 500 (ресивер на linux для спутникового телевиденья). Циклится при загрузке. Как это чинить - идей нет, поэтому решил перепрошить. Щас с легкостью перепрошивается.
Такая вот фигня при загрузке:
Такая вот фигня при загрузке:
[...]
Multiplex thread got Data
Command='ZAP'
Zap data ,
Multiplex thread got Data
Dropping connection
active count=0
rc=0 '0,'
------------> changed! 0
no transponder 1 444
[TUNE] tune failed
Segmentation fault
воскресенье, 25 марта 2007 г.
вторник, 13 марта 2007 г.
OSD Desktop
Еще один пост, который давно откладываю (уже годы). Вобщем, я записал ролик о том, как мой десктоп выглядит (640x480 10fps 2mb или 1024x768 10fps 6mb). Идея сделать его OSD'ным витала в воздухе задолго до того, как я написал первые строки кода. В результате эволюции десктопа, я привык работать в полноэкранном режиме. Часики, измерители и прочие пищали быстро сгинули с моего рабочего стола. И несмотря на то, что я оказался в мире без уведомлений, я был счастлив. И тогда OSD пришло ко мне как решение удержать программы в полноэкранном режиме и в то же время быть в курсе событий. Используя python и библиотеку OSD для него, я написал демона событий. Демон читает строки из файла ~/log/events и парсит их согласно шаблонам:
string - добавляет строку в список отображаемых строк.
[][][]\d\d\d\d: string - тоже самое, что и в предыдущем случае, но отображает строку заданное количество мс.
\d\d\:\d\d:\d\d: string - тоже, что и первый случай, но с датой. Дата не отображается на экране.
\d\d\:\d\d:\d\d: [][][]\d\d\d\d: string - тоже, что и второй случай, но с комментарием из третьего случая.
После этого пришло время реализовать программы, которые писали бы в файл ~/log/events. Первой такой программой стала aktimelog, которая пишет события о текущем времени каждые 25 минут. Еще сделал: плагин для irssi, чтобы видеть публичные сообщения, приватные или и то и то, мониторить переключение раскладки клавиатуры, переключение рабочих столов, уведомления о почте, уведомления шела. Так же стоит сказать, что переключение рабочих столов происходит по шоткатам. Например, если вы нажимаете MOD-E, то в дополнение к переключению, ion3 проверяет а запущен ли emacs, и если не запущен и вы подтвердите запуск, то запускает его. Я обычно знаю, куда хочу переключиться, поэтому не трачу время на бег по списку программ или тыкание на тулбар (как это делают виндузятники и прочие линуксойды). Итого, MOD-e для emacs, MOD-p -- revelation, MOD-c -- eclipse, MOD-b -- browser, MOD-1 -- первый терминал, MOD-2 -- второй терминал... и тд. Вот так устроен мой десктоп. А ваш как? :)
Исходники.
После этого пришло время реализовать программы, которые писали бы в файл ~/log/events. Первой такой программой стала aktimelog, которая пишет события о текущем времени каждые 25 минут. Еще сделал: плагин для irssi, чтобы видеть публичные сообщения, приватные или и то и то, мониторить переключение раскладки клавиатуры, переключение рабочих столов, уведомления о почте, уведомления шела.
Исходники.
пятница, 9 марта 2007 г.
LPTRA
Для EE фанатиков, я реализовал адаптер ресурсов (JCA 1.5 через CCI), это правильный способ работы с параллельным портом из J2ee приложения. Чтобы использовать адаптер, нужно установить UParPort. Затем продеплоить этот RAR (resource adapter archive) в сервер приложений. Когда это будет сделано, создайте датасоурс для LPTRA. При создании надо будет указать имена пинов, типа такого: 1PinName=eye1, 2PinName=eye2 и т.д.. Вот и все. В дополнение можно сказать исходники LPTRA.
Пример:
Пример:
@Resource (name = "eis/ParPort")
private ConnectionFactory connFactory;
Connection conn = null;
try {
conn = connFactory.getConnection();
Interaction interaction = conn.createInteraction ();
MappedRecord r =
connFactory.getRecordFactory ().createMappedRecord ("");
r.put ("eye1", true); // turn eye1 pin into the on state
r.put ("eye2", false); // turn eye2 off
interaction.execute (null, r);
} catch (ResourceException e) {
e.printStackTrace (); // Not sexy
} finally {
if (conn != null) {
try {
conn.close();
} catch (ResourceException e) {
e.printStackTrace (); // Not sexy
}
}
}
UParPort
Давно я планировал выложить эту программку. UParPort - библиотека для работы с параллельным портом (портом принтера) из Java программ. Но в отличии от parport, эта библиотека не требует привилегий root'а. Есть главный класс UParPort в пакете package ru.toril.uparport. В качестве аргумента он получает имя устройства. Имя устройства выглядит типа "/dev/par0" или "lpt1". После создания экземпляра класса можно использовать следующие методы: getData, getStatus setData, close. isClosed, toString. Итак, бинарники и исходники UParPort..
понедельник, 5 марта 2007 г.
WM5DevSpy
Выкладываю утилиту для мониторинга обращений к устройствам WM5. Если вы не программист-хакер, то вам программа не нужна. А нужна она вам, если вы хотите видеть с какими аргументами и когда вызываются функции того или иного драйвера. Перед использованием программу нужно скомпилировать. Имя устройсва без труда найдете в файле WM5DevSpy.c - если оно вам и правда нужно. Делать нормальный гуи лень. Как бонус данное приложение показывает какие программы обслуживают какие прерывания и какими нитями.
Пример лога:
Пример лога:
2007.02.22 00:15:32: Starting ------------------------------------------------------
2007.02.22 00:15:33: interrupt 5 (abs 13): event struct at 8ffb2818, thread struct at 8efb4024, owner proc at 8c5976d0, proc name=NK.EXE, thread start addr=8c215240
2007.02.22 00:15:33: interrupt 8 (abs 16): event struct at 8f7a5xf0, thread struct at 8e7a2a64, owner proc at 8c597ad0, proc name=gwes.exe, thread start addr=015c39b4
2007.02.22 00:15:33: interrupt 9 (abs 17): event struct at 8f796yc4, thread struct at 8e785400, owner proc at 8c597ad0, proc name=gwes.exe, thread start addr=01e944e4
[...]
2007.02.22 00:15:34: fsDev_t at: 06048c50
2007.02.22 00:15:34: LegalName: BAT1:
2007.02.22 00:15:34: DeviceName: BAT1
2007.02.22 00:15:34: BusName: BuiltInPhase1_0_26_0
2007.02.22 00:15:34: DeviceKey: Drivers\BuiltIn\Battery
2007.02.22 00:15:34: control (openData=0x00000001, code=0x00290400, inBuf=0x0806fa8c, inSize=0x00000004, outBuf=0x0806fa60, outSize=0x00000014, outUsed=0x0806fa20) -> 0x00000001
2007.02.22 00:15:34: [ *outUsed : 0x00000018 ]
2007.02.22 00:15:34: IN:
2007.02.22 00:15:34: 01 00 00 00
2007.02.22 00:15:34: OUT:
2007.02.22 00:15:34: 00 08 5a 00 ff ff ff ff
2007.02.22 00:15:34: ff ff ff ff 00 ff 00 00
2007.02.22 00:15:34: ff ff ff ff ff ff ff ff
2007.02.22 00:15:37: Calls to open function: 0
2007.02.22 00:15:37: Calls to close function: 0
2007.02.22 00:15:38: Calls to control function: 1
2007.02.22 00:15:38: Calls to read function: 0
2007.02.22 00:15:38: Calls to write function: 0
2007.02.22 00:15:38: Calls to seek function: 0
2007.02.22 00:15:38: Calls to powerup function: 0
2007.02.22 00:15:38: Calls to powerdn function: 0
2007.02.22 00:15:38: ----------------------- stop -------------------------
воскресенье, 4 марта 2007 г.
LooxLight 2007-03-04
Подробнее о Looxlight (утилита для Fujitsu-Siemens Loox N560/C550) смотрите здесь.
Сделал новую версию LooxLight. Изменения:
Полная поддержка GPS светодиода.
Поддержка bluetooth стека от Broadcom.
Полная поддержка индиктора питания.
Лучше реализована поддержка индикатора клавиатуры (теперь переживает изменение яркости).
LooxLight теперь не EXE, а DLL. Это лучше тем, что в wince есть ограничение в 32 процесса.
В два раза меньшее потребление памяти, чем раньше
CAB архив в ZIP'е: тут.
Исходные коды (GPL): тут.
Будущие версии программы можно будет найти здесь.
Другая программа для уменьшения расхода заряда батареи описана здесь.
Сделал новую версию LooxLight. Изменения:
CAB архив в ZIP'е: тут.
Исходные коды (GPL): тут.
Будущие версии программы можно будет найти здесь.
Другая программа для уменьшения расхода заряда батареи описана здесь.
понедельник, 19 февраля 2007 г.
Вирус для WinCE
Конкретно так изучил внутренности WM5. Может вспомнить детство и написать под него вирус? Надо перейти в режим ядра? Нет проблем, есть ф-ия SetKMode. Надо прочитать память какого-то прилажения? Нет проблем, бери да читай. Надо перехватит системный вызов, обращение к драйверу или прерывание? И это можно. :)
воскресенье, 11 февраля 2007 г.
WM5EventSpy
Сегодня очень продуктивный день. Сегодня я реализовал утилиту для мониторига системных событий в Windows Mobile 2005. Если вы запустите WM5EventSpy, оно создаст файл с именем \SD-MMCard\WM5EventSpy.log. Туда утилита запишет имена всех зарегестрированных приложениями событий. Затем утилита будет ожидать срабатывания какого либо события и писать об этом в лог, когда одно из событий сработает. Тут зип архив с исполняемым файлом WM5EventSpy внутри. А тут его исходные коды. При написании утилиты были использованы недокументированные структуры ядра WM5, поэтому оно врятли заработает на какой-то другой версии ОС.
Пример лога:
Пример лога:
2007.02.11 22:28:36: Started ------------------------------------------------------
2007.02.11 22:28:36: - - - - Start of event list - - - -
2007.02.11 22:28:36: 1: 'WM5EventSpy/SomeEvent', manualreset=0, pIntrProxy=00000000
2007.02.11 22:28:36: 2: '50650_ConnMgr', manualreset=1, pIntrProxy=00000000
2007.02.11 22:28:36: 3: 'PluginInitialized', manualreset=0, pIntrProxy=00000000
2007.02.11 22:28:36: 4: 'HistoryMappingsClosedEvent', manualreset=1, pIntrProxy=00000000
2007.02.11 22:28:36: 5: 'CookiesMappingsClosedEvent', manualreset=1, pIntrProxy=00000000
2007.02.11 22:28:36: 6: 'ContentMappingsClosedEvent', manualreset=1, pIntrProxy=00000000
2007.02.11 22:28:36: 7: 'HistoryCloseMappingsEvent', manualreset=1, pIntrProxy=00000000
2007.02.11 22:28:36: 8: 'CookiesCloseMappingsEvent', manualreset=1, pIntrProxy=00000000
2007.02.11 22:28:36: 9: 'ContentCloseMappingsEvent', manualreset=1, pIntrProxy=00000000
2007.02.11 22:28:36: 10: 'ActiveSync:Started', manualreset=1, pIntrProxy=00000000
2007.02.11 22:28:36: 11: 'CE2STATEEVENT1', manualreset=0, pIntrProxy=00000000
2007.02.11 22:28:36: 12: 'CE2COMMANDDONEEVENT', manualreset=0, pIntrProxy=00000000
2007.02.11 22:28:36: 13: 'CE2COMMANDEVENT', manualreset=0, pIntrProxy=00000000
2007.02.11 22:28:36: 14: '__SD_CARD_INOUT', manualreset=0, pIntrProxy=00000000
2007.02.11 22:28:36: 15: 'tiacwlnControlReady', manualreset=0, pIntrProxy=00000000
2007.02.11 22:28:36: 16: 'tiacwlnResponseToControlReady', manualreset=0, pIntrProxy=00000000
2007.02.11 22:28:36: 17: '_LEAP_LIST_CHANGE', manualreset=0, pIntrProxy=00000000
2007.02.11 22:28:36: 18: '_BT_STATE_OFF', manualreset=0, pIntrProxy=00000000
2007.02.11 22:28:36: 19: '_BT_STATE_ON', manualreset=0, pIntrProxy=00000000
2007.02.11 22:28:36: 20: 'WLANStateNotified', manualreset=0, pIntrProxy=00000000
2007.02.11 22:28:36: 21: 'LooxLight/FlashlightEvent', manualreset=0, pIntrProxy=00000000
2007.02.11 22:28:36: 22: 'LooxLight/SetupEvent', manualreset=0, pIntrProxy=00000000
2007.02.11 22:28:36: 23: 'LooxLight/ExitEvent', manualreset=0, pIntrProxy=00000000
2007.02.11 22:28:36: 24: 'SYSTEM\netui-TNETWLN1', manualreset=0, pIntrProxy=00000000
2007.02.11 22:28:36: 25: 'WLANStatusHasChanged', manualreset=0, pIntrProxy=00000000
2007.02.11 22:28:36: 26: 'ProfileStatusEvent', manualreset=0, pIntrProxy=00000000
2007.02.11 22:28:36: 27: 'ConnMgrApiReady', manualreset=1, pIntrProxy=00000000
2007.02.11 22:28:36: 28: 'DTPT_SRV_STARTED', manualreset=1, pIntrProxy=00000000
2007.02.11 22:28:36: 29: 'BindingMapSharedMemoryEvent', manualreset=1, pIntrProxy=00000000
2007.02.11 22:28:36: 30: 'All_Awake', manualreset=1, pIntrProxy=00000000
2007.02.11 22:28:36: 31: 'BT_EVENT_SECURITY', manualreset=0, pIntrProxy=00000000
2007.02.11 22:28:36: 32: '_KeyPress', manualreset=0, pIntrProxy=00000000
2007.02.11 22:28:36: 33: 'Shell_Ready', manualreset=1, pIntrProxy=00000000
2007.02.11 22:28:36: 34: '$*@DBChanged#%&', manualreset=1, pIntrProxy=00000000
2007.02.11 22:28:36: 35: '$*@RegChanged#%&', manualreset=1, pIntrProxy=00000000
2007.02.11 22:28:36: 36: 'SSTimeChange', manualreset=0, pIntrProxy=00000000
2007.02.11 22:28:36: 37: 'SSUpdatePower', manualreset=0, pIntrProxy=00000000
2007.02.11 22:28:36: 38: '$*EventInboxEnableSound*$', manualreset=1, pIntrProxy=00000000
2007.02.11 22:28:36: 39: '$*EventInboxDisableSound*$', manualreset=1, pIntrProxy=00000000
2007.02.11 22:28:36: 40: 'SSUpdateRecalc', manualreset=0, pIntrProxy=00000000
2007.02.11 22:28:36: 41: 'SYSTEM\SipTimerActive', manualreset=1, pIntrProxy=00000000
2007.02.11 22:28:36: 42: 'EventSounds_GlobalStopEvent', manualreset=1, pIntrProxy=00000000
2007.02.11 22:28:36: 43: 'MS_GWE_TPC_cont_startup', manualreset=1, pIntrProxy=00000000
2007.02.11 22:28:36: 44: 'MS_GWE_TPC_startup', manualreset=1, pIntrProxy=00000000
2007.02.11 22:28:36: 45: 'TouchPanelCommandEvent', manualreset=0, pIntrProxy=00000000
2007.02.11 22:28:36: 46: 'CgrTabletInnerEvent', manualreset=1, pIntrProxy=00000000
2007.02.11 22:28:36: 47: 'CgrTabletEvent', manualreset=1, pIntrProxy=00000000
2007.02.11 22:28:36: 48: '_SSP_INIT_OK_EVENT3', manualreset=1, pIntrProxy=00000000
2007.02.11 22:28:36: 49: 'WatsonUploadClientReady', manualreset=0, pIntrProxy=00000000
2007.02.11 22:28:36: 50: 'WALNStatusChangeEvent', manualreset=0, pIntrProxy=8f9fba3c
2007.02.11 22:28:36: 50: 'system/events/bluetooth/PairingChange', manualreset=1, pIntrProxy=00000000
2007.02.11 22:28:36: 51: 'system/events/bluetooth/HardwareChange', manualreset=1, pIntrProxy=00000000
2007.02.11 22:28:36: 52: 'system/events/bluetooth/DeviceIdChange', manualreset=1, pIntrProxy=00000000
2007.02.11 22:28:36: 53: 'system/events/bluetooth/ConnectivityChange', manualreset=1, pIntrProxy=00000000
2007.02.11 22:28:36: 54: 'system/events/bluetooth/SecurityChange', manualreset=1, pIntrProxy=00000000
2007.02.11 22:28:36: 55: 'system/events/bluetooth/ConnectionsChange', manualreset=1, pIntrProxy=00000000
2007.02.11 22:28:36: 56: 'system/events/bluetooth/BasebandChange', manualreset=1, pIntrProxy=00000000
2007.02.11 22:28:36: 57: 'system/events/bluetooth/StackInitialized', manualreset=1, pIntrProxy=00000000
2007.02.11 22:28:36: 58: 'IP6_ROUTE_CHANGE_EVENT', manualreset=1, pIntrProxy=00000000
2007.02.11 22:28:36: 59: 'IP6_ADDR_CHANGE_EVENT', manualreset=1, pIntrProxy=00000000
2007.02.11 22:28:36: 60: 'TAPILINE00000000', manualreset=0, pIntrProxy=00000000
2007.02.11 22:28:36: 61: 'IP_ROUTE_CHANGE_EVENT', manualreset=1, pIntrProxy=00000000
2007.02.11 22:28:36: 62: 'IP_ADDR_CHANGE_EVENT', manualreset=1, pIntrProxy=00000000
2007.02.11 22:28:36: 63: 'BTWCEShimShutdownThread', manualreset=0, pIntrProxy=00000000
2007.02.11 22:28:36: 64: 'BTWCEShimFreeLibs', manualreset=0, pIntrProxy=00000000
2007.02.11 22:28:36: 65: 'BTWCEShimLoadLibs', manualreset=0, pIntrProxy=00000000
2007.02.11 22:28:36: 66: '_SSP_INIT_OK_EVENT2', manualreset=1, pIntrProxy=00000000
2007.02.11 22:28:36: 67: 'Event_HS_PTT_Down', manualreset=0, pIntrProxy=00000000
2007.02.11 22:28:36: 68: 'Event_HS_PTT_Up', manualreset=0, pIntrProxy=00000000
2007.02.11 22:28:36: 69: 'CPUSpeed4lter', manualreset=0, pIntrProxy=00000000
2007.02.11 22:28:36: 70: '_SSP_INIT_OK_EVENT', manualreset=1, pIntrProxy=00000000
2007.02.11 22:28:36: 71: '_hLedChangeEvent_Name_', manualreset=0, pIntrProxy=00000000
2007.02.11 22:28:36: 72: 'BackLightOverTempEvent', manualreset=0, pIntrProxy=00000000
2007.02.11 22:28:36: 73: 'BackLightNormTempEvent', manualreset=0, pIntrProxy=00000000
2007.02.11 22:28:36: 74: 'BackLightHighTempEvent', manualreset=0, pIntrProxy=00000000
2007.02.11 22:28:36: 75: 'BackLightChangeEvent', manualreset=0, pIntrProxy=00000000
2007.02.11 22:28:36: 76: 'BackLightActiveEvent', manualreset=0, pIntrProxy=00000000
2007.02.11 22:28:36: 77: 'BackLightNotifyEvent', manualreset=0, pIntrProxy=00000000
2007.02.11 22:28:36: 78: 'PowerManager/SystemIdleTimerReset', manualreset=0, pIntrProxy=00000000
2007.02.11 22:28:36: 79: 'PowerManager/ReloadActivityTimeouts', manualreset=0, pIntrProxy=00000000
2007.02.11 22:28:36: 80: 'PowerManager/UserActivity_Inactive', manualreset=1, pIntrProxy=00000000
2007.02.11 22:28:36: 81: 'PowerManager/UserActivity_Active', manualreset=1, pIntrProxy=00000000
2007.02.11 22:28:36: 82: 'PowerManager/ActivityTimer/UserActivity', manualreset=0, pIntrProxy=00000000
2007.02.11 22:28:36: 83: 'SYSTEM/SystemStarted', manualreset=1, pIntrProxy=00000000
2007.02.11 22:28:36: 84: 'system/events/notify/APIReady', manualreset=1, pIntrProxy=00000000
2007.02.11 22:28:36: 85: 'SYSTEM/ShellAPIReady', manualreset=1, pIntrProxy=00000000
2007.02.11 22:28:36: 86: 'SYSTEM/BatteryAPIsReady', manualreset=1, pIntrProxy=00000000
2007.02.11 22:28:36: 87: 'SYSTEM/NLedAPIsReady', manualreset=1, pIntrProxy=00000000
2007.02.11 22:28:36: 88: 'SYSTEM/CertChange', manualreset=0, pIntrProxy=00000000
2007.02.11 22:28:36: 89: 'SYSTEM/BootPhase2', manualreset=1, pIntrProxy=00000000
2007.02.11 22:28:36: 90: 'SYSTEM/DevMgrApiSetReady', manualreset=1, pIntrProxy=00000000
2007.02.11 22:28:36: 91: 'SYSTEM/PowerManagerReady', manualreset=1, pIntrProxy=00000000
2007.02.11 22:28:36: 92: 'SYSTEM/GweApiSetReady', manualreset=1, pIntrProxy=00000000
2007.02.11 22:28:36: 93: 'LASS_SRV_STARTED', manualreset=1, pIntrProxy=00000000
2007.02.11 22:28:36: 94: 'WatsonEventDumpFileReady', manualreset=0, pIntrProxy=00000000
2007.02.11 22:28:36: - - - - End of event list - --- - - -
2007.02.11 22:28:37: We are going to monitor 63 events!
2007.02.11 22:28:37: We are going to monitor 31 events!
[...]
2007.02.11 22:28:56: Event 'PowerManager/ActivityTimer/UserActivity' is signaled, avgDelay = 54, count=10!
2007.02.11 22:28:56: Event 'PowerManager/ActivityTimer/UserActivity' is signaled, avgDelay = 46, count=11!
2007.02.11 22:28:56: Monitoring of 'PowerManager/ActivityTimer/UserActivity' is disabled, current count of monitoring events=69!
2007.02.11 22:29:16: Event '$*@RegChanged#%&' is signaled, avgDelay = 0, count=1!
2007.02.11 22:29:17: Event '$*@RegChanged#%&' is signaled, avgDelay = 24, count=2!
пятница, 9 февраля 2007 г.
Synce & Linux & WM5 & Password
Когда я разрабатывал для WM5 под linux'ом мне показалось, что копировать файлы для тестирования на КПК весьма напряжно. Файлы копировались на КПК либо через MMC карточку, либо с помощью монтирования КПК как USB флешки. Оба способа совершенно не удобны, когда эти действия приходится делать каждые 5 минут. В добавок, исполняемый файл надо было запускать, чтобы увидеть как он работает. Я запускал файлы руками. Вобщем-то нет особого смысла говорить, как меня это раздражало после того как я в свое время поразрабатывал под виндой, где все эти действия выполнялись одним батничком. Тогда когда я попробовал найти что-то типа того я наткнулся на проект synce. Сначало мне показалось, что надо поставить драйвер usb-rndis. Я попытался, но оно обломалось на этапе компиляции. После небольшого изучения сайта synce я все-таки обнаружил существование новой версии драйвера "usb-rndis-lite". На этот раз получилось без проблем. После установки драйвера появилось новое сетевое устройство: rndis0. Затем надо было поставить synce утилиты и библиотеки. Это была самая жостка часть. Первым делом я попробовал следовать инструкциям с вики. Но odccm вывавал мне ошибки о d-ubs, hal и т.д.. Ошибки были откровенно тупыми, т.е. по ним нельзя никак было сказать о причине... ну это было что-то типа "d-bus error" или типа того. Тогда я попробовал vdccm.. и мне показалось, что уже лучше. Появилось что-то первое и хорошее - программа запустилась без ошибок :). В остальном все было тихо и грустно. Я начал искать в гугле слово 'vdccm' и через какое-то время нашел, что некто пользовался утилитой triggerconnection, чтобы уведомить ActiveSync. Но в моих руках triggerconnection не производила никакого эффекта ни на vdccm, ни на ActiveSync. Я прошелся по исходникам triggerconnection, было походе, что оно (утилито) отсылает пакет на порт 5679 нашего PPC. Тогда я посканил КПК с помощью nmap. Но nmap сказал мне, что портов открытых немає. У меня не было никаких идей почему порт 5679 закрыт в том время, как сам ActiveSync запущен. Я устал и заколебался. Увы, я потратил кучу времени пытаясь понять почему порт 5679 закрыт, пока в конце-концов, не предположил, что порт может оставаться открытым только несколько секунд после того как мы воткнули КПК в кроватку. И действительно, vdcomm обнаружил КПК, когда я запустил tirggerconnection сразу после того, как воткнул КПК в крэдл. В этот раз стало ясно, что одна проблема закрывала собой другую. Теперь, vdccm мог обнаруживать КПК, но он не мог держать соединение с КПК больше нескольких секунд. И снова я стал гуглить. Где-то кто-то написал, что vdccm не работает с устройствами защищенными паролями. "@!#%@#%*#$!!!" воскликнул я. Я не хотел держать КПК не защищенным или снимать пароль каждый раз как я вставляю КПК в крэдл. Короче я сделал патч для vdccm, сразу как только отреверсинженирил протокол авторизации и разобрался в коде synce. И тогда наше время пришло, пропатченный vdccm разарботал как надо! Вии! Итак вкратце, что я сделал:
1. Поставил usb-rndis-lite.
2. Поставил библиотеки: librapi2, libsynce.
3. Пропатчил vdccm.
4. Установил ifplugd. Он запускает ifup/ifdown для rndis0 когда это нужно.
5. Добавил следующее в /etc/network/interfaces:
6. Добавил строку '169.254.2.1 local-pda' в /etc/hosts.
7. Написал /usr/local/bin/triggerconnection-delayed:
8. Следующее я добавил в ~/.xsession:
9. Записал секретный пароль в ~/.pda-pwd file (chmod 0600).
Теперь могу наслаждаться использованием утилит: pls, pstatus... ставить кабы и тд.
Любые комменты приветствуются.
P.S. Патч собственно не совсем полный. Я написал его очень прямолинейно. Он не поддерживает ожидание ввода пароля откуда-то, вместо этого вы должны указать пароль через ключ -p. К сожалению, у меня нет времени это реализовывать.
1. Поставил usb-rndis-lite.
2. Поставил библиотеки: librapi2, libsynce.
3. Пропатчил vdccm.
4. Установил ifplugd. Он запускает ifup/ifdown для rndis0 когда это нужно.
5. Добавил следующее в /etc/network/interfaces:
iface rndis0 inet static
address 169.254.2.2
netmask 255.255.255.0
post-up /usr/local/bin/triggerconnection-delayed local-pda
6. Добавил строку '169.254.2.1 local-pda' в /etc/hosts.
7. Написал /usr/local/bin/triggerconnection-delayed:
#!/bin/sh
sleep 2
exec /usr/local/bin/triggerconnection $@
8. Следующее я добавил в ~/.xsession:
vdccm -d 3 -f -t -p `cat ~/.pda-pwd` 1>>~/logs/vdccm 2>>~/logs/vdccm &
9. Записал секретный пароль в ~/.pda-pwd file (chmod 0600).
Теперь могу наслаждаться использованием утилит: pls, pstatus... ставить кабы и тд.
Любые комменты приветствуются.
P.S. Патч собственно не совсем полный. Я написал его очень прямолинейно. Он не поддерживает ожидание ввода пароля откуда-то, вместо этого вы должны указать пароль через ключ -p. К сожалению, у меня нет времени это реализовывать.
воскресенье, 4 февраля 2007 г.
LooxLight-2007-02-03
Подробнее о Looxlight (утилита для Fujitsu-Siemens Loox N560/C550) смотрите здесь.
Обновление. Надеюсь исправил проблему из-за которой владельцы локализованных версий WM5 не могли поставить программу. Сообщение об ошибке сделал более детальным - если проблема все-таки не исчезла можно будет хоть понять причину более точно.
Зазипованный каб файл (2007-02-03),
Будущие версии программы можно будет найти здесь.
Другая программа для уменьшения расхода заряда батареи описана здесь.
Обновление. Надеюсь исправил проблему из-за которой владельцы локализованных версий WM5 не могли поставить программу. Сообщение об ошибке сделал более детальным - если проблема все-таки не исчезла можно будет хоть понять причину более точно.
Зазипованный каб файл (2007-02-03),
Будущие версии программы можно будет найти здесь.
Другая программа для уменьшения расхода заряда батареи описана здесь.
пятница, 2 февраля 2007 г.
GoodWavPower
Третья программа. Смотрел форум firstloox и нашел, что после того как КПК Fujitsu-Siemens Loox N560 или C550 просыпается из спящего режима, она вдруг начинает потреблять на 40мА больше, чем до сна. Советуют нажимать на кнопку Start - помогает. Попытался определить почему помогает и предположил, что проблема в аудио драйвере. Вобщем, поставив это программу забудите про эту багу, как если бы вы о ней не знали вообще. Вы сможете читать книги на 3 часа дольше на той же батарее.
Зазипованный cab архив (3k).
Сырцы (GPL, 11k).
Следить за обновлением программы можно по ссылке.
(другая программа, чтобы сэкономить эл-энэргию (где-то 15 ... 40мА) тут)
Зазипованный cab архив (3k).
Сырцы (GPL, 11k).
Следить за обновлением программы можно по ссылке.
(другая программа, чтобы сэкономить эл-энэргию (где-то 15 ... 40мА) тут)
четверг, 1 февраля 2007 г.
LooxLight
Я сделал это! Я написал свое второе приложение для PPC. LooxLight - это крошечное приложение, которое позволяет контролировать встроенные светодиоды на вашем FSC Pocket PC.
Фичи:
ZIP архив с CAB'ом (17k).
Что к чему в диалоге настройки.
KBD озанчает KEYBOARD т.е. клавиатура, BTH сокращение от BLUETOOTH, PWR это POWER т.е. питание как вы догадались уже. Каждая строка с элементами управления озаглавлена названием светодиода.
"On" кнопка просто включает светодиод, а "off" выключает. Blink означает мигать.
"KEEP ON"/"KEEP OFF" подразумевает, что LooxLight будет восстанавливать состояние светодиода после того как какая либо другая программа установит его в ненужное состояние.
Некоторые элементы управления отключены сейчас, потому, что еще не реализованы.
Опции командной строки:
LooxLightCtrl.exe
История создания:
Однажды я нашел KeyLightC. Это была полезная программа, но в ней нельзя было включать-выключать отдельные светодиоды (а только все вместе и только выключать). Также там нужно было заново запускать KeyLightC как только какая-то программа поменяла состояние светодиода или просто после включения КПК. Я написал письмо Phill McManus. Я попросил его добавить опции +keyboard или -keyboard. Также я попросил его открыть исходники KeyLightC, чтобы я сам мог добавить эти фичи, если у него нет времени или желания. Но он не ответил. Тогда я начал мои собственные исследования прошивки. Прошло порядка 20 вечеров, прежде чем я нашел как управлять светодиодами правильным образом. Потом ушло порядка 10 вечеров, чтобы разобраться как писать под КПК и как пользоваться WinCE API. Потом ушло 3 дня, чтобы избавится от ужасного MS Visual Studio и мигрировать на mingw32ce под линух. И вообще, я ненавижу Win32 API за тонну подводных камней и неожиданностей.
Планы:
О прошивке 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 г.
Перечитывая спецификацию
Джава как язык сдохнет под тяжестью собственной распухшей спецификации.
Чем меньше в языке синтаксических конструкций тем язык красивее и логичнее. Например лямбда исчисление... красота. Хаскелл - можно реализовывать в терминах языка те фичи которые в других языках зашиты в сам язык. Язык форт - алфавит языка до ужаса прост и расширяем.
Может в качестве хобби покомпилировать хаскелл в джава байт код? Есть ли смысл в таком?
Чем меньше в языке синтаксических конструкций тем язык красивее и логичнее. Например лямбда исчисление... красота. Хаскелл - можно реализовывать в терминах языка те фичи которые в других языках зашиты в сам язык. Язык форт - алфавит языка до ужаса прост и расширяем.
Может в качестве хобби покомпилировать хаскелл в джава байт код? Есть ли смысл в таком?
Подписаться на:
Сообщения (Atom)