Sorry for the delay. The OS2 patches should now be in the libcdio git repository.
I had some problems applying the patch. (Patch wants the original listed first, not second and it would have been helpful to attach this as a separate file). I have no way to check whether these changes work. So please double check my work. (I often make mistakes ;-) Thanks. On Mon, Jan 12, 2009 at 8:31 AM, KO Myung-Hun <[email protected]> wrote: > Hi/2. > > These patches add a OS/2 driver for libcdio-0.81. > > Review, please. > > -- > KO Myung-Hun > > Using Mozilla SeaMonkey 1.1.14 > Under OS/2 Warp 4 for Korean with FixPak #15 > On AMD ThunderBird 1 GHz with 512 MB RAM > > Korean OS/2 User Community : http://www.ecomstation.co.kr > > > > diff -buNr configure.ac.org configure.ac > --- configure.ac.org 2008-10-26 23:48:24.000000000 +0900 > +++ configure.ac 2009-01-09 02:09:10.000000000 +0900 > @@ -529,6 +529,13 @@ > # LIBS="$LIBS -lcam" > cd_drivers="${cd_drivers}, NetBSD " > ;; > + os2*) > + AC_DEFINE([HAVE_OS2_CDROM], [1], > + [Define 1 if you have OS/2 CD-ROM support]) > + LT_NO_UNDEFINED="-no-undefined" > + LDFLAGS="$LDFLAGS -Zbin-files" > + cd_drivers="${cd_drivers}, OS2 " > + ;; > *) > AC_MSG_WARN([Don't have OS CD-reading support for ${host_os}...]) > AC_MSG_WARN([Will use generic support.]) > @@ -563,6 +570,7 @@ > AC_SUBST(HAVE_LINUX_CDROM) > AC_SUBST(HAVE_SOLARIS_CDROM) > AC_SUBST(HAVE_WIN32_CDROM) > +AC_SUBST(HAVE_OS2_CDROM) > > LIBCDIO_SOURCE_PATH="`pwd`" > AC_DEFINE_UNQUOTED(LIBCDIO_SOURCE_PATH, "$LIBCDIO_SOURCE_PATH", > diff -buNr include/cdio/device.h.org include/cdio/device.h > --- include/cdio/device.h.org 2008-03-27 18:28:36.000000000 +0900 > +++ include/cdio/device.h 2009-01-12 22:05:00.000000000 +0900 > @@ -159,6 +159,7 @@ > DRIVER_OSX, /**< Apple OSX Driver */ > DRIVER_WIN32, /**< Microsoft Windows Driver. Includes ASPI and > ioctl access. */ > + DRIVER_OS2, /**< OS/2 Driver */ > DRIVER_NETBSD, /**< NetBSD Driver. */ > DRIVER_CDRDAO, /**< cdrdao format CD image. This is listed > before BIN/CUE, to make the code prefer cdrdao > @@ -810,6 +811,44 @@ > > char **cdio_get_devices_win32(void); > > + /*! Set up CD-ROM for reading using the IBM OS/2 driver. The > + device_name is the some sort of device name. > + > + NULL is returned on error or there is no OS/2 driver. > + > + In some situations of drivers or OS's we can't find a CD device if > + there is no media in it and it is possible for this routine to return > + NULL even though there may be a hardware CD-ROM. > + > + @see cdio_open_cd, cdio_open > + */ > + CdIo_t * cdio_open_os2 (const char *psz_source); > + > + /*! Set up CD-ROM for reading using the IBM OS/2 driver. The > + device_name is the some sort of device name. > + > + NULL is returned on error or there is no OS/2 driver. > + > + @see cdio_open_cd, cdio_open > + */ > + CdIo_t * cdio_open_am_os2 (const char *psz_source, > + const char *psz_access_mode); > + > + /*! Return a string containing the default device name that the > + OS/2 driver would use when none is specified. A scan is made > + for CD-ROM drives with CDs in them. > + > + In some situations of drivers or OS's we can't find a CD device if > + there is no media in it and it is possible for this routine to return > + NULL even though there may be a hardware CD-ROM. > + */ > + char * cdio_get_default_device_os2(void); > + > + /*! Return a list of all of the CD-ROM devices that the OS/2 driver > + can find. > + */ > + char **cdio_get_devices_os2(void); > + > /*! Set up CD-ROM for reading using the Nero driver. The > device_name is the some sort of device name. > > diff -buNr > lib/cdda_interface/common_interface.h.orglib/cdda_interface/common_interface.h > --- lib/cdda_interface/common_interface.h.org 2008-04-23 > 23:59:52.000000000 +0900 > +++ lib/cdda_interface/common_interface.h 2009-01-09 > 01:59:08.000000000 +0900 > @@ -28,7 +28,7 @@ > #include <cdio/types.h> > #include "low_interface.h" > > -#if defined(HAVE_LSTAT) && !defined(HAVE_WIN32_CDROM) > +#if defined(HAVE_LSTAT) && !defined(HAVE_WIN32_CDROM) && > !defined(HAVE_OS2_CDROM) > /* Define this if the CD-ROM device is a file in the filesystem > that can be lstat'd > */ > diff -buNr lib/driver/cdio_private.h.org lib/driver/cdio_private.h > --- lib/driver/cdio_private.h.org 2008-04-23 23:59:52.000000000 > +0900 > +++ lib/driver/cdio_private.h 2009-01-12 22:05:42.000000000 +0900 > @@ -488,6 +488,7 @@ > driver_return_code_t close_tray_osx (const char *psz_drive); > driver_return_code_t close_tray_solaris (const char *psz_drive); > driver_return_code_t close_tray_win32 (const char *psz_drive); > + driver_return_code_t close_tray_os2 (const char *psz_drive); > > bool cdio_have_netbsd(void); > CdIo_t * cdio_open_netbsd (const char *psz_source); > @@ -531,6 +532,10 @@ > True if Microsoft Windows driver is available. */ > bool cdio_have_win32 (void); > > + /*! DEPRICATED: use cdio_have_driver(). > + True if IBM OS/2 driver is available. */ > + bool cdio_have_os2 (void); > + > /*! True if Nero driver is available. */ > bool cdio_have_nrg (void); > > diff -buNr lib/driver/device.c.org lib/driver/device.c > --- lib/driver/device.c.org 2008-04-23 23:59:52.000000000 +0900 > +++ lib/driver/device.c 2009-01-09 01:59:08.000000000 +0900 > @@ -71,6 +71,8 @@ > const driver_id_t cdio_os_driver = DRIVER_SOLARIS; > #elif HAVE_DARWIN_WIN32 > const driver_id_t cdio_os_driver = DRIVER_WIN32; > +#elif HAVE_OS2_CDROM > +const driver_id_t cdio_os_driver = DRIVER_OS2; > #else > const driver_id_t cdio_os_driver = DRIVER_UNKNOWN; > #endif > @@ -213,6 +215,19 @@ > &close_tray_win32 > }, > > + {DRIVER_OS2, > + CDIO_SRC_IS_DEVICE_MASK|CDIO_SRC_IS_NATIVE_MASK|CDIO_SRC_IS_SCSI_MASK, > + "OS2", > + "IBM OS/2 driver", > + &cdio_have_os2, > + &cdio_open_os2, > + &cdio_open_am_os2, > + &cdio_get_default_device_os2, > + &cdio_is_device_os2, > + &cdio_get_devices_os2, > + &close_tray_os2 > + }, > + > {DRIVER_CDRDAO, > CDIO_SRC_IS_DISK_IMAGE_MASK, > "CDRDAO", > @@ -939,6 +954,7 @@ > case DRIVER_SOLARIS: > case DRIVER_WIN32: > case DRIVER_OSX: > + case DRIVER_OS2: > case DRIVER_NRG: > case DRIVER_BINCUE: > case DRIVER_CDRDAO: > diff -buNr lib/driver/generic.h.org lib/driver/generic.h > --- lib/driver/generic.h.org 2008-04-23 23:59:52.000000000 +0900 > +++ lib/driver/generic.h 2009-01-09 02:26:50.000000000 +0900 > @@ -134,6 +134,12 @@ > */ > bool cdio_is_device_win32(const char *source_name); > > + /*! > + Return true if source_name could be a device containing a CD-ROM on > + OS/2 > + */ > + bool cdio_is_device_os2(const char *source_name); > + > > /*! > Return true if source_name could be a device containing a CD-ROM on > diff -buNr lib/driver/Makefile.am.org lib/driver/Makefile.am > --- lib/driver/Makefile.am.org 2008-10-19 18:25:30.000000000 +0900 > +++ lib/driver/Makefile.am 2009-01-06 12:42:40.000000000 +0900 > @@ -90,6 +90,7 @@ > MSWindows/win32.h \ > netbsd.c \ > osx.c \ > + os2.c \ > read.c \ > sector.c \ > solaris.c \ > diff -buNr lib/driver/os2.c.org lib/driver/os2.c > --- lib/driver/os2.c.org 2009-01-09 23:57:26.000000000 +0900 > +++ lib/driver/os2.c 2009-01-11 17:49:36.000000000 +0900 > @@ -0,0 +1,1554 @@ > +/* > + $Id: os2.c,v 1.30 2008/04/21 18:30:21 karl Exp $ > + > + Copyright (C) 2009 KO Myung-Hun <[email protected]> > + > + This program is free software: you can redistribute it and/or modify > + it under the terms of the GNU General Public License as published by > + the Free Software Foundation, either version 3 of the License, or > + (at your option) any later version. > + > + This program is distributed in the hope that it will be useful, > + but WITHOUT ANY WARRANTY; without even the implied warranty of > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + GNU General Public License for more details. > + > + You should have received a copy of the GNU General Public License > + along with this program. If not, see <http://www.gnu.org/licenses/>. > +*/ > + > +/* This file contains OS/2-specific code using the DosDevIOCtl > + access method. > +*/ > + > +#ifdef HAVE_CONFIG_H > +# include "config.h" > +#endif > + > +static const char _rcsid[] = "$Id: os2.c,v 1.30 2008/04/21 18:30:21 karl > Exp $"; > + > +#include <cdio/cdio.h> > +#include <cdio/sector.h> > +#include <cdio/util.h> > +#include <cdio/mmc.h> > +#include "cdio_assert.h" > +#include "cdio_private.h" > + > +#include <string.h> > + > +#ifdef HAVE_OS2_CDROM > + > +#define INCL_DOS > +#define INCL_DOSDEVIOCTL > +#include <os2.h> > + > +#include <ctype.h> > + > + > +typedef struct { > + lsn_t lsn_start; > + UCHAR uc_adr; > + UCHAR uc_control; > +} toc_t; > + > +typedef enum { > + _AM_NONE, > + _AM_OS2, > +} access_mode_t; > + > +typedef struct { > + /* Things common to all drivers like this. > + This must be first. */ > + generic_img_private_t gen; > + > + access_mode_t access_mode; > + > + /* Track information */ > + toc_t toc[CDIO_CD_MAX_TRACKS + 1]; /* 1 more for leadout */ > + int i_first_track; > + int i_last_track; > + > + /* Some of the more OS specific things. */ > + HFILE h_cd; > + BYTE uc_drive; > +} _img_private_t; > + > +#pragma pack(1) > + > +static track_format_t > +get_track_format_os2(const _img_private_t *p_env, track_t i_track); > + > +static bool read_toc_os2 (void *p_user_data); > + > +static int > +run_mmc_cmd_os2( void *p_user_data, unsigned int i_timeout_ms, > + unsigned int i_cdb, const mmc_cdb_t *p_cdb, > + cdio_mmc_direction_t e_direction, > + unsigned int i_buf, /*in/out*/ void *p_buf ); > + > +/*! > + Set the volume of an audio CD. > + > + @param p_cdio the CD object to be acted upon. > + > +*/ > +static driver_return_code_t > +audio_get_volume_os2 (void *p_user_data, > + /*out*/ cdio_audio_volume_t *p_volume) > +{ > + _img_private_t *p_env = p_user_data; > + > + struct { > + UCHAR auch_sign[4]; > + } s_param = {{'C', 'D', '0', '1'}}; > + > + struct { > + struct { > + BYTE uc_in_ch; > + BYTE uc_vol; > + } as_out_ch[4]; > + } s_data; > + > + ULONG ul_param_len; > + ULONG ul_data_len; > + ULONG rc; > + int i; > + > + rc = DosDevIOCtl( > + p_env->h_cd, IOCTL_CDROMAUDIO, CDROMAUDIO_GETCHANNEL, > + &s_param, sizeof( s_param ), &ul_param_len, > + &s_data, sizeof( s_data ), &ul_data_len ); > + > + if( rc ) > + { > + cdio_warn("audio_get_volume_os2 : DosDevIOCtl(GETCHANNEL) = 0x%lx\n", > rc ); > + > + return DRIVER_OP_ERROR; > + } > + > + for( i = 0; i < 4; i++ ) > + p_volume->level[ i ] = s_data.as_out_ch[ i ].uc_vol; > + > + return DRIVER_OP_SUCCESS; > +} > + > +/*! > + Pause playing CD through analog output > + > + @param p_cdio the CD object to be acted upon. > +*/ > +static driver_return_code_t > +audio_pause_os2 (void *p_user_data) > +{ > + _img_private_t *p_env = p_user_data; > + > + struct { > + UCHAR auch_sign[4]; > + } s_param = {{'C', 'D', '0', '1'}}; > + > + ULONG ul_param_len; > + ULONG ul_data_len; > + ULONG rc; > + > + rc = DosDevIOCtl( > + p_env->h_cd, IOCTL_CDROMAUDIO, CDROMAUDIO_STOPAUDIO, > + &s_param, sizeof( s_param ), &ul_param_len, > + NULL, 0, &ul_data_len ); > + > + if( rc ) > + { > + cdio_warn("audio_pause_os2 : DosDevIOCtl(STOPAUDIO) = 0x%lx\n", rc ); > + > + return DRIVER_OP_ERROR; > + } > + > + return DRIVER_OP_SUCCESS; > +} > + > +/*! > + Playing CD through analog output at the given MSF. > + > + @param p_cdio the CD object to be acted upon. > +*/ > +static driver_return_code_t > +audio_play_msf_os2 (void *p_user_data, msf_t *p_start_msf, msf_t > *p_end_msf) > +{ > + _img_private_t *p_env = p_user_data; > + > + struct { > + UCHAR auch_sign[4]; > + BYTE uc_access_mode; > + BYTE uc_start_msf_f; > + BYTE uc_start_msf_s; > + BYTE uc_start_msf_m; > + BYTE uc_start_msf_reserved; > + BYTE uc_end_msf_f; > + BYTE uc_end_msf_s; > + BYTE uc_end_msf_m; > + BYTE uc_end_msf_reserved; > + } s_param = { > + .auch_sign = {'C', 'D', '0', '1'}, > + .uc_access_mode = 01, /* use MSF format */ > + }; > + > + ULONG ul_param_len; > + ULONG ul_data_len; > + ULONG rc; > + > + s_param.uc_start_msf_m = cdio_from_bcd8(p_start_msf->m); > + s_param.uc_start_msf_s = cdio_from_bcd8(p_start_msf->s); > + s_param.uc_start_msf_f = cdio_from_bcd8(p_start_msf->f); > + > + s_param.uc_end_msf_m = cdio_from_bcd8(p_end_msf->m); > + s_param.uc_end_msf_s = cdio_from_bcd8(p_end_msf->s); > + s_param.uc_end_msf_f = cdio_from_bcd8(p_end_msf->f); > + > + rc = DosDevIOCtl( > + p_env->h_cd, IOCTL_CDROMAUDIO, CDROMAUDIO_PLAYAUDIO, > + &s_param, sizeof( s_param ), &ul_param_len, > + NULL, 0, &ul_data_len ); > + > + if( rc ) > + { > + cdio_warn("audio_play_msf_os2 : DosDevIOCtl(PLAYAUDIO) = 0x%lx\n", rc > ); > + > + return DRIVER_OP_ERROR; > + } > + > + return DRIVER_OP_SUCCESS; > +} > + > +/*! > + Read Audio Subchannel information > + > + @param p_cdio the CD object to be acted upon. > + > +*/ > +static driver_return_code_t > +audio_read_subchannel_os2 (void *p_user_data, > + cdio_subchannel_t *p_subchannel) > +{ > + _img_private_t *p_env = p_user_data; > + > + struct { > + UCHAR auch_sign[4]; > + } s_param = {{'C', 'D', '0', '1'}}; > + > + struct { > + BYTE uc_control_and_adr; > + BYTE uc_track_number; /* in BCD */ > + BYTE uc_index; /* in BCD */ > + BYTE uc_running_time_in_track_m; > + BYTE uc_running_time_in_track_s; > + BYTE uc_running_time_in_track_f; > + BYTE uc_reserved; > + BYTE uc_running_time_on_disk_m; > + BYTE uc_running_time_on_disk_s; > + BYTE uc_running_time_on_disk_f; > + } s_data_subchannel_q; > + > + struct { > + USHORT us_audio_status_bits; > + ULONG ul_start_msf; > + ULONG ul_end_msf; > + } s_data_audio_status; > + > + ULONG ul_data_device_status; > + ULONG ul_param_len; > + ULONG ul_data_len; > + ULONG rc; > + > + rc = DosDevIOCtl( > + p_env->h_cd, IOCTL_CDROMAUDIO, CDROMAUDIO_GETSUBCHANNELQ, > + &s_param, sizeof( s_param ), &ul_param_len, > + &s_data_subchannel_q, sizeof( s_data_subchannel_q ), > &ul_data_len ); > + > + if( rc ) > + { > + cdio_warn("audio_read_subchannel_os2 : DosDevIOCtl(GETSUBCHANNELQ) = > 0x%lx\n", rc ); > + > + return DRIVER_OP_ERROR; > + } > + > + rc = DosDevIOCtl( > + p_env->h_cd, IOCTL_CDROMAUDIO, CDROMAUDIO_GETAUDIOSTATUS, > + &s_param, sizeof( s_param ), &ul_param_len, > + &s_data_audio_status, sizeof( s_data_audio_status ), > &ul_data_len ); > + > + if( rc ) > + { > + cdio_warn("audio_read_subchannel_os2 : DosDevIOCtl(GETAUDIOSTATUS) = > 0x%lx\n", rc ); > + > + return DRIVER_OP_ERROR; > + } > + > + rc = DosDevIOCtl( > + p_env->h_cd, IOCTL_CDROMDISK, CDROMDISK_DEVICESTATUS, > + &s_param, sizeof( s_param ), &ul_param_len, > + &ul_data_device_status, sizeof( ul_data_device_status ), > &ul_data_len ); > + > + if( rc ) > + { > + cdio_warn("audio_read_subchannel_os2 : DosDevIOCtl(DEVICESTATUS) = > 0x%lx\n", rc ); > + > + return DRIVER_OP_ERROR; > + } > + > + p_subchannel->track = > cdio_from_bcd8(s_data_subchannel_q.uc_track_number); > + p_subchannel->index = cdio_from_bcd8(s_data_subchannel_q.uc_index); > + > + p_subchannel->abs_addr.m = > cdio_to_bcd8(s_data_subchannel_q.uc_running_time_on_disk_m); > + p_subchannel->abs_addr.s = > cdio_to_bcd8(s_data_subchannel_q.uc_running_time_on_disk_s); > + p_subchannel->abs_addr.f = > cdio_to_bcd8(s_data_subchannel_q.uc_running_time_on_disk_f); > + p_subchannel->rel_addr.m = > cdio_to_bcd8(s_data_subchannel_q.uc_running_time_in_track_m); > + p_subchannel->rel_addr.s = > cdio_to_bcd8(s_data_subchannel_q.uc_running_time_in_track_s); > + p_subchannel->rel_addr.f = > cdio_to_bcd8(s_data_subchannel_q.uc_running_time_in_track_f); > + > + p_subchannel->address = s_data_subchannel_q.uc_control_and_adr > & 0x0F; > + p_subchannel->control = ( s_data_subchannel_q.uc_control_and_adr >> 4 ) > & 0x0F; > + > + if( ul_data_device_status & 0x1000 ) > + p_subchannel->audio_status = CDIO_MMC_READ_SUB_ST_PLAY; > + else if( s_data_audio_status.us_audio_status_bits & 1 ) > + p_subchannel->audio_status = CDIO_MMC_READ_SUB_ST_PAUSED; > + else if( s_data_audio_status.ul_start_msf == 0 && > + s_data_audio_status.ul_end_msf == 0 ) > + p_subchannel->audio_status = CDIO_MMC_READ_SUB_ST_NO_STATUS; > + else > + p_subchannel->audio_status = CDIO_MMC_READ_SUB_ST_COMPLETED; > + > + return DRIVER_OP_SUCCESS; > +} > + > + /*! > + Resume playing an audio CD. > + > + @param p_cdio the CD object to be acted upon. > + > + */ > +static driver_return_code_t > +audio_resume_os2 (void *p_user_data) > +{ > + _img_private_t *p_env = p_user_data; > + > + struct { > + UCHAR auch_sign[4]; > + } s_param = {{'C', 'D', '0', '1'}}; > + > + ULONG ul_param_len; > + ULONG ul_data_len; > + ULONG rc; > + > + rc = DosDevIOCtl( > + p_env->h_cd, IOCTL_CDROMAUDIO, CDROMAUDIO_RESUMEAUDIO, > + &s_param, sizeof( s_param ), &ul_param_len, > + NULL, 0, &ul_data_len ); > + > + if( rc ) > + { > + cdio_warn("audio_resume_os2 : DosDevIOCtl(RESUMEAUDIO) = 0x%lx\n", rc > ); > + > + return DRIVER_OP_ERROR; > + } > + > + return DRIVER_OP_SUCCESS; > +} > + > +/*! > + Set the volume of an audio CD. > + > + @param p_cdio the CD object to be acted upon. > + > +*/ > +static driver_return_code_t > +audio_set_volume_os2 ( void *p_user_data, cdio_audio_volume_t *p_volume) > +{ > + _img_private_t *p_env = p_user_data; > + > + struct { > + UCHAR auch_sign[4]; > + } s_param = {{'C', 'D', '0', '1'}}; > + > + struct { > + struct { > + BYTE uc_in_ch; > + BYTE uc_vol; > + } as_out_ch[4]; > + } s_data; > + > + ULONG ul_param_len; > + ULONG ul_data_len; > + ULONG rc; > + int i; > + > + /* first retrive current input ch. */ > + rc = DosDevIOCtl( > + p_env->h_cd, IOCTL_CDROMAUDIO, CDROMAUDIO_GETCHANNEL, > + &s_param, sizeof( s_param ), &ul_param_len, > + &s_data, sizeof( s_data ), &ul_data_len ); > + > + if( rc ) > + { > + cdio_warn("audio_set_volume_os2 : DosDevIOCtl(GETCHANNEL) = 0x%lx\n", > rc ); > + > + return DRIVER_OP_ERROR; > + } > + > + for( i = 0; i < 4; i++ ) > + s_data.as_out_ch[ i ].uc_vol = p_volume->level[ i ]; > + > + /* now set volumes */ > + rc = DosDevIOCtl( > + p_env->h_cd, IOCTL_CDROMAUDIO, CDROMAUDIO_SETCHANNELCTRL, > + &s_param, sizeof( s_param ), &ul_param_len, > + &s_data, sizeof( s_data ), &ul_data_len ); > + > + if( rc ) > + { > + cdio_warn("audio_set_volume_os2 : DosDevIOCtl(SETCHANNELCTRL) = > 0x%lx\n", rc ); > + > + return DRIVER_OP_ERROR; > + } > + > + return DRIVER_OP_SUCCESS; > +} > + > +static driver_return_code_t > +audio_stop_os2 (void *p_user_data) > +{ > + _img_private_t *p_env = p_user_data; > + > + struct { > + UCHAR auch_sign[4]; > + } s_param = {{'C', 'D', '0', '1'}}; > + > + ULONG ul_param_len; > + ULONG ul_data_len; > + ULONG rc; > + > + rc = DosDevIOCtl( > + p_env->h_cd, IOCTL_CDROMAUDIO, CDROMAUDIO_STOPAUDIO, > + &s_param, sizeof( s_param ), &ul_param_len, > + NULL, 0, &ul_data_len ); > + > + if( rc ) > + { > + cdio_warn("audio_stop_os2 : DosDevIOCtl(STOPAUDIO) = 0x%lx\n", rc ); > + > + return DRIVER_OP_ERROR; > + } > + > + return DRIVER_OP_SUCCESS; > +} > + > +/*! > + Get disc type associated with cd object. > +*/ > +static discmode_t > +dvd_discmode_os2 (_img_private_t *p_env) > +{ > + discmode_t discmode=CDIO_DISC_MODE_NO_INFO; > + driver_return_code_t rc; > + > + /* See if this is a DVD. */ > + cdio_dvd_struct_t dvd; /* DVD READ STRUCT for layer 0. */ > + > + dvd.physical.type = CDIO_DVD_STRUCT_PHYSICAL; > + dvd.physical.layer_num = 0; > + > + rc = mmc_get_dvd_struct_physical_private (p_env, &run_mmc_cmd_os2, > + &dvd); > + > + if (DRIVER_OP_SUCCESS == rc) { > + switch(dvd.physical.layer[0].book_type) { > + case CDIO_DVD_BOOK_DVD_ROM: return CDIO_DISC_MODE_DVD_ROM; > + case CDIO_DVD_BOOK_DVD_RAM: return CDIO_DISC_MODE_DVD_RAM; > + case CDIO_DVD_BOOK_DVD_R: return CDIO_DISC_MODE_DVD_R; > + case CDIO_DVD_BOOK_DVD_RW: return CDIO_DISC_MODE_DVD_RW; > + case CDIO_DVD_BOOK_DVD_PR: return CDIO_DISC_MODE_DVD_PR; > + case CDIO_DVD_BOOK_DVD_PRW: return CDIO_DISC_MODE_DVD_PRW; > + default: return CDIO_DISC_MODE_DVD_OTHER; > + } > + } > + return discmode; > +} > + > +/*! > + Get disc type associated with the cd object. > +*/ > +static discmode_t > +get_discmode_os2(void *p_user_data) > +{ > + _img_private_t *p_env = p_user_data; > + > + track_t i_track; > + discmode_t discmode; > + > + if (!p_env) return CDIO_DISC_MODE_ERROR; > + > + discmode = dvd_discmode_os2(p_env); > + > + if (CDIO_DISC_MODE_NO_INFO != discmode) return discmode; > + > + if (!p_env->gen.toc_init) read_toc_os2 (p_env); > + > + if (!p_env->gen.toc_init) return CDIO_DISC_MODE_ERROR; > + > + for (i_track = p_env->gen.i_first_track; > + i_track < p_env->gen.i_first_track + p_env->gen.i_tracks ; > + i_track ++) { > + track_format_t track_fmt=get_track_format_os2(p_env, i_track); > + > + switch(track_fmt) { > + case TRACK_FORMAT_AUDIO: > + switch(discmode) { > + case CDIO_DISC_MODE_NO_INFO: > + discmode = CDIO_DISC_MODE_CD_DA; > + break; > + case CDIO_DISC_MODE_CD_DA: > + case CDIO_DISC_MODE_CD_MIXED: > + case CDIO_DISC_MODE_ERROR: > + /* No change*/ > + break; > + default: > + discmode = CDIO_DISC_MODE_CD_MIXED; > + } > + break; > + case TRACK_FORMAT_XA: > + switch(discmode) { > + case CDIO_DISC_MODE_NO_INFO: > + discmode = CDIO_DISC_MODE_CD_XA; > + break; > + case CDIO_DISC_MODE_CD_XA: > + case CDIO_DISC_MODE_CD_MIXED: > + case CDIO_DISC_MODE_ERROR: > + /* No change*/ > + break; > + default: > + discmode = CDIO_DISC_MODE_CD_MIXED; > + } > + break; > + case TRACK_FORMAT_DATA: > + switch(discmode) { > + case CDIO_DISC_MODE_NO_INFO: > + discmode = CDIO_DISC_MODE_CD_DATA; > + break; > + case CDIO_DISC_MODE_CD_DATA: > + case CDIO_DISC_MODE_CD_MIXED: > + case CDIO_DISC_MODE_ERROR: > + /* No change*/ > + break; > + default: > + discmode = CDIO_DISC_MODE_CD_MIXED; > + } > + break; > + case TRACK_FORMAT_ERROR: > + default: > + discmode = CDIO_DISC_MODE_ERROR; > + } > + } > + return discmode; > +} > + > +#define CDROMDISK_EXECMD 0x7A > + > +/* 0, if transfer data to device, 1, if transfer data from device */ > +#define EX_DIRECTION_IN 0x0001 > +/* 0, if don't check playing audio, 1, if device plays audio return error > */ > +#define EX_PLAYING_CHK 0x0002 > + > +/*! > + Run a SCSI MMC command. > + > + env private CD structure > + i_timeout_ms time in milliseconds we will wait for the command > + to complete. If this value is -1, use the default > + time-out value. > + p_buf Buffer for data, both sending and receiving > + i_buf Size of buffer > + e_direction direction the transfer is to go. > + cdb CDB bytes. All values that are needed should be set on > + input. We'll figure out what the right CDB length should > be. > + > + Return 0 if command completed successfully. > + */ > +static int > +run_mmc_cmd_os2( void *p_user_data, unsigned int i_timeout_ms, > + unsigned int i_cdb, const mmc_cdb_t *p_cdb, > + cdio_mmc_direction_t e_direction, > + unsigned int i_buf, /*in/out*/ void *p_buf ) > +{ > + _img_private_t *p_env = p_user_data; > + > + struct { > + UCHAR auch_sign[4]; // 'CD01' > + USHORT us_data_length; // length of the Data Packet > + USHORT us_cmd_length; // length of the Command Buffer > + USHORT us_flags; // flags > + BYTE auc_cmd_buffer[16]; // Command Buffer for SCSI command > + } s_param = { > + .auch_sign = {'C', 'D', '0', '1'}, > + }; > + > + ULONG ul_param_len; > + ULONG ul_data_len; > + ULONG rc; > + > + s_param.us_data_length = i_buf; > + s_param.us_cmd_length = i_cdb; > + s_param.us_flags = > + ( e_direction == SCSI_MMC_DATA_READ ) ? EX_DIRECTION_IN : 0; > + > + memcpy( s_param.auc_cmd_buffer, p_cdb, i_cdb ); > + > + rc = DosDevIOCtl( > + p_env->h_cd, IOCTL_CDROMDISK, CDROMDISK_EXECMD, > + &s_param, sizeof( s_param ), &ul_param_len, > + p_buf, i_buf, &ul_data_len ); > + > + if( rc ) > + { > + cdio_warn("run_mmc_cmd_os2 : DosDevIOCtl(EXECMD) = 0x%lx\n", rc ); > + > + return DRIVER_OP_ERROR; > + } > + > + return DRIVER_OP_SUCCESS; > +} > + > +/*! > + Initialize CD device. > + */ > +static bool > +init_os2 (void *p_user_data) > +{ > + _img_private_t *p_env = p_user_data; > + > + ULONG ul_action; > + ULONG rc; > + > + if (p_env->gen.init) { > + cdio_warn ("init called more than once"); > + return false; > + } > + > + /* Initializations */ > + p_env->h_cd = 0; > + > + rc = DosOpen((PSZ)p_env->gen.source_name, &p_env->h_cd, > + &ul_action, 0, FILE_NORMAL, > + OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW, > + OPEN_ACCESS_READONLY | OPEN_SHARE_DENYNONE | > OPEN_FLAGS_DASD, > + NULL ); > + if( rc ) > + { > + cdio_warn("init_os2 : DosOpen(%s) = %ld\n", p_env->gen.source_name, rc > ); > + > + return false; > + } > + > + p_env->uc_drive = toupper( p_env->gen.source_name[ 0 ]) - 'A'; > + > + p_env->gen.init = true; > + p_env->gen.toc_init = false; > + p_env->gen.b_cdtext_init = false; > + p_env->gen.b_cdtext_error = false; > + p_env->gen.fd = p_env->h_cd; > + > + return true; > +} > + > +/*! > + Release and free resources associated with cd. > + */ > +static void > +free_os2 (void *p_user_data) > +{ > + _img_private_t *p_env = p_user_data; > + > + if( !p_env ) > + return; > + > + free (p_env->gen.source_name); > + > + if( p_env->h_cd ) > + DosClose( p_env->h_cd ); > + > + free (p_env); > + > +} > + > +/*! > + Reads i_blocks of audio sectors from cd device into p_data starting > + from i_lsn. > + Returns DRIVER_OP_SUCCESS if no error. > + */ > +static int > +read_audio_sectors_os2 (void *p_user_data, void *p_buf, lsn_t i_lsn, > + unsigned int i_blocks) > +{ > + _img_private_t *p_env = p_user_data; > + > + struct > + { > + UCHAR auch_sign[ 4 ]; > + BYTE uc_addr_mode; > + USHORT us_sectors; > + ULONG ul_start_sector; > + BYTE uc_reserved; > + BYTE uc_interleaved_size; > + } s_param = { > + .auch_sign = {'C', 'D', '0', '1'}, > + .uc_addr_mode = 0, /* use LBA format */ > + }; > + > + ULONG ul_param_len; > + ULONG ul_data_len; > + ULONG rc; > + > + s_param.us_sectors = i_blocks; > + s_param.ul_start_sector = i_lsn; > + > + rc = DosDevIOCtl( > + p_env->h_cd, IOCTL_CDROMDISK, CDROMDISK_READLONG, > + &s_param, sizeof( s_param ), &ul_param_len, > + p_buf, CDIO_CD_FRAMESIZE_RAW * i_blocks, &ul_data_len ); > + > + if( rc ) > + { > + cdio_warn("read_audio_sectors_os2 : DosDevIOCtl(READLONG) = 0x%lx\n", > rc ); > + > + return DRIVER_OP_ERROR; > + } > + > + return DRIVER_OP_SUCCESS; > +} > + > +/*! > + Reads a single raw sector using the DosDevIOCtl method into > + data starting from lsn. Returns 0 if no error. > + */ > +static int > +read_raw_sector (_img_private_t *p_env, void *p_buf, lsn_t lsn) > +{ > + struct > + { > + UCHAR auch_sign[ 4 ]; > + BYTE uc_addr_mode; > + USHORT us_sectors; > + ULONG ul_start_sector; > + BYTE uc_reserved; > + BYTE uc_interleaved_size; > + } s_param = { > + .auch_sign = {'C', 'D', '0', '1'}, > + .uc_addr_mode = 0, /* use LBA format */ > + .us_sectors = 1, > + }; > + > + ULONG ul_param_len; > + ULONG ul_data_len; > + ULONG rc; > + > + s_param.ul_start_sector = lsn; > + > + rc = DosDevIOCtl( > + p_env->h_cd, IOCTL_CDROMDISK, CDROMDISK_READLONG, > + &s_param, sizeof( s_param ), &ul_param_len, > + p_buf, CDIO_CD_FRAMESIZE_RAW, &ul_data_len ); > + > + if( rc ) > + { > + cdio_warn("read_raw_sector : DosDevIOCtl(READLONG) = 0x%lx\n", rc ); > + > + return DRIVER_OP_ERROR; > + } > + > + return DRIVER_OP_SUCCESS; > +} > + > +/*! > + Reads a single mode1 sector from cd device into data starting from > + lsn. Returns 0 if no error. > + */ > +static int > +read_mode1_sector_os2 (void *p_user_data, void *p_buf, lsn_t lsn, > + bool b_form2) > +{ > + _img_private_t *p_env = p_user_data; > + char buf[CDIO_CD_FRAMESIZE_RAW] = { 0, }; > + int ret = read_raw_sector (p_env, buf, lsn); > + > + if ( 0 != ret) return ret; > + > + memcpy (p_buf, > + buf + CDIO_CD_SYNC_SIZE+CDIO_CD_HEADER_SIZE, > + b_form2 ? M2RAW_SECTOR_SIZE: CDIO_CD_FRAMESIZE); > + > + return 0; > +} > + > +/*! > + Reads nblocks of mode1 sectors from cd device into data starting > + from lsn. > + Returns 0 if no error. > + */ > +static int > +read_mode1_sectors_os2 (void *p_user_data, void *p_buf, lsn_t lsn, > + bool b_form2, unsigned int nblocks) > +{ > + _img_private_t *p_env = p_user_data; > + int i; > + int retval; > + > + for (i = 0; i < nblocks; i++) { > + if (b_form2) { > + retval = read_mode1_sector_os2 ( > + p_env, ((char *)p_buf) + > + (M2RAW_SECTOR_SIZE * i), > + lsn + i, true); > + if ( retval ) return retval; > + } else { > + char buf[M2RAW_SECTOR_SIZE] = { 0, }; > + if ( (retval = read_mode1_sector_os2 (p_env, buf, lsn + i, false)) ) > + return retval; > + > + memcpy (((char *)p_buf) + (CDIO_CD_FRAMESIZE * i), > + buf, CDIO_CD_FRAMESIZE); > + } > + } > + return 0; > +} > + > +/*! > + Reads a single mode2 sector from cd device into data starting > + from lsn. Returns 0 if no error. > + */ > +static int > +read_mode2_sector_os2 (void *p_user_data, void *data, lsn_t lsn, > + bool b_form2) > +{ > + _img_private_t *p_env = p_user_data; > + char buf[CDIO_CD_FRAMESIZE_RAW] = { 0, }; > + int ret = read_raw_sector (p_env, buf, lsn); > + > + if ( 0 != ret) return ret; > + > + memcpy (data, > + buf + CDIO_CD_SYNC_SIZE + CDIO_CD_XA_HEADER, > + b_form2 ? M2RAW_SECTOR_SIZE: CDIO_CD_FRAMESIZE); > + > + return 0; > +} > + > +/*! > + Reads nblocks of mode2 sectors from cd device into data starting > + from lsn. > + Returns 0 if no error. > + */ > +static int > +read_mode2_sectors_os2 (void *p_user_data, void *data, lsn_t lsn, > + bool b_form2, unsigned int i_blocks) > +{ > + int i; > + int retval; > + unsigned int blocksize = b_form2 ? M2RAW_SECTOR_SIZE : > CDIO_CD_FRAMESIZE; > + > + for (i = 0; i < i_blocks; i++) { > + if ( (retval = read_mode2_sector_os2 (p_user_data, > + ((char *)data) + (blocksize * i), > + lsn + i, b_form2)) ) > + return retval; > + } > + return 0; > +} > + > +/*! > + Return the size of the CD in logical block address (LBA) units. > + */ > +static lsn_t > +get_disc_last_lsn_os2 (void *p_user_data) > +{ > + _img_private_t *p_env = p_user_data; > + > + struct { > + UCHAR auch_sign[4]; > + } s_param = {{'C', 'D', '0', '1'}}; > + > + ULONG ul_data_volume_size; > + ULONG ul_param_len; > + ULONG ul_data_len; > + ULONG rc; > + > + rc = DosDevIOCtl( > + p_env->h_cd, IOCTL_CDROMDISK, CDROMDISK_GETVOLUMESIZE, > + &s_param, sizeof( s_param ), &ul_param_len, > + &ul_data_volume_size, sizeof( ul_data_volume_size ), > &ul_data_len ); > + > + if( rc ) > + { > + cdio_warn("get_disc_last_lsn_os2 : DosDevIOCtl(GETVOLUMESIZE) = > 0x%lx\n", rc ); > + > + return CDIO_INVALID_LSN; > + } > + > + return ul_data_volume_size; > +} > + > +/*! > + Set the key "arg" to "value" in source device. > +*/ > +static int > +set_arg_os2 (void *p_user_data, const char key[], const char value[]) > +{ > + _img_private_t *p_env = p_user_data; > + > + if (!strcmp (key, "source")) > + { > + if (!value) > + return DRIVER_OP_ERROR; > + > + free (p_env->gen.source_name); > + p_env->gen.source_name = strdup (value); > + } > + else if (!strcmp (key, "access-mode")) > + { > + if (!strcmp(value, "OS2")) > + p_env->access_mode = _AM_OS2; > + else > + cdio_warn ("unknown access type: %s. ignored.", value); > + } > + else > + return DRIVER_OP_ERROR; > + > + return DRIVER_OP_SUCCESS; > +} > + > +/*! > + Read and cache the CD's Track Table of Contents and track info. > + Return true if successful or false if an error. > +*/ > +static bool > +read_toc_os2 (void *p_user_data) > +{ > + _img_private_t *p_env = p_user_data; > + > + struct { > + UCHAR auch_sign[4]; > + } s_param_disk = {{'C', 'D', '0', '1'}}; > + > + struct { > + BYTE uc_first_track; > + BYTE uc_last_track; > + ULONG ul_lead_out_addr; /* in MSF */ > + } s_data_disk; > + > + struct { > + UCHAR auch_sign[4]; > + BYTE uc_track; > + } s_param_track = { > + .auch_sign = {'C', 'D', '0', '1'}, > + }; > + > + struct { > + ULONG ul_track_addr; /* in MSF */ > + BYTE uc_control_and_adr; > + } s_data_track; > + > + ULONG ul_param_len; > + ULONG ul_data_len; > + ULONG rc; > + int i_track; > + > + rc = DosDevIOCtl( > + p_env->h_cd, IOCTL_CDROMAUDIO, CDROMAUDIO_GETAUDIODISK, > + &s_param_disk, sizeof( s_param_disk ), &ul_param_len, > + &s_data_disk, sizeof( s_data_disk ), &ul_data_len ); > + > + if( rc ) > + { > + cdio_warn("read_toc_os2 : DosDevIOCtl(GETAUDIODISK) = 0x%lx\n", rc ); > + > + return false; > + } > + > + p_env->gen.i_first_track = s_data_disk.uc_first_track; > + p_env->gen.i_tracks = s_data_disk.uc_last_track - > s_data_disk.uc_first_track + 1; > + > + p_env->i_first_track = s_data_disk.uc_first_track; > + p_env->i_last_track = s_data_disk.uc_last_track; > + > + for( i_track = p_env->i_first_track; i_track <= p_env->i_last_track; > i_track++ ) > + { > + s_param_track.uc_track = i_track; > + > + rc = DosDevIOCtl( > + p_env->h_cd, IOCTL_CDROMAUDIO, CDROMAUDIO_GETAUDIOTRACK, > + &s_param_track, sizeof( s_param_track ), &ul_param_len, > + &s_data_track, sizeof( s_data_track ), &ul_data_len ); > + > + if( rc ) > + { > + cdio_warn("read_toc_os2 : DosDevIOCtl(GETAUDIOTRACK) = 0x%lx\n", rc > ); > + > + return false; > + } > + > + p_env->toc[i_track].lsn_start = > + cdio_lba_to_lsn( cdio_msf3_to_lba( > + ( s_data_track.ul_track_addr >> 16 ) & 0xFF, > + ( s_data_track.ul_track_addr >> 8 ) & 0xFF, > + s_data_track.ul_track_addr & 0xFF )); > + > + p_env->toc[i_track].uc_adr = s_data_track.uc_control_and_adr > & 0x0F; > + p_env->toc[i_track].uc_control = ( s_data_track.uc_control_and_adr >> > 4 ) & 0x0F; > + > + p_env->gen.track_flags[i_track].preemphasis = > + p_env->toc[i_track].uc_control & 0x01 > + ? CDIO_TRACK_FLAG_TRUE : CDIO_TRACK_FLAG_FALSE; > + > + p_env->gen.track_flags[i_track].copy_permit = > + p_env->toc[i_track].uc_control & 0x02 > + ? CDIO_TRACK_FLAG_TRUE : CDIO_TRACK_FLAG_FALSE; > + > + p_env->gen.track_flags[i_track].channels = > + p_env->toc[i_track].uc_control & 0x08 ? 4 : 2; > + } > + > + /* store lead out info */ > + p_env->toc[p_env->i_last_track + 1].lsn_start = > + cdio_lba_to_lsn( cdio_msf3_to_lba( > + ( s_data_disk.ul_lead_out_addr >> 16 ) & 0xFF, > + ( s_data_disk.ul_lead_out_addr >> 8 ) & 0xFF, > + s_data_disk.ul_lead_out_addr & 0xFF )); > + > + p_env->gen.toc_init = true; > + > + return true; > +} > + > +/*! > + Eject media. > + */ > +static driver_return_code_t > +eject_media_os2 (void *p_user_data) > +{ > + _img_private_t *p_env = p_user_data; > + > + struct { > + BYTE uc_cmd_info; > + BYTE uc_drive; > + } s_param; > + > + ULONG ul_param_len; > + ULONG ul_data_len; > + ULONG rc; > + > + s_param.uc_cmd_info = 2; > + s_param.uc_drive = p_env->uc_drive; > + > + rc = DosDevIOCtl( > + ( HFILE )-1, IOCTL_DISK, DSK_UNLOCKEJECTMEDIA, > + &s_param, sizeof( s_param ), &ul_param_len, > + NULL, 0, &ul_data_len ); > + > + if( rc ) > + { > + cdio_warn("eject_media_os2 : DosDevIOCtl(UNLOCKEJECTMEDIA) = 0x%lx\n", > rc ); > + > + return DRIVER_OP_ERROR; > + } > + > + return DRIVER_OP_SUCCESS; > +} > + > +/*! > + Return the value associated with the key "arg". > +*/ > +static const char * > +get_arg_os2 (void *p_user_data, const char key[]) > +{ > + _img_private_t *p_env = p_user_data; > + > + if (!strcmp (key, "source")) { > + return p_env->gen.source_name; > + } else if (!strcmp (key, "access-mode")) { > + switch (p_env->access_mode) { > + case _AM_OS2: > + return "OS2"; > + case _AM_NONE: > + return "no access method"; > + } > + } > + return NULL; > +} > + > +/*! > + Return the media catalog number MCN. > + > + Note: string is malloc'd so caller should free() then returned > + string when done with it. > + > + */ > +static char * > +_cdio_get_mcn (const void *p_user_data) { > + const _img_private_t *p_env = p_user_data; > + return mmc_get_mcn( p_env->gen.cdio ); > +} > + > +/*! > + Get the format (XA, DATA, AUDIO) of a track. > +*/ > +static track_format_t > +get_track_format_os2(const _img_private_t *p_env, track_t i_track) > +{ > + /* This is pretty much copied from the "badly broken" cdrom_count_tracks > + in linux/cdrom.c. > + */ > + > + if (p_env->toc[i_track].uc_control & 0x04) { > + if (p_env->toc[i_track].uc_adr == 0x10) > + return TRACK_FORMAT_CDI; > + else if (p_env->toc[i_track].uc_adr == 0x20) > + return TRACK_FORMAT_XA; > + else > + return TRACK_FORMAT_DATA; > + } else > + return TRACK_FORMAT_AUDIO; > +} > + > +/*! > + Get format of track. > +*/ > +static track_format_t > +_cdio_get_track_format(void *p_obj, track_t i_track) > +{ > + _img_private_t *p_env = p_obj; > + > + if ( !p_env ) > + return TRACK_FORMAT_ERROR; > + > + if (!p_env->gen.toc_init) > + if (!read_toc_os2 (p_env)) > + return TRACK_FORMAT_ERROR; > + > + if ( i_track < p_env->gen.i_first_track > + || i_track >= p_env->gen.i_tracks + p_env->gen.i_first_track ) > + return TRACK_FORMAT_ERROR; > + > + return get_track_format_os2(p_env, i_track); > +} > + > +/*! > + Return true if we have XA data (green, mode2 form1) or > + XA data (green, mode2 form2). That is track begins: > + sync - header - subheader > + 12 4 - 8 > + > + FIXME: there's gotta be a better design for this and get_track_format? > +*/ > +static bool > +_cdio_get_track_green(void *p_obj, track_t i_track) > +{ > + _img_private_t *p_env = p_obj; > + > + switch (_cdio_get_track_format(p_env, i_track)) { > + case TRACK_FORMAT_XA: > + return true; > + case TRACK_FORMAT_ERROR: > + case TRACK_FORMAT_CDI: > + case TRACK_FORMAT_AUDIO: > + return false; > + case TRACK_FORMAT_DATA: > + default: > + break; > + } > + > + /* FIXME: Dunno if this is the right way, but it's what > + I was using in cd-info for a while. > + */ > + return ((p_env->toc[i_track].uc_control & 2) != 0); > +} > + > +/*! > + Return the starting MSF (minutes/secs/frames) for track number > + i_tracks in obj. Track numbers start at 1. > + The "leadout" track is specified either by > + using i_tracks LEADOUT_TRACK or the total tracks+1. > + False is returned if there is no track entry. > +*/ > +static bool > +_cdio_get_track_msf(void *p_user_data, track_t i_tracks, msf_t *p_msf) > +{ > + _img_private_t *p_env = p_user_data; > + > + if (!p_msf) > + return false; > + > + if (!p_env->gen.toc_init) > + if (!read_toc_os2 (p_env)) > + return false; > + > + if (i_tracks == CDIO_CDROM_LEADOUT_TRACK) > + i_tracks = p_env->gen.i_tracks+1; > + > + if (i_tracks > p_env->gen.i_tracks+1 || i_tracks == 0) { > + return false; > + } else { > + cdio_lsn_to_msf(p_env->toc[i_tracks].lsn_start, p_msf); > + return true; > + } > +} > + > +#endif /* HAVE_OS2_CDROM */ > + > +/*! > + Return an array of strings giving possible CD devices. > + */ > +char ** > +cdio_get_devices_os2 (void) > +{ > +#ifndef HAVE_OS2_CDROM > + return NULL; > +#else > + char **drives = NULL; > + unsigned int num_drives=0; > + > + struct { > + BYTE uc_cmd_info; > + BYTE uc_drive; > + } s_param; > + > + struct { > + struct { > + USHORT us_bytes_per_sector; > + BYTE uc_sectors_per_cluster; > + USHORT us_reserved_sectors; > + BYTE uc_number_of_fats; > + USHORT us_root_dir_entries; > + USHORT us_total_sectors; > + BYTE uc_media_descriptor; > + USHORT us_sectors_per_fat; > + USHORT us_sectors_per_track; > + USHORT us_number_of_heads; > + ULONG ul_hidden_sectors; > + ULONG ul_large_total_sectors; > + BYTE auc_reserved[6]; > + } s_ebpb; > + > + USHORT us_cylinders; > + BYTE uc_dev_type; > + USHORT us_dev_attr; > + } s_data; > + > + ULONG ul_param_len; > + ULONG ul_data_len; > + UCHAR uc_drive; > + char sz_drive_str[ 3 ] = "X:"; > + ULONG rc; > + > + /* Scan the system for CD-ROM drives. > + */ > + > + for( uc_drive = 0; uc_drive < 26; uc_drive++ ) > + { > + s_param.uc_cmd_info = 0; > + s_param.uc_drive = uc_drive; > + > + rc = DosDevIOCtl( > + ( HFILE )-1, IOCTL_DISK, DSK_GETDEVICEPARAMS, > + &s_param, sizeof( s_param ), &ul_param_len, > + &s_data, sizeof( s_data ), &ul_data_len ); > + > + if( rc ) > + continue; > + > + switch( s_data.s_ebpb.uc_media_descriptor ) > + { > + case 4 : /* CD-R */ > + case 128 + 4 : /* CD-R but cannot be written */ > + case 5 : /* CD-ROM */ > + case 128 + 5 : /* CD-ROM but cannot be written */ > + case 6 : /* DVD-ROM */ > + case 128 + 6 : /* DVD-ROM but cannot be written */ > + case 7 : /* DVD-RAM */ > + case 128 + 7 : /* DVD-RAM but cannot be written */ > + case 8 : /* CD-RW */ > + case 128 + 8 : /* CD-RW but cannot be written */ > + case 9 : /* DVD-R */ > + case 128 + 9 : /* DVD-R but cannot be written */ > + case 10 : /* DVD-RW */ > + case 128 + 10 : /* DVD-RW but cannot be written */ > + case 11 : /* DVD+RW */ > + case 128 + 11 : /* DVD+RW but cannot be written */ > + sz_drive_str[0] = 'A' + uc_drive; > + cdio_add_device_list(&drives, strdup(sz_drive_str), &num_drives); > + break; > + } > + } > + > + cdio_add_device_list(&drives, NULL, &num_drives); > + return drives; > +#endif /*HAVE_OS2_CDROM*/ > +} > + > +#define IOCTL_CDROMDISK2 0x82 > + > +#define CDROMDISK2_DRIVELETTERS 0x60 > + > +/*! > + Return a string containing the default CD device if none is specified. > + if CdIo is NULL (we haven't initialized a specific device driver), > + then find a suitable one and return the default device for that. > + > + NULL is returned if we couldn't get a default device. > +*/ > +char * > +cdio_get_default_device_os2(void) > +{ > +#ifdef HAVE_OS2_CDROM > + struct { > + USHORT us_drive_count; > + USHORT us_drive_first; > + } s_drive_letters; > + > + HFILE h_cd2; > + ULONG ul_action; > + ULONG ul_param_len; > + ULONG ul_data_len; > + char sz_drive_str[ 3 ] = "X:"; > + ULONG rc; > + > + rc = DosOpen((PSZ)"CD-ROM2$", &h_cd2, &ul_action, 0, FILE_NORMAL, > + OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW, > + OPEN_ACCESS_READONLY | OPEN_SHARE_DENYNONE, > + NULL ); > + > + if( rc ) > + { > + cdio_warn("cdio_get_default_device_os2 : DosOpen(CD-ROM2$) = %ld\n", > rc ); > + > + return NULL; > + } > + > + rc = DosDevIOCtl( > + h_cd2, IOCTL_CDROMDISK2, CDROMDISK2_DRIVELETTERS, > + NULL, 0, &ul_param_len, > + &s_drive_letters, sizeof( s_drive_letters ), &ul_data_len ); > + > + DosClose( h_cd2 ); > + > + if( rc ) > + { > + cdio_warn("cdio_get_default_device_os2 : DosDevIOCtl(DRIVELETTERS) = > 0x%lx\n", rc ); > + > + return NULL; > + } > + > + if( s_drive_letters.us_drive_count == 0 ) > + return NULL; > + > + sz_drive_str[0] = 'A' + s_drive_letters.us_drive_first; > + > + return strdup( sz_drive_str ); > +#else > + return NULL; > +#endif > +} > + > +/*! > + Return true if source_name could be a device containing a CD-ROM. > +*/ > +bool > +cdio_is_device_os2(const char *source_name) > +{ > + if (!source_name) > + return false; > + > +#ifdef HAVE_OS2_CDROM > + return (isalpha(source_name[0]) && > + source_name[1] == ':' && > + source_name[2] == '\0'); > +#else > + return false; > +#endif > +} > + > +/*! > + Close tray on CD-ROM. > + > + @param p_user_data the CD object to be acted upon. > + > +*/ > +driver_return_code_t > +close_tray_os2 (const char *psz_os2_drive) > +{ > +#ifdef HAVE_OS2_CDROM > + struct { > + BYTE uc_cmd_info; > + BYTE uc_drive; > + } s_param; > + > + ULONG ul_param_len; > + ULONG ul_data_len; > + ULONG rc; > + > + s_param.uc_cmd_info = 3; > + s_param.uc_drive = toupper(psz_os2_drive[0]) - 'A'; > + > + rc = DosDevIOCtl( > + ( HFILE )-1, IOCTL_DISK, DSK_UNLOCKEJECTMEDIA, > + &s_param, sizeof( s_param ), &ul_param_len, > + NULL, 0, &ul_data_len ); > + > + if( rc && rc != 99 /* device in use */ ) > + { > + cdio_warn("close_tray_os2 : DosDevIOCtl(UNLOCKEJECTMEDIA) = 0x%lx\n", > rc ); > + > + return DRIVER_OP_ERROR; > + } > + > + return DRIVER_OP_SUCCESS; > +#else > + return DRIVER_OP_UNSUPPORTED; > +#endif /* HAVE_OS2_CDROM */ > +} > + > +/*! > + Initialization routine. This is the only thing that doesn't > + get called via a function pointer. In fact *we* are the > + ones to set that up. > + */ > +CdIo_t * > +cdio_open_os2 (const char *psz_orig_source) > +{ > + > +#ifdef HAVE_OS2_CDROM > + CdIo_t *ret; > + _img_private_t *_data; > + char *psz_source; > + > + cdio_funcs_t _funcs; > + > + memset( &_funcs, 0, sizeof(_funcs) ); > + > + _funcs.audio_get_volume = audio_get_volume_os2; > + _funcs.audio_pause = audio_pause_os2; > + _funcs.audio_play_msf = audio_play_msf_os2; > +#if 0 > + _funcs.audio_play_track_index = audio_play_track_index_os2; > +#endif > + _funcs.audio_read_subchannel = audio_read_subchannel_os2; > + _funcs.audio_resume = audio_resume_os2; > + _funcs.audio_set_volume = audio_set_volume_os2; > + _funcs.audio_stop = audio_stop_os2; > + _funcs.eject_media = eject_media_os2; > + _funcs.free = free_os2; > + _funcs.get_arg = get_arg_os2; > +#if 0 > + _funcs.get_blocksize = get_blocksize_os2; > +#endif > + _funcs.get_cdtext = get_cdtext_generic; > + _funcs.get_default_device = cdio_get_default_device_os2; > + _funcs.get_devices = cdio_get_devices_os2; > + _funcs.get_disc_last_lsn = get_disc_last_lsn_os2; > + _funcs.get_discmode = get_discmode_os2; > + _funcs.get_drive_cap = get_drive_cap_mmc; > + _funcs.get_first_track_num = get_first_track_num_generic; > + _funcs.get_hwinfo = NULL; > +#if 0 > + _funcs.get_last_session = get_last_session_os2; > +#endif > + _funcs.get_media_changed = get_media_changed_mmc; > + _funcs.get_mcn = _cdio_get_mcn; > + _funcs.get_num_tracks = get_num_tracks_generic; > + _funcs.get_track_channels = get_track_channels_generic; > + _funcs.get_track_copy_permit = get_track_copy_permit_generic; > + _funcs.get_track_format = _cdio_get_track_format; > + _funcs.get_track_green = _cdio_get_track_green; > + _funcs.get_track_lba = NULL; /* This could be done if need be. > */ > +#if 0 > + _funcs.get_track_pregap_lba = get_track_pregap_lba_os2; > + _funcs.get_track_isrc = get_track_isrc_os2; > +#endif > + _funcs.get_track_msf = _cdio_get_track_msf; > + _funcs.get_track_preemphasis = get_track_preemphasis_generic; > + _funcs.lseek = cdio_generic_lseek; > + _funcs.read = cdio_generic_read; > + _funcs.read_audio_sectors = read_audio_sectors_os2; > + _funcs.read_data_sectors = read_data_sectors_mmc; > + _funcs.read_mode1_sector = read_mode1_sector_os2; > + _funcs.read_mode1_sectors = read_mode1_sectors_os2; > + _funcs.read_mode2_sector = read_mode2_sector_os2; > + _funcs.read_mode2_sectors = read_mode2_sectors_os2; > + _funcs.read_toc = read_toc_os2; > + _funcs.run_mmc_cmd = run_mmc_cmd_os2; > + _funcs.set_arg = set_arg_os2; > + _funcs.set_blocksize = set_blocksize_mmc; > + _funcs.set_speed = set_drive_speed_mmc; > + > + _data = calloc(1, sizeof (_img_private_t)); > + _data->access_mode = _AM_OS2; > + _data->gen.init = false; > + _data->gen.fd = -1; > + > + if (NULL == psz_orig_source) { > + psz_source=cdio_get_default_device_os2(); > + if (NULL == psz_source) return NULL; > + set_arg_os2(_data, "source", psz_source); > + free(psz_source); > + } else { > + if (cdio_is_device_os2(psz_orig_source)) > + set_arg_os2(_data, "source", psz_orig_source); > + else { > + /* The below would be okay if all device drivers worked this way. */ > +#if 0 > + cdio_info ("source %s is a not a device", psz_orig_source); > +#endif > + free(_data); > + return NULL; > + } > + } > + > + ret = cdio_new ((void *)_data, &_funcs); > + if (ret == NULL) return NULL; > + > + ret->driver_id = DRIVER_OS2; > + > + if (init_os2(_data)) > + return ret; > + else { > + free_os2 (_data); > + return NULL; > + } > +#else > + return NULL; > +#endif /* HAVE_OS2_CDROM */ > + > +} > + > +/*! > + Initialization routine. This is the only thing that doesn't > + get called via a function pointer. In fact *we* are the > + ones to set that up. > + */ > +CdIo_t * > +cdio_open_am_os2 (const char *psz_source_name, const char > *psz_access_mode) > +{ > + > + if (psz_access_mode != NULL) > + cdio_warn ("there is only one access mode for OS/2. Arg %s ignored", > + psz_access_mode); > + return cdio_open_os2(psz_source_name); > +} > + > +bool > +cdio_have_os2 (void) > +{ > +#ifdef HAVE_OS2_CDROM > + return true; > +#else > + return false; > +#endif /* HAVE_OS2_CDROM */ > +} > + > + > diff -buNr src/util.c.org src/util.c > --- src/util.c.org 2008-04-15 10:22:12.000000000 +0900 > +++ src/util.c 2009-01-09 01:59:12.000000000 +0900 > @@ -160,7 +160,7 @@ > char * > fillout_device_name(const char *device_name) > { > -#if defined(HAVE_WIN32_CDROM) > +#if defined(HAVE_WIN32_CDROM) || defined(HAVE_OS2_CDROM) > return strdup(device_name); > #else > unsigned int prefix_len = strlen(DEV_PREFIX); > >
