1 /*---------------------------------------------------------------------------*
2   Project:  Revolution Low-Level Sync USB keyboard demo
3   File:     kbdLowLevelSync.c
4 
5   Copyright 2007 Nintendo.  All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain
8   proprietary information of Nintendo of America Inc. and/or Nintendo
9   Company Ltd., and are protected by Federal copyright law.  They may
10   not be disclosed to third parties or copied or duplicated in any form,
11   in whole or in part, without the prior written consent of Nintendo.
12 
13   $Log: kbdLowLevelSync.c,v $
14   Revision 1.12.6.1  2009/10/14 10:03:27  iwai_yuma
15   Rool back into StackB.
16 
17   Revision 1.10  2007/10/08 18:44:55  henrch
18   per API change
19 
20   Revision 1.9  2007/10/03 22:48:01  henrch
21   changed to use new KBD / HID lib
22 
23   Revision 1.8  2007/07/13 23:37:18  carlmu
24   Changed from TrySetLeds to KBDSetLedsRetry.
25 
26   Revision 1.7  2007/06/21 22:46:50  carlmu
27   Updated for KBD 1.4 API (changed LED handling).
28 
29   Revision 1.6  2007/05/05 01:56:57  carlmu
30   Changes for 0.8 API
31 
32   Revision 1.5  2007/04/17 23:55:57  carlmu
33   Updated for 0.5 API.
34 
35   Revision 1.4  2007/04/10 18:34:05  carlmu
36   Changed for compatibility with 0.4 API.
37 
38   Revision 1.3  2007/04/02 19:12:17  carlmu
39   Set callback functions modified for new return value.
40 
41   Revision 1.2  2007/03/29 22:38:01  carlmu
42   Added multiple channel support.
43 
44   Revision 1.1  2007/03/28 00:18:25  carlmu
45   Initial version.
46 
47 
48   $NoKeywords: $
49  *---------------------------------------------------------------------------*/
50 
51 /*
52   Example simple keyboard application to output the low-level API HID code
53   to the console.  Uses the synchronous keyboard API.
54  */
55 
56 #include <demo.h>
57 #include <revolution/kbd.h>
58 
59 static u8 __kbd_mem[KBD_MEM_SIZE];
60 
61 
62 //-----------------------------------------------------------------------------
63 
64 #define KBD_CALL(_fn_call)                         \
65   if ((_fn_call) != KBD_SUCCESS) {                 \
66     OSReport ("KBD error: calling %s @ %s:%i\n",   \
67               #_fn_call, __FILE__, __LINE__);      \
68   }
69 
70 //-----------------------------------------------------------------------------
71 
72 static void
kbdAppAttach(KBDDevEvent * kde)73 kbdAppAttach (KBDDevEvent *kde) {
74   OSReport ("kbd app: keyboard added on channel %d\n", kde->channel);
75   // for demo purposes, enable NumLock on newly attached keyboard
76   KBDSetModState(kde->channel, KBD_MS_NUM_LOCK);
77   KBDSetLedsRetry(kde->channel, KBD_LED_NUM_LOCK);
78 }
79 
80 
81 static void
kbdAppDetach(KBDDevEvent * kde)82 kbdAppDetach (KBDDevEvent *kde) {
83   OSReport ("kbd app: keyboard removed on channel %d\n", kde->channel);
84 }
85 
86 
87 static void
kbdAppKeyEvent(KBDKeyEvent * kke)88 kbdAppKeyEvent (KBDKeyEvent *kke) {
89   if (KBD_KEY_MODE_REPEAT(kke->mode)) {
90       return;
91   }
92 
93   if (KBD_KEY_MODE_UP(kke->mode))
94     OSReport ("\t\t\thid code: 0x%02x ^ up (chan %d)\n", kke->hid, kke->channel);
95   else
96     OSReport ("hid code: 0x%02x v down (chan %d)\n", kke->hid, kke->channel);
97 
98   // check for CapsLock, NumLock, or ScrollLock (handle LEDs)
99   if (kke->hid == KBD_HID_Caps_Lock ||
100       kke->hid == KBD_HID_Keypad_Num_Lock ||
101       kke->unicode == KBK_Scroll_Lock) {
102 
103       KBDModState ms;
104       KBDLedState leds;
105 
106       // First compute the new LED state
107       KBDGetModState(kke->channel, &ms);
108 
109       leds = (KBDLedState)
110       (((ms & KBD_MS_NUM_LOCK) == KBD_MS_NUM_LOCK) * KBD_LED_NUM_LOCK |
111        ((ms & KBD_MS_CAPS_LOCK) == KBD_MS_CAPS_LOCK) * KBD_LED_CAPS_LOCK |
112        ((ms & KBD_MS_SCROLL_LOCK) == KBD_MS_SCROLL_LOCK) * KBD_LED_SCROLL_LOCK);
113 
114       KBDSetLedsRetry(kke->channel, leds);
115   }
116 }
117 
118 extern void hid_open_async(void);
119 extern void hid_close_async(void);
120 
main(void)121 int main(void) {
122   KBDKeyEvent kevent;
123   KBDChannel ch;
124   KBDEc      rc;
125 
126   DEMOInit (NULL);
127 
128   hid_open_async();
129 
130   OSReport ("\n\n");
131   OSReport ("************************************************\n");
132   OSReport ("kbdLowLevelSync Low-level Sync keyboard demo\n");
133   OSReport ("************************************************\n");
134   OSReport ("Attach a USB keyboard and press some keys.\n");
135   OSReport ("Use a GameCube controller plugged into port 1.\n");
136   OSReport ("Right Trigger: sleeps for 5 seconds (to test overflow)\n");
137   OSReport ("\n");
138 
139   KBD_CALL (KBDInit(&__kbd_mem, kbdAppAttach, kbdAppDetach, 0));
140 
141   // One of these MUST be called after calling KBDInit.
142   // It's okay to call more than one.
143   KBDInitRegionUS();
144   KBDInitRegionJP();
145   KBDInitRegionEU();
146 
147   while (1) {
148 
149     DEMOPadRead();
150 
151     if ( DEMOPadGetButtonDown(0) & PAD_TRIGGER_R ) {
152       OSSleepSeconds(5);
153     }
154 
155     // poll all keyboard channels
156     for(ch=0; ch<KBD_MAX_CHANNELS; ch++) {
157       KBDChanStatus cstat;
158 
159       // see if keyboard is connected
160       KBD_CALL(KBDGetChannelStatus (ch, &cstat));
161       if (cstat == KBD_CS_OK) {
162 
163     // call KBDGetKey until queue is empty or error
164     do {
165       rc=KBDGetKey(ch, &kevent);
166       if (rc != KBD_SUCCESS) break;
167 
168       if (kevent.hid == KBD_HID_OVERFLOW) {
169         OSReport("KBD queue overflowed!\n");
170         continue;
171       }
172       if (kevent.hid == KBD_HID_NONE) {
173         break;
174       }
175       // process event
176       kbdAppKeyEvent(&kevent);
177     } while (1);
178       }
179     }
180 
181     OSYieldThread();
182 
183   }
184 
185   hid_close_async();
186 
187   OSShutdownSystem(); // Never reached!
188 
189   return 0;
190 }
191 
192 
193