obcsim/msp_obc_link.c
struct msp_response msp_recv_data_frame(msp_link_t *lnk,
                                        unsigned char *data,
                                        unsigned long *datalen)
{
	int code;
	struct msp_response r;
	struct msp_obc_frame frame;
	unsigned long len;
	unsigned long rx_len;
	unsigned long i;

	if (lnk == NULL || data == NULL || datalen == NULL || lnk->buffer == NULL)
		return msp_response_error(MSP_OBC_ERR_NULL_POINTER);

	if (lnk->next_action != MSP_LINK_ACTION_RX_DATA) {
		lnk->corrupt_frame_count += 1;
		return msp_response_error(MSP_OBC_ERR_INVALID_ACTION);
	}

	len = msp_next_data_length(lnk);
	if (len == 0) {
		lnk->corrupt_frame_count += 1;
		return msp_response_error(MSP_OBC_ERR_INVALID_ACTION);
	}

	/* Make sure that rx_len is at least 9 so that we can decode an unexpected
	 * header frame if the experiment decides to send that */
	rx_len = len + 5;
	if (rx_len < 9)
		rx_len = 9;

	code = msp_i2c_read(lnk->slave_address, lnk->buffer, rx_len);
	if (code) {
		lnk->corrupt_frame_count += 1;
		return msp_response_error(MSP_OBC_ERR_I2C_ERROR);
	}

	/* First try to decode it as a data frame */
	frame = msp_obc_decode_frame(lnk, lnk->buffer, len + 5);
	if (frame.type == MSP_OBC_FRAME_DATA) {
		/* Check that it is not a duplicate frame */
		if (frame.id != (lnk->frame_id ^ 1)) {
			lnk->corrupt_frame_count += 1;
			return msp_response_error(MSP_OBC_ERR_INVALID_FRAME);
		}

		/* All good, copy over the data and update link state */
		for (i = 0; i < frame.datalen; i++)
			data[i] = frame.data[i];

		*datalen = frame.datalen;

		lnk->frame_id = frame.id;
		lnk->next_action = MSP_LINK_ACTION_TX_HEADER;
		lnk->processed_length += frame.datalen;

		r.status = MSP_RESPONSE_OK;
		return r;
	}


	/* If that didn't work, we should try to decode it as a header frame */
	frame = msp_obc_decode_frame(lnk, lnk->buffer, 9);
	if (frame.type != MSP_OBC_FRAME_HEADER) {
		msp_debug("Expected data frame, got a corrupt frame");
		lnk->corrupt_frame_count += 1;
		lnk->next_action = MSP_LINK_ACTION_TX_HEADER;
		return msp_response_error(MSP_OBC_ERR_INVALID_FRAME);
	}
	
	msp_debug("Expected data frame, got header frame");

	/* If the frame was a NULL frame, we must abort the transaction */
	if (frame.opcode == MSP_OP_NULL) {
		r = msp_response_aborted(lnk);
		msp_set_as_ready(lnk);
		return r;
	}

	/* If it turns out that the experiment is busy, we report that */
	if (frame.opcode == MSP_OP_EXP_BUSY)
		return msp_response_busy();

	/* If we received the EXP_SEND header again, then we simply discard it as
	 * an error. */
	/*if (frame.opcode == MSP_OP_EXP_SEND && frame.id == link->transaction_id) {
		link->corrupt_frame_count += 1;
		link->next_action = MSP_OBC_ACTION_TX_HEADER;
		r.status = MSP_RESPONSE_ERROR;
		r.error_code = MSP_OBC_ERR_INVALID_FRAME;
		return r;
	}*/

	/* If none of the previous cases, we received some frame that we should not
	 * have received. Next we just send and ACK and hope for the best. */
	lnk->corrupt_frame_count += 1;
	lnk->next_action = MSP_LINK_ACTION_TX_HEADER;
	return msp_response_error(MSP_OBC_ERR_INVALID_FRAME);
}
/*
 * Blocking (read over I2C)
 *
 * Receives a data frame from the experiment. The data that was present in the
 * data frame will be copied over into the area of memory pointed to by the
 * argument data and the number of bytes copied will be written into the long
 * pointed to by datalen. However, if the experiment did send a header frame
 * instead, this will get interpreted accordingly as well and nothing will be
 * written to the area of memory pointed to by the argument data.
 *
 * This function will also update the state of the link.
 *
 * If the link is in an incorrect state or if any of the inputs are invalid
 * then no I2C transmission will be made and an error will be returned.
 */
