Пример #1
0
/*********************************************************************************************************
** Function name: isData
** Descriptions:  if get data?
*********************************************************************************************************/
bool LightCom::isData()
{
    if(state == STATE_STOP)
    {
#if __DEBUG
        __PRINTLN("get in is data! ");
        __PRINT("rawLen = ");__PRINTLN(rawLen);

        __PRINTLN("raw: ");
        for(int i = 0; i<rawLen; i++)
        {
            __PRINT(rawBuf[i]);
            __PRINT("\t");
        }
        __PRINTLN();
#endif
        if((rawLen)%9 == 0)
        {
#if __DEBUG
            __PRINTLN("GET GOOD DATA");
#endif
            return 1;
        }
        else
        {
            clear();
        }
    }
    return 0;
}
Пример #2
0
/**
Implementation of pure virtual function.
@see    MWTCacheInterface::ReadL()
*/
void CDynamicDirCache::ReadL(TInt64 aPos, TInt aLength, TDes8& aDes)
    {
#ifdef _DEBUG
    if(iCacheDisabled)
        {
        // cache is disabled for debug purposes
        __PRINT(_L("CDynamicDirCache disabled"));
        User::LeaveIfError(iDrive.ReadNonCritical(aPos, aLength, aDes));
        return;
        }
#endif //_DEBUG

    aDes.Zero();
    const TUint32 PageSz = iPageSizeInBytes;//-- cache page size

    TInt64 pageStartMedPos = CalcPageStartPos(aPos);
    const TUint32 bytesToPageEnd = (TUint32)(pageStartMedPos + PageSz - aPos); //-- number of bytes from aPos to the end of the page

//    __PRINT5(_L("CDynamicDirCache::ReadL: aPos=%lx, aLength=%x, page:%lx, pageSz:%x, bytesToPageEnd=%x"), aPos, aLength, pageStartMedPos, PageSz, bytesToPageEnd);
    // if all data needed is on a single page
    if((TUint32)aLength <= bytesToPageEnd)
        {
        ReadDataFromSinglePageL(aPos, aLength, aDes);
        }
    // or data to be read cross cache page boundary or probably we have more than 1 page to read
    else
        {
        __PRINT(_L("CDynamicDirCache::ReadL() CROSS PAGE!"));
        TUint32 dataLen(aLength);   //-- current data length
        TInt64  currMediaPos(aPos); //-- current media position

        //-- 1. read data that are already in the current page
        ReadDataFromSinglePageL(currMediaPos, bytesToPageEnd, aDes);
        dataLen -= bytesToPageEnd;
        currMediaPos += bytesToPageEnd;

        TPtr8 dataNext = aDes.MidTPtr(aDes.Length());

        //-- 2. read whole pages of data
        while (dataLen >= PageSz)
            {
            //-- find out if currMediaPos is in cache. If not, find a spare page and read data there
            ReadDataFromSinglePageL(currMediaPos, PageSz, dataNext);
            currMediaPos += PageSz;
            dataLen -= PageSz;
            dataNext = dataNext.MidTPtr(dataNext.Length());
            }

        //-- 3. read the rest of the data
        if(dataLen > 0)
            {
            ReadDataFromSinglePageL(currMediaPos, dataLen, dataNext);
            }
        } //else((TUint32)aLength <= bytesToPageEnd)
    }
Пример #3
0
//===================Main function=================
int main(int argc, char* argv)
{
	int buf_len;
	char main_buffer[MAX_MAIN_BUFFER];
	KConnectionManager::Initialize();
    KConnectionManager km = KConnectionManager();
	KConnection* main_con = km.create_con(MAIN_PORT);
	KLobby lobby = KLobby(&km);
    //Handle signal
    signal(SIGINT, TerminalHandler);
    //Debug memory leak
#ifdef MEMORY_LEAK
    _CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_FILE | _CRTDBG_MODE_WNDW );
    _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
#endif//MEMORY_LEAK

	sockaddr remote_addr;
	while(Running) {//MainLoop
 		km.check(1,0);
	    if (main_con->has_data()) {
			//Reinitialize buffer and len
			buf_len = MAX_MAIN_BUFFER;
			memset(main_buffer, 0, sizeof(main_buffer));
 			memset(&remote_addr, 0, sizeof(remote_addr));	
			//Recv data
			buf_len = main_con->recv_data(main_buffer, buf_len, false);
			main_con->get_raddr(&remote_addr);
			if (strncmp("PING", main_buffer, MAX_MAIN_BUFFER) == 0) {//Echo message
				//TODO:Send "PONG"
			}
			else if (strncmp("HELLO", main_buffer, 5) == 0) {
				if (strncmp("0.83", main_buffer + 5, MAX_MAIN_BUFFER - 5) == 0) {
					//XXX:Rember to delete user and game at list
					KUser* nuser = lobby.new_user();
					__PRINT("Port:%d\n", nuser->get_port());
					snprintf(main_buffer, MAX_MAIN_BUFFER, "HELLOD00D%i", nuser->get_port());
					main_con->send(main_buffer,sizeof(main_buffer));
				}
				else {
					//Version error
					//TODO:Send "VER"
				}
			}
			else {
				printf("Got an unexcept data:%s", main_buffer);		
			}
			__PRINT("Recvdata:%s\n", main_buffer);		
		}
	lobby.tick();
	}
    km.Release();
	return 0;
}
Пример #4
0
//-------------------------------------------------------------------------------------------------------------------
void Dump_TLDFormatInfo(const TLDFormatInfo& aInfo)
{
    (void)aInfo;
#ifdef _DEBUG
    __PRINT(_L("----- TLDFormatInfo dump:"));
    __PRINT1(_L("iCapacity:%d"), aInfo.iCapacity);
    __PRINT1(_L("iSectorsPerCluster:%d"), aInfo.iSectorsPerCluster);
    __PRINT1(_L("iSectorsPerTrack:%d"), aInfo.iSectorsPerTrack);
    __PRINT1(_L("iFATBits:%d"), aInfo.iFATBits);
    __PRINT1(_L("iReservedSectors:%d"), aInfo.iReservedSectors);
    __PRINT1(_L("iFlags:%d"), aInfo.iFlags);
    __PRINT(_L("-----"));
#endif
}
Пример #5
0
void Object_increaseA( Object *object, int value )
{
	//__DEBUG(" Increased value by %d", value );
	object->propertyA += value;
	
	__PRINT( "Value of object's property A with dboid <%s> is now: %d", object->databaseId, object->propertyA );
}
Пример #6
0
/**
Dump cache information, only enabled in debug mode.
@see CDynamicDirCache::Control()
*/
void CDynamicDirCache::Info() const
    {
    __PRINT(_L("======== CDynamicDirCache::Info ========="));
    const TUint32 SegmentSizeInBytesLog2 = CCacheMemoryManagerFactory::CacheMemoryManager()->SegmentSizeInBytesLog2();
    // page size
    __PRINT1(_L("=== Pages size:               [%d Bytes]"), iPageSizeInBytes);
    __PRINT1(_L("=== Segment size:             [%d Bytes]"), 1 << SegmentSizeInBytesLog2);

    // data size:
    __PRINT1(_L("=== Min data size:            [%d Bytes]"), iMinSizeInPages << iPageSizeLog2);
    __PRINT1(_L("=== Max data size:            [%d Bytes]"), iMaxSizeInPages << iPageSizeLog2);

    // memory size:
    const TUint32 pageMemSizeLog2 = iPageSizeLog2 > SegmentSizeInBytesLog2 ? iPageSizeLog2 : SegmentSizeInBytesLog2;
    __PRINT1(_L("=== Min memory size:          [%d Bytes]"), iMinSizeInPages << pageMemSizeLog2);
    __PRINT1(_L("=== Max memory size:          [%d Bytes]"), iMaxSizeInPages << pageMemSizeLog2);

    // reserved pages
    __PRINT1(_L("=== Number of pages reserved: [%d]"), iMinSizeInPages);
    __PRINT1(_L("=== Reserved memory:          [%d Bytes]"), (iMinSizeInPages * PageSizeInSegs()) << SegmentSizeInBytesLog2);
    // locked page num
    __PRINT1(_L("=== Number of pages locked:   [%d]"), iLockedQCount);
    __PRINT1(_L("=== Locked memory:            [%d Bytes]"), (iLockedQCount * PageSizeInSegs()) << SegmentSizeInBytesLog2);
    // unlocked page num
    __PRINT1(_L("=== Number of pages unlocked: [%d]"), iUnlockedQCount);
    __PRINT1(_L("=== Unlocked memory:          [%d Bytes]"), (iUnlockedQCount * PageSizeInSegs()) << SegmentSizeInBytesLog2);
    }
