1 // sketch_11_03_host_keyboard
3 // This sketch is based on the LCDlbd example sketch from the USB_Host_Shield library
10 /* keyboard data taken from configuration descriptor */
14 #define EP_MAXPKTSIZE 8
17 //******************************************************************************
18 // macros to identify special charaters(other than Digits and Alphabets)
19 //******************************************************************************
24 #define PERCENT (0x22)
28 #define OPENBKT (0x26)
29 #define CLOSEBKT (0x27)
33 #define BACKSPACE (0x2A)
38 #define SQBKTOPEN (0x2F)
39 #define SQBKTCLOSE (0x30)
40 #define BACKSLASH (0x31)
41 #define SEMICOLON (0x33)
42 #define INVCOMMA (0x34)
46 #define FRONTSLASH (0x38)
49 /* Modifier masks. One for both modifiers */
56 #define CAPSLOCK (0x39)
57 #define NUMLOCK (0x53)
58 #define SCROLLLOCK (0x47)
59 /* Sticky keys output report bitmasks */
60 #define bmNUMLOCK 0x01
61 #define bmCAPSLOCK 0x02
62 #define bmSCROLLLOCK 0x04
64 EP_RECORD ep_record[ 2 ]; //endpoint record structure for the keyboard
66 char buf[ 8 ] = { 0 }; //keyboard buffer
67 char old_buf[ 8 ] = { 0 }; //last poll
68 /* Sticky key state */
70 bool capsLock = false;
71 bool scrollLock = false;
77 // set up the LCD's number of rows and columns:
79 Serial.println("Start");
87 if( Usb.getUsbTaskState() == USB_STATE_CONFIGURING ) { //wait for addressing state
89 Usb.setUsbTaskState( USB_STATE_RUNNING );
91 if( Usb.getUsbTaskState() == USB_STATE_RUNNING ) { //poll the keyboard
95 /* Initialize keyboard */
98 byte rcode = 0; //return code
100 /* Initialize data structures */
101 ep_record[ 0 ] = *( Usb.getDevTableEntry( 0,0 )); //copy endpoint 0 parameters
102 ep_record[ 1 ].MaxPktSize = EP_MAXPKTSIZE;
103 ep_record[ 1 ].Interval = EP_POLL;
104 ep_record[ 1 ].sndToggle = bmSNDTOG0;
105 ep_record[ 1 ].rcvToggle = bmRCVTOG0;
106 Usb.setDevTableEntry( 1, ep_record ); //plug kbd.endpoint parameters to devtable
107 /* Configure device */
108 rcode = Usb.setConf( KBD_ADDR, 0, 1 );
110 Serial.print("Error attempting to configure keyboard. Return code :");
111 Serial.println( rcode, HEX );
114 /* Set boot protocol */
115 rcode = Usb.setProto( KBD_ADDR, 0, 0, 0 );
117 Serial.print("Error attempting to configure boot protocol. Return code :");
118 Serial.println( rcode, HEX );
121 Serial.println("Keyboard initialized");
125 /* Poll keyboard and print result */
126 /* buffer starts at position 2, 0 is modifier key state and 1 is irrelevant */
127 void kbd_poll( void )
130 static char leds = 0;
131 byte rcode = 0; //return code
133 rcode = Usb.inTransfer( KBD_ADDR, KBD_EP, 8, buf );
137 for( i = 2; i < 8; i++ ) {
138 if( buf[ i ] == 0 ) { //end of non-empty space
141 if( buf_compare( buf[ i ] ) == false ) { //if new key
144 capsLock =! capsLock;
145 leds = ( capsLock ) ? leds |= bmCAPSLOCK : leds &= ~bmCAPSLOCK; // set or clear bit 1 of LED report byte
149 leds = ( numLock ) ? leds |= bmNUMLOCK : leds &= ~bmNUMLOCK; // set or clear bit 0 of LED report byte
152 scrollLock =! scrollLock;
153 leds = ( scrollLock ) ? leds |= bmSCROLLLOCK : leds &= ~bmSCROLLLOCK; // set or clear bit 2 of LED report byte
161 Serial.write(HIDtoA( buf[ i ], buf[ 0 ] ));
163 }//switch( buf[ i ...
164 rcode = Usb.setReport( KBD_ADDR, 0, 1, KBD_IF, 0x02, 0, &leds );
166 Serial.print("Set report error: ");
167 Serial.println( rcode, HEX );
169 }//if( buf_compare( buf[ i ] ) == false ...
171 for( i = 2; i < 8; i++ ) { //copy new buffer to old
172 old_buf[ i ] = buf[ i ];
175 /* compare byte against bytes in old buffer */
176 bool buf_compare( byte data )
179 for( i = 2; i < 8; i++ ) {
180 if( old_buf[ i ] == data ) {
187 /* HID to ASCII converter. Takes HID keyboard scancode, returns ASCII code */
188 byte HIDtoA( byte HIDbyte, byte mod )
190 /* upper row of the keyboard, numbers and special symbols */
191 if( HIDbyte >= 0x1e && HIDbyte <= 0x27 ) {
192 if(( mod & SHIFT ) || numLock ) { //shift key pressed
194 case BANG: return( 0x21 );
195 case AT: return( 0x40 );
196 case POUND: return( 0x23 );
197 case DOLLAR: return( 0x24 );
198 case PERCENT: return( 0x25 );
199 case CAP: return( 0x5e );
200 case AND: return( 0x26 );
201 case STAR: return( 0x2a );
202 case OPENBKT: return( 0x28 );
203 case CLOSEBKT: return( 0x29 );
204 }//switch( HIDbyte...
207 if( HIDbyte == 0x27 ) { //zero
211 return( HIDbyte + 0x13 );
214 }//if( HIDbyte >= 0x1e && HIDbyte <= 0x27
216 /* number pad. Arrows are not supported */
217 if(( HIDbyte >= 0x59 && HIDbyte <= 0x61 ) && ( numLock == true )) { // numbers 1-9
218 return( HIDbyte - 0x28 );
220 if(( HIDbyte == 0x62 ) && ( numLock == true )) { //zero
224 if( HIDbyte >= 0x04 && HIDbyte <= 0x1d ) {
225 if((( capsLock == true ) && ( mod & SHIFT ) == 0 ) || (( capsLock == false ) && ( mod & SHIFT ))) { //upper case
226 return( HIDbyte + 0x3d );
229 return( HIDbyte + 0x5d );
231 }//if( HIDbyte >= 0x04 && HIDbyte <= 0x1d...
232 /* Other special symbols */
233 if( HIDbyte >= 0x2c && HIDbyte <= 0x38 ) {
235 case SPACE: return( 0x20 );
237 if(( mod & SHIFT ) == false ) {
244 if(( mod & SHIFT ) == false ) {
251 if(( mod & SHIFT ) == false ) {
258 if(( mod & SHIFT ) == false ) {
265 if(( mod & SHIFT ) == false ) {
272 if(( mod & SHIFT ) == false ) {
279 if(( mod & SHIFT ) == false ) {
286 if(( mod & SHIFT ) == false ) {
293 if(( mod & SHIFT ) == false ) {
300 if(( mod & SHIFT ) == false ) {
307 if(( mod & SHIFT ) == false ) {
316 }//if( HIDbye >= 0x2d && HIDbyte <= 0x38..