gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[taler-taler-mdb] 06/23: major mdb refactoring


From: gnunet
Subject: [taler-taler-mdb] 06/23: major mdb refactoring
Date: Wed, 04 Dec 2019 14:15:52 +0100

This is an automated email from the git hooks/post-receive script.

grothoff pushed a commit to branch master
in repository taler-mdb.

commit ffcbd9152a3443346ab95bcc637250191b617a58
Author: Christian Grothoff <address@hidden>
AuthorDate: Wed Dec 4 12:26:29 2019 +0100

    major mdb refactoring
---
 src/Makefile.am    |   3 +-
 src/main.c         | 765 ++++++++++++++++++++++++++++++++++++++++-------------
 src/mdb/.gitkeep   |   0
 src/mdb/mdb_uart.c | 362 -------------------------
 src/mdb/mdb_uart.h |  83 ------
 5 files changed, 579 insertions(+), 634 deletions(-)

diff --git a/src/Makefile.am b/src/Makefile.am
index 808739e..4b5e750 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -7,8 +7,7 @@ if USE_COVERAGE
 endif
 
 taler_mdb_SOURCES = \
-  main.c \
-  mdb/mdb_uart.c
+  main.c 
 taler_mdb_LDADD = \
   -ltalermerchant \
   -ltalerjson \
diff --git a/src/main.c b/src/main.c
index eaa6b1f..a1dac68 100644
--- a/src/main.c
+++ b/src/main.c
@@ -53,7 +53,11 @@ along with
 #include <linux/fb.h>
 #endif
 
-#include "mdb/mdb_uart.h"
+/* Constants */
+#define MAX_SIZE_RX_BUFFER 256
+
+/* Constants */
+#define MAX_SIZE_TX_BUFFER 256
 
 /**
  * Disable i18n support.
@@ -113,19 +117,13 @@ along with
 #define READER_REVALUE_APPROVED "0D"
 #define READER_REVALUE_DENIED "0E"
 
-/* Constants */
-#define MAX_SIZE_RX_BUFFER 256
-
-/* Macro for char to hex conversion */
-#define convertChar2Hex(C) (((C) >= 'A' && (C) <= 'F') ? ((C) -55) : ((C) \
-                                                                      - '0'))
 
 /**
  * @brief FRAMEBUFFER_DEVICE framebuffer device to diplay qr code
  */
-const char *FRAMEBUFFER_DEVICE = "/dev/fb1";
+static const char *FRAMEBUFFER_DEVICE = "/dev/fb1";
 
-const char *UART_DEVICE = "/dev/ttyAMA0";
+static const char *UART_DEVICE = "/dev/ttyAMA0";
 
 /**
   * Taler wallet application identifier
@@ -146,6 +144,23 @@ static const uint8_t put_data[] = { 0x00, 0xDA, 0x01, 
0x00, 0x7c, 0x01 };
 static const uint8_t get_data[] = { 0x00, 0xCA, 0x01, 0x00, 0x00, 0x00 };
 #endif
 
+
+struct MdbBlock
+{
+  uint8_t*bin;
+  size_t bin_size;
+};
+
+
+/* Datatype for mdb command */
+struct mdbCmd
+{
+  const char *name;
+  struct MdbBlock cmd;
+  struct MdbBlock data;
+};
+
+
 /**
  * Struct holding the information for a product to sell
  */
@@ -164,7 +179,7 @@ struct Product
   /**
    * Number of the product in the vending machine
    */
-  char *number;
+  unsigned long long number;
 
   /**
    * Key for the product (optional, needed to test the application without 
vending machine)
@@ -225,13 +240,42 @@ struct PaymentActivity
   int wallet_has_uri;
 };
 
+#define MAX_ACK_LATENCY GNUNET_TIME_UNIT_SECONDS
+
 struct mdbHandle
 {
   int uartfd;
   struct mdbCmd *cmd;
+  struct mdbCmd *last_cmd;
   int session_running;
+
+  struct GNUNET_TIME_Absolute ack_timeout;
+
+  uint8_t rxBuffer[MAX_SIZE_RX_BUFFER];
+
+  size_t rx_off;
+
+  struct GNUNET_SCHEDULER_Task *rtask;
+
+  uint8_t txBuffer[MAX_SIZE_TX_BUFFER];
+
+  /**
+   * Current write offset in @e txBuffer.
+   */
+  size_t tx_off;
+
+  /**
+   * Number of bytes in @e txBuffer with the serialized data of the
+   * @e last_cmd.
+   */
+  size_t tx_len;
+
+  struct GNUNET_SCHEDULER_Task *wtask;
+
+  struct termios uart_opts_backup;
 };
 
+
 /**
  * Handle for the Framebuffer device
  */
@@ -278,12 +322,16 @@ static nfc_context *context;
  */
 static int global_ret;
 
+/**
+ * Flag set to remember that we are in shutdown.
+ */
+static int in_shutdown;
+
 /**
  * Refenence to the keyboard task
  */
 static struct GNUNET_SCHEDULER_Task *keyboard_task;
 
-static struct GNUNET_SCHEDULER_Task *mdb_task;
 /**
  * Curl context for communication with taler backend
  */
@@ -335,17 +383,20 @@ static struct Product *products;
 static unsigned int products_length;
 
 static struct mdbHandle mdb;
-struct mdbCmd *readerConfigData;
-struct mdbCmd *beginSession;
-struct mdbCmd *denyVend;
-struct mdbCmd *approveVend;
-struct mdbCmd *endSession;
+
+struct mdbCmd readerConfigData;
+struct mdbCmd beginSession;
+struct mdbCmd denyVend;
+struct mdbCmd approveVend;
+struct mdbCmd endSession;
+
 
 /**
  * Handle for the framebuffer device
  */
 static struct Display qrDisplay;
 
+
 #if HAVE_QRENCODE_H
 #include <qrencode.h>
 
@@ -439,6 +490,53 @@ show_qrcode (const char *uri)
 
 #endif
 
