Exemplo n.º 1
0
/*------------------------------------------------------------------------------
-- FUNCTION:    PortIOThreadProc
--
-- DATE:        Oct 13, 2010
--
-- REVISIONS:   Nov 05, 2010
--              Modified the function to also listen for a "disconnect" event,
--              and to break in that case. ProcessRead() is now called once a 
--				complete packet is confirmed (as opposed to sending the 
--				contents of the buffer to ProcessRead() as soon as they arrive).
--
--				Nov 29, 2010
--				Renamed function from ReadThreadProc(). The event handling is
--				from the original function, but the response to each event has
--				changed.
--
-- DESIGNER:    Dean Morin
--
-- PROGRAMMER:  Dean Morin, Daniel Wright
--
-- INTERFACE:   DWORD WINAPI PortIOThreadProc(HWND hWnd)
--                      hWnd - the handle to the window
--
-- RETURNS:     0 because threads are required to return a DWORD.
--
-- NOTES:
--              While connected, this thread will loop and wait for characters
--              to arrive at the port, or for a timeout to occur, then call the
--				appropriate function. This function uses overlapped I/O.
------------------------------------------------------------------------------*/
DWORD WINAPI PortIOThreadProc(HWND hWnd) {
    OVERLAPPED  ol		= {0};
    DWORD       dwEvent = 0;
    DWORD       dwError = 0;
    COMSTAT     cs      = {0};
    HANDLE*     hEvents = NULL;
    PSTATEINFO  psi     = NULL;
    PWNDDATA	pwd		= (PWNDDATA) GetWindowLongPtr(hWnd, 0);
    

    if ((ol.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL)) == NULL) {
        DISPLAY_ERROR("Error creating event in read thread");
    }
    hEvents     = (HANDLE*) malloc(sizeof(HANDLE) * PORT_IO_EVENTS);
    hEvents[0]  = CreateEvent(NULL, FALSE, FALSE, TEXT("disconnected"));
    hEvents[1]  = ol.hEvent;
    
    psi = (PSTATEINFO) malloc(sizeof(STATEINFO));
    InitStateInfo(psi);
    DL_STATE = psi->iState;


    while (pwd->bConnected) {
        
        SetCommMask(pwd->hPort, EV_RXCHAR);      
        if (!WaitCommEvent(pwd->hPort, &dwEvent, &ol)) {
            ProcessCommError(pwd->hPort);
        }
        dwEvent = WaitForMultipleObjects(PORT_IO_EVENTS, hEvents, FALSE, 
                                         psi->dwTimeout);
        ClearCommError(pwd->hPort, &dwError, &cs);
 
        if (dwEvent == WAIT_OBJECT_0) {
            // the connection was severed
            break;
        }
        else if (dwEvent == WAIT_OBJECT_0 + 1  &&  cs.cbInQue) {
            // data arrived at the port
            ReadFromPort(hWnd, psi, ol, cs.cbInQue);
        }
        else if (dwEvent == WAIT_TIMEOUT) {
            // a timeout occured
            ProcessTimeout(hWnd, psi);
        }
        else if (dwEvent == WAIT_FAILED) {
            DISPLAY_ERROR("Invalid event occured in the Port I/O thread");
        }
        ResetEvent(ol.hEvent);
    }

    if (!PurgeComm(pwd->hPort, PURGE_RXCLEAR)) {
        DISPLAY_ERROR("Error purging read buffer");
    }
    CloseHandle(ol.hEvent);
    CloseHandle(hEvents[0]);
    free(hEvents);
    return 0;
}
Exemplo n.º 2
0
status_t
LinkReceiver::GetNextMessage(int32 &code, bigtime_t timeout)
{
	fReadError = B_OK;

	int32 remaining = fDataSize - (fRecvStart + fReplySize);
	STRACE(("info: LinkReceiver GetNextReply() reports %ld bytes remaining in buffer.\n", remaining));

	// find the position of the next message header in the buffer
	message_header *header;
	if (remaining <= 0) {
		status_t err = ReadFromPort(timeout);
		if (err < B_OK)
			return err;
		remaining = fDataSize;
		header = (message_header *)fRecvBuffer;
	} else {
		fRecvStart += fReplySize;	// start of the next message
		fRecvPosition = fRecvStart;
		header = (message_header *)(fRecvBuffer + fRecvStart);
	}

	// check we have a well-formed message
	if (remaining < (int32)sizeof(message_header)) {
		// we don't have enough data for a complete header
		STRACE(("error info: LinkReceiver remaining %ld bytes is less than header size.\n", remaining));
		ResetBuffer();
		return B_ERROR;
	}

	fReplySize = header->size;
	if (fReplySize > remaining || fReplySize < (int32)sizeof(message_header)) {
		STRACE(("error info: LinkReceiver message size of %ld bytes smaller than header size.\n", fReplySize));
		ResetBuffer();
		return B_ERROR;
	}

	code = header->code;
	fRecvPosition += sizeof(message_header);

	STRACE(("info: LinkReceiver got header %ld [%ld %ld %ld] from port %ld.\n",
		header->code, fReplySize, header->code, header->flags, fReceivePort));

	return B_OK;
}