diff --git a/examples/simple/main.c b/examples/simple/main.c
index dcf169a..a1cae75 100644
--- a/examples/simple/main.c
+++ b/examples/simple/main.c
@@ -1,101 +1,107 @@
 /*
  * Copyright (c) 2011 Alexandre Tuleu <alexandre.tuleu.2005@polytechnique.org>
  * Ecole Polytechnique Fédérale de Lausanne.
  *
  * this file is part of sbcpd.
  *
  * sbcpd is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Lesser General Public License as published by
  * the Free Software Foundation, either version 3 of the License, or
  * (at your option) any later version.
  *
  * sbcpd is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU Lesser General Public License for more details.
  *
  * You should have received a copy of the Lesser GNU General Public License
  * along with sbcpd.  If not, see <http://www.gnu.org/licenses/>.
  */
 /**
  * \file main.c
  *
  *  \date Oct 11, 2011
  *  \author Alexandre Tuleu
  */
 #include <stdio.h>
 //for all bus transfer definition
 #include <sbcpd/sbcpd.h>
 //for SBCP definitions
 #include <sbcpd/sbcp.h>
 
+//Motordriver class 0xea
 #define DEVICE_CLASS 0xea
 
 static uint16_t firmware_code;
 static int    received_status;
 
 
 //a basic callback. Callback should be as simple as possible. Think them
 //as interrupt
 void my_simple_firmware_callback(sbcpd_transfer * t){
 	if(t->status){//if status != 0, there was an error.
 		received_status = 2;
 		return;
 	}
 
 	firmware_code = t->in_buffer[SBCP_PAYLOAD_START_POS + 1];
 	firmware_code += t->in_buffer[SBCP_PAYLOAD_START_POS] << 8;
 	received_status = 1;
 }
 
 int main(int argc, char ** argv){
 	//first the program shouldinitialize as soon as possible the library
-	sbcpd_bus * bus = sbcpd_default_oncilla_init(0);
+	sbcpd_error err;
+	sbcpd_bus * bus = sbcpd_default_oncilla_init(0,&err);
 
 	if(bus == NULL){
-		fprintf(stderr,"Unable to initialize library.\n");
+		fprintf(stderr,"Unable to initialize library : %s.\n",err.msg);
 		return 1;
 	}
 	if(argc <= 1){
 		fprintf(stderr,"Need at least the id of the board to reach.\n");
 		return 2;
 	}
 	unsigned int id = atoi(argv[1]);
 	if(id < 0 || id > 0xff){
 		fprintf(stderr,"Bad id #%d, should be between 0x00 and 0xff.\n",id);
 		return 3;
 	}
 
 	//ask for a new transfer with a payload of 0
 	sbcpd_transfer * t = sbcpd_bus_append_transfer(bus,0);
 
 	//fill the packet destination
-	t->out_buffer[SBCP_CLASS_POS] = DEVICE_CLASS; //Motordriver board.
+	t->out_buffer[SBCP_CLASS_POS] = DEVICE_CLASS;
 	t->out_buffer[SBCP_ID_POS]    = id;
 	//fill the packet instruction
 	t->out_buffer[SBCP_INSTRUCTION_POS] = 0x00; //ask for firmware version
 
 	//don't need to fill, payload, there is none.
 
 	received_status = 0; //static data to wait for completion.
 
 	//submission will make sure that our packet is correct for the communication
-	//layer
-	sbcpd_bus_submit_all_transfer(bus);
+	//layer (header,payload value, checksum)
+	if(sbcpd_bus_submit_all_transfer(bus)){
+		fprintf(stderr,"Unable to initiate transfer : %s",bus->error.msg);
+		return 5;
+	}
 
 	//wait until completion.
 	while(received_status == 0){
 
 	}
+
 	if(received_status == 2){
 		fprintf(stderr,"Got an error during transfer.\n");
 		return 4;
 	}
 
 	printf("Device 0x%x : 0x%x has a firmare value of : 0x%x.\n",
 	       DEVICE_CLASS,
 	       id,
 	       firmware_code);
 
 	return 0;
 }
