Пример #1
0
            private static int ReadSubChannel <T>(UnixFileDescriptor fd, CDDataFormat format, byte track, out T data) where T : struct
            {
                var req = new ReadSubChannelRequest {
                    address_format = CDAddressFormat.CD_LBA_FORMAT,
                    data_format    = format,
                    track          = track,
                    data_len       = Util.SizeOfStructure <T>(),
                };

                req.data = Marshal.AllocHGlobal(new IntPtr(req.data_len));
                try {
                    var rc = NativeApi.SendIORequest(fd.Value, IOCTL.CDIOCREADSUBCHANNEL, ref req);
                    if (rc == 0)
                    {
                        data = Util.MarshalPointerToStructure <T>(req.data);
                    }
                    else
                    {
                        data = default(T);
                    }
                    return(rc);
                }
                finally {
                    Marshal.FreeHGlobal(req.data);
                }
            }
Пример #2
0
            public static UnixFileDescriptor OpenDevice(string name)
            {
                const uint O_RDONLY   = 0x0000;
                const uint O_NONBLOCK = 0x0800;

                return(UnixFileDescriptor.OpenPath(name, O_RDONLY | O_NONBLOCK, 0));
            }
Пример #3
0
            public static void GetCdTextInfo(UnixFileDescriptor fd, out MMC.CDTextDescriptor cdtext)
            {
                var cmd = MMC.CDB.ReadTocPmaAtip.CDText();

                try { NativeApi.SendSCSIRequest(fd, ref cmd, out cdtext); }
                catch (Exception e) { throw new IOException("Failed to retrieve CD-TEXT information.", e); }
                cdtext.FixUp();
            }
Пример #4
0
            public static void GetTableOfContents(UnixFileDescriptor fd, out MMC.TOCDescriptor rawtoc)
            {
                var msf = false;
                var cmd = MMC.CDB.ReadTocPmaAtip.TOC(msf);

                try { NativeApi.SendSCSIRequest(fd, ref cmd, out rawtoc); }
                catch (Exception e) { throw new IOException("Failed to retrieve table of contents.", e); }
                rawtoc.FixUp(msf);
            }
Пример #5
0
 public static string GetTrackIsrc(UnixFileDescriptor fd, byte track)
 {
     if (NativeApi.ReadSubChannel(fd, CDDataFormat.CD_TRACK_INFO, track, out MMC.SubChannelISRC isrc) != 0)
     {
         throw new IOException($"Failed to retrieve ISRC for track {track}.", new UnixException());
     }
     isrc.FixUp();
     return(isrc.Status.IsValid ? Encoding.ASCII.GetString(isrc.ISRC) : string.Empty);
 }
Пример #6
0
 public static string GetMediaCatalogNumber(UnixFileDescriptor fd)
 {
     if (NativeApi.ReadSubChannel(fd, CDDataFormat.CD_MEDIA_CATALOG, 0, out MMC.SubChannelMediaCatalogNumber mcn) != 0)
     {
         throw new IOException("Failed to retrieve media catalog number.", new UnixException());
     }
     mcn.FixUp();
     return(mcn.Status.IsValid ? Encoding.ASCII.GetString(mcn.MCN) : string.Empty);
 }