+
+static void
+parse_block (struct MdbBlock *blk,
+             const char *hex)
+{
+  if (NULL == hex)
+  {
+    blk->bin_size = 0;
+    blk->bin = NULL;
+    return;
+  }
+  blk->bin_size = strlen (hex) / 2;
+  blk->bin = GNUNET_malloc (blk->bin_size);
+  for (size_t idx = 0; idx < blk->bin_size; idx++)
+  {
+    unsigned int val;
+
+    GNUNET_assert (1 ==
+                   sscanf (&hex[idx * 2],
+                           "%2X",
+                           &val));
+    blk->bin[idx] = (uint8_t) val;
+  }
+}
+
+
+struct mdbCmd
+setup_mdb_cmd (const char *name,
+               const char *cmd,
+               const char *data)
+{
+  struct mdbCmd cmdNew;
+
+  cmdNew.name = (NULL == name)
+                ? "No Cmd Name Set"
+                : name;
+  parse_block (&cmdNew.cmd, cmd);
+  parse_block (&cmdNew.data, data);
+  return cmdNew;
+}
+
+
+static void
+start_mdb (void);
+
+
+
 /**
  * Cleanup all the data when a order has succeeded or got cancelled
  * @param pa the payment activity to clean up
@@ -459,11 +557,6 @@ cleanup_payment (struct PaymentActivity *pa)
     GNUNET_SCHEDULER_cancel (pa->task);
   if (NULL != pa->delay_task)
     GNUNET_SCHEDULER_cancel (pa->delay_task);
-  if (0 < mdb.uartfd)
-  {
-    mdb.cmd = NULL;
-               sendMdbCmd(endSession, mdb.uartfd);
-  }
   if (NULL != pa->taler_pay_uri)
   {
 #if HAVE_QRENCODE_H
@@ -481,6 +574,38 @@ cleanup_payment (struct PaymentActivity *pa)
   GNUNET_free (pa);
 }
 
+
+static void
+mdb_shutdown ()
+{
+  if (NULL != mdb.rtask)
+  {
+    GNUNET_SCHEDULER_cancel (mdb.rtask);
+    mdb.rtask = NULL;
+  }
+  if (NULL != mdb.wtask)
+  {
+    GNUNET_SCHEDULER_cancel (mdb.wtask);
+    mdb.wtask = NULL;
+  }
+
+  /* restore UART */
+  if (0 != tcsetattr (mdb.uartfd,
+                      TCSAFLUSH,
+                      &mdb.uart_opts_backup))
+  {
+    printf ("Failed to restore uart discipline\n");
+    global_ret = EXIT_FAILURE;
+  }
+  if (-1 != mdb.uartfd)
+  {
+    (void) close (mdb.uartfd);
+    mdb.uartfd = -1;
+  }
+
+}
+
+
 /**
  * Shutdown the application.
  * @param cls closure
@@ -508,14 +633,10 @@ shutdown_task (void *cls)
     GNUNET_SCHEDULER_cancel (keyboard_task);
     keyboard_task = NULL;
   }
-  if (NULL != mdb_task)
-  {
-    GNUNET_SCHEDULER_cancel (mdb_task);
-    mdb_task = NULL;
-  }
-  if (0 < mdb.uartfd){
-               sendMdbCmd(endSession, mdb.uartfd);
-       }       
+  /* last ditch saying nicely goodbye to MDB */
+  in_shutdown = GNUNET_YES;
+  mdb.cmd = &endSession;
+  start_mdb ();
   if (NULL != ctx)
   {
     GNUNET_CURL_fini (ctx);
@@ -526,6 +647,7 @@ shutdown_task (void *cls)
     GNUNET_CURL_gnunet_rc_destroy (rc);
     rc = NULL;
   }
