Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лаб11_ЮСБ.doc
Скачиваний:
13
Добавлен:
21.12.2018
Размер:
1.78 Mб
Скачать

Листинг программы для работы с мышью через интерфейс usb (ос Dos):

IDEAL

P386

LOCALS

MODEL MEDIUM

; Физический адрес области памяти для списка кадров USB

FrameListBaseAddr equ 200000h

; Параметры экрана в текстовом режиме

ScreenLength equ 80 ;количество символов в строке

ScreenHeigth equ 25 ;количество строк на экране

; Подключить файл мнемонических обозначений

; кодов управляющих клавиш и цветовых кодов

include "list1_03.inc"

; Подключить файл макросов

include "list1_04.inc"

DATASEG

; Старое значение фона символа

OldCharBackground DB 2 DUP(0Fh)

; Текущее состояние кнопок

ButtonsStatus DB 0

; Текущие координаты курсора мыши

XCoordinate DW 0

YCoordinate DW 0

; Предыдущая позиция курсора мыши

OldXCoordinate DW 0

OldYCoordinate DW 0

;>Счетчик перемещений мыщы (в любом направлении)

MovementCounter DD 0

; Режим курсора, нормальный или увеличеный на 2 клетки

CursorMode DB 0

;<

; Текстовые сообщения

Txt0 DB LIGHTBLUE,0,25,"ПОИСК И ТЕСТИРОВАНИЕ МЫШИ USB",0

DB LIGHTMAGENTA,12,9,"Отображение курсора "

DB "осуществляется инверсией атрибута символа",0

DB YELLOW,24,21

DB "Для выхода нажмите левую клавишу мыши",0

Txt1 DB 2,24,"Порядковый номер контроллера:",0

DB 4,8,"Базовый адрес набора регистров:",0

DB 5,8,"Номер используемого прерывания:",0

DB 7,23,"Регистр команды:",0

DB 8,21,"Регистр состояния:",0

DB 9,7,"Регистр управления прерываниями:",0

DB 10,27,"Номер кадра:",0

DB 11,11,"Базовый адрес списка кадров:",0

DB 12,14,"Модификация начала кадра:",0

DB 13,13,"Регистр состояния порта 1:",0

DB 14,13,"Регистр состояния порта 2:",0

DB 16,17,"Адрес активного порта:",0

AnyK DB YELLOW,24,29,"Нажмите любую клавишу",0; Сообщения об ошибках

NoMouse DB 12,31,"Мышь не обнаружена",0

; ДЕСКРИПТОРЫ КОМАНД

; Дескриптор команды "Get Device Descriptor"

GetDevDesc DB 80h,6

DW 100h,0,8

; Дескриптор команды "Set Address"

SetAddrDesc DB 0,5

DW 0,0,0

; Дескриптор команды "Get Configuration Descriptor"

GetConfDesc DB 80h,6

DW 200h,0,8

; Дескриптор команды "Set Configuration"

SetConfigur DB 00h,9

DW 1,0,0

ENDS

SEGMENT sseg para stack 'STACK'

DB 400h DUP(?)

ENDS

; Область памяти для хранения дескрипторов передачи

SEGMENT USB_DESCR para public 'DATA'

; Заголовок очереди дескрипторов

QH_Descriptor DD 00000003h ;единственный заголовок

DD 00000000h ;указатель на первый TD

DD 0,0,0,0,0,0 ;область данных ПО

; Список дескрипторов для одной транзакции

TD_Array DD 8*16 DUP(0)

ENDS

CODESEG

;*****************************

;* Основной модуль программы *

;*****************************

PROC USB_Mouse

mov AX,DGROUP

mov DS,AX

mov [CS:MainDataSeg],AX

; Установить текстовый режим и очистить экран

mov AX,3

int 10h

; Скрыть курсор - убрать за нижнюю границу экрана

mov [ScreenString],25

mov [ScreenColumn],0

call SetCursorPosition

; Проверить наличие PCI BIOS

mov AX,0B101h

int 1Ah

jc @@PCIBIOSNotFound

cmp EDX,20494350h

jne @@PCIBIOSNotFound

; Установить режим прямой адресации памяти

call Initialization

; Инициализировать дескрипторы USB

call InitializeDeascriptors

; ЦИКЛ ПОИСКА ХОСТ-КОНТРОЛЛЕРОВ

mov [SearchResult],0

mov [USB_HostIndex],0

@@NextHost:

; Найти контроллер USB

call FindUSBController

cmp [SearchResult],0

jne @@NoHost

; Произвести глобальный сброс контроллера

mov DX,[USB_BaseAddr]

