Modem Connections: 4 Receiving Data

Up: GEOS SDK TechDocs | Up | Prev: 3 Sending Data | Next: 5 Disconnecting

When the modem driver receives notification that data has arrived on the port, it sends a pre-registered message to a specified object. (You specify both the object and the message when you call ModemConnect() .)

In the MTalk example, the driver sends MSG_MTALK_PROCESS_READ_DATA to the process object when data has arrived on the port. The handler for this message is shown in Receiving Data Over A Serial Connection .

To receive data, MTalk does the following:

Code Display 9-3 Receiving Data Over A Serial Connection

@method MTalkProcessClass, MSG_MTALK_PROCESS_READ_DATA
{
	/*
	 * recvDataSize - Amout of data actually read in.
	 * recvDataPtr - Pointer to data to read in.
	 * retVal - Return value of ModemReceive().
	 */
    word		revDataSize;
    char *		recvDataPtr;
    StreamError		retVal;
	/*
	 * Check to see if connection is still open. Because of message queueing
	 * delays, we may have received this data notification after the connection
	 * has been closed.
	 *
	 * ConnectionOpen - global flag that keeps track of whether
	 * the connection is open or closed.
	 */
    if ( ConnectionOpen == FALSE )
    {
	return;
    }
	/*
	 * Lock the input buffer down on the heap, and obtain a pointer to it.
	 * (Note: This buffer is a memory block that was allocated in the
	 * "Connecting" example.)
	 */
    recvDataPtr = MemLock( recvBuffer );
	/*
	 * A NULL pointer means that the memory manager has gone ahead
	 * and discarded the buffer block since the last time it was
	 * unlocked.  So we need to reallocate it here.  Note that the
	 * MemHandle is still in use; it just isn't bound to any block of memory.
	 */
    if ( recvDataPtr == NULL )
    {
	    /*
	     * Reallocate the block, locking it immediately,
	     * so it doesn't get discarded again. If the block cannot
	     * be re-allocated, memory must be low so close the connection.
	     */
	if (( MemReAlloc( recvBuffer, RECV_BUFFER_SIZE, HAF_LOCK ) == NullHandle)
	{
		@send self::MSG_MTALK_PROCESS_CLOSE();
		return;
	}
	    /*
	     * After re-allocating the locked block, dereference its handle
	     * to obtain a pointer to it.
	     */
	recvDataPtr = MemDeref( recvBuffer );
    }
	/*
	 * Read available data up to the size of our buffer then display it.
	 */
	if ( ModemReceive( RECV_BUFFER_SIZE, (byte*)recvDataPtr, &recvDataSize )
							== STREAM_NO_ERROR )
	{
	    @call MTalkOutText::MSG_VIS_TEXT_APPEND_PTR( recvDataPtr, 
						     recvDataSize );
	}
	/*
	 * If the read data filled the entire buffer, there's a good
	 * chance more data is available so send the message through the
	 * process object's queue again.  (We do not want to keep reading
	 * in a loop in case the other side dumped a very large stream
	 * of data; this would keep the process object from handling
	 * other messages in its queue.)
	 */
    if ( RECV_BUFFER_SIZE == recvDataSize ) {
	@send ,forceQueue self::MSG_MTALK_PROCESS_READ_DATA();
    }
	/*
	 * Once all the data has been read, unlock the buffer block.
	 */
    MemUnlock( recvBuffer );
} /* end of MSG_MTALK_PROCESS_READ_DATA */

Like ModemSend() , ModemReceive() calls a VirtualSerial routine, VirtualSerialRead() , to read incoming data. Because no blocking is specified, VirtualSerialRead() reads only data that is currently available in the stream. (If you want the routine to block until there is enough data in the stream to fill the entire buffer, pass STREAM_BLOCK in VirtualSerialRead() .)

ModemReceive() takes three arguments:

recvBufLength
Size of allocated buffer (in bytes).
recvBuf
Byte pointer to the buffer.
bytesReceived
Word pointer. ModemReceive() writes the number of bytes actually read in to this parameter.

ModemReceive() returns a StreamError value:

STREAM_NO_ERROR
if it successfully reads the data.
STREAM_CLOSED
if the stream is not open.
STREAM_SHORT_READ_WRITE
if the required amount of data was not available and STREAM_NO_BLOCK was specified.

Up: GEOS SDK TechDocs | Up | Prev: 3 Sending Data | Next: 5 Disconnecting