This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Send key value problem

Hello, I modified the instance in usbd_hid_generic to simulate it as keyboard. I checked the code of NRF52840 on github about the keyboard. It USES the function app_usbd_hid_generic_in_report_set() to send the key value, but I can't port it to generic, please help me

#include <stdint.h>
#include "nrf5_usb.h"
#include "ble_service.h"
#include "outputselect.h"

#ifdef NKRO_ENABLE
#    include "keycode_config.h"
extern keymap_config_t keymap_config;
#endif

static uint8_t keyboard_led_stats = 0;

static bool m_report_pending;

static const app_usbd_hid_subclass_desc_t *keyboard_hid_report_desc[] = {&kbd_desc};
APP_USBD_HID_GENERIC_GLOBAL_DEF(m_app_hid_kbd, HID_KBD_INTERFACE, hid_kbd_user_ev_handler, (NRF_DRV_USBD_EPIN6), keyboard_hid_report_desc, 1, 1, APP_USBD_HID_SUBCLASS_BOOT, APP_USBD_HID_PROTO_KEYBOARD);

#ifdef NKRO_ENABLE
static const app_usbd_hid_subclass_desc_t *keyboard2_hid_report_desc[] = {&kbd2_desc};
APP_USBD_HID_GENERIC_GLOBAL_DEF(m_app_hid_kbd2, HID_KBD2_INTERFACE, hid_kbd_user_ev_handler, (NRF_DRV_USBD_EPIN2), keyboard2_hid_report_desc, 1, 1, APP_USBD_HID_SUBCLASS_NONE, APP_USBD_HID_PROTO_GENERIC);
#endif

#ifdef MOUSE_ENABLE
static const app_usbd_hid_subclass_desc_t *mouse_hid_report_desc[] = {&mouse_desc};
APP_USBD_HID_GENERIC_GLOBAL_DEF(m_app_hid_mouse, HID_MOUSE_INTERFACE, hid_user_ev_handler, (NRF_DRV_USBD_EPIN3), mouse_hid_report_desc, 1, 0, APP_USBD_HID_SUBCLASS_NONE, APP_USBD_HID_PROTO_GENERIC);
#endif

#ifdef EXTRAKEY_ENABLE
static const app_usbd_hid_subclass_desc_t *extra_hid_report_desc[] = {&extrakey_desc};
APP_USBD_HID_GENERIC_GLOBAL_DEF(m_app_hid_extra, HID_EXTRA_INTERFACE, hid_user_ev_handler, (NRF_DRV_USBD_EPIN4), extra_hid_report_desc, 1, 0, APP_USBD_HID_SUBCLASS_NONE, APP_USBD_HID_PROTO_GENERIC);
#endif

#define REPORT_QUEUE_LEN 32

static uint8_t kbd_report_queue[REPORT_QUEUE_LEN][KEYBOARD_REPORT_SIZE];
#ifdef NKRO_ENABLE
static uint8_t kbd2_report_queue[REPORT_QUEUE_LEN][NKRO_EPSIZE];
#endif

static volatile uint8_t widx = 0;

static void hid_kbd_process_state(report_keyboard_t *report) {
    if (m_report_pending) return;
    ret_code_t ret;

#ifdef NKRO_ENABLE
    if (keyboard_protocol && keymap_config.nkro) {
        memcpy(kbd2_report_queue[widx], &report->nkro.mods, NKRO_EPSIZE);
        ret = app_usbd_hid_generic_in_report_set(&m_app_hid_kbd2, kbd2_report_queue[widx++], NKRO_EPSIZE);
        widx %= REPORT_QUEUE_LEN;
    } else
#endif
    {
        memcpy(kbd_report_queue[widx], report, KEYBOARD_REPORT_SIZE);

        // uint8_t asdf[8] = {};
        // memcpy(&asdf[0], &report->mods, 8);
        // NRF_LOG_INFO("%d %d %d %d", asdf[widx], asdf[widx], asdf[2], asdf[3]);
        // NRF_LOG_INFO("%d %d %d %d", asdf[4], asdf[5], asdf[6], asdf[7]);
        // ret = app_usbd_hid_generic_in_report_set(&m_app_hid_kbd, &report->mods, 8);
        ret = app_usbd_hid_generic_in_report_set(&m_app_hid_kbd, kbd_report_queue[widx++], KEYBOARD_REPORT_SIZE);

        widx %= REPORT_QUEUE_LEN;
    }
    APP_ERROR_CHECK(ret);
}

#ifdef MOUSE_ENABLE
static void hid_mouse_process_state(report_mouse_t *report) {
    if (m_report_pending) return;
    ret_code_t ret;

    ret = app_usbd_hid_generic_in_report_set(&m_app_hid_mouse, &report->buttons, 5);
    APP_ERROR_CHECK(ret);
}
#endif