mov AX,100b ;установить сигнал сброса

out DX,AX

; Ожидать не менее 10 мс

call Wait05s

; Снять сигнал сброса

mov AX,0

out DX,AX

; Ожидать не менее 10 мс

call Wait05s

; Обнулить счетчик номеров

mov [USB_Device_Number],0

; Загрузить указатель на список кадров в регистр

; адреса списка кадров

mov DX,[USB_BaseAddr]

add DX,6

mov AX,0

out DX,AX

add DX,2

mov EAX,FrameListBaseAddr

out DX,EAX

; Активизировать хост-контроллер

mov DX,[USB_BaseAddr]

mov AX,1

out DX,AX

; Проверить регистр состояния порта 1

mov [USB_PortNum],1

; Вычислить адрес регистра состояния порта

mov DX,[USB_BaseAddr]

add DX,10h

; Запомнить адрес регистра состояния порта

mov [USB_PortReg],DX

; Проверить наличие устройства

in AX,DX

test AX,000Fh

jz @@TestPort2

; Присвоить устройству порядковый номер

call Enumeration

; Получить дескриптор конфигурации

call GetConfigurationDescriptor

; Устройство является мышью?

cmp [byte ptr DataBuffer+9+5],03h

jne @@TestPort2

cmp [byte ptr DataBuffer+9+7],02h

je @@MouseFound

; Проверить регистр состояния порта 2

@@TestPort2:

mov [USB_PortNum],2

; Вычислить адрес регистра состояния порта

mov DX,[USB_BaseAddr]

add DX,12h

; Запомнить адрес регистра состояния порта

mov [USB_PortReg],DX

; Проверить наличие устройства

in AX,DX

test AX,000Fh

jz @@ContrStop

; Присвоить устройству порядковый номер

call Enumeration

; Получить дескриптор конфигурации

call GetConfigurationDescriptor

cmp [byte ptr DataBuffer+9+5],03h

jne @@TestPort2

cmp [byte ptr DataBuffer+9+7],02h

je @@MouseFound

; Остановить контроллер

@@ContrStop:

mov DX,[USB_BaseAddr]

mov AX,0

out DX,AX

jmp @@NextHost

@@MouseFound:

; Вывести текстовые сообщения на экран

MShowColorText 3,Txt0

; СКОНФИГУРИРОВАТЬ УСТРОЙСТВО

; Подать команду "Set Configuration"

mov SI,offset SetConfigur

call Setup_Transaction

; Определить адрес конечной точки и размер пакета

call IntEndpointDescriptor

; Отобразить курсор мыши первый раз

call ShowNewMouseCursorPosition

; Сбросить триггер данных

mov [dword ptr DataTrigger],0

@@NextInterrupt:

; Принять от мыши пакет данных

call InterruptIN_Transaction

; Прибавить перемещение по X к координате X

mov AL,[DataBuffer+1]

cbw

add AX,[XCoordinate]

js @@X1

cmp AX,ScreenLength

jb @@X2

mov AX,ScreenLength-1

jmp @@X2

@@X1: xor AX,AX

@@X2: mov [XCoordinate],AX

; Прибавить перемещение по Y к координате Y

mov AL,[DataBuffer+2]

cbw

add AX,[YCoordinate]

js @@Y1

cmp AX,ScreenHeigth

jb @@Y2

mov AX,ScreenHeigth-1

jmp @@Y2

@@Y1: xor AX,AX

@@Y2: mov [YCoordinate],AX

; Показать курсор в новой позиции

call ShowNewMouseCursorPosition

;>Если нажата левая кнопка показать сообщение "Left clicked"

test [DataBuffer],00000001b

jz @@RightClick

MShowColorText 1,Txt2

; Если нажата правая кнопка показать сообщение "Right clicked"

@@RightClick:

test [DataBuffer],00000010b

jz @@NoClick

MShowColorText 1,Txt3

@@NoClick:

; Проверить состояние буфера клавиатуры

mov AH,1

int 16h

jz @@Next

; Принять символ из буфера клавиатуры

mov AX,0

int 16h

; Завершить програму если нажа Escape

cmp AH,01h

je @@Exit

; Поменять форму курсора если нажат пробел

cmp AH,39h

jne @@Next

not [CursorMode]

; Продолжить прием событий

@@Next:

jmp @@NextInterrupt

@@Exit:

;<

; Остановить контроллер

mov DX,[USB_BaseAddr]

mov AX,0

out DX,AX

; Переустановить текстовый режим и очистить экран

mov AX,3

int 10h

; Выход в DOS

mov AH,4Ch

int 21h

; Обработка ошибок

@@NoHost:

