#include "rm_usb.h" #include #include #include #include #include #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(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(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)