#ifdef EXTRAKEY_ENABLE
static void hid_extra_process_state(uint8_t report_id, uint16_t data) {
    if (m_report_pending) return;
    ret_code_t ret;

    uint8_t report[3];
    report[0] = report_id;
    report[1] = data & 0xFF;
    report[2] = (data >> 8) & 0xFF;

    ret = app_usbd_hid_generic_in_report_set(&m_app_hid_extra, &report, 3);
    APP_ERROR_CHECK(ret);
}
#endif

static void kbd_status(void) {
    size_t         led_stats_size = 0;
    const uint8_t *p_buff;
#ifdef NKRO_ENABLE
    if (keyboard_protocol && keymap_config.nkro) {
        p_buff = app_usbd_hid_generic_out_report_get(&m_app_hid_kbd2, &led_stats_size);
    } else
#endif
    {
        p_buff = app_usbd_hid_generic_out_report_get(&m_app_hid_kbd, &led_stats_size);
    }
    keyboard_led_stats = *(p_buff + 1);
}

/**
 * @brief Class specific event handler.
 *
 * @param p_inst    Class instance.
 * @param event     Class specific event.
 * */
void hid_kbd_user_ev_handler(app_usbd_class_inst_t const *p_inst, app_usbd_hid_user_event_t event) {
    switch (event) {
        case APP_USBD_HID_USER_EVT_OUT_REPORT_READY: {
            m_report_pending = false;
            kbd_status();
            break;
        }
        case APP_USBD_HID_USER_EVT_IN_REPORT_DONE: {
            m_report_pending = false;
            // hid_generic_mouse_process_state();
            // bsp_board_led_invert(LED_HID_REP_IN);
            break;
        }
        case APP_USBD_HID_USER_EVT_SET_BOOT_PROTO: {
            UNUSED_RETURN_VALUE(hid_generic_clear_buffer(p_inst));
            NRF_LOG_INFO("SET_BOOT_PROTO");
            break;
        }
        case APP_USBD_HID_USER_EVT_SET_REPORT_PROTO: {
            UNUSED_RETURN_VALUE(hid_generic_clear_buffer(p_inst));
            NRF_LOG_INFO("SET_REPORT_PROTO");
            break;
        }
        default:
            break;
    }
}

void hid_user_ev_handler(app_usbd_class_inst_t const *p_inst, app_usbd_hid_user_event_t event) {
    switch (event) {
        case APP_USBD_HID_USER_EVT_OUT_REPORT_READY: {
            m_report_pending = false;
            /* No output report defined for this example.*/
            ASSERT(0);
            break;
        }
        case APP_USBD_HID_USER_EVT_IN_REPORT_DONE: {
            m_report_pending = false;
            // hid_generic_mouse_process_state();
            // bsp_board_led_invert(LED_HID_REP_IN);
            break;
        }
        case APP_USBD_HID_USER_EVT_SET_BOOT_PROTO: {
            UNUSED_RETURN_VALUE(hid_generic_clear_buffer(p_inst));
            NRF_LOG_INFO("SET_BOOT_PROTO");
            break;
        }
        case APP_USBD_HID_USER_EVT_SET_REPORT_PROTO: {
            UNUSED_RETURN_VALUE(hid_generic_clear_buffer(p_inst));
            NRF_LOG_INFO("SET_REPORT_PROTO");
            break;
        }
        default:
            break;
    }
}

/**
 * @brief USBD library specific event handler.
 *
 * @param event     USBD library event.
 * */
static void usbd_user_ev_handler(app_usbd_event_type_t event) {
    switch (event) {
        case APP_USBD_EVT_DRV_SOF:
            break;
        case APP_USBD_EVT_DRV_RESET:
            m_report_pending = false;
            break;
        case APP_USBD_EVT_DRV_SUSPEND:  // 3
            m_report_pending = false;
            app_usbd_suspend_req();  // Allow the library to put the peripheral into sleep mode
            // bsp_board_leds_off();
            break;
        case APP_USBD_EVT_DRV_RESUME:  // 4
            m_report_pending = false;
            // bsp_board_led_on(LED_USB_START);
            kbd_status(); /* Restore LED state - during SUSPEND all LEDS are turned off */
            break;
        case APP_USBD_EVT_STARTED:  // 2
            m_report_pending = false;
            // bsp_board_led_on(LED_USB_START);
            break;
        case APP_USBD_EVT_STOPPED:
            app_usbd_disable();
            // bsp_board_leds_off();
            break;
        case APP_USBD_EVT_POWER_DETECTED:  // 0
            NRF_LOG_INFO("USB power detected");
            if (!nrf_drv_usbd_is_enabled()) {
                app_usbd_enable();
            }
            ble_disconnect();
            set_output(OUTPUT_USB);
            break;
        case APP_USBD_EVT_POWER_REMOVED:
            NRF_LOG_INFO("USB power removed");
            app_usbd_stop();
            advertising_start(false);
            break;
        case APP_USBD_EVT_POWER_READY:  // 1
            NRF_LOG_INFO("USB ready");
            app_usbd_start();
            break;
        default:
            break;
    }
}

