МЫШЬ И КАК С НЕЮ БОРОТЬСЯ
Всем тем, кто участвует
в мышиной возне. ;)
(c) Alexey Kulentsov, 2:5020/216.6@fidonet
RealName: Алексей Куленцов
Version 1.08 from 17-10-96 16:18
Если Вам что-то не понравилось в данном файле или есть что добавить, не
поленитесь написать мне об этом, пожалуйста.
A. Что такое "мышь"?
Q. На протяжении всего этого файла под мышью будет подразумеваться
двухмерный аналоговый манипулятор, подключаемый к персональному
компьютеру через последовательный порт, соответствующий стандарту
RS-232 и снабженный парой- тройкой кнопок на верхней крышке. С этим
можно поспорить, но все прочие диджитайзеры тут опущены, как другая
разновидность устройств. Аминь.
Краткое описание функционирования с высоты птичьего полета.
Как было указано выше, мышь подключается к стандартному порту RS-232.
Таким образом, для передачи данных в компьютер используются стандартные
протоколы. Но есть еще проблема питания мыши. Эту проблему решили, запитав
мышь от неиспользуемых сигнальных цепей. А постольку допустимый ток для
этих цепей небольшой, мышь должна быть экономичным устройством.
Когда Вы нажимаете или отпускаете кнопку на мыши или двигаете ее,
микросхема, стоящая в мыши, обрабатывает это событие и посылает в компьютер
пачку байтов с информацией о событии. Приход байтов вызывает в компьютере
аппаратные прерывания (IRQ3 или IRQ4), обрабатываемые драйвером мыши. Про
то, как программировать последовательный порт и обрабатывать прерывания,
смотри TechHelp. Драйвер мыши "складывает" эту информацию в свои внутренние
переменные и в зависимости от режима может выполнять дополнительную работу-
как правило, перемещать мышиный курсор. Программа, которая знает, что такое
мышь и горит желанием воспользоваться ею, может сделать это через
стандартный интерфейс на прерывании 33h. Об этом интерфейсе смотри,
например, TechHelp или Interrupt List.
Описание протокола посылок мыши.
Для активизации мыши необходимо повесить обработчик на соответствующее
аппаратное прерывание, размаскировать это прерывание и установить в порту
биты питания мыши. Обработчик аппаратного прерывания обязан, помимо
обработки приходящих от мыши данных, также восстанавливать в порту биты
питания. Эти биты устанавливаются в порту базовый_адрес+4, который
называется Modem Control Register. Мне известны мыши, для питания которых
нужно выдавать в этот порт число 8, число 0Bh, а также мышь, которая в
зависимости от этого числа меняет свой режим работы (0B-MS, 08-PC). Драйвер
TRUEDOX обеспечивает это переключение по функциям A0 (PC mouse) и A1 (MS
mouse).
Есть два распространенных протокола обмена.
1. Microsoft Mouse.
Протокол обмена следующий: 1200,N71.
Обеспечивает информацию о 2 клавишах.
По каждому событию выдается пачка из 3 байт:
=T=======================
1¦ - 1 LB RB Y7 Y6 X7 X6
2¦ - 0 X5 X4 X3 X2 X1 X0
3¦ - 0 Y5 Y4 Y3 Y2 Y1 Y0
LB, RB - состояние клавиш, нажатая клавиша = 1. Остальные значащие биты-
относительное пеpемещение в дополнительном коде со времени последней
посылки.
Определить наличие мыши можно следующим образом: в порт xFC записать
число 8, подождать, а потом опять 0Bh. На запись числа 0Bh мышь реагирует
посылкой одного или нескольких байтов, среди которых обязательно должен
быть байт 4Dh (буква 'M' в таблице ASCII).
2. PC Mouse System
Протокол обмена следующий: 1200,N81
Обеспечивает информацию о 3 клавишах.
По каждому событию выдается пачка из 5 байт:
=T=======================
1¦ 1 0 0 0 0 LB MB RB
2¦X7 X6 X5 X4 X3 X2 X1 X0
3¦Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0
4¦X7 X6 X5 X4 X3 X2 X1 X0
5¦Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0
LB, MB, RB - состояние клавиш, нажатая клавиша = 0. Остальные значащие
биты- относительное пеpемещение со времени последней посылки в
дополнительном коде в друх частях, которые надо суммировать. Видимо,
это связано с тем, чтобы не использовать X7 и Y7, чтобы не пересекаться
с первым ключевым байтом. Способ определения наличия мыши в этом
режиме мне неизвестен.
Современные мыши могут переключаться между этими двумя протоколами.
Это может делаться тремя способами:
1. По нажатой средней кнопке в момент инициализации мыши.
2. Переключателем MS-PC.
3. Комбинацией напряжений на питающих пинах COM-порта.
Бывают мыши, в которых переключатель предусмотрен по схеме, но для
экономии не впаян и в корпусе нет под него отверстия. Это можно
проверить, разобрав мышь и поискав монтажное место под переключатель.
Бывают мыши с регулировкой чуствительности в виде ползунка. Бывают мыши
без шарика, перемещаемые по специальной площадке. Бывают мыши без
провода к компьютеру. Разные бывают мыши!
В приложении "A" Вы найдете программу, позволяющую посмотреть на это и
заодно иллюстрирующую, как сделать свой обработчик прерывания.
Эксперименты
В ходе экспериментов по выявлению присутствия мыши программным путем
оказалось, что каждая мышь обладает индивидуальностью, не отставая в этом
от одноименного зверя. Это в том, что касается реакции на переключение
питающих пинов и посылки мыши байтов.
HQA2VTEAK3 (Model 3): питанием переключается режим работы. При
переключении PC -> MS возвращает 4D, при переходе обратно реакции нет. Но
иногда при PC -> MS после байта 4D возвращает еще пакет типа 40 00 01, а
при переходе MS -> PC начинает генерить нулевые байты до тех пор, пока не
произойдет событие- нажатие на кнопку или движение мыши. Если во время
генерации нулей переключить порт обратно, перед 4D дополнительно пробегает
байт типа FF. На посылаемые байты эта мышь не реагирует.
E6Q5J8MOUSEX11: Только MS режим. Три кнопки, но средняя работает как
правая. На действие 8 -> 0B в порту xFC реагирует одним байтом- 4D.
Посылаемые компьютером байты возвращает обратно (эхо).
ITEUEC19604966 (Artec): есть переключатель MS-PC. В режиме MS реагирует
на 8 -> 0B тремя байтами: 4D 00 00. Кроме того, при переключении
переключателя PC -> MS возвращает 4D 00 00, а MS -> PC - 4D 00 00 00 00. На
посылаемые байты не реагирует.
17X-HM-A-B: С переключателем MS - PC. На переход 8 -> 0B реагирует байтом
4D. Кроме того, при переключении PC -> MS посылает 4D, а при MS -> PC
посылает два байта: 4D 4D. На посылаемые байты реакция интересная: на 00
возвращает 00 4D. На остальные реагирует либо числом (40 или 70 или 78, 7E,
7F), либо числом и пакетом из трех байт или даже двумя. Например: 01 4C 01
3F.
IYPTS: MS-PC, чип HM8350A. На 8->0B реагирует байтом 4D. На переключение
MS->PC чаще всего посылает 00, PC->MS - 00 4D 4D. Но часто вместо этого
шлет разную муть. При нажатии средней клавиши в режиме MS посылает пачку
байт с текущим состоянием. Hа посылаемые байты не реагирует.
FSUGMZA7 (Genius MouseOne, model Serial 3B): MS-PC. На инициализацию
реагирует неустойчиво, часто выдает вместо 4D байт 4F. В режиме MS при
переходе B->8 выдает 7F, обратно- 4F 4F 4F 4F 4F 4F. В режиме PC B->8
выдает 7F, обратно- 4C 4C 4C 4C 4C 4C. Посылаемые байты возвращает.
Переключение кнопки MS->PC выдает 4С 4С 4С 4С 4С 4С, обратно- 4F 4F 4F
4F 4F 4F.
IOWCM-290F (JEC): MS-PC. При инициализации в MS режиме выдает 4D, в PC-
молчит. При переключении MS<->PC выдает 00 а потом трех- или
пятибайтовую (в зависимости от установленного режима) посылку с текущим
состоянием. В режиме MS при нажатии средней кнопки выдает посылку с
текущим состоянием. Hа посылаемые байты отвечает некоторым хитрым
образом. Hибо ничего, либо байт, либо байт и посылка. Вот начало
таблицы: посылаемый байт, возвращаемый байт, S обозначает посылку.
г==T=====T==T=====T==T=====T========¬
¦ 0¦00 S ¦ 8¦00 S ¦10¦00 S ¦18 66 ¦
¦ 1¦40 S ¦ 9¦7C ¦11¦7C ¦19 -- ¦
¦ 2¦60 S ¦ A¦7C ¦12¦7C ¦ ¦
¦ 3¦78 ¦ B¦7E ¦13¦-- ¦ more.. ¦
¦ 4¦60 S ¦ C¦7C ¦14¦7C ¦ ¦
¦ 5¦78 ¦ D¦-- ¦15¦-- ¦ ¦
¦ 6¦7C ¦ E¦-- ¦16¦-- ¦ ¦
¦ 7¦7E ¦ F¦-- ¦17¦-- ¦ ¦
L==¦=====¦==¦=====¦==¦=====¦========-
E6QMOUSE X31: MS-PC, чип Z-8350. Режим РС включается, если в момент подачи
питания нажата средняя кнопка. Механическая. В работе соответствует
стандарту. Hа любой посланный байт инициализируется и возвращает 4D.
FSUGMZC7 (Genius EasyMouse), чип Genius K030302B: MS-PC. При инициализации
в MS режиме выдает 4D и иногда посылку, в режиме PC - 6D и иногда посылку.
Поведение при переключении кнопки MS-PC такое же, как и у FSUGMZA7: пачки
по шесть 4F или 4C. На посылаемые байты реагирует одним байтом,
кореллирующим с посылкой, и опять же пачкой из шести 4F/4C.
Все это можно выяснить при помощи программы из приложения A. Если Вы тоже
получили интересные результаты, напишите мне.
Краткое пособие по ремонту мыши.
Во всех примерах предполагается, что карта портов исправна, и
неисправность кроется в мыши.
Q. Мышь стала плохо перемещаться по обоим или одному из направлений.
Возможно перемещение только вправо, например.
A. Сначала откройте крышку снизу и вытащите шарик. Посмотрите на ролики,
которых касается шарик. Если на них налипла грязь, прочистите их,
используя шило, скрепку или что-нибудь подобное в качестве инструмента.
Больше всего загрязнению подвергаются мыши с металлическими роликами.
Меньше всего- мыши с тонкими пластмассовыми роликами. Проверьте, как
двигается курсор. Если прочистка не дала результатов, отсоедините мышь
от компьютера и разберите. Используя омметр, прозвоните четыре провода
в хвосте мыши, покачивая разъем в мыши и перегибая хвост рядом с мышью
и рядом с разъемом, включаемым в ком-порт. При обнаружении слабого
контакта устранить (см. следующий пункт). Если с хвостом все в порядке,
найдите на плате мыши резистор, через который питаются светодиоды мыши.
(Предполагается, что мышь на светодиодах, если же она на щетках,
средства исчерпываются их прочисткой). Его сопротивление надо
подобрать, как правило, уменьшить. Можно его выпаять, замерить
сопротивление и впаять в два раза меньший резистор. Можно также просто
припаять параллельно ему резистор сопротивлением примерно один килоом.
Как правило, этого достаточно. Если предыдущие действия ничего не
изменили и мышь по прежнему не работает, возьмите шило и покрутите
неработающее колесико в обе стороны, касаясь шилом до тех ножек
фотодиодов неработающей пары, которые идут к главной микросхеме. Если
при касании одного из фотодиодов мышь вдруг отреагирует на вращение
ролика, это означает, что соответствующий ему светодиод сел и его надо
менять. На этом встречавшиеся мне поломки исчерпываются.
Q. Драйвер вообще не видит мышь.
A. Проверьте правильность установок драйвера и правильность подключения
мыши. Если Вы уверены, что все правильно, отсоедините мышь от
компьютера и разберите ее. Прозвоните омметром провода в хвосте мыши и
найдите, который из них оборвался. Как правило, обрывы случаются в том
месте, где кабель выходит из мыши. Причем обычно сломан оранжевый
провод. (Кто мне объяснит эту загадку?%-) В этом случае обрыв можно
обнаружить и так, потянув отдельно за каждый из проводов кабеля со
стороны мыши. Изоляция на проводах непрочная, и нужный провод вылезет
из кабеля. Как исправить это без укорочения кабеля: возьмите нож или
лучше скальпель и начинайте осторожно резать внешнюю оболочку кабеля
вдоль до места обрыва и дальше примерно на 8 мм, чтобы иметь доступ к
другому концу оборванного провода. Спаяйте оборванный провод и засуньте
провода обратно в оболочку. Можно обмотать ее после этого нитками или
изолентой, но обычно этого не требуется, разрез даже незаметен. Если
все провода целы, а мышь не работает, возможно, полетел кварц. Кроме
того, иногда вместо кварца ставят конденсатор.
Q. Курсор ведет себя странно: перемещается по углам экрана, индицирует
постоянно нажатую клавишу.
A. Это происходит из-за несоответствия протоколов мыши и драйвера.
Проверьте переключатель MS-PC на мыши, а также установки драйвера.
Q. Стала плохо нажиматься одна из кнопок.
A. Кнопки обычно не ремонтируются. Советую найти новую кнопку или
поменять ее местом с менее используемой средней кнопкой, если она
есть. Правда, может быть, кнопка просто засорилась. В этом случае
может помочь окунание кнопки в спирт с последующим нажиманием
вплоть до высыхания.
Приложение A. Пpогpамма тестиpования мыши.
- - - - - - - - - - - - - - - - moutest.c - - - - - - - - - - - - - - - -
#include <stdlib.h>
#include <conio.h>
#include <dos.h>
#include <bios.h>
#ifndef MY_TYPE
#define MY_TYPE 1
typedef unsigned char byte;
typedef unsigned int word;
typedef unsigned long dword;
#endif
#define F1 0x3B00
#define F2 0x3C00
#define F3 0x3D00
#define F4 0x3E00
#define F5 0x3F00
#define F6 0x4000
#define F7 0x4100
#define Escape 0x011B
#define Enter 0x1C0D
#define VERSION "1.3"
word baseport; /* Базовый адрес COM-порта */
word intnum; /* Номер его прерывания */
word port3FC=0xB;
#define MBSIZE 32
byte mbuffer[MBSIZE+1];
byte *mbhead=mbuffer,*mbtail=mbuffer;
void FIbyte(byte b)
{ byte *tmp=mbtail+1;
if(tmp>=mbuffer+MBSIZE) tmp=mbuffer;
if(tmp!=mbhead)
{ *mbtail=b;mbtail=tmp;
}
}
byte FObyte(void)
{ byte *tmp;
if((tmp=mbhead)==mbtail) return 0xFF;
if(++mbhead>=mbuffer+MBSIZE) mbhead=mbuffer;
return *tmp;
}
/* Обработчик аппаратного прерывания */
void interrupt newhrd(void)
{ /* Взять байт от мыши и запихнуть в очередь */
FIbyte(inportb(baseport));
/* Восстановить питание мыши */
outportb(baseport+4,port3FC);
/* Конец прерывания */
outport(0x20,0x20);
}
main(int argc,char **argv)
{ int i;
void interrupt (*oldint)(void);
byte intmask;
cprintf("Mouse tester V"VERSION" Copyright (c) by Alexey Kulentsov,
2:5020/216.6\r\n");
if(argc<2)
{ cprintf("Syntax: moutest <port_number>\r\n"
"Keys: F1 - Clear screen\r\n"
" F2 - Microsoft mode\r\n"
" F3 - PC Mouse System mode\r\n"
" F4 - Custom values to ports xFB,xFC\r\n"
" F5 - 0xB -> to port xFC\r\n"
" F6 - 8 -> to port xFC\r\n"
" Enter - Send byte to mouse\r\n"
);
_exit(1);
}
_AX=0;__int__(0x33);
if(_AX==0xFFFF)
{ cprintf("Mouse driver present- remove and try again.\r\n");
_exit(3);
}
i=(*argv[1])-'0';
if(i<1 || i>2)
{ cprintf("Incorrect port number (only 1 or 2 need).\r\n");
_exit(2);
}
if(i==1)
{ baseport=0x3F8;
intnum=0xC;
intmask=0x10;
}else
{ baseport=0x2F8;
intnum=0xB;
intmask=0x8;
}
/* Установить обработчик аппаратного прерывания */
oldint=getvect(intnum);
setvect(intnum,newhrd);
/* Проинициализировать PIC 8259-1 */
i=inportb(0x21)&~intmask;
delay(1);
outportb(0x21,(byte)i);
delay(1);
/* Проверить наличие порта в адресном пространстве */
if(inportb(baseport+1)&0xF8)
{ cprintf("Error - No port present?\r\n");
_exit(4);
}
/* Ставим параметры порта */
outportb(baseport+3,0x80);
outport(baseport,0x60); /* 1200 */
delay(1);
outportb(baseport+3,2); /* N71 ( L..ppsbb) */
delay(1);
outportb(baseport+1,0);
delay(1);
outportb(baseport+4,1); /* Set DTR, /RTS for power */
/* На всякий случай */
delay(100);
/* Установить DTR, RTS, OUT для питания мыши */
outportb(baseport+4,port3FC);
/* Прерывание только по приему байтов */
outportb(baseport+1,1);
clrscr();
redr:
while(mbhead!=mbtail)
cprintf("%02X ",FObyte());
in:
if(!bioskey(1)) goto redr;
switch(bioskey(0))
{ case Escape: goto quit;
case F1: clrscr();
cprintf("F2·MS mode (N71), F3·PC mode (N81),
F4·custom mode, F5·0xB, F6·8\r\n");
break;
case F2: outportb(baseport+3,2); /* ( L..ppsbb) */
break;
case F3: outportb(baseport+3,3); /* ( L..ppsbb) */
break;
case F4: cprintf("\r\nEnter new xFC value, xFB value:");
cscanf("%x %x",&port3FC,&i);
outportb(baseport+3,i); /* ( L..ppsbb) */
outportb(baseport+4,port3FC);
break;
case F5: port3FC=0xB;outportb(baseport+4,port3FC);
break;
case F6: port3FC=0x8;outportb(baseport+4,port3FC);
break;
case Enter: cprintf("Send byte: ");
cscanf("%x",&i);outportb(baseport,i);cprintf("\r\n");
break;
}
goto redr;
quit:
/* Запретить прерывания от порта */
outportb(baseport+1,0);
/* Запретить обработку прерывания в контроллере */
outportb(0x21,inportb(0x21)|intmask);
/* Вернуть вектор на место */
setvect(intnum,oldint);
return 0;
}
|