diff --git a/adaptors/matlab/analogout.c b/adaptors/matlab/analogout.c
index e545ab93cd860c48a222857451a2f43e588c972f..a8ea2a01d4d393da65d563328150bbe040c38dce 100644
--- a/adaptors/matlab/analogout.c
+++ b/adaptors/matlab/analogout.c
@@ -33,13 +33,24 @@
             1           moberg_analog_out pointer[1]
             ...
 
- */
+  RWork:    0           exit_value[0] (optional)
+            1           exit_value[1] (optional)
+            ...
+
+*/
 
 #define MDL_CHECK_PARAMETERS
 static void mdlCheckParameters(SimStruct *S)
 {
+  int number_of_params = ssGetSFcnParamsCount(S);
+
+  if (number_of_params < 2 || 3 < number_of_params) {
+    ssSetErrorStatus(S, "block accepts 2 or 3 parameters");
+    return;
+  }
+
   /* 1st parameter: sampling interval */
-  {
+  if (number_of_params >= 1) {
     if (!mxIsDouble(ssGetSFcnParam(S,0)) ||
 	mxGetNumberOfElements(ssGetSFcnParam(S,0)) != 1) {
       ssSetErrorStatus(S, "sampling time must be a scalar");
@@ -47,8 +58,8 @@ static void mdlCheckParameters(SimStruct *S)
     }
   }
  
-  /* 2nd parameter: input channels */
-  {
+  /* 2nd parameter: output channels */
+  if (number_of_params >= 2) {
     int number_of_dims = mxGetNumberOfDimensions(ssGetSFcnParam(S,1)); 
     
     if (!mxIsDouble(ssGetSFcnParam(S,1)) ||
@@ -57,19 +68,36 @@ static void mdlCheckParameters(SimStruct *S)
       return;
     }
   }
+
+  /* 3nd parameter: (optional) exit output values */
+  if (number_of_params >= 3) {
+    int number_of_dims = mxGetNumberOfDimensions(ssGetSFcnParam(S,2));
+
+    if (!mxIsDouble(ssGetSFcnParam(S,2)) ||
+        number_of_dims != 2 || mxGetM(ssGetSFcnParam(S,2)) != 1) {
+      ssSetErrorStatus(S, "exit output values must be a scalar or a vector");
+      return;
+    }
+
+    if (mxGetN(ssGetSFcnParam(S,1)) != mxGetN(ssGetSFcnParam(S,2))) {
+      ssSetErrorStatus(S, "exit output values must same size as channels");
+      return;
+    }
+  }
 }
 
 static void mdlInitializeSizes(SimStruct *S)
 {
   int channelCount;
+  int number_of_params = ssGetSFcnParamsCount(S);
 
-  ssSetNumSFcnParams(S, 2);
-  if (ssGetNumSFcnParams(S) == ssGetSFcnParamsCount(S)) {
-    mdlCheckParameters(S);
-    if (ssGetErrorStatus(S) != NULL) { return; }
-  } else {
+  if (number_of_params < 2 || 3 < number_of_params) {
+    ssSetErrorStatus(S, "block accepts 2 or 3 parameters");
     return;
   }
+  ssSetNumSFcnParams(S, number_of_params);
+  mdlCheckParameters(S);
+  if (ssGetErrorStatus(S) != NULL) { return; }
 
   channelCount = mxGetN(ssGetSFcnParam(S,1));
 
@@ -87,9 +115,15 @@ static void mdlInitializeSizes(SimStruct *S)
 
   ssSetNumSampleTimes(S, 1);
   ssSetNumPWork(S, channelCount);     /* 0:      moberg_analog_out pointer[0]
-                                         1:      moberg_analog_out pointer[1]
-					 ...
-				      */
+                                       * 1:      moberg_analog_out pointer[1]
+                                       * ...
+                                       */
+  if (number_of_params == 3) {
+    ssSetNumRWork(S, channelCount);   /* 0:       exit_value[0]
+                                       * 1:       exit_value[1]
+                                       * ...
+                                       */
+  }
   ssSetNumModes(S, 0);
   ssSetNumNonsampledZCs(S, 0);
   
@@ -106,24 +140,30 @@ static void mdlInitializeSampleTimes(SimStruct *S)
 static void mdlInitializeConditions(SimStruct *S)
 {
   void **pwork = ssGetPWork(S);
+  real_T *rwork = ssGetRWork(S);
   double *channel = mxGetPr(ssGetSFcnParam(S,1));
-  int channel_count = mxGetN(ssGetSFcnParam(S,1));
   int i;
 
-  for (i = 0 ; i < channel_count ; i++) {
+  if (rwork) {
+    real_T *exit_value = mxGetPr(ssGetSFcnParam(S,2));
+    for (i = 0 ; i < ssGetNumRWork(S) ; i++) {
+      rwork[i] = exit_value[i];
+    }
+  }
+
+  for (i = 0 ; i < ssGetNumPWork(S) ; i++) {
     pwork[i] = moberg4simulink_analog_out_open(channel[i]);
     if (! pwork[i]) {
       static char error[256];
       sprintf(error, "Failed to open analogout #%d", (int)channel[i]);
       ssSetErrorStatus(S, error);
+      return;
     }
   }
 }
 
 static void mdlOutputs(SimStruct *S, int_T tid)
 {
-  void **pwork = ssGetPWork(S);
-
   {
     /* Propagate the dummy sorting signal */
     InputRealPtrsType up = ssGetInputPortRealSignalPtrs(S,0);
@@ -133,6 +173,7 @@ static void mdlOutputs(SimStruct *S, int_T tid)
   {
     int i;
     InputRealPtrsType up = ssGetInputPortRealSignalPtrs(S,1);
+    void **pwork = ssGetPWork(S);
 
     for (i = 0 ; i < ssGetNumPWork(S) ; i++) {
       struct moberg_analog_out *aout = (struct moberg_analog_out*)pwork[i];
@@ -150,10 +191,21 @@ static void mdlTerminate(SimStruct *S)
 {
   int i;
   void **pwork = ssGetPWork(S);
+  real_T *rwork = ssGetRWork(S);
   double *channel = mxGetPr(ssGetSFcnParam(S,1));
-  int channel_count = mxGetN(ssGetSFcnParam(S,1));
 
-  for (i = 0 ; i < channel_count ; i++) {
+  for (i = 0 ; i < ssGetNumPWork(S) && i < ssGetNumRWork(S) ; i++) {
+    struct moberg_analog_out *aout = (struct moberg_analog_out*)pwork[i];
+    if (aout == NULL) continue;
+    if (! moberg_OK(aout->write(aout->context, rwork[i], NULL))) {
+      static char error[256];
+      double *channel = mxGetPr(ssGetSFcnParam(S,1));
+      sprintf(error, "Failed to write analogout #%d", (int)channel[i]);
+      ssSetErrorStatus(S, error);
+    }
+  }
+
+  for (i = 0 ; i < ssGetNumPWork(S) ; i++) {
     if (pwork[i]) {
       struct moberg_analog_out *aout = (struct moberg_analog_out*)pwork[i];
       moberg4simulink_analog_out_close(channel[i], aout);
diff --git a/adaptors/matlab/digitalout.c b/adaptors/matlab/digitalout.c
index be8d48e9e85e3e9d786797d4b73f7a705519cd81..b12903f2b51c8ea41066aa7e352905e29fae84a9 100644
--- a/adaptors/matlab/digitalout.c
+++ b/adaptors/matlab/digitalout.c
@@ -33,13 +33,24 @@
             1           moberg_digital_out pointer[1]
             ...
 
- */
+  RWork:    0           exit_value[0] (optional)
+            1           exit_value[1] (optional)
+            ...
+
+*/
 
 #define MDL_CHECK_PARAMETERS
 static void mdlCheckParameters(SimStruct *S)
 {
+  int number_of_params = ssGetSFcnParamsCount(S);
+
+  if (number_of_params < 2 || 3 < number_of_params) {
+    ssSetErrorStatus(S, "block accepts 2 or 3 parameters");
+    return;
+  }
+
   /* 1st parameter: sampling interval */
-  {
+  if (number_of_params >= 1) {
     if (!mxIsDouble(ssGetSFcnParam(S,0)) ||
 	mxGetNumberOfElements(ssGetSFcnParam(S,0)) != 1) {
       ssSetErrorStatus(S, "sampling time must be a scalar");
@@ -47,8 +58,8 @@ static void mdlCheckParameters(SimStruct *S)
     }
   }
  
-  /* 2nd parameter: input channels */
-  {
+  /* 2nd parameter: output channels */
+  if (number_of_params >= 2) {
     int number_of_dims = mxGetNumberOfDimensions(ssGetSFcnParam(S,1)); 
     
     if (!mxIsDouble(ssGetSFcnParam(S,1)) ||
@@ -57,20 +68,37 @@ static void mdlCheckParameters(SimStruct *S)
       return;
     }
   }
+
+  /* 3nd parameter: (optional) exit output values */
+  if (number_of_params >= 3) {
+    int number_of_dims = mxGetNumberOfDimensions(ssGetSFcnParam(S,2));
+
+    if (!mxIsDouble(ssGetSFcnParam(S,2)) ||
+        number_of_dims != 2 || mxGetM(ssGetSFcnParam(S,2)) != 1) {
+      ssSetErrorStatus(S, "exit output values must be a scalar or a vector");
+      return;
+    }
+
+    if (mxGetN(ssGetSFcnParam(S,1)) != mxGetN(ssGetSFcnParam(S,2))) {
+      ssSetErrorStatus(S, "exit output values must same size as channels");
+      return;
+    }
+  }
 }
 
 static void mdlInitializeSizes(SimStruct *S)
 {
   int channelCount;
+  int number_of_params = ssGetSFcnParamsCount(S);
 
-  ssSetNumSFcnParams(S, 2);
-  if (ssGetNumSFcnParams(S) == ssGetSFcnParamsCount(S)) {
-    mdlCheckParameters(S);
-    if (ssGetErrorStatus(S) != NULL) { return; }
-  } else {
+  if (number_of_params < 2 || 3 < number_of_params) {
+    ssSetErrorStatus(S, "block accepts 2 or 3 parameters");
     return;
   }
-
+  ssSetNumSFcnParams(S, number_of_params);
+  mdlCheckParameters(S);
+  if (ssGetErrorStatus(S) != NULL) { return; }
+  
   channelCount = mxGetN(ssGetSFcnParam(S,1));
 
   ssSetNumContStates(S, 0);
@@ -87,9 +115,15 @@ static void mdlInitializeSizes(SimStruct *S)
 
   ssSetNumSampleTimes(S, 1);
   ssSetNumPWork(S, channelCount);     /* 0:      moberg_digital_out pointer[0]
-                                         1:      moberg_digital_out pointer[1]
-					 ...
-				      */
+                                       * 1:      moberg_digital_out pointer[1]
+                                       * ...
+                                       */
+  if (number_of_params == 3) {
+    ssSetNumRWork(S, channelCount);   /* 0:       exit_value[0]
+                                       * 1:       exit_value[1]
+                                       * ...
+                                       */
+  }
   ssSetNumModes(S, 0);
   ssSetNumNonsampledZCs(S, 0);
   
@@ -106,24 +140,30 @@ static void mdlInitializeSampleTimes(SimStruct *S)
 static void mdlInitializeConditions(SimStruct *S)
 {
   void **pwork = ssGetPWork(S);
+  real_T *rwork = ssGetRWork(S);
   double *channel = mxGetPr(ssGetSFcnParam(S,1));
-  int channel_count = mxGetN(ssGetSFcnParam(S,1));
   int i;
 
-  for (i = 0 ; i < channel_count ; i++) {
+  if (rwork) {
+    real_T *exit_value = mxGetPr(ssGetSFcnParam(S,2));
+    for (i = 0 ; i < ssGetNumRWork(S) ; i++) {
+      rwork[i] = exit_value[i];
+    }
+  }
+
+  for (i = 0 ; i < ssGetNumPWork(S) ; i++) {
     pwork[i] = moberg4simulink_digital_out_open(channel[i]);
     if (! pwork[i]) {
       static char error[256];
       sprintf(error, "Failed to open digitalout #%d", (int)channel[i]);
       ssSetErrorStatus(S, error);
+      return;
     }
   }
 }
 
 static void mdlOutputs(SimStruct *S, int_T tid)
 {
-  void **pwork = ssGetPWork(S);
-
   {
     /* Propagate the dummy sorting signal */
     InputRealPtrsType up = ssGetInputPortRealSignalPtrs(S,0);
@@ -133,6 +173,7 @@ static void mdlOutputs(SimStruct *S, int_T tid)
   {
     int i;
     InputRealPtrsType up = ssGetInputPortRealSignalPtrs(S,1);
+    void **pwork = ssGetPWork(S);
 
     for (i = 0 ; i < ssGetNumPWork(S) ; i++) {
       struct moberg_digital_out *dout = (struct moberg_digital_out*)pwork[i];
@@ -150,10 +191,21 @@ static void mdlTerminate(SimStruct *S)
 {
   int i;
   void **pwork = ssGetPWork(S);
+  real_T *rwork = ssGetRWork(S);
   double *channel = mxGetPr(ssGetSFcnParam(S,1));
-  int channel_count = mxGetN(ssGetSFcnParam(S,1));
 
-  for (i = 0 ; i < channel_count ; i++) {
+  for (i = 0 ; i < ssGetNumPWork(S) && i < ssGetNumRWork(S) ; i++) {
+    struct moberg_digital_out *dout = (struct moberg_digital_out*)pwork[i];
+    if (dout == NULL) continue;
+    if (! moberg_OK(dout->write(dout->context, rwork[i], NULL))) {
+      static char error[256];
+      double *channel = mxGetPr(ssGetSFcnParam(S,1));
+      sprintf(error, "Failed to write analogout #%d", (int)channel[i]);
+      ssSetErrorStatus(S, error);
+    }
+  }
+
+  for (i = 0 ; i < ssGetNumPWork(S) ; i++) {
     if (pwork[i]) {
       struct moberg_digital_out *dout = (struct moberg_digital_out*)pwork[i];
       moberg4simulink_digital_out_close(channel[i], dout);