2 * Copyright (c) 2002 Frodo
3 * Portions Copyright (c) by the authors of ffmpeg and xvid
4 * Copyright (C) 2002-2013 Team XBMC
7 * This Program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2, or (at your option)
12 * This Program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with XBMC; see the file COPYING. If not, see
19 * <http://www.gnu.org/licenses/>.
23 // IoSupport.cpp: implementation of the CIoSupport class.
25 //////////////////////////////////////////////////////////////////////
28 #include "IoSupport.h"
29 #include "utils/log.h"
31 #include "my_ntddcdrm.h"
32 #include "WIN32Util.h"
33 #include "utils/CharsetConverter.h"
35 #if defined(TARGET_LINUX)
36 #include <linux/limits.h>
37 #include <sys/types.h>
38 #include <sys/ioctl.h>
41 #include <linux/cdrom.h>
43 #if defined(TARGET_DARWIN)
44 #include <sys/param.h>
45 #include <mach-o/dyld.h>
46 #if defined(TARGET_DARWIN_OSX)
47 #include <IOKit/IOKitLib.h>
48 #include <IOKit/IOBSD.h>
49 #include <IOKit/storage/IOCDTypes.h>
50 #include <IOKit/storage/IODVDTypes.h>
51 #include <IOKit/storage/IOMedia.h>
52 #include <IOKit/storage/IOCDMedia.h>
53 #include <IOKit/storage/IODVDMedia.h>
54 #include <IOKit/storage/IOCDMediaBSDClient.h>
55 #include <IOKit/storage/IODVDMediaBSDClient.h>
56 #include <IOKit/storage/IOStorageDeviceCharacteristics.h>
60 #include <sys/syslimits.h>
62 #include "cdioSupport.h"
63 #include "filesystem/iso9660.h"
64 #include "MediaManager.h"
70 PVOID CIoSupport::m_rawXferBuffer;
72 HANDLE CIoSupport::OpenCDROM()
77 #if defined(TARGET_POSIX)
78 int fd = open(CLibcdio::GetInstance()->GetDeviceFileName(), O_RDONLY | O_NONBLOCK);
79 hDevice = new CXHandle(CXHandle::HND_FILE);
81 hDevice->m_bCDROM = true;
82 #elif defined(TARGET_WINDOWS)
83 hDevice = CreateFile(g_mediaManager.TranslateDevicePath("",true), GENERIC_READ, FILE_SHARE_READ,
85 FILE_FLAG_RANDOM_ACCESS, NULL );
88 hDevice = CreateFile("\\\\.\\Cdrom0", GENERIC_READ, FILE_SHARE_READ,
90 FILE_FLAG_RANDOM_ACCESS, NULL );
97 void CIoSupport::AllocReadBuffer()
100 m_rawXferBuffer = GlobalAlloc(GPTR, RAW_SECTOR_SIZE);
104 void CIoSupport::FreeReadBuffer()
107 GlobalFree(m_rawXferBuffer);
111 INT CIoSupport::ReadSector(HANDLE hDevice, DWORD dwSector, LPSTR lpczBuffer)
115 DWORD dwSectorSize = 2048;
117 #if defined(TARGET_DARWIN) && defined(HAS_DVD_DRIVE)
118 dk_cd_read_t cd_read;
119 memset( &cd_read, 0, sizeof(cd_read) );
121 cd_read.sectorArea = kCDSectorAreaUser;
122 cd_read.buffer = lpczBuffer;
124 cd_read.sectorType = kCDSectorTypeMode1;
125 cd_read.offset = dwSector * kCDSectorSizeMode1;
127 cd_read.bufferLength = 2048;
129 if( ioctl(hDevice->fd, DKIOCCDREAD, &cd_read ) == -1 )
134 #elif defined(TARGET_POSIX)
135 if (hDevice->m_bCDROM)
137 int fd = hDevice->fd;
139 // seek to requested sector
140 off_t offset = (off_t)dwSector * (off_t)MODE1_DATA_SIZE;
142 if (lseek(fd, offset, SEEK_SET) < 0)
144 CLog::Log(LOGERROR, "CD: ReadSector Request to read sector %d\n", (int)dwSector);
145 CLog::Log(LOGERROR, "CD: ReadSector error: %s\n", strerror(errno));
146 OutputDebugString("CD Read error\n");
150 // read data block of this sector
151 while (read(fd, lpczBuffer, MODE1_DATA_SIZE) < 0)
153 // read was interrupted - try again
157 // error reading sector
158 CLog::Log(LOGERROR, "CD: ReadSector Request to read sector %d\n", (int)dwSector);
159 CLog::Log(LOGERROR, "CD: ReadSector error: %s\n", strerror(errno));
160 OutputDebugString("CD Read error\n");
164 return MODE1_DATA_SIZE;
167 LARGE_INTEGER Displacement;
168 Displacement.QuadPart = ((INT64)dwSector) * dwSectorSize;
170 for (int i = 0; i < 5; i++)
172 if (SetFilePointer(hDevice, Displacement.u.LowPart, &Displacement.u.HighPart, FILE_BEGIN) != (DWORD)-1)
174 if (ReadFile(hDevice, m_rawXferBuffer, dwSectorSize, &dwRead, NULL))
176 memcpy(lpczBuffer, m_rawXferBuffer, dwSectorSize);
182 OutputDebugString("CD Read error\n");
187 INT CIoSupport::ReadSectorMode2(HANDLE hDevice, DWORD dwSector, LPSTR lpczBuffer)
190 #if defined(TARGET_DARWIN)
191 dk_cd_read_t cd_read;
193 memset( &cd_read, 0, sizeof(cd_read) );
195 cd_read.sectorArea = kCDSectorAreaUser;
196 cd_read.buffer = lpczBuffer;
198 cd_read.offset = dwSector * kCDSectorSizeMode2Form2;
199 cd_read.sectorType = kCDSectorTypeMode2Form2;
200 cd_read.bufferLength = kCDSectorSizeMode2Form2;
202 if( ioctl( hDevice->fd, DKIOCCDREAD, &cd_read ) == -1 )
206 return MODE2_DATA_SIZE;
207 #elif defined(TARGET_FREEBSD)
209 #elif defined(TARGET_POSIX)
210 if (hDevice->m_bCDROM)
212 int fd = hDevice->fd;
213 int lba = (dwSector + CD_MSF_OFFSET) ;
217 struct cdrom_msf msf;
221 // convert sector offset to minute, second, frame format
222 // since that is what the 'ioctl' requires as input
229 arg.msf.cdmsf_min0 = m;
230 arg.msf.cdmsf_sec0 = s;
231 arg.msf.cdmsf_frame0 = f;
233 int ret = ioctl(fd, CDROMREADMODE2, &arg);
236 memcpy(lpczBuffer, arg.buffer, MODE2_DATA_SIZE); // don't think offset is needed here
237 return MODE2_DATA_SIZE;
239 CLog::Log(LOGERROR, "CD: ReadSectorMode2 Request to read sector %d\n", (int)dwSector);
240 CLog::Log(LOGERROR, "CD: ReadSectorMode2 error: %s\n", strerror(errno));
241 CLog::Log(LOGERROR, "CD: ReadSectorMode2 minute %d, second %d, frame %d\n", m, s, f);
242 OutputDebugString("CD Read error\n");
246 DWORD dwBytesReturned;
247 RAW_READ_INFO rawRead = {0};
249 // Oddly enough, DiskOffset uses the Red Book sector size
250 rawRead.DiskOffset.QuadPart = 2048 * dwSector;
251 rawRead.SectorCount = 1;
252 rawRead.TrackMode = XAForm2;
255 for (int i = 0; i < 5; i++)
257 if ( DeviceIoControl( hDevice,
258 IOCTL_CDROM_RAW_READ,
260 sizeof(RAW_READ_INFO),
266 memcpy(lpczBuffer, (char*)m_rawXferBuffer+MODE2_DATA_START, MODE2_DATA_SIZE);
267 return MODE2_DATA_SIZE;
271 int iErr = GetLastError();
279 INT CIoSupport::ReadSectorCDDA(HANDLE hDevice, DWORD dwSector, LPSTR lpczBuffer)
284 VOID CIoSupport::CloseCDROM(HANDLE hDevice)
286 CloseHandle(hDevice);