Таймаут Write Read

295
04 августа 2017, 01:15
char inBuf[] = { 0x1d, 0x72 }; //0x1d, 0x72, 0x01
int inBufSize = sizeof(inBuf);
DWORD ReturnedLength = 0, eror;
byte sim[256];

hUsb = CreateFile((LPCWSTR)DeviceName, // Создание файла
    GENERIC_READ | GENERIC_WRITE,
    FILE_SHARE_READ,
    NULL,
    OPEN_ALWAYS |FILE_FLAG_OVERLAPPED,
    FILE_ATTRIBUTE_NORMAL | FILE_EXECUTE ,
    NULL);


// очистка мусора порта
PurgeComm(hUsb, PURGE_RXCLEAR);
PurgeComm(hUsb, PURGE_TXCLEAR);
DCB dcb;
dcb.BaudRate = CBR_9600;
dcb.fBinary = TRUE;
dcb.fOutxCtsFlow = FALSE;
dcb.fOutxDsrFlow = FALSE;
dcb.fDtrControl = DTR_CONTROL_HANDSHAKE;
dcb.fDsrSensitivity = FALSE;
dcb.fNull = FALSE;
dcb.fRtsControl = RTS_CONTROL_DISABLE;
dcb.fAbortOnError = FALSE;
dcb.ByteSize = 8;
dcb.Parity = NOPARITY;
dcb.StopBits = ONESTOPBIT;
SetCommState(hUsb, &dcb);

COMMTIMEOUTS CommTimeOuts;
CommTimeOuts.ReadIntervalTimeout = 0;
CommTimeOuts.ReadTotalTimeoutMultiplier = 0;
// значений этих тайм – аутов вполне хватает для уверенного приема 
// даже на скорости 110 бод 
CommTimeOuts.ReadTotalTimeoutConstant = 0;
// используется в данном случае как время ожидания посылки 
CommTimeOuts.WriteTotalTimeoutMultiplier = 0;
CommTimeOuts.WriteTotalTimeoutConstant = 0;
bool yes=SetCommTimeouts(hUsb, &CommTimeOuts);
if (!yes)
    eror = GetLastError(); 
if (hUsb == INVALID_HANDLE_VALUE)
{
    statusLB->Text="Нет соединения";
    return;
}
    Success = WriteFile(hUsb, inBuf, inBufSize, &ReturnedLength, NULL);
    ReturnedLength = 0;
    Success = ReadFile(hUsb, &sim, sizeof(sim), &ReturnedLength, NULL );

getlasteror дает ошибку 1008 ругается на hUsb помогите

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

Answer 1

Для установки таймаутов на операции чтения/записи MS предлагает использование асинхронного механизма. Функции ReadFile/WriteFile вызываются с доп. параметром в виде overlapped-структуры и возвращают управление немедленно, а опрос состояния производится с помощью функции GetOverlappedResult, возвращающей ERROR_IO_INCOMPLETE до тех пор, пока операция чтения/записи не будет завершена.

Пример кода (цикл чтения данных с внешнего устройства):

.h

OVERLAPPED m_ovWrite;   // Struct for writing process
OVERLAPPED m_ovRead;    // Struct for reading process

.cpp

ZeroMemory(&m_ovRead, sizeof(m_ovRead));
ZeroMemory(&m_ovWrite, sizeof(m_ovWrite));
m_ovRead.hEvent = CreateEvent(NULL, false, false, NULL);
m_ovWrite.hEvent = CreateEvent(NULL, false, false, NULL);
...
do
{
    // Здесь может быть ваша проверка на таймаут
    if (ClearCommError(m_portHandle, &errorCode, &portState) == 0)
    {
        // Ошибка очистки 
        return 0;
    }
    DWORD currentReaded = 0;
    if (portState.cbInQue)
    {
        if (ReadFile(m_portHandle, buffer, min (portState.cbInQue, 4096), &currentReaded, &m_ovRead) == 0)
        {
            if (GetLastError() != ERROR_IO_PENDING)
            {
                // Ошибка чтения
                return 0;
            }
            if (GetOverlappedResult(m_portHandle, &m_ovRead, &transfered, true) == 0)
            {
                // Ошибка ожидания
                if (GetLastError() != ERROR_IO_INCOMPLETE)
                    return 0;
            }
        }
    }
    // чтение блока данных успешно, сохраняем результат в буфер
    memcpy(readBuf + readed, buffer, currentReaded);
    readed += currentReaded;
}
while (readed != expectedLength);

Кроме этого есть функция GetOverlappedResultEx позволяющая задать таймаут ожидания одним из параметров (конкретно в моем случае она используется для ожидания ивентов на ком-порту).

Обмен данными с ком-портом можете организовать как синхронный (когда в ответ на каждую команду приходи подтверждение от устройства) либо асинхронный (когда существуют две очереди команд отправка/прием

По ошибке 1008, вы некорректно вызываете CreateFile(...), чему равен hUsb после вызова?

hUsb = CreateFile((LPCWSTR)DeviceName, // Создание файла
    GENERIC_READ | GENERIC_WRITE,
    FILE_SHARE_READ,
    NULL,
    **OPEN_ALWAYS** |**FILE_FLAG_OVERLAPPED**,
    FILE_ATTRIBUTE_NORMAL | **FILE_EXECUTE** ,
    NULL);

OPEN_ALWAYS - позволяет открыть файл в случае физического отсутствия устройства, лучше использовать OPEN_EXISTING;

FILE_FLAG_OVERLAPPED - добавлен не туда

FILE_EXECUTE - это что за флаг, описания не нашел

Попробуйте так:

hUsb = CreateFile((LPCWSTR)DeviceName, // Создание файла
    GENERIC_READ | GENERIC_WRITE,
    FILE_SHARE_READ,
    NULL,
    OPEN_EXISTING,
    FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
    NULL);

описание структуры: https://msdn.microsoft.com/en-us/library/windows/desktop/ms684342(v=vs.85).aspx

описание методов ReadFile/WriteFile (секция Remarks): https://msdn.microsoft.com/en-us/library/windows/desktop/aa365467(v=vs.85).aspx https://msdn.microsoft.com/en-us/library/windows/desktop/aa365747(v=vs.85).aspx

асинхронное ио: https://msdn.microsoft.com/en-us/library/windows/desktop/ms683209(v=vs.85).aspx

READ ALSO
Получение подключенных устройств к Linux на C

Получение подключенных устройств к Linux на C

Задача следующая: необходимо на C/C++ получить список подключенных к ПК на Linux подключенных USB-устройств

277
Продвинутое изучение С++ [дубликат]

Продвинутое изучение С++ [дубликат]

На данный вопрос уже ответили:

272
Постоянно открытое дропменю [требует правки]

Постоянно открытое дропменю [требует правки]

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

247