mirror of
https://github.com/aaru-dps/Aaru.git
synced 2025-12-16 19:24:25 +00:00
Add MMC/SecureDigital device support. Not yet used because of
a bad implementation of SEND_CSD and SEND_CID commands (TODO).
This commit is contained in:
@@ -328,6 +328,71 @@ namespace DiscImageChef.Devices.Linux
|
||||
return error;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends a MMC/SD command
|
||||
/// </summary>
|
||||
/// <returns>The result of the command.</returns>
|
||||
/// <param name="fd">File handle</param>
|
||||
/// <param name="command">MMC/SD opcode</param>
|
||||
/// <param name="buffer">Buffer for MMC/SD command response</param>
|
||||
/// <param name="timeout">Timeout in seconds</param>
|
||||
/// <param name="duration">Time it took to execute the command in milliseconds</param>
|
||||
/// <param name="sense"><c>True</c> if MMC/SD returned non-OK status</param>
|
||||
/// <param name="write"><c>True</c> if data is sent from host to card</param>
|
||||
/// <param name="isApplication"><c>True</c> if command should be preceded with CMD55</param>
|
||||
/// <param name="flags">Flags indicating kind and place of response</param>
|
||||
/// <param name="blocks">How many blocks to transfer</param>
|
||||
/// <param name="argument">Command argument</param>
|
||||
/// <param name="response">Response registers</param>
|
||||
/// <param name="blockSize">Size of block in bytes</param>
|
||||
internal static int SendMmcCommand(int fd, MmcCommands command, bool write, bool isApplication, MmcFlags flags, uint argument, uint blockSize, uint blocks, ref byte[] buffer, out uint[] response, out double duration, out bool sense, uint timeout = 0)
|
||||
{
|
||||
response = null;
|
||||
duration = 0;
|
||||
sense = false;
|
||||
|
||||
if(buffer == null)
|
||||
return -1;
|
||||
|
||||
mmc_ioc_cmd io_cmd = new mmc_ioc_cmd();
|
||||
|
||||
IntPtr bufPtr = Marshal.AllocHGlobal(buffer.Length);
|
||||
|
||||
io_cmd.write_flag = write;
|
||||
io_cmd.is_ascmd = isApplication;
|
||||
io_cmd.opcode = (uint)command;
|
||||
io_cmd.arg = argument;
|
||||
io_cmd.flags = flags;
|
||||
io_cmd.blksz = blockSize;
|
||||
io_cmd.blksz = blocks;
|
||||
if(timeout > 0)
|
||||
{
|
||||
io_cmd.data_timeout_ns = timeout * 1000000000;
|
||||
io_cmd.cmd_timeout_ms = timeout * 1000;
|
||||
}
|
||||
io_cmd.data_ptr = (ulong)bufPtr;
|
||||
|
||||
Marshal.Copy(buffer, 0, bufPtr, buffer.Length);
|
||||
|
||||
DateTime start = DateTime.UtcNow;
|
||||
int error = Extern.ioctlMmc(fd, LinuxIoctl.MMC_IOC_CMD, ref io_cmd);
|
||||
DateTime end = DateTime.UtcNow;
|
||||
|
||||
sense |= error < 0;
|
||||
|
||||
if(error < 0)
|
||||
error = Marshal.GetLastWin32Error();
|
||||
|
||||
Marshal.Copy(bufPtr, buffer, 0, buffer.Length);
|
||||
|
||||
response = io_cmd.response;
|
||||
duration = (end - start).TotalMilliseconds;
|
||||
|
||||
Marshal.FreeHGlobal(bufPtr);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
public static string ReadLink(string path)
|
||||
{
|
||||
IntPtr buf = Marshal.AllocHGlobal(4096);
|
||||
|
||||
@@ -145,6 +145,8 @@ namespace DiscImageChef.Devices.Linux
|
||||
// SCSI IOCtls
|
||||
SG_GET_VERSION_NUM = 0x2282,
|
||||
SG_IO = 0x2285,
|
||||
// MMC IOCtl
|
||||
MMC_IOC_CMD = 0xC048B300
|
||||
}
|
||||
|
||||
[Flags]
|
||||
|
||||
@@ -52,6 +52,9 @@ namespace DiscImageChef.Devices.Linux
|
||||
[DllImport("libc", EntryPoint = "ioctl", SetLastError = true)]
|
||||
internal static extern int ioctlSg(int fd, LinuxIoctl request, ref sg_io_hdr_t value);
|
||||
|
||||
[DllImport("libc", EntryPoint = "ioctl", SetLastError = true)]
|
||||
internal static extern int ioctlMmc(int fd, LinuxIoctl request, ref mmc_ioc_cmd value);
|
||||
|
||||
[DllImport("libc", CharSet = CharSet.Ansi, SetLastError = true)]
|
||||
internal static extern int readlink(string path, System.IntPtr buf, int bufsize);
|
||||
|
||||
|
||||
@@ -65,5 +65,62 @@ namespace DiscImageChef.Devices.Linux
|
||||
public uint duration; /* [o] */
|
||||
public SgInfo info; /* [o] */
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
struct mmc_ioc_cmd
|
||||
{
|
||||
/// <summary>
|
||||
/// Implies direction of data. true = write, false = read
|
||||
/// </summary>
|
||||
public bool write_flag;
|
||||
/// <summary>
|
||||
/// Application-specific command. true = precede with CMD55
|
||||
/// </summary>
|
||||
public bool is_ascmd;
|
||||
public uint opcode;
|
||||
public uint arg;
|
||||
/// <summary>
|
||||
/// CMD response
|
||||
/// </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
|
||||
public uint[] response;
|
||||
public MmcFlags flags;
|
||||
public uint blksz;
|
||||
public uint blocks;
|
||||
/// <summary>
|
||||
/// Sleep at least <see cref="postsleep_min_us"/> useconds, and at most
|
||||
/// <see cref="postsleep_max_us"/> useconds *after* issuing command.Needed for
|
||||
/// some read commands for which cards have no other way of indicating
|
||||
/// they're ready for the next command (i.e. there is no equivalent of
|
||||
/// a "busy" indicator for read operations).
|
||||
/// </summary>
|
||||
public uint postsleep_min_us;
|
||||
/// <summary>
|
||||
/// Sleep at least <see cref="postsleep_min_us"/> useconds, and at most
|
||||
/// <see cref="postsleep_max_us"/> useconds *after* issuing command.Needed for
|
||||
/// some read commands for which cards have no other way of indicating
|
||||
/// they're ready for the next command (i.e. there is no equivalent of
|
||||
/// a "busy" indicator for read operations).
|
||||
/// </summary>
|
||||
public uint postsleep_max_us;
|
||||
/// <summary>
|
||||
/// Override driver-computed timeouts.
|
||||
/// </summary>
|
||||
public uint data_timeout_ns;
|
||||
/// <summary>
|
||||
/// Override driver-computed timeouts.
|
||||
/// </summary>
|
||||
public uint cmd_timeout_ms;
|
||||
/// <summary>
|
||||
/// For 64-bit machines <see cref="data_ptr"/> , wants to
|
||||
/// be 8-byte aligned.Make sure this struct is the same size when
|
||||
/// built for 32-bit.
|
||||
/// </summary>
|
||||
public uint __pad;
|
||||
/// <summary>
|
||||
/// DAT buffer
|
||||
/// </summary>
|
||||
public ulong data_ptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user