v-usb hid клавиатура atmega8

Тема в разделе "Микроконтроллеры AVR", создана пользователем akl, 12 ноя 2017.

  1. akl

    akl Гуру

    Обновление!
    Можно сказать доделано.
    приблуда успешно логинится на форум



    Выражаю благодарность товарищу ostrov, т.к. изначально вдохновился его микро-проектом. Как уже упоминалось, за основу взято вот это https://github.com/odwdinc/AVR-Testing-Device с некоторыми доработками.
    вот тут еще есть немного как пользоваться библиотекой http://we.easyelectronics.ru/electro-and-pc/usb-dlya-avr-chast-2-hid-class-na-v-usb.html в принципе можно делать не только такие игрушки, но и гораздо более мощные штуки.

    п.с. варнинги о несовпадении типов в функциях вроде
    warning: passing argument 1 of 'usbSendHidReport' from incompatible pointer type
    note: expected 'unsigned char *' but argument is of type 'struct keyboard_report_t *'
    ничему не мешают. главное правильно usbconfig.h отредактировать.


    целиком проект для авр-студии (последующие версии hidA8.c разной степени доделанности - в комментах ниже)
     

    Вложения:

    • hidA8.zip
      Размер файла:
      181,1 КБ
      Просмотров:
      760
    Последнее редактирование: 3 дек 2017
  2. akl

    akl Гуру

    короче получилось заткнуть варнинги сделав типа явное приведение типа, то есть во всех штуках типа
    usbSendHidReport(&keyboard_report, sizeof(keyboard_report_t));
    в функциях вдуплить (uchar*) перед этим адресом вот так
    usbSendHidReport((uchar*)&keyboard_report, sizeof(keyboard_report_t));

    теперь не орет. но не факт что будет работать. всеж не спроста варнинги наверно были. Придется делать плату чтоб проверить.
     
  3. rkit

    rkit Гуру

    С библиотекой не сталкивался, но такая практика довольно обычная для C, так что вполне может работать.
     
  4. akl

    akl Гуру

    сделал приблуду
    [​IMG]

    кое как заработало, но не полностью. то есть оно коннектится, определяется компом, в диспетчере появляется и вроде нормально там висит как клавиатура, но никак не получается заставить его "нажимать кнопки".
    то есть например я думаю что надо по какому-то алгоритму прописать например строчку
    keyboard_report.keycodes[0]=30;
    и после этого оно вроде как должно отправлять нажатие клавиши "1". но почему-то не работает. не хватает мозгов разобраться [​IMG]

    Код (C++):
    // please see http://frank.circleofcurrent.com/index.php?page=hid_tutorial_1
    // the "usb_hid_rpt_desc.hid" file needs to be viewed with the HID Descriptor Tool from USB.org

    // required headers
    #include <avr/io.h>
    #include <avr/wdt.h>
    #include <avr/interrupt.h>
    #include <util/delay.h>
    #include <avr/pgmspace.h>
    #include <string.h>

    // V-USB
    #include "usbdrv.h"



    PROGMEM char usbHidReportDescriptor[USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH] = {//47
        0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)
        0x09, 0x06,                    // USAGE (Keyboard)
        0xa1, 0x01,                    // COLLECTION (Application)
        0x85, 0x01,                    //   REPORT_ID (1)
        0x05, 0x07,                    //   USAGE_PAGE (Keyboard)
        0x19, 0xe0,                    //   USAGE_MINIMUM (Keyboard LeftControl)
        0x29, 0xe7,                    //   USAGE_MAXIMUM (Keyboard Right GUI)
        0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
        0x25, 0x01,                    //   LOGICAL_MAXIMUM (1)
        0x75, 0x01,                    //   REPORT_SIZE (1)
        0x95, 0x08,                    //   REPORT_COUNT (8)
        0x81, 0x02,                    //   INPUT (Data,Var,Abs)
        0x95, 0x01,                    //   REPORT_COUNT (1)
        0x75, 0x08,                    //   REPORT_SIZE (8)
        0x81, 0x03,                    //   INPUT (Cnst,Var,Abs)
        0x95, 0x06,                    //   REPORT_COUNT (6)
        0x75, 0x08,                    //   REPORT_SIZE (8)
        0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
        0x25, 0x65,                    //   LOGICAL_MAXIMUM (101)
        0x05, 0x07,                    //   USAGE_PAGE (Keyboard)
        0x19, 0x00,                    //   USAGE_MINIMUM (Reserved (no event indicated))
        0x29, 0x65,                    //   USAGE_MAXIMUM (Keyboard Application)
        0x81, 0x00,                    //   INPUT (Data,Ary,Abs)
        0xc0                          // END_COLLECTION
        };

    typedef struct
    {
        uint8_t report_id;
        uint8_t modifier;
        uint8_t reserved;
        uint8_t keycodes[6];
    } keyboard_report_t;





    static uint8_t idle_rate = 500 / 4; // see HID1_11.pdf sect 7.2.4
    static uint8_t protocol_version = 0; // see HID1_11.pdf sect 7.2.6

    static  keyboard_report_t keyboard_report;


    static  keyboard_report_t keyboard_report_old;



    usbMsgLen_t usbFunctionSetup(uint8_t data[8])
    {
        // see HID1_11.pdf sect 7.2 and http://vusb.wikidot.com/driver-api
        usbRequest_t *rq = (void *)data;

        if ((rq->bmRequestType & USBRQ_TYPE_MASK) != USBRQ_TYPE_CLASS)
            return 0; // ignore request if it's not a class specific request

        // see HID1_11.pdf sect 7.2
        switch (rq->bRequest)
        {
            case USBRQ_HID_GET_IDLE:
                usbMsgPtr = &idle_rate; // send data starting from this byte
                return 1; // send 1 byte
            case USBRQ_HID_SET_IDLE:
                idle_rate = rq->wValue.bytes[1]; // read in idle rate
                return 0; // send nothing
            case USBRQ_HID_GET_PROTOCOL:
                usbMsgPtr = &protocol_version; // send data starting from this byte
                return 1; // send 1 byte
            case USBRQ_HID_SET_PROTOCOL:
                protocol_version = rq->wValue.bytes[1];
                return 0; // send nothing
            case USBRQ_HID_GET_REPORT:
                // check for report ID then send back report
                if (rq->wValue.bytes[0] == 1)
                {
                    usbMsgPtr = &keyboard_report;
                    return sizeof(keyboard_report);
                }
               
               
                else
                {
                    return 0; // no such report, send nothing
                }
            case USBRQ_HID_SET_REPORT: // no "output" or "feature" implemented, so ignore
                return 0; // send nothing
            default: // do not understand data, ignore
                return 0; // send nothing
        }
    }

    // this function is used to guarantee that the data is sent to the computer once
    void usbSendHidReport(uchar * data, uchar len)
    {
        while(1)
        {
            usbPoll();
            if (usbInterruptIsReady())
            {
                usbSetInterrupt(data, len);
                break;
            }
        }
    }

    int main()
    {
       

        wdt_enable(WDTO_2S);


        TCCR1B = _BV(CS12) | _BV(CS11); // timer is initialized, used to keep track of idle period
       
        usbInit(); // start v-usb
        usbDeviceDisconnect(); // enforce USB re-enumeration, do this while interrupts are disabled!
        _delay_ms(250);
        usbDeviceConnect();
       
        sei(); // enable interrupts
       
        uint8_t to_send = 1; // boolean, true for first time
        unsigned long tmm;
        tmm=0;
        uint8_t fl;
        fl=0;
        while (1)
        {
            wdt_reset();
            usbPoll();
           
            // set the report IDs manually
            keyboard_report.report_id = 1;
       
           
           
            /*
             * this area is where you should set the movement
             * and button values of the reports using the input
             * method of your choice
             *
            */

           
               
                    /*
                   keyboard_report.keycodes[0]=30; //key "1"
                    */

               

           
            // determine whether or not the report should be sent
            if ((TCNT1 > ((4 * (F_CPU / 1024000)) * idle_rate) || TCNT1 > 0x7FFF) && idle_rate != 0)
            {// using idle rate
                to_send = 1;
            }
            else
            {// or if data has changed
                if (memcmp(&keyboard_report, &keyboard_report_old, sizeof(keyboard_report_t)) != 0)
                {
                    to_send = 1;
                }
               
            }
           
            usbPoll();
            if (to_send != 0)
            {
                // send the data if needed
                usbSendHidReport(&keyboard_report, sizeof(keyboard_report_t));
               
               
                TCNT1 = 0; // reset timer
            }
           
            usbPoll();
           
           
            memcpy(&keyboard_report_old, &keyboard_report, sizeof(keyboard_report_t));
           
            to_send = 0; // reset flag
        }
       
        return 0;
    }
     
    :(
     
  5. rkit

    rkit Гуру

    А где кварц? Для USB нужна точная частота
     
  6. akl

    akl Гуру

    кварц с другой стороны платы торчит. 12мгц. вроде основное работает, т.к. коннектится и определяется компом. а вот как нажимать клавиши -хз
     
  7. akl

    akl Гуру

  8. akl

    akl Гуру

    ух кажется запустилось [​IMG]

    короче тупо пример из ссылки постом выше, и выкинул из него лишнее
     
    Последнее редактирование: 20 ноя 2017
  9. akl

    akl Гуру

    запилил основу для алгоритма, теперь можно кнопками выбирать режимы, запускать действия и т.д. (еще запихнул туда миллис()), но главное - переделал некоторые функции, которые работали криво, например ввод альт-кодами.
    .
     
    Последнее редактирование: 19 ноя 2017
  10. akl

    akl Гуру

    добавил общение через уарт, потестировал через блютус и оказалось что альт-ввод таки криво я сделал. Теперь исправил - вроде работает как надо.

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

    мышь так и не потестировал, да и много чего еще, уверен багов дофига осталось, но вдруг кому будет полезно
     

    Вложения:

    • hidA8.c
      Размер файла:
      21,6 КБ
      Просмотров:
      633
    Последнее редактирование: 30 ноя 2017
  11. akl

    akl Гуру

    исправил пару багов и запилил такой режим, в котором можно с телефона через блютус вводить строку символов (включая русские буквы) заканчивающуюся на # и приблуда печатает ее в комп. то есть можно прям чатить без проблем.

    в связи с этим возник вопрос:
    у меня в телефоне (андроид) русские буквы в блютус-терминале посылаются в виде 4х-значного НЕХ в формате 0xD081...0xD191 (с пробелами). Я запилил пересчет этой фигни в ASCII с последующим альт-вводом. Собственно вопрос - что это за кодировка русских букв такая в моем телефоне - как называется?

    а всё понял - это ЮТФ-8 [​IMG]

    быдло-кот:
     

    Вложения:

    • hidA8.c
      Размер файла:
      22,5 КБ
      Просмотров:
      605
    Последнее редактирование: 1 дек 2017
  12. rkit

    rkit Гуру

    utf-8
     
    akl нравится это.
  13. akl

    akl Гуру

    переделал режим прямого ввода через уарт (режим 't') - теперь совмещенный альт- и обычный кнопочный, есть управляющие символы типа \n(энтер) \t(табуляция), \# (конец строки), и т.д., а так же спец-символы формата \m..k.. , которые вместе с набором кратких кодов для некоторых клавиш позволяют быстро вводить все что угодно с телефона, в том числе жать любые клавиши. Например если отправить вот такую штуку
    \mcakdel\# приблуда нажмет контрол-альт-дель.
    вот так будет контрол-ц и контрол-в
    \mckс\# \mckv\#
    альт-таб сокращениями и хекс-кодами:
    \maktab\# \m04k2B\#
    Но и это еще не всё! звоните и заказывайте
    Добавлена мышь с регулировкой скорости и тремя кнопками.
    теперь компом можно управлять с телефона полностью[​IMG]
     

    Вложения:

    • hidA8.c
      Размер файла:
      29,3 КБ
      Просмотров:
      579
  14. akl

    akl Гуру

    помимо того что в режимах программирования и стирания были почему-то удалены send_UART(0x0d); send_UART(0x0a); из-за чего приблуда не отвечала нормально в этих режимах,
    нашелся еще один прикольный баг - при писании альт-вводом длинной строки, оно почему-то зависало ровно на 30м символе (хотя буфер позволяет до 120 в прямом уарт-режиме и до 60 если из еепрома), причем оставался залипшим альт. Все утро ломал голову, пока внезапно не оказалось, что это просто вотчдог срабатывает (альт-ввод то медленный сволочь), а я его не напихал куда надо было :D
    только вот память начинает кончаться - 80% забито :confused: думаю это из-за быдлокодности
    а еще колесо к мыщи добавил
     

    Вложения:

    • hidA8.c
      Размер файла:
      29,8 КБ
      Просмотров:
      605
    Последнее редактирование: 3 дек 2017
  15. akl

    akl Гуру

    добавил мыши возможность зажимать и отжимать левую кнопку и нажимать левую кнопку с шифтом - чтобы выделять текст или что угодно на экране. А так же добавил в чат-режим еще один бесконечный цикл для удобства - теперь после отправки строки не вылетает в меню, а остается в режиме, а чтобы выйти в меню надо послать спец-команду "\!\#"

    кстати, в тему спора зачем нужен бутлодер:
    потому что можно вот так просто вывести контакты для уарта, и они будут полезны не только для прошивки. Причем они легко выводятся именно в том порядке, который нужен для тыкания этого юсб-переходника (тут вывел на проводках для компактности, но можно это гнездо прямо в плату впаять и переходник будет втыкаться так же напрямую). А с SPI так просто не получится, да и применений у него помимо подключения программатора не много.
    [​IMG]

     

    Вложения:

    • hidA8.c
      Размер файла:
      30,7 КБ
      Просмотров:
      568
    Последнее редактирование: 5 дек 2017
  16. akl

    akl Гуру

    допилил приблуду до чего-то более полезного и менее забагованного. в совокупности с очень хорошим BlueTooth Serial Controller (много кнопок + полноценный терминал на одном экране) получается неплохая клаво-мышь с телефона. даже почти удобно в использовании :D



    кот:
     

    Вложения:

    • hidA8.c
      Размер файла:
      31,2 КБ
      Просмотров:
      609
    Securbond нравится это.
  17. Unixon

    Unixon Оракул Модератор

    А в чем сакральный смысл неиспользования МК со встроенным интерфейсом USB?
     
  18. akl

    akl Гуру

    сакральный смысл в том, чтобы не использовать богохульное ардуино. И что-то мне подсказывает, что при таком условии разобраться с LUFA (или что там нужно для аппаратного юсб) будет не сильно проще, чем с v-usb. А во-вторых, уже имелись в наличии несколько дешевых атмег8, поэтому использовал что было.
    кстати было бы неплохо разобраться и с аппаратным. но судя по поверхностному гуглению там тоже все не так просто.
     
  19. Unixon

    Unixon Оракул Модератор

    Так кто ж заставляет... Просто можно вместо ATmega8 взять ATmega8U2 в точно таком же корпусе :)

    М\б, сильно подробно не вникал, но это должно быть хотя бы отчасти проще, т.к. уходит эмуляция шины.
     
  20. Unixon

    Unixon Оракул Модератор