Пример #7
0
/*
    Get all user data in current lobby
*/
int KLobby::get_UData(unsigned char* buffer, int* len)
{
	unsigned char* result;
	KUser* cur_user;
    KListNode<KUser*>* p_node;
	int ptr = 0;//pointer
	if (buffer == NULL) {
        __PRINT("[KLoby::get_UData] Buffer ptr error", NULL);
        return 0;
	}
	else {
		result = buffer;
	}
	KList<KUser*>::iterator it = m_userlist.begin();
	while ((p_node = it.next()) != 0) {
		int dl = 0;//data len
        cur_user = p_node->m_data;
        if (cur_user->get_status() != 2) {//not connecting
		    cur_user->toData(result + ptr, &dl);
		    ptr += dl;
        }
	}
	*len = ptr;
	return 1;
}
Пример #8
0
TInt TFsCloseObject::DoRequestL(CFsRequest* /*aRequest*/)
//
//
//
	{
	__PRINT(_L("TFsCloseObject::DoRequestL()"));
	return(KErrNone);
	}
Пример #9
0
/**
    Read and validate the boot sector.
    If there is an error in reading the main boot sector (sec:0) or it is invalid, tries to read backup boot sector from sec:6.
    Flag iMainBootSecValid indicates the validity of the main boot sector. if it is false, but ret. value is KErrNone, it means that
    the backup boot sector was used and it is valid.

    @param      aBootSector reference to the boot sector object to be read.
    @param      aDoNotReadBkBootSec if true, there won't be an attempt to read backup sector
    @return     standard error code.

*/
TInt CFatMountCB::ReadBootSector(TFatBootSector& aBootSector, TBool aDoNotReadBkBootSec/*=EFalse*/)
    {
    iMainBootSecValid = EFalse; 

    //-- read main boot sector from the sector 0
    TInt nRes = DoReadBootSector(KBootSectorNum << KDefSectorSzLog2, aBootSector); 
    if(nRes == KErrNone)
        {
        if(aBootSector.IsValid())
            {
            iMainBootSecValid = ETrue; //-- main boot sector is valid, everything is OK
            return KErrNone;
            }
        else
            {
            __PRINT(_L("MainBoot Sector is invalid! dump:\n"));
            aBootSector.PrintDebugInfo();
            nRes = KErrCorrupt;
            }
        }

    ASSERT(nRes!= KErrNone && !iMainBootSecValid);

    if(aDoNotReadBkBootSec)
        return nRes;

    //-- main boot sector is invalid, try backup one (it might not present at all) 
    __PRINT(_L("Using backup boot sector...\n"));
    nRes=DoReadBootSector(KBkBootSectorNum << KDefSectorSzLog2, aBootSector); 
    if(nRes == KErrNone )
        {
        if(aBootSector.IsValid())
            return KErrNone; //-- main boot sector is bad, but backup one is OK
        else
            {//-- backup boot sector is invalid
            __PRINT(_L("Backup Sector is invalid! dump:\n"));    
            aBootSector.PrintDebugInfo();
            nRes = KErrCorrupt;
            }
        }
    
    //-- can't read boot sectors, or both are invalid
    return nRes;
    }