cmp [USB_HostIndex],0

je @@HostNotFound

jmp short @@MouseNotFound

; Не поддерживается PCI BIOS

@@PCIBIOSNotFound:

MFatalError NoPCI

; Неверный номер регистра

@@BadRegisterNumber:

MFatalError BadRg

; Нет ни одного контроллера USB

@@HostNotFound:

MFatalError NoUSB

; Мышь USB не найдена

@@MouseNotFound:

MFatalError NoMouse

ENDP USB_Mouse

;*******************************************

;* ОТОБРАЖЕНИЕ КУРСОРА МЫШИ ПУТЕМ ИНВЕРСИИ *

;* АТРИБУТА СИМВОЛА В ПОЗИЦИИ КУРСОРА *

;*******************************************

PROC ShowNewMouseCursorPosition NEAR

pusha

push ES

;>Показать координаты курсора в верхнем правом углу

MShowHexWord 1,70,[YCoordinate]

MShowHexWord 1,75,[XCoordinate]

; Проверить сосотяние буфера клавиатуры

mov AH,02h

int 16h

mov AH,AL

; Если зажат Alt, перемещение только по горизонтали

test AL,04h

jz @@TestY

mov AX,[OldXCoordinate]

mov [XCoordinate],AX

jmp @@TestOk

@@TestY:

; Если зажат Cntl, перемещение только по вертикали

test AL,08h

jz @@TestOk

mov AX,[OldYCoordinate]

mov [YCoordinate],AX

; Посчитать общее количество пперемещений курсора по оси X и Y

@@TestOk:

push ECX

xor EAX,EAX

mov ECX,EAX

mov AX,[YCoordinate]

sub AX,[OldYCoordinate]

jns @AX_AbsValue

not AX

inc AX

@AX_AbsValue:

mov CX,[XCoordinate]

sub CX,[OldXCoordinate]

jns @@CX_AbsValue

not CX

inc CX

@@CX_AbsValue:

; Показать количество перемещений в верхнем правом углу

add EAX,ECX

add [MovementCounter],EAX

pop ECX

MShowHexDWord 1,60,[MovementCounter]

;<

; Настроить ES на видеопамять

mov AX,0B800h

mov ES,AX

; Вычислить старую координату курсора

mov AX,[OldYCoordinate]

mov DX,160

mul DX

add AX,[OldXCoordinate]

add AX,[OldXCoordinate]

inc AX

mov DI,AX

; Восстановить атрибут символа

mov AL,[OldCharBackground]

mov [ES:DI],AL

;> Восстановить атрибут символа для курсора большого размера

push DI

mov AL,[OldCharBackground+1]

add DI,2

mov [ES:DI],AL

pop DI

;<

; Вычислить новую координату курсора

mov AX,[YCoordinate]

mov DX,160

mul DX

add AX,[XCoordinate]

add AX,[XCoordinate]

inc AX

mov DI,AX

; Сохранить атрибут символа

mov AL,[ES:DI]

mov [OldCharBackground],AL

;>Сохранить атрибут символа для курсора большого размера

push DI

add DI,2

mov AL,[ES:DI]

mov [OldCharBackground+1],AL

pop DI

; Если включен режим большого курсора, инвертировать артибут

cmp [CursorMode],0

jz @@Xor1

push DI

add DI,2

xor [byte ptr ES:DI],1111111b

pop DI

@@Xor1:

;<

; Инвертировать атрибут

xor [byte ptr ES:DI],1111111b

; Запомнить координаты символа

mov AX,[XCoordinate]

mov [OldXCoordinate],AX

mov AX,[YCoordinate]

mov [OldYCoordinate],AX

pop ES

popa

ret

ENDP ShowNewMouseCursorPosition

;********************************************

;* ПРИНЯТЬ ПАКЕТ ПО ПРЕРЫВАНИЮ *

;* Передаваемые параметры: *

;* INT_DataSize - объем принимаемых данных. *

;********************************************

PROC InterruptIN_Transaction near

pushad

; Загрузить в ESI указатель на массив дескрипторов

mov ESI,[Addr_TD_Array]

; Загрузить в EBX указатель на буфер данных

mov EBX,[Addr_DataDescr]

; Сформировать дескриптор данных

; Указатель на следующий TD

mov [dword ptr GS:ESI],1b ;последний TD

; Слово управления

mov EAX,[ShDevType] ;тип устройства

or EAX,00800000h ;признак активности

mov [GS:ESI+4],EAX

; Маркер

mov EAX,69h ;прием данных

or EAX,[ShFuncNum] ;номер функции

or EAX,[ShEndpNum] ;конечная точка

