Mercurial > mplayer.hg
annotate libdvdcss/device.c @ 36837:4f59b1b06cf2
sync with en/mplayer.1 rev. 36848
author | jrash |
---|---|
date | Tue, 25 Feb 2014 06:22:29 +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 |