Mercurial > mplayer.hg
annotate libdvdcss/device.c @ 37195:ac6c37d85d65 default tip
configure: Fix initialization of variable def_local_aligned_32
It contiained the #define of HAVE_LOCAL_ALIGNED_16 instead
of HAVE_LOCAL_ALIGNED_32.
| author | al |
|---|---|
| date | Sun, 28 Sep 2014 18:38:41 +0000 |
| parents | 691431d2289e |
| children |
| rev | line source |
|---|---|
| 20613 | 1 /***************************************************************************** |
| 2 * device.h: DVD device access | |
| 3 ***************************************************************************** | |
| 4 * Copyright (C) 1998-2006 VideoLAN | |
| 5 * | |
| 27442 | 6 * Authors: Stéphane Borel <stef@via.ecp.fr> |
| 20613 | 7 * Sam Hocevar <sam@zoy.org> |
| 27442 | 8 * Håkan Hjort <d95hjort@dtek.chalmers.se> |
| 20613 | 9 * |
|
31098
9e9595c779cf
libdvdcss: cosmetics: Fix FSF address and program name in license headers.
diego
parents:
27442
diff
changeset
|
10 * This library is free software; you can redistribute it and/or modify |
| 20613 | 11 * it under the terms of the GNU General Public License as published by |
| 12 * the Free Software Foundation; either version 2 of the License, or | |
| 13 * (at your option) any later version. | |
| 14 * | |
|
31098
9e9595c779cf
libdvdcss: cosmetics: Fix FSF address and program name in license headers.
diego
parents:
27442
diff
changeset
|
15 * This library is distributed in the hope that it will be useful, |
| 20613 | 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 18 * GNU General Public License for more details. | |
| 19 * | |
|
31098
9e9595c779cf
libdvdcss: cosmetics: Fix FSF address and program name in license headers.
diego
parents:
27442
diff
changeset
|
20 * You should have received a copy of the GNU General Public License along |
|
9e9595c779cf
libdvdcss: cosmetics: Fix FSF address and program name in license headers.
diego
parents:
27442
diff
changeset
|
21 * with this library; if not, write to the Free Software Foundation, Inc., |
|
9e9595c779cf
libdvdcss: cosmetics: Fix FSF address and program name in license headers.
diego
parents:
27442
diff
changeset
|
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
| 20613 | 23 *****************************************************************************/ |
| 24 | |
| 25 /***************************************************************************** | |
| 26 * Preamble | |
| 27 *****************************************************************************/ | |
| 28 #include "config.h" | |
| 29 | |
| 30 #include <stdio.h> | |
| 31 #include <stdlib.h> | |
| 32 #include <string.h> | |
| 33 #ifdef HAVE_ERRNO_H | |
| 34 # include <errno.h> | |
| 35 #endif | |
| 36 #include <sys/types.h> | |
| 37 #include <sys/stat.h> | |
| 38 #ifdef HAVE_SYS_PARAM_H | |
| 39 # include <sys/param.h> | |
| 40 #endif | |
| 41 #include <fcntl.h> | |
| 42 | |
| 43 #ifdef HAVE_UNISTD_H | |
| 44 # include <unistd.h> | |
| 45 #endif | |
| 46 | |
| 47 #ifdef HAVE_LIMITS_H | |
| 48 # include <limits.h> | |
| 49 #endif | |
| 50 | |
| 51 #ifdef DARWIN_DVD_IOCTL | |
| 52 # include <paths.h> | |
| 53 # include <CoreFoundation/CoreFoundation.h> | |
| 54 # include <IOKit/IOKitLib.h> | |
| 55 # include <IOKit/IOBSD.h> | |
| 56 # include <IOKit/storage/IOMedia.h> | |
| 57 # include <IOKit/storage/IOCDMedia.h> | |
| 58 # include <IOKit/storage/IODVDMedia.h> | |
| 59 #endif | |
| 60 | |
| 35952 | 61 #ifdef __OS2__ |
|
31099
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
62 # define INCL_DOS |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
63 # define INCL_DOSDEVIOCTL |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
64 # include <os2.h> |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
65 # include <io.h> /* setmode() */ |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
66 # include <fcntl.h> /* O_BINARY */ |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
67 #endif |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
68 |
| 20613 | 69 #include "dvdcss/dvdcss.h" |
| 70 | |
| 71 #include "common.h" | |
| 72 #include "css.h" | |
| 73 #include "libdvdcss.h" | |
| 74 #include "ioctl.h" | |
| 75 #include "device.h" | |
| 76 | |
| 77 /***************************************************************************** | |
| 78 * Device reading prototypes | |
| 79 *****************************************************************************/ | |
| 80 static int libc_open ( dvdcss_t, char const * ); | |
| 81 static int libc_seek ( dvdcss_t, int ); | |
| 82 static int libc_read ( dvdcss_t, void *, int ); | |
| 83 static int libc_readv ( dvdcss_t, struct iovec *, int ); | |
| 84 | |
| 85 #ifdef WIN32 | |
| 86 static int win2k_open ( dvdcss_t, char const * ); | |
| 87 static int aspi_open ( dvdcss_t, char const * ); | |
| 88 static int win2k_seek ( dvdcss_t, int ); | |
| 89 static int aspi_seek ( dvdcss_t, int ); | |
| 90 static int win2k_read ( dvdcss_t, void *, int ); | |
| 91 static int aspi_read ( dvdcss_t, void *, int ); | |
| 92 static int win_readv ( dvdcss_t, struct iovec *, int ); | |
| 93 | |
| 94 static int aspi_read_internal ( int, void *, int ); | |
| 35952 | 95 #elif defined( __OS2__ ) |
|
31099
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
96 static int os2_open ( dvdcss_t, char const * ); |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
97 /* just use macros for libc */ |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
98 # define os2_seek libc_seek |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
99 # define os2_read libc_read |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
100 # define os2_readv libc_readv |
| 20613 | 101 #endif |
| 102 | |
| 103 int _dvdcss_use_ioctls( dvdcss_t dvdcss ) | |
| 104 { | |
| 105 #if defined( WIN32 ) | |
| 106 if( dvdcss->b_file ) | |
| 107 { | |
| 108 return 0; | |
| 109 } | |
| 110 | |
| 111 /* FIXME: implement this for Windows */ | |
| 112 if( WIN2K ) | |
| 113 { | |
| 114 return 1; | |
| 115 } | |
| 116 else | |
| 117 { | |
| 118 return 1; | |
| 119 } | |
| 35952 | 120 #elif defined( __OS2__ ) |
|
31099
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
121 ULONG ulMode; |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
122 |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
123 if( DosQueryFHState( dvdcss->i_fd, &ulMode ) != 0 ) |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
124 return 1; /* What to do? Be conservative and try to use the ioctls */ |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
125 |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
126 if( ulMode & OPEN_FLAGS_DASD ) |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
127 return 1; |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
128 |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
129 return 0; |
| 20613 | 130 #else |
| 131 struct stat fileinfo; | |
| 132 int ret; | |
| 133 | |
| 134 ret = fstat( dvdcss->i_fd, &fileinfo ); | |
| 135 if( ret < 0 ) | |
| 136 { | |
| 137 return 1; /* What to do? Be conservative and try to use the ioctls */ | |
| 138 } | |
| 139 | |
| 140 /* Complete this list and check that we test for the right things | |
| 141 * (I've assumed for all OSs that 'r', (raw) device, are char devices | |
| 142 * and those that don't contain/use an 'r' in the name are block devices) | |
| 143 * | |
| 144 * Linux needs a block device | |
| 145 * Solaris needs a char device | |
| 146 * Darwin needs a char device | |
| 147 * OpenBSD needs a char device | |
| 148 * NetBSD needs a char device | |
| 149 * FreeBSD can use either the block or the char device | |
| 150 */ | |
| 151 | |
| 152 /* Check if this is a block/char device */ | |
| 153 if( S_ISBLK( fileinfo.st_mode ) || | |
| 154 S_ISCHR( fileinfo.st_mode ) ) | |
| 155 { | |
| 156 return 1; | |
| 157 } | |
| 158 else | |
| 159 { | |
| 160 return 0; | |
| 161 } | |
| 162 #endif | |
| 163 } | |
| 164 | |
| 165 void _dvdcss_check ( dvdcss_t dvdcss ) | |
| 166 { | |
| 167 #if defined( WIN32 ) | |
| 168 DWORD drives; | |
| 169 int i; | |
| 170 #elif defined( DARWIN_DVD_IOCTL ) | |
| 171 io_object_t next_media; | |
| 172 mach_port_t master_port; | |
| 173 kern_return_t kern_result; | |
| 174 io_iterator_t media_iterator; | |
| 175 CFMutableDictionaryRef classes_to_match; | |
| 35952 | 176 #elif defined( __OS2__ ) |
|
31099
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
177 #pragma pack( 1 ) |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
178 struct |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
179 { |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
180 BYTE bCmdInfo; |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
181 BYTE bDrive; |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
182 } param; |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
183 |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
184 struct |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
185 { |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
186 BYTE abEBPB[31]; |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
187 USHORT usCylinders; |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
188 BYTE bDevType; |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
189 USHORT usDevAttr; |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
190 } data; |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
191 #pragma pack() |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
192 |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
193 ULONG ulParamLen; |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
194 ULONG ulDataLen; |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
195 ULONG rc; |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
196 |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
197 int i; |
| 20613 | 198 #else |
| 199 char *ppsz_devices[] = { "/dev/dvd", "/dev/cdrom", "/dev/hdc", NULL }; | |
| 200 int i, i_fd; | |
| 201 #endif | |
| 202 | |
| 203 /* If the device name is non-null, return */ | |
| 204 if( dvdcss->psz_device[0] ) | |
| 205 { | |
| 206 return; | |
| 207 } | |
| 208 | |
| 209 #if defined( WIN32 ) | |
| 210 drives = GetLogicalDrives(); | |
| 211 | |
| 212 for( i = 0; drives; i++ ) | |
| 213 { | |
| 214 char psz_device[5]; | |
| 215 DWORD cur = 1 << i; | |
| 216 UINT i_ret; | |
| 217 | |
| 218 if( (drives & cur) == 0 ) | |
| 219 { | |
| 220 continue; | |
| 221 } | |
| 222 drives &= ~cur; | |
| 223 | |
| 224 sprintf( psz_device, "%c:\\", 'A' + i ); | |
| 225 i_ret = GetDriveType( psz_device ); | |
| 226 if( i_ret != DRIVE_CDROM ) | |
| 227 { | |
| 228 continue; | |
| 229 } | |
| 230 | |
| 231 /* Remove trailing backslash */ | |
| 232 psz_device[2] = '\0'; | |
| 233 | |
| 35952 | 234 /* FIXME: we want to differentiate between CD and DVD drives |
| 20613 | 235 * using DeviceIoControl() */ |
| 236 print_debug( dvdcss, "defaulting to drive `%s'", psz_device ); | |
| 237 free( dvdcss->psz_device ); | |
| 238 dvdcss->psz_device = strdup( psz_device ); | |
| 239 return; | |
| 240 } | |
| 241 #elif defined( DARWIN_DVD_IOCTL ) | |
| 242 | |
| 243 kern_result = IOMasterPort( MACH_PORT_NULL, &master_port ); | |
| 244 if( kern_result != KERN_SUCCESS ) | |
| 245 { | |
| 246 return; | |
| 247 } | |
| 248 | |
| 249 classes_to_match = IOServiceMatching( kIODVDMediaClass ); | |
| 250 if( classes_to_match == NULL ) | |
| 251 { | |
| 252 return; | |
| 253 } | |
| 254 | |
| 255 CFDictionarySetValue( classes_to_match, CFSTR( kIOMediaEjectableKey ), | |
| 256 kCFBooleanTrue ); | |
| 257 | |
| 258 kern_result = IOServiceGetMatchingServices( master_port, classes_to_match, | |
| 259 &media_iterator ); | |
| 260 if( kern_result != KERN_SUCCESS ) | |
| 261 { | |
| 262 return; | |
| 263 } | |
| 264 | |
| 265 next_media = IOIteratorNext( media_iterator ); | |
| 266 for( ; ; ) | |
| 267 { | |
| 268 char psz_buf[0x32]; | |
| 269 size_t i_pathlen; | |
| 270 CFTypeRef psz_path; | |
| 271 | |
| 272 next_media = IOIteratorNext( media_iterator ); | |
| 273 if( next_media == 0 ) | |
| 274 { | |
| 275 break; | |
| 276 } | |
| 277 | |
| 278 psz_path = IORegistryEntryCreateCFProperty( next_media, | |
| 279 CFSTR( kIOBSDNameKey ), | |
| 280 kCFAllocatorDefault, | |
| 281 0 ); | |
| 282 if( psz_path == NULL ) | |
| 283 { | |
| 284 IOObjectRelease( next_media ); | |
| 285 continue; | |
| 286 } | |
| 287 | |
| 288 snprintf( psz_buf, sizeof(psz_buf), "%s%c", _PATH_DEV, 'r' ); | |
| 289 i_pathlen = strlen( psz_buf ); | |
| 290 | |
| 291 if( CFStringGetCString( psz_path, | |
| 292 (char*)&psz_buf + i_pathlen, | |
| 293 sizeof(psz_buf) - i_pathlen, | |
| 294 kCFStringEncodingASCII ) ) | |
| 295 { | |
| 296 print_debug( dvdcss, "defaulting to drive `%s'", psz_buf ); | |
| 297 CFRelease( psz_path ); | |
| 298 IOObjectRelease( next_media ); | |
| 299 IOObjectRelease( media_iterator ); | |
| 300 free( dvdcss->psz_device ); | |
| 301 dvdcss->psz_device = strdup( psz_buf ); | |
| 302 return; | |
| 303 } | |
| 304 | |
| 305 CFRelease( psz_path ); | |
| 306 | |
| 307 IOObjectRelease( next_media ); | |
| 308 } | |
| 309 | |
| 310 IOObjectRelease( media_iterator ); | |
| 35952 | 311 #elif defined( __OS2__ ) |
|
31099
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
312 for( i = 0; i < 26; i++ ) |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
313 { |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
314 param.bCmdInfo = 0; |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
315 param.bDrive = i; |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
316 |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
317 rc = DosDevIOCtl( ( HFILE )-1, IOCTL_DISK, DSK_GETDEVICEPARAMS, |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
318 ¶m, sizeof( param ), &ulParamLen, |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
319 &data, sizeof( data ), &ulDataLen ); |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
320 |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
321 if( rc == 0 ) |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
322 { |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
323 /* Check for removable and for cylinders */ |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
324 if( ( data.usDevAttr & 1 ) == 0 && data.usCylinders == 0xFFFF ) |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
325 { |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
326 char psz_dvd[] = "A:"; |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
327 |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
328 psz_dvd[0] += i; |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
329 |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
330 print_debug( dvdcss, "defaulting to drive `%s'", psz_dvd ); |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
331 free( dvdcss->psz_device ); |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
332 dvdcss->psz_device = strdup( psz_dvd ); |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
333 return; |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
334 } |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
335 } |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
336 } |
| 20613 | 337 #else |
| 338 for( i = 0; ppsz_devices[i]; i++ ) | |
| 339 { | |
| 340 i_fd = open( ppsz_devices[i], 0 ); | |
| 341 if( i_fd != -1 ) | |
| 342 { | |
| 343 print_debug( dvdcss, "defaulting to drive `%s'", ppsz_devices[i] ); | |
| 344 close( i_fd ); | |
| 345 free( dvdcss->psz_device ); | |
| 346 dvdcss->psz_device = strdup( ppsz_devices[i] ); | |
| 347 return; | |
| 348 } | |
| 349 } | |
| 350 #endif | |
| 351 | |
| 352 print_error( dvdcss, "could not find a suitable default drive" ); | |
| 353 } | |
| 354 | |
| 355 int _dvdcss_open ( dvdcss_t dvdcss ) | |
| 356 { | |
| 357 char const *psz_device = dvdcss->psz_device; | |
| 358 | |
| 359 print_debug( dvdcss, "opening target `%s'", psz_device ); | |
| 360 | |
| 361 #if defined( WIN32 ) | |
| 362 dvdcss->b_file = 1; | |
| 363 /* If device is "X:" or "X:\", we are not actually opening a file. */ | |
| 364 if (psz_device[0] && psz_device[1] == ':' && | |
| 365 (!psz_device[2] || (psz_device[2] == '\\' && !psz_device[3]))) | |
| 366 dvdcss->b_file = 0; | |
| 367 | |
| 368 /* Initialize readv temporary buffer */ | |
| 369 dvdcss->p_readv_buffer = NULL; | |
| 370 dvdcss->i_readv_buf_size = 0; | |
| 371 | |
| 372 if( !dvdcss->b_file && WIN2K ) | |
| 373 { | |
| 374 print_debug( dvdcss, "using Win2K API for access" ); | |
| 375 dvdcss->pf_seek = win2k_seek; | |
| 376 dvdcss->pf_read = win2k_read; | |
| 377 dvdcss->pf_readv = win_readv; | |
| 378 return win2k_open( dvdcss, psz_device ); | |
| 379 } | |
| 380 else if( !dvdcss->b_file ) | |
| 381 { | |
| 382 print_debug( dvdcss, "using ASPI for access" ); | |
| 383 dvdcss->pf_seek = aspi_seek; | |
| 384 dvdcss->pf_read = aspi_read; | |
| 385 dvdcss->pf_readv = win_readv; | |
| 386 return aspi_open( dvdcss, psz_device ); | |
| 387 } | |
| 388 else | |
| 35952 | 389 #elif defined( __OS2__ ) |
|
31099
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
390 /* If device is "X:" or "X:\", we are not actually opening a file. */ |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
391 if( psz_device[0] && psz_device[1] == ':' && |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
392 ( !psz_device[2] || ( psz_device[2] == '\\' && !psz_device[3] ) ) ) |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
393 { |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
394 print_debug( dvdcss, "using OS2 API for access" ); |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
395 dvdcss->pf_seek = os2_seek; |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
396 dvdcss->pf_read = os2_read; |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
397 dvdcss->pf_readv = os2_readv; |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
398 return os2_open( dvdcss, psz_device ); |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
399 } |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
400 else |
| 20613 | 401 #endif |
| 402 { | |
| 403 print_debug( dvdcss, "using libc for access" ); | |
| 404 dvdcss->pf_seek = libc_seek; | |
| 405 dvdcss->pf_read = libc_read; | |
| 406 dvdcss->pf_readv = libc_readv; | |
| 407 return libc_open( dvdcss, psz_device ); | |
| 408 } | |
| 409 } | |
| 410 | |
| 35952 | 411 #ifdef DVDCSS_RAW_OPEN |
| 20613 | 412 int _dvdcss_raw_open ( dvdcss_t dvdcss, char const *psz_device ) |
| 413 { | |
| 414 dvdcss->i_raw_fd = open( psz_device, 0 ); | |
| 415 | |
| 416 if( dvdcss->i_raw_fd == -1 ) | |
| 417 { | |
| 418 print_debug( dvdcss, "cannot open %s (%s)", | |
| 419 psz_device, strerror(errno) ); | |
| 420 print_error( dvdcss, "failed to open raw device, but continuing" ); | |
| 421 return -1; | |
| 422 } | |
| 423 else | |
| 424 { | |
| 425 dvdcss->i_read_fd = dvdcss->i_raw_fd; | |
| 426 } | |
| 427 | |
| 428 return 0; | |
| 429 } | |
| 430 #endif | |
| 431 | |
| 432 int _dvdcss_close ( dvdcss_t dvdcss ) | |
| 433 { | |
| 434 #if defined( WIN32 ) | |
| 435 if( dvdcss->b_file ) | |
| 436 { | |
| 437 close( dvdcss->i_fd ); | |
| 438 } | |
| 439 else if( WIN2K ) | |
| 440 { | |
| 441 CloseHandle( (HANDLE) dvdcss->i_fd ); | |
| 442 } | |
| 443 else /* ASPI */ | |
| 444 { | |
| 445 struct w32_aspidev *fd = (struct w32_aspidev *) dvdcss->i_fd; | |
| 446 | |
| 35952 | 447 /* Unload ASPI and free w32_aspidev structure */ |
| 20613 | 448 FreeLibrary( (HMODULE) fd->hASPI ); |
| 449 free( (void*) dvdcss->i_fd ); | |
| 450 } | |
| 451 | |
| 452 /* Free readv temporary buffer */ | |
| 453 if( dvdcss->p_readv_buffer ) | |
| 454 { | |
| 455 free( dvdcss->p_readv_buffer ); | |
| 456 dvdcss->p_readv_buffer = NULL; | |
| 457 dvdcss->i_readv_buf_size = 0; | |
| 458 } | |
| 459 | |
| 460 return 0; | |
| 461 #else | |
| 462 close( dvdcss->i_fd ); | |
| 463 | |
| 35952 | 464 #ifdef DVDCSS_RAW_OPEN |
| 20613 | 465 if( dvdcss->i_raw_fd >= 0 ) |
| 466 { | |
| 467 close( dvdcss->i_raw_fd ); | |
| 468 dvdcss->i_raw_fd = -1; | |
| 469 } | |
|
31099
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
470 #endif |
| 20613 | 471 |
| 472 return 0; | |
| 473 #endif | |
| 474 } | |
| 475 | |
| 476 /* Following functions are local */ | |
| 477 | |
| 478 /***************************************************************************** | |
| 479 * Open commands. | |
| 480 *****************************************************************************/ | |
| 481 static int libc_open ( dvdcss_t dvdcss, char const *psz_device ) | |
| 482 { | |
| 483 dvdcss->i_fd = dvdcss->i_read_fd = open( psz_device, O_BINARY ); | |
| 484 | |
| 485 if( dvdcss->i_fd == -1 ) | |
| 486 { | |
| 487 print_debug( dvdcss, "cannot open %s (%s)", | |
| 488 psz_device, strerror(errno) ); | |
| 489 print_error( dvdcss, "failed to open device" ); | |
| 490 return -1; | |
| 491 } | |
| 492 | |
| 493 dvdcss->i_pos = 0; | |
| 494 | |
| 495 return 0; | |
| 496 } | |
| 497 | |
| 498 #if defined( WIN32 ) | |
| 499 static int win2k_open ( dvdcss_t dvdcss, char const *psz_device ) | |
| 500 { | |
| 501 char psz_dvd[7]; | |
|
34178
3c0cf739f1e1
libdvdcss: consistently use snprintf() instead of _snprintf()
diego
parents:
31099
diff
changeset
|
502 snprintf( psz_dvd, 7, "\\\\.\\%c:", psz_device[0] ); |
| 20613 | 503 |
| 504 /* To work around an M$ bug in IOCTL_DVD_READ_STRUCTURE, we need read | |
| 505 * _and_ write access to the device (so we can make SCSI Pass Through | |
| 506 * Requests). Unfortunately this is only allowed if you have | |
| 35952 | 507 * administrator privileges so we allow for a fallback method with |
| 20613 | 508 * only read access to the device (in this case ioctl_ReadCopyright() |
| 509 * won't send back the right result). | |
| 510 * (See Microsoft Q241374: Read and Write Access Required for SCSI | |
| 511 * Pass Through Requests) */ | |
| 512 dvdcss->i_fd = (int) | |
| 513 CreateFile( psz_dvd, GENERIC_READ | GENERIC_WRITE, | |
| 514 FILE_SHARE_READ | FILE_SHARE_WRITE, | |
| 515 NULL, OPEN_EXISTING, | |
| 516 FILE_FLAG_RANDOM_ACCESS, NULL ); | |
| 517 | |
| 518 if( (HANDLE) dvdcss->i_fd == INVALID_HANDLE_VALUE ) | |
| 519 dvdcss->i_fd = (int) | |
| 520 CreateFile( psz_dvd, GENERIC_READ, FILE_SHARE_READ, | |
| 521 NULL, OPEN_EXISTING, | |
| 522 FILE_FLAG_RANDOM_ACCESS, NULL ); | |
| 523 | |
| 524 if( (HANDLE) dvdcss->i_fd == INVALID_HANDLE_VALUE ) | |
| 525 { | |
| 526 print_error( dvdcss, "failed opening device" ); | |
| 527 return -1; | |
| 528 } | |
| 529 | |
| 530 dvdcss->i_pos = 0; | |
| 531 | |
| 532 return 0; | |
| 533 } | |
| 534 | |
| 535 static int aspi_open( dvdcss_t dvdcss, char const * psz_device ) | |
| 536 { | |
| 537 HMODULE hASPI; | |
| 538 DWORD dwSupportInfo; | |
| 539 struct w32_aspidev *fd; | |
| 540 int i, j, i_hostadapters; | |
| 541 GETASPI32SUPPORTINFO lpGetSupport; | |
| 542 SENDASPI32COMMAND lpSendCommand; | |
| 543 char c_drive = psz_device[0]; | |
| 544 | |
| 35952 | 545 /* load ASPI and init w32_aspidev structure */ |
| 20613 | 546 hASPI = LoadLibrary( "wnaspi32.dll" ); |
| 547 if( hASPI == NULL ) | |
| 548 { | |
| 549 print_error( dvdcss, "unable to load wnaspi32.dll" ); | |
| 550 return -1; | |
| 551 } | |
| 552 | |
| 553 lpGetSupport = (GETASPI32SUPPORTINFO) GetProcAddress( hASPI, "GetASPI32SupportInfo" ); | |
| 554 lpSendCommand = (SENDASPI32COMMAND) GetProcAddress( hASPI, "SendASPI32Command" ); | |
| 555 | |
| 556 if(lpGetSupport == NULL || lpSendCommand == NULL ) | |
| 557 { | |
| 35952 | 558 print_error( dvdcss, "unable to get ASPI function pointers" ); |
| 20613 | 559 FreeLibrary( hASPI ); |
| 560 return -1; | |
| 561 } | |
| 562 | |
| 563 dwSupportInfo = lpGetSupport(); | |
| 564 | |
| 565 if( HIBYTE( LOWORD ( dwSupportInfo ) ) == SS_NO_ADAPTERS ) | |
| 566 { | |
| 567 print_error( dvdcss, "no ASPI adapters found" ); | |
| 568 FreeLibrary( hASPI ); | |
| 569 return -1; | |
| 570 } | |
| 571 | |
| 572 if( HIBYTE( LOWORD ( dwSupportInfo ) ) != SS_COMP ) | |
| 573 { | |
| 35952 | 574 print_error( dvdcss, "unable to initialize ASPI layer" ); |
| 20613 | 575 FreeLibrary( hASPI ); |
| 576 return -1; | |
| 577 } | |
| 578 | |
| 579 i_hostadapters = LOBYTE( LOWORD( dwSupportInfo ) ); | |
| 580 if( i_hostadapters == 0 ) | |
| 581 { | |
| 582 print_error( dvdcss, "no ASPI adapters ready" ); | |
| 583 FreeLibrary( hASPI ); | |
| 584 return -1; | |
| 585 } | |
| 586 | |
| 587 fd = malloc( sizeof( struct w32_aspidev ) ); | |
| 588 if( fd == NULL ) | |
| 589 { | |
| 590 print_error( dvdcss, "not enough memory" ); | |
| 591 FreeLibrary( hASPI ); | |
| 592 return -1; | |
| 593 } | |
| 594 | |
| 595 fd->i_blocks = 0; | |
| 596 fd->hASPI = (long) hASPI; | |
| 597 fd->lpSendCommand = lpSendCommand; | |
| 598 | |
| 599 c_drive = c_drive > 'Z' ? c_drive - 'a' : c_drive - 'A'; | |
| 600 | |
| 601 for( i = 0; i < i_hostadapters; i++ ) | |
| 602 { | |
| 603 for( j = 0; j < 15; j++ ) | |
| 604 { | |
| 605 struct SRB_GetDiskInfo srbDiskInfo; | |
| 606 | |
| 607 srbDiskInfo.SRB_Cmd = SC_GET_DISK_INFO; | |
| 608 srbDiskInfo.SRB_HaId = i; | |
| 609 srbDiskInfo.SRB_Flags = 0; | |
| 610 srbDiskInfo.SRB_Hdr_Rsvd = 0; | |
| 611 srbDiskInfo.SRB_Target = j; | |
| 612 srbDiskInfo.SRB_Lun = 0; | |
| 613 | |
| 614 lpSendCommand( (void*) &srbDiskInfo ); | |
| 615 | |
| 616 if( (srbDiskInfo.SRB_Status == SS_COMP) && | |
| 617 (srbDiskInfo.SRB_Int13HDriveInfo == c_drive) ) | |
| 618 { | |
| 35952 | 619 /* Make sure this is a CD-ROM device */ |
| 620 struct SRB_GDEVBlock srbGDEVBlock = { 0 }; | |
| 20613 | 621 |
| 622 srbGDEVBlock.SRB_Cmd = SC_GET_DEV_TYPE; | |
| 623 srbGDEVBlock.SRB_HaId = i; | |
| 624 srbGDEVBlock.SRB_Target = j; | |
| 625 | |
| 626 lpSendCommand( (void*) &srbGDEVBlock ); | |
| 627 | |
| 628 if( ( srbGDEVBlock.SRB_Status == SS_COMP ) && | |
| 629 ( srbGDEVBlock.SRB_DeviceType == DTYPE_CDROM ) ) | |
| 630 { | |
| 631 fd->i_sid = MAKEWORD( i, j ); | |
| 632 dvdcss->i_fd = (int) fd; | |
| 633 dvdcss->i_pos = 0; | |
| 634 return 0; | |
| 635 } | |
| 636 else | |
| 637 { | |
| 638 free( (void*) fd ); | |
| 639 FreeLibrary( hASPI ); | |
| 35952 | 640 print_error( dvdcss,"this is not a CD-ROM drive" ); |
| 20613 | 641 return -1; |
| 642 } | |
| 643 } | |
| 644 } | |
| 645 } | |
| 646 | |
| 647 free( (void*) fd ); | |
| 648 FreeLibrary( hASPI ); | |
| 35952 | 649 print_error( dvdcss, "unable to get haid and target (ASPI)" ); |
| 20613 | 650 return -1; |
| 651 } | |
| 652 #endif | |
| 653 | |
| 35952 | 654 #ifdef __OS2__ |
|
31099
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
655 static int os2_open ( dvdcss_t dvdcss, char const *psz_device ) |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
656 { |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
657 char psz_dvd[] = "X:"; |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
658 HFILE hfile; |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
659 ULONG ulAction; |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
660 ULONG rc; |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
661 |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
662 psz_dvd[0] = psz_device[0]; |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
663 |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
664 rc = DosOpenL( ( PSZ )psz_dvd, &hfile, &ulAction, 0, FILE_NORMAL, |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
665 OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW, |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
666 OPEN_ACCESS_READONLY | OPEN_SHARE_DENYNONE | OPEN_FLAGS_DASD, |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
667 NULL ); |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
668 |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
669 if( rc ) |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
670 { |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
671 print_error( dvdcss, "failed to open device" ); |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
672 return -1; |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
673 } |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
674 |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
675 setmode( hfile, O_BINARY ); |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
676 |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
677 dvdcss->i_fd = dvdcss->i_read_fd = hfile; |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
678 |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
679 dvdcss->i_pos = 0; |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
680 |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
681 return 0; |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
682 } |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
683 #endif |
|
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
684 |
| 20613 | 685 /***************************************************************************** |
| 686 * Seek commands. | |
| 687 *****************************************************************************/ | |
| 688 static int libc_seek( dvdcss_t dvdcss, int i_blocks ) | |
| 689 { | |
| 690 off_t i_seek; | |
| 691 | |
| 692 if( dvdcss->i_pos == i_blocks ) | |
| 693 { | |
| 694 /* We are already in position */ | |
| 695 return i_blocks; | |
| 696 } | |
| 697 | |
| 698 i_seek = (off_t)i_blocks * (off_t)DVDCSS_BLOCK_SIZE; | |
|
20730
66c2f233ccff
Fix linking on Cygwin and remove nonsense lseek64 --> lseek indirection,
diego
parents:
20613
diff
changeset
|
699 i_seek = lseek( dvdcss->i_read_fd, i_seek, SEEK_SET ); |
| 20613 | 700 |
| 701 if( i_seek < 0 ) | |
| 702 { | |
| 703 print_error( dvdcss, "seek error" ); | |
| 704 dvdcss->i_pos = -1; | |
| 705 return i_seek; | |
| 706 } | |
| 707 | |
| 708 dvdcss->i_pos = i_seek / DVDCSS_BLOCK_SIZE; | |
| 709 | |
| 710 return dvdcss->i_pos; | |
| 711 } | |
| 712 | |
| 713 #if defined( WIN32 ) | |
| 714 static int win2k_seek( dvdcss_t dvdcss, int i_blocks ) | |
| 715 { | |
| 716 LARGE_INTEGER li_seek; | |
| 717 | |
| 718 #ifndef INVALID_SET_FILE_POINTER | |
| 719 # define INVALID_SET_FILE_POINTER ((DWORD)-1) | |
| 720 #endif | |
| 721 | |
| 722 if( dvdcss->i_pos == i_blocks ) | |
| 723 { | |
| 724 /* We are already in position */ | |
| 725 return i_blocks; | |
| 726 } | |
| 727 | |
| 728 li_seek.QuadPart = (LONGLONG)i_blocks * DVDCSS_BLOCK_SIZE; | |
| 729 | |
| 730 li_seek.LowPart = SetFilePointer( (HANDLE) dvdcss->i_fd, | |
| 731 li_seek.LowPart, | |
| 732 &li_seek.HighPart, FILE_BEGIN ); | |
| 733 if( (li_seek.LowPart == INVALID_SET_FILE_POINTER) | |
| 734 && GetLastError() != NO_ERROR) | |
| 735 { | |
| 736 dvdcss->i_pos = -1; | |
| 737 return -1; | |
| 738 } | |
| 739 | |
| 740 dvdcss->i_pos = li_seek.QuadPart / DVDCSS_BLOCK_SIZE; | |
| 741 | |
| 742 return dvdcss->i_pos; | |
| 743 } | |
| 744 | |
| 745 static int aspi_seek( dvdcss_t dvdcss, int i_blocks ) | |
| 746 { | |
| 747 int i_old_blocks; | |
| 748 char sz_buf[ DVDCSS_BLOCK_SIZE ]; | |
| 749 struct w32_aspidev *fd = (struct w32_aspidev *) dvdcss->i_fd; | |
| 750 | |
| 751 if( dvdcss->i_pos == i_blocks ) | |
| 752 { | |
| 753 /* We are already in position */ | |
| 754 return i_blocks; | |
| 755 } | |
| 756 | |
| 757 i_old_blocks = fd->i_blocks; | |
| 758 fd->i_blocks = i_blocks; | |
| 759 | |
| 760 if( aspi_read_internal( dvdcss->i_fd, sz_buf, 1 ) == -1 ) | |
| 761 { | |
| 762 fd->i_blocks = i_old_blocks; | |
| 763 dvdcss->i_pos = -1; | |
| 764 return -1; | |
| 765 } | |
| 766 | |
| 767 (fd->i_blocks)--; | |
| 768 | |
| 769 dvdcss->i_pos = fd->i_blocks; | |
| 770 | |
| 771 return dvdcss->i_pos; | |
| 772 } | |
| 773 #endif | |
| 774 | |
| 775 /***************************************************************************** | |
| 776 * Read commands. | |
| 777 *****************************************************************************/ | |
| 778 static int libc_read ( dvdcss_t dvdcss, void *p_buffer, int i_blocks ) | |
| 779 { | |
| 780 off_t i_size, i_ret; | |
| 781 | |
| 782 i_size = (off_t)i_blocks * (off_t)DVDCSS_BLOCK_SIZE; | |
| 783 i_ret = read( dvdcss->i_read_fd, p_buffer, i_size ); | |
| 784 | |
| 785 if( i_ret < 0 ) | |
| 786 { | |
| 787 print_error( dvdcss, "read error" ); | |
| 788 dvdcss->i_pos = -1; | |
| 789 return i_ret; | |
| 790 } | |
| 791 | |
| 792 /* Handle partial reads */ | |
| 793 if( i_ret != i_size ) | |
| 794 { | |
| 795 int i_seek; | |
| 796 | |
| 797 dvdcss->i_pos = -1; | |
| 798 i_seek = libc_seek( dvdcss, i_ret / DVDCSS_BLOCK_SIZE ); | |
| 799 if( i_seek < 0 ) | |
| 800 { | |
| 801 return i_seek; | |
| 802 } | |
| 803 | |
| 804 /* We have to return now so that i_pos isn't clobbered */ | |
| 805 return i_ret / DVDCSS_BLOCK_SIZE; | |
| 806 } | |
| 807 | |
| 808 dvdcss->i_pos += i_ret / DVDCSS_BLOCK_SIZE; | |
| 809 return i_ret / DVDCSS_BLOCK_SIZE; | |
| 810 } | |
| 811 | |
| 812 #if defined( WIN32 ) | |
| 813 static int win2k_read ( dvdcss_t dvdcss, void *p_buffer, int i_blocks ) | |
| 814 { | |
| 815 int i_bytes; | |
| 816 | |
| 817 if( !ReadFile( (HANDLE) dvdcss->i_fd, p_buffer, | |
| 818 i_blocks * DVDCSS_BLOCK_SIZE, | |
| 819 (LPDWORD)&i_bytes, NULL ) ) | |
| 820 { | |
| 821 dvdcss->i_pos = -1; | |
| 822 return -1; | |
| 823 } | |
| 824 | |
| 825 dvdcss->i_pos += i_bytes / DVDCSS_BLOCK_SIZE; | |
| 826 return i_bytes / DVDCSS_BLOCK_SIZE; | |
| 827 } | |
| 828 | |
| 829 static int aspi_read ( dvdcss_t dvdcss, void *p_buffer, int i_blocks ) | |
| 830 { | |
| 831 int i_read = aspi_read_internal( dvdcss->i_fd, p_buffer, i_blocks ); | |
| 832 | |
| 833 if( i_read < 0 ) | |
| 834 { | |
| 835 dvdcss->i_pos = -1; | |
| 836 return i_read; | |
| 837 } | |
| 838 | |
| 839 dvdcss->i_pos += i_read; | |
| 840 return i_read; | |
| 841 } | |
| 842 #endif | |
| 843 | |
| 844 /***************************************************************************** | |
| 845 * Readv commands. | |
| 846 *****************************************************************************/ | |
| 847 static int libc_readv ( dvdcss_t dvdcss, struct iovec *p_iovec, int i_blocks ) | |
| 848 { | |
| 849 #if defined( WIN32 ) | |
| 850 int i_index, i_len, i_total = 0; | |
| 851 unsigned char *p_base; | |
| 852 int i_bytes; | |
| 853 | |
| 854 for( i_index = i_blocks; | |
| 855 i_index; | |
| 856 i_index--, p_iovec++ ) | |
| 857 { | |
| 858 i_len = p_iovec->iov_len; | |
| 859 p_base = p_iovec->iov_base; | |
| 860 | |
| 861 if( i_len <= 0 ) | |
| 862 { | |
| 863 continue; | |
| 864 } | |
| 865 | |
| 866 i_bytes = read( dvdcss->i_fd, p_base, i_len ); | |
| 867 | |
| 868 if( i_bytes < 0 ) | |
| 869 { | |
| 870 /* One of the reads failed, too bad. | |
| 35952 | 871 * We won't even bother returning the reads that went OK, |
| 872 * and as in the POSIX spec the file position is left | |
| 20613 | 873 * unspecified after a failure */ |
| 874 dvdcss->i_pos = -1; | |
| 875 return -1; | |
| 876 } | |
| 877 | |
| 878 i_total += i_bytes; | |
| 879 | |
| 880 if( i_bytes != i_len ) | |
| 881 { | |
| 882 /* We reached the end of the file or a signal interrupted | |
| 883 * the read. Return a partial read. */ | |
| 884 int i_seek; | |
| 885 | |
| 886 dvdcss->i_pos = -1; | |
| 887 i_seek = libc_seek( dvdcss, i_total / DVDCSS_BLOCK_SIZE ); | |
| 888 if( i_seek < 0 ) | |
| 889 { | |
| 890 return i_seek; | |
| 891 } | |
| 892 | |
| 893 /* We have to return now so that i_pos isn't clobbered */ | |
| 894 return i_total / DVDCSS_BLOCK_SIZE; | |
| 895 } | |
| 896 } | |
| 897 | |
| 898 dvdcss->i_pos += i_total / DVDCSS_BLOCK_SIZE; | |
| 899 return i_total / DVDCSS_BLOCK_SIZE; | |
| 900 #else | |
| 901 int i_read = readv( dvdcss->i_read_fd, p_iovec, i_blocks ); | |
| 902 | |
| 903 if( i_read < 0 ) | |
| 904 { | |
| 905 dvdcss->i_pos = -1; | |
| 906 return i_read; | |
| 907 } | |
| 908 | |
| 909 dvdcss->i_pos += i_read / DVDCSS_BLOCK_SIZE; | |
| 910 return i_read / DVDCSS_BLOCK_SIZE; | |
| 911 #endif | |
| 912 } | |
| 913 | |
| 914 #if defined( WIN32 ) | |
| 915 /***************************************************************************** | |
| 916 * win_readv: vectored read using ReadFile for Win2K and ASPI for win9x | |
| 917 *****************************************************************************/ | |
| 918 static int win_readv ( dvdcss_t dvdcss, struct iovec *p_iovec, int i_blocks ) | |
| 919 { | |
| 920 int i_index; | |
| 921 int i_blocks_read, i_blocks_total = 0; | |
| 922 | |
| 923 /* Check the size of the readv temp buffer, just in case we need to | |
| 924 * realloc something bigger */ | |
| 925 if( dvdcss->i_readv_buf_size < i_blocks * DVDCSS_BLOCK_SIZE ) | |
| 926 { | |
| 927 dvdcss->i_readv_buf_size = i_blocks * DVDCSS_BLOCK_SIZE; | |
| 928 | |
| 929 if( dvdcss->p_readv_buffer ) free( dvdcss->p_readv_buffer ); | |
| 930 | |
| 931 /* Allocate a buffer which will be used as a temporary storage | |
| 932 * for readv */ | |
| 933 dvdcss->p_readv_buffer = malloc( dvdcss->i_readv_buf_size ); | |
| 934 if( !dvdcss->p_readv_buffer ) | |
| 935 { | |
| 936 print_error( dvdcss, " failed (readv)" ); | |
| 937 dvdcss->i_pos = -1; | |
| 938 return -1; | |
| 939 } | |
| 940 } | |
| 941 | |
| 942 for( i_index = i_blocks; i_index; i_index-- ) | |
| 943 { | |
| 944 i_blocks_total += p_iovec[i_index-1].iov_len; | |
| 945 } | |
| 946 | |
| 947 if( i_blocks_total <= 0 ) return 0; | |
| 948 | |
| 949 i_blocks_total /= DVDCSS_BLOCK_SIZE; | |
| 950 | |
| 951 if( WIN2K ) | |
| 952 { | |
| 953 unsigned long int i_bytes; | |
| 954 if( !ReadFile( (HANDLE)dvdcss->i_fd, dvdcss->p_readv_buffer, | |
| 955 i_blocks_total * DVDCSS_BLOCK_SIZE, &i_bytes, NULL ) ) | |
| 956 { | |
| 957 /* The read failed... too bad. | |
| 35952 | 958 * As in the POSIX spec the file position is left |
| 20613 | 959 * unspecified after a failure */ |
| 960 dvdcss->i_pos = -1; | |
| 961 return -1; | |
| 962 } | |
| 963 i_blocks_read = i_bytes / DVDCSS_BLOCK_SIZE; | |
| 964 } | |
| 965 else /* Win9x */ | |
| 966 { | |
| 967 i_blocks_read = aspi_read_internal( dvdcss->i_fd, | |
| 968 dvdcss->p_readv_buffer, | |
| 969 i_blocks_total ); | |
| 970 if( i_blocks_read < 0 ) | |
| 971 { | |
| 972 /* See above */ | |
| 973 dvdcss->i_pos = -1; | |
| 974 return -1; | |
| 975 } | |
| 976 } | |
| 977 | |
| 978 /* We just have to copy the content of the temp buffer into the iovecs */ | |
| 979 for( i_index = 0, i_blocks_total = i_blocks_read; | |
| 980 i_blocks_total > 0; | |
| 981 i_index++ ) | |
| 982 { | |
| 983 memcpy( p_iovec[i_index].iov_base, | |
| 984 dvdcss->p_readv_buffer + (i_blocks_read - i_blocks_total) | |
| 985 * DVDCSS_BLOCK_SIZE, | |
| 986 p_iovec[i_index].iov_len ); | |
| 987 /* if we read less blocks than asked, we'll just end up copying | |
| 988 * garbage, this isn't an issue as we return the number of | |
| 989 * blocks actually read */ | |
| 990 i_blocks_total -= ( p_iovec[i_index].iov_len / DVDCSS_BLOCK_SIZE ); | |
| 991 } | |
| 992 | |
| 993 dvdcss->i_pos += i_blocks_read; | |
| 994 return i_blocks_read; | |
| 995 } | |
| 996 | |
| 997 static int aspi_read_internal( int i_fd, void *p_data, int i_blocks ) | |
| 998 { | |
| 999 HANDLE hEvent; | |
| 35952 | 1000 struct SRB_ExecSCSICmd ssc = { 0 }; |
| 20613 | 1001 struct w32_aspidev *fd = (struct w32_aspidev *) i_fd; |
| 1002 | |
| 1003 /* Create the transfer completion event */ | |
| 1004 hEvent = CreateEvent( NULL, TRUE, FALSE, NULL ); | |
| 1005 if( hEvent == NULL ) | |
| 1006 { | |
| 1007 return -1; | |
| 1008 } | |
| 1009 | |
| 1010 ssc.SRB_Cmd = SC_EXEC_SCSI_CMD; | |
| 1011 ssc.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY; | |
| 1012 ssc.SRB_HaId = LOBYTE( fd->i_sid ); | |
| 1013 ssc.SRB_Target = HIBYTE( fd->i_sid ); | |
| 1014 ssc.SRB_SenseLen = SENSE_LEN; | |
| 1015 | |
| 1016 ssc.SRB_PostProc = (LPVOID) hEvent; | |
| 1017 ssc.SRB_BufPointer = p_data; | |
| 1018 ssc.SRB_CDBLen = 12; | |
| 1019 | |
| 1020 ssc.CDBByte[0] = 0xA8; /* RAW */ | |
| 1021 ssc.CDBByte[2] = (UCHAR) (fd->i_blocks >> 24); | |
| 1022 ssc.CDBByte[3] = (UCHAR) (fd->i_blocks >> 16) & 0xff; | |
| 1023 ssc.CDBByte[4] = (UCHAR) (fd->i_blocks >> 8) & 0xff; | |
| 1024 ssc.CDBByte[5] = (UCHAR) (fd->i_blocks) & 0xff; | |
| 1025 | |
| 35952 | 1026 /* We have to break down the reads into 64KB pieces (ASPI restriction) */ |
| 20613 | 1027 if( i_blocks > 32 ) |
| 1028 { | |
| 1029 ssc.SRB_BufLen = 32 * DVDCSS_BLOCK_SIZE; | |
| 1030 ssc.CDBByte[9] = 32; | |
| 1031 fd->i_blocks += 32; | |
| 1032 | |
| 1033 /* Initiate transfer */ | |
| 1034 ResetEvent( hEvent ); | |
| 1035 fd->lpSendCommand( (void*) &ssc ); | |
| 1036 | |
| 35952 | 1037 /* transfer the next 64KB (aspi_read_internal is called recursively) |
| 20613 | 1038 * We need to check the status of the read on return */ |
| 1039 if( aspi_read_internal( i_fd, | |
| 1040 (uint8_t*) p_data + 32 * DVDCSS_BLOCK_SIZE, | |
| 1041 i_blocks - 32) < 0 ) | |
| 1042 { | |
| 1043 return -1; | |
| 1044 } | |
| 1045 } | |
| 1046 else | |
| 1047 { | |
| 1048 /* This is the last transfer */ | |
| 1049 ssc.SRB_BufLen = i_blocks * DVDCSS_BLOCK_SIZE; | |
| 1050 ssc.CDBByte[9] = (UCHAR) i_blocks; | |
| 1051 fd->i_blocks += i_blocks; | |
| 1052 | |
| 1053 /* Initiate transfer */ | |
| 1054 ResetEvent( hEvent ); | |
| 1055 fd->lpSendCommand( (void*) &ssc ); | |
| 1056 | |
| 1057 } | |
| 1058 | |
| 1059 /* If the command has still not been processed, wait until it's finished */ | |
| 1060 if( ssc.SRB_Status == SS_PENDING ) | |
| 1061 { | |
| 1062 WaitForSingleObject( hEvent, INFINITE ); | |
| 1063 } | |
| 1064 CloseHandle( hEvent ); | |
| 1065 | |
| 1066 /* check that the transfer went as planned */ | |
| 1067 if( ssc.SRB_Status != SS_COMP ) | |
| 1068 { | |
| 1069 return -1; | |
| 1070 } | |
| 1071 | |
| 1072 return i_blocks; | |
| 1073 } | |
| 1074 #endif | |
| 1075 |