+
   if (NULL != qrDisplay.memory)
   {
     /* free the display data  */
@@ -550,10 +672,7 @@ shutdown_task (void *cls)
   if (NULL != products)
   {
     for (unsigned int i = 0; i < products_length; i++)
-    {
       GNUNET_free (products[i].description);
-      GNUNET_free (products[i].number);
-    }
     GNUNET_array_grow (products,
                        products_length,
                        0);
@@ -808,7 +927,8 @@ check_payment_cb (void *cls,
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                 "Backend request to /check-payment failed: %u",
                 http_status);
-    sendMdbCmd (denyVend, mdb.uartfd);
+    mdb.cmd = &denyVend;
+    start_mdb ();
     cleanup_payment (pa);
     GNUNET_assert (payment_activity == pa);
     payment_activity = NULL;
@@ -817,7 +937,7 @@ check_payment_cb (void *cls,
 
   if (paid)
   {
-    sendMdbCmd (approveVend, mdb.uartfd);
+    mdb.cmd = &approveVend;
     cleanup_payment (pa);
     GNUNET_assert (payment_activity == pa);
     payment_activity = NULL;
@@ -897,6 +1017,8 @@ proposal_cb (void *cls,
                 "Failed to setup order with backend: %u/%d\n",
                 http_status,
                 (int) ec);
+    mdb.cmd = &denyVend;
+    start_mdb ();
     cleanup_payment (pa);
     GNUNET_assert (payment_activity == pa);
     payment_activity = NULL;
@@ -979,6 +1101,7 @@ launch_payment (const struct Product *product)
 static void
 start_read_keyboard (void);
 
+
 /**
  * Read the character from stdin and activate the selected task
  * @param cls closure
@@ -1001,8 +1124,8 @@ read_keyboard_command (void *cls)
   {
     if (NULL != payment_activity)
     {
-                       sendMdbCmd(denyVend, mdb.uartfd);
-                       sleep(2);
+      mdb.cmd = &denyVend;
+      start_mdb ();
       cleanup_payment (payment_activity);
       payment_activity = NULL;
     }
@@ -1055,105 +1178,377 @@ start_read_keyboard ()
                                                   NULL);
 }
 
-static void
-start_read_mdb (void);
 
 static void
-read_mdb_command (void *cls)
+write_mdb_command (void *cls)
 {
-  (void) cls;
-  char* input;
-
-  mdb_task = NULL;
-  input =  receiveMdbCmd (mdb.uartfd);
-
-  /* FIXME SHUTDOWN ? */
+  int did_write = 0;
 
-  if (NULL != input)
+  (void) cls;
+  mdb.wtask = NULL;
+  if (mdb.tx_off < mdb.tx_len)
   {
-    if (0 == strcmp ("Config Data", input))
-    {
-       printf("%s\n", input); 
-                       mdb.cmd = readerConfigData;
-    }
-    else if (0 == strcmp ("Reader Enable", input))
+    ssize_t ret = write (mdb.uartfd,
+                         &mdb.txBuffer[mdb.tx_off],
+                         mdb.tx_len - mdb.tx_off);
+
+    did_write = 1;
+    if (-1 == ret)
     {
-      mdb.cmd = beginSession;
+      GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
+                                "write",
+                                UART_DEVICE);
+      GNUNET_SCHEDULER_shutdown ();
+      return;
     }
-    else if (0 == strcmp ("Command out of Sequence", input))
+    mdb.tx_off += ret;
+    if ( (ret > 0) &&
+         (mdb.tx_off == mdb.tx_len) )
+      mdb.ack_timeout = GNUNET_TIME_relative_to_absolute (MAX_ACK_LATENCY);
+  }
+  /* ongoing write incomplete, continue later */
+  if (mdb.tx_off < mdb.tx_len)
+  {
+    start_mdb ();
+    return;
+  }
+  if (NULL != mdb.last_cmd)
+  {
+    struct GNUNET_TIME_Relative del;
+
+    /* Still waiting for ACK! */
+    del = GNUNET_TIME_absolute_get_remaining (mdb.ack_timeout);
+    if (0 != del.rel_value_us)
     {
-      mdb.cmd = beginSession;
+      if (did_write)
+        start_mdb ();
+      else
+        mdb.wtask = GNUNET_SCHEDULER_add_delayed (del,
+                                                  &write_mdb_command,
+                                                  NULL);
+      return;
     }
-    else if (0 == strcmp ("Resend previous data", input))
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "MDB failed to acknowledge command `%s' within timeout\n",
+                mdb.last_cmd->name);
+    mdb.last_cmd = NULL;
+    if (in_shutdown)
     {
-      sendMdbCmd (mdb.cmd, mdb.uartfd);
+      mdb_shutdown ();
+      return;
     }
-    else if (0 == strncmp ("Vend Request", input, strlen ("Vend Request")))
+  }
+  if (NULL == mdb.cmd)
+    return;
+  mdb.tx_off = 0;
+  mdb.tx_len = mdb.cmd->cmd.bin_size + mdb.cmd->data.bin_size + 1;
+  GNUNET_assert (mdb.tx_len <= sizeof (mdb.txBuffer));
+  {
+    uint32_t chkSum = 0;
+
+    for (size_t idx = 0; idx < mdb.cmd->cmd.bin_size; idx++)
+      chkSum += mdb.txBuffer[idx] = mdb.cmd->cmd.bin[idx];
+    for (size_t idx = 0; idx < mdb.cmd->data.bin_size; idx++)
+      chkSum += mdb.txBuffer[idx + mdb.cmd->cmd.bin_size] =
+        mdb.cmd->data.bin[idx];
+    mdb.txBuffer[mdb.cmd->cmd.bin_size + mdb.cmd->data.bin_size] =
+      (uint8_t) (chkSum & 0xFF);
+  }
+  mdb.last_cmd = mdb.cmd;
+  mdb.cmd = NULL;
+  start_mdb ();
+}
+
+
+/**
+ *
+ * @param hex_len number of characters in @a hex
+ */
+static void
+handle_command (const char *hex,
+                size_t hex_len)
+{
+  unsigned int cmd;
+
+  if (0 == hex_len)
+    return;
+  if (0 != (hex_len % 2))
+  {
+    GNUNET_break_op (0);
+    return;
+  }
+  if (1 != sscanf (hex,
+                   "%2X",
+                   &cmd))
+  {
+    GNUNET_break_op (0);
+    return;
+  }
+  switch (cmd)
+  {
+  case 0x13:
     {
-       mdb.cmd = NULL; 
-                       printf("%s\n", input); 
-                       printf("%s", &input[strlen("Vend request for: ")]);
-                       for (unsigned int i = 0; i < products_length; i++){
-        if (0 == strncmp (&input[strlen ("Vend Request for: ")],
-                         products[i].number,1))
+      unsigned int subcmd;
+
+      if (4 < hex_len)
+      {
+        GNUNET_break_op (0);
+        return;
+      }
+      if (1 != sscanf (&hex[2],
+                       "%2X",
+                       &subcmd))
+      {
+        GNUNET_break_op (0);
+        return;
+      }
+      switch (subcmd)
+      {
+      case 0x00:
         {
-          payment_activity = launch_payment (&products[i]);
-          start_read_mdb ();
-          return;
+          unsigned int product;
+
+          /* NOTE: hex[4..7] contain the price */
+          if (12 < hex_len)
+          {
+            GNUNET_break_op (0);
+            return;
+          }
+          if (1 != sscanf (&hex[8],
+                           "%4X",
+                           &product))
+          {
+            GNUNET_break_op (0);
+            return;
+          }
+          for (unsigned int i = 0; i < products_length; i++)
+            if (product == products[i].number)
+            {
+              payment_activity = launch_payment (&products[i]);
+              return;
+            }
+          GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                      "Unknown product %u selected, denying vend\n",
+                      product);
+          mdb.cmd = &denyVend;
+          break;
         }
-                       }
-                       mdb.cmd = denyVend;
-
-    }
-    else if (0 == strcmp ("Vend Success", input))
-    {
+      case 0x02:
+        GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                    "Vend Success");
+        break;
+      case 0x03:
+        {
+          mdb.cmd = &endSession;
+          mdb.session_running = GNUNET_NO;
+          GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                      "Vend Failure");
+          /* FIXME: refund logic here! */
+          if (NULL != payment_activity)
+          {
+            cleanup_payment (payment_activity);
+            payment_activity = NULL;
+          }
+          break;
+        }
+      case 0x04:
+        {
+          GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                      "Session Complete");
+          mdb.session_running = GNUNET_NO;
+          mdb.cmd = &endSession;
+          cleanup_payment (payment_activity);
+          payment_activity = NULL;
+        }
+        break;
+      default:
+        GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                    "Unknown MDB sub-command %X of command %X\n",
+                    subcmd,
+                    cmd);
+        break;
+      }
+      break;
     }
