diff --git a/compiler2/Type.cc b/compiler2/Type.cc
index 9cd01254a7ca94021de2df24b40c42b4c253a84e..0bdc941d399c2403f42fdcb429dac7800e6961f4 100644
--- a/compiler2/Type.cc
+++ b/compiler2/Type.cc
@@ -604,6 +604,8 @@ namespace Common {
     owner = 0;
     chk_finished = false;
     pard_type_instance = false;
+    asn_encoding = CT_UNDEF;
+    asn_decoding = CT_UNDEF;
   }
 
   void Type::clean_up()
@@ -4402,98 +4404,134 @@ namespace Common {
     coding_str = function_name;
     coding_by_function = true;
   }
+  
+  void Type::set_asn_coding(bool encode, Type::MessageEncodingType_t new_coding)
+  {
+    MessageEncodingType_t& coding = encode ? asn_encoding : asn_decoding;
+    if (coding == CT_UNDEF) {
+      // this is the first encoding/decoding function for this type, store it
+      coding = new_coding;
+    }
+    else if (coding != new_coding) {
+      // there are several encoding/decoding functions declared for this type
+      // with different codings (encvalue/decvalue cannot be used in this case)
+      coding = CT_MULTIPLE;
+    }
+  }
 
   void Type::chk_coding(bool encode, bool delayed /* = false */) {
     string& coding_str = encode ? encoding_str : decoding_str;
     if (!coding_str.empty())
       return;
     coding_by_function = false;
-
-    if (!w_attrib_path) {
-      error("No coding rule specified for type '%s'", get_typename().c_str());
-      return;
-    }
     Type::MessageEncodingType_t coding = CT_UNDEF;
 
-    // Checking extension attributes
-    Ttcn::ExtensionAttributes * extatrs = parse_extattributes(w_attrib_path);
-    if (extatrs != 0) { // NULL means parsing error
-      for (size_t k = 0; k < extatrs->size(); ++k) {
-        Ttcn::ExtensionAttribute &ea = extatrs->get(k);
-        Ttcn::TypeMappings *inmaps = 0, *maps = 0;
-        Ttcn::TypeMapping* mapping = 0;
-        Ttcn::TypeMappingTarget* target = 0;
-        Type* t = 0;
-        switch (ea.get_type()) {
-        case Ttcn::ExtensionAttribute::ENCDECVALUE:
-          ea.get_encdecvalue_mappings(inmaps, maps);
-          maps = encode ? maps : inmaps;
-          maps->set_my_scope(this->get_my_scope());
-          maps->chk();
-          // look for coding settings
-          t = encode ? this : Type::get_pooltype(T_BSTR);
-          mapping = maps->get_mapping_byType(t);
-          if (mapping->get_nof_targets() == 0)
-            goto end_ext;
-          else {
-            for (size_t ind = 0; ind < mapping->get_nof_targets(); ind++) {
-              target = mapping->get_target_byIndex(ind);
-              t = target->get_target_type();
-              if ((encode && (t->get_typetype() == T_BSTR)) ||
-                (!encode && (t->get_typename() == this->get_typename())))
-              {
-                if (target->get_mapping_type() ==
-                  Ttcn::TypeMappingTarget::TM_FUNCTION) {
-                  if (!coding_str.empty())
-                    target->error("Multiple definition of this target");
-                  coding_str = target->get_function()->
-                    get_genname_from_scope(my_scope);
-                  coding_by_function = true;
-                } else {
-                  target->error("Only function is supported to do this mapping");
+    if (!is_asn1()) {
+      if (!w_attrib_path) {
+        error("No coding rule specified for type '%s'", get_typename().c_str());
+        return;
+      }
+
+      // Checking extension attributes
+      Ttcn::ExtensionAttributes * extatrs = parse_extattributes(w_attrib_path);
+      if (extatrs != 0) { // NULL means parsing error
+        for (size_t k = 0; k < extatrs->size(); ++k) {
+          Ttcn::ExtensionAttribute &ea = extatrs->get(k);
+          Ttcn::TypeMappings *inmaps = 0, *maps = 0;
+          Ttcn::TypeMapping* mapping = 0;
+          Ttcn::TypeMappingTarget* target = 0;
+          Type* t = 0;
+          switch (ea.get_type()) {
+          case Ttcn::ExtensionAttribute::ENCDECVALUE:
+            ea.get_encdecvalue_mappings(inmaps, maps);
+            maps = encode ? maps : inmaps;
+            maps->set_my_scope(this->get_my_scope());
+            maps->chk();
+            // look for coding settings
+            t = encode ? this : Type::get_pooltype(T_BSTR);
+            mapping = maps->get_mapping_byType(t);
+            if (mapping->get_nof_targets() == 0)
+              goto end_ext;
+            else {
+              for (size_t ind = 0; ind < mapping->get_nof_targets(); ind++) {
+                target = mapping->get_target_byIndex(ind);
+                t = target->get_target_type();
+                if ((encode && (t->get_typetype() == T_BSTR)) ||
+                  (!encode && (t->get_typename() == this->get_typename())))
+                {
+                  if (target->get_mapping_type() ==
+                    Ttcn::TypeMappingTarget::TM_FUNCTION) {
+                    if (!coding_str.empty())
+                      target->error("Multiple definition of this target");
+                    coding_str = target->get_function()->
+                      get_genname_from_scope(my_scope);
+                    coding_by_function = true;
+                  } else {
+                    target->error("Only function is supported to do this mapping");
+                  }
                 }
               }
+              if (coding_str.empty()) {
+                ea.warning("Extension attribute is found for %s but without "
+                "typemappings", encode ? "encvalue" : "decvalue");
+              }
             }
-            if (coding_str.empty()) {
-              ea.warning("Extension attribute is found for %s but without "
-              "typemappings", encode ? "encvalue" : "decvalue");
-            }
-          }
-          break;
+            break;
 
-        case Ttcn::ExtensionAttribute::ANYTYPELIST:
-          break; // ignore (may be inherited from the module)
+          case Ttcn::ExtensionAttribute::ANYTYPELIST:
+            break; // ignore (may be inherited from the module)
 
-        case Ttcn::ExtensionAttribute::NONE:
-          break; // ignore erroneous attribute
+          case Ttcn::ExtensionAttribute::NONE:
+            break; // ignore erroneous attribute
 
-        default:
-          ea.error("A type can only have type mapping extension attribute: "
-            "in(...) or out(...)");
-          break;
+          default:
+            ea.error("A type can only have type mapping extension attribute: "
+              "in(...) or out(...)");
+            break;
+          }
         }
+        delete extatrs;
       }
-      delete extatrs;
-    }
 
-    if (!coding_str.empty())
-      return;
-end_ext:
-
-    const vector<SingleWithAttrib>& real_attribs
-                = w_attrib_path->get_real_attrib();
-    bool found = false;
-    for (size_t i = real_attribs.size(); i > 0 && !found; i--) {
-      if (real_attribs[i-1]->get_attribKeyword()
-                                              == SingleWithAttrib::AT_ENCODE) {
-        found = true;
-        coding = get_enc_type(*real_attribs[i-1]);
+      if (!coding_str.empty())
+        return;
+  end_ext:
+
+      const vector<SingleWithAttrib>& real_attribs
+                  = w_attrib_path->get_real_attrib();
+      bool found = false;
+      for (size_t i = real_attribs.size(); i > 0 && !found; i--) {
+        if (real_attribs[i-1]->get_attribKeyword()
+                                                == SingleWithAttrib::AT_ENCODE) {
+          found = true;
+          coding = get_enc_type(*real_attribs[i-1]);
+        }
+      }
+      if (coding == CT_UNDEF) {
+        // no "encode" attribute found
+        error("No coding rule specified for type '%s'", get_typename().c_str());
+        return;
       }
     }
-    if (coding == CT_UNDEF) {
-      // no "encode" attribute found
-      error("No coding rule specified for type '%s'", get_typename().c_str());
-      return;
+    else { // ASN.1 type
+      coding = encode ? asn_encoding : asn_decoding;
+      if ((coding == CT_UNDEF && delayed) || coding == CT_MULTIPLE) {
+        // either this is the delayed call and no external function has been
+        // found, or there was already more than one function
+        error("Cannot determine the %s rules for ASN.1 type `%s'. "
+          "%s %s external function%s found%s", encode ? "encoding" : "decoding",
+          get_typename().c_str(), coding == CT_UNDEF ? "No" : "Multiple",
+          encode ? "encoding" : "decoding", coding == CT_UNDEF ? "" : "s",
+          coding == CT_UNDEF ? "" : " with different rules");
+        return;
+      }
+      if (coding == CT_UNDEF && !delayed) {
+        // the coding type is set by the external function's checker in this case;
+        // it's possible, that the function exists, but has not been reached yet;
+        // delay this function until everything else has been checked
+        Modules::delay_type_encode_check(this, encode);
+        return;
+      }
     }
     if (coding != CT_CUSTOM && !has_encoding(coding)) {
       error("Type '%s' cannot be coded with the selected method '%s'",
diff --git a/compiler2/Type.hh b/compiler2/Type.hh
index a23a222092e3e4e2bf3c06ef6f6e246b01bab31e..a210100a704fdc1729846322d9b722a0086209c6 100644
--- a/compiler2/Type.hh
+++ b/compiler2/Type.hh
@@ -201,7 +201,8 @@ namespace Common {
       CT_TEXT,  /**< TTCN-3 TEXT */
       CT_XER,    /**< ASN.1 XER */
       CT_JSON,   /**< TTCN-3 JSON */
-      CT_CUSTOM /**< user defined encoding */
+      CT_CUSTOM, /**< user defined encoding */
+      CT_MULTIPLE /**< multiple codings defined for an ASN.1 type */
     };
 
     /** selector for value checking algorithms */
@@ -307,6 +308,8 @@ namespace Common {
     string encoding_str;  // needed by codegen for encvalue() and decvalue()
     string decoding_str;
     bool coding_by_function;  // false - coding attribute is set, true - coding via coding function
+    MessageEncodingType_t asn_encoding; // set by the semantic analysis of encoding
+    MessageEncodingType_t asn_decoding; // and decoding external functions for ASN.1 types
     /** What kind of AST element owns the type.
      *  It may not be known at creation type, so it's initially OT_UNKNOWN.
      *  We want this information so we don't have to bother with XER
@@ -649,6 +652,7 @@ namespace Common {
     /** Sets the encoding or decoding function for the type (in case of custom
       * encoding). */
     void set_coding_function(bool encode, const string& function_name);
+    void set_asn_coding(bool encode, MessageEncodingType_t new_coding);
     void chk_coding(bool encode, bool delayed = false);
     bool is_coding_by_function() const;
     const string& get_coding(bool encode) const;
diff --git a/compiler2/record_of.c b/compiler2/record_of.c
index 828cd66de89fb62683f737322434ca40eeaed3a4..c98be28c2134ec4d9fc3deff9660f5666f62c6f7 100644
--- a/compiler2/record_of.c
+++ b/compiler2/record_of.c
@@ -1240,9 +1240,9 @@ void defRecordOfClass1(const struct_of_def *sdef, output_struct *output)
         "        after.XER_encode(UNIVERSAL_CHARSTRING_xer_, p_buf, p_flavor | ANY_ATTRIBUTES, p_indent, 0);\n"
         // Put this attribute in a dummy element and walk through it to check its validity
         "        TTCN_Buffer check_buf;\n"
-        "        check_buf.put_s(2, (unsigned char*)\"<a\");\n"
+        "        check_buf.put_s(2, (const unsigned char*)\"<a\");\n"
         "        check_buf.put_s(p_buf.get_len() - buf_start, p_buf.get_data() + buf_start);\n"
-        "        check_buf.put_s(2, (unsigned char*)\"/>\");"
+        "        check_buf.put_s(2, (const unsigned char*)\"/>\");"
         "        XmlReaderWrap checker(check_buf);\n"
         "        while (1 == checker.Read()) ;\n"
         "      }\n"
diff --git a/compiler2/ttcn3/AST_ttcn3.cc b/compiler2/ttcn3/AST_ttcn3.cc
index dec0bdcf1172bf404327ffd4ea4e6b696d98732d..3d9482329cad862d802c3cd37205da2f2e15ea4a 100644
--- a/compiler2/ttcn3/AST_ttcn3.cc
+++ b/compiler2/ttcn3/AST_ttcn3.cc
@@ -6573,6 +6573,10 @@ namespace Ttcn {
               function_type = EXTFUNC_MANUAL;
             }
           }
+          else if (input_type->is_ref() && input_type->get_type_refd()->is_asn1()) {
+            // let the input ASN.1 type know that this is its encoding type
+            input_type->get_type_refd()->set_asn_coding(true, encoding_type);
+          }
         }
       }
       if (output_type) {
@@ -6649,6 +6653,11 @@ namespace Ttcn {
             function_type = EXTFUNC_MANUAL;
           }
         }
+        else if (output_type != NULL && output_type->is_ref() &&
+                 output_type->get_type_refd()->is_asn1()) {
+          // let the output ASN.1 type know that this is its decoding type
+          output_type->get_type_refd()->set_asn_coding(false, encoding_type);
+        }
       }
       if (eb_list) eb_list->chk();
       chk_allowed_encode();
diff --git a/core2/Basetype2.cc b/core2/Basetype2.cc
index 695fdff6de0a1aae65ec6cc459dc8e7e6e2eff44..86195fc04d8cd7a5ac692a959e4108af3fac4e1c 100644
--- a/core2/Basetype2.cc
+++ b/core2/Basetype2.cc
@@ -1928,9 +1928,9 @@ int Record_Of_Type::XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf,
       
       // Put this attribute in a dummy element and walk through it to check its validity
       TTCN_Buffer check_buf;
-      check_buf.put_s(2, (unsigned char*)"<a");
+      check_buf.put_s(2, (const unsigned char*)"<a");
       check_buf.put_s(p_buf.get_len() - buf_start, p_buf.get_data() + buf_start);
-      check_buf.put_s(2, (unsigned char*)"/>");
+      check_buf.put_s(2, (const unsigned char*)"/>");
       XmlReaderWrap checker(check_buf);
       while (1 == checker.Read());
     }
diff --git a/regression_test/customEncoding/Custom1.ttcn b/regression_test/customEncoding/Custom1.ttcn
index 29b7c8ce7dee303552174dfddfa78bbdebfda602..8f253de2f4afe96fbaa3c192009fbc66da86f4b0 100644
--- a/regression_test/customEncoding/Custom1.ttcn
+++ b/regression_test/customEncoding/Custom1.ttcn
@@ -11,14 +11,17 @@
  *
  ******************************************************************************/
 
-// This module tests custom encoding
-// (encvalue and decvalue encode and decode values using manually written
-// external functions, as long as they have the same encoding name as the 
-// value's type)
+// This module tests custom encoding for TTCN-3 types and encoding for ASN.1 types
+// (Encvalue and decvalue encode and decode values of TTCN-3 types using manually written
+// external functions, as long as they have the same encoding name as the value's type.
+// A similar technique is used when using encvalue or decvalue on a value of
+// and ASN.1 type: an encoding/decoding external function, of a built-in encoding type,
+// must be declared for the ASN.1 type).
 module Custom1 {
 
 import from Custom2 all;
 import from Custom3 all;
+import from Types all;
 
 type record Msg {
   octetstring data optional,
@@ -237,6 +240,92 @@ testcase tc_custom_decmatch() runs on CT
   }
 }
 
+// these let encvalue and decvalue know which encoding to use for the ASN.1 type
+external function f_enc_seq(in Seq x) return octetstring
+  with { extension "prototype(convert) encode(JSON)" };
+  
+external function f_dec_seq(in octetstring x) return Seq
+  with { extension "prototype(convert) decode(JSON)" };
+  
+// Test 8.
+// Using encvalue and decvalue on the ASN.1 type Seq (with JSON encoding).
+testcase tc_asn() runs on CT
+{
+  var Seq x := { num := 10, str := "abc" };
+  var bitstring enc_exp := oct2bit(char2oct("{\n\t\"num\" : 10,\n\t\"str\" : \"abc\"\n}"));
+  var Seq dec_exp := x;
+  
+  var bitstring enc := encvalue(x);
+  if (enc != enc_exp) {
+    setverdict(fail, "Expected: ", enc_exp, ", got: ", enc);
+  }
+  var Seq dec;
+  var integer res := decvalue(enc_exp, dec);
+  if (res != 0) {
+    setverdict(fail, "Failed to decode ", enc_exp);
+  }
+  if (dec != dec_exp) {
+    setverdict(fail, "Expected: ", dec_exp, ", got: ", dec);
+  }
+  setverdict(pass);
+}
+
+// Test 9.
+// The redirected parameter is decoded into a value of ASN.1 type Seq.
+// Same input value as in test 8.
+testcase tc_asn_param_redirect() runs on CT
+{
+  connect(self:pt_proc, self:pt_proc);
+  var Seq val := { num := 10, str := "abc" };
+  var charstring str_fmt := "UTF-8";
+  var universal charstring val_enc := encvalue_unichar(val, str_fmt);
+  var Seq res;
+  pt_proc.reply(Sig: { p := val_enc });
+  timer tmr := 1.0;
+  tmr.start;
+  alt {
+    [] pt_proc.getreply(Sig: { p := val_enc }) -> param (res := @decoded(str_fmt) p) {
+      if (res != val) {
+        setverdict(fail, "Invalid decoded parameter. Expected: ", val, ", got: ", res);
+      }
+      else {
+        setverdict(pass);
+      }
+    }
+    [] pt_proc.getreply(Sig: { p := ?}) {
+      setverdict(fail, "Invalid reply received.");
+    }
+    [] tmr.timeout {
+      setverdict(fail, "Timed out.");
+    }
+  }
+}
+
+// Test 10.
+// Decoded content matching against a value of ASN.1 type Seq.
+// Same input value as in test 8.
+testcase tc_asn_decmatch() runs on CT
+{
+  connect(self:pt_msg, self:pt_msg);
+  var Seq val := { num := 10, str := "abc" };
+  var Msg msg := { data := omit, list := { encvalue(val) } };
+  var Seq res;
+  pt_msg.send(msg);
+  timer tmr := 1.0;
+  tmr.start;
+  alt {
+    [] pt_msg.receive(Msg: { data := omit, list := { decmatch val } }) {
+      setverdict(pass);
+    }
+    [] pt_msg.receive(?) {
+      setverdict(fail, "Invalid message received or decoded content matching failed.");
+    }
+    [] tmr.timeout {
+      setverdict(fail, "Timed out.");
+    }
+  }
+}
+
 control {
   execute(tc_custom1());
   execute(tc_custom2());
@@ -245,6 +334,9 @@ control {
   execute(tc_custom_unichar());
   execute(tc_custom_param_redirect());
   execute(tc_custom_decmatch());
+  execute(tc_asn());
+  execute(tc_asn_param_redirect());
+  execute(tc_asn_decmatch());
 }
 
 }
diff --git a/regression_test/customEncoding/Custom4.ttcn b/regression_test/customEncoding/Custom4.ttcn
index c3e68713a56ac1f96597e60bb4628030d29c36eb..9326226fe0675ac0d2457e35ffe57e075b3ae6d1 100644
--- a/regression_test/customEncoding/Custom4.ttcn
+++ b/regression_test/customEncoding/Custom4.ttcn
@@ -10,15 +10,16 @@
  *
  ******************************************************************************/
 
-// This module contains further tests for custom encodings
+// This module contains further tests for custom encodings and encodings for ASN.1 types
 // (in features only available in the Function Test Runtime).
 module Custom4 {
 
 import from Custom1 all;
 import from Custom2 all;
 import from Custom3 all;
+import from Types all;
 
-// Test 8 (RT2 only).
+// Test 11 (RT2 only).
 // Using custom encoding on a decoded value redirect.
 // Same input value as in test 1.
 testcase tc_custom_value_redirect() runs on CT
@@ -49,8 +50,39 @@ testcase tc_custom_value_redirect() runs on CT
   }
 }
 
+// Test 12 (RT2 only).
+// The redirected value is decoded into a value of ASN.1 type Seq.
+// Same input value as in test 8.
+testcase tc_asn_value_redirect() runs on CT
+{
+  connect(self:pt_msg, self:pt_msg);
+  var Seq val := { num := 10, str := "abc" };
+  var Msg msg := { data := bit2oct(encvalue(val)), list := { } };
+  var Seq res;
+  pt_msg.send(msg);
+  timer tmr := 1.0;
+  tmr.start;
+  alt {
+    [] pt_msg.receive(msg) -> value (res := @decoded data) {
+      if (res != val) {
+        setverdict(fail, "Invalid decoded value. Expected: ", val, ", got: ", res);
+      }
+      else {
+        setverdict(pass);
+      }
+    }
+    [] pt_msg.receive(?) {
+      setverdict(fail, "Invalid message received.");
+    }
+    [] tmr.timeout {
+      setverdict(fail, "Timed out.");
+    }
+  }
+}
+
 control {
   execute(tc_custom_value_redirect());
+  execute(tc_asn_value_redirect());
 }
 
 }
diff --git a/regression_test/customEncoding/Makefile b/regression_test/customEncoding/Makefile
index 21f701f43ac93fea3b7c4b0f103403fff6105a41..fee2198833b40b7655a1230a50cd0bb7655a999a 100644
--- a/regression_test/customEncoding/Makefile
+++ b/regression_test/customEncoding/Makefile
@@ -20,6 +20,7 @@ include $(TOPDIR)/Makefile.regression
 TTCN3_LIB = ttcn3$(RT2_SUFFIX)$(DYNAMIC_SUFFIX)
 
 TTCN3_MODULES = Custom1.ttcn Custom2.ttcn Custom3.ttcn
+ASN1_MODULES = Types.asn
 
 ifdef RT2
 TTCN3_MODULES += Custom4.ttcn
@@ -27,7 +28,7 @@ endif
 
 USER_SOURCES = Coders.cc
 
-GENERATED_SOURCES = $(TTCN3_MODULES:.ttcn=.cc)
+GENERATED_SOURCES = $(TTCN3_MODULES:.ttcn=.cc) $(ASN1_MODULES:.asn=.cc)
 GENERATED_HEADERS = $(GENERATED_SOURCES:.cc=.hh)
 ifdef CODE_SPLIT
 GENERATED_SOURCES := $(foreach file, $(GENERATED_SOURCES:.cc=), $(addprefix $(file), .cc _seq.cc _set.cc  _seqof.cc _setof.cc _union.cc))
diff --git a/regression_test/customEncoding/Types.asn b/regression_test/customEncoding/Types.asn
new file mode 100644
index 0000000000000000000000000000000000000000..b3ce172b1ce327e92a7272335bfa32f57070a054
--- /dev/null
+++ b/regression_test/customEncoding/Types.asn
@@ -0,0 +1,26 @@
+--/////////////////////////////////////////////////////////////////////////////
+-- Copyright (c) 2000-2016 Ericsson Telecom AB
+-- All rights reserved. This program and the accompanying materials
+-- are made available under the terms of the Eclipse Public License v1.0
+-- which accompanies this distribution, and is available at
+-- http://www.eclipse.org/legal/epl-v10.html
+--
+-- Contributors:
+--   Baranyi, Botond
+--
+--/////////////////////////////////////////////////////////////////////////////
+
+Types
+DEFINITIONS
+
+AUTOMATIC TAGS ::=
+
+BEGIN
+IMPORTS;
+
+Seq ::= SEQUENCE {
+  num INTEGER,
+  str VisibleString
+}
+
+END
diff --git a/usrguide/referenceguide.doc b/usrguide/referenceguide.doc
index 034462f3ca0ea6aa904a5b2c53084a98ad7ab030..8756b417fd8bd5d0684cc4b4e2149ea7e0c65089 100644
Binary files a/usrguide/referenceguide.doc and b/usrguide/referenceguide.doc differ