Совместное использование клавиатуры для компа и ардуино

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

Каждый раз, подсоединяя к ардуино какие нибудь кнопки или энкодер смотрел на лежащую рядом клавиатуру компа, и думал, что хорошо бы её как-то использовать. Расшарить для ардуины так сказать. А сегодня попалась статья на амперке про клавиатурный шпион. И тут осенило -вот то, что нужно. Вставить в клавиатуру М.К., он будет отлавливать нажатие нужных клавиш на USB-клавиатуре, и дёргать нужные ноги своего порта. Выводы вывести на гребёнку, и использовать на ардуине вместо кнопок. И никакого дребезга :)  Дело сразу пошло лёгко,  спаял из ненужной меги8 ардуину, вывел 10 контактный разъём наружу, вот вид уже вставленного контроллера в клавиатуру. Питается он от юсб. Можно взять любую 16-мгц ардуину.

Вот так выглядит в собранном виде.

Скетч для примера. Тут перехватываю нажатия кнопок F9..F12 и дёргаю соответсвующие ноги порта. Библиотека V-USB адаптированная для ардуины качается по ссылке с амперки, в ней я ничего не менял.

 

 // библа и идея отсюда:  http://wiki.amperka.ru/projects:keylogger
#include <usbdrv.h>
uint8_t usbRxBuf[USB_BUFSIZE];
uint8_t FIFOBuf[(IN_SIZE+USB_BUFSIZE)*FIFO_BUF_SIZE];
uint8_t CurWritePos=0,CurReadPos=0;
uint8_t KeyData[8];

void setup(){
pinMode(2,INPUT); //USB d- (зелёный)
pinMode(4,INPUT);// USB d+ (белый)
pinMode(8,OUTPUT); //выход для кнопки F12
pinMode(9,OUTPUT); //выход для кнопки F11
pinMode(10,OUTPUT); //выход для кнопки F10
pinMode(11,OUTPUT); //выход для кнопки F9

Serial.begin(9600);
usbInit();
}

void loop() {
  if(CurWritePos!=CurReadPos){
     for (uint8_t n=0; n < 8; n++) {
        KeyData[n] = FIFOBuf[CurReadPos*14+4+n];
  //      Serial.print (KeyData[n],HEX);
  //      Serial.print (" ");
          } 
  //      Serial.println ();
        CurReadPos++;
          if (CurReadPos>=FIFO_BUF_SIZE) CurReadPos = 0;    }

if (KeyData[2]==0x45 && (KeyData[0]|KeyData[1]|KeyData[3]|KeyData[4]|KeyData[5]|KeyData[6]|KeyData[7]==0) )
     { PORTB|=1<<0 ; } else  PORTB&=~(1<<0); // если была нажата клавиша F12
if (KeyData[2]==0x44 && (KeyData[0]|KeyData[1]|KeyData[3]|KeyData[4]|KeyData[5]|KeyData[6]|KeyData[7]==0) ) 
    { PORTB|=1<<1 ; } else  PORTB&=~(1<<1); // если была нажата клавиша F11
if (KeyData[2]==0x43 && (KeyData[0]|KeyData[1]|KeyData[3]|KeyData[4]|KeyData[5]|KeyData[6]|KeyData[7]==0) ) 
    { PORTB|=1<<2 ; } else  PORTB&=~(1<<2); // если была нажата клавиша F10
if (KeyData[2]==0x42 && (KeyData[0]|KeyData[1]|KeyData[3]|KeyData[4]|KeyData[5]|KeyData[6]|KeyData[7]==0) ) 
    { PORTB|=1<<3 ; } else  PORTB&=~(1<<3); // если была нажата клавиша F9

}


Если убрать ремарки с сериалпринтов, то можно посмотреть коды других кнопок, и настроить другие варианты. Потом допишу эмулятор энкодера, переключать типы эмуляции (кнопки/энкодер) можно опять таки с клавиатуры.

selen_UNO
Offline
Зарегистрирован: 07.03.2018

Здравствуйте! Уже не первый день ковыряю этот вопрос. Прошу вашей помощи.

Использую ваш код в качестве эталона. Задача на данном этапе - перехватить нажатие "Scroll lock". При этом столкнулся с рядом проблем, не получив даже простых нажатий:

