На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Обратите внимание:
1. Прежде чем начать новую тему или отправить сообщение, убедитесь, что вы не нарушаете правил форума!
2. Обязательно воспользуйтесь поиском. Возможно, Ваш вопрос уже обсуждали. Полезные ссылки приведены ниже.
3. Темы с просьбой выполнить какую-либо работу за автора в этом разделе не обсуждаются.
4. Используйте теги [ code=cpp ] ...текст программы... [ /code ] для выделения текста программы подсветкой.
5. Помните, здесь телепатов нет. Старайтесь формулировать свой вопрос максимально грамотно и чётко: Как правильно задавать вопросы
6. Запрещено отвечать в темы месячной и более давности без веских на то причин.

Полезные ссылки:
user posted image FAQ Сайта (C++) user posted image FAQ Форума user posted image Наши Исходники user posted image Поиск по Разделу user posted image MSDN Library Online (Windows Driver Kit) user posted image Google

Ваше мнение о модераторах: user posted image B.V.
Модераторы: B.V.
  
> Детект присоединения/отсоединения USB-устройства
    Всем привет!

    Народ, выручайте - я уже весь моск сломал! :'( Крокодил не ловится, и не растет кокос! :'(

    Решил добавить в свою прогу функционал сабжа (тот самый usb-картридер). Ну и понеслась ...

    Типа хистори
    1. Сперва решил заюзать libusb. Но не срослось. Функция libusb_hotplug_register_callback возвращала строго фэйл. Тестовые исходники сохранил, но решил попробовать что-то более другое.
    2. Нашел в сети практически идеал - заготовка под Qt с использованием QWidget::::nativeEvent и отслеживанием WM_DEVICECHANGE и последующим отловом DBT_DEVICEARRIVAL и DBT_DEVICEREMOVECOMPLETE. Но, как я не старался, всегда ловил DBT_DEVNODES_CHANGED и только его и ничего более.
    3. Ланна, думаю, надо как-то задебажить на уровне сообщений венды. Пока взял паузу, вернее ... решил попотчивать себя куриным фрикасе с грибами и зеленой фасолью в майонезной заливке, и со свежайшим белорусским картофаном неизвестного происхождения, но под укропчиком с петрушкой и злободневной долей чесночка (а я этот участок пространства-времени готовлю просто божественно!!!), а потом резко взял нашел и запустил тулзу Spy++. И что я увилел? :blink: При подключении/отключении картридера летают WM_DEVICECHANGE, НО на пару с DBT_DEVINSTSTARTED и DBT_DEVINSTREMOVED. Спецом проверил и выверил - DBT_DEVICEARRIVAL и DBT_DEVICEREMOVECOMPLETE ну не было в журнале этого спая, совсем не было!!!
    4. Переделал исходники уже под DBT_DEVINSTSTARTED и DBT_DEVINSTREMOVED ... и все равно этот, простите, сраный Qt'шный QWidget::::nativeEvent ловит строго и исключительно WM_DEVICECHANGE с DBT_DEVNODES_CHANGED и все тут!
    5. Я уже отчаялся :-? Потом думаю - дай найду какую нить хрень без Qt. Нашел прикольный прожект HWDetect, и он мой девайс определял запросто.
    6. А потом решил тупо найти прожект без Qt, но рабочий и без сраной студии ... и тож нашел

    А рабочий проект без Qt работает только в путь ... единственное (я х3) пришлось его мало-мало править, иначе не компилился. В результате получился работающий исходник, который ловит мой девайс:
    Скрытый текст
    ExpandedWrap disabled
      #define ANSI
      #define WIN32_LEAN_AND_MEAN
      #define _WIN32_WINNT   0x0501
       
      #include <windows.h>
      #include <winuser.h>
      #include <Dbt.h>
       
      #include <string>
      #include <iostream>
      #include <stdexcept>
       
      #define HID_CLASSGUID {0x4d1e55b2, 0xf16f, 0x11cf,{ 0x88, 0xcb, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30}}
      #define CLS_NAME L"DUMMY_CLASS"
      #define HWND_MESSAGE     ((HWND)-3)
       
      LRESULT message_handler(HWND__* hwnd, UINT uint, WPARAM wparam, LPARAM lparam) {
          switch (uint) {
              case WM_NCCREATE: // before window creation
                  return true;
                  break;
              case WM_CREATE: { // the actual creation of the window
                      // you can get your creation params here..like GUID..
                      LPCREATESTRUCT params = (LPCREATESTRUCT) lparam;
                      GUID InterfaceClassGuid = *((GUID *)params->lpCreateParams);
                      DEV_BROADCAST_DEVICEINTERFACE NotificationFilter;
                      ZeroMemory(&NotificationFilter, sizeof(NotificationFilter));
                      NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
                      NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
                      NotificationFilter.dbcc_classguid = InterfaceClassGuid;
                      HDEVNOTIFY dev_notify = RegisterDeviceNotification(hwnd, &NotificationFilter,
                                                                      DEVICE_NOTIFY_WINDOW_HANDLE);
                      if (dev_notify == NULL)
                          throw std::runtime_error("Could not register for devicenotifications!");
                      break;
                  }
              case WM_DEVICECHANGE: {
                      PDEV_BROADCAST_HDR lpdb = (PDEV_BROADCAST_HDR) lparam;
                      PDEV_BROADCAST_DEVICEINTERFACE lpdbv = (PDEV_BROADCAST_DEVICEINTERFACE) lpdb;
                      std::string path;
                      if (lpdb->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) {
                          std::wstring ws(lpdbv->dbcc_name);
                          path = std::string(ws.begin(), ws.end());
                          switch (wparam) {
                              case DBT_DEVICEARRIVAL:
                                  std::cout << "new device connected: " << path << "\n";
                                  break;
                              case DBT_DEVICEREMOVECOMPLETE:
                                  std::cout << "device disconnected: " << path << "\n";
                                  break;
                          }
                      }
                      break;
                  }
          }
          return 0L;
      }
       
      int main(int, char **) {
          HWND hWnd = NULL;
          WNDCLASSEX wx;
          ZeroMemory(&wx, sizeof(wx));
          wx.cbSize = sizeof(WNDCLASSEX);
          wx.lpfnWndProc = reinterpret_cast<WNDPROC>(message_handler);
          wx.hInstance = reinterpret_cast<HINSTANCE>(GetModuleHandle(0));
          wx.style = CS_HREDRAW | CS_VREDRAW;
          wx.hInstance = GetModuleHandle(0);
          wx.hbrBackground = (HBRUSH)(COLOR_WINDOW);
          wx.lpszClassName = CLS_NAME;
          GUID guid = HID_CLASSGUID;
          if (RegisterClassEx(&wx)) {
              hWnd = CreateWindow(CLS_NAME, L"DevNotifWnd", WS_ICONIC,
                                                      0, 0, CW_USEDEFAULT, 0, HWND_MESSAGE,
                                                      NULL, GetModuleHandle(0), (void *)&guid);
          }
          if (hWnd == NULL)
              throw std::runtime_error("Could not create message window!");
          std::cout << "waiting for new devices..\n";
          MSG msg;
          while (GetMessage(&msg, NULL, 0, 0)) {
              TranslateMessage(&msg);
              DispatchMessage(&msg);
          }
          return 0;
      }


    Вот теперь наверное самое время ругаться (нет, не ругаться!!! просто разговаривать - матом). Последний сорс - ловит. Spy++ эту хрень не ловит, равно как и все остальные мои ранешние поползновения. Что я ДЕЛАЮ НЕ ТАГ!!! >:(
      JoeUser
      Короче вот тут китайцы работают с ЮСБ под виндоус. Код с прода, работает детектит нужное устройство, но только с хабами работать не умеет(или не совсеми). Исходник простой думаю если разберетесь он вам сильно поможет.
      https://github.com/xuxiandi/AndroidAdb/tree...dows/usb/winusb
        Pavia. tnx - завтра гляну и отпишусь!
          Pavia, глянул. Материал интересный, но уж больно низкоуровневый.
          Я пока обхожусь программированием на уровне юзерспейса. Может быть
          когда-нибудь, для чего нибудь ...
            Ну что .... это Победа! :lol:

            user posted image

            Все работает, все ловится. Файлы тестового проекта прилагаю (Qt 5.14.1, С++17, версия компилятора 19.16.27035 от студии 2017)

            UsbTestWatcher.pro
            Скрытый текст
            ExpandedWrap disabled
              QT       += core gui
               
              greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
               
              CONFIG += c++17
               
              # The following define makes your compiler emit warnings if you use
              # any Qt feature that has been marked deprecated (the exact warnings
              # depend on your compiler). Please consult the documentation of the
              # deprecated API in order to know how to port your code away from it.
              DEFINES += QT_DEPRECATED_WARNINGS
               
              # You can also make your code fail to compile if it uses deprecated APIs.
              # In order to do so, uncomment the following line.
              # You can also select to disable deprecated APIs only up to a certain version of Qt.
              DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0
               
              SOURCES += \
                  main.cpp \
                  dialog.cpp
               
              HEADERS += \
                  dialog.h
               
              LIBS += -lUser32
               
              # Fuck windows-1251 !!!
              QMAKE_EXTRA_TARGETS += before_build makefilehook
              makefilehook.target = $(MAKEFILE)
              makefilehook.depends = .beforebuild
              PRE_TARGETDEPS += .beforebuild
              before_build.target = .beforebuild
              before_build.depends = FORCE
              before_build.commands = chcp 1251

            main.cpp
            Скрытый текст
            ExpandedWrap disabled
              #include <QApplication>
              #include "dialog.h"
               
              int main(int argc, char *argv[]) {
                  QApplication a(argc, argv);
                  Dialog w;
                  w.show();
                  return a.exec();
              }

            dialog.h
            Скрытый текст
            ExpandedWrap disabled
              #ifndef DIALOG_H
              #define DIALOG_H
               
              #include <QtWidgets>
              #include <dbt.h>
               
              class Dialog : public QDialog {
                      Q_OBJECT
                      QLabel *L;
                      bool nativeEvent(const QByteArray& eventType, void *message, long *result);
                  public:
                      Dialog(QWidget *parent = nullptr);
                      ~Dialog() {}
                  public slots:
                      void SlotRegister();
                      void SlotArrived(QString iName);
                      void SlotRemoved(QString iName);
                  signals:
                      void SigUsbArrived(QString iName);
                      void SigUsbRemoved(QString iName);
              };
               
              #endif // DIALOG_H

            dialog.cpp
            Скрытый текст
            ExpandedWrap disabled
              #include "dialog.h"
               
              #define DBT_DEVNODES_CHANGED             0x0007  // devnode changed
              #define DBT_DEVINSTSTARTED               0x8008  // device installed and started
              #define DBT_DEVINSTREMOVED               0x8009  // device removed from system
               
              //
              // Можно расширить своими классами USB-устройств, тех которые нужно отслеживать
              //
               
              static const GUID GUID_DEVINTERFACE_LIST[] = {
                  // USB Raw Device Interface Class GUID
                  {   0xa5dcbf10, 0x6530, 0x11d2, {0x90, 0x1f, 0x00, 0xc0, 0x4f, 0xb9, 0x51, 0xed}},
                  // Disk Device Interface Class GUID
                  {   0x53f56307, 0xb6bf, 0x11d0, {0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b}},
                  // Human Interface Device Class GUID
                  {   0x4d1e55b2, 0xf16f, 0x11Cf, {0x88, 0xcb, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30}},
                  // FTDI_D2XX_Device Class GUID
                  {   0x219d0508, 0x57a8, 0x4ff5, {0x97, 0xa1, 0xbd, 0x86, 0x58, 0x7c, 0x6c, 0x7e}},
                  // FTDI_VCP_Device Class GUID
                  {   0x86e0d1e0, 0x8089, 0x11d0, {0x9c, 0xe4, 0x08, 0x00, 0x3e, 0x30, 0x1f, 0x73}}
              };
               
              Dialog::Dialog(QWidget *parent)
                  : QDialog(parent) {
                  L = new QLabel("Можно читать список usb-устройств при старте ...");
                  QVBoxLayout *H = new QVBoxLayout();
                  H->addWidget(L);
                  setLayout(H);
                  setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
                  connect(this, &Dialog::SigUsbArrived, this, &Dialog::SlotArrived);
                  connect(this, &Dialog::SigUsbRemoved, this, &Dialog::SlotRemoved);
                  QTimer::singleShot(100, this, &Dialog::SlotRegister);
              }
               
              void Dialog::SlotRegister() {
                  DEV_BROADCAST_DEVICEINTERFACE NotificationFilter;
                  ZeroMemory(&NotificationFilter, sizeof(NotificationFilter));
                  NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
                  NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
                  HWND hw = (HWND) this->effectiveWinId();
                  for (size_t i = 0; i < sizeof(GUID_DEVINTERFACE_LIST) / sizeof(GUID); i++) {
                      NotificationFilter.dbcc_classguid = GUID_DEVINTERFACE_LIST[i];
                      HDEVNOTIFY hDevNotify = RegisterDeviceNotification(hw, &NotificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE);
                      if (!hDevNotify) {
                          QMessageBox::critical(this, "Ошибка", "Ошибка регистрации уведомителя!");
                          emit close();
                      }
                  }
              }
               
              void Dialog::SlotArrived(QString iName) {
                  L->setText(QString("Подключено: %1").arg(iName));
                  L->repaint();
                  qDebug() << QString("Подключено: %1").arg(iName);
              }
               
              void Dialog::SlotRemoved(QString iName) {
                  L->setText(QString("Отключено: %1").arg(iName));
                  L->repaint();
                  qDebug() << QString("Отключено: %1").arg(iName);
              }
               
              bool Dialog::nativeEvent([[maybe_unused]] const QByteArray& eventType, void *message,
                                                               [[maybe_unused]] long *result) {
                  MSG *msg = static_cast< MSG * >(message);
                  int msgType = msg->message;
                  if (msgType == WM_DEVICECHANGE) {
                      if (msg->wParam == DBT_DEVICEARRIVAL || msg->wParam == DBT_DEVICEREMOVECOMPLETE) {
                          PDEV_BROADCAST_HDR lpdb = (PDEV_BROADCAST_HDR)msg->lParam;
                          PDEV_BROADCAST_DEVICEINTERFACE lpdbv = (PDEV_BROADCAST_DEVICEINTERFACE) lpdb;
                          if (lpdb->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) {
                              QString path = QString::fromWCharArray(lpdbv->dbcc_name);
                              if (msg->wParam == DBT_DEVICEARRIVAL)
                                  emit SigUsbArrived(path);
                              else
                                  emit SigUsbRemoved(path);
                              return true;
                          }
                      }
                  }
                  return false;
              }

            Пример отладочного вывода при использовании моего картридера:
            ExpandedWrap disabled
              "Подключено: \\\\?\\USB#VID_0801&PID_0001#6&5f46f56&0&6#{a5dcbf10-6530-11d2-901f-00c04fb951ed}"
              "Подключено: \\\\?\\HID#VID_0801&PID_0001#7&8918959&1&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}"
              "Отключено: \\\\?\\HID#VID_0801&PID_0001#7&8918959&1&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}"
              "Отключено: \\\\?\\USB#VID_0801&PID_0001#6&5f46f56&0&6#{a5dcbf10-6530-11d2-901f-00c04fb951ed}"

            Устройство регается дважды - как обычное USB-устройство, и как HID USB. Это можно фильтровать - правильно настроить в коде регистрацию в RegisterDeviceNotification.

            Всем спасибо за участие :)
            0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
            0 пользователей:


            Рейтинг@Mail.ru
            [ Script execution time: 0,0354 ]   [ 18 queries used ]   [ Generated: 19.03.24, 05:54 GMT ]