/*------------------------------------------------------------------------*/
/* usblMscCopySmp.c - MatrixQuestUSB/lite MSC Direct copy sample program. */
/*                                                                        */
/* Copyright 2011 TEPCO UQUEST, LTD.                                      */
/*------------------------------------------------------------------------*/

/* $Id: usblMscCopySmp.c,v 1.4 2011/06/17 07:25:20 sasaki Exp $: */

/*
HISTORY
-------
1.1.0a 2011/04/26,ssa create.
*/

/*----- defines -----*/

#define USBL_TASK_PRI   (5)               /* 管理タスクの優先順位         */
#define K_OK            (0)               /* 正常時の戻り値               */
#define K_ERROR         (-1)              /* エラー時の戻り値             */
#define NULL     (void*)(0)               /* NULLポインタ                 */
#define printf   k_printf                 /* k_printf()を使用             */

#define BUFF_SIZE       (4096)            /* コピーする単位:4kbytes       */
#define SECTOR_SIZE     (512)             /* セクタサイズ(固定):512bytes  */
#define COPY_SECTOR_NUM (0x40000)         /* コピーするセクタ数           */

/*----- forward decralations -----*/

int usblMscInsert( void *pDevice );       /* デバイス接続時のコールバック */
int usblMscRemove( void *pDevice );       /* デバイス切断時のコールバック */
int usblMscCopy(void);                    /* コピー処理のメイン関数       */

int usblDeviceManage[2];                  /* 2つのUSBメモリをサポート     */
int usblDeviceCount=0;                    /* MSCデバイスの数を保持        */
int usblMscCopyBuf[(BUFF_SIZE/4)];        /* バッファは32bit境界に配置    */
char * pUsblMscCopyBuf=(char *)usblMscCopyBuf; /* ポインタで保持する      */

/*----- externs -----*/

extern int k_printf( const char *fmt, ... );   /* ドライバ提供の printf() */



/*************************************************************************
 user_main - ユーザ起動ルーチン OS起動時に実行されます。

 解説
    戻り値を０にするとデモプログラムが起動します。
    戻り値を０以外にするとshellが使用できます。

*/

int user_main() 
{
#if 0
    return (0); /* usblMscInitを起動します */
#else
    return (1); /* shellを起動します */
#endif
}

/*************************************************************************
 usblMscInit - USBホストドライバの初期化

 解説
    呼び出す関数はマスストレージクラスドライバの初期化関数です。
    内部でUSBホストドライバとハブクラスドライバの初期化を行います。
*/
int usblMscInit(void) {
    int result;

    /* マスストレージクラスドライバの初期化を行います。  *
     * 管理タスクの優先順位と接続時、切断時に実行される  *
     * コールバック関数を引数で指定します。              */

    result = usblBlkDrv(USBL_TASK_PRI,usblMscInsert,usblMscRemove);
        if ( result != K_OK ) {
            return (K_ERROR);
        }

    usblMscCopy(); /* コピー開始 */

    return (K_OK);
}

/*************************************************************************
 usblMscCopy - 

 解説
    マスストレージデバイスのコピーを行います。
    usblMscInsert()で最初に登録されたデバイスをマスターとして
    次に接続されたデバイスにコピーします。
    コピーする単位をBUFF_SIZEで指定し、セクタサイズは512バイト固定です。
    BUFFサイズは小さすぎるとUSBメモリによってはエラーになる可能性があります。
    転送するセクタ数をCOPY_SECTOR_NUM（デフォルト0x40000）で指定します。
    デフォルトの全転送量は読出し128M 書込み128M 合計256M です。
*/
int usblMscCopy(void) {
    int result;
    int SectorNumber;
    int SectorCount=BUFF_SIZE/SECTOR_SIZE; /* 8kbytes/512 = 16 */

    printf("Waiting USB memory to read ...");
    while( usblDeviceCount == 0 );
    printf(" ...done.\n");

    printf("Waiting USB memory to write ...");
    while( usblDeviceCount == 1 );
    printf("...done.\n");

    printf("Start Copy 0x%x ==> 0x%x \n",
                usblDeviceManage[0],usblDeviceManage[1]);
    for ( SectorNumber=0 ; SectorNumber<COPY_SECTOR_NUM ; SectorNumber+=SectorCount){
        
        result = usblBlkRd (usblDeviceManage[0],SectorNumber,SectorCount,pUsblMscCopyBuf);
        if ( result != K_OK ) {
            printf("ERROR usblBlkRd():SectorNumber = 0x%x\n",SectorNumber);
            return (K_ERROR);
        }

        result = usblBlkWrt(usblDeviceManage[1],SectorNumber,SectorCount,pUsblMscCopyBuf);
        if ( result != K_OK ) {
            printf("ERROR usblBlkWrt():SectorNumber = 0x%x\n",SectorNumber);
            return (K_ERROR);
        }
    }
    printf("Copy done. SectorNumber = 0x%x\n",SectorNumber);

    return (SectorNumber);

}

/*************************************************************************
 usblMscInsert - 接続時コールバック関数

 解説
    マスストレージクラウスのデバイスが接続されるとドライバが実行します。
    デバイスをドライバに登録して、その情報を保持するようにします。
 引数
    デバイス情報へのポインタです。
    デバイス情報の仕様は今回非公開となっています。
*/
int usblMscInsert( void *pDevice )
{
    if ( usblDeviceCount < 2 ){
        usblDeviceManage[usblDeviceCount] = usblBlkDevCreate( pDevice,0,0,0);
        if (usblDeviceManage == NULL ) {
            printf("create blkDev error\n");
            return K_ERROR;
        }
        printf("Insert(%d:0x%x)\n",usblDeviceCount,usblDeviceManage[usblDeviceCount]);
        usblDeviceCount++;
    }else {
        printf("COPY already started.(%d)\n",usblDeviceCount);
    }
    return K_OK;
}

/*************************************************************************
 usblMscRemove - 

 解説
    マスストレージクラウスのデバイスが切断されるとドライバが実行します。
    サンプルではシリアルコンソールにメッセージを出力します。
    本来は引数を元に接続時に生成したデバイスを特定してリソース解放を行いますが
    今回は非対応です。
  引数
    デバイス情報へのポインタです。
    デバイス情報の仕様は今回非公開となっています。
*/
int usblMscRemove( void *pDevice )
{

    printf("Remove.\n");

    return K_OK;
}
