rio-1.07.orig/0042755000175000017500000000000006746050361012200 5ustar vincevincerio-1.07.orig/README0100744000175000017500000001404006746050463013056 0ustar vincevince RIO utility v1.07 - The Snowblind Alliance (c) 1999 --------------------------------------------------- Files ----- README This file CREDITS Credits for contributors to this version rio.txt Protocol information gpl.txt Copy of licence std.h standard defines binary.h defines for binary numbers from 0-255 rioioctl.h ioctl constants used for WinNT version iopl32.h low-level port i/o function declarations for OS/2 rio.h rio class header rio.cpp rio class app.cpp utility which uses rio class io.obj low-level port i/o functions for OS/2 os2.def linker def file for OS/2 playlist.txt example playlist file makefile linux makefile os2.mak IVMVAC+ v3.0 makefile for OS/2 v4 winnt.mak MSVC++ v5.0 makefile for WinNT v4 win9x.mak MSVC++ v5.0 makefile for Win9x dos.mak Borland Turbo C++ v1.01 for DOS Overview -------- 'rio' is a simple command line utility which allows you to display and manage files on your Diamond Rio portable music player. At present the Rio utility supports the Diamond Rio PMP300 with 32M internal flash memory. Additional external flash memory is now supported thanks to the work done by Guido March (march@pc40.mpier.uni-frankfurt.de). command line switches available :- -d display directory -iy initialize with check for bad blocks -in initialize without check for bad blocks -x perform operations on external flash ram -u specify file(s) to upload -g specify file to download -f specify text based playlist file which contains files to be upload -z specify file to delete -za delete all files -o specify new playlist order in quotes -p specify parallel port base IO address, default=0x378 -v enable verbose mode -di specify initialization delay -dt specify tx delay -dr specify rx delay examples... ; display directory using parallel port at 0x278 rio -p 0x278 -d ; initialize (with bad block check) and upload files rio -iy -u *.mp3 ; delete existing files and upload playlist onto external flash ram rio -za -f playlist.txt -x ; initialize, upload files in playlist and then display directory rio -d -in -f playlist.txt ; download file then delete it and finally display directory rio -d -g mp3Files/song.mp3 -z song.mp3 ; reverse playlist order and display directory, also change rx iodelay rio -o "5 4 3 2 1" -d -dr 4 Initialization -------------- Initialization should only be performed on new or corrupt cards. You can initialize with bad block checking enabled (-iy) which will test all blocks on the internal or external flash ram (which ever is selected) and note all bad blocks. This process will take some time (upto 20 minutes on slow machines). You can also initialize with bad block checking disabled (-in) which is much quicker but all blocks (even bad blocks) will be used. If you want to delete all files on the device, the (-za) option should be used instead of using the initialization options mentioned above. Building and running -------------------- Linux, GCC ---------- To build and run the application you must be logged on as root, then use 'make'. (rio utility has been built and tested using gcc compiler v2.7.2.3 under Linux v2.0.34) Windows NT v4.0, Visual C++ v5 ------------------------------ Use 'nmake /fwinnt.mak'. (rio utility has been built and tested using MS Visual C++ compiler v5 under Windows Workstation NT 4.0) Windows 95/98, Visual C++ v5 ---------------------------- Use 'nmake /fwin9x.mak'. (rio utility has been built and tested using MS Visual C++ compiler v5 under Windows 98) OS/2 v4.0, VisualAge C++ v3 ------------------------------ Use 'nmake /f os2.mak'. (rio utility has been built and tested using IBM VisualAge C++ compiler v3 under OS/2 v4.0) DOS, Borland Turbo C++ v1.01 ---------------------------- Use 'make -fdos.mak' (rio utility has been built and tested using Borland Turbo C++ v1.01 under DOS v6.22 and Windows 98). Known Bugs ---------- Because of the difference in timings between different machines it is possible that you may experience problems when downloading and displaying the directory. If you encounter this problem try one or both of the following... Try increasing one or more of the command line delay parameters (-di, -dt, -dr). Type 'rio' without any command line parameters to display the default settings. Use the utility when the device is powered on as this seems to improve IO performance. Bug Reports ----------- If you encounter any problems using this utility please send e-mail outlining the problem along with details about your Rio (memory installed, memory remaining and tracks loaded) to... sba@tessier-ashpool.cix.co.uk Licence Terms ------------- This software is released under the terms of the GPL. Please see the file gpl.txt for further information. rio-1.07.orig/app.cpp0100744000175000017500000005076006730234306013464 0ustar vincevince/////////////////////////////////////////////////////////////////////////////// // // app.cpp // // see RIO.CPP for version history // /////////////////////////////////////////////////////////////////////////////// #include #include #include #include #include #include "std.h" #include "rio.h" // output #define INFOSTR printf #define ERRORSTR INFOSTR // platform dependencies #if defined(_WINNT) // MS VC++ v5.0 for WinNT v4 #include #define SIZE_MAXPATH _MAX_PATH #define DELETEARRAY delete[] #elif defined(_WIN32) // MS VC++ v5.0 for Win9x #include #define SIZE_MAXPATH _MAX_PATH #define DELETEARRAY delete[] #elif defined(__linux__) // linux g++ #include #include #include #if defined(PATH_MAX) #define SIZE_MAXPATH PATH_MAX #else #define SIZE_MAXPATH 256 #endif #define DELETEARRAY delete[] #elif defined(__FreeBSD__) // FreeBSD g++ #include #include #define SIZE_MAXPATH PATH_MAX #define DELETEARRAY delete[] #elif defined(__bsdi__) // BSD/OS g++ #include #include #define SIZE_MAXPATH PATH_MAX #define DELETEARRAY delete[] #elif defined(__OS2__) // OS/2 VisualAge C++ v. 3 #include #elif defined(__TURBOC__) // turboc v1.01 #include #define SIZE_MAXPATH MAXPATH #define DELETEARRAY delete #else // not supported #error ! ! compiler/platform not supported ! ! #endif // default port base #if defined(__alpha) #define PORT_BASE_DEFAULT 0x3bc #else #define PORT_BASE_DEFAULT 0x378 #endif // return code #define CLEANUP_RETURN( ret ) \ { \ if ( pRio ) \ { \ delete pRio; \ pRio = NULL; \ } \ if ( pszFilePlaylistTemp ) \ { \ unlink( pszFilePlaylistTemp ); \ pszFilePlaylistTemp = NULL; \ } \ return ret; \ } /////////////////////////////////////////////////////////////////////////////// // return pointer to static string containing datetime static char* TimeStr( long lValue ) { static char szBuf[ 64 ]; struct tm* psDateTime; psDateTime = localtime( &lValue ); if ( !psDateTime ) strcpy( szBuf, "INVALID DATE/TIME" ); else { sprintf( szBuf, "%02u/%02u/%02u %02u:%02u:%02u", (UINT)psDateTime->tm_mday % 100, (UINT)psDateTime->tm_mon+1 % 100, (UINT)psDateTime->tm_year % 100, (UINT)psDateTime->tm_hour % 100, (UINT)psDateTime->tm_min % 100, (UINT)psDateTime->tm_sec % 100 ); } return szBuf; } /////////////////////////////////////////////////////////////////////////////// // return maxpath static int GetMaxPathSize( void ) { #if defined(__OS2__) ULONG ulSize; DosQuerySysInfo( QSV_MAX_PATH_LENGTH, QSV_MAX_PATH_LENGTH, &ulSize, sizeof(ulSize) ); return ulSize; #endif return SIZE_MAXPATH; } /////////////////////////////////////////////////////////////////////////////// // return file size static long GetFileSize( char* pszPathFile ) { long lReturn = 0; FILE* fpFile = fopen( pszPathFile, "rb" ); if ( fpFile ) { struct stat sStat; if ( !stat(pszPathFile, &sStat) ) lReturn = sStat.st_size; fclose( fpFile ); } return lReturn; } /////////////////////////////////////////////////////////////////////////////// // progress callback static BOOL ProgressCallback( int iPos, int iCount ) { INFOSTR( "blocks %-5hd\r", iCount-iPos ); fflush( stdout ); return TRUE; } /////////////////////////////////////////////////////////////////////////////// // compute sample frequency static UINT GetSampleFreq( UCHAR* paucProp ) { int iVersion, iFreq; UINT auiFreq[3][4] = { { 44100, 48000, 32000, 0 }, { 22050, 24000, 16000, 0 }, { 11025, 8000, 8000, 0 } }; switch( (paucProp[2] >> 3 & 0x3) ) { case 3: iVersion = 0; break; case 2: iVersion = 1; break; case 0: iVersion = 2; break; default: return 0; } iFreq = (paucProp[1] >> 2) & 0x03; return auiFreq[ iVersion ][ iFreq ]; } /////////////////////////////////////////////////////////////////////////////// // compute bit rate static int GetBitRate( UCHAR* paucProp ) { int iVersion, iLay, iPosBitrate; int aBitrate[3][3][15] = { { { 0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448 }, { 0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384 }, { 0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320 } }, { { 0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256 }, { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160 }, { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160 } }, { { 0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256 }, { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160 }, { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160 } } }; iLay = 4 - ((paucProp[2] >> 1) & 0x03); iPosBitrate = (paucProp[1] >> 4) & 0x0f; switch( (paucProp[2]>>3 & 0x03) ) { case 3: iVersion = 0; break; case 2: iVersion = 1; break; case 0: iVersion = 2; break; default: return 0; } return aBitrate[ iVersion][iLay - 1 ][ iPosBitrate ]; } /////////////////////////////////////////////////////////////////////////////// // display directory static void DisplayDirectory( CRio& cRio, BOOL bVerbose ) { CDirBlock& cDirBlock = cRio.GetDirectoryBlock(); CDirHeader& cDirHeader = cDirBlock.m_cDirHeader; INFOSTR( "\n" ); INFOSTR( " entry count: %hu\n", cDirHeader.m_usCountEntry ); INFOSTR( " total memory: %ld KB\n", ((long)cDirHeader.m_usCount32KBlockAvailable * CRIO_SIZE_32KBLOCK) / 1024 ); INFOSTR( " used memory: %ld KB\n", ((long)cDirHeader.m_usCount32KBlockUsed * CRIO_SIZE_32KBLOCK) / 1024 ); INFOSTR( " unused memory: %ld KB\n", ((long)cDirHeader.m_usCount32KBlockRemaining * CRIO_SIZE_32KBLOCK) / 1024 ); INFOSTR( "flash ram type: %s\n", cRio.GetUseExternalFlashStatus() ? "external" : "internal" ); if ( bVerbose ) { INFOSTR( "bad 32K blocks: %hu\n", cDirHeader.m_usCount32KBlockBad ); INFOSTR( " last update: %s\n", TimeStr(cDirHeader.m_lTimeLastUpdate) ); INFOSTR( " checksum1: 0x%04hx\n", cDirHeader.m_usChecksum1 ); INFOSTR( " checksum2: 0x%04hx\n", cDirHeader.m_usChecksum2 ); INFOSTR( " host version: 0x%04hx\n", cDirHeader.m_usVersion ); } UINT uiCountEntry = cDirHeader.m_usCountEntry; if ( uiCountEntry ) { CDirEntry* pDirEntry = cDirBlock.m_acDirEntry; if ( uiCountEntry > CRIO_MAX_DIRENTRY ) uiCountEntry = CRIO_MAX_DIRENTRY; // extended output if ( bVerbose ) { INFOSTR( "\n" ); INFOSTR( "No 32KPos 32KCount Mod32K Size Upload Date/Time Title\n" ); INFOSTR( "-----------------------------------------------------------------------------\n" ); for( UINT uiA=0; uiAm_usPos32KBlock, pDirEntry->m_usCount32KBlock, pDirEntry->m_usSize32KMod, pDirEntry->m_lSize, TimeStr(pDirEntry->m_lTimeUpload), pDirEntry->m_szName ); } } // normal output else { INFOSTR( "\n" ); INFOSTR( "No Size K/s SFreq Upload Date/Time Title\n" ); INFOSTR( "----------------------------------------------------------------------------\n" ); for( UINT uiA=0; uiAm_lSize, GetBitRate(pDirEntry->m_aucProperty), GetSampleFreq(pDirEntry->m_aucProperty), TimeStr(pDirEntry->m_lTimeUpload), pDirEntry->m_szName ); } } } } /////////////////////////////////////////////////////////////////////////////// // hex dump directory block static void DumpDirectory( CRio& cRio, int iPos, int iSize ) { int iA, iB; CDirBlock& cDirBlock = cRio.GetDirectoryBlock(); UCHAR* pucS = ((UCHAR*)&cDirBlock) + iPos; if ( iSize % 16 ) iSize = ((iSize / 16)+1) * 16; for( iA=0; iA<(iSize/16); ++iA, pucS+=16 ) { INFOSTR( "%08lx ", iA*16 ); for( iB=0; iB<16; ++iB ) { int iC = *(pucS+iB); INFOSTR( "%02x ", iC ); if ( (iB%8) == 7 ) INFOSTR( " " ); } for( iB=0; iB<16; ++iB ) { int iC = *(pucS+iB); INFOSTR( "%c", iC > 32 ? iC : '.' ); if ( (iB%8) == 7 ) INFOSTR( " " ); } INFOSTR( "\n" ); if ( (iA%8) == 7 ) INFOSTR( "\n" ); } } /////////////////////////////////////////////////////////////////////////////// // process playlist file static BOOL ProcessPlaylist( CRio& cRio, char* pszFile, BOOL bVerbose ) { // open playlist for read FILE* fpFile = fopen( pszFile, "r" ); if ( !fpFile ) { ERRORSTR( "unable to open '%s' for read\n", pszFile ); return FALSE; } // create buffer int iSizeMaxPath = GetMaxPathSize(); char* pszBuf = new char[ iSizeMaxPath ]; // check if device can accommodate all files in playlist CDirBlock& cDirBlock = cRio.GetDirectoryBlock(); CDirHeader& cDirHeader = cDirBlock.m_cDirHeader; long lSizeAvailable = (long)cDirHeader.m_usCount32KBlockAvailable * CRIO_SIZE_32KBLOCK; long lSizeCurrent = (long)cDirHeader.m_usCount32KBlockUsed * CRIO_SIZE_32KBLOCK; int iCountEntryCurrent = cDirHeader.m_usCountEntry; while( fgets(pszBuf, iSizeMaxPath, fpFile) ) { // strip 'new line' char int iLength = strlen( pszBuf ); pszBuf[ --iLength ] = 0; // if blank line or comment if ( !iLength || pszBuf[0] == '#' || pszBuf[0] == ';' ) continue; // get file size long lSize = GetFileSize( pszBuf ); if ( !lSize ) { ERRORSTR( "unable to open '%s' for read\n", pszBuf ); fclose( fpFile ); DELETEARRAY pszBuf; return FALSE; } // check space lSizeCurrent += lSize; if ( lSizeCurrent > lSizeAvailable ) { ERRORSTR( "entry '%s' exceed's memory capacity of device\n", pszBuf ); fclose( fpFile ); DELETEARRAY pszBuf; return FALSE; } // check enough entries ++iCountEntryCurrent; if ( iCountEntryCurrent > CRIO_MAX_DIRENTRY ) { ERRORSTR( "entry '%s' exceed's maximum directory entry count for device\n", pszBuf ); fclose( fpFile ); DELETEARRAY pszBuf; return FALSE; } } // rewind playlist rewind( fpFile ); // process entries while( fgets(pszBuf, iSizeMaxPath, fpFile) ) { // strip 'new line' char int iLength = strlen( pszBuf ); pszBuf[ --iLength ] = 0; // if blank line or comment if ( !iLength || pszBuf[0] == '#' || pszBuf[0] == ';' ) continue; // upload if ( bVerbose ) INFOSTR( "uploading %s\n", pszBuf ); if ( !cRio.TxFile(pszBuf, bVerbose ? ProgressCallback : NULL) ) { ERRORSTR( "tx file failed, %s\n", cRio.GetErrorStr() ); fclose( fpFile ); DELETEARRAY pszBuf; return FALSE; } } // cleanup fclose( fpFile ); DELETEARRAY pszBuf; return TRUE; } /////////////////////////////////////////////////////////////////////////////// // change playlist order static BOOL ChangePlaylistOrder( CRio& cRio, char* pszPlaylistOrder ) { UINT auiPosNew[ CRIO_MAX_DIRENTRY ]; UINT uiPosNew = 0; char* pszEntry; do { pszEntry = strtok( uiPosNew ? NULL : pszPlaylistOrder, " " ); if ( pszEntry ) auiPosNew[ uiPosNew++ ] = atoi( pszEntry ) - 1; } while( pszEntry && (uiPosNew < CRIO_MAX_DIRENTRY) ); if ( !cRio.SetFileOrder(auiPosNew, uiPosNew) ) { ERRORSTR( "change in playlist order failed, %s\n", cRio.GetErrorStr() ); return FALSE; } return TRUE; } /////////////////////////////////////////////////////////////////////////////// // display help static void Help( void ) { INFOSTR( "\nRio utility v%d.%02d - The Snowblind Alliance (c) 1999\n", CRIO_ID_VERSION/100, CRIO_ID_VERSION%100 ); INFOSTR( "----------------------------------------------------\n" ); INFOSTR( "command line switches available :-\n" ); INFOSTR( " -d display directory\n" ); INFOSTR( " -iy initialize with check for bad blocks\n" ); INFOSTR( " -in initialize without check for bad blocks\n" ); INFOSTR( " -x perform operations on external flash ram\n" ); INFOSTR( " -u specify file(s) to upload\n" ); INFOSTR( " -g specify file to download\n" ); INFOSTR( " -f specify text based playlist file which contains files to be upload\n" ); INFOSTR( " -z specify file to delete\n" ); INFOSTR( " -za delete all files\n" ); INFOSTR( " -o specify new playlist order in quotes\n" ); INFOSTR( " -p specify parallel port base IO address, default=0x%x\n", PORT_BASE_DEFAULT ); INFOSTR( " -v enable verbose mode\n" ); INFOSTR( " -di specify initialization delay (default is %ld)\n", CRIO_TIME_IODELAY_INIT ); INFOSTR( " -dt specify tx delay (default is %ld)\n", CRIO_TIME_IODELAY_TX ); INFOSTR( " -dr specify rx delay (default is %ld)\n", CRIO_TIME_IODELAY_RX ); INFOSTR( "\nexamples...\n" ); INFOSTR( " ; display directory using parallel port at 0x278\n" ); INFOSTR( " rio -p 0x278 -d\n" ); INFOSTR( " ; initialize (with bad block check) and upload files\n" ); INFOSTR( " rio -iy -u *.mp3\n" ); INFOSTR( " ; delete existing files and upload playlist onto external flash ram\n" ); INFOSTR( " rio -za -f playlist.txt -x\n" ); INFOSTR( " ; initialize, upload files in playlist and then display directory\n" ); INFOSTR( " rio -d -in -f playlist.txt\n" ); INFOSTR( " ; download file then delete it and finally display directory\n" ); INFOSTR( " rio -d -g mp3Files/song.mp3 -z song.mp3\n" ); INFOSTR( " ; reverse playlist order and display directory, also change rx iodelay\n" ); INFOSTR( " rio -o \"5 4 3 2 1\" -d -dr %ld\n", CRIO_TIME_IODELAY_RX*2 ); } /////////////////////////////////////////////////////////////////////////////// int main( int iCountArg, char* paszArg[] ) { // default settings BOOL bDisplayDir = FALSE; BOOL bInit = FALSE; BOOL bInitMarkBadBlock = FALSE; BOOL bUseExternalFlash = FALSE; BOOL bDeleteAll = FALSE; BOOL bVerbose = FALSE; CRio* pRio = NULL; char* pszFileDelete = NULL; char* pszFileDownload = NULL; char* pszFilePlaylist = NULL; char* pszFilePlaylistTemp = NULL; char* pszPlaylistOrder = NULL; long lTimeIODelayInit = -1; long lTimeIODelayTx = -1; long lTimeIODelayRx = -1; int iPortBase = PORT_BASE_DEFAULT; int iPosDumpDirectory = 0; int iSizeDumpDirectory = 0; // process command line args if ( iCountArg < 2 ) { Help(); CLEANUP_RETURN( FALSE ); } for( int iA=1; iA= 0 ) cRio.SetIODelayInit( lTimeIODelayInit ); if ( lTimeIODelayTx >= 0 ) cRio.SetIODelayTx( lTimeIODelayTx ); if ( lTimeIODelayRx >= 0 ) cRio.SetIODelayRx( lTimeIODelayRx ); // select internal or external flash memory if ( bVerbose ) INFOSTR( "performing operations on %s flash ram\n", bUseExternalFlash ? "external" : "internal" ); cRio.UseExternalFlash( bUseExternalFlash ); // check device present if ( bVerbose ) INFOSTR( "check device present\n" ); if ( !cRio.CheckPresent() ) { ERRORSTR( "%s\n", cRio.GetErrorStr() ); CLEANUP_RETURN( FALSE ); } // update directory flag BOOL bUpdateDirectory = FALSE; // get current directory if ( bVerbose ) INFOSTR( "downloading directory\n" ); if ( !cRio.RxDirectory() ) { if ( cRio.GetErrorID() == CRIO_ERROR_CORRUPT ) ERRORSTR( "%s\n", cRio.GetErrorStr() ); else { ERRORSTR( "rx directory failed, %s\n", cRio.GetErrorStr() ); CLEANUP_RETURN( FALSE ); } } // if dump directory request if ( iSizeDumpDirectory ) DumpDirectory( cRio, iPosDumpDirectory, iSizeDumpDirectory ); // if init request if ( bInit ) { if ( bVerbose ) INFOSTR( "initializing with bad block check %s\n", bInitMarkBadBlock ? "enabled" : "disabled" ); if ( !cRio.Initialize(bInitMarkBadBlock, bVerbose ? ProgressCallback : NULL) ) { ERRORSTR( "Initialize failed, %s\n", cRio.GetErrorStr() ); CLEANUP_RETURN( FALSE ); } bUpdateDirectory = TRUE; } // if delete request if ( pszFileDelete ) { if ( bVerbose ) INFOSTR( "deleting %s\n", pszFileDelete ); if ( !cRio.RemoveFile(pszFileDelete) ) { ERRORSTR( "delete file failed, %s\n", cRio.GetErrorStr() ); CLEANUP_RETURN( FALSE ); } bUpdateDirectory = TRUE; } // if delete all request if ( bDeleteAll ) { if ( bVerbose ) INFOSTR( "deleting all files\n" ); if ( !cRio.RemoveAllFiles() ) { ERRORSTR( "delete all files failed, %s\n", cRio.GetErrorStr() ); CLEANUP_RETURN( FALSE ); } bUpdateDirectory = TRUE; } // if playlist request if ( pszFilePlaylist ) { if ( !ProcessPlaylist(cRio, pszFilePlaylist, bVerbose) ) CLEANUP_RETURN( FALSE ); bUpdateDirectory = TRUE; } // if temp playlist request if ( pszFilePlaylistTemp ) { if ( !ProcessPlaylist(cRio, pszFilePlaylistTemp, bVerbose) ) CLEANUP_RETURN( FALSE ); bUpdateDirectory = TRUE; } // if download request if ( pszFileDownload ) { if ( bVerbose ) INFOSTR( "downloading %s\n", pszFileDownload ); if ( !cRio.RxFile(pszFileDownload, bVerbose ? ProgressCallback : NULL) ) { ERRORSTR( "rx file failed, %s\n", cRio.GetErrorStr() ); CLEANUP_RETURN( FALSE ); } } // if playlist order request if ( pszPlaylistOrder ) { if ( bVerbose ) INFOSTR( "changing playlist order\n" ); if ( !ChangePlaylistOrder(cRio, pszPlaylistOrder) ) CLEANUP_RETURN( FALSE ); bUpdateDirectory = TRUE; } // if directory update required if ( bUpdateDirectory ) { if ( bVerbose ) INFOSTR( "updating directory\n" ); if ( !cRio.TxDirectory() ) { ERRORSTR( "tx directory failed, %s\n", cRio.GetErrorStr() ); CLEANUP_RETURN( FALSE ); } } // if display directory request if ( bDisplayDir ) DisplayDirectory( cRio, bVerbose ); // restore CLEANUP_RETURN( TRUE ); } rio-1.07.orig/binary.h0100744000175000017500000001457706730234306013643 0ustar vincevince/////////////////////////////////////////////////////////////////////////////// // // binary.h // /////////////////////////////////////////////////////////////////////////////// #ifndef _BINARY_ #define _BINARY_ #define B_00000000 0 #define B_00000001 1 #define B_00000010 2 #define B_00000011 3 #define B_00000100 4 #define B_00000101 5 #define B_00000110 6 #define B_00000111 7 #define B_00001000 8 #define B_00001001 9 #define B_00001010 10 #define B_00001011 11 #define B_00001100 12 #define B_00001101 13 #define B_00001110 14 #define B_00001111 15 #define B_00010000 16 #define B_00010001 17 #define B_00010010 18 #define B_00010011 19 #define B_00010100 20 #define B_00010101 21 #define B_00010110 22 #define B_00010111 23 #define B_00011000 24 #define B_00011001 25 #define B_00011010 26 #define B_00011011 27 #define B_00011100 28 #define B_00011101 29 #define B_00011110 30 #define B_00011111 31 #define B_00100000 32 #define B_00100001 33 #define B_00100010 34 #define B_00100011 35 #define B_00100100 36 #define B_00100101 37 #define B_00100110 38 #define B_00100111 39 #define B_00101000 40 #define B_00101001 41 #define B_00101010 42 #define B_00101011 43 #define B_00101100 44 #define B_00101101 45 #define B_00101110 46 #define B_00101111 47 #define B_00110000 48 #define B_00110001 49 #define B_00110010 50 #define B_00110011 51 #define B_00110100 52 #define B_00110101 53 #define B_00110110 54 #define B_00110111 55 #define B_00111000 56 #define B_00111001 57 #define B_00111010 58 #define B_00111011 59 #define B_00111100 60 #define B_00111101 61 #define B_00111110 62 #define B_00111111 63 #define B_01000000 64 #define B_01000001 65 #define B_01000010 66 #define B_01000011 67 #define B_01000100 68 #define B_01000101 69 #define B_01000110 70 #define B_01000111 71 #define B_01001000 72 #define B_01001001 73 #define B_01001010 74 #define B_01001011 75 #define B_01001100 76 #define B_01001101 77 #define B_01001110 78 #define B_01001111 79 #define B_01010000 80 #define B_01010001 81 #define B_01010010 82 #define B_01010011 83 #define B_01010100 84 #define B_01010101 85 #define B_01010110 86 #define B_01010111 87 #define B_01011000 88 #define B_01011001 89 #define B_01011010 90 #define B_01011011 91 #define B_01011100 92 #define B_01011101 93 #define B_01011110 94 #define B_01011111 95 #define B_01100000 96 #define B_01100001 97 #define B_01100010 98 #define B_01100011 99 #define B_01100100 100 #define B_01100101 101 #define B_01100110 102 #define B_01100111 103 #define B_01101000 104 #define B_01101001 105 #define B_01101010 106 #define B_01101011 107 #define B_01101100 108 #define B_01101101 109 #define B_01101110 110 #define B_01101111 111 #define B_01110000 112 #define B_01110001 113 #define B_01110010 114 #define B_01110011 115 #define B_01110100 116 #define B_01110101 117 #define B_01110110 118 #define B_01110111 119 #define B_01111000 120 #define B_01111001 121 #define B_01111010 122 #define B_01111011 123 #define B_01111100 124 #define B_01111101 125 #define B_01111110 126 #define B_01111111 127 #define B_10000000 128 #define B_10000001 129 #define B_10000010 130 #define B_10000011 131 #define B_10000100 132 #define B_10000101 133 #define B_10000110 134 #define B_10000111 135 #define B_10001000 136 #define B_10001001 137 #define B_10001010 138 #define B_10001011 139 #define B_10001100 140 #define B_10001101 141 #define B_10001110 142 #define B_10001111 143 #define B_10010000 144 #define B_10010001 145 #define B_10010010 146 #define B_10010011 147 #define B_10010100 148 #define B_10010101 149 #define B_10010110 150 #define B_10010111 151 #define B_10011000 152 #define B_10011001 153 #define B_10011010 154 #define B_10011011 155 #define B_10011100 156 #define B_10011101 157 #define B_10011110 158 #define B_10011111 159 #define B_10100000 160 #define B_10100001 161 #define B_10100010 162 #define B_10100011 163 #define B_10100100 164 #define B_10100101 165 #define B_10100110 166 #define B_10100111 167 #define B_10101000 168 #define B_10101001 169 #define B_10101010 170 #define B_10101011 171 #define B_10101100 172 #define B_10101101 173 #define B_10101110 174 #define B_10101111 175 #define B_10110000 176 #define B_10110001 177 #define B_10110010 178 #define B_10110011 179 #define B_10110100 180 #define B_10110101 181 #define B_10110110 182 #define B_10110111 183 #define B_10111000 184 #define B_10111001 185 #define B_10111010 186 #define B_10111011 187 #define B_10111100 188 #define B_10111101 189 #define B_10111110 190 #define B_10111111 191 #define B_11000000 192 #define B_11000001 193 #define B_11000010 194 #define B_11000011 195 #define B_11000100 196 #define B_11000101 197 #define B_11000110 198 #define B_11000111 199 #define B_11001000 200 #define B_11001001 201 #define B_11001010 202 #define B_11001011 203 #define B_11001100 204 #define B_11001101 205 #define B_11001110 206 #define B_11001111 207 #define B_11010000 208 #define B_11010001 209 #define B_11010010 210 #define B_11010011 211 #define B_11010100 212 #define B_11010101 213 #define B_11010110 214 #define B_11010111 215 #define B_11011000 216 #define B_11011001 217 #define B_11011010 218 #define B_11011011 219 #define B_11011100 220 #define B_11011101 221 #define B_11011110 222 #define B_11011111 223 #define B_11100000 224 #define B_11100001 225 #define B_11100010 226 #define B_11100011 227 #define B_11100100 228 #define B_11100101 229 #define B_11100110 230 #define B_11100111 231 #define B_11101000 232 #define B_11101001 233 #define B_11101010 234 #define B_11101011 235 #define B_11101100 236 #define B_11101101 237 #define B_11101110 238 #define B_11101111 239 #define B_11110000 240 #define B_11110001 241 #define B_11110010 242 #define B_11110011 243 #define B_11110100 244 #define B_11110101 245 #define B_11110110 246 #define B_11110111 247 #define B_11111000 248 #define B_11111001 249 #define B_11111010 250 #define B_11111011 251 #define B_11111100 252 #define B_11111101 253 #define B_11111110 254 #define B_11111111 255 #endif // _BINARY_ rio-1.07.orig/dos.mak0100744000175000017500000000052606730234306013452 0ustar vincevince############################################################################### # # RIO utility makefile for Borland Turbo C++ v1.01 # # Ashpool Systems (c) 1999 # ############################################################################### all: rio.exe rio.exe: app.cpp rio.cpp tcc -mh -erio.exe app.cpp rio.cpp \tc\lib\wildargs.obj rio-1.07.orig/io.obj0100744000175000017500000000016305305734064013276 0ustar vincevinceio.asm+IO_TEXTCODEH!RPORTWPORT Ѡ%UPRFVZX]URV2Z]trio-1.07.orig/iopl32.h0100744000175000017500000000022506730234306013450 0ustar vincevince#ifdef __cplusplus extern "C" { #endif USHORT _Far16 _Pascal RPORT(USHORT); void _Far16 _Pascal WPORT(USHORT, USHORT); #ifdef __cplusplus } #endif rio-1.07.orig/makefile0100744000175000017500000000053206730234306013670 0ustar vincevince############################################################################### # # RIO utility makefile for linux g++ # # Ashpool Systems (c) 1999 # ############################################################################### all: rio rio: app.cpp rio.cpp g++ -O1 -o rio app.cpp rio.cpp chmod +s rio clean: rm -f rio rm -f *.o rio-1.07.orig/os2.def0100744000175000017500000000011306730234306013346 0ustar vincevinceNAME RIO WINDOWCOMPAT SEGMENTS IO_TEXT IOPL EXPORTS RPORT 1 WPORT 2 rio-1.07.orig/os2.mak0100744000175000017500000000116106730234306013364 0ustar vincevince# os2.mak # Created by IBM WorkFrame/2 MakeMake at 21:04:53 on 24 Mar 1999 # # The actions included in this make file are: # Compile::C++ Compiler # Link::Linker .SUFFIXES: .CPP .obj .all: rio.exe .CPP.obj: icc.exe /Sp1 /Ss /Q /G5 /Tm /Fo"%|dpfF.obj" /C %s rio.exe: APP.obj RIO.obj io.obj {$(LIB)}os2.def icc.exe @<< /B" /st:65535 /nologo" /Ferio.exe io.obj os2.def APP.obj RIO.obj << APP.obj: \ APP.CPP \ {;$(INCLUDE);}std.h \ {;$(INCLUDE);}rio.h RIO.obj: \ RIO.CPP \ {;$(INCLUDE);}std.h \ {;$(INCLUDE);}binary.h \ {;$(INCLUDE);}rio.h \ iopl32.h rio-1.07.orig/playlist.txt0100744000175000017500000000064406730234306014576 0ustar vincevince;------------------------------------------------------------------------------ ; example playlist file which can use ';' and '#' to preceed comments # first entry ../../mp3/diplomat6_bigmouthshut.mp3 ../../mp3/boogie_beat.mp3 ../../mp3/its_alright.mp3 ../../mp3/im_not_lost_im_exploring.mp3 ../../mp3/hit_the_ground_runnin.mp3 ../../mp3/midnight_high.mp3 ../../mp3/when_she_runs.mp3 ; last entry ../../mp3/Charm.Mp3 rio-1.07.orig/rio.cpp0100744000175000017500000010776406730234306013504 0ustar vincevince/////////////////////////////////////////////////////////////////////////////// // // rio.cpp // // v1.01 14/01/99 Initial launch. // // v1.02 18/01/99 Additional debug added for ioperm() call. // // v1.03 25/01/99 Added download support. // Added delete support. // Progress callback for upload/download file. // Boland Turbo C++ v1.01 supported. // // v1.04 27/01/99 Win NT v4.0 supported, using RIOIO driver provided. // // v1.05 29/01/99 Added version field in dir header to be compatible // with later Rio Manager v1.01 software. // Added CheckPresent() member function. // Support for Alpha platform. // // v1.06 11/03/99 Added support for external flash ram. // Added initialization with bad block check. // Added file re-ordering support. // // v1.07 10/06/99 Added support for FreeBSD. // Added support for BSDI. // Added support for OS/2. // Added support for Rio 64M SE (Special Edition). // Improved detection of device, using manufacturer ID. // Selectable IO delays. // /////////////////////////////////////////////////////////////////////////////// #include #include #include #include #include #include #include "rio.h" #include "binary.h" // platform dependencies #if defined(_WINNT) // MS VC++ v5.0 for WinNT v4 #include #include #include "rioioctl.h" #define OUTPORT( p, v ) WinNTOutPort( p, v ) #define INPORT( p ) WinNTInPort( p ) #define CLOCK_SECOND CLOCKS_PER_SEC #define DELETEARRAY delete[] #define ID_DRIVER_VERSION 101 #elif defined(_WIN32) // MS VC++ v5.0 for Win9x #include #define OUTPORT( p, v ) _outp( p, v ) #define INPORT( p ) _inp( p ) #define CLOCK_SECOND CLOCKS_PER_SEC #define DELETEARRAY delete[] #elif defined(__linux__) // linux g++ #include #if defined(__alpha) #include #else #include #endif #include #define OUTPORT(p,v) outb( v, p ) #define INPORT(p) inb( p ) #define CLOCK_SECOND CLOCKS_PER_SEC #define DELETEARRAY delete[] #elif defined(__FreeBSD__) // FreeBSD g++ #include #include #include #define OUTPORT(p,v) outb( p, v ) #define INPORT(p) inb( p ) #define CLOCK_SECOND CLOCKS_PER_SEC #define DELETEARRAY delete[] #elif defined(__bsdi__) // BSD/OS g++ #include #include #define OUTPORT(p,v) outb( p, v ) #define INPORT(p) inb( p ) #define CLOCK_SECOND CLOCKS_PER_SEC #define DELETEARRAY delete[] #elif defined(__OS2__) // OS/2 VisualAge C++ v. 3 #include "iopl32.h" #define OUTPORT(p,v) WPORT( p, v ) #define INPORT(p) ((UCHAR)RPORT( p )) #define CLOCK_SECOND CLOCKS_PER_SEC #define DELETEARRAY delete[] #elif defined(__TURBOC__) // turboc v1.01 #include #define OUTPORT( p, v ) outp( p, v ) #define INPORT( p ) inp( p ) #define CLOCK_SECOND ((int)CLOCKS_PER_SEC) #define DELETEARRAY delete #else // not supported #error ! ! compiler/platform not supported ! ! #endif // port offset constants #define OFFSET_PORT_DATA 0 #define OFFSET_PORT_STATUS 1 #define OFFSET_PORT_CONTROL 2 // max tx/rx block retry #define MAX_RETRY 3 // flash ram bank pos #define POS_BANK_EXTERNALFLASH 4 // delay's #define IODELAY(c) { for( long _lA=0; _lA clock() ) ; } // new, delete #define NEWBLOCK( p ) { p = new UCHAR[ CRIO_SIZE_32KBLOCK ]; if ( !p ) { LogError( CRIO_ERROR_ALLOC, "new failed" ); return FALSE; } } #define ZERONEWBLOCK( p ) { NEWBLOCK(p); memset(p, 0, CRIO_SIZE_32KBLOCK); } #define DELETEBLOCK( p ) { if ( p ) { DELETEARRAY p; p = NULL; } } // command out #define COMMANDOUT(v1, v2, v3) { OUTPORT(m_iPortData, v1); OUTPORT(m_iPortControl, v2); OUTPORT(m_iPortControl, v3); } // wait for reply #define WAITNIBBLE( v1 ) { if (!WaitInput(v1)) return FALSE; } #define WAITACK() { if (!WaitAck()) return FALSE; } /////////////////////////////////////////////////////////////////////////////// // if WinNT #if defined(_WINNT) // handle static HANDLE m_hDriver; // WinNT out port void WinNTOutPort( int iPort, int iValue ) { DWORD dwSizeReturn; ULONG ulInput = ((ULONG)iPort-0x378) | ((ULONG)iValue << 16); DeviceIoControl( m_hDriver, RIOIO_IOCTL_WRITE, &ulInput, sizeof(long), NULL, 0, &dwSizeReturn, NULL ); } // WinNT in port int WinNTInPort( int iPort ) { DWORD dwSizeReturn; ULONG ulPort = iPort - 0x378; ULONG ulData = 0; DeviceIoControl( m_hDriver, RIOIO_IOCTL_READ, &ulPort, sizeof(ulPort), &ulData, sizeof(char), &dwSizeReturn, NULL ); return (int)ulData; } #endif /////////////////////////////////////////////////////////////////////////////// // if DOS #if defined(__TURBOC__) // get clock ticks long clock( void ) { return (long) (*(int far*)MK_FP( 0x40, 0x6c )); } #endif /////////////////////////////////////////////////////////////////////////////// // return file only static char* GetFile( char* pszPathFile ) { int iLength = strlen( pszPathFile ); if ( !iLength ) return pszPathFile; char* pc = pszPathFile + iLength - 1; while( *pc != '\\' && *pc != '/' && *pc != ':' ) { if ( pc == pszPathFile ) return pc; --pc; } ++pc; return pc; } /////////////////////////////////////////////////////////////////////////////// // set/unset, constructors and destructors void CRio::Unset( void ) { // if WinNT #if defined(_WINNT) // close device file if ( m_hDriver ) { CloseHandle( m_hDriver ); m_hDriver = NULL; } #endif } BOOL CRio::Set( int iPortBase ) { // cleanup any previous Set() Unset(); // determine ports m_iPortBase = iPortBase; m_iPortData = m_iPortBase + OFFSET_PORT_DATA; m_iPortStatus = m_iPortBase + OFFSET_PORT_STATUS; m_iPortControl = m_iPortBase + OFFSET_PORT_CONTROL; // if linux #if defined(__linux__) // request access to required ports if ( ioperm(m_iPortBase, 3, 1) ) { LogError( CRIO_ERROR_IOPRERM, "ioperm() failed, reason '%s'", SZERROR ); return FALSE; } #endif // if FreeBSD #if defined(__FreeBSD__) // request direct access to memory addresses if ( open("/dev/io", O_RDONLY) == -1 ) { LogError( CRIO_ERROR_IOPRERM, "open() failed, reason '%s'\n", SZERROR ); return FALSE; } #endif // if WinNT #if defined(_WINNT) // open generic IO device m_hDriver = CreateFile( "\\\\.\\RioDev", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL ); if ( m_hDriver == INVALID_HANDLE_VALUE ) { LogError( CRIO_ERROR_CREATEFILE, "CreateFile() failed, reason %ld\n", GetLastError() ); return FALSE; } // check version DWORD dwSizeReturn; ULONG ulVersion; DeviceIoControl( m_hDriver, RIOIO_IOCTL_GETVERSION, NULL, 0, &ulVersion, sizeof(ulVersion), &dwSizeReturn, NULL ); if ( ulVersion != ID_DRIVER_VERSION ) { LogError( CRIO_ERROR_DRIVERVERSION, "incorrect RioIO driver version, v%d.%d loaded, v%d.%d expected\n", ulVersion/100, ulVersion%100, ID_DRIVER_VERSION/100, ID_DRIVER_VERSION%100 ); return FALSE; } #endif return TRUE; } CRio::CRio() { // if WinNT #if defined(_WINNT) m_hDriver = NULL; #endif // default to use internal flash m_bUseExternalFlash = FALSE; // default to not using special edition m_bSpecialEdition = FALSE; // default io delay's m_lTimeIODelayInit = CRIO_TIME_IODELAY_INIT; m_lTimeIODelayTx = CRIO_TIME_IODELAY_TX; m_lTimeIODelayRx = CRIO_TIME_IODELAY_RX; } CRio::~CRio() { Unset(); } /////////////////////////////////////////////////////////////////////////////// // log error void CRio::LogError( int iIDError, const char* pszFormat, ... ) { va_list ArgPtr; va_start( ArgPtr, pszFormat ); vsprintf( m_szError, pszFormat, ArgPtr ); va_end( ArgPtr ); m_iIDError = iIDError; } // find first free 32K block UINT CRio::FindFirstFree32KBlock( void ) { UINT uiA; UCHAR* puc = m_cDirBlock.m_auc32KBlockUsed; for( uiA=0; uiA clock() ) { ucRx = INPORT( m_iPortStatus ) & 0xf8; if ( ucRx == (int)iValue ) return TRUE; } return FALSE; } // wait for ack BOOL CRio::WaitAck( void ) { long lTime = clock() + CLOCK_SECOND; while( lTime > clock() ) { UCHAR ucRx = INPORT( m_iPortStatus ); if ( ucRx & 0x08 ) return TRUE; } return FALSE; } // get byte from status port UINT CRio::GetDataByte( void ) { // get hi nibble OUTPORT( m_iPortControl, B_00000000 ); IODELAY( m_lTimeIODelayRx ); UCHAR ucRx = INPORT( m_iPortStatus ); UCHAR ucIn = ((ucRx & 0xf0) ^ 0x80) >> 4; // get lo nibble and combine with previous nibble to make byte OUTPORT( m_iPortControl, B_00000100 ); IODELAY( m_lTimeIODelayRx ); ucRx = INPORT( m_iPortStatus ); ucIn |= (ucRx & 0xf0) ^ 0x80; // reverse bits in byte UCHAR ucReversed = 0; for( int iC=0; iC<8; ++iC ) { ucReversed <<= 1; ucReversed |= (ucIn & 1); ucIn >>= 1; } return ucReversed; } // io intro BOOL CRio::IOIntro( void ) { OUTPORT( m_iPortControl, B_00000100 ); COMMANDOUT( B_10101000, B_00001100, B_00000100 ); OUTPORT( m_iPortControl, B_00000000 ); IODELAY( m_lTimeIODelayInit ); OUTPORT( m_iPortControl, B_00000100 ); IODELAY( m_lTimeIODelayInit ); COMMANDOUT( B_10101101, B_00001100, B_00000100 ); COMMANDOUT( B_01010101, B_00000000, B_00000100 ); COMMANDOUT( B_10101110, B_00001100, B_00000100 ); COMMANDOUT( B_10101010, B_00000000, B_00000100 ); COMMANDOUT( B_10101000, B_00001100, B_00000100 ); OUTPORT( m_iPortControl, B_00000000 ); IODELAY( m_lTimeIODelayInit ); OUTPORT( m_iPortControl, B_00000100 ); IODELAY( m_lTimeIODelayInit ); return TRUE; } // io outro BOOL CRio::IOOutro( void ) { COMMANDOUT( B_10101101, B_00001100, B_00000100 ); COMMANDOUT( B_11111111, B_00000000, B_00000100 ); OUTPORT( m_iPortData, B_00000000 ); return TRUE; } // tx 32K block retry BOOL CRio::Tx32KBlockRetry( void* pv, UINT uiPos32KBlock, UINT uiPos32KBlockPrev, UINT uiPos32KBlockNext ) { ULONG ulPos512ByteBlock; ULONG ulPosHi; ULONG ulPosMid; ULONG ulPosLo; int iA, iB; // io intro if ( !IOIntro() ) return FALSE; // if internal, blocksize = 8K else if external blocksize = 16K int iCount8K = m_bUseExternalFlash ? 2 : 1; // prepare all pages in block for( iA=0; iA<4; iA+=iCount8K ) { ulPos512ByteBlock = ((ULONG)uiPos32KBlock * 32768 + (ULONG)iA * 8192) / 512; ulPosLo = ulPos512ByteBlock & 0xff; if ( m_bUseExternalFlash ) { ulPosHi = POS_BANK_EXTERNALFLASH; ulPosMid = (ulPos512ByteBlock & 0xff00) >> 8; } else if ( m_bSpecialEdition ) { ulPosHi = ulPos512ByteBlock / 32768; ulPosMid = (ulPos512ByteBlock & 0x7f00) >> 8; } else { ulPosHi = ulPos512ByteBlock / 16384; ulPosMid = (ulPos512ByteBlock & 0x3f00) >> 8; } COMMANDOUT( B_10101011, B_00001100, B_00000100 ); COMMANDOUT( ulPosHi, B_00000000, B_00000100 ); COMMANDOUT( B_10100001, B_00001100, B_00000100 ); COMMANDOUT( B_01100000, B_00000000, B_00000100 ); COMMANDOUT( B_10100010, B_00001100, B_00000100 ); COMMANDOUT( ulPosLo, B_00000000, B_00000100 ); COMMANDOUT( ulPosMid, B_00000000, B_00000100 ); COMMANDOUT( B_10100001, B_00001100, B_00000100 ); COMMANDOUT( B_11010000, B_00000000, B_00000100 ); WAITACK(); COMMANDOUT( B_10100001, B_00001100, B_00000100 ); COMMANDOUT( B_01110000, B_00000000, B_00000100 ); COMMANDOUT( B_10100000, B_00001100, B_00000100 ); OUTPORT( m_iPortControl, B_00000000 ); IODELAY( m_lTimeIODelayTx ); OUTPORT( m_iPortControl, B_00000100 ); IODELAY( m_lTimeIODelayTx ); } // send 32K in 512 byte chunks UCHAR* pauc = (UCHAR*)pv; for( iA=0; iA<(32768/512); ++iA, pauc+=512 ) { ulPos512ByteBlock = ((ULONG)uiPos32KBlock * 32768 + (ULONG)iA * 512) / 512; ulPosLo = ulPos512ByteBlock & 0xff; if ( m_bUseExternalFlash ) { ulPosHi = POS_BANK_EXTERNALFLASH; ulPosMid = (ulPos512ByteBlock & 0xff00) >> 8; } else if ( m_bSpecialEdition ) { ulPosHi = ulPos512ByteBlock / 32768; ulPosMid = (ulPos512ByteBlock & 0x7f00) >> 8; } else { ulPosHi = ulPos512ByteBlock / 16384; ulPosMid = (ulPos512ByteBlock & 0x3f00) >> 8; } // issue upload 512 byte block command COMMANDOUT( B_10101011, B_00001100, B_00000100 ); COMMANDOUT( ulPosHi, B_00000000, B_00000100 ); COMMANDOUT( B_10100001, B_00001100, B_00000100 ); COMMANDOUT( B_10000000, B_00000000, B_00000100 ); COMMANDOUT( B_10100010, B_00001100, B_00000100 ); COMMANDOUT( B_00000000, B_00000000, B_00000100 ); COMMANDOUT( ulPosLo, B_00000000, B_00000100 ); COMMANDOUT( ulPosMid, B_00000000, B_00000100 ); COMMANDOUT( B_10100011, B_00001100, B_00000100 ); // create checksum of 512 byte block USHORT usChecksum = 0; USHORT* paus = (USHORT*)pauc; for( iB=0; iB<(512/sizeof(short)); ++iB, ++paus ) usChecksum -= *paus; // clock out data #if defined(_WINNT) { DWORD dwSizeReturn; DeviceIoControl( m_hDriver, RIOIO_IOCTL_WRITEBLOCK, pauc, 512, NULL, 0, &dwSizeReturn, NULL ); } #else UCHAR* pauc2 = pauc; for( iB=0; iB<512; ++iB, ++pauc2 ) { OUTPORT( m_iPortData, (*pauc2) ); if ( !(iB & 1) ) OUTPORT( m_iPortControl, B_00000000 ); else OUTPORT( m_iPortControl, B_00000100 ); IODELAY( 1 ); } #endif // prepare end of block CEnd512ByteBlock cEnd512ByteBlock; memset( &cEnd512ByteBlock, 0, sizeof(CEnd512ByteBlock) ); cEnd512ByteBlock.m_usChecksum = usChecksum; if ( uiPos32KBlockNext == 0xffff ) { cEnd512ByteBlock.m_ulPos512ByteBlockNextMult256 = 0xffffffff; cEnd512ByteBlock.m_ucPos8192KBlockNext1 = 0xff; cEnd512ByteBlock.m_ucPos8192KBlockNext2 = 0xff; } else { cEnd512ByteBlock.m_ulPos512ByteBlockNextMult256 = ((ULONG)uiPos32KBlockNext * 64) * 256; if ( !m_bSpecialEdition ) { cEnd512ByteBlock.m_ucPos8192KBlockNext1 = uiPos32KBlockNext / 256; cEnd512ByteBlock.m_ucPos8192KBlockNext2 = uiPos32KBlockNext / 256; } else { cEnd512ByteBlock.m_ucPos8192KBlockNext1 = uiPos32KBlockNext / 512; cEnd512ByteBlock.m_ucPos8192KBlockNext2 = uiPos32KBlockNext / 512; } if ( m_bUseExternalFlash ) { cEnd512ByteBlock.m_ulPos512ByteBlockNextMult256 += 0x01000000; cEnd512ByteBlock.m_ucPos8192KBlockNext1 = 0; cEnd512ByteBlock.m_ucPos8192KBlockNext2 = 0; } } if ( uiPos32KBlockPrev == 0xffff ) { cEnd512ByteBlock.m_ulPos512ByteBlockPrevMult256 = 0xffffffff; cEnd512ByteBlock.m_ucPos8192KBlockPrev1 = 0xff; cEnd512ByteBlock.m_ucPos8192KBlockPrev2 = 0xff; cEnd512ByteBlock.m_usPos32KBlockPrevMult256 = 0xffff; } else { cEnd512ByteBlock.m_ulPos512ByteBlockPrevMult256 = ((ULONG)uiPos32KBlockPrev * 64) * 256; if ( !m_bSpecialEdition ) { cEnd512ByteBlock.m_ucPos8192KBlockPrev1 = uiPos32KBlockPrev / 256; cEnd512ByteBlock.m_ucPos8192KBlockPrev2 = uiPos32KBlockPrev / 256; } else { cEnd512ByteBlock.m_ucPos8192KBlockPrev1 = uiPos32KBlockPrev / 512; cEnd512ByteBlock.m_ucPos8192KBlockPrev2 = uiPos32KBlockPrev / 512; } if ( m_bUseExternalFlash ) { cEnd512ByteBlock.m_ulPos512ByteBlockPrevMult256 += 0x01000000; cEnd512ByteBlock.m_ucPos8192KBlockPrev1 = 0; cEnd512ByteBlock.m_ucPos8192KBlockPrev2 = 0; } cEnd512ByteBlock.m_usPos32KBlockPrevMult256 = uiPos32KBlockPrev * 256; } // output end of block #if defined(_WINNT) { DWORD dwSizeReturn; DeviceIoControl( m_hDriver, RIOIO_IOCTL_WRITEBLOCK, &cEnd512ByteBlock, sizeof(CEnd512ByteBlock), NULL, 0, &dwSizeReturn, NULL ); } #else pauc2 = (UCHAR*)&cEnd512ByteBlock; for( iB=0; iB> 8; } else if ( m_bSpecialEdition ) { ulPosHi = ulPos512ByteBlock / 32768; ulPosMid = (ulPos512ByteBlock & 0x7f00) >> 8; } else { ulPosHi = ulPos512ByteBlock / 16384; ulPosMid = (ulPos512ByteBlock & 0x3f00) >> 8; } // issue download 512 byte block command COMMANDOUT( B_10101011, B_00001100, B_00000100 ); COMMANDOUT( ulPosHi, B_00000000, B_00000100 ); COMMANDOUT( B_10100001, B_00001100, B_00000100 ); COMMANDOUT( B_00000000, B_00000000, B_00000100 ); COMMANDOUT( B_10100010, B_00001100, B_00000100 ); COMMANDOUT( B_00000000, B_00000000, B_00000100 ); COMMANDOUT( ulPosLo, B_00000000, B_00000100 ); COMMANDOUT( ulPosMid, B_00000000, B_00000100 ); WAITACK(); COMMANDOUT( B_10100000, B_00001100, B_00000100 ); // clock in data #if defined(_WINNT) { DWORD dwSizeReturn; DeviceIoControl( m_hDriver, RIOIO_IOCTL_READBLOCK, pauc, 512, pauc, 512, &dwSizeReturn, NULL ); } #else for( iB=0; iB<512; ++iB ) *(pauc+iB) = GetDataByte(); #endif // clock in 16 bytes which are ignored for( iB=0; iB<16; ++iB ) GetDataByte(); // delay WAITACK(); } return TRUE; } // rx 32K block BOOL CRio::Rx32KBlock( void* pv, UINT uiPos32KBlock ) { int iRetry = 0; while( iRetry < MAX_RETRY ) { if ( Rx32KBlockRetry(pv, uiPos32KBlock) ) return TRUE; DELAY( CLOCK_SECOND ); ++iRetry; } LogError( CRIO_ERROR_RXBLOCKRETRY, "too many retries for rx block" ); return FALSE; } // mark bad blocks BOOL CRio::MarkBadBlocks( BOOL (*pfProgress)(int iPos, int iCount) ) { // create temp block UCHAR* paucBlock; NEWBLOCK( paucBlock ); // block count USHORT usPos32KBlockEnd; if ( m_bUseExternalFlash ) usPos32KBlockEnd = m_uiCount32KBlockAvailableExternal; else usPos32KBlockEnd = m_bSpecialEdition ? CRIO_COUNT_32KBLOCKIN64M : CRIO_COUNT_32KBLOCKIN32M; // assume directory block is ok m_cDirBlock.m_auc32KBlockUsed[ 0 ] = CRIO_ID_32KBLOCK_FREE; // process all blocks (except directory block) int iCount32KBlockBad = 0; USHORT usPos32KBlock; for( usPos32KBlock=1; usPos32KBlockm_szName) ) return pDirEntry; } return NULL; } BOOL CRio::Initialize( BOOL bMarkBadBlock, BOOL (*pfProgress)(int iPos, int iCount) ) { CDirHeader& cDirHeader = m_cDirBlock.m_cDirHeader; // init directory header memset( &m_cDirBlock.m_cDirHeader, 0, sizeof(m_cDirBlock.m_cDirHeader) ); // set version (so compatible with Rio Manager v1.01) cDirHeader.m_usVersion = 0x0100; // init directory entries memset( &m_cDirBlock.m_acDirEntry, 0, sizeof(m_cDirBlock.m_acDirEntry) ); // init block used flags memset( &m_cDirBlock.m_auc32KBlockUsed, CRIO_ID_32KBLOCK_FREE, sizeof(m_cDirBlock.m_auc32KBlockUsed) ); // init FAT memset( &m_cDirBlock.m_ausFAT, 0, sizeof(m_cDirBlock.m_ausFAT) ); // if mark bad block request if ( bMarkBadBlock ) { if ( !MarkBadBlocks(pfProgress) ) return FALSE; } // available blocks if ( m_bUseExternalFlash ) cDirHeader.m_usCount32KBlockAvailable = m_uiCount32KBlockAvailableExternal; else cDirHeader.m_usCount32KBlockAvailable = m_bSpecialEdition ? CRIO_COUNT_32KBLOCKIN64M : CRIO_COUNT_32KBLOCKIN32M; // blocks remaining (taking into account bad blocks) cDirHeader.m_usCount32KBlockRemaining = cDirHeader.m_usCount32KBlockAvailable - cDirHeader.m_usCount32KBlockBad; return TRUE; } BOOL CRio::RemoveFile( char* pszFile ) { // get directory entry for file CDirEntry* pDirEntry = FindFile( pszFile ); if ( !pDirEntry ) { LogError( CRIO_ERROR_FILENOTFOUND, "file '%s' not present on device", pszFile ); return FALSE; } // free FAT and blocks used USHORT usPos32KBlock = pDirEntry->m_usPos32KBlock; while( usPos32KBlock ) { m_cDirBlock.m_auc32KBlockUsed[ usPos32KBlock ] = CRIO_ID_32KBLOCK_FREE; USHORT usTemp = m_cDirBlock.m_ausFAT[ usPos32KBlock ]; m_cDirBlock.m_ausFAT[ usPos32KBlock ] = 0; usPos32KBlock = usTemp; } // adjust directory header CDirHeader& cDirHeader = m_cDirBlock.m_cDirHeader; --cDirHeader.m_usCountEntry; cDirHeader.m_usCount32KBlockUsed -= pDirEntry->m_usCount32KBlock; cDirHeader.m_usCount32KBlockRemaining += pDirEntry->m_usCount32KBlock; // clear directory entry memset( pDirEntry, 0, sizeof(CDirEntry) ); // shuffle directory entries int iPosEntry = pDirEntry - m_cDirBlock.m_acDirEntry; int iCount = (int)cDirHeader.m_usCountEntry - iPosEntry; for( int iA=0; iA= uiCountEntry || uiPosNew >= uiCountEntry ) { LogError( CRIO_ERROR_INVALIDFILEPOSITION, "invalid file position" ); DELETEARRAY paDirEntryNew; return FALSE; } memcpy( &paDirEntryNew[uiPosNew], &paDirEntry[uiPosOld], sizeof(CDirEntry) ); } // update current directory entries memcpy( paDirEntry, paDirEntryNew, CRIO_MAX_DIRENTRY * sizeof(CDirEntry) ); DELETEARRAY paDirEntryNew; return TRUE; } BOOL CRio::TxDirectory( void ) { // create zero initialized temp block UCHAR* paucBlock; ZERONEWBLOCK( paucBlock ); // directory header CDirHeader& cDirHeader = m_cDirBlock.m_cDirHeader; // update directory header time cDirHeader.m_lTimeLastUpdate = time( NULL ); // create checksums (note: second checksum needs to be calculated first as // this makes up part of the first checksum) cDirHeader.m_usChecksum2 = CalculateChecksum2(); cDirHeader.m_usChecksum1 = CalculateChecksum1(); // copy directory block to temp block memcpy( paucBlock, &m_cDirBlock, sizeof(m_cDirBlock) ); // send block BOOL bResult = Tx32KBlock( paucBlock, 0, 0, 0 ); if ( bResult ) { // IO outro IOOutro(); } // release temp block DELETEBLOCK( paucBlock ); return bResult; } BOOL CRio::RxDirectory( void ) { // create temp block UCHAR* paucBlock; NEWBLOCK( paucBlock ); // get block BOOL bResult = Rx32KBlock( paucBlock, 0 ); if ( bResult ) { // io outro IOOutro(); // store directory memcpy( &m_cDirBlock, paucBlock, sizeof(m_cDirBlock) ); // validate checksums USHORT usChecksum1 = (USHORT)CalculateChecksum1(); USHORT usChecksum2 = (USHORT)CalculateChecksum2(); if ( usChecksum1 != m_cDirBlock.m_cDirHeader.m_usChecksum1 || usChecksum2 != m_cDirBlock.m_cDirHeader.m_usChecksum2 ) { LogError( CRIO_ERROR_CORRUPT, "invalid directory checksum, initialization recommended" ); bResult = FALSE; } } // release temp block DELETEBLOCK( paucBlock ); return bResult; } BOOL CRio::TxFile( char* pszPathFile, BOOL (*pfProgress)(int iPos, int iCount) ) { // directory header CDirHeader& cDirHeader = m_cDirBlock.m_cDirHeader; // if no enough room in directory for entry if ( cDirHeader.m_usCountEntry >= CRIO_MAX_DIRENTRY ) { LogError( CRIO_ERROR_MAXDIRENTRY, "max number of directory entries (%d) already in use", CRIO_MAX_DIRENTRY ); return FALSE; } // open file for read FILE* fpFile = fopen( pszPathFile, "rb" ); if ( !fpFile ) { LogError( CRIO_ERROR_OPEN, "unable to open '%s' for read", pszPathFile ); return FALSE; } // get fileinfo struct stat sStat; if ( stat(pszPathFile, &sStat) ) { LogError( CRIO_ERROR_STAT, "stat() failed for '%s'", pszPathFile ); fclose( fpFile ); return FALSE; } // determine if enough room to store file USHORT usCount32KBlock = (sStat.st_size/CRIO_SIZE_32KBLOCK) + (sStat.st_size % CRIO_SIZE_32KBLOCK ? 1 : 0); if ( usCount32KBlock > cDirHeader.m_usCount32KBlockRemaining ) { LogError( CRIO_ERROR_MEMORY, "not enough memory on device to upload '%s'", pszPathFile ); fclose( fpFile ); return FALSE; } // get first four bytes of file which determine mp3 properties UCHAR aucProperty[ 4 ]; if ( fread(aucProperty, sizeof(aucProperty), 1, fpFile) < 1 ) { LogError( CRIO_ERROR_READ, "error reading from file '%s'", pszPathFile ); fclose( fpFile ); return FALSE; } rewind( fpFile ); // point to directory entry that will be used CDirEntry& cDirEntry = m_cDirBlock.m_acDirEntry[ cDirHeader.m_usCountEntry ]; // update directory header if ( !cDirHeader.m_usCountEntry ) { // adjust for dir block ++cDirHeader.m_usCount32KBlockUsed; --cDirHeader.m_usCount32KBlockRemaining; // mark first block as used by directory m_cDirBlock.m_auc32KBlockUsed[ 0 ] = CRIO_ID_32KBLOCK_USED; // first entry in FAT used by directory m_cDirBlock.m_ausFAT[ 0 ] = 0; } ++cDirHeader.m_usCountEntry; cDirHeader.m_usCount32KBlockUsed += usCount32KBlock; cDirHeader.m_usCount32KBlockRemaining -= usCount32KBlock; // find first free 32K block USHORT usPos32KBlockFree = FindFirstFree32KBlock(); if ( usPos32KBlockFree == 0xffff ) { LogError( CRIO_ERROR_CORRUPT, "no free 32K blocks, initialization recommended" ); fclose( fpFile ); return FALSE; } // update directory entry memset( &cDirEntry, 0, sizeof(CDirEntry) ); cDirEntry.m_usPos32KBlock = usPos32KBlockFree; cDirEntry.m_usCount32KBlock = usCount32KBlock; cDirEntry.m_usSize32KMod = sStat.st_size % CRIO_SIZE_32KBLOCK; cDirEntry.m_lSize = sStat.st_size; cDirEntry.m_lTimeUpload = time( NULL ); cDirEntry.m_aucProperty[ 0 ] = aucProperty[ 3 ]; cDirEntry.m_aucProperty[ 1 ] = aucProperty[ 2 ]; cDirEntry.m_aucProperty[ 2 ] = aucProperty[ 1 ]; cDirEntry.m_aucProperty[ 3 ] = aucProperty[ 0 ]; strncpy( cDirEntry.m_szName, GetFile(pszPathFile), sizeof(cDirEntry.m_szName) ); // create zero initialized temp block UCHAR* paucBlock; ZERONEWBLOCK( paucBlock ); // default return BOOL bResult = FALSE; // process all 32K blocks of file USHORT usPos32KBlockCurrent = cDirEntry.m_usPos32KBlock; USHORT usPos32KBlockPrev = 0xffff; USHORT usPos32KBlockEnd = cDirEntry.m_usCount32KBlock; USHORT usPos32KBlockNext; USHORT usPos32KBlock; for( usPos32KBlock=0; usPos32KBlockm_usPos32KBlock; USHORT usPos32KBlockEnd = pDirEntry->m_usCount32KBlock; USHORT usPos32KBlock; for( usPos32KBlock=0; usPos32KBlockm_usSize32KMod ) iSizeWrite = pDirEntry->m_usSize32KMod; else iSizeWrite = CRIO_SIZE_32KBLOCK; // save block if ( fwrite(paucBlock, iSizeWrite, 1, fpFile) < 1 ) { LogError( CRIO_ERROR_WRITE, "error writing to file '%s'", pszPathFile ); break; } // next block usPos32KBlockCurrent = m_cDirBlock.m_ausFAT[ usPos32KBlockCurrent ]; } // if transfer ok if ( usPos32KBlock == usPos32KBlockEnd ) { // flag as ok bResult = TRUE; // IO outro IOOutro(); } // release temp block DELETEBLOCK( paucBlock ); // close file fclose( fpFile ); return bResult; } rio-1.07.orig/rio.h0100744000175000017500000001304206730234306013132 0ustar vincevince/////////////////////////////////////////////////////////////////////////////// // // rio.h // /////////////////////////////////////////////////////////////////////////////// #ifndef _RIO_ #define _RIO_ // dependencies #include "std.h" // version #define CRIO_ID_VERSION 107 // blocks available on 32M and SE 64M unit #define CRIO_COUNT_32KBLOCKIN32M 1024 #define CRIO_COUNT_32KBLOCKIN64M 2048 // max available 32k blocks #define CRIO_MAX_32KBLOCK 8192 // size of 32k block #define CRIO_SIZE_32KBLOCK 32768 // max directory entries #define CRIO_MAX_DIRENTRY 60 // 32Kblock type #define CRIO_ID_32KBLOCK_USED 0x00 #define CRIO_ID_32KBLOCK_BAD 0x0f #define CRIO_ID_32KBLOCK_FREE 0xff // default io delay #if defined(_WINNT) #define CRIO_TIME_IODELAY_INIT 2000 #define CRIO_TIME_IODELAY_RX 2 #define CRIO_TIME_IODELAY_TX 10 #elif defined(__OS2__) #define CRIO_TIME_IODELAY_INIT 3000 #define CRIO_TIME_IODELAY_RX 0 #define CRIO_TIME_IODELAY_TX 15 #else #define CRIO_TIME_IODELAY_INIT 20000 #define CRIO_TIME_IODELAY_RX 2 #define CRIO_TIME_IODELAY_TX 100 #endif // 32 bit word #if defined(__alpha) typedef int SIGNED32; typedef unsigned int UNSIGNED32; #else typedef long SIGNED32; typedef unsigned long UNSIGNED32; #endif // error id's enum { CRIO_ERROR_ALLOC = 0, CRIO_ERROR_IOPRERM, CRIO_ERROR_CREATEFILE, CRIO_ERROR_DEVICENOTFOUND, CRIO_ERROR_DRIVERVERSION, CRIO_ERROR_TXBLOCKRETRY, CRIO_ERROR_RXBLOCKRETRY, CRIO_ERROR_CORRUPT, CRIO_ERROR_FILENOTFOUND, CRIO_ERROR_INVALIDFILEPOSITION, CRIO_ERROR_MAXDIRENTRY, CRIO_ERROR_MEMORY, CRIO_ERROR_OPEN, CRIO_ERROR_STAT, CRIO_ERROR_READ, CRIO_ERROR_WRITE, CRIO_ERROR_INTERRUPTED, }; /////////////////////////////////////////////////////////////////////////////// // enable byte align structs #pragma pack( 1 ) // directory header struct CDirHeader { USHORT m_usCountEntry; USHORT m_usCount32KBlockAvailable; USHORT m_usCount32KBlockUsed; USHORT m_usCount32KBlockRemaining; USHORT m_usCount32KBlockBad; SIGNED32 m_lTimeLastUpdate; USHORT m_usChecksum1; USHORT m_usChecksum2; char m_acNotUsed2[ 2 ]; USHORT m_usVersion; char m_acNotUsed3[ 512 - 22 ]; }; // directory entry struct CDirEntry { USHORT m_usPos32KBlock; USHORT m_usCount32KBlock; USHORT m_usSize32KMod; SIGNED32 m_lSize; char m_acNotUsed[ 5 ]; SIGNED32 m_lTimeUpload; UCHAR m_aucProperty[ 4 ]; char m_acNotUsed3[ 5 ]; char m_szName[ 128 - 28 ]; }; // directory block struct CDirBlock { CDirHeader m_cDirHeader; CDirEntry m_acDirEntry[ CRIO_MAX_DIRENTRY ]; UCHAR m_auc32KBlockUsed[ CRIO_MAX_32KBLOCK ]; USHORT m_ausFAT[ CRIO_MAX_32KBLOCK ]; }; // end 512 byte block struct CEnd512ByteBlock { UNSIGNED32 m_ulPos512ByteBlockNextMult256; UCHAR m_ucPos8192KBlockNext1; UCHAR m_ucPos8192KBlockNext2; UNSIGNED32 m_ulPos512ByteBlockPrevMult256; UCHAR m_ucPos8192KBlockPrev1; UCHAR m_ucPos8192KBlockPrev2; USHORT m_usChecksum; USHORT m_usPos32KBlockPrevMult256; }; // disable byte align #pragma pack() /////////////////////////////////////////////////////////////////////////////// // rio class class CRio { protected: // directory block CDirBlock m_cDirBlock; // error str char m_szError[ 128 ]; // external flash 32K block count UINT m_uiCount32KBlockAvailableExternal; // io port delay's long m_lTimeIODelayInit; long m_lTimeIODelayTx; long m_lTimeIODelayRx; // port constants int m_iPortBase; int m_iPortData; int m_iPortStatus; int m_iPortControl; // error int m_iIDError; // internal/external flash ram flag BOOL m_bUseExternalFlash; // special edition flag BOOL m_bSpecialEdition; // operations void LogError( int iType, const char* pszFormat, ... ); UINT FindFirstFree32KBlock( void ); UINT CalculateChecksum1( void ); UINT CalculateChecksum2( void ); BOOL WaitInput( int iValue ); BOOL WaitAck( void ); UINT GetDataByte( void ); BOOL IOIntro( void ); BOOL IOOutro( void ); BOOL Tx32KBlockRetry( void* pv, UINT uiPos32KBlock, UINT uiPos32KBlockPrev, UINT uiPos32KBlockNext ); BOOL Tx32KBlock( void* pv, UINT uiPos32KBlock, UINT uiPos32KBlockPrev, UINT uiPos32KBlockNext ); BOOL Rx32KBlockRetry( void* pv, UINT uiPos32KBlock ); BOOL Rx32KBlock( void* pv, UINT uiPos32KBlock ); BOOL MarkBadBlocks( BOOL (*pfProgress)(int iPos, int iCount) ); public: // set/unset void Unset( void ); BOOL Set( int iPortBase ); // constructors/destructors CRio(); ~CRio(); // retrieval long GetIODelayInit( void ) { return m_lTimeIODelayInit; } long GetIODelayTx( void ) { return m_lTimeIODelayTx; } long GetIODelayRx( void ) { return m_lTimeIODelayRx; } CDirBlock& GetDirectoryBlock( void ) { return m_cDirBlock; } int GetErrorID( void ) { return m_iIDError; } char* GetErrorStr( void ) { return m_szError; } BOOL GetUseExternalFlashStatus( void ) { return m_bUseExternalFlash; } BOOL GetSpecialEditionStatus( void ) { return m_bSpecialEdition; } // operations void SetIODelayInit( long lTime ) { m_lTimeIODelayInit = lTime; } void SetIODelayTx( long lTime ) { m_lTimeIODelayTx = lTime; } void SetIODelayRx( long lTime ) { m_lTimeIODelayRx = lTime; } void UseExternalFlash( BOOL bUseExternalFlash ); BOOL CheckPresent( void ); CDirEntry* FindFile( char* pszFile ); BOOL Initialize( BOOL bMarkBadBlock, BOOL (*pfProgress)(int iPos, int iCount) ); BOOL RemoveFile( char* pszFile ); BOOL RemoveAllFiles( void ); BOOL SetFileOrder( UINT* pauiPosOrder, UINT uiCount ); BOOL TxDirectory( void ); BOOL RxDirectory( void ); BOOL TxFile( char* pszPathFile, BOOL (*pfProgress)(int iPos, int iCount) ); BOOL RxFile( char* pszPathFile, BOOL (*pfProgress)(int iPos, int iCount) ); }; #endif // _RIO_ rio-1.07.orig/rio.txt0100744000175000017500000002530006730234306013522 0ustar vincevince Diamond Rio Protocol Investigation - The Snowblind Alliance (c) 1999 -------------------------------------------------------------------- Last updated 11/03/99 Author jab@cix.co.uk Contents -------- 1. Hardware used to determine protocol 2. Software tools used to determine protocol 3. PC parallel port access 4. Directory block layout 5. Transmitting and receiving data to the device 6. Block usage table and FAT 1. Hardware used to determine protocol ------------------------------------- The following hardware was used in determining the protocol used between a PC and the Diamond Rio... HP VectraXA P233 32M running MS Win98 Diamond Rio PMP300 2. Software tools used to determine protocol -------------------------------------------- A Win98 VxD was put together which intercepted and logged all I/O traffic between the PC (running the 'Rio Manager' software) and the Rio. This data was then used to determine the protocol used to upload and download data to the device. 3. PC parallel port access -------------------------- The following ports are used (using the default 0x378). 0x378 Parallel Port Data 0x379 Parallel Port Status 0x37a Parallel Port Control Data to be sent from the host to the Rio is written to this port as normal 8 bit data. The host then writes a value to the control port. This value is made up using a alternating bit 3 (used as a data latch) which informs the Rio that data is present in the data port and is waiting to be retrieved. Data to be sent from the Rio to the host is done using the status port. Only the top 4 bits are used so a single byte sent to the host is split up into 2 nibbles which are sent with their bits reversed. Also because bit 7 of the status port is an inversion of the +busy line (pin 11) this bit needs to be inverted. Below is a example of how the host would read the nibble pair from the Rio to make up a single data byte. UCHAR ucIn, ucRx; // get first nibble ucRx = INPORT( ParallelPortStatus ); ucIn = ((ucRx & 0xf0) ^ 0x80) >> 4; // get second nibble ucRx = INPORT( ParallelPortStatus ); ucIn |= (ucRx & 0xf0) ^ 0x80; // reverse all bits in byte ucIn = BitReverse( ucIn ); The Control port is used to latch data present in the data port and to send commands to the Rio. 4. Directory block layout ------------------------- The first 32K on the Rio is dedicated to the directory block which contains the directory header, directory entries and the file allocation table (FAT) used by he Rio. Ammending the directory block is all that is required to delete a file, rename a file or change the playlist order. The layout of the 32K directory block is as follows... Description Offset Size ----------------------------------------------- directory header 0 512 directory entries (60*128) 512 7680 32K block used flags 8192 8192 FAT (8192*sizeof(short)) 16384 16384 ----- total 32768 Directory Header ---------------- The CDirHeader class represents the directory header. A description of the members are as follows... USHORT m_usCountEntry; ---------------------- Number of files currently on the device. USHORT m_usCount32KBlockAvailable; ---------------------------------- Number of 32K blocks available on flash ram. USHORT m_usCount32KBlockUsed; ----------------------------- Number of 32K blocks currently used by directory block and files or which are marked as bad. USHORT m_usCount32KBlockRemaining; ---------------------------------- Number of 32K blocks not is use or marked as bad. USHORT m_usCount32KBlockBad; ---------------------------- Number 32K blocks marked as bad. long m_lTimeLastUpdate; ----------------------- The Rio Manager software updates this with the current time ( taken from time(NULL) ) whenever data has been uploaded to the device. USHORT m_usChecksum1; --------------------- Checksum of the directory header only. USHORT m_usChecksum2; --------------------- Checksum of everything in the directory block except the directory header. Note that because m_usChecksum2 is part of the directory header it must be calculated first before calculating m_usChecksum1. char m_acNotUsed2[ 2 ]; ----------------------- Unknown. Rio Manager software sets these to 0xff. The Rio utility on the otherhand sets them to 0x00. USHORT m_usVersion; ------------------- Rio manager v1.00 doesn't use this value. Rio manager v1.01 expects this value to be 0x0100 otherwise it think's a earlier version has been used to update the device and will therefore reformat the device. The Rio utility sets this value to 0x0100 so both v1.00 and v1.01 of the Rio manager software will recognize the directory. char m_acNotUsed3[ 512 - 22 ]; ------------------------------ Always seems to be 0. Directory Entries ----------------- The CDirEntry class represents a directory entry. Each directory entry is 128 bytes long. The maximum number of directory entries and therefore files which can be uploaded to the device is 60. A description of the members are as follows... USHORT m_usPos32KBlock; ----------------------- Position of the first 32K where data for this file is stored. USHORT m_usCount32KBlock; ------------------------- Number of 32K blocks taken up by the file. USHORT m_usSize32KMod; ---------------------- Number of bytes in the last 32K block. If the filesize is divisible by 32K then this value is 0. long m_lSize; ------------- File size. The duration of a track as displayed by the device is calculated using the filesize and the properties. char m_acNotUsed[ 5 ]; ---------------------- Unknown. long m_lTimeUpload; ------------------- Upload time ( taken from time(NULL) ). char m_aucProperty[ 4 ]; ------------------------ The files audio property (bits per sample, sample rate...) taken from the first four bytes of the audio file. char m_acNotUsed3[ 5 ]; ----------------------- Always seems to be filled with 0. char m_szName[ 128 - 28 ]; -------------------------- File name. 5. Transmitting and receiving data to the device ------------------------------------------------ Although the directory header and directory entries use references to 32K blocks, data is tx'ed and rx'ed in 512 + 16 byte blocks. When uploading data the extra 16 bytes contains information about the location of the previous and next 512 byte block. I assume this information is used by the device so it knows which 512 block of audio to goto when seeking forwards or backwards. To send or receive data a series of bytes which indicate the upload/download command and a 512 byte offset is sent to the device. Data is then received or transmitted to the device. If sending data the additional 16 bytes (described above) must be sent. If receiving data the additional 16 bytes (which can be ignored) must be received. Although the Rio manager software does not allow you to upload non-mp3 files or to download files from the device it is possible with the Rio utility. 6. Block usage table and FAT ---------------------------- The directory block contains an array of 8192 bytes which indicate which 32K blocks are in use or marked as bad. 0x00 Indicates that the block is ok and in use. 0x0f Indicates that the block is bad and should therefore not be used. 0xff Indicates that the block is ok and is free. Also in the directory block there is an array of 8192 16-bit values which are used to determine the next 32K audio block in use. A 0 signifies that it is the last 32K block. Investigation shows that the above two tables are not used by the device for playback as information about the next audio block to play is sent in the extra 16 bytes following a 512 byte upload (see above). This means that the above tables are used as a means of block management by the host software only and can therefore be organized differently and/or used to store other information. rio-1.07.orig/rioioctl.h0100744000175000017500000000133606730234306014170 0ustar vincevince/////////////////////////////////////////////////////////////////////////////// // // rioioctl.h // /////////////////////////////////////////////////////////////////////////////// // Device type #define RIOIO_ID_DEVICE 40000 #define RIOIO_IOCTL_GETVERSION CTL_CODE( RIOIO_ID_DEVICE, 0x900, METHOD_BUFFERED, FILE_READ_ACCESS ) #define RIOIO_IOCTL_READ CTL_CODE( RIOIO_ID_DEVICE, 0x901, METHOD_BUFFERED, FILE_READ_ACCESS ) #define RIOIO_IOCTL_WRITE CTL_CODE( RIOIO_ID_DEVICE, 0x902, METHOD_BUFFERED, FILE_WRITE_ACCESS ) #define RIOIO_IOCTL_READBLOCK CTL_CODE( RIOIO_ID_DEVICE, 0x903, METHOD_BUFFERED, FILE_WRITE_ACCESS ) #define RIOIO_IOCTL_WRITEBLOCK CTL_CODE( RIOIO_ID_DEVICE, 0x904, METHOD_BUFFERED, FILE_WRITE_ACCESS ) rio-1.07.orig/std.h0100744000175000017500000000125406730234306013135 0ustar vincevince////////////////////////////////////////////////////////////////////////////// // // std.h // ////////////////////////////////////////////////////////////////////////////// #if defined(__OS2__) #define INCL_DOSMISC #define INCL_BASE #include #define _STD_ #endif #ifndef _STD_ #define _STD_ #ifndef TRUE #define TRUE (1==1) #endif #ifndef FALSE #define FALSE (1==0) #endif #ifndef BOOL typedef int BOOL; #endif #ifndef CBOOL typedef char CBOOL; #endif #ifndef SZERROR #define SZERROR sys_errlist[errno] #endif typedef unsigned char UCHAR; typedef unsigned short USHORT; typedef unsigned int UINT; typedef unsigned long ULONG; #endif // _STD_ rio-1.07.orig/win9x.mak0100744000175000017500000000060706730234306013743 0ustar vincevince############################################################################### # # RIO utility makefile for MSVC++ v5 running on Win95/98 # # Ashpool Systems (c) 1999 # ############################################################################### all: rio.exe rio.exe: app.cpp rio.cpp cl /Ferio.exe app.cpp rio.cpp /link setargv.obj clean: del rio.exe del app.obj del rio.obj rio-1.07.orig/winnt.mak0100744000175000017500000000060506730234306014022 0ustar vincevince############################################################################### # # RIO utility makefile for MSVC++ v5 running on WinNT v4.0 # # Ashpool Systems (c) 1999 # ############################################################################### all: rio.exe rio.exe: app.cpp rio.cpp cl /Ferio.exe /D "_WINNT" app.cpp rio.cpp /link setargv.obj clean: del rio.exe del *.obj rio-1.07.orig/CREDITS0100744000175000017500000000172006746045540013217 0ustar vincevinceAcknowledgments =============== The following people especially contributed to version 1.07 of the Rio utilities, many thanks to them and all others who contributed. Rio 64M SE (Special Edition) Support (Martin Sjolin martin@sjolin.ch). FreeBSD support (Dermot McNally ) BSDI support (Steve Schultz sms@moe.sbsd.com). OS/2 support (Bob Pesner bpesner@pcdialogs.com). Playlist support comments and blank lines (Tim Hogard thogard@abnormal.com). Directory listing now shows sample frequency and bit rate of each file (Bernhard Nebel nebel@informatik.uni-freiburg.de) Faster detection of device (Harald Niesche hn@mind.de). IO delays for initialization, tx and rx can be specified on command line(Bob Pesner bpesner@pcdialogs.com). An extra special thanks to "Mark B. Elrod" for providing a 64mb Rio for us - without this, we would have been unable to test and tweak the 64mb support. rio-1.07.orig/gpl.txt0100744000175000017500000004312706745055562013535 0ustar vincevince GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 19yy This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19yy name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License.