or EAX,[DataTrigger]

or EAX,[ShPackSize] ;размер блока

mov [GS:ESI+8],EAX

; Переключить триггер данных

xor [dword ptr DataTrigger],80000h

mov [GS:ESI+12],EBX ;буфер данных

xor EAX,EAX

mov [GS:ESI+16],EAX

mov [GS:ESI+20],EAX

mov [GS:ESI+24],EAX

mov [GS:ESI+28],EAX

; Установить указатель на список дескрипторов

; (контроллер начинает передачу данных)

mov EAX,[Addr_TD_Array]

mov ESI,[Addr_QH]

add ESI,4

mov [GS:ESI],EAX

; Ожидать завершения операции

@@Wait_OpComplete:

cmp [dword ptr GS:ESI],1b

jne @@Wait_OpComplete

popad

ret

ENDP InterruptIN_Transaction

;*****************************************

;* ОПРЕДЕЛИТЬ МАКСИМАЛЬНЫЙ РАЗМЕР ПАКЕТА *

;* ДЛЯ ИСПОЛЬЗУЕМОЙ КОНЕЧНОЙ ТОЧКИ *

;*****************************************

PROC IntEndpointDescriptor near

pusha

; Поиск дескриптора конечной точки в списке дескрипторов

mov BX,0 ;счетчик байтов

@@NextDescriptor:

cmp [word ptr DataBuffer+BX],0507h

je @@Endpoint

@@NextDescOffset:

; Вычислить смещение следующего дескриптора

add BL,[DataBuffer+BX]

adc BH,0

; Проверка на превышение длины массива

cmp BX,[word ptr DataBuffer+2]

jb @@NextDescriptor

MFatalError NoDev

@@Endpoint:

; Точка передачи по прерываниям?

test [DataBuffer+BX+2],10000000b

jz @@NextDescOffset

cmp [DataBuffer+BX+3],3

jne @@NextDescOffset

; Запомнить адрес конечной точки

xor EAX,EAX

mov AL,[DataBuffer+BX+2]

and AL,00001111b

shl EAX,15

mov [ShEndpNum],EAX

; Запомнить размер пакета

xor EAX,EAX

mov AX,[word ptr DataBuffer+BX+4]

dec AX

shl EAX,21

mov [ShPackSize],EAX

popa

ret

ENDP IntEndpointDescriptor

ENDS

; Подключить процедуры ввода данных и вывода на экран

; в текстовом режиме

include "list1_02.inc"

; Подключить подпрограмму, переводящую сегментный

; регистр GS в режим линейной адресации

include "list2_01.inc"

; Подключить процедуры для работы с контроллером USB

include "list8_01.inc"

END

Блок-схема алгоритма программы:

Результат работы программы.

Листинг программы для работы с мышью (ОС Windows ХР)

через интерфейс USB.

//---------------------------------------------------------------------------

#include <vcl.h>

#pragma hdrstop

#include "Unit1.h"

//---------------------------------------------------------------------------

#pragma package(smart_init)

#pragma resource "*.dfm"

TForm1 *Form1;

//---------------------------------------------------------------------------

__fastcall TForm1::TForm1(TComponent* Owner)

: TForm(Owner)

{}

//---------------------------------------------------------------------------

void __fastcall TForm1::Button1Click(TObject *Sender)

{

RECT LR;

LR.left=100;

LR.top=100;

LR.right=500;

LR.bottom=500;

ClipCursor(&LR);// Ограничиваем в заданой области

}

// Освободить курсор можно, передав функции NULL:

//---------------------------------------------------------------------------

void __fastcall TForm1::Button2Click(TObject *Sender)

{

HWND i;

i=LoadImage(0,"3dgarro.cur",IMAGE_CURSOR,0,0,LR_LOADFROMFILE);

if (i==0) ShowMessage("Ошибка загрузки курсора!");

else

{

Screen->Cursors[1]=i;

Form1->Cursor=1;

}

}

//---------------------------------------------------------------------------

void __fastcall TForm1::Button3Click(TObject *Sender)

{

ClipCursor(NULL);

}

//---------------------------------------------------------------------------

void __fastcall TForm1::FormMouseMove(TObject *Sender, TShiftState Shift,

int X, int Y)

{

TPoint cPt;

GetCursorPos(&cPt);

Label1->Caption=cPt.y; //Возвращает y-позицию курсора мыши

GetCursorPos(&cPt);

Label2->Caption=cPt.x; //Возвращает x-позицию курсора мыши

}

//---------------------------------------------------------------------------

void __fastcall TForm1::Button4Click(TObject *Sender)

{

SetCursorPos(50,50);}

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]