1) Для теста я решил добиться стабильного захвата нажатия той или иной клавиши. Для этого изменил ваш участок кода:

  { PORTB|=1<<0 ; } else  PORTB&=~(1<<0); // если была нажата клавиша F12

на

  {Serial.print("F12"); }  // если была нажата клавиша F12

чтобы мониторить срабатывание перехвата.

По итогу перехват не работает ни в какую, а по вашему совету раскомментировав

  // Serial.print (KeyData[n],HEX);

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

"778FFFFFFFFFFFF1F7FF2FFFFFFFFFFF571F87FE17FFC51FBFFB2FFE93FFFFCBFFFFFFFFFFFFFF778A3FFE"

------------------

2) Хочу заметить, вдруг это важно, при каждой компиляции ошибка: 

Warning: size of symbol `usbRxBuf' changed from 22 to 11

При этом скетч компилируется и загружается. Видимо причина ее возникновения в том, что в библиотеке размер определен значением "[2*USB_BUFSIZE]" а в вашем примере и в скетче амперки "[USB_BUFSIZE]". 
От проблемы избавлялся двумя методами: удваивая значения в коде; удалением "2*" из определения в библиотеке. Результат не поменялся от данных перестановок.
Подскажите может ли это влиять на результат перехвата нажатых клавиш?

Работая со скетчем приведенным на сайте амперки, получаю абсолютно идентичные проблемы (п.1 и п.2)

-----------------

3)Частота кварцевого резонатора на моей Arduino UNO 12MHz, а вы указываете следующее: "Можно взять любую 16-мгц ардуину". Подскажите могут ли мои проблемы с некорректным захватом заключаться в частоте? Либо я ошибаюсь и это не влияет на частотные хар-ки чипа?

Я использую:

*Arduino UNO 328P
*Среда arduino: 1.8.5
*Библиотека V-USB такая же как и у вас - zip с сайта амперки
*USB приемник + беспроводная клавиатура
*Подключен "всквозную", как у амперки на сайте. Клавиатура подключена к ПК и функционирует, при этом между ними я перехватываю сигнал.
К pin2 подключен D+
К pin4 подключен D-
В отчаянии пробовал даже обратное включение, конечно же, это не дало результата :)

Заранее благодарен за ответ!

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

selen_UNO, по поводу ошибок компиляции -учтите что это написано в 2015 году, возможно в новых версиях Arduino IDE корректно не будет компилироваться, лучше поставить старую, какую-нибудь 1.0.5 например. По поводу кварца -для кого я писал про 16 МГц ? В библиотеке половина кода на ассемблере, и всё жёстко привязано к таймингам.

selen_UNO
Offline
Зарегистрирован: 07.03.2018

 

"По поводу кварца -для кого я писал про 16 МГц ?"

да вот на этой же странице в вашем описании это указано в первом блоке текста. Все ясно, спасибо, буду пробовать воспроизводить условия. И попутный вопрос, лежит у меня парочка Arduino Nano, номиналы их резонаторов не разобрать из-за размера, есть ли способ, помимо осциллографа, определить их частоту?

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

selen_UNO, керамические резонаторы менее желательны из-за низкой точности. Частоту можно узнать разными способами, самый простой тут. По идее библу можно и на 12 МГц перенастроить, для этого необходимо поменять все упоминания о частоте в её дефайнах F_CPU, USB_CFG_CLOCK_KHZ может и ещё где-то что-то подправить.

selen_UNO
Offline
Зарегистрирован: 07.03.2018

Спасибо! Очень помогли. Буду последовательно исключать возможные несостыковки.

selen_UNO
Offline
Зарегистрирован: 07.03.2018

Установки частоты в библиотеке просто делают ее неработоспособной, никакие нажатия не отслеживаются, устанавливал 12МГц. При чем в самой библиотеке указано, что это оптимальнейшая частота для ее работы. Опробовано на 12-ти и 16-ти МГц Arduino UNO

В конечном итоге хоть что-то дала смена клавиатуры на проводную, причем одинаково работает на устройствах с разными частотами резонатора, но только с установленными в библиотеке 16МГц. Исходные настройки библиотеки от Амперки, дают возможность захвата кода клавиши, только срабатывания нестабильны и в 20% нажатий код клавиши отличается от ожидаемого у некоторых клавиш,  либо нажатие никак не регистрируется вовсе(такая проблема у всех клавиш и довольно часто).

У вас так же работало с ньюансами по стабильности захвата или вопросов не было? Нет ли у вас соображений с чем связана такая нестабильность работы?

Но по большому счету это уже придирки. Главный вопрос теперь - как быть с универсальностью.

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

selen_UNO
Offline
Зарегистрирован: 07.03.2018

Думаю истина около документации по протоколам HID USB приемников, видимо пакеты устроены немного наче, но пока не могу найти ничего близкого к этой теме. Может библиотеку можно настроить под это дело? Там много опций около этой темы, но ни одна из них не дала результата на данный момент.

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

selen_UNO пишет:

У вас так же работало с ньюансами по стабильности захвата или вопросов не было? Нет ли у вас соображений с чем связана такая нестабильность работы?

У меня совершенно никаких проблем. Качество перехвата зависит  в первую очередь от точности частоты кварца, ну и качество монтажа тоже не последнюю роль играет. По поводу перенастройки на 12 МГц помимо дефайнов как я говорил может быть ещё что-то.

selen_UNO пишет:

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

Как это не может идти речи? Никакой разницы. Программа перехватывает пакеты USB, ей безразразлично какими путями они туда попали -по воздуху или по проводу. На этом же принципе работают usb-шные KVM-свитчи. Соответссно никаких специальных настроек в программе делать не  нужно.

selen_UNO
Offline
Зарегистрирован: 07.03.2018

Использование вашего скетча значительно снижает процент ошибок при перехвате, в сравнении со скетчем Амперки.

По поводу беспроводной - как есть.

Если со стабильностью еще можно поиграть меняя аппаратуру, то в случае с USB приемником байты сигналов клавиш, просто не на своем месте, их нет в обрабатываемом буфере. При чем проблема повторяется так же с переходником ps/2 - usb, который я использую для ps/2 клавиатуры.

Если вывести "незнакомое" нажатие, чтобы определить его шеснадцатиричный код, то в случае с проводной клавиатурой монитор порта чист и по нажатию, выдает код клавиши из KeyData[2]. Тот же код начинает сыпать значениями даже без нажатий клавиш при использовании беспроводной или ps/2 переходника. Прерывания срабатывают на служебную информацию.

Видимо из-за того, что это устройство клавиатура+мышь. Вот тут прошу вашего содействия, хотя бы идеями.

Вот интересный проект, как раз то, что я задумал в конечном итоге. Реализован конечно на другом чипе, но библиотека и настройки очень интересные и схожие. Так вот тут именно комбинированное USB устройство клав+мышь работает изначально. Правда автор указывает, что работа устройства ограничена USB 1.1 Low Speed

http://obruboff.ru/mini-kvm-for-usb-keyboard/

Я уже подвыдохся копать немного, но решение уже так близко :)

В итоге последняя проблема с USB приемником и ps/2 переходником. Есть ли у вас мысли по этому поводу?

 

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

selen_UNO, для начала добейтесь что-б стандартная проводная клавиатура перехватывалась без ошибок.  Если с беспроводной после этого всё равно нет перехвата -возможно она работает в стандарте USB2,  тогда нужно будет делать перехватчик на меге с аппаратным USB (подойдт ардуины леонардо и её вариации) . На гигтаймсе был пример.

PS: у Обрубова -та же библиотека, только более старая версия.

selen_UNO
Offline
Зарегистрирован: 07.03.2018

Leonardo обнаруживается ПК как HID-устройство. Она изначально без USB-host shield, не может работать как хост. В итоге перехват с Leonardo сведется к тому же подключению к портам 2 и 4 либо покупке USB-host shield, что можно сделать и с UNO

Или вы имели в виду другую схему?

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

selen_UNO, причём тут хост вообще? Хост -это инициатор обмена данных. Наш перехватчик ничего не инициирует, он сидит молча, на запросы хоста не отзывается,  только слушает  о чём другие говорят.  Для МК с аппаратным USB есть хорошая библа -LUFA. Но примера перехватчика там нет, его придётся переделать из клавиатурного драйвера. Для начинающего это скорее всего неподъёмная задача, так что не знаю что вам посоветовать.