59 #define DEFAULT_IDLE_RATE 500
108 static uint32_t tmpBuffer;
109 static uint8_t idleRate;
110 static void *hidDescriptor = NULL;
121 static
bool QueueEmpty(
void );
122 static
bool QueueFull(
void );
124 static
void QueueInit(
void );
134 static
void IdleTimeout(
void )
141 QueueGet( &lastSentReport );
144 USBD_Write( HIDKBD_INTR_IN_EP_ADDR, &lastSentReport,
148 USBTIMER_Start( HIDKBD_IDLE_TIMER, idleRate * 4, IdleTimeout );
162 static int OutputReportReceived( USB_Status_TypeDef status,
168 if ( ( status == USB_STATUS_OK )
170 && ( setReportFunc != NULL ) )
172 setReportFunc( (uint8_t)tmpBuffer );
175 return USB_STATUS_OK;
204 lastKnownReport = *report;
214 lastSentReport = *report;
215 USBD_Write( HIDKBD_INTR_IN_EP_ADDR, &lastSentReport,
234 STATIC_UBUF( hidDesc, USB_HID_DESCSIZE );
236 int retVal = USB_STATUS_REQ_UNHANDLED;
238 if ( ( setup->Type == USB_SETUP_TYPE_STANDARD ) &&
239 ( setup->Direction == USB_SETUP_DIR_IN ) &&
240 ( setup->Recipient == USB_SETUP_RECIPIENT_INTERFACE ) )
244 switch (setup->bRequest)
248 if ( ( setup->wValue >> 8 ) == USB_HID_REPORT_DESCRIPTOR )
250 USBD_Write( 0, (
void*)HIDKBD_ReportDescriptor,
251 SL_MIN(
sizeof(HIDKBD_ReportDescriptor), setup->wLength),
253 retVal = USB_STATUS_OK;
255 else if ( ( setup->wValue >> 8 ) == USB_HID_DESCRIPTOR )
258 memcpy( hidDesc, hidDescriptor, USB_HID_DESCSIZE );
259 USBD_Write( 0, hidDesc,
SL_MIN(USB_HID_DESCSIZE, setup->wLength),
261 retVal = USB_STATUS_OK;
267 else if ( ( setup->Type == USB_SETUP_TYPE_CLASS ) &&
268 ( setup->Recipient == USB_SETUP_RECIPIENT_INTERFACE ) &&
269 ( setup->wIndex == HIDKBD_INTERFACE_NO ) )
272 switch ( setup->bRequest )
274 case USB_HID_SET_REPORT:
276 if ( ( ( setup->wValue >> 8 ) == 2 ) &&
277 ( ( setup->wValue & 0xFF ) == 0 ) &&
278 ( setup->wLength == 1 ) &&
279 ( setup->Direction != USB_SETUP_DIR_IN ) )
281 USBD_Read( 0, (
void*)&tmpBuffer, 1, OutputReportReceived );
282 retVal = USB_STATUS_OK;
286 case USB_HID_GET_REPORT:
288 if ( ( ( setup->wValue >> 8 ) == 1 ) &&
289 ( ( setup->wValue & 0xFF ) == 0 ) &&
290 ( setup->wLength == 8 ) &&
291 ( setup->Direction == USB_SETUP_DIR_IN ) )
293 USBD_Write( HIDKBD_INTR_IN_EP_ADDR, &lastKnownReport,
295 retVal = USB_STATUS_OK;
299 case USB_HID_SET_IDLE:
301 if ( ( ( setup->wValue & 0xFF) == 0 ) &&
302 ( setup->wLength == 0 ) &&
303 ( setup->Direction != USB_SETUP_DIR_IN ) )
305 idleRate = setup->wValue >> 8;
306 if ( ( idleRate != 0 ) && ( idleRate < ( HIDKBD_POLL_RATE / 4 ) ) )
308 idleRate = HIDKBD_POLL_RATE / 4;
310 USBTIMER_Stop( HIDKBD_IDLE_TIMER );
315 retVal = USB_STATUS_OK;
319 case USB_HID_GET_IDLE:
321 if ( ( setup->wValue == 0 ) &&
322 ( setup->wLength == 1 ) &&
323 ( setup->Direction == USB_SETUP_DIR_IN ) )
325 *(uint8_t*)&tmpBuffer = idleRate;
326 USBD_Write( 0, (
void*)&tmpBuffer, 1, NULL );
327 retVal = USB_STATUS_OK;
345 USBD_State_TypeDef newState )
347 if ( newState == USBD_STATE_CONFIGURED )
350 if ( oldState != USBD_STATE_SUSPENDED )
357 USBTIMER_Start( HIDKBD_IDLE_TIMER, idleRate * 4, IdleTimeout );
361 else if ( ( oldState == USBD_STATE_CONFIGURED ) &&
362 ( newState != USBD_STATE_SUSPENDED ) )
365 USBTIMER_Stop( HIDKBD_IDLE_TIMER );
368 else if ( newState == USBD_STATE_SUSPENDED )
372 USBTIMER_Stop( HIDKBD_IDLE_TIMER );
380 #define QUEUE_SIZE 16
382 typedef struct ringBuffer_t
391 static bool QueueEmpty(
void )
393 return ( queue.putIdx - queue.getIdx ) == 0;
396 static bool QueueFull(
void )
398 return ( queue.putIdx - queue.getIdx ) >= QUEUE_SIZE;
405 *element = queue.buf[ queue.getIdx++ & (QUEUE_SIZE - 1) ];
406 queue.getIdx = ( queue.getIdx + 1 ) % QUEUE_SIZE;
412 static void QueueInit(
void )
422 queue.buf[ queue.putIdx++ & (QUEUE_SIZE - 1) ] = *element;
423 queue.putIdx = ( queue.putIdx + 1 ) % QUEUE_SIZE;
HIDKBD_SetReportFunc_t setReportFunc
#define DEFAULT_IDLE_RATE
CMSIS Cortex-M Peripheral Access Layer for Silicon Laboratories microcontroller devices.
#define SL_ALIGN(X)
Macro for aligning a variable. Use this macro before the variable definition. X denotes the stora...
void HIDKBD_StateChangeEvent(USBD_State_TypeDef oldState, USBD_State_TypeDef newState)
Handle USB state change events, this function must be called each time the USB device state is change...
General purpose utilities.
const char HIDKBD_ReportDescriptor[69] SL_ATTRIBUTE_ALIGN(4)
int HIDKBD_SetupCmd(const USB_Setup_TypeDef *setup)
Handle USB setup commands. Implements HID class specific commands. This function must be called each ...
void HIDKBD_Init(HIDKBD_Init_t *init)
Initialize HID Keyboard driver.
void(* HIDKBD_SetReportFunc_t)(uint8_t report)
Callback function pointer for HID output reports. This function will be called by the driver each tim...
void HIDKBD_KeyboardEvent(HIDKBD_KeyReport_t *report)
Report a keyboard press/release event.
#define SL_MIN(a, b)
Macro for getting minimum value. No sideeffects, a and b are evaluated once only. ...
USB Human Interface Devices (HID) class keyboard driver.