-    else if (0 == strcmp ("Vend Failure", input))
+  case 0x11:
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "Received request for configuration");
+    mdb.cmd = &readerConfigData;
+    break;
+  case 0x14:
     {
-      mdb.cmd = endSession;
-      if (NULL != payment_activity)
+      unsigned int subcmd;
+
+      if (4 < hex_len)
       {
-        cleanup_payment (payment_activity);
-        payment_activity = NULL;
+        GNUNET_break_op (0);
+        return;
+      }
+      if (1 != sscanf (&hex[2],
+                       "%2X",
+                       &subcmd))
+      {
+        GNUNET_break_op (0);
+        return;
       }
+
+      switch (subcmd)
+      {
+      case 0x01:
+        GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                    "Received Reader Enable");
+        mdb.session_running = GNUNET_NO;
+        break;
+      default:
+        GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                    "Unknown MDB sub-command %X of command %X\n",
+                    subcmd,
+                    cmd);
+        break;
+      }
+      break;
     }
-    else if (0 == strcmp ("Session Complete", input))
+  case 0x00:
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "Received Acknowledge (for %s)",
+                (NULL != mdb.last_cmd) ? mdb.last_cmd->name : "?");
+    if (&beginSession == mdb.last_cmd)
+      mdb.session_running = GNUNET_YES;
+    if (&denyVend == mdb.last_cmd)
+      mdb.cmd = &endSession;
+    mdb.last_cmd = NULL;
+    if (NULL != mdb.wtask)
     {
-      sendMdbCmd (endSession, mdb.uartfd);
-      cleanup_payment (payment_activity);
-      payment_activity = NULL;
+      GNUNET_SCHEDULER_cancel (mdb.wtask);
+      mdb.wtask = NULL;
     }
-    else
+    if (in_shutdown)
     {
-      mdb.cmd = NULL;
+      mdb_shutdown ();
+      return;
     }
+    break;
+  case 0xB0:
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "Received Command out of Sequence (%s)",
+                (NULL != mdb.last_cmd) ? mdb.last_cmd->name : "?");
+    mdb.session_running = GNUNET_NO;
+    if (mdb.last_cmd != &endSession)
+      mdb.cmd = &endSession;
+    else
+      mdb.last_cmd = NULL;
+    break;
+  case 0xAA:
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "Received request to resend previous data (%s)",
+                (NULL != mdb.last_cmd) ? mdb.last_cmd->name : "?");
+    GNUNET_break (NULL == mdb.cmd);
+    GNUNET_break (NULL != mdb.last_cmd);
+    mdb.cmd = mdb.last_cmd;
+    mdb.last_cmd = NULL;
+    break;
+  default:
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "Unknown MDB command %X\n",
+                cmd);
+    break;
+  }
+}
 
-    free (input);
-    input = NULL;
+
+static void
+read_mdb_command (void *cls)
+{
+  ssize_t ret;
+  size_t cmdStartIdx;
+  size_t cmdEndIdx;
+
+  (void) cls;
+  mdb.rtask = NULL;
+  ret = read (mdb.uartfd,
+              &mdb.rxBuffer[mdb.rx_off],
+              sizeof (mdb.rxBuffer) - mdb.rx_off);
+  if (-1 == ret)
+  {
+    GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
+                              "read",
+                              UART_DEVICE);
+    GNUNET_SCHEDULER_shutdown ();
+    return;
+  }
+  mdb.rx_off += ret;
+
+  while (mdb.rx_off > 0)
+  {
+    /* find begining of command */
+    for (cmdStartIdx = 0; cmdStartIdx < mdb.rx_off; cmdStartIdx++)
+      if (0x02 == mdb.rxBuffer[cmdStartIdx])
+        break;
+    if (cmdStartIdx == mdb.rx_off)
+    {
+      mdb.rx_off = 0;
+      break;
+    }
+    /* find end of command */
+    for (cmdEndIdx = cmdStartIdx; cmdEndIdx < mdb.rx_off; cmdEndIdx++)
+      if (0x03 == mdb.rxBuffer[cmdEndIdx])
+        break;
+    if (cmdEndIdx == mdb.rx_off)
+    {
+      /* check we have more buffer space available,
+   otherwise the rxBuffer was fundamentally too
+   small to receive an entire command! */
+      if ( (cmdStartIdx > 0) ||
+           (mdb.rx_off < sizeof (mdb.rxBuffer)) )
+      {
+        /* Developer: if this happens, try increasing rxBuffer! */
+        GNUNET_break (0);
+        GNUNET_SCHEDULER_shutdown ();
+        return;
+      }
+      memmove (mdb.rxBuffer,
+               &mdb.rxBuffer[cmdStartIdx],
+               mdb.rx_off - cmdStartIdx);
+      mdb.rx_off -= cmdStartIdx;
+      break;
+    }
+    handle_command ((const char *) &mdb.rxBuffer[cmdStartIdx + 1],
+                    cmdEndIdx - cmdStartIdx - 1);
+    memmove (mdb.rxBuffer,
+             &mdb.rxBuffer[cmdEndIdx + 1],
+             mdb.rx_off - cmdEndIdx + 1);
+    mdb.rx_off -= (cmdEndIdx + 1);
   }
-  else
-       {
-               mdb.cmd = NULL;
-       }
 
-  start_read_mdb ();
+  start_mdb ();
 }
 
+
 static void
