Results 1 to 4 of 4

Thread: USB Win Events messages Detecting in QT

  1. #1
    Join Date
    Aug 2008
    Posts
    38
    Thanks
    15
    Qt products
    Qt4
    Platforms
    Windows

    Default USB Win Events messages Detecting in QT

    Hello all,
    I have been searching through the QT Assistant and the forums here on events and processing them. I am working on an application where I need to detect when the VID/PID of the device is attached/detached to/from the system. From what I have discovered so far, it would appear as though I can create a class using a QAbstractEventDispatcher and an event filter function referencing a pointer to the received message. Which in the implementation would set the instance thread to 0, i.e. m_EvtDispatch = QAbstractEventDispatcher::instance(0);" and then set event filter, "m_EvtDispatch->setEventFilter(myClass::myEventFilter);"

    For the function implementation, it would process the message, maybe as a MSG type (unsure). I have a sample I am working with now as described, and the myEvent loop activates, but the parameters don't seem to ever match DBT_DEVICEARRIVAL/DBT_DEVICEREMOVECOMPLETE/or even DBT_DEVNODES_CHANGED, from the WM_DEVICECHANGE message.

    I have searched through the QEvent and QActionEvent and multiple others looking for something close on searching for new devices, but I am kind of at a loss. Any help would be greatly appreciated.

    Thanks,
    Alphawolfxv

    [EDIT 2008-Aug-14]: Should have noted system parameters, QT4.3.3, Win Vista.
    [EDIT 2008-Aug-14]: Added code sample.

    All these files are trying to do is to break when the WM_DEVICECHANGE is received, I can look for the Attach/Detach once this step is complete, I hope...

    Header:
    Qt Code:
    1. #ifndef TESTMSG1_H
    2. #define TESTMSG1_H
    3.  
    4. #include <QtGui/QDialog>
    5. #include <QAbstractEventDispatcher>
    6. #include <QtDebug>
    7. #include <windows.h>
    8. #include <dbt.h>
    9.  
    10. class TestMsg : public QDialog
    11. {
    12. Q_OBJECT
    13.  
    14. public:
    15. TestMsg(QWidget *parent = 0);
    16. ~TestMsg();
    17.  
    18. static bool myEvtFilter(void *message);
    19.  
    20. private:
    21. QAbstractEventDispatcher * m_EvtDispatch;
    22. };
    23.  
    24. #endif // TESTMSG1_H
    To copy to clipboard, switch view to plain text mode 

    Implementation:

    Qt Code:
    1. #include "testmsg1.h"
    2.  
    3. bool TestMsg::myEvtFilter(void *message)
    4. {
    5. MSG *msg;
    6. static int i = 0;
    7.  
    8. msg = (MSG*)message;
    9. qDebug() << "Test that we are getting events...";
    10. qDebug() << "message: " << msg->message << " wParam: " << msg->wParam
    11. << " lParam: " << msg->lParam << " handle: " << msg->hwnd;
    12. if (msg->message == WM_DEVICECHANGE)
    13. {
    14. i++;
    15. qDebug() << "Count:" << i << "wParam:" << msg->wParam << "lParam:" << msg-> lParam;
    16. }
    17.  
    18. return false;
    19. }
    20.  
    21.  
    22. TestMsg::TestMsg(QWidget *parent)
    23. : QDialog(parent)
    24. {
    25.  
    26. m_EvtDispatch = QAbstractEventDispatcher::instance(0);
    27. m_EvtDispatch->setEventFilter(TestMsg::myEvtFilter);
    28. }
    29.  
    30. TestMsg::~TestMsg()
    31. {
    32.  
    33. }
    To copy to clipboard, switch view to plain text mode 
    Last edited by AlphaWolfXV; 14th August 2008 at 15:58.

  2. #2
    Join Date
    Mar 2007
    Posts
    5
    Thanked 2 Times in 2 Posts
    Qt products
    Qt/Embedded
    Platforms
    MacOS X Windows

    Default Re: USB Win Events messages Detecting in QT

    I have also tried to install an event filter for CD arrival notification and could not
    get it to work. Here is what i did :

    _________ MFrame.h_________________
    Qt Code:
    1. #include <qt_windows.h>
    2.  
    3. class MFrame : public QWidget
    4. {
    5. Q_OBJECT
    6. public:
    7. MFrame();
    8.  
    9. protected :
    10. bool winEvent(MSG *msg,long * result);
    11.  
    12. signals:
    13. void CD_Removed(QChar tchar);
    14. void CD_Arrived(QChar tchar);
    15. };
    To copy to clipboard, switch view to plain text mode 
    ________ MFrame.cpp ____________________
    Qt Code:
    1. #include <QtCore>
    2. #include <QtGui>
    3. #include <QtDebug>
    4. #include "mframe.h"
    5. #include <dbt.h>
    6.  
    7. static char FirstDriveFromMask (ULONG unitmask)
    8. {
    9. char i;
    10.  
    11. for (i = 0; i < 26; ++i)
    12. {
    13. if (unitmask & 0x1)
    14. break;
    15. unitmask = unitmask >> 1;
    16. }
    17.  
    18. return (i + 'A');
    19. }
    20.  
    21. bool MFrame::winEvent(MSG * msg, long * result)
    22. {
    23. int msgType = msg->message;
    24. if(msgType == WM_DEVICECHANGE)
    25. {
    26. qDebug() << "winEvent in MgFrame : WM_DEVICECHANGE" ;
    27. PDEV_BROADCAST_HDR lpdb = (PDEV_BROADCAST_HDR)msg->lParam;
    28. switch(msg->wParam)
    29. {
    30. case DBT_DEVICEARRIVAL:
    31. if (lpdb -> dbch_devicetype == DBT_DEVTYP_VOLUME)
    32. {
    33. PDEV_BROADCAST_VOLUME lpdbv = (PDEV_BROADCAST_VOLUME)lpdb;
    34. if (lpdbv -> dbcv_flags & DBTF_MEDIA)
    35. {
    36. char ALET = FirstDriveFromMask(lpdbv->dbcv_unitmask);
    37. emit CD_Arrived(QChar(ALET));
    38. qDebug() << "CD_Arrived ";
    39.  
    40. }
    41. }
    42. break;
    43.  
    44. case DBT_DEVICEREMOVECOMPLETE:
    45. if (lpdb -> dbch_devicetype == DBT_DEVTYP_VOLUME)
    46. {
    47. PDEV_BROADCAST_VOLUME lpdbv = (PDEV_BROADCAST_VOLUME)lpdb;
    48. if (lpdbv -> dbcv_flags & DBTF_MEDIA)
    49. {
    50. char ALET = FirstDriveFromMask(lpdbv->dbcv_unitmask);
    51. emit CD_Removed(QChar(ALET));
    52. qDebug() << "CD_Removed";
    53. }
    54. }
    55. break;
    56. } // skip the rest
    57.  
    58. } // end of if msgType
    59. return false; // let qt handle the rest
    60. }
    To copy to clipboard, switch view to plain text mode 

    I found that It only works on the main window. This is why I emit CD_Arrived and
    CD_Removed signals.
    Hope this helps
    Murielle
    Last edited by jacek; 14th August 2008 at 19:15. Reason: missing [code] tags

  3. The following user says thank you to LaOnze2000 for this useful post:

    AlphaWolfXV (14th August 2008)

  4. #3
    Join Date
    Aug 2008
    Posts
    38
    Thanks
    15
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: USB Win Events messages Detecting in QT

    Murielle,
    Thank you so very much. I am able to now at least detect when the change happens! I can filter through the rest of the necessary parameters for VID/PID now that I have a starting point! Thanks again for the great example!!

    Cyrus

  5. #4

    Default Re: USB Win Events messages Detecting in QT

    It's been a while since the original post, but I encountered the same problem and here is how i solved it:

    1. How to recognize if an USB drive is plugged in or out:
    • inclde the following headers: #include <windows.h> #include <Dbt.h> #include <SetupAPI.h>
    • register this function in your GUI class header filer under public: bool winEvent ( MSG * msg, long * result );
    • also define the char variable DriveLetter there: char DriveLetter;
    • in your GUI class cpp-file this function shoud be definde like this:
      bool myGUI::winEvent(MSG *msg, long *result)
      {
      int msgType = msg->message;
      if(msgType == WM_DEVICECHANGE)
      {
      switch(msg->wParam)
      {
      case DBT_DEVICEARRIVAL:
      getDriveLetterFromMsg(msg);
      getMoreDriveInfosFromLetter(DriveLetter);
      break;

      case DBT_DEVICEREMOVECOMPLETE:
      getDriveLetterFromMsg(msg);
      break;
      }
      }
      return false;
      }

    2. What you now need are the functions getDriveLetterFromMsg(msg) and getMoreDriveInfosFromLetter(DriveLetter). Here they are:
    • char getDriveLetterFromMsg(MSG *msg)
      {
      char DriveLetter = 0;
      PDEV_BROADCAST_HDR drive_hdr = (PDEV_BROADCAST_HDR)msg->lParam;

      if (drive_hdr -> dbch_devicetype == DBT_DEVTYP_VOLUME)
      {
      PDEV_BROADCAST_VOLUME volume_hdr = (PDEV_BROADCAST_VOLUME)drive_hdr;
      PDEV_BROADCAST_DEVICEINTERFACE device_info = (PDEV_BROADCAST_DEVICEINTERFACE)drive_hdr;
      char name = (char)device_info->dbcc_name;
      DriveLetter = FirstDriveFromMask(volume_hdr->dbcv_unitmask);
      }

      return DriveLetter;
      }
    • bool getMoreDriveInfosFromLetter(char driveletter, mydrive *drive){

      //catch errors
      DWORD ercode;

      //create Path
      std::wstring drivePath_str( L"X:\\" );
      std::wstring drivePath_str_UNC( L"\\\\.\\X:" );
      drivePath_str[0] = driveletter;
      drivePath_str_UNC[4] = driveletter;
      const wchar_t* drivePath_chr = drivePath_str.c_str();
      const wchar_t* drivePath_chr_UNC = drivePath_str_UNC.c_str();

      //get Drive Type
      UINT DriveType = GetDriveType((LPCWSTR)drivePath_chr);
      ercode = GetLastError();
      if(ercode > 0){ tools::writeError(ercode); return false; }

      //get Device Number
      HANDLE DriveHandle = CreateFile((LPCTSTR)drivePath_chr_UNC,GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE ,NULL, OPEN_EXISTING, 0, NULL);
      STORAGE_DEVICE_NUMBER storageDeviceNumber;
      DWORD BytesReturned = 0;
      DeviceIoControl(DriveHandle,IOCTL_STORAGE_GET_DEVI CE_NUMBER,NULL, 0, &storageDeviceNumber, sizeof(storageDeviceNumber),&BytesReturned, NULL);
      ercode = GetLastError();
      if(ercode > 0){ tools::writeError(ercode); return false; }
      unsigned long DeviceNumber = storageDeviceNumber.DeviceNumber;

      //get more Infos
      QString driveInfos = GetDrivesDevInstByDiskNumber(DeviceNumber,DriveTyp e);
      if(driveInfos.isEmpty())
      {
      tools::writeError(QString("Can't get Infos of Drive %1").arg(driveletter));
      return false;
      }

      //save Infos: All the Information gathered is stored in 'driveInfos'
      //do something with driveInfos


      //everything went ok
      return true;

      }

    3. In addition you need the functions FirstDriveFromMask(volume_hdr->dbcv_unitmask) and GetDrivesDevInstByDiskNumber(long DiskNumber, UINT DriveType):
    • char FirstDriveFromMask( ULONG unitmask ){
      char i;

      for (i = 0; i < 26; ++i){
      if (unitmask & 0x1)
      break;
      unitmask = unitmask >> 1;
      }
      return( i + 'A' );
      }
    • QString GetDrivesDevInstByDiskNumber(long DiskNumber, UINT DriveType)
      {
      GUID* guid;
      QString DriveInfos;

      switch (DriveType)
      {
      case DRIVE_REMOVABLE:
      case DRIVE_FIXED:
      guid = (GUID*)(void*)&GUID_DEVINTERFACE_DISK;
      break;
      case DRIVE_CDROM:
      guid = (GUID*)(void*)&GUID_DEVINTERFACE_CDROM;
      break;
      default:
      return 0;
      }

      // Get device interface info set handle for all devices attached to system

      HDEVINFO hDevInfo = SetupDiGetClassDevs(guid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
      if (hDevInfo == INVALID_HANDLE_VALUE)
      {
      return 0;
      }

      SP_DEVICE_INTERFACE_DATA devInterfaceData = {0};
      BOOL bRet = FALSE;
      BYTE Buf[1024];
      PSP_DEVICE_INTERFACE_DETAIL_DATA pspdidd = (PSP_DEVICE_INTERFACE_DETAIL_DATA)Buf;
      SP_DEVICE_INTERFACE_DATA spdid;
      SP_DEVINFO_DATA spdd;
      DWORD dwSize;

      devInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
      spdid.cbSize = sizeof(spdid);
      for(DWORD dwIndex = 0; TRUE; dwIndex++)
      {
      bRet = SetupDiEnumDeviceInterfaces(hDevInfo, NULL, guid, dwIndex, &devInterfaceData);
      if (!bRet)
      break;

      SetupDiEnumInterfaceDevice(hDevInfo, NULL, guid, dwIndex, &spdid);
      dwSize = 0;
      SetupDiGetDeviceInterfaceDetail(hDevInfo, &spdid, NULL, 0, &dwSize, NULL);
      if ( dwSize!=0 && dwSize<=sizeof(Buf) )
      {
      pspdidd->cbSize = sizeof(*pspdidd); // 5 Bytes!

      ZeroMemory((PVOID)&spdd, sizeof(spdd));
      spdd.cbSize = sizeof(spdd);

      long res = SetupDiGetDeviceInterfaceDetail(hDevInfo, &spdid, pspdidd, dwSize, &dwSize, &spdd);
      if ( res )
      {
      HANDLE hDrive = CreateFile(pspdidd->DevicePath, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, NULL, NULL);
      if ( hDrive != INVALID_HANDLE_VALUE )
      {
      STORAGE_DEVICE_NUMBER sdn;
      DWORD dwBytesReturned = 0;
      res = DeviceIoControl(hDrive, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &sdn, sizeof(sdn), &dwBytesReturned, NULL);
      CloseHandle(hDrive);
      if (res && (DiskNumber == (long)sdn.DeviceNumber))
      {
      DriveInfos = QString::fromWCharArray(pspdidd->DevicePath);
      break;
      }
      }
      }
      }
      }

      SetupDiDestroyDeviceInfoList(hDevInfo);
      return DriveInfos;

      }

Similar Threads

  1. QGraphicsView Mouse Events
    By tomf in forum Qt Programming
    Replies: 5
    Last Post: 29th July 2008, 15:03
  2. Detecting KeyPad Events from my Keypad
    By Svaths in forum Qt for Embedded and Mobile
    Replies: 0
    Last Post: 18th August 2006, 07:28

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.