diff --git a/targets/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.c b/targets/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.c
index d515a206ae8e0683ff5ba4529107fe6fbb0b6f5a..c9ca8fedc653962ba217db816904e23b837f127c 100644
--- a/targets/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.c
+++ b/targets/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.c
@@ -185,7 +185,7 @@ int trx_brf_set_gains(openair0_device* device) {
 
 }
 
-int openair0_dev_init_bladerf(openair0_device *device, openair0_config_t *openair0_cfg) {
+int device_init(openair0_device *device, openair0_config_t *openair0_cfg, char *cfgfile) {
 
   int status;
   int card=0;
@@ -308,6 +308,7 @@ int openair0_dev_init_bladerf(openair0_device *device, openair0_config_t *openai
   printf("BLADERF: Initializing openair0_device\n");
   device->priv           = brf; 
   device->Mod_id         = num_devices++;
+  device->type             = BLADERF_DEV; 
   device->trx_start_func = trx_brf_start;
   device->trx_end_func   = trx_brf_end;
   device->trx_read_func  = trx_brf_read;
@@ -317,6 +318,31 @@ int openair0_dev_init_bladerf(openair0_device *device, openair0_config_t *openai
   device->trx_stop_func        = trx_brf_stop;
   device->trx_set_freq_func    = trx_brf_set_freq;
   device->trx_set_gains_func   = trx_brf_set_gains;
+
+  if(brf->sample_rate==30.72e6) {
+    openair0_cfg->tx_delay = 8;
+    openair0_cfg->tx_forward_nsamps = 175;
+    brf->tx_forward_nsamps  = 175;
+  }
+  if(brf->sample_rate==15.36e6) {
+    openair0_cfg->tx_delay = 5;
+    openair0_cfg->tx_forward_nsamps = 95;
+    brf->tx_forward_nsamps = 95;
+  }
+  if(brf->sample_rate==7.68e6) {
+    openair0_cfg->tx_delay = 8;
+    openair0_cfg->tx_forward_nsamps = 0;
+    brf->tx_forward_nsamps = 0;
+  }
+  if(brf->sample_rate==1.92e6) {
+    openair0_cfg->tx_delay = 8;
+    openair0_cfg->tx_forward_nsamps = 40;
+    brf->tx_forward_nsamps = 40;
+  }
+  
+  openair0_cfg->iq_txshift= 0;
+  openair0_cfg->iq_rxrescale = 15;
+
   memcpy((void*)&device->openair0_cfg,(void*)openair0_cfg,sizeof(openair0_config_t));
 
   return 0;
diff --git a/targets/ARCH/COMMON/common_lib.c b/targets/ARCH/COMMON/common_lib.c
index 8b91a74b4923ec5cc7d3f30c6dc87875a7c6d228..8fb07d7eb5a4f37ecca10a596a4b38c578002f18 100644
--- a/targets/ARCH/COMMON/common_lib.c
+++ b/targets/ARCH/COMMON/common_lib.c
@@ -37,28 +37,150 @@
  * \warning
  */
 #include <stdio.h>
+#include <strings.h>
+#include <dlfcn.h>
+#include <errno.h>
+#include <string.h>
+
 #include "common_lib.h"
 
+/* 
+   FT: The device interface is implemented in a shared library, the softmodem knows which kind
+   of harware is used by parsing the device name returned when calling the trx_getinfo_func function
+   provided by this shared library
+*/
+int set_device(openair0_device *device) {
+
+  switch (device->type) {
+    
+  case EXMIMO_DEV:
+    printf("[%s] has loaded EXPRESS MIMO device.\n",((device->host_type == BBU_HOST) ? "BBU": "RRH"));
+    return 0;     
+    break;
+  case USRP_DEV:
+    printf("[%s] has loaded USRP device.\n",((device->host_type == BBU_HOST) ? "BBU": "RRH")); 
+    return 0;
+    break;
+  case BLADERF_DEV:
+    printf("[%s] has loaded BLADERF device.\n",((device->host_type == BBU_HOST) ? "BBU": "RRH")); 
+    return 0;
+    break;
+  case NONE_DEV:
+    printf("[%s] has not loaded a HW device.\n",((device->host_type == BBU_HOST) ? "BBU": "RRH"));
+    return 0; 
+    break;    
+  default:
+    printf("[%s] invalid HW device.\n",((device->host_type == BBU_HOST) ? "BBU": "RRH")); 
+    return -1;
+    break;
+  }
+  
+}
+
+int set_transport(openair0_device *device) {
+
+  switch (device->transp_type) {
+    
+  case ETHERNET_TP:
+    printf("[%s] has loaded ETHERNET trasport protocol.\n",((device->host_type == BBU_HOST) ? "BBU": "RRH"));
+    return 0;     
+    break;
+  case NONE_TP:
+    printf("[%s] has not loaded a transport protocol.\n",((device->host_type == BBU_HOST) ? "BBU": "RRH"));
+    return 0; 
+    break;    
+  default:
+    printf("[%s] invalid transport protocol.\n",((device->host_type == BBU_HOST) ? "BBU": "RRH")); 
+    return -1;
+    break;
+  }
+  
+}
+
+/* FT: looking for the rh interface library and load it */
+int load_lib(openair0_device *device, openair0_config_t *openair0_cfg, char *cfgfile, uint8_t flag) {
+  
+  void *lib_handle;
+  char *OAI_RF_LIBNAME;
+  char *OAI_TP_LIBNAME;
+  oai_device_initfunc_t fp ;
+
+  if (device->host_type==BBU_HOST) {
+    OAI_RF_LIBNAME= "/home/guepe/openairinterface5g/cmake_targets/lte_noS1_build_oai/build/liboai_device.so";
+    OAI_TP_LIBNAME= "/home/guepe/openairinterface5g/cmake_targets/lte_noS1_build_oai/build/liboai_transpro.so";
+  } else {
+    OAI_RF_LIBNAME= "liboai_device.so";
+    OAI_TP_LIBNAME= "liboai_transpro.so";
+  }
+    
+    if (flag == RF_DEVICE) {
+      lib_handle = dlopen(OAI_RF_LIBNAME, RTLD_LAZY);
+      if (!lib_handle) {
+	printf( "Unable to locate %s: HW device set to NONE_DEV.\n", OAI_RF_LIBNAME);
+	return 0;
+      } 
+      
+      fp = dlsym(lib_handle,"device_init");
+      
+      if (fp != NULL ) {
+	fp(device,openair0_cfg,cfgfile);
+      } else {
+	fprintf(stderr, "%s %d:oai device intializing function not found %s\n", __FILE__, __LINE__, dlerror());
+	return -1;
+      }
+    } else {
+      lib_handle = dlopen(OAI_TP_LIBNAME, RTLD_LAZY);
+      if (!lib_handle) {
+	printf( "Unable to locate %s: transport protocol set to NONE_TP.\n", OAI_TP_LIBNAME);
+	return 0;
+      } 
+      
+      fp = dlsym(lib_handle,"transport_init");
+      
+      if (fp != NULL ) {
+	fp(device,openair0_cfg,cfgfile);
+      } else {
+	fprintf(stderr, "%s %d:oai device intializing function not found %s\n", __FILE__, __LINE__, dlerror());
+	return -1;
+      }
+    } 
+    
+  return 0; 	       
+}
+
+
+
+int openair0_device_load(openair0_device *device, openair0_config_t *openair0_cfg) {
+  
+  int rc;
+  static char   *cfgfile;
+  uint8_t       flag=RF_DEVICE;
+  /* FT: rewritten for shared library, common, radio head interface implementation */
+  rc=load_lib(device, openair0_cfg, NULL,flag);
+  if ( rc >= 0) {       
+    if ( set_device(device) < 0) {
+      fprintf(stderr, "%s %d:Unsupported radio head\n",__FILE__, __LINE__);
+      return -1;		   
+    }   
+  }
+  
+  return 0;
+}
+
+int openair0_transport_load(openair0_device *device, openair0_config_t *openair0_cfg) {
+  
+  int rc;
+  static char   *cfgfile;
+  uint8_t       flag=TRANSPORT_PROTOCOL;
 
-int openair0_device_init(openair0_device *device, openair0_config_t *openair0_cfg) {
+  /* FT: rewritten for shared library, common, radio head interface implementation */
+  rc=load_lib(device, openair0_cfg, NULL,flag);
+  if ( rc >= 0) {       
+    if ( set_transport(device) < 0) {
+      fprintf(stderr, "%s %d:Unsupported radio head\n",__FILE__, __LINE__);
+      return -1;		   
+    }   
+  }
   
-#ifdef ETHERNET 
-  device->type=ETH_IF; 
-  device->func_type = BBU_FUNC;
-  openair0_dev_init_eth(device, openair0_cfg);
-  printf(" openair0_dev_init_eth ...\n");
-#elif EXMIMO
-  device->type=EXMIMO_IF;
-  openair0_dev_init_exmimo(device, openair0_cfg);
-  printf("openair0_dev_init_exmimo...\n");
-#elif OAI_USRP
-  device->type=USRP_IF;
-  openair0_dev_init_usrp(device, openair0_cfg);
-  printf("openair0_dev_init_usrp ...\n");
-#elif OAI_BLADERF  
-  device->type=BLADERF_IF;
-  openair0_dev_init_bladerf(device, openair0_cfg);	
-  printf(" openair0_dev_init_bladerf ...\n");   
-#endif 
-   
+  return 0;
 }
diff --git a/targets/ARCH/COMMON/common_lib.h b/targets/ARCH/COMMON/common_lib.h
index 8cc7926d4571158f210eb976dd3df102f4d2a510..0b4825714b273d58bd10f0a8b3c50cdf0ac64ae3 100644
--- a/targets/ARCH/COMMON/common_lib.h
+++ b/targets/ARCH/COMMON/common_lib.h
@@ -42,6 +42,22 @@
 #include <stdint.h>
 #include <sys/types.h>
 
+/* name of shared library implementing the radio front end */
+#define OAI_RF_LIBNAME        "liboai_device.so"
+/* name of shared library implementing the transport */
+#define OAI_TP_LIBNAME        "liboai_transpro.so"
+
+/* flags for BBU to determine whether RF front end is local or remote 
+Note: currently lte-softmodem supports either a local RF device or a remote. */
+#define BBU_LOCAL_RF_ENABLED 1
+#define BBU_REMOTE_RF_ENABLED 2
+#define BBU_LOCAL_REMOTE_RF_ENABLED 3
+/*flags for load_lib() used to specify whether a RF device or a transport protocol library is loaded */
+#define TRANSPORT_PROTOCOL 1
+#define RF_DEVICE 2
+
+
+
 typedef int64_t openair0_timestamp;
 typedef volatile int64_t openair0_vtimestamp;
 
@@ -75,7 +91,7 @@ typedef struct {
   //! Module ID for this configuration
   int Mod_id;
   // device log level
-  int log_level;
+  unsigned int log_level;
   //! number of downlink resource blocks
   int num_rb_dl;
   //! number of samples per frame 
@@ -83,12 +99,15 @@ typedef struct {
   //! the sample rate for both transmit and receive.
   double sample_rate;
   //! number of samples per RX/TX packet (USRP + Ethernet)
-  int samples_per_packet;
+  unsigned int samples_per_packet;
   // delay in sending samples (write)  due to hardware access, softmodem processing and fronthaul delay if exist
   int tx_delay;
   //! adjust the position of the samples after delay when sending   
   unsigned int	tx_forward_nsamps;
-  //! number of RX channels (=RX antennas)
+  //! configurable tx thread lauch delay 
+  int txlaunch_wait;               /* 1 or 0 */
+  int txlaunch_wait_slotcount;
+  //! number of RX channels (=RX antennas)  
   int rx_num_channels;
   //! number of TX channels (=TX antennas)
   int tx_num_channels;
@@ -114,14 +133,18 @@ typedef struct {
   double tx_bw;
   //! Auto calibration flag
   int autocal[4];
-  //! RRH IP addr for Ethernet interface
-  char *remote_ip;
-  //! RRH port number for Ethernet interface
-  int remote_port;
-  //! my IP addr for Ethernet interface (eNB/BBU, UE)
-  char *my_ip;
-  //! my port number for Ethernet interface (eNB/BBU, UE)
-  int my_port;
+  //! rf devices work with x bits iqs when oai have its own iq format
+  //! the two following parameters are used to convert iqs 
+  int iq_txshift;
+  int iq_rxrescale;
+  //! remote IP/MAC addr for Ethernet interface
+  char *remote_addr;
+  //! remote port number for Ethernet interface
+  unsigned int remote_port;
+  //! local IP/MAC addr for Ethernet interface (eNB/BBU, UE)
+  char *my_addr;
+  //! local port number for Ethernet interface (eNB/BBU, UE)
+  unsigned int my_port;
 
 } openair0_config_t;
 
@@ -134,55 +157,63 @@ typedef struct {
 
 
 
-/*!\brief interface types that apply to modules (RRH_BBU/RRH_UE) created in RRH (rrh_gw.c)
-          and are defined with respect to the RF device that is present in RRH
-          -RRH_BBU modules have two devices, one is by default ETHERNET (will have ETH_IF) and the other one is a
-	  RF device (EXMIMO,USRP,BLADERF) or no device (NONE_IF).
-          -RRH_UE modules have two devices one is by default ETHERNET (will have ETH_IF) 
-	  and the other one by default not present so it will have NONE_IF
+/*!\brief RF device types
  */
 typedef enum {
-  MIN_DEV_TYPE = 0,
-  /*!\brief device is ETH */
-  ETH_IF,
+  MIN_RF_DEV_TYPE = 0,
   /*!\brief device is ExpressMIMO */
-  EXMIMO_IF,
+  EXMIMO_DEV,
   /*!\brief device is USRP*/
-  USRP_IF,
+  USRP_DEV,
   /*!\brief device is BLADE RF*/
-  BLADERF_IF,
+  BLADERF_DEV,
   /*!\brief device is NONE*/
-  NONE_IF,
-  MAX_DEV_TYPE
+  NONE_DEV,
+  MAX_RF_DEV_TYPE
 
 } dev_type_t;
 
+/*!\brief transport protocol types
+ */
+typedef enum {
+  MIN_TRANSP_TYPE = 0,
+  /*!\brief transport protocol ETHERNET */
+  ETHERNET_TP,
+  /*!\brief no transport protocol*/
+  NONE_TP,
+  MAX_TRANSP_TYPE
+
+} transport_type_t;
+
 
 /*!\brief  openair0 device host type */
 typedef enum {
-  MIN_FUNC_TYPE = 0,
+  MIN_HOST_TYPE = 0,
  /*!\brief device functions within a BBU */
-  BBU_FUNC,
+  BBU_HOST,
  /*!\brief device functions within a RRH */
-  RRH_FUNC,
-  MAX_FUNC_TYPE
+  RRH_HOST,
+  MAX_HOST_TYPE
 
-}func_type_t;
+}host_type_t;
 
 struct openair0_device_t {
-  /* Module ID of this device */
+  /*!brief Module ID of this device */
   int Mod_id;
   
-  /* Type of this device */
+  /*!brief Type of this device */
   dev_type_t type;
 
-   /* Type of the device's host (BBU/RRH) */
-  func_type_t func_type;
+  /*!brief Transport protocol type that the device suppports (in case I/Q samples need to be transported) */
+  transport_type_t transp_type;
+
+   /*!brief Type of the device's host (BBU/RRH) */
+  host_type_t host_type;
 
-  /* RF frontend parameters set by application */
+  /*!brief RF frontend parameters set by application */
   openair0_config_t openair0_cfg;
 
-  /* Can be used by driver to hold internal structure*/
+  /*!brief Can be used by driver to hold internal structure*/
   void *priv;
 
   /* Functions API, which are called by the application*/
@@ -263,28 +294,25 @@ struct openair0_device_t {
 
 };
 
+/* type of device init function, implemented in shared lib */
+typedef int(*oai_device_initfunc_t)(openair0_device *device, openair0_config_t *openair0_cfg, char *cfgfile);
 
 #ifdef __cplusplus
 extern "C"
 {
 #endif
 
-/*! \brief Initialize Openair RF target. It returns 0 if OK */
-  int openair0_device_init(openair0_device* device, openair0_config_t *openair0_cfg);
+  /*! \brief Initialize openair RF target. It returns 0 if OK */
+  int openair0_device_load(openair0_device *device, openair0_config_t *openair0_cfg);  
+  /*! \brief Initialize transport protocol . It returns 0 if OK */
+  int openair0_transport_load(openair0_device *device, openair0_config_t *openair0_cfg);
   
   //USRP
 /*! \brief Get the current timestamp of USRP */
   openair0_timestamp get_usrp_time(openair0_device *device);
 /*! \brief Set the RX frequency of USRP RF TARGET */
   int openair0_set_rx_frequencies(openair0_device* device, openair0_config_t *openair0_cfg);
-  
-//extern
-/*! \brief Initialize Openair ETHERNET target. It returns 0 if OK */
-  int openair0_dev_init_eth(openair0_device *device, openair0_config_t *openair0_cfg);
-  int openair0_dev_init_bladerf(openair0_device *device, openair0_config_t *openair0_cfg);
-  int openair0_dev_init_usrp(openair0_device* device, openair0_config_t *openair0_cfg);
-  int openair0_dev_init_exmimo(openair0_device *device, openair0_config_t *openair0_cfg);
-/*@}*/
+
 
 #ifdef __cplusplus
 }
diff --git a/targets/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c b/targets/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c
index df9900d3bc98720090143b73c2989a30ad0868ea..05105d60df1c01ea9b39fc52a530ebf171fcc9a0 100644
--- a/targets/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c
+++ b/targets/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c
@@ -247,7 +247,7 @@ int openair0_stop_without_reset(int card)
 #define MY_RF_MODE      (RXEN + TXEN + TXLPFNORM + TXLPFEN + TXLPF25 + RXLPFNORM + RXLPFEN + RXLPF25 + LNA1ON +LNAMax + RFBBNORM + DMAMODE_RX + DMAMODE_TX)
 #define RF_MODE_BASE    (LNA1ON + RFBBNORM)
 
-int openair0_dev_init_exmimo(openair0_device *device, openair0_config_t *openair0_cfg) {
+int device_init(openair0_device *device, openair0_config_t *openair0_cfg, char *cfgfile) {
 
   // Initialize card
   //  exmimo_config_t         *p_exmimo_config;
@@ -287,6 +287,8 @@ int openair0_dev_init_exmimo(openair0_device *device, openair0_config_t *openair
     return(-1);
   }
 
+  device->type             = EXMIMO_DEV; 
+
   return(0);
 }
 
diff --git a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp
index e57f55720b14fbb7605fc41e6ab091a61cc7755d..00a0a93116d008603ade4fcec99eabbd7f40a254 100644
--- a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp
+++ b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp
@@ -329,8 +329,9 @@ int trx_usrp_reset_stats(openair0_device* device) {
 }
 
 
-int openair0_dev_init_usrp(openair0_device* device, openair0_config_t *openair0_cfg)
-{
+extern "C" {
+  int device_init(openair0_device* device, openair0_config_t *openair0_cfg, char *cfgfile) {
+    
   uhd::set_thread_priority_safe(1.0);
   usrp_state_t *s = (usrp_state_t*)malloc(sizeof(usrp_state_t));
   memset(s, 0, sizeof(usrp_state_t));
@@ -364,7 +365,7 @@ int openair0_dev_init_usrp(openair0_device* device, openair0_config_t *openair0_
 
     }
 
-    printf("Found USRP X300\n");
+ printf("Found USRP X300\n");
     s->usrp = uhd::usrp::multi_usrp::make(args);
     //  s->usrp->set_rx_subdev_spec(rx_subdev);
     //  s->usrp->set_tx_subdev_spec(tx_subdev);
@@ -475,6 +476,7 @@ int openair0_dev_init_usrp(openair0_device* device, openair0_config_t *openair0_
   std::cout << boost::format("Device timestamp: %f...") % (s->usrp->get_time_now().get_real_secs()) << std::endl;
 
   device->priv = s;
+  device->type             = USRP_DEV; 
   device->trx_start_func = trx_usrp_start;
   device->trx_write_func = trx_usrp_write;
   device->trx_read_func  = trx_usrp_read;
@@ -488,11 +490,37 @@ int openair0_dev_init_usrp(openair0_device* device, openair0_config_t *openair0_
   s->sample_rate = openair0_cfg[0].sample_rate;
   // TODO:
   // init tx_forward_nsamps based usrp_time_offset ex
-  if(is_equal(s->sample_rate, (double)30.72e6))
+  /*if(is_equal(s->sample_rate, (double)30.72e6))
     s->tx_forward_nsamps  = 176;
   if(is_equal(s->sample_rate, (double)15.36e6))
     s->tx_forward_nsamps = 90;
   if(is_equal(s->sample_rate, (double)7.68e6))
-    s->tx_forward_nsamps = 50;
+    s->tx_forward_nsamps = 50;*/
+/* move device specific parameters from lte-softmodem.c here */
+    if(is_equal(s->sample_rate, (double)30.72e6)) {
+      openair0_cfg->tx_delay = 8;
+      s->tx_forward_nsamps  = 175;
+      openair0_cfg->tx_forward_nsamps  = 175;
+    }
+    if(is_equal(s->sample_rate, (double)15.36e6)) {
+      openair0_cfg->tx_delay = 5;
+      s->tx_forward_nsamps = 95;
+      openair0_cfg->tx_forward_nsamps = 95;
+    }
+    if(is_equal(s->sample_rate, (double)7.68e6)) {
+      openair0_cfg->tx_delay = 5;
+      s->tx_forward_nsamps = 70;
+      openair0_cfg->tx_forward_nsamps = 70;
+    }
+    if(is_equal(s->sample_rate, (double)1.92e6)) {
+      openair0_cfg->tx_delay = 8;
+      s->tx_forward_nsamps = 40;
+      openair0_cfg->tx_forward_nsamps = 40;
+    }
+    openair0_cfg->iq_txshift= 5;
+    openair0_cfg->iq_rxrescale = 15;
+    printf("check params %d:%d",openair0_cfg->tx_forward_nsamps, openair0_cfg->tx_delay);
+   
   return 0;
 }
+}
\ No newline at end of file