1 /*---------------------------------------------------------------------------*
2   Project:  WiiConnect24
3   File:     Download.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: Download.c,v $
14   Revision 1.2  2007/11/30 08:49:07  adachi_hiroaki
15   Changed the priority that is set
16 
17   Revision 1.1  2007/06/07 06:06:39  adachi_hiroaki
18   Added a demo of the download feature.
19 
20 
21  *---------------------------------------------------------------------------*/
22 
23 /*---------------------------------------------------------------------------*
24 
25  *---------------------------------------------------------------------------*/
26 
27 #include <string.h>
28 #include <revolution/os.h>
29 #include <revolution/mem.h>
30 #include <revolution/nand.h>
31 #include <revolution/net.h>
32 #include <revolution/vf.h>
33 #include <revolution/nwc24.h>
34 #include <revolution/nwc24/NWC24Dl.h>
35 
36 /*---------------------------------------------------------------------------*
37     Macros
38  *---------------------------------------------------------------------------*/
39 
40 #define VERIFY_NWC24ERR(err, expected)      ASSERTMSG( err == expected, "unexpected error code: %d", err )
41 
42 #define URL             "http://nintendo/file.bin"
43 
44 #define DRIVE           "C"
45 
46 /* Force simulation of the initial run (it is best to initialize the task list with nwc24init.elf)*/
47 //#define SIMULATE_FIRSTRUN
48 
49 /* Do not use a signature*/
50 #define NOSIGN
51 
52 /* Use the public key prepared by the application*/
53 //#define USE_MYPUBLICKEY
54 
55 BOOL DownloadTaskMain( void );
56 
57 /*---------------------------------------------------------------------------*
58     Static Data
59  *---------------------------------------------------------------------------*/
60 
61 /* The application's public key is specified here. It is easiest to use makeo*/
62 static u8 publicKey[] =
63 {
64     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
65     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
66     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
67     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
68     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
69     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
70     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
71     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
72     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
73     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
74     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
75     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
77     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
78     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
79     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
80     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
81     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
82     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
83     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
84     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
85     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
86     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
87     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
88     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
89     0x00, 0x00, 0x00, 0x00, 0x00, 0x00
90 };
91 
92 /*---------------------------------------------------------------------------*
93     Forward references to local functions
94  *---------------------------------------------------------------------------*/
95 static void SetProperty( NWC24DlTask* task );
96 static NWC24Err UpdateTask( NWC24DlTask* task );
97 static BOOL CheckVf( NWC24DlTask* task, NWC24Err* nwc24Err, VFErr* vfErr );
98 
main()99 int main()
100 {
101     OSReport("*******************************************************\n");
102     OSReport("    WiiConnect24 download sample\n");
103     OSReport("*******************************************************\n");
104     VFInit();
105     if (DownloadTaskMain())
106     {
107         OSReport("==== Waiting... ====\n");
108         OSSleepSeconds(60*5);
109 
110         (void) DownloadTaskMain();
111     }
112     else
113     {
114         OSReport("NG\n");
115     }
116     OSHalt("Finished.\n");
117     return 0;
118 }
119 
DownloadTaskMain(void)120 BOOL DownloadTaskMain( void )
121 {
122     static u32  libWorkMem[NWC24_WORK_MEM_SIZE/sizeof(u32)] ATTRIBUTE_ALIGN(32);
123 
124     NWC24Err    err     = NWC24_OK;
125     NWC24Err    err2    = NWC24_OK;
126     VFErr       vfErr   = VF_ERR_SUCCESS;
127     NWC24DlTask dlTask;
128 
129     /*
130        Ease the restrictions on the parameters for the sake of debugging.
131        (Incorporating this into products is prohibited)
132      */
133     NWC24EnableDlLaxParameterChecking(TRUE);
134 
135     /*
136        Reduce the scheduler interval to make the downloads happen earlier
137        (Incorporating this into products is prohibited)
138      */
139     (void) NWC24SetScheduleSpan(10, 1);
140 
141     err = NWC24OpenLib(&libWorkMem);
142     if (err < NWC24_OK)
143     {
144         return FALSE;
145     }
146 
147     /* Update the task*/
148     err = UpdateTask(&dlTask);
149 
150     if (err < NWC24_OK)
151     {
152         goto close;
153     }
154 
155     /* Display the task's content to the console*/
156     (void) NWC24DumpDlTask(&dlTask);
157 
158     /* Check that the content was downloaded*/
159     if (CheckVf(&dlTask, &err, &vfErr))
160     {
161         OSReport("a new content was found.\n");
162     }
163 
164 
165 close:
166     err2 = NWC24CloseLib();
167     return err == NWC24_OK;
168 }
169 
UpdateTask(NWC24DlTask * task)170 static NWC24Err UpdateTask( NWC24DlTask* task )
171 {
172     NWC24Err    err;
173     u16         myId    = 0;
174 
175     /*
176        Get the tasks that have already been registered. Register again if it failed.
177 
178        NOTE: This function cannot be used if one application has registering two or more tasks.
179 
180           The application must record each task ID and get them with NWC24GetDlTask().
181 
182      */
183 #ifndef SIMULATE_FIRSTRUN
184     err = NWC24GetDlTaskMine( task );
185 #else
186     err = NWC24_ERR_NOT_FOUND;
187 #endif
188     if (err == NWC24_ERR_NOT_FOUND)
189     {
190         /*
191            The task has been deleted due to initial registration, expiration, or other such reasons, so it is necessary to recreate it.
192 
193          */
194 
195         /* Create a new binary data receiving-type task*/
196         err = NWC24InitDlTask(task, NWC24_DLTYPE_OCTETSTREAM);
197         if (err < NWC24_OK)
198         {
199             return err;
200         }
201         /*
202            If the task was newly created, configure the required items.
203          */
204         SetProperty( task );
205     }
206     else if (err < NWC24_OK)
207     {
208         return err;
209     }
210 
211     /*
212        Specify the number of remaining downloads.
213        Each time a download is done, the number is decreased by one; when it reaches zero, the task is removed.
214        For this reason, it is necessary to restore the value each time the application is run in order to prevent the task from being removed.
215      */
216     err = NWC24SetDlCount( task, 50 );
217     if (err < NWC24_OK)
218     {
219         return err;
220     }
221 
222     /*
223        Register the task data in the task list
224      */
225     err = NWC24AddDlTask(task);
226     if (err < NWC24_OK)
227     {
228         return err;
229     }
230     return NWC24_OK;
231 }
232 
233 
SetProperty(NWC24DlTask * task)234 static void SetProperty( NWC24DlTask* task )
235 {
236     NWC24Err    err;
237     u32         flags = 0;
238     /* Specify the URL*/
239     err = NWC24SetDlUrl( task, URL );
240     VERIFY_NWC24ERR( err, NWC24_OK );
241 
242     /*
243        Specify the priority. Tasks will be run with priority given to those with lower values.
244        The values should be set following the guidelines.
245      */
246     err = NWC24SetDlPriority( task, 192 );
247     VERIFY_NWC24ERR( err, NWC24_OK );
248 
249     /*
250        Specify the execution interval of the download task
251        Note that task execution won't necessarily be performed in this interval
252      */
253     err = NWC24SetDlInterval( task, 1 );
254     VERIFY_NWC24ERR( err, NWC24_OK );
255 
256     /*
257        Specify the file name when storing in VF
258      */
259     err = NWC24SetDlFilename(task, "file.dat");
260     VERIFY_NWC24ERR( err, NWC24_OK );
261 
262 #ifdef USE_MYPUBLICKEY
263     err = NWC24SetDlPublicKey(task, publicKey);
264     VERIFY_NWC24ERR( err, NWC24_OK );
265 
266     flags |= NWC24_DL_FLAG_USE_MYPUBLICKEY;
267 #endif
268 
269     /*
270        Specify to download unsigned content without any further processing.
271        If parameter checking has been disabled for tasks, this cannot be used for http:// URLs.
272      */
273 #ifdef NOSIGN
274     flags |= NWC24_DL_FLAG_RAW_CONTENT;
275 #endif
276 
277     err = NWC24SetDlFlags(task, flags);
278     VERIFY_NWC24ERR( err, NWC24_OK );
279 
280 }
281 
CheckVf(NWC24DlTask * task,NWC24Err * nwc24Err,VFErr * vfErr)282 static BOOL CheckVf( NWC24DlTask* task, NWC24Err* nwc24Err, VFErr* vfErr )
283 {
284     VFFile*     vfFile = NULL;
285     BOOL        create = TRUE;
286     BOOL        result = FALSE;
287     char        bufVfName[NAND_MAX_PATH];
288     char        bufVfContentName[VF_PATH_BUF_SIZE];
289 
290     /* Load the content that was obtained using the VF library*/
291 
292     /* Get the VFF file name*/
293     *nwc24Err = NWC24GetDlVfName(task, bufVfName, sizeof(bufVfName));
294     VERIFY_NWC24ERR( *nwc24Err, NWC24_OK );
295 
296     /* Get the file name of the content that was saved within VFF*/
297     *nwc24Err = NWC24GetDlFilename(task, bufVfContentName, sizeof(bufVfContentName));
298     VERIFY_NWC24ERR( *nwc24Err, NWC24_OK );
299 
300     OSReport("VF archive = %s\n", bufVfName);
301 
302     /* Mount */
303     *vfErr = VFMountDriveNANDFlash( DRIVE, bufVfName );
304     if (*vfErr == VF_ERR_SUCCESS)
305     {
306         vfFile = VFOpenFile(bufVfContentName, "r", 0);
307         if ( vfFile )
308         {
309             /* Load the content that was downloaded here*/
310             {
311                 s32 length = 0;
312                 length = VFGetFileSizeByFd( vfFile );
313                 OSReport("filename = %s, size = %d\n", bufVfContentName, length);
314 
315                /*
316                   In order to check whether the content is new or not, you must embed data such as the sequence number and the creation date within the content, and when checking the received content, make the determination by comparing it with the previously-received information.
317 
318 
319                 */
320             }
321             (void)VFCloseFile( vfFile );
322 
323             /* If the later file is not required, delete it.*/
324             *vfErr = VFDeleteFile(bufVfContentName);
325             result = TRUE;
326             create = FALSE;
327         }
328         else
329         {
330             result = FALSE;
331             /* Find out the reason that the file failed to open*/
332             *vfErr = VFGetLastError();
333             if (*vfErr == VF_ERR_ENOENT)
334             {
335                 /* The file simple doesn't exist. Recreating VFF is not necessary*/
336                 create = FALSE;
337             }
338             else
339             {
340                 /* There is a chance that the VFF file is corrupted. Recreate it just in case*/
341                 create = TRUE;
342             }
343         }
344         (void)VFUnmountDrive( DRIVE );
345     }
346     else
347     {
348         result = FALSE;
349         create = TRUE;
350     }
351 
352     /* Processing if recreating the VFF file is required*/
353     if (create)
354     {
355         /* If recreating, delete it first*/
356         (void)NANDDelete(bufVfName);
357 
358         /* Before creating VFF, check it with NANDCheck()*/
359 
360         /*
361            Prepare a 500 KB VF archive as the destination for storing the download file
362            Files that exceed this size will not be downloaded
363          */
364         *nwc24Err = NWC24CreateDlVf(task, 500*1024);
365 
366         /* If creation failed, handle it in the same way as you would if save data creation failed*/
367     }
368     return result;
369 }
370 
371 #if 0
372 static void CheckErrors( NWC24DlTask* task )
373 {
374     NWC24Err    err;
375     int         globalErr = 0, count = 0;
376 
377     /* Get the error that occurred when the task was running*/
378     err = NWC24GetDlError( task, &globalErr, &count );
379     VERIFY_NWC24ERR( err, NWC24_OK );
380 
381     if (count > 0 && globalErr != 0)
382     {
383         /* No guidelines have been prepared that relate to the handling of error codes*/
384         OSReport("error %d\n", globalErr);
385 
386         /* Clear the error information that was stored in the task*/
387         (void) NWC24ClearDlError( task );
388     }
389 }
390 #endif
391 
392 /*---------------------------------------------------------------------------*/
393 
394 /*---------------------------------------------------------------------------*/
395