1 /*---------------------------------------------------------------------------*
2   Project:    WPAD demo program
3   File:       sync.c
4   Programmer: Eugene Kwon
5 
6   Copyright (C) 2005-2006 Nintendo.  All rights reserved.
7 
8   These coded instructions, statements, and computer programs contain
9   proprietary information of Nintendo of America Inc. and/or Nintendo
10   Company Ltd., and are protected by Federal copyright law.  They may
11   not be disclosed to third parties or copied or duplicated in any form,
12   in whole or in part, without the prior written consent of Nintendo.
13 
14   $Log: sync-callback.c,v $
15   Revision 1.4  08/15/2006 08:55:56  tojo
16   (none)
17 
18   Revision 1.3  06/16/2006 14:10:56  ekwon
19   Ensured that WPADProbe() is used to check channel status and to update device type.
20 
21   Revision 1.2  06/15/2006 13:50:00  tojo
22   Removed DOLPHIN.
23   Added WPAD_CLEAR_EVT_BUSY.
24 
25   Revision 1.1  06/14/2006 11:39:45  ekwon
26   Demonstrates use of the SYNC and CLEAR callbacks. Also demonstrates how to retrieve number of registered devicesl
27 
28 
29  *---------------------------------------------------------------------------*/
30 
31 #include <stdlib.h>
32 #include <string.h>
33 #include <stddef.h>
34 #include <stdarg.h>
35 #include <stdio.h>
36 #include <ctype.h>
37 
38 #include <revolution.h>
39 #include <revolution/wpad.h>
40 
41 #define DEMO_USE_MEMLIB=1 // This turns on the DEMO library's MEM heaps.
42 #include <demo.h>
43 
44 
45 #define SCREEN_WIDTH  320
46 #define SCREEN_HEIGHT 240
47 #define FONT_HEIGHT     9
48 
49 
50 /*---------------------------------------------------------------------------*
51  * Function prototypes
52  *---------------------------------------------------------------------------*/
53 
54 
55 // MEM2 memory allocation routines. The application must provide these to
56 // WPAD, so it can setup the data transfer buffer. This buffer must reside
57 // in MEM2.
58 static void *myAlloc                 (u32 size);
59 static u8    myFree                  (void *ptr);
60 
61 // The sync and clear callbacks are optional; applications can register
62 // callbacks to receive notifications for sync/clear events.
63 static void  syncCallback            (s32 result, s32 num);
64 static void  clearCallback           (s32 result);
65 
66 // internal functions
67 static void  initialize              (void);
68 static void  renderStatus            (void);
69 static void  printBuffer             (char *string, ...);
70 
71 
72 /*---------------------------------------------------------------------------*
73  * Local Data
74  *---------------------------------------------------------------------------*/
75 
76 #define BUFFER_SIZE_BYTES 128
77 static char __buffer[BUFFER_SIZE_BYTES];
78 
79 
80 /*===========================================================================*
81  *                   F U N C T I O N    D E F I N I T I O N S
82  *===========================================================================*/
83 
84 
85 /*---------------------------------------------------------------------------*
86  * Name        : main()
87  * Description :
88  * Arguments   : None.
89  * Returns     : None.
90  *---------------------------------------------------------------------------*/
91 
main(void)92 int main( void )
93 {
94 
95     s32 wpad_state;
96 
97         initialize();
98 
99         // - We must now register memory allocation/free functions
100         //   for MEM2.
101         // - WPAD requires some memory in MEM2 for data transfers
102         //   between the controller and WPAD driver stack.
103         // - Memory allocation only occurs once, at the initialization.
104         // - Memory usage is on the order of 1KB.
105         // - NOTE: We are using the MEM library allocators defined by
106         //   the DEMO library.
107         //
108         WPADRegisterAllocator(myAlloc, myFree);
109 
110         // Initialize WPAD!
111         WPADInit();
112 
113         // The WPAD initialization process is asynchronous.
114         // So we should wait until it's completed.
115         do
116         {
117             wpad_state = WPADGetStatus();
118 
119         } while (WPAD_STATE_SETUP != wpad_state);
120 
121 
122         // Register our callback. The callback will be invoked when
123         // the user presses the "Sync" button on the console/dev kit.
124         WPADSetSyncDeviceCallback(syncCallback);
125 
126         // Register our callback. The callback will be invoked when
127         // the user presses AND HOLDS the "Sync" button for longer
128         // than 10 seconds or so.
129         WPADSetClearDeviceCallback(clearCallback);
130 
131 
132         while(1)
133         {
134             DEMOBeforeRender();
135             renderStatus();
136             DEMODoneRender();
137         }
138 
139 
140 } // end main()
141 
142 /*---------------------------------------------------------------------------*
143  * Name        : myAlloc()
144  * Description : Callback needed by WPAD to allocate mem from MEM2 heap
145  * Arguments   : size of block, in bytes.
146  * Returns     : pointer to allocated block.
147  *---------------------------------------------------------------------------*/
myAlloc(u32 size)148 static void *myAlloc(u32 size)
149 {
150     void *ptr;
151 
152     ptr = MEMAllocFromAllocator(&DemoAllocator2, size);
153     ASSERTMSG(ptr, "Memory allocation failed\n");
154 
155     return(ptr);
156 
157 } // myAlloc()
158 
159 /*---------------------------------------------------------------------------*
160  * Name        : myFree()
161  * Description : Callback needed by WPAD to free mem from MEM2 heap
162  * Arguments   : None.
163  * Returns     : Always 1.
164  *---------------------------------------------------------------------------*/
myFree(void * ptr)165 static u8 myFree(void *ptr)
166 {
167 
168     MEMFreeToAllocator(&DemoAllocator2, ptr);
169 
170     // we should ensure that memory is free'd properly, but oh well
171     return(1);
172 
173 } // myFree()
174 
175 /*---------------------------------------------------------------------------*
176  * Name        : syncCallback()
177  * Description :
178  * Arguments   : None.
179  * Returns     : None.
180  *---------------------------------------------------------------------------*/
syncCallback(s32 result,s32 num)181 static void syncCallback(s32 result, s32 num)
182 {
183 #pragma unused(num)
184 
185     switch (result)
186     {
187         case WPAD_SYNC_EVT_BUSY:
188             printBuffer(">> SYNC already in progress.");
189             break;
190 
191         case WPAD_SYNC_EVT_START:
192 
193             printBuffer(">> SYNC process starting...");
194 
195             // Because we registered a callback for the SYNC button-press
196             // event, we are responsible for invoking the SYNC process.
197             // If we do not register a callback, WPAD will start the process
198             // automatically.
199             if (FALSE == WPADStartSyncDevice())
200             {
201                 printBuffer(">> SYNC Request Failed!");
202             }
203             break;
204 
205         case WPAD_SYNC_EVT_DONE:
206 
207             // When complete, this callback will be invoked with the number
208             // of devices that were paired during the SYNC process.
209             printBuffer(">> SYNC complete.");
210 
211             break;
212 
213         default:
214             printBuffer(">> SYNC ERROR: 0x%08X", result);
215 
216             break;
217 
218     } // end switch
219 
220 
221 } // end syncCallback()
222 
223 
224 /*---------------------------------------------------------------------------*
225  * Name        : clearCallback()
226  * Description :
227  * Arguments   : None.
228  * Returns     : None.
229  *---------------------------------------------------------------------------*/
clearCallback(s32 result)230 static void clearCallback(s32 result)
231 {
232     switch (result)
233     {
234         case WPAD_CLEAR_EVT_BUSY:
235             printBuffer(">> CLEAR already in progress.");
236             break;
237 
238         case WPAD_CLEAR_EVT_START:
239 
240             printBuffer(">> CLEAR process starting...");
241 
242             // Again, because we have registered a callback, we are
243             // responsible for invoking the clearing process.
244             // If no callback is registered, WPAD will do this
245             // automatically.
246             WPADStartClearDevice();
247 
248             break;
249 
250         case WPAD_CLEAR_EVT_DONE:
251             printBuffer(">> All devices cleared.");
252             break;
253         default:
254             printBuffer(">> CLEAR ERROR: Unknown result 0x%08X", result);
255             break;
256 
257     } // end switch
258 
259 } // end clearCallback()
260 
261 
262 /*---------------------------------------------------------------------------*
263  * Name        : renderStatus()
264  * Description : Prints interesting data from WPADStatus.
265  * Arguments   : Pointer to current WPADStatus.
266  * Returns     : None.
267  *---------------------------------------------------------------------------*/
renderStatus(void)268 static void renderStatus(void)
269 {
270 
271     s32 i;
272     s16 y;
273 
274     u8  num_paired;
275 
276     s32 status;
277     u32 type;
278 
279 
280         // Retrieve the number of devices currently paired to
281         // to this host
282 
283         num_paired = WPADGetRegisteredDevNum();
284 
285 
286         y = FONT_HEIGHT;
287         DEMOPrintf(5, y, 0, "SYNC/CLEAR Demo");
288 
289         y += FONT_HEIGHT;
290         y += FONT_HEIGHT;
291 
292         DEMOPrintf(5, y, 0, "Connect Status");
293 
294         y += FONT_HEIGHT;
295         DEMOPrintf(5, y, 0, "--------------");
296 
297 
298         for (i=0; i<WPAD_MAX_CONTROLLERS; i++)
299         {
300 
301             // Probe the channel
302             status = WPADProbe(i, &type);
303 
304             y += FONT_HEIGHT;
305             DEMOPrintf(5, y, 0, "Channel %2d:", i);
306 
307             switch(status)
308             {
309                 case WPAD_ERR_NONE:
310                     DEMOPrintf(105, y, 0, "[Connected]");
311                     break;
312                 case WPAD_ERR_NO_CONTROLLER:
313                     DEMOPrintf(105, y, 0, "[None     ]");
314                     break;
315                 case WPAD_ERR_BUSY:
316                     DEMOPrintf(105, y, 0, "[Busy     ]");
317                     break;
318                 case WPAD_ERR_TRANSFER:
319                     DEMOPrintf(105, y, 0, "[Transfer ]");
320                     break;
321                 case WPAD_ERR_INVALID:
322                     DEMOPrintf(105, y, 0, "[Invalid  ]");
323                     break;
324                 default:
325                     DEMOPrintf(105, y, 0, "[Undefined]");
326                     break;
327 
328             }// end switch
329 
330             switch(type)
331             {
332                 case WPAD_DEV_CORE:
333                     DEMOPrintf(200, y, 0, "[Core     ]");
334                     break;
335                 case WPAD_DEV_FREESTYLE:
336                     DEMOPrintf(200, y, 0, "[Nunchak  ]");
337                     break;
338                 case WPAD_DEV_UNKNOWN:
339                     DEMOPrintf(200, y, 0, "[Unknown  ]");
340                     break;
341                 default:
342                     DEMOPrintf(200, y, 0, "[Undefined]");
343                     break;
344 
345             }// end switch
346 
347         }
348 
349         y += FONT_HEIGHT;
350         y += FONT_HEIGHT;
351         DEMOPrintf(5, y, 0, ">> There are %2d devices currently <<", num_paired);
352         y += FONT_HEIGHT;
353         DEMOPrintf(5, y, 0, ">> paired to this host.           <<");
354 
355         y += FONT_HEIGHT;
356         y += FONT_HEIGHT;
357         DEMOPrintf(5, y, 0, "- Press SYNC to start pairing. Then");
358         y += FONT_HEIGHT;
359         DEMOPrintf(5, y, 0, "  press the SYNC button on the back");
360         y += FONT_HEIGHT;
361         DEMOPrintf(5, y, 0, "  of the controller.");
362 
363         y += FONT_HEIGHT;
364         DEMOPrintf(5, y, 0, "- Hold SYNC for 10 seconds to CLEAR");
365         y += FONT_HEIGHT;
366         DEMOPrintf(5, y, 0, "  all devices.");
367 
368 
369 
370         y += FONT_HEIGHT;
371         y += FONT_HEIGHT;
372 
373         DEMOPrintf(5, y,  0, __buffer);
374 
375 } // end renderStatus()
376 
printBuffer(char * string,...)377 static void printBuffer(char *string, ...)
378 {
379 
380     va_list vlist;
381 
382 
383         memset(__buffer, 0, BUFFER_SIZE_BYTES);
384 
385         va_start(vlist, string);
386         vsprintf((char *)__buffer, string, vlist);
387         va_end(vlist);
388 
389 
390 } // clear and dump string to buffer
391 
392 
393 /*---------------------------------------------------------------------------*
394  * Name        : initialize()
395  * Description : Performs basic system initialization.
396  * Arguments   : None.
397  * Returns     : None.
398  *---------------------------------------------------------------------------*/
399 
initialize(void)400 static void initialize( void )
401 {
402     const GXColor DARKBLUE = { 0, 0, 40, 255 };
403 
404         OSInit();
405 
406         DEMOInit( &GXNtsc480IntDf );
407 
408         GXSetCopyClear( DARKBLUE, GX_MAX_Z24 );
409         GXCopyDisp( DEMOGetCurrentBuffer(), GX_TRUE );
410         DEMOInitCaption( DM_FT_XLU, SCREEN_WIDTH, SCREEN_HEIGHT );
411         GXSetZMode( GX_ENABLE, GX_ALWAYS, GX_ENABLE );                       // Set pixel processing mode
412         GXSetBlendMode( GX_BM_BLEND, GX_BL_ONE, GX_BL_ONE, GX_LO_CLEAR );    // Translucent mode
413 
414 
415         memset(__buffer, 0, BUFFER_SIZE_BYTES);
416 
417 } // end
418