/*---------------------------------------------------------------------------* Project: WiiConnect24 File: Download.c Copyright 2007 Nintendo. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo of America Inc. and/or Nintendo Company Ltd., and are protected by Federal copyright law. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. $Log: Download.c,v $ Revision 1.2 2007/11/30 08:49:07 adachi_hiroaki Changed the priority that is set Revision 1.1 2007/06/07 06:06:39 adachi_hiroaki Added a demo of the download feature. *---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------* *---------------------------------------------------------------------------*/ #include #include #include #include #include #include #include #include /*---------------------------------------------------------------------------* Macros *---------------------------------------------------------------------------*/ #define VERIFY_NWC24ERR(err, expected) ASSERTMSG( err == expected, "unexpected error code: %d", err ) #define URL "http://nintendo/file.bin" #define DRIVE "C" /* Force simulation of the initial run (it is best to initialize the task list with nwc24init.elf)*/ //#define SIMULATE_FIRSTRUN /* Do not use a signature*/ #define NOSIGN /* Use the public key prepared by the application*/ //#define USE_MYPUBLICKEY BOOL DownloadTaskMain( void ); /*---------------------------------------------------------------------------* Static Data *---------------------------------------------------------------------------*/ /* The application's public key is specified here. It is easiest to use makeo*/ static u8 publicKey[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /*---------------------------------------------------------------------------* Forward references to local functions *---------------------------------------------------------------------------*/ static void SetProperty( NWC24DlTask* task ); static NWC24Err UpdateTask( NWC24DlTask* task ); static BOOL CheckVf( NWC24DlTask* task, NWC24Err* nwc24Err, VFErr* vfErr ); int main() { OSReport("*******************************************************\n"); OSReport(" WiiConnect24 download sample\n"); OSReport("*******************************************************\n"); VFInit(); if (DownloadTaskMain()) { OSReport("==== Waiting... ====\n"); OSSleepSeconds(60*5); (void) DownloadTaskMain(); } else { OSReport("NG\n"); } OSHalt("Finished.\n"); return 0; } BOOL DownloadTaskMain( void ) { static u32 libWorkMem[NWC24_WORK_MEM_SIZE/sizeof(u32)] ATTRIBUTE_ALIGN(32); NWC24Err err = NWC24_OK; NWC24Err err2 = NWC24_OK; VFErr vfErr = VF_ERR_SUCCESS; NWC24DlTask dlTask; /* Ease the restrictions on the parameters for the sake of debugging. (Incorporating this into products is prohibited) */ NWC24EnableDlLaxParameterChecking(TRUE); /* Reduce the scheduler interval to make the downloads happen earlier (Incorporating this into products is prohibited) */ (void) NWC24SetScheduleSpan(10, 1); err = NWC24OpenLib(&libWorkMem); if (err < NWC24_OK) { return FALSE; } /* Update the task*/ err = UpdateTask(&dlTask); if (err < NWC24_OK) { goto close; } /* Display the task's content to the console*/ (void) NWC24DumpDlTask(&dlTask); /* Check that the content was downloaded*/ if (CheckVf(&dlTask, &err, &vfErr)) { OSReport("a new content was found.\n"); } close: err2 = NWC24CloseLib(); return err == NWC24_OK; } static NWC24Err UpdateTask( NWC24DlTask* task ) { NWC24Err err; u16 myId = 0; /* Get the tasks that have already been registered. Register again if it failed. NOTE: This function cannot be used if one application has registering two or more tasks. The application must record each task ID and get them with NWC24GetDlTask(). */ #ifndef SIMULATE_FIRSTRUN err = NWC24GetDlTaskMine( task ); #else err = NWC24_ERR_NOT_FOUND; #endif if (err == NWC24_ERR_NOT_FOUND) { /* The task has been deleted due to initial registration, expiration, or other such reasons, so it is necessary to recreate it. */ /* Create a new binary data receiving-type task*/ err = NWC24InitDlTask(task, NWC24_DLTYPE_OCTETSTREAM); if (err < NWC24_OK) { return err; } /* If the task was newly created, configure the required items. */ SetProperty( task ); } else if (err < NWC24_OK) { return err; } /* Specify the number of remaining downloads. Each time a download is done, the number is decreased by one; when it reaches zero, the task is removed. 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. */ err = NWC24SetDlCount( task, 50 ); if (err < NWC24_OK) { return err; } /* Register the task data in the task list */ err = NWC24AddDlTask(task); if (err < NWC24_OK) { return err; } return NWC24_OK; } static void SetProperty( NWC24DlTask* task ) { NWC24Err err; u32 flags = 0; /* Specify the URL*/ err = NWC24SetDlUrl( task, URL ); VERIFY_NWC24ERR( err, NWC24_OK ); /* Specify the priority. Tasks will be run with priority given to those with lower values. The values should be set following the guidelines. */ err = NWC24SetDlPriority( task, 192 ); VERIFY_NWC24ERR( err, NWC24_OK ); /* Specify the execution interval of the download task Note that task execution won't necessarily be performed in this interval */ err = NWC24SetDlInterval( task, 1 ); VERIFY_NWC24ERR( err, NWC24_OK ); /* Specify the file name when storing in VF */ err = NWC24SetDlFilename(task, "file.dat"); VERIFY_NWC24ERR( err, NWC24_OK ); #ifdef USE_MYPUBLICKEY err = NWC24SetDlPublicKey(task, publicKey); VERIFY_NWC24ERR( err, NWC24_OK ); flags |= NWC24_DL_FLAG_USE_MYPUBLICKEY; #endif /* Specify to download unsigned content without any further processing. If parameter checking has been disabled for tasks, this cannot be used for http:// URLs. */ #ifdef NOSIGN flags |= NWC24_DL_FLAG_RAW_CONTENT; #endif err = NWC24SetDlFlags(task, flags); VERIFY_NWC24ERR( err, NWC24_OK ); } static BOOL CheckVf( NWC24DlTask* task, NWC24Err* nwc24Err, VFErr* vfErr ) { VFFile* vfFile = NULL; BOOL create = TRUE; BOOL result = FALSE; char bufVfName[NAND_MAX_PATH]; char bufVfContentName[VF_PATH_BUF_SIZE]; /* Load the content that was obtained using the VF library*/ /* Get the VFF file name*/ *nwc24Err = NWC24GetDlVfName(task, bufVfName, sizeof(bufVfName)); VERIFY_NWC24ERR( *nwc24Err, NWC24_OK ); /* Get the file name of the content that was saved within VFF*/ *nwc24Err = NWC24GetDlFilename(task, bufVfContentName, sizeof(bufVfContentName)); VERIFY_NWC24ERR( *nwc24Err, NWC24_OK ); OSReport("VF archive = %s\n", bufVfName); /* Mount */ *vfErr = VFMountDriveNANDFlash( DRIVE, bufVfName ); if (*vfErr == VF_ERR_SUCCESS) { vfFile = VFOpenFile(bufVfContentName, "r", 0); if ( vfFile ) { /* Load the content that was downloaded here*/ { s32 length = 0; length = VFGetFileSizeByFd( vfFile ); OSReport("filename = %s, size = %d\n", bufVfContentName, length); /* 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. */ } (void)VFCloseFile( vfFile ); /* If the later file is not required, delete it.*/ *vfErr = VFDeleteFile(bufVfContentName); result = TRUE; create = FALSE; } else { result = FALSE; /* Find out the reason that the file failed to open*/ *vfErr = VFGetLastError(); if (*vfErr == VF_ERR_ENOENT) { /* The file simple doesn't exist. Recreating VFF is not necessary*/ create = FALSE; } else { /* There is a chance that the VFF file is corrupted. Recreate it just in case*/ create = TRUE; } } (void)VFUnmountDrive( DRIVE ); } else { result = FALSE; create = TRUE; } /* Processing if recreating the VFF file is required*/ if (create) { /* If recreating, delete it first*/ (void)NANDDelete(bufVfName); /* Before creating VFF, check it with NANDCheck()*/ /* Prepare a 500 KB VF archive as the destination for storing the download file Files that exceed this size will not be downloaded */ *nwc24Err = NWC24CreateDlVf(task, 500*1024); /* If creation failed, handle it in the same way as you would if save data creation failed*/ } return result; } #if 0 static void CheckErrors( NWC24DlTask* task ) { NWC24Err err; int globalErr = 0, count = 0; /* Get the error that occurred when the task was running*/ err = NWC24GetDlError( task, &globalErr, &count ); VERIFY_NWC24ERR( err, NWC24_OK ); if (count > 0 && globalErr != 0) { /* No guidelines have been prepared that relate to the handling of error codes*/ OSReport("error %d\n", globalErr); /* Clear the error information that was stored in the task*/ (void) NWC24ClearDlError( task ); } } #endif /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/