All Classes Namespaces Files Functions Variables Enumerations Enumerator
libs/connection/resetComPort.cpp
Go to the documentation of this file.
00001 
00010 #include "resetComPort.h"
00011 #include "DetectOS.h"
00012 #if defined(WINDOWS_OS)
00013 #include <windows.h>
00014 #include <setupapi.h>
00015 #include <stdio.h>
00016 #endif
00017 
00018 
00019 namespace
00020 {
00021 #if defined(WINDOWS_OS)
00022     //4D36E978-E325-11CE-BFC1-08002BE10318
00023     GUID GUID_DEVINTERFACE_COM_DEVICE = {
00024         0x4D36E978L, 0xE325, 0x11CE,
00025         {
00026             0xBF, 0xC1, 0x08, 0x00, 0x2B, 0xE1, 0x03, 0x18
00027         }
00028     };
00029 
00030 
00031     int deviceId(const char* com_device, HDEVINFO hdi)
00032     {
00033         // com_name_ と同じものがあれば、返す
00034         SP_DEVINFO_DATA sDevInfo;
00035         sDevInfo.cbSize = sizeof(SP_DEVINFO_DATA);
00036         for (DWORD i = 0; SetupDiEnumDeviceInfo(hdi, i, &sDevInfo); ++i){
00037 
00038             enum { BufferSize = 128 };
00039             char buffer[BufferSize];
00040             DWORD dwRegType;
00041             DWORD dwSize = 0;
00042 
00043             // フレンドリーネームを取得し COM 番号とマッチするかで検出を判定する
00044             SetupDiGetDeviceRegistryProperty(hdi, &sDevInfo, SPDRP_FRIENDLYNAME,
00045                                              &dwRegType, (BYTE*)buffer,
00046                                              BufferSize, &dwSize);
00047             if (dwSize < 7) {
00048                 continue;
00049             }
00050             char* p = strstr(&buffer[dwSize - 7], "COM");
00051             if (! p) {
00052                 continue;
00053             }
00054 
00055             if (! strncmp(com_device, p, strlen(com_device))) {
00056                 return i;
00057             }
00058         }
00059 
00060         return -1;
00061     }
00062 
00063 
00064     void setDeviceState(int state, int device_id, HDEVINFO hdi)
00065     {
00066         SP_DEVINFO_DATA sDevInfo;
00067         sDevInfo.cbSize = sizeof(SP_DEVINFO_DATA);
00068         if (! SetupDiEnumDeviceInfo(hdi, device_id, &sDevInfo)) {
00069             return;
00070         }
00071 
00072         SP_PROPCHANGE_PARAMS sPropChange;
00073         sPropChange.ClassInstallHeader.cbSize =
00074             sizeof(sPropChange.ClassInstallHeader);
00075 
00076         sPropChange.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE;
00077         sPropChange.Scope = DICS_FLAG_GLOBAL;
00078         sPropChange.StateChange = state;
00079         if (! SetupDiSetClassInstallParams(hdi, &sDevInfo,
00080                                            &sPropChange.ClassInstallHeader,
00081                                            sizeof(sPropChange))) {
00082             return;
00083         }
00084         if (! SetupDiCallClassInstaller(DIF_PROPERTYCHANGE, hdi, &sDevInfo)) {
00085             return;
00086         }
00087 
00088         sPropChange.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE;
00089         sPropChange.Scope = DICS_FLAG_CONFIGSPECIFIC;
00090         sPropChange.StateChange = state;
00091         if (! SetupDiSetClassInstallParams(hdi, &sDevInfo,
00092                                            &sPropChange.ClassInstallHeader,
00093                                            sizeof(sPropChange))) {
00094             return;
00095         }
00096         if (! SetupDiCallClassInstaller(DIF_PROPERTYCHANGE, hdi, &sDevInfo)) {
00097             return;
00098         }
00099 
00100         return;
00101     }
00102 
00103 
00104     void disableDevice(int device_id, HDEVINFO hdi)
00105     {
00106         setDeviceState(DICS_DISABLE, device_id, hdi);
00107     }
00108 
00109 
00110     void enableDevice(int device_id, HDEVINFO hdi)
00111     {
00112         setDeviceState(DICS_ENABLE, device_id, hdi);
00113     }
00114 #endif
00115 }
00116 
00117 
00118 bool qrk::resetComPort(const char* com_device)
00119 {
00120 #if defined(WINDOWS_OS)
00121     HDEVINFO hdi = SetupDiGetClassDevs(&GUID_DEVINTERFACE_COM_DEVICE, 0, 0,
00122                                        DIGCF_PRESENT | DIGCF_INTERFACEDEVICE);
00123     if (hdi == INVALID_HANDLE_VALUE) {
00124         return false;
00125     }
00126 
00127 
00128     int id = deviceId(com_device, hdi);
00129     if (id >= 0) {
00130         disableDevice(id, hdi);
00131         enableDevice(id, hdi);
00132     }
00133 
00134     SetupDiDestroyDeviceInfoList(hdi);
00135 
00136     return true;
00137 #else
00138     // Linux では実装しない
00139     static_cast<void>(com_device);
00140 
00141     return false;
00142 #endif
00143 }