Лентяйка, или… что можно делать, сидя на диване

Сергей Бадло (г. Запорожье)

Речь пойдет, конечно, не о самом интимном, а о такой прозаической вещи, как дистанционка, но не совсем обычная. Многим из вас наверняка знакомы такие утилиты по управлению компьютером, как SlyControl, Girder, WinLirc и многие другие. Сегодня мы создадим альтернативное приложение по управлению на расстоянии с помощью любого пульта дистанционного управления, в том числе ТВ-тюнера с такими дополнительными «фичами», как планировщик и модуль «горячих» клавиш.

BIGITALRU_11

На рисунке: Окно тестовой утилиты системы дистанционного управления

С расширением номенклатуры выпускаемых моделей тюнеров у пользователей все чаще появляется желание расширить возможности стандартных программ управления копьютером и ноутбуком, которые зачастую имеют убогий набор функций. Особо продвинутые пользователи «лезут внутрь» стандартных утилит управления и перехватывают команды пульта через них, но… этот метод, к сожалению сугубо индивидуальный и не универсальный.

Второй подход заключается в использовании интерфейса производителя, т.е. работа с тюнером осуществляется через готовую библиотеку* (DLL) идущую в комплекте. К примеру, avertv2k.dll, averapi.dll или becholder32.dll в зависимости от модели тюнера и чипсета.

Сама же библиотека, как правило, работает с тюнером через шину PCI компьютера. И опять мы ограничены,  ведь техподдержка не всегда такая «добрая» и готова поделиться своими API.

Краткий экскурс…

Все устройства на шине PCI, а к ним также относится большинство современных внутренних тюнеров, имеют уникальные идентификаторы и номера, в пределах условной стандартизации производителей (на самом деле, чтобы BIOS распознал находящееся в PCI- устройство, необходимо, чтобы при инициализации оно вернуло VendorID/DeviceID не равным 0xFFFF): VendorID и DeviceID, что вы можете сами увидеть при каждой загрузке BIOSа… Непосредственный доступ к этой шине в NT/XP-подобных системах возможен при входе в так называемое «нулевое кольцо», то бишь без драйвера уже не обойтись. Как правило, разрабатывается WDM-драйвер, через который и идет обмен с этой областью памяти. Подобный подход используют, по крайней мере, несколько из известных приложений, такие как Dscaler, bTTool, bTTest и RC4WA.

Предпосылки реализации. Существующие решения

Все имеющиеся в глобальной сети «комплекты разработчиков драйверов», к примеру, WinDriver, имеют один общий недостаток — наличие DEMO режима с ограничением функциональности по времени, либо с навязчивым сообщением о «денежках». Оно и понятно, кушать всем хочется.

Исследование DLL обслуживания WDM-драйвера с помощью утилиты [1] дало только название точек входа: readPort / readPortW / readPortL / writePort / writePortW / writePortL / memoryMap / memoryUnmap / memoryReadmemoryWrite / pciGetHardwareResources / isDriverOpened / memoryMapEx / memoryAlloc / memoryFree.

Примечание. Входная точка любого драйвера — функция, которая фактически играет ту же самую роль для драйвера, что и main для приложения на C. Эта функция вызывается при загрузке драйвера (неважно, загружается ли он динамически или при запуске системы). Данная функция регистрирует в специальном массиве адреса всех остальных функций драйвера, чтобы диспетчер ввода — вывода мог вызывать их по этим адресам. Если это не WDM драйвер, то в этой функции происходит поиск оборудования, выделение и подтверждение используемых аппаратных ресурсов, выдача видимых для системы имён всем устройствам и т.д. WDM драйвера эту работу перекладывают на функцию AddDevice…

Но решение было найдено в Dscaler. Всем известно, что эта замечательная программа работает с железом напрямую. И что показательно, последние из сервисных приложений воспользовались решением от Dscaler-а, перекомпилировав исходники под новым названием :-). Полные тексты драйверов приводить тут не буду, глядите ссылку [2]. Таким образом, наша задача облегчается, функции и точки входа нам известны, остается реализовать их вызов в виде компонента и обеспечить универсальность для любых VendorID/DeviceID. Что нам дает реализация в виде компонента? Ну, хотя бы то, что разработчику не нужно ломать голову над написанием драйвера, достаточно будет просто перетянуть компонент в свое приложение для реализации доступа к шине PCI [3, 4].

Практика. Разработка ПО и средства отладки

Итак, приступим к основной задаче. Для работы нам понадобиться следующее:

  • среда Borland Delphi 5-7 (компиляция и отладка проекта)
  • собственно сам тюнер для тестирования модуля управления

В моем распоряжении оказались самые распространенные типы тюнеров от именитого китайского производителя — AVerMEDIA 305 и 307 версии и K-World 878. Ввиду ограниченности места в журнале рассмотрим вкратце основные моменты по реализации функциональности и возможностей в нашей «лентяйке»…

1. Пользовательский интерфейс

Целесообразно будет совместить планировщик, модуль горячих клавиш и модуль управления в одной программе. Для этого создадим для каждого режима панели, которые будут сменять друг-друга. Пользователю останется лишь осуществить выбор через меню мышкой, либо по клику по названию панели.

2. Меню

