J
Jerry Lai1
Guest
I'm finding the way to access SD card blocks under user mode application.
Through IOCTL_SFFDISK_DEVICE_COMMAND I have wrote a code to issue SD commands, I can use it to read the SD Card registers (eg. CID, CSD..etc.), it works on my laptop (with embedded SD slot), but I can't use it to send block access related commands (like CMD 56, 17, 18, 24, 25). The DeivceIoControl returns error and got error 5 when I attempt to send these commands.
The code I wrote as following:
int main()
{
char c;
std::cout << "Version: 20201028_o\n";
TCHAR drive;
printf("Input Drive Letter: ");
std::wcin >> drive;
BYTE buffer[512];
SD_StdCmd(drive, 9, 0x02600000, SDTD_UNSPECIFIED, SDTT_CMD_ONLY, NULL, 0);
SD_StdCmd(drive, 10, 0x02600000, SDTD_UNSPECIFIED, SDTT_CMD_ONLY, NULL, 0);
SD_StdCmd(drive, 32, 0, SDTD_UNSPECIFIED, SDTT_CMD_ONLY, NULL, 0);
SD_StdCmd(drive, 33, 10, SDTD_UNSPECIFIED, SDTT_CMD_ONLY, NULL, 0);
SD_StdCmd(drive, 38, 10, SDTD_UNSPECIFIED, SDTT_CMD_ONLY, NULL, 0);
SD_StdCmd(drive, 16, 0x200, SDTD_WRITE, SDTT_CMD_ONLY, NULL, 0);
//SD_StdCmd(drive, 24, 100, SDTD_WRITE, SDTT_SINGLE_BLOCK, buffer, 512);
SD_StdCmd(drive, 56, 1, SDTD_READ, SDTT_CMD_ONLY, buffer, 512);
printf("Process Done\n");
std::cin >> c;
}
void SD_StdCmd(TCHAR Drive,
SD_COMMAND_CODE Cmd,
ULONG Argument,
SD_TRANSFER_DIRECTION Dir,
SD_TRANSFER_TYPE Type,
BYTE* Buffer,
int DataLength)
{
TCHAR StrDeviceName[64] = { 0 };
printf(" CMD_%d (ARG: %08x) Dir = %d\n", Cmd, Argument, Dir);
wsprintf(StrDeviceName, _T("\\\\.\\%C:"), Drive/*pComBox->GetCurSel()*/);
HANDLE hVol = CreateFile(StrDeviceName,
GENERIC_READ | GENERIC_WRITE, // no access to the drive
FILE_SHARE_READ | // share mode
FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL, // default security attributes
OPEN_EXISTING, // disposition
FILE_ATTRIBUTE_NORMAL, // file attributes
NULL); // do not copy file attributes
if (INVALID_HANDLE_VALUE != hVol && NULL != hVol) {
int respOffset = sizeof(SDCMD_DESCRIPTOR);
int respLength = 0;
SDCMD_DESCRIPTOR sdCmdDescriptor = { 0 };
sdCmdDescriptor.Cmd = Cmd; // Issue CMD10 to driver
sdCmdDescriptor.CmdClass = SDCC_STANDARD;
sdCmdDescriptor.TransferDirection = Dir;
sdCmdDescriptor.TransferType = Type;
switch (Cmd)
{
case (56):
case (16):
case (17):
case (18):
case (24):
case (25):
case (32):
case (33):
sdCmdDescriptor.ResponseType = SDRT_1;
respLength = 8;
break;
case (9):
case (10):
sdCmdDescriptor.ResponseType = SDRT_2;
respLength = 16;
break;
case (12):
case (20):
case (28):
case (38):
sdCmdDescriptor.ResponseType = SDRT_1;
respLength = 8;
break;
default:
sdCmdDescriptor.ResponseType = SDRT_1;
respLength = 8;
break;
}
int dataOffset = respOffset + respLength;
int nSizeOfCmd = sizeof(SFFDISK_DEVICE_COMMAND_DATA) + sizeof(SDCMD_DESCRIPTOR) + respLength + DataLength;
SFFDISK_DEVICE_COMMAND_DATA *pCmdBuf = (SFFDISK_DEVICE_COMMAND_DATA*) new BYTE[nSizeOfCmd];
memset(pCmdBuf, 0, nSizeOfCmd);
pCmdBuf->HeaderSize = sizeof(SFFDISK_DEVICE_COMMAND_DATA);
pCmdBuf->Command = SFFDISK_DC_DEVICE_COMMAND;
pCmdBuf->ProtocolArgumentSize = sizeof(SDCMD_DESCRIPTOR);
pCmdBuf->DeviceDataBufferSize = respLength + DataLength;
pCmdBuf->Information = Argument;
memcpy(pCmdBuf->Data, &sdCmdDescriptor, sizeof(SDCMD_DESCRIPTOR));
if (DataLength && (Dir == SDTD_WRITE)) {
memcpy(&pCmdBuf->Data[respOffset + respLength], Buffer, DataLength);
}
DWORD dwBytesReturned = 0;
BOOL bResult = DeviceIoControl(hVol,
IOCTL_SFFDISK_DEVICE_COMMAND,
pCmdBuf,
nSizeOfCmd,
pCmdBuf,
nSizeOfCmd,
&dwBytesReturned,
NULL);
DWORD dwErr = GetLastError();
CloseHandle(hVol);
if (!bResult) {
printf("Failed to issue SD command, err code is %d\n", dwErr);
}
else {
if (sdCmdDescriptor.ResponseType == SDRT_1 || sdCmdDescriptor.ResponseType == SDRT_1B)
printf(" Resp R1: ");
else if (sdCmdDescriptor.ResponseType == SDRT_2)
printf(" Resp R2: ");
for (int i = 0; i < respLength; ++i)
{
printf("%02x ", pCmdBuf->Data[respOffset + respLength - 1 - i]);
if (i != 0 && (i % 16 == 0)) {
std::cout << std::endl;
printf(" ");
}
}
std::cout << std::endl;
if (Dir == SDTD_READ) {
memcpy(Buffer, &pCmdBuf->Data[dataOffset], DataLength);
printf(" Data: ");
for (int i = 0; i < DataLength; ++i)
{
if ((i % 16 == 0)) {
std::cout << std::endl;
printf("\n ");
}
printf("%02x ", pCmdBuf->Data[dataOffset + i]);
}
std::cout << std::endl;
}
}
delete[] pCmdBuf;
}
else {
printf("Can't open handle\n");
}
}
Continue reading...
Through IOCTL_SFFDISK_DEVICE_COMMAND I have wrote a code to issue SD commands, I can use it to read the SD Card registers (eg. CID, CSD..etc.), it works on my laptop (with embedded SD slot), but I can't use it to send block access related commands (like CMD 56, 17, 18, 24, 25). The DeivceIoControl returns error and got error 5 when I attempt to send these commands.
The code I wrote as following:
int main()
{
char c;
std::cout << "Version: 20201028_o\n";
TCHAR drive;
printf("Input Drive Letter: ");
std::wcin >> drive;
BYTE buffer[512];
SD_StdCmd(drive, 9, 0x02600000, SDTD_UNSPECIFIED, SDTT_CMD_ONLY, NULL, 0);
SD_StdCmd(drive, 10, 0x02600000, SDTD_UNSPECIFIED, SDTT_CMD_ONLY, NULL, 0);
SD_StdCmd(drive, 32, 0, SDTD_UNSPECIFIED, SDTT_CMD_ONLY, NULL, 0);
SD_StdCmd(drive, 33, 10, SDTD_UNSPECIFIED, SDTT_CMD_ONLY, NULL, 0);
SD_StdCmd(drive, 38, 10, SDTD_UNSPECIFIED, SDTT_CMD_ONLY, NULL, 0);
SD_StdCmd(drive, 16, 0x200, SDTD_WRITE, SDTT_CMD_ONLY, NULL, 0);
//SD_StdCmd(drive, 24, 100, SDTD_WRITE, SDTT_SINGLE_BLOCK, buffer, 512);
SD_StdCmd(drive, 56, 1, SDTD_READ, SDTT_CMD_ONLY, buffer, 512);
printf("Process Done\n");
std::cin >> c;
}
void SD_StdCmd(TCHAR Drive,
SD_COMMAND_CODE Cmd,
ULONG Argument,
SD_TRANSFER_DIRECTION Dir,
SD_TRANSFER_TYPE Type,
BYTE* Buffer,
int DataLength)
{
TCHAR StrDeviceName[64] = { 0 };
printf(" CMD_%d (ARG: %08x) Dir = %d\n", Cmd, Argument, Dir);
wsprintf(StrDeviceName, _T("\\\\.\\%C:"), Drive/*pComBox->GetCurSel()*/);
HANDLE hVol = CreateFile(StrDeviceName,
GENERIC_READ | GENERIC_WRITE, // no access to the drive
FILE_SHARE_READ | // share mode
FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL, // default security attributes
OPEN_EXISTING, // disposition
FILE_ATTRIBUTE_NORMAL, // file attributes
NULL); // do not copy file attributes
if (INVALID_HANDLE_VALUE != hVol && NULL != hVol) {
int respOffset = sizeof(SDCMD_DESCRIPTOR);
int respLength = 0;
SDCMD_DESCRIPTOR sdCmdDescriptor = { 0 };
sdCmdDescriptor.Cmd = Cmd; // Issue CMD10 to driver
sdCmdDescriptor.CmdClass = SDCC_STANDARD;
sdCmdDescriptor.TransferDirection = Dir;
sdCmdDescriptor.TransferType = Type;
switch (Cmd)
{
case (56):
case (16):
case (17):
case (18):
case (24):
case (25):
case (32):
case (33):
sdCmdDescriptor.ResponseType = SDRT_1;
respLength = 8;
break;
case (9):
case (10):
sdCmdDescriptor.ResponseType = SDRT_2;
respLength = 16;
break;
case (12):
case (20):
case (28):
case (38):
sdCmdDescriptor.ResponseType = SDRT_1;
respLength = 8;
break;
default:
sdCmdDescriptor.ResponseType = SDRT_1;
respLength = 8;
break;
}
int dataOffset = respOffset + respLength;
int nSizeOfCmd = sizeof(SFFDISK_DEVICE_COMMAND_DATA) + sizeof(SDCMD_DESCRIPTOR) + respLength + DataLength;
SFFDISK_DEVICE_COMMAND_DATA *pCmdBuf = (SFFDISK_DEVICE_COMMAND_DATA*) new BYTE[nSizeOfCmd];
memset(pCmdBuf, 0, nSizeOfCmd);
pCmdBuf->HeaderSize = sizeof(SFFDISK_DEVICE_COMMAND_DATA);
pCmdBuf->Command = SFFDISK_DC_DEVICE_COMMAND;
pCmdBuf->ProtocolArgumentSize = sizeof(SDCMD_DESCRIPTOR);
pCmdBuf->DeviceDataBufferSize = respLength + DataLength;
pCmdBuf->Information = Argument;
memcpy(pCmdBuf->Data, &sdCmdDescriptor, sizeof(SDCMD_DESCRIPTOR));
if (DataLength && (Dir == SDTD_WRITE)) {
memcpy(&pCmdBuf->Data[respOffset + respLength], Buffer, DataLength);
}
DWORD dwBytesReturned = 0;
BOOL bResult = DeviceIoControl(hVol,
IOCTL_SFFDISK_DEVICE_COMMAND,
pCmdBuf,
nSizeOfCmd,
pCmdBuf,
nSizeOfCmd,
&dwBytesReturned,
NULL);
DWORD dwErr = GetLastError();
CloseHandle(hVol);
if (!bResult) {
printf("Failed to issue SD command, err code is %d\n", dwErr);
}
else {
if (sdCmdDescriptor.ResponseType == SDRT_1 || sdCmdDescriptor.ResponseType == SDRT_1B)
printf(" Resp R1: ");
else if (sdCmdDescriptor.ResponseType == SDRT_2)
printf(" Resp R2: ");
for (int i = 0; i < respLength; ++i)
{
printf("%02x ", pCmdBuf->Data[respOffset + respLength - 1 - i]);
if (i != 0 && (i % 16 == 0)) {
std::cout << std::endl;
printf(" ");
}
}
std::cout << std::endl;
if (Dir == SDTD_READ) {
memcpy(Buffer, &pCmdBuf->Data[dataOffset], DataLength);
printf(" Data: ");
for (int i = 0; i < DataLength; ++i)
{
if ((i % 16 == 0)) {
std::cout << std::endl;
printf("\n ");
}
printf("%02x ", pCmdBuf->Data[dataOffset + i]);
}
std::cout << std::endl;
}
}
delete[] pCmdBuf;
}
else {
printf("Can't open handle\n");
}
}
Continue reading...