#ifdef MOUSE_ENABLE
static ret_code_t idle_handle(app_usbd_class_inst_t const *p_inst, uint8_t report_id) {
    switch (report_id) {
        case 0: {
            uint8_t report[] = {0xBE, 0xEF};
            return app_usbd_hid_generic_idle_report_set(&m_app_hid_mouse, report, sizeof(report));
        }
        default:
            return NRF_ERROR_NOT_SUPPORTED;
    }
}
#endif

static uint8_t keyboard_leds(void);
static void    send_keyboard(report_keyboard_t *report);
static void    send_mouse(report_mouse_t *report);
static void    send_system(uint16_t data);
static void    send_consumer(uint16_t data);

static host_driver_t driver = {keyboard_leds, send_keyboard, send_mouse, send_system, send_consumer};

host_driver_t *nrf5_usb_driver(void) { return &driver; }

static uint8_t keyboard_leds(void) { return keyboard_led_stats; }

static void send_keyboard(report_keyboard_t *report) {
    if (NRF_USBD->ENABLE) {
        hid_kbd_process_state(report);
    }
}

static void send_mouse(report_mouse_t *report) {
#ifdef MOUSE_ENABLE
    if (NRF_USBD->ENABLE) {
        hid_mouse_process_state(report);
    }
#endif
}

static void send_system(uint16_t data) {
#ifdef EXTRAKEY_ENABLE
    if (NRF_USBD->ENABLE) {
        hid_extra_process_state(REPORT_ID_SYSTEM, data);
    }
#endif
}

static void send_consumer(uint16_t data) {
#ifdef EXTRAKEY_ENABLE
    if (NRF_USBD->ENABLE) {
        hid_extra_process_state(REPORT_ID_CONSUMER, data);
    }
#endif
}

#ifdef MIDI_ENABLE

void send_midi_packet(MIDI_EventPacket_t *event) {
    // NRF_LOG_INFO("asdfjkl %d", sizeof(MIDI_EventPacket_t));
    // NRF_LOG_INFO("asdfjkl %d %d", event->Event, event->Data1);
    // app_usbd_audio_class_tx_start(&m_app_audio_microphone.base, (uint8_t *)event, sizeof(MIDI_EventPacket_t));

    // NRF_LOG_INFO("EPINEN: %d", NRF_USBD->EPINEN);
    // chnWrite(&drivers.midi_driver.driver, (uint8_t *)event, sizeof(MIDI_EventPacket_t));
}

bool recv_midi_packet(MIDI_EventPacket_t *const event) {
    // size_t size = chnReadTimeout(&drivers.midi_driver.driver, (uint8_t *)event, sizeof(MIDI_EventPacket_t), TIME_IMMEDIATE);
    // return size == sizeof(MIDI_EventPacket_t);
    return 0;
}

#endif

#include "nrf_delay.h"
void usb_keyboard_init(void) {
    ret_code_t                     ret;
    static const app_usbd_config_t usbd_config = {.ev_state_proc = usbd_user_ev_handler,
                                                  // chie4 add
                                                  .enable_sof = true};

    ret = app_usbd_init(&usbd_config);
    APP_ERROR_CHECK(ret);

    app_usbd_class_inst_t const *class_inst_kbd;
    class_inst_kbd = app_usbd_hid_generic_class_inst_get(&m_app_hid_kbd);
    ret            = app_usbd_class_append(class_inst_kbd);
    APP_ERROR_CHECK(ret);

#ifdef NKRO_ENABLE
    app_usbd_class_inst_t const *class_inst_kbd2;
    class_inst_kbd2 = app_usbd_hid_generic_class_inst_get(&m_app_hid_kbd2);
    ret             = app_usbd_class_append(class_inst_kbd2);
    APP_ERROR_CHECK(ret);
#endif

#ifdef MOUSE_ENABLE
    app_usbd_class_inst_t const *class_inst_mouse;
    class_inst_mouse = app_usbd_hid_generic_class_inst_get(&m_app_hid_mouse);
    ret              = hid_generic_idle_handler_set(class_inst_mouse, idle_handle);
    ret              = app_usbd_class_append(class_inst_mouse);
    APP_ERROR_CHECK(ret);
#endif

#ifdef EXTRAKEY_ENABLE
    app_usbd_class_inst_t const *class_inst_extra;
    class_inst_extra = app_usbd_hid_generic_class_inst_get(&m_app_hid_extra);
    ret              = app_usbd_class_append(class_inst_extra);
    APP_ERROR_CHECK(ret);
#endif

    NRF_LOG_INFO("USBD HID composite example started.");

    nrf_delay_ms(50);
    ret = app_usbd_power_events_enable();
    APP_ERROR_CHECK(ret);
}

Parents Reply Children
No Data
Related