Перейти к содержанию
    

USB CDC +HAL. Как правильно обрабатывать переподключение?

1 час назад, -=Женек=- сказал:

Заработало!

Все оказалось очень просто

Поздравляю!  :good2:

Вот моя функция сканирования. Это main-функция отдельного потока ОС, в котором и осуществляется периодическое сканирование. Результат она отправляет в GUI-поток.

Спойлер

void __fastcall TMonitorCommThread::Main()
{
  //GUID={4d36e978-e325-11ce-bfc1-08002be10318}
  static GUID cdcGUID = {0x4D36E978, 0xE325, 0x11CE, 0xBF, 0xC1, 0x08,
    0x00, 0x2B, 0xE1, 0x03, 0x18};
  DWORD i, i1, i2, i3, j, n, n1, maxValueNameLen, maxValueLen;
  char *s, *s1, *s2, *s3, **ss;
  HKEY hk;
  LList *p, *p1, *p2;
  HDEVINFO hdi;
  SP_DEVINFO_DATA devinfo;
  RegPropertyHead *pr;

  do {
    if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Hardware\\DeviceMap\\SerialComm",
      0, KEY_READ, &hk) == ERROR_SUCCESS) {
      if (RegQueryInfoKey(hk, NULL, NULL, NULL, NULL, NULL, NULL, &n,
        &maxValueNameLen, &maxValueLen, NULL, NULL) == ERROR_SUCCESS)
        if (maxValueLen && maxValueNameLen && n) {
        p = new LList;
        p1 = new LList;
        s2 = new char[maxValueLen + n +
          (i = max(maxValueLen * 2, maxValueNameLen + 1))];
        s3 = (s1 = s2 + i) + maxValueLen;
        for (i = n1 = 0; i < n; i++) {
          i1 = maxValueLen;
          i2 = maxValueNameLen + 1;
          if (RegEnumValue(hk, i, s2, &i2, NULL, &j, s1, &i1)
            != ERROR_SUCCESS) continue;
          if (!i1 || j != REG_SZ) continue;
          i3 = SplitCommName(strcpy(s2 + maxValueLen, s1));
          for (j = 0; s = (*p)[j]; j++) {
            i2 = SplitCommName(strcpy(s2, s));
            if (!(i1 = strcmp(s2 + maxValueLen, s2))) i1 = i3 - i2;
            if ((int)i1 <= 0) break;
          }
          memmove(s3 + j + 1, s3 + j, n1 - j);
          s3[j] = (i1) ? 1: 0;
          (*p)[j] += s1;
          (*p1)[j] += s1;
          n1++;
        }
        for (i = n1; (int)--i >= 0; ) if (!s3[i]) {
          --(*p)[i];
          n1--;
        }
        delete s2;
        if (n1 && RegQueryInfoKey(hk, NULL, NULL, NULL, NULL, NULL, NULL,
          &i, &i1, &i2, NULL, NULL) == ERROR_SUCCESS)
          if (!(i - n | i1 - maxValueNameLen | i2 - maxValueLen)) {
          p1 = (LList *)InterlockedExchangePointer((void **)&testList, p1);
          SetEvent(evTestCom);
          EnterCriticalSection(&csExcludeList);
          for (j = 0; s = (*excludeList)[j]; j++)
            for (i = 0; s1 = (*p)[i]; i++) if (!strcmp(s, s1)) {
            --(*p)[i];
            n1--;
            break;
          }
          LeaveCriticalSection(&csExcludeList);

          if (n1) {
            ZeroMemory(ss = new char *[n1], n1 * sizeof(*ss));
            hdi = SetupDiGetClassDevs(&cdcGUID, NULL, NULL, DIGCF_PRESENT);
            if (hdi != INVALID_HANDLE_VALUE) {
              for (j = 0; ; j++) {
                devinfo.cbSize = sizeof(devinfo);
                if (!SetupDiEnumDeviceInfo(hdi, j, &devinfo)) break;
                SetupDiGetDeviceInstanceId(hdi, &devinfo, NULL, 0, &i);
                if (pr = GetDeviceRegistryProperty(hdi, &devinfo,
                  SPDRP_FRIENDLYNAME)) {
                  if (((char *)&pr[1])[pr->size - 2] == ')') {
                    ((char *)&pr[1])[pr->size - 2] = i = 0;
                    for (; s1 = (*p)[i]; i++) if (pr->typ == REG_SZ)
                      if ((int)(i1 = pr->size - strlen(s1) - 3) >= 0)
                      if (*(s2 = (char *)&pr[1] + i1) == '(')
                      if (!strcmp(s1, s2 + 1)) {
                      if (ss[i]) {
                        delete ss[i];
                        ss[i] = strdup("Конфликт!");
                      } else {
                        *s2 = 0;
                        ss[i] = strdup((char *)&pr[1]);
                      }
                      break;
                    }
                  }
                  delete pr;
                }
              }
              SetupDiDestroyDeviceInfoList(hdi);
            }
          }

          EnterCriticalSection(&csGet);
          n = ports.n;
          ports.n = n1;
          s = (char *)ports.name;
          ports.name = p;
          s1 = (char *)ports.description;
          ports.description = ss;
          LeaveCriticalSection(&csGet);
          p = (LList *)s;
          if (n) {
            do if (s = ((char **)s1)[--n]) delete s;
            while (n);
            delete s1;
          }

        }
        delete p;
        if (p1) delete p1;
      }
      RegCloseKey(hk);
    }
    SetEvent(evReady);
    if (notifyReady) Synchronize(notifyReady);
  } while (WaitForSingleObject(evBreak, 1500) != WAIT_OBJECT_0);
}

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

У меня начало было примерно такое же, когда я пытался зайти с хвоста - получить список компортов, а потом через них дескриптор.

Но то, что я привел выше, оказалось проще.

Я вот думаю, раз с реестром такая беда, может ему целиком отредактированный inf файл скармливать? Есть такая функция в API?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

51 minutes ago, GenaSPB said:

RegNotifyChangeKeyValue

Не... это называется "гора идет к Магомету". У меня же Магомет сам взбирается на гору до 10 раз в секунду)

Хм... я вот тут подумал... я ведь когда-то делал проект, который превращает часть флеш памяти контроллера в usb флешку. Интересно, а можно ли сделать так, чтобы при подключении устройства оно по usb как-то само передавало бы и устанавливало бы инф файл?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Устройство не может быть ведущим.

Да и не все ПК будут устанавливать что-то непонятное с подключеного USB.

Но можете попробовать. В корне диска обязательно должен быть autorun.inf, ссылающайся на исполняемый файл, или .bat скрипт, который и будет устанавливать что-либо на систему.

Естественно, нужно определять какая именно система на ПК. А некоторые даже этот самый волшебный файл будут игнорировать (автозапуск отключен и запрещён).

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

3 часа назад, -=Женек=- сказал:

Хм... я вот тут подумал... я ведь когда-то делал проект, который превращает часть флеш памяти контроллера в usb флешку. Интересно, а можно ли сделать так, чтобы при подключении устройства оно по usb как-то само передавало бы и устанавливало бы инф файл?

Видимо возможно если в винде разрешён автозапуск с внешних носителей. Останется только прописать туда необходимый exe-шник.

PS: Блин - уже написали, не заметил....

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

On 7/22/2019 at 10:29 AM, Сергей Борщ said:

А черт его знает. Баловался с ним лет 5 назад, в голове отложилось, что там есть получение списка портов. С QSerialPort не работал.

На всякий случай: в Qt5 есть абсолютно рабочие и достаточно удобные QSerialPort и QSerialPortInfo. Список (со всеми необходимыми подробностями) в инфо есть.

Со всякими Qt2/3/4 сталкиваться не приходилось, может, там актуальнее было...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

36 minutes ago, jcxz said:

Видимо возможно если в винде разрешён автозапуск с внешних носителей. Останется только прописать туда необходимый exe-шник.

PS: Блин - уже написали, не заметил....

Не... все таки это плохая идея. Лучше уж программно, софтом со стороны ПК. То есть, запускается софт и если видит устройство с определенными параметрами, но политически некорректным именем, то оно устанавливает идеологически правильный inf.

Скажите вот это https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupcopyoeminfa

спасет отца русской демократии?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

12 минут назад, -=Женек=- сказал:

то оно устанавливает идеологически правильный inf.

Который вы должны будете сначала подписать у микрософта, а они по головке не погладят за использование чужих VID/PID

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

7 minutes ago, Сергей Борщ said:

Который вы должны будете сначала подписать у микрософта, а они по головке не погладят за использование чужих VID/PID

То есть, если я оставлю все что есть в дескрипторе от STM , включая название производителя, но изменю frendly_name, меня посодють?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

44 минуты назад, -=Женек=- сказал:

если я оставлю все что есть в дескрипторе от STM , включая название производителя, но изменю frendly_name

В дескрипторе творите все, что хотите. Система выбирает драйвер по VID/PID. Подпись дравера гарантирует, что это правильный дравер от владельца VID/PID. Вы же пытаетесь подсунуть свой левый драйвер вместо законного - за это может и не посадят, но подпись на такой драйвер вы не получите. И будете объяснять своим заказчикам, какие танцы им надо исполнить, чтобы поставить неподписанный драйвер. Хотите иметь в виндовсе свое имя - придется пройти весь путь: вступить в USB alliance (или как он там называется), купить VID, написать свой драйвер и подписать его в микрософте. Я так думаю.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В описании программы zadig  есть ссылка на сайт где было про автоматическую установку уже имеющихся на машине драйверов для вашего устройства. Я использовал этот метод для установки  libusb для своего dfu устройства. Почитайте может ваш случай решён. А вообще виндовс 10 для компортов ставит сама. Да название не индивидуальное.

Использую vid 0xFFFF

Изменено пользователем GenaSPB

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 hours ago, GenaSPB said:

Это называется WCID

О, устройство может самостоятельно попросить винду поставить libusb ?

Геннадий, спасибо, полезная информация.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Причем, в W10 оно (LIBUSB какое-то из) уже входит в комплект. Т.е. ставится все вообще без звука.
 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...