diff --git a/sbcpd/bus.c b/sbcpd/bus.c
index 7d58c34..2992c4b 100644
--- a/sbcpd/bus.c
+++ b/sbcpd/bus.c
@@ -1,471 +1,487 @@
 /*
  * Copyright (c) 2011 Alexandre Tuleu <alexandre.tuleu.2005@polytechnique.org>
  * Ecole Polytechnique Fédérale de Lausanne.
  *
  * this file is part of sbcpd.
  *
  * sbcpd is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Lesser General Public License as published by
  * the Free Software Foundation, either version 3 of the License, or
  * (at your option) any later version.
  *
  * sbcpd is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU Lesser General Public License for more details.
  *
  * You should have received a copy of the Lesser GNU General Public License
  * along with sbcpd.  If not, see <http://www.gnu.org/licenses/>.
  */
 /**
  * \file bus.c
  *
  *  \date Aug 15, 2011
  *  \author Alexandre Tuleu
  */
 
 #include <stdlib.h>
 #include <string.h>
 
 #ifndef NDEBUG
 #include <stdio.h>
 #endif
 
 #include "bus.h"
 #include <ftdi.h>
 
 #include "transfer.h"
 
 #include "sbcp.h"
 #include "error.h"
 
 sbcpd_bus * sbcpd_create_bus(const sbcpd_bus_settings settings){
 	sbcpd_bus  * bus = malloc(sizeof(sbcpd_bus));
 
 	sbcpd_init_error(&bus->error,SBCPD_BUS_ERROR);
 	bus->flags = SBCPD_BUS_VOID;
 	*((unsigned int*)&bus->max_frame_packets) = 8;
 	*((unsigned int*)&bus->max_packet_size)   = 64;
 	bus->si         = NULL;
 
 	bus->in_buffer  = NULL;
 	bus->out_buffer = NULL;
 	bus->out_buffer_actual_size = 0;
 
 
 	*((unsigned int *)&bus->buffers_size) = 0;
 	bus->transfers = NULL;
 	bus->transfers_size = 0;
 
 	memcpy((void*)&(bus->settings),&settings,sizeof(sbcpd_bus_settings));
 
 	printf("Created a new sbcpd_bus object. \n");
 
 	return bus;
 }
 
 #define CHECK_IF_BUS_ALLOCATED if(!bus){\
 SBCPD_RETURN_WITH_ERROR(bus,SBCPD_EBUS_NOT_ALLOCATED,\
                         "You passed a NULL pointer !");\
 }
 
 #define CHECK_IF_BUS_OPENED(m)if(!(bus->flags & SBCPD_BUS_OPEN)){\
 	SBCPD_RETURN_WITH_ERROR(bus,SBCPD_EBUS_IS_NOT_OPEN,\
 	                        m);\
 }
 
 int sbcpd_bus_open(sbcpd_bus * bus,
                    sbcpd_serial_interface * interface){
 	CHECK_IF_BUS_ALLOCATED
 
 
 	if (bus -> si || (bus->flags & SBCPD_BUS_OPEN)){
 		SBCPD_RETURN_WITH_ERROR(bus,SBCPD_EBUS_ALREADY_OPEN,
 		                        "Bus is already opened, you cannot open"
 " it twice !");
 	}
 
 	bus->si = interface;
 
 	///\todo : Check for the master board, ask for frame size and
 	///max packet size.
 	*((unsigned int*)&(bus->buffers_size)) = sizeof(uint8_t)
 	                                         * bus->max_frame_packets
 	                                         * bus->max_packet_size;
 
 	bus->out_buffer = malloc(bus->buffers_size);
 	bus->in_buffer = malloc(bus->buffers_size);
 	bus->out_buffer_actual_size = 0;
 
 
 	bus->transfers = malloc(sizeof(sbcpd_transfer)
 	                               * bus->max_frame_packets);
 
 	bus->transfers_size = 0;
 
 	bus->flags |= SBCPD_BUS_OPEN;
 	return SBCPD_NO_ERROR;
 
 }
 
 int sbcpd_bus_close(sbcpd_bus * bus){
 	CHECK_IF_BUS_ALLOCATED
 
 	if(!(bus->flags & SBCPD_BUS_OPEN)){
 		SBCPD_RETURN_WITH_ERROR(bus,
 		                        SBCPD_EBUS_IS_NOT_OPEN,
 		                        "Bus is not opened, cannot close it");
 	}
 
 	//unlink all pending transfer.
 	if(bus->flags & SBCPD_BUS_BUSY){
 		sbcpd_bus_unlink_all_transfer(bus);
 	}
 
 	if(bus->si){
 		(*(bus->si->close))(bus->si);
 		(*(bus->si->free))(bus->si);
 		bus->si = NULL;
 	}
 
 	if(bus->out_buffer){
 		free(bus->out_buffer);
 	}
 
 	if(bus->in_buffer){
 		free(bus->in_buffer);
 	}
 
 	*((unsigned int*)&bus->buffers_size) = 0;
 	bus->out_buffer_actual_size = 0;
 
 	if(bus->transfers){
 		free(bus->transfers);
 	}
 	bus->transfers_size = 0;
 
 	bus->flags &= ~SBCPD_BUS_OPEN;
 
 	return SBCPD_NO_ERROR;
 }
 
 int sbcpd_free_bus(sbcpd_bus * bus){
 	CHECK_IF_BUS_ALLOCATED
 	if(bus->flags & SBCPD_BUS_OPEN){
 		sbcpd_bus_close(bus);
 	}
 
 	free(bus);
 
 	return SBCPD_NO_ERROR;
 }
 
 sbcpd_transfer * sbcpd_bus_append_transfer(sbcpd_bus * bus,
                                            unsigned int payload_size){
 	if(!bus){
 		SBCPD_RETURN_WITH_ERROR_AND_VALUE(bus,
 		                                  SBCPD_EBUS_NOT_ALLOCATED,
 		                                  "You passed a NULL pointer for a bus",
 		                                  NULL);
 	}
 
 	if(!(bus->flags & SBCPD_BUS_OPEN)){
 		SBCPD_RETURN_WITH_ERROR_AND_VALUE(bus,
 		                                  SBCPD_EBUS_IS_NOT_OPEN,
 		                                  "You should open the bus to make transfers.",
 		                                  NULL);
 	}
 
 	if((bus->flags & SBCPD_BUS_BUSY)){
 		SBCPD_RETURN_WITH_ERROR_AND_VALUE(bus,
 		                                  SBCPD_EBUS_IS_BUSY,
 		                                  "You cannot create new transfer while "
 		                                  "transfering, please wait for other transfer to "
 		                                  "finish",
 		                                  NULL);
 	}
 
 	//no slot available
 	if(bus->transfers_size == bus->max_frame_packets){
 		SBCPD_RETURN_WITH_ERROR_AND_VALUE(bus,
 		                                  SBCPD_EBUS_BUS_RESSOUCE_ALREADY_TOOK,
 		                                  "Not enough packet available in the frame",
 		                                  NULL);
 	}
 
 	if(payload_size > bus->max_packet_size - SBCP_MINIMAL_SIZE){
 		SBCPD_RETURN_WITH_ERROR_AND_VALUE(bus,
 		                                  SBCPD_EBUS_BAD_TRANSFER_DEFINITION,
 		                                  "payload size should be between 0 and "
 		                                  "bus->max_packet_size - 6",
 		                                  NULL);
 	}
 
 	sbcpd_transfer * t = &(bus->transfers[bus->transfers_size]);
 	++bus->transfers_size;
 
 	t->status = SBCPD_TRANSFER_UNSTARTED;
 	t->callback = NULL;
 	*((uint8_t **)&(t->out_buffer)) = &(bus->out_buffer[bus->out_buffer_actual_size]);
 	*((unsigned int *)&t->out_size) = payload_size + SBCP_MINIMAL_SIZE;
 	bus->out_buffer_actual_size    += t->out_size;
 
 	*((uint8_t**)&t->in_buffer)   = NULL;
 	*((unsigned int*)&t->in_size) = 0;
 
 	return t;
 }
 
 void sbcpd_bus_unlink_last_transfer(sbcpd_bus *bus){
 
 }
 
 int sbcpd_bus_remove_last_transfer(sbcpd_bus * bus){
 	CHECK_IF_BUS_ALLOCATED
 	CHECK_IF_BUS_OPENED("Bus should be opened.");
 	if(bus->transfers_size == 0){
 		SBCPD_RETURN_WITH_ERROR(bus,
 		                        SBCPD_EBUS_TRANSFER_LIST_EMPTY,
 		                        "Need at least one transfer to remove.");
 	}
 
 	if(bus->flags & SBCPD_BUS_BUSY){
 		sbcpd_bus_unlink_last_transfer(bus);
 	}
 	--bus->transfers_size;
 	return SBCPD_NO_ERROR;
 }
 
 int sbcpd_bus_clear_all_transfers(sbcpd_bus * bus){
 	CHECK_IF_BUS_ALLOCATED
 	CHECK_IF_BUS_OPENED("Bus should be opened.");
 	if(bus->transfers_size == 0){
 		SBCPD_RETURN_WITH_ERROR(bus,
 		                        SBCPD_EBUS_TRANSFER_LIST_EMPTY,
 		                        "Need at least one transfer to remove.");
 	}
 
 	if(bus->flags & SBCPD_BUS_BUSY){
 		sbcpd_bus_unlink_all_transfer(bus);
 	}
 	bus->transfers_size = 0;
 	return SBCPD_NO_ERROR;
 }
 
 int sbcpd_bus_read_needed_byte(sbcpd_bus * bus,
                                       unsigned int current_packet,
                                       unsigned int needed_bytes){
 	unsigned int maxTrials = bus->settings.max_trials;
 	while(   bus->received_bytes < bus->parsed_bytes + needed_bytes
 	      && maxTrials > 0){
-		bus->received_bytes +=
+		int readout =
 			(*bus->si->read_data)(bus->si,
 			                      &(bus->in_buffer[bus->received_bytes]),
 		                          bus->buffers_size - bus->received_bytes);
+
+		if(readout < 0){
+			maxTrials = 0;
+			break;
+		}
+
+		bus->received_bytes += readout;
 		--maxTrials;
 	}
 
 	if(maxTrials == 0 && bus->received_bytes < bus->parsed_bytes + needed_bytes){
 		for(; current_packet < bus->transfers_size; ++current_packet){
 			bus->transfers[current_packet].com_error =
 				SBCPD_CERR_IMCOMPLETE_READOUT;
 			bus->transfers[current_packet].status =
 				SBCPD_TRANSFER_HAS_COMMUNICATION_ERROR;
 		}
 		return 1;
 	}
 	return SBCPD_NO_ERROR;
 }
 
 
 
 uint8_t sbcpd_compute_checksum_of_packet(const uint8_t * data){
 	uint8_t cs = 0;
 	unsigned int i = SBCP_CLASS_POS;
 	uint8_t cs_pos = data[SBCP_PAYLOAD_SIZE_POS] + SBCP_PAYLOAD_START_POS;
 	for(;i < cs_pos; ++i){
 		cs += data[i];
 	}
 	return cs;
 }
 
 void sbcpd_transfer_parse_communication_errors(sbcpd_transfer * t){
 
 	if(t->in_size != 7){
 		t->com_error = SBCPD_CERR_BAD_CERR_PACKET;
 		return;
 	}
 
 	switch(t->in_buffer[SBCP_PAYLOAD_START_POS]){
 	case SBCP_CERR_INCORRECT_CHECKSUM :
 		if(t->in_buffer[SBCP_CLASS_POS] == SBCP_MASTER_CLASS){
 			t->com_error = SBCPD_CERR_HOST_BAD_CHECKSUM;
 		} else {
 			t->com_error = SBCPD_CERR_MASTER_BAD_CHECKSUM;
 		}
 		break;
 	case SBCP_CERR_HOST_BUS_TIMEOUT :
 		t->com_error = SBCPD_CERR_HOST_TIMEDOUT;
 		break;
 	case SBCP_CERR_SLAVE_BUS_TIMEOUT :
 		if(t->in_buffer[SBCP_CLASS_POS] == SBCP_MASTER_CLASS){
 			t->com_error = SBCPD_CERR_SLAVE_TIMEOUT;
 		}else{
 			t->com_error = SBCPD_CERR_MASTER_TIMEDOUT;
 		}
 		break;
 	case SBCP_CERR_HOST_BUS_FRAME_ERROR :
 		t->com_error = SBCPD_CERR_HOST_FRAME_ERROR;
 		break;
 	case SBCP_CERR_SLAVE_BUS_FRAME_ERROR :
 		if(t->in_buffer[SBCP_CLASS_POS] == SBCP_MASTER_CLASS){
 			t->com_error = SBCPD_CERR_SLAVE_FRAME_ERROR;
 		} else {
 			t->com_error = SBCPD_CERR_MASTER_FRAME_ERROR;
 		}
 		break;
 	case SBCP_CERR_UNKNOWN_INSTRUCTION :
 		t->com_error = SBCPD_CERR_UNKNOWN_INSTRUCTION_ERROR;
 		break;
 	default :
 		t->status = SBCPD_CERR_BAD_CERR_PACKET;
 		break;
 	}
 }
 
 
 void sbcpd_transfer_check_response(sbcpd_transfer * t){
 	uint8_t cs = sbcpd_compute_checksum_of_packet(t->in_buffer);
 
 	if(cs != t->in_size - 1 ){
 		t->com_error = SBCPD_CERR_SLAVE_BAD_CHECKSUM;
 		t->status    = SBCPD_TRANSFER_HAS_COMMUNICATION_ERROR;
 		return;
 	}
 
 	if(t->in_buffer[SBCP_INSTRUCTION_POS] != SBCP_COMMUNICATION_ERROR){
 		t->status = SBCPD_TRANSFER_OK;
 		return;
 	}
 
 	if(t->in_buffer[SBCP_INSTRUCTION_POS] != SBCP_NO_ERROR){
 		t->status = SBCPD_TRANSFER_HAS_APPLICATION_ERROR;
 		return;
 	}
 
 	t->status = SBCPD_TRANSFER_HAS_COMMUNICATION_ERROR;
 	//we got an error to parse.
 	sbcpd_transfer_parse_communication_errors(t);
 }
 
 
 
 void sbcpd_bus_get_response_packets(sbcpd_bus * bus){
 	bus->parsed_bytes   = 0;
 	bus->received_bytes = 0;
 	unsigned int i;
 	for(i = 0; i < bus->transfers_size; ++i){
 		//getting the data from interface
 		do{
 			if(sbcpd_bus_read_needed_byte(bus,i,SBCP_HEADER_POS + 1)){
 				return;
 			}
 		}while(bus->in_buffer[bus->parsed_bytes] != SBCP_HEADER_VALUE &&
 				++bus->parsed_bytes);
 
 		if(sbcpd_bus_read_needed_byte(bus,i,SBCP_PAYLOAD_SIZE_POS + 1)){
 			return;
 		}
 
 		unsigned int packet_total_size =
 				bus->in_buffer[bus->parsed_bytes + SBCP_PAYLOAD_SIZE_POS]
 				               + SBCP_MINIMAL_SIZE;
 		if(packet_total_size > bus->max_packet_size){
 			bus->transfers[i].status    = SBCPD_TRANSFER_HAS_COMMUNICATION_ERROR;
 			bus->transfers[i].com_error = SBCPD_CERR_INCONSISTENT_RESPONSE_SIZE;
 			//ignore the rest of the data, continue parsing
 			bus->parsed_bytes += SBCP_PAYLOAD_SIZE_POS + 1;
 			continue;
 		}
 
 		if(sbcpd_bus_read_needed_byte(bus,i,packet_total_size)){
 			return;
 		}
 
 		//data is received, noy check the incoming packet
 		sbcpd_transfer * t = &(bus->transfers[i]);
 		*((uint8_t **)&t->in_buffer) = &(bus->in_buffer[bus->parsed_bytes]);
 		*((unsigned int*)&t->in_size)  = packet_total_size;
 		bus->parsed_bytes += packet_total_size;
 
 
 		//now we have to check out the incomming data
 		sbcpd_transfer_check_response(t);
 	}
 }
 
 
 
 int sbcpd_bus_submit_all_transfer(sbcpd_bus * bus){
 	CHECK_IF_BUS_ALLOCATED
 	CHECK_IF_BUS_OPENED("Bus should be opened.");
 	if(bus->transfers_size == 0){
 		SBCPD_RETURN_WITH_ERROR(bus,SBCPD_EBUS_TRANSFER_LIST_EMPTY,
 		                        "Need at least one transfer definition to send "
 		                        "data over the bus");
 	}
 
 	if(bus->flags & SBCPD_BUS_BUSY){
 		SBCPD_RETURN_WITH_ERROR(bus,SBCPD_EBUS_IS_BUSY,
 		                        "Bus is already sending data, wait for current"
 		                        "transfer termination.");
 	}
 
 	bus->flags |= SBCPD_BUS_BUSY;
 
 
 	// Preparing packet to send
 	unsigned int i;
 	for(i = 0; i < bus->transfers_size ; ++i){
 		if(bus->transfers[i].callback == NULL){
 			bus->flags &= ~SBCPD_BUS_BUSY;
 			SBCPD_RETURN_WITH_ERROR(bus,
 			                        SBCPD_EBUS_BAD_TRANSFER_DEFINITION,
 			                        "Transfer does not have a callback set.");
 		}
 
 		//put the correct header
 		bus->transfers[i].out_buffer[SBCP_HEADER_POS] = SBCP_HEADER_VALUE;
 
 		//computes the right size
 		uint8_t payload_size = bus->transfers[i].out_size - SBCP_MINIMAL_SIZE;
 		bus->transfers[i].out_buffer[SBCP_PAYLOAD_SIZE_POS] = payload_size;
 
 		//computes the right checksum
 		bus->transfers[i].out_buffer[payload_size + SBCP_PAYLOAD_START_POS] =
 			sbcpd_compute_checksum_of_packet(bus->transfers[i].out_buffer);
 	}
 	//all packet prepared successfully.
 
 	//setting all the transfer status
 	for(i = 0; i < bus->transfers_size ; ++i){
 		bus->transfers[i].status = SBCPD_TRANSFER_IN_PROGRESS;
 	}
 
 
 	//sending all the data over the host bus.
-	(*(bus->si->write_data))(bus->si,
-	                         bus->out_buffer,
-	                         bus->out_buffer_actual_size);
+	int sended_bytes = (*(bus->si->write_data))(bus->si,
+	                                            bus->out_buffer,
+	                                            bus->out_buffer_actual_size);
+
+	if( sended_bytes < 0 ){
+		for(i = 0; i < bus->transfers_size;++i){
+			bus->transfers[i].status = SBCPD_TRANSFER_ABORTED;
+		}
+
+		SBCPD_RETURN_WITH_ERROR(bus,SBCPD_EBUS_CANNOT_SEND_DATA,
+		                        "serial interface was not able to send data.");
+	}
 
 	//now get all the response packet.
 	sbcpd_bus_get_response_packets(bus);
 	//all packet are received, the bus is not busy anymore.
 	bus->flags &= ~SBCPD_BUS_BUSY;
 	return SBCPD_NO_ERROR;
 }
 
 int sbcpd_bus_unlink_all_transfer(sbcpd_bus * bus){
 	return 0;
 }
 
