Merge branch 'master' of git.osmocom.org:erlang/osmo_ss7
diff --git a/src/sccp_codec.erl b/src/sccp_codec.erl
index 6293fac..a3b0352 100644
--- a/src/sccp_codec.erl
+++ b/src/sccp_codec.erl
@@ -120,7 +120,7 @@
 % Parse incoming SCCP message, one function for every message type
 parse_sccp_msgt(?SCCP_MSGT_CR, DataBin) ->
 	% first get the fixed part
-	<<_:8, SrcLocalRef:24/big, ProtoClass:8, RemainVar/binary >> = DataBin,
+	<<_:8, SrcLocalRef:24/big, PCOpt:4, ProtoClass:4, RemainVar/binary >> = DataBin,
 	% variable length fixed part
 	<<PtrVar:8, PtrOpt:8, _/binary>> = RemainVar,
 	CalledPartyLen = binary:at(RemainVar, PtrVar),
@@ -131,14 +131,16 @@
 	OptList = parse_sccp_opts(OptBin, []),
 	%OptList = [],
 	% build parsed list of message
-	[{src_local_ref, SrcLocalRef},{protocol_class, ProtoClass},{called_party_addr, CalledPartyDec}|OptList];
+	[{src_local_ref, SrcLocalRef},{protocol_class, {ProtoClass, PCOpt}},
+	 {called_party_addr, CalledPartyDec} | OptList];
 parse_sccp_msgt(?SCCP_MSGT_CC, DataBin) ->
 	% first get the fixed part
-	<<_:8, DstLocalRef:24/big, SrcLocalRef:24/big, ProtoClass:8, Remain/binary >> = DataBin,
+	<<_:8, DstLocalRef:24/big, SrcLocalRef:24/big, PCOpt:4, ProtoClass:4, Remain/binary >> = DataBin,
 	% optional part
 	OptList = parse_sccp_opts(Remain, []),
 	% build parsed list of message
-	[{dst_local_ref, DstLocalRef},{src_local_ref, SrcLocalRef},{protocol_class, ProtoClass}|OptList];
+	[{dst_local_ref, DstLocalRef},{src_local_ref, SrcLocalRef},
+	 {protocol_class, {ProtoClass, PCOpt}} | OptList];
 parse_sccp_msgt(?SCCP_MSGT_CREF, DataBin) ->
 	% first get the fixed part
 	<<_:8, DstLocalRef:24/big, RefusalCause:8, Remain/binary >> = DataBin,
@@ -172,7 +174,7 @@
 	<<_:8, DstLocalRef:24/big, RxSeqnr:8, Credit:8>> = DataBin,
 	[{dst_local_ref, DstLocalRef},{rx_seq_nr, RxSeqnr},{credit, Credit}];
 parse_sccp_msgt(?SCCP_MSGT_UDT, DataBin) ->
-	<<_:8, ProtoClass:8, CalledPartyPtr:8, CallingPartyPtr:8, DataPtr:8, Remain/binary >> = DataBin,
+	<<_:8, PCOpt:4, ProtoClass:4, CalledPartyPtr:8, CallingPartyPtr:8, DataPtr:8, Remain/binary >> = DataBin,
 	% variable part
 	CalledPartyLen = binary:at(Remain, CalledPartyPtr-3),
 	CalledParty = binary:part(Remain, CalledPartyPtr-3+1, CalledPartyLen),
@@ -182,7 +184,7 @@
 	CallingPartyDec = parse_sccp_addr(CallingParty),
 	DataLen = binary:at(Remain, DataPtr-1),
 	UserData = binary:part(Remain, DataPtr-1+1, DataLen),
