Пример #1
0
        /// <summary>Returns true if the specified handle is controlled by a SFFDISK (aka SDHCI) driver</summary>
        /// <param name="fd">Device handle</param>
        /// <returns><c>true</c> if SDHCI, false otherwise</returns>
        internal static bool IsSdhci(SafeFileHandle fd)
        {
            var queryData1 = new SffdiskQueryDeviceProtocolData();

            queryData1.size = (ushort)Marshal.SizeOf(queryData1);

            Extern.DeviceIoControl(fd, WindowsIoctl.IoctlSffdiskQueryDeviceProtocol, IntPtr.Zero, 0, ref queryData1,
                                   queryData1.size, out _, IntPtr.Zero);

            return(queryData1.protocolGuid.Equals(Consts.GuidSffProtocolSd) ||
                   queryData1.protocolGuid.Equals(Consts.GuidSffProtocolMmc));
        }
Пример #2
0
        /// <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(SafeFileHandle 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)
        {
            var commandData       = new SffdiskDeviceCommandData();
            var commandDescriptor = new SdCmdDescriptor();

            commandData.size    = (ushort)Marshal.SizeOf(commandData);
            commandData.command = SffdiskDcmd.DeviceCommand;
            commandData.protocolArgumentSize    = (ushort)Marshal.SizeOf(commandDescriptor);
            commandData.deviceDataBufferSize    = blockSize * blocks;
            commandDescriptor.commandCode       = (byte)command;
            commandDescriptor.cmdClass          = isApplication ? SdCommandClass.AppCmd : SdCommandClass.Standard;
            commandDescriptor.transferDirection = write ? SdTransferDirection.Write : SdTransferDirection.Read;

            commandDescriptor.transferType = flags.HasFlag(MmcFlags.CommandAdtc)
                                                 ? command == MmcCommands.ReadMultipleBlock
                                                       ? SdTransferType.MultiBlock
                                                       : SdTransferType.SingleBlock : SdTransferType.CmdOnly;

            commandDescriptor.responseType = 0;

            if (flags.HasFlag(MmcFlags.ResponseR1) ||
                flags.HasFlag(MmcFlags.ResponseSpiR1))
            {
                commandDescriptor.responseType = SdResponseType.R1;
            }

            if (flags.HasFlag(MmcFlags.ResponseR1B) ||
                flags.HasFlag(MmcFlags.ResponseSpiR1B))
            {
                commandDescriptor.responseType = SdResponseType.R1b;
            }

            if (flags.HasFlag(MmcFlags.ResponseR2) ||
                flags.HasFlag(MmcFlags.ResponseSpiR2))
            {
                commandDescriptor.responseType = SdResponseType.R2;
            }

            if (flags.HasFlag(MmcFlags.ResponseR3) ||
                flags.HasFlag(MmcFlags.ResponseSpiR3))
            {
                commandDescriptor.responseType = SdResponseType.R3;
            }

            if (flags.HasFlag(MmcFlags.ResponseR4) ||
                flags.HasFlag(MmcFlags.ResponseSpiR4))
            {
                commandDescriptor.responseType = SdResponseType.R4;
            }

            if (flags.HasFlag(MmcFlags.ResponseR5) ||
                flags.HasFlag(MmcFlags.ResponseSpiR5))
            {
                commandDescriptor.responseType = SdResponseType.R5;
            }

            if (flags.HasFlag(MmcFlags.ResponseR6))
            {
                commandDescriptor.responseType = SdResponseType.R6;
            }

            byte[] commandB = new byte[commandData.size + commandData.protocolArgumentSize +
                                       commandData.deviceDataBufferSize];

            Array.Copy(buffer, 0, commandB, commandData.size + commandData.protocolArgumentSize, buffer.Length);
            IntPtr hBuf = Marshal.AllocHGlobal(commandB.Length);

            Marshal.StructureToPtr(commandData, hBuf, true);
            var descriptorOffset = IntPtr.Add(hBuf, commandData.size);

            Marshal.StructureToPtr(commandDescriptor, descriptorOffset, true);
            Marshal.Copy(hBuf, commandB, 0, commandB.Length);
            Marshal.FreeHGlobal(hBuf);

            int      error = 0;
            DateTime start = DateTime.Now;

            sense = !Extern.DeviceIoControl(fd, WindowsIoctl.IoctlSffdiskDeviceCommand, commandB, (uint)commandB.Length,
                                            commandB, (uint)commandB.Length, out _, IntPtr.Zero);

            DateTime end = DateTime.Now;

            if (sense)
            {
                error = Marshal.GetLastWin32Error();
            }

            buffer = new byte[blockSize * blocks];
            Buffer.BlockCopy(commandB, commandB.Length - buffer.Length, buffer, 0, buffer.Length);

            response = new uint[4];
            duration = (end - start).TotalMilliseconds;

            return(error);
        }