993 lines
30 KiB
C
993 lines
30 KiB
C
/**
|
|
* \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 <a href="http://www.atmel.com/design-support/">Atmel Support</a>
|
|
*/
|
|
|
|
#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 <string.h>
|
|
#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)
|
|
0x05, 0x07, // Usage Page (Keyboard)
|
|
0x19, 0xE0, // Usage Minimum (224)
|
|
0x29, 0xE7, // Usage Maximum (231)
|
|
0x15, 0x00, // Logical Minimum (0)
|
|
0x25, 0x01, // Logical Maximum (1)
|
|
0x75, 0x01, // Report Size (1)
|
|
0x95, 0x08, // Report Count (8)
|
|
0x81, 0x02, // Input (Data, Variable, Absolute)
|
|
0x81, 0x01, // Input (Constant)
|
|
0x19, 0x00, // Usage Minimum (0)
|
|
0x29, 0x65, // Usage Maximum (101)
|
|
0x15, 0x00, // Logical Minimum (0)
|
|
0x25, 0x65, // Logical Maximum (101)
|
|
0x75, 0x08, // Report Size (8)
|
|
0x95, 0x06, // Report Count (6)
|
|
0x81, 0x00, // Input (Data, Array)
|
|
0x05, 0x08, // Usage Page (LED)
|
|
0x19, 0x01, // Usage Minimum (1)
|
|
0x29, 0x05, // Usage Maximum (5)
|
|
0x15, 0x00, // Logical Minimum (0)
|
|
0x25, 0x01, // Logical Maximum (1)
|
|
0x75, 0x01, // Report Size (1)
|
|
0x95, 0x05, // Report Count (5)
|
|
0x91, 0x02, // Output (Data, Variable, Absolute)
|
|
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) - Keyboard,
|
|
|
|
//Mods
|
|
0x75, 0x01, // Report Size (1),
|
|
0x95, 0x08, // Report Count (8),
|
|
0x15, 0x00, // Logical Minimum (0),
|
|
0x25, 0x01, // Logical Maximum (1),
|
|
0x05, 0x07, // Usage Page (Key Codes),
|
|
0x19, 0xE0, // Usage Minimum (224),
|
|
0x29, 0xE7, // Usage Maximum (231),
|
|
0x81, 0x02, // Input (Data, Variable, Absolute),
|
|
|
|
//LED Report
|
|
0x75, 0x01, // Report Size (1),
|
|
0x95, 0x05, // Report Count (5),
|
|
0x05, 0x08, // Usage Page (LEDs),
|
|
0x19, 0x01, // Usage Minimum (1),
|
|
0x29, 0x05, // Usage Maximum (5),
|
|
0x91, 0x02, // Output (Data, Variable, Absolute),
|
|
|
|
//LED Report Padding
|
|
0x75, 0x03, // Report Size (3),
|
|
0x95, 0x01, // Report Count (1),
|
|
0x91, 0x03, // Output (Constant),
|
|
|
|
//Main keys
|
|
0x75, 0x01, // Report Size (1),
|
|
0x95, 0xF8, // Report Count (248),
|
|
0x15, 0x00, // Logical Minimum (0),
|
|
0x25, 0x01, // Logical Maximum (1),
|
|
0x05, 0x07, // Usage Page (Key Codes),
|
|
0x19, 0x00, // Usage Minimum (0),
|
|
0x29, 0xF7, // Usage Maximum (247),
|
|
0x81, 0x02, // Input (Data, Variable, Absolute, Bitfield),
|
|
0xc0, // End Collection - Keyboard
|
|
}
|
|
};
|
|
|
|
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 = {
|
|
{
|
|
// System Control Collection (8 bits)
|
|
|
|
0x05, 0x01, // Usage Page (Generic Desktop),
|
|
0x09, 0x80, // Usage (System Control),
|
|
0xA1, 0x01, // Collection (Application),
|
|
0x85, REPORT_ID_SYSTEM, // Report ID (2) (System),
|
|
0x16, 0x01, 0x00, // Logical Minimum (1),
|
|
0x26, 0x03, 0x00, // Logical Maximum (3),
|
|
0x1A, 0x81, 0x00, // Usage Minimum (81) (System Power Down),
|
|
0x2A, 0x83, 0x00, // Usage Maximum (83) (System Wake Up),
|
|
0x75, 0x10, // Report Size (16),
|
|
0x95, 0x01, // Report Count (1),
|
|
0x81, 0x00, // Input (Data, Array),
|
|
0xC0, // End Collection - System Control
|
|
|
|
// Consumer Control Collection - Media Keys (16 bits)
|
|
|
|
0x05, 0x0C, // Usage Page (Consumer),
|
|
0x09, 0x01, // Usage (Consumer Control),
|
|
0xA1, 0x01, // Collection (Application),
|
|
0x85, REPORT_ID_CONSUMER, // Report ID (3) (Consumer),
|
|
0x16, 0x01, 0x00, // Logical Minimum (1),
|
|
0x26, 0x9C, 0x02, // Logical Maximum (668),
|
|
0x1A, 0x01, 0x00, // Usage Minimum (1),
|
|
0x2A, 0x9C, 0x02, // Usage Maximum (668),
|
|
0x75, 0x10, // Report Size (16),
|
|
0x95, 0x01, // Report Count (1),
|
|
0x81, 0x00, // Input (Data, Array),
|
|
0xC0, // End Collection - Consumer Control
|
|
}
|
|
};
|
|
|
|
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),
|
|
0x05, 0x09, // Usage Page (Buttons),
|
|
0x19, 0x01, // Usage Minimum (01),
|
|
0x29, 0x05, // Usage Maximun (05),
|
|
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), ;5 button bits
|
|
0x95, 0x01, // Report Count (1),
|
|
0x75, 0x03, // Report Size (3),
|
|
0x81, 0x01, // Input (Constant), ;3 bit padding,
|
|
|
|
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), ;2 position bytes (X & Y),
|
|
|
|
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),
|
|
|
|
0x05, 0x0C, // Usage Page (Consumer),
|
|
0x0A, 0x38, 0x02, // Usage (AC Pan (Horizontal 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),
|
|
|
|
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, // Usage Page (Vendor Defined)
|
|
0xFF, 0xFF,
|
|
0x0A, // Usage (Mouse)
|
|
0xFF, 0xFF,
|
|
0xA1, 0x01, // Collection (Application)
|
|
0x75, 0x08, // Report Size (8)
|
|
0x15, 0x00, // Logical Minimum (0)
|
|
0x25, 0xFF, // Logical Maximum (255)
|
|
0x95, 0x40, // Report Count
|
|
0x09, 0x01, // Usage (Input)
|
|
0x81, 0x02, // Input (Data
|
|
0x95, 0x40, // Report Count
|
|
0x09, 0x02, // Usage (Output)
|
|
0x91, 0x02, // Output (Data
|
|
0xC0, // End Collection - Consumer Control
|
|
}
|
|
};
|
|
|
|
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, // Vendor Page (PJRC Teensy compatible)
|
|
0x09, 0x74, // Vendor Usage (PJRC Teensy compatible)
|
|
0xA1, 0x01, // Collection (Application)
|
|
0x09, 0x75, // Usage (Vendor)
|
|
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)
|
|
0x09, 0x76, // Usage (Vendor)
|
|
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
|