Blocking (read over I2C)

Receives a data frame from the experiment. The data that was present in the
data frame will be copied over into the area of memory pointed to by the
argument data and the number of bytes copied will be written into the long
pointed to by datalen. However, if the experiment did send a header frame
instead, this will get interpreted accordingly as well and nothing will be
written to the area of memory pointed to by the argument data.

This function will also update the state of the link.

If the link is in an incorrect state or if any of the inputs are invalid
then no I2C transmission will be made and an error will be returned.
Blocking ( read over I2C ) Receives a data frame from the experiment . The data that was present in the data frame will be copied over into the area of memory pointed to by the argument data and the number of bytes copied will be written into the long pointed to by datalen . However if the experiment did send a header frame instead this will get interpreted accordingly as well and nothing will be written to the area of memory pointed to by the argument data . This function will also update the state of the link . If the link is in an incorrect state or if any of the inputs are invalid then no I2C transmission will be made and an error will be returned .
struct msp_response msp_recv_data_frame(msp_link_t *lnk,
                                        unsigned char *data,
                                        unsigned long *datalen)
{
	int code;
	struct msp_response r;
	struct msp_obc_frame frame;
	unsigned long len;
	unsigned long rx_len;
	unsigned long i;
	if (lnk == NULL || data == NULL || datalen == NULL || lnk->buffer == NULL)
		return msp_response_error(MSP_OBC_ERR_NULL_POINTER);
	if (lnk->next_action != MSP_LINK_ACTION_RX_DATA) {
		lnk->corrupt_frame_count += 1;
		return msp_response_error(MSP_OBC_ERR_INVALID_ACTION);
	}
	len = msp_next_data_length(lnk);
	if (len == 0) {
		lnk->corrupt_frame_count += 1;
		return msp_response_error(MSP_OBC_ERR_INVALID_ACTION);
	}
	rx_len = len + 5;
	if (rx_len < 9)
		rx_len = 9;
	code = msp_i2c_read(lnk->slave_address, lnk->buffer, rx_len);
	if (code) {
		lnk->corrupt_frame_count += 1;
		return msp_response_error(MSP_OBC_ERR_I2C_ERROR);
	}
	frame = msp_obc_decode_frame(lnk, lnk->buffer, len + 5);
	if (frame.type == MSP_OBC_FRAME_DATA) {
		if (frame.id != (lnk->frame_id ^ 1)) {
			lnk->corrupt_frame_count += 1;
			return msp_response_error(MSP_OBC_ERR_INVALID_FRAME);
		}
		for (i = 0; i < frame.datalen; i++)
			data[i] = frame.data[i];
		*datalen = frame.datalen;
		lnk->frame_id = frame.id;
		lnk->next_action = MSP_LINK_ACTION_TX_HEADER;
		lnk->processed_length += frame.datalen;
		r.status = MSP_RESPONSE_OK;
		return r;
	}
	frame = msp_obc_decode_frame(lnk, lnk->buffer, 9);
	if (frame.type != MSP_OBC_FRAME_HEADER) {
		msp_debug("Expected data frame, got a corrupt frame");
		lnk->corrupt_frame_count += 1;
		lnk->next_action = MSP_LINK_ACTION_TX_HEADER;
		return msp_response_error(MSP_OBC_ERR_INVALID_FRAME);
	}
	msp_debug("Expected data frame, got header frame");
	if (frame.opcode == MSP_OP_NULL) {
		r = msp_response_aborted(lnk);
		msp_set_as_ready(lnk);
		return r;
	}
	if (frame.opcode == MSP_OP_EXP_BUSY)
		return msp_response_busy();
	lnk->corrupt_frame_count += 1;
	lnk->next_action = MSP_LINK_ACTION_TX_HEADER;
	return msp_response_error(MSP_OBC_ERR_INVALID_FRAME);
}
struct msp_response msp_recv_data_frame ( msp_link_t * lnk , unsigned char * data , unsigned long * datalen ) { int code ; struct msp_response r ; struct msp_obc_frame frame ; unsigned long len ; unsigned long rx_len ; unsigned long i ; if ( lnk == NULL || data == NULL || datalen == NULL || lnk -> buffer == NULL ) return msp_response_error ( MSP_OBC_ERR_NULL_POINTER ) ; if ( lnk -> next_action != MSP_LINK_ACTION_RX_DATA ) { lnk -> corrupt_frame_count += 1 ; return msp_response_error ( MSP_OBC_ERR_INVALID_ACTION ) ; } len = msp_next_data_length ( lnk ) ; if ( len == 0 ) { lnk -> corrupt_frame_count += 1 ; return msp_response_error ( MSP_OBC_ERR_INVALID_ACTION ) ; } rx_len = len + 5 ; if ( rx_len < 9 ) rx_len = 9 ; code = msp_i2c_read ( lnk -> slave_address , lnk -> buffer , rx_len ) ; if ( code ) { lnk -> corrupt_frame_count += 1 ; return msp_response_error ( MSP_OBC_ERR_I2C_ERROR ) ; } frame = msp_obc_decode_frame ( lnk , lnk -> buffer , len + 5 ) ; if ( frame . type == MSP_OBC_FRAME_DATA ) { if ( frame . id != ( lnk -> frame_id ^ 1 ) ) { lnk -> corrupt_frame_count += 1 ; return msp_response_error ( MSP_OBC_ERR_INVALID_FRAME ) ; } for ( i = 0 ; i < frame . datalen ; i ++ ) data [ i ] = frame . data [ i ] ; * datalen = frame . datalen ; lnk -> frame_id = frame . id ; lnk -> next_action = MSP_LINK_ACTION_TX_HEADER ; lnk -> processed_length += frame . datalen ; r . status = MSP_RESPONSE_OK ; return r ; } frame = msp_obc_decode_frame ( lnk , lnk -> buffer , 9 ) ; if ( frame . type != MSP_OBC_FRAME_HEADER ) { msp_debug ( " " ) ; lnk -> corrupt_frame_count += 1 ; lnk -> next_action = MSP_LINK_ACTION_TX_HEADER ; return msp_response_error ( MSP_OBC_ERR_INVALID_FRAME ) ; } msp_debug ( " " ) ; if ( frame . opcode == MSP_OP_NULL ) { r = msp_response_aborted ( lnk ) ; msp_set_as_ready ( lnk ) ; return r ; } if ( frame . opcode == MSP_OP_EXP_BUSY ) return msp_response_busy ( ) ; lnk -> corrupt_frame_count += 1 ; lnk -> next_action = MSP_LINK_ACTION_TX_HEADER ; return msp_response_error ( MSP_OBC_ERR_INVALID_FRAME ) ; }
Blocking (read over I2C)
Blocking ( read over I2C )
/* Make sure that rx_len is at least 9 so that we can decode an unexpected
	 * header frame if the experiment decides to send that */ /* First try to decode it as a data frame */ /* Check that it is not a duplicate frame */ /* All good, copy over the data and update link state */ /* If that didn't work, we should try to decode it as a header frame */ /* If the frame was a NULL frame, we must abort the transaction */ /* If it turns out that the experiment is busy, we report that */ /* If we received the EXP_SEND header again, then we simply discard it as
	 * an error. */ /*if (frame.opcode == MSP_OP_EXP_SEND && frame.id == link->transaction_id) {
		link->corrupt_frame_count += 1;
		link->next_action = MSP_OBC_ACTION_TX_HEADER;
		r.status = MSP_RESPONSE_ERROR;
		r.error_code = MSP_OBC_ERR_INVALID_FRAME;
		return r;
	}*/ /* If none of the previous cases, we received some frame that we should not
	 * have received. Next we just send and ACK and hope for the best. */