aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.checkpatch.conf1
-rw-r--r--.clang-format563
-rw-r--r--.github/FUNDING.yml1
-rw-r--r--.gitignore9
-rw-r--r--.gitreview3
-rw-r--r--Makefile23
-rw-r--r--README.md32
-rw-r--r--TODO-RELEASE10
-rwxr-xr-xcontrib/flash.py164
-rwxr-xr-xcontrib/jenkins.sh73
-rwxr-xr-xcontrib/prepare_upload.sh18
-rw-r--r--contrib/simtrace.lua286
-rw-r--r--debian/changelog209
-rw-r--r--debian/compat2
-rw-r--r--debian/control46
-rw-r--r--debian/libosmo-simtrace2-1.install1
-rw-r--r--debian/libosmo-simtrace2-dev.install5
-rwxr-xr-xdebian/rules14
-rw-r--r--debian/source/format1
-rw-r--r--firmware/Makefile171
-rw-r--r--firmware/README.txt2
-rw-r--r--firmware/apps/blupdate/Makefile12
-rw-r--r--firmware/apps/blupdate/main.c136
-rw-r--r--firmware/apps/blupdate/usb_strings.txt6
-rw-r--r--firmware/apps/cardem/Makefile2
-rw-r--r--firmware/apps/cardem/main.c60
-rw-r--r--firmware/apps/cardem/usb_strings.txt4
-rw-r--r--firmware/apps/dfu/main.c106
-rw-r--r--firmware/apps/dfu/usb_strings.txt3
-rw-r--r--firmware/apps/freq_ctr/usb_strings.txt4
-rw-r--r--firmware/apps/gpio_test/Makefile3
-rw-r--r--firmware/apps/gpio_test/gpio_test.c8
-rw-r--r--firmware/apps/gpio_test/main.c54
-rw-r--r--firmware/apps/gpio_test/usb_strings.txt10
-rw-r--r--firmware/apps/trace/Makefile2
-rw-r--r--firmware/apps/trace/main.c22
-rw-r--r--firmware/apps/trace/usb_strings.txt4
-rw-r--r--firmware/apps/triple_play/Makefile2
-rw-r--r--firmware/apps/triple_play/main.c18
-rw-r--r--firmware/atmel_softpack_libraries/libchip_sam3s/chip.h2
-rw-r--r--firmware/atmel_softpack_libraries/libchip_sam3s/source/USBD_HAL.c45
-rw-r--r--firmware/atmel_softpack_libraries/libchip_sam3s/source/efc.c2
-rw-r--r--firmware/atmel_softpack_libraries/libchip_sam3s/source/exceptions.c3
-rw-r--r--firmware/atmel_softpack_libraries/libchip_sam3s/source/flashd.c2
-rw-r--r--firmware/atmel_softpack_libraries/libchip_sam3s/source/pio_it.c26
-rw-r--r--firmware/atmel_softpack_libraries/libchip_sam3s/source/unique_id.c7
-rw-r--r--firmware/atmel_softpack_libraries/usb/device/core/USBD.c2
-rw-r--r--firmware/atmel_softpack_libraries/usb/device/core/USBDDriver.c48
-rw-r--r--firmware/atmel_softpack_libraries/usb/device/dfu/dfu.h9
-rw-r--r--firmware/atmel_softpack_libraries/usb/device/dfu/dfu_desc.c181
-rw-r--r--firmware/atmel_softpack_libraries/usb/device/dfu/dfu_driver.c30
-rw-r--r--firmware/atmel_softpack_libraries/usb/device/dfu/dfu_runtime.c22
-rw-r--r--firmware/atmel_softpack_libraries/usb/include/USBD.h4
-rw-r--r--firmware/atmel_softpack_libraries/usb/include/USBDescriptors.h2
-rw-r--r--firmware/libboard/common/include/board_common.h28
-rw-r--r--firmware/libboard/common/include/boardver_adc.h4
-rw-r--r--firmware/libboard/common/include/led.h7
-rw-r--r--firmware/libboard/common/include/manifest.h4
-rw-r--r--firmware/libboard/common/include/sim_switch.h12
-rw-r--r--firmware/libboard/common/resources/sam3s4/dfu.ld38
-rw-r--r--firmware/libboard/common/resources/sam3s4/flash.ld15
-rw-r--r--firmware/libboard/common/source/board_cstartup_gnu.c7
-rw-r--r--firmware/libboard/common/source/board_lowlevel.c14
-rw-r--r--firmware/libboard/common/source/boardver_adc.c4
-rw-r--r--firmware/libboard/common/source/led.c12
-rw-r--r--firmware/libboard/common/source/manifest.c4
-rw-r--r--firmware/libboard/common/source/uart_console.c1
-rw-r--r--firmware/libboard/ngff_cardem/include/board.h162
-rw-r--r--firmware/libboard/ngff_cardem/include/card_pres.h18
-rw-r--r--firmware/libboard/ngff_cardem/include/wwan_led.h16
-rw-r--r--firmware/libboard/ngff_cardem/include/wwan_perst.h17
-rw-r--r--firmware/libboard/ngff_cardem/product_string.txt1
-rw-r--r--firmware/libboard/ngff_cardem/source/board_ngff_cardem.c155
-rw-r--r--firmware/libboard/ngff_cardem/source/card_pres.c72
-rw-r--r--firmware/libboard/ngff_cardem/source/sim_switch.c77
-rw-r--r--firmware/libboard/ngff_cardem/source/wwan_led.c89
-rw-r--r--firmware/libboard/ngff_cardem/source/wwan_perst.c123
-rw-r--r--firmware/libboard/octsimtest/include/board.h119
-rw-r--r--firmware/libboard/octsimtest/include/i2c.h24
-rw-r--r--firmware/libboard/octsimtest/include/mcp23017.h23
-rw-r--r--firmware/libboard/octsimtest/include/mux.h17
-rw-r--r--firmware/libboard/octsimtest/product_string.txt1
-rw-r--r--firmware/libboard/octsimtest/source/board_octsimtest.c120
-rw-r--r--firmware/libboard/octsimtest/source/i2c.c221
-rw-r--r--firmware/libboard/octsimtest/source/mcp23017.c156
-rw-r--r--firmware/libboard/octsimtest/source/mux.c109
-rw-r--r--firmware/libboard/octsimtest/source/sim_switch.c33
-rw-r--r--firmware/libboard/owhw/include/board.h22
-rw-r--r--firmware/libboard/owhw/product_string.txt1
-rw-r--r--firmware/libboard/owhw/source/owhw.c19
-rw-r--r--firmware/libboard/owhw/source/sim_switch.c (renamed from firmware/libboard/common/source/sim_switch.c)4
-rw-r--r--firmware/libboard/qmod/include/board.h31
-rw-r--r--firmware/libboard/qmod/include/card_pres.h4
-rw-r--r--firmware/libboard/qmod/include/i2c.h4
-rw-r--r--firmware/libboard/qmod/include/wwan_led.h4
-rw-r--r--firmware/libboard/qmod/include/wwan_perst.h4
-rw-r--r--firmware/libboard/qmod/product_string.txt1
-rw-r--r--firmware/libboard/qmod/source/board_qmod.c33
-rw-r--r--firmware/libboard/qmod/source/card_pres.c4
-rw-r--r--firmware/libboard/qmod/source/i2c.c4
-rw-r--r--firmware/libboard/qmod/source/sim_switch.c86
-rw-r--r--firmware/libboard/qmod/source/wwan_led.c4
-rw-r--r--firmware/libboard/qmod/source/wwan_perst.c4
-rw-r--r--firmware/libboard/sam3p256/include/board.h24
-rw-r--r--firmware/libboard/sam3p256/source/board_sam3p256.c4
-rw-r--r--firmware/libboard/simtrace/include/board.h46
-rw-r--r--firmware/libboard/simtrace/product_string.txt1
-rw-r--r--firmware/libboard/simtrace/source/board_simtrace.c4
-rw-r--r--firmware/libboard/simtrace/source/sim_switch.c50
-rw-r--r--firmware/libcommon/include/assert.h2
-rw-r--r--firmware/libcommon/include/card_emu.h36
-rw-r--r--firmware/libcommon/include/cciddriver.h28
-rw-r--r--firmware/libcommon/include/iso7816_fidi.h12
-rw-r--r--firmware/libcommon/include/llist_irqsafe.h4
-rw-r--r--firmware/libcommon/include/main_common.h3
-rw-r--r--firmware/libcommon/include/ringbuffer.h24
-rw-r--r--firmware/libcommon/include/simtrace.h8
-rw-r--r--firmware/libcommon/include/simtrace_prot.h36
-rw-r--r--firmware/libcommon/include/simtrace_usb.h8
-rw-r--r--firmware/libcommon/include/talloc.h6
-rw-r--r--firmware/libcommon/include/usb_buf.h6
-rw-r--r--firmware/libcommon/include/utils.h4
-rw-r--r--firmware/libcommon/source/card_emu.c447
-rw-r--r--firmware/libcommon/source/cciddriver.c10
-rw-r--r--firmware/libcommon/source/crcstub.c86
-rw-r--r--firmware/libcommon/source/fputs.c4
-rw-r--r--firmware/libcommon/source/host_communication.c39
-rw-r--r--firmware/libcommon/source/iso7816_fidi.c20
-rw-r--r--firmware/libcommon/source/main_common.c50
-rw-r--r--firmware/libcommon/source/mode_cardemu.c378
-rw-r--r--firmware/libcommon/source/pseudo_talloc.c25
-rw-r--r--firmware/libcommon/source/ringbuffer.c68
-rw-r--r--firmware/libcommon/source/simtrace_iso7816.c10
-rw-r--r--firmware/libcommon/source/sniffer.c470
-rw-r--r--firmware/libcommon/source/stack_check.c14
-rw-r--r--firmware/libcommon/source/stdio.c1
-rw-r--r--firmware/libcommon/source/tc_etu.c4
-rw-r--r--firmware/libcommon/source/usb.c168
-rw-r--r--firmware/libcommon/source/usb_buf.c19
-rw-r--r--firmware/libosmocore/include/osmocom/core/bit16gen.h4
-rw-r--r--firmware/libosmocore/include/osmocom/core/bit32gen.h4
-rw-r--r--firmware/libosmocore/include/osmocom/core/bit64gen.h4
-rw-r--r--firmware/libosmocore/include/osmocom/core/linuxrbtree.h4
-rw-r--r--firmware/libosmocore/include/osmocom/core/msgb.h47
-rw-r--r--firmware/libosmocore/include/osmocom/core/timer.h4
-rw-r--r--firmware/libosmocore/source/backtrace.c4
-rw-r--r--firmware/libosmocore/source/bits.c4
-rw-r--r--firmware/libosmocore/source/msgb.c4
-rw-r--r--firmware/libosmocore/source/panic.c6
-rw-r--r--firmware/libosmocore/source/rbtree.c4
-rw-r--r--firmware/libosmocore/source/timer.c4
-rw-r--r--firmware/libosmocore/source/utils.c4
-rw-r--r--firmware/misc/crctool.c91
-rw-r--r--firmware/test/Makefile4
-rw-r--r--firmware/test/card_emu_tests.c75
-rw-r--r--firmware/usbstring/usbstring.c4
-rw-r--r--hardware/board_gpio.gnumeric1640
-rw-r--r--host/.gitignore37
-rw-r--r--host/COPYING339
-rw-r--r--host/Makefile28
-rw-r--r--host/Makefile.am17
-rw-r--r--host/configure.ac104
-rw-r--r--host/contrib/99-simtrace2.rules (renamed from host/99-simtrace2.rules)4
-rw-r--r--host/contrib/Makefile.am1
-rw-r--r--host/contrib/simtrace2.spec.in102
-rw-r--r--host/include/Makefile.am8
-rw-r--r--host/include/osmocom/simtrace2/apdu_dispatch.h (renamed from host/apdu_dispatch.h)16
-rw-r--r--host/include/osmocom/simtrace2/gsmtap.h6
-rw-r--r--host/include/osmocom/simtrace2/simtrace2_api.h63
l---------host/include/osmocom/simtrace2/simtrace_prot.h1
l---------host/include/osmocom/simtrace2/simtrace_usb.h1
-rw-r--r--host/include/osmocom/simtrace2/usb_util.h5
-rw-r--r--host/lib/Makefile.am20
-rw-r--r--host/lib/apdu_dispatch.c (renamed from host/apdu_dispatch.c)48
-rw-r--r--host/lib/gsmtap.c78
-rw-r--r--host/lib/simtrace2_api.c343
-rw-r--r--host/lib/usb_util.c34
-rw-r--r--host/libosmo-simtrace2.pc.in10
-rw-r--r--host/libusb_util.c297
-rw-r--r--host/libusb_util.h70
-rw-r--r--host/simtrace.h7
-rw-r--r--host/simtrace2-discovery.c94
-rw-r--r--host/simtrace2-discovery.h26
-rw-r--r--host/simtrace2-remsim.c775
l---------host/simtrace_prot.h1
l---------host/simtrace_usb.h1
-rw-r--r--host/src/Makefile.am16
-rw-r--r--host/src/simtrace2-cardem-pcsc.c683
-rw-r--r--host/src/simtrace2-sniff.c (renamed from host/simtrace2-sniff.c)146
-rw-r--r--host/src/simtrace2-tool.c361
-rw-r--r--host/src/simtrace2_usb.c (renamed from host/simtrace2_usb.c)29
-rw-r--r--host/usb2udp.c286
192 files changed, 9000 insertions, 3494 deletions
diff --git a/.checkpatch.conf b/.checkpatch.conf
new file mode 100644
index 0000000..591ff65
--- /dev/null
+++ b/.checkpatch.conf
@@ -0,0 +1 @@
+--exclude ^firmware/atmel_softpack_libraries/.*$
diff --git a/.clang-format b/.clang-format
new file mode 100644
index 0000000..5d4791c
--- /dev/null
+++ b/.clang-format
@@ -0,0 +1,563 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# clang-format configuration file. Intended for clang-format >= 4.
+#
+# For more information, see:
+#
+# Documentation/process/clang-format.rst
+# https://clang.llvm.org/docs/ClangFormat.html
+# https://clang.llvm.org/docs/ClangFormatStyleOptions.html
+#
+---
+AccessModifierOffset: -4
+AlignAfterOpenBracket: Align
+AlignConsecutiveAssignments: false
+AlignConsecutiveDeclarations: false
+#AlignEscapedNewlines: Left # Unknown to clang-format-4.0
+AlignOperands: true
+AlignTrailingComments: false
+AllowAllParametersOfDeclarationOnNextLine: false
+AllowShortBlocksOnASingleLine: false
+AllowShortCaseLabelsOnASingleLine: false
+AllowShortFunctionsOnASingleLine: None
+AllowShortIfStatementsOnASingleLine: false
+AllowShortLoopsOnASingleLine: false
+AlwaysBreakAfterDefinitionReturnType: None
+AlwaysBreakAfterReturnType: None
+AlwaysBreakBeforeMultilineStrings: false
+AlwaysBreakTemplateDeclarations: false
+BinPackArguments: true
+BinPackParameters: true
+BraceWrapping:
+ AfterClass: false
+ AfterControlStatement: false
+ AfterEnum: false
+ AfterFunction: true
+ AfterNamespace: true
+ AfterObjCDeclaration: false
+ AfterStruct: false
+ AfterUnion: false
+ #AfterExternBlock: false # Unknown to clang-format-5.0
+ BeforeCatch: false
+ BeforeElse: false
+ IndentBraces: false
+ #SplitEmptyFunction: true # Unknown to clang-format-4.0
+ #SplitEmptyRecord: true # Unknown to clang-format-4.0
+ #SplitEmptyNamespace: true # Unknown to clang-format-4.0
+BreakBeforeBinaryOperators: None
+BreakBeforeBraces: Custom
+#BreakBeforeInheritanceComma: false # Unknown to clang-format-4.0
+BreakBeforeTernaryOperators: false
+BreakConstructorInitializersBeforeComma: false
+#BreakConstructorInitializers: BeforeComma # Unknown to clang-format-4.0
+BreakAfterJavaFieldAnnotations: false
+BreakStringLiterals: false
+ColumnLimit: 120
+CommentPragmas: '^ IWYU pragma:'
+#CompactNamespaces: false # Unknown to clang-format-4.0
+ConstructorInitializerAllOnOneLineOrOnePerLine: false
+ConstructorInitializerIndentWidth: 8
+ContinuationIndentWidth: 8
+Cpp11BracedListStyle: false
+DerivePointerAlignment: false
+DisableFormat: false
+ExperimentalAutoDetectBinPacking: false
+#FixNamespaceComments: false # Unknown to clang-format-4.0
+
+# Taken from:
+# git grep -h '^#define [^[:space:]]*for_each[^[:space:]]*(' include/ \
+# | sed "s,^#define \([^[:space:]]*for_each[^[:space:]]*\)(.*$, - '\1'," \
+# | sort | uniq
+ForEachMacros:
+ - 'apei_estatus_for_each_section'
+ - 'ata_for_each_dev'
+ - 'ata_for_each_link'
+ - '__ata_qc_for_each'
+ - 'ata_qc_for_each'
+ - 'ata_qc_for_each_raw'
+ - 'ata_qc_for_each_with_internal'
+ - 'ax25_for_each'
+ - 'ax25_uid_for_each'
+ - '__bio_for_each_bvec'
+ - 'bio_for_each_bvec'
+ - 'bio_for_each_bvec_all'
+ - 'bio_for_each_integrity_vec'
+ - '__bio_for_each_segment'
+ - 'bio_for_each_segment'
+ - 'bio_for_each_segment_all'
+ - 'bio_list_for_each'
+ - 'bip_for_each_vec'
+ - 'bitmap_for_each_clear_region'
+ - 'bitmap_for_each_set_region'
+ - 'blkg_for_each_descendant_post'
+ - 'blkg_for_each_descendant_pre'
+ - 'blk_queue_for_each_rl'
+ - 'bond_for_each_slave'
+ - 'bond_for_each_slave_rcu'
+ - 'bpf_for_each_spilled_reg'
+ - 'btree_for_each_safe128'
+ - 'btree_for_each_safe32'
+ - 'btree_for_each_safe64'
+ - 'btree_for_each_safel'
+ - 'card_for_each_dev'
+ - 'cgroup_taskset_for_each'
+ - 'cgroup_taskset_for_each_leader'
+ - 'cpufreq_for_each_entry'
+ - 'cpufreq_for_each_entry_idx'
+ - 'cpufreq_for_each_valid_entry'
+ - 'cpufreq_for_each_valid_entry_idx'
+ - 'css_for_each_child'
+ - 'css_for_each_descendant_post'
+ - 'css_for_each_descendant_pre'
+ - 'device_for_each_child_node'
+ - 'displayid_iter_for_each'
+ - 'dma_fence_chain_for_each'
+ - 'do_for_each_ftrace_op'
+ - 'drm_atomic_crtc_for_each_plane'
+ - 'drm_atomic_crtc_state_for_each_plane'
+ - 'drm_atomic_crtc_state_for_each_plane_state'
+ - 'drm_atomic_for_each_plane_damage'
+ - 'drm_client_for_each_connector_iter'
+ - 'drm_client_for_each_modeset'
+ - 'drm_connector_for_each_possible_encoder'
+ - 'drm_for_each_bridge_in_chain'
+ - 'drm_for_each_connector_iter'
+ - 'drm_for_each_crtc'
+ - 'drm_for_each_crtc_reverse'
+ - 'drm_for_each_encoder'
+ - 'drm_for_each_encoder_mask'
+ - 'drm_for_each_fb'
+ - 'drm_for_each_legacy_plane'
+ - 'drm_for_each_plane'
+ - 'drm_for_each_plane_mask'
+ - 'drm_for_each_privobj'
+ - 'drm_mm_for_each_hole'
+ - 'drm_mm_for_each_node'
+ - 'drm_mm_for_each_node_in_range'
+ - 'drm_mm_for_each_node_safe'
+ - 'flow_action_for_each'
+ - 'for_each_acpi_dev_match'
+ - 'for_each_active_dev_scope'
+ - 'for_each_active_drhd_unit'
+ - 'for_each_active_iommu'
+ - 'for_each_aggr_pgid'
+ - 'for_each_available_child_of_node'
+ - 'for_each_bio'
+ - 'for_each_board_func_rsrc'
+ - 'for_each_bvec'
+ - 'for_each_card_auxs'
+ - 'for_each_card_auxs_safe'
+ - 'for_each_card_components'
+ - 'for_each_card_dapms'
+ - 'for_each_card_pre_auxs'
+ - 'for_each_card_prelinks'
+ - 'for_each_card_rtds'
+ - 'for_each_card_rtds_safe'
+ - 'for_each_card_widgets'
+ - 'for_each_card_widgets_safe'
+ - 'for_each_cgroup_storage_type'
+ - 'for_each_child_of_node'
+ - 'for_each_clear_bit'
+ - 'for_each_clear_bit_from'
+ - 'for_each_cmsghdr'
+ - 'for_each_compatible_node'
+ - 'for_each_component_dais'
+ - 'for_each_component_dais_safe'
+ - 'for_each_comp_order'
+ - 'for_each_console'
+ - 'for_each_cpu'
+ - 'for_each_cpu_and'
+ - 'for_each_cpu_not'
+ - 'for_each_cpu_wrap'
+ - 'for_each_dapm_widgets'
+ - 'for_each_dev_addr'
+ - 'for_each_dev_scope'
+ - 'for_each_dma_cap_mask'
+ - 'for_each_dpcm_be'
+ - 'for_each_dpcm_be_rollback'
+ - 'for_each_dpcm_be_safe'
+ - 'for_each_dpcm_fe'
+ - 'for_each_drhd_unit'
+ - 'for_each_dss_dev'
+ - 'for_each_dtpm_table'
+ - 'for_each_efi_memory_desc'
+ - 'for_each_efi_memory_desc_in_map'
+ - 'for_each_element'
+ - 'for_each_element_extid'
+ - 'for_each_element_id'
+ - 'for_each_endpoint_of_node'
+ - 'for_each_evictable_lru'
+ - 'for_each_fib6_node_rt_rcu'
+ - 'for_each_fib6_walker_rt'
+ - 'for_each_free_mem_pfn_range_in_zone'
+ - 'for_each_free_mem_pfn_range_in_zone_from'
+ - 'for_each_free_mem_range'
+ - 'for_each_free_mem_range_reverse'
+ - 'for_each_func_rsrc'
+ - 'for_each_hstate'
+ - 'for_each_if'
+ - 'for_each_iommu'
+ - 'for_each_ip_tunnel_rcu'
+ - 'for_each_irq_nr'
+ - 'for_each_link_codecs'
+ - 'for_each_link_cpus'
+ - 'for_each_link_platforms'
+ - 'for_each_lru'
+ - 'for_each_matching_node'
+ - 'for_each_matching_node_and_match'
+ - 'for_each_member'
+ - 'for_each_memcg_cache_index'
+ - 'for_each_mem_pfn_range'
+ - '__for_each_mem_range'
+ - 'for_each_mem_range'
+ - '__for_each_mem_range_rev'
+ - 'for_each_mem_range_rev'
+ - 'for_each_mem_region'
+ - 'for_each_migratetype_order'
+ - 'for_each_msi_entry'
+ - 'for_each_msi_entry_safe'
+ - 'for_each_msi_vector'
+ - 'for_each_net'
+ - 'for_each_net_continue_reverse'
+ - 'for_each_netdev'
+ - 'for_each_netdev_continue'
+ - 'for_each_netdev_continue_rcu'
+ - 'for_each_netdev_continue_reverse'
+ - 'for_each_netdev_feature'
+ - 'for_each_netdev_in_bond_rcu'
+ - 'for_each_netdev_rcu'
+ - 'for_each_netdev_reverse'
+ - 'for_each_netdev_safe'
+ - 'for_each_net_rcu'
+ - 'for_each_new_connector_in_state'
+ - 'for_each_new_crtc_in_state'
+ - 'for_each_new_mst_mgr_in_state'
+ - 'for_each_new_plane_in_state'
+ - 'for_each_new_private_obj_in_state'
+ - 'for_each_node'
+ - 'for_each_node_by_name'
+ - 'for_each_node_by_type'
+ - 'for_each_node_mask'
+ - 'for_each_node_state'
+ - 'for_each_node_with_cpus'
+ - 'for_each_node_with_property'
+ - 'for_each_nonreserved_multicast_dest_pgid'
+ - 'for_each_of_allnodes'
+ - 'for_each_of_allnodes_from'
+ - 'for_each_of_cpu_node'
+ - 'for_each_of_pci_range'
+ - 'for_each_old_connector_in_state'
+ - 'for_each_old_crtc_in_state'
+ - 'for_each_old_mst_mgr_in_state'
+ - 'for_each_oldnew_connector_in_state'
+ - 'for_each_oldnew_crtc_in_state'
+ - 'for_each_oldnew_mst_mgr_in_state'
+ - 'for_each_oldnew_plane_in_state'
+ - 'for_each_oldnew_plane_in_state_reverse'
+ - 'for_each_oldnew_private_obj_in_state'
+ - 'for_each_old_plane_in_state'
+ - 'for_each_old_private_obj_in_state'
+ - 'for_each_online_cpu'
+ - 'for_each_online_node'
+ - 'for_each_online_pgdat'
+ - 'for_each_pci_bridge'
+ - 'for_each_pci_dev'
+ - 'for_each_pci_msi_entry'
+ - 'for_each_pcm_streams'
+ - 'for_each_physmem_range'
+ - 'for_each_populated_zone'
+ - 'for_each_possible_cpu'
+ - 'for_each_present_cpu'
+ - 'for_each_prime_number'
+ - 'for_each_prime_number_from'
+ - 'for_each_process'
+ - 'for_each_process_thread'
+ - 'for_each_prop_codec_conf'
+ - 'for_each_prop_dai_codec'
+ - 'for_each_prop_dai_cpu'
+ - 'for_each_prop_dlc_codecs'
+ - 'for_each_prop_dlc_cpus'
+ - 'for_each_prop_dlc_platforms'
+ - 'for_each_property_of_node'
+ - 'for_each_registered_fb'
+ - 'for_each_requested_gpio'
+ - 'for_each_requested_gpio_in_range'
+ - 'for_each_reserved_mem_range'
+ - 'for_each_reserved_mem_region'
+ - 'for_each_rtd_codec_dais'
+ - 'for_each_rtd_components'
+ - 'for_each_rtd_cpu_dais'
+ - 'for_each_rtd_dais'
+ - 'for_each_set_bit'
+ - 'for_each_set_bit_from'
+ - 'for_each_set_clump8'
+ - 'for_each_sg'
+ - 'for_each_sg_dma_page'
+ - 'for_each_sg_page'
+ - 'for_each_sgtable_dma_page'
+ - 'for_each_sgtable_dma_sg'
+ - 'for_each_sgtable_page'
+ - 'for_each_sgtable_sg'
+ - 'for_each_sibling_event'
+ - 'for_each_subelement'
+ - 'for_each_subelement_extid'
+ - 'for_each_subelement_id'
+ - '__for_each_thread'
+ - 'for_each_thread'
+ - 'for_each_unicast_dest_pgid'
+ - 'for_each_vsi'
+ - 'for_each_wakeup_source'
+ - 'for_each_zone'
+ - 'for_each_zone_zonelist'
+ - 'for_each_zone_zonelist_nodemask'
+ - 'fwnode_for_each_available_child_node'
+ - 'fwnode_for_each_child_node'
+ - 'fwnode_graph_for_each_endpoint'
+ - 'gadget_for_each_ep'
+ - 'genradix_for_each'
+ - 'genradix_for_each_from'
+ - 'hash_for_each'
+ - 'hash_for_each_possible'
+ - 'hash_for_each_possible_rcu'
+ - 'hash_for_each_possible_rcu_notrace'
+ - 'hash_for_each_possible_safe'
+ - 'hash_for_each_rcu'
+ - 'hash_for_each_safe'
+ - 'hctx_for_each_ctx'
+ - 'hlist_bl_for_each_entry'
+ - 'hlist_bl_for_each_entry_rcu'
+ - 'hlist_bl_for_each_entry_safe'
+ - 'hlist_for_each'
+ - 'hlist_for_each_entry'
+ - 'hlist_for_each_entry_continue'
+ - 'hlist_for_each_entry_continue_rcu'
+ - 'hlist_for_each_entry_continue_rcu_bh'
+ - 'hlist_for_each_entry_from'
+ - 'hlist_for_each_entry_from_rcu'
+ - 'hlist_for_each_entry_rcu'
+ - 'hlist_for_each_entry_rcu_bh'
+ - 'hlist_for_each_entry_rcu_notrace'
+ - 'hlist_for_each_entry_safe'
+ - 'hlist_for_each_entry_srcu'
+ - '__hlist_for_each_rcu'
+ - 'hlist_for_each_safe'
+ - 'hlist_nulls_for_each_entry'
+ - 'hlist_nulls_for_each_entry_from'
+ - 'hlist_nulls_for_each_entry_rcu'
+ - 'hlist_nulls_for_each_entry_safe'
+ - 'i3c_bus_for_each_i2cdev'
+ - 'i3c_bus_for_each_i3cdev'
+ - 'ide_host_for_each_port'
+ - 'ide_port_for_each_dev'
+ - 'ide_port_for_each_present_dev'
+ - 'idr_for_each_entry'
+ - 'idr_for_each_entry_continue'
+ - 'idr_for_each_entry_continue_ul'
+ - 'idr_for_each_entry_ul'
+ - 'in_dev_for_each_ifa_rcu'
+ - 'in_dev_for_each_ifa_rtnl'
+ - 'inet_bind_bucket_for_each'
+ - 'inet_lhash2_for_each_icsk_rcu'
+ - 'key_for_each'
+ - 'key_for_each_safe'
+ - 'klp_for_each_func'
+ - 'klp_for_each_func_safe'
+ - 'klp_for_each_func_static'
+ - 'klp_for_each_object'
+ - 'klp_for_each_object_safe'
+ - 'klp_for_each_object_static'
+ - 'kunit_suite_for_each_test_case'
+ - 'kvm_for_each_memslot'
+ - 'kvm_for_each_vcpu'
+ - 'list_for_each'
+ - 'list_for_each_codec'
+ - 'list_for_each_codec_safe'
+ - 'list_for_each_continue'
+ - 'list_for_each_entry'
+ - 'list_for_each_entry_continue'
+ - 'list_for_each_entry_continue_rcu'
+ - 'list_for_each_entry_continue_reverse'
+ - 'list_for_each_entry_from'
+ - 'list_for_each_entry_from_rcu'
+ - 'list_for_each_entry_from_reverse'
+ - 'list_for_each_entry_lockless'
+ - 'list_for_each_entry_rcu'
+ - 'list_for_each_entry_reverse'
+ - 'list_for_each_entry_safe'
+ - 'list_for_each_entry_safe_continue'
+ - 'list_for_each_entry_safe_from'
+ - 'list_for_each_entry_safe_reverse'
+ - 'list_for_each_entry_srcu'
+ - 'list_for_each_prev'
+ - 'list_for_each_prev_safe'
+ - 'list_for_each_safe'
+ - 'llist_for_each'
+ - 'llist_for_each_entry'
+ - 'llist_for_each_entry_safe'
+ - 'llist_for_each_safe'
+ - 'mci_for_each_dimm'
+ - 'media_device_for_each_entity'
+ - 'media_device_for_each_intf'
+ - 'media_device_for_each_link'
+ - 'media_device_for_each_pad'
+ - 'nanddev_io_for_each_page'
+ - 'netdev_for_each_lower_dev'
+ - 'netdev_for_each_lower_private'
+ - 'netdev_for_each_lower_private_rcu'
+ - 'netdev_for_each_mc_addr'
+ - 'netdev_for_each_uc_addr'
+ - 'netdev_for_each_upper_dev_rcu'
+ - 'netdev_hw_addr_list_for_each'
+ - 'nft_rule_for_each_expr'
+ - 'nla_for_each_attr'
+ - 'nla_for_each_nested'
+ - 'nlmsg_for_each_attr'
+ - 'nlmsg_for_each_msg'
+ - 'nr_neigh_for_each'
+ - 'nr_neigh_for_each_safe'
+ - 'nr_node_for_each'
+ - 'nr_node_for_each_safe'
+ - 'of_for_each_phandle'
+ - 'of_property_for_each_string'
+ - 'of_property_for_each_u32'
+ - 'pci_bus_for_each_resource'
+ - 'pcl_for_each_chunk'
+ - 'pcl_for_each_segment'
+ - 'pcm_for_each_format'
+ - 'ping_portaddr_for_each_entry'
+ - 'plist_for_each'
+ - 'plist_for_each_continue'
+ - 'plist_for_each_entry'
+ - 'plist_for_each_entry_continue'
+ - 'plist_for_each_entry_safe'
+ - 'plist_for_each_safe'
+ - 'pnp_for_each_card'
+ - 'pnp_for_each_dev'
+ - 'protocol_for_each_card'
+ - 'protocol_for_each_dev'
+ - 'queue_for_each_hw_ctx'
+ - 'radix_tree_for_each_slot'
+ - 'radix_tree_for_each_tagged'
+ - 'rb_for_each'
+ - 'rbtree_postorder_for_each_entry_safe'
+ - 'rdma_for_each_block'
+ - 'rdma_for_each_port'
+ - 'rdma_umem_for_each_dma_block'
+ - 'resource_list_for_each_entry'
+ - 'resource_list_for_each_entry_safe'
+ - 'rhl_for_each_entry_rcu'
+ - 'rhl_for_each_rcu'
+ - 'rht_for_each'
+ - 'rht_for_each_entry'
+ - 'rht_for_each_entry_from'
+ - 'rht_for_each_entry_rcu'
+ - 'rht_for_each_entry_rcu_from'
+ - 'rht_for_each_entry_safe'
+ - 'rht_for_each_from'
+ - 'rht_for_each_rcu'
+ - 'rht_for_each_rcu_from'
+ - '__rq_for_each_bio'
+ - 'rq_for_each_bvec'
+ - 'rq_for_each_segment'
+ - 'scsi_for_each_prot_sg'
+ - 'scsi_for_each_sg'
+ - 'sctp_for_each_hentry'
+ - 'sctp_skb_for_each'
+ - 'shdma_for_each_chan'
+ - '__shost_for_each_device'
+ - 'shost_for_each_device'
+ - 'sk_for_each'
+ - 'sk_for_each_bound'
+ - 'sk_for_each_entry_offset_rcu'
+ - 'sk_for_each_from'
+ - 'sk_for_each_rcu'
+ - 'sk_for_each_safe'
+ - 'sk_nulls_for_each'
+ - 'sk_nulls_for_each_from'
+ - 'sk_nulls_for_each_rcu'
+ - 'snd_array_for_each'
+ - 'snd_pcm_group_for_each_entry'
+ - 'snd_soc_dapm_widget_for_each_path'
+ - 'snd_soc_dapm_widget_for_each_path_safe'
+ - 'snd_soc_dapm_widget_for_each_sink_path'
+ - 'snd_soc_dapm_widget_for_each_source_path'
+ - 'tb_property_for_each'
+ - 'tcf_exts_for_each_action'
+ - 'udp_portaddr_for_each_entry'
+ - 'udp_portaddr_for_each_entry_rcu'
+ - 'usb_hub_for_each_child'
+ - 'v4l2_device_for_each_subdev'
+ - 'v4l2_m2m_for_each_dst_buf'
+ - 'v4l2_m2m_for_each_dst_buf_safe'
+ - 'v4l2_m2m_for_each_src_buf'
+ - 'v4l2_m2m_for_each_src_buf_safe'
+ - 'virtio_device_for_each_vq'
+ - 'while_for_each_ftrace_op'
+ - 'xa_for_each'
+ - 'xa_for_each_marked'
+ - 'xa_for_each_range'
+ - 'xa_for_each_start'
+ - 'xas_for_each'
+ - 'xas_for_each_conflict'
+ - 'xas_for_each_marked'
+ - 'xbc_array_for_each_value'
+ - 'xbc_for_each_key_value'
+ - 'xbc_node_for_each_array_value'
+ - 'xbc_node_for_each_child'
+ - 'xbc_node_for_each_key_value'
+ - 'zorro_for_each_dev'
+ - 'for_each_line'
+ - 'for_each_non_empty_line'
+
+#IncludeBlocks: Preserve # Unknown to clang-format-5.0
+IncludeCategories:
+ - Regex: '.*'
+ Priority: 1
+IncludeIsMainRegex: '(Test)?$'
+IndentCaseLabels: false
+#IndentPPDirectives: None # Unknown to clang-format-5.0
+IndentWidth: 8
+IndentWrappedFunctionNames: false
+JavaScriptQuotes: Leave
+JavaScriptWrapImports: true
+KeepEmptyLinesAtTheStartOfBlocks: false
+MacroBlockBegin: ''
+MacroBlockEnd: ''
+MaxEmptyLinesToKeep: 1
+NamespaceIndentation: None
+#ObjCBinPackProtocolList: Auto # Unknown to clang-format-5.0
+ObjCBlockIndentWidth: 8
+ObjCSpaceAfterProperty: true
+ObjCSpaceBeforeProtocolList: true
+
+# Taken from git's rules
+#PenaltyBreakAssignment: 10 # Unknown to clang-format-4.0
+PenaltyBreakBeforeFirstCallParameter: 30
+PenaltyBreakComment: 10
+PenaltyBreakFirstLessLess: 0
+PenaltyBreakString: 10
+PenaltyExcessCharacter: 100
+PenaltyReturnTypeOnItsOwnLine: 60
+
+PointerAlignment: Right
+ReflowComments: false
+SortIncludes: false
+#SortUsingDeclarations: false # Unknown to clang-format-4.0
+SpaceAfterCStyleCast: false
+SpaceAfterTemplateKeyword: true
+SpaceBeforeAssignmentOperators: true
+#SpaceBeforeCtorInitializerColon: true # Unknown to clang-format-5.0
+#SpaceBeforeInheritanceColon: true # Unknown to clang-format-5.0
+SpaceBeforeParens: ControlStatements
+#SpaceBeforeRangeBasedForLoopColon: true # Unknown to clang-format-5.0
+SpaceInEmptyParentheses: false
+SpacesBeforeTrailingComments: 1
+SpacesInAngles: false
+SpacesInContainerLiterals: false
+SpacesInCStyleCastParentheses: false
+SpacesInParentheses: false
+SpacesInSquareBrackets: false
+Standard: Cpp03
+TabWidth: 8
+UseTab: Always
+...
diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
new file mode 100644
index 0000000..7592deb
--- /dev/null
+++ b/.github/FUNDING.yml
@@ -0,0 +1 @@
+open_collective: osmocom
diff --git a/.gitignore b/.gitignore
index a4e484c..f8f1139 100644
--- a/.gitignore
+++ b/.gitignore
@@ -18,6 +18,11 @@ tags
*.bin
*.p
host/simtrace2-list
-host/simtrace2-remsim
-host/simtrace2-remsim-usb2udp
+host/simtrace2-cardem-pcsc
+host/contrib/simtrace2.spec
+host/src/simtrace2-tool
+host/tests
usb_strings_generated.h
+firmware/usbstring/usbstring
+firmware/apps/*/usb_strings.txt.patched
+firmware/misc/crctool \ No newline at end of file
diff --git a/.gitreview b/.gitreview
new file mode 100644
index 0000000..d1ed04a
--- /dev/null
+++ b/.gitreview
@@ -0,0 +1,3 @@
+[gerrit]
+host=gerrit.osmocom.org
+project=simtrace2
diff --git a/Makefile b/Makefile
index 1c00740..9951e54 100644
--- a/Makefile
+++ b/Makefile
@@ -8,19 +8,34 @@ fw-$(1)-$(2)-clean:
endef
$(eval $(call RULES,simtrace,dfu))
+$(eval $(call RULES,simtrace,blupdate))
$(eval $(call RULES,simtrace,trace))
$(eval $(call RULES,simtrace,cardem))
$(eval $(call RULES,qmod,dfu))
+$(eval $(call RULES,qmod,blupdate))
$(eval $(call RULES,qmod,cardem))
+$(eval $(call RULES,ngff_cardem,dfu))
+$(eval $(call RULES,ngff_cardem,blupdate))
+$(eval $(call RULES,ngff_cardem,trace))
+$(eval $(call RULES,ngff_cardem,cardem))
-fw-clean: fw-simtrace-dfu-clean fw-simtrace-trace-clean fw-simtrace-cardem-clean fw-qmod-dfu-clean fw-qmod-cardem-clean
-fw: fw-simtrace-dfu fw-simtrace-trace fw-simtrace-cardem fw-qmod-dfu fw-qmod-cardem
+fw-clean: fw-simtrace-dfu-clean fw-simtrace-blupdate-clean fw-simtrace-trace-clean fw-simtrace-cardem-clean \
+ fw-qmod-dfu-clean fw-qmod-blupdate-clean fw-qmod-cardem-clean \
+ fw-ngff_cardem-dfu-clean fw-ngff_cardem-blupdate-clean fw-ngff_cardem-trace-clean fw-ngff_cardem-cardem-clean
+fw: fw-simtrace-dfu fw-simtrace-blupdate fw-simtrace-trace fw-simtrace-cardem \
+ fw-qmod-dfu fw-qmod-blupdate fw-qmod-cardem \
+ fw-ngff_cardem-dfu fw-ngff_cardem-blupdate fw-ngff_cardem-trace fw-ngff_cardem-cardem
utils:
- make -C host
+ (cd host && \
+ autoreconf -fi && \
+ ./configure --prefix=/usr --disable-werror && \
+ make)
clean: fw-clean
- make -C host clean
+ if [ -e host/Makefile ]; then \
+ make -C host clean; \
+ fi
install:
make -C firmware install
diff --git a/README.md b/README.md
index 1f14317..d24effc 100644
--- a/README.md
+++ b/README.md
@@ -5,9 +5,6 @@ This is the repository for the next-generation SIMtrace devices,
providing abilities to trace the communication between (U)SIM card and
phone, remote (U)SIM card forward, (U)SIM man-in-the-middle, and more.
-This is under heavy development, and right now it is not surprising if
-things still break on a daily basis.
-
NOTE: Nothing in this repository applies to the SIMtrace v1.x hardware
or its associated firmware. SIMtrace v1.x is based on a different CPU /
microcontroller architecture and uses a completely different software
@@ -16,18 +13,17 @@ stack and host software.
Supported Hardware
------------------
-At this point, the primary development target is still the OWHW + sysmoQMOD
-device, but we expect to add support for a SAM3 based SIMtrace hardware
-board soon.
-
-The goal is to support the following devices:
-
-* Osmocom SIMtrace 1.x with SAM3 controller
-** this is open hardware and schematics / PCB design is published
-* sysmocom sysmoQMOD (with 4 Modems, 4 SIM slots and 2 SAM3)
-** this is a proprietary device, publicly available from sysmocom
+* Osmocom [SIMtrace2](https://osmocom.org/projects/simtrace2/wiki) with SAM3 controller
+ * this is open hardware and schematics / PCB design is published
+ * pre-built hardware available from [sysmocom webshop](https://shop.sysmocom.de/SIMtrace2-Hardware-Kit/simtrace2-kit)
+* Osmocom [ngff-cardem](https://osmocom.org/projects/ngff-cardem/wiki) M.2/NGFF modem carrier with SAM3 controller
+ * this is open hardware and schematics / PCB design is published
+ * pre-built hardware available from [sysmocom webshoo](https://shop.sysmocom.de/M.2-modem-carrier-with-remote-SIM-tracing/ngff-cardem-kit-external)
+* sysmocom [sysmoQMOD](https://sysmocom.de/products/lab/sysmoqmod/index.html) (with 4 Modems, 4 SIM slots and 2 SAM3)
+ * this is a proprietary device, publicly available from sysmocom
+ * hardware evaluation kit available from [sysmocom webshop](https://shop.sysmocom.de/sysmoQMOD-evaluation-kit/sysmoQMOD-evk)
* sysmocom OWHW (with 2 Modems and 1 SAM3 onboard)
-** this is not publicly available hardware, but still supported
+ * this is not publicly available hardware, but still supported
This Repository
---------------
@@ -37,3 +33,11 @@ This repository contains several directory
* firmware - the firmware to run on the actual devices
* hardware - some information related to the hardware
* host - Programs to use on the USB host to interface with the hardware
+
+
+The host software includes
+
+* libosmo-simtrace2 - a shared library to talk to devices running the simtrace2 firmware
+* simtrace2-list - list any USB-attached devices running simtrace2 firmware
+* simtrace2-sniff - interface the 'trace' firmware to obtain card protocol traces
+* simtrace2-cardem-pcsc - interface the 'cardem' fimrware to use a SIM in a PC/SC reader
diff --git a/TODO-RELEASE b/TODO-RELEASE
new file mode 100644
index 0000000..5da461b
--- /dev/null
+++ b/TODO-RELEASE
@@ -0,0 +1,10 @@
+# When cleaning up this file: bump API version in corresponding Makefile.am and rename corresponding debian/lib*.install
+# according to https://osmocom.org/projects/cellular-infrastructure/wiki/Make_a_new_release
+# In short: https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html#Updating-version-info
+# LIBVERSION=c:r:a
+# If the library source code has changed at all since the last update, then increment revision: c:r + 1:a.
+# If any interfaces have been added, removed, or changed since the last update: c + 1:0:0.
+# If any interfaces have been added since the last public release: c:r:a + 1.
+# If any interfaces have been removed or changed since the last public release: c:r:0.
+#library what description / commit summary line
+simtrace2 API/ABI change osmo_st2_transport new member
diff --git a/contrib/flash.py b/contrib/flash.py
new file mode 100755
index 0000000..01fe7c9
--- /dev/null
+++ b/contrib/flash.py
@@ -0,0 +1,164 @@
+#!/usr/bin/env python
+# encoding: utf-8
+# python: 3.8.1
+
+# library to enumerate USB devices
+import usb.core
+from usb.util import *
+# more elegant structure
+from typing import NamedTuple
+# regular expressions utilities
+import re
+# open utilities to handle files
+import os, sys
+# to download the firmwares
+import urllib.request
+# to flash using DFU-util
+import subprocess
+
+# SIMtrace 2 device information
+class Device(NamedTuple):
+ usb_vendor_id: int
+ usb_product_id: int
+ name: str
+ url: dict # 1: sniff/trace firmware, 2: card emulation firmware
+
+# SIMtrace 2 devices definitions
+DEVICE_SIMTRACE = Device(usb_vendor_id=0x1d50, usb_product_id=0x60e3, name="SIMtrace 2", url={"trace": "https://ftp.osmocom.org/binaries/simtrace2/firmware/latest/simtrace-trace-dfu-latest.bin", "cardem": "https://osmocom.org/attachments/download/3868/simtrace-cardem-dfu.bin"})
+DEVICE_QMOD = Device(usb_vendor_id=0x1d50, usb_product_id=0x4004, name="sysmoQMOD (Quad Modem)", url={"cardem": "https://ftp.osmocom.org/binaries/simtrace2/firmware/latest/qmod-cardem-dfu-latest.bin"})
+DEVICE_OWHW = Device(usb_vendor_id=0x1d50, usb_product_id=0x4001, name="OWHW", url={"cardem": "https://ftp.osmocom.org/binaries/simtrace2/firmware/latest/owhw-cardem-dfu-latest.bin"})
+DEVICE_OCTSIMTEST = Device(usb_vendor_id=0x1d50, usb_product_id=0x616d, name="OCTSIMTEST", url={"cardem": "https://ftp.osmocom.org/binaries/simtrace2/firmware/latest/octsimtest-cardem-dfu-latest.bin"})
+DEVICE_NGFF_CARDEM = Device(usb_vendor_id=0x1d50, usb_product_id=0x616e, name="ngff-cardem", url={"cardem": "https://ftp.osmocom.org/binaries/simtrace2/firmware/latest/ngff_cardem-cardem-dfu-latest.bin"})
+DEVICES = [DEVICE_SIMTRACE, DEVICE_QMOD, DEVICE_OCTSIMTEST, DEVICE_NGFF_CARDEM]
+
+# which firmware does the SIMtrace USN interface subclass correspond
+FIRMWARE_SUBCLASS = {1: "trace", 2: "cardem"}
+
+def print_help():
+ print("this script will flash SIMtrace 2 - based devices")
+ print("when no argument is provided, it will try to flash the application firmware of all SIMtrace 2 devices connected to USB with the latest version")
+ print("to flash a specific firmware, provide the name as argument")
+ print("the possible firmwares are: trace, cardem")
+ print("to list all devices connected to USB, provide the argument \"list\"")
+
+# the firmware to flash
+to_flash = None
+
+# parse command line argument
+if len(sys.argv) == 2:
+ to_flash = sys.argv[1]
+if to_flash not in ["list", "trace", "cardem"] and len(sys.argv) > 1:
+ print_help()
+ exit(0)
+
+# get all USB devices
+devices = []
+devices_nb = 0
+updated_nb = 0
+usb_devices = usb.core.find(find_all=True)
+for usb_device in usb_devices:
+ # find SIMtrace devices
+ definitions = list(filter(lambda x: x.usb_vendor_id == usb_device.idVendor and x.usb_product_id == usb_device.idProduct, DEVICES))
+ if 1 != len(definitions):
+ continue
+ devices_nb += 1
+ definition = definitions[0]
+ serial = usb_device.serial_number or "unknown"
+ usb_path = str(usb_device.bus) + "-" + ".".join(map(str, usb_device.port_numbers))
+ print("found " + definition.name + " device (chip ID " + serial + ") at USB path " + usb_path)
+ # determine if we are running DFU (in most cases the bootloader, but could also be the application)
+ dfu_interface = None
+ for configuration in usb_device:
+ # get DFU interface descriptor
+ dfu_interface = dfu_interface or find_descriptor(configuration, bInterfaceClass=254, bInterfaceSubClass=1)
+ if (None == dfu_interface):
+ print("no DFU USB interface found")
+ continue
+ dfu_mode = (2 == dfu_interface.bInterfaceProtocol) # InterfaceProtocol 1 is runtime mode, 2 is DFU mode
+ # determine firmware type (when not in DFU mode)
+ firmware = None
+ simtrace_interface = None
+ for configuration in usb_device:
+ simtrace_interface = simtrace_interface or find_descriptor(configuration, bInterfaceClass=255)
+ if simtrace_interface and simtrace_interface.bInterfaceSubClass in FIRMWARE_SUBCLASS:
+ firmware = firmware or FIRMWARE_SUBCLASS[simtrace_interface.bInterfaceSubClass]
+ if dfu_mode:
+ firmware = 'dfu'
+ if firmware:
+ print("installed firmware: " + firmware)
+ else:
+ print("unknown installed firmware")
+ continue
+ # determine version of the application/bootloader firmware
+ version = None
+ version_interface = None
+ for configuration in usb_device:
+ # get custom interface with string
+ version_interface = version_interface or find_descriptor(configuration, bInterfaceClass=255, bInterfaceSubClass=255)
+ if version_interface and version_interface.iInterface and version_interface.iInterface > 0 and get_string(usb_device, version_interface.iInterface):
+ version = get_string(usb_device, version_interface.iInterface)
+ if not version:
+ # the USB serial is set (in the application) since version 0.5.1.34-e026 from 2019-08-06
+ # https://git.osmocom.org/simtrace2/commit/?id=e0265462d8c05ebfa133db2039c2fbe3ebbd286e
+ # the USB serial is set (in the bootloader) since version 0.5.1.45-ac7e from 2019-11-18
+ # https://git.osmocom.org/simtrace2/commit/?id=5db9402a5f346e30288db228157f71c29aefce5a
+ # the firmware version is set (in the application) since version 0.5.1.37-ede8 from 2019-08-13
+ # https://git.osmocom.org/simtrace2/commit/?id=ede87e067dadd07119f24e96261b66ac92b3af6f
+ # the firmware version is set (in the bootloader) since version 0.5.1.45-ac7e from 2019-11-18
+ # https://git.osmocom.org/simtrace2/commit/?id=5db9402a5f346e30288db228157f71c29aefce5a
+ if dfu_mode:
+ if serial:
+ version = "< 0.5.1.45-ac7e"
+ else:
+ versoin = "< 0.5.1.45-ac7e"
+ else:
+ if serial:
+ version = "< 0.5.1.37-ede8"
+ else:
+ versoin = "< 0.5.1.34-e026"
+ print("device firmware version: " + version)
+ # flash latest firmware
+ if to_flash == "list": # we just want to list the devices, not flash them
+ continue
+ # check the firmware exists
+ if firmware == "dfu" and to_flash is None:
+ print("device is currently in DFU mode. you need to specify which firmware to flash")
+ continue
+ to_flash = to_flash or firmware
+ if to_flash not in definition.url.keys():
+ print("no firmware image available for " + firmware + " firmware")
+ continue
+ # download firmware
+ try:
+ dl_path, header = urllib.request.urlretrieve(definition.url[to_flash])
+ except:
+ print("could not download firmware " + definition.url[to_flash])
+ continue
+ dl_file = open(dl_path, "rb")
+ dl_data = dl_file.read()
+ dl_file.close()
+ # compare versions
+ dl_version = re.search(b'firmware \d+\.\d+\.\d+\.\d+-[0-9a-fA-F]{4}', dl_data)
+ if dl_version is None:
+ print("could not get version from downloaded firmware image")
+ os.remove(dl_path)
+ continue
+ dl_version = dl_version.group(0).decode("utf-8").split(" ")[1]
+ print("latest firmware version: " + dl_version)
+ versions = list(map(lambda x: int(x), version.split(" ")[-1].split("-")[0].split(".")))
+ dl_versions = list(map(lambda x: int(x), dl_version.split("-")[0].split(".")))
+ dl_newer = (versions[0] < dl_versions[0] or (versions[0] == dl_versions[0] and versions[1] < dl_versions[1]) or (versions[0] == dl_versions[0] and versions[1] == dl_versions[1] and versions[2] < dl_versions[2]) or (versions[0] == dl_versions[0] and versions[1] == dl_versions[1] and versions[2] == dl_versions[2] and versions[3] < dl_versions[3]))
+ if not dl_newer:
+ print("no need to flash latest version")
+ os.remove(dl_path)
+ continue
+ print("flashing latest version")
+ dfu_result = subprocess.run(["dfu-util", "--device", hex(definition.usb_vendor_id) + ":" + hex(definition.usb_product_id), "--path", usb_path, "--cfg", "1", "--alt", "1", "--reset", "--download", dl_path])
+ os.remove(dl_path)
+ if 0 != dfu_result.returncode:
+ printf("flashing firmware using dfu-util failed. ensure dfu-util is installed and you have the permissions to access this USB device")
+ continue
+ updated_nb += 1
+
+print(str(devices_nb)+ " SIMtrace 2 device(s) found")
+print(str(updated_nb)+ " SIMtrace 2 device(s) updated")
diff --git a/contrib/jenkins.sh b/contrib/jenkins.sh
index 99a6f00..e53a450 100755
--- a/contrib/jenkins.sh
+++ b/contrib/jenkins.sh
@@ -21,22 +21,51 @@ mkdir "$deps" || true
osmo-build-dep.sh libosmocore "" '--disable-doxygen --enable-gnutls'
+# verify only after building the dependency (to ensure we have most recent source of dependency)
+verify_value_string_arrays_are_terminated.py $(find . -name "*.[hc]")
+
export PKG_CONFIG_PATH="$inst/lib/pkgconfig:$PKG_CONFIG_PATH"
export LD_LIBRARY_PATH="$inst/lib"
-BUILDS=""
-BUILDS+="simtrace/dfu simtrace/cardem simtrace/trace " # simtrace/triple_play
-BUILDS+="qmod/dfu qmod/cardem "
-BUILDS+="owhw/dfu owhw/cardem "
+# dfu target MUST be built first, the combined targets need a bl that can be combined..
+BUILDS="simtrace/dfu qmod/dfu owhw/dfu ngff_cardem/dfu "
+#
+BUILDS+="simtrace/blupdate qmod/blupdate owhw/blupdate ngff_cardem/blupdate "
+BUILDS+="simtrace/cardem qmod/cardem owhw/cardem octsimtest/cardem ngff_cardem/cardem "
+BUILDS+="simtrace/trace ngff_cardem/trace "
cd $TOPDIR/firmware
for build in $BUILDS; do
board=`echo $build | cut -d "/" -f 1`
app=`echo $build | cut -d "/" -f 2`
+ case "$build" in
+ "owhw/cardem")
+ comb="combined"
+ ;;
+ "qmod/cardem")
+ comb="combined"
+ ;;
+ "ngff_cardem/cardem")
+ comb="combined"
+ ;;
+ "simtrace/trace")
+ comb="combined"
+ ;;
+ *)
+ comb=""
+ ;;
+ esac
echo
- echo "=============== $board / $app START =============="
- make BOARD="$board" APP="$app"
- echo "=============== $board / $app RES:$? =============="
+ # Build the bootloader with clang, the rest with gcc (OS#5260, OS#6026)
+ if [ "$app" = "dfu" ]; then
+ echo "=============== $board / $app START (CLANG) =============="
+ PATH="/opt/llvm-arm/bin:$PATH" make USE_CLANG=1 BOARD="$board" APP="$app" $comb
+ echo "=============== $board / $app RES:$? =============="
+ else
+ echo "=============== $board / $app START (GCC) =============="
+ make USE_CLANG=0 BOARD="$board" APP="$app" $comb
+ echo "=============== $board / $app RES:$? =============="
+ fi
done
echo
@@ -50,24 +79,36 @@ make clean
echo
echo "=============== HOST START =============="
cd $TOPDIR/host
-make clean
-make
-make clean
+autoreconf --install --force
+./configure --enable-sanitize --enable-werror
+$MAKE $PARALLEL_MAKE
+#$MAKE distcheck || cat-testlogs.sh
+make dist
+
+#if [ "$WITH_MANUALS" = "1" ] && [ "$PUBLISH" = "1" ]; then
+# make -C "$base/doc/manuals" publish
+#fi
if [ "x$publish" = "x--publish" ]; then
echo
echo "=============== UPLOAD BUILD =============="
+ $TOPDIR/contrib/prepare_upload.sh
- cat > "$WORKSPACE/known_hosts" <<EOF
-[rita.osmocom.org]:48 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDDgQ9HntlpWNmh953a2Gc8NysKE4orOatVT1wQkyzhARnfYUerRuwyNr1GqMyBKdSI9amYVBXJIOUFcpV81niA7zQRUs66bpIMkE9/rHxBd81SkorEPOIS84W4vm3SZtuNqa+fADcqe88Hcb0ZdTzjKILuwi19gzrQyME2knHY71EOETe9Yow5RD2hTIpB5ecNxI0LUKDq+Ii8HfBvndPBIr0BWYDugckQ3Bocf+yn/tn2/GZieFEyFpBGF/MnLbAAfUKIdeyFRX7ufaiWWz5yKAfEhtziqdAGZaXNaLG6gkpy3EixOAy6ZXuTAk3b3Y0FUmDjhOHllbPmTOcKMry9
-[rita.osmocom.org]:48 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBPdWn1kEousXuKsZ+qJEZTt/NSeASxCrUfNDW3LWtH+d8Ust7ZuKp/vuyG+5pe5pwpPOgFu7TjN+0lVjYJVXH54=
-[rita.osmocom.org]:48 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIK8iivY70EiR5NiGChV39gRLjNpC8lvu1ZdHtdMw2zuX
+ cat > "/build/known_hosts" <<EOF
+[ftp.osmocom.org]:48 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDDgQ9HntlpWNmh953a2Gc8NysKE4orOatVT1wQkyzhARnfYUerRuwyNr1GqMyBKdSI9amYVBXJIOUFcpV81niA7zQRUs66bpIMkE9/rHxBd81SkorEPOIS84W4vm3SZtuNqa+fADcqe88Hcb0ZdTzjKILuwi19gzrQyME2knHY71EOETe9Yow5RD2hTIpB5ecNxI0LUKDq+Ii8HfBvndPBIr0BWYDugckQ3Bocf+yn/tn2/GZieFEyFpBGF/MnLbAAfUKIdeyFRX7ufaiWWz5yKAfEhtziqdAGZaXNaLG6gkpy3EixOAy6ZXuTAk3b3Y0FUmDjhOHllbPmTOcKMry9
+[ftp.osmocom.org]:48 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBPdWn1kEousXuKsZ+qJEZTt/NSeASxCrUfNDW3LWtH+d8Ust7ZuKp/vuyG+5pe5pwpPOgFu7TjN+0lVjYJVXH54=
+[ftp.osmocom.org]:48 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIK8iivY70EiR5NiGChV39gRLjNpC8lvu1ZdHtdMw2zuX
EOF
- SSH_COMMAND="ssh -o 'UserKnownHostsFile=$WORKSPACE/known_hosts' -p 48"
- rsync -avz --delete -e "$SSH_COMMAND" $TOPDIR/firmware/bin/*.bin binaries@rita.osmocom.org:web-files/simtrace2/firmware/
+ SSH_COMMAND="ssh -o 'UserKnownHostsFile=/build/known_hosts' -p 48"
+ rsync --archive --verbose --compress --delete --rsh "$SSH_COMMAND" $TOPDIR/firmware/bin/*-latest.{bin,elf} binaries@ftp.osmocom.org:web-files/simtrace2/firmware/latest/
+ rsync --archive --verbose --compress --rsh "$SSH_COMMAND" --exclude $TOPDIR/firmware/bin/*-latest.{bin,elf} $TOPDIR/firmware/bin/*-*-*-*.{bin,elf} binaries@ftp.osmocom.org:web-files/simtrace2/firmware/all/
fi
echo
+echo "=============== HOST CLEAN =============="
+$MAKE maintainer-clean
+
+echo
echo "=============== FIRMWARE CLEAN =============="
cd $TOPDIR/firmware/
for build in $BUILDS; do
diff --git a/contrib/prepare_upload.sh b/contrib/prepare_upload.sh
new file mode 100755
index 0000000..cdd144f
--- /dev/null
+++ b/contrib/prepare_upload.sh
@@ -0,0 +1,18 @@
+#!/bin/bash -e
+# Create copies of binaries with -latest, -$GIT_VERSION (OS#4413, OS#3452)
+cd "$(dirname "$0")/.."
+
+GIT_VERSION="$(./git-version-gen .tarball-version)"
+
+echo "Copying binaries with "-latest" and "-$GIT_VERSION" appended..."
+
+cd firmware/bin
+for ext in bin elf; do
+ for file in *."$ext"; do
+ if ! [[ "$file" =~ ^(.*padded.*|.*nocrcstub.*bin)$ ]];then
+ without_ext="${file%.*}"
+ cp -v "$file" "$without_ext-latest.$ext"
+ cp -v "$file" "$without_ext-$GIT_VERSION.$ext"
+ fi
+ done
+done
diff --git a/contrib/simtrace.lua b/contrib/simtrace.lua
new file mode 100644
index 0000000..9015085
--- /dev/null
+++ b/contrib/simtrace.lua
@@ -0,0 +1,286 @@
+-- wireshark LUA dissector for the SIMtrace USB protocol
+-- (C) 2021 by sysmocom - s.f.m.c. GmbH, Author: Eric Wild
+-- SPDX-License-Identifier: GPL-2.0+
+--
+-- Usage: Move this file to your "personal lua plugins" folder that
+-- can be found in the Wireshark Help->About Wireshark->Folders tab
+-- Windows: %APPDATA%\Wireshark\plugins.
+-- Unix-like systems: ~/.local/lib/wireshark/plugins.
+
+usb_simtrace_protocol = Proto("USB_simtrace", "USB simtrace protocol")
+
+
+local control_commands = {
+-- /* SIMTRACE_MSGC_GENERIC */
+[0x0000] = "SIMTRACE_CMD_DO_ERROR",
+[0x0001] = "SIMTRACE_CMD_BD_BOARD_INFO",
+
+-- /* SIMTRACE_MSGC_CARDEM */
+[0x0101] = "DT_CEMU_TX_DATA",
+[0x0102] = "DT_CEMU_SET_ATR",
+[0x0103] = "BD_CEMU_STATS",
+[0x0104] = "BD_CEMU_STATUS",
+[0x0105] = "DT_CEMU_CARDINSERT",
+[0x0106] = "DO_CEMU_RX_DATA",
+[0x0107] = "DO_CEMU_PTS",
+[0x0108] = "BD_CEMU_CONFIG",
+
+-- /* SIMTRACE_MSGC_MODEM */
+[0x0201] = "DT_MODEM_RESET",
+[0x0202] = "DT_MODEM_SIM_SELECT",
+[0x0203] = "BD_MODEM_STATUS",
+
+-- /* SIMTRACE_MSGC_SNIFF */
+[0x0300] = "SNIFF_CHANGE",
+[0x0301] = "SNIFF_FIDI",
+[0x0302] = "SNIFF_ATR",
+[0x0304] = "SNIFF_TPDU",
+[0x0303] = "SNIFF_PPS"
+}
+
+local msgtype = ProtoField.uint16("usb_simtrace.msgtype", "Message Type", base.HEX_DEC, control_commands)
+local seqnr = ProtoField.uint8("usb_simtrace.seqnr", "Sequence Number", base.DEC)
+local slotnr = ProtoField.uint8("usb_simtrace.slotnr", "Slot Number", base.DEC)
+local reserved = ProtoField.uint16("usb_simtrace.reserved", "reserved", base.HEX_DEC)
+local payloadlen = ProtoField.uint16("usb_simtrace.length", "length", base.DEC)
+local payload = ProtoField.bytes("usb_simtrace.payload", "Data")
+
+local pb_and_rx = ProtoField.uint32("usb_simtrace.pb_and_rx", "pb_and_rx", base.HEX_DEC, NULL, 0x8)
+local pb_and_tx = ProtoField.uint32("usb_simtrace.pb_and_tx", "pb_and_tx", base.HEX_DEC, NULL, 0x4)
+local final = ProtoField.uint32("usb_simtrace.final", "final", base.HEX_DEC, NULL, 0x2)
+local tpdu_hdr = ProtoField.uint32("usb_simtrace.tpdu_hdr", "tpdu_hdr", base.HEX_DEC, NULL, 0x1)
+local rxtxdatalen = ProtoField.uint16("usb_simtrace.rxtxdatalen", "rx/tx data length", base.DEC)
+local rxtxdata = ProtoField.bytes("usb_simtrace.rxtxdata", "rx/tx (data)")
+
+local hf_pts_len = ProtoField.uint8("usb_simtrace.pts_len", "PTS length", base.DEC)
+local hf_pts_req = ProtoField.bytes("usb_simtrace.pts_req", "PTS request")
+local hf_pts_resp = ProtoField.bytes("usb_simtrace.pts_resp", "PTS response")
+
+local hf_cemu_cfg_features = ProtoField.uint32("usb_simtrace.cemu_cfg.features.status_irq", "CardEm Features", base.HEX)
+local hf_cemu_cfg_slot_mux_nr = ProtoField.uint32("usb_simtrace.cemu_cfg.features.slot_mux_nr", "CardEm Slot Mux Nr", base.DEC)
+
+local card_insert_types = {
+ [0x00] = "not inserted",
+ [0x01] = "inserted",
+}
+local hf_cemu_cardinsert = ProtoField.uint8("usb_simtrace.cardinsert", "Card Insert", base.DEC, card_insert_types, 0xff)
+
+local CEMU_STATUS_F_VCC_PRESENT = ProtoField.uint32("usb_simtrace.CEMU_STATUS.F_VCC_PRESENT", "VCC_PRESENT", base.HEX_DEC, NULL, 0x00000001)
+local CEMU_STATUS_F_CLK_ACTIVE = ProtoField.uint32("usb_simtrace.CEMU_STATUS.F_CLK_ACTIVE", "CLK_ACTIVE", base.HEX_DEC, NULL, 0x00000002)
+local CEMU_STATUS_F_RCEMU_ACTIVE = ProtoField.uint32("usb_simtrace.CEMU_STATUS.F_RCEMU_ACTIVE", "CEMU_ACTIVE", base.HEX_DEC, NULL, 0x00000004)
+local CEMU_STATUS_F_CARD_INSERT = ProtoField.uint32("usb_simtrace.CEMU_STATUS.F_CARD_INSERT", "CARD_INSERT", base.HEX_DEC, NULL, 0x00000008)
+local CEMU_STATUS_F_RESET_ACTIVE = ProtoField.uint32("usb_simtrace.CEMU_STATUS.F_RESET_ACTIVE", "RESET_ACTIVE", base.HEX_DEC, NULL, 0x00000010)
+
+local modem_reset_types = {
+ [0x00] = "de-assert",
+ [0x01] = "assert",
+ [0x02] = "pulse"
+}
+local modem_reset_status = ProtoField.uint8("usb_simtrace.modem.reset_type", "modem reset type", base.HEX, modem_reset_types, 0xf)
+local modem_reset_len = ProtoField.uint8("usb_simtrace.modem.reset_len", "modem reset length (ms)", base.DEC)
+
+local modem_sim_select_types = {
+ [0x00] = "local",
+ [0x01] = "remote",
+}
+local hf_modem_sim_select = ProtoField.uint8("usb_simtrace.modem.sim_select", "SIM card selection", base.DEC, modem_sim_select_types, 0xff)
+
+usb_simtrace_protocol.fields = {
+ msgtype, seqnr, slotnr, reserved, payloadlen, payload,
+ pb_and_rx, pb_and_tx, final, tpdu_hdr, rxtxdatalen, rxtxdata,
+ CEMU_STATUS_F_VCC_PRESENT, CEMU_STATUS_F_CLK_ACTIVE, CEMU_STATUS_F_RCEMU_ACTIVE, CEMU_STATUS_F_CARD_INSERT, CEMU_STATUS_F_RESET_ACTIVE,
+ modem_reset_status, modem_reset_len,
+ hf_pts_len, hf_pts_req, hf_pts_resp,
+ hf_cemu_cfg_features, hf_cemu_cfg_slot_mux_nr,
+ hf_cemu_cardinsert, hf_modem_sim_select,
+}
+
+local is_hdr = Field.new("usb_simtrace.tpdu_hdr")
+local is_pbrx = Field.new("usb_simtrace.pb_and_rx")
+local is_pbtx = Field.new("usb_simtrace.pb_and_tx")
+local is_final= Field.new("usb_simtrace.final")
+
+function dissect_rxtx(payload_data,pinfo,tree)
+
+ local headerSubtree = tree:add(usb_simtrace_protocol, payload_data, "rx/tx data")
+ local len = payload_data(4,2):le_uint();
+ local cmd32 = payload_data(0,4):le_uint();
+
+ headerSubtree:add(pb_and_rx, cmd32)
+ headerSubtree:add(pb_and_tx, cmd32)
+ headerSubtree:add(final, cmd32)
+ headerSubtree:add(tpdu_hdr, cmd32)
+
+ headerSubtree:add(rxtxdatalen, len)
+ headerSubtree:add_le(rxtxdata, payload_data(6,len))
+
+ local flagstr = " "
+ if is_pbrx().value == 1 then
+ flagstr = flagstr .. "R"
+ else
+ flagstr = flagstr .. "."
+ end
+ if is_pbtx().value == 1 then
+ flagstr = flagstr .. "T"
+ else
+ flagstr = flagstr .. "."
+ end
+ if is_final().value == 1 then
+ flagstr = flagstr .. "F"
+ else
+ flagstr = flagstr .. "."
+ end
+ if is_hdr().value == 1 then
+ flagstr = flagstr .. "H"
+ else
+ flagstr = flagstr .. "."
+ end
+ flagstr = flagstr .. " "
+ pinfo.cols.info:append(flagstr .. payload_data(6,len))
+
+ -- ghetto dissection does not work due to mixed in procedure bytes
+ --if pinfo.visited == false then
+ -- Dissector.get("iso7816"):call(payload_data(6):tvb(), pinfo, tree)
+
+-- local offs = 0
+-- if (is_pbrx().value == 1 or is_pbtx().value == 1) and is_final().value == 0 then
+-- offs = 1
+-- else
+-- offs = 0
+-- end
+--
+-- if is_hdr().value == 1 then
+-- Dissector.get("gsm_sim"):call(concatss:tvb(), pinfo, tree)
+-- concatss = payload_data(6):bytes()
+-- else
+-- concatss = concatss .. payload_data(6+offs):bytes()
+-- end
+
+--end
+
+end
+
+function dissect_status(payload_data,pinfo,tree)
+
+ local headerSubtree = tree:add(usb_simtrace_protocol, payload_data, "status message")
+ local cmd32 = payload_data(0,4):le_uint();
+
+ headerSubtree:add(CEMU_STATUS_F_VCC_PRESENT, cmd32)
+ headerSubtree:add(CEMU_STATUS_F_CLK_ACTIVE, cmd32)
+ headerSubtree:add(CEMU_STATUS_F_RCEMU_ACTIVE, cmd32)
+ headerSubtree:add(CEMU_STATUS_F_CARD_INSERT, cmd32)
+ headerSubtree:add(CEMU_STATUS_F_RESET_ACTIVE, cmd32)
+
+ pinfo.cols.info:append(" VCC:" .. payload_data(0,1):bitfield(7, 1) .. " CLK:" .. payload_data(0,1):bitfield(6, 1) .. " RESET:" .. payload_data(0,1):bitfield(3, 1))
+end
+
+function dissect_atr(payload_data,pinfo,tree)
+
+ local len = payload_data(0,1):le_uint()
+ Dissector.get("iso7816.atr"):call(payload_data(1):tvb(), pinfo, tree)
+end
+
+function dissect_modem_reset(payload_data,pinfo,tree)
+
+ local headerSubtree = tree:add(usb_simtrace_protocol, payload_data, "modem reset")
+ local cmd8 = payload_data(0,1):le_uint();
+
+ headerSubtree:add(modem_reset_status, cmd8)
+ pinfo.cols.info:append(" reset type:" .. modem_reset_types[cmd8]);
+
+ if(cmd8 == 2) then
+ local duration = payload_data(1,2):le_uint()
+ headerSubtree:add(modem_reset_len, duration)
+ pinfo.cols.info:append(" duration:" .. duration .. "ms")
+ end
+
+
+end
+
+function dissect_pts(payload_data, pinfo, tree)
+ local subtree = tree:add(usb_simtrace_protocol, payload_data, "PTS")
+ local pts_len = payload_data(0,1):le_uint()
+ local pts_req = payload_data(1, pts_len);
+ local pts_resp = payload_data(7, pts_len);
+
+ subtree:add(hf_pts_len, pts_len);
+ subtree:add(hf_pts_req, pts_req);
+ subtree:add(hf_pts_resp, pts_resp);
+
+ pinfo.cols.info:append(" Req: " .. pts_req .. ", Resp: " .. pts_resp);
+end
+
+function dissect_cemu_config(payload_data, pinfo, tree)
+ local subtree = tree:add(usb_simtrace_protocol, payload_data, "Card Emu Config")
+
+ subtree:add(hf_cemu_cfg_features, payload_data(0,4));
+ subtree:add(hf_cemu_cfg_slot_mux_nr, payload_data(4,1));
+end
+
+function dissect_modem_sim_sel(payload_data, pinfo, tree)
+ local subtree = tree:add(usb_simtrace_protocol, payload_data, "Modem SIM Select")
+ local sim_select = payload_data(0,1):le_uint();
+
+ subtree:add(hf_modem_sim_select, sim_select);
+ pinfo.cols.info:append(" " .. modem_sim_select_types[sim_select]);
+end
+
+function dissect_cemu_cardinsert(payload_data, pinfo, tree)
+ local subtree = tree:add(usb_simtrace_protocol, payload_data, "Card Insert")
+ local cins_type = payload_data(0,1):le_uint()
+
+ subtree:add(hf_cemu_cardinsert, cins_type);
+ pinfo.cols.info:append(" " .. card_insert_types[cins_type]);
+end
+
+
+
+function usb_simtrace_protocol.dissector(buffer, pinfo, tree)
+ length = buffer:len()
+ if length == 0 then return end
+
+ pinfo.cols.protocol = usb_simtrace_protocol.name
+
+ local subtree = tree:add(usb_simtrace_protocol, buffer(), "USB simtrace Data")
+ local command = buffer(0,2):uint()
+
+ subtree:add(msgtype, command):set_generated()
+ subtree:add(seqnr, buffer(2,1))
+ subtree:add(slotnr, buffer(3,1))
+ subtree:add_le(payloadlen, buffer(6,2))
+ pinfo.cols.info = string.format("Cmd 0x%04X : %s", command, control_commands[command])
+ local payload_data = buffer(8,length-8)
+ if(command == 0x0101 or command == 0x0106) then
+ return dissect_rxtx(payload_data(),pinfo,subtree)
+ elseif(command == 0x0104) then
+ return dissect_status(payload_data(),pinfo,subtree)
+ elseif(command == 0x0102) then
+ return dissect_atr(payload_data(),pinfo,subtree)
+ elseif(command == 0x0105) then
+ return dissect_cemu_cardinsert(payload_data(),pinfo,subtree)
+ elseif(command == 0x0107) then
+ return dissect_pts(payload_data(),pinfo,subtree)
+ elseif(command == 0x0108) then
+ return dissect_cemu_config(payload_data(),pinfo,subtree)
+ elseif(command == 0x0201) then
+ return dissect_modem_reset(payload_data(),pinfo,subtree)
+ elseif(command == 0x0202) then
+ return dissect_modem_sim_sel(payload_data(),pinfo,subtree)
+ else
+ subtree:add(payload, payload_data)
+ end
+
+end
+
+
+function usb_simtrace_protocol.init()
+ local usb_product_dissectors = DissectorTable.get("usb.product")
+ usb_product_dissectors:add(0x1d50616d, usb_simtrace_protocol) -- OCTSIMTEST
+ usb_product_dissectors:add(0x1d50616e, usb_simtrace_protocol) -- NGFF_CARDEM
+ usb_product_dissectors:add(0x1d5060e3, usb_simtrace_protocol) -- SIMTRACE2
+ usb_product_dissectors:add(0x1d504004, usb_simtrace_protocol) -- QMOD
+ usb_product_dissectors:add(0x1d504001, usb_simtrace_protocol) -- OWHW
+ DissectorTable.get("usb.device"):add_for_decode_as(usb_simtrace_protocol)
+ DissectorTable.get("usb.bulk"):add(0xffff, usb_simtrace_protocol)
+ DissectorTable.get("usb.interrupt"):add(0xffff, usb_simtrace_protocol)
+end
diff --git a/debian/changelog b/debian/changelog
index a3da488..99cfb8b 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,212 @@
+simtrace2 (0.8.1) unstable; urgency=medium
+
+ * host/contrib/simtrace2.spec.in: fix soname
+
+ -- Oliver Smith <osmith@sysmocom.de> Fri, 10 Dec 2021 10:04:28 +0100
+
+simtrace2 (0.8.0) unstable; urgency=medium
+
+ [ Harald Welte ]
+ * adapt to host tools in autotools
+ * simtrace2_api: Remove dead code
+ * fix baudrate of 'make log'
+ * qmod DFU: Don't overwrite memory beyond end of usb_strings[]
+ * usb_strings.txt: s/SIMtrace Phone/SIMtrace Card Emulation/
+ * Patch actual board name into the USB iProduct string descriptor
+ * Build only 'reasonable' combinations of APP/MEMORY
+ * stdio: Add support for %p format string (pointer address)
+ * Fix format string related warnings (int vs. long)
+ * Add missing CR to achieve CRLF at end of log lines
+ * more comments in host_communication.c.
+ * usb_buf: count number of elements in queue
+ * usb_buf: Limit the maximum queue length to 3 elements
+ * qmod: Don't print EEPROM operations in help when not supported
+ * cosmetic: board_qmod: Annotate #endif with comments
+ * qmod: Document '!' and '@' commands on UART
+ * implement minimalistic talloc_report(); add 't' command on UART
+ * update copyright statement
+ * cardem: Fix memory leak on unsupported SIMTRACE_MSGT_DT_CEMU_CARDINSERT
+ * usb_buf: Actually limit queue to 3 elements, not 4
+ * USBD_HAL: Don't disable UDP peripheral clock on suspend
+ * usb_buf: Properly initialize buffered_endpoint->ep number
+ * pseudo_talloc: Increment number of buffers from 10 to 20
+ * card_emu: Factor out card_handle_reset() from card_emu_init()
+ * cardem: Move card_emu_io_statechg() calls out of interrupt context
+ * cardem: RST resets all state (including release of buffers)
+ * host_communication: Send zero-length-packet on wMaxPacketSize
+ * card_emu: Initialize PTSS state every time we start PTS
+ * card_emu: Avoid recursive calls to card_set_state()
+ * card_emu: Always print state names in string representation
+ * card_emu: Remove extraneous code
+ * card_emu: Remove extraneous initialization of ch->pts.state
+ * cardem: Make card_emu_report_status() optionally use IRQ endpoint
+ * cardem: Add SIMTRACE_MSGT_BD_CEMU_CONFIG
+ * cardem: Implement support for CEMU_FEAT_F_STATUS_IRQ
+ * simtrace2-sniff: Reformat value_string to pass our validation scripts
+ * firmware: Reformat value_string to pass our validation scripts
+ * jenkins.sh: Add verify_value_string_arrays_are_terminated.py
+ * [lib] apdu_dispatch: Use DLGLOBAL and don't printf() directly
+ * [lib] apdu_dispatch: Don't print APDU state to stdout
+ * OSMO_ASSERT() on double-free or invalid pointer
+ * Update .gitignore file for host
+ * migrate to libosmousb
+ * library: Add osmo_st2_compatible_dev_idsp[]
+ * firmware: move printing of welcome banner to common function print_banner()
+ * firmware: apps/cardem/main.c: Synchronize with apps/trace/main.c
+ * host: Add COPYING file for host software (GPLv2)
+ * host/lib/gsmtap.c: Add GPLv2 disclaimer
+ * increase ringbuffer size from 512 to 1024 bytes
+ * simtrace2_api: Add osmo_st2_cardem_request_config()
+ * Disable interrupts during EEFC_ReadUniqueID()
+ * cardem: Fix infinite loop + watchdog reset on long OUT message
+ * extend osmo_st2_cardem_inst with fields required by osmo-remsim
+ * cosmetic: Add missing CR to LF in dispatch_received_usb_msg()
+ * USBD.c: Don't reset EP0 on SetConfiguration(0)
+ * pio_it.c: Permit repeated calls to PIO_ConfigureIt()
+ * simtrace2_siff: getopt_long() returns int, not char
+ * Introduce support for asynchronous USB transmission
+ * firmware: fix builds with gcc stack smashing protection enabled
+ * dfu: Shrink code by 144 bytes (by not calling PIO_InitializeInterrupts)
+ * dfu: Save another 60 bytes by changing the way we print horizontal lines
+ * migrate from BSC_FD_* to OSMO_FD_*
+ * remove usb2udp
+ * rename simtrace2-remsim to simtrace2-cardem-pcsc
+ * Update README
+ * remove old pre-autoconf makefile
+ * simtrace2-cardem-pcsc: Make it work again
+ * Revert "add ISO 7816-3 library to remsim project"
+ * Revert "add library providing ISO 7816-3 utilities"
+ * card_emu: waiting_time is stored in etu, not clocks.
+ * card_emu: Rename fi to Fi and di to Di
+ * card_emu: Clarify and differentiate F/Fi/F_index/Fi_index
+ * iso7816_fidi: Add iso7816_3_ prefix to symbols; fix terminology
+ * card_emu: improve reset detection conditions
+ * card_emu: explicitly initialize PTS and TPDU states
+ * card_emu: Use USART timeout for waiting time
+ * card_emu: Fix USART timer, particularly in re-start situations
+ * card_emu: Fix computation of waiting time
+ * contrib/jenkins.sh: Switch from rita -> ftp.osmocom.org
+ * st2-cardem-pcsc: Fix goto-in-while mess
+ * st2-cardem-pcsc: Use ATR of real card by default
+ * simtrace board.h: Enable HAVE_CARDEM if we build the cardem firmware
+ * jenkins.sh: build 'cardem' firmware also for simtrace board
+ * Revert "cardem: disable upload for simtrace2"
+ * simtrace2-cardem-pcsc: Decode STATUS flags to strings
+ * simtrace2-cardem-pcsc: Reset the real card if reader resets cardem
+ * assert: Use printf_sync() to ensure printing of assert / panic
+ * Add usb product ID of sysmoOCTSIMTEST
+ * octsimtest: remove lots of unused #defines
+ * octsimtest: most code for support of this new board
+ * octsimtest: Switch direction of I/O level shifter depending on uart tx / rx
+ * cardem-pcsc: initialize libosmocore logging
+ * octsimtest: Adjust VCC voltage thresholds (resistive VCC divider)
+ * contrib/jenkins.sh: Build 'cardem' app for 'octsimtest' board
+ * firmware: octsimtest: Fix IO_DIR pin definition
+ * firmware: octsimtest: Make slot mux configurable via USB
+ * firmware: octsimtest: mcp23017 initializaiton
+ * firmware: cardem: re-factor CARDINSERT command processing
+ * firmware: octsimtest: Support SIMTRACE_MSGT_DT_CEMU_CARDINSERT
+ * firmware: octsimtest: use TRACE_* macros instead of direct printf
+ * firmware: octsimtest: Fix disabling the card_insert signal
+ * firmware: octsimtest: Add i/I command for setting card-insert via I2C GPIO
+ * firmware: octsimtest: ensure all card_insert GPIO are 0 after reset
+ * don't printf() directly from library code, go via libosmocore logging
+ * simtrace2-list: Use osmo_st2_compatible_dev_ids[]
+ * board_gpio.gnumeric: Add ngff-cardem pin-out
+ * 99-simtrace2.rules: Add OCTSIMTEST
+ * contrib/flash.py: Add OCTSIMTEST support
+ * Introduce simtrace2-tool
+ * introduce support for new ngff_cardem board
+ * simtrace2.spec: Add simtrace2-tool binary to package
+ * contrib/jenkins.sh: Build APP=cardem for BOARD=ngff_cardem
+ * jenkins.sh: Build 'trace' firmware for ngff_cardem
+ * Use osmo_libusb_{init,exit}() instead of libusb_{init,exit}()
+ * simtrace2-cardem-pcsc: Remove double libusb initialization
+ * simtrace2-tool: Initialize logging to avoid error on first log output
+ * cardem-pcsc: Fix return of uninitialized variable
+ * host: Upgrade libosmocore dependency to 1.4.0
+
+ [ Kévin Redon ]
+ * minor: fix spacing
+ * minor: updated copyright years
+ * dfu: minor: make debug output only verbose in info level
+ * minor: move USB debug output from info to debug level
+ * minor: improve debug output
+ * minor : fix typo in comment
+ * better detect VCC and nRST changes on simtrace2 board
+ * minor: ignore usbstring binary
+ * simtrace2-remsim: Use simplest ATR
+ * cardem: use simplest ATR as default ATR
+ * minor: fix typo
+ * DFU: increase USB reset duration to 50 ms
+ * DFU: restart bootloader when USB conf failed
+ * Makefile: add linker option showing memory usage
+ * improve shared bootloader/application memory
+ * minor: improve trace output
+ * DFU: add DFU application
+ * add script to flash latest firmware
+ * minor: use same LED pattern for cardem as other applications
+ * cardem: currently simtrace does not support cardem
+ * add library providing ISO 7816-3 utilities
+ * add ISO 7816-3 library to remsim project
+ * rename PIN_PHONE_{CLK,IO} to PIN_USIM1_{CLK,IO}
+ * minor add comments
+ * make sim switch board specific
+
+ [ Eric Wild ]
+ * remsim: allow selecting pcsc reader number
+ * cardem: disable upload for simtrace2
+ * firmware: do not allow undefined symbols
+ * firmware: allow verbose builds
+ * cardem: choose a more reasonable default ATR
+ * contrib: add a basic simtrace lua dissector for wireshark
+ * cardem: free the buf
+ * cardemu: support 1v8 for the tester
+ * firmware: data sections
+ * firmware: proper makefile deps
+ * firmware: make the ngff beakout blink
+ * simtrace2-cardem: use local sim on exit
+ * contrib: more cardem dissection
+ * firmware: trace for ngff
+ * cardem: fix spurious NULL bytes during transfers
+ * contrib/jenkins.sh: build ngff_Cardem dfu bootloader
+ * contrib: allow manually forcing bulk simtrace dissection
+ * contrib/jenkins.sh: lower trace to make bl fit
+ * Revert "firmware: data sections"
+ * add the ngff cardem to default build targets
+ * drop unused exidx sections when linking
+ * clang build support
+ * fix bootloader led config crash
+ * firmware: add bootloader update "app"
+ * firmware: remove usb pullup that dates back to simtrace1
+ * firmware: increase reset delay before usb reattach
+ * firmware: drop cref printing
+ * add our default clang-format file
+ * firmware: add missing usb strings to blupdate that prevented building it
+ * jenkins: build bootloader updater
+ * firmware: remove dfu-dfu default target
+
+ [ Oliver Smith ]
+ * contrib: import RPM spec
+ * contrib: integrate RPM spec
+ * d/source/format: new file
+ * firmware/Makefile: fix UNKNOWN in OBS packages
+ * host: use git-version-gen/tarball-v. from topdir
+ * gitignore: add firmware/apps/*/usb_strings.txt.patched
+ * firmware: create duplicate files for upload only
+ * contrib/prepare_upload.sh: fix cd problems
+ * firmware: qmod-dfu: disable stack protector
+ * firmware: disable stack protector by default
+ * gitreview: new file
+
+ [ Leonard Hübner ]
+ * remsim: adding cli argument to set the atr
+
+ [ Eric ]
+ * dfu: let the device reset itself
+
+ -- Harald Welte <laforge@osmocom.org> Thu, 09 Dec 2021 08:12:56 +0100
+
simtrace2 (0.5.1) unstable; urgency=medium
* Backwards-compatibility with older (released, non-master) libosmocore
diff --git a/debian/compat b/debian/compat
index ec63514..f599e28 100644
--- a/debian/compat
+++ b/debian/compat
@@ -1 +1 @@
-9
+10
diff --git a/debian/control b/debian/control
index f30b1d3..cae4e8d 100644
--- a/debian/control
+++ b/debian/control
@@ -1,16 +1,23 @@
Source: simtrace2
-Maintainer: Harald Welte <laforge@gnumonks.org>
+Maintainer: Osmocom team <openbsc@lists.osmocom.org>
Section: devel
Priority: optional
-Build-Depends: debhelper (>= 9),
- libosmocore-dev,
+Build-Depends: debhelper (>= 10),
+ autotools-dev,
+ autoconf,
+ automake,
+ libtool,
+ pkg-config,
+ git,
+ dh-autoreconf,
+ libosmocore-dev (>= 1.4.0),
libpcsclite-dev,
libnewlib-arm-none-eabi,
libusb-1.0-0-dev,
gcc-arm-none-eabi
Standards-Version: 3.9.8
-Vcs-Git: git://git.osmocom.org/simtrace2.git
-Vcs-Browser: http://git.osmocom.org/simtrace2/
+Vcs-Git: https://gitea.osmocom.org/sim-card/simtrace2
+Vcs-Browser: https://gitea.osmocom.org/sim-card/simtrace2
Homepage: http://osmocom.org/projects/simtrace2/wiki
Package: simtrace2-firmware
@@ -26,6 +33,33 @@ Package: simtrace2-utils
Section: devel
Architecture: any
Multi-Arch: same
-Depends: ${shlibs:Depends}, ${misc:Depends}
+Depends: ${shlibs:Depends}, ${misc:Depends}, libosmo-simtrace2-1
Recommends: simtrace2-firmware
Description: Host utilities to communicate with SIMtrace2 USB Devices.
+
+Package: libosmo-simtrace2-1
+Section: libs
+Architecture: any
+Multi-Arch: same
+Depends: ${shlibs:Depends}, ${misc:Depends}
+Description: Osmocom SIMtrace2 library
+ This library contains core "driver" functionality to interface with the
+ Osmocom SIMtrace2 (and compatible) USB device firmware. It enables
+ applications to implement SIM card / smart card tracing as well as
+ SIM / smart card emulation functions.
+
+Package: libosmo-simtrace2-dev
+Section: libdevel
+Architecture: any
+Multi-Arch: same
+Depends: libosmo-simtrace2-1, ${misc:Depends}
+Description: Development headers for Osmocom SIMtrace2 library
+ This library contains core "driver" functionality to interface with the
+ Osmocom SIMtrace2 (and compatible) USB device firmware. It enables
+ applications to implement SIM card / smart card tracing as well as
+ SIM / smart card emulation functions.
+ .
+ The header files provided by this package may be used to develop
+ with any of the libosmocore libraries.
+ .
+ Also static libraries are installed with this package.
diff --git a/debian/libosmo-simtrace2-1.install b/debian/libosmo-simtrace2-1.install
new file mode 100644
index 0000000..383b232
--- /dev/null
+++ b/debian/libosmo-simtrace2-1.install
@@ -0,0 +1 @@
+usr/lib/libosmo-simtrace2*.so.*
diff --git a/debian/libosmo-simtrace2-dev.install b/debian/libosmo-simtrace2-dev.install
new file mode 100644
index 0000000..eec0e15
--- /dev/null
+++ b/debian/libosmo-simtrace2-dev.install
@@ -0,0 +1,5 @@
+usr/include/*
+usr/lib/lib*.a
+usr/lib/lib*.so
+usr/lib/lib*.la
+usr/lib/pkgconfig/*
diff --git a/debian/rules b/debian/rules
index 2d33f6a..37cd4d7 100755
--- a/debian/rules
+++ b/debian/rules
@@ -1,4 +1,16 @@
#!/usr/bin/make -f
+# Uncomment this to turn on verbose mode.
+#export DH_VERBOSE=1
+
+DEBIAN := $(shell dpkg-parsechangelog | grep ^Version: | cut -d' ' -f2)
+DEBVERS := $(shell echo '$(DEBIAN)' | cut -d- -f1)
+VERSION := $(shell echo '$(DEBVERS)' | sed -e 's/[+-].*//' -e 's/~//g')
+
+export DEB_BUILD_MAINT_OPTIONS = hardening=+all
+
+export DEB_LDFLAGS_MAINT_STRIP = -Wl,-Bsymbolic-functions
+
+
%:
- dh $@
+ dh $@ --no-parallel
diff --git a/debian/source/format b/debian/source/format
new file mode 100644
index 0000000..89ae9db
--- /dev/null
+++ b/debian/source/format
@@ -0,0 +1 @@
+3.0 (native)
diff --git a/firmware/Makefile b/firmware/Makefile
index fa72bd3..2f7a370 100644
--- a/firmware/Makefile
+++ b/firmware/Makefile
@@ -28,22 +28,41 @@
# Makefile for compiling the Getting Started with SAM3S Microcontrollers project
+GIT_VERSION=$(shell $(TOP)/git-version-gen $(TOP)/.tarball-version)
+
+CFLAGS = \
+ -Werror=format-security \
+ -Wformat \
+ -g \
+ $(NULL)
+
#-------------------------------------------------------------------------------
# User-modifiable options
#-------------------------------------------------------------------------------
+# verbosity
+V ?= 0
+ifneq ("$(V)","0")
+SILENT :=
+else
+SILENT := @
+endif
+
# Chip & board used for compilation
# (can be overriden by adding CHIP=chip and BOARD=board to the command-line)
CHIP ?= sam3s4
BOARD ?= qmod
-
-# Defines which are the available memory targets for the SAM3S-EK board.
-MEMORIES ?= flash dfu
-
-# Output file basename
APP ?= dfu
-# Output directories
+# Defines which are the available memory targets for the SAM3S-EK board.
+ifeq ($(APP), dfu)
+MEMORIES ?= flash
+TRACE_LEVEL ?= 0
+else
+MEMORIES ?= dfu
+endif
+
+# Output directories and filename
OUTPUT = $(BOARD)-$(APP)
BIN = bin
OBJ = obj/$(BOARD)
@@ -61,19 +80,26 @@ AT91LIB_USB_DFU_PATH = $(AT91LIB)/usb/device/dfu
# Tool suffix when cross-compiling
CROSS_COMPILE = arm-none-eabi-
-LIBS = -Wl,--start-group -lgcc -Wl,--end-group -nostdlib
-
-# Compilation tools
+USE_CLANG ?= 0
+ifneq ("$(USE_CLANG)","0")
+# --target=thumbv7m-none-eabi
+CC = clang
+LD = ld.lld
+SIZE = llvm-size
+LIBS = -nostdlib
+else
CC = $(CROSS_COMPILE)gcc
LD = $(CROSS_COMPILE)ld
SIZE = $(CROSS_COMPILE)size
+LIBS = -Wl,--start-group -lgcc -Wl,--end-group -nostdlib
+endif
+
STRIP = $(CROSS_COMPILE)strip
OBJCOPY = $(CROSS_COMPILE)objcopy
GDB = $(CROSS_COMPILE)gdb
NM = $(CROSS_COMPILE)nm
TOP=..
-GIT_VERSION=$(shell $(TOP)/git-version-gen $(TOP)/.tarvers)
#-------------------------------------------------------------------------------
# Files
@@ -97,10 +123,11 @@ C_LIBCHIP = $(notdir $(wildcard $(AT91LIB)/libchip_sam3s/source/*.c) $(wildcard
C_LIBUSB = USBDescriptors.c USBRequests.c USBD.c USBDCallbacks.c USBDDriver.c USBDDriverCallbacks.c
C_LIBUSB_RT = dfu.c dfu_runtime.c
C_LIBUSB_DFU = dfu.c dfu_desc.c dfu_driver.c
-C_LIBCOMMON = string.c stdio.c fputs.c usb_buf.c ringbuffer.c pseudo_talloc.c host_communication.c
+C_LIBCOMMON = string.c stdio.c fputs.c usb_buf.c ringbuffer.c pseudo_talloc.c host_communication.c \
+ main_common.c stack_check.c crcstub.c
C_BOARD = $(notdir $(wildcard libboard/common/source/*.c))
-C_BOARD += $(notdir $(wildcard libboard/$(BOARD)/source/*.c))
+C_BOARD += $(notdir $(wildcard libboard/$(BOARD)/source/*.c))
C_APPLEVEL = $(notdir $(wildcard apps/$(APP)/*.c))
@@ -124,14 +151,14 @@ TRACE_LEVEL ?= 4
# only applicable for qmod board
ALLOW_PEER_ERASE?=0
-DEBUG_PHONE_SNIFF?=0
-
#CFLAGS+=-DUSB_NO_DEBUG=1
# Optimization level, put in comment for debugging
+ifneq ("$(USE_CLANG)","0")
+OPTIMIZATION ?= -Oz
+else
OPTIMIZATION ?= -Os
-
-
+endif
# Flags
INCLUDES_USB = -I$(AT91LIB)/usb/include -I$(AT91LIB)
@@ -145,6 +172,11 @@ INCLUDES += -Ilibosmocore/include
INCLUDES += -Isrc_simtrace -Iinclude
INCLUDES += -Iapps/$(APP)
+ifneq ("$(USE_CLANG)","0")
+CFLAGS += -Wno-unknown-warning-option -Wno-empty-body -fno-exceptions -fno-unwind-tables --config armv7em_soft_nofp_nosys
+else
+CFLAGS += -Wno-suggest-attribute=noreturn --param max-inline-insns-single=500
+endif
CFLAGS += -Wall -Wchar-subscripts -Wcomment -Wimplicit-int -Wformat=2
CFLAGS += -Werror-implicit-function-declaration -Wmain -Wparentheses
CFLAGS += -Wsequence-point -Wreturn-type -Wswitch -Wtrigraphs #-Wunused
@@ -157,33 +189,43 @@ CFLAGS += -Wredundant-decls -Wnested-externs #-Winline -Wlong-long
CFLAGS += -Wunreachable-code
#CFLAGS += -Wcast-align
#CFLAGS += -std=c11
-CFLAGS += -Wmissing-noreturn
+#CFLAGS += -Wmissing-noreturn
#CFLAGS += -Wconversion
CFLAGS += -Wno-unused-but-set-variable -Wno-unused-variable
-CFLAGS += -Wno-suggest-attribute=noreturn
+
# -mlong-calls -Wall
#CFLAGS += -save-temps -fverbose-asm
#CFLAGS += -Wa,-a,-ad
-CFLAGS += -D__ARM
-CFLAGS += --param max-inline-insns-single=500 -mcpu=cortex-m3 -mthumb # -mfix-cortex-m3-ldrd
-CFLAGS += -ffunction-sections -g $(OPTIMIZATION) $(INCLUDES) -D$(CHIP) -DTRACE_LEVEL=$(TRACE_LEVEL) -DDEBUG_PHONE_SNIFF=$(DEBUG_PHONE_SNIFF) -DALLOW_PEER_ERASE=$(ALLOW_PEER_ERASE)
+CFLAGS += -D__ARM -fno-builtin
+CFLAGS += -mcpu=cortex-m3 -mthumb # -mfix-cortex-m3-ldrd
+CFLAGS += -ffunction-sections -g $(OPTIMIZATION) $(INCLUDES) -D$(CHIP) -DTRACE_LEVEL=$(TRACE_LEVEL) -DALLOW_PEER_ERASE=$(ALLOW_PEER_ERASE)
CFLAGS += -DGIT_VERSION=\"$(GIT_VERSION)\"
CFLAGS += -DBOARD=\"$(BOARD)\" -DBOARD_$(BOARD)
CFLAGS += -DAPPLICATION=\"$(APP)\" -DAPPLICATION_$(APP)
+
+# Disable stack protector by default (OS#5081)
+ifeq ($(STACK_PROTECTOR), 1)
+CFLAGS += -fstack-protector
+else
+CFLAGS += -fno-stack-protector
+endif
+
ASFLAGS = -mcpu=cortex-m3 -mthumb -Wall -g $(OPTIMIZATION) $(INCLUDES) -D$(CHIP) -D__ASSEMBLY__
-LDFLAGS = -mcpu=cortex-m3 -mthumb -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--entry=ResetException -Wl,--unresolved-symbols=report-all -Wl,--warn-common -Wl,--warn-section-align -Wl,--warn-unresolved-symbols $(LIB)
+LDFLAGS = -mcpu=cortex-m3 -mthumb -Wl,--check-sections -Wl,--gc-sections -Wl,--entry=ResetException -Wl,--unresolved-symbols=report-all -Wl,--warn-common -Wl,--no-undefined $(LIB)
+ifeq ("$(USE_CLANG)","0")
+LDFLAGS += -Wl,--warn-section-align -Wl,--print-memory-usage
+endif
#LD_OPTIONAL=-Wl,--print-gc-sections -Wl,--stats
-
-# Append OBJ and BIN directories to output filename
+# Append BIN directories to output filename
OUTPUT := $(BIN)/$(OUTPUT)
#-------------------------------------------------------------------------------
# Rules
#-------------------------------------------------------------------------------
-all: apps/$(APP)/usb_strings_generated.h $(BIN) $(OBJ) $(MEMORIES)
+all: $(BIN) $(OBJ) $(MEMORIES)
combined: $(OUTPUT)-combined.bin
@@ -194,48 +236,97 @@ $(BIN)/$(BOARD)-dfu-flash-padded.bin: $(BIN)/$(BOARD)-dfu-flash.bin
$(OUTPUT)-combined.bin: $(BIN)/$(BOARD)-dfu-flash-padded.bin $(OUTPUT)-dfu.bin
cat $^ > $@
-$(BIN) $(OBJ):
+$(BIN) $(OBJ): apps/$(APP)/usb_strings_generated.h misc/crctool
mkdir -p $@
usbstring/usbstring: usbstring/usbstring.c
gcc $^ -o $@
-apps/$(APP)/usb_strings_generated.h: apps/$(APP)/usb_strings.txt usbstring/usbstring
+misc/crctool: misc/crctool.c
+ gcc $^ -o $@
+
+.PHONY: apps/$(APP)/usb_strings.txt.patched
+apps/$(APP)/usb_strings.txt.patched: apps/$(APP)/usb_strings.txt
+ sed "s/PRODUCT_STRING/$(shell cat libboard/$(BOARD)/product_string.txt)/" $< > $@
+
+apps/$(APP)/usb_strings_generated.h: apps/$(APP)/usb_strings.txt.patched usbstring/usbstring
cat $< | usbstring/usbstring > $@
define RULES
C_OBJECTS_$(1) = $(addprefix $(OBJ)/$(1)_, $(C_OBJECTS))
ASM_OBJECTS_$(1) = $(addprefix $(OBJ)/$(1)_, $(ASM_OBJECTS))
+EXTRA_OBJECTS_$(1) = $(addprefix $(OBJ)/$(1)_, $(EXTRA_OBJECTS))
-$(1): $$(ASM_OBJECTS_$(1)) $$(C_OBJECTS_$(1))
- @$(CC) $(LDFLAGS) $(LD_OPTIONAL) -T"libboard/common/resources/$(CHIP)/$$@.ld" -Wl,-Map,$(OUTPUT)-$$@.map -o $(OUTPUT)-$$@.elf $$^ $(LIBS)
- @$(NM) $(OUTPUT)-$$@.elf >$(OUTPUT)-$$@.elf.txt
- @$(OBJCOPY) -O binary $(OUTPUT)-$$@.elf $(OUTPUT)-$$@.bin
- @$(SIZE) $$^ $(OUTPUT)-$$@.elf
+build_$(1): $$(ASM_OBJECTS_$(1)) $$(C_OBJECTS_$(1)) $$(EXTRA_OBJECTS_$(1))
+ $(SILENT)$(CC) $(CFLAGS) $(LDFLAGS) $(LD_OPTIONAL) -T"libboard/common/resources/$(CHIP)/$(1).ld" -Wl,-Map,$(OUTPUT)-$(1).map -o $(OUTPUT)-$(1).elf $$^ $(LIBS)
+ $(SILENT)$(NM) $(OUTPUT)-$(1).elf >$(OUTPUT)-$(1).elf.txt
+ $(SILENT)$(OBJCOPY) -O binary $(OUTPUT)-$(1).elf $(OUTPUT)-$(1).bin
$$(C_OBJECTS_$(1)): $(OBJ)/$(1)_%.o: %.c Makefile $(OBJ) $(BIN)
@echo [COMPILING $$<]
- @$(CC) $(CFLAGS) -DENVIRONMENT_$(1) -DENVIRONMENT=\"$(1)\" -Wa,-ahlms=$(BIN)/$$*.lst -c -o $$@ $$<
+ $(SILENT)$(CC) $(CFLAGS) -DENVIRONMENT_$(1) -DENVIRONMENT=\"$(1)\" -c -o $$@ $$<
$$(ASM_OBJECTS_$(1)): $(OBJ)/$(1)_%.o: %.S Makefile $(OBJ) $(BIN)
@echo [ASSEMBLING $$@]
- @$(CC) $(ASFLAGS) -DENVIRONMENT_$(1) -DENVIRONMENT=\"$(1)\" -c -o $$@ $$<
+ $(SILENT)$(CC) $(ASFLAGS) -DENVIRONMENT_$(1) -DENVIRONMENT=\"$(1)\" -c -o $$@ $$<
-debug_$(1): $(1)
- $(GDB) -x "$(BOARD_LIB)/resources/gcc/$(BOARD)_$(1).gdb" -ex "reset" -readnow -se $(OUTPUT)-$(1).elf
endef
-$(foreach MEMORY, $(MEMORIES), $(eval $(call RULES,$(MEMORY))))
+ALL_MEMORIES = flash ram
+$(foreach MEMORY, $(ALL_MEMORIES), $(eval $(call RULES,$(MEMORY))))
+
+# files with those names do exist..
+.PHONY: dfu
+dfu: $(OUTPUT)-dfu.bin
+.PHONY: ram
+ram: build_ram
+.PHONY: flash
+flash: build_flash
+#alternate way of embedding: obj file
+#ifeq ($(APP), dfu)
+# $(info bootloader bin file to obj..)
+# $(SILENT)$(OBJCOPY) --rename-section .data=.fwupdate -I binary -O elf32-littlearm bin/$(BOARD)-dfu-flash.bin $(OBJ)/flash_fwupdate.o
+#endif
+
+C_OBJECTS_dfu = $(addprefix $(OBJ)/dfu_, $(C_OBJECTS))
+ASM_OBJECTS_dfu = $(addprefix $(OBJ)/dfu_, $(ASM_OBJECTS))
+EXTRA_OBJECTS_dfu = $(addprefix $(OBJ)/dfu_, $(EXTRA_OBJECTS))
+
+$(OUTPUT)-dfu.bin: $(OUTPUT)-dfu_nocrcstub.bin
+ $(info updating app with crc..)
+ $(SILENT)cp $< $@.temp
+ $(SILENT)misc/crctool 512 $@.temp
+ $(SILENT)mv $@.temp $@
+
+$(OUTPUT)-dfu_nocrcstub.bin: $(OUTPUT)-dfu_nocrcstub.elf
+ifeq ($(APP), blupdate)
+ $(info updating updater section with padded bootloader file..)
+ $(SILENT)dd status=none if=/dev/zero bs=16384 count=1 of=$(BIN)/$(BOARD)-dfu-flash-padded.bin
+ $(SILENT)dd status=none if=$(BIN)/$(BOARD)-dfu-flash.bin conv=notrunc of=$(BIN)/$(BOARD)-dfu-flash-padded.bin
+ $(SILENT)$(OBJCOPY) --update-section .blupdate=bin/$(BOARD)-dfu-flash-padded.bin $<
+endif
+ $(SILENT)$(OBJCOPY) -O binary $< $@
+
+$(OUTPUT)-dfu_nocrcstub.elf: $(ASM_OBJECTS_dfu) $(C_OBJECTS_dfu) $(EXTRA_OBJECTS_dfu)
+ $(SILENT)$(CC) $(CFLAGS) $(LDFLAGS) $(LD_OPTIONAL) -T"libboard/common/resources/$(CHIP)/dfu.ld" -Wl,-Map,$(OUTPUT)-dfu_nocrcstub.map -o $@ $^ $(LIBS)
+ $(SILENT)$(NM) $@ >$@.txt
+
+$(C_OBJECTS_dfu): $(OBJ)/dfu_%.o: %.c Makefile $(OBJ) $(BIN)
+ @echo [COMPILING $<]
+ $(SILENT)$(CC) $(CFLAGS) -DENVIRONMENT_dfu -DENVIRONMENT=\"dfu\" -c -o $@ $<
+
+$(ASM_OBJECTS_dfu): $(OBJ)/dfu_%.o: %.S Makefile $(OBJ) $(BIN)
+ @echo [ASSEMBLING $@]
+ $(SILENT)$(CC) $(ASFLAGS) -DENVIRONMENT_dfu -DENVIRONMENT=\"dfu\" -c -o$@ $<
-program:
- openocd -f openocd/openocd.cfg -c "init" -c "halt" -c "flash write_bank 0 ./bin/project-flash.bin 0" -c "reset" -c "shutdown"
SERIAL ?= /dev/ttyUSB0
log:
- stty -F $(SERIAL) 115200
+ stty -F $(SERIAL) 921600
lsof $(SERIAL) && echo "log is already opened" || ( sed -u "s/\r//" $(SERIAL) | ts )
clean:
+ -rm -f apps/$(APP)/usb_strings.txt.patched
-rm -fR $(OBJ)/*.o $(BIN)/*.bin $(BIN)/*.elf $(BIN)/*.elf.txt $(BIN)/*.map $(BIN)/*.lst `find . -name \*.p`
install:
diff --git a/firmware/README.txt b/firmware/README.txt
index fa7f60a..cd04e7a 100644
--- a/firmware/README.txt
+++ b/firmware/README.txt
@@ -24,6 +24,7 @@ Current boards supported are:
* `simtrace`: The good old Osmocom SIMtrace PCB with SAM3 instead of SAM7, open hardware.
* `qmod`: A sysmocom-proprietary quad mPCIe carrier board, publicly available
* `owhw`: An undisclosed sysmocom-internal board, not publicly available
+* `octsimtest`: A sysmocom-proprietary production testing board, not publicly available
= Firmware
@@ -51,6 +52,7 @@ Current applications supported are:
* `cardem`: To provide remote SIM operation capabilities.
* `trace`: To monitor the communication between a SIM card and a phone (corresponds to the functionality provide by the first SIMtrace)
* `triple_play`: To support the three previous functionalities, using USB configurations.
+* `gpio_test`: internal test code
== Memories
diff --git a/firmware/apps/blupdate/Makefile b/firmware/apps/blupdate/Makefile
new file mode 100644
index 0000000..4f1d377
--- /dev/null
+++ b/firmware/apps/blupdate/Makefile
@@ -0,0 +1,12 @@
+
+C_FILES += $(C_LIBUSB_DFU)
+
+# Trace level used for compilation
+# (can be overridden by adding TRACE_LEVEL=#number to the command-line)
+# TRACE_LEVEL_DEBUG 5
+# TRACE_LEVEL_INFO 4
+# TRACE_LEVEL_WARNING 3
+# TRACE_LEVEL_ERROR 2
+# TRACE_LEVEL_FATAL 1
+# TRACE_LEVEL_NO_TRACE 0
+TRACE_LEVEL ?= 3
diff --git a/firmware/apps/blupdate/main.c b/firmware/apps/blupdate/main.c
new file mode 100644
index 0000000..8c48e37
--- /dev/null
+++ b/firmware/apps/blupdate/main.c
@@ -0,0 +1,136 @@
+/* SIMtrace 2 firmware USB DFU bootloader
+ *
+ * (C) 2015-2017 by Harald Welte <hwelte@hmw-consulting.de>
+ * (C) 2018-2019 by sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon@sysmocom.de>
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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.
+ */
+#include "board.h"
+#include "core_cm3.h"
+#include "flashd.h"
+#include "utils.h"
+#include "usb/device/dfu/dfu.h"
+#include "usb/common/dfu/usb_dfu.h"
+#include "manifest.h"
+#include "USBD_HAL.h"
+
+#include <osmocom/core/timer.h>
+
+/* actual section content must be replaced with the padded bootloader by running objcopy! */
+const uint32_t bl_update_data[BOARD_DFU_BOOT_SIZE / sizeof(uint32_t)] __attribute__((section(".fwupdate"))) = { 0xFF };
+
+unsigned int g_unique_id[4];
+/* remember if the watchdog has been configured in the main loop so we can kick it in the ISR */
+static bool watchdog_configured = false;
+
+extern uint32_t _end;
+extern uint32_t _srelocate;
+extern uint32_t _etext;
+
+void DFURT_SwitchToDFU(void)
+{
+}
+void USBDFU_Runtime_RequestHandler(const USBGenericRequest *request)
+{
+}
+int USBDFU_handle_dnload(uint8_t altif, unsigned int offset, uint8_t *data, unsigned int len)
+{
+ return 0;
+}
+int USBDFU_handle_upload(uint8_t altif, unsigned int offset, uint8_t *data, unsigned int req_len)
+{
+ return 0;
+}
+int USBDFU_OverrideEnterDFU(void)
+{
+ return 0;
+}
+
+__attribute__((section(".ramfunc"), noinline)) static uint32_t flash_wait_ready()
+{
+ Efc *efc = EFC;
+ uint32_t dwStatus;
+
+ do {
+ dwStatus = efc->EEFC_FSR;
+ } while ((dwStatus & EEFC_FSR_FRDY) != EEFC_FSR_FRDY);
+ return (dwStatus & (EEFC_FSR_FLOCKE | EEFC_FSR_FCMDE));
+}
+
+__attribute__((section(".ramfunc"), noinline)) static void flash_cmd(uint32_t dwCommand, uint32_t dwArgument)
+{
+ Efc *efc = EFC;
+ uint32_t dwStatus;
+ efc->EEFC_FCR = EEFC_FCR_FKEY(0x5A) | EEFC_FCR_FARG(dwArgument) | EEFC_FCR_FCMD(dwCommand);
+}
+
+__attribute__((section(".ramfunc"), noinline, noreturn)) static void erase_first_app_sector()
+{
+ /* page 64 */
+ uint32_t first_app_page = (BOARD_DFU_BOOT_SIZE / IFLASH_PAGE_SIZE);
+ uint32_t *first_app_address = (uint32_t *)(IFLASH_ADDR + first_app_page * IFLASH_PAGE_SIZE + 0);
+
+#if 1
+ /* overwrite first app sector so we don't keep booting this */
+ for (int i = 0; i < IFLASH_PAGE_SIZE / 4; i++)
+ first_app_address[i] = 0xffffffff;
+
+ flash_cmd(EFC_FCMD_EWP, first_app_page);
+#else
+ /* why does erasing the whole flash with a protected bootloader not work at all? */
+ flash_cmd(EFC_FCMD_EA, 0);
+#endif
+ flash_wait_ready();
+ for (;;) {
+ /* no functon call, since NVIC_SystemReset() might not be inlined! */
+ SCB->AIRCR = ((0x5FA << SCB_AIRCR_VECTKEY_Pos) | (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) |
+ SCB_AIRCR_SYSRESETREQ_Msk);
+ __DSB();
+ while (1)
+ ;
+ }
+}
+
+#define MAX_USB_ITER BOARD_MCK / 72 // This should be around a second
+extern int main(void)
+{
+ uint8_t isUsbConnected = 0;
+ unsigned int i = 0;
+ uint32_t reset_cause = (RSTC->RSTC_SR & RSTC_SR_RSTTYP_Msk) >> RSTC_SR_RSTTYP_Pos;
+
+ /* Enable watchdog for 2000ms, with no window */
+ WDT_Enable(WDT, WDT_MR_WDRSTEN | WDT_MR_WDDBGHLT | WDT_MR_WDIDLEHLT | (WDT_GetPeriod(2000) << 16) |
+ WDT_GetPeriod(2000));
+ watchdog_configured = true;
+
+ EEFC_ReadUniqueID(g_unique_id);
+
+ printf("\n\r\n\r");
+ printf("bootloader updater %s for board %s\n\r"
+ "(C) 2010-2017 by Harald Welte, 2018-2019 by Kevin Redon\n\r",
+ manifest_revision, manifest_board);
+
+ /* clear g_dfu on power-up reset */
+ memset(g_dfu, 0, sizeof(*g_dfu));
+
+ TRACE_INFO("USB init...\n\r");
+ /* Signal USB reset by disabling the pull-up on USB D+ for at least 10 ms */
+ USBD_Disconnect();
+
+ /* Initialize the flash to be able to write it, using the IAP ROM code */
+ FLASHD_Initialize(BOARD_MCK, 1);
+
+ __disable_irq();
+ FLASHD_Unlock(IFLASH_ADDR, IFLASH_ADDR + IFLASH_SIZE - 1, 0, 0);
+ FLASHD_Write(IFLASH_ADDR, bl_update_data, BOARD_DFU_BOOT_SIZE);
+
+ erase_first_app_sector();
+}
diff --git a/firmware/apps/blupdate/usb_strings.txt b/firmware/apps/blupdate/usb_strings.txt
new file mode 100644
index 0000000..f652071
--- /dev/null
+++ b/firmware/apps/blupdate/usb_strings.txt
@@ -0,0 +1,6 @@
+sysmocom - s.f.m.c. GmbH
+PRODUCT_STRING
+bootloader updater
+RAM
+Flash (Application Partition)
+Flash (Bootloader Partition)
diff --git a/firmware/apps/cardem/Makefile b/firmware/apps/cardem/Makefile
index 75c43e8..c0d903f 100644
--- a/firmware/apps/cardem/Makefile
+++ b/firmware/apps/cardem/Makefile
@@ -1,3 +1,3 @@
C_FILES += $(C_LIBUSB_RT)
-C_FILES += card_emu.c cciddriver.c iso7816_4.c iso7816_fidi.c mitm.c mode_cardemu.c mode_ccid.c simtrace_iso7816.c sniffer.c tc_etu.c usb.c
+C_FILES += card_emu.c cciddriver.c iso7816_4.c iso7816_fidi.c mitm.c mode_cardemu.c mode_ccid.c simtrace_iso7816.c sniffer.c usb.c
diff --git a/firmware/apps/cardem/main.c b/firmware/apps/cardem/main.c
index 209c79f..6372e04 100644
--- a/firmware/apps/cardem/main.c
+++ b/firmware/apps/cardem/main.c
@@ -1,7 +1,7 @@
/* SIMtrace 2 firmware card emulation application
*
* (C) 2015-2017 by Harald Welte <hwelte@hmw-consulting.de>
- * (C) 2018, sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon@sysmocom.de>
+ * (C) 2018-2019, sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon@sysmocom.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -12,10 +12,6 @@
* 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 this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*------------------------------------------------------------------------------
* Headers
@@ -24,10 +20,9 @@
#include "board.h"
#include "simtrace.h"
#include "utils.h"
+#include "main_common.h"
#include <osmocom/core/timer.h>
-unsigned int g_unique_id[4];
-
/*------------------------------------------------------------------------------
* Internal variables
*------------------------------------------------------------------------------*/
@@ -40,7 +35,7 @@ typedef struct {
void (*exit) (void);
/* main loop content for given configuration */
void (*run) (void);
- /* Interrupt handler for USART1 */
+ /* Interrupt handler for USART0 */
void (*usart0_irq) (void);
/* Interrupt handler for USART1 */
void (*usart1_irq) (void);
@@ -54,6 +49,8 @@ static const conf_func config_func_ptrs[] = {
.init = Sniffer_init,
.exit = Sniffer_exit,
.run = Sniffer_run,
+ .usart0_irq = Sniffer_usart0_irq,
+ .usart1_irq = Sniffer_usart1_irq,
},
#endif
#ifdef HAVE_CCID
@@ -70,8 +67,13 @@ static const conf_func config_func_ptrs[] = {
.init = mode_cardemu_init,
.exit = mode_cardemu_exit,
.run = mode_cardemu_run,
+#if defined (ngff_cardem)
+ .usart0_irq = mode_cardemu_usart1_irq,
+ .usart1_irq = mode_cardemu_usart0_irq,
+#else
.usart0_irq = mode_cardemu_usart0_irq,
.usart1_irq = mode_cardemu_usart1_irq,
+#endif
},
#endif
#ifdef HAVE_MITM
@@ -146,41 +148,16 @@ extern int main(void)
unsigned int i = 0;
led_init();
- led_blink(LED_RED, BLINK_3O_5F);
+ led_blink(LED_RED, BLINK_ALWAYS_ON);
+ led_blink(LED_GREEN, BLINK_ALWAYS_ON);
/* Enable watchdog for 2000ms, with no window */
WDT_Enable(WDT, WDT_MR_WDRSTEN | WDT_MR_WDDBGHLT | WDT_MR_WDIDLEHLT |
(WDT_GetPeriod(2000) << 16) | WDT_GetPeriod(2000));
- PIO_InitializeInterrupts(0);
-
- EEFC_ReadUniqueID(g_unique_id);
-
- printf("\n\r\n\r"
- "=============================================================================\n\r"
- "SIMtrace2 firmware " GIT_VERSION " (C) 2010-2016 by Harald Welte\n\r"
- "=============================================================================\n\r");
-
-#if (TRACE_LEVEL >= TRACE_LEVEL_INFO)
- TRACE_INFO("Chip ID: 0x%08lx (Ext 0x%08lx)\n\r", CHIPID->CHIPID_CIDR, CHIPID->CHIPID_EXID);
- TRACE_INFO("Serial Nr. %08x-%08x-%08x-%08x\n\r",
- g_unique_id[0], g_unique_id[1],
- g_unique_id[2], g_unique_id[3]);
- uint8_t reset_cause = (RSTC->RSTC_SR & RSTC_SR_RSTTYP_Msk) >> RSTC_SR_RSTTYP_Pos;
- static const char* reset_causes[] = {
- "general reset (first power-up reset)",
- "backup reset (return from backup mode)",
- "watchdog reset (watchdog fault occurred)",
- "software reset (processor reset required by the software)",
- "user reset (NRST pin detected low)",
- };
- if (reset_cause < ARRAY_SIZE(reset_causes)) {
- TRACE_INFO("Reset Cause: %s\n\r", reset_causes[reset_cause]);
- } else {
- TRACE_INFO("Reset Cause: 0x%lx\n\r", (RSTC->RSTC_SR & RSTC_SR_RSTTYP_Msk) >> RSTC_SR_RSTTYP_Pos);
- }
-#endif
+ PIO_InitializeInterrupts(10);
+ print_banner();
board_main_top();
TRACE_INFO("USB init...\n\r");
@@ -201,8 +178,7 @@ extern int main(void)
}
TRACE_INFO("calling configure of all configurations...\n\r");
- for (i = 1; i < sizeof(config_func_ptrs) / sizeof(config_func_ptrs[0]);
- ++i) {
+ for (i = 1; i < ARRAY_SIZE(config_func_ptrs); i++) {
if (config_func_ptrs[i].configure)
config_func_ptrs[i].configure();
}
@@ -218,8 +194,8 @@ extern int main(void)
WDT_Restart(WDT);
#if TRACE_LEVEL >= TRACE_LEVEL_DEBUG
const char rotor[] = { '-', '\\', '|', '/' };
- putchar('\b');
putchar(rotor[i++ % ARRAY_SIZE(rotor)]);
+ putchar('\b');
#endif
check_exec_dbg_cmd();
osmo_timers_prepare();
@@ -230,6 +206,10 @@ extern int main(void)
if (isUsbConnected) {
isUsbConnected = 0;
}
+ /* HACK: we don't really deal with USB disconnect yet,
+ * so let's just reset the entire uC if this happens */
+ TRACE_INFO("Resetting uC on USB disconnect\n\r");
+ NVIC_SystemReset();
} else if (isUsbConnected == 0) {
TRACE_INFO("USB is now configured\n\r");
diff --git a/firmware/apps/cardem/usb_strings.txt b/firmware/apps/cardem/usb_strings.txt
index 0e797ac..3a1bcc3 100644
--- a/firmware/apps/cardem/usb_strings.txt
+++ b/firmware/apps/cardem/usb_strings.txt
@@ -1,8 +1,8 @@
sysmocom - s.f.m.c. GmbH
-SIMtrace 2 compatible device
+PRODUCT_STRING
SIMtrace Sniffer
SIMtrace CCID
-SIMtrace Phone
+SIMtrace Card Emulation
SIMtrace MITM
CardEmulator Modem 1
CardEmulator Modem 2
diff --git a/firmware/apps/dfu/main.c b/firmware/apps/dfu/main.c
index f9b6aed..ef58ec2 100644
--- a/firmware/apps/dfu/main.c
+++ b/firmware/apps/dfu/main.c
@@ -1,7 +1,7 @@
/* SIMtrace 2 firmware USB DFU bootloader
*
* (C) 2015-2017 by Harald Welte <hwelte@hmw-consulting.de>
- * (C) 2018 by sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon@sysmocom.de>
+ * (C) 2018-2019 by sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon@sysmocom.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -12,10 +12,6 @@
* 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 this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "board.h"
#include "utils.h"
@@ -26,8 +22,15 @@
#include <osmocom/core/timer.h>
+/* USB alternate interface index used to identify which partition to flash */
+/** USB alternate interface index indicating RAM partition */
#define ALTIF_RAM 0
+/** USB alternate interface index indicating flash partition */
+#if defined(ENVIRONMENT_flash)
#define ALTIF_FLASH 1
+#elif defined(ENVIRONMENT_dfu)
+#define ALTIF_FLASH 2
+#endif
unsigned int g_unique_id[4];
/* remember if the watchdog has been configured in the main loop so we can kick it in the ISR */
@@ -44,10 +47,18 @@ static const Pin pinsLeds[] = { PINS_LEDS } ;
*----------------------------------------------------------------------------*/
#define RAM_ADDR(offset) (IRAM_ADDR + BOARD_DFU_RAM_SIZE + offset)
+#if defined(ENVIRONMENT_flash)
#define FLASH_ADDR(offset) (IFLASH_ADDR + BOARD_DFU_BOOT_SIZE + offset)
+#elif defined(ENVIRONMENT_dfu)
+#define FLASH_ADDR(offset) (IFLASH_ADDR + offset)
+#endif
-#define IFLASH_END ((uint8_t *)IFLASH_ADDR + IFLASH_SIZE)
-#define IRAM_END ((uint8_t *)IRAM_ADDR + IRAM_SIZE)
+#define IRAM_END ((uint8_t *)IRAM_ADDR + IRAM_SIZE)
+#if defined(ENVIRONMENT_flash)
+#define IFLASH_END ((uint8_t *)IFLASH_ADDR + IFLASH_SIZE)
+#elif defined(ENVIRONMENT_dfu)
+#define IFLASH_END ((uint8_t *)IFLASH_ADDR + BOARD_DFU_BOOT_SIZE)
+#endif
/* incoming call-back: Host has transferred 'len' bytes (stored at
* 'data'), which we shall write to 'offset' into the partition
@@ -66,7 +77,11 @@ int USBDFU_handle_dnload(uint8_t altif, unsigned int offset,
WDT_Restart(WDT);
}
- printf("dnload(altif=%u, offset=%u, len=%u)\n\r", altif, offset, len);
+#if TRACE_LEVEL >= TRACE_LEVEL_INFO
+ TRACE_INFO("dnload(altif=%u, offset=%u, len=%u)\n\r", altif, offset, len);
+#else
+ printf("DL off=%u\n\r", offset);
+#endif
#ifdef PINS_LEDS
PIO_Clear(&pinsLeds[LED_NUM_RED]);
@@ -86,7 +101,11 @@ int USBDFU_handle_dnload(uint8_t altif, unsigned int offset,
break;
case ALTIF_FLASH:
addr = FLASH_ADDR(offset);
+#if defined(ENVIRONMENT_flash)
if (addr < IFLASH_ADDR || addr + len >= IFLASH_ADDR + IFLASH_SIZE) {
+#elif defined(ENVIRONMENT_dfu)
+ if (addr < IFLASH_ADDR || addr + len >= IFLASH_ADDR + BOARD_DFU_BOOT_SIZE) {
+#endif
g_dfu->state = DFU_STATE_dfuERROR;
g_dfu->status = DFU_STATUS_errADDRESS;
rc = DFU_RET_STALL;
@@ -220,6 +239,17 @@ static void check_exec_dbg_cmd(void)
//board_exec_dbg_cmd(ch);
}
+/* print a horizontal line of '=' characters; Doing this in a loop vs. using a 'const'
+ * string saves us ~60 bytes of executable size (matters particularly for DFU loader) */
+static void print_line(void)
+{
+ int i;
+ for (i = 0; i < 78; i++)
+ fputc('=', stdout);
+ fputc('\n', stdout);
+ fputc('\r', stdout);
+}
+
/*------------------------------------------------------------------------------
* Main
*------------------------------------------------------------------------------*/
@@ -237,38 +267,50 @@ extern int main(void)
#ifdef PINS_LEDS
/* Configure LED */
- PIO_Configure(pinsLeds, sizeof(pinsLeds));
+ PIO_Configure(pinsLeds, PIO_LISTSIZE(pinsLeds));
PIO_Set(&pinsLeds[LED_NUM_RED]);
PIO_Clear(&pinsLeds[LED_NUM_GREEN]);
#endif
- PIO_InitializeInterrupts(0);
-
EEFC_ReadUniqueID(g_unique_id);
- printf("\n\r\n\r"
- "=============================================================================\n\r"
- "DFU bootloader %s for board %s (C) 2010-2017 by Harald Welte\n\r"
- "=============================================================================\n\r",
+ printf("\n\r\n\r");
+ print_line();
+ printf("DFU bootloader %s for board %s\n\r"
+ "(C) 2010-2017 by Harald Welte, 2018-2019 by Kevin Redon\n\r",
manifest_revision, manifest_board);
+ print_line();
- TRACE_INFO("Chip ID: 0x%08x (Ext 0x%08x)\n\r", CHIPID->CHIPID_CIDR, CHIPID->CHIPID_EXID);
+#if (TRACE_LEVEL >= TRACE_LEVEL_INFO)
+ TRACE_INFO("Chip ID: 0x%08lx (Ext 0x%08lx)\n\r", CHIPID->CHIPID_CIDR, CHIPID->CHIPID_EXID);
TRACE_INFO("Serial Nr. %08x-%08x-%08x-%08x\n\r",
g_unique_id[0], g_unique_id[1],
g_unique_id[2], g_unique_id[3]);
- TRACE_INFO("Reset Cause: 0x%lx\n\r", reset_cause);
+ static const char* reset_causes[] = {
+ "general reset (first power-up reset)",
+ "backup reset (return from backup mode)",
+ "watchdog reset (watchdog fault occurred)",
+ "software reset (processor reset required by the software)",
+ "user reset (NRST pin detected low)",
+ };
+ if (reset_cause < ARRAY_SIZE(reset_causes)) {
+ TRACE_INFO("Reset Cause: %s\n\r", reset_causes[reset_cause]);
+ } else {
+ TRACE_INFO("Reset Cause: 0x%lx\n\r", (RSTC->RSTC_SR & RSTC_SR_RSTTYP_Msk) >> RSTC_SR_RSTTYP_Pos);
+ }
+#endif
#if (TRACE_LEVEL >= TRACE_LEVEL_INFO)
/* Find out why we are in the DFU bootloader, and not the main application */
TRACE_INFO("DFU bootloader start reason: ");
switch (USBDFU_OverrideEnterDFU()) {
case 0:
- /* 0 normally means that there is no override, but we are in the bootloader,
- * thus the first check in board_cstartup_gnu did return something else than 0.
- * this can only be g_dfu->magic which is erased when the segment are
- * relocated, which happens in board_cstartup_gnu just after USBDFU_OverrideEnterDFU.
- * no static variable can be used to store this case since this will also be overwritten
- */
+ if (SCB->VTOR < IFLASH_ADDR + BOARD_DFU_BOOT_SIZE) {
+ TRACE_INFO_WP("unknown\n\r");
+ } else {
+ TRACE_INFO_WP("DFU is the main application\n\r");
+ }
+ break;
case 1:
TRACE_INFO_WP("DFU switch requested by main application\n\r");
break;
@@ -295,18 +337,8 @@ extern int main(void)
TRACE_INFO("USB init...\n\r");
/* Signal USB reset by disabling the pull-up on USB D+ for at least 10 ms */
-#ifdef PIN_USB_PULLUP
- const Pin usb_dp_pullup = PIN_USB_PULLUP;
- PIO_Configure(&usb_dp_pullup, 1);
- PIO_Set(&usb_dp_pullup);
-#endif
- USBD_HAL_Suspend();
- mdelay(20);
-#ifdef PIN_USB_PULLUP
- PIO_Clear(&usb_dp_pullup);
-#endif
- USBD_HAL_Activate();
-
+ USBD_Disconnect();
+ mdelay(500);
USBDFU_Initialize(&dfu_descriptors);
while (USBD_GetState() < USBD_STATE_CONFIGURED) {
@@ -314,8 +346,8 @@ extern int main(void)
check_exec_dbg_cmd();
#if 1
if (i >= MAX_USB_ITER * 3) {
- TRACE_ERROR("Resetting board (USB could "
- "not be configured)\n\r");
+ TRACE_ERROR("Resetting board (USB could not be configured)\n\r");
+ g_dfu->magic = USB_DFU_MAGIC; // start the bootloader after reboot
USBD_Disconnect();
NVIC_SystemReset();
}
diff --git a/firmware/apps/dfu/usb_strings.txt b/firmware/apps/dfu/usb_strings.txt
index 8a4facb..4a58cb8 100644
--- a/firmware/apps/dfu/usb_strings.txt
+++ b/firmware/apps/dfu/usb_strings.txt
@@ -1,5 +1,6 @@
sysmocom - s.f.m.c. GmbH
-SIMtrace 2 compatible device
+PRODUCT_STRING
DFU (Device Firmware Upgrade)
RAM
Flash (Application Partition)
+Flash (Bootloader Partition)
diff --git a/firmware/apps/freq_ctr/usb_strings.txt b/firmware/apps/freq_ctr/usb_strings.txt
index 0e797ac..3a1bcc3 100644
--- a/firmware/apps/freq_ctr/usb_strings.txt
+++ b/firmware/apps/freq_ctr/usb_strings.txt
@@ -1,8 +1,8 @@
sysmocom - s.f.m.c. GmbH
-SIMtrace 2 compatible device
+PRODUCT_STRING
SIMtrace Sniffer
SIMtrace CCID
-SIMtrace Phone
+SIMtrace Card Emulation
SIMtrace MITM
CardEmulator Modem 1
CardEmulator Modem 2
diff --git a/firmware/apps/gpio_test/Makefile b/firmware/apps/gpio_test/Makefile
new file mode 100644
index 0000000..b2b4707
--- /dev/null
+++ b/firmware/apps/gpio_test/Makefile
@@ -0,0 +1,3 @@
+C_FILES += $(C_LIBUSB_RT)
+
+C_FILES += gpio_test.c
diff --git a/firmware/apps/gpio_test/gpio_test.c b/firmware/apps/gpio_test/gpio_test.c
new file mode 100644
index 0000000..a6b0a00
--- /dev/null
+++ b/firmware/apps/gpio_test/gpio_test.c
@@ -0,0 +1,8 @@
+#include <stdint.h>
+#include "utils.h"
+#include "chip.h"
+
+void gpio_test_init(void)
+{
+ printf("FIXME run tests here\n\r");
+}
diff --git a/firmware/apps/gpio_test/main.c b/firmware/apps/gpio_test/main.c
new file mode 100644
index 0000000..8fe68b3
--- /dev/null
+++ b/firmware/apps/gpio_test/main.c
@@ -0,0 +1,54 @@
+
+#include "board.h"
+#include "utils.h"
+#include "osmocom/core/timer.h"
+
+extern void gpio_test_init(void);
+
+/* returns '1' in case we should break any endless loop */
+static void check_exec_dbg_cmd(void)
+{
+ int ch;
+
+ if (!UART_IsRxReady())
+ return;
+
+ ch = UART_GetChar();
+
+ board_exec_dbg_cmd(ch);
+}
+
+
+extern int main(void)
+{
+ led_init();
+ led_blink(LED_RED, BLINK_ALWAYS_ON);
+ led_blink(LED_GREEN, BLINK_ALWAYS_ON);
+
+ /* Enable watchdog for 2000 ms, with no window */
+ WDT_Enable(WDT, WDT_MR_WDRSTEN | WDT_MR_WDDBGHLT | WDT_MR_WDIDLEHLT |
+ (WDT_GetPeriod(2000) << 16) | WDT_GetPeriod(2000));
+
+ PIO_InitializeInterrupts(0);
+
+
+ printf("\n\r\n\r"
+ "=============================================================================\n\r"
+ "GPIO Test firmware " GIT_VERSION " (C) 2019 Sysmocom GmbH\n\r"
+ "=============================================================================\n\r");
+
+ board_main_top();
+
+ TRACE_INFO("starting gpio test...\n\r");
+ gpio_test_init();
+
+ TRACE_INFO("entering main loop...\n\r");
+ while (1) {
+ WDT_Restart(WDT);
+
+ check_exec_dbg_cmd();
+ osmo_timers_prepare();
+ osmo_timers_update();
+ }
+
+}
diff --git a/firmware/apps/gpio_test/usb_strings.txt b/firmware/apps/gpio_test/usb_strings.txt
new file mode 100644
index 0000000..3a1bcc3
--- /dev/null
+++ b/firmware/apps/gpio_test/usb_strings.txt
@@ -0,0 +1,10 @@
+sysmocom - s.f.m.c. GmbH
+PRODUCT_STRING
+SIMtrace Sniffer
+SIMtrace CCID
+SIMtrace Card Emulation
+SIMtrace MITM
+CardEmulator Modem 1
+CardEmulator Modem 2
+CardEmulator Modem 3
+CardEmulator Modem 4
diff --git a/firmware/apps/trace/Makefile b/firmware/apps/trace/Makefile
index 75c43e8..c0d903f 100644
--- a/firmware/apps/trace/Makefile
+++ b/firmware/apps/trace/Makefile
@@ -1,3 +1,3 @@
C_FILES += $(C_LIBUSB_RT)
-C_FILES += card_emu.c cciddriver.c iso7816_4.c iso7816_fidi.c mitm.c mode_cardemu.c mode_ccid.c simtrace_iso7816.c sniffer.c tc_etu.c usb.c
+C_FILES += card_emu.c cciddriver.c iso7816_4.c iso7816_fidi.c mitm.c mode_cardemu.c mode_ccid.c simtrace_iso7816.c sniffer.c usb.c
diff --git a/firmware/apps/trace/main.c b/firmware/apps/trace/main.c
index 97455fb..ec84b5a 100644
--- a/firmware/apps/trace/main.c
+++ b/firmware/apps/trace/main.c
@@ -12,10 +12,6 @@
* 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 this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/*------------------------------------------------------------------------------
* Headers
@@ -24,10 +20,9 @@
#include "board.h"
#include "simtrace.h"
#include "utils.h"
+#include "main_common.h"
#include "osmocom/core/timer.h"
-unsigned int g_unique_id[4];
-
/*------------------------------------------------------------------------------
* Internal variables
*------------------------------------------------------------------------------*/
@@ -158,20 +153,7 @@ extern int main(void)
PIO_InitializeInterrupts(0);
- EEFC_ReadUniqueID(g_unique_id);
-
- printf("\n\r\n\r"
- "=============================================================================\n\r"
- "SIMtrace2 firmware " GIT_VERSION " (C) 2010-2016 by Harald Welte\n\r"
- "=============================================================================\n\r");
-
- TRACE_INFO("Chip ID: 0x%08lx (Ext 0x%08lx)\n\r", CHIPID->CHIPID_CIDR, CHIPID->CHIPID_EXID);
- TRACE_INFO("Serial Nr. %08x-%08x-%08x-%08x\n\r",
- g_unique_id[0], g_unique_id[1],
- g_unique_id[2], g_unique_id[3]);
- TRACE_INFO("Reset Cause: 0x%lx\n\r", (RSTC->RSTC_SR & RSTC_SR_RSTTYP_Msk) >> RSTC_SR_RSTTYP_Pos);
- TRACE_INFO("USB configuration used: %d\n\r", simtrace_config);
-
+ print_banner();
board_main_top();
TRACE_INFO("USB init...\n\r");
diff --git a/firmware/apps/trace/usb_strings.txt b/firmware/apps/trace/usb_strings.txt
index 0e797ac..3a1bcc3 100644
--- a/firmware/apps/trace/usb_strings.txt
+++ b/firmware/apps/trace/usb_strings.txt
@@ -1,8 +1,8 @@
sysmocom - s.f.m.c. GmbH
-SIMtrace 2 compatible device
+PRODUCT_STRING
SIMtrace Sniffer
SIMtrace CCID
-SIMtrace Phone
+SIMtrace Card Emulation
SIMtrace MITM
CardEmulator Modem 1
CardEmulator Modem 2
diff --git a/firmware/apps/triple_play/Makefile b/firmware/apps/triple_play/Makefile
index df89448..be06c11 100644
--- a/firmware/apps/triple_play/Makefile
+++ b/firmware/apps/triple_play/Makefile
@@ -1,3 +1,3 @@
C_FILES += $(C_LIBUSB_RT)
-C_FILES += card_emu.c iso7816_4.c iso7816_fidi.c mitm.c mode_cardemu.c mode_ccid.c simtrace_iso7816.c sniffer.c tc_etu.c usb.c
+C_FILES += card_emu.c iso7816_4.c iso7816_fidi.c mitm.c mode_cardemu.c mode_ccid.c simtrace_iso7816.c sniffer.c usb.c
diff --git a/firmware/apps/triple_play/main.c b/firmware/apps/triple_play/main.c
index b81abdd..b853cdb 100644
--- a/firmware/apps/triple_play/main.c
+++ b/firmware/apps/triple_play/main.c
@@ -11,10 +11,6 @@
* 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 this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*------------------------------------------------------------------------------
* Headers
@@ -26,8 +22,6 @@
#include "req_ctx.h"
#include <osmocom/core/timer.h>
-unsigned int g_unique_id[4];
-
/*------------------------------------------------------------------------------
* Internal variables
*------------------------------------------------------------------------------*/
@@ -149,17 +143,7 @@ extern int main(void)
PIO_InitializeInterrupts(0);
- EEFC_ReadUniqueID(g_unique_id);
-
- printf("\r\n\r\n"
- "=============================================================================\r\n"
- "SIMtrace2 firmware " GIT_REVISION " (C) 2010-2017 by Harald Welte\r\n"
- "=============================================================================\r\n");
-
- TRACE_INFO("Serial Nr. %08x-%08x-%08x-%08x\r\n",
- g_unique_id[0], g_unique_id[1],
- g_unique_id[2], g_unique_id[3]);
-
+ print_banner();
board_main_top();
TRACE_INFO("USB init...\r\n");
diff --git a/firmware/atmel_softpack_libraries/libchip_sam3s/chip.h b/firmware/atmel_softpack_libraries/libchip_sam3s/chip.h
index e6af94e..8ae70df 100644
--- a/firmware/atmel_softpack_libraries/libchip_sam3s/chip.h
+++ b/firmware/atmel_softpack_libraries/libchip_sam3s/chip.h
@@ -15,7 +15,7 @@
/* Define attribute */
-#if defined ( __CC_ARM ) /* Keil µVision 4 */
+#if defined ( __CC_ARM ) /* Keil µVision 4 */
#define WEAK __attribute__ ((weak))
#elif defined ( __ICCARM__ ) /* IAR Ewarm 5.41+ */
#define WEAK __weak
diff --git a/firmware/atmel_softpack_libraries/libchip_sam3s/source/USBD_HAL.c b/firmware/atmel_softpack_libraries/libchip_sam3s/source/USBD_HAL.c
index 2f56602..1ebab5b 100644
--- a/firmware/atmel_softpack_libraries/libchip_sam3s/source/USBD_HAL.c
+++ b/firmware/atmel_softpack_libraries/libchip_sam3s/source/USBD_HAL.c
@@ -45,11 +45,6 @@
* Headers
*---------------------------------------------------------------------------*/
-#ifdef TRACE_LEVEL
-#undef TRACE_LEVEL
-#endif
-#define TRACE_LEVEL TRACE_LEVEL_WARNING
-
#include "chip.h"
#include "USBD_HAL.h"
#include <usb/device/dfu/dfu.h>
@@ -1082,6 +1077,14 @@ static inline uint8_t UDP_Read(uint8_t bEndpoint,
* Exported functions
*---------------------------------------------------------------------------*/
+
+uint16_t USBD_GetEndpointSize(uint8_t bEndpoint)
+{
+ Endpoint *pEndpoint = &(endpoints[bEndpoint]);
+
+ return pEndpoint->size;
+}
+
/**
* USBD (UDP) interrupt handler
* Manages device resume, suspend, end of bus reset.
@@ -1138,7 +1141,7 @@ void USBD_IrqHandler(void)
/* Resume (Wakeup) */
if ((status & (UDP_ISR_WAKEUP | UDP_ISR_RXRSM)) != 0) {
- TRACE_INFO_WP("Res ");
+ TRACE_DEBUG_WP("Res ");
/* Clear and disable resume interrupts */
UDP->UDP_ICR = UDP_ICR_WAKEUP | UDP_ICR_RXRSM | UDP_ICR_RXSUSP;
UDP->UDP_IDR = UDP_IDR_WAKEUP | UDP_IDR_RXRSM;
@@ -1150,7 +1153,7 @@ void USBD_IrqHandler(void)
This interrupt is always treated last (hence the '==') */
if (status == UDP_ISR_RXSUSP) {
- TRACE_INFO_WP("Susp ");
+ TRACE_DEBUG_WP("Susp ");
/* Enable wakeup */
UDP->UDP_IER = UDP_IER_WAKEUP | UDP_IER_RXRSM;
/* Acknowledge interrupt */
@@ -1161,19 +1164,26 @@ void USBD_IrqHandler(void)
/* End of bus reset */
else if ((status & UDP_ISR_ENDBUSRES) != 0) {
- TRACE_INFO_WP("EoBRes ");
+ TRACE_DEBUG_WP("EoBRes ");
#if defined(BOARD_USB_DFU)
#if defined(APPLICATION_dfu)
/* if we are currently in the DFU bootloader, and we are beyond
* the MANIFEST stage, we shall switch to the normal
* application */
- if (g_dfu->past_manifest)
+ if (g_dfu->past_manifest) {
+#if defined(ENVIRONMENT_flash)
USBDFU_SwitchToApp();
+#elif defined(ENVIRONMENT_dfu)
+ USBDFU_SwitchToDFU();
+#endif
+ }
+
#else
/* if we are currently in the main application, and we are in
- * appDETACH state, switch into the DFU bootloader */
- if (g_dfu->state == DFU_STATE_appDETACH)
+ * appDETACH state or past downloading, switch into the DFU bootloader.
+ */
+ if (g_dfu->state == DFU_STATE_appDETACH || g_dfu->state == DFU_STATE_dfuMANIFEST)
DFURT_SwitchToDFU();
#endif /* APPLICATION_dfu */
#endif /* BOARD_USB_DFU */
@@ -1202,7 +1212,7 @@ void USBD_IrqHandler(void)
if (status != 0) {
- TRACE_INFO_WP("\n\r - ");
+ TRACE_DEBUG_WP("\n\r - ");
}
}
eptnum++;
@@ -1211,7 +1221,7 @@ void USBD_IrqHandler(void)
/* Toggle LED back to its previous state */
TRACE_DEBUG_WP("!");
- TRACE_INFO_WP("\n\r");
+ TRACE_DEBUG_WP("\n\r");
if (USBD_GetState() >= USBD_STATE_POWERED) {
//LED_Clear(USBD_LEDUSB);
@@ -1361,7 +1371,7 @@ uint8_t USBD_HAL_ConfigureEP(const USBEndpointDescriptor *pDescriptor)
UDP->UDP_IER = (1 << bEndpoint);
}
- TRACE_INFO_WP("CfgEp%d ", bEndpoint);
+ TRACE_DEBUG_WP("CfgEp%d ", bEndpoint);
return bEndpoint;
}
@@ -1529,7 +1539,7 @@ void USBD_HAL_RemoteWakeUp(void)
UDP_EnableUsbClock();
UDP_EnableTransceiver();
- TRACE_INFO_WP("RWUp ");
+ TRACE_DEBUG_WP("RWUp ");
// Activates a remote wakeup (edge on ESR), then clear ESR
UDP->UDP_GLB_STAT |= UDP_GLB_STAT_ESR;
@@ -1692,7 +1702,10 @@ void USBD_HAL_Suspend(void)
/* The device enters the Suspended state */
UDP_DisableTransceiver();
UDP_DisableUsbClock();
- UDP_DisablePeripheralClock();
+ /* Don't disable peripheral clock; this somehow breaks completion of any IN transfers
+ * that have already been written to the peripheral, and which we expect to complete
+ * after resume */
+ //UDP_DisablePeripheralClock();
}
/**
diff --git a/firmware/atmel_softpack_libraries/libchip_sam3s/source/efc.c b/firmware/atmel_softpack_libraries/libchip_sam3s/source/efc.c
index 0c288e0..f8925b4 100644
--- a/firmware/atmel_softpack_libraries/libchip_sam3s/source/efc.c
+++ b/firmware/atmel_softpack_libraries/libchip_sam3s/source/efc.c
@@ -163,7 +163,7 @@ extern void EFC_TranslateAddress( Efc** ppEfc, uint32_t dwAddress, uint16_t* pwP
wPage = (dwAddress - IFLASH_ADDR) / IFLASH_PAGE_SIZE;
wOffset = (dwAddress - IFLASH_ADDR) % IFLASH_PAGE_SIZE;
- TRACE_DEBUG( "Translated 0x%08X to page=%d and offset=%d\n\r", dwAddress, wPage, wOffset ) ;
+ TRACE_DEBUG( "Translated 0x%08lX to page=%d and offset=%d\n\r", dwAddress, wPage, wOffset ) ;
/* Store values */
if ( pEfc )
{
diff --git a/firmware/atmel_softpack_libraries/libchip_sam3s/source/exceptions.c b/firmware/atmel_softpack_libraries/libchip_sam3s/source/exceptions.c
index 4799eae..7496f3a 100644
--- a/firmware/atmel_softpack_libraries/libchip_sam3s/source/exceptions.c
+++ b/firmware/atmel_softpack_libraries/libchip_sam3s/source/exceptions.c
@@ -151,8 +151,7 @@ WEAK void HardFault_Handler( void )
" mrseq r0, msp \n"
" mrsne r0, psp \n"
//" ldr r1, [r0, #24] \n"
- " b hard_fault_handler_c\n"
- ".syntax divided \n");
+ " b hard_fault_handler_c\n");
}
/**
diff --git a/firmware/atmel_softpack_libraries/libchip_sam3s/source/flashd.c b/firmware/atmel_softpack_libraries/libchip_sam3s/source/flashd.c
index 677ea30..c661b3f 100644
--- a/firmware/atmel_softpack_libraries/libchip_sam3s/source/flashd.c
+++ b/firmware/atmel_softpack_libraries/libchip_sam3s/source/flashd.c
@@ -134,7 +134,7 @@ static void ComputeLockRange( uint32_t dwStart, uint32_t dwEnd, uint32_t *pdwAct
// Store actual page numbers
EFC_ComputeAddress( pStartEfc, wActualStartPage, 0, pdwActualStart ) ;
EFC_ComputeAddress( pEndEfc, wActualEndPage, 0, pdwActualEnd ) ;
- TRACE_DEBUG( "Actual lock range is 0x%06X - 0x%06X\n\r", *pdwActualStart, *pdwActualEnd ) ;
+ TRACE_DEBUG( "Actual lock range is 0x%06lX - 0x%06lX\n\r", *pdwActualStart, *pdwActualEnd ) ;
}
diff --git a/firmware/atmel_softpack_libraries/libchip_sam3s/source/pio_it.c b/firmware/atmel_softpack_libraries/libchip_sam3s/source/pio_it.c
index 7feccd1..781b914 100644
--- a/firmware/atmel_softpack_libraries/libchip_sam3s/source/pio_it.c
+++ b/firmware/atmel_softpack_libraries/libchip_sam3s/source/pio_it.c
@@ -211,6 +211,16 @@ extern void PIO_InitializeInterrupts( uint32_t dwPriority )
NVIC_EnableIRQ( PIOC_IRQn ) ;
}
+static InterruptSource *find_intsource4pin(const Pin *pPin)
+{
+ unsigned int i ;
+ for (i = 0; i < _dwNumSources; i++) {
+ if (_aIntSources[i].pPin == pPin)
+ return &_aIntSources[i];
+ }
+ return NULL;
+}
+
/**
* Configures a PIO or a group of PIO to generate an interrupt on status
* change. The provided interrupt handler will be called with the triggering
@@ -228,15 +238,17 @@ extern void PIO_ConfigureIt( const Pin *pPin, void (*handler)( const Pin* ) )
assert( pPin ) ;
pio = pPin->pio ;
- assert( _dwNumSources < MAX_INTERRUPT_SOURCES ) ;
-
- /* Define new source */
- TRACE_DEBUG( "PIO_ConfigureIt: Defining new source #%" PRIu32 ".\n\r", _dwNumSources ) ;
- pSource = &(_aIntSources[_dwNumSources]) ;
- pSource->pPin = pPin ;
+ pSource = find_intsource4pin(pPin);
+ if (!pSource) {
+ /* Define new source */
+ TRACE_DEBUG( "PIO_ConfigureIt: Defining new source #%" PRIu32 ".\n\r", _dwNumSources ) ;
+ assert( _dwNumSources < MAX_INTERRUPT_SOURCES ) ;
+ pSource = &(_aIntSources[_dwNumSources]) ;
+ pSource->pPin = pPin ;
+ _dwNumSources++ ;
+ }
pSource->handler = handler ;
- _dwNumSources++ ;
/* PIO3 with additional interrupt support
* Configure additional interrupt mode registers */
diff --git a/firmware/atmel_softpack_libraries/libchip_sam3s/source/unique_id.c b/firmware/atmel_softpack_libraries/libchip_sam3s/source/unique_id.c
index 460eb9c..00c1aac 100644
--- a/firmware/atmel_softpack_libraries/libchip_sam3s/source/unique_id.c
+++ b/firmware/atmel_softpack_libraries/libchip_sam3s/source/unique_id.c
@@ -8,6 +8,11 @@ void EEFC_ReadUniqueID(unsigned int *pdwUniqueID)
{
unsigned int status;
+ /* disable interrupts, as interrupt vectors are stored in flash,
+ * and after STUI was issued, we can no longer access flassh until
+ * SPUI complets */
+ __disable_irq();
+
/* Errata / Workaround: Set bit 16 of EEFC Flash Mode Register
* to 1 */
EFC->EEFC_FMR |= (1 << 16);
@@ -40,4 +45,6 @@ void EEFC_ReadUniqueID(unsigned int *pdwUniqueID)
do {
status = EFC->EEFC_FSR;
} while ((status & EEFC_FSR_FRDY) != EEFC_FSR_FRDY);
+
+ __enable_irq();
}
diff --git a/firmware/atmel_softpack_libraries/usb/device/core/USBD.c b/firmware/atmel_softpack_libraries/usb/device/core/USBD.c
index bd39a53..747bdd0 100644
--- a/firmware/atmel_softpack_libraries/usb/device/core/USBD.c
+++ b/firmware/atmel_softpack_libraries/usb/device/core/USBD.c
@@ -300,7 +300,7 @@ void USBD_SetConfiguration(uint8_t cfgnum)
else {
deviceState = USBD_STATE_ADDRESS;
/* Reset all endpoints */
- USBD_HAL_ResetEPs(0xFFFFFFFF, USBD_STATUS_RESET, 0);
+ USBD_HAL_ResetEPs(0xFFFFFFFE, USBD_STATUS_RESET, 0);
}
}
diff --git a/firmware/atmel_softpack_libraries/usb/device/core/USBDDriver.c b/firmware/atmel_softpack_libraries/usb/device/core/USBDDriver.c
index 22889cf..c6cf6e0 100644
--- a/firmware/atmel_softpack_libraries/usb/device/core/USBDDriver.c
+++ b/firmware/atmel_softpack_libraries/usb/device/core/USBDDriver.c
@@ -251,7 +251,7 @@ static void GetDescriptor(
switch (type) {
case USBGenericDescriptor_DEVICE:
- TRACE_INFO_WP("Dev ");
+ TRACE_DEBUG_WP("Dev ");
/* Adjust length and send descriptor */
@@ -263,7 +263,7 @@ static void GetDescriptor(
break;
case USBGenericDescriptor_CONFIGURATION:
- TRACE_INFO_WP("Cfg ");
+ TRACE_DEBUG_WP("Cfg ");
/* Adjust length and send descriptor */
@@ -280,7 +280,7 @@ static void GetDescriptor(
break;
case USBGenericDescriptor_DEVICEQUALIFIER:
- TRACE_INFO_WP("Qua ");
+ TRACE_DEBUG_WP("Qua ");
/* Check if descriptor exists */
@@ -301,7 +301,7 @@ static void GetDescriptor(
break;
case USBGenericDescriptor_OTHERSPEEDCONFIGURATION:
- TRACE_INFO_WP("OSC ");
+ TRACE_DEBUG_WP("OSC ");
/* Check if descriptor exists */
@@ -327,7 +327,7 @@ static void GetDescriptor(
break;
case USBGenericDescriptor_STRING:
- TRACE_INFO_WP("Str%d ", indexRDesc);
+ TRACE_DEBUG_WP("Str%d ", indexRDesc);
/* Check if descriptor exists */
@@ -504,13 +504,13 @@ void USBDDriver_RequestHandler(
uint32_t length;
uint32_t address;
- TRACE_INFO_WP("Std ");
+ TRACE_DEBUG_WP("Std ");
/* Check request code */
switch (USBGenericRequest_GetRequest(pRequest)) {
case USBGenericRequest_GETDESCRIPTOR:
- TRACE_INFO_WP("gDesc ");
+ TRACE_DEBUG_WP("gDesc ");
/* Send the requested descriptor */
type = USBGetDescriptorRequest_GetDescriptorType(pRequest);
@@ -520,7 +520,7 @@ void USBDDriver_RequestHandler(
break;
case USBGenericRequest_SETADDRESS:
- TRACE_INFO_WP("sAddr ");
+ TRACE_DEBUG_WP("sAddr ");
/* Sends a zero-length packet and then set the device address */
address = USBSetAddressRequest_GetAddress(pRequest);
@@ -528,7 +528,7 @@ void USBDDriver_RequestHandler(
break;
case USBGenericRequest_SETCONFIGURATION:
- TRACE_INFO_WP("sCfg ");
+ TRACE_DEBUG_WP("sCfg ");
/* Set the requested configuration */
cfgnum = USBSetConfigurationRequest_GetConfiguration(pRequest);
@@ -536,27 +536,27 @@ void USBDDriver_RequestHandler(
break;
case USBGenericRequest_GETCONFIGURATION:
- TRACE_INFO_WP("gCfg ");
+ TRACE_DEBUG_WP("gCfg ");
/* Send the current configuration number */
GetConfiguration(pDriver);
break;
case USBGenericRequest_GETSTATUS:
- TRACE_INFO_WP("gSta ");
+ TRACE_DEBUG_WP("gSta ");
/* Check who is the recipient */
switch (USBGenericRequest_GetRecipient(pRequest)) {
case USBGenericRequest_DEVICE:
- TRACE_INFO_WP("Dev ");
+ TRACE_DEBUG_WP("Dev ");
/* Send the device status */
GetDeviceStatus(pDriver);
break;
case USBGenericRequest_ENDPOINT:
- TRACE_INFO_WP("Ept ");
+ TRACE_DEBUG_WP("Ept ");
/* Send the endpoint status */
eptnum = USBGenericRequest_GetEndpointNumber(pRequest);
@@ -572,13 +572,13 @@ void USBDDriver_RequestHandler(
break;
case USBGenericRequest_CLEARFEATURE:
- TRACE_INFO_WP("cFeat ");
+ TRACE_DEBUG_WP("cFeat ");
/* Check which is the requested feature */
switch (USBFeatureRequest_GetFeatureSelector(pRequest)) {
case USBFeatureRequest_ENDPOINTHALT:
- TRACE_INFO_WP("Hlt ");
+ TRACE_DEBUG_WP("Hlt ");
/* Unhalt endpoint and send a zero-length packet */
USBD_Unhalt(USBGenericRequest_GetEndpointNumber(pRequest));
@@ -586,7 +586,7 @@ void USBDDriver_RequestHandler(
break;
case USBFeatureRequest_DEVICEREMOTEWAKEUP:
- TRACE_INFO_WP("RmWU ");
+ TRACE_DEBUG_WP("RmWU ");
/* Disable remote wake-up and send a zero-length packet */
pDriver->isRemoteWakeUpEnabled = 0;
@@ -602,13 +602,13 @@ void USBDDriver_RequestHandler(
break;
case USBGenericRequest_SETFEATURE:
- TRACE_INFO_WP("sFeat ");
+ TRACE_DEBUG_WP("sFeat ");
/* Check which is the selected feature */
switch (USBFeatureRequest_GetFeatureSelector(pRequest)) {
case USBFeatureRequest_DEVICEREMOTEWAKEUP:
- TRACE_INFO_WP("RmWU ");
+ TRACE_DEBUG_WP("RmWU ");
/* Enable remote wake-up and send a ZLP */
pDriver->isRemoteWakeUpEnabled = 1;
@@ -616,25 +616,25 @@ void USBDDriver_RequestHandler(
break;
case USBFeatureRequest_ENDPOINTHALT:
- TRACE_INFO_WP("Halt ");
+ TRACE_DEBUG_WP("Halt ");
/* Halt endpoint */
USBD_Halt(USBGenericRequest_GetEndpointNumber(pRequest));
USBD_Write(0, 0, 0, 0, 0);
break;
case USBFeatureRequest_OTG_B_HNP_ENABLE:
- TRACE_INFO_WP("OTG_B_HNP_ENABLE ");
+ TRACE_DEBUG_WP("OTG_B_HNP_ENABLE ");
pDriver->otg_features_supported |=
1<<USBFeatureRequest_OTG_B_HNP_ENABLE;
USBD_Write(0, 0, 0, 0, 0);
break;
case USBFeatureRequest_OTG_A_HNP_SUPPORT:
- TRACE_INFO_WP("OTG_A_HNP_SUPPORT ");
+ TRACE_DEBUG_WP("OTG_A_HNP_SUPPORT ");
pDriver->otg_features_supported |=
1<<USBFeatureRequest_OTG_A_HNP_SUPPORT;
USBD_Write(0, 0, 0, 0, 0);
break;
case USBFeatureRequest_OTG_A_ALT_HNP_SUPPORT:
- TRACE_INFO_WP("OTG_A_ALT_HNP_SUPPORT ");
+ TRACE_DEBUG_WP("OTG_A_ALT_HNP_SUPPORT ");
pDriver->otg_features_supported |=
1<<USBFeatureRequest_OTG_A_ALT_HNP_SUPPORT;
USBD_Write(0, 0, 0, 0, 0);
@@ -649,7 +649,7 @@ void USBDDriver_RequestHandler(
break;
case USBGenericRequest_SETINTERFACE:
- TRACE_INFO_WP("sInterface ");
+ TRACE_DEBUG_WP("sInterface ");
infnum = USBInterfaceRequest_GetInterface(pRequest);
setting = USBInterfaceRequest_GetAlternateSetting(pRequest);
@@ -657,7 +657,7 @@ void USBDDriver_RequestHandler(
break;
case USBGenericRequest_GETINTERFACE:
- TRACE_INFO_WP("gInterface ");
+ TRACE_DEBUG_WP("gInterface ");
infnum = USBInterfaceRequest_GetInterface(pRequest);
GetInterface(pDriver, infnum);
diff --git a/firmware/atmel_softpack_libraries/usb/device/dfu/dfu.h b/firmware/atmel_softpack_libraries/usb/device/dfu/dfu.h
index 2a44602..84ce14e 100644
--- a/firmware/atmel_softpack_libraries/usb/device/dfu/dfu.h
+++ b/firmware/atmel_softpack_libraries/usb/device/dfu/dfu.h
@@ -39,8 +39,8 @@ struct dfu_desc {
#define DFU_FUNC_DESC { \
.bLength = USB_DT_DFU_SIZE, \
.bDescriptorType = USB_DT_DFU, \
- .bmAttributes = USB_DFU_CAN_UPLOAD | USB_DFU_CAN_DOWNLOAD, \
- .wDetachTimeOut = 0xff00, \
+ .bmAttributes = USB_DFU_CAN_UPLOAD | USB_DFU_CAN_DOWNLOAD | USB_DFU_WILL_DETACH, \
+ .wDetachTimeOut = 0x00, \
.wTransferSize = BOARD_DFU_PAGE_SIZE, \
.bcdDFUVersion = 0x0100, \
}
@@ -101,7 +101,7 @@ struct dfudata {
extern struct dfudata _g_dfu;
extern struct dfudata *g_dfu;
-void set_usb_serial_str(const uint8_t *serial_usbstr);
+void set_usb_serial_str(void);
void DFURT_SwitchToDFU(void);
@@ -124,6 +124,9 @@ void USBDFU_Initialize(const USBDDriverDescriptors *pDescriptors);
/* USBD tells us to switch from DFU mode to application mode */
void USBDFU_SwitchToApp(void);
+/* USBD tells us to switch from to DFU mode */
+void USBDFU_SwitchToDFU(void);
+
/* Return values to be used by USBDFU_handle_{dn,up}load */
#define DFU_RET_NOTHING 0
#define DFU_RET_ZLP 1
diff --git a/firmware/atmel_softpack_libraries/usb/device/dfu/dfu_desc.c b/firmware/atmel_softpack_libraries/usb/device/dfu/dfu_desc.c
index 75fded1..faebc13 100644
--- a/firmware/atmel_softpack_libraries/usb/device/dfu/dfu_desc.c
+++ b/firmware/atmel_softpack_libraries/usb/device/dfu/dfu_desc.c
@@ -13,14 +13,107 @@
#include <usb/common/dfu/usb_dfu.h>
#include <usb/device/dfu/dfu.h>
+#include "usb_strings_generated.h"
+
enum {
STR_MANUF = 1,
STR_PROD,
STR_CONFIG,
+ // strings for the first alternate interface (e.g. DFU)
_STR_FIRST_ALT,
- STR_SERIAL = (_STR_FIRST_ALT+BOARD_DFU_NUM_IF),
+ // serial string
+ STR_SERIAL = (_STR_FIRST_ALT + BOARD_DFU_NUM_IF),
+ // version string (on additional interface)
+ VERSION_CONF_STR,
+ VERSION_STR,
+ // count
+ STRING_DESC_CNT,
+};
+
+/* string used to replace one of both DFU flash partition atlsettings */
+static const unsigned char usb_string_notavailable[] = {
+ USBStringDescriptor_LENGTH(13),
+ USBGenericDescriptor_STRING,
+ USBStringDescriptor_UNICODE('n'),
+ USBStringDescriptor_UNICODE('o'),
+ USBStringDescriptor_UNICODE('t'),
+ USBStringDescriptor_UNICODE(' '),
+ USBStringDescriptor_UNICODE('a'),
+ USBStringDescriptor_UNICODE('v'),
+ USBStringDescriptor_UNICODE('a'),
+ USBStringDescriptor_UNICODE('i'),
+ USBStringDescriptor_UNICODE('l'),
+ USBStringDescriptor_UNICODE('a'),
+ USBStringDescriptor_UNICODE('b'),
+ USBStringDescriptor_UNICODE('l'),
+ USBStringDescriptor_UNICODE('e'),
};
+/* USB string for the serial (using 128-bit device ID) */
+static unsigned char usb_string_serial[] = {
+ USBStringDescriptor_LENGTH(32),
+ USBGenericDescriptor_STRING,
+ USBStringDescriptor_UNICODE('0'),
+ USBStringDescriptor_UNICODE('0'),
+ USBStringDescriptor_UNICODE('1'),
+ USBStringDescriptor_UNICODE('1'),
+ USBStringDescriptor_UNICODE('2'),
+ USBStringDescriptor_UNICODE('2'),
+ USBStringDescriptor_UNICODE('3'),
+ USBStringDescriptor_UNICODE('3'),
+ USBStringDescriptor_UNICODE('4'),
+ USBStringDescriptor_UNICODE('4'),
+ USBStringDescriptor_UNICODE('5'),
+ USBStringDescriptor_UNICODE('5'),
+ USBStringDescriptor_UNICODE('6'),
+ USBStringDescriptor_UNICODE('6'),
+ USBStringDescriptor_UNICODE('7'),
+ USBStringDescriptor_UNICODE('7'),
+ USBStringDescriptor_UNICODE('8'),
+ USBStringDescriptor_UNICODE('8'),
+ USBStringDescriptor_UNICODE('9'),
+ USBStringDescriptor_UNICODE('9'),
+ USBStringDescriptor_UNICODE('a'),
+ USBStringDescriptor_UNICODE('a'),
+ USBStringDescriptor_UNICODE('b'),
+ USBStringDescriptor_UNICODE('b'),
+ USBStringDescriptor_UNICODE('c'),
+ USBStringDescriptor_UNICODE('c'),
+ USBStringDescriptor_UNICODE('d'),
+ USBStringDescriptor_UNICODE('d'),
+ USBStringDescriptor_UNICODE('e'),
+ USBStringDescriptor_UNICODE('e'),
+ USBStringDescriptor_UNICODE('f'),
+ USBStringDescriptor_UNICODE('f'),
+};
+
+/* USB string for the version */
+static const unsigned char usb_string_version_conf[] = {
+ USBStringDescriptor_LENGTH(16),
+ USBGenericDescriptor_STRING,
+ USBStringDescriptor_UNICODE('f'),
+ USBStringDescriptor_UNICODE('i'),
+ USBStringDescriptor_UNICODE('r'),
+ USBStringDescriptor_UNICODE('m'),
+ USBStringDescriptor_UNICODE('w'),
+ USBStringDescriptor_UNICODE('a'),
+ USBStringDescriptor_UNICODE('r'),
+ USBStringDescriptor_UNICODE('e'),
+ USBStringDescriptor_UNICODE(' '),
+ USBStringDescriptor_UNICODE('v'),
+ USBStringDescriptor_UNICODE('e'),
+ USBStringDescriptor_UNICODE('r'),
+ USBStringDescriptor_UNICODE('s'),
+ USBStringDescriptor_UNICODE('i'),
+ USBStringDescriptor_UNICODE('o'),
+ USBStringDescriptor_UNICODE('n'),
+};
+
+static const char git_version[] = GIT_VERSION;
+static unsigned char usb_string_version[2 + ARRAY_SIZE(git_version) * 2 - 2];
+/** array of static (from usb_strings) and runtime (serial, version) USB strings */
+static const unsigned char *usb_strings_extended[STRING_DESC_CNT];
+
static const USBDeviceDescriptor fsDevice = {
.bLength = sizeof(USBDeviceDescriptor),
.bDescriptorType = USBGenericDescriptor_DEVICE,
@@ -34,12 +127,8 @@ static const USBDeviceDescriptor fsDevice = {
.bcdDevice = BOARD_USB_RELEASE,
.iManufacturer = STR_MANUF,
.iProduct = STR_PROD,
-#ifdef BOARD_USB_SERIAL
.iSerialNumber = STR_SERIAL,
-#else
- .iSerialNumber = 0,
-#endif
- .bNumConfigurations = 1,
+ .bNumConfigurations = 2, // DFU + version configurations
};
/* Alternate Interface Descriptor, we use one per partition/memory type */
@@ -52,7 +141,7 @@ static const USBDeviceDescriptor fsDevice = {
.bNumEndpoints = 0, \
.bInterfaceClass = 0xfe, \
.bInterfaceSubClass = 1, \
- .iInterface = (_STR_FIRST_ALT+ALT), \
+ .iInterface = (_STR_FIRST_ALT + ALT), \
.bInterfaceProtocol = 2, \
}
@@ -85,17 +174,79 @@ const struct dfu_desc dfu_cfg_descriptor = {
.func_dfu = DFU_FUNC_DESC
};
-#include "usb_strings_generated.h"
-
-#if 0
-void set_usb_serial_str(const uint8_t *serial_usbstr)
+void set_usb_serial_str(void)
{
- usb_strings[STR_SERIAL] = serial_usbstr;
-}
+ unsigned int i;
+
+ // put device ID into USB serial number description
+ unsigned int device_id[4];
+ EEFC_ReadUniqueID(device_id);
+ char device_id_string[32 + 1];
+ snprintf(device_id_string, ARRAY_SIZE(device_id_string), "%08x%08x%08x%08x",
+ device_id[0], device_id[1], device_id[2], device_id[3]);
+ for (i = 0; i < ARRAY_SIZE(device_id_string) - 1; i++) {
+ usb_string_serial[2 + 2 * i] = device_id_string[i];
+ }
+
+ // put version into USB string
+ usb_string_version[0] = USBStringDescriptor_LENGTH(ARRAY_SIZE(git_version) - 1);
+ usb_string_version[1] = USBGenericDescriptor_STRING;
+ for (i = 0; i < ARRAY_SIZE(git_version) - 1; i++) {
+ usb_string_version[2 + i * 2 + 0] = git_version[i];
+ usb_string_version[2 + i * 2 + 1] = 0;
+ }
+
+ // fill extended USB strings
+ for (i = 0; i < ARRAY_SIZE(usb_strings) && i < ARRAY_SIZE(usb_strings_extended); i++) {
+ usb_strings_extended[i] = usb_strings[i];
+ }
+#if defined(ENVIRONMENT_dfu)
+ usb_strings_extended[_STR_FIRST_ALT + 1] = usb_string_notavailable;
+#elif defined(ENVIRONMENT_flash)
+ usb_strings_extended[_STR_FIRST_ALT + 2] = usb_string_notavailable;
#endif
+ usb_strings_extended[STR_SERIAL] = usb_string_serial;
+ usb_strings_extended[VERSION_CONF_STR] = usb_string_version_conf;
+ usb_strings_extended[VERSION_STR] = usb_string_version;
+}
+
+/* USB descriptor just to show the version */
+typedef struct _SIMTraceDriverConfigurationDescriptorVersion {
+ /** Standard configuration descriptor. */
+ USBConfigurationDescriptor configuration;
+ USBInterfaceDescriptor version;
+} __attribute__ ((packed)) SIMTraceDriverConfigurationDescriptorVersion;
+
+static const SIMTraceDriverConfigurationDescriptorVersion
+ configurationDescriptorVersion = {
+ /* Standard configuration descriptor for the interface descriptor*/
+ .configuration = {
+ .bLength = sizeof(USBConfigurationDescriptor),
+ .bDescriptorType = USBGenericDescriptor_CONFIGURATION,
+ .wTotalLength = sizeof(SIMTraceDriverConfigurationDescriptorVersion),
+ .bNumInterfaces = 1,
+ .bConfigurationValue = 2,
+ .iConfiguration = VERSION_CONF_STR,
+ .bmAttributes = USBD_BMATTRIBUTES,
+ .bMaxPower = USBConfigurationDescriptor_POWER(100),
+ },
+ /* Interface standard descriptor just holding the version information */
+ .version = {
+ .bLength = sizeof(USBInterfaceDescriptor),
+ .bDescriptorType = USBGenericDescriptor_INTERFACE,
+ .bInterfaceNumber = 0,
+ .bAlternateSetting = 0,
+ .bNumEndpoints = 0,
+ .bInterfaceClass = USB_CLASS_PROPRIETARY,
+ .bInterfaceSubClass = 0xff,
+ .bInterfaceProtocol = 0,
+ .iInterface = VERSION_STR,
+ },
+};
static const USBConfigurationDescriptor *conf_desc_arr[] = {
&dfu_cfg_descriptor.ucfg,
+ &configurationDescriptorVersion.configuration,
};
const USBDDriverDescriptors dfu_descriptors = {
@@ -108,6 +259,6 @@ const USBDDriverDescriptors dfu_descriptors = {
.pHsConfiguration = NULL,
.pHsQualifier = NULL,
.pHsOtherSpeed = NULL,
- .pStrings = usb_strings,
- .numStrings = ARRAY_SIZE(usb_strings),
+ .pStrings = usb_strings_extended,
+ .numStrings = ARRAY_SIZE(usb_strings_extended),
};
diff --git a/firmware/atmel_softpack_libraries/usb/device/dfu/dfu_driver.c b/firmware/atmel_softpack_libraries/usb/device/dfu/dfu_driver.c
index 6230d6c..afec518 100644
--- a/firmware/atmel_softpack_libraries/usb/device/dfu/dfu_driver.c
+++ b/firmware/atmel_softpack_libraries/usb/device/dfu/dfu_driver.c
@@ -14,10 +14,6 @@
* 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 this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
*/
#include <unistd.h>
@@ -33,8 +29,7 @@
#include <usb/common/dfu/usb_dfu.h>
#include <usb/device/dfu/dfu.h>
-/* FIXME: this was used for a special ELF section which then got called
- * by DFU code and Application code, across flash partitions */
+/** specific memory location shared across bootloader and application */
#define __dfudata __attribute__ ((section (".dfudata")))
#define __dfufunc
@@ -42,11 +37,14 @@
static USBDDriver usbdDriver;
static unsigned char if_altsettings[1];
+/** structure containing the DFU state and magic value to know if DFU or application should be started */
__dfudata struct dfudata _g_dfu = {
- .state = DFU_STATE_appIDLE,
+ .state = DFU_STATE_dfuIDLE,
.past_manifest = 0,
.total_bytes = 0,
};
+
+/** variable to structure containing DFU state */
struct dfudata *g_dfu = &_g_dfu;
WEAK void dfu_drv_updstatus(void)
@@ -83,7 +81,7 @@ static void __dfufunc handle_getstate(void)
{
uint8_t u8 = g_dfu->state;
- TRACE_DEBUG("handle_getstate(%u)\n\r", g_dfu->state);
+ TRACE_DEBUG("handle_getstate(%ld)\n\r", g_dfu->state);
USBD_Write(0, (char *)&u8, sizeof(u8), NULL, 0);
}
@@ -447,6 +445,7 @@ void USBDFU_Initialize(const USBDDriverDescriptors *pDescriptors)
/* We already start in DFU idle mode */
g_dfu->state = DFU_STATE_dfuIDLE;
+ set_usb_serial_str();
USBDDriver_Initialize(&usbdDriver, pDescriptors, if_altsettings);
USBD_Init();
USBD_Connect();
@@ -460,7 +459,20 @@ void USBDFU_SwitchToApp(void)
/* make sure the MAGIC is not set to enter DFU again */
g_dfu->magic = 0;
- printf("switching to app\r\n");
+ /* disconnect from USB to ensure re-enumeration */
+ USBD_Disconnect();
+
+ /* disable any interrupts during transition */
+ __disable_irq();
+
+ /* Tell the hybrid to execute FTL JUMP! */
+ NVIC_SystemReset();
+}
+
+void USBDFU_SwitchToDFU(void)
+{
+ /* make sure the MAGIC is not set to enter DFU again */
+ g_dfu->magic = USB_DFU_MAGIC;
/* disconnect from USB to ensure re-enumeration */
USBD_Disconnect();
diff --git a/firmware/atmel_softpack_libraries/usb/device/dfu/dfu_runtime.c b/firmware/atmel_softpack_libraries/usb/device/dfu/dfu_runtime.c
index 444b75f..6e16a86 100644
--- a/firmware/atmel_softpack_libraries/usb/device/dfu/dfu_runtime.c
+++ b/firmware/atmel_softpack_libraries/usb/device/dfu/dfu_runtime.c
@@ -15,10 +15,6 @@
* 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 this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
*/
#include <board.h>
@@ -36,7 +32,12 @@
#include <usb/common/dfu/usb_dfu.h>
#include <usb/device/dfu/dfu.h>
-struct dfudata *g_dfu = (struct dfudata *) IRAM_ADDR;
+/** specific memory location shared across bootloader and application */
+#define __dfudata __attribute__ ((section (".dfudata")))
+/** structure containing the magic value to know if DFU or application should be started */
+__dfudata struct dfudata _g_dfu;
+/** variable to structure containing the magic value to know if DFU or application should be started */
+struct dfudata *g_dfu = &_g_dfu;
/* FIXME: this was used for a special ELF section which then got called
* by DFU code and Application code, across flash partitions */
@@ -63,7 +64,7 @@ static void __dfufunc handle_getstate(void)
{
uint8_t u8 = g_dfu->state;
- TRACE_DEBUG("handle_getstate(%u)\n\r", g_dfu->state);
+ TRACE_DEBUG("handle_getstate(%lu)\n\r", g_dfu->state);
USBD_Write(0, (char *)&u8, sizeof(u8), NULL, 0);
}
@@ -160,6 +161,8 @@ void USBDFU_Runtime_RequestHandler(const USBGenericRequest *request)
* will then trigger DFURT_SwitchToDFU() below */
TRACE_DEBUG("\r\n====dfu_detach\n\r");
g_dfu->state = DFU_STATE_appDETACH;
+ USBD_Write(0, 0, 0, 0, 0);
+ DFURT_SwitchToDFU();
ret = DFU_RET_ZLP;
goto out;
break;
@@ -204,13 +207,14 @@ out:
void DFURT_SwitchToDFU(void)
{
+ __disable_irq();
+
/* store the magic value that the DFU loader can detect and
* activate itself, rather than boot into the application */
g_dfu->magic = USB_DFU_MAGIC;
-
- /* Disconnect the USB by remoting the pull-up */
+ __DMB();
+ /* Disconnect the USB by removing the pull-up */
USBD_Disconnect();
- __disable_irq();
/* reset the processor, we will start execution with the
* ResetVector of the bootloader */
diff --git a/firmware/atmel_softpack_libraries/usb/include/USBD.h b/firmware/atmel_softpack_libraries/usb/include/USBD.h
index 15a6859..6eeb68a 100644
--- a/firmware/atmel_softpack_libraries/usb/include/USBD.h
+++ b/firmware/atmel_softpack_libraries/usb/include/USBD.h
@@ -63,7 +63,7 @@
*------------------------------------------------------------------------------*/
/* Define attribute */
-#if defined ( __CC_ARM ) /* Keil µVision 4 */
+#if defined ( __CC_ARM ) /* Keil µVision 4 */
#define WEAK __attribute__ ((weak))
#elif defined ( __ICCARM__ ) /* IAR Ewarm 5.41+ */
#define WEAK __weak
@@ -214,6 +214,8 @@ typedef void (*MblTransferCallback)(void *pArg,
* Exported functions
*------------------------------------------------------------------------------*/
+extern uint16_t USBD_GetEndpointSize(uint8_t bEndpoint);
+
//extern void USBD_IrqHandler(void);
extern void USBD_Init(void);
diff --git a/firmware/atmel_softpack_libraries/usb/include/USBDescriptors.h b/firmware/atmel_softpack_libraries/usb/include/USBDescriptors.h
index 84b5ef6..aada0f1 100644
--- a/firmware/atmel_softpack_libraries/usb/include/USBDescriptors.h
+++ b/firmware/atmel_softpack_libraries/usb/include/USBDescriptors.h
@@ -296,7 +296,7 @@ typedef uint32_t (*USBDescriptorParseFunction)(void *descriptor, void *parseArg)
*/
#pragma pack(1)
-#if defined ( __CC_ARM ) /* Keil µVision 4 */
+#if defined ( __CC_ARM ) /* Keil µVision 4 */
#elif defined ( __ICCARM__ ) /* IAR Ewarm 5.41+ */
#define __attribute__(...)
#elif defined ( __GNUC__ ) /* GCC CS3 2009q3-68 */
diff --git a/firmware/libboard/common/include/board_common.h b/firmware/libboard/common/include/board_common.h
index cb72d40..37fd1a3 100644
--- a/firmware/libboard/common/include/board_common.h
+++ b/firmware/libboard/common/include/board_common.h
@@ -12,10 +12,6 @@
* 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 this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*/
#ifndef _BOARD_
#define _BOARD_
@@ -56,16 +52,12 @@
/** Core definition */
#define cortexm3
-#define PIO_LED_RED PIO_PA17
-#define PIO_LED_GREEN PIO_PA18
-
-#define PIN_LED_RED {PIO_LED_RED, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
-#define PIN_LED_GREEN {PIO_LED_GREEN, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
-#define PINS_LEDS PIN_LED_RED, PIN_LED_GREEN
-
-#define LED_NUM_RED 0
-#define LED_NUM_GREEN 1
-
+/* LEDs are used to indicate the status
+ * the LED definition is board specific
+ * most boards have two LEDs, one green and one red
+ * the red LED indicates of the main firmware is ready (on) or if there is an error (blinking)
+ * the green LED indicates if the firmware is idling (on) or if there is activity (blinking)
+ */
/** USART0 pin RX */
#define PIN_USART0_RXD {PIO_PA9A_URXD0, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
/** USART0 pin TX */
@@ -112,17 +104,17 @@
/* Interrupt request ID of USART peripheral connected to the phone */
#define IRQ_USART_PHONE USART1_IRQn
-#define SIM_PWEN PIO_PA5
-#define VCC_FWD PIO_PA26
-
// Board has UDP controller
#define BOARD_USB_UDP
#define BOARD_USB_DFU
+
+
#define BOARD_DFU_BOOT_SIZE (16 * 1024)
#define BOARD_DFU_RAM_SIZE (2 * 1024)
#define BOARD_DFU_PAGE_SIZE 512
-#define BOARD_DFU_NUM_IF 2
+/** number of DFU interfaces (used to flash specific partitions) */
+#define BOARD_DFU_NUM_IF 3
extern void board_exec_dbg_cmd(int ch);
extern void board_main_top(void);
diff --git a/firmware/libboard/common/include/boardver_adc.h b/firmware/libboard/common/include/boardver_adc.h
index 956c302..c8f320e 100644
--- a/firmware/libboard/common/include/boardver_adc.h
+++ b/firmware/libboard/common/include/boardver_adc.h
@@ -7,10 +7,6 @@
* 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 this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*/
#pragma once
diff --git a/firmware/libboard/common/include/led.h b/firmware/libboard/common/include/led.h
index 339702d..ab12448 100644
--- a/firmware/libboard/common/include/led.h
+++ b/firmware/libboard/common/include/led.h
@@ -7,10 +7,6 @@
* 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 this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*/
#pragma once
@@ -31,7 +27,8 @@ enum led_pattern {
BLINK_200O_F = 7,
BLINK_600O_F = 8,
BLINK_CUSTOM = 9,
- BLINK_2F_O,
+ BLINK_2F_O = 10,
+ BLINK_5O_5F = 11,
_NUM_LED_BLINK
};
diff --git a/firmware/libboard/common/include/manifest.h b/firmware/libboard/common/include/manifest.h
index b29c1aa..0635bf9 100644
--- a/firmware/libboard/common/include/manifest.h
+++ b/firmware/libboard/common/include/manifest.h
@@ -7,10 +7,6 @@
* 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 this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*/
#ifndef _MANIFEST_H
#define _MANIFEST_H
diff --git a/firmware/libboard/common/include/sim_switch.h b/firmware/libboard/common/include/sim_switch.h
index 3d131f2..61d9c1f 100644
--- a/firmware/libboard/common/include/sim_switch.h
+++ b/firmware/libboard/common/include/sim_switch.h
@@ -7,12 +7,16 @@
* 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 this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*/
#pragma once
+/** switch card lines to use physical or emulated card
+ * @param[in] nr card interface number (i.e. slot)
+ * @param[in] physical which physical interface to switch to (e.g. 0: physical, 1: virtual)
+ * @return 0 on success, negative else
+ */
int sim_switch_use_physical(unsigned int nr, int physical);
+/** initialise card switching capabilities
+ * @return number of switchable card interfaces
+ */
int sim_switch_init(void);
diff --git a/firmware/libboard/common/resources/sam3s4/dfu.ld b/firmware/libboard/common/resources/sam3s4/dfu.ld
index e56a435..86e6622 100644
--- a/firmware/libboard/common/resources/sam3s4/dfu.ld
+++ b/firmware/libboard/common/resources/sam3s4/dfu.ld
@@ -39,17 +39,26 @@ SEARCH_DIR(.)
MEMORY
{
/* reserve the first 16k (= 0x4000) for the DFU bootloader */
- rom (rx) : ORIGIN = 0x00404000, LENGTH = 0x0003c000 /* flash, 256K */
- /* reserve the first 32 (= 0x20) bytes for the _g_dfu struct */
- ram (rwx) : ORIGIN = 0x20000020, LENGTH = 0x0000bfe0 /* sram, 48K */
+ crcstub (rx) : ORIGIN = 0x00400000 + 16K, LENGTH = 512 /* crcstub part */
+ rom (rx) : ORIGIN = 0x00400000 + 16K + 512, LENGTH = 256K - 16K - 512 /* flash, 256K */
+ /* note: dfudata will be at the start */
+ ram (rwx) : ORIGIN = 0x20000000, LENGTH = 48K /* SRAM, 48K */
}
/* Section Definitions */
SECTIONS
{
- .text :
- {
+ .crcstub :
+ {
. = ALIGN(4);
+ KEEP(*(.crcstub_table))
+ KEEP(*(.crcstub_code))
+ } > crcstub = 0xff
+
+ .text :
+ {
+
+ . = ALIGN(512);
_sfixed = .;
KEEP(*(.vectors .vectors.*))
*(.text .text.* .gnu.linkonce.t.*)
@@ -94,15 +103,20 @@ SECTIONS
. = ALIGN(4);
_efixed = .; /* End of text section */
- } > rom
+ } > rom = 0xff
+
+ /DISCARD/ :
+ {
+ *(.ARM.exidx)
+ }
- /* .ARM.exidx is sorted, so has to go in its own output section. */
- PROVIDE_HIDDEN (__exidx_start = .);
- .ARM.exidx :
+ .blupdate :
{
- *(.ARM.exidx* .gnu.linkonce.armexidx.*)
+ . = ALIGN(4);
+ _blupdate_start = .;
+ KEEP(*(.fwupdate .fwupdate.*));
+ _blupdate_end = .;
} > rom
- PROVIDE_HIDDEN (__exidx_end = .);
. = ALIGN(4);
_etext = .;
@@ -111,6 +125,8 @@ SECTIONS
{
. = ALIGN(4);
_srelocate = .;
+ /* we must make sure the .dfudata is linked to start of RAM */
+ *(.dfudata .dfudata.*);
*(.ramfunc .ramfunc.*);
*(.data .data.*);
. = ALIGN(4);
diff --git a/firmware/libboard/common/resources/sam3s4/flash.ld b/firmware/libboard/common/resources/sam3s4/flash.ld
index bdebbde..b1de154 100644
--- a/firmware/libboard/common/resources/sam3s4/flash.ld
+++ b/firmware/libboard/common/resources/sam3s4/flash.ld
@@ -38,8 +38,8 @@ SEARCH_DIR(.)
/* Memory Spaces Definitions */
MEMORY
{
- rom (rx) : ORIGIN = 0x00400000, LENGTH = 0x00040000 /* flash, 256K */
- ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x0000c000 /* sram, 48K */
+ rom (rx) : ORIGIN = 0x00400000, LENGTH = 16K /* flash, 256K, but only the first 16K should be used for the bootloader */
+ ram (rwx) : ORIGIN = 0x20000000, LENGTH = 48K /* SRAM, 48K */
}
/* Section Definitions */
@@ -94,13 +94,12 @@ SECTIONS
_efixed = .; /* End of text section */
} > rom
- /* .ARM.exidx is sorted, so has to go in its own output section. */
- PROVIDE_HIDDEN (__exidx_start = .);
- .ARM.exidx :
+ /DISCARD/ :
{
- *(.ARM.exidx* .gnu.linkonce.armexidx.*)
- } > rom
- PROVIDE_HIDDEN (__exidx_end = .);
+ *(.ARM.exidx)
+ *(.crcstub_table)
+ *(.crcstub_code)
+ }
. = ALIGN(4);
_etext = .;
diff --git a/firmware/libboard/common/source/board_cstartup_gnu.c b/firmware/libboard/common/source/board_cstartup_gnu.c
index e82a2fb..d548a30 100644
--- a/firmware/libboard/common/source/board_cstartup_gnu.c
+++ b/firmware/libboard/common/source/board_cstartup_gnu.c
@@ -126,7 +126,7 @@ IntFunc exception_table[] = {
IrqHandlerNotUsed /* 35 not used */
};
-#if defined(BOARD_USB_DFU) && defined(APPLICATION_dfu)
+#if defined(BOARD_USB_DFU) && defined(APPLICATION_dfu) && defined(ENVIRONMENT_flash)
#include "usb/device/dfu/dfu.h"
static void BootIntoApp(void)
{
@@ -159,8 +159,9 @@ void ResetException( void )
LowLevelInit() ;
-#if defined(BOARD_USB_DFU) && defined(APPLICATION_dfu)
- if (!USBDFU_OverrideEnterDFU()) {
+#if defined(BOARD_USB_DFU) && defined(APPLICATION_dfu) && defined(ENVIRONMENT_flash)
+ // boot application if there is not DFU override
+ if (!USBDFU_OverrideEnterDFU() && SCB->VTOR < IFLASH_ADDR + BOARD_DFU_BOOT_SIZE) {
UART_Exit();
__disable_irq();
BootIntoApp();
diff --git a/firmware/libboard/common/source/board_lowlevel.c b/firmware/libboard/common/source/board_lowlevel.c
index 8210938..a04ce10 100644
--- a/firmware/libboard/common/source/board_lowlevel.c
+++ b/firmware/libboard/common/source/board_lowlevel.c
@@ -127,6 +127,9 @@ extern WEAK void LowLevelInit( void )
SUPC->SUPC_SMMR = SUPC_SMMR_SMTH_3_0V | SUPC_SMMR_SMSMPL_CSM |
SUPC_SMMR_SMRSTEN_ENABLE;
+ /* disable ERASE pin to prevent accidental flash erase */
+ MATRIX->CCFG_SYSIO |= CCFG_SYSIO_SYSIO12;
+
/* enable both LED and green LED */
PIOA->PIO_PER |= PIO_LED_RED | PIO_LED_GREEN;
PIOA->PIO_OER |= PIO_LED_RED | PIO_LED_GREEN;
@@ -144,7 +147,7 @@ extern WEAK void LowLevelInit( void )
}
*/
-#ifndef qmod
+#ifndef BOARD_MAINOSC_BYPASS
/* Initialize main oscillator */
if ( !(PMC->CKGR_MOR & CKGR_MOR_MOSCSEL) )
{
@@ -162,11 +165,11 @@ extern WEAK void LowLevelInit( void )
timeout = 0;
while (!(PMC->PMC_SR & PMC_SR_MOSCSELS) && (timeout++ < CLOCK_TIMEOUT));
#else
- /* QMOD has external 12MHz clock source */
+ /* Board has external clock, not a crystal oscillator */
PIOB->PIO_PDR = (1 << 9);
PIOB->PIO_PUDR = (1 << 9);
PIOB->PIO_PPDDR = (1 << 9);
- PMC->CKGR_MOR = CKGR_MOR_KEY(0x37) | CKGR_MOR_MOSCRCEN | CKGR_MOR_MOSCXTBY| CKGR_MOR_MOSCSEL;
+ PMC->CKGR_MOR = CKGR_MOR_KEY(0x37) | CKGR_MOR_MOSCRCEN | CKGR_MOR_MOSCXTBY | CKGR_MOR_MOSCSEL;
#endif
/* disable the red LED after main clock initialization */
@@ -215,3 +218,8 @@ void mdelay(unsigned int msecs)
do {
} while ((jiffies - jiffies_start) < msecs);
}
+
+void abort() {
+ NVIC_SystemReset();
+ while(1) {};
+}
diff --git a/firmware/libboard/common/source/boardver_adc.c b/firmware/libboard/common/source/boardver_adc.c
index 11799cc..9c7769d 100644
--- a/firmware/libboard/common/source/boardver_adc.c
+++ b/firmware/libboard/common/source/boardver_adc.c
@@ -7,10 +7,6 @@
* 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 this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*/
#include "board.h"
#include "boardver_adc.h"
diff --git a/firmware/libboard/common/source/led.c b/firmware/libboard/common/source/led.c
index 6772007..8fcb61f 100644
--- a/firmware/libboard/common/source/led.c
+++ b/firmware/libboard/common/source/led.c
@@ -12,10 +12,6 @@
* 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 this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*/
#include <stdint.h>
#include <string.h>
@@ -58,6 +54,10 @@ static const struct blink_state bs_on[] = {
{ 0, 1 }
};
+static const struct blink_state bs_5on_5off[] = {
+ { 500, 1 }, { 500, 0 }
+};
+
static const struct blink_state bs_3on_5off[] = {
{ 300, 1 }, { 500, 0 }
};
@@ -107,6 +107,10 @@ static const struct blink_pattern patterns[] = {
.states = bs_on,
.size = ARRAY_SIZE(bs_on),
},
+ [BLINK_5O_5F] = {
+ .states = bs_5on_5off,
+ .size = ARRAY_SIZE(bs_5on_5off),
+ },
[BLINK_3O_5F] = {
.states = bs_3on_5off,
.size = ARRAY_SIZE(bs_3on_5off),
diff --git a/firmware/libboard/common/source/manifest.c b/firmware/libboard/common/source/manifest.c
index 0ad537c..fb3870f 100644
--- a/firmware/libboard/common/source/manifest.c
+++ b/firmware/libboard/common/source/manifest.c
@@ -7,10 +7,6 @@
* 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 this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*/
#include "manifest.h"
diff --git a/firmware/libboard/common/source/uart_console.c b/firmware/libboard/common/source/uart_console.c
index bcfb0b7..ead5555 100644
--- a/firmware/libboard/common/source/uart_console.c
+++ b/firmware/libboard/common/source/uart_console.c
@@ -100,6 +100,7 @@ extern void UART_Configure( uint32_t baudrate, uint32_t masterClock)
/* Enable TX interrupts */
pUart->UART_IER = UART_IER_TXRDY;
+ NVIC_SetPriority(CONSOLE_IRQ, 15); /* lowest priority */
NVIC_EnableIRQ(CONSOLE_IRQ);
/* Enable receiver and transmitter */
diff --git a/firmware/libboard/ngff_cardem/include/board.h b/firmware/libboard/ngff_cardem/include/board.h
new file mode 100644
index 0000000..f74cea1
--- /dev/null
+++ b/firmware/libboard/ngff_cardem/include/board.h
@@ -0,0 +1,162 @@
+/* Osmocom ngff-cardem board definition
+ *
+ * (C) 2021 by Harald Welte <laforge@osmocom.org>
+ *
+ * This program 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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.
+ */
+#pragma once
+#include "board_common.h"
+#include "simtrace_usb.h"
+
+/** Name of the board */
+#define BOARD_NAME "NGFF-CARDEM"
+/** Board definition */
+#define ngff_cardem
+
+/** oscillator used as main clock source (in Hz) */
+#define BOARD_MAINOSC 12000000
+/** desired main clock frequency (in Hz, based on BOARD_MAINOSC) */
+#define BOARD_MCK 58000000 // 12.000 * 29 / 6
+
+/** MCU pin connected to red LED */
+#define PIO_LED_RED PIO_PA17
+/** MCU pin connected to green LED */
+#define PIO_LED_GREEN PIO_PA18
+/** red LED pin definition */
+#define PIN_LED_RED {PIO_LED_RED, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
+/** green LED pin definition */
+#define PIN_LED_GREEN {PIO_LED_GREEN, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
+/** LEDs pin definition */
+#define PINS_LEDS PIN_LED_RED, PIN_LED_GREEN
+/** index for red LED in LEDs pin definition array */
+#define LED_NUM_RED 0
+/** index for green LED in LEDs pin definition array */
+#define LED_NUM_GREEN 1
+/** the green LED is actually red and used as indication for USIM1 */
+#define LED_USIM1 LED_GREEN
+
+/* USIM 2 interface (USART) */
+#define PIN_USIM2_CLK {PIO_PA2, PIOA, ID_PIOA, PIO_PERIPH_B, PIO_DEFAULT}
+#define PIN_USIM2_IO {PIO_PA6, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
+#define PINS_ISO7816_USIM2 PIN_USIM2_CLK, PIN_USIM2_IO
+
+/* USIM 2 interface (TC) */
+#define PIN_USIM2_IO_TC {PIO_PA1, PIOA, ID_PIOA, PIO_PERIPH_B, PIO_DEFAULT}
+#define PIN_USIM2_CLK_TC {PIO_PA4, PIOA, ID_PIOA, PIO_PERIPH_B, PIO_DEFAULT}
+#define PINS_TC_USIM2 PIN_USIM2_IO_TC, PIN_USIM2_CLK_TC
+
+/* USIM 1 interface (USART) */
+#define PIN_USIM1_IO {PIO_PA22, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
+#define PIN_USIM1_CLK {PIO_PA23, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
+#define PINS_ISO7816_USIM1 PIN_USIM1_CLK, PIN_USIM1_IO
+
+/* USIM 1 interface (TC) */
+#define PIN_USIM1_IO_TC {PIO_PA27, PIOA, ID_PIOA, PIO_PERIPH_B, PIO_DEFAULT}
+#define PIN_USIM1_CLK_TC {PIO_PA29, PIOA, ID_PIOA, PIO_PERIPH_B, PIO_DEFAULT}
+#define PINS_TC_USIM1 PIN_USIM1_IO_TC, PIN_USIM1_CLK_TC
+
+#define PIN_USIM1_nRST {PIO_PA24, PIOA, ID_PIOA, PIO_INPUT, PIO_DEFAULT}
+#define PIN_USIM1_VCC {PIO_PB3, PIOB, ID_PIOB, PIO_INPUT, PIO_DEFAULT}
+
+#define PIN_USIM2_nRST {PIO_PA7, PIOA, ID_PIOA, PIO_INPUT, PIO_DEFAULT}
+//#define PIN_USIM2_VCC {PIO_PB2, PIOB, ID_PIOB, PIO_INPUT, PIO_DEFAULT}
+
+#define PINS_USIM1 PINS_TC_USIM1, PINS_ISO7816_USIM1, PIN_USIM1_nRST
+#define PINS_USIM2 PINS_TC_USIM2, PINS_ISO7816_USIM2, PIN_USIM2_nRST
+
+/* from v3 and onwards only (!) */
+#define PIN_DET_USIM1_PRES {PIO_PA8, PIOA, ID_PIOA, PIO_INPUT, PIO_DEGLITCH | PIO_IT_EDGE}
+
+/* inputs reading the WWAN LED level */
+#define PIN_WWAN1 {PIO_PA15, PIOA, ID_PIOA, PIO_INPUT, PIO_PULLUP | PIO_DEGLITCH | PIO_IT_EDGE}
+#define PINS_WWAN_IN { PIN_WWAN1 }
+
+#define PIN_MODEM_EN {PIO_PA11, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
+#define PIN_N_MODEM_PWR_ON {PIO_PA26, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}
+
+/* outputs controlling RESET input of modems */
+#define PIN_PERST1 {PIO_PA25, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
+#define PINS_PERST { PIN_PERST1 }
+
+#define PIN_VERSION_DET {PIO_PA19, PIOA, ID_PIOA, PIO_PERIPH_D, PIO_DEFAULT}
+
+/* GPIO towards SPDT switches between real SIM and SAM3 */
+//#define PIN_SIM_SWITCH1 {PIO_PA20, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}
+//#define PIN_SIM_SWITCH2 {PIO_PA28, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}
+
+#define BOARD_USB_BMATTRIBUTES USBConfigurationDescriptor_SELFPOWERED_NORWAKEUP
+
+#define BOARD_USB_VENDOR_ID USB_VENDOR_OPENMOKO
+#define BOARD_USB_PRODUCT_ID USB_PRODUCT_NGFF_CARDEM
+#define BOARD_DFU_USB_PRODUCT_ID USB_PRODUCT_NGFF_CARDEM
+#define BOARD_USB_RELEASE 0x010
+
+#define DETECT_VCC_BY_ADC
+#define VCC_UV_THRESH_1V8 1500000
+#define VCC_UV_THRESH_3V VCC_UV_THRESH_1V8
+
+#ifdef APPLICATION_cardem
+#define HAVE_CARDEM
+#define HAVE_BOARD_CARDINSERT
+struct cardem_inst;
+void board_set_card_insert(struct cardem_inst *ci, bool card_insert);
+#endif
+
+#ifdef APPLICATION_trace
+#define HAVE_SNIFFER
+#endif
+
+/* Card I/O data signal input/output (I/O_SIM in schematic) */
+#define PIN_SIM_IO {PIO_PA6A_TXD0, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
+/* Card CLK clock input (CLK_SIM in schematic) */
+#define PIN_SIM_CLK {PIO_PA2B_SCK0, PIOA, ID_PIOA, PIO_PERIPH_B, PIO_DEFAULT}
+/* Card RST reset signal input (use as input since the phone will drive it) */
+#define PIN_SIM_RST_SNIFF {PIO_PA7, PIOA, ID_PIOA, PIO_INPUT, PIO_DEGLITCH | PIO_IT_EDGE}
+/* Pins used to sniff phone-card communication */
+#define PINS_SIM_SNIFF PIN_SIM_IO, PIN_SIM_CLK, PIN_SIM_RST_SNIFF
+
+/* Pin to measure card I/O timing (to start measuring the ETU on I/O activity; connected I/O_SIM in schematic) */
+#define PIN_SIM_IO_INPUT {PIO_PA1B_TIOB0, PIOA, ID_PIOA, PIO_PERIPH_B, PIO_DEFAULT}
+/* Pin used as clock input (to measure the ETU duration; connected to CLK_SIM in schematic) */
+#define PIN_SIM_CLK_INPUT {PIO_PA4B_TCLK0, PIOA, ID_PIOA, PIO_PERIPH_B, PIO_DEFAULT}
+/* Pins used to measure ETU timing (using timer counter) */
+#define PINS_TC PIN_SIM_IO_INPUT, PIN_SIM_CLK_INPUT
+
+//default state: NO uart connected, modem connected to physical sim, NO sim presence override, modem powers sim slot
+#define pin_conn_usim1_default {PIO_PA20, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
+#define pin_conn_usim2_default {PIO_PA28, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
+#define pin_conn_mdm_sim_default {PIO_PA0, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}
+#define pin_conn_set_sim_det_default {PIO_PA13, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
+#define pin_en_st_sim_vdd_default {PIO_PB2, PIOB, ID_PIOB, PIO_OUTPUT_0, PIO_DEFAULT}
+#define pin_en_mdm_sim_vdd_default {PIO_PA16, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
+
+//cardem state: uart2 (!) connected, NO modem connected to physical sim, sim presence override, NOTHING powers sim slot
+#define pin_conn_usim1_cem {PIO_PA20, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
+#define pin_conn_usim2_cem {PIO_PA28, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}
+#define pin_conn_mdm_sim_cem {PIO_PA0, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
+#define pin_en_st_sim_vdd_cem {PIO_PB2, PIOB, ID_PIOB, PIO_OUTPUT_0, PIO_DEFAULT}
+#define pin_en_mdm_sim_vdd_cem {PIO_PA16, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}
+
+//trace state: uart2 (!) connected, modem connected to physical sim, st powers sim slot
+#define pin_conn_usim1_trace {PIO_PA20, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
+#define pin_conn_usim2_trace {PIO_PA28, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}
+#define pin_conn_mdm_sim_trace {PIO_PA0, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}
+#define pin_conn_set_sim_det_trace {PIO_PA13, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
+#define pin_en_st_sim_vdd_trace {PIO_PB2, PIOB, ID_PIOB, PIO_OUTPUT_1, PIO_DEFAULT}
+#define pin_en_mdm_sim_vdd_trace {PIO_PA16, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}
+
+#define PIN_MODEM_EN_off {PIO_PA11, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}
+
+#define PINS_SIM_DEFAULT pin_conn_usim1_default, pin_conn_usim2_default, pin_conn_mdm_sim_default, pin_conn_set_sim_det_default, PIN_N_MODEM_PWR_ON, PIN_MODEM_EN, pin_en_st_sim_vdd_default, pin_en_mdm_sim_vdd_default
+#define PINS_SIM_CARDEM pin_conn_usim1_cem, pin_conn_usim2_cem, pin_conn_mdm_sim_cem, pin_en_mdm_sim_vdd_cem, pin_en_st_sim_vdd_cem// , pin_conn_set_sim_det_cem
+
+#define PINS_BUS_SNIFF pin_conn_usim1_trace, pin_conn_usim2_trace, pin_conn_mdm_sim_trace, pin_conn_set_sim_det_trace,PIN_MODEM_EN_off
+#define PINS_PWR_SNIFF PIN_N_MODEM_PWR_ON, PIN_MODEM_EN, pin_en_st_sim_vdd_trace, pin_en_mdm_sim_vdd_trace
diff --git a/firmware/libboard/ngff_cardem/include/card_pres.h b/firmware/libboard/ngff_cardem/include/card_pres.h
new file mode 100644
index 0000000..e06642e
--- /dev/null
+++ b/firmware/libboard/ngff_cardem/include/card_pres.h
@@ -0,0 +1,18 @@
+/* card presence utilities
+ *
+ * (C) 2016-2017 by Harald Welte <hwelte@hmw-consulting.de>
+ *
+ * This program 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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.
+ */
+#pragma once
+
+int is_card_present(int port);
+int card_present_init(void);
diff --git a/firmware/libboard/ngff_cardem/include/wwan_led.h b/firmware/libboard/ngff_cardem/include/wwan_led.h
new file mode 100644
index 0000000..a0f060a
--- /dev/null
+++ b/firmware/libboard/ngff_cardem/include/wwan_led.h
@@ -0,0 +1,16 @@
+/* Code to read/track the status of the WWAN LEDs of attached modems
+ *
+ * This program 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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.
+ */
+#pragma once
+
+int wwan_led_active(int wwan);
+int wwan_led_init(void);
diff --git a/firmware/libboard/ngff_cardem/include/wwan_perst.h b/firmware/libboard/ngff_cardem/include/wwan_perst.h
new file mode 100644
index 0000000..623184e
--- /dev/null
+++ b/firmware/libboard/ngff_cardem/include/wwan_perst.h
@@ -0,0 +1,17 @@
+/* Code to control the PERST lines of attached modems
+ *
+ * This program 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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.
+ */
+#pragma once
+
+int wwan_perst_set(int modem_nr, int active);
+int wwan_perst_do_reset_pulse(int modem_nr, unsigned int duration_ms);
+int wwan_perst_init(void);
diff --git a/firmware/libboard/ngff_cardem/product_string.txt b/firmware/libboard/ngff_cardem/product_string.txt
new file mode 100644
index 0000000..09a33c6
--- /dev/null
+++ b/firmware/libboard/ngff_cardem/product_string.txt
@@ -0,0 +1 @@
+ngff-cardem
diff --git a/firmware/libboard/ngff_cardem/source/board_ngff_cardem.c b/firmware/libboard/ngff_cardem/source/board_ngff_cardem.c
new file mode 100644
index 0000000..fea64d3
--- /dev/null
+++ b/firmware/libboard/ngff_cardem/source/board_ngff_cardem.c
@@ -0,0 +1,155 @@
+/* sysmocom ngff-cardem application code
+ *
+ * (C) 2021 Harald Welte <laforge@osmocom.org>
+ *
+ * This program 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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.
+ */
+#include "board.h"
+#include "simtrace.h"
+#include "utils.h"
+#include "led.h"
+#include "wwan_led.h"
+#include "wwan_perst.h"
+#include "sim_switch.h"
+#include "boardver_adc.h"
+#include "card_pres.h"
+#include <osmocom/core/timer.h>
+#include "usb_buf.h"
+
+/* array of generated USB Strings */
+extern unsigned char *usb_strings[];
+
+/* returns '1' in case we should break any endless loop */
+void board_exec_dbg_cmd(int ch)
+{
+ switch (ch) {
+ case '?':
+ printf("\t?\thelp\n\r");
+ printf("\tR\treset SAM3\n\r");
+ printf("\tl\tswitch off LED 1\n\r");
+ printf("\tL\tswitch on LED 1\n\r");
+ printf("\tg\tswitch off LED 2\n\r");
+ printf("\tG\tswitch on LED 2\n\r");
+ printf("\t1\tGenerate 1ms reset pulse on WWAN1\n\r");
+ printf("\t!\tSwitch Channel A from physical -> remote\n\r");
+ printf("\tt\t(pseudo)talloc report\n\r");
+ break;
+ case 'R':
+ printf("Asking NVIC to reset us\n\r");
+ USBD_Disconnect();
+ NVIC_SystemReset();
+ break;
+ case 'l':
+ led_blink(LED_GREEN, BLINK_ALWAYS_OFF);
+ printf("LED 1 switched off\n\r");
+ break;
+ case 'L':
+ led_blink(LED_GREEN, BLINK_ALWAYS_ON);
+ printf("LED 1 switched on\n\r");
+ break;
+ case 'g':
+ led_blink(LED_RED, BLINK_ALWAYS_OFF);
+ printf("LED 2 switched off\n\r");
+ break;
+ case 'G':
+ led_blink(LED_RED, BLINK_ALWAYS_ON);
+ printf("LED 2 switched on\n\r");
+ break;
+ case '1':
+ printf("Resetting Modem\n\r");
+ wwan_perst_do_reset_pulse(0, 300);
+ break;
+ case '!':
+ sim_switch_use_physical(0, 0);
+ break;
+ case 't':
+ talloc_report(NULL, stdout);
+ break;
+ default:
+ printf("Unknown command '%c'\n\r", ch);
+ break;
+ }
+}
+
+void board_main_top(void)
+{
+#ifndef APPLICATION_dfu
+ usb_buf_init();
+
+ wwan_led_init();
+ wwan_perst_init();
+ sim_switch_init();
+#endif
+
+ /* Obtain the circuit board version (currently just prints voltage) */
+ get_board_version_adc();
+#ifndef APPLICATION_dfu
+ /* Initialize checking for card insert/remove events */
+ card_present_init();
+#endif
+ wwan_perst_set(0, 0);
+}
+
+static int uart_has_loopback_jumper(void)
+{
+ unsigned int i;
+ const Pin uart_loopback_pins[] = {
+ {PIO_PA9A_URXD0, PIOA, ID_PIOA, PIO_INPUT, PIO_DEFAULT},
+ {PIO_PA10A_UTXD0, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}
+ };
+
+ /* Configure UART pins as I/O */
+ PIO_Configure(uart_loopback_pins, PIO_LISTSIZE(uart_loopback_pins));
+
+ /* Send pattern over UART TX and check if it is received on RX
+ * If the loop doesn't get interrupted, RxD always follows TxD and thus a
+ * loopback jumper has been placed on RxD/TxD, and we will boot
+ * into DFU unconditionally
+ */
+ int has_loopback_jumper = 1;
+ for (i = 0; i < 10; i++) {
+ /* Set TxD high; abort if RxD doesn't go high either */
+ PIO_Set(&uart_loopback_pins[1]);
+ if (!PIO_Get(&uart_loopback_pins[0])) {
+ has_loopback_jumper = 0;
+ break;
+ }
+ /* Set TxD low, abort if RxD doesn't go low either */
+ PIO_Clear(&uart_loopback_pins[1]);
+ if (PIO_Get(&uart_loopback_pins[0])) {
+ has_loopback_jumper = 0;
+ break;
+ }
+ }
+
+ /* Put pins back to UART mode */
+ const Pin uart_pins[] = {PINS_UART};
+ PIO_Configure(uart_pins, PIO_LISTSIZE(uart_pins));
+
+ return has_loopback_jumper;
+}
+
+int board_override_enter_dfu(void)
+{
+ /* If the loopback jumper is set, we enter DFU mode */
+ if (uart_has_loopback_jumper())
+ return 1;
+
+ return 0;
+}
+
+ static const Pin deton = {PIO_PA13, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT};
+ static const Pin detoff = {PIO_PA13, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT};
+
+void board_set_card_insert(struct cardem_inst *ci, bool card_insert)
+{
+ PIO_Configure(card_insert ? &deton : &detoff, 1);
+} \ No newline at end of file
diff --git a/firmware/libboard/ngff_cardem/source/card_pres.c b/firmware/libboard/ngff_cardem/source/card_pres.c
new file mode 100644
index 0000000..d425ec5
--- /dev/null
+++ b/firmware/libboard/ngff_cardem/source/card_pres.c
@@ -0,0 +1,72 @@
+/* card presence utilities
+ *
+ * (C) 2016-2021 by Harald Welte <hwelte@hmw-consulting.de>
+ *
+ * This program 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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.
+ */
+#include <osmocom/core/timer.h>
+#include "board.h"
+#include "utils.h"
+#include "card_pres.h"
+
+#define NUM_CARDPRES 1
+
+#define TIMER_INTERVAL_MS 500
+
+static const Pin pin_cardpres[NUM_CARDPRES] = { PIN_DET_USIM1_PRES };
+static int last_state[NUM_CARDPRES] = { -1 };
+static struct osmo_timer_list cardpres_timer;
+
+/* Determine if a SIM card is present in the given slot */
+int is_card_present(int port)
+{
+ const Pin *pin;
+ int present;
+
+ if (port < 0 || port >= NUM_CARDPRES)
+ return -1;
+ pin = &pin_cardpres[port];
+
+
+ /* high active here */
+ present = PIO_Get(pin);
+
+ return present;
+}
+
+static void cardpres_tmr_cb(void *data)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(pin_cardpres); i++) {
+ int state = is_card_present(i);
+ if (state != last_state[i]) {
+ TRACE_INFO("%u: Card Detect Status %d -> %d\r\n", i, last_state[i], state);
+ /* FIXME: report to USB host */
+ last_state[i] = state;
+ }
+ }
+
+ osmo_timer_schedule(&cardpres_timer, 0, TIMER_INTERVAL_MS*1000);
+}
+
+int card_present_init(void)
+{
+ unsigned int i;
+
+ PIO_Configure(pin_cardpres, ARRAY_SIZE(pin_cardpres));
+
+ /* start timer */
+ cardpres_timer.cb = cardpres_tmr_cb;
+ osmo_timer_schedule(&cardpres_timer, 0, TIMER_INTERVAL_MS*1000);
+
+ return 2;
+}
diff --git a/firmware/libboard/ngff_cardem/source/sim_switch.c b/firmware/libboard/ngff_cardem/source/sim_switch.c
new file mode 100644
index 0000000..999d7a7
--- /dev/null
+++ b/firmware/libboard/ngff_cardem/source/sim_switch.c
@@ -0,0 +1,77 @@
+/* Code to switch between local (physical) and remote (emulated) SIM
+ *
+ * (C) 2015-2017 by Harald Welte <hwelte@hmw-consulting.de>
+ *
+ * This program 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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.
+ */
+#include "board.h"
+#include "trace.h"
+#include "led.h"
+#include "sim_switch.h"
+
+//uart12bus 2-20e pa20
+//uart22bus 1-20e pa28
+//usim2bus 1-10e pa0 pivot
+//sim det 2-10e pa13
+
+static const Pin pins_default[] = {PINS_SIM_DEFAULT};
+static const Pin pins_cem[] = {PINS_SIM_CARDEM};
+
+static int initialized = 0;
+
+int sim_switch_use_physical(unsigned int nr, int physical)
+{
+ const Pin pin = PIN_MODEM_EN;// PIN_N_MODEM_PWR_ON;
+ enum led led;
+
+ if (!initialized) {
+ TRACE_ERROR("Somebody forgot to call sim_switch_init()\r\n");
+ sim_switch_init();
+ }
+
+ TRACE_INFO("Modem %d: %s SIM\n\r", nr,
+ physical ? "physical" : "virtual");
+
+ switch (nr) {
+ case 0:
+ led = LED_USIM1;
+ break;
+
+ default:
+ TRACE_ERROR("Invalid SIM%u\n\r", nr);
+ return -1;
+ }
+
+ if (physical) {
+ TRACE_INFO("%u: Use local/physical SIM\r\n", nr);
+ PIO_Configure(pins_default, PIO_LISTSIZE(pins_default));
+ led_blink(led, BLINK_ALWAYS_ON);
+ } else {
+ TRACE_INFO("%u: Use remote/emulated SIM\r\n", nr);
+ PIO_Configure(pins_cem, PIO_LISTSIZE(pins_cem));
+ led_blink(led, BLINK_5O_5F);
+ }
+
+ /* just power cycle the modem because this circumvents weird issues with unreliable signals */
+ PIO_Clear(&pin);
+ mdelay(200);
+ PIO_Set(&pin);
+
+
+ return 0;
+}
+
+int sim_switch_init(void)
+{
+ PIO_Configure(pins_default, PIO_LISTSIZE(pins_default));
+ initialized = 1;
+ return 1;
+}
diff --git a/firmware/libboard/ngff_cardem/source/wwan_led.c b/firmware/libboard/ngff_cardem/source/wwan_led.c
new file mode 100644
index 0000000..619d5c8
--- /dev/null
+++ b/firmware/libboard/ngff_cardem/source/wwan_led.c
@@ -0,0 +1,89 @@
+/* Code to read/track the status of the WWAN LEDs of attached modems
+ *
+ * This program 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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.
+ */
+/* Depending on the board this is running on, it might be possible
+ * for the controller to read the status of the WWAN LED output lines of
+ * the cellular modem. If the board supports this, it sets the
+ * PIN_WWAN1 and/or PIN_WWAN2 defines in its board.h file.
+ */
+#include "board.h"
+#include "wwan_led.h"
+
+#ifdef PIN_WWAN1
+static const Pin pin_wwan1 = PIN_WWAN1;
+
+static void wwan1_irqhandler(const Pin *pPin)
+{
+ int active = wwan_led_active(0);
+
+ TRACE_INFO("0: WWAN LED %u\r\n", active);
+
+ /* TODO: notify host via USB */
+}
+#endif
+
+#ifdef PIN_WWAN2
+static const Pin pin_wwan2 = PIN_WWAN2;
+
+static void wwan2_irqhandler(const Pin *pPin)
+{
+ int active = wwan_led_active(1);
+ TRACE_INFO("1: WWAN LED %u\r\n", active);
+
+ /* TODO: notify host via USB */
+}
+#endif
+
+/* determine if a given WWAN led is currently active or not */
+int wwan_led_active(int wwan)
+{
+ const Pin *pin;
+ int active;
+
+ switch (wwan) {
+#ifdef PIN_WWAN1
+ case 0:
+ pin = &pin_wwan1;
+ break;
+#endif
+#ifdef PIN_WWAN2
+ case 1:
+ pin = &pin_wwan2;
+ break;
+#endif
+ default:
+ return -1;
+ }
+
+ active = PIO_Get(pin) ? 0 : 1;
+ return active;
+}
+
+int wwan_led_init(void)
+{
+ int num_leds = 0;
+
+#ifdef PIN_WWAN1
+ PIO_Configure(&pin_wwan1, 1);
+ PIO_ConfigureIt(&pin_wwan1, wwan1_irqhandler);
+ PIO_EnableIt(&pin_wwan1);
+ num_leds++;
+#endif
+
+#ifdef PIN_WWAN2
+ PIO_Configure(&pin_wwan2, 1);
+ PIO_ConfigureIt(&pin_wwan2, wwan2_irqhandler);
+ PIO_EnableIt(&pin_wwan2);
+ num_leds++;
+#endif
+ return num_leds;
+}
diff --git a/firmware/libboard/ngff_cardem/source/wwan_perst.c b/firmware/libboard/ngff_cardem/source/wwan_perst.c
new file mode 100644
index 0000000..b314781
--- /dev/null
+++ b/firmware/libboard/ngff_cardem/source/wwan_perst.c
@@ -0,0 +1,123 @@
+/* Code to control the PERST lines of attached modems
+ *
+ * This program 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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.
+ */
+/* Depending on the board this is running on, it might be possible
+ * for the controller to set the status of the PERST input line of
+ * the cellular modem. If the board supports this, it sets the
+ * PIN_PERST1 and/or PIN_PERST2 defines in its board.h file.
+ */
+#include "board.h"
+#include "trace.h"
+#include "wwan_perst.h"
+#include <osmocom/core/timer.h>
+
+struct wwan_perst {
+ uint8_t idx;
+ const Pin pin;
+ struct osmo_timer_list timer;
+};
+
+#ifdef PIN_PERST1
+static struct wwan_perst perst1 = {
+ .idx = 0,
+ .pin = PIN_PERST1,
+};
+#endif
+
+#ifdef PIN_PERST2
+static struct wwan_perst perst2 = {
+ .idx = 1,
+ .pin = PIN_PERST2,
+};
+#endif
+
+static int initialized = 0;
+
+static void perst_tmr_cb(void *data)
+{
+ struct wwan_perst *perst = data;
+ /* release the (low-active) reset */
+ TRACE_INFO("%u: De-asserting modem reset\r\n", perst->idx);
+ PIO_Clear(&perst->pin);
+}
+
+static struct wwan_perst *get_perst_for_modem(int modem_nr)
+{
+ if (!initialized) {
+ TRACE_ERROR("Somebody forgot to call wwan_perst_init()\r\n");
+ wwan_perst_init();
+ }
+
+ switch (modem_nr) {
+#ifdef PIN_PERST1
+ case 0:
+ return &perst1;
+#endif
+#ifdef PIN_PERST2
+ case 1:
+ return &perst2;
+#endif
+ default:
+ return NULL;
+ }
+}
+
+int wwan_perst_do_reset_pulse(int modem_nr, unsigned int duration_ms)
+{
+ struct wwan_perst *perst = get_perst_for_modem(modem_nr);
+ if (!perst)
+ return -1;
+
+ TRACE_INFO("%u: Asserting modem reset\r\n", modem_nr);
+ PIO_Set(&perst->pin);
+ osmo_timer_schedule(&perst->timer, duration_ms/1000, (duration_ms%1000)*1000);
+
+ return 0;
+}
+
+int wwan_perst_set(int modem_nr, int active)
+{
+ struct wwan_perst *perst = get_perst_for_modem(modem_nr);
+ if (!perst)
+ return -1;
+
+ osmo_timer_del(&perst->timer);
+ if (active) {
+ TRACE_INFO("%u: Asserting modem reset\r\n", modem_nr);
+ PIO_Set(&perst->pin);
+ } else {
+ TRACE_INFO("%u: De-asserting modem reset\r\n", modem_nr);
+ PIO_Clear(&perst->pin);
+ }
+
+ return 0;
+}
+
+int wwan_perst_init(void)
+{
+ int num_perst = 0;
+#ifdef PIN_PERST1
+ PIO_Configure(&perst1.pin, 1);
+ perst1.timer.cb = perst_tmr_cb;
+ perst1.timer.data = (void *) &perst1;
+ num_perst++;
+#endif
+
+#ifdef PIN_PERST2
+ PIO_Configure(&perst2.pin, 1);
+ perst2.timer.cb = perst_tmr_cb;
+ perst2.timer.data = (void *) &perst2;
+ num_perst++;
+#endif
+ initialized = 1;
+ return num_perst;
+}
diff --git a/firmware/libboard/octsimtest/include/board.h b/firmware/libboard/octsimtest/include/board.h
new file mode 100644
index 0000000..3540aa2
--- /dev/null
+++ b/firmware/libboard/octsimtest/include/board.h
@@ -0,0 +1,119 @@
+/* octSIMtest with SAM3S board definition
+ *
+ * (C) 2019 by sysmocom -s.f.m.c. GmbH, Author:Joachim Steiger <jsteiger@sysmocom.de>
+ *
+ * This program 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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.
+ */
+#pragma once
+#include "board_common.h"
+#include "simtrace_usb.h"
+
+/* Name of the board */
+#define BOARD_NAME "OCTSIMTEST"
+/* Board definition */
+#define octsimtest
+
+/** oscillator used as main clock source (in Hz) */
+#define BOARD_MAINOSC 18432000
+/** desired main clock frequency (in Hz, based on BOARD_MAINOSC) */
+#define BOARD_MCK 58982400 // 18.432 * 16 / 5
+
+/** Pin configuration **/
+
+/** there is no red LED, but the code needs this second LED, thus we provide an unused pin */
+#define PIO_LED_RED PIO_PB13
+/** MCU pin connected to green LED, which is actually amber, and the logic is inverted since it is connected to an NPN transistor (used as open drain) */
+#define PIO_LED_GREEN PIO_PA4
+/** red LED pin definition */
+#define PIN_LED_RED {PIO_LED_RED, PIOB, ID_PIOB, PIO_OUTPUT_1, PIO_DEFAULT}
+/** green LED pin definition */
+#define PIN_LED_GREEN {PIO_LED_GREEN, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
+/** LEDs pin definition */
+#define PINS_LEDS PIN_LED_RED, PIN_LED_GREEN
+/** index for red LED in LEDs pin definition array */
+#define LED_NUM_RED 0
+/** index for green LED in LEDs pin definition array */
+#define LED_NUM_GREEN 1
+
+/* Button to force bootloader start (shorted to ground when pressed */
+#define PIN_BOOTLOADER_SW {PIO_PA5, PIOA, ID_PIOA, PIO_INPUT, PIO_PULLUP}
+
+// FIXME PA8 is 32khz xtal on octsimtest
+/* Pull card presence pin high (shorted to ground in card slot when card is present) */
+
+/** Phone connection **/
+/* Phone USIM slot 1 VCC pin (VCC_PHONE in schematic) */
+#define PIN_USIM1_VCC {PIO_PA25, PIOA, ID_PIOA, PIO_INPUT, PIO_DEFAULT}
+/* Phone USIM slot 1 RST pin (active low; RST_PHONE in schematic) */
+#define PIN_USIM1_nRST {PIO_PA24, PIOA, ID_PIOA, PIO_INPUT, PIO_IT_EDGE | PIO_DEGLITCH }
+/* Phone I/O data signal input/output (I/O_PHONE in schematic) */
+#define PIN_PHONE_IO {PIO_PA22A_TXD1, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
+/* Phone CLK clock input (CLK_PHONE in schematic) */
+#define PIN_PHONE_CLK {PIO_PA23A_SCK1, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
+/* Pin used to switch level shifter in I/O line between rx (0) and tx (1) */
+#define PIN_USIM1_IO_DIR {PIO_PA26, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}
+/* Pin used for phone USIM slot 1 communication */
+#define PINS_USIM1 PIN_PHONE_IO, PIN_PHONE_CLK, PIN_PHONE_CLK_INPUT, PIN_USIM1_VCC, PIN_PHONE_IO_INPUT, PIN_USIM1_nRST, PIN_USIM1_IO_DIR
+/* Phone I/O data signal input/output (unused USART RX input; connected to I/O_PHONE in schematic) */
+#define PIN_PHONE_IO_INPUT {PIO_PA21A_RXD1, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
+/* Pin used as clock input (to measure the ETU duration; connected to CLK_PHONE in schematic) */
+#define PIN_PHONE_CLK_INPUT {PIO_PA29B_TCLK2, PIOA, ID_PIOA, PIO_PERIPH_B, PIO_DEFAULT}
+
+/** Default pin configuration **/
+
+/** External SPI flash interface **/
+/* SPI MISO pin definition */
+#define PIN_SPI_MISO {PIO_PA12A_MISO, PIOA, PIOA, PIO_PERIPH_A, PIO_PULLUP}
+/* SPI MOSI pin definition */
+#define PIN_SPI_MOSI {PIO_PA13A_MOSI, PIOA, PIOA, PIO_PERIPH_A, PIO_DEFAULT}
+/* SPI SCK pin definition */
+#define PIN_SPI_SCK {PIO_PA14A_SPCK, PIOA, PIOA, PIO_PERIPH_A, PIO_DEFAULT}
+/* SPI pins definition. Contains MISO, MOSI & SCK */
+#define PINS_SPI PIN_SPI_MISO, PIN_SPI_MOSI, PIN_SPI_SCK
+/* SPI chip select 0 pin definition */
+#define PIN_SPI_NPCS0 {PIO_PA11A_NPCS0, PIOA, PIOA, PIO_PERIPH_A, PIO_DEFAULT}
+/* SPI flash write protect pin (active low, pulled low) */
+#define PIN_SPI_WP {PA15, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}
+
+/** USB definitions */
+/* OpenMoko SIMtrace 2 USB vendor ID */
+#define BOARD_USB_VENDOR_ID USB_VENDOR_OPENMOKO
+/* OpenMoko SIMtrace 2 USB product ID (main application/runtime mode) */
+#define BOARD_USB_PRODUCT_ID USB_PRODUCT_OCTSIMTEST
+/* OpenMoko SIMtrace 2 DFU USB product ID (DFU bootloader/DFU mode) */
+#define BOARD_DFU_USB_PRODUCT_ID USB_PRODUCT_OCTSIMTEST
+/* USB release number (bcdDevice, shown as 0.00) */
+#define BOARD_USB_RELEASE 0x000
+/* Indicate SIMtrace is bus power in USB attributes */
+#define BOARD_USB_BMATTRIBUTES USBConfigurationDescriptor_BUSPOWERED_NORWAKEUP
+
+#define DETECT_VCC_BY_ADC
+/* we have a resistive voltage divider of 47 + 30 kOhms to also detect 5V supply power */
+#define VCC_UV_THRESH_1V8 (1500000*47)/(47+30)
+#define VCC_UV_THRESH_3V (2500000*47)/(47+30)
+
+#define HAVE_SLOT_MUX
+
+#define HAVE_BOARD_CARDINSERT
+struct cardem_inst;
+void board_set_card_insert(struct cardem_inst *ci, bool card_insert);
+
+/** Supported modes */
+/* SIMtrace board supports sniffer mode */
+//#define HAVE_SNIFFER
+/* SIMtrace board supports CCID mode */
+//#define HAVE_CCID
+/* SIMtrace board supports card emulation mode */
+#define HAVE_CARDEM
+/* SIMtrace board supports man-in-the-middle mode */
+//#define HAVE_MITM
+/* octsimtest board supports gpio_test mode */
+#define HAVE_GPIO_TEST
diff --git a/firmware/libboard/octsimtest/include/i2c.h b/firmware/libboard/octsimtest/include/i2c.h
new file mode 100644
index 0000000..7edad2f
--- /dev/null
+++ b/firmware/libboard/octsimtest/include/i2c.h
@@ -0,0 +1,24 @@
+/* I2C EEPROM memory read and write utilities
+ *
+ * This program 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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.
+ */
+#pragma once
+
+#include <stdbool.h>
+
+void i2c_pin_init(void);
+
+bool i2c_write_byte(bool send_start, bool send_stop, uint8_t byte);
+uint8_t i2c_read_byte(bool nack, bool send_stop);
+void i2c_stop_cond(void);
+
+int eeprom_write_byte(uint8_t slave, uint8_t addr, uint8_t byte);
+int eeprom_read_byte(uint8_t slave, uint8_t addr);
diff --git a/firmware/libboard/octsimtest/include/mcp23017.h b/firmware/libboard/octsimtest/include/mcp23017.h
new file mode 100644
index 0000000..1f05d3d
--- /dev/null
+++ b/firmware/libboard/octsimtest/include/mcp23017.h
@@ -0,0 +1,23 @@
+/* mcp23017 i2c gpio expander read and write utilities
+ *
+ * This program 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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.
+ */
+#pragma once
+
+#define MCP23017_ADDRESS 0x20
+
+int mcp23017_init(uint8_t slave, uint8_t iodira, uint8_t iodirb);
+int mcp23017_test(uint8_t slave);
+int mcp23017_toggle(uint8_t slave);
+int mcp23017_set_output_a(uint8_t slave, uint8_t val);
+int mcp23017_set_output_b(uint8_t slave, uint8_t val);
+//int mcp23017_write_byte(uint8_t slave, uint8_t addr, uint8_t byte);
+//int mcp23017_read_byte(uint8_t slave, uint8_t addr);
diff --git a/firmware/libboard/octsimtest/include/mux.h b/firmware/libboard/octsimtest/include/mux.h
new file mode 100644
index 0000000..3181478
--- /dev/null
+++ b/firmware/libboard/octsimtest/include/mux.h
@@ -0,0 +1,17 @@
+#pragma once
+
+void mux_init(void);
+int mux_set_slot(uint8_t s);
+int mux_get_slot(void);
+void mux_set_freq(uint8_t s);
+
+/* this reflects the wiring between U5 and U4 */
+#define MUX_FREQ_DIV_2 0
+#define MUX_FREQ_DIV_4 1
+#define MUX_FREQ_DIV_16 2
+#define MUX_FREQ_DIV_32 3
+#define MUX_FREQ_DIV_32 3
+#define MUX_FREQ_DIV_128 4
+#define MUX_FREQ_DIV_512 5
+#define MUX_FREQ_DIV_2048 6
+#define MUX_FREQ_DIV_4096 7
diff --git a/firmware/libboard/octsimtest/product_string.txt b/firmware/libboard/octsimtest/product_string.txt
new file mode 100644
index 0000000..83cbcf5
--- /dev/null
+++ b/firmware/libboard/octsimtest/product_string.txt
@@ -0,0 +1 @@
+sysmoOCTSIM-Tester
diff --git a/firmware/libboard/octsimtest/source/board_octsimtest.c b/firmware/libboard/octsimtest/source/board_octsimtest.c
new file mode 100644
index 0000000..92496da
--- /dev/null
+++ b/firmware/libboard/octsimtest/source/board_octsimtest.c
@@ -0,0 +1,120 @@
+/* SIMtrace with SAM3S specific application code
+ *
+ * (C) 2017 by Harald Welte <laforge@gnumonks.org>
+ * (C) 2018 by sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon@sysmocom.de>
+ *
+ * This program 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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.
+ */
+#include <stdbool.h>
+#include "board.h"
+#include "simtrace.h"
+#include "utils.h"
+#include "sim_switch.h"
+#include <osmocom/core/timer.h>
+#include "usb_buf.h"
+#include "i2c.h"
+#include "mcp23017.h"
+#include "mux.h"
+
+static bool mcp2317_present = false;
+
+void board_exec_dbg_cmd(int ch)
+{
+ switch (ch) {
+ case '?':
+ printf("\t?\thelp\n\r");
+ printf("\t0-8\tselect physical SIM slot\n\r");
+ printf("\tR\treset SAM3\n\r");
+ printf("\tm\trun mcp23017 test\n\r");
+ printf("\ti\tset card insert via I2C\n\r");
+ printf("\tI\tdisable card insert\n\r");
+ break;
+ case '0': mux_set_slot(0); break;
+ case '1': mux_set_slot(1); break;
+ case '2': mux_set_slot(2); break;
+ case '3': mux_set_slot(3); break;
+ case '4': mux_set_slot(4); break;
+ case '5': mux_set_slot(5); break;
+ case '6': mux_set_slot(6); break;
+ case '7': mux_set_slot(7); break;
+ case 'R':
+ printf("Asking NVIC to reset us\n\r");
+ USBD_Disconnect();
+ NVIC_SystemReset();
+ break;
+ case 'm':
+ mcp23017_test(MCP23017_ADDRESS);
+ break;
+ case 'i':
+ printf("Setting card insert (slot=%u)\r\n", mux_get_slot());
+ mcp23017_set_output_a(MCP23017_ADDRESS, (1 << mux_get_slot()));
+ break;
+ case 'I':
+ printf("Releasing card insert (slot=%u)\r\n", mux_get_slot());
+ mcp23017_set_output_a(MCP23017_ADDRESS, 0);
+ break;
+ default:
+ printf("Unknown command '%c'\n\r", ch);
+ break;
+ }
+}
+
+void board_main_top(void)
+{
+#ifndef APPLICATION_dfu
+ usb_buf_init();
+
+ mux_init();
+ i2c_pin_init();
+ /* PORT A: all outputs, Port B0 output, B1..B7 unused */
+ if (mcp23017_init(MCP23017_ADDRESS, 0x00, 0xfe) == 0) {
+ mcp2317_present = true;
+ mcp23017_set_output_a(MCP23017_ADDRESS, 0);
+ }
+ /* Initialize checking for card insert/remove events */
+ //card_present_init();
+#endif
+}
+
+int board_override_enter_dfu(void)
+{
+ const Pin bl_sw_pin = PIN_BOOTLOADER_SW;
+
+ PIO_Configure(&bl_sw_pin, 1);
+
+ /* Enter DFU bootloader in case the respective button is pressed */
+ if (PIO_Get(&bl_sw_pin) == 0) {
+ /* do not print to early since the console is not initialized yet */
+ //printf("BOOTLOADER switch pressed -> Force DFU\n\r");
+ return 1;
+ } else
+ return 0;
+}
+
+void board_set_card_insert(struct cardem_inst *ci, bool card_insert)
+{
+ int s = mux_get_slot();
+
+ /* A0 .. A7 of the MCP are each connected to the gate of a FET which closes
+ * the sim-present signal of the respective slot */
+
+ if (mcp2317_present) {
+ if (card_insert) {
+ /* we must enable card-presence of the active slot and disable it on all others */
+ mcp23017_set_output_a(MCP23017_ADDRESS, (1 << s));
+ } else {
+ /* we disable all card insert signals */
+ mcp23017_set_output_a(MCP23017_ADDRESS, 0);
+ }
+ } else {
+ TRACE_WARNING("No MCP23017 present; cannot set CARD_INSERT\r\n");
+ }
+}
diff --git a/firmware/libboard/octsimtest/source/i2c.c b/firmware/libboard/octsimtest/source/i2c.c
new file mode 100644
index 0000000..8627b69
--- /dev/null
+++ b/firmware/libboard/octsimtest/source/i2c.c
@@ -0,0 +1,221 @@
+/* I2C EEPROM memory read and write utilities
+ *
+ * This program 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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.
+ */
+#include "board.h"
+#include <stdbool.h>
+
+/* Low-Level I2C Routines */
+
+static const Pin pin_sda = {PIO_PA30, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_OPENDRAIN };
+static const Pin pin_sda_in = {PIO_PA30, PIOA, ID_PIOA, PIO_INPUT, PIO_DEFAULT };
+static const Pin pin_scl = {PIO_PA31, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_OPENDRAIN };
+
+static void i2c_delay()
+{
+ volatile int v;
+ int i;
+
+ /* 100 cycles results in SCL peak length of 44us, so it's about
+ * 440ns per cycle here */
+ for (i = 0; i < 14; i++) {
+ v = 0;
+ }
+}
+
+void i2c_pin_init(void)
+{
+ PIO_Configure(&pin_scl, PIO_LISTSIZE(pin_scl));
+ PIO_Configure(&pin_sda, PIO_LISTSIZE(pin_sda));
+}
+
+static void set_scl(void)
+{
+ PIO_Set(&pin_scl);
+ i2c_delay();
+}
+
+static void set_sda(void)
+{
+ PIO_Set(&pin_sda);
+ i2c_delay();
+}
+
+static void clear_scl(void)
+{
+ PIO_Clear(&pin_scl);
+ i2c_delay();
+}
+
+static void clear_sda(void)
+{
+ PIO_Clear(&pin_sda);
+ i2c_delay();
+}
+
+static bool read_sda(void)
+{
+ bool ret;
+
+ PIO_Configure(&pin_sda_in, PIO_LISTSIZE(pin_sda_in));
+ if (PIO_Get(&pin_sda_in))
+ ret = true;
+ else
+ ret = false;
+ PIO_Configure(&pin_sda, PIO_LISTSIZE(pin_sda));
+
+ return ret;
+}
+
+/* Core I2C Routines */
+
+static bool i2c_started = false;
+
+static void i2c_start_cond(void)
+{
+ if (i2c_started) {
+ set_sda();
+ set_scl();
+ }
+
+ clear_sda();
+ i2c_delay();
+ clear_scl();
+ i2c_started = true;
+}
+
+void i2c_stop_cond(void)
+{
+ clear_sda();
+ set_scl();
+ set_sda();
+ i2c_delay();
+ i2c_started = false;
+}
+
+static void i2c_write_bit(bool bit)
+{
+ if (bit)
+ set_sda();
+ else
+ clear_sda();
+ i2c_delay(); // ?
+ set_scl();
+ clear_scl();
+}
+
+static bool i2c_read_bit(void)
+{
+ bool bit;
+
+ set_sda();
+ set_scl();
+ bit = read_sda();
+ clear_scl();
+
+ return bit;
+}
+
+bool i2c_write_byte(bool send_start, bool send_stop, uint8_t byte)
+{
+ uint8_t bit;
+ bool nack;
+
+ if (send_start)
+ i2c_start_cond();
+
+ for (bit = 0; bit < 8; bit++) {
+ i2c_write_bit((byte & 0x80) != 0);
+ byte <<= 1;
+ }
+
+ nack = i2c_read_bit();
+
+ if (send_stop)
+ i2c_stop_cond();
+
+ return nack;
+}
+
+uint8_t i2c_read_byte(bool nack, bool send_stop)
+{
+ uint8_t byte = 0;
+ uint8_t bit;
+
+ for (bit = 0; bit < 8; bit++) {
+ byte = (byte << 1) | i2c_read_bit();
+ }
+
+ i2c_write_bit(nack);
+
+ if (send_stop)
+ i2c_stop_cond();
+
+ return byte;
+}
+
+
+/* EEPROM related code */
+
+int eeprom_write_byte(uint8_t slave, uint8_t addr, uint8_t byte)
+{
+ bool nack;
+
+ WDT_Restart(WDT);
+
+ /* Write slave address */
+ nack = i2c_write_byte(true, false, slave << 1);
+ if (nack)
+ goto out_stop;
+ nack = i2c_write_byte(false, false, addr);
+ if (nack)
+ goto out_stop;
+ nack = i2c_write_byte(false, true, byte);
+ if (nack)
+ goto out_stop;
+ /* Wait tWR time to ensure EEPROM is writing correctly (tWR = 5 ms for AT24C02) */
+ mdelay(5);
+
+out_stop:
+ i2c_stop_cond();
+ if (nack)
+ return -1;
+ else
+ return 0;
+}
+
+int eeprom_read_byte(uint8_t slave, uint8_t addr)
+{
+ bool nack;
+
+ WDT_Restart(WDT);
+
+ /* dummy write cycle */
+ nack = i2c_write_byte(true, false, slave << 1);
+ if (nack)
+ goto out_stop;
+ nack = i2c_write_byte(false, false, addr);
+ if (nack)
+ goto out_stop;
+ /* Re-start with read */
+ nack = i2c_write_byte(true, false, (slave << 1) | 1);
+ if (nack)
+ goto out_stop;
+
+ return i2c_read_byte(true, true);
+
+out_stop:
+ i2c_stop_cond();
+ if (nack)
+ return -1;
+ else
+ return 0;
+}
diff --git a/firmware/libboard/octsimtest/source/mcp23017.c b/firmware/libboard/octsimtest/source/mcp23017.c
new file mode 100644
index 0000000..959f2c6
--- /dev/null
+++ b/firmware/libboard/octsimtest/source/mcp23017.c
@@ -0,0 +1,156 @@
+#include "board.h"
+#include <stdbool.h>
+#include "i2c.h"
+#include "mcp23017.h"
+
+
+//defines from https://github.com/adafruit/Adafruit-MCP23017-Arduino-Library/blob/master/Adafruit_MCP23017.h under BSD license
+
+// registers
+#define MCP23017_IODIRA 0x00
+#define MCP23017_IPOLA 0x02
+#define MCP23017_GPINTENA 0x04
+#define MCP23017_DEFVALA 0x06
+#define MCP23017_INTCONA 0x08
+#define MCP23017_IOCONA 0x0A
+#define MCP23017_GPPUA 0x0C
+#define MCP23017_INTFA 0x0E
+#define MCP23017_INTCAPA 0x10
+#define MCP23017_GPIOA 0x12
+#define MCP23017_OLATA 0x14
+
+
+#define MCP23017_IODIRB 0x01
+#define MCP23017_IPOLB 0x03
+#define MCP23017_GPINTENB 0x05
+#define MCP23017_DEFVALB 0x07
+#define MCP23017_INTCONB 0x09
+#define MCP23017_IOCONB 0x0B
+#define MCP23017_GPPUB 0x0D
+#define MCP23017_INTFB 0x0F
+#define MCP23017_INTCAPB 0x11
+#define MCP23017_GPIOB 0x13
+#define MCP23017_OLATB 0x15
+
+#define MCP23017_INT_ERR 255
+
+
+//bool i2c_write_byte(bool send_start, bool send_stop, uint8_t byte)
+//uint8_t i2c_read_byte(bool nack, bool send_stop)
+//static void i2c_stop_cond(void)
+
+int mcp23017_write_byte(uint8_t slave, uint8_t addr, uint8_t byte)
+{
+ bool nack;
+
+ WDT_Restart(WDT);
+
+// Write slave address
+ nack = i2c_write_byte(true, false, slave << 1);
+ if (nack)
+ goto out_stop;
+ nack = i2c_write_byte(false, false, addr);
+ if (nack)
+ goto out_stop;
+ nack = i2c_write_byte(false, true, byte);
+ if (nack)
+ goto out_stop;
+
+out_stop:
+ i2c_stop_cond();
+ if (nack)
+ return -1;
+ else
+ return 0;
+}
+
+int mcp23017_read_byte(uint8_t slave, uint8_t addr)
+{
+ bool nack;
+
+ WDT_Restart(WDT);
+
+ // dummy write cycle
+ nack = i2c_write_byte(true, false, slave << 1);
+ if (nack)
+ goto out_stop;
+ nack = i2c_write_byte(false, false, addr);
+ if (nack)
+ goto out_stop;
+ // Re-start with read
+ nack = i2c_write_byte(true, false, (slave << 1) | 1);
+ if (nack)
+ goto out_stop;
+
+ return i2c_read_byte(true, true);
+
+out_stop:
+ i2c_stop_cond();
+ if (nack)
+ return -1;
+ else
+ return 0;
+}
+
+int mcp23017_init(uint8_t slave, uint8_t iodira, uint8_t iodirb)
+{
+ TRACE_DEBUG("mcp23017_init\n\r");
+
+ // all gpio input
+ if (mcp23017_write_byte(slave, MCP23017_IODIRA, iodira))
+ goto out_err;
+ // msb of portb output, rest input
+ if (mcp23017_write_byte(slave, MCP23017_IODIRB, iodirb))
+ goto out_err;
+ if (mcp23017_write_byte(slave, MCP23017_IOCONA, 0x20)) //disable SEQOP (autoinc addressing)
+ goto out_err;
+
+ TRACE_DEBUG("mcp23017 found\n\r");
+ return 0;
+
+out_err:
+ TRACE_WARNING("mcp23017 NOT found!\n\r");
+ return -1;
+}
+
+int mcp23017_test(uint8_t slave)
+{
+ printf("mcp23017_test\n\r");
+ printf("GPIOA 0x%x\n\r", mcp23017_read_byte(slave,MCP23017_GPIOA));
+ printf("GPIOB 0x%x\n\r", mcp23017_read_byte(slave,MCP23017_GPIOB));
+ printf("IODIRA 0x%x\n\r", mcp23017_read_byte(slave,MCP23017_IODIRA));
+ printf("IODIRB 0x%x\n\r", mcp23017_read_byte(slave,MCP23017_IODIRB));
+ printf("IOCONA 0x%x\n\r", mcp23017_read_byte(slave,MCP23017_IOCONA));
+ printf("IOCONB 0x%x\n\r", mcp23017_read_byte(slave,MCP23017_IOCONB));
+
+ return 0;
+}
+
+int mcp23017_set_output_a(uint8_t slave, uint8_t val)
+{
+ return mcp23017_write_byte(slave, MCP23017_OLATA, val);
+}
+
+int mcp23017_set_output_b(uint8_t slave, uint8_t val)
+{
+ return mcp23017_write_byte(slave, MCP23017_OLATB, val);
+}
+
+int mcp23017_toggle(uint8_t slave)
+{
+ // example writing MSB of gpio
+ static bool foo=false;
+ if (foo)
+ {
+ printf("+\n\r");
+ mcp23017_write_byte(slave, MCP23017_OLATB, 0x80);
+ foo=false;
+ }
+ else
+ {
+ printf("-\n\r");
+ mcp23017_write_byte(slave, MCP23017_OLATB, 0x00);
+ foo=true;
+ }
+ return 0;
+}
diff --git a/firmware/libboard/octsimtest/source/mux.c b/firmware/libboard/octsimtest/source/mux.c
new file mode 100644
index 0000000..d37adfb
--- /dev/null
+++ b/firmware/libboard/octsimtest/source/mux.c
@@ -0,0 +1,109 @@
+/* sysmoOCTSIMTEST support for multiplexers
+ *
+ * (C) 2021 by Harald Welte <laforge@gnumonks.org>
+ *
+ * This program 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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.
+ */
+
+#include "board.h"
+#include "mux.h"
+#include <stdbool.h>
+#include <errno.h>
+
+/* 3-bit S0..S2 signal for slot selection */
+static const Pin pin_in_sel[3] = {
+ { PIO_PA1, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT },
+ { PIO_PA2, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT },
+ { PIO_PA3, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT },
+};
+
+/* 3-bit S0..S2 signal for frequency divider selection */
+static const Pin pin_freq_sel[3] = {
+ { PIO_PA16, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT },
+ { PIO_PA17, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT },
+ { PIO_PA18, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT },
+};
+
+/* low-active output enable for all muxes */
+static const Pin pin_oe = { PIO_PA19, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT };
+
+static uint8_t g_mux_slot = 0;
+
+/* initialize the external 1:8 multiplexers */
+void mux_init(void)
+{
+ PIO_Configure(&pin_oe, PIO_LISTSIZE(pin_oe));
+ PIO_Configure(pin_in_sel, PIO_LISTSIZE(pin_in_sel));
+ PIO_Configure(pin_freq_sel, PIO_LISTSIZE(pin_freq_sel));
+
+ mux_set_slot(0);
+}
+
+/* set the slot selection mux */
+int mux_set_slot(uint8_t s)
+{
+ TRACE_INFO("%s(%u)\r\n", __func__, s);
+
+ if (s > 7)
+ return -EINVAL;
+
+ /* !OE = H: disconnect input and output of muxes */
+ PIO_Set(&pin_oe);
+
+ if (s & 1)
+ PIO_Set(&pin_in_sel[0]);
+ else
+ PIO_Clear(&pin_in_sel[0]);
+ if (s & 2)
+ PIO_Set(&pin_in_sel[1]);
+ else
+ PIO_Clear(&pin_in_sel[1]);
+ if (s & 4)
+ PIO_Set(&pin_in_sel[2]);
+ else
+ PIO_Clear(&pin_in_sel[2]);
+
+ /* !OE = L: (re-)enable the output of muxes */
+ PIO_Clear(&pin_oe);
+
+ g_mux_slot = s;
+ return s;
+}
+
+int mux_get_slot(void)
+{
+ return g_mux_slot;
+}
+
+/* set the frequency divider mux */
+void mux_set_freq(uint8_t s)
+{
+ TRACE_INFO("%s(%u)\r\n", __func__, s);
+
+ /* no need for 'break before make' here, this would also affect
+ * the SIM card I/O signals which we don't want to disturb */
+
+ if (s & 1)
+ PIO_Set(&pin_freq_sel[0]);
+ else
+ PIO_Clear(&pin_freq_sel[0]);
+ if (s & 2)
+ PIO_Set(&pin_freq_sel[1]);
+ else
+ PIO_Clear(&pin_freq_sel[1]);
+ if (s & 4)
+ PIO_Set(&pin_freq_sel[2]);
+ else
+ PIO_Clear(&pin_freq_sel[2]);
+
+ /* !OE = L: ensure enable the output of muxes */
+ PIO_Clear(&pin_oe);
+}
diff --git a/firmware/libboard/octsimtest/source/sim_switch.c b/firmware/libboard/octsimtest/source/sim_switch.c
new file mode 100644
index 0000000..f001360
--- /dev/null
+++ b/firmware/libboard/octsimtest/source/sim_switch.c
@@ -0,0 +1,33 @@
+/* Code to switch between local (physical) and remote (emulated) SIM
+ *
+ * (C) 2021 by Harald Welte <hwelte@hmw-consulting.de>
+ *
+ * This program 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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.
+ */
+#include "board.h"
+#include "trace.h"
+#include "sim_switch.h"
+
+int sim_switch_use_physical(unsigned int nr, int physical)
+{
+ if (physical) {
+ TRACE_ERROR("%u: Use local/physical SIM - UNSUPPORTED!\r\n", nr);
+ } else {
+ TRACE_INFO("%u: Use remote/emulated SIM\r\n", nr);
+ }
+
+ return 0;
+}
+
+int sim_switch_init(void)
+{
+ return 1; // SIMtrace hardware has only one switchable interface
+}
diff --git a/firmware/libboard/owhw/include/board.h b/firmware/libboard/owhw/include/board.h
index 8c0052d..1980324 100644
--- a/firmware/libboard/owhw/include/board.h
+++ b/firmware/libboard/owhw/include/board.h
@@ -12,10 +12,6 @@
* 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 this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*/
#pragma once
#include "board_common.h"
@@ -31,6 +27,24 @@
/** desired main clock frequency (in Hz, based on BOARD_MAINOSC) */
#define BOARD_MCK 58982400 // 18.432 * 16 / 5
+/** MCU pin connected to red LED */
+#define PIO_LED_RED PIO_PA17
+/** MCU pin connected to green LED */
+#define PIO_LED_GREEN PIO_PA18
+/** red LED pin definition */
+#define PIN_LED_RED {PIO_LED_RED, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
+/** green LED pin definition */
+#define PIN_LED_GREEN {PIO_LED_GREEN, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
+/** LEDs pin definition */
+#define PINS_LEDS PIN_LED_RED, PIN_LED_GREEN
+/** index for red LED in LEDs pin definition array */
+#define LED_NUM_RED 0
+/** index for green LED in LEDs pin definition array */
+#define LED_NUM_GREEN 1
+
+/* pin connected to the SIMTRACE_BOOTLOADER signal. set high to force DFU bootloader start */
+#define PIN_BOOTLOADER {PIO_PA31, PIOA, ID_PIOA, PIO_INPUT, PIO_DEFAULT}
+
/* USIM 2 interface (USART) */
#define PIN_USIM2_CLK {PIO_PA2, PIOA, ID_PIOA, PIO_PERIPH_B, PIO_DEFAULT}
#define PIN_USIM2_IO {PIO_PA6, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
diff --git a/firmware/libboard/owhw/product_string.txt b/firmware/libboard/owhw/product_string.txt
new file mode 100644
index 0000000..77c3b1b
--- /dev/null
+++ b/firmware/libboard/owhw/product_string.txt
@@ -0,0 +1 @@
+OWHW
diff --git a/firmware/libboard/owhw/source/owhw.c b/firmware/libboard/owhw/source/owhw.c
index 3bf51ec..1238082 100644
--- a/firmware/libboard/owhw/source/owhw.c
+++ b/firmware/libboard/owhw/source/owhw.c
@@ -1,7 +1,7 @@
/* Card simulator specific functions
*
* (C) 2015-2017 by Harald Welte <hwelte@hmw-consulting.de>
- * (C) 2018, sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon@sysmocom.de>
+ * (C) 2018-2019, sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon@sysmocom.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -12,10 +12,6 @@
* 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 this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*/
#include "chip.h"
@@ -65,3 +61,16 @@ void cardsim_gpio_init(void)
{
PIO_Configure(pins_cardsim, ARRAY_SIZE(pins_cardsim));
}
+
+int board_override_enter_dfu(void)
+{
+ const Pin bl_pin = PIN_BOOTLOADER;
+
+ PIO_Configure(&bl_pin, 1);
+
+ if (PIO_Get(&bl_pin) == 0) { // signal low
+ return 0; // do not override enter DFU
+ } else {
+ return 1; // override enter DFU
+ }
+}
diff --git a/firmware/libboard/common/source/sim_switch.c b/firmware/libboard/owhw/source/sim_switch.c
index 59513ad..0b829b6 100644
--- a/firmware/libboard/common/source/sim_switch.c
+++ b/firmware/libboard/owhw/source/sim_switch.c
@@ -11,10 +11,6 @@
* 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 this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*/
#include "board.h"
#include "trace.h"
diff --git a/firmware/libboard/qmod/include/board.h b/firmware/libboard/qmod/include/board.h
index a738daa..7ea5bd7 100644
--- a/firmware/libboard/qmod/include/board.h
+++ b/firmware/libboard/qmod/include/board.h
@@ -11,18 +11,11 @@
* 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 this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*/
#pragma once
#include "board_common.h"
#include "simtrace_usb.h"
-#define LED_USIM1 LED_GREEN
-#define LED_USIM2 LED_RED
-
/** Name of the board */
#define BOARD_NAME "QMOD"
/** Board definition */
@@ -32,6 +25,27 @@
#define BOARD_MAINOSC 12000000
/** desired main clock frequency (in Hz, based on BOARD_MAINOSC) */
#define BOARD_MCK 58000000 // 18.432 * 29 / 6
+/** board has external clock, not crystal */
+#define BOARD_MAINOSC_BYPASS
+
+/** MCU pin connected to red LED */
+#define PIO_LED_RED PIO_PA17
+/** MCU pin connected to green LED */
+#define PIO_LED_GREEN PIO_PA18
+/** red LED pin definition */
+#define PIN_LED_RED {PIO_LED_RED, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
+/** green LED pin definition */
+#define PIN_LED_GREEN {PIO_LED_GREEN, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
+/** LEDs pin definition */
+#define PINS_LEDS PIN_LED_RED, PIN_LED_GREEN
+/** index for red LED in LEDs pin definition array */
+#define LED_NUM_RED 0
+/** index for green LED in LEDs pin definition array */
+#define LED_NUM_GREEN 1
+/** the green LED is actually red and used as indication for USIM1 */
+#define LED_USIM1 LED_GREEN
+/** the green LED is actually red and used as indication for USIM2 */
+#define LED_USIM2 LED_RED
/* USIM 2 interface (USART) */
#define PIN_USIM2_CLK {PIO_PA2, PIOA, ID_PIOA, PIO_PERIPH_B, PIO_DEFAULT}
@@ -93,6 +107,9 @@
#define BOARD_USB_RELEASE 0x010
#define CARDEMU_SECOND_UART
+
#define DETECT_VCC_BY_ADC
+#define VCC_UV_THRESH_1V8 1500000
+#define VCC_UV_THRESH_3V 2500000
#define HAVE_CARDEM
diff --git a/firmware/libboard/qmod/include/card_pres.h b/firmware/libboard/qmod/include/card_pres.h
index 81f0613..e06642e 100644
--- a/firmware/libboard/qmod/include/card_pres.h
+++ b/firmware/libboard/qmod/include/card_pres.h
@@ -11,10 +11,6 @@
* 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 this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*/
#pragma once
diff --git a/firmware/libboard/qmod/include/i2c.h b/firmware/libboard/qmod/include/i2c.h
index 30f57ce..aff1ea6 100644
--- a/firmware/libboard/qmod/include/i2c.h
+++ b/firmware/libboard/qmod/include/i2c.h
@@ -9,10 +9,6 @@
* 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 this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*/
#pragma once
diff --git a/firmware/libboard/qmod/include/wwan_led.h b/firmware/libboard/qmod/include/wwan_led.h
index 77887c7..a0f060a 100644
--- a/firmware/libboard/qmod/include/wwan_led.h
+++ b/firmware/libboard/qmod/include/wwan_led.h
@@ -9,10 +9,6 @@
* 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 this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*/
#pragma once
diff --git a/firmware/libboard/qmod/include/wwan_perst.h b/firmware/libboard/qmod/include/wwan_perst.h
index c934afc..623184e 100644
--- a/firmware/libboard/qmod/include/wwan_perst.h
+++ b/firmware/libboard/qmod/include/wwan_perst.h
@@ -9,10 +9,6 @@
* 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 this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*/
#pragma once
diff --git a/firmware/libboard/qmod/product_string.txt b/firmware/libboard/qmod/product_string.txt
new file mode 100644
index 0000000..2407b9d
--- /dev/null
+++ b/firmware/libboard/qmod/product_string.txt
@@ -0,0 +1 @@
+sysmoQMOD (Quad Modem)
diff --git a/firmware/libboard/qmod/source/board_qmod.c b/firmware/libboard/qmod/source/board_qmod.c
index 4d75b98..189fb58 100644
--- a/firmware/libboard/qmod/source/board_qmod.c
+++ b/firmware/libboard/qmod/source/board_qmod.c
@@ -12,10 +12,6 @@
* 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 this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*/
#include "board.h"
#include "simtrace.h"
@@ -28,6 +24,7 @@
#include "card_pres.h"
#include <osmocom/core/timer.h>
#include "usb_buf.h"
+#include "i2c.h"
static const Pin pin_hubpwr_override = PIN_PRTPWR_OVERRIDE;
static const Pin pin_hub_rst = {PIO_PA13, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT};
@@ -46,6 +43,7 @@ static int qmod_sam3_is_12(void)
return 0;
}
+#if (ALLOW_PEER_ERASE > 0)
const unsigned char __eeprom_bin[256] = {
USB_VENDOR_OPENMOKO & 0xff,
USB_VENDOR_OPENMOKO >> 8,
@@ -69,7 +67,6 @@ const unsigned char __eeprom_bin[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA0, 0x56, 0x23, 0x71, 0x04, 0x00, /* 0xf0 - 0xff */
};
-#include "i2c.h"
static int write_hub_eeprom(void)
{
int i;
@@ -126,7 +123,7 @@ static int erase_hub_eeprom(void)
return 0;
}
-
+#endif /* ALLOW_PEER_ERASE */
static void board_exec_dbg_cmd_st12only(int ch)
{
@@ -137,12 +134,14 @@ static void board_exec_dbg_cmd_st12only(int ch)
return;
switch (ch) {
+#if (ALLOW_PEER_ERASE > 0)
case 'E':
write_hub_eeprom();
break;
case 'e':
erase_hub_eeprom();
break;
+#endif /* ALLOW_PEER_ERASE */
case 'O':
printf("Setting PRTPWR_OVERRIDE\n\r");
PIO_Set(&pin_hubpwr_override);
@@ -151,6 +150,7 @@ static void board_exec_dbg_cmd_st12only(int ch)
printf("Clearing PRTPWR_OVERRIDE\n\r");
PIO_Clear(&pin_hubpwr_override);
break;
+#if (ALLOW_PEER_ERASE > 0)
case 'H':
printf("Clearing _HUB_RESET -> HUB_RESET high (inactive)\n\r");
PIO_Clear(&pin_hub_rst);
@@ -170,6 +170,7 @@ static void board_exec_dbg_cmd_st12only(int ch)
printf("Writing value 0x%02lx to EEPROM offset 0x%02lx\n\r", val, addr);
eeprom_write_byte(0x50, addr, val);
break;
+#endif /* ALLOW_PEER_ERASE */
case 'r':
printf("Please enter EEPROM offset:\n\r");
UART_GetIntegerMinMax(&addr, 0, 255);
@@ -189,7 +190,7 @@ void board_exec_dbg_cmd(int ch)
this is done to prevent accidental ERASE on noisy serial input since only one character can trigger the ERASE.
*/
static bool allow_erase = false;
-#endif
+#endif /* ALLOW_PEER_ERASE */
switch (ch) {
case '?':
@@ -200,13 +201,17 @@ void board_exec_dbg_cmd(int ch)
printf("\tg\tswitch off LED 2\n\r");
printf("\tG\tswitch off LED 2\n\r");
if (qmod_sam3_is_12()) {
+#if (ALLOW_PEER_ERASE > 0)
printf("\tE\tprogram EEPROM\n\r");
printf("\te\tErase EEPROM\n\r");
+#endif /* ALLOW_PEER_ERASE */
printf("\tO\tEnable PRTPWR_OVERRIDE\n\r");
printf("\to\tDisable PRTPWR_OVERRIDE\n\r");
+#if (ALLOW_PEER_ERASE > 0)
printf("\tH\tRelease HUB RESET (high)\n\r");
printf("\th\tAssert HUB RESET (low)\n\r");
printf("\tw\tWrite single byte in EEPROM\n\r");
+#endif /* ALLOW_PEER_ERASE */
printf("\tr\tRead single byte from EEPROM\n\r");
}
printf("\tX\tRelease peer SAM3 from reset\n\r");
@@ -215,10 +220,13 @@ void board_exec_dbg_cmd(int ch)
printf("\tY\tRelease peer SAM3 ERASE signal\n\r");
printf("\ta\tAllow asserting peer SAM3 ERASE signal\n\r");
printf("\ty\tAssert peer SAM3 ERASE signal\n\r");
-#endif
+#endif /* ALLOW_PEER_ERASE */
printf("\tU\tProceed to USB Initialization\n\r");
printf("\t1\tGenerate 1ms reset pulse on WWAN1\n\r");
printf("\t2\tGenerate 1ms reset pulse on WWAN2\n\r");
+ printf("\t!\tSwitch Channel A from physical -> remote\n\r");
+ printf("\t@\tSwitch Channel B from physical -> remote\n\r");
+ printf("\tt\t(pseudo)talloc report\n\r");
break;
case 'R':
printf("Asking NVIC to reset us\n\r");
@@ -266,7 +274,7 @@ void board_exec_dbg_cmd(int ch)
printf("Please first allow setting SIMTRACExx_ERASE\n\r");
}
break;
-#endif
+#endif /* ALLOW_PEER_ERASE */
case '1':
printf("Resetting Modem 1 (of this SAM3)\n\r");
wwan_perst_do_reset_pulse(0, 300);
@@ -281,6 +289,9 @@ void board_exec_dbg_cmd(int ch)
case '@':
sim_switch_use_physical(0, 0);
break;
+ case 't':
+ talloc_report(NULL, stdout);
+ break;
default:
if (!qmod_sam3_is_12())
printf("Unknown command '%c'\n\r", ch);
@@ -294,7 +305,7 @@ void board_exec_dbg_cmd(int ch)
if ('a' != ch) {
allow_erase = false;
}
-#endif
+#endif /* ALLOW_PEER_ERASE */
}
void board_main_top(void)
@@ -327,11 +338,13 @@ void board_main_top(void)
TRACE_INFO("Detected Quad-Modem ST12\n\r");
} else {
TRACE_INFO("Detected Quad-Modem ST34\n\r");
+#ifndef APPLICATION_dfu
/* make sure we use the second set of USB Strings
* calling the interfaces "Modem 3" and "Modem 4" rather
* than 1+2 */
usb_strings[7] = usb_strings[9];
usb_strings[8] = usb_strings[10];
+#endif
}
/* Obtain the circuit board version (currently just prints voltage */
diff --git a/firmware/libboard/qmod/source/card_pres.c b/firmware/libboard/qmod/source/card_pres.c
index 7a32b57..21ce1fb 100644
--- a/firmware/libboard/qmod/source/card_pres.c
+++ b/firmware/libboard/qmod/source/card_pres.c
@@ -11,10 +11,6 @@
* 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 this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*/
#include <osmocom/core/timer.h>
#include "board.h"
diff --git a/firmware/libboard/qmod/source/i2c.c b/firmware/libboard/qmod/source/i2c.c
index a708704..7aa3d1d 100644
--- a/firmware/libboard/qmod/source/i2c.c
+++ b/firmware/libboard/qmod/source/i2c.c
@@ -9,10 +9,6 @@
* 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 this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*/
#include "board.h"
#include <stdbool.h>
diff --git a/firmware/libboard/qmod/source/sim_switch.c b/firmware/libboard/qmod/source/sim_switch.c
new file mode 100644
index 0000000..0b829b6
--- /dev/null
+++ b/firmware/libboard/qmod/source/sim_switch.c
@@ -0,0 +1,86 @@
+/* Code to switch between local (physical) and remote (emulated) SIM
+ *
+ * (C) 2015-2017 by Harald Welte <hwelte@hmw-consulting.de>
+ *
+ * This program 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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.
+ */
+#include "board.h"
+#include "trace.h"
+#include "led.h"
+#include "sim_switch.h"
+
+#ifdef PIN_SIM_SWITCH1
+static const Pin pin_conn_usim1 = {PIO_PA20, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT};
+#endif
+#ifdef PIN_SIM_SWITCH2
+static const Pin pin_conn_usim2 = {PIO_PA28, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT};
+#endif
+
+static int initialized = 0;
+
+int sim_switch_use_physical(unsigned int nr, int physical)
+{
+ const Pin *pin;
+ enum led led;
+
+ if (!initialized) {
+ TRACE_ERROR("Somebody forgot to call sim_switch_init()\r\n");
+ sim_switch_init();
+ }
+
+ TRACE_INFO("Modem %d: %s SIM\n\r", nr,
+ physical ? "physical" : "virtual");
+
+ switch (nr) {
+#ifdef PIN_SIM_SWITCH1
+ case 0:
+ pin = &pin_conn_usim1;
+ led = LED_USIM1;
+ break;
+#endif
+#ifdef PIN_SIM_SWITCH2
+ case 1:
+ pin = &pin_conn_usim2;
+ led = LED_USIM2;
+ break;
+#endif
+ default:
+ TRACE_ERROR("Invalid SIM%u\n\r", nr);
+ return -1;
+ }
+
+ if (physical) {
+ TRACE_INFO("%u: Use local/physical SIM\r\n", nr);
+ PIO_Clear(pin);
+ led_blink(led, BLINK_ALWAYS_ON);
+ } else {
+ TRACE_INFO("%u: Use remote/emulated SIM\r\n", nr);
+ PIO_Set(pin);
+ led_blink(led, BLINK_ALWAYS_OFF);
+ }
+
+ return 0;
+}
+
+int sim_switch_init(void)
+{
+ int num_switch = 0;
+#ifdef PIN_SIM_SWITCH1
+ PIO_Configure(&pin_conn_usim1, 1);
+ num_switch++;
+#endif
+#ifdef PIN_SIM_SWITCH2
+ PIO_Configure(&pin_conn_usim2, 1);
+ num_switch++;
+#endif
+ initialized = 1;
+ return num_switch;
+}
diff --git a/firmware/libboard/qmod/source/wwan_led.c b/firmware/libboard/qmod/source/wwan_led.c
index b3b5693..f055080 100644
--- a/firmware/libboard/qmod/source/wwan_led.c
+++ b/firmware/libboard/qmod/source/wwan_led.c
@@ -9,10 +9,6 @@
* 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 this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*/
/* Depending on the board this is running on, it might be possible
* for the controller to read the status of the WWAN LED output lines of
diff --git a/firmware/libboard/qmod/source/wwan_perst.c b/firmware/libboard/qmod/source/wwan_perst.c
index 95a7c7b..b314781 100644
--- a/firmware/libboard/qmod/source/wwan_perst.c
+++ b/firmware/libboard/qmod/source/wwan_perst.c
@@ -9,10 +9,6 @@
* 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 this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*/
/* Depending on the board this is running on, it might be possible
* for the controller to set the status of the PERST input line of
diff --git a/firmware/libboard/sam3p256/include/board.h b/firmware/libboard/sam3p256/include/board.h
index bd2ab49..ff87c99 100644
--- a/firmware/libboard/sam3p256/include/board.h
+++ b/firmware/libboard/sam3p256/include/board.h
@@ -11,10 +11,6 @@
* 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 this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*/
#pragma once
#include "board_common.h"
@@ -30,6 +26,21 @@
/** desired main clock frequency (in Hz, based on BOARD_MAINOSC) */
#define BOARD_MCK 58000000
+/** MCU pin connected to yellow LED2 */
+#define PIO_LED_RED PIO_PA17
+/** MCU pin connected to green LED1 */
+#define PIO_LED_GREEN PIO_PA18
+/** red LED pin definition */
+#define PIN_LED_RED {PIO_LED_RED, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
+/** green LED pin definition */
+#define PIN_LED_GREEN {PIO_LED_GREEN, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
+/** LEDs pin definition */
+#define PINS_LEDS PIN_LED_RED, PIN_LED_GREEN
+/** index for red LED in LEDs pin definition array */
+#define LED_NUM_RED 0
+/** index for green LED in LEDs pin definition array */
+#define LED_NUM_GREEN 1
+
/** Pin configuration **/
/* Button to force bootloader start (shorted to ground when pressed */
#define PIN_BOOTLOADER_SW {PIO_PA20, PIOA, ID_PIOA, PIO_INPUT, PIO_DEFAULT}
@@ -120,11 +131,6 @@
#define PIN_SPI_WP {PA15, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}
#endif
-/** Pin configuration to control USB pull-up on D+
- * @details the USB pull-up on D+ is enable by default on the board but can be disabled by setting PA16 high
- */
-#define PIN_USB_PULLUP {PIO_PA16, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}
-
/** USB definitions */
/* OpenMoko SIMtrace 2 USB vendor ID */
#define BOARD_USB_VENDOR_ID USB_VENDOR_OPENMOKO
diff --git a/firmware/libboard/sam3p256/source/board_sam3p256.c b/firmware/libboard/sam3p256/source/board_sam3p256.c
index 4b6a451..47f8ea7 100644
--- a/firmware/libboard/sam3p256/source/board_sam3p256.c
+++ b/firmware/libboard/sam3p256/source/board_sam3p256.c
@@ -12,10 +12,6 @@
* 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 this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*/
#include "board.h"
#include "simtrace.h"
diff --git a/firmware/libboard/simtrace/include/board.h b/firmware/libboard/simtrace/include/board.h
index 0c1e533..7cb30b0 100644
--- a/firmware/libboard/simtrace/include/board.h
+++ b/firmware/libboard/simtrace/include/board.h
@@ -12,10 +12,6 @@
* 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 this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*/
#pragma once
#include "board_common.h"
@@ -31,11 +27,26 @@
/** desired main clock frequency (in Hz, based on BOARD_MAINOSC) */
#define BOARD_MCK 58982400 // 18.432 * 16 / 5
+/** MCU pin connected to red LED */
+#define PIO_LED_RED PIO_PA17
+/** MCU pin connected to green LED */
+#define PIO_LED_GREEN PIO_PA18
+/** red LED pin definition */
+#define PIN_LED_RED {PIO_LED_RED, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
+/** green LED pin definition */
+#define PIN_LED_GREEN {PIO_LED_GREEN, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
+/** LEDs pin definition */
+#define PINS_LEDS PIN_LED_RED, PIN_LED_GREEN
+/** index for red LED in LEDs pin definition array */
+#define LED_NUM_RED 0
+/** index for green LED in LEDs pin definition array */
+#define LED_NUM_GREEN 1
+
/** Pin configuration **/
/* Button to force bootloader start (shorted to ground when pressed */
#define PIN_BOOTLOADER_SW {PIO_PA31, PIOA, ID_PIOA, PIO_INPUT, PIO_PULLUP}
/* Enable powering the card using the second 3.3 V output of the LDO (active high) */
-#define SIM_PWEN_PIN {SIM_PWEN, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
+#define SIM_PWEN_PIN {PIO_PA5, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
/* Enable powering the SIM card */
#define PWR_PINS SIM_PWEN_PIN
/* Card presence pin */
@@ -59,15 +70,15 @@
/** Phone connection **/
/* Phone USIM slot 1 VCC pin (VCC_PHONE in schematic) */
-#define PIN_USIM1_VCC {PIO_PA25, PIOA, ID_PIOA, PIO_INPUT, PIO_DEFAULT}
+#define PIN_USIM1_VCC {PIO_PA25, PIOA, ID_PIOA, PIO_INPUT, PIO_IT_EDGE | PIO_DEGLITCH }
/* Phone USIM slot 1 RST pin (active low; RST_PHONE in schematic) */
-#define PIN_USIM1_nRST {PIO_PA24, PIOA, ID_PIOA, PIO_INPUT, PIO_IT_RISE_EDGE | PIO_DEGLITCH }
+#define PIN_USIM1_nRST {PIO_PA24, PIOA, ID_PIOA, PIO_INPUT, PIO_IT_EDGE | PIO_DEGLITCH }
/* Phone I/O data signal input/output (I/O_PHONE in schematic) */
-#define PIN_PHONE_IO {PIO_PA22A_TXD1, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
+#define PIN_USIM1_IO {PIO_PA22A_TXD1, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
/* Phone CLK clock input (CLK_PHONE in schematic) */
-#define PIN_PHONE_CLK {PIO_PA23A_SCK1, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
+#define PIN_USIM1_CLK {PIO_PA23A_SCK1, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
/* Pin used for phone USIM slot 1 communication */
-#define PINS_USIM1 PIN_PHONE_IO, PIN_PHONE_CLK, PIN_PHONE_CLK_INPUT, PIN_USIM1_VCC, PIN_PHONE_IO_INPUT, PIN_USIM1_nRST
+#define PINS_USIM1 PIN_USIM1_IO, PIN_USIM1_CLK, PIN_PHONE_CLK_INPUT, PIN_USIM1_VCC, PIN_PHONE_IO_INPUT, PIN_USIM1_nRST
/* Phone I/O data signal input/output (unused USART RX input; connected to I/O_PHONE in schematic) */
#define PIN_PHONE_IO_INPUT {PIO_PA21A_RXD1, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
/* Pin used as clock input (to measure the ETU duration; connected to CLK_PHONE in schematic) */
@@ -93,9 +104,9 @@
/* Pins used to sniff phone-card communication */
#define PINS_SIM_SNIFF PIN_SIM_IO, PIN_SIM_CLK, PIN_SIM_RST_SNIFF
/* Disable power converter 4.5-6V to 3.3V (active high) */
-#define PIN_SIM_PWEN_SNIFF {SIM_PWEN, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}
+#define PIN_SIM_PWEN_SNIFF {PIO_PA5, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}
/* Enable power switch to forward VCC_PHONE to VCC_SIM (active high) */
-#define PIN_VCC_FWD_SNIFF {VCC_FWD, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
+#define PIN_VCC_FWD_SNIFF {PIO_PA26, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
/* Use phone VCC to power card */
#define PINS_PWR_SNIFF PIN_SIM_PWEN_SNIFF, PIN_VCC_FWD_SNIFF
@@ -119,11 +130,6 @@
/* SPI flash write protect pin (active low, pulled low) */
#define PIN_SPI_WP {PA15, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}
-/** Pin configuration to control USB pull-up on D+
- * @details the USB pull-up on D+ is enable by default on the board but can be disabled by setting PA16 high
- */
-#define PIN_USB_PULLUP {PIO_PA16, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}
-
/** USB definitions */
/* OpenMoko SIMtrace 2 USB vendor ID */
#define BOARD_USB_VENDOR_ID USB_VENDOR_OPENMOKO
@@ -138,10 +144,14 @@
/** Supported modes */
/* SIMtrace board supports sniffer mode */
+#ifdef APPLICATION_trace
#define HAVE_SNIFFER
+#endif
/* SIMtrace board supports CCID mode */
//#define HAVE_CCID
/* SIMtrace board supports card emulation mode */
-//#define HAVE_CARDEM
+#ifdef APPLICATION_cardem
+#define HAVE_CARDEM
+#endif
/* SIMtrace board supports man-in-the-middle mode */
//#define HAVE_MITM
diff --git a/firmware/libboard/simtrace/product_string.txt b/firmware/libboard/simtrace/product_string.txt
new file mode 100644
index 0000000..5634f3a
--- /dev/null
+++ b/firmware/libboard/simtrace/product_string.txt
@@ -0,0 +1 @@
+SIMtrace 2
diff --git a/firmware/libboard/simtrace/source/board_simtrace.c b/firmware/libboard/simtrace/source/board_simtrace.c
index 9d323cf..d15d6b9 100644
--- a/firmware/libboard/simtrace/source/board_simtrace.c
+++ b/firmware/libboard/simtrace/source/board_simtrace.c
@@ -12,10 +12,6 @@
* 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 this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*/
#include "board.h"
#include "simtrace.h"
diff --git a/firmware/libboard/simtrace/source/sim_switch.c b/firmware/libboard/simtrace/source/sim_switch.c
new file mode 100644
index 0000000..c3a8503
--- /dev/null
+++ b/firmware/libboard/simtrace/source/sim_switch.c
@@ -0,0 +1,50 @@
+/* Code to switch between local (physical) and remote (emulated) SIM
+ *
+ * (C) 2015-2017 by Harald Welte <hwelte@hmw-consulting.de>
+ * (C) 2018, sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon@sysmocom.de>
+ *
+ * This program 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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.
+ */
+#include "board.h"
+#include "trace.h"
+#include "led.h"
+#include "sim_switch.h"
+
+int sim_switch_use_physical(unsigned int nr, int physical)
+{
+ const Pin pin_sc = PIN_SC_SW_DEFAULT; // pin to control bus switch for VCC/RST/CLK signals
+ const Pin pin_io = PIN_IO_SW_DEFAULT; // pin to control bus switch for I/O signal
+
+ if (nr > 0) {
+ TRACE_ERROR("SIM interface for Modem %d can't be switched\r\n", nr);
+ return -1;
+ }
+
+ TRACE_INFO("Modem %u: %s SIM\n\r", nr, physical ? "physical" : "virtual");
+
+ if (physical) {
+ TRACE_INFO("%u: Use local/physical SIM\r\n", nr);
+ PIO_Set(&pin_sc);
+ PIO_Set(&pin_io);
+ } else {
+ TRACE_INFO("%u: Use remote/emulated SIM\r\n", nr);
+ PIO_Clear(&pin_sc);
+ PIO_Clear(&pin_io);
+ }
+
+ return 0;
+}
+
+int sim_switch_init(void)
+{
+ // the bus switch is already initialised
+ return 1; // SIMtrace hardware has only one switchable interface
+}
diff --git a/firmware/libcommon/include/assert.h b/firmware/libcommon/include/assert.h
index 22bb101..dc6b1b5 100644
--- a/firmware/libcommon/include/assert.h
+++ b/firmware/libcommon/include/assert.h
@@ -89,7 +89,7 @@
/// \param condition Condition to verify.
#define ASSERT(condition) { \
if (!(condition)) { \
- printf("-F- ASSERT: %s %s:%d\n\r", #condition, __BASE_FILE__, __LINE__); \
+ printf_sync("-F- ASSERT: %s %s:%d\n\r", #condition, __BASE_FILE__, __LINE__); \
while (1); \
} \
}
diff --git a/firmware/libcommon/include/card_emu.h b/firmware/libcommon/include/card_emu.h
index a3c1cf2..2668d73 100644
--- a/firmware/libcommon/include/card_emu.h
+++ b/firmware/libcommon/include/card_emu.h
@@ -12,10 +12,6 @@
* 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 this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*/
#pragma once
@@ -29,8 +25,17 @@ enum card_io {
CARD_IO_CLK,
};
-struct card_handle *card_emu_init(uint8_t slot_num, uint8_t tc_chan, uint8_t uart_chan,
- uint8_t in_ep, uint8_t irq_ep);
+/** initialise card slot
+ * @param[in] slot_num slot number (arbitrary number)
+ * @param[in] uart_chan UART peripheral channel
+ * @param[in] in_ep USB IN end point number
+ * @param[in] irq_ep USB INTerrupt end point number
+ * @param[in] vcc_active initial VCC signal state (true = on)
+ * @param[in] in_reset initial RST signal state (true = reset asserted)
+ * @param[in] clocked initial CLK signat state (true = active)
+ * @return main card handle reference
+ */
+struct card_handle *card_emu_init(uint8_t slot_num, uint8_t uart_chan, uint8_t in_ep, uint8_t irq_ep, bool vcc_active, bool in_reset, bool clocked);
/* process a single byte received from the reader */
void card_emu_process_rx_byte(struct card_handle *ch, uint8_t byte);
@@ -46,13 +51,26 @@ int card_emu_set_atr(struct card_handle *ch, const uint8_t *atr, uint8_t len);
struct llist_head *card_emu_get_uart_tx_queue(struct card_handle *ch);
void card_emu_have_new_uart_tx(struct card_handle *ch);
-void card_emu_report_status(struct card_handle *ch);
+void card_emu_report_status(struct card_handle *ch, bool report_on_irq);
+
+void card_emu_wtime_half_expired(void *ch);
+void card_emu_wtime_expired(void *ch);
-#define ENABLE_TX 0x01
-#define ENABLE_RX 0x02
+
+#define ENABLE_TX 0x01
+#define ENABLE_RX 0x02
+#define ENABLE_TX_TIMER_ONLY 0x03
int card_emu_uart_update_fidi(uint8_t uart_chan, unsigned int fidi);
+void card_emu_uart_update_wt(uint8_t uart_chan, uint32_t wt);
+void card_emu_uart_reset_wt(uint8_t uart_chan);
int card_emu_uart_tx(uint8_t uart_chan, uint8_t byte);
void card_emu_uart_enable(uint8_t uart_chan, uint8_t rxtx);
void card_emu_uart_wait_tx_idle(uint8_t uart_chan);
void card_emu_uart_interrupt(uint8_t uart_chan);
+
+int card_emu_get_vcc(uint8_t uart_chan);
+
+struct cardemu_usb_msg_config;
+int card_emu_set_config(struct card_handle *ch, const struct cardemu_usb_msg_config *scfg,
+ unsigned int scfg_len);
diff --git a/firmware/libcommon/include/cciddriver.h b/firmware/libcommon/include/cciddriver.h
index f9be027..df77fa3 100644
--- a/firmware/libcommon/include/cciddriver.h
+++ b/firmware/libcommon/include/cciddriver.h
@@ -175,11 +175,11 @@ typedef struct
{
/// Number of seconds. If 00h then CCID default value is used.
unsigned char bTimeOut;
- /// Several parameters for the PIN format options (defined in § 6.1.11.4)
+ /// Several parameters for the PIN format options (defined in § 6.1.11.4)
unsigned char bmFormatString4;
/// Define the length of the PIN to present in the APDU command
unsigned char bmPINBlockString;
- /// Allows the length PIN insertion in the APDU command (defined in § 6.1.11.6)
+ /// Allows the length PIN insertion in the APDU command (defined in § 6.1.11.6)
unsigned char bmPinLengthFormat;
/// Insertion position offset in byte for the current PIN
unsigned char bInsertionOffsetOld;
@@ -218,13 +218,13 @@ typedef struct
/// Protocol Data Structure for Protocol T=0 (bProtocolNum=0, dwLength=00000005h)
typedef struct
{
- /// B7-4 – FI – Index into the table 7 in ISO/IEC 7816-3:1997 selecting a
+ /// B7-4 - FI - Index into the table 7 in ISO/IEC 7816-3:1997 selecting a
/// clock rate conversion factor
- /// B3-0 – DI - Index into the table 8 in ISO/IEC 7816-3:1997 selecting a
+ /// B3-0 - DI - Index into the table 8 in ISO/IEC 7816-3:1997 selecting a
/// baud rate conversion factor
unsigned char bmFindexDindex;
- /// For T=0 ,B0 – 0b, B7-2 – 000000b
- /// B1 – Convention used (b1=0 for direct, b1=1 for inverse)
+ /// For T=0 ,B0 - 0b, B7-2 - 000000b
+ /// B1 - Convention used (b1=0 for direct, b1=1 for inverse)
unsigned char bmTCCKST0; // 0 to 2
/// Extra Guardtime between two characters. Add 0 to 254 etu to the normal
/// guardtime of 12etu. FFh is the same as 00h.
@@ -243,14 +243,14 @@ typedef struct
/// Protocol Data Structure for Protocol T=1 (bProtocolNum=1, dwLength=00000007h)
typedef struct
{
- /// B7-4 – FI – Index into the table 7 in ISO/IEC 7816-3:1997 selecting a
+ /// B7-4 - FI - Index into the table 7 in ISO/IEC 7816-3:1997 selecting a
/// clock rate conversion factor
- /// B3-0 – DI - Index into the table 8 in ISO/IEC 7816-3:1997 selecting a
+ /// B3-0 - DI - Index into the table 8 in ISO/IEC 7816-3:1997 selecting a
/// baud rate conversion factor
unsigned char bmFindexDindex;
- /// For T=1, B7-2 – 000100b
- /// B0 – Checksum type (b0=0 for LRC, b0=1 for CRC
- /// B1 – Convention used (b1=0 for direct, b1=1 for inverse)
+ /// For T=1, B7-2 - 000100b
+ /// B0 - Checksum type (b0=0 for LRC, b0=1 for CRC
+ /// B1 - Convention used (b1=0 for direct, b1=1 for inverse)
unsigned char bmTCCKST1; // 10h, 11h, 12h, 13h
/// Extra Guardtime (0 to 254 etu between two characters).
/// If value is FFh, then guardtime is reduced by 1.
@@ -292,8 +292,8 @@ typedef struct
/// - 04h 1.8V
/// Other bits are RFU.
unsigned char bVoltageSupport;
- /// RRRR –Upper Word- is RFU = 0000h
- /// PPPP –Lower Word- Encodes the supported protocol types. A ‘1’ in a given
+ /// RRRR -Upper Word- is RFU = 0000h
+ /// PPPP -Lower Word- Encodes the supported protocol types. A "1" in a given
/// bit position indicates support for the associated ISO protocol.
/// 0001h = Protocol T=0
/// 0002h = Protocol T=1
@@ -318,7 +318,7 @@ typedef struct
/// Indicates the maximum IFSD supported by CCID for protocol T=1.
unsigned long dwMaxIFSD;
/// - RRRR-Upper Word- is RFU = 0000h
- /// - PPPP-Lower Word- encodes the supported protocol types. A ‘1’ in a given
+ /// - PPPP-Lower Word- encodes the supported protocol types. A "1" in a given
/// bit position indicates support for the associated protocol.
/// 0001h indicates support for the 2-wire protocol 1
/// 0002h indicates support for the 3-wire protocol 1
diff --git a/firmware/libcommon/include/iso7816_fidi.h b/firmware/libcommon/include/iso7816_fidi.h
index c56478b..823e7ab 100644
--- a/firmware/libcommon/include/iso7816_fidi.h
+++ b/firmware/libcommon/include/iso7816_fidi.h
@@ -11,20 +11,16 @@
* 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 this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*/
#pragma once
#include <stdint.h>
/* Table 7 of ISO 7816-3:2006 */
-extern const uint16_t fi_table[];
+extern const uint16_t iso7816_3_fi_table[16];
/* Table 8 from ISO 7816-3:2006 */
-extern const uint8_t di_table[];
+extern const uint8_t iso7816_3_di_table[16];
-/* compute the F/D ratio based on Fi and Di values */
-int compute_fidi_ratio(uint8_t fi, uint8_t di);
+/* compute the F/D ratio based on F_index and D_index values */
+int iso7816_3_compute_fd_ratio(uint8_t f_index, uint8_t d_index);
diff --git a/firmware/libcommon/include/llist_irqsafe.h b/firmware/libcommon/include/llist_irqsafe.h
index 9171ccf..8aafcfb 100644
--- a/firmware/libcommon/include/llist_irqsafe.h
+++ b/firmware/libcommon/include/llist_irqsafe.h
@@ -11,10 +11,6 @@
* 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 this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*/
#pragma once
diff --git a/firmware/libcommon/include/main_common.h b/firmware/libcommon/include/main_common.h
new file mode 100644
index 0000000..ce19f81
--- /dev/null
+++ b/firmware/libcommon/include/main_common.h
@@ -0,0 +1,3 @@
+#pragma once
+
+void print_banner(void);
diff --git a/firmware/libcommon/include/ringbuffer.h b/firmware/libcommon/include/ringbuffer.h
index a6eddc9..99fe96b 100644
--- a/firmware/libcommon/include/ringbuffer.h
+++ b/firmware/libcommon/include/ringbuffer.h
@@ -9,10 +9,6 @@
* 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 this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*/
#ifndef SIMTRACE_RINGBUF_H
#define SIMTRACE_RINGBUF_H
@@ -21,7 +17,7 @@
#include <stdbool.h>
#include <sys/types.h>
-#define RING_BUFLEN 512
+#define RING_BUFLEN 1024
typedef struct ringbuf {
uint8_t buf[RING_BUFLEN];
@@ -36,4 +32,22 @@ int rbuf_write(volatile ringbuf * rb, uint8_t item);
bool rbuf_is_empty(volatile ringbuf * rb);
bool rbuf_is_full(volatile ringbuf * rb);
+
+/* same as above but with 16bit values instead of 8bit */
+
+#define RING16_BUFLEN 512
+
+typedef struct ringbuf16 {
+ uint16_t buf[RING16_BUFLEN];
+ size_t ird;
+ size_t iwr;
+} ringbuf16;
+
+void rbuf16_reset(volatile ringbuf16 * rb);
+uint16_t rbuf16_read(volatile ringbuf16 * rb);
+uint16_t rbuf16_peek(volatile ringbuf16 * rb);
+int rbuf16_write(volatile ringbuf16 * rb, uint16_t item);
+bool rbuf16_is_empty(volatile ringbuf16 * rb);
+bool rbuf16_is_full(volatile ringbuf16 * rb);
+
#endif /* end of include guard: SIMTRACE_RINGBUF_H */
diff --git a/firmware/libcommon/include/simtrace.h b/firmware/libcommon/include/simtrace.h
index 0486581..a37ec4f 100644
--- a/firmware/libcommon/include/simtrace.h
+++ b/firmware/libcommon/include/simtrace.h
@@ -1,6 +1,7 @@
/* SIMtrace 2 mode definitions
*
- * (C) 2015-2017 by Harald Welte <hwelte@hmw-consulting.de>
+ * Copyright (c) 2015-2017 by Harald Welte <hwelte@hmw-consulting.de>
+ * Copyright (c) 2018-2019, sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon@sysmocom.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -11,10 +12,6 @@
* 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 this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*/
#ifndef SIMTRACE_H
#define SIMTRACE_H
@@ -57,6 +54,7 @@ enum confNum {
#ifdef HAVE_MITM
CFG_NUM_MITM,
#endif
+ CFG_NUM_VERSION,
NUM_CONF
};
diff --git a/firmware/libcommon/include/simtrace_prot.h b/firmware/libcommon/include/simtrace_prot.h
index 878bc34..d1eb89b 100644
--- a/firmware/libcommon/include/simtrace_prot.h
+++ b/firmware/libcommon/include/simtrace_prot.h
@@ -12,10 +12,6 @@
* 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 this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*/
#pragma once
@@ -62,6 +58,8 @@ enum simtrace_msg_type_cardem {
SIMTRACE_MSGT_DO_CEMU_RX_DATA,
/* Indicate PTS request from phone */
SIMTRACE_MSGT_DO_CEMU_PTS,
+ /* Set configurable parameters */
+ SIMTRACE_MSGT_BD_CEMU_CONFIG,
};
/* SIMTRACE_MSGC_MODEM */
@@ -228,11 +226,17 @@ struct cardemu_usb_msg_status {
uint32_t flags;
/* phone-applied target voltage in mV */
uint16_t voltage_mv;
- /* Fi/Di related information */
- uint8_t fi;
- uint8_t di;
- uint8_t wi;
- uint32_t waiting_time;
+ /* F/D related information. Not actual Fn/Dn values but indexes into tables! */
+ union {
+ uint8_t F_index; /* <! Index to ISO7816-3 Table 7 (F and f_max values) */
+ uint8_t fi; /* <! old, wrong name for API compatibility */
+ };
+ union {
+ uint8_t D_index; /* <! Index to ISO7816-3 Table 8 (D value) */
+ uint8_t di; /* <! old, wrong name for API compatibility */
+ };
+ uint8_t wi; /* <! Waiting Integer as defined in ISO7816-3 Section 10.2 */
+ uint32_t waiting_time; /* <! Waiting Time in etu as defined in ISO7816-3 Section 8.1 */
} __attribute__ ((packed));
/* CEMU_USB_MSGT_DO_PTS */
@@ -254,6 +258,17 @@ struct cardemu_usb_msg_error {
uint8_t msg[0];
} __attribute__ ((packed));
+/* enable/disable the generation of DO_STATUS on IRQ endpoint */
+#define CEMU_FEAT_F_STATUS_IRQ 0x00000001
+
+/* SIMTRACE_MSGT_BD_CEMU_CONFIG */
+struct cardemu_usb_msg_config {
+ /* bit-mask of CEMU_FEAT_F flags */
+ uint32_t features;
+ /* the selected slot number (if an external mux is present) */
+ uint8_t slot_mux_nr;
+} __attribute__ ((packed));
+
/***********************************************************************
* MODEM CONTROL
***********************************************************************/
@@ -298,6 +313,9 @@ struct st_modem_status {
#define SNIFF_DATA_FLAG_ERROR_INCOMPLETE (1<<5)
#define SNIFF_DATA_FLAG_ERROR_MALFORMED (1<<6)
#define SNIFF_DATA_FLAG_ERROR_CHECKSUM (1<<7)
+#define SNIFF_DATA_FLAG_ERROR_OVERRUN (1<<8)
+#define SNIFF_DATA_FLAG_ERROR_FRAMING (1<<9)
+#define SNIFF_DATA_FLAG_ERROR_PARITY (1<<10)
/* SIMTRACE_MSGT_SNIFF_CHANGE */
struct sniff_change {
diff --git a/firmware/libcommon/include/simtrace_usb.h b/firmware/libcommon/include/simtrace_usb.h
index c0da9c5..1473762 100644
--- a/firmware/libcommon/include/simtrace_usb.h
+++ b/firmware/libcommon/include/simtrace_usb.h
@@ -11,10 +11,6 @@
* 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 this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*/
/* SIMtrace USB IDs */
#define USB_VENDOR_OPENMOKO 0x1d50
@@ -25,6 +21,8 @@
#define USB_PRODUCT_QMOD_SAM3 0x4004
#define USB_PRODUCT_SIMTRACE2_DFU 0x60e3 /* was 0x60e2 */
#define USB_PRODUCT_SIMTRACE2 0x60e3
+#define USB_PRODUCT_OCTSIMTEST 0x616d
+#define USB_PRODUCT_NGFF_CARDEM 0x616e
/* USB proprietary class */
#define USB_CLASS_PROPRIETARY 0xff
@@ -64,4 +62,4 @@
#define SIMTRACE_CARDEM_USB_EP_USIM2_INT 3
/*! Maximum number of endpoints */
-#define BOARD_USB_NUMENDPOINTS 6
+#define BOARD_USB_NUMENDPOINTS 7 /* 0 (control) + 2 (interfaces) * 3 (endpoints) */
diff --git a/firmware/libcommon/include/talloc.h b/firmware/libcommon/include/talloc.h
index 0bd75d2..1e95603 100644
--- a/firmware/libcommon/include/talloc.h
+++ b/firmware/libcommon/include/talloc.h
@@ -9,14 +9,11 @@
* 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 this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*/
#pragma once
#include <stdlib.h>
+#include <stdio.h>
#include <stdarg.h>
/* minimalistic emulation of core talloc API functions used by msgb.c */
@@ -39,3 +36,4 @@ void *talloc_named_const(const void *context, size_t size, const char *name);
void talloc_set_name_const(const void *ptr, const char *name);
char *talloc_strdup(const void *t, const char *p);
void *talloc_pool(const void *context, size_t size);
+void talloc_report(const void *ptr, FILE *f);
diff --git a/firmware/libcommon/include/usb_buf.h b/firmware/libcommon/include/usb_buf.h
index bd6947b..39198f3 100644
--- a/firmware/libcommon/include/usb_buf.h
+++ b/firmware/libcommon/include/usb_buf.h
@@ -9,10 +9,6 @@
* 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 this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*/
#pragma once
@@ -29,6 +25,8 @@ struct usb_buffered_ep {
volatile uint32_t in_progress;
/* Tx queue (IN) / Rx queue (OUT) */
struct llist_head queue;
+ /* current length of queue */
+ unsigned int queue_len;
};
struct msgb *usb_buf_alloc(uint8_t ep);
diff --git a/firmware/libcommon/include/utils.h b/firmware/libcommon/include/utils.h
index 2c966f9..234d278 100644
--- a/firmware/libcommon/include/utils.h
+++ b/firmware/libcommon/include/utils.h
@@ -9,10 +9,6 @@
* 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 this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*/
#pragma once
diff --git a/firmware/libcommon/source/card_emu.c b/firmware/libcommon/source/card_emu.c
index b7d0e1f..e6907e6 100644
--- a/firmware/libcommon/source/card_emu.c
+++ b/firmware/libcommon/source/card_emu.c
@@ -1,6 +1,6 @@
/* ISO7816-3 state machine for the card side
*
- * (C) 2010-2017 by Harald Welte <laforge@gnumonks.org>
+ * (C) 2010-2021 by Harald Welte <laforge@gnumonks.org>
* (C) 2018 by sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon@sysmocom.de>
*
* This program is free software; you can redistribute it and/or modify
@@ -12,10 +12,6 @@
* 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 this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*/
#include <stdio.h>
#include <assert.h>
@@ -27,16 +23,21 @@
#include "utils.h"
#include "trace.h"
#include "iso7816_fidi.h"
-#include "tc_etu.h"
#include "card_emu.h"
#include "simtrace_prot.h"
#include "usb_buf.h"
#include <osmocom/core/linuxlist.h>
#include <osmocom/core/msgb.h>
+#ifdef HAVE_SLOT_MUX
+#include "mux.h"
+#endif
#define NUM_SLOTS 2
+/* bit-mask of supported CEMU_FEAT_F_ flags */
+#define SUPPORTED_FEATURES (CEMU_FEAT_F_STATUS_IRQ)
+
#define ISO7816_3_INIT_WTIME 9600
#define ISO7816_3_DEFAULT_WI 10
#define ISO7816_3_ATR_LEN_MAX (1+32) /* TS plus 32 chars */
@@ -55,42 +56,15 @@ enum iso7816_3_card_state {
};
const struct value_string iso7816_3_card_state_names[] = {
- {
- .value = ISO_S_WAIT_POWER,
- .str = "WAIT_POWER",
- },
- {
- .value = ISO_S_WAIT_CLK,
- .str = "WAIT_CLK",
- },
- {
- .value = ISO_S_WAIT_RST,
- .str = "WAIT_RST",
- },
- {
- .value = ISO_S_WAIT_ATR,
- .str = "WAIT_ATR",
- },
- {
- .value = ISO_S_IN_ATR,
- .str = "IN_ATR",
- },
- {
- .value = ISO_S_IN_PTS,
- .str = "IN_PTS",
- },
- {
- .value = ISO_S_WAIT_TPDU,
- .str = "WAIT_TPDU",
- },
- {
- .value = ISO_S_IN_TPDU,
- .str = "IN_TPDU",
- },
- {
- .value = 0,
- .str = NULL,
- },
+ { ISO_S_WAIT_POWER, "WAIT_POWER" },
+ { ISO_S_WAIT_CLK, "WAIT_CLK" },
+ { ISO_S_WAIT_RST, "WAIT_RST" },
+ { ISO_S_WAIT_ATR, "WAIT_ATR" },
+ { ISO_S_IN_ATR, "IN_ATR" },
+ { ISO_S_IN_PTS, "IN_PTS" },
+ { ISO_S_WAIT_TPDU, "WAIT_TPDU" },
+ { ISO_S_IN_TPDU, "IN_TPDU" },
+ { 0, NULL }
};
@@ -110,6 +84,22 @@ enum pts_state {
PTS_S_WAIT_RESP_PCK = PTS_S_WAIT_REQ_PCK | 0x10,
};
+const struct value_string pts_state_names[] = {
+ { PTS_S_WAIT_REQ_PTSS, "WAIT_REQ_PTSS" },
+ { PTS_S_WAIT_REQ_PTS0, "WAIT_REQ_PTS0" },
+ { PTS_S_WAIT_REQ_PTS1, "WAIT_REQ_PTS1" },
+ { PTS_S_WAIT_REQ_PTS2, "WAIT_REQ_PTS2" },
+ { PTS_S_WAIT_REQ_PTS3, "WAIT_REQ_PTS3" },
+ { PTS_S_WAIT_REQ_PCK, "WAIT_REQ_PCK" },
+ { PTS_S_WAIT_RESP_PTSS, "WAIT_RESP_PTSS" },
+ { PTS_S_WAIT_RESP_PTS0, "WAIT_RESP_PTS0" },
+ { PTS_S_WAIT_RESP_PTS1, "WAIT_RESP_PTS1" },
+ { PTS_S_WAIT_RESP_PTS2, "WAIT_RESP_PTS2" },
+ { PTS_S_WAIT_RESP_PTS3, "WAIT_RESP_PTS3" },
+ { PTS_S_WAIT_RESP_PCK, "WAIT_RESP_PCK" },
+ { 0, NULL }
+};
+
/* PTS field byte index */
#define _PTSS 0
#define _PTS0 1
@@ -131,42 +121,15 @@ enum tpdu_state {
};
const struct value_string tpdu_state_names[] = {
- {
- .value = TPDU_S_WAIT_CLA,
- .str = "WAIT_CLA",
- },
- {
- .value = TPDU_S_WAIT_INS,
- .str = "WAIT_INS",
- },
- {
- .value = TPDU_S_WAIT_P1,
- .str = "WAIT_P1",
- },
- {
- .value = TPDU_S_WAIT_P2,
- .str = "WAIT_P2",
- },
- {
- .value = TPDU_S_WAIT_P3,
- .str = "WAIT_P3",
- },
- {
- .value = TPDU_S_WAIT_PB,
- .str = "WAIT_PB",
- },
- {
- .value = TPDU_S_WAIT_RX,
- .str = "WAIT_RX",
- },
- {
- .value = TPDU_S_WAIT_TX,
- .str = "WAIT_TX",
- },
- {
- .value = 0,
- .str = NULL,
- },
+ { TPDU_S_WAIT_CLA, "WAIT_CLA" },
+ { TPDU_S_WAIT_INS, "WAIT_INS" },
+ { TPDU_S_WAIT_P1, "WAIT_P1" },
+ { TPDU_S_WAIT_P2, "WAIT_P2" },
+ { TPDU_S_WAIT_P3, "WAIT_P3" },
+ { TPDU_S_WAIT_PB, "WAIT_PB" },
+ { TPDU_S_WAIT_RX, "WAIT_RX" },
+ { TPDU_S_WAIT_TX, "WAIT_TX" },
+ { 0, NULL }
};
/* TPDU field byte index */
@@ -179,26 +142,44 @@ const struct value_string tpdu_state_names[] = {
struct card_handle {
unsigned int num;
+ /* bit-mask of enabled optional features (CEMU_FEAT_F_*) */
+ uint32_t features;
+
enum iso7816_3_card_state state;
/* signal levels */
- uint8_t vcc_active; /* 1 = on, 0 = off */
- uint8_t in_reset; /* 1 = RST low, 0 = RST high */
- uint8_t clocked; /* 1 = active, 0 = inactive */
-
- /* timing parameters, from PTS */
- uint8_t fi;
- uint8_t di;
+ bool vcc_active; /*< if VCC is active (true = active/ON) */
+ bool in_reset; /*< if card is in reset (true = RST low/asserted, false = RST high/ released) */
+ bool clocked; /*< if clock is active ( true = active, false = inactive) */
+
+ /* All below variables with _index suffix are indexes from 0..15 into Tables 7 + 8
+ * of ISO7816-3. */
+
+ /*! Index to clock rate conversion integer Fi (ISO7816-3 Table 7).
+ * \note this represents the maximum value supported by the card, and can be indicated in TA1 */
+ uint8_t Fi_index;
+ /*! Current value of index to clock rate conversion integer F (ISO 7816-3 Section 7.1). */
+ uint8_t F_index;
+
+ /*! Index to baud rate adjustment factor Di (ISO7816-3 Table 8).
+ * \note this represents the maximum value supported by the card, and can be indicated in TA1 */
+ uint8_t Di_index;
+ /*! Current value of index to baud rate adjustment factor D (ISO 7816-3 Section 7.1). */
+ uint8_t D_index;
+
+ /*! Waiting Integer (ISO7816-3 Section 10.2).
+ * \note this value can be set in TA2 */
uint8_t wi;
- uint8_t tc_chan; /* TC channel number */
+ /*! Waiting Time, in ETU (ISO7816-3 Section 8.1).
+ * \note this depends on Fi, Di, and WI if T=0 is used */
+ uint32_t waiting_time; /* in etu */
+
uint8_t uart_chan; /* UART channel */
uint8_t in_ep; /* USB IN EP */
uint8_t irq_ep; /* USB IN EP */
- uint32_t waiting_time; /* in clocks */
-
/* ATR state machine */
struct {
uint8_t idx;
@@ -233,6 +214,27 @@ struct card_handle {
} stats;
};
+/* reset all the 'dynamic' state of the card handle to the initial/default values */
+static void card_handle_reset(struct card_handle *ch)
+{
+ struct msgb *msg;
+
+ card_emu_uart_update_wt(ch->uart_chan, 0);
+
+ /* release any buffers we may still own */
+ if (ch->uart_tx_msg) {
+ usb_buf_free(ch->uart_tx_msg);
+ ch->uart_tx_msg = NULL;
+ }
+ if (ch->uart_rx_msg) {
+ usb_buf_free(ch->uart_rx_msg);
+ ch->uart_rx_msg = NULL;
+ }
+ while ((msg = msgb_dequeue(&ch->uart_tx_queue))) {
+ usb_buf_free(msg);
+ }
+}
+
struct llist_head *card_emu_get_uart_tx_queue(struct card_handle *ch)
{
return &ch->uart_tx_queue;
@@ -254,12 +256,35 @@ void usb_buf_upd_len_and_submit(struct msgb *msg)
/* Allocate USB buffer and push + initialize simtrace_msg_hdr */
struct msgb *usb_buf_alloc_st(uint8_t ep, uint8_t msg_class, uint8_t msg_type)
{
- struct msgb *msg;
+ struct msgb *msg = NULL;
struct simtrace_msg_hdr *sh;
- msg = usb_buf_alloc(ep);
- if (!msg)
- return NULL;
+ while (!msg) {
+ msg = usb_buf_alloc(ep); // try to allocate some memory
+ if (!msg) { // allocation failed, we might be out of memory
+ struct usb_buffered_ep *bep = usb_get_buf_ep(ep);
+ if (!bep) {
+ TRACE_ERROR("ep %u: %s queue does not exist\n\r",
+ ep, __func__);
+ return NULL;
+ }
+ if (llist_empty(&bep->queue)) {
+ TRACE_ERROR("ep %u: %s EOMEM (queue already empty)\n\r",
+ ep, __func__);
+ return NULL;
+ }
+ msg = msgb_dequeue_count(&bep->queue, &bep->queue_len);
+ if (!msg) {
+ TRACE_ERROR("ep %u: %s no msg in non-empty queue\n\r",
+ ep, __func__);
+ return NULL;
+ }
+ usb_buf_free(msg);
+ msg = NULL;
+ TRACE_DEBUG("ep %u: %s queue msg dropped\n\r",
+ ep, __func__);
+ }
+ }
msg->l1h = msgb_put(msg, sizeof(*sh));
sh = (struct simtrace_msg_hdr *) msg->l1h;
@@ -349,16 +374,14 @@ static void emu_update_fidi(struct card_handle *ch)
{
int rc;
- rc = compute_fidi_ratio(ch->fi, ch->di);
+ rc = iso7816_3_compute_fd_ratio(ch->F_index, ch->D_index);
if (rc > 0 && rc < 0x400) {
- TRACE_INFO("%u: computed Fi(%u) Di(%u) ratio: %d\r\n",
- ch->num, ch->fi, ch->di, rc);
+ TRACE_INFO("%u: computed F(%u)/D(%u) ratio: %d\r\n", ch->num,
+ ch->F_index, ch->D_index, rc);
/* make sure UART uses new F/D ratio */
card_emu_uart_update_fidi(ch->uart_chan, rc);
- /* notify ETU timer about this */
- tc_etu_set_etu(ch->tc_chan, rc);
} else
- TRACE_INFO("%u: computed FiDi ration %d unsupported\r\n",
+ TRACE_INFO("%u: computed F/D ratio %d unsupported\r\n",
ch->num, rc);
}
@@ -380,19 +403,23 @@ static void card_set_state(struct card_handle *ch,
case ISO_S_WAIT_RST:
/* disable Rx and Tx of UART */
card_emu_uart_enable(ch->uart_chan, 0);
+ /* disable timeout */
+ card_emu_uart_update_wt(ch->uart_chan, 0);
break;
case ISO_S_WAIT_ATR:
/* Reset to initial Fi / Di ratio */
- ch->fi = 1;
- ch->di = 1;
+ ch->Fi_index = ch->F_index = 1;
+ ch->Di_index = ch->D_index = 1;
+ ch->wi = ISO7816_3_DEFAULT_WI;
+ ch->waiting_time = ISO7816_3_INIT_WTIME;
emu_update_fidi(ch);
+ /* enable TX to be able to use the timeout */
+ card_emu_uart_enable(ch->uart_chan, ENABLE_TX_TIMER_ONLY);
/* the ATR should only be sent 400 to 40k clock cycles after the RESET.
- * we use the tc_etu mechanism to wait this time.
+ * we use the UART timeout mechanism to wait this time.
* since the initial ETU is Fd=372/Dd=1 clock cycles long, we have to wait 2-107 ETU.
*/
- tc_etu_set_wtime(ch->tc_chan, 2);
- /* ensure the TC_ETU timer is enabled */
- tc_etu_enable(ch->tc_chan);
+ card_emu_uart_update_wt(ch->uart_chan, 2);
break;
case ISO_S_IN_ATR:
/* initialize to default WI, this will be overwritten if we
@@ -402,7 +429,7 @@ static void card_set_state(struct card_handle *ch,
/* update waiting time to initial waiting time */
ch->waiting_time = ISO7816_3_INIT_WTIME;
/* set initial waiting time */
- tc_etu_set_wtime(ch->tc_chan, ch->waiting_time);
+ card_emu_uart_update_wt(ch->uart_chan, ch->waiting_time);
/* Set ATR sub-state to initial state */
ch->atr.idx = 0;
/* enable USART transmission to reader */
@@ -477,11 +504,11 @@ static int tx_byte_atr(struct card_handle *ch)
}
}
}
- /* update waiting time (see ISO 7816-3 10.2) */
- ch->waiting_time = ch->wi * 960 * ch->fi;
- tc_etu_set_wtime(ch->tc_chan, ch->waiting_time);
- /* reset PTS to initial state */
- set_pts_state(ch, PTS_S_WAIT_REQ_PTSS);
+ /* update waiting time (see ISO 7816-3 10.2). We can drop the Fi
+ * multiplier as we store the waiting time in units of 'etu', and
+ * don't really care what the number of clock cycles or the absolute
+ * wall clock time is */
+ ch->waiting_time = ch->wi * 960;
/* go to next state */
card_set_state(ch, ISO_S_WAIT_TPDU);
return 0;
@@ -498,8 +525,9 @@ static int tx_byte_atr(struct card_handle *ch)
/* Update the PTS sub-state */
static void set_pts_state(struct card_handle *ch, enum pts_state new_ptss)
{
- TRACE_DEBUG("%u: 7816 PTS state %u -> %u\r\n",
- ch->num, ch->pts.state, new_ptss);
+ TRACE_DEBUG("%u: 7816 PTS state %s -> %s\r\n", ch->num,
+ get_value_string(pts_state_names, ch->pts.state),
+ get_value_string(pts_state_names, new_ptss));
ch->pts.state = new_ptss;
}
@@ -579,8 +607,8 @@ process_byte_pts(struct card_handle *ch, uint8_t byte)
memcpy(ch->pts.resp, ch->pts.req, sizeof(ch->pts.resp));
break;
default:
- TRACE_ERROR("%u: process_byte_pts() in invalid state %u\r\n",
- ch->num, ch->pts.state);
+ TRACE_ERROR("%u: process_byte_pts() in invalid PTS state %s\r\n", ch->num,
+ get_value_string(pts_state_names, ch->pts.state));
break;
}
/* calculate the next state and set it */
@@ -615,10 +643,11 @@ static int tx_byte_pts(struct card_handle *ch)
case PTS_S_WAIT_RESP_PTS1:
byte = ch->pts.resp[_PTS1];
/* This must be TA1 */
- ch->fi = byte >> 4;
- ch->di = byte & 0xf;
- TRACE_DEBUG("%u: found Fi=%u Di=%u\r\n", ch->num,
- ch->fi, ch->di);
+ ch->F_index = byte >> 4;
+ ch->D_index = byte & 0xf;
+ TRACE_DEBUG("%u: found F=%u D=%u\r\n", ch->num,
+ iso7816_3_fi_table[ch->F_index], iso7816_3_di_table[ch->D_index]);
+ /* FIXME: if F or D are 0, become unresponsive to signal error condition */
break;
case PTS_S_WAIT_RESP_PTS2:
byte = ch->pts.resp[_PTS2];
@@ -630,8 +659,8 @@ static int tx_byte_pts(struct card_handle *ch)
byte = ch->pts.resp[_PCK];
break;
default:
- TRACE_ERROR("%u: get_byte_pts() in invalid state %u\r\n",
- ch->num, ch->pts.state);
+ TRACE_ERROR("%u: get_byte_pts() in invalid PTS state %s\r\n", ch->num,
+ get_value_string(pts_state_names, ch->pts.state));
return 0;
}
@@ -643,7 +672,7 @@ static int tx_byte_pts(struct card_handle *ch)
switch (ch->pts.state) {
case PTS_S_WAIT_RESP_PCK:
card_emu_uart_wait_tx_idle(ch->uart_chan);
- /* update baud rate generator with Fi/Di */
+ /* update baud rate generator with F/D */
emu_update_fidi(ch);
/* Wait for the next TPDU */
card_set_state(ch, ISO_S_WAIT_TPDU);
@@ -723,14 +752,37 @@ static void set_tpdu_state(struct card_handle *ch, enum tpdu_state new_ts)
switch (new_ts) {
case TPDU_S_WAIT_CLA:
+ /* switch back to receiving mode */
+ card_emu_uart_enable(ch->uart_chan, ENABLE_RX);
+ /* disable waiting time since we don't expect any data */
+ card_emu_uart_update_wt(ch->uart_chan, 0);
+ break;
+ case TPDU_S_WAIT_INS:
+ /* start waiting for the rest of the header/body */
+ card_emu_uart_update_wt(ch->uart_chan, ch->waiting_time);
+ break;
case TPDU_S_WAIT_RX:
+ /* switch to receive mode to receive the body */
card_emu_uart_enable(ch->uart_chan, ENABLE_RX);
+ /* start waiting for the body */
+ card_emu_uart_update_wt(ch->uart_chan, ch->waiting_time);
break;
case TPDU_S_WAIT_PB:
/* we just completed the TPDU header from reader to card
* and now need to disable the receiver, enable the
* transmitter and transmit the procedure byte */
card_emu_uart_enable(ch->uart_chan, ENABLE_TX);
+ /* prepare to extend the waiting time once half of it is reached */
+ card_emu_uart_update_wt(ch->uart_chan, ch->waiting_time);
+ break;
+ case TPDU_S_WAIT_TX:
+ /* If we came from WAIT_RX, disable the receiver and
+ * enable the transmitter. If we came from WAIT_RX or
+ * WAIT_PB, reset the waiting time so that we can extend
+ * waiting time if needed. */
+ card_emu_uart_enable(ch->uart_chan, ENABLE_TX);
+ /* prepare to extend the waiting time once half of it is reached */
+ card_emu_uart_update_wt(ch->uart_chan, ch->waiting_time);
break;
default:
break;
@@ -837,8 +889,8 @@ process_byte_tpdu(struct card_handle *ch, uint8_t byte)
add_tpdu_byte(ch, byte);
break;
default:
- TRACE_ERROR("%u: process_byte_tpdu() in invalid state %u\r\n",
- ch->num, ch->tpdu.state);
+ TRACE_ERROR("%u: process_byte_tpdu() in invalid TPDU state %s\r\n", ch->num,
+ get_value_string(tpdu_state_names, ch->tpdu.state));
}
/* ensure we stay in TPDU ISO state */
@@ -875,6 +927,7 @@ static int tx_byte_tpdu(struct card_handle *ch)
byte = msgb_pull_u8(msg);
card_emu_uart_tx(ch->uart_chan, byte);
+ card_emu_uart_reset_wt(ch->uart_chan);
/* this must happen _after_ the byte has been transmitted */
switch (ch->tpdu.state) {
@@ -925,6 +978,8 @@ void card_emu_process_rx_byte(struct card_handle *ch, uint8_t byte)
switch (ch->state) {
case ISO_S_WAIT_TPDU:
if (byte == 0xff) {
+ /* reset PTS to initial state */
+ set_pts_state(ch, PTS_S_WAIT_REQ_PTSS);
new_state = process_byte_pts(ch, byte);
ch->stats.pps++;
goto out_silent;
@@ -937,8 +992,8 @@ void card_emu_process_rx_byte(struct card_handle *ch, uint8_t byte)
new_state = process_byte_pts(ch, byte);
goto out_silent;
default:
- TRACE_ERROR("%u: Received UART char in invalid 7816 state "
- "%u\r\n", ch->num, ch->state);
+ TRACE_ERROR("%u: Received UART char in invalid 7816 state %s\r\n", ch->num,
+ get_value_string(iso7816_3_card_state_names, ch->state));
break;
}
@@ -991,13 +1046,16 @@ void card_emu_have_new_uart_tx(struct card_handle *ch)
}
}
-void card_emu_report_status(struct card_handle *ch)
+void card_emu_report_status(struct card_handle *ch, bool report_on_irq)
{
struct msgb *msg;
struct cardemu_usb_msg_status *sts;
+ uint8_t ep = ch->in_ep;
+
+ if (report_on_irq)
+ ep = ch->irq_ep;
- msg = usb_buf_alloc_st(ch->in_ep, SIMTRACE_MSGC_CARDEM,
- SIMTRACE_MSGT_BD_CEMU_STATUS);
+ msg = usb_buf_alloc_st(ep, SIMTRACE_MSGC_CARDEM, SIMTRACE_MSGT_BD_CEMU_STATUS);
if (!msg)
return;
@@ -1009,27 +1067,61 @@ void card_emu_report_status(struct card_handle *ch)
sts->flags |= CEMU_STATUS_F_CLK_ACTIVE;
if (ch->in_reset)
sts->flags |= CEMU_STATUS_F_RESET_ACTIVE;
- /* FIXME: voltage + card insert */
- sts->fi = ch->fi;
- sts->di = ch->di;
+#ifdef DETECT_VCC_BY_ADC
+ sts->voltage_mv = card_emu_get_vcc(ch->num);
+#endif
+ /* FIXME: card insert */
+ sts->F_index = ch->F_index;
+ sts->D_index = ch->D_index;
sts->wi = ch->wi;
sts->waiting_time = ch->waiting_time;
usb_buf_upd_len_and_submit(msg);
}
+static void card_emu_report_config(struct card_handle *ch)
+{
+ struct msgb *msg;
+ struct cardemu_usb_msg_config *cfg;
+ uint8_t ep = ch->in_ep;
+
+ msg = usb_buf_alloc_st(ch->in_ep, SIMTRACE_MSGC_CARDEM, SIMTRACE_MSGT_BD_CEMU_CONFIG);
+ if (!msg)
+ return;
+
+ cfg = (struct cardemu_usb_msg_config *) msgb_put(msg, sizeof(*cfg));
+ cfg->features = ch->features;
+#ifdef HAVE_SLOT_MUX
+ cfg->slot_mux_nr = mux_get_slot();
+#else
+ cfg->slot_mux_nr = 0;
+#endif
+
+
+ usb_buf_upd_len_and_submit(msg);
+}
+
/* hardware driver informs us that a card I/O signal has changed */
void card_emu_io_statechg(struct card_handle *ch, enum card_io io, int active)
{
+ uint32_t chg_mask = 0;
+
switch (io) {
case CARD_IO_VCC:
if (active == 0 && ch->vcc_active == 1) {
TRACE_INFO("%u: VCC deactivated\r\n", ch->num);
- tc_etu_disable(ch->tc_chan);
+ card_handle_reset(ch);
card_set_state(ch, ISO_S_WAIT_POWER);
+ chg_mask |= CEMU_STATUS_F_VCC_PRESENT;
} else if (active == 1 && ch->vcc_active == 0) {
+#ifdef DETECT_VCC_BY_ADC
+ TRACE_INFO("%u: VCC activated (%d mV)\r\n", ch->num,
+ card_emu_get_vcc(ch->num));
+#else
TRACE_INFO("%u: VCC activated\r\n", ch->num);
+#endif
card_set_state(ch, ISO_S_WAIT_CLK);
+ chg_mask |= CEMU_STATUS_F_VCC_PRESENT;
}
ch->vcc_active = active;
break;
@@ -1038,27 +1130,49 @@ void card_emu_io_statechg(struct card_handle *ch, enum card_io io, int active)
TRACE_INFO("%u: CLK activated\r\n", ch->num);
if (ch->state == ISO_S_WAIT_CLK)
card_set_state(ch, ISO_S_WAIT_RST);
+ chg_mask |= CEMU_STATUS_F_CLK_ACTIVE;
} else if (active == 0 && ch->clocked == 1) {
TRACE_INFO("%u: CLK deactivated\r\n", ch->num);
+ chg_mask |= CEMU_STATUS_F_CLK_ACTIVE;
}
ch->clocked = active;
break;
case CARD_IO_RST:
if (active == 0 && ch->in_reset) {
TRACE_INFO("%u: RST released\r\n", ch->num);
- if (ch->vcc_active && ch->clocked) {
- /* enable the TC/ETU counter once reset has been released */
- tc_etu_enable(ch->tc_chan);
+ if (ch->vcc_active && ch->clocked && ch->state == ISO_S_WAIT_RST) {
/* prepare to send the ATR */
card_set_state(ch, ISO_S_WAIT_ATR);
}
+ chg_mask |= CEMU_STATUS_F_RESET_ACTIVE;
} else if (active && !ch->in_reset) {
TRACE_INFO("%u: RST asserted\r\n", ch->num);
- tc_etu_disable(ch->tc_chan);
+ card_handle_reset(ch);
+ chg_mask |= CEMU_STATUS_F_RESET_ACTIVE;
+ card_set_state(ch, ISO_S_WAIT_RST);
}
ch->in_reset = active;
break;
}
+
+ switch (ch->state) {
+ case ISO_S_WAIT_POWER:
+ case ISO_S_WAIT_CLK:
+ case ISO_S_WAIT_RST:
+ /* check end activation state (even if the reader does
+ * not respect the activation sequence) */
+ if (ch->vcc_active && ch->clocked && !ch->in_reset) {
+ /* prepare to send the ATR */
+ card_set_state(ch, ISO_S_WAIT_ATR);
+ }
+ break;
+ default:
+ break;
+ }
+
+ /* notify the host about the state change */
+ if ((ch->features & CEMU_FEAT_F_STATUS_IRQ) && chg_mask)
+ card_emu_report_status(ch, true);
}
/* User sets a new ATR to be returned during next card reset */
@@ -1085,7 +1199,7 @@ int card_emu_set_atr(struct card_handle *ch, const uint8_t *atr, uint8_t len)
}
/* hardware driver informs us that one (more) ETU has expired */
-void tc_etu_wtime_half_expired(void *handle)
+void card_emu_wtime_half_expired(void *handle)
{
struct card_handle *ch = handle;
/* transmit NULL procedure byte well before waiting time expires */
@@ -1095,7 +1209,10 @@ void tc_etu_wtime_half_expired(void *handle)
case TPDU_S_WAIT_PB:
case TPDU_S_WAIT_TX:
putchar('N');
+ /* we are waiting for data from the user. Send a procedure byte to ask the
+ * reader to wait more time */
card_emu_uart_tx(ch->uart_chan, ISO7816_3_PB_NULL);
+ card_emu_uart_reset_wt(ch->uart_chan);
break;
default:
break;
@@ -1107,7 +1224,7 @@ void tc_etu_wtime_half_expired(void *handle)
}
/* hardware driver informs us that one (more) ETU has expired */
-void tc_etu_wtime_expired(void *handle)
+void card_emu_wtime_expired(void *handle)
{
struct card_handle *ch = handle;
switch (ch->state) {
@@ -1121,13 +1238,45 @@ void tc_etu_wtime_expired(void *handle)
}
}
-/* shortest ATR found in smartcard_list.txt */
-static const uint8_t default_atr[] = { 0x3B, 0x02, 0x14, 0x50 };
+/* reasonable ATR offering all protocols and voltages
+ * smartphones might not care, but other readers do
+ *
+ * TS = 0x3B Direct Convention
+ * T0 = 0x80 Y(1): b1000, K: 0 (historical bytes)
+ * TD(1) = 0x80 Y(i+1) = b1000, Protocol T=0
+ * ----
+ * TD(2) = 0x81 Y(i+1) = b1000, Protocol T=1
+ * ----
+ * TD(3) = 0x1F Y(i+1) = b0001, Protocol T=15
+ * ----
+ * TA(4) = 0xC7 Clock stop: no preference - Class accepted by the card: (3G) A 5V B 3V C 1.8V
+ * ----
+ * Historical bytes
+ * TCK = 0x59 correct checksum
+ */
+static const uint8_t default_atr[] = { 0x3B, 0x80, 0x80, 0x81 , 0x1F, 0xC7, 0x59 };
static struct card_handle card_handles[NUM_SLOTS];
-struct card_handle *card_emu_init(uint8_t slot_num, uint8_t tc_chan, uint8_t uart_chan,
- uint8_t in_ep, uint8_t irq_ep)
+int card_emu_set_config(struct card_handle *ch, const struct cardemu_usb_msg_config *scfg,
+ unsigned int scfg_len)
+{
+ if (scfg_len >= sizeof(uint32_t))
+ ch->features = (scfg->features & SUPPORTED_FEATURES);
+
+#ifdef HAVE_SLOT_MUX
+ if (scfg_len >= sizeof(uint32_t)+sizeof(uint8_t)) {
+ mux_set_slot(scfg->slot_mux_nr);
+ }
+#endif
+
+ /* send back a report of our current configuration */
+ card_emu_report_config(ch);
+
+ return 0;
+}
+
+struct card_handle *card_emu_init(uint8_t slot_num, uint8_t uart_chan, uint8_t in_ep, uint8_t irq_ep, bool vcc_active, bool in_reset, bool clocked)
{
struct card_handle *ch;
@@ -1140,20 +1289,18 @@ struct card_handle *card_emu_init(uint8_t slot_num, uint8_t tc_chan, uint8_t uar
INIT_LLIST_HEAD(&ch->uart_tx_queue);
- /* initialize the card_handle with reasonable defaults */
ch->num = slot_num;
ch->irq_ep = irq_ep;
ch->in_ep = in_ep;
ch->state = ISO_S_WAIT_POWER;
- ch->vcc_active = 0;
- ch->in_reset = 1;
- ch->clocked = 0;
+ ch->vcc_active = vcc_active;
+ ch->in_reset = in_reset;
+ ch->clocked = clocked;
- ch->fi = 0;
- ch->di = 1;
+ ch->Fi_index = ch->F_index = 1;
+ ch->Di_index = ch->D_index = 1;
ch->wi = ISO7816_3_DEFAULT_WI;
- ch->tc_chan = tc_chan;
ch->uart_chan = uart_chan;
ch->waiting_time = ISO7816_3_INIT_WTIME;
@@ -1164,7 +1311,7 @@ struct card_handle *card_emu_init(uint8_t slot_num, uint8_t tc_chan, uint8_t uar
ch->pts.state = PTS_S_WAIT_REQ_PTSS;
ch->tpdu.state = TPDU_S_WAIT_CLA;
- tc_etu_init(ch->tc_chan, ch);
+ card_handle_reset(ch);
return ch;
}
diff --git a/firmware/libcommon/source/cciddriver.c b/firmware/libcommon/source/cciddriver.c
index 1dbdf23..b4ff451 100644
--- a/firmware/libcommon/source/cciddriver.c
+++ b/firmware/libcommon/source/cciddriver.c
@@ -193,8 +193,8 @@ static void RDRtoPCDatablock_ATR( void )
ccidDriver.ProtocolDataStructure[0] = Atr[2]; // TA(1)
// bmTCCKST0
- // For T=0 ,B0 – 0b, B7-2 – 000000b
- // B1 – Convention used (b1=0 for direct, b1=1 for inverse)
+ // For T=0 ,B0 - 0b, B7-2 - 000000b
+ // B1 - Convention used (b1=0 for direct, b1=1 for inverse)
// bGuardTimeT0
// Extra Guardtime between two characters. Add 0 to 254 etu to the normal
@@ -428,7 +428,7 @@ static void PCtoRDRXfrBlock( void )
uint16_t msglen = 0;
uint32_t ret;
- TRACE_DEBUG("PCtoRDRXfrBlock\n");
+ TRACE_DEBUG("PCtoRDRXfrBlock\n\r");
// Check the block length
if ( ccidDriver.sCcidCommand.wLength > (configurationDescriptorsFS->ccid.dwMaxCCIDMessageLength-10) ) {
@@ -921,7 +921,7 @@ void USBDCallbacks_RequestReceived(const USBGenericRequest *request)
void CCID_SmartCardRequest( void )
{
unsigned char bStatus;
- TRACE_DEBUG("CCID_req\n");
+ TRACE_DEBUG("CCID_req\n\r");
do {
@@ -1005,7 +1005,7 @@ unsigned char CCID_Removal( void )
//------------------------------------------------------------------------------
/// Interrupt-IN Messages
/// This message is sent when any bit in the bHardwareErrorCode field is set.
-/// If this message is sent when there is no “outstanding” command, the bSeq
+/// If this message is sent when there is no "outstanding" command, the bSeq
/// field will be undefined.
/// \param bSlot ICC slot number
/// \param bSeq Sequence number of the bulk OUT command when the hardware error
diff --git a/firmware/libcommon/source/crcstub.c b/firmware/libcommon/source/crcstub.c
new file mode 100644
index 0000000..ef52521
--- /dev/null
+++ b/firmware/libcommon/source/crcstub.c
@@ -0,0 +1,86 @@
+/* SIMtrace 2 firmware crc stub
+ *
+ * (C) 2021 by sysmocom -s.f.m.c. GmbH, Author: Eric Wild <ewild@sysmocom.de>
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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.
+ */
+
+#include <stdint.h>
+#include "board.h"
+#include "core_cm3.h"
+#include "usb/device/dfu/dfu.h"
+
+/*
+* This file is a bit special, everything has to go to specific sections, and no globals are available.
+* No external functions may be called, unless inlining is enforced!
+*/
+
+static void crc_check_stub();
+__attribute__((section(".crcstub_table"))) volatile uint32_t crcstub_dummy_table[] = {
+ (uint32_t)0xdeadc0de, /* deliberately choose invalid value so unpatched image will not be started */
+ (uint32_t)crc_check_stub, /* must be valid flash addr */
+ (uint32_t)0xf1, /* crc value calculated by the host */
+ (uint32_t)0xf2, /* crc calc start address */
+ (uint32_t)0xf3 /* crc calc length (byte) */
+};
+
+__attribute__((section(".crcstub_code"))) static void do_crc32(int8_t c, uint32_t *crc_reg)
+{
+ int32_t i, mask;
+ *crc_reg ^= c;
+
+ for (unsigned int j = 0; j < 8; j++)
+ if (*crc_reg & 1)
+ *crc_reg = (*crc_reg >> 1) ^ 0xEDB88320;
+ else
+ *crc_reg = *crc_reg >> 1;
+}
+
+__attribute__((section(".crcstub_code"), noinline)) static void crc_check_stub()
+{
+ uint32_t crc_reg = 0xffffffff;
+ uint32_t expected_crc_val = crcstub_dummy_table[2];
+ uint8_t *crc_calc_startaddr = (uint8_t *)crcstub_dummy_table[3];
+ volatile uint32_t *actual_exc_tbl = (volatile uint32_t *)crc_calc_startaddr;
+ uint32_t crc_len = crcstub_dummy_table[4];
+
+ /* 4000ms wdt tickling */
+ WDT->WDT_MR = WDT_MR_WDRSTEN | WDT_MR_WDDBGHLT | WDT_MR_WDIDLEHLT | (((4000UL << 8) / 1000) << 16) |
+ ((4000UL << 8) / 1000);
+
+ for (uint8_t *i = crc_calc_startaddr; i < crc_calc_startaddr + crc_len; i++)
+ do_crc32(*i, &crc_reg);
+
+ crc_reg = ~crc_reg;
+
+ if (crc_reg == expected_crc_val) {
+ /* this looks a bit awkward because we have to ensure the bx does not require a sp-relative load */
+ __asm__ volatile("\
+ mov r0, %0;\n\
+ mov r1, %1;\n\
+ MSR msp,r0;\n\
+ bx r1;"
+ :
+ : "r"(actual_exc_tbl[0]), "r"(actual_exc_tbl[1]));
+ } else {
+ /* no globals ! */
+ ((struct dfudata *)0x20000000)->magic = USB_DFU_MAGIC;
+ __DSB();
+ for (;;) {
+ /* no functon call, since NVIC_SystemReset() might not be inlined! */
+ SCB->AIRCR = ((0x5FA << SCB_AIRCR_VECTKEY_Pos) | (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) |
+ SCB_AIRCR_SYSRESETREQ_Msk);
+ __DSB();
+ while (1)
+ ;
+ }
+ }
+}
diff --git a/firmware/libcommon/source/fputs.c b/firmware/libcommon/source/fputs.c
index 110f68e..8f2b21e 100644
--- a/firmware/libcommon/source/fputs.c
+++ b/firmware/libcommon/source/fputs.c
@@ -9,10 +9,6 @@
* 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 this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*/
#include <stdio.h>
#include "uart_console.h"
diff --git a/firmware/libcommon/source/host_communication.c b/firmware/libcommon/source/host_communication.c
index ea573bb..b2faf1b 100644
--- a/firmware/libcommon/source/host_communication.c
+++ b/firmware/libcommon/source/host_communication.c
@@ -9,10 +9,6 @@
* 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 this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*/
#include "board.h"
#include "llist_irqsafe.h"
@@ -27,27 +23,36 @@
* USBD Integration API
***********************************************************************/
-/* call-back after (successful?) transfer of a buffer */
+/* call-back after (successful?) transfer of a write buffer on IN EP */
static void usb_write_cb(uint8_t *arg, uint8_t status, uint32_t transferred,
uint32_t remaining)
{
struct msgb *msg = (struct msgb *) arg;
struct usb_buffered_ep *bep = msg->dst;
+ uint16_t ep_size = USBD_GetEndpointSize(bep->ep);
unsigned long x;
TRACE_DEBUG("%s (EP=0x%02x)\r\n", __func__, bep->ep);
+ if (((msgb_length(msg) % ep_size) == 0) && (transferred == ep_size)) {
+ /* terminate with ZLP; pass in 'msg' again as 'arg' so we get
+ * called the second time and proceed with usb_buf_free below */
+ USBD_Write(bep->ep, 0, 0, (TransferCallback) &usb_write_cb, msg);
+ return;
+ }
+
local_irq_save(x);
bep->in_progress--;
local_irq_restore(x);
- TRACE_DEBUG("%u: in_progress=%d\n", bep->ep, bep->in_progress);
+ TRACE_DEBUG("%u: in_progress=%lu\r\n", bep->ep, bep->in_progress);
if (status != USBD_STATUS_SUCCESS)
- TRACE_ERROR("%s error, status=%d\n", __func__, status);
+ TRACE_ERROR("%s error, status=%d\r\n", __func__, status);
usb_buf_free(msg);
}
+/* check if the spcified IN endpoint is idle and submit the next buffer from queue */
int usb_refill_to_host(uint8_t ep)
{
struct usb_buffered_ep *bep = usb_get_buf_ep(ep);
@@ -75,44 +80,44 @@ int usb_refill_to_host(uint8_t ep)
bep->in_progress++;
- msg = msgb_dequeue(&bep->queue);
+ msg = msgb_dequeue_count(&bep->queue, &bep->queue_len);
local_irq_restore(x);
- TRACE_DEBUG("%s (EP=0x%02x), in_progress=%d\r\n", __func__, ep, bep->in_progress);
+ TRACE_DEBUG("%s (EP=0x%02x), in_progress=%lu\r\n", __func__, ep, bep->in_progress);
msg->dst = bep;
rc = USBD_Write(ep, msgb_data(msg), msgb_length(msg),
(TransferCallback) &usb_write_cb, msg);
if (rc != USBD_STATUS_SUCCESS) {
- TRACE_ERROR("%s error %x\n", __func__, rc);
+ TRACE_ERROR("%s error %x\r\n", __func__, rc);
/* re-insert to head of queue */
llist_add_irqsafe(&msg->list, &bep->queue);
local_irq_save(x);
bep->in_progress--;
local_irq_restore(x);
- TRACE_DEBUG("%02x: in_progress=%d\n", bep->ep, bep->in_progress);
+ TRACE_DEBUG("%02x: in_progress=%lu\r\n", bep->ep, bep->in_progress);
return 0;
}
return 1;
}
-/* call-back after (successful?) transfer of a buffer */
+/* call-back after (successful?) read transfer of a buffer on OUT EP */
static void usb_read_cb(uint8_t *arg, uint8_t status, uint32_t transferred,
uint32_t remaining)
{
struct msgb *msg = (struct msgb *) arg;
struct usb_buffered_ep *bep = msg->dst;
- TRACE_DEBUG("%s (EP=%u, len=%u, q=%p)\r\n", __func__,
+ TRACE_DEBUG("%s (EP=%u, len=%lu, q=%p)\r\n", __func__,
bep->ep, transferred, &bep->queue);
bep->in_progress = 0;
if (status != USBD_STATUS_SUCCESS) {
- TRACE_ERROR("%s error, status=%d\n", __func__, status);
+ TRACE_ERROR("%s error, status=%d\r\n", __func__, status);
usb_buf_free(msg);
return;
}
@@ -120,6 +125,7 @@ static void usb_read_cb(uint8_t *arg, uint8_t status, uint32_t transferred,
llist_add_tail_irqsafe(&msg->list, &bep->queue);
}
+/* refill the read queue for data received from host PC on OUT EP, if needed */
int usb_refill_from_host(uint8_t ep)
{
struct usb_buffered_ep *bep = usb_get_buf_ep(ep);
@@ -150,7 +156,7 @@ int usb_refill_from_host(uint8_t ep)
rc = USBD_Read(ep, msg->head, msgb_tailroom(msg),
(TransferCallback) &usb_read_cb, msg);
if (rc != USBD_STATUS_SUCCESS) {
- TRACE_ERROR("%s error %d\n", __func__, rc);
+ TRACE_ERROR("%s error %d\r\n", __func__, rc);
usb_buf_free(msg);
bep->in_progress = 0;
}
@@ -158,6 +164,7 @@ int usb_refill_from_host(uint8_t ep)
return 1;
}
+/* drain any buffers from the queue of the endpoint and release their memory */
int usb_drain_queue(uint8_t ep)
{
struct usb_buffered_ep *bep = usb_get_buf_ep(ep);
@@ -177,7 +184,7 @@ int usb_drain_queue(uint8_t ep)
}
/* free all queued msgbs */
- while ((msg = msgb_dequeue(&bep->queue))) {
+ while ((msg = msgb_dequeue_count(&bep->queue, &bep->queue_len))) {
usb_buf_free(msg);
ret++;
}
diff --git a/firmware/libcommon/source/iso7816_fidi.c b/firmware/libcommon/source/iso7816_fidi.c
index 1c70467..024663b 100644
--- a/firmware/libcommon/source/iso7816_fidi.c
+++ b/firmware/libcommon/source/iso7816_fidi.c
@@ -11,10 +11,6 @@
* 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 this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*/
#include <stdint.h>
#include <errno.h>
@@ -23,38 +19,38 @@
#include "iso7816_fidi.h"
/* Table 7 of ISO 7816-3:2006 */
-const uint16_t fi_table[] = {
+const uint16_t iso7816_3_fi_table[] = {
372, 372, 558, 744, 1116, 1488, 1860, 0,
0, 512, 768, 1024, 1536, 2048, 0, 0
};
/* Table 8 from ISO 7816-3:2006 */
-const uint8_t di_table[] = {
+const uint8_t iso7816_3_di_table[] = {
0, 1, 2, 4, 8, 16, 32, 64,
12, 20, 2, 4, 8, 16, 32, 64,
};
/* compute the F/D ratio based on Fi and Di values */
-int compute_fidi_ratio(uint8_t fi, uint8_t di)
+int iso7816_3_compute_fd_ratio(uint8_t f_index, uint8_t d_index)
{
uint16_t f, d;
int ret;
- if (fi >= ARRAY_SIZE(fi_table) ||
- di >= ARRAY_SIZE(di_table))
+ if (f_index >= ARRAY_SIZE(iso7816_3_fi_table) ||
+ d_index >= ARRAY_SIZE(iso7816_3_di_table))
return -EINVAL;
- f = fi_table[fi];
+ f = iso7816_3_fi_table[f_index];
if (f == 0)
return -EINVAL;
- d = di_table[di];
+ d = iso7816_3_di_table[d_index];
if (d == 0)
return -EINVAL;
/* See table 7 of ISO 7816-3: From 1000 on we divide by 1/d,
* which equals a multiplication by d */
- if (di < 8)
+ if (d_index < 8)
ret = f / d;
else
ret = f * d;
diff --git a/firmware/libcommon/source/main_common.c b/firmware/libcommon/source/main_common.c
new file mode 100644
index 0000000..cd3bced
--- /dev/null
+++ b/firmware/libcommon/source/main_common.c
@@ -0,0 +1,50 @@
+/* SIMtrace 2 firmware common main helpers
+ *
+ * (C) 2015-2019 by Harald Welte <hwelte@hmw-consulting.de>
+ *
+ * This program 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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.
+ */
+
+#include "board.h"
+#include "utils.h"
+
+void print_banner(void)
+{
+ printf("\n\r\n\r"
+ "=============================================================================\n\r"
+ "SIMtrace2 firmware " GIT_VERSION ", BOARD=" BOARD ", APP=" APPLICATION "\n\r"
+ "(C) 2010-2019 by Harald Welte, 2018-2019 by Kevin Redon\n\r"
+ "=============================================================================\n\r");
+
+#if (TRACE_LEVEL >= TRACE_LEVEL_INFO)
+ /* print chip-unique ID */
+ unsigned int unique_id[4];
+ EEFC_ReadUniqueID(unique_id);
+ TRACE_INFO("Chip ID: 0x%08lx (Ext 0x%08lx)\n\r", CHIPID->CHIPID_CIDR, CHIPID->CHIPID_EXID);
+ TRACE_INFO("Serial Nr. %08x-%08x-%08x-%08x\n\r",
+ unique_id[0], unique_id[1], unique_id[2], unique_id[3]);
+
+ /* print reset cause */
+ uint8_t reset_cause = (RSTC->RSTC_SR & RSTC_SR_RSTTYP_Msk) >> RSTC_SR_RSTTYP_Pos;
+ static const char* reset_causes[] = {
+ "general reset (first power-up reset)",
+ "backup reset (return from backup mode)",
+ "watchdog reset (watchdog fault occurred)",
+ "software reset (processor reset required by the software)",
+ "user reset (NRST pin detected low)",
+ };
+ if (reset_cause < ARRAY_SIZE(reset_causes)) {
+ TRACE_INFO("Reset Cause: %s\n\r", reset_causes[reset_cause]);
+ } else {
+ TRACE_INFO("Reset Cause: 0x%lx\n\r", (RSTC->RSTC_SR & RSTC_SR_RSTTYP_Msk) >> RSTC_SR_RSTTYP_Pos);
+ }
+#endif
+}
diff --git a/firmware/libcommon/source/mode_cardemu.c b/firmware/libcommon/source/mode_cardemu.c
index 98818e1..a05840e 100644
--- a/firmware/libcommon/source/mode_cardemu.c
+++ b/firmware/libcommon/source/mode_cardemu.c
@@ -1,7 +1,7 @@
/* card emulation mode
*
* (C) 2015-2017 by Harald Welte <laforge@gnumonks.org>
- * (C) 2018 by sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon@sysmocom.de>
+ * (C) 2018-2019 by sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon@sysmocom.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -12,10 +12,6 @@
* 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 this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*/
#include "board.h"
#include "boardver_adc.h"
@@ -39,12 +35,28 @@ static const Pin pins_cardsim[] = PINS_CARDSIM;
#endif
/* UART pins */
+#if defined(ngff_cardem)
+static const Pin pins_usim1[] = {PINS_USIM2};
+static const Pin pin_usim1_rst = PIN_USIM2_nRST;
+#define FIRST_USART_BASE USART0
+#define FIRST_USART_ID ID_USART0
+#define FIRST_USART_IRQ USART0_IRQn
+#else
static const Pin pins_usim1[] = {PINS_USIM1};
static const Pin pin_usim1_rst = PIN_USIM1_nRST;
+#define FIRST_USART_BASE USART1
+#define FIRST_USART_ID ID_USART1
+#define FIRST_USART_IRQ USART1_IRQn
+#endif
static const Pin pin_usim1_vcc = PIN_USIM1_VCC;
+#ifdef PIN_USIM1_IO_DIR
+static const Pin pin_io_dir = PIN_USIM1_IO_DIR;
+#endif
+
+
#ifdef CARDEMU_SECOND_UART
-static const Pin pins_usim2[] = {PINS_USIM2};
+static const Pin pins_usim2[] = {PINS_USIM2};
static const Pin pin_usim2_rst = PIN_USIM2_nRST;
static const Pin pin_usim2_vcc = PIN_USIM2_VCC;
#endif
@@ -55,21 +67,45 @@ struct cardem_inst {
struct llist_head usb_out_queue;
struct ringbuf rb;
struct Usart_info usart_info;
+ struct {
+ /*! receiver waiting time to trigger timeout (0 to deactivate it) */
+ uint32_t total;
+ /*! remaining waiting time (we may need multiple timer runs to reach total */
+ uint32_t remaining;
+ /*! did we already notify about half the time having expired? */
+ bool half_time_notified;
+ } wt;
int usb_pending_old;
uint8_t ep_out;
uint8_t ep_in;
uint8_t ep_int;
const Pin pin_insert;
+#ifdef DETECT_VCC_BY_ADC
uint32_t vcc_uv;
- uint32_t vcc_uv_last;
+#endif
+
+ /*! real-time state of VCC I/O line, irrespective of enabled flag */
+ bool vcc_active;
+
+ /*! last VCC state we reported to the card emu state machine (conditioned by enabled flag) */
+ bool vcc_active_last;
+
+ /*! real-time state of RST I/O line, irrespective of enabled flag */
+ bool rst_active;
+
+ /*! last RST state we reported to the card emu state machine (conditioned by enabled flag) */
+ bool rst_active_last;
+
+ /*! flag indicating whether this instance should perform card emulation, or not */
+ bool enabled;
};
struct cardem_inst cardem_inst[] = {
{
.num = 0,
.usart_info = {
- .base = USART1,
- .id = ID_USART1,
+ .base = FIRST_USART_BASE,
+ .id = FIRST_USART_ID,
.state = USART_RCV
},
.ep_out = SIMTRACE_CARDEM_USB_EP_USIM1_DATAOUT,
@@ -129,18 +165,54 @@ void card_emu_uart_wait_tx_idle(uint8_t uart_chan)
wait_tx_idle(usart);
}
+static void card_emu_uart_set_direction(uint8_t uart_chan, bool tx)
+{
+ /* only on some boards (octsimtest) we hae an external level
+ * shifter that requires us to switch the direction between RX and TX */
+#ifdef PIN_USIM1_IO_DIR
+ if (uart_chan == 0) {
+ if (tx)
+ PIO_Set(&pin_io_dir);
+ else
+ PIO_Clear(&pin_io_dir);
+ }
+#endif
+}
+
+int card_emu_get_vcc(uint8_t uart_chan)
+{
+ struct cardem_inst *ci = &cardem_inst[uart_chan];
+#ifdef DETECT_VCC_BY_ADC
+ return ci->vcc_uv / 1000;
+#else
+ return -1;
+#endif
+}
+
/* call-back from card_emu.c to enable/disable transmit and/or receive */
void card_emu_uart_enable(uint8_t uart_chan, uint8_t rxtx)
{
Usart *usart = get_usart_by_chan(uart_chan);
switch (rxtx) {
case ENABLE_TX:
- USART_DisableIt(usart, ~US_IER_TXRDY);
+ card_emu_uart_set_direction(uart_chan, true);
+ USART_DisableIt(usart, ~(US_IER_TXRDY | US_IER_TIMEOUT));
+ /* as irritating as it is, we actually want to keep the
+ * receiver enabled during transmit */
+ USART_SetReceiverEnabled(usart, 1);
+ usart->US_CR = US_CR_RSTSTA | US_CR_RSTIT | US_CR_RSTNACK;
+ USART_EnableIt(usart, US_IER_TXRDY | US_IER_TIMEOUT);
+ USART_SetTransmitterEnabled(usart, 1);
+ break;
+ case ENABLE_TX_TIMER_ONLY:
+ /* enable the transmitter without generating TXRDY interrupts
+ * just so that the timer can run */
+ USART_DisableIt(usart, ~US_IER_TIMEOUT);
/* as irritating as it is, we actually want to keep the
* receiver enabled during transmit */
USART_SetReceiverEnabled(usart, 1);
usart->US_CR = US_CR_RSTSTA | US_CR_RSTIT | US_CR_RSTNACK;
- USART_EnableIt(usart, US_IER_TXRDY);
+ USART_EnableIt(usart, US_IER_TIMEOUT);
USART_SetTransmitterEnabled(usart, 1);
break;
case ENABLE_RX:
@@ -149,6 +221,7 @@ void card_emu_uart_enable(uint8_t uart_chan, uint8_t rxtx)
* transmitter enabled during receive */
USART_SetTransmitterEnabled(usart, 1);
wait_tx_idle(usart);
+ card_emu_uart_set_direction(uart_chan, false);;
usart->US_CR = US_CR_RSTSTA | US_CR_RSTIT | US_CR_RSTNACK;
USART_EnableIt(usart, US_IER_RXRDY);
USART_SetReceiverEnabled(usart, 1);
@@ -188,8 +261,25 @@ int card_emu_uart_tx(uint8_t uart_chan, uint8_t byte)
return 1;
}
+static uint16_t compute_next_timeout(struct cardem_inst *ci)
+{
+ uint32_t want_to_expire;
+
+ if (ci->wt.total == 0)
+ return 0;
+
+ if (!ci->wt.half_time_notified) {
+ /* we need to make sure to expire after half the total waiting time */
+ OSMO_ASSERT(ci->wt.remaining > (ci->wt.total / 2));
+ want_to_expire = ci->wt.remaining - (ci->wt.total / 2);
+ } else
+ want_to_expire = ci->wt.remaining;
+ /* if value exceeds the USART TO range, use the maximum possible value for one round */
+ return OSMO_MIN(want_to_expire, 0xffff);
+}
-/* FIXME: integrate this with actual irq handler */
+/*! common handler if interrupt was received.
+ * \param[in] inst_num Instance number, range 0..1 (some boards only '0' permitted) */
static void usart_irq_rx(uint8_t inst_num)
{
Usart *usart = get_usart_by_chan(inst_num);
@@ -197,32 +287,84 @@ static void usart_irq_rx(uint8_t inst_num)
uint32_t csr;
uint8_t byte = 0;
+ /* get one atomic snapshot of state/flags before they get changed */
csr = usart->US_CSR & usart->US_IMR;
+ /* check if one byte has been completely received and is now in the holding register */
if (csr & US_CSR_RXRDY) {
+ /* read the bye from the holding register */
byte = (usart->US_RHR) & 0xFF;
+ /* append it to the buffer */
if (rbuf_write(&ci->rb, byte) < 0)
TRACE_ERROR("rbuf overrun\r\n");
}
+ /* check if the transmitter is ready for the next byte */
if (csr & US_CSR_TXRDY) {
- if (card_emu_tx_byte(ci->ch) == 0)
+ /* transmit next byte and check if more bytes are to be transmitted */
+ if (card_emu_tx_byte(ci->ch) == 0) {
+ /* stop the TX ready interrupt of no more bytes to transmit */
USART_DisableIt(usart, US_IER_TXRDY);
+ }
}
- if (csr & (US_CSR_OVRE|US_CSR_FRAME|US_CSR_PARE|
- US_CSR_TIMEOUT|US_CSR_NACK|(1<<10))) {
+ /* check if any error flags are set */
+ if (csr & (US_CSR_OVRE|US_CSR_FRAME|US_CSR_PARE|US_CSR_NACK|(1<<10))) {
+ /* clear any error flags */
usart->US_CR = US_CR_RSTSTA | US_CR_RSTIT | US_CR_RSTNACK;
- TRACE_ERROR("%u e 0x%x st: 0x%lx\n", ci->num, byte, csr);
+ TRACE_ERROR("%u USART error on 0x%x status: 0x%lx\n", ci->num, byte, csr);
+ }
+
+ /* check if the timeout has expired. We "abuse" the receive timer for tracking
+ * how many etu have expired since we last sent a byte. See section
+ * 33.7.3.11 "Receiver Time-out" of the SAM3S8 Data Sheet */
+ if (csr & US_CSR_TIMEOUT) {
+ /* clear timeout flag (and stop timeout until next character is received) */
+ usart->US_CR |= US_CR_STTTO;
+
+ /* RX has been inactive for some time */
+ if (ci->wt.remaining <= (usart->US_RTOR & 0xffff)) {
+ /* waiting time is over; will stop the timer */
+ ci->wt.remaining = 0;
+ } else {
+ /* subtract the actual timeout since the new might not have been set and
+ * reloaded yet */
+ ci->wt.remaining -= (usart->US_RTOR & 0xffff);
+ }
+ if (ci->wt.remaining == 0) {
+ /* let the FSM know that WT has expired */
+ card_emu_wtime_expired(ci->ch);
+ /* don't automatically re-start in this case */
+ } else {
+ bool half_time_just_reached = false;
+
+ if (ci->wt.remaining <= ci->wt.total / 2 && !ci->wt.half_time_notified) {
+ ci->wt.half_time_notified = true;
+ /* don't immediately call card_emu_wtime_half_expired(), as that
+ * in turn may calls card_emu_uart_update_wt() which will change
+ * the timeout but would be overridden 4 lines below */
+ half_time_just_reached = true;
+ }
+
+ /* update the counter no matter if we reached half time or not */
+ usart->US_RTOR = compute_next_timeout(ci);
+ /* restart the counter (if wt is 0, the timeout is not started) */
+ usart->US_CR |= US_CR_RETTO;
+
+ if (half_time_just_reached)
+ card_emu_wtime_half_expired(ci->ch);
+ }
}
}
+/*! ISR called for USART0 */
void mode_cardemu_usart0_irq(void)
{
/* USART0 == Instance 1 == USIM 2 */
usart_irq_rx(1);
}
+/*! ISR called for USART1 */
void mode_cardemu_usart1_irq(void)
{
/* USART1 == Instance 0 == USIM 1 */
@@ -241,13 +383,47 @@ int card_emu_uart_update_fidi(uint8_t uart_chan, unsigned int fidi)
return 0;
}
+/*! Update WT on USART peripheral. Will automatically re-start timer with new value.
+ * \param[in] usart USART peripheral to configure
+ * \param[in] wt inactivity Waiting Time before card_emu_wtime_expired is called (0 to disable) */
+void card_emu_uart_update_wt(uint8_t uart_chan, uint32_t wt)
+{
+ OSMO_ASSERT(uart_chan < ARRAY_SIZE(cardem_inst));
+ struct cardem_inst *ci = &cardem_inst[uart_chan];
+ Usart *usart = get_usart_by_chan(uart_chan);
+
+ if (ci->wt.total != wt) {
+ TRACE_DEBUG("%u: USART WT changed from %lu to %lu ETU\r\n", uart_chan,
+ ci->wt.total, wt);
+ }
+
+ ci->wt.total = wt;
+ /* reset and start the timer */
+ card_emu_uart_reset_wt(uart_chan);
+}
+
+/*! Reset and re-start waiting timeout count down on USART peripheral.
+ * \param[in] usart USART peripheral to configure */
+void card_emu_uart_reset_wt(uint8_t uart_chan)
+{
+ OSMO_ASSERT(uart_chan < ARRAY_SIZE(cardem_inst));
+ struct cardem_inst *ci = &cardem_inst[uart_chan];
+ Usart *usart = get_usart_by_chan(uart_chan);
+
+ /* FIXME: guard against race with interrupt handler */
+ ci->wt.remaining = ci->wt.total;
+ ci->wt.half_time_notified = false;
+ usart->US_RTOR = compute_next_timeout(ci);
+ /* restart the counter (if wt is 0, the timeout is not started) */
+ usart->US_CR |= US_CR_RETTO;
+}
+
/* call-back from card_emu.c to force a USART interrupt */
void card_emu_uart_interrupt(uint8_t uart_chan)
{
+ OSMO_ASSERT(uart_chan < ARRAY_SIZE(cardem_inst));
Usart *usart = get_usart_by_chan(uart_chan);
- if (!usart) {
- return;
- }
+
if (USART0 == usart) {
NVIC_SetPendingIRQ(USART0_IRQn);
} else if (USART1 == usart) {
@@ -260,8 +436,11 @@ void card_emu_uart_interrupt(uint8_t uart_chan)
***********************************************************************/
#ifdef DETECT_VCC_BY_ADC
+#if !defined(VCC_UV_THRESH_1V8) || !defined(VCC_UV_THRESH_3V)
+#error "You must define VCC_UV_THRESH_{1V8,3V} if you use ADC VCC detection"
+#endif
-static int adc_triggered = 0;
+static volatile int adc_triggered = 0;
static int adc_sam3s_reva_errata = 0;
static int card_vcc_adc_init(void)
@@ -302,29 +481,23 @@ static int card_vcc_adc_init(void)
ADC->ADC_CHER |= ADC_CHER_CH6;
ADC->ADC_IER |= ADC_IER_EOC6;
#endif
+ NVIC_SetPriority(ADC_IRQn, 13);
NVIC_EnableIRQ(ADC_IRQn);
ADC->ADC_CR |= ADC_CR_START;
return 0;
}
-#define VCC_UV_THRESH_1V8 1500000
-#define VCC_UV_THRESH_3V 2800000
-
static void process_vcc_adc(struct cardem_inst *ci)
{
- if (ci->vcc_uv >= VCC_UV_THRESH_3V &&
- ci->vcc_uv_last < VCC_UV_THRESH_3V) {
- card_emu_io_statechg(ci->ch, CARD_IO_VCC, 1);
- /* FIXME do this for real */
- card_emu_io_statechg(ci->ch, CARD_IO_CLK, 1);
- } else if (ci->vcc_uv < VCC_UV_THRESH_3V &&
- ci->vcc_uv_last >= VCC_UV_THRESH_3V) {
- /* FIXME do this for real */
- card_emu_io_statechg(ci->ch, CARD_IO_CLK, 0);
- card_emu_io_statechg(ci->ch, CARD_IO_VCC, 0);
- }
- ci->vcc_uv_last = ci->vcc_uv;
+#ifdef octsimtest
+ if (ci->vcc_uv >= VCC_UV_THRESH_1V8)
+#else
+ if (ci->vcc_uv >= VCC_UV_THRESH_3V)
+#endif
+ ci->vcc_active = true;
+ else
+ ci->vcc_active = false;
}
void ADC_IrqHandler(void)
@@ -347,44 +520,60 @@ void ADC_IrqHandler(void)
cardem_inst[0].vcc_uv = adc2uv(val);
process_vcc_adc(&cardem_inst[0]);
ADC->ADC_CR |= ADC_CR_START;
+ adc_triggered = 1;
}
}
#endif /* DETECT_VCC_BY_ADC */
+
+/**
+ * called from main loop; dispatches card I/O state changes to card_emu from main loop.
+ * NOTE: conditions I/O state on the ci->enabled flag; if the instance is disabled, we assume VCC is
+ * disabled and the device is not in reset
+ */
+static void process_io_statechg(struct cardem_inst *ci)
+{
+ const bool vcc_active = ci->vcc_active && ci->enabled;
+ if (vcc_active != ci->vcc_active_last) {
+ card_emu_io_statechg(ci->ch, CARD_IO_VCC, vcc_active);
+ /* FIXME do this for real */
+ card_emu_io_statechg(ci->ch, CARD_IO_CLK, vcc_active);
+ ci->vcc_active_last = vcc_active;
+ }
+
+ const bool rst_active = ci->rst_active && ci->enabled;
+ if (rst_active != ci->rst_active_last) {
+ card_emu_io_statechg(ci->ch, CARD_IO_RST, rst_active);
+ ci->rst_active_last = rst_active;
+ }
+}
+
/***********************************************************************
* Core USB / main loop integration
***********************************************************************/
static void usim1_rst_irqhandler(const Pin *pPin)
{
- int active = PIO_Get(&pin_usim1_rst) ? 0 : 1;
- card_emu_io_statechg(cardem_inst[0].ch, CARD_IO_RST, active);
+ cardem_inst[0].rst_active = PIO_Get(&pin_usim1_rst) ? false : true;
}
#ifndef DETECT_VCC_BY_ADC
static void usim1_vcc_irqhandler(const Pin *pPin)
{
- int active = PIO_Get(&pin_usim1_vcc) ? 1 : 0;
- card_emu_io_statechg(cardem_inst[0].ch, CARD_IO_VCC, active);
- /* FIXME do this for real */
- card_emu_io_statechg(cardem_inst[0].ch, CARD_IO_CLK, active);
+ cardem_inst[0].vcc_active = PIO_Get(&pin_usim1_vcc) ? true : false;
}
#endif /* !DETECT_VCC_BY_ADC */
#ifdef CARDEMU_SECOND_UART
static void usim2_rst_irqhandler(const Pin *pPin)
{
- int active = PIO_Get(&pin_usim2_rst) ? 0 : 1;
- card_emu_io_statechg(cardem_inst[1].ch, CARD_IO_RST, active);
+ cardem_inst[1].rst_active = PIO_Get(&pin_usim2_rst) ? false : true;
}
#ifndef DETECT_VCC_BY_ADC
static void usim2_vcc_irqhandler(const Pin *pPin)
{
- int active = PIO_Get(&pin_usim2_vcc) ? 1 : 0;
- card_emu_io_statechg(cardem_inst[1].ch, CARD_IO_VCC, active);
- /* FIXME do this for real */
- card_emu_io_statechg(cardem_inst[1].ch, CARD_IO_CLK, active);
+ cardem_inst[1].vcc_active = PIO_Get(&pin_usim2_vcc) ? true : false;
}
#endif /* !DETECT_VCC_BY_ADC */
#endif /* CARDEMU_SECOND_UART */
@@ -402,6 +591,8 @@ void mode_cardemu_init(void)
TRACE_ENTRY();
+ NVIC_SetPriority(UDP_IRQn, 14);
+
#ifdef PINS_CARDSIM
PIO_Configure(pins_cardsim, PIO_LISTSIZE(pins_cardsim));
#endif
@@ -412,15 +603,29 @@ void mode_cardemu_init(void)
INIT_LLIST_HEAD(&cardem_inst[0].usb_out_queue);
rbuf_reset(&cardem_inst[0].rb);
PIO_Configure(pins_usim1, PIO_LISTSIZE(pins_usim1));
+
+ /* configure USART as ISO-7816 slave (e.g. card) */
ISO7816_Init(&cardem_inst[0].usart_info, CLK_SLAVE);
- NVIC_EnableIRQ(USART1_IRQn);
+ NVIC_SetPriority(FIRST_USART_IRQ, 0);
+ NVIC_EnableIRQ(FIRST_USART_IRQ);
PIO_ConfigureIt(&pin_usim1_rst, usim1_rst_irqhandler);
PIO_EnableIt(&pin_usim1_rst);
+
+ /* obtain current RST state */
+ usim1_rst_irqhandler(&pin_usim1_rst);
#ifndef DETECT_VCC_BY_ADC
PIO_ConfigureIt(&pin_usim1_vcc, usim1_vcc_irqhandler);
PIO_EnableIt(&pin_usim1_vcc);
+
+ /* obtain current VCC state */
+ usim1_vcc_irqhandler(&pin_usim1_vcc);
+#else
+ do {} while (!adc_triggered); /* wait for first ADC reading */
#endif /* DETECT_VCC_BY_ADC */
- cardem_inst[0].ch = card_emu_init(0, 2, 0, SIMTRACE_CARDEM_USB_EP_USIM1_DATAIN, SIMTRACE_CARDEM_USB_EP_USIM1_INT);
+
+ cardem_inst[0].ch = card_emu_init(0, 0, SIMTRACE_CARDEM_USB_EP_USIM1_DATAIN,
+ SIMTRACE_CARDEM_USB_EP_USIM1_INT, cardem_inst[0].vcc_active,
+ cardem_inst[0].rst_active, cardem_inst[0].vcc_active);
sim_switch_use_physical(0, 1);
#ifdef CARDEMU_SECOND_UART
@@ -428,17 +633,26 @@ void mode_cardemu_init(void)
rbuf_reset(&cardem_inst[1].rb);
PIO_Configure(pins_usim2, PIO_LISTSIZE(pins_usim2));
ISO7816_Init(&cardem_inst[1].usart_info, CLK_SLAVE);
+ /* TODO enable timeout */
+ NVIC_SetPriority(USART0_IRQn, 0);
NVIC_EnableIRQ(USART0_IRQn);
PIO_ConfigureIt(&pin_usim2_rst, usim2_rst_irqhandler);
PIO_EnableIt(&pin_usim2_rst);
+ usim2_rst_irqhandler(&pin_usim2_rst); /* obtain current RST state */
#ifndef DETECT_VCC_BY_ADC
PIO_ConfigureIt(&pin_usim2_vcc, usim2_vcc_irqhandler);
PIO_EnableIt(&pin_usim2_vcc);
+ usim2_vcc_irqhandler(&pin_usim2_vcc); /* obtain current VCC state */
+#else
+ do {} while (!adc_triggered); /* wait for first ADC reading */
#endif /* DETECT_VCC_BY_ADC */
- cardem_inst[1].ch = card_emu_init(1, 0, 1, SIMTRACE_CARDEM_USB_EP_USIM2_DATAIN, SIMTRACE_CARDEM_USB_EP_USIM2_INT);
+
+ cardem_inst[1].ch = card_emu_init(1, 1, SIMTRACE_CARDEM_USB_EP_USIM2_DATAIN,
+ SIMTRACE_CARDEM_USB_EP_USIM2_INT, cardem_inst[1].vcc_active,
+ cardem_inst[1].rst_active, cardem_inst[1].vcc_active);
sim_switch_use_physical(1, 1);
+ /* TODO check RST and VCC */
#endif /* CARDEMU_SECOND_UART */
-
}
/* called if config is deactivated */
@@ -452,9 +666,9 @@ void mode_cardemu_exit(void)
PIO_DisableIt(&pin_usim1_rst);
PIO_DisableIt(&pin_usim1_vcc);
- NVIC_DisableIRQ(USART1_IRQn);
- USART_SetTransmitterEnabled(USART1, 0);
- USART_SetReceiverEnabled(USART1, 0);
+ NVIC_DisableIRQ(FIRST_USART_IRQ);
+ USART_SetTransmitterEnabled(FIRST_USART_BASE, 0);
+ USART_SetReceiverEnabled(FIRST_USART_BASE, 0);
#ifdef CARDEMU_SECOND_UART
PIO_DisableIt(&pin_usim2_rst);
@@ -481,12 +695,33 @@ static void dispatch_usb_command_generic(struct msgb *msg, struct cardem_inst *c
usb_buf_free(msg);
}
+static void process_card_insert(struct cardem_inst *ci, bool card_insert)
+{
+ TRACE_INFO("%u: set card_insert to %s\r\n", ci->num, card_insert ? "INSERTED" : "REMOVED");
+
+#ifdef HAVE_BOARD_CARDINSERT
+ board_set_card_insert(ci, card_insert);
+#else
+ if (!ci->pin_insert.pio) {
+ TRACE_INFO("%u: skipping unsupported card_insert to %s\r\n",
+ ci->num, card_insert ? "INSERTED" : "REMOVED");
+ return;
+ }
+
+ if (card_insert)
+ PIO_Set(&ci->pin_insert);
+ else
+ PIO_Clear(&ci->pin_insert);
+#endif
+}
+
/* handle a single USB command as received from the USB host */
static void dispatch_usb_command_cardem(struct msgb *msg, struct cardem_inst *ci)
{
struct simtrace_msg_hdr *hdr;
struct cardemu_usb_msg_set_atr *atr;
struct cardemu_usb_msg_cardinsert *cardins;
+ struct cardemu_usb_msg_config *cfg;
struct llist_head *queue;
hdr = (struct simtrace_msg_hdr *) msg->l1h;
@@ -503,21 +738,16 @@ static void dispatch_usb_command_cardem(struct msgb *msg, struct cardem_inst *ci
break;
case SIMTRACE_MSGT_DT_CEMU_CARDINSERT:
cardins = (struct cardemu_usb_msg_cardinsert *) msg->l2h;
- if (!ci->pin_insert.pio) {
- TRACE_INFO("%u: skipping unsupported card_insert to %s\r\n",
- ci->num, cardins->card_insert ? "INSERTED" : "REMOVED");
- break;
- }
- TRACE_INFO("%u: set card_insert to %s\r\n", ci->num,
- cardins->card_insert ? "INSERTED" : "REMOVED");
- if (cardins->card_insert)
- PIO_Set(&ci->pin_insert);
- else
- PIO_Clear(&ci->pin_insert);
+ process_card_insert(ci, cardins->card_insert);
usb_buf_free(msg);
break;
case SIMTRACE_MSGT_BD_CEMU_STATUS:
- card_emu_report_status(ci->ch);
+ card_emu_report_status(ci->ch, false);
+ usb_buf_free(msg);
+ break;
+ case SIMTRACE_MSGT_BD_CEMU_CONFIG:
+ cfg = (struct cardemu_usb_msg_config *) msg->l2h;
+ card_emu_set_config(ci->ch, cfg, msgb_l2len(msg));
usb_buf_free(msg);
break;
case SIMTRACE_MSGT_BD_CEMU_STATS:
@@ -565,10 +795,8 @@ static int usb_command_sim_select(struct msgb *msg, struct cardem_inst *ci)
if (msgb_l2len(msg) < sizeof(*mss))
return -1;
- if (mss->remote_sim)
- sim_switch_use_physical(ci->num, 0);
- else
- sim_switch_use_physical(ci->num, 1);
+ ci->enabled = mss->remote_sim ? true : false;
+ sim_switch_use_physical(ci->num, !ci->enabled);
return 0;
}
@@ -653,9 +881,10 @@ static void dispatch_received_msg(struct msgb *msg, struct cardem_inst *ci)
}
if (mh->msg_len > msgb_length(msg)) {
- TRACE_ERROR("%u: Unexpected large message (%u bytes)\n",
+ TRACE_ERROR("%u: Unexpected large message (%u bytes)\r\n",
ci->num, mh->msg_len);
usb_buf_free(segm);
+ break;
} else {
uint8_t *cur = msgb_put(segm, mh->msg_len);
segm->l1h = segm->head;
@@ -711,10 +940,15 @@ void mode_cardemu_run(void)
}
uint8_t byte = rbuf_read(&ci->rb);
__enable_irq();
- card_emu_process_rx_byte(ci->ch, byte);
+
+ if (ci->enabled) {
+ card_emu_process_rx_byte(ci->ch, byte);
+ }
//TRACE_ERROR("%uRx%02x\r\n", i, byte);
}
+ process_io_statechg(ci);
+
/* first try to send any pending messages on IRQ */
usb_refill_to_host(ci->ep_int);
diff --git a/firmware/libcommon/source/pseudo_talloc.c b/firmware/libcommon/source/pseudo_talloc.c
index 862fffd..5a4d1ca 100644
--- a/firmware/libcommon/source/pseudo_talloc.c
+++ b/firmware/libcommon/source/pseudo_talloc.c
@@ -9,19 +9,18 @@
* 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 this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*/
#include <stdint.h>
+#include <stdio.h>
#include "talloc.h"
#include "trace.h"
#include "utils.h"
#include <osmocom/core/utils.h>
-#define NUM_RCTX_SMALL 10
+/* TODO: this number should dynamically scale. We need at least one per IN/IRQ endpoint,
+ * as well as at least 3 for every OUT endpoint. Plus some more depending on the application */
+#define NUM_RCTX_SMALL 20
#define RCTX_SIZE_SMALL 348
static uint8_t msgb_data[NUM_RCTX_SMALL][RCTX_SIZE_SMALL] __attribute__((aligned(sizeof(long))));
@@ -63,6 +62,7 @@ int _talloc_free(void *ptr, const char *location)
if (ptr == msgb_data[i]) {
if (!msgb_inuse[i]) {
TRACE_ERROR("%s: double_free by %s\r\n", __func__, location);
+ OSMO_ASSERT(0);
} else {
msgb_inuse[i] = 0;
}
@@ -73,9 +73,24 @@ int _talloc_free(void *ptr, const char *location)
local_irq_restore(x);
TRACE_ERROR("%s: invalid pointer %p from %s\r\n", __func__, ptr, location);
+ OSMO_ASSERT(0);
return -1;
}
+void talloc_report(const void *ptr, FILE *f)
+{
+ unsigned int i;
+
+ fprintf(f, "talloc_report(): ");
+ for (i = 0; i < ARRAY_SIZE(msgb_inuse); i++) {
+ if (msgb_inuse[i])
+ fputc('X', f);
+ else
+ fputc('_', f);
+ }
+ fprintf(f, "\r\n");
+}
+
void talloc_set_name_const(const void *ptr, const char *name)
{
/* do nothing */
diff --git a/firmware/libcommon/source/ringbuffer.c b/firmware/libcommon/source/ringbuffer.c
index 70747a1..d3690be 100644
--- a/firmware/libcommon/source/ringbuffer.c
+++ b/firmware/libcommon/source/ringbuffer.c
@@ -9,10 +9,6 @@
* 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 this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*/
#include "ringbuffer.h"
#include "trace.h"
@@ -32,6 +28,16 @@ void rbuf_reset(volatile ringbuf * rb)
local_irq_restore(state);
}
+void rbuf16_reset(volatile ringbuf16 * rb)
+{
+ unsigned long state;
+
+ local_irq_save(state);
+ rb->ird = 0;
+ rb->iwr = 0;
+ local_irq_restore(state);
+}
+
uint8_t rbuf_read(volatile ringbuf * rb)
{
unsigned long state;
@@ -45,21 +51,49 @@ uint8_t rbuf_read(volatile ringbuf * rb)
return val;
}
+uint16_t rbuf16_read(volatile ringbuf16 * rb)
+{
+ unsigned long state;
+ uint16_t val;
+
+ local_irq_save(state);
+ val = rb->buf[rb->ird];
+ rb->ird = (rb->ird + 1) % RING16_BUFLEN;
+ local_irq_restore(state);
+
+ return val;
+}
+
uint8_t rbuf_peek(volatile ringbuf * rb)
{
return rb->buf[rb->ird];
}
+uint16_t rbuf16_peek(volatile ringbuf16 * rb)
+{
+ return rb->buf[rb->ird];
+}
+
bool rbuf_is_empty(volatile ringbuf * rb)
{
return rb->ird == rb->iwr;
}
+bool rbuf16_is_empty(volatile ringbuf16 * rb)
+{
+ return rb->ird == rb->iwr;
+}
+
static bool __rbuf_is_full(volatile ringbuf * rb)
{
return rb->ird == (rb->iwr + 1) % RING_BUFLEN;
}
+static bool __rbuf16_is_full(volatile ringbuf16 * rb)
+{
+ return rb->ird == (rb->iwr + 1) % RING16_BUFLEN;
+}
+
bool rbuf_is_full(volatile ringbuf * rb)
{
unsigned long state;
@@ -72,6 +106,18 @@ bool rbuf_is_full(volatile ringbuf * rb)
return rc;
}
+bool rbuf16_is_full(volatile ringbuf16 * rb)
+{
+ unsigned long state;
+ bool rc;
+
+ local_irq_save(state);
+ rc = rb->ird == (rb->iwr + 1) % RING16_BUFLEN;
+ local_irq_restore(state);
+
+ return rc;
+}
+
int rbuf_write(volatile ringbuf * rb, uint8_t item)
{
unsigned long state;
@@ -88,4 +134,18 @@ int rbuf_write(volatile ringbuf * rb, uint8_t item)
}
}
+int rbuf16_write(volatile ringbuf16 * rb, uint16_t item)
+{
+ unsigned long state;
+ local_irq_save(state);
+ if (!__rbuf16_is_full(rb)) {
+ rb->buf[rb->iwr] = item;
+ rb->iwr = (rb->iwr + 1) % RING16_BUFLEN;
+ local_irq_restore(state);
+ return 0;
+ } else {
+ local_irq_restore(state);
+ return -1;
+ }
+}
diff --git a/firmware/libcommon/source/simtrace_iso7816.c b/firmware/libcommon/source/simtrace_iso7816.c
index 889ca2d..27677a6 100644
--- a/firmware/libcommon/source/simtrace_iso7816.c
+++ b/firmware/libcommon/source/simtrace_iso7816.c
@@ -71,7 +71,7 @@ void ISR_PhoneRST(const Pin * pPin)
USBD_Write(SIMTRACE_USB_EP_PHONE_INT, "R", 1,
(TransferCallback) & Callback_PhoneRST_ISR,
0)) != USBD_STATUS_SUCCESS) {
- TRACE_ERROR("USB err status: %d (%s)\n", ret, __FUNCTION__);
+ TRACE_ERROR("USB err status: %d (%s)\r\n", ret, __FUNCTION__);
return;
}
@@ -80,7 +80,7 @@ void ISR_PhoneRST(const Pin * pPin)
}
/*
- * char_stat is zero if no error occured.
+ * char_stat is zero if no error occurred.
* Otherwise it is filled with the content of the status register.
*/
void mode_trace_usart1_irq(void)
@@ -109,8 +109,8 @@ void mode_trace_usart1_irq(void)
/* Fill char into buffer */
rbuf_write(&sim_rcv_buf, c);
} else {
- TRACE_DEBUG("e %x st: %x\n", c, stat);
- } /* else: error occured */
+ TRACE_DEBUG("e %x st: %lx\r\n", c, stat);
+ } /* else: error occurred */
char_stat = stat;
}
@@ -125,7 +125,7 @@ void update_fidi(Usart_info *usart, uint8_t fidi)
uint8_t fi = fidi >> 4;
uint8_t di = fidi & 0xf;
- int ratio = compute_fidi_ratio(fi, di);
+ int ratio = iso7816_3_compute_fd_ratio(fi, di);
if (ratio > 0 && ratio < 0x8000) {
/* make sure USART uses new F/D ratio */
diff --git a/firmware/libcommon/source/sniffer.c b/firmware/libcommon/source/sniffer.c
index 33c16d3..948eee8 100644
--- a/firmware/libcommon/source/sniffer.c
+++ b/firmware/libcommon/source/sniffer.c
@@ -1,6 +1,6 @@
/* SIMtrace 2 sniffer mode
*
- * (C) 2016-2017 by Harald Welte <hwelte@hmw-consulting.de>
+ * (C) 2016-2022 by Harald Welte <hwelte@hmw-consulting.de>
* (C) 2018 by sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon@sysmocom.de>
*
* This program is free software; you can redistribute it and/or modify
@@ -12,10 +12,6 @@
* 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 this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*/
/* This code implement the Sniffer mode to sniff the communication between a
* SIM card (or any ISO 7816 smart card) and a phone (or any ISO 7816 card
@@ -115,6 +111,13 @@ enum tpdu_sniff_state {
TPDU_S_SW2, /*!< second status word */
};
+/*! Error flags we use to report USART errors via the ringbuffer */
+#define RBUF16_F_OVERRUN 0x0100
+#define RBUF16_F_FRAMING 0x0200
+#define RBUF16_F_PARITY 0x0400
+#define RBUF16_F_TIMEOUT_WT 0x0800
+#define RBUF16_F_DATA_BYTE 0x8000
+
/*------------------------------------------------------------------------------
* Internal variables
*------------------------------------------------------------------------------*/
@@ -142,50 +145,58 @@ static struct Usart_info sniff_usart = {
.state = USART_RCV,
};
/*! Ring buffer to store sniffer communication data */
-static struct ringbuf sniff_buffer;
+static struct ringbuf16 sniff_buffer;
/* Flags to know is the card status changed (see SIMTRACE_MSGT_DT_SNIFF_CHANGE flags) */
-volatile uint32_t change_flags = 0;
+static volatile uint32_t change_flags = 0;
/* ISO 7816 variables */
/*! ISO 7816-3 state */
-enum iso7816_3_sniff_state iso_state = ISO7816_S_RESET;
-/*! ATR state */
-enum atr_sniff_state atr_state;
-/*! ATR data
- * @remark can be used to check later protocol changes
- */
-uint8_t atr[MAX_ATR_SIZE];
-/*! Current index in the ATR data */
-uint8_t atr_i = 0;
+static enum iso7816_3_sniff_state iso_state = ISO7816_S_RESET;
+
+static struct {
+ /*! ATR state */
+ enum atr_sniff_state state;
+ /*! ATR data
+ * @remark can be used to check later protocol changes
+ */
+ uint8_t atr[MAX_ATR_SIZE];
+ /*! Current index in the ATR data */
+ uint8_t atr_i;
+} g_atr;
+
/*! If convention conversion is needed */
-bool convention_convert = false;
+static bool convention_convert = false;
/*! The supported T protocols */
-uint16_t t_protocol_support = 0;
-/*! PPS state
- * @remark it is shared between request and response since they aren't simultaneous but follow the same procedure
- */
-enum pps_sniff_state pps_state;
-/*! PPS request data
- * @remark can be used to check PPS response
- */
-uint8_t pps_req[MAX_PPS_SIZE];
-/*! PPS response data */
-uint8_t pps_rsp[MAX_PPS_SIZE];
-/*! TPDU state */
-enum tpdu_sniff_state tpdu_state;
-/*! Final TPDU packet
- * @note this is the complete command+response TPDU, including header, data, and status words
- * @remark this does not include the procedure bytes
- */
-uint8_t tpdu_packet[5+256+2];
-/*! Current index in TPDU packet */
-uint16_t tpdu_packet_i = 0;
+static uint16_t t_protocol_support = 0;
+
+static struct {
+ /*! PPS state
+ * @remark it is shared between request and response since they aren't simultaneous but
+ * follow the same procedure */
+ enum pps_sniff_state state;
+ /*! PPS request data
+ * @remark can be used to check PPS response */
+ uint8_t req[MAX_PPS_SIZE];
+ /*! PPS response data */
+ uint8_t rsp[MAX_PPS_SIZE];
+} g_pps;
+
+static struct {
+ /*! TPDU state */
+ enum tpdu_sniff_state state;
+ /*! Final TPDU packet
+ * @note this is the complete command+response TPDU, including header, data, and status words
+ * @remark this does not include the procedure bytes */
+ uint8_t packet[5+256+2];
+ /*! Current index in TPDU packet */
+ uint16_t packet_i;
+} g_tpdu;
/*! Waiting Time (WT)
* @note defined in ISO/IEC 7816-3:2006(E) section 8.1 and 10.2
*/
-uint32_t wt = 9600;
+static uint32_t g_wt = 9600;
/*------------------------------------------------------------------------------
* Internal functions
@@ -200,10 +211,11 @@ static const uint8_t convention_convert_lut[256] = { 0xff, 0x7f, 0xbf, 0x3f, 0xd
/*! Update Waiting Time (WT)
* @param[in] wi Waiting Integer (0 if unchanged)
* @param[in] d Baud Rate divider (0 if unchanged)
+ * @param[in] cause String describing the source of the change
* @note set wt to be used by the receiver timeout
* @note defined in ISO/IEC 7816-3:2006(E) section 8.1 and 10.2
*/
-static void update_wt(uint8_t wi, uint8_t d)
+static void update_wt(uint8_t wi, uint8_t d, const char *cause)
{
static uint8_t wt_wi = 10; /* Waiting time Integer (WI), used to calculate the Waiting Time (WT) */
static uint8_t wt_d = 1; /* baud rate adjustment integer (the actual value, not the table index) */
@@ -214,8 +226,8 @@ static void update_wt(uint8_t wi, uint8_t d)
if (0 != d) {
wt_d = d;
}
- wt = wt_wi*960UL*wt_d;
- TRACE_INFO("WT updated to %lu\n\r", wt);
+ g_wt = wt_wi * 960UL * wt_d;
+ TRACE_INFO("WT updated (wi=%u, d=%u, cause=%s) to %lu ETU\n\r", wi, d, cause, g_wt);
}
/*! Allocate USB buffer and push + initialize simtrace_msg_hdr
@@ -259,6 +271,15 @@ void usb_msg_upd_len_and_submit(struct msgb *usb_msg)
usb_buf_submit(usb_msg);
}
+/*! Update the TPDU state
+ * @param[in] tpdu_state_new new TPDU state to update to
+ */
+static void change_tpdu_state(enum tpdu_sniff_state tpdu_state_new)
+{
+ //TRACE_ERROR("TPDU state %u->%u\n\r", g_tpdu.state, tpdu_state_new);
+ g_tpdu.state = tpdu_state_new;
+}
+
/*! Update the ISO 7816-3 state
* @param[in] iso_state_new new ISO 7816-3 state to update to
*/
@@ -274,51 +295,40 @@ static void change_state(enum iso7816_3_sniff_state iso_state_new)
switch (iso_state_new) {
case ISO7816_S_RESET:
update_fidi(&sniff_usart, 0x11); /* reset baud rate to default Di/Fi values */
- update_wt(10, 1); /* reset WT time-out */
+ update_wt(10, 1, "RESET"); /* reset WT time-out */
break;
case ISO7816_S_WAIT_ATR:
- rbuf_reset(&sniff_buffer); /* reset buffer for new communication */
+ rbuf16_reset(&sniff_buffer); /* reset buffer for new communication */
break;
case ISO7816_S_IN_ATR:
- atr_i = 0;
+ g_atr.atr_i = 0;
convention_convert = false;
t_protocol_support = 0;
- atr_state = ATR_S_WAIT_TS;
+ g_atr.state = ATR_S_WAIT_TS;
break;
case ISO7816_S_IN_PPS_REQ:
case ISO7816_S_IN_PPS_RSP:
- pps_state = PPS_S_WAIT_PPSS;
+ g_pps.state = PPS_S_WAIT_PPSS;
break;
case ISO7816_S_WAIT_TPDU:
- tpdu_state = TPDU_S_CLA;
- tpdu_packet_i = 0;
+ change_tpdu_state(TPDU_S_CLA);
+ g_tpdu.packet_i = 0;
break;
default:
break;
}
+ TRACE_INFO("ISO 7816-3 state %u->%u\n\r", iso_state, iso_state_new);
+
/* save new state */
iso_state = iso_state_new;
- TRACE_INFO("Changed to ISO 7816-3 state %u\n\r", iso_state);
}
const struct value_string data_flags[] = {
- {
- .value = SNIFF_DATA_FLAG_ERROR_INCOMPLETE,
- .str = "incomplete",
- },
- {
- .value = SNIFF_DATA_FLAG_ERROR_MALFORMED,
- .str = "malformed",
- },
- {
- .value = SNIFF_DATA_FLAG_ERROR_CHECKSUM,
- .str = "checksum error",
- },
- {
- .value = 0,
- .str = NULL,
- },
+ { SNIFF_DATA_FLAG_ERROR_INCOMPLETE, "incomplete" },
+ { SNIFF_DATA_FLAG_ERROR_MALFORMED, "malformed" },
+ { SNIFF_DATA_FLAG_ERROR_CHECKSUM, "checksum error" },
+ { 0, NULL }
};
static void print_flags(const struct value_string* flag_meanings, uint32_t nb_flags, uint32_t flags) {
@@ -396,13 +406,13 @@ static void usb_send_atr(uint32_t flags)
TRACE_WARNING("Can't print ATR in ISO 7816-3 state %u\n\r", iso_state);
return;
}
- if (atr_i >= ARRAY_SIZE(atr)) {
+ if (g_atr.atr_i >= ARRAY_SIZE(g_atr.atr)) {
TRACE_ERROR("ATR buffer overflow\n\r");
return;
}
/* Send ATR over USB */
- usb_send_data(SIMTRACE_MSGT_SNIFF_ATR, atr, atr_i, flags);
+ usb_send_data(SIMTRACE_MSGT_SNIFF_ATR, g_atr.atr, g_atr.atr_i, flags);
}
/*! Process ATR byte
@@ -420,16 +430,16 @@ static void process_byte_atr(uint8_t byte)
TRACE_ERROR("Processing ATR data in wrong ISO 7816-3 state %u\n\r", iso_state);
return;
}
- if (atr_i >= ARRAY_SIZE(atr)) {
+ if (g_atr.atr_i >= ARRAY_SIZE(g_atr.atr)) {
TRACE_ERROR("ATR data overflow\n\r");
return;
}
/* save data for use by other functions */
- atr[atr_i++] = byte;
+ g_atr.atr[g_atr.atr_i++] = byte;
/* handle ATR byte depending on current state */
- switch (atr_state) {
+ switch (g_atr.state) {
case ATR_S_WAIT_TS: /* see ISO/IEC 7816-3:2006 section 8.1 */
flags = 0;
switch (byte) {
@@ -438,7 +448,7 @@ static void process_byte_atr(uint8_t byte)
convention_convert = !convention_convert;
case 0x3b: /* direct convention used and correctly decoded */
case 0x3f: /* inverse convention used and correctly decoded */
- atr_state = ATR_S_WAIT_T0; /* wait for format byte */
+ g_atr.state = ATR_S_WAIT_T0; /* wait for format byte */
break;
default:
TRACE_WARNING("Invalid TS received\n\r");
@@ -451,41 +461,41 @@ static void process_byte_atr(uint8_t byte)
break;
case ATR_S_WAIT_T0: /* see ISO/IEC 7816-3:2006 section 8.2.2 */
case ATR_S_WAIT_TD: /* see ISO/IEC 7816-3:2006 section 8.2.3 */
- if (ATR_S_WAIT_T0 == atr_state) {
+ if (ATR_S_WAIT_T0 == g_atr.state) {
atr_hist_len = (byte & 0x0f); /* save the number of historical bytes */
- } else if (ATR_S_WAIT_TD == atr_state) {
+ } else if (ATR_S_WAIT_TD == g_atr.state) {
t_protocol_support |= (1<<(byte & 0x0f)); /* remember supported protocol to know if TCK will be present */
}
y = (byte & 0xf0); /* remember upcoming interface bytes */
i++; /* next interface byte sub-group is coming */
if (y & 0x10) {
- atr_state = ATR_S_WAIT_TA; /* wait for interface byte TA */
+ g_atr.state = ATR_S_WAIT_TA; /* wait for interface byte TA */
break;
}
case ATR_S_WAIT_TA: /* see ISO/IEC 7816-3:2006 section 8.2.3 */
if (y & 0x20) {
- atr_state = ATR_S_WAIT_TB; /* wait for interface byte TB */
+ g_atr.state = ATR_S_WAIT_TB; /* wait for interface byte TB */
break;
}
case ATR_S_WAIT_TB: /* see ISO/IEC 7816-3:2006 section 8.2.3 */
if (y & 0x40) {
- atr_state = ATR_S_WAIT_TC; /* wait for interface byte TC */
+ g_atr.state = ATR_S_WAIT_TC; /* wait for interface byte TC */
break;
}
case ATR_S_WAIT_TC: /* see ISO/IEC 7816-3:2006 section 8.2.3 */
/* retrieve WI encoded in TC2*/
- if (ATR_S_WAIT_TC==atr_state && 2==i) {
+ if (ATR_S_WAIT_TC == g_atr.state && 2 == i) {
if (0 == byte) {
- update_wt(10, 0);
+ update_wt(10, 0, "TC2=0");
} else {
- update_wt(byte, 0);
+ update_wt(byte, 0, "TC2");
}
}
if (y & 0x80) {
- atr_state = ATR_S_WAIT_TD; /* wait for interface byte TD */
+ g_atr.state = ATR_S_WAIT_TD; /* wait for interface byte TD */
break;
} else if (atr_hist_len) {
- atr_state = ATR_S_WAIT_HIST; /* wait for historical bytes */
+ g_atr.state = ATR_S_WAIT_HIST; /* wait for historical bytes */
break;
}
case ATR_S_WAIT_HIST: /* see ISO/IEC 7816-3:2006 section 8.2.4 */
@@ -494,7 +504,7 @@ static void process_byte_atr(uint8_t byte)
}
if (0 == atr_hist_len) {
if (t_protocol_support > 1) {
- atr_state = ATR_S_WAIT_TCK; /* wait for check bytes */
+ g_atr.state = ATR_S_WAIT_TCK; /* wait for check bytes */
break;
}
} else {
@@ -502,11 +512,11 @@ static void process_byte_atr(uint8_t byte)
}
case ATR_S_WAIT_TCK: /* see ISO/IEC 7816-3:2006 section 8.2.5 */
/* verify checksum if present */
- if (ATR_S_WAIT_TCK == atr_state) {
+ if (ATR_S_WAIT_TCK == g_atr.state) {
uint8_t ui;
uint8_t checksum = 0;
- for (ui = 1; ui < atr_i; ui++) {
- checksum ^= atr[ui];
+ for (ui = 1; ui < g_atr.atr_i; ui++) {
+ checksum ^= g_atr.atr[ui];
}
if (checksum) {
flags |= SNIFF_DATA_FLAG_ERROR_CHECKSUM;
@@ -519,7 +529,7 @@ static void process_byte_atr(uint8_t byte)
change_state(ISO7816_S_WAIT_TPDU); /* go to next state */
break;
default:
- TRACE_INFO("Unknown ATR state %u\n\r", atr_state);
+ TRACE_INFO("Unknown ATR state %u\n\r", g_atr.state);
}
}
@@ -533,9 +543,9 @@ static void usb_send_pps(uint32_t flags)
/* Sanity check */
if (ISO7816_S_IN_PPS_REQ == iso_state) {
- pps_cur = pps_req;
+ pps_cur = g_pps.req;
} else if (ISO7816_S_IN_PPS_RSP == iso_state) {
- pps_cur = pps_rsp;
+ pps_cur = g_pps.rsp;
} else {
TRACE_ERROR("Can't print PPS in ISO 7816-3 state %u\n\r", iso_state);
return;
@@ -544,22 +554,22 @@ static void usb_send_pps(uint32_t flags)
/* Get only relevant data */
uint8_t pps[6];
uint8_t pps_i = 0;
- if (pps_state > PPS_S_WAIT_PPSS) {
+ if (g_pps.state > PPS_S_WAIT_PPSS) {
pps[pps_i++] = pps_cur[0];
}
- if (pps_state > PPS_S_WAIT_PPS0) {
+ if (g_pps.state > PPS_S_WAIT_PPS0) {
pps[pps_i++] = pps_cur[1];
}
- if (pps_state > PPS_S_WAIT_PPS1 && pps_cur[1] & 0x10) {
+ if (g_pps.state > PPS_S_WAIT_PPS1 && pps_cur[1] & 0x10) {
pps[pps_i++] = pps_cur[2];
}
- if (pps_state > PPS_S_WAIT_PPS2 && pps_cur[1] & 0x20) {
+ if (g_pps.state > PPS_S_WAIT_PPS2 && pps_cur[1] & 0x20) {
pps[pps_i++] = pps_cur[3];
}
- if (pps_state > PPS_S_WAIT_PPS3 && pps_cur[1] & 0x40) {
+ if (g_pps.state > PPS_S_WAIT_PPS3 && pps_cur[1] & 0x40) {
pps[pps_i++] = pps_cur[4];
}
- if (pps_state > PPS_S_WAIT_PCK) {
+ if (g_pps.state > PPS_S_WAIT_PCK) {
pps[pps_i++] = pps_cur[5];
}
@@ -589,21 +599,21 @@ static void process_byte_pps(uint8_t byte)
/* sanity check */
if (ISO7816_S_IN_PPS_REQ == iso_state) {
- pps_cur = pps_req;
+ pps_cur = g_pps.req;
} else if (ISO7816_S_IN_PPS_RSP == iso_state) {
- pps_cur = pps_rsp;
+ pps_cur = g_pps.rsp;
} else {
TRACE_ERROR("Processing PPS data in wrong ISO 7816-3 state %u\n\r", iso_state);
return;
}
/* handle PPS byte depending on current state */
- switch (pps_state) { /* see ISO/IEC 7816-3:2006 section 9.2 */
+ switch (g_pps.state) { /* see ISO/IEC 7816-3:2006 section 9.2 */
case PPS_S_WAIT_PPSS: /*!< initial byte */
flags = 0;
- if (0xff) {
+ if (byte == 0xff) {
pps_cur[0] = byte;
- pps_state = PPS_S_WAIT_PPS0; /* go to next state */
+ g_pps.state = PPS_S_WAIT_PPS0; /* go to next state */
} else {
TRACE_INFO("Invalid PPSS received\n\r");
led_blink(LED_RED, BLINK_2F_O); /* indicate error to user */
@@ -614,24 +624,24 @@ static void process_byte_pps(uint8_t byte)
case PPS_S_WAIT_PPS0: /*!< format byte */
pps_cur[1] = byte;
if (pps_cur[1] & 0x10) {
- pps_state = PPS_S_WAIT_PPS1; /* go to next state */
+ g_pps.state = PPS_S_WAIT_PPS1; /* go to next state */
break;
}
case PPS_S_WAIT_PPS1: /*!< first parameter byte */
pps_cur[2] = byte; /* not always right but doesn't affect the process */
if (pps_cur[1] & 0x20) {
- pps_state = PPS_S_WAIT_PPS2; /* go to next state */
+ g_pps.state = PPS_S_WAIT_PPS2; /* go to next state */
break;
}
case PPS_S_WAIT_PPS2: /*!< second parameter byte */
pps_cur[3] = byte; /* not always right but doesn't affect the process */
if (pps_cur[1] & 0x40) {
- pps_state = PPS_S_WAIT_PPS3; /* go to next state */
+ g_pps.state = PPS_S_WAIT_PPS3; /* go to next state */
break;
}
case PPS_S_WAIT_PPS3: /*!< third parameter byte */
pps_cur[4] = byte; /* not always right but doesn't affect the process */
- pps_state = PPS_S_WAIT_PCK; /* go to next state */
+ g_pps.state = PPS_S_WAIT_PCK; /* go to next state */
break;
case PPS_S_WAIT_PCK: /*!< check byte */
pps_cur[5] = byte; /* not always right but doesn't affect the process */
@@ -652,7 +662,7 @@ static void process_byte_pps(uint8_t byte)
if (check) {
flags |= SNIFF_DATA_FLAG_ERROR_CHECKSUM;
}
- pps_state = PPS_S_WAIT_END;
+ g_pps.state = PPS_S_WAIT_END;
usb_send_pps(flags); /* send PPS to host software using USB */
if (ISO7816_S_IN_PPS_REQ == iso_state) {
if (0 == check) { /* checksum is valid */
@@ -670,9 +680,10 @@ static void process_byte_pps(uint8_t byte)
fn = 1;
dn = 1;
}
- TRACE_INFO("PPS negotiation successful: Fn=%u Dn=%u\n\r", fi_table[fn], di_table[dn]);
+ TRACE_INFO("PPS negotiation successful: Fn=%u Dn=%u\n\r",
+ iso7816_3_fi_table[fn], iso7816_3_di_table[dn]);
update_fidi(&sniff_usart, pps_cur[2]);
- update_wt(0, di_table[dn]);
+ update_wt(0, iso7816_3_di_table[dn], "PPS");
usb_send_fidi(pps_cur[2]); /* send Fi/Di change notification to host software over USB */
} else { /* checksum is invalid */
TRACE_INFO("PPS negotiation failed\n\r");
@@ -681,10 +692,10 @@ static void process_byte_pps(uint8_t byte)
}
break;
case PPS_S_WAIT_END:
- TRACE_WARNING("Unexpected PPS received %u\n\r", pps_state);
+ TRACE_WARNING("Unexpected PPS received %u\n\r", g_pps.state);
break;
default:
- TRACE_WARNING("Unknown PPS state %u\n\r", pps_state);
+ TRACE_WARNING("Unknown PPS state %u\n\r", g_pps.state);
break;
}
}
@@ -702,7 +713,7 @@ static void usb_send_tpdu(uint32_t flags)
}
/* Send ATR over USB */
- usb_send_data(SIMTRACE_MSGT_SNIFF_TPDU, tpdu_packet, tpdu_packet_i, flags);
+ usb_send_data(SIMTRACE_MSGT_SNIFF_TPDU, g_tpdu.packet, g_tpdu.packet_i, flags);
}
static void process_byte_tpdu(uint8_t byte)
@@ -712,13 +723,13 @@ static void process_byte_tpdu(uint8_t byte)
TRACE_ERROR("Processing TPDU data in wrong ISO 7816-3 state %u\n\r", iso_state);
return;
}
- if (tpdu_packet_i >= ARRAY_SIZE(tpdu_packet)) {
+ if (g_tpdu.packet_i >= ARRAY_SIZE(g_tpdu.packet)) {
TRACE_ERROR("TPDU data overflow\n\r");
return;
}
/* handle TPDU byte depending on current state */
- switch (tpdu_state) {
+ switch (g_tpdu.state) {
case TPDU_S_CLA:
if (0xff == byte) {
TRACE_WARNING("0xff is not a valid class byte\n\r");
@@ -727,51 +738,51 @@ static void process_byte_tpdu(uint8_t byte)
change_state(ISO7816_S_WAIT_TPDU); /* go back to TPDU state */
return;
}
- tpdu_packet_i = 0;
- tpdu_packet[tpdu_packet_i++] = byte;
- tpdu_state = TPDU_S_INS;
+ g_tpdu.packet_i = 0;
+ g_tpdu.packet[g_tpdu.packet_i++] = byte;
+ change_tpdu_state(TPDU_S_INS);
break;
case TPDU_S_INS:
if ((0x60 == (byte & 0xf0)) || (0x90 == (byte & 0xf0))) {
- TRACE_WARNING("invalid CLA 0x%02x\n\r", byte);
+ TRACE_WARNING("invalid INS 0x%02x\n\r", byte);
led_blink(LED_RED, BLINK_2F_O); /* indicate error to user */
usb_send_tpdu(SNIFF_DATA_FLAG_ERROR_MALFORMED); /* send ATR to host software using USB */
change_state(ISO7816_S_WAIT_TPDU); /* go back to TPDU state */
return;
}
- tpdu_packet_i = 1;
- tpdu_packet[tpdu_packet_i++] = byte;
- tpdu_state = TPDU_S_P1;
+ g_tpdu.packet_i = 1;
+ g_tpdu.packet[g_tpdu.packet_i++] = byte;
+ change_tpdu_state(TPDU_S_P1);
break;
case TPDU_S_P1:
- tpdu_packet_i = 2;
- tpdu_packet[tpdu_packet_i++] = byte;
- tpdu_state = TPDU_S_P2;
+ g_tpdu.packet_i = 2;
+ g_tpdu.packet[g_tpdu.packet_i++] = byte;
+ change_tpdu_state(TPDU_S_P2);
break;
case TPDU_S_P2:
- tpdu_packet_i = 3;
- tpdu_packet[tpdu_packet_i++] = byte;
- tpdu_state = TPDU_S_P3;
+ g_tpdu.packet_i = 3;
+ g_tpdu.packet[g_tpdu.packet_i++] = byte;
+ change_tpdu_state(TPDU_S_P3);
break;
case TPDU_S_P3:
- tpdu_packet_i = 4;
- tpdu_packet[tpdu_packet_i++] = byte;
- tpdu_state = TPDU_S_PROCEDURE;
+ g_tpdu.packet_i = 4;
+ g_tpdu.packet[g_tpdu.packet_i++] = byte;
+ change_tpdu_state(TPDU_S_PROCEDURE);
break;
case TPDU_S_PROCEDURE:
if (0x60 == byte) { /* wait for next procedure byte */
break;
- } else if (tpdu_packet[1] == byte) { /* get all remaining data bytes */
- tpdu_state = TPDU_S_DATA_REMAINING;
+ } else if (g_tpdu.packet[1] == byte) { /* get all remaining data bytes */
+ change_tpdu_state(TPDU_S_DATA_REMAINING);
break;
- } else if ((~tpdu_packet[1]) == byte) { /* get single data byte */
- tpdu_state = TPDU_S_DATA_SINGLE;
+ } else if ((~g_tpdu.packet[1]) == byte) { /* get single data byte */
+ change_tpdu_state(TPDU_S_DATA_SINGLE);
break;
}
case TPDU_S_SW1:
if ((0x60 == (byte & 0xf0)) || (0x90 == (byte & 0xf0))) { /* this procedure byte is SW1 */
- tpdu_packet[tpdu_packet_i++] = byte;
- tpdu_state = TPDU_S_SW2;
+ g_tpdu.packet[g_tpdu.packet_i++] = byte;
+ change_tpdu_state(TPDU_S_SW2);
} else {
TRACE_WARNING("invalid SW1 0x%02x\n\r", byte);
led_blink(LED_RED, BLINK_2F_O); /* indicate error to user */
@@ -781,28 +792,28 @@ static void process_byte_tpdu(uint8_t byte)
}
break;
case TPDU_S_SW2:
- tpdu_packet[tpdu_packet_i++] = byte;
+ g_tpdu.packet[g_tpdu.packet_i++] = byte;
usb_send_tpdu(0); /* send TPDU to host software using USB */
change_state(ISO7816_S_WAIT_TPDU); /* this is the end of the TPDU */
break;
case TPDU_S_DATA_SINGLE:
case TPDU_S_DATA_REMAINING:
- tpdu_packet[tpdu_packet_i++] = byte;
- if (0 == tpdu_packet[4]) {
- if (5+256 <= tpdu_packet_i) {
- tpdu_state = TPDU_S_PROCEDURE;
+ g_tpdu.packet[g_tpdu.packet_i++] = byte;
+ if (0 == g_tpdu.packet[4]) {
+ if (5+256 <= g_tpdu.packet_i) {
+ change_tpdu_state(TPDU_S_PROCEDURE);
}
} else {
- if (5+tpdu_packet[4] <= tpdu_packet_i) {
- tpdu_state = TPDU_S_PROCEDURE;
+ if (5+g_tpdu.packet[4] <= g_tpdu.packet_i) {
+ change_tpdu_state(TPDU_S_PROCEDURE);
}
}
- if (TPDU_S_DATA_SINGLE == tpdu_state) {
- tpdu_state = TPDU_S_PROCEDURE;
+ if (TPDU_S_DATA_SINGLE == g_tpdu.state) {
+ change_tpdu_state(TPDU_S_PROCEDURE);
}
break;
default:
- TRACE_ERROR("unhandled TPDU state %u\n\r", tpdu_state);
+ TRACE_ERROR("unhandled TPDU state %u\n\r", g_tpdu.state);
}
}
@@ -814,37 +825,37 @@ void Sniffer_usart_isr(void)
/* Read channel status register */
uint32_t csr = sniff_usart.base->US_CSR;
- /* Verify if there was an error */
- if (csr & US_CSR_OVRE) {
- TRACE_WARNING("USART overrun error\n\r");
- sniff_usart.base->US_CR |= US_CR_RSTSTA;
- }
- if (csr & US_CSR_FRAME) {
- TRACE_WARNING("USART framing error\n\r");
- sniff_usart.base->US_CR |= US_CR_RSTSTA;
- }
+
+ uint16_t byte = 0;
/* Verify if character has been received */
if (csr & US_CSR_RXRDY) {
/* Read communication data byte between phone and SIM */
- uint8_t byte = sniff_usart.base->US_RHR;
+ byte = RBUF16_F_DATA_BYTE | (sniff_usart.base->US_RHR & 0xff);
/* Reset WT timer */
- wt_remaining = wt;
- /* Store sniffed data into buffer (also clear interrupt */
- if (rbuf_is_full(&sniff_buffer)) {
- TRACE_ERROR("USART buffer full\n\r");
- } else {
- rbuf_write(&sniff_buffer, byte);
- }
+ wt_remaining = g_wt;
}
+ /* Verify if there was an error */
+ if (csr & US_CSR_OVRE)
+ byte |= RBUF16_F_OVERRUN;
+ if (csr & US_CSR_FRAME)
+ byte |= RBUF16_F_FRAMING;
+ if (csr & US_CSR_PARE)
+ byte |= RBUF16_F_PARITY;
+
+ if (csr & (US_CSR_OVRE|US_CSR_FRAME|US_CSR_PARE))
+ sniff_usart.base->US_CR |= US_CR_RSTSTA;
+
/* Verify it WT timeout occurred, to detect unresponsive card */
if (csr & US_CSR_TIMEOUT) {
if (wt_remaining <= (sniff_usart.base->US_RTOR & 0xffff)) {
+ /* ensure the timeout is enqueued in the ring-buffer */
+ byte |= RBUF16_F_TIMEOUT_WT;
/* Just set the flag and let the main loop handle it */
change_flags |= SNIFF_CHANGE_FLAG_TIMEOUT_WT;
/* Reset timeout value */
- wt_remaining = wt;
+ wt_remaining = g_wt;
} else {
wt_remaining -= (sniff_usart.base->US_RTOR & 0xffff); /* be sure to subtract the actual timeout since the new might not have been set and reloaded yet */
}
@@ -860,6 +871,12 @@ void Sniffer_usart_isr(void)
sniff_usart.base->US_CR |= US_CR_RETTO;
}
}
+
+ /* Store sniffed data (or error flags, or both) into buffer */
+ if (byte) {
+ if (rbuf16_write(&sniff_buffer, byte) != 0)
+ TRACE_ERROR("USART buffer full\n\r");
+ }
}
/** PIO interrupt service routine to checks if the card reset line has changed
@@ -901,6 +918,8 @@ void Sniffer_usart0_irq(void)
* Initialization routine
*-----------------------------------------------------------------------------*/
+#define SNIFFER_IER (US_IER_RXRDY | US_IER_TIMEOUT | US_IER_OVRE | US_IER_FRAME | US_IER_PARE)
+
/* Called during USB enumeration after device is enumerated by host */
void Sniffer_configure(void)
{
@@ -912,7 +931,7 @@ void Sniffer_exit(void)
{
TRACE_INFO("Sniffer exit\n\r");
/* Disable USART */
- USART_DisableIt(sniff_usart.base, US_IER_RXRDY);
+ USART_DisableIt(sniff_usart.base, SNIFFER_IER);
/* NOTE: don't forget to set the IRQ according to the USART peripheral used */
NVIC_DisableIRQ(IRQ_USART_SIM);
USART_SetReceiverEnabled(sniff_usart.base, 0);
@@ -940,15 +959,15 @@ void Sniffer_init(void)
PIO_EnableIt(&pin_rst);
/* Clear ring buffer containing the sniffed data */
- rbuf_reset(&sniff_buffer);
+ rbuf16_reset(&sniff_buffer);
/* Configure USART to as ISO-7816 slave communication to sniff communication */
ISO7816_Init(&sniff_usart, CLK_SLAVE);
/* Only receive data when sniffing */
USART_SetReceiverEnabled(sniff_usart.base, 1);
/* Enable Receiver time-out to detect waiting time (WT) time-out (e.g. unresponsive cards) */
- sniff_usart.base->US_RTOR = wt;
+ sniff_usart.base->US_RTOR = g_wt;
/* Enable interrupt to indicate when data has been received or timeout occurred */
- USART_EnableIt(sniff_usart.base, US_IER_RXRDY | US_IER_TIMEOUT);
+ USART_EnableIt(sniff_usart.base, SNIFFER_IER);
/* Set USB priority lower than USART to not miss sniffing data (both at 0 per default) */
if (NVIC_GetPriority(IRQ_USART_SIM) >= NVIC_GetPriority(UDP_IRQn)) {
NVIC_SetPriority(UDP_IRQn, NVIC_GetPriority(IRQ_USART_SIM) + 2);
@@ -1006,101 +1025,114 @@ void Sniffer_run(void)
* is remaining
*/
/* Handle sniffed data */
- if (!rbuf_is_empty(&sniff_buffer)) { /* use if instead of while to let the main loop restart the watchdog */
- uint8_t byte = rbuf_read(&sniff_buffer);
- /* Convert convention if required */
- if (convention_convert) {
- byte = convention_convert_lut[byte];
- }
- //TRACE_ERROR_WP(">%02x", byte);
- switch (iso_state) { /* Handle byte depending on state */
- case ISO7816_S_RESET: /* During reset we shouldn't receive any data */
- break;
- case ISO7816_S_WAIT_ATR: /* After a reset we expect the ATR */
- change_state(ISO7816_S_IN_ATR); /* go to next state */
- case ISO7816_S_IN_ATR: /* More ATR data incoming */
- process_byte_atr(byte);
- break;
- case ISO7816_S_WAIT_TPDU: /* After the ATR we expect TPDU or PPS data */
- case ISO7816_S_WAIT_PPS_RSP:
- if (0xff == byte) {
- if (ISO7816_S_WAIT_PPS_RSP == iso_state) {
- change_state(ISO7816_S_IN_PPS_RSP); /* Go to PPS state */
- } else {
- change_state(ISO7816_S_IN_PPS_REQ); /* Go to PPS state */
+ if (!rbuf16_is_empty(&sniff_buffer)) { /* use if instead of while to let the main loop restart the watchdog */
+ uint16_t entry = rbuf16_read(&sniff_buffer);
+
+ if (entry & RBUF16_F_DATA_BYTE) {
+ uint8_t byte = entry & 0xff;
+ /* Convert convention if required */
+ if (convention_convert) {
+ byte = convention_convert_lut[byte];
+ }
+
+ //TRACE_ERROR_WP(">%02x", byte);
+ switch (iso_state) { /* Handle byte depending on state */
+ case ISO7816_S_RESET: /* During reset we shouldn't receive any data */
+ break;
+ case ISO7816_S_WAIT_ATR: /* After a reset we expect the ATR */
+ change_state(ISO7816_S_IN_ATR); /* go to next state */
+ case ISO7816_S_IN_ATR: /* More ATR data incoming */
+ process_byte_atr(byte);
+ break;
+ case ISO7816_S_WAIT_TPDU: /* After the ATR we expect TPDU or PPS data */
+ case ISO7816_S_WAIT_PPS_RSP:
+ if (0xff == byte) {
+ if (ISO7816_S_WAIT_PPS_RSP == iso_state) {
+ change_state(ISO7816_S_IN_PPS_RSP); /* Go to PPS state */
+ } else {
+ change_state(ISO7816_S_IN_PPS_REQ); /* Go to PPS state */
+ }
+ process_byte_pps(byte);
+ break;
+ }
+ case ISO7816_S_IN_TPDU: /* More TPDU data incoming */
+ if (ISO7816_S_WAIT_TPDU == iso_state) {
+ change_state(ISO7816_S_IN_TPDU);
}
+ process_byte_tpdu(byte);
+ break;
+ case ISO7816_S_IN_PPS_REQ:
+ case ISO7816_S_IN_PPS_RSP:
process_byte_pps(byte);
break;
+ default:
+ TRACE_ERROR("Data received in unknown state %u\n\r", iso_state);
}
- case ISO7816_S_IN_TPDU: /* More TPDU data incoming */
- if (ISO7816_S_WAIT_TPDU == iso_state) {
- change_state(ISO7816_S_IN_TPDU);
- }
- process_byte_tpdu(byte);
- break;
- case ISO7816_S_IN_PPS_REQ:
- case ISO7816_S_IN_PPS_RSP:
- process_byte_pps(byte);
- break;
- default:
- TRACE_ERROR("Data received in unknown state %u\n\r", iso_state);
}
- }
- /* Handle flags */
- if (change_flags) { /* WARNING this is not synced with the data buffer handling */
- if (change_flags & SNIFF_CHANGE_FLAG_RESET_ASSERT) {
+ /* Use timeout to detect interrupted data transmission */
+ if (entry & RBUF16_F_TIMEOUT_WT) {
+ TRACE_ERROR("USART TIMEOUT Error\n\r");
switch (iso_state) {
case ISO7816_S_IN_ATR:
led_blink(LED_RED, BLINK_2F_O); /* indicate error to user */
usb_send_atr(SNIFF_DATA_FLAG_ERROR_INCOMPLETE); /* send incomplete ATR to host software using USB */
+ change_state(ISO7816_S_WAIT_ATR);
break;
case ISO7816_S_IN_TPDU:
led_blink(LED_RED, BLINK_2F_O); /* indicate error to user */
usb_send_tpdu(SNIFF_DATA_FLAG_ERROR_INCOMPLETE); /* send incomplete PPS to host software using USB */
+ change_state(ISO7816_S_WAIT_TPDU);
break;
case ISO7816_S_IN_PPS_REQ:
case ISO7816_S_IN_PPS_RSP:
led_blink(LED_RED, BLINK_2F_O); /* indicate error to user */
usb_send_pps(SNIFF_DATA_FLAG_ERROR_INCOMPLETE); /* send incomplete TPDU to host software using USB */
+ change_state(ISO7816_S_WAIT_TPDU);
break;
default:
break;
}
- if (ISO7816_S_RESET != iso_state) {
- change_state(ISO7816_S_RESET);
- printf("reset asserted\n\r");
- }
}
- if (change_flags & SNIFF_CHANGE_FLAG_RESET_DEASSERT) {
- if (ISO7816_S_WAIT_ATR != iso_state) {
- change_state(ISO7816_S_WAIT_ATR);
- printf("reset de-asserted\n\r");
- }
- }
- if (change_flags & SNIFF_CHANGE_FLAG_TIMEOUT_WT) {
- /* Use timeout to detect interrupted data transmission */
+
+ if (entry & RBUF16_F_PARITY)
+ TRACE_ERROR("USART PARITY Error\r\n");
+ if (entry & RBUF16_F_FRAMING)
+ TRACE_ERROR("USART FRAMING Error\r\n");
+ if (entry & RBUF16_F_OVERRUN)
+ TRACE_ERROR("USART OVERRUN Error\r\n");
+ }
+
+ /* Handle flags */
+ if (change_flags) { /* WARNING this is not synced with the data buffer handling */
+ if (change_flags & SNIFF_CHANGE_FLAG_RESET_ASSERT) {
switch (iso_state) {
case ISO7816_S_IN_ATR:
led_blink(LED_RED, BLINK_2F_O); /* indicate error to user */
usb_send_atr(SNIFF_DATA_FLAG_ERROR_INCOMPLETE); /* send incomplete ATR to host software using USB */
- change_state(ISO7816_S_WAIT_ATR);
break;
case ISO7816_S_IN_TPDU:
led_blink(LED_RED, BLINK_2F_O); /* indicate error to user */
usb_send_tpdu(SNIFF_DATA_FLAG_ERROR_INCOMPLETE); /* send incomplete PPS to host software using USB */
- change_state(ISO7816_S_WAIT_TPDU);
break;
case ISO7816_S_IN_PPS_REQ:
case ISO7816_S_IN_PPS_RSP:
led_blink(LED_RED, BLINK_2F_O); /* indicate error to user */
usb_send_pps(SNIFF_DATA_FLAG_ERROR_INCOMPLETE); /* send incomplete TPDU to host software using USB */
- change_state(ISO7816_S_WAIT_TPDU);
break;
default:
- change_flags &= ~SNIFF_CHANGE_FLAG_TIMEOUT_WT; /* We don't care about the timeout is all other cases */
break;
}
+ if (ISO7816_S_RESET != iso_state) {
+ change_state(ISO7816_S_RESET);
+ printf("reset asserted\n\r");
+ }
+ }
+ if (change_flags & SNIFF_CHANGE_FLAG_RESET_DEASSERT) {
+ if (ISO7816_S_WAIT_ATR != iso_state) {
+ change_state(ISO7816_S_WAIT_ATR);
+ printf("reset de-asserted\n\r");
+ }
}
if (change_flags) {
usb_send_change(change_flags); /* send timeout to host software over USB */
diff --git a/firmware/libcommon/source/stack_check.c b/firmware/libcommon/source/stack_check.c
new file mode 100644
index 0000000..3130dd8
--- /dev/null
+++ b/firmware/libcommon/source/stack_check.c
@@ -0,0 +1,14 @@
+#include <stdint.h>
+#include <osmocom/core/panic.h>
+
+/* This is what's minimally required to fix builds on Ubuntu 20.04,
+ * where stack smashing protection is enabled by default when using dpkg
+ * - even when cross-compiling: https://osmocom.org/issues/4687
+ */
+
+uintptr_t __stack_chk_guard = 0xdeadbeef;
+
+void __stack_chk_fail(void)
+{
+ osmo_panic("Stack smashing detected!\r\n");
+}
diff --git a/firmware/libcommon/source/stdio.c b/firmware/libcommon/source/stdio.c
index a8612d1..1002c2d 100644
--- a/firmware/libcommon/source/stdio.c
+++ b/firmware/libcommon/source/stdio.c
@@ -358,6 +358,7 @@ signed int vsnprintf(char *pStr, size_t length, const char *pFormat, va_list ap)
case 'i': num = PutSignedInt(pStr, fill, width, va_arg(ap, signed int)); break;
case 'u': num = PutUnsignedInt(pStr, fill, width, va_arg(ap, unsigned int)); break;
case 'x': num = PutHexa(pStr, fill, width, 0, va_arg(ap, unsigned int)); break;
+ case 'p': num = PutHexa(pStr, fill, width, 0, va_arg(ap, unsigned long)); break;
case 'X': num = PutHexa(pStr, fill, width, 1, va_arg(ap, unsigned int)); break;
case 's': num = PutString(pStr, va_arg(ap, char *)); break;
case 'c': num = PutChar(pStr, va_arg(ap, unsigned int)); break;
diff --git a/firmware/libcommon/source/tc_etu.c b/firmware/libcommon/source/tc_etu.c
index 04a7324..a48da8c 100644
--- a/firmware/libcommon/source/tc_etu.c
+++ b/firmware/libcommon/source/tc_etu.c
@@ -11,10 +11,6 @@
* 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 this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*/
#include <stdint.h>
diff --git a/firmware/libcommon/source/usb.c b/firmware/libcommon/source/usb.c
index 43c7bb2..25b35cf 100644
--- a/firmware/libcommon/source/usb.c
+++ b/firmware/libcommon/source/usb.c
@@ -2,7 +2,7 @@
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation
- * Copyright (c) 2018, sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon@sysmocom.de>
+ * Copyright (c) 2018-2019, sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon@sysmocom.de>
*
* All rights reserved.
*
@@ -46,7 +46,10 @@
* USB String descriptors
*------------------------------------------------------------------------------*/
#include "usb_strings_generated.h"
+
+// the index of the strings (must match the order in usb_strings.txt)
enum strDescNum {
+ // static strings from usb_strings
MANUF_STR = 1,
PRODUCT_STRING,
SNIFFER_CONF_STR,
@@ -55,9 +58,82 @@ enum strDescNum {
MITM_CONF_STR,
CARDEM_USIM1_INTF_STR,
CARDEM_USIM2_INTF_STR,
+ CARDEM_USIM3_INTF_STR,
+ CARDEM_USIM4_INTF_STR,
+ // runtime strings
+ SERIAL_STR,
+ VERSION_CONF_STR,
+ VERSION_STR,
+ // count
STRING_DESC_CNT
};
+/** array of static (from usb_strings) and runtime (serial, version) USB strings
+ */
+static const unsigned char *usb_strings_extended[ARRAY_SIZE(usb_strings) + 3];
+
+/* USB string for the serial (using 128-bit device ID) */
+static unsigned char usb_string_serial[] = {
+ USBStringDescriptor_LENGTH(32),
+ USBGenericDescriptor_STRING,
+ USBStringDescriptor_UNICODE('0'),
+ USBStringDescriptor_UNICODE('0'),
+ USBStringDescriptor_UNICODE('1'),
+ USBStringDescriptor_UNICODE('1'),
+ USBStringDescriptor_UNICODE('2'),
+ USBStringDescriptor_UNICODE('2'),
+ USBStringDescriptor_UNICODE('3'),
+ USBStringDescriptor_UNICODE('3'),
+ USBStringDescriptor_UNICODE('4'),
+ USBStringDescriptor_UNICODE('4'),
+ USBStringDescriptor_UNICODE('5'),
+ USBStringDescriptor_UNICODE('5'),
+ USBStringDescriptor_UNICODE('6'),
+ USBStringDescriptor_UNICODE('6'),
+ USBStringDescriptor_UNICODE('7'),
+ USBStringDescriptor_UNICODE('7'),
+ USBStringDescriptor_UNICODE('8'),
+ USBStringDescriptor_UNICODE('8'),
+ USBStringDescriptor_UNICODE('9'),
+ USBStringDescriptor_UNICODE('9'),
+ USBStringDescriptor_UNICODE('a'),
+ USBStringDescriptor_UNICODE('a'),
+ USBStringDescriptor_UNICODE('b'),
+ USBStringDescriptor_UNICODE('b'),
+ USBStringDescriptor_UNICODE('c'),
+ USBStringDescriptor_UNICODE('c'),
+ USBStringDescriptor_UNICODE('d'),
+ USBStringDescriptor_UNICODE('d'),
+ USBStringDescriptor_UNICODE('e'),
+ USBStringDescriptor_UNICODE('e'),
+ USBStringDescriptor_UNICODE('f'),
+ USBStringDescriptor_UNICODE('f'),
+};
+
+/* USB string for the version */
+static const unsigned char usb_string_version_conf[] = {
+ USBStringDescriptor_LENGTH(16),
+ USBGenericDescriptor_STRING,
+ USBStringDescriptor_UNICODE('f'),
+ USBStringDescriptor_UNICODE('i'),
+ USBStringDescriptor_UNICODE('r'),
+ USBStringDescriptor_UNICODE('m'),
+ USBStringDescriptor_UNICODE('w'),
+ USBStringDescriptor_UNICODE('a'),
+ USBStringDescriptor_UNICODE('r'),
+ USBStringDescriptor_UNICODE('e'),
+ USBStringDescriptor_UNICODE(' '),
+ USBStringDescriptor_UNICODE('v'),
+ USBStringDescriptor_UNICODE('e'),
+ USBStringDescriptor_UNICODE('r'),
+ USBStringDescriptor_UNICODE('s'),
+ USBStringDescriptor_UNICODE('i'),
+ USBStringDescriptor_UNICODE('o'),
+ USBStringDescriptor_UNICODE('n'),
+};
+static const char git_version[] = GIT_VERSION;
+static unsigned char usb_string_version[2 + ARRAY_SIZE(git_version) * 2 - 2];
+
/*------------------------------------------------------------------------------
* USB Device descriptors
*------------------------------------------------------------------------------*/
@@ -130,7 +206,7 @@ static const SIMTraceDriverConfigurationDescriptorSniffer
SIMTRACE_USB_EP_CARD_INT),
.bmAttributes = USBEndpointDescriptor_INTERRUPT,
.wMaxPacketSize = USBEndpointDescriptor_MAXINTERRUPTSIZE_FS,
- .bInterval = 0x10,
+ .bInterval = 1,
},
DFURT_IF_DESCRIPTOR(1, 0),
};
@@ -306,7 +382,7 @@ static const SIMTraceDriverConfigurationDescriptorPhone
SIMTRACE_CARDEM_USB_EP_USIM1_INT),
.bmAttributes = USBEndpointDescriptor_INTERRUPT,
.wMaxPacketSize = USBEndpointDescriptor_MAXINTERRUPTSIZE_FS,
- .bInterval = 0x10
+ .bInterval = 1
},
#ifdef CARDEMU_SECOND_UART
/* Communication class interface standard descriptor */
@@ -353,7 +429,7 @@ static const SIMTraceDriverConfigurationDescriptorPhone
SIMTRACE_CARDEM_USB_EP_USIM2_INT),
.bmAttributes = USBEndpointDescriptor_INTERRUPT,
.wMaxPacketSize = USBEndpointDescriptor_MAXINTERRUPTSIZE_FS,
- .bInterval = 0x10,
+ .bInterval = 1,
},
DFURT_IF_DESCRIPTOR(2, 0),
#else
@@ -471,7 +547,7 @@ static const SIMTraceDriverConfigurationDescriptorMITM
CCID_EPT_NOTIFICATION),
.bmAttributes = USBEndpointDescriptor_INTERRUPT,
.wMaxPacketSize = USBEndpointDescriptor_MAXINTERRUPTSIZE_FS,
- .bInterval = 0x10,
+ .bInterval = 1,
},
/* Communication class interface standard descriptor */
@@ -517,12 +593,46 @@ static const SIMTraceDriverConfigurationDescriptorMITM
SIMTRACE_USB_EP_PHONE_INT),
.bmAttributes = USBEndpointDescriptor_INTERRUPT,
.wMaxPacketSize = USBEndpointDescriptor_MAXINTERRUPTSIZE_FS,
- .bInterval = 0x10
+ .bInterval = 1
},
DFURT_IF_DESCRIPTOR(2, 0),
};
#endif /* HAVE_CARDEM */
+/* USB descriptor just to show the version */
+typedef struct _SIMTraceDriverConfigurationDescriptorVersion {
+ /** Standard configuration descriptor. */
+ USBConfigurationDescriptor configuration;
+ USBInterfaceDescriptor version;
+} __attribute__ ((packed)) SIMTraceDriverConfigurationDescriptorVersion;
+
+static const SIMTraceDriverConfigurationDescriptorVersion
+ configurationDescriptorVersion = {
+ /* Standard configuration descriptor for the interface descriptor*/
+ .configuration = {
+ .bLength = sizeof(USBConfigurationDescriptor),
+ .bDescriptorType = USBGenericDescriptor_CONFIGURATION,
+ .wTotalLength = sizeof(SIMTraceDriverConfigurationDescriptorVersion),
+ .bNumInterfaces = 1,
+ .bConfigurationValue = CFG_NUM_VERSION,
+ .iConfiguration = VERSION_CONF_STR,
+ .bmAttributes = USBD_BMATTRIBUTES,
+ .bMaxPower = USBConfigurationDescriptor_POWER(100),
+ },
+ /* Interface standard descriptor just holding the version information */
+ .version = {
+ .bLength = sizeof(USBInterfaceDescriptor),
+ .bDescriptorType = USBGenericDescriptor_INTERFACE,
+ .bInterfaceNumber = 0,
+ .bAlternateSetting = 0,
+ .bNumEndpoints = 0,
+ .bInterfaceClass = USB_CLASS_PROPRIETARY,
+ .bInterfaceSubClass = 0xff,
+ .bInterfaceProtocol = 0,
+ .iInterface = VERSION_STR,
+ },
+};
+
const USBConfigurationDescriptor *configurationDescriptorsArr[] = {
#ifdef HAVE_SNIFFER
&configurationDescriptorSniffer.configuration,
@@ -536,6 +646,7 @@ const USBConfigurationDescriptor *configurationDescriptorsArr[] = {
#ifdef HAVE_MITM
&configurationDescriptorMITM.configuration,
#endif
+ &configurationDescriptorVersion.configuration,
};
/** Standard USB device descriptor for the CDC serial driver */
@@ -552,7 +663,7 @@ const USBDeviceDescriptor deviceDescriptor = {
.bcdDevice = 2, /* Release number */
.iManufacturer = MANUF_STR,
.iProduct = PRODUCT_STRING,
- .iSerialNumber = 0,
+ .iSerialNumber = SERIAL_STR,
.bNumConfigurations = ARRAY_SIZE(configurationDescriptorsArr),
};
@@ -566,8 +677,8 @@ static const USBDDriverDescriptors driverDescriptors = {
0, /* No high-speed configuration descriptor */
0, /* No high-speed device qualifier descriptor */
0, /* No high-speed other speed configuration descriptor */
- usb_strings,
- ARRAY_SIZE(usb_strings),/* cnt string descriptors in list */
+ usb_strings_extended,
+ ARRAY_SIZE(usb_strings_extended),/* cnt string descriptors in list */
};
/*----------------------------------------------------------------------------
@@ -576,23 +687,42 @@ static const USBDDriverDescriptors driverDescriptors = {
void SIMtrace_USB_Initialize(void)
{
-
+ unsigned int i;
/* Signal USB reset by disabling the pull-up on USB D+ for at least 10 ms */
-#ifdef PIN_USB_PULLUP
- const Pin usb_dp_pullup = PIN_USB_PULLUP;
- PIO_Configure(&usb_dp_pullup, 1);
- PIO_Set(&usb_dp_pullup);
-#endif
+ USBD_HAL_Disconnect();
USBD_HAL_Suspend();
- mdelay(20);
-#ifdef PIN_USB_PULLUP
- PIO_Clear(&usb_dp_pullup);
-#endif
+ mdelay(500);
USBD_HAL_Activate();
// Get std USB driver
USBDDriver *pUsbd = USBD_GetDriver();
+ // put device ID into USB serial number description
+ unsigned int device_id[4];
+ EEFC_ReadUniqueID(device_id);
+ char device_id_string[32 + 1];
+ snprintf(device_id_string, ARRAY_SIZE(device_id_string), "%08x%08x%08x%08x",
+ device_id[0], device_id[1], device_id[2], device_id[3]);
+ for (i = 0; i < ARRAY_SIZE(device_id_string) - 1; i++) {
+ usb_string_serial[2 + 2 * i] = device_id_string[i];
+ }
+
+ // put version into USB string
+ usb_string_version[0] = USBStringDescriptor_LENGTH(ARRAY_SIZE(git_version) - 1);
+ usb_string_version[1] = USBGenericDescriptor_STRING;
+ for (i = 0; i < ARRAY_SIZE(git_version) - 1; i++) {
+ usb_string_version[2 + i * 2 + 0] = git_version[i];
+ usb_string_version[2 + i * 2 + 1] = 0;
+ }
+
+ // fill extended USB strings
+ for (i = 0; i < ARRAY_SIZE(usb_strings) && i < ARRAY_SIZE(usb_strings_extended); i++) {
+ usb_strings_extended[i] = usb_strings[i];
+ }
+ usb_strings_extended[SERIAL_STR] = usb_string_serial;
+ usb_strings_extended[VERSION_CONF_STR] = usb_string_version_conf;
+ usb_strings_extended[VERSION_STR] = usb_string_version;
+
// Initialize standard USB driver
USBDDriver_Initialize(pUsbd, &driverDescriptors, 0); // Multiple interface settings not supported
USBD_Init();
diff --git a/firmware/libcommon/source/usb_buf.c b/firmware/libcommon/source/usb_buf.c
index 418569e..72eae54 100644
--- a/firmware/libcommon/source/usb_buf.c
+++ b/firmware/libcommon/source/usb_buf.c
@@ -9,10 +9,6 @@
* 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 this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*/
#include "board.h"
#include "trace.h"
@@ -24,6 +20,7 @@
#include <errno.h>
#define USB_ALLOC_SIZE 280
+#define USB_MAX_QLEN 3
static struct usb_buffered_ep usb_buffered_ep[BOARD_USB_NUMENDPOINTS];
@@ -78,7 +75,18 @@ int usb_buf_submit(struct msgb *msg)
/* no need for irqsafe operation, as the usb_tx_queue is
* processed only by the main loop context */
- msgb_enqueue(&ep->queue, msg);
+
+ if (ep->queue_len >= USB_MAX_QLEN) {
+ struct msgb *evict;
+ /* free the first pending buffer in the queue */
+ TRACE_INFO("EP%02x: dropping first queue element (qlen=%u)\r\n",
+ ep->ep, ep->queue_len);
+ evict = msgb_dequeue_count(&ep->queue, &ep->queue_len);
+ OSMO_ASSERT(evict);
+ usb_buf_free(evict);
+ }
+
+ msgb_enqueue_count(&ep->queue, msg, &ep->queue_len);
return 0;
}
@@ -89,5 +97,6 @@ void usb_buf_init(void)
for (i = 0; i < ARRAY_SIZE(usb_buffered_ep); i++) {
struct usb_buffered_ep *ep = &usb_buffered_ep[i];
INIT_LLIST_HEAD(&ep->queue);
+ ep->ep = i;
}
}
diff --git a/firmware/libosmocore/include/osmocom/core/bit16gen.h b/firmware/libosmocore/include/osmocom/core/bit16gen.h
index 5c6162c..ed47285 100644
--- a/firmware/libosmocore/include/osmocom/core/bit16gen.h
+++ b/firmware/libosmocore/include/osmocom/core/bit16gen.h
@@ -14,10 +14,6 @@
* 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 this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#pragma once
diff --git a/firmware/libosmocore/include/osmocom/core/bit32gen.h b/firmware/libosmocore/include/osmocom/core/bit32gen.h
index 6640e76..12abb72 100644
--- a/firmware/libosmocore/include/osmocom/core/bit32gen.h
+++ b/firmware/libosmocore/include/osmocom/core/bit32gen.h
@@ -14,10 +14,6 @@
* 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 this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#pragma once
diff --git a/firmware/libosmocore/include/osmocom/core/bit64gen.h b/firmware/libosmocore/include/osmocom/core/bit64gen.h
index 8c7b709..2aa2a2e 100644
--- a/firmware/libosmocore/include/osmocom/core/bit64gen.h
+++ b/firmware/libosmocore/include/osmocom/core/bit64gen.h
@@ -14,10 +14,6 @@
* 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 this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#pragma once
diff --git a/firmware/libosmocore/include/osmocom/core/linuxrbtree.h b/firmware/libosmocore/include/osmocom/core/linuxrbtree.h
index d3f9fd1..4212109 100644
--- a/firmware/libosmocore/include/osmocom/core/linuxrbtree.h
+++ b/firmware/libosmocore/include/osmocom/core/linuxrbtree.h
@@ -11,10 +11,6 @@
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 this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA.
linux/include/linux/rbtree.h
diff --git a/firmware/libosmocore/include/osmocom/core/msgb.h b/firmware/libosmocore/include/osmocom/core/msgb.h
index afb887c..dadf487 100644
--- a/firmware/libosmocore/include/osmocom/core/msgb.h
+++ b/firmware/libosmocore/include/osmocom/core/msgb.h
@@ -13,10 +13,6 @@
* 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 this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
*/
#include <stdint.h>
@@ -80,6 +76,49 @@ extern int msgb_resize_area(struct msgb *msg, uint8_t *area,
extern struct msgb *msgb_copy(const struct msgb *msg, const char *name);
static int msgb_test_invariant(const struct msgb *msg) __attribute__((pure));
+/*! Free all msgbs from a queue built with msgb_enqueue().
+ * \param[in] queue list head of a msgb queue.
+ */
+static inline void msgb_queue_free(struct llist_head *queue)
+{
+ struct msgb *msg;
+ while ((msg = msgb_dequeue(queue))) msgb_free(msg);
+}
+
+/*! Enqueue message buffer to tail of a queue and increment queue size counter
+ * \param[in] queue linked list header of queue
+ * \param[in] msg message buffer to be added to the queue
+ * \param[in] count pointer to variable holding size of the queue
+ *
+ * The function will append the specified message buffer \a msg to the queue
+ * implemented by \ref llist_head \a queue using function \ref msgb_enqueue_count,
+ * then increment \a count
+ */
+static inline void msgb_enqueue_count(struct llist_head *queue, struct msgb *msg,
+ unsigned int *count)
+{
+ msgb_enqueue(queue, msg);
+ (*count)++;
+}
+
+/*! Dequeue message buffer from head of queue and decrement queue size counter
+ * \param[in] queue linked list header of queue
+ * \param[in] count pointer to variable holding size of the queue
+ * \returns message buffer (if any) or NULL if queue empty
+ *
+ * The function will remove the first message buffer from the queue
+ * implemented by \ref llist_head \a queue using function \ref msgb_enqueue_count,
+ * and decrement \a count, all if queue is not empty.
+ */
+static inline struct msgb *msgb_dequeue_count(struct llist_head *queue,
+ unsigned int *count)
+{
+ struct msgb *msg = msgb_dequeue(queue);
+ if (msg)
+ (*count)--;
+ return msg;
+}
+
#ifdef MSGB_DEBUG
#include <osmocom/core/panic.h>
#define MSGB_ABORT(msg, fmt, args ...) do { \
diff --git a/firmware/libosmocore/include/osmocom/core/timer.h b/firmware/libosmocore/include/osmocom/core/timer.h
index 6d70fff..6bd95a7 100644
--- a/firmware/libosmocore/include/osmocom/core/timer.h
+++ b/firmware/libosmocore/include/osmocom/core/timer.h
@@ -12,10 +12,6 @@
* 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 this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
*/
/*! \defgroup timer Osmocom timers
diff --git a/firmware/libosmocore/source/backtrace.c b/firmware/libosmocore/source/backtrace.c
index 5d6dc4a..3938d7a 100644
--- a/firmware/libosmocore/source/backtrace.c
+++ b/firmware/libosmocore/source/backtrace.c
@@ -14,10 +14,6 @@
* 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 this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
*/
/*! \file backtrace.c
diff --git a/firmware/libosmocore/source/bits.c b/firmware/libosmocore/source/bits.c
index 0c77b27..5fa9488 100644
--- a/firmware/libosmocore/source/bits.c
+++ b/firmware/libosmocore/source/bits.c
@@ -14,10 +14,6 @@
* 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 this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
*/
#include <stdint.h>
diff --git a/firmware/libosmocore/source/msgb.c b/firmware/libosmocore/source/msgb.c
index a27100c..fcdda87 100644
--- a/firmware/libosmocore/source/msgb.c
+++ b/firmware/libosmocore/source/msgb.c
@@ -12,10 +12,6 @@
* 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 this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
*/
/*! \addtogroup msgb
diff --git a/firmware/libosmocore/source/panic.c b/firmware/libosmocore/source/panic.c
index 74243b0..589464a 100644
--- a/firmware/libosmocore/source/panic.c
+++ b/firmware/libosmocore/source/panic.c
@@ -14,10 +14,6 @@
* 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 this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
*/
/*! \addtogroup utils
@@ -46,7 +42,7 @@ static osmo_panic_handler_t osmo_panic_handler = (void*)0;
__attribute__ ((format (printf, 1, 0)))
static void osmo_panic_default(const char *fmt, va_list args)
{
- vfprintf(stderr, fmt, args);
+ vfprintf_sync(stderr, fmt, args);
osmo_generate_backtrace();
assert(0);
}
diff --git a/firmware/libosmocore/source/rbtree.c b/firmware/libosmocore/source/rbtree.c
index f0ebb8c..a8969f4 100644
--- a/firmware/libosmocore/source/rbtree.c
+++ b/firmware/libosmocore/source/rbtree.c
@@ -12,10 +12,6 @@
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 this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA
linux/lib/rbtree.c
diff --git a/firmware/libosmocore/source/timer.c b/firmware/libosmocore/source/timer.c
index 75c7d45..eb43884 100644
--- a/firmware/libosmocore/source/timer.c
+++ b/firmware/libosmocore/source/timer.c
@@ -17,10 +17,6 @@
* 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 this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
*/
diff --git a/firmware/libosmocore/source/utils.c b/firmware/libosmocore/source/utils.c
index 3096572..f519df7 100644
--- a/firmware/libosmocore/source/utils.c
+++ b/firmware/libosmocore/source/utils.c
@@ -17,10 +17,6 @@
* 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 this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
*/
diff --git a/firmware/misc/crctool.c b/firmware/misc/crctool.c
new file mode 100644
index 0000000..2602753
--- /dev/null
+++ b/firmware/misc/crctool.c
@@ -0,0 +1,91 @@
+/* SIMtrace 2 firmware crc tool
+ *
+ * (C) 2021 by sysmocom -s.f.m.c. GmbH, Author: Eric Wild <ewild@sysmocom.de>
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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.
+ */
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+static void do_crc32(int8_t c, uint32_t *crc_reg)
+{
+ int32_t i, mask;
+ *crc_reg ^= c;
+
+ for (unsigned int j = 0; j < 8; j++)
+ if (*crc_reg & 1)
+ *crc_reg = (*crc_reg >> 1) ^ 0xEDB88320;
+ else
+ *crc_reg = *crc_reg >> 1;
+}
+
+int main(int argc, char *argv[])
+{
+ uint32_t crc_reg = 0xffffffff;
+ long fsize;
+ uint8_t *buffer;
+ uint32_t crc_start_offset;
+
+ if (argc < 3) {
+ perror("usage: crctool startoffset blupdate.bin");
+ return -1;
+ }
+
+ crc_start_offset = strtoull(argv[1], 0, 10);
+
+ FILE *blfile = fopen(argv[2], "rb+");
+ if (blfile == NULL) {
+ perror("error opening file!");
+ return -1;
+ }
+
+ fseek(blfile, 0, SEEK_END);
+ fsize = ftell(blfile);
+
+ if (fsize <= crc_start_offset) {
+ perror("file size?!");
+ return -1;
+ }
+
+ fseek(blfile, 0, SEEK_SET);
+
+ buffer = malloc(fsize);
+ fread(buffer, 1, fsize, blfile);
+
+ if (*(uint32_t *)buffer != 0xdeadc0de) {
+ perror("weird magic, not a valid blupdate file?");
+ free(buffer);
+ return -1;
+ }
+
+ uint8_t *startaddr = buffer + crc_start_offset;
+ uint8_t *endaddr = buffer + fsize;
+ for (uint8_t *i = startaddr; i < endaddr; i++) {
+ do_crc32(*i, &crc_reg);
+ }
+ crc_reg = ~crc_reg;
+
+ fprintf(stderr, "len: %ld crc: %.8x\n", fsize - crc_start_offset, crc_reg);
+
+ ((uint32_t *)buffer)[0] = 0x2000baa0; /* fix magic to valid stack address, checked by BL */
+ ((uint32_t *)buffer)[2] = crc_reg;
+ ((uint32_t *)buffer)[3] = 0x00400000 + 0x4000 + crc_start_offset;
+ ((uint32_t *)buffer)[4] = fsize - crc_start_offset;
+
+ fseek(blfile, 0, SEEK_SET);
+ fwrite(buffer, 4, 5, blfile);
+
+ fclose(blfile);
+ free(buffer);
+ return 0;
+}
diff --git a/firmware/test/Makefile b/firmware/test/Makefile
index d4c543a..4341c92 100644
--- a/firmware/test/Makefile
+++ b/firmware/test/Makefile
@@ -11,12 +11,12 @@ CFLAGS=-g -Wall $(LIBOSMOCORE_CFLAGS) \
-I../libboard/common/include \
-I../libboard/simtrace/include \
-I.
-LDFLAGS=$(LIBOSMOCORE_LIBS)
+LIBS=$(LIBOSMOCORE_LIBS)
VPATH=../src_simtrace ../libcommon/source
card_emu_test: card_emu_tests.hobj card_emu.hobj usb_buf.hobj iso7816_fidi.hobj
- $(CC) $(LDFLAGS) -o $@ $^
+ $(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
%.hobj: %.c
$(CC) $(CFLAGS) -o $@ -c $^
diff --git a/firmware/test/card_emu_tests.c b/firmware/test/card_emu_tests.c
index 09b2e0d..5d5bd3e 100644
--- a/firmware/test/card_emu_tests.c
+++ b/firmware/test/card_emu_tests.c
@@ -13,7 +13,23 @@
#define PHONE_INT 2
#define PHONE_DATAOUT 3
-/* stub functions required by card_emu.c */
+/* stub for stdio */
+signed int printf_sync(const char *pFormat, ...)
+{
+ va_list ap;
+ signed int result;
+
+ va_start(ap, pFormat);
+ result = vprintf(pFormat, ap);
+ va_end(ap);
+
+ return result;
+}
+
+
+/***********************************************************************
+ * stub functions required by card_emu.c
+ ***********************************************************************/
void card_emu_uart_wait_tx_idle(uint8_t uart_chan)
{
@@ -30,6 +46,7 @@ int card_emu_uart_update_fidi(uint8_t uart_chan, unsigned int fidi)
static uint8_t tx_debug_buf[1024];
static unsigned int tx_debug_buf_idx;
+/* the card emulator wants to send some data to the host [reader] */
int card_emu_uart_tx(uint8_t uart_chan, uint8_t byte)
{
printf("UART_TX(%02x)\n", byte);
@@ -37,13 +54,6 @@ int card_emu_uart_tx(uint8_t uart_chan, uint8_t byte)
return 1;
}
-static void reader_check_and_clear(const uint8_t *data, unsigned int len)
-{
- assert(len == tx_debug_buf_idx);
- assert(!memcmp(tx_debug_buf, data, len));
- tx_debug_buf_idx = 0;
-}
-
void card_emu_uart_enable(uint8_t uart_chan, uint8_t rxtx)
{
char *rts;
@@ -54,6 +64,9 @@ void card_emu_uart_enable(uint8_t uart_chan, uint8_t rxtx)
case ENABLE_TX:
rts = "TX";
break;
+ case ENABLE_TX_TIMER_ONLY:
+ rts = "TX-TIMER-ONLY";
+ break;
case ENABLE_RX:
rts = "RX";
break;
@@ -70,32 +83,31 @@ void card_emu_uart_interrupt(uint8_t uart_chan)
printf("uart_interrupt(uart_chan=%u)\n", uart_chan);
}
-void tc_etu_set_wtime(uint8_t tc_chan, uint16_t wtime)
+void card_emu_uart_update_wt(uint8_t uart_chan, uint32_t wt)
{
- printf("tc_etu_set_wtime(tc_chan=%u, wtime=%u)\n", tc_chan, wtime);
+ printf("%s(uart_chan=%u, wtime=%u)\n", __func__, uart_chan, wt);
}
-void tc_etu_set_etu(uint8_t tc_chan, uint16_t etu)
+void card_emu_uart_reset_wt(uint8_t uart_chan)
{
- printf("tc_etu_set_etu(tc_chan=%u, etu=%u)\n", tc_chan, etu);
+ printf("%s(uart_chan=%u\n", __func__, uart_chan);
}
-void tc_etu_init(uint8_t chan_nr, void *handle)
-{
- printf("tc_etu_init(tc_chan=%u)\n", chan_nr);
-}
-void tc_etu_enable(uint8_t chan_nr)
-{
- printf("tc_etu_enable(tc_chan=%u)\n", chan_nr);
-}
-void tc_etu_disable(uint8_t chan_nr)
+/***********************************************************************
+ * test helper functions
+ ***********************************************************************/
+
+
+static void reader_check_and_clear(const uint8_t *data, unsigned int len)
{
- printf("tc_etu_disable(tc_chan=%u)\n", chan_nr);
+ assert(len == tx_debug_buf_idx);
+ assert(!memcmp(tx_debug_buf, data, len));
+ tx_debug_buf_idx = 0;
}
-const uint8_t atr[] = { 0x3b, 0x02, 0x14, 0x50 };
+static const uint8_t atr[] = { 0x3b, 0x02, 0x14, 0x50 };
static int verify_atr(struct card_handle *ch)
{
@@ -126,10 +138,11 @@ static void io_start_card(struct card_handle *ch)
/* release from reset and verify th ATR */
card_emu_io_statechg(ch, CARD_IO_RST, 0);
/* simulate waiting time before ATR expired */
- tc_etu_wtime_expired(ch);
+ card_emu_wtime_expired(ch);
verify_atr(ch);
}
+/* emulate the host/reader sending some bytes to the [emulated] card */
static void reader_send_bytes(struct card_handle *ch, const uint8_t *bytes, unsigned int len)
{
unsigned int i;
@@ -166,14 +179,14 @@ static void dump_rctx(struct msgb *msg)
static void get_and_verify_rctx(uint8_t ep, const uint8_t *data, unsigned int len)
{
- struct llist_head *queue = usb_get_queue(ep);
+ struct usb_buffered_ep *bep = usb_get_buf_ep(ep);
struct msgb *msg;
struct cardemu_usb_msg_tx_data *td;
struct cardemu_usb_msg_rx_data *rd;
struct simtrace_msg_hdr *mh;
- assert(queue);
- msg = msgb_dequeue(queue);
+ assert(bep);
+ msg = msgb_dequeue_count(&bep->queue, &bep->queue_len);
assert(msg);
dump_rctx(msg);
assert(msg->l1h);
@@ -203,13 +216,13 @@ static void get_and_verify_rctx(uint8_t ep, const uint8_t *data, unsigned int le
static void get_and_verify_rctx_pps(const uint8_t *data, unsigned int len)
{
- struct llist_head *queue = usb_get_queue(PHONE_DATAIN);
+ struct usb_buffered_ep *bep = usb_get_buf_ep(PHONE_DATAIN);
struct msgb *msg;
struct simtrace_msg_hdr *mh;
struct cardemu_usb_msg_pts_info *ptsi;
- assert(queue);
- msg = msgb_dequeue(queue);
+ assert(bep);
+ msg = msgb_dequeue_count(&bep->queue, &bep->queue_len);
assert(msg);
dump_rctx(msg);
assert(msg->l1h);
@@ -397,7 +410,7 @@ int main(int argc, char **argv)
struct card_handle *ch;
unsigned int i;
- ch = card_emu_init(0, 23, 42, PHONE_DATAIN, PHONE_INT);
+ ch = card_emu_init(0, 42, PHONE_DATAIN, PHONE_INT, false, true, false);
assert(ch);
usb_buf_init();
diff --git a/firmware/usbstring/usbstring.c b/firmware/usbstring/usbstring.c
index ed07568..e7c6c8c 100644
--- a/firmware/usbstring/usbstring.c
+++ b/firmware/usbstring/usbstring.c
@@ -10,10 +10,6 @@
* 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 this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* Based on existing utf8_to_utf16le() function,
diff --git a/hardware/board_gpio.gnumeric b/hardware/board_gpio.gnumeric
index 1ec9ff6..17cc60f 100644
--- a/hardware/board_gpio.gnumeric
+++ b/hardware/board_gpio.gnumeric
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<gnm:Workbook xmlns:gnm="http://www.gnumeric.org/v10.dtd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.gnumeric.org/v9.xsd">
- <gnm:Version Epoch="1" Major="12" Minor="44" Full="1.12.44"/>
+ <gnm:Version Epoch="1" Major="12" Minor="48" Full="1.12.48"/>
<gnm:Attributes>
<gnm:Attribute>
<gnm:name>WorkbookView::show_horizontal_scrollbar</gnm:name>
@@ -25,7 +25,7 @@
</gnm:Attributes>
<office:document-meta xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:ooo="http://openoffice.org/2004/office" office:version="1.2">
<office:meta>
- <dc:date>2019-02-28T17:12:35Z</dc:date>
+ <dc:date>2021-07-01T21:26:44Z</dc:date>
<meta:creation-date>2017-03-05T18:42:38Z</meta:creation-date>
</office:meta>
</office:document-meta>
@@ -39,7 +39,7 @@
<gnm:Sheets>
<gnm:Sheet DisplayFormulas="0" HideZero="0" HideGrid="0" HideColHeader="0" HideRowHeader="0" DisplayOutlines="1" OutlineSymbolsBelow="1" OutlineSymbolsRight="1" Visibility="GNM_SHEET_VISIBILITY_VISIBLE" GridColor="0:0:0">
<gnm:Name>Sheet1</gnm:Name>
- <gnm:MaxCol>9</gnm:MaxCol>
+ <gnm:MaxCol>13</gnm:MaxCol>
<gnm:MaxRow>67</gnm:MaxRow>
<gnm:Zoom>1</gnm:Zoom>
<gnm:Names>
@@ -82,132 +82,132 @@
<gnm:errors PrintErrorsAs="GNM_PRINT_ERRORS_AS_DISPLAYED"/>
</gnm:PrintInformation>
<gnm:Styles>
- <gnm:StyleRegion startCol="0" startRow="0" endCol="1" endRow="5">
+ <gnm:StyleRegion startCol="0" startRow="0" endCol="2" endRow="5">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="0" startRow="6" endCol="1" endRow="9">
+ <gnm:StyleRegion startCol="0" startRow="6" endCol="2" endRow="9">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="0" startRow="10" endCol="1" endRow="11">
+ <gnm:StyleRegion startCol="0" startRow="10" endCol="2" endRow="11">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="0" startRow="12" endCol="1" endRow="14">
+ <gnm:StyleRegion startCol="0" startRow="12" endCol="2" endRow="14">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="0" startRow="15" endCol="1" endRow="15">
+ <gnm:StyleRegion startCol="0" startRow="15" endCol="2" endRow="15">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="0" startRow="16" endCol="1" endRow="19">
+ <gnm:StyleRegion startCol="0" startRow="16" endCol="2" endRow="19">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="0" startRow="20" endCol="1" endRow="21">
+ <gnm:StyleRegion startCol="0" startRow="20" endCol="2" endRow="21">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="0" startRow="22" endCol="1" endRow="26">
+ <gnm:StyleRegion startCol="0" startRow="22" endCol="2" endRow="26">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="0" startRow="27" endCol="1" endRow="27">
+ <gnm:StyleRegion startCol="0" startRow="27" endCol="2" endRow="27">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="0" startRow="28" endCol="1" endRow="35">
+ <gnm:StyleRegion startCol="0" startRow="28" endCol="2" endRow="35">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="0" startRow="36" endCol="1" endRow="36">
+ <gnm:StyleRegion startCol="0" startRow="36" endCol="2" endRow="36">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="0" startRow="37" endCol="1" endRow="41">
+ <gnm:StyleRegion startCol="0" startRow="37" endCol="2" endRow="41">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="0" startRow="42" endCol="1" endRow="43">
+ <gnm:StyleRegion startCol="0" startRow="42" endCol="2" endRow="43">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="0" startRow="44" endCol="1" endRow="47">
+ <gnm:StyleRegion startCol="0" startRow="44" endCol="2" endRow="47">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="0" startRow="48" endCol="1" endRow="49">
+ <gnm:StyleRegion startCol="0" startRow="48" endCol="2" endRow="49">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="0" startRow="50" endCol="1" endRow="51">
+ <gnm:StyleRegion startCol="0" startRow="50" endCol="2" endRow="51">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="0" startRow="52" endCol="1" endRow="54">
+ <gnm:StyleRegion startCol="0" startRow="52" endCol="2" endRow="54">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="0" startRow="55" endCol="1" endRow="55">
+ <gnm:StyleRegion startCol="0" startRow="55" endCol="2" endRow="55">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="0" startRow="56" endCol="1" endRow="57">
+ <gnm:StyleRegion startCol="0" startRow="56" endCol="2" endRow="57">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="0" startRow="58" endCol="1" endRow="58">
+ <gnm:StyleRegion startCol="0" startRow="58" endCol="2" endRow="58">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="0" startRow="59" endCol="1" endRow="61">
+ <gnm:StyleRegion startCol="0" startRow="59" endCol="2" endRow="61">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="0" startRow="62" endCol="1" endRow="62">
+ <gnm:StyleRegion startCol="0" startRow="62" endCol="2" endRow="62">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="0" startRow="63" endCol="1" endRow="63">
+ <gnm:StyleRegion startCol="0" startRow="63" endCol="2" endRow="63">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="0" startRow="64" endCol="1" endRow="66">
+ <gnm:StyleRegion startCol="0" startRow="64" endCol="2" endRow="66">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="0" startRow="67" endCol="1" endRow="65535">
+ <gnm:StyleRegion startCol="0" startRow="67" endCol="2" endRow="65535">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="2" startRow="0" endCol="2" endRow="5">
+ <gnm:StyleRegion startCol="3" startRow="0" endCol="3" endRow="5">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -215,7 +215,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="2" startRow="6" endCol="2" endRow="9">
+ <gnm:StyleRegion startCol="3" startRow="6" endCol="3" endRow="9">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -223,7 +223,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="2" startRow="10" endCol="2" endRow="11">
+ <gnm:StyleRegion startCol="3" startRow="10" endCol="3" endRow="11">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -231,7 +231,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="2" startRow="12" endCol="2" endRow="14">
+ <gnm:StyleRegion startCol="3" startRow="12" endCol="3" endRow="14">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -239,7 +239,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="2" startRow="15" endCol="2" endRow="15">
+ <gnm:StyleRegion startCol="3" startRow="15" endCol="3" endRow="15">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -247,7 +247,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="2" startRow="16" endCol="2" endRow="19">
+ <gnm:StyleRegion startCol="3" startRow="16" endCol="3" endRow="19">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -255,7 +255,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="2" startRow="20" endCol="2" endRow="21">
+ <gnm:StyleRegion startCol="3" startRow="20" endCol="3" endRow="21">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -263,7 +263,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="2" startRow="22" endCol="2" endRow="26">
+ <gnm:StyleRegion startCol="3" startRow="22" endCol="3" endRow="26">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -271,7 +271,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="2" startRow="27" endCol="2" endRow="27">
+ <gnm:StyleRegion startCol="3" startRow="27" endCol="3" endRow="27">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -279,7 +279,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="2" startRow="28" endCol="2" endRow="35">
+ <gnm:StyleRegion startCol="3" startRow="28" endCol="3" endRow="35">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -287,7 +287,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="2" startRow="36" endCol="2" endRow="36">
+ <gnm:StyleRegion startCol="3" startRow="36" endCol="3" endRow="36">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -295,7 +295,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="2" startRow="37" endCol="2" endRow="41">
+ <gnm:StyleRegion startCol="3" startRow="37" endCol="3" endRow="41">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -303,7 +303,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="2" startRow="42" endCol="2" endRow="43">
+ <gnm:StyleRegion startCol="3" startRow="42" endCol="3" endRow="43">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -311,7 +311,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="2" startRow="44" endCol="2" endRow="47">
+ <gnm:StyleRegion startCol="3" startRow="44" endCol="3" endRow="47">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -319,7 +319,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="2" startRow="48" endCol="2" endRow="49">
+ <gnm:StyleRegion startCol="3" startRow="48" endCol="3" endRow="49">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -327,7 +327,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="2" startRow="50" endCol="2" endRow="51">
+ <gnm:StyleRegion startCol="3" startRow="50" endCol="3" endRow="51">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -335,7 +335,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="2" startRow="52" endCol="2" endRow="54">
+ <gnm:StyleRegion startCol="3" startRow="52" endCol="3" endRow="54">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -343,7 +343,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="2" startRow="55" endCol="2" endRow="55">
+ <gnm:StyleRegion startCol="3" startRow="55" endCol="3" endRow="55">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -351,7 +351,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="2" startRow="56" endCol="2" endRow="57">
+ <gnm:StyleRegion startCol="3" startRow="56" endCol="3" endRow="57">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -359,7 +359,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="2" startRow="58" endCol="2" endRow="58">
+ <gnm:StyleRegion startCol="3" startRow="58" endCol="3" endRow="58">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -367,7 +367,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="2" startRow="59" endCol="2" endRow="61">
+ <gnm:StyleRegion startCol="3" startRow="59" endCol="3" endRow="61">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -375,7 +375,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="2" startRow="62" endCol="2" endRow="62">
+ <gnm:StyleRegion startCol="3" startRow="62" endCol="3" endRow="62">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -383,7 +383,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="2" startRow="63" endCol="2" endRow="63">
+ <gnm:StyleRegion startCol="3" startRow="63" endCol="3" endRow="63">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -391,7 +391,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="2" startRow="64" endCol="2" endRow="66">
+ <gnm:StyleRegion startCol="3" startRow="64" endCol="3" endRow="66">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -399,7 +399,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="2" startRow="67" endCol="2" endRow="65535">
+ <gnm:StyleRegion startCol="3" startRow="67" endCol="3" endRow="65535">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -407,132 +407,132 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="3" startRow="0" endCol="3" endRow="5">
+ <gnm:StyleRegion startCol="4" startRow="0" endCol="4" endRow="5">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="3" startRow="6" endCol="3" endRow="9">
+ <gnm:StyleRegion startCol="4" startRow="6" endCol="4" endRow="9">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="3" startRow="10" endCol="3" endRow="11">
+ <gnm:StyleRegion startCol="4" startRow="10" endCol="4" endRow="11">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="3" startRow="12" endCol="3" endRow="14">
+ <gnm:StyleRegion startCol="4" startRow="12" endCol="4" endRow="14">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="3" startRow="15" endCol="3" endRow="15">
+ <gnm:StyleRegion startCol="4" startRow="15" endCol="4" endRow="15">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="3" startRow="16" endCol="3" endRow="19">
+ <gnm:StyleRegion startCol="4" startRow="16" endCol="4" endRow="19">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="3" startRow="20" endCol="3" endRow="21">
+ <gnm:StyleRegion startCol="4" startRow="20" endCol="4" endRow="21">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="3" startRow="22" endCol="3" endRow="26">
+ <gnm:StyleRegion startCol="4" startRow="22" endCol="4" endRow="26">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="3" startRow="27" endCol="3" endRow="27">
+ <gnm:StyleRegion startCol="4" startRow="27" endCol="4" endRow="27">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="3" startRow="28" endCol="3" endRow="35">
+ <gnm:StyleRegion startCol="4" startRow="28" endCol="4" endRow="35">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="3" startRow="36" endCol="3" endRow="36">
+ <gnm:StyleRegion startCol="4" startRow="36" endCol="4" endRow="36">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="3" startRow="37" endCol="3" endRow="41">
+ <gnm:StyleRegion startCol="4" startRow="37" endCol="4" endRow="41">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="3" startRow="42" endCol="3" endRow="43">
+ <gnm:StyleRegion startCol="4" startRow="42" endCol="4" endRow="43">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="3" startRow="44" endCol="3" endRow="47">
+ <gnm:StyleRegion startCol="4" startRow="44" endCol="4" endRow="47">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="3" startRow="48" endCol="3" endRow="49">
+ <gnm:StyleRegion startCol="4" startRow="48" endCol="4" endRow="49">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="3" startRow="50" endCol="3" endRow="51">
+ <gnm:StyleRegion startCol="4" startRow="50" endCol="4" endRow="51">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="3" startRow="52" endCol="3" endRow="54">
+ <gnm:StyleRegion startCol="4" startRow="52" endCol="4" endRow="54">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="3" startRow="55" endCol="3" endRow="55">
+ <gnm:StyleRegion startCol="4" startRow="55" endCol="4" endRow="55">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="3" startRow="56" endCol="3" endRow="57">
+ <gnm:StyleRegion startCol="4" startRow="56" endCol="4" endRow="57">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="3" startRow="58" endCol="3" endRow="58">
+ <gnm:StyleRegion startCol="4" startRow="58" endCol="4" endRow="58">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="3" startRow="59" endCol="3" endRow="61">
+ <gnm:StyleRegion startCol="4" startRow="59" endCol="4" endRow="61">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="3" startRow="62" endCol="3" endRow="62">
+ <gnm:StyleRegion startCol="4" startRow="62" endCol="4" endRow="62">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="3" startRow="63" endCol="3" endRow="63">
+ <gnm:StyleRegion startCol="4" startRow="63" endCol="4" endRow="63">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="3" startRow="64" endCol="3" endRow="66">
+ <gnm:StyleRegion startCol="4" startRow="64" endCol="4" endRow="66">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="3" startRow="67" endCol="3" endRow="65535">
+ <gnm:StyleRegion startCol="4" startRow="67" endCol="4" endRow="65535">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="4" startRow="0" endCol="4" endRow="5">
+ <gnm:StyleRegion startCol="5" startRow="0" endCol="5" endRow="5">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -540,7 +540,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="4" startRow="6" endCol="4" endRow="9">
+ <gnm:StyleRegion startCol="5" startRow="6" endCol="5" endRow="9">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -548,7 +548,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="4" startRow="10" endCol="4" endRow="11">
+ <gnm:StyleRegion startCol="5" startRow="10" endCol="5" endRow="11">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -556,7 +556,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="4" startRow="12" endCol="4" endRow="14">
+ <gnm:StyleRegion startCol="5" startRow="12" endCol="5" endRow="14">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -564,7 +564,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="4" startRow="15" endCol="4" endRow="15">
+ <gnm:StyleRegion startCol="5" startRow="15" endCol="5" endRow="15">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -572,7 +572,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="4" startRow="16" endCol="4" endRow="19">
+ <gnm:StyleRegion startCol="5" startRow="16" endCol="5" endRow="19">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -580,7 +580,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="4" startRow="20" endCol="4" endRow="21">
+ <gnm:StyleRegion startCol="5" startRow="20" endCol="5" endRow="21">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -588,7 +588,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="4" startRow="22" endCol="4" endRow="26">
+ <gnm:StyleRegion startCol="5" startRow="22" endCol="5" endRow="26">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -596,7 +596,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="4" startRow="27" endCol="4" endRow="27">
+ <gnm:StyleRegion startCol="5" startRow="27" endCol="5" endRow="27">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -604,7 +604,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="4" startRow="28" endCol="4" endRow="35">
+ <gnm:StyleRegion startCol="5" startRow="28" endCol="5" endRow="35">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -612,7 +612,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="4" startRow="36" endCol="4" endRow="36">
+ <gnm:StyleRegion startCol="5" startRow="36" endCol="5" endRow="36">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -620,7 +620,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="4" startRow="37" endCol="4" endRow="41">
+ <gnm:StyleRegion startCol="5" startRow="37" endCol="5" endRow="41">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -628,7 +628,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="4" startRow="42" endCol="4" endRow="43">
+ <gnm:StyleRegion startCol="5" startRow="42" endCol="5" endRow="43">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -636,7 +636,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="4" startRow="44" endCol="4" endRow="47">
+ <gnm:StyleRegion startCol="5" startRow="44" endCol="5" endRow="47">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -644,7 +644,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="4" startRow="48" endCol="4" endRow="49">
+ <gnm:StyleRegion startCol="5" startRow="48" endCol="5" endRow="49">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -652,7 +652,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="4" startRow="50" endCol="4" endRow="51">
+ <gnm:StyleRegion startCol="5" startRow="50" endCol="5" endRow="51">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -660,7 +660,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="4" startRow="52" endCol="4" endRow="54">
+ <gnm:StyleRegion startCol="5" startRow="52" endCol="5" endRow="54">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -668,7 +668,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="4" startRow="55" endCol="4" endRow="55">
+ <gnm:StyleRegion startCol="5" startRow="55" endCol="5" endRow="55">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -676,7 +676,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="4" startRow="56" endCol="4" endRow="57">
+ <gnm:StyleRegion startCol="5" startRow="56" endCol="5" endRow="57">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -684,7 +684,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="4" startRow="58" endCol="4" endRow="58">
+ <gnm:StyleRegion startCol="5" startRow="58" endCol="5" endRow="58">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -692,7 +692,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="4" startRow="59" endCol="4" endRow="61">
+ <gnm:StyleRegion startCol="5" startRow="59" endCol="5" endRow="61">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -700,7 +700,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="4" startRow="62" endCol="4" endRow="62">
+ <gnm:StyleRegion startCol="5" startRow="62" endCol="5" endRow="62">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -708,7 +708,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="4" startRow="63" endCol="4" endRow="63">
+ <gnm:StyleRegion startCol="5" startRow="63" endCol="5" endRow="63">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -716,7 +716,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="4" startRow="64" endCol="4" endRow="66">
+ <gnm:StyleRegion startCol="5" startRow="64" endCol="5" endRow="66">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -724,7 +724,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="4" startRow="67" endCol="4" endRow="65535">
+ <gnm:StyleRegion startCol="5" startRow="67" endCol="5" endRow="65535">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -732,132 +732,132 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="5" startRow="0" endCol="5" endRow="5">
+ <gnm:StyleRegion startCol="6" startRow="0" endCol="6" endRow="5">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="5" startRow="6" endCol="5" endRow="9">
+ <gnm:StyleRegion startCol="6" startRow="6" endCol="6" endRow="9">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="5" startRow="10" endCol="5" endRow="11">
+ <gnm:StyleRegion startCol="6" startRow="10" endCol="6" endRow="11">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="5" startRow="12" endCol="5" endRow="14">
+ <gnm:StyleRegion startCol="6" startRow="12" endCol="6" endRow="14">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="5" startRow="15" endCol="5" endRow="15">
+ <gnm:StyleRegion startCol="6" startRow="15" endCol="6" endRow="15">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="5" startRow="16" endCol="5" endRow="19">
+ <gnm:StyleRegion startCol="6" startRow="16" endCol="6" endRow="19">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="5" startRow="20" endCol="5" endRow="21">
+ <gnm:StyleRegion startCol="6" startRow="20" endCol="6" endRow="21">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="5" startRow="22" endCol="5" endRow="26">
+ <gnm:StyleRegion startCol="6" startRow="22" endCol="6" endRow="26">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="5" startRow="27" endCol="5" endRow="27">
+ <gnm:StyleRegion startCol="6" startRow="27" endCol="6" endRow="27">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="5" startRow="28" endCol="5" endRow="35">
+ <gnm:StyleRegion startCol="6" startRow="28" endCol="6" endRow="35">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="5" startRow="36" endCol="5" endRow="36">
+ <gnm:StyleRegion startCol="6" startRow="36" endCol="6" endRow="36">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="5" startRow="37" endCol="5" endRow="41">
+ <gnm:StyleRegion startCol="6" startRow="37" endCol="6" endRow="41">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="5" startRow="42" endCol="5" endRow="43">
+ <gnm:StyleRegion startCol="6" startRow="42" endCol="6" endRow="43">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="5" startRow="44" endCol="5" endRow="47">
+ <gnm:StyleRegion startCol="6" startRow="44" endCol="6" endRow="47">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="5" startRow="48" endCol="5" endRow="49">
+ <gnm:StyleRegion startCol="6" startRow="48" endCol="6" endRow="49">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="5" startRow="50" endCol="5" endRow="51">
+ <gnm:StyleRegion startCol="6" startRow="50" endCol="6" endRow="51">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="5" startRow="52" endCol="5" endRow="54">
+ <gnm:StyleRegion startCol="6" startRow="52" endCol="6" endRow="54">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="5" startRow="55" endCol="5" endRow="55">
+ <gnm:StyleRegion startCol="6" startRow="55" endCol="6" endRow="55">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="5" startRow="56" endCol="5" endRow="57">
+ <gnm:StyleRegion startCol="6" startRow="56" endCol="6" endRow="57">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="5" startRow="58" endCol="5" endRow="58">
+ <gnm:StyleRegion startCol="6" startRow="58" endCol="6" endRow="58">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="5" startRow="59" endCol="5" endRow="61">
+ <gnm:StyleRegion startCol="6" startRow="59" endCol="6" endRow="61">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="5" startRow="62" endCol="5" endRow="62">
+ <gnm:StyleRegion startCol="6" startRow="62" endCol="6" endRow="62">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="5" startRow="63" endCol="5" endRow="63">
+ <gnm:StyleRegion startCol="6" startRow="63" endCol="6" endRow="63">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="5" startRow="64" endCol="5" endRow="66">
+ <gnm:StyleRegion startCol="6" startRow="64" endCol="6" endRow="66">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="5" startRow="67" endCol="5" endRow="65535">
+ <gnm:StyleRegion startCol="6" startRow="67" endCol="6" endRow="65535">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="6" startRow="0" endCol="6" endRow="5">
+ <gnm:StyleRegion startCol="7" startRow="0" endCol="7" endRow="5">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -865,7 +865,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="6" startRow="6" endCol="6" endRow="9">
+ <gnm:StyleRegion startCol="7" startRow="6" endCol="7" endRow="9">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -873,7 +873,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="6" startRow="10" endCol="6" endRow="11">
+ <gnm:StyleRegion startCol="7" startRow="10" endCol="7" endRow="11">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -881,7 +881,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="6" startRow="12" endCol="6" endRow="14">
+ <gnm:StyleRegion startCol="7" startRow="12" endCol="7" endRow="14">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -889,7 +889,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="6" startRow="15" endCol="6" endRow="15">
+ <gnm:StyleRegion startCol="7" startRow="15" endCol="7" endRow="15">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -897,7 +897,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="6" startRow="16" endCol="6" endRow="19">
+ <gnm:StyleRegion startCol="7" startRow="16" endCol="7" endRow="19">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -905,7 +905,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="6" startRow="20" endCol="6" endRow="21">
+ <gnm:StyleRegion startCol="7" startRow="20" endCol="7" endRow="21">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -913,7 +913,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="6" startRow="22" endCol="6" endRow="26">
+ <gnm:StyleRegion startCol="7" startRow="22" endCol="7" endRow="26">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -921,7 +921,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="6" startRow="27" endCol="6" endRow="27">
+ <gnm:StyleRegion startCol="7" startRow="27" endCol="7" endRow="27">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -929,7 +929,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="6" startRow="28" endCol="6" endRow="35">
+ <gnm:StyleRegion startCol="7" startRow="28" endCol="7" endRow="35">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -937,7 +937,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="6" startRow="36" endCol="6" endRow="36">
+ <gnm:StyleRegion startCol="7" startRow="36" endCol="7" endRow="36">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -945,7 +945,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="6" startRow="37" endCol="6" endRow="41">
+ <gnm:StyleRegion startCol="7" startRow="37" endCol="7" endRow="41">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -953,7 +953,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="6" startRow="42" endCol="6" endRow="43">
+ <gnm:StyleRegion startCol="7" startRow="42" endCol="7" endRow="43">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -961,7 +961,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="6" startRow="44" endCol="6" endRow="47">
+ <gnm:StyleRegion startCol="7" startRow="44" endCol="7" endRow="47">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -969,7 +969,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="6" startRow="48" endCol="6" endRow="49">
+ <gnm:StyleRegion startCol="7" startRow="48" endCol="7" endRow="49">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -977,7 +977,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="6" startRow="50" endCol="6" endRow="51">
+ <gnm:StyleRegion startCol="7" startRow="50" endCol="7" endRow="51">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -985,7 +985,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="6" startRow="52" endCol="6" endRow="54">
+ <gnm:StyleRegion startCol="7" startRow="52" endCol="7" endRow="54">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -993,7 +993,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="6" startRow="55" endCol="6" endRow="55">
+ <gnm:StyleRegion startCol="7" startRow="55" endCol="7" endRow="55">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -1001,7 +1001,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="6" startRow="56" endCol="6" endRow="57">
+ <gnm:StyleRegion startCol="7" startRow="56" endCol="7" endRow="57">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -1009,7 +1009,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="6" startRow="58" endCol="6" endRow="58">
+ <gnm:StyleRegion startCol="7" startRow="58" endCol="7" endRow="58">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -1017,7 +1017,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="6" startRow="59" endCol="6" endRow="61">
+ <gnm:StyleRegion startCol="7" startRow="59" endCol="7" endRow="61">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -1025,7 +1025,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="6" startRow="62" endCol="6" endRow="62">
+ <gnm:StyleRegion startCol="7" startRow="62" endCol="7" endRow="62">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -1033,7 +1033,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="6" startRow="63" endCol="6" endRow="63">
+ <gnm:StyleRegion startCol="7" startRow="63" endCol="7" endRow="63">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -1041,7 +1041,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="6" startRow="64" endCol="6" endRow="66">
+ <gnm:StyleRegion startCol="7" startRow="64" endCol="7" endRow="66">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -1049,7 +1049,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="6" startRow="67" endCol="6" endRow="65535">
+ <gnm:StyleRegion startCol="7" startRow="67" endCol="7" endRow="65535">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -1057,132 +1057,132 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="7" startRow="0" endCol="7" endRow="5">
+ <gnm:StyleRegion startCol="8" startRow="0" endCol="8" endRow="5">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="7" startRow="6" endCol="7" endRow="9">
+ <gnm:StyleRegion startCol="8" startRow="6" endCol="8" endRow="9">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="7" startRow="10" endCol="7" endRow="11">
+ <gnm:StyleRegion startCol="8" startRow="10" endCol="8" endRow="11">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="7" startRow="12" endCol="7" endRow="14">
+ <gnm:StyleRegion startCol="8" startRow="12" endCol="8" endRow="14">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="7" startRow="15" endCol="7" endRow="15">
+ <gnm:StyleRegion startCol="8" startRow="15" endCol="8" endRow="15">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="7" startRow="16" endCol="7" endRow="19">
+ <gnm:StyleRegion startCol="8" startRow="16" endCol="8" endRow="19">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="7" startRow="20" endCol="7" endRow="21">
+ <gnm:StyleRegion startCol="8" startRow="20" endCol="8" endRow="21">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="7" startRow="22" endCol="7" endRow="26">
+ <gnm:StyleRegion startCol="8" startRow="22" endCol="8" endRow="26">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="7" startRow="27" endCol="7" endRow="27">
+ <gnm:StyleRegion startCol="8" startRow="27" endCol="8" endRow="27">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="7" startRow="28" endCol="7" endRow="35">
+ <gnm:StyleRegion startCol="8" startRow="28" endCol="8" endRow="35">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="7" startRow="36" endCol="7" endRow="36">
+ <gnm:StyleRegion startCol="8" startRow="36" endCol="8" endRow="36">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="7" startRow="37" endCol="7" endRow="41">
+ <gnm:StyleRegion startCol="8" startRow="37" endCol="8" endRow="41">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="7" startRow="42" endCol="7" endRow="43">
+ <gnm:StyleRegion startCol="8" startRow="42" endCol="8" endRow="43">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="7" startRow="44" endCol="7" endRow="47">
+ <gnm:StyleRegion startCol="8" startRow="44" endCol="8" endRow="47">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="7" startRow="48" endCol="7" endRow="49">
+ <gnm:StyleRegion startCol="8" startRow="48" endCol="8" endRow="49">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="7" startRow="50" endCol="7" endRow="51">
+ <gnm:StyleRegion startCol="8" startRow="50" endCol="8" endRow="51">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="7" startRow="52" endCol="7" endRow="54">
+ <gnm:StyleRegion startCol="8" startRow="52" endCol="8" endRow="54">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="7" startRow="55" endCol="7" endRow="55">
+ <gnm:StyleRegion startCol="8" startRow="55" endCol="8" endRow="55">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="7" startRow="56" endCol="7" endRow="57">
+ <gnm:StyleRegion startCol="8" startRow="56" endCol="8" endRow="57">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="7" startRow="58" endCol="7" endRow="58">
+ <gnm:StyleRegion startCol="8" startRow="58" endCol="8" endRow="58">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="7" startRow="59" endCol="7" endRow="61">
+ <gnm:StyleRegion startCol="8" startRow="59" endCol="8" endRow="61">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="7" startRow="62" endCol="7" endRow="62">
+ <gnm:StyleRegion startCol="8" startRow="62" endCol="8" endRow="62">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="7" startRow="63" endCol="7" endRow="63">
+ <gnm:StyleRegion startCol="8" startRow="63" endCol="8" endRow="63">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="7" startRow="64" endCol="7" endRow="66">
+ <gnm:StyleRegion startCol="8" startRow="64" endCol="8" endRow="66">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="7" startRow="67" endCol="7" endRow="65535">
+ <gnm:StyleRegion startCol="8" startRow="67" endCol="8" endRow="65535">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="8" startRow="0" endCol="8" endRow="5">
+ <gnm:StyleRegion startCol="9" startRow="0" endCol="9" endRow="5">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -1190,7 +1190,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="8" startRow="6" endCol="8" endRow="9">
+ <gnm:StyleRegion startCol="9" startRow="6" endCol="9" endRow="9">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -1198,7 +1198,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="8" startRow="10" endCol="8" endRow="11">
+ <gnm:StyleRegion startCol="9" startRow="10" endCol="9" endRow="11">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -1206,7 +1206,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="8" startRow="12" endCol="8" endRow="14">
+ <gnm:StyleRegion startCol="9" startRow="12" endCol="9" endRow="14">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -1214,7 +1214,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="8" startRow="15" endCol="8" endRow="15">
+ <gnm:StyleRegion startCol="9" startRow="15" endCol="9" endRow="15">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -1222,7 +1222,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="8" startRow="16" endCol="8" endRow="19">
+ <gnm:StyleRegion startCol="9" startRow="16" endCol="9" endRow="19">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -1230,7 +1230,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="8" startRow="20" endCol="8" endRow="21">
+ <gnm:StyleRegion startCol="9" startRow="20" endCol="9" endRow="21">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -1238,7 +1238,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="8" startRow="22" endCol="8" endRow="26">
+ <gnm:StyleRegion startCol="9" startRow="22" endCol="9" endRow="26">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -1246,7 +1246,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="8" startRow="27" endCol="8" endRow="27">
+ <gnm:StyleRegion startCol="9" startRow="27" endCol="9" endRow="27">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -1254,7 +1254,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="8" startRow="28" endCol="8" endRow="35">
+ <gnm:StyleRegion startCol="9" startRow="28" endCol="9" endRow="35">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -1262,7 +1262,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="8" startRow="36" endCol="8" endRow="36">
+ <gnm:StyleRegion startCol="9" startRow="36" endCol="9" endRow="36">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -1270,7 +1270,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="8" startRow="37" endCol="8" endRow="41">
+ <gnm:StyleRegion startCol="9" startRow="37" endCol="9" endRow="41">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -1278,7 +1278,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="8" startRow="42" endCol="8" endRow="43">
+ <gnm:StyleRegion startCol="9" startRow="42" endCol="9" endRow="43">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -1286,7 +1286,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="8" startRow="44" endCol="8" endRow="47">
+ <gnm:StyleRegion startCol="9" startRow="44" endCol="9" endRow="47">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -1294,7 +1294,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="8" startRow="48" endCol="8" endRow="49">
+ <gnm:StyleRegion startCol="9" startRow="48" endCol="9" endRow="49">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -1302,7 +1302,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="8" startRow="50" endCol="8" endRow="51">
+ <gnm:StyleRegion startCol="9" startRow="50" endCol="9" endRow="51">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -1310,7 +1310,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="8" startRow="52" endCol="8" endRow="54">
+ <gnm:StyleRegion startCol="9" startRow="52" endCol="9" endRow="54">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -1318,7 +1318,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="8" startRow="55" endCol="8" endRow="55">
+ <gnm:StyleRegion startCol="9" startRow="55" endCol="9" endRow="55">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -1326,7 +1326,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="8" startRow="56" endCol="8" endRow="57">
+ <gnm:StyleRegion startCol="9" startRow="56" endCol="9" endRow="57">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -1334,7 +1334,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="8" startRow="58" endCol="8" endRow="58">
+ <gnm:StyleRegion startCol="9" startRow="58" endCol="9" endRow="58">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -1342,7 +1342,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="8" startRow="59" endCol="8" endRow="61">
+ <gnm:StyleRegion startCol="9" startRow="59" endCol="9" endRow="61">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -1350,7 +1350,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="8" startRow="62" endCol="8" endRow="62">
+ <gnm:StyleRegion startCol="9" startRow="62" endCol="9" endRow="62">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -1358,7 +1358,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="8" startRow="63" endCol="8" endRow="63">
+ <gnm:StyleRegion startCol="9" startRow="63" endCol="9" endRow="63">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -1366,7 +1366,7 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="8" startRow="64" endCol="8" endRow="66">
+ <gnm:StyleRegion startCol="9" startRow="64" endCol="9" endRow="66">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -1374,7 +1374,332 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="8" startRow="67" endCol="8" endRow="65535">
+ <gnm:StyleRegion startCol="9" startRow="67" endCol="9" endRow="65535">
+ <gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
+ <gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
+ <gnm:StyleBorder>
+ <gnm:Left Style="1" Color="0:0:0"/>
+ </gnm:StyleBorder>
+ </gnm:Style>
+ </gnm:StyleRegion>
+ <gnm:StyleRegion startCol="10" startRow="0" endCol="10" endRow="5">
+ <gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
+ <gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
+ </gnm:Style>
+ </gnm:StyleRegion>
+ <gnm:StyleRegion startCol="10" startRow="6" endCol="10" endRow="9">
+ <gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
+ <gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
+ </gnm:Style>
+ </gnm:StyleRegion>
+ <gnm:StyleRegion startCol="10" startRow="10" endCol="10" endRow="11">
+ <gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
+ <gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
+ </gnm:Style>
+ </gnm:StyleRegion>
+ <gnm:StyleRegion startCol="10" startRow="12" endCol="10" endRow="14">
+ <gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
+ <gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
+ </gnm:Style>
+ </gnm:StyleRegion>
+ <gnm:StyleRegion startCol="10" startRow="15" endCol="10" endRow="15">
+ <gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
+ <gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
+ </gnm:Style>
+ </gnm:StyleRegion>
+ <gnm:StyleRegion startCol="10" startRow="16" endCol="10" endRow="19">
+ <gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
+ <gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
+ </gnm:Style>
+ </gnm:StyleRegion>
+ <gnm:StyleRegion startCol="10" startRow="20" endCol="10" endRow="21">
+ <gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
+ <gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
+ </gnm:Style>
+ </gnm:StyleRegion>
+ <gnm:StyleRegion startCol="10" startRow="22" endCol="10" endRow="26">
+ <gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
+ <gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
+ </gnm:Style>
+ </gnm:StyleRegion>
+ <gnm:StyleRegion startCol="10" startRow="27" endCol="10" endRow="27">
+ <gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
+ <gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
+ </gnm:Style>
+ </gnm:StyleRegion>
+ <gnm:StyleRegion startCol="10" startRow="28" endCol="10" endRow="35">
+ <gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
+ <gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
+ </gnm:Style>
+ </gnm:StyleRegion>
+ <gnm:StyleRegion startCol="10" startRow="36" endCol="10" endRow="36">
+ <gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
+ <gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
+ </gnm:Style>
+ </gnm:StyleRegion>
+ <gnm:StyleRegion startCol="10" startRow="37" endCol="10" endRow="41">
+ <gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
+ <gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
+ </gnm:Style>
+ </gnm:StyleRegion>
+ <gnm:StyleRegion startCol="10" startRow="42" endCol="10" endRow="43">
+ <gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
+ <gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
+ </gnm:Style>
+ </gnm:StyleRegion>
+ <gnm:StyleRegion startCol="10" startRow="44" endCol="10" endRow="47">
+ <gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
+ <gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
+ </gnm:Style>
+ </gnm:StyleRegion>
+ <gnm:StyleRegion startCol="10" startRow="48" endCol="10" endRow="49">
+ <gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
+ <gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
+ </gnm:Style>
+ </gnm:StyleRegion>
+ <gnm:StyleRegion startCol="10" startRow="50" endCol="10" endRow="51">
+ <gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
+ <gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
+ </gnm:Style>
+ </gnm:StyleRegion>
+ <gnm:StyleRegion startCol="10" startRow="52" endCol="10" endRow="54">
+ <gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
+ <gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
+ </gnm:Style>
+ </gnm:StyleRegion>
+ <gnm:StyleRegion startCol="10" startRow="55" endCol="10" endRow="55">
+ <gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
+ <gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
+ </gnm:Style>
+ </gnm:StyleRegion>
+ <gnm:StyleRegion startCol="10" startRow="56" endCol="10" endRow="57">
+ <gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
+ <gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
+ </gnm:Style>
+ </gnm:StyleRegion>
+ <gnm:StyleRegion startCol="10" startRow="58" endCol="10" endRow="58">
+ <gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
+ <gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
+ </gnm:Style>
+ </gnm:StyleRegion>
+ <gnm:StyleRegion startCol="10" startRow="59" endCol="10" endRow="61">
+ <gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
+ <gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
+ </gnm:Style>
+ </gnm:StyleRegion>
+ <gnm:StyleRegion startCol="10" startRow="62" endCol="10" endRow="62">
+ <gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
+ <gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
+ </gnm:Style>
+ </gnm:StyleRegion>
+ <gnm:StyleRegion startCol="10" startRow="63" endCol="10" endRow="63">
+ <gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
+ <gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
+ </gnm:Style>
+ </gnm:StyleRegion>
+ <gnm:StyleRegion startCol="10" startRow="64" endCol="10" endRow="66">
+ <gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
+ <gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
+ </gnm:Style>
+ </gnm:StyleRegion>
+ <gnm:StyleRegion startCol="10" startRow="67" endCol="10" endRow="65535">
+ <gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
+ <gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
+ </gnm:Style>
+ </gnm:StyleRegion>
+ <gnm:StyleRegion startCol="11" startRow="0" endCol="11" endRow="5">
+ <gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
+ <gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
+ <gnm:StyleBorder>
+ <gnm:Left Style="1" Color="0:0:0"/>
+ </gnm:StyleBorder>
+ </gnm:Style>
+ </gnm:StyleRegion>
+ <gnm:StyleRegion startCol="11" startRow="6" endCol="11" endRow="9">
+ <gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
+ <gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
+ <gnm:StyleBorder>
+ <gnm:Left Style="1" Color="0:0:0"/>
+ </gnm:StyleBorder>
+ </gnm:Style>
+ </gnm:StyleRegion>
+ <gnm:StyleRegion startCol="11" startRow="10" endCol="11" endRow="11">
+ <gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
+ <gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
+ <gnm:StyleBorder>
+ <gnm:Left Style="1" Color="0:0:0"/>
+ </gnm:StyleBorder>
+ </gnm:Style>
+ </gnm:StyleRegion>
+ <gnm:StyleRegion startCol="11" startRow="12" endCol="11" endRow="14">
+ <gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
+ <gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
+ <gnm:StyleBorder>
+ <gnm:Left Style="1" Color="0:0:0"/>
+ </gnm:StyleBorder>
+ </gnm:Style>
+ </gnm:StyleRegion>
+ <gnm:StyleRegion startCol="11" startRow="15" endCol="11" endRow="15">
+ <gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
+ <gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
+ <gnm:StyleBorder>
+ <gnm:Left Style="1" Color="0:0:0"/>
+ </gnm:StyleBorder>
+ </gnm:Style>
+ </gnm:StyleRegion>
+ <gnm:StyleRegion startCol="11" startRow="16" endCol="11" endRow="19">
+ <gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
+ <gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
+ <gnm:StyleBorder>
+ <gnm:Left Style="1" Color="0:0:0"/>
+ </gnm:StyleBorder>
+ </gnm:Style>
+ </gnm:StyleRegion>
+ <gnm:StyleRegion startCol="11" startRow="20" endCol="11" endRow="21">
+ <gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
+ <gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
+ <gnm:StyleBorder>
+ <gnm:Left Style="1" Color="0:0:0"/>
+ </gnm:StyleBorder>
+ </gnm:Style>
+ </gnm:StyleRegion>
+ <gnm:StyleRegion startCol="11" startRow="22" endCol="11" endRow="26">
+ <gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
+ <gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
+ <gnm:StyleBorder>
+ <gnm:Left Style="1" Color="0:0:0"/>
+ </gnm:StyleBorder>
+ </gnm:Style>
+ </gnm:StyleRegion>
+ <gnm:StyleRegion startCol="11" startRow="27" endCol="11" endRow="27">
+ <gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
+ <gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
+ <gnm:StyleBorder>
+ <gnm:Left Style="1" Color="0:0:0"/>
+ </gnm:StyleBorder>
+ </gnm:Style>
+ </gnm:StyleRegion>
+ <gnm:StyleRegion startCol="11" startRow="28" endCol="11" endRow="35">
+ <gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
+ <gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
+ <gnm:StyleBorder>
+ <gnm:Left Style="1" Color="0:0:0"/>
+ </gnm:StyleBorder>
+ </gnm:Style>
+ </gnm:StyleRegion>
+ <gnm:StyleRegion startCol="11" startRow="36" endCol="11" endRow="36">
+ <gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
+ <gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
+ <gnm:StyleBorder>
+ <gnm:Left Style="1" Color="0:0:0"/>
+ </gnm:StyleBorder>
+ </gnm:Style>
+ </gnm:StyleRegion>
+ <gnm:StyleRegion startCol="11" startRow="37" endCol="11" endRow="41">
+ <gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
+ <gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
+ <gnm:StyleBorder>
+ <gnm:Left Style="1" Color="0:0:0"/>
+ </gnm:StyleBorder>
+ </gnm:Style>
+ </gnm:StyleRegion>
+ <gnm:StyleRegion startCol="11" startRow="42" endCol="11" endRow="43">
+ <gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
+ <gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
+ <gnm:StyleBorder>
+ <gnm:Left Style="1" Color="0:0:0"/>
+ </gnm:StyleBorder>
+ </gnm:Style>
+ </gnm:StyleRegion>
+ <gnm:StyleRegion startCol="11" startRow="44" endCol="11" endRow="47">
+ <gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
+ <gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
+ <gnm:StyleBorder>
+ <gnm:Left Style="1" Color="0:0:0"/>
+ </gnm:StyleBorder>
+ </gnm:Style>
+ </gnm:StyleRegion>
+ <gnm:StyleRegion startCol="11" startRow="48" endCol="11" endRow="49">
+ <gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
+ <gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
+ <gnm:StyleBorder>
+ <gnm:Left Style="1" Color="0:0:0"/>
+ </gnm:StyleBorder>
+ </gnm:Style>
+ </gnm:StyleRegion>
+ <gnm:StyleRegion startCol="11" startRow="50" endCol="11" endRow="51">
+ <gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
+ <gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
+ <gnm:StyleBorder>
+ <gnm:Left Style="1" Color="0:0:0"/>
+ </gnm:StyleBorder>
+ </gnm:Style>
+ </gnm:StyleRegion>
+ <gnm:StyleRegion startCol="11" startRow="52" endCol="11" endRow="54">
+ <gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
+ <gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
+ <gnm:StyleBorder>
+ <gnm:Left Style="1" Color="0:0:0"/>
+ </gnm:StyleBorder>
+ </gnm:Style>
+ </gnm:StyleRegion>
+ <gnm:StyleRegion startCol="11" startRow="55" endCol="11" endRow="55">
+ <gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
+ <gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
+ <gnm:StyleBorder>
+ <gnm:Left Style="1" Color="0:0:0"/>
+ </gnm:StyleBorder>
+ </gnm:Style>
+ </gnm:StyleRegion>
+ <gnm:StyleRegion startCol="11" startRow="56" endCol="11" endRow="57">
+ <gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
+ <gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
+ <gnm:StyleBorder>
+ <gnm:Left Style="1" Color="0:0:0"/>
+ </gnm:StyleBorder>
+ </gnm:Style>
+ </gnm:StyleRegion>
+ <gnm:StyleRegion startCol="11" startRow="58" endCol="11" endRow="58">
+ <gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
+ <gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
+ <gnm:StyleBorder>
+ <gnm:Left Style="1" Color="0:0:0"/>
+ </gnm:StyleBorder>
+ </gnm:Style>
+ </gnm:StyleRegion>
+ <gnm:StyleRegion startCol="11" startRow="59" endCol="11" endRow="61">
+ <gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
+ <gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
+ <gnm:StyleBorder>
+ <gnm:Left Style="1" Color="0:0:0"/>
+ </gnm:StyleBorder>
+ </gnm:Style>
+ </gnm:StyleRegion>
+ <gnm:StyleRegion startCol="11" startRow="62" endCol="11" endRow="62">
+ <gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
+ <gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
+ <gnm:StyleBorder>
+ <gnm:Left Style="1" Color="0:0:0"/>
+ </gnm:StyleBorder>
+ </gnm:Style>
+ </gnm:StyleRegion>
+ <gnm:StyleRegion startCol="11" startRow="63" endCol="11" endRow="63">
+ <gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
+ <gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
+ <gnm:StyleBorder>
+ <gnm:Left Style="1" Color="0:0:0"/>
+ </gnm:StyleBorder>
+ </gnm:Style>
+ </gnm:StyleRegion>
+ <gnm:StyleRegion startCol="11" startRow="64" endCol="11" endRow="66">
+ <gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
+ <gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
+ <gnm:StyleBorder>
+ <gnm:Left Style="1" Color="0:0:0"/>
+ </gnm:StyleBorder>
+ </gnm:Style>
+ </gnm:StyleRegion>
+ <gnm:StyleRegion startCol="11" startRow="67" endCol="11" endRow="65535">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
<gnm:StyleBorder>
@@ -1382,545 +1707,668 @@
</gnm:StyleBorder>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="9" startRow="0" endCol="255" endRow="5">
+ <gnm:StyleRegion startCol="12" startRow="0" endCol="255" endRow="5">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="9" startRow="6" endCol="255" endRow="9">
+ <gnm:StyleRegion startCol="12" startRow="6" endCol="255" endRow="9">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="9" startRow="10" endCol="255" endRow="11">
+ <gnm:StyleRegion startCol="12" startRow="10" endCol="255" endRow="11">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="9" startRow="12" endCol="255" endRow="14">
+ <gnm:StyleRegion startCol="12" startRow="12" endCol="255" endRow="14">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="9" startRow="15" endCol="255" endRow="15">
+ <gnm:StyleRegion startCol="12" startRow="15" endCol="255" endRow="15">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="9" startRow="16" endCol="255" endRow="19">
+ <gnm:StyleRegion startCol="12" startRow="16" endCol="255" endRow="19">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="9" startRow="20" endCol="255" endRow="21">
+ <gnm:StyleRegion startCol="12" startRow="20" endCol="255" endRow="21">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="9" startRow="22" endCol="255" endRow="26">
+ <gnm:StyleRegion startCol="12" startRow="22" endCol="255" endRow="26">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="9" startRow="27" endCol="255" endRow="27">
+ <gnm:StyleRegion startCol="12" startRow="27" endCol="255" endRow="27">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="9" startRow="28" endCol="255" endRow="35">
+ <gnm:StyleRegion startCol="12" startRow="28" endCol="255" endRow="35">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="9" startRow="36" endCol="255" endRow="36">
+ <gnm:StyleRegion startCol="12" startRow="36" endCol="255" endRow="36">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="9" startRow="37" endCol="255" endRow="41">
+ <gnm:StyleRegion startCol="12" startRow="37" endCol="255" endRow="41">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="9" startRow="42" endCol="255" endRow="43">
+ <gnm:StyleRegion startCol="12" startRow="42" endCol="255" endRow="43">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="9" startRow="44" endCol="255" endRow="47">
+ <gnm:StyleRegion startCol="12" startRow="44" endCol="255" endRow="47">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="9" startRow="48" endCol="255" endRow="49">
+ <gnm:StyleRegion startCol="12" startRow="48" endCol="255" endRow="49">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="9" startRow="50" endCol="255" endRow="51">
+ <gnm:StyleRegion startCol="12" startRow="50" endCol="255" endRow="51">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="9" startRow="52" endCol="255" endRow="54">
+ <gnm:StyleRegion startCol="12" startRow="52" endCol="255" endRow="54">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="9" startRow="55" endCol="255" endRow="55">
+ <gnm:StyleRegion startCol="12" startRow="55" endCol="255" endRow="55">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="9" startRow="56" endCol="255" endRow="57">
+ <gnm:StyleRegion startCol="12" startRow="56" endCol="255" endRow="57">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="9" startRow="58" endCol="255" endRow="58">
+ <gnm:StyleRegion startCol="12" startRow="58" endCol="255" endRow="58">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="9" startRow="59" endCol="255" endRow="61">
+ <gnm:StyleRegion startCol="12" startRow="59" endCol="255" endRow="61">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="9" startRow="62" endCol="255" endRow="62">
+ <gnm:StyleRegion startCol="12" startRow="62" endCol="255" endRow="62">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="9" startRow="63" endCol="255" endRow="63">
+ <gnm:StyleRegion startCol="12" startRow="63" endCol="255" endRow="63">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="9" startRow="64" endCol="255" endRow="66">
+ <gnm:StyleRegion startCol="12" startRow="64" endCol="255" endRow="66">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="1" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:BABA" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
- <gnm:StyleRegion startCol="9" startRow="67" endCol="255" endRow="65535">
+ <gnm:StyleRegion startCol="12" startRow="67" endCol="255" endRow="65535">
<gnm:Style HAlign="GNM_HALIGN_GENERAL" VAlign="GNM_VALIGN_BOTTOM" WrapText="0" ShrinkToFit="0" Rotation="0" Shade="0" Indent="0" Locked="1" Hidden="0" Fore="0:0:0" Back="FFFF:FFFF:FFFF" PatternColor="0:0:0" Format="General">
<gnm:Font Unit="10" Bold="0" Italic="0" Underline="0" StrikeThrough="0" Script="0">Sans</gnm:Font>
</gnm:Style>
</gnm:StyleRegion>
</gnm:Styles>
<gnm:Cols DefaultSizePts="48">
- <gnm:ColInfo No="1" Unit="118.5" HardSize="1"/>
- <gnm:ColInfo No="2" Unit="78.75" HardSize="1"/>
- <gnm:ColInfo No="3" Unit="102.8" HardSize="1"/>
- <gnm:ColInfo No="5" Unit="120" HardSize="1"/>
- <gnm:ColInfo No="7" Unit="161.2" HardSize="1"/>
+ <gnm:ColInfo No="2" Unit="118.5" HardSize="1"/>
+ <gnm:ColInfo No="3" Unit="78.75" HardSize="1"/>
+ <gnm:ColInfo No="4" Unit="102.8" HardSize="1"/>
+ <gnm:ColInfo No="6" Unit="120" HardSize="1"/>
+ <gnm:ColInfo No="8" Unit="161.2" HardSize="1"/>
+ <gnm:ColInfo No="9" Unit="48" HardSize="1"/>
+ <gnm:ColInfo No="10" Unit="141" HardSize="1"/>
+ <gnm:ColInfo No="12" Unit="144.8" HardSize="1"/>
</gnm:Cols>
<gnm:Rows DefaultSizePts="12.75">
- <gnm:RowInfo No="2" Unit="13.5" Count="2"/>
- <gnm:RowInfo No="12" Unit="13.5" Count="3"/>
- <gnm:RowInfo No="16" Unit="13.5" Count="2"/>
- <gnm:RowInfo No="19" Unit="13.5"/>
- <gnm:RowInfo No="22" Unit="13.5"/>
- <gnm:RowInfo No="24" Unit="13.5" Count="2"/>
- <gnm:RowInfo No="30" Unit="13.5" Count="5"/>
- <gnm:RowInfo No="39" Unit="13.5"/>
- <gnm:RowInfo No="46" Unit="13.5"/>
- <gnm:RowInfo No="55" Unit="13.5"/>
+ <gnm:RowInfo No="2" Unit="13.5" Count="13"/>
+ <gnm:RowInfo No="16" Unit="13.5" Count="4"/>
+ <gnm:RowInfo No="21" Unit="13.5" Count="42"/>
+ <gnm:RowInfo No="64" Unit="13.5" Count="4"/>
</gnm:Rows>
- <gnm:Selections CursorCol="3" CursorRow="0">
- <gnm:Selection startCol="3" startRow="0" endCol="3" endRow="0"/>
+ <gnm:Selections CursorCol="11" CursorRow="2">
+ <gnm:Selection startCol="11" startRow="2" endCol="12" endRow="2"/>
</gnm:Selections>
<gnm:Cells>
- <gnm:Cell Row="0" Col="0" ValueType="60">Pins / Ios of SAM3 based devices</gnm:Cell>
- <gnm:Cell Row="2" Col="2" ValueType="60">SIMtrace v1.x</gnm:Cell>
- <gnm:Cell Row="2" Col="4" ValueType="60">Quad Modem</gnm:Cell>
- <gnm:Cell Row="2" Col="6" ValueType="60">OWHW</gnm:Cell>
- <gnm:Cell Row="2" Col="8" ValueType="60">SAM3-P256</gnm:Cell>
- <gnm:Cell Row="3" Col="0" ValueType="60">Pin Number</gnm:Cell>
- <gnm:Cell Row="3" Col="1" ValueType="60">Pin Name</gnm:Cell>
- <gnm:Cell Row="3" Col="2" ValueType="60">Used Function</gnm:Cell>
- <gnm:Cell Row="3" Col="3" ValueType="60">Signal Name</gnm:Cell>
- <gnm:Cell Row="3" Col="4" ValueType="60">Used Function</gnm:Cell>
- <gnm:Cell Row="3" Col="5" ValueType="60">Signal Name</gnm:Cell>
- <gnm:Cell Row="3" Col="6" ValueType="60">Used Function</gnm:Cell>
- <gnm:Cell Row="3" Col="7" ValueType="60">Signal Name</gnm:Cell>
- <gnm:Cell Row="3" Col="8" ValueType="60">Used Function</gnm:Cell>
- <gnm:Cell Row="3" Col="9" ValueType="60">Signal Name</gnm:Cell>
+ <gnm:Cell Row="0" Col="1" ValueType="60">Pins / Ios of SAM3 based devices</gnm:Cell>
+ <gnm:Cell Row="2" Col="3" ValueType="60">SIMtrace v1.x</gnm:Cell>
+ <gnm:Cell Row="2" Col="5" ValueType="60">Quad Modem</gnm:Cell>
+ <gnm:Cell Row="2" Col="7" ValueType="60">OWHW</gnm:Cell>
+ <gnm:Cell Row="2" Col="9" ValueType="60">SAM3-P256</gnm:Cell>
+ <gnm:Cell Row="2" Col="11" ValueType="60">mPCIe / m.2 CCID</gnm:Cell>
+ <gnm:Cell Row="3" Col="0" ValueType="60">Pin48</gnm:Cell>
+ <gnm:Cell Row="3" Col="1" ValueType="60">Pin Number</gnm:Cell>
+ <gnm:Cell Row="3" Col="2" ValueType="60">Pin Name</gnm:Cell>
+ <gnm:Cell Row="3" Col="3" ValueType="60">Used Function</gnm:Cell>
+ <gnm:Cell Row="3" Col="4" ValueType="60">Signal Name</gnm:Cell>
+ <gnm:Cell Row="3" Col="5" ValueType="60">Used Function</gnm:Cell>
+ <gnm:Cell Row="3" Col="6" ValueType="60">Signal Name</gnm:Cell>
+ <gnm:Cell Row="3" Col="7" ValueType="60">Used Function</gnm:Cell>
+ <gnm:Cell Row="3" Col="8" ValueType="60">Signal Name</gnm:Cell>
+ <gnm:Cell Row="3" Col="9" ValueType="60">Used Function</gnm:Cell>
+ <gnm:Cell Row="3" Col="10" ValueType="60">Signal Name</gnm:Cell>
+ <gnm:Cell Row="3" Col="11" ValueType="60">Used Fun</gnm:Cell>
+ <gnm:Cell Row="3" Col="12" ValueType="60">Signal Name</gnm:Cell>
<gnm:Cell Row="4" Col="0" ValueType="40">1</gnm:Cell>
- <gnm:Cell Row="4" Col="1" ValueType="60">ADVREF</gnm:Cell>
- <gnm:Cell Row="4" Col="4" ValueType="60">ADVREF</gnm:Cell>
+ <gnm:Cell Row="4" Col="1" ValueType="40">1</gnm:Cell>
+ <gnm:Cell Row="4" Col="2" ValueType="60">ADVREF</gnm:Cell>
<gnm:Cell Row="4" Col="5" ValueType="60">ADVREF</gnm:Cell>
+ <gnm:Cell Row="4" Col="6" ValueType="60">ADVREF</gnm:Cell>
<gnm:Cell Row="5" Col="0" ValueType="40">2</gnm:Cell>
- <gnm:Cell Row="5" Col="1" ValueType="60">GND</gnm:Cell>
+ <gnm:Cell Row="5" Col="1" ValueType="40">2</gnm:Cell>
+ <gnm:Cell Row="5" Col="2" ValueType="60">GND</gnm:Cell>
<gnm:Cell Row="6" Col="0" ValueType="40">3</gnm:Cell>
- <gnm:Cell Row="6" Col="1" ValueType="60">AD4</gnm:Cell>
- <gnm:Cell Row="6" Col="5" ValueType="60">GND</gnm:Cell>
- <gnm:Cell Row="6" Col="7" ValueType="60">GND</gnm:Cell>
+ <gnm:Cell Row="6" Col="1" ValueType="40">3</gnm:Cell>
+ <gnm:Cell Row="6" Col="2" ValueType="60">AD4</gnm:Cell>
+ <gnm:Cell Row="6" Col="6" ValueType="60">GND</gnm:Cell>
+ <gnm:Cell Row="6" Col="8" ValueType="60">GND</gnm:Cell>
<gnm:Cell Row="7" Col="0" ValueType="40">4</gnm:Cell>
- <gnm:Cell Row="7" Col="1" ValueType="60">AD5</gnm:Cell>
- <gnm:Cell Row="7" Col="5" ValueType="60">GND</gnm:Cell>
- <gnm:Cell Row="7" Col="7" ValueType="60">GND</gnm:Cell>
+ <gnm:Cell Row="7" Col="1" ValueType="40">4</gnm:Cell>
+ <gnm:Cell Row="7" Col="2" ValueType="60">AD5</gnm:Cell>
+ <gnm:Cell Row="7" Col="6" ValueType="60">GND</gnm:Cell>
+ <gnm:Cell Row="7" Col="8" ValueType="60">GND</gnm:Cell>
<gnm:Cell Row="8" Col="0" ValueType="40">5</gnm:Cell>
- <gnm:Cell Row="8" Col="1" ValueType="60">AD6</gnm:Cell>
- <gnm:Cell Row="8" Col="4" ValueType="60">AD6</gnm:Cell>
- <gnm:Cell Row="8" Col="5" ValueType="60">MDM2_USIM_VDD</gnm:Cell>
- <gnm:Cell Row="8" Col="6" ValueType="60">AD6</gnm:Cell>
- <gnm:Cell Row="8" Col="7" ValueType="60">MDM2_USIM_VDD</gnm:Cell>
+ <gnm:Cell Row="8" Col="1" ValueType="40">5</gnm:Cell>
+ <gnm:Cell Row="8" Col="2" ValueType="60">AD6</gnm:Cell>
+ <gnm:Cell Row="8" Col="5" ValueType="60">AD6</gnm:Cell>
+ <gnm:Cell Row="8" Col="6" ValueType="60">MDM2_USIM_VDD</gnm:Cell>
+ <gnm:Cell Row="8" Col="7" ValueType="60">AD6</gnm:Cell>
+ <gnm:Cell Row="8" Col="8" ValueType="60">MDM2_USIM_VDD</gnm:Cell>
+ <gnm:Cell Row="8" Col="11" ValueType="60">PB2</gnm:Cell>
+ <gnm:Cell Row="8" Col="12" ValueType="60">EN_ST_SIM_VDD</gnm:Cell>
<gnm:Cell Row="9" Col="0" ValueType="40">6</gnm:Cell>
- <gnm:Cell Row="9" Col="1" ValueType="60">AD7</gnm:Cell>
- <gnm:Cell Row="9" Col="4" ValueType="60">AD7</gnm:Cell>
- <gnm:Cell Row="9" Col="5" ValueType="60">MDM1_USIM_VDD</gnm:Cell>
- <gnm:Cell Row="9" Col="6" ValueType="60">AD7</gnm:Cell>
- <gnm:Cell Row="9" Col="7" ValueType="60">MDM1_USIM_VDD</gnm:Cell>
+ <gnm:Cell Row="9" Col="1" ValueType="40">6</gnm:Cell>
+ <gnm:Cell Row="9" Col="2" ValueType="60">AD7</gnm:Cell>
+ <gnm:Cell Row="9" Col="5" ValueType="60">AD7</gnm:Cell>
+ <gnm:Cell Row="9" Col="6" ValueType="60">MDM1_USIM_VDD</gnm:Cell>
+ <gnm:Cell Row="9" Col="7" ValueType="60">AD7</gnm:Cell>
+ <gnm:Cell Row="9" Col="8" ValueType="60">MDM1_USIM_VDD</gnm:Cell>
+ <gnm:Cell Row="9" Col="11" ValueType="60">AD7</gnm:Cell>
+ <gnm:Cell Row="9" Col="12" ValueType="60">MDM_UIM_VDD</gnm:Cell>
<gnm:Cell Row="10" Col="0" ValueType="40">7</gnm:Cell>
- <gnm:Cell Row="10" Col="1" ValueType="60">VDDIN</gnm:Cell>
+ <gnm:Cell Row="10" Col="1" ValueType="40">7</gnm:Cell>
+ <gnm:Cell Row="10" Col="2" ValueType="60">VDDIN</gnm:Cell>
<gnm:Cell Row="11" Col="0" ValueType="40">8</gnm:Cell>
- <gnm:Cell Row="11" Col="1" ValueType="60">VDDOUT</gnm:Cell>
+ <gnm:Cell Row="11" Col="1" ValueType="40">8</gnm:Cell>
+ <gnm:Cell Row="11" Col="2" ValueType="60">VDDOUT</gnm:Cell>
<gnm:Cell Row="12" Col="0" ValueType="40">9</gnm:Cell>
- <gnm:Cell Row="12" Col="1" ValueType="60">PA17</gnm:Cell>
+ <gnm:Cell Row="12" Col="1" ValueType="40">9</gnm:Cell>
<gnm:Cell Row="12" Col="2" ValueType="60">PA17</gnm:Cell>
- <gnm:Cell Row="12" Col="3" ValueType="60">LED_R</gnm:Cell>
- <gnm:Cell Row="12" Col="4" ValueType="60">PA17</gnm:Cell>
- <gnm:Cell Row="12" Col="5" ValueType="60">LED_RED</gnm:Cell>
- <gnm:Cell Row="12" Col="6" ValueType="60">PA17</gnm:Cell>
- <gnm:Cell Row="12" Col="7" ValueType="60">LED_RED</gnm:Cell>
- <gnm:Cell Row="12" Col="8" ValueType="60">LED2</gnm:Cell>
+ <gnm:Cell Row="12" Col="3" ValueType="60">PA17</gnm:Cell>
+ <gnm:Cell Row="12" Col="4" ValueType="60">LED_R</gnm:Cell>
+ <gnm:Cell Row="12" Col="5" ValueType="60">PA17</gnm:Cell>
+ <gnm:Cell Row="12" Col="6" ValueType="60">LED_RED</gnm:Cell>
+ <gnm:Cell Row="12" Col="7" ValueType="60">PA17</gnm:Cell>
+ <gnm:Cell Row="12" Col="8" ValueType="60">LED_RED</gnm:Cell>
+ <gnm:Cell Row="12" Col="9" ValueType="60">LED2</gnm:Cell>
+ <gnm:Cell Row="12" Col="11" ValueType="60">PA17</gnm:Cell>
+ <gnm:Cell Row="12" Col="12" ValueType="60">LED_RED</gnm:Cell>
<gnm:Cell Row="13" Col="0" ValueType="40">10</gnm:Cell>
- <gnm:Cell Row="13" Col="1" ValueType="60">PA18</gnm:Cell>
+ <gnm:Cell Row="13" Col="1" ValueType="40">10</gnm:Cell>
<gnm:Cell Row="13" Col="2" ValueType="60">PA18</gnm:Cell>
- <gnm:Cell Row="13" Col="3" ValueType="60">LED_G</gnm:Cell>
- <gnm:Cell Row="13" Col="4" ValueType="60">PA18</gnm:Cell>
- <gnm:Cell Row="13" Col="5" ValueType="60">LED_GREEN</gnm:Cell>
- <gnm:Cell Row="13" Col="6" ValueType="60">PA18</gnm:Cell>
- <gnm:Cell Row="13" Col="7" ValueType="60">LED_GREEN</gnm:Cell>
- <gnm:Cell Row="13" Col="8" ValueType="60">LED1</gnm:Cell>
+ <gnm:Cell Row="13" Col="3" ValueType="60">PA18</gnm:Cell>
+ <gnm:Cell Row="13" Col="4" ValueType="60">LED_G</gnm:Cell>
+ <gnm:Cell Row="13" Col="5" ValueType="60">PA18</gnm:Cell>
+ <gnm:Cell Row="13" Col="6" ValueType="60">LED_GREEN</gnm:Cell>
+ <gnm:Cell Row="13" Col="7" ValueType="60">PA18</gnm:Cell>
+ <gnm:Cell Row="13" Col="8" ValueType="60">LED_GREEN</gnm:Cell>
+ <gnm:Cell Row="13" Col="9" ValueType="60">LED1</gnm:Cell>
+ <gnm:Cell Row="13" Col="11" ValueType="60">PA18</gnm:Cell>
+ <gnm:Cell Row="13" Col="12" ValueType="60">LED_GREEN</gnm:Cell>
<gnm:Cell Row="14" Col="0" ValueType="40">11</gnm:Cell>
- <gnm:Cell Row="14" Col="1" ValueType="60">PA21/RXD1/PCK1</gnm:Cell>
- <gnm:Cell Row="14" Col="2" ValueType="60">RXD1</gnm:Cell>
- <gnm:Cell Row="14" Col="3" ValueType="60">I/O_PHONE</gnm:Cell>
- <gnm:Cell Row="14" Col="4" ValueType="60">RXD1</gnm:Cell>
- <gnm:Cell Row="14" Col="5" ValueType="60">ST_USIM1_IO</gnm:Cell>
- <gnm:Cell Row="14" Col="6" ValueType="60">RXD1</gnm:Cell>
- <gnm:Cell Row="14" Col="7" ValueType="60">ST_USIM1_IO</gnm:Cell>
- <gnm:Cell Row="14" Col="8" ValueType="60">RXD1</gnm:Cell>
- <gnm:Cell Row="15" Col="0" ValueType="40">12</gnm:Cell>
- <gnm:Cell Row="15" Col="1" ValueType="60">VDDCORE</gnm:Cell>
- <gnm:Cell Row="16" Col="0" ValueType="40">13</gnm:Cell>
- <gnm:Cell Row="16" Col="1" ValueType="60">PA19/RK/FIQ</gnm:Cell>
- <gnm:Cell Row="16" Col="2" ValueType="60">PA19</gnm:Cell>
- <gnm:Cell Row="16" Col="3" ValueType="60">I/O_SW</gnm:Cell>
- <gnm:Cell Row="16" Col="4" ValueType="60">AD2</gnm:Cell>
- <gnm:Cell Row="16" Col="5" ValueType="60">VERSION_DETECT12</gnm:Cell>
- <gnm:Cell Row="16" Col="7" ValueType="60">NC</gnm:Cell>
- <gnm:Cell Row="16" Col="8" ValueType="60">B1</gnm:Cell>
- <gnm:Cell Row="17" Col="0" ValueType="40">14</gnm:Cell>
- <gnm:Cell Row="17" Col="1" ValueType="60">PA22/TXD1/NPCS3</gnm:Cell>
- <gnm:Cell Row="17" Col="2" ValueType="60">TXD1</gnm:Cell>
- <gnm:Cell Row="17" Col="3" ValueType="60">I/O_PHONE</gnm:Cell>
- <gnm:Cell Row="17" Col="4" ValueType="60">TXD1</gnm:Cell>
- <gnm:Cell Row="17" Col="5" ValueType="60">ST_USIM1_IO</gnm:Cell>
- <gnm:Cell Row="17" Col="6" ValueType="60">TXD1</gnm:Cell>
- <gnm:Cell Row="17" Col="7" ValueType="60">ST_USIM1_IO</gnm:Cell>
- <gnm:Cell Row="17" Col="8" ValueType="60">TXD1</gnm:Cell>
- <gnm:Cell Row="18" Col="0" ValueType="40">15</gnm:Cell>
- <gnm:Cell Row="18" Col="1" ValueType="60">PA23/SCK1/PWM0</gnm:Cell>
- <gnm:Cell Row="18" Col="2" ValueType="60">SCK1</gnm:Cell>
- <gnm:Cell Row="18" Col="3" ValueType="60">CLK_PHONE</gnm:Cell>
- <gnm:Cell Row="18" Col="4" ValueType="60">SCK1</gnm:Cell>
- <gnm:Cell Row="18" Col="5" ValueType="60">ST_USIM1_CLK</gnm:Cell>
- <gnm:Cell Row="18" Col="6" ValueType="60">SCK1</gnm:Cell>
- <gnm:Cell Row="18" Col="7" ValueType="60">ST_USIM1_CLK</gnm:Cell>
- <gnm:Cell Row="19" Col="0" ValueType="40">16</gnm:Cell>
- <gnm:Cell Row="19" Col="1" ValueType="60">PA20/RF/IRQ0/AD3</gnm:Cell>
- <gnm:Cell Row="19" Col="2" ValueType="60">PA20</gnm:Cell>
- <gnm:Cell Row="19" Col="3" ValueType="60">SC_SW</gnm:Cell>
- <gnm:Cell Row="19" Col="4" ValueType="60">PA20</gnm:Cell>
- <gnm:Cell Row="19" Col="5" ValueType="60">!CONNECT_ST_USIM1</gnm:Cell>
- <gnm:Cell Row="19" Col="7" ValueType="60">NC</gnm:Cell>
- <gnm:Cell Row="19" Col="8" ValueType="60">B2</gnm:Cell>
- <gnm:Cell Row="20" Col="0" ValueType="40">17</gnm:Cell>
- <gnm:Cell Row="20" Col="1" ValueType="60">GND</gnm:Cell>
- <gnm:Cell Row="21" Col="0" ValueType="40">18</gnm:Cell>
- <gnm:Cell Row="21" Col="1" ValueType="60">VDDIO</gnm:Cell>
- <gnm:Cell Row="22" Col="0" ValueType="40">19</gnm:Cell>
- <gnm:Cell Row="22" Col="1" ValueType="60">PA16/TK/TIOB1</gnm:Cell>
- <gnm:Cell Row="22" Col="2" ValueType="60">PA16</gnm:Cell>
- <gnm:Cell Row="22" Col="3" ValueType="60">!UDP_PUP</gnm:Cell>
- <gnm:Cell Row="22" Col="4" ValueType="60">PA16</gnm:Cell>
- <gnm:Cell Row="22" Col="5" ValueType="60">WWAN2</gnm:Cell>
- <gnm:Cell Row="22" Col="6" ValueType="60">PA16</gnm:Cell>
- <gnm:Cell Row="22" Col="7" ValueType="60">UDP_PUP_CTL</gnm:Cell>
- <gnm:Cell Row="22" Col="8" ValueType="60">DP_PUP</gnm:Cell>
- <gnm:Cell Row="23" Col="0" ValueType="40">20</gnm:Cell>
- <gnm:Cell Row="23" Col="1" ValueType="60">PA15/TF/TIOA1</gnm:Cell>
- <gnm:Cell Row="23" Col="2" ValueType="60">PA15</gnm:Cell>
- <gnm:Cell Row="23" Col="3" ValueType="60">WP</gnm:Cell>
- <gnm:Cell Row="23" Col="4" ValueType="60">PA15</gnm:Cell>
- <gnm:Cell Row="23" Col="5" ValueType="60">WWAN1</gnm:Cell>
- <gnm:Cell Row="23" Col="7" ValueType="60">NC</gnm:Cell>
- <gnm:Cell Row="24" Col="0" ValueType="40">21</gnm:Cell>
- <gnm:Cell Row="24" Col="1" ValueType="60">PA14/SPCK/PWM3</gnm:Cell>
- <gnm:Cell Row="24" Col="2" ValueType="60">SPCK</gnm:Cell>
- <gnm:Cell Row="24" Col="3" ValueType="60">SCK</gnm:Cell>
- <gnm:Cell Row="24" Col="4" ValueType="60">PA14</gnm:Cell>
- <gnm:Cell Row="24" Col="5" ValueType="60">ST12_ST34_SELECT</gnm:Cell>
- <gnm:Cell Row="24" Col="6" ValueType="60">PA14</gnm:Cell>
- <gnm:Cell Row="24" Col="7" ValueType="60">SET_USIM2_PRES</gnm:Cell>
- <gnm:Cell Row="24" Col="8" ValueType="60">SPCK</gnm:Cell>
- <gnm:Cell Row="25" Col="0" ValueType="40">22</gnm:Cell>
- <gnm:Cell Row="25" Col="1" ValueType="60">PA13/MOSI/PWM2</gnm:Cell>
- <gnm:Cell Row="25" Col="2" ValueType="60">MOSI</gnm:Cell>
+ <gnm:Cell Row="14" Col="1" ValueType="40">11</gnm:Cell>
+ <gnm:Cell Row="14" Col="2" ValueType="60">PA21/RXD1/PCK1</gnm:Cell>
+ <gnm:Cell Row="14" Col="3" ValueType="60">RXD1</gnm:Cell>
+ <gnm:Cell Row="14" Col="4" ValueType="60">I/O_PHONE</gnm:Cell>
+ <gnm:Cell Row="14" Col="5" ValueType="60">RXD1</gnm:Cell>
+ <gnm:Cell Row="14" Col="6" ValueType="60">ST_USIM1_IO</gnm:Cell>
+ <gnm:Cell Row="14" Col="7" ValueType="60">RXD1</gnm:Cell>
+ <gnm:Cell Row="14" Col="8" ValueType="60">ST_USIM1_IO</gnm:Cell>
+ <gnm:Cell Row="14" Col="9" ValueType="60">RXD1</gnm:Cell>
+ <gnm:Cell Row="14" Col="12" ValueType="60">ST_UART1_IO</gnm:Cell>
+ <gnm:Cell Row="15" Col="1" ValueType="40">12</gnm:Cell>
+ <gnm:Cell Row="15" Col="2" ValueType="60">VDDCORE</gnm:Cell>
+ <gnm:Cell Row="16" Col="1" ValueType="40">13</gnm:Cell>
+ <gnm:Cell Row="16" Col="2" ValueType="60">PA19/RK/FIQ</gnm:Cell>
+ <gnm:Cell Row="16" Col="3" ValueType="60">PA19</gnm:Cell>
+ <gnm:Cell Row="16" Col="4" ValueType="60">I/O_SW</gnm:Cell>
+ <gnm:Cell Row="16" Col="5" ValueType="60">AD2</gnm:Cell>
+ <gnm:Cell Row="16" Col="6" ValueType="60">VERSION_DETECT12</gnm:Cell>
+ <gnm:Cell Row="16" Col="8" ValueType="60">NC</gnm:Cell>
+ <gnm:Cell Row="16" Col="9" ValueType="60">B1</gnm:Cell>
+ <gnm:Cell Row="16" Col="11" ValueType="60">AD2</gnm:Cell>
+ <gnm:Cell Row="16" Col="12" ValueType="60">VERSION_DETECT</gnm:Cell>
+ <gnm:Cell Row="17" Col="1" ValueType="40">14</gnm:Cell>
+ <gnm:Cell Row="17" Col="2" ValueType="60">PA22/TXD1/NPCS3</gnm:Cell>
+ <gnm:Cell Row="17" Col="3" ValueType="60">TXD1</gnm:Cell>
+ <gnm:Cell Row="17" Col="4" ValueType="60">I/O_PHONE</gnm:Cell>
+ <gnm:Cell Row="17" Col="5" ValueType="60">TXD1</gnm:Cell>
+ <gnm:Cell Row="17" Col="6" ValueType="60">ST_USIM1_IO</gnm:Cell>
+ <gnm:Cell Row="17" Col="7" ValueType="60">TXD1</gnm:Cell>
+ <gnm:Cell Row="17" Col="8" ValueType="60">ST_USIM1_IO</gnm:Cell>
+ <gnm:Cell Row="17" Col="9" ValueType="60">TXD1</gnm:Cell>
+ <gnm:Cell Row="17" Col="11" ValueType="60">TXD1</gnm:Cell>
+ <gnm:Cell Row="17" Col="12" ValueType="60">ST_UART1_IO</gnm:Cell>
+ <gnm:Cell Row="18" Col="1" ValueType="40">15</gnm:Cell>
+ <gnm:Cell Row="18" Col="2" ValueType="60">PA23/SCK1/PWM0</gnm:Cell>
+ <gnm:Cell Row="18" Col="3" ValueType="60">SCK1</gnm:Cell>
+ <gnm:Cell Row="18" Col="4" ValueType="60">CLK_PHONE</gnm:Cell>
+ <gnm:Cell Row="18" Col="5" ValueType="60">SCK1</gnm:Cell>
+ <gnm:Cell Row="18" Col="6" ValueType="60">ST_USIM1_CLK</gnm:Cell>
+ <gnm:Cell Row="18" Col="7" ValueType="60">SCK1</gnm:Cell>
+ <gnm:Cell Row="18" Col="8" ValueType="60">ST_USIM1_CLK</gnm:Cell>
+ <gnm:Cell Row="18" Col="11" ValueType="60">SCK1</gnm:Cell>
+ <gnm:Cell Row="18" Col="12" ValueType="60">ST_UART1_CLK</gnm:Cell>
+ <gnm:Cell Row="19" Col="0" ValueType="40">12</gnm:Cell>
+ <gnm:Cell Row="19" Col="1" ValueType="40">16</gnm:Cell>
+ <gnm:Cell Row="19" Col="2" ValueType="60">PA20/RF/IRQ0/AD3</gnm:Cell>
+ <gnm:Cell Row="19" Col="3" ValueType="60">PA20</gnm:Cell>
+ <gnm:Cell Row="19" Col="4" ValueType="60">SC_SW</gnm:Cell>
+ <gnm:Cell Row="19" Col="5" ValueType="60">PA20</gnm:Cell>
+ <gnm:Cell Row="19" Col="6" ValueType="60">!CONNECT_ST_USIM1</gnm:Cell>
+ <gnm:Cell Row="19" Col="8" ValueType="60">NC</gnm:Cell>
+ <gnm:Cell Row="19" Col="9" ValueType="60">B2</gnm:Cell>
+ <gnm:Cell Row="19" Col="11" ValueType="60">PA20</gnm:Cell>
+ <gnm:Cell Row="19" Col="12" ValueType="60">!CONNECT_UART1</gnm:Cell>
+ <gnm:Cell Row="20" Col="1" ValueType="40">17</gnm:Cell>
+ <gnm:Cell Row="20" Col="2" ValueType="60">GND</gnm:Cell>
+ <gnm:Cell Row="21" Col="0" ValueType="40">13</gnm:Cell>
+ <gnm:Cell Row="21" Col="1" ValueType="40">18</gnm:Cell>
+ <gnm:Cell Row="21" Col="2" ValueType="60">VDDIO</gnm:Cell>
+ <gnm:Cell Row="22" Col="0" ValueType="40">14</gnm:Cell>
+ <gnm:Cell Row="22" Col="1" ValueType="40">19</gnm:Cell>
+ <gnm:Cell Row="22" Col="2" ValueType="60">PA16/TK/TIOB1</gnm:Cell>
+ <gnm:Cell Row="22" Col="3" ValueType="60">PA16</gnm:Cell>
+ <gnm:Cell Row="22" Col="4" ValueType="60">!UDP_PUP</gnm:Cell>
+ <gnm:Cell Row="22" Col="5" ValueType="60">PA16</gnm:Cell>
+ <gnm:Cell Row="22" Col="6" ValueType="60">WWAN2</gnm:Cell>
+ <gnm:Cell Row="22" Col="7" ValueType="60">PA16</gnm:Cell>
+ <gnm:Cell Row="22" Col="8" ValueType="60">UDP_PUP_CTL</gnm:Cell>
+ <gnm:Cell Row="22" Col="9" ValueType="60">DP_PUP</gnm:Cell>
+ <gnm:Cell Row="22" Col="11" ValueType="60">PA16</gnm:Cell>
+ <gnm:Cell Row="22" Col="12" ValueType="60">EN_MDM_SIM_VDD</gnm:Cell>
+ <gnm:Cell Row="23" Col="0" ValueType="40">15</gnm:Cell>
+ <gnm:Cell Row="23" Col="1" ValueType="40">20</gnm:Cell>
+ <gnm:Cell Row="23" Col="2" ValueType="60">PA15/TF/TIOA1</gnm:Cell>
+ <gnm:Cell Row="23" Col="3" ValueType="60">PA15</gnm:Cell>
+ <gnm:Cell Row="23" Col="4" ValueType="60">WP</gnm:Cell>
+ <gnm:Cell Row="23" Col="5" ValueType="60">PA15</gnm:Cell>
+ <gnm:Cell Row="23" Col="6" ValueType="60">WWAN1</gnm:Cell>
+ <gnm:Cell Row="23" Col="8" ValueType="60">NC</gnm:Cell>
+ <gnm:Cell Row="23" Col="11" ValueType="60">PA15</gnm:Cell>
+ <gnm:Cell Row="23" Col="12" ValueType="60">WWAN1</gnm:Cell>
+ <gnm:Cell Row="24" Col="0" ValueType="40">16</gnm:Cell>
+ <gnm:Cell Row="24" Col="1" ValueType="40">21</gnm:Cell>
+ <gnm:Cell Row="24" Col="2" ValueType="60">PA14/SPCK/PWM3</gnm:Cell>
+ <gnm:Cell Row="24" Col="3" ValueType="60">SPCK</gnm:Cell>
+ <gnm:Cell Row="24" Col="4" ValueType="60">SCK</gnm:Cell>
+ <gnm:Cell Row="24" Col="5" ValueType="60">PA14</gnm:Cell>
+ <gnm:Cell Row="24" Col="6" ValueType="60">ST12_ST34_SELECT</gnm:Cell>
+ <gnm:Cell Row="24" Col="7" ValueType="60">PA14</gnm:Cell>
+ <gnm:Cell Row="24" Col="8" ValueType="60">SET_USIM2_PRES</gnm:Cell>
+ <gnm:Cell Row="24" Col="9" ValueType="60">SPCK</gnm:Cell>
+ <gnm:Cell Row="24" Col="11" ValueType="60">PA14</gnm:Cell>
+ <gnm:Cell Row="24" Col="12" ValueType="60">!ALARM_ST_SIM_VDD</gnm:Cell>
+ <gnm:Cell Row="25" Col="0" ValueType="40">17</gnm:Cell>
+ <gnm:Cell Row="25" Col="1" ValueType="40">22</gnm:Cell>
+ <gnm:Cell Row="25" Col="2" ValueType="60">PA13/MOSI/PWM2</gnm:Cell>
<gnm:Cell Row="25" Col="3" ValueType="60">MOSI</gnm:Cell>
- <gnm:Cell Row="25" Col="4" ValueType="60">PA13</gnm:Cell>
- <gnm:Cell Row="25" Col="5" ValueType="60">HUB_RESET</gnm:Cell>
- <gnm:Cell Row="25" Col="7" ValueType="60">NC</gnm:Cell>
- <gnm:Cell Row="25" Col="8" ValueType="60">MOSI</gnm:Cell>
- <gnm:Cell Row="26" Col="0" ValueType="40">23</gnm:Cell>
- <gnm:Cell Row="26" Col="1" ValueType="60">PA24/RTS1/PWM1</gnm:Cell>
- <gnm:Cell Row="26" Col="2" ValueType="60">PA24</gnm:Cell>
- <gnm:Cell Row="26" Col="3" ValueType="60">RST_PHONE</gnm:Cell>
- <gnm:Cell Row="26" Col="4" ValueType="60">PA24</gnm:Cell>
- <gnm:Cell Row="26" Col="5" ValueType="60">!ST_USIM1_RST</gnm:Cell>
- <gnm:Cell Row="26" Col="6" ValueType="60">PA24</gnm:Cell>
- <gnm:Cell Row="26" Col="7" ValueType="60">!ST_USIM1_RST</gnm:Cell>
- <gnm:Cell Row="27" Col="0" ValueType="40">24</gnm:Cell>
- <gnm:Cell Row="27" Col="1" ValueType="60">VDDCORE</gnm:Cell>
- <gnm:Cell Row="28" Col="0" ValueType="40">25</gnm:Cell>
- <gnm:Cell Row="28" Col="1" ValueType="60">PA25/CTS1/PWM2</gnm:Cell>
- <gnm:Cell Row="28" Col="2" ValueType="60">PA25</gnm:Cell>
- <gnm:Cell Row="28" Col="3" ValueType="60">VCC_PHONE</gnm:Cell>
- <gnm:Cell Row="28" Col="4" ValueType="60">PA25</gnm:Cell>
- <gnm:Cell Row="28" Col="5" ValueType="60">PERST1</gnm:Cell>
- <gnm:Cell Row="28" Col="7" ValueType="60">NC</gnm:Cell>
- <gnm:Cell Row="29" Col="0" ValueType="40">26</gnm:Cell>
- <gnm:Cell Row="29" Col="1" ValueType="60">PA26/DCD1/TIOA2</gnm:Cell>
- <gnm:Cell Row="29" Col="2" ValueType="60">PA26</gnm:Cell>
- <gnm:Cell Row="29" Col="3" ValueType="60">VCC_FWD</gnm:Cell>
- <gnm:Cell Row="29" Col="4" ValueType="60">PA26</gnm:Cell>
- <gnm:Cell Row="29" Col="5" ValueType="60">PERST2</gnm:Cell>
- <gnm:Cell Row="29" Col="7" ValueType="60">NC</gnm:Cell>
- <gnm:Cell Row="30" Col="0" ValueType="40">27</gnm:Cell>
- <gnm:Cell Row="30" Col="1" ValueType="60">PA12/MISO/PWM1</gnm:Cell>
- <gnm:Cell Row="30" Col="2" ValueType="60">MISO</gnm:Cell>
+ <gnm:Cell Row="25" Col="4" ValueType="60">MOSI</gnm:Cell>
+ <gnm:Cell Row="25" Col="5" ValueType="60">PA13</gnm:Cell>
+ <gnm:Cell Row="25" Col="6" ValueType="60">HUB_RESET</gnm:Cell>
+ <gnm:Cell Row="25" Col="8" ValueType="60">NC</gnm:Cell>
+ <gnm:Cell Row="25" Col="9" ValueType="60">MOSI</gnm:Cell>
+ <gnm:Cell Row="25" Col="11" ValueType="60">PA13</gnm:Cell>
+ <gnm:Cell Row="25" Col="12" ValueType="60">!SET_SIM_DET</gnm:Cell>
+ <gnm:Cell Row="26" Col="1" ValueType="40">23</gnm:Cell>
+ <gnm:Cell Row="26" Col="2" ValueType="60">PA24/RTS1/PWM1</gnm:Cell>
+ <gnm:Cell Row="26" Col="3" ValueType="60">PA24</gnm:Cell>
+ <gnm:Cell Row="26" Col="4" ValueType="60">RST_PHONE</gnm:Cell>
+ <gnm:Cell Row="26" Col="5" ValueType="60">PA24</gnm:Cell>
+ <gnm:Cell Row="26" Col="6" ValueType="60">!ST_USIM1_RST</gnm:Cell>
+ <gnm:Cell Row="26" Col="7" ValueType="60">PA24</gnm:Cell>
+ <gnm:Cell Row="26" Col="8" ValueType="60">!ST_USIM1_RST</gnm:Cell>
+ <gnm:Cell Row="26" Col="11" ValueType="60">PA24</gnm:Cell>
+ <gnm:Cell Row="26" Col="12" ValueType="60">!ST_UART1_RST</gnm:Cell>
+ <gnm:Cell Row="27" Col="0" ValueType="40">18</gnm:Cell>
+ <gnm:Cell Row="27" Col="1" ValueType="40">24</gnm:Cell>
+ <gnm:Cell Row="27" Col="2" ValueType="60">VDDCORE</gnm:Cell>
+ <gnm:Cell Row="28" Col="1" ValueType="40">25</gnm:Cell>
+ <gnm:Cell Row="28" Col="2" ValueType="60">PA25/CTS1/PWM2</gnm:Cell>
+ <gnm:Cell Row="28" Col="3" ValueType="60">PA25</gnm:Cell>
+ <gnm:Cell Row="28" Col="4" ValueType="60">VCC_PHONE</gnm:Cell>
+ <gnm:Cell Row="28" Col="5" ValueType="60">PA25</gnm:Cell>
+ <gnm:Cell Row="28" Col="6" ValueType="60">PERST1</gnm:Cell>
+ <gnm:Cell Row="28" Col="8" ValueType="60">NC</gnm:Cell>
+ <gnm:Cell Row="28" Col="11" ValueType="60">PA25</gnm:Cell>
+ <gnm:Cell Row="28" Col="12" ValueType="60">PERST</gnm:Cell>
+ <gnm:Cell Row="29" Col="1" ValueType="40">26</gnm:Cell>
+ <gnm:Cell Row="29" Col="2" ValueType="60">PA26/DCD1/TIOA2</gnm:Cell>
+ <gnm:Cell Row="29" Col="3" ValueType="60">PA26</gnm:Cell>
+ <gnm:Cell Row="29" Col="4" ValueType="60">VCC_FWD</gnm:Cell>
+ <gnm:Cell Row="29" Col="5" ValueType="60">PA26</gnm:Cell>
+ <gnm:Cell Row="29" Col="6" ValueType="60">PERST2</gnm:Cell>
+ <gnm:Cell Row="29" Col="8" ValueType="60">NC</gnm:Cell>
+ <gnm:Cell Row="29" Col="11" ValueType="60">PA26</gnm:Cell>
+ <gnm:Cell Row="29" Col="12" ValueType="60">!PWR_ON</gnm:Cell>
+ <gnm:Cell Row="30" Col="0" ValueType="40">19</gnm:Cell>
+ <gnm:Cell Row="30" Col="1" ValueType="40">27</gnm:Cell>
+ <gnm:Cell Row="30" Col="2" ValueType="60">PA12/MISO/PWM1</gnm:Cell>
<gnm:Cell Row="30" Col="3" ValueType="60">MISO</gnm:Cell>
- <gnm:Cell Row="30" Col="4" ValueType="60">NC</gnm:Cell>
- <gnm:Cell Row="30" Col="5" ValueType="60">SIMPRES1</gnm:Cell>
- <gnm:Cell Row="30" Col="6" ValueType="60">PA12</gnm:Cell>
- <gnm:Cell Row="30" Col="7" ValueType="60">SET_USIM1_PRES</gnm:Cell>
- <gnm:Cell Row="30" Col="8" ValueType="60">MISO</gnm:Cell>
- <gnm:Cell Row="31" Col="0" ValueType="40">28</gnm:Cell>
- <gnm:Cell Row="31" Col="1" ValueType="60">PA11/NPCS0/PWM0</gnm:Cell>
- <gnm:Cell Row="31" Col="2" ValueType="60">NPCS0</gnm:Cell>
- <gnm:Cell Row="31" Col="3" ValueType="60">CS</gnm:Cell>
- <gnm:Cell Row="31" Col="4" ValueType="60">PA11</gnm:Cell>
- <gnm:Cell Row="31" Col="5" ValueType="60">_SIMTRACE34_ERASE</gnm:Cell>
- <gnm:Cell Row="31" Col="7" ValueType="60">NC</gnm:Cell>
- <gnm:Cell Row="31" Col="8" ValueType="60">NPCS0</gnm:Cell>
- <gnm:Cell Row="32" Col="0" ValueType="40">29</gnm:Cell>
- <gnm:Cell Row="32" Col="1" ValueType="60">PA10/DTXD/NCPS2</gnm:Cell>
- <gnm:Cell Row="32" Col="2" ValueType="60">DTXD</gnm:Cell>
+ <gnm:Cell Row="30" Col="4" ValueType="60">MISO</gnm:Cell>
+ <gnm:Cell Row="30" Col="5" ValueType="60">NC</gnm:Cell>
+ <gnm:Cell Row="30" Col="6" ValueType="60">SIMPRES1</gnm:Cell>
+ <gnm:Cell Row="30" Col="7" ValueType="60">PA12</gnm:Cell>
+ <gnm:Cell Row="30" Col="8" ValueType="60">SET_USIM1_PRES</gnm:Cell>
+ <gnm:Cell Row="30" Col="9" ValueType="60">MISO</gnm:Cell>
+ <gnm:Cell Row="30" Col="12" ValueType="60">NC</gnm:Cell>
+ <gnm:Cell Row="31" Col="0" ValueType="40">20</gnm:Cell>
+ <gnm:Cell Row="31" Col="1" ValueType="40">28</gnm:Cell>
+ <gnm:Cell Row="31" Col="2" ValueType="60">PA11/NPCS0/PWM0</gnm:Cell>
+ <gnm:Cell Row="31" Col="3" ValueType="60">NPCS0</gnm:Cell>
+ <gnm:Cell Row="31" Col="4" ValueType="60">CS</gnm:Cell>
+ <gnm:Cell Row="31" Col="5" ValueType="60">PA11</gnm:Cell>
+ <gnm:Cell Row="31" Col="6" ValueType="60">_SIMTRACE34_ERASE</gnm:Cell>
+ <gnm:Cell Row="31" Col="8" ValueType="60">NC</gnm:Cell>
+ <gnm:Cell Row="31" Col="9" ValueType="60">NPCS0</gnm:Cell>
+ <gnm:Cell Row="31" Col="11" ValueType="60">PA11</gnm:Cell>
+ <gnm:Cell Row="31" Col="12" ValueType="60">MODEM_EN</gnm:Cell>
+ <gnm:Cell Row="32" Col="0" ValueType="40">21</gnm:Cell>
+ <gnm:Cell Row="32" Col="1" ValueType="40">29</gnm:Cell>
+ <gnm:Cell Row="32" Col="2" ValueType="60">PA10/DTXD/NCPS2</gnm:Cell>
<gnm:Cell Row="32" Col="3" ValueType="60">DTXD</gnm:Cell>
<gnm:Cell Row="32" Col="4" ValueType="60">DTXD</gnm:Cell>
- <gnm:Cell Row="32" Col="5" ValueType="60">SIMTRACE1_DTXD</gnm:Cell>
- <gnm:Cell Row="32" Col="6" ValueType="60">DTXD</gnm:Cell>
- <gnm:Cell Row="32" Col="7" ValueType="60">SIMTRACE_DTXD</gnm:Cell>
- <gnm:Cell Row="32" Col="8" ValueType="60">DTXD</gnm:Cell>
- <gnm:Cell Row="33" Col="0" ValueType="40">30</gnm:Cell>
- <gnm:Cell Row="33" Col="1" ValueType="60">PA9/DRXDNPCS1</gnm:Cell>
- <gnm:Cell Row="33" Col="2" ValueType="60">DRXD</gnm:Cell>
+ <gnm:Cell Row="32" Col="5" ValueType="60">DTXD</gnm:Cell>
+ <gnm:Cell Row="32" Col="6" ValueType="60">SIMTRACE1_DTXD</gnm:Cell>
+ <gnm:Cell Row="32" Col="7" ValueType="60">DTXD</gnm:Cell>
+ <gnm:Cell Row="32" Col="8" ValueType="60">SIMTRACE_DTXD</gnm:Cell>
+ <gnm:Cell Row="32" Col="9" ValueType="60">DTXD</gnm:Cell>
+ <gnm:Cell Row="32" Col="11" ValueType="60">DTXD</gnm:Cell>
+ <gnm:Cell Row="33" Col="0" ValueType="40">22</gnm:Cell>
+ <gnm:Cell Row="33" Col="1" ValueType="40">30</gnm:Cell>
+ <gnm:Cell Row="33" Col="2" ValueType="60">PA9/DRXDNPCS1</gnm:Cell>
<gnm:Cell Row="33" Col="3" ValueType="60">DRXD</gnm:Cell>
<gnm:Cell Row="33" Col="4" ValueType="60">DRXD</gnm:Cell>
- <gnm:Cell Row="33" Col="5" ValueType="60">SIMTRACE1_DRXD</gnm:Cell>
- <gnm:Cell Row="33" Col="6" ValueType="60">DRXD</gnm:Cell>
- <gnm:Cell Row="33" Col="7" ValueType="60">SIMTRACE_DRXD</gnm:Cell>
- <gnm:Cell Row="33" Col="8" ValueType="60">DRXD</gnm:Cell>
- <gnm:Cell Row="34" Col="0" ValueType="40">31</gnm:Cell>
- <gnm:Cell Row="34" Col="1" ValueType="60">PA8/CTS0/ADTRG</gnm:Cell>
- <gnm:Cell Row="34" Col="2" ValueType="60">PA8</gnm:Cell>
- <gnm:Cell Row="34" Col="3" ValueType="60">SW_SIM</gnm:Cell>
- <gnm:Cell Row="34" Col="4" ValueType="60">PA8</gnm:Cell>
- <gnm:Cell Row="34" Col="5" ValueType="60">SIMPRES2 / ST12_PRTPWR-OVERRIDE</gnm:Cell>
- <gnm:Cell Row="34" Col="7" ValueType="60">NC</gnm:Cell>
- <gnm:Cell Row="34" Col="8" ValueType="60">DM_PUP</gnm:Cell>
- <gnm:Cell Row="35" Col="0" ValueType="40">32</gnm:Cell>
- <gnm:Cell Row="35" Col="1" ValueType="60">PA7/RTS0/PWM3</gnm:Cell>
- <gnm:Cell Row="35" Col="2" ValueType="60">PA7</gnm:Cell>
- <gnm:Cell Row="35" Col="3" ValueType="60">RST_SIM</gnm:Cell>
- <gnm:Cell Row="35" Col="4" ValueType="60">PA7</gnm:Cell>
- <gnm:Cell Row="35" Col="5" ValueType="60">!ST_USIM2_RST</gnm:Cell>
- <gnm:Cell Row="35" Col="6" ValueType="60">PA7</gnm:Cell>
- <gnm:Cell Row="35" Col="7" ValueType="60">!ST_USIM2_RST</gnm:Cell>
- <gnm:Cell Row="36" Col="0" ValueType="40">33</gnm:Cell>
- <gnm:Cell Row="36" Col="1" ValueType="60">TDI</gnm:Cell>
- <gnm:Cell Row="36" Col="4" ValueType="60">TDI</gnm:Cell>
- <gnm:Cell Row="36" Col="5" ValueType="60">SIMTRACE12_TDI</gnm:Cell>
- <gnm:Cell Row="37" Col="0" ValueType="40">34</gnm:Cell>
- <gnm:Cell Row="37" Col="1" ValueType="60">PA6/TXD0/PCK0</gnm:Cell>
- <gnm:Cell Row="37" Col="3" ValueType="60">I/O_SIM</gnm:Cell>
- <gnm:Cell Row="37" Col="4" ValueType="60">TXD0</gnm:Cell>
- <gnm:Cell Row="37" Col="5" ValueType="60">ST_USIM2_IO</gnm:Cell>
- <gnm:Cell Row="37" Col="6" ValueType="60">TXD0</gnm:Cell>
- <gnm:Cell Row="37" Col="7" ValueType="60">ST_USIM2_IO</gnm:Cell>
- <gnm:Cell Row="38" Col="0" ValueType="40">35</gnm:Cell>
- <gnm:Cell Row="38" Col="1" ValueType="60">PA5/RXD0/NPCS3</gnm:Cell>
- <gnm:Cell Row="38" Col="2" ValueType="60">PA5</gnm:Cell>
- <gnm:Cell Row="38" Col="3" ValueType="60">SIM_PWEN</gnm:Cell>
- <gnm:Cell Row="38" Col="4" ValueType="60">RXD0</gnm:Cell>
- <gnm:Cell Row="38" Col="5" ValueType="60">ST_USIM2_IO</gnm:Cell>
- <gnm:Cell Row="38" Col="6" ValueType="60">RXD0</gnm:Cell>
- <gnm:Cell Row="38" Col="7" ValueType="60">ST_USIM2_IO</gnm:Cell>
- <gnm:Cell Row="39" Col="0" ValueType="40">36</gnm:Cell>
- <gnm:Cell Row="39" Col="1" ValueType="60">PA4/TWCK/TCLK0</gnm:Cell>
- <gnm:Cell Row="39" Col="2" ValueType="60">TCLK0</gnm:Cell>
- <gnm:Cell Row="39" Col="3" ValueType="60">CLK_SIM</gnm:Cell>
- <gnm:Cell Row="39" Col="4" ValueType="60">TCLK0</gnm:Cell>
- <gnm:Cell Row="39" Col="5" ValueType="60">ST_USIM2_CLK</gnm:Cell>
- <gnm:Cell Row="39" Col="6" ValueType="60">TCLK0</gnm:Cell>
- <gnm:Cell Row="39" Col="7" ValueType="60">ST_USIM2_CLK</gnm:Cell>
- <gnm:Cell Row="39" Col="8" ValueType="60">TWCK</gnm:Cell>
- <gnm:Cell Row="40" Col="0" ValueType="40">37</gnm:Cell>
- <gnm:Cell Row="40" Col="1" ValueType="60">PA27/DTR1/TIOB2</gnm:Cell>
- <gnm:Cell Row="40" Col="2" ValueType="60">NC</gnm:Cell>
+ <gnm:Cell Row="33" Col="5" ValueType="60">DRXD</gnm:Cell>
+ <gnm:Cell Row="33" Col="6" ValueType="60">SIMTRACE1_DRXD</gnm:Cell>
+ <gnm:Cell Row="33" Col="7" ValueType="60">DRXD</gnm:Cell>
+ <gnm:Cell Row="33" Col="8" ValueType="60">SIMTRACE_DRXD</gnm:Cell>
+ <gnm:Cell Row="33" Col="9" ValueType="60">DRXD</gnm:Cell>
+ <gnm:Cell Row="33" Col="11" ValueType="60">DRXD</gnm:Cell>
+ <gnm:Cell Row="34" Col="0" ValueType="40">23</gnm:Cell>
+ <gnm:Cell Row="34" Col="1" ValueType="40">31</gnm:Cell>
+ <gnm:Cell Row="34" Col="2" ValueType="60">PA8/CTS0/ADTRG</gnm:Cell>
+ <gnm:Cell Row="34" Col="3" ValueType="60">PA8</gnm:Cell>
+ <gnm:Cell Row="34" Col="4" ValueType="60">SW_SIM</gnm:Cell>
+ <gnm:Cell Row="34" Col="5" ValueType="60">PA8</gnm:Cell>
+ <gnm:Cell Row="34" Col="6" ValueType="60">SIMPRES2 / ST12_PRTPWR-OVERRIDE</gnm:Cell>
+ <gnm:Cell Row="34" Col="8" ValueType="60">NC</gnm:Cell>
+ <gnm:Cell Row="34" Col="9" ValueType="60">DM_PUP</gnm:Cell>
+ <gnm:Cell Row="34" Col="11" ValueType="60">PA8</gnm:Cell>
+ <gnm:Cell Row="34" Col="12" ValueType="60">SLOT_DET</gnm:Cell>
+ <gnm:Cell Row="35" Col="0" ValueType="40">24</gnm:Cell>
+ <gnm:Cell Row="35" Col="1" ValueType="40">32</gnm:Cell>
+ <gnm:Cell Row="35" Col="2" ValueType="60">PA7/RTS0/PWM3</gnm:Cell>
+ <gnm:Cell Row="35" Col="3" ValueType="60">PA7</gnm:Cell>
+ <gnm:Cell Row="35" Col="4" ValueType="60">RST_SIM</gnm:Cell>
+ <gnm:Cell Row="35" Col="5" ValueType="60">PA7</gnm:Cell>
+ <gnm:Cell Row="35" Col="6" ValueType="60">!ST_USIM2_RST</gnm:Cell>
+ <gnm:Cell Row="35" Col="7" ValueType="60">PA7</gnm:Cell>
+ <gnm:Cell Row="35" Col="8" ValueType="60">!ST_USIM2_RST</gnm:Cell>
+ <gnm:Cell Row="35" Col="11" ValueType="60">PA7</gnm:Cell>
+ <gnm:Cell Row="35" Col="12" ValueType="60">!ST_UART2_RST</gnm:Cell>
+ <gnm:Cell Row="36" Col="0" ValueType="40">25</gnm:Cell>
+ <gnm:Cell Row="36" Col="1" ValueType="40">33</gnm:Cell>
+ <gnm:Cell Row="36" Col="2" ValueType="60">TDI</gnm:Cell>
+ <gnm:Cell Row="36" Col="5" ValueType="60">TDI</gnm:Cell>
+ <gnm:Cell Row="36" Col="6" ValueType="60">SIMTRACE12_TDI</gnm:Cell>
+ <gnm:Cell Row="36" Col="11" ValueType="60">TDI</gnm:Cell>
+ <gnm:Cell Row="37" Col="0" ValueType="40">26</gnm:Cell>
+ <gnm:Cell Row="37" Col="1" ValueType="40">34</gnm:Cell>
+ <gnm:Cell Row="37" Col="2" ValueType="60">PA6/TXD0/PCK0</gnm:Cell>
+ <gnm:Cell Row="37" Col="4" ValueType="60">I/O_SIM</gnm:Cell>
+ <gnm:Cell Row="37" Col="5" ValueType="60">TXD0</gnm:Cell>
+ <gnm:Cell Row="37" Col="6" ValueType="60">ST_USIM2_IO</gnm:Cell>
+ <gnm:Cell Row="37" Col="7" ValueType="60">TXD0</gnm:Cell>
+ <gnm:Cell Row="37" Col="8" ValueType="60">ST_USIM2_IO</gnm:Cell>
+ <gnm:Cell Row="37" Col="11" ValueType="60">TXD0</gnm:Cell>
+ <gnm:Cell Row="37" Col="12" ValueType="60">ST_UART2_IO</gnm:Cell>
+ <gnm:Cell Row="38" Col="0" ValueType="40">27</gnm:Cell>
+ <gnm:Cell Row="38" Col="1" ValueType="40">35</gnm:Cell>
+ <gnm:Cell Row="38" Col="2" ValueType="60">PA5/RXD0/NPCS3</gnm:Cell>
+ <gnm:Cell Row="38" Col="3" ValueType="60">PA5</gnm:Cell>
+ <gnm:Cell Row="38" Col="4" ValueType="60">SIM_PWEN</gnm:Cell>
+ <gnm:Cell Row="38" Col="5" ValueType="60">RXD0</gnm:Cell>
+ <gnm:Cell Row="38" Col="6" ValueType="60">ST_USIM2_IO</gnm:Cell>
+ <gnm:Cell Row="38" Col="7" ValueType="60">RXD0</gnm:Cell>
+ <gnm:Cell Row="38" Col="8" ValueType="60">ST_USIM2_IO</gnm:Cell>
+ <gnm:Cell Row="38" Col="11" ValueType="60">RXD0</gnm:Cell>
+ <gnm:Cell Row="38" Col="12" ValueType="60">ST_UART2_IO</gnm:Cell>
+ <gnm:Cell Row="39" Col="0" ValueType="40">28</gnm:Cell>
+ <gnm:Cell Row="39" Col="1" ValueType="40">36</gnm:Cell>
+ <gnm:Cell Row="39" Col="2" ValueType="60">PA4/TWCK/TCLK0</gnm:Cell>
+ <gnm:Cell Row="39" Col="3" ValueType="60">TCLK0</gnm:Cell>
+ <gnm:Cell Row="39" Col="4" ValueType="60">CLK_SIM</gnm:Cell>
+ <gnm:Cell Row="39" Col="5" ValueType="60">TCLK0</gnm:Cell>
+ <gnm:Cell Row="39" Col="6" ValueType="60">ST_USIM2_CLK</gnm:Cell>
+ <gnm:Cell Row="39" Col="7" ValueType="60">TCLK0</gnm:Cell>
+ <gnm:Cell Row="39" Col="8" ValueType="60">ST_USIM2_CLK</gnm:Cell>
+ <gnm:Cell Row="39" Col="9" ValueType="60">TWCK</gnm:Cell>
+ <gnm:Cell Row="39" Col="11" ValueType="60">TCLK0</gnm:Cell>
+ <gnm:Cell Row="39" Col="12" ValueType="60">ST_UART2_CLK</gnm:Cell>
+ <gnm:Cell Row="40" Col="1" ValueType="40">37</gnm:Cell>
+ <gnm:Cell Row="40" Col="2" ValueType="60">PA27/DTR1/TIOB2</gnm:Cell>
<gnm:Cell Row="40" Col="3" ValueType="60">NC</gnm:Cell>
- <gnm:Cell Row="40" Col="4" ValueType="60">TIOB2</gnm:Cell>
- <gnm:Cell Row="40" Col="5" ValueType="60">ST_USIM1_IO</gnm:Cell>
- <gnm:Cell Row="40" Col="6" ValueType="60">TIOB2</gnm:Cell>
- <gnm:Cell Row="40" Col="7" ValueType="60">ST_USIM1_IO</gnm:Cell>
- <gnm:Cell Row="41" Col="0" ValueType="40">38</gnm:Cell>
- <gnm:Cell Row="41" Col="1" ValueType="60">PA28/DSR1/TCLK1</gnm:Cell>
- <gnm:Cell Row="41" Col="2" ValueType="60">TCLK1</gnm:Cell>
- <gnm:Cell Row="41" Col="3" ValueType="60">CLK_PHONE</gnm:Cell>
- <gnm:Cell Row="41" Col="4" ValueType="60">PA28</gnm:Cell>
- <gnm:Cell Row="41" Col="5" ValueType="60">!CONNET_ST_USIM2</gnm:Cell>
- <gnm:Cell Row="41" Col="7" ValueType="60">NC</gnm:Cell>
- <gnm:Cell Row="42" Col="0" ValueType="40">39</gnm:Cell>
- <gnm:Cell Row="42" Col="1" ValueType="60">!RST</gnm:Cell>
+ <gnm:Cell Row="40" Col="4" ValueType="60">NC</gnm:Cell>
+ <gnm:Cell Row="40" Col="5" ValueType="60">TIOB2</gnm:Cell>
+ <gnm:Cell Row="40" Col="6" ValueType="60">ST_USIM1_IO</gnm:Cell>
+ <gnm:Cell Row="40" Col="7" ValueType="60">TIOB2</gnm:Cell>
+ <gnm:Cell Row="40" Col="8" ValueType="60">ST_USIM1_IO</gnm:Cell>
+ <gnm:Cell Row="40" Col="11" ValueType="60">TIOB2</gnm:Cell>
+ <gnm:Cell Row="40" Col="12" ValueType="60">ST_UART1_IO</gnm:Cell>
+ <gnm:Cell Row="41" Col="1" ValueType="40">38</gnm:Cell>
+ <gnm:Cell Row="41" Col="2" ValueType="60">PA28/DSR1/TCLK1</gnm:Cell>
+ <gnm:Cell Row="41" Col="3" ValueType="60">TCLK1</gnm:Cell>
+ <gnm:Cell Row="41" Col="4" ValueType="60">CLK_PHONE</gnm:Cell>
+ <gnm:Cell Row="41" Col="5" ValueType="60">PA28</gnm:Cell>
+ <gnm:Cell Row="41" Col="6" ValueType="60">!CONNET_ST_USIM2</gnm:Cell>
+ <gnm:Cell Row="41" Col="8" ValueType="60">NC</gnm:Cell>
+ <gnm:Cell Row="41" Col="11" ValueType="60">PA28</gnm:Cell>
+ <gnm:Cell Row="41" Col="12" ValueType="60">!CONNECT_UART2</gnm:Cell>
+ <gnm:Cell Row="42" Col="0" ValueType="40">29</gnm:Cell>
+ <gnm:Cell Row="42" Col="1" ValueType="40">39</gnm:Cell>
<gnm:Cell Row="42" Col="2" ValueType="60">!RST</gnm:Cell>
<gnm:Cell Row="42" Col="3" ValueType="60">!RST</gnm:Cell>
<gnm:Cell Row="42" Col="4" ValueType="60">!RST</gnm:Cell>
- <gnm:Cell Row="42" Col="5" ValueType="60">!SIMTRACE12_RESET</gnm:Cell>
- <gnm:Cell Row="43" Col="0" ValueType="40">40</gnm:Cell>
- <gnm:Cell Row="43" Col="1" ValueType="60">TST</gnm:Cell>
- <gnm:Cell Row="43" Col="4" ValueType="60">TST</gnm:Cell>
- <gnm:Cell Row="44" Col="0" ValueType="40">41</gnm:Cell>
- <gnm:Cell Row="44" Col="1" ValueType="60">PA29/RI1/TCLK2</gnm:Cell>
- <gnm:Cell Row="44" Col="2" ValueType="60">PA29</gnm:Cell>
- <gnm:Cell Row="44" Col="3" ValueType="60">A-B-DETECT</gnm:Cell>
- <gnm:Cell Row="44" Col="4" ValueType="60">TCLK2</gnm:Cell>
- <gnm:Cell Row="44" Col="5" ValueType="60">ST_USIM1_CLK</gnm:Cell>
- <gnm:Cell Row="44" Col="6" ValueType="60">TCLK2</gnm:Cell>
- <gnm:Cell Row="44" Col="7" ValueType="60">ST_USIM1_CLK</gnm:Cell>
- <gnm:Cell Row="45" Col="0" ValueType="40">42</gnm:Cell>
- <gnm:Cell Row="45" Col="1" ValueType="60">PA30/IRQ1/NPCS2</gnm:Cell>
- <gnm:Cell Row="45" Col="2" ValueType="60">NC</gnm:Cell>
+ <gnm:Cell Row="42" Col="5" ValueType="60">!RST</gnm:Cell>
+ <gnm:Cell Row="42" Col="6" ValueType="60">!SIMTRACE12_RESET</gnm:Cell>
+ <gnm:Cell Row="43" Col="0" ValueType="40">30</gnm:Cell>
+ <gnm:Cell Row="43" Col="1" ValueType="40">40</gnm:Cell>
+ <gnm:Cell Row="43" Col="2" ValueType="60">TST</gnm:Cell>
+ <gnm:Cell Row="43" Col="5" ValueType="60">TST</gnm:Cell>
+ <gnm:Cell Row="44" Col="1" ValueType="40">41</gnm:Cell>
+ <gnm:Cell Row="44" Col="2" ValueType="60">PA29/RI1/TCLK2</gnm:Cell>
+ <gnm:Cell Row="44" Col="3" ValueType="60">PA29</gnm:Cell>
+ <gnm:Cell Row="44" Col="4" ValueType="60">A-B-DETECT</gnm:Cell>
+ <gnm:Cell Row="44" Col="5" ValueType="60">TCLK2</gnm:Cell>
+ <gnm:Cell Row="44" Col="6" ValueType="60">ST_USIM1_CLK</gnm:Cell>
+ <gnm:Cell Row="44" Col="7" ValueType="60">TCLK2</gnm:Cell>
+ <gnm:Cell Row="44" Col="8" ValueType="60">ST_USIM1_CLK</gnm:Cell>
+ <gnm:Cell Row="44" Col="11" ValueType="60">TCLK2</gnm:Cell>
+ <gnm:Cell Row="44" Col="12" ValueType="60">ST_UART1_CLK</gnm:Cell>
+ <gnm:Cell Row="45" Col="1" ValueType="40">42</gnm:Cell>
+ <gnm:Cell Row="45" Col="2" ValueType="60">PA30/IRQ1/NPCS2</gnm:Cell>
<gnm:Cell Row="45" Col="3" ValueType="60">NC</gnm:Cell>
- <gnm:Cell Row="45" Col="4" ValueType="60">PA30</gnm:Cell>
- <gnm:Cell Row="45" Col="5" ValueType="60">SDA</gnm:Cell>
- <gnm:Cell Row="45" Col="7" ValueType="60">NC</gnm:Cell>
- <gnm:Cell Row="46" Col="0" ValueType="40">43</gnm:Cell>
- <gnm:Cell Row="46" Col="1" ValueType="60">PA3/TWD/NPCS3</gnm:Cell>
- <gnm:Cell Row="46" Col="2" ValueType="60">NC</gnm:Cell>
+ <gnm:Cell Row="45" Col="4" ValueType="60">NC</gnm:Cell>
+ <gnm:Cell Row="45" Col="5" ValueType="60">PA30</gnm:Cell>
+ <gnm:Cell Row="45" Col="6" ValueType="60">SDA</gnm:Cell>
+ <gnm:Cell Row="45" Col="8" ValueType="60">NC</gnm:Cell>
+ <gnm:Cell Row="45" Col="11" ValueType="60">NC</gnm:Cell>
+ <gnm:Cell Row="46" Col="0" ValueType="40">31</gnm:Cell>
+ <gnm:Cell Row="46" Col="1" ValueType="40">43</gnm:Cell>
+ <gnm:Cell Row="46" Col="2" ValueType="60">PA3/TWD/NPCS3</gnm:Cell>
<gnm:Cell Row="46" Col="3" ValueType="60">NC</gnm:Cell>
<gnm:Cell Row="46" Col="4" ValueType="60">NC</gnm:Cell>
<gnm:Cell Row="46" Col="5" ValueType="60">NC</gnm:Cell>
- <gnm:Cell Row="46" Col="7" ValueType="60">NC</gnm:Cell>
- <gnm:Cell Row="46" Col="8" ValueType="60">TWD</gnm:Cell>
- <gnm:Cell Row="47" Col="0" ValueType="40">44</gnm:Cell>
- <gnm:Cell Row="47" Col="1" ValueType="60">PA2/PWM2/SCK0</gnm:Cell>
- <gnm:Cell Row="47" Col="2" ValueType="60">SCK0</gnm:Cell>
- <gnm:Cell Row="47" Col="3" ValueType="60">CLK_SIM</gnm:Cell>
- <gnm:Cell Row="47" Col="4" ValueType="60">SCK0</gnm:Cell>
- <gnm:Cell Row="47" Col="5" ValueType="60">ST_USIM2_CLK</gnm:Cell>
- <gnm:Cell Row="47" Col="6" ValueType="60">SCK0</gnm:Cell>
- <gnm:Cell Row="47" Col="7" ValueType="60">ST_USIM2_CLK</gnm:Cell>
- <gnm:Cell Row="48" Col="0" ValueType="40">45</gnm:Cell>
- <gnm:Cell Row="48" Col="1" ValueType="60">VDDIO</gnm:Cell>
- <gnm:Cell Row="49" Col="0" ValueType="40">46</gnm:Cell>
- <gnm:Cell Row="49" Col="1" ValueType="60">GND</gnm:Cell>
- <gnm:Cell Row="50" Col="0" ValueType="40">47</gnm:Cell>
- <gnm:Cell Row="50" Col="1" ValueType="60">PA1/PWM1/TIOB0</gnm:Cell>
- <gnm:Cell Row="50" Col="2" ValueType="60">TIOB0</gnm:Cell>
- <gnm:Cell Row="50" Col="3" ValueType="60">I/O_SIM</gnm:Cell>
- <gnm:Cell Row="50" Col="4" ValueType="60">TIOB0</gnm:Cell>
- <gnm:Cell Row="50" Col="5" ValueType="60">ST_USIM2_IO</gnm:Cell>
- <gnm:Cell Row="50" Col="6" ValueType="60">TIOB0</gnm:Cell>
- <gnm:Cell Row="50" Col="7" ValueType="60">ST_USIM2_IO</gnm:Cell>
- <gnm:Cell Row="51" Col="0" ValueType="40">48</gnm:Cell>
- <gnm:Cell Row="51" Col="1" ValueType="60">PA0/PWM0/TIOA0</gnm:Cell>
- <gnm:Cell Row="51" Col="2" ValueType="60">NC</gnm:Cell>
+ <gnm:Cell Row="46" Col="6" ValueType="60">NC</gnm:Cell>
+ <gnm:Cell Row="46" Col="8" ValueType="60">NC</gnm:Cell>
+ <gnm:Cell Row="46" Col="9" ValueType="60">TWD</gnm:Cell>
+ <gnm:Cell Row="46" Col="11" ValueType="60">NC</gnm:Cell>
+ <gnm:Cell Row="47" Col="0" ValueType="40">32</gnm:Cell>
+ <gnm:Cell Row="47" Col="1" ValueType="40">44</gnm:Cell>
+ <gnm:Cell Row="47" Col="2" ValueType="60">PA2/PWM2/SCK0</gnm:Cell>
+ <gnm:Cell Row="47" Col="3" ValueType="60">SCK0</gnm:Cell>
+ <gnm:Cell Row="47" Col="4" ValueType="60">CLK_SIM</gnm:Cell>
+ <gnm:Cell Row="47" Col="5" ValueType="60">SCK0</gnm:Cell>
+ <gnm:Cell Row="47" Col="6" ValueType="60">ST_USIM2_CLK</gnm:Cell>
+ <gnm:Cell Row="47" Col="7" ValueType="60">SCK0</gnm:Cell>
+ <gnm:Cell Row="47" Col="8" ValueType="60">ST_USIM2_CLK</gnm:Cell>
+ <gnm:Cell Row="47" Col="11" ValueType="60">SCK0</gnm:Cell>
+ <gnm:Cell Row="47" Col="12" ValueType="60">ST_UART2_CLK</gnm:Cell>
+ <gnm:Cell Row="48" Col="0" ValueType="40">33</gnm:Cell>
+ <gnm:Cell Row="48" Col="1" ValueType="40">45</gnm:Cell>
+ <gnm:Cell Row="48" Col="2" ValueType="60">VDDIO</gnm:Cell>
+ <gnm:Cell Row="49" Col="0" ValueType="40">34</gnm:Cell>
+ <gnm:Cell Row="49" Col="1" ValueType="40">46</gnm:Cell>
+ <gnm:Cell Row="49" Col="2" ValueType="60">GND</gnm:Cell>
+ <gnm:Cell Row="50" Col="0" ValueType="40">35</gnm:Cell>
+ <gnm:Cell Row="50" Col="1" ValueType="40">47</gnm:Cell>
+ <gnm:Cell Row="50" Col="2" ValueType="60">PA1/PWM1/TIOB0</gnm:Cell>
+ <gnm:Cell Row="50" Col="3" ValueType="60">TIOB0</gnm:Cell>
+ <gnm:Cell Row="50" Col="4" ValueType="60">I/O_SIM</gnm:Cell>
+ <gnm:Cell Row="50" Col="5" ValueType="60">TIOB0</gnm:Cell>
+ <gnm:Cell Row="50" Col="6" ValueType="60">ST_USIM2_IO</gnm:Cell>
+ <gnm:Cell Row="50" Col="7" ValueType="60">TIOB0</gnm:Cell>
+ <gnm:Cell Row="50" Col="8" ValueType="60">ST_USIM2_IO</gnm:Cell>
+ <gnm:Cell Row="50" Col="11" ValueType="60">TIOB0</gnm:Cell>
+ <gnm:Cell Row="50" Col="12" ValueType="60">ST_UART2_IO</gnm:Cell>
+ <gnm:Cell Row="51" Col="0" ValueType="40">36</gnm:Cell>
+ <gnm:Cell Row="51" Col="1" ValueType="40">48</gnm:Cell>
+ <gnm:Cell Row="51" Col="2" ValueType="60">PA0/PWM0/TIOA0</gnm:Cell>
<gnm:Cell Row="51" Col="3" ValueType="60">NC</gnm:Cell>
- <gnm:Cell Row="51" Col="4" ValueType="60">PA0</gnm:Cell>
- <gnm:Cell Row="51" Col="5" ValueType="60">_SIMTRACE34_RESET</gnm:Cell>
- <gnm:Cell Row="51" Col="7" ValueType="60">NC</gnm:Cell>
- <gnm:Cell Row="52" Col="0" ValueType="40">49</gnm:Cell>
- <gnm:Cell Row="52" Col="1" ValueType="60">TDO</gnm:Cell>
+ <gnm:Cell Row="51" Col="4" ValueType="60">NC</gnm:Cell>
+ <gnm:Cell Row="51" Col="5" ValueType="60">PA0</gnm:Cell>
+ <gnm:Cell Row="51" Col="6" ValueType="60">_SIMTRACE34_RESET</gnm:Cell>
+ <gnm:Cell Row="51" Col="8" ValueType="60">NC</gnm:Cell>
+ <gnm:Cell Row="51" Col="11" ValueType="60">PA0</gnm:Cell>
+ <gnm:Cell Row="51" Col="12" ValueType="60">!CONNECT_MDM_SIM</gnm:Cell>
+ <gnm:Cell Row="52" Col="0" ValueType="40">37</gnm:Cell>
+ <gnm:Cell Row="52" Col="1" ValueType="40">49</gnm:Cell>
<gnm:Cell Row="52" Col="2" ValueType="60">TDO</gnm:Cell>
- <gnm:Cell Row="52" Col="4" ValueType="60">TDO</gnm:Cell>
- <gnm:Cell Row="52" Col="5" ValueType="60">SIMTRACE12_TDO</gnm:Cell>
- <gnm:Cell Row="52" Col="6" ValueType="60">TDO</gnm:Cell>
- <gnm:Cell Row="52" Col="7" ValueType="60">SIMTRACE_TDO</gnm:Cell>
- <gnm:Cell Row="53" Col="0" ValueType="40">50</gnm:Cell>
- <gnm:Cell Row="53" Col="1" ValueType="60">JTAGSEL</gnm:Cell>
+ <gnm:Cell Row="52" Col="3" ValueType="60">TDO</gnm:Cell>
+ <gnm:Cell Row="52" Col="5" ValueType="60">TDO</gnm:Cell>
+ <gnm:Cell Row="52" Col="6" ValueType="60">SIMTRACE12_TDO</gnm:Cell>
+ <gnm:Cell Row="52" Col="7" ValueType="60">TDO</gnm:Cell>
+ <gnm:Cell Row="52" Col="8" ValueType="60">SIMTRACE_TDO</gnm:Cell>
+ <gnm:Cell Row="52" Col="11" ValueType="60">TDO</gnm:Cell>
+ <gnm:Cell Row="53" Col="0" ValueType="40">38</gnm:Cell>
+ <gnm:Cell Row="53" Col="1" ValueType="40">50</gnm:Cell>
<gnm:Cell Row="53" Col="2" ValueType="60">JTAGSEL</gnm:Cell>
- <gnm:Cell Row="53" Col="4" ValueType="60">JTAGSEL</gnm:Cell>
- <gnm:Cell Row="53" Col="5" ValueType="60">GND</gnm:Cell>
- <gnm:Cell Row="54" Col="0" ValueType="40">51</gnm:Cell>
- <gnm:Cell Row="54" Col="1" ValueType="60">TMS</gnm:Cell>
+ <gnm:Cell Row="53" Col="3" ValueType="60">JTAGSEL</gnm:Cell>
+ <gnm:Cell Row="53" Col="5" ValueType="60">JTAGSEL</gnm:Cell>
+ <gnm:Cell Row="53" Col="6" ValueType="60">GND</gnm:Cell>
+ <gnm:Cell Row="53" Col="11" ValueType="60">JTAGSEL</gnm:Cell>
+ <gnm:Cell Row="54" Col="0" ValueType="40">39</gnm:Cell>
+ <gnm:Cell Row="54" Col="1" ValueType="40">51</gnm:Cell>
<gnm:Cell Row="54" Col="2" ValueType="60">TMS</gnm:Cell>
- <gnm:Cell Row="54" Col="4" ValueType="60">TMS</gnm:Cell>
- <gnm:Cell Row="54" Col="5" ValueType="60">SIMTRACE12_TMS</gnm:Cell>
- <gnm:Cell Row="54" Col="6" ValueType="60">TMS</gnm:Cell>
- <gnm:Cell Row="54" Col="7" ValueType="60">SIMTRACE_TMS</gnm:Cell>
- <gnm:Cell Row="55" Col="0" ValueType="40">52</gnm:Cell>
- <gnm:Cell Row="55" Col="1" ValueType="60">PA31/NPCS1/PCK2</gnm:Cell>
- <gnm:Cell Row="55" Col="2" ValueType="60">PA31</gnm:Cell>
- <gnm:Cell Row="55" Col="3" ValueType="60">BOTLOADER_SW</gnm:Cell>
- <gnm:Cell Row="55" Col="4" ValueType="60">PA31</gnm:Cell>
- <gnm:Cell Row="55" Col="5" ValueType="60">SCL</gnm:Cell>
- <gnm:Cell Row="55" Col="8" ValueType="60">NPCS1</gnm:Cell>
- <gnm:Cell Row="56" Col="0" ValueType="40">53</gnm:Cell>
- <gnm:Cell Row="56" Col="1" ValueType="60">TCK</gnm:Cell>
+ <gnm:Cell Row="54" Col="3" ValueType="60">TMS</gnm:Cell>
+ <gnm:Cell Row="54" Col="5" ValueType="60">TMS</gnm:Cell>
+ <gnm:Cell Row="54" Col="6" ValueType="60">SIMTRACE12_TMS</gnm:Cell>
+ <gnm:Cell Row="54" Col="7" ValueType="60">TMS</gnm:Cell>
+ <gnm:Cell Row="54" Col="8" ValueType="60">SIMTRACE_TMS</gnm:Cell>
+ <gnm:Cell Row="54" Col="11" ValueType="60">TMS</gnm:Cell>
+ <gnm:Cell Row="55" Col="1" ValueType="40">52</gnm:Cell>
+ <gnm:Cell Row="55" Col="2" ValueType="60">PA31/NPCS1/PCK2</gnm:Cell>
+ <gnm:Cell Row="55" Col="3" ValueType="60">PA31</gnm:Cell>
+ <gnm:Cell Row="55" Col="4" ValueType="60">BOTLOADER_SW</gnm:Cell>
+ <gnm:Cell Row="55" Col="5" ValueType="60">PA31</gnm:Cell>
+ <gnm:Cell Row="55" Col="6" ValueType="60">SCL</gnm:Cell>
+ <gnm:Cell Row="55" Col="9" ValueType="60">NPCS1</gnm:Cell>
+ <gnm:Cell Row="55" Col="11" ValueType="60">NC</gnm:Cell>
+ <gnm:Cell Row="56" Col="0" ValueType="40">40</gnm:Cell>
+ <gnm:Cell Row="56" Col="1" ValueType="40">53</gnm:Cell>
<gnm:Cell Row="56" Col="2" ValueType="60">TCK</gnm:Cell>
- <gnm:Cell Row="56" Col="4" ValueType="60">TCK</gnm:Cell>
- <gnm:Cell Row="56" Col="5" ValueType="60">SIMTRACE_TCK</gnm:Cell>
- <gnm:Cell Row="57" Col="0" ValueType="40">54</gnm:Cell>
- <gnm:Cell Row="57" Col="1" ValueType="60">VDDCORE</gnm:Cell>
- <gnm:Cell Row="58" Col="0" ValueType="40">55</gnm:Cell>
- <gnm:Cell Row="58" Col="1" ValueType="60">PB12/ERASE</gnm:Cell>
- <gnm:Cell Row="58" Col="2" ValueType="60">ERASE</gnm:Cell>
- <gnm:Cell Row="58" Col="4" ValueType="60">ERASE</gnm:Cell>
- <gnm:Cell Row="58" Col="5" ValueType="60">SIMTRACE12_ERASE</gnm:Cell>
- <gnm:Cell Row="59" Col="0" ValueType="40">56</gnm:Cell>
- <gnm:Cell Row="59" Col="1" ValueType="60">DDM</gnm:Cell>
- <gnm:Cell Row="59" Col="4" ValueType="60">DDM</gnm:Cell>
- <gnm:Cell Row="60" Col="0" ValueType="40">57</gnm:Cell>
- <gnm:Cell Row="60" Col="1" ValueType="60">DDP</gnm:Cell>
- <gnm:Cell Row="60" Col="4" ValueType="60">DDN</gnm:Cell>
- <gnm:Cell Row="61" Col="0" ValueType="40">58</gnm:Cell>
- <gnm:Cell Row="61" Col="1" ValueType="60">VDDIO</gnm:Cell>
- <gnm:Cell Row="62" Col="0" ValueType="40">59</gnm:Cell>
- <gnm:Cell Row="62" Col="1" ValueType="60">PB13/VDDFLASH</gnm:Cell>
- <gnm:Cell Row="62" Col="4" ValueType="60">NC</gnm:Cell>
+ <gnm:Cell Row="56" Col="3" ValueType="60">TCK</gnm:Cell>
+ <gnm:Cell Row="56" Col="5" ValueType="60">TCK</gnm:Cell>
+ <gnm:Cell Row="56" Col="6" ValueType="60">SIMTRACE_TCK</gnm:Cell>
+ <gnm:Cell Row="56" Col="11" ValueType="60">TCK</gnm:Cell>
+ <gnm:Cell Row="57" Col="0" ValueType="40">41</gnm:Cell>
+ <gnm:Cell Row="57" Col="1" ValueType="40">54</gnm:Cell>
+ <gnm:Cell Row="57" Col="2" ValueType="60">VDDCORE</gnm:Cell>
+ <gnm:Cell Row="58" Col="0" ValueType="40">42</gnm:Cell>
+ <gnm:Cell Row="58" Col="1" ValueType="40">55</gnm:Cell>
+ <gnm:Cell Row="58" Col="2" ValueType="60">PB12/ERASE</gnm:Cell>
+ <gnm:Cell Row="58" Col="3" ValueType="60">ERASE</gnm:Cell>
+ <gnm:Cell Row="58" Col="5" ValueType="60">ERASE</gnm:Cell>
+ <gnm:Cell Row="58" Col="6" ValueType="60">SIMTRACE12_ERASE</gnm:Cell>
+ <gnm:Cell Row="58" Col="11" ValueType="60">ERASE</gnm:Cell>
+ <gnm:Cell Row="59" Col="0" ValueType="40">43</gnm:Cell>
+ <gnm:Cell Row="59" Col="1" ValueType="40">56</gnm:Cell>
+ <gnm:Cell Row="59" Col="2" ValueType="60">DDM</gnm:Cell>
+ <gnm:Cell Row="59" Col="5" ValueType="60">DDM</gnm:Cell>
+ <gnm:Cell Row="60" Col="0" ValueType="40">44</gnm:Cell>
+ <gnm:Cell Row="60" Col="1" ValueType="40">57</gnm:Cell>
+ <gnm:Cell Row="60" Col="2" ValueType="60">DDP</gnm:Cell>
+ <gnm:Cell Row="60" Col="5" ValueType="60">DDN</gnm:Cell>
+ <gnm:Cell Row="61" Col="0" ValueType="40">47</gnm:Cell>
+ <gnm:Cell Row="61" Col="1" ValueType="40">58</gnm:Cell>
+ <gnm:Cell Row="61" Col="2" ValueType="60">VDDIO</gnm:Cell>
+ <gnm:Cell Row="62" Col="1" ValueType="40">59</gnm:Cell>
+ <gnm:Cell Row="62" Col="2" ValueType="60">PB13/VDDFLASH</gnm:Cell>
<gnm:Cell Row="62" Col="5" ValueType="60">NC</gnm:Cell>
- <gnm:Cell Row="63" Col="0" ValueType="40">60</gnm:Cell>
- <gnm:Cell Row="63" Col="1" ValueType="60">GND</gnm:Cell>
- <gnm:Cell Row="64" Col="0" ValueType="40">61</gnm:Cell>
- <gnm:Cell Row="64" Col="1" ValueType="60">XOUT</gnm:Cell>
+ <gnm:Cell Row="62" Col="6" ValueType="60">NC</gnm:Cell>
+ <gnm:Cell Row="62" Col="11" ValueType="60">NC</gnm:Cell>
+ <gnm:Cell Row="63" Col="1" ValueType="40">60</gnm:Cell>
+ <gnm:Cell Row="63" Col="2" ValueType="60">GND</gnm:Cell>
+ <gnm:Cell Row="64" Col="0" ValueType="40">45</gnm:Cell>
+ <gnm:Cell Row="64" Col="1" ValueType="40">61</gnm:Cell>
<gnm:Cell Row="64" Col="2" ValueType="60">XOUT</gnm:Cell>
- <gnm:Cell Row="64" Col="4" ValueType="60">NC</gnm:Cell>
+ <gnm:Cell Row="64" Col="3" ValueType="60">XOUT</gnm:Cell>
<gnm:Cell Row="64" Col="5" ValueType="60">NC</gnm:Cell>
- <gnm:Cell Row="65" Col="0" ValueType="40">62</gnm:Cell>
- <gnm:Cell Row="65" Col="1" ValueType="60">XIN</gnm:Cell>
+ <gnm:Cell Row="64" Col="6" ValueType="60">NC</gnm:Cell>
+ <gnm:Cell Row="64" Col="11" ValueType="60">XOUT</gnm:Cell>
+ <gnm:Cell Row="65" Col="0" ValueType="40">46</gnm:Cell>
+ <gnm:Cell Row="65" Col="1" ValueType="40">62</gnm:Cell>
<gnm:Cell Row="65" Col="2" ValueType="60">XIN</gnm:Cell>
- <gnm:Cell Row="65" Col="4" ValueType="60">XIN</gnm:Cell>
- <gnm:Cell Row="65" Col="5" ValueType="60">ST12_12MHZ</gnm:Cell>
- <gnm:Cell Row="66" Col="0" ValueType="40">63</gnm:Cell>
- <gnm:Cell Row="66" Col="1" ValueType="60">PB14/PLLRC</gnm:Cell>
- <gnm:Cell Row="66" Col="4" ValueType="60">NC</gnm:Cell>
+ <gnm:Cell Row="65" Col="3" ValueType="60">XIN</gnm:Cell>
+ <gnm:Cell Row="65" Col="5" ValueType="60">XIN</gnm:Cell>
+ <gnm:Cell Row="65" Col="6" ValueType="60">ST12_12MHZ</gnm:Cell>
+ <gnm:Cell Row="65" Col="11" ValueType="60">XIN</gnm:Cell>
+ <gnm:Cell Row="66" Col="1" ValueType="40">63</gnm:Cell>
+ <gnm:Cell Row="66" Col="2" ValueType="60">PB14/PLLRC</gnm:Cell>
<gnm:Cell Row="66" Col="5" ValueType="60">NC</gnm:Cell>
- <gnm:Cell Row="67" Col="0" ValueType="40">64</gnm:Cell>
- <gnm:Cell Row="67" Col="1" ValueType="60">VDDPLL</gnm:Cell>
+ <gnm:Cell Row="66" Col="6" ValueType="60">NC</gnm:Cell>
+ <gnm:Cell Row="66" Col="11" ValueType="60">NC</gnm:Cell>
+ <gnm:Cell Row="67" Col="0" ValueType="40">48</gnm:Cell>
+ <gnm:Cell Row="67" Col="1" ValueType="40">64</gnm:Cell>
+ <gnm:Cell Row="67" Col="2" ValueType="60">VDDPLL</gnm:Cell>
</gnm:Cells>
+ <gnm:MergedRegions>
+ <gnm:Merge>L3:M3</gnm:Merge>
+ </gnm:MergedRegions>
<gnm:SheetLayout TopLeft="A1"/>
<gnm:Solver ModelType="0" ProblemType="0" MaxTime="60" MaxIter="1000" NonNeg="1" Discr="0" AutoScale="0" ProgramR="0" SensitivityR="0"/>
</gnm:Sheet>
diff --git a/host/.gitignore b/host/.gitignore
new file mode 100644
index 0000000..f9841ab
--- /dev/null
+++ b/host/.gitignore
@@ -0,0 +1,37 @@
+.o
+*.a
+*.lo
+*.la
+.deps
+Makefile
+Makefile.in
+
+#configure
+aclocal.m4
+autom4te.cache/
+compile
+config.guess
+config.log
+config.status
+config.sub
+configure
+configure.lineno
+depcomp
+install-sh
+missing
+stamp-h1
+m4
+
+#libtool
+ltmain.sh
+libtool
+.libs
+
+.tarball-version
+.version
+
+*.pc
+
+simtrace2-list
+simtrace2-sniff
+simtrace2-cardem-pcsc
diff --git a/host/COPYING b/host/COPYING
new file mode 100644
index 0000000..d159169
--- /dev/null
+++ b/host/COPYING
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program 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 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
diff --git a/host/Makefile b/host/Makefile
deleted file mode 100644
index aee399c..0000000
--- a/host/Makefile
+++ /dev/null
@@ -1,28 +0,0 @@
-LDFLAGS+=`pkg-config --libs libusb-1.0 libosmocore` -pthread
-CFLAGS=-Wall -g
-
-APPS=simtrace2-remsim simtrace2-remsim-usb2udp simtrace2-list simtrace2-sniff
-
-all: $(APPS)
-
-simtrace2-remsim: simtrace2-remsim.o apdu_dispatch.o simtrace2-discovery.o libusb_util.o
- $(CC) -o $@ $^ $(LDFLAGS) `pkg-config --libs libosmosim libpcsclite`
-
-simtrace2-remsim-usb2udp: usb2udp.o simtrace2-discovery.o
- $(CC) -o $@ $^ $(LDFLAGS)
-
-simtrace2-list: simtrace2_usb.o libusb_util.o
- $(CC) -o $@ $^ $(LDFLAGS)
-
-simtrace2-sniff: simtrace2-sniff.o simtrace2-discovery.o libusb_util.o
- $(CC) -o $@ $^ $(LDFLAGS)
-
-%.o: %.c
- $(CC) $(CFLAGS) `pkg-config --cflags libusb-1.0 libosmocore` -o $@ -c $^
-
-clean:
- @rm -f *.o $(APPS)
-
-install: $(APPS)
- mkdir -p $(DESTDIR)/usr/bin
- cp $(APPS) $(DESTDIR)/usr/bin/
diff --git a/host/Makefile.am b/host/Makefile.am
new file mode 100644
index 0000000..338a46b
--- /dev/null
+++ b/host/Makefile.am
@@ -0,0 +1,17 @@
+AUTOMAKE_OPTIONS = foreign dist-bzip2 1.6
+
+AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include
+SUBDIRS = include lib src contrib #tests examples doc
+
+EXTRA_DIST = .version
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = libosmo-simtrace2.pc
+
+@RELMAKE@
+
+BUILT_SOURCES = $(top_srcdir)/.version
+$(top_srcdir)/.version:
+ echo $(VERSION) > $@-t && mv $@-t $@
+dist-hook:
+ echo $(VERSION) > $(distdir)/.tarball-version
diff --git a/host/configure.ac b/host/configure.ac
new file mode 100644
index 0000000..8ba9930
--- /dev/null
+++ b/host/configure.ac
@@ -0,0 +1,104 @@
+AC_INIT([simtrace2],
+ m4_esyscmd([../git-version-gen ../.tarball-version]),
+ [simtrace@lists.osmocom.org])
+
+dnl *This* is the root dir, even if an install-sh exists in ../ or ../../
+AC_CONFIG_AUX_DIR([.])
+
+AM_INIT_AUTOMAKE([foreign dist-bzip2 no-dist-gzip 1.6 subdir-objects])
+AC_CONFIG_TESTDIR(tests)
+
+dnl kernel style compile messages
+m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
+
+dnl include release helper
+RELMAKE='-include osmo-release.mk'
+AC_SUBST([RELMAKE])
+
+dnl checks for programs
+AC_PROG_MAKE_SET
+AC_PROG_CC
+AC_PROG_INSTALL
+LT_INIT([pic-only])
+
+dnl check for pkg-config (explained in detail in libosmocore/configure.ac)
+AC_PATH_PROG(PKG_CONFIG_INSTALLED, pkg-config, no)
+if test "x$PKG_CONFIG_INSTALLED" = "xno"; then
+ AC_MSG_WARN([You need to install pkg-config])
+fi
+PKG_PROG_PKG_CONFIG([0.20])
+
+AC_CONFIG_MACRO_DIR([m4])
+
+CFLAGS="$CFLAGS -Wall"
+CPPFLAGS="$CPPFLAGS -Wall"
+
+AC_ARG_ENABLE(sanitize,
+ [AS_HELP_STRING(
+ [--enable-sanitize],
+ [Compile with address sanitizer enabled],
+ )],
+ [sanitize=$enableval], [sanitize="no"])
+if test x"$sanitize" = x"yes"
+then
+ CFLAGS="$CFLAGS -fsanitize=address -fsanitize=undefined"
+ CPPFLAGS="$CPPFLAGS -fsanitize=address -fsanitize=undefined"
+fi
+
+# The following test is taken from WebKit's webkit.m4
+saved_CFLAGS="$CFLAGS"
+CFLAGS="$CFLAGS -fvisibility=hidden "
+AC_MSG_CHECKING([if ${CC} supports -fvisibility=hidden])
+AC_COMPILE_IFELSE([AC_LANG_SOURCE([char foo;])],
+ [ AC_MSG_RESULT([yes])
+ SYMBOL_VISIBILITY="-fvisibility=hidden"],
+ AC_MSG_RESULT([no]))
+CFLAGS="$saved_CFLAGS"
+AC_SUBST(SYMBOL_VISIBILITY)
+
+PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 1.4.0)
+PKG_CHECK_MODULES(LIBOSMOSIM, libosmosim >= 1.4.0)
+PKG_CHECK_MODULES(LIBOSMOUSB, libosmousb >= 1.4.0)
+PKG_CHECK_MODULES(LIBUSB, libusb-1.0)
+
+AC_ARG_ENABLE(sanitize,
+ [AS_HELP_STRING(
+ [--enable-sanitize],
+ [Compile with address sanitizer enabled],
+ )],
+ [sanitize=$enableval], [sanitize="no"])
+if test x"$sanitize" = x"yes"
+then
+ CFLAGS="$CFLAGS -fsanitize=address -fsanitize=undefined"
+ CPPFLAGS="$CPPFLAGS -fsanitize=address -fsanitize=undefined"
+fi
+
+AC_ARG_ENABLE(werror,
+ [AS_HELP_STRING(
+ [--enable-werror],
+ [Turn all compiler warnings into errors, with exceptions:
+ a) deprecation (allow upstream to mark deprecation without breaking builds);
+ b) "#warning" pragmas (allow to remind ourselves of errors without breaking builds)
+ ]
+ )],
+ [werror=$enableval], [werror="no"])
+if test x"$werror" = x"yes"
+then
+ WERROR_FLAGS="-Werror"
+ WERROR_FLAGS+=" -Wno-error=deprecated -Wno-error=deprecated-declarations"
+ WERROR_FLAGS+=" -Wno-error=cpp" # "#warning"
+ CFLAGS="$CFLAGS $WERROR_FLAGS"
+ CPPFLAGS="$CPPFLAGS $WERROR_FLAGS"
+fi
+
+AC_MSG_RESULT([CFLAGS="$CFLAGS"])
+AC_MSG_RESULT([CPPFLAGS="$CPPFLAGS"])
+
+AC_OUTPUT(
+ libosmo-simtrace2.pc
+ include/Makefile
+ src/Makefile
+ lib/Makefile
+ contrib/Makefile
+ contrib/simtrace2.spec
+ Makefile)
diff --git a/host/99-simtrace2.rules b/host/contrib/99-simtrace2.rules
index 4a8b2ea..5ae04e2 100644
--- a/host/99-simtrace2.rules
+++ b/host/contrib/99-simtrace2.rules
@@ -16,6 +16,10 @@ ATTRS{idVendor}=="1d50", ATTRS{idProduct}=="4002", GROUP="plugdev"
# sysmocom QMOD SAM3 (DFU and runtime)
ATTRS{idVendor}=="1d50", ATTRS{idProduct}=="4003", GROUP="plugdev"
ATTRS{idVendor}=="1d50", ATTRS{idProduct}=="4004", GROUP="plugdev"
+# sysmocom OCTSIMTEST
+ATTRS{idVendor}=="1d50", ATTRS{idProduct}=="616d", GROUP="plugdev"
+# ngff-cardem
+ATTRS{idVendor}=="1d50", ATTRS{idProduct}=="616e", GROUP="plugdev"
# All done
LABEL="simtrace2_rules_end"
diff --git a/host/contrib/Makefile.am b/host/contrib/Makefile.am
new file mode 100644
index 0000000..4f11962
--- /dev/null
+++ b/host/contrib/Makefile.am
@@ -0,0 +1 @@
+EXTRA_DIST = 99-simtrace2.rules
diff --git a/host/contrib/simtrace2.spec.in b/host/contrib/simtrace2.spec.in
new file mode 100644
index 0000000..0bc5d2a
--- /dev/null
+++ b/host/contrib/simtrace2.spec.in
@@ -0,0 +1,102 @@
+#
+# spec file for package simtrace2
+#
+# Copyright (c) 2021 SUSE LLC
+# Copyright (c) 2018-2021, Martin Hauke <mardnh@gmx.de>
+#
+# All modifications and additions to the file contributed by third parties
+# remain the property of their copyright owners, unless otherwise agreed
+# upon. The license for this file, and modifications and additions to the
+# file, is the same license as for the pristine package itself (unless the
+# license for the pristine package is not an Open Source License, in which
+# case the license is the MIT License). An "Open Source License" is a
+# license that conforms to the Open Source Definition (Version 1.9)
+# published by the Open Source Initiative.
+
+%define sover 1
+Name: simtrace2
+Version: @VERSION@
+Release: 0
+Summary: Osmocom SIMtrace host utility
+License: GPL-2.0-or-later
+Group: Productivity/Telephony/Utilities
+URL: https://osmocom.org/projects/simtrace2/wiki
+Source: %{name}-%{version}.tar.xz
+BuildRequires: autoconf
+BuildRequires: automake
+BuildRequires: libtool
+BuildRequires: pkgconfig
+BuildRequires: pkgconfig(libosmocore) >= 1.4.0
+BuildRequires: pkgconfig(libosmosim) >= 1.4.0
+BuildRequires: pkgconfig(libosmousb) >= 1.4.0
+BuildRequires: pkgconfig(libpcsclite)
+BuildRequires: pkgconfig(libusb-1.0)
+
+%description
+Osmocom SIMtrace 2 is a software and hardware system for passively
+tracing SIM-ME communication between the SIM card and the mobile phone,
+and remote SIM operation.
+
+This package contains SIMtrace 2 host utility.
+
+%package -n libosmo-simtrace2-%{sover}
+Summary: Driver functions for Osmocom SIMtrace2 and compatible firmware
+Group: System/Libraries
+
+%description -n libosmo-simtrace2-%{sover}
+This library contains core "driver" functionality to interface with the
+Osmocom SIMtrace2 (and compatible) USB device firmware. It enables
+applications to implement SIM card / smart card tracing as well as
+SIM / smart card emulation functions.
+
+%package -n libosmo-simtrace2-devel
+Summary: Development files for the Osmocom SIMtrace2 library
+Group: Development/Libraries/C and C++
+Requires: libosmo-simtrace2-%{sover} = %{version}
+
+%description -n libosmo-simtrace2-devel
+Osmocom SIMtrace2 (and compatible) USB device firmware. It enables
+applications to implement SIM card / smart card tracing as well as
+SIM / smart card emulation functions.
+
+This subpackage contains libraries and header files for developing
+applications that want to make use of libosmo-simtrace2.
+
+%prep
+%setup -q
+
+%build
+cd host
+echo "%{version}" >.tarball-version
+autoreconf -fiv
+%configure --disable-static
+%make_build
+
+%install
+%make_install -C host
+install -Dm0644 host/contrib/99-simtrace2.rules %{buildroot}/%{_udevrulesdir}/99-simtrace2.rules
+find %{buildroot} -type f -name "*.la" -delete -print
+
+%post -n libosmo-simtrace2-%{sover} -p /sbin/ldconfig
+%postun -n libosmo-simtrace2-%{sover} -p /sbin/ldconfig
+
+%files
+%license host/COPYING
+%doc README.md
+%{_bindir}/simtrace2-cardem-pcsc
+%{_bindir}/simtrace2-list
+%{_bindir}/simtrace2-sniff
+%{_bindir}/simtrace2-tool
+%{_udevrulesdir}/99-simtrace2.rules
+
+%files -n libosmo-simtrace2-%{sover}
+%{_libdir}/libosmo-simtrace2.so.%{sover}*
+
+%files -n libosmo-simtrace2-devel
+%dir %{_includedir}/osmocom/
+%dir %{_includedir}/osmocom/simtrace2/
+%{_includedir}/osmocom/simtrace2/*.h
+%{_libdir}/libosmo-simtrace2.so
+%{_libdir}/pkgconfig/libosmo-simtrace2.pc
+
+%changelog
diff --git a/host/include/Makefile.am b/host/include/Makefile.am
new file mode 100644
index 0000000..60134f3
--- /dev/null
+++ b/host/include/Makefile.am
@@ -0,0 +1,8 @@
+nobase_include_HEADERS = \
+ osmocom/simtrace2/apdu_dispatch.h \
+ osmocom/simtrace2/simtrace2_api.h \
+ osmocom/simtrace2/simtrace_usb.h \
+ osmocom/simtrace2/simtrace_prot.h \
+ osmocom/simtrace2/usb_util.h \
+ osmocom/simtrace2/gsmtap.h \
+ $(NULL)
diff --git a/host/apdu_dispatch.h b/host/include/osmocom/simtrace2/apdu_dispatch.h
index 2c99858..62ff762 100644
--- a/host/apdu_dispatch.h
+++ b/host/include/osmocom/simtrace2/apdu_dispatch.h
@@ -1,6 +1,6 @@
/* apdu_dispatch - State machine to determine Rx/Tx phases of APDU
*
- * (C) 2016 by Harald Welte <hwelte@hmw-consulting.de>
+ * (C) 2016-2019 by Harald Welte <hwelte@hmw-consulting.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -11,10 +11,6 @@
* 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 this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#pragma once
@@ -23,7 +19,7 @@
#include <osmocom/sim/sim.h>
-struct apdu_context {
+struct osmo_apdu_context {
struct osim_apdu_cmd_hdr hdr;
uint8_t dc[256];
uint8_t de[256];
@@ -39,11 +35,13 @@ struct apdu_context {
} le;
};
-enum apdu_action {
+enum osmo_apdu_action {
APDU_ACT_TX_CAPDU_TO_CARD = 0x0001,
APDU_ACT_RX_MORE_CAPDU_FROM_READER = 0x0002,
};
+const char *osmo_apdu_dump_context_buf(char *buf, unsigned int buf_len,
+ const struct osmo_apdu_context *ac);
-int apdu_segment_in(struct apdu_context *ac, const uint8_t *apdu_buf,
- unsigned int apdu_len, bool new_apdu);
+int osmo_apdu_segment_in(struct osmo_apdu_context *ac, const uint8_t *apdu_buf,
+ unsigned int apdu_len, bool new_apdu);
diff --git a/host/include/osmocom/simtrace2/gsmtap.h b/host/include/osmocom/simtrace2/gsmtap.h
new file mode 100644
index 0000000..d7184dc
--- /dev/null
+++ b/host/include/osmocom/simtrace2/gsmtap.h
@@ -0,0 +1,6 @@
+#pragma once
+#include <stdint.h>
+#include <osmocom/core/gsmtap.h>
+
+int osmo_st2_gsmtap_init(const char *gsmtap_host);
+int osmo_st2_gsmtap_send_apdu(uint8_t sub_type, const uint8_t *apdu, unsigned int len);
diff --git a/host/include/osmocom/simtrace2/simtrace2_api.h b/host/include/osmocom/simtrace2/simtrace2_api.h
new file mode 100644
index 0000000..d658d16
--- /dev/null
+++ b/host/include/osmocom/simtrace2/simtrace2_api.h
@@ -0,0 +1,63 @@
+#pragma once
+
+#include <stdint.h>
+#include <osmocom/sim/sim.h>
+
+/* transport to a SIMtrace device */
+struct osmo_st2_transport {
+ /* USB */
+ struct libusb_device_handle *usb_devh;
+ struct {
+ uint8_t in;
+ uint8_t out;
+ uint8_t irq_in;
+ } usb_ep;
+ /* use non-blocking / asynchronous libusb I/O */
+ bool usb_async;
+
+ /* UDP */
+ int udp_fd;
+};
+
+/* a SIMtrace slot; communicates over a transport */
+struct osmo_st2_slot {
+ /* transport through which the slot can be reached */
+ struct osmo_st2_transport *transp;
+ /* number of the slot within the transport */
+ uint8_t slot_nr;
+};
+
+/* One istance of card emulation */
+struct osmo_st2_cardem_inst {
+ /* slot on which this card emulation instance runs */
+ struct osmo_st2_slot *slot;
+ /* libosmosim SIM card profile */
+ const struct osim_cla_ins_card_profile *card_prof;
+ /* libosmosim SIM card channel */
+ struct osim_chan_hdl *chan;
+ /* path of the underlying USB device */
+ char *usb_path;
+ /* opaque data TBD by user */
+ void *priv;
+};
+
+int osmo_st2_slot_tx_msg(struct osmo_st2_slot *slot, struct msgb *msg,
+ uint8_t msg_class, uint8_t msg_type);
+
+
+int osmo_st2_cardem_request_card_insert(struct osmo_st2_cardem_inst *ci, bool inserted);
+int osmo_st2_cardem_request_pb_and_rx(struct osmo_st2_cardem_inst *ci, uint8_t pb, uint8_t le);
+int osmo_st2_cardem_request_pb_and_tx(struct osmo_st2_cardem_inst *ci, uint8_t pb,
+ const uint8_t *data, uint16_t data_len_in);
+int osmo_st2_cardem_request_sw_tx(struct osmo_st2_cardem_inst *ci, const uint8_t *sw);
+int osmo_st2_cardem_request_set_atr(struct osmo_st2_cardem_inst *ci, const uint8_t *atr,
+ unsigned int atr_len);
+int osmo_st2_cardem_request_config(struct osmo_st2_cardem_inst *ci, uint32_t features);
+
+
+int osmo_st2_modem_reset_pulse(struct osmo_st2_slot *slot, uint16_t duration_ms);
+int osmo_st2_modem_reset_active(struct osmo_st2_slot *slot);
+int osmo_st2_modem_reset_inactive(struct osmo_st2_slot *slot);
+int osmo_st2_modem_sim_select_local(struct osmo_st2_slot *slot);
+int osmo_st2_modem_sim_select_remote(struct osmo_st2_slot *slot);
+int osmo_st2_modem_get_status(struct osmo_st2_slot *slot);
diff --git a/host/include/osmocom/simtrace2/simtrace_prot.h b/host/include/osmocom/simtrace2/simtrace_prot.h
new file mode 120000
index 0000000..cf485f3
--- /dev/null
+++ b/host/include/osmocom/simtrace2/simtrace_prot.h
@@ -0,0 +1 @@
+../../../../firmware/libcommon/include/simtrace_prot.h \ No newline at end of file
diff --git a/host/include/osmocom/simtrace2/simtrace_usb.h b/host/include/osmocom/simtrace2/simtrace_usb.h
new file mode 120000
index 0000000..ec0c021
--- /dev/null
+++ b/host/include/osmocom/simtrace2/simtrace_usb.h
@@ -0,0 +1 @@
+../../../../firmware/libcommon/include/simtrace_usb.h \ No newline at end of file
diff --git a/host/include/osmocom/simtrace2/usb_util.h b/host/include/osmocom/simtrace2/usb_util.h
new file mode 100644
index 0000000..3bb2486
--- /dev/null
+++ b/host/include/osmocom/simtrace2/usb_util.h
@@ -0,0 +1,5 @@
+#pragma once
+
+#include <osmocom/usb/libusb.h>
+
+extern const struct dev_id osmo_st2_compatible_dev_ids[];
diff --git a/host/lib/Makefile.am b/host/lib/Makefile.am
new file mode 100644
index 0000000..e134c75
--- /dev/null
+++ b/host/lib/Makefile.am
@@ -0,0 +1,20 @@
+# This is _NOT_ the library release version, it's an API version.
+# Please read chapter "Library interface versions" of the libtool documentation
+# before making any modifications: https://www.gnu.org/software/libtool/manual/html_node/Versioning.html
+ST2_LIBVERSION=1:0:0
+
+AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include -I$(top_builddir)
+AM_CFLAGS= -Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOSIM_CFLAGS) $(LIBUSB_CFLAGS) $(COVERAGE_CFLAGS)
+AM_LDFLAGS = $(COVERAGE_LDFLAGS)
+COMMONLIBS = $(LIBOSMOCORE_LIBS) $(LIBOSMOSIM_LIBS) $(LIBUSB_LIBS)
+
+lib_LTLIBRARIES = libosmo-simtrace2.la
+
+libosmo_simtrace2_la_LDFLAGS = $(AM_LDFLAGS) -version-info $(ST2_LIBVERSION)
+libosmo_simtrace2_la_LIBADD = $(COMMONLIBS)
+libosmo_simtrace2_la_SOURCES = \
+ apdu_dispatch.c \
+ gsmtap.c \
+ simtrace2_api.c \
+ usb_util.c \
+ $(NULL)
diff --git a/host/apdu_dispatch.c b/host/lib/apdu_dispatch.c
index 7c7ed01..4c8f505 100644
--- a/host/apdu_dispatch.c
+++ b/host/lib/apdu_dispatch.c
@@ -1,6 +1,6 @@
/* apdu_dispatch - State machine to determine Rx/Tx phases of APDU
*
- * (C) 2016 by Harald Welte <hwelte@hmw-consulting.de>
+ * (C) 2016-2019 by Harald Welte <hwelte@hmw-consulting.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -11,10 +11,6 @@
* 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 this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <stdint.h>
#include <stdlib.h>
@@ -24,24 +20,25 @@
#include <errno.h>
#include <osmocom/core/utils.h>
+#include <osmocom/core/logging.h>
#include <osmocom/sim/sim.h>
#include <osmocom/sim/class_tables.h>
-#include "apdu_dispatch.h"
+#include <osmocom/simtrace2/apdu_dispatch.h>
/*! \brief Has the command-data phase been completed yet? */
-static inline bool is_dc_complete(struct apdu_context *ac)
+static inline bool is_dc_complete(struct osmo_apdu_context *ac)
{
return (ac->lc.tot == ac->lc.cur);
}
/*! \brief Has the expected-data phase been completed yet? */
-static inline bool is_de_complete(struct apdu_context *ac)
+static inline bool is_de_complete(struct osmo_apdu_context *ac)
{
return (ac->le.tot == ac->le.cur);
}
-static const char *dump_apdu_hdr(const struct osim_apdu_cmd_hdr *h)
+static const char *stringify_apdu_hdr(const struct osim_apdu_cmd_hdr *h)
{
static char buf[256];
sprintf(buf, "CLA=%02x INS=%02x P1=%02x P2=%02x P3=%02x",
@@ -50,12 +47,19 @@ static const char *dump_apdu_hdr(const struct osim_apdu_cmd_hdr *h)
return buf;
}
-static void dump_apdu_ctx(const struct apdu_context *ac)
+/*! generate string representation of APDU context in specified output buffer.
+ * \param[in] buf output string buffer provided by caller
+ * \param[in] buf_len size of buf in bytes
+ * \param[in] ac APDU context to dump in buffer
+ * \returns pointer to buf on success */
+const char *osmo_apdu_dump_context_buf(char *buf, unsigned int buf_len,
+ const struct osmo_apdu_context *ac)
{
- printf("%s; case=%d, lc=%d(%d), le=%d(%d)\n",
- dump_apdu_hdr(&ac->hdr), ac->apdu_case,
- ac->lc.tot, ac->lc.cur,
- ac->le.tot, ac->le.cur);
+ snprintf(buf, buf_len, "%s; case=%d, lc=%d(%d), le=%d(%d)\n",
+ stringify_apdu_hdr(&ac->hdr), ac->apdu_case,
+ ac->lc.tot, ac->lc.cur,
+ ac->le.tot, ac->le.cur);
+ return buf;
}
/*! \brief input function for APDU segmentation
@@ -71,8 +75,8 @@ static void dump_apdu_ctx(const struct apdu_context *ac)
* The function retunrs APDU_ACT_RX_MORE_CAPDU_FROM_READER when there
* is more data to be received from the card reader (GSM Phone).
*/
-int apdu_segment_in(struct apdu_context *ac, const uint8_t *apdu_buf,
- unsigned int apdu_len, bool new_apdu)
+int osmo_apdu_segment_in(struct osmo_apdu_context *ac, const uint8_t *apdu_buf,
+ unsigned int apdu_len, bool new_apdu)
{
int rc = 0;
@@ -105,7 +109,7 @@ int apdu_segment_in(struct apdu_context *ac, const uint8_t *apdu_buf,
break;
case 0:
default:
- fprintf(stderr, "Unknown APDU case %d\n", ac->apdu_case);
+ LOGP(DLGLOBAL, LOGL_ERROR, "Unknown APDU case %d\n", ac->apdu_case);
return -1;
}
} else {
@@ -124,8 +128,8 @@ int apdu_segment_in(struct apdu_context *ac, const uint8_t *apdu_buf,
ac->lc.cur += cpy_len;
break;
default:
- fprintf(stderr, "Unknown APDU case %d\n", ac->apdu_case);
- break;
+ LOGP(DLGLOBAL, LOGL_ERROR, "Unknown APDU case %d\n", ac->apdu_case);
+ return -1;
}
}
@@ -163,11 +167,9 @@ int apdu_segment_in(struct apdu_context *ac, const uint8_t *apdu_buf,
break;
case 0:
default:
- fprintf(stderr, "Unknown APDU case %d\n", ac->apdu_case);
- break;
+ LOGP(DLGLOBAL, LOGL_ERROR, "Unknown APDU case %d\n", ac->apdu_case);
+ return -1;
}
- dump_apdu_ctx(ac);
-
return rc;
}
diff --git a/host/lib/gsmtap.c b/host/lib/gsmtap.c
new file mode 100644
index 0000000..3fc3da6
--- /dev/null
+++ b/host/lib/gsmtap.c
@@ -0,0 +1,78 @@
+/* gsmtap - How to encapsulate SIM protocol traces in GSMTAP
+ *
+ * (C) 2016-2019 by Harald Welte <hwelte@hmw-consulting.de>
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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.
+ */
+
+#include <osmocom/simtrace2/gsmtap.h>
+
+#include <osmocom/core/gsmtap.h>
+#include <osmocom/core/gsmtap_util.h>
+
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdio.h>
+
+/*! global GSMTAP instance */
+static struct gsmtap_inst *g_gti;
+
+/*! initialize the global GSMTAP instance for SIM traces */
+int osmo_st2_gsmtap_init(const char *gsmtap_host)
+{
+ if (g_gti)
+ return -EEXIST;
+
+ g_gti = gsmtap_source_init(gsmtap_host, GSMTAP_UDP_PORT, 0);
+ if (!g_gti) {
+ perror("unable to open GSMTAP");
+ return -EIO;
+ }
+ gsmtap_source_add_sink(g_gti);
+
+ return 0;
+}
+
+/*! log one APDU via the global GSMTAP instance.
+ * \param[in] sub_type GSMTAP sub-type (GSMTAP_SIM_* constant)
+ * \param[in] apdu User-provided buffer with APDU to log
+ * \param[in] len Length of apdu in bytes
+ */
+int osmo_st2_gsmtap_send_apdu(uint8_t sub_type, const uint8_t *apdu, unsigned int len)
+{
+ struct gsmtap_hdr *gh;
+ unsigned int gross_len = len + sizeof(*gh);
+ uint8_t *buf = malloc(gross_len);
+ int rc;
+
+ if (!buf)
+ return -ENOMEM;
+
+ memset(buf, 0, sizeof(*gh));
+ gh = (struct gsmtap_hdr *) buf;
+ gh->version = GSMTAP_VERSION;
+ gh->hdr_len = sizeof(*gh)/4;
+ gh->type = GSMTAP_TYPE_SIM;
+ gh->sub_type = sub_type;
+
+ memcpy(buf + sizeof(*gh), apdu, len);
+
+ rc = write(gsmtap_inst_fd(g_gti), buf, gross_len);
+ if (rc < 0) {
+ perror("write gsmtap");
+ free(buf);
+ return rc;
+ }
+
+ free(buf);
+ return 0;
+}
diff --git a/host/lib/simtrace2_api.c b/host/lib/simtrace2_api.c
new file mode 100644
index 0000000..4ad7eb7
--- /dev/null
+++ b/host/lib/simtrace2_api.c
@@ -0,0 +1,343 @@
+
+/* simtrace2-protocol - USB protocol library code for SIMtrace2
+ *
+ * (C) 2016-2019 by Harald Welte <hwelte@hmw-consulting.de>
+ * (C) 2018, sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon@sysmocom.de>
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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.
+ */
+
+#include <errno.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include <signal.h>
+#include <time.h>
+#define _GNU_SOURCE
+#include <getopt.h>
+
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <libusb.h>
+
+#include <osmocom/simtrace2/simtrace_prot.h>
+#include <osmocom/simtrace2/simtrace2_api.h>
+
+#include <osmocom/core/utils.h>
+#include <osmocom/core/socket.h>
+#include <osmocom/core/msgb.h>
+#include <osmocom/core/logging.h>
+#include <osmocom/sim/class_tables.h>
+#include <osmocom/sim/sim.h>
+
+#define LOGSLOT(slot, lvl, fmt, args...) \
+ LOGP(DLINP, lvl, "[%u] " fmt, (slot)->slot_nr, ## args)
+
+/***********************************************************************
+ * SIMTRACE core protocol
+ ***********************************************************************/
+
+/*! \brief allocate a message buffer for simtrace use */
+static struct msgb *st_msgb_alloc(void)
+{
+ return msgb_alloc_headroom(1024+32, 32, "SIMtrace");
+}
+
+
+static void usb_out_xfer_cb(struct libusb_transfer *xfer)
+{
+ struct msgb *msg = xfer->user_data;
+
+ switch (xfer->status) {
+ case LIBUSB_TRANSFER_COMPLETED:
+ break;
+ case LIBUSB_TRANSFER_NO_DEVICE:
+ fprintf(stderr, "USB device disappeared\n");
+ exit(1);
+ break;
+ default:
+ fprintf(stderr, "USB OUT transfer failed, status=%u\n", xfer->status);
+ exit(1);
+ break;
+ }
+
+ msgb_free(msg);
+ libusb_free_transfer(xfer);
+}
+
+
+static int st2_transp_tx_msg_usb_async(struct osmo_st2_transport *transp, struct msgb *msg)
+{
+ struct libusb_transfer *xfer;
+ int rc;
+
+ xfer = libusb_alloc_transfer(0);
+ OSMO_ASSERT(xfer);
+ xfer->dev_handle = transp->usb_devh;
+ xfer->flags = 0;
+ xfer->type = LIBUSB_TRANSFER_TYPE_BULK;
+ xfer->endpoint = transp->usb_ep.out;
+ xfer->timeout = 100000;
+ xfer->user_data = msg;
+ xfer->length = msgb_length(msg);
+ xfer->buffer = msgb_data(msg);
+ xfer->callback = usb_out_xfer_cb;
+
+ rc = libusb_submit_transfer(xfer);
+ OSMO_ASSERT(rc == 0);
+
+ return rc;
+}
+
+/*! \brief Transmit a given command to the SIMtrace2 device */
+static int st2_transp_tx_msg_usb_sync(struct osmo_st2_transport *transp, struct msgb *msg)
+{
+ int rc;
+ int xfer_len;
+ rc = libusb_bulk_transfer(transp->usb_devh, transp->usb_ep.out,
+ msgb_data(msg), msgb_length(msg),
+ &xfer_len, 100000);
+ msgb_free(msg);
+ return rc;
+}
+
+static struct simtrace_msg_hdr *st_push_hdr(struct msgb *msg, uint8_t msg_class, uint8_t msg_type,
+ uint8_t slot_nr)
+{
+ struct simtrace_msg_hdr *sh;
+
+ sh = (struct simtrace_msg_hdr *) msgb_push(msg, sizeof(*sh));
+ memset(sh, 0, sizeof(*sh));
+ sh->msg_class = msg_class;
+ sh->msg_type = msg_type;
+ sh->slot_nr = slot_nr;
+ sh->msg_len = msgb_length(msg);
+
+ return sh;
+}
+
+/* transmit a given message to a specified slot. Expects all headers
+ * present before calling the function */
+int osmo_st2_slot_tx_msg(struct osmo_st2_slot *slot, struct msgb *msg,
+ uint8_t msg_class, uint8_t msg_type)
+{
+ struct osmo_st2_transport *transp = slot->transp;
+ int rc;
+
+ OSMO_ASSERT(transp);
+
+ st_push_hdr(msg, msg_class, msg_type, slot->slot_nr);
+
+ if (transp->udp_fd < 0) {
+ if (transp->usb_async)
+ rc = st2_transp_tx_msg_usb_async(transp, msg);
+ else
+ rc = st2_transp_tx_msg_usb_sync(transp, msg);
+ } else {
+ rc = write(transp->udp_fd, msgb_data(msg), msgb_length(msg));
+ msgb_free(msg);
+ }
+ return rc;
+}
+
+/***********************************************************************
+ * Card Emulation protocol
+ ***********************************************************************/
+
+
+/*! \brief Request the SIMtrace2 to generate a card-insert signal */
+int osmo_st2_cardem_request_card_insert(struct osmo_st2_cardem_inst *ci, bool inserted)
+{
+ struct msgb *msg = st_msgb_alloc();
+ struct cardemu_usb_msg_cardinsert *cins;
+
+ LOGSLOT(ci->slot, LOGL_NOTICE, "<= %s(inserted=%d)\n", __func__, inserted);
+
+ cins = (struct cardemu_usb_msg_cardinsert *) msgb_put(msg, sizeof(*cins));
+ memset(cins, 0, sizeof(*cins));
+ if (inserted)
+ cins->card_insert = 1;
+
+ return osmo_st2_slot_tx_msg(ci->slot, msg, SIMTRACE_MSGC_CARDEM, SIMTRACE_MSGT_DT_CEMU_CARDINSERT);
+}
+
+/*! \brief Request the SIMtrace2 to transmit a Procedure Byte, then Rx */
+int osmo_st2_cardem_request_pb_and_rx(struct osmo_st2_cardem_inst *ci, uint8_t pb, uint8_t le)
+{
+ struct msgb *msg = st_msgb_alloc();
+ struct cardemu_usb_msg_tx_data *txd;
+ txd = (struct cardemu_usb_msg_tx_data *) msgb_put(msg, sizeof(*txd));
+
+ LOGSLOT(ci->slot, LOGL_DEBUG, "<= %s(pb=%02x, le=%u)\n", __func__, pb, le);
+
+ memset(txd, 0, sizeof(*txd));
+ txd->data_len = 1;
+ txd->flags = CEMU_DATA_F_PB_AND_RX;
+ /* one data byte */
+ msgb_put_u8(msg, pb);
+
+ return osmo_st2_slot_tx_msg(ci->slot, msg, SIMTRACE_MSGC_CARDEM, SIMTRACE_MSGT_DT_CEMU_TX_DATA);
+}
+
+/*! \brief Request the SIMtrace2 to transmit a Procedure Byte, then Tx */
+int osmo_st2_cardem_request_pb_and_tx(struct osmo_st2_cardem_inst *ci, uint8_t pb,
+ const uint8_t *data, uint16_t data_len_in)
+{
+ struct msgb *msg = st_msgb_alloc();
+ struct cardemu_usb_msg_tx_data *txd;
+ uint8_t *cur;
+
+ txd = (struct cardemu_usb_msg_tx_data *) msgb_put(msg, sizeof(*txd));
+
+ LOGSLOT(ci->slot, LOGL_DEBUG, "<= %s(pb=%02x, tx=%s, len=%d)\n", __func__, pb,
+ osmo_hexdump(data, data_len_in), data_len_in);
+
+ memset(txd, 0, sizeof(*txd));
+ txd->data_len = 1 + data_len_in;
+ txd->flags = CEMU_DATA_F_PB_AND_TX;
+ /* procedure byte */
+ msgb_put_u8(msg, pb);
+ /* data */
+ cur = msgb_put(msg, data_len_in);
+ memcpy(cur, data, data_len_in);
+
+ return osmo_st2_slot_tx_msg(ci->slot, msg, SIMTRACE_MSGC_CARDEM, SIMTRACE_MSGT_DT_CEMU_TX_DATA);
+}
+
+/*! \brief Request the SIMtrace2 to send a Status Word */
+int osmo_st2_cardem_request_sw_tx(struct osmo_st2_cardem_inst *ci, const uint8_t *sw)
+{
+ struct msgb *msg = st_msgb_alloc();
+ struct cardemu_usb_msg_tx_data *txd;
+ uint8_t *cur;
+
+ txd = (struct cardemu_usb_msg_tx_data *) msgb_put(msg, sizeof(*txd));
+
+ LOGSLOT(ci->slot, LOGL_DEBUG, "<= %s(sw=%02x%02x)\n", __func__, sw[0], sw[1]);
+
+ memset(txd, 0, sizeof(*txd));
+ txd->data_len = 2;
+ txd->flags = CEMU_DATA_F_PB_AND_TX | CEMU_DATA_F_FINAL;
+ cur = msgb_put(msg, 2);
+ cur[0] = sw[0];
+ cur[1] = sw[1];
+
+ return osmo_st2_slot_tx_msg(ci->slot, msg, SIMTRACE_MSGC_CARDEM, SIMTRACE_MSGT_DT_CEMU_TX_DATA);
+}
+
+int osmo_st2_cardem_request_set_atr(struct osmo_st2_cardem_inst *ci, const uint8_t *atr, unsigned int atr_len)
+{
+ struct msgb *msg = st_msgb_alloc();
+ struct cardemu_usb_msg_set_atr *satr;
+ uint8_t *cur;
+
+ satr = (struct cardemu_usb_msg_set_atr *) msgb_put(msg, sizeof(*satr));
+
+ LOGSLOT(ci->slot, LOGL_NOTICE, "<= %s(%s)\n", __func__, osmo_hexdump(atr, atr_len));
+
+ memset(satr, 0, sizeof(*satr));
+ satr->atr_len = atr_len;
+ cur = msgb_put(msg, atr_len);
+ memcpy(cur, atr, atr_len);
+
+ return osmo_st2_slot_tx_msg(ci->slot, msg, SIMTRACE_MSGC_CARDEM, SIMTRACE_MSGT_DT_CEMU_SET_ATR);
+}
+
+int osmo_st2_cardem_request_config(struct osmo_st2_cardem_inst *ci, uint32_t features)
+{
+ struct msgb *msg = st_msgb_alloc();
+ struct cardemu_usb_msg_config *cfg;
+
+ cfg = (struct cardemu_usb_msg_config *) msgb_put(msg, sizeof(*cfg));
+
+ LOGSLOT(ci->slot, LOGL_NOTICE, "<= %s(features=%08x)\n", __func__, features);
+
+ memset(cfg, 0, sizeof(*cfg));
+ cfg->features = features;
+
+ return osmo_st2_slot_tx_msg(ci->slot, msg, SIMTRACE_MSGC_CARDEM, SIMTRACE_MSGT_BD_CEMU_CONFIG);
+}
+
+/***********************************************************************
+ * Modem Control protocol
+ ***********************************************************************/
+
+static int _modem_reset(struct osmo_st2_slot *slot, uint8_t asserted, uint16_t pulse_ms)
+{
+ struct msgb *msg = st_msgb_alloc();
+ struct st_modem_reset *sr ;
+
+ LOGSLOT(slot, LOGL_NOTICE, "<= %s(asserted=%u, pulse_ms=%u)\n", __func__,
+ asserted, pulse_ms);
+
+ sr = (struct st_modem_reset *) msgb_put(msg, sizeof(*sr));
+ sr->asserted = asserted;
+ sr->pulse_duration_msec = pulse_ms;
+
+ return osmo_st2_slot_tx_msg(slot, msg, SIMTRACE_MSGC_MODEM, SIMTRACE_MSGT_DT_MODEM_RESET);
+}
+
+/*! \brief pulse the RESET line of the modem for \a duration_ms milli-seconds*/
+int osmo_st2_modem_reset_pulse(struct osmo_st2_slot *slot, uint16_t duration_ms)
+{
+ return _modem_reset(slot, 2, duration_ms);
+}
+
+/*! \brief assert the RESET line of the modem */
+int osmo_st2_modem_reset_active(struct osmo_st2_slot *slot)
+{
+ return _modem_reset(slot, 1, 0);
+}
+
+/*! \brief de-assert the RESET line of the modem */
+int osmo_st2_modem_reset_inactive(struct osmo_st2_slot *slot)
+{
+ return _modem_reset(slot, 0, 0);
+}
+
+static int _modem_sim_select(struct osmo_st2_slot *slot, uint8_t remote_sim)
+{
+ struct msgb *msg = st_msgb_alloc();
+ struct st_modem_sim_select *ss;
+
+ LOGSLOT(slot, LOGL_NOTICE, "<= %s(remote_sim=%u)\n", __func__, remote_sim);
+
+ ss = (struct st_modem_sim_select *) msgb_put(msg, sizeof(*ss));
+ ss->remote_sim = remote_sim;
+
+ return osmo_st2_slot_tx_msg(slot, msg, SIMTRACE_MSGC_MODEM, SIMTRACE_MSGT_DT_MODEM_SIM_SELECT);
+}
+
+/*! \brief select local (physical) SIM for given slot */
+int osmo_st2_modem_sim_select_local(struct osmo_st2_slot *slot)
+{
+ return _modem_sim_select(slot, 0);
+}
+
+/*! \brief select remote (emulated/forwarded) SIM for given slot */
+int osmo_st2_modem_sim_select_remote(struct osmo_st2_slot *slot)
+{
+ return _modem_sim_select(slot, 1);
+}
+
+/*! \brief Request slot to send us status information about the modem */
+int osmo_st2_modem_get_status(struct osmo_st2_slot *slot)
+{
+ struct msgb *msg = st_msgb_alloc();
+
+ return osmo_st2_slot_tx_msg(slot, msg, SIMTRACE_MSGC_MODEM, SIMTRACE_MSGT_BD_MODEM_STATUS);
+}
diff --git a/host/lib/usb_util.c b/host/lib/usb_util.c
new file mode 100644
index 0000000..d55bbc7
--- /dev/null
+++ b/host/lib/usb_util.c
@@ -0,0 +1,34 @@
+/* usb_util - USB related utilities for SIMtrace 2 USB devices
+ *
+ * (C) 2016-2019 by Harald Welte <hwelte@hmw-consulting.de>
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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.
+ */
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <getopt.h>
+
+#include <osmocom/core/utils.h>
+
+#include <osmocom/usb/libusb.h>
+#include <osmocom/simtrace2/simtrace_usb.h>
+
+/*! list of USB idVendor/idProduct tuples of devices using simtrace2 firmware */
+const struct dev_id osmo_st2_compatible_dev_ids[] = {
+ { USB_VENDOR_OPENMOKO, USB_PRODUCT_OWHW_SAM3 },
+ { USB_VENDOR_OPENMOKO, USB_PRODUCT_QMOD_SAM3 },
+ { USB_VENDOR_OPENMOKO, USB_PRODUCT_SIMTRACE2 },
+ { USB_VENDOR_OPENMOKO, USB_PRODUCT_OCTSIMTEST },
+ { USB_VENDOR_OPENMOKO, USB_PRODUCT_NGFF_CARDEM },
+ { 0, 0 }
+};
diff --git a/host/libosmo-simtrace2.pc.in b/host/libosmo-simtrace2.pc.in
new file mode 100644
index 0000000..6e9f6f2
--- /dev/null
+++ b/host/libosmo-simtrace2.pc.in
@@ -0,0 +1,10 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: Osmocom SIMtrace2 library
+Description: Library for SIM Card / Smart Card tracing + emulation
+Version: @VERSION@
+Libs: -L${libdir} -losmo-simtrace2
+Cflags: -I${includedir}/
diff --git a/host/libusb_util.c b/host/libusb_util.c
deleted file mode 100644
index 45e3f50..0000000
--- a/host/libusb_util.c
+++ /dev/null
@@ -1,297 +0,0 @@
-/* libisb utilities
- *
- * (C) 2010-2016 by Harald Welte <hwelte@hmw-consulting.de>
- *
- * This program 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 2
- * of the License, or (at your option) any later version.
- *
- * This program 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 this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-#include <errno.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <string.h>
-
-#include <libusb.h>
-
-#include "libusb_util.h"
-
-static char path_buf[USB_MAX_PATH_LEN];
-
-static char *get_path(libusb_device *dev)
-{
-#if (defined(LIBUSB_API_VERSION) && LIBUSB_API_VERSION >= 0x01000102) || (defined(LIBUSBX_API_VERSION) && LIBUSBX_API_VERSION >= 0x01000102)
- uint8_t path[8];
- int r,j;
- r = libusb_get_port_numbers(dev, path, sizeof(path));
- if (r > 0) {
- sprintf(path_buf,"%d-%d",libusb_get_bus_number(dev),path[0]);
- for (j = 1; j < r; j++){
- sprintf(path_buf+strlen(path_buf),".%d",path[j]);
- };
- }
- return path_buf;
-#else
-# warning "libusb too old - building without USB path support!"
- return NULL;
-#endif
-}
-
-static int match_dev_id(const struct libusb_device_descriptor *desc, const struct dev_id *id)
-{
- if ((desc->idVendor == id->vendor_id) && (desc->idProduct == id->product_id))
- return 1;
- return 0;
-}
-
-
-static int match_dev_ids(const struct libusb_device_descriptor *desc, const struct dev_id *ids)
-{
- const struct dev_id *id;
-
- for (id = ids; id->vendor_id || id->product_id; id++) {
- if (match_dev_id(desc, id))
- return 1;
- }
- return 0;
-}
-
-libusb_device **find_matching_usb_devs(const struct dev_id *dev_ids)
-{
- libusb_device **list;
- libusb_device **out = calloc(256, sizeof(libusb_device *));
- libusb_device **cur = out;
- unsigned int i;
- int rc;
-
- if (!out)
- return NULL;
-
- rc = libusb_get_device_list(NULL, &list);
- if (rc <= 0) {
- perror("No USB devices found");
- free(out);
- return NULL;
- }
-
- for (i = 0; list[i] != NULL; i++) {
- struct libusb_device_descriptor dev_desc;
- libusb_device *dev = list[i];
-
- rc = libusb_get_device_descriptor(dev, &dev_desc);
- if (rc < 0) {
- perror("Couldn't get device descriptor\n");
- libusb_unref_device(dev);
- continue;
- }
-
- if (match_dev_ids(&dev_desc, dev_ids)) {
- *cur = dev;
- cur++;
- /* FIXME: overflow check */
- } else
- libusb_unref_device(dev);
- }
- if (cur == out) {
- libusb_free_device_list(list, 1);
- free(out);
- return NULL;
- }
-
- libusb_free_device_list(list, 0);
- return out;
-}
-
-int dev_find_matching_interfaces(libusb_device *dev, int class, int sub_class, int protocol,
- struct usb_interface_match *out, unsigned int out_len)
-{
- struct libusb_device_descriptor dev_desc;
- int rc, i, out_idx = 0;
- uint8_t addr;
- char *path;
-
- rc = libusb_get_device_descriptor(dev, &dev_desc);
- if (rc < 0) {
- perror("Couldn't get device descriptor\n");
- return -EIO;
- }
-
- addr = libusb_get_device_address(dev);
- path = get_path(dev);
-
- /* iterate over all configurations */
- for (i = 0; i < dev_desc.bNumConfigurations; i++) {
- struct libusb_config_descriptor *conf_desc;
- int j;
-
- rc = libusb_get_config_descriptor(dev, i, &conf_desc);
- if (rc < 0) {
- fprintf(stderr, "Couldn't get config descriptor %u\n", i);
- continue;
- }
- /* iterate over all interfaces */
- for (j = 0; j < conf_desc->bNumInterfaces; j++) {
- const struct libusb_interface *intf = &conf_desc->interface[j];
- int k;
- /* iterate over all alternate settings */
- for (k = 0; k < intf->num_altsetting; k++) {
- const struct libusb_interface_descriptor *if_desc;
- if_desc = &intf->altsetting[k];
- if (class >= 0 && if_desc->bInterfaceClass != class)
- continue;
- if (sub_class >= 0 && if_desc->bInterfaceSubClass != sub_class)
- continue;
- if (protocol >= 0 && if_desc->bInterfaceProtocol != protocol)
- continue;
- /* MATCH! */
- out[out_idx].usb_dev = dev;
- out[out_idx].vendor = dev_desc.idVendor;
- out[out_idx].product = dev_desc.idProduct;
- out[out_idx].addr = addr;
- strncpy(out[out_idx].path, path, sizeof(out[out_idx].path)-1);
- out[out_idx].path[sizeof(out[out_idx].path)-1] = '\0';
- out[out_idx].configuration = conf_desc->bConfigurationValue;
- out[out_idx].interface = if_desc->bInterfaceNumber;
- out[out_idx].altsetting = if_desc->bAlternateSetting;
- out[out_idx].class = if_desc->bInterfaceClass;
- out[out_idx].sub_class = if_desc->bInterfaceSubClass;
- out[out_idx].protocol = if_desc->bInterfaceProtocol;
- out[out_idx].string_idx = if_desc->iInterface;
- out_idx++;
- if (out_idx >= out_len)
- return out_idx;
- }
- }
- }
- return out_idx;
-}
-
-int usb_match_interfaces(libusb_context *ctx, const struct dev_id *dev_ids,
- int class, int sub_class, int protocol,
- struct usb_interface_match *out, unsigned int out_len)
-{
- struct usb_interface_match *out_cur = out;
- unsigned int out_len_remain = out_len;
- libusb_device **list;
- libusb_device **dev;
-
- list = find_matching_usb_devs(dev_ids);
- if (!list)
- return 0;
-
- for (dev = list; *dev; dev++) {
- int rc;
-
-#if 0
- struct libusb_device_descriptor dev_desc;
- uint8_t ports[8];
- uint8_t addr;
- rc = libusb_get_device_descriptor(*dev, &dev_desc);
- if (rc < 0) {
- perror("Cannot get device descriptor");
- continue;
- }
-
- addr = libusb_get_device_address(*dev);
-
- rc = libusb_get_port_numbers(*dev, ports, sizeof(ports));
- if (rc < 0) {
- perror("Cannot get device path");
- continue;
- }
-
- printf("Found USB Device %04x:%04x at address %d\n",
- dev_desc.idVendor, dev_desc.idProduct, addr);
-#endif
-
- rc = dev_find_matching_interfaces(*dev, class, sub_class, protocol, out_cur, out_len_remain);
- if (rc < 0)
- continue;
- out_cur += rc;
- out_len_remain -= rc;
-
- }
- return out_len - out_len_remain;
-}
-
-libusb_device_handle *usb_open_claim_interface(libusb_context *ctx,
- const struct usb_interface_match *ifm)
-{
- int rc, config;
- struct dev_id dev_ids[] = { { ifm->vendor, ifm->product }, { 0, 0 } };
- libusb_device **list;
- libusb_device **dev;
- libusb_device_handle *usb_devh = NULL;
-
- list = find_matching_usb_devs(dev_ids);
- if (!list) {
- perror("No USB device with matching VID/PID");
- return NULL;
- }
-
- for (dev = list; *dev; dev++) {
- int addr;
- char *path;
-
- addr = libusb_get_device_address(*dev);
- path = get_path(*dev);
- if ((ifm->addr && addr == ifm->addr) ||
- (strlen(ifm->path) && !strcmp(path, ifm->path))) {
- rc = libusb_open(*dev, &usb_devh);
- if (rc < 0) {
- fprintf(stderr, "Cannot open device: %s\n", libusb_error_name(rc));
- usb_devh = NULL;
- break;
- }
- rc = libusb_get_configuration(usb_devh, &config);
- if (rc < 0) {
- fprintf(stderr, "Cannot get current configuration: %s\n", libusb_error_name(rc));
- libusb_close(usb_devh);
- usb_devh = NULL;
- break;
- }
- if (config != ifm->configuration) {
- rc = libusb_set_configuration(usb_devh, ifm->configuration);
- if (rc < 0) {
- fprintf(stderr, "Cannot set configuration: %s\n", libusb_error_name(rc));
- libusb_close(usb_devh);
- usb_devh = NULL;
- break;
- }
- }
- rc = libusb_claim_interface(usb_devh, ifm->interface);
- if (rc < 0) {
- fprintf(stderr, "Cannot claim interface: %s\n", libusb_error_name(rc));
- libusb_close(usb_devh);
- usb_devh = NULL;
- break;
- }
- rc = libusb_set_interface_alt_setting(usb_devh, ifm->interface, ifm->altsetting);
- if (rc < 0) {
- fprintf(stderr, "Cannot set interface altsetting: %s\n", libusb_error_name(rc));
- libusb_release_interface(usb_devh, ifm->interface);
- libusb_close(usb_devh);
- usb_devh = NULL;
- break;
- }
- }
- }
-
- /* unref / free list */
- for (dev = list; *dev; dev++)
- libusb_unref_device(*dev);
- free(list);
-
- return usb_devh;
-}
diff --git a/host/libusb_util.h b/host/libusb_util.h
deleted file mode 100644
index 2b2d92e..0000000
--- a/host/libusb_util.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/* libisb utilities
- *
- * (C) 2010-2016 by Harald Welte <hwelte@hmw-consulting.de>
- *
- * This program 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 2
- * of the License, or (at your option) any later version.
- *
- * This program 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 this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-#pragma once
-
-#include <libusb.h>
-
-#define USB_MAX_PATH_LEN 20
-
-struct dev_id {
- uint16_t vendor_id;
- uint16_t product_id;
-};
-
-/* Find any USB devices in the system matching the given Vendor and
- * Product ID */
-libusb_device **find_matching_usb_devs(const struct dev_id *dev_ids);
-
-/* structure describing a single matching interface found */
-struct usb_interface_match {
- /* libusb device E*/
- libusb_device *usb_dev;
- /* Vendor ID of the device running matching interface */
- uint16_t vendor;
- /* Product ID of the device running matching interface */
- uint16_t product;
- /* USB Bus Address */
- uint8_t addr;
- /* physical path */
- char path[USB_MAX_PATH_LEN];
- /* configuration of matching interface */
- uint8_t configuration;
- /* interface number of matching interface */
- uint8_t interface;
- /* altsetting of matching interface */
- uint8_t altsetting;
- /* bInterfaceClass of matching interface */
- uint8_t class;
- /* bInterfaceSubClass of matching interface */
- uint8_t sub_class;
- /* bInterfaceProtocol of matching interface */
- uint8_t protocol;
- /* index of string descriptor of matching interface */
- uint8_t string_idx;
-};
-
-int dev_find_matching_interfaces(libusb_device *dev, int class, int sub_class, int protocol,
- struct usb_interface_match *out, unsigned int out_len);
-
-int usb_match_interfaces(libusb_context *ctx, const struct dev_id *dev_ids,
- int class, int sub_class, int protocol,
- struct usb_interface_match *out, unsigned int out_len);
-
-libusb_device_handle *usb_open_claim_interface(libusb_context *ctx,
- const struct usb_interface_match *ifm);
diff --git a/host/simtrace.h b/host/simtrace.h
deleted file mode 100644
index c4a20da..0000000
--- a/host/simtrace.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef _SIMTRACE_H
-#define _SIMTRACE_H
-
-#define SIMTRACE_USB_VENDOR 0x1d50
-#define SIMTRACE_USB_PRODUCT 0x60e3
-
-#endif
diff --git a/host/simtrace2-discovery.c b/host/simtrace2-discovery.c
deleted file mode 100644
index a7306ce..0000000
--- a/host/simtrace2-discovery.c
+++ /dev/null
@@ -1,94 +0,0 @@
-/* simtrace2-discovery - host PC library to scan for matching USB
- * devices
- *
- * (C) 2016 by Harald Welte <hwelte@hmw-consulting.de>
- *
- * This program 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 2
- * of the License, or (at your option) any later version.
- *
- * This program 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 this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-#include <stdint.h>
-
-#include <libusb.h>
-
-/*! \brief obtain the endpoint addresses for a given USB interface */
-int get_usb_ep_addrs(libusb_device_handle *devh, unsigned int if_num,
- uint8_t *out, uint8_t *in, uint8_t *irq)
-{
- libusb_device *dev = libusb_get_device(devh);
- struct libusb_config_descriptor *cdesc;
- const struct libusb_interface_descriptor *idesc;
- const struct libusb_interface *iface;
- int rc, l;
-
- rc = libusb_get_active_config_descriptor(dev, &cdesc);
- if (rc < 0)
- return rc;
-
- iface = &cdesc->interface[if_num];
- /* FIXME: we assume there's no altsetting */
- idesc = &iface->altsetting[0];
-
- for (l = 0; l < idesc->bNumEndpoints; l++) {
- const struct libusb_endpoint_descriptor *edesc = &idesc->endpoint[l];
- switch (edesc->bmAttributes & 3) {
- case LIBUSB_TRANSFER_TYPE_BULK:
- if (edesc->bEndpointAddress & 0x80) {
- if (in)
- *in = edesc->bEndpointAddress;
- } else {
- if (out)
- *out = edesc->bEndpointAddress;
- }
- break;
- case LIBUSB_TRANSFER_TYPE_INTERRUPT:
- if (irq)
- *irq = edesc->bEndpointAddress;
- break;
- default:
- break;
- }
- }
- return 0;
-}
-
-#if 0
- struct libusb_device_descriptor ddesc;
- int rc, i, j, k;
-
- rc = libusb_get_device_descriptor(devh, &ddesc);
- if (rc < 0)
- return;
-
- for (i = 0; i < ddesc.bNumConfigurations; i++) {
- struct libusb_config_descriptor *cdesc;
- rc = libusb_get_config_descriptor(devh, i, &cdesc);
- if (rc < 0)
- return;
-
- for (j = 0; j < cdesc->bNumInterfaces; j++) {
- const struct libusb_interface *iface = cdesc->interface[j];
- for (k = 0; k < iface->num_altsetting; k++) {
- const struct libusb_interface_descriptor *idesc = iface->altsetting[k];
- /* make sure this is the interface we're looking for */
- if (idesc->bInterfaceClass != 0xFF ||
- idesc->bInterfaceSubClass != if_class ||
- idsec->bInterfaceProtocol != if_proto)
- continue;
- /* FIXME */
- }
- }
-
- libusb_free_config_descriptor(cdesc);
- }
-#endif
diff --git a/host/simtrace2-discovery.h b/host/simtrace2-discovery.h
deleted file mode 100644
index cfba956..0000000
--- a/host/simtrace2-discovery.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/* simtrace2-discovery - host PC library to scan for matching USB
- * devices
- *
- * (C) 2016 by Harald Welte <hwelte@hmw-consulting.de>
- *
- * This program 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 2
- * of the License, or (at your option) any later version.
- *
- * This program 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 this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-#pragma once
-
-#include <stdint.h>
-#include <libusb.h>
-
-int get_usb_ep_addrs(libusb_device_handle *devh, unsigned int if_num,
- uint8_t *out, uint8_t *in, uint8_t *irq);
diff --git a/host/simtrace2-remsim.c b/host/simtrace2-remsim.c
deleted file mode 100644
index 73a7272..0000000
--- a/host/simtrace2-remsim.c
+++ /dev/null
@@ -1,775 +0,0 @@
-/* simtrace2-remsim - main program for the host PC to provide a remote SIM
- * using the SIMtrace 2 firmware in card emulation mode
- *
- * (C) 2016-2017 by Harald Welte <hwelte@hmw-consulting.de>
- * (C) 2018, sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon@sysmocom.de>
- *
- * This program 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 2
- * of the License, or (at your option) any later version.
- *
- * This program 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 this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-#include <errno.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdint.h>
-#include <signal.h>
-#include <time.h>
-#define _GNU_SOURCE
-#include <getopt.h>
-
-#include <sys/time.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-#include <libusb.h>
-
-#include "libusb_util.h"
-#include "simtrace.h"
-#include "simtrace_prot.h"
-#include "apdu_dispatch.h"
-#include "simtrace2-discovery.h"
-
-#include <osmocom/core/gsmtap.h>
-#include <osmocom/core/gsmtap_util.h>
-#include <osmocom/core/utils.h>
-#include <osmocom/core/socket.h>
-#include <osmocom/core/msgb.h>
-#include <osmocom/sim/class_tables.h>
-#include <osmocom/sim/sim.h>
-
-/* transport to a SIMtrace device */
-struct st_transport {
- /* USB */
- struct libusb_device_handle *usb_devh;
- struct {
- uint8_t in;
- uint8_t out;
- uint8_t irq_in;
- } usb_ep;
-
- /* UDP */
- int udp_fd;
-};
-
-/* a SIMtrace slot; communicates over a transport */
-struct st_slot {
- /* transport through which the slot can be reached */
- struct st_transport *transp;
- /* number of the slot within the transport */
- uint8_t slot_nr;
-};
-
-/* One istance of card emulation */
-struct cardem_inst {
- /* slot on which this card emulation instance runs */
- struct st_slot *slot;
- /* libosmosim SIM card profile */
- const struct osim_cla_ins_card_profile *card_prof;
- /* libosmosim SIM card channel */
- struct osim_chan_hdl *chan;
-};
-
-/* global GSMTAP instance */
-static struct gsmtap_inst *g_gti;
-
-static int gsmtap_send_sim(const uint8_t *apdu, unsigned int len)
-{
- struct gsmtap_hdr *gh;
- unsigned int gross_len = len + sizeof(*gh);
- uint8_t *buf = malloc(gross_len);
- int rc;
-
- if (!buf)
- return -ENOMEM;
-
- memset(buf, 0, sizeof(*gh));
- gh = (struct gsmtap_hdr *) buf;
- gh->version = GSMTAP_VERSION;
- gh->hdr_len = sizeof(*gh)/4;
- gh->type = GSMTAP_TYPE_SIM;
-
- memcpy(buf + sizeof(*gh), apdu, len);
-
- rc = write(gsmtap_inst_fd(g_gti), buf, gross_len);
- if (rc < 0) {
- perror("write gsmtap");
- free(buf);
- return rc;
- }
-
- free(buf);
- return 0;
-}
-
-/***********************************************************************
- * SIMTRACE pcore protocol
- ***********************************************************************/
-
-/*! \brief allocate a message buffer for simtrace use */
-static struct msgb *st_msgb_alloc(void)
-{
- return msgb_alloc_headroom(1024+32, 32, "SIMtrace");
-}
-
-#if 0
-static void apdu_out_cb(uint8_t *buf, unsigned int len, void *user_data)
-{
- printf("APDU: %s\n", osmo_hexdump(buf, len));
- gsmtap_send_sim(buf, len);
-}
-#endif
-
-/*! \brief Transmit a given command to the SIMtrace2 device */
-int st_transp_tx_msg(struct st_transport *transp, struct msgb *msg)
-{
- int rc;
-
- printf("<- %s\n", msgb_hexdump(msg));
-
- if (transp->udp_fd < 0) {
- int xfer_len;
-
- rc = libusb_bulk_transfer(transp->usb_devh, transp->usb_ep.out,
- msgb_data(msg), msgb_length(msg),
- &xfer_len, 100000);
- } else {
- rc = write(transp->udp_fd, msgb_data(msg), msgb_length(msg));
- }
-
- msgb_free(msg);
- return rc;
-}
-
-static struct simtrace_msg_hdr *st_push_hdr(struct msgb *msg, uint8_t msg_class, uint8_t msg_type,
- uint8_t slot_nr)
-{
- struct simtrace_msg_hdr *sh;
-
- sh = (struct simtrace_msg_hdr *) msgb_push(msg, sizeof(*sh));
- memset(sh, 0, sizeof(*sh));
- sh->msg_class = msg_class;
- sh->msg_type = msg_type;
- sh->slot_nr = slot_nr;
- sh->msg_len = msgb_length(msg);
-
- return sh;
-}
-
-/* transmit a given message to a specified slot. Expects all headers
- * present before calling the function */
-int st_slot_tx_msg(struct st_slot *slot, struct msgb *msg,
- uint8_t msg_class, uint8_t msg_type)
-{
- st_push_hdr(msg, msg_class, msg_type, slot->slot_nr);
-
- return st_transp_tx_msg(slot->transp, msg);
-}
-
-/***********************************************************************
- * Card Emulation protocol
- ***********************************************************************/
-
-
-/*! \brief Request the SIMtrace2 to generate a card-insert signal */
-static int cardem_request_card_insert(struct cardem_inst *ci, bool inserted)
-{
- struct msgb *msg = st_msgb_alloc();
- struct cardemu_usb_msg_cardinsert *cins;
-
- cins = (struct cardemu_usb_msg_cardinsert *) msgb_put(msg, sizeof(*cins));
- memset(cins, 0, sizeof(*cins));
- if (inserted)
- cins->card_insert = 1;
-
- return st_slot_tx_msg(ci->slot, msg, SIMTRACE_MSGC_CARDEM, SIMTRACE_MSGT_DT_CEMU_CARDINSERT);
-}
-
-/*! \brief Request the SIMtrace2 to transmit a Procedure Byte, then Rx */
-static int cardem_request_pb_and_rx(struct cardem_inst *ci, uint8_t pb, uint8_t le)
-{
- struct msgb *msg = st_msgb_alloc();
- struct cardemu_usb_msg_tx_data *txd;
- txd = (struct cardemu_usb_msg_tx_data *) msgb_put(msg, sizeof(*txd));
-
- printf("<= %s(%02x, %d)\n", __func__, pb, le);
-
- memset(txd, 0, sizeof(*txd));
- txd->data_len = 1;
- txd->flags = CEMU_DATA_F_PB_AND_RX;
- /* one data byte */
- msgb_put_u8(msg, pb);
-
- return st_slot_tx_msg(ci->slot, msg, SIMTRACE_MSGC_CARDEM, SIMTRACE_MSGT_DT_CEMU_TX_DATA);
-}
-
-/*! \brief Request the SIMtrace2 to transmit a Procedure Byte, then Tx */
-static int cardem_request_pb_and_tx(struct cardem_inst *ci, uint8_t pb,
- const uint8_t *data, uint16_t data_len_in)
-{
- struct msgb *msg = st_msgb_alloc();
- struct cardemu_usb_msg_tx_data *txd;
- uint8_t *cur;
-
- txd = (struct cardemu_usb_msg_tx_data *) msgb_put(msg, sizeof(*txd));
-
- printf("<= %s(%02x, %s, %d)\n", __func__, pb,
- osmo_hexdump(data, data_len_in), data_len_in);
-
- memset(txd, 0, sizeof(*txd));
- txd->data_len = 1 + data_len_in;
- txd->flags = CEMU_DATA_F_PB_AND_TX;
- /* procedure byte */
- msgb_put_u8(msg, pb);
- /* data */
- cur = msgb_put(msg, data_len_in);
- memcpy(cur, data, data_len_in);
-
- return st_slot_tx_msg(ci->slot, msg, SIMTRACE_MSGC_CARDEM, SIMTRACE_MSGT_DT_CEMU_TX_DATA);
-}
-
-/*! \brief Request the SIMtrace2 to send a Status Word */
-static int cardem_request_sw_tx(struct cardem_inst *ci, const uint8_t *sw)
-{
- struct msgb *msg = st_msgb_alloc();
- struct cardemu_usb_msg_tx_data *txd;
- uint8_t *cur;
-
- txd = (struct cardemu_usb_msg_tx_data *) msgb_put(msg, sizeof(*txd));
-
- printf("<= %s(%02x %02x)\n", __func__, sw[0], sw[1]);
-
- memset(txd, 0, sizeof(*txd));
- txd->data_len = 2;
- txd->flags = CEMU_DATA_F_PB_AND_TX | CEMU_DATA_F_FINAL;
- cur = msgb_put(msg, 2);
- cur[0] = sw[0];
- cur[1] = sw[1];
-
- return st_slot_tx_msg(ci->slot, msg, SIMTRACE_MSGC_CARDEM, SIMTRACE_MSGT_DT_CEMU_TX_DATA);
-}
-
-static void atr_update_csum(uint8_t *atr, unsigned int atr_len)
-{
- uint8_t csum = 0;
- int i;
-
- for (i = 1; i < atr_len - 1; i++)
- csum = csum ^ atr[i];
-
- atr[atr_len-1] = csum;
-}
-
-static int cardem_request_set_atr(struct cardem_inst *ci, const uint8_t *atr, unsigned int atr_len)
-{
- struct msgb *msg = st_msgb_alloc();
- struct cardemu_usb_msg_set_atr *satr;
- uint8_t *cur;
-
- satr = (struct cardemu_usb_msg_set_atr *) msgb_put(msg, sizeof(*satr));
-
- printf("<= %s(%s)\n", __func__, osmo_hexdump(atr, atr_len));
-
- memset(satr, 0, sizeof(*satr));
- satr->atr_len = atr_len;
- cur = msgb_put(msg, atr_len);
- memcpy(cur, atr, atr_len);
-
- return st_slot_tx_msg(ci->slot, msg, SIMTRACE_MSGC_CARDEM, SIMTRACE_MSGT_DT_CEMU_SET_ATR);
-}
-
-/***********************************************************************
- * Modem Control protocol
- ***********************************************************************/
-
-static int _modem_reset(struct st_slot *slot, uint8_t asserted, uint16_t pulse_ms)
-{
- struct msgb *msg = st_msgb_alloc();
- struct st_modem_reset *sr ;
-
- sr = (struct st_modem_reset *) msgb_put(msg, sizeof(*sr));
- sr->asserted = asserted;
- sr->pulse_duration_msec = pulse_ms;
-
- return st_slot_tx_msg(slot, msg, SIMTRACE_MSGC_MODEM, SIMTRACE_MSGT_DT_MODEM_RESET);
-}
-
-/*! \brief pulse the RESET line of the modem for \a duration_ms milli-seconds*/
-int st_modem_reset_pulse(struct st_slot *slot, uint16_t duration_ms)
-{
- return _modem_reset(slot, 2, duration_ms);
-}
-
-/*! \brief assert the RESET line of the modem */
-int st_modem_reset_active(struct st_slot *slot)
-{
- return _modem_reset(slot, 1, 0);
-}
-
-/*! \brief de-assert the RESET line of the modem */
-int st_modem_reset_inactive(struct st_slot *slot)
-{
- return _modem_reset(slot, 0, 0);
-}
-
-static int _modem_sim_select(struct st_slot *slot, uint8_t remote_sim)
-{
- struct msgb *msg = st_msgb_alloc();
- struct st_modem_sim_select *ss;
-
- ss = (struct st_modem_sim_select *) msgb_put(msg, sizeof(*ss));
- ss->remote_sim = remote_sim;
-
- return st_slot_tx_msg(slot, msg, SIMTRACE_MSGC_MODEM, SIMTRACE_MSGT_DT_MODEM_SIM_SELECT);
-}
-
-/*! \brief select local (physical) SIM for given slot */
-int st_modem_sim_select_local(struct st_slot *slot)
-{
- return _modem_sim_select(slot, 0);
-}
-
-/*! \brief select remote (emulated/forwarded) SIM for given slot */
-int st_modem_sim_select_remote(struct st_slot *slot)
-{
- return _modem_sim_select(slot, 1);
-}
-
-/*! \brief Request slot to send us status information about the modem */
-int st_modem_get_status(struct st_slot *slot)
-{
- struct msgb *msg = st_msgb_alloc();
-
- return st_slot_tx_msg(slot, msg, SIMTRACE_MSGC_MODEM, SIMTRACE_MSGT_BD_MODEM_STATUS);
-}
-
-
-/***********************************************************************
- * Incoming Messages
- ***********************************************************************/
-
-/*! \brief Process a STATUS message from the SIMtrace2 */
-static int process_do_status(struct cardem_inst *ci, uint8_t *buf, int len)
-{
- struct cardemu_usb_msg_status *status;
- status = (struct cardemu_usb_msg_status *) buf;
-
- printf("=> STATUS: flags=0x%x, fi=%u, di=%u, wi=%u wtime=%u\n",
- status->flags, status->fi, status->di, status->wi,
- status->waiting_time);
-
- return 0;
-}
-
-/*! \brief Process a PTS indication message from the SIMtrace2 */
-static int process_do_pts(struct cardem_inst *ci, uint8_t *buf, int len)
-{
- struct cardemu_usb_msg_pts_info *pts;
- pts = (struct cardemu_usb_msg_pts_info *) buf;
-
- printf("=> PTS req: %s\n", osmo_hexdump(pts->req, sizeof(pts->req)));
-
- return 0;
-}
-
-/*! \brief Process a ERROR indication message from the SIMtrace2 */
-static int process_do_error(struct cardem_inst *ci, uint8_t *buf, int len)
-{
- struct cardemu_usb_msg_error *err;
- err = (struct cardemu_usb_msg_error *) buf;
-
- printf("=> ERROR: %u/%u/%u: %s\n",
- err->severity, err->subsystem, err->code,
- err->msg_len ? (char *)err->msg : "");
-
- return 0;
-}
-
-/*! \brief Process a RX-DATA indication message from the SIMtrace2 */
-static int process_do_rx_da(struct cardem_inst *ci, uint8_t *buf, int len)
-{
- static struct apdu_context ac;
- struct cardemu_usb_msg_rx_data *data;
- int rc;
-
- data = (struct cardemu_usb_msg_rx_data *) buf;
-
- printf("=> DATA: flags=%x, %s: ", data->flags,
- osmo_hexdump(data->data, data->data_len));
-
- rc = apdu_segment_in(&ac, data->data, data->data_len,
- data->flags & CEMU_DATA_F_TPDU_HDR);
-
- if (rc & APDU_ACT_TX_CAPDU_TO_CARD) {
- struct msgb *tmsg = msgb_alloc(1024, "TPDU");
- struct osim_reader_hdl *rh = ci->chan->card->reader;
- uint8_t *cur;
-
- /* Copy TPDU header */
- cur = msgb_put(tmsg, sizeof(ac.hdr));
- memcpy(cur, &ac.hdr, sizeof(ac.hdr));
- /* Copy D(c), if any */
- if (ac.lc.tot) {
- cur = msgb_put(tmsg, ac.lc.tot);
- memcpy(cur, ac.dc, ac.lc.tot);
- }
- /* send to actual card */
- tmsg->l3h = tmsg->tail;
- rc = rh->ops->transceive(rh, tmsg);
- if (rc < 0) {
- fprintf(stderr, "error during transceive: %d\n", rc);
- msgb_free(tmsg);
- return rc;
- }
- msgb_apdu_sw(tmsg) = msgb_get_u16(tmsg);
- ac.sw[0] = msgb_apdu_sw(tmsg) >> 8;
- ac.sw[1] = msgb_apdu_sw(tmsg) & 0xff;
- printf("SW=0x%04x, len_rx=%d\n", msgb_apdu_sw(tmsg), msgb_l3len(tmsg));
- if (msgb_l3len(tmsg))
- cardem_request_pb_and_tx(ci, ac.hdr.ins, tmsg->l3h, msgb_l3len(tmsg));
- cardem_request_sw_tx(ci, ac.sw);
- } else if (ac.lc.tot > ac.lc.cur) {
- cardem_request_pb_and_rx(ci, ac.hdr.ins, ac.lc.tot - ac.lc.cur);
- }
- return 0;
-}
-
-#if 0
- case SIMTRACE_CMD_DO_ERROR
- rc = process_do_error(ci, buf, len);
- break;
-#endif
-
-/*! \brief Process an incoming message from the SIMtrace2 */
-static int process_usb_msg(struct cardem_inst *ci, uint8_t *buf, int len)
-{
- struct simtrace_msg_hdr *sh = (struct simtrace_msg_hdr *)buf;
- int rc;
-
- printf("-> %s\n", osmo_hexdump(buf, len));
-
- buf += sizeof(*sh);
-
- switch (sh->msg_type) {
- case SIMTRACE_MSGT_BD_CEMU_STATUS:
- rc = process_do_status(ci, buf, len);
- break;
- case SIMTRACE_MSGT_DO_CEMU_PTS:
- rc = process_do_pts(ci, buf, len);
- break;
- case SIMTRACE_MSGT_DO_CEMU_RX_DATA:
- rc = process_do_rx_da(ci, buf, len);
- break;
- default:
- printf("unknown simtrace msg type 0x%02x\n", sh->msg_type);
- rc = -1;
- break;
- }
-
- return rc;
-}
-
-static void print_welcome(void)
-{
- printf("simtrace2-remsim - Remote SIM card forwarding\n"
- "(C) 2010-2017, Harald Welte <laforge@gnumonks.org>\n"
- "(C) 2018, sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon@sysmocom.de>\n\n");
-}
-
-static void print_help(void)
-{
- printf( "\t-r\t--remote-udp-host HOST\n"
- "\t-p\t--remote-udp-port PORT\n"
- "\t-h\t--help\n"
- "\t-i\t--gsmtap-ip\tA.B.C.D\n"
- "\t-a\t--skip-atr\n"
- "\t-k\t--keep-running\n"
- "\t-V\t--usb-vendor\tVENDOR_ID\n"
- "\t-P\t--usb-product\tPRODUCT_ID\n"
- "\t-C\t--usb-config\tCONFIG_ID\n"
- "\t-I\t--usb-interface\tINTERFACE_ID\n"
- "\t-S\t--usb-altsetting ALTSETTING_ID\n"
- "\t-A\t--usb-address\tADDRESS\n"
- "\t-H\t--usb-path\tPATH\n"
- "\n"
- );
-}
-
-static const struct option opts[] = {
- { "remote-udp-host", 1, 0, 'r' },
- { "remote-udp-port", 1, 0, 'p' },
- { "gsmtap-ip", 1, 0, 'i' },
- { "skip-atr", 0, 0, 'a' },
- { "help", 0, 0, 'h' },
- { "keep-running", 0, 0, 'k' },
- { "usb-vendor", 1, 0, 'V' },
- { "usb-product", 1, 0, 'P' },
- { "usb-config", 1, 0, 'C' },
- { "usb-interface", 1, 0, 'I' },
- { "usb-altsetting", 1, 0, 'S' },
- { "usb-address", 1, 0, 'A' },
- { "usb-path", 1, 0, 'H' },
- { NULL, 0, 0, 0 }
-};
-
-static void run_mainloop(struct cardem_inst *ci)
-{
- struct st_transport *transp = ci->slot->transp;
- unsigned int msg_count, byte_count = 0;
- uint8_t buf[16*265];
- int xfer_len;
- int rc;
-
- printf("Entering main loop\n");
-
- while (1) {
- /* read data from SIMtrace2 device (local or via USB) */
- if (transp->udp_fd < 0) {
- rc = libusb_bulk_transfer(transp->usb_devh, transp->usb_ep.in,
- buf, sizeof(buf), &xfer_len, 100);
- if (rc < 0 && rc != LIBUSB_ERROR_TIMEOUT &&
- rc != LIBUSB_ERROR_INTERRUPTED &&
- rc != LIBUSB_ERROR_IO) {
- fprintf(stderr, "BULK IN transfer error; rc=%d\n", rc);
- return;
- }
- } else {
- rc = read(transp->udp_fd, buf, sizeof(buf));
- if (rc <= 0) {
- fprintf(stderr, "shor read from UDP\n");
- return;
- }
- xfer_len = rc;
- }
- /* dispatch any incoming data */
- if (xfer_len > 0) {
- printf("URB: %s\n", osmo_hexdump(buf, xfer_len));
- process_usb_msg(ci, buf, xfer_len);
- msg_count++;
- byte_count += xfer_len;
- }
- }
-}
-
-static struct st_transport _transp;
-
-static struct st_slot _slot = {
- .transp = &_transp,
- .slot_nr = 0,
-};
-
-struct cardem_inst _ci = {
- .slot = &_slot,
-};
-
-struct cardem_inst *ci = &_ci;
-
-static void signal_handler(int signal)
-{
- switch (signal) {
- case SIGINT:
- cardem_request_card_insert(ci, false);
- exit(0);
- break;
- default:
- break;
- }
-}
-
-int main(int argc, char **argv)
-{
- struct st_transport *transp = ci->slot->transp;
- char *gsmtap_host = "127.0.0.1";
- int rc;
- int c, ret = 1;
- int skip_atr = 0;
- int keep_running = 0;
- int remote_udp_port = 52342;
- int if_num = 0, vendor_id = -1, product_id = -1;
- int config_id = -1, altsetting = 0, addr = -1;
- char *remote_udp_host = NULL;
- char *path = NULL;
- struct osim_reader_hdl *reader;
- struct osim_card_hdl *card;
-
- print_welcome();
-
- while (1) {
- int option_index = 0;
-
- c = getopt_long(argc, argv, "r:p:hi:V:P:C:I:S:A:H:ak", opts, &option_index);
- if (c == -1)
- break;
- switch (c) {
- case 'r':
- remote_udp_host = optarg;
- break;
- case 'p':
- remote_udp_port = atoi(optarg);
- break;
- case 'h':
- print_help();
- exit(0);
- break;
- case 'i':
- gsmtap_host = optarg;
- break;
- case 'a':
- skip_atr = 1;
- break;
- case 'k':
- keep_running = 1;
- break;
- case 'V':
- vendor_id = strtol(optarg, NULL, 16);
- break;
- case 'P':
- product_id = strtol(optarg, NULL, 16);
- break;
- case 'C':
- config_id = atoi(optarg);
- break;
- case 'I':
- if_num = atoi(optarg);
- break;
- case 'S':
- altsetting = atoi(optarg);
- break;
- case 'A':
- addr = atoi(optarg);
- break;
- case 'H':
- path = optarg;
- break;
- }
- }
-
- if (!remote_udp_host && (vendor_id < 0 || product_id < 0)) {
- fprintf(stderr, "You have to specify the vendor and product ID\n");
- goto do_exit;
- }
-
- transp->udp_fd = -1;
-
- ci->card_prof = &osim_uicc_sim_cic_profile;
-
- if (!remote_udp_host) {
- rc = libusb_init(NULL);
- if (rc < 0) {
- fprintf(stderr, "libusb initialization failed\n");
- goto do_exit;
- }
- } else {
- transp->udp_fd = osmo_sock_init(AF_INET, SOCK_DGRAM, IPPROTO_UDP,
- remote_udp_host, remote_udp_port+if_num,
- OSMO_SOCK_F_CONNECT);
- if (transp->udp_fd < 0) {
- fprintf(stderr, "error binding UDP port\n");
- goto do_exit;
- }
- }
-
- g_gti = gsmtap_source_init(gsmtap_host, GSMTAP_UDP_PORT, 0);
- if (!g_gti) {
- perror("unable to open GSMTAP");
- goto close_exit;
- }
- gsmtap_source_add_sink(g_gti);
-
- reader = osim_reader_open(OSIM_READER_DRV_PCSC, 0, "", NULL);
- if (!reader) {
- perror("unable to open PC/SC reader");
- goto close_exit;
- }
-
- card = osim_card_open(reader, OSIM_PROTO_T0);
- if (!card) {
- perror("unable to open SIM card");
- goto close_exit;
- }
-
- ci->chan = llist_entry(card->channels.next, struct osim_chan_hdl, list);
- if (!ci->chan) {
- perror("SIM card has no channel?!?");
- goto close_exit;
- }
-
- signal(SIGINT, &signal_handler);
-
- do {
- if (transp->udp_fd < 0) {
- struct usb_interface_match _ifm, *ifm = &_ifm;
- ifm->vendor = vendor_id;
- ifm->product = product_id;
- ifm->configuration = config_id;
- ifm->interface = if_num;
- ifm->altsetting = altsetting;
- ifm->addr = addr;
- if (path)
- osmo_strlcpy(ifm->path, path, sizeof(ifm->path));
- transp->usb_devh = usb_open_claim_interface(NULL, ifm);
- if (!transp->usb_devh) {
- fprintf(stderr, "can't open USB device\n");
- goto close_exit;
- }
-
- rc = libusb_claim_interface(transp->usb_devh, if_num);
- if (rc < 0) {
- fprintf(stderr, "can't claim interface %d; rc=%d\n", if_num, rc);
- goto close_exit;
- }
-
- rc = get_usb_ep_addrs(transp->usb_devh, if_num, &transp->usb_ep.out,
- &transp->usb_ep.in, &transp->usb_ep.irq_in);
- if (rc < 0) {
- fprintf(stderr, "can't obtain EP addrs; rc=%d\n", rc);
- goto close_exit;
- }
- }
-
- /* simulate card-insert to modem (owhw, not qmod) */
- cardem_request_card_insert(ci, true);
-
- /* select remote (forwarded) SIM */
- st_modem_sim_select_remote(ci->slot);
-
- /* set the ATR */
- uint8_t real_atr[] = { 0x3B, 0x9F, 0x96, 0x80, 0x1F, 0xC7, 0x80, 0x31,
- 0xA0, 0x73, 0xBE, 0x21, 0x13, 0x67, 0x43, 0x20,
- 0x07, 0x18, 0x00, 0x00, 0x01, 0xA5 };
- atr_update_csum(real_atr, sizeof(real_atr));
- cardem_request_set_atr(ci, real_atr, sizeof(real_atr));
-
- /* select remote (forwarded) SIM */
- st_modem_reset_pulse(ci->slot, 300);
-
- run_mainloop(ci);
- ret = 0;
-
- if (transp->udp_fd < 0)
- libusb_release_interface(transp->usb_devh, 0);
-close_exit:
- if (transp->usb_devh)
- libusb_close(transp->usb_devh);
- if (keep_running)
- sleep(1);
- } while (keep_running);
-
- if (transp->udp_fd < 0)
- libusb_exit(NULL);
-do_exit:
- return ret;
-}
diff --git a/host/simtrace_prot.h b/host/simtrace_prot.h
deleted file mode 120000
index a9fffe1..0000000
--- a/host/simtrace_prot.h
+++ /dev/null
@@ -1 +0,0 @@
-../firmware/libcommon/include/simtrace_prot.h \ No newline at end of file
diff --git a/host/simtrace_usb.h b/host/simtrace_usb.h
deleted file mode 120000
index f1e0982..0000000
--- a/host/simtrace_usb.h
+++ /dev/null
@@ -1 +0,0 @@
-../firmware/libcommon/include/simtrace_usb.h \ No newline at end of file
diff --git a/host/src/Makefile.am b/host/src/Makefile.am
new file mode 100644
index 0000000..17be9eb
--- /dev/null
+++ b/host/src/Makefile.am
@@ -0,0 +1,16 @@
+AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include
+AM_CFLAGS=-Wall -g $(LIBOSMOCORE_CFLAGS) $(LIBOSMOSIM_CFLAGS) $(LIBOSMOUSB_CFLAGS) $(LIBUSB_CFLAGS) $(COVERAGE_FLAGS)
+AM_LDFLAGS=$(COVERAGE_LDFLAGS)
+
+LDADD= $(top_builddir)/lib/libosmo-simtrace2.la \
+ $(LIBOSMOCORE_LIBS) $(LIBOSMOSIM_LIBS) $(LIBOSMOUSB_LIBS) $(LIBUSB_LIBS)
+
+bin_PROGRAMS = simtrace2-cardem-pcsc simtrace2-list simtrace2-sniff simtrace2-tool
+
+simtrace2_cardem_pcsc_SOURCES = simtrace2-cardem-pcsc.c
+
+simtrace2_list_SOURCES = simtrace2_usb.c
+
+simtrace2_sniff_SOURCES = simtrace2-sniff.c
+
+simtrace2_tool_SOURCES = simtrace2-tool.c
diff --git a/host/src/simtrace2-cardem-pcsc.c b/host/src/simtrace2-cardem-pcsc.c
new file mode 100644
index 0000000..4acf268
--- /dev/null
+++ b/host/src/simtrace2-cardem-pcsc.c
@@ -0,0 +1,683 @@
+/* simtrace2-cardem-pcsc - main program for the host PC to provide a remote SIM
+ * using the SIMtrace 2 firmware in card emulation mode
+ *
+ * (C) 2016-2022 by Harald Welte <hwelte@hmw-consulting.de>
+ * (C) 2018, sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon@sysmocom.de>
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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.
+ */
+
+#include <errno.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include <signal.h>
+#include <time.h>
+#define _GNU_SOURCE
+#include <getopt.h>
+
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <libusb.h>
+
+#include <osmocom/usb/libusb.h>
+#include <osmocom/simtrace2/simtrace2_api.h>
+#include <osmocom/simtrace2/simtrace_prot.h>
+#include <osmocom/simtrace2/apdu_dispatch.h>
+#include <osmocom/simtrace2/gsmtap.h>
+
+#include <osmocom/core/utils.h>
+#include <osmocom/core/socket.h>
+#include <osmocom/core/msgb.h>
+#include <osmocom/core/select.h>
+#include <osmocom/core/logging.h>
+#include <osmocom/core/application.h>
+#include <osmocom/sim/class_tables.h>
+#include <osmocom/sim/sim.h>
+
+#define LOGCI(ci, lvl, fmt, args ...) LOGP(DLGLOBAL, lvl, fmt, ## args)
+
+static void atr_update_csum(uint8_t *atr, unsigned int atr_len)
+{
+ uint8_t csum = 0;
+ int i;
+
+ for (i = 1; i < atr_len - 1; i++)
+ csum = csum ^ atr[i];
+
+ atr[atr_len-1] = csum;
+}
+
+static void cemu_status_flags2str(char *out, unsigned int out_len, uint32_t flags)
+{
+ snprintf(out, out_len, "%s%s%s%s%s",
+ flags & CEMU_STATUS_F_RESET_ACTIVE ? "RESET " : "",
+ flags & CEMU_STATUS_F_VCC_PRESENT ? "VCC " : "",
+ flags & CEMU_STATUS_F_CLK_ACTIVE ? "CLK " : "",
+ flags & CEMU_STATUS_F_CARD_INSERT ? "CARD_PRES " : "",
+ flags & CEMU_STATUS_F_RCEMU_ACTIVE ? "RCEMU " : "");
+}
+
+static uint32_t last_status_flags = 0;
+
+#define NO_RESET 0
+#define COLD_RESET 1
+#define WARM_RESET 2
+
+static void update_status_flags(struct osmo_st2_cardem_inst *ci, uint32_t flags)
+{
+ struct osim_card_hdl *card = ci->chan->card;
+ int reset = NO_RESET;
+
+ /* check if card is _now_ operational: VCC+CLK present, RST absent */
+ if ((flags & CEMU_STATUS_F_VCC_PRESENT) && (flags & CEMU_STATUS_F_CLK_ACTIVE) &&
+ !(flags & CEMU_STATUS_F_RESET_ACTIVE)) {
+ if (last_status_flags & CEMU_STATUS_F_RESET_ACTIVE) {
+ /* a reset has just ended, forward it to the real card */
+ if (last_status_flags & CEMU_STATUS_F_VCC_PRESENT)
+ reset = WARM_RESET;
+ else
+ reset = COLD_RESET;
+ } else if (!(last_status_flags & CEMU_STATUS_F_VCC_PRESENT)) {
+ /* power-up has just happened, perform cold reset */
+ reset = COLD_RESET;
+ }
+ } else if (flags == CEMU_STATUS_F_VCC_PRESENT &&
+ !(last_status_flags & CEMU_STATUS_F_VCC_PRESENT)) {
+ /* improper power-up: Only power enabled, but no reset active. */
+ reset = COLD_RESET;
+ }
+
+ if (reset) {
+ LOGCI(ci, LOGL_NOTICE, "%s Resetting card in reader...\n",
+ reset == COLD_RESET ? "Cold" : "Warm");
+ osim_card_reset(card, reset == COLD_RESET ? true : false);
+
+ /* Mark reset event in GSMTAP wireshark trace */
+ osmo_st2_gsmtap_send_apdu(GSMTAP_SIM_ATR, card->atr, card->atr_len);
+ }
+
+ last_status_flags = flags;
+}
+
+static const char *cemu_data_flags2str(uint32_t flags)
+{
+ static char out[64];
+ snprintf(out, sizeof(out), "%s%s%s%s",
+ flags & CEMU_DATA_F_TPDU_HDR ? "HDR " : "",
+ flags & CEMU_DATA_F_FINAL ? "FINAL " : "",
+ flags & CEMU_DATA_F_PB_AND_TX ? "PB_AND_TX " : "",
+ flags & CEMU_DATA_F_PB_AND_RX ? "PB_AND_RX" : "");
+ return out;
+}
+
+/***********************************************************************
+ * Incoming Messages
+ ***********************************************************************/
+
+/*! \brief Process a STATUS message from the SIMtrace2 */
+static int process_do_status(struct osmo_st2_cardem_inst *ci, uint8_t *buf, int len)
+{
+ struct cardemu_usb_msg_status *status = (struct cardemu_usb_msg_status *) buf;
+ char fbuf[80];
+
+ cemu_status_flags2str(fbuf, sizeof(fbuf), status->flags);
+ LOGCI(ci, LOGL_NOTICE, "=> STATUS: flags=0x%x, fi=%u, di=%u, wi=%u wtime=%u (%s)\n",
+ status->flags, status->fi, status->di, status->wi,
+ status->waiting_time, fbuf);
+
+ update_status_flags(ci, status->flags);
+
+ return 0;
+}
+
+/*! \brief Process a PTS indication message from the SIMtrace2 */
+static int process_do_pts(struct osmo_st2_cardem_inst *ci, uint8_t *buf, int len)
+{
+ struct cardemu_usb_msg_pts_info *pts;
+ pts = (struct cardemu_usb_msg_pts_info *) buf;
+
+ LOGCI(ci, LOGL_NOTICE, "=> PTS req: %s\n", osmo_hexdump(pts->req, pts->pts_len));
+
+ return 0;
+}
+
+/*! \brief Process a RX-DATA indication message from the SIMtrace2 */
+static int process_do_rx_da(struct osmo_st2_cardem_inst *ci, uint8_t *buf, int len)
+{
+ static struct osmo_apdu_context ac;
+ struct cardemu_usb_msg_rx_data *data;
+ int rc;
+
+ data = (struct cardemu_usb_msg_rx_data *) buf;
+
+ LOGCI(ci, LOGL_INFO, "=> DATA: flags=0x%02x (%s), %s\n ", data->flags,
+ cemu_data_flags2str(data->flags), osmo_hexdump(data->data, data->data_len));
+
+ rc = osmo_apdu_segment_in(&ac, data->data, data->data_len,
+ data->flags & CEMU_DATA_F_TPDU_HDR);
+ if (rc < 0) {
+ /* At this point the communication is broken. We cannot keep running, as we
+ * don't know if we should continue transmitting or receiving. Only a successful
+ * return value by osmo_apdu_segment_in() would allow us to know this. */
+ LOGCI(ci, LOGL_FATAL, "Failed to recognize APDU, terminating\n");
+ exit(1);
+ }
+
+ if (rc & APDU_ACT_TX_CAPDU_TO_CARD) {
+ struct msgb *tmsg = msgb_alloc(1024, "TPDU");
+ struct osim_reader_hdl *rh = ci->chan->card->reader;
+ uint8_t *cur;
+
+ /* Copy TPDU header */
+ cur = msgb_put(tmsg, sizeof(ac.hdr));
+ memcpy(cur, &ac.hdr, sizeof(ac.hdr));
+ /* Copy D(c), if any */
+ if (ac.lc.tot) {
+ cur = msgb_put(tmsg, ac.lc.tot);
+ memcpy(cur, ac.dc, ac.lc.tot);
+ }
+ /* send to actual card */
+ tmsg->l3h = tmsg->tail;
+ rc = rh->ops->transceive(rh, tmsg);
+ if (rc < 0) {
+ fprintf(stderr, "error during transceive: %d\n", rc);
+ msgb_free(tmsg);
+ return rc;
+ }
+ /* send via GSMTAP for wireshark tracing */
+ osmo_st2_gsmtap_send_apdu(GSMTAP_SIM_APDU, tmsg->data, msgb_length(tmsg));
+
+ msgb_apdu_sw(tmsg) = msgb_get_u16(tmsg);
+ ac.sw[0] = msgb_apdu_sw(tmsg) >> 8;
+ ac.sw[1] = msgb_apdu_sw(tmsg) & 0xff;
+ if (msgb_l3len(tmsg))
+ osmo_st2_cardem_request_pb_and_tx(ci, ac.hdr.ins, tmsg->l3h, msgb_l3len(tmsg));
+ osmo_st2_cardem_request_sw_tx(ci, ac.sw);
+ } else if (ac.lc.tot > ac.lc.cur) {
+ osmo_st2_cardem_request_pb_and_rx(ci, ac.hdr.ins, ac.lc.tot - ac.lc.cur);
+ }
+ return 0;
+}
+
+/*! \brief Process an incoming message from the SIMtrace2 */
+static int process_usb_msg(struct osmo_st2_cardem_inst *ci, uint8_t *buf, int len)
+{
+ struct simtrace_msg_hdr *sh = (struct simtrace_msg_hdr *)buf;
+ int rc;
+
+ buf += sizeof(*sh);
+
+ switch (sh->msg_type) {
+ case SIMTRACE_MSGT_BD_CEMU_STATUS:
+ rc = process_do_status(ci, buf, len);
+ break;
+ case SIMTRACE_MSGT_DO_CEMU_PTS:
+ rc = process_do_pts(ci, buf, len);
+ break;
+ case SIMTRACE_MSGT_DO_CEMU_RX_DATA:
+ rc = process_do_rx_da(ci, buf, len);
+ break;
+ case SIMTRACE_MSGT_BD_CEMU_CONFIG:
+ /* firmware confirms configuration change; ignore */
+ rc = 0;
+ break;
+ default:
+ printf("unknown simtrace msg type 0x%02x\n", sh->msg_type);
+ rc = -1;
+ break;
+ }
+
+ return rc;
+}
+
+/*! \brief Process a STATUS message on IRQ endpoint from the SIMtrace2 */
+static int process_irq_status(struct osmo_st2_cardem_inst *ci, const uint8_t *buf, int len)
+{
+ const struct cardemu_usb_msg_status *status = (struct cardemu_usb_msg_status *) buf;
+ char fbuf[80];
+
+ cemu_status_flags2str(fbuf, sizeof(fbuf), status->flags);
+ LOGCI(ci, LOGL_NOTICE, "=> IRQ STATUS: flags=0x%x, fi=%u, di=%u, wi=%u wtime=%u (%s)\n",
+ status->flags, status->fi, status->di, status->wi,
+ status->waiting_time, fbuf);
+
+ update_status_flags(ci, status->flags);
+
+ return 0;
+}
+
+static int process_usb_msg_irq(struct osmo_st2_cardem_inst *ci, const uint8_t *buf, unsigned int len)
+{
+ struct simtrace_msg_hdr *sh = (struct simtrace_msg_hdr *)buf;
+ int rc;
+
+ buf += sizeof(*sh);
+
+ switch (sh->msg_type) {
+ case SIMTRACE_MSGT_BD_CEMU_STATUS:
+ rc = process_irq_status(ci, buf, len);
+ break;
+ default:
+ LOGCI(ci, LOGL_ERROR, "unknown simtrace msg type 0x%02x\n", sh->msg_type);
+ rc = -1;
+ break;
+ }
+
+ return rc;
+}
+
+static void usb_in_xfer_cb(struct libusb_transfer *xfer)
+{
+ struct osmo_st2_cardem_inst *ci = xfer->user_data;
+ int rc;
+
+ switch (xfer->status) {
+ case LIBUSB_TRANSFER_COMPLETED:
+ /* hand the message up the stack */
+ process_usb_msg(ci, xfer->buffer, xfer->actual_length);
+ break;
+ case LIBUSB_TRANSFER_ERROR:
+ LOGCI(ci, LOGL_FATAL, "USB IN transfer error, trying resubmit\n");
+ break;
+ case LIBUSB_TRANSFER_NO_DEVICE:
+ LOGCI(ci, LOGL_FATAL, "USB device disappeared\n");
+ exit(1);
+ break;
+ default:
+ LOGCI(ci, LOGL_FATAL, "USB IN transfer failed, status=%u\n", xfer->status);
+ exit(1);
+ break;
+ }
+
+ /* re-submit the IN transfer */
+ rc = libusb_submit_transfer(xfer);
+ OSMO_ASSERT(rc == 0);
+}
+
+
+static void allocate_and_submit_in(struct osmo_st2_cardem_inst *ci)
+{
+ struct osmo_st2_transport *transp = ci->slot->transp;
+ struct libusb_transfer *xfer;
+ int rc;
+
+ xfer = libusb_alloc_transfer(0);
+ OSMO_ASSERT(xfer);
+ xfer->dev_handle = transp->usb_devh;
+ xfer->flags = 0;
+ xfer->type = LIBUSB_TRANSFER_TYPE_BULK;
+ xfer->endpoint = transp->usb_ep.in;
+ xfer->timeout = 0;
+ xfer->user_data = ci;
+ xfer->length = 16*256;
+
+ xfer->buffer = libusb_dev_mem_alloc(xfer->dev_handle, xfer->length);
+ OSMO_ASSERT(xfer->buffer);
+ xfer->callback = usb_in_xfer_cb;
+
+ /* submit the IN transfer */
+ rc = libusb_submit_transfer(xfer);
+ OSMO_ASSERT(rc == 0);
+}
+
+
+static void usb_irq_xfer_cb(struct libusb_transfer *xfer)
+{
+ struct osmo_st2_cardem_inst *ci = xfer->user_data;
+ int rc;
+
+ switch (xfer->status) {
+ case LIBUSB_TRANSFER_COMPLETED:
+ process_usb_msg_irq(ci, xfer->buffer, xfer->actual_length);
+ break;
+ case LIBUSB_TRANSFER_ERROR:
+ LOGCI(ci, LOGL_FATAL, "USB INT transfer error, trying resubmit\n");
+ break;
+ case LIBUSB_TRANSFER_NO_DEVICE:
+ LOGCI(ci, LOGL_FATAL, "USB device disappeared\n");
+ exit(1);
+ break;
+ default:
+ LOGCI(ci, LOGL_FATAL, "USB INT transfer failed, status=%u\n", xfer->status);
+ exit(1);
+ break;
+ }
+
+ /* re-submit the IN transfer */
+ rc = libusb_submit_transfer(xfer);
+ OSMO_ASSERT(rc == 0);
+}
+
+
+static void allocate_and_submit_irq(struct osmo_st2_cardem_inst *ci)
+{
+ struct osmo_st2_transport *transp = ci->slot->transp;
+ struct libusb_transfer *xfer;
+ int rc;
+
+ xfer = libusb_alloc_transfer(0);
+ OSMO_ASSERT(xfer);
+ xfer->dev_handle = transp->usb_devh;
+ xfer->flags = 0;
+ xfer->type = LIBUSB_TRANSFER_TYPE_INTERRUPT;
+ xfer->endpoint = transp->usb_ep.irq_in;
+ xfer->timeout = 0;
+ xfer->user_data = ci;
+ xfer->length = 64;
+
+ xfer->buffer = libusb_dev_mem_alloc(xfer->dev_handle, xfer->length);
+ OSMO_ASSERT(xfer->buffer);
+ xfer->callback = usb_irq_xfer_cb;
+
+ /* submit the IN transfer */
+ rc = libusb_submit_transfer(xfer);
+ OSMO_ASSERT(rc == 0);
+}
+
+
+
+static void print_welcome(void)
+{
+ printf("simtrace2-cardem-pcsc - Using PC/SC reader as SIM\n"
+ "(C) 2010-2022, Harald Welte <laforge@gnumonks.org>\n"
+ "(C) 2018, sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon@sysmocom.de>\n\n");
+}
+
+static void print_help(void)
+{
+ printf( "\t-h\t--help\n"
+ "\t-i\t--gsmtap-ip\tA.B.C.D\n"
+ "\t-a\t--skip-atr\n"
+ "\t-t\t--set-atr\tATR-STRING in HEX\n"
+ "\t-k\t--keep-running\n"
+ "\t-n\t--pcsc-reader-num\n"
+ "\t-V\t--usb-vendor\tVENDOR_ID\n"
+ "\t-P\t--usb-product\tPRODUCT_ID\n"
+ "\t-C\t--usb-config\tCONFIG_ID\n"
+ "\t-I\t--usb-interface\tINTERFACE_ID\n"
+ "\t-S\t--usb-altsetting ALTSETTING_ID\n"
+ "\t-A\t--usb-address\tADDRESS\n"
+ "\t-H\t--usb-path\tPATH\n"
+ "\n"
+ );
+}
+
+static const struct option opts[] = {
+ { "gsmtap-ip", 1, 0, 'i' },
+ { "skip-atr", 0, 0, 'a' },
+ { "set-atr", 1, 0, 't' },
+ { "help", 0, 0, 'h' },
+ { "keep-running", 0, 0, 'k' },
+ { "pcsc-reader-num", 1, 0, 'n' },
+ { "usb-vendor", 1, 0, 'V' },
+ { "usb-product", 1, 0, 'P' },
+ { "usb-config", 1, 0, 'C' },
+ { "usb-interface", 1, 0, 'I' },
+ { "usb-altsetting", 1, 0, 'S' },
+ { "usb-address", 1, 0, 'A' },
+ { "usb-path", 1, 0, 'H' },
+ { NULL, 0, 0, 0 }
+};
+
+static void run_mainloop(struct osmo_st2_cardem_inst *ci)
+{
+ printf("Entering main loop\n");
+ while (1) {
+ osmo_select_main(0);
+ }
+}
+
+static struct osmo_st2_transport _transp;
+
+static struct osmo_st2_slot _slot = {
+ .transp = &_transp,
+ .slot_nr = 0,
+};
+
+struct osmo_st2_cardem_inst _ci = {
+ .slot = &_slot,
+};
+
+struct osmo_st2_cardem_inst *ci = &_ci;
+
+static void signal_handler(int signal)
+{
+ switch (signal) {
+ case SIGINT:
+ osmo_st2_cardem_request_card_insert(ci, false);
+ osmo_st2_modem_sim_select_local(ci->slot);
+ exit(0);
+ break;
+ default:
+ break;
+ }
+}
+
+static struct log_info log_info = {};
+
+int main(int argc, char **argv)
+{
+ struct osmo_st2_transport *transp = ci->slot->transp;
+ char *gsmtap_host = "127.0.0.1";
+ int rc;
+ int c, ret = 1;
+ int skip_atr = 0;
+ char *atr = NULL;
+ uint8_t override_atr[OSIM_MAX_ATR_LEN];
+ int override_atr_len = 0;
+ int keep_running = 0;
+ int if_num = 0, vendor_id = -1, product_id = -1;
+ int config_id = -1, altsetting = 0, addr = -1;
+ int reader_num = 0;
+ char *path = NULL;
+ struct osim_reader_hdl *reader;
+ struct osim_card_hdl *card;
+
+ print_welcome();
+
+ osmo_init_logging2(NULL, &log_info);
+
+ rc = osmo_libusb_init(NULL);
+ if (rc < 0) {
+ fprintf(stderr, "libusb initialization failed\n");
+ return rc;
+ }
+
+ log_set_print_category_hex(osmo_stderr_target, false);
+ log_set_print_category(osmo_stderr_target, true);
+ log_set_print_level(osmo_stderr_target, true);
+ log_set_print_filename_pos(osmo_stderr_target, LOG_FILENAME_POS_LINE_END);
+ log_set_print_filename2(osmo_stderr_target, LOG_FILENAME_NONE);
+ log_set_category_filter(osmo_stderr_target, DLINP, 1, LOGL_DEBUG);
+ log_set_category_filter(osmo_stderr_target, DLGLOBAL, 1, LOGL_DEBUG);
+
+ while (1) {
+ int option_index = 0;
+
+ c = getopt_long(argc, argv, "hi:V:P:C:I:S:A:H:akn:t:", opts, &option_index);
+ if (c == -1)
+ break;
+ switch (c) {
+ case 'h':
+ print_help();
+ exit(0);
+ break;
+ case 'i':
+ gsmtap_host = optarg;
+ break;
+ case 'a':
+ skip_atr = 1;
+ break;
+ case 't':
+ atr = optarg;
+ break;
+ case 'k':
+ keep_running = 1;
+ break;
+ case 'n':
+ reader_num = atoi(optarg);
+ break;
+ case 'V':
+ vendor_id = strtol(optarg, NULL, 16);
+ break;
+ case 'P':
+ product_id = strtol(optarg, NULL, 16);
+ break;
+ case 'C':
+ config_id = atoi(optarg);
+ break;
+ case 'I':
+ if_num = atoi(optarg);
+ break;
+ case 'S':
+ altsetting = atoi(optarg);
+ break;
+ case 'A':
+ addr = atoi(optarg);
+ break;
+ case 'H':
+ path = optarg;
+ break;
+ }
+ }
+
+ if (atr) {
+ override_atr_len = osmo_hexparse(atr, override_atr, sizeof(override_atr));
+ if (override_atr_len < 2) {
+ fprintf(stderr, "Invalid ATR - please omit a leading 0x and only use valid hex "
+ "digits and whitespace. ATRs need to be between 2 and 33 bytes long.\n");
+ goto do_exit;
+ }
+ }
+
+ if (vendor_id < 0 || product_id < 0) {
+ fprintf(stderr, "You have to specify the vendor and product ID\n");
+ goto do_exit;
+ }
+
+ ci->card_prof = &osim_uicc_sim_cic_profile;
+
+ rc = osmo_st2_gsmtap_init(gsmtap_host);
+ if (rc < 0) {
+ perror("unable to open GSMTAP");
+ goto close_exit;
+ }
+
+ reader = osim_reader_open(OSIM_READER_DRV_PCSC, reader_num, "", NULL);
+ if (!reader) {
+ perror("unable to open PC/SC reader");
+ goto close_exit;
+ }
+
+ card = osim_card_open(reader, OSIM_PROTO_T0);
+ if (!card) {
+ perror("unable to open SIM card");
+ goto close_exit;
+ }
+
+ ci->chan = llist_entry(card->channels.next, struct osim_chan_hdl, list);
+ if (!ci->chan) {
+ perror("SIM card has no channel?!?");
+ goto close_exit;
+ }
+
+ signal(SIGINT, &signal_handler);
+
+ do {
+ struct usb_interface_match _ifm, *ifm = &_ifm;
+ memset(ifm, 0, sizeof(*ifm));
+ ifm->vendor = vendor_id;
+ ifm->product = product_id;
+ ifm->configuration = config_id;
+ ifm->interface = if_num;
+ ifm->altsetting = altsetting;
+ if (addr > 0 && addr < 256)
+ ifm->addr = addr;
+ if (path)
+ osmo_strlcpy(ifm->path, path, sizeof(ifm->path));
+ transp->udp_fd = -1;
+ transp->usb_async = true;
+ transp->usb_devh = osmo_libusb_open_claim_interface(NULL, NULL, ifm);
+ if (!transp->usb_devh) {
+ fprintf(stderr, "can't open USB device: %s\n", strerror(errno));
+ goto close;
+ }
+
+ rc = libusb_claim_interface(transp->usb_devh, if_num);
+ if (rc < 0) {
+ fprintf(stderr, "can't claim interface %d; rc=%d\n", if_num, rc);
+ goto close;
+ }
+
+ rc = osmo_libusb_get_ep_addrs(transp->usb_devh, if_num, &transp->usb_ep.out,
+ &transp->usb_ep.in, &transp->usb_ep.irq_in);
+ if (rc < 0) {
+ fprintf(stderr, "can't obtain EP addrs; rc=%d\n", rc);
+ goto close;
+ }
+
+ allocate_and_submit_irq(ci);
+ for (int i = 0; i < 4; i++)
+ allocate_and_submit_in(ci);
+
+ /* request firmware to generate STATUS on IRQ endpoint */
+ osmo_st2_cardem_request_config(ci, CEMU_FEAT_F_STATUS_IRQ);
+
+ /* simulate card-insert to modem (owhw, not qmod) */
+ osmo_st2_cardem_request_card_insert(ci, true);
+
+ /* select remote (forwarded) SIM */
+ osmo_st2_modem_sim_select_remote(ci->slot);
+
+ if (!skip_atr) {
+ /* set the ATR */
+ if (override_atr_len) {
+ /* user has specified an override-ATR */
+ atr_update_csum(override_atr, override_atr_len);
+ osmo_st2_cardem_request_set_atr(ci, override_atr, override_atr_len);
+ } else {
+ /* use the real ATR of the card */
+ osmo_st2_cardem_request_set_atr(ci, card->atr, card->atr_len);
+ }
+ }
+
+ /* select remote (forwarded) SIM */
+ osmo_st2_modem_reset_pulse(ci->slot, 300);
+
+ run_mainloop(ci);
+ ret = 0;
+
+ libusb_release_interface(transp->usb_devh, 0);
+
+close:
+ if (transp->usb_devh) {
+ libusb_close(transp->usb_devh);
+ transp->usb_devh = NULL;
+ }
+ if (keep_running)
+ sleep(1);
+ } while (keep_running);
+
+close_exit:
+ if (transp->usb_devh)
+ libusb_close(transp->usb_devh);
+
+ osmo_libusb_exit(NULL);
+do_exit:
+ return ret;
+}
diff --git a/host/simtrace2-sniff.c b/host/src/simtrace2-sniff.c
index dddf5cf..8504e8b 100644
--- a/host/simtrace2-sniff.c
+++ b/host/src/simtrace2-sniff.c
@@ -13,10 +13,6 @@
* 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 this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <errno.h>
#include <unistd.h>
@@ -37,33 +33,18 @@
#include <libusb.h>
-#include "libusb_util.h"
-#include "simtrace.h"
-#include "simtrace_usb.h"
-#include "simtrace_prot.h"
-#include "simtrace2-discovery.h"
+#include <osmocom/usb/libusb.h>
+#include <osmocom/simtrace2/simtrace_usb.h>
+#include <osmocom/simtrace2/simtrace_prot.h>
+
+#include <osmocom/simtrace2/gsmtap.h>
-#include <osmocom/core/gsmtap.h>
-#include <osmocom/core/gsmtap_util.h>
#include <osmocom/core/utils.h>
#include <osmocom/core/socket.h>
#include <osmocom/core/msgb.h>
#include <osmocom/sim/class_tables.h>
#include <osmocom/sim/sim.h>
-/* as of August 26, 2018 we don't have any released libosmocore version which includes those
- * definitions yet. Let's ensure some backwards compatibility: */
-#ifndef GSMTAP_SIM_APDU
-#define GSMTAP_SIM_APDU 0x00 /* APDU data (complete APDU) */
-#define GSMTAP_SIM_ATR 0x01 /* card ATR data */
-#define GSMTAP_SIM_PPS_REQ 0x02 /* PPS request data */
-#define GSMTAP_SIM_PPS_RSP 0x03 /* PPS response data */
-#define GSMTAP_SIM_TPDU_HDR 0x04 /* TPDU command header */
-#define GSMTAP_SIM_TPDU_CMD 0x05 /* TPDU command body */
-#define GSMTAP_SIM_TPDU_RSP 0x06 /* TPDU response body */
-#define GSMTAP_SIM_TPDU_SW 0x07 /* TPDU response trailer */
-#endif
-
/* transport to a SIMtrace device */
struct st_transport {
/* USB */
@@ -75,90 +56,27 @@ struct st_transport {
} usb_ep;
};
-/* global GSMTAP instance */
-static struct gsmtap_inst *g_gti;
-
-static int gsmtap_send_sim(uint8_t sub_type, const uint8_t *data, unsigned int len)
-{
- struct gsmtap_hdr *gh;
- unsigned int gross_len = len + sizeof(*gh);
- uint8_t *buf = malloc(gross_len);
- int rc;
-
- if (!buf)
- return -ENOMEM;
-
- memset(buf, 0, sizeof(*gh));
- gh = (struct gsmtap_hdr *) buf;
- gh->version = GSMTAP_VERSION;
- gh->hdr_len = sizeof(*gh)/4;
- gh->type = GSMTAP_TYPE_SIM;
- gh->sub_type = sub_type;
-
- memcpy(buf + sizeof(*gh), data, len);
-
- rc = write(gsmtap_inst_fd(g_gti), buf, gross_len);
- if (rc < 0) {
- perror("write gsmtap");
- free(buf);
- return rc;
- }
-
- free(buf);
- return 0;
-}
-
const struct value_string change_flags[] = {
- {
- .value = SNIFF_CHANGE_FLAG_CARD_INSERT,
- .str = "card inserted",
- },
- {
- .value = SNIFF_CHANGE_FLAG_CARD_EJECT,
- .str = "card ejected",
- },
- {
- .value = SNIFF_CHANGE_FLAG_RESET_ASSERT,
- .str = "reset asserted",
- },
- {
- .value = SNIFF_CHANGE_FLAG_RESET_DEASSERT,
- .str = "reset de-asserted",
- },
- {
- .value = SNIFF_CHANGE_FLAG_TIMEOUT_WT,
- .str = "data transfer timeout",
- },
- {
- .value = 0,
- .str = NULL,
- },
+ { SNIFF_CHANGE_FLAG_CARD_INSERT, "card inserted" },
+ { SNIFF_CHANGE_FLAG_CARD_EJECT, "card ejected" },
+ { SNIFF_CHANGE_FLAG_RESET_ASSERT, "reset asserted" },
+ { SNIFF_CHANGE_FLAG_RESET_DEASSERT, "reset de-asserted" },
+ { SNIFF_CHANGE_FLAG_TIMEOUT_WT, "data transfer timeout" },
+ { 0, NULL }
};
const struct value_string data_flags[] = {
- {
- .value = SNIFF_DATA_FLAG_ERROR_INCOMPLETE,
- .str = "incomplete",
- },
- {
- .value = SNIFF_DATA_FLAG_ERROR_MALFORMED,
- .str = "malformed",
- },
- {
- .value = SNIFF_DATA_FLAG_ERROR_CHECKSUM,
- .str = "checksum error",
- },
- {
- .value = 0,
- .str = NULL,
- },
+ { SNIFF_DATA_FLAG_ERROR_INCOMPLETE, "incomplete" },
+ { SNIFF_DATA_FLAG_ERROR_MALFORMED, "malformed" },
+ { SNIFF_DATA_FLAG_ERROR_CHECKSUM, "checksum error" },
+ { 0, NULL }
};
static void print_flags(const struct value_string* flag_meanings, uint32_t nb_flags, uint32_t flags) {
uint32_t i;
for (i = 0; i < nb_flags; i++) {
if (flags & flag_meanings[i].value) {
- printf(flag_meanings[i].str);
+ printf("%s", flag_meanings[i].str);
flags &= ~flag_meanings[i].value;
if (flags) {
printf(", ");
@@ -252,11 +170,11 @@ static int process_data(enum simtrace_msg_type_sniff type, const uint8_t *buf, i
/* Send message as GSNTAP */
switch (type) {
case SIMTRACE_MSGT_SNIFF_ATR:
- gsmtap_send_sim(GSMTAP_SIM_ATR, data->data, data->length);
+ osmo_st2_gsmtap_send_apdu(GSMTAP_SIM_ATR, data->data, data->length);
break;
case SIMTRACE_MSGT_SNIFF_TPDU:
/* TPDU is now considered as APDU since SIMtrace sends complete TPDU */
- gsmtap_send_sim(GSMTAP_SIM_APDU, data->data, data->length);
+ osmo_st2_gsmtap_send_apdu(GSMTAP_SIM_APDU, data->data, data->length);
break;
default:
break;
@@ -393,6 +311,7 @@ static const struct option opts[] = {
/* Known USB device with SIMtrace firmware supporting sniffer */
static const struct dev_id compatible_dev_ids[] = {
{ USB_VENDOR_OPENMOKO, USB_PRODUCT_SIMTRACE2 },
+ { USB_VENDOR_OPENMOKO, USB_PRODUCT_NGFF_CARDEM },
{ 0, 0 }
};
@@ -420,7 +339,7 @@ int main(int argc, char **argv)
while (1) {
int option_index = 0;
- char c = getopt_long(argc, argv, "hi:kV:P:C:I:S:A:", opts, &option_index);
+ int c = getopt_long(argc, argv, "hi:kV:P:C:I:S:A:", opts, &option_index);
if (c == -1)
break;
switch (c) {
@@ -456,13 +375,13 @@ int main(int argc, char **argv)
}
/* Scan for available SIMtrace USB devices supporting sniffing */
- rc = libusb_init(NULL);
+ rc = osmo_libusb_init(NULL);
if (rc < 0) {
fprintf(stderr, "libusb initialization failed\n");
goto do_exit;
}
struct usb_interface_match ifm_scan[16];
- int num_interfaces = usb_match_interfaces(NULL, compatible_dev_ids,
+ int num_interfaces = osmo_libusb_find_matching_interfaces(NULL, compatible_dev_ids,
USB_CLASS_PROPRIETARY, SIMTRACE_SNIFFER_USB_SUBCLASS, -1, ifm_scan, ARRAY_SIZE(ifm_scan));
if (num_interfaces <= 0) {
perror("No compatible USB devices found");
@@ -523,9 +442,9 @@ int main(int argc, char **argv)
}
struct usb_interface_match ifm_selected = ifm_filtered[0];
printf("Using USB device %04x:%04x Addr=%u, Path=%s, Cfg=%u, Intf=%u, Alt=%u: %d/%d/%d ",
- ifm_selected.vendor, ifm_selected.product, ifm_selected.addr, ifm_selected.path,
- ifm_selected.configuration, ifm_selected.interface, ifm_selected.altsetting,
- ifm_selected.class, ifm_selected.sub_class, ifm_selected.protocol);
+ ifm_selected.vendor, ifm_selected.product, ifm_selected.addr, ifm_selected.path,
+ ifm_selected.configuration, ifm_selected.interface, ifm_selected.altsetting,
+ ifm_selected.class, ifm_selected.sub_class, ifm_selected.protocol);
libusb_device_handle *dev_handle;
rc = libusb_open(ifm_selected.usb_dev, &dev_handle);
if (rc < 0) {
@@ -542,19 +461,18 @@ int main(int argc, char **argv)
}
printf("(%s)\n", strbuf);
- g_gti = gsmtap_source_init(gsmtap_host, GSMTAP_UDP_PORT, 0);
- if (!g_gti) {
+ rc = osmo_st2_gsmtap_init(gsmtap_host);
+ if (rc < 0) {
perror("unable to open GSMTAP");
goto close_exit;
}
- gsmtap_source_add_sink(g_gti);
signal(SIGINT, &signal_handler);
do {
- _transp.usb_devh = usb_open_claim_interface(NULL, &ifm_selected);
+ _transp.usb_devh = osmo_libusb_open_claim_interface(NULL, NULL, &ifm_selected);
if (!_transp.usb_devh) {
- fprintf(stderr, "can't open USB device\n");
+ fprintf(stderr, "can't open USB device: %s\n", strerror(errno));
goto close_exit;
}
@@ -564,8 +482,8 @@ int main(int argc, char **argv)
goto close_exit;
}
- rc = get_usb_ep_addrs(_transp.usb_devh, ifm_selected.interface, &_transp.usb_ep.out,
- &_transp.usb_ep.in, &_transp.usb_ep.irq_in);
+ rc = osmo_libusb_get_ep_addrs(_transp.usb_devh, ifm_selected.interface, &_transp.usb_ep.out,
+ &_transp.usb_ep.in, &_transp.usb_ep.irq_in);
if (rc < 0) {
fprintf(stderr, "can't obtain EP addrs; rc=%d\n", rc);
goto close_exit;
@@ -583,7 +501,7 @@ close_exit:
sleep(1);
} while (keep_running);
- libusb_exit(NULL);
+ osmo_libusb_exit(NULL);
do_exit:
return ret;
}
diff --git a/host/src/simtrace2-tool.c b/host/src/simtrace2-tool.c
new file mode 100644
index 0000000..fdf0d56
--- /dev/null
+++ b/host/src/simtrace2-tool.c
@@ -0,0 +1,361 @@
+/* simtrace2-tool - main program for the host PC to provide a remote SIM
+ * using the SIMtrace 2 firmware in card emulation mode
+ *
+ * (C) 2019 by Harald Welte <hwelte@hmw-consulting.de>
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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.
+ */
+
+#include <errno.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include <signal.h>
+#define _GNU_SOURCE
+#include <getopt.h>
+
+#include <sys/types.h>
+
+#include <libusb.h>
+
+#include <osmocom/usb/libusb.h>
+#include <osmocom/simtrace2/simtrace2_api.h>
+#include <osmocom/simtrace2/simtrace_prot.h>
+#include <osmocom/simtrace2/gsmtap.h>
+
+#include <osmocom/core/utils.h>
+#include <osmocom/core/msgb.h>
+#include <osmocom/core/logging.h>
+#include <osmocom/core/application.h>
+
+/***********************************************************************
+ * Incoming Messages
+ ***********************************************************************/
+
+static void print_welcome(void)
+{
+ printf("simtrace2-tool\n"
+ "(C) 2019 Harald Welte <laforge@gnumonks.org>\n");
+}
+
+static void print_help(void)
+{
+ printf( "simtrace2-tool [OPTIONS] COMMAND\n\n");
+ printf( "Options:\n"
+ "\t-h\t--help\n"
+ "\t-V\t--usb-vendor\tVENDOR_ID\n"
+ "\t-P\t--usb-product\tPRODUCT_ID\n"
+ "\t-C\t--usb-config\tCONFIG_ID\n"
+ "\t-I\t--usb-interface\tINTERFACE_ID\n"
+ "\t-S\t--usb-altsetting ALTSETTING_ID\n"
+ "\t-A\t--usb-address\tADDRESS\n"
+ "\t-H\t--usb-path\tPATH\n"
+ "\n"
+ );
+ printf( "Commands:\n"
+ "\tmodem reset (enable|disable|cycle)\n"
+ "\tmodem sim-switch (local|remote)\n"
+ "\tmodem sim-card (insert|remove)\n"
+ "\n");
+}
+
+static const struct option opts[] = {
+ { "help", 0, 0, 'h' },
+ { "usb-vendor", 1, 0, 'V' },
+ { "usb-product", 1, 0, 'P' },
+ { "usb-config", 1, 0, 'C' },
+ { "usb-interface", 1, 0, 'I' },
+ { "usb-altsetting", 1, 0, 'S' },
+ { "usb-address", 1, 0, 'A' },
+ { "usb-path", 1, 0, 'H' },
+ { NULL, 0, 0, 0 }
+};
+
+static void run_mainloop(struct osmo_st2_cardem_inst *ci)
+{
+ struct osmo_st2_transport *transp = ci->slot->transp;
+ uint8_t buf[16*265];
+ int xfer_len;
+ int rc;
+
+ while (1) {
+ /* read data from SIMtrace2 device */
+ rc = libusb_bulk_transfer(transp->usb_devh, transp->usb_ep.in,
+ buf, sizeof(buf), &xfer_len, 100);
+ if (rc < 0 && rc != LIBUSB_ERROR_TIMEOUT &&
+ rc != LIBUSB_ERROR_INTERRUPTED &&
+ rc != LIBUSB_ERROR_IO) {
+ fprintf(stderr, "BULK IN transfer error; rc=%d\n", rc);
+ return;
+ }
+ /* break the loop if no new messages arrive within 100ms */
+ if (rc == LIBUSB_ERROR_TIMEOUT)
+ return;
+ }
+}
+
+static struct osmo_st2_transport _transp;
+
+static struct osmo_st2_slot _slot = {
+ .transp = &_transp,
+ .slot_nr = 0,
+};
+
+struct osmo_st2_cardem_inst _ci = {
+ .slot = &_slot,
+};
+
+struct osmo_st2_cardem_inst *ci = &_ci;
+
+/* perform a modem reset */
+static int do_modem_reset(int argc, char **argv)
+{
+ char *command;
+ if (argc < 1)
+ command = "cycle";
+ else {
+ command = argv[0];
+ argc--;
+ argv++;
+ }
+
+ if (!strcmp(command, "enable")) {
+ printf("Activating Modem RESET\n");
+ return osmo_st2_modem_reset_active(ci->slot);
+ } else if (!strcmp(command, "disable")) {
+ printf("Deactivating Modem RESET\n");
+ return osmo_st2_modem_reset_inactive(ci->slot);
+ } else if (!strcmp(command, "cycle")) {
+ printf("Pulsing Modem RESET (1s)\n");
+ return osmo_st2_modem_reset_pulse(ci->slot, 1000);
+ } else {
+ fprintf(stderr, "Unsupported modem reset command: '%s'\n", command);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+/* switch between local and remote (emulated) SIM */
+static int do_modem_sim_switch(int argc, char **argv)
+{
+ char *command;
+ if (argc < 1)
+ return -EINVAL;
+ command = argv[0];
+ argc--;
+ argv++;
+
+ if (!strcmp(command, "local")) {
+ printf("Setting SIM=LOCAL; Modem reset recommended\n");
+ return osmo_st2_modem_sim_select_local(ci->slot);
+ } else if (!strcmp(command, "remote")) {
+ printf("Setting SIM=REMOTE; Modem reset recommended\n");
+ return osmo_st2_modem_sim_select_remote(ci->slot);
+ } else {
+ fprintf(stderr, "Unsupported modem sim-switch command: '%s'\n", command);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+/* emulate SIM card insertion / removal from modem */
+static int do_modem_sim_card(int argc, char **argv)
+{
+ char *command;
+ if (argc < 1)
+ return -EINVAL;
+ command = argv[0];
+ argc--;
+ argv++;
+
+ if (!strcmp(command, "insert")) {
+ printf("Setting SIM=INSERTED; Modem reset recommended\n");
+ return osmo_st2_cardem_request_card_insert(ci, 1);
+ } else if (!strcmp(command, "remove")) {
+ printf("Setting SIM=REMOVED; Modem reset recommended\n");
+ return osmo_st2_cardem_request_card_insert(ci, 0);
+ } else {
+ fprintf(stderr, "Unsupported modem sim-card command: '%s'\n", command);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int do_subsys_modem(int argc, char **argv)
+{
+ char *command;
+ int rc;
+
+ if (argc < 1)
+ return -EINVAL;
+ command = argv[0];
+ argc--;
+ argv++;
+
+ if (!strcmp(command, "reset")) {
+ rc = do_modem_reset(argc, argv);
+ } else if (!strcmp(command, "sim-switch")) {
+ rc = do_modem_sim_switch(argc, argv);
+ } else if (!strcmp(command, "sim-card")) {
+ rc = do_modem_sim_card(argc, argv);
+ } else {
+ fprintf(stderr, "Unsupported command for subsystem modem: '%s'\n", command);
+ return -EINVAL;
+ }
+
+ return rc;
+}
+
+static int do_command(int argc, char **argv)
+{
+ char *subsys;
+ int rc;
+
+ if (argc < 1)
+ return -EINVAL;
+ subsys = argv[0];
+ argc--;
+ argv++;
+
+ if (!strcmp(subsys, "modem"))
+ rc = do_subsys_modem(argc, argv);
+ else {
+ fprintf(stderr, "Unsupported subsystem '%s'\n", subsys);
+ rc = -EINVAL;
+ }
+
+ return rc;
+}
+
+static struct log_info log_info = {};
+
+int main(int argc, char **argv)
+{
+ struct osmo_st2_transport *transp = ci->slot->transp;
+ int rc;
+ int c, ret = 1;
+ int if_num = 0, vendor_id = -1, product_id = -1;
+ int config_id = -1, altsetting = 0, addr = -1;
+ char *path = NULL;
+
+ while (1) {
+ int option_index = 0;
+
+ c = getopt_long(argc, argv, "hV:P:C:I:S:A:H:", opts, &option_index);
+ if (c == -1)
+ break;
+ switch (c) {
+ case 'h':
+ print_help();
+ exit(0);
+ break;
+ case 'V':
+ vendor_id = strtol(optarg, NULL, 16);
+ break;
+ case 'P':
+ product_id = strtol(optarg, NULL, 16);
+ break;
+ case 'C':
+ config_id = atoi(optarg);
+ break;
+ case 'I':
+ if_num = atoi(optarg);
+ break;
+ case 'S':
+ altsetting = atoi(optarg);
+ break;
+ case 'A':
+ addr = atoi(optarg);
+ break;
+ case 'H':
+ path = optarg;
+ break;
+ }
+ }
+
+ if (vendor_id < 0 || product_id < 0) {
+ fprintf(stderr, "You have to specify the vendor and product ID\n");
+ goto do_exit;
+ }
+
+ transp->udp_fd = -1;
+
+ print_welcome();
+
+ osmo_init_logging2(NULL, &log_info);
+
+ rc = osmo_libusb_init(NULL);
+ if (rc < 0) {
+ fprintf(stderr, "libusb initialization failed\n");
+ goto do_exit;
+ }
+
+ do {
+ if (transp->udp_fd < 0) {
+ struct usb_interface_match _ifm, *ifm = &_ifm;
+ memset(ifm, 0, sizeof(*ifm));
+ ifm->vendor = vendor_id;
+ ifm->product = product_id;
+ ifm->configuration = config_id;
+ ifm->interface = if_num;
+ ifm->altsetting = altsetting;
+ if (addr > 0 && addr < 256)
+ ifm->addr = addr;
+ if (path)
+ osmo_strlcpy(ifm->path, path, sizeof(ifm->path));
+ transp->usb_devh = osmo_libusb_open_claim_interface(NULL, NULL, ifm);
+ if (!transp->usb_devh) {
+ fprintf(stderr, "can't open USB device: %s\n", strerror(errno));
+ goto close_exit;
+ }
+
+ rc = osmo_libusb_get_ep_addrs(transp->usb_devh, if_num, &transp->usb_ep.out,
+ &transp->usb_ep.in, &transp->usb_ep.irq_in);
+ if (rc < 0) {
+ fprintf(stderr, "can't obtain EP addrs; rc=%d\n", rc);
+ goto close_exit;
+ }
+ }
+
+ if (argc - optind <= 0) {
+ fprintf(stderr, "You have to specify a command to execute\n");
+ exit(1);
+ }
+
+ rc = do_command(argc-optind, argv+optind);
+ switch (rc) {
+ case 0:
+ break;
+ case -EINVAL:
+ fprintf(stderr, "Error: Invalid command/syntax\n");
+ exit(1);
+ break;
+ default:
+ fprintf(stderr, "Error executing command: %d\n", rc);
+ exit(1);
+ break;
+ }
+
+ run_mainloop(ci);
+ ret = 0;
+
+ libusb_release_interface(transp->usb_devh, 0);
+close_exit:
+ if (transp->usb_devh)
+ libusb_close(transp->usb_devh);
+ } while (0);
+
+ osmo_libusb_exit(NULL);
+do_exit:
+ return ret;
+}
diff --git a/host/simtrace2_usb.c b/host/src/simtrace2_usb.c
index 1e3104a..b329ead 100644
--- a/host/simtrace2_usb.c
+++ b/host/src/simtrace2_usb.c
@@ -11,10 +11,6 @@
* 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 this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <stdio.h>
#include <stdint.h>
@@ -22,25 +18,21 @@
#include <errno.h>
#include <osmocom/core/utils.h>
+#include <osmocom/core/logging.h>
+#include <osmocom/core/application.h>
-#include "libusb_util.h"
-#include "simtrace_usb.h"
-
-static const struct dev_id compatible_dev_ids[] = {
- { USB_VENDOR_OPENMOKO, USB_PRODUCT_OWHW_SAM3 },
- { USB_VENDOR_OPENMOKO, USB_PRODUCT_QMOD_SAM3 },
- { USB_VENDOR_OPENMOKO, USB_PRODUCT_SIMTRACE2 },
- { 0, 0 }
-};
+#include <osmocom/usb/libusb.h>
+#include <osmocom/simtrace2/simtrace_usb.h>
+#include <osmocom/simtrace2/usb_util.h>
static int find_devices(void)
{
struct usb_interface_match ifm[16];
int rc, i, num_interfaces;
- /* scan for USB devices matching SIMtrace USB ID with proprietary class */
- rc = usb_match_interfaces(NULL, compatible_dev_ids,
- USB_CLASS_PROPRIETARY, -1, -1, ifm, ARRAY_SIZE(ifm));
+ /* scan for USB devices matching SIMtrace USB ID with proprietary class */
+ rc = osmo_libusb_find_matching_interfaces(NULL, osmo_st2_compatible_dev_ids,
+ USB_CLASS_PROPRIETARY, -1, -1, ifm, ARRAY_SIZE(ifm));
printf("USB matches: %d\n", rc);
if (rc < 0)
return rc;
@@ -81,9 +73,12 @@ static int find_devices(void)
return num_interfaces;
}
+static struct log_info log_info = {};
+
int main(int argc, char **argv)
{
- libusb_init(NULL);
+ osmo_init_logging2(NULL, &log_info);
+ OSMO_ASSERT(osmo_libusb_init(NULL) == 0);
find_devices();
return 0;
}
diff --git a/host/usb2udp.c b/host/usb2udp.c
deleted file mode 100644
index 97ffad0..0000000
--- a/host/usb2udp.c
+++ /dev/null
@@ -1,286 +0,0 @@
-/* simtrace - main program for the host PC
- *
- * (C) 2010-2016 by Harald Welte <hwelte@hmw-consulting.de>
- *
- * This program 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 2
- * of the License, or (at your option) any later version.
- *
- * This program 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 this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-#include <errno.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdint.h>
-#include <time.h>
-#define _GNU_SOURCE
-#include <getopt.h>
-#include <poll.h>
-
-#include <sys/time.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-#include <libusb.h>
-
-#include "simtrace_usb.h"
-#include "simtrace_prot.h"
-#include "apdu_dispatch.h"
-#include "simtrace2-discovery.h"
-
-#include <osmocom/core/utils.h>
-#include <osmocom/core/socket.h>
-#include <osmocom/core/select.h>
-
-struct libusb_device_handle *g_devh;
-static struct sockaddr_in g_sa_remote;
-static struct osmo_fd g_udp_ofd;
-
-static void print_welcome(void)
-{
- printf("usb2udp - UDP/IP forwarding of SIMtrace card emulation\n"
- "(C) 2016 by Harald Welte <laforge@gnumonks.org>\n\n");
-}
-
-static void print_help(void)
-{
- printf( "\t-h\t--help\n"
- "\t-i\t--interface <0-255>\n"
- "\n"
- );
-}
-
-struct ep_buf {
- uint8_t ep;
- uint8_t buf[1024];
- struct libusb_transfer *xfer;
-};
-static struct ep_buf g_buf_in;
-static struct ep_buf g_buf_out;
-
-static void usb_in_xfer_cb(struct libusb_transfer *xfer)
-{
- int rc;
-
- printf("xfer_cb(ep=%02x): status=%d, flags=0x%x, type=%u, len=%u, act_len=%u\n",
- xfer->endpoint, xfer->status, xfer->flags, xfer->type, xfer->length, xfer->actual_length);
- switch (xfer->status) {
- case LIBUSB_TRANSFER_COMPLETED:
- if (xfer->endpoint == g_buf_in.ep) {
- /* process the data */
- printf("read %d bytes from SIMTRACE, forwarding to UDP\n", xfer->actual_length);
- rc = sendto(g_udp_ofd.fd, xfer->buffer, xfer->actual_length, 0, (struct sockaddr *)&g_sa_remote, sizeof(g_sa_remote));
- if (rc <= 0) {
- fprintf(stderr, "error writing to UDP\n");
- }
- /* and re-submit the URB */
- libusb_submit_transfer(xfer);
- } else if (xfer->endpoint == g_buf_out.ep) {
- /* re-enable reading from the UDP side */
- g_udp_ofd.when |= BSC_FD_READ;
- }
- break;
- default:
- fprintf(stderr, "xfer_cb(ERROR '%s')\n", osmo_hexdump_nospc(xfer->buffer, xfer->actual_length));
- break;
- }
-}
-
-static void init_ep_buf(struct ep_buf *epb)
-{
- if (!epb->xfer)
- epb->xfer = libusb_alloc_transfer(0);
-
- epb->xfer->flags = 0;
-
- libusb_fill_bulk_transfer(epb->xfer, g_devh, epb->ep, epb->buf, sizeof(epb->buf), usb_in_xfer_cb, NULL, 0);
-}
-
-/***********************************************************************
- * libosmocore main loop integration of libusb async I/O
- ***********************************************************************/
-
-static int g_libusb_pending = 0;
-
-static int ofd_libusb_cb(struct osmo_fd *ofd, unsigned int what)
-{
- /* FIXME */
- g_libusb_pending = 1;
-
- return 0;
-}
-
-/* call-back when libusb adds a FD */
-static void libusb_fd_added_cb(int fd, short events, void *user_data)
-{
- struct osmo_fd *ofd = talloc_zero(NULL, struct osmo_fd);
-
- printf("%s(%u, %x)\n", __func__, fd, events);
-
- ofd->fd = fd;
- ofd->cb = &ofd_libusb_cb;
- if (events & POLLIN)
- ofd->when |= BSC_FD_READ;
- if (events & POLLOUT)
- ofd->when |= BSC_FD_WRITE;
-
- osmo_fd_register(ofd);
-}
-
-/* call-back when libusb removes a FD */
-static void libusb_fd_removed_cb(int fd, void *user_data)
-{
-
- printf("%s(%u)\n", __func__, fd);
-#if 0
- struct osmo_fd *ofd;
- /* FIXME: This needs new export in libosmocore! */
- ofd = osmo_fd_get_by_fd(fd);
-
- if (ofd) {
- osmo_fd_unregister(ofd);
- talloc_free(ofd);
- }
-#endif
-}
-
-/* call-back when the UDP socket is readable */
-static int ofd_udp_cb(struct osmo_fd *ofd, unsigned int what)
-{
- int rc;
- socklen_t addrlen = sizeof(g_sa_remote);
-
- rc = recvfrom(ofd->fd, g_buf_out.buf, sizeof(g_buf_out.buf), 0,
- (struct sockaddr *)&g_sa_remote, &addrlen);
- if (rc <= 0) {
- fprintf(stderr, "error reading from UDP\n");
- return 0;
- }
- printf("read %d bytes from UDP, forwarding to SIMTRACE\n", rc);
- g_buf_out.xfer->length = rc;
-
- /* disable further READ interest for the UDP socket */
- ofd->when &= ~BSC_FD_READ;
-
- /* submit the URB on the OUT end point */
- libusb_submit_transfer(g_buf_out.xfer);
-
- return 0;
-}
-
-static void run_mainloop(void)
-{
- int rc;
-
- printf("Entering main loop\n");
-
- while (1) {
- osmo_select_main(0);
- if (g_libusb_pending) {
- struct timeval tv;
- memset(&tv, 0, sizeof(tv));
- rc = libusb_handle_events_timeout_completed(NULL, &tv, NULL);
- if (rc != 0) {
- fprintf(stderr, "handle_events_timeout_completed == %d\n", rc);
- break;
- }
- }
- }
-}
-
-int main(int argc, char **argv)
-{
- int rc;
- int c, ret = 1;
- int local_udp_port = 52342;
- unsigned int if_num = 0;
-
- print_welcome();
-
- while (1) {
- int option_index = 0;
- static const struct option opts[] = {
- { "udp-port", 1, 0, 'u' },
- { "interface", 1, 0, 'I' },
- { "help", 0, 0, 'h' },
- { NULL, 0, 0, 0 }
- };
-
- c = getopt_long(argc, argv, "u:I:h", opts, &option_index);
- if (c == -1)
- break;
- switch (c) {
- case 'u':
- local_udp_port = atoi(optarg);
- break;
- case 'I':
- if_num = atoi(optarg);
- break;
- case 'h':
- print_help();
- exit(0);
- break;
- }
- }
-
- rc = libusb_init(NULL);
- if (rc < 0) {
- fprintf(stderr, "libusb initialization failed\n");
- goto close_exit;
- }
-
- libusb_set_pollfd_notifiers(NULL, &libusb_fd_added_cb, &libusb_fd_removed_cb, NULL);
-
- g_devh = libusb_open_device_with_vid_pid(NULL, USB_VENDOR_OPENMOKO, USB_PRODUCT_OWHW_SAM3);
- if (!g_devh) {
- fprintf(stderr, "can't open USB device\n");
- goto close_exit;
- }
-
- rc = libusb_claim_interface(g_devh, if_num);
- if (rc < 0) {
- fprintf(stderr, "can't claim interface %u; rc=%d\n", if_num, rc);
- goto close_exit;
- }
-
- /* open UDP socket, register with select handling and mark it
- * readable */
- g_udp_ofd.cb = ofd_udp_cb;
- osmo_sock_init_ofd(&g_udp_ofd, AF_INET, SOCK_DGRAM, IPPROTO_UDP, NULL, local_udp_port + if_num, OSMO_SOCK_F_BIND);
-
- rc = get_usb_ep_addrs(g_devh, if_num, &g_buf_out.ep, &g_buf_in.ep, NULL);
- if (rc < 0) {
- fprintf(stderr, "couldn't find enpdoint addresses; rc=%d\n", rc);
- goto close_exit;
- }
- /* initialize USB buffers / transfers */
- init_ep_buf(&g_buf_out);
- init_ep_buf(&g_buf_in);
-
- /* submit the first transfer for the IN endpoint */
- libusb_submit_transfer(g_buf_in.xfer);
-
- run_mainloop();
-
- ret = 0;
-
- libusb_release_interface(g_devh, 0);
-close_exit:
- if (g_devh)
- libusb_close(g_devh);
-
- libusb_exit(NULL);
- return ret;
-}