
татарский Нео
  
Профиль
Группа: Завсегдатай
Сообщений: 1701
Регистрация: 22.3.2006
Где: Альметьевск
Репутация: нет Всего: 57
|
Всем добрый день. Есть необходимость в написании драйвера для работы с com-портом на erlang. OC - windows XP. В интернете нашел я нечто похожее. Я плохо знаю С, но все же малость подхачив найденный мною исходник уткнулся в две последние проблемы на этапе компиляции Код | [Linker error] undefined reference to `SecureZeroMemory' [Linker error] undefined reference to `WinMain@16' ld returned 1 exit status
|
оригинал исходников выглядиит следующим образом gen_serial.c : Код | #include <assert.h> #include <erl_driver.h> #include <stdio.h> #include <memory.h> #define WIN32_LEAN_AND_MEAN #include <windows.h>
#define CODE_OK 0x80 #define CODE_CANT_OPEN 0xA0 #define CODE_CANT_WRITE 0xA1 #define CODE_CANT_READ 0xA2 #define CODE_BADARG 0xFF
typedef struct { ErlDrvPort port; HANDLE hComm; } DriverData;
static HANDLE connect( char* buffer, int bufflen ) { HANDLE hComm; DCB dcb = {0}; COMMTIMEOUTS timeouts; unsigned comm_port; unsigned baud_rate; unsigned data_bits; unsigned parity; unsigned stop_bits; unsigned flow_control; wchar_t comm_port_str[8];
assert( bufflen == 7 );
comm_port = buffer[0]; baud_rate = (buffer[1]<<8) + buffer[2]; data_bits = buffer[3]; parity = buffer[4]; stop_bits = buffer[5]; flow_control = buffer[6];
wsprintf( comm_port_str, L"COM%u", comm_port ); hComm = CreateFile( comm_port_str, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0); if (hComm == INVALID_HANDLE_VALUE) return hComm;
SecureZeroMemory(&dcb, sizeof(DCB)); dcb.DCBlength = sizeof(DCB); if ( !GetCommState(hComm, &dcb) ) { CloseHandle( hComm ); return INVALID_HANDLE_VALUE; } dcb.BaudRate = (baud_rate==0) ? 110 : (unsigned long)baud_rate * 300; dcb.fParity = TRUE; dcb.ByteSize = data_bits; dcb.Parity = parity; dcb.StopBits = ONESTOPBIT; dcb.fOutxCtsFlow = FALSE; dcb.fRtsControl = RTS_CONTROL_DISABLE; dcb.fOutxDsrFlow = FALSE; dcb.fDtrControl = DTR_CONTROL_DISABLE; dcb.fInX = FALSE; dcb.fOutX = FALSE; switch ( flow_control ) { default: case 0: // No flow control // Already in default state break; case 1: // RTS/CTS control dcb.fOutxCtsFlow = TRUE; dcb.fRtsControl = RTS_CONTROL_HANDSHAKE; break; case 2: // DTR/DSR control dcb.fOutxDsrFlow = TRUE; dcb.fDtrControl = DTR_CONTROL_HANDSHAKE; break; case 3: // Xon/Xoff control dcb.fInX = TRUE; dcb.fOutX = TRUE; break; } if ( !SetCommState(hComm, &dcb) ) { CloseHandle( hComm ); return INVALID_HANDLE_VALUE; }
if ( !GetCommTimeouts( hComm, &timeouts ) ) { CloseHandle( hComm ); return INVALID_HANDLE_VALUE; } timeouts.ReadIntervalTimeout = MAXDWORD; timeouts.ReadTotalTimeoutMultiplier = 0; timeouts.ReadTotalTimeoutConstant = 0; timeouts.WriteTotalTimeoutMultiplier = 0; timeouts.WriteTotalTimeoutConstant = 0; if ( !SetCommTimeouts(hComm, &timeouts) ) { CloseHandle( hComm ); return INVALID_HANDLE_VALUE; }
if ( !SetCommMask( hComm, EV_RXCHAR | EV_RXFLAG | EV_TXEMPTY ) ) { CloseHandle( hComm ); return INVALID_HANDLE_VALUE; }
return hComm; }
static ErlDrvData gen_serial_start(ErlDrvPort port, char *buff) { DriverData* data = (DriverData*)driver_alloc( sizeof(DriverData) ); if ( !data ) return ERL_DRV_ERROR_GENERAL;
data->port = port; data->hComm = INVALID_HANDLE_VALUE; return (ErlDrvData)data; }
static void gen_serial_stop(ErlDrvData handle) { DriverData* data = (DriverData*)handle;
assert( handle ); assert( data );
if ( data->hComm != INVALID_HANDLE_VALUE ) CloseHandle( data->hComm ); driver_free( (char*)handle ); }
static void gen_serial_output(ErlDrvData const drv_data, char *buff, int bufflen) { DriverData* const data = (DriverData*)drv_data; DWORD written = 0; BOOL flag; char msg = CODE_OK;
assert( drv_data ); assert( data ); assert( buff ); assert( bufflen > 0 );
flag = WriteFile( data->hComm, buff, bufflen, &written, NULL ); if ( !flag || written != bufflen ) msg = CODE_CANT_WRITE; driver_output( data->port, &msg, 1 ); }
static int gen_serial_control( ErlDrvData drv_data, unsigned int command, char *buf, int len, char **rbuf, int rlen ) { DriverData* const data = (DriverData*)drv_data; DWORD written; BOOL flag;
static char msg_80[] = "\x80"; /* Ok */ static char msg_a0[] = "\xA0"; /* Could not open port */ static char msg_a1[] = "\xA1"; /* Error sending data */ static char msg_a2[] = "\xA2"; /* Error reading data */ static char msg_fe[] = "\xFE"; /* Invalid format for message */ static char msg_ff[] = "\xFF"; /* Unrecognized message */
assert( drv_data ); assert( data ); assert( rbuf ); assert( rlen > 0 );
switch ( command ) { case 1: /* connect */ if ( len != 7 ) { *rbuf[0] = CODE_BADARG; return 1; } else { HANDLE hComm = connect( buf, len ); if ( hComm == INVALID_HANDLE_VALUE ) { *rbuf[0] = CODE_CANT_OPEN; return 1; } else { data->hComm = hComm; *rbuf[0] = CODE_OK; return 1; } } return 0;
case 3: /* recv */ written = 0; *rbuf[0] = CODE_OK; flag = ReadFile( data->hComm, (*rbuf)+1, rlen-1, &written, NULL ); if ( !flag ) { *rbuf[0] = CODE_CANT_READ; return 1; } return written + 1;
case 4: /* recv length */ if ( len != 4 ) { *rbuf[0] = CODE_BADARG; return 1; } written = (((DWORD)buf[0])<<24) + (((DWORD)buf[1])<<16) + (((DWORD)buf[2])<<8) + buf[3]; if ( written > rlen-1 ) written = rlen-1; *rbuf[0] = CODE_OK; flag = ReadFile( data->hComm, (*rbuf)+1, written, &written, NULL ); if ( !flag ) { *rbuf[0] = CODE_CANT_READ; return 1; } return written + 1;
default: /* error */ *rbuf[0] = CODE_BADARG; return 1; return 0; } }
ErlDrvEntry driver_entry = { NULL, /* F_PTR init, N/A */ gen_serial_start, /* L_PTR start, called when port is opened */ gen_serial_stop, /* F_PTR stop, called when port is closed */ gen_serial_output, /* F_PTR output, called when erlang has sent */ NULL, /* F_PTR ready_input, called when input descriptor ready */ NULL, /* F_PTR ready_output, called when output descriptor ready */ "gen_serial", /* char *driver_name, the argument to open_port */ NULL, /* F_PTR finish, called when unloaded */ NULL, /* handle */ gen_serial_control, /* F_PTR control, port_command callback */ NULL, /* F_PTR timeout, reserved */ NULL /* F_PTR outputv, reserved */ };
DRIVER_INIT(gen_serial) /* must match name in driver_entry */ { return &driver_entry; }
|
dllmain.c : Код | #define WIN32_LEAN_AND_MEAN #include <windows.h>
BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: break; } return TRUE; }
|
Если кто-нибудь мне поможет разобраться в чем тут дело - буду очень признателен
--------------------
менеджер по кодеврайтингу
|