// // This is part of dvd+rw-tools by Andy Polyakov <appro@fy.chalmers.se> // // Use-it-on-your-own-risk, GPL bless... // // For further details see http://fy.chalmers.se/~appro/linux/DVD+RW/ // // // edited by ShultZ to use with QPxTool http://qpxtool.sf.net // #include <string.h> #ifndef __qpx_transport_h #define __qpx_transport_h #if defined(__unix) || defined(__unix__) extern long getmsecs(); #include <errno.h> #ifndef EMEDIUMTYPE #define EMEDIUMTYPE EINVAL #endif #ifndef ENOMEDIUM #define ENOMEDIUM ENODEV #endif //* #elif defined(_WIN32) #include <windows.h> #include <stddef.h> #include <stdio.h> #include <stdlib.h> #define ssize_t LONG_PTR #define off64_t __int64 #include "win32err.h" #define poll(a,b,t) Sleep(t) #define getmsecs() GetTickCount() #include <locale.h> #define ENV_LOCALE ".OCP" //*/ #endif #define CREAM_ON_ERRNO_NAKED(s) \ switch ((s)[12]) \ { case 0x04: errno=EAGAIN; break; \ case 0x20: errno=ENODEV; break; \ case 0x21: if ((s)[13]==0) errno=ENOSPC; \ else errno=EINVAL; \ break; \ case 0x30: errno=EMEDIUMTYPE; break; \ case 0x3A: errno=ENOMEDIUM; break; \ } #define CREAM_ON_ERRNO(s) do { CREAM_ON_ERRNO_NAKED(s) } while(0) #define FATAL_START(er) (0x80|(er)) #define ERRCODE(s) ((((s)[2]&0x0F)<<16)|((s)[12]<<8)|((s)[13])) #define SK(errcode) (((errcode)>>16)&0xF) #define ASC(errcode) (((errcode)>>8)&0xFF) #define ASCQ(errcode) ((errcode)&0xFF) extern void sperror (const char *cmd, int err); //, Scsi_Command *scsi); class autofree { private: unsigned char *ptr; public: autofree(); ~autofree(); unsigned char *operator=(unsigned char *str) { return ptr=str; } operator unsigned char *() { return ptr; } }; #if defined(__linux) //#include <sys/ioctl.h> #include <linux/cdrom.h> //#include <mntent.h> //#include <sys/wait.h> //#include <sys/utsname.h> #include <scsi/sg.h> #if !defined(SG_FLAG_LUN_INHIBIT) # if defined(SG_FLAG_UNUSED_LUN_INHIBIT) # define SG_FLAG_LUN_INHIBIT SG_FLAG_UNUSED_LUN_INHIBIT # else # define SG_FLAG_LUN_INHIBIT 0 # endif #endif #ifndef CHECK_CONDITION #define CHECK_CONDITION 0x01 #endif typedef enum { NONE=CGC_DATA_NONE, // 3 READ=CGC_DATA_READ, // 2 WRITE=CGC_DATA_WRITE // 1 } Direction; #ifdef SG_IO static const int Dir_xlate [4] = { // should have been defined // private in USE_SG_IO scope, // but it appears to be too 0, // implementation-dependent... SG_DXFER_TO_DEV, // 1,CGC_DATA_WRITE SG_DXFER_FROM_DEV, // 2,CGC_DATA_READ SG_DXFER_NONE }; // 3,CGC_DATA_NONE class USE_SG_IO { private: int yes_or_no; public: USE_SG_IO(); ~USE_SG_IO(); operator int() const { return yes_or_no; } int operator[] (Direction dir) const { return Dir_xlate[dir]; } }; #endif static const class USE_SG_IO use_sg_io; class Scsi_Command { private: // long cmd_time; int fd,autoclose; char *filename; struct cdrom_generic_command cgc; union sense_union{ struct request_sense s; unsigned char u[18]; } _sense; #ifdef SG_IO struct sg_io_hdr sg_io; #else struct { int cmd_len,timeout; } sg_io; #endif public: Scsi_Command(); Scsi_Command(int f); Scsi_Command(void*f); ~Scsi_Command(); int associate (const char *file,const struct stat *ref); unsigned char &operator[] (size_t i) { if (i==0) { memset(&cgc,0,sizeof(cgc)), memset(&_sense,0,sizeof(_sense)); cgc.quiet = 1; cgc.sense = &_sense.s; #ifdef SG_IO if (use_sg_io) { memset(&sg_io,0,sizeof(sg_io)); sg_io.interface_id= 'S'; sg_io.mx_sb_len = sizeof(_sense); sg_io.cmdp = cgc.cmd; sg_io.sbp = _sense.u; sg_io.flags = SG_FLAG_LUN_INHIBIT|SG_FLAG_DIRECT_IO; } #endif } sg_io.cmd_len = i+1; return cgc.cmd[i]; } unsigned char &operator()(size_t i) { return _sense.u[i]; } // unsigned char *sense(); unsigned char *sense() { return _sense.u; } void timeout(int i); size_t residue(); int transport(Direction dir,void *buf,size_t sz); int umount(int f); int is_reload_needed (); }; #elif defined(__OpenBSD__) || defined(__NetBSD__) #include <sys/ioctl.h> #include <sys/scsiio.h> #include <sys/wait.h> #include <sys/param.h> #include <sys/mount.h> typedef off_t off64_t; #define stat64 stat #define fstat64 fstat #define open64 open #define pread64 pread #define pwrite64 pwrite #define lseek64 lseek typedef enum { NONE=0, READ=SCCMD_READ, WRITE=SCCMD_WRITE } Direction; class Scsi_Command { private: int fd,autoclose; char *filename; scsireq_t req; public: Scsi_Command(); Scsi_Command(int f); Scsi_Command(void*f); ~Scsi_Command(); int associate (const char *file,const struct stat *ref); unsigned char &operator[] (size_t i) { if (i==0) { memset(&req,0,sizeof(req)); req.flags = SCCMD_ESCAPE; req.timeout = 30000; req.senselen = 18; //sizeof(req.sense); } req.cmdlen = i+1; return req.cmd[i]; } unsigned char &operator()(size_t i) { return req.sense[i]; } unsigned char *sense() { return req.sense; } void timeout(int i); size_t residue(); int transport(Direction dir,void *buf,size_t sz); int umount(int f); int is_reload_needed (); }; #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) #include <sys/ioctl.h> #include <stdio.h> #include <camlib.h> #include <cam/scsi/scsi_message.h> #include <cam/scsi/scsi_pass.h> #include <sys/wait.h> #include <sys/param.h> #include <sys/mount.h> #include <dirent.h> typedef off_t off64_t; #define stat64 stat #define fstat64 fstat #define open64 open #define pread64 pread #define pwrite64 pwrite #define lseek64 lseek #define ioctl_fd (((struct cam_device *)ioctl_handle)->fd) typedef enum { NONE=CAM_DIR_NONE, READ=CAM_DIR_IN, WRITE=CAM_DIR_OUT } Direction; class Scsi_Command { private: int fd,autoclose; char *filename; struct cam_device *cam; union ccb ccb; public: Scsi_Command(); Scsi_Command(int f); Scsi_Command(void *f); ~Scsi_Command(); int associate (const char *file,const struct stat *ref); unsigned char &operator[] (size_t i) { if (i==0) { memset(&ccb,0,sizeof(ccb)); ccb.ccb_h.path_id = cam->path_id; ccb.ccb_h.target_id = cam->target_id; ccb.ccb_h.target_lun = cam->target_lun; cam_fill_csio (&(ccb.csio), 1, // retries NULL, // cbfncp CAM_DEV_QFRZDIS, // flags MSG_SIMPLE_Q_TAG, // tag_action NULL, // data_ptr 0, // dxfer_len sizeof(ccb.csio.sense_data), // sense_len 0, // cdb_len 30*1000); // timeout } ccb.csio.cdb_len = i+1; return ccb.csio.cdb_io.cdb_bytes[i]; } unsigned char &operator()(size_t i) { return ((unsigned char *)&ccb.csio.sense_data)[i]; } unsigned char *sense() { return (unsigned char*)&ccb.csio.sense_data; } void timeout(int i); size_t residue(); int transport(Direction dir,void *buf,size_t sz); int umount(int f); #define RELOAD_NEVER_NEEDED // according to Matthew Dillon int is_reload_needed (); }; //* #elif defined(_WIN32) #if defined(__MINGW32__) #include <ddk/ntddscsi.h> #define FSCTL_LOCK_VOLUME CTL_CODE(FILE_DEVICE_FILE_SYSTEM,6,METHOD_BUFFERED,FILE_ANY_ACCESS) #define FSCTL_UNLOCK_VOLUME CTL_CODE(FILE_DEVICE_FILE_SYSTEM,7,METHOD_BUFFERED,FILE_ANY_ACCESS) #define FSCTL_DISMOUNT_VOLUME CTL_CODE(FILE_DEVICE_FILE_SYSTEM,8,METHOD_BUFFERED,FILE_ANY_ACCESS) #else #include <winioctl.h> #include <ntddscsi.h> #endif typedef enum { NONE=SCSI_IOCTL_DATA_UNSPECIFIED, READ=SCSI_IOCTL_DATA_IN, WRITE=SCSI_IOCTL_DATA_OUT } Direction; typedef struct { SCSI_PASS_THROUGH_DIRECT spt; unsigned char sense[18]; } SPKG; class Scsi_Command { private: HANDLE fd; int autoclose; char *filename; SPKG p; public: Scsi_Command(); Scsi_Command(void*f); ~Scsi_Command(); int associate (const char *file,const struct stat *ref=NULL); unsigned char &operator[] (size_t i) { if (i==0) { memset(&p,0,sizeof(p)); p.spt.Length = sizeof(p.spt); p.spt.DataIn = SCSI_IOCTL_DATA_UNSPECIFIED; p.spt.TimeOutValue = 30; p.spt.SenseInfoLength = sizeof(p.sense); p.spt.SenseInfoOffset = offsetof(SPKG,sense); } p.spt.CdbLength = i+1; return p.spt.Cdb[i]; } unsigned char &operator()(size_t i) { return p.sense[i]; } unsigned char *sense(); void timeout(int i); size_t residue(); int transport(Direction dir=NONE,void *buf=NULL,size_t sz=0); int umount (int f=-1); #define RELOAD_NEVER_NEEDED int is_reload_needed (); }; //*/ #else #error "Unsupported OS" #endif #undef ERRCODE #undef CREAM_ON_ERRNO #undef CREAM_ON_ERRNO_NAKED #endif