Проблемы с эмулятором клавиатуры Arduino PS / 2

10

Да, я искал форумы Arduino.cc и здесь. Да, я нашел статьи, касающиеся библиотеки ps2dev. Да, я прочитал (хорошо, некоторые я просмотрел) статью об интерфейсе PS / 2 на этом сайте . Да, у меня это работает, вроде. Мне нужны идеи, чтобы сделать прыжок на полную мощность. :)

Нет, я не могу просто эмулировать USB HID Keyboard и оставить все как есть - это должна быть эмуляция PS / 2 Keyboard. Да, я посылаю правильные сигналы «сделай и сломай» - он даже обрабатывает очень сложные комбинации клавиш. На данный момент у меня есть код, написанный для моего Arduino, как указано ниже (технически это Freeduino 1.22), и я отправлял нажатия клавиш через терминал Serial Monitor или PuTTY, а также с помощью удобной оболочки / драйвера Python, которая отправляет фактические Информация о скан-коде PS / 2 - и вообще делает мою жизнь намного проще - также снимает часть нагрузки с Arduino.

Прямо сейчас у меня на Arduino работает эскиз, который имитирует клавиатуру PS / 2. Естественно, я должен загрузить свою «целевую» машину (машину, в которую входит PS / 2 Plug), и я вижу, что происходит «рукопожатие». Загрузитесь в WinDoze, откройте блокнот и нажмите на клавишу (успешно), используя мой «драйвер» Python. (Драйвер просто размещается на терминале Serial Monitor / PuTTY и читает / записывает в последовательный порт, используя модуль под названием PySerial.) Все это делается на материнской плате AMD in ASUS «target».

Теперь цель состоит в том, чтобы заставить его работать на моей «мишени» на материнской плате Intel, я подключаю его, загружаюсь и не играю в кости. Итак, я немного изменил эскиз, чтобы попытаться понять, что на самом деле происходит с моим маленьким другом Арди. Версия после модов отображается ниже. Насколько я понимаю (код был «заимствован» из другого поста на форуме Arduino.cc, здесь ) Он попытается установить соединение с «целью» через PS / 2 в первую очередь, мигая встроенным светодиодом в течение 0,5 секунды до тех пор, пока соединение установлено. Цель Intel не проходит через 5 секунд мигания, и последовательное соединение никогда не устанавливается с «хостом».

У меня такой вопрос: есть ли существенное различие в том, как клавиатуры ps / 2 устанавливают связь с целевым компьютером? Это действительно разница в дизайне, или я должен искать что-то более основное, что проблема здесь? Я слышал кое-что о необходимости подтягивающих резисторов на входах данных / тактовых импульсов, но это должно быть обработано в коде, особенно потому, что он РАБОТАЕТ на другой цели, но не на той, с которой мне нужно работать.

Есть идеи? Я бы хотел, чтобы это работало КАК МОЖНО СКОРЕЕ - я буду продолжать делать отладку, любые указания или предложения будут с благодарностью. Всем им будет уделено полное внимание, потому что мне нужно по-новому взглянуть на эту проблему. Возможно, нужна лучшая реализация в библиотеке ps2dev?

#include "ps2dev.h" // to emulate a PS/2 device

// Orange = 2
// Blue = 3
// Red = 5V (3 in)
// Black = GND (4 in)
// EXT Power, USB for COM only

PS2dev keyboard(3,2); // PS2dev object (2:data, 3:clock)
int enabled = 0; // pseudo variable for state of "keyboard"
boolean serialConnected = false;
int incomingByte = 0;

void ack() {
  //acknowledge commands
  while(keyboard.write(0xFA));
}

int kbdCmd(int command) {
  unsigned char val;
  switch (command) {
  case 0xFF: //reset
    ack();
    //the while loop lets us wait for the host to be ready
    while(keyboard.write(0xAA)!=0);
    break;
  case 0xFE: //resend
    ack();
    break;
  case 0xF6: //set defaults
    //enter stream mode
    ack();
    break;
  case 0xF5: //disable data reporting
    //FM
    enabled = 0;
    ack();
    break;
  case 0xF4: //enable data reporting
    //FM
    enabled = 1;
    ack();
    break;
  case 0xF3: //set typematic rate
    ack();
    keyboard.read(&val); //do nothing with the rate
    ack();
    break;
  case 0xF2: //get device id
    ack();
    keyboard.write(0xAB);
    keyboard.write(0x83);
    break;
  case 0xF0: //set scan code set
    ack();
    keyboard.read(&val); //do nothing with the rate
    ack();
    break;
  case 0xEE: //echo
    //ack();
    keyboard.write(0xEE);
    break;
  case 0xED: //set/reset LEDs
    ack();
    keyboard.read(&val); //do nothing with the rate
    ack();
    break;
  }
}

void connectHost() {
  while (Serial.available() <= 0) {
    Serial.print('A');   // send a capital A
    delay(300);
  }
}