Пример #10
0
/**
Dump cache content, only enabled in debug mode.
@see CDynamicDirCache::Control()
*/
void CDynamicDirCache::Dump()
    {
    __PRINT(_L("======== CDynamicDirCache::Dump ========="));
    if (!iLockedQ.IsEmpty())
        {
        TDblQueIter<TDynamicDirCachePage> q(iLockedQ);
        q.SetToFirst();
        TInt i = 0;
        while((TDynamicDirCachePage*)q)
            {
            TDynamicDirCachePage* pP = q++;
            __PRINT3(_L("=== CDynamicDirCache::iLockedQ\t[%4d](pos=%lx, size=%d)"), i++, pP->StartPos(), pP->PageSizeInBytes());
            }
        }
    if (!iUnlockedQ.IsEmpty())
        {
        TDblQueIter<TDynamicDirCachePage> q(iUnlockedQ);
        q.SetToFirst();
        TInt i = 0;
        while((TDynamicDirCachePage*)q)
            {
            TDynamicDirCachePage* pP = q++;
            __PRINT3(_L("=== CDynamicDirCache::iUnlockedQ\t[%4d](pos=%lx, size=%u)"), i++, pP->StartPos(), pP->PageSizeInBytes());
            }
        }
    __PRINT2(_L("=== CDynamicDirCache::iActivePage\t[*](pos=%lx, size=%u)"), iActivePage->StartPos(), iActivePage->PageSizeInBytes());

    if (iLookupTable.Count())
        {
        TInt i = 0;
        THashSetIter<TLookupEntry> iter(iLookupTable);
        TLookupEntry* pEntry;
        pEntry = (TLookupEntry*) iter.Next();
        while(pEntry)
            {
            TDynamicDirCachePage* pP = pEntry->iPage;
            __PRINT3(_L("=== CDynamicDirCache::iLookupTable\t[%4d](pos=%lx, size=%u)"), i++, pP->StartPos(), pP->PageSizeInBytes());
            pEntry = (TLookupEntry*) iter.Next();
            };
        }
    __PRINT(_L("===========================================\n"));
    }
Пример #11
0
TInt TFsCloseObject::Complete(CFsRequest* aRequest)
//
//
//
	{
	__PRINT(_L("TFsCloseObject::Complete()"));
	CFsDispatchObject* pO=(CFsDispatchObject*)aRequest->ScratchValue();
	// set CFsDispatchObject::iRequest to NULL since request will be deleted in Free()
	pO->iRequest=NULL;
	pO->DoClose();
	return(KErrNone);
	}
Пример #12
0
/**
    Close all objects that were created in the main file server thread.
    For sync. drives all objects must be closed in the main file server thread, because
    they are created in this thread, as soon as all synch. requests are processed there.
*/
void CFsObjectIx::CloseMainThreadObjects()
	{
	__ASSERT_DEBUG(FsThreadManager::IsMainThread(),Fault(EObjectIxMainThread));
	__PRINT(_L("CFsObjectIx::CloseThreadObjects()"));
    
	Lock();
	// We have to be very careful here. Calling Close() on the objects in the array
	// may result in other entries being removed from the array before we delete
	// them here, and may result in the array being ReAlloc()ed, corrupting the removed
	// entries, hence we must check the iHighWaterMark value each time round the loop.
	TInt i=-1;
	while(++i<iHighWaterMark)
		{
		SFsObjectIxRec* pS=iObjects+i;
		CFsObject *pO=pS->obj;
		if (pO && pO->IsCorrectThread())
			{
			// invalidate entry before closing it
			pS->obj=NULL;
			pO->Close();	
			}
		}
	Unlock();
	}
