Some more ISUP decoding and encoding routines, mostly for phone numbers
diff --git a/src/isup_codec.erl b/src/isup_codec.erl
index 025808f..a98da31 100644
--- a/src/isup_codec.erl
+++ b/src/isup_codec.erl
@@ -23,6 +23,71 @@
 
 -export([parse_isup_msg/1, encode_isup_msg/1]).
 
+parse_isup_party(<<>>, OddEven, DigitList) ->
+	% in case of odd number of digits, we need to cut the last
+	case OddEven of
+		1 ->
+			lists:sublist(DigitList, lists:length(DigitList)-1);
+		0 ->
+			DigitList
+	end;
+parse_isup_party(BcdBin, OddEven, DigitList) ->
+	<<Second:4, First:4, Remain/binary>> = BcdBin,
+	NewDigits = [First, Second],
+	parse_isup_party(Remain, OddEven, DigitList ++ NewDigits).
+
+parse_isup_party(BinBcd, OddEven) when is_binary(BinBcd) ->
+	parse_isup_party(BinBcd, OddEven, []).
+
+
+% parse a single option
+parse_isup_opt(?ISUP_PAR_CALLED_P_NUM, OptLen, Content) ->
+	% C.3.7 Called Party Number
+	<<OddEven:1, Nature:7, Inn:1, NumPlan:3, 0:4, Remain/binary>> = Content,
+	PhoneNum = parse_isup_party(Remain, OddEven),
+	{OptType, #party_number{nature_of_addr_ind = Nature,
+				internal_net_num = Inn,
+				numbering_plan = NumPlan,
+				phone_number = PhoneNum}};
+parse_isup_opt(?ISUP_PAR_CALLING_P_NUM, OptLen, Content) ->
+	% C.3.8 Calling Party Number
+	<<OddEven:1, Nature:7, Ni:1, NumPlan:3, PresRestr:2, Screen:2, Remain/binary>> = Content,
+	PhoneNum = parse_isup_party(Remain, OddEven),
+	{OptType, #party_number{nature_of_addr_ind = Nature,
+				number_incompl_ind = Ni,
+				numbering_plan = NumPlan,
+				present_restrict = PresRestr,
+				screening_ind = Screen,
+				phone_number = PhoneNum}};
+parse_isup_opt(?ISUP_PAR_CONNECTED_NUM, OptLen, Content) ->
+	% C.3.14 Connected Number
+	<<OddEven:1, Nature:7, 0:1, NumPlan:3, PresRestr:2, Screen:2, Remain/binary>> = Content,
+	PhoneNum = parse_isup_party(Remain, OddEven),
+	{OptType, #party_number{nature_of_addr_ind = Nature,
+				numbering_plan = NumPlan,
+				present_restrict = PresRestr,
+				screening_ind = Screen,
+				phone_number = PhoneNum}};
+parse_isup_opt(?ISUP_PAR_SUBSEQ_NUM, OptLen, Content) ->
+	% C.3.32 Subsequent Number
+	<<OddEven:1, Spare:7, Remain/binary>> = Content,
+	PhoneNum = parse_isup_party(Remain, OddEven),
+	{OptType, #party_number{phone_number = PhoneNum}};
+parse_isup_opt(OptType, OptLen, Content) ->
+	{OptType, {OptLen, Content}}.
+
+% parse a Binary into a list of options
+parse_isup_opts(<<>>, OptList) ->
+	% empty list
+	OptList;
+parse_isup_opts(<<0>>, OptList) ->
+	% end of options
+	OptList;
+parse_isup_opts(OptBin, OptList) when is_binary(OptBin) ->
+	<<OptType:8, OptLen:8, Content:OptLen/binary, Remain/binary>> = OptBin,
+	NewOpt = parse_isup_opt(OptType, OptLen, Content),
+	parse_isup_opts(Remain, [NewOpt|OptList]).
+
 % References to 'Tabe C-xxx' are to Annex C of Q.767
 
 % Default case: no fixed and no variable parts, only options
@@ -30,29 +95,29 @@
 parse_isup_msgt(M, Bin) when
 	M == ?ISUP_MSGT_ANM;
 	M == ?ISUP_MSGT_RLC;
-	M == ?ISUP_MSGT_FOT;
+	M == ?ISUP_MSGT_FOT ->
 		parse_isup_opts(Bin);
 % Table C-5	Address complete
 parse_isup_msgt(?ISUP_MSGT_ACM, Bin) ->
 	<<BackCallInd:16, Remain/binary>> = Bin,
 	BciOpt = {backward_call_ind, BackCallInd},
-	Opts = parse_isup_opts(Remain)
+	Opts = parse_isup_opts(Remain),
 	[BciOpt|Opts];
 % Table C-7	Call progress
 parse_isup_msgt(?ISUP_MSGT_CPG, Bin) ->
 	<<EventInf:8, Remain/binary>> = Bin,
 	BciOpt = {event_info, EventInf},
-	Opts = parse_isup_opts(Remain)
+	Opts = parse_isup_opts(Remain),
 	[BciOpt|Opts];
 % Table C-9	Circuit group reset acknowledgement
 parse_isup_msgt(?ISUP_MSGT_GRA, Bin) ->
 	% V: Range and status
-
+	0;
 % Table C-11	Connect
 parse_isup_msgt(?ISUP_MSGT_CON, Bin) ->
 	<<BackCallInd:16, Remain/binary>> = Bin,
 	BciOpt = {backward_call_ind, BackCallInd},
-	Opts = parse_isup_opts(Remain)
+	Opts = parse_isup_opts(Remain),
 	[BciOpt|Opts];
 % Table C-12	Continuity
 parse_isup_msgt(?ISUP_MSGT_COT, Bin) ->
@@ -64,23 +129,23 @@
 	FixedOpts = [{conn_ind_nature, CINat}, {fw_call_ind, FwCallInd}, {calling_cat, CallingCat},
 		     {transm_medium_req, TransmReq}],
 	% V: Called Party Number
-	VarOpts = FIXME;
+	VarOpts = FIXME,
 	Opts = parse_isup_opts(Remain),
 	[FixedOpts,VarOpts,Opts];
 % Table C-17	Release
 parse_isup_msgt(?ISUP_MSGT_REL, Bin) ->
 	% V: Cause indicators
-	VarOpts = FIXME;
+	VarOpts = FIXME,
 	Opts = parse_isup_opts(Remain),
 	[VarOpts,Opts];
 % Table C-19	Subsequent address
 parse_isup_msgt(?ISUP_MSGT_SAM, Bin) ->
 	% V: Subsequent number
-	VarOpts = FIXME;
+	VarOpts = FIXME,
 	Opts = parse_isup_opts(Remain),
 	[VarOpts,Opts];
 % Table C-21	Suspend, Resume
-parse_isup_msgt(Msgt, Bin) when Msgt == ?ISUP_MSGT_RES or Msgt == ?ISUP_MSGT_SUS ->
+parse_isup_msgt(Msgt, Bin) when Msgt == ?ISUP_MSGT_RES; Msgt == ?ISUP_MSGT_SUS ->
 	<<SuspResInd:8, Remain/binary>> = Bin,
 	FixedOpts = [{susp_res_ind, SuspResInd}],
 	Opts = parse_isup_opts(Remain),
@@ -116,3 +181,48 @@
 	<<0:4, Cic:12/big, MsgType:8, Remain/binary>> = DataBin,
 	Opts = parse_isup_msgt(MsgType, Remain),
 	#isup_msg{cic = Cic, msg_type = MsgType, parameters = Opts}.
+
+
+encode_isup_party(BcdList) ->
+	encode_isup_party(BcdList, <<>>, list:length(BcdList)).
+encode_isup_party([], Bin, NumDigits) ->
+	case NumDigits rem 2 of
+		1 ->
+			{Bin, 1};
+		0 ->
+			{Bin, 0}
+	end;
+encode_isup_party([First,Second|BcdList], Bin, NumDigits) ->
+	encode_isup_party(BcdList, <<Bin/binary, Second:4, First:4>>).
+	
+% encode a single option
+encode_isup_opt(?ISUP_PAR_CALLED_P_NUM,
+		#party_number{nature_of_addr_ind = Nature,
+			      internal_net_num = Inn,
+			      numbering_plan = NumPlan,
+			      phone_number=  PhoneNum}) ->
+	% C.3.7 Called Party Number
+	{PhoneBin, OddEven} = encode_isup_party(PhoneNum),
+	<<OddEven:1, Nature:7, Inn:1, NumPlan:3, 0:4, PhoneBin/binary>>.
+encode_isup_opt(?ISUP_PAR_CALLING_P_NUM,
+		#party_number{nature_of_addr_ind = Nature,
+			      number_incompl_ind = Ni,
+			      numbering_plan = NumPlan,
+			      present_restrict = PresRestr,
+			      screening_ind = Screen,
+			      phone_number=  PhoneNum}) ->
+	% C.3.8 Calling Party Number
+	{PhoneBin, OddEven} = encode_isup_party(PhoneNum),
+	<<OddEven:1, Nature:7, Ni:1, NumPlan:3, PresRestr:2, Screen:2, PhoneBin/binary>>;
+encode_isup_opt(?ISUP_PAR_CONNECTED_NUM,
+		#party_number{nature_of_addr_ind = Nature,
+			      numbering_plan = NumPlan,
+			      present_restrict = PresRestr,
+			      screening_ind = Screen,
+			      phone_number = PhoneNum}) ->
+	% C.3.14 Connected Number
+	{PhoneBin, OddEven} = encode_isup_party(PhoneNum),
+	<<OddEven:1, Nature:7, 0:1, NumPlan:3, PresRestr:2, Screen:2, PhoneBin/binary>>;
+encode_isup_opt(OptNum, {OptLen, Binary}) when is_binary(Binary) ->
+	Binary.
+