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