diff --git a/sbcpd/bus.h b/sbcpd/bus.h
index 3bfed4c..ad68ceb 100644
--- a/sbcpd/bus.h
+++ b/sbcpd/bus.h
@@ -1,260 +1,261 @@
 /*
  * Copyright (c) 2011 Alexandre Tuleu <alexandre.tuleu.2005@polytechnique.org>
  * Ecole Polytechnique Fédérale de Lausanne.
  *
  * this file is part of sbcpd.
  *
  * sbcpd is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Lesser General Public License as published by
  * the Free Software Foundation, either version 3 of the License, or
  * (at your option) any later version.
  *
  * sbcpd is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU Lesser General Public License for more details.
  *
  * You should have received a copy of the Lesser GNU General Public License
  * along with sbcpd.  If not, see <http://www.gnu.org/licenses/>.
  */
 
 /**
  * \file bus.h
  *
  *  \date Aug 15, 2011
  *  \author Alexandre Tuleu
  */
 
 #ifndef SBCPD_BUS_H_
 #define SBCPD_BUS_H_
 
 #include "error.h"
 #include "transfer.h"
 #include "si/serial_interface.h"
 /**
  * Error code that could be returned by the \ref sbcpd_bus_m  'sfunctions.
  * \ingroup sbcpd_bus_m
  */
 enum sbcpd_bus_error_code{
 	SBCPD_EBUS_NO_ERROR                      = 0x0000,
 	//!< SBCPD_EBUS_NO_ERROR No errors happened.
 	SBCPD_EBUS_ALREADY_OPEN,
 	//!< SBCPD_EBUS_ALREADY_OPENED Bus is already opened.
 	SBCPD_EBUS_NOT_ALLOCATED,
 	//!< SBCPD_EBUS_NOT_ALLOCATED the bus is not allocated
 	SBCPD_EBUS_IS_NOT_OPEN,
 	//!< SBCPD_EBUS_IS_NOT_OPEN the bus was not opened when running the command.
 	SBCPD_EBUS_BUS_RESSOUCE_ALREADY_TOOK,
 	//!< SBCPD_EBUS_IS_ALREADY_OPENED the bus ressources is already allocated
 	//!< to another application.
 	SBCPD_EBUS_IS_BUSY,
 	//!< SBCPD_EBUS_IS_BUSY The bus is currently busy, the operation could not
 	//!< be performed.
 	SBCPD_EBUS_TRANSFER_LIST_EMPTY,
 	//!< SBCPD_EBUS_TRAMNSFER_LIST_EMPTY There is no transfer definition pending
 	//!< for this bus.
-	SBCPD_EBUS_BAD_TRANSFER_DEFINITION
+	SBCPD_EBUS_BAD_TRANSFER_DEFINITION,
 	//!< SBCPD_EBUS_BAD_TRANSFER_DEFINITION The transfer definition isn't
 	//!< correct.
+	SBCPD_EBUS_CANNOT_SEND_DATA
 };
 
 typedef enum sbcpd_bus_error_code sbcpd_bus_error_code;
 
 enum sbcpd_bus_flags{
 	SBCPD_BUS_VOID = 0x0,
 	SBCPD_BUS_OPEN = 0x01,
 	SBCPD_BUS_BUSY = 0x02
 };
 
 typedef enum sbcpd_bus_flags sbcpd_bus_flags;
 
 
 /**
  *  Settings of the bus that should be set by the user before opening it.
  *  \ingroup sbcpd_bus_m
  */
 struct sbcpd_bus_settings {
 	/**
 	 * The id of the master over the bus
 	 */
 	unsigned char master_id;
 
 	/**
 	 * The frame rate of the bus, in ms.
 	 */
 	unsigned int frame_rate;
 
 	/**
 	 * The number of trial before dropping a packet.
 	 */
 
 	unsigned int max_trials;
 };
 typedef struct sbcpd_bus_settings sbcpd_bus_settings;
 
 /**
  * Represents a SBCP bus that could be issued to manipulate sbcpd_transfer.
  * End user should not write in any of the structure fields, at the exception of
  * the settings, before opening
  * \ingroup sbcpd_bus_m
  */
 struct sbcpd_bus{
 	/**
 	 * Status of the bus.
 	 */
 	sbcpd_bus_flags          flags;
 	/**
 	 * \name some constants of the bus
 	 */
 	///@{
 	/**
 	 * The maximal number of packet that a frame could contain.
 	 */
 	const unsigned int             max_frame_packets;
 
 	/**
 	 * The maximal total byte size of a packet over this bus.
 	 */
 	unsigned int             max_packet_size;
 	/**
 	 * User defined settings.
 	 */
 	const sbcpd_bus_settings settings;
 	///@}
 
 	/**
 	 * The last error that occured on the bus.
 	 */
 	sbcpd_error              error;
 
 	sbcpd_serial_interface * si;
 
 	const unsigned int buffers_size;
 	uint8_t * out_buffer;
 	uint8_t * in_buffer;
 	unsigned int out_buffer_actual_size;
 
 	struct sbcpd_transfer * transfers;;
 	unsigned int  transfers_size;
 
 	unsigned int received_bytes;
 	unsigned int parsed_bytes;
 
 };
 typedef struct sbcpd_bus sbcpd_bus;
 
 /**
  * Creates a new bus.
  * \return
  */
 sbcpd_bus * sbcpd_create_bus(const sbcpd_bus_settings settings);
 
 /**
  * Finds and opens a bus through a serial interface. Please notice that
  * the settings of the bus should already be set in the sbcpd_bus structure.
  * \ingroup sbcpd_bus_m
  * \param bus the bus structure with settings already set.
  * \param interface the sbcpd_serial_interface to use.
  * \return 0 on success, otherwise any of the following code :
  *  - SBCPD_EBUS_NOT_FOUND if the specified device is not found.
  *  - SBCPD_EBUS_ALREADY_OPEN if the specified bus is already opened.
  */
 
 int sbcpd_bus_open(sbcpd_bus* bus,
                    sbcpd_serial_interface * interface);
 
 
 /**
  * Closes a bus. This should be done to release ownership of the application on
  * the bus.
  * \ingroup sbcpd_bus_m
  * \param bus
  * \return
  */
 int sbcpd_bus_close(sbcpd_bus * bus);
 
 /**
  * Free the memory used by a bus.
  * \ingroup sbcpd_bus_m
  * \param bus
  * \return
  */
 int sbcpd_free_bus(sbcpd_bus * bus);
 
 
 
 /**
  * Append a new transfer definition to the bus
  * \param bus the sbcpd_bus to use
  * \param out_size the output size of the transfer.
  * \return a pointer to the new sbcpd_transfer structure when there is no error
  *         or NULL otherwise. It may set the following bus errors :
  * -
  * \ingroup sbcpd_bus_m
  */
 sbcpd_transfer * sbcpd_bus_append_transfer(sbcpd_bus * bus,
                                            unsigned int payload_size);
 
 /**
  * Removes the last requested transer. It will unlink it first.
  * \param bus
  * \return 0 on success, or any of the following error code otherwise :
  * \ingroup sbcpd_bus_m
  */
 int sbcpd_bus_remove_last_transfer(sbcpd_bus * bus);
 
 /**
  * Removes all the transfer of the bus. it will unlink them first.
  * \param bus
  * \return 0 on success, or any of the following error code otherwise :
  * \ingroup sbcpd_bus_m
  */
 int sbcpd_bus_clear_all_transfers(sbcpd_bus * bus);
 
 /**
  * Submits all the current affected tranfer to the bus.
  * \param bus
  * \return 0 on success, or any of the following error code otherwise :
  * \ingroup sbcpd_bus_m
  */
 int sbcpd_bus_submit_all_transfer(sbcpd_bus * bus);
 
 /**
  * Unlinks all transfers of the bus. It will not prevent data to be sent, but
  * sbcpd_transfer callbacks will not be called.
  * \param bus
  * \return 0 on success, or any of the following error code otherwise :
  * \ingroup sbcpd_bus_m
  */
 int sbcpd_bus_unlink_all_transfer(sbcpd_bus * bus);
 
 
 
 /**
  * \return the last bus error code
  * \ingroup sbcpd_bus_m
  * \param bus
  */
 static inline sbcpd_bus_error_code sbcpd_bus_get_last_error_code(sbcpd_bus * bus){
 	return sbcpd_get_error_code(&(bus->error));
 }
 
 /**
  * \return the last bus error code
  * \ingroup sbcpd_bus_m
  * \param bus
  * \return
  */
 static inline const char * sbcpd_bus_get_last_error_message(sbcpd_bus * bus){
 	return bus->error.msg;
 }
 
 /**
  * \defgroup sbcpd_bus_m SBCP Bus
  *
  *
  * \ingroup sbcpd_m
  *
  */
 
 #endif //SBCPD_BUS_H_
