2011-07-20 15:32:52 +00:00
/*
Copyright 2011 Jun Wako < wakojun @ gmail . com >
This program is free software : you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation , either version 2 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program . If not , see < http : //www.gnu.org/licenses/>.
*/
2011-03-09 15:50:27 +00:00
# include <stdint.h>
2011-02-03 04:26:44 +00:00
# include "usbdrv.h"
# include "usbconfig.h"
# include "host.h"
2011-09-17 13:39:50 +00:00
# include "report.h"
# include "print.h"
2011-02-10 06:51:30 +00:00
# include "debug.h"
2011-09-17 13:39:50 +00:00
# include "host_driver.h"
# include "vusb.h"
2011-02-03 04:26:44 +00:00
2011-09-17 13:39:50 +00:00
static uint8_t vusb_keyboard_leds = 0 ;
static uint8_t vusb_idle_rate = 0 ;
2011-02-10 06:51:30 +00:00
2011-09-17 13:39:50 +00:00
/* Keyboard report send buffer */
# define KBUF_SIZE 16
static report_keyboard_t kbuf [ KBUF_SIZE ] ;
static uint8_t kbuf_head = 0 ;
static uint8_t kbuf_tail = 0 ;
2011-02-10 06:51:30 +00:00
2011-09-17 13:39:50 +00:00
/* transfer keyboard report from buffer */
void vusb_transfer_keyboard ( void )
2011-02-10 06:51:30 +00:00
{
2011-09-17 13:39:50 +00:00
if ( usbInterruptIsReady ( ) ) {
2012-05-27 05:17:48 +00:00
if ( kbuf_head ! = kbuf_tail ) {
2011-09-17 13:39:50 +00:00
usbSetInterrupt ( ( void * ) & kbuf [ kbuf_tail ] , sizeof ( report_keyboard_t ) ) ;
kbuf_tail = ( kbuf_tail + 1 ) % KBUF_SIZE ;
2012-10-16 18:44:01 +00:00
if ( debug_keyboard ) {
print ( " V-USB: kbuf[ " ) ; pdec ( kbuf_tail ) ; print ( " -> " ) ; pdec ( kbuf_head ) ; print ( " ]( " ) ;
phex ( ( kbuf_head < kbuf_tail ) ? ( KBUF_SIZE - kbuf_tail + kbuf_head ) : ( kbuf_head - kbuf_tail ) ) ;
print ( " ) \n " ) ;
}
2012-05-27 05:17:48 +00:00
}
2011-02-25 12:58:00 +00:00
}
2011-02-10 06:51:30 +00:00
}
/*------------------------------------------------------------------*
2011-09-17 13:39:50 +00:00
* Host driver
2011-02-10 06:51:30 +00:00
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2011-09-17 13:39:50 +00:00
static uint8_t keyboard_leds ( void ) ;
static void send_keyboard ( report_keyboard_t * report ) ;
static void send_mouse ( report_mouse_t * report ) ;
static void send_system ( uint16_t data ) ;
static void send_consumer ( uint16_t data ) ;
static host_driver_t driver = {
keyboard_leds ,
send_keyboard ,
send_mouse ,
send_system ,
send_consumer
} ;
2011-02-03 04:26:44 +00:00
2011-09-17 13:39:50 +00:00
host_driver_t * vusb_driver ( void )
2011-02-03 04:26:44 +00:00
{
2011-09-17 13:39:50 +00:00
return & driver ;
2011-02-03 04:26:44 +00:00
}
2011-09-17 13:39:50 +00:00
static uint8_t keyboard_leds ( void ) {
return vusb_keyboard_leds ;
}
static void send_keyboard ( report_keyboard_t * report )
2011-02-03 04:26:44 +00:00
{
uint8_t next = ( kbuf_head + 1 ) % KBUF_SIZE ;
if ( next ! = kbuf_tail ) {
2011-09-17 13:39:50 +00:00
kbuf [ kbuf_head ] = * report ;
2011-02-03 04:26:44 +00:00
kbuf_head = next ;
2011-02-07 05:59:07 +00:00
} else {
2011-02-10 06:51:30 +00:00
debug ( " kbuf: full \n " ) ;
2011-02-03 04:26:44 +00:00
}
}
2011-02-10 06:51:30 +00:00
2012-06-28 07:51:56 +00:00
typedef struct {
uint8_t report_id ;
report_mouse_t report ;
} __attribute__ ( ( packed ) ) vusb_mouse_report_t ;
2011-09-17 13:39:50 +00:00
static void send_mouse ( report_mouse_t * report )
2011-02-03 04:26:44 +00:00
{
2012-06-28 07:51:56 +00:00
vusb_mouse_report_t r = {
. report_id = REPORT_ID_MOUSE ,
. report = * report
} ;
2011-02-03 04:26:44 +00:00
if ( usbInterruptIsReady3 ( ) ) {
2012-06-28 07:51:56 +00:00
usbSetInterrupt3 ( ( void * ) & r , sizeof ( vusb_mouse_report_t ) ) ;
2011-02-03 04:26:44 +00:00
}
}
2011-05-21 01:28:57 +00:00
2012-06-28 11:15:56 +00:00
2012-06-28 07:51:56 +00:00
typedef struct {
2012-06-28 11:15:56 +00:00
uint8_t report_id ;
uint16_t usage ;
} __attribute__ ( ( packed ) ) report_extra_t ;
2012-06-28 07:51:56 +00:00
2011-09-17 13:39:50 +00:00
static void send_system ( uint16_t data )
2011-05-21 01:28:57 +00:00
{
2012-06-28 11:15:56 +00:00
static uint16_t last_data = 0 ;
if ( data = = last_data ) return ;
last_data = data ;
report_extra_t report = {
2012-06-28 07:51:56 +00:00
. report_id = REPORT_ID_SYSTEM ,
2012-06-28 11:15:56 +00:00
. usage = data
2012-06-28 07:51:56 +00:00
} ;
2011-05-21 01:28:57 +00:00
if ( usbInterruptIsReady3 ( ) ) {
2012-06-28 11:15:56 +00:00
usbSetInterrupt3 ( ( void * ) & report , sizeof ( report ) ) ;
2011-05-21 01:28:57 +00:00
}
}
2011-09-17 13:39:50 +00:00
static void send_consumer ( uint16_t data )
2011-05-21 01:28:57 +00:00
{
2011-05-31 12:17:56 +00:00
static uint16_t last_data = 0 ;
if ( data = = last_data ) return ;
last_data = data ;
2012-06-28 11:15:56 +00:00
report_extra_t report = {
. report_id = REPORT_ID_CONSUMER ,
. usage = data
} ;
2011-05-21 01:28:57 +00:00
if ( usbInterruptIsReady3 ( ) ) {
usbSetInterrupt3 ( ( void * ) & report , sizeof ( report ) ) ;
}
}
2011-02-03 04:26:44 +00:00
2011-02-10 06:51:30 +00:00
/*------------------------------------------------------------------*
* Request from host *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2011-02-07 05:59:07 +00:00
static struct {
uint16_t len ;
enum {
NONE ,
SET_LED
} kind ;
} last_req ;
2011-02-03 04:26:44 +00:00
usbMsgLen_t usbFunctionSetup ( uchar data [ 8 ] )
{
usbRequest_t * rq = ( void * ) data ;
if ( ( rq - > bmRequestType & USBRQ_TYPE_MASK ) = = USBRQ_TYPE_CLASS ) { /* class request type */
if ( rq - > bRequest = = USBRQ_HID_GET_REPORT ) {
2011-09-17 13:39:50 +00:00
debug ( " GET_REPORT: " ) ;
2011-02-03 04:26:44 +00:00
/* we only have one report type, so don't look at wValue */
2012-10-09 07:50:14 +00:00
usbMsgPtr = ( void * ) keyboard_report ;
return sizeof ( * keyboard_report ) ;
2011-02-03 04:26:44 +00:00
} else if ( rq - > bRequest = = USBRQ_HID_GET_IDLE ) {
2011-09-17 13:39:50 +00:00
debug ( " GET_IDLE: " ) ;
//debug_hex(vusb_idle_rate);
usbMsgPtr = & vusb_idle_rate ;
2011-02-03 04:26:44 +00:00
return 1 ;
} else if ( rq - > bRequest = = USBRQ_HID_SET_IDLE ) {
2011-09-17 13:39:50 +00:00
vusb_idle_rate = rq - > wValue . bytes [ 1 ] ;
debug ( " SET_IDLE: " ) ;
debug_hex ( vusb_idle_rate ) ;
2011-02-07 05:59:07 +00:00
} else if ( rq - > bRequest = = USBRQ_HID_SET_REPORT ) {
2011-09-17 13:39:50 +00:00
debug ( " SET_REPORT: " ) ;
// Report Type: 0x02(Out)/ReportID: 0x00(none) && Interface: 0(keyboard)
2011-02-07 05:59:07 +00:00
if ( rq - > wValue . word = = 0x0200 & & rq - > wIndex . word = = 0 ) {
2011-09-17 13:39:50 +00:00
debug ( " SET_LED: " ) ;
2011-02-07 05:59:07 +00:00
last_req . kind = SET_LED ;
last_req . len = rq - > wLength . word ;
}
return USB_NO_MSG ; // to get data in usbFunctionWrite
2011-09-17 13:39:50 +00:00
} else {
debug ( " UNKNOWN: " ) ;
2011-02-03 04:26:44 +00:00
}
} else {
2011-09-17 13:39:50 +00:00
debug ( " VENDOR: " ) ;
2011-02-03 04:26:44 +00:00
/* no vendor specific requests implemented */
}
2011-09-17 13:39:50 +00:00
debug ( " \n " ) ;
2011-02-03 04:26:44 +00:00
return 0 ; /* default for not implemented requests: return no data back to host */
}
2011-02-07 05:59:07 +00:00
uchar usbFunctionWrite ( uchar * data , uchar len )
{
if ( last_req . len = = 0 ) {
return - 1 ;
}
switch ( last_req . kind ) {
case SET_LED :
2011-09-17 13:39:50 +00:00
debug ( " SET_LED: " ) ;
debug_hex ( data [ 0 ] ) ;
debug ( " \n " ) ;
vusb_keyboard_leds = data [ 0 ] ;
2011-02-07 05:59:07 +00:00
last_req . len = 0 ;
return 1 ;
break ;
case NONE :
default :
return - 1 ;
break ;
}
return 1 ;
}
2011-02-03 04:26:44 +00:00
2011-02-10 06:51:30 +00:00
/*------------------------------------------------------------------*
* Descriptors *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/*
* Report Descriptor for keyboard
*
* from an example in HID spec appendix
*/
2011-02-03 04:26:44 +00:00
PROGMEM uchar keyboard_hid_report [ ] = {
0x05 , 0x01 , // Usage Page (Generic Desktop),
0x09 , 0x06 , // Usage (Keyboard),
0xA1 , 0x01 , // Collection (Application),
0x75 , 0x01 , // Report Size (1),
0x95 , 0x08 , // Report Count (8),
0x05 , 0x07 , // Usage Page (Key Codes),
0x19 , 0xE0 , // Usage Minimum (224),
0x29 , 0xE7 , // Usage Maximum (231),
0x15 , 0x00 , // Logical Minimum (0),
0x25 , 0x01 , // Logical Maximum (1),
0x81 , 0x02 , // Input (Data, Variable, Absolute), ;Modifier byte
0x95 , 0x01 , // Report Count (1),
0x75 , 0x08 , // Report Size (8),
0x81 , 0x03 , // Input (Constant), ;Reserved byte
0x95 , 0x05 , // Report Count (5),
0x75 , 0x01 , // Report Size (1),
0x05 , 0x08 , // Usage Page (LEDs),
0x19 , 0x01 , // Usage Minimum (1),
0x29 , 0x05 , // Usage Maximum (5),
0x91 , 0x02 , // Output (Data, Variable, Absolute), ;LED report
0x95 , 0x01 , // Report Count (1),
0x75 , 0x03 , // Report Size (3),
0x91 , 0x03 , // Output (Constant), ;LED report padding
0x95 , 0x06 , // Report Count (6),
0x75 , 0x08 , // Report Size (8),
0x15 , 0x00 , // Logical Minimum (0),
0x25 , 0xFF , // Logical Maximum(255),
0x05 , 0x07 , // Usage Page (Key Codes),
0x19 , 0x00 , // Usage Minimum (0),
0x29 , 0xFF , // Usage Maximum (255),
0x81 , 0x00 , // Input (Data, Array),
0xc0 // End Collection
} ;
2011-02-10 06:51:30 +00:00
/*
* Report Descriptor for mouse
*
* Mouse Protocol 1 , HID 1.11 spec , Appendix B , page 59 - 60 , with wheel extension
* http : //www.microchip.com/forums/tm.aspx?high=&m=391435&mpage=1#391521
* http : //www.keil.com/forum/15671/
* http : //www.microsoft.com/whdc/device/input/wheel.mspx
*/
2011-02-03 04:26:44 +00:00
PROGMEM uchar mouse_hid_report [ ] = {
2011-05-21 01:28:57 +00:00
/* mouse */
2011-05-31 12:17:56 +00:00
0x05 , 0x01 , // USAGE_PAGE (Generic Desktop)
0x09 , 0x02 , // USAGE (Mouse)
0xa1 , 0x01 , // COLLECTION (Application)
0x85 , REPORT_ID_MOUSE , // REPORT_ID (1)
0x09 , 0x01 , // USAGE (Pointer)
0xa1 , 0x00 , // COLLECTION (Physical)
// ---------------------------- Buttons
0x05 , 0x09 , // USAGE_PAGE (Button)
0x19 , 0x01 , // USAGE_MINIMUM (Button 1)
0x29 , 0x05 , // USAGE_MAXIMUM (Button 5)
0x15 , 0x00 , // LOGICAL_MINIMUM (0)
0x25 , 0x01 , // LOGICAL_MAXIMUM (1)
0x75 , 0x01 , // REPORT_SIZE (1)
0x95 , 0x05 , // REPORT_COUNT (5)
0x81 , 0x02 , // INPUT (Data,Var,Abs)
0x75 , 0x03 , // REPORT_SIZE (3)
0x95 , 0x01 , // REPORT_COUNT (1)
0x81 , 0x03 , // INPUT (Cnst,Var,Abs)
// ---------------------------- X,Y position
0x05 , 0x01 , // USAGE_PAGE (Generic Desktop)
0x09 , 0x30 , // USAGE (X)
0x09 , 0x31 , // USAGE (Y)
0x15 , 0x81 , // LOGICAL_MINIMUM (-127)
0x25 , 0x7f , // LOGICAL_MAXIMUM (127)
0x75 , 0x08 , // REPORT_SIZE (8)
0x95 , 0x02 , // REPORT_COUNT (2)
0x81 , 0x06 , // INPUT (Data,Var,Rel)
// ---------------------------- Vertical wheel
0x09 , 0x38 , // USAGE (Wheel)
0x15 , 0x81 , // LOGICAL_MINIMUM (-127)
0x25 , 0x7f , // LOGICAL_MAXIMUM (127)
0x35 , 0x00 , // PHYSICAL_MINIMUM (0) - reset physical
0x45 , 0x00 , // PHYSICAL_MAXIMUM (0)
0x75 , 0x08 , // REPORT_SIZE (8)
0x95 , 0x01 , // REPORT_COUNT (1)
0x81 , 0x06 , // INPUT (Data,Var,Rel)
// ---------------------------- Horizontal wheel
0x05 , 0x0c , // USAGE_PAGE (Consumer Devices)
0x0a , 0x38 , 0x02 , // USAGE (AC Pan)
0x15 , 0x81 , // LOGICAL_MINIMUM (-127)
0x25 , 0x7f , // LOGICAL_MAXIMUM (127)
0x75 , 0x08 , // REPORT_SIZE (8)
0x95 , 0x01 , // REPORT_COUNT (1)
0x81 , 0x06 , // INPUT (Data,Var,Rel)
0xc0 , // END_COLLECTION
0xc0 , // END_COLLECTION
/* system control */
2011-05-21 01:28:57 +00:00
0x05 , 0x01 , // USAGE_PAGE (Generic Desktop)
0x09 , 0x80 , // USAGE (System Control)
0xa1 , 0x01 , // COLLECTION (Application)
2011-05-31 12:17:56 +00:00
0x85 , REPORT_ID_SYSTEM , // REPORT_ID (2)
0x15 , 0x01 , // LOGICAL_MINIMUM (0x1)
0x25 , 0xb7 , // LOGICAL_MAXIMUM (0xb7)
0x19 , 0x01 , // USAGE_MINIMUM (0x1)
0x29 , 0xb7 , // USAGE_MAXIMUM (0xb7)
0x75 , 0x10 , // REPORT_SIZE (16)
0x95 , 0x01 , // REPORT_COUNT (1)
0x81 , 0x00 , // INPUT (Data,Array,Abs)
2011-05-21 01:28:57 +00:00
0xc0 , // END_COLLECTION
2011-05-31 12:17:56 +00:00
/* consumer */
2011-05-21 01:28:57 +00:00
0x05 , 0x0c , // USAGE_PAGE (Consumer Devices)
0x09 , 0x01 , // USAGE (Consumer Control)
0xa1 , 0x01 , // COLLECTION (Application)
2011-05-31 12:17:56 +00:00
0x85 , REPORT_ID_CONSUMER , // REPORT_ID (3)
0x15 , 0x01 , // LOGICAL_MINIMUM (0x1)
0x26 , 0x9c , 0x02 , // LOGICAL_MAXIMUM (0x29c)
0x19 , 0x01 , // USAGE_MINIMUM (0x1)
0x2a , 0x9c , 0x02 , // USAGE_MAXIMUM (0x29c)
0x75 , 0x10 , // REPORT_SIZE (16)
2011-05-21 01:28:57 +00:00
0x95 , 0x01 , // REPORT_COUNT (1)
2011-05-31 12:17:56 +00:00
0x81 , 0x00 , // INPUT (Data,Array,Abs)
2011-05-21 01:28:57 +00:00
0xc0 , // END_COLLECTION
2011-02-03 04:26:44 +00:00
} ;
2011-02-10 06:51:30 +00:00
/*
* Descriptor for compite device : Keyboard + Mouse
*
* contains : device , interface , HID and endpoint descriptors
*/
2011-02-03 04:26:44 +00:00
# if USB_CFG_DESCR_PROPS_CONFIGURATION
PROGMEM char usbDescriptorConfiguration [ ] = { /* USB configuration descriptor */
9 , /* sizeof(usbDescriptorConfiguration): length of descriptor in bytes */
USBDESCR_CONFIG , /* descriptor type */
9 + ( 9 + 9 + 7 ) + ( 9 + 9 + 7 ) , 0 ,
//18 + 7 * USB_CFG_HAVE_INTRIN_ENDPOINT + 7 * USB_CFG_HAVE_INTRIN_ENDPOINT3 + 9, 0,
/* total length of data returned (including inlined descriptors) */
2 , /* number of interfaces in this configuration */
1 , /* index of this configuration */
0 , /* configuration name string index */
# if USB_CFG_IS_SELF_POWERED
( 1 < < 7 ) | USBATTR_SELFPOWER , /* attributes */
# else
( 1 < < 7 ) , /* attributes */
# endif
USB_CFG_MAX_BUS_POWER / 2 , /* max USB current in 2mA units */
/*
* Keyboard interface
*/
/* Interface descriptor */
9 , /* sizeof(usbDescrInterface): length of descriptor in bytes */
USBDESCR_INTERFACE , /* descriptor type */
0 , /* index of this interface */
0 , /* alternate setting for this interface */
USB_CFG_HAVE_INTRIN_ENDPOINT , /* endpoints excl 0: number of endpoint descriptors to follow */
USB_CFG_INTERFACE_CLASS ,
USB_CFG_INTERFACE_SUBCLASS ,
USB_CFG_INTERFACE_PROTOCOL ,
0 , /* string index for interface */
/* HID descriptor */
9 , /* sizeof(usbDescrHID): length of descriptor in bytes */
USBDESCR_HID , /* descriptor type: HID */
0x01 , 0x01 , /* BCD representation of HID version */
0x00 , /* target country code */
0x01 , /* number of HID Report (or other HID class) Descriptor infos to follow */
0x22 , /* descriptor type: report */
sizeof ( keyboard_hid_report ) , 0 , /* total length of report descriptor */
/* Endpoint descriptor */
# if USB_CFG_HAVE_INTRIN_ENDPOINT /* endpoint descriptor for endpoint 1 */
7 , /* sizeof(usbDescrEndpoint) */
USBDESCR_ENDPOINT , /* descriptor type = endpoint */
( char ) 0x81 , /* IN endpoint number 1 */
0x03 , /* attrib: Interrupt endpoint */
8 , 0 , /* maximum packet size */
USB_CFG_INTR_POLL_INTERVAL , /* in ms */
# endif
/*
* Mouse interface
*/
/* Interface descriptor */
9 , /* sizeof(usbDescrInterface): length of descriptor in bytes */
USBDESCR_INTERFACE , /* descriptor type */
1 , /* index of this interface */
0 , /* alternate setting for this interface */
USB_CFG_HAVE_INTRIN_ENDPOINT3 , /* endpoints excl 0: number of endpoint descriptors to follow */
0x03 , /* CLASS: HID */
0 , /* SUBCLASS: none */
0 , /* PROTOCOL: none */
0 , /* string index for interface */
/* HID descriptor */
9 , /* sizeof(usbDescrHID): length of descriptor in bytes */
USBDESCR_HID , /* descriptor type: HID */
0x01 , 0x01 , /* BCD representation of HID version */
0x00 , /* target country code */
0x01 , /* number of HID Report (or other HID class) Descriptor infos to follow */
0x22 , /* descriptor type: report */
sizeof ( mouse_hid_report ) , 0 , /* total length of report descriptor */
# if USB_CFG_HAVE_INTRIN_ENDPOINT3 /* endpoint descriptor for endpoint 3 */
/* Endpoint descriptor */
7 , /* sizeof(usbDescrEndpoint) */
USBDESCR_ENDPOINT , /* descriptor type = endpoint */
( char ) ( 0x80 | USB_CFG_EP3_NUMBER ) , /* IN endpoint number 3 */
0x03 , /* attrib: Interrupt endpoint */
8 , 0 , /* maximum packet size */
USB_CFG_INTR_POLL_INTERVAL , /* in ms */
# endif
} ;
# endif
2011-02-10 06:51:30 +00:00
2011-02-03 04:26:44 +00:00
USB_PUBLIC usbMsgLen_t usbFunctionDescriptor ( struct usbRequest * rq )
{
usbMsgLen_t len = 0 ;
2011-09-17 13:39:50 +00:00
/*
2011-02-10 06:51:30 +00:00
debug ( " usbFunctionDescriptor: " ) ;
debug_hex ( rq - > bmRequestType ) ; debug ( " " ) ;
debug_hex ( rq - > bRequest ) ; debug ( " " ) ;
debug_hex16 ( rq - > wValue . word ) ; debug ( " " ) ;
debug_hex16 ( rq - > wIndex . word ) ; debug ( " " ) ;
debug_hex16 ( rq - > wLength . word ) ; debug ( " \n " ) ;
2011-09-17 13:39:50 +00:00
*/
2011-02-03 04:26:44 +00:00
switch ( rq - > wValue . bytes [ 1 ] ) {
# if USB_CFG_DESCR_PROPS_CONFIGURATION
case USBDESCR_CONFIG :
usbMsgPtr = ( unsigned char * ) usbDescriptorConfiguration ;
len = sizeof ( usbDescriptorConfiguration ) ;
break ;
# endif
case USBDESCR_HID :
2011-09-17 13:39:50 +00:00
switch ( rq - > wValue . bytes [ 0 ] ) {
case 0 :
usbMsgPtr = ( unsigned char * ) ( usbDescriptorConfiguration + 9 + 9 ) ;
len = 9 ;
break ;
case 1 :
usbMsgPtr = ( unsigned char * ) ( usbDescriptorConfiguration + 9 + ( 9 + 9 + 7 ) + 9 ) ;
len = 9 ;
break ;
}
2011-02-03 04:26:44 +00:00
break ;
case USBDESCR_HID_REPORT :
/* interface index */
switch ( rq - > wIndex . word ) {
case 0 :
usbMsgPtr = keyboard_hid_report ;
len = sizeof ( keyboard_hid_report ) ;
break ;
case 1 :
usbMsgPtr = mouse_hid_report ;
len = sizeof ( mouse_hid_report ) ;
break ;
}
break ;
}
2011-09-17 13:39:50 +00:00
//debug("desc len: "); debug_hex(len); debug("\n");
2011-02-03 04:26:44 +00:00
return len ;
}