/** * \file * * \brief USB Device Human Interface Device (HID) keyboard interface. * * Copyright (c) 2009-2015 Atmel Corporation. All rights reserved. * * \asf_license_start * * \page License * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * 3. The name of Atmel may not be used to endorse or promote products derived * from this software without specific prior written permission. * * 4. This software may only be redistributed and used in connection with an * Atmel microcontroller product. * * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * \asf_license_stop * */ /* * Support and FAQ: visit Atmel Support */ #include "samd51j18a.h" #include "d51_util.h" #include "conf_usb.h" #include "usb_protocol.h" #include "udd.h" #include "udc.h" #include "udi_device_conf.h" #include "udi_hid.h" #include "udi_hid_kbd.h" #include #include "report.h" //*************************************************************************** // KBD //*************************************************************************** #ifdef KBD bool udi_hid_kbd_enable(void); void udi_hid_kbd_disable(void); bool udi_hid_kbd_setup(void); uint8_t udi_hid_kbd_getsetting(void); UDC_DESC_STORAGE udi_api_t udi_api_hid_kbd = { .enable = (bool (*)(void))udi_hid_kbd_enable, .disable = (void (*)(void))udi_hid_kbd_disable, .setup = (bool (*)(void))udi_hid_kbd_setup, .getsetting = (uint8_t(*)(void))udi_hid_kbd_getsetting, .sof_notify = NULL, }; COMPILER_WORD_ALIGNED static uint8_t udi_hid_kbd_rate; COMPILER_WORD_ALIGNED static uint8_t udi_hid_kbd_protocol; COMPILER_WORD_ALIGNED uint8_t udi_hid_kbd_report_set; bool udi_hid_kbd_b_report_valid; COMPILER_WORD_ALIGNED uint8_t udi_hid_kbd_report[UDI_HID_KBD_REPORT_SIZE]; volatile bool udi_hid_kbd_b_report_trans_ongoing; COMPILER_WORD_ALIGNED static uint8_t udi_hid_kbd_report_trans[UDI_HID_KBD_REPORT_SIZE]; COMPILER_WORD_ALIGNED UDC_DESC_STORAGE udi_hid_kbd_report_desc_t udi_hid_kbd_report_desc = {{ 0x05, 0x01, // Usage Page (Generic Desktop) 0x09, 0x06, // Usage (Keyboard) 0xA1, 0x01, // Collection (Application) // Modifiers (8 bits) 0x05, 0x07, // Usage Page (Keyboard) 0x19, 0xE0, // Usage Minimum (Keyboard Left Control) 0x29, 0xE7, // Usage Maximum (Keyboard Right GUI) 0x15, 0x00, // Logical Minimum (0) 0x25, 0x01, // Logical Maximum (1) 0x95, 0x08, // Report Count (8) 0x75, 0x01, // Report Size (1) 0x81, 0x02, // Input (Data, Variable, Absolute) // Reserved (1 byte) 0x81, 0x01, // Input (Constant) // Keycodes (6 bytes) 0x19, 0x00, // Usage Minimum (0) 0x29, 0xFF, // Usage Maximum (255) 0x15, 0x00, // Logical Minimum (0) 0x25, 0xFF, // Logical Maximum (255) 0x95, 0x06, // Report Count (6) 0x75, 0x08, // Report Size (8) 0x81, 0x00, // Input (Data, Array, Absolute) // Status LEDs (5 bits) 0x05, 0x08, // Usage Page (LED) 0x19, 0x01, // Usage Minimum (Num Lock) 0x29, 0x05, // Usage Maximum (Kana) 0x15, 0x00, // Logical Minimum (0) 0x25, 0x01, // Logical Maximum (1) 0x95, 0x05, // Report Count (5) 0x75, 0x01, // Report Size (1) 0x91, 0x02, // Output (Data, Variable, Absolute) // LED padding (3 bits) 0x95, 0x03, // Report Count (3) 0x91, 0x01, // Output (Constant) 0xC0 // End Collection }}; static bool udi_hid_kbd_setreport(void); static void udi_hid_kbd_report_sent(udd_ep_status_t status, iram_size_t nb_sent, udd_ep_id_t ep); static void udi_hid_kbd_setreport_valid(void); bool udi_hid_kbd_enable(void) { // Initialize internal values udi_hid_kbd_rate = 0; udi_hid_kbd_protocol = 0; udi_hid_kbd_b_report_trans_ongoing = false; memset(udi_hid_kbd_report, 0, UDI_HID_KBD_REPORT_SIZE); udi_hid_kbd_b_report_valid = false; return UDI_HID_KBD_ENABLE_EXT(); } void udi_hid_kbd_disable(void) { UDI_HID_KBD_DISABLE_EXT(); } bool udi_hid_kbd_setup(void) { return udi_hid_setup(&udi_hid_kbd_rate, &udi_hid_kbd_protocol, (uint8_t *)&udi_hid_kbd_report_desc, udi_hid_kbd_setreport); } uint8_t udi_hid_kbd_getsetting(void) { return 0; } static bool udi_hid_kbd_setreport(void) { if ((USB_HID_REPORT_TYPE_OUTPUT == (udd_g_ctrlreq.req.wValue >> 8)) && (0 == (0xFF & udd_g_ctrlreq.req.wValue)) && (1 == udd_g_ctrlreq.req.wLength)) { // Report OUT type on report ID 0 from USB Host udd_g_ctrlreq.payload = &udi_hid_kbd_report_set; udd_g_ctrlreq.callback = udi_hid_kbd_setreport_valid; udd_g_ctrlreq.payload_size = 1; return true; } return false; } bool udi_hid_kbd_send_report(void) { if (!main_b_kbd_enable) { return false; } if (udi_hid_kbd_b_report_trans_ongoing) { return false; } memcpy(udi_hid_kbd_report_trans, udi_hid_kbd_report, UDI_HID_KBD_REPORT_SIZE); udi_hid_kbd_b_report_valid = false; udi_hid_kbd_b_report_trans_ongoing = udd_ep_run(UDI_HID_KBD_EP_IN | USB_EP_DIR_IN, false, udi_hid_kbd_report_trans, UDI_HID_KBD_REPORT_SIZE, udi_hid_kbd_report_sent); return udi_hid_kbd_b_report_trans_ongoing; } static void udi_hid_kbd_report_sent(udd_ep_status_t status, iram_size_t nb_sent, udd_ep_id_t ep) { UNUSED(status); UNUSED(nb_sent); UNUSED(ep); udi_hid_kbd_b_report_trans_ongoing = false; if (udi_hid_kbd_b_report_valid) { udi_hid_kbd_send_report(); } } static void udi_hid_kbd_setreport_valid(void) { // UDI_HID_KBD_CHANGE_LED(udi_hid_kbd_report_set); } #endif // KBD //******************************************************************************************** // NKRO Keyboard //******************************************************************************************** #ifdef NKRO bool udi_hid_nkro_enable(void); void udi_hid_nkro_disable(void); bool udi_hid_nkro_setup(void); uint8_t udi_hid_nkro_getsetting(void); UDC_DESC_STORAGE udi_api_t udi_api_hid_nkro = { .enable = (bool (*)(void))udi_hid_nkro_enable, .disable = (void (*)(void))udi_hid_nkro_disable, .setup = (bool (*)(void))udi_hid_nkro_setup, .getsetting = (uint8_t(*)(void))udi_hid_nkro_getsetting, .sof_notify = NULL, }; COMPILER_WORD_ALIGNED static uint8_t udi_hid_nkro_rate; COMPILER_WORD_ALIGNED static uint8_t udi_hid_nkro_protocol; COMPILER_WORD_ALIGNED uint8_t udi_hid_nkro_report_set; bool udi_hid_nkro_b_report_valid; COMPILER_WORD_ALIGNED uint8_t udi_hid_nkro_report[UDI_HID_NKRO_REPORT_SIZE]; volatile bool udi_hid_nkro_b_report_trans_ongoing; COMPILER_WORD_ALIGNED static uint8_t udi_hid_nkro_report_trans[UDI_HID_NKRO_REPORT_SIZE]; COMPILER_WORD_ALIGNED UDC_DESC_STORAGE udi_hid_nkro_report_desc_t udi_hid_nkro_report_desc = {{ 0x05, 0x01, // Usage Page (Generic Desktop) 0x09, 0x06, // Usage (Keyboard) 0xA1, 0x01, // Collection (Application) // Modifiers (8 bits) 0x05, 0x07, // Usage Page (Keyboard/Keypad) 0x19, 0xE0, // Usage Minimum (Keyboard Left Control) 0x29, 0xE7, // Usage Maximum (Keyboard Right GUI) 0x15, 0x00, // Logical Minimum (0) 0x25, 0x01, // Logical Maximum (1) 0x95, 0x08, // Report Count (8) 0x75, 0x01, // Report Size (1) 0x81, 0x02, // Input (Data, Variable, Absolute) // Keycodes 0x05, 0x07, // Usage Page (Keyboard/Keypad) 0x19, 0x00, // Usage Minimum (0) 0x29, 0xF7, // Usage Maximum (247) 0x15, 0x00, // Logical Minimum (0) 0x25, 0x01, // Logical Maximum (1) 0x95, 0xF8, // Report Count (248) 0x75, 0x01, // Report Size (1) 0x81, 0x02, // Input (Data, Variable, Absolute, Bitfield) // Status LEDs (5 bits) 0x05, 0x08, // Usage Page (LED) 0x19, 0x01, // Usage Minimum (Num Lock) 0x29, 0x05, // Usage Maximum (Kana) 0x95, 0x05, // Report Count (5) 0x75, 0x01, // Report Size (1) 0x91, 0x02, // Output (Data, Variable, Absolute) // LED padding (3 bits) 0x95, 0x01, // Report Count (1) 0x75, 0x03, // Report Size (3) 0x91, 0x03, // Output (Constant) 0xC0 // End Collection }}; static bool udi_hid_nkro_setreport(void); static void udi_hid_nkro_setreport_valid(void); static void udi_hid_nkro_report_sent(udd_ep_status_t status, iram_size_t nb_sent, udd_ep_id_t ep); bool udi_hid_nkro_enable(void) { // Initialize internal values udi_hid_nkro_rate = 0; udi_hid_nkro_protocol = 0; udi_hid_nkro_b_report_trans_ongoing = false; memset(udi_hid_nkro_report, 0, UDI_HID_NKRO_REPORT_SIZE); udi_hid_nkro_b_report_valid = false; return UDI_HID_NKRO_ENABLE_EXT(); } void udi_hid_nkro_disable(void) { UDI_HID_NKRO_DISABLE_EXT(); } bool udi_hid_nkro_setup(void) { return udi_hid_setup(&udi_hid_nkro_rate, &udi_hid_nkro_protocol, (uint8_t *)&udi_hid_nkro_report_desc, udi_hid_nkro_setreport); } uint8_t udi_hid_nkro_getsetting(void) { return 0; } // keyboard receives LED report here static bool udi_hid_nkro_setreport(void) { if ((USB_HID_REPORT_TYPE_OUTPUT == (udd_g_ctrlreq.req.wValue >> 8)) && (0 == (0xFF & udd_g_ctrlreq.req.wValue)) && (1 == udd_g_ctrlreq.req.wLength)) { // Report OUT type on report ID 0 from USB Host udd_g_ctrlreq.payload = &udi_hid_nkro_report_set; udd_g_ctrlreq.callback = udi_hid_nkro_setreport_valid; // must call routine to transform setreport to LED state udd_g_ctrlreq.payload_size = 1; return true; } return false; } bool udi_hid_nkro_send_report(void) { if (!main_b_nkro_enable) { return false; } if (udi_hid_nkro_b_report_trans_ongoing) { return false; } memcpy(udi_hid_nkro_report_trans, udi_hid_nkro_report, UDI_HID_NKRO_REPORT_SIZE); udi_hid_nkro_b_report_valid = false; udi_hid_nkro_b_report_trans_ongoing = udd_ep_run(UDI_HID_NKRO_EP_IN | USB_EP_DIR_IN, false, udi_hid_nkro_report_trans, UDI_HID_NKRO_REPORT_SIZE, udi_hid_nkro_report_sent); return udi_hid_nkro_b_report_trans_ongoing; } static void udi_hid_nkro_report_sent(udd_ep_status_t status, iram_size_t nb_sent, udd_ep_id_t ep) { UNUSED(status); UNUSED(nb_sent); UNUSED(ep); udi_hid_nkro_b_report_trans_ongoing = false; if (udi_hid_nkro_b_report_valid) { udi_hid_nkro_send_report(); } } static void udi_hid_nkro_setreport_valid(void) { // UDI_HID_NKRO_CHANGE_LED(udi_hid_nkro_report_set); } #endif // NKRO //******************************************************************************************** // EXK (extra-keys) SYS-CTRL Keyboard //******************************************************************************************** #ifdef EXK bool udi_hid_exk_enable(void); void udi_hid_exk_disable(void); bool udi_hid_exk_setup(void); uint8_t udi_hid_exk_getsetting(void); UDC_DESC_STORAGE udi_api_t udi_api_hid_exk = { .enable = (bool (*)(void))udi_hid_exk_enable, .disable = (void (*)(void))udi_hid_exk_disable, .setup = (bool (*)(void))udi_hid_exk_setup, .getsetting = (uint8_t(*)(void))udi_hid_exk_getsetting, .sof_notify = NULL, }; COMPILER_WORD_ALIGNED static uint8_t udi_hid_exk_rate; COMPILER_WORD_ALIGNED static uint8_t udi_hid_exk_protocol; COMPILER_WORD_ALIGNED uint8_t udi_hid_exk_report_set; bool udi_hid_exk_b_report_valid; COMPILER_WORD_ALIGNED udi_hid_exk_report_t udi_hid_exk_report; static bool udi_hid_exk_b_report_trans_ongoing; COMPILER_WORD_ALIGNED static uint8_t udi_hid_exk_report_trans[UDI_HID_EXK_REPORT_SIZE]; COMPILER_WORD_ALIGNED UDC_DESC_STORAGE udi_hid_exk_report_desc_t udi_hid_exk_report_desc = {{ // clang-format off 0x05, 0x01, // Usage Page (Generic Desktop) 0x09, 0x80, // Usage (System Control) 0xA1, 0x01, // Collection (Application) 0x85, REPORT_ID_SYSTEM, // Report ID 0x19, 0x01, // Usage Minimum (Pointer) 0x2A, 0xB7, 0x00, // Usage Maximum (System Display LCD Autoscale) 0x15, 0x01, // Logical Minimum 0x26, 0xB7, 0x00, // Logical Maximum 0x95, 0x01, // Report Count (1) 0x75, 0x10, // Report Size (16) 0x81, 0x00, // Input (Data, Array, Absolute) 0xC0, // End Collection 0x05, 0x0C, // Usage Page (Consumer) 0x09, 0x01, // Usage (Consumer Control) 0xA1, 0x01, // Collection (Application) 0x85, REPORT_ID_CONSUMER, // Report ID 0x19, 0x01, // Usage Minimum (Consumer Control) 0x2A, 0xA0, 0x02, // Usage Maximum (AC Desktop Show All Applications) 0x15, 0x01, // Logical Minimum 0x26, 0xA0, 0x02, // Logical Maximum 0x95, 0x01, // Report Count (1) 0x75, 0x10, // Report Size (16) 0x81, 0x00, // Input (Data, Array, Absolute) 0xC0 // End Collection //clang-format on }}; static bool udi_hid_exk_setreport(void); static void udi_hid_exk_report_sent(udd_ep_status_t status, iram_size_t nb_sent, udd_ep_id_t ep); static void udi_hid_exk_setreport_valid(void); bool udi_hid_exk_enable(void) { // Initialize internal values udi_hid_exk_rate = 0; udi_hid_exk_protocol = 0; udi_hid_exk_b_report_trans_ongoing = false; memset(udi_hid_exk_report.raw, 0, UDI_HID_EXK_REPORT_SIZE); udi_hid_exk_b_report_valid = false; return UDI_HID_EXK_ENABLE_EXT(); } void udi_hid_exk_disable(void) { UDI_HID_EXK_DISABLE_EXT(); } bool udi_hid_exk_setup(void) { return udi_hid_setup(&udi_hid_exk_rate, &udi_hid_exk_protocol, (uint8_t *)&udi_hid_exk_report_desc, udi_hid_exk_setreport); } uint8_t udi_hid_exk_getsetting(void) { return 0; } static bool udi_hid_exk_setreport(void) { if ((USB_HID_REPORT_TYPE_OUTPUT == (udd_g_ctrlreq.req.wValue >> 8)) && (0 == (0xFF & udd_g_ctrlreq.req.wValue)) && (1 == udd_g_ctrlreq.req.wLength)) { // Report OUT type on report ID 0 from USB Host udd_g_ctrlreq.payload = &udi_hid_exk_report_set; udd_g_ctrlreq.callback = udi_hid_exk_setreport_valid; udd_g_ctrlreq.payload_size = 1; return true; } return false; } bool udi_hid_exk_send_report(void) { if (!main_b_exk_enable) { return false; } if (udi_hid_exk_b_report_trans_ongoing) { return false; } memcpy(udi_hid_exk_report_trans, udi_hid_exk_report.raw, UDI_HID_EXK_REPORT_SIZE); udi_hid_exk_b_report_valid = false; udi_hid_exk_b_report_trans_ongoing = udd_ep_run(UDI_HID_EXK_EP_IN | USB_EP_DIR_IN, false, udi_hid_exk_report_trans, UDI_HID_EXK_REPORT_SIZE, udi_hid_exk_report_sent); return udi_hid_exk_b_report_trans_ongoing; } static void udi_hid_exk_report_sent(udd_ep_status_t status, iram_size_t nb_sent, udd_ep_id_t ep) { UNUSED(status); UNUSED(nb_sent); UNUSED(ep); udi_hid_exk_b_report_trans_ongoing = false; if (udi_hid_exk_b_report_valid) { udi_hid_exk_send_report(); } } static void udi_hid_exk_setreport_valid(void) {} #endif // EXK //******************************************************************************************** // MOU Mouse //******************************************************************************************** #ifdef MOU bool udi_hid_mou_enable(void); void udi_hid_mou_disable(void); bool udi_hid_mou_setup(void); uint8_t udi_hid_mou_getsetting(void); UDC_DESC_STORAGE udi_api_t udi_api_hid_mou = { .enable = (bool (*)(void))udi_hid_mou_enable, .disable = (void (*)(void))udi_hid_mou_disable, .setup = (bool (*)(void))udi_hid_mou_setup, .getsetting = (uint8_t(*)(void))udi_hid_mou_getsetting, .sof_notify = NULL, }; COMPILER_WORD_ALIGNED static uint8_t udi_hid_mou_rate; COMPILER_WORD_ALIGNED static uint8_t udi_hid_mou_protocol; // COMPILER_WORD_ALIGNED // uint8_t udi_hid_mou_report_set; //No set report bool udi_hid_mou_b_report_valid; COMPILER_WORD_ALIGNED uint8_t udi_hid_mou_report[UDI_HID_MOU_REPORT_SIZE]; static bool udi_hid_mou_b_report_trans_ongoing; COMPILER_WORD_ALIGNED static uint8_t udi_hid_mou_report_trans[UDI_HID_MOU_REPORT_SIZE]; COMPILER_WORD_ALIGNED UDC_DESC_STORAGE udi_hid_mou_report_desc_t udi_hid_mou_report_desc = {{ 0x05, 0x01, // Usage Page (Generic Desktop) 0x09, 0x02, // Usage (Mouse) 0xA1, 0x01, // Collection (Application) 0x09, 0x01, // Usage (Pointer) 0xA1, 0x00, // Collection (Physical) // Buttons (5 bits) 0x05, 0x09, // Usage Page (Button) 0x19, 0x01, // Usage Minimum (Button 1) 0x29, 0x05, // Usage Maximun (Button 5) 0x15, 0x00, // Logical Minimum (0) 0x25, 0x01, // Logical Maximum (1) 0x95, 0x05, // Report Count (5) 0x75, 0x01, // Report Size (1) 0x81, 0x02, // Input (Data, Variable, Absolute) // Button padding (3 bits) 0x95, 0x01, // Report Count (1) 0x75, 0x03, // Report Size (3) 0x81, 0x01, // Input (Constant) // X/Y position (2 bytes) 0x05, 0x01, // Usage Page (Generic Desktop) 0x09, 0x30, // Usage (X) 0x09, 0x31, // Usage (Y) 0x15, 0x81, // Logical Minimum (-127) 0x25, 0x7F, // Logical Maximum (127) 0x95, 0x02, // Report Count (2) 0x75, 0x08, // Report Size (8) 0x81, 0x06, // Input (Data, Variable, Relative) // Vertical wheel (1 byte) 0x09, 0x38, // Usage (Wheel) 0x15, 0x81, // Logical Minimum (-127) 0x25, 0x7F, // Logical Maximum (127) 0x95, 0x01, // Report Count (1) 0x75, 0x08, // Report Size (8) 0x81, 0x06, // Input (Data, Variable, Relative) // Horizontal wheel (1 byte) 0x05, 0x0C, // Usage Page (Consumer) 0x0A, 0x38, 0x02, // Usage (AC Pan) 0x15, 0x81, // Logical Minimum (-127) 0x25, 0x7F, // Logical Maximum (127) 0x95, 0x01, // Report Count (1) 0x75, 0x08, // Report Size (8) 0x81, 0x06, // Input (Data, Variable, Relative) 0xC0, // End Collection 0xC0 // End Collection }}; static void udi_hid_mou_report_sent(udd_ep_status_t status, iram_size_t nb_sent, udd_ep_id_t ep); bool udi_hid_mou_enable(void) { // Initialize internal values udi_hid_mou_rate = 0; udi_hid_mou_protocol = 0; udi_hid_mou_b_report_trans_ongoing = false; memset(udi_hid_mou_report, 0, UDI_HID_MOU_REPORT_SIZE); udi_hid_mou_b_report_valid = false; return UDI_HID_MOU_ENABLE_EXT(); } void udi_hid_mou_disable(void) { UDI_HID_MOU_DISABLE_EXT(); } bool udi_hid_mou_setup(void) { return udi_hid_setup(&udi_hid_mou_rate, &udi_hid_mou_protocol, (uint8_t *)&udi_hid_mou_report_desc, NULL); } uint8_t udi_hid_mou_getsetting(void) { return 0; } bool udi_hid_mou_send_report(void) { if (!main_b_mou_enable) { return false; } if (udi_hid_mou_b_report_trans_ongoing) { return false; } memcpy(udi_hid_mou_report_trans, udi_hid_mou_report, UDI_HID_MOU_REPORT_SIZE); udi_hid_mou_b_report_valid = false; udi_hid_mou_b_report_trans_ongoing = udd_ep_run(UDI_HID_MOU_EP_IN | USB_EP_DIR_IN, false, udi_hid_mou_report_trans, UDI_HID_MOU_REPORT_SIZE, udi_hid_mou_report_sent); return udi_hid_mou_b_report_trans_ongoing; } static void udi_hid_mou_report_sent(udd_ep_status_t status, iram_size_t nb_sent, udd_ep_id_t ep) { UNUSED(status); UNUSED(nb_sent); UNUSED(ep); udi_hid_mou_b_report_trans_ongoing = false; if (udi_hid_mou_b_report_valid) { udi_hid_mou_send_report(); } } #endif // MOU //******************************************************************************************** // RAW //******************************************************************************************** #ifdef RAW bool udi_hid_raw_enable(void); void udi_hid_raw_disable(void); bool udi_hid_raw_setup(void); uint8_t udi_hid_raw_getsetting(void); UDC_DESC_STORAGE udi_api_t udi_api_hid_raw = { .enable = (bool (*)(void))udi_hid_raw_enable, .disable = (void (*)(void))udi_hid_raw_disable, .setup = (bool (*)(void))udi_hid_raw_setup, .getsetting = (uint8_t(*)(void))udi_hid_raw_getsetting, .sof_notify = NULL, }; COMPILER_WORD_ALIGNED static uint8_t udi_hid_raw_rate; COMPILER_WORD_ALIGNED static uint8_t udi_hid_raw_protocol; COMPILER_WORD_ALIGNED uint8_t udi_hid_raw_report_set[UDI_HID_RAW_REPORT_SIZE]; static bool udi_hid_raw_b_report_valid; COMPILER_WORD_ALIGNED uint8_t udi_hid_raw_report[UDI_HID_RAW_REPORT_SIZE]; static bool udi_hid_raw_b_report_trans_ongoing; COMPILER_WORD_ALIGNED static uint8_t udi_hid_raw_report_trans[UDI_HID_RAW_REPORT_SIZE]; COMPILER_WORD_ALIGNED UDC_DESC_STORAGE udi_hid_raw_report_desc_t udi_hid_raw_report_desc = {{ 0x06, 0x60, 0xFF, // Usage Page (Vendor Defined) 0x09, 0x61, // Usage (Vendor Defined) 0xA1, 0x01, // Collection (Application) 0x75, 0x08, // Report Size (8) 0x15, 0x00, // Logical Minimum (0) 0x25, 0xFF, // Logical Maximum (255) // Data to host 0x09, 0x62, // Usage (Vendor Defined) 0x95, RAW_EPSIZE, // Report Count 0x81, 0x02, // Input (Data, Variable, Absolute) // Data from host 0x09, 0x63, // Usage (Vendor Defined) 0x95, RAW_EPSIZE, // Report Count 0x91, 0x02, // Output (Data, Variable, Absolute) 0xC0 // End Collection }}; static bool udi_hid_raw_setreport(void); static void udi_hid_raw_setreport_valid(void); static void udi_hid_raw_report_sent(udd_ep_status_t status, iram_size_t nb_sent, udd_ep_id_t ep); bool udi_hid_raw_enable(void) { // Initialize internal values udi_hid_raw_rate = 0; udi_hid_raw_protocol = 0; udi_hid_raw_b_report_trans_ongoing = false; memset(udi_hid_raw_report, 0, UDI_HID_RAW_REPORT_SIZE); udi_hid_raw_b_report_valid = false; return UDI_HID_RAW_ENABLE_EXT(); } void udi_hid_raw_disable(void) { UDI_HID_RAW_DISABLE_EXT(); } bool udi_hid_raw_setup(void) { return udi_hid_setup(&udi_hid_raw_rate, &udi_hid_raw_protocol, (uint8_t *)&udi_hid_raw_report_desc, udi_hid_raw_setreport); } uint8_t udi_hid_raw_getsetting(void) { return 0; } static bool udi_hid_raw_setreport(void) { if ((USB_HID_REPORT_TYPE_OUTPUT == (udd_g_ctrlreq.req.wValue >> 8)) && (0 == (0xFF & udd_g_ctrlreq.req.wValue)) && (UDI_HID_RAW_REPORT_SIZE == udd_g_ctrlreq.req.wLength)) { // Report OUT type on report ID 0 from USB Host udd_g_ctrlreq.payload = udi_hid_raw_report_set; udd_g_ctrlreq.callback = udi_hid_raw_setreport_valid; // must call routine to transform setreport to LED state udd_g_ctrlreq.payload_size = UDI_HID_RAW_REPORT_SIZE; return true; } return false; } bool udi_hid_raw_send_report(void) { if (!main_b_raw_enable) { return false; } if (udi_hid_raw_b_report_trans_ongoing) { return false; } memcpy(udi_hid_raw_report_trans, udi_hid_raw_report, UDI_HID_RAW_REPORT_SIZE); udi_hid_raw_b_report_valid = false; udi_hid_raw_b_report_trans_ongoing = udd_ep_run(UDI_HID_RAW_EP_IN | USB_EP_DIR_IN, false, udi_hid_raw_report_trans, UDI_HID_RAW_REPORT_SIZE, udi_hid_raw_report_sent); return udi_hid_raw_b_report_trans_ongoing; } static void udi_hid_raw_report_sent(udd_ep_status_t status, iram_size_t nb_sent, udd_ep_id_t ep) { UNUSED(status); UNUSED(nb_sent); UNUSED(ep); udi_hid_raw_b_report_trans_ongoing = false; if (udi_hid_raw_b_report_valid) { udi_hid_raw_send_report(); } } static void udi_hid_raw_setreport_valid(void) {} #endif // RAW //******************************************************************************************** // CON //******************************************************************************************** #ifdef CON bool udi_hid_con_enable(void); void udi_hid_con_disable(void); bool udi_hid_con_setup(void); uint8_t udi_hid_con_getsetting(void); UDC_DESC_STORAGE udi_api_t udi_api_hid_con = { .enable = (bool (*)(void))udi_hid_con_enable, .disable = (void (*)(void))udi_hid_con_disable, .setup = (bool (*)(void))udi_hid_con_setup, .getsetting = (uint8_t(*)(void))udi_hid_con_getsetting, .sof_notify = NULL, }; COMPILER_WORD_ALIGNED static uint8_t udi_hid_con_rate; COMPILER_WORD_ALIGNED static uint8_t udi_hid_con_protocol; COMPILER_WORD_ALIGNED uint8_t udi_hid_con_report_set[UDI_HID_CON_REPORT_SIZE]; bool udi_hid_con_b_report_valid; COMPILER_WORD_ALIGNED uint8_t udi_hid_con_report[UDI_HID_CON_REPORT_SIZE]; volatile bool udi_hid_con_b_report_trans_ongoing; COMPILER_WORD_ALIGNED static uint8_t udi_hid_con_report_trans[UDI_HID_CON_REPORT_SIZE]; COMPILER_WORD_ALIGNED UDC_DESC_STORAGE udi_hid_con_report_desc_t udi_hid_con_report_desc = {{ 0x06, 0x31, 0xFF, // Usage Page (Vendor Defined - PJRC Teensy compatible) 0x09, 0x74, // Usage (Vendor Defined - PJRC Teensy compatible) 0xA1, 0x01, // Collection (Application) // Data to host 0x09, 0x75, // Usage (Vendor Defined) 0x15, 0x00, // Logical Minimum (0x00) 0x26, 0xFF, 0x00, // Logical Maximum (0x00FF) 0x95, CONSOLE_EPSIZE, // Report Count 0x75, 0x08, // Report Size (8) 0x81, 0x02, // Input (Data, Variable, Absolute) // Data from host 0x09, 0x76, // Usage (Vendor Defined) 0x15, 0x00, // Logical Minimum (0x00) 0x26, 0xFF, 0x00, // Logical Maximum (0x00FF) 0x95, CONSOLE_EPSIZE, // Report Count 0x75, 0x08, // Report Size (8) 0x91, 0x02, // Output (Data) 0xC0 // End Collection }}; static bool udi_hid_con_setreport(void); static void udi_hid_con_setreport_valid(void); static void udi_hid_con_report_sent(udd_ep_status_t status, iram_size_t nb_sent, udd_ep_id_t ep); bool udi_hid_con_enable(void) { // Initialize internal values udi_hid_con_rate = 0; udi_hid_con_protocol = 0; udi_hid_con_b_report_trans_ongoing = false; memset(udi_hid_con_report, 0, UDI_HID_CON_REPORT_SIZE); udi_hid_con_b_report_valid = false; return UDI_HID_CON_ENABLE_EXT(); } void udi_hid_con_disable(void) { UDI_HID_CON_DISABLE_EXT(); } bool udi_hid_con_setup(void) { return udi_hid_setup(&udi_hid_con_rate, &udi_hid_con_protocol, (uint8_t *)&udi_hid_con_report_desc, udi_hid_con_setreport); } uint8_t udi_hid_con_getsetting(void) { return 0; } static bool udi_hid_con_setreport(void) { if ((USB_HID_REPORT_TYPE_OUTPUT == (udd_g_ctrlreq.req.wValue >> 8)) && (0 == (0xFF & udd_g_ctrlreq.req.wValue)) && (UDI_HID_CON_REPORT_SIZE == udd_g_ctrlreq.req.wLength)) { udd_g_ctrlreq.payload = udi_hid_con_report_set; udd_g_ctrlreq.callback = udi_hid_con_setreport_valid; udd_g_ctrlreq.payload_size = UDI_HID_CON_REPORT_SIZE; return true; } return false; } bool udi_hid_con_send_report(void) { if (!main_b_con_enable) { return false; } if (udi_hid_con_b_report_trans_ongoing) { return false; } memcpy(udi_hid_con_report_trans, udi_hid_con_report, UDI_HID_CON_REPORT_SIZE); udi_hid_con_b_report_valid = false; udi_hid_con_b_report_trans_ongoing = udd_ep_run(UDI_HID_CON_EP_IN | USB_EP_DIR_IN, false, udi_hid_con_report_trans, UDI_HID_CON_REPORT_SIZE, udi_hid_con_report_sent); return udi_hid_con_b_report_trans_ongoing; } static void udi_hid_con_report_sent(udd_ep_status_t status, iram_size_t nb_sent, udd_ep_id_t ep) { UNUSED(status); UNUSED(nb_sent); UNUSED(ep); udi_hid_con_b_report_trans_ongoing = false; if (udi_hid_con_b_report_valid) { udi_hid_con_send_report(); } } static void udi_hid_con_setreport_valid(void) {} #endif // CON