kopia lustrzana https://github.com/skuep/AIOC
171 wiersze
5.3 KiB
C
171 wiersze
5.3 KiB
C
#include <io.h>
|
|
#include "usb_hid.h"
|
|
#include "tusb.h"
|
|
#include "settings.h"
|
|
#include "usb_descriptors.h"
|
|
|
|
#define USB_HID_INOUT_REPORT_LEN 4
|
|
|
|
static uint8_t buttonState = 0x00;
|
|
static uint8_t gpioState = 0x00;
|
|
|
|
static void MakeReport(uint8_t * buffer)
|
|
{
|
|
/* TODO: Read the actual states of the GPIO input hardware pins. */
|
|
buffer[0] = buttonState & 0x0F;
|
|
buffer[1] = gpioState;
|
|
buffer[2] = 0x00;
|
|
buffer[3] = 0x00;
|
|
}
|
|
|
|
static bool SendReport(void)
|
|
{
|
|
uint8_t reportBuffer[USB_HID_INOUT_REPORT_LEN];
|
|
MakeReport(reportBuffer);
|
|
|
|
return tud_hid_report(0, reportBuffer, sizeof(reportBuffer));
|
|
}
|
|
|
|
static void ControlPTT(uint8_t gpio)
|
|
{
|
|
uint8_t pttMask = IO_PTT_MASK_NONE;
|
|
|
|
if (settingsRegMap[SETTINGS_REG_AIOC_IOMUX0] & SETTINGS_REG_AIOC_IOMUX0_PTT1SRC_CM108GPIO1_MASK) {
|
|
pttMask |= gpio & 0x01 ? IO_PTT_MASK_PTT1 : 0;
|
|
}
|
|
|
|
if (settingsRegMap[SETTINGS_REG_AIOC_IOMUX0] & SETTINGS_REG_AIOC_IOMUX0_PTT1SRC_CM108GPIO2_MASK) {
|
|
pttMask |= gpio & 0x02 ? IO_PTT_MASK_PTT1 : 0;
|
|
}
|
|
|
|
if (settingsRegMap[SETTINGS_REG_AIOC_IOMUX0] & SETTINGS_REG_AIOC_IOMUX0_PTT1SRC_CM108GPIO3_MASK) {
|
|
pttMask |= gpio & 0x04 ? IO_PTT_MASK_PTT1 : 0;
|
|
}
|
|
|
|
if (settingsRegMap[SETTINGS_REG_AIOC_IOMUX0] & SETTINGS_REG_AIOC_IOMUX0_PTT1SRC_CM108GPIO4_MASK) {
|
|
pttMask |= gpio & 0x08 ? IO_PTT_MASK_PTT1 : 0;
|
|
}
|
|
|
|
if (settingsRegMap[SETTINGS_REG_AIOC_IOMUX1] & SETTINGS_REG_AIOC_IOMUX1_PTT2SRC_CM108GPIO1_MASK) {
|
|
pttMask |= gpio & 0x01 ? IO_PTT_MASK_PTT2 : 0;
|
|
}
|
|
|
|
if (settingsRegMap[SETTINGS_REG_AIOC_IOMUX1] & SETTINGS_REG_AIOC_IOMUX1_PTT2SRC_CM108GPIO2_MASK) {
|
|
pttMask |= gpio & 0x02 ? IO_PTT_MASK_PTT2 : 0;
|
|
}
|
|
|
|
if (settingsRegMap[SETTINGS_REG_AIOC_IOMUX1] & SETTINGS_REG_AIOC_IOMUX1_PTT2SRC_CM108GPIO3_MASK) {
|
|
pttMask |= gpio & 0x04 ? IO_PTT_MASK_PTT2 : 0;
|
|
}
|
|
|
|
if (settingsRegMap[SETTINGS_REG_AIOC_IOMUX1] & SETTINGS_REG_AIOC_IOMUX1_PTT2SRC_CM108GPIO4_MASK) {
|
|
pttMask |= gpio & 0x08 ? IO_PTT_MASK_PTT2 : 0;
|
|
}
|
|
|
|
IO_PTTControl(pttMask);
|
|
}
|
|
|
|
// Invoked when received GET_REPORT control request
|
|
// Application must fill buffer report's content and return its length.
|
|
// Return zero will cause the stack to STALL request
|
|
uint16_t tud_hid_get_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen)
|
|
{
|
|
(void) itf;
|
|
(void) report_id;
|
|
(void) buffer;
|
|
(void) reqlen;
|
|
|
|
switch (report_type) {
|
|
case HID_REPORT_TYPE_INPUT:
|
|
TU_ASSERT(reqlen >= USB_HID_INOUT_REPORT_LEN, 0);
|
|
|
|
MakeReport(buffer);
|
|
return USB_HID_INOUT_REPORT_LEN;
|
|
|
|
case HID_REPORT_TYPE_FEATURE:
|
|
return Settings_RegRead(report_id, buffer, reqlen);
|
|
|
|
default:
|
|
TU_BREAKPOINT();
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
// Invoked when received SET_REPORT control request
|
|
void tud_hid_set_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize)
|
|
{
|
|
(void) itf;
|
|
(void) report_id;
|
|
|
|
switch (report_type) {
|
|
case HID_REPORT_TYPE_OUTPUT:
|
|
TU_ASSERT(bufsize == USB_HID_INOUT_REPORT_LEN, /* */);
|
|
|
|
/* Output report, emulate CM108 behaviour */
|
|
if ((buffer[0] & 0xC0) == 0) {
|
|
uint8_t gpioChange = gpioState ^ buffer[1];
|
|
gpioState = buffer[1];
|
|
ControlPTT(gpioState);
|
|
|
|
/* The CM108 sends an input report via the HID interrupt endpoint to the host,
|
|
* whenever something changes (e.g. GPIO). Currently, this is only the case, whenever
|
|
* the host changes the GPIO state (since the GPIOs are hardwired as output).
|
|
* In the future, we might also support GPIO as input for other purposes. In that
|
|
* case, we might need some kind of interrupt mechanism to detect changes on the GPIOs.
|
|
* However some GPIOs might be shared (e.g. with UART), so we need to find a way to
|
|
* only enable the external GPIO interrupts, if the host actually has opened the HID
|
|
* interrupt pipe.
|
|
*/
|
|
if (gpioChange) {
|
|
SendReport();
|
|
}
|
|
}
|
|
break;
|
|
|
|
case HID_REPORT_TYPE_FEATURE:
|
|
if (report_id == 0) {
|
|
/* Special HID feature report case. Not a valid register map address to write.
|
|
* It is used for other functions (store, recall, defaults...) */
|
|
uint32_t data = ( (((uint32_t) buffer[0]) << 0) |
|
|
(((uint32_t) buffer[1]) << 8) |
|
|
(((uint32_t) buffer[2]) << 16) |
|
|
(((uint32_t) buffer[3]) << 24) );
|
|
|
|
if (data & 0x00000010UL) {
|
|
Settings_Default();
|
|
}
|
|
|
|
if (data & 0x00000040UL) {
|
|
Settings_Recall();
|
|
}
|
|
|
|
if (data & 0x00000080UL) {
|
|
Settings_Store();
|
|
}
|
|
} else {
|
|
Settings_RegWrite(report_id, buffer, bufsize);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
TU_BREAKPOINT();
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
void USB_HIDInit(void)
|
|
{
|
|
|
|
|
|
}
|
|
|
|
bool USB_HIDSendButtonState(uint8_t buttonMask)
|
|
{
|
|
buttonState = buttonMask;
|
|
|
|
return SendReport();
|
|
}
|