diff --git a/sbcpd/error.h b/sbcpd/error.h
index 7fe4f4e..57397fb 100644
--- a/sbcpd/error.h
+++ b/sbcpd/error.h
@@ -1,138 +1,138 @@
 /*
  * Copyright (c) 2011 Alexandre Tuleu <alexandre.tuleu.2005@polytechnique.org>
  * Ecole Polytechnique Fédérale de Lausanne.
  *
  * this file is part of sbcpd.
  *
  * sbcpd is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Lesser General Public License as published by
  * the Free Software Foundation, either version 3 of the License, or
  * (at your option) any later version.
  *
  * sbcpd is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU Lesser General Public License for more details.
  *
  * You should have received a copy of the Lesser GNU General Public License
  * along with sbcpd.  If not, see <http://www.gnu.org/licenses/>.
  */
 /**
  * \file error.h
  *
  *  \date Aug 24, 2011
  *  \author Alexandre Tuleu
  */
 
 #ifndef SBCPD_ERROR_H_
 #define SBCPD_ERROR_H_
 
 #include <stdint.h>
 
 static const uint32_t SBCPD_NO_ERROR = 0;
 
 /**
  * Domain of errors that could occurs in the SBCP low level drivers.
  * \ingroup sbcpd_error_m
  */
 enum sbcpd_error_domain{
-	SBCPD_GLOBAL_ERROR   = 0x0001,
-	SBCPD_BUS_ERROR      = 0x0002,
-	SBCPD_FRAME_ERROR    = 0x0003,
-	SBCPD_TRANSFER_ERROR = 0x0004,
+	SBCPD_GLOBAL_ERROR              = 0x0001,
+	SBCPD_BUS_ERROR                 = 0x0002,
+	SBCPD_SERIAL_INTERFACE_ERROR    = 0x0003,
+	SBCPD_TRANSFER_ERROR            = 0x0004,
 };
 typedef enum sbcpd_error_domain sbcpd_error_domain;
 
 /**
  * Represents an error of the sbcp low level driver.
  * \ingroup sbcpd_error_m
  */
 struct sbcpd_error {
 	/**
 	 * A code that represents the error. If it is zero, there is no error.
 	 */
 	uint32_t           code;
 
 	/**
 	 * The domain of the error.
 	 */
 	sbcpd_error_domain domain;
 	/**
 	 * Message associated with the error.
 	 */
 	const char *       msg;
 };
 
 typedef struct sbcpd_error sbcpd_error;
 
 
 
 /**
  * Initializes the error.
  * \ingroup sbcpd_error_m
  * \param error the sbcpd_error to initialize.
  * \param domain the sbcpd_error_domain used for this error.
  */
 void sbcpd_init_error(sbcpd_error * error, sbcpd_error_domain domain);
 
 /**
  * Creates a new error.
  * @return a pointer to the new sbcpd_error
  * \ingroup sbcpd_error_m
  */
 sbcpd_error * sbcpd_create_global_error();
 
 /**
  * Releases an allocated error.
  * @param error
  * \ingroup sbcpd_error_m
  */
 void sbcpd_free_global_error(sbcpd_error * error);
 
 
 
 /**
  * \return the error code of an sbcpd_error
  * \param error the error to get the code from.
  * \ingroup sbcpd_error_m
  */
 static inline uint16_t sbcpd_get_error_code(sbcpd_error * error){
 	return error->code;
 }
 
 
 /**
  * \return the domain of an sbcpd_error
  *
  * \ingroup sbcpd_error_m
  */
 static inline sbcpd_error_domain sbcpd_get_error_domain(sbcpd_error * error){
 	return error->domain;
 }
 
 
 
 #define SBCPD_RETURN_WITH_ERROR_AND_VALUE(var,error_code,error_msg,value) do{\
 	var->error.code = error_code;\
 	var->error.msg = error_msg;\
 	return value;\
 }while(0)
 /**
  * A convenience macro to return of a function that causes an error.
  * \ingroup sbcpd_error_m
  */
 #define SBCPD_RETURN_WITH_ERROR(var, error_code , error_msg) \
 	SBCPD_RETURN_WITH_ERROR_AND_VALUE(var,error_code,error_msg,error_code)
 
 
 
 /**
  * \defgroup sbcpd_error_m Error Handling
  *
  * In the SBCP low level driver, errors are reported using an sbcpd_error
  * structure. It has an sbcpd_error_domain, which id unique for each module,
  * and an error code, which if it is zero, means that no errors occured.
  * \ingroup sbcpd_m
  */
 
 #endif // SBCPD_ERROR_H_
