Merge remote-tracking branch 'origin' into enhancement-10-harmony
Merge in develop too. Conflicts: cmake_targets/CMakeLists.txt openair1/PHY/CODING/3gpplte_sse.c openair1/PHY/LTE_TRANSPORT/phich.c openair1/PHY/LTE_TRANSPORT/ulsch_demodulation.c openair1/SCHED/phy_mac_stub.c openair1/SCHED/phy_procedures_lte_eNb.c targets/RT/USER/lte-softmodem.c
This commit is contained in:
+1284
-1227
File diff suppressed because it is too large
Load Diff
@@ -1,18 +1,18 @@
|
||||
<testCaseList>
|
||||
|
||||
<MachineList>mozart calisson stevens nano amerique</MachineList>
|
||||
<MachineList>mozart tique stevens nano amerique</MachineList>
|
||||
<NFSResultsShare>/mnt/sradio/TEST_RESULTS/</NFSResultsShare>
|
||||
<GitOAI5GRepo>https://gitlab.eurecom.fr/oai/openairinterface5g.git</GitOAI5GRepo>
|
||||
<GitOpenair-cnRepo>https://gitlab.eurecom.fr/oai/openair-cn.git</GitOpenair-cnRepo>
|
||||
<GitOAI5GRepoBranch>develop</GitOAI5GRepoBranch>
|
||||
<GitOpenair-cnRepoBranch>develop</GitOpenair-cnRepoBranch>
|
||||
<CleanUpOldProgs>oaisim oaisim_nos1 lte-softmodem lte-softmodem-nos1 mme_gw run_epc auth_request run_hss oai_hss mme spgw hss hss_sim configure_cots* wvdial iperf iperf_script iperf_script_phone ping tshark rrh_gw iperf3 iperf3_script iperf3_script_phone</CleanUpOldProgs>
|
||||
<CleanUpOldProgs>oaisim oaisim_nos1 lte-softmodem lte-softmodem-nos1 mme_gw run_epc auth_request run_hss oai_hss mme spgw hss hss_sim configure_cots* wvdial iperf iperf_script iperf_script_phone ping tshark rrh_gw iperf3 iperf3_script iperf3_script_phone pppd</CleanUpOldProgs>
|
||||
<CleanUpAluLteBox>sudo -S -E /opt/ltebox/tools/stop_ltebox</CleanUpAluLteBox>
|
||||
<ExmimoRfStop>$OPENAIR_DIR/cmake_targets/build_oai -w EXMIMO -c; sudo -S -E $OPENAIR_DIR/cmake_targets/tools/stop_exmimo2; sudo -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; sudo -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_huaweiE398_ue.py --reset-ue; sudo -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_sony_experia_m4_ue.py --stop-ue; uname -a; sudo -E dmesg</ExmimoRfStop>
|
||||
<Timeout_execution>36000</Timeout_execution>
|
||||
<TestCaseExclusionList>010141 0102+ 010304 010305 0104+ 015502 015505 015506 015507 015508 015509 015510 015511 015602 015605 015702 015705 015802 015805 016102 016105 016502 016505 017002 017005 017502 017505 018002 018005 018502 018505 025502 025505</TestCaseExclusionList>
|
||||
<nruns_lte-softmodem>3</nruns_lte-softmodem>
|
||||
<MachineListGeneric>mozart calisson stevens nano amerique</MachineListGeneric>
|
||||
<MachineListGeneric>mozart tique stevens nano amerique </MachineListGeneric>
|
||||
<testCase id="010101" >
|
||||
<class>compilation</class>
|
||||
<desc>Build oaisim.Rel8</desc>
|
||||
@@ -874,7 +874,7 @@
|
||||
<testCase id="015500" >
|
||||
<class>lte-softmodem</class>
|
||||
<desc></desc>
|
||||
<eNB>calisson</eNB>
|
||||
<eNB>tique</eNB>
|
||||
<UE>stevens</UE>
|
||||
<EPC>amerique</EPC>
|
||||
<TimeOut_cmd>390</TimeOut_cmd>
|
||||
@@ -891,10 +891,10 @@
|
||||
targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf frame_type \"FDD\"
|
||||
targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf nb_antennas_rx 1
|
||||
targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf nb_antennas_tx 1
|
||||
targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth5\"
|
||||
targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.82/24\"
|
||||
targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_INTERFACE_NAME_FOR_S1U \"eth5\"
|
||||
targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.82/24\"
|
||||
targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth1\"
|
||||
targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.147/24\"
|
||||
targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_INTERFACE_NAME_FOR_S1U \"eth1\"
|
||||
targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.147/24\"
|
||||
targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_PORT_FOR_S1U 2152</eNB_config_file>
|
||||
<eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog>
|
||||
<eNB_compile_prog_args>--eNB -w USRP -x -c </eNB_compile_prog_args>
|
||||
@@ -949,7 +949,7 @@
|
||||
<testCase id="015501" >
|
||||
<class>lte-softmodem</class>
|
||||
<desc></desc>
|
||||
<eNB>calisson</eNB>
|
||||
<eNB>tique</eNB>
|
||||
<UE>stevens</UE>
|
||||
<EPC>amerique</EPC>
|
||||
<TimeOut_cmd>390</TimeOut_cmd>
|
||||
@@ -966,10 +966,10 @@
|
||||
targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf frame_type \"FDD\"
|
||||
targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf nb_antennas_rx 1
|
||||
targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf nb_antennas_tx 1
|
||||
targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth5\"
|
||||
targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.82/24\"
|
||||
targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_INTERFACE_NAME_FOR_S1U \"eth5\"
|
||||
targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.82/24\"
|
||||
targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth1\"
|
||||
targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.147/24\"
|
||||
targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_INTERFACE_NAME_FOR_S1U \"eth1\"
|
||||
targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.147/24\"
|
||||
targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_PORT_FOR_S1U 2152</eNB_config_file>
|
||||
<eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog>
|
||||
<eNB_compile_prog_args>--eNB -w USRP -x -c </eNB_compile_prog_args>
|
||||
@@ -1097,7 +1097,7 @@
|
||||
<testCase id="015503" >
|
||||
<class>lte-softmodem</class>
|
||||
<desc></desc>
|
||||
<eNB>calisson</eNB>
|
||||
<eNB>tique</eNB>
|
||||
<UE>stevens</UE>
|
||||
<EPC>amerique</EPC>
|
||||
<TimeOut_cmd>390</TimeOut_cmd>
|
||||
@@ -1114,10 +1114,10 @@
|
||||
targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf frame_type \"FDD\"
|
||||
targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf nb_antennas_rx 1
|
||||
targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf nb_antennas_tx 1
|
||||
targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth5\"
|
||||
targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.82/24\"
|
||||
targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_INTERFACE_NAME_FOR_S1U \"eth5\"
|
||||
targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.82/24\"
|
||||
targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth1\"
|
||||
targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.147/24\"
|
||||
targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_INTERFACE_NAME_FOR_S1U \"eth1\"
|
||||
targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.147/24\"
|
||||
targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_PORT_FOR_S1U 2152</eNB_config_file>
|
||||
<eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog>
|
||||
<eNB_compile_prog_args>--eNB -w USRP -x -c </eNB_compile_prog_args>
|
||||
@@ -1139,7 +1139,7 @@
|
||||
<UE_pre_exec_args></UE_pre_exec_args>
|
||||
<UE_main_exec>$OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 10; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue </UE_main_exec>
|
||||
<UE_main_exec_args></UE_main_exec_args>
|
||||
<UE_traffic_exec>$OPENAIR_DIR/cmake_targets/autotests/tools/iperf3_script 1 ppp0 -c 192.172.0.1 -i 1 -u -f m -B 192.172.0.2 -b 10M -R</UE_traffic_exec>
|
||||
<UE_traffic_exec>$OPENAIR_DIR/cmake_targets/autotests/tools/iperf3_script 1 ppp0 -c 192.172.0.1 -i 1 -u -f m -B 192.172.0.2 -b 17M -R</UE_traffic_exec>
|
||||
<UE_traffic_exec_args></UE_traffic_exec_args>
|
||||
<UE_terminate_missing_procs>False</UE_terminate_missing_procs>
|
||||
<UE_stop_script>sudo -S -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue </UE_stop_script>
|
||||
@@ -1170,7 +1170,7 @@
|
||||
<testCase id="015504" >
|
||||
<class>lte-softmodem</class>
|
||||
<desc></desc>
|
||||
<eNB>calisson</eNB>
|
||||
<eNB>tique</eNB>
|
||||
<UE>stevens</UE>
|
||||
<EPC>amerique</EPC>
|
||||
<TimeOut_cmd>390</TimeOut_cmd>
|
||||
@@ -1187,10 +1187,10 @@
|
||||
targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf frame_type \"FDD\"
|
||||
targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf nb_antennas_rx 1
|
||||
targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf nb_antennas_tx 1
|
||||
targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth5\"
|
||||
targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.82/24\"
|
||||
targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_INTERFACE_NAME_FOR_S1U \"eth5\"
|
||||
targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.82/24\"
|
||||
targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth1\"
|
||||
targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.147/24\"
|
||||
targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_INTERFACE_NAME_FOR_S1U \"eth1\"
|
||||
targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.147/24\"
|
||||
targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf ENB_PORT_FOR_S1U 2152</eNB_config_file>
|
||||
<eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog>
|
||||
<eNB_compile_prog_args>--eNB -w USRP -x -c </eNB_compile_prog_args>
|
||||
@@ -1211,7 +1211,7 @@
|
||||
<UE_pre_exec_args></UE_pre_exec_args>
|
||||
<UE_main_exec>$OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 10; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue </UE_main_exec>
|
||||
<UE_main_exec_args></UE_main_exec_args>
|
||||
<UE_traffic_exec>$OPENAIR_DIR/cmake_targets/autotests/tools/iperf3_script 1 ppp0 -c 192.172.0.1 -i 1 -u -f m -B 192.172.0.2 -b 30M -R</UE_traffic_exec>
|
||||
<UE_traffic_exec>$OPENAIR_DIR/cmake_targets/autotests/tools/iperf3_script 1 ppp0 -c 192.172.0.1 -i 1 -u -f m -B 192.172.0.2 -b 34M -R</UE_traffic_exec>
|
||||
<UE_traffic_exec_args></UE_traffic_exec_args>
|
||||
<UE_search_expr_true>throughput_test min=8.0Mbits/sec max=9.0Mbits/sec average=8.5Mbits/sec </UE_search_expr_true>
|
||||
<UE_search_expr_false></UE_search_expr_false>
|
||||
@@ -2854,7 +2854,7 @@ c
|
||||
targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf ENB_PORT_FOR_S1U 2152</eNB_config_file>
|
||||
<eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog>
|
||||
<eNB_compile_prog_args>--eNB -w USRP -x -c </eNB_compile_prog_args>
|
||||
<eNB_pre_exec>$OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash ; sudo -E -S /usr/local/bin/niusrprio_pcie start ; dmesg|tail</eNB_pre_exec>
|
||||
<eNB_pre_exec>$OPENAIR_DIR/cmake_targets/autotests/tools/configure_usrpb210.py --stop-usrpb210 ; $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash ; sudo -E -S /usr/local/bin/niusrprio_pcie start ; dmesg|tail</eNB_pre_exec>
|
||||
<eNB_pre_exec_args></eNB_pre_exec_args>
|
||||
<eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem</eNB_main_exec>
|
||||
<eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf -W </eNB_main_exec_args>
|
||||
@@ -2926,7 +2926,7 @@ c
|
||||
targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf ENB_PORT_FOR_S1U 2152</eNB_config_file>
|
||||
<eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog>
|
||||
<eNB_compile_prog_args>--eNB -w USRP -x -c </eNB_compile_prog_args>
|
||||
<eNB_pre_exec>$OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash ; sudo -E -S /usr/local/bin/niusrprio_pcie start ; dmesg|tail</eNB_pre_exec>
|
||||
<eNB_pre_exec>$OPENAIR_DIR/cmake_targets/autotests/tools/configure_usrpb210.py --stop-usrpb210 ; $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash ; sudo -E -S /usr/local/bin/niusrprio_pcie start ; dmesg|tail</eNB_pre_exec>
|
||||
<eNB_pre_exec_args></eNB_pre_exec_args>
|
||||
<eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem</eNB_main_exec>
|
||||
<eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf -W </eNB_main_exec_args>
|
||||
@@ -2997,7 +2997,7 @@ c
|
||||
targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf ENB_PORT_FOR_S1U 2152</eNB_config_file>
|
||||
<eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog>
|
||||
<eNB_compile_prog_args>--eNB -w USRP -x -c </eNB_compile_prog_args>
|
||||
<eNB_pre_exec>$OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash ; sudo -E -S /usr/local/bin/niusrprio_pcie start ; dmesg|tail</eNB_pre_exec>
|
||||
<eNB_pre_exec>$OPENAIR_DIR/cmake_targets/autotests/tools/configure_usrpb210.py --stop-usrpb210 ; $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash ; sudo -E -S /usr/local/bin/niusrprio_pcie start ; dmesg|tail</eNB_pre_exec>
|
||||
<eNB_pre_exec_args></eNB_pre_exec_args>
|
||||
<eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem</eNB_main_exec>
|
||||
<eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf -W </eNB_main_exec_args>
|
||||
@@ -3015,7 +3015,7 @@ c
|
||||
<UE_pre_exec_args></UE_pre_exec_args>
|
||||
<UE_main_exec>$OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 10; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue </UE_main_exec>
|
||||
<UE_main_exec_args></UE_main_exec_args>
|
||||
<UE_traffic_exec>$OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -B 192.172.0.2</UE_traffic_exec>
|
||||
<UE_traffic_exec>$OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 17Mbits/s -B 192.172.0.2</UE_traffic_exec>
|
||||
<UE_traffic_exec_args></UE_traffic_exec_args>
|
||||
<UE_search_expr_true></UE_search_expr_true>
|
||||
<UE_search_expr_false></UE_search_expr_false>
|
||||
@@ -3069,7 +3069,7 @@ c
|
||||
targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf ENB_PORT_FOR_S1U 2152</eNB_config_file>
|
||||
<eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog>
|
||||
<eNB_compile_prog_args>--eNB -w USRP -x -c </eNB_compile_prog_args>
|
||||
<eNB_pre_exec>$OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash ; sudo -E -S /usr/local/bin/niusrprio_pcie start ; dmesg|tail</eNB_pre_exec>
|
||||
<eNB_pre_exec>$OPENAIR_DIR/cmake_targets/autotests/tools/configure_usrpb210.py --stop-usrpb210 ; $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash ; sudo -E -S /usr/local/bin/niusrprio_pcie start ; dmesg|tail</eNB_pre_exec>
|
||||
<eNB_pre_exec_args></eNB_pre_exec_args>
|
||||
<eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem</eNB_main_exec>
|
||||
<eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf -W </eNB_main_exec_args>
|
||||
@@ -3087,7 +3087,7 @@ c
|
||||
<UE_pre_exec_args></UE_pre_exec_args>
|
||||
<UE_main_exec>$OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 10; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue </UE_main_exec>
|
||||
<UE_main_exec_args></UE_main_exec_args>
|
||||
<UE_traffic_exec>$OPENAIR_DIR/cmake_targets/autotests/tools/iperf3_script 1 ppp0 -c 192.172.0.1 -i 1 -u -f m -B 192.172.0.2 -b 10M -R</UE_traffic_exec>
|
||||
<UE_traffic_exec>$OPENAIR_DIR/cmake_targets/autotests/tools/iperf3_script 1 ppp0 -c 192.172.0.1 -i 1 -u -f m -B 192.172.0.2 -b 17M -R</UE_traffic_exec>
|
||||
<UE_traffic_exec_args></UE_traffic_exec_args>
|
||||
<UE_terminate_missing_procs>False</UE_terminate_missing_procs>
|
||||
<UE_stop_script>sudo -S -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue </UE_stop_script>
|
||||
@@ -3140,7 +3140,7 @@ c
|
||||
targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf ENB_PORT_FOR_S1U 2152</eNB_config_file>
|
||||
<eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog>
|
||||
<eNB_compile_prog_args>--eNB -w USRP -x -c </eNB_compile_prog_args>
|
||||
<eNB_pre_exec>$OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash ; sudo -E -S /usr/local/bin/niusrprio_pcie start ; dmesg|tail</eNB_pre_exec>
|
||||
<eNB_pre_exec>$OPENAIR_DIR/cmake_targets/autotests/tools/configure_usrpb210.py --stop-usrpb210 ; $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash ; sudo -E -S /usr/local/bin/niusrprio_pcie start ; dmesg|tail</eNB_pre_exec>
|
||||
<eNB_pre_exec_args>sudo -E -S /usr/local/bin/niusrprio_pcie start ; dmesg|tail</eNB_pre_exec_args>
|
||||
<eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem</eNB_main_exec>
|
||||
<eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf -W </eNB_main_exec_args>
|
||||
@@ -3158,7 +3158,7 @@ c
|
||||
<UE_pre_exec_args></UE_pre_exec_args>
|
||||
<UE_main_exec>$OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 10; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue </UE_main_exec>
|
||||
<UE_main_exec_args></UE_main_exec_args>
|
||||
<UE_traffic_exec>$OPENAIR_DIR/cmake_targets/autotests/tools/iperf3_script 1 ppp0 -c 192.172.0.1 -i 1 -u -f m -B 192.172.0.2 -b 20M -R</UE_traffic_exec>
|
||||
<UE_traffic_exec>$OPENAIR_DIR/cmake_targets/autotests/tools/iperf3_script 1 ppp0 -c 192.172.0.1 -i 1 -u -f m -B 192.172.0.2 -b 35M -R</UE_traffic_exec>
|
||||
<UE_traffic_exec_args></UE_traffic_exec_args>
|
||||
<UE_terminate_missing_procs>False</UE_terminate_missing_procs>
|
||||
<UE_stop_script>sudo -S -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue </UE_stop_script>
|
||||
@@ -3211,7 +3211,7 @@ c
|
||||
targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf ENB_PORT_FOR_S1U 2152</eNB_config_file>
|
||||
<eNB_compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</eNB_compile_prog>
|
||||
<eNB_compile_prog_args>--eNB -w USRP -x -c </eNB_compile_prog_args>
|
||||
<eNB_pre_exec>sudo -E -S /usr/local/bin/niusrprio_pcie start ; dmesg|tail</eNB_pre_exec>
|
||||
<eNB_pre_exec>$OPENAIR_DIR/cmake_targets/autotests/tools/configure_usrpb210.py --stop-usrpb210 ; $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash ; sudo -E -S /usr/local/bin/niusrprio_pcie start ; dmesg|tail</eNB_pre_exec>
|
||||
<eNB_pre_exec_args></eNB_pre_exec_args>
|
||||
<eNB_main_exec>$OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem</eNB_main_exec>
|
||||
<eNB_main_exec_args> -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpx310.conf -W </eNB_main_exec_args>
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
import time
|
||||
import serial
|
||||
import os
|
||||
from socket import AF_INET
|
||||
from pyroute2 import IPRoute
|
||||
import sys
|
||||
import re
|
||||
@@ -62,7 +63,7 @@ def find_open_port():
|
||||
while True:
|
||||
if os.path.exists(serial_port) == True:
|
||||
return serial_port
|
||||
for port in range(2,100):
|
||||
for port in range(0,100):
|
||||
serial_port_tmp = '/dev/ttyUSB'+str(port)
|
||||
if os.path.exists(serial_port_tmp) == True:
|
||||
print 'New Serial Port : ' + serial_port_tmp
|
||||
@@ -97,11 +98,12 @@ signal.signal(signal.SIGINT, signal_handler)
|
||||
#ser.isOpen()
|
||||
|
||||
class pppThread (threading.Thread):
|
||||
def __init__(self, threadID, name, counter):
|
||||
def __init__(self, threadID, name, counter,port):
|
||||
threading.Thread.__init__(self)
|
||||
self.threadID = threadID
|
||||
self.name = name
|
||||
self.counter = counter
|
||||
self.port=port
|
||||
def run(self):
|
||||
print "Starting " + self.name
|
||||
#Here we keep running pppd thread in indefinite loop as this script terminates sometimes
|
||||
@@ -111,6 +113,10 @@ class pppThread (threading.Thread):
|
||||
print "Starting wvdial now..."
|
||||
print 'exit_flag = ' + str(exit_flag)
|
||||
send_command('AT+CGATT=1','OK', 300)
|
||||
|
||||
#Now we do search and replace on wvdial config file
|
||||
cmd="sed -i \"s%Modem = .*%Modem = " + self.port + "%g\" " + bandrich_ppd_config
|
||||
os.system(cmd)
|
||||
os.system('wvdial -C ' + bandrich_ppd_config + '' )
|
||||
if exit_flag == 1:
|
||||
print "Exit flag set to true. Exiting pppThread now"
|
||||
@@ -146,6 +152,7 @@ def send_command (cmd, response, timeout):
|
||||
|
||||
def start_ue () :
|
||||
#print 'Enter your commands below.\r\nInsert "exit" to leave the application.'
|
||||
global serial_port
|
||||
timeout=60 #timeout in seconds
|
||||
send_command('AT', 'OK' , timeout)
|
||||
send_command('AT+CFUN=1' , 'OK' , timeout)
|
||||
@@ -153,23 +160,33 @@ def start_ue () :
|
||||
send_command('AT+CGATT=1','OK', 300)
|
||||
#os.system('wvdial -C ' + bandrich_ppd_config + ' &' )
|
||||
|
||||
thread_ppp = pppThread(1, "ppp_thread", 1)
|
||||
thread_ppp = pppThread(1, "ppp_thread", 1,port=serial_port)
|
||||
thread_ppp.start()
|
||||
|
||||
iface='ppp0'
|
||||
#iface='ppp0'
|
||||
|
||||
while 1:
|
||||
time.sleep ( 2)
|
||||
iface=''
|
||||
#Now we check if ppp0 interface is up and running
|
||||
try:
|
||||
if exit_flag == 1:
|
||||
break
|
||||
cmd="ifconfig -a | sed 's/[ \t].*//;/^$/d' | grep ppp"
|
||||
status, out = commands.getstatusoutput(cmd)
|
||||
iface=out
|
||||
ip = IPRoute()
|
||||
idx = ip.link_lookup(ifname=iface)[0]
|
||||
os.system ('route add ' + gw + ' ppp0')
|
||||
print "iface = " + iface
|
||||
print " Setting route now..."
|
||||
#os.system("status=1; while [ \"$status\" -ne \"0\" ]; do route add -host " + gw + ' ' + iface + " ; status=$? ;sleep 1; echo \"status = $status\" ; sleep 2; done ")
|
||||
os.system ('route add -host ' + gw + ' ' + iface + ' 2> /dev/null')
|
||||
#ip.route('add', dst=gw, oif=iface)
|
||||
|
||||
os.system('sleep 5')
|
||||
os.system ('ping ' + gw)
|
||||
break
|
||||
#print "Starting ping now..."
|
||||
os.system ('ping -c 1 ' + gw)
|
||||
#break
|
||||
except Exception, e:
|
||||
error = ' Interface ' + iface + 'does not exist...'
|
||||
error = error + ' In function: ' + sys._getframe().f_code.co_name + ': *** Caught exception: ' + str(e.__class__) + " : " + str( e)
|
||||
@@ -206,6 +223,7 @@ def reset_ue():
|
||||
os.system(cmd + " ; sleep 15" )
|
||||
cmd = "sudo sh -c \"echo 1 > " + usb_dir + "/authorized\""
|
||||
os.system(cmd + " ; sleep 30" )
|
||||
find_open_port()
|
||||
stop_ue()
|
||||
|
||||
i=1
|
||||
@@ -213,14 +231,17 @@ gw='192.172.0.1'
|
||||
while i < len(sys.argv):
|
||||
arg=sys.argv[i]
|
||||
if arg == '--start-ue' :
|
||||
print "Turning on UE..."
|
||||
find_open_port()
|
||||
print 'Using Serial port : ' + serial_port
|
||||
start_ue()
|
||||
elif arg == '--stop-ue' :
|
||||
print "Turning off UE..."
|
||||
find_open_port()
|
||||
print 'Using Serial port : ' + serial_port
|
||||
stop_ue()
|
||||
elif arg == '--reset-ue' :
|
||||
print "Resetting UE..."
|
||||
find_open_port()
|
||||
reset_ue()
|
||||
elif arg == '-gw' :
|
||||
|
||||
+108
@@ -0,0 +1,108 @@
|
||||
#!/usr/bin/python
|
||||
#******************************************************************************
|
||||
|
||||
# OpenAirInterface
|
||||
# Copyright(c) 1999 - 2014 Eurecom
|
||||
|
||||
# OpenAirInterface 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 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
|
||||
# OpenAirInterface 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 OpenAirInterface.The full GNU General Public License is
|
||||
# included in this distribution in the file called "COPYING". If not,
|
||||
# see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# Contact Information
|
||||
# OpenAirInterface Admin: openair_admin@eurecom.fr
|
||||
# OpenAirInterface Tech : openair_tech@eurecom.fr
|
||||
# OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr
|
||||
|
||||
# Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
|
||||
|
||||
# *******************************************************************************/
|
||||
# \author Navid Nikaein, Rohit Gupta
|
||||
|
||||
import time
|
||||
import serial
|
||||
import os
|
||||
from pyroute2 import IPRoute
|
||||
import sys
|
||||
import re
|
||||
import threading
|
||||
import signal
|
||||
import traceback
|
||||
import os
|
||||
import commands
|
||||
|
||||
# configure the serial connections (the parameters differs on the device you are connecting to)
|
||||
#First we find an open port to work with
|
||||
serial_port=''
|
||||
openair_dir = os.environ.get('OPENAIR_DIR')
|
||||
if openair_dir == None:
|
||||
print "Error getting OPENAIR_DIR environment variable"
|
||||
sys.exit(1)
|
||||
|
||||
sys.path.append(os.path.expandvars('$OPENAIR_DIR/cmake_targets/autotests/tools/'))
|
||||
|
||||
from lib_autotest import *
|
||||
|
||||
#Stop the USB BUS of USRPB210
|
||||
def stop_usrpb210():
|
||||
stringIdBandrich='National Instruments Corp.'
|
||||
status, out = commands.getstatusoutput('lsusb | grep -i \'' + stringIdBandrich + '\'')
|
||||
if (out == '') :
|
||||
print "USRP B210 not found. Exiting now..."
|
||||
sys.exit()
|
||||
p=re.compile('Bus\s*(\w+)\s*Device\s*(\w+):\s*ID\s*(\w+):(\w+)')
|
||||
res=p.findall(out)
|
||||
BusId=res[0][0]
|
||||
DeviceId=res[0][1]
|
||||
VendorId=res[0][2]
|
||||
ProductId=res[0][3]
|
||||
usb_dir= find_usb_path(VendorId, ProductId)
|
||||
print "USRP B210 found in..." + usb_dir
|
||||
cmd = "sudo sh -c \"echo 0 > " + usb_dir + "/authorized\""
|
||||
os.system(cmd)
|
||||
|
||||
#Start the USB bus of USRP B210
|
||||
def start_usrpb210():
|
||||
stringIdBandrich='National Instruments Corp.'
|
||||
status, out = commands.getstatusoutput('lsusb | grep -i \'' + stringIdBandrich + '\'')
|
||||
if (out == '') :
|
||||
print "USRP B210 not found. Exiting now..."
|
||||
sys.exit()
|
||||
p=re.compile('Bus\s*(\w+)\s*Device\s*(\w+):\s*ID\s*(\w+):(\w+)')
|
||||
res=p.findall(out)
|
||||
BusId=res[0][0]
|
||||
DeviceId=res[0][1]
|
||||
VendorId=res[0][2]
|
||||
ProductId=res[0][3]
|
||||
usb_dir= find_usb_path(VendorId, ProductId)
|
||||
print "USRP B210 found in..." + usb_dir
|
||||
cmd = "sudo sh -c \"echo 1 > " + usb_dir + "/authorized\""
|
||||
os.system(cmd)
|
||||
|
||||
i=1
|
||||
while i < len(sys.argv):
|
||||
arg=sys.argv[i]
|
||||
if arg == '--start-usrpb210' :
|
||||
start_usrpb210()
|
||||
elif arg == '--stop-usrpb210' :
|
||||
stop_usrpb210()
|
||||
elif arg == '-h' :
|
||||
print "--stop-usrpb210: Stop the USRP B210. It cannot be found in uhd_find_devices"
|
||||
print "--start-usrpb210: Start the USRP B210. It can now be found in uhd_find_devices"
|
||||
else :
|
||||
print " Script called with wrong arguments, arg = " + arg
|
||||
sys.exit()
|
||||
i = i +1
|
||||
|
||||
|
||||
@@ -58,6 +58,7 @@ CFLAGS_PROCESSOR_USER=""
|
||||
RUN_GROUP=0
|
||||
TEST_CASE_GROUP=""
|
||||
BUILD_DOXYGEN=0
|
||||
T_TRACER="False"
|
||||
trap handle_ctrl_c INT
|
||||
|
||||
function print_help() {
|
||||
@@ -128,6 +129,8 @@ Options
|
||||
Enable deadline scheduler of Linux kernel (>=3.14.x).
|
||||
--disable-cpu-affinity
|
||||
Disables CPU Affinity between UHD/TX/RX Threads (Valid only when deadline scheduler is disabled). By defaulT, CPU Affinity is enabled when not using deadline scheduler. It is enabled only with >2 CPUs. For eNB, CPU_0-> Device library (UHD), CPU_1->TX Threads, CPU_2...CPU_MAX->Rx Threads. For UE, CPU_0->Device Library(UHD), CPU_1..CPU_MAX -> All the UE threads
|
||||
--T-tracer
|
||||
Enables the T tracer.
|
||||
Usage (first build):
|
||||
oaisim (eNB + UE): ./build_oai -I -g --oaisim -x --install-system-files
|
||||
Eurecom EXMIMO + COTS UE : ./build_oai -I -g --eNB -x --install-system-files
|
||||
@@ -270,6 +273,10 @@ function main() {
|
||||
CPU_AFFINITY_FLAG_USER="False"
|
||||
echo_info "Disabling CPU Affinity (only valid when not using deadline scheduler)"
|
||||
shift 1;;
|
||||
--T-tracer)
|
||||
T_TRACER="True"
|
||||
echo_info "Enabling the T tracer"
|
||||
shift 1;;
|
||||
-h | --help)
|
||||
print_help
|
||||
exit 1;;
|
||||
@@ -434,6 +441,7 @@ function main() {
|
||||
echo "set(PACKAGE_NAME \"${lte_exec}\")" >> $cmake_file
|
||||
echo "set (DEADLINE_SCHEDULER \"${DEADLINE_SCHEDULER_FLAG_USER}\" )" >>$cmake_file
|
||||
echo "set (CPU_AFFINITY \"${CPU_AFFINITY_FLAG_USER}\" )" >>$cmake_file
|
||||
echo "set ( T_TRACER $T_TRACER )" >> $cmake_file
|
||||
echo 'include(${CMAKE_CURRENT_SOURCE_DIR}/../CMakeLists.txt)' >> $cmake_file
|
||||
cd $DIR/$lte_build_dir/build
|
||||
cmake ..
|
||||
@@ -567,6 +575,7 @@ function main() {
|
||||
echo "set ( PRINT_STATS $PRINT_STATS )" >> $cmake_file
|
||||
echo "set ( RRC_ASN1_VERSION \"${REL}\")" >> $cmake_file
|
||||
echo "set ( ENABLE_VCD_FIFO $VCD_TIMING )" >> $cmake_file
|
||||
echo "set ( T_TRACER $T_TRACER )" >> $cmake_file
|
||||
echo 'include(${CMAKE_CURRENT_SOURCE_DIR}/../CMakeLists.txt)' >> $cmake_file
|
||||
[ "$CLEAN" = "1" ] && rm -rf $DIR/$oaisim_build_dir/build
|
||||
mkdir -p $DIR/$oaisim_build_dir/build
|
||||
@@ -632,6 +641,7 @@ function main() {
|
||||
echo "set(XFORMS $XFORMS )" >> $cmake_file
|
||||
echo "set(RRC_ASN1_VERSION \"${REL}\")" >> $cmake_file
|
||||
echo "set(ENABLE_VCD_FIFO $VCD_TIMING )" >> $cmake_file
|
||||
echo "set ( T_TRACER $T_TRACER )" >> $cmake_file
|
||||
echo 'include(${CMAKE_CURRENT_SOURCE_DIR}/../CMakeLists.txt)' >> $cmake_file
|
||||
#[ "$CLEAN" = "1" ] && rm -rf $DIR/oaisim_mme_build_oai/build
|
||||
#mkdir -p $DIR/oaisim_mme_build_oai/build
|
||||
@@ -662,6 +672,7 @@ function main() {
|
||||
echo 'set(PACKAGE_NAME "\"rrh_gw\"")' >> $cmake_file
|
||||
echo "set (DEADLINE_SCHEDULER \"${DEADLINE_SCHEDULER_FLAG_USER}\" )" >>$cmake_file
|
||||
echo "set (CPU_AFFINITY \"${CPU_AFFINITY_FLAG_USER}\" )" >>$cmake_file
|
||||
echo "set ( T_TRACER $T_TRACER )" >> $cmake_file
|
||||
echo 'include(${CMAKE_CURRENT_SOURCE_DIR}/../CMakeLists.txt)' >> $cmake_file
|
||||
cd $DIR/$rrh_build_dir/build
|
||||
cmake ..
|
||||
|
||||
@@ -226,7 +226,25 @@ check_install_additional_tools (){
|
||||
valgrind \
|
||||
vlan \
|
||||
ctags \
|
||||
ntpdate
|
||||
ntpdate \
|
||||
iperf3 \
|
||||
android-tools-adb
|
||||
|
||||
$SUDO pip install paramiko
|
||||
$SUDO pip install pyroute2
|
||||
$SUDO rm -fr /opt/ssh
|
||||
$SUDO git clone https://gist.github.com/2190472.git /opt/ssh
|
||||
|
||||
log_netiface=$OPENAIR_DIR/cmake_targets/log/netiface_install_log.txt
|
||||
echo_info "Installing Netinterfaces package. The logfile for installation is in $log_netiface"
|
||||
(
|
||||
$SUDO rm -fr /tmp/netifaces-0.10.4.tar.gz /tmp/netifaces
|
||||
wget -P /tmp https://pypi.python.org/packages/18/fa/dd13d4910aea339c0bb87d2b3838d8fd923c11869b1f6e741dbd0ff3bc00/netifaces-0.10.4.tar.gz
|
||||
tar -xzvf /tmp/netifaces-0.10.4.tar.gz -C /tmp
|
||||
cd /tmp/netifaces-0.10.4
|
||||
$SUDO python setup.py install
|
||||
cd -
|
||||
) >& $log_netiface
|
||||
}
|
||||
|
||||
check_install_oai_software() {
|
||||
@@ -293,8 +311,7 @@ check_install_oai_software() {
|
||||
python-numpy \
|
||||
sshpass \
|
||||
libxslt1-dev \
|
||||
android-tools-adb \
|
||||
iperf3
|
||||
android-tools-adb
|
||||
|
||||
$SUDO update-alternatives --set liblapack.so /usr/lib/atlas-base/atlas/liblapack.so
|
||||
|
||||
@@ -303,11 +320,7 @@ check_install_oai_software() {
|
||||
install_nettle_from_source
|
||||
install_gnutls_from_source
|
||||
|
||||
$SUDO pip install paramiko
|
||||
$SUDO pip install pyroute2
|
||||
install_asn1c_from_source
|
||||
$SUDO rm -fr /opt/ssh
|
||||
$SUDO git clone https://gist.github.com/2190472.git /opt/ssh
|
||||
}
|
||||
|
||||
install_asn1c_from_source(){
|
||||
@@ -315,14 +328,12 @@ install_asn1c_from_source(){
|
||||
echo_info "\nInstalling ASN1. The log file for ASN1 installation is here: $asn1_install_log "
|
||||
(
|
||||
$SUDO rm -rf /tmp/asn1c-r1516
|
||||
mkdir -p /tmp/asn1c-r1516
|
||||
cd /tmp/asn1c-r1516
|
||||
rm -rf /tmp/asn1c-r1516/*
|
||||
svn co https://github.com/vlm/asn1c/trunk /tmp/asn1c-r1516 -r 1516 > /tmp/log_compile_asn1c
|
||||
patch -p0 < $OPENAIR_DIR/openair3/S1AP/MESSAGES/ASN1/asn1cpatch.p0 >> /tmp/log_compile_asn1c
|
||||
patch -p0 < $OPENAIR_DIR/openair3/S1AP/MESSAGES/ASN1/asn1cpatch_2.p0 >> /tmp/log_compile_asn1c
|
||||
patch -p0 < $OPENAIR_DIR/openair2/RRC/LITE/MESSAGES/asn1c/asn1cpatch.p0 >> /tmp/log_compile_asn1c
|
||||
patch -p0 < $OPENAIR_DIR/openair3/S1AP/MESSAGES/ASN1/asn1cpatch_3.p0 >> /tmp/log_compile_asn1c
|
||||
svn co https://github.com/vlm/asn1c/trunk /tmp/asn1c-r1516 -r 1516
|
||||
cd /tmp/asn1c-r1516
|
||||
patch -p0 < $OPENAIR_DIR/openair3/S1AP/MESSAGES/ASN1/asn1cpatch.p0
|
||||
patch -p0 < $OPENAIR_DIR/openair3/S1AP/MESSAGES/ASN1/asn1cpatch_2.p0
|
||||
patch -p0 < $OPENAIR_DIR/openair2/RRC/LITE/MESSAGES/asn1c/asn1cpatch.p0
|
||||
patch -p0 < $OPENAIR_DIR/openair3/S1AP/MESSAGES/ASN1/asn1cpatch_3.p0
|
||||
./configure
|
||||
make -j`nproc`
|
||||
$SUDO make install
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
CC=gcc
|
||||
CFLAGS=-Wall -g
|
||||
|
||||
GENIDS=genids
|
||||
GENIDS_OBJS=genids.o
|
||||
|
||||
all : $(GENIDS) T_messages.txt.h T_IDs.h
|
||||
|
||||
$(GENIDS): $(GENIDS_OBJS)
|
||||
$(CC) $(CFLAGS) -o $(GENIDS) $(GENIDS_OBJS)
|
||||
|
||||
%.o: %.c
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
T_messages.txt.h: T_messages.txt
|
||||
xxd -i T_messages.txt > T_messages.txt.h
|
||||
|
||||
T_IDs.h: $(GENIDS) T_messages.txt
|
||||
./$(GENIDS) T_messages.txt T_IDs.h
|
||||
|
||||
clean:
|
||||
rm -f *.o $(GENIDS) core T_IDs.h T_messages.txt.h
|
||||
cd tracer && make clean
|
||||
@@ -0,0 +1,181 @@
|
||||
#include "T.h"
|
||||
#include "T_messages.txt.h"
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#define QUIT(x) do { \
|
||||
printf("T tracer: QUIT: %s\n", x); \
|
||||
exit(1); \
|
||||
} while (0)
|
||||
|
||||
/* array used to activate/disactivate a log */
|
||||
static int T_IDs[T_NUMBER_OF_IDS];
|
||||
int *T_active = T_IDs;
|
||||
|
||||
static int T_socket;
|
||||
|
||||
/* T_cache
|
||||
* - the T macro picks up the head of freelist and marks it busy
|
||||
* - the T sender thread periodically wakes up and sends what's to be sent
|
||||
*/
|
||||
volatile int _T_freelist_head;
|
||||
volatile int *T_freelist_head = &_T_freelist_head;
|
||||
T_cache_t *T_cache;
|
||||
|
||||
static void get_message(int s)
|
||||
{
|
||||
char t;
|
||||
int l;
|
||||
int id;
|
||||
int is_on;
|
||||
|
||||
if (read(s, &t, 1) != 1) QUIT("get_message fails");
|
||||
printf("got mess %d\n", t);
|
||||
switch (t) {
|
||||
case 0:
|
||||
/* toggle all those IDs */
|
||||
/* optimze? (too much syscalls) */
|
||||
if (read(s, &l, sizeof(int)) != sizeof(int)) QUIT("get_message fails");
|
||||
while (l) {
|
||||
if (read(s, &id, sizeof(int)) != sizeof(int)) QUIT("get_message fails");
|
||||
T_IDs[id] = 1 - T_IDs[id];
|
||||
l--;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
/* set IDs as given */
|
||||
/* optimize? */
|
||||
if (read(s, &l, sizeof(int)) != sizeof(int)) QUIT("get_message fails");
|
||||
id = 0;
|
||||
while (l) {
|
||||
if (read(s, &is_on, sizeof(int)) != sizeof(int))
|
||||
QUIT("get_message fails");
|
||||
T_IDs[id] = is_on;
|
||||
id++;
|
||||
l--;
|
||||
}
|
||||
break;
|
||||
case 2: break; /* do nothing, this message is to wait for local tracer */
|
||||
}
|
||||
}
|
||||
|
||||
static void *T_receive_thread(void *_)
|
||||
{
|
||||
while (1) get_message(T_socket);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void new_thread(void *(*f)(void *), void *data)
|
||||
{
|
||||
pthread_t t;
|
||||
pthread_attr_t att;
|
||||
|
||||
if (pthread_attr_init(&att))
|
||||
{ fprintf(stderr, "pthread_attr_init err\n"); exit(1); }
|
||||
if (pthread_attr_setdetachstate(&att, PTHREAD_CREATE_DETACHED))
|
||||
{ fprintf(stderr, "pthread_attr_setdetachstate err\n"); exit(1); }
|
||||
if (pthread_create(&t, &att, f, data))
|
||||
{ fprintf(stderr, "pthread_create err\n"); exit(1); }
|
||||
if (pthread_attr_destroy(&att))
|
||||
{ fprintf(stderr, "pthread_attr_destroy err\n"); exit(1); }
|
||||
}
|
||||
|
||||
/* defined in local_tracer.c */
|
||||
void T_local_tracer_main(int remote_port, int wait_for_tracer,
|
||||
int local_socket);
|
||||
|
||||
/* We monitor the tracee and the local tracer processes.
|
||||
* When one dies we forcefully kill the other.
|
||||
*/
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
static void monitor_and_kill(int child1, int child2)
|
||||
{
|
||||
int child;
|
||||
int status;
|
||||
|
||||
child = wait(&status);
|
||||
if (child == -1) perror("wait");
|
||||
kill(child1, SIGKILL);
|
||||
kill(child2, SIGKILL);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void T_init(int remote_port, int wait_for_tracer)
|
||||
{
|
||||
int socket_pair[2];
|
||||
int s;
|
||||
int T_shm_fd;
|
||||
unsigned char *buf;
|
||||
int len;
|
||||
int child1, child2;
|
||||
|
||||
if (socketpair(AF_UNIX, SOCK_STREAM, 0, socket_pair))
|
||||
{ perror("socketpair"); abort(); }
|
||||
|
||||
/* child1 runs the local tracer and child2 runs the tracee */
|
||||
|
||||
child1 = fork(); if (child1 == -1) abort();
|
||||
if (child1 == 0) {
|
||||
close(socket_pair[1]);
|
||||
T_local_tracer_main(remote_port, wait_for_tracer, socket_pair[0]);
|
||||
exit(0);
|
||||
}
|
||||
close(socket_pair[0]);
|
||||
|
||||
child2 = fork(); if (child2 == -1) abort();
|
||||
if (child2 != 0) {
|
||||
close(socket_pair[1]);
|
||||
monitor_and_kill(child1, child2);
|
||||
}
|
||||
|
||||
s = socket_pair[1];
|
||||
/* wait for first message - initial list of active T events */
|
||||
get_message(s);
|
||||
|
||||
T_socket = s;
|
||||
|
||||
/* setup shared memory */
|
||||
T_shm_fd = shm_open(T_SHM_FILENAME, O_RDWR /*| O_SYNC*/, 0666);
|
||||
shm_unlink(T_SHM_FILENAME);
|
||||
if (T_shm_fd == -1) { perror(T_SHM_FILENAME); abort(); }
|
||||
T_cache = mmap(NULL, T_CACHE_SIZE * sizeof(T_cache_t),
|
||||
PROT_READ | PROT_WRITE, MAP_SHARED, T_shm_fd, 0);
|
||||
if (T_cache == NULL)
|
||||
{ perror(T_SHM_FILENAME); abort(); }
|
||||
close(T_shm_fd);
|
||||
|
||||
new_thread(T_receive_thread, NULL);
|
||||
|
||||
/* trace T_message.txt
|
||||
* Send several messages -1 with content followed by message -2.
|
||||
* We can't use the T macro directly, events -1 and -2 are special.
|
||||
*/
|
||||
buf = T_messages_txt;
|
||||
len = T_messages_txt_len;
|
||||
while (len) {
|
||||
int send_size = len;
|
||||
if (send_size > T_PAYLOAD_MAXSIZE - sizeof(int))
|
||||
send_size = T_PAYLOAD_MAXSIZE - sizeof(int);
|
||||
do {
|
||||
T_LOCAL_DATA
|
||||
T_HEADER(T_ID(-1));
|
||||
T_PUT_buffer(1, ((T_buffer){addr:(buf), length:(len)}));
|
||||
T_COMMIT();
|
||||
} while (0);
|
||||
buf += send_size;
|
||||
len -= send_size;
|
||||
}
|
||||
do {
|
||||
T_LOCAL_DATA
|
||||
T_HEADER(T_ID(-2));
|
||||
T_COMMIT();
|
||||
} while (0);
|
||||
}
|
||||
@@ -0,0 +1,574 @@
|
||||
#ifndef _T_T_T_
|
||||
#define _T_T_T_
|
||||
|
||||
#if T_TRACER
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "T_defs.h"
|
||||
|
||||
#ifdef T_SEND_TIME
|
||||
#include <time.h>
|
||||
#endif
|
||||
|
||||
/* T message IDs */
|
||||
#include "T_IDs.h"
|
||||
|
||||
/* known type - this is where you add new types */
|
||||
|
||||
#define T_INT(x) int, (x)
|
||||
#define T_FLOAT(x) float, (x)
|
||||
#define T_BUFFER(x, len) buffer, ((T_buffer){addr:(x), length:(len)})
|
||||
#define T_STRING(x) string, (x)
|
||||
#define T_PRINTF(...) printf, (__VA_ARGS__)
|
||||
|
||||
/* for each known type a T_PUT_XX macro is defined */
|
||||
|
||||
#define T_PUT_int(argnum, val) \
|
||||
do { \
|
||||
int T_PUT_var = (val); \
|
||||
T_CHECK_SIZE(sizeof(int), argnum); \
|
||||
memcpy(T_LOCAL_buf + T_LOCAL_size, &T_PUT_var, sizeof(int)); \
|
||||
T_LOCAL_size += sizeof(int); \
|
||||
} while (0)
|
||||
|
||||
#define T_PUT_ulong(argnum, val) \
|
||||
do { \
|
||||
unsigned long T_PUT_var = (val); \
|
||||
T_CHECK_SIZE(sizeof(unsigned long), argnum); \
|
||||
memcpy(T_LOCAL_buf + T_LOCAL_size, &T_PUT_var, sizeof(unsigned long)); \
|
||||
T_LOCAL_size += sizeof(unsigned long); \
|
||||
} while (0)
|
||||
|
||||
#define T_PUT_float(argnum, val) \
|
||||
do { \
|
||||
float T_PUT_var = (val); \
|
||||
T_CHECK_SIZE(sizeof(float), argnum); \
|
||||
memcpy(T_LOCAL_buf + T_LOCAL_size, &T_PUT_var, sizeof(float)); \
|
||||
T_LOCAL_size += sizeof(float); \
|
||||
} while (0)
|
||||
|
||||
#define T_PUT_buffer(argnum, val) \
|
||||
do { \
|
||||
T_buffer T_PUT_buffer_var = (val); \
|
||||
T_PUT_int(argnum, T_PUT_buffer_var.length); \
|
||||
T_CHECK_SIZE(T_PUT_buffer_var.length, argnum); \
|
||||
memcpy(T_LOCAL_buf + T_LOCAL_size, T_PUT_buffer_var.addr, \
|
||||
T_PUT_buffer_var.length); \
|
||||
T_LOCAL_size += T_PUT_buffer_var.length; \
|
||||
} while (0)
|
||||
|
||||
#define T_PUT_string(argnum, val) \
|
||||
do { \
|
||||
char *T_PUT_var = (val); \
|
||||
int T_PUT_len = strlen(T_PUT_var) + 1; \
|
||||
T_CHECK_SIZE(T_PUT_len, argnum); \
|
||||
memcpy(T_LOCAL_buf + T_LOCAL_size, T_PUT_var, T_PUT_len); \
|
||||
T_LOCAL_size += T_PUT_len; \
|
||||
} while (0)
|
||||
|
||||
#define T_PUT_printf_deref(...) __VA_ARGS__
|
||||
|
||||
#define T_PUT_printf(argnum, x) \
|
||||
do { \
|
||||
int T_PUT_len = snprintf(T_LOCAL_buf + T_LOCAL_size, \
|
||||
T_BUFFER_MAX - T_LOCAL_size, T_PUT_printf_deref x); \
|
||||
if (T_PUT_len < 0) { \
|
||||
printf("%s:%d:%s: you can't read this, or can you?", \
|
||||
__FILE__, __LINE__, __FUNCTION__); \
|
||||
abort(); \
|
||||
} \
|
||||
if (T_PUT_len >= T_BUFFER_MAX - T_LOCAL_size) { \
|
||||
printf("%s:%d:%s: cannot put argument %d in T macro, not enough space" \
|
||||
", consider increasing T_BUFFER_MAX (%d)\n", \
|
||||
__FILE__, __LINE__, __FUNCTION__, argnum, T_BUFFER_MAX); \
|
||||
abort(); \
|
||||
} \
|
||||
T_LOCAL_size += T_PUT_len + 1; \
|
||||
} while (0)
|
||||
|
||||
/* structure type to detect that you pass a known type as first arg of T */
|
||||
struct T_header;
|
||||
|
||||
/* to define message ID */
|
||||
#define T_ID(x) ((struct T_header *)(uintptr_t)(x))
|
||||
|
||||
/* T macro tricks */
|
||||
|
||||
#define TN(...) TN_N(__VA_ARGS__,33,32,31,30,29,28,27,26,25,24,23,22,21,\
|
||||
20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0)(__VA_ARGS__)
|
||||
#define TN_N(n0,n1,n2,n3,n4,n5,n6,n7,n8,n9,n10,n11,n12,n13,n14,n15,n16,n17,\
|
||||
n18,n19,n20,n21,n22,n23,n24,n25,n26,n27,n28,n29,n30,n31,n32,n,...) T##n
|
||||
#define T(...) TN(__VA_ARGS__)
|
||||
|
||||
/* type used to send arbitrary buffer data */
|
||||
typedef struct {
|
||||
void *addr;
|
||||
int length;
|
||||
} T_buffer;
|
||||
|
||||
extern volatile int *T_freelist_head;
|
||||
extern T_cache_t *T_cache;
|
||||
|
||||
/* used at header of Tn, allocates buffer */
|
||||
#define T_LOCAL_DATA \
|
||||
char *T_LOCAL_buf; \
|
||||
int T_LOCAL_size = 0; \
|
||||
int T_LOCAL_slot; \
|
||||
T_LOCAL_slot = __sync_fetch_and_add(T_freelist_head, 1) \
|
||||
& (T_CACHE_SIZE - 1); \
|
||||
(void)__sync_fetch_and_and(T_freelist_head, T_CACHE_SIZE - 1); \
|
||||
if (T_cache[T_LOCAL_slot].busy) { \
|
||||
printf("%s:%d:%s: T cache is full - consider increasing its size\n", \
|
||||
__FILE__, __LINE__, __FUNCTION__); \
|
||||
abort(); \
|
||||
} \
|
||||
T_LOCAL_buf = T_cache[T_LOCAL_slot].buffer;
|
||||
|
||||
#define T_ACTIVE(x) T_active[(intptr_t)x]
|
||||
|
||||
#define T_COMMIT() \
|
||||
T_cache[T_LOCAL_slot].length = T_LOCAL_size; \
|
||||
__sync_synchronize(); \
|
||||
T_cache[T_LOCAL_slot].busy = 1; \
|
||||
|
||||
#define T_CHECK_SIZE(len, argnum) \
|
||||
if (T_LOCAL_size + (len) > T_BUFFER_MAX) { \
|
||||
printf("%s:%d:%s: cannot put argument %d in T macro, not enough space" \
|
||||
", consider increasing T_BUFFER_MAX (%d)\n", \
|
||||
__FILE__, __LINE__, __FUNCTION__, argnum, T_BUFFER_MAX); \
|
||||
abort(); \
|
||||
}
|
||||
|
||||
#if 0
|
||||
#define T_PUT(type, var, argnum) \
|
||||
do { \
|
||||
if (T_LOCAL_size + sizeof(var) > T_BUFFER_MAX) { \
|
||||
printf("%s:%d:%s: cannot put argument %d in T macro, not enough space" \
|
||||
", consider increasing T_BUFFER_MAX (%d)\n", \
|
||||
__FILE__, __LINE__, __FUNCTION__, argnum, T_BUFFER_MAX); \
|
||||
abort(); \
|
||||
} \
|
||||
memcpy(T_LOCAL_buf + T_LOCAL_size, &var, sizeof(var)); \
|
||||
T_LOCAL_size += sizeof(var); \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
#define T_PROCESS(x, argnum) \
|
||||
do { \
|
||||
T_PUT(typeof(x), x, argnum); \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
#define T_PROCESS(x, argnum) \
|
||||
do { \
|
||||
if (__builtin_types_compatible_p(typeof(x), int)) \
|
||||
{ T_PUT(int, (intptr_t)(x), argnum); printf("int\n"); } \
|
||||
else if (__builtin_types_compatible_p(typeof(x), short)) \
|
||||
{ T_PUT(short, (intptr_t)(x), argnum); printf("short\n"); } \
|
||||
else if (__builtin_types_compatible_p(typeof(x), float)) \
|
||||
{ T_PUT(float, (x), argnum); printf("float\n"); } \
|
||||
else if (__builtin_types_compatible_p(typeof(x), char *)) \
|
||||
{ T_PUT(char *, (char *)(intptr_t)(x), argnum); printf("char *\n"); } \
|
||||
else if (__builtin_types_compatible_p(typeof(x), float *)) \
|
||||
{ T_PUT(float *, (float *)(intptr_t)(x), argnum); printf("float *\n"); } \
|
||||
else if (__builtin_types_compatible_p(typeof(x), void *)) \
|
||||
{ T_PUT(void *, (void *)(intptr_t)(x), argnum); printf("void *\n"); } \
|
||||
else { \
|
||||
printf("%s:%d:%s: unsupported type for argument %d in T macro\n", \
|
||||
__FILE__, __LINE__, __FUNCTION__, argnum); \
|
||||
abort(); \
|
||||
} \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#ifdef T_SEND_TIME
|
||||
|
||||
#define T_HEADER(x) \
|
||||
do { \
|
||||
if (!__builtin_types_compatible_p(typeof(x), struct T_header *)) { \
|
||||
printf("%s:%d:%s: " \
|
||||
"bad use of T, pass a message ID as first parameter\n", \
|
||||
__FILE__, __LINE__, __FUNCTION__); \
|
||||
abort(); \
|
||||
} \
|
||||
struct timespec T_HEADER_time; \
|
||||
if (clock_gettime(CLOCK_REALTIME, &T_HEADER_time)) abort(); \
|
||||
memcpy(T_LOCAL_buf, &T_HEADER_time, sizeof(struct timespec)); \
|
||||
T_LOCAL_size += sizeof(struct timespec); \
|
||||
T_PUT_int(1, (int)(uintptr_t)(x)); \
|
||||
} while (0)
|
||||
|
||||
#else /* #ifdef T_SEND_TIME */
|
||||
|
||||
#define T_HEADER(x) \
|
||||
do { \
|
||||
if (!__builtin_types_compatible_p(typeof(x), struct T_header *)) { \
|
||||
printf("%s:%d:%s: " \
|
||||
"bad use of T, pass a message ID as first parameter\n", \
|
||||
__FILE__, __LINE__, __FUNCTION__); \
|
||||
abort(); \
|
||||
} \
|
||||
T_PUT_int(1, (int)(uintptr_t)(x)); \
|
||||
} while (0)
|
||||
|
||||
#endif /* #ifdef T_SEND_TIME */
|
||||
|
||||
#define T1(t) \
|
||||
do { \
|
||||
if (T_ACTIVE(t)) { \
|
||||
T_LOCAL_DATA \
|
||||
T_HEADER(t); \
|
||||
T_COMMIT(); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define T3(t,t0,x0) \
|
||||
do { \
|
||||
if (T_ACTIVE(t)) { \
|
||||
T_LOCAL_DATA \
|
||||
T_HEADER(t); \
|
||||
T_PUT_##t0(2, x0); \
|
||||
T_COMMIT(); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define T5(t,t0,x0,t1,x1) \
|
||||
do { \
|
||||
if (T_ACTIVE(t)) { \
|
||||
T_LOCAL_DATA \
|
||||
T_HEADER(t); \
|
||||
T_PUT_##t0(2, x0); \
|
||||
T_PUT_##t1(3, x1); \
|
||||
T_COMMIT(); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define T7(t,t0,x0,t1,x1,t2,x2) \
|
||||
do { \
|
||||
if (T_ACTIVE(t)) { \
|
||||
T_LOCAL_DATA \
|
||||
T_HEADER(t); \
|
||||
T_PUT_##t0(2, x0); \
|
||||
T_PUT_##t1(3, x1); \
|
||||
T_PUT_##t2(4, x2); \
|
||||
T_COMMIT(); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define T9(t,t0,x0,t1,x1,t2,x2,t3,x3) \
|
||||
do { \
|
||||
if (T_ACTIVE(t)) { \
|
||||
T_LOCAL_DATA \
|
||||
T_HEADER(t); \
|
||||
T_PUT_##t0(2, x0); \
|
||||
T_PUT_##t1(3, x1); \
|
||||
T_PUT_##t2(4, x2); \
|
||||
T_PUT_##t3(5, x3); \
|
||||
T_COMMIT(); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define T11(t,t0,x0,t1,x1,t2,x2,t3,x3,t4,x4) \
|
||||
do { \
|
||||
if (T_ACTIVE(t)) { \
|
||||
T_LOCAL_DATA \
|
||||
T_HEADER(t); \
|
||||
T_PUT_##t0(2, x0); \
|
||||
T_PUT_##t1(3, x1); \
|
||||
T_PUT_##t2(4, x2); \
|
||||
T_PUT_##t3(5, x3); \
|
||||
T_PUT_##t4(6, x4); \
|
||||
T_COMMIT(); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define T13(t,t0,x0,t1,x1,t2,x2,t3,x3,t4,x4,t5,x5) \
|
||||
do { \
|
||||
if (T_ACTIVE(t)) { \
|
||||
T_LOCAL_DATA \
|
||||
T_HEADER(t); \
|
||||
T_PUT_##t0(2, x0); \
|
||||
T_PUT_##t1(3, x1); \
|
||||
T_PUT_##t2(4, x2); \
|
||||
T_PUT_##t3(5, x3); \
|
||||
T_PUT_##t4(6, x4); \
|
||||
T_PUT_##t5(7, x5); \
|
||||
T_COMMIT(); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define T15(t,t0,x0,t1,x1,t2,x2,t3,x3,t4,x4,t5,x5,t6,x6) \
|
||||
do { \
|
||||
if (T_ACTIVE(t)) { \
|
||||
T_LOCAL_DATA \
|
||||
T_HEADER(t); \
|
||||
T_PUT_##t0(2, x0); \
|
||||
T_PUT_##t1(3, x1); \
|
||||
T_PUT_##t2(4, x2); \
|
||||
T_PUT_##t3(5, x3); \
|
||||
T_PUT_##t4(6, x4); \
|
||||
T_PUT_##t5(7, x5); \
|
||||
T_PUT_##t6(8, x6); \
|
||||
T_COMMIT(); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define T17(t,t0,x0,t1,x1,t2,x2,t3,x3,t4,x4,t5,x5,t6,x6,t7,x7) \
|
||||
do { \
|
||||
if (T_ACTIVE(t)) { \
|
||||
T_LOCAL_DATA \
|
||||
T_HEADER(t); \
|
||||
T_PUT_##t0(2, x0); \
|
||||
T_PUT_##t1(3, x1); \
|
||||
T_PUT_##t2(4, x2); \
|
||||
T_PUT_##t3(5, x3); \
|
||||
T_PUT_##t4(6, x4); \
|
||||
T_PUT_##t5(7, x5); \
|
||||
T_PUT_##t6(8, x6); \
|
||||
T_PUT_##t7(9, x7); \
|
||||
T_COMMIT(); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define T19(t,t0,x0,t1,x1,t2,x2,t3,x3,t4,x4,t5,x5,t6,x6,t7,x7,t8,x8) \
|
||||
do { \
|
||||
if (T_ACTIVE(t)) { \
|
||||
T_LOCAL_DATA \
|
||||
T_HEADER(t); \
|
||||
T_PUT_##t0(2, x0); \
|
||||
T_PUT_##t1(3, x1); \
|
||||
T_PUT_##t2(4, x2); \
|
||||
T_PUT_##t3(5, x3); \
|
||||
T_PUT_##t4(6, x4); \
|
||||
T_PUT_##t5(7, x5); \
|
||||
T_PUT_##t6(8, x6); \
|
||||
T_PUT_##t7(9, x7); \
|
||||
T_PUT_##t8(10, x8); \
|
||||
T_COMMIT(); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define T21(t,t0,x0,t1,x1,t2,x2,t3,x3,t4,x4,t5,x5,t6,x6,t7,x7,t8,x8,t9,x9) \
|
||||
do { \
|
||||
if (T_ACTIVE(t)) { \
|
||||
T_LOCAL_DATA \
|
||||
T_HEADER(t); \
|
||||
T_PUT_##t0(2, x0); \
|
||||
T_PUT_##t1(3, x1); \
|
||||
T_PUT_##t2(4, x2); \
|
||||
T_PUT_##t3(5, x3); \
|
||||
T_PUT_##t4(6, x4); \
|
||||
T_PUT_##t5(7, x5); \
|
||||
T_PUT_##t6(8, x6); \
|
||||
T_PUT_##t7(9, x7); \
|
||||
T_PUT_##t8(10, x8); \
|
||||
T_PUT_##t9(11, x9); \
|
||||
T_COMMIT(); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define T23(t,t0,x0,t1,x1,t2,x2,t3,x3,t4,x4,t5,x5,t6,x6,t7,x7,t8,x8,t9,x9,t10,x10) \
|
||||
do { \
|
||||
if (T_ACTIVE(t)) { \
|
||||
T_LOCAL_DATA \
|
||||
T_HEADER(t); \
|
||||
T_PUT_##t0(2, x0); \
|
||||
T_PUT_##t1(3, x1); \
|
||||
T_PUT_##t2(4, x2); \
|
||||
T_PUT_##t3(5, x3); \
|
||||
T_PUT_##t4(6, x4); \
|
||||
T_PUT_##t5(7, x5); \
|
||||
T_PUT_##t6(8, x6); \
|
||||
T_PUT_##t7(9, x7); \
|
||||
T_PUT_##t8(10, x8); \
|
||||
T_PUT_##t9(11, x9); \
|
||||
T_PUT_##t10(12, x10); \
|
||||
T_COMMIT(); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define T25(t,t0,x0,t1,x1,t2,x2,t3,x3,t4,x4,t5,x5,t6,x6,t7,x7,t8,x8,t9,x9,t10,x10,t11,x11) \
|
||||
do { \
|
||||
if (T_ACTIVE(t)) { \
|
||||
T_LOCAL_DATA \
|
||||
T_HEADER(t); \
|
||||
T_PUT_##t0(2, x0); \
|
||||
T_PUT_##t1(3, x1); \
|
||||
T_PUT_##t2(4, x2); \
|
||||
T_PUT_##t3(5, x3); \
|
||||
T_PUT_##t4(6, x4); \
|
||||
T_PUT_##t5(7, x5); \
|
||||
T_PUT_##t6(8, x6); \
|
||||
T_PUT_##t7(9, x7); \
|
||||
T_PUT_##t8(10, x8); \
|
||||
T_PUT_##t9(11, x9); \
|
||||
T_PUT_##t10(12, x10); \
|
||||
T_PUT_##t11(13, x11); \
|
||||
T_COMMIT(); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define T27(t,t0,x0,t1,x1,t2,x2,t3,x3,t4,x4,t5,x5,t6,x6,t7,x7,t8,x8,t9,x9,t10,x10,t11,x11,t12,x12) \
|
||||
do { \
|
||||
if (T_ACTIVE(t)) { \
|
||||
T_LOCAL_DATA \
|
||||
T_HEADER(t); \
|
||||
T_PUT_##t0(2, x0); \
|
||||
T_PUT_##t1(3, x1); \
|
||||
T_PUT_##t2(4, x2); \
|
||||
T_PUT_##t3(5, x3); \
|
||||
T_PUT_##t4(6, x4); \
|
||||
T_PUT_##t5(7, x5); \
|
||||
T_PUT_##t6(8, x6); \
|
||||
T_PUT_##t7(9, x7); \
|
||||
T_PUT_##t8(10, x8); \
|
||||
T_PUT_##t9(11, x9); \
|
||||
T_PUT_##t10(12, x10); \
|
||||
T_PUT_##t11(13, x11); \
|
||||
T_PUT_##t12(14, x12); \
|
||||
T_COMMIT(); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define T29(t,t0,x0,t1,x1,t2,x2,t3,x3,t4,x4,t5,x5,t6,x6,t7,x7,t8,x8,t9,x9,t10,x10,t11,x11,t12,x12,t13,x13) \
|
||||
do { \
|
||||
if (T_ACTIVE(t)) { \
|
||||
T_LOCAL_DATA \
|
||||
T_HEADER(t); \
|
||||
T_PUT_##t0(2, x0); \
|
||||
T_PUT_##t1(3, x1); \
|
||||
T_PUT_##t2(4, x2); \
|
||||
T_PUT_##t3(5, x3); \
|
||||
T_PUT_##t4(6, x4); \
|
||||
T_PUT_##t5(7, x5); \
|
||||
T_PUT_##t6(8, x6); \
|
||||
T_PUT_##t7(9, x7); \
|
||||
T_PUT_##t8(10, x8); \
|
||||
T_PUT_##t9(11, x9); \
|
||||
T_PUT_##t10(12, x10); \
|
||||
T_PUT_##t11(13, x11); \
|
||||
T_PUT_##t12(14, x12); \
|
||||
T_PUT_##t13(15, x13); \
|
||||
T_COMMIT(); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define T31(t,t0,x0,t1,x1,t2,x2,t3,x3,t4,x4,t5,x5,t6,x6,t7,x7,t8,x8,t9,x9,t10,x10,t11,x11,t12,x12,t13,x13,t14,x14) \
|
||||
do { \
|
||||
if (T_ACTIVE(t)) { \
|
||||
T_LOCAL_DATA \
|
||||
T_HEADER(t); \
|
||||
T_PUT_##t0(2, x0); \
|
||||
T_PUT_##t1(3, x1); \
|
||||
T_PUT_##t2(4, x2); \
|
||||
T_PUT_##t3(5, x3); \
|
||||
T_PUT_##t4(6, x4); \
|
||||
T_PUT_##t5(7, x5); \
|
||||
T_PUT_##t6(8, x6); \
|
||||
T_PUT_##t7(9, x7); \
|
||||
T_PUT_##t8(10, x8); \
|
||||
T_PUT_##t9(11, x9); \
|
||||
T_PUT_##t10(12, x10); \
|
||||
T_PUT_##t11(13, x11); \
|
||||
T_PUT_##t12(14, x12); \
|
||||
T_PUT_##t13(15, x13); \
|
||||
T_PUT_##t14(16, x14); \
|
||||
T_COMMIT(); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define T33(t,t0,x0,t1,x1,t2,x2,t3,x3,t4,x4,t5,x5,t6,x6,t7,x7,t8,x8,t9,x9,t10,x10,t11,x11,t12,x12,t13,x13,t14,x14,t15,x15) \
|
||||
do { \
|
||||
if (T_ACTIVE(t)) { \
|
||||
T_LOCAL_DATA \
|
||||
T_HEADER(t); \
|
||||
T_PUT_##t0(2, x0); \
|
||||
T_PUT_##t1(3, x1); \
|
||||
T_PUT_##t2(4, x2); \
|
||||
T_PUT_##t3(5, x3); \
|
||||
T_PUT_##t4(6, x4); \
|
||||
T_PUT_##t5(7, x5); \
|
||||
T_PUT_##t6(8, x6); \
|
||||
T_PUT_##t7(9, x7); \
|
||||
T_PUT_##t8(10, x8); \
|
||||
T_PUT_##t9(11, x9); \
|
||||
T_PUT_##t10(12, x10); \
|
||||
T_PUT_##t11(13, x11); \
|
||||
T_PUT_##t12(14, x12); \
|
||||
T_PUT_##t13(15, x13); \
|
||||
T_PUT_##t14(16, x14); \
|
||||
T_PUT_##t15(17, x15); \
|
||||
T_COMMIT(); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define T_CALL_ERROR \
|
||||
do { \
|
||||
printf("%s:%d:%s: error calling T, you have to use T_INT() or T_XX()\n", \
|
||||
__FILE__, __LINE__, __FUNCTION__); \
|
||||
} while (0)
|
||||
|
||||
#define T2(...) T_CALL_ERROR
|
||||
#define T4(...) T_CALL_ERROR
|
||||
#define T6(...) T_CALL_ERROR
|
||||
#define T8(...) T_CALL_ERROR
|
||||
#define T10(...) T_CALL_ERROR
|
||||
#define T12(...) T_CALL_ERROR
|
||||
#define T14(...) T_CALL_ERROR
|
||||
#define T16(...) T_CALL_ERROR
|
||||
#define T18(...) T_CALL_ERROR
|
||||
#define T20(...) T_CALL_ERROR
|
||||
#define T22(...) T_CALL_ERROR
|
||||
#define T24(...) T_CALL_ERROR
|
||||
#define T26(...) T_CALL_ERROR
|
||||
#define T28(...) T_CALL_ERROR
|
||||
#define T30(...) T_CALL_ERROR
|
||||
#define T32(...) T_CALL_ERROR
|
||||
|
||||
/* special cases for VCD logs */
|
||||
|
||||
#define T_VCD_VARIABLE(var, val) \
|
||||
do { \
|
||||
if (T_ACTIVE(((var) + VCD_FIRST_VARIABLE))) { \
|
||||
if ((var) > VCD_NUM_VARIABLES) { \
|
||||
printf("%s:%d:%s: VCD data out of synch for the T, contact" \
|
||||
" the authors!\n", __FILE__, __LINE__, __FUNCTION__); \
|
||||
abort(); \
|
||||
} \
|
||||
T_LOCAL_DATA \
|
||||
T_HEADER(T_ID((var) + VCD_FIRST_VARIABLE)); \
|
||||
T_PUT_ulong(1, (val)); \
|
||||
T_COMMIT(); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define T_VCD_FUNCTION(fun, val) \
|
||||
do { \
|
||||
if (T_ACTIVE(((fun) + VCD_FIRST_FUNCTION))) { \
|
||||
if ((fun) > VCD_NUM_FUNCTIONS) { \
|
||||
printf("%s:%d:%s: VCD data out of synch for the T, contact" \
|
||||
" the authors!\n", __FILE__, __LINE__, __FUNCTION__); \
|
||||
abort(); \
|
||||
} \
|
||||
T_LOCAL_DATA \
|
||||
T_HEADER(T_ID((fun) + VCD_FIRST_FUNCTION)); \
|
||||
T_PUT_int(1, (val)); \
|
||||
T_COMMIT(); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
extern int *T_active;
|
||||
|
||||
void T_init(int remote_port, int wait_for_tracer);
|
||||
|
||||
#else /* T_TRACER */
|
||||
|
||||
/* if T_TRACER is not defined or is 0, the T is deactivated */
|
||||
#define T(...) /**/
|
||||
|
||||
#endif /* T_TRACER */
|
||||
|
||||
#endif /* _T_T_T_ */
|
||||
@@ -0,0 +1,43 @@
|
||||
#ifndef _T_defs_H_
|
||||
#define _T_defs_H_
|
||||
|
||||
/* comment (and recompile everything) to not send time in events */
|
||||
#define T_SEND_TIME
|
||||
|
||||
/* maximum number of arguments for the T macro */
|
||||
#define T_MAX_ARGS 16
|
||||
|
||||
/* maximum size of a message - increase if needed */
|
||||
#define T_BUFFER_MAX (1024*64)
|
||||
|
||||
/* size of the local cache for messages (must be pow(2,something)) */
|
||||
#define T_CACHE_SIZE (8192 * 2)
|
||||
|
||||
/* maximum number of bytes a message can contain */
|
||||
#ifdef T_SEND_TIME
|
||||
# define T_PAYLOAD_MAXSIZE (T_BUFFER_MAX-sizeof(int)-sizeof(struct timespec))
|
||||
#else
|
||||
# define T_PAYLOAD_MAXSIZE (T_BUFFER_MAX-sizeof(int))
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
volatile int busy;
|
||||
char buffer[T_BUFFER_MAX];
|
||||
int length;
|
||||
} T_cache_t;
|
||||
|
||||
#define T_SHM_FILENAME "/T_shm_segment"
|
||||
|
||||
/* number of VCD functions (to be kept up to date! see in T_messages.txt) */
|
||||
#define VCD_NUM_FUNCTIONS 146
|
||||
|
||||
/* number of VCD variables (to be kept up to date! see in T_messages.txt) */
|
||||
#define VCD_NUM_VARIABLES 99
|
||||
|
||||
/* first VCD function (to be kept up to date! see in T_messages.txt) */
|
||||
#define VCD_FIRST_FUNCTION ((uintptr_t)T_VCD_FUNCTION_RT_SLEEP)
|
||||
|
||||
/* first VCD variable (to be kept up to date! see in T_messages.txt) */
|
||||
#define VCD_FIRST_VARIABLE ((uintptr_t)T_VCD_VARIABLE_FRAME_NUMBER_TX_ENB)
|
||||
|
||||
#endif /* _T_defs_H_ */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,30 @@
|
||||
#ifndef _TRACER_DEFS_H_
|
||||
#define _TRACER_DEFS_H_
|
||||
|
||||
/* types of plots */
|
||||
#define PLOT_VS_TIME 0
|
||||
#define PLOT_IQ_POINTS 1
|
||||
#define PLOT_MINMAX 2
|
||||
|
||||
void new_thread(void *(*f)(void *), void *data);
|
||||
|
||||
/* ... is { int count; int type; char *color; } for 'nplots' plots */
|
||||
void *make_plot(int width, int height, char *title, int nplots, ...);
|
||||
void plot_set(void *plot, float *data, int len, int pos, int pp);
|
||||
void iq_plot_set(void *plot, short *data, int len, int pos, int pp);
|
||||
void iq_plot_set_sized(void *_plot, short *data, int len, int pp);
|
||||
void iq_plot_add_iq_point_loop(void *_plot, short i, short q, int pp);
|
||||
void iq_plot_add_energy_point_loop(void *_plot, int e, int pp);
|
||||
|
||||
/* returns an opaque pointer - truly a 'database *', see t_data.c */
|
||||
void *parse_database(char *filename);
|
||||
void dump_database(void *database);
|
||||
void list_ids(void *database);
|
||||
void list_groups(void *database);
|
||||
void on_off(void *d, char *item, int *a, int onoff);
|
||||
|
||||
void *forwarder(char *ip, int port);
|
||||
void forward(void *forwarder, char *buf, int size);
|
||||
void forward_start_client(void *forwarder, int socket);
|
||||
|
||||
#endif /* _TRACER_DEFS_H_ */
|
||||
@@ -0,0 +1,25 @@
|
||||
#include <stdio.h>
|
||||
|
||||
void print(int n)
|
||||
{
|
||||
int i;
|
||||
printf("#define T%d(t", n);
|
||||
for(i=0; i<(n-1)/2; i++) printf(",t%d,x%d", i, i);
|
||||
printf(") \\\n");
|
||||
printf(" do { \\\n");
|
||||
printf(" if (T_ACTIVE(t)) { \\\n");
|
||||
printf(" T_LOCAL_DATA \\\n");
|
||||
printf(" T_HEADER(t); \\\n");
|
||||
for(i=0; i<(n-1)/2; i++) printf(" T_PUT_##t%d(%d, x%d); \\\n", i, i+2, i);
|
||||
printf(" T_COMMIT(); \\\n");
|
||||
printf(" } \\\n");
|
||||
printf(" } while (0)\n");
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int i;
|
||||
for (i = 11; i <= 33; i+=2) print(i);
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
char **unique_ids;
|
||||
int unique_ids_size;
|
||||
int unique_ids_maxsize;
|
||||
|
||||
int cmp(const void *p1, const void *p2)
|
||||
{
|
||||
return strcmp(*(char * const *)p1, *(char * const *)p2);
|
||||
}
|
||||
|
||||
/* return 1 if s was not already known, 0 if it was */
|
||||
int new_unique_id(char *s)
|
||||
{
|
||||
if (unique_ids_size)
|
||||
if (bsearch(&s, unique_ids, unique_ids_size, sizeof(char *), cmp) != NULL) {
|
||||
printf("FATAL: ID %s is not unique\n", s);
|
||||
return 0;
|
||||
}
|
||||
if (unique_ids_size == unique_ids_maxsize) {
|
||||
unique_ids_maxsize += 256;
|
||||
unique_ids = realloc(unique_ids, unique_ids_maxsize * sizeof(char *));
|
||||
if (unique_ids == NULL) { printf("out of memory\n"); abort(); }
|
||||
}
|
||||
unique_ids[unique_ids_size] = strdup(s);
|
||||
if (unique_ids[unique_ids_size] == NULL)
|
||||
{ printf("out of memory\n"); abort(); }
|
||||
unique_ids_size++;
|
||||
qsort(unique_ids, unique_ids_size, sizeof(char *), cmp);
|
||||
return 1;
|
||||
}
|
||||
|
||||
char *bufname;
|
||||
int bufname_size;
|
||||
int bufname_maxsize;
|
||||
|
||||
void putname(int c)
|
||||
{
|
||||
if (bufname_size == bufname_maxsize) {
|
||||
bufname_maxsize += 256;
|
||||
bufname = realloc(bufname, bufname_maxsize);
|
||||
if (bufname == NULL) { printf("memory allocation error\n"); exit(1); }
|
||||
}
|
||||
bufname[bufname_size] = c;
|
||||
bufname_size++;
|
||||
}
|
||||
|
||||
char *bufvalue;
|
||||
int bufvalue_size;
|
||||
int bufvalue_maxsize;
|
||||
|
||||
void putvalue(int c)
|
||||
{
|
||||
if (bufvalue_size == bufvalue_maxsize) {
|
||||
bufvalue_maxsize += 256;
|
||||
bufvalue = realloc(bufvalue, bufvalue_maxsize);
|
||||
if (bufvalue == NULL) { printf("memory allocation error\n"); exit(1); }
|
||||
}
|
||||
bufvalue[bufvalue_size] = c;
|
||||
bufvalue_size++;
|
||||
}
|
||||
|
||||
void smash_spaces(FILE *f)
|
||||
{
|
||||
int c;
|
||||
while (1) {
|
||||
c = fgetc(f);
|
||||
if (isspace(c)) continue;
|
||||
if (c == ' ') continue;
|
||||
if (c == '\t') continue;
|
||||
if (c == '\n') continue;
|
||||
if (c == 10 || c == 13) continue;
|
||||
if (c == '#') {
|
||||
while (1) {
|
||||
c = fgetc(f);
|
||||
if (c == '\n' || c == EOF) break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (c != EOF) ungetc(c, f);
|
||||
}
|
||||
|
||||
void get_line(FILE *f, char **name, char **value)
|
||||
{
|
||||
int c;
|
||||
bufname_size = 0;
|
||||
bufvalue_size = 0;
|
||||
*name = NULL;
|
||||
*value = NULL;
|
||||
smash_spaces(f);
|
||||
c = fgetc(f);
|
||||
while (!(c == '=' || isspace(c) || c == EOF)) { putname(c); c = fgetc(f); }
|
||||
if (c == EOF) return;
|
||||
putname(0);
|
||||
while (!(c == EOF || c == '=')) c = fgetc(f);
|
||||
if (c == EOF) return;
|
||||
smash_spaces(f);
|
||||
c = fgetc(f);
|
||||
while (!(c == 10 || c == 13 || c == EOF)) { putvalue(c); c = fgetc(f); }
|
||||
putvalue(0);
|
||||
if (bufname_size <= 1) return;
|
||||
if (bufvalue_size <= 1) return;
|
||||
*name = bufname;
|
||||
*value = bufvalue;
|
||||
}
|
||||
|
||||
int main(int n, char **v)
|
||||
{
|
||||
FILE *in;
|
||||
FILE *out;
|
||||
char *name;
|
||||
char *value;
|
||||
char *in_name;
|
||||
char *out_name;
|
||||
|
||||
if (n != 3) { printf("gimme <source> <dest>\n"); exit(1); }
|
||||
|
||||
n = 0;
|
||||
|
||||
in_name = v[1];
|
||||
out_name = v[2];
|
||||
|
||||
in = fopen(in_name, "r"); if (in == NULL) { perror(in_name); exit(1); }
|
||||
out = fopen(out_name, "w"); if (out == NULL) { perror(out_name); exit(1); }
|
||||
|
||||
fprintf(out, "/* generated file, do not edit by hand */\n\n");
|
||||
|
||||
while (1) {
|
||||
get_line(in, &name, &value);
|
||||
if (name == NULL) break;
|
||||
printf("name '%s' value '%s'\n", name, value);
|
||||
if (isspace(value[strlen(value)-1])) {
|
||||
printf("bad value '%s' (no space at the end please!)\n", value);
|
||||
unlink(out_name);
|
||||
exit(1);
|
||||
}
|
||||
if (!strcmp(name, "ID")) {
|
||||
if (!new_unique_id(value)) { unlink(out_name); exit(1); }
|
||||
fprintf(out, "#define T_%s T_ID(%d)\n", value, n);
|
||||
n++;
|
||||
}
|
||||
}
|
||||
fprintf(out, "#define T_NUMBER_OF_IDS %d\n", n);
|
||||
|
||||
fclose(in);
|
||||
fclose(out);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,344 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <pthread.h>
|
||||
#include <inttypes.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include "T_defs.h"
|
||||
#include "T_IDs.h"
|
||||
|
||||
static T_cache_t *T_cache;
|
||||
static int T_busylist_head;
|
||||
|
||||
typedef struct databuf {
|
||||
char *d;
|
||||
int l;
|
||||
struct databuf *next;
|
||||
} databuf;
|
||||
|
||||
typedef struct {
|
||||
int socket_local;
|
||||
volatile int socket_remote;
|
||||
int remote_port;
|
||||
pthread_mutex_t lock;
|
||||
pthread_cond_t cond;
|
||||
databuf * volatile head, *tail;
|
||||
uint64_t memusage;
|
||||
uint64_t last_warning_memusage;
|
||||
} forward_data;
|
||||
|
||||
/****************************************************************************/
|
||||
/* utility functions */
|
||||
/****************************************************************************/
|
||||
|
||||
static void new_thread(void *(*f)(void *), void *data)
|
||||
{
|
||||
pthread_t t;
|
||||
pthread_attr_t att;
|
||||
|
||||
if (pthread_attr_init(&att))
|
||||
{ fprintf(stderr, "pthread_attr_init err\n"); exit(1); }
|
||||
if (pthread_attr_setdetachstate(&att, PTHREAD_CREATE_DETACHED))
|
||||
{ fprintf(stderr, "pthread_attr_setdetachstate err\n"); exit(1); }
|
||||
if (pthread_attr_setstacksize(&att, 10000000))
|
||||
{ fprintf(stderr, "pthread_attr_setstacksize err\n"); exit(1); }
|
||||
if (pthread_create(&t, &att, f, data))
|
||||
{ fprintf(stderr, "pthread_create err\n"); exit(1); }
|
||||
if (pthread_attr_destroy(&att))
|
||||
{ fprintf(stderr, "pthread_attr_destroy err\n"); exit(1); }
|
||||
}
|
||||
|
||||
static int get_connection(char *addr, int port)
|
||||
{
|
||||
struct sockaddr_in a;
|
||||
socklen_t alen;
|
||||
int s, t;
|
||||
|
||||
printf("waiting for connection on %s:%d\n", addr, port);
|
||||
|
||||
s = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (s == -1) { perror("socket"); exit(1); }
|
||||
t = 1;
|
||||
if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &t, sizeof(int)))
|
||||
{ perror("setsockopt"); exit(1); }
|
||||
|
||||
a.sin_family = AF_INET;
|
||||
a.sin_port = htons(port);
|
||||
a.sin_addr.s_addr = inet_addr(addr);
|
||||
|
||||
if (bind(s, (struct sockaddr *)&a, sizeof(a))) { perror("bind"); exit(1); }
|
||||
if (listen(s, 5)) { perror("bind"); exit(1); }
|
||||
alen = sizeof(a);
|
||||
t = accept(s, (struct sockaddr *)&a, &alen);
|
||||
if (t == -1) { perror("accept"); exit(1); }
|
||||
close(s);
|
||||
|
||||
printf("connected\n");
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
/* forward functions */
|
||||
/****************************************************************************/
|
||||
|
||||
static void *data_sender(void *_f)
|
||||
{
|
||||
forward_data *f = _f;
|
||||
databuf *cur;
|
||||
char *buf, *b;
|
||||
int size;
|
||||
|
||||
wait:
|
||||
if (pthread_mutex_lock(&f->lock)) abort();
|
||||
while (f->head == NULL)
|
||||
if (pthread_cond_wait(&f->cond, &f->lock)) abort();
|
||||
cur = f->head;
|
||||
buf = cur->d;
|
||||
size = cur->l;
|
||||
f->head = cur->next;
|
||||
f->memusage -= size;
|
||||
if (f->head == NULL) f->tail = NULL;
|
||||
if (pthread_mutex_unlock(&f->lock)) abort();
|
||||
free(cur);
|
||||
goto process;
|
||||
|
||||
process:
|
||||
b = buf;
|
||||
if (f->socket_remote != -1)
|
||||
while (size) {
|
||||
int l = write(f->socket_remote, b, size);
|
||||
if (l <= 0) {
|
||||
printf("forward error\n");
|
||||
close(f->socket_remote);
|
||||
f->socket_remote = -1;
|
||||
break;
|
||||
}
|
||||
size -= l;
|
||||
b += l;
|
||||
}
|
||||
|
||||
free(buf);
|
||||
|
||||
goto wait;
|
||||
}
|
||||
|
||||
static void *forward_remote_messages(void *_f)
|
||||
{
|
||||
#define PUT(x) do { \
|
||||
if (bufsize == bufmaxsize) { \
|
||||
bufmaxsize += 4096; \
|
||||
buf = realloc(buf, bufmaxsize); \
|
||||
if (buf == NULL) abort(); \
|
||||
} \
|
||||
buf[bufsize] = x; \
|
||||
bufsize++; \
|
||||
} while (0)
|
||||
#define PUT_BUF(x, l) do { \
|
||||
char *zz = (char *)(x); \
|
||||
int len = l; \
|
||||
while (len) { PUT(*zz); zz++; len--; } \
|
||||
} while (0)
|
||||
|
||||
forward_data *f = _f;
|
||||
int from;
|
||||
int to;
|
||||
int l, len;
|
||||
char *b;
|
||||
char *buf = NULL;
|
||||
int bufsize = 0;
|
||||
int bufmaxsize = 0;
|
||||
char t;
|
||||
|
||||
again:
|
||||
|
||||
while (1) {
|
||||
from = f->socket_remote;
|
||||
to = f->socket_local;
|
||||
|
||||
bufsize = 0;
|
||||
|
||||
/* let's read and process messages */
|
||||
len = read(from, &t, 1); if (len <= 0) goto dead;
|
||||
PUT(t);
|
||||
|
||||
switch (t) {
|
||||
case 0:
|
||||
case 1:
|
||||
/* message 0 and 1: get a length and then 'length' numbers */
|
||||
if (read(from, &len, sizeof(int)) != sizeof(int)) goto dead;
|
||||
PUT_BUF(&len, 4);
|
||||
while (len) {
|
||||
if (read(from, &l, sizeof(int)) != sizeof(int)) goto dead;
|
||||
PUT_BUF(&l, 4);
|
||||
len--;
|
||||
}
|
||||
break;
|
||||
|
||||
case 2: break;
|
||||
default:
|
||||
printf("%s:%d:%s: unhandled message type %d\n",
|
||||
__FILE__, __LINE__, __FUNCTION__, t);
|
||||
abort();
|
||||
}
|
||||
|
||||
b = buf;
|
||||
while (bufsize) {
|
||||
l = write(to, b, bufsize);
|
||||
if (l <= 0) abort();
|
||||
bufsize -= l;
|
||||
b += l;
|
||||
}
|
||||
}
|
||||
|
||||
dead:
|
||||
/* socket died, let's stop all traces and wait for another tracer */
|
||||
/* TODO: be careful with those write, they might write less than wanted */
|
||||
buf[0] = 1;
|
||||
if (write(to, buf, 1) != 1) abort();
|
||||
len = T_NUMBER_OF_IDS;
|
||||
if (write(to, &len, sizeof(int)) != sizeof(int)) abort();
|
||||
l = 0;
|
||||
while (len) {
|
||||
if (write(to, &l, sizeof(int)) != sizeof(int)) abort();
|
||||
len--;
|
||||
};
|
||||
|
||||
close(f->socket_remote);
|
||||
f->socket_remote = get_connection("0.0.0.0", f->remote_port);
|
||||
goto again;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void *forwarder(int port, int s)
|
||||
{
|
||||
forward_data *f;
|
||||
|
||||
f = malloc(sizeof(*f)); if (f == NULL) abort();
|
||||
|
||||
pthread_mutex_init(&f->lock, NULL);
|
||||
pthread_cond_init(&f->cond, NULL);
|
||||
|
||||
f->socket_local = s;
|
||||
f->head = f->tail = NULL;
|
||||
|
||||
f->memusage = 0;
|
||||
f->last_warning_memusage = 0;
|
||||
|
||||
printf("waiting for remote tracer on port %d\n", port);
|
||||
|
||||
f->remote_port = port;
|
||||
f->socket_remote = get_connection("0.0.0.0", port);
|
||||
|
||||
new_thread(data_sender, f);
|
||||
new_thread(forward_remote_messages, f);
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
static void forward(void *_forwarder, char *buf, int size)
|
||||
{
|
||||
forward_data *f = _forwarder;
|
||||
int32_t ssize = size;
|
||||
databuf *new;
|
||||
|
||||
new = malloc(sizeof(*new)); if (new == NULL) abort();
|
||||
|
||||
if (pthread_mutex_lock(&f->lock)) abort();
|
||||
|
||||
new->d = malloc(size + 4); if (new->d == NULL) abort();
|
||||
/* put the size of the message at the head */
|
||||
memcpy(new->d, &ssize, 4);
|
||||
memcpy(new->d+4, buf, size);
|
||||
new->l = size+4;
|
||||
new->next = NULL;
|
||||
if (f->head == NULL) f->head = new;
|
||||
if (f->tail != NULL) f->tail->next = new;
|
||||
f->tail = new;
|
||||
|
||||
f->memusage += size+4;
|
||||
/* warn every 100MB */
|
||||
if (f->memusage > f->last_warning_memusage &&
|
||||
f->memusage - f->last_warning_memusage > 100000000) {
|
||||
f->last_warning_memusage += 100000000;
|
||||
printf("WARNING: memory usage is over %"PRIu64"MB\n",
|
||||
f->last_warning_memusage / 1000000);
|
||||
} else
|
||||
if (f->memusage < f->last_warning_memusage &&
|
||||
f->last_warning_memusage - f->memusage > 100000000) {
|
||||
f->last_warning_memusage = (f->memusage/100000000) * 100000000;
|
||||
}
|
||||
|
||||
if (pthread_cond_signal(&f->cond)) abort();
|
||||
if (pthread_mutex_unlock(&f->lock)) abort();
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
/* local functions */
|
||||
/****************************************************************************/
|
||||
|
||||
static void wait_message(void)
|
||||
{
|
||||
while (T_cache[T_busylist_head].busy == 0) usleep(1000);
|
||||
}
|
||||
|
||||
static void init_shm(void)
|
||||
{
|
||||
int i;
|
||||
int s = shm_open(T_SHM_FILENAME, O_RDWR | O_CREAT /*| O_SYNC*/, 0666);
|
||||
if (s == -1) { perror(T_SHM_FILENAME); abort(); }
|
||||
if (ftruncate(s, T_CACHE_SIZE * sizeof(T_cache_t)))
|
||||
{ perror(T_SHM_FILENAME); abort(); }
|
||||
T_cache = mmap(NULL, T_CACHE_SIZE * sizeof(T_cache_t),
|
||||
PROT_READ | PROT_WRITE, MAP_SHARED, s, 0);
|
||||
if (T_cache == NULL)
|
||||
{ perror(T_SHM_FILENAME); abort(); }
|
||||
close(s);
|
||||
|
||||
/* let's garbage the memory to catch some potential problems
|
||||
* (think multiprocessor sync issues, barriers, etc.)
|
||||
*/
|
||||
memset(T_cache, 0x55, T_CACHE_SIZE * sizeof(T_cache_t));
|
||||
for (i = 0; i < T_CACHE_SIZE; i++) T_cache[i].busy = 0;
|
||||
}
|
||||
|
||||
void T_local_tracer_main(int remote_port, int wait_for_tracer,
|
||||
int local_socket)
|
||||
{
|
||||
int s;
|
||||
int port = remote_port;
|
||||
int dont_wait = wait_for_tracer ? 0 : 1;
|
||||
void *f;
|
||||
|
||||
/* write on a socket fails if the other end is closed and we get SIGPIPE */
|
||||
if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) abort();
|
||||
|
||||
init_shm();
|
||||
s = local_socket;
|
||||
|
||||
if (dont_wait) {
|
||||
char t = 2;
|
||||
if (write(s, &t, 1) != 1) abort();
|
||||
}
|
||||
|
||||
f = forwarder(port, s);
|
||||
|
||||
/* read messages */
|
||||
while (1) {
|
||||
wait_message();
|
||||
__sync_synchronize();
|
||||
forward(f, T_cache[T_busylist_head].buffer,
|
||||
T_cache[T_busylist_head].length);
|
||||
T_cache[T_busylist_head].busy = 0;
|
||||
T_busylist_head++;
|
||||
T_busylist_head &= T_CACHE_SIZE - 1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,291 @@
|
||||
#include "defs.h"
|
||||
#include <X11/Xlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
#include <math.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/select.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
typedef struct {
|
||||
float *buf;
|
||||
short *iqbuf;
|
||||
int count;
|
||||
int type;
|
||||
volatile int iq_count; /* for ULSCH IQ data */
|
||||
int iq_insert_pos;
|
||||
GC g;
|
||||
} data;
|
||||
|
||||
typedef struct {
|
||||
Display *d;
|
||||
Window w;
|
||||
Pixmap px;
|
||||
GC bg;
|
||||
int width;
|
||||
int height;
|
||||
pthread_mutex_t lock;
|
||||
float zoom;
|
||||
int timer_pipe[2];
|
||||
data *p; /* list of plots */
|
||||
int nplots;
|
||||
} plot;
|
||||
|
||||
static void *timer_thread(void *_p)
|
||||
{
|
||||
plot *p = _p;
|
||||
char c;
|
||||
|
||||
while (1) {
|
||||
/* more or less 10Hz */
|
||||
usleep(100*1000);
|
||||
c = 1;
|
||||
if (write(p->timer_pipe[1], &c, 1) != 1) abort();
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void *plot_thread(void *_p)
|
||||
{
|
||||
float v;
|
||||
float *s;
|
||||
int i, j;
|
||||
plot *p = _p;
|
||||
int redraw = 0;
|
||||
int replot = 0;
|
||||
fd_set rset;
|
||||
int xfd = ConnectionNumber(p->d);
|
||||
int maxfd = xfd > p->timer_pipe[0] ? xfd : p->timer_pipe[0];
|
||||
int pp;
|
||||
|
||||
while (1) {
|
||||
while (XPending(p->d)) {
|
||||
XEvent e;
|
||||
XNextEvent(p->d, &e);
|
||||
switch (e.type) {
|
||||
case ButtonPress:
|
||||
/* button 4: zoom out */
|
||||
if (e.xbutton.button == 4) { p->zoom = p->zoom * 1.25; replot = 1; }
|
||||
/* button 5: zoom in */
|
||||
if (e.xbutton.button == 5) { p->zoom = p->zoom * 0.8; replot = 1; }
|
||||
printf("zoom: %f\n", p->zoom);
|
||||
break;
|
||||
case Expose: redraw = 1; break;
|
||||
}
|
||||
}
|
||||
|
||||
if (replot == 1) {
|
||||
replot = 0;
|
||||
redraw = 1;
|
||||
|
||||
if (pthread_mutex_lock(&p->lock)) abort();
|
||||
|
||||
XFillRectangle(p->d, p->px, p->bg, 0, 0, p->width, p->height);
|
||||
|
||||
for (pp = 0; pp < p->nplots; pp++) {
|
||||
if (p->p[pp].type == PLOT_MINMAX) {
|
||||
s = p->p[pp].buf;
|
||||
for (i = 0; i < 512; i++) {
|
||||
int min = *s;
|
||||
int max = *s;
|
||||
for (j = 0; j < p->p[pp].count/512; j++, s++) {
|
||||
if (*s < min) min = *s;
|
||||
if (*s > max) max = *s;
|
||||
}
|
||||
XDrawLine(p->d, p->px, p->p[pp].g, i, 100-min, i, 100-max);
|
||||
}
|
||||
} else if (p->p[pp].type == PLOT_VS_TIME) {
|
||||
for (i = 0; i < p->p[pp].count; i++)
|
||||
p->p[pp].buf[i] =
|
||||
10*log10(1.0+(float)(p->p[pp].iqbuf[2*i]*p->p[pp].iqbuf[2*i]+
|
||||
p->p[pp].iqbuf[2*i+1]*p->p[pp].iqbuf[2*i+1]));
|
||||
s = p->p[pp].buf;
|
||||
for (i = 0; i < 512; i++) {
|
||||
v = 0;
|
||||
for (j = 0; j < p->p[pp].count/512; j++, s++) v += *s;
|
||||
v /= p->p[pp].count/512;
|
||||
XDrawLine(p->d, p->px, p->p[pp].g, i, 100, i, 100-v);
|
||||
}
|
||||
} else if (p->p[pp].type == PLOT_IQ_POINTS) {
|
||||
XPoint pts[p->p[pp].iq_count];
|
||||
int count = p->p[pp].iq_count;
|
||||
for (i = 0; i < count; i++) {
|
||||
pts[i].x = p->p[pp].iqbuf[2*i]*p->zoom/20+50;
|
||||
pts[i].y = -p->p[pp].iqbuf[2*i+1]*p->zoom/20+50;
|
||||
}
|
||||
XDrawPoints(p->d, p->px, p->p[pp].g, pts, count, CoordModeOrigin);
|
||||
}
|
||||
}
|
||||
|
||||
if (pthread_mutex_unlock(&p->lock)) abort();
|
||||
}
|
||||
|
||||
if (redraw) {
|
||||
redraw = 0;
|
||||
XCopyArea(p->d, p->px, p->w, DefaultGC(p->d, DefaultScreen(p->d)),
|
||||
0, 0, p->width, p->height, 0, 0);
|
||||
}
|
||||
|
||||
XFlush(p->d);
|
||||
|
||||
FD_ZERO(&rset);
|
||||
FD_SET(p->timer_pipe[0], &rset);
|
||||
FD_SET(xfd, &rset);
|
||||
if (select(maxfd+1, &rset, NULL, NULL, NULL) == -1) abort();
|
||||
if (FD_ISSET(p->timer_pipe[0], &rset)) {
|
||||
char b[512];
|
||||
if (read(p->timer_pipe[0], b, 512) <= 0) abort();
|
||||
replot = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *make_plot(int width, int height, char *title, int nplots, ...)
|
||||
{
|
||||
plot *p;
|
||||
Display *d;
|
||||
Window w;
|
||||
Pixmap pm;
|
||||
int i;
|
||||
va_list ap;
|
||||
XGCValues gcv;
|
||||
|
||||
p = malloc(sizeof(*p)); if (p == NULL) abort();
|
||||
|
||||
d = XOpenDisplay(0); if (d == NULL) abort();
|
||||
w = XCreateSimpleWindow(d, DefaultRootWindow(d), 0, 0, width, height,
|
||||
0, WhitePixel(d, DefaultScreen(d)), WhitePixel(d, DefaultScreen(d)));
|
||||
XSelectInput(d, w, ExposureMask | ButtonPressMask);
|
||||
XMapWindow(d, w);
|
||||
|
||||
{
|
||||
XSetWindowAttributes att;
|
||||
att.backing_store = Always;
|
||||
XChangeWindowAttributes(d, w, CWBackingStore, &att);
|
||||
}
|
||||
|
||||
XStoreName(d, w, title);
|
||||
|
||||
p->bg = XCreateGC(d, w, 0, NULL);
|
||||
XCopyGC(d, DefaultGC(d, DefaultScreen(d)), -1L, p->bg);
|
||||
gcv.foreground = WhitePixel(d, DefaultScreen(d));
|
||||
XChangeGC(d, p->bg, GCForeground, &gcv);
|
||||
|
||||
pm = XCreatePixmap(d, w, width, height, DefaultDepth(d, DefaultScreen(d)));
|
||||
|
||||
p->width = width;
|
||||
p->height = height;
|
||||
p->p = malloc(nplots * sizeof(data)); if (p->p == NULL) abort();
|
||||
|
||||
va_start(ap, nplots);
|
||||
for (i = 0; i < nplots; i++) {
|
||||
int count;
|
||||
int type;
|
||||
char *color;
|
||||
XColor rcol, scol;
|
||||
|
||||
count = va_arg(ap, int);
|
||||
type = va_arg(ap, int);
|
||||
color = va_arg(ap, char *);
|
||||
|
||||
p->p[i].g = XCreateGC(d, w, 0, NULL);
|
||||
XCopyGC(d, DefaultGC(d, DefaultScreen(d)), -1L, p->p[i].g);
|
||||
if (XAllocNamedColor(d, DefaultColormap(d, DefaultScreen(d)),
|
||||
color, &scol, &rcol)) {
|
||||
gcv.foreground = scol.pixel;
|
||||
XChangeGC(d, p->p[i].g, GCForeground, &gcv);
|
||||
} else {
|
||||
printf("could not allocate color '%s'\n", color);
|
||||
abort();
|
||||
}
|
||||
|
||||
if (type == PLOT_VS_TIME) {
|
||||
p->p[i].buf = malloc(sizeof(float) * count);
|
||||
if (p->p[i].buf == NULL) abort();
|
||||
p->p[i].iqbuf = malloc(sizeof(short) * count * 2);
|
||||
if(p->p[i].iqbuf==NULL)abort();
|
||||
} else if (type == PLOT_MINMAX) {
|
||||
p->p[i].buf = malloc(sizeof(float) * count);
|
||||
if (p->p[i].buf == NULL) abort();
|
||||
p->p[i].iqbuf = NULL;
|
||||
} else {
|
||||
p->p[i].buf = NULL;
|
||||
p->p[i].iqbuf = malloc(sizeof(short) * count * 2);
|
||||
if(p->p[i].iqbuf==NULL)abort();
|
||||
}
|
||||
p->p[i].count = count;
|
||||
p->p[i].type = type;
|
||||
p->p[i].iq_count = 0;
|
||||
p->p[i].iq_insert_pos = 0;
|
||||
}
|
||||
va_end(ap);
|
||||
|
||||
p->d = d;
|
||||
p->w = w;
|
||||
p->px = pm;
|
||||
|
||||
p->zoom = 1;
|
||||
p->nplots = nplots;
|
||||
|
||||
pthread_mutex_init(&p->lock, NULL);
|
||||
|
||||
if (pipe(p->timer_pipe)) abort();
|
||||
|
||||
new_thread(plot_thread, p);
|
||||
new_thread(timer_thread, p);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
void plot_set(void *_plot, float *data, int len, int pos, int pp)
|
||||
{
|
||||
plot *p = _plot;
|
||||
if (pthread_mutex_lock(&p->lock)) abort();
|
||||
memcpy(p->p[pp].buf + pos, data, len * sizeof(float));
|
||||
if (pthread_mutex_unlock(&p->lock)) abort();
|
||||
}
|
||||
|
||||
void iq_plot_set(void *_plot, short *data, int count, int pos, int pp)
|
||||
{
|
||||
plot *p = _plot;
|
||||
if (pthread_mutex_lock(&p->lock)) abort();
|
||||
memcpy(p->p[pp].iqbuf + pos * 2, data, count * 2 * sizeof(short));
|
||||
if (pthread_mutex_unlock(&p->lock)) abort();
|
||||
}
|
||||
|
||||
void iq_plot_set_sized(void *_plot, short *data, int count, int pp)
|
||||
{
|
||||
plot *p = _plot;
|
||||
if (pthread_mutex_lock(&p->lock)) abort();
|
||||
memcpy(p->p[pp].iqbuf, data, count * 2 * sizeof(short));
|
||||
p->p[pp].iq_count = count;
|
||||
if (pthread_mutex_unlock(&p->lock)) abort();
|
||||
}
|
||||
|
||||
void iq_plot_add_iq_point_loop(void *_plot, short i, short q, int pp)
|
||||
{
|
||||
plot *p = _plot;
|
||||
if (pthread_mutex_lock(&p->lock)) abort();
|
||||
p->p[pp].iqbuf[p->p[pp].iq_insert_pos*2] = i;
|
||||
p->p[pp].iqbuf[p->p[pp].iq_insert_pos*2+1] = q;
|
||||
if (p->p[pp].iq_count != p->p[pp].count) p->p[pp].iq_count++;
|
||||
p->p[pp].iq_insert_pos++;
|
||||
if (p->p[pp].iq_insert_pos == p->p[pp].count) p->p[pp].iq_insert_pos = 0;
|
||||
if (pthread_mutex_unlock(&p->lock)) abort();
|
||||
}
|
||||
|
||||
void iq_plot_add_energy_point_loop(void *_plot, int e, int pp)
|
||||
{
|
||||
plot *p = _plot;
|
||||
if (pthread_mutex_lock(&p->lock)) abort();
|
||||
p->p[pp].buf[p->p[pp].iq_insert_pos] = e;
|
||||
if (p->p[pp].iq_count != p->p[pp].count) p->p[pp].iq_count++;
|
||||
p->p[pp].iq_insert_pos++;
|
||||
if (p->p[pp].iq_insert_pos == p->p[pp].count) p->p[pp].iq_insert_pos = 0;
|
||||
if (pthread_mutex_unlock(&p->lock)) abort();
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
CC=gcc
|
||||
CFLAGS=-Wall -g -pthread -DT_TRACER -I.
|
||||
|
||||
PROG=tracee
|
||||
OBJS=tracee.o ../T.o
|
||||
|
||||
$(PROG): $(OBJS)
|
||||
$(CC) $(CFLAGS) -o $(PROG) $(OBJS) -lrt
|
||||
|
||||
tracee.o: tracee.c
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
clean:
|
||||
rm -f *.o $(PROG) core
|
||||
@@ -0,0 +1 @@
|
||||
this is a very basic tracee, used to debug the tracer
|
||||
@@ -0,0 +1,16 @@
|
||||
#include "../T.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int frame = 0;
|
||||
T_connect_to_tracer("127.0.0.1", 2020);
|
||||
while (1) {
|
||||
getchar();
|
||||
T(T_ENB_PHY_PUCCH_1AB_IQ, T_INT(0), T_INT(0), T_INT(frame), T_INT(0), T_INT(0), T_INT(0));
|
||||
frame++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
CC=gcc
|
||||
CFLAGS=-Wall -g -pthread -DT_TRACER -I.
|
||||
|
||||
#CFLAGS += -O3 -ffast-math -fomit-frame-pointer
|
||||
|
||||
LIBS=-lX11 -lm -lpng -lXft
|
||||
|
||||
all: textlog enb vcd
|
||||
|
||||
textlog: utils.o textlog.o database.o event.o handler.o config.o \
|
||||
event_selector.o view/view.a gui/gui.a logger/logger.a \
|
||||
filter/filter.a
|
||||
$(CC) $(CFLAGS) -o textlog $^ $(LIBS)
|
||||
|
||||
enb: utils.o enb.o database.o event.o handler.o config.o \
|
||||
event_selector.o view/view.a gui/gui.a logger/logger.a \
|
||||
filter/filter.a
|
||||
$(CC) $(CFLAGS) -o enb $^ $(LIBS)
|
||||
|
||||
vcd: utils.o vcd.o database.o event.o handler.o config.o \
|
||||
event_selector.o view/view.a gui/gui.a logger/logger.a \
|
||||
filter/filter.a
|
||||
$(CC) $(CFLAGS) -o vcd $^ $(LIBS)
|
||||
|
||||
.PHONY: all gui/gui.a view/view.a logger/logger.a filter/filter.a
|
||||
|
||||
gui/gui.a:
|
||||
cd gui && make
|
||||
|
||||
view/view.a:
|
||||
cd view && make
|
||||
|
||||
logger/logger.a:
|
||||
cd logger && make
|
||||
|
||||
filter/filter.a:
|
||||
cd filter && make
|
||||
|
||||
%.o: %.c
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
clean:
|
||||
rm -f *.o core tracer_remote textlog enb vcd
|
||||
cd gui && make clean
|
||||
cd view && make clean
|
||||
cd logger && make clean
|
||||
cd filter && make clean
|
||||
@@ -0,0 +1,62 @@
|
||||
#include "config.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
static char *local;
|
||||
static int local_size;
|
||||
static char *remote;
|
||||
static int remote_size;
|
||||
|
||||
static char *PUT(char *to, int tosize, char c)
|
||||
{
|
||||
if ((tosize & 4095) == 0) {
|
||||
to = realloc(to, tosize + 4096); if (to == NULL) abort();
|
||||
}
|
||||
to[tosize] = c;
|
||||
return to;
|
||||
}
|
||||
|
||||
void clear_remote_config(void)
|
||||
{
|
||||
free(remote);
|
||||
remote = NULL;
|
||||
remote_size = 0;
|
||||
}
|
||||
|
||||
void append_received_config_chunk(char *buf, int length)
|
||||
{
|
||||
int buflen = *(int *)buf;
|
||||
if (buflen != length - sizeof(int)) {
|
||||
printf("ERROR: bad trace -1, should not happen...\n");
|
||||
abort();
|
||||
}
|
||||
buf += sizeof(int);
|
||||
while (buflen) {
|
||||
remote = PUT(remote, remote_size, *buf);
|
||||
remote_size++;
|
||||
buf++;
|
||||
buflen--;
|
||||
}
|
||||
}
|
||||
|
||||
void load_config_file(char *filename)
|
||||
{
|
||||
int c;
|
||||
FILE *f = fopen(filename, "r");
|
||||
if (f == NULL) { perror(filename); abort(); }
|
||||
while (1) {
|
||||
c = fgetc(f); if (c == EOF) break;
|
||||
local = PUT(local, local_size, c);
|
||||
local_size++;
|
||||
}
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
void verify_config(void)
|
||||
{
|
||||
if (local_size != remote_size || memcmp(local, remote, local_size) != 0) {
|
||||
printf("ERROR: local and remote T_messages.txt not identical\n");
|
||||
abort();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
#ifndef _CONFIG_H_
|
||||
#define _CONFIG_H_
|
||||
|
||||
void clear_remote_config(void);
|
||||
void append_received_config_chunk(char *buf, int length);
|
||||
void load_config_file(char *filename);
|
||||
void verify_config(void);
|
||||
|
||||
#endif /* _CONFIG_H_ */
|
||||
@@ -0,0 +1,503 @@
|
||||
#include "database.h"
|
||||
#include "utils.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
|
||||
typedef struct {
|
||||
char *name;
|
||||
char *desc;
|
||||
char **groups;
|
||||
int gsize;
|
||||
char **arg_type;
|
||||
char **arg_name;
|
||||
int asize;
|
||||
int id;
|
||||
} id;
|
||||
|
||||
typedef struct {
|
||||
char *name;
|
||||
char **ids;
|
||||
int size;
|
||||
} group;
|
||||
|
||||
typedef struct {
|
||||
char *name;
|
||||
id *i;
|
||||
int isize;
|
||||
group *g;
|
||||
int gsize;
|
||||
int *id_to_pos;
|
||||
} database;
|
||||
|
||||
typedef struct {
|
||||
char *data;
|
||||
int size;
|
||||
int maxsize;
|
||||
} buffer;
|
||||
|
||||
typedef struct {
|
||||
buffer name;
|
||||
buffer value;
|
||||
} parser;
|
||||
|
||||
void put(buffer *b, int c)
|
||||
{
|
||||
if (b->size == b->maxsize) {
|
||||
b->maxsize += 256;
|
||||
b->data = realloc(b->data, b->maxsize);
|
||||
if (b->data == NULL) { printf("memory allocation error\n"); exit(1); }
|
||||
}
|
||||
b->data[b->size] = c;
|
||||
b->size++;
|
||||
}
|
||||
|
||||
void smash_spaces(FILE *f)
|
||||
{
|
||||
int c;
|
||||
while (1) {
|
||||
c = fgetc(f);
|
||||
if (isspace(c)) continue;
|
||||
if (c == ' ') continue;
|
||||
if (c == '\t') continue;
|
||||
if (c == '\n') continue;
|
||||
if (c == 10 || c == 13) continue;
|
||||
if (c == '#') {
|
||||
while (1) {
|
||||
c = fgetc(f);
|
||||
if (c == '\n' || c == EOF) break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (c != EOF) ungetc(c, f);
|
||||
}
|
||||
|
||||
void get_line(parser *p, FILE *f, char **name, char **value)
|
||||
{
|
||||
int c;
|
||||
p->name.size = 0;
|
||||
p->value.size = 0;
|
||||
*name = NULL;
|
||||
*value = NULL;
|
||||
smash_spaces(f);
|
||||
c = fgetc(f);
|
||||
while (!(c == '=' || isspace(c) || c == EOF))
|
||||
{ put(&p->name, c); c = fgetc(f); }
|
||||
if (c == EOF) return;
|
||||
put(&p->name, 0);
|
||||
while (!(c == EOF || c == '=')) c = fgetc(f);
|
||||
if (c == EOF) return;
|
||||
smash_spaces(f);
|
||||
c = fgetc(f);
|
||||
while (!(c == 10 || c == 13 || c == EOF))
|
||||
{ put(&p->value, c); c = fgetc(f); }
|
||||
put(&p->value, 0);
|
||||
if (p->name.size <= 1) return;
|
||||
if (p->value.size <= 1) return;
|
||||
*name = p->name.data;
|
||||
*value = p->value.data;
|
||||
}
|
||||
|
||||
int group_cmp(const void *_p1, const void *_p2)
|
||||
{
|
||||
const group *p1 = _p1;
|
||||
const group *p2 = _p2;
|
||||
return strcmp(p1->name, p2->name);
|
||||
}
|
||||
|
||||
int id_cmp(const void *_p1, const void *_p2)
|
||||
{
|
||||
const id *p1 = _p1;
|
||||
const id *p2 = _p2;
|
||||
return strcmp(p1->name, p2->name);
|
||||
}
|
||||
|
||||
int string_cmp(const void *_p1, const void *_p2)
|
||||
{
|
||||
char * const *p1 = _p1;
|
||||
char * const *p2 = _p2;
|
||||
return strcmp(*p1, *p2);
|
||||
}
|
||||
|
||||
id *add_id(database *r, char *idname, int i)
|
||||
{
|
||||
if (bsearch(&(id){name:idname}, r->i, r->isize, sizeof(id), id_cmp) != NULL)
|
||||
{ printf("ERROR: ID '%s' declared more than once\n", idname); exit(1); }
|
||||
if ((r->isize & 1023) == 0) {
|
||||
r->i = realloc(r->i, (r->isize + 1024) * sizeof(id));
|
||||
if (r->i == NULL) { printf("out of memory\n"); exit(1); }
|
||||
}
|
||||
r->i[r->isize].name = strdup(idname);
|
||||
if (r->i[r->isize].name == NULL) { printf("out of memory\n"); exit(1); }
|
||||
r->i[r->isize].desc = NULL;
|
||||
r->i[r->isize].groups = NULL;
|
||||
r->i[r->isize].gsize = 0;
|
||||
r->i[r->isize].arg_type = NULL;
|
||||
r->i[r->isize].arg_name = NULL;
|
||||
r->i[r->isize].asize = 0;
|
||||
r->i[r->isize].id = i;
|
||||
r->isize++;
|
||||
qsort(r->i, r->isize, sizeof(id), id_cmp);
|
||||
return (id*)bsearch(&(id){name:idname}, r->i, r->isize, sizeof(id), id_cmp);
|
||||
}
|
||||
|
||||
group *get_group(database *r, char *group_name)
|
||||
{
|
||||
group *ret;
|
||||
|
||||
ret = bsearch(&(group){name:group_name},
|
||||
r->g, r->gsize, sizeof(group), group_cmp);
|
||||
if (ret != NULL) return ret;
|
||||
|
||||
if ((r->gsize & 1023) == 0) {
|
||||
r->g = realloc(r->g, (r->gsize + 1024) * sizeof(group));
|
||||
if (r->g == NULL) abort();
|
||||
}
|
||||
r->g[r->gsize].name = strdup(group_name);
|
||||
if (r->g[r->gsize].name == NULL) abort();
|
||||
r->g[r->gsize].ids = NULL;
|
||||
r->g[r->gsize].size = 0;
|
||||
r->gsize++;
|
||||
|
||||
qsort(r->g, r->gsize, sizeof(group), group_cmp);
|
||||
|
||||
return bsearch(&(group){name:group_name},
|
||||
r->g, r->gsize, sizeof(group), group_cmp);
|
||||
}
|
||||
|
||||
void group_add_id(group *g, char *id)
|
||||
{
|
||||
if ((g->size & 1023) == 0) {
|
||||
g->ids = realloc(g->ids, (g->size + 1024) * sizeof(char *));
|
||||
if (g->ids == NULL) abort();
|
||||
}
|
||||
g->ids[g->size] = id;
|
||||
g->size++;
|
||||
}
|
||||
|
||||
void id_add_group(id *i, char *group)
|
||||
{
|
||||
char *g = bsearch(&group, i->groups, i->gsize, sizeof(char *), string_cmp);
|
||||
if (g != NULL) return;
|
||||
|
||||
if ((i->gsize & 1023) == 0) {
|
||||
i->groups = realloc(i->groups, (i->gsize+1024) * sizeof(char *));
|
||||
if (i->groups == NULL) abort();
|
||||
}
|
||||
i->groups[i->gsize] = group;
|
||||
i->gsize++;
|
||||
qsort(i->groups, i->gsize, sizeof(char *), string_cmp);
|
||||
}
|
||||
|
||||
void add_groups(database *r, id *i, char *groups)
|
||||
{
|
||||
group *g;
|
||||
if (i == NULL) {printf("ERROR: GROUP line before ID line\n");exit(1);}
|
||||
while (1) {
|
||||
char *start = groups;
|
||||
char *end = start;
|
||||
while (!isspace(*end) && *end != ':' && *end != 0) end++;
|
||||
if (end == start) {
|
||||
printf("bad group line: groups are seperated by ':'\n");
|
||||
abort();
|
||||
}
|
||||
if (*end == 0) end = NULL; else *end = 0;
|
||||
|
||||
g = get_group(r, start);
|
||||
group_add_id(g, i->name);
|
||||
id_add_group(i, g->name);
|
||||
|
||||
if (end == NULL) break;
|
||||
end++;
|
||||
while ((isspace(*end) || *end == ':') && *end != 0) end++;
|
||||
if (*end == 0) break;
|
||||
groups = end;
|
||||
}
|
||||
}
|
||||
|
||||
void add_desc(id *i, char *desc)
|
||||
{
|
||||
if (i == NULL) {printf("ERROR: DESC line before ID line\n");exit(1);}
|
||||
i->desc = strdup(desc); if (i->desc == NULL) abort();
|
||||
}
|
||||
|
||||
char *format_get_next_token(char **cur)
|
||||
{
|
||||
char *start;
|
||||
char *end;
|
||||
char *ret;
|
||||
|
||||
start = *cur;
|
||||
|
||||
/* remove spaces */
|
||||
while (*start && isspace(*start)) start ++;
|
||||
if (*start == 0) return NULL;
|
||||
|
||||
/* special cases: ',' and ':' */
|
||||
if (*start == ',' || *start == ':') { end = start + 1; goto special; }
|
||||
|
||||
end = start;
|
||||
|
||||
/* go to end of token */
|
||||
while (*end && !isspace(*end) && *end != ',' && *end != ':') end++;
|
||||
|
||||
special:
|
||||
ret = malloc(end-start+1); if (ret == NULL) abort();
|
||||
memcpy(ret, start, end-start);
|
||||
ret[end-start] = 0;
|
||||
|
||||
*cur = end;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void add_format(id *id, char *format)
|
||||
{
|
||||
char *cur = format;
|
||||
char *type;
|
||||
char *name;
|
||||
char *sep;
|
||||
while (1) {
|
||||
/* parse next type/name: expected " <type> , <name> :" */
|
||||
/* get type */
|
||||
type = format_get_next_token(&cur);
|
||||
if (type == NULL) break;
|
||||
/* get comma */
|
||||
sep = format_get_next_token(&cur);
|
||||
if (sep == NULL || strcmp(sep, ",") != 0) goto error;
|
||||
free(sep);
|
||||
/* get name */
|
||||
name = format_get_next_token(&cur);
|
||||
if (name == NULL) goto error;
|
||||
/* if there is a next token it has to be : */
|
||||
sep = format_get_next_token(&cur);
|
||||
if (sep != NULL && strcmp(sep, ":") != 0) goto error;
|
||||
free(sep);
|
||||
|
||||
/* add type/name */
|
||||
if (id->asize % 64 == 0) {
|
||||
id->arg_type = realloc(id->arg_type, (id->asize + 64) * sizeof(char *));
|
||||
if (id->arg_type == NULL) abort();
|
||||
id->arg_name = realloc(id->arg_name, (id->asize + 64) * sizeof(char *));
|
||||
if (id->arg_name == NULL) abort();
|
||||
}
|
||||
id->arg_type[id->asize] = type;
|
||||
id->arg_name[id->asize] = name;
|
||||
id->asize++;
|
||||
}
|
||||
return;
|
||||
|
||||
error:
|
||||
printf("bad format '%s'\n", format);
|
||||
abort();
|
||||
}
|
||||
|
||||
void *parse_database(char *filename)
|
||||
{
|
||||
FILE *in;
|
||||
parser p;
|
||||
database *r;
|
||||
char *name, *value;
|
||||
id *last_id = NULL;
|
||||
int i;
|
||||
|
||||
r = calloc(1, sizeof(*r)); if (r == NULL) abort();
|
||||
memset(&p, 0, sizeof(p));
|
||||
|
||||
r->name = strdup(filename); if (r->name == NULL) abort();
|
||||
|
||||
in = fopen(filename, "r"); if (in == NULL) { perror(filename); abort(); }
|
||||
|
||||
i = 0;
|
||||
|
||||
while (1) {
|
||||
get_line(&p, in, &name, &value);
|
||||
if (name == NULL) break;
|
||||
//printf("%s %s\n", name, value);
|
||||
if (!strcmp(name, "ID")) { last_id = add_id(r, value, i); i++; }
|
||||
if (!strcmp(name, "GROUP")) add_groups(r, last_id, value);
|
||||
if (!strcmp(name, "DESC")) add_desc(last_id, value);
|
||||
if (!strcmp(name, "FORMAT")) add_format(last_id, value);
|
||||
}
|
||||
|
||||
fclose(in);
|
||||
free(p.name.data);
|
||||
free(p.value.data);
|
||||
|
||||
/* setup id_to_pos */
|
||||
r->id_to_pos = malloc(sizeof(int) * r->isize);
|
||||
if (r->id_to_pos == NULL) abort();
|
||||
for (i = 0; i < r->isize; i++)
|
||||
r->id_to_pos[r->i[i].id] = i;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
void dump_database(void *_d)
|
||||
{
|
||||
database *d = _d;
|
||||
int i;
|
||||
|
||||
printf("database %s: %d IDs, %d GROUPs\n", d->name, d->isize, d->gsize);
|
||||
for (i = 0; i < d->isize; i++) {
|
||||
int j;
|
||||
printf("ID %s [%s] [in %d group%s]\n",
|
||||
d->i[i].name, d->i[i].desc ? d->i[i].desc : "",
|
||||
d->i[i].gsize, d->i[i].gsize > 1 ? "s" : "");
|
||||
for (j = 0; j < d->i[i].gsize; j++)
|
||||
printf(" in GROUP: %s\n", d->i[i].groups[j]);
|
||||
if (d->i[i].asize == 0) printf(" no FORMAT\n");
|
||||
else {
|
||||
int j;
|
||||
printf(" FORMAT: ");
|
||||
for (j = 0; j < d->i[i].asize; j++)
|
||||
printf("'%s' , '%s' %s", d->i[i].arg_type[j], d->i[i].arg_name[j],
|
||||
j == d->i[i].asize-1 ? "" : " : ");
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
for (i = 0; i < d->gsize; i++) {
|
||||
int j;
|
||||
printf("GROUP %s [size %d]\n", d->g[i].name, d->g[i].size);
|
||||
for (j = 0; j < d->g[i].size; j++)
|
||||
printf(" contains ID: %s\n", d->g[i].ids[j]);
|
||||
}
|
||||
}
|
||||
|
||||
void list_ids(void *_d)
|
||||
{
|
||||
database *d = _d;
|
||||
int i;
|
||||
for (i = 0; i < d->isize; i++) printf("%s\n", d->i[i].name);
|
||||
}
|
||||
|
||||
void list_groups(void *_d)
|
||||
{
|
||||
database *d = _d;
|
||||
int i;
|
||||
for (i = 0; i < d->gsize; i++) printf("%s\n", d->g[i].name);
|
||||
}
|
||||
|
||||
static int onoff_id(database *d, char *name, int *a, int onoff)
|
||||
{
|
||||
id *i;
|
||||
i = bsearch(&(id){name:name}, d->i, d->isize, sizeof(id), id_cmp);
|
||||
if (i == NULL) return 0;
|
||||
a[i->id] = onoff;
|
||||
printf("turning %s %s\n", onoff ? "ON" : "OFF", name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int onoff_group(database *d, char *name, int *a, int onoff)
|
||||
{
|
||||
group *g;
|
||||
int i;
|
||||
g = bsearch(&(group){name:name}, d->g, d->gsize, sizeof(group), group_cmp);
|
||||
if (g == NULL) return 0;
|
||||
for (i = 0; i < g->size; i++) onoff_id(d, g->ids[i], a, onoff);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void on_off(void *_d, char *item, int *a, int onoff)
|
||||
{
|
||||
int done;
|
||||
database *d = _d;
|
||||
int i;
|
||||
if (item == NULL) {
|
||||
for (i = 0; i < d->isize; i++) a[i] = onoff;
|
||||
printf("turning %s all traces\n", onoff ? "ON" : "OFF");
|
||||
return;
|
||||
}
|
||||
done = onoff_group(d, item, a, onoff);
|
||||
done += onoff_id(d, item, a, onoff);
|
||||
if (done == 0) {
|
||||
printf("ERROR: ID/group '%s' not found in database\n", item);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
char *event_name_from_id(void *_database, int id)
|
||||
{
|
||||
database *d = _database;
|
||||
return d->i[d->id_to_pos[id]].name;
|
||||
}
|
||||
|
||||
int event_id_from_name(void *_database, char *name)
|
||||
{
|
||||
database *d = _database;
|
||||
id *i = (id*)bsearch(&(id){name:name}, d->i, d->isize, sizeof(id), id_cmp);
|
||||
if (i == NULL)
|
||||
{ printf("%s:%d: '%s' not found\n", __FILE__, __LINE__, name); abort(); }
|
||||
return i->id;
|
||||
}
|
||||
|
||||
database_event_format get_format(void *_database, int event_id)
|
||||
{
|
||||
database *d = _database;
|
||||
database_event_format ret;
|
||||
|
||||
if (event_id < 0 || event_id >= d->isize) {
|
||||
printf("%s:%d: bad event ID (%d)\n", __FILE__, __LINE__, event_id);
|
||||
abort();
|
||||
}
|
||||
|
||||
ret.type = d->i[d->id_to_pos[event_id]].arg_type;
|
||||
ret.name = d->i[d->id_to_pos[event_id]].arg_name;
|
||||
ret.count = d->i[d->id_to_pos[event_id]].asize;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int number_of_ids(void *_d)
|
||||
{
|
||||
database *d = _d;
|
||||
return d->isize;
|
||||
}
|
||||
|
||||
int database_get_ids(void *_d, char ***ids)
|
||||
{
|
||||
database *d = _d;
|
||||
int i;
|
||||
*ids = malloc(d->isize * sizeof(char **)); if (*ids == NULL) abort();
|
||||
for (i = 0; i < d->isize; i++) (*ids)[i] = d->i[i].name;
|
||||
return d->isize;
|
||||
}
|
||||
|
||||
int database_get_groups(void *_d, char ***groups)
|
||||
{
|
||||
database *d = _d;
|
||||
int i;
|
||||
*groups = malloc(d->gsize * sizeof(char **)); if (*groups == NULL) abort();
|
||||
for (i = 0; i < d->gsize; i++) (*groups)[i] = d->g[i].name;
|
||||
return d->gsize;
|
||||
}
|
||||
|
||||
int database_pos_to_id(void *_d, int pos)
|
||||
{
|
||||
database *d = _d;
|
||||
return d->i[pos].id;
|
||||
}
|
||||
|
||||
void database_get_generic_description(void *_d, int id,
|
||||
char **name, char **desc)
|
||||
{
|
||||
database *d = _d;
|
||||
int pos = d->id_to_pos[id];
|
||||
OBUF o;
|
||||
int i;
|
||||
*name = strdup(d->i[pos].name); if (*name == NULL) abort();
|
||||
o.osize = o.omaxsize = 0;
|
||||
o.obuf = NULL;
|
||||
PUTS(&o, *name);
|
||||
for (i = 0; i < d->i[pos].asize; i++) {
|
||||
PUTC(&o, ' ');
|
||||
PUTS(&o, d->i[pos].arg_name[i]);
|
||||
PUTS(&o, " [");
|
||||
PUTS(&o, d->i[pos].arg_name[i]);
|
||||
PUTS(&o, "]");
|
||||
}
|
||||
PUTC(&o, 0);
|
||||
*desc = o.obuf;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
#ifndef _DATABASE_H_
|
||||
#define _DATABASE_H_
|
||||
|
||||
/* returns an opaque pointer - truly a 'database *', see database.c */
|
||||
void *parse_database(char *filename);
|
||||
void dump_database(void *database);
|
||||
void list_ids(void *database);
|
||||
void list_groups(void *database);
|
||||
void on_off(void *d, char *item, int *a, int onoff);
|
||||
char *event_name_from_id(void *database, int id);
|
||||
int event_id_from_name(void *database, char *name);
|
||||
int number_of_ids(void *database);
|
||||
int database_get_ids(void *database, char ***ids);
|
||||
int database_get_groups(void *database, char ***groups);
|
||||
int database_pos_to_id(void *database, int pos);
|
||||
void database_get_generic_description(void *database, int id,
|
||||
char **name, char **desc);
|
||||
|
||||
/****************************************************************************/
|
||||
/* get format of an event */
|
||||
/****************************************************************************/
|
||||
|
||||
typedef struct {
|
||||
char **type;
|
||||
char **name;
|
||||
int count;
|
||||
} database_event_format;
|
||||
|
||||
database_event_format get_format(void *database, int event_id);
|
||||
|
||||
#endif /* _DATABASE_H_ */
|
||||
@@ -0,0 +1,24 @@
|
||||
#ifndef _TRACER_DEFS_H_
|
||||
#define _TRACER_DEFS_H_
|
||||
|
||||
/* types of plots */
|
||||
#define PLOT_VS_TIME 0
|
||||
#define PLOT_IQ_POINTS 1
|
||||
#define PLOT_MINMAX 2
|
||||
|
||||
void new_thread(void *(*f)(void *), void *data);
|
||||
|
||||
/* ... is { int count; int type; char *color; } for 'nplots' plots */
|
||||
void *make_plot(int width, int height, char *title, int nplots, ...);
|
||||
void plot_set(void *plot, float *data, int len, int pos, int pp);
|
||||
void iq_plot_set(void *plot, short *data, int len, int pos, int pp);
|
||||
void iq_plot_set_sized(void *_plot, short *data, int len, int pp);
|
||||
void iq_plot_add_iq_point_loop(void *_plot, short i, short q, int pp);
|
||||
void iq_plot_add_energy_point_loop(void *_plot, int e, int pp);
|
||||
|
||||
/* T gui functions */
|
||||
void t_gui_start(void);
|
||||
void t_gui_set_input_signal(int eNB, int frame, int subframe, int antenna,
|
||||
int size, void *buf);
|
||||
|
||||
#endif /* _TRACER_DEFS_H_ */
|
||||
@@ -0,0 +1,574 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include "database.h"
|
||||
#include "event.h"
|
||||
#include "handler.h"
|
||||
#include "logger/logger.h"
|
||||
#include "view/view.h"
|
||||
#include "gui/gui.h"
|
||||
#include "filter/filter.h"
|
||||
#include "utils.h"
|
||||
#include "../T_defs.h"
|
||||
#include "event_selector.h"
|
||||
#include "openair_logo.h"
|
||||
#include "config.h"
|
||||
|
||||
typedef struct {
|
||||
view *phyview;
|
||||
view *macview;
|
||||
view *rlcview;
|
||||
view *pdcpview;
|
||||
view *rrcview;
|
||||
view *legacy;
|
||||
} enb_gui;
|
||||
|
||||
typedef struct {
|
||||
int socket;
|
||||
int *is_on;
|
||||
int nevents;
|
||||
pthread_mutex_t lock;
|
||||
} enb_data;
|
||||
|
||||
#define DEFAULT_REMOTE_IP "127.0.0.1"
|
||||
#define DEFAULT_REMOTE_PORT 2021
|
||||
|
||||
void is_on_changed(void *_d)
|
||||
{
|
||||
enb_data *d = _d;
|
||||
char t;
|
||||
|
||||
if (pthread_mutex_lock(&d->lock)) abort();
|
||||
|
||||
if (d->socket == -1) goto no_connection;
|
||||
|
||||
t = 1;
|
||||
if (socket_send(d->socket, &t, 1) == -1 ||
|
||||
socket_send(d->socket, &d->nevents, sizeof(int)) == -1 ||
|
||||
socket_send(d->socket, d->is_on, d->nevents * sizeof(int)) == -1)
|
||||
goto connection_dies;
|
||||
|
||||
no_connection:
|
||||
if (pthread_mutex_unlock(&d->lock)) abort();
|
||||
return;
|
||||
|
||||
connection_dies:
|
||||
close(d->socket);
|
||||
d->socket = -1;
|
||||
if (pthread_mutex_unlock(&d->lock)) abort();
|
||||
}
|
||||
|
||||
void usage(void)
|
||||
{
|
||||
printf(
|
||||
"options:\n"
|
||||
" -d <database file> this option is mandatory\n"
|
||||
" -on <GROUP or ID> turn log ON for given GROUP or ID\n"
|
||||
" -off <GROUP or ID> turn log OFF for given GROUP or ID\n"
|
||||
" -ON turn all logs ON\n"
|
||||
" -OFF turn all logs OFF\n"
|
||||
" note: you may pass several -on/-off/-ON/-OFF,\n"
|
||||
" they will be processed in order\n"
|
||||
" by default, all is off\n"
|
||||
" -ip <host> connect to given IP address (default %s)\n"
|
||||
" -p <port> connect to given port (default %d)\n"
|
||||
" -debug-gui activate GUI debug logs\n",
|
||||
DEFAULT_REMOTE_IP,
|
||||
DEFAULT_REMOTE_PORT
|
||||
);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static void *gui_thread(void *_g)
|
||||
{
|
||||
gui *g = _g;
|
||||
gui_loop(g);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static filter *ticktime_filter(void *database, char *event, int i)
|
||||
{
|
||||
/* filter is "harq_pid == i && UE_id == 0 && eNB_id == 0" */
|
||||
return
|
||||
filter_and(
|
||||
filter_eq(filter_evarg(database, event, "harq_pid"), filter_int(i)),
|
||||
filter_and(
|
||||
filter_eq(filter_evarg(database, event, "UE_id"), filter_int(0)),
|
||||
filter_eq(filter_evarg(database, event, "eNB_ID"), filter_int(0))));
|
||||
}
|
||||
|
||||
static void enb_main_gui(enb_gui *e, gui *g, event_handler *h, void *database)
|
||||
{
|
||||
widget *main_window;
|
||||
widget *top_container;
|
||||
widget *line, *col;
|
||||
widget *logo;
|
||||
widget *input_signal_plot;
|
||||
logger *input_signal_log;
|
||||
view *input_signal_view;
|
||||
widget *timeline_plot;
|
||||
logger *timelog;
|
||||
view *timeview;
|
||||
view *subview;
|
||||
widget *text;
|
||||
view *textview;
|
||||
int i;
|
||||
|
||||
main_window = new_toplevel_window(g, 800, 600, "eNB tracer");
|
||||
top_container = new_container(g, VERTICAL);
|
||||
widget_add_child(g, main_window, top_container, -1);
|
||||
|
||||
line = new_container(g, HORIZONTAL);
|
||||
widget_add_child(g, top_container, line, -1);
|
||||
logo = new_image(g, openair_logo_png, openair_logo_png_len);
|
||||
widget_add_child(g, line, logo, -1);
|
||||
input_signal_plot = new_xy_plot(g, 256, 55, "input signal", 20);
|
||||
widget_add_child(g, line, input_signal_plot, -1);
|
||||
xy_plot_set_range(g, input_signal_plot, 0, 7680*10, 20, 70);
|
||||
input_signal_log = new_framelog(h, database,
|
||||
"ENB_PHY_INPUT_SIGNAL", "subframe", "rxdata");
|
||||
/* a skip value of 10 means to process 1 frame over 10, that is
|
||||
* more or less 10 frames per second
|
||||
*/
|
||||
framelog_set_skip(input_signal_log, 10);
|
||||
input_signal_view = new_view_xy(7680*10, 10,
|
||||
g, input_signal_plot, new_color(g, "#0c0c72"));
|
||||
logger_add_view(input_signal_log, input_signal_view);
|
||||
|
||||
/* downlink/uplink UE DCIs */
|
||||
widget_add_child(g, top_container,
|
||||
new_label(g,"DL/UL TICK/DCI/ACK/NACK "), -1);
|
||||
line = new_container(g, HORIZONTAL);
|
||||
widget_add_child(g, top_container, line, -1);
|
||||
timeline_plot = new_timeline(g, 512, 8, 5);
|
||||
widget_add_child(g, line, timeline_plot, -1);
|
||||
container_set_child_growable(g, line, timeline_plot, 1);
|
||||
for (i = 0; i < 8; i++)
|
||||
timeline_set_subline_background_color(g, timeline_plot, i,
|
||||
new_color(g, i==0 || i==4 ? "#aaf" : "#eee"));
|
||||
timeview = new_view_time(3600, 10, g, timeline_plot);
|
||||
/* DL tick logging */
|
||||
timelog = new_timelog(h, database, "ENB_PHY_DL_TICK");
|
||||
subview = new_subview_time(timeview, 0, new_color(g, "#77c"), 3600*1000);
|
||||
logger_add_view(timelog, subview);
|
||||
/* DL DCI logging */
|
||||
timelog = new_timelog(h, database, "ENB_PHY_DLSCH_UE_DCI");
|
||||
subview = new_subview_time(timeview, 1, new_color(g, "#228"), 3600*1000);
|
||||
logger_add_view(timelog, subview);
|
||||
/* DL ACK */
|
||||
timelog = new_timelog(h, database, "ENB_PHY_DLSCH_UE_ACK");
|
||||
subview = new_subview_time(timeview, 2, new_color(g, "#282"), 3600*1000);
|
||||
logger_add_view(timelog, subview);
|
||||
/* DL NACK */
|
||||
timelog = new_timelog(h, database, "ENB_PHY_DLSCH_UE_NACK");
|
||||
subview = new_subview_time(timeview, 3, new_color(g, "#f22"), 3600*1000);
|
||||
logger_add_view(timelog, subview);
|
||||
|
||||
/* UL tick logging */
|
||||
timelog = new_timelog(h, database, "ENB_PHY_UL_TICK");
|
||||
subview = new_subview_time(timeview, 4, new_color(g, "#77c"), 3600*1000);
|
||||
logger_add_view(timelog, subview);
|
||||
/* UL DCI logging */
|
||||
timelog = new_timelog(h, database, "ENB_PHY_ULSCH_UE_DCI");
|
||||
subview = new_subview_time(timeview, 5, new_color(g, "#228"), 3600*1000);
|
||||
logger_add_view(timelog, subview);
|
||||
/* UL retransmission without DCI logging */
|
||||
timelog = new_timelog(h,database,"ENB_PHY_ULSCH_UE_NO_DCI_RETRANSMISSION");
|
||||
subview = new_subview_time(timeview, 5, new_color(g, "#f22"), 3600*1000);
|
||||
logger_add_view(timelog, subview);
|
||||
/* UL ACK */
|
||||
timelog = new_timelog(h, database, "ENB_PHY_ULSCH_UE_ACK");
|
||||
subview = new_subview_time(timeview, 6, new_color(g, "#282"), 3600*1000);
|
||||
logger_add_view(timelog, subview);
|
||||
/* UL NACK */
|
||||
timelog = new_timelog(h, database, "ENB_PHY_ULSCH_UE_NACK");
|
||||
subview = new_subview_time(timeview, 7, new_color(g, "#f22"), 3600*1000);
|
||||
logger_add_view(timelog, subview);
|
||||
|
||||
/* harq processes' ticktime view */
|
||||
widget_add_child(g, top_container,
|
||||
new_label(g,"DL/UL HARQ (x8) "), -1);
|
||||
line = new_container(g, HORIZONTAL);
|
||||
widget_add_child(g, top_container, line, -1);
|
||||
timeline_plot = new_timeline(g, 512, 2*8+2, 3);
|
||||
widget_add_child(g, line, timeline_plot, -1);
|
||||
container_set_child_growable(g, line, timeline_plot, 1);
|
||||
for (i = 0; i < 2*8+2; i++)
|
||||
timeline_set_subline_background_color(g, timeline_plot, i,
|
||||
new_color(g, i==0 || i==9 ? "#ddd" : (i%9)&1 ? "#e6e6e6" : "#eee"));
|
||||
timeview = new_view_ticktime(10, g, timeline_plot);
|
||||
ticktime_set_tick(timeview,
|
||||
new_ticklog(h, database, "ENB_MASTER_TICK", "frame", "subframe"));
|
||||
/* tick */
|
||||
timelog = new_ticklog(h, database, "ENB_MASTER_TICK", "frame", "subframe");
|
||||
/* tick on DL view */
|
||||
subview = new_subview_ticktime(timeview, 0, new_color(g,"#bbb"), 3600*1000);
|
||||
logger_add_view(timelog, subview);
|
||||
/* tick on UL view */
|
||||
subview = new_subview_ticktime(timeview, 9, new_color(g,"#bbb"), 3600*1000);
|
||||
logger_add_view(timelog, subview);
|
||||
/* DL harq pids */
|
||||
for (i = 0; i < 8; i++) {
|
||||
timelog = new_ticklog(h, database, "ENB_PHY_DLSCH_UE_DCI",
|
||||
"frame", "subframe");
|
||||
subview = new_subview_ticktime(timeview, i+1,
|
||||
new_color(g,"#55f"), 3600*1000);
|
||||
logger_add_view(timelog, subview);
|
||||
logger_set_filter(timelog,
|
||||
ticktime_filter(database, "ENB_PHY_DLSCH_UE_DCI", i));
|
||||
}
|
||||
/* DL ACK */
|
||||
for (i = 0; i < 8; i++) {
|
||||
timelog = new_ticklog(h, database, "ENB_PHY_DLSCH_UE_ACK",
|
||||
"frame", "subframe");
|
||||
subview = new_subview_ticktime(timeview, i+1,
|
||||
new_color(g,"#282"), 3600*1000);
|
||||
logger_add_view(timelog, subview);
|
||||
logger_set_filter(timelog,
|
||||
ticktime_filter(database, "ENB_PHY_DLSCH_UE_ACK", i));
|
||||
}
|
||||
/* DL NACK */
|
||||
for (i = 0; i < 8; i++) {
|
||||
timelog = new_ticklog(h, database, "ENB_PHY_DLSCH_UE_NACK",
|
||||
"frame", "subframe");
|
||||
subview = new_subview_ticktime(timeview, i+1,
|
||||
new_color(g,"#f22"), 3600*1000);
|
||||
logger_add_view(timelog, subview);
|
||||
logger_set_filter(timelog,
|
||||
ticktime_filter(database, "ENB_PHY_DLSCH_UE_NACK", i));
|
||||
}
|
||||
/* UL harq pids */
|
||||
for (i = 0; i < 8; i++) {
|
||||
/* first transmission */
|
||||
timelog = new_ticklog(h, database, "ENB_PHY_ULSCH_UE_DCI",
|
||||
"frame", "subframe");
|
||||
subview = new_subview_ticktime(timeview, i+9+1,
|
||||
new_color(g,"#55f"), 3600*1000);
|
||||
logger_add_view(timelog, subview);
|
||||
logger_set_filter(timelog,
|
||||
ticktime_filter(database, "ENB_PHY_ULSCH_UE_DCI", i));
|
||||
/* retransmission */
|
||||
timelog = new_ticklog(h, database,
|
||||
"ENB_PHY_ULSCH_UE_NO_DCI_RETRANSMISSION", "frame", "subframe");
|
||||
subview = new_subview_ticktime(timeview, i+9+1,
|
||||
new_color(g,"#99f"), 3600*1000);
|
||||
logger_add_view(timelog, subview);
|
||||
logger_set_filter(timelog,
|
||||
ticktime_filter(database,
|
||||
"ENB_PHY_ULSCH_UE_NO_DCI_RETRANSMISSION", i));
|
||||
}
|
||||
/* UL ACK */
|
||||
for (i = 0; i < 8; i++) {
|
||||
timelog = new_ticklog(h, database, "ENB_PHY_ULSCH_UE_ACK",
|
||||
"frame", "subframe");
|
||||
subview = new_subview_ticktime(timeview, i+9+1,
|
||||
new_color(g,"#282"), 3600*1000);
|
||||
logger_add_view(timelog, subview);
|
||||
logger_set_filter(timelog,
|
||||
ticktime_filter(database, "ENB_PHY_ULSCH_UE_ACK", i));
|
||||
}
|
||||
/* UL NACK */
|
||||
for (i = 0; i < 8; i++) {
|
||||
timelog = new_ticklog(h, database, "ENB_PHY_ULSCH_UE_NACK",
|
||||
"frame", "subframe");
|
||||
subview = new_subview_ticktime(timeview, i+9+1,
|
||||
new_color(g,"#f22"), 3600*1000);
|
||||
logger_add_view(timelog, subview);
|
||||
logger_set_filter(timelog,
|
||||
ticktime_filter(database, "ENB_PHY_ULSCH_UE_NACK", i));
|
||||
}
|
||||
|
||||
/* phy/mac/rlc/pdcp/rrc textlog */
|
||||
line = new_container(g, HORIZONTAL);
|
||||
widget_add_child(g, top_container, line, -1);
|
||||
container_set_child_growable(g, top_container, line, 1);
|
||||
|
||||
/* phy */
|
||||
col = new_container(g, VERTICAL);
|
||||
widget_add_child(g, line, col, -1);
|
||||
container_set_child_growable(g, line, col, 1);
|
||||
widget_add_child(g, col, new_label(g, "PHY"), -1);
|
||||
text = new_textlist(g, 100, 10, new_color(g, "#afa"));
|
||||
widget_add_child(g, col, text, -1);
|
||||
container_set_child_growable(g, col, text, 1);
|
||||
textview = new_view_textlist(10000, 10, g, text);
|
||||
e->phyview = textview;
|
||||
|
||||
/* mac */
|
||||
col = new_container(g, VERTICAL);
|
||||
widget_add_child(g, line, col, -1);
|
||||
container_set_child_growable(g, line, col, 1);
|
||||
widget_add_child(g, col, new_label(g, "MAC"), -1);
|
||||
text = new_textlist(g, 100, 10, new_color(g, "#adf"));
|
||||
widget_add_child(g, col, text, -1);
|
||||
container_set_child_growable(g, col, text, 1);
|
||||
textview = new_view_textlist(10000, 10, g, text);
|
||||
e->macview = textview;
|
||||
|
||||
line = new_container(g, HORIZONTAL);
|
||||
widget_add_child(g, top_container, line, -1);
|
||||
container_set_child_growable(g, top_container, line, 1);
|
||||
|
||||
/* rlc */
|
||||
col = new_container(g, VERTICAL);
|
||||
widget_add_child(g, line, col, -1);
|
||||
container_set_child_growable(g, line, col, 1);
|
||||
widget_add_child(g, col, new_label(g, "RLC"), -1);
|
||||
text = new_textlist(g, 100, 10, new_color(g, "#aff"));
|
||||
widget_add_child(g, col, text, -1);
|
||||
container_set_child_growable(g, col, text, 1);
|
||||
textview = new_view_textlist(10000, 10, g, text);
|
||||
e->rlcview = textview;
|
||||
|
||||
/* pdcp */
|
||||
col = new_container(g, VERTICAL);
|
||||
widget_add_child(g, line, col, -1);
|
||||
container_set_child_growable(g, line, col, 1);
|
||||
widget_add_child(g, col, new_label(g, "PDCP"), -1);
|
||||
text = new_textlist(g, 100, 10, new_color(g, "#ed9"));
|
||||
widget_add_child(g, col, text, -1);
|
||||
container_set_child_growable(g, col, text, 1);
|
||||
textview = new_view_textlist(10000, 10, g, text);
|
||||
e->pdcpview = textview;
|
||||
|
||||
line = new_container(g, HORIZONTAL);
|
||||
widget_add_child(g, top_container, line, -1);
|
||||
container_set_child_growable(g, top_container, line, 1);
|
||||
|
||||
/* rrc */
|
||||
col = new_container(g, VERTICAL);
|
||||
widget_add_child(g, line, col, -1);
|
||||
container_set_child_growable(g, line, col, 1);
|
||||
widget_add_child(g, col, new_label(g, "RRC"), -1);
|
||||
text = new_textlist(g, 100, 10, new_color(g, "#fdb"));
|
||||
widget_add_child(g, col, text, -1);
|
||||
container_set_child_growable(g, col, text, 1);
|
||||
textview = new_view_textlist(10000, 10, g, text);
|
||||
e->rrcview = textview;
|
||||
|
||||
/* legacy logs (LOG_I, LOG_D, ...) */
|
||||
widget_add_child(g, top_container, new_label(g, "LEGACY"), -1);
|
||||
text = new_textlist(g, 100, 10, new_color(g, "#eeb"));
|
||||
widget_add_child(g, top_container, text, -1);
|
||||
container_set_child_growable(g, top_container, text, 1);
|
||||
e->legacy = new_view_textlist(10000, 10, g, text);
|
||||
}
|
||||
|
||||
void view_add_log(view *v, char *log, event_handler *h, void *database,
|
||||
int *is_on)
|
||||
{
|
||||
logger *textlog;
|
||||
char *name, *desc;
|
||||
|
||||
database_get_generic_description(database,
|
||||
event_id_from_name(database, log), &name, &desc);
|
||||
textlog = new_textlog(h, database, name, desc);
|
||||
logger_add_view(textlog, v);
|
||||
free(name);
|
||||
free(desc);
|
||||
|
||||
on_off(database, log, is_on, 1);
|
||||
}
|
||||
|
||||
int main(int n, char **v)
|
||||
{
|
||||
extern int volatile gui_logd;
|
||||
char *database_filename = NULL;
|
||||
void *database;
|
||||
char *ip = DEFAULT_REMOTE_IP;
|
||||
int port = DEFAULT_REMOTE_PORT;
|
||||
char **on_off_name;
|
||||
int *on_off_action;
|
||||
int on_off_n = 0;
|
||||
int *is_on;
|
||||
int number_of_events;
|
||||
int i;
|
||||
event_handler *h;
|
||||
gui *g;
|
||||
enb_gui eg;
|
||||
enb_data enb_data;
|
||||
|
||||
/* write on a socket fails if the other end is closed and we get SIGPIPE */
|
||||
if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) abort();
|
||||
|
||||
on_off_name = malloc(n * sizeof(char *)); if (on_off_name == NULL) abort();
|
||||
on_off_action = malloc(n * sizeof(int)); if (on_off_action == NULL) abort();
|
||||
|
||||
for (i = 1; i < n; i++) {
|
||||
if (!strcmp(v[i], "-h") || !strcmp(v[i], "--help")) usage();
|
||||
if (!strcmp(v[i], "-d"))
|
||||
{ if (i > n-2) usage(); database_filename = v[++i]; continue; }
|
||||
if (!strcmp(v[i], "-ip")) { if (i > n-2) usage(); ip = v[++i]; continue; }
|
||||
if (!strcmp(v[i], "-p"))
|
||||
{ if (i > n-2) usage(); port = atoi(v[++i]); continue; }
|
||||
if (!strcmp(v[i], "-on")) { if (i > n-2) usage();
|
||||
on_off_name[on_off_n]=v[++i]; on_off_action[on_off_n++]=1; continue; }
|
||||
if (!strcmp(v[i], "-off")) { if (i > n-2) usage();
|
||||
on_off_name[on_off_n]=v[++i]; on_off_action[on_off_n++]=0; continue; }
|
||||
if (!strcmp(v[i], "-ON"))
|
||||
{ on_off_name[on_off_n]=NULL; on_off_action[on_off_n++]=1; continue; }
|
||||
if (!strcmp(v[i], "-OFF"))
|
||||
{ on_off_name[on_off_n]=NULL; on_off_action[on_off_n++]=0; continue; }
|
||||
if (!strcmp(v[i], "-debug-gui")) { gui_logd = 1; continue; }
|
||||
usage();
|
||||
}
|
||||
|
||||
if (database_filename == NULL) {
|
||||
printf("ERROR: provide a database file (-d)\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
database = parse_database(database_filename);
|
||||
|
||||
load_config_file(database_filename);
|
||||
|
||||
number_of_events = number_of_ids(database);
|
||||
is_on = calloc(number_of_events, sizeof(int));
|
||||
if (is_on == NULL) abort();
|
||||
|
||||
h = new_handler(database);
|
||||
|
||||
g = gui_init();
|
||||
new_thread(gui_thread, g);
|
||||
|
||||
enb_main_gui(&eg, g, h, database);
|
||||
|
||||
for (i = 0; i < number_of_events; i++) {
|
||||
logger *textlog;
|
||||
char *name, *desc;
|
||||
database_get_generic_description(database, i, &name, &desc);
|
||||
if (strncmp(name, "LEGACY_", 7) != 0) continue;
|
||||
textlog = new_textlog(h, database, name, desc);
|
||||
logger_add_view(textlog, eg.legacy);
|
||||
free(name);
|
||||
free(desc);
|
||||
}
|
||||
|
||||
on_off(database, "ENB_PHY_INPUT_SIGNAL", is_on, 1);
|
||||
on_off(database, "ENB_PHY_DL_TICK", is_on, 1);
|
||||
on_off(database, "ENB_PHY_DLSCH_UE_DCI", is_on, 1);
|
||||
on_off(database, "ENB_PHY_DLSCH_UE_ACK", is_on, 1);
|
||||
on_off(database, "ENB_PHY_DLSCH_UE_NACK", is_on, 1);
|
||||
on_off(database, "ENB_PHY_UL_TICK", is_on, 1);
|
||||
on_off(database, "ENB_PHY_ULSCH_UE_DCI", is_on, 1);
|
||||
on_off(database, "ENB_PHY_ULSCH_UE_NO_DCI_RETRANSMISSION", is_on, 1);
|
||||
on_off(database, "ENB_PHY_ULSCH_UE_ACK", is_on, 1);
|
||||
on_off(database, "ENB_PHY_ULSCH_UE_NACK", is_on, 1);
|
||||
on_off(database, "ENB_MASTER_TICK", is_on, 1);
|
||||
|
||||
on_off(database, "LEGACY_RRC_INFO", is_on, 1);
|
||||
on_off(database, "LEGACY_RRC_ERROR", is_on, 1);
|
||||
on_off(database, "LEGACY_RRC_WARNING", is_on, 1);
|
||||
|
||||
view_add_log(eg.phyview, "ENB_PHY_DLSCH_UE_DCI", h, database, is_on);
|
||||
view_add_log(eg.phyview, "ENB_PHY_DLSCH_UE_ACK", h, database, is_on);
|
||||
view_add_log(eg.phyview, "ENB_PHY_DLSCH_UE_NACK", h, database, is_on);
|
||||
view_add_log(eg.phyview, "ENB_PHY_ULSCH_UE_DCI", h, database, is_on);
|
||||
view_add_log(eg.phyview, "ENB_PHY_ULSCH_UE_NO_DCI_RETRANSMISSION",
|
||||
h, database, is_on);
|
||||
view_add_log(eg.phyview, "ENB_PHY_ULSCH_UE_ACK", h, database, is_on);
|
||||
view_add_log(eg.phyview, "ENB_PHY_ULSCH_UE_NACK", h, database, is_on);
|
||||
|
||||
view_add_log(eg.macview, "ENB_MAC_UE_DL_SDU", h, database, is_on);
|
||||
view_add_log(eg.macview, "ENB_MAC_UE_UL_SCHEDULE", h, database, is_on);
|
||||
view_add_log(eg.macview, "ENB_MAC_UE_UL_SCHEDULE_RETRANSMISSION",
|
||||
h, database, is_on);
|
||||
view_add_log(eg.macview, "ENB_MAC_UE_UL_PDU", h, database, is_on);
|
||||
view_add_log(eg.macview, "ENB_MAC_UE_UL_SDU", h, database, is_on);
|
||||
view_add_log(eg.macview, "ENB_MAC_UE_UL_CE", h, database, is_on);
|
||||
|
||||
view_add_log(eg.rlcview, "ENB_RLC_DL", h, database, is_on);
|
||||
view_add_log(eg.rlcview, "ENB_RLC_UL", h, database, is_on);
|
||||
view_add_log(eg.rlcview, "ENB_RLC_MAC_DL", h, database, is_on);
|
||||
view_add_log(eg.rlcview, "ENB_RLC_MAC_UL", h, database, is_on);
|
||||
|
||||
view_add_log(eg.pdcpview, "ENB_PDCP_UL", h, database, is_on);
|
||||
view_add_log(eg.pdcpview, "ENB_PDCP_DL", h, database, is_on);
|
||||
|
||||
view_add_log(eg.rrcview, "ENB_RRC_CONNECTION_SETUP_COMPLETE",
|
||||
h, database, is_on);
|
||||
view_add_log(eg.rrcview, "ENB_RRC_SECURITY_MODE_COMMAND",
|
||||
h, database, is_on);
|
||||
view_add_log(eg.rrcview, "ENB_RRC_UE_CAPABILITY_ENQUIRY",
|
||||
h, database, is_on);
|
||||
view_add_log(eg.rrcview, "ENB_RRC_CONNECTION_REJECT",
|
||||
h, database, is_on);
|
||||
view_add_log(eg.rrcview, "ENB_RRC_CONNECTION_REESTABLISHMENT_REJECT",
|
||||
h, database, is_on);
|
||||
view_add_log(eg.rrcview, "ENB_RRC_CONNECTION_RELEASE",
|
||||
h, database, is_on);
|
||||
view_add_log(eg.rrcview, "ENB_RRC_CONNECTION_RECONFIGURATION",
|
||||
h, database, is_on);
|
||||
view_add_log(eg.rrcview, "ENB_RRC_MEASUREMENT_REPORT",
|
||||
h, database, is_on);
|
||||
view_add_log(eg.rrcview, "ENB_RRC_HANDOVER_PREPARATION_INFORMATION",
|
||||
h, database, is_on);
|
||||
view_add_log(eg.rrcview, "ENB_RRC_CONNECTION_RECONFIGURATION_COMPLETE",
|
||||
h, database, is_on);
|
||||
view_add_log(eg.rrcview, "ENB_RRC_CONNECTION_SETUP",
|
||||
h, database, is_on);
|
||||
view_add_log(eg.rrcview, "ENB_RRC_UL_CCCH_DATA_IN",
|
||||
h, database, is_on);
|
||||
view_add_log(eg.rrcview, "ENB_RRC_UL_DCCH_DATA_IN",
|
||||
h, database, is_on);
|
||||
view_add_log(eg.rrcview, "ENB_RRC_SECURITY_MODE_COMPLETE",
|
||||
h, database, is_on);
|
||||
view_add_log(eg.rrcview, "ENB_RRC_SECURITY_MODE_FAILURE",
|
||||
h, database, is_on);
|
||||
view_add_log(eg.rrcview, "ENB_RRC_UE_CAPABILITY_INFORMATION",
|
||||
h, database, is_on);
|
||||
view_add_log(eg.rrcview, "ENB_RRC_CONNECTION_REQUEST",
|
||||
h, database, is_on);
|
||||
view_add_log(eg.rrcview, "ENB_RRC_CONNECTION_REESTABLISHMENT_REQUEST",
|
||||
h, database, is_on);
|
||||
view_add_log(eg.rrcview, "ENB_RRC_CONNECTION_REESTABLISHMENT_COMPLETE",
|
||||
h, database, is_on);
|
||||
view_add_log(eg.rrcview, "ENB_RRC_UL_HANDOVER_PREPARATION_TRANSFER",
|
||||
h, database, is_on);
|
||||
view_add_log(eg.rrcview, "ENB_RRC_UL_INFORMATION_TRANSFER",
|
||||
h, database, is_on);
|
||||
view_add_log(eg.rrcview, "ENB_RRC_COUNTER_CHECK_RESPONSE",
|
||||
h, database, is_on);
|
||||
view_add_log(eg.rrcview, "ENB_RRC_UE_INFORMATION_RESPONSE_R9",
|
||||
h, database, is_on);
|
||||
view_add_log(eg.rrcview, "ENB_RRC_PROXIMITY_INDICATION_R9",
|
||||
h, database, is_on);
|
||||
view_add_log(eg.rrcview, "ENB_RRC_RECONFIGURATION_COMPLETE_R10",
|
||||
h, database, is_on);
|
||||
view_add_log(eg.rrcview, "ENB_RRC_MBMS_COUNTING_RESPONSE_R10",
|
||||
h, database, is_on);
|
||||
view_add_log(eg.rrcview, "ENB_RRC_INTER_FREQ_RSTD_MEASUREMENT_INDICATION",
|
||||
h, database, is_on);
|
||||
view_add_log(eg.rrcview, "ENB_RRC_UNKNOW_MESSAGE",
|
||||
h, database, is_on);
|
||||
|
||||
for (i = 0; i < on_off_n; i++)
|
||||
on_off(database, on_off_name[i], is_on, on_off_action[i]);
|
||||
|
||||
enb_data.socket = -1;
|
||||
enb_data.is_on = is_on;
|
||||
enb_data.nevents = number_of_events;
|
||||
if (pthread_mutex_init(&enb_data.lock, NULL)) abort();
|
||||
setup_event_selector(g, database, is_on, is_on_changed, &enb_data);
|
||||
|
||||
restart:
|
||||
clear_remote_config();
|
||||
enb_data.socket = connect_to(ip, port);
|
||||
|
||||
/* send the first message - activate selected traces */
|
||||
is_on_changed(&enb_data);
|
||||
|
||||
/* read messages */
|
||||
while (1) {
|
||||
char v[T_BUFFER_MAX];
|
||||
event e;
|
||||
e = get_event(enb_data.socket, v, database);
|
||||
if (e.type == -1) goto restart;
|
||||
handle_event(h, e);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
#include "event.h"
|
||||
#include "database.h"
|
||||
#include "utils.h"
|
||||
#include "config.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
event get_event(int socket, char *event_buffer, void *database)
|
||||
{
|
||||
#ifdef T_SEND_TIME
|
||||
struct timespec t;
|
||||
#endif
|
||||
int type;
|
||||
int32_t length;
|
||||
|
||||
/* Events type -1 and -2 are special: the tracee sends its version
|
||||
* of T_messages.txt using those events.
|
||||
* We have to check that the local version of T_messages.txt is identical
|
||||
* to the one the tracee uses. We don't report those events to the
|
||||
* application.
|
||||
*/
|
||||
|
||||
again:
|
||||
if (fullread(socket, &length, 4) == -1) goto read_error;
|
||||
#ifdef T_SEND_TIME
|
||||
if (fullread(socket, &t, sizeof(struct timespec)) == -1) goto read_error;
|
||||
length -= sizeof(struct timespec);
|
||||
#endif
|
||||
if (fullread(socket, &type, sizeof(int)) == -1) goto read_error;
|
||||
length -= sizeof(int);
|
||||
if (fullread(socket, event_buffer, length) == -1) goto read_error;
|
||||
|
||||
if (type == -1) append_received_config_chunk(event_buffer, length);
|
||||
if (type == -2) verify_config();
|
||||
|
||||
if (type == -1 || type == -2) goto again;
|
||||
|
||||
#ifdef T_SEND_TIME
|
||||
return new_event(t, type, length, event_buffer, database);
|
||||
#else
|
||||
return new_event(type, length, event_buffer, database);
|
||||
#endif
|
||||
|
||||
read_error:
|
||||
return (event){type: -1};
|
||||
}
|
||||
|
||||
#ifdef T_SEND_TIME
|
||||
event new_event(struct timespec sending_time, int type,
|
||||
int length, char *buffer, void *database)
|
||||
#else
|
||||
event new_event(int type, int length, char *buffer, void *database)
|
||||
#endif
|
||||
{
|
||||
database_event_format f;
|
||||
event e;
|
||||
int i;
|
||||
int offset;
|
||||
|
||||
#ifdef T_SEND_TIME
|
||||
e.sending_time = sending_time;
|
||||
#endif
|
||||
e.type = type;
|
||||
e.buffer = buffer;
|
||||
|
||||
f = get_format(database, type);
|
||||
|
||||
e.ecount = f.count;
|
||||
|
||||
offset = 0;
|
||||
|
||||
/* setup offsets */
|
||||
/* TODO: speedup (no strcmp, string event to include length at head) */
|
||||
for (i = 0; i < f.count; i++) {
|
||||
//e.e[i].offset = offset;
|
||||
if (!strcmp(f.type[i], "int")) {
|
||||
e.e[i].type = EVENT_INT;
|
||||
e.e[i].i = *(int *)(&buffer[offset]);
|
||||
offset += 4;
|
||||
} else if (!strcmp(f.type[i], "ulong")) {
|
||||
e.e[i].type = EVENT_ULONG;
|
||||
e.e[i].ul = *(unsigned long *)(&buffer[offset]);
|
||||
offset += sizeof(unsigned long);
|
||||
} else if (!strcmp(f.type[i], "string")) {
|
||||
e.e[i].type = EVENT_STRING;
|
||||
e.e[i].s = &buffer[offset];
|
||||
while (buffer[offset]) offset++;
|
||||
offset++;
|
||||
} else if (!strcmp(f.type[i], "buffer")) {
|
||||
int len;
|
||||
e.e[i].type = EVENT_BUFFER;
|
||||
len = *(int *)(&buffer[offset]);
|
||||
e.e[i].bsize = len;
|
||||
e.e[i].b = &buffer[offset+sizeof(int)];
|
||||
offset += len+sizeof(int);
|
||||
} else {
|
||||
printf("unhandled type '%s'\n", f.type[i]);
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
if (e.ecount==0) { printf("FORMAT not set in event %d\n", type); abort(); }
|
||||
|
||||
return e;
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
#ifndef _EVENT_H_
|
||||
#define _EVENT_H_
|
||||
|
||||
#include "../T_defs.h"
|
||||
#ifdef T_SEND_TIME
|
||||
#include <time.h>
|
||||
#endif
|
||||
|
||||
enum event_arg_type {
|
||||
EVENT_INT,
|
||||
EVENT_ULONG,
|
||||
EVENT_STRING,
|
||||
EVENT_BUFFER
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
enum event_arg_type type;
|
||||
//int offset;
|
||||
union {
|
||||
int i;
|
||||
unsigned long ul;
|
||||
char *s;
|
||||
struct {
|
||||
int bsize;
|
||||
void *b;
|
||||
};
|
||||
};
|
||||
} event_arg;
|
||||
|
||||
typedef struct {
|
||||
#ifdef T_SEND_TIME
|
||||
struct timespec sending_time;
|
||||
#endif
|
||||
int type;
|
||||
char *buffer;
|
||||
event_arg e[T_MAX_ARGS];
|
||||
int ecount;
|
||||
} event;
|
||||
|
||||
event get_event(int s, char *v, void *d);
|
||||
|
||||
#ifdef T_SEND_TIME
|
||||
event new_event(struct timespec sending_time, int type,
|
||||
int length, char *buffer, void *database);
|
||||
#else
|
||||
event new_event(int type, int length, char *buffer, void *database);
|
||||
#endif
|
||||
|
||||
#endif /* _EVENT_H_ */
|
||||
@@ -0,0 +1,231 @@
|
||||
#include "event_selector.h"
|
||||
#include "gui/gui.h"
|
||||
#include "database.h"
|
||||
#include "utils.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
struct event_selector {
|
||||
int *is_on;
|
||||
int *is_on_paused; /* when pausing, is_on is set to all 0, this one
|
||||
* is used to copy back data when un-pausing */
|
||||
int red;
|
||||
int green;
|
||||
gui *g;
|
||||
widget *events;
|
||||
widget *groups;
|
||||
void *database;
|
||||
int nevents;
|
||||
int ngroups;
|
||||
int paused;
|
||||
/* those three widgets used to pause/unpause reception of events */
|
||||
widget *parent_widget;
|
||||
widget *normal_widget;
|
||||
widget *pause_widget;
|
||||
void (*change_callback)(void *change_callback_data);
|
||||
void *change_callback_data;
|
||||
};
|
||||
|
||||
static void scroll(void *private, gui *g,
|
||||
char *notification, widget *w, void *notification_data)
|
||||
{
|
||||
int visible_lines;
|
||||
int start_line;
|
||||
int number_of_lines;
|
||||
int new_line;
|
||||
int inc;
|
||||
|
||||
textlist_state(g, w, &visible_lines, &start_line, &number_of_lines);
|
||||
inc = 10;
|
||||
if (inc > visible_lines - 2) inc = visible_lines - 2;
|
||||
if (inc < 1) inc = 1;
|
||||
if (!strcmp(notification, "scrollup")) inc = -inc;
|
||||
|
||||
new_line = start_line + inc;
|
||||
if (new_line > number_of_lines - visible_lines)
|
||||
new_line = number_of_lines - visible_lines;
|
||||
if (new_line < 0) new_line = 0;
|
||||
|
||||
textlist_set_start_line(g, w, new_line);
|
||||
}
|
||||
|
||||
static void click(void *private, gui *g,
|
||||
char *notification, widget *w, void *notification_data)
|
||||
{
|
||||
int *d = notification_data;
|
||||
struct event_selector *this = private;
|
||||
int set_on;
|
||||
int line = d[0];
|
||||
int button = d[1];
|
||||
char *text;
|
||||
int color;
|
||||
int i;
|
||||
|
||||
/* notification_data depends on the kind of widget */
|
||||
if (w == this->pause_widget) {
|
||||
line = 0;
|
||||
button = d[0];
|
||||
} else {
|
||||
line = d[0];
|
||||
button = d[1];
|
||||
}
|
||||
|
||||
/* middle-button toggles - redo with SPACE when keyboard is processed */
|
||||
if (button == 2) {
|
||||
if (this->paused == 0) {
|
||||
widget_del_child(g, this->parent_widget, this->normal_widget);
|
||||
widget_add_child(g, this->parent_widget, this->pause_widget, 0);
|
||||
container_set_child_growable(g, this->parent_widget,
|
||||
this->pause_widget, 1);
|
||||
/* pause */
|
||||
memcpy(this->is_on_paused, this->is_on, this->nevents * sizeof(int));
|
||||
memset(this->is_on, 0, this->nevents * sizeof(int));
|
||||
this->change_callback(this->change_callback_data);
|
||||
} else {
|
||||
widget_del_child(g, this->parent_widget, this->pause_widget);
|
||||
widget_add_child(g, this->parent_widget, this->normal_widget, 0);
|
||||
container_set_child_growable(g, this->parent_widget,
|
||||
this->normal_widget, 1);
|
||||
/* un-pause */
|
||||
memcpy(this->is_on, this->is_on_paused, this->nevents * sizeof(int));
|
||||
this->change_callback(this->change_callback_data);
|
||||
}
|
||||
this->paused = 1 - this->paused;
|
||||
return;
|
||||
}
|
||||
|
||||
if (w == this->pause_widget) return;
|
||||
|
||||
if (button != 1 && button != 3) return;
|
||||
|
||||
if (button == 1) set_on = 1; else set_on = 0;
|
||||
|
||||
if (w == this->events)
|
||||
textlist_get_line(this->g, this->events, line, &text, &color);
|
||||
else
|
||||
textlist_get_line(this->g, this->groups, line, &text, &color);
|
||||
|
||||
on_off(this->database, text, this->is_on, set_on);
|
||||
|
||||
for (i = 0; i < this->nevents; i++)
|
||||
textlist_set_color(this->g, this->events, i,
|
||||
this->is_on[database_pos_to_id(this->database, i)] ?
|
||||
this->green : this->red);
|
||||
|
||||
for (i = 0; i < this->ngroups; i++)
|
||||
textlist_set_color(this->g, this->groups, i, FOREGROUND_COLOR);
|
||||
if (w == this->groups)
|
||||
textlist_set_color(this->g, this->groups, line,
|
||||
set_on ? this->green : this->red);
|
||||
|
||||
this->change_callback(this->change_callback_data);
|
||||
}
|
||||
|
||||
event_selector *setup_event_selector(gui *g, void *database, int *is_on,
|
||||
void (*change_callback)(void *), void *change_callback_data)
|
||||
{
|
||||
struct event_selector *ret;
|
||||
widget *win;
|
||||
widget *win_container;
|
||||
widget *main_container;
|
||||
widget *container;
|
||||
widget *left, *right;
|
||||
widget *events, *groups;
|
||||
widget *pause_container;
|
||||
char **ids;
|
||||
char **gps;
|
||||
int n;
|
||||
int i;
|
||||
int red, green;
|
||||
|
||||
ret = calloc(1, sizeof(struct event_selector)); if (ret == NULL) abort();
|
||||
|
||||
red = new_color(g, "#c93535");
|
||||
green = new_color(g, "#2f9e2a");
|
||||
|
||||
win = new_toplevel_window(g, 470, 300, "event selector");
|
||||
win_container = new_container(g, VERTICAL);
|
||||
widget_add_child(g, win, win_container, -1);
|
||||
|
||||
main_container = new_container(g, VERTICAL);
|
||||
widget_add_child(g, win_container, main_container, -1);
|
||||
container_set_child_growable(g, win_container, main_container, 1);
|
||||
|
||||
container = new_container(g, HORIZONTAL);
|
||||
widget_add_child(g, main_container, container, -1);
|
||||
container_set_child_growable(g, main_container, container, 1);
|
||||
widget_add_child(g, main_container,
|
||||
new_label(g, "mouse scroll to scroll - "
|
||||
"left click to activate - "
|
||||
"right click to deactivate"), -1);
|
||||
|
||||
left = new_container(g, VERTICAL);
|
||||
right = new_container(g, VERTICAL);
|
||||
widget_add_child(g, container, left, -1);
|
||||
widget_add_child(g, container, right, -1);
|
||||
container_set_child_growable(g, container, left, 1);
|
||||
container_set_child_growable(g, container, right, 1);
|
||||
|
||||
widget_add_child(g, left, new_label(g, "Events"), -1);
|
||||
widget_add_child(g, right, new_label(g, "Groups"), -1);
|
||||
|
||||
events = new_textlist(g, 235, 10, new_color(g, "#b3c1e1"));
|
||||
groups = new_textlist(g, 235, 10, new_color(g, "#edd6cb"));
|
||||
|
||||
widget_add_child(g, left, events, -1);
|
||||
widget_add_child(g, right, groups, -1);
|
||||
container_set_child_growable(g, left, events, 1);
|
||||
container_set_child_growable(g, right, groups, 1);
|
||||
|
||||
pause_container = new_positioner(g);
|
||||
widget_add_child(g, pause_container,
|
||||
new_label(g,
|
||||
"events' reception paused - click middle button to resume"), -1);
|
||||
label_set_clickable(g, pause_container, 1);
|
||||
|
||||
n = database_get_ids(database, &ids);
|
||||
for (i = 0; i < n; i++) {
|
||||
textlist_add(g, events, ids[i], -1,
|
||||
is_on[database_pos_to_id(database, i)] ? green : red);
|
||||
}
|
||||
free(ids);
|
||||
|
||||
ret->nevents = n;
|
||||
|
||||
ret->is_on_paused = calloc(n, sizeof(int));
|
||||
if (ret->is_on_paused == NULL) abort();
|
||||
|
||||
n = database_get_groups(database, &gps);
|
||||
for (i = 0; i < n; i++) {
|
||||
textlist_add(g, groups, gps[i], -1, FOREGROUND_COLOR);
|
||||
}
|
||||
free(gps);
|
||||
|
||||
ret->ngroups = n;
|
||||
|
||||
ret->g = g;
|
||||
ret->is_on = is_on;
|
||||
ret->red = red;
|
||||
ret->green = green;
|
||||
ret->events = events;
|
||||
ret->groups = groups;
|
||||
ret->database = database;
|
||||
ret->change_callback = change_callback;
|
||||
ret->change_callback_data = change_callback_data;
|
||||
|
||||
ret->parent_widget = win_container;
|
||||
ret->normal_widget = main_container;
|
||||
ret->pause_widget = pause_container;
|
||||
|
||||
register_notifier(g, "scrollup", events, scroll, ret);
|
||||
register_notifier(g, "scrolldown", events, scroll, ret);
|
||||
register_notifier(g, "click", events, click, ret);
|
||||
|
||||
register_notifier(g, "scrollup", groups, scroll, ret);
|
||||
register_notifier(g, "scrolldown", groups, scroll, ret);
|
||||
register_notifier(g, "click", groups, click, ret);
|
||||
|
||||
register_notifier(g, "click", pause_container, click, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
#ifndef _EVENT_SELECTOR_H_
|
||||
#define _EVENT_SELECTOR_H_
|
||||
|
||||
#include "gui/gui.h"
|
||||
|
||||
typedef void event_selector;
|
||||
|
||||
event_selector *setup_event_selector(gui *g, void *database, int *is_on,
|
||||
void (*change_callback)(void *), void *change_callback_data);
|
||||
|
||||
#endif /* _EVENT_SELECTOR_H_ */
|
||||
@@ -0,0 +1,13 @@
|
||||
CC=gcc
|
||||
CFLAGS=-Wall -g -pthread -I..
|
||||
|
||||
OBJS=filter.o
|
||||
|
||||
filter.a: $(OBJS)
|
||||
ar cr filter.a $(OBJS)
|
||||
|
||||
%.o: %.c
|
||||
$(CC) $(CFLAGS) -o $@ -c $<
|
||||
|
||||
clean:
|
||||
rm -f *.a *.o
|
||||
@@ -0,0 +1,125 @@
|
||||
#include "filter.h"
|
||||
#include "event.h"
|
||||
#include "database.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
struct filter {
|
||||
union {
|
||||
struct { struct filter *a, *b; } op2;
|
||||
int v;
|
||||
struct { int event_type; int arg_index; } evarg;
|
||||
} v;
|
||||
|
||||
int (*eval)(struct filter *this, event e);
|
||||
};
|
||||
|
||||
/****************************************************************************/
|
||||
/* evaluation functions */
|
||||
/****************************************************************************/
|
||||
|
||||
int eval_and(struct filter *f, event e)
|
||||
{
|
||||
if (f->v.op2.a->eval(f->v.op2.a, e) == 0) return 0;
|
||||
return f->v.op2.b->eval(f->v.op2.b, e);
|
||||
}
|
||||
|
||||
int eval_eq(struct filter *f, event e)
|
||||
{
|
||||
int a = f->v.op2.a->eval(f->v.op2.a, e);
|
||||
int b = f->v.op2.b->eval(f->v.op2.b, e);
|
||||
return a == b;
|
||||
}
|
||||
|
||||
int eval_int(struct filter *f, event e)
|
||||
{
|
||||
return f->v.v;
|
||||
}
|
||||
|
||||
int eval_evarg(struct filter *f, event e)
|
||||
{
|
||||
if (e.type != f->v.evarg.event_type) {
|
||||
printf("%s:%d:%s: bad event type\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
abort();
|
||||
}
|
||||
if (e.e[f->v.evarg.arg_index].type != EVENT_INT) {
|
||||
printf("%s:%d:%s: bad event argtype; has to be 'int'\n",
|
||||
__FILE__, __LINE__, __FUNCTION__);
|
||||
abort();
|
||||
}
|
||||
return e.e[f->v.evarg.arg_index].i;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
/* filter construction functions */
|
||||
/****************************************************************************/
|
||||
|
||||
filter *filter_and(filter *a, filter *b)
|
||||
{
|
||||
struct filter *ret = calloc(1, sizeof(struct filter));
|
||||
if (ret == NULL) abort();
|
||||
ret->eval = eval_and;
|
||||
ret->v.op2.a = a;
|
||||
ret->v.op2.b = b;
|
||||
return ret;
|
||||
}
|
||||
|
||||
filter *filter_eq(filter *a, filter *b)
|
||||
{
|
||||
struct filter *ret = calloc(1, sizeof(struct filter));
|
||||
if (ret == NULL) abort();
|
||||
ret->eval = eval_eq;
|
||||
ret->v.op2.a = a;
|
||||
ret->v.op2.b = b;
|
||||
return ret;
|
||||
}
|
||||
|
||||
filter *filter_int(int v)
|
||||
{
|
||||
struct filter *ret = calloc(1, sizeof(struct filter));
|
||||
if (ret == NULL) abort();
|
||||
ret->eval = eval_int;
|
||||
ret->v.v = v;
|
||||
return ret;
|
||||
}
|
||||
|
||||
filter *filter_evarg(void *database, char *event_name, char *varname)
|
||||
{
|
||||
struct filter *ret;
|
||||
int event_id;
|
||||
database_event_format f;
|
||||
int i;
|
||||
|
||||
ret = calloc(1, sizeof(struct filter)); if (ret == NULL) abort();
|
||||
|
||||
event_id = event_id_from_name(database, event_name);
|
||||
f = get_format(database, event_id);
|
||||
|
||||
ret->eval = eval_evarg;
|
||||
ret->v.evarg.event_type = event_id;
|
||||
ret->v.evarg.arg_index = -1;
|
||||
|
||||
for (i = 0; i < f.count; i++) {
|
||||
if (strcmp(f.name[i], varname) != 0) continue;
|
||||
ret->v.evarg.arg_index = i;
|
||||
break;
|
||||
}
|
||||
if (ret->v.evarg.arg_index == -1) {
|
||||
printf("%s:%d:%s: event '%s' has no argument '%s'\n",
|
||||
__FILE__, __LINE__, __FUNCTION__, event_name, varname);
|
||||
abort();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
/* eval function */
|
||||
/****************************************************************************/
|
||||
|
||||
int filter_eval(filter *_f, event e)
|
||||
{
|
||||
struct filter *f = _f;
|
||||
return f->eval(f, e);
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
#ifndef _FILTER_H_
|
||||
#define _FILTER_H_
|
||||
|
||||
#include "event.h"
|
||||
|
||||
typedef void filter;
|
||||
|
||||
filter *filter_and(filter *a, filter *b);
|
||||
filter *filter_eq(filter *a, filter *b);
|
||||
filter *filter_int(int v);
|
||||
filter *filter_evarg(void *database, char *event_name, char *varname);
|
||||
|
||||
int filter_eval(filter *f, event e);
|
||||
|
||||
#endif /* _FILTER_H_ */
|
||||
@@ -0,0 +1,102 @@
|
||||
#include "defs.h"
|
||||
#include "gui/gui.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
static struct {
|
||||
gui *g;
|
||||
widget *input_signal; /* CC_id 0 antenna 0 */
|
||||
volatile int input_signal_length; /* unit: byte */
|
||||
void *input_signal_iq;
|
||||
pthread_mutex_t input_signal_lock;
|
||||
} eNB_data;
|
||||
|
||||
static void *gui_thread(void *g)
|
||||
{
|
||||
gui_loop(g);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static void *input_signal_plotter(void *_)
|
||||
{
|
||||
short *iqbuf;
|
||||
float *x;
|
||||
float *y;
|
||||
int i;
|
||||
int length = eNB_data.input_signal_length / 4;
|
||||
|
||||
x = calloc(1, sizeof(float) * eNB_data.input_signal_length / 4);
|
||||
y = calloc(1, sizeof(float) * eNB_data.input_signal_length / 4);
|
||||
if (x == NULL || y == NULL) abort();
|
||||
|
||||
while (1) {
|
||||
usleep(100 * 1000);
|
||||
|
||||
if (pthread_mutex_lock(&eNB_data.input_signal_lock)) abort();
|
||||
|
||||
if (length * 4 != eNB_data.input_signal_length) {
|
||||
free(x);
|
||||
free(y);
|
||||
x = calloc(1, sizeof(float) * eNB_data.input_signal_length / 4);
|
||||
y = calloc(1, sizeof(float) * eNB_data.input_signal_length / 4);
|
||||
if (x == NULL || y == NULL) abort();
|
||||
length = eNB_data.input_signal_length / 4;
|
||||
}
|
||||
|
||||
iqbuf = eNB_data.input_signal_iq;
|
||||
|
||||
for (i = 0; i < length; i++) {
|
||||
x[i] = i;
|
||||
y[i] = 10*log10(1.0+(float)(iqbuf[2*i]*iqbuf[2*i]+
|
||||
iqbuf[2*i+1]*iqbuf[2*i+1]));
|
||||
}
|
||||
|
||||
xy_plot_set_points(eNB_data.g, eNB_data.input_signal, 0,
|
||||
length, x, y);
|
||||
|
||||
if (pthread_mutex_unlock(&eNB_data.input_signal_lock)) abort();
|
||||
}
|
||||
}
|
||||
|
||||
void t_gui_start(void)
|
||||
{
|
||||
gui *g = gui_init();
|
||||
|
||||
widget *win = new_toplevel_window(g, 550, 140, "input signal");
|
||||
widget *plot = new_xy_plot(g, 512, 100, "eNB 0 input signal", 20);
|
||||
widget_add_child(g, win, plot, -1);
|
||||
xy_plot_set_range(g, plot, 0, 76800, 30, 70);
|
||||
xy_plot_new_plot(g, plot, FOREGROUND_COLOR);
|
||||
|
||||
eNB_data.input_signal = plot;
|
||||
eNB_data.input_signal_length = 76800 * 4;
|
||||
eNB_data.input_signal_iq = calloc(1, 76800 * 4);
|
||||
if (eNB_data.input_signal_iq == NULL) abort();
|
||||
pthread_mutex_init(&eNB_data.input_signal_lock, NULL);
|
||||
|
||||
eNB_data.g = g;
|
||||
|
||||
new_thread(gui_thread, g);
|
||||
new_thread(input_signal_plotter, NULL);
|
||||
}
|
||||
|
||||
void t_gui_set_input_signal(int eNB, int frame, int subframe, int antenna,
|
||||
int size, void *buf)
|
||||
{
|
||||
if (pthread_mutex_lock(&eNB_data.input_signal_lock)) abort();
|
||||
|
||||
if (eNB_data.input_signal_length != size * 10) {
|
||||
free(eNB_data.input_signal_iq);
|
||||
eNB_data.input_signal_length = size * 10;
|
||||
eNB_data.input_signal_iq = calloc(1, eNB_data.input_signal_length);
|
||||
if (eNB_data.input_signal_iq == NULL) abort();
|
||||
}
|
||||
|
||||
memcpy((char *)eNB_data.input_signal_iq + subframe * size, buf, size);
|
||||
|
||||
if (pthread_mutex_unlock(&eNB_data.input_signal_lock)) abort();
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
CC=gcc
|
||||
CFLAGS=-Wall -g -pthread -I/usr/include/X11/Xft -I/usr/include/freetype2
|
||||
|
||||
OBJS=init.o loop.o toplevel_window.o x.o container.o widget.o \
|
||||
gui.o label.o event.o xy_plot.o textlist.o notify.o positioner.o \
|
||||
timeline.o space.o image.o
|
||||
|
||||
gui.a: $(OBJS)
|
||||
ar cr gui.a $(OBJS)
|
||||
|
||||
test: test.o gui.a
|
||||
$(CC) -o test $(OBJS) test.o -lX11 -pthread -lm
|
||||
|
||||
%.o: %.c
|
||||
$(CC) $(CFLAGS) -o $@ -c $<
|
||||
|
||||
clean:
|
||||
rm -f *.a *.o test
|
||||
@@ -0,0 +1,339 @@
|
||||
#include "gui.h"
|
||||
#include "gui_defs.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define MAX(a, b) ((a)>(b)?(a):(b))
|
||||
|
||||
static void repack(gui *g, widget *_this)
|
||||
{
|
||||
LOGD("REPACK container %p\n", _this);
|
||||
struct container_widget *this = _this;
|
||||
this->hints_are_valid = 0;
|
||||
return this->common.parent->repack(g, this->common.parent);
|
||||
}
|
||||
|
||||
static void add_child(gui *g, widget *_this, widget *child, int position)
|
||||
{
|
||||
LOGD("ADD_CHILD container\n");
|
||||
struct container_widget *this = _this;
|
||||
|
||||
this->hints_are_valid = 0;
|
||||
widget_add_child_internal(g, this, child, position);
|
||||
|
||||
/* initially not growable */
|
||||
this->growable = realloc(this->growable, (this->nchildren+1)*sizeof(int));
|
||||
if (this->growable == NULL) abort();
|
||||
|
||||
if (position == -1) position = this->nchildren;
|
||||
|
||||
memmove(this->growable + position+1, this->growable + position,
|
||||
(this->nchildren - position) * sizeof(int));
|
||||
|
||||
this->growable[position] = 0;
|
||||
|
||||
this->nchildren++;
|
||||
}
|
||||
|
||||
static void del_child(gui *g, widget *_this, widget *child)
|
||||
{
|
||||
LOGD("DEL_CHILD container\n");
|
||||
struct container_widget *this = _this;
|
||||
int position = widget_get_child_position(g, _this, child);
|
||||
|
||||
this->hints_are_valid = 0;
|
||||
widget_del_child_internal(g, this, child);
|
||||
|
||||
memmove(this->growable + position, this->growable + position+1,
|
||||
(this->nchildren - position - 1) * sizeof(int));
|
||||
|
||||
this->growable = realloc(this->growable, (this->nchildren-1)*sizeof(int));
|
||||
if (this->nchildren != 1 && this->growable == NULL) abort();
|
||||
|
||||
this->nchildren--;
|
||||
}
|
||||
|
||||
static void compute_vertical_hints(struct gui *g,
|
||||
struct container_widget *this)
|
||||
{
|
||||
struct widget_list *l;
|
||||
int cwidth, cheight;
|
||||
int allocated_width = 0, allocated_height = 0;
|
||||
|
||||
/* get largest width */
|
||||
l = this->common.children;
|
||||
while (l) {
|
||||
l->item->hints(g, l->item, &cwidth, &cheight);
|
||||
if (cwidth > allocated_width) allocated_width = cwidth;
|
||||
allocated_height += cheight;
|
||||
l = l->next;
|
||||
}
|
||||
this->hint_width = allocated_width;
|
||||
this->hint_height = allocated_height;
|
||||
this->hints_are_valid = 1;
|
||||
}
|
||||
|
||||
static void compute_horizontal_hints(struct gui *g,
|
||||
struct container_widget *this)
|
||||
{
|
||||
struct widget_list *l;
|
||||
int cwidth, cheight;
|
||||
int allocated_width = 0, allocated_height = 0;
|
||||
|
||||
/* get largest height */
|
||||
l = this->common.children;
|
||||
while (l) {
|
||||
l->item->hints(g, l->item, &cwidth, &cheight);
|
||||
if (cheight > allocated_height) allocated_height = cheight;
|
||||
allocated_width += cwidth;
|
||||
l = l->next;
|
||||
}
|
||||
this->hint_width = allocated_width;
|
||||
this->hint_height = allocated_height;
|
||||
this->hints_are_valid = 1;
|
||||
}
|
||||
|
||||
static void vertical_allocate(gui *_gui, widget *_this,
|
||||
int x, int y, int width, int height)
|
||||
{
|
||||
LOGD("ALLOCATE container vertical %p\n", _this);
|
||||
int cy = 0;
|
||||
int cwidth, cheight;
|
||||
struct gui *g = _gui;
|
||||
struct container_widget *this = _this;
|
||||
struct widget_list *l;
|
||||
int over_pixels = 0;
|
||||
int i;
|
||||
|
||||
if (this->hints_are_valid == 1) goto hints_ok;
|
||||
|
||||
compute_vertical_hints(g, this);
|
||||
|
||||
hints_ok:
|
||||
|
||||
this->common.x = x;
|
||||
this->common.y = y;
|
||||
this->common.width = width;
|
||||
this->common.height = height;
|
||||
|
||||
/* TODO: some pixels won't be allocated, take care of it? */
|
||||
if (height > this->hint_height) {
|
||||
int ngrowable = 0;
|
||||
for (i = 0; i < this->nchildren; i++) if (this->growable[i]) ngrowable++;
|
||||
if (ngrowable)
|
||||
over_pixels = (height - this->hint_height) / ngrowable;
|
||||
}
|
||||
|
||||
/* allocate */
|
||||
l = this->common.children;
|
||||
i = 0;
|
||||
while (l) {
|
||||
int allocated_height;
|
||||
l->item->hints(g, l->item, &cwidth, &cheight);
|
||||
allocated_height = cheight + (this->growable[i] ? over_pixels : 0);
|
||||
l->item->allocate(g, l->item, this->common.x, this->common.y + cy,
|
||||
MAX(width, cwidth), allocated_height);
|
||||
cy += allocated_height;
|
||||
l = l->next;
|
||||
i++;
|
||||
}
|
||||
|
||||
// if (cy != this->hint_height) ERR("reachable?\n");
|
||||
}
|
||||
|
||||
static void horizontal_allocate(gui *_gui, widget *_this,
|
||||
int x, int y, int width, int height)
|
||||
{
|
||||
LOGD("ALLOCATE container horizontal %p\n", _this);
|
||||
int cx = 0;
|
||||
int cwidth, cheight;
|
||||
struct gui *g = _gui;
|
||||
struct container_widget *this = _this;
|
||||
struct widget_list *l;
|
||||
int over_pixels = 0;
|
||||
int i;
|
||||
|
||||
if (this->hints_are_valid == 1) goto hints_ok;
|
||||
|
||||
compute_horizontal_hints(g, this);
|
||||
|
||||
hints_ok:
|
||||
|
||||
this->common.x = x;
|
||||
this->common.y = y;
|
||||
this->common.width = width;
|
||||
this->common.height = height;
|
||||
|
||||
/* TODO: some pixels won't be allocated, take care of it? */
|
||||
if (width > this->hint_width) {
|
||||
int ngrowable = 0;
|
||||
for (i = 0; i < this->nchildren; i++) if (this->growable[i]) ngrowable++;
|
||||
if (ngrowable)
|
||||
over_pixels = (width - this->hint_width) / ngrowable;
|
||||
}
|
||||
|
||||
/* allocate */
|
||||
l = this->common.children;
|
||||
i = 0;
|
||||
while (l) {
|
||||
int allocated_width;
|
||||
l->item->hints(g, l->item, &cwidth, &cheight);
|
||||
allocated_width = cwidth + (this->growable[i] ? over_pixels : 0);
|
||||
l->item->allocate(g, l->item, this->common.x + cx, this->common.y,
|
||||
allocated_width, MAX(height, cheight)/* this->hint_height */);
|
||||
cx += allocated_width;
|
||||
l = l->next;
|
||||
i++;
|
||||
}
|
||||
|
||||
// if (cx != this->hint_width) ERR("reachable?\n");
|
||||
}
|
||||
|
||||
static void vertical_hints(gui *_gui, widget *_w, int *width, int *height)
|
||||
{
|
||||
LOGD("HINTS container vertical %p\n", _w);
|
||||
struct gui *g = _gui;
|
||||
struct container_widget *this = _w;
|
||||
|
||||
if (this->hints_are_valid) {
|
||||
*width = this->hint_width;
|
||||
*height = this->hint_height;
|
||||
return;
|
||||
}
|
||||
|
||||
compute_vertical_hints(g, this);
|
||||
|
||||
*width = this->hint_width;
|
||||
*height = this->hint_height;
|
||||
}
|
||||
|
||||
static void horizontal_hints(gui *_gui, widget *_w, int *width, int *height)
|
||||
{
|
||||
LOGD("HINTS container horizontal %p\n", _w);
|
||||
struct gui *g = _gui;
|
||||
struct container_widget *this = _w;
|
||||
|
||||
if (this->hints_are_valid) {
|
||||
*width = this->hint_width;
|
||||
*height = this->hint_height;
|
||||
return;
|
||||
}
|
||||
|
||||
compute_horizontal_hints(g, this);
|
||||
|
||||
*width = this->hint_width;
|
||||
*height = this->hint_height;
|
||||
}
|
||||
|
||||
static void horizontal_button(gui *_g, widget *_this, int x, int y,
|
||||
int key_modifiers, int button, int up)
|
||||
{
|
||||
LOGD("BUTTON container horizontal %p xy %d %d button %d up %d\n", _this, x, y, button, up);
|
||||
struct gui *g = _g;
|
||||
struct container_widget *this = _this;
|
||||
struct widget_list *l;
|
||||
|
||||
l = this->common.children;
|
||||
while (l) {
|
||||
if (l->item->x <= x && x < l->item->x + l->item->width) {
|
||||
l->item->button(g, l->item, x, y, key_modifiers, button, up);
|
||||
break;
|
||||
}
|
||||
l = l->next;
|
||||
}
|
||||
}
|
||||
|
||||
static void vertical_button(gui *_g, widget *_this, int x, int y,
|
||||
int key_modifiers, int button, int up)
|
||||
{
|
||||
LOGD("BUTTON container vertical %p xy %d %d button %d up %d\n", _this, x, y, button, up);
|
||||
struct gui *g = _g;
|
||||
struct container_widget *this = _this;
|
||||
struct widget_list *l;
|
||||
|
||||
l = this->common.children;
|
||||
while (l) {
|
||||
if (l->item->y <= y && y < l->item->y + l->item->height) {
|
||||
l->item->button(g, l->item, x, y, key_modifiers, button, up);
|
||||
break;
|
||||
}
|
||||
l = l->next;
|
||||
}
|
||||
}
|
||||
|
||||
static void paint(gui *_gui, widget *_this)
|
||||
{
|
||||
LOGD("PAINT container\n");
|
||||
struct gui *g = _gui;
|
||||
struct widget *this = _this;
|
||||
struct widget_list *l;
|
||||
|
||||
l = this->children;
|
||||
while (l) {
|
||||
l->item->paint(g, l->item);
|
||||
l = l->next;
|
||||
}
|
||||
}
|
||||
|
||||
widget *new_container(gui *_gui, int vertical)
|
||||
{
|
||||
struct gui *g = _gui;
|
||||
struct container_widget *w;
|
||||
|
||||
glock(g);
|
||||
|
||||
w = new_widget(g, CONTAINER, sizeof(struct container_widget));
|
||||
|
||||
w->vertical = vertical;
|
||||
w->hints_are_valid = 0;
|
||||
|
||||
w->common.paint = paint;
|
||||
w->common.add_child = add_child;
|
||||
w->common.del_child = del_child;
|
||||
w->common.repack = repack;
|
||||
|
||||
if (vertical) {
|
||||
w->common.allocate = vertical_allocate;
|
||||
w->common.hints = vertical_hints;
|
||||
w->common.button = vertical_button;
|
||||
} else {
|
||||
w->common.allocate = horizontal_allocate;
|
||||
w->common.hints = horizontal_hints;
|
||||
w->common.button = horizontal_button;
|
||||
}
|
||||
|
||||
gunlock(g);
|
||||
|
||||
return w;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/* public functions */
|
||||
/*************************************************************************/
|
||||
|
||||
void container_set_child_growable(gui *_gui, widget *_this,
|
||||
widget *child, int growable)
|
||||
{
|
||||
gui *g = _gui;
|
||||
struct container_widget *this = _this;
|
||||
struct widget_list *lcur;
|
||||
int i;
|
||||
|
||||
glock(g);
|
||||
|
||||
lcur = this->common.children;
|
||||
i = 0;
|
||||
while (lcur) {
|
||||
if (lcur->item == child) break;
|
||||
lcur = lcur->next;
|
||||
i++;
|
||||
}
|
||||
if (lcur == NULL) ERR("%s:%d: child not found\n", __FILE__, __LINE__);
|
||||
|
||||
this->growable[i] = growable;
|
||||
|
||||
send_event(g, REPACK, this->common.id);
|
||||
|
||||
gunlock(g);
|
||||
}
|
||||
@@ -0,0 +1,209 @@
|
||||
#include "gui.h"
|
||||
#include "gui_defs.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
/*****************************************************************/
|
||||
/* generic functions */
|
||||
/*****************************************************************/
|
||||
|
||||
static void event_list_append(struct gui *g, struct event *e)
|
||||
{
|
||||
struct event_list *new;
|
||||
|
||||
new = calloc(1, sizeof(struct event_list));
|
||||
if (new == NULL) OOM;
|
||||
|
||||
new->item = e;
|
||||
|
||||
if (g->queued_events == NULL) {
|
||||
g->queued_events = new;
|
||||
new->last = new;
|
||||
return;
|
||||
}
|
||||
|
||||
g->queued_events->last->next = new;
|
||||
g->queued_events->last = new;
|
||||
}
|
||||
|
||||
static void free_event(struct event *e)
|
||||
{
|
||||
switch (e->type) {
|
||||
case REPACK: /* nothing */ break;
|
||||
case DIRTY: /* nothing */ break;
|
||||
}
|
||||
free(e);
|
||||
}
|
||||
|
||||
static int events_equal(struct event *e1, struct event *e2)
|
||||
{
|
||||
if (e1->type != e2->type) return 0;
|
||||
switch (e1->type) {
|
||||
case REPACK: {
|
||||
struct repack_event *re1 = (struct repack_event *)e1;
|
||||
struct repack_event *re2 = (struct repack_event *)e2;
|
||||
return re1->id == re2->id;
|
||||
}
|
||||
case DIRTY: {
|
||||
struct dirty_event *re1 = (struct dirty_event *)e1;
|
||||
struct dirty_event *re2 = (struct dirty_event *)e2;
|
||||
return re1->id == re2->id;
|
||||
}}
|
||||
/* unreachable */
|
||||
abort();
|
||||
}
|
||||
|
||||
/*****************************************************************/
|
||||
/* sending events */
|
||||
/*****************************************************************/
|
||||
|
||||
static event *new_event_repack(int id)
|
||||
{
|
||||
struct repack_event *ret;
|
||||
ret = calloc(1, sizeof(struct repack_event));
|
||||
if (ret == NULL) OOM;
|
||||
ret->id = id;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static event *new_event_dirty(int id)
|
||||
{
|
||||
struct dirty_event *ret;
|
||||
ret = calloc(1, sizeof(struct dirty_event));
|
||||
if (ret == NULL) OOM;
|
||||
ret->id = id;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void compress_event_list(struct gui *g)
|
||||
{
|
||||
struct event *last;
|
||||
struct event_list *cur;
|
||||
/* basic compression, to be refined */
|
||||
|
||||
/* pickup last event and remove every copy of it found before
|
||||
* if it's DIRTY or REPACK
|
||||
*/
|
||||
last = g->queued_events->last->item;
|
||||
if (last->type == DIRTY || last->type == REPACK) {
|
||||
cur = g->queued_events;
|
||||
while (cur->item != last) {
|
||||
if (cur->item != NULL && events_equal(cur->item, last)) {
|
||||
free_event(cur->item);
|
||||
cur->item = NULL;
|
||||
}
|
||||
cur = cur->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void send_event(gui *_gui, enum event_type type, ...)
|
||||
{
|
||||
LOGD("send_event %d\n", type);
|
||||
struct gui *g = _gui;
|
||||
int do_write = 0;
|
||||
va_list ap;
|
||||
struct event *e;
|
||||
|
||||
if (g->queued_events == NULL) do_write = 1;
|
||||
|
||||
va_start(ap, type);
|
||||
|
||||
switch (type) {
|
||||
case REPACK: {
|
||||
int id;
|
||||
id = va_arg(ap, int);
|
||||
e = new_event_repack(id);
|
||||
break;
|
||||
}
|
||||
case DIRTY: {
|
||||
int id;
|
||||
id = va_arg(ap, int);
|
||||
e = new_event_dirty(id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
va_end(ap);
|
||||
|
||||
e->type = type;
|
||||
|
||||
event_list_append(g, e);
|
||||
compress_event_list(g);
|
||||
|
||||
if (do_write) {
|
||||
char c = 1;
|
||||
if (write(g->event_pipe[1], &c, 1) != 1)
|
||||
ERR("error writing to pipe: %s\n", strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************/
|
||||
/* processing events */
|
||||
/*****************************************************************/
|
||||
|
||||
static void repack_event(struct gui *g, int id)
|
||||
{
|
||||
struct widget *w = find_widget(g, id);
|
||||
if (w == NULL) { WARN("widget id %d not found\n", id); return; }
|
||||
w->repack(g, w);
|
||||
}
|
||||
|
||||
/* TODO: put that function somewhere else? */
|
||||
static struct toplevel_window_widget *get_toplevel_window(struct widget *w)
|
||||
{
|
||||
while (w != NULL) {
|
||||
if (w->type == TOPLEVEL_WINDOW)
|
||||
return (struct toplevel_window_widget *)w;
|
||||
w = w->parent;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void dirty_event(struct gui *g, int id)
|
||||
{
|
||||
struct widget *w = find_widget(g, id);
|
||||
struct toplevel_window_widget *win;
|
||||
if (w == NULL) { WARN("widget id %d not found\n", id); return; }
|
||||
win = get_toplevel_window(w);
|
||||
if (win == NULL)
|
||||
{ WARN("widget id %d not contained in a window\n", id); return; }
|
||||
g->xwin = win->x;
|
||||
w->clear(g, w);
|
||||
w->paint(g, w);
|
||||
g->xwin = NULL;
|
||||
g->repainted = 1;
|
||||
}
|
||||
|
||||
static void process_event(struct gui *g, struct event *e)
|
||||
{
|
||||
LOGD("processing event type %d\n", e->type);
|
||||
switch (e->type) {
|
||||
case REPACK: repack_event(g, ((struct repack_event *)e)->id); break;
|
||||
case DIRTY: dirty_event(g, ((struct dirty_event *)e)->id); break;
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: events' compression */
|
||||
void gui_events(gui *_gui)
|
||||
{
|
||||
struct gui *g = _gui;
|
||||
|
||||
LOGD("gui_events START: head %p\n", g->queued_events);
|
||||
|
||||
while (g->queued_events) {
|
||||
struct event_list *cur = g->queued_events;
|
||||
g->queued_events = cur->next;
|
||||
if (g->queued_events) g->queued_events->last = cur->last;
|
||||
if (cur->item != NULL) {
|
||||
process_event(g, cur->item);
|
||||
free_event(cur->item);
|
||||
}
|
||||
free(cur);
|
||||
}
|
||||
LOGD("gui_events DONE\n");
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
#include "gui.h"
|
||||
#include "gui_defs.h"
|
||||
#include "x.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
|
||||
int volatile gui_logd;
|
||||
|
||||
void glock(gui *_gui)
|
||||
{
|
||||
struct gui *g = _gui;
|
||||
if (pthread_mutex_lock(g->lock)) ERR("mutex error\n");
|
||||
}
|
||||
|
||||
void gunlock(gui *_gui)
|
||||
{
|
||||
struct gui *g = _gui;
|
||||
if (pthread_mutex_unlock(g->lock)) ERR("mutex error\n");
|
||||
}
|
||||
|
||||
int new_color(gui *_gui, char *color)
|
||||
{
|
||||
struct gui *g = _gui;
|
||||
int ret;
|
||||
|
||||
glock(g);
|
||||
|
||||
ret = x_new_color(g->x, color);
|
||||
|
||||
gunlock(g);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
#ifndef _GUI_H_
|
||||
#define _GUI_H_
|
||||
|
||||
/* defines the public API of the GUI */
|
||||
|
||||
typedef void gui;
|
||||
typedef void widget;
|
||||
|
||||
#define HORIZONTAL 0
|
||||
#define VERTICAL 1
|
||||
|
||||
#define BACKGROUND_COLOR 0
|
||||
#define FOREGROUND_COLOR 1
|
||||
|
||||
#define DEFAULT_FONT 0
|
||||
|
||||
/* key modifiers */
|
||||
#define KEY_SHIFT (1<<0)
|
||||
#define KEY_CONTROL (1<<1)
|
||||
#define KEY_ALT (1<<2)
|
||||
|
||||
gui *gui_init(void);
|
||||
|
||||
/* position = -1 to put at the end */
|
||||
void widget_add_child(gui *gui, widget *parent, widget *child, int position);
|
||||
void widget_del_child(gui *gui, widget *parent, widget *child);
|
||||
void widget_dirty(gui *gui, widget *this);
|
||||
|
||||
widget *new_toplevel_window(gui *gui, int width, int height, char *title);
|
||||
widget *new_container(gui *gui, int vertical);
|
||||
widget *new_positioner(gui *gui);
|
||||
widget *new_label(gui *gui, const char *text);
|
||||
widget *new_xy_plot(gui *gui, int width, int height, char *label,
|
||||
int vruler_width);
|
||||
widget *new_textlist(gui *gui, int width, int nlines, int background_color);
|
||||
widget *new_timeline(gui *gui, int width, int number_of_sublines,
|
||||
int subline_height);
|
||||
widget *new_space(gui *gui, int width, int height);
|
||||
widget *new_image(gui *gui, unsigned char *data, int length);
|
||||
|
||||
void label_set_clickable(gui *gui, widget *label, int clickable);
|
||||
|
||||
void container_set_child_growable(gui *_gui, widget *_this,
|
||||
widget *child, int growable);
|
||||
|
||||
int xy_plot_new_plot(gui *gui, widget *this, int color);
|
||||
void xy_plot_set_range(gui *gui, widget *this,
|
||||
float xmin, float xmax, float ymin, float ymax);
|
||||
void xy_plot_set_points(gui *gui, widget *this,
|
||||
int plot, int npoints, float *x, float *y);
|
||||
void xy_plot_get_dimensions(gui *gui, widget *this, int *width, int *height);
|
||||
|
||||
void textlist_add(gui *gui, widget *this, const char *text, int position,
|
||||
int color);
|
||||
void textlist_del(gui *gui, widget *this, int position);
|
||||
void textlist_add_silent(gui *gui, widget *this, const char *text,
|
||||
int position, int color);
|
||||
void textlist_del_silent(gui *gui, widget *this, int position);
|
||||
void textlist_state(gui *_gui, widget *_this,
|
||||
int *visible_lines, int *start_line, int *number_of_lines);
|
||||
void textlist_set_start_line(gui *gui, widget *this, int line);
|
||||
void textlist_get_line(gui *gui, widget *this, int line,
|
||||
char **text, int *color);
|
||||
void textlist_set_color(gui *gui, widget *this, int line, int color);
|
||||
|
||||
void timeline_clear(gui *gui, widget *this);
|
||||
void timeline_clear_silent(gui *gui, widget *this);
|
||||
void timeline_add_points(gui *gui, widget *this, int subline, int color,
|
||||
int *x, int len);
|
||||
void timeline_add_points_silent(gui *gui, widget *this, int subline,
|
||||
int color, int *x, int len);
|
||||
void timeline_set_subline_background_color(gui *gui, widget *this,
|
||||
int subline, int color);
|
||||
void timeline_get_width(gui *gui, widget *this, int *width);
|
||||
|
||||
void gui_loop(gui *gui);
|
||||
|
||||
void glock(gui *gui);
|
||||
void gunlock(gui *gui);
|
||||
|
||||
int new_color(gui *gui, char *color);
|
||||
|
||||
/* notifications */
|
||||
/* known notifications:
|
||||
* - textlist:
|
||||
* - scrollup { void *: NULL }
|
||||
* - scrolldown { void *: NULL }
|
||||
* - click { int [2]: line, button }
|
||||
* - label:
|
||||
* - click { int: button } (if enabled)
|
||||
* - timeline
|
||||
* - resize { int: width }
|
||||
* - scrollup { int [3]: x, y, key_modifiers }
|
||||
* - scrolldown { int [3]: x, y, key_modifiers }
|
||||
* - click { int: button }
|
||||
*/
|
||||
|
||||
/* same type as in gui_defs.h */
|
||||
typedef void (*notifier)(void *private, gui *g,
|
||||
char *notification, widget *w, void *notification_data);
|
||||
unsigned long register_notifier(gui *g, char *notification, widget *w,
|
||||
notifier handler, void *private);
|
||||
void unregister_notifier(gui *g, unsigned long notifier_id);
|
||||
|
||||
#endif /* _GUI_H_ */
|
||||
@@ -0,0 +1,255 @@
|
||||
#ifndef _GUI_DEFS_H_
|
||||
#define _GUI_DEFS_H_
|
||||
|
||||
/* defines the private API of the GUI */
|
||||
|
||||
extern int volatile gui_logd;
|
||||
#define LOGD(...) do { if (gui_logd) printf(__VA_ARGS__); } while (0)
|
||||
|
||||
/*************************************************************************/
|
||||
/* logging macros */
|
||||
/*************************************************************************/
|
||||
|
||||
#define ERR(...) \
|
||||
do { \
|
||||
printf("%s:%d:%s: ERROR: ", __FILE__, __LINE__, __FUNCTION__); \
|
||||
printf(__VA_ARGS__); \
|
||||
abort(); \
|
||||
} while (0)
|
||||
|
||||
#define WARN(...) \
|
||||
do { \
|
||||
printf("%s:%d:%s: WARNING: ", __FILE__, __LINE__, __FUNCTION__); \
|
||||
printf(__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#define OOM ERR("out of memory\n")
|
||||
|
||||
/*************************************************************************/
|
||||
/* widgets */
|
||||
/*************************************************************************/
|
||||
|
||||
enum widget_type {
|
||||
TOPLEVEL_WINDOW, CONTAINER, POSITIONER, TEXT_LIST, XY_PLOT, BUTTON, LABEL,
|
||||
TIMELINE, SPACE, IMAGE
|
||||
};
|
||||
|
||||
struct widget_list;
|
||||
|
||||
struct widget {
|
||||
enum widget_type type;
|
||||
int id;
|
||||
int x; /* allocated x after packing */
|
||||
int y; /* allocated y after packing */
|
||||
int width; /* allocated width after packing */
|
||||
int height; /* allocated height after packing */
|
||||
struct widget_list *children;
|
||||
struct widget *parent;
|
||||
void (*repack)(gui *g, widget *this);
|
||||
void (*add_child)(gui *g, widget *this, widget *child, int position);
|
||||
void (*del_child)(gui *g, widget *this, widget *child);
|
||||
void (*allocate)(gui *g, widget *this, int x, int y, int width, int height);
|
||||
void (*hints)(gui *g, widget *this, int *width, int *height);
|
||||
void (*paint)(gui *g, widget *this);
|
||||
void (*clear)(gui *g, widget *this);
|
||||
/* user input */
|
||||
void (*button)(gui *g, widget *this, int x, int y, int key_modifiers,
|
||||
int button, int up);
|
||||
};
|
||||
|
||||
struct widget_list {
|
||||
struct widget *item;
|
||||
struct widget_list *next;
|
||||
//struct widget_list *prev; /* unused? */
|
||||
struct widget_list *last; /* valid only for the head of the list */
|
||||
};
|
||||
|
||||
struct toplevel_window_widget {
|
||||
struct widget common;
|
||||
void *x; /* opaque X data (type x_window), used in x.c */
|
||||
};
|
||||
|
||||
struct container_widget {
|
||||
struct widget common;
|
||||
int vertical;
|
||||
int hints_are_valid; /* used to cache hints values */
|
||||
int hint_width; /* cached hint values - invalid if */
|
||||
int hint_height; /* repack_was_called == 1 */
|
||||
int *growable;
|
||||
int nchildren;
|
||||
};
|
||||
|
||||
struct positioner_widget {
|
||||
struct widget common;
|
||||
};
|
||||
|
||||
struct textlist_widget {
|
||||
struct widget common;
|
||||
char **text;
|
||||
int *color;
|
||||
int text_count;
|
||||
int wanted_width;
|
||||
int wanted_nlines; /* number of lines of text the user wants to see */
|
||||
int allocated_nlines; /* actual number of visible lines */
|
||||
int starting_line; /* points to the first visible line of text */
|
||||
int line_height;
|
||||
int baseline;
|
||||
int background_color;
|
||||
};
|
||||
|
||||
struct xy_plot_plot {
|
||||
float *x;
|
||||
float *y;
|
||||
int npoints;
|
||||
int color;
|
||||
};
|
||||
|
||||
struct xy_plot_widget {
|
||||
struct widget common;
|
||||
char *label;
|
||||
int label_width;
|
||||
int label_height;
|
||||
int label_baseline;
|
||||
int vrule_width; /* the width of the vertical ruler text zone */
|
||||
float xmin, xmax;
|
||||
float ymin, ymax;
|
||||
int wanted_width;
|
||||
int wanted_height;
|
||||
struct xy_plot_plot *plots;
|
||||
int nplots;
|
||||
};
|
||||
|
||||
struct timeline_subline {
|
||||
int *color; /* length = width of timeline widget
|
||||
* value = -1 if no color
|
||||
*/
|
||||
int width;
|
||||
int background; /* background color of the subline */
|
||||
};
|
||||
|
||||
struct timeline_widget {
|
||||
struct widget common;
|
||||
int n; /* number of sublines */
|
||||
struct timeline_subline *s;
|
||||
int subline_height;
|
||||
int wanted_width;
|
||||
};
|
||||
|
||||
struct button_widget {
|
||||
struct widget common;
|
||||
};
|
||||
|
||||
struct label_widget {
|
||||
struct widget common;
|
||||
const char *t;
|
||||
int color;
|
||||
int width; /* as given by the graphic's backend */
|
||||
int height; /* as given by the graphic's backend */
|
||||
int baseline; /* as given by the graphic's backend */
|
||||
};
|
||||
|
||||
struct space_widget {
|
||||
struct widget common;
|
||||
int wanted_width;
|
||||
int wanted_height;
|
||||
};
|
||||
|
||||
struct image_widget {
|
||||
struct widget common;
|
||||
int width;
|
||||
int height;
|
||||
void *x; /* opaque X data (type x_image), used in x.c */
|
||||
};
|
||||
|
||||
/*************************************************************************/
|
||||
/* events */
|
||||
/*************************************************************************/
|
||||
|
||||
typedef void event;
|
||||
|
||||
enum event_type {
|
||||
DIRTY, REPACK
|
||||
};
|
||||
|
||||
struct event {
|
||||
enum event_type type;
|
||||
};
|
||||
|
||||
struct event_list {
|
||||
struct event *item;
|
||||
struct event_list *next;
|
||||
struct event_list *last;
|
||||
};
|
||||
|
||||
struct dirty_event {
|
||||
struct event common;
|
||||
int id;
|
||||
};
|
||||
|
||||
struct repack_event {
|
||||
struct event common;
|
||||
int id;
|
||||
};
|
||||
|
||||
/*************************************************************************/
|
||||
/* notifications */
|
||||
/*************************************************************************/
|
||||
|
||||
/* same type as in gui.h */
|
||||
typedef void (*notifier)(void *private, gui *g,
|
||||
char *notification, widget *w, void *notification_data);
|
||||
|
||||
struct notifier {
|
||||
notifier handler;
|
||||
unsigned long id;
|
||||
char *notification;
|
||||
widget *w;
|
||||
void *private;
|
||||
/* done is used bu gui_notify */
|
||||
int done;
|
||||
};
|
||||
|
||||
/*************************************************************************/
|
||||
/* main structure */
|
||||
/*************************************************************************/
|
||||
|
||||
struct gui {
|
||||
void *lock;
|
||||
void *x; /* opaque X data (type x_connection), used in x.c */
|
||||
struct widget_list *toplevel;
|
||||
struct event_list *queued_events;
|
||||
int event_pipe[2];
|
||||
int next_id; /* tells what is the ID of
|
||||
the next created widget */
|
||||
int repainted; /* set to 1 when some widget has
|
||||
* been repainted (TODO: can be any,
|
||||
* to be optimized) */
|
||||
void *xwin; /* set by a toplevel_window when
|
||||
* it paints itself, to be used
|
||||
* by its children */
|
||||
struct notifier *notifiers;
|
||||
int notifiers_count;
|
||||
unsigned long next_notifier_id;
|
||||
};
|
||||
|
||||
/*************************************************************************/
|
||||
/* internal functions */
|
||||
/*************************************************************************/
|
||||
|
||||
widget *new_widget(struct gui *g, enum widget_type type, int size);
|
||||
void widget_add_child_internal(
|
||||
gui *_gui, widget *parent, widget *child, int position);
|
||||
void widget_del_child_internal(gui *_gui, widget *parent, widget *child);
|
||||
int widget_get_child_position(gui *_gui, widget *parent, widget *child);
|
||||
|
||||
const char *widget_name(enum widget_type type);
|
||||
|
||||
void send_event(gui *gui, enum event_type type, ...);
|
||||
void gui_events(gui *gui);
|
||||
|
||||
struct widget *find_widget(struct gui *g, int id);
|
||||
|
||||
void gui_notify(struct gui *g, char *notification, widget *w,
|
||||
void *notification_data);
|
||||
|
||||
#endif /* _GUI_DEFS_H_ */
|
||||
@@ -0,0 +1,114 @@
|
||||
#include "gui.h"
|
||||
#include "gui_defs.h"
|
||||
#include "x.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <png.h>
|
||||
|
||||
static void paint(gui *_gui, widget *_w)
|
||||
{
|
||||
struct gui *g = _gui;
|
||||
struct image_widget *w = _w;
|
||||
LOGD("PAINT image %p\n", w);
|
||||
x_draw_image(g->x, g->xwin, w->x, w->common.x, w->common.y);
|
||||
}
|
||||
|
||||
static void hints(gui *_gui, widget *_w, int *width, int *height)
|
||||
{
|
||||
struct image_widget *w = _w;
|
||||
LOGD("HINTS image %p\n", w);
|
||||
*width = w->width;
|
||||
*height = w->height;
|
||||
}
|
||||
|
||||
struct png_reader {
|
||||
unsigned char *data;
|
||||
int size;
|
||||
int pos;
|
||||
};
|
||||
|
||||
static void png_readfn(png_structp png_ptr, png_bytep data, png_size_t length)
|
||||
{
|
||||
struct png_reader *r = png_get_io_ptr(png_ptr);
|
||||
if (length > r->size - r->pos) png_error(png_ptr, "bad png image");
|
||||
memcpy(data, r->data + r->pos, length);
|
||||
r->pos += length;
|
||||
}
|
||||
|
||||
static void load_image(struct gui *g, struct image_widget *w,
|
||||
unsigned char *data, int length)
|
||||
{
|
||||
png_structp png_ptr;
|
||||
png_infop info_ptr;
|
||||
png_bytepp image;
|
||||
int width, height, bit_depth, color_type, channels;
|
||||
unsigned char *img_data;
|
||||
struct png_reader r;
|
||||
int i;
|
||||
|
||||
/* unpack PNG data */
|
||||
|
||||
r.data = data;
|
||||
r.size = length;
|
||||
r.pos = 0;
|
||||
|
||||
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
||||
if (png_ptr == NULL) abort();
|
||||
|
||||
info_ptr = png_create_info_struct(png_ptr);
|
||||
if (info_ptr == NULL) abort();
|
||||
|
||||
if (setjmp(png_jmpbuf(png_ptr))) abort();
|
||||
|
||||
png_set_read_fn(png_ptr, &r, png_readfn);
|
||||
|
||||
png_read_png(png_ptr, info_ptr,
|
||||
PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_EXPAND | PNG_TRANSFORM_PACKING |
|
||||
PNG_TRANSFORM_GRAY_TO_RGB | PNG_TRANSFORM_BGR, NULL);
|
||||
|
||||
image = png_get_rows(png_ptr, info_ptr);
|
||||
|
||||
width = png_get_image_width(png_ptr, info_ptr);
|
||||
height = png_get_image_height(png_ptr, info_ptr);
|
||||
bit_depth = png_get_bit_depth(png_ptr, info_ptr);
|
||||
color_type = png_get_color_type(png_ptr, info_ptr);
|
||||
channels = png_get_channels(png_ptr, info_ptr);
|
||||
|
||||
if (width < 1 || width > 1000 || height < 1 || height > 1000 ||
|
||||
bit_depth != 8 || color_type != PNG_COLOR_TYPE_RGBA || channels != 4)
|
||||
{ printf("bad image\n"); abort(); }
|
||||
|
||||
img_data = malloc(4 * width * height); if (img_data == NULL) abort();
|
||||
for (i = 0; i < height; i++)
|
||||
memcpy(img_data+i*4*width, image[i], width*4);
|
||||
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||
|
||||
/* create the X image */
|
||||
w->x = x_create_image(g->x, img_data, width, height);
|
||||
|
||||
free(img_data);
|
||||
|
||||
w->width = width;
|
||||
w->height = height;
|
||||
}
|
||||
|
||||
widget *new_image(gui *_gui, unsigned char *data, int length)
|
||||
{
|
||||
struct gui *g = _gui;
|
||||
struct image_widget *w;
|
||||
|
||||
glock(g);
|
||||
|
||||
w = new_widget(g, IMAGE, sizeof(struct image_widget));
|
||||
|
||||
load_image(g, w, data, length);
|
||||
|
||||
w->common.paint = paint;
|
||||
w->common.hints = hints;
|
||||
|
||||
gunlock(g);
|
||||
|
||||
return w;
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
#include "gui.h"
|
||||
#include "gui_defs.h"
|
||||
#include "x.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
gui *gui_init(void)
|
||||
{
|
||||
struct gui *ret;
|
||||
|
||||
ret = calloc(1, sizeof(struct gui));
|
||||
if (ret == NULL) OOM;
|
||||
|
||||
ret->lock = malloc(sizeof(pthread_mutex_t));
|
||||
if (ret->lock == NULL) OOM;
|
||||
if (pthread_mutex_init(ret->lock, NULL))
|
||||
ERR("mutex initialization failed\n");
|
||||
|
||||
if (pipe(ret->event_pipe))
|
||||
ERR("%s\n", strerror(errno));
|
||||
|
||||
/* lock not necessary but there for consistency (when instrumenting x.c
|
||||
* we need the gui to be locked when calling any function in x.c)
|
||||
*/
|
||||
glock(ret);
|
||||
ret->x = x_open();
|
||||
gunlock(ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
#include "gui.h"
|
||||
#include "gui_defs.h"
|
||||
#include "x.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
static void paint(gui *_gui, widget *_w)
|
||||
{
|
||||
struct gui *g = _gui;
|
||||
struct label_widget *l = _w;
|
||||
LOGD("PAINT label '%s'\n", l->t);
|
||||
x_draw_string(g->x, g->xwin, DEFAULT_FONT, l->color,
|
||||
l->common.x, l->common.y + l->baseline, l->t);
|
||||
}
|
||||
|
||||
static void hints(gui *_gui, widget *_w, int *width, int *height)
|
||||
{
|
||||
struct label_widget *l = _w;
|
||||
LOGD("HINTS label '%s'\n", l->t);
|
||||
*width = l->width;
|
||||
*height = l->height;
|
||||
}
|
||||
|
||||
widget *new_label(gui *_gui, const char *label)
|
||||
{
|
||||
struct gui *g = _gui;
|
||||
struct label_widget *w;
|
||||
|
||||
glock(g);
|
||||
|
||||
w = new_widget(g, LABEL, sizeof(struct label_widget));
|
||||
|
||||
w->t = strdup(label);
|
||||
if (w->t == NULL) OOM;
|
||||
w->color = FOREGROUND_COLOR;
|
||||
|
||||
x_text_get_dimensions(g->x, DEFAULT_FONT, label,
|
||||
&w->width, &w->height, &w->baseline);
|
||||
|
||||
w->common.paint = paint;
|
||||
w->common.hints = hints;
|
||||
|
||||
gunlock(g);
|
||||
|
||||
return w;
|
||||
}
|
||||
|
||||
static void button(gui *gui, widget *_this, int x, int y,
|
||||
int key_modifiers, int button, int up)
|
||||
{
|
||||
LOGD("BUTTON label %p xy %d %d button %d up %d\n", _this, x, y, button, up);
|
||||
|
||||
if (up != 0) return;
|
||||
|
||||
gui_notify(gui, "click", _this, &button);
|
||||
}
|
||||
|
||||
/* we could use default_button, but it's in widget.c, so, well... */
|
||||
static void no_button(gui *gui, widget *_this, int x, int y,
|
||||
int key_modifiers, int button, int up)
|
||||
{
|
||||
/* do nothing */
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/* public functions */
|
||||
/*************************************************************************/
|
||||
|
||||
void label_set_clickable(gui *_g, widget *_this, int clickable)
|
||||
{
|
||||
struct gui *g = _g;
|
||||
struct label_widget *this = _this;
|
||||
|
||||
glock(g);
|
||||
|
||||
if (clickable)
|
||||
this->common.button = button;
|
||||
else
|
||||
this->common.button = no_button;
|
||||
|
||||
gunlock(g);
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
#include "gui.h"
|
||||
#include "gui_defs.h"
|
||||
#include "x.h"
|
||||
#include <sys/select.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
void gui_loop(gui *_gui)
|
||||
{
|
||||
struct gui *g = _gui;
|
||||
int xfd;
|
||||
int eventfd;
|
||||
int maxfd;
|
||||
fd_set rd;
|
||||
|
||||
/* lock not necessary but there for consistency (when instrumenting x.c
|
||||
* we need the gui to be locked when calling any function in x.c)
|
||||
*/
|
||||
glock(g);
|
||||
xfd = x_connection_fd(g->x);
|
||||
gunlock(g);
|
||||
eventfd = g->event_pipe[0];
|
||||
|
||||
if (eventfd > xfd) maxfd = eventfd;
|
||||
else maxfd = xfd;
|
||||
|
||||
while (1) {
|
||||
glock(g);
|
||||
x_flush(g->x);
|
||||
gunlock(g);
|
||||
FD_ZERO(&rd);
|
||||
FD_SET(xfd, &rd);
|
||||
FD_SET(eventfd, &rd);
|
||||
if (select(maxfd+1, &rd, NULL, NULL, NULL) == -1)
|
||||
ERR("select: %s\n", strerror(errno));
|
||||
|
||||
glock(g);
|
||||
|
||||
if (FD_ISSET(xfd, &rd))
|
||||
x_events(g);
|
||||
|
||||
if (FD_ISSET(eventfd, &rd)) {
|
||||
char c[256];
|
||||
if (read(eventfd, c, 256)); /* for no gcc warnings */
|
||||
}
|
||||
|
||||
gui_events(g);
|
||||
|
||||
if (g->repainted) {
|
||||
struct widget_list *cur;
|
||||
g->repainted = 0;
|
||||
cur = g->toplevel;
|
||||
while (cur) {
|
||||
struct toplevel_window_widget *w =
|
||||
(struct toplevel_window_widget *)cur->item;
|
||||
x_draw(g->x, w->x);
|
||||
cur = cur->next;
|
||||
}
|
||||
}
|
||||
|
||||
gunlock(g);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
#include "gui.h"
|
||||
#include "gui_defs.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
unsigned long register_notifier(gui *_g, char *notification, widget *w,
|
||||
notifier handler, void *private)
|
||||
{
|
||||
struct gui *g = _g;
|
||||
unsigned long ret;
|
||||
|
||||
glock(g);
|
||||
|
||||
if (g->next_notifier_id == 2UL * 1024 * 1024 * 1024)
|
||||
ERR("%s:%d: report a bug\n", __FILE__, __LINE__);
|
||||
|
||||
g->notifiers = realloc(g->notifiers,
|
||||
(g->notifiers_count+1) * sizeof(struct notifier));
|
||||
if (g->notifiers == NULL) abort();
|
||||
|
||||
ret = g->next_notifier_id;
|
||||
|
||||
g->notifiers[g->notifiers_count].handler = handler;
|
||||
g->notifiers[g->notifiers_count].id = g->next_notifier_id;
|
||||
g->next_notifier_id++;
|
||||
g->notifiers[g->notifiers_count].notification = strdup(notification);
|
||||
if (g->notifiers[g->notifiers_count].notification == NULL) abort();
|
||||
g->notifiers[g->notifiers_count].w = w;
|
||||
g->notifiers[g->notifiers_count].private = private;
|
||||
/* initialize done to 1 so as not to call the handler if it's created
|
||||
* by the call of another one that is in progress
|
||||
*/
|
||||
g->notifiers[g->notifiers_count].done = 1;
|
||||
|
||||
g->notifiers_count++;
|
||||
|
||||
gunlock(g);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void unregister_notifier(gui *_g, unsigned long notifier_id)
|
||||
{
|
||||
struct gui *g = _g;
|
||||
int i;
|
||||
|
||||
glock(g);
|
||||
|
||||
for (i = 0; i < g->notifiers_count; i++)
|
||||
if (g->notifiers[i].id == notifier_id) break;
|
||||
|
||||
if (i == g->notifiers_count)
|
||||
ERR("%s:%d: notifier_id %ld not found\n", __FILE__,__LINE__,notifier_id);
|
||||
|
||||
free(g->notifiers[i].notification);
|
||||
|
||||
memmove(g->notifiers + i, g->notifiers + i + 1,
|
||||
(g->notifiers_count-1 - i) * sizeof(struct notifier));
|
||||
|
||||
g->notifiers_count--;
|
||||
g->notifiers = realloc(g->notifiers,
|
||||
g->notifiers_count * sizeof(struct notifier));
|
||||
if (g->notifiers == NULL) abort();
|
||||
|
||||
gunlock(g);
|
||||
}
|
||||
|
||||
/* called with lock ON */
|
||||
void gui_notify(struct gui *g, char *notification, widget *w,
|
||||
void *notification_data)
|
||||
{
|
||||
void *private;
|
||||
notifier handler;
|
||||
int i;
|
||||
|
||||
/* this function is not re-entrant, for the moment keep as is
|
||||
* and if the need is there, we'll make a new thread to handle
|
||||
* notifications (or something)
|
||||
* for now let's crash in case of recursive call
|
||||
*/
|
||||
static int inside = 0;
|
||||
if (inside) ERR("%s:%d: BUG! contact the authors\n", __FILE__, __LINE__);
|
||||
inside = 1;
|
||||
|
||||
/* clear all handlers */
|
||||
/* TODO: speedup */
|
||||
for (i = 0; i < g->notifiers_count; i++) g->notifiers[i].done = 0;
|
||||
|
||||
/* calling the handler may modify the list of notifiers, we
|
||||
* need to be careful here
|
||||
*/
|
||||
loop:
|
||||
for (i = 0; i < g->notifiers_count; i++) {
|
||||
if (g->notifiers[i].done == 1 ||
|
||||
g->notifiers[i].w != w ||
|
||||
strcmp(g->notifiers[i].notification, notification) != 0)
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
if (i == g->notifiers_count) goto done;
|
||||
|
||||
g->notifiers[i].done = 1;
|
||||
|
||||
handler = g->notifiers[i].handler;
|
||||
private = g->notifiers[i].private;
|
||||
|
||||
gunlock(g);
|
||||
handler(private, g, notification, w, notification_data);
|
||||
glock(g);
|
||||
|
||||
goto loop;
|
||||
|
||||
done:
|
||||
inside = 0;
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
#include "gui.h"
|
||||
#include "gui_defs.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
static void add_child(gui *g, widget *_this, widget *child, int position)
|
||||
{
|
||||
LOGD("ADD_CHILD positioner\n");
|
||||
struct positioner_widget *this = _this;
|
||||
widget_add_child_internal(g, this, child, position);
|
||||
}
|
||||
|
||||
static void del_child(gui *g, widget *_this, widget *child)
|
||||
{
|
||||
LOGD("DEL_CHILD positioner\n");
|
||||
struct positioner_widget *this = _this;
|
||||
widget_del_child_internal(g, this, child);
|
||||
}
|
||||
|
||||
static void allocate(
|
||||
gui *_g, widget *_this, int x, int y, int width, int height)
|
||||
{
|
||||
LOGD("ALLOCATE positioner %p\n", _this);
|
||||
struct gui *g = _g;
|
||||
struct positioner_widget *this = _this;
|
||||
struct widget_list *l = this->common.children;
|
||||
int cwidth, cheight;
|
||||
|
||||
this->common.x = x;
|
||||
this->common.y = y;
|
||||
this->common.width = width;
|
||||
this->common.height = height;
|
||||
|
||||
if (l != NULL) {
|
||||
l->item->hints(g, l->item, &cwidth, &cheight);
|
||||
l->item->allocate(g, l->item, x+(width-cwidth)/2, y+(height-cheight)/2,
|
||||
cwidth, cheight);
|
||||
}
|
||||
}
|
||||
|
||||
static void hints(gui *_gui, widget *_w, int *width, int *height)
|
||||
{
|
||||
LOGD("HINTS positioner %p\n", _w);
|
||||
struct gui *g = _gui;
|
||||
struct positioner_widget *this = _w;
|
||||
struct widget_list *l = this->common.children;
|
||||
if (l != NULL)
|
||||
l->item->hints(g, l->item, width, height);
|
||||
else { *width = *height = 1; }
|
||||
}
|
||||
|
||||
static void button(gui *_g, widget *_this, int x, int y,
|
||||
int key_modifiers, int button, int up)
|
||||
{
|
||||
LOGD("BUTTON positioner %p xy %d %d button %d up %d\n", _this, x, y, button, up);
|
||||
struct gui *g = _g;
|
||||
struct positioner_widget *this = _this;
|
||||
struct widget_list *l = this->common.children;
|
||||
if (l != NULL)
|
||||
l->item->button(g, l->item, x, y, key_modifiers, button, up);
|
||||
}
|
||||
|
||||
static void paint(gui *_gui, widget *_this)
|
||||
{
|
||||
LOGD("PAINT positioner\n");
|
||||
struct gui *g = _gui;
|
||||
struct widget *this = _this;
|
||||
struct widget_list *l = this->children;
|
||||
if (l != NULL)
|
||||
l->item->paint(g, l->item);
|
||||
}
|
||||
|
||||
widget *new_positioner(gui *_gui)
|
||||
{
|
||||
struct gui *g = _gui;
|
||||
struct positioner_widget *w;
|
||||
|
||||
glock(g);
|
||||
|
||||
w = new_widget(g, POSITIONER, sizeof(struct positioner_widget));
|
||||
|
||||
w->common.paint = paint;
|
||||
w->common.add_child = add_child;
|
||||
w->common.del_child = del_child;
|
||||
w->common.allocate = allocate;
|
||||
w->common.hints = hints;
|
||||
w->common.button = button;
|
||||
|
||||
gunlock(g);
|
||||
|
||||
return w;
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
#include "gui.h"
|
||||
#include "gui_defs.h"
|
||||
#include <stdio.h>
|
||||
|
||||
static void paint(gui *_gui, widget *_w)
|
||||
{
|
||||
/* nothing */
|
||||
}
|
||||
|
||||
static void hints(gui *_gui, widget *_w, int *width, int *height)
|
||||
{
|
||||
struct space_widget *w = _w;
|
||||
LOGD("HINTS space %p\n", w);
|
||||
*width = w->wanted_width;
|
||||
*height = w->wanted_height;
|
||||
}
|
||||
|
||||
widget *new_space(gui *_gui, int width, int height)
|
||||
{
|
||||
struct gui *g = _gui;
|
||||
struct space_widget *w;
|
||||
|
||||
glock(g);
|
||||
|
||||
w = new_widget(g, SPACE, sizeof(struct space_widget));
|
||||
|
||||
w->wanted_width = width;
|
||||
w->wanted_height = height;
|
||||
|
||||
w->common.paint = paint;
|
||||
w->common.hints = hints;
|
||||
|
||||
gunlock(g);
|
||||
|
||||
return w;
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
#include "gui.h"
|
||||
|
||||
int main(void)
|
||||
{
|
||||
gui *g;
|
||||
widget *w, *c1, *c2, *l, *plot, *tl;
|
||||
int tlcol;
|
||||
|
||||
g = gui_init();
|
||||
|
||||
c1 = new_container(g, VERTICAL);
|
||||
c2 = new_container(g, HORIZONTAL);
|
||||
|
||||
l = new_label(g, "this is a good label");
|
||||
widget_add_child(g, c2, l, 0);
|
||||
l = new_label(g, "this is another good label");
|
||||
widget_add_child(g, c2, l, -1);
|
||||
|
||||
l = new_label(g, "OH! WHAT A LABEL!");
|
||||
widget_add_child(g, c1, l, -1);
|
||||
|
||||
widget_add_child(g, c1, c2, 0);
|
||||
|
||||
plot = new_xy_plot(g, 100, 100, "xy plot test", 30);
|
||||
#if 0
|
||||
c2 = new_container(g, HORIZONTAL);
|
||||
widget_add_child(g, c2, plot, -1);
|
||||
widget_add_child(g, c1, c2, -1);
|
||||
#else
|
||||
widget_add_child(g, c1, plot, -1);
|
||||
#endif
|
||||
|
||||
tlcol = new_color(g, "#ddf");
|
||||
tl = new_textlist(g, 300, 10, tlcol);
|
||||
widget_add_child(g, c1, tl, -1);
|
||||
|
||||
textlist_add(g, tl, "hello", -1, FOREGROUND_COLOR);
|
||||
textlist_add(g, tl, "world", -1, FOREGROUND_COLOR);
|
||||
|
||||
w = new_toplevel_window(g, 500, 400, "test window");
|
||||
widget_add_child(g, w, c1, 0);
|
||||
|
||||
gui_loop(g);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,248 @@
|
||||
#include "gui.h"
|
||||
#include "gui_defs.h"
|
||||
#include "x.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
static void paint(gui *_gui, widget *_this)
|
||||
{
|
||||
struct gui *g = _gui;
|
||||
struct textlist_widget *this = _this;
|
||||
int i, j;
|
||||
LOGD("PAINT textlist %p xywh %d %d %d %d starting line %d allocated nlines %d text_count %d\n", _this, this->common.x, this->common.y, this->common.width, this->common.height, this->starting_line, this->allocated_nlines, this->text_count);
|
||||
x_fill_rectangle(g->x, g->xwin, this->background_color,
|
||||
this->common.x, this->common.y,
|
||||
this->common.width, this->common.height);
|
||||
for (i = 0, j = this->starting_line;
|
||||
i < this->allocated_nlines && j < this->text_count; i++, j++)
|
||||
x_draw_clipped_string(g->x, g->xwin, DEFAULT_FONT, this->color[j],
|
||||
this->common.x,
|
||||
this->common.y + i * this->line_height + this->baseline,
|
||||
this->text[j],
|
||||
this->common.x, this->common.y,
|
||||
this->common.width, this->common.height);
|
||||
}
|
||||
|
||||
static void hints(gui *_gui, widget *_w, int *width, int *height)
|
||||
{
|
||||
struct textlist_widget *w = _w;
|
||||
*width = w->wanted_width;
|
||||
*height = w->wanted_nlines * w->line_height;
|
||||
LOGD("HINTS textlist wh %d %d\n", *width, *height);
|
||||
}
|
||||
|
||||
static void allocate(
|
||||
gui *gui, widget *_this, int x, int y, int width, int height)
|
||||
{
|
||||
struct textlist_widget *this = _this;
|
||||
this->common.x = x;
|
||||
this->common.y = y;
|
||||
this->common.width = width;
|
||||
this->common.height = height;
|
||||
this->allocated_nlines = height / this->line_height;
|
||||
LOGD("ALLOCATE textlist %p xywh %d %d %d %d nlines %d\n", this, x, y, width, height, this->allocated_nlines);
|
||||
}
|
||||
|
||||
static void button(gui *_g, widget *_this, int x, int y,
|
||||
int key_modifiers, int button, int up)
|
||||
{
|
||||
struct gui *g = _g;
|
||||
struct textlist_widget *this = _this;
|
||||
LOGD("BUTTON textlist %p xy %d %d button %d up %d\n", _this, x, y, button, up);
|
||||
y -= this->common.y;
|
||||
x -= this->common.x;
|
||||
/* scroll up */
|
||||
if (button == 4 && up == 0) {
|
||||
gui_notify(g, "scrollup", _this, NULL);
|
||||
}
|
||||
/* scroll down */
|
||||
if (button == 5 && up == 0) {
|
||||
gui_notify(g, "scrolldown", _this, NULL);
|
||||
}
|
||||
/* button 1/2/3 click */
|
||||
if (button >= 1 && button <= 3 && up == 0) {
|
||||
int line = this->starting_line + y / this->line_height;
|
||||
if (line >= 0 && line < this->text_count)
|
||||
gui_notify(g, "click", _this, (int[2]){ line, button });
|
||||
}
|
||||
}
|
||||
|
||||
widget *new_textlist(gui *_gui, int width, int nlines, int bgcol)
|
||||
{
|
||||
struct gui *g = _gui;
|
||||
struct textlist_widget *w;
|
||||
int dummy;
|
||||
|
||||
glock(g);
|
||||
|
||||
w = new_widget(g, TEXT_LIST, sizeof(struct textlist_widget));
|
||||
|
||||
w->wanted_nlines = nlines;
|
||||
x_text_get_dimensions(g->x, DEFAULT_FONT, ".",
|
||||
&dummy, &w->line_height, &w->baseline);
|
||||
w->background_color = bgcol;
|
||||
w->wanted_width = width;
|
||||
|
||||
w->common.paint = paint;
|
||||
w->common.hints = hints;
|
||||
w->common.allocate = allocate;
|
||||
|
||||
w->common.button = button;
|
||||
|
||||
gunlock(g);
|
||||
|
||||
return w;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/* public functions */
|
||||
/*************************************************************************/
|
||||
|
||||
static void _textlist_add(gui *_gui, widget *_this, const char *text,
|
||||
int position, int color, int silent)
|
||||
{
|
||||
struct gui *g = _gui;
|
||||
struct textlist_widget *this = _this;
|
||||
|
||||
glock(g);
|
||||
|
||||
if (position < 0) position = this->text_count;
|
||||
if (position > this->text_count) position = this->text_count;
|
||||
|
||||
this->text_count++;
|
||||
this->text = realloc(this->text, this->text_count * sizeof(char *));
|
||||
if (this->text == NULL) OOM;
|
||||
this->color = realloc(this->color, this->text_count * sizeof(int));
|
||||
if (this->color == NULL) OOM;
|
||||
|
||||
memmove(this->text + position + 1, this->text + position,
|
||||
(this->text_count-1 - position) * sizeof(char *));
|
||||
memmove(this->color + position + 1, this->color + position,
|
||||
(this->text_count-1 - position) * sizeof(int));
|
||||
|
||||
this->text[position] = strdup(text); if (this->text[position] == NULL) OOM;
|
||||
this->color[position] = color;
|
||||
|
||||
if (!silent) send_event(g, DIRTY, this->common.id);
|
||||
|
||||
gunlock(g);
|
||||
}
|
||||
|
||||
static void _textlist_del(gui *_gui, widget *_this, int position, int silent)
|
||||
{
|
||||
struct gui *g = _gui;
|
||||
struct textlist_widget *this = _this;
|
||||
|
||||
glock(g);
|
||||
|
||||
/* TODO: useful check? */
|
||||
if (this->text_count == 0) goto done;
|
||||
|
||||
if (position < 0) position = this->text_count;
|
||||
if (position > this->text_count-1) position = this->text_count-1;
|
||||
|
||||
free(this->text[position]);
|
||||
|
||||
memmove(this->text + position, this->text + position + 1,
|
||||
(this->text_count-1 - position) * sizeof(char *));
|
||||
memmove(this->color + position, this->color + position + 1,
|
||||
(this->text_count-1 - position) * sizeof(int));
|
||||
|
||||
this->text_count--;
|
||||
this->text = realloc(this->text, this->text_count * sizeof(char *));
|
||||
if (this->text == NULL) OOM;
|
||||
this->color = realloc(this->color, this->text_count * sizeof(int));
|
||||
if (this->color == NULL) OOM;
|
||||
|
||||
if (!silent) send_event(g, DIRTY, this->common.id);
|
||||
|
||||
done:
|
||||
gunlock(g);
|
||||
}
|
||||
|
||||
void textlist_add(gui *gui, widget *this, const char *text, int position,
|
||||
int color)
|
||||
{
|
||||
_textlist_add(gui, this, text, position, color, 0);
|
||||
}
|
||||
|
||||
void textlist_del(gui *gui, widget *this, int position)
|
||||
{
|
||||
_textlist_del(gui, this, position, 0);
|
||||
}
|
||||
|
||||
void textlist_add_silent(gui *gui, widget *this, const char *text,
|
||||
int position, int color)
|
||||
{
|
||||
_textlist_add(gui, this, text, position, color, 1);
|
||||
}
|
||||
|
||||
void textlist_del_silent(gui *gui, widget *this, int position)
|
||||
{
|
||||
_textlist_del(gui, this, position, 1);
|
||||
}
|
||||
|
||||
void textlist_state(gui *_gui, widget *_this,
|
||||
int *visible_lines, int *start_line, int *number_of_lines)
|
||||
{
|
||||
struct gui *g = _gui;
|
||||
struct textlist_widget *this = _this;
|
||||
|
||||
glock(g);
|
||||
|
||||
*visible_lines = this->allocated_nlines;
|
||||
*start_line = this->starting_line;
|
||||
*number_of_lines = this->text_count;
|
||||
|
||||
gunlock(g);
|
||||
}
|
||||
|
||||
void textlist_set_start_line(gui *_gui, widget *_this, int line)
|
||||
{
|
||||
struct gui *g = _gui;
|
||||
struct textlist_widget *this = _this;
|
||||
|
||||
glock(g);
|
||||
|
||||
this->starting_line = line;
|
||||
|
||||
send_event(g, DIRTY, this->common.id);
|
||||
|
||||
gunlock(g);
|
||||
}
|
||||
|
||||
void textlist_get_line(gui *_gui, widget *_this, int line,
|
||||
char **text, int *color)
|
||||
{
|
||||
struct gui *g = _gui;
|
||||
struct textlist_widget *this = _this;
|
||||
|
||||
glock(g);
|
||||
|
||||
if (line < 0 || line >= this->text_count) {
|
||||
*text = NULL;
|
||||
*color = -1;
|
||||
} else {
|
||||
*text = this->text[line];
|
||||
*color = this->color[line];
|
||||
}
|
||||
|
||||
gunlock(g);
|
||||
}
|
||||
|
||||
void textlist_set_color(gui *_gui, widget *_this, int line, int color)
|
||||
{
|
||||
struct gui *g = _gui;
|
||||
struct textlist_widget *this = _this;
|
||||
|
||||
glock(g);
|
||||
|
||||
if (line >= 0 && line < this->text_count) {
|
||||
this->color[line] = color;
|
||||
|
||||
send_event(g, DIRTY, this->common.id);
|
||||
}
|
||||
|
||||
gunlock(g);
|
||||
}
|
||||
@@ -0,0 +1,214 @@
|
||||
#include "gui.h"
|
||||
#include "gui_defs.h"
|
||||
#include "x.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static void paint(gui *_gui, widget *_this)
|
||||
{
|
||||
struct gui *g = _gui;
|
||||
struct timeline_widget *this = _this;
|
||||
int i;
|
||||
int j;
|
||||
|
||||
for (i = 0; i < this->n; i++) {
|
||||
x_fill_rectangle(g->x, g->xwin, this->s[i].background,
|
||||
this->common.x, this->common.y + i * this->subline_height,
|
||||
this->common.width, this->subline_height);
|
||||
for (j = 0; j < this->s[i].width; j++)
|
||||
if (this->s[i].color[j] != -1)
|
||||
x_draw_line(g->x, g->xwin, this->s[i].color[j],
|
||||
this->common.x + j, this->common.y + i * this->subline_height,
|
||||
this->common.x + j, this->common.y + this->subline_height -1
|
||||
+ i * this->subline_height);
|
||||
}
|
||||
|
||||
LOGD("PAINT timeline xywh %d %d %d %d\n", this->common.x, this->common.y, this->common.width, this->common.height);
|
||||
}
|
||||
|
||||
static void hints(gui *_gui, widget *_w, int *width, int *height)
|
||||
{
|
||||
struct timeline_widget *w = _w;
|
||||
*width = w->wanted_width;
|
||||
*height = w->n * w->subline_height;
|
||||
LOGD("HINTS timeline wh %d %d\n", *width, *height);
|
||||
}
|
||||
|
||||
static void allocate(gui *_gui, widget *_this,
|
||||
int x, int y, int width, int height)
|
||||
{
|
||||
struct timeline_widget *this = _this;
|
||||
int i;
|
||||
int j;
|
||||
this->common.x = x;
|
||||
this->common.y = y;
|
||||
this->common.width = width;
|
||||
this->common.height = height;
|
||||
LOGD("ALLOCATE timeline %p xywh %d %d %d %d\n", this, x, y, width, height);
|
||||
for (i = 0; i < this->n; i++) {
|
||||
this->s[i].width = width;
|
||||
this->s[i].color = realloc(this->s[i].color, width * sizeof(int));
|
||||
if (this->s[i].color == NULL) abort();
|
||||
for (j = 0; j < width; j++) this->s[i].color[j] = -1;
|
||||
}
|
||||
gui_notify(_gui, "resize", _this, &width);
|
||||
}
|
||||
|
||||
static void button(gui *_g, widget *_this, int x, int y,
|
||||
int key_modifiers, int button, int up)
|
||||
{
|
||||
struct gui *g = _g;
|
||||
struct timeline_widget *w = _this;
|
||||
int d[3];
|
||||
LOGD("BUTTON timeline %p xy %d %d button %d up %d\n", _this, x, y, button, up);
|
||||
/* scroll up */
|
||||
if (button == 4 && up == 0) {
|
||||
d[0] = x - w->common.x;
|
||||
d[1] = y - w->common.y;
|
||||
d[2] = key_modifiers;
|
||||
gui_notify(g, "scrollup", _this, d);
|
||||
}
|
||||
/* scroll down */
|
||||
if (button == 5 && up == 0) {
|
||||
d[0] = x - w->common.x;
|
||||
d[1] = y - w->common.y;
|
||||
d[2] = key_modifiers;
|
||||
gui_notify(g, "scrolldown", _this, d);
|
||||
}
|
||||
/* button 1/2/3 */
|
||||
if ((button == 1 || button == 2 || button == 3) && up == 0) {
|
||||
gui_notify(g, "click", _this, &button);
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/* creation function */
|
||||
/*************************************************************************/
|
||||
|
||||
widget *new_timeline(gui *_gui, int width, int number_of_sublines,
|
||||
int subline_height)
|
||||
{
|
||||
struct gui *g = _gui;
|
||||
struct timeline_widget *w;
|
||||
int i;
|
||||
int j;
|
||||
|
||||
glock(g);
|
||||
|
||||
w = new_widget(g, TIMELINE, sizeof(struct timeline_widget));
|
||||
|
||||
w->wanted_width = width;
|
||||
w->n = number_of_sublines;
|
||||
w->s = calloc(w->n, sizeof(struct timeline_subline)); if (w->s == NULL) OOM;
|
||||
w->subline_height = subline_height;
|
||||
|
||||
/* initialize colors */
|
||||
for (i = 0; i < w->n; i++) {
|
||||
w->s[i].width = width;
|
||||
w->s[i].color = calloc(width, sizeof(int));
|
||||
if (w->s[i].color == NULL) abort();
|
||||
for (j = 0; j < width; j++) w->s[i].color[j] = -1;
|
||||
w->s[i].background = BACKGROUND_COLOR;
|
||||
}
|
||||
|
||||
w->common.paint = paint;
|
||||
w->common.hints = hints;
|
||||
w->common.allocate = allocate;
|
||||
w->common.button = button;
|
||||
|
||||
gunlock(g);
|
||||
|
||||
return w;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/* public functions */
|
||||
/*************************************************************************/
|
||||
|
||||
static void _timeline_clear(gui *_gui, widget *_this, int silent)
|
||||
{
|
||||
struct gui *g = _gui;
|
||||
struct timeline_widget *this = _this;
|
||||
int i;
|
||||
int j;
|
||||
|
||||
glock(g);
|
||||
|
||||
for (i = 0; i < this->n; i++)
|
||||
for (j = 0; j < this->s[i].width; j++)
|
||||
this->s[i].color[j] = -1;
|
||||
|
||||
if (silent == 0)
|
||||
send_event(g, DIRTY, this->common.id);
|
||||
|
||||
gunlock(g);
|
||||
}
|
||||
|
||||
void timeline_clear(gui *_gui, widget *_this)
|
||||
{
|
||||
_timeline_clear(_gui, _this, 0);
|
||||
}
|
||||
|
||||
void timeline_clear_silent(gui *_gui, widget *_this)
|
||||
{
|
||||
_timeline_clear(_gui, _this, 1);
|
||||
}
|
||||
|
||||
static void _timeline_add_points(gui *_gui, widget *_this, int subline,
|
||||
int color, int *x, int len, int silent)
|
||||
{
|
||||
struct gui *g = _gui;
|
||||
struct timeline_widget *this = _this;
|
||||
int i;
|
||||
|
||||
glock(g);
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
if (x[i] >= this->s[subline].width) { WARN("out of bounds\n"); continue; }
|
||||
this->s[subline].color[x[i]] = color;
|
||||
}
|
||||
|
||||
if (silent == 0)
|
||||
send_event(g, DIRTY, this->common.id);
|
||||
|
||||
gunlock(g);
|
||||
}
|
||||
|
||||
void timeline_add_points(gui *_gui, widget *_this, int subline, int color,
|
||||
int *x, int len)
|
||||
{
|
||||
_timeline_add_points(_gui, _this, subline, color, x, len, 0);
|
||||
}
|
||||
|
||||
void timeline_add_points_silent(gui *_gui, widget *_this, int subline,
|
||||
int color, int *x, int len)
|
||||
{
|
||||
_timeline_add_points(_gui, _this, subline, color, x, len, 1);
|
||||
}
|
||||
|
||||
void timeline_set_subline_background_color(gui *_gui, widget *_this,
|
||||
int subline, int color)
|
||||
{
|
||||
struct gui *g = _gui;
|
||||
struct timeline_widget *this = _this;
|
||||
|
||||
glock(g);
|
||||
|
||||
this->s[subline].background = color;
|
||||
|
||||
send_event(g, DIRTY, this->common.id);
|
||||
|
||||
gunlock(g);
|
||||
}
|
||||
|
||||
void timeline_get_width(gui *_gui, widget *_this, int *width)
|
||||
{
|
||||
struct gui *g = _gui;
|
||||
struct timeline_widget *this = _this;
|
||||
|
||||
glock(g);
|
||||
|
||||
*width = this->common.width == 0 ? this->wanted_width : this->common.width;
|
||||
|
||||
gunlock(g);
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
#include "gui.h"
|
||||
#include "gui_defs.h"
|
||||
#include "x.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/**********************************************************************/
|
||||
/* callback functions */
|
||||
/**********************************************************************/
|
||||
|
||||
static void repack(gui *g, widget *_this)
|
||||
{
|
||||
LOGD("REPACK toplevel_window\n");
|
||||
struct toplevel_window_widget *this = _this;
|
||||
if (this->common.children == NULL) ERR("toplevel window has no child\n");
|
||||
if (this->common.children->next != NULL)
|
||||
ERR("toplevel window has too much children\n");
|
||||
this->common.children->item->allocate(g, this->common.children->item,
|
||||
0 /* x */, 0 /* y */, this->common.width, this->common.height);
|
||||
send_event(g, DIRTY, this->common.id);
|
||||
}
|
||||
|
||||
static void add_child(gui *_gui, widget *_this, widget *child, int position)
|
||||
{
|
||||
LOGD("ADD_CHILD toplevel_window\n");
|
||||
struct widget *this = _this;
|
||||
if (this->children != NULL) {
|
||||
WARN("toplevel window already has a child\n");
|
||||
return;
|
||||
}
|
||||
widget_add_child_internal(_gui, _this, child, 0); /* this does the REPACK */
|
||||
}
|
||||
|
||||
/* called when the underlying window is resized by the user or the system */
|
||||
static void allocate(
|
||||
gui *_gui, widget *_this, int x, int y, int width, int height)
|
||||
{
|
||||
LOGD("ALLOCATE toplevel_window\n");
|
||||
struct toplevel_window_widget *this = _this;
|
||||
this->common.width = width;
|
||||
this->common.height = height;
|
||||
// repack(_gui, _this);
|
||||
send_event(_gui, REPACK, this->common.id);
|
||||
}
|
||||
|
||||
static void paint(gui *_gui, widget *_this)
|
||||
{
|
||||
struct gui *g = _gui;
|
||||
struct toplevel_window_widget *this = _this;
|
||||
LOGD("PAINT toplevel_window (%d %d)\n", this->common.width, this->common.height);
|
||||
x_fill_rectangle(g->x, this->x, BACKGROUND_COLOR,
|
||||
0, 0, this->common.width, this->common.height);
|
||||
g->xwin = this->x;
|
||||
this->common.children->item->paint(_gui, this->common.children->item);
|
||||
g->xwin = NULL; /* TODO: remove? it's just in case */
|
||||
}
|
||||
|
||||
static void button(gui *_g, widget *_this, int x, int y,
|
||||
int key_modifiers, int button, int up)
|
||||
{
|
||||
struct gui *g = _g;
|
||||
struct toplevel_window_widget *this = _this;
|
||||
g->xwin = this->x;
|
||||
this->common.children->item->button(_g, this->common.children->item,
|
||||
x, y, key_modifiers, button, up);
|
||||
g->xwin = NULL; /* TODO: remove? it's just in case */
|
||||
}
|
||||
|
||||
/**********************************************************************/
|
||||
/* creation */
|
||||
/**********************************************************************/
|
||||
|
||||
widget *new_toplevel_window(gui *_gui, int width, int height, char *title)
|
||||
{
|
||||
struct gui *g = _gui;
|
||||
struct toplevel_window_widget *w;
|
||||
|
||||
glock(g);
|
||||
|
||||
w = new_widget(g, TOPLEVEL_WINDOW, sizeof(struct toplevel_window_widget));
|
||||
|
||||
w->common.width = width;
|
||||
w->common.height = height;
|
||||
|
||||
w->x = x_create_window(g->x, width, height, title);
|
||||
|
||||
w->common.repack = repack;
|
||||
w->common.add_child = add_child;
|
||||
w->common.allocate = allocate;
|
||||
w->common.paint = paint;
|
||||
|
||||
w->common.button = button;
|
||||
|
||||
gunlock(g);
|
||||
|
||||
return w;
|
||||
}
|
||||
@@ -0,0 +1,322 @@
|
||||
#include "gui.h"
|
||||
#include "gui_defs.h"
|
||||
#include "x.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
||||
static void default_clear(gui *gui, widget *_this);
|
||||
static void default_repack(gui *gui, widget *_this);
|
||||
static void default_allocate(
|
||||
gui *gui, widget *_this, int x, int y, int width, int height);
|
||||
static void default_add_child(
|
||||
gui *_gui, widget *_this, widget *child, int position);
|
||||
static void default_del_child(gui *_gui, widget *_this, widget *child);
|
||||
static void default_hints(gui *g, widget *this, int *width, int *height);
|
||||
static void default_button(gui *gui, widget *_this, int x, int y,
|
||||
int key_modifiers, int button, int up);
|
||||
|
||||
static void toplevel_list_append(struct gui *g, struct widget *e)
|
||||
{
|
||||
struct widget_list *new;
|
||||
|
||||
new = calloc(1, sizeof(struct widget_list));
|
||||
if (new == NULL) OOM;
|
||||
|
||||
new->item = e;
|
||||
|
||||
if (g->toplevel == NULL) {
|
||||
g->toplevel = new;
|
||||
new->last = new;
|
||||
return;
|
||||
}
|
||||
|
||||
g->toplevel->last->next = new;
|
||||
g->toplevel->last = new;
|
||||
}
|
||||
|
||||
widget *new_widget(struct gui *g, enum widget_type type, int size)
|
||||
{
|
||||
struct widget *ret;
|
||||
|
||||
//glock(g);
|
||||
|
||||
ret = calloc(1, size);
|
||||
if (ret == NULL) OOM;
|
||||
|
||||
ret->clear = default_clear;
|
||||
ret->repack = default_repack;
|
||||
ret->add_child = default_add_child;
|
||||
ret->del_child = default_del_child;
|
||||
ret->allocate = default_allocate;
|
||||
ret->hints = default_hints;
|
||||
ret->button = default_button;
|
||||
/* there is no default paint, on purpose */
|
||||
|
||||
ret->type = type;
|
||||
ret->id = g->next_id;
|
||||
g->next_id++;
|
||||
ret->width = 0;
|
||||
ret->height = 0;
|
||||
|
||||
/* add toplevel windows to g->toplevel */
|
||||
if (type == TOPLEVEL_WINDOW)
|
||||
toplevel_list_append(g, ret);
|
||||
|
||||
//gunlock(g);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/* internal functions */
|
||||
/*************************************************************************/
|
||||
|
||||
void widget_add_child_internal(
|
||||
gui *_gui, widget *parent, widget *child, int position)
|
||||
{
|
||||
struct widget *p = parent;
|
||||
struct widget *c = child;
|
||||
struct widget_list *new;
|
||||
struct widget_list *prev, *cur;
|
||||
int i;
|
||||
|
||||
new = calloc(1, sizeof(struct widget_list));
|
||||
if (new == NULL) OOM;
|
||||
|
||||
new->item = c;
|
||||
c->parent = p;
|
||||
|
||||
prev = NULL;
|
||||
cur = p->children;
|
||||
|
||||
for (i = 0; position < 0 || i < position; i++) {
|
||||
if (cur == NULL) break;
|
||||
prev = cur;
|
||||
cur = cur->next;
|
||||
}
|
||||
|
||||
/* TODO: warn/err if i != position+1? */
|
||||
|
||||
if (prev == NULL) {
|
||||
/* new is at head */
|
||||
new->next = p->children;
|
||||
if (p->children != NULL) new->last = p->children->last;
|
||||
else new->last = new;
|
||||
p->children = new;
|
||||
goto repack;
|
||||
}
|
||||
|
||||
if (cur == NULL) {
|
||||
/* new is at tail */
|
||||
prev->next = new;
|
||||
p->children->last = new;
|
||||
goto repack;
|
||||
}
|
||||
|
||||
/* new is between two existing items */
|
||||
prev->next = new;
|
||||
new->next = cur;
|
||||
|
||||
repack:
|
||||
send_event(_gui, REPACK, p->id);
|
||||
}
|
||||
|
||||
void widget_del_child_internal(gui *_gui, widget *parent, widget *child)
|
||||
{
|
||||
struct widget *p = parent;
|
||||
struct widget *c = child;
|
||||
struct widget_list *prev, *cur;
|
||||
|
||||
c->parent = NULL;
|
||||
|
||||
prev = NULL;
|
||||
cur = p->children;
|
||||
|
||||
while (cur != NULL && cur->item != c) {
|
||||
prev = cur;
|
||||
cur = cur->next;
|
||||
}
|
||||
|
||||
if (cur == NULL) ERR("child not found\n");
|
||||
|
||||
if (prev == NULL) {
|
||||
/* child is at head */
|
||||
p->children = cur->next;
|
||||
if (p->children != NULL) p->children->last = cur->last;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (cur->next == NULL) {
|
||||
/* child is last (and prev is != NULL) */
|
||||
prev->next = NULL;
|
||||
p->children->last = prev;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* child is between two existing items */
|
||||
prev->next = cur->next;
|
||||
|
||||
done:
|
||||
free(cur);
|
||||
send_event(_gui, REPACK, p->id);
|
||||
}
|
||||
|
||||
int widget_get_child_position(gui *_gui, widget *parent, widget *child)
|
||||
{
|
||||
struct widget *p = parent;
|
||||
struct widget *c = child;
|
||||
struct widget_list *cur;
|
||||
int i = 0;
|
||||
|
||||
cur = p->children;
|
||||
|
||||
while (cur != NULL && cur->item != c) {
|
||||
cur = cur->next;
|
||||
i++;
|
||||
}
|
||||
|
||||
if (cur == NULL) return -1;
|
||||
return i;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/* default functions */
|
||||
/*************************************************************************/
|
||||
|
||||
static void default_clear(gui *_gui, widget *_this)
|
||||
{
|
||||
struct gui *g = _gui;
|
||||
struct widget *this = _this;
|
||||
x_fill_rectangle(g->x, g->xwin, BACKGROUND_COLOR,
|
||||
this->x, this->y, this->width, this->height);
|
||||
}
|
||||
|
||||
static void default_repack(gui *gui, widget *_this)
|
||||
{
|
||||
struct widget *this = _this;
|
||||
return this->parent->repack(gui, this->parent);
|
||||
}
|
||||
|
||||
static void default_add_child(
|
||||
gui *_gui, widget *_this, widget *child, int position)
|
||||
{
|
||||
struct widget *this = _this;
|
||||
WARN("cannot add child to widget %s\n", widget_name(this->type));
|
||||
}
|
||||
|
||||
static void default_del_child( gui *_gui, widget *_this, widget *child)
|
||||
{
|
||||
struct widget *this = _this;
|
||||
WARN("cannot del child from widget %s\n", widget_name(this->type));
|
||||
}
|
||||
|
||||
static void default_allocate(
|
||||
gui *gui, widget *_this, int x, int y, int width, int height)
|
||||
{
|
||||
struct widget *this = _this;
|
||||
this->x = x;
|
||||
this->y = y;
|
||||
this->width = width;
|
||||
this->height = height;
|
||||
}
|
||||
|
||||
static void default_hints(gui *g, widget *this, int *width, int *height)
|
||||
{
|
||||
*width = 1;
|
||||
*height = 1;
|
||||
}
|
||||
|
||||
static void default_button(gui *gui, widget *_this, int x, int y,
|
||||
int key_modifiers, int button, int up)
|
||||
{
|
||||
/* nothing */
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/* utils functions */
|
||||
/*************************************************************************/
|
||||
|
||||
void widget_add_child(gui *_gui, widget *parent, widget *child, int position)
|
||||
{
|
||||
struct widget *this = parent;
|
||||
glock(_gui);
|
||||
this->add_child(_gui, parent, child, position);
|
||||
gunlock(_gui);
|
||||
}
|
||||
|
||||
void widget_del_child(gui *_gui, widget *parent, widget *child)
|
||||
{
|
||||
struct widget *this = parent;
|
||||
glock(_gui);
|
||||
this->del_child(_gui, parent, child);
|
||||
gunlock(_gui);
|
||||
}
|
||||
|
||||
void widget_dirty(gui *_gui, widget *_this)
|
||||
{
|
||||
struct gui *g = _gui;
|
||||
struct widget *this = _this;
|
||||
glock(g);
|
||||
send_event(g, DIRTY, this->id);
|
||||
gunlock(g);
|
||||
}
|
||||
|
||||
static const char *names[] = {
|
||||
"TOPLEVEL_WINDOW", "CONTAINER", "POSITIONER", "TEXT_LIST",
|
||||
"XY_PLOT", "BUTTON", "LABEL", "TIMELINE", "SPACE", "IMAGE"
|
||||
};
|
||||
const char *widget_name(enum widget_type type)
|
||||
{
|
||||
switch (type) {
|
||||
case TOPLEVEL_WINDOW:
|
||||
case CONTAINER:
|
||||
case POSITIONER:
|
||||
case TEXT_LIST:
|
||||
case XY_PLOT:
|
||||
case BUTTON:
|
||||
case LABEL:
|
||||
case TIMELINE:
|
||||
case SPACE:
|
||||
case IMAGE:
|
||||
return names[type];
|
||||
}
|
||||
return "UNKNOWN (error)";
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/* find a widget */
|
||||
/*************************************************************************/
|
||||
|
||||
/* TODO: optimize traversal and also use a cache */
|
||||
struct widget *_find_widget(struct widget *c, int id)
|
||||
{
|
||||
struct widget_list *l;
|
||||
struct widget *ret;
|
||||
if (c == NULL) return NULL;
|
||||
if (c->id == id) return c;
|
||||
l = c->children;
|
||||
while (l) {
|
||||
ret = _find_widget(l->item, id);
|
||||
if (ret != NULL) return ret;
|
||||
l = l->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct widget *find_widget(struct gui *g, int id)
|
||||
{
|
||||
struct widget_list *l;
|
||||
struct widget *ret;
|
||||
|
||||
l = g->toplevel;
|
||||
|
||||
while (l) {
|
||||
ret = _find_widget(l->item, id);
|
||||
if (ret != NULL) return ret;
|
||||
l = l->next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,435 @@
|
||||
#include "x.h"
|
||||
#include "x_defs.h"
|
||||
#include "gui_defs.h"
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
int x_connection_fd(x_connection *_x)
|
||||
{
|
||||
struct x_connection *x = _x;
|
||||
return ConnectionNumber(x->d);
|
||||
}
|
||||
|
||||
static GC create_gc(Display *d, char *color)
|
||||
{
|
||||
GC ret = XCreateGC(d, DefaultRootWindow(d), 0, NULL);
|
||||
XGCValues gcv;
|
||||
XColor rcol, scol;
|
||||
|
||||
XCopyGC(d, DefaultGC(d, DefaultScreen(d)), -1L, ret);
|
||||
if (XAllocNamedColor(d, DefaultColormap(d, DefaultScreen(d)),
|
||||
color, &scol, &rcol)) {
|
||||
gcv.foreground = scol.pixel;
|
||||
XChangeGC(d, ret, GCForeground, &gcv);
|
||||
} else ERR("X: could not allocate color '%s'\n", color);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int x_new_color(x_connection *_x, char *color)
|
||||
{
|
||||
struct x_connection *x = _x;
|
||||
x->ncolors++;
|
||||
|
||||
x->colors = realloc(x->colors, x->ncolors * sizeof(GC));
|
||||
if (x->colors == NULL) OOM;
|
||||
x->colors[x->ncolors-1] = create_gc(x->d, color);
|
||||
|
||||
x->xft_colors = realloc(x->xft_colors, x->ncolors * sizeof(XftColor));
|
||||
if (x->xft_colors == NULL) OOM;
|
||||
if (XftColorAllocName(x->d, DefaultVisual(x->d, DefaultScreen(x->d)),
|
||||
DefaultColormap(x->d, DefaultScreen(x->d)),
|
||||
color, &x->xft_colors[x->ncolors-1]) == False)
|
||||
ERR("could not allocate color '%s'\n", color);
|
||||
|
||||
return x->ncolors - 1;
|
||||
}
|
||||
|
||||
int x_new_font(x_connection *_x, char *font)
|
||||
{
|
||||
struct x_connection *x = _x;
|
||||
/* TODO: allocate fonts only once */
|
||||
x->nfonts++;
|
||||
x->fonts = realloc(x->fonts, x->nfonts * sizeof(XftFont *));
|
||||
if (x->fonts == NULL) OOM;
|
||||
x->fonts[x->nfonts-1] = XftFontOpenName(x->d, DefaultScreen(x->d), font);
|
||||
if (x->fonts[x->nfonts-1] == NULL)
|
||||
ERR("failed allocating font '%s'\n", font);
|
||||
return x->nfonts - 1;
|
||||
}
|
||||
|
||||
x_connection *x_open(void)
|
||||
{
|
||||
struct x_connection *ret;
|
||||
|
||||
ret = calloc(1, sizeof(struct x_connection));
|
||||
if (ret == NULL) OOM;
|
||||
|
||||
ret->d = XOpenDisplay(0);
|
||||
LOGD("XOpenDisplay display %p return x_connection %p\n", ret->d, ret);
|
||||
if (ret->d == NULL) ERR("error calling XOpenDisplay: no X? you root?\n");
|
||||
|
||||
x_new_color(ret, "white"); /* background color */
|
||||
x_new_color(ret, "black"); /* foreground color */
|
||||
|
||||
x_new_font(ret, "sans-8");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
x_window *x_create_window(x_connection *_x, int width, int height,
|
||||
char *title)
|
||||
{
|
||||
struct x_connection *x = _x;
|
||||
struct x_window *ret;
|
||||
|
||||
ret = calloc(1, sizeof(struct x_window));
|
||||
if (ret == NULL) OOM;
|
||||
|
||||
ret->w = XCreateSimpleWindow(x->d, DefaultRootWindow(x->d), 0, 0,
|
||||
width, height, 0, WhitePixel(x->d, DefaultScreen(x->d)),
|
||||
WhitePixel(x->d, DefaultScreen(x->d)));
|
||||
ret->width = width;
|
||||
ret->height = height;
|
||||
|
||||
XStoreName(x->d, ret->w, title);
|
||||
|
||||
ret->p = XCreatePixmap(x->d, ret->w, width, height,
|
||||
DefaultDepth(x->d, DefaultScreen(x->d)));
|
||||
XFillRectangle(x->d, ret->p, x->colors[BACKGROUND_COLOR],
|
||||
0, 0, width, height);
|
||||
|
||||
ret->xft = XftDrawCreate(x->d, ret->p,
|
||||
DefaultVisual(x->d, DefaultScreen(x->d)),
|
||||
DefaultColormap(x->d, DefaultScreen(x->d)));
|
||||
if (ret->xft == NULL) ERR("XftDrawCreate failed\n");
|
||||
|
||||
/* enable backing store */
|
||||
{
|
||||
XSetWindowAttributes att;
|
||||
att.backing_store = Always;
|
||||
XChangeWindowAttributes(x->d, ret->w, CWBackingStore, &att);
|
||||
}
|
||||
|
||||
XSelectInput(x->d, ret->w,
|
||||
KeyPressMask |
|
||||
ButtonPressMask |
|
||||
ButtonReleaseMask |
|
||||
PointerMotionMask |
|
||||
ExposureMask |
|
||||
StructureNotifyMask);
|
||||
|
||||
XMapWindow(x->d, ret->w);
|
||||
|
||||
#if 0
|
||||
/* wait for window to be mapped */
|
||||
LOGD("wait for map\n");
|
||||
while (1) {
|
||||
XEvent ev;
|
||||
//XWindowEvent(x->d, ret->w, StructureNotifyMask, &ev);
|
||||
XWindowEvent(x->d, ret->w, ExposureMask, &ev);
|
||||
LOGD("got ev %d\n", ev.type);
|
||||
//if (ev.type == MapNotify) break;
|
||||
if (ev.type == Expose) break;
|
||||
}
|
||||
LOGD("XXX create connection %p window %p (win id %d pixmap %d) w h %d %d\n", x, ret, (int)ret->w, (int)ret->p, width, height);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
x_image *x_create_image(x_connection *_x, unsigned char *data,
|
||||
int width, int height)
|
||||
{
|
||||
struct x_connection *x = _x;
|
||||
struct x_image *ret;
|
||||
XImage *ximage;
|
||||
XVisualInfo *vs;
|
||||
XVisualInfo template;
|
||||
int nvs;
|
||||
Visual *v;
|
||||
|
||||
ret = calloc(1, sizeof(struct x_image)); if (ret == NULL) OOM;
|
||||
|
||||
template.class = TrueColor;
|
||||
template.depth = 24;
|
||||
template.red_mask = 0xff0000;
|
||||
template.green_mask = 0x00ff00;
|
||||
template.blue_mask = 0x0000ff;
|
||||
template.bits_per_rgb = 8;
|
||||
|
||||
vs = XGetVisualInfo(x->d, VisualDepthMask | VisualClassMask |
|
||||
VisualRedMaskMask | VisualGreenMaskMask | VisualBlueMaskMask |
|
||||
VisualBitsPerRGBMask, &template, &nvs);
|
||||
if (vs == NULL || nvs == 0) ERR("no good visual found\n");
|
||||
v = vs[0].visual;
|
||||
XFree(vs);
|
||||
|
||||
ximage = XCreateImage(x->d, v, 24, ZPixmap, 0,
|
||||
(char*)data, width, height, 32, 0);
|
||||
if (ximage == NULL) ERR("image creation failed\n");
|
||||
|
||||
ret->p = XCreatePixmap(x->d, DefaultRootWindow(x->d), width, height, 24);
|
||||
|
||||
XPutImage(x->d, ret->p, DefaultGC(x->d, DefaultScreen(x->d)),
|
||||
ximage, 0, 0, 0, 0, width, height);
|
||||
|
||||
/* TODO: be sure it's fine to set data to NULL */
|
||||
ximage->data = NULL;
|
||||
XDestroyImage(ximage);
|
||||
|
||||
ret->width = width;
|
||||
ret->height = height;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct toplevel_window_widget *find_x_window(struct gui *g, Window id)
|
||||
{
|
||||
struct widget_list *cur;
|
||||
struct toplevel_window_widget *w;
|
||||
struct x_window *xw;
|
||||
cur = g->toplevel;
|
||||
while (cur) {
|
||||
w = (struct toplevel_window_widget *)cur->item;
|
||||
xw = w->x;
|
||||
if (xw->w == id) return w;
|
||||
cur = cur->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void x_events(gui *_gui)
|
||||
{
|
||||
struct gui *g = _gui;
|
||||
struct widget_list *cur;
|
||||
struct x_connection *x = g->x;
|
||||
struct toplevel_window_widget *w;
|
||||
|
||||
LOGD("x_events START\n");
|
||||
/* preprocessing (to "compress" events) */
|
||||
cur = g->toplevel;
|
||||
while (cur) {
|
||||
struct x_window *xw;
|
||||
w = (struct toplevel_window_widget *)cur->item;
|
||||
xw = w->x;
|
||||
xw->redraw = 0;
|
||||
xw->repaint = 0;
|
||||
xw->resize = 0;
|
||||
cur = cur->next;
|
||||
}
|
||||
|
||||
while (XPending(x->d)) {
|
||||
XEvent ev;
|
||||
XNextEvent(x->d, &ev);
|
||||
LOGD("XEV %d\n", ev.type);
|
||||
switch (ev.type) {
|
||||
case MapNotify:
|
||||
case Expose:
|
||||
if ((w = find_x_window(g, ev.xexpose.window)) != NULL) {
|
||||
struct x_window *xw = w->x;
|
||||
xw->redraw = 1;
|
||||
}
|
||||
break;
|
||||
case ConfigureNotify:
|
||||
if ((w = find_x_window(g, ev.xconfigure.window)) != NULL) {
|
||||
struct x_window *xw = w->x;
|
||||
xw->resize = 1;
|
||||
xw->new_width = ev.xconfigure.width;
|
||||
xw->new_height = ev.xconfigure.height;
|
||||
if (xw->new_width < 10) xw->new_width = 10;
|
||||
if (xw->new_height < 10) xw->new_height = 10;
|
||||
LOGD("ConfigureNotify %d %d\n", ev.xconfigure.width, ev.xconfigure.height);
|
||||
}
|
||||
break;
|
||||
case ButtonPress:
|
||||
if ((w = find_x_window(g, ev.xbutton.window)) != NULL) {
|
||||
int key_modifiers = 0;
|
||||
if (ev.xbutton.state & ShiftMask) key_modifiers |= KEY_SHIFT;
|
||||
if (ev.xbutton.state & Mod1Mask) key_modifiers |= KEY_ALT;
|
||||
if (ev.xbutton.state & ControlMask) key_modifiers |= KEY_CONTROL;
|
||||
w->common.button(g, w, ev.xbutton.x, ev.xbutton.y, key_modifiers,
|
||||
ev.xbutton.button, 0);
|
||||
}
|
||||
break;
|
||||
case ButtonRelease:
|
||||
if ((w = find_x_window(g, ev.xbutton.window)) != NULL) {
|
||||
int key_modifiers = 0;
|
||||
if (ev.xbutton.state & ShiftMask) key_modifiers |= KEY_SHIFT;
|
||||
if (ev.xbutton.state & Mod1Mask) key_modifiers |= KEY_ALT;
|
||||
if (ev.xbutton.state & ControlMask) key_modifiers |= KEY_CONTROL;
|
||||
w->common.button(g, w, ev.xbutton.x, ev.xbutton.y, key_modifiers,
|
||||
ev.xbutton.button, 1);
|
||||
}
|
||||
break;
|
||||
#if 0
|
||||
case MapNotify:
|
||||
if ((w = find_x_window(g, ev.xmap.window)) != NULL) {
|
||||
struct x_window *xw = w->x;
|
||||
xw->repaint = 1;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
default: if (gui_logd) WARN("TODO: X event type %d\n", ev.type); break;
|
||||
}
|
||||
}
|
||||
|
||||
/* postprocessing */
|
||||
LOGD("post processing\n");
|
||||
cur = g->toplevel;
|
||||
while (cur) {
|
||||
struct toplevel_window_widget *w =
|
||||
(struct toplevel_window_widget *)cur->item;
|
||||
struct x_window *xw = w->x;
|
||||
if (xw->resize) {
|
||||
LOGD("resize old %d %d new %d %d\n", xw->width, xw->height, xw->new_width, xw->new_height);
|
||||
if (xw->width != xw->new_width || xw->height != xw->new_height) {
|
||||
w->common.allocate(g, w, 0, 0, xw->new_width, xw->new_height);
|
||||
xw->width = xw->new_width;
|
||||
xw->height = xw->new_height;
|
||||
XftDrawDestroy(xw->xft);
|
||||
XFreePixmap(x->d, xw->p);
|
||||
xw->p = XCreatePixmap(x->d, xw->w, xw->width, xw->height,
|
||||
DefaultDepth(x->d, DefaultScreen(x->d)));
|
||||
XFillRectangle(x->d, xw->p, x->colors[BACKGROUND_COLOR],
|
||||
0, 0, xw->width, xw->height);
|
||||
xw->xft = XftDrawCreate(x->d, xw->p,
|
||||
DefaultVisual(x->d, DefaultScreen(x->d)),
|
||||
DefaultColormap(x->d, DefaultScreen(x->d)));
|
||||
if (xw->xft == NULL) ERR("XftDrawCreate failed\n");
|
||||
|
||||
//xw->repaint = 1;
|
||||
}
|
||||
}
|
||||
if (xw->repaint) {
|
||||
w->common.paint(g, w);
|
||||
xw->redraw = 1;
|
||||
}
|
||||
if (xw->redraw) {
|
||||
struct x_connection *x = g->x;
|
||||
LOGD("XCopyArea w h %d %d\n", xw->width, xw->height);
|
||||
XCopyArea(x->d, xw->p, xw->w, x->colors[1],
|
||||
0, 0, xw->width, xw->height, 0, 0);
|
||||
}
|
||||
cur = cur->next;
|
||||
}
|
||||
LOGD("x_events DONE\n");
|
||||
}
|
||||
|
||||
void x_flush(x_connection *_x)
|
||||
{
|
||||
struct x_connection *x = _x;
|
||||
XFlush(x->d);
|
||||
}
|
||||
|
||||
void x_text_get_dimensions(x_connection *_c, int font, const char *t,
|
||||
int *width, int *height, int *baseline)
|
||||
{
|
||||
struct x_connection *c = _c;
|
||||
XGlyphInfo ext;
|
||||
|
||||
XftTextExtentsUtf8(c->d, c->fonts[font], (FcChar8 *)t, strlen(t), &ext);
|
||||
|
||||
*width = ext.width;
|
||||
*height = c->fonts[font]->height;
|
||||
*baseline = c->fonts[font]->ascent;
|
||||
}
|
||||
|
||||
/***********************************************************************/
|
||||
/* public drawing functions */
|
||||
/***********************************************************************/
|
||||
|
||||
void x_draw_line(x_connection *_c, x_window *_w, int color,
|
||||
int x1, int y1, int x2, int y2)
|
||||
{
|
||||
struct x_connection *c = _c;
|
||||
struct x_window *w = _w;
|
||||
XDrawLine(c->d, w->p, c->colors[color], x1, y1, x2, y2);
|
||||
}
|
||||
|
||||
void x_draw_rectangle(x_connection *_c, x_window *_w, int color,
|
||||
int x, int y, int width, int height)
|
||||
{
|
||||
struct x_connection *c = _c;
|
||||
struct x_window *w = _w;
|
||||
XDrawRectangle(c->d, w->p, c->colors[color], x, y, width, height);
|
||||
}
|
||||
|
||||
void x_fill_rectangle(x_connection *_c, x_window *_w, int color,
|
||||
int x, int y, int width, int height)
|
||||
{
|
||||
struct x_connection *c = _c;
|
||||
struct x_window *w = _w;
|
||||
XFillRectangle(c->d, w->p, c->colors[color], x, y, width, height);
|
||||
}
|
||||
|
||||
void x_draw_string(x_connection *_c, x_window *_w, int font, int color,
|
||||
int x, int y, const char *t)
|
||||
{
|
||||
struct x_connection *c = _c;
|
||||
struct x_window *w = _w;
|
||||
int tlen = strlen(t);
|
||||
XftDrawStringUtf8(w->xft, &c->xft_colors[color], c->fonts[font],
|
||||
x, y, (const unsigned char *)t, tlen);
|
||||
}
|
||||
|
||||
void x_draw_clipped_string(x_connection *_c, x_window *_w, int font,
|
||||
int color, int x, int y, const char *t,
|
||||
int clipx, int clipy, int clipwidth, int clipheight)
|
||||
{
|
||||
struct x_window *w = _w;
|
||||
|
||||
XRectangle clip = { clipx, clipy, clipwidth, clipheight };
|
||||
if (XftDrawSetClipRectangles(w->xft, 0, 0, &clip, 1) == False) abort();
|
||||
x_draw_string(_c, _w, font, color, x, y, t);
|
||||
if (XftDrawSetClip(w->xft, NULL) == False) abort();
|
||||
}
|
||||
|
||||
void x_draw_image(x_connection *_c, x_window *_w, x_image *_img, int x, int y)
|
||||
{
|
||||
struct x_connection *c = _c;
|
||||
struct x_window *w = _w;
|
||||
struct x_image *img = _img;
|
||||
|
||||
XCopyArea(c->d, img->p, w->p, DefaultGC(c->d, DefaultScreen(c->d)),
|
||||
0, 0, img->width, img->height, x, y);
|
||||
}
|
||||
|
||||
void x_draw(x_connection *_c, x_window *_w)
|
||||
{
|
||||
struct x_connection *c = _c;
|
||||
struct x_window *w = _w;
|
||||
LOGD("x_draw XCopyArea w h %d %d display %p window %d pixmap %d\n", w->width, w->height, c->d, (int)w->w, (int)w->p);
|
||||
XCopyArea(c->d, w->p, w->w, c->colors[1], 0, 0, w->width, w->height, 0, 0);
|
||||
}
|
||||
|
||||
/* those two special functions are to plot many points
|
||||
* first call x_add_point many times then x_plot_points once
|
||||
*/
|
||||
void x_add_point(x_connection *_c, int x, int y)
|
||||
{
|
||||
struct x_connection *c = _c;
|
||||
|
||||
if (c->pts_size == c->pts_maxsize) {
|
||||
c->pts_maxsize += 65536;
|
||||
c->pts = realloc(c->pts, c->pts_maxsize * sizeof(XPoint));
|
||||
if (c->pts == NULL) OOM;
|
||||
}
|
||||
|
||||
c->pts[c->pts_size].x = x;
|
||||
c->pts[c->pts_size].y = y;
|
||||
c->pts_size++;
|
||||
}
|
||||
|
||||
void x_plot_points(x_connection *_c, x_window *_w, int color)
|
||||
{
|
||||
struct x_connection *c = _c;
|
||||
LOGD("x_plot_points %d points\n", c->pts_size);
|
||||
struct x_window *w = _w;
|
||||
XDrawPoints(c->d, w->p, c->colors[color], c->pts, c->pts_size,
|
||||
CoordModeOrigin);
|
||||
c->pts_size = 0;
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
#ifndef _X_H_
|
||||
#define _X_H_
|
||||
|
||||
/* public X interface */
|
||||
|
||||
typedef void x_connection;
|
||||
typedef void x_window;
|
||||
typedef void x_image;
|
||||
|
||||
x_connection *x_open(void);
|
||||
|
||||
x_window *x_create_window(x_connection *x, int width, int height,
|
||||
char *title);
|
||||
|
||||
x_image *x_create_image(x_connection *x, unsigned char *data,
|
||||
int width, int height);
|
||||
|
||||
int x_connection_fd(x_connection *x);
|
||||
|
||||
void x_flush(x_connection *x);
|
||||
|
||||
int x_new_color(x_connection *x, char *color);
|
||||
int x_new_font(x_connection *x, char *font);
|
||||
|
||||
/* for x_events, we pass the gui */
|
||||
#include "gui.h"
|
||||
void x_events(gui *gui);
|
||||
|
||||
void x_text_get_dimensions(x_connection *, int font, const char *t,
|
||||
int *width, int *height, int *baseline);
|
||||
|
||||
/* drawing functions */
|
||||
|
||||
void x_draw_line(x_connection *c, x_window *w, int color,
|
||||
int x1, int y1, int x2, int y2);
|
||||
|
||||
void x_draw_rectangle(x_connection *c, x_window *w, int color,
|
||||
int x, int y, int width, int height);
|
||||
|
||||
void x_fill_rectangle(x_connection *c, x_window *w, int color,
|
||||
int x, int y, int width, int height);
|
||||
|
||||
void x_draw_string(x_connection *_c, x_window *_w, int font, int color,
|
||||
int x, int y, const char *t);
|
||||
|
||||
void x_draw_clipped_string(x_connection *_c, x_window *_w, int font,
|
||||
int color, int x, int y, const char *t,
|
||||
int clipx, int clipy, int clipwidth, int clipheight);
|
||||
|
||||
void x_draw_image(x_connection *c, x_window *w, x_image *img, int x, int y);
|
||||
|
||||
/* specials functions to plot many points
|
||||
* you call several times x_add_point() then x_plot_points()
|
||||
*/
|
||||
void x_add_point(x_connection *c, int x, int y);
|
||||
void x_plot_points(x_connection *c, x_window *w, int color);
|
||||
|
||||
/* this function copies the pixmap to the window */
|
||||
void x_draw(x_connection *c, x_window *w);
|
||||
|
||||
#endif /* _X_H_ */
|
||||
@@ -0,0 +1,37 @@
|
||||
#ifndef _X_DEFS_H_
|
||||
#define _X_DEFS_H_
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <Xft.h>
|
||||
|
||||
struct x_connection {
|
||||
Display *d;
|
||||
GC *colors;
|
||||
XftColor *xft_colors;
|
||||
int ncolors;
|
||||
XPoint *pts;
|
||||
int pts_size;
|
||||
int pts_maxsize;
|
||||
XftFont **fonts;
|
||||
int nfonts;
|
||||
};
|
||||
|
||||
struct x_window {
|
||||
Window w;
|
||||
Pixmap p;
|
||||
int width;
|
||||
int height;
|
||||
XftDraw *xft;
|
||||
/* below: internal data used for X events handling */
|
||||
int redraw;
|
||||
int repaint;
|
||||
int resize, new_width, new_height;
|
||||
};
|
||||
|
||||
struct x_image {
|
||||
Pixmap p;
|
||||
int width;
|
||||
int height;
|
||||
};
|
||||
|
||||
#endif /* _X_DEFS_H_ */
|
||||
@@ -0,0 +1,292 @@
|
||||
#include "gui.h"
|
||||
#include "gui_defs.h"
|
||||
#include "x.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
static void paint(gui *_gui, widget *_this)
|
||||
{
|
||||
struct gui *g = _gui;
|
||||
struct xy_plot_widget *this = _this;
|
||||
int wanted_plot_width, allocated_plot_width;
|
||||
int wanted_plot_height, allocated_plot_height;
|
||||
float pxsize;
|
||||
float ticdist;
|
||||
float tic;
|
||||
float ticstep;
|
||||
int k, kmin, kmax;
|
||||
float allocated_xmin, allocated_xmax;
|
||||
float allocated_ymin, allocated_ymax;
|
||||
float center;
|
||||
int i;
|
||||
int n;
|
||||
|
||||
# define FLIP(v) (-(v) + allocated_plot_height-1)
|
||||
|
||||
LOGD("PAINT xy plot xywh %d %d %d %d\n", this->common.x, this->common.y, this->common.width, this->common.height);
|
||||
|
||||
//x_draw_rectangle(g->x, g->xwin, 1, this->common.x, this->common.y, this->common.width, this->common.height);
|
||||
|
||||
wanted_plot_width = this->wanted_width;
|
||||
allocated_plot_width = this->common.width - this->vrule_width;
|
||||
wanted_plot_height = this->wanted_height;
|
||||
allocated_plot_height = this->common.height - this->label_height * 2;
|
||||
|
||||
/* plot zone */
|
||||
/* TODO: refine height - height of hrule text may be != from label */
|
||||
x_draw_rectangle(g->x, g->xwin, 1,
|
||||
this->common.x + this->vrule_width,
|
||||
this->common.y,
|
||||
this->common.width - this->vrule_width -1, /* -1 to see right border */
|
||||
this->common.height - this->label_height * 2);
|
||||
|
||||
/* horizontal tics */
|
||||
pxsize = (this->xmax - this->xmin) / wanted_plot_width;
|
||||
ticdist = 100;
|
||||
tic = floor(log10(ticdist * pxsize));
|
||||
ticstep = powf(10, tic);
|
||||
center = (this->xmax + this->xmin) / 2;
|
||||
allocated_xmin = center - ((this->xmax - this->xmin) *
|
||||
allocated_plot_width / wanted_plot_width) / 2;
|
||||
allocated_xmax = center + ((this->xmax - this->xmin) *
|
||||
allocated_plot_width / wanted_plot_width) / 2;
|
||||
/* adjust tic if too tight */
|
||||
LOGD("pre x ticstep %g\n", ticstep);
|
||||
while (1) {
|
||||
if (ticstep / (allocated_xmax - allocated_xmin)
|
||||
* (allocated_plot_width - 1) > 40) break;
|
||||
ticstep *= 2;
|
||||
}
|
||||
LOGD("post x ticstep %g\n", ticstep);
|
||||
LOGD("xmin/max %g %g width wanted allocated %d %d alloc xmin/max %g %g ticstep %g\n", this->xmin, this->xmax, wanted_plot_width, allocated_plot_width, allocated_xmin, allocated_xmax, ticstep);
|
||||
kmin = ceil(allocated_xmin / ticstep);
|
||||
kmax = floor(allocated_xmax / ticstep);
|
||||
for (k = kmin; k <= kmax; k++) {
|
||||
/*
|
||||
(k * ticstep - allocated_xmin) / (allocated_max - allocated_xmin) =
|
||||
(x - 0) / (allocated_plot_width-1 - 0)
|
||||
*/
|
||||
char v[64];
|
||||
int vwidth, dummy;
|
||||
float x = (k * ticstep - allocated_xmin) /
|
||||
(allocated_xmax - allocated_xmin) *
|
||||
(allocated_plot_width - 1);
|
||||
x_draw_line(g->x, g->xwin, FOREGROUND_COLOR,
|
||||
this->common.x + this->vrule_width + x,
|
||||
this->common.y + this->common.height - this->label_height * 2,
|
||||
this->common.x + this->vrule_width + x,
|
||||
this->common.y + this->common.height - this->label_height * 2 - 5);
|
||||
sprintf(v, "%g", k * ticstep);
|
||||
x_text_get_dimensions(g->x, DEFAULT_FONT, v, &vwidth, &dummy, &dummy);
|
||||
x_draw_string(g->x, g->xwin, DEFAULT_FONT, FOREGROUND_COLOR,
|
||||
this->common.x + this->vrule_width + x - vwidth/2,
|
||||
this->common.y + this->common.height - this->label_height * 2 +
|
||||
this->label_baseline,
|
||||
v);
|
||||
LOGD("tic k %d val %g x %g\n", k, k * ticstep, x);
|
||||
}
|
||||
|
||||
/* vertical tics */
|
||||
pxsize = (this->ymax - this->ymin) / wanted_plot_height;
|
||||
ticdist = 30;
|
||||
tic = floor(log10(ticdist * pxsize));
|
||||
ticstep = powf(10, tic);
|
||||
center = (this->ymax + this->ymin) / 2;
|
||||
allocated_ymin = center - ((this->ymax - this->ymin) *
|
||||
allocated_plot_height / wanted_plot_height) / 2;
|
||||
allocated_ymax = center + ((this->ymax - this->ymin) *
|
||||
allocated_plot_height / wanted_plot_height) / 2;
|
||||
/* adjust tic if too tight */
|
||||
LOGD("pre y ticstep %g\n", ticstep);
|
||||
while (1) {
|
||||
if (ticstep / (allocated_ymax - allocated_ymin)
|
||||
* (allocated_plot_height - 1) > 20) break;
|
||||
ticstep *= 2;
|
||||
}
|
||||
LOGD("post y ticstep %g\n", ticstep);
|
||||
LOGD("ymin/max %g %g height wanted allocated %d %d alloc ymin/max %g %g ticstep %g\n", this->ymin, this->ymax, wanted_plot_height, allocated_plot_height, allocated_ymin, allocated_ymax, ticstep);
|
||||
kmin = ceil(allocated_ymin / ticstep);
|
||||
kmax = floor(allocated_ymax / ticstep);
|
||||
for (k = kmin; k <= kmax; k++) {
|
||||
char v[64];
|
||||
int vwidth, dummy;
|
||||
float y = (k * ticstep - allocated_ymin) /
|
||||
(allocated_ymax - allocated_ymin) *
|
||||
(allocated_plot_height - 1);
|
||||
sprintf(v, "%g", k * ticstep);
|
||||
x_text_get_dimensions(g->x, DEFAULT_FONT, v, &vwidth, &dummy, &dummy);
|
||||
x_draw_line(g->x, g->xwin, FOREGROUND_COLOR,
|
||||
this->common.x + this->vrule_width,
|
||||
this->common.y + FLIP(y),
|
||||
this->common.x + this->vrule_width + 5,
|
||||
this->common.y + FLIP(y));
|
||||
x_draw_string(g->x, g->xwin, DEFAULT_FONT, FOREGROUND_COLOR,
|
||||
this->common.x + this->vrule_width - vwidth - 2,
|
||||
this->common.y + FLIP(y) - this->label_height/2+this->label_baseline,
|
||||
v);
|
||||
}
|
||||
|
||||
/* label at bottom, in the middle */
|
||||
x_draw_string(g->x, g->xwin, DEFAULT_FONT, FOREGROUND_COLOR,
|
||||
this->common.x + (this->common.width - this->label_width) / 2,
|
||||
this->common.y + this->common.height - this->label_height
|
||||
+ this->label_baseline,
|
||||
this->label);
|
||||
|
||||
for (n = 0; n < this->nplots; n++) {
|
||||
/* points */
|
||||
float ax, bx, ay, by;
|
||||
ax = (allocated_plot_width-1) / (allocated_xmax - allocated_xmin);
|
||||
bx = -ax * allocated_xmin;
|
||||
ay = (allocated_plot_height-1) / (allocated_ymax - allocated_ymin);
|
||||
by = -ay * allocated_ymin;
|
||||
for (i = 0; i < this->plots[n].npoints; i++) {
|
||||
int x, y;
|
||||
x = ax * this->plots[n].x[i] + bx;
|
||||
y = ay * this->plots[n].y[i] + by;
|
||||
if (x >= 0 && x < allocated_plot_width &&
|
||||
y >= 0 && y < allocated_plot_height)
|
||||
x_add_point(g->x,
|
||||
this->common.x + this->vrule_width + x,
|
||||
this->common.y + FLIP(y));
|
||||
}
|
||||
x_plot_points(g->x, g->xwin, this->plots[n].color);
|
||||
}
|
||||
}
|
||||
|
||||
static void hints(gui *_gui, widget *_w, int *width, int *height)
|
||||
{
|
||||
struct xy_plot_widget *w = _w;
|
||||
*width = w->wanted_width + w->vrule_width;
|
||||
*height = w->wanted_height + w->label_height * 2; /* TODO: refine */
|
||||
LOGD("HINTS xy plot wh %d %d (vrule_width %d) (wanted wh %d %d)\n", *width, *height, w->vrule_width, w->wanted_width, w->wanted_height);
|
||||
}
|
||||
|
||||
widget *new_xy_plot(gui *_gui, int width, int height, char *label,
|
||||
int vruler_width)
|
||||
{
|
||||
struct gui *g = _gui;
|
||||
struct xy_plot_widget *w;
|
||||
|
||||
glock(g);
|
||||
|
||||
w = new_widget(g, XY_PLOT, sizeof(struct xy_plot_widget));
|
||||
|
||||
w->label = strdup(label); if (w->label == NULL) OOM;
|
||||
/* TODO: be sure calling X there is valid wrt "global model" (we are
|
||||
* not in the "gui thread") */
|
||||
x_text_get_dimensions(g->x, DEFAULT_FONT, label,
|
||||
&w->label_width, &w->label_height, &w->label_baseline);
|
||||
LOGD("XY PLOT label wh %d %d\n", w->label_width, w->label_height);
|
||||
|
||||
w->wanted_width = width;
|
||||
w->wanted_height = height;
|
||||
w->vrule_width = vruler_width;
|
||||
|
||||
w->xmin = -1;
|
||||
w->xmax = 1;
|
||||
w->ymin = -1;
|
||||
w->ymax = 1;
|
||||
w->plots = NULL;
|
||||
w->nplots = 0;
|
||||
|
||||
w->common.paint = paint;
|
||||
w->common.hints = hints;
|
||||
|
||||
gunlock(g);
|
||||
|
||||
return w;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
/* public functions */
|
||||
/*************************************************************************/
|
||||
|
||||
int xy_plot_new_plot(gui *_gui, widget *_this, int color)
|
||||
{
|
||||
int ret;
|
||||
struct gui *g = _gui;
|
||||
struct xy_plot_widget *this = _this;
|
||||
|
||||
glock(g);
|
||||
|
||||
ret = this->nplots;
|
||||
|
||||
this->nplots++;
|
||||
this->plots = realloc(this->plots,
|
||||
this->nplots * sizeof(struct xy_plot_plot));
|
||||
if (this->plots == NULL) abort();
|
||||
|
||||
this->plots[ret].x = NULL;
|
||||
this->plots[ret].y = NULL;
|
||||
this->plots[ret].npoints = 0;
|
||||
this->plots[ret].color = color;
|
||||
|
||||
gunlock(g);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void xy_plot_set_range(gui *_gui, widget *_this,
|
||||
float xmin, float xmax, float ymin, float ymax)
|
||||
{
|
||||
struct gui *g = _gui;
|
||||
struct xy_plot_widget *this = _this;
|
||||
|
||||
glock(g);
|
||||
|
||||
this->xmin = xmin;
|
||||
this->xmax = xmax;
|
||||
this->ymin = ymin;
|
||||
this->ymax = ymax;
|
||||
|
||||
send_event(g, DIRTY, this->common.id);
|
||||
|
||||
gunlock(g);
|
||||
}
|
||||
|
||||
void xy_plot_set_points(gui *_gui, widget *_this, int plot,
|
||||
int npoints, float *x, float *y)
|
||||
{
|
||||
struct gui *g = _gui;
|
||||
struct xy_plot_widget *this = _this;
|
||||
|
||||
glock(g);
|
||||
|
||||
if (npoints != this->plots[plot].npoints) {
|
||||
free(this->plots[plot].x);
|
||||
free(this->plots[plot].y);
|
||||
this->plots[plot].x = calloc(npoints, sizeof(float));
|
||||
if (this->plots[plot].x == NULL) abort();
|
||||
this->plots[plot].y = calloc(npoints, sizeof(float));
|
||||
if (this->plots[plot].y == NULL) abort();
|
||||
this->plots[plot].npoints = npoints;
|
||||
}
|
||||
|
||||
memcpy(this->plots[plot].x, x, npoints * sizeof(float));
|
||||
memcpy(this->plots[plot].y, y, npoints * sizeof(float));
|
||||
|
||||
send_event(g, DIRTY, this->common.id);
|
||||
|
||||
gunlock(g);
|
||||
}
|
||||
|
||||
void xy_plot_get_dimensions(gui *_gui, widget *_this, int *width, int *height)
|
||||
{
|
||||
struct gui *g = _gui;
|
||||
struct xy_plot_widget *this = _this;
|
||||
|
||||
glock(g);
|
||||
|
||||
if (this->common.width == 0 || this->common.height == 0) {
|
||||
*width = this->wanted_width;
|
||||
*height = this->wanted_height;
|
||||
} else {
|
||||
*width = this->common.width - this->vrule_width;
|
||||
*height = this->common.height - this->label_height * 2;
|
||||
}
|
||||
|
||||
gunlock(g);
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
#include "handler.h"
|
||||
#include "event.h"
|
||||
#include "database.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
typedef void (*handler_function)(void *p, event e);
|
||||
|
||||
struct handler_data {
|
||||
handler_function f;
|
||||
void *p;
|
||||
unsigned long id;
|
||||
};
|
||||
|
||||
struct handler_list {
|
||||
struct handler_data *f;
|
||||
int size;
|
||||
int maxsize;
|
||||
};
|
||||
|
||||
/* internal definition of an event handler */
|
||||
struct _event_handler {
|
||||
void *database;
|
||||
struct handler_list *events;
|
||||
unsigned long next_id;
|
||||
};
|
||||
|
||||
void handle_event(event_handler *_h, event e)
|
||||
{
|
||||
struct _event_handler *h = _h;
|
||||
int i;
|
||||
for (i = 0; i < h->events[e.type].size; i++)
|
||||
h->events[e.type].f[i].f(h->events[e.type].f[i].p, e);
|
||||
}
|
||||
|
||||
event_handler *new_handler(void *database)
|
||||
{
|
||||
struct _event_handler *ret = calloc(1, sizeof(struct _event_handler));
|
||||
if (ret == NULL) abort();
|
||||
|
||||
ret->database = database;
|
||||
|
||||
ret->events = calloc(number_of_ids(database), sizeof(struct handler_list));
|
||||
if (ret->events == NULL) abort();
|
||||
|
||||
ret->next_id = 1;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
unsigned long register_handler_function(event_handler *_h, int event_id,
|
||||
void (*f)(void *, event), void *p)
|
||||
{
|
||||
struct _event_handler *h = _h;
|
||||
unsigned long ret = h->next_id;
|
||||
struct handler_list *l;
|
||||
|
||||
h->next_id++;
|
||||
if (h->next_id == 2UL * 1024 * 1024 * 1024)
|
||||
{ printf("%s:%d: this is bad...\n", __FILE__, __LINE__); abort(); }
|
||||
|
||||
l = &h->events[event_id];
|
||||
if (l->size == l->maxsize) {
|
||||
l->maxsize += 16;
|
||||
l->f = realloc(l->f, l->maxsize * sizeof(struct handler_data));
|
||||
if (l->f == NULL) abort();
|
||||
}
|
||||
l->f[l->size].f = f;
|
||||
l->f[l->size].p = p;
|
||||
l->f[l->size].id = ret;
|
||||
|
||||
l->size++;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void remove_handler_function(event_handler *h, int event_id,
|
||||
unsigned long handler_id)
|
||||
{
|
||||
printf("%s:%d: TODO\n", __FILE__, __LINE__);
|
||||
abort();
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
#ifndef _HANDLER_H_
|
||||
#define _HANDLER_H_
|
||||
|
||||
typedef void event_handler;
|
||||
|
||||
#include "event.h"
|
||||
|
||||
event_handler *new_handler(void *database);
|
||||
void handle_event(event_handler *h, event e);
|
||||
|
||||
unsigned long register_handler_function(event_handler *_h, int event_id,
|
||||
void (*f)(void *, event), void *p);
|
||||
void remove_handler_function(event_handler *h, int event_id,
|
||||
unsigned long handler_id);
|
||||
|
||||
#endif /* _HANDLER_H_ */
|
||||
@@ -0,0 +1,13 @@
|
||||
CC=gcc
|
||||
CFLAGS=-Wall -g -pthread -I..
|
||||
|
||||
OBJS=logger.o textlog.o framelog.o ttilog.o timelog.o ticklog.o
|
||||
|
||||
logger.a: $(OBJS)
|
||||
ar cr logger.a $(OBJS)
|
||||
|
||||
%.o: %.c
|
||||
$(CC) $(CFLAGS) -o $@ -c $<
|
||||
|
||||
clean:
|
||||
rm -f *.a *.o
|
||||
@@ -0,0 +1,146 @@
|
||||
#include "logger.h"
|
||||
#include "logger_defs.h"
|
||||
#include "handler.h"
|
||||
#include "database.h"
|
||||
#include "filter/filter.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
|
||||
struct framelog {
|
||||
struct logger common;
|
||||
void *database;
|
||||
int subframe_arg;
|
||||
int buffer_arg;
|
||||
float *x;
|
||||
float *buffer;
|
||||
int blength;
|
||||
int skip_delay; /* one frame over 'skip_delay' is truly processed
|
||||
* 0 to disable (process all data)
|
||||
*/
|
||||
int skip_current; /* internal data for the skip mechanism */
|
||||
int skip_on; /* internal data for the skip mechanism */
|
||||
};
|
||||
|
||||
static void _event(void *p, event e)
|
||||
{
|
||||
struct framelog *l = p;
|
||||
int i;
|
||||
int subframe;
|
||||
void *buffer;
|
||||
int bsize;
|
||||
int nsamples;
|
||||
|
||||
if (l->common.filter != NULL && filter_eval(l->common.filter, e) == 0)
|
||||
return;
|
||||
|
||||
subframe = e.e[l->subframe_arg].i;
|
||||
buffer = e.e[l->buffer_arg].b;
|
||||
bsize = e.e[l->buffer_arg].bsize;
|
||||
|
||||
if (l->skip_delay != 0) {
|
||||
if (subframe == 0) {
|
||||
l->skip_current++;
|
||||
if (l->skip_current >= l->skip_delay) {
|
||||
l->skip_on = 0;
|
||||
l->skip_current = 0;
|
||||
} else
|
||||
l->skip_on = 1;
|
||||
}
|
||||
}
|
||||
if (l->skip_on) return;
|
||||
|
||||
nsamples = bsize / (2*sizeof(int16_t));
|
||||
|
||||
if (l->blength != nsamples * 10) {
|
||||
l->blength = nsamples * 10;
|
||||
free(l->x);
|
||||
free(l->buffer);
|
||||
l->x = calloc(l->blength, sizeof(float));
|
||||
if (l->x == NULL) abort();
|
||||
l->buffer = calloc(l->blength, sizeof(float));
|
||||
if (l->buffer == NULL) abort();
|
||||
/* update 'x' */
|
||||
for (i = 0; i < l->blength; i++)
|
||||
l->x[i] = i;
|
||||
/* update 'length' of views */
|
||||
for (i = 0; i < l->common.vsize; i++)
|
||||
l->common.v[i]->set(l->common.v[i], "length", l->blength);
|
||||
}
|
||||
|
||||
/* TODO: compute the LOGs in the plotter (too much useless computations) */
|
||||
for (i = 0; i < nsamples; i++) {
|
||||
int I = ((int16_t *)buffer)[i*2];
|
||||
int Q = ((int16_t *)buffer)[i*2+1];
|
||||
l->buffer[subframe * nsamples + i] = 10*log10(1.0+(float)(I*I+Q*Q));
|
||||
}
|
||||
|
||||
if (subframe == 9)
|
||||
for (i = 0; i < l->common.vsize; i++)
|
||||
l->common.v[i]->append(l->common.v[i], l->x, l->buffer, l->blength);
|
||||
}
|
||||
|
||||
logger *new_framelog(event_handler *h, void *database,
|
||||
char *event_name, char *subframe_varname, char *buffer_varname)
|
||||
{
|
||||
struct framelog *ret;
|
||||
int event_id;
|
||||
database_event_format f;
|
||||
int i;
|
||||
|
||||
ret = calloc(1, sizeof(struct framelog)); if (ret == NULL) abort();
|
||||
|
||||
ret->common.event_name = strdup(event_name);
|
||||
if (ret->common.event_name == NULL) abort();
|
||||
ret->database = database;
|
||||
|
||||
event_id = event_id_from_name(database, event_name);
|
||||
|
||||
ret->common.handler_id = register_handler_function(h,event_id,_event,ret);
|
||||
|
||||
f = get_format(database, event_id);
|
||||
|
||||
/* look for subframe and buffer args */
|
||||
ret->subframe_arg = -1;
|
||||
ret->buffer_arg = -1;
|
||||
for (i = 0; i < f.count; i++) {
|
||||
if (!strcmp(f.name[i], subframe_varname)) ret->subframe_arg = i;
|
||||
if (!strcmp(f.name[i], buffer_varname)) ret->buffer_arg = i;
|
||||
}
|
||||
if (ret->subframe_arg == -1) {
|
||||
printf("%s:%d: subframe argument '%s' not found in event '%s'\n",
|
||||
__FILE__, __LINE__, subframe_varname, event_name);
|
||||
abort();
|
||||
}
|
||||
if (ret->buffer_arg == -1) {
|
||||
printf("%s:%d: buffer argument '%s' not found in event '%s'\n",
|
||||
__FILE__, __LINE__, buffer_varname, event_name);
|
||||
abort();
|
||||
}
|
||||
if (strcmp(f.type[ret->subframe_arg], "int") != 0) {
|
||||
printf("%s:%d: argument '%s' has wrong type (should be 'int')\n",
|
||||
__FILE__, __LINE__, subframe_varname);
|
||||
abort();
|
||||
}
|
||||
if (strcmp(f.type[ret->buffer_arg], "buffer") != 0) {
|
||||
printf("%s:%d: argument '%s' has wrong type (should be 'buffer')\n",
|
||||
__FILE__, __LINE__, buffer_varname);
|
||||
abort();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
/* public functions */
|
||||
/****************************************************************************/
|
||||
|
||||
void framelog_set_skip(logger *_this, int skip_delay)
|
||||
{
|
||||
struct framelog *l = _this;
|
||||
/* TODO: protect with a lock? */
|
||||
l->skip_delay = skip_delay;
|
||||
l->skip_current = 0;
|
||||
l->skip_on = 0;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
#include "logger.h"
|
||||
#include "logger_defs.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
void logger_add_view(logger *_l, view *v)
|
||||
{
|
||||
struct logger *l = _l;
|
||||
l->vsize++;
|
||||
l->v = realloc(l->v, l->vsize * sizeof(view *)); if (l->v == NULL) abort();
|
||||
l->v[l->vsize-1] = v;
|
||||
}
|
||||
|
||||
void logger_set_filter(logger *_l, void *filter)
|
||||
{
|
||||
struct logger *l = _l;
|
||||
l->filter = filter;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
#ifndef _LOGGER_H_
|
||||
#define _LOGGER_H_
|
||||
|
||||
typedef void logger;
|
||||
|
||||
logger *new_framelog(void *event_handler, void *database,
|
||||
char *event_name, char *subframe_varname, char *buffer_varname);
|
||||
logger *new_textlog(void *event_handler, void *database,
|
||||
char *event_name, char *format);
|
||||
logger *new_ttilog(void *event_handler, void *database,
|
||||
char *event_name, char *frame_varname, char *subframe_varname,
|
||||
char *data_varname, int convert_to_dB);
|
||||
logger *new_timelog(void *event_handler, void *database, char *event_name);
|
||||
logger *new_ticklog(void *event_handler, void *database,
|
||||
char *event_name, char *frame_name, char *subframe_name);
|
||||
|
||||
void framelog_set_skip(logger *_this, int skip_delay);
|
||||
|
||||
#include "view/view.h"
|
||||
|
||||
void logger_add_view(logger *l, view *v);
|
||||
void logger_set_filter(logger *l, void *filter);
|
||||
|
||||
#endif /* _LOGGER_H_ */
|
||||
@@ -0,0 +1,16 @@
|
||||
#ifndef _LOGGER_DEFS_H_
|
||||
#define _LOGGER_DEFS_H_
|
||||
|
||||
#include "view/view.h"
|
||||
|
||||
struct logger {
|
||||
char *event_name;
|
||||
unsigned long handler_id;
|
||||
/* list of views */
|
||||
view **v;
|
||||
int vsize;
|
||||
/* filter - NULL if no filter set */
|
||||
void *filter;
|
||||
};
|
||||
|
||||
#endif /* _LOGGER_DEFS_H_ */
|
||||
@@ -0,0 +1,198 @@
|
||||
#include "logger.h"
|
||||
#include "logger_defs.h"
|
||||
#include "handler.h"
|
||||
#include "database.h"
|
||||
#include "view/view.h"
|
||||
#include "utils.h"
|
||||
#include "filter/filter.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
enum format_item_type {
|
||||
INSTRING,
|
||||
INT, ULONG, STRING, BUFFER };
|
||||
|
||||
struct format_item {
|
||||
enum format_item_type type;
|
||||
union {
|
||||
/* INSTRING */
|
||||
char *s;
|
||||
/* others */
|
||||
int event_arg;
|
||||
};
|
||||
};
|
||||
|
||||
struct textlog {
|
||||
struct logger common;
|
||||
char *format;
|
||||
void *database;
|
||||
/* parsed format string */
|
||||
struct format_item *f;
|
||||
int fsize;
|
||||
/* local output buffer */
|
||||
OBUF o;
|
||||
};
|
||||
|
||||
static void _event(void *p, event e)
|
||||
{
|
||||
struct textlog *l = p;
|
||||
int i;
|
||||
#ifdef T_SEND_TIME
|
||||
struct tm *t;
|
||||
char tt[64];
|
||||
#endif
|
||||
|
||||
if (l->common.filter != NULL && filter_eval(l->common.filter, e) == 0)
|
||||
return;
|
||||
|
||||
l->o.osize = 0;
|
||||
|
||||
#ifdef T_SEND_TIME
|
||||
t = localtime(&e.sending_time.tv_sec);
|
||||
/* round tv_nsec to nearest millisecond */
|
||||
sprintf(tt, "%2.2d:%2.2d:%2.2d.%9.9ld: ", t->tm_hour, t->tm_min, t->tm_sec,
|
||||
e.sending_time.tv_nsec);
|
||||
PUTS(&l->o, tt);
|
||||
#endif
|
||||
|
||||
for (i = 0; i < l->fsize; i++)
|
||||
switch(l->f[i].type) {
|
||||
case INSTRING: PUTS(&l->o, l->f[i].s); break;
|
||||
case INT: PUTI(&l->o, e.e[l->f[i].event_arg].i); break;
|
||||
case ULONG: PUTUL(&l->o, e.e[l->f[i].event_arg].ul); break;
|
||||
case STRING: PUTS_CLEAN(&l->o, e.e[l->f[i].event_arg].s); break;
|
||||
case BUFFER:
|
||||
PUTS(&l->o, "{buffer size:");
|
||||
PUTI(&l->o, e.e[l->f[i].event_arg].bsize);
|
||||
PUTS(&l->o, "}");
|
||||
break;
|
||||
}
|
||||
PUTC(&l->o, 0);
|
||||
|
||||
for (i = 0; i < l->common.vsize; i++)
|
||||
l->common.v[i]->append(l->common.v[i], l->o.obuf);
|
||||
}
|
||||
|
||||
enum chunk_type { C_ERROR, C_STRING, C_ARG_NAME, C_EVENT_NAME };
|
||||
struct chunk {
|
||||
enum chunk_type type;
|
||||
char *s;
|
||||
enum format_item_type it;
|
||||
int event_arg;
|
||||
};
|
||||
|
||||
/* TODO: speed it up? */
|
||||
static int find_argument(char *name, database_event_format f,
|
||||
enum format_item_type *it, int *event_arg)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < f.count; i++) if (!strcmp(name, f.name[i])) break;
|
||||
if (i == f.count) return 0;
|
||||
*event_arg = i;
|
||||
if (!strcmp(f.type[i], "int")) *it = INT;
|
||||
else if (!strcmp(f.type[i], "ulong")) *it = ULONG;
|
||||
else if (!strcmp(f.type[i], "string")) *it = STRING;
|
||||
else if (!strcmp(f.type[i], "buffer")) *it = BUFFER;
|
||||
else return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct chunk next_chunk(char **s, database_event_format f)
|
||||
{
|
||||
char *cur = *s;
|
||||
char *name;
|
||||
enum format_item_type it;
|
||||
int event_arg;
|
||||
|
||||
/* argument in [ ] */
|
||||
if (*cur == '[') {
|
||||
*cur = 0;
|
||||
cur++;
|
||||
name = cur;
|
||||
/* no \ allowed there */
|
||||
while (*cur && *cur != ']' && *cur != '\\') cur++;
|
||||
if (*cur != ']') goto error;
|
||||
*cur = 0;
|
||||
cur++;
|
||||
*s = cur;
|
||||
if (find_argument(name, f, &it, &event_arg) == 0) goto error;
|
||||
return (struct chunk){type:C_ARG_NAME, s:name, it:it, event_arg:event_arg};
|
||||
}
|
||||
|
||||
/* { } is name of event (anything in between is smashed) */
|
||||
if (*cur == '{') {
|
||||
*cur = 0;
|
||||
cur++;
|
||||
while (*cur && *cur != '}') cur++;
|
||||
if (*cur != '}') goto error;
|
||||
*cur = 0;
|
||||
cur++;
|
||||
*s = cur;
|
||||
return (struct chunk){type:C_EVENT_NAME};
|
||||
}
|
||||
|
||||
/* anything but [ and { is raw string */
|
||||
/* TODO: deal with \ */
|
||||
name = cur;
|
||||
while (*cur && *cur != '[' && *cur != '{') cur++;
|
||||
*s = cur;
|
||||
return (struct chunk){type:C_STRING, s:name};
|
||||
|
||||
error:
|
||||
return (struct chunk){type:C_ERROR};
|
||||
}
|
||||
|
||||
logger *new_textlog(event_handler *h, void *database,
|
||||
char *event_name, char *format)
|
||||
{
|
||||
struct textlog *ret;
|
||||
int event_id;
|
||||
database_event_format f;
|
||||
char *cur;
|
||||
|
||||
ret = calloc(1, sizeof(struct textlog)); if (ret == NULL) abort();
|
||||
|
||||
ret->common.event_name = strdup(event_name);
|
||||
if (ret->common.event_name == NULL) abort();
|
||||
ret->format = strdup(format); if (ret->format == NULL) abort();
|
||||
ret->database = database;
|
||||
|
||||
event_id = event_id_from_name(database, event_name);
|
||||
|
||||
ret->common.handler_id = register_handler_function(h,event_id,_event,ret);
|
||||
|
||||
f = get_format(database, event_id);
|
||||
|
||||
/* we won't get more than strlen(format) "chunks" */
|
||||
ret->f = malloc(sizeof(struct format_item) * strlen(format));
|
||||
if (ret->f == NULL) abort();
|
||||
|
||||
cur = ret->format;
|
||||
|
||||
while (*cur) {
|
||||
struct chunk c = next_chunk(&cur, f);
|
||||
switch (c.type) {
|
||||
case C_ERROR: goto error;
|
||||
case C_STRING:
|
||||
ret->f[ret->fsize].type = INSTRING;
|
||||
ret->f[ret->fsize].s = c.s;
|
||||
break;
|
||||
case C_ARG_NAME:
|
||||
ret->f[ret->fsize].type = c.it;
|
||||
ret->f[ret->fsize].event_arg = c.event_arg;
|
||||
break;
|
||||
case C_EVENT_NAME:
|
||||
ret->f[ret->fsize].type = INSTRING;
|
||||
ret->f[ret->fsize].s = ret->common.event_name;
|
||||
break;
|
||||
}
|
||||
ret->fsize++;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
error:
|
||||
printf("%s:%d: bad format '%s'\n", __FILE__, __LINE__, format);
|
||||
abort();
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
#include "logger.h"
|
||||
#include "logger_defs.h"
|
||||
#include "event.h"
|
||||
#include "database.h"
|
||||
#include "handler.h"
|
||||
#include "filter/filter.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
struct ticklog {
|
||||
struct logger common;
|
||||
void *database;
|
||||
int frame_arg;
|
||||
int subframe_arg;
|
||||
};
|
||||
|
||||
static void _event(void *p, event e)
|
||||
{
|
||||
struct ticklog *l = p;
|
||||
int i;
|
||||
int frame;
|
||||
int subframe;
|
||||
|
||||
if (l->common.filter != NULL && filter_eval(l->common.filter, e) == 0)
|
||||
return;
|
||||
|
||||
frame = e.e[l->frame_arg].i;
|
||||
subframe = e.e[l->subframe_arg].i;
|
||||
|
||||
for (i = 0; i < l->common.vsize; i++)
|
||||
l->common.v[i]->append(l->common.v[i], e.sending_time, frame, subframe);
|
||||
}
|
||||
|
||||
logger *new_ticklog(event_handler *h, void *database,
|
||||
char *event_name, char *frame_varname, char *subframe_varname)
|
||||
{
|
||||
struct ticklog *ret;
|
||||
int event_id;
|
||||
database_event_format f;
|
||||
int i;
|
||||
|
||||
ret = calloc(1, sizeof(struct ticklog)); if (ret == NULL) abort();
|
||||
|
||||
ret->common.event_name = strdup(event_name);
|
||||
if (ret->common.event_name == NULL) abort();
|
||||
ret->database = database;
|
||||
|
||||
event_id = event_id_from_name(database, event_name);
|
||||
|
||||
ret->common.handler_id = register_handler_function(h,event_id,_event,ret);
|
||||
|
||||
f = get_format(database, event_id);
|
||||
|
||||
/* look for frame and subframe args */
|
||||
ret->frame_arg = -1;
|
||||
ret->subframe_arg = -1;
|
||||
for (i = 0; i < f.count; i++) {
|
||||
if (!strcmp(f.name[i], frame_varname)) ret->frame_arg = i;
|
||||
if (!strcmp(f.name[i], subframe_varname)) ret->subframe_arg = i;
|
||||
}
|
||||
if (ret->frame_arg == -1) {
|
||||
printf("%s:%d: frame argument '%s' not found in event '%s'\n",
|
||||
__FILE__, __LINE__, frame_varname, event_name);
|
||||
abort();
|
||||
}
|
||||
if (ret->subframe_arg == -1) {
|
||||
printf("%s:%d: subframe argument '%s' not found in event '%s'\n",
|
||||
__FILE__, __LINE__, subframe_varname, event_name);
|
||||
abort();
|
||||
}
|
||||
if (strcmp(f.type[ret->frame_arg], "int") != 0) {
|
||||
printf("%s:%d: argument '%s' has wrong type (should be 'int')\n",
|
||||
__FILE__, __LINE__, frame_varname);
|
||||
abort();
|
||||
}
|
||||
if (strcmp(f.type[ret->subframe_arg], "int") != 0) {
|
||||
printf("%s:%d: argument '%s' has wrong type (should be 'int')\n",
|
||||
__FILE__, __LINE__, subframe_varname);
|
||||
abort();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
#include "logger.h"
|
||||
#include "logger_defs.h"
|
||||
#include "event.h"
|
||||
#include "database.h"
|
||||
#include "handler.h"
|
||||
#include "filter/filter.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
struct timelog {
|
||||
struct logger common;
|
||||
};
|
||||
|
||||
static void _event(void *p, event e)
|
||||
{
|
||||
struct timelog *l = p;
|
||||
int i;
|
||||
|
||||
if (l->common.filter != NULL && filter_eval(l->common.filter, e) == 0)
|
||||
return;
|
||||
|
||||
for (i = 0; i < l->common.vsize; i++)
|
||||
l->common.v[i]->append(l->common.v[i], e.sending_time);
|
||||
}
|
||||
|
||||
logger *new_timelog(event_handler *h, void *database, char *event_name)
|
||||
{
|
||||
struct timelog *ret;
|
||||
int event_id;
|
||||
|
||||
ret = calloc(1, sizeof(struct timelog)); if (ret == NULL) abort();
|
||||
|
||||
ret->common.event_name = strdup(event_name);
|
||||
if (ret->common.event_name == NULL) abort();
|
||||
|
||||
event_id = event_id_from_name(database, event_name);
|
||||
|
||||
ret->common.handler_id = register_handler_function(h,event_id,_event,ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
#include "logger.h"
|
||||
#include "logger_defs.h"
|
||||
#include "event.h"
|
||||
#include "database.h"
|
||||
#include "handler.h"
|
||||
#include "filter/filter.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
struct ttilog {
|
||||
struct logger common;
|
||||
void *database;
|
||||
int frame_arg;
|
||||
int subframe_arg;
|
||||
int data_arg;
|
||||
int convert_to_dB;
|
||||
};
|
||||
|
||||
static void _event(void *p, event e)
|
||||
{
|
||||
struct ttilog *l = p;
|
||||
int i;
|
||||
int frame;
|
||||
int subframe;
|
||||
float value;
|
||||
|
||||
if (l->common.filter != NULL && filter_eval(l->common.filter, e) == 0)
|
||||
return;
|
||||
|
||||
frame = e.e[l->frame_arg].i;
|
||||
subframe = e.e[l->subframe_arg].i;
|
||||
switch (e.e[l->data_arg].type) {
|
||||
case EVENT_INT: value = e.e[l->data_arg].i; break;
|
||||
case EVENT_ULONG: value = e.e[l->data_arg].ul; break;
|
||||
default: printf("%s:%d: unsupported type\n", __FILE__, __LINE__); abort();
|
||||
}
|
||||
|
||||
if (l->convert_to_dB) value = 10 * log10(value);
|
||||
|
||||
for (i = 0; i < l->common.vsize; i++)
|
||||
l->common.v[i]->append(l->common.v[i], frame, subframe, value);
|
||||
}
|
||||
|
||||
logger *new_ttilog(event_handler *h, void *database,
|
||||
char *event_name, char *frame_varname, char *subframe_varname,
|
||||
char *data_varname, int convert_to_dB)
|
||||
{
|
||||
struct ttilog *ret;
|
||||
int event_id;
|
||||
database_event_format f;
|
||||
int i;
|
||||
|
||||
ret = calloc(1, sizeof(struct ttilog)); if (ret == NULL) abort();
|
||||
|
||||
ret->common.event_name = strdup(event_name);
|
||||
if (ret->common.event_name == NULL) abort();
|
||||
ret->database = database;
|
||||
ret->convert_to_dB = convert_to_dB;
|
||||
|
||||
event_id = event_id_from_name(database, event_name);
|
||||
|
||||
ret->common.handler_id = register_handler_function(h,event_id,_event,ret);
|
||||
|
||||
f = get_format(database, event_id);
|
||||
|
||||
/* look for frame, subframe and data args */
|
||||
ret->frame_arg = -1;
|
||||
ret->subframe_arg = -1;
|
||||
ret->data_arg = -1;
|
||||
for (i = 0; i < f.count; i++) {
|
||||
if (!strcmp(f.name[i], frame_varname)) ret->frame_arg = i;
|
||||
if (!strcmp(f.name[i], subframe_varname)) ret->subframe_arg = i;
|
||||
if (!strcmp(f.name[i], data_varname)) ret->data_arg = i;
|
||||
}
|
||||
if (ret->frame_arg == -1) {
|
||||
printf("%s:%d: frame argument '%s' not found in event '%s'\n",
|
||||
__FILE__, __LINE__, frame_varname, event_name);
|
||||
abort();
|
||||
}
|
||||
if (ret->subframe_arg == -1) {
|
||||
printf("%s:%d: subframe argument '%s' not found in event '%s'\n",
|
||||
__FILE__, __LINE__, subframe_varname, event_name);
|
||||
abort();
|
||||
}
|
||||
if (ret->data_arg == -1) {
|
||||
printf("%s:%d: data argument '%s' not found in event '%s'\n",
|
||||
__FILE__, __LINE__, data_varname, event_name);
|
||||
abort();
|
||||
}
|
||||
if (strcmp(f.type[ret->frame_arg], "int") != 0) {
|
||||
printf("%s:%d: argument '%s' has wrong type (should be 'int')\n",
|
||||
__FILE__, __LINE__, frame_varname);
|
||||
abort();
|
||||
}
|
||||
if (strcmp(f.type[ret->subframe_arg], "int") != 0) {
|
||||
printf("%s:%d: argument '%s' has wrong type (should be 'int')\n",
|
||||
__FILE__, __LINE__, subframe_varname);
|
||||
abort();
|
||||
}
|
||||
if (strcmp(f.type[ret->data_arg], "int") != 0 &&
|
||||
strcmp(f.type[ret->data_arg], "float") != 0) {
|
||||
printf("%s:%d: argument '%s' has wrong type"
|
||||
" (should be 'int' or 'float')\n",
|
||||
__FILE__, __LINE__, data_varname);
|
||||
abort();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,395 @@
|
||||
/* this file (minus this comment) was obtained by running:
|
||||
* xxd -i openair_logo.png > openair_logo.h
|
||||
*/
|
||||
unsigned char openair_logo_png[] = {
|
||||
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d,
|
||||
0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x28,
|
||||
0x08, 0x06, 0x00, 0x00, 0x00, 0x08, 0x78, 0x5f, 0x43, 0x00, 0x00, 0x00,
|
||||
0x06, 0x62, 0x4b, 0x47, 0x44, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0xa0,
|
||||
0xbd, 0xa7, 0x93, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00,
|
||||
0x00, 0x0b, 0x13, 0x00, 0x00, 0x0b, 0x13, 0x01, 0x00, 0x9a, 0x9c, 0x18,
|
||||
0x00, 0x00, 0x00, 0x07, 0x74, 0x49, 0x4d, 0x45, 0x07, 0xe0, 0x05, 0x17,
|
||||
0x0e, 0x30, 0x2a, 0xd1, 0xdd, 0x83, 0x5b, 0x00, 0x00, 0x11, 0xc5, 0x49,
|
||||
0x44, 0x41, 0x54, 0x68, 0xde, 0xed, 0x9b, 0x79, 0x70, 0x94, 0xe7, 0x7d,
|
||||
0xc7, 0x3f, 0xcf, 0xf3, 0xbe, 0xbb, 0x2b, 0xed, 0xea, 0xbe, 0xef, 0x03,
|
||||
0x24, 0x10, 0x08, 0x8c, 0xb9, 0x31, 0x06, 0x73, 0xd4, 0xd8, 0x4e, 0x38,
|
||||
0x62, 0x63, 0x77, 0x92, 0x90, 0xcb, 0x9d, 0x34, 0x19, 0x27, 0xce, 0xa4,
|
||||
0xed, 0x8c, 0xd3, 0x78, 0xd2, 0x64, 0xd2, 0x36, 0x9d, 0x34, 0xa9, 0xdb,
|
||||
0xa6, 0x99, 0xb6, 0x49, 0x67, 0x82, 0xe3, 0x24, 0x76, 0x9a, 0x34, 0x76,
|
||||
0x5c, 0x1f, 0x18, 0x8f, 0x31, 0xc4, 0xc6, 0x06, 0xcc, 0x69, 0x21, 0xb0,
|
||||
0x05, 0x08, 0x1d, 0x80, 0x2e, 0x74, 0xae, 0xa4, 0xbd, 0xb4, 0xbb, 0xef,
|
||||
0xfb, 0x3c, 0xfd, 0x63, 0x57, 0x2b, 0xd6, 0x12, 0x58, 0x60, 0x32, 0x74,
|
||||
0xb0, 0x9f, 0x99, 0x1d, 0x69, 0x9f, 0xe7, 0xf9, 0x3d, 0xd7, 0xf7, 0x77,
|
||||
0x3f, 0xcf, 0x0a, 0xad, 0xb5, 0xe6, 0x43, 0x5a, 0x94, 0xd6, 0xf4, 0x07,
|
||||
0xc3, 0xf8, 0xa3, 0x51, 0x3a, 0x47, 0xfc, 0xf4, 0x05, 0x82, 0x0c, 0xf8,
|
||||
0x43, 0x98, 0x52, 0x50, 0xec, 0x49, 0xa5, 0x38, 0xdd, 0x4d, 0x71, 0xba,
|
||||
0x87, 0x34, 0x97, 0x93, 0x74, 0x97, 0x13, 0x21, 0xc4, 0x1f, 0x7d, 0x4d,
|
||||
0xe2, 0xc3, 0x0a, 0xc8, 0xde, 0xce, 0x3e, 0xde, 0xea, 0x1e, 0x60, 0x45,
|
||||
0x51, 0x2e, 0x45, 0x9e, 0x14, 0x72, 0x52, 0x9c, 0xa4, 0x3b, 0x1d, 0x38,
|
||||
0x0d, 0x03, 0x04, 0x44, 0x6d, 0x9b, 0x50, 0xc4, 0xc2, 0x1f, 0x8e, 0x30,
|
||||
0x1c, 0x0a, 0xd1, 0xed, 0x1d, 0xa1, 0x36, 0x3f, 0x97, 0x19, 0x05, 0xb9,
|
||||
0x1f, 0x01, 0x72, 0x3d, 0xcb, 0x68, 0x24, 0xca, 0x7f, 0x34, 0xb6, 0x30,
|
||||
0x37, 0x27, 0x83, 0x7b, 0x67, 0x96, 0x5e, 0x15, 0x6d, 0x63, 0x47, 0x0f,
|
||||
0x03, 0x23, 0x3e, 0x6e, 0x9f, 0x5d, 0x4d, 0x8a, 0xc3, 0xf1, 0x11, 0x20,
|
||||
0x1f, 0xb4, 0xbc, 0x7c, 0xbe, 0x97, 0x0e, 0x9f, 0x9f, 0x7b, 0x67, 0x94,
|
||||
0x51, 0xe0, 0x76, 0x5d, 0xd3, 0x18, 0xc1, 0x48, 0x84, 0x53, 0x1d, 0xdd,
|
||||
0xe4, 0x78, 0xdc, 0x54, 0x17, 0x15, 0x7c, 0x04, 0xc8, 0xb5, 0x96, 0x86,
|
||||
0xfe, 0x61, 0x0e, 0x5c, 0x1c, 0xe4, 0xe1, 0xf9, 0x33, 0xaf, 0xcb, 0x78,
|
||||
0xa7, 0x2e, 0x74, 0x91, 0x9b, 0x91, 0x46, 0x41, 0x56, 0xe6, 0x75, 0x5d,
|
||||
0xa7, 0xfc, 0x30, 0x80, 0xb1, 0xaf, 0x67, 0x90, 0x97, 0xcf, 0xf7, 0x4d,
|
||||
0x0b, 0x8c, 0xd1, 0x70, 0x04, 0x7f, 0x38, 0xfa, 0xbe, 0xfd, 0xe6, 0x54,
|
||||
0x94, 0xd2, 0x33, 0xe8, 0x65, 0x60, 0x78, 0xe4, 0xba, 0xae, 0xd5, 0xbc,
|
||||
0xd9, 0xc1, 0x08, 0x5a, 0x36, 0xfb, 0x7b, 0x86, 0xf8, 0xd6, 0x92, 0x59,
|
||||
0x97, 0xed, 0xd3, 0xe1, 0x0b, 0xf2, 0xf8, 0x89, 0xb3, 0x48, 0x65, 0x33,
|
||||
0x33, 0xc3, 0x83, 0x43, 0x08, 0x46, 0x82, 0x21, 0xd2, 0x1d, 0x06, 0x1b,
|
||||
0xea, 0x66, 0x90, 0xeb, 0x71, 0x4f, 0x49, 0xb7, 0x60, 0x66, 0x15, 0x0d,
|
||||
0x67, 0x5a, 0xc8, 0xf0, 0xb8, 0x71, 0x5e, 0x27, 0x9b, 0x72, 0xd3, 0xab,
|
||||
0xac, 0x7f, 0x6a, 0x38, 0xcb, 0xa6, 0xaa, 0x22, 0xe6, 0x66, 0xa7, 0x4f,
|
||||
0x6a, 0x3b, 0x37, 0x1a, 0x64, 0xe7, 0xb9, 0x6e, 0xb2, 0x9d, 0x0e, 0xb6,
|
||||
0xd6, 0x96, 0xe3, 0x32, 0x92, 0x15, 0x86, 0x65, 0x2b, 0x1a, 0x3b, 0xba,
|
||||
0x51, 0xb6, 0xa2, 0xb6, 0x28, 0x8f, 0xac, 0x29, 0x80, 0x09, 0x85, 0xc3,
|
||||
0xf4, 0x0d, 0x0e, 0x53, 0x59, 0x52, 0xf8, 0x91, 0x84, 0xbc, 0x5f, 0x79,
|
||||
0x77, 0xc8, 0x87, 0x37, 0x6c, 0x4d, 0x09, 0x46, 0x87, 0x2f, 0xc4, 0x4f,
|
||||
0xdf, 0x69, 0xe3, 0x6f, 0x97, 0xcd, 0x21, 0xd5, 0x34, 0xa6, 0x3e, 0x1c,
|
||||
0x43, 0xb2, 0xb8, 0xaa, 0x8c, 0xa8, 0x6d, 0xd3, 0xd8, 0x7a, 0x9e, 0xb9,
|
||||
0x95, 0xa5, 0xb8, 0x5d, 0xc9, 0xce, 0x40, 0xaa, 0xcb, 0xc5, 0xa8, 0xdf,
|
||||
0x8f, 0x52, 0xf9, 0x48, 0x79, 0x1d, 0x2c, 0x80, 0xbe, 0x89, 0xcb, 0x5f,
|
||||
0xee, 0x3b, 0xa9, 0xb5, 0x9a, 0x5c, 0xdf, 0x1f, 0x0a, 0xeb, 0x07, 0x77,
|
||||
0x1f, 0x9b, 0x54, 0xef, 0x1d, 0x0b, 0xeb, 0xd6, 0xa1, 0x11, 0x7d, 0xde,
|
||||
0x3b, 0xaa, 0xfd, 0xe1, 0x48, 0x52, 0x9b, 0xd2, 0x4a, 0xbf, 0x71, 0xfc,
|
||||
0x1d, 0x1d, 0x89, 0x46, 0x27, 0xd1, 0x05, 0x82, 0x21, 0x7d, 0xa6, 0xa5,
|
||||
0xed, 0xba, 0xac, 0xf9, 0xa6, 0x95, 0x90, 0xd1, 0x88, 0x45, 0x65, 0x7a,
|
||||
0x2a, 0x4c, 0x11, 0x5c, 0x3f, 0xdd, 0xd2, 0xc5, 0xbf, 0xae, 0x9a, 0x9f,
|
||||
0x54, 0xf7, 0xc3, 0xa3, 0xa7, 0x29, 0x48, 0x71, 0xb0, 0xa2, 0x30, 0x07,
|
||||
0x5b, 0xc0, 0xa1, 0xf6, 0x0e, 0xa4, 0xb2, 0x59, 0x3b, 0xa7, 0x36, 0xa6,
|
||||
0xdb, 0x11, 0xac, 0x9c, 0x3f, 0x87, 0xd3, 0xed, 0xe7, 0xa9, 0x9f, 0x59,
|
||||
0x9d, 0x44, 0xeb, 0x4e, 0x4d, 0x21, 0x1c, 0x8d, 0x60, 0xdb, 0x0a, 0xc3,
|
||||
0x90, 0xfc, 0x67, 0x63, 0x1b, 0xbf, 0x69, 0xef, 0x27, 0x64, 0xab, 0xd8,
|
||||
0xf4, 0xd2, 0x60, 0xd7, 0xc7, 0x17, 0x91, 0xe3, 0x8a, 0x1d, 0xf7, 0xe3,
|
||||
0xef, 0x9c, 0xe3, 0x17, 0x67, 0x7b, 0xc9, 0x4e, 0x75, 0xf1, 0xcd, 0x85,
|
||||
0xd5, 0xdc, 0x5e, 0x98, 0x79, 0xf3, 0xab, 0xac, 0xe1, 0x48, 0x74, 0x4a,
|
||||
0x55, 0x15, 0xb2, 0x6d, 0xbc, 0x91, 0x28, 0xd9, 0xae, 0x09, 0x23, 0xfc,
|
||||
0x58, 0x43, 0x33, 0x9b, 0x67, 0x94, 0x32, 0x37, 0x67, 0xa2, 0x7f, 0x6d,
|
||||
0x5e, 0x36, 0x43, 0xfe, 0x20, 0x0d, 0x2d, 0xed, 0x2c, 0xac, 0x89, 0x01,
|
||||
0x60, 0x48, 0x49, 0xa6, 0xc7, 0x43, 0x24, 0x1a, 0x9d, 0x64, 0xc4, 0x0b,
|
||||
0x72, 0x73, 0x09, 0x04, 0x83, 0x64, 0xa4, 0xa7, 0xd1, 0x36, 0x1a, 0xa4,
|
||||
0x69, 0x38, 0xcc, 0x33, 0x1b, 0xea, 0x09, 0x5a, 0x0a, 0x1b, 0xf0, 0x98,
|
||||
0x12, 0xb4, 0x66, 0xcb, 0x8b, 0x87, 0x79, 0x7b, 0x34, 0xc2, 0xf7, 0x97,
|
||||
0xd5, 0xd0, 0x33, 0xea, 0xe7, 0xae, 0x17, 0x8e, 0xf0, 0xe4, 0x5d, 0x8b,
|
||||
0xd8, 0x5a, 0x99, 0x73, 0x73, 0x03, 0x32, 0x12, 0x89, 0x92, 0xee, 0x9c,
|
||||
0xbc, 0xbd, 0x5f, 0x9e, 0xee, 0x60, 0x55, 0xf1, 0x44, 0xfa, 0xe3, 0xdf,
|
||||
0x1a, 0x5b, 0x59, 0x92, 0x9f, 0x93, 0x04, 0xc6, 0x78, 0xc9, 0x49, 0x73,
|
||||
0x13, 0xcc, 0x48, 0xa7, 0x7f, 0xc8, 0x4b, 0x7e, 0x4e, 0x36, 0x00, 0x69,
|
||||
0xee, 0x54, 0x02, 0x81, 0x20, 0xce, 0xf7, 0xc4, 0x1f, 0x99, 0xe9, 0xe9,
|
||||
0xf8, 0xfc, 0x7e, 0x74, 0x9a, 0x07, 0x7f, 0xd4, 0x26, 0xc3, 0x65, 0x72,
|
||||
0xbc, 0x6f, 0x04, 0xbf, 0xd2, 0x3c, 0x30, 0xa3, 0x18, 0x97, 0x21, 0x19,
|
||||
0x0c, 0x8e, 0x71, 0xc6, 0x1f, 0x66, 0x43, 0x65, 0x11, 0x9f, 0x9f, 0x55,
|
||||
0x0c, 0xc0, 0x17, 0xeb, 0x2b, 0x89, 0xe8, 0x0f, 0x41, 0x1c, 0xd2, 0x13,
|
||||
0x1c, 0x23, 0x63, 0x0a, 0x57, 0xf4, 0xe5, 0x0b, 0xbd, 0xdc, 0x56, 0x18,
|
||||
0xe3, 0x46, 0x0d, 0x1c, 0xe9, 0x1f, 0x66, 0x5d, 0x59, 0x5e, 0xcc, 0xab,
|
||||
0xd2, 0x9a, 0xed, 0xa7, 0x3a, 0xd9, 0x7e, 0xaa, 0x13, 0x3b, 0xee, 0x7c,
|
||||
0x96, 0x15, 0xe4, 0xd1, 0x76, 0xa1, 0x73, 0xc2, 0x88, 0xa7, 0xb8, 0x18,
|
||||
0x1e, 0xf5, 0x4d, 0x0e, 0xe8, 0x0c, 0x09, 0x08, 0x34, 0x10, 0x88, 0x5a,
|
||||
0x78, 0x43, 0x21, 0x5e, 0xec, 0x18, 0x62, 0x5f, 0xe7, 0x20, 0x8b, 0x9f,
|
||||
0x39, 0xc0, 0x6f, 0xdb, 0x07, 0x70, 0x4a, 0x81, 0x00, 0x0c, 0x21, 0xe8,
|
||||
0x1d, 0xf1, 0xb1, 0xf8, 0x99, 0xb7, 0xd8, 0xb8, 0xf3, 0x18, 0x47, 0x07,
|
||||
0xfc, 0x37, 0x3f, 0x20, 0x1e, 0xc3, 0x24, 0xcb, 0x35, 0x19, 0x90, 0xd9,
|
||||
0x59, 0x69, 0x38, 0xa4, 0x48, 0xe4, 0xb5, 0xee, 0xad, 0x2e, 0x4e, 0xb4,
|
||||
0xf5, 0x06, 0x23, 0xbc, 0x70, 0xae, 0x8f, 0x1d, 0xe7, 0xfb, 0x39, 0xed,
|
||||
0x0d, 0x24, 0xea, 0x73, 0x33, 0x33, 0x12, 0xff, 0x3b, 0x4c, 0x13, 0xa7,
|
||||
0x39, 0x59, 0xf2, 0xa4, 0x90, 0x38, 0x1c, 0x26, 0x42, 0x08, 0xfe, 0xe2,
|
||||
0xd6, 0x99, 0xfc, 0x6e, 0xc3, 0xad, 0xbc, 0xb6, 0x65, 0x09, 0xbb, 0x3e,
|
||||
0xb1, 0x8c, 0xfb, 0xcb, 0xb3, 0xf8, 0x61, 0xc3, 0xb9, 0x84, 0x37, 0x27,
|
||||
0x80, 0x5c, 0x4f, 0x2a, 0xdf, 0x5e, 0x3c, 0x83, 0x40, 0x34, 0xca, 0xf6,
|
||||
0xa6, 0xee, 0x9b, 0xdf, 0x86, 0xdc, 0x5e, 0x9c, 0x33, 0x75, 0x5c, 0x72,
|
||||
0x5b, 0xfd, 0x84, 0x9a, 0x71, 0x3a, 0xf8, 0xd3, 0x99, 0x25, 0x89, 0xef,
|
||||
0xa5, 0x1e, 0x17, 0x2f, 0x7c, 0x6c, 0xd1, 0x24, 0x9a, 0x9a, 0xea, 0xca,
|
||||
0x89, 0x83, 0x97, 0x92, 0xd2, 0x92, 0xa2, 0xc9, 0x2e, 0xb2, 0x69, 0x90,
|
||||
0x95, 0x99, 0x81, 0xd2, 0x9a, 0x1d, 0x6d, 0x17, 0x39, 0xe8, 0x0d, 0xb1,
|
||||
0xa1, 0x2c, 0x17, 0x8d, 0x26, 0x60, 0xd9, 0xb8, 0x1d, 0x4e, 0x24, 0x60,
|
||||
0x4a, 0xc1, 0xc5, 0xe0, 0x18, 0xd2, 0x30, 0x59, 0x5d, 0x94, 0x85, 0x29,
|
||||
0x48, 0x30, 0xc8, 0xa4, 0xc0, 0x30, 0x14, 0x0a, 0xd2, 0xd1, 0xd1, 0x85,
|
||||
0xdf, 0xef, 0xc7, 0x30, 0x0c, 0x72, 0x73, 0x73, 0x28, 0x2b, 0x2b, 0x9b,
|
||||
0x34, 0x79, 0x67, 0x67, 0x27, 0x7d, 0x7d, 0x7d, 0xc9, 0x11, 0xa6, 0x10,
|
||||
0xa4, 0xa5, 0xa5, 0x51, 0x56, 0x56, 0x4e, 0x6a, 0x6a, 0xca, 0x24, 0x9a,
|
||||
0xf6, 0xf6, 0x76, 0xbc, 0x5e, 0xef, 0x94, 0x87, 0xa4, 0x94, 0xa2, 0xb8,
|
||||
0xb8, 0x98, 0xd2, 0xd2, 0x58, 0xf6, 0xb5, 0xbf, 0xbf, 0x9f, 0x8e, 0x8e,
|
||||
0x0e, 0x4a, 0x4b, 0x4b, 0x29, 0x2c, 0x2c, 0xbc, 0xd4, 0x45, 0xa7, 0xb9,
|
||||
0xb9, 0x99, 0x40, 0x20, 0x80, 0xd3, 0xe9, 0xa4, 0xbe, 0xbe, 0xfe, 0xaa,
|
||||
0xee, 0x28, 0x0e, 0x5c, 0x1c, 0xe6, 0xf8, 0xa0, 0x8f, 0x95, 0x85, 0x59,
|
||||
0xdc, 0x9a, 0x37, 0xd9, 0x66, 0x74, 0x07, 0xc2, 0x3c, 0xdd, 0x7a, 0x11,
|
||||
0x29, 0x04, 0x1b, 0xca, 0x73, 0xa9, 0xcb, 0xf2, 0x4c, 0xd0, 0x0d, 0x8c,
|
||||
0xa2, 0x92, 0x24, 0x42, 0x50, 0x90, 0xe2, 0x64, 0x79, 0x61, 0x26, 0xe5,
|
||||
0x69, 0xc9, 0xfb, 0x7d, 0x77, 0x60, 0x84, 0x47, 0xde, 0x3a, 0xc3, 0xbb,
|
||||
0xc3, 0x21, 0x9c, 0x02, 0x8a, 0xd3, 0xdd, 0xfc, 0xe4, 0x8e, 0x7a, 0xe6,
|
||||
0x67, 0xbb, 0xd9, 0xd1, 0xda, 0xc3, 0x3f, 0x34, 0xb4, 0x33, 0x10, 0xb6,
|
||||
0x89, 0xda, 0x36, 0x17, 0x02, 0x63, 0x6c, 0xa8, 0x28, 0x61, 0xd7, 0xc6,
|
||||
0x5b, 0x92, 0x25, 0xe4, 0xb5, 0xd7, 0x5e, 0xa7, 0xb1, 0xb1, 0x71, 0xd2,
|
||||
0x22, 0x0d, 0xc3, 0x60, 0xf3, 0xe6, 0x4d, 0x54, 0x55, 0x55, 0x01, 0xd0,
|
||||
0xd2, 0xd2, 0xca, 0x73, 0xcf, 0x3d, 0x87, 0x69, 0x5e, 0x5e, 0xb8, 0xe6,
|
||||
0xcd, 0x9b, 0xc7, 0x9d, 0x77, 0xfe, 0x49, 0xe2, 0xfb, 0xd1, 0xa3, 0x47,
|
||||
0xd9, 0xbb, 0xf7, 0x0d, 0x0c, 0x63, 0xea, 0x00, 0xcc, 0xb6, 0x6d, 0x56,
|
||||
0xac, 0x58, 0x4e, 0x69, 0x69, 0x29, 0xd1, 0x68, 0x94, 0x27, 0x9e, 0xf8,
|
||||
0x05, 0x4e, 0xa7, 0x13, 0x87, 0xc3, 0xc1, 0xb6, 0x6d, 0x9f, 0x26, 0x3b,
|
||||
0x3b, 0x3b, 0x01, 0xdc, 0xf1, 0xe3, 0x8d, 0xf4, 0xf4, 0xf4, 0x90, 0x99,
|
||||
0x99, 0x49, 0x7d, 0x7d, 0xfd, 0xb4, 0xc1, 0xd8, 0xdb, 0x33, 0xc4, 0xdd,
|
||||
0x3b, 0x8e, 0xe1, 0x36, 0x0d, 0xa2, 0x4a, 0x73, 0xf4, 0xfe, 0x15, 0xcc,
|
||||
0x8e, 0x1f, 0xf8, 0x78, 0x39, 0xef, 0x0f, 0xf1, 0xe8, 0xa1, 0xb3, 0xb8,
|
||||
0x0c, 0x41, 0x5e, 0x8a, 0x83, 0xba, 0x2c, 0x0f, 0xbb, 0x3b, 0x07, 0xf9,
|
||||
0xe4, 0xee, 0x46, 0xa6, 0xca, 0x67, 0x8c, 0xb3, 0xc2, 0x7d, 0xd5, 0x85,
|
||||
0x6c, 0x5f, 0x3b, 0xb1, 0x96, 0xfa, 0xbc, 0x4c, 0x76, 0x6e, 0x5e, 0xc6,
|
||||
0x38, 0xaf, 0x0b, 0x21, 0x12, 0x7d, 0x37, 0xcd, 0x2c, 0x66, 0xe3, 0x8c,
|
||||
0x62, 0x34, 0xfa, 0x92, 0x71, 0x26, 0x98, 0xca, 0xb4, 0x6d, 0x9b, 0x17,
|
||||
0x5e, 0x78, 0x91, 0xd6, 0xd6, 0x56, 0x84, 0x10, 0x54, 0x54, 0x94, 0x53,
|
||||
0x54, 0x54, 0x44, 0x24, 0x12, 0xa5, 0xad, 0xad, 0x8d, 0x40, 0x20, 0xc0,
|
||||
0xef, 0x7f, 0xff, 0x2c, 0x5b, 0xb7, 0xde, 0x47, 0x75, 0x75, 0x35, 0x3e,
|
||||
0x9f, 0x0f, 0x21, 0x04, 0x4a, 0x29, 0x66, 0xcc, 0x98, 0x41, 0x41, 0x41,
|
||||
0x01, 0x5a, 0x2b, 0x6c, 0x5b, 0xd1, 0xd3, 0xd3, 0x43, 0x57, 0x57, 0x17,
|
||||
0x8d, 0x8d, 0x8d, 0x8c, 0x8e, 0xfa, 0xb8, 0xf7, 0xde, 0x2d, 0x48, 0x29,
|
||||
0xf1, 0x7a, 0x87, 0x13, 0x34, 0x75, 0x75, 0x75, 0x64, 0x65, 0x65, 0x72,
|
||||
0x69, 0xc6, 0x46, 0x29, 0x4d, 0x69, 0x69, 0x4c, 0x12, 0xfd, 0x7e, 0x7f,
|
||||
0xa2, 0x2d, 0x1c, 0x0e, 0xb3, 0x67, 0xcf, 0x6b, 0x3c, 0xf0, 0xc0, 0xd6,
|
||||
0x0f, 0xac, 0xc2, 0xbe, 0xf6, 0xe6, 0x69, 0x52, 0xe2, 0xa9, 0x11, 0x01,
|
||||
0xfc, 0xd5, 0xfe, 0x33, 0xec, 0xdc, 0x98, 0xac, 0x9e, 0xf4, 0x7b, 0xfe,
|
||||
0x02, 0x0c, 0x86, 0xa3, 0x68, 0x1d, 0x33, 0xf8, 0x6b, 0x8b, 0x73, 0x58,
|
||||
0x51, 0x98, 0x89, 0xa5, 0x35, 0x96, 0xd2, 0x9c, 0x1c, 0xf2, 0xb1, 0xab,
|
||||
0x63, 0x90, 0xff, 0x6e, 0xe9, 0xe1, 0x1d, 0xaf, 0x8f, 0x5d, 0x1b, 0x97,
|
||||
0x90, 0x11, 0xf7, 0xec, 0x44, 0x1c, 0x88, 0x29, 0xf3, 0x55, 0x22, 0x19,
|
||||
0x84, 0x24, 0xd5, 0x37, 0x3a, 0x3a, 0x4a, 0x47, 0x47, 0x07, 0x86, 0x61,
|
||||
0x24, 0x38, 0x7b, 0x7c, 0xa0, 0x45, 0x8b, 0x16, 0xf2, 0xd4, 0x53, 0xbf,
|
||||
0x46, 0x6b, 0xcd, 0xab, 0xaf, 0xee, 0xe6, 0xcb, 0x5f, 0xfe, 0x52, 0xa2,
|
||||
0x4d, 0x29, 0x45, 0x4d, 0xcd, 0x4c, 0xe6, 0xcd, 0x9b, 0x97, 0xc4, 0xe9,
|
||||
0x3b, 0x77, 0xbe, 0x4c, 0x6b, 0x6b, 0x2b, 0xed, 0xed, 0xed, 0x84, 0xc3,
|
||||
0x61, 0x52, 0x53, 0x53, 0x13, 0x34, 0xb6, 0x6d, 0x53, 0x5f, 0x3f, 0x97,
|
||||
0xca, 0xca, 0xca, 0xcb, 0x27, 0xd7, 0x2e, 0xd9, 0x84, 0x94, 0x92, 0xf3,
|
||||
0xe7, 0xcf, 0x71, 0xe2, 0xc4, 0x49, 0x6e, 0xb9, 0x65, 0xfe, 0x35, 0x83,
|
||||
0xb1, 0xb7, 0xdb, 0xcb, 0x05, 0x7f, 0x08, 0x43, 0x08, 0x6c, 0xad, 0x31,
|
||||
0xa5, 0xe0, 0x8d, 0x8b, 0x5e, 0xce, 0x8e, 0x04, 0xa9, 0xcd, 0x74, 0x5f,
|
||||
0x39, 0xd9, 0x17, 0x3f, 0x38, 0x4b, 0x69, 0xee, 0x2c, 0xcb, 0xe1, 0xeb,
|
||||
0xf3, 0x93, 0xd7, 0xfe, 0x9d, 0xc3, 0x67, 0xf9, 0xf1, 0xc9, 0x0b, 0x9c,
|
||||
0x1d, 0x0e, 0x72, 0xa0, 0x77, 0x98, 0x7b, 0xca, 0xf3, 0x3e, 0x58, 0xfa,
|
||||
0x5d, 0x29, 0x85, 0x6d, 0xdb, 0x00, 0x14, 0x16, 0x16, 0x24, 0x1d, 0x48,
|
||||
0x76, 0x76, 0x36, 0x5a, 0x6b, 0x84, 0x10, 0x04, 0x83, 0xc1, 0xe9, 0xa4,
|
||||
0x61, 0x88, 0x46, 0x63, 0xa9, 0xeb, 0x71, 0x8f, 0x63, 0x2a, 0xee, 0xb8,
|
||||
0x9a, 0x62, 0x18, 0x06, 0xfb, 0xf7, 0xef, 0x23, 0x18, 0x0c, 0x5d, 0x5b,
|
||||
0x6a, 0x08, 0x78, 0xaa, 0xb9, 0x1b, 0x43, 0x08, 0x94, 0xd6, 0x3c, 0xb2,
|
||||
0xa0, 0x8a, 0x90, 0x65, 0xe3, 0x90, 0x82, 0xff, 0x6a, 0xba, 0xf0, 0x81,
|
||||
0x25, 0x2f, 0x60, 0xd9, 0x89, 0x7d, 0xa5, 0x1a, 0x1f, 0xdc, 0x69, 0x35,
|
||||
0x93, 0x8d, 0xab, 0x9e, 0x16, 0xe7, 0x4e, 0x78, 0x16, 0x31, 0xf2, 0xa1,
|
||||
0xa1, 0x21, 0x4e, 0x9d, 0x3a, 0x4d, 0x53, 0x53, 0x13, 0x81, 0x40, 0x80,
|
||||
0x68, 0x34, 0xca, 0xaa, 0x55, 0xb7, 0x93, 0x92, 0x92, 0x32, 0x69, 0x0c,
|
||||
0x9f, 0x2f, 0xc0, 0xe8, 0xe8, 0x08, 0x4a, 0x69, 0xb4, 0x56, 0x64, 0x66,
|
||||
0x66, 0x5d, 0x36, 0x29, 0xe7, 0x74, 0x3a, 0xb1, 0x2c, 0x8b, 0xb1, 0xb1,
|
||||
0x30, 0x47, 0x8e, 0x1c, 0x61, 0xcd, 0x9a, 0x3b, 0xae, 0xfe, 0xc0, 0xa2,
|
||||
0x36, 0x7b, 0xba, 0x06, 0x01, 0x58, 0x55, 0x9c, 0xcd, 0xb7, 0x17, 0xcd,
|
||||
0xe4, 0x7f, 0xdb, 0xfb, 0x38, 0xe7, 0x0b, 0xf1, 0x87, 0xae, 0x21, 0x7c,
|
||||
0x51, 0x8b, 0x74, 0xc7, 0xd5, 0x3b, 0x9b, 0xaf, 0x74, 0x0c, 0xf0, 0xfd,
|
||||
0xb7, 0xdb, 0x38, 0x39, 0xe4, 0xc7, 0xd2, 0x9a, 0xf5, 0x45, 0x39, 0xac,
|
||||
0x29, 0xc9, 0xb9, 0x71, 0xd9, 0x5e, 0xd3, 0x34, 0xd9, 0xbd, 0x7b, 0x0f,
|
||||
0xcf, 0x3f, 0xff, 0x02, 0x5a, 0x6b, 0xa4, 0x94, 0x78, 0x3c, 0x1e, 0x0a,
|
||||
0x0b, 0x0b, 0x58, 0xb1, 0xe2, 0x36, 0xaa, 0xab, 0xab, 0xa6, 0xa4, 0x79,
|
||||
0xe9, 0xa5, 0x9d, 0xd8, 0xb6, 0x8d, 0x10, 0x82, 0x50, 0x28, 0xc4, 0x37,
|
||||
0xbe, 0xf1, 0x08, 0x69, 0x69, 0x9e, 0x29, 0xe7, 0x28, 0x2c, 0x2c, 0xc4,
|
||||
0xb2, 0xa2, 0xf4, 0xf4, 0x5c, 0xe4, 0xd0, 0xa1, 0x43, 0xd4, 0xd6, 0xd6,
|
||||
0x5c, 0x75, 0x46, 0xf5, 0x77, 0x2d, 0x17, 0xe9, 0x0e, 0x86, 0xf1, 0x98,
|
||||
0x06, 0x5b, 0xab, 0x0b, 0x11, 0x02, 0x3e, 0x5b, 0x5b, 0xc2, 0x3f, 0xbc,
|
||||
0xdd, 0xca, 0x69, 0x6f, 0x90, 0xe3, 0x03, 0x3e, 0x56, 0x17, 0x67, 0x4f,
|
||||
0xef, 0xae, 0x02, 0xc1, 0x33, 0x6d, 0xbd, 0x3c, 0xfc, 0x66, 0x13, 0xde,
|
||||
0xb0, 0x85, 0x43, 0x0a, 0x72, 0x53, 0x1c, 0x7c, 0x69, 0x4e, 0x19, 0x3f,
|
||||
0x5c, 0x31, 0xeb, 0xc6, 0xa7, 0xdf, 0x23, 0x91, 0x08, 0x85, 0x85, 0x05,
|
||||
0x14, 0x17, 0x17, 0x53, 0x55, 0x55, 0x4d, 0x7e, 0x7e, 0x1e, 0x59, 0x59,
|
||||
0x97, 0xe7, 0x78, 0xa5, 0x14, 0x95, 0x95, 0xe5, 0xa4, 0xa6, 0xba, 0x01,
|
||||
0x4d, 0x24, 0x12, 0xc1, 0x71, 0x05, 0xee, 0x34, 0x4d, 0x93, 0x75, 0xeb,
|
||||
0xd6, 0xf2, 0xb3, 0x9f, 0x6d, 0xc7, 0xe5, 0x72, 0xb1, 0x63, 0xc7, 0x0e,
|
||||
0xdc, 0x6e, 0xcf, 0x55, 0xad, 0xf1, 0x9b, 0x87, 0x9a, 0x71, 0x9b, 0x06,
|
||||
0x52, 0x08, 0xb6, 0xd5, 0xc6, 0x82, 0xc0, 0xad, 0x33, 0x0a, 0x78, 0xac,
|
||||
0xb1, 0x1d, 0x5b, 0x6b, 0xfe, 0xe6, 0xf0, 0x59, 0xde, 0xf8, 0xc4, 0xb2,
|
||||
0x69, 0x8d, 0xe5, 0x34, 0x04, 0x0f, 0xbd, 0xd1, 0x84, 0xad, 0x35, 0x45,
|
||||
0x6e, 0x27, 0xdf, 0x5b, 0x5a, 0xcb, 0x1d, 0x25, 0xd9, 0x54, 0xa7, 0xa7,
|
||||
0x5e, 0xb7, 0xf8, 0xc9, 0xbc, 0x56, 0xfd, 0x6e, 0x59, 0x16, 0x9b, 0x36,
|
||||
0x6d, 0xa4, 0xae, 0xae, 0x6e, 0xda, 0x34, 0xb6, 0x6d, 0xb3, 0x72, 0xe5,
|
||||
0x4a, 0xca, 0xcb, 0xcb, 0xa7, 0x7b, 0x35, 0x40, 0x4e, 0x4e, 0x0e, 0xb7,
|
||||
0xdf, 0xbe, 0x92, 0xc3, 0x87, 0x8f, 0x10, 0x0c, 0x86, 0x08, 0x04, 0x82,
|
||||
0xd3, 0x8e, 0x3d, 0x9e, 0x38, 0xdd, 0xc5, 0x98, 0xad, 0x30, 0xa5, 0xc0,
|
||||
0xed, 0x30, 0x78, 0x68, 0x6f, 0x13, 0x11, 0x15, 0xfb, 0x6e, 0x6b, 0x8d,
|
||||
0x21, 0x04, 0x07, 0xfb, 0x46, 0x38, 0xd2, 0x37, 0xc2, 0xd2, 0x82, 0xf7,
|
||||
0xbf, 0x1b, 0xb7, 0x94, 0xe6, 0xcf, 0xea, 0x4a, 0xf8, 0x59, 0x53, 0x17,
|
||||
0xde, 0x70, 0x94, 0x53, 0x5e, 0x3f, 0x5f, 0x98, 0x5d, 0x72, 0x5d, 0x03,
|
||||
0xda, 0xf7, 0x95, 0xff, 0xf1, 0xcd, 0x4f, 0x75, 0xb1, 0x68, 0x59, 0xd6,
|
||||
0x55, 0x4f, 0xa8, 0x94, 0xba, 0x6a, 0x9a, 0x65, 0xcb, 0x96, 0x91, 0x99,
|
||||
0x99, 0x79, 0x59, 0x5b, 0x36, 0xa5, 0xf4, 0x2a, 0xc5, 0x6f, 0x5b, 0x2f,
|
||||
0xe2, 0x90, 0x02, 0x4b, 0x69, 0x2e, 0x8c, 0x86, 0xf8, 0xe5, 0xe9, 0x4e,
|
||||
0x7e, 0xd3, 0xdc, 0xcd, 0x93, 0xa7, 0xbb, 0xe8, 0x0f, 0x45, 0xb0, 0xb5,
|
||||
0xc6, 0x63, 0x1a, 0x7c, 0xbf, 0xa1, 0x6d, 0x7a, 0x0c, 0xa5, 0x35, 0x8f,
|
||||
0xad, 0x98, 0xcd, 0x9a, 0x92, 0x6c, 0x94, 0x86, 0x1f, 0x9f, 0xbc, 0xc0,
|
||||
0xd7, 0xf6, 0x9d, 0xba, 0xae, 0x80, 0x98, 0x2e, 0x97, 0x0b, 0xb7, 0xdb,
|
||||
0x4d, 0x28, 0x14, 0x62, 0xff, 0xfe, 0xfd, 0x54, 0x54, 0x54, 0x90, 0x91,
|
||||
0x91, 0x81, 0x52, 0x8a, 0x86, 0x86, 0x06, 0x94, 0x52, 0x28, 0xa5, 0xa8,
|
||||
0xad, 0xad, 0xbd, 0x2e, 0x13, 0xda, 0xb6, 0x9d, 0x18, 0x33, 0x89, 0x33,
|
||||
0xa4, 0xbc, 0xa2, 0x71, 0x5f, 0xbe, 0x7c, 0x39, 0xbb, 0x76, 0xed, 0x9a,
|
||||
0xb6, 0x0d, 0xe9, 0x0a, 0x84, 0x69, 0x18, 0x18, 0x45, 0x03, 0x1f, 0xab,
|
||||
0xc8, 0xe3, 0x89, 0x75, 0xf3, 0xb0, 0x2f, 0xe1, 0x29, 0xa7, 0x14, 0xdc,
|
||||
0xf3, 0xd2, 0x31, 0x1a, 0x07, 0x7d, 0x34, 0x0e, 0xf8, 0xe8, 0x0c, 0x8c,
|
||||
0x31, 0x5d, 0x05, 0xf1, 0xfc, 0x3d, 0x0b, 0xb9, 0xfb, 0xa5, 0x63, 0x1c,
|
||||
0xee, 0x1d, 0xe1, 0xc9, 0xe6, 0x6e, 0x66, 0x65, 0x7a, 0xf8, 0xfa, 0xfc,
|
||||
0x8a, 0xeb, 0x03, 0x48, 0x5a, 0x5a, 0x1a, 0x6b, 0xd6, 0xac, 0x61, 0xd7,
|
||||
0xae, 0x5d, 0x04, 0x83, 0x21, 0xb6, 0x6f, 0x7f, 0x9c, 0x9c, 0x9c, 0x1c,
|
||||
0xa2, 0xd1, 0x28, 0x3e, 0x5f, 0x2c, 0xab, 0x59, 0x5a, 0x5a, 0xc2, 0x86,
|
||||
0x0d, 0x77, 0x5e, 0xf3, 0x24, 0x4a, 0x29, 0xb4, 0xd6, 0x98, 0xa6, 0xc9,
|
||||
0x9e, 0x3d, 0x7f, 0x98, 0x14, 0xe5, 0xdb, 0xb6, 0xcd, 0xad, 0xb7, 0x2e,
|
||||
0x60, 0xc9, 0x92, 0x25, 0x57, 0x88, 0xfe, 0xeb, 0x69, 0x69, 0x69, 0xa5,
|
||||
0xa5, 0xe5, 0x2c, 0xa6, 0x69, 0xbe, 0xaf, 0xa4, 0xfd, 0xe2, 0x74, 0x17,
|
||||
0xc1, 0xa8, 0x4d, 0x8a, 0x69, 0xf0, 0x99, 0xda, 0x62, 0x3c, 0x53, 0x5c,
|
||||
0xd3, 0x7e, 0xb1, 0xae, 0x94, 0xaf, 0xef, 0x3b, 0x4d, 0xdf, 0x58, 0x84,
|
||||
0xd7, 0xbb, 0xbc, 0xcc, 0xca, 0x72, 0x27, 0x45, 0xe0, 0x57, 0x04, 0xe5,
|
||||
0xee, 0x85, 0xdc, 0xb3, 0xf3, 0x18, 0x6f, 0xf7, 0x8f, 0xf2, 0xd7, 0x07,
|
||||
0xcf, 0x20, 0x05, 0x7c, 0x6d, 0x5e, 0xc5, 0xf5, 0x51, 0x59, 0x75, 0x75,
|
||||
0xb3, 0xf9, 0xea, 0x57, 0x1f, 0x62, 0xe9, 0xd2, 0x25, 0xa4, 0xa4, 0xa4,
|
||||
0x30, 0x32, 0x32, 0x42, 0x30, 0x18, 0xa4, 0x20, 0xbf, 0x80, 0xcd, 0x9b,
|
||||
0x37, 0xb3, 0x6d, 0xdb, 0xb6, 0x84, 0x0b, 0xab, 0xb5, 0x4e, 0xfa, 0x4c,
|
||||
0xa7, 0xac, 0x5e, 0xbd, 0x8a, 0xf4, 0xf4, 0x74, 0xb4, 0xd6, 0xf8, 0xfd,
|
||||
0x7e, 0x86, 0x87, 0x87, 0x27, 0x7d, 0xc6, 0x42, 0xa1, 0xf8, 0xf8, 0x5c,
|
||||
0x76, 0xfc, 0x4d, 0x9b, 0x3e, 0x4e, 0x41, 0x41, 0x21, 0x4a, 0x69, 0xe6,
|
||||
0xce, 0x9d, 0x73, 0x45, 0xf5, 0xf5, 0x83, 0x86, 0x76, 0x4c, 0x29, 0x71,
|
||||
0x9b, 0x92, 0x75, 0xa5, 0x53, 0xbb, 0xa3, 0xab, 0x8b, 0xb3, 0xc9, 0x70,
|
||||
0x9a, 0x18, 0x42, 0xf2, 0xdd, 0xa3, 0x2d, 0xa4, 0x1a, 0x12, 0xa5, 0x35,
|
||||
0x4a, 0x5f, 0x1a, 0xb5, 0x6b, 0xb4, 0x26, 0xa9, 0x0e, 0x20, 0xc5, 0x94,
|
||||
0xbc, 0xbe, 0x65, 0x29, 0x15, 0x69, 0x29, 0xb8, 0xa4, 0xc1, 0x77, 0x8e,
|
||||
0xb4, 0xf0, 0x54, 0x73, 0xf7, 0x07, 0x06, 0x44, 0x04, 0x7c, 0x83, 0xda,
|
||||
0xb6, 0x2d, 0x94, 0xb6, 0x30, 0xe2, 0x1b, 0x0c, 0xf8, 0x7d, 0x18, 0x12,
|
||||
0x4c, 0xd3, 0x41, 0x24, 0x12, 0xc6, 0xb2, 0x22, 0x68, 0xad, 0xd0, 0x4a,
|
||||
0x13, 0xb5, 0xa2, 0xd8, 0xd1, 0x28, 0x5a, 0xdb, 0x48, 0x19, 0x7b, 0x07,
|
||||
0x8b, 0x56, 0x09, 0x29, 0x40, 0xab, 0x58, 0xdf, 0xd8, 0xc9, 0xc6, 0x0f,
|
||||
0x55, 0xe3, 0x30, 0x4d, 0x82, 0xa1, 0x20, 0xca, 0xb6, 0xe3, 0xdb, 0x14,
|
||||
0xb1, 0xbf, 0xf1, 0x76, 0x29, 0x24, 0x86, 0x61, 0xa0, 0xb4, 0xc6, 0x8a,
|
||||
0x07, 0x97, 0x42, 0x08, 0x4c, 0xc3, 0x84, 0xf1, 0xb4, 0x9e, 0x10, 0x18,
|
||||
0x86, 0x41, 0x34, 0x12, 0xa1, 0x7c, 0xc6, 0x2d, 0xe4, 0x16, 0x4f, 0xed,
|
||||
0x6a, 0xaa, 0x78, 0xaa, 0xc3, 0x52, 0x0a, 0x43, 0x88, 0x49, 0xaf, 0x49,
|
||||
0xde, 0x6b, 0x17, 0xb4, 0x86, 0x90, 0xad, 0x48, 0x77, 0x18, 0x58, 0xf1,
|
||||
0x58, 0xcc, 0x8c, 0x67, 0x60, 0xc7, 0x01, 0xba, 0xb4, 0x6e, 0x2a, 0x63,
|
||||
0xaf, 0xb4, 0x66, 0xcc, 0x56, 0x89, 0xd4, 0xc9, 0x35, 0xab, 0x2c, 0xad,
|
||||
0x35, 0x1a, 0x85, 0x56, 0x8a, 0xa8, 0x6d, 0x61, 0x2b, 0x1b, 0x69, 0x08,
|
||||
0x94, 0x6d, 0x13, 0x0a, 0x85, 0xd0, 0xda, 0x46, 0x29, 0x3b, 0x01, 0x88,
|
||||
0x40, 0x23, 0x24, 0x08, 0x25, 0x50, 0xda, 0x42, 0xdb, 0x3a, 0x0e, 0x88,
|
||||
0x1d, 0xe7, 0x6a, 0x95, 0x00, 0x05, 0x0d, 0x4a, 0x2b, 0x34, 0x60, 0x45,
|
||||
0x42, 0x71, 0x90, 0x6c, 0x40, 0xa1, 0x11, 0x08, 0x4d, 0xec, 0xb0, 0x75,
|
||||
0x6c, 0xe3, 0xb6, 0x15, 0x0b, 0xad, 0xa5, 0x14, 0x38, 0xa4, 0x40, 0x6b,
|
||||
0x8d, 0x1d, 0x89, 0xa0, 0xb1, 0x27, 0x0e, 0x30, 0xae, 0x54, 0x0c, 0xe3,
|
||||
0xf2, 0xef, 0xa0, 0x9a, 0x87, 0x03, 0xbc, 0xd5, 0x3b, 0xcc, 0x67, 0x67,
|
||||
0x95, 0xd0, 0x19, 0x18, 0x23, 0x64, 0xd9, 0xcc, 0xcd, 0x4e, 0xa3, 0x71,
|
||||
0xd0, 0xc7, 0x81, 0x8b, 0xc3, 0x6c, 0xae, 0xcc, 0xe7, 0xc5, 0xf3, 0xfd,
|
||||
0x49, 0xa0, 0x6c, 0xab, 0x2d, 0xe6, 0xed, 0x81, 0x00, 0x07, 0x2e, 0x0e,
|
||||
0x23, 0x85, 0x60, 0xcc, 0xb2, 0x79, 0x78, 0x5e, 0x05, 0xbe, 0xa8, 0xcd,
|
||||
0x33, 0xad, 0x17, 0xb1, 0xb5, 0xa6, 0x30, 0xd5, 0xc5, 0x03, 0x33, 0x63,
|
||||
0xd9, 0x67, 0x5f, 0xd4, 0xe2, 0xe9, 0xd6, 0x5e, 0xc6, 0xec, 0x18, 0xf3,
|
||||
0x95, 0xa7, 0xa7, 0xb0, 0xa5, 0xb2, 0x00, 0x0d, 0x3c, 0x7f, 0xae, 0x97,
|
||||
0x8d, 0x15, 0x05, 0x49, 0x69, 0xf5, 0x86, 0x81, 0x51, 0x8e, 0xf4, 0x8d,
|
||||
0xf0, 0xa9, 0xda, 0x62, 0x32, 0xe2, 0xae, 0xfe, 0xab, 0x9d, 0x83, 0x34,
|
||||
0x0f, 0x07, 0x10, 0x42, 0xa0, 0xd1, 0x3c, 0x5c, 0x5f, 0x81, 0xe9, 0x49,
|
||||
0xff, 0xe3, 0xbe, 0xe6, 0xbe, 0x96, 0xf2, 0x64, 0xdb, 0x20, 0x0f, 0xbe,
|
||||
0xf6, 0x2e, 0xa6, 0x10, 0x68, 0x31, 0x2e, 0x4d, 0xc9, 0xf9, 0x10, 0xeb,
|
||||
0x74, 0x2b, 0xa8, 0xe6, 0x09, 0xce, 0x32, 0x24, 0xed, 0x9f, 0x59, 0x4d,
|
||||
0x99, 0x27, 0x85, 0xc3, 0x7d, 0x23, 0x7c, 0xfb, 0x48, 0x0b, 0x0f, 0xd6,
|
||||
0x95, 0x72, 0xf7, 0x8e, 0xa3, 0x8c, 0x46, 0x2d, 0x5a, 0x3e, 0x7d, 0x07,
|
||||
0x7b, 0xbb, 0x87, 0x78, 0xe4, 0x60, 0x33, 0x1b, 0x2b, 0xf2, 0x69, 0x19,
|
||||
0x09, 0xf2, 0x6a, 0xd7, 0x20, 0x29, 0x52, 0xb2, 0xb2, 0x28, 0x0b, 0xa7,
|
||||
0x94, 0x2c, 0x7f, 0xf6, 0x20, 0xf7, 0x56, 0x15, 0x52, 0xea, 0x71, 0x11,
|
||||
0xb0, 0x6c, 0x94, 0xd6, 0xfc, 0xf3, 0xf1, 0x73, 0xfc, 0xaa, 0xb9, 0x8b,
|
||||
0xcf, 0xcf, 0x2a, 0xe1, 0xad, 0xde, 0x61, 0xbe, 0x79, 0xf0, 0x0c, 0x87,
|
||||
0xef, 0xbf, 0x8d, 0x57, 0x3a, 0x06, 0x78, 0xf4, 0x50, 0x33, 0x5f, 0x98,
|
||||
0x55, 0x42, 0x44, 0xa9, 0xc4, 0x0a, 0xf7, 0xf5, 0x78, 0xb9, 0x6f, 0xc7,
|
||||
0x31, 0xd6, 0x57, 0x14, 0xb0, 0x67, 0x4b, 0xcc, 0x26, 0x3e, 0xb4, 0xb7,
|
||||
0x89, 0xc6, 0x21, 0x1f, 0x8b, 0xf3, 0x33, 0xf8, 0xd6, 0xaf, 0xdf, 0xe4,
|
||||
0xdf, 0x57, 0xd5, 0xf1, 0xc9, 0x9a, 0x62, 0xee, 0x7a, 0xee, 0x30, 0x0f,
|
||||
0xcc, 0x2a, 0xa1, 0xd4, 0xe3, 0xfa, 0xff, 0x73, 0x41, 0x35, 0xd4, 0x77,
|
||||
0x1e, 0xad, 0xed, 0x84, 0x29, 0x95, 0x02, 0x22, 0xfd, 0x7d, 0x3c, 0x98,
|
||||
0x37, 0xc6, 0x54, 0x1a, 0x42, 0x03, 0xa6, 0xe1, 0x20, 0x33, 0xaf, 0x2a,
|
||||
0x26, 0x85, 0xf1, 0x92, 0xe3, 0x72, 0x90, 0xeb, 0x72, 0xc6, 0xf2, 0x5f,
|
||||
0x42, 0xc4, 0x32, 0xbb, 0x1a, 0xdc, 0xa6, 0x41, 0x87, 0x7f, 0x8c, 0xfb,
|
||||
0x77, 0x35, 0xf0, 0xe9, 0x9a, 0x12, 0x52, 0x0d, 0x49, 0x45, 0x7a, 0x0a,
|
||||
0xff, 0xb2, 0x72, 0x36, 0x5f, 0x79, 0xa3, 0x89, 0x2c, 0x97, 0x83, 0x7f,
|
||||
0x5c, 0x1e, 0xf3, 0x20, 0x53, 0x0d, 0x83, 0x47, 0x17, 0x56, 0xb3, 0x38,
|
||||
0x7f, 0xe2, 0x86, 0xd0, 0x90, 0x82, 0xca, 0xf4, 0x54, 0x7e, 0xb0, 0x62,
|
||||
0x16, 0x27, 0x87, 0x7c, 0x2c, 0x79, 0xe6, 0x20, 0x61, 0x5b, 0x21, 0x04,
|
||||
0xcc, 0xca, 0xf4, 0xf0, 0xd8, 0x6d, 0xb3, 0xdf, 0x93, 0x55, 0x3e, 0xc5,
|
||||
0xdd, 0xd5, 0x85, 0x1c, 0xea, 0x1b, 0xe1, 0xc4, 0xa0, 0x8f, 0x5b, 0x72,
|
||||
0xd3, 0x79, 0xb6, 0xbd, 0x97, 0x03, 0x5b, 0x97, 0x53, 0x93, 0xe1, 0xe6,
|
||||
0xbb, 0x8b, 0x67, 0x22, 0x85, 0xc0, 0x56, 0x1a, 0xa7, 0xcb, 0x9c, 0x34,
|
||||
0xdf, 0x0d, 0x05, 0x44, 0x6b, 0xcd, 0xbb, 0x47, 0x77, 0x20, 0x44, 0xb2,
|
||||
0x8e, 0x5f, 0xec, 0x30, 0x58, 0x96, 0x26, 0x2e, 0xe3, 0xb1, 0xd9, 0x94,
|
||||
0x54, 0x2d, 0x20, 0xbf, 0xb6, 0x66, 0x7a, 0x1e, 0x1e, 0xf0, 0xb9, 0x59,
|
||||
0x25, 0xfc, 0xbe, 0xbd, 0x37, 0x61, 0x23, 0x2f, 0x05, 0x57, 0x5d, 0xe2,
|
||||
0x38, 0x08, 0x01, 0x9f, 0xd9, 0x73, 0x82, 0x2c, 0xa7, 0xc9, 0xcf, 0xd7,
|
||||
0xcd, 0x63, 0x6e, 0x76, 0x5a, 0xa2, 0x6d, 0xdb, 0xee, 0x13, 0x1c, 0xe8,
|
||||
0x1d, 0xe6, 0xb7, 0x1b, 0x16, 0x50, 0xe2, 0x71, 0x21, 0x85, 0xa0, 0xc9,
|
||||
0xeb, 0x67, 0xc1, 0xd3, 0x07, 0xf8, 0xca, 0xdc, 0x72, 0x1e, 0xaa, 0x2f,
|
||||
0xe7, 0xad, 0xde, 0x61, 0xce, 0xf9, 0x43, 0x3c, 0xbe, 0xb6, 0x9e, 0x4f,
|
||||
0xed, 0x3e, 0xc1, 0x13, 0x67, 0xba, 0xf8, 0xd1, 0xca, 0x3a, 0x10, 0x24,
|
||||
0xe6, 0xce, 0x4f, 0x8d, 0x31, 0x4d, 0xc4, 0x56, 0x58, 0x4a, 0xf3, 0xd9,
|
||||
0x3d, 0x27, 0xc8, 0x74, 0x99, 0x3c, 0x7b, 0xd7, 0x42, 0x4a, 0x3c, 0xae,
|
||||
0x1b, 0x0d, 0x88, 0xcd, 0x82, 0xdb, 0x92, 0xef, 0x3a, 0x1c, 0x52, 0xf2,
|
||||
0xc0, 0x2b, 0xc7, 0x71, 0x3b, 0x8c, 0xcb, 0x82, 0x98, 0xda, 0x66, 0xe2,
|
||||
0xe8, 0x7a, 0xe7, 0x12, 0x23, 0xae, 0xb9, 0xaf, 0xba, 0x90, 0x4f, 0x54,
|
||||
0x4d, 0xfd, 0xf3, 0x80, 0x5b, 0xf3, 0x32, 0x58, 0x5a, 0x90, 0xc9, 0xc3,
|
||||
0x6f, 0x9e, 0x22, 0xd5, 0x94, 0x57, 0x58, 0x0f, 0xfc, 0x74, 0xf5, 0x5c,
|
||||
0xee, 0x28, 0xc9, 0x9e, 0x04, 0xde, 0x2d, 0x39, 0x69, 0x1c, 0xeb, 0x1f,
|
||||
0x65, 0x6d, 0x49, 0x76, 0x62, 0xce, 0x9a, 0x4c, 0x37, 0x87, 0xb7, 0xae,
|
||||
0x20, 0x1a, 0x77, 0xc1, 0x7f, 0x7e, 0xaa, 0x0b, 0x0d, 0xfc, 0xf9, 0xde,
|
||||
0x26, 0xc6, 0x6c, 0xc5, 0x73, 0xe7, 0xfa, 0xf8, 0xd1, 0xca, 0x3a, 0x2c,
|
||||
0xa5, 0x13, 0xf6, 0x64, 0x77, 0xe7, 0x20, 0x11, 0x5b, 0x71, 0x77, 0x79,
|
||||
0x1e, 0x86, 0x10, 0xfc, 0xe4, 0x3d, 0xf3, 0xdd, 0x50, 0x40, 0x84, 0x30,
|
||||
0x48, 0xcf, 0x2a, 0x4c, 0xca, 0x0a, 0x9c, 0x1c, 0xf0, 0xf1, 0x87, 0x61,
|
||||
0x41, 0x86, 0xf3, 0xf2, 0x07, 0x27, 0x7c, 0x01, 0x60, 0xe2, 0x11, 0x42,
|
||||
0x54, 0x29, 0x3e, 0x57, 0x5b, 0x9a, 0xc4, 0xe9, 0x46, 0xec, 0x16, 0x28,
|
||||
0xa6, 0x02, 0x6d, 0xc5, 0x57, 0xeb, 0x2b, 0xf9, 0xd5, 0x99, 0x6e, 0xda,
|
||||
0x46, 0x43, 0x97, 0x5c, 0xc3, 0xc6, 0xae, 0x62, 0xc7, 0x4b, 0x9a, 0xc3,
|
||||
0xe0, 0xa9, 0xb3, 0x3d, 0xbc, 0xde, 0x3d, 0x44, 0xd0, 0xb2, 0xf9, 0xde,
|
||||
0xb2, 0xda, 0x78, 0x1f, 0x78, 0x74, 0xd1, 0x0c, 0x0e, 0xf4, 0x8d, 0x70,
|
||||
0xff, 0x2b, 0xc7, 0x79, 0xe9, 0xe3, 0x8b, 0x11, 0x62, 0xc2, 0xeb, 0x72,
|
||||
0x48, 0x89, 0x37, 0x1c, 0x65, 0x77, 0xd7, 0x20, 0x2f, 0xde, 0xb3, 0x88,
|
||||
0x35, 0x71, 0xd0, 0x2a, 0x9e, 0xdc, 0xcb, 0xce, 0xf3, 0xfd, 0x7c, 0x69,
|
||||
0x4e, 0x19, 0x5b, 0x5e, 0x6e, 0x60, 0x7d, 0x49, 0x0e, 0xff, 0xd3, 0x76,
|
||||
0x91, 0xbf, 0x5b, 0x52, 0x83, 0x21, 0x63, 0xde, 0xdf, 0x53, 0x67, 0xbb,
|
||||
0x79, 0xbd, 0x7b, 0x08, 0x0d, 0xfc, 0xfd, 0xd2, 0x9a, 0x1b, 0xfb, 0xd8,
|
||||
0xba, 0xfb, 0x5c, 0x23, 0xde, 0x81, 0x8e, 0xa4, 0x2b, 0xd1, 0xa1, 0x31,
|
||||
0x8b, 0x36, 0x5f, 0x68, 0x12, 0x87, 0x26, 0x24, 0xc8, 0x99, 0xca, 0xac,
|
||||
0x05, 0xeb, 0x93, 0x62, 0x14, 0xad, 0xa1, 0x3e, 0x27, 0x2d, 0xe1, 0xde,
|
||||
0xf6, 0x06, 0xc3, 0xb4, 0xfb, 0xc6, 0x58, 0x51, 0x98, 0xc9, 0x91, 0xbe,
|
||||
0x11, 0x8a, 0xdd, 0x2e, 0xca, 0xd2, 0x52, 0xe8, 0xf0, 0x8f, 0xe1, 0x8b,
|
||||
0x5a, 0x09, 0x55, 0xd4, 0x3c, 0x1c, 0xc0, 0x90, 0x82, 0x99, 0x19, 0xb1,
|
||||
0x80, 0xf0, 0xdd, 0x21, 0x3f, 0xfd, 0xa1, 0x08, 0x3a, 0x0e, 0xf2, 0xfa,
|
||||
0xd2, 0x5c, 0x3a, 0xfc, 0x63, 0x78, 0xc3, 0x51, 0x16, 0xe5, 0x67, 0x60,
|
||||
0x6b, 0xcd, 0xde, 0x6e, 0x2f, 0x4b, 0xf2, 0x33, 0x18, 0xb3, 0x15, 0x9d,
|
||||
0xfe, 0x31, 0x16, 0xc5, 0xf5, 0x7f, 0xd0, 0xb2, 0x39, 0xd8, 0x3b, 0xc2,
|
||||
0xfa, 0x4b, 0x62, 0x9e, 0x53, 0xde, 0x00, 0xa0, 0x99, 0x93, 0x9d, 0xc6,
|
||||
0x89, 0x41, 0x1f, 0xde, 0x70, 0x94, 0xaa, 0x74, 0x37, 0x95, 0xe9, 0xb1,
|
||||
0x98, 0xee, 0x68, 0xff, 0x28, 0xfe, 0xa8, 0x15, 0x8b, 0xbd, 0x80, 0xf5,
|
||||
0xa5, 0x39, 0x37, 0x0e, 0x10, 0xad, 0x15, 0x67, 0x4f, 0xbc, 0xc6, 0x88,
|
||||
0x37, 0x39, 0x98, 0x0a, 0x59, 0x2a, 0xe9, 0xbe, 0x39, 0x39, 0x6e, 0xd6,
|
||||
0xe4, 0xe4, 0x55, 0x50, 0x33, 0x7f, 0xed, 0x15, 0x52, 0xe4, 0xd3, 0xa8,
|
||||
0x13, 0x53, 0xd5, 0x8b, 0x2b, 0x46, 0xe9, 0xd3, 0x1b, 0xe3, 0x72, 0xf7,
|
||||
0x8d, 0x5c, 0x79, 0xbd, 0x22, 0x6e, 0xd0, 0xc4, 0x0d, 0xfe, 0x39, 0x82,
|
||||
0x6d, 0x45, 0x92, 0x0e, 0x5f, 0x69, 0x58, 0xb7, 0xe3, 0x18, 0x41, 0xdb,
|
||||
0xc6, 0x10, 0x32, 0xa1, 0x52, 0x0c, 0x29, 0xd1, 0x42, 0x60, 0x0a, 0x81,
|
||||
0x34, 0x0d, 0x4c, 0xd3, 0x81, 0x94, 0x02, 0xa7, 0x90, 0x08, 0xa1, 0x71,
|
||||
0x08, 0x89, 0x29, 0x63, 0xed, 0xa6, 0x10, 0x98, 0x52, 0x20, 0xa5, 0xc0,
|
||||
0x10, 0x02, 0x87, 0x20, 0x51, 0x6f, 0x88, 0x98, 0xd7, 0x64, 0x08, 0x19,
|
||||
0x7b, 0x7e, 0x13, 0x57, 0x6d, 0x26, 0x02, 0x43, 0x82, 0x21, 0x0d, 0x0c,
|
||||
0x21, 0x30, 0x0c, 0x30, 0x90, 0x31, 0x3a, 0x34, 0x86, 0x90, 0x13, 0xb4,
|
||||
0xd2, 0x48, 0x3c, 0xe7, 0x31, 0x20, 0x56, 0x2f, 0x04, 0x32, 0x3e, 0xe6,
|
||||
0xf8, 0xbc, 0x32, 0x51, 0x1f, 0x03, 0x25, 0x36, 0xbf, 0x8e, 0xed, 0x47,
|
||||
0xc4, 0xd6, 0x27, 0x11, 0xf1, 0xf5, 0x80, 0x88, 0xc7, 0x5f, 0x37, 0xd4,
|
||||
0x86, 0x18, 0xa6, 0x33, 0xe9, 0x7b, 0xfb, 0x68, 0x88, 0x8e, 0x90, 0xcd,
|
||||
0x98, 0x52, 0x18, 0x09, 0x30, 0xc0, 0x90, 0x1a, 0x25, 0xc1, 0x29, 0x80,
|
||||
0xa8, 0x85, 0x29, 0x15, 0xd2, 0x90, 0x38, 0xa5, 0xc0, 0x14, 0xe0, 0x94,
|
||||
0x32, 0x01, 0x84, 0x63, 0x1c, 0x10, 0xc3, 0xc0, 0x21, 0x62, 0x34, 0x86,
|
||||
0x90, 0x38, 0x25, 0x48, 0x62, 0x6d, 0x46, 0xbc, 0xdf, 0xa5, 0x60, 0x99,
|
||||
0x02, 0x4c, 0x43, 0xc7, 0x0e, 0x4e, 0x09, 0x0c, 0x14, 0x26, 0xe3, 0x6d,
|
||||
0xb1, 0x88, 0xdf, 0x21, 0x05, 0x52, 0xc6, 0x40, 0x70, 0x48, 0x89, 0x8c,
|
||||
0x03, 0x62, 0x0a, 0x81, 0x21, 0x63, 0xb4, 0x52, 0x49, 0x0c, 0x19, 0x4b,
|
||||
0xed, 0x1b, 0x82, 0x58, 0x7f, 0x40, 0x09, 0x1d, 0x03, 0x4c, 0x80, 0x8a,
|
||||
0x83, 0x65, 0xa0, 0xd1, 0x0a, 0xb4, 0x88, 0x8d, 0xa3, 0x15, 0xfc, 0x1f,
|
||||
0xd7, 0xc0, 0x3b, 0xab, 0xdb, 0x65, 0xb1, 0x8a, 0x00, 0x00, 0x00, 0x00,
|
||||
0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
|
||||
};
|
||||
unsigned int openair_logo_png_len = 4664;
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 4.6 KiB |
@@ -0,0 +1,291 @@
|
||||
#include "defs.h"
|
||||
#include <X11/Xlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
#include <math.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/select.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
typedef struct {
|
||||
float *buf;
|
||||
short *iqbuf;
|
||||
int count;
|
||||
int type;
|
||||
volatile int iq_count; /* for ULSCH IQ data */
|
||||
int iq_insert_pos;
|
||||
GC g;
|
||||
} data;
|
||||
|
||||
typedef struct {
|
||||
Display *d;
|
||||
Window w;
|
||||
Pixmap px;
|
||||
GC bg;
|
||||
int width;
|
||||
int height;
|
||||
pthread_mutex_t lock;
|
||||
float zoom;
|
||||
int timer_pipe[2];
|
||||
data *p; /* list of plots */
|
||||
int nplots;
|
||||
} plot;
|
||||
|
||||
static void *timer_thread(void *_p)
|
||||
{
|
||||
plot *p = _p;
|
||||
char c;
|
||||
|
||||
while (1) {
|
||||
/* more or less 10Hz */
|
||||
usleep(100*1000);
|
||||
c = 1;
|
||||
if (write(p->timer_pipe[1], &c, 1) != 1) abort();
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void *plot_thread(void *_p)
|
||||
{
|
||||
float v;
|
||||
float *s;
|
||||
int i, j;
|
||||
plot *p = _p;
|
||||
int redraw = 0;
|
||||
int replot = 0;
|
||||
fd_set rset;
|
||||
int xfd = ConnectionNumber(p->d);
|
||||
int maxfd = xfd > p->timer_pipe[0] ? xfd : p->timer_pipe[0];
|
||||
int pp;
|
||||
|
||||
while (1) {
|
||||
while (XPending(p->d)) {
|
||||
XEvent e;
|
||||
XNextEvent(p->d, &e);
|
||||
switch (e.type) {
|
||||
case ButtonPress:
|
||||
/* button 4: zoom out */
|
||||
if (e.xbutton.button == 4) { p->zoom = p->zoom * 1.25; replot = 1; }
|
||||
/* button 5: zoom in */
|
||||
if (e.xbutton.button == 5) { p->zoom = p->zoom * 0.8; replot = 1; }
|
||||
printf("zoom: %f\n", p->zoom);
|
||||
break;
|
||||
case Expose: redraw = 1; break;
|
||||
}
|
||||
}
|
||||
|
||||
if (replot == 1) {
|
||||
replot = 0;
|
||||
redraw = 1;
|
||||
|
||||
if (pthread_mutex_lock(&p->lock)) abort();
|
||||
|
||||
XFillRectangle(p->d, p->px, p->bg, 0, 0, p->width, p->height);
|
||||
|
||||
for (pp = 0; pp < p->nplots; pp++) {
|
||||
if (p->p[pp].type == PLOT_MINMAX) {
|
||||
s = p->p[pp].buf;
|
||||
for (i = 0; i < 512; i++) {
|
||||
int min = *s;
|
||||
int max = *s;
|
||||
for (j = 0; j < p->p[pp].count/512; j++, s++) {
|
||||
if (*s < min) min = *s;
|
||||
if (*s > max) max = *s;
|
||||
}
|
||||
XDrawLine(p->d, p->px, p->p[pp].g, i, 100-min, i, 100-max);
|
||||
}
|
||||
} else if (p->p[pp].type == PLOT_VS_TIME) {
|
||||
for (i = 0; i < p->p[pp].count; i++)
|
||||
p->p[pp].buf[i] =
|
||||
10*log10(1.0+(float)(p->p[pp].iqbuf[2*i]*p->p[pp].iqbuf[2*i]+
|
||||
p->p[pp].iqbuf[2*i+1]*p->p[pp].iqbuf[2*i+1]));
|
||||
s = p->p[pp].buf;
|
||||
for (i = 0; i < 512; i++) {
|
||||
v = 0;
|
||||
for (j = 0; j < p->p[pp].count/512; j++, s++) v += *s;
|
||||
v /= p->p[pp].count/512;
|
||||
XDrawLine(p->d, p->px, p->p[pp].g, i, 100, i, 100-v);
|
||||
}
|
||||
} else if (p->p[pp].type == PLOT_IQ_POINTS) {
|
||||
XPoint pts[p->p[pp].iq_count];
|
||||
int count = p->p[pp].iq_count;
|
||||
for (i = 0; i < count; i++) {
|
||||
pts[i].x = p->p[pp].iqbuf[2*i]*p->zoom/20+50;
|
||||
pts[i].y = -p->p[pp].iqbuf[2*i+1]*p->zoom/20+50;
|
||||
}
|
||||
XDrawPoints(p->d, p->px, p->p[pp].g, pts, count, CoordModeOrigin);
|
||||
}
|
||||
}
|
||||
|
||||
if (pthread_mutex_unlock(&p->lock)) abort();
|
||||
}
|
||||
|
||||
if (redraw) {
|
||||
redraw = 0;
|
||||
XCopyArea(p->d, p->px, p->w, DefaultGC(p->d, DefaultScreen(p->d)),
|
||||
0, 0, p->width, p->height, 0, 0);
|
||||
}
|
||||
|
||||
XFlush(p->d);
|
||||
|
||||
FD_ZERO(&rset);
|
||||
FD_SET(p->timer_pipe[0], &rset);
|
||||
FD_SET(xfd, &rset);
|
||||
if (select(maxfd+1, &rset, NULL, NULL, NULL) == -1) abort();
|
||||
if (FD_ISSET(p->timer_pipe[0], &rset)) {
|
||||
char b[512];
|
||||
if (read(p->timer_pipe[0], b, 512) <= 0) abort();
|
||||
replot = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *make_plot(int width, int height, char *title, int nplots, ...)
|
||||
{
|
||||
plot *p;
|
||||
Display *d;
|
||||
Window w;
|
||||
Pixmap pm;
|
||||
int i;
|
||||
va_list ap;
|
||||
XGCValues gcv;
|
||||
|
||||
p = malloc(sizeof(*p)); if (p == NULL) abort();
|
||||
|
||||
d = XOpenDisplay(0); if (d == NULL) abort();
|
||||
w = XCreateSimpleWindow(d, DefaultRootWindow(d), 0, 0, width, height,
|
||||
0, WhitePixel(d, DefaultScreen(d)), WhitePixel(d, DefaultScreen(d)));
|
||||
XSelectInput(d, w, ExposureMask | ButtonPressMask);
|
||||
XMapWindow(d, w);
|
||||
|
||||
{
|
||||
XSetWindowAttributes att;
|
||||
att.backing_store = Always;
|
||||
XChangeWindowAttributes(d, w, CWBackingStore, &att);
|
||||
}
|
||||
|
||||
XStoreName(d, w, title);
|
||||
|
||||
p->bg = XCreateGC(d, w, 0, NULL);
|
||||
XCopyGC(d, DefaultGC(d, DefaultScreen(d)), -1L, p->bg);
|
||||
gcv.foreground = WhitePixel(d, DefaultScreen(d));
|
||||
XChangeGC(d, p->bg, GCForeground, &gcv);
|
||||
|
||||
pm = XCreatePixmap(d, w, width, height, DefaultDepth(d, DefaultScreen(d)));
|
||||
|
||||
p->width = width;
|
||||
p->height = height;
|
||||
p->p = malloc(nplots * sizeof(data)); if (p->p == NULL) abort();
|
||||
|
||||
va_start(ap, nplots);
|
||||
for (i = 0; i < nplots; i++) {
|
||||
int count;
|
||||
int type;
|
||||
char *color;
|
||||
XColor rcol, scol;
|
||||
|
||||
count = va_arg(ap, int);
|
||||
type = va_arg(ap, int);
|
||||
color = va_arg(ap, char *);
|
||||
|
||||
p->p[i].g = XCreateGC(d, w, 0, NULL);
|
||||
XCopyGC(d, DefaultGC(d, DefaultScreen(d)), -1L, p->p[i].g);
|
||||
if (XAllocNamedColor(d, DefaultColormap(d, DefaultScreen(d)),
|
||||
color, &scol, &rcol)) {
|
||||
gcv.foreground = scol.pixel;
|
||||
XChangeGC(d, p->p[i].g, GCForeground, &gcv);
|
||||
} else {
|
||||
printf("could not allocate color '%s'\n", color);
|
||||
abort();
|
||||
}
|
||||
|
||||
if (type == PLOT_VS_TIME) {
|
||||
p->p[i].buf = malloc(sizeof(float) * count);
|
||||
if (p->p[i].buf == NULL) abort();
|
||||
p->p[i].iqbuf = malloc(sizeof(short) * count * 2);
|
||||
if(p->p[i].iqbuf==NULL)abort();
|
||||
} else if (type == PLOT_MINMAX) {
|
||||
p->p[i].buf = malloc(sizeof(float) * count);
|
||||
if (p->p[i].buf == NULL) abort();
|
||||
p->p[i].iqbuf = NULL;
|
||||
} else {
|
||||
p->p[i].buf = NULL;
|
||||
p->p[i].iqbuf = malloc(sizeof(short) * count * 2);
|
||||
if(p->p[i].iqbuf==NULL)abort();
|
||||
}
|
||||
p->p[i].count = count;
|
||||
p->p[i].type = type;
|
||||
p->p[i].iq_count = 0;
|
||||
p->p[i].iq_insert_pos = 0;
|
||||
}
|
||||
va_end(ap);
|
||||
|
||||
p->d = d;
|
||||
p->w = w;
|
||||
p->px = pm;
|
||||
|
||||
p->zoom = 1;
|
||||
p->nplots = nplots;
|
||||
|
||||
pthread_mutex_init(&p->lock, NULL);
|
||||
|
||||
if (pipe(p->timer_pipe)) abort();
|
||||
|
||||
new_thread(plot_thread, p);
|
||||
new_thread(timer_thread, p);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
void plot_set(void *_plot, float *data, int len, int pos, int pp)
|
||||
{
|
||||
plot *p = _plot;
|
||||
if (pthread_mutex_lock(&p->lock)) abort();
|
||||
memcpy(p->p[pp].buf + pos, data, len * sizeof(float));
|
||||
if (pthread_mutex_unlock(&p->lock)) abort();
|
||||
}
|
||||
|
||||
void iq_plot_set(void *_plot, short *data, int count, int pos, int pp)
|
||||
{
|
||||
plot *p = _plot;
|
||||
if (pthread_mutex_lock(&p->lock)) abort();
|
||||
memcpy(p->p[pp].iqbuf + pos * 2, data, count * 2 * sizeof(short));
|
||||
if (pthread_mutex_unlock(&p->lock)) abort();
|
||||
}
|
||||
|
||||
void iq_plot_set_sized(void *_plot, short *data, int count, int pp)
|
||||
{
|
||||
plot *p = _plot;
|
||||
if (pthread_mutex_lock(&p->lock)) abort();
|
||||
memcpy(p->p[pp].iqbuf, data, count * 2 * sizeof(short));
|
||||
p->p[pp].iq_count = count;
|
||||
if (pthread_mutex_unlock(&p->lock)) abort();
|
||||
}
|
||||
|
||||
void iq_plot_add_iq_point_loop(void *_plot, short i, short q, int pp)
|
||||
{
|
||||
plot *p = _plot;
|
||||
if (pthread_mutex_lock(&p->lock)) abort();
|
||||
p->p[pp].iqbuf[p->p[pp].iq_insert_pos*2] = i;
|
||||
p->p[pp].iqbuf[p->p[pp].iq_insert_pos*2+1] = q;
|
||||
if (p->p[pp].iq_count != p->p[pp].count) p->p[pp].iq_count++;
|
||||
p->p[pp].iq_insert_pos++;
|
||||
if (p->p[pp].iq_insert_pos == p->p[pp].count) p->p[pp].iq_insert_pos = 0;
|
||||
if (pthread_mutex_unlock(&p->lock)) abort();
|
||||
}
|
||||
|
||||
void iq_plot_add_energy_point_loop(void *_plot, int e, int pp)
|
||||
{
|
||||
plot *p = _plot;
|
||||
if (pthread_mutex_lock(&p->lock)) abort();
|
||||
p->p[pp].buf[p->p[pp].iq_insert_pos] = e;
|
||||
if (p->p[pp].iq_count != p->p[pp].count) p->p[pp].iq_count++;
|
||||
p->p[pp].iq_insert_pos++;
|
||||
if (p->p[pp].iq_insert_pos == p->p[pp].count) p->p[pp].iq_insert_pos = 0;
|
||||
if (pthread_mutex_unlock(&p->lock)) abort();
|
||||
}
|
||||
@@ -0,0 +1,194 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include "database.h"
|
||||
#include "event.h"
|
||||
#include "handler.h"
|
||||
#include "logger/logger.h"
|
||||
#include "view/view.h"
|
||||
#include "gui/gui.h"
|
||||
#include "utils.h"
|
||||
#include "../T_defs.h"
|
||||
#include "event_selector.h"
|
||||
#include "config.h"
|
||||
|
||||
#define DEFAULT_REMOTE_IP "127.0.0.1"
|
||||
#define DEFAULT_REMOTE_PORT 2021
|
||||
|
||||
typedef struct {
|
||||
int socket;
|
||||
int *is_on;
|
||||
int nevents;
|
||||
pthread_mutex_t lock;
|
||||
} textlog_data;
|
||||
|
||||
void is_on_changed(void *_d)
|
||||
{
|
||||
textlog_data *d = _d;
|
||||
char t;
|
||||
|
||||
if (pthread_mutex_lock(&d->lock)) abort();
|
||||
|
||||
if (d->socket == -1) goto no_connection;
|
||||
|
||||
t = 1;
|
||||
if (socket_send(d->socket, &t, 1) == -1 ||
|
||||
socket_send(d->socket, &d->nevents, sizeof(int)) == -1 ||
|
||||
socket_send(d->socket, d->is_on, d->nevents * sizeof(int)) == -1)
|
||||
abort();
|
||||
|
||||
no_connection:
|
||||
if (pthread_mutex_unlock(&d->lock)) abort();
|
||||
}
|
||||
|
||||
void usage(void)
|
||||
{
|
||||
printf(
|
||||
"options:\n"
|
||||
" -d <database file> this option is mandatory\n"
|
||||
" -on <GROUP or ID> turn log ON for given GROUP or ID\n"
|
||||
" -off <GROUP or ID> turn log OFF for given GROUP or ID\n"
|
||||
" -ON turn all logs ON\n"
|
||||
" -OFF turn all logs OFF\n"
|
||||
" note: you may pass several -on/-off/-ON/-OFF,\n"
|
||||
" they will be processed in order\n"
|
||||
" by default, all is off\n"
|
||||
" -ip <host> connect to given IP address (default %s)\n"
|
||||
" -p <port> connect to given port (default %d)\n"
|
||||
" -x GUI output\n"
|
||||
" -debug-gui activate GUI debug logs\n"
|
||||
" -no-gui disable GUI entirely\n",
|
||||
DEFAULT_REMOTE_IP,
|
||||
DEFAULT_REMOTE_PORT
|
||||
);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static void *gui_thread(void *_g)
|
||||
{
|
||||
gui *g = _g;
|
||||
gui_loop(g);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int main(int n, char **v)
|
||||
{
|
||||
extern int volatile gui_logd;
|
||||
char *database_filename = NULL;
|
||||
void *database;
|
||||
char *ip = DEFAULT_REMOTE_IP;
|
||||
int port = DEFAULT_REMOTE_PORT;
|
||||
char **on_off_name;
|
||||
int *on_off_action;
|
||||
int on_off_n = 0;
|
||||
int *is_on;
|
||||
int number_of_events;
|
||||
int i;
|
||||
event_handler *h;
|
||||
logger *textlog;
|
||||
gui *g;
|
||||
int gui_mode = 0;
|
||||
view *out;
|
||||
int gui_active = 1;
|
||||
textlog_data textlog_data;
|
||||
|
||||
/* write on a socket fails if the other end is closed and we get SIGPIPE */
|
||||
if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) abort();
|
||||
|
||||
on_off_name = malloc(n * sizeof(char *)); if (on_off_name == NULL) abort();
|
||||
on_off_action = malloc(n * sizeof(int)); if (on_off_action == NULL) abort();
|
||||
|
||||
for (i = 1; i < n; i++) {
|
||||
if (!strcmp(v[i], "-h") || !strcmp(v[i], "--help")) usage();
|
||||
if (!strcmp(v[i], "-d"))
|
||||
{ if (i > n-2) usage(); database_filename = v[++i]; continue; }
|
||||
if (!strcmp(v[i], "-ip")) { if (i > n-2) usage(); ip = v[++i]; continue; }
|
||||
if (!strcmp(v[i], "-p"))
|
||||
{ if (i > n-2) usage(); port = atoi(v[++i]); continue; }
|
||||
if (!strcmp(v[i], "-on")) { if (i > n-2) usage();
|
||||
on_off_name[on_off_n]=v[++i]; on_off_action[on_off_n++]=1; continue; }
|
||||
if (!strcmp(v[i], "-off")) { if (i > n-2) usage();
|
||||
on_off_name[on_off_n]=v[++i]; on_off_action[on_off_n++]=0; continue; }
|
||||
if (!strcmp(v[i], "-ON"))
|
||||
{ on_off_name[on_off_n]=NULL; on_off_action[on_off_n++]=1; continue; }
|
||||
if (!strcmp(v[i], "-OFF"))
|
||||
{ on_off_name[on_off_n]=NULL; on_off_action[on_off_n++]=0; continue; }
|
||||
if (!strcmp(v[i], "-x")) { gui_mode = 1; continue; }
|
||||
if (!strcmp(v[i], "-debug-gui")) { gui_logd = 1; continue; }
|
||||
if (!strcmp(v[i], "-no-gui")) { gui_active = 0; continue; }
|
||||
usage();
|
||||
}
|
||||
|
||||
if (gui_active == 0) gui_mode = 0;
|
||||
|
||||
if (database_filename == NULL) {
|
||||
printf("ERROR: provide a database file (-d)\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
database = parse_database(database_filename);
|
||||
|
||||
load_config_file(database_filename);
|
||||
|
||||
number_of_events = number_of_ids(database);
|
||||
is_on = calloc(number_of_events, sizeof(int));
|
||||
if (is_on == NULL) abort();
|
||||
|
||||
h = new_handler(database);
|
||||
|
||||
if (gui_active) {
|
||||
g = gui_init();
|
||||
new_thread(gui_thread, g);
|
||||
}
|
||||
|
||||
if (gui_mode) {
|
||||
widget *w, *win;
|
||||
// w = new_textlist(g, 600, 20, 0);
|
||||
w = new_textlist(g, 800, 50, BACKGROUND_COLOR);
|
||||
win = new_toplevel_window(g, 800, 50*12, "textlog");
|
||||
widget_add_child(g, win, w, -1);
|
||||
out = new_view_textlist(1000, 10, g, w);
|
||||
//tout = new_view_textlist(7, 4, g, w);
|
||||
} else {
|
||||
out = new_view_stdout();
|
||||
}
|
||||
|
||||
for (i = 0; i < number_of_events; i++) {
|
||||
char *name, *desc;
|
||||
database_get_generic_description(database, i, &name, &desc);
|
||||
textlog = new_textlog(h, database, name, desc);
|
||||
// "ENB_PHY_UL_CHANNEL_ESTIMATE",
|
||||
// "ev: {} eNB_id [eNB_ID] frame [frame] subframe [subframe]");
|
||||
logger_add_view(textlog, out);
|
||||
free(name);
|
||||
free(desc);
|
||||
}
|
||||
|
||||
for (i = 0; i < on_off_n; i++)
|
||||
on_off(database, on_off_name[i], is_on, on_off_action[i]);
|
||||
|
||||
textlog_data.socket = -1;
|
||||
textlog_data.is_on = is_on;
|
||||
textlog_data.nevents = number_of_events;
|
||||
if (pthread_mutex_init(&textlog_data.lock, NULL)) abort();
|
||||
if (gui_active)
|
||||
setup_event_selector(g, database, is_on, is_on_changed, &textlog_data);
|
||||
|
||||
textlog_data.socket = connect_to(ip, port);
|
||||
|
||||
/* send the first message - activate selected traces */
|
||||
is_on_changed(&textlog_data);
|
||||
|
||||
/* read messages */
|
||||
while (1) {
|
||||
char v[T_BUFFER_MAX];
|
||||
event e;
|
||||
e = get_event(textlog_data.socket, v, database);
|
||||
if (e.type == -1) abort();
|
||||
handle_event(h, e);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,198 @@
|
||||
#include "utils.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <ctype.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
void new_thread(void *(*f)(void *), void *data)
|
||||
{
|
||||
pthread_t t;
|
||||
pthread_attr_t att;
|
||||
|
||||
if (pthread_attr_init(&att))
|
||||
{ fprintf(stderr, "pthread_attr_init err\n"); exit(1); }
|
||||
if (pthread_attr_setdetachstate(&att, PTHREAD_CREATE_DETACHED))
|
||||
{ fprintf(stderr, "pthread_attr_setdetachstate err\n"); exit(1); }
|
||||
if (pthread_attr_setstacksize(&att, 10000000))
|
||||
{ fprintf(stderr, "pthread_attr_setstacksize err\n"); exit(1); }
|
||||
if (pthread_create(&t, &att, f, data))
|
||||
{ fprintf(stderr, "pthread_create err\n"); exit(1); }
|
||||
if (pthread_attr_destroy(&att))
|
||||
{ fprintf(stderr, "pthread_attr_destroy err\n"); exit(1); }
|
||||
}
|
||||
|
||||
void sleepms(int ms)
|
||||
{
|
||||
struct timespec t;
|
||||
|
||||
t.tv_sec = ms / 1000;
|
||||
t.tv_nsec = (ms % 1000) * 1000000L;
|
||||
|
||||
/* TODO: deal with EINTR */
|
||||
if (nanosleep(&t, NULL)) abort();
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
/* list */
|
||||
/****************************************************************************/
|
||||
|
||||
list *list_remove_head(list *l)
|
||||
{
|
||||
list *ret;
|
||||
if (l == NULL) return NULL;
|
||||
ret = l->next;
|
||||
if (ret != NULL) ret->last = l->last;
|
||||
free(l);
|
||||
return ret;
|
||||
}
|
||||
|
||||
list *list_append(list *l, void *data)
|
||||
{
|
||||
list *new = calloc(1, sizeof(list));
|
||||
if (new == NULL) abort();
|
||||
new->data = data;
|
||||
if (l == NULL) {
|
||||
new->last = new;
|
||||
return new;
|
||||
}
|
||||
l->last->next = new;
|
||||
l->last = new;
|
||||
return l;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
/* socket */
|
||||
/****************************************************************************/
|
||||
|
||||
int socket_send(int socket, void *buffer, int size)
|
||||
{
|
||||
char *x = buffer;
|
||||
int ret;
|
||||
while (size) {
|
||||
ret = write(socket, x, size);
|
||||
if (ret <= 0) return -1;
|
||||
size -= ret;
|
||||
x += ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int get_connection(char *addr, int port)
|
||||
{
|
||||
struct sockaddr_in a;
|
||||
socklen_t alen;
|
||||
int s, t;
|
||||
|
||||
printf("waiting for connection on %s:%d\n", addr, port);
|
||||
|
||||
s = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (s == -1) { perror("socket"); exit(1); }
|
||||
t = 1;
|
||||
if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &t, sizeof(int)))
|
||||
{ perror("setsockopt"); exit(1); }
|
||||
|
||||
a.sin_family = AF_INET;
|
||||
a.sin_port = htons(port);
|
||||
a.sin_addr.s_addr = inet_addr(addr);
|
||||
|
||||
if (bind(s, (struct sockaddr *)&a, sizeof(a))) { perror("bind"); exit(1); }
|
||||
if (listen(s, 5)) { perror("bind"); exit(1); }
|
||||
alen = sizeof(a);
|
||||
t = accept(s, (struct sockaddr *)&a, &alen);
|
||||
if (t == -1) { perror("accept"); exit(1); }
|
||||
close(s);
|
||||
|
||||
printf("connected\n");
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
int fullread(int fd, void *_buf, int count)
|
||||
{
|
||||
char *buf = _buf;
|
||||
int ret = 0;
|
||||
int l;
|
||||
while (count) {
|
||||
l = read(fd, buf, count);
|
||||
if (l <= 0) return -1;
|
||||
count -= l;
|
||||
buf += l;
|
||||
ret += l;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int connect_to(char *addr, int port)
|
||||
{
|
||||
int s;
|
||||
struct sockaddr_in a;
|
||||
|
||||
printf("connecting to %s:%d\n", addr, port);
|
||||
|
||||
again:
|
||||
s = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (s == -1) { perror("socket"); exit(1); }
|
||||
|
||||
a.sin_family = AF_INET;
|
||||
a.sin_port = htons(port);
|
||||
a.sin_addr.s_addr = inet_addr(addr);
|
||||
|
||||
if (connect(s, (struct sockaddr *)&a, sizeof(a)) == -1) {
|
||||
perror("connect");
|
||||
close(s);
|
||||
printf("trying again in 1s\n");
|
||||
sleep(1);
|
||||
goto again;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
/* buffer */
|
||||
/****************************************************************************/
|
||||
|
||||
void PUTC(OBUF *o, char c)
|
||||
{
|
||||
if (o->osize == o->omaxsize) {
|
||||
o->omaxsize += 512;
|
||||
o->obuf = realloc(o->obuf, o->omaxsize);
|
||||
if (o->obuf == NULL) abort();
|
||||
}
|
||||
o->obuf[o->osize] = c;
|
||||
o->osize++;
|
||||
}
|
||||
|
||||
void PUTS(OBUF *o, char *s)
|
||||
{
|
||||
while (*s) PUTC(o, *s++);
|
||||
}
|
||||
|
||||
static int clean(char c)
|
||||
{
|
||||
if (!isprint(c)) c = ' ';
|
||||
return c;
|
||||
}
|
||||
|
||||
void PUTS_CLEAN(OBUF *o, char *s)
|
||||
{
|
||||
while (*s) PUTC(o, clean(*s++));
|
||||
}
|
||||
|
||||
void PUTI(OBUF *o, int i)
|
||||
{
|
||||
char s[64];
|
||||
sprintf(s, "%d", i);
|
||||
PUTS(o, s);
|
||||
}
|
||||
|
||||
void PUTUL(OBUF *o, unsigned long l)
|
||||
{
|
||||
char s[128];
|
||||
sprintf(s, "%ld", l);
|
||||
PUTS(o, s);
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
#ifndef _UTILS_H_
|
||||
#define _UTILS_H_
|
||||
|
||||
void new_thread(void *(*f)(void *), void *data);
|
||||
void sleepms(int ms);
|
||||
|
||||
/****************************************************************************/
|
||||
/* list */
|
||||
/****************************************************************************/
|
||||
|
||||
typedef struct list {
|
||||
struct list *last, *next;
|
||||
void *data;
|
||||
} list;
|
||||
|
||||
list *list_remove_head(list *l);
|
||||
list *list_append(list *l, void *data);
|
||||
|
||||
/****************************************************************************/
|
||||
/* socket */
|
||||
/****************************************************************************/
|
||||
|
||||
/* socket_send: return 0 if okay, -1 on error */
|
||||
int socket_send(int socket, void *buffer, int size);
|
||||
int get_connection(char *addr, int port);
|
||||
/* fullread: return length read if okay (that is: 'count'), -1 on error */
|
||||
int fullread(int fd, void *_buf, int count);
|
||||
int connect_to(char *addr, int port);
|
||||
|
||||
/****************************************************************************/
|
||||
/* buffer */
|
||||
/****************************************************************************/
|
||||
|
||||
typedef struct {
|
||||
int osize;
|
||||
int omaxsize;
|
||||
char *obuf;
|
||||
} OBUF;
|
||||
|
||||
void PUTC(OBUF *o, char c);
|
||||
void PUTS(OBUF *o, char *s);
|
||||
void PUTS_CLEAN(OBUF *o, char *s);
|
||||
void PUTI(OBUF *o, int i);
|
||||
void PUTUL(OBUF *o, unsigned long i);
|
||||
|
||||
#endif /* _UTILS_H_ */
|
||||
@@ -0,0 +1,204 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include "database.h"
|
||||
#include "event.h"
|
||||
#include "handler.h"
|
||||
#include "logger/logger.h"
|
||||
#include "view/view.h"
|
||||
#include "gui/gui.h"
|
||||
#include "utils.h"
|
||||
#include "../T_defs.h"
|
||||
#include "event_selector.h"
|
||||
#include "config.h"
|
||||
|
||||
typedef struct {
|
||||
int socket;
|
||||
int *is_on;
|
||||
int nevents;
|
||||
pthread_mutex_t lock;
|
||||
} vcd_data;
|
||||
|
||||
void is_on_changed(void *_d)
|
||||
{
|
||||
vcd_data *d = _d;
|
||||
char t;
|
||||
|
||||
if (pthread_mutex_lock(&d->lock)) abort();
|
||||
|
||||
if (d->socket == -1) goto no_connection;
|
||||
|
||||
t = 1;
|
||||
if (socket_send(d->socket, &t, 1) == -1 ||
|
||||
socket_send(d->socket, &d->nevents, sizeof(int)) == -1 ||
|
||||
socket_send(d->socket, d->is_on, d->nevents * sizeof(int)) == -1)
|
||||
abort();
|
||||
|
||||
no_connection:
|
||||
if (pthread_mutex_unlock(&d->lock)) abort();
|
||||
}
|
||||
|
||||
#define DEFAULT_REMOTE_IP "127.0.0.1"
|
||||
#define DEFAULT_REMOTE_PORT 2021
|
||||
|
||||
void usage(void)
|
||||
{
|
||||
printf(
|
||||
"options:\n"
|
||||
" -d <database file> this option is mandatory\n"
|
||||
" -on <GROUP or ID> turn log ON for given GROUP or ID\n"
|
||||
" -off <GROUP or ID> turn log OFF for given GROUP or ID\n"
|
||||
" -ON turn all logs ON\n"
|
||||
" -OFF turn all logs OFF\n"
|
||||
" note: you may pass several -on/-off/-ON/-OFF,\n"
|
||||
" they will be processed in order\n"
|
||||
" by default, all is off\n"
|
||||
" -ip <host> connect to given IP address (default %s)\n"
|
||||
" -p <port> connect to given port (default %d)\n"
|
||||
" -debug-gui activate GUI debug logs\n",
|
||||
DEFAULT_REMOTE_IP,
|
||||
DEFAULT_REMOTE_PORT
|
||||
);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static void *gui_thread(void *_g)
|
||||
{
|
||||
gui *g = _g;
|
||||
gui_loop(g);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void vcd_main_gui(gui *g, event_handler *h, void *database)
|
||||
{
|
||||
int i, j;
|
||||
int n;
|
||||
int nb_functions = 0;
|
||||
char **ids;
|
||||
widget *win;
|
||||
widget *container;
|
||||
widget *w;
|
||||
view *timeview;
|
||||
view *subview;
|
||||
logger *timelog;
|
||||
|
||||
/* get number of vcd functions - look for all events VCD_FUNCTION_xxx */
|
||||
n = database_get_ids(database, &ids);
|
||||
for (i = 0; i < n; i++) {
|
||||
if (strncmp(ids[i], "VCD_FUNCTION_", 13) != 0) continue;
|
||||
nb_functions++;
|
||||
}
|
||||
|
||||
win = new_toplevel_window(g, 1000, 5 * nb_functions, "VCD tracer");
|
||||
container = new_container(g, VERTICAL);
|
||||
widget_add_child(g, win, container, -1);
|
||||
|
||||
w = new_timeline(g, 1000, nb_functions, 5);
|
||||
widget_add_child(g, container, w, -1);
|
||||
for (i = 0; i < nb_functions; i++)
|
||||
timeline_set_subline_background_color(g, w, i,
|
||||
new_color(g, i & 1 ? "#ddd" : "#eee"));
|
||||
timeview = new_view_time(3600, 10, g, w);
|
||||
i = 0;
|
||||
for (j = 0; j < n; j++) {
|
||||
if (strncmp(ids[j], "VCD_FUNCTION_", 13) != 0) continue;
|
||||
timelog = new_timelog(h, database, ids[j]);
|
||||
subview = new_subview_time(timeview, i, FOREGROUND_COLOR, 3600*1000);
|
||||
logger_add_view(timelog, subview);
|
||||
i++;
|
||||
}
|
||||
|
||||
free(ids);
|
||||
}
|
||||
|
||||
int main(int n, char **v)
|
||||
{
|
||||
extern int volatile gui_logd;
|
||||
char *database_filename = NULL;
|
||||
void *database;
|
||||
char *ip = DEFAULT_REMOTE_IP;
|
||||
int port = DEFAULT_REMOTE_PORT;
|
||||
char **on_off_name;
|
||||
int *on_off_action;
|
||||
int on_off_n = 0;
|
||||
int *is_on;
|
||||
int number_of_events;
|
||||
int i;
|
||||
event_handler *h;
|
||||
gui *g;
|
||||
vcd_data vcd_data;
|
||||
|
||||
/* write on a socket fails if the other end is closed and we get SIGPIPE */
|
||||
if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) abort();
|
||||
|
||||
on_off_name = malloc(n * sizeof(char *)); if (on_off_name == NULL) abort();
|
||||
on_off_action = malloc(n * sizeof(int)); if (on_off_action == NULL) abort();
|
||||
|
||||
for (i = 1; i < n; i++) {
|
||||
if (!strcmp(v[i], "-h") || !strcmp(v[i], "--help")) usage();
|
||||
if (!strcmp(v[i], "-d"))
|
||||
{ if (i > n-2) usage(); database_filename = v[++i]; continue; }
|
||||
if (!strcmp(v[i], "-ip")) { if (i > n-2) usage(); ip = v[++i]; continue; }
|
||||
if (!strcmp(v[i], "-p"))
|
||||
{ if (i > n-2) usage(); port = atoi(v[++i]); continue; }
|
||||
if (!strcmp(v[i], "-on")) { if (i > n-2) usage();
|
||||
on_off_name[on_off_n]=v[++i]; on_off_action[on_off_n++]=1; continue; }
|
||||
if (!strcmp(v[i], "-off")) { if (i > n-2) usage();
|
||||
on_off_name[on_off_n]=v[++i]; on_off_action[on_off_n++]=0; continue; }
|
||||
if (!strcmp(v[i], "-ON"))
|
||||
{ on_off_name[on_off_n]=NULL; on_off_action[on_off_n++]=1; continue; }
|
||||
if (!strcmp(v[i], "-OFF"))
|
||||
{ on_off_name[on_off_n]=NULL; on_off_action[on_off_n++]=0; continue; }
|
||||
if (!strcmp(v[i], "-debug-gui")) { gui_logd = 1; continue; }
|
||||
usage();
|
||||
}
|
||||
|
||||
if (database_filename == NULL) {
|
||||
printf("ERROR: provide a database file (-d)\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
database = parse_database(database_filename);
|
||||
|
||||
load_config_file(database_filename);
|
||||
|
||||
number_of_events = number_of_ids(database);
|
||||
is_on = calloc(number_of_events, sizeof(int));
|
||||
if (is_on == NULL) abort();
|
||||
|
||||
h = new_handler(database);
|
||||
|
||||
g = gui_init();
|
||||
new_thread(gui_thread, g);
|
||||
|
||||
vcd_main_gui(g, h, database);
|
||||
|
||||
on_off(database, "VCD_FUNCTION", is_on, 1);
|
||||
|
||||
for (i = 0; i < on_off_n; i++)
|
||||
on_off(database, on_off_name[i], is_on, on_off_action[i]);
|
||||
|
||||
vcd_data.socket = -1;
|
||||
vcd_data.is_on = is_on;
|
||||
vcd_data.nevents = number_of_events;
|
||||
if (pthread_mutex_init(&vcd_data.lock, NULL)) abort();
|
||||
setup_event_selector(g, database, is_on, is_on_changed, &vcd_data);
|
||||
|
||||
vcd_data.socket = connect_to(ip, port);
|
||||
|
||||
/* send the first message - activate selected traces */
|
||||
is_on_changed(&vcd_data);
|
||||
|
||||
/* read messages */
|
||||
while (1) {
|
||||
char v[T_BUFFER_MAX];
|
||||
event e;
|
||||
e = get_event(vcd_data.socket, v, database);
|
||||
if (e.type == -1) abort();
|
||||
handle_event(h, e);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
CC=gcc
|
||||
CFLAGS=-Wall -g -pthread -I.. -I../logger
|
||||
|
||||
OBJS=stdout.o textlist.o xy.o tti.o time.o ticktime.o
|
||||
|
||||
view.a: $(OBJS)
|
||||
ar cr view.a $(OBJS)
|
||||
|
||||
%.o: %.c
|
||||
$(CC) $(CFLAGS) -o $@ -c $<
|
||||
|
||||
clean:
|
||||
rm -f *.a *.o
|
||||
@@ -0,0 +1,35 @@
|
||||
#include "view.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <pthread.h>
|
||||
|
||||
struct stdout {
|
||||
view common;
|
||||
pthread_mutex_t lock;
|
||||
};
|
||||
|
||||
static void clear(view *this)
|
||||
{
|
||||
/* do nothing */
|
||||
}
|
||||
|
||||
static void append(view *_this, char *s)
|
||||
{
|
||||
struct stdout *this = (struct stdout *)_this;
|
||||
if (pthread_mutex_lock(&this->lock)) abort();
|
||||
printf("%s\n", s);
|
||||
if (pthread_mutex_unlock(&this->lock)) abort();
|
||||
}
|
||||
|
||||
view *new_view_stdout(void)
|
||||
{
|
||||
struct stdout *ret = calloc(1, sizeof(struct stdout));
|
||||
if (ret == NULL) abort();
|
||||
|
||||
ret->common.clear = clear;
|
||||
ret->common.append = (void (*)(view *, ...))append;
|
||||
|
||||
if (pthread_mutex_init(&ret->lock, NULL)) abort();
|
||||
|
||||
return (view *)ret;
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
#include "view.h"
|
||||
#include "../utils.h"
|
||||
#include "gui/gui.h"
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <string.h>
|
||||
|
||||
struct textlist {
|
||||
view common;
|
||||
gui *g;
|
||||
widget *w;
|
||||
int maxsize;
|
||||
int cursize;
|
||||
float refresh_rate;
|
||||
int autoscroll;
|
||||
pthread_mutex_t lock;
|
||||
list * volatile to_append;
|
||||
};
|
||||
|
||||
static void _append(struct textlist *this, char *s, int *deleted)
|
||||
{
|
||||
if (this->cursize == this->maxsize) {
|
||||
textlist_del_silent(this->g, this->w, 0);
|
||||
this->cursize--;
|
||||
(*deleted)++;
|
||||
}
|
||||
textlist_add_silent(this->g, this->w, s, -1, FOREGROUND_COLOR);
|
||||
this->cursize++;
|
||||
}
|
||||
|
||||
static void *textlist_thread(void *_this)
|
||||
{
|
||||
struct textlist *this = _this;
|
||||
int dirty;
|
||||
int deleted;
|
||||
int visible_lines, start_line, number_of_lines;
|
||||
|
||||
while (1) {
|
||||
if (pthread_mutex_lock(&this->lock)) abort();
|
||||
dirty = this->to_append == NULL ? 0 : 1;
|
||||
deleted = 0;
|
||||
while (this->to_append != NULL) {
|
||||
char *s = this->to_append->data;
|
||||
this->to_append = list_remove_head(this->to_append);
|
||||
_append(this, s, &deleted);
|
||||
free(s);
|
||||
}
|
||||
if (dirty) {
|
||||
textlist_state(this->g, this->w, &visible_lines, &start_line,
|
||||
&number_of_lines);
|
||||
if (this->autoscroll)
|
||||
start_line = number_of_lines - visible_lines;
|
||||
else
|
||||
start_line -= deleted;
|
||||
if (start_line < 0) start_line = 0;
|
||||
textlist_set_start_line(this->g, this->w, start_line);
|
||||
/* this call is not necessary, but if things change in textlist... */
|
||||
widget_dirty(this->g, this->w);
|
||||
}
|
||||
if (pthread_mutex_unlock(&this->lock)) abort();
|
||||
sleepms(1000/this->refresh_rate);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void clear(view *this)
|
||||
{
|
||||
/* TODO */
|
||||
}
|
||||
|
||||
static void append(view *_this, char *s)
|
||||
{
|
||||
struct textlist *this = (struct textlist *)_this;
|
||||
char *dup;
|
||||
|
||||
if (pthread_mutex_lock(&this->lock)) abort();
|
||||
dup = strdup(s); if (dup == NULL) abort();
|
||||
this->to_append = list_append(this->to_append, dup);
|
||||
if (pthread_mutex_unlock(&this->lock)) abort();
|
||||
}
|
||||
|
||||
static void scroll(void *private, gui *g,
|
||||
char *notification, widget *w, void *notification_data)
|
||||
{
|
||||
struct textlist *this = private;
|
||||
int visible_lines;
|
||||
int start_line;
|
||||
int number_of_lines;
|
||||
int new_line;
|
||||
int inc;
|
||||
|
||||
if (pthread_mutex_lock(&this->lock)) abort();
|
||||
|
||||
textlist_state(g, w, &visible_lines, &start_line, &number_of_lines);
|
||||
inc = 10;
|
||||
if (inc > visible_lines - 2) inc = visible_lines - 2;
|
||||
if (inc < 1) inc = 1;
|
||||
if (!strcmp(notification, "scrollup")) inc = -inc;
|
||||
|
||||
new_line = start_line + inc;
|
||||
if (new_line > number_of_lines - visible_lines)
|
||||
new_line = number_of_lines - visible_lines;
|
||||
if (new_line < 0) new_line = 0;
|
||||
|
||||
textlist_set_start_line(g, w, new_line);
|
||||
|
||||
if (new_line + visible_lines < number_of_lines)
|
||||
this->autoscroll = 0;
|
||||
else
|
||||
this->autoscroll = 1;
|
||||
|
||||
if (pthread_mutex_unlock(&this->lock)) abort();
|
||||
}
|
||||
|
||||
static void click(void *private, gui *g,
|
||||
char *notification, widget *w, void *notification_data)
|
||||
{
|
||||
struct textlist *this = private;
|
||||
int *d = notification_data;
|
||||
int button = d[1];
|
||||
|
||||
if (pthread_mutex_lock(&this->lock)) abort();
|
||||
|
||||
if (button == 1) this->autoscroll = 1 - this->autoscroll;
|
||||
|
||||
if (pthread_mutex_unlock(&this->lock)) abort();
|
||||
}
|
||||
|
||||
view *new_view_textlist(int maxsize, float refresh_rate, gui *g, widget *w)
|
||||
{
|
||||
struct textlist *ret = calloc(1, sizeof(struct textlist));
|
||||
if (ret == NULL) abort();
|
||||
|
||||
ret->common.clear = clear;
|
||||
ret->common.append = (void (*)(view *, ...))append;
|
||||
|
||||
ret->cursize = 0;
|
||||
ret->maxsize = maxsize;
|
||||
ret->refresh_rate = refresh_rate;
|
||||
ret->g = g;
|
||||
ret->w = w;
|
||||
ret->autoscroll = 1;
|
||||
|
||||
if (pthread_mutex_init(&ret->lock, NULL)) abort();
|
||||
|
||||
register_notifier(g, "scrollup", w, scroll, ret);
|
||||
register_notifier(g, "scrolldown", w, scroll, ret);
|
||||
register_notifier(g, "click", w, click, ret);
|
||||
|
||||
new_thread(textlist_thread, ret);
|
||||
|
||||
return (view *)ret;
|
||||
}
|
||||
@@ -0,0 +1,411 @@
|
||||
#include "view.h"
|
||||
#include "../utils.h"
|
||||
#include "logger.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <string.h>
|
||||
|
||||
/* TODO: some code is identical/almost identical to time.c, merge/factorize */
|
||||
|
||||
/****************************************************************************/
|
||||
/* tick timeview */
|
||||
/****************************************************************************/
|
||||
|
||||
struct plot {
|
||||
struct timespec *tick;
|
||||
int ticksize;
|
||||
int tickmaxsize;
|
||||
int tickstart;
|
||||
int line;
|
||||
int color;
|
||||
};
|
||||
|
||||
struct ticktime {
|
||||
view common;
|
||||
gui *g;
|
||||
widget *w;
|
||||
float refresh_rate;
|
||||
pthread_mutex_t lock;
|
||||
struct plot *p;
|
||||
int psize;
|
||||
double pixel_length; /* unit: nanosecond (maximum 1 hour/pixel) */
|
||||
struct timespec latest_time;
|
||||
struct timespec start_time;
|
||||
int autoscroll;
|
||||
struct timespec tick_latest_time;
|
||||
int tick_latest_frame;
|
||||
int tick_latest_subframe;
|
||||
void *clock_ticktime; /* data for the clock tick, see below */
|
||||
};
|
||||
|
||||
/* TODO: put that function somewhere else (utils.c) */
|
||||
static struct timespec time_add(struct timespec a, struct timespec b)
|
||||
{
|
||||
struct timespec ret;
|
||||
ret.tv_sec = a.tv_sec + b.tv_sec;
|
||||
ret.tv_nsec = a.tv_nsec + b.tv_nsec;
|
||||
if (ret.tv_nsec > 1000000000) {
|
||||
ret.tv_sec++;
|
||||
ret.tv_nsec -= 1000000000;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* TODO: put that function somewhere else (utils.c) */
|
||||
static struct timespec time_sub(struct timespec a, struct timespec b)
|
||||
{
|
||||
struct timespec ret;
|
||||
if (a.tv_nsec < b.tv_nsec) {
|
||||
ret.tv_nsec = (int64_t)a.tv_nsec - (int64_t)b.tv_nsec + 1000000000;
|
||||
ret.tv_sec = a.tv_sec - b.tv_sec - 1;
|
||||
} else {
|
||||
ret.tv_nsec = a.tv_nsec - b.tv_nsec;
|
||||
ret.tv_sec = a.tv_sec - b.tv_sec;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* TODO: put that function somewhere else (utils.c) */
|
||||
static struct timespec nano_to_time(int64_t n)
|
||||
{
|
||||
struct timespec ret;
|
||||
ret.tv_sec = n / 1000000000;
|
||||
ret.tv_nsec = n % 1000000000;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* TODO: put that function somewhere else (utils.c) */
|
||||
static int time_cmp(struct timespec a, struct timespec b)
|
||||
{
|
||||
if (a.tv_sec < b.tv_sec) return -1;
|
||||
if (a.tv_sec > b.tv_sec) return 1;
|
||||
if (a.tv_nsec < b.tv_nsec) return -1;
|
||||
if (a.tv_nsec > b.tv_nsec) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int interval_empty(struct ticktime *this, int sub,
|
||||
struct timespec start, struct timespec end)
|
||||
{
|
||||
int a, b, mid;
|
||||
int i;
|
||||
|
||||
if (this->p[sub].ticksize == 0) return 1;
|
||||
|
||||
/* look for a tick larger than start and smaller than end */
|
||||
a = 0;
|
||||
b = this->p[sub].ticksize - 1;
|
||||
while (b >= a) {
|
||||
mid = (a+b) / 2;
|
||||
i = (this->p[sub].tickstart + mid) % this->p[sub].ticksize;
|
||||
if (time_cmp(this->p[sub].tick[i], start) < 0) a = mid + 1;
|
||||
else if (time_cmp(this->p[sub].tick[i], end) > 0) b = mid - 1;
|
||||
else return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void *ticktime_thread(void *_this)
|
||||
{
|
||||
struct ticktime *this = _this;
|
||||
int width;
|
||||
int l;
|
||||
int i;
|
||||
struct timespec tstart;
|
||||
struct timespec tnext;
|
||||
struct plot *p;
|
||||
int64_t pixel_length;
|
||||
|
||||
while (1) {
|
||||
if (pthread_mutex_lock(&this->lock)) abort();
|
||||
|
||||
timeline_get_width(this->g, this->w, &width);
|
||||
timeline_clear_silent(this->g, this->w);
|
||||
|
||||
/* TODO: optimize? */
|
||||
|
||||
/* use rounded pixel_length */
|
||||
pixel_length = this->pixel_length;
|
||||
|
||||
if (this->autoscroll) {
|
||||
tnext = time_add(this->latest_time,
|
||||
(struct timespec){tv_sec:0,tv_nsec:1});
|
||||
tstart = time_sub(tnext, nano_to_time(pixel_length * width));
|
||||
this->start_time = tstart;
|
||||
} else {
|
||||
tstart = this->start_time;
|
||||
tnext = time_add(tstart, nano_to_time(pixel_length * width));
|
||||
}
|
||||
|
||||
for (l = 0; l < this->psize; l++) {
|
||||
for (i = 0; i < width; i++) {
|
||||
struct timespec tick_start, tick_end;
|
||||
tick_start = time_add(tstart, nano_to_time(pixel_length * i));
|
||||
tick_end = time_add(tick_start, nano_to_time(pixel_length-1));
|
||||
if (interval_empty(this, l, tick_start, tick_end))
|
||||
continue;
|
||||
p = &this->p[l];
|
||||
/* TODO: only one call */
|
||||
int x[3] = {i==0?i:i-1, i, i==width-1?i:i+1};
|
||||
timeline_add_points_silent(this->g, this->w, p->line, p->color, x, 3);
|
||||
}
|
||||
}
|
||||
|
||||
widget_dirty(this->g, this->w);
|
||||
|
||||
if (pthread_mutex_unlock(&this->lock)) abort();
|
||||
sleepms(1000 / this->refresh_rate);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void scroll(void *private, gui *g,
|
||||
char *notification, widget *w, void *notification_data)
|
||||
{
|
||||
struct ticktime *this = private;
|
||||
int *d = notification_data;
|
||||
int x = d[0];
|
||||
int key_modifiers = d[2];
|
||||
double mul = 1.2;
|
||||
double pixel_length;
|
||||
int64_t old_px_len_rounded;
|
||||
struct timespec t;
|
||||
int scroll_px;
|
||||
int width;
|
||||
|
||||
if (pthread_mutex_lock(&this->lock)) abort();
|
||||
|
||||
old_px_len_rounded = this->pixel_length;
|
||||
|
||||
/* scroll if control+wheel, zoom otherwise */
|
||||
|
||||
if (key_modifiers & KEY_CONTROL) {
|
||||
timeline_get_width(this->g, this->w, &width);
|
||||
if (width < 2) width = 2;
|
||||
scroll_px = 100;
|
||||
if (scroll_px > width - 1) scroll_px = width - 1;
|
||||
if (!strcmp(notification, "scrolldown"))
|
||||
this->start_time = time_add(this->start_time,
|
||||
nano_to_time(scroll_px * old_px_len_rounded));
|
||||
else
|
||||
this->start_time = time_sub(this->start_time,
|
||||
nano_to_time(scroll_px * old_px_len_rounded));
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!strcmp(notification, "scrollup")) mul = 1 / mul;
|
||||
|
||||
again:
|
||||
pixel_length = this->pixel_length * mul;
|
||||
if (pixel_length < 1) pixel_length = 1;
|
||||
if (pixel_length > (double)3600 * 1000000000)
|
||||
pixel_length = (double)3600 * 1000000000;
|
||||
|
||||
this->pixel_length = pixel_length;
|
||||
|
||||
/* due to rounding, we may need to zoom by more than 1.2 with
|
||||
* very close lookup, otherwise the user zooming command won't
|
||||
* be visible (say length is 2.7, zoom in, new length is 2.25,
|
||||
* and rounding is 2, same value, no change, no feedback to user => bad)
|
||||
* TODO: make all this cleaner
|
||||
*/
|
||||
if (pixel_length != 1 && pixel_length != (double)3600 * 1000000000 &&
|
||||
(int64_t)pixel_length == old_px_len_rounded)
|
||||
goto again;
|
||||
|
||||
t = time_add(this->start_time, nano_to_time(x * old_px_len_rounded));
|
||||
this->start_time = time_sub(t, nano_to_time(x * (int64_t)pixel_length));
|
||||
|
||||
end:
|
||||
if (pthread_mutex_unlock(&this->lock)) abort();
|
||||
}
|
||||
|
||||
static void click(void *private, gui *g,
|
||||
char *notification, widget *w, void *notification_data)
|
||||
{
|
||||
struct ticktime *this = private;
|
||||
int *d = notification_data;
|
||||
int button = *d;
|
||||
|
||||
if (button == 3) this->autoscroll = 0;
|
||||
if (button == 1) this->autoscroll = 1;
|
||||
}
|
||||
|
||||
view *new_view_ticktime(float refresh_rate, gui *g, widget *w)
|
||||
{
|
||||
struct ticktime *ret = calloc(1, sizeof(struct ticktime));
|
||||
if (ret == NULL) abort();
|
||||
|
||||
ret->refresh_rate = refresh_rate;
|
||||
ret->g = g;
|
||||
ret->w = w;
|
||||
|
||||
ret->p = NULL;
|
||||
ret->psize = 0;
|
||||
|
||||
ret->autoscroll = 1;
|
||||
|
||||
ret->tick_latest_time.tv_sec = 1;
|
||||
|
||||
/* default pixel length: 10ms */
|
||||
ret->pixel_length = 10 * 1000000;
|
||||
|
||||
register_notifier(g, "scrollup", w, scroll, ret);
|
||||
register_notifier(g, "scrolldown", w, scroll, ret);
|
||||
register_notifier(g, "click", w, click, ret);
|
||||
|
||||
if (pthread_mutex_init(&ret->lock, NULL)) abort();
|
||||
|
||||
new_thread(ticktime_thread, ret);
|
||||
|
||||
return (view *)ret;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
/* subticktimeview */
|
||||
/****************************************************************************/
|
||||
|
||||
struct subticktime {
|
||||
view common;
|
||||
struct ticktime *parent;
|
||||
int line;
|
||||
int color;
|
||||
int subview;
|
||||
};
|
||||
|
||||
static void append(view *_this, struct timespec t, int frame, int subframe)
|
||||
{
|
||||
struct subticktime *this = (struct subticktime *)_this;
|
||||
struct ticktime *ticktime = this->parent;
|
||||
struct plot *p = &ticktime->p[this->subview];
|
||||
int i;
|
||||
struct timespec swap;
|
||||
int64_t diff;
|
||||
|
||||
if (pthread_mutex_lock(&ticktime->lock)) abort();
|
||||
|
||||
/* get time with respect to latest known tick time */
|
||||
diff = (frame*10 + subframe) -
|
||||
(ticktime->tick_latest_frame*10 + ticktime->tick_latest_subframe);
|
||||
if (diff > 1024*10/2) diff -= 1024*10;
|
||||
else if (diff < -1024*10/2) diff += 1024*10;
|
||||
if (diff < 0)
|
||||
t = time_sub(ticktime->tick_latest_time, nano_to_time(-diff * 1000000));
|
||||
else
|
||||
t = time_add(ticktime->tick_latest_time, nano_to_time(diff * 1000000));
|
||||
|
||||
if (p->ticksize < p->tickmaxsize) {
|
||||
p->tick[p->ticksize] = t;
|
||||
p->ticksize++;
|
||||
} else {
|
||||
p->tick[p->tickstart] = t;
|
||||
p->tickstart = (p->tickstart + 1) % p->ticksize;
|
||||
}
|
||||
|
||||
/* due to adjustment of the time, array may not be ordered anymore */
|
||||
for (i = p->ticksize-2; i >= 0; i--) {
|
||||
int prev = (p->tickstart + i) % p->ticksize;
|
||||
int cur = (prev + 1) % p->ticksize;
|
||||
if (time_cmp(p->tick[prev], p->tick[cur]) <= 0) break;
|
||||
swap = p->tick[prev];
|
||||
p->tick[prev] = p->tick[cur];
|
||||
p->tick[cur] = swap;
|
||||
}
|
||||
|
||||
if (time_cmp(ticktime->latest_time, t) < 0)
|
||||
ticktime->latest_time = t;
|
||||
|
||||
if (pthread_mutex_unlock(&ticktime->lock)) abort();
|
||||
}
|
||||
|
||||
view *new_subview_ticktime(view *_time, int line, int color, int size)
|
||||
{
|
||||
struct ticktime *ticktime = (struct ticktime *)_time;
|
||||
struct subticktime *ret = calloc(1, sizeof(struct subticktime));
|
||||
if (ret == NULL) abort();
|
||||
|
||||
ret->common.append = (void (*)(view *, ...))append;
|
||||
|
||||
if (pthread_mutex_lock(&ticktime->lock)) abort();
|
||||
|
||||
ret->parent = ticktime;
|
||||
ret->line = line;
|
||||
ret->color = color;
|
||||
ret->subview = ticktime->psize;
|
||||
|
||||
ticktime->p = realloc(ticktime->p,
|
||||
(ticktime->psize + 1) * sizeof(struct plot));
|
||||
if (ticktime->p == NULL) abort();
|
||||
ticktime->p[ticktime->psize].tick = calloc(size, sizeof(struct timespec));
|
||||
if (ticktime->p[ticktime->psize].tick == NULL) abort();
|
||||
ticktime->p[ticktime->psize].ticksize = 0;
|
||||
ticktime->p[ticktime->psize].tickmaxsize = size;
|
||||
ticktime->p[ticktime->psize].tickstart = 0;
|
||||
ticktime->p[ticktime->psize].line = line;
|
||||
ticktime->p[ticktime->psize].color = color;
|
||||
|
||||
ticktime->psize++;
|
||||
|
||||
if (pthread_mutex_unlock(&ticktime->lock)) abort();
|
||||
|
||||
return (view *)ret;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
/* clock tick */
|
||||
/****************************************************************************/
|
||||
|
||||
struct clock_ticktime {
|
||||
view common;
|
||||
struct ticktime *parent;
|
||||
};
|
||||
|
||||
static void clock_append(view *_this, struct timespec t,
|
||||
int frame, int subframe)
|
||||
{
|
||||
struct clock_ticktime *this = (struct clock_ticktime *)_this;
|
||||
struct ticktime *tt = this->parent;
|
||||
int64_t diff;
|
||||
|
||||
if (subframe == 10) { subframe = 0; frame = (frame + 1) % 1024; }
|
||||
|
||||
if (pthread_mutex_lock(&tt->lock)) abort();
|
||||
|
||||
/* get time relative to latest known tick time */
|
||||
/* In normal conditions diff is 1 but if the user pauses reception of events
|
||||
* it may be anything. Let's take only positive values.
|
||||
*/
|
||||
diff = (frame*10 + subframe) -
|
||||
(tt->tick_latest_frame*10 + tt->tick_latest_subframe);
|
||||
if (diff < 0) diff += 1024*10;
|
||||
tt->tick_latest_time = time_add(tt->tick_latest_time,
|
||||
nano_to_time(diff * 1000000));
|
||||
tt->tick_latest_frame = frame;
|
||||
tt->tick_latest_subframe = subframe;
|
||||
|
||||
if (time_cmp(tt->latest_time, tt->tick_latest_time) < 0)
|
||||
tt->latest_time = tt->tick_latest_time;
|
||||
|
||||
if (pthread_mutex_unlock(&tt->lock)) abort();
|
||||
}
|
||||
|
||||
void ticktime_set_tick(view *_ticktime, void *logger)
|
||||
{
|
||||
struct ticktime *ticktime = (struct ticktime *)_ticktime;
|
||||
struct clock_ticktime *n;
|
||||
|
||||
if (pthread_mutex_lock(&ticktime->lock)) abort();
|
||||
|
||||
free(ticktime->clock_ticktime);
|
||||
n = ticktime->clock_ticktime = calloc(1, sizeof(struct clock_ticktime));
|
||||
if (n == NULL) abort();
|
||||
|
||||
n->common.append = (void (*)(view *, ...))clock_append;
|
||||
n->parent = ticktime;
|
||||
|
||||
logger_add_view(logger, (view *)n);
|
||||
|
||||
if (pthread_mutex_unlock(&ticktime->lock)) abort();
|
||||
}
|
||||
@@ -0,0 +1,322 @@
|
||||
#include "view.h"
|
||||
#include "../utils.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <string.h>
|
||||
|
||||
/****************************************************************************/
|
||||
/* timeview */
|
||||
/****************************************************************************/
|
||||
|
||||
struct plot {
|
||||
struct timespec *tick;
|
||||
int ticksize;
|
||||
int tickmaxsize;
|
||||
int tickstart;
|
||||
int line;
|
||||
int color;
|
||||
};
|
||||
|
||||
struct time {
|
||||
view common;
|
||||
gui *g;
|
||||
widget *w;
|
||||
float refresh_rate;
|
||||
pthread_mutex_t lock;
|
||||
struct plot *p;
|
||||
int psize;
|
||||
double pixel_length; /* unit: nanosecond (maximum 1 hour/pixel) */
|
||||
struct timespec latest_time;
|
||||
struct timespec start_time;
|
||||
int autoscroll;
|
||||
};
|
||||
|
||||
/* TODO: put that function somewhere else (utils.c) */
|
||||
static struct timespec time_add(struct timespec a, struct timespec b)
|
||||
{
|
||||
struct timespec ret;
|
||||
ret.tv_sec = a.tv_sec + b.tv_sec;
|
||||
ret.tv_nsec = a.tv_nsec + b.tv_nsec;
|
||||
if (ret.tv_nsec > 1000000000) {
|
||||
ret.tv_sec++;
|
||||
ret.tv_nsec -= 1000000000;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* TODO: put that function somewhere else (utils.c) */
|
||||
static struct timespec time_sub(struct timespec a, struct timespec b)
|
||||
{
|
||||
struct timespec ret;
|
||||
if (a.tv_nsec < b.tv_nsec) {
|
||||
ret.tv_nsec = (int64_t)a.tv_nsec - (int64_t)b.tv_nsec + 1000000000;
|
||||
ret.tv_sec = a.tv_sec - b.tv_sec - 1;
|
||||
} else {
|
||||
ret.tv_nsec = a.tv_nsec - b.tv_nsec;
|
||||
ret.tv_sec = a.tv_sec - b.tv_sec;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* TODO: put that function somewhere else (utils.c) */
|
||||
static struct timespec nano_to_time(int64_t n)
|
||||
{
|
||||
struct timespec ret;
|
||||
ret.tv_sec = n / 1000000000;
|
||||
ret.tv_nsec = n % 1000000000;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* TODO: put that function somewhere else (utils.c) */
|
||||
static int time_cmp(struct timespec a, struct timespec b)
|
||||
{
|
||||
if (a.tv_sec < b.tv_sec) return -1;
|
||||
if (a.tv_sec > b.tv_sec) return 1;
|
||||
if (a.tv_nsec < b.tv_nsec) return -1;
|
||||
if (a.tv_nsec > b.tv_nsec) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int interval_empty(struct time *this, int sub,
|
||||
struct timespec start, struct timespec end)
|
||||
{
|
||||
int a, b, mid;
|
||||
int i;
|
||||
|
||||
if (this->p[sub].ticksize == 0) return 1;
|
||||
|
||||
/* look for a tick larger than start and smaller than end */
|
||||
a = 0;
|
||||
b = this->p[sub].ticksize - 1;
|
||||
while (b >= a) {
|
||||
mid = (a+b) / 2;
|
||||
i = (this->p[sub].tickstart + mid) % this->p[sub].ticksize;
|
||||
if (time_cmp(this->p[sub].tick[i], start) < 0) a = mid + 1;
|
||||
else if (time_cmp(this->p[sub].tick[i], end) > 0) b = mid - 1;
|
||||
else return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void *time_thread(void *_this)
|
||||
{
|
||||
struct time *this = _this;
|
||||
int width;
|
||||
int l;
|
||||
int i;
|
||||
struct timespec tstart;
|
||||
struct timespec tnext;
|
||||
struct plot *p;
|
||||
int64_t pixel_length;
|
||||
|
||||
while (1) {
|
||||
if (pthread_mutex_lock(&this->lock)) abort();
|
||||
|
||||
timeline_get_width(this->g, this->w, &width);
|
||||
timeline_clear_silent(this->g, this->w);
|
||||
|
||||
/* TODO: optimize? */
|
||||
|
||||
/* use rounded pixel_length */
|
||||
pixel_length = this->pixel_length;
|
||||
|
||||
if (this->autoscroll) {
|
||||
tnext = time_add(this->latest_time,
|
||||
(struct timespec){tv_sec:0,tv_nsec:1});
|
||||
tstart = time_sub(tnext, nano_to_time(pixel_length * width));
|
||||
this->start_time = tstart;
|
||||
} else {
|
||||
tstart = this->start_time;
|
||||
tnext = time_add(tstart, nano_to_time(pixel_length * width));
|
||||
}
|
||||
|
||||
for (l = 0; l < this->psize; l++) {
|
||||
for (i = 0; i < width; i++) {
|
||||
struct timespec tick_start, tick_end;
|
||||
tick_start = time_add(tstart, nano_to_time(pixel_length * i));
|
||||
tick_end = time_add(tick_start, nano_to_time(pixel_length-1));
|
||||
if (interval_empty(this, l, tick_start, tick_end))
|
||||
continue;
|
||||
p = &this->p[l];
|
||||
/* TODO: only one call */
|
||||
timeline_add_points_silent(this->g, this->w, p->line, p->color, &i, 1);
|
||||
}
|
||||
}
|
||||
|
||||
widget_dirty(this->g, this->w);
|
||||
|
||||
if (pthread_mutex_unlock(&this->lock)) abort();
|
||||
sleepms(1000 / this->refresh_rate);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void scroll(void *private, gui *g,
|
||||
char *notification, widget *w, void *notification_data)
|
||||
{
|
||||
struct time *this = private;
|
||||
int *d = notification_data;
|
||||
int x = d[0];
|
||||
int key_modifiers = d[2];
|
||||
double mul = 1.2;
|
||||
double pixel_length;
|
||||
int64_t old_px_len_rounded;
|
||||
struct timespec t;
|
||||
int scroll_px;
|
||||
int width;
|
||||
|
||||
if (pthread_mutex_lock(&this->lock)) abort();
|
||||
|
||||
old_px_len_rounded = this->pixel_length;
|
||||
|
||||
/* scroll if control+wheel, zoom otherwise */
|
||||
|
||||
if (key_modifiers & KEY_CONTROL) {
|
||||
timeline_get_width(this->g, this->w, &width);
|
||||
if (width < 2) width = 2;
|
||||
scroll_px = 100;
|
||||
if (scroll_px > width - 1) scroll_px = width - 1;
|
||||
if (!strcmp(notification, "scrolldown"))
|
||||
this->start_time = time_add(this->start_time,
|
||||
nano_to_time(scroll_px * old_px_len_rounded));
|
||||
else
|
||||
this->start_time = time_sub(this->start_time,
|
||||
nano_to_time(scroll_px * old_px_len_rounded));
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!strcmp(notification, "scrollup")) mul = 1 / mul;
|
||||
|
||||
again:
|
||||
pixel_length = this->pixel_length * mul;
|
||||
if (pixel_length < 1) pixel_length = 1;
|
||||
if (pixel_length > (double)3600 * 1000000000)
|
||||
pixel_length = (double)3600 * 1000000000;
|
||||
|
||||
this->pixel_length = pixel_length;
|
||||
|
||||
/* due to rounding, we may need to zoom by more than 1.2 with
|
||||
* very close lookup, otherwise the user zooming command won't
|
||||
* be visible (say length is 2.7, zoom in, new length is 2.25,
|
||||
* and rounding is 2, same value, no change, no feedback to user => bad)
|
||||
* TODO: make all this cleaner
|
||||
*/
|
||||
if (pixel_length != 1 && pixel_length != (double)3600 * 1000000000 &&
|
||||
(int64_t)pixel_length == old_px_len_rounded)
|
||||
goto again;
|
||||
|
||||
t = time_add(this->start_time, nano_to_time(x * old_px_len_rounded));
|
||||
this->start_time = time_sub(t, nano_to_time(x * (int64_t)pixel_length));
|
||||
|
||||
end:
|
||||
if (pthread_mutex_unlock(&this->lock)) abort();
|
||||
}
|
||||
|
||||
static void click(void *private, gui *g,
|
||||
char *notification, widget *w, void *notification_data)
|
||||
{
|
||||
struct time *this = private;
|
||||
int *d = notification_data;
|
||||
int button = *d;
|
||||
|
||||
if (button == 3) this->autoscroll = 0;
|
||||
if (button == 1) this->autoscroll = 1;
|
||||
}
|
||||
|
||||
view *new_view_time(int number_of_seconds, float refresh_rate,
|
||||
gui *g, widget *w)
|
||||
{
|
||||
struct time *ret = calloc(1, sizeof(struct time));
|
||||
if (ret == NULL) abort();
|
||||
|
||||
ret->refresh_rate = refresh_rate;
|
||||
ret->g = g;
|
||||
ret->w = w;
|
||||
|
||||
ret->p = NULL;
|
||||
ret->psize = 0;
|
||||
|
||||
ret->autoscroll = 1;
|
||||
|
||||
/* default pixel length: 10ms */
|
||||
ret->pixel_length = 10 * 1000000;
|
||||
|
||||
register_notifier(g, "scrollup", w, scroll, ret);
|
||||
register_notifier(g, "scrolldown", w, scroll, ret);
|
||||
register_notifier(g, "click", w, click, ret);
|
||||
|
||||
if (pthread_mutex_init(&ret->lock, NULL)) abort();
|
||||
|
||||
new_thread(time_thread, ret);
|
||||
|
||||
return (view *)ret;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
/* subtimeview */
|
||||
/****************************************************************************/
|
||||
|
||||
struct subtime {
|
||||
view common;
|
||||
struct time *parent;
|
||||
int line;
|
||||
int color;
|
||||
int subview;
|
||||
};
|
||||
|
||||
static void append(view *_this, struct timespec t)
|
||||
{
|
||||
struct subtime *this = (struct subtime *)_this;
|
||||
struct time *time = this->parent;
|
||||
struct plot *p = &time->p[this->subview];
|
||||
|
||||
if (pthread_mutex_lock(&time->lock)) abort();
|
||||
|
||||
if (p->ticksize < p->tickmaxsize) {
|
||||
p->tick[p->ticksize] = t;
|
||||
p->ticksize++;
|
||||
} else {
|
||||
p->tick[p->tickstart] = t;
|
||||
p->tickstart = (p->tickstart + 1) % p->ticksize;
|
||||
}
|
||||
|
||||
if (time_cmp(time->latest_time, t) < 0)
|
||||
time->latest_time = t;
|
||||
|
||||
if (pthread_mutex_unlock(&time->lock)) abort();
|
||||
}
|
||||
|
||||
view *new_subview_time(view *_time, int line, int color, int size)
|
||||
{
|
||||
struct time *time = (struct time *)_time;
|
||||
struct subtime *ret = calloc(1, sizeof(struct subtime));
|
||||
if (ret == NULL) abort();
|
||||
|
||||
ret->common.append = (void (*)(view *, ...))append;
|
||||
|
||||
if (pthread_mutex_lock(&time->lock)) abort();
|
||||
|
||||
ret->parent = time;
|
||||
ret->line = line;
|
||||
ret->color = color;
|
||||
ret->subview = time->psize;
|
||||
|
||||
time->p = realloc(time->p,
|
||||
(time->psize + 1) * sizeof(struct plot));
|
||||
if (time->p == NULL) abort();
|
||||
time->p[time->psize].tick = calloc(size, sizeof(struct timespec));
|
||||
if (time->p[time->psize].tick == NULL) abort();
|
||||
time->p[time->psize].ticksize = 0;
|
||||
time->p[time->psize].tickmaxsize = size;
|
||||
time->p[time->psize].tickstart = 0;
|
||||
time->p[time->psize].line = line;
|
||||
time->p[time->psize].color = color;
|
||||
|
||||
time->psize++;
|
||||
|
||||
if (pthread_mutex_unlock(&time->lock)) abort();
|
||||
|
||||
return (view *)ret;
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
#include "view.h"
|
||||
#include "../utils.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
||||
struct tti {
|
||||
view common;
|
||||
gui *g;
|
||||
widget *w;
|
||||
int plot;
|
||||
float refresh_rate;
|
||||
pthread_mutex_t lock;
|
||||
float data[1024*10];
|
||||
int valid[1024*10];
|
||||
float xout[1024*10];
|
||||
float yout[1024*10];
|
||||
int last_insert_point;
|
||||
};
|
||||
|
||||
static int far_enough(int i, int last_insert, int plot_width)
|
||||
{
|
||||
int p1;
|
||||
int p2;
|
||||
int hole_size_px;
|
||||
int hole_size_tti;
|
||||
hole_size_px = 10;
|
||||
hole_size_tti = 10240 * hole_size_px / plot_width;
|
||||
p1 = last_insert;
|
||||
p2 = (last_insert + hole_size_tti) % (1024*10);
|
||||
if (p1 < p2) {
|
||||
return !(i > p1 && i < p2);
|
||||
}
|
||||
return i > p2 && i <= p1;
|
||||
}
|
||||
|
||||
static void *tti_thread(void *_this)
|
||||
{
|
||||
struct tti *this = _this;
|
||||
int i;
|
||||
int length;
|
||||
int plot_width;
|
||||
int plot_height;
|
||||
|
||||
while (1) {
|
||||
if (pthread_mutex_lock(&this->lock)) abort();
|
||||
xy_plot_get_dimensions(this->g, this->w, &plot_width, &plot_height);
|
||||
length = 0;
|
||||
/* TODO: optimize */
|
||||
for (i = 0; i < 1024*10; i++)
|
||||
/* do not take points too close after last insertion point */
|
||||
if (this->valid[i] &&
|
||||
far_enough(i, this->last_insert_point, plot_width)) {
|
||||
this->xout[length] = i;
|
||||
this->yout[length] = this->data[i];
|
||||
length++;
|
||||
}
|
||||
xy_plot_set_points(this->g, this->w, this->plot,
|
||||
length, this->xout, this->yout);
|
||||
if (pthread_mutex_unlock(&this->lock)) abort();
|
||||
sleepms(1000/this->refresh_rate);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void clear(view *this)
|
||||
{
|
||||
/* TODO */
|
||||
}
|
||||
|
||||
static void append(view *_this, int frame, int subframe, double value)
|
||||
{
|
||||
struct tti *this = (struct tti *)_this;
|
||||
int i;
|
||||
int index = frame * 10 + subframe;
|
||||
|
||||
if (pthread_mutex_lock(&this->lock)) abort();
|
||||
|
||||
/* TODO: optimize */
|
||||
/* clear all between last insert point and current one
|
||||
* this may be wrong if delay between two append is
|
||||
* greater than 1024 frames (something like that)
|
||||
*/
|
||||
i = (this->last_insert_point + 1) % (1024*10);
|
||||
while (i != index) {
|
||||
this->valid[i] = 0;
|
||||
i = (i + 1) % (1024*10);
|
||||
}
|
||||
|
||||
this->data[index] = value;
|
||||
this->valid[index] = 1;
|
||||
|
||||
this->last_insert_point = index;
|
||||
|
||||
if (pthread_mutex_unlock(&this->lock)) abort();
|
||||
}
|
||||
|
||||
view *new_view_tti(float refresh_rate, gui *g, widget *w, int color)
|
||||
{
|
||||
struct tti *ret = calloc(1, sizeof(struct tti));
|
||||
if (ret == NULL) abort();
|
||||
|
||||
ret->common.clear = clear;
|
||||
ret->common.append = (void (*)(view *, ...))append;
|
||||
|
||||
ret->refresh_rate = refresh_rate;
|
||||
ret->g = g;
|
||||
ret->w = w;
|
||||
ret->plot = xy_plot_new_plot(g, w, color);
|
||||
|
||||
ret->last_insert_point = 0;
|
||||
|
||||
if (pthread_mutex_init(&ret->lock, NULL)) abort();
|
||||
|
||||
new_thread(tti_thread, ret);
|
||||
|
||||
return (view *)ret;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
#ifndef _VIEW_H_
|
||||
#define _VIEW_H_
|
||||
|
||||
#include "gui/gui.h"
|
||||
|
||||
/* defines the public API of views */
|
||||
|
||||
typedef struct view {
|
||||
void (*clear)(struct view *this);
|
||||
void (*append)(struct view *this, ...);
|
||||
void (*set)(struct view *this, char *name, ...);
|
||||
} view;
|
||||
|
||||
view *new_view_stdout(void);
|
||||
view *new_view_textlist(int maxsize, float refresh_rate, gui *g, widget *w);
|
||||
view *new_view_xy(int length, float refresh_rate, gui *g, widget *w,
|
||||
int color);
|
||||
view *new_view_tti(float refresh_rate, gui *g, widget *w,
|
||||
int color);
|
||||
view *new_view_time(int number_of_seconds, float refresh_rate,
|
||||
gui *g, widget *w);
|
||||
view *new_subview_time(view *time, int line, int color, int size);
|
||||
view *new_view_ticktime(float refresh_rate, gui *g, widget *w);
|
||||
view *new_subview_ticktime(view *ticktime, int line, int color, int size);
|
||||
void ticktime_set_tick(view *ticktime, void *logger);
|
||||
|
||||
#endif /* _VIEW_H_ */
|
||||
@@ -0,0 +1,116 @@
|
||||
#include "view.h"
|
||||
#include "../utils.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
||||
struct xy {
|
||||
view common;
|
||||
gui *g;
|
||||
widget *w;
|
||||
int plot;
|
||||
float refresh_rate;
|
||||
pthread_mutex_t lock;
|
||||
int length;
|
||||
float *x;
|
||||
float *y;
|
||||
int insert_point;
|
||||
};
|
||||
|
||||
static void *xy_thread(void *_this)
|
||||
{
|
||||
struct xy *this = _this;
|
||||
|
||||
while (1) {
|
||||
if (pthread_mutex_lock(&this->lock)) abort();
|
||||
xy_plot_set_points(this->g, this->w, this->plot,
|
||||
this->length, this->x, this->y);
|
||||
if (pthread_mutex_unlock(&this->lock)) abort();
|
||||
sleepms(1000/this->refresh_rate);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void clear(view *this)
|
||||
{
|
||||
/* TODO */
|
||||
}
|
||||
|
||||
static void append(view *_this, float *x, float *y, int length)
|
||||
{
|
||||
struct xy *this = (struct xy *)_this;
|
||||
int i;
|
||||
int ip;
|
||||
|
||||
if (pthread_mutex_lock(&this->lock)) abort();
|
||||
|
||||
ip = this->insert_point;
|
||||
|
||||
/* TODO: optimize the copy */
|
||||
for (i = 0; i < length; i++) {
|
||||
this->x[ip] = x[i];
|
||||
this->y[ip] = y[i];
|
||||
ip++; if (ip == this->length) ip = 0;
|
||||
}
|
||||
|
||||
this->insert_point = ip;
|
||||
|
||||
if (pthread_mutex_unlock(&this->lock)) abort();
|
||||
}
|
||||
|
||||
static void set(view *_this, char *name, ...)
|
||||
{
|
||||
struct xy *this = (struct xy *)_this;
|
||||
va_list ap;
|
||||
|
||||
if (!strcmp(name, "length")) {
|
||||
if (pthread_mutex_lock(&this->lock)) abort();
|
||||
|
||||
va_start(ap, name);
|
||||
|
||||
free(this->x);
|
||||
free(this->y);
|
||||
this->length = va_arg(ap, int);
|
||||
this->x = calloc(this->length, sizeof(float)); if (this->x==NULL)abort();
|
||||
this->y = calloc(this->length, sizeof(float)); if (this->y==NULL)abort();
|
||||
this->insert_point = 0;
|
||||
|
||||
va_end(ap);
|
||||
|
||||
if (pthread_mutex_unlock(&this->lock)) abort();
|
||||
return;
|
||||
}
|
||||
|
||||
printf("%s:%d: unkown setting '%s'\n", __FILE__, __LINE__, name);
|
||||
abort();
|
||||
}
|
||||
|
||||
view *new_view_xy(int length, float refresh_rate, gui *g, widget *w,
|
||||
int color)
|
||||
{
|
||||
struct xy *ret = calloc(1, sizeof(struct xy));
|
||||
if (ret == NULL) abort();
|
||||
|
||||
ret->common.clear = clear;
|
||||
ret->common.append = (void (*)(view *, ...))append;
|
||||
ret->common.set = set;
|
||||
|
||||
ret->refresh_rate = refresh_rate;
|
||||
ret->g = g;
|
||||
ret->w = w;
|
||||
ret->plot = xy_plot_new_plot(g, w, color);
|
||||
|
||||
ret->length = length;
|
||||
ret->x = calloc(length, sizeof(float)); if (ret->x == NULL) abort();
|
||||
ret->y = calloc(length, sizeof(float)); if (ret->y == NULL) abort();
|
||||
ret->insert_point = 0;
|
||||
|
||||
if (pthread_mutex_init(&ret->lock, NULL)) abort();
|
||||
|
||||
new_thread(xy_thread, ret);
|
||||
|
||||
return (view *)ret;
|
||||
}
|
||||
@@ -58,6 +58,10 @@
|
||||
# include "vcd_signal_dumper.h"
|
||||
#endif
|
||||
|
||||
#if T_TRACER
|
||||
#include "T.h"
|
||||
#endif
|
||||
|
||||
/* Includes "intertask_interface_init.h" to check prototype coherence, but
|
||||
* disable threads and messages information generation.
|
||||
*/
|
||||
|
||||
@@ -64,6 +64,10 @@
|
||||
#include "vcd_signal_dumper.h"
|
||||
#endif
|
||||
|
||||
#if T_TRACER
|
||||
#include "T.h"
|
||||
#endif
|
||||
|
||||
static const int itti_dump_debug = 0; // 0x8 | 0x4 | 0x2;
|
||||
|
||||
#ifdef RTAI
|
||||
|
||||
@@ -37,6 +37,11 @@
|
||||
# include "vcd_signal_dumper.h"
|
||||
#endif
|
||||
|
||||
#if T_TRACER
|
||||
#include <string.h>
|
||||
#include "T.h"
|
||||
#endif
|
||||
|
||||
/*------------------------------------------------------------------------------*/
|
||||
const static int mp_debug = 0;
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include "PHY/sse_intrin.h"
|
||||
//#define DEBUG_CH
|
||||
|
||||
#include "T.h"
|
||||
|
||||
// For Channel Estimation in Distributed Alamouti Scheme
|
||||
//static int16_t temp_out_ifft[2048*4] __attribute__((aligned(16)));
|
||||
@@ -331,6 +332,13 @@ int32_t lte_ul_channel_estimation(PHY_VARS_eNB *eNB,
|
||||
break;
|
||||
}
|
||||
|
||||
#if T_TRACER
|
||||
if (aa == 0)
|
||||
T(T_ENB_PHY_UL_CHANNEL_ESTIMATE, T_INT(eNB_id), T_INT(UE_id),
|
||||
T_INT(phy_vars_eNB->proc[sched_subframe].frame_rx), T_INT(subframe),
|
||||
T_INT(0), T_BUFFER(ul_ch_estimates_time[0], 512 * 4));
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_CH
|
||||
|
||||
if (aa==0) {
|
||||
|
||||
@@ -46,6 +46,8 @@
|
||||
#include "ARCH/CBMIMO1/DEVICE_DRIVER/extern.h"
|
||||
#endif
|
||||
|
||||
#include "T.h"
|
||||
|
||||
//#define DEBUG_PHICH 1
|
||||
|
||||
//extern unsigned short pcfich_reg[4];
|
||||
@@ -1501,9 +1503,12 @@ void generate_phich_top(PHY_VARS_eNB *eNB,
|
||||
// if no format0 DCI was transmitted by MAC, prepare the
|
||||
// MCS parameters for the retransmission
|
||||
|
||||
|
||||
if ((ulsch[UE_id]->harq_processes[harq_pid]->dci_alloc == 0) &&
|
||||
(ulsch[UE_id]->harq_processes[harq_pid]->rar_alloc == 0) ) {
|
||||
if (ulsch[UE_id]->harq_processes[harq_pid]->phich_ACK==0 ) {
|
||||
T(T_ENB_PHY_ULSCH_UE_NO_DCI_RETRANSMISSION, T_INT(eNB->Mod_id), T_INT(eNB->proc->frame_tx),
|
||||
T_INT(subframe), T_INT(UE_id), T_INT(ulsch[UE_id]->rnti), T_INT(harq_pid));
|
||||
LOG_D(PHY,"[eNB %d][PUSCH %d] frame %d, subframe %d : PHICH NACK / (no format0 DCI) Setting subframe_scheduling_flag\n",
|
||||
eNB->Mod_id,harq_pid,proc->frame_tx,subframe);
|
||||
ulsch[UE_id]->harq_processes[harq_pid]->subframe_scheduling_flag = 1;
|
||||
|
||||
@@ -1667,6 +1667,7 @@ uint32_t rx_pucch(PHY_VARS_eNB *phy_vars_eNB,
|
||||
uint16_t n2_pucch,
|
||||
uint8_t shortened_format,
|
||||
uint8_t *payload,
|
||||
int frame,
|
||||
uint8_t subframe,
|
||||
uint8_t pucch1_thres);
|
||||
|
||||
|
||||
@@ -44,6 +44,8 @@
|
||||
#include "UTIL/LOG/log.h"
|
||||
#include "UTIL/LOG/vcd_signal_dumper.h"
|
||||
|
||||
#include "T.h"
|
||||
|
||||
//uint8_t ncs_cell[20][7];
|
||||
//#define DEBUG_PUCCH_TX
|
||||
//#define DEBUG_PUCCH_RX
|
||||
@@ -440,6 +442,7 @@ uint32_t rx_pucch(PHY_VARS_eNB *eNB,
|
||||
uint16_t n2_pucch,
|
||||
uint8_t shortened_format,
|
||||
uint8_t *payload,
|
||||
int frame,
|
||||
uint8_t subframe,
|
||||
uint8_t pucch1_thres)
|
||||
{
|
||||
@@ -796,6 +799,9 @@ uint32_t rx_pucch(PHY_VARS_eNB *eNB,
|
||||
eNB->pucch1_stats_thres[UE_id][(subframe<<10)+eNB->pucch1_stats_cnt[UE_id][subframe]] = sigma2_dB+pucch1_thres;
|
||||
eNB->pucch1_stats_cnt[UE_id][subframe] = (eNB->pucch1_stats_cnt[UE_id][subframe]+1)&1023;
|
||||
|
||||
T(T_ENB_PHY_PUCCH_1_ENERGY, T_INT(phy_vars_eNB->Mod_id), T_INT(UE_id), T_INT(frame), T_INT(subframe),
|
||||
T_INT(stat_max), T_INT(sigma2_dB+pucch1_thres));
|
||||
|
||||
/*
|
||||
if (eNB->pucch1_stats_cnt[UE_id][subframe] == 0) {
|
||||
write_output("pucch_debug.m","pucch_energy",
|
||||
@@ -1037,6 +1043,8 @@ uint32_t rx_pucch(PHY_VARS_eNB *eNB,
|
||||
eNB->pucch1ab_stats[UE_id][(subframe<<11) + 1+2*(eNB->pucch1ab_stats_cnt[UE_id][subframe])] = (stat_im);
|
||||
eNB->pucch1ab_stats_cnt[UE_id][subframe] = (eNB->pucch1ab_stats_cnt[UE_id][subframe]+1)&1023;
|
||||
|
||||
/* frame not available here - set to -1 for the moment */
|
||||
T(T_ENB_PHY_PUCCH_1AB_IQ, T_INT(phy_vars_eNB->Mod_id), T_INT(UE_id), T_INT(-1), T_INT(subframe), T_INT(stat_re), T_INT(stat_im));
|
||||
|
||||
|
||||
*payload = (stat_re<0) ? 1 : 0;
|
||||
|
||||
@@ -45,6 +45,8 @@
|
||||
//#define DEBUG_ULSCH
|
||||
#include "PHY/sse_intrin.h"
|
||||
|
||||
#include "T.h"
|
||||
|
||||
//extern char* namepointer_chMag ;
|
||||
//eren
|
||||
//extern int **ulchmag_eren;
|
||||
@@ -1615,7 +1617,7 @@ void rx_ulsch(PHY_VARS_eNB *eNB,
|
||||
rx_power_correction = 1;
|
||||
|
||||
if (ulsch[UE_id]->harq_processes[harq_pid]->nb_rb == 0) {
|
||||
LOG_E(PHY,"PUSCH (%d/%x) nb_rb=0!\n", harq_pid,ulsch[UE_id]->rnti,harq_pid);
|
||||
LOG_E(PHY,"PUSCH (%d/%x) nb_rb=0!\n", harq_pid,ulsch[UE_id]->rnti);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1837,8 +1839,14 @@ void rx_ulsch(PHY_VARS_eNB *eNB,
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
llrp = (int16_t*)&pusch_vars->llr[0];
|
||||
|
||||
T(T_ENB_PHY_PUSCH_IQ, T_INT(eNB_id), T_INT(UE_id), T_INT(phy_vars_eNB->proc[sched_subframe].frame_rx),
|
||||
T_INT(subframe), T_INT(ulsch[UE_id]->harq_processes[harq_pid]->nb_rb),
|
||||
T_BUFFER(eNB_pusch_vars->rxdataF_comp[eNB_id][0],
|
||||
2 * /* ulsch[UE_id]->harq_processes[harq_pid]->nb_rb */ frame_parms->N_RB_UL *12*frame_parms->symbols_per_tti*2));
|
||||
|
||||
for (l=0; l<frame_parms->symbols_per_tti-ulsch[UE_id]->harq_processes[harq_pid]->srs_active; l++) {
|
||||
|
||||
if (((frame_parms->Ncp == 0) && ((l==3) || (l==10)))|| // skip pilots
|
||||
|
||||
@@ -57,6 +57,7 @@ void fill_dci(DCI_PDU *DCI_pdu,PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc)
|
||||
|
||||
uint32_t rballoc = 0x7FFF;
|
||||
//uint32_t rballoc2 = 0x000F;
|
||||
|
||||
int subframe = proc->subframe_tx;
|
||||
|
||||
LTE_eNB_DLSCH_t *DLSCH_ptr = eNB->dlsch[0][0];
|
||||
@@ -143,7 +144,7 @@ void fill_dci(DCI_PDU *DCI_pdu,PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc)
|
||||
DCI_pdu->dci_alloc[0].dci_length = sizeof_DCI1A_10MHz_FDD_t;
|
||||
((DCI1A_10MHz_FDD_t*)&bcch_pdu)->type = 1;
|
||||
((DCI1A_10MHz_FDD_t*)&bcch_pdu)->vrb_type = 0;
|
||||
((DCI1A_10MHz_FDD_t*)&bcch_pdu)->rballoc = computeRIV(25,10,3);
|
||||
((DCI1A_10MHz_FDD_t*)&bcch_pdu)->rballoc = computeRIV(50,10,3);
|
||||
((DCI1A_10MHz_FDD_t*)&bcch_pdu)->ndi = proc->frame_tx&1;
|
||||
((DCI1A_10MHz_FDD_t*)&bcch_pdu)->rv = 1;
|
||||
((DCI1A_10MHz_FDD_t*)&bcch_pdu)->mcs = 1;
|
||||
@@ -154,7 +155,7 @@ void fill_dci(DCI_PDU *DCI_pdu,PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc)
|
||||
DCI_pdu->dci_alloc[0].dci_length = sizeof_DCI1A_10MHz_TDD_1_6_t;
|
||||
((DCI1A_10MHz_TDD_1_6_t*)&bcch_pdu)->type = 1;
|
||||
((DCI1A_10MHz_TDD_1_6_t*)&bcch_pdu)->vrb_type = 0;
|
||||
((DCI1A_10MHz_TDD_1_6_t*)&bcch_pdu)->rballoc = computeRIV(25,10,3);
|
||||
((DCI1A_10MHz_TDD_1_6_t*)&bcch_pdu)->rballoc = computeRIV(50,10,3);
|
||||
((DCI1A_10MHz_TDD_1_6_t*)&bcch_pdu)->ndi = proc->frame_tx&1;
|
||||
((DCI1A_10MHz_TDD_1_6_t*)&bcch_pdu)->rv = 1;
|
||||
((DCI1A_10MHz_TDD_1_6_t*)&bcch_pdu)->mcs = 1;
|
||||
@@ -170,7 +171,7 @@ void fill_dci(DCI_PDU *DCI_pdu,PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc)
|
||||
DCI_pdu->dci_alloc[0].dci_length = sizeof_DCI1A_20MHz_FDD_t;
|
||||
((DCI1A_20MHz_FDD_t*)&bcch_pdu)->type = 1;
|
||||
((DCI1A_20MHz_FDD_t*)&bcch_pdu)->vrb_type = 0;
|
||||
((DCI1A_20MHz_FDD_t*)&bcch_pdu)->rballoc = computeRIV(25,10,3);
|
||||
((DCI1A_20MHz_FDD_t*)&bcch_pdu)->rballoc = computeRIV(100,10,3);
|
||||
((DCI1A_20MHz_FDD_t*)&bcch_pdu)->ndi = proc->frame_tx&1;
|
||||
((DCI1A_20MHz_FDD_t*)&bcch_pdu)->rv = 1;
|
||||
((DCI1A_20MHz_FDD_t*)&bcch_pdu)->mcs = 1;
|
||||
@@ -181,7 +182,7 @@ void fill_dci(DCI_PDU *DCI_pdu,PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc)
|
||||
DCI_pdu->dci_alloc[0].dci_length = sizeof_DCI1A_20MHz_TDD_1_6_t;
|
||||
((DCI1A_20MHz_TDD_1_6_t*)&bcch_pdu)->type = 1;
|
||||
((DCI1A_20MHz_TDD_1_6_t*)&bcch_pdu)->vrb_type = 0;
|
||||
((DCI1A_20MHz_TDD_1_6_t*)&bcch_pdu)->rballoc = computeRIV(25,10,3);
|
||||
((DCI1A_20MHz_TDD_1_6_t*)&bcch_pdu)->rballoc = computeRIV(100,10,3);
|
||||
((DCI1A_20MHz_TDD_1_6_t*)&bcch_pdu)->ndi = proc->frame_tx&1;
|
||||
((DCI1A_20MHz_TDD_1_6_t*)&bcch_pdu)->rv = 1;
|
||||
((DCI1A_20MHz_TDD_1_6_t*)&bcch_pdu)->mcs = 1;
|
||||
@@ -231,14 +232,16 @@ void fill_dci(DCI_PDU *DCI_pdu,PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc)
|
||||
if (eNB->frame_parms.frame_type == FDD) {
|
||||
DCI_pdu->dci_alloc[0].dci_length = sizeof_DCI1_5MHz_FDD_t;
|
||||
|
||||
((DCI1_5MHz_FDD_t *)&dlsch_pdu)->rballoc = rballoc;
|
||||
((DCI1_5MHz_FDD_t *)&dlsch_pdu)->rballoc = rballoc; //computeRIV(25,10,3);
|
||||
((DCI1_5MHz_FDD_t *)&dlsch_pdu)->TPC = 0;
|
||||
((DCI1_5MHz_FDD_t *)&dlsch_pdu)->harq_pid = DLSCH_ptr->harq_pid_freelist[DLSCH_ptr->head_freelist];
|
||||
((DCI1_5MHz_FDD_t *)&dlsch_pdu)->mcs = eNB->target_ue_dl_mcs;
|
||||
//((DCI1_5MHz_FDD_t *)&dlsch_pdu)->mcs = (unsigned char) ((eNB->frame%1024)%28);
|
||||
((DCI1_5MHz_FDD_t *)&dlsch_pdu)->ndi = proc->frame_tx&1;
|
||||
((DCI1_5MHz_FDD_t *)&dlsch_pdu)->rv = 0;
|
||||
memcpy((void*)&DCI_pdu->dci_alloc[0].dci_pdu[0],(void *)&dlsch_pdu,sizeof(DCI1_5MHz_TDD_t));
|
||||
((DCI1_5MHz_FDD_t *)&dlsch_pdu)->rah = 0;
|
||||
|
||||
memcpy((void*)&DCI_pdu->dci_alloc[0].dci_pdu[0],(void *)&dlsch_pdu,sizeof(DCI1_5MHz_FDD_t));
|
||||
|
||||
/*
|
||||
//user2
|
||||
@@ -261,7 +264,7 @@ void fill_dci(DCI_PDU *DCI_pdu,PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc)
|
||||
} else {
|
||||
DCI_pdu->dci_alloc[0].dci_length = sizeof_DCI1_5MHz_TDD_t;
|
||||
|
||||
((DCI1_5MHz_TDD_t *)&dlsch_pdu)->rballoc = rballoc;
|
||||
((DCI1_5MHz_TDD_t *)&dlsch_pdu)->rballoc = rballoc; //computeRIV(25,10,3);
|
||||
((DCI1_5MHz_TDD_t *)&dlsch_pdu)->TPC = 0;
|
||||
((DCI1_5MHz_TDD_t *)&dlsch_pdu)->dai = 0;
|
||||
((DCI1_5MHz_TDD_t *)&dlsch_pdu)->harq_pid = DLSCH_ptr->harq_pid_freelist[DLSCH_ptr->head_freelist];
|
||||
@@ -269,6 +272,7 @@ void fill_dci(DCI_PDU *DCI_pdu,PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc)
|
||||
//((DCI1_5MHz_TDD_t *)&dlsch_pdu)->mcs = (unsigned char) ((eNB->frame%1024)%28);
|
||||
((DCI1_5MHz_TDD_t *)&dlsch_pdu)->ndi = proc->frame_tx&1;
|
||||
((DCI1_5MHz_TDD_t *)&dlsch_pdu)->rv = 0;
|
||||
((DCI1_5MHz_TDD_t *)&dlsch_pdu)->rah = 0;
|
||||
memcpy((void*)&DCI_pdu->dci_alloc[0].dci_pdu[0],(void *)&dlsch_pdu,sizeof(DCI1_5MHz_TDD_t));
|
||||
|
||||
/*
|
||||
@@ -287,6 +291,7 @@ void fill_dci(DCI_PDU *DCI_pdu,PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc)
|
||||
((DCI1_5MHz_FDD_t *)&dlsch_pdu)->mcs = eNB->target_ue_dl_mcs;
|
||||
((DCI1_5MHz_FDD_t *)&dlsch_pdu)->ndi = 1;
|
||||
((DCI1_5MHz_FDD_t *)&dlsch_pdu)->rv = 0;
|
||||
((DCI1_5MHz_FDD_t *)&dlsch_pdu)->rah = 0;
|
||||
memcpy((void*)&DCI_pdu->dci_alloc[1].dci_pdu[0],(void *)&((DCI1_5MHz_FDD_t *)&dlsch_pdu)->,sizeof(DCI1_5MHz_TDD_t));
|
||||
*/
|
||||
}
|
||||
@@ -298,14 +303,16 @@ void fill_dci(DCI_PDU *DCI_pdu,PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc)
|
||||
if (eNB->frame_parms.frame_type == FDD) {
|
||||
DCI_pdu->dci_alloc[0].dci_length = sizeof_DCI1_10MHz_FDD_t;
|
||||
|
||||
((DCI1_10MHz_FDD_t *)&dlsch_pdu)->rballoc = rballoc;
|
||||
((DCI1_10MHz_FDD_t *)&dlsch_pdu)->rballoc = rballoc; //computeRIV(50,10,3);
|
||||
((DCI1_10MHz_FDD_t *)&dlsch_pdu)->TPC = 0;
|
||||
((DCI1_10MHz_FDD_t *)&dlsch_pdu)->harq_pid = DLSCH_ptr->harq_pid_freelist[DLSCH_ptr->head_freelist];
|
||||
((DCI1_10MHz_FDD_t *)&dlsch_pdu)->mcs = eNB->target_ue_dl_mcs;
|
||||
//((DCI1_10MHz_FDD_t *)&dlsch_pdu)->mcs = (unsigned char) ((eNB->frame%1024)%28);
|
||||
((DCI1_10MHz_FDD_t *)&dlsch_pdu)->ndi = proc->frame_tx&1;
|
||||
((DCI1_10MHz_FDD_t *)&dlsch_pdu)->rv = 0;
|
||||
memcpy((void*)&DCI_pdu->dci_alloc[0].dci_pdu[0],(void *)&dlsch_pdu,sizeof(DCI1_10MHz_TDD_t));
|
||||
((DCI1_10MHz_FDD_t *)&dlsch_pdu)->rah = 0;
|
||||
|
||||
memcpy((void*)&DCI_pdu->dci_alloc[0].dci_pdu[0],(void *)&dlsch_pdu,sizeof(DCI1_10MHz_FDD_t));
|
||||
|
||||
/*
|
||||
//user2
|
||||
@@ -323,12 +330,13 @@ void fill_dci(DCI_PDU *DCI_pdu,PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc)
|
||||
((DCI1_10MHz_FDD_t *)&dlsch_pdu)->mcs = eNB->target_ue_dl_mcs;
|
||||
((DCI1_10MHz_FDD_t *)&dlsch_pdu)->ndi = 1;
|
||||
((DCI1_10MHz_FDD_t *)&dlsch_pdu)->rv = 0;
|
||||
((DCI1_10MHz_FDD_t *)&dlsch_pdu)->rah = 0;
|
||||
memcpy((void*)&DCI_pdu->dci_alloc[1].dci_pdu[0],(void *)&((DCI1_10MHz_FDD_t *)&dlsch_pdu)->,sizeof(DCI1_10MHz_TDD_t));
|
||||
*/
|
||||
} else {
|
||||
DCI_pdu->dci_alloc[0].dci_length = sizeof_DCI1_10MHz_TDD_t;
|
||||
|
||||
((DCI1_10MHz_TDD_t *)&dlsch_pdu)->rballoc = rballoc;
|
||||
((DCI1_10MHz_TDD_t *)&dlsch_pdu)->rballoc = rballoc; //computeRIV(50,10,3);
|
||||
((DCI1_10MHz_TDD_t *)&dlsch_pdu)->TPC = 0;
|
||||
((DCI1_10MHz_TDD_t *)&dlsch_pdu)->dai = 0;
|
||||
((DCI1_10MHz_TDD_t *)&dlsch_pdu)->harq_pid = DLSCH_ptr->harq_pid_freelist[DLSCH_ptr->head_freelist];
|
||||
@@ -336,6 +344,7 @@ void fill_dci(DCI_PDU *DCI_pdu,PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc)
|
||||
//((DCI1_10MHz_TDD_t *)&dlsch_pdu)->mcs = (unsigned char) ((eNB->frame%1024)%28);
|
||||
((DCI1_10MHz_TDD_t *)&dlsch_pdu)->ndi = proc->frame_tx&1;
|
||||
((DCI1_10MHz_TDD_t *)&dlsch_pdu)->rv = 0;
|
||||
((DCI1_10MHz_TDD_t *)&dlsch_pdu)->rah = 0;
|
||||
memcpy((void*)&DCI_pdu->dci_alloc[0].dci_pdu[0],(void *)&dlsch_pdu,sizeof(DCI1_10MHz_TDD_t));
|
||||
|
||||
/*
|
||||
@@ -354,6 +363,7 @@ void fill_dci(DCI_PDU *DCI_pdu,PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc)
|
||||
((DCI1_10MHz_FDD_t *)&dlsch_pdu)->mcs = eNB->target_ue_dl_mcs;
|
||||
((DCI1_10MHz_FDD_t *)&dlsch_pdu)->ndi = 1;
|
||||
((DCI1_10MHz_FDD_t *)&dlsch_pdu)->rv = 0;
|
||||
((DCI1_10MHz_FDD_t *)&dlsch_pdu)->rah = 0;
|
||||
memcpy((void*)&DCI_pdu->dci_alloc[1].dci_pdu[0],(void *)&((DCI1_10MHz_FDD_t *)&dlsch_pdu)->,sizeof(DCI1_10MHz_TDD_t));
|
||||
*/
|
||||
}
|
||||
@@ -366,13 +376,12 @@ void fill_dci(DCI_PDU *DCI_pdu,PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc)
|
||||
|
||||
((DCI1_5MHz_FDD_t *)&dlsch_pdu)->rballoc = rballoc;
|
||||
((DCI1_5MHz_FDD_t *)&dlsch_pdu)->TPC = 0;
|
||||
((DCI1_5MHz_FDD_t *)&dlsch_pdu)->harq_pid = DLSCH_ptr->harq_pid_freelist[DLSCH_ptr->head_freelist];
|
||||
((DCI1_5MHz_FDD_t *)&dlsch_pdu)->harq_pid = DLSCH_ptr->harq_pid_freelist[DLSCH_ptr->head_freelist];
|
||||
((DCI1_5MHz_FDD_t *)&dlsch_pdu)->mcs = eNB->target_ue_dl_mcs;
|
||||
//((DCI1_5MHz_FDD_t *)&dlsch_pdu)->mcs = (unsigned char) ((eNB->frame%1024)%28);
|
||||
((DCI1_5MHz_FDD_t *)&dlsch_pdu)->ndi = proc->frame_tx&1;
|
||||
((DCI1_5MHz_FDD_t *)&dlsch_pdu)->rv = 0;
|
||||
memcpy((void*)&DCI_pdu->dci_alloc[0].dci_pdu[0],(void *)&dlsch_pdu,sizeof(DCI1_5MHz_TDD_t));
|
||||
|
||||
/*
|
||||
//user2
|
||||
DCI_pdu->dci_alloc[1].dci_length = sizeof_DCI1_5MHz_TDD_t;
|
||||
@@ -389,12 +398,13 @@ void fill_dci(DCI_PDU *DCI_pdu,PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc)
|
||||
((DCI1_5MHz_FDD_t *)&dlsch_pdu)->mcs = eNB->target_ue_dl_mcs;
|
||||
((DCI1_5MHz_FDD_t *)&dlsch_pdu)->ndi = 1;
|
||||
((DCI1_5MHz_FDD_t *)&dlsch_pdu)->rv = 0;
|
||||
((DCI1_5MHz_FDD_t *)&dlsch_pdu)->rah = 0;
|
||||
memcpy((void*)&DCI_pdu->dci_alloc[1].dci_pdu[0],(void *)&((DCI1_5MHz_FDD_t *)&dlsch_pdu)->,sizeof(DCI1_5MHz_TDD_t));
|
||||
*/
|
||||
} else {
|
||||
DCI_pdu->dci_alloc[0].dci_length = sizeof_DCI1_20MHz_TDD_t;
|
||||
|
||||
((DCI1_20MHz_TDD_t *)&dlsch_pdu)->rballoc = rballoc;
|
||||
((DCI1_20MHz_TDD_t *)&dlsch_pdu)->rballoc = rballoc; //computeRIV(100,10,3);
|
||||
((DCI1_20MHz_TDD_t *)&dlsch_pdu)->TPC = 0;
|
||||
((DCI1_20MHz_TDD_t *)&dlsch_pdu)->dai = 0;
|
||||
((DCI1_20MHz_TDD_t *)&dlsch_pdu)->harq_pid = DLSCH_ptr->harq_pid_freelist[DLSCH_ptr->head_freelist];
|
||||
@@ -402,6 +412,7 @@ void fill_dci(DCI_PDU *DCI_pdu,PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc)
|
||||
//((DCI1_20MHz_TDD_t *)&dlsch_pdu)->mcs = (unsigned char) ((eNB->frame%1024)%28);
|
||||
((DCI1_20MHz_TDD_t *)&dlsch_pdu)->ndi = proc->frame_tx&1;
|
||||
((DCI1_20MHz_TDD_t *)&dlsch_pdu)->rv = 0;
|
||||
((DCI1_20MHz_TDD_t *)&dlsch_pdu)->rah = 0;
|
||||
memcpy((void*)&DCI_pdu->dci_alloc[0].dci_pdu[0],(void *)&dlsch_pdu,sizeof(DCI1_20MHz_TDD_t));
|
||||
|
||||
/*
|
||||
@@ -420,6 +431,7 @@ void fill_dci(DCI_PDU *DCI_pdu,PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc)
|
||||
((DCI1_20MHz_FDD_t *)&dlsch_pdu)->mcs = eNB->target_ue_dl_mcs;
|
||||
((DCI1_20MHz_FDD_t *)&dlsch_pdu)->ndi = 1;
|
||||
((DCI1_20MHz_FDD_t *)&dlsch_pdu)->rv = 0;
|
||||
((DCI1_20MHz_FDD_t *)&dlsch_pdu)->rah = 0;
|
||||
memcpy((void*)&DCI_pdu->dci_alloc[1].dci_pdu[0],(void *)&((DCI1_20MHz_FDD_t *)&dlsch_pdu)->,sizeof(DCI1_5MHz_TDD_t));
|
||||
*/
|
||||
}
|
||||
|
||||
@@ -58,6 +58,8 @@
|
||||
#include "UTIL/LOG/log.h"
|
||||
#include "UTIL/LOG/vcd_signal_dumper.h"
|
||||
|
||||
#include "T.h"
|
||||
|
||||
#include "assertions.h"
|
||||
#include "msc.h"
|
||||
|
||||
@@ -436,14 +438,18 @@ int QPSK2[4]= {AMP_OVER_2|(AMP_OVER_2<<16),AMP_OVER_2|((65536-AMP_OVER_2)<<16),(
|
||||
|
||||
|
||||
unsigned int taus(void);
|
||||
DCI_PDU DCI_pdu_tmp;
|
||||
|
||||
|
||||
void pmch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,PHY_VARS_RN *rn, int abstraction_flag,relaying_type_t r_type) {
|
||||
|
||||
|
||||
#ifdef Rel10
|
||||
MCH_PDU *mch_pduP;
|
||||
MCH_PDU mch_pdu;
|
||||
// uint8_t sync_area=255;
|
||||
#endif
|
||||
|
||||
int subframe = proc->subframe_tx;
|
||||
|
||||
if (abstraction_flag==0) {
|
||||
@@ -1035,10 +1041,21 @@ void pdsch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,LTE_eNB_DLSCH_t *d
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#ifdef DEBUG_PHY_PROC
|
||||
#ifdef DEBUG_DLSCH
|
||||
LOG_T(PHY,"eNB DLSCH SDU: \n");
|
||||
|
||||
T(T_ENB_PHY_DLSCH_UE_DCI, T_INT(phy_vars_eNB->Mod_id), T_INT(frame), T_INT(subframe), T_INT(UE_id),
|
||||
T_INT(DCI_pdu->dci_alloc[i].rnti), T_INT(DCI_pdu->dci_alloc[i].format),
|
||||
T_INT(phy_vars_eNB->dlsch_eNB[(int)UE_id][0]->current_harq_pid));
|
||||
|
||||
phy_vars_eNB->dlsch_eNB[(uint8_t)UE_id][0]->nCCE[subframe] = DCI_pdu->dci_alloc[i].firstCCE;
|
||||
|
||||
LOG_D(PHY,"[eNB %"PRIu8"] Frame %d subframe %d : CCE resource for ue DCI (PDSCH %"PRIx16") => %"PRIu8"/%u\n",phy_vars_eNB->Mod_id,phy_vars_eNB->proc[sched_subframe].frame_tx,subframe,
|
||||
DCI_pdu->dci_alloc[i].rnti,phy_vars_eNB->dlsch_eNB[(uint8_t)UE_id][0]->nCCE[subframe],DCI_pdu->dci_alloc[i].firstCCE);
|
||||
|
||||
|
||||
for (i=0; i<dlsch_harq->TBS>>3; i++)
|
||||
LOG_T(PHY,"%"PRIx8".",DLSCH_pdu[i]);
|
||||
|
||||
@@ -1096,6 +1113,7 @@ void pdsch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,LTE_eNB_DLSCH_t *d
|
||||
stop_meas(&eNB->dlsch_modulation_stats);
|
||||
}
|
||||
|
||||
|
||||
#ifdef PHY_ABSTRACTION
|
||||
else {
|
||||
start_meas(&eNB->dlsch_encoding_stats);
|
||||
@@ -1657,6 +1675,9 @@ void process_HARQ_feedback(uint8_t UE_id,
|
||||
dlsch->rnti,dl_harq_pid[m],M,m,mp,dlsch_harq_proc->round);
|
||||
#endif
|
||||
|
||||
T(T_ENB_PHY_DLSCH_UE_NACK, T_INT(phy_vars_eNB->Mod_id), T_INT(frame), T_INT(subframe), T_INT(UE_id), T_INT(dlsch->rnti),
|
||||
T_INT(dl_harq_pid[m]));
|
||||
|
||||
if (dlsch_harq_proc->round == 0)
|
||||
ue_stats->dlsch_NAK_round0++;
|
||||
|
||||
@@ -1690,6 +1711,10 @@ void process_HARQ_feedback(uint8_t UE_id,
|
||||
LOG_D(PHY,"[eNB %d][PDSCH %x/%d] ACK Received in round %d, resetting process\n",eNB->Mod_id,
|
||||
dlsch->rnti,dl_harq_pid[m],dlsch_harq_proc->round);
|
||||
#endif
|
||||
|
||||
T(T_ENB_PHY_DLSCH_UE_ACK, T_INT(phy_vars_eNB->Mod_id), T_INT(frame), T_INT(subframe), T_INT(UE_id), T_INT(dlsch->rnti),
|
||||
T_INT(dl_harq_pid[m]));
|
||||
|
||||
ue_stats->dlsch_ACK[dl_harq_pid[m]][dlsch_harq_proc->round]++;
|
||||
|
||||
// Received ACK so set round to 0 and set dlsch_harq_pid IDLE
|
||||
@@ -2025,6 +2050,7 @@ void pucch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq
|
||||
|
||||
// Now ACK/NAK
|
||||
// First check subframe_tx flag for earlier subframes
|
||||
|
||||
get_n1_pucch_eNB(eNB,
|
||||
proc,
|
||||
UE_id,
|
||||
@@ -2073,6 +2099,7 @@ void pucch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq
|
||||
if (do_SR == 1) {
|
||||
eNB->UE_stats[UE_id].sr_total++;
|
||||
|
||||
|
||||
if (abstraction_flag == 0)
|
||||
metric0_SR = rx_pucch(eNB,
|
||||
pucch_format1,
|
||||
@@ -2081,6 +2108,7 @@ void pucch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq
|
||||
0, // n2_pucch
|
||||
0, // shortened format, should be use_srs flag, later
|
||||
&SR_payload,
|
||||
frame,
|
||||
subframe,
|
||||
PUCCH1_THRES);
|
||||
|
||||
@@ -2096,6 +2124,7 @@ void pucch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
if (SR_payload == 1) {
|
||||
LOG_D(PHY,"[eNB %d][SR %x] Frame %d subframe %d Got SR for PUSCH, transmitting to MAC\n",eNB->Mod_id,
|
||||
@@ -2141,6 +2170,7 @@ void pucch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq
|
||||
0, //n2_pucch
|
||||
0, // shortened format
|
||||
pucch_payload0,
|
||||
frame,
|
||||
subframe,
|
||||
PUCCH1a_THRES);
|
||||
|
||||
@@ -2152,6 +2182,7 @@ void pucch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq
|
||||
0, //n2_pucch
|
||||
0, // shortened format
|
||||
pucch_payload0,
|
||||
frame,
|
||||
subframe,
|
||||
PUCCH1a_THRES);
|
||||
}
|
||||
@@ -2211,6 +2242,7 @@ void pucch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq
|
||||
0, //n2_pucch
|
||||
0, // shortened format
|
||||
pucch_payload0,
|
||||
frame,
|
||||
subframe,
|
||||
PUCCH1a_THRES);
|
||||
else {
|
||||
@@ -2242,6 +2274,7 @@ void pucch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq
|
||||
0, // n2_pucch
|
||||
0, // shortened format
|
||||
pucch_payload0,
|
||||
frame,
|
||||
subframe,
|
||||
PUCCH1a_THRES);
|
||||
else {
|
||||
@@ -2265,6 +2298,7 @@ void pucch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq
|
||||
0, //n2_pucch
|
||||
0, // shortened format
|
||||
pucch_payload1,
|
||||
frame,
|
||||
subframe,
|
||||
PUCCH1a_THRES);
|
||||
else {
|
||||
@@ -2697,6 +2731,11 @@ void phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,const
|
||||
LOG_D(PHY,"[eNB %d] Frame %d: Doing phy_procedures_eNB_RX(%d)\n",eNB->Mod_id,frame, subframe);
|
||||
#endif
|
||||
|
||||
T(T_ENB_PHY_UL_TICK, T_INT(phy_vars_eNB->Mod_id), T_INT(frame), T_INT(subframe));
|
||||
|
||||
T(T_ENB_PHY_INPUT_SIGNAL, T_INT(phy_vars_eNB->Mod_id), T_INT(frame), T_INT(subframe), T_INT(0),
|
||||
T_BUFFER(&phy_vars_eNB->lte_eNB_common_vars.rxdata[0][0][subframe*phy_vars_eNB->lte_frame_parms.samples_per_tti],
|
||||
phy_vars_eNB->lte_frame_parms.samples_per_tti * 4));
|
||||
|
||||
eNB->rb_mask_ul[0]=0;
|
||||
eNB->rb_mask_ul[1]=0;
|
||||
@@ -2885,6 +2924,8 @@ void phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,const
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_ULSCH_MSG3,0);
|
||||
|
||||
if (ret == (1+MAX_TURBO_ITERATIONS)) {
|
||||
T(T_ENB_PHY_ULSCH_UE_NACK, T_INT(phy_vars_eNB->Mod_id), T_INT(frame), T_INT(subframe), T_INT(i), T_INT(phy_vars_eNB->ulsch_eNB[i]->rnti),
|
||||
T_INT(harq_pid));
|
||||
|
||||
eNB->UE_stats[i].ulsch_round_errors[harq_pid][eNB->ulsch[i]->harq_processes[harq_pid]->round]++;
|
||||
eNB->ulsch[i]->harq_processes[harq_pid]->phich_active = 1;
|
||||
@@ -2988,6 +3029,12 @@ void phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,const
|
||||
}
|
||||
} // ulsch in error
|
||||
else {
|
||||
|
||||
|
||||
|
||||
T(T_ENB_PHY_ULSCH_UE_ACK, T_INT(phy_vars_eNB->Mod_id), T_INT(frame), T_INT(subframe), T_INT(i), T_INT(phy_vars_eNB->ulsch_eNB[i]->rnti),
|
||||
T_INT(harq_pid));
|
||||
|
||||
if (eNB->ulsch[i]->Msg3_flag == 1) {
|
||||
LOG_D(PHY,"[eNB %d][PUSCH %d] Frame %d subframe %d ULSCH received, setting round to 0, PHICH ACK\n",
|
||||
eNB->Mod_id,harq_pid,
|
||||
|
||||
@@ -557,6 +557,7 @@ int main(int argc, char **argv)
|
||||
n2_pucch,
|
||||
0, //shortened_format,
|
||||
&pucch_payload_rx, //payload,
|
||||
0 /* frame not defined, let's pass 0 */,
|
||||
subframe,
|
||||
pucch1_thres);
|
||||
|
||||
|
||||
@@ -65,6 +65,8 @@
|
||||
# include "intertask_interface.h"
|
||||
#endif
|
||||
|
||||
#include "T.h"
|
||||
|
||||
#define ENABLE_MAC_PAYLOAD_DEBUG
|
||||
//#define DEBUG_eNB_SCHEDULER 1
|
||||
|
||||
@@ -825,6 +827,9 @@ schedule_ue_spec(
|
||||
DCCH,
|
||||
(char *)&dlsch_buffer[sdu_lengths[0]]);
|
||||
|
||||
T(T_ENB_MAC_UE_DL_SDU, T_INT(module_idP), T_INT(CC_id), T_INT(rnti), T_INT(frameP), T_INT(subframeP),
|
||||
T_INT(harq_pid), T_INT(DCCH), T_INT(sdu_lengths[0]));
|
||||
|
||||
LOG_D(MAC,"[eNB %d][DCCH] CC_id %d Got %d bytes from RLC\n",module_idP,CC_id,sdu_lengths[0]);
|
||||
sdu_length_total = sdu_lengths[0];
|
||||
sdu_lcids[0] = DCCH;
|
||||
@@ -872,6 +877,9 @@ schedule_ue_spec(
|
||||
DCCH+1,
|
||||
(char *)&dlsch_buffer[sdu_lengths[0]]);
|
||||
|
||||
T(T_ENB_MAC_UE_DL_SDU, T_INT(module_idP), T_INT(CC_id), T_INT(rnti), T_INT(frameP), T_INT(subframeP),
|
||||
T_INT(harq_pid), T_INT(DCCH+1), T_INT(sdu_lengths[num_sdus]));
|
||||
|
||||
sdu_lcids[num_sdus] = DCCH1;
|
||||
sdu_length_total += sdu_lengths[num_sdus];
|
||||
header_len_dcch += 2;
|
||||
@@ -916,6 +924,9 @@ schedule_ue_spec(
|
||||
DTCH,
|
||||
(char*)&dlsch_buffer[sdu_length_total]);
|
||||
|
||||
T(T_ENB_MAC_UE_DL_SDU, T_INT(module_idP), T_INT(CC_id), T_INT(rnti), T_INT(frameP), T_INT(subframeP),
|
||||
T_INT(harq_pid), T_INT(DTCH), T_INT(sdu_lengths[num_sdus]));
|
||||
|
||||
LOG_D(MAC,"[eNB %d][USER-PLANE DEFAULT DRB] CC_id %d Got %d bytes for DTCH %d \n",
|
||||
module_idP,CC_id,sdu_lengths[num_sdus],DTCH);
|
||||
sdu_lcids[num_sdus] = DTCH;
|
||||
|
||||
@@ -996,79 +996,71 @@ int allocate_CCEs(int module_idP,
|
||||
int nCCE_max = mac_xface->get_nCCE_max(module_idP,CC_idP,1,subframeP);
|
||||
int fCCE;
|
||||
int i,j;
|
||||
int allocation_is_feasible = 1;
|
||||
DCI_ALLOC_t *dci_alloc;
|
||||
int nCCE=0;
|
||||
|
||||
LOG_D(MAC,"Allocate CCEs subframe %d, test %d : (common %d,uspec %d)\n",subframeP,test_onlyP,DCI_pdu->Num_common_dci,DCI_pdu->Num_ue_spec_dci);
|
||||
DCI_pdu->num_pdcch_symbols=1;
|
||||
|
||||
while (allocation_is_feasible == 1) {
|
||||
init_CCE_table(module_idP,CC_idP);
|
||||
nCCE=0;
|
||||
try_again:
|
||||
init_CCE_table(module_idP,CC_idP);
|
||||
nCCE=0;
|
||||
|
||||
for (i=0;i<DCI_pdu->Num_common_dci + DCI_pdu->Num_ue_spec_dci;i++) {
|
||||
dci_alloc = &DCI_pdu->dci_alloc[i];
|
||||
LOG_D(MAC,"Trying to allocate DCI %d/%d (%d,%d) : rnti %x, aggreg %d nCCE %d / %d (num_pdcch_symbols %d)\n",
|
||||
i,DCI_pdu->Num_common_dci+DCI_pdu->Num_ue_spec_dci,
|
||||
DCI_pdu->Num_common_dci,DCI_pdu->Num_ue_spec_dci,
|
||||
dci_alloc->rnti,1<<dci_alloc->L,
|
||||
nCCE,nCCE_max,DCI_pdu->num_pdcch_symbols);
|
||||
for (i=0;i<DCI_pdu->Num_common_dci + DCI_pdu->Num_ue_spec_dci;i++) {
|
||||
dci_alloc = &DCI_pdu->dci_alloc[i];
|
||||
LOG_D(MAC,"Trying to allocate DCI %d/%d (%d,%d) : rnti %x, aggreg %d nCCE %d / %d (num_pdcch_symbols %d)\n",
|
||||
i,DCI_pdu->Num_common_dci+DCI_pdu->Num_ue_spec_dci,
|
||||
DCI_pdu->Num_common_dci,DCI_pdu->Num_ue_spec_dci,
|
||||
dci_alloc->rnti,1<<dci_alloc->L,
|
||||
nCCE,nCCE_max,DCI_pdu->num_pdcch_symbols);
|
||||
|
||||
if (nCCE + (1<<dci_alloc->L) > nCCE_max) {
|
||||
if (DCI_pdu->num_pdcch_symbols == 3)
|
||||
allocation_is_feasible = 0;
|
||||
else {
|
||||
DCI_pdu->num_pdcch_symbols++;
|
||||
nCCE_max = mac_xface->get_nCCE_max(module_idP,CC_idP,DCI_pdu->num_pdcch_symbols,subframeP);
|
||||
}
|
||||
break;
|
||||
if (nCCE + (1<<dci_alloc->L) > nCCE_max) {
|
||||
if (DCI_pdu->num_pdcch_symbols == 3)
|
||||
goto failed;
|
||||
DCI_pdu->num_pdcch_symbols++;
|
||||
nCCE_max = mac_xface->get_nCCE_max(module_idP,CC_idP,DCI_pdu->num_pdcch_symbols,subframeP);
|
||||
goto try_again;
|
||||
}
|
||||
|
||||
// number of CCEs left can potentially hold this allocation
|
||||
fCCE = get_nCCE_offset(CCE_table,
|
||||
1<<(dci_alloc->L),
|
||||
nCCE_max,
|
||||
(i<DCI_pdu->Num_common_dci) ? 1 : 0,
|
||||
dci_alloc->rnti,
|
||||
subframeP);
|
||||
if (fCCE == -1) {
|
||||
if (DCI_pdu->num_pdcch_symbols == 3) {
|
||||
LOG_I(MAC,"subframe %d: Dropping Allocation for RNTI %x\n",
|
||||
subframeP,dci_alloc->rnti);
|
||||
for (j=0;j<=i;j++){
|
||||
LOG_I(MAC,"DCI %d/%d (%d,%d) : rnti %x dci format %d, aggreg %d nCCE %d / %d (num_pdcch_symbols %d)\n",
|
||||
i,DCI_pdu->Num_common_dci+DCI_pdu->Num_ue_spec_dci,
|
||||
DCI_pdu->Num_common_dci,DCI_pdu->Num_ue_spec_dci,
|
||||
DCI_pdu->dci_alloc[j].rnti,DCI_pdu->dci_alloc[j].format,
|
||||
1<<DCI_pdu->dci_alloc[j].L,
|
||||
nCCE,nCCE_max,DCI_pdu->num_pdcch_symbols);
|
||||
}
|
||||
goto failed;
|
||||
}
|
||||
else { // number of CCEs left can potentially hold this allocation
|
||||
if ((fCCE = get_nCCE_offset(CCE_table,
|
||||
1<<(dci_alloc->L),
|
||||
nCCE_max,
|
||||
(i<DCI_pdu->Num_common_dci) ? 1 : 0,
|
||||
dci_alloc->rnti,
|
||||
subframeP))>=0) {// the allocation is feasible, rnti rule passes
|
||||
DCI_pdu->num_pdcch_symbols++;
|
||||
nCCE_max = mac_xface->get_nCCE_max(module_idP,CC_idP,DCI_pdu->num_pdcch_symbols,subframeP);
|
||||
goto try_again;
|
||||
} // fCCE==-1
|
||||
|
||||
LOG_D(MAC,"Allocating at nCCE %d\n",fCCE);
|
||||
if (test_onlyP == 0) {
|
||||
nCCE += (1<<dci_alloc->L);
|
||||
dci_alloc->firstCCE=fCCE;
|
||||
LOG_D(MAC,"Allocate CCEs subframe %d, test %d\n",subframeP,test_onlyP);
|
||||
}
|
||||
} // fCCE>=0
|
||||
else {
|
||||
if (DCI_pdu->num_pdcch_symbols == 3) {
|
||||
allocation_is_feasible = 0;
|
||||
LOG_I(MAC,"subframe %d: Dropping Allocation for RNTI %x\n",
|
||||
subframeP,dci_alloc->rnti);
|
||||
for (j=0;j<=i;j++){
|
||||
|
||||
LOG_I(MAC,"DCI %d/%d (%d,%d) : rnti %x dci format %d, aggreg %d nCCE %d / %d (num_pdcch_symbols %d)\n",
|
||||
i,DCI_pdu->Num_common_dci+DCI_pdu->Num_ue_spec_dci,
|
||||
DCI_pdu->Num_common_dci,DCI_pdu->Num_ue_spec_dci,
|
||||
DCI_pdu->dci_alloc[j].rnti,DCI_pdu->dci_alloc[j].format,
|
||||
1<<DCI_pdu->dci_alloc[j].L,
|
||||
nCCE,nCCE_max,DCI_pdu->num_pdcch_symbols);
|
||||
}
|
||||
}
|
||||
else {
|
||||
DCI_pdu->num_pdcch_symbols++;
|
||||
nCCE_max = mac_xface->get_nCCE_max(module_idP,CC_idP,DCI_pdu->num_pdcch_symbols,subframeP);
|
||||
}
|
||||
break;
|
||||
} // fCCE==-1
|
||||
} // nCCE <= nCCE_max
|
||||
} // for i = 0 ... num_dcis
|
||||
if (allocation_is_feasible==1)
|
||||
return (0);
|
||||
} // allocation_is_feasible == 1
|
||||
// the allocation is feasible, rnti rule passes
|
||||
nCCE += (1<<dci_alloc->L);
|
||||
LOG_D(MAC,"Allocating at nCCE %d\n",fCCE);
|
||||
if (test_onlyP == 0) {
|
||||
dci_alloc->firstCCE=fCCE;
|
||||
LOG_D(MAC,"Allocate CCEs subframe %d, test %d\n",subframeP,test_onlyP);
|
||||
}
|
||||
} // for i = 0 ... num_dcis
|
||||
|
||||
return(-1);
|
||||
|
||||
return 0;
|
||||
|
||||
failed:
|
||||
return -1;
|
||||
}
|
||||
|
||||
boolean_t CCE_allocation_infeasible(int module_idP,
|
||||
|
||||
@@ -63,6 +63,8 @@
|
||||
# include "intertask_interface.h"
|
||||
#endif
|
||||
|
||||
#include "T.h"
|
||||
|
||||
#define ENABLE_MAC_PAYLOAD_DEBUG
|
||||
#define DEBUG_eNB_SCHEDULER 1
|
||||
|
||||
@@ -126,7 +128,8 @@ void rx_sdu(
|
||||
|
||||
payload_ptr = parse_ulsch_header(sduP,&num_ce,&num_sdu,rx_ces,rx_lcids,rx_lengths,sdu_lenP);
|
||||
|
||||
|
||||
T(T_ENB_MAC_UE_UL_PDU, T_INT(enb_mod_idP), T_INT(CC_idP), T_INT(rntiP), T_INT(frameP), T_INT(subframeP),
|
||||
T_INT(harq_pidP), T_INT(sdu_lenP), T_INT(num_ce), T_INT(num_sdu));
|
||||
|
||||
eNB->eNB_stats[CC_idP].ulsch_bytes_rx=sdu_lenP;
|
||||
eNB->eNB_stats[CC_idP].total_ulsch_bytes_rx+=sdu_lenP;
|
||||
@@ -134,6 +137,9 @@ void rx_sdu(
|
||||
// control element
|
||||
for (i=0; i<num_ce; i++) {
|
||||
|
||||
T(T_ENB_MAC_UE_UL_CE, T_INT(enb_mod_idP), T_INT(CC_idP), T_INT(rntiP), T_INT(frameP), T_INT(subframeP),
|
||||
T_INT(rx_ces[i]));
|
||||
|
||||
switch (rx_ces[i]) { // implement and process BSR + CRNTI +
|
||||
case POWER_HEADROOM:
|
||||
if (UE_id != -1) {
|
||||
@@ -305,6 +311,9 @@ void rx_sdu(
|
||||
for (i=0; i<num_sdu; i++) {
|
||||
LOG_D(MAC,"SDU Number %d MAC Subheader SDU_LCID %d, length %d\n",i,rx_lcids[i],rx_lengths[i]);
|
||||
|
||||
T(T_ENB_MAC_UE_UL_SDU, T_INT(enb_mod_idP), T_INT(CC_idP), T_INT(rntiP), T_INT(frameP), T_INT(subframeP),
|
||||
T_INT(rx_lcids[i]), T_INT(rx_lengths[i]));
|
||||
|
||||
switch (rx_lcids[i]) {
|
||||
case CCCH :
|
||||
if (rx_lengths[i] > CCCH_PAYLOAD_SIZE_MAX) {
|
||||
@@ -853,6 +862,11 @@ void schedule_ulsch_rnti(module_id_t module_idP,
|
||||
rballoc = mac_xface->computeRIV(frame_parms->N_RB_UL,
|
||||
first_rb[CC_id],
|
||||
rb_table[rb_table_index]);
|
||||
|
||||
T(T_ENB_MAC_UE_UL_SCHEDULE, T_INT(module_idP), T_INT(CC_id), T_INT(rnti), T_INT(frameP),
|
||||
T_INT(subframeP), T_INT(harq_pid), T_INT(mcs), T_INT(first_rb[CC_id]), T_INT(rb_table[rb_table_index]),
|
||||
T_INT(TBS));
|
||||
|
||||
// bad indices : 20 (40 PRB), 21 (45 PRB), 22 (48 PRB)
|
||||
// increment for next UE allocation
|
||||
first_rb[CC_id]+=rb_table[rb_table_index];
|
||||
@@ -867,7 +881,7 @@ void schedule_ulsch_rnti(module_id_t module_idP,
|
||||
module_idP,harq_pid,rnti,CC_id,frameP,subframeP,UE_id,mcs,
|
||||
first_rb[CC_id],rb_table[rb_table_index],
|
||||
rb_table_index,TBS,harq_pid);
|
||||
|
||||
|
||||
// adjust total UL buffer status by TBS, wait for UL sdus to do final update
|
||||
LOG_D(MAC,"[eNB %d] CC_id %d UE %d/%x : adjusting ul_total_buffer, old %d, TBS %d\n", module_idP,CC_id,UE_id,rnti,UE_template->ul_total_buffer,TBS);
|
||||
if (UE_template->ul_total_buffer > TBS)
|
||||
@@ -1091,6 +1105,10 @@ void schedule_ulsch_rnti(module_id_t module_idP,
|
||||
|
||||
}
|
||||
else {
|
||||
T(T_ENB_MAC_UE_UL_SCHEDULE_RETRANSMISSION, T_INT(module_idP), T_INT(CC_id), T_INT(rnti), T_INT(frameP),
|
||||
T_INT(subframeP), T_INT(harq_pid), T_INT(mcs), T_INT(first_rb[CC_id]), T_INT(rb_table[rb_table_index]),
|
||||
T_INT(round));
|
||||
|
||||
LOG_D(MAC,"[eNB %d][PUSCH %d/%x] CC_id %d Frame %d subframeP %d Scheduled (PHICH) UE %d (mcs %d, first rb %d, nb_rb %d, rb_table_index %d, TBS %d, harq_pid %d,round %d)\n",
|
||||
module_idP,harq_pid,rnti,CC_id,frameP,subframeP,UE_id,mcs,
|
||||
first_rb[CC_id],rb_table[rb_table_index],
|
||||
|
||||
@@ -111,6 +111,11 @@ boolean_t pdcp_data_req(
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_REQ,VCD_FUNCTION_IN);
|
||||
CHECK_CTXT_ARGS(ctxt_pP);
|
||||
|
||||
#if T_TRACER
|
||||
if (ctxt_pP->enb_flag != ENB_FLAG_NO)
|
||||
T(T_ENB_PDCP_DL, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->rnti), T_INT(rb_idP), T_INT(sdu_buffer_sizeP));
|
||||
#endif
|
||||
|
||||
if (modeP == PDCP_TRANSMISSION_MODE_TRANSPARENT) {
|
||||
AssertError (rb_idP < NB_RB_MBMS_MAX, return FALSE, "RB id is too high (%u/%d) %u %u!\n", rb_idP, NB_RB_MBMS_MAX, ctxt_pP->module_id, ctxt_pP->rnti);
|
||||
} else {
|
||||
@@ -458,6 +463,11 @@ pdcp_data_ind(
|
||||
LOG_F(PDCP,"\n");
|
||||
#endif
|
||||
|
||||
#if T_TRACER
|
||||
if (ctxt_pP->enb_flag != ENB_FLAG_NO)
|
||||
T(T_ENB_PDCP_UL, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->rnti), T_INT(rb_idP), T_INT(sdu_buffer_sizeP));
|
||||
#endif
|
||||
|
||||
if (MBMS_flagP) {
|
||||
AssertError (rb_idP < NB_RB_MBMS_MAX, return FALSE,
|
||||
"RB id is too high (%u/%d) %u rnti %x!\n",
|
||||
|
||||
@@ -359,6 +359,11 @@ rlc_op_status_t rlc_data_req (const protocol_ctxt_t* const ctxt_pP,
|
||||
|
||||
#endif
|
||||
|
||||
#if T_TRACER
|
||||
if (ctxt_pP->enb_flag)
|
||||
T(T_ENB_RLC_DL, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->rnti), T_INT(rb_idP), T_INT(sdu_sizeP));
|
||||
#endif
|
||||
|
||||
if (MBMS_flagP) {
|
||||
AssertFatal (rb_idP < NB_RB_MBMS_MAX, "RB id is too high (%u/%d)!\n", rb_idP, NB_RB_MBMS_MAX);
|
||||
} else {
|
||||
@@ -571,6 +576,12 @@ void rlc_data_ind (
|
||||
rlc_util_print_hex_octets(RLC, (unsigned char*)sdu_pP->data, sdu_sizeP);
|
||||
#endif
|
||||
|
||||
#if T_TRACER
|
||||
if (ctxt_pP->enb_flag)
|
||||
T(T_ENB_RLC_UL, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->rnti), T_INT(rb_idP), T_INT(sdu_sizeP));
|
||||
#endif
|
||||
|
||||
|
||||
pdcp_data_ind (
|
||||
ctxt_pP,
|
||||
srb_flagP,
|
||||
|
||||
@@ -221,6 +221,11 @@ tbs_size_t mac_rlc_data_req(
|
||||
;
|
||||
}
|
||||
|
||||
#if T_TRACER
|
||||
if (enb_flagP)
|
||||
T(T_ENB_RLC_MAC_DL, T_INT(module_idP), T_INT(rntiP), T_INT(channel_idP), T_INT(ret_tb_size));
|
||||
#endif
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_MAC_RLC_DATA_REQ,VCD_FUNCTION_OUT);
|
||||
return ret_tb_size;
|
||||
}
|
||||
@@ -276,6 +281,10 @@ void mac_rlc_data_ind (
|
||||
|
||||
#endif
|
||||
|
||||
#if T_TRACER
|
||||
if (enb_flagP)
|
||||
T(T_ENB_RLC_MAC_UL, T_INT(module_idP), T_INT(rntiP), T_INT(channel_idP), T_INT(tb_sizeP));
|
||||
#endif
|
||||
|
||||
if (MBMS_flagP) {
|
||||
if (BOOL_NOT(enb_flagP)) {
|
||||
|
||||
@@ -63,6 +63,8 @@
|
||||
#include "platform_types.h"
|
||||
#include "msc.h"
|
||||
|
||||
#include "T.h"
|
||||
|
||||
//#ifdef Rel10
|
||||
#include "MeasResults.h"
|
||||
//#endif
|
||||
@@ -858,6 +860,9 @@ rrc_eNB_process_RRCConnectionSetupComplete(
|
||||
PROTOCOL_RRC_CTXT_UE_FMT" [RAPROC] Logical Channel UL-DCCH, " "processing RRCConnectionSetupComplete from UE\n",
|
||||
PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP));
|
||||
|
||||
T(T_ENB_RRC_CONNECTION_SETUP_COMPLETE, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame),
|
||||
T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti));
|
||||
|
||||
#if defined(ENABLE_USE_MME)
|
||||
|
||||
if (EPC_MODE_ENABLED == 1) {
|
||||
@@ -888,6 +893,9 @@ rrc_eNB_generate_SecurityModeCommand(
|
||||
uint8_t buffer[100];
|
||||
uint8_t size;
|
||||
|
||||
T(T_ENB_RRC_SECURITY_MODE_COMMAND, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame),
|
||||
T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti));
|
||||
|
||||
size = do_SecurityModeCommand(
|
||||
ctxt_pP,
|
||||
buffer,
|
||||
@@ -952,6 +960,9 @@ rrc_eNB_generate_UECapabilityEnquiry(
|
||||
uint8_t buffer[100];
|
||||
uint8_t size;
|
||||
|
||||
T(T_ENB_RRC_UE_CAPABILITY_ENQUIRY, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame),
|
||||
T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti));
|
||||
|
||||
size = do_UECapabilityEnquiry(
|
||||
ctxt_pP,
|
||||
buffer,
|
||||
@@ -1004,6 +1015,9 @@ rrc_eNB_generate_RRCConnectionReject(
|
||||
int cnt;
|
||||
#endif
|
||||
|
||||
T(T_ENB_RRC_CONNECTION_REJECT, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame),
|
||||
T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti));
|
||||
|
||||
eNB_rrc_inst[ctxt_pP->module_id].carrier[CC_id].Srb0.Tx_buffer.payload_size =
|
||||
do_RRCConnectionReject(ctxt_pP->module_id,
|
||||
(uint8_t*) eNB_rrc_inst[ctxt_pP->module_id].carrier[CC_id].Srb0.Tx_buffer.Payload);
|
||||
@@ -1047,6 +1061,9 @@ rrc_eNB_generate_RRCConnectionReestablishmentReject(
|
||||
int cnt;
|
||||
#endif
|
||||
|
||||
T(T_ENB_RRC_CONNECTION_REESTABLISHMENT_REJECT, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame),
|
||||
T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti));
|
||||
|
||||
eNB_rrc_inst[ctxt_pP->module_id].carrier[CC_id].Srb0.Tx_buffer.payload_size =
|
||||
do_RRCConnectionReestablishmentReject(ctxt_pP->module_id,
|
||||
(uint8_t*) eNB_rrc_inst[ctxt_pP->module_id].carrier[CC_id].Srb0.Tx_buffer.Payload);
|
||||
@@ -1089,6 +1106,9 @@ rrc_eNB_generate_RRCConnectionRelease(
|
||||
uint8_t buffer[RRC_BUF_SIZE];
|
||||
uint16_t size;
|
||||
|
||||
T(T_ENB_RRC_CONNECTION_RELEASE, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame),
|
||||
T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti));
|
||||
|
||||
memset(buffer, 0, RRC_BUF_SIZE);
|
||||
|
||||
size = do_RRCConnectionRelease(ctxt_pP->module_id, buffer,rrc_eNB_get_next_transaction_identifier(ctxt_pP->module_id));
|
||||
@@ -1217,6 +1237,10 @@ rrc_eNB_generate_defaultRRCConnectionReconfiguration(
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
T(T_ENB_RRC_CONNECTION_RECONFIGURATION, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame),
|
||||
T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti));
|
||||
|
||||
// Configure SRB2
|
||||
/// SRB2
|
||||
SRB2_config = CALLOC(1, sizeof(*SRB2_config));
|
||||
@@ -1844,6 +1868,9 @@ rrc_eNB_process_MeasurementReport(
|
||||
)
|
||||
//-----------------------------------------------------------------------------
|
||||
{
|
||||
T(T_ENB_RRC_MEASUREMENT_REPORT, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame),
|
||||
T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti));
|
||||
|
||||
|
||||
LOG_I(RRC, "[eNB %d] Frame %d: Process Measurement Report From UE %x (Measurement Id %d)\n",
|
||||
ctxt_pP->module_id, ctxt_pP->frame, ctxt_pP->rnti, (int)measResults2->measId);
|
||||
@@ -1913,6 +1940,9 @@ rrc_eNB_generate_HandoverPreparationInformation(
|
||||
RadioResourceConfigDedicated_t *radioResourceConfigDedicated = CALLOC(1,sizeof(RadioResourceConfigDedicated_t));
|
||||
*/
|
||||
|
||||
T(T_ENB_RRC_HANDOVER_PREPARATION_INFORMATION, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame),
|
||||
T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti));
|
||||
|
||||
handoverInfo->as_config.antennaInfoCommon.antennaPortsCount = 0; //Not used 0- but check value
|
||||
handoverInfo->as_config.sourceDl_CarrierFreq = 36090; //Verify!
|
||||
|
||||
@@ -2003,6 +2033,9 @@ rrc_eNB_process_handoverPreparationInformation(
|
||||
)
|
||||
//-----------------------------------------------------------------------------
|
||||
{
|
||||
T(T_ENB_RRC_HANDOVER_PREPARATION_INFORMATION, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame),
|
||||
T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti));
|
||||
|
||||
|
||||
LOG_I(RRC,
|
||||
"[eNB %d] Frame %d : Logical Channel UL-DCCH, processing RRCHandoverPreparationInformation, sending RRCConnectionReconfiguration to UE %d \n",
|
||||
@@ -2078,6 +2111,9 @@ rrc_eNB_generate_RRCConnectionReconfiguration_handover(
|
||||
)
|
||||
//-----------------------------------------------------------------------------
|
||||
{
|
||||
T(T_ENB_RRC_CONNECTION_RECONFIGURATION, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame),
|
||||
T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti));
|
||||
|
||||
|
||||
uint8_t buffer[RRC_BUF_SIZE];
|
||||
uint16_t size;
|
||||
@@ -3034,6 +3070,9 @@ rrc_eNB_process_RRCConnectionReconfigurationComplete(
|
||||
DRB_ToAddModList_t* DRB_configList = ue_context_pP->ue_context.DRB_configList;
|
||||
//SRB_ToAddModList_t* SRB_configList = ue_context_pP->ue_context.SRB_configList;
|
||||
|
||||
T(T_ENB_RRC_CONNECTION_RECONFIGURATION_COMPLETE, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame),
|
||||
T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti));
|
||||
|
||||
#if defined(ENABLE_SECURITY)
|
||||
|
||||
/* Derive the keys from kenb */
|
||||
@@ -3294,6 +3333,9 @@ rrc_eNB_generate_RRCConnectionSetup(
|
||||
SRB_ToAddMod_t *SRB1_config;
|
||||
int cnt;
|
||||
|
||||
T(T_ENB_RRC_CONNECTION_SETUP, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame),
|
||||
T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti));
|
||||
|
||||
SRB_configList = &ue_context_pP->ue_context.SRB_configList;
|
||||
eNB_rrc_inst[ctxt_pP->module_id].carrier[CC_id].Srb0.Tx_buffer.payload_size =
|
||||
do_RRCConnectionSetup(ctxt_pP,
|
||||
@@ -3572,6 +3614,9 @@ rrc_eNB_decode_ccch(
|
||||
uint64_t random_value = 0;
|
||||
int stmsi_received = 0;
|
||||
|
||||
T(T_ENB_RRC_UL_CCCH_DATA_IN, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame),
|
||||
T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti));
|
||||
|
||||
//memset(ul_ccch_msg,0,sizeof(UL_CCCH_Message_t));
|
||||
|
||||
LOG_D(RRC, PROTOCOL_RRC_CTXT_UE_FMT" Decoding UL CCCH %x.%x.%x.%x.%x.%x (%p)\n",
|
||||
@@ -3642,6 +3687,9 @@ rrc_eNB_decode_ccch(
|
||||
break;
|
||||
|
||||
case UL_CCCH_MessageType__c1_PR_rrcConnectionReestablishmentRequest:
|
||||
T(T_ENB_RRC_CONNECTION_REESTABLISHMENT_REQUEST, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame),
|
||||
T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti));
|
||||
|
||||
#ifdef RRC_MSG_PRINT
|
||||
LOG_F(RRC,"[MSG] RRC Connection Reestablishement Request\n");
|
||||
|
||||
@@ -3684,6 +3732,9 @@ rrc_eNB_decode_ccch(
|
||||
break;
|
||||
|
||||
case UL_CCCH_MessageType__c1_PR_rrcConnectionRequest:
|
||||
T(T_ENB_RRC_CONNECTION_REQUEST, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame),
|
||||
T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti));
|
||||
|
||||
#ifdef RRC_MSG_PRINT
|
||||
LOG_F(RRC,"[MSG] RRC Connection Request\n");
|
||||
|
||||
@@ -3920,6 +3971,9 @@ rrc_eNB_decode_dcch(
|
||||
int i;
|
||||
struct rrc_eNB_ue_context_s* ue_context_p = NULL;
|
||||
|
||||
T(T_ENB_RRC_UL_DCCH_DATA_IN, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame),
|
||||
T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti));
|
||||
|
||||
if ((Srb_id != 1) && (Srb_id != 2)) {
|
||||
LOG_E(RRC, PROTOCOL_RRC_CTXT_UE_FMT" Received message on SRB%d, should not have ...\n",
|
||||
PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP),
|
||||
@@ -4067,6 +4121,9 @@ rrc_eNB_decode_dcch(
|
||||
break;
|
||||
|
||||
case UL_DCCH_MessageType__c1_PR_rrcConnectionReestablishmentComplete:
|
||||
T(T_ENB_RRC_CONNECTION_REESTABLISHMENT_COMPLETE, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame),
|
||||
T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti));
|
||||
|
||||
#ifdef RRC_MSG_PRINT
|
||||
LOG_F(RRC,"[MSG] RRC Connection Reestablishment Complete\n");
|
||||
|
||||
@@ -4142,6 +4199,9 @@ rrc_eNB_decode_dcch(
|
||||
break;
|
||||
|
||||
case UL_DCCH_MessageType__c1_PR_securityModeComplete:
|
||||
T(T_ENB_RRC_SECURITY_MODE_COMPLETE, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame),
|
||||
T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti));
|
||||
|
||||
#ifdef RRC_MSG_PRINT
|
||||
LOG_F(RRC,"[MSG] RRC Security Mode Complete\n");
|
||||
|
||||
@@ -4184,6 +4244,9 @@ rrc_eNB_decode_dcch(
|
||||
break;
|
||||
|
||||
case UL_DCCH_MessageType__c1_PR_securityModeFailure:
|
||||
T(T_ENB_RRC_SECURITY_MODE_FAILURE, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame),
|
||||
T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti));
|
||||
|
||||
#ifdef RRC_MSG_PRINT
|
||||
LOG_F(RRC,"[MSG] RRC Security Mode Failure\n");
|
||||
|
||||
@@ -4221,6 +4284,9 @@ rrc_eNB_decode_dcch(
|
||||
break;
|
||||
|
||||
case UL_DCCH_MessageType__c1_PR_ueCapabilityInformation:
|
||||
T(T_ENB_RRC_UE_CAPABILITY_INFORMATION, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame),
|
||||
T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti));
|
||||
|
||||
#ifdef RRC_MSG_PRINT
|
||||
LOG_F(RRC,"[MSG] RRC UECapablility Information \n");
|
||||
|
||||
@@ -4283,9 +4349,15 @@ rrc_eNB_decode_dcch(
|
||||
break;
|
||||
|
||||
case UL_DCCH_MessageType__c1_PR_ulHandoverPreparationTransfer:
|
||||
T(T_ENB_RRC_UL_HANDOVER_PREPARATION_TRANSFER, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame),
|
||||
T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti));
|
||||
|
||||
break;
|
||||
|
||||
case UL_DCCH_MessageType__c1_PR_ulInformationTransfer:
|
||||
T(T_ENB_RRC_UL_INFORMATION_TRANSFER, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame),
|
||||
T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti));
|
||||
|
||||
#ifdef RRC_MSG_PRINT
|
||||
LOG_F(RRC,"[MSG] RRC UL Information Transfer \n");
|
||||
|
||||
@@ -4319,27 +4391,48 @@ rrc_eNB_decode_dcch(
|
||||
break;
|
||||
|
||||
case UL_DCCH_MessageType__c1_PR_counterCheckResponse:
|
||||
T(T_ENB_RRC_COUNTER_CHECK_RESPONSE, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame),
|
||||
T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti));
|
||||
|
||||
break;
|
||||
|
||||
#ifdef Rel10
|
||||
|
||||
case UL_DCCH_MessageType__c1_PR_ueInformationResponse_r9:
|
||||
T(T_ENB_RRC_UE_INFORMATION_RESPONSE_R9, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame),
|
||||
T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti));
|
||||
|
||||
break;
|
||||
|
||||
case UL_DCCH_MessageType__c1_PR_proximityIndication_r9:
|
||||
T(T_ENB_RRC_PROXIMITY_INDICATION_R9, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame),
|
||||
T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti));
|
||||
|
||||
break;
|
||||
|
||||
case UL_DCCH_MessageType__c1_PR_rnReconfigurationComplete_r10:
|
||||
T(T_ENB_RRC_RECONFIGURATION_COMPLETE_R10, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame),
|
||||
T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti));
|
||||
|
||||
break;
|
||||
|
||||
case UL_DCCH_MessageType__c1_PR_mbmsCountingResponse_r10:
|
||||
T(T_ENB_RRC_MBMS_COUNTING_RESPONSE_R10, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame),
|
||||
T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti));
|
||||
|
||||
break;
|
||||
|
||||
case UL_DCCH_MessageType__c1_PR_interFreqRSTDMeasurementIndication_r10:
|
||||
T(T_ENB_RRC_INTER_FREQ_RSTD_MEASUREMENT_INDICATION, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame),
|
||||
T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti));
|
||||
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
T(T_ENB_RRC_UNKNOW_MESSAGE, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame),
|
||||
T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti));
|
||||
|
||||
LOG_E(RRC, PROTOCOL_RRC_CTXT_UE_FMT" Unknown message %s:%u\n",
|
||||
PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP),
|
||||
__FILE__, __LINE__);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user