/**
* \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 = {{
0x05, 0x01, // Usage Page (Generic Desktop)
0x09, 0x80, // Usage (System Control)
0xA1, 0x01, // Collection (Application)
0x85, REPORT_ID_SYSTEM, // Report ID
0x1A, 0x81,
0x00, // Usage Minimum (81) (System Power Down)
0x2A, 0x83,
0x00, // Usage Maximum (83) (System Wake Up)
0x16, 0x01,
0x00, // Logical Minimum (1)
0x26, 0x03,
0x00, // Logical Maximum (3)
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
0x1A, 0x01,
0x00, // Usage Minimum (Consumer Control)
0x2A, 0x9C,
0x02, // Usage Maximum (AC Distribute Vertically)
0x16, 0x01,
0x00, // Logical Minimum
0x26, 0x9C,
0x02, // Logical Maximum
0x95, 0x01, // Report Count (1)
0x75, 0x10, // Report Size (16)
0x81, 0x00, // Input (Data, Array, Absolute)
0xC0 // End Collection
}};
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
static uint8_t udi_hid_raw_report_recv[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);
static void udi_hid_raw_report_rcvd(udd_ep_status_t status, iram_size_t nb_rcvd, 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) {}
void raw_hid_send(uint8_t *data, uint8_t length) {
if (main_b_raw_enable && !udi_hid_raw_b_report_trans_ongoing && length == UDI_HID_RAW_REPORT_SIZE) {
memcpy(udi_hid_raw_report, data, UDI_HID_RAW_REPORT_SIZE);
udi_hid_raw_send_report();
}
}
bool udi_hid_raw_receive_report(void) {
if (!main_b_raw_enable) {
return false;
}
return udd_ep_run(UDI_HID_RAW_EP_OUT | USB_EP_DIR_OUT, false, udi_hid_raw_report_recv, UDI_HID_RAW_REPORT_SIZE, udi_hid_raw_report_rcvd);
}
static void udi_hid_raw_report_rcvd(udd_ep_status_t status, iram_size_t nb_rcvd, udd_ep_id_t ep) {
UNUSED(ep);
if (status == UDD_EP_TRANSFER_OK && nb_rcvd == UDI_HID_RAW_REPORT_SIZE) {
UDI_HID_RAW_RECEIVE(udi_hid_raw_report_recv, UDI_HID_RAW_REPORT_SIZE);
}
}
#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