Пример #13
0
/**
    Open the device and do some initalisation work.
    
    @param  aParams device parameters
    @return Epoc error code, KErrNone if everything is OK
*/
TInt CWinImgFileDevice::Connect(const TMediaDeviceParams& aParams)
{
    __PRINT(_L("#-- CWinImgFileDevice::Connect()"));    
    
    if(!aParams.ipDevName)
    {
        __LOG(_L("#-- CWinImgFileDevice::Connect() device name is not set!"));    
        return KErrBadName;
    }
    __PRINTF(aParams.ipDevName);
    ASSERT(!HandleValid());

    //-- 1. try to locate an image file by given name.
    WIN32_FIND_DATAA wfd;
    iDevHandle = FindFirstFileA(aParams.ipDevName, &wfd);

    const TBool ImgFileAlreadyExists = HandleValid(iDevHandle);
    
    FindClose(iDevHandle);
    iDevHandle = NULL;
    
    //-- sector size we will use within image file
    const TUint32   sectorSizeToUse = (aParams.iDrvGeometry.iBytesPerSector == 0) ? KDefaultSectorSz : aParams.iDrvGeometry.iBytesPerSector; 
          TUint32   fileSzInSectorsToUse = 0;

    const TUint32   reqSizeSec = aParams.iDrvGeometry.iSizeInSectors; //-- required size in sectors
    const DWORD     dwAccessMode = (aParams.iReadOnly) ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE;  

    if(ImgFileAlreadyExists)
    {//-- if the image file already exists, try to open it and optionally adjust its size
        const TInt64    ImgFileSize = MAKE_TINT64(wfd.nFileSizeHigh, wfd.nFileSizeLow);
        const TUint32   ImgFileSectors = (TUint32)(ImgFileSize / sectorSizeToUse);
        const TBool     ImgFileIsRO = wfd.dwFileAttributes & FILE_ATTRIBUTE_READONLY;
        
        DWORD dwFileCreationMode = 0;
        TBool bNeedToAdjustFileSize = EFalse;

        if(reqSizeSec == 0 || reqSizeSec == ImgFileSectors)
        {//-- the required size is either not specified (auto) or the same as the existing file has.
         //-- we can just open this file
         dwFileCreationMode = OPEN_EXISTING;
         fileSzInSectorsToUse = ImgFileSectors;
        }
        else
        {//-- we will have to overwrite the image file
            if(ImgFileIsRO)
            {//-- we won't be able to overwrite existing file.
                __LOG(_L("#-- CWinImgFileDevice::Connect() unable to adjust image file size!"));    
                return KErrAccessDenied;
            }

         fileSzInSectorsToUse = reqSizeSec;
         dwFileCreationMode = CREATE_ALWAYS;
         bNeedToAdjustFileSize = ETrue;
        }

        iDevHandle = CreateFileA(aParams.ipDevName,
                                dwAccessMode, 
                                FILE_SHARE_READ,
                                (LPSECURITY_ATTRIBUTES)NULL,
                                dwFileCreationMode,
                                FILE_ATTRIBUTE_NORMAL,
                                NULL);

        if(!HandleValid(iDevHandle))
        {
            const DWORD winErr = GetLastError();
            __LOG1(_L("#-- CWinImgFileDevice::Connect() Error opening/creating file! WinErr:%d"), winErr);
            return MapWinError(winErr);
        }     

        //-- adjust file size if we need
        if(bNeedToAdjustFileSize)
        {
            const TInt64 newFileSize = (TInt64)reqSizeSec * sectorSizeToUse;
            ASSERT(newFileSize);

            LONG  newFSzHi = I64HIGH(newFileSize);
            DWORD dwRes = SetFilePointer(iDevHandle, I64LOW(newFileSize), &newFSzHi, FILE_BEGIN);
            if(dwRes == INVALID_SET_FILE_POINTER || !SetEndOfFile(iDevHandle))
            {
                const DWORD winErr = GetLastError();
                Disconnect();
                __LOG1(_L("#-- CWinImgFileDevice::Connect() unable to set file size! WinErr:%d"), winErr);
                return MapWinError(winErr);
            }
        }

    }
    else //if(ImgFileAlreadyExists)
    {//-- if the image file does not exist or its size differs from required. try to create it
       
        if(reqSizeSec == 0)
        {
            __LOG(_L("#-- CWinImgFileDevice::Connect() The image file doesn't exist ant its size isn't specified!"));    
            return KErrArgument;
        }
       
        fileSzInSectorsToUse = reqSizeSec;

        //-- create a new image file
        iDevHandle = CreateFileA(aParams.ipDevName,
                                GENERIC_READ | GENERIC_WRITE, 
                                FILE_SHARE_READ,
                                (LPSECURITY_ATTRIBUTES)NULL,
                                CREATE_ALWAYS,
                                FILE_ATTRIBUTE_NORMAL,
                                NULL);

        if(!HandleValid(iDevHandle))
        {
            const DWORD winErr = GetLastError();
            __LOG1(_L("#-- CWinImgFileDevice::Connect() can not create file! WinErr:%d"), winErr);
            return MapWinError(winErr);
        }     

        //-- set its size
        const TInt64 newFileSize = (TInt64)reqSizeSec * sectorSizeToUse;
        ASSERT(newFileSize);

        LONG  newFSzHi = I64HIGH(newFileSize);
        DWORD dwRes = SetFilePointer(iDevHandle, I64LOW(newFileSize), &newFSzHi, FILE_BEGIN);
        if(dwRes == INVALID_SET_FILE_POINTER || !SetEndOfFile(iDevHandle))
        {
            const DWORD winErr = GetLastError();
            Disconnect();
            __LOG1(_L("#-- CWinImgFileDevice::Connect() unable to set file size! WinErr:%d"), winErr);
            return MapWinError(winErr);
        }

        //-- if parametrs require a read-only file, reopen it in RO mode, it doesn't make a lot of sense though...
        if(aParams.iReadOnly)
        {
            CloseHandle(iDevHandle);
            iDevHandle = NULL;

            iDevHandle = CreateFileA(aParams.ipDevName,
                                GENERIC_READ , 
                                FILE_SHARE_READ,
                                (LPSECURITY_ATTRIBUTES)NULL,
                                OPEN_EXISTING,
                                FILE_ATTRIBUTE_NORMAL,
                                NULL);

            if(!HandleValid(iDevHandle))
            {
                const DWORD winErr = GetLastError();
                __LOG1(_L("#-- CWinImgFileDevice::Connect() Can't reopen a file in RO mode! WinErr:%d"), winErr);
                return MapWinError(winErr);
            }     
            
        }//if(aParams.iReadOnly)

    }//else if(ImgFileAlreadyExists)
    
    //-- here we must have the image file created/opened and with correct size
    ASSERT(HandleValid());
    ASSERT(sectorSizeToUse);

    if(fileSzInSectorsToUse < KMinMediaSizeInSectors)
    {
        __LOG1(_L("#-- CWinImgFileDevice::Connect() Image file is too small!  sectors:%d"), fileSzInSectorsToUse);
        Disconnect();
        return KErrGeneral;     
    }

    iDrvGeometry.iBytesPerSector = sectorSizeToUse;
    iDrvGeometry.iSizeInSectors  = fileSzInSectorsToUse;
    
    //-- map the image file into memory.
    ASSERT(!HandleValid(ihFileMapping));
    ASSERT(!ipImageFile);
    
    /*
    don't map image file, because it can be > 4G.
    ihFileMapping = CreateFileMapping(Handle(), NULL,
                                      aParams.iReadOnly ? PAGE_READONLY : PAGE_READWRITE,
                                      0, 0, NULL);
    if(HandleValid(ihFileMapping))
    {
    ipImageFile = (TUint8*)MapViewOfFile(ihFileMapping, 
                                         aParams.iReadOnly ? FILE_MAP_READ : FILE_MAP_WRITE,
                                         0,0,0);
    }

    if(!ipImageFile)
    {
        __PRINT1(_L("#-- CWinImgFileDevice::Connect() Error mapping file! WinErr:%d"), GetLastError());
        Disconnect();
        return KErrGeneral;
    }
    */

    return KErrNone;
}
Пример #14
0
/**
    Open the device and do some initalisation work.
    
    @param  aParams device parameters
    @return Epoc error code, KErrNone if everything is OK
*/
TInt CWinVolumeDevice::Connect(const TMediaDeviceParams& aParams)
{
    
    __PRINT(_L("#-- CWinVolumeDevice::Connect()"));    
    
    if(!aParams.ipDevName)
    {
        __LOG(_L("#-- CWinVolumeDevice::Connect() device name is not set!"));    
        return KErrBadName;
    }

    __PRINTF(aParams.ipDevName);
    
    ASSERT(!HandleValid() && ipScratchBuf);

    //-- open the device
    DWORD dwAccess = GENERIC_READ;
    
    if(!aParams.iReadOnly)
        dwAccess |= GENERIC_WRITE;  
    
    iDevHandle = CreateFileA(aParams.ipDevName,
                             dwAccess, 
                             FILE_SHARE_READ,
                             (LPSECURITY_ATTRIBUTES)NULL,
                             OPEN_EXISTING,
                             FILE_ATTRIBUTE_NORMAL,
                             NULL);

    if(!HandleValid())
    {
        __LOG1(_L("#-- CWinVolumeDevice::Connect() Error creating device handle! WinErr:%d"), GetLastError());
        return KErrGeneral;
    }     
    
    //-- find out device geometry
    iMediaType = Unknown;
    iDrvGeometry.iBytesPerSector = KDefaultSectorSz;

    DWORD junk; 

    //-- 1. try to query disk geometry, but it can produce wrong results for partitioned media
    BOOL bResult = DeviceIoControl(Handle(),
                                   IOCTL_DISK_GET_DRIVE_GEOMETRY,
                                   NULL, 0,
                                   ipScratchBuf, KScratchBufSz,
                                   &junk, (LPOVERLAPPED)NULL);

    if(bResult)
    {
        const DISK_GEOMETRY& dg = (const DISK_GEOMETRY&)*ipScratchBuf;
        
        iDrvGeometry.iBytesPerSector = dg.BytesPerSector;
        iMediaType = dg.MediaType;

        __PRINT3(_L("#-- dev geometry: Cyl:%d Heads:%d Sectors:%d"), dg.Cylinders.LowPart, dg.TracksPerCylinder, dg.SectorsPerTrack);    
        __PRINT2(_L("#-- dev geometry: MediaType:%d, bps:%d"), dg.MediaType, dg.BytesPerSector);    

    }
    else
    {
        iMediaType = Unknown;
        iDrvGeometry.iBytesPerSector = KDefaultSectorSz;

        __LOG1(_L("#-- CWinVolumeDevice::Connect() IOCTL_DISK_GET_DRIVE_GEOMETRY WinError:%d !"), GetLastError());
    }

    //-- 1.1 check "bytes per sector" value and how it corresponds to the request from parameters
    if(aParams.iDrvGeometry.iBytesPerSector == 0)
    {//-- do nothing, this parameter is not set in config file, use media's
    } 
    else if(aParams.iDrvGeometry.iBytesPerSector != iDrvGeometry.iBytesPerSector)
    {//-- we can't set "SectorSize" value for the physical media
        __LOG1(_L("#-- CWinVolumeDevice::Connect() can not use 'Sec. Size' value from config:%d !"), aParams.iDrvGeometry.iBytesPerSector);
        Disconnect();
        return KErrArgument;
    }


    ASSERT(IsPowerOf2(BytesPerSector()) && BytesPerSector() >= KDefaultSectorSz && BytesPerSector() < 4096);

    //-- find out partition information in order to determine volume size. 
    bResult = DeviceIoControl(Handle(),
                              IOCTL_DISK_GET_PARTITION_INFO,
                              NULL, 0,
                              ipScratchBuf, KScratchBufSz,
                              &junk, (LPOVERLAPPED)NULL);

    if(!bResult)
    {//-- this is a fatal error
        __LOG1(_L("#-- CWinVolumeDevice::Connect() IOCTL_DISK_GET_PARTITION_INFO WinError:%d !"), GetLastError());
        Disconnect();
        return KErrBadHandle;    
    }

    //-- get partition informaton
    const PARTITION_INFORMATION& pi = (const PARTITION_INFORMATION&)*ipScratchBuf;
    TInt64 volSz = MAKE_TINT64(pi.PartitionLength.HighPart, pi.PartitionLength.LowPart);
    iDrvGeometry.iSizeInSectors = (TUint32)(volSz / iDrvGeometry.iBytesPerSector);
            
    __LOG3(_L("#-- partition size, bytes:%LU (%uMB), sectors:%u"), volSz, (TUint32)(volSz>>20), iDrvGeometry.iSizeInSectors);
   
    //-- check if the media size is set in coonfig and if we can use this setting.
    if(aParams.iDrvGeometry.iSizeInSectors == 0)
    {//-- do nothing, the media size is not set in the ini file, use existing media parameters
    }
    else if(aParams.iDrvGeometry.iSizeInSectors > iDrvGeometry.iSizeInSectors)
    {//-- requested media size in ini file is bigger than physical media, error.
     //-- we can't increase physical media size
    __LOG2(_L("#-- CWinVolumeDevice::Connect() 'MediaSizeSectors' value from config:%d > than physical:%d !"), aParams.iDrvGeometry.iSizeInSectors, iDrvGeometry.iSizeInSectors);
    Disconnect();
    return KErrArgument;
    }
    else if(aParams.iDrvGeometry.iSizeInSectors < iDrvGeometry.iSizeInSectors)
    {//-- settings specify smaller media than physical one, adjust the size
    __PRINT1(_L("#-- reducing media size to %d sectors"), aParams.iDrvGeometry.iSizeInSectors);
    iDrvGeometry.iSizeInSectors = aParams.iDrvGeometry.iSizeInSectors;
    }


    ASSERT(iDrvGeometry.iSizeInSectors > KMinMediaSizeInSectors);
    return KErrNone;
}
Пример #15
0
/**
Set or reset "VolumeClean" (ClnShutBitmask) flag.

@param  aClean if ETrue, marks the volume as clean, otherwise as dirty.
@leave  if write error occured.        
*/
void CFatMountCB::SetVolumeCleanL(TBool aClean) 
    {

	//-- The volume can't be set clean if there are disk access objects opened on it. This precondition must be checked before calling this function
    if(aClean && Locked())
        {
        __PRINT1(_L("#- CFatMountCB::SetVolumeCleanL drive:%d isn't free!"),DriveNumber());
        ASSERT(0);
        User::Leave(KErrInUse);
        return;
        }
    
    if(FatType() == EFat12)
        {//-- Fat12 doesn't support this feature; do nothing other than notify the underlying drive (ignoring any error for now as there's nothing we can do with it)
		(void)LocalDrive()->Finalise(aClean);
        return;
        }

    //-- further read and write will be directly from the CProxyDrive, bypassing FAT cache. 
    //-- this is because CFatTable doesn't allow access to FAT[0] & FAT[1]
    //-- We also need to write data through CProxyDrive, because TDriveInterface has a call back that can call this method

    if(Is32BitFat())
        {//-- Fat32
		__PRINT2(_L("#- CFatMountCB::SetVolumeCleanL, drive:%d, param:%d, FAT32"),DriveNumber(), aClean);
		
        TFat32Entry fatEntry;
        const TInt  KFatEntrySize=sizeof(fatEntry); //-- FAT entry size in bytes
        TPtr8       ptrFatEntry((TUint8*)&fatEntry,KFatEntrySize);
        
        User::LeaveIfError(LocalDrive()->Read(StartOfFatInBytes()+KFatEntrySize, KFatEntrySize, ptrFatEntry)); //read FAT32[1] entry

        const TFat32Entry tmp = fatEntry;
        
        if(aClean)
            fatEntry |= KFat32CleanShutDownMask;  //-- set ClnShutBit flag
        else
            fatEntry &= ~KFat32CleanShutDownMask; //-- reset ClnShutBit flag

        if(tmp != fatEntry)
            {//-- write FAT[1] entry to all available FATs
                for(TUint32 i=0; i<NumberOfFats(); ++i)
                {
                const TInt64 pos = StartOfFatInBytes()+KFatEntrySize+(FatSizeInBytes()*i);
                User::LeaveIfError(LocalDrive()->Write(pos, ptrFatEntry)); //write FAT32[1] entry
                }
            }

        __PRINT2(_L("#- CFatMountCB::SetVolumeCleanL() entry:  %x->%x"), tmp, fatEntry);
        }
    else 
    if(Is16BitFat())
        {//-- Fat16. 
            __PRINT2(_L("#- CFatMountCB::SetVolumeCleanL, drive:%d, param:%d, FAT16"),DriveNumber(), aClean);

            if(FatConfig().FAT16_UseCleanShutDownBit())
                {
            TFat16Entry fatEntry;
            const TInt  KFatEntrySize=sizeof(fatEntry); //-- FAT entry size in bytes
            TPtr8       ptrFatEntry((TUint8*)&fatEntry,KFatEntrySize);
        
            User::LeaveIfError(LocalDrive()->Read(StartOfFatInBytes()+KFatEntrySize, KFatEntrySize, ptrFatEntry)); //read FAT16[1] entry

            const TFat16Entry tmp = fatEntry;
        
            if(aClean)
                fatEntry |= KFat16CleanShutDownMask;  //-- set ClnShutBit flag
            else
                fatEntry &= ~KFat16CleanShutDownMask; //-- reset ClnShutBit flag

            if(tmp != fatEntry)
                {//-- write FAT[1] entry to all available FATs
                for(TUint32 i=0; i<NumberOfFats(); ++i)
                    {
                    const TInt64 pos = StartOfFatInBytes()+KFatEntrySize+(FatSizeInBytes()*i);
                    User::LeaveIfError(LocalDrive()->Write(pos, ptrFatEntry)); //write FAT16[1] entry
                    }
                }
		    
            __PRINT2(_L("#- CFatMountCB::SetVolumeCleanL() entry:  %x->%x"), tmp, fatEntry);    
            }
            else
            {
            __PRINT(_L("#- changing FAT16[1] is disabled in config!"));    
            }
        }
    else
        {//-- must never get here
        ASSERT(0);
        }
    
		//-- Notify the underlying media that the mount is consistent  (ignoring any error for now as there's nothing we can do with it)
		(void)LocalDrive()->Finalise(aClean);


    }