-	[{protocol_class, ProtoClass},{called_party_addr, CalledPartyDec},
+	[{protocol_class, {ProtoClass, PCOpt}},{called_party_addr, CalledPartyDec},
 	 {calling_party_addr, CallingPartyDec},{user_data, UserData}];
 parse_sccp_msgt(?SCCP_MSGT_UDTS, DataBin) ->
 	<<_:8, ReturnCause:8, CalledPartyPtr:8, CallingPartyPtr:8, DataPtr:8, Remain/binary >> = DataBin,
@@ -215,9 +217,9 @@
 	<<_:8, DstLocalRef:24/big, ErrCause:8>> = DataBin,
 	[{dst_local_ref, DstLocalRef},{error_cause, ErrCause}];
 parse_sccp_msgt(?SCCP_MSGT_IT, DataBin) ->
-	<<_:8, DstLocalRef:24/big, SrcLocalRef:24/big, ProtoClass:8, SegmSeq:16, Credit:8>> = DataBin,
+	<<_:8, DstLocalRef:24/big, SrcLocalRef:24/big, PCOpt: 4, ProtoClass:4, SegmSeq:16, Credit:8>> = DataBin,
 	[{dst_local_ref, DstLocalRef},{src_local_ref, SrcLocalRef},
-         {protocol_class, ProtoClass},{seq_segm, SegmSeq},{credit, Credit}].
+         {protocol_class, {ProtoClass, PCOpt}},{seq_segm, SegmSeq},{credit, Credit}].
 % FIXME: XUDT/XUDTS, LUDT/LUDTS
 
 % process one incoming SCCP message
@@ -319,15 +321,15 @@
 
 encode_sccp_msgt(?SCCP_MSGT_CR, Params) ->
 	SrcLocalRef = proplists:get_value(src_local_ref, Params),
-	ProtoClass = proplists:get_value(protocol_class, Params),
+	{ProtoClass, PCOpt} = proplists:get_value(protocol_class, Params),
 	OptBin = encode_sccp_opts(Params, []),
-	<<?SCCP_MSGT_CR:8, SrcLocalRef:24/big, ProtoClass:8, OptBin/binary>>;
+	<<?SCCP_MSGT_CR:8, SrcLocalRef:24/big, PCOpt:4, ProtoClass:4, OptBin/binary>>;
 encode_sccp_msgt(?SCCP_MSGT_CC, Params) ->
 	SrcLocalRef = proplists:get_value(src_local_ref, Params),
 	DstLocalRef = proplists:get_value(dst_local_ref, Params),
-	ProtoClass = proplists:get_value(protocol_class, Params),
+	{ProtoClass, PCOpt} = proplists:get_value(protocol_class, Params),
 	OptBin = encode_sccp_opts(Params, []),
-	<<?SCCP_MSGT_CC:8, DstLocalRef:24/big, SrcLocalRef:24/big, ProtoClass:8, OptBin/binary>>;
+	<<?SCCP_MSGT_CC:8, DstLocalRef:24/big, SrcLocalRef:24/big, PCOpt:4, ProtoClass:4, OptBin/binary>>;
 encode_sccp_msgt(?SCCP_MSGT_CREF, Params) ->
 	DstLocalRef = proplists:get_value(dst_local_ref, Params),
 	RefusalCause = proplists:get_value(refusal_cause, Params),
@@ -361,7 +363,7 @@
 	Credit = proplists:get_value(credit, Params),
 	<<?SCCP_MSGT_AK:8, DstLocalRef:24/big, RxSeqnr:8, Credit:8>>;
 encode_sccp_msgt(?SCCP_MSGT_UDT, Params) ->
-	ProtoClass = proplists:get_value(protocol_class, Params),
+	{ProtoClass, PCOpt} = proplists:get_value(protocol_class, Params),
 	CalledParty = proplists:get_value(called_party_addr, Params),
 	CalledPartyEnc = encode_sccp_addr(CalledParty),
 	CalledPartyLen = byte_size(CalledPartyEnc),
@@ -377,7 +379,7 @@
 	Remain = <<CalledPartyLen:8, CalledPartyEnc/binary,
 		   CallingPartyLen:8, CallingPartyEnc/binary,
 		   UserDataLen:8, UserData/binary>>,
