comm.c

来自「一个类似windows」· C语言 代码 · 共 1,430 行 · 第 1/5 页

C
1,430
字号
	result = BuildCommDCBW(wide_string, &dcb);

	if(GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
		return;

	/* check results */
	check_result("BuildCommDCBW", ptest, initial_value, result);
	check_dcb("BuildCommDCBW", ptest, initial_value, &dcb, pexpected_dcb);
}

static void test_BuildCommDCBAndTimeoutsW(TEST *ptest, int initial_value, DCB *pexpected_dcb, COMMTIMEOUTS *pexpected_timeouts)
{
	BOOL result;
	DCB dcb;
	COMMTIMEOUTS timeouts;
	WCHAR wide_string[sizeof(ptest->string)];

	MultiByteToWideChar(CP_ACP, 0, ptest->string, -1, wide_string, sizeof(wide_string) / sizeof(WCHAR));

	/* set initial conditions */
	memset(&dcb, initial_value, sizeof(DCB));
	memset(&timeouts, initial_value, sizeof(COMMTIMEOUTS));
	SetLastError(0xdeadbeef);

	result = BuildCommDCBAndTimeoutsW(wide_string, &dcb, &timeouts);

	if(GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
		return;

	/* check results */
	check_result("BuildCommDCBAndTimeoutsA", ptest, initial_value, result);
	check_dcb("BuildCommDCBAndTimeoutsA", ptest, initial_value, &dcb, pexpected_dcb);
	check_timeouts("BuildCommDCBAndTimeoutsA", ptest, initial_value, &timeouts, pexpected_timeouts);
}

static void test_BuildCommDCB(void)
{
	char port_name[] = "COMx";
	char port = 0;
	unsigned int i;
	char *ptr;

	/* Some of these tests require a valid COM port.  This loop will try to find
	   a valid port. */
	for(port_name[3] = '1'; port_name[3] <= '9'; port_name[3]++)
	{
		COMMCONFIG commconfig;
		DWORD size = sizeof(COMMCONFIG);

		if(GetDefaultCommConfig(port_name, &commconfig, &size))
		{
			port = port_name[3];
			break;
		}
	}

	if(!port)
		trace("Could not find a valid COM port.  Some tests will be skipped.\n");

	for(i = 0; i < TEST_COUNT; i++)
	{
		/* Check if this test case needs a valid COM port. */
		ptr = strstr(test[i].string, "COMx");

		/* If required, substitute valid port number into device control string. */
		if(ptr)
		{
			if(port)
				ptr[3] = port;
			else
				continue;
		}

		test_BuildCommDCBA(&test[i], 0x00, &test[i].dcb1);
		test_BuildCommDCBA(&test[i], 0xff, &test[i].dcb2);
		test_BuildCommDCBAndTimeoutsA(&test[i], 0x00, &test[i].dcb1, &test[i].timeouts1);
		test_BuildCommDCBAndTimeoutsA(&test[i], 0xff, &test[i].dcb2, &test[i].timeouts2);

		test_BuildCommDCBW(&test[i], 0x00, &test[i].dcb1);
		test_BuildCommDCBW(&test[i], 0xff, &test[i].dcb2);
		test_BuildCommDCBAndTimeoutsW(&test[i], 0x00, &test[i].dcb1, &test[i].timeouts1);
		test_BuildCommDCBAndTimeoutsW(&test[i], 0xff, &test[i].dcb2, &test[i].timeouts2);
	}
}

static HANDLE test_OpenComm(BOOL doOverlap)
{
    HANDLE hcom = INVALID_HANDLE_VALUE;
    char port_name[] = "COMx";
    static BOOL shown = FALSE;

    /* Try to find a port */
    for(port_name[3] = '1'; port_name[3] <= '9'; port_name[3]++)
    {
	hcom = CreateFile( port_name, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
			   (doOverlap)?FILE_FLAG_OVERLAPPED:0, NULL );
	if (hcom != INVALID_HANDLE_VALUE)
	    break;
    }
    if(!shown)
    {
	if (hcom == INVALID_HANDLE_VALUE)
	    trace("Could not find a valid COM port.  Skipping test_ReadTimeOut\n");
	else
	    trace("Found Com port %s. Connected devices may disturbe results\n", port_name);
	/*shown = TRUE; */
    }
    return hcom;
}

static void test_GetModemStatus(HANDLE hcom)
{
    DWORD ModemStat;

    ok(GetCommModemStatus(hcom, &ModemStat), "GetCommModemStatus failed\n");
    trace("GetCommModemStatus returned 0x%08lx->%s%s%s%s\n", ModemStat,
	  (ModemStat &MS_RLSD_ON)?"MS_RLSD_ON ":"",
	  (ModemStat &MS_RING_ON)?"MS_RING_ON ":"",
	  (ModemStat &MS_DSR_ON)?"MS_DSR_ON ":"",
	  (ModemStat &MS_CTS_ON)?"MS_CTS_ON ":"");
}

/* When we don't write anything, Read should time out even on a loopbacked port */
static void test_ReadTimeOut(HANDLE hcom)
{
    DCB dcb;
    COMMTIMEOUTS timeouts;
    char rbuf[32];
    DWORD before, after, read, timediff, LastError;
    BOOL res;

    ok(GetCommState(hcom, &dcb), "GetCommState failed\n");
    dcb.BaudRate = FASTBAUD;
    dcb.ByteSize = 8;
    dcb.Parity = NOPARITY;
    dcb.StopBits = ONESTOPBIT;
    ok(SetCommState(hcom, &dcb), "SetCommState failed\n");

    ZeroMemory( &timeouts, sizeof(timeouts));
    timeouts.ReadTotalTimeoutConstant = TIMEOUT;
    ok(SetCommTimeouts(hcom, &timeouts),"SetCommTimeouts failed\n");

    before = GetTickCount();
    SetLastError(0xdeadbeef);
    res = ReadFile(hcom, rbuf, sizeof(rbuf), &read, NULL);
    LastError = GetLastError();
    after = GetTickCount();
    todo_wine ok( res == TRUE, "A timed-out read should return TRUE\n");
    todo_wine ok( LastError == 0xdeadbeef, "err=%ld\n", LastError);
    timediff = after - before;
    ok( timediff > TIMEOUT>>2 && timediff < TIMEOUT *2,
	"Unexpected TimeOut %ld, expected %d\n", timediff, TIMEOUT);
}

static void test_waittxempty(HANDLE hcom)
{
    DCB dcb;
    COMMTIMEOUTS timeouts;
    char tbuf[]="Some Characters\n";
    DWORD before, after, written, timediff, evtmask = 0;
    BOOL res_write, res;
    DWORD baud = SLOWBAUD;

    /* set a low baud rate to have ample time*/
    ok(GetCommState(hcom, &dcb), "GetCommState failed\n");
    dcb.BaudRate = baud;
    dcb.ByteSize = 8;
    dcb.Parity = NOPARITY;
    dcb.StopBits = ONESTOPBIT;
    ok(SetCommState(hcom, &dcb), "SetCommState failed\n");

    ZeroMemory( &timeouts, sizeof(timeouts));
    timeouts.ReadTotalTimeoutConstant = TIMEOUT;
    ok(SetCommTimeouts(hcom, &timeouts),"SetCommTimeouts failed\n");

    ok(SetupComm(hcom,1024,1024),"SetUpComm failed\n");
    ok(SetCommMask(hcom, EV_TXEMPTY), "SetCommMask failed\n");

    before = GetTickCount();
    res_write=WriteFile(hcom, tbuf, sizeof(tbuf), &written, NULL);
    after = GetTickCount();
    ok(res_write == TRUE, "WriteFile failed\n");
    ok(written == sizeof(tbuf),
       "WriteFile: Unexpected write_size %ld , expected %d\n", written, sizeof(tbuf));

    trace("WriteFile succeeded, took %ld ms to write %d Bytes at %ld Baud\n",
	  after - before, sizeof(tbuf), baud);

    before = GetTickCount();
    res = WaitCommEvent(hcom, &evtmask, NULL);
    after = GetTickCount();

    todo_wine ok(res == TRUE, "WaitCommEvent failed\n");
    todo_wine ok(evtmask == EV_TXEMPTY,
		 "WaitCommEvent: Unexpected EvtMask 0x%08lx, expected 0x%08x\n",
		 evtmask, EV_TXEMPTY);

    timediff = after - before;

    trace("WaitCommEvent for EV_TXEMPTY took %ld ms\n", timediff);
    /* 050604: This shows a difference between XP (tested with mingw compiled crosstest):
       XP returns Writefile only after everything went out of the Serial port,
       while wine returns immedate.
       Thus on XP, WaintCommEvent after setting the CommMask for EV_TXEMPTY
       nearly return immediate,
       while on wine the most time is spent here
    */

}

/* A new open handle should not return error or have bytes in the Queues */
static void test_ClearCommErrors(HANDLE hcom)
{
    DWORD   errors;
    COMSTAT lpStat;

    ok(ClearCommError(hcom, &errors, &lpStat), "ClearCommError failed\n");
    ok(lpStat.cbInQue == 0, "Unexpected %ld Bytes in InQueue\n", lpStat.cbInQue);
    ok(lpStat.cbOutQue == 0, "Unexpected %ld Bytes in OutQueue\n", lpStat.cbOutQue);
    ok(errors == 0, "ClearCommErrors: Unexpected error 0x%08lx\n", errors);
}

/**/
static void test_LoopbackRead(HANDLE hcom)
{
    DCB dcb;
    COMMTIMEOUTS timeouts;
    char rbuf[32];
    DWORD before, after, diff, read, written, evtmask=0;
    BOOL res;
    char tbuf[]="Some Characters\n";

    ok(GetCommState(hcom, &dcb), "GetCommState failed\n");
    dcb.BaudRate = FASTBAUD;
    dcb.ByteSize = 8;
    dcb.Parity = NOPARITY;
    dcb.StopBits = ONESTOPBIT;
    ok(SetCommState(hcom, &dcb), "SetCommState failed\n");

    ZeroMemory( &timeouts, sizeof(timeouts));
    timeouts.ReadTotalTimeoutConstant = TIMEOUT;
    ok(SetCommTimeouts(hcom, &timeouts),"SetCommTimeouts failed\n");

    ok(SetCommMask(hcom, EV_TXEMPTY), "SetCommMask failed\n");

    ok(WriteFile(hcom,tbuf,sizeof(tbuf),&written, NULL), "WriteFile failed\n");
    ok(written == sizeof(tbuf),"WriteFile %ld bytes written, expected %d\n",
       written, sizeof(tbuf));

    /* make sure all bytes are written, so Readfile will succeed in one call*/
    todo_wine ok(WaitCommEvent(hcom, &evtmask, NULL), "WaitCommEvent failed\n");
    todo_wine ok(evtmask == EV_TXEMPTY,
		 "WaitCommEvent: Unexpected EvtMask 0x%08lx, expected 0x%08x\n",
		 evtmask, EV_TXEMPTY);

    read=0;
    todo_wine ok(ReadFile(hcom, rbuf, sizeof(rbuf), &read, NULL), "Readfile failed\n");
    todo_wine ok(read == sizeof(tbuf),"ReadFile read %ld bytes, expected %d\n", read, sizeof(tbuf));

    /* Now do the same withe a slow Baud rate.
       On XP, nothing should change, as WriteFile only returns
       after all Bytes have gone to the physical line
    */

    ok(GetCommState(hcom, &dcb), "GetCommState failed\n");
    dcb.BaudRate = 9600;
    dcb.ByteSize = 8;
    dcb.Parity = NOPARITY;
    dcb.StopBits = ONESTOPBIT;
    ok(SetCommState(hcom, &dcb), "SetCommState failed\n");

    ok(SetCommMask(hcom, EV_RXCHAR), "SetCommMask failed\n");
    ok(WriteFile(hcom,tbuf,sizeof(tbuf),&written, NULL), "WriteFile failed\n");
    ok(written == sizeof(tbuf),"WriteFile %ld bytes written, expected %d\n",
       written, sizeof(tbuf));

    todo_wine ok(WaitCommEvent(hcom, &evtmask, NULL), "WaitCommEvent failed\n");
    todo_wine ok(evtmask == EV_RXCHAR, "WaitCommEvent: Unexpected EvtMask 0x%08lx, expected 0x%08x\n",
       evtmask, EV_RXCHAR);

    before = GetTickCount();
    res = ReadFile(hcom, rbuf, sizeof(rbuf), &read, NULL);
    after = GetTickCount();
    todo_wine ok(res, "Readfile failed\n");
    todo_wine ok(read == sizeof(tbuf),"ReadFile read %ld bytes, expected %d\n", read, sizeof(tbuf));
    diff = after - before;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?