Пример #7
0
            private static void SendSCSIRequest <TCommand, TData>(UnixFileDescriptor fd, ref TCommand cmd, out TData data) where TCommand : struct where TData : struct
            {
                var cmdlen = Util.SizeOfStructure <TCommand>();

                if (cmdlen > 16)
                {
                    throw new InvalidOperationException("A SCSI command must not exceed 16 bytes in size.");
                }
                var req = new SCSIRequest {
                    interface_id    = 'S',
                    dxfer_direction = SCSITransferDirection.FROM_DEV,
                    timeout         = NativeApi.DefaultSCSIRequestTimeOut,
                    cmd_len         = (byte)cmdlen,
                    mx_sb_len       = (byte)64,
                    dxfer_len       = (uint)Util.SizeOfStructure <TData>(),
                };
                var memlen = (uint)(req.cmd_len + req.mx_sb_len + req.dxfer_len);
                var bytes  = NativeApi.AllocZero(new UIntPtr(1), new UIntPtr(memlen));

                try {
                    req.cmdp   = bytes;
                    req.sbp    = req.cmdp + req.cmd_len;
                    req.dxferp = req.sbp + req.mx_sb_len;
                    Marshal.StructureToPtr(cmd, req.cmdp, false);
                    try {
                        if (NativeApi.SendSCSIRequest(fd.Value, IOCTL.SG_IO, ref req) != 0)
                        {
                            throw new UnixException();
                        }
                        if (req.status == SAM.StatusCode.CHECK_CONDITION || req.driver_status == SCSIDriverStatus.DRIVER_SENSE)
                        {
                            var response = Marshal.ReadByte(req.sbp) & 0x7f;
                            switch (response)
                            {
                            case 0x70:
                            case 0x71: // Fixed Format (Current or Deferred)
                                throw new ScsiException(Util.MarshalPointerToStructure <SPC.FixedSenseData>(req.sbp));

                            case 0x72:
                            case 0x73: // Descriptor Format (Current or Deferred)
                                throw new ScsiException(Util.MarshalPointerToStructure <SPC.DescriptorSenseData>(req.sbp));

                            default:
                                throw new IOException($"SCSI CHECK CONDITION: BAD RESPONSE CODE ({response:X2})");
                            }
                        }
                        data = Util.MarshalPointerToStructure <TData>(req.dxferp);
                    }
                    finally {
                        Util.DestroyStructure <TCommand>(req.cmdp);
                    }
                }
                finally {
                    NativeApi.Free(bytes);
                }
            }
Пример #8
0
            public static string GetTrackIsrc(UnixFileDescriptor fd, byte track)
            {
                MMC.SubChannelISRC isrc;
                var cmd = MMC.CDB.ReadSubChannel.ISRC(track);

                try { NativeApi.SendSCSIRequest(fd, ref cmd, out isrc); }
                catch (Exception e) { throw new IOException($"Failed to retrieve ISRC for track {track}.", e); }
                isrc.FixUp();
                return(isrc.Status.IsValid ? Encoding.ASCII.GetString(isrc.ISRC) : string.Empty);
            }
Пример #9
0
            public static string GetMediaCatalogNumber(UnixFileDescriptor fd)
            {
                MMC.SubChannelMediaCatalogNumber mcn;
                var cmd = MMC.CDB.ReadSubChannel.MediaCatalogNumber();

                try { NativeApi.SendSCSIRequest(fd, ref cmd, out mcn); }
                catch (Exception e) { throw new IOException("Failed to retrieve media catalog number.", e); }
                mcn.FixUp();
                return(mcn.Status.IsValid ? Encoding.ASCII.GetString(mcn.MCN) : string.Empty);
            }
Пример #10
0
 public static void ReadTOC(UnixFileDescriptor fd, out byte first, out byte last, out MMC.TrackDescriptor[] tracks, bool nativeAddress)
 {
     { // Read the TOC header
         var req = new TOCHeaderRequest();
         if (NativeApi.SendIORequest(fd.Value, IOCTL.CDIOREADTOCHEADER, ref req) != 0)
         {
             throw new IOException("Failed to retrieve table of contents.", new UnixException());
         }
         first = req.starting_track;
         last  = req.ending_track;
     }
     {
         var trackcount = last - first + 2; // first->last plus lead-out
         var itemsize   = Util.SizeOfStructure <MMC.TrackDescriptor>();
         var req        = new TOCEntriesRequest {
             address_format = CDAddressFormat.CD_LBA_FORMAT,
             starting_track = first,
             data_len       = (ushort)(trackcount * itemsize),
         };
         req.data = Marshal.AllocHGlobal(new IntPtr(req.data_len));
         try {
             if (NativeApi.SendIORequest(fd.Value, IOCTL.CDIOREADTOCENTRIES, ref req) != 0)
             {
                 throw new IOException("Failed to retrieve TOC entries.", new UnixException());
             }
             tracks = new MMC.TrackDescriptor[trackcount];
             var walker = req.data;
             for (var i = 0; i < trackcount; ++i)
             {
                 tracks[i] = Util.MarshalPointerToStructure <MMC.TrackDescriptor>(walker);
                 // The FixUp call assumes the address is in network byte order.
                 if (nativeAddress)
                 {
                     tracks[i].Address = IPAddress.HostToNetworkOrder(tracks[i].Address);
                 }
                 tracks[i].FixUp(req.address_format == CDAddressFormat.CD_MSF_FORMAT);
                 walker += itemsize;
             }
         }
         finally {
             Marshal.FreeHGlobal(req.data);
         }
     }
 }