-start_read_mdb ()
+start_mdb ()
 {
   struct GNUNET_DISK_FileHandle fh = { mdb.uartfd };
-  if (NULL != mdb.cmd)
-  {
-    sendMdbCmd (mdb.cmd, mdb.uartfd);
-  }
-  GNUNET_assert (NULL == mdb_task);
-  mdb_task = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
-                                             &fh,
-                                             &read_mdb_command,
-                                             NULL);
+
+  if ( (GNUNET_NO == mdb.session_running) &&
+       (NULL == mdb.cmd) &&
+       (NULL == mdb.last_cmd) )
+    mdb.cmd = &beginSession;
+
+  if ( (NULL == mdb.wtask) &&
+       ( (NULL != mdb.cmd) ||
+         (mdb.tx_len > mdb.tx_off) ) )
+    mdb.wtask = GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL,
+                                                 &fh,
+                                                 &write_mdb_command,
+                                                 NULL);
+  if (NULL == mdb.rtask)
+    mdb.rtask = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
+                                                &fh,
+                                                &read_mdb_command,
+                                                NULL);
 }
 
+
 /**
  * Read the products from the configuration file
  * @param cls closure
@@ -1218,7 +1613,7 @@ read_products (void *cls,
     tmpProduct.key = '\0';
   }
   if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_string (cls,
+      GNUNET_CONFIGURATION_get_value_number (cls,
                                              section,
                                              "number",
                                              &tmpProduct.number))
@@ -1234,8 +1629,69 @@ read_products (void *cls,
                        tmpProduct);
 }
 
+
+static int
+mdb_init ()
+{
+  struct termios uart_opts_raw;
+
+  /* open uart connection */
+  if (0 > (mdb.uartfd = open (UART_DEVICE,
+                              O_RDWR | O_NOCTTY | O_NDELAY)))
+  {
+    GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
+                              "open",
+                              UART_DEVICE);
+    return GNUNET_SYSERR;
+  }
+
+  if (0 != tcgetattr (mdb.uartfd, &mdb.uart_opts_backup))
+  {
+    GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
+                         "tcgetattr");
+    return GNUNET_SYSERR;
+  }
+  uart_opts_raw = mdb.uart_opts_backup;
+
+  /* reset current uart discipline */
+  memset (&uart_opts_raw,
+          0,
+          sizeof(uart_opts_raw));
+
+  /* set baudrate */
+  cfsetispeed (&uart_opts_raw, B9600);
+  cfsetospeed (&uart_opts_raw, B9600);
+
+  /* set options */
+  uart_opts_raw.c_cflag &= ~PARENB;
+  uart_opts_raw.c_cflag &= ~CSTOPB;
+  uart_opts_raw.c_cflag &= ~CSIZE;
+  uart_opts_raw.c_cflag |= CS8;
+
+  /* 19200 bps, 8 databits, ignore cd-signal, allow reading */
+  uart_opts_raw.c_cflag |= (CLOCAL | CREAD);
+  uart_opts_raw.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
+  uart_opts_raw.c_iflag = IGNPAR;
+  uart_opts_raw.c_oflag &= ~OPOST;
+  uart_opts_raw.c_cc[VMIN]  = 0;
+  uart_opts_raw.c_cc[VTIME] = 50;
+  tcflush (mdb.uartfd, TCIOFLUSH);
+  if (0 != tcsetattr (mdb.uartfd,
+                      TCSAFLUSH,
+                      &uart_opts_raw))
+  {
+    GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
+                         "tcsetattr");
+    return GNUNET_SYSERR;
+  }
+  start_mdb ();
+  return GNUNET_OK;
+}
+
+
 /**
  * Start the application
+ *
  * @param cls closure
  * @param args arguments left
  * @param cfgfile config file name
@@ -1326,6 +1782,17 @@ run (void *cls,
 
   GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
                                  NULL);
+
+  /* initialize mdb */
+  if (GNUNET_OK != mdb_init ())
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Unable to initialize MDB (mdb_init() failed)\n");
+    global_ret = EXIT_FAILURE;
+    GNUNET_SCHEDULER_shutdown ();
+    return;
+  }
+
   /* initialize nfc */
   nfc_init (&context);
   if (NULL == context)
@@ -1415,7 +1882,7 @@ run (void *cls,
     }
     else
     {
-      write (qrDisplay.backlightfd, "0", 1);
+      (void) write (qrDisplay.backlightfd, "0", 1);
     }
   }
   else
@@ -1425,13 +1892,10 @@ run (void *cls,
                 FRAMEBUFFER_DEVICE);
   }
 #endif
-
-
-    
-       start_read_keyboard ();
-  start_read_mdb ();
+  start_read_keyboard ();
 }
 
+
 int
 main (int argc,
       char*const*argv)
@@ -1457,75 +1921,11 @@ main (int argc,
                "Failed to set terminal discipline\n");
   }
 
-  /* open uart connection */
-  struct termios uart_opts_backup, uart_opts_raw;
-  if (0 > (mdb.uartfd = open (UART_DEVICE,
-                              O_RDWR | O_NOCTTY | O_NDELAY)))
-  {
-    fprintf (stderr,
-             "Failed to open uart device\n");
-    return EXIT_FAILURE;
-  }
-
-  if (0 != tcgetattr (mdb.uartfd, &uart_opts_backup))
-  {
-    fprintf (stderr,
-             "Failed to get uart discipline\n");
-    return EXIT_FAILURE;
-  }
-
-  uart_opts_raw = uart_opts_backup;
-
-  /* reset current uart discipline */
-  memset (&uart_opts_raw,
-          0,
-          sizeof(uart_opts_raw));
-
-  /* set baudrate */
-  cfsetispeed (&uart_opts_raw, B9600);
-  cfsetospeed (&uart_opts_raw, B9600);
-
-  /* set options */
-  uart_opts_raw.c_cflag &= ~PARENB;
-  uart_opts_raw.c_cflag &= ~CSTOPB;
-  uart_opts_raw.c_cflag &= ~CSIZE;
-  uart_opts_raw.c_cflag |= CS8;
-
-  /* 19200 bps, 8 databits, ignore cd-signal, allow reading */
-  uart_opts_raw.c_cflag |= (CLOCAL | CREAD);
-
-  uart_opts_raw.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
-  uart_opts_raw.c_iflag = IGNPAR;
-  uart_opts_raw.c_oflag &= ~OPOST;
-  uart_opts_raw.c_cc[VMIN]  = 0;
-  uart_opts_raw.c_cc[VTIME] = 50;
-  tcflush (mdb.uartfd,TCIOFLUSH);
-  if (0 != tcsetattr (mdb.uartfd,
-                      TCSAFLUSH,
-                      &uart_opts_raw))
-  {
-    printf ("Failed to set uart discipline\n");
-    return EXIT_FAILURE;
-  }
-
-       readerConfigData = newMdbCmd ("Reader Config", "0101", "19780A02FF0C");
-       beginSession = newMdbCmd ("Begin Session", "03", "FFFF");
-       denyVend = newMdbCmd ("Deny Vend", "06", NULL);
-       approveVend = newMdbCmd ("Approve Vend", "05", "0001");
-       endSession = newMdbCmd ("End Session", "07", NULL);
-
-       char* input;
-
-       input = receiveMdbCmd(mdb.uartfd);
-  
-       if(NULL != input && 0 == strcmp(input, "Config Data"))
-  {
-               mdb.cmd = readerConfigData;
-       }
-       else
-       {
-               mdb.cmd = beginSession;
-       }
+  readerConfigData = setup_mdb_cmd ("Reader Config", "0101", "19780A02FF0C");
+  beginSession = setup_mdb_cmd ("Begin Session", "03", "FFFF");
+  denyVend = setup_mdb_cmd ("Deny Vend", "06", NULL);
+  approveVend = setup_mdb_cmd ("Approve Vend", "05", "0001");
+  endSession = setup_mdb_cmd ("End Session", "07", NULL);
 
   ret = GNUNET_PROGRAM_run (argc,
                             argv,
@@ -1542,15 +1942,6 @@ main (int argc,
                "Failed to restore terminal discipline\n");
   }
 
