Есть некое устройство и программа, которая общается с ним. Исходников и документации нет.
Общается по COM-порту - 3 провода (GND, RX, TX).
Хочется написать свою альтернативную программку. Сниффинг обмена вроде бы прояснил ситуацию, протокол вроде бы понятен, но с общением есть проблемы
При работе через терминальные проги железяка или молчит в ответ на запросы, или отвечает один раз и больше не реагирует. =((
Вот пример лога общения родной программы (использовал Eltima Serial Port Monitor 4, но пробовал и другие):
- Код: Выделить всё • Развернуть
[12/02/2010 17:19:21] 9245 IRP_MJ_CREATE - Opens a COM port (COM1)
[12/02/2010 17:19:21] 9247 IOCTL_SERIAL_SET_QUEUE_SIZE
InSize - 1024
OutSize - 300
[12/02/2010 17:19:21] 9249 IOCTL_SERIAL_GET_BAUD_RATE
BaudRate - 9600
[12/02/2010 17:19:21] 9251 IOCTL_SERIAL_GET_LINE_CONTROL
StopBits - 0
Parity - 0
WordLength - 8
[12/02/2010 17:19:21] 9253 IOCTL_SERIAL_GET_CHARS
EofChar - 0
ErrorChar - 0
BreakChar - 0
EventChar - 0
XonChar - 17
XoffChar - 19
[12/02/2010 17:19:21] 9255 IOCTL_SERIAL_GET_HANDFLOW
ControlHandShake - 0x1 (SERIAL_DTR_CONTROL)
FlowReplace - 0x40 (SERIAL_RTS_CONTROL)
XonLimit - 2048
XoffLimit - 512
Зачем-то еще раз GET_BAUDRATE, GET_LINE_CONTROL, GET_CHARS, GET_HANDFLOW
[12/02/2010 17:19:21] 9265 IOCTL_SERIAL_SET_BAUD_RATE
BaudRate - 9600
[12/02/2010 17:19:21] 9267 IOCTL_SERIAL_SET_RTS
[12/02/2010 17:19:21] 9269 IOCTL_SERIAL_SET_DTR
[12/02/2010 17:19:21] 9271 IOCTL_SERIAL_SET_LINE_CONTROL
StopBits - 0
Parity - 0
WordLength - 8
[12/02/2010 17:19:21] 9273 IOCTL_SERIAL_SET_CHARS
EofChar - 0
ErrorChar - 0
BreakChar - 0
EventChar - 0
XonChar - 17
XoffChar - 19
[12/02/2010 17:19:21] 9275 IOCTL_SERIAL_SET_HANDFLOW
ControlHandShake - 0x1 (SERIAL_DTR_CONTROL)
FlowReplace - 0x40 (SERIAL_RTS_CONTROL)
XonLimit - 2048
XoffLimit - 512
Несколько десятков вот таких команд:
[12/02/2010 17:19:21] 9277 IOCTL_SERIAL_GET_COMMSTATUS
Errors - 0
HoldReasons - 0
AmountInInQueue - 0
AmountInOutQueue - 0
EofReceived - 0
WaitForImmediate - 0
Запрос программы железке:
[12/02/2010 17:19:23] 9347 IOCTL_SERIAL_SET_BREAK_ON - Sets the line control break signal active
[12/02/2010 17:19:23] 9349 IOCTL_SERIAL_SET_BREAK_OFF - Request sets the line control break signal inactive
[12/02/2010 17:19:23] 9351 IRP_MJ_WRITE
00 ff ff 01 f0 a6 10 47 .??.?│.G
Вот тут непонятно, почему Errors = 1 - глюк программы-сниффера?
[12/02/2010 17:19:23] 9353 IOCTL_SERIAL_GET_COMMSTATUS
Errors - 1
HoldReasons - 0
AmountInInQueue - 0
AmountInOutQueue - 0
EofReceived - 0
WaitForImmediate - 0
[12/02/2010 17:19:23] 9355 IOCTL_SERIAL_GET_COMMSTATUS
Errors - 0
HoldReasons - 0
AmountInInQueue - 25
AmountInOutQueue - 0
EofReceived - 0
WaitForImmediate - 0
Ну и сам ответ железки:
[12/02/2010 17:19:23] 9357 IRP_MJ_READ
00 00 00 00 01 f0 a6 10 29 99 04 50 00 00 00 00 .....?│.)T.P....
00 00 00 00 00 00 00 00 a3 99 04 50 00 00 00 00 ........?T.P....
Дальше пара IOCTL_SERIAL_GET_COMMSTATUS
IOCTL_SERIAL_SET_BREAK_ON
IOCTL_SERIAL_SET_BREAK_OFF
IRP_MJ_WRITE 00 ff ff 01 03 00 04 06 - запрос железке
IOCTL_SERIAL_GET_COMMSTATUS
IRP_MJ_READ - ответ железки
ну и т.д.
В winapi я не силен, попробовал накропать небольшую программенку, на основе каких-то примеров.
- Код: Выделить всё • Развернуть
#include <windows.h>
#include <stdio.h>
HANDLE hCom;
char *pcCommPort = "COM1";
void mem_read (char *buffer, WORD addr, unsigned char count)
{
unsigned char command_mem_request [8] = {
0, 0xFF, 0xFF, 1, 0xF0, 0xA6, 0x10, 0x47 };
unsigned char buffer2 [30];
// Зачем это - не знаю.
// В логе фирменной программы была установка/снятие BREAK
SetCommBreak (hCom);
ClearCommBreak (hCom);
// Запрос железке
WriteFile (hCom, @command_mem_request, 8, &dwBytes, NULL);
if (dwBytes != 8) printf ("Error!!!\n");
// Хотим ответ
// По факту ничего не получаем
while (1)
{
ReadFile (hCom, &buffer2, 0x1, &dwBytes, NULL);
printf ("%u bytes read!\n", dwBytes);
}
}
int main(int argc, char *argv[])
{
unsigned char buffer, buffer_prev = 0xF0;
COMMTIMEOUTS CommTimeouts;
DCB dcb;
hCom = CreateFile( pcCommPort,
GENERIC_READ | GENERIC_WRITE,
0, // must be opened with exclusive-access
NULL, // no security attributes
OPEN_EXISTING, // must use OPEN_EXISTING
0, // not overlapped I/O
NULL // hTemplate must be NULL for comm devices
);
if (hCom == INVALID_HANDLE_VALUE)
{
printf ("CreateFile failed with error %d.\n", GetLastError());
return (1);
}
if (!SetupComm (hCom, 1024, 300); )
{
printf ("SetupComm with error %d.\n", GetLastError());
return (1);
}
if (!GetCommState (hCom, &dcb))
{
printf ("GetCommState failed with error %d.\n", GetLastError());
return (1);
}
dcb.BaudRate = CBR_9600;
dcb.ByteSize = 8;
dcb.Parity = NOPARITY;
dcb.StopBits = ONESTOPBIT;
if (!SetCommState(hCom, &dcb))
{
printf ("SetCommState failed with error %d.\n", GetLastError());
return (1);
}
if (hCom != INVALID_HANDLE_VALUE && hCom != NULL)
printf ("COM1 cofigured!\n");
mem_read (NULL, 0xA6F0, 0x10);
return (0);
}
Лог сниффера работы моей программки:
- Код: Выделить всё • Развернуть
IRP_MJ_CREATE
IOCTL_SERIAL_SET_QUEUE_SIZE
InSize - 1024
OutSize - 300
IOCTL_SERIAL_GET_BAUD_RATE
BaudRate - 9600
IOCTL_SERIAL_GET_LINE_CONTROL
StopBits - 0
Parity - 0
WordLength - 8
IOCTL_SERIAL_GET_CHARS
EofChar - 0
ErrorChar - 0
BreakChar - 0
EventChar - 0
XonChar - 17
XoffChar - 19
IOCTL_SERIAL_GET_HANDFLOW
ControlHandShake - 0x1 (SERIAL_DTR_CONTROL)
FlowReplace - 0x40 (SERIAL_RTS_CONTROL)
XonLimit - 2048
XoffLimit - 512
Зачем-то еще раз GET_BAUDRATE, GET_LINE_CONTROL, GET_CHARS, GET_HANDFLOW
IOCTL_SERIAL_SET_BAUD_RATE
BaudRate - 9600
IOCTL_SERIAL_SET_RTS
IOCTL_SERIAL_SET_DTR
IOCTL_SERIAL_SET_LINE_CONTROL
StopBits - 0
Parity - 0
WordLength - 8
IOCTL_SERIAL_SET_CHARS
EofChar - 0
ErrorChar - 0
BreakChar - 0
EventChar - 0
XonChar - 17
XoffChar - 19
IOCTL_SERIAL_SET_HANDFLOW
ControlHandShake - 0x1 (SERIAL_DTR_CONTROL)
FlowReplace - 0x40 (SERIAL_RTS_CONTROL)
XonLimit - 2048
XoffLimit - 512
Даем запрос устройству.
IOCTL_SERIAL_SET_BREAK_ON
IOCTL_SERIAL_SET_BREAK_OFF
IRP_MJ_WRITE 00 ff ff 01 f0 a6 10 47
И вместо ответа вот такая ерунда в цикле:
14101 IRP_MJ_READ - STATUS_TIMEOUT
Есть у кого-нибудь мысли, что я делаю не так?
Какая функция winapi вызывает IOCTL_SERIAL_GET_COMMSTATUS?
P.S. Прошу прощения за большой объем сообщения =)