341 lines
11 KiB
C++
341 lines
11 KiB
C++
#include "rm_usb.h"
|
|
#include <Windows.h>
|
|
#include <dbt.h>
|
|
#include <QDebug>
|
|
#include <QDir>
|
|
#include <QTimer>
|
|
#if (RM_MODEL_EMT_KR)
|
|
#include "../cfg/rm_settings_cfg_emt_kr.h"
|
|
#endif
|
|
|
|
#if (DETECT_SETTING_USB_EJECT || DETECT_USB_CHANGE)
|
|
|
|
rm_usb::rm_usb(QObject *parent) :
|
|
QObject(parent)
|
|
{
|
|
_hDevNotify = NULL;
|
|
_insertringDrive = 0;
|
|
_removingDrive = 0;
|
|
_openDrive = "";
|
|
_irTimer = NULL;
|
|
}
|
|
rm_usb::~rm_usb()
|
|
{
|
|
if(_hDevNotify != NULL) {
|
|
::UnregisterDeviceNotification(_hDevNotify);
|
|
}
|
|
_cancelIRTimer();
|
|
}
|
|
|
|
// 항상 대문자로 리턴됨
|
|
char rm_usb::_firstDriveFromMask( uint unitmask )
|
|
{
|
|
char i;
|
|
|
|
for (i = 0; i < 26; ++i)
|
|
{
|
|
if (unitmask & 0x1)
|
|
break;
|
|
unitmask = unitmask >> 1;
|
|
}
|
|
return( i + 'A' );
|
|
}
|
|
void rm_usb::_startIRTimer()
|
|
{
|
|
_cancelIRTimer();
|
|
_irTimer = new QTimer(this);
|
|
_irTimer->setSingleShot(true);
|
|
_irTimer->setInterval(1000);
|
|
connect(_irTimer,SIGNAL(timeout()),SLOT(onClearIR()));
|
|
_irTimer->start();
|
|
}
|
|
void rm_usb::_cancelIRTimer()
|
|
{
|
|
if(_irTimer != NULL) {
|
|
_irTimer->stop();
|
|
delete _irTimer;
|
|
_irTimer = NULL;
|
|
}
|
|
}
|
|
void rm_usb::onClearIR()
|
|
{
|
|
_insertringDrive = 0;
|
|
_removingDrive = 0;
|
|
}
|
|
|
|
bool rm_usb::nativeEventFilter(const QByteArray &eventType, void *message, long *result)
|
|
{
|
|
Q_UNUSED(eventType);
|
|
Q_UNUSED(result);
|
|
#ifdef Q_OS_WIN32
|
|
MSG *msg = (MSG *)message;
|
|
if( WM_DEVICECHANGE == msg->message && DBT_DEVICEARRIVAL == msg->wParam )
|
|
{
|
|
DEV_BROADCAST_HDR* dev = (DEV_BROADCAST_HDR*)msg->lParam;
|
|
if (dev->dbch_devicetype == DBT_DEVTYP_VOLUME)
|
|
{
|
|
PDEV_BROADCAST_VOLUME lpdbv = (PDEV_BROADCAST_VOLUME)dev;
|
|
char driver = _firstDriveFromMask(lpdbv->dbcv_unitmask);
|
|
|
|
// 다중 호출 방지 -> 처리 끝나면 초기화 해야 함
|
|
if (_insertringDrive != driver)
|
|
{
|
|
_insertringDrive = driver;
|
|
QString driver_letter(driver);
|
|
driver_letter += ":";
|
|
// qInfo() << "USB arrival detected:" << driver;
|
|
*result = 1;
|
|
emit usbChanged(true,driver_letter);
|
|
_startIRTimer();
|
|
}
|
|
}
|
|
}
|
|
else if( WM_DEVICECHANGE == msg->message && DBT_DEVICEREMOVECOMPLETE == msg->wParam )
|
|
{
|
|
DEV_BROADCAST_HDR* dev = (DEV_BROADCAST_HDR*)msg->lParam;
|
|
if (dev->dbch_devicetype == DBT_DEVTYP_VOLUME)
|
|
{
|
|
PDEV_BROADCAST_VOLUME lpdbv = (PDEV_BROADCAST_VOLUME)dev;
|
|
char driver = _firstDriveFromMask(lpdbv->dbcv_unitmask);
|
|
if (_removingDrive != driver)
|
|
{
|
|
_removingDrive = driver;
|
|
QString driver_letter(driver);
|
|
driver_letter += ":";
|
|
// qInfo() << "USB departure detected:" << " driver:" << driver;
|
|
*result = 1;
|
|
emit usbChanged(false,driver_letter);
|
|
_startIRTimer();
|
|
}
|
|
}
|
|
}
|
|
#endif // Q_OS_WIN32
|
|
// Return false so that the event is propagated
|
|
return false;
|
|
}
|
|
|
|
|
|
void rm_usb::registerEvent(QWidget *window)
|
|
{
|
|
if( window != nullptr )
|
|
{
|
|
#ifdef Q_OS_WIN32
|
|
GUID WceusbshGUID = { 0x25dbce51, 0x6c8f, 0x4a72, 0x8a,0x6d,0xb5,0x4c,0x2b,0x4f,0xc8,0x35 };
|
|
//GUID WusbrawGUID = {0xa5dcbf10, 0x6530, 0x11d2, 0x90, 0x1f, 0x00, 0xc0, 0x4f, 0xb9, 0x51, 0xed };
|
|
//GUID WusbGUID = {0x88BAE032, 0x5A81, 0x49f0, 0xBC, 0x3D, 0xA4, 0xFF, 0x13, 0x82, 0x16, 0xD6 };
|
|
|
|
DEV_BROADCAST_DEVICEINTERFACE NotificationFilter;
|
|
|
|
::ZeroMemory( &NotificationFilter, sizeof(NotificationFilter) );
|
|
NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
|
|
NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
|
|
NotificationFilter.dbcc_classguid = WceusbshGUID;
|
|
_hDevNotify = ::RegisterDeviceNotification((HANDLE)window->winId(), &NotificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE);
|
|
if( NULL == _hDevNotify )
|
|
{
|
|
// Print error
|
|
}
|
|
#endif
|
|
}
|
|
|
|
}
|
|
bool rm_usb::isRemovablePath(QString path)
|
|
{
|
|
if(path.contains(":")) {
|
|
QString driver = path.split(":").first();
|
|
WCHAR diskName[4] = {0,};
|
|
driver = driver.left(1) + ":\\";
|
|
driver.toWCharArray(diskName);
|
|
if(::GetDriveType(diskName) == DRIVE_REMOVABLE) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
void rm_usb::setOpenDriveWithPath(QString path)
|
|
{
|
|
if(rm_usb::isRemovablePath(path)) {
|
|
_openDrive = path.left(1).toUpper() + ":";
|
|
}
|
|
}
|
|
int rm_usb::isDeviceDriver(QString folder, bool loadCFG)
|
|
{
|
|
#if (RM_MODEL_TB) // RM_MODEL == RM_MODEL_TYPE_TB4000
|
|
return QDir(folder).exists() && QDir(folder + QDir::separator() + QString("Video")).exists() && QDir(folder + QDir::separator() + QString("Photo")).exists();
|
|
#elif (RM_MODEL_EMT_KR)
|
|
// 각 모델별로 확인
|
|
for(int i=0;i<CFG::model_names.size();i++) {
|
|
QString path = folder + "Setting" + QDir::separator() + CFG::model_names.at(i) + "_setting.cfg";
|
|
if(QFile::exists(path)) {
|
|
// 설정파일 읽을 필요 없음
|
|
if(!loadCFG) {
|
|
return 0;
|
|
}
|
|
// checksum + 크기 + 모델코드 확인
|
|
CFG_ERROR_CODE code = CFG::load(path);
|
|
if(code != CFG_SUCCESS) {
|
|
if(code == CFG_CHECKSUM_ERROR) {
|
|
return code;
|
|
}
|
|
//qInfo() << path << " MODEL CODE:" << CFG::info.model << "ERROR:" << code << __FUNCTION__;
|
|
}
|
|
if(code == CFG_SUCCESS && CFG::info.model == CFG::model_codes[i])
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
// E:\Setting , NM5000_setting.cfg
|
|
// Magnus : 5101
|
|
// Trinity : 5102
|
|
// Mirror5 : 5103
|
|
// Pro5 : 5104
|
|
// 360X : 5105
|
|
|
|
return 999;
|
|
#else //
|
|
return false;
|
|
#endif;
|
|
}
|
|
|
|
// Disk 의 볼륨명이 모델명과 동일함
|
|
#if (RM_MODEL_EMT_KR)
|
|
QString rm_usb::getRemovableDisk()
|
|
{
|
|
#if defined(WIN32)
|
|
WCHAR szLogicalDrives[MAX_PATH * sizeof(TCHAR)];
|
|
DWORD dwByte = ::GetLogicalDriveStrings(MAX_PATH, szLogicalDrives);
|
|
|
|
for(DWORD i=0; i<dwByte / 4; i++)
|
|
{
|
|
WCHAR* diskName = &szLogicalDrives[i * 4];
|
|
UINT type = ::GetDriveType(diskName);
|
|
if(DRIVE_REMOVABLE == type)
|
|
{
|
|
#if (!NO_SD_CHECK)
|
|
QString diskLetter = QString::fromUtf16((const ushort*)diskName);
|
|
|
|
diskLetter.replace("\\","");
|
|
|
|
diskLetter = "\\\\.\\" + diskLetter;
|
|
|
|
// qInfo() << "check disk name:" << diskLetter;
|
|
// empty media check
|
|
HANDLE hDisk = ::CreateFile(reinterpret_cast<LPCWSTR>(diskLetter.utf16()),
|
|
FILE_READ_DATA,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
0,
|
|
NULL);
|
|
|
|
if(hDisk == INVALID_HANDLE_VALUE || hDisk == NULL)
|
|
{
|
|
//qInfo() << "INVALID_HANDLE_VALUE" << diskLetter << "type" << type;
|
|
continue;
|
|
}
|
|
|
|
DWORD dwBytesReturned;
|
|
ULONG MediaChangeCount;
|
|
BOOL res = ::DeviceIoControl( hDisk,
|
|
IOCTL_STORAGE_CHECK_VERIFY,
|
|
NULL,
|
|
0,
|
|
&MediaChangeCount,
|
|
sizeof(ULONG),
|
|
&dwBytesReturned,
|
|
NULL);
|
|
::CloseHandle(hDisk);
|
|
if(res == FALSE)
|
|
{
|
|
//qInfo() << "empty" << QString::fromUtf16((const ushort*)diskName) << "type" << type;
|
|
continue;
|
|
}
|
|
#endif
|
|
QString diskPath = QString::fromUtf16((const ushort*)diskName);
|
|
// 설정파일 존재 확인
|
|
if(isDeviceDriver(diskPath,false) == 0) {
|
|
return diskPath;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
return "";
|
|
}
|
|
#else // TB
|
|
QString rm_usb::getRemovableDisk(QString volume)
|
|
{
|
|
#if defined(WIN32)
|
|
WCHAR szLogicalDrives[MAX_PATH * sizeof(TCHAR)];
|
|
DWORD dwByte = ::GetLogicalDriveStrings(MAX_PATH, szLogicalDrives);
|
|
|
|
for(DWORD i=0; i<dwByte / 4; i++)
|
|
{
|
|
WCHAR* diskName = &szLogicalDrives[i * 4];
|
|
UINT type = ::GetDriveType(diskName);
|
|
if(DRIVE_REMOVABLE == type)
|
|
{
|
|
|
|
#if (!NO_SD_CHECK)
|
|
QString diskLetter = QString::fromUtf16((const ushort*)diskName);
|
|
|
|
diskLetter.replace("\\","");
|
|
|
|
diskLetter = "\\\\.\\" + diskLetter;
|
|
|
|
// qInfo() << "check disk name:" << diskLetter;
|
|
// empty media check
|
|
HANDLE hDisk = ::CreateFile(reinterpret_cast<LPCWSTR>(diskLetter.utf16()),
|
|
FILE_READ_DATA,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
0,
|
|
NULL);
|
|
|
|
if(hDisk == INVALID_HANDLE_VALUE || hDisk == NULL)
|
|
{
|
|
//qInfo() << "INVALID_HANDLE_VALUE" << diskLetter << "type" << type;
|
|
continue;
|
|
}
|
|
|
|
DWORD dwBytesReturned;
|
|
ULONG MediaChangeCount;
|
|
BOOL res = ::DeviceIoControl( hDisk,
|
|
IOCTL_STORAGE_CHECK_VERIFY,
|
|
NULL,
|
|
0,
|
|
&MediaChangeCount,
|
|
sizeof(ULONG),
|
|
&dwBytesReturned,
|
|
NULL);
|
|
::CloseHandle(hDisk);
|
|
if(res == FALSE)
|
|
{
|
|
//qInfo() << "empty" << QString::fromUtf16((const ushort*)diskName) << "type" << type;
|
|
continue;
|
|
}
|
|
#endif
|
|
|
|
WCHAR volumeNameW[MAX_PATH * sizeof(TCHAR)] = {0,};
|
|
|
|
::GetVolumeInformation(diskName,volumeNameW, 1024, NULL, NULL, NULL, NULL, MAX_PATH);
|
|
|
|
QString volumeName = QString::fromUtf16((const ushort*)volumeNameW);
|
|
QString diskPath = QString::fromUtf16((const ushort*)diskName);
|
|
//qInfo() << volumeName << __FUNCTION__;
|
|
if(volume.isEmpty() || volume.compare(volumeName,Qt::CaseInsensitive) == 0)
|
|
{
|
|
diskPath = diskPath.replace("\\","");
|
|
//rm_usb::current_driver = diskPath.at(0).toLatin1();
|
|
return diskPath;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
return "";
|
|
}
|
|
#endif // #if (RM_MODEL_EMT_KR)
|
|
#endif // #if (USE_SD_CARD_DETECT)
|