Режим меню должен позволять получить полный доступ ко всем функциям программы с помощью всего трех клавиш (меню, вверх, вниз), что удобно:

  • при использовании пульта с малым количеством клавиш
  • не нужно запоминать каждую кнопку на пульте

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

BIGITALRU_22

На рисунке: Вызов меню программы

3. Горячие клавиши

Большинство пользователей наверняка пользуется неким любимым набором или комбинацией «горячих клавиш» для быстрого совершения определенного действия. Как это реализовать в своем приложении? Не вдаваясь подробно в сам код [7] все достаточно просто. На панели Win32 среды разработки Delphi расположен стандартный компонент THotkey. Вот он-то нам и нужен. Перетянув его на нашу форму, мы получим возможность назначить в его окне любую доступную в системе, т.е. не занятую другим приложением, например Lingvo или Word, глобальную «горячую» комбинацию клавиш. А значит, нам достаточно назначить на событие вызова этой комбинации некую команду, и она будет выполняться.

4. Пульт ДУ или… интерпретатор команд

Каждой кнопке на пульте, как мы уже знаем, соответствуют коды нажатых и отжатых клавиш, выдаваемых платой тюнера. Вы спросите, а как их получить? В данном случае, производитель чипсета пошел навстречу сторонним разработчикам и предоставил API для работы со своей платой. Эти функции известны: AVER_GetRemoteData, AVER_HWInit, AVER_Free. Кроме того, их можно получить утилитой Dbgview [6].

BIGITALRU_33

На рисункe:  Принята команда управления регулятором громкости

Следовательно, получив данный код через вызов функции AVER_GetRemoteData и сопоставив его более понятному нам текстовым обозначениям, мы получим готовый интерпретатор команд, на выходе которого формируется имя нажатой кнопки на пульте:

Работа с пультом ДУ

Для реализации управления с помощью любого пульта ДУ воспользуемся известной утилитой-сервером Winlirc (последние версии сервера можно скачать тут — <a href=»http://lirc.sourceforge.net»>http://lirc.sourceforge.net</a>).

Принцип ее работы следующий. Сервер опрашивает выбранный COM-порт на компьютере и отсылает данные по протоколу TCP. Наша программа декодирует посылки и через интерпретатор выполняет выбранный пользователем набор команд.

Но как же нам подключиться? Чтобы осуществить подключение к серверу Winlirc используем компонент TClientSocket из стандартной поставки среды разработки. Установив порт подключения равным 8765, активируем соединение и по событию приема данных OnClientSosketRead осуществим декодирование принятой команды (кнопки пульта). Если у вас есть карточка PCI тюнера, то с нее тоже можно получать команды пульта, для этого достаточно воспользоваться универсальным модулем PCI I/O for DELPHI разработки автора http://raxp.radioliga.com/cnt/s.php?p=bt.zip, но это тема уже отдельной статьи…

Аппаратная часть, или для тех кто «дружит» с паяльником

Если у вас отсутствует готовый приемник ДУ, то его всегда можно собрать самому. Вам понадобятся всего несколько деталей: коннектор DB9 с корпусом, 2 резистора, 1 диод типа 1N4148, 1 конденсатор и один 5-ти вольтовый ИК приемник TSOP любой марки или ILMS5360 от «дистанционок» телевизоров (последний можно свободно достать на местном радиорынке).

BIGITALRU_44

На рисунке: Схема электрическая принципиальная приемника ДУ

Внешний вид и расположение выводов (обратите внимание, распиновка ИК модулей может отличаться) наиболее распространенных ИК приемников приведены на следующем рисунке.

Как видите, все составляющие схемы комфортно умещаются внутри корпуса разъема, еще и место остается. Длина соединительного шлейфа между датчиком и «девайсом» не критична, но по возможности должна быть минимальной, для исключений возможных наводок и, следовательно, проблем с распознаванием команд.

BIGITALRU_55

На рисунках: Распиновка ИК приемника TSOP48x и ILMS5360 и Внешний вид «девайса»

Заключение

Полные исходные тексты и ресурсы тестового проекта по управлению ПК (файл elt_res.zip), а также глобальной системы ДУ (файл ram.zip) вы можете загрузить с сайта автора http://raxp.radioliga.com

Удачи в управлении!

Ресурсы

  • Dependency Walker из комплекта Visual C++ 6.0  http://raxp.radioliga.com/cnt/s.php?p=dll.zip
  • dTVdrv драйвер Dscaler http://www.koders.com/cpp/fidADFA3760B21797F8DD0A30670C7C6D747B334132.aspx
  • Примеры разработки PCI устройств http://www.xilinx.com
  • Компонент PCI I/0 для работы с драйвером HWIO http://raxp.radioliga.com/cnt/s.php?p=bt.zip
  • Спецификация чипов bt8xx http://raxp.radioliga.com/cnt/s.php?p=bt8xx.pdf
  • Утилита Dbgview http://www.sysinternals.com
  • Исходники и компиляция тестовой системы ДУ http://raxp.radioliga.com/cnt/s.php?p=elt_res.zip
  • Глобальная система ДУ http://raxp.radioliga.com/cnt/s.php?p=ram.zip

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Можно использовать следующие HTML-теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>