📄 hiddkeyboarddriver.c
字号:
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: 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
* 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.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include "HIDDKeyboardDriver.h"
#include "HIDDKeyboardDriverDescriptors.h"
#include "HIDDKeyboardCallbacks.h"
#include "HIDDKeyboardInputReport.h"
#include "HIDDKeyboardOutputReport.h"
#include <utility/trace.h>
#include <usb/common/core/USBGetDescriptorRequest.h>
#include <usb/common/hid/HIDGenericDescriptor.h>
#include <usb/common/hid/HIDDescriptor.h>
#include <usb/common/hid/HIDGenericRequest.h>
#include <usb/common/hid/HIDReportRequest.h>
#include <usb/common/hid/HIDIdleRequest.h>
#include <usb/common/hid/HIDKeypad.h>
#include <usb/device/core/USBD.h>
#include <usb/device/core/USBDDriver.h>
//------------------------------------------------------------------------------
// Internal types
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Driver structure for an HID device implementing keyboard functionalities.
//------------------------------------------------------------------------------
typedef struct {
/// Standard USB device driver instance.
USBDDriver usbdDriver;
/// Idle rate (in milliseconds) of the input report.
unsigned char inputReportIdleRate;
/// Input report instance.
HIDDKeyboardInputReport inputReport;
/// Output report instance.
HIDDKeyboardOutputReport outputReport;
} HIDDKeyboardDriver;
//------------------------------------------------------------------------------
// Internal variables
//------------------------------------------------------------------------------
/// Static instance of the HID keyboard device driver.
static HIDDKeyboardDriver hiddKeyboardDriver;
//------------------------------------------------------------------------------
// Internal functions
//------------------------------------------------------------------------------
/**
Returns the descriptor requested by the host.
\param type Descriptor type.
\param length Maximum number of bytes to send.
\return 1 if the request has been handled by this function, otherwise 0.
*/
static unsigned char HIDDKeyboardDriver_GetDescriptor(unsigned char type,
unsigned char length)
{
const USBConfigurationDescriptor *pConfiguration;
HIDDescriptor *hidDescriptor;
switch (type) {
case HIDGenericDescriptor_REPORT:
TRACE_INFO_WP("Report ");
// Adjust length and send report descriptor
if (length > HIDDKeyboardDriverDescriptors_REPORTSIZE) {
length = HIDDKeyboardDriverDescriptors_REPORTSIZE;
}
USBD_Write(0, &hiddReportDescriptor, length, 0, 0);
break;
case HIDGenericDescriptor_HID:
TRACE_INFO_WP("HID ");
// Configuration descriptor is different depending on configuration
if (USBD_IsHighSpeed()) {
pConfiguration = hiddKeyboardDriver.usbdDriver.pDescriptors->pHsConfiguration;
}
else {
pConfiguration = hiddKeyboardDriver.usbdDriver.pDescriptors->pFsConfiguration;
}
// Parse the device configuration to get the HID descriptor
USBConfigurationDescriptor_Parse(
pConfiguration,
0,
0,
(USBGenericDescriptor **) &hidDescriptor);
// Adjust length and send HID descriptor
if (length > sizeof(HIDDescriptor)) {
length = sizeof(HIDDescriptor);
}
USBD_Write(0, hidDescriptor, length, 0, 0);
break;
default:
return 0;
}
return 1;
}
/**
Sends the current Idle rate of the input report to the host.
*/
static void HIDDKeyboardDriver_GetIdle()
{
TRACE_INFO_WP("gIdle ");
USBD_Write(0, &(hiddKeyboardDriver.inputReportIdleRate), 1, 0, 0);
}
/**
Retrieves the new idle rate of the input report from the USB host.
\param idleRate New input report idle rate.
*/
static void HIDDKeyboardDriver_SetIdle(unsigned char idleRate)
{
TRACE_INFO_WP("sIdle(%d) ", idleRate);
hiddKeyboardDriver.inputReportIdleRate = idleRate;
USBD_Write(0, 0, 0, 0, 0);
}
/**
Sends the requested report to the host.
\param type Report type.
\param length Maximum number of bytes to send.
*/
static void HIDDKeyboardDriver_GetReport(unsigned char type,
unsigned short length)
{
TRACE_INFO_WP("gReport ");
// Check report type
switch (type) {
case HIDReportRequest_INPUT:
TRACE_INFO_WP("In ");
// Adjust size and send report
if (length > sizeof(HIDDKeyboardInputReport)) {
length = sizeof(HIDDKeyboardInputReport);
}
USBD_Write(0, // Endpoint #0
&(hiddKeyboardDriver.inputReport),
length,
0, // No callback
0);
break;
case HIDReportRequest_OUTPUT:
TRACE_INFO_WP("Out ");
// Adjust size and send report
if (length > sizeof(HIDDKeyboardOutputReport)) {
length = sizeof(HIDDKeyboardOutputReport);
}
USBD_Write(0, // Endpoint #0
&(hiddKeyboardDriver.outputReport),
length,
0, // No callback
0);
break;
default:
USBD_Stall(0);
}
}
/**
Callback invoked when an output report has been received from the host.
Forward the new status of the LEDs to the user program via the
HIDDKeyboardCallbacks_LedsChanged callback.
*/
static void HIDDKeyboardDriver_ReportReceived()
{
TRACE_INFO_WP("oReport ");
// Trigger callback
HIDDKeyboardCallbacks_LedsChanged(
HIDDKeyboardOutputReport_GetNumLockStatus(&(hiddKeyboardDriver.outputReport)),
HIDDKeyboardOutputReport_GetCapsLockStatus(&(hiddKeyboardDriver.outputReport)),
HIDDKeyboardOutputReport_GetScrollLockStatus(&(hiddKeyboardDriver.outputReport)));
// Restart transfer
USBD_Read(HIDDKeyboardDriverDescriptors_INTERRUPTOUT,
&(hiddKeyboardDriver.outputReport),
sizeof(HIDDKeyboardOutputReport),
(TransferCallback) HIDDKeyboardDriver_ReportReceived,
0); // No argument for callback function
}
/**
Retrieves the new value of a report from the host and saves it.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -