Содержание
Введение……………………………………………………….….…….....................3
1. Постановка задачи…………………………………………...…..….….….4
2. Описание HID устройств…………………………………………........….6
3. Описание DLL библиотек…………………………………..…………..…7
4. Динамическая библиотека
HID_Lib_Plus.dll………..…………..…....….8
5. Программирование с
использованием сокетов……..……………....….11
6. Результат работы программ……………………….……….…………..…14
Заключение………………………….……………………….……………….....…..16
Список литературы………………………………………………….…….………..18
Приложение
А………………………………………………………….…….....….19
Введение
Целью данной курсовой работы
является освоение использования динамически
подключаемых библиотек и их взаимодействие
с устройствами, подключаемыми к
персональному компьютеру через
интерфейс USB, а также создание приложения
типа “клиент-сервер” с помощью технологии
Winsock.
Будем рассматривать
работу с интерфейсом USB на примере
HID джойстика Logitech Precision.
Для реализации
задачи был выбран язык С++ и среда
программирования Borland C++ Builder 6.0 Enterprise.
Постановка задачи
Написать клиент серверное
приложение, в котором посредством
подключенного к компьютеру-клиенту
джойстика осуществлялось дистанционное
управление программной моделью
системы на компьютере-сервере.
Рисунок
1. Схема установки
Описание HID устройств
Класс USB HID описывает устройства,
которые используются практически в каждом
современном компьютере. В нём существует
множество предопределённых функций.
Они позволяют производителям аппаратного
обеспечения разрабатывать продукты,
соответствующие спецификации USB HID, и
ожидать, что они будут работать с любым
программным обеспечением, которое так
же поддерживает эти спецификации. Примечательно
то, что USB HID может быть использован, как
для описания работы самого устройства,
так и для описания интерфейса устройства.
Например, вполне допустимым будет использование
USB устройства, имеющего два различных
USB интерфейса одновременно(например,
USB-телефон может использовать HID клавиатуру,
и USB аудио устройство, для микрофона).
Современные игровые контроллеры
и джойстики часто являются USB
HID устройствами. В отличие от устройств,
которые подключаются через игровой
порт, USB HID устройства обычно не требуют
драйверов для нормальной работы.
Почти все игровые устройства
будут работать с использованием
встроенных драйверов, поскольку они
разрабатываются с использованием
USB HID спецификаций.
Описание DLL библиотек
Разработка драйвера USB-устройст-ва
для компьютера не каждому под
силу, так как это требует немалых
знаний и специального набора компьютерных
программ. Выходом из данной ситуации
может быть создание USB-уст-ройств класса
HID (Human Interface Device — устройство взаимодействия
человека с компьютером), драйверы для
которых имеются в операционной
системе.
К HID относятся, в частности,
USB клавиатуры, мыши, джойстики и
другие средства ручного ввода информации.
Тип устройства должен быть задан
в специальной логической структуре,
называемой дескриптором сообщения. Спецификацией
НЮ предусмотрен тип "нестандартное
устройство", которым можно пользоваться
для обмена произвольной информацией.
Это позволяет создавать различные
конструкции с интерфейсом USB —
термометры, программаторы, вольтметры,
которые компьютер воспринимает
как НЮ, хотя фактически они таковыми
не являются. Для работы с HID в операционных
системах семейства Windows предусмотрены
так называемые API-функции, находящиеся
в системных библиотеках "hid.dll,
"setupapi.dll", "kernel32.dll" и некоторых
других. Эти функции позволяют не только
работать с HID, но и узнавать некоторые
параметры его конфигурации, которые требуются,
например, для определения оптимального
объема буферов приема и передачи.
Динамическая библиотека
HID_Lib_Plus.dll
Чтобы упростить работу с
HID, был разработан компонент приложения
- динамическая библиотека подпрограмм
(DLL), названная "HID_Lib_Plus". В отличие
от "HID_Lib", которая предназначена
исключительно для PureBasic, "HID_Lib_Plus"
можно использовать в любой среде
программирования, поддерживающей вызовы
функций из динамических библиотек,
например в Visual Studio или Delphi.
Библиотека HID_Lib_Plus содержит
16 функций:
HID_DeviceTest(PID,VID,VersionNumber,Index) определяет,
подключено ли к компьютеру устройство
с требуемыми идентификаторами.
HID_OpenDevice(PID,VID,VersionNumber,Index) открывает
доступ к устройству перед началом работы
с ним. Назначение ее аргументов и их размерность
такие же, как и у функции HID_DeviceTest. При
успешном получении доступа (устройство
должно быть доступно для записи и чтения)
функция возвращает целое число, так называемый
handle — идентификатор устройства, назначенный
операционной системой. Он необходим для
работы большинства других функций библиотеки,
имеющих одноименный аргумент.
HID_CloseDevice(Handle) завершает работу с
НЮ и освобождает все ресурсы компьютера,
использовавшиеся при работе с ним. Ее
параметр — идентификатор устройства,
полученный ранее с помощью функции HID_OpenDevice.
В случае успешного выполнения заданной
операции будет возвращено число, не равное
нулю.
HID_ReadDevice(Handle,*buffer,Len) читает информацию
из HID, точнее, из его конечной точки типа
INPUT. Она помещает полученную информацию
в буфер, созданный в оперативной памяти
компьютера. Указатель на начало буфера
нужно передать этой функции во втором
аргументе. Третий аргумент — объем буфера
в байтах. Его значение должно быть на
единицу больше заданного в дескрипторе
сообщения устройства. Если это условие
не соблюдено, произойдет ошибка. Функция
возвращает число принятых байтов. Как
правило, оно равно заданному объему буфера,
но может отличаться от него в случае ошибки
приема.
HID_WriteDevice(Handle,*buffer,Len) передает информацию
устройству через конечную точку типа
OUTPUT из указанного вторым аргументом буфера.
В остальном логика ее работы аналогична
функции HID_Read Device.
Особенность функций HID_ReadDevice и HID_WriteDevice заключается в том, что они
не возвращают управление вызвавшей их
программе до завершения чтения или записи
информации. Это приводит, например, к
тому, что при чтении программа "зависает",
пока от НЮ не поступит весь ожидаемый
информационный пакет. Поэтому для чтения
и обработки информации рекомендуется
создать в программе отдельный поток.
GetlnputReport(Handle,*buffer,Len) - альтернатива HID_ReadDevice,
не ожидает завершение чтения, но доступна
только в операционных системах, начиная
с Windows XR При успешном выполнении функция
возвращает число, не равное нулю (как
правило, 1).
НID_SetOutputReport(Handle,*buffer,Len) - альтернатива HID_WriteDevice, не ожидает завершение записи,
но доступна только в операционных системах,
начиная с Windows XR При успешном выполнении
функция возвращает число, не равное нулю
(как правило, 1).
HID_GetFeature(Handle,*buffer,Len) и HID_SetFeature(Handle,*buffer,Len) выполняют операции
соответственно чтения и записи информации,
если HID для обмена информацией использует
FEATURE-сообщения, передаваемые через нулевую
конечную точку. Эти функции ожидают завершения
приема и передачи, но, благодаря специальному
механизму обмена, зависания программы
при приеме не происходит. При успешном
выполнении функции возвращают число,
не равное нулю (как правило, 1).
HID_GetCaps(Handle,*Capabilities.HIDP_CAPS) позволяет
получить некоторые сведения о конфигурации
HID. Они будут помещены в стандартную структуру
HIDP_CAPS, указатель на которую должен быть
передан во втором аргументе.
HID_GetNumlnputBuffers(Handle) позволяет узнать
размер буфера, в котором временно хранится
информация, отправленная устройством,
но еще не прочитанная программой.
HID_GetManufacturerString(Handle), HID_GetProductString(Handle) и
HID_GetSerialNumberString(Handle) позволяют получить
сведения соответственно о разработчике
устройства, его названии и серийном номере.
Каждая из них возвращает указатель на
строку содержащего запрошенную информацию
текста в кодах ASCII или Unicode (в зависимости
от версии использованной библиотеки
"HID_Lib_Plus").
HID_Devicelnfo(*Struct.HID_Devicelnfo) помещает в
структуру HID_Devicelnfo, указатель на которую должен
быть передан в качестве аргумента, список
всех HID, подключенных к компьютеру и их
конфигурацию.
Программирование
с использованием сокетов
Winsocket, поставляемый со
всеми последними версиями Microsoft
Windows, представляет собой набор
функций, оформленных в виде
динамической библиотеки (DLL), и предназначен
для осуществления сетевого взаимодействия
между компьютерами. Благодаря этому
становится возможным применение
его встроенных средств в приложениях,
создаваемых независимыми разработчиками
с помощью любых языков программирования,
при условии, что в них имеются
встроенные средства для использования
функций из внешних динамических
библиотек. Такими инструментами
могут быть, например, Borland Delphi, Microsoft
Visual Basic или различные реализации
С/C++.
Создатели Winsocket сделали
его универсальным средством
для построения сетевых приложений:
задуманный как интерфейс прикладного
программирования для сетей TCP/IP,
он, тем не менее, может работать
с любыми сетевыми протоколами.
Чтобы обеспечить совместимость
разрабатываемого программного
обеспечения, а также избежать
ошибок при попытке вызова
функций, отсутствующих в устаревших
версиях Winsocket, в состав библиотеки
были введены две функции -
WSAStartup и WSACleanup. Функция WSAStartup, кроме
непосредственно инициализации
библиотеки, позволяет узнать версию
Winsocket, установленную на данном
компьютере, и вызывается до любой
другой функции из числа входящих
в состав библиотеки. Вторая функция
- WSACleanup - должна вызываться последней
из функций сокета, например по
окончании работы программы. Эта
функция очищает программные
буферы и переменные, которые
были задействованы сокетом. Обе
функции могут вызываться в
программе неоднократно, но на
каждый вызов WSAStartup должен приходиться
вызов WSACleanup.
Работа с Winsocket в
какой-то степени напоминает работу
с файлами или COM-портами персонального
компьютера: для того чтобы получить
или передать информацию (а именно
обеспечение обмена информацией
и является главной задачей
Winsocket), необходимо сначала создать
сокет и получить ссылку на
соответствующую область памяти.
Указанная информация потребуется
в дальнейшем для управления
данным экземпляром сокета, а
в конце работы - для его закрытия
и освобождения занимаемой памяти.
Для этого используется функция
Socket(Семейство_Протоколов, Тип_Сокета,
Тип_Протокола). Такое количество
аргументов у данной функции
связано с тем, что Winsocket - это
универсальный инструмент для
осуществления сетевого взаимодействия
как в небольшой локальной
сети из нескольких компьютеров
(интрасеть), так и в глобальных
сетях с тысячами компьютеров,
работающих под управлением разных
операционных систем (Internet). Параметр
Семейство_Протоколов указывает
на группу протоколов, с помощью
которых будет осуществляться
взаимодействие. Например, использование
константы PF_INET означает, что вы
хотите работать с семейством
протоколов Internet, PF_UNIX - с семейством
Unix-протоколов, а PF_IPX - IPX/SPX. Константа
Тип_Сокета может принимать значения
SOCK_STREAM и SOCK_DGRAM, соответствующие
работе с потоком байтов и
с дейтаграммами (группами байтов).
И наконец, третий параметр
указывает на протокол, по которому
будет осуществляться соединение:
IPPROTO_TCP говорит о том, что будет
использоваться протокол TCP - основной
протокол четвертого уровня в
Internet. В результате некоторой
двусмысленности данной терминологии
может показаться, что вам придется
работать с двумя протоколами
одновременно, например с TCP и
FTP. Следует помнить, что TCP, SPX и
т. д. являются протоколами
транспортного уровня, а FTP, SMTP и
т. п. - протоколы обмена информацией
с определенными службами, к примеру
с файловой или службой отправки
почтовых сообщений. Таким образом,
вызов функции создания нового
сокета для работы, скажем, с почтовыми
службами (SMTP и POP3) или протоколом
передачи файлов по Internet (File Transfer Protocol)
будет выглядеть следующим образом: Socket(PF_INET,
SOCK_STREAM, IPPROTO_TCP). При этом функция вернет
либо ссылку на вновь созданный сокет,
если этот процесс завершится успешно,
либо значение INVALID_SOCKET. В этом случае,
чтобы получить код ошибки, необходимо
вызвать функцию WSAGetLastError. Обратите внимание
на то, что при создании сокета не указывается
ни адрес удаленного компьютера, к которому
вы хотите подключиться, ни ваш локальный
адрес. Локальный адрес вам потребуется
указать лишь при работе с некоторыми
протоколами высокого уровня, например
с SMTP (протокол передачи сообщений) или
NNTP (протокол работы со службами новостей).
В зависимости от типа сетевого взаимодействия
для настройки сокета могут использоваться
различные функции, реализованные в библиотеке
Winsocket: если вы создаете программу-клиент,
ориентированную на соединение, достаточно
вызвать функцию Connect, если же ваша программа
не предназначается для постоянного соединения,
вы должны использовать функцию Bind (см.
врезку "Ориентированные и не ориентированные
на соединение программы
Получив подтверждение
от удаленного сервера, ваша
программа может приступать к
обмену данными. Для этого в
библиотеке Winsocket предусмотрены функции
передачи данных (Send, Sendto) и чтения
данных (Recv, Recvfrom). В случае успешно
проведенной операции эти функции
возвращают число переданных
или принятых байтов, в противном
случае возвращаемое значение
равно константе SOCKET_ERROR и для
получения кода ошибки вам
потребуется вызвать функцию
WSAGetLastError.
Результат работы программ
Клиент может считывать
данные с джойстика, подключаясь
к нему используя его идентификаторы
(Pid, Vid, Rev), визуально отображать состояния
кнопок (панель изначально скрыта, но может
быть развёрнута щелчком по панели Button state)
и отправлять закодированное состояние
кнопок на сервер по протоколу TCP/IP на указанный
пользователем адрес. При этом визуально
отображаются состояния подключений джойстика
и сетевого соединения.
Рисунок
2. Внешний вид программы клиента
Сервер «прослушивает» указанный пользователем
порт и принимает от клиента закодированные
состояния кнопок джойстика. На основании
принятых данных и карты управления (задаётся
в настройках) вычисляется следующее состояние
системы, которое используется для визуального
отображения программной модели.
Рисунок 3.
Внешний вид программы сервера
Рисунок 4.
Окно настроек управления
Заключение
В данной работе мы ознакомились
с устройством и программированием
HID устройств из под ОС Windows, созданием
сетевых соединений с помощью сокетов
и реализацией дистанционного управления.
Список литературы
1. http://www.radioman-portal.ru/pages/1698/
2. http://msdn.microsoft.com/library/
3. http://www.bitbybit.ru/tutorial_lesson/148
4. http://book.itep.ru/4/41/eth_4111.htm
5. http://belani.narod.ru/1/Lklser2.htm
Приложение А
Листинг клиента
Unit1.cpp – реализует основной
алгоритм работы клиента
//---------------------------------------------------------------------------
#undef UNICODE
//#include <windows.h>
#include <stdio.h>
#include <vcl.h>
#include <math.h>
#pragma hdrstop
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
//ОПРЕДЕЛЕНИЯ ДЛЯ
КНОПОК
#define Button_Down 0x0001
#define Button_Up 0x0002
#define Button_Left 0x0004
#define Button_Right 0x0008
#define Button_1 0x0010
#define Button_2 0x0020
#define Button_3 0x0040
#define Button_4 0x0080
#define Button_5 0x0100
#define Button_6 0x0200