void setup() {
  pinMode(13, OUTPUT);
  //establish serial connection with host
  Serial.begin(9600);
  // establish ps/2 connection with target
  while(keyboard.write(0xAA)!=0){
    digitalWrite(13, HIGH);
    delay(500); 
    digitalWrite(13, LOW);
    delay(500);
  }
  delay(100);  
  
  connectHost();
  Serial.println("\nSerial Host Connected");
  Serial.flush();
}

void loop() {
  unsigned char c;
  if( (digitalRead(3)==LOW) || (digitalRead(2) == LOW)) {
    if(digitalRead(3)==LOW){
      Serial.println("pin 3  is LOW");
    } else {
      Serial.println("pin 2 is LOW");
    }
    while(keyboard.read(&c));
    kbdCmd(c);
    Serial.print("Target: 0x");
    Serial.println(c, HEX);
  }  
  else {//if host device wants to send a command:
    //echo ASCII code from terminal and write to ps/2
    if(Serial.available() > 0) {
      incomingByte = Serial.read();
      keyboard.write(incomingByte);      
      Serial.print("Host: 0x");
      Serial.print(incomingByte, HEX);
      Serial.print(" ");
      Serial.print(incomingByte);
      Serial.print(" ");
      Serial.println(incomingByte, BIN);
    }
  }
}
chisaipete
источник
Несколько вопросов: «Скетч» - это Arduino-lingo для «программы»? Этот драйвер Python не зависит от целевой машины, верно? Ваша проблема в том, что он работает на одной целевой машине, а не на другой, верно? Вы пытались загрузить нерабочую цель с подключенной клавиатурой PS / 2, а затем поменять ее с Arduino?
AndreKR
Да, Sketch == программа на Ardu-lingo. Я попробовал это, и это не сработало (но мне нужно изменить эскиз, чтобы он не ждал подтверждения от цели перед отправкой символов.) Я дам вам знать, когда у меня будет возможность протестировать его позже сегодня.
Чисапете
Итак, я протестировал программу, как вы предложили, и она работает! В конце я хотел бы иметь возможность включать и выключать цель с установленным эмулятором клавиатуры и изменять настройки BIOS с ним. Итак, я думаю, что рукопожатие при запуске выключено?
Чисапете
Да, возможно. Вы видели последовательность инициализации в самом низу computer-engineering.org/ps2keyboard ? Я бы начал со сравнения моей последовательности с этим.
AndreKR
1
Извините, я оставил эту ветку устаревшей - у меня не было времени попробовать решение AndreKR. Кроме того, я не использую подтягивающие резисторы, поэтому сложно определить, на каком конце нет подтягивающих резисторов :)
chisaipete

Ответы:

5

Как я понимаю, вы подключаете свой Arduino к двум разным целевым машинам, и на одной он работает, а на другой - нет.

Таким образом, кажется, есть разница между требованиями инициализации двух машин. На этой странице в самом низу есть список возможных последовательностей инициализации. Начните со сравнения вашей инициализации с этой.

Это будет намного проще, если использовать логический анализатор. Я использую Intronix Logicport , но есть и более дешевые, и лучшие, хотя и не в одно и то же время.

Подключиться к шине с открытым коллектором немного громоздко, потому что вы не видите, какое устройство говорит. Тем не менее, если вы положили в резисторе в конце , где подтяжка не , вы можете сказать , по уровню напряжения , которое устройство держит вниз автобус. Каждая шина с открытым коллектором (например, PS / 2) нуждается в подтягивающих резисторах, обычно они встроены в ПК. Вы можете легко увидеть различные уровни напряжения на DSO. Только с LA вы должны записывать дважды с разными пороговыми напряжениями.

AndreKR
источник
Решение о том, кому отдать награду, оказалось труднее, чем я ожидал, но ваш ответ набрал наибольшее количество голосов, и я немного предпочитаю. Я бы предпочел вознаграждение всем!
Кортук
3

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

Вы можете сделать это, просто взглянув на проблему и подумав, как она должна работать (возможно, после перерыва - или однажды ответ ударит вас в душе), но вы будете более эффективны, если сможете контролировать что здесь происходит. Для электрических проблем это означает область, для протоколов - логический анализатор. В этой области есть несколько дешевых опций, например, плата "bus пират", которая имеет некоторые специфические возможности для протокола клавиатуры или что-то на основе FPGA, которая может иметь более длинный буфер захвата (см. Sump.org).

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

Крис Страттон
источник
2

Я не смотрел библиотеку ps2dev, чтобы понять, как именно она работает, но одна вещь действительно бросается в глаза.

На данный момент делается одна попытка подключиться к «хосту» компьютера. Когда это не удается, ожидается еще одна секунда (светодиод на 0,5 с, светодиод на 0,5 с), прежде чем будет предпринята другая попытка.

Если материнская плата Intel не ждет достаточно времени для обнаружения клавиатуры, возможно, она никогда не получит попытку подключения, пока не продолжит свою последовательность загрузки.

Если вы уменьшите время ожидания до 0,1 с (измените время задержки (500) на задержку (50)), вам может повезти.

Если нет, попробуйте еще быстрее. Черт, даже попробуй это без промедления и посмотри, как это пойдет.

Majenko
источник