-  if (0 != tcsetattr (mdb.uartfd,
-                      TCSAFLUSH,
-                      &uart_opts_backup))
-  {
-    printf ("Failed to restore uart discipline\n");
-    global_ret = EXIT_FAILURE;
-  }
-  close (mdb.uartfd);
-
   if (GNUNET_OK != ret)
     return 1;
   return global_ret;
diff --git a/src/mdb/.gitkeep b/src/mdb/.gitkeep
deleted file mode 100644
index e69de29..0000000
diff --git a/src/mdb/mdb_uart.c b/src/mdb/mdb_uart.c
deleted file mode 100644
index 1d92d47..0000000
--- a/src/mdb/mdb_uart.c
+++ /dev/null
@@ -1,362 +0,0 @@
-/*
-  This file is part of TALER
-  Copyright (C) 2014 GNUnet e.V.
-
-  TALER is free software; you can redistribute it and/or modify it under the
-  terms of the GNU General Public License as published by the Free Software
-  Foundation; either version 3, or (at your option) any later version.
-
-  TALER 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 General Public License for more
-details.
-
-  You should have received a copy of the GNU General Public License
-along with
-  TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
-*/
-
-/**
- * @file mdb_uart.c
- * @brief Functions for communication via the mdb bus with the VMC
- * @author Dominik Hofer <address@hidden>
- */
-
-#include "mdb_uart.h"
-
-int
-mdbUart_init (void)
-{
-  int uart0_filestream = -1;
-  struct termios options;
-
-  // Open Uart
-  uart0_filestream = open ("/dev/ttyAMA0", O_RDWR | O_NOCTTY | O_NDELAY);
-  printf ("File Descriptor: %d\n", uart0_filestream);
-
-  if (uart0_filestream < 0)
-  {
-    printf ("Error - cannot open UART Device\n");
-  }
-  else{
-    fcntl (uart0_filestream, F_SETFL, 0);
-    if (tcgetattr (uart0_filestream, &options) != 0)
-    {
-      printf ("Error - Cannot get current UART configuration\n");
-      return -1;
-    }
-
-    memset (&options, 0, sizeof(options));    /* Structur loeschen, ggf. 
vorher sichern
-                                          und bei Programmende wieder 
restaurieren */
-    /* Baudrate setzen */
-    cfsetispeed (&options, B9600);
-    cfsetospeed (&options, B9600);
-
-    /* setze Optionen */
-    options.c_cflag &= ~PARENB;             /* kein Paritybit */
-    options.c_cflag &= ~CSTOPB;             /* 1 Stoppbit */
-    options.c_cflag &= ~CSIZE;              /* 8 Datenbits */
-    options.c_cflag |= CS8;
-
-    /* 19200 bps, 8 Datenbits, CD-Signal ignorieren, Lesen erlauben */
-    options.c_cflag |= (CLOCAL | CREAD);
-
-    /* Kein Echo, keine Steuerzeichen, keine Interrupts */
-    options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
-    options.c_iflag = IGNPAR;               /* Parity-Fehler ignorieren */
-    options.c_oflag &= ~OPOST;              /* setze "raw" Input */
-    options.c_cc[VMIN]  = 14;                /* warten auf min. 0 Zeichen */
-    options.c_cc[VTIME] = 10;               /* Timeout 1 Sekunde */
-    tcflush (uart0_filestream,TCIOFLUSH);                 /* Puffer leeren */
-    if (tcsetattr (uart0_filestream, TCSAFLUSH, &options) != 0)
-    {
-      printf ("Error - Cannot configurate UART device\n");
-      return(-1);
-    }
-  }
-
-  return uart0_filestream;
-}
-
-int
-uart_close (int filestream)
-{
-
-  return close (filestream);
-}
-
-
-int
-uartSendBytes (int uart0_filestream, uint8_t*txBuffer, int nrOfBytes)
-{
-  int nrOfSentBytes = 0;
-
-  nrOfSentBytes = write (uart0_filestream, txBuffer, nrOfBytes);
-
-  printf ("Number of Bytes sent: %d\n", nrOfSentBytes);
-
-  return nrOfSentBytes;
-}
-
-int
-uartReceiveBytes (int uart0_filestream, uint8_t *rxBuffer, int nrOfBytes)
-{
-  int nrOfReceivedBytes = 0;
-
-  nrOfReceivedBytes = read (uart0_filestream, rxBuffer, nrOfBytes);
-
-  //   printf("Number of Bytes received: %d\n", nrOfReceivedBytes);
-
-  return nrOfReceivedBytes;
-}
-
-char *
-receiveMdbCmd (int filestream)
-{
-  uint8_t rxBuffer[MAX_SIZE_RX_BUFFER];
-  uint8_t cmd = 0xFF;
-
-  size_t cmdStartIdx = 0;
-  int nrOfReceivedBytes = 0;
-
-  nrOfReceivedBytes = read (filestream, rxBuffer, MAX_SIZE_RX_BUFFER);
-  
-       if (nrOfReceivedBytes < 4)
-  {
-    return NULL;
-  }
-
-  while (rxBuffer[cmdStartIdx] != 0x02)
-  {
-    cmdStartIdx++;
-    if (cmdStartIdx == nrOfReceivedBytes)
-    {
-      return NULL;
-    }
-  }
-  printf("Received Bytes: %d\n", nrOfReceivedBytes);
-  char *retVal = malloc (30 * sizeof(char) + sizeof(uint16_t));
-
-  if (! retVal)
-  {
-    puts ("Error: Cannot allocate memory");
-  }
-
-  cmd = ((convertChar2Hex (rxBuffer[cmdStartIdx + 1]) << 4) | (convertChar2Hex 
(
-                                                                 rxBuffer[
-                                                                   cmdStartIdx
-                                                                   + 2])));
-  //printf ("Received Command: %X\n", cmd);
-
-  switch (cmd)
-  {
-  case 0x13:
-    if (((convertChar2Hex (rxBuffer[cmdStartIdx + 3]) << 4) | (convertChar2Hex 
(
-                                                                 rxBuffer[
-                                                                   cmdStartIdx
-                                                                   + 4]))) ==
-        0x00)
-    {
-      uint16_t productNmbr = 0x0000;
-      size_t idx;
-      size_t shiftIdx;
-      for (idx = cmdStartIdx + 9, shiftIdx = 12; idx <= cmdStartIdx + 12; 
idx++,
-           shiftIdx -= 4) {
-        productNmbr |= ((uint16_t) ((convertChar2Hex (rxBuffer[idx]))
-                                    << shiftIdx));
-      }
-      puts ("");
-      sprintf (retVal, "Vend Request for: %d", productNmbr);
-    }
-    else if (((convertChar2Hex (rxBuffer[cmdStartIdx + 3]) << 4)
-              | (convertChar2Hex (rxBuffer[cmdStartIdx + 4]))) == 0x02)
-    {
-      sprintf (retVal, "Vend Success");
-    }
-    else if (((convertChar2Hex (rxBuffer[cmdStartIdx + 3]) << 4)
-              | (convertChar2Hex (rxBuffer[cmdStartIdx + 4]))) == 0x03)
-    {
-      sprintf (retVal, "Vend Failure");
-    }
-    else if (((convertChar2Hex (rxBuffer[cmdStartIdx + 3]) << 4)
-              | (convertChar2Hex (rxBuffer[cmdStartIdx + 4]))) == 0x04)
-    {
-      sprintf (retVal, "Session Complete");
-    }
-    else {
-      free (retVal);
-      retVal = NULL;
-    }
-    break;
-  case 0x11:
-    sprintf (retVal, "Config Data");
-    break;
-  case 0x14:
-    if (((convertChar2Hex (rxBuffer[cmdStartIdx + 3]) << 4) | (convertChar2Hex 
(
-                                                                 rxBuffer[
-                                                                   cmdStartIdx
-                                                                   + 4]))) ==
-                                                                               
                                                                                
                                                                                
        0x01)
-    {
-      sprintf (retVal, "Reader Enable");
-    }
-    else {
-      free (retVal);
-      retVal = NULL;
-    }
-    break;
-  case 0x00:
-    sprintf (retVal, "Acknowledge");
-    break;
-  case 0xD0:
-    sprintf (retVal, "Command out of Sequence");
-    break;
-  case 0xAA:
-    sprintf (retVal, "Resend previous data");
-    break;
-  default:
-    free (retVal);
-    retVal = NULL;
-    break;
-  }
-  return retVal;
-
-}
-struct mdbCmd *
-newMdbCmd (char *name, char *cmd, char *data)
-{
-
-  struct mdbCmd*cmdNew = malloc (sizeof(struct mdbCmd));
-  size_t idx = 0;
-  size_t strIdx = 0;
-
-  if (name == NULL)
-  {
-    cmdNew->name = malloc (sizeof(char) * strlen ("No Cmd Name Set") + 1);
-    strncpy (cmdNew->name, "No Cmd Name Set", strlen ("No Cmd Name Set") + 1);
-  }
-  else{
-    cmdNew->name = malloc (sizeof(char) * strlen (name) + 1);
-    strncpy (cmdNew->name, name, strlen (name) + 1);
-  }
-
-  if (cmd == NULL)
-  {
-    cmdNew->cmdLength = 0;
-    cmdNew->cmd = NULL;
-  }
-  else{
-    cmdNew->cmdLength = strlen (cmd) / 2;
-    cmdNew->cmd = malloc (sizeof(uint8_t) * cmdNew->cmdLength);
-    printf ("New Command: ");
-    for (idx = 0, strIdx = 0; idx < cmdNew->cmdLength; idx++, strIdx += 2) {
-      cmdNew->cmd[idx] = (convertChar2Hex (cmd[strIdx]) << 4 | convertChar2Hex 
(
-                            cmd[strIdx + 1]));
-      printf ("%X", cmdNew->cmd[idx]);
-    }
-    puts ("");
-  }
-
-  if (data == NULL)
-  {
-    cmdNew->dataLength = 0;
-    cmdNew->data = NULL;
-  }
-  else{
-    cmdNew->dataLength = strlen (data) / 2;
-    cmdNew->data = malloc (sizeof(uint8_t) * cmdNew->dataLength);
-
-    for (idx = 0, strIdx = 0; idx < cmdNew->dataLength; idx++, strIdx += 2) {
-      cmdNew->data[idx] = ((convertChar2Hex (data[strIdx])) << 4
-                           | convertChar2Hex (data[strIdx + 1]));
-    }
-  }
-
-  return cmdNew;
-}
-
-void
-deleteMdbCmd (struct mdbCmd *mdbCmdToDelete)
-{
-  free (mdbCmdToDelete->name);
-  free (mdbCmdToDelete->cmd);
-  free (mdbCmdToDelete->data);
-  free (mdbCmdToDelete);
-}
-
-void
-setMdbCmdData (struct mdbCmd *mdbCmdToSet, char *data)
-{
-  mdbCmdToSet->dataLength = strlen (data);
-
-  if (mdbCmdToSet->dataLength == 0)
-  {
-    free (mdbCmdToSet->data);
-    mdbCmdToSet->data = NULL;
-  }
-  else{
-    mdbCmdToSet = realloc (mdbCmdToSet->data, sizeof(uint8_t)
-                           * mdbCmdToSet->dataLength);
-    size_t strIdx = 0;
-    for (size_t idx = 0; idx < mdbCmdToSet->dataLength; idx++) {
-      mdbCmdToSet->data[idx] = (convertChar2Hex (data[strIdx]) << 4)
-                               | (convertChar2Hex (data[strIdx + 1]));
-      strIdx = strIdx + 2;
-    }
-  }
-
-}
-
-int
-sendMdbCmd (struct mdbCmd*cmdToSend, int filestream)
-{
-
-  uint8_t*txBuffer;
-  uint32_t chkSum = 0x00000000;
-  int nrOfSentBytes = 0;
-  char *receivedMdbCmd = NULL;
-
-  txBuffer = malloc (sizeof(uint8_t) * (cmdToSend->cmdLength
-                                        + cmdToSend->dataLength + 1));
-
-  for (size_t idx = 0; idx < cmdToSend->cmdLength; idx++) {
-    txBuffer[idx] = cmdToSend->cmd[idx];
-    // printf("%X", cmdToSend->cmd[idx]);
-    chkSum += cmdToSend->cmd[idx];
-  }
-
-  for (size_t idx = 0; idx < cmdToSend->dataLength; idx++) {
-    txBuffer[idx + cmdToSend->cmdLength] = cmdToSend->data[idx];
-    chkSum += cmdToSend->data[idx];
-  }
-
-  txBuffer[cmdToSend->cmdLength + cmdToSend->dataLength] = (uint8_t) (chkSum
-                                                                      & 0xFF);
-
-  printf ("Send command: %s\n", cmdToSend->name);
-
-
-       nrOfSentBytes = uartSendBytes (filestream, txBuffer, 
cmdToSend->cmdLength
-                                   + cmdToSend->dataLength + 1);
-
-  while (! receivedMdbCmd)
-  {
-    receivedMdbCmd = receiveMdbCmd (filestream);
-
-    if (receivedMdbCmd)
-    {
-      if (strcmp ("Acknowledge", receivedMdbCmd) == 0)
-      {
-        break;
-      }
-      else{
-        free (receivedMdbCmd);
-        receivedMdbCmd = NULL;
-      }
-    }
-  }
-  free (receivedMdbCmd);
-
-  return nrOfSentBytes;
-}
diff --git a/src/mdb/mdb_uart.h b/src/mdb/mdb_uart.h
deleted file mode 100644
index e31cf8d..0000000
--- a/src/mdb/mdb_uart.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
-  This file is part of TALER
-  Copyright (C) 2014 GNUnet e.V.
-
-  TALER is free software; you can redistribute it and/or modify it under the
-  terms of the GNU General Public License as published by the Free Software
-  Foundation; either version 3, or (at your option) any later version.
-
-  TALER 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 General Public License for more
-details.
-
-  You should have received a copy of the GNU General Public License
-along with
-  TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
-*/
-
-/**
- * @file mdb_uart.h
- * @brief Functions for communication via the mdb bus with the VMC
- * @author Dominik Hofer <address@hidden>
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdbool.h>
-#include <stdint.h>
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <termios.h>
-
-/* Commands for communication via MDB/ICP */
-/* VMC commands */
-#define VMC_VEND 0x13
-#define VMC_VEND_REQUEST 0x00
-#define VMC_VEND_CANCEL 0x01
-#define VMC_VEND_SUCCESS 0x02
-#define VMC_VEND_FAILURE 0x03
-#define VMC_VEND_SESSION_COMPLETE 0x04
-
-/* Reader commands */
-#define READER_CONFIG "01"
-#define READER_DISPLAY_REQUEST "02"
-#define READER_BEGIN_SESSION "03"
-#define READER_SESSION_CANCEL_REQUEST "04"
-#define READER_VEND_APPROVE "05"
-#define READER_VEND_DENIED "06"
-#define READER_END_SESSION "07"
-#define READER_SESSION_CANCELLED "08"
-#define READER_REVALUE_APPROVED "0D"
-#define READER_REVALUE_DENIED "0E"
-
-/* Constants */
-#define MAX_SIZE_RX_BUFFER 256
-
-/* Macro for char to hex conversion */
-#define convertChar2Hex(C) (((C) >= 'A' && (C) <= 'F') ? ((C) -55) : ((C) \
-                                                                      - '0'))
-
-/* Datatype for mdb command */
-struct mdbCmd
-{
-  char*name;
-  uint8_t*cmd;
-  size_t cmdLength;
-  uint8_t*data;
-  size_t dataLength;
-};
-
-/* Function Prototypes */
-int uart_init (void);
-int uart_close (int filestream);
-int mdb_init (int filestream);
-int uartSendBytes (int uart0_filestream, uint8_t*txBuffer, int nrOfBytes);
-int uartReceiveBytes (int uart0_filestream, uint8_t*rxBuffer, int nrOfBytes);
-struct mdbCmd *newMdbCmd (char*name, char *cmd, char *data);
-void deleteMdbCmd (struct mdbCmd *mdbCmdToDelete);
-void setMdbCmdData (struct mdbCmd *mdbCmdToSet, char *data);
-int sendMdbCmd (struct mdbCmd*cmdToSend, int filestream);
-char *receiveMdbCmd (int filestream);

-- 
To stop receiving notification emails like this one, please contact
address@hidden.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]