#include <Windows.h>
#include <tchar.h>

#include "tstring.h"
#include "ftd2xx.h"
#include "ftd2xx_func.h"

const _TCHAR FTDI_DLL_NAME[] = _T("ftd2xx.dll");

int _tmain(int argc, _TCHAR *argv[])
{
	HMODULE hFtModule;						// ftdi dll のハンドル
	TCHAR szSysPath[MAX_PATH] = _T("");		// windows system パス
	std::tstring dllname;					// ftdi dll のフルパス

	// ftdi dll 公開関数へのポインタ
	_FT_CreateDeviceInfoList FT_CreateDeviceInfoList = NULL;
	_FT_GetDeviceInfoList FT_GetDeviceInfoList = NULL;

	GetSystemDirectory(szSysPath, _countof(szSysPath));
	dllname = szSysPath;
	dllname += _T("\\");
	dllname += FTDI_DLL_NAME;			// ftdi dll フルパス

	// dll ロード
	hFtModule = LoadLibrary(dllname.c_str());
	if (hFtModule) {
		FT_CreateDeviceInfoList = (_FT_CreateDeviceInfoList)GetProcAddress(hFtModule, "FT_CreateDeviceInfoList");
		FT_GetDeviceInfoList = (_FT_GetDeviceInfoList)GetProcAddress(hFtModule, "FT_GetDeviceInfoList");

		//  ftdi デバイス情報取得
		DWORD devNum = 0;		// デバイス数
		FT_STATUS ret = FT_OK;	// 返り値

		ret = FT_CreateDeviceInfoList(&devNum);
		if ((ret == FT_OK) && (devNum > 0)) {

			FT_DEVICE_LIST_INFO_NODE *pInfo = new FT_DEVICE_LIST_INFO_NODE[devNum];
			ret = FT_GetDeviceInfoList(pInfo, &devNum);
			
			if (ret == FT_OK) {
			
				_tprintf(_T("FTDI デバイスが %d 個見つかりました\r\n"), devNum);
	
				std::tstring chipType = _T("");

				for (DWORD i = 0; i < devNum; i++) {

					switch (pInfo[i].Type) {
					case FT_DEVICE_BM:
						chipType = _T("FT232BM");
						break;

					case FT_DEVICE_AM:
						chipType = _T("FT232AM");
						break;

					case FT_DEVICE_100AX:
						chipType = _T("100AX");
						break;

					case FT_DEVICE_UNKNOWN:
						chipType = _T("Unknown");
						break;

					case FT_DEVICE_2232C:
						chipType = _T("FT2232C/D/L");
						break;

					case FT_DEVICE_232R:
						chipType = _T("FT232R");
						break;

					case FT_DEVICE_2232H:
						chipType = _T("FT2232H");
						break;

					case FT_DEVICE_4232H:
						chipType = _T("FT4232H");
						break;

					case FT_DEVICE_232H:
						chipType = _T("FT232H");
						break;

					case FT_DEVICE_X_SERIES:
						chipType = _T("FT-X series");
						break;

					case FT_DEVICE_4222H_0:
						chipType = _T("FT4222H_0");
						break;

					case FT_DEVICE_4222H_1_2:
						chipType = _T("FT4222H_1_2");
						break;

					case FT_DEVICE_4222H_3:
						chipType = _T("FT4222H_3");
						break;

					case FT_DEVICE_4222_PROG:
						chipType = _T("FT4222_PROG");
						break;

					case FT_DEVICE_900:
						chipType = _T("FT900");
						break;

					case FT_DEVICE_930:
						chipType = _T("FT930");
						break;

					case FT_DEVICE_UMFTPD3A:
						chipType = _T("UMFTPD3A");
						break;

					default:
						chipType = _T("UNDEFINED");
						break;
					}

					_tprintf(_T("-------------------------------------------------------\r\n"));
					_tprintf(_T("Device No.    = %d\r\n"), i);
					_tprintf(_T("Device Type   = %s\r\n"), chipType.c_str());
					_tprintf(_T("Serial Number = \"%s\"\r\n"), pInfo[i].SerialNumber);
					_tprintf(_T("Description   = \"%s\"\r\n"), pInfo[i].Description);
					_tprintf(_T("Location ID   = %d\r\n"), pInfo[i].LocId);
					_tprintf(_T("ID            = %d\r\n"), pInfo[i].ID);
					if (pInfo[i].Flags & 0x01) {
						_tprintf(_T("Port Status   = Opend\r\n"));
					}
					else {
						_tprintf(_T("Port Status   = Closed\r\n"));
					}
					if (pInfo[i].Flags & 0x02) {
						_tprintf(_T("USB type      = Hi-speed\r\n"));
					}
					else {
						_tprintf(_T("USB type      = Full-speed\r\n"));
					}

					
				} // for
			} // if

			delete[] pInfo;
			pInfo = NULL;
		}
		else {	// devNum>0 ?
			_tprintf(_T("FTDI デバイスがありません\r\n"));
		}

		FreeLibrary(hFtModule);

	}
	else {
		_tprintf(_T("FTDI DLL がロードできません\r\n"));
	}

	system("pause");
	return 0;
}