/*----------------------------------------------------------------------------- * Zeichen in Empfangspuffer zurückschreiben */ uint8_t SioUnRead(int handle, uint8_t *pBuf, uint8_t bufSize) { unsigned int free; unsigned int used; unsigned int i; unsigned int rdIdx; unsigned int wrIdx; if (HandleValid(handle)) { wrIdx = sSio[handle].unRead.bufIdxWr; used = UnReadBufLen(handle); free = UNREAD_BUF_SIZE - 1 - used; for (i = 0; i < bufSize; i++) { sSio[handle].unRead.buf[wrIdx] = *(pBuf + i); wrIdx++; wrIdx &= (UNREAD_BUF_SIZE - 1); } // falls alte Daten im unread-buf überschrieben wurden: rdIdx korr. if (free < bufSize) { rdIdx = (wrIdx + 1) & (UNREAD_BUF_SIZE - 1); sSio[handle].unRead.bufIdxRd = rdIdx; } sSio[handle].unRead.bufIdxWr = wrIdx; } return bufSize; }
/*----------------------------------------------------------------------------- * Sio Empfangspuffer lesen */ uint8_t SioRead(int handle, uint8_t *pBuf, uint8_t bufSize) { bool fSuccess; unsigned long bytesRead = 0; uint8_t readUnread; if (!HandleValid(handle)) { return 0; } readUnread = ReadUnRead(handle, pBuf, bufSize); if (readUnread < bufSize) { // noch Platz im Buffer fSuccess = ReadFile(sSio[handle].hCom, pBuf + readUnread, bufSize - readUnread, &bytesRead ,NULL); if (!fSuccess) { CommErrorClear(handle); } } #if 0 if (bytesRead != 0) { printf("sioread"); for (int i = 0; i < bytesRead; i++) { printf(" %02x", *(pBuf + i)); } printf("\r\n"); } #endif return (uint8_t)(bytesRead + readUnread); }
/*----------------------------------------------------------------------------- * trigger tx of buffer */ bool SioSendBuffer(int handle) { bool fSuccess; unsigned long bytesWritten = 123; TSioDesc *pSio; bool rc = false; if (!HandleValid(handle)) { return 0; } pSio = &sSio[handle]; fSuccess = WriteFile(pSio->hCom, pSio->bufferedTx.buf, pSio->bufferedTx.pos, &bytesWritten ,NULL); if (!fSuccess) { printf("comm err\n"); CommErrorClear(handle); } else { if (bytesWritten == pSio->bufferedTx.pos) { rc = true; } } pSio->bufferedTx.pos = 0; return rc; }
/*----------------------------------------------------------------------------- * Schnittstelle zurücksetzen */ static void CommErrorClear(int handle) { if (HandleValid(handle)) { COMSTAT comStat; DWORD dwErrorFlags; ClearCommError(sSio[handle].hCom, &dwErrorFlags, &comStat); } }
/*----------------------------------------------------------------------------- * Belegung des unread-buf */ static unsigned int UnReadBufLen(int handle) { unsigned int used = UNREAD_BUF_SIZE; if (HandleValid(handle)) { used = (sSio[handle].unRead.bufIdxWr - sSio[handle].unRead.bufIdxRd) & (UNREAD_BUF_SIZE - 1); } return used; }
/*----------------------------------------------------------------------------- * Schnittstelle schließen */ int SioClose(int handle) { if (!HandleValid(handle)) { return -1; } sSio[handle].used = false; CloseHandle(sSio[handle].hCom); return 0; }
/*----------------------------------------------------------------------------- * Sio Sendepuffer schreiben */ uint8_t SioWrite(int handle, uint8_t *pBuf, uint8_t bufSize) { bool fSuccess; unsigned long bytesWritten; if (!HandleValid(handle)) { return 0; } fSuccess = WriteFile(sSio[handle].hCom, pBuf, bufSize, &bytesWritten ,NULL); if (!fSuccess) { CommErrorClear(handle); } return (uint8_t)bytesWritten; }
/*----------------------------------------------------------------------------- * Anzahl der Zeichen im Empfangspuffer */ uint8_t SioGetNumRxChar(int handle) { DWORD inLen; DWORD numRxChar = 0; if (HandleValid(handle)) { COMSTAT comStat; DWORD dwErrorFlags; ClearCommError(sSio[handle].hCom, &dwErrorFlags, &comStat); inLen = comStat.cbInQue; numRxChar = inLen + UnReadBufLen(handle); if (numRxChar > 255) { numRxChar = 255; } } return numRxChar; }
/*----------------------------------------------------------------------------- * write data to tx buffer - do not yet start with tx */ uint8_t SioWriteBuffered(int handle, uint8_t *pBuf, uint8_t bufSize) { uint8_t len; TSioDesc *pSio; if (!HandleValid(handle)) { return 0; } pSio = &sSio[handle]; len = sizeof(pSio->bufferedTx.buf) - pSio->bufferedTx.pos; len = min(len, bufSize); memcpy(&pSio->bufferedTx.buf[pSio->bufferedTx.pos], pBuf, len); pSio->bufferedTx.pos += len; return (uint8_t)len; }
/*----------------------------------------------------------------------------- * Zeichen in Empfangspuffer zurückschreiben */ static uint8_t ReadUnRead(int handle, uint8_t *pBuf, uint8_t bufSize) { unsigned int len = 0; unsigned int used; unsigned int i; unsigned int rdIdx; if (HandleValid(handle)) { rdIdx = sSio[handle].unRead.bufIdxRd; used = UnReadBufLen(handle); len = min(bufSize, used); for (i = 0; i < len; i++) { *(pBuf + i) = sSio[handle].unRead.buf[rdIdx]; rdIdx++; rdIdx &= (UNREAD_BUF_SIZE - 1); } sSio[handle].unRead.bufIdxRd = rdIdx; } return (uint8_t)len; }
/** Write some data to the device. @param aPos media position in bytes @param aLength how many bytes to read @param aDataDes data descriptor @return KErrNone on success, standard Epoc error code otherwise */ TInt CWinImgFileDevice::Write(TInt64 aPos, TInt aLength, const TDesC8& aDataDes) { //__PRINT3(_L("#-- CWinImgFileDevice::Write, pos:%LU, len:%u, desLen:%u" ), aPos, aLength, aDataDes.Length()); ASSERT(HandleValid()); if(aLength == 0 || aDataDes.Length() == 0) return KErrNone; if(aLength > aDataDes.Length()) { ASSERT(0); return KErrArgument; } //-- check position on the volume const TInt64 maxPos = iDrvGeometry.TotalSizeInBytes(); if(aPos < 0 || aPos > maxPos) return KErrArgument; const TInt64 lastPos = aPos+aLength; if(lastPos > maxPos) return KErrArgument; TUint32 dataLen = aLength; DWORD dwRes; DWORD dwBytes = 0; const TUint8 *pData = aDataDes.Ptr(); try { //-- 1. position to the media LONG mediaPosHi = I64HIGH(aPos); const TUint32 mediaPosLo = I64LOW(aPos); dwRes = SetFilePointer(iDevHandle, mediaPosLo, &mediaPosHi, FILE_BEGIN); if(dwRes == INVALID_SET_FILE_POINTER) { throw KDiskOpError; } //-- 2. write data to the media //-- check if the pointer is word-aligned const DWORD dwPtrMask = 0x01; if( (DWORD)pData & dwPtrMask) {//-- data pointer isn't aligned, write non-aligned bytes through buffer ASSERT(dataLen); const int oddCnt = 1; ipScratchBuf[0] = *pData; ++pData; --dataLen; if(!WriteFile(iDevHandle, ipScratchBuf, oddCnt, &dwBytes, NULL)) throw KDiskOpError; } ASSERT(!((DWORD)pData & dwPtrMask)); if(dataLen > 0) { if(!WriteFile(iDevHandle, pData, dataLen, &dwBytes, NULL)) throw KDiskOpError; } } catch(TInt nErrId) {//-- some disk operation finished with the error (void)nErrId; ASSERT(nErrId == KDiskOpError); const DWORD dwWinErr = GetLastError(); const TInt epocErr = MapWinError(dwWinErr); __PRINT2(_L("#-- CWinImgFileDevice::Write() error! WinErr:%d, EpocErr:%d"), dwWinErr, epocErr); ASSERT(epocErr != KErrNone); return epocErr; } return KErrNone; }
/** Read a portion of data from the device. Note: at present it _APPENDS_ data to the aDataDes, so the caller must take care of setting its length @param aPos media position in bytes @param aLength how many bytes to read @param aDataDes data descriptor @return KErrNone on success, standard Epoc error code otherwise */ TInt CWinImgFileDevice::Read(TInt64 aPos,TInt aLength, TDes8& aDataDes) { //__PRINT3(_L("#-- CWinImgFileDevice::Read, pos:%LU, len:%u, desMaxLen:%u"), aPos, aLength, aDataDes.MaxLength()); ASSERT(HandleValid()); ASSERT(aLength <= aDataDes.MaxLength()); //-- check position on the volume const TInt64 maxPos = iDrvGeometry.TotalSizeInBytes(); if(aPos < 0 || aPos > maxPos) return KErrArgument; const TInt64 lastPos = aPos+aLength; if(lastPos > maxPos) return KErrArgument; TUint32 dataLen = aLength; if(dataLen == 0) return KErrNone; DWORD dwRes; DWORD dwBytesRead = 0; //aDataDes.SetLength(0); try { //-- 1. position to the media LONG mediaPosHi = I64HIGH(aPos); const TUint32 mediaPosLo = I64LOW(aPos); dwRes = SetFilePointer(iDevHandle, mediaPosLo, &mediaPosHi, FILE_BEGIN); if(dwRes == INVALID_SET_FILE_POINTER) throw KDiskOpError; //-- 2. read data to the scratch buffer and copy it to the descriptor. ASSERT(ipScratchBuf); TUint32 rem = dataLen; while(rem) { const TUint32 bytesToRead = Min(KScratchBufSz, rem); if(!ReadFile(iDevHandle, ipScratchBuf, bytesToRead, &dwBytesRead, NULL)) throw KDiskOpError; aDataDes.Append(ipScratchBuf, bytesToRead); rem-=bytesToRead; } } catch(TInt nErrId) {//-- some disk operation finished with the error (void)nErrId; ASSERT(nErrId == KDiskOpError); const DWORD dwWinErr = GetLastError(); const TInt epocErr = MapWinError(dwWinErr); __PRINT2(_L("#-- CWinImgFileDevice::Read() error! WinErr:%d, EpocErr:%d"), dwWinErr, epocErr); ASSERT(epocErr != KErrNone); return epocErr; } return KErrNone; }
/** 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; }
/** Write some data to the device. @param aPos media position in bytes @param aLength how many bytes to read @param aDataDes data descriptor @return KErrNone on success, standard Epoc error code otherwise */ TInt CWinVolumeDevice::Write(TInt64 aPos, TInt aLength, const TDesC8& aDataDes) { //__PRINT2(_L("#-- CWinVolumeDevice::Write, pos:%LU, len:%u"), aPos, aLength); ASSERT(HandleValid()); if(aLength == 0 || aDataDes.Length() == 0) return KErrNone; if(aLength > aDataDes.Length()) { ASSERT(0); return KErrArgument; } //-- check position on the volume const TInt64 maxPos = iDrvGeometry.TotalSizeInBytes(); if(aPos < 0 || aPos > maxPos) return KErrArgument; const TInt64 lastPos = aPos+aLength; if(lastPos > maxPos) return KErrArgument; TUint32 dataLen = aLength; DWORD dwRes; DWORD dwBytes = 0; const TUint32 KSectorSize = BytesPerSector(); const TUint8 *pData = aDataDes.Ptr(); try { LONG mediaPosHi = I64HIGH(aPos); const TUint32 mediaPosLo = I64LOW(aPos); const TUint32 startPosOffset = mediaPosLo & (KSectorSize-1); const TUint32 sectorPos = mediaPosLo-startPosOffset; //-- 1. position to the media with sector size granularity dwRes = SetFilePointer(iDevHandle, sectorPos, &mediaPosHi, FILE_BEGIN); if(dwRes == INVALID_SET_FILE_POINTER) { throw KDiskOpError; } if(startPosOffset || dataLen <= KSectorSize) {//-- need a read-modify-write here. //-- 1.1 read first sector if(!ReadFile(iDevHandle, ipScratchBuf, KSectorSize, &dwBytes, NULL)) throw KDiskOpError; dwRes = SetFilePointer(iDevHandle, sectorPos, &mediaPosHi, FILE_BEGIN); if(dwRes == INVALID_SET_FILE_POINTER) { throw KDiskOpError; } if(dwRes == INVALID_SET_FILE_POINTER) throw KDiskOpError; //-- 1.2 copy chunk of data there const TUint32 firstChunkLen = Min(dataLen, KSectorSize - startPosOffset); Mem::Copy(ipScratchBuf+startPosOffset, pData, firstChunkLen); //-- 1.3 write sector if(!WriteFile(iDevHandle, ipScratchBuf, KSectorSize, &dwBytes, NULL)) throw KDiskOpError; dataLen-=firstChunkLen; pData+=firstChunkLen; if(dataLen == 0) return KErrNone; //-- no more data to write } //-- 2. write whole number of sectors to the media const TUint32 KBytesTail = dataLen & (KSectorSize-1); //-- number of bytes in the incomplete last sector TUint32 KMainChunkBytes = dataLen - KBytesTail; ASSERT((KMainChunkBytes % KSectorSize) == 0); //-- the pointer to the data shall be 2-bytes aligned, otherwise WriteFile will fail if(!((DWORD)pData & 0x01)) {//-- data pointer aligned, ok if(!WriteFile(iDevHandle, pData, KMainChunkBytes, &dwBytes, NULL)) throw KDiskOpError; pData+=KMainChunkBytes; dataLen-=KMainChunkBytes; } else {//-- data pointer is odd, we need to copy data to the aligned buffer TUint32 rem = KMainChunkBytes; while(rem) { const TUint32 nBytesToWrite = Min(KScratchBufSz, rem); Mem::Copy(ipScratchBuf, pData, nBytesToWrite); if(!WriteFile(iDevHandle, ipScratchBuf, nBytesToWrite, &dwBytes, NULL)) throw KDiskOpError; rem-=nBytesToWrite; pData+=nBytesToWrite; dataLen-=nBytesToWrite; } } //-- 3. write the rest of the bytes into the incomplete last sector if(KBytesTail) { //-- 3.1 read last sector if(!ReadFile(iDevHandle, ipScratchBuf, KSectorSize, &dwBytes, NULL)) throw KDiskOpError; LARGE_INTEGER liRelOffset; liRelOffset.QuadPart = -(LONG)KSectorSize; //dwRes = SetFilePointer(iDevHandle, -(LONG)KSectorSize, NULL, FILE_CURRENT); dwRes = SetFilePointer(iDevHandle, liRelOffset.LowPart, &liRelOffset.HighPart, FILE_CURRENT); if(dwRes == INVALID_SET_FILE_POINTER) throw KDiskOpError; //-- 1.2 copy chunk of data there Mem::Copy(ipScratchBuf, pData, KBytesTail); //-- 1.3 write sector if(!WriteFile(iDevHandle, ipScratchBuf, KSectorSize, &dwBytes, NULL)) throw KDiskOpError; } }//try catch(TInt nErrId) {//-- some disk operation finished with the error (void)nErrId; ASSERT(nErrId == KDiskOpError); const DWORD dwWinErr = GetLastError(); const TInt epocErr = MapWinError(dwWinErr); __PRINT2(_L("#-- CWinVolumeDevice::Write() error! WinErr:%d, EpocErr:%d"), dwWinErr, epocErr); ASSERT(epocErr != KErrNone); return epocErr; } return KErrNone; }
/** Read a portion of data from the device. Note: at present it _APPENDS_ data to the aDataDes, so the caller must take care of setting its length @param aPos media position in bytes @param aLength how many bytes to read @param aDataDes data descriptor @return KErrNone on success, standard Epoc error code otherwise */ TInt CWinVolumeDevice::Read(TInt64 aPos, TInt aLength, TDes8& aDataDes) { //__PRINT2(_L("#-- CWinVolumeDevice::Read, pos:%LU, len:%u"), aPos, aLength); ASSERT(HandleValid()); ASSERT(aLength <= aDataDes.MaxLength()); //-- check position on the volume const TInt64 maxPos = iDrvGeometry.TotalSizeInBytes(); if(aPos < 0 || aPos > maxPos) return KErrArgument; const TInt64 lastPos = aPos+aLength; if(lastPos > maxPos) return KErrArgument; //-- TUint32 dataLen = aLength; if(dataLen == 0) return KErrNone; DWORD dwRes; DWORD dwBytesRead = 0; //aDataDes.SetLength(0); const TUint32 KSectorSize = BytesPerSector(); try { LONG mediaPosHi = I64HIGH(aPos); const TUint32 mediaPosLo = I64LOW(aPos); const TUint32 startPosOffset = mediaPosLo & (KSectorSize-1); //-- 1. position to the media with sector size granularity and read 1st sector dwRes = SetFilePointer(iDevHandle, mediaPosLo-startPosOffset, &mediaPosHi, FILE_BEGIN); if(dwRes == INVALID_SET_FILE_POINTER) throw KDiskOpError; //-- 1.1 read 1st sector if(!ReadFile(iDevHandle, ipScratchBuf, KSectorSize, &dwBytesRead, NULL)) throw KDiskOpError; const TUint32 firstChunkLen = Min(dataLen, KSectorSize - startPosOffset); aDataDes.Append(ipScratchBuf+startPosOffset, firstChunkLen); dataLen-=firstChunkLen; if(dataLen == 0) return KErrNone; //-- no more data to read //-- 2. read whole number of sectors from the meida const TUint32 KBytesTail = dataLen & (KSectorSize-1); //-- number of bytes in the incomplete last sector ASSERT((KScratchBufSz % KSectorSize) == 0); TUint32 rem = dataLen - KBytesTail; while(rem) { const TUint32 bytesToRead = Min(KScratchBufSz, rem); if(!ReadFile(iDevHandle, ipScratchBuf, bytesToRead, &dwBytesRead, NULL)) throw KDiskOpError; aDataDes.Append(ipScratchBuf, bytesToRead); rem-=bytesToRead; } //-- 3. read the rest of the bytes in the incomplete last sector if(KBytesTail) { if(!ReadFile(iDevHandle, ipScratchBuf, KSectorSize, &dwBytesRead, NULL)) throw KDiskOpError; aDataDes.Append(ipScratchBuf, KBytesTail); } }//try catch(TInt nErrId) {//-- some disk operation finished with the error (void)nErrId; ASSERT(nErrId == KDiskOpError); const DWORD dwWinErr = GetLastError(); const TInt epocErr = MapWinError(dwWinErr); __PRINT2(_L("#-- CWinVolumeDevice::Read() error! WinErr:%d, EpocErr:%d"), dwWinErr, epocErr); ASSERT(epocErr != KErrNone); return epocErr; } return KErrNone; }
/** 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; }