Пример #16
0
//===================Signal handler================
void TerminalHandler(int signal)
{
    __PRINT("Got a terminal signal, stopping\n", NULL);
    Running = false;
}
Пример #17
0
/**
Mount a Fat volume. 

@param aForceMount Flag to indicate whether mount should be forced to succeed if an error occurs
@leave KErrNoMemory,KErrNotReady,KErrCorrupt,KErrUnknown.
*/
void CFatMountCB::MountL(TBool aForceMount)
	{

    const TInt driveNo = Drive().DriveNumber();
    
    __PRINT3(_L("CFatMountCB::MountL() drv:%d, forceMount=%d, RuggedFAT:%d\n"), driveNo, aForceMount, IsRuggedFSys());

    ASSERT(State() == ENotMounted || State() == EDismounted);
    SetState(EMounting);
    SetReadOnly(EFalse);
   
	User::LeaveIfError(CreateDrive(driveNo));


    //-- read FAT configuration parameters from estart.txt
    iFatConfig.ReadConfig(driveNo);

    //-- initialise interface to the low-level drive access
    if(!iDriverInterface.Init(this))
        User::LeaveIfError(KErrNoMemory);    

	//-- get drive capabilities
    TLocalDriveCapsV2Buf capsBuf;
	User::LeaveIfError(LocalDrive()->Caps(capsBuf));
	

    iSize=capsBuf().iSize;
    iRamDrive = EFalse;

    if(capsBuf().iMediaAtt & KMediaAttVariableSize)
    {//-- this is a RAM drive
        UserSvr::UnlockRamDrive();
        iRamDrive = ETrue;
    }

	if(aForceMount)
	{//-- the state is "forcedly mounted", special case. This is an inconsistent state.
        SetState(EInit_Forced);  
    	return;
    }

    //-- read boot sector. If main is damaged, try to use backup one instead if this is not a RAM drive.
    TFatBootSector bootSector;
    User::LeaveIfError(ReadBootSector(bootSector, iRamDrive));


    //-- print out boot sector debug information
    bootSector.PrintDebugInfo();

    //-- determine FAT type by data from boot sector. This is done by counting number of clusters, not by BPB_RootEntCnt
    SetFatType(bootSector.FatType());
    ASSERT(iFatType != EInvalid); //-- this shall be checked in ReadBootSector()
    

    if(bootSector.RootDirEntries() == 0 && !Is32BitFat())
    {//-- FAT types mismatch. BPB_RootEntCnt is 0, which can be only for FAT32, but the number of clusters is less 
     //-- than required for FAT32. Probably this is incorrectly FAT32 formatted media. Put the drive into ReadOnly mode, assuming
     //-- that is FAT32.
        __PRINT(_L("FAT type mismatch! Setting drive to ReadOnly mode for FAT32. \n"));
        SetFatType(EFat32); //-- force FAT type to be FAT32
        SetReadOnly(ETrue);
    }

    //-- store volume UID, it can be checked on Remount
    iUniqueID = bootSector.UniqueID();

    //-- populate volume parameters with the values from boot sector. They had been validated in TFatBootSector::IsValid()
    iVolParam.Populate(bootSector); 
	
    //-- initialize the volume
    InitializeL(capsBuf());
    ASSERT(State()==EInit_R);

    GetVolumeLabelFromDiskL(bootSector);

	__PRINT2(_L("CFatMountCB::MountL() Completed, drv: %d, state:%d"), DriveNumber(), State());
	}
