【FatFs】車載外部ストレージ その95【ファイル上シミュレーション②】

【FatFs】車載外部ストレージ その95【ファイル上シミュレーション②】 車載外部ストレージ

バックナンバーはこちら。
https://www.simulationroom999.com/blog/In-vehicle-external-storage-backnumber/

はじめに

FatFsのファイル上シミュレーションの話。
diskio.cを改造する。

登場人物

博識フクロウのフクさん

指差しフクロウ

イラストACにて公開の「kino_k」さんのイラストを使用しています。
https://www.ac-illust.com/main/profile.php?id=iKciwKA9&area=1

エンジニア歴8年の太郎くん

技術者太郎

イラストACにて公開の「しのみ」さんのイラストを使用しています。
https://www.ac-illust.com/main/profile.php?id=uCKphAW2&area=1

FatFs Win32のdiskio.cを改造してディスクイメージをファイル化

太郎くん
太郎くん

diskio.cを改造するって前回言ってたけど、
どうだった?

フクさん
フクさん

まぁ結果としてはそれほど面倒なところも無かったかな。

太郎くん
太郎くん

ほう。相変わらずすごいね。

フクさん
フクさん

とりあえず、ざっと改造してみた。
変更差分としてはこんな感じだ。

FatFs Win32のdiskio.c 変更差分

--- ffsample/win32/diskio.c	
+++ ffsample_file_sim/win32/diskio.c	
@@ -14,8 +14,8 @@
 #define SZ_RAMDISK	135		/* Size of drive 0 (RAM disk) [MiB] */
 #define SS_RAMDISK	512		/* Initial sector size of drive 0 (RAM disk) [byte] */
 
-#define MIN_READ_ONLY	1	/* Read-only drive from */
-#define	MAX_READ_ONLY	1	/* Read-only drive to */
+#define MIN_READ_ONLY	5	/* Read-only drive from */
+#define	MAX_READ_ONLY	5	/* Read-only drive to */
 
 
 
@@ -50,6 +50,7 @@
 /*-----------------------------------------------------------------------*/
 
 
+#if 0
 DWORD WINAPI tmr_thread (LPVOID parms)
 {
 	DWORD dw;
@@ -70,6 +70,7 @@
 		}
 	}
 }
+#endif
 
 
 
@@ -92,6 +93,12 @@
 		return 1;
 	}
 
+	if (pdrv > 0) {
+		stat->n_sectors = 1024 * 1024;
+		stat->sz_sector = 512;
+		stat->status = 0;
+	}
+
 	/* Get drive size */
 	if (!DeviceIoControl(h, IOCTL_STORAGE_CHECK_VERIFY, 0, 0, 0, 0, &rb, 0)) return 0;
 	if (DeviceIoControl(h, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, 0, 0, &parms_ex, sizeof parms_ex, &rb, 0)) {
@@ -130,7 +137,7 @@
 	BYTE pdrv, ndrv;
 	WCHAR str[50];
 	HANDLE h;
-	OSVERSIONINFO vinfo = { sizeof (OSVERSIONINFO) };
+	//OSVERSIONINFO vinfo = { sizeof (OSVERSIONINFO) };
 
 
 	hMutex = CreateMutex(0, 0, 0);
@@ -143,17 +150,19 @@
 	if (!RamDisk) return 0;
 	Stat[0].sz_sector = SS_RAMDISK;
 
-	if (GetVersionEx(&vinfo) == FALSE) return 0;
-	ndrv = vinfo.dwMajorVersion > 5 ? 1 : MAX_DRIVES;
+	ndrv = MAX_DRIVES;
 
 	for (pdrv = 0; pdrv < ndrv; pdrv++) {
 		if (pdrv == 0) {	/* \\.\PhysicalDrive0 is never mapped to disk function, but RAM disk is mapped to pd#0 instead. */
 			swprintf(str, 50, L"RAM Disk");
-		} else {			/* \\.\PhysicalDrive<n> (n=1..) are mapped to disk funtion pd#<n>. */
-			swprintf(str, 50, L"\\\\.\\PhysicalDrive%u", pdrv);
-			h = CreateFileW(str, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING, 0);
-			if (h == INVALID_HANDLE_VALUE) break;
-			Stat[pdrv].h_drive = h;
+		}else {
+			swprintf(str, 50, L"PhysicalDrive%u", pdrv);
+			if (Stat[pdrv].h_drive != 0) {
+				CloseHandle(Stat[pdrv].h_drive);
+			}
+			h = CreateFileW(str, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING, 0);
+			if (h != INVALID_HANDLE_VALUE)
+				Stat[pdrv].h_drive = h;
 		}
 		wprintf(L"PD#%u <== %s", pdrv, str);
 		if (get_status(pdrv)) {
@@ -163,7 +172,7 @@
 		}
 	}
 
-	hTmrThread = CreateThread(0, 0, tmr_thread, 0, 0, &TmrThreadID);
+	//hTmrThread = CreateThread(0, 0, tmr_thread, 0, 0, &TmrThreadID);
 	if (hTmrThread == INVALID_HANDLE_VALUE) pdrv = 0;
 
 	if (ndrv > 1) {
@@ -321,9 +330,31 @@
 				res = RES_ERROR;
 			} else {
 				memcpy(Buffer, buff, nc);
-				if (!WriteFile(Stat[pdrv].h_drive, Buffer, nc, &rnc, 0) || nc != rnc) {
-					res = RES_ERROR;
+				{
+					int i;
+					for (i = 0; i < 10; i++) {
+						if (!WriteFile(Stat[pdrv].h_drive, Buffer, nc, &rnc, 0) || nc != rnc) {
+							LPVOID lpMsgBuf;
+							res = RES_ERROR;
+
+							FormatMessage(
+								FORMAT_MESSAGE_ALLOCATE_BUFFER  //      テキストのメモリ割り当てを要求する
+								| FORMAT_MESSAGE_FROM_SYSTEM    //      エラーメッセージはWindowsが用意しているものを使用
+								| FORMAT_MESSAGE_IGNORE_INSERTS,//      次の引数を無視してエラーコードに対するエラーメッセージを作成する
+								NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),//   言語を指定
+								(LPTSTR)&lpMsgBuf,                          //      メッセージテキストが保存されるバッファへのポインタ
+								0,
+								NULL);
+							printf((char*)lpMsgBuf);
+
+						}
+						else {
+							res = RES_OK;
+							break;
+						}
+					}
 				}
+				FlushFileBuffers(Stat[pdrv].h_drive);
 			}
 		}
 	} else {	/* RAM disk */

改造部分解説

太郎くん
太郎くん

確かに思ったよりも改造した箇所は少なそうだね。

フクさん
フクさん

簡単に解説すると以下になる。

  • 物理ドライブの走査をMAX_DRIVEにすることで、認識できる物理ドライブが増える。
  • 物理ドライブ0は従来通りのRAM Disk。
  • 物理ドライブ1以上を指定されたらCreateFileWでディスクイメージをオープン
太郎くん
太郎くん

確かにそんな感じの改造だね。

フクさん
フクさん

次回は実際に動作させてみよう。

まとめ

フクさん
フクさん

まとめだよ。

  • FatFs Win32のdiskio.cを改造。
    • 修正差分確認。
  • 改造の概要説明。
    • 物理ドライブ走査数をMAX_DRIVE分に修正して認識できる物理ドライブの数を増加。
    • 物理ドライブ1以上を指定されたらディスクイメージファイルをオープン。

バックナンバーはこちら。

コメント

タイトルとURLをコピーしました