-	<<?SCCP_MSGT_UDT:8, ProtoClass:8, CalledPartyPtr:8, CallingPartyPtr:8, DataPtr:8, Remain/binary>>;
+	<<?SCCP_MSGT_UDT:8, PCOpt:4, ProtoClass:4, CalledPartyPtr:8, CallingPartyPtr:8, DataPtr:8, Remain/binary>>;
 encode_sccp_msgt(?SCCP_MSGT_UDTS, Params) ->
 	ReturnCause = proplists:get_value(return_cause, Params),
 	CalledParty = proplists:get_value(called_party_addr, Params),
@@ -421,10 +423,10 @@
 encode_sccp_msgt(?SCCP_MSGT_IT, Params) ->
 	DstLocalRef = proplists:get_value(dst_local_ref, Params),
 	SrcLocalRef = proplists:get_value(src_local_ref, Params),
-	ProtoClass = proplists:get_value(protocol_class, Params),
+	{ProtoClass, PCOpt} = proplists:get_value(protocol_class, Params),
 	SegmSeq = proplists:get_value(seq_segm, Params),
 	Credit = proplists:get_value(credit, Params),
-	<<?SCCP_MSGT_IT:8, DstLocalRef:24/big, SrcLocalRef:24/big, ProtoClass:8, SegmSeq:16, Credit:8>>.
+	<<?SCCP_MSGT_IT:8, DstLocalRef:24/big, SrcLocalRef:24/big, PCOpt:4, ProtoClass:4, SegmSeq:16, Credit:8>>.
 % FIXME: XUDT/XUDTS, LUDT/LUDTS
 
 
diff --git a/test/sccp_codec_tests.erl b/test/sccp_codec_tests.erl
index 783febe..f7ec730 100644
--- a/test/sccp_codec_tests.erl
+++ b/test/sccp_codec_tests.erl
@@ -7,7 +7,7 @@
 
 -define(SCCP_MSG_BIN, <<9,0,3,13,24,10,18,7,0,18,4,83,132,9,0,23,11,18,6,0,18,4,68,119,88,16,70,35,67,100,65,73,4,81,1,2,200,107,42,40,40,6,7,0,17,134,5,1,1,1,160,29,97,27,128,2,7,128,161,9,6,7,4,0,0,1,0,1,3,162,3,2,1,0,163,5,161,3,2,1,0,108,13,163,11,2,1,64,2,1,8,48,3,10,1,0>>).
 
--define(SCCP_MSG_DEC, {sccp_msg,9,[{protocol_class,0},{called_party_addr,{sccp_addr,0,0,undef,7,{global_title,4,4,0,2,1,[3,5,4,8,9,0,0,0,7,1]}}},{calling_party_addr,{sccp_addr,0,0,undef,6,{global_title,4,4,0,2,1,[4,4,7,7,8,5,0,1,6,4,3,2]}}},{user_data,<<100,65,73,4,81,1,2,200,107,42,40,40,6,7,0,17,134,5,1,1,1,160,29,97,27,128,2,7,128,161,9,6,7,4,0,0,1,0,1,3,162,3,2,1,0,163,5,161,3,2,1,0,108,13,163,11,2,1,64,2,1,8,48,3,10,1,0>>}]}).
+-define(SCCP_MSG_DEC, {sccp_msg,9,[{protocol_class,{0,0}},{called_party_addr,{sccp_addr,0,0,undef,7,{global_title,4,4,0,2,1,[3,5,4,8,9,0,0,0,7,1]}}},{calling_party_addr,{sccp_addr,0,0,undef,6,{global_title,4,4,0,2,1,[4,4,7,7,8,5,0,1,6,4,3,2]}}},{user_data,<<100,65,73,4,81,1,2,200,107,42,40,40,6,7,0,17,134,5,1,1,1,160,29,97,27,128,2,7,128,161,9,6,7,4,0,0,1,0,1,3,162,3,2,1,0,163,5,161,3,2,1,0,108,13,163,11,2,1,64,2,1,8,48,3,10,1,0>>}]}).
 
 parse_test() ->
 	?assertEqual({ok, ?SCCP_MSG_DEC}, sccp_codec:parse_sccp_msg(?SCCP_MSG_BIN)).