Пример #18
0
/**
Implementation of pure virtual function.
@see    MWTCacheInterface::WriteL()
*/
void CDynamicDirCache::WriteL(TInt64 aPos,const TDesC8& aDes)
    {
#ifdef _DEBUG
    if(iCacheDisabled)
        {
        // cache is disabled for debug purposes
        __PRINT(_L("CDynamicDirCache disabled"));
        User::LeaveIfError(iDrive.WriteCritical(aPos,aDes));
        return;
        }
#endif //_DEBUG

    TUint32 dataLen = aDes.Size();
    const TUint8* pData   = aDes.Ptr();
    const TUint32 PageSz  = iPageSizeInBytes; //-- cache page size

    TInt64 pageStartMedPos = CalcPageStartPos(aPos);
    TUint32 bytesToPageEnd = (TUint32)(pageStartMedPos + PageSz - aPos);

//    __PRINT5(_L("CDynamicDirCache::WriteL: aPos=%lx, aLength=%x, page:%lx, pageSz:%x, bytesToPageEnd=%x"), aPos, dataLen, pageStartMedPos, PageSz, bytesToPageEnd);

    if(dataLen <= bytesToPageEnd)
        {
        WriteDataOntoSinglePageL(aPos, pData, dataLen);
        }
    else
        {
        __PRINT(_L("CDynamicDirCache::WriteL() CROSS PAGE!"));

        //-- Data to be written cross cache page boundary or probably we have more than 1 page to write
        TInt64  currMediaPos(aPos);

        //-- 1. update the current page
        WriteDataOntoSinglePageL(currMediaPos, pData, bytesToPageEnd);

        pData += bytesToPageEnd;
        currMediaPos += bytesToPageEnd;
        dataLen -= bytesToPageEnd;

        //-- 2. write whole pages of data to the cache
        while (dataLen >= PageSz)
            {
            WriteDataOntoSinglePageL(currMediaPos, pData, PageSz);

            pData += PageSz;
            currMediaPos += PageSz;
            dataLen -= PageSz;
            }

        //-- 3. write the rest of the data
        if(dataLen > 0)
            {
            WriteDataOntoSinglePageL(currMediaPos, pData, dataLen);
            }
        }// else(dataLen <= bytesToPageEnd)


    //-- write data to the media
    const TInt nErr = iDrive.WriteCritical(aPos,aDes);
    if(nErr != KErrNone)
        {//-- some serious problem occured during writing, invalidate cache.
        InvalidateCache();
        User::Leave(nErr);
        }
    }
Пример #19
0
/**
    Open a drive for formatting.
*/
TInt FsFormatOpen(CFsRequest* aRequest)
	{
    TDrive& drive = *aRequest->Drive();

	__PRINT1(_L("FsFormatOpen() drv:%d"), drive.DriveNumber());
    
    TInt nMountRes = drive.CheckMount();
    //-- KErrNotReady means that there is no file system mounted on this drive
    //-- KErrInUse means that there are some "disk access" objects, like RFormat or RRawDisk opened on the mount.
    if(nMountRes == KErrNotReady || nMountRes == KErrInUse) 
        {
        __PRINT1(_L("FsFormatOpen() ChkMount:%d"), nMountRes);
        return nMountRes;
        }
    
    const TFormatMode fmtMode = (TFormatMode)aRequest->Message().Int1();
    TName buf;
    TUint32 currFsNameHash = 0; //-- current file system name hash, 0 means "not set"; used during forced FS dismounting

    if((nMountRes == KErrNone) && drive.CurrentMount().LockStatus() < 0)
        {//-- the mount is locked, it has normal objects (files, directories) opened on it. 
        
        //-- if someone is interested in the list of opened files and number of opened directories, compile this code in.
        #ifdef DUMP_OPENED_OBJECTS
            DumpOpenedObjects(drive);
        #endif //DUMP_OPENED_OBJECTS


        if(!(fmtMode & EForceFormat))
            {
            __PRINT(_L("FsFormatOpen() The mount is in use"));
            return KErrInUse;
            }    

        //-- there is a special flag that tells to force media dismounting even if it has files or dirs opened.
        __PRINT(_L("FsFormatOpen() The mount is in use, forcing dismounting!"));

        //-- record currently mounted FS name hash, it may be used after forced dismounting
        drive.CurrentMount().FileSystemName(buf); //-- the iCurrentMount is alive
        currFsNameHash = TVolFormatParam::CalcFSNameHash(buf);

        //-- kill the current mount
        FsThreadManager::LockDrive(drive.DriveNumber());
        TInt nRes = drive.ForceUnmountFileSystemForFormatting();
        FsThreadManager::UnlockDrive(drive.DriveNumber());

        
        switch(nRes)
            {
            case KErrInUse: 
            __PRINT(_L("FsFormatOpen() The mount has clamps! Can't force dismount"));    
            return KErrInUse; //-- there are clamps on this drive - can't dismount

            case KErrNone:
            break;

            default:
            ASSERT(0); //-- unexpected error code
            return nRes;

            };

        if(fmtMode & EQuickFormat)
            {//-- quick format may require the normally mounted FS, make the best effrot to mount it
            nMountRes = drive.CheckMount();
            }
        else
            {//-- this will make the FS mounted by force; for full format it will be quicker
            nMountRes = KErrCorrupt;
            }

        }

	//-- if True, we will need mount (probably specific) file system by force because normal mounting has failed
    TBool bNeedForceMount = (nMountRes != KErrNone); 

    //-- find out if we have optional data structure that describes format parameter
    TUint32 newFsNameHash = 0; //-- file system name hash, may be used for selecting which file system to put onto the volume. 0 means "not specified"

    const TLDFormatInfo*    pLDFormatInfo   = NULL;
    const TVolFormatParam*  pVolFormatParam = NULL;

    __ASSERT_COMPILE(sizeof(TVolFormatParam) >= sizeof(TLDFormatInfo));
    TBuf8<sizeof(TVolFormatParam)> paramBuf;
   
    
    if(fmtMode & ESpecialFormat)  
        {   
        //-- the user has provided format parameters structure.
        //-- IPC argument #2 contains a structure: <TUint32>[optional package descriptor]
        //-- where 1st mandatory TUint32 is a pointer to format counter and the optional additional package is a data structure passed to the filesystem by the client of RFormat
        const TInt desLen = aRequest->GetDesLength(KMsgPtr2);
        ASSERT((TUint32)desLen >= sizeof(TUint32));
    
        const TInt dataPckgLen = desLen - sizeof(TUint32);

        if((TUint32)dataPckgLen > sizeof(TUint32))
            {
            aRequest->ReadL(KMsgPtr2, paramBuf); 
            }
        
        if(dataPckgLen == sizeof(TLDFormatInfo))
            {//-- the user has provided formatting parameters via TLDFormatInfo structure.
            pLDFormatInfo = (const TLDFormatInfo*)(paramBuf.Ptr() + sizeof(TUint32));
            }
        else if(dataPckgLen == sizeof(TVolFormatParam))
            {//-- it's likely to be TVolFormatParam, need to check UId to be sure.
            pVolFormatParam = (const TVolFormatParam*)(const TVolFormatParam*)(paramBuf.Ptr() + sizeof(TUint32));

            if(pVolFormatParam->iUId == TVolFormatParam::KUId)  //-- check the class UID
                {//-- this is the real TVolFormatParam object passed
                newFsNameHash = pVolFormatParam->FSNameHash();
                }
            }
        else if(dataPckgLen >0)
            {//-- parameters data structure has strange length
            return KErrArgument;
            }
    
        }

    //-------------------
    if(!newFsNameHash && currFsNameHash)
        {//-- new file system name isn't specified (default formatting), but the volume had been forcedly dismounted.
         //-- restore the original file system   
        newFsNameHash = currFsNameHash;
        }
    
    if(newFsNameHash)
        {//-- check if the specified FS is already mounted on the volume
        if(!bNeedForceMount)
            {
            drive.CurrentMount().FileSystemName(buf); //-- the iCurrentMount is alive
            }
        else
            { //-- the iCurrentMount can be NULL, use the iFsys - the real file system associated with this drive
            buf = drive.GetFSys()->Name();
            }

        const TUint32 currFSNameHash = TVolFormatParam::CalcFSNameHash(buf);
        if(currFSNameHash == newFsNameHash)
            {//-- no need to do anything, the required FS is already mounted
            newFsNameHash = 0; 
            } 
        }

    if(newFsNameHash) 
        {
        //-- the user has specified some filesystem to be mounted on the volume. Check if this FS is supported at all.
        //-- if it is supported, but some other FS is currently mounted, it will be dismounted and the new one will be forced.
        TInt nRes;
            
        for(TInt cntFS=0; ;++cntFS)
            {
            nRes = drive.FSys().GetSupportedFileSystemName(cntFS, buf); //-- enumerate possible child file systems
            
            if(nRes != KErrNone)
                return KErrNotSupported; //-- the filesystem with the given name (fsNameHash) is not supported.

            if(newFsNameHash == TVolFormatParam::CalcFSNameHash(buf))
                {//-- the filesystem with the given name (fsNameHash) is supported, but some other filesystem can be already mounted
                drive.Dismount();
                bNeedForceMount = ETrue; //-- this will force the desired FS to be mounted
                break;
                }
            }
    
        }//if(fsNameHash) 


    //-- try force mounting the desired file system if it is required
    if(bNeedForceMount)
        {
        const TInt KMaxRetries = 3;
        for(TInt cnt=0; ; ++cnt)
            {
            drive.MountFileSystem(ETrue, newFsNameHash);

            nMountRes = drive.GetReason();
            if(nMountRes == KErrNone || nMountRes == KErrLocked)
                break;
            
            drive.Dismount(); //-- will reset mount retries counter
            
            if(cnt >= KMaxRetries)
                {
                __PRINT1(_L("FsFormatOpen() can't mount FS! res:%d"), nMountRes);    
                return nMountRes;
                }
            }
        }

    ASSERT(nMountRes == KErrNone || nMountRes == KErrLocked);
    
    __ASSERT_DEBUG(drive.CurrentMount().LockStatus()==0, Fault(ESvrFormatOpenFailed));


	TDriveInfo dInfo;
	drive.DriveInfo(dInfo);
	const TInt mediaAtt = dInfo.iMediaAtt;

#if defined(_LOCKABLE_MEDIA)
	if (!(fmtMode & EForceErase) && (mediaAtt & KMediaAttLocked))
		{
		// if attempting to format a locked drive, dismount otherwise subsequent 
		// requests will operate on a mount that has been forcibly mounted (a few lines above)
		CMountCB* pM = &drive.CurrentMount();
		
        if(pM)
			pM->Close();

		drive.MountFileSystem(EFalse);	// clear iCurrentMount
		return KErrLocked;
		}
#endif

	if (!(mediaAtt & KMediaAttFormattable) || (mediaAtt & KMediaAttWriteProtected))
		{
		CMountCB* pM = &drive.CurrentMount();
		
        if(pM)
			pM->Close();

		drive.MountFileSystem(EFalse);
        return KErrAccessDenied;
		}

	//-- instantinate and open CFormatCB object for this drive
    CFormatCB* formatCB=NULL;
	TInt fmtHandle;
    
    TRAPD(ret, formatCB = drive.FormatOpenL(aRequest, fmtHandle, fmtMode, pLDFormatInfo, pVolFormatParam ));

	if (ret!=KErrNone)
		{
		if(formatCB)
			formatCB->Close();

		return ret;
		}

	TPtrC8 pH((TUint8*)&fmtHandle,sizeof(TInt));
	aRequest->WriteL(KMsgPtr3,pH);
	TInt count=100;

	TPtrC8 pCount((TUint8*)&count,sizeof(TInt));
	aRequest->WriteL(KMsgPtr2,pCount);
	aRequest->Session()->IncResourceCount();
	
    return KErrNone;
	}
Пример #20
0
/*********************************************************************************************************
** Function name: Recv
** Descriptions:  get data, return length of data
*********************************************************************************************************/
unsigned char LightCom::Recv(unsigned char *rDta)
{

    int count       = rawLen;
    int count_data  = 0;
    
    unsigned char revData[20];
    
    count_data = (count)/9;     // here
    
    cmpOneZero = COMONE;
    
    for(int i = 0; i<count_data; i++)
    {
        unsigned char tmp = 0;
        for(int j = 1; j<25; j++)
        {
            if(REVOK == checkCrc(&rawBuf[9*i], cmpOneZero, &tmp))
            {
#if __DEBUG
                __PRINTLN("CRC OK");
                __PRINT("tmp = ");
                __PRINTLN(tmp);
#endif
                revData[i+D_DATA] = tmp;
                break;
            }
            else
            {
                if(j%2 == 0)
                {
                    cmpOneZero += j;
                }
                else
                {
                    cmpOneZero -= j;
                }
#if __DEBUG
                __PRINTLN("**********HERE***********");
                __PRINT("cmpOneZero = ");
                __PRINTLN(cmpOneZero);
                __PRINTLN("**********HERE***********");
#endif
            }
        }
    }
    
    revData[D_DATALEN]  = count_data;
    for(int i = 0; i<revData[D_DATALEN]; i++)
    {
        rDta[i] = revData[D_DATA+i];
    }
    
#if __DEBUG
    __PRINT("\r\n*************************************************************\r\n");
    __PRINT("data_len = ");
	__PRINTLN(revData[D_DATALEN]);
    for(int i = 0; i<revData[D_DATALEN]; i++)
    {
        __PRINT(revData[D_DATA+i]);__PRINT("\t");
    }
    __PRINT("\r\n*************************************************************\r\n");
#endif
    clear(); // Receive the next value
    return revData[D_DATALEN];
}