00001
00015 #include "em_device.h"
00016 #include "em_common.h"
00017 #include "em_usb.h"
00018 #include "hidkbd.h"
00019
00020
00059 #define DEFAULT_IDLE_RATE 500
00060
00066 EFM32_ALIGN(4)
00067 const char HIDKBD_ReportDescriptor[ 69 ] __attribute__ ((aligned(4)))=
00068 {
00069 0x05, 0x01,
00070 0x09, 0x06,
00071 0xa1, 0x01,
00072 0x05, 0x07,
00073 0x19, 0xe0,
00074 0x29, 0xe7,
00075 0x15, 0x00,
00076 0x25, 0x01,
00077 0x75, 0x01,
00078 0x95, 0x08,
00079 0x81, 0x02,
00080 0x15, 0x00,
00081 0x25, 0x01,
00082 0x75, 0x01,
00083 0x95, 0x08,
00084 0x81, 0x01,
00085 0x19, 0x00,
00086 0x29, 0x65,
00087 0x15, 0x00,
00088 0x25, 0x65,
00089 0x75, 0x08,
00090 0x95, 0x06,
00091 0x81, 0x00,
00092 0x05, 0x08,
00093 0x19, 0x01,
00094 0x29, 0x03,
00095 0x15, 0x00,
00096 0x25, 0x01,
00097 0x75, 0x01,
00098 0x95, 0x03,
00099 0x91, 0x02,
00100 0x75, 0x01,
00101 0x95, 0x05,
00102 0x91, 0x01,
00103 0xc0
00104 };
00105
00108 static uint32_t tmpBuffer;
00109 static uint8_t idleRate;
00110 static void *hidDescriptor = NULL;
00111 static HIDKBD_SetReportFunc_t setReportFunc = NULL;
00112
00113
00114 EFM32_ALIGN(4)
00115 static HIDKBD_KeyReport_t lastSentReport __attribute__ ((aligned(4)));
00116
00117
00118 EFM32_ALIGN(4)
00119 static HIDKBD_KeyReport_t lastKnownReport __attribute__ ((aligned(4)));
00120
00121 static bool QueueEmpty( void );
00122 static bool QueueFull( void );
00123 static bool QueueGet( HIDKBD_KeyReport_t *element );
00124 static void QueueInit( void );
00125 static bool QueuePut( HIDKBD_KeyReport_t *element );
00126
00127
00134 static void IdleTimeout( void )
00135 {
00136
00137
00138 if ( !QueueEmpty() )
00139 {
00140
00141 QueueGet( &lastSentReport );
00142 }
00143
00144 USBD_Write( HIDKBD_INTR_IN_EP_ADDR, &lastSentReport,
00145 sizeof( HIDKBD_KeyReport_t ), NULL );
00146
00147
00148 USBTIMER_Start( HIDKBD_IDLE_TIMER, idleRate * 4, IdleTimeout );
00149 }
00150
00151
00162 static int OutputReportReceived( USB_Status_TypeDef status,
00163 uint32_t xferred,
00164 uint32_t remaining )
00165 {
00166 (void) remaining;
00167
00168 if ( ( status == USB_STATUS_OK )
00169 && ( xferred == 1 )
00170 && ( setReportFunc != NULL ) )
00171 {
00172 setReportFunc( (uint8_t)tmpBuffer );
00173 }
00174
00175 return USB_STATUS_OK;
00176 }
00177
00180
00187 void HIDKBD_Init( HIDKBD_Init_t *init )
00188 {
00189 hidDescriptor = init->hidDescriptor;
00190 setReportFunc = init->setReportFunc;
00191 memset( &lastSentReport, 0, sizeof( HIDKBD_KeyReport_t ) );
00192 memset( &lastKnownReport, 0, sizeof( HIDKBD_KeyReport_t ) );
00193 }
00194
00195
00202 void HIDKBD_KeyboardEvent( HIDKBD_KeyReport_t *report )
00203 {
00204 lastKnownReport = *report;
00205
00206 if ( idleRate != 0 )
00207 {
00208
00209
00210 QueuePut( report );
00211 }
00212 else
00213 {
00214 lastSentReport = *report;
00215 USBD_Write( HIDKBD_INTR_IN_EP_ADDR, &lastSentReport,
00216 sizeof( HIDKBD_KeyReport_t ), NULL );
00217 }
00218 }
00219
00220
00232 int HIDKBD_SetupCmd( const USB_Setup_TypeDef *setup )
00233 {
00234 STATIC_UBUF( hidDesc, USB_HID_DESCSIZE );
00235
00236 int retVal = USB_STATUS_REQ_UNHANDLED;
00237
00238 if ( ( setup->Type == USB_SETUP_TYPE_STANDARD ) &&
00239 ( setup->Direction == USB_SETUP_DIR_IN ) &&
00240 ( setup->Recipient == USB_SETUP_RECIPIENT_INTERFACE ) )
00241 {
00242
00243
00244 switch (setup->bRequest)
00245 {
00246 case GET_DESCRIPTOR:
00247
00248 if ( ( setup->wValue >> 8 ) == USB_HID_REPORT_DESCRIPTOR )
00249 {
00250 USBD_Write( 0, (void*)HIDKBD_ReportDescriptor,
00251 EFM32_MIN(sizeof(HIDKBD_ReportDescriptor), setup->wLength),
00252 NULL );
00253 retVal = USB_STATUS_OK;
00254 }
00255 else if ( ( setup->wValue >> 8 ) == USB_HID_DESCRIPTOR )
00256 {
00257
00258 memcpy( hidDesc, hidDescriptor, USB_HID_DESCSIZE );
00259 USBD_Write( 0, hidDesc, EFM32_MIN(USB_HID_DESCSIZE, setup->wLength),
00260 NULL );
00261 retVal = USB_STATUS_OK;
00262 }
00263 break;
00264 }
00265 }
00266
00267 else if ( ( setup->Type == USB_SETUP_TYPE_CLASS ) &&
00268 ( setup->Recipient == USB_SETUP_RECIPIENT_INTERFACE ) &&
00269 ( setup->wIndex == HIDKBD_INTERFACE_NO ) )
00270 {
00271
00272 switch ( setup->bRequest )
00273 {
00274 case USB_HID_SET_REPORT:
00275
00276 if ( ( ( setup->wValue >> 8 ) == 2 ) &&
00277 ( ( setup->wValue & 0xFF ) == 0 ) &&
00278 ( setup->wLength == 1 ) &&
00279 ( setup->Direction != USB_SETUP_DIR_IN ) )
00280 {
00281 USBD_Read( 0, (void*)&tmpBuffer, 1, OutputReportReceived );
00282 retVal = USB_STATUS_OK;
00283 }
00284 break;
00285
00286 case USB_HID_GET_REPORT:
00287
00288 if ( ( ( setup->wValue >> 8 ) == 1 ) &&
00289 ( ( setup->wValue & 0xFF ) == 0 ) &&
00290 ( setup->wLength == 8 ) &&
00291 ( setup->Direction == USB_SETUP_DIR_IN ) )
00292 {
00293 USBD_Write( HIDKBD_INTR_IN_EP_ADDR, &lastKnownReport,
00294 sizeof( HIDKBD_KeyReport_t ), NULL );
00295 retVal = USB_STATUS_OK;
00296 }
00297 break;
00298
00299 case USB_HID_SET_IDLE:
00300
00301 if ( ( ( setup->wValue & 0xFF) == 0 ) &&
00302 ( setup->wLength == 0 ) &&
00303 ( setup->Direction != USB_SETUP_DIR_IN ) )
00304 {
00305 idleRate = setup->wValue >> 8;
00306 if ( ( idleRate != 0 ) && ( idleRate < ( HIDKBD_POLL_RATE / 4 ) ) )
00307 {
00308 idleRate = HIDKBD_POLL_RATE / 4;
00309 }
00310 USBTIMER_Stop( HIDKBD_IDLE_TIMER );
00311 if ( idleRate != 0 )
00312 {
00313 IdleTimeout();
00314 }
00315 retVal = USB_STATUS_OK;
00316 }
00317 break;
00318
00319 case USB_HID_GET_IDLE:
00320
00321 if ( ( setup->wValue == 0 ) &&
00322 ( setup->wLength == 1 ) &&
00323 ( setup->Direction == USB_SETUP_DIR_IN ) )
00324 {
00325 *(uint8_t*)&tmpBuffer = idleRate;
00326 USBD_Write( 0, (void*)&tmpBuffer, 1, NULL );
00327 retVal = USB_STATUS_OK;
00328 }
00329 break;
00330 }
00331 }
00332
00333 return retVal;
00334 }
00335
00336
00344 void HIDKBD_StateChangeEvent( USBD_State_TypeDef oldState,
00345 USBD_State_TypeDef newState )
00346 {
00347 if ( newState == USBD_STATE_CONFIGURED )
00348 {
00349
00350 if ( oldState != USBD_STATE_SUSPENDED )
00351 {
00352 idleRate = DEFAULT_IDLE_RATE / 4;
00353 QueueInit();
00354 }
00355 if ( idleRate )
00356 {
00357 USBTIMER_Start( HIDKBD_IDLE_TIMER, idleRate * 4, IdleTimeout );
00358 }
00359 }
00360
00361 else if ( ( oldState == USBD_STATE_CONFIGURED ) &&
00362 ( newState != USBD_STATE_SUSPENDED ) )
00363 {
00364
00365 USBTIMER_Stop( HIDKBD_IDLE_TIMER );
00366 }
00367
00368 else if ( newState == USBD_STATE_SUSPENDED )
00369 {
00370
00371
00372 USBTIMER_Stop( HIDKBD_IDLE_TIMER );
00373 }
00374 }
00375
00378
00379
00380 #define QUEUE_SIZE 16
00381
00382 typedef struct ringBuffer_t
00383 {
00384 unsigned int putIdx;
00385 unsigned int getIdx;
00386 HIDKBD_KeyReport_t buf[ QUEUE_SIZE ];
00387 } ringBuffer_t;
00388
00389 ringBuffer_t queue;
00390
00391 static bool QueueEmpty( void )
00392 {
00393 return ( queue.putIdx - queue.getIdx ) == 0;
00394 }
00395
00396 static bool QueueFull( void )
00397 {
00398 return ( queue.putIdx - queue.getIdx ) >= QUEUE_SIZE;
00399 }
00400
00401 static bool QueueGet( HIDKBD_KeyReport_t *element )
00402 {
00403 if ( !QueueEmpty() )
00404 {
00405 *element = queue.buf[ queue.getIdx++ & (QUEUE_SIZE - 1) ];
00406 queue.getIdx = ( queue.getIdx + 1 ) % QUEUE_SIZE;
00407 return true;
00408 }
00409 return false;
00410 }
00411
00412 static void QueueInit( void )
00413 {
00414 queue.getIdx = 0;
00415 queue.putIdx = 0;
00416 }
00417
00418 static bool QueuePut( HIDKBD_KeyReport_t *element )
00419 {
00420 if ( !QueueFull() )
00421 {
00422 queue.buf[ queue.putIdx++ & (QUEUE_SIZE - 1) ] = *element;
00423 queue.putIdx = ( queue.putIdx + 1 ) % QUEUE_SIZE;
00424 return true;
00425 }
00426 return false;
00427 }
00428