📄 keyboard_driver.c
字号:
static const S_usb_endpoint_descriptor *pEndpoints[] = {
&(sConfiguration.sInterruptIn),
&(sConfiguration.sInterruptOut)
};
//! \brief Standard descriptors list
static const S_std_descriptors sDescriptors = {
&sDevice,
(S_usb_configuration_descriptor *) &sConfiguration,
pStrings,
pEndpoints
};
//------------------------------------------------------------------------------
// Internal functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//! \brief Invokes the "report received" callback if it is set.
//! \param pKbd Pointer to a S_kbd instance
//------------------------------------------------------------------------------
static void KBD_ReportReceived(const S_kbd *pKbd)
{
if (pKbd->fReportReceivedCallback != 0) {
pKbd->fReportReceivedCallback(0, 0, 0, 0);
}
// Send a ZLP to the host
USB_SendZLP0(pKbd->sClass.pUsb, 0, 0);
}
//------------------------------------------------------------------------------
// Exported functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//! \brief Handles standard and class-specific SETUP requests.
//!
//! \param pKbd Pointer to a S_kbd instance
//! \see S_kbd
//------------------------------------------------------------------------------
void KBD_RequestHandler(S_kbd *pKbd)
{
const S_usb *pUsb = pKbd->sClass.pUsb;
S_usb_request *pSetup = USB_GetSetup(pUsb);
TRACE_DEBUG_M("NewReq ");
// Check request type
if (USB_REQUEST_TYPE(pSetup) == USB_STANDARD_REQUEST) {
// Handle standard requests
switch (pSetup->bRequest) {
//----------------------
case USB_GET_DESCRIPTOR:
//----------------------
// Identify requested descriptor
switch (HBYTE(pSetup->wValue)) {
//-------------------------
case HID_REPORT_DESCRIPTOR:
//-------------------------
// Send report descriptor
TRACE_DEBUG_M("Report ");
USB_Write(pUsb,
0,
pReport,
min(sizeof(pReport), pSetup->wLength),
0,
0);
break;
//------------------
case HID_DESCRIPTOR:
//------------------
// Send HID descriptor
TRACE_DEBUG_M("HID ");
USB_Write(pUsb,
0,
(void *) &sConfiguration.sHID,
min(sizeof(S_hid_descriptor), pSetup->wLength),
0,
0);
break;
//------
default:
//------
// Forward request to standard handler
STD_RequestHandler(&(pKbd->sClass));
break;
}
break;
//------
default:
//------
// Forward request to standard handler
STD_RequestHandler(&(pKbd->sClass));
break;
}
}
else {
// Handle class-specific requests
switch (pSetup->bRequest) {
//----------------
case HID_GET_IDLE:
//----------------
// Return current Idle rate
TRACE_DEBUG_M("gIdle ");
USB_Write(pUsb, 0, &(pKbd->bIdleRate), 1, 0, 0);
break;
//----------------
case HID_SET_IDLE:
//----------------
// Get new Idle rate
pKbd->bIdleRate = HBYTE(pSetup->wValue);
TRACE_DEBUG_M("sIdle(%d) ", pKbd->bIdleRate);
USB_SendZLP0(pUsb, 0, 0);
break;
//------------------
case HID_GET_REPORT:
//------------------
// Send the current report to the host
TRACE_DEBUG_M("gReport ");
// Check report type
if (HBYTE(pSetup->wValue) == HID_INPUT_REPORT) {
// Send report
TRACE_DEBUG_M("In ");
USB_Write(pUsb, 0, &(pKbd->sInputReport),
KBD_INPUT_REPORT_SIZE, 0, 0);
}
else if (HBYTE(pSetup->wValue) == HID_OUTPUT_REPORT) {
// Send report
TRACE_DEBUG_M("Out ");
USB_Write(pUsb, 0, &(pKbd->sOutputReport),
KBD_OUTPUT_REPORT_SIZE, 0, 0);
}
else {
// STALL endpoint 0
USB_Stall(pUsb, 0);
}
break;
//------------------
case HID_SET_REPORT:
//------------------
// Retrieve new report
TRACE_DEBUG_M("sReport ");
// Check report type
if (HBYTE(pSetup->wValue) == HID_OUTPUT_REPORT) {
// Retrieve report
USB_Read(pUsb, 0, &(pKbd->sOutputReport), KBD_OUTPUT_REPORT_SIZE,
(Callback_f) KBD_ReportReceived, pKbd);
}
else {
// STALL endpoint 0
USB_Stall(pUsb, 0);
}
break;
//------
default:
//------
// STALL endpoint 0
TRACE_WARNING("W: KBD_RequestHandler: Unknown request 0x%02X\n\r",
pSetup->bRequest);
USB_Stall(pUsb, 0);
}
}
}
//------------------------------------------------------------------------------
//! \brief Initializes a HID keyboard driver
//!
//! This method sets the standard descriptors of the device and the
//! default HID keyboard configuration.
//! \param pKbd Pointer to a S_kbd instance
//! \param pUsb Pointer to the S_usb driver instance to use
//! \param fCallback Callback function to invoke when a new report is received
//! \see S_kbd
//! \see S_usb
//------------------------------------------------------------------------------
void KBD_Init(S_kbd *pKbd, const S_usb *pUsb, Callback_f fCallback)
{
// Initialize mouse driver
pKbd->bIdleRate = 0;
pKbd->sInputReport.bmModifierKeys = 0;
pKbd->sInputReport.pPressedKeys[0] = 0;
pKbd->sInputReport.pPressedKeys[1] = 0;
pKbd->sInputReport.pPressedKeys[2] = 0;
pKbd->sOutputReport.bmLeds = 0;
pKbd->fReportReceivedCallback = fCallback;
// Initialize standard class attributes
pKbd->sClass.pUsb = pUsb;
pKbd->sClass.pDescriptors = &sDescriptors;
// Initialize the USB driver
USB_Init(pUsb);
}
//------------------------------------------------------------------------------
//! \brief Sends the current mouse report to the host, through the interrupt IN
//! endpoint
//! \param pKbd Pointer to a S_kbd instance
//! \param fCallback Optional callback function to invoke when the report is
//! sent
//! \param pArgument Optional argument to pass to the callback function
//------------------------------------------------------------------------------
unsigned char KBD_SendReport(const S_kbd *pKbd,
Callback_f fCallback,
void *pArgument)
{
return USB_Write(pKbd->sClass.pUsb, KBD_INTERRUPT_IN, &(pKbd->sInputReport),
KBD_INPUT_REPORT_SIZE, fCallback, pArgument);
}
//------------------------------------------------------------------------------
//! \brief Waits for a new report from the host to be received.
//! \param pKbd Pointer to a S_kbd instance
//! \param fCallback Optional callback function to invoke when the report is
//! received
//! \param pArgument Optional argument to pass to the callback function
//------------------------------------------------------------------------------
unsigned char KBD_ReceiveReport(S_kbd *pKbd,
Callback_f fCallback,
void *pArgument)
{
return USB_Read(pKbd->sClass.pUsb, KBD_INTERRUPT_OUT, &(pKbd->sOutputReport),
KBD_OUTPUT_REPORT_SIZE, fCallback, pArgument);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -