crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )

История благодарностей участнику ahalaj ::: Спасибо сказали: 13 раз(а)
Дата поста: В теме: За сообщение: Спасибо сказали:
18.9.2015, 0:29 QtCreator почему строка текста, начинающаяся с двух вопросов, подсвечивается серым
Всё просто. Потому что строки, начинающиеся с "??", трактуются как триграфы.

Цитата(Steklova Olga @ 17.9.2015, 13:36) *
Нет, компилятор выдает ошибку.

Значит или данная комбинация не является валидным триграфом (после "??" должен идти конкретный символ, какой конкретно -- в википедию), или у компилятора выключена поддержка триграфов, или компилятор вообще триграфы не умеет.

Цитата(Steklova Olga @ 17.9.2015, 13:36) *
Но QtCreator-то подсвечивает такие строки зачем-то.

А QtCreator получается в курсе насчёт триграфов и именно строки с ними и подсвечивает.

Цитата(ViGOur @ 16.9.2015, 18:00) *
Начнем с того, имеет ли такая строка смысл с позиции С\С++? :)

Имеет. Во всяком случае пока что имеет. Правда уже не во всех компиляторах. А в будущем вообще собираются убрать поддержку этого безобразия, пришедшего из лохматых годов.
Steklova Olga, ViGOur,
4.9.2015, 20:09 Сборки под разные системы
Цитата(ViGOur @ 4.9.2015, 17:14) *
Появилась задача, делать сборки для Centos, Debian, Mandriva и ...
Я знаю, что есть такая штука как кросс компиляция, но пока вот не знаю, можно откомпилить будучи под Debian, для других ОС семейства линукс, не дебиано подобных?
И как бы при этом еще централизованно делать пакеты? (deb, rpm и ...)

А то как-то муторно будет с виртуалками... :(

Попробуй глянуть на OpenBuildService. Я сам его не пробовал, но судя по докциям на сайте этот самый OpenBuildService как раз для этого и предназначен.

PS: выше Sokoloff говорил про OpenSUSE, это тоже из OpenSUSE, но не сам OpenSUSE, а отдельно build system.
ViGOur,
11.2.2015, 8:10 Вопрос по книге Жасмин Бланшет, Марк Саммерфилд - Qt 4. Программирование GUI на C++(2 издание)
Цитата(zanac @ 10.2.2015, 9:31) *
В самом начале в книге показывают пример с возрастом и есть такие строчки:«здесь мы задаем расстояние между виджетами 6 пикселей». Но в примере ничего такого нет! Или расстояние задано неявно?

IMHO копипейст перевода аналогичной книги Жасмин Бланшет про Qt 3.0, там действительно было такое:

5 int main(int argc, char *argv[])
6 {
7     QApplication app(argc, argv);

8    QHBox *hbox = new QHBox(0);
9    hbox->setCaption("Enter Your Age");
10    hbox->setMargin(6);
11    hbox->setSpacing(6);

12    QSpinBox *spinBox = new QSpinBox(hbox);
13    QSlider *slider = new QSlider(Qt::Horizontal, hbox);
14    spinBox->setRange(0, 130);
15    slider->setRange(0, 130);

    [...]

23    return app.exec();
24}

Lines 8 to 11 set up the QHBox. We call setCaption() to set the text displayed in the window’s title bar. Then we put some space (6 pixels) around and in between the child widgets. Lines 12 and 13 create a QSpinBox and a QSlider with the QHBox as the parent.


Вот "hbox->setMargin(6);" и "hbox->setSpacing(6);" как раз оно и есть. А в оригинальной книге Жасмин Бланшет про Qt 4.0 такого уже нет:

5 int main(int argc, char *argv[])
6 {
7     QApplication app(argc, argv);

8     QWidget *window = new QWidget;
9     window->setWindowTitle("Enter Your Age");

10     QSpinBox *spinBox = new QSpinBox;
11     QSlider *slider = new QSlider(Qt::Horizontal);
12     spinBox->setRange(0, 130);
13     slider->setRange(0, 130);

    [...]
24     return app.exec();
25  }
                                          
Lines 8 and 9 set up the  QWidget that will serve as the application's main window. We call  setWindowTitle() to set the text displayed in the window's title bar. Lines 10 and 11 create a QSpinBox , and lines 12 and 13 set their valid ranges.


Переводчику видать лениво было переводить занова, он использовал уже готовый перевод про Qt 3 и просто попытался поменять некоторые места, которые в книге про Qt 4 изменились, да не все заметил.

Я всегда говорил, говорю и буду говорить: читайте книжки в оригинале (благо английский это не китайский и не японский, на уровне чтения его выучить -- ну неделя, максимум две), в переводной документации ещё не такие ляпы бывают.
zanac,
27.10.2014, 11:25 QtSerialPort
А зачем снова менять и собирать если нужна стандартная? Стандартная пусть всегда на месте остаётся, а модифицированная единовременно собирается для конкретного проекта и поставляется вместе с ним. Я так и сделал из расчёта чтобы как раз стандартную и не менять.
borune,
27.10.2014, 8:51 QtSerialPort
Цитата(borune @ 27.10.2014, 8:20) *
Цитата(ahalaj @ 26.10.2014, 21:48) *
Да, скопировать. Но не в папку .lib, а в ту папку, где оказывается твой целевой exe'шник.
хм, а почему туда..ты ж сам описал порядок поиска требуемых dll..он в итоге должен дойти до каталога с компилятором, где все dll лежат, и оттуда его взять

Ну можно и в ту папку, где лежат все стандартные .dll от Qt. Просто тогда придётся новую dll записывать поверх стандартно-родной и соответственно стандартно-родной уже в оригинале не останется. А так когда кладёшь её в папку с exe'шником и волки получаются сыты (exe использует новую dll) и овцы целы (оригинальную dll из поставки Qt никто не трогает).
borune,
26.10.2014, 20:48 QtSerialPort
Да, скопировать. Но не в папку .lib, а в ту папку, где оказывается твой целевой exe'шник.
borune,
26.10.2014, 19:24 QtSerialPort
Сначала модифицируем как надо C:\Qt\5.3\Src\qtserialport\src\serialport\qserialportinfo_win.cpp

После делаем так:

cd C:\Qt\5.3\Src\qtserialport\src
qmake
nmake


Вновь собранные debug и release .dll теперь находятся тут:

cd ..\lib
dir *.dll

Volume in drive C has no label.
Volume Serial Number is 94E6-4722

Directory of C:\Qt\5.3\Src\qtserialport\lib

26.10.2014  19:08            56,832 Qt5SerialPort.dll
26.10.2014  19:08           122,880 Qt5SerialPortd.dll
               2 File(s)        179,712 bytes
               0 Dir(s)  300,561,043,456 bytes free


А .lib пофигу, они подходят и к родным, и к модифицированным. Затем я просто брал отсюда Qt5SerialPort.dll и клал в тот каталог, где лежал откомпилированный пример enumerator.exe Ведь .dll без явного указания пути ищутся сначала в текущем каталоге, если там нет, то в каталоге откуда запущен .exe, если и там нет, то во всех каталогах переменной %PATH%. Т.к. мой лежал там же, где сам enumerator.exe, то родная .dll из C:\Qt\5.3\msvc2010_opengl\bin\Qt5SerialPort.dll не бралась, модифицированная находилась раньше и именно она использавалась при запуске enumerator.exe. Вот как-то так.
borune,
25.10.2014, 10:30 QtSerialPort
Цитата(borune @ 24.10.2014, 8:28) *
ahalaj, спасибо большое, но мне хотелось бы все же через QSerialPort сделать. В такие дебри лезть неохота, если честно, но за помощь спасибо тебе.

А kuzulis прав!

Цитата(kuzulis @ 21.10.2014, 19:57) *
Ах, если имелось ввиду найти все у-ва которые когда-либо были подключены и определены, а теперь являются "скрытыми" hidden (т.к. их например, выдернули из USB) и кстати, их можно отобразить в диспетчере устройств.

То это не проблема, достаточно удалить (закомментировать) DIGCF_PRESENT в qserialportinfo_win.cpp и пересобрать.

Посмотрел я на код qserialportinfo_win.cpp, там практически то же самое, что у меня. Закоментировал DIGCF_PRESENT

[...]

static inline const QList<GuidFlagsPair>& guidFlagsPairs()
{
    static const QList<GuidFlagsPair> guidFlagsPairList = QList<GuidFlagsPair>()
        // Standard Setup Ports Class GUID
        << qMakePair(QUuid(0x4D36E978, 0xE325, 0x11CE, 0xBF, 0xC1, 0x08, 0x00, 0x2B, 0xE1, 0x03, 0x18), 0 /*DWORD(DIGCF_PRESENT)*/)
        // Standard Setup Modems Class GUID
        << qMakePair(QUuid(0x4D36E96D, 0xE325, 0x11CE, 0xBF, 0xC1, 0x08, 0x00, 0x2B, 0xE1, 0x03, 0x18), 0 /*DWORD(DIGCF_PRESENT)*/)
        // Standard Serial Port Device Interface Class GUID
        << qMakePair(QUuid(0x86E0D1E0, 0x8089, 0x11D0, 0x9C, 0xE4, 0x08, 0x00, 0x3E, 0x30, 0x1F, 0x73), DWORD(/*DIGCF_PRESENT |*/DIGCF_DEVICEINTERFACE))
        // Standard Modem Device Interface Class GUID
        << qMakePair(QUuid(0x2C7089AA, 0x2E0E, 0x11D1, 0xB1, 0x14, 0x00, 0xC0, 0x4F, 0xC2, 0xAA, 0xE4), DWORD(/*DIGCF_PRESENT |*/DIGCF_DEVICEINTERFACE));
    return guidFlagsPairList;
}

[...]


пересобрал C:\Qt\5.3\Src\qtserialport\examples\serialport\enumerator и QSerialPortInfo::availablePorts() стал показывать не только реально подключенные устройства, но и те, которые зарегистрированы в системе, но не подключены в данный момент. Проверял на телефоне Nokia, единственное различие в выводе примера enumerator это то, что он не показывает IMEI телефона когда он не подключен, а так всё то же самое:

оригинальный код когда телефон не подключен:
оригинальный код когда телефон подключен:
модифицированный код с закоментированным DIGCF_PRESENT когда телефон не подключен:
модифицированный код с закоментированным DIGCF_PRESENT когда телефон подключен:

Так что или модифицировать qserialportinfo_win.cpp, или делать то же самое, но вручную, без QSerialPortInfo, других способов похоже нет.
borune,
23.10.2014, 22:27 QtSerialPort
Цитата(ahalaj @ 23.10.2014, 22:13) *
Единственное что лично я могу предложить, это мой маленький кусочек из исходника 10-тилетней давности. Но он на Delphi и естественно никаким QSerialPort там и не пахнет.

[...]

Нашёл ещё кое-что. Докопался я тогда до этого дела путём наглого и бессовестного реверсинга trial копии LogoManager For Nokia phones. В те времена это был единственный софт помимо родной для телефонов Nokia программы Nokia PC Suite который умел находить виртуальные порты DKU-2 как для подключенных, так и для неподключенных физически телефонов. Весь путь реверсинга я сохранял в C со своими коментариями по ходу чтобы после было легче понять что там к чему. Потом уже переделал на Delphi потому что в продакшн надо было на Delphi отдавать. Так что вот то, из чего после был сделан предыдущий паскальный исходник. Опять не Qt, но думаю что C всё же поближе должно быть чем Pascal. Тут и коментариев чуть больше, и SetupApi.pas не требуется, всё в обычном стандартном Microsoft Windows SDK имеется. Ищутся исключительно виртуальные порты DKU-2 для мобильных телефонов Nokia как и реально подключенные, так и hidden, которые в диспетчере устройств не показаны, но в системе тем не менее есть.

Стиль кода, определение ошибок и сами ошибки -- это всё не моё, данная функция отреверсена из LogoManager For Nokia phones практически "один в один", в оригинале не было только никаких вызовов logData(const char *format, ...), а всё остальное оттуда © 2004 год.

Раскрывающийся текст
#include <ctype.h>
#include <io.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#pragma pack(push,1)

#include <windows.h>
#include <setupapi.h>

#pragma pack(pop)

// тут мы будем хранить информацию о найденных устройствах
//
struct CDevice
{
    CDevice *pNext;
    bool     fNeedOpen;
    HANDLE   h;
    TCHAR    path[ANYSIZE_ARRAY];
};

// ПОРЯДОК ЭТИХ КЛАССОВ В МАССИВЕ ВАЖЕН!!!

static GUID aDevGUID[] = {
    {
        0x4D36E978,
        0xE325,
        0x11CE,
        {0xBF, 0xC1, 0x08, 0x00, 0x2B, 0xE1, 0x03, 0x18}
    },
    {
        0x4F919104,
        0x4ADF,
        0x11D5,
        {0x88, 0x2D, 0x00, 0xB0, 0xD0, 0x2F, 0xE3, 0x81}
    },
    {
        0x4F919102,
        0x4ADF,
        0x11D5,
        {0x88, 0x2D, 0x00, 0xB0, 0xD0, 0x2F, 0xE3, 0x81}
    },
    {
        0x4F919100,
        0x4ADF,
        0x11D5,
        {0x88, 0x2D, 0x00, 0xB0, 0xD0, 0x2F, 0xE3, 0x81}
    },
    {
        0x86E0D1E0,
        0x8089,
        0x11D0,
        {0x9C, 0xE4, 0x08, 0x00, 0x3E, 0x30, 0x1F, 0x73}
    }
};

static char szLogFName[] = "dku-2.log";
static bool fNeedLog     = false;

static void logData(const char *format, ...)
{
    if (fNeedLog)
    {
        FILE *pFLog = fopen(szLogFName, "a+t");

        if (pFLog)
        {
            time_t timer = time(NULL);
            struct tm *stm = localtime(&timer);
            char *p = asctime(stm);
            p[strlen(p) - 1] = '\0';

            fprintf(pFLog, "%s: ", p);

            va_list args;
            va_start(args, format);
            vfprintf(pFLog, format, args);
            va_end(args);

            fclose(pFLog);
        }
    }
}

static void logStart()
{
    if (fNeedLog)
    {
        if (!access(szLogFName, 6))
        {
            FILE *pFLog = fopen(szLogFName, "a+t");

            if (pFLog)
            {
                fprintf(pFLog, "\n");
                fclose(pFLog);
            }
        }
    }
}

static void GUID2str(const GUID& guid, char *str)
{
    sprintf(str, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
            guid.Data1, guid.Data2, guid.Data3,
            guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3],
            guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]);
}

static void scanForDevices(CDevice **paDevices)
{
    CDevice  *aDevices = NULL;
    bool      fError = false;
    HDEVINFO  hDevInfo;
    char      szGUID[39];

    // начинаем просмотр всех возможных классов устройств в поисках
    // подходящего дивайса
    //
    for (int iDevClass = 0;
         iDevClass < sizeof(aDevGUID) / sizeof (aDevGUID[0]);
         iDevClass++)
    {
        GUID2str(aDevGUID[iDevClass], szGUID);

        hDevInfo = SetupDiGetClassDevs(&aDevGUID[iDevClass],
                                       0,
                                       0,
                                       DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);

        // попробуем посмотреть есть ли у нас какие-нибудь дивайсы
        // в этом классе
        //
        if (hDevInfo == INVALID_HANDLE_VALUE)
        {
            // нифига, литовский национальный праздник ``Обломайтис''
            // вываливаемся сразу же, все четыре класса должны быть
            //
            logData("hmm... couldn't find device class %s\n", szGUID);
            fError = true;
            break;
        }
        else
        {
            // дивайсы в этом классе есть
            //
            logData("found device class %s\n", szGUID);

            SP_DEVINFO_DATA DevInfoData;

            DevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);

            // пробежимся по всем дивайсам данного класса начиная с нулевого,
            // пока функция SetupDiEnumDeviceInfo не вернёт FALSE
            //
            bool fFound = false;

            for (int iDevice = 0;
                 SetupDiEnumDeviceInfo(hDevInfo, iDevice, &DevInfoData);
                 iDevice++)
            {
                fFound = true;
                // дивайс с таким номером найден
                //
                logData("  device number: #%d\n", iDevice);

                // смотрим какие интерфейсы поддерживает данный дивайс
                //
                SP_DEVICE_INTERFACE_DATA DeviceInterfaceData;

                DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);

                if (!SetupDiEnumDeviceInterfaces(hDevInfo,
                                                 NULL,
                                                 &aDevGUID[iDevClass],
                                                 iDevice,
                                                 &DeviceInterfaceData))
                {
                    // какая-то ошибка в потрохах Weendoze, такого быть
                    // не должно по хорошему
                    //
                    logData("failed to get SP_DEVICE_INTERFACE_DATA for "
                            "device #%d: %08X\n", iDevice, GetLastError());
                }
                else
                {
                    // узнаем про этот интерфейс поподробнее
                    //

                    // тут мы получим необходимый размер буфера
                    //
                    ULONG cbSize;

                    // а это сам буфер
                    //
                    PSP_DEVICE_INTERFACE_DETAIL_DATA pDevIFCDetailData = NULL;

                    // во время первого вызова SetupDiGetDeviceInterfaceDetail
                    // передаём NULL в качестве указателя на буфер,
                    // 0 в качестве размера буфера и в результате Windows
                    // должен вернуть нам требуемый размер буфера в cbSize
                    //
                    SetupDiGetDeviceInterfaceDetail(hDevInfo,
                                                    &DeviceInterfaceData,
                                                    NULL,
                                                    0,
                                                    &cbSize,
                                                    NULL);

                    // ДОЛЖНА БЫТЬ ОШИБКА ПРО МАЛЫЙ РАЗМЕР БУФЕРА !!!
                    //
                    int ec = GetLastError();

                    if (ec != ERROR_INSUFFICIENT_BUFFER)
                    {
                        // не повезло, ошибка какая-то другая, вываливаемся
                        //
                        logData("error getting interface detail: %08X, "
                                "skip going any further\n", ec);
                    }
                    else
                    {
                        // выделяем памяти ровно столько, сколько надо
                        //
                        pDevIFCDetailData =
                            (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(cbSize);

                        if (!pDevIFCDetailData)
                        {
                            logData("insufficient memory, "
                                    "skip going any further\n");
                        }
                        else
                        {
/*
* ТУТ НАЧИНАЮТСЯ ПОЛНЫЕ НЕПОНЯТКИ. НЕСМОТРЯ НА ТО, ЧТО ВСЕ ПАРАМЕТРЫ
* ТЕПЕРЬ БУДУТ УСТАНОВЛЕНЫ КОРРЕКТНО, LMMPC ОЖИДАЕТ, ЧТО ФУНКЦИЯ ВЕРНЁТ
* ОШИБКУ (SIC!). ЕСЛИ ЖЕ ФУНКЦИЯ ВЫПОЛНИЛАСЬ БЕЗ ОШИБКИ, ТО LMMPC
* ЗАЧЕМ-ТО ПОЛУЧАЕТ INSTANCE ID ДАННОГО ИНТЕРФЕЙСА (ЧТО МЫ И ДЕЛАЕМ
* НИЖЕ ПО ТЕКСТУ) И ТОЖЕ ОЖИДАЕТ, ЧТО ФУНКЦИЯ ВЕРНЁТ ОШИБКУ! СУДЯ
* ПО ТЕКСТУ LMMPC, ТАКОЕ ПОВЕДЕНИЕ ВПОЛНЕ ВОЗМОЖНО, НО НЕ ДЛЯ ВСЕХ
* КЛАССОВ УСТРОЙСТВ (ВСЕГО ТАМ ЧЕТЫРЕ ВОЗМОЖНЫХ КЛАССА).
*
* БЫТЬ МОЖЕТ ВСЯ ЭТА БАДЯГА ТУТ НАДЕЛАНА ДЛЯ ТОГО, ЧТОБЫ ИЗБЕЖАТЬ
* ПОВТОРНОГО ОТКРЫТИЯ УЖЕ ОТКРЫТОГО ДИВАЙСА, ФИГ ЗНАЕТ
*/

/*
  * BIZARRE BEGIN
  */
                            // подготавливаем структуру
                            // SP_DEVICE_INTERFACE_DETAIL_DATA
                            //
                            pDevIFCDetailData->cbSize =
                                sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);

                            // и опять вызываем SetupDiGetDeviceInterfaceDetail,
                            // но уже с установленными значениями параметров
                            //
/*
* В LMMPC ДАЛЕЕ ВЫПОЛНЕНИЕ ИДЁТ НА ОТКРЫТИЕ ДИВАЙСА ЕСЛИ ЭТА ФУНКЦИЯ ВЕРНУЛА
* ОШИБКУ И КЛАСС ДИВАЙСА РАВЕН ОПРЕДЕЛЁННОМУ ЗНАЧЕНИЮ. ЖУТЬ КАКАЯ-ТО, ЯВНО
* КАКИЕ-ТО МАНЬЯКИ ТАКОЕ ПРИДУМЫВАЛИ
*/
                            if (!SetupDiGetDeviceInterfaceDetail(
                                hDevInfo,
                                &DeviceInterfaceData,
                                pDevIFCDetailData,
                                cbSize,
                                NULL,
                                NULL))
                            {
/*
* НА ВСЯКИЙ СЛУЧАЙ ЗАПИСЫВАЕМ КОД ОШИБКИ В ЖУРНАЛ, МОЖЕТ БЫТЬ
* ЧУТЬ ПОНЯТНЕЕ СТАНЕТ (ПРОВЕРИТЬ ВОТ НЕ НА ЧЕМ)
*/
                                logData("bizarre error code 0: %08X\n",
                                        GetLastError());
                            }
                            else
                            {
/*
* ОШИБКИ НЕ БЫЛО, ЗНАЧИТ СМОТРИМ НА DEVICE INSTANCE ID
*/
                                logData("    device path: %s\n",
                                        pDevIFCDetailData->DevicePath);

                                // используем такой же способ определения
                                // требуемого размера буфера, как и выше
                                // для SetupDiGetDeviceInterfaceDetail
                                //
                                SetupDiGetDeviceInstanceId(hDevInfo,
                                                           &DevInfoData,
                                                           NULL,
                                                           0,
                                                           &cbSize);

                                ec = GetLastError();

                                if (ec != ERROR_SUCCESS)
                                {
                                    if (ec != ERROR_INSUFFICIENT_BUFFER)
                                    {
/*
* И ЭТУ СТРАННУЮ ОШИБКУ ТОЖЕ ПИШЕМ В ЖУРНАЛ
*/
                                        logData("bizarre error code 1: %08X\n",
                                                GetLastError());
                                    }
                                    else
                                    {
/*
* ПОПАДАЕМ СЮДА ТОЛЬКО В ТОМ СЛУЧАЕ, ЕСЛИ БЫЛА ОШИБКА ПРО МАЛЫЙ
* РАЗМЕР БУФЕРА. В ПРОТИВНОМ СЛУЧАЕ ПРОСТО ИДЁМ НА ОТКРЫТИЕ ДИВАЙСА
*/
                                        // выделяем памяти ровно столько,
                                        //  сколько надо
                                        //
                                        char *pInstanceID =
                                            (char*)malloc(cbSize);

                                        if (pInstanceID)
                                        {
                                            if (!SetupDiGetDeviceInstanceId(
                                                hDevInfo,
                                                &DevInfoData,
                                                pInstanceID,
                                                cbSize,
                                                NULL))
                                            {
/*
* ЖУРНАЛИРУЕМ ЕЩЁ ОДНУ СТРАННУЮ ОШИБКУ
*/
                                                logData(
                                                    "bizarre error code 2: "
                                                    "%08X\n",
                                                    GetLastError());
                                            }
                                            else
                                            {
                                                // на всякий случай записываем
                                                // device instance id в лог
                                                //
                                                logData("    instance ID: %s\n",
                                                        pInstanceID);
                                            }
                                            // следим за heap
                                            //
                                            free(pInstanceID);
                                        }
                                    }
                                }
                            }
/*
  * BIZARRE END
  */
                            // смотрим к какому классу относится устройство
                            // (СМ. НАВЕРХУ ПРО ТО, ЧТО ПОРЯДОК КЛАССОВ В
                            // МАССИВЕ [i.e. ИХ НУМЕРАЦИЯ] ВАЖЕН!!!)
                            //
                            // устройства классов
                            // {4F919104-4ADF-11D5-882D-00B0D02FE381}
                            // {4F919100-4ADF-11D5-882D-00B0D02FE381},
                            // индексируемые через 0 и 2 соответственно,
                            // мы просто игнорируем (то есть мы проверяем
                            // эти классы только на присутствие, больше они
                            // нас никак не интересуют)
                            //
                            // устройство класса
                            // {4F919102-4ADF-11D5-882D-00B0D02FE381},
                            // индексируемое через 1, надлежит открыть
                            //
                            // устройство класса
                            // {86E0D1E0-8089-11D0-9CE4-08003E301F73},
                            // индексируемое через 3 и имеющее четвёртым
                            // символом пути букву `u' (USB?) тоже
                            // попадает под нашу юрисдикцию, однако
                            // открытия не требует (было открыто ранее?)
                            //
                            if ((iDevClass == 1) ||
                                    (iDevClass == 3 &&
                                    pDevIFCDetailData->DevicePath[4] == 'u'))
                            {
                                CDevice *pDevice =
                                    (CDevice*)malloc(sizeof (CDevice) +
                                    strlen(pDevIFCDetailData->DevicePath));

                                if(!pDevice)
                                {
                                    logData("insufficient memory to keep "
                                            "device info\n");
                                }
                                else
                                {
                                    fFound = true;

                                    if (aDevices)
                                        aDevices->pNext = pDevice;
                                    else
                                        aDevices = pDevice;

                                    pDevice->pNext = NULL;
                                    pDevice->fNeedOpen = (iDevClass == 1)
                                                                ? true
                                                                : false;
                                    pDevice->h = INVALID_HANDLE_VALUE;
                                    strcpy(pDevice->path,
                                        pDevIFCDetailData->DevicePath);
                                }
                            }

                            // следим за heap
                            //
                            free(pDevIFCDetailData);
                        }
                    }
                 }
             }
             if (!fFound)
             {
                 // в этом классе дивайсов нет
                 //
                 logData("  no any device(s)\n");
             }
             // больше нам этот класс не нужен
             //
             SetupDiDestroyDeviceInfoList(hDevInfo);
         }
    }

    // если выходим по ошибке, то освобождаем всю занятую память
    //
    if (fError)
    {
        for (CDevice *p = aDevices; p;)
        {
            CDevice *pTmp = p->pNext;
            free(p);
            p = pTmp;
        }
        aDevices = NULL;
    }

    *paDevices = aDevices;
}

static bool openDevice(CDevice&  device,
                       DWORD     IOCode,
                       BYTE     *pOutBuf,
                       DWORD    *cOutBytes)
{
    bool rc = false;

    logData("  about to open %s\n", device.path);

    if ((device.h = CreateFile(device.path,
                              0xC0000000,
                              0,
                              NULL,
                              OPEN_EXISTING,
                              FILE_FLAG_OVERLAPPED | FILE_ATTRIBUTE_NORMAL,
                              NULL)) == INVALID_HANDLE_VALUE)
    {
        logData("  error: %08X\n", GetLastError());
    }
    else
    {
        logData("  HANDLE: %08X\n", device.h);
        logData("  about to create event semaphore\n");

        HANDLE hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);

        logData("  HANDLE: %08X\n", hEvent);

        if (hEvent)
        {
            DWORD sysErr = ERROR_WAIT_NO_CHILDREN;
            OVERLAPPED ovrlpd;

            memset(&ovrlpd, 0, sizeof (OVERLAPPED));
            logData("  about to send %08X IOCTL code\n", IOCode);
            if (DeviceIoControl(device.h,
                                 IOCode,
                                 NULL,
                                 0,
                                 pOutBuf,
                                 *cOutBytes,
                                 cOutBytes,
                                 &ovrlpd));
            {
                logData("  success\n");
                sysErr = ERROR_SUCCESS;
            }
            if (sysErr)
            {
                sysErr = GetLastError();
                logData("  failed: %08X\n", sysErr);
                if (sysErr == ERROR_IO_PENDING)
                    sysErr = WaitForSingleObject(hEvent, 5000);
                    logData("  after waiting for 5000 ms: %08X\n", sysErr);
            }
            CloseHandle(hEvent);

            if (sysErr == ERROR_SUCCESS)
                rc = true;
        }
        CloseHandle(device.h);
        device.h = INVALID_HANDLE_VALUE;
    }
    return rc;
}

static void processDevice(CDevice& device)
{
    if (device.fNeedOpen)
    {
        DWORD cBytes;
        BYTE  buf[512];

        cBytes = sizeof(buf);
        memset(buf, 0, sizeof(buf));

        openDevice(device, 0x22203C, buf, &cBytes);
        openDevice(device, 0x222034, buf, &cBytes);
    }
}

static void dumpData(const char *buf, size_t len)
{
    char *dst = (char*)malloc(80);

    if (dst)
    {
        for (size_t i = 0; i < len;)
        {
            sprintf(dst, "%04X  ", i);

            size_t j;
            char   tmp[9];

            for (j = 0; j < 16; j++)
            {
                if ((i + j) == len)
                {
                    break;
                }
                sprintf(tmp, "%02X ", (unsigned char)buf[i + j]);
                strcat(dst, tmp);
            }

            for (; j < 16; j++)
                strcat(dst, "   ");

            strcat(dst, " ");

            for (j = 0; j < 16; j++)
            {
                if ((i + j) == len)
                {
                    break;
                }
                sprintf(tmp, "%c", isascii(buf[i + j]) ? buf[i + j] : '.');
                strcat(dst, tmp);
            }
            i += 16;

            logData("%s\n", dst);
        }
        free(dst);
    }
}

static void sendstuff(CDevice& device)
{
    DWORD  rc;
    HANDLE hDev;

    logData("  about to send some bytes\n");

    if ((hDev = CreateFile(device.path,
                           0xC0000000,
                           0,
                           NULL,
                           OPEN_EXISTING,
                           FILE_FLAG_OVERLAPPED | FILE_ATTRIBUTE_NORMAL,
                           NULL)) == INVALID_HANDLE_VALUE)
    {
        logData("  error opening: %08X\n", GetLastError());
    }
    else
    {
        HANDLE hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);

        if (hEvent)
        {
            OVERLAPPED ovrlpd;
            DWORD      nBytes;
            char       buf[512];

            memset(&ovrlpd, 0, sizeof (OVERLAPPED));
            ovrlpd.hEvent = hEvent;

            buf[0] = 0x1B;
            buf[1] = 0x00;
            buf[2] = 0x0C;
            buf[3] = 0xD0;
            buf[4] = 0x00;
            buf[5] = 0x01;
            buf[6] = 0x04;

            logData("  about to send data:\n");
            dumpData(buf, 7);

            rc = WriteFile(hDev,
                           buf,
                           7,
                           &nBytes,
                           &ovrlpd);

            if (rc)
            {
                if (GetLastError() == ERROR_IO_PENDING)
                {
                    printf ("waiting for 5 seconds to complete (write)\n");
                    logData("  waiting for 5 seconds to complete (write)\n");

                    rc = WaitForSingleObject(hEvent, 5000);
                }
            }
            if (rc)
            {
                logData("  error sending data: %08X\n", GetLastError());
            }
            else
            {
                logData("  about to read response:\n");
                SetEvent(hEvent);

                rc = ReadFile(hDev,
                              buf,
                              sizeof(buf),
                              &nBytes,
                              &ovrlpd);
                if (rc)
                {
                    if (GetLastError() == ERROR_IO_PENDING)
                    {
                        printf ("waiting for 5 seconds to complete (read)\n");
                        logData("  waiting for 5 seconds to complete (read)\n");

                        rc = WaitForSingleObject(hEvent, 5000);
                    }
                }
                if (rc)
                {
                    logData("  error getting response: %08X\n", GetLastError());
                }
                else
                {
                    dumpData(buf, nBytes);
                }
            }
            CloseHandle(hEvent);
        }
        CloseHandle(hDev);
    }
}

int main()
{
    CDevice *aDevices;

    char *pch = getenv("LOG_DKU-2");
    if (pch && stricmp(pch, "yes"))
        fNeedLog = true;

    logStart();
    logData("Start logging\n");

    scanForDevices(&aDevices);

    if (aDevices)
    {
        for (CDevice *p = aDevices; p; p = p->pNext)
        {
            logData("  BEFORE DeviceIoControl\n");
            sendstuff(*p);

            processDevice(*p);

            logData("  AFTER DeviceIoControl\n");
            sendstuff(*p);
        }

        for (CDevice *p = aDevices; p;)
        {
            if (p->h != INVALID_HANDLE_VALUE)
                CloseHandle(p->h);

            CDevice *pTmp = p->pNext;
            free(p);
            p = pTmp;
        }
    }

    logData("End logging\n");

    return 0;
}
borune,
23.10.2014, 21:13 QtSerialPort
Цитата(borune @ 23.10.2014, 20:37) *
Господа, вопрос актуален, ибо тов. kuzulis мало того, что не понимает русского языка, так еще и дает неверные советы. Как получить список всех когда-либо установленных ком портов средствами QSerialPort?

Единственное что лично я могу предложить, это мой маленький кусочек из исходника 10-тилетней давности. Но он на Delphi и естественно никаким QSerialPort там и не пахнет. Мне в то время надо было ловить подключение мобильных телефонов Nokia через интерфейс DKU-2. При каждом подключении создавался виртуальный ком-порт, при первом подключении система его у себя прописывала и запоминала, при отключении этот виртуальный ком-порт из диспетчера задач пропадал, но система созданную запись о нём не забывала и в системе он всё равно присутствовал, правда был hidden пока телефон физически не подключишь. И вот мне надо было ловить и видимые в диспетчере устройства, подключенные реально, и невидимые, но про которые система знала.

Использовался SetupApi.pas из JEDI Visual Component Library (в 2004-м году этот юнит назывался SetupApi.pas, сейчас он же называется по-моему JvSetupApi.pas, я с тех пор в эту библиотеку не лазил, как 10 лет назад сделал так и забыл, принцип программиста "работает -- не трожь!" :lol: )

Вот моя функция на Delphi, которая этот SetupApi.pas использует.

Раскрывающийся текст
unit Dku2;

interface

uses Windows;

const
   aDevGUID:array[0..3] of TGUID = (
            '{4F919104-4ADF-11D5-882D-00B0D02FE381}',
            '{4F919102-4ADF-11D5-882D-00B0D02FE381}',
            '{4F919100-4ADF-11D5-882D-00B0D02FE381}',
            '{86E0D1E0-8089-11D0-9CE4-08003E301F73}'
   );

type
  HDEVINFO = Pointer;

function GetDKU2List:string;

implementation

uses
  SetupApi, SysUtils;

function GetDKU2List:string;
var iDevClass,iDevice:integer;
     DevInfo:HDEVINFO;
     DevInfoData:TSpDevInfoData;
     DeviceInterfaceData:TSPDeviceInterfaceData;
     cbSize:DWORD;
     DevIFCDetailData:PSPDeviceInterfaceDetailData;
     InstanceID:PChar;
begin

  // начинаем просмотр всех возможных классов устройств в поисках
  // подходящего дивайса
  For iDevClass:=Low(aDevGUID) to High(aDevGUID) do begin
    DevInfo:=SetupDiGetClassDevs(@(aDevGUID[iDevClass]), nil, 0, DIGCF_PRESENT or DIGCF_DEVICEINTERFACE);
    If DevInfo=Pointer(INVALID_HANDLE_VALUE) then Exit
    else begin
      // дивайсы в этом классе есть
      DevInfoData.cbSize:=sizeof(SP_DEVINFO_DATA);
      // пробежимся по всем дивайсам данного класса начиная с нулевого,
      // пока функция SetupDiEnumDeviceInfo не вернёт FALSE
      iDevice:=0;
      While SetupDiEnumDeviceInfo(DevInfo,iDevice,DevInfoData) do begin
        // дивайс с таким номером найден
        // смотрим какие интерфейсы поддерживает данный дивайс
        DeviceInterfaceData.cbSize:=sizeof(SP_DEVICE_INTERFACE_DATA);
        If not SetupDiEnumDeviceInterfaces(DevInfo, nil, aDevGUID[iDevClass], iDevice, DeviceInterfaceData) then begin
          //*****ошибка
        end
        else begin
          SetupDiGetDeviceInterfaceDetail(DevInfo, @DeviceInterfaceData, nil, 0, cbSize, nil);
          GetLastError();
          DevIFCDetailData:=AllocMem(cbSize);
          DevIFCDetailData.cbSize:=sizeof(TSPDeviceInterfaceDetailData);

          If SetupDiGetDeviceInterfaceDetail(DevInfo, @DeviceInterfaceData, DevIFCDetailData, cbSize, cbSize, nil) then begin
            SetupDiGetDeviceInstanceId(DevInfo, @DevInfoData, nil, 0, @cbSize);
            GetLastError();
            InstanceID:=AllocMem(cbSize);
            SetupDiGetDeviceInstanceId(DevInfo, @DevInfoData, InstanceID, cbSize, nil);
            Dispose(InstanceID);

            If (iDevClass=1) or ((iDevClass=333) (*and (DevIFCDetailData.DevicePath[4]=Ord('u'))*)) then begin
              Result:=Result+';'+StrPas(DevIFCDetailData.DevicePath);
            end;
          end;
          Dispose(DevIFCDetailData);
        end;

        Inc(iDevice);
      end;
    end;
  end;
end;

end.


Расчитано именно на DKU-2 и именно для мобильных телефонов Nokia, но по аналогии думаю можно разобраться что там к чему. Больше помочь ничем не могу, извини.
borune,
8.9.2014, 18:25 как определить тип записывающего устройства?
Если портируемо, то IMHO только QSystemStorageInfo из Qt Mobility API. Ну а если только для винды, то через GetDriveType. Лично я других способов навскидку и не знаю.
Анна,
10.7.2014, 10:43 ошибка 0xc000001d при запуске
Абсолютно точно это из-за SSE2.

отсюда
Цитата
As far as I’ve tested, if Qt library is compiled with SSE2 and machine does not have the SSE2 support, your Qt application will crash with “The application failed to initialize properly “0xc000001d” error message.
И говорят что надо самому пересобрать Qt с опцией "-sse2", потому что в готовых бинарниках с сайта qt-project эта опция включена и они не будут работать на всяких Атлонах и прочих недопроцессорах.

Цитата(ahalaj @ 10.7.2014, 11:40) *
И говорят что надо самому пересобрать Qt с опцией "-sse2", потому что в готовых бинарниках с сайта qt-project эта опция включена и они не будут работать на всяких Атлонах и прочих недопроцессорах.

То есть "-no-sse2" конечно, бинарники на сайте собраны как раз с "-sse2", поэтому и не работают на старых процах.
abc,

RSS Текстовая версия Сейчас: 21.11.2019, 13:55