diff --git a/sbcpd/sbcpd.c b/sbcpd/sbcpd.c
index 3425a1c..24b9d41 100644
--- a/sbcpd/sbcpd.c
+++ b/sbcpd/sbcpd.c
@@ -1,56 +1,69 @@
 /*
  * Copyright (c) 2011 Alexandre Tuleu <alexandre.tuleu.2005@polytechnique.org>
  * Ecole Polytechnique Fédérale de Lausanne.
  *
  * this file is part of sbcpd.
  *
  * sbcpd is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Lesser General Public License as published by
  * the Free Software Foundation, either version 3 of the License, or
  * (at your option) any later version.
  *
  * sbcpd is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU Lesser General Public License for more details.
  *
  * You should have received a copy of the Lesser GNU General Public License
  * along with sbcpd.  If not, see <http://www.gnu.org/licenses/>.
  */
 
 /**
  * \file sbcpd.c
  *
  *  \date Aug 15, 2011
  *  \author Alexandre Tuleu
  */
 
 
 #include "sbcpd.h"
+#include <stdlib.h>
 
 #include "si/ft2232h.h"
 
-sbcpd_bus * sbcpd_default_oncilla_init(unsigned int master_id){
+sbcpd_bus * sbcpd_default_oncilla_init(unsigned int master_id,
+                                       sbcpd_error * err){
 	sbcpd_bus_settings settings;
 	settings.frame_rate = 1;
 	settings.master_id = master_id;
 	settings.max_trials = 20;
 	sbcpd_bus * bus = sbcpd_create_bus(settings);
 
 	sbcpd_serial_interface * si = sbcpd_ft2232h_create_interface();
 
-	sbcpd_ft2232h_open(si,3310000,0,2);
+	if(sbcpd_ft2232h_open(si,3310000,0,2) < 0 ){
+		if(err){
+			*err=si->error;
+		}
+		return NULL;
+	}
 
-	sbcpd_bus_open(bus,si);
+
+	if(sbcpd_bus_open(bus,si) < 0){
+		if(err){
+			*err = bus->error;
+		}
+		return NULL;
+	}
 
 	return bus;
 }
 
 /**
  * \defgroup sbcpd_m SBCP Driver Module
  *
  * \brief This module is responsible of the communication over SBCP buses.
  * Through the sbcpd_bus structure you can open and request the management of
  * one bus, where you can issue sbcpd_transfer request.
  *
  */
diff --git a/sbcpd/sbcpd.h b/sbcpd/sbcpd.h
index 27e0289..377f48e 100644
--- a/sbcpd/sbcpd.h
+++ b/sbcpd/sbcpd.h
@@ -1,35 +1,36 @@
 /*
  * Copyright (c) 2011 Alexandre Tuleu <alexandre.tuleu.2005@polytechnique.org>
  * Ecole Polytechnique Fédérale de Lausanne.
  *
  * this file is part of sbcpd.
  *
  * sbcpd is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Lesser General Public License as published by
  * the Free Software Foundation, either version 3 of the License, or
  * (at your option) any later version.
  *
  * sbcpd is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU Lesser General Public License for more details.
  *
  * You should have received a copy of the Lesser GNU General Public License
  * along with sbcpd.  If not, see <http://www.gnu.org/licenses/>.
  */
 /**
  * \file sbcpd.h
  *
  *  \date Aug 15, 2011
  *  \author Alexandre Tuleu
  */
 
 #ifndef SBCPD_H_
 #define SBCPD_H_
 
 #include "common.h"
 #include "bus.h"
 #include "transfer.h"
 
-sbcpd_bus * sbcpd_default_oncilla_init();
+sbcpd_bus * sbcpd_default_oncilla_init(unsigned int master_id,
+                                       sbcpd_error * err);
 #endif //SBCPD_H_
diff --git a/sbcpd/si/ft2232h.c b/sbcpd/si/ft2232h.c
index 19675a6..71072cc 100644
--- a/sbcpd/si/ft2232h.c
+++ b/sbcpd/si/ft2232h.c
@@ -1,108 +1,122 @@
 /*
  * Copyright (c) 2011 Alexandre Tuleu <alexandre.tuleu.2005@polytechnique.org>
  * Ecole Polytechnique Fédérale de Lausanne.
  *
  * this file is part of sbcpd.
  *
  * sbcpd is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Lesser General Public License as published by
  * the Free Software Foundation, either version 3 of the License, or
  * (at your option) any later version.
  *
  * sbcpd is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU Lesser General Public License for more details.
  *
  * You should have received a copy of the Lesser GNU General Public License
  * along with sbcpd.  If not, see <http://www.gnu.org/licenses/>.
  */
 /**
  * \file ft2232h.c
  *
  *  \date Oct 10, 2011
  *  \author Alexandre Tuleu
  */
 
 
 #include "ft2232h.h"
 
 #include <sbcpd/ftdi/ft2232h.h>
 #include <ftdi.h>
 
 
 sbcpd_serial_interface * sbcpd_ft2232h_create_interface(){
 	sbcpd_serial_interface * si = malloc(sizeof(sbcpd_serial_interface));
 
 	struct ftdi_context * ftdi =  malloc(sizeof(struct ftdi_context));
 
 	int f;
 
 	if((f = ftdi_init(ftdi)) < 0){
 		//report it
 		return si;
 	}
 
 	si->dev = ftdi;
 	si->read_data  = &sbcpd_ft2232h_read;
 	si->write_data = &sbcpd_ft2232h_write;
 	si->close = &sbcpd_ft2232h_close;
 	si->free  = &sbcpd_ft2232h_free;
 	return si;
 
 }
 
 
 int sbcpd_ft2232h_open(sbcpd_serial_interface * si,
                        unsigned int baudrate,
                        unsigned char latency,
                        unsigned int interface){
 	ftdi_set_interface(si->dev, interface < 6? interface : 5 );
 
 	int f;
 	if((f = ftdi_usb_open(si->dev,0x403,0x6010)) < 0 ) {
-
-		return f;
+		si->error.code = SBCPD_ESI_CANNOT_ACCESS_DEVICE;
+		si->error.msg = ftdi_get_error_string(si->dev);
+		return SBCPD_ESI_CANNOT_ACCESS_DEVICE;
 	}
 
 	if ((f = ft2232h_set_baudrate(si->dev,baudrate)) < 0 ){
-
-		return f;
+		si->error.code = SBCPD_ESI_CONFIGURE_ERROR;
+		si->error.msg = ftdi_get_error_string(si->dev);
+		return SBCPD_ESI_CONFIGURE_ERROR;
 	}
 
 	if ((f = ft2232h_set_latency_timer(si->dev,latency)) < 0){
-
-		return f;
+		si->error.code = SBCPD_ESI_CONFIGURE_ERROR;
+		si->error.msg = ftdi_get_error_string(si->dev);
+		return SBCPD_ESI_CONFIGURE_ERROR;
 	}
 
 	if((f = ftdi_usb_purge_buffers(si->dev)) < 0){
-
+		si->error.code = SBCPD_ESI_CONFIGURE_ERROR;
+		si->error.msg = ftdi_get_error_string(si->dev);
+		return SBCPD_ESI_CONFIGURE_ERROR;
 	}
-	return 0;
+	return SBCPD_ESI_NO_ERROR;
 }
 
-int sbcpd_ft2232h_close(sbcpd_serial_interface *si){
+void sbcpd_ft2232h_close(sbcpd_serial_interface *si){
 	ftdi_deinit(si->dev);
-	return 0;
 }
 
 void sbcpd_ft2232h_free(sbcpd_serial_interface *si){
 	sbcpd_ft2232h_close(si);
 	ftdi_free(si->dev);
 }
 
-unsigned int sbcpd_ft2232h_write(sbcpd_serial_interface * si,
-                                 const uint8_t * data,
-                                 unsigned int size){
+int sbcpd_ft2232h_write(sbcpd_serial_interface * si,
+                        const uint8_t * data,
+                        int size){
 	int ret = ftdi_write_data(si->dev,(uint8_t*)data,size);
-	return ret >= 0 ? ret : 0;
+	if(ret < 0){
+		si->error.code = SBCPD_ESI_WRITE_ERROR;
+		si->error.msg  = ftdi_get_error_string(si->dev);
+		return SBCPD_ESI_WRITE_ERROR;
+	}
+	return ret;
 }
 
-unsigned int sbcpd_ft2232h_read(sbcpd_serial_interface * si,
-                                uint8_t * data,
-                                unsigned int size){
+int sbcpd_ft2232h_read(sbcpd_serial_interface * si,
+                       uint8_t * data,
+                       int size){
 	int ret = ftdi_read_data(si->dev,data,size);
-	return ret >= 0 ? ret : 0;
+	if(ret < 0){
+		si->error.code = SBCPD_ESI_READ_ERROR;
+		si->error.msg  = ftdi_get_error_string(si->dev);
+		return SBCPD_ESI_READ_ERROR;
+	}
+	return ret;
 }
 
 
diff --git a/sbcpd/si/ft2232h.h b/sbcpd/si/ft2232h.h
index b27ad3e..4448bcc 100644
--- a/sbcpd/si/ft2232h.h
+++ b/sbcpd/si/ft2232h.h
@@ -1,53 +1,53 @@
 /*
  * Copyright (c) 2011 Alexandre Tuleu <alexandre.tuleu.2005@polytechnique.org>
  * Ecole Polytechnique Fédérale de Lausanne.
  *
  * this file is part of sbcpd.
  *
  * sbcpd is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Lesser General Public License as published by
  * the Free Software Foundation, either version 3 of the License, or
  * (at your option) any later version.
  *
  * sbcpd is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU Lesser General Public License for more details.
  *
  * You should have received a copy of the Lesser GNU General Public License
  * along with sbcpd.  If not, see <http://www.gnu.org/licenses/>.
  */
 /**
  * \file ft2232.h
  *
  *  \date Oct 6, 2011
  *  \author Alexandre Tuleu
  */
 
 #ifndef SBCPD_SI_FT2232H_H_
 #define SBCPD_SI_FT2232H_H_
 
 
 #include "serial_interface.h"
 
 
 sbcpd_serial_interface * sbcpd_ft2232h_create_interface();
 
 int sbcpd_ft2232h_open(sbcpd_serial_interface * si, unsigned int baudrate,
                        unsigned char latency, unsigned int interface);
 
-int sbcpd_ft2232h_close(sbcpd_serial_interface * si);
+void sbcpd_ft2232h_close(sbcpd_serial_interface * si);
 
 void sbcpd_ft2232h_free(sbcpd_serial_interface * si);
 
-unsigned int sbcpd_ft2232h_write(sbcpd_serial_interface * si,
-                                 const uint8_t * data,
-                                 unsigned int size);
+int sbcpd_ft2232h_write(sbcpd_serial_interface * si,
+                        const uint8_t * data,
+                        int size);
 
-unsigned int sbcpd_ft2232h_read(sbcpd_serial_interface * si,
-                                uint8_t * data,
-                                unsigned int size);
+int sbcpd_ft2232h_read(sbcpd_serial_interface * si,
+                       uint8_t * data,
+                       int size);
 
 
 
 #endif // SBCPD_SI_FT2232_H_
diff --git a/sbcpd/si/serial_interface.h b/sbcpd/si/serial_interface.h
index 7545146..07c91ed 100644
--- a/sbcpd/si/serial_interface.h
+++ b/sbcpd/si/serial_interface.h
@@ -1,57 +1,71 @@
 /*
  * Copyright (c) 2011 Alexandre Tuleu <alexandre.tuleu.2005@polytechnique.org>
  * Ecole Polytechnique Fédérale de Lausanne.
  *
  * this file is part of sbcpd.
  *
  * sbcpd is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Lesser General Public License as published by
  * the Free Software Foundation, either version 3 of the License, or
  * (at your option) any later version.
  *
  * sbcpd is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU Lesser General Public License for more details.
  *
  * You should have received a copy of the Lesser GNU General Public License
  * along with sbcpd.  If not, see <http://www.gnu.org/licenses/>.
  */
 /**
  * \file serial_interface.h
  *
  *  \date Oct 6, 2011
  *  \author Alexandre Tuleu
  */
 
 #ifndef SBCPD_SI_SERIAL_INTERFACE_H_
 #define SBCPD_SI_SERIAL_INTERFACE_H_
 
 #include <stdint.h>
+#include <sbcpd/error.h>
+/**
+ * Errors that can be returned by the modules functions.
+ */
+enum sbcpd_serial_interface_error{
+	SBCPD_ESI_NO_ERROR             =  0,//!< SBCPD_ESI_NO_ERROR
+	SBCPD_ESI_CANNOT_ACCESS_DEVICE = -1,//!< SBCPD_ESI_CANNOT_ACCESS_DEVICE
+	SBCPD_ESI_CONFIGURE_ERROR      = -2,//!< SBCPD_ESI_CONFIGURE_ERROR
+	SBCPD_ESI_READ_ERROR           = -3,//!< SBCPD_ESI_READ_ERROR
+	SBCPD_ESI_WRITE_ERROR          = -4 //!< SBCPD_ESI_WRITE_ERROR
+};
 
 struct sbcpd_serial_interface;
 
 typedef struct sbcpd_serial_interface sbcpd_serial_interface;
 
-typedef unsigned int (*sbcpd_si_write) (sbcpd_serial_interface * dev,
+typedef int (*sbcpd_si_write) (sbcpd_serial_interface * dev,
                                const uint8_t * data,
-                               unsigned int size);
+                               int size);
 
-typedef unsigned int (*sbcpd_si_read)  (sbcpd_serial_interface * dev,
+typedef int (*sbcpd_si_read)  (sbcpd_serial_interface * dev,
                                uint8_t * data,
-                               unsigned int size);
+                               int size);
 
 
-typedef int (*sbcpd_si_close)(sbcpd_serial_interface * si);
+typedef void (*sbcpd_si_close)(sbcpd_serial_interface * si);
 typedef void (*sbcpd_si_free)(sbcpd_serial_interface * si);
 
-
+/**
+ * Represents a serial interface used to do Serial I/O from user space.
+ */
 struct sbcpd_serial_interface {
 	sbcpd_si_write        write_data;
 	sbcpd_si_read         read_data;
 	sbcpd_si_close        close;
 	sbcpd_si_free         free;
 	void * dev;
+	sbcpd_error           error;
 };
 
 #endif // SBCPD_SI_SERIAL_INTERFACE_H_