diff --git a/Android.mk b/Android.mk new file mode 100644 index 000000000..bbde07405 --- /dev/null +++ b/Android.mk @@ -0,0 +1,75 @@ +# +# Copyright (C) 2016 The CyanogenMod Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# This contains the module build definitions for the hardware-specific +# components for this device. +# +# As much as possible, those components should be built unconditionally, +# with device-specific names to avoid collisions, to avoid device-specific +# bitrot and build breakages. Building a component unconditionally does +# *not* include it on all devices, so it is safe even with hardware-specific +# components. + +LOCAL_PATH := $(call my-dir) + +ifeq ($(TARGET_DEVICE),z2_plus) + +include $(call all-makefiles-under,$(LOCAL_PATH)) + +include $(CLEAR_VARS) + +LOCAL_MODULE := wifi_symlinks +LOCAL_MODULE_TAGS := optional +LOCAL_MODULE_CLASS := FAKE +LOCAL_MODULE_SUFFIX := -timestamp + +include $(BUILD_SYSTEM)/base_rules.mk + +$(LOCAL_BUILT_MODULE): ACTUAL_INI_FILE := /system/etc/wifi/WCNSS_qcom_cfg.ini +$(LOCAL_BUILT_MODULE): WCNSS_INI_SYMLINK := $(TARGET_OUT)/etc/firmware/wlan/qca_cld/WCNSS_qcom_cfg.ini + +$(LOCAL_BUILT_MODULE): ACTUAL_MAC_FILE := /persist/wlan_mac.bin +$(LOCAL_BUILT_MODULE): WCNSS_MAC_SYMLINK := $(TARGET_OUT)/etc/firmware/wlan/qca_cld/wlan_mac.bin + + +$(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/Android.mk +$(LOCAL_BUILT_MODULE): + $(hide) echo "Making symlinks for wifi" + $(hide) mkdir -p $(dir $@) + $(hide) mkdir -p $(dir $(WCNSS_INI_SYMLINK)) + $(hide) rm -rf $@ + $(hide) rm -rf $(WCNSS_INI_SYMLINK) + $(hide) ln -sf $(ACTUAL_INI_FILE) $(WCNSS_INI_SYMLINK) + $(hide) rm -rf $(WCNSS_MAC_SYMLINK) + $(hide) ln -sf $(ACTUAL_MAC_FILE) $(WCNSS_MAC_SYMLINK) + $(hide) touch $@ + +include $(call all-makefiles-under,$(LOCAL_PATH)) + +IMS_LIBS := libimscamera_jni.so libimsmedia_jni.so + +IMS_SYMLINKS := $(addprefix $(TARGET_OUT)/app/ims/lib/arm64/,$(notdir $(IMS_LIBS))) +$(IMS_SYMLINKS): $(LOCAL_INSTALLED_MODULE) + @echo "IMS lib link: $@" + @mkdir -p $(dir $@) + @rm -rf $@ + $(hide) ln -sf /system/vendor/lib64/$(notdir $@) $@ + +ALL_DEFAULT_INSTALLED_MODULES += $(IMS_SYMLINKS) + +include device/zuk/z2_plus/tftp.mk + +endif diff --git a/BoardConfig.mk b/BoardConfig.mk new file mode 100644 index 000000000..0977f389a --- /dev/null +++ b/BoardConfig.mk @@ -0,0 +1,213 @@ +# Copyright (C) 2016 The CyanogenMod Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# +# This file sets variables that control the way modules are built +# thorughout the system. It should not be used to conditionally +# disable makefiles (the proper mechanism to control what gets +# included in a build is to use PRODUCT_PACKAGES in a product +# definition file). +# + +# Boldly go. +USE_CLANG_PLATFORM_BUILD := true + +TARGET_OTA_ASSERT_DEVICE := z2,Z2,z2plus,z2_plus + +PLATFORM_PATH := device/zuk/z2_plus + +TARGET_SPECIFIC_HEADER_PATH := $(PLATFORM_PATH)/include + +BOARD_VENDOR := zuk + +# CM building options +CM_DEVELOPER := Fedor917 +CM_BUILDTYPE := UNOFFICIAL + +# Bootloader +TARGET_BOOTLOADER_BOARD_NAME := msm8996 +TARGET_NO_BOOTLOADER := true + +# Platform +TARGET_BOARD_PLATFORM := msm8996 +TARGET_BOARD_PLATFORM_GPU := qcom-adreno530 + +# Architecture +TARGET_ARCH := arm64 +TARGET_ARCH_VARIANT := armv8-a +TARGET_CPU_ABI := arm64-v8a +TARGET_CPU_ABI2 := +TARGET_CPU_VARIANT := kryo + +TARGET_2ND_ARCH := arm +TARGET_2ND_ARCH_VARIANT := armv7-a-neon +TARGET_2ND_CPU_ABI := armeabi-v7a +TARGET_2ND_CPU_ABI2 := armeabi +TARGET_2ND_CPU_VARIANT := cortex-a53 + +ENABLE_CPUSETS := true + +TARGET_USES_64_BIT_BINDER := true + +# Kernel +BOARD_KERNEL_CMDLINE := console=tty60,115200,n8 androidboot.hardware=qcom user_debug=31 msm_rtb.filter=0x237 ehci-hcd.park=3 lpm_levels.sleep_disabled=1 cma=16M@0-0xffffffff androidboot.selinux=permissive +BOARD_KERNEL_BASE := 0x80000000 +BOARD_KERNEL_PAGESIZE := 4096 +BOARD_KERNEL_TAGS_OFFSET := 0x00000100 +BOARD_RAMDISK_OFFSET := 0x01000000 +BOARD_KERNEL_IMAGE_NAME := Image.gz-dtb +TARGET_KERNEL_APPEND_DTB := true +TARGET_KERNEL_ARCH := arm64 +TARGET_KERNEL_HEADER_ARCH := arm64 +TARGET_KERNEL_CROSS_COMPILE_PREFIX := aarch64-linux-android- +TARGET_KERNEL_CONFIG := cyanogenmod_z2_defconfig +TARGET_KERNEL_SOURCE := kernel/zuk/msm8996 + +# QCOM hardware +BOARD_USES_QCOM_HARDWARE := true + +BLOCK_BASED_OTA := true + +# ANT+ +BOARD_ANT_WIRELESS_DEVICE := "qualcomm-uart" + +# Audio +USE_CUSTOM_AUDIO_POLICY := 1 +BOARD_USES_ALSA_AUDIO := true +AUDIO_USE_LL_AS_PRIMARY_OUTPUT := true +AUDIO_FEATURE_ENABLED_ACDB_LICENSE := true +AUDIO_FEATURE_ENABLED_ANC_HEADSET := true +AUDIO_FEATURE_ENABLED_AUDIOSPHERE := true +AUDIO_FEATURE_ENABLED_COMPRESS_VOIP := true +AUDIO_FEATURE_ENABLED_DEV_ARBI := true +AUDIO_FEATURE_ENABLED_EXTN_FORMATS := true +AUDIO_FEATURE_ENABLED_FLAC_OFFLOAD := true +AUDIO_FEATURE_ENABLED_FLUENCE := true +AUDIO_FEATURE_ENABLED_HFP := true +AUDIO_FEATURE_ENABLED_KPI_OPTIMIZE := true +AUDIO_FEATURE_ENABLED_NT_PAUSE_TIMEOUT := true +AUDIO_FEATURE_ENABLED_PCM_OFFLOAD := true +AUDIO_FEATURE_ENABLED_PCM_OFFLOAD_24 := true +AUDIO_FEATURE_ENABLED_PROXY_DEVICE := true +AUDIO_FEATURE_ENABLED_MULTI_VOICE_SESSIONS := true + +# Bluetooth +BOARD_BLUETOOTH_BDROID_BUILDCFG_INCLUDE_DIR := $(PLATFORM_PATH)/bluetooth +BOARD_HAS_QCA_BT_ROME := true +BOARD_HAVE_BLUETOOTH := true +BOARD_HAVE_BLUETOOTH_QCOM := true +QCOM_BT_USE_BTNV := true +QCOM_BT_USE_SMD_TTY := true + +# Camera +BOARD_QTI_CAMERA_32BIT_ONLY := true +USE_DEVICE_SPECIFIC_CAMERA := true + +# Charger +BOARD_CHARGER_ENABLE_SUSPEND := true +BOARD_CHARGER_DISABLE_INIT_BLANK := true +BOARD_HAL_STATIC_LIBRARIES += libhealthd.zuk + +# CM Hardware +BOARD_HARDWARE_CLASS += $(PLATFORM_PATH)/cmhw +TARGET_TAP_TO_WAKE_NODE := "/sys/devices/virtual/touch/tp_dev/gesture_on" + +# CNE and DPM +TARGET_LDPRELOAD := libNimsWrap.so +BOARD_USES_QCNE := true + +# Crypto +TARGET_HW_DISK_ENCRYPTION := true + +# Display +TARGET_CONTINUOUS_SPLASH_ENABLED := true +TARGET_USES_C2D_COMPOSITION := true +TARGET_USES_ION := true +TARGET_USES_OVERLAY := true +USE_OPENGL_RENDERER := true +MAX_EGL_CACHE_KEY_SIZE := 12*1024 +MAX_EGL_CACHE_SIZE := 2048*1024 +OVERRIDE_RS_DRIVER:= libRSDriver_adreno.so +MAX_VIRTUAL_DISPLAY_DIMENSION := 4096 +TARGET_FORCE_HWC_FOR_VIRTUAL_DISPLAYS := true + +# GPS +TARGET_NO_RPC := true +USE_DEVICE_SPECIFIC_GPS := true + +# Init +TARGET_INIT_VENDOR_LIB := libinit_z2_plus +TARGET_RECOVERY_DEVICE_MODULES := libinit_z2_plus +TARGET_PLATFORM_DEVICE_BASE := /devices/soc/ + +# Keystore +TARGET_PROVIDES_KEYMASTER := true + +# Lights +TARGET_PROVIDES_LIBLIGHT := true + +# Partitions +BOARD_BOOTIMAGE_PARTITION_SIZE := 67108864 +BOARD_CACHEIMAGE_PARTITION_SIZE := 268435456 +BOARD_RECOVERYIMAGE_PARTITION_SIZE := 67108864 +BOARD_SYSTEMIMAGE_PARTITION_SIZE := 3154116608 +BOARD_USERDATAIMAGE_PARTITION_SIZE := 57436708864 +BOARD_FLASH_BLOCK_SIZE := 262144 + +# RIL +TARGET_RIL_VARIANT := caf +PROTOBUF_SUPPORTED := true + +# Recovery +TARGET_RECOVERY_FSTAB := device/zuk/z2_plus/rootdir/etc/recovery/recovery.fstab +TARGET_USERIMAGES_USE_EXT4 := true +TARGET_USERIMAGES_USE_F2FS := true +TW_INCLUDE_CRYPTO := true +BOARD_HAS_NO_REAL_SDCARD := true +RECOVERY_SDCARD_ON_DATA := true +BOARD_HAS_LARGE_FILESYSTEM := true +DEVICE_RESOLUTION := 1080x1920 +HAVE_SELINUX := true +TARGET_RECOVERY_PIXEL_FORMAT := "BGBX_8888" + +# SELinux +include device/qcom/sepolicy/sepolicy.mk + +BOARD_SEPOLICY_DIRS += $(PLATFORM_PATH)/sepolicy + +# Sensors +USE_SENSOR_MULTI_HAL := true + +# Wifi +BOARD_HAS_QCOM_WLAN := true +BOARD_HAS_QCOM_WLAN_SDK := true +BOARD_WLAN_DEVICE := qcwcn +BOARD_HOSTAPD_DRIVER := NL80211 +BOARD_HOSTAPD_PRIVATE_LIB := lib_driver_cmd_$(BOARD_WLAN_DEVICE) +HOSTAPD_VERSION := VER_0_8_X +BOARD_WPA_SUPPLICANT_DRIVER := NL80211 +BOARD_WPA_SUPPLICANT_PRIVATE_LIB := lib_driver_cmd_$(BOARD_WLAN_DEVICE) +WIFI_DRIVER_FW_PATH_AP := "ap" +WIFI_DRIVER_FW_PATH_STA := "sta" +WIFI_DRIVER_FW_PATH_P2P := "p2p" +WIFI_DRIVER_MODULE_PATH := "/system/lib/modules/wlan.ko" +WIFI_DRIVER_MODULE_NAME := "wlan" +WPA_SUPPLICANT_VERSION := VER_0_8_X + + +# Timeservice +BOARD_USES_QC_TIME_SERVICES := true + +# inherit from the proprietary version +-include vendor/zuk/z2_plus/BoardConfigVendor.mk diff --git a/README.md b/README.md index e7062a3c8..9f212309e 100644 --- a/README.md +++ b/README.md @@ -1 +1,2 @@ -# android_device_zuk_z2_plus \ No newline at end of file +Device configuration for ZUK Z2 Plus by Fedor917 +For CM13 and RR diff --git a/audio/aanc_tuning_mixer.txt b/audio/aanc_tuning_mixer.txt new file mode 100644 index 000000000..35743ff58 --- /dev/null +++ b/audio/aanc_tuning_mixer.txt @@ -0,0 +1,143 @@ +#ANC_TEST_P_PATH_MIC_STEREO Capture +acdb_dev_id:85 +!Capture +Txdevice:0 + +enable +AIF1_CAP Mixer SLIM TX7:1 +AIF1_CAP Mixer SLIM TX8:1 +SLIM TX7 MUX:DEC7 +ADC MUX7:DMIC +DMIC MUX7:DMIC3 +SLIM TX8 MUX:DEC8 +ADC MUX8:DMIC +DMIC MUX8:DMIC2 +SLIM_0_TX Channels:Two +MultiMedia1 Mixer SLIM_0_TX:1 + +disable +MultiMedia1 Mixer SLIM_0_TX:0 +AIF1_CAP Mixer SLIM TX7:0 +AIF1_CAP Mixer SLIM TX8:0 +SLIM TX7 MUX:ZERO +SLIM TX8 MUX:ZERO +DMIC MUX7:ZERO +DMIC MUX8:ZERO + +#ANC_TEST_S_PATH_MIC_STEREO Capture +acdb_dev_id:88 +!Capture +Txdevice:0 + +enable +AIF1_CAP Mixer SLIM TX7:1 +AIF1_CAP Mixer SLIM TX8:1 +SLIM TX7 MUX:DEC7 +ADC MUX7:ANC_FB_TUNE1 +ADC MUX10:DMIC +DMIC MUX10:DMIC2 +SLIM TX8 MUX:DEC8 +ADC MUX8:ANC_FB_TUNE2 +ADC MUX12:DMIC +DMIC MUX12:DMIC2 +ANC0 FB MUX:ANC_IN_EAR +ANC EAR Enable Switch:1 +SLIM_0_TX Channels:Two +MultiMedia1 Mixer SLIM_0_TX:1 + +disable +MultiMedia1 Mixer SLIM_0_TX:0 +AIF1_CAP Mixer SLIM TX7:0 +AIF1_CAP Mixer SLIM TX8:0 +SLIM TX7 MUX:ZERO +SLIM TX8 MUX:ZERO +ADC MUX7:DMIC +ADC MUX8:DMIC +DMIC MUX10:ZERO +DMIC MUX12:ZERO +ANC0 FB MUX:ZERO +ANC EAR Enable Switch:0 + + +#ANC_TEST_E_PATH_MIC_STEREO Capture +acdb_dev_id:91 +!Capture +Txdevice:0 + +enable +AIF1_CAP Mixer SLIM TX7:1 +AIF1_CAP Mixer SLIM TX8:1 +SLIM TX7 MUX:DEC7 +ADC MUX7:ANC_FB_TUNE1 +ADC MUX10:DMIC +DMIC MUX10:DMIC3 +SLIM TX8 MUX:DEC8 +ADC MUX8:ANC_FB_TUNE2 +ADC MUX12:DMIC +DMIC MUX12:DMIC3 +ANC0 FB MUX:ANC_IN_EAR +ANC EAR Enable Switch:1 +SLIM_0_TX Channels:Two +MultiMedia1 Mixer SLIM_0_TX:1 + +disable +MultiMedia1 Mixer SLIM_0_TX:0 +AIF1_CAP Mixer SLIM TX7:0 +AIF1_CAP Mixer SLIM TX8:0 +SLIM TX7 MUX:ZERO +SLIM TX8 MUX:ZERO +ADC MUX7:DMIC +ADC MUX8:DMIC +DMIC MUX10:ZERO +DMIC MUX12:ZERO +ANC0 FB MUX:ZERO +ANC EAR Enable Switch:0 + + +#ANC_TEST_S_PATH_HANDSET_SPKR_ANC_MONO +acdb_dev_id:86 +!Playback +Rxdevice:0 + +enable +ANC Function:ON +SLIM RX0 MUX:AIF_MIX1_PB +SLIM_0_RX Channels:One +RX INT0_1 MIX1 INP0:RX0 +RX INT0 DEM MUX:CLSH_DSM_OUT +RX0 Digital Volume:87 +ANC Slot:7 +EAR PA Gain:G_6_DB +SLIMBUS_0_RX Audio Mixer MultiMedia1:1 + +disable +SLIMBUS_0_RX Audio Mixer MultiMedia1:0 +ANC Slot:0 +SLIM RX0 MUX:ZERO +RX INT0_1 MIX1 INP0:ZERO +RX0 Digital Volume:0 +ANC Function:OFF + +#ANC_TEST_E_PATH_HANDSET_SPKR_ANC_MONO +acdb_dev_id:89 +!Playback +Rxdevice:0 + +enable +ANC Function:ON +SLIM RX0 MUX:AIF_MIX1_PB +SLIM_0_RX Channels:One +RX INT0_1 MIX1 INP0:RX0 +RX INT0 DEM MUX:CLSH_DSM_OUT +RX0 Digital Volume:87 +ANC Slot:8 +EAR PA Gain:G_6_DB +SLIMBUS_0_RX Audio Mixer MultiMedia1:1 + +disable +SLIMBUS_0_RX Audio Mixer MultiMedia1:0 +ANC Slot:0 +SLIM RX0 MUX:ZERO +RX INT0_1 MIX1 INP0:ZERO +RX0 Digital Volume:0 +ANC Function:OFF diff --git a/audio/audio_effects.conf b/audio/audio_effects.conf new file mode 100644 index 000000000..c3c4b6714 --- /dev/null +++ b/audio/audio_effects.conf @@ -0,0 +1,188 @@ +# List of effect libraries to load. Each library element must contain a "path" element +# giving the full path of the library .so file. +# libraries { +# { +# path +# } +# } +libraries { +# This is a proxy library that will be an abstraction for +# the HW and SW effects + + #proxy { + #path /system/lib/soundfx/libeffectproxy.so + #} + +# This is the SW implementation library of the effect + #libSW { + #path /system/lib/soundfx/libswwrapper.so + #} + +# This is the HW implementation library for the effect + #libHW { + #path /system/lib/soundfx/libhwwrapper.so + #} + + bundle { + path /system/lib/soundfx/libbundlewrapper.so + } + reverb { + path /system/lib/soundfx/libreverbwrapper.so + } + visualizer { + path /system/lib/soundfx/libvisualizer.so + } + downmix { + path /system/lib/soundfx/libdownmix.so + } + loudness_enhancer { + path /system/lib/soundfx/libldnhncr.so + } +} + +# Default pre-processing library. Add to audio_effect.conf "libraries" section if +# audio HAL implements support for default software audio pre-processing effects +# +# pre_processing { +# path /system/lib/soundfx/libaudiopreprocessing.so +# } + +# list of effects to load. Each effect element must contain a "library" and a "uuid" element. +# The value of the "library" element must correspond to the name of one library element in the +# "libraries" element. +# The name of the effect element is indicative, only the value of the "uuid" element +# designates the effect. +# The uuid is the implementation specific UUID as specified by the effect vendor. This is not the +# generic effect type UUID. +# effects { +# { +# library +# uuid +# } +# ... +# } + +effects { + +# additions for the proxy implementation +# Proxy implementation + #effectname { + #library proxy + #uuid xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + + # SW implemetation of the effect. Added as a node under the proxy to + # indicate this as a sub effect. + #libsw { + #library libSW + #uuid yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy + #} End of SW effect + + # HW implementation of the effect. Added as a node under the proxy to + # indicate this as a sub effect. + #libhw { + #library libHW + #uuid zzzzzzzz-zzzz-zzzz-zzzz-zzzzzzzzzzzz + #}End of HW effect + #} End of effect proxy + + bassboost { + library bundle + uuid 8631f300-72e2-11df-b57e-0002a5d5c51b + } + virtualizer { + library bundle + uuid 1d4033c0-8557-11df-9f2d-0002a5d5c51b + } + equalizer { + library bundle + uuid ce772f20-847d-11df-bb17-0002a5d5c51b + } + volume { + library bundle + uuid 119341a0-8469-11df-81f9-0002a5d5c51b + } + reverb_env_aux { + library reverb + uuid 4a387fc0-8ab3-11df-8bad-0002a5d5c51b + } + reverb_env_ins { + library reverb + uuid c7a511a0-a3bb-11df-860e-0002a5d5c51b + } + reverb_pre_aux { + library reverb + uuid f29a1400-a3bb-11df-8ddc-0002a5d5c51b + } + reverb_pre_ins { + library reverb + uuid 172cdf00-a3bc-11df-a72f-0002a5d5c51b + } + visualizer { + library visualizer + uuid d069d9e0-8329-11df-9168-0002a5d5c51b + } + downmix { + library downmix + uuid 93f04452-e4fe-41cc-91f9-e475b6d1d69f + } + loudness_enhancer { + library loudness_enhancer + uuid fa415329-2034-4bea-b5dc-5b381c8d1e2c + } +} + +# Default pre-processing effects. Add to audio_effect.conf "effects" section if +# audio HAL implements support for them. +# +# agc { +# library pre_processing +# uuid aa8130e0-66fc-11e0-bad0-0002a5d5c51b +# } +# aec { +# library pre_processing +# uuid bb392ec0-8d4d-11e0-a896-0002a5d5c51b +# } +# ns { +# library pre_processing +# uuid c06c8400-8e06-11e0-9cb6-0002a5d5c51b +# } + +# Audio preprocessor configurations. +# The pre processor configuration consists in a list of elements each describing +# pre processor settings for a given input source. Valid input source names are: +# "mic", "camcorder", "voice_recognition", "voice_communication" +# Each input source element contains a list of effects elements. The name of the effect +# element must be the name of one of the effects in the "effects" list of the file. +# Each effect element may optionally contain a list of parameters and their +# default value to apply when the pre processor effect is created. +# A parameter is defined by a "param" element and a "value" element. Each of these elements +# consists in one or more elements specifying a type followed by a value. +# The types defined are: "int", "short", "float", "bool" and "string" +# When both "param" and "value" are a single int, a simple form is allowed where just +# the param and value pair is present in the parameter description +# pre_processing { +# { +# { +# { +# param { +# int|short|float|bool|string +# [ int|short|float|bool|string ] +# ... +# } +# value { +# int|short|float|bool|string +# [ int|short|float|bool|string ] +# ... +# } +# } +# { } +# ... +# } +# ... +# } +# ... +# } + +# +# TODO: add default audio pre processor configurations after debug and tuning phase +# diff --git a/audio/audio_output_policy.conf b/audio/audio_output_policy.conf new file mode 100644 index 000000000..33aba7187 --- /dev/null +++ b/audio/audio_output_policy.conf @@ -0,0 +1,56 @@ +# List of profiles for the output device session where stream is routed. +# A stream opened with the inputs attributes which match the "flags" and +# "formats" as specified in the profile is routed to a device at +# sample rate specified under "sampling_rates" and bit width under +# "bit_width" and the topology extracted from the acdb data against +# the "app_type". +# +# the flags and formats are specified using the strings corresponding to +# enums in audio.h and audio_policy.h. They are concatenated with "|" +# without space or "\n". +# the flags and formats should match the ones in "audio_policy.conf" + +outputs { + default { + flags AUDIO_OUTPUT_FLAG_PRIMARY + formats AUDIO_FORMAT_PCM_16_BIT + sampling_rates 48000 + bit_width 16 + app_type 69937 + } + deep_buffer { + flags AUDIO_OUTPUT_FLAG_DEEP_BUFFER + formats AUDIO_FORMAT_PCM_16_BIT + sampling_rates 48000 + bit_width 16 + app_type 69936 + } + direct { + flags AUDIO_OUTPUT_FLAG_DIRECT + formats AUDIO_FORMAT_PCM_16_BIT + sampling_rates 48000 + bit_width 16 + app_type 69936 + } + direct_pcm { + flags AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_DIRECT_PCM + formats AUDIO_FORMAT_PCM_16_BIT + sampling_rates 44100|48000|96000|192000 + bit_width 16 + app_type 69936 + } + compress_offload_16 { + flags AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD|AUDIO_OUTPUT_FLAG_NON_BLOCKING + formats AUDIO_FORMAT_MP3|AUDIO_FORMAT_PCM_16_BIT_OFFLOAD|AUDIO_FORMAT_PCM_24_BIT_OFFLOAD|AUDIO_FORMAT_FLAC|AUDIO_FORMAT_ALAC|AUDIO_FORMAT_APE|AUDIO_FORMAT_AAC_LC|AUDIO_FORMAT_AAC_HE_V1|AUDIO_FORMAT_AAC_HE_V2|AUDIO_FORMAT_WMA|AUDIO_FORMAT_WMA_PRO|AUDIO_FORMAT_VORBIS|AUDIO_FORMAT_AAC_ADTS_LC|AUDIO_FORMAT_AAC_ADTS_HE_V1|AUDIO_FORMAT_AAC_ADTS_HE_V2 + sampling_rates 44100|48000|96000|192000 + bit_width 16 + app_type 69936 + } + compress_offload_24 { + flags AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD|AUDIO_OUTPUT_FLAG_NON_BLOCKING + formats AUDIO_FORMAT_PCM_24_BIT_OFFLOAD|AUDIO_FORMAT_FLAC|AUDIO_FORMAT_ALAC|AUDIO_FORMAT_APE|AUDIO_FORMAT_VORBIS|AUDIO_FORMAT_WMA|AUDIO_FORMAT_WMA_PRO + sampling_rates 44100|48000|96000|192000 + bit_width 24 + app_type 69940 + } +} diff --git a/audio/audio_platform_info.xml b/audio/audio_platform_info.xml new file mode 100644 index 000000000..e563762e5 --- /dev/null +++ b/audio/audio_platform_info.xml @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/audio/audio_policy.conf b/audio/audio_policy.conf new file mode 100644 index 000000000..d1de2782d --- /dev/null +++ b/audio/audio_policy.conf @@ -0,0 +1,169 @@ +# Global configuration section: lists input and output devices always present on the device +# as well as the output device selected by default. +# Devices are designated by a string that corresponds to the enum in audio.h + +global_configuration { + attached_output_devices AUDIO_DEVICE_OUT_EARPIECE|AUDIO_DEVICE_OUT_SPEAKER|AUDIO_DEVICE_OUT_TELEPHONY_TX + default_output_device AUDIO_DEVICE_OUT_SPEAKER + attached_input_devices AUDIO_DEVICE_IN_BUILTIN_MIC|AUDIO_DEVICE_IN_BACK_MIC|AUDIO_DEVICE_IN_REMOTE_SUBMIX|AUDIO_DEVICE_IN_VOICE_CALL|AUDIO_DEVICE_IN_TELEPHONY_RX|AUDIO_DEVICE_IN_FM_TUNER +} + +# audio hardware module section: contains descriptors for all audio hw modules present on the +# device. Each hw module node is named after the corresponding hw module library base name. +# For instance, "primary" corresponds to audio.primary..so. +# The "primary" module is mandatory and must include at least one output with +# AUDIO_OUTPUT_FLAG_PRIMARY flag. +# Each module descriptor contains one or more output profile descriptors and zero or more +# input profile descriptors. Each profile lists all the parameters supported by a given output +# or input stream category. +# The "channel_masks", "formats", "devices" and "flags" are specified using strings corresponding +# to enums in audio.h and audio_policy.h. They are concatenated by use of "|" without space or "\n". + +audio_hw_modules { + primary { + outputs { + primary { + sampling_rates 44100|48000 + channel_masks AUDIO_CHANNEL_OUT_STEREO + formats AUDIO_FORMAT_PCM_16_BIT + devices AUDIO_DEVICE_OUT_EARPIECE|AUDIO_DEVICE_OUT_SPEAKER|AUDIO_DEVICE_OUT_WIRED_HEADSET|AUDIO_DEVICE_OUT_WIRED_HEADPHONE|AUDIO_DEVICE_OUT_LINE|AUDIO_DEVICE_OUT_ALL_SCO|AUDIO_DEVICE_OUT_AUX_DIGITAL|AUDIO_DEVICE_OUT_PROXY|AUDIO_DEVICE_OUT_FM + flags AUDIO_OUTPUT_FLAG_FAST|AUDIO_OUTPUT_FLAG_PRIMARY + } + raw { + sampling_rates 48000 + channel_masks AUDIO_CHANNEL_OUT_STEREO + formats AUDIO_FORMAT_PCM_16_BIT + devices AUDIO_DEVICE_OUT_EARPIECE|AUDIO_DEVICE_OUT_SPEAKER|AUDIO_DEVICE_OUT_WIRED_HEADSET|AUDIO_DEVICE_OUT_WIRED_HEADPHONE|AUDIO_DEVICE_OUT_LINE|AUDIO_DEVICE_OUT_ALL_SCO|AUDIO_DEVICE_OUT_AUX_DIGITAL + flags AUDIO_OUTPUT_FLAG_FAST|AUDIO_OUTPUT_FLAG_RAW + } + deep_buffer { + sampling_rates 44100|48000 + channel_masks AUDIO_CHANNEL_OUT_STEREO + formats AUDIO_FORMAT_PCM_16_BIT + devices AUDIO_DEVICE_OUT_SPEAKER|AUDIO_DEVICE_OUT_EARPIECE|AUDIO_DEVICE_OUT_WIRED_HEADSET|AUDIO_DEVICE_OUT_WIRED_HEADPHONE|AUDIO_DEVICE_OUT_LINE|AUDIO_DEVICE_OUT_ALL_SCO|AUDIO_DEVICE_OUT_AUX_DIGITAL|AUDIO_DEVICE_OUT_PROXY|AUDIO_DEVICE_OUT_FM + flags AUDIO_OUTPUT_FLAG_DEEP_BUFFER + } + multichannel { + sampling_rates 8000|11025|16000|22050|32000|44100|48000|64000|88200|96000|128000|176400|192000 + channel_masks dynamic + formats AUDIO_FORMAT_PCM_16_BIT + devices AUDIO_DEVICE_OUT_AUX_DIGITAL|AUDIO_DEVICE_OUT_PROXY + flags AUDIO_OUTPUT_FLAG_DIRECT + } + direct_pcm { + sampling_rates 44100|48000|64000|88200|96000|176400|192000 + channel_masks AUDIO_CHANNEL_OUT_MONO|AUDIO_CHANNEL_OUT_STEREO|AUDIO_CHANNEL_OUT_2POINT1|AUDIO_CHANNEL_OUT_QUAD|AUDIO_CHANNEL_OUT_PENTA|AUDIO_CHANNEL_OUT_5POINT1|AUDIO_CHANNEL_OUT_6POINT1|AUDIO_CHANNEL_OUT_7POINT1 + formats AUDIO_FORMAT_PCM_16_BIT + devices AUDIO_DEVICE_OUT_SPEAKER|AUDIO_DEVICE_OUT_EARPIECE|AUDIO_DEVICE_OUT_WIRED_HEADSET|AUDIO_DEVICE_OUT_WIRED_HEADPHONE|AUDIO_DEVICE_OUT_LINE|AUDIO_DEVICE_OUT_ALL_SCO + flags AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_DIRECT_PCM + } + compress_offload { + sampling_rates 8000|11025|12000|16000|22050|24000|32000|44100|48000|64000|88200|96000|176400|192000 + channel_masks AUDIO_CHANNEL_OUT_MONO|AUDIO_CHANNEL_OUT_STEREO|AUDIO_CHANNEL_OUT_2POINT1|AUDIO_CHANNEL_OUT_QUAD|AUDIO_CHANNEL_OUT_PENTA|AUDIO_CHANNEL_OUT_5POINT1|AUDIO_CHANNEL_OUT_6POINT1|AUDIO_CHANNEL_OUT_7POINT1 + formats AUDIO_FORMAT_MP3|AUDIO_FORMAT_PCM_16_BIT_OFFLOAD|AUDIO_FORMAT_PCM_24_BIT_OFFLOAD|AUDIO_FORMAT_FLAC|AUDIO_FORMAT_ALAC|AUDIO_FORMAT_APE|AUDIO_FORMAT_AAC_LC|AUDIO_FORMAT_AAC_HE_V1|AUDIO_FORMAT_AAC_HE_V2|AUDIO_FORMAT_WMA|AUDIO_FORMAT_WMA_PRO|AUDIO_FORMAT_VORBIS|AUDIO_FORMAT_AAC_ADTS_LC|AUDIO_FORMAT_AAC_ADTS_HE_V1|AUDIO_FORMAT_AAC_ADTS_HE_V2 + devices AUDIO_DEVICE_OUT_SPEAKER|AUDIO_DEVICE_OUT_EARPIECE|AUDIO_DEVICE_OUT_WIRED_HEADSET|AUDIO_DEVICE_OUT_WIRED_HEADPHONE|AUDIO_DEVICE_OUT_LINE|AUDIO_DEVICE_OUT_ALL_SCO|AUDIO_DEVICE_OUT_AUX_DIGITAL|AUDIO_DEVICE_OUT_PROXY + flags AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD|AUDIO_OUTPUT_FLAG_NON_BLOCKING + } + incall_music { + sampling_rates 8000|16000|48000 + channel_masks AUDIO_CHANNEL_OUT_MONO + formats AUDIO_FORMAT_PCM_16_BIT + devices AUDIO_DEVICE_OUT_SPEAKER|AUDIO_DEVICE_OUT_EARPIECE|AUDIO_DEVICE_OUT_WIRED_HEADSET|AUDIO_DEVICE_OUT_WIRED_HEADPHONE|AUDIO_DEVICE_OUT_LINE|AUDIO_DEVICE_OUT_ALL_SCO + flags AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_INCALL_MUSIC + } + voice_tx { + sampling_rates 8000|16000|48000 + channel_masks AUDIO_CHANNEL_OUT_STEREO|AUDIO_CHANNEL_OUT_MONO + formats AUDIO_FORMAT_PCM_16_BIT + devices AUDIO_DEVICE_OUT_TELEPHONY_TX + } + voip_rx { + sampling_rates 8000|16000 + channel_masks AUDIO_CHANNEL_OUT_MONO + formats AUDIO_FORMAT_PCM_16_BIT|AUDIO_FORMAT_AMR_NB|AUDIO_FORMAT_AMR_WB|AUDIO_FORMAT_QCELP|AUDIO_FORMAT_EVRC|AUDIO_FORMAT_EVRCB|AUDIO_FORMAT_EVRCWB|AUDIO_FORMAT_EVRCNW + devices AUDIO_DEVICE_OUT_SPEAKER|AUDIO_DEVICE_OUT_EARPIECE|AUDIO_DEVICE_OUT_WIRED_HEADSET|AUDIO_DEVICE_OUT_WIRED_HEADPHONE|AUDIO_DEVICE_OUT_LINE|AUDIO_DEVICE_OUT_ALL_SCO + flags AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_VOIP_RX + } + } + inputs { + primary { + sampling_rates 8000|11025|12000|16000|22050|24000|32000|44100|48000 + channel_masks AUDIO_CHANNEL_IN_MONO|AUDIO_CHANNEL_IN_STEREO|AUDIO_CHANNEL_IN_FRONT_BACK + formats AUDIO_FORMAT_PCM_16_BIT|AUDIO_FORMAT_AMR_NB|AUDIO_FORMAT_AMR_WB|AUDIO_FORMAT_QCELP|AUDIO_FORMAT_EVRC|AUDIO_FORMAT_EVRCB|AUDIO_FORMAT_EVRCWB|AUDIO_FORMAT_EVRCNW + devices AUDIO_DEVICE_IN_WIRED_HEADSET|AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET|AUDIO_DEVICE_IN_FM_TUNER|AUDIO_DEVICE_IN_VOICE_CALL + } + surround_sound { + sampling_rates 8000|11025|12000|16000|22050|24000|32000|44100|48000 + channel_masks AUDIO_CHANNEL_IN_5POINT1|AUDIO_CHANNEL_IN_MONO|AUDIO_CHANNEL_IN_STEREO|AUDIO_CHANNEL_IN_FRONT_BACK + formats AUDIO_FORMAT_PCM_16_BIT + devices AUDIO_DEVICE_IN_BUILTIN_MIC|AUDIO_DEVICE_IN_BACK_MIC + } + voice_rx { + sampling_rates 8000|16000|48000 + channel_masks AUDIO_CHANNEL_IN_STEREO|AUDIO_CHANNEL_IN_MONO + formats AUDIO_FORMAT_PCM_16_BIT + devices AUDIO_DEVICE_IN_TELEPHONY_RX + } + } + } + a2dp { + outputs { + a2dp { + sampling_rates 44100 + channel_masks AUDIO_CHANNEL_OUT_STEREO + formats AUDIO_FORMAT_PCM_16_BIT + devices AUDIO_DEVICE_OUT_ALL_A2DP + } + } + inputs { + a2dp { + sampling_rates 44100|48000 + channel_masks AUDIO_CHANNEL_IN_MONO|AUDIO_CHANNEL_IN_STEREO + formats AUDIO_FORMAT_PCM_16_BIT + devices AUDIO_DEVICE_IN_BLUETOOTH_A2DP + } + } + } + usb { + outputs { + usb_accessory { + sampling_rates 44100 + channel_masks AUDIO_CHANNEL_OUT_STEREO + formats AUDIO_FORMAT_PCM_16_BIT + devices AUDIO_DEVICE_OUT_USB_ACCESSORY + } + usb_device { + sampling_rates dynamic + channel_masks dynamic + formats dynamic + devices AUDIO_DEVICE_OUT_USB_DEVICE + } + } + inputs { + usb_device { + sampling_rates dynamic + channel_masks dynamic + formats dynamic + devices AUDIO_DEVICE_IN_USB_DEVICE + } + } + } + r_submix { + outputs { + submix { + sampling_rates 48000 + channel_masks AUDIO_CHANNEL_OUT_STEREO + formats AUDIO_FORMAT_PCM_16_BIT + devices AUDIO_DEVICE_OUT_REMOTE_SUBMIX + } + } + inputs { + submix { + sampling_rates 48000 + channel_masks AUDIO_CHANNEL_IN_STEREO + formats AUDIO_FORMAT_PCM_16_BIT + devices AUDIO_DEVICE_IN_REMOTE_SUBMIX + } + } + } +} diff --git a/audio/listen_platform_info.xml b/audio/listen_platform_info.xml new file mode 100644 index 000000000..cc218476c --- /dev/null +++ b/audio/listen_platform_info.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/audio/mixer_paths_tasha.xml b/audio/mixer_paths_tasha.xml new file mode 100644 index 000000000..3c59d8995 --- /dev/null +++ b/audio/mixer_paths_tasha.xml @@ -0,0 +1,2611 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/audio/mixer_paths_tasha_z2_plus.xml b/audio/mixer_paths_tasha_z2_plus.xml new file mode 100644 index 000000000..f648aba17 --- /dev/null +++ b/audio/mixer_paths_tasha_z2_plus.xml @@ -0,0 +1,2501 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/audio/sound_trigger_mixer_paths.xml b/audio/sound_trigger_mixer_paths.xml new file mode 100644 index 000000000..29ab7ed89 --- /dev/null +++ b/audio/sound_trigger_mixer_paths.xml @@ -0,0 +1,105 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/audio/sound_trigger_mixer_paths_wcd9330.xml b/audio/sound_trigger_mixer_paths_wcd9330.xml new file mode 100644 index 000000000..5bcdccfda --- /dev/null +++ b/audio/sound_trigger_mixer_paths_wcd9330.xml @@ -0,0 +1,89 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/audio/sound_trigger_platform_info.xml b/audio/sound_trigger_platform_info.xml new file mode 100644 index 000000000..6dbd18950 --- /dev/null +++ b/audio/sound_trigger_platform_info.xml @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/bluetooth/bdroid_buildcfg.h b/bluetooth/bdroid_buildcfg.h new file mode 100644 index 000000000..8a7f266ac --- /dev/null +++ b/bluetooth/bdroid_buildcfg.h @@ -0,0 +1,34 @@ +/* + * + * Copyright (c) 2013, The Linux Foundation. All rights reserved. + * Not a Contribution, Apache license notifications and license are retained + * for attribution purposes only. + * + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _BDROID_BUILDCFG_H +#define _BDROID_BUILDCFG_H +#define BTM_DEF_LOCAL_NAME "ZUK Z2 Plus" +// Disables read remote device feature +#define BTA_SKIP_BLE_READ_REMOTE_FEAT FALSE +#define MAX_ACL_CONNECTIONS 7 +#define MAX_L2CAP_CHANNELS 16 +#define BLE_VND_INCLUDED TRUE +// skips conn update at conn completion +#define BTA_BLE_SKIP_CONN_UPD FALSE +#define BLE_PERIPHERAL_ADV_NAME FALSE +#define BT_CLEAN_TURN_ON_DISABLED 1 +#endif diff --git a/cm.dependencies b/cm.dependencies new file mode 100644 index 000000000..13aeb7235 --- /dev/null +++ b/cm.dependencies @@ -0,0 +1,8 @@ +[ + { + "remote": "cm", + "repository": "android_device_qcom_common", + "target_path": "device/qcom/common", + "revision": "cm-13.0" + } +] diff --git a/cm.mk b/cm.mk new file mode 100644 index 000000000..6f941f0d9 --- /dev/null +++ b/cm.mk @@ -0,0 +1,41 @@ +# Copyright (C) 2016 The CyanogenMod Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Inherit from those products. Most specific first. +$(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit.mk) +$(call inherit-product, $(SRC_TARGET_DIR)/product/full_base_telephony.mk) + +# Inherit from oneplus3 device +$(call inherit-product, device/zuk/z2_plus/device.mk) + +# Inherit some common CM stuff. +$(call inherit-product, vendor/cm/config/common_full_phone.mk) + +PRODUCT_NAME := cm_z2_plus +PRODUCT_DEVICE := z2_plus +PRODUCT_MANUFACTURER := ZUK +PRODUCT_BRAND := ZUK +PRODUCT_MODEL := Z2 Plus + +PRODUCT_GMS_CLIENTID_BASE := android-zuk + +TARGET_VENDOR_PRODUCT_NAME := z2_plus +TARGET_VENDOR_DEVICE_NAME := z2_plus +PRODUCT_BUILD_PROP_OVERRIDES += TARGET_DEVICE=z2_plus PRODUCT_NAME=z2_plus + +PRODUCT_BUILD_PROP_OVERRIDES += \ + PRODUCT_DEFAULT_LOCALE="ru-RU" +# BUILD_FINGERPRINT=ZUK/z2_plus/z2_plus:6.0.1/MMB29M/2.1.059_160829:user/release-keys \ +# PRIVATE_BUILD_DESC="z2_plus-user 6.0.1 MMB29M 2.1.059_160829 release-keys" +TARGET_VENDOR := zuk diff --git a/cmhw/org/cyanogenmod/hardware/KeyDisabler.java b/cmhw/org/cyanogenmod/hardware/KeyDisabler.java new file mode 100644 index 000000000..3098af5fd --- /dev/null +++ b/cmhw/org/cyanogenmod/hardware/KeyDisabler.java @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2014 The CyanogenMod Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.cyanogenmod.hardware; + +import org.cyanogenmod.internal.util.FileUtils; + +/* + * Disable capacitive keys + * + * This is intended for use on devices in which the capacitive keys + * can be fully disabled for replacement with a soft navbar. You + * really should not be using this on a device with mechanical or + * otherwise visible-when-inactive keys + */ + +public class KeyDisabler { + + private static String CONTROL_PATH = "/proc/s1302/virtual_key"; + + public static boolean isSupported() { + return FileUtils.isFileWritable(CONTROL_PATH); + } + + public static boolean isActive() { + return FileUtils.readOneLine(CONTROL_PATH).equals("1"); + } + + public static boolean setActive(boolean state) { + return FileUtils.writeLine(CONTROL_PATH, (state ? "1" : "0")); + } +} diff --git a/configs/calib.cfg b/configs/calib.cfg new file mode 100644 index 000000000..9b9362d8f --- /dev/null +++ b/configs/calib.cfg @@ -0,0 +1,114 @@ +# Assertive Display Calibration Output File Format +# Calibration config file consists of one or more sections. Each section is set +# of parameter values stored on one line each. Number of parameters (hence number +# of lines in each section is fixed. Order in which parameters are specified in +# given section is fixed as well. +# Comments are supported in configuration file to improve readability of +# calibration configuration parameters. Any line begining with '#' is considered +# as comment and will not be processed further. +# Blank lines are allowed and are ignored. They can be used to improve +# readability of assertive display calibration output file. +# Sections: Any line begining with '=' indicates start of new section in +# calibration output file. Sections, parameters which are part of section and +# order in which they will appear in calibration output file is kept outside +# scope of this documentation in order to have flexibility in development of +# assertive display calibration system. This information can be shared between +# APICAL and Qualcomm as part of assertive display bring ups on given platforms. +# There should not be any spaces betweetn '=' and section name. +# Version 1.0 of calibration output format supports following sections: +# version - Contains assertive display calibration output file format version +# init - Contains assertive display parameters which are independent of +# assertive display mode +# config - Contains assertive display parameters which are dependent on specific +# assertive display mode +# Each parameter for assertive display calibration is stored on new line. If +# parameter consists of more than one values (set of values), each value is +# separated by single space (' ') character. In version 1.0 of assertive +# display calibration output file format, all numerical values are in decimal +# unsigned integer format, limited by 32 bits. Range for values or valid value +# for given parameter is outside scope of this documentation. This information +# can be shared between APICAL and Qualcomm as part of assertive display bring +# ups on given platforms. +# Version 1.1 adds two more init parameters (21 in total) to the config file to support the +# newly added power saving feature, Parameters added are alpha and BL_ATT lut +# Version 1.2 adds two more init parameters (23 in total) to the config file to support the +# driver change, Parameters added are ALS_offset and ALS_threshold +# Version 1.3 changes the parameters BL linearity LUT and BL inverse LUT +# from 8 bit to 12 bits. This is done to support the precision increase in the AD Driver +=version +1.3 +# APICAL mode indepent initialization Params +=init +# A +0 287 511 712 897 1072 1237 1395 1545 1690 1830 1964 2095 2221 2343 2462 2578 2690 2800 2907 3011 3112 3212 3309 3404 3497 3587 3676 3764 3849 3933 4015 4095 +#0 211 414 609 796 975 1148 1315 1475 1630 1779 1922 2061 2195 2325 2451 2572 2690 2804 2915 3022 3126 3227 3325 3420 3513 3603 3691 3776 3859 3940 4019 4095 +# B +255 278 302 326 350 374 398 422 446 470 494 517 541 565 589 613 637 661 684 708 732 755 779 803 826 850 874 897 921 945 968 992 1016 +# C +7 134 +# D +0 +# E +1023 +# F +241 +# G +240 +# H +0 +# I +60 +# J +224 +# dither_control +5 +# L +3 +# M +0 +# frame_width +720 +# frame_height +1280 +# P +0 +# Q +0 +# BL_linearity_LUT +0 16 32 48 64 80 96 112 128 145 161 177 193 209 225 241 257 273 289 305 321 337 353 369 385 401 418 434 450 466 482 498 514 530 546 562 578 594 610 626 642 658 674 691 707 723 739 755 771 787 803 819 835 851 867 883 899 915 931 947 964 980 996 1012 1028 1044 1060 1076 1092 1108 1124 1140 1156 1172 1188 1204 1220 1237 1253 1269 1285 1301 1317 1333 1349 1365 1381 1397 1413 1429 1445 1461 1477 1493 1510 1526 1542 1558 1574 1590 1606 1622 1638 1654 1670 1686 1702 1718 1734 1750 1766 1783 1799 1815 1831 1847 1863 1879 1895 1911 1927 1943 1959 1975 1991 2007 2023 2039 2056 2072 2088 2104 2120 2136 2152 2168 2184 2200 2216 2232 2248 2264 2280 2296 2312 2329 2345 2361 2377 2393 2409 2425 2441 2457 2473 2489 2505 2521 2537 2553 2569 2585 2602 2618 2634 2650 2666 2682 2698 2714 2730 2746 2762 2778 2794 2810 2826 2842 2858 2875 2891 2907 2923 2939 2955 2971 2987 3003 3019 3035 3051 3067 3083 3099 3115 3131 3148 3164 3180 3196 3212 3228 3244 3260 3276 3292 3308 3324 3340 3356 3372 3388 3404 3421 3437 3453 3469 3485 3501 3517 3533 3549 3565 3581 3597 3613 3629 3645 3661 3677 3694 3710 3726 3742 3758 3774 3790 3806 3822 3838 3854 3870 3886 3902 3918 3934 3950 3967 3983 3999 4015 4031 4047 4063 4079 4095 +# 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 +# BL_linearity_inverse_LUT +0 16 32 48 64 80 96 112 128 145 161 177 193 209 225 241 257 273 289 305 321 337 353 369 385 401 418 434 450 466 482 498 514 530 546 562 578 594 610 626 642 658 674 691 707 723 739 755 771 787 803 819 835 851 867 883 899 915 931 947 964 980 996 1012 1028 1044 1060 1076 1092 1108 1124 1140 1156 1172 1188 1204 1220 1237 1253 1269 1285 1301 1317 1333 1349 1365 1381 1397 1413 1429 1445 1461 1477 1493 1510 1526 1542 1558 1574 1590 1606 1622 1638 1654 1670 1686 1702 1718 1734 1750 1766 1783 1799 1815 1831 1847 1863 1879 1895 1911 1927 1943 1959 1975 1991 2007 2023 2039 2056 2072 2088 2104 2120 2136 2152 2168 2184 2200 2216 2232 2248 2264 2280 2296 2312 2329 2345 2361 2377 2393 2409 2425 2441 2457 2473 2489 2505 2521 2537 2553 2569 2585 2602 2618 2634 2650 2666 2682 2698 2714 2730 2746 2762 2778 2794 2810 2826 2842 2858 2875 2891 2907 2923 2939 2955 2971 2987 3003 3019 3035 3051 3067 3083 3099 3115 3131 3148 3164 3180 3196 3212 3228 3244 3260 3276 3292 3308 3324 3340 3356 3372 3388 3404 3421 3437 3453 3469 3485 3501 3517 3533 3549 3565 3581 3597 3613 3629 3645 3661 3677 3694 3710 3726 3742 3758 3774 3790 3806 3822 3838 3854 3870 3886 3902 3918 3934 3950 3967 3983 3999 4015 4031 4047 4063 4079 4095 +# power_saving_coeff +614 +# BL_att_LUT +0 128 256 384 512 640 768 896 994 1086 1175 1256 1323 1371 1393 1393 1390 1386 1383 1382 1413 1499 1627 1785 1961 2142 2329 2551 2807 3093 3406 3742 4095 +# al_offset +2000 +# al_tolarance +0.7 +#APICAL mode specific configuration +=config +# mode +1 +# R +0 0 4096 6144 8192 10240 12288 14336 16384 18432 20480 22528 24576 26624 28672 30720 32768 34815 36863 38911 40959 43007 45055 47103 49151 51199 53247 55295 57343 59391 61439 63487 65535 +# back_min +205 +# back_max +4095 +# back_scale +4095 +# ambient_light_min +14 +# S +1738 6 +# calibration_abcd +25 95 0 0 +# T +160 +# U +5 +# V +160 +# M_CC 30d89c85748d4ed61aa9c909f176ed07 diff --git a/configs/capability.xml b/configs/capability.xml new file mode 100644 index 000000000..2fa70d6f3 --- /dev/null +++ b/configs/capability.xml @@ -0,0 +1,115 @@ + + + + + LPCM + 1 + 2 + 48000 + 33 + + + AAC + 0 + 0 + 0 + 0 + + + AC3 + 0 + 0 + 0 + 0 + + + 1 + 0 + 2 + 1 + + + + 1 + 1 + 800 + 480 + 0 + 0 + 0 + 1 + 30 + + + + + 2 + 1 + 800 + 480 + 0 + 0 + 0 + 1 + 30 + + + + + 1 + + + + 0 + 0 + + + 0 + 0 + + + + 0 + 0 + + + 0 + WFD_HDCP_2_1 + 6789 + + + 0 + + + 0 + + + 0 + + 1 + + + + 1 + 1 + 1 + 1 + 1 + 0 + 0 + 1 + + + 4321 + + 0 + diff --git a/configs/media_codecs.xml b/configs/media_codecs.xml new file mode 100644 index 000000000..78dd159f3 --- /dev/null +++ b/configs/media_codecs.xml @@ -0,0 +1,407 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/configs/media_codecs_performance.xml b/configs/media_codecs_performance.xml new file mode 100644 index 000000000..3eda3281e --- /dev/null +++ b/configs/media_codecs_performance.xml @@ -0,0 +1,127 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/configs/media_profiles.xml b/configs/media_profiles.xml new file mode 100644 index 000000000..82700dd04 --- /dev/null +++ b/configs/media_profiles.xml @@ -0,0 +1,768 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/configs/msm_irqbalance.conf b/configs/msm_irqbalance.conf new file mode 100644 index 000000000..294e48952 --- /dev/null +++ b/configs/msm_irqbalance.conf @@ -0,0 +1,2 @@ +PRIO=1,1,0,0 +IGNORED_IRQ=27,62,171 diff --git a/configs/sec_config b/configs/sec_config new file mode 100644 index 000000000..f2f24b86e --- /dev/null +++ b/configs/sec_config @@ -0,0 +1,313 @@ +/* IPC Security Config */ +/* :: */ +16:4294967295:1000:3004 +/* :: */ +56:4294967295:1021:3004 +/* Allow SS CTL service to be used by system and net_raw processes */ +43:4294967295:1000:3004 +/* :: */ +50:4294967295:1001 +/* QMI-SLIM service permitted to gps and net_raw */ +55:4294967295:1021:3004 +/* Allow Sensor services to be used by sensor process */ +256:4294967295:3011 +257:4294967295:3011 +258:4294967295:3011 +259:4294967295:3011 +260:4294967295:3011 +261:4294967295:3011 +262:4294967295:3011 +263:4294967295:3011 +264:4294967295:3011 +265:4294967295:3011 +266:4294967295:3011 +267:4294967295:3011 +268:4294967295:3011 +269:4294967295:3011 +270:4294967295:3011 +271:4294967295:3011 +272:4294967295:3011 +273:4294967295:3011 +274:4294967295:3011 +275:4294967295:3011 +276:4294967295:3011 +277:4294967295:3011 +278:4294967295:3011 +279:4294967295:3011 +280:4294967295:3011 +281:4294967295:3011 +282:4294967295:3011 +283:4294967295:3011 +284:4294967295:3011 +285:4294967295:3011 +286:4294967295:3011 +287:4294967295:3011 +288:4294967295:3011 +289:4294967295:3011 +290:4294967295:3011 +291:4294967295:3011 +292:4294967295:3011 +293:4294967295:3011 +294:4294967295:3011 +295:4294967295:3011 +296:4294967295:3011 +297:4294967295:3011 +298:4294967295:3011 +299:4294967295:3011 +300:4294967295:3011 +301:4294967295:3011 +302:4294967295:3011 +303:4294967295:3011 +304:4294967295:3011 +305:4294967295:3011 +306:4294967295:3011 +307:4294967295:3011 +308:4294967295:3011 +309:4294967295:3011 +310:4294967295:3011 +311:4294967295:3011 +312:4294967295:3011 +313:4294967295:3011 +314:4294967295:3011 +315:4294967295:3011 +316:4294967295:3011 +317:4294967295:3011 +318:4294967295:3011 +319:4294967295:3011 +320:4294967295:3011 +321:4294967295:3011 +322:4294967295:3011 +323:4294967295:3011 +324:4294967295:3011 +325:4294967295:3011 +326:4294967295:3011 +327:4294967295:3011 +328:4294967295:3011 +329:4294967295:3011 +330:4294967295:3011 +331:4294967295:3011 +332:4294967295:3011 +333:4294967295:3011 +334:4294967295:3011 +335:4294967295:3011 +336:4294967295:3011 +337:4294967295:3011 +338:4294967295:3011 +339:4294967295:3011 +340:4294967295:3011 +341:4294967295:3011 +342:4294967295:3011 +343:4294967295:3011 +344:4294967295:3011 +345:4294967295:3011 +346:4294967295:3011 +347:4294967295:3011 +348:4294967295:3011 +349:4294967295:3011 +350:4294967295:3011 +351:4294967295:3011 +352:4294967295:3011 +353:4294967295:3011 +354:4294967295:3011 +355:4294967295:3011 +356:4294967295:3011 +357:4294967295:3011 +358:4294967295:3011 +359:4294967295:3011 +360:4294967295:3011 +361:4294967295:3011 +362:4294967295:3011 +363:4294967295:3011 +364:4294967295:3011 +365:4294967295:3011 +366:4294967295:3011 +367:4294967295:3011 +368:4294967295:3011 +369:4294967295:3011 +370:4294967295:3011 +371:4294967295:3011 +372:4294967295:3011 +373:4294967295:3011 +374:4294967295:3011 +375:4294967295:3011 +376:4294967295:3011 +377:4294967295:3011 +378:4294967295:3011 +379:4294967295:3011 +380:4294967295:3011 +381:4294967295:3011 +382:4294967295:3011 +383:4294967295:3011 +384:4294967295:3011 +385:4294967295:3011 +386:4294967295:3011 +387:4294967295:3011 +388:4294967295:3011 +389:4294967295:3011 +390:4294967295:3011 +391:4294967295:3011 +392:4294967295:3011 +393:4294967295:3011 +394:4294967295:3011 +395:4294967295:3011 +396:4294967295:3011 +397:4294967295:3011 +398:4294967295:3011 +399:4294967295:3011 +400:4294967295:3011 +401:4294967295:3011 +402:4294967295:3011 +403:4294967295:3011 +404:4294967295:3011 +405:4294967295:3011 +406:4294967295:3011 +407:4294967295:3011 +408:4294967295:3011 +409:4294967295:3011 +410:4294967295:3011 +411:4294967295:3011 +412:4294967295:3011 +413:4294967295:3011 +414:4294967295:3011 +415:4294967295:3011 +416:4294967295:3011 +417:4294967295:3011 +418:4294967295:3011 +419:4294967295:3011 +420:4294967295:3011 +421:4294967295:3011 +422:4294967295:3011 +423:4294967295:3011 +424:4294967295:3011 +425:4294967295:3011 +426:4294967295:3011 +427:4294967295:3011 +428:4294967295:3011 +429:4294967295:3011 +430:4294967295:3011 +431:4294967295:3011 +432:4294967295:3011 +433:4294967295:3011 +434:4294967295:3011 +435:4294967295:3011 +436:4294967295:3011 +437:4294967295:3011 +438:4294967295:3011 +439:4294967295:3011 +440:4294967295:3011 +441:4294967295:3011 +442:4294967295:3011 +443:4294967295:3011 +444:4294967295:3011 +445:4294967295:3011 +446:4294967295:3011 +447:4294967295:3011 +448:4294967295:3011 +449:4294967295:3011 +450:4294967295:3011 +451:4294967295:3011 +452:4294967295:3011 +453:4294967295:3011 +454:4294967295:3011 +455:4294967295:3011 +456:4294967295:3011 +457:4294967295:3011 +458:4294967295:3011 +459:4294967295:3011 +460:4294967295:3011 +461:4294967295:3011 +462:4294967295:3011 +463:4294967295:3011 +464:4294967295:3011 +465:4294967295:3011 +466:4294967295:3011 +467:4294967295:3011 +468:4294967295:3011 +469:4294967295:3011 +470:4294967295:3011 +471:4294967295:3011 +472:4294967295:3011 +473:4294967295:3011 +474:4294967295:3011 +475:4294967295:3011 +476:4294967295:3011 +477:4294967295:3011 +478:4294967295:3011 +479:4294967295:3011 +480:4294967295:3011 +481:4294967295:3011 +482:4294967295:3011 +483:4294967295:3011 +484:4294967295:3011 +485:4294967295:3011 +486:4294967295:3011 +487:4294967295:3011 +488:4294967295:3011 +489:4294967295:3011 +490:4294967295:3011 +491:4294967295:3011 +492:4294967295:3011 +493:4294967295:3011 +494:4294967295:3011 +495:4294967295:3011 +496:4294967295:3011 +497:4294967295:3011 +498:4294967295:3011 +499:4294967295:3011 +500:4294967295:3011 +501:4294967295:3011 +502:4294967295:3011 +503:4294967295:3011 +504:4294967295:3011 +505:4294967295:3011 +506:4294967295:3011 +507:4294967295:3011 +508:4294967295:3011 +509:4294967295:3011 +510:4294967295:3011 +511:4294967295:3011 +/* Allow RCS service to aquire net_raw permission */ +18:4294967295:1001:3004 +/* Allow QMID service to aquire net_raw permission */ +3:4294967295:1001:3004 +2:4294967295:1001:3004 +42:4294967295:1001:3004 +18:4294967295:1001:3004 +9:4294967295:1001:3004 +1:4294967295:1001:3004:1000 +4:4294967295:1001:3004 +7:4294967295:1001:3004 +8:4294967295:1001:3004:1000 +/* DPM */ +47:4294967295:1001:3004 +/* Allow communication to some QMI services with radio privilages */ +/* Format is :: */ +/* PBM */ +12:4294967295:1001 +/* WMS */ +5:4294967295:1001 +/* IMS VT */ +32:4294967295:1001 +/* IMSP */ +31:4294967295:1001 +/* PDC */ +36:4294967295:1001 +/* SAR */ +17:4294967295:1001 +/* RFRPE */ +41:4294967295:1001 +/*UIM*/ +11:4294967295:1001 +/*CAT*/ +10:4294967295:1001 +/*IMSA*/ +33:4294967295:1001 +/* CSVT */ +29:4294967295:1001 +/* Allow Data dpmd to access QMI DFS */ +48:4294967295:1000:3004 +/* DIAG */ +4097:4294967295:3009 +/* Add for FANCY_VIRTUAL_SIM for future use. */ +/* Redtea */ +50:4294967295:1001 diff --git a/data-ipa-cfg-mgr/Android.mk b/data-ipa-cfg-mgr/Android.mk new file mode 100644 index 000000000..5053e7d64 --- /dev/null +++ b/data-ipa-cfg-mgr/Android.mk @@ -0,0 +1 @@ +include $(call all-subdir-makefiles) diff --git a/data-ipa-cfg-mgr/Makefile.am b/data-ipa-cfg-mgr/Makefile.am new file mode 100644 index 000000000..fab2aff30 --- /dev/null +++ b/data-ipa-cfg-mgr/Makefile.am @@ -0,0 +1,3 @@ +ACLOCAL_AMFLAGS = -I m4 +AUTOMAKE_OPTIONS = foreign +SUBDIRS = ipanat/src ipacm/src/ diff --git a/data-ipa-cfg-mgr/configure.ac b/data-ipa-cfg-mgr/configure.ac new file mode 100644 index 000000000..33164c075 --- /dev/null +++ b/data-ipa-cfg-mgr/configure.ac @@ -0,0 +1,57 @@ +# -*- Autoconf -*- +# Process this file with autoconf to produce a configure script. + +AC_PREREQ([2.65]) +AC_INIT(data-ipa, 1.0.0) +AM_INIT_AUTOMAKE(data-ipa, 1.0.0) +AC_OUTPUT(Makefile ipanat/src/Makefile ipacm/src/Makefile) +AC_CONFIG_SRCDIR([ipanat/src/ipa_nat_drv.c]) +AC_CONFIG_HEADERS([config.h]) +AC_CONFIG_MACRO_DIR([m4]) + +# Checks for programs. +AC_PROG_CC +AC_PROG_LIBTOOL +AC_PROG_CXX + +PKG_CHECK_MODULES([LIBXML], [libxml-2.0]) +AC_SUBST([LIBXML_CFLAGS]) +AC_SUBST([LIBXML_LIBS]) + +# Checks for libraries. + +AC_ARG_WITH(sanitized-headers, + AS_HELP_STRING([--with-sanitized-headers=DIR], + [Specify the location of the sanitized Linux headers]), + [CPPFLAGS="$CPPFLAGS -idirafter $withval"]) + +AC_ARG_WITH([glib], + AC_HELP_STRING([--with-glib], + [enable glib, building HLOS systems which use glib])) + +if (test "x${with_glib}" = "xyes"); then + AC_DEFINE(ENABLE_USEGLIB, 1, [Define if HLOS systems uses glib]) + PKG_CHECK_MODULES(GTHREAD, gthread-2.0 >= 2.16, dummy=yes, + AC_MSG_ERROR(GThread >= 2.16 is required)) + PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.16, dummy=yes, + AC_MSG_ERROR(GLib >= 2.16 is required)) + GLIB_CFLAGS="$GLIB_CFLAGS $GTHREAD_CFLAGS" + GLIB_LIBS="$GLIB_LIBS $GTHREAD_LIBS" + AC_SUBST(GLIB_CFLAGS) + AC_SUBST(GLIB_LIBS) +fi + +AM_CONDITIONAL(USE_GLIB, test "x${with_glib}" = "xyes") + +# Checks for header files. +AC_CHECK_HEADERS([fcntl.h netinet/in.h sys/ioctl.h unistd.h]) + +# Checks for typedefs, structures, and compiler characteristics. +AC_TYPE_OFF_T + +# Checks for library functions. +AC_FUNC_MALLOC +AC_FUNC_MMAP +AC_CHECK_FUNCS([memset munmap]) + +AC_OUTPUT diff --git a/data-ipa-cfg-mgr/ipacm/Android.mk b/data-ipa-cfg-mgr/ipacm/Android.mk new file mode 100644 index 000000000..5053e7d64 --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/Android.mk @@ -0,0 +1 @@ +include $(call all-subdir-makefiles) diff --git a/data-ipa-cfg-mgr/ipacm/inc/IPACM_CmdQueue.h b/data-ipa-cfg-mgr/ipacm/inc/IPACM_CmdQueue.h new file mode 100644 index 000000000..2f7709ac2 --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/inc/IPACM_CmdQueue.h @@ -0,0 +1,107 @@ +/* +Copyright (c) 2013, The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +/*! + @file + IPACM_CmdQueue.h + + @brief + This file implements the IPAM Comment Queue definitions + + @Author + +*/ +#ifndef IPA_CONNTRACK_MESSAGE_H +#define IPA_CONNTRACK_MESSAGE_H + +#include +#include "IPACM_Defs.h" + + + +/*--------------------------------------------------------------------------- + Event data required by IPA_CM +---------------------------------------------------------------------------*/ + + +typedef struct _ipacm_cmd_q_data { + ipa_cm_event_id event; + void *evt_data; +}ipacm_cmd_q_data; + +typedef struct cmd_s +{ + void (*callback_ptr)(ipacm_cmd_q_data *); + ipacm_cmd_q_data data; +}cmd_t; + +class Message +{ +private: + Message *m_next; + +public: + cmd_t evt; + + Message() + { + m_next = NULL; + evt.callback_ptr = NULL; + } + ~Message() { } + void setnext(Message *item) { m_next = item; } + Message* getnext() { return m_next; } +}; + +class MessageQueue +{ + +private: + Message *Head; + Message *Tail; + Message* dequeue(void); + static MessageQueue *inst; + + MessageQueue() + { + Head = NULL; + Tail = NULL; + } + +public: + + ~MessageQueue() { } + void enqueue(Message *item); + + static void* Process(void *); + static MessageQueue* getInstance(); + +}; + +#endif /* IPA_CONNTRACK_MESSAGE_H */ + diff --git a/data-ipa-cfg-mgr/ipacm/inc/IPACM_Config.h b/data-ipa-cfg-mgr/ipacm/inc/IPACM_Config.h new file mode 100644 index 000000000..665b84448 --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/inc/IPACM_Config.h @@ -0,0 +1,356 @@ +/* +Copyright (c) 2013, The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +/*! + @file + IPACM_Config.h + + @brief + This file implements the IPACM Configuration from XML file + + @Author + Skylar Chang + +*/ +#ifndef IPACM_CONFIG_H +#define IPACM_CONFIG_H + +#include "IPACM_Defs.h" +#include "IPACM_Xml.h" +#include "IPACM_EvtDispatcher.h" + +typedef struct +{ + char iface_name[IPA_IFACE_NAME_LEN]; +}NatIfaces; + +/* for IPACM rm dependency use*/ +typedef struct _ipa_rm_client +{ + ipa_rm_resource_name producer_rm1; + ipa_rm_resource_name consumer_rm1; + ipa_rm_resource_name producer_rm2; + ipa_rm_resource_name consumer_rm2; + bool producer1_up; /* only monitor producer_rm1, not monitor producer_rm2 */ + bool consumer1_up; /* only monitor consumer_rm1, not monitor consumer_rm2 */ + bool rm_set; /* once producer1_up and consumer1_up, will add bi-directional dependency */ + bool rx_bypass_ipa; /* support WLAN may not register RX-property, should not add dependency */ +}ipa_rm_client; + +#define MAX_NUM_EXT_PROPS 15 + +/* used to hold extended properties */ +typedef struct +{ + uint8_t num_ext_props; + ipa_ioc_ext_intf_prop prop[MAX_NUM_EXT_PROPS]; +} ipacm_ext_prop; + +/* iface */ +class IPACM_Config +{ +public: + + /* IPACM ipa_client map to rm_resource*/ + ipa_rm_resource_name ipa_client_rm_map_tbl[IPA_CLIENT_MAX]; + + /* IPACM monitored rm_depency table */ + ipa_rm_client ipa_rm_tbl[IPA_MAX_RM_ENTRY]; + + /* IPACM rm_depency a2 endpoint check*/ + int ipa_rm_a2_check; + + /* Store interested interface and their configuration from XML file */ + ipa_ifi_dev_name_t *iface_table; + + /* Store interested ALG port from XML file */ + ipacm_alg *alg_table; + + /* Store private subnet configuration from XML file */ + ipa_private_subnet private_subnet_table[IPA_MAX_PRIVATE_SUBNET_ENTRIES]; + + /* Store the non nat iface names */ + NatIfaces *pNatIfaces; + + /* Store the bridge iface names */ + char ipa_virtual_iface_name[IPA_IFACE_NAME_LEN]; + + /* Store the number of interface IPACM read from XML file */ + int ipa_num_ipa_interfaces; + + int ipa_num_private_subnet; + + int ipa_num_alg_ports; + + int ipa_nat_max_entries; + + bool ipacm_odu_router_mode; + + bool ipacm_odu_enable; + + bool ipacm_odu_embms_enable; + + int ipa_nat_iface_entries; + + /* Store the total number of wlan guest ap configured */ + int ipa_num_wlan_guest_ap; + + /* Max valid rm entry */ + int ipa_max_valid_rm_entry; + + /* Store SW-enable or not */ + bool ipa_sw_rt_enable; + + /* Store bridge mode or not */ + bool ipa_bridge_enable; + + /* Store bridge netdev mac */ + uint8_t bridge_mac[IPA_MAC_ADDR_SIZE]; + + /* Store the flt rule count for each producer client*/ + int flt_rule_count_v4[IPA_CLIENT_CONS - IPA_CLIENT_PROD]; + int flt_rule_count_v6[IPA_CLIENT_CONS - IPA_CLIENT_PROD]; + + /* IPACM routing table name for v4/v6 */ + struct ipa_ioc_get_rt_tbl rt_tbl_lan_v4, rt_tbl_wan_v4, rt_tbl_default_v4, rt_tbl_v6, rt_tbl_wan_v6; + struct ipa_ioc_get_rt_tbl rt_tbl_wan_dl; + struct ipa_ioc_get_rt_tbl rt_tbl_lan2lan_v4, rt_tbl_lan2lan_v6; + struct ipa_ioc_get_rt_tbl rt_tbl_odu_v4, rt_tbl_odu_v6; + struct ipa_ioc_get_rt_tbl rt_tbl_eth_bridge_lan_lan_v4, rt_tbl_eth_bridge_lan_wlan_v4, rt_tbl_eth_bridge_wlan_wlan_v4; + struct ipa_ioc_get_rt_tbl rt_tbl_eth_bridge_lan_lan_v6, rt_tbl_eth_bridge_lan_wlan_v6, rt_tbl_eth_bridge_wlan_wlan_v6; + + bool isMCC_Mode; + + /* To return the instance */ + static IPACM_Config* GetInstance(); + + inline void increaseFltRuleCount(int index, ipa_ip_type iptype, int increment) + { + if((index >= IPA_CLIENT_CONS - IPA_CLIENT_PROD) || (index < 0)) + { + IPACMERR("Index is out of range: %d.\n", index); + return; + } + if(iptype == IPA_IP_v4) + { + flt_rule_count_v4[index] += increment; + IPACMDBG_H("Now num of v4 flt rules on client %d is %d.\n", index, flt_rule_count_v4[index]); + } + else + { + flt_rule_count_v6[index] += increment; + IPACMDBG_H("Now num of v6 flt rules on client %d is %d.\n", index, flt_rule_count_v6[index]); + } + return; + } + + inline void decreaseFltRuleCount(int index, ipa_ip_type iptype, int decrement) + { + if((index >= IPA_CLIENT_CONS - IPA_CLIENT_PROD) || (index < 0)) + { + IPACMERR("Index is out of range: %d.\n", index); + return; + } + if(iptype == IPA_IP_v4) + { + flt_rule_count_v4[index] -= decrement; + IPACMDBG_H("Now num of v4 flt rules on client %d is %d.\n", index, flt_rule_count_v4[index]); + } + else + { + flt_rule_count_v6[index] -= decrement; + IPACMDBG_H("Now num of v6 flt rules on client %d is %d.\n", index, flt_rule_count_v6[index]); + } + return; + } + + inline int getFltRuleCount(int index, ipa_ip_type iptype) + { + if((index >= IPA_CLIENT_CONS - IPA_CLIENT_PROD) || (index < 0)) + { + IPACMERR("Index is out of range: %d.\n", index); + return -1; + } + if(iptype == IPA_IP_v4) + { + return flt_rule_count_v4[index]; + } + else + { + return flt_rule_count_v6[index]; + } + } + + inline int GetAlgPortCnt() + { + return ipa_num_alg_ports; + } + + int GetAlgPorts(int nPorts, ipacm_alg *pAlgPorts); + + inline int GetNatMaxEntries(void) + { + return ipa_nat_max_entries; + } + + inline int GetNatIfacesCnt() + { + return ipa_nat_iface_entries; + } + int GetNatIfaces(int nPorts, NatIfaces *ifaces); + + /* for IPACM resource manager dependency usage */ + void AddRmDepend(ipa_rm_resource_name rm1,bool rx_bypass_ipa); + + void DelRmDepend(ipa_rm_resource_name rm1); + + int AddNatIfaces(char *dev_name); + + int DelNatIfaces(char *dev_name); + + inline void SetQmapId(uint8_t id) + { + qmap_id = id; + } + + inline uint8_t GetQmapId() + { + return qmap_id; + } + + int SetExtProp(ipa_ioc_query_intf_ext_props *prop); + + ipacm_ext_prop* GetExtProp(ipa_ip_type ip_type); + + int DelExtProp(ipa_ip_type ip_type); + + int Init(void); + + inline bool isPrivateSubnet(uint32_t ip_addr) + { + for(int cnt=0; cnt> 8) << 8; + ipa_num_private_subnet++; + + /* IPACM private subnet set changes */ + data_fid = (ipacm_event_data_fid *)malloc(sizeof(ipacm_event_data_fid)); + if(data_fid == NULL) + { + IPACMERR("unable to allocate memory for event data_fid\n"); + return IPACM_FAILURE; + } + data_fid->if_index = ipa_if_index; // already ipa index, not fid index + evt_data.event = IPA_PRIVATE_SUBNET_CHANGE_EVENT; + evt_data.evt_data = data_fid; + + /* Insert IPA_PRIVATE_SUBNET_CHANGE_EVENT to command queue */ + IPACM_EvtDispatcher::PostEvt(&evt_data); + return true; + } + IPACMERR("IPACM private subnet_addr overflow, total entry(%d)\n", ipa_num_private_subnet); + return false; + } + + inline bool DelPrivateSubnet(uint32_t ip_addr, int ipa_if_index) + { + ipacm_cmd_q_data evt_data; + ipacm_event_data_fid *data_fid; + for(int cnt=0; cntif_index = ipa_if_index; // already ipa index, not fid index + evt_data.event = IPA_PRIVATE_SUBNET_CHANGE_EVENT; + evt_data.evt_data = data_fid; + + /* Insert IPA_PRIVATE_SUBNET_CHANGE_EVENT to command queue */ + IPACM_EvtDispatcher::PostEvt(&evt_data); + return true; + } + } + IPACMDBG("can't find private subnet_addr as: 0x%x \n", ip_addr); + return false; + } +#endif /* defined(FEATURE_IPA_ANDROID)*/ + + static const char *DEVICE_NAME_ODU; + +private: + static IPACM_Config *pInstance; + static const char *DEVICE_NAME; + IPACM_Config(void); + int m_fd; /* File descriptor of the IPA device node /dev/ipa */ + uint8_t qmap_id; + ipacm_ext_prop ext_prop_v4; + ipacm_ext_prop ext_prop_v6; +}; + +#endif /* IPACM_CONFIG */ diff --git a/data-ipa-cfg-mgr/ipacm/inc/IPACM_ConntrackClient.h b/data-ipa-cfg-mgr/ipacm/inc/IPACM_ConntrackClient.h new file mode 100644 index 000000000..a6076cfe7 --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/inc/IPACM_ConntrackClient.h @@ -0,0 +1,104 @@ +/* +Copyright (c) 2013, The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef IPACM_CONNTRACK_FILTER_H +#define IPACM_CONNTRACK_FILTER_H + +#include +#include +#include +#include +#include +#include + +#include "IPACM_ConntrackClient.h" +#include "IPACM_CmdQueue.h" +#include "IPACM_Conntrack_NATApp.h" +#include "IPACM_EvtDispatcher.h" +#include "IPACM_Defs.h" + +#ifndef IPACM_DEBUG +#define IPACM_DEBUG +#endif + +extern "C" +{ +#include +#include +#include +} + +using namespace std; + +#define UDP_TIMEOUT_UPDATE 20 +#define BROADCAST_IPV4_ADDR 0xFFFFFFFF + +class IPACM_ConntrackClient +{ + +private: + static IPACM_ConntrackClient *pInstance; + + struct nfct_handle *tcp_hdl; + struct nfct_handle *udp_hdl; + struct nfct_filter *tcp_filter; + struct nfct_filter *udp_filter; + static int IPA_Conntrack_Filters_Ignore_Local_Addrs(struct nfct_filter *filter); + static int IPA_Conntrack_Filters_Ignore_Bridge_Addrs(struct nfct_filter *filter); + static int IPA_Conntrack_Filters_Ignore_Local_Iface(struct nfct_filter *, ipacm_event_iface_up *); + IPACM_ConntrackClient(); + +public: + static int IPAConntrackEventCB(enum nf_conntrack_msg_type type, + struct nf_conntrack *ct, + void *data); + + static int IPA_Conntrack_UDP_Filter_Init(void); + static int IPA_Conntrack_TCP_Filter_Init(void); + static void* TCPRegisterWithConnTrack(void *); + static void* UDPRegisterWithConnTrack(void *); + static void* UDPConnTimeoutUpdate(void *); + + static void UpdateUDPFilters(void *, bool); + static void UpdateTCPFilters(void *, bool); + static void Read_TcpUdp_Timeout(char *in, int len); + + static IPACM_ConntrackClient* GetInstance(); + +#ifdef IPACM_DEBUG +#define iptodot(X,Y) \ + IPACMLOG(" %s(0x%x): %d.%d.%d.%d\n", X, Y, ((Y>>24) & 0xFF), ((Y>>16) & 0xFF), ((Y>>8) & 0xFF), (Y & 0xFF)); +#endif + +#define log_nat(A,B,C,D,E,F) \ + IPACMDBG_H("protocol %d Private IP: %d.%d.%d.%d\t Target IP: %d.%d.%d.%d\t private port: %d public port: %d %s",A,((B>>24) & 0xFF), ((B>>16) & 0xFF), ((B>>8) & 0xFF), (B & 0xFF), ((C>>24) & 0xFF), ((C>>16) & 0xFF),((C>>8) & 0xFF),(C & 0xFF),D,E,F); + +}; + +#endif /* IPACM_CONNTRACK_FILTER_H */ diff --git a/data-ipa-cfg-mgr/ipacm/inc/IPACM_ConntrackListener.h b/data-ipa-cfg-mgr/ipacm/inc/IPACM_ConntrackListener.h new file mode 100644 index 000000000..db83598a4 --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/inc/IPACM_ConntrackListener.h @@ -0,0 +1,105 @@ +/* +Copyright (c) 2013, The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef IPACM_CONNTRACK_LISTENER +#define IPACM_CONNTRACK_LISTENER + +#include +#include +#include +#include + +#include +#include +#include + +#include "IPACM_CmdQueue.h" +#include "IPACM_Conntrack_NATApp.h" +#include "IPACM_Listener.h" +#ifdef CT_OPT +#include "IPACM_LanToLan.h" +#endif + +#define MAX_NAT_IFACES 50 +#define MAX_STA_CLNT_IFACES 10 + +using namespace std; + +class IPACM_ConntrackListener : public IPACM_Listener +{ + +private: + bool isCTReg; + bool isNatThreadStart; + bool WanUp; + NatApp *nat_inst; + + int NatIfaceCnt; + int StaClntCnt; + NatIfaces *pNatIfaces; + uint32_t nat_iface_ipv4_addr[MAX_NAT_IFACES]; + uint32_t nonnat_iface_ipv4_addr[MAX_NAT_IFACES]; + uint32_t sta_clnt_ipv4_addr[MAX_STA_CLNT_IFACES]; + IPACM_Config *pConfig; +#ifdef CT_OPT + IPACM_LanToLan *p_lan2lan; +#endif + + void ProcessCTMessage(void *); + void ProcessTCPorUDPMsg(struct nf_conntrack *, + enum nf_conntrack_msg_type, u_int8_t); + void TriggerWANUp(void *); + void TriggerWANDown(uint32_t); + int CreateNatThreads(void); + int CreateConnTrackThreads(void); + +#ifdef CT_OPT + void ProcessCTV6Message(void *); +#endif + +public: + char wan_ifname[IPA_IFACE_NAME_LEN]; + uint32_t wan_ipaddr; + bool isStaMode; + IPACM_ConntrackListener(); + void event_callback(ipa_cm_event_id, void *data); + inline bool isWanUp() + { + return WanUp; + } + + void HandleNeighIpAddrAddEvt(ipacm_event_data_all *); + void HandleNeighIpAddrDelEvt(uint32_t); + void HandleSTAClientAddEvt(uint32_t); + void HandleSTAClientDelEvt(uint32_t); +}; + +extern IPACM_ConntrackListener *CtList; + +#endif /* IPACM_CONNTRACK_LISTENER */ diff --git a/data-ipa-cfg-mgr/ipacm/inc/IPACM_Conntrack_NATApp.h b/data-ipa-cfg-mgr/ipacm/inc/IPACM_Conntrack_NATApp.h new file mode 100644 index 000000000..e6c27af81 --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/inc/IPACM_Conntrack_NATApp.h @@ -0,0 +1,133 @@ +/* +Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +#ifndef IPACM_CONNTRACK_NATAPP_H +#define IPACM_CONNTRACK_NATAPP_H + +#include /* for stderror */ +#include +#include /* for perror */ + +#include "IPACM_Config.h" +#include "IPACM_Xml.h" + +extern "C" +{ +#include +#include +} + +#define MAX_TEMP_ENTRIES 25 + +#define IPACM_TCP_FULL_FILE_NAME "/proc/sys/net/ipv4/netfilter/ip_conntrack_tcp_timeout_established" +#define IPACM_UDP_FULL_FILE_NAME "/proc/sys/net/ipv4/netfilter/ip_conntrack_udp_timeout_stream" + +typedef struct _nat_table_entry +{ + uint32_t private_ip; + uint16_t private_port; + + uint32_t target_ip; + uint16_t target_port; + + uint32_t public_ip; + uint16_t public_port; + + u_int8_t protocol; + uint32_t timestamp; + + bool dst_nat; + bool enabled; + uint32_t rule_hdl; + +}nat_table_entry; + +#define CHK_TBL_HDL() if(nat_table_hdl == 0){ return -1; } + +class NatApp +{ +private: + + static NatApp *pInstance; + + nat_table_entry *cache; + nat_table_entry temp[MAX_TEMP_ENTRIES]; + uint32_t pub_ip_addr; + uint32_t pub_ip_addr_pre; + uint32_t nat_table_hdl; + + int curCnt, max_entries; + + ipacm_alg *pALGPorts; + uint16_t nALGPort; + + uint32_t tcp_timeout; + uint32_t udp_timeout; + + uint32_t PwrSaveIfs[IPA_MAX_NUM_WIFI_CLIENTS]; + + struct nf_conntrack *ct; + struct nfct_handle *ct_hdl; + + NatApp(); + int Init(); + + void UpdateCTUdpTs(nat_table_entry *, uint32_t); + bool ChkForDup(const nat_table_entry *); + bool isAlgPort(uint8_t, uint16_t); + void Reset(); + bool isPwrSaveIf(uint32_t); + +public: + static NatApp* GetInstance(); + + int AddTable(uint32_t); + uint32_t GetTableHdl(uint32_t); + int DeleteTable(uint32_t); + + int AddEntry(const nat_table_entry *); + int DeleteEntry(const nat_table_entry *); + + void UpdateUDPTimeStamp(); + + int UpdatePwrSaveIf(uint32_t); + int ResetPwrSaveIf(uint32_t); + int DelEntriesOnClntDiscon(uint32_t); + int DelEntriesOnSTAClntDiscon(uint32_t); + + void Read_TcpUdp_Timeout(void); + + void AddTempEntry(const nat_table_entry *); + void CacheEntry(const nat_table_entry *); + void DeleteTempEntry(const nat_table_entry *); + void FlushTempEntries(uint32_t, bool); +}; + + + +#endif /* IPACM_CONNTRACK_NATAPP_H */ diff --git a/data-ipa-cfg-mgr/ipacm/inc/IPACM_Defs.h b/data-ipa-cfg-mgr/ipacm/inc/IPACM_Defs.h new file mode 100644 index 000000000..677b12244 --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/inc/IPACM_Defs.h @@ -0,0 +1,362 @@ +/* +Copyright (c) 2013, The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +/*! + @file + IPACM_Defs.h + + @brief + This file implements the common definitions amon all ifaces. + + @Author + Skylar Chang + +*/ +#ifndef IPA_CM_DEFS_H +#define IPA_CM_DEFS_H + +#include +#include +#include +#include "IPACM_Log.h" + +extern "C" +{ +#include +#include +} + +#define IF_NAME_LEN 16 +#define IPA_MAX_FILE_LEN 64 +#define IPA_IFACE_NAME_LEN 16 +#define IPA_ALG_PROTOCOL_NAME_LEN 10 + +#define IPA_WLAN_PARTIAL_HDR_OFFSET 0 // dst mac first then src mac +//#define IPA_ETH_PARTIAL_HDR_OFFSET 8 // dst mac first then src mac +#define IPA_ODU_PARTIAL_HDR_OFFSET 8 // dst mac first then src mac +#define IPA_WLAN_PARTIAL_HDR_NAME_v4 "IEEE802_3_v4" +#define IPA_WLAN_PARTIAL_HDR_NAME_v6 "IEEE802_3_v6" +#define IPA_WAN_PARTIAL_HDR_NAME_v4 "IEEE802_3_STA_v4" +#define IPA_WAN_PARTIAL_HDR_NAME_v6 "IEEE802_3_STA_v6" +#define IPA_ETH_HDR_NAME_v4 "IPACM_ETH_v4" +#define IPA_ETH_HDR_NAME_v6 "IPACM_ETH_v6" +#define IPA_ODU_HDR_NAME_v4 "IPACM_ODU_v4" +#define IPA_ODU_HDR_NAME_v6 "IPACM_ODU_v6" + + +#define IPA_MAX_IFACE_ENTRIES 15 +#define IPA_MAX_PRIVATE_SUBNET_ENTRIES 3 +#define IPA_MAX_ALG_ENTRIES 20 +#define IPA_MAX_RM_ENTRY 6 + +#define IPV4_ADDR_LINKLOCAL 0xA9FE0000 +#define IPV4_ADDR_LINKLOCAL_MASK 0xFFFF0000 + +#define V4_DEFAULT_ROUTE_TABLE_NAME "ipa_dflt_rt" +#define V4_LAN_ROUTE_TABLE_NAME "COMRTBLLANv4" +#define V4_WAN_ROUTE_TABLE_NAME "WANRTBLv4" +#define WAN_DL_ROUTE_TABLE_NAME "ipa_dflt_wan_rt" +#define V6_COMMON_ROUTE_TABLE_NAME "COMRTBLv6" +#define V6_WAN_ROUTE_TABLE_NAME "WANRTBLv6" +#define V4_LAN_TO_LAN_ROUTE_TABLE_NAME "LANTOLANRTBLv4" +#define V6_LAN_TO_LAN_ROUTE_TABLE_NAME "LANTOLANRTBLv6" +#define V4_ODU_ROUTE_TABLE_NAME "ODURTBLv4" +#define V6_ODU_ROUTE_TABLE_NAME "ODURTBLv6" + +#define ETH_BRIDGE_USB_CPE_ROUTE_TABLE_NAME_V4 "ETH_BRIDGE_LAN_LAN_RTBLv4" +#define ETH_BRIDGE_USB_WLAN_ROUTE_TABLE_NAME_V4 "ETH_BRIDGE_LAN_WLAN_RTBLv4" +#define ETH_BRIDGE_WLAN_WLAN_ROUTE_TABLE_NAME_V4 "ETH_BRIDGE_WLAN_WLAN_RTBLv4" +#define ETH_BRIDGE_USB_CPE_ROUTE_TABLE_NAME_V6 "ETH_BRIDGE_LAN_LAN_RTBLv6" +#define ETH_BRIDGE_USB_WLAN_ROUTE_TABLE_NAME_V6 "ETH_BRIDGE_LAN_WLAN_RTBLv6" +#define ETH_BRIDGE_WLAN_WLAN_ROUTE_TABLE_NAME_V6 "ETH_BRIDGE_WLAN_WLAN_RTBLv6" + +#define WWAN_QMI_IOCTL_DEVICE_NAME "/dev/wwan_ioctl" +#define IPA_DEVICE_NAME "/dev/ipa" +#define IPA_MAX_FLT_RULE 50 + +#define MAX_OFFLOAD_PAIR 3 +#define MAX_NUM_PROP 8 +#define IPA_LAN_TO_LAN_USB_HDR_NAME_V4 "Lan2Lan_USB_v4" +#define IPA_LAN_TO_LAN_USB_HDR_NAME_V6 "Lan2Lan_USB_v6" +#define IPA_LAN_TO_LAN_WLAN_HDR_NAME_V4 "Lan2Lan_Wlan_v4" +#define IPA_LAN_TO_LAN_WLAN_HDR_NAME_V6 "Lan2Lan_Wlan_v6" +#define IPA_LAN_TO_LAN_MAX_WLAN_CLIENT 16 +#define IPA_LAN_TO_LAN_MAX_USB_CLIENT 1 +#define IPA_LAN_TO_LAN_MAX_CPE_CLIENT 15 +#define IPA_LAN_TO_LAN_MAX_LAN_CLIENT (IPA_LAN_TO_LAN_MAX_USB_CLIENT + IPA_LAN_TO_LAN_MAX_CPE_CLIENT) +#define TCP_FIN_SHIFT 16 +#define TCP_SYN_SHIFT 17 +#define TCP_RST_SHIFT 18 +#define NUM_TCP_CTL_FLT_RULE 3 +#define NUM_IPV6_PREFIX_FLT_RULE 1 + +/*--------------------------------------------------------------------------- + Return values indicating error status +---------------------------------------------------------------------------*/ + +#define IPACM_SUCCESS 0 /* Successful operation */ +#define IPACM_FAILURE -1 /* Unsuccessful operation */ + +#define IPACM_IP_NULL (ipa_ip_type)0xFF +#define IPACM_INVALID_INDEX (ipa_ip_type)0xFF + +#define IPA_MAX_NUM_WIFI_CLIENTS 32 +#define IPA_MAX_NUM_WAN_CLIENTS 10 +#define IPA_MAX_NUM_ETH_CLIENTS 15 +#define IPA_MAX_NUM_AMPDU_RULE 15 +#define IPA_MAC_ADDR_SIZE 6 + +/*=========================================================================== + GLOBAL DEFINITIONS AND DECLARATIONS +===========================================================================*/ +typedef enum +{ + IPA_CFG_CHANGE_EVENT = 1, /* 1 NULL */ + IPA_LINK_UP_EVENT, /* 2 ipacm_event_data_fid */ + IPA_LINK_DOWN_EVENT, /* 3 ipacm_event_data_fid */ + IPA_ADDR_ADD_EVENT, /* 4 ipacm_event_data_addr */ + IPA_ADDR_DEL_EVENT, /* 5 no use */ + IPA_ROUTE_ADD_EVENT, /* 6 ipacm_event_data_addr */ + IPA_ROUTE_DEL_EVENT, /* 7 ipacm_event_data_addr */ + IPA_FIREWALL_CHANGE_EVENT, /* 8 NULL */ + IPA_WLAN_AP_LINK_UP_EVENT, /* 9 ipacm_event_data_mac */ + IPA_WLAN_STA_LINK_UP_EVENT, /* 10 ipacm_event_data_mac */ + IPA_WLAN_CLIENT_ADD_EVENT, /* 11 ipacm_event_data_mac */ + IPA_WLAN_CLIENT_DEL_EVENT, /* 12 ipacm_event_data_mac */ + IPA_WLAN_CLIENT_POWER_SAVE_EVENT, /* 13 ipacm_event_data_mac */ + IPA_WLAN_CLIENT_RECOVER_EVENT, /* 14 ipacm_event_data_mac */ + IPA_NEW_NEIGH_EVENT, /* 15 ipacm_event_data_all */ + IPA_DEL_NEIGH_EVENT, /* 16 ipacm_event_data_all */ + IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT, /* 17 ipacm_event_data_all */ + IPA_NEIGH_CLIENT_IP_ADDR_DEL_EVENT, /* 18 ipacm_event_data_all */ + IPA_SW_ROUTING_ENABLE, /* 19 NULL */ + IPA_SW_ROUTING_DISABLE, /* 20 NULL */ + IPA_PROCESS_CT_MESSAGE, /* 21 ipacm_ct_evt_data */ + IPA_HANDLE_WAN_UP, /* 22 ipacm_event_iface_up */ + IPA_HANDLE_WAN_DOWN, /* 23 ipacm_event_iface_up */ + IPA_HANDLE_WLAN_UP, /* 24 ipacm_event_iface_up */ + IPA_HANDLE_LAN_UP, /* 25 ipacm_event_iface_up */ + IPA_WLAN_CLIENT_ADD_EVENT_EX, /* 26 ipacm_event_data_wlan_ex */ + IPA_HANDLE_WAN_UP_V6, /* 27 NULL */ + IPA_HANDLE_WAN_DOWN_V6, /* 28 NULL */ + IPA_LAN_CLIENT_ACTIVE, /* 29 ipacm_event_lan_client*/ + IPA_LAN_CLIENT_INACTIVE, /* 30 ipacm_event_lan_client*/ + IPA_LAN_CLIENT_DISCONNECT, /* 31 ipacm_event_lan_client*/ + IPA_LAN_CLIENT_POWER_SAVE, /* 32 ipacm_event_lan_client*/ + IPA_LAN_CLIENT_POWER_RECOVER, /* 33 ipacm_event_lan_client*/ + IPA_LAN_TO_LAN_NEW_CONNECTION, /* 34 ipacm_event_connection */ + IPA_LAN_TO_LAN_DEL_CONNECTION, /* 35 ipacm_event_connection */ + IPA_LAN_DELETE_SELF, /* 36 ipacm_event_data_fid */ + IPA_WLAN_LINK_DOWN_EVENT, /* 37 ipacm_event_data_mac */ + IPA_USB_LINK_UP_EVENT, /* 38 ipacm_event_data_fid */ + IPA_PROCESS_CT_MESSAGE_V6, /* 39 ipacm_ct_evt_data */ + IPA_PRIVATE_SUBNET_CHANGE_EVENT, /* 40 ipacm_event_data_fid */ + IPA_WAN_UPSTREAM_ROUTE_ADD_EVENT, /* 41 ipacm_event_data_fid */ + IPA_WAN_UPSTREAM_ROUTE_DEL_EVENT, /* 42 ipacm_event_data_fid */ + IPA_WAN_EMBMS_LINK_UP_EVENT, /* 43 ipacm_event_data_mac */ + IPA_ETH_BRIDGE_LAN_CLIENT_ADD_EVENT, /* 44 ipacm_event_data_mac */ + IPA_ETH_BRIDGE_WLAN_CLIENT_ADD_EVENT, /* 45 ipacm_event_data_mac */ + IPA_ETH_BRIDGE_LAN_CLIENT_DEL_EVENT, /* 46 ipacm_event_data_mac */ + IPA_ETH_BRIDGE_WLAN_CLIENT_DEL_EVENT, /* 47 ipacm_event_data_mac */ + IPA_ETH_BRIDGE_HDR_PROC_CTX_SET_EVENT, /* 48 ipacm_event_data_if_cat */ + IPA_ETH_BRIDGE_HDR_PROC_CTX_UNSET_EVENT, /* 49 ipacm_event_data_if_cat */ + IPA_WLAN_SWITCH_TO_SCC, /* 50 No Data */ + IPA_WLAN_SWITCH_TO_MCC, /* 51 No Data */ + IPA_CRADLE_WAN_MODE_SWITCH, /* 52 ipacm_event_cradle_wan_mode */ + IPA_WAN_XLAT_CONNECT_EVENT, /* 53 ipacm_event_data_fid */ + IPA_TETHERING_STATS_UPDATE_EVENT, /* 54 ipacm_event_data_fid */ + IPA_NETWORK_STATS_UPDATE_EVENT, /* 55 ipacm_event_data_fid */ + IPA_HANDLE_WAN_UP_TETHER, /* 56 ipacm_event_iface_up_tehter */ + IPA_HANDLE_WAN_DOWN_TETHER, /* 57 ipacm_event_iface_up_tehter */ + IPA_HANDLE_WAN_UP_V6_TETHER, /* 58 ipacm_event_iface_up_tehter */ + IPA_HANDLE_WAN_DOWN_V6_TETHER, /* 59 ipacm_event_iface_up_tehter */ + IPA_BRIDGE_LINK_UP_EVENT, /* 60 ipacm_event_data_all */ + IPACM_EVENT_MAX +} ipa_cm_event_id; + +typedef struct +{ + uint8_t num_rule; + uint32_t rule_hdl[MAX_NUM_PROP]; +} lan_to_lan_rt_rule_hdl; + +typedef enum +{ + LAN_IF = 0, + WLAN_IF, + WAN_IF, + VIRTUAL_IF, + ETH_IF, + EMBMS_IF, + ODU_IF, + UNKNOWN_IF +} ipacm_iface_type; + +typedef enum +{ + ROUTER = 0, + BRIDGE +} ipacm_cradle_iface_mode; + +typedef enum +{ + FULL, + INTERNET +} ipacm_wlan_access_mode; + +typedef struct +{ + struct nf_conntrack *ct; + enum nf_conntrack_msg_type type; +}ipacm_ct_evt_data; + +typedef struct +{ + char iface_name[IPA_IFACE_NAME_LEN]; + ipacm_iface_type if_cat; + ipacm_cradle_iface_mode if_mode; + ipacm_wlan_access_mode wlan_mode; + int netlink_interface_index; +} ipa_ifi_dev_name_t; + +typedef struct +{ + uint32_t subnet_addr; + uint32_t subnet_mask; +} ipa_private_subnet; + + +typedef struct _ipacm_event_data_all +{ + enum ipa_ip_type iptype; + int if_index; + uint32_t ipv4_addr; + uint32_t ipv6_addr[4]; + uint8_t mac_addr[IPA_MAC_ADDR_SIZE]; +} ipacm_event_data_all; + +class IPACM_Lan; + +typedef struct +{ + ipacm_cradle_iface_mode cradle_wan_mode; +} ipacm_event_cradle_wan_mode; + +typedef struct +{ + enum ipa_ip_type iptype; + uint32_t ipv4_addr; + uint32_t ipv6_addr[4]; + uint8_t mac_addr[6]; + IPACM_Lan* p_iface; +} ipacm_event_lan_client; + +typedef struct +{ + enum ipa_ip_type iptype; + uint32_t src_ipv4_addr; + uint32_t dst_ipv4_addr; + uint32_t src_ipv6_addr[4]; + uint32_t dst_ipv6_addr[4]; +} ipacm_event_connection; + +typedef struct _ipacm_event_data_fid +{ + int if_index; +} ipacm_event_data_fid; + +typedef struct +{ + ipacm_iface_type if_cat; +} ipacm_event_data_if_cat; + +typedef struct _ipacm_event_data_iptype +{ + int if_index; + int if_index_tether; + enum ipa_ip_type iptype; +} ipacm_event_data_iptype; + + +typedef struct _ipacm_event_data_addr +{ + enum ipa_ip_type iptype; + int if_index; + uint32_t ipv4_addr_gw; + uint32_t ipv4_addr; + uint32_t ipv4_addr_mask; + uint32_t ipv6_addr[4]; + uint32_t ipv6_addr_mask[4]; + uint32_t ipv6_addr_gw[4]; +} ipacm_event_data_addr; + +typedef struct _ipacm_event_data_mac +{ + int if_index; + uint8_t mac_addr[IPA_MAC_ADDR_SIZE]; +} ipacm_event_data_mac; + +typedef struct +{ + int if_index; + uint8_t num_of_attribs; + struct ipa_wlan_hdr_attrib_val attribs[0]; +} ipacm_event_data_wlan_ex; + +typedef struct _ipacm_event_iface_up +{ + char ifname[IPA_IFACE_NAME_LEN]; + uint32_t ipv4_addr; + uint32_t addr_mask; + uint32_t ipv6_prefix[2]; + bool is_sta; + uint8_t xlat_mux_id; +}ipacm_event_iface_up; + +typedef struct _ipacm_event_iface_up_tether +{ + uint32_t if_index_tether; + uint32_t ipv6_prefix[2]; + bool is_sta; +}ipacm_event_iface_up_tehter; + +typedef enum +{ + Q6_WAN = 0, + WLAN_WAN, + ECM_WAN +} ipacm_wan_iface_type; + +typedef struct _ipacm_ifacemgr_data +{ + int if_index; + ipacm_wan_iface_type if_type; + uint8_t mac_addr[IPA_MAC_ADDR_SIZE]; +}ipacm_ifacemgr_data; + +#endif /* IPA_CM_DEFS_H */ diff --git a/data-ipa-cfg-mgr/ipacm/inc/IPACM_EvtDispatcher.h b/data-ipa-cfg-mgr/ipacm/inc/IPACM_EvtDispatcher.h new file mode 100644 index 000000000..550f4d4c3 --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/inc/IPACM_EvtDispatcher.h @@ -0,0 +1,76 @@ +/* +Copyright (c) 2013, The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/*! + @file + IPACM_EvtDispatcher.h + + @brief + This file implements the IPAM event dispatcher definitions + + @Author + +*/ +#ifndef IPACM_EvtDispatcher_H +#define IPACM_EvtDispatcher_H + +#include +#include +#include "IPACM_Defs.h" +#include "IPACM_Listener.h" + +/* queue */ +typedef struct _cmd_evts +{ + ipa_cm_event_id event; + IPACM_Listener *obj; + //int ipa_interface_index; + _cmd_evts *next; +} cmd_evts; + + + +class IPACM_EvtDispatcher +{ +public: + + /* api for all iface instances to register events */ + static int registr(ipa_cm_event_id event, IPACM_Listener *obj); + + /* api for all iface instances to de-register events */ + static int deregistr(IPACM_Listener *obj); + + static int PostEvt(ipacm_cmd_q_data *); + static void ProcessEvt(ipacm_cmd_q_data *); + +private: + static cmd_evts *head; +}; + +#endif /* IPACM_EvtDispatcher_H */ diff --git a/data-ipa-cfg-mgr/ipacm/inc/IPACM_Filtering.h b/data-ipa-cfg-mgr/ipacm/inc/IPACM_Filtering.h new file mode 100644 index 000000000..7554ba90a --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/inc/IPACM_Filtering.h @@ -0,0 +1,75 @@ +/* +Copyright (c) 2013, The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/*! + @file + IPACM_Filtering.h + + @brief + This file implements the IPACM filtering definitions + + @Author + Skylar Chang + +*/ + +#ifndef IPACM_FILTERING_H +#define IPACM_FILTERING_H + +#include +#include +#include +#include + +class IPACM_Filtering +{ +public: + IPACM_Filtering(); + ~IPACM_Filtering(); + bool AddFilteringRule(struct ipa_ioc_add_flt_rule const *ruleTable); + bool DeleteFilteringRule(struct ipa_ioc_del_flt_rule *ruleTable); + bool Commit(enum ipa_ip_type ip); + bool Reset(enum ipa_ip_type ip); + bool DeviceNodeIsOpened(); + bool DeleteFilteringHdls(uint32_t *flt_rule_hdls, + ipa_ip_type ip, + uint8_t num_rules); + + bool AddWanDLFilteringRule(struct ipa_ioc_add_flt_rule const *rule_table_v4, struct ipa_ioc_add_flt_rule const * rule_table_v6, uint8_t mux_id); + bool SendFilteringRuleIndex(struct ipa_fltr_installed_notif_req_msg_v01* table); + bool ModifyFilteringRule(struct ipa_ioc_mdfy_flt_rule* ruleTable); + ipa_filter_action_enum_v01 GetQmiFilterAction(ipa_flt_action action); + +private: + static const char *DEVICE_NAME; + int fd; /* File descriptor of the IPA device node /dev/ipa */ +}; + +#endif //IPACM_FILTERING_H + diff --git a/data-ipa-cfg-mgr/ipacm/inc/IPACM_Header.h b/data-ipa-cfg-mgr/ipacm/inc/IPACM_Header.h new file mode 100644 index 000000000..027c8ff3b --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/inc/IPACM_Header.h @@ -0,0 +1,70 @@ +/* +Copyright (c) 2013, The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* + * IPACM_Header.h + * + * Created on: Jun 20, 2012 + * Author: tatias + */ + +////////////////////////////////////////////////////////////////////////////////// + +#ifndef IPACM_HEADER_H +#define IPACM_HEADER_H + +#include +#include "linux/msm_ipa.h" + +////////////////////////////////////////////////////////////////////////////////// + +class IPACM_Header +{ +private: + int m_fd; +public: + bool AddHeader(struct ipa_ioc_add_hdr *pHeaderTable); + bool DeleteHeader(struct ipa_ioc_del_hdr *pHeaderTable); + bool GetHeaderHandle(struct ipa_ioc_get_hdr *pHeaderStruct); + bool CopyHeader(struct ipa_ioc_copy_hdr *pCopyHeaderStruct); + bool Commit(); + bool Reset(); + bool DeleteHeaderHdl(uint32_t hdr_hdl); + bool AddHeaderProcCtx(struct ipa_ioc_add_hdr_proc_ctx* pHeader); + bool DeleteHeaderProcCtx(uint32_t hdl); + + IPACM_Header(); + ~IPACM_Header(); + bool DeviceNodeIsOpened(); +}; + + +#endif + + diff --git a/data-ipa-cfg-mgr/ipacm/inc/IPACM_Iface.h b/data-ipa-cfg-mgr/ipacm/inc/IPACM_Iface.h new file mode 100644 index 000000000..efcaa6313 --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/inc/IPACM_Iface.h @@ -0,0 +1,158 @@ +/* +Copyright (c) 2013, The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +/*! + @file + IPACM_iface.h + + @brief + This file implements the basis Iface definitions. + + @Author + Skylar Chang + +*/ +#ifndef IPACM_IFACE_H +#define IPACM_IFACE_H + +#include +#include +#include +#include "IPACM_Routing.h" +#include "IPACM_Filtering.h" +#include "IPACM_Header.h" +#include "IPACM_EvtDispatcher.h" +#include "IPACM_Xml.h" +#include "IPACM_Log.h" +#include "IPACM_Config.h" +#include "IPACM_Defs.h" +#include + +/* current support 2 ipv6-address*/ +#define MAX_DEFAULT_v4_ROUTE_RULES 1 +#define MAX_DEFAULT_v6_ROUTE_RULES 2 +#define IPV4_DEFAULT_FILTERTING_RULES 3 + +#ifdef FEATURE_IPA_ANDROID +#define IPV6_DEFAULT_FILTERTING_RULES 6 +#else +#define IPV6_DEFAULT_FILTERTING_RULES 3 +#endif + +#define IPV6_DEFAULT_LAN_FILTERTING_RULES 1 +#define IPV6_NUM_ADDR 3 +#define MAX_SOFTWAREROUTING_FILTERTING_RULES 2 +#define INVALID_IFACE -1 + +/* iface */ +class IPACM_Iface :public IPACM_Listener +{ +public: + + /* Static class for reading IPACM configuration from XML file*/ + static IPACM_Config *ipacmcfg; + + /* IPACM interface id */ + int ipa_if_num; + + /* IPACM interface category */ + int ipa_if_cate; + + /* IPACM interface name */ + char dev_name[IF_NAME_LEN]; + + /* IPACM interface iptype v4, v6 or both */ + ipa_ip_type ip_type; + + /* IPACM interface v6 ip-address*/ + uint32_t ipv6_addr[MAX_DEFAULT_v6_ROUTE_RULES][4]; + + uint32_t header_hdl; + + uint32_t software_routing_fl_rule_hdl[MAX_SOFTWAREROUTING_FILTERTING_RULES]; + + bool softwarerouting_act; + + /* IPACM number of default route rules for ipv6*/ + int num_dft_rt_v6; + + uint32_t dft_v4fl_rule_hdl[IPV4_DEFAULT_FILTERTING_RULES]; + uint32_t dft_v6fl_rule_hdl[IPV6_DEFAULT_FILTERTING_RULES + IPV6_DEFAULT_LAN_FILTERTING_RULES]; + /* create additional set of v6 RT-rules in Wanv6RT table*/ + uint32_t dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES+2*MAX_DEFAULT_v6_ROUTE_RULES]; + + ipa_ioc_query_intf *iface_query; + ipa_ioc_query_intf_tx_props *tx_prop; + ipa_ioc_query_intf_rx_props *rx_prop; + + virtual int handle_down_evt() = 0; + + virtual int handle_addr_evt(ipacm_event_data_addr *data) = 0; + + IPACM_Iface(int iface_index); + + virtual void event_callback(ipa_cm_event_id event, + void *data) = 0; + + /* Query ipa_interface_index by given linux interface_index */ + static int iface_ipa_index_query(int interface_index); + + /* Query ipa_interface ipv4_addr by given linux interface_index */ + static void iface_addr_query(int interface_index); + + /*Query the IPA endpoint property */ + int query_iface_property(void); + + /*implement IPACM strlcpy */ + size_t strlcpy(char *dest, const char *src, size_t size); + + /*implement IPACM strlcat */ + size_t strlcat(char *dest, const char *src, size_t n); + + /*Configure the initial filter rules */ + virtual int init_fl_rule(ipa_ip_type iptype); + + /* Get interface index */ + virtual int ipa_get_if_index(char * if_name, int * if_index); + + static IPACM_Routing m_routing; + static IPACM_Filtering m_filtering; + static IPACM_Header m_header; + + /* software routing enable */ + virtual int handle_software_routing_enable(void); + + /* software routing disable */ + virtual int handle_software_routing_disable(void); + +private: + + static const char *DEVICE_NAME; +}; + +#endif /* IPACM_IFACE_H */ diff --git a/data-ipa-cfg-mgr/ipacm/inc/IPACM_IfaceManager.h b/data-ipa-cfg-mgr/ipacm/inc/IPACM_IfaceManager.h new file mode 100644 index 000000000..e65c5d5b6 --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/inc/IPACM_IfaceManager.h @@ -0,0 +1,91 @@ +/* +Copyright (c) 2013, The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +/*! + @file + IPACM_IfaceManager.h + + @brief + This file implements the IPAM iface_manager definitions + + @Author + Skylar Chang + +*/ +#ifndef IPACM_IFACEMANAGER_H +#define IPACM_IFACEMANAGER_H + +#include +#include + +#include "IPACM_Routing.h" +#include "IPACM_Filtering.h" +#include "IPACM_Listener.h" +#include "IPACM_Iface.h" + +#define IPA_MAX_NUM_NEIGHBOR_CLIENTS 17 +#define IPA_INSTANCE_NOT_FOUND 0 +#define IPA_INSTANCE_FOUND 1 + +/* queue */ +typedef struct _iface_instances +{ + /* Linux interface id */ + int ipa_if_index; + IPACM_Listener *obj; + _iface_instances *next; +} iface_instances; + + +class IPACM_IfaceManager : public IPACM_Listener +{ + +public: + + IPACM_IfaceManager(); + + void event_callback(ipa_cm_event_id event, + void *data); + + /* api for all iface instances to de-register instances */ + static int deregistr(IPACM_Listener *param); + + +private: + int create_iface_instance(ipacm_ifacemgr_data *); + + /* api to register instances */ + int registr(int ipa_if_index, IPACM_Listener *obj); + + int SearchInstance(int ipa_if_index); + + static iface_instances *head; + +}; + +#endif /* IPACM_IFACEMANAGER_H */ diff --git a/data-ipa-cfg-mgr/ipacm/inc/IPACM_Lan.h b/data-ipa-cfg-mgr/ipacm/inc/IPACM_Lan.h new file mode 100644 index 000000000..a21025519 --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/inc/IPACM_Lan.h @@ -0,0 +1,518 @@ +/* +Copyright (c) 2013, The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +/*! + @file + IPACM_Lan.h + + @brief + This file implements the LAN iface definitions + + @Author + Skylar Chang + +*/ +#ifndef IPACM_LAN_H +#define IPACM_LAN_H + +#include +#include + +#include "IPACM_CmdQueue.h" +#include "IPACM_Iface.h" +#include "IPACM_Routing.h" +#include "IPACM_Filtering.h" +#include "IPACM_Config.h" +#include "IPACM_Conntrack_NATApp.h" + +#define IPA_WAN_DEFAULT_FILTER_RULE_HANDLES 1 +#define IPA_PRIV_SUBNET_FILTER_RULE_HANDLES 3 +#define IPA_NUM_ODU_ROUTE_RULES 2 +#define MAX_WAN_UL_FILTER_RULES MAX_NUM_EXT_PROPS +#define NUM_IPV4_ICMP_FLT_RULE 1 +#define NUM_IPV6_ICMP_FLT_RULE 1 + +/* ndc bandwidth ipatetherstats */ +/* out_bytes> out_pkts> in_bytes> in_pkts */ + +#define PIPE_STATS "%s %s %lu %lu %lu %lu" +#define IPA_PIPE_STATS_FILE_NAME "/data/misc/ipa/tether_stats" + +/* store each lan-iface unicast routing rule and its handler*/ +struct ipa_lan_rt_rule +{ + ipa_ip_type ip; + uint32_t v4_addr; + uint32_t v4_addr_mask; + uint32_t v6_addr[4]; + uint32_t rt_rule_hdl[0]; +}; + +typedef enum +{ + SRC_WLAN, + SRC_LAN +} eth_bridge_src_iface; + +typedef enum +{ + DST_WLAN, + DST_LAN +} eth_bridge_dst_iface; + +/* Support multiple eth client */ +typedef struct _eth_client_rt_hdl +{ + uint32_t eth_rt_rule_hdl_v4; + uint32_t eth_rt_rule_hdl_v6[IPV6_NUM_ADDR]; + uint32_t eth_rt_rule_hdl_v6_wan[IPV6_NUM_ADDR]; +}eth_client_rt_hdl; + +typedef struct _ipa_eth_client +{ + uint8_t mac[IPA_MAC_ADDR_SIZE]; + uint32_t v4_addr; + uint32_t v6_addr[IPV6_NUM_ADDR][4]; + uint32_t hdr_hdl_v4; + uint32_t hdr_hdl_v6; + bool route_rule_set_v4; + int route_rule_set_v6; + bool ipv4_set; + int ipv6_set; + bool ipv4_header_set; + bool ipv6_header_set; + eth_client_rt_hdl eth_rt_hdl[0]; /* depends on number of tx properties */ +}ipa_eth_client; + +struct lan2lan_flt_rule_hdl +{ + uint32_t rule_hdl; + bool valid; +}; + +struct lan2lan_hdr_hdl +{ + uint32_t hdr_hdl; + bool valid; +}; + +struct eth_bridge_client_flt_info +{ + uint8_t mac[IPA_MAC_ADDR_SIZE]; + uint32_t flt_rule_hdl_v4; + bool flt_rule_set_v4; + uint32_t flt_rule_hdl_v6; + bool flt_rule_set_v6; +}; + +struct eth_bridge_client_rt_info +{ + uint8_t mac[IPA_MAC_ADDR_SIZE]; + uint32_t rt_rule_hdl[0]; +}; + +struct hdr_proc_ctx_info +{ + uint32_t proc_ctx_hdl; + bool valid; +}; + +struct eth_bridge_subnet_client_info +{ + uint8_t mac[IPA_MAC_ADDR_SIZE]; + int ipa_if_num; +}; + +/* lan iface */ +class IPACM_Lan : public IPACM_Iface +{ +public: + + IPACM_Lan(int iface_index); + ~IPACM_Lan(); + + /* store lan's wan-up filter rule handlers */ + uint32_t lan_wan_fl_rule_hdl[IPA_WAN_DEFAULT_FILTER_RULE_HANDLES]; + + /* store private-subnet filter rule handlers */ + uint32_t private_fl_rule_hdl[IPA_MAX_PRIVATE_SUBNET_ENTRIES]; + + /* LAN-iface's callback function */ + void event_callback(ipa_cm_event_id event, void *data); + + virtual int handle_wan_up(ipa_ip_type ip_type); + + /* configure filter rule for wan_up event*/ + virtual int handle_wan_up_ex(ipacm_ext_prop* ext_prop, ipa_ip_type iptype, uint8_t xlat_mux_id); + + /* delete filter rule for wan_down event*/ + virtual int handle_wan_down(bool is_sta_mode); + + /* delete filter rule for wan_down event*/ + virtual int handle_wan_down_v6(bool is_sta_mode); + + /* configure private subnet filter rules*/ + virtual int handle_private_subnet(ipa_ip_type iptype); + + /* handle new_address event*/ + int handle_addr_evt(ipacm_event_data_addr *data); + + int handle_addr_evt_odu_bridge(ipacm_event_data_addr* data); + + int handle_del_ipv6_addr(ipacm_event_data_all *data); + + static bool odu_up; + + /* install UL filter rule from Q6 */ + virtual int handle_uplink_filter_rule(ipacm_ext_prop* prop, ipa_ip_type iptype, uint8_t xlat_mux_id); + + int add_lan2lan_flt_rule(ipa_ip_type iptype, uint32_t src_v4_addr, uint32_t dst_v4_addr, uint32_t* src_v6_addr, uint32_t* dst_v6_addr, uint32_t* rule_hdl); + + int del_lan2lan_flt_rule(ipa_ip_type iptype, uint32_t rule_hdl); + + virtual int add_lan2lan_hdr(ipa_ip_type iptype, uint8_t* src_mac, uint8_t* dst_mac, uint32_t* hdr_hdl); + + int add_lan2lan_rt_rule(ipa_ip_type iptype, uint32_t src_v4_addr, uint32_t dst_v4_addr, + uint32_t* src_v6_addr, uint32_t* dst_v6_addr, uint32_t hdr_hdl, lan_to_lan_rt_rule_hdl* rule_hdl); + + int del_lan2lan_rt_rule(ipa_ip_type iptype, lan_to_lan_rt_rule_hdl); + + int del_lan2lan_hdr(ipa_ip_type iptype, uint32_t hdr_hdl); + + int handle_cradle_wan_mode_switch(bool is_wan_bridge_mode); + + int install_ipv4_icmp_flt_rule(); + + static ipa_hdr_l2_type lan_hdr_type; + static ipa_hdr_l2_type wlan_hdr_type; + + static uint32_t usb_hdr_template_hdl; + static uint32_t wlan_hdr_template_hdl; + static uint32_t cpe_hdr_template_hdl; + + static hdr_proc_ctx_info lan_to_wlan_hdr_proc_ctx, wlan_to_usb_hdr_proc_ctx, wlan_to_cpe_hdr_proc_ctx; + static hdr_proc_ctx_info wlan_to_wlan_hdr_proc_ctx; + static hdr_proc_ctx_info cpe_to_usb_hdr_proc_ctx, usb_to_cpe_hdr_proc_ctx; + + static eth_bridge_subnet_client_info eth_bridge_wlan_client[IPA_LAN_TO_LAN_MAX_WLAN_CLIENT]; + static eth_bridge_subnet_client_info eth_bridge_lan_client[IPA_LAN_TO_LAN_MAX_LAN_CLIENT]; + + static int num_wlan_client; + static int num_lan_client; + + static bool is_usb_up; + static bool is_cpe_up; + +protected: + + lan2lan_flt_rule_hdl wlan_client_flt_rule_hdl_v4[IPA_LAN_TO_LAN_MAX_WLAN_CLIENT]; + lan2lan_flt_rule_hdl wlan_client_flt_rule_hdl_v6[IPA_LAN_TO_LAN_MAX_WLAN_CLIENT]; + lan2lan_flt_rule_hdl lan_client_flt_rule_hdl_v4[IPA_LAN_TO_LAN_MAX_LAN_CLIENT]; + lan2lan_flt_rule_hdl lan_client_flt_rule_hdl_v6[IPA_LAN_TO_LAN_MAX_LAN_CLIENT]; + + eth_bridge_client_flt_info eth_bridge_wlan_client_flt_info[IPA_LAN_TO_LAN_MAX_WLAN_CLIENT]; + eth_bridge_client_flt_info eth_bridge_lan_client_flt_info[IPA_LAN_TO_LAN_MAX_LAN_CLIENT]; + + int wlan_client_flt_info_count; + int lan_client_flt_info_count; + + int client_rt_info_size_v4; + int client_rt_info_size_v6; + + eth_bridge_client_rt_info* eth_bridge_lan_client_rt_from_lan_info_v4; + int lan_client_rt_from_lan_info_count_v4; + eth_bridge_client_rt_info* eth_bridge_lan_client_rt_from_lan_info_v6; + int lan_client_rt_from_lan_info_count_v6; + eth_bridge_client_rt_info* eth_bridge_lan_client_rt_from_wlan_info_v4; + int lan_client_rt_from_wlan_info_count_v4; + eth_bridge_client_rt_info* eth_bridge_lan_client_rt_from_wlan_info_v6; + int lan_client_rt_from_wlan_info_count_v6; + + int each_client_rt_rule_count_v4; + int each_client_rt_rule_count_v6; + + virtual int eth_bridge_handle_dummy_wlan_client_flt_rule(ipa_ip_type iptype); + + virtual int eth_bridge_handle_dummy_lan_client_flt_rule(ipa_ip_type iptype); + + int eth_bridge_add_lan_client_flt_rule(uint8_t* mac, ipa_ip_type iptype); + + int eth_bridge_del_lan_client_flt_rule(uint8_t* mac); + + int eth_bridge_add_wlan_client_flt_rule(uint8_t* mac, ipa_ip_type iptype); + + int eth_bridge_del_wlan_client_flt_rule(uint8_t* mac); + + int eth_bridge_post_lan_client_event(uint8_t* mac_addr, ipa_cm_event_id evt); + + int add_hdr_proc_ctx(); + + int del_hdr_proc_ctx(); + + ipa_hdr_proc_type get_hdr_proc_type(ipa_hdr_l2_type t1, ipa_hdr_l2_type t2); + + virtual int eth_bridge_install_cache_wlan_client_flt_rule(ipa_ip_type iptype); + + virtual int eth_bridge_install_cache_lan_client_flt_rule(ipa_ip_type iptype); + + int eth_bridge_add_lan_client_rt_rule(uint8_t* mac, eth_bridge_src_iface src, ipa_ip_type iptype); + + int eth_bridge_del_lan_client_rt_rule(uint8_t* mac, eth_bridge_src_iface src); + + eth_bridge_client_rt_info* eth_bridge_get_client_rt_info_ptr(uint8_t index, eth_bridge_src_iface src, ipa_ip_type iptype); + + void eth_bridge_add_lan_client(uint8_t* mac); + + void eth_bridge_del_lan_client(uint8_t* mac); + + int eth_bridge_get_hdr_template_hdl(uint32_t* hdr_hdl); + + + + virtual int add_dummy_lan2lan_flt_rule(ipa_ip_type iptype); + + virtual int add_dummy_private_subnet_flt_rule(ipa_ip_type iptype); + + int handle_private_subnet_android(ipa_ip_type iptype); + + int reset_to_dummy_flt_rule(ipa_ip_type iptype, uint32_t rule_hdl); + + /*handle lan2lan client active*/ + int handle_lan2lan_client_active(ipacm_event_data_all *data, ipa_cm_event_id event); + + virtual int install_ipv6_prefix_flt_rule(uint32_t* prefix); + + virtual void delete_ipv6_prefix_flt_rule(); + + int install_ipv6_icmp_flt_rule(); + + void post_del_self_evt(); + + /* handle tethering stats */ + int handle_tethering_stats_event(ipa_get_data_stats_resp_msg_v01 *data); + + /* handle tethering client */ + int handle_tethering_client(bool reset, ipacm_client_enum ipa_client); + + lan2lan_flt_rule_hdl lan2lan_flt_rule_hdl_v4[MAX_OFFLOAD_PAIR]; + lan2lan_flt_rule_hdl lan2lan_flt_rule_hdl_v6[MAX_OFFLOAD_PAIR]; + + uint8_t num_lan2lan_flt_rule_v4; + uint8_t num_lan2lan_flt_rule_v6; + + lan2lan_hdr_hdl lan2lan_hdr_hdl_v4[MAX_OFFLOAD_PAIR]; + lan2lan_hdr_hdl lan2lan_hdr_hdl_v6[MAX_OFFLOAD_PAIR]; + + /* store ipv4 UL filter rule handlers from Q6*/ + uint32_t wan_ul_fl_rule_hdl_v4[MAX_WAN_UL_FILTER_RULES]; + + /* store ipv6 UL filter rule handlers from Q6*/ + uint32_t wan_ul_fl_rule_hdl_v6[MAX_WAN_UL_FILTER_RULES]; + + virtual void install_tcp_ctl_flt_rule(ipa_ip_type iptype); + + uint32_t ipv4_icmp_flt_rule_hdl[NUM_IPV4_ICMP_FLT_RULE]; + uint32_t tcp_ctl_flt_rule_hdl_v4[NUM_TCP_CTL_FLT_RULE]; + uint32_t tcp_ctl_flt_rule_hdl_v6[NUM_TCP_CTL_FLT_RULE]; + + uint32_t ipv6_prefix_flt_rule_hdl[NUM_IPV6_PREFIX_FLT_RULE]; + uint32_t ipv6_icmp_flt_rule_hdl[NUM_IPV6_ICMP_FLT_RULE]; + + int num_wan_ul_fl_rule_v4; + int num_wan_ul_fl_rule_v6; + + bool is_active; + bool modem_ul_v4_set; + bool modem_ul_v6_set; + + uint32_t if_ipv4_subnet; + + /* expected modem UL rules starting index */ + int exp_index_v4; + int exp_index_v6; + +private: + + /* dynamically allocate lan iface's unicast routing rule structure */ + + bool is_mode_switch; /* indicate mode switch, need post internal up event */ + + int eth_client_len; + + ipa_eth_client *eth_client; + + int header_name_count; + + int num_eth_client; + + NatApp *Nat_App; + + int ipv6_set; + + uint32_t ODU_hdr_hdl_v4, ODU_hdr_hdl_v6; + + uint32_t *odu_route_rule_v4_hdl; + + uint32_t *odu_route_rule_v6_hdl; + + bool ipv4_header_set; + + bool ipv6_header_set; + + inline ipa_eth_client* get_client_memptr(ipa_eth_client *param, int cnt) + { + char *ret = ((char *)param) + (eth_client_len * cnt); + return (ipa_eth_client *)ret; + } + + inline int get_eth_client_index(uint8_t *mac_addr) + { + int cnt; + int num_eth_client_tmp = num_eth_client; + + IPACMDBG_H("Passed MAC %02x:%02x:%02x:%02x:%02x:%02x\n", + mac_addr[0], mac_addr[1], mac_addr[2], + mac_addr[3], mac_addr[4], mac_addr[5]); + + for(cnt = 0; cnt < num_eth_client_tmp; cnt++) + { + IPACMDBG_H("stored MAC %02x:%02x:%02x:%02x:%02x:%02x\n", + get_client_memptr(eth_client, cnt)->mac[0], + get_client_memptr(eth_client, cnt)->mac[1], + get_client_memptr(eth_client, cnt)->mac[2], + get_client_memptr(eth_client, cnt)->mac[3], + get_client_memptr(eth_client, cnt)->mac[4], + get_client_memptr(eth_client, cnt)->mac[5]); + + if(memcmp(get_client_memptr(eth_client, cnt)->mac, + mac_addr, + sizeof(get_client_memptr(eth_client, cnt)->mac)) == 0) + { + IPACMDBG_H("Matched client index: %d\n", cnt); + return cnt; + } + } + + return IPACM_INVALID_INDEX; + } + + inline int delete_eth_rtrules(int clt_indx, ipa_ip_type iptype) + { + uint32_t tx_index; + uint32_t rt_hdl; + int num_v6; + + if(iptype == IPA_IP_v4) + { + for(tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++) + { + if((tx_prop->tx[tx_index].ip == IPA_IP_v4) && (get_client_memptr(eth_client, clt_indx)->route_rule_set_v4==true)) /* for ipv4 */ + { + IPACMDBG_H("Delete client index %d ipv4 RT-rules for tx:%d\n",clt_indx,tx_index); + rt_hdl = get_client_memptr(eth_client, clt_indx)->eth_rt_hdl[tx_index].eth_rt_rule_hdl_v4; + + if(m_routing.DeleteRoutingHdl(rt_hdl, IPA_IP_v4) == false) + { + return IPACM_FAILURE; + } + } + } /* end of for loop */ + + /* clean the ipv4 RT rules for eth-client:clt_indx */ + if(get_client_memptr(eth_client, clt_indx)->route_rule_set_v4==true) /* for ipv4 */ + { + get_client_memptr(eth_client, clt_indx)->route_rule_set_v4 = false; + } + } + + if(iptype == IPA_IP_v6) + { + for(tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++) + { + if((tx_prop->tx[tx_index].ip == IPA_IP_v6) && (get_client_memptr(eth_client, clt_indx)->route_rule_set_v6 != 0)) /* for ipv6 */ + { + for(num_v6 =0;num_v6 < get_client_memptr(eth_client, clt_indx)->route_rule_set_v6;num_v6++) + { + IPACMDBG_H("Delete client index %d ipv6 RT-rules for %d-st ipv6 for tx:%d\n", clt_indx,num_v6,tx_index); + rt_hdl = get_client_memptr(eth_client, clt_indx)->eth_rt_hdl[tx_index].eth_rt_rule_hdl_v6[num_v6]; + if(m_routing.DeleteRoutingHdl(rt_hdl, IPA_IP_v6) == false) + { + return IPACM_FAILURE; + } + + rt_hdl = get_client_memptr(eth_client, clt_indx)->eth_rt_hdl[tx_index].eth_rt_rule_hdl_v6_wan[num_v6]; + if(m_routing.DeleteRoutingHdl(rt_hdl, IPA_IP_v6) == false) + { + return IPACM_FAILURE; + } + } + } + } /* end of for loop */ + + /* clean the ipv6 RT rules for eth-client:clt_indx */ + if(get_client_memptr(eth_client, clt_indx)->route_rule_set_v6 != 0) /* for ipv6 */ + { + get_client_memptr(eth_client, clt_indx)->route_rule_set_v6 = 0; + } + } + + return IPACM_SUCCESS; + } + + /* handle eth client initial, construct full headers (tx property) */ + int handle_eth_hdr_init(uint8_t *mac_addr); + + /* handle eth client ip-address */ + int handle_eth_client_ipaddr(ipacm_event_data_all *data); + + /* handle eth client routing rule*/ + int handle_eth_client_route_rule(uint8_t *mac_addr, ipa_ip_type iptype); + + /*handle eth client del mode*/ + int handle_eth_client_down_evt(uint8_t *mac_addr); + + /* handle odu client initial, construct full headers (tx property) */ + int handle_odu_hdr_init(uint8_t *mac_addr); + + /* handle odu default route rule configuration */ + int handle_odu_route_add(); + + /* handle odu default route rule deletion */ + int handle_odu_route_del(); + + /*handle lan iface down event*/ + int handle_down_evt(); + + /*handle lan2lan internal mesg posting*/ + int post_lan2lan_client_disconnect_msg(ipa_ip_type iptype); + + /*handle reset usb-client rt-rules */ + int handle_lan_client_reset_rt(ipa_ip_type iptype); +}; + +#endif /* IPACM_LAN_H */ diff --git a/data-ipa-cfg-mgr/ipacm/inc/IPACM_LanToLan.h b/data-ipa-cfg-mgr/ipacm/inc/IPACM_LanToLan.h new file mode 100644 index 000000000..06d5832ed --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/inc/IPACM_LanToLan.h @@ -0,0 +1,175 @@ +/* +Copyright (c) 2014, The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* + * IPACM_LanToLan.h + * + * Created on: Mar 4th, 2014 + * Author: Shihuan Liu + */ + +#ifndef IPACM_LANTOLAN_H +#define IPACM_LANTOLAN_H + +#include +#include "linux/msm_ipa.h" +#include "IPACM_Iface.h" +#include "IPACM_Defs.h" +#include "IPACM_Lan.h" +#include + +#ifdef FEATURE_IPA_ANDROID +#include +#else/* defined(FEATURE_IPA_ANDROID) */ +#include +#endif /* ndefined(FEATURE_IPA_ANDROID)*/ + +struct client_info; + +struct peer_info +{ + struct client_info* peer_pointer; + int num_connection; +}; + +//used to store rule handles for offload link (one direction) +struct offload_link_info +{ + struct client_info* peer_pointer; + uint32_t flt_rule_hdl; + lan_to_lan_rt_rule_hdl rt_rule_hdl; + uint32_t hdr_hdl; +}; + +typedef list peer_info_list; +typedef list offload_link_info_list; +typedef list connection_list; + +struct client_info +{ + union + { + uint32_t ipv4_addr; + uint32_t ipv6_addr[4]; + } ip; + uint8_t mac_addr[6]; + bool is_active; + bool is_powersave; + IPACM_Lan* p_iface; + peer_info_list peer; + offload_link_info_list link; +}; + +struct v6_addr +{ + uint32_t ipv6_addr[4]; +}; + +typedef unordered_map client_table_v4; +typedef unordered_map client_table_v6; + + +class IPACM_LanToLan : public IPACM_Listener +{ + +public: + + IPACM_LanToLan(); + ~IPACM_LanToLan(); + + void handle_new_connection(ipacm_event_connection* new_conn); + void handle_del_connection(ipacm_event_connection* del_conn); + + static IPACM_LanToLan* getLan2LanInstance(); + +private: + + uint8_t num_offload_pair_v4_; + uint8_t num_offload_pair_v6_; + client_table_v4 client_info_v4_; + client_table_v6 client_info_v6_; + + connection_list connection_v4_; + connection_list connection_v6_; + + static IPACM_LanToLan* p_instance; + + void event_callback(ipa_cm_event_id event, void* param); + + void handle_client_active(ipacm_event_lan_client* data); + + void check_potential_link(ipa_ip_type iptype, client_info* client); + + int add_offload_link(ipa_ip_type iptype, client_info* client, client_info* peer); + + void handle_client_inactive(ipacm_event_lan_client* data); + + int turnoff_offload_links(ipa_ip_type iptype, client_info* client); + + int del_offload_link(ipa_ip_type iptype, IPACM_Lan* client, IPACM_Lan* peer, offload_link_info* link); + + void handle_client_disconnect(ipacm_event_lan_client* data); + + int clear_peer_list(client_info* client); + + void handle_client_power_save(ipacm_event_lan_client* data); + + void handle_client_power_recover(ipacm_event_lan_client* data); + + int remove_flt_rules(ipa_ip_type iptype, client_info* client); + + int add_flt_rules(ipa_ip_type iptype, client_info* client); + +//the following are for connections + + void handle_new_lan2lan_connection(ipacm_event_connection* data); + + bool add_connection(client_info* src_client, client_info* dst_client); + + void handle_del_lan2lan_connection(ipacm_event_connection* data); + + bool remove_connection(client_info* src_client, client_info* dst_client); + + void erase_offload_link(ipa_ip_type iptype, client_info* src_client, client_info* dst_client); + + void generate_new_connection(ipa_ip_type iptype, client_info* client); + + bool is_lan2lan_connection(ipacm_event_connection* data); + + bool is_potential_lan2lan_connection(ipacm_event_connection* new_conn); + + void cache_new_connection(ipacm_event_connection* new_conn); + + void remove_cache_connection(ipacm_event_connection* del_conn); + + void check_cache_connection(ipa_ip_type iptype, client_info* client); + +}; + +#endif diff --git a/data-ipa-cfg-mgr/ipacm/inc/IPACM_Listener.h b/data-ipa-cfg-mgr/ipacm/inc/IPACM_Listener.h new file mode 100644 index 000000000..9d774feb4 --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/inc/IPACM_Listener.h @@ -0,0 +1,54 @@ +/* +Copyright (c) 2013, The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +/*! + @file + IPACM_Listener.h + + @brief + This file implements the abstract class notifier. + + @Author + Skylar Chang + +*/ +#ifndef IPACM_LISTENER_H +#define IPACM_LISTENER_H + +#include "IPACM_Defs.h" +#include "IPACM_CmdQueue.h" + +/* abstract class notifier */ +class IPACM_Listener +{ +public: + virtual void event_callback(ipa_cm_event_id event, void *data) = 0; + virtual ~IPACM_Listener(void) {}; +}; + +#endif /* IPACM_LISTENER_H */ diff --git a/data-ipa-cfg-mgr/ipacm/inc/IPACM_Log.h b/data-ipa-cfg-mgr/ipacm/inc/IPACM_Log.h new file mode 100644 index 000000000..8fce44e51 --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/inc/IPACM_Log.h @@ -0,0 +1,100 @@ +/* +Copyright (c) 2013, The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +/*! + @file + IPACM_log.h + + @brief + This file implements the IPAM log functionality. + + @Author + Skylar Chang + +*/ + +#ifndef IPACM_LOG_H +#define IPACM_LOG_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include +#include +#include + +#define MAX_BUF_LEN 256 + +#ifdef FEATURE_IPA_ANDROID +#define IPACMLOG_FILE "/dev/socket/ipacm_log_file" +#else/* defined(FEATURE_IPA_ANDROID) */ +#define IPACMLOG_FILE "/etc/ipacm_log_file" +#endif /* defined(NOT FEATURE_IPA_ANDROID)*/ + +typedef struct ipacm_log_buffer_s { + char user_data[MAX_BUF_LEN]; +} ipacm_log_buffer_t; + +void ipacm_log_send( void * user_data); + +static char buffer_send[MAX_BUF_LEN]; +static char dmesg_cmd[MAX_BUF_LEN]; + +#define IPACMDBG_DMESG(fmt, ...) memset(buffer_send, 0, MAX_BUF_LEN);\ + snprintf(buffer_send,MAX_BUF_LEN,"%s:%d %s: " fmt, __FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__);\ + memset(dmesg_cmd, 0, MAX_BUF_LEN);\ + snprintf(dmesg_cmd, MAX_BUF_LEN, "echo %s > /dev/kmsg", buffer_send);\ + system(dmesg_cmd); +#ifdef DEBUG +#define PERROR(fmt) memset(buffer_send, 0, MAX_BUF_LEN);\ + snprintf(buffer_send,MAX_BUF_LEN,"%s:%d %s()", __FILE__, __LINE__, __FUNCTION__);\ + ipacm_log_send (buffer_send); \ + perror(fmt); +#define IPACMERR(fmt, ...) memset(buffer_send, 0, MAX_BUF_LEN);\ + snprintf(buffer_send,MAX_BUF_LEN,"ERR: %s:%d %s() " fmt, __FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__);\ + ipacm_log_send (buffer_send);\ + printf("ERR: %s:%d %s() " fmt, __FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__); +#define IPACMDBG_H(fmt, ...) memset(buffer_send, 0, MAX_BUF_LEN);\ + snprintf(buffer_send,MAX_BUF_LEN,"%s:%d %s() " fmt, __FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__);\ + ipacm_log_send (buffer_send);\ + printf("%s:%d %s() " fmt, __FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__); +#else +#define PERROR(fmt) perror(fmt) +#define IPACMERR(fmt, ...) printf("ERR: %s:%d %s() " fmt, __FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__); +#define IPACMDBG_H(fmt, ...) printf("%s:%d %s() " fmt, __FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__); +#endif +#define IPACMDBG(fmt, ...) printf("%s:%d %s() " fmt, __FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__); +#define IPACMLOG(fmt, ...) printf(fmt, ##__VA_ARGS__); + +#ifdef __cplusplus +} +#endif + +#endif /* IPACM_LOG_H */ diff --git a/data-ipa-cfg-mgr/ipacm/inc/IPACM_Neighbor.h b/data-ipa-cfg-mgr/ipacm/inc/IPACM_Neighbor.h new file mode 100644 index 000000000..14e86e563 --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/inc/IPACM_Neighbor.h @@ -0,0 +1,81 @@ +/* +Copyright (c) 2013, The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +/*! + @file + IPACM_Neighbor.h + + @brief + This file implements the functionality of handling IPACM Neighbor events. + + @Author + Skylar Chang + +*/ +#ifndef IPACM_NEIGHBOR_H +#define IPACM_NEIGHBOR_H + +#include +#include +#include +#include "IPACM_Routing.h" +#include "IPACM_Filtering.h" +#include "IPACM_Listener.h" +#include "IPACM_Iface.h" + +#define IPA_MAX_NUM_NEIGHBOR_CLIENTS 100 + +struct ipa_neighbor_client +{ + uint8_t mac_addr[6]; + int iface_index; + uint32_t v4_addr; + int ipa_if_num; +}; + +class IPACM_Neighbor : public IPACM_Listener +{ + +public: + + IPACM_Neighbor(); + + void event_callback(ipa_cm_event_id event, + void *data); + +private: + + int num_neighbor_client; + + int circular_index; + + ipa_neighbor_client neighbor_client[IPA_MAX_NUM_NEIGHBOR_CLIENTS]; + +}; + +#endif /* IPACM_NEIGHBOR_H */ diff --git a/data-ipa-cfg-mgr/ipacm/inc/IPACM_Netlink.h b/data-ipa-cfg-mgr/ipacm/inc/IPACM_Netlink.h new file mode 100644 index 000000000..b0bdeb8e7 --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/inc/IPACM_Netlink.h @@ -0,0 +1,223 @@ +/* +Copyright (c) 2013, The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +/*! + @file + IPA_Netlink.h + + @brief + IPACM Netlink Messaging Implementation File + + @Author + Skylar Chang + +*/ +#ifndef IPACM_NETLINK_H +#define IPACM_NETLINK_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "IPACM_Defs.h" + +#define MAX_NUM_OF_FD 10 +#define IPA_NL_MSG_MAX_LEN (2048) + +/*--------------------------------------------------------------------------- + Type representing enumeration of NetLink event indication messages +---------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------- + Types representing parsed NetLink message +---------------------------------------------------------------------------*/ +#define IPA_NLA_PARAM_NONE (0x0000) +#define IPA_NLA_PARAM_PREFIXADDR (0x0001) +#define IPA_NLA_PARAM_LOCALADDR (0x0002) +#define IPA_NLA_PARAM_LABELNAME (0x0004) +#define IPA_NLA_PARAM_BCASTADDR (0x0008) +#define IPA_NLA_PARAM_ACASTADDR (0x0010) +#define IPA_NLA_PARAM_MCASTADDR (0x0020) +#define IPA_NLA_PARAM_CACHEINFO (0x0080) +#define IPA_NLA_PARAM_PROTOINFO (0x0100) +#define IPA_NLA_PARAM_FLAGS (0x0200) + +#define IPA_RTA_PARAM_NONE (0x0000) +#define IPA_RTA_PARAM_DST (0x0001) +#define IPA_RTA_PARAM_SRC (0x0002) +#define IPA_RTA_PARAM_GATEWAY (0x0004) +#define IPA_RTA_PARAM_IIF (0x0008) +#define IPA_RTA_PARAM_OIF (0x0010) +#define IPA_RTA_PARAM_CACHEINFO (0x0020) +#define IPA_RTA_PARAM_PRIORITY (0x0080) +#define IPA_RTA_PARAM_METRICS (0x0100) + + +/*--------------------------------------------------------------------------- + Type representing function callback registered with a socket listener + thread for reading from a socket on receipt of an incoming message +---------------------------------------------------------------------------*/ +typedef int (*ipa_sock_thrd_fd_read_f)(int fd); + +typedef enum +{ + IPA_INIT = 0, + IPA_LINK_UP_WAIT, + IPA_LINK_UP, + IPA_LINK_DOWN_WAIT, + IPA_LINK_DOWN +} ipa_nl_state_e; + +typedef struct +{ + int sk_fd; + ipa_sock_thrd_fd_read_f read_func; +} ipa_nl_sk_fd_map_info_t; + +typedef struct +{ + ipa_nl_sk_fd_map_info_t sk_fds[MAX_NUM_OF_FD]; + fd_set fdset; + int num_fd; + int max_fd; +} ipa_nl_sk_fd_set_info_t; + +typedef struct +{ + int sk_fd; /* socket descriptor */ + struct sockaddr_nl sk_addr_loc; /* local address of socket */ +} ipa_nl_sk_info_t; + +typedef struct ipa_nl_addr_s { + struct sockaddr_storage ip_addr; + unsigned int mask; +} ipa_nl_addr_t; + +typedef struct ipa_nl_proto_info_s { + unsigned int param_mask; + unsigned int flags; + struct ifla_cacheinfo cache_info; +} ipa_nl_proto_info_t; + +typedef struct +{ + struct ifinfomsg metainfo; /* from header */ +} ipa_nl_link_info_t; + + + +typedef struct ipa_nl_addr_info_s { + struct ifaddrmsg metainfo; /* from header */ + struct /* attributes */ + { + unsigned int param_mask; + unsigned char label_name[IF_NAME_LEN]; + struct sockaddr_storage prefix_addr; + struct sockaddr_storage local_addr; + struct sockaddr_storage bcast_addr; + struct sockaddr_storage acast_addr; + struct sockaddr_storage mcast_addr; + } attr_info; +} ipa_nl_addr_info_t; + + +typedef struct ipa_nl_neigh_info_s { + struct ndmsg metainfo; /* from header */ + struct /* attributes */ + { + unsigned int param_mask; + struct sockaddr_storage local_addr; + struct sockaddr lladdr_hwaddr; + } attr_info; +} ipa_nl_neigh_info_t; + + + +typedef struct ipa_nl_route_info_s { + struct rtmsg metainfo; /* from header */ + struct /* attributes */ + { + unsigned int param_mask; + struct sockaddr_storage dst_addr; + struct sockaddr_storage src_addr; + struct sockaddr_storage gateway_addr; + struct sockaddr_storage mark_addr; + struct rta_cacheinfo cache_info; + __u32 iif_index; /* Link index */ + __u32 oif_index; /* Link index */ + __u32 priority; + __u32 metrics; + ipa_nl_proto_info_t proto_info; + } attr_info; +} ipa_nl_route_info_t; + +#define IPA_FLOW_TYPE_INVALID (-1) + +typedef struct +{ + unsigned int type; + bool link_event; + /* Optional parameters */ + ipa_nl_link_info_t nl_link_info; + ipa_nl_addr_info_t nl_addr_info; + ipa_nl_neigh_info_t nl_neigh_info; + ipa_nl_route_info_t nl_route_info; +} ipa_nl_msg_t; + +/* Initialization routine for listener on NetLink sockets interface */ +int ipa_nl_listener_init +( + unsigned int nl_type, + unsigned int nl_groups, + ipa_nl_sk_fd_set_info_t *sk_fdset, + ipa_sock_thrd_fd_read_f read_f + ); + +/* Virtual function registered to receive incoming messages over the NETLINK routing socket*/ +int ipa_nl_recv_msg(int fd); + +/* map mask value for ipv6 */ +int mask_v6(int index, uint32_t *mask); + +#ifdef __cplusplus +} +#endif + +#endif /* IPACM_NETLINK_H */ diff --git a/data-ipa-cfg-mgr/ipacm/inc/IPACM_Routing.h b/data-ipa-cfg-mgr/ipacm/inc/IPACM_Routing.h new file mode 100644 index 000000000..4f5488f7e --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/inc/IPACM_Routing.h @@ -0,0 +1,77 @@ +/* +Copyright (c) 2013, The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +/*! + @file + IPACM_Routing.cpp + + @brief + This file implements the IPACM routing functionality. + + @Author + Skylar Chang + +*/ + + +#ifndef IPACM_ROUTING_H +#define IPACM_ROUTING_H + +#include +#include +#include + +using namespace std; + +class IPACM_Routing +{ +public: + IPACM_Routing(); + ~IPACM_Routing(); + + bool AddRoutingRule(struct ipa_ioc_add_rt_rule *ruleTable); + bool DeleteRoutingRule(struct ipa_ioc_del_rt_rule *ruleTable); + + bool Commit(enum ipa_ip_type ip); + bool Reset(enum ipa_ip_type ip); + + bool GetRoutingTable(struct ipa_ioc_get_rt_tbl *routingTable); + bool PutRoutingTable(uint32_t routingTableHandle); + + bool DeviceNodeIsOpened(); + bool DeleteRoutingHdl(uint32_t rt_rule_hdl, ipa_ip_type ip); + + bool ModifyRoutingRule(struct ipa_ioc_mdfy_rt_rule *); + +private: + static const char *DEVICE_NAME; + int m_fd; /* File descriptor of the IPA device node /dev/ipa */ +}; + +#endif //IPACM_ROUTING_H + diff --git a/data-ipa-cfg-mgr/ipacm/inc/IPACM_Wan.h b/data-ipa-cfg-mgr/ipacm/inc/IPACM_Wan.h new file mode 100644 index 000000000..711f2769a --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/inc/IPACM_Wan.h @@ -0,0 +1,488 @@ +/* +Copyright (c) 2013, The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +/*! + @file + IPACM_Wan.cpp + + @brief + This file implements the WAN iface functionality. + + @Author + Skylar Chang + +*/ +#ifndef IPACM_WAN_H +#define IPACM_WAN_H + +#include +#include +#include +#include "IPACM_Routing.h" +#include "IPACM_Filtering.h" +#include +#include +#include + +#define IPA_NUM_DEFAULT_WAN_FILTER_RULES 3 /*1 for v4, 2 for v6*/ +#define IPA_V2_NUM_DEFAULT_WAN_FILTER_RULE_IPV4 2 + +#ifdef FEATURE_IPA_ANDROID +#define IPA_V2_NUM_DEFAULT_WAN_FILTER_RULE_IPV6 6 +#else +#define IPA_V2_NUM_DEFAULT_WAN_FILTER_RULE_IPV6 3 +#endif + +#define NETWORK_STATS "%s %lu %lu %lu %lu" +#define IPA_NETWORK_STATS_FILE_NAME "/data/misc/ipa/network_stats" + +typedef struct _wan_client_rt_hdl +{ + uint32_t wan_rt_rule_hdl_v4; + uint32_t wan_rt_rule_hdl_v6[IPV6_NUM_ADDR]; + uint32_t wan_rt_rule_hdl_v6_wan[IPV6_NUM_ADDR]; +}wan_client_rt_hdl; + +typedef struct _ipa_wan_client +{ + ipacm_event_data_wlan_ex* p_hdr_info; + uint8_t mac[IPA_MAC_ADDR_SIZE]; + uint32_t v4_addr; + uint32_t v6_addr[IPV6_NUM_ADDR][4]; + uint32_t hdr_hdl_v4; + uint32_t hdr_hdl_v6; + bool route_rule_set_v4; + int route_rule_set_v6; + bool ipv4_set; + int ipv6_set; + bool ipv4_header_set; + bool ipv6_header_set; + bool power_save_set; + wan_client_rt_hdl wan_rt_hdl[0]; /* depends on number of tx properties */ +}ipa_wan_client; + +/* wan iface */ +class IPACM_Wan : public IPACM_Iface +{ + +public: + + static bool wan_up; + static bool wan_up_v6; + static uint8_t xlat_mux_id; + /* IPACM interface name */ + static char wan_up_dev_name[IF_NAME_LEN]; + IPACM_Wan(int, ipacm_wan_iface_type, uint8_t *); + virtual ~IPACM_Wan(); + + static bool isWanUP(int ipa_if_num_tether) + { +#ifdef FEATURE_IPA_ANDROID + int i; + for (i=0; i < ipa_if_num_tether_v4_total;i++) + { + if (ipa_if_num_tether_v4[i] == ipa_if_num_tether) + { + IPACMDBG_H("support ipv4 tether_iface(%s)\n", + IPACM_Iface::ipacmcfg->iface_table[ipa_if_num_tether].iface_name); + return wan_up; + break; + } + } + return false; +#else + return wan_up; +#endif + } + + static bool isWanUP_V6(int ipa_if_num_tether) + { +#ifdef FEATURE_IPA_ANDROID + int i; + for (i=0; i < ipa_if_num_tether_v6_total;i++) + { + if (ipa_if_num_tether_v6[i] == ipa_if_num_tether) + { + IPACMDBG_H("support ipv6 tether_iface(%s)\n", + IPACM_Iface::ipacmcfg->iface_table[ipa_if_num_tether].iface_name); + return wan_up_v6; + break; + } + } + return false; +#else + return wan_up_v6; +#endif + } + + static bool getXlat_Mux_Id() + { + return xlat_mux_id; + } + + void event_callback(ipa_cm_event_id event, + void *data); + + static struct ipa_flt_rule_add flt_rule_v4[IPA_MAX_FLT_RULE]; + static struct ipa_flt_rule_add flt_rule_v6[IPA_MAX_FLT_RULE]; + + static int num_v4_flt_rule; + static int num_v6_flt_rule; + + ipacm_wan_iface_type m_is_sta_mode; + static bool backhaul_is_sta_mode; + static bool is_ext_prop_set; + static uint32_t backhaul_ipv6_prefix[2]; + + static bool embms_is_on; + static bool backhaul_is_wan_bridge; + + static bool isWan_Bridge_Mode() + { + return backhaul_is_wan_bridge; + } +#ifdef FEATURE_IPA_ANDROID + /* IPACM interface id */ + static int ipa_if_num_tether_v4_total; + static int ipa_if_num_tether_v4[IPA_MAX_IFACE_ENTRIES]; + static int ipa_if_num_tether_v6_total; + static int ipa_if_num_tether_v6[IPA_MAX_IFACE_ENTRIES]; +#endif + +private: + + uint32_t ipv6_frag_firewall_flt_rule_hdl; + uint32_t *wan_route_rule_v4_hdl; + uint32_t *wan_route_rule_v6_hdl; + uint32_t *wan_route_rule_v6_hdl_a5; + uint32_t hdr_hdl_sta_v4; + uint32_t hdr_hdl_sta_v6; + uint32_t firewall_hdl_v4[IPACM_MAX_FIREWALL_ENTRIES]; + uint32_t firewall_hdl_v6[IPACM_MAX_FIREWALL_ENTRIES]; + uint32_t dft_wan_fl_hdl[IPA_NUM_DEFAULT_WAN_FILTER_RULES]; + uint32_t ipv6_dest_flt_rule_hdl[MAX_DEFAULT_v6_ROUTE_RULES]; + int num_ipv6_dest_flt_rule; + uint32_t ODU_fl_hdl[IPA_NUM_DEFAULT_WAN_FILTER_RULES]; + int num_firewall_v4,num_firewall_v6; + uint32_t wan_v4_addr; + uint32_t wan_v4_addr_gw; + uint32_t wan_v6_addr_gw[4]; + bool wan_v4_addr_set; + bool wan_v4_addr_gw_set; + bool wan_v6_addr_gw_set; + bool active_v4; + bool active_v6; + bool header_set_v4; + bool header_set_v6; + bool header_partial_default_wan_v4; + bool header_partial_default_wan_v6; + uint8_t ext_router_mac_addr[IPA_MAC_ADDR_SIZE]; + + static int num_ipv4_modem_pdn; + + static int num_ipv6_modem_pdn; + + int modem_ipv4_pdn_index; + + int modem_ipv6_pdn_index; + + bool is_default_gateway; + + uint32_t ipv6_prefix[2]; + + /* IPACM firewall Configuration file*/ + IPACM_firewall_conf_t firewall_config; + + /* STA mode wan-client*/ + int wan_client_len; + ipa_wan_client *wan_client; + int header_name_count; + int num_wan_client; + uint8_t invalid_mac[IPA_MAC_ADDR_SIZE]; + bool is_xlat; + + /* update network stats for CNE */ + int ipa_network_stats_fd; + + inline ipa_wan_client* get_client_memptr(ipa_wan_client *param, int cnt) + { + char *ret = ((char *)param) + (wan_client_len * cnt); + return (ipa_wan_client *)ret; + } + + inline int get_wan_client_index(uint8_t *mac_addr) + { + int cnt; + int num_wan_client_tmp = num_wan_client; + + IPACMDBG_H("Passed MAC %02x:%02x:%02x:%02x:%02x:%02x\n", + mac_addr[0], mac_addr[1], mac_addr[2], + mac_addr[3], mac_addr[4], mac_addr[5]); + + for(cnt = 0; cnt < num_wan_client_tmp; cnt++) + { + IPACMDBG_H("stored MAC %02x:%02x:%02x:%02x:%02x:%02x\n", + get_client_memptr(wan_client, cnt)->mac[0], + get_client_memptr(wan_client, cnt)->mac[1], + get_client_memptr(wan_client, cnt)->mac[2], + get_client_memptr(wan_client, cnt)->mac[3], + get_client_memptr(wan_client, cnt)->mac[4], + get_client_memptr(wan_client, cnt)->mac[5]); + + if(memcmp(get_client_memptr(wan_client, cnt)->mac, + mac_addr, + sizeof(get_client_memptr(wan_client, cnt)->mac)) == 0) + { + IPACMDBG_H("Matched client index: %d\n", cnt); + return cnt; + } + } + + return IPACM_INVALID_INDEX; + } + + inline int get_wan_client_index_ipv4(uint32_t ipv4_addr) + { + int cnt; + int num_wan_client_tmp = num_wan_client; + + IPACMDBG_H("Passed IPv4 %x\n", ipv4_addr); + + for(cnt = 0; cnt < num_wan_client_tmp; cnt++) + { + if (get_client_memptr(wan_client, cnt)->ipv4_set) + { + IPACMDBG_H("stored IPv4 %x\n", get_client_memptr(wan_client, cnt)->v4_addr); + + if(ipv4_addr == get_client_memptr(wan_client, cnt)->v4_addr) + { + IPACMDBG_H("Matched client index: %d\n", cnt); + IPACMDBG_H("The MAC is %02x:%02x:%02x:%02x:%02x:%02x\n", + get_client_memptr(wan_client, cnt)->mac[0], + get_client_memptr(wan_client, cnt)->mac[1], + get_client_memptr(wan_client, cnt)->mac[2], + get_client_memptr(wan_client, cnt)->mac[3], + get_client_memptr(wan_client, cnt)->mac[4], + get_client_memptr(wan_client, cnt)->mac[5]); + IPACMDBG_H("header set ipv4(%d) ipv6(%d)\n", + get_client_memptr(wan_client, cnt)->ipv4_header_set, + get_client_memptr(wan_client, cnt)->ipv6_header_set); + return cnt; + } + } + } + return IPACM_INVALID_INDEX; + } + + inline int get_wan_client_index_ipv6(uint32_t* ipv6_addr) + { + int cnt, v6_num; + int num_wan_client_tmp = num_wan_client; + + IPACMDBG_H("Get ipv6 address 0x%08x.0x%08x.0x%08x.0x%08x\n", ipv6_addr[0], ipv6_addr[1], ipv6_addr[2], ipv6_addr[3]); + + for(cnt = 0; cnt < num_wan_client_tmp; cnt++) + { + if (get_client_memptr(wan_client, cnt)->ipv6_set) + { + for(v6_num=0;v6_num < get_client_memptr(wan_client, cnt)->ipv6_set;v6_num++) + { + + IPACMDBG_H("stored IPv6 0x%08x.0x%08x.0x%08x.0x%08x\n", get_client_memptr(wan_client, cnt)->v6_addr[v6_num][0], + get_client_memptr(wan_client, cnt)->v6_addr[v6_num][1], + get_client_memptr(wan_client, cnt)->v6_addr[v6_num][2], + get_client_memptr(wan_client, cnt)->v6_addr[v6_num][3]); + + if(ipv6_addr[0] == get_client_memptr(wan_client, cnt)->v6_addr[v6_num][0] && + ipv6_addr[1] == get_client_memptr(wan_client, cnt)->v6_addr[v6_num][1] && + ipv6_addr[2]== get_client_memptr(wan_client, cnt)->v6_addr[v6_num][2] && + ipv6_addr[3] == get_client_memptr(wan_client, cnt)->v6_addr[v6_num][3]) + { + IPACMDBG_H("Matched client index: %d\n", cnt); + IPACMDBG_H("The MAC is %02x:%02x:%02x:%02x:%02x:%02x\n", + get_client_memptr(wan_client, cnt)->mac[0], + get_client_memptr(wan_client, cnt)->mac[1], + get_client_memptr(wan_client, cnt)->mac[2], + get_client_memptr(wan_client, cnt)->mac[3], + get_client_memptr(wan_client, cnt)->mac[4], + get_client_memptr(wan_client, cnt)->mac[5]); + IPACMDBG_H("header set ipv4(%d) ipv6(%d)\n", + get_client_memptr(wan_client, cnt)->ipv4_header_set, + get_client_memptr(wan_client, cnt)->ipv6_header_set); + return cnt; + } + } + } + } + return IPACM_INVALID_INDEX; + } + + inline int delete_wan_rtrules(int clt_indx, ipa_ip_type iptype) + { + uint32_t tx_index; + uint32_t rt_hdl; + int num_v6; + + if(iptype == IPA_IP_v4) + { + for(tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++) + { + if((tx_prop->tx[tx_index].ip == IPA_IP_v4) && (get_client_memptr(wan_client, clt_indx)->route_rule_set_v4==true)) /* for ipv4 */ + { + IPACMDBG_H("Delete client index %d ipv4 Qos rules for tx:%d \n",clt_indx,tx_index); + rt_hdl = get_client_memptr(wan_client, clt_indx)->wan_rt_hdl[tx_index].wan_rt_rule_hdl_v4; + + if(m_routing.DeleteRoutingHdl(rt_hdl, IPA_IP_v4) == false) + { + return IPACM_FAILURE; + } + } + } /* end of for loop */ + + /* clean the 4 Qos ipv4 RT rules for client:clt_indx */ + if(get_client_memptr(wan_client, clt_indx)->route_rule_set_v4==true) /* for ipv4 */ + { + get_client_memptr(wan_client, clt_indx)->route_rule_set_v4 = false; + } + } + + if(iptype == IPA_IP_v6) + { + for(tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++) + { + + if((tx_prop->tx[tx_index].ip == IPA_IP_v6) && (get_client_memptr(wan_client, clt_indx)->route_rule_set_v6 != 0)) /* for ipv6 */ + { + for(num_v6 =0;num_v6 < get_client_memptr(wan_client, clt_indx)->route_rule_set_v6;num_v6++) + { + IPACMDBG_H("Delete client index %d ipv6 Qos rules for %d-st ipv6 for tx:%d\n", clt_indx,num_v6,tx_index); + rt_hdl = get_client_memptr(wan_client, clt_indx)->wan_rt_hdl[tx_index].wan_rt_rule_hdl_v6[num_v6]; + if(m_routing.DeleteRoutingHdl(rt_hdl, IPA_IP_v6) == false) + { + return IPACM_FAILURE; + } + + rt_hdl = get_client_memptr(wan_client, clt_indx)->wan_rt_hdl[tx_index].wan_rt_rule_hdl_v6_wan[num_v6]; + if(m_routing.DeleteRoutingHdl(rt_hdl, IPA_IP_v6) == false) + { + return IPACM_FAILURE; + } + } + + } + } /* end of for loop */ + + /* clean the 4 Qos ipv6 RT rules for client:clt_indx */ + if(get_client_memptr(wan_client, clt_indx)->route_rule_set_v6 != 0) /* for ipv6 */ + { + get_client_memptr(wan_client, clt_indx)->route_rule_set_v6 = 0; + } + } + + return IPACM_SUCCESS; + } + + int handle_wan_hdr_init(uint8_t *mac_addr); + int handle_wan_client_ipaddr(ipacm_event_data_all *data); + int handle_wan_client_route_rule(uint8_t *mac_addr, ipa_ip_type iptype); + + /* handle new_address event */ + int handle_addr_evt(ipacm_event_data_addr *data); + + /* wan default route/filter rule configuration */ + int handle_route_add_evt(ipa_ip_type iptype); + + /* construct complete STA ethernet header */ + int handle_sta_header_add_evt(); + + bool check_dft_firewall_rules_attr_mask(IPACM_firewall_conf_t *firewall_config); + +#ifdef FEATURE_IPA_ANDROID + /* wan posting supported tether_iface */ + int post_wan_up_tether_evt(ipa_ip_type iptype, int ipa_if_num_tether); + + int post_wan_down_tether_evt(ipa_ip_type iptype, int ipa_if_num_tether); +#endif + int config_dft_firewall_rules(ipa_ip_type iptype); + + /* configure the initial firewall filter rules */ + int config_dft_embms_rules(ipa_ioc_add_flt_rule *pFilteringTable_v4, ipa_ioc_add_flt_rule *pFilteringTable_v6); + + int handle_route_del_evt(ipa_ip_type iptype); + + int del_dft_firewall_rules(ipa_ip_type iptype); + + int handle_down_evt(); + + /*handle wan-iface down event */ + int handle_down_evt_ex(); + + /* wan default route/filter rule delete */ + int handle_route_del_evt_ex(ipa_ip_type iptype); + + /* configure the initial firewall filter rules */ + int config_dft_firewall_rules_ex(struct ipa_flt_rule_add* rules, int rule_offset, + ipa_ip_type iptype); + + /* Change IP Type.*/ + void config_ip_type(ipa_ip_type iptype); + + /* init filtering rule in wan dl filtering table */ + int init_fl_rule_ex(ipa_ip_type iptype); + + /* add ICMP and ALG rules in wan dl filtering table */ + int add_icmp_alg_rules(struct ipa_flt_rule_add* rules, int rule_offset, ipa_ip_type iptype); + + /* query extended property */ + int query_ext_prop(); + + ipa_ioc_query_intf_ext_props *ext_prop; + + int config_wan_firewall_rule(ipa_ip_type iptype); + + int del_wan_firewall_rule(ipa_ip_type iptype); + + int add_dft_filtering_rule(struct ipa_flt_rule_add* rules, int rule_offset, ipa_ip_type iptype); + + int install_wan_filtering_rule(bool is_sw_routing); + + void change_to_network_order(ipa_ip_type iptype, ipa_rule_attrib* attrib); + + bool is_global_ipv6_addr(uint32_t* ipv6_addr); + + void handle_wlan_SCC_MCC_switch(bool, ipa_ip_type); + void handle_wan_client_SCC_MCC_switch(bool, ipa_ip_type); + + int handle_network_stats_evt(); + + int m_fd_ipa; + + int handle_network_stats_update(ipa_get_apn_data_stats_resp_msg_v01 *data); +}; + +#endif /* IPACM_WAN_H */ diff --git a/data-ipa-cfg-mgr/ipacm/inc/IPACM_Wlan.h b/data-ipa-cfg-mgr/ipacm/inc/IPACM_Wlan.h new file mode 100644 index 000000000..6a2d53a11 --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/inc/IPACM_Wlan.h @@ -0,0 +1,329 @@ +/* +Copyright (c) 2013, The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +/*! + @file + IPACM_Wlan.h + + @brief + This file implements the WLAN iface functionality. + + @Author + Skylar Chang + +*/ +#ifndef IPACM_WLAN_H +#define IPACM_WLAN_H + +#include +#include +#include +#include "IPACM_Routing.h" +#include "IPACM_Filtering.h" +#include "IPACM_Lan.h" +#include "IPACM_Iface.h" +#include "IPACM_Conntrack_NATApp.h" + +typedef struct _wlan_client_rt_hdl +{ + uint32_t wifi_rt_rule_hdl_v4; + uint32_t wifi_rt_rule_hdl_v6[IPV6_NUM_ADDR]; + uint32_t wifi_rt_rule_hdl_v6_wan[IPV6_NUM_ADDR]; +}wlan_client_rt_hdl; + +typedef struct _ipa_wlan_client +{ + ipacm_event_data_wlan_ex* p_hdr_info; + uint8_t mac[IPA_MAC_ADDR_SIZE]; + uint32_t v4_addr; + uint32_t v6_addr[IPV6_NUM_ADDR][4]; + uint32_t hdr_hdl_v4; + uint32_t hdr_hdl_v6; + bool route_rule_set_v4; + int route_rule_set_v6; + bool ipv4_set; + int ipv6_set; + bool ipv4_header_set; + bool ipv6_header_set; + bool power_save_set; + wlan_client_rt_hdl wifi_rt_hdl[0]; /* depends on number of tx properties */ +}ipa_wlan_client; + +/* wlan iface */ +class IPACM_Wlan : public IPACM_Lan +{ + +public: + + IPACM_Wlan(int iface_index); + virtual ~IPACM_Wlan(void); + + static int total_num_wifi_clients; + + void event_callback(ipa_cm_event_id event, + void *data); + + virtual int add_lan2lan_hdr(ipa_ip_type iptype, uint8_t* src_mac, uint8_t* dst_mac, uint32_t* hdr_hdl); + +private: + + eth_bridge_client_flt_info eth_bridge_lan_client_flt_info[IPA_LAN_TO_LAN_MAX_LAN_CLIENT]; + int lan_client_flt_info_count; + + static lan2lan_flt_rule_hdl self_client_flt_rule_hdl_v4[IPA_LAN_TO_LAN_MAX_WLAN_CLIENT]; + static lan2lan_flt_rule_hdl self_client_flt_rule_hdl_v6[IPA_LAN_TO_LAN_MAX_WLAN_CLIENT]; + + static lan2lan_flt_rule_hdl lan_client_flt_rule_hdl_v4[IPA_LAN_TO_LAN_MAX_LAN_CLIENT]; + static lan2lan_flt_rule_hdl lan_client_flt_rule_hdl_v6[IPA_LAN_TO_LAN_MAX_LAN_CLIENT]; + + bool is_guest_ap; + + eth_bridge_client_rt_info* eth_bridge_wlan_client_rt_from_lan_info_v4; + int wlan_client_rt_from_lan_info_count_v4; + eth_bridge_client_rt_info* eth_bridge_wlan_client_rt_from_lan_info_v6; + int wlan_client_rt_from_lan_info_count_v6; + + eth_bridge_client_rt_info* eth_bridge_wlan_client_rt_from_wlan_info_v4; + int wlan_client_rt_from_wlan_info_count_v4; + eth_bridge_client_rt_info* eth_bridge_wlan_client_rt_from_wlan_info_v6; + int wlan_client_rt_from_wlan_info_count_v6; + + int eth_bridge_install_wlan_guest_ap_ipv6_flt_rule(); + + virtual int eth_bridge_handle_dummy_wlan_client_flt_rule(ipa_ip_type iptype); + + virtual int eth_bridge_handle_dummy_lan_client_flt_rule(ipa_ip_type iptype); + + int eth_bridge_add_lan_client_flt_rule(uint8_t* mac, ipa_ip_type iptype); + + int eth_bridge_del_lan_client_flt_rule(uint8_t* mac); + + int eth_bridge_add_self_client_flt_rule(uint8_t* mac, ipa_ip_type iptype); + + int eth_bridge_del_self_client_flt_rule(uint8_t* mac); + + virtual int eth_bridge_install_cache_wlan_client_flt_rule(ipa_ip_type iptype); + + virtual int eth_bridge_install_cache_lan_client_flt_rule(ipa_ip_type iptype); + + int eth_bridge_add_wlan_client_rt_rule(uint8_t* mac, eth_bridge_src_iface src, ipa_ip_type iptype); + + int eth_bridge_del_wlan_client_rt_rule(uint8_t* mac, eth_bridge_src_iface src); + + eth_bridge_client_rt_info* eth_bridge_get_client_rt_info_ptr(uint8_t index, eth_bridge_src_iface src, ipa_ip_type iptype); + + void eth_bridge_add_wlan_client(uint8_t* mac, int if_num); + + void eth_bridge_del_wlan_client(uint8_t* mac); + + + int wlan_client_len; + ipa_wlan_client *wlan_client; + + int header_name_count; + int num_wifi_client; + + int wlan_ap_index; + + static uint32_t* dummy_flt_rule_hdl_v4; + static uint32_t* dummy_flt_rule_hdl_v6; + + static int num_wlan_ap_iface; + + NatApp *Nat_App; + + inline ipa_wlan_client* get_client_memptr(ipa_wlan_client *param, int cnt) + { + char *ret = ((char *)param) + (wlan_client_len * cnt); + return (ipa_wlan_client *)ret; + } + + inline int get_wlan_client_index(uint8_t *mac_addr) + { + int cnt; + int num_wifi_client_tmp = num_wifi_client; + + IPACMDBG_H("Passed MAC %02x:%02x:%02x:%02x:%02x:%02x\n", + mac_addr[0], mac_addr[1], mac_addr[2], + mac_addr[3], mac_addr[4], mac_addr[5]); + + for(cnt = 0; cnt < num_wifi_client_tmp; cnt++) + { + IPACMDBG_H("stored MAC %02x:%02x:%02x:%02x:%02x:%02x\n", + get_client_memptr(wlan_client, cnt)->mac[0], + get_client_memptr(wlan_client, cnt)->mac[1], + get_client_memptr(wlan_client, cnt)->mac[2], + get_client_memptr(wlan_client, cnt)->mac[3], + get_client_memptr(wlan_client, cnt)->mac[4], + get_client_memptr(wlan_client, cnt)->mac[5]); + + if(memcmp(get_client_memptr(wlan_client, cnt)->mac, + mac_addr, + sizeof(get_client_memptr(wlan_client, cnt)->mac)) == 0) + { + IPACMDBG_H("Matched client index: %d\n", cnt); + return cnt; + } + } + + return IPACM_INVALID_INDEX; + } + + inline int delete_default_qos_rtrules(int clt_indx, ipa_ip_type iptype) + { + uint32_t tx_index; + uint32_t rt_hdl; + int num_v6; + + if(iptype == IPA_IP_v4) + { + for(tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++) + { + if((tx_prop->tx[tx_index].ip == IPA_IP_v4) && (get_client_memptr(wlan_client, clt_indx)->route_rule_set_v4==true)) /* for ipv4 */ + { + IPACMDBG_H("Delete client index %d ipv4 Qos rules for tx:%d \n",clt_indx,tx_index); + rt_hdl = get_client_memptr(wlan_client, clt_indx)->wifi_rt_hdl[tx_index].wifi_rt_rule_hdl_v4; + + if(m_routing.DeleteRoutingHdl(rt_hdl, IPA_IP_v4) == false) + { + return IPACM_FAILURE; + } + } + } /* end of for loop */ + + /* clean the 4 Qos ipv4 RT rules for client:clt_indx */ + if(get_client_memptr(wlan_client, clt_indx)->route_rule_set_v4==true) /* for ipv4 */ + { + get_client_memptr(wlan_client, clt_indx)->route_rule_set_v4 = false; + } + } + + if(iptype == IPA_IP_v6) + { + for(tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++) + { + + if((tx_prop->tx[tx_index].ip == IPA_IP_v6) && (get_client_memptr(wlan_client, clt_indx)->route_rule_set_v6 != 0)) /* for ipv6 */ + { + for(num_v6 =0;num_v6 < get_client_memptr(wlan_client, clt_indx)->route_rule_set_v6;num_v6++) + { + IPACMDBG_H("Delete client index %d ipv6 Qos rules for %d-st ipv6 for tx:%d\n", clt_indx,num_v6,tx_index); + rt_hdl = get_client_memptr(wlan_client, clt_indx)->wifi_rt_hdl[tx_index].wifi_rt_rule_hdl_v6[num_v6]; + if(m_routing.DeleteRoutingHdl(rt_hdl, IPA_IP_v6) == false) + { + return IPACM_FAILURE; + } + + rt_hdl = get_client_memptr(wlan_client, clt_indx)->wifi_rt_hdl[tx_index].wifi_rt_rule_hdl_v6_wan[num_v6]; + if(m_routing.DeleteRoutingHdl(rt_hdl, IPA_IP_v6) == false) + { + return IPACM_FAILURE; + } + } + + } + } /* end of for loop */ + + /* clean the 4 Qos ipv6 RT rules for client:clt_indx */ + if(get_client_memptr(wlan_client, clt_indx)->route_rule_set_v6 != 0) /* for ipv6 */ + { + get_client_memptr(wlan_client, clt_indx)->route_rule_set_v6 = 0; + } + } + + return IPACM_SUCCESS; + } + + /* for handle wifi client initial,copy all partial headers (tx property) */ + int handle_wlan_client_init_ex(ipacm_event_data_wlan_ex *data); + + /*handle lan2lan internal mesg posting*/ + int handle_lan2lan_msg_post(uint8_t *mac_addr, ipa_cm_event_id event, ipa_ip_type iptype); + + /*handle wifi client */ + int handle_wlan_client_ipaddr(ipacm_event_data_all *data); + + /*handle wifi client routing rule*/ + int handle_wlan_client_route_rule(uint8_t *mac_addr, ipa_ip_type iptype); + + /*handle wifi client power-save mode*/ + int handle_wlan_client_pwrsave(uint8_t *mac_addr); + + /*handle wifi client del mode*/ + int handle_wlan_client_down_evt(uint8_t *mac_addr); + + /*handle wlan iface down event*/ + int handle_down_evt(); + + /* add dummy filtering rules for WLAN AP-AP mode support */ + void add_dummy_flt_rule(); + + /* install dummy filtering rules for WLAN AP-AP mode support */ + int install_dummy_flt_rule(ipa_ip_type iptype, int num_rule); + + /* delete dummy flt rule for WLAN AP-AP mode support*/ + void del_dummy_flt_rule(); + + /*Configure the initial filter rules */ + virtual int init_fl_rule(ipa_ip_type iptype); + + virtual int add_dummy_lan2lan_flt_rule(ipa_ip_type iptype); + + virtual int add_dummy_private_subnet_flt_rule(ipa_ip_type iptype); + + /*configure private subnet filter rules*/ + virtual int handle_private_subnet(ipa_ip_type iptype); + + /* install UL filter rule from Q6 */ + virtual int handle_uplink_filter_rule(ipacm_ext_prop* prop, ipa_ip_type iptype, uint8_t xlat_mux_id); + + /* install TCP control filter rules */ + virtual void install_tcp_ctl_flt_rule(ipa_ip_type iptype); + + /*handle reset wifi-client rt-rules */ + int handle_wlan_client_reset_rt(ipa_ip_type iptype); + + void handle_SCC_MCC_switch(ipa_ip_type); + + void eth_bridge_handle_wlan_SCC_MCC_switch(ipa_ip_type iptype); + + int eth_bridge_modify_wlan_client_flt_rule(uint8_t* mac, eth_bridge_dst_iface dst_iface, ipa_ip_type iptype); + + int eth_bridge_modify_wlan_rt_rule(uint8_t* mac, eth_bridge_src_iface src_iface, ipa_ip_type iptyp); + + /*handle wlan access mode switch */ + void eth_bridge_handle_wlan_mode_switch(); + + virtual int install_ipv6_prefix_flt_rule(uint32_t* prefix); + + virtual void delete_ipv6_prefix_flt_rule(); + +}; + + +#endif /* IPACM_WLAN_H */ diff --git a/data-ipa-cfg-mgr/ipacm/inc/IPACM_Xml.h b/data-ipa-cfg-mgr/ipacm/inc/IPACM_Xml.h new file mode 100644 index 000000000..f645ae17b --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/inc/IPACM_Xml.h @@ -0,0 +1,299 @@ +/* +Copyright (c) 2013, The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +/*! + @file + IPACM_Xml.h + + @brief + This file implements the XML specific parsing functionality. + + @Author + Skylar Chang/Shihuan Liu + +*/ +#ifndef IPACM_XML_H +#define IPACM_XML_H + +#include +#include "IPACM_Defs.h" +#include +#include +#include +#include +#include +#include +#include +#ifdef __cplusplus +extern "C" { +#endif + + +#define IPACM_ASSERT(a) \ +if (!(a)) { \ + fprintf(stderr, "%s, %d: assertion (a) failed!", \ + __FILE__, \ + __LINE__); \ + abort(); \ +} + +/* Max allowed size of the XML file (2 MB) */ +#define IPACM_XML_MAX_FILESIZE (2 << 20) +#define IPACM_MAX_FIREWALL_ENTRIES 50 +#define IPACM_IPV6_ADDR_LEN 16 + +/* Defines for clipping space or space & quotes (single, double) */ +#define IPACM_XML_CLIP_SPACE " " +#define IPACM_XML_CLIP_SPACE_QUOTES " '\"" + +#define MAX_XML_STR_LEN 120 + +/* IPA Config Entries */ +#define system_TAG "system" +#define ODU_TAG "ODUCFG" +#define ODUMODE_TAG "OduMode" +#define ODUEMBMS_OFFLOAD_TAG "eMBMS_offload" +#define ODU_ROUTER_TAG "router" +#define ODU_BRIDGE_TAG "bridge" +#define IPACMCFG_TAG "IPACM" +#define IPACMIFACECFG_TAG "IPACMIface" +#define IFACE_TAG "Iface" +#define NAME_TAG "Name" +#define CATEGORY_TAG "Category" +#define MODE_TAG "Mode" +#define IPACMPRIVATESUBNETCFG_TAG "IPACMPrivateSubnet" +#define SUBNET_TAG "Subnet" +#define SUBNETADDRESS_TAG "SubnetAddress" +#define SUBNETMASK_TAG "SubnetMask" +#define WANIF_TAG "WAN" +#define LANIF_TAG "LAN" +#define WLANIF_TAG "WLAN" +#define WLAN_FULL_MODE_TAG "full" +#define WLAN_INTERNET_MODE_TAG "internet" +#define WLAN_MODE_TAG "WlanMode" +#define VIRTUALIF_TAG "VIRTUAL" +#define UNKNOWNIF_TAG "UNKNOWN" +#define ODUIF_TAG "ODU" +#define EMBMSIF_TAG "EMBMS" +#define ETHIF_TAG "ETH" +#define IFACE_ROUTER_MODE_TAG "ROUTER" +#define IFACE_BRIDGE_MODE_TAG "BRIDGE" +#define IPACMALG_TAG "IPACMALG" +#define ALG_TAG "ALG" +#define Protocol_TAG "Protocol" +#define Port_TAG "Port" +#define TCP_PROTOCOL_TAG "TCP" +#define UDP_PROTOCOL_TAG "UDP" + +/* FIREWALL Config Entries */ +#define Firewall_TAG "Firewall" +#define MobileAPFirewallCfg_TAG "MobileAPFirewallCfg" +#define FirewallEnabled_TAG "FirewallEnabled" +#define FirewallPktsAllowed_TAG "FirewallPktsAllowed" + +#define IPFamily_TAG "IPFamily" +#define IPV4SourceAddress_TAG "IPV4SourceAddress" +#define IPV4SourceIPAddress_TAG "IPV4SourceIPAddress" +#define IPV4SourceSubnetMask_TAG "IPV4SourceSubnetMask" + +#define IPV4DestinationAddress_TAG "IPV4DestinationAddress" +#define IPV4DestinationIPAddress_TAG "IPV4DestinationIPAddress" +#define IPV4DestinationSubnetMask_TAG "IPV4DestinationSubnetMask" + +#define IPV4TypeOfService_TAG "IPV4TypeOfService" +#define TOSValue_TAG "TOSValue" +#define TOSMask_TAG "TOSMask" + +#define IPV4NextHeaderProtocol_TAG "IPV4NextHeaderProtocol" + +#define IPV6SourceAddress_TAG "IPV6SourceAddress" +#define IPV6SourceIPAddress_TAG "IPV6SourceIPAddress" +#define IPV6SourcePrefix_TAG "IPV6SourcePrefix" + +#define IPV6DestinationAddress_TAG "IPV6DestinationAddress" +#define IPV6DestinationIPAddress_TAG "IPV6DestinationIPAddress" +#define IPV6DestinationPrefix_TAG "IPV6DestinationPrefix" + +#define IPV6TrafficClass_TAG "IPV6TrafficClass" +#define TrfClsValue_TAG "TrfClsValue" +#define TrfClsMask_TAG "TrfClsMask" + +#define IPV6NextHeaderProtocol_TAG "IPV6NextHeaderProtocol" + +#define TCPSource_TAG "TCPSource" +#define TCPSourcePort_TAG "TCPSourcePort" +#define TCPSourceRange_TAG "TCPSourceRange" + +#define TCPDestination_TAG "TCPDestination" +#define TCPDestinationPort_TAG "TCPDestinationPort" +#define TCPDestinationRange_TAG "TCPDestinationRange" + +#define UDPSource_TAG "UDPSource" +#define UDPSourcePort_TAG "UDPSourcePort" +#define UDPSourceRange_TAG "UDPSourceRange" + +#define UDPDestination_TAG "UDPDestination" +#define UDPDestinationPort_TAG "UDPDestinationPort" +#define UDPDestinationRange_TAG "UDPDestinationRange" + +#define ICMPType_TAG "ICMPType" +#define ICMPCode_TAG "ICMPCode" + +#define ESP_TAG "ESP" +#define ESPSPI_TAG "ESPSPI" + +#define TCP_UDPSource_TAG "TCP_UDPSource" +#define TCP_UDPSourcePort_TAG "TCP_UDPSourcePort" +#define TCP_UDPSourceRange_TAG "TCP_UDPSourceRange" + +#define TCP_UDPDestination_TAG "TCP_UDPDestination" +#define TCP_UDPDestinationPort_TAG "TCP_UDPDestinationPort" +#define TCP_UDPDestinationRange_TAG "TCP_UDPDestinationRange" + +#define IPACMNat_TAG "IPACMNAT" +#define NAT_MaxEntries_TAG "MaxNatEntries" + +/*--------------------------------------------------------------------------- + IP protocol numbers - use in dss_socket() to identify protocols. + Also contains the extension header types for IPv6. +---------------------------------------------------------------------------*/ +typedef enum +{ + IPACM_FIREWALL_IPV6_BASE_HDR = 4, /* IPv6 Base Header */ + IPACM_FIREWALL_IPPROTO_HOP_BY_HOP_OPT_HDR = 0, /* Hop-by-hop Option Header */ + IPACM_FIREWALL_IPPROTO_ICMP = 1, /* ICMP protocol */ + IPACM_FIREWALL_IPPROTO_IGMP = 2, /* IGMP protocol */ + IPACM_FIREWALL_IPPROTO_IP = IPACM_FIREWALL_IPV6_BASE_HDR, /* IPv4 */ + IPACM_FIREWALL_IPPROTO_TCP = 6, /* TCP Protocol */ + IPACM_FIREWALL_IPPROTO_UDP = 17, /* UDP Protocol */ + IPACM_FIREWALL_IPPROTO_IPV6 = 41, /* IPv6 */ + IPACM_FIREWALL_IPPROTO_ROUTING_HDR = 43, /* Routing Header */ + IPACM_FIREWALL_IPPROTO_FRAG_HDR = 44, /* Fragmentation Header */ + IPACM_FIREWALL_IPPROTO_GRE = 47, /* GRE Protocol */ + IPACM_FIREWALL_IPPROTO_ESP = 50, /* ESP Protocol */ + IPACM_FIREWALL_IPPROTO_AH = 51, /* Authentication Header */ + IPACM_FIREWALL_IPPROTO_ICMP6 = 58, /* ICMPv6 */ + IPACM_FIREWALL_NO_NEXT_HDR = 59, /* No Next Header for IPv6 */ + IPACM_FIREWALL_IPPROTO_DEST_OPT_HDR = 60, /* Destination Options Header */ + IPACM_FIREWALL_IPPROTO_MOBILITY_HDR = 135, /* Mobility Header */ + IPACM_FIREWALL_IPPROTO_TCP_UDP = 253 /* Unspecified protocol used for IPACM */ +} ipacm_firewall_ip_protocol_enum_type; + +/* define as mobileap firewall rule format*/ +typedef enum +{ + IP_V4 = 4, + IP_V6 = 6 +} firewall_ip_version_enum; + +/*--------------------------------------------------------------------------- + Extended FireWall Entry Configuration. +---------------------------------------------------------------------------*/ +typedef struct +{ + struct ipa_rule_attrib attrib; + firewall_ip_version_enum ip_vsn; +} IPACM_extd_firewall_entry_conf_t; + + +/*--------------------------------------------------------------------------- + Extended FireWall configuration. +---------------------------------------------------------------------------*/ +typedef union +{ + IPACM_extd_firewall_entry_conf_t extd_firewall_entry; +} IPACM_extd_firewall_conf_t; + + +typedef struct +{ + char firewall_config_file[IPA_MAX_FILE_LEN]; + uint8_t num_extd_firewall_entries; + IPACM_extd_firewall_entry_conf_t extd_firewall_entries[IPACM_MAX_FIREWALL_ENTRIES]; + bool rule_action_accept; + bool firewall_enable; +} IPACM_firewall_conf_t; + + + +typedef struct +{ + uint8_t num_iface_entries; + ipa_ifi_dev_name_t iface_entries[IPA_MAX_IFACE_ENTRIES]; +} ipacm_iface_conf_t; + +typedef struct +{ + uint8_t num_subnet_entries; + ipa_private_subnet private_subnet_entries[IPA_MAX_PRIVATE_SUBNET_ENTRIES]; +} ipacm_private_subnet_conf_t; + +typedef struct +{ + uint8_t protocol; + uint16_t port; +} ipacm_alg; + +typedef struct +{ + uint8_t num_alg_entries; + ipacm_alg alg_entries[IPA_MAX_ALG_ENTRIES]; +} ipacm_alg_conf_t; + + +typedef struct _IPACM_conf_t +{ + ipacm_iface_conf_t iface_config; + ipacm_private_subnet_conf_t private_subnet_config; + ipacm_alg_conf_t alg_config; + int nat_max_entries; + bool odu_enable; + bool router_mode_enable; + bool odu_embms_enable; + int num_wlan_guest_ap; +} IPACM_conf_t; + +/* This function read IPACM XML configuration*/ +int ipacm_read_cfg_xml +( + char *xml_file, /* Filename and path */ + IPACM_conf_t *config /* Mobile AP config data */ +); + +/* This function reads QCMAP Firewall XML and store in IPACM Firewall stucture */ +int IPACM_read_firewall_xml +( + char *xml_file, /* Filename and path */ + IPACM_firewall_conf_t *config /* Mobile AP config data */ +); + +#ifdef __cplusplus +} +#endif + +#endif //IPACM_XML diff --git a/data-ipa-cfg-mgr/ipacm/src/Android.mk b/data-ipa-cfg-mgr/ipacm/src/Android.mk new file mode 100644 index 000000000..cdfda29d7 --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/src/Android.mk @@ -0,0 +1,89 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_C_INCLUDES := $(LOCAL_PATH)/../src +LOCAL_C_INCLUDES += $(LOCAL_PATH)/../inc +LOCAL_C_INCLUDES += $(LOCAL_PATH)/../../ipanat/inc +ifeq ($(call is-platform-sdk-version-at-least,20),true) +LOCAL_C_INCLUDES += external/icu/icu4c/source/common +else +LOCAL_C_INCLUDES += external/icu4c/common +endif +LOCAL_C_INCLUDES += external/dhcpcd +LOCAL_C_INCLUDES += external/libxml2/include +LOCAL_C_INCLUDES += external/libnetfilter_conntrack/include +LOCAL_C_INCLUDES += external/libnfnetlink/include + +LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include +LOCAL_ADDITIONAL_DEPENDENCIES := $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr + + +LOCAL_CFLAGS := -v +LOCAL_CFLAGS += -DFEATURE_IPA_ANDROID +ifneq (,$(filter userdebug eng, $(TARGET_BUILD_VARIANT))) +LOCAL_CFLAGS += -DDEBUG +endif + +ifeq ($(TARGET_BOARD_PLATFORM),msm8998) +LOCAL_CFLAGS += -DFEATURE_IPA_V3 +endif + +filetoadd = bionic/libc/kernel/arch-arm/asm/posix_types.h +LOCAL_CFLAGS += $(shell if [ -a $(filetoadd) ] ; then echo -include $(filetoadd) ; fi ;) +filetoadd = bionic/libc/kernel/arch-arm/asm/byteorder.h +LOCAL_CFLAGS += $(shell if [ -a $(filetoadd) ] ; then echo -include $(filetoadd) ; fi ;) + +LOCAL_SRC_FILES := IPACM_Main.cpp \ + IPACM_EvtDispatcher.cpp \ + IPACM_Config.cpp \ + IPACM_CmdQueue.cpp \ + IPACM_Filtering.cpp \ + IPACM_Routing.cpp \ + IPACM_Header.cpp \ + IPACM_Lan.cpp \ + IPACM_Iface.cpp \ + IPACM_Wlan.cpp \ + IPACM_Wan.cpp \ + IPACM_IfaceManager.cpp \ + IPACM_Neighbor.cpp \ + IPACM_Netlink.cpp \ + IPACM_Xml.cpp \ + IPACM_Conntrack_NATApp.cpp\ + IPACM_ConntrackClient.cpp \ + IPACM_ConntrackListener.cpp \ + IPACM_Log.cpp + +LOCAL_MODULE := ipacm +LOCAL_CLANG := false +LOCAL_MODULE_TAGS := optional + +LOCAL_SHARED_LIBRARIES := libipanat +LOCAL_SHARED_LIBRARIES += libxml2 +LOCAL_SHARED_LIBRARIES += libnfnetlink +LOCAL_SHARED_LIBRARIES += libnetfilter_conntrack +LOCAL_SHARED_LIBRARIES += libdhcpcd +include $(BUILD_EXECUTABLE) + +################################################################################ + +define ADD_TEST + +include $(CLEAR_VARS) +LOCAL_MODULE := $1 +LOCAL_SRC_FILES := $1 +LOCAL_MODULE_CLASS := ipacm +LOCAL_MODULE_TAGS := debug +LOCAL_MODULE_PATH := $(TARGET_OUT_ETC) +include $(BUILD_PREBUILT) + +endef + +include $(CLEAR_VARS) +LOCAL_MODULE := IPACM_cfg.xml +LOCAL_MODULE_CLASS := ETC +LOCAL_MODULE_PATH := $(TARGET_OUT_ETC) +LOCAL_MODULE_TAGS := optional +LOCAL_SRC_FILES := $(LOCAL_MODULE) +LOCAL_MODULE_OWNER := ipacm +include $(BUILD_PREBUILT) diff --git a/data-ipa-cfg-mgr/ipacm/src/IPACM_CmdQueue.cpp b/data-ipa-cfg-mgr/ipacm/src/IPACM_CmdQueue.cpp new file mode 100644 index 000000000..7e48546a3 --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/src/IPACM_CmdQueue.cpp @@ -0,0 +1,165 @@ +/* +Copyright (c) 2013, The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +/*! + @file + IPACM_CmdQueue.cpp + + @brief + This file implements the IPAM Comment Queue functionality + + @Author + Sunil + +*/ +#include +#include "IPACM_CmdQueue.h" +#include "IPACM_Log.h" + +pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; +pthread_cond_t cond_var = PTHREAD_COND_INITIALIZER; + +MessageQueue* MessageQueue::inst = NULL; +MessageQueue* MessageQueue::getInstance() +{ + if(inst == NULL) + { + inst = new MessageQueue(); + if(inst == NULL) + { + IPACMERR("unable to create Message Queue instance\n"); + return NULL; + } + } + + return inst; +} + +void MessageQueue::enqueue(Message *item) +{ + if(!Head) + { + Tail = item; + Head = item; + } + else + { + if(Tail == NULL) + { + IPACMDBG("Tail is null\n"); + Head->setnext(item); + } + else + { + Tail->setnext(item); + } + Tail = item; + } +} + + +Message* MessageQueue::dequeue(void) +{ + if(Head == NULL) + { + return NULL; + } + else + { + Message *tmp = Head; + Head = Head->getnext(); + + return tmp; + } +} + + +void* MessageQueue::Process(void *param) +{ + MessageQueue *MsgQueue = NULL; + Message *item = NULL; + IPACMDBG("MessageQueue::Process()\n"); + + MsgQueue = MessageQueue::getInstance(); + if(MsgQueue == NULL) + { + IPACMERR("unable to start cmd queue process\n"); + return NULL; + } + + while(1) + { + if(pthread_mutex_lock(&mutex) != 0) + { + IPACMERR("unable to lock the mutex\n"); + return NULL; + } + + item = MsgQueue->dequeue(); + + if(item == NULL) + { + IPACMDBG("Waiting for Message\n"); + + if(pthread_cond_wait(&cond_var, &mutex) != 0) + { + IPACMERR("unable to lock the mutex\n"); + + if(pthread_mutex_unlock(&mutex) != 0) + { + IPACMERR("unable to unlock the mutex\n"); + return NULL; + } + + return NULL; + } + + if(pthread_mutex_unlock(&mutex) != 0) + { + IPACMERR("unable to unlock the mutex\n"); + return NULL; + } + + } + else + { + if(pthread_mutex_unlock(&mutex) != 0) + { + IPACMERR("unable to unlock the mutex\n"); + return NULL; + } + + IPACMDBG("Processing item %p event ID: %d\n",item,item->evt.data.event); + item->evt.callback_ptr(&item->evt.data); + delete item; + item = NULL; + } + + } /* Go forever until a termination indication is received */ + +} diff --git a/data-ipa-cfg-mgr/ipacm/src/IPACM_Config.cpp b/data-ipa-cfg-mgr/ipacm/src/IPACM_Config.cpp new file mode 100644 index 000000000..c718603e6 --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/src/IPACM_Config.cpp @@ -0,0 +1,776 @@ +/* +Copyright (c) 2013, The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +/*! + @file + IPACM_Config.cpp + + @brief + This file implements the IPACM Configuration from XML file + + @Author + Skylar Chang + +*/ +#include +#include +#include +#include +#include + +IPACM_Config *IPACM_Config::pInstance = NULL; +const char *IPACM_Config::DEVICE_NAME = "/dev/ipa"; +const char *IPACM_Config::DEVICE_NAME_ODU = "/dev/odu_ipa_bridge"; + +IPACM_Config::IPACM_Config() +{ + iface_table = NULL; + alg_table = NULL; + memset(&ipa_client_rm_map_tbl, 0, sizeof(ipa_client_rm_map_tbl)); + memset(&ipa_rm_tbl, 0, sizeof(ipa_rm_tbl)); + ipa_rm_a2_check=0; + ipacm_odu_enable = false; + ipacm_odu_router_mode = false; + ipa_num_wlan_guest_ap = 0; + + ipa_num_ipa_interfaces = 0; + ipa_num_private_subnet = 0; + ipa_num_alg_ports = 0; + ipa_nat_max_entries = 0; + ipa_nat_iface_entries = 0; + ipa_sw_rt_enable = false; + ipa_bridge_enable = false; + isMCC_Mode = false; + ipa_max_valid_rm_entry = 0; + + memset(&rt_tbl_default_v4, 0, sizeof(rt_tbl_default_v4)); + memset(&rt_tbl_lan_v4, 0, sizeof(rt_tbl_lan_v4)); + memset(&rt_tbl_wan_v4, 0, sizeof(rt_tbl_wan_v4)); + memset(&rt_tbl_v6, 0, sizeof(rt_tbl_v6)); + memset(&rt_tbl_wan_v6, 0, sizeof(rt_tbl_wan_v6)); + memset(&rt_tbl_wan_dl, 0, sizeof(rt_tbl_wan_dl)); + memset(&rt_tbl_odu_v4, 0, sizeof(rt_tbl_odu_v4)); + memset(&rt_tbl_odu_v6, 0, sizeof(rt_tbl_odu_v6)); + + memset(&ext_prop_v4, 0, sizeof(ext_prop_v4)); + memset(&ext_prop_v6, 0, sizeof(ext_prop_v6)); + + memset(&rt_tbl_eth_bridge_lan_wlan_v4, 0, sizeof(rt_tbl_eth_bridge_lan_wlan_v4)); + memset(&rt_tbl_eth_bridge_wlan_wlan_v4, 0, sizeof(rt_tbl_eth_bridge_wlan_wlan_v4)); + memset(&rt_tbl_eth_bridge_lan_wlan_v6, 0, sizeof(rt_tbl_eth_bridge_lan_wlan_v6)); + memset(&rt_tbl_eth_bridge_wlan_wlan_v6, 0, sizeof(rt_tbl_eth_bridge_wlan_wlan_v6)); + + qmap_id = ~0; + + memset(flt_rule_count_v4, 0, (IPA_CLIENT_CONS - IPA_CLIENT_PROD)*sizeof(int)); + memset(flt_rule_count_v6, 0, (IPA_CLIENT_CONS - IPA_CLIENT_PROD)*sizeof(int)); + memset(bridge_mac, 0, IPA_MAC_ADDR_SIZE*sizeof(uint8_t)); + + IPACMDBG_H(" create IPACM_Config constructor\n"); + return; +} + +int IPACM_Config::Init(void) +{ + /* Read IPACM Config file */ + char IPACM_config_file[IPA_MAX_FILE_LEN]; + IPACM_conf_t *cfg; + cfg = (IPACM_conf_t *)malloc(sizeof(IPACM_conf_t)); + if(cfg == NULL) + { + IPACMERR("Unable to allocate cfg memory.\n"); + return IPACM_FAILURE; + } + uint32_t subnet_addr; + uint32_t subnet_mask; + int i, ret = IPACM_SUCCESS; + struct in_addr in_addr_print; + + m_fd = open(DEVICE_NAME, O_RDWR); + if (0 > m_fd) + { + IPACMERR("Failed opening %s.\n", DEVICE_NAME); + } + strncpy(IPACM_config_file, "/etc/IPACM_cfg.xml", sizeof(IPACM_config_file)); + + IPACMDBG_H("\n IPACM XML file is %s \n", IPACM_config_file); + if (IPACM_SUCCESS == ipacm_read_cfg_xml(IPACM_config_file, cfg)) + { + IPACMDBG_H("\n IPACM XML read OK \n"); + } + else + { + IPACMERR("\n IPACM XML read failed \n"); + ret = IPACM_FAILURE; + goto fail; + } + + /* Check wlan AP-AP access mode configuration */ + if (cfg->num_wlan_guest_ap == 2) + { + IPACMDBG_H("IPACM_Config::Both wlan APs can not be configured in guest ap mode. \n"); + IPACMDBG_H("IPACM_Config::configure both APs in full access mode or at least one in guest ap mode. \n"); + ret = IPACM_FAILURE; + goto fail; + } + /* Construct IPACM Iface table */ + ipa_num_ipa_interfaces = cfg->iface_config.num_iface_entries; + if (iface_table != NULL) + { + free(iface_table); + iface_table = NULL; + IPACMDBG_H("RESET IPACM_Config::iface_table\n"); + } + iface_table = (ipa_ifi_dev_name_t *)calloc(ipa_num_ipa_interfaces, + sizeof(ipa_ifi_dev_name_t)); + if(iface_table == NULL) + { + IPACMERR("Unable to allocate iface_table memory.\n"); + ret = IPACM_FAILURE; + goto fail; + } + + for (i = 0; i < cfg->iface_config.num_iface_entries; i++) + { + strncpy(iface_table[i].iface_name, cfg->iface_config.iface_entries[i].iface_name, sizeof(iface_table[i].iface_name)); + iface_table[i].if_cat = cfg->iface_config.iface_entries[i].if_cat; + iface_table[i].if_mode = cfg->iface_config.iface_entries[i].if_mode; + iface_table[i].wlan_mode = cfg->iface_config.iface_entries[i].wlan_mode; + IPACMDBG_H("IPACM_Config::iface_table[%d] = %s, cat=%d, mode=%d wlan-mode=%d \n", i, iface_table[i].iface_name, + iface_table[i].if_cat, iface_table[i].if_mode, iface_table[i].wlan_mode); + /* copy bridge interface name to ipacmcfg */ + if( iface_table[i].if_cat == VIRTUAL_IF) + { + memcpy(ipa_virtual_iface_name, iface_table[i].iface_name, sizeof(ipa_virtual_iface_name)); + IPACMDBG_H("ipa_virtual_iface_name(%s) \n", ipa_virtual_iface_name); + } + } + + /* Construct IPACM Private_Subnet table */ + memset(&private_subnet_table, 0, sizeof(private_subnet_table)); + ipa_num_private_subnet = cfg->private_subnet_config.num_subnet_entries; + + for (i = 0; i < cfg->private_subnet_config.num_subnet_entries; i++) + { + memcpy(&private_subnet_table[i].subnet_addr, + &cfg->private_subnet_config.private_subnet_entries[i].subnet_addr, + sizeof(cfg->private_subnet_config.private_subnet_entries[i].subnet_addr)); + + memcpy(&private_subnet_table[i].subnet_mask, + &cfg->private_subnet_config.private_subnet_entries[i].subnet_mask, + sizeof(cfg->private_subnet_config.private_subnet_entries[i].subnet_mask)); + + subnet_addr = htonl(private_subnet_table[i].subnet_addr); + memcpy(&in_addr_print,&subnet_addr,sizeof(in_addr_print)); + IPACMDBG_H("%dst::private_subnet_table= %s \n ", i, + inet_ntoa(in_addr_print)); + + subnet_mask = htonl(private_subnet_table[i].subnet_mask); + memcpy(&in_addr_print,&subnet_mask,sizeof(in_addr_print)); + IPACMDBG_H("%dst::private_subnet_table= %s \n ", i, + inet_ntoa(in_addr_print)); + } + + /* Construct IPACM ALG table */ + ipa_num_alg_ports = cfg->alg_config.num_alg_entries; + if (alg_table != NULL) + { + free(alg_table); + alg_table = NULL; + IPACMDBG_H("RESET IPACM_Config::alg_table \n"); + } + alg_table = (ipacm_alg *)calloc(ipa_num_alg_ports, + sizeof(ipacm_alg)); + if(alg_table == NULL) + { + IPACMERR("Unable to allocate alg_table memory.\n"); + ret = IPACM_FAILURE; + free(iface_table); + goto fail;; + } + for (i = 0; i < cfg->alg_config.num_alg_entries; i++) + { + alg_table[i].protocol = cfg->alg_config.alg_entries[i].protocol; + alg_table[i].port = cfg->alg_config.alg_entries[i].port; + IPACMDBG_H("IPACM_Config::ipacm_alg[%d] = %d, port=%d\n", i, alg_table[i].protocol, alg_table[i].port); + } + + ipa_nat_max_entries = cfg->nat_max_entries; + IPACMDBG_H("Nat Maximum Entries %d\n", ipa_nat_max_entries); + + /* Find ODU is either router mode or bridge mode*/ + ipacm_odu_enable = cfg->odu_enable; + ipacm_odu_router_mode = cfg->router_mode_enable; + ipacm_odu_embms_enable = cfg->odu_embms_enable; + IPACMDBG_H("ipacm_odu_enable %d\n", ipacm_odu_enable); + IPACMDBG_H("ipacm_odu_mode %d\n", ipacm_odu_router_mode); + IPACMDBG_H("ipacm_odu_embms_enable %d\n", ipacm_odu_embms_enable); + ipa_num_wlan_guest_ap = cfg->num_wlan_guest_ap; + IPACMDBG_H("ipa_num_wlan_guest_ap %d\n",ipa_num_wlan_guest_ap); + + /* Allocate more non-nat entries if the monitored iface dun have Tx/Rx properties */ + if (pNatIfaces != NULL) + { + free(pNatIfaces); + pNatIfaces = NULL; + IPACMDBG_H("RESET IPACM_Config::pNatIfaces \n"); + } + ipa_nat_iface_entries = 0; + pNatIfaces = (NatIfaces *)calloc(ipa_num_ipa_interfaces, sizeof(NatIfaces)); + if (pNatIfaces == NULL) + { + IPACMERR("unable to allocate nat ifaces\n"); + ret = IPACM_FAILURE; + free(iface_table); + free(alg_table); + goto fail; + } + + /* Construct the routing table ictol name in iface static member*/ + rt_tbl_default_v4.ip = IPA_IP_v4; + strncpy(rt_tbl_default_v4.name, V4_DEFAULT_ROUTE_TABLE_NAME, sizeof(rt_tbl_default_v4.name)); + + rt_tbl_lan_v4.ip = IPA_IP_v4; + strncpy(rt_tbl_lan_v4.name, V4_LAN_ROUTE_TABLE_NAME, sizeof(rt_tbl_lan_v4.name)); + + rt_tbl_wan_v4.ip = IPA_IP_v4; + strncpy(rt_tbl_wan_v4.name, V4_WAN_ROUTE_TABLE_NAME, sizeof(rt_tbl_wan_v4.name)); + + rt_tbl_v6.ip = IPA_IP_v6; + strncpy(rt_tbl_v6.name, V6_COMMON_ROUTE_TABLE_NAME, sizeof(rt_tbl_v6.name)); + + rt_tbl_wan_v6.ip = IPA_IP_v6; + strncpy(rt_tbl_wan_v6.name, V6_WAN_ROUTE_TABLE_NAME, sizeof(rt_tbl_wan_v6.name)); + + rt_tbl_odu_v4.ip = IPA_IP_v4; + strncpy(rt_tbl_odu_v4.name, V4_ODU_ROUTE_TABLE_NAME, sizeof(rt_tbl_odu_v4.name)); + + rt_tbl_odu_v6.ip = IPA_IP_v6; + strncpy(rt_tbl_odu_v6.name, V6_ODU_ROUTE_TABLE_NAME, sizeof(rt_tbl_odu_v6.name)); + + rt_tbl_wan_dl.ip = IPA_IP_MAX; + strncpy(rt_tbl_wan_dl.name, WAN_DL_ROUTE_TABLE_NAME, sizeof(rt_tbl_wan_dl.name)); + + rt_tbl_lan2lan_v4.ip = IPA_IP_v4; + strncpy(rt_tbl_lan2lan_v4.name, V4_LAN_TO_LAN_ROUTE_TABLE_NAME, sizeof(rt_tbl_lan2lan_v4.name)); + + rt_tbl_lan2lan_v6.ip = IPA_IP_v6; + strncpy(rt_tbl_lan2lan_v6.name, V6_LAN_TO_LAN_ROUTE_TABLE_NAME, sizeof(rt_tbl_lan2lan_v6.name)); + + rt_tbl_eth_bridge_lan_lan_v4.ip = IPA_IP_v4; + strncpy(rt_tbl_eth_bridge_lan_lan_v4.name, ETH_BRIDGE_USB_CPE_ROUTE_TABLE_NAME_V4, sizeof(rt_tbl_eth_bridge_lan_lan_v4.name)); + + rt_tbl_eth_bridge_lan_wlan_v4.ip = IPA_IP_v4; + strncpy(rt_tbl_eth_bridge_lan_wlan_v4.name, ETH_BRIDGE_USB_WLAN_ROUTE_TABLE_NAME_V4, sizeof(rt_tbl_eth_bridge_lan_wlan_v4.name)); + + rt_tbl_eth_bridge_wlan_wlan_v4.ip = IPA_IP_v4; + strncpy(rt_tbl_eth_bridge_wlan_wlan_v4.name, ETH_BRIDGE_WLAN_WLAN_ROUTE_TABLE_NAME_V4, sizeof(rt_tbl_eth_bridge_wlan_wlan_v4.name)); + + rt_tbl_eth_bridge_lan_lan_v6.ip = IPA_IP_v6; + strncpy(rt_tbl_eth_bridge_lan_lan_v6.name, ETH_BRIDGE_USB_CPE_ROUTE_TABLE_NAME_V6, sizeof(rt_tbl_eth_bridge_lan_lan_v6.name)); + + rt_tbl_eth_bridge_lan_wlan_v6.ip = IPA_IP_v6; + strncpy(rt_tbl_eth_bridge_lan_wlan_v6.name, ETH_BRIDGE_USB_WLAN_ROUTE_TABLE_NAME_V6, sizeof(rt_tbl_eth_bridge_lan_wlan_v6.name)); + + rt_tbl_eth_bridge_wlan_wlan_v6.ip = IPA_IP_v6; + strncpy(rt_tbl_eth_bridge_wlan_wlan_v6.name, ETH_BRIDGE_WLAN_WLAN_ROUTE_TABLE_NAME_V6, sizeof(rt_tbl_eth_bridge_wlan_wlan_v6.name)); + + /* Construct IPACM ipa_client map to rm_resource table */ + ipa_client_rm_map_tbl[IPA_CLIENT_WLAN1_PROD]= IPA_RM_RESOURCE_WLAN_PROD; + ipa_client_rm_map_tbl[IPA_CLIENT_USB_PROD]= IPA_RM_RESOURCE_USB_PROD; + ipa_client_rm_map_tbl[IPA_CLIENT_A5_WLAN_AMPDU_PROD]= IPA_RM_RESOURCE_HSIC_PROD; + ipa_client_rm_map_tbl[IPA_CLIENT_A2_EMBEDDED_PROD]= IPA_RM_RESOURCE_Q6_PROD; + ipa_client_rm_map_tbl[IPA_CLIENT_A2_TETHERED_PROD]= IPA_RM_RESOURCE_Q6_PROD; + ipa_client_rm_map_tbl[IPA_CLIENT_APPS_LAN_WAN_PROD]= IPA_RM_RESOURCE_Q6_PROD; + ipa_client_rm_map_tbl[IPA_CLIENT_WLAN1_CONS]= IPA_RM_RESOURCE_WLAN_CONS; + ipa_client_rm_map_tbl[IPA_CLIENT_WLAN2_CONS]= IPA_RM_RESOURCE_WLAN_CONS; + ipa_client_rm_map_tbl[IPA_CLIENT_WLAN3_CONS]= IPA_RM_RESOURCE_WLAN_CONS; + ipa_client_rm_map_tbl[IPA_CLIENT_WLAN4_CONS]= IPA_RM_RESOURCE_WLAN_CONS; + ipa_client_rm_map_tbl[IPA_CLIENT_USB_CONS]= IPA_RM_RESOURCE_USB_CONS; + ipa_client_rm_map_tbl[IPA_CLIENT_A2_EMBEDDED_CONS]= IPA_RM_RESOURCE_Q6_CONS; + ipa_client_rm_map_tbl[IPA_CLIENT_A2_TETHERED_CONS]= IPA_RM_RESOURCE_Q6_CONS; + ipa_client_rm_map_tbl[IPA_CLIENT_APPS_WAN_CONS]= IPA_RM_RESOURCE_Q6_CONS; + ipa_client_rm_map_tbl[IPA_CLIENT_ODU_PROD]= IPA_RM_RESOURCE_ODU_ADAPT_PROD; + ipa_client_rm_map_tbl[IPA_CLIENT_ODU_EMB_CONS]= IPA_RM_RESOURCE_ODU_ADAPT_CONS; + ipa_client_rm_map_tbl[IPA_CLIENT_ODU_TETH_CONS]= IPA_RM_RESOURCE_ODU_ADAPT_CONS; + + /* Create the entries which IPACM wants to add dependencies on */ + ipa_rm_tbl[0].producer_rm1 = IPA_RM_RESOURCE_WLAN_PROD; + ipa_rm_tbl[0].consumer_rm1 = IPA_RM_RESOURCE_Q6_CONS; + ipa_rm_tbl[0].producer_rm2 = IPA_RM_RESOURCE_Q6_PROD; + ipa_rm_tbl[0].consumer_rm2 = IPA_RM_RESOURCE_WLAN_CONS; + + ipa_rm_tbl[1].producer_rm1 = IPA_RM_RESOURCE_USB_PROD; + ipa_rm_tbl[1].consumer_rm1 = IPA_RM_RESOURCE_Q6_CONS; + ipa_rm_tbl[1].producer_rm2 = IPA_RM_RESOURCE_Q6_PROD; + ipa_rm_tbl[1].consumer_rm2 = IPA_RM_RESOURCE_USB_CONS; + + ipa_rm_tbl[2].producer_rm1 = IPA_RM_RESOURCE_WLAN_PROD; + ipa_rm_tbl[2].consumer_rm1 = IPA_RM_RESOURCE_USB_CONS; + ipa_rm_tbl[2].producer_rm2 = IPA_RM_RESOURCE_USB_PROD; + ipa_rm_tbl[2].consumer_rm2 = IPA_RM_RESOURCE_WLAN_CONS; + + ipa_rm_tbl[3].producer_rm1 = IPA_RM_RESOURCE_ODU_ADAPT_PROD; + ipa_rm_tbl[3].consumer_rm1 = IPA_RM_RESOURCE_Q6_CONS; + ipa_rm_tbl[3].producer_rm2 = IPA_RM_RESOURCE_Q6_PROD; + ipa_rm_tbl[3].consumer_rm2 = IPA_RM_RESOURCE_ODU_ADAPT_CONS; + + ipa_rm_tbl[4].producer_rm1 = IPA_RM_RESOURCE_WLAN_PROD; + ipa_rm_tbl[4].consumer_rm1 = IPA_RM_RESOURCE_ODU_ADAPT_CONS; + ipa_rm_tbl[4].producer_rm2 = IPA_RM_RESOURCE_ODU_ADAPT_PROD; + ipa_rm_tbl[4].consumer_rm2 = IPA_RM_RESOURCE_WLAN_CONS; + + ipa_rm_tbl[5].producer_rm1 = IPA_RM_RESOURCE_ODU_ADAPT_PROD; + ipa_rm_tbl[5].consumer_rm1 = IPA_RM_RESOURCE_USB_CONS; + ipa_rm_tbl[5].producer_rm2 = IPA_RM_RESOURCE_USB_PROD; + ipa_rm_tbl[5].consumer_rm2 = IPA_RM_RESOURCE_ODU_ADAPT_CONS; + ipa_max_valid_rm_entry = 6; /* max is IPA_MAX_RM_ENTRY (6)*/ + + IPACMDBG_H(" depend MAP-0 rm index %d to rm index: %d \n", IPA_RM_RESOURCE_WLAN_PROD, IPA_RM_RESOURCE_Q6_CONS); + IPACMDBG_H(" depend MAP-1 rm index %d to rm index: %d \n", IPA_RM_RESOURCE_USB_PROD, IPA_RM_RESOURCE_Q6_CONS); + IPACMDBG_H(" depend MAP-2 rm index %d to rm index: %d \n", IPA_RM_RESOURCE_WLAN_PROD, IPA_RM_RESOURCE_USB_CONS); + IPACMDBG_H(" depend MAP-3 rm index %d to rm index: %d \n", IPA_RM_RESOURCE_ODU_ADAPT_PROD, IPA_RM_RESOURCE_Q6_CONS); + IPACMDBG_H(" depend MAP-4 rm index %d to rm index: %d \n", IPA_RM_RESOURCE_WLAN_PROD, IPA_RM_RESOURCE_ODU_ADAPT_CONS); + IPACMDBG_H(" depend MAP-5 rm index %d to rm index: %d \n", IPA_RM_RESOURCE_ODU_ADAPT_PROD, IPA_RM_RESOURCE_USB_CONS); + +fail: + if (cfg != NULL) + { + free(cfg); + cfg = NULL; + } + + return ret; +} + +IPACM_Config* IPACM_Config::GetInstance() +{ + int res = IPACM_SUCCESS; + + if (pInstance == NULL) + { + pInstance = new IPACM_Config(); + + res = pInstance->Init(); + if (res != IPACM_SUCCESS) + { + delete pInstance; + IPACMERR("unable to initialize config instance\n"); + return NULL; + } + } + + return pInstance; +} + +int IPACM_Config::GetAlgPorts(int nPorts, ipacm_alg *pAlgPorts) +{ + if (nPorts <= 0 || pAlgPorts == NULL) + { + IPACMERR("Invalid input\n"); + return -1; + } + + for (int cnt = 0; cnt < nPorts; cnt++) + { + pAlgPorts[cnt].protocol = alg_table[cnt].protocol; + pAlgPorts[cnt].port = alg_table[cnt].port; + } + + return 0; +} + +int IPACM_Config::GetNatIfaces(int nIfaces, NatIfaces *pIfaces) +{ + if (nIfaces <= 0 || pIfaces == NULL) + { + IPACMERR("Invalid input\n"); + return -1; + } + + for (int cnt=0; cntnum_ext_props <= 0) + { + IPACMERR("There is no extended property!\n"); + return IPACM_FAILURE; + } + + num = prop->num_ext_props; + for(i=0; iext[i].ip == IPA_IP_v4) + { + if(ext_prop_v4.num_ext_props >= MAX_NUM_EXT_PROPS) + { + IPACMDBG_H("IPv4 extended property table is full!\n"); + continue; + } + memcpy(&ext_prop_v4.prop[ext_prop_v4.num_ext_props], &prop->ext[i], sizeof(struct ipa_ioc_ext_intf_prop)); + ext_prop_v4.num_ext_props++; + } + else if(prop->ext[i].ip == IPA_IP_v6) + { + if(ext_prop_v6.num_ext_props >= MAX_NUM_EXT_PROPS) + { + IPACMDBG_H("IPv6 extended property table is full!\n"); + continue; + } + memcpy(&ext_prop_v6.prop[ext_prop_v6.num_ext_props], &prop->ext[i], sizeof(struct ipa_ioc_ext_intf_prop)); + ext_prop_v6.num_ext_props++; + } + else + { + IPACMERR("The IP type is not expected!\n"); + return IPACM_FAILURE; + } + } + + IPACMDBG_H("Set extended property succeeded.\n"); + + return IPACM_SUCCESS; +} + +ipacm_ext_prop* IPACM_Config::GetExtProp(ipa_ip_type ip_type) +{ + if(ip_type == IPA_IP_v4) + return &ext_prop_v4; + else if(ip_type == IPA_IP_v6) + return &ext_prop_v6; + else + { + IPACMERR("Failed to get extended property: the IP version is neither IPv4 nor IPv6!\n"); + return NULL; + } +} + +int IPACM_Config::DelExtProp(ipa_ip_type ip_type) +{ + if(ip_type != IPA_IP_v6) + { + memset(&ext_prop_v4, 0, sizeof(ext_prop_v4)); + } + + if(ip_type != IPA_IP_v4) + { + memset(&ext_prop_v6, 0, sizeof(ext_prop_v6)); + } + + return IPACM_SUCCESS; +} diff --git a/data-ipa-cfg-mgr/ipacm/src/IPACM_ConntrackClient.cpp b/data-ipa-cfg-mgr/ipacm/src/IPACM_ConntrackClient.cpp new file mode 100644 index 000000000..2a670c8fa --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/src/IPACM_ConntrackClient.cpp @@ -0,0 +1,652 @@ +/* +Copyright (c) 2013, The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "IPACM_Iface.h" +#include "IPACM_ConntrackListener.h" +#include "IPACM_ConntrackClient.h" +#include "IPACM_Log.h" + +#define LO_NAME "lo" + +extern IPACM_EvtDispatcher cm_dis; +extern void ParseCTMessage(struct nf_conntrack *ct); + +IPACM_ConntrackClient *IPACM_ConntrackClient::pInstance = NULL; +IPACM_ConntrackListener *CtList = NULL; + +/* ================================ + Local Function Definitions + ================================= +*/ +IPACM_ConntrackClient::IPACM_ConntrackClient() +{ + IPACMDBG("\n"); + + tcp_hdl = NULL; + udp_hdl = NULL; + tcp_filter = NULL; + udp_filter = NULL; +} + +IPACM_ConntrackClient* IPACM_ConntrackClient::GetInstance() +{ + if(pInstance == NULL) + { + pInstance = new IPACM_ConntrackClient(); + + pInstance->udp_filter = nfct_filter_create(); + if(pInstance->udp_filter == NULL) + { + IPACMERR("unable to create UDP filter\n"); + delete pInstance; + return NULL; + } + IPACMDBG("Created UDP filter\n"); + + pInstance->tcp_filter = nfct_filter_create(); + if(pInstance->tcp_filter == NULL) + { + IPACMERR("unable to create TCP filter\n"); + delete pInstance; + return NULL; + } + IPACMDBG("Created TCP filter\n"); + } + + return pInstance; +} + +int IPACM_ConntrackClient::IPAConntrackEventCB +( + enum nf_conntrack_msg_type type, + struct nf_conntrack *ct, + void *data + ) +{ + ipacm_cmd_q_data evt_data; + ipacm_ct_evt_data *ct_data; + uint8_t ip_type = 0; + + IPACMDBG("Event callback called with msgtype: %d\n",type); + + /* Retrieve ip type */ + ip_type = nfct_get_attr_u8(ct, ATTR_REPL_L3PROTO); + +#ifndef CT_OPT + if(AF_INET6 == ip_type) + { + IPACMDBG("Ignoring ipv6(%d) connections\n", ip_type); + goto IGNORE; + } + +#endif + + ct_data = (ipacm_ct_evt_data *)malloc(sizeof(ipacm_ct_evt_data)); + if(ct_data == NULL) + { + IPACMERR("unable to allocate memory \n"); + goto IGNORE; + } + + ct_data->ct = ct; + ct_data->type = type; + + evt_data.event = IPA_PROCESS_CT_MESSAGE; + evt_data.evt_data = (void *)ct_data; + +#ifdef CT_OPT + if(AF_INET6 == ip_type) + { + evt_data.event = IPA_PROCESS_CT_MESSAGE_V6; + } +#endif + + if(0 != IPACM_EvtDispatcher::PostEvt(&evt_data)) + { + IPACMERR("Error sending Conntrack message to processing thread!\n"); + free(ct_data); + goto IGNORE; + } + +/* NFCT_CB_STOLEN means that the conntrack object is not released after the + callback That must be manually done later when the object is no longer needed. */ + return NFCT_CB_STOLEN; + +IGNORE: + nfct_destroy(ct); + return NFCT_CB_STOLEN; + +} + +int IPACM_ConntrackClient::IPA_Conntrack_Filters_Ignore_Bridge_Addrs +( + struct nfct_filter *filter +) +{ + int fd; + fd = socket(AF_INET, SOCK_DGRAM, 0); + if(fd < 0) + { + PERROR("unable to open socket"); + return -1; + } + + int ret; + uint32_t ipv4_addr; + struct ifreq ifr; + + /* retrieve bridge interface ipv4 address */ + memset(&ifr, 0, sizeof(struct ifreq)); + ifr.ifr_addr.sa_family = AF_INET; + (void)strncpy(ifr.ifr_name, IPACM_Iface::ipacmcfg->ipa_virtual_iface_name, sizeof(ifr.ifr_name)); + IPACMDBG("bridge interface name (%s)\n", ifr.ifr_name); + + ret = ioctl(fd, SIOCGIFADDR, &ifr); + if (ret < 0) + { + IPACMERR("unable to retrieve (%s) interface address\n",ifr.ifr_name); + close(fd); + return -1; + } + IPACMDBG("Interface (%s) address %s\n", ifr.ifr_name, inet_ntoa(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr)); + ipv4_addr = ntohl(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr); + close(fd); + + /* ignore whatever is destined to or originates from broadcast ip address */ + struct nfct_filter_ipv4 filter_ipv4; + + filter_ipv4.addr = ipv4_addr; + filter_ipv4.mask = 0xffffffff; + + nfct_filter_set_logic(filter, + NFCT_FILTER_DST_IPV4, + NFCT_FILTER_LOGIC_NEGATIVE); + + nfct_filter_add_attr(filter, NFCT_FILTER_DST_IPV4, &filter_ipv4); + + nfct_filter_set_logic(filter, + NFCT_FILTER_SRC_IPV4, + NFCT_FILTER_LOGIC_NEGATIVE); + + nfct_filter_add_attr(filter, NFCT_FILTER_SRC_IPV4, &filter_ipv4); + + return 0; +} + +int IPACM_ConntrackClient::IPA_Conntrack_Filters_Ignore_Local_Iface +( + struct nfct_filter *filter, + ipacm_event_iface_up *param +) +{ + struct nfct_filter_ipv4 filter_ipv4; + + filter_ipv4.addr = param->ipv4_addr; + filter_ipv4.mask = 0xffffffff; + + /* ignore whatever is destined to local interfaces */ + IPACMDBG("Ignore connections destinated to interface %s", param->ifname); + iptodot("with ipv4 address", param->ipv4_addr); + nfct_filter_set_logic(filter, + NFCT_FILTER_DST_IPV4, + NFCT_FILTER_LOGIC_NEGATIVE); + + nfct_filter_add_attr(filter, NFCT_FILTER_DST_IPV4, &filter_ipv4); + + IPACMDBG("Ignore connections orignated from interface %s", param->ifname); + iptodot("with ipv4 address", filter_ipv4.addr); + nfct_filter_set_logic(filter, + NFCT_FILTER_SRC_IPV4, + NFCT_FILTER_LOGIC_NEGATIVE); + + nfct_filter_add_attr(filter, NFCT_FILTER_SRC_IPV4, &filter_ipv4); + + /* Retrieve broadcast address */ + /* Intialize with 255.255.255.255 */ + uint32_t bc_ip_addr = 0xFFFFFFFF; + + /* calculate broadcast address from addr and addr_mask */ + bc_ip_addr = (bc_ip_addr & (~param->addr_mask)); + bc_ip_addr = (bc_ip_addr | (param->ipv4_addr & param->addr_mask)); + + /* netfitler expecting in host-byte order */ + filter_ipv4.addr = bc_ip_addr; + filter_ipv4.mask = 0xffffffff; + + iptodot("with broadcast address", filter_ipv4.addr); + nfct_filter_set_logic(filter, + NFCT_FILTER_DST_IPV4, + NFCT_FILTER_LOGIC_NEGATIVE); + + nfct_filter_add_attr(filter, NFCT_FILTER_DST_IPV4, &filter_ipv4); + + return 0; +} + +/* Function which sets up filters to ignore + connections to and from local interfaces */ +int IPACM_ConntrackClient::IPA_Conntrack_Filters_Ignore_Local_Addrs +( + struct nfct_filter *filter +) +{ + struct nfct_filter_ipv4 filter_ipv4; + + /* ignore whatever is destined to or originates from broadcast ip address */ + filter_ipv4.addr = 0xffffffff; + filter_ipv4.mask = 0xffffffff; + + nfct_filter_set_logic(filter, + NFCT_FILTER_DST_IPV4, + NFCT_FILTER_LOGIC_NEGATIVE); + + nfct_filter_add_attr(filter, NFCT_FILTER_DST_IPV4, &filter_ipv4); + + nfct_filter_set_logic(filter, + NFCT_FILTER_SRC_IPV4, + NFCT_FILTER_LOGIC_NEGATIVE); + + nfct_filter_add_attr(filter, NFCT_FILTER_SRC_IPV4, &filter_ipv4); + + return 0; +} /* IPA_Conntrack_Filters_Ignore_Local_Addrs() */ + +/* Initialize TCP Filter */ +int IPACM_ConntrackClient::IPA_Conntrack_TCP_Filter_Init(void) +{ + int ret = 0; + IPACM_ConntrackClient *pClient; + + IPACMDBG("\n"); + + pClient = IPACM_ConntrackClient::GetInstance(); + if(pClient == NULL) + { + IPACMERR("unable to get conntrack client instance\n"); + return -1; + } + + ret = nfct_filter_set_logic(pClient->tcp_filter, + NFCT_FILTER_L4PROTO, + NFCT_FILTER_LOGIC_POSITIVE); + if(ret == -1) + { + IPACMERR("Unable to set filter logic\n"); + return -1; + } + + /* set protocol filters as tcp and udp */ + nfct_filter_add_attr_u32(pClient->tcp_filter, NFCT_FILTER_L4PROTO, IPPROTO_TCP); + + + struct nfct_filter_proto tcp_proto_state; + tcp_proto_state.proto = IPPROTO_TCP; + tcp_proto_state.state = TCP_CONNTRACK_ESTABLISHED; + + ret = nfct_filter_set_logic(pClient->tcp_filter, + NFCT_FILTER_L4PROTO_STATE, + NFCT_FILTER_LOGIC_POSITIVE); + if(ret == -1) + { + IPACMERR("unable to set filter logic\n"); + return -1; + } + nfct_filter_add_attr(pClient->tcp_filter, + NFCT_FILTER_L4PROTO_STATE, + &tcp_proto_state); + + + tcp_proto_state.proto = IPPROTO_TCP; + tcp_proto_state.state = TCP_CONNTRACK_FIN_WAIT; + ret = nfct_filter_set_logic(pClient->tcp_filter, + NFCT_FILTER_L4PROTO_STATE, + NFCT_FILTER_LOGIC_POSITIVE); + if(ret == -1) + { + IPACMERR("unable to set filter logic\n"); + return -1; + } + + nfct_filter_add_attr(pClient->tcp_filter, + NFCT_FILTER_L4PROTO_STATE, + &tcp_proto_state); + return 0; +} + + +/* Initialize UDP Filter */ +int IPACM_ConntrackClient::IPA_Conntrack_UDP_Filter_Init(void) +{ + int ret = 0; + IPACM_ConntrackClient *pClient = IPACM_ConntrackClient::GetInstance(); + if(pClient == NULL) + { + IPACMERR("unable to get conntrack client instance\n"); + return -1; + } + + ret = nfct_filter_set_logic(pClient->udp_filter, + NFCT_FILTER_L4PROTO, + NFCT_FILTER_LOGIC_POSITIVE); + if(ret == -1) + { + IPACMERR("unable to set filter logic\n"); + } + /* set protocol filters as tcp and udp */ + nfct_filter_add_attr_u32(pClient->udp_filter, NFCT_FILTER_L4PROTO, IPPROTO_UDP); + + return 0; +} + +void* IPACM_ConntrackClient::UDPConnTimeoutUpdate(void *ptr) +{ + + NatApp *nat_inst = NULL; +#ifdef IPACM_DEBUG + IPACMDBG("\n"); +#endif + + nat_inst = NatApp::GetInstance(); + if(nat_inst == NULL) + { + IPACMERR("unable to create nat instance\n"); + return NULL; + } + + while(1) + { + nat_inst->UpdateUDPTimeStamp(); + sleep(UDP_TIMEOUT_UPDATE); + } /* end of while(1) loop */ + +#ifdef IPACM_DEBUG + IPACMDBG("Returning from %s() %d\n", __FUNCTION__, __LINE__); +#endif + + return NULL; +} + +/* Thread to initialize TCP Conntrack Filters*/ +void* IPACM_ConntrackClient::TCPRegisterWithConnTrack(void *) +{ + int ret; + IPACM_ConntrackClient *pClient; + unsigned subscrips = 0; + + IPACMDBG("\n"); + + pClient = IPACM_ConntrackClient::GetInstance(); + if(pClient == NULL) + { + IPACMERR("unable to get conntrack client instance\n"); + return NULL; + } + + subscrips = (NF_NETLINK_CONNTRACK_UPDATE | NF_NETLINK_CONNTRACK_DESTROY); +#ifdef CT_OPT + subscrips |= NF_NETLINK_CONNTRACK_NEW; +#endif + + pClient->tcp_hdl = nfct_open(CONNTRACK, subscrips); + if(pClient->tcp_hdl == NULL) + { + PERROR("nfct_open\n"); + return NULL; + } + + /* Initialize the filter */ + ret = IPA_Conntrack_TCP_Filter_Init(); + if(ret == -1) + { + IPACMERR("Unable to initliaze TCP Filter\n"); + return NULL; + } + + /* Attach the filter to net filter handler */ + ret = nfct_filter_attach(nfct_fd(pClient->tcp_hdl), pClient->tcp_filter); + if(ret == -1) + { + IPACMDBG("unable to attach TCP filter\n"); + return NULL; + } + + /* Register callback with netfilter handler */ + IPACMDBG_H("tcp handle:%p, fd:%d\n", pClient->tcp_hdl, nfct_fd(pClient->tcp_hdl)); +#ifndef CT_OPT + nfct_callback_register(pClient->tcp_hdl, + (nf_conntrack_msg_type) (NFCT_T_UPDATE | NFCT_T_DESTROY | NFCT_T_NEW), + IPAConntrackEventCB, NULL); +#else + nfct_callback_register(pClient->tcp_hdl, (nf_conntrack_msg_type) NFCT_T_ALL, IPAConntrackEventCB, NULL); +#endif + + /* Block to catch events from net filter connection track */ + /* nfct_catch() receives conntrack events from kernel-space, by default it + blocks waiting for events. */ + IPACMDBG("Waiting for events\n"); + + ret = nfct_catch(pClient->tcp_hdl); + if(ret == -1) + { + IPACMERR("(%d)(%s)\n", ret, strerror(errno)); + return NULL; + } + + IPACMDBG("Exit from tcp thread\n"); + + /* destroy the filter.. this will not detach the filter */ + nfct_filter_destroy(pClient->tcp_filter); + pClient->tcp_filter = NULL; + + /* de-register the callback */ + nfct_callback_unregister(pClient->tcp_hdl); + /* close the handle */ + nfct_close(pClient->tcp_hdl); + pClient->tcp_hdl = NULL; + + pthread_exit(NULL); + return NULL; +} + +/* Thread to initialize UDP Conntrack Filters*/ +void* IPACM_ConntrackClient::UDPRegisterWithConnTrack(void *) +{ + int ret; + IPACM_ConntrackClient *pClient = NULL; + + IPACMDBG("\n"); + + pClient = IPACM_ConntrackClient::GetInstance(); + if(pClient == NULL) + { + IPACMERR("unable to retrieve instance of conntrack client\n"); + return NULL; + } + + pClient->udp_hdl = nfct_open(CONNTRACK, + (NF_NETLINK_CONNTRACK_NEW | NF_NETLINK_CONNTRACK_DESTROY)); + if(pClient->udp_hdl == NULL) + { + PERROR("nfct_open\n"); + return NULL; + } + + /* Initialize Filter */ + ret = IPA_Conntrack_UDP_Filter_Init(); + if(-1 == ret) + { + IPACMDBG("Unable to initalize udp filters\n"); + return NULL; + } + + /* Attach the filter to net filter handler */ + ret = nfct_filter_attach(nfct_fd(pClient->udp_hdl), pClient->udp_filter); + if(ret == -1) + { + IPACMDBG("unable to attach the filter\n"); + return NULL; + } + + /* Register callback with netfilter handler */ + IPACMDBG_H("udp handle:%p, fd:%d\n", pClient->udp_hdl, nfct_fd(pClient->udp_hdl)); + nfct_callback_register(pClient->udp_hdl, + (nf_conntrack_msg_type)(NFCT_T_NEW | NFCT_T_DESTROY), + IPAConntrackEventCB, + NULL); + + /* Block to catch events from net filter connection track */ +ctcatch: + ret = nfct_catch(pClient->udp_hdl); + if(ret == -1) + { + IPACMDBG("(%d)(%s)\n", ret, strerror(errno)); + return NULL; + } + else + { + IPACMDBG("ctcatch ret:%d\n", ret); + goto ctcatch; + } + + IPACMDBG("Exit from udp thread with ret: %d\n", ret); + + /* destroy the filter.. this will not detach the filter */ + nfct_filter_destroy(pClient->udp_filter); + pClient->udp_filter = NULL; + + /* de-register the callback */ + nfct_callback_unregister(pClient->udp_hdl); + /* close the handle */ + nfct_close(pClient->udp_hdl); + pClient->udp_hdl = NULL; + + pthread_exit(NULL); + return NULL; +} + +void IPACM_ConntrackClient::UpdateUDPFilters(void *param, bool isWan) +{ + static bool isIgnore = false; + int ret = 0; + IPACM_ConntrackClient *pClient = NULL; + + pClient = IPACM_ConntrackClient::GetInstance(); + if(pClient == NULL) + { + IPACMERR("unable to retrieve conntrack client instance\n"); + return; + } + + if(pClient->udp_filter == NULL) + { + return; + } + + if(!isWan) + { + IPA_Conntrack_Filters_Ignore_Local_Iface(pClient->udp_filter, + (ipacm_event_iface_up *)param); + + if(!isIgnore) + { + IPA_Conntrack_Filters_Ignore_Bridge_Addrs(pClient->udp_filter); + IPA_Conntrack_Filters_Ignore_Local_Addrs(pClient->udp_filter); + isIgnore = true; + } + } + + /* Attach the filter to udp handle */ + if(pClient->udp_hdl != NULL) + { + IPACMDBG("attaching the filter to udp handle\n"); + ret = nfct_filter_attach(nfct_fd(pClient->udp_hdl), pClient->udp_filter); + if(ret == -1) + { + PERROR("unable to attach the filter to udp handle\n"); + IPACMERR("udp handle:%p, fd:%d Error: %d\n",pClient->udp_hdl, nfct_fd(pClient->udp_hdl), ret); + return; + } + } + + return; +} + +void IPACM_ConntrackClient::UpdateTCPFilters(void *param, bool isWan) +{ + static bool isIgnore = false; + int ret = 0; + IPACM_ConntrackClient *pClient = NULL; + + pClient = IPACM_ConntrackClient::GetInstance(); + if(pClient == NULL) + { + IPACMERR("unable to retrieve conntrack client instance\n"); + return; + } + + if(pClient->tcp_filter == NULL) + return; + + if(!isWan) + { + IPA_Conntrack_Filters_Ignore_Local_Iface(pClient->tcp_filter, + (ipacm_event_iface_up *)param); + + if(!isIgnore) + { + IPA_Conntrack_Filters_Ignore_Bridge_Addrs(pClient->udp_filter); + IPA_Conntrack_Filters_Ignore_Local_Addrs(pClient->udp_filter); + isIgnore = true; + } + } + + /* Attach the filter to tcp handle */ + if(pClient->tcp_hdl != NULL) + { + IPACMDBG("attaching the filter to tcp handle\n"); + ret = nfct_filter_attach(nfct_fd(pClient->tcp_hdl), pClient->tcp_filter); + if(ret == -1) + { + PERROR("unable to attach the filter to tcp handle\n"); + IPACMERR("tcp handle:%p, fd:%d Error: %d\n",pClient->tcp_hdl, nfct_fd(pClient->tcp_hdl), ret); + return; + } + } + + return; +} + diff --git a/data-ipa-cfg-mgr/ipacm/src/IPACM_ConntrackListener.cpp b/data-ipa-cfg-mgr/ipacm/src/IPACM_ConntrackListener.cpp new file mode 100644 index 000000000..ab25bdea6 --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/src/IPACM_ConntrackListener.cpp @@ -0,0 +1,1058 @@ +/* +Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include +#include + +#include "IPACM_ConntrackListener.h" +#include "IPACM_ConntrackClient.h" +#include "IPACM_EvtDispatcher.h" + +IPACM_ConntrackListener::IPACM_ConntrackListener() +{ + IPACMDBG("\n"); + + isNatThreadStart = false; + isCTReg = false; + WanUp = false; + nat_inst = NatApp::GetInstance(); + + NatIfaceCnt = 0; + StaClntCnt = 0; + pNatIfaces = NULL; + pConfig = NULL; + + memset(nat_iface_ipv4_addr, 0, sizeof(nat_iface_ipv4_addr)); + memset(nonnat_iface_ipv4_addr, 0, sizeof(nonnat_iface_ipv4_addr)); + memset(sta_clnt_ipv4_addr, 0, sizeof(sta_clnt_ipv4_addr)); + + IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_UP, this); + IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_DOWN, this); + IPACM_EvtDispatcher::registr(IPA_PROCESS_CT_MESSAGE, this); + IPACM_EvtDispatcher::registr(IPA_PROCESS_CT_MESSAGE_V6, this); + IPACM_EvtDispatcher::registr(IPA_HANDLE_WLAN_UP, this); + IPACM_EvtDispatcher::registr(IPA_HANDLE_LAN_UP, this); + +#ifdef CT_OPT + p_lan2lan = IPACM_LanToLan::getLan2LanInstance(); +#endif +} + +void IPACM_ConntrackListener::event_callback(ipa_cm_event_id evt, + void *data) +{ + ipacm_event_iface_up *wan_down = NULL; + + if(data == NULL) + { + IPACMERR("Invalid Data\n"); + return; + } + + switch(evt) + { + case IPA_PROCESS_CT_MESSAGE: + IPACMDBG("Received IPA_PROCESS_CT_MESSAGE event\n"); + ProcessCTMessage(data); + break; + +#ifdef CT_OPT + case IPA_PROCESS_CT_MESSAGE_V6: + IPACMDBG("Received IPA_PROCESS_CT_MESSAGE_V6 event\n"); + ProcessCTV6Message(data); + break; +#endif + + case IPA_HANDLE_WAN_UP: + IPACMDBG_H("Received IPA_HANDLE_WAN_UP event\n"); + CreateConnTrackThreads(); + if(!isWanUp()) + { + TriggerWANUp(data); + } + break; + + case IPA_HANDLE_WAN_DOWN: + IPACMDBG_H("Received IPA_HANDLE_WAN_DOWN event\n"); + wan_down = (ipacm_event_iface_up *)data; + if(isWanUp()) + { + TriggerWANDown(wan_down->ipv4_addr); + } + break; + + /* if wlan or lan comes up after wan interface, modify + tcp/udp filters to ignore local wlan or lan connections */ + case IPA_HANDLE_WLAN_UP: + case IPA_HANDLE_LAN_UP: + IPACMDBG_H("Received event: %d with ifname: %s and address: 0x%x\n", + evt, ((ipacm_event_iface_up *)data)->ifname, + ((ipacm_event_iface_up *)data)->ipv4_addr); + CreateConnTrackThreads(); + IPACM_ConntrackClient::UpdateUDPFilters(data, false); + IPACM_ConntrackClient::UpdateTCPFilters(data, false); + break; + + default: + IPACMDBG("Ignore cmd %d\n", evt); + break; + } +} +void IPACM_ConntrackListener::HandleNeighIpAddrAddEvt(ipacm_event_data_all *data) +{ + int fd = 0, len = 0, cnt, i, j; + struct ifreq ifr; + bool isNatIface = false; + + if(data->ipv4_addr == 0 || data->iptype != IPA_IP_v4) + { + IPACMDBG("Ignoring IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT EVENT\n"); + return; + } + + IPACMDBG("\n"); + IPACMDBG("Received interface index %d with ip type: %d", data->if_index, data->iptype); + iptodot(" and ipv4 address", data->ipv4_addr); + + if(pConfig == NULL) + { + pConfig = IPACM_Config::GetInstance(); + if(pConfig == NULL) + { + IPACMERR("Unable to get Config instance\n"); + return; + } + } + + + cnt = pConfig->GetNatIfacesCnt(); + NatIfaceCnt = cnt; + if (pNatIfaces != NULL) { + free(pNatIfaces); + pNatIfaces = NULL; + } + + len = (sizeof(NatIfaces) * NatIfaceCnt); + pNatIfaces = (NatIfaces *)malloc(len); + if (pNatIfaces == NULL) { + IPACMERR("Unable to allocate memory for non nat ifaces\n"); + return; + } + memset(pNatIfaces, 0, len); + + if (pConfig->GetNatIfaces(NatIfaceCnt, pNatIfaces) != 0) { + IPACMERR("Unable to retrieve non nat ifaces\n"); + return; + } + IPACMDBG("Update %d Nat ifaces\n", NatIfaceCnt); + + + /* Search/Configure linux interface-index and map it to IPA interface-index */ + if((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) + { + PERROR("get interface name socket create failed"); + return; + } + + memset(&ifr, 0, sizeof(struct ifreq)); + ifr.ifr_ifindex = data->if_index; + + if(ioctl(fd, SIOCGIFNAME, &ifr) < 0) + { + PERROR("call_ioctl_on_dev: ioctl failed:"); + close(fd); + return; + } + close(fd); + + for(i = 0; i < NatIfaceCnt; i++) + { + if(strncmp(ifr.ifr_name, + pNatIfaces[i].iface_name, + sizeof(pNatIfaces[i].iface_name)) == 0) + { + /* copy the ipv4 address to filter out downlink connections + ignore downlink after listening connection event from + conntrack as it is not destinated to private ip address */ + IPACMDBG("Interface (%s) is nat\n", ifr.ifr_name); + for(j = 0; j < MAX_NAT_IFACES; j++) + { + /* check if duplicate NAT ip */ + if(nat_iface_ipv4_addr[j] == data->ipv4_addr) + break; + + if(nat_iface_ipv4_addr[j] == 0) + { + nat_iface_ipv4_addr[j] = data->ipv4_addr; + nat_inst->ResetPwrSaveIf(data->ipv4_addr); + nat_inst->FlushTempEntries(data->ipv4_addr, true); + break; + } + } + + if(j == MAX_NAT_IFACES) + { + IPACMERR("Nat ifaces(%d) exceed maximum\n", j); + break; + } + + + isNatIface = true; + IPACMDBG_H("Nating connections of Interface (%s), entry (%d) ", pNatIfaces[i].iface_name, j); + IPACMDBG_H(" with ipv4 address(0x%x): %d.%d.%d.%d\n", nat_iface_ipv4_addr[j], + ((nat_iface_ipv4_addr[j]>>24) & 0xFF), ((nat_iface_ipv4_addr[j]>>16) & 0xFF), + ((nat_iface_ipv4_addr[j]>>8) & 0xFF), (nat_iface_ipv4_addr[j] & 0xFF)); + break; + } + } + + /* Cache the non nat iface ip address */ + if(isNatIface != true) + { + for(i = 0; i < MAX_NAT_IFACES; i++) + { + if(nonnat_iface_ipv4_addr[i] == 0) + { + nonnat_iface_ipv4_addr[i] = data->ipv4_addr; + nat_inst->FlushTempEntries(data->ipv4_addr, false); + break; + } + } + } + +} + +void IPACM_ConntrackListener::HandleNeighIpAddrDelEvt(uint32_t ipv4_addr) +{ + int cnt; + + if(ipv4_addr == 0) + { + IPACMDBG("Ignoring IPA_NEIGH_CLIENT_IP_ADDR_DEL_EVENT EVENT\n"); + return; + } + + IPACMDBG("\n"); + iptodot("Received ip addr", ipv4_addr); + IPACMDBG("Entering NAT entry deletion checking\n"); + + for(cnt = 0; cntFlushTempEntries(ipv4_addr, false); + nat_inst->DelEntriesOnClntDiscon(ipv4_addr); + return; +} + +void IPACM_ConntrackListener::TriggerWANUp(void *in_param) +{ + ipacm_event_iface_up *wanup_data = (ipacm_event_iface_up *)in_param; + + IPACMDBG_H("Recevied below information during wanup,\n"); + IPACMDBG_H("if_name:%s, ipv4_address:0x%x\n", + wanup_data->ifname, wanup_data->ipv4_addr); + + if(wanup_data->ipv4_addr == 0) + { + IPACMERR("Invalid ipv4 address,ignoring IPA_HANDLE_WAN_UP event\n"); + return; + } + + WanUp = true; + isStaMode = wanup_data->is_sta; + IPACMDBG("isStaMode: %d\n", isStaMode); + + wan_ipaddr = wanup_data->ipv4_addr; + memcpy(wan_ifname, wanup_data->ifname, sizeof(wan_ifname)); + + if(nat_inst != NULL) + { + nat_inst->AddTable(wanup_data->ipv4_addr); + } + + IPACMDBG("creating nat threads\n"); + CreateNatThreads(); +} + +int IPACM_ConntrackListener::CreateConnTrackThreads(void) +{ + int ret; + pthread_t tcp_thread = 0, udp_thread = 0; + + if(isCTReg == false) + { + if(!tcp_thread) + { + ret = pthread_create(&tcp_thread, NULL, IPACM_ConntrackClient::TCPRegisterWithConnTrack, NULL); + if(0 != ret) + { + IPACMERR("unable to create TCP conntrack event listner thread\n"); + PERROR("unable to create TCP conntrack\n"); + return -1; + } + + IPACMDBG("created TCP conntrack event listner thread\n"); + if(pthread_setname_np(tcp_thread, "tcp ct listener") != 0) + { + IPACMERR("unable to set thread name\n"); + } + } + + if(!udp_thread) + { + ret = pthread_create(&udp_thread, NULL, IPACM_ConntrackClient::UDPRegisterWithConnTrack, NULL); + if(0 != ret) + { + IPACMERR("unable to create UDP conntrack event listner thread\n"); + PERROR("unable to create UDP conntrack\n"); + goto error; + } + + IPACMDBG("created UDP conntrack event listner thread\n"); + if(pthread_setname_np(udp_thread, "udp ct listener") != 0) + { + IPACMERR("unable to set thread name\n"); + } + } + + isCTReg = true; + } + + return 0; + +error: + return -1; +} +int IPACM_ConntrackListener::CreateNatThreads(void) +{ + int ret; + pthread_t udpcto_thread = 0; + + if(isNatThreadStart == false) + { + if(!udpcto_thread) + { + ret = pthread_create(&udpcto_thread, NULL, IPACM_ConntrackClient::UDPConnTimeoutUpdate, NULL); + if(0 != ret) + { + IPACMERR("unable to create udp conn timeout thread\n"); + PERROR("unable to create udp conn timeout\n"); + goto error; + } + + IPACMDBG("created upd conn timeout thread\n"); + if(pthread_setname_np(udpcto_thread, "udp conn timeout") != 0) + { + IPACMERR("unable to set thread name\n"); + } + } + + isNatThreadStart = true; + } + return 0; + +error: + return -1; +} + +void IPACM_ConntrackListener::TriggerWANDown(uint32_t wan_addr) +{ + IPACMDBG_H("Deleting ipv4 nat table with"); + IPACMDBG_H(" public ip address(0x%x): %d.%d.%d.%d\n", wan_addr, + ((wan_addr>>24) & 0xFF), ((wan_addr>>16) & 0xFF), + ((wan_addr>>8) & 0xFF), (wan_addr & 0xFF)); + + WanUp = false; + + if(nat_inst != NULL) + { + nat_inst->DeleteTable(wan_addr); + } +} + + +void ParseCTMessage(struct nf_conntrack *ct) +{ + uint32_t status, timeout; + IPACMDBG("Printing conntrack parameters\n"); + + iptodot("ATTR_IPV4_SRC = ATTR_ORIG_IPV4_SRC:", nfct_get_attr_u32(ct, ATTR_ORIG_IPV4_SRC)); + iptodot("ATTR_IPV4_DST = ATTR_ORIG_IPV4_DST:", nfct_get_attr_u32(ct, ATTR_ORIG_IPV4_DST)); + IPACMDBG("ATTR_PORT_SRC = ATTR_ORIG_PORT_SRC: 0x%x\n", nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC)); + IPACMDBG("ATTR_PORT_DST = ATTR_ORIG_PORT_DST: 0x%x\n", nfct_get_attr_u16(ct, ATTR_ORIG_PORT_DST)); + + iptodot("ATTR_REPL_IPV4_SRC:", nfct_get_attr_u32(ct, ATTR_REPL_IPV4_SRC)); + iptodot("ATTR_REPL_IPV4_DST:", nfct_get_attr_u32(ct, ATTR_REPL_IPV4_DST)); + IPACMDBG("ATTR_REPL_PORT_SRC: 0x%x\n", nfct_get_attr_u16(ct, ATTR_REPL_PORT_SRC)); + IPACMDBG("ATTR_REPL_PORT_DST: 0x%x\n", nfct_get_attr_u16(ct, ATTR_REPL_PORT_DST)); + + iptodot("ATTR_SNAT_IPV4:", nfct_get_attr_u32(ct, ATTR_SNAT_IPV4)); + iptodot("ATTR_DNAT_IPV4:", nfct_get_attr_u32(ct, ATTR_DNAT_IPV4)); + IPACMDBG("ATTR_SNAT_PORT: 0x%x\n", nfct_get_attr_u16(ct, ATTR_SNAT_PORT)); + IPACMDBG("ATTR_DNAT_PORT: 0x%x\n", nfct_get_attr_u16(ct, ATTR_DNAT_PORT)); + + IPACMDBG("ATTR_MARK: 0x%x\n", nfct_get_attr_u32(ct, ATTR_MARK)); + IPACMDBG("ATTR_USE: 0x%x\n", nfct_get_attr_u32(ct, ATTR_USE)); + IPACMDBG("ATTR_ID: 0x%x\n", nfct_get_attr_u32(ct, ATTR_ID)); + + status = nfct_get_attr_u32(ct, ATTR_STATUS); + IPACMDBG("ATTR_STATUS: 0x%x\n", status); + + timeout = nfct_get_attr_u32(ct, ATTR_TIMEOUT); + IPACMDBG("ATTR_TIMEOUT: 0x%x\n", timeout); + + if(IPS_SRC_NAT & status) + { + IPACMDBG("IPS_SRC_NAT set\n"); + } + + if(IPS_DST_NAT & status) + { + IPACMDBG("IPS_DST_NAT set\n"); + } + + if(IPS_SRC_NAT_DONE & status) + { + IPACMDBG("IPS_SRC_NAT_DONE set\n"); + } + + if(IPS_DST_NAT_DONE & status) + { + IPACMDBG(" IPS_DST_NAT_DONE set\n"); + } + + IPACMDBG("\n"); + return; +} + +void ParseCTV6Message(struct nf_conntrack *ct) +{ + uint32_t status, timeout, secmark; + struct nfct_attr_grp_ipv6 orig_params; + uint8_t l4proto, tcp_flags, tcp_state; + + IPACMDBG("Printing conntrack parameters\n"); + + nfct_get_attr_grp(ct, ATTR_GRP_ORIG_IPV6, (void *)&orig_params); + IPACMDBG("Orig src_v6_addr: 0x%08x%08x%08x%08x\n", orig_params.src[0], orig_params.src[1], + orig_params.src[2], orig_params.src[3]); + IPACMDBG("Orig dst_v6_addr: 0x%08x%08x%08x%08x\n", orig_params.dst[0], orig_params.dst[1], + orig_params.dst[2], orig_params.dst[3]); + + IPACMDBG("ATTR_PORT_SRC = ATTR_ORIG_PORT_SRC: 0x%x\n", nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC)); + IPACMDBG("ATTR_PORT_DST = ATTR_ORIG_PORT_DST: 0x%x\n", nfct_get_attr_u16(ct, ATTR_ORIG_PORT_DST)); + + IPACMDBG("ATTR_MARK: 0x%x\n", nfct_get_attr_u32(ct, ATTR_MARK)); + IPACMDBG("ATTR_USE: 0x%x\n", nfct_get_attr_u32(ct, ATTR_USE)); + IPACMDBG("ATTR_ID: 0x%x\n", nfct_get_attr_u32(ct, ATTR_ID)); + + timeout = nfct_get_attr_u32(ct, ATTR_TIMEOUT); + IPACMDBG("ATTR_TIMEOUT: 0x%x\n", timeout); + + status = nfct_get_attr_u32(ct, ATTR_STATUS); + IPACMDBG("ATTR_STATUS: 0x%x\n", status); + + l4proto = nfct_get_attr_u8(ct, ATTR_ORIG_L4PROTO); + IPACMDBG("ATTR_ORIG_L4PROTO: 0x%x\n", l4proto); + if(l4proto == IPPROTO_TCP) + { + tcp_state = nfct_get_attr_u8(ct, ATTR_TCP_STATE); + IPACMDBG("ATTR_TCP_STATE: 0x%x\n", tcp_state); + + tcp_flags = nfct_get_attr_u8(ct, ATTR_TCP_FLAGS_ORIG); + IPACMDBG("ATTR_TCP_FLAGS_ORIG: 0x%x\n", tcp_flags); + } + + IPACMDBG("\n"); + return; +} + +#ifdef CT_OPT +void IPACM_ConntrackListener::ProcessCTV6Message(void *param) +{ + ipacm_ct_evt_data *evt_data = (ipacm_ct_evt_data *)param; + u_int8_t l4proto = 0; + uint32_t status = 0; + struct nf_conntrack *ct = evt_data->ct; + +#ifdef IPACM_DEBUG + char buf[1024]; + + /* Process message and generate ioctl call to kernel thread */ + nfct_snprintf(buf, sizeof(buf), evt_data->ct, + evt_data->type, NFCT_O_PLAIN, NFCT_OF_TIME); + IPACMDBG("%s\n", buf); + IPACMDBG("\n"); + ParseCTV6Message(ct); +#endif + + if(p_lan2lan == NULL) + { + IPACMERR("Lan2Lan Instance is null\n"); + goto IGNORE; + } + + status = nfct_get_attr_u32(ct, ATTR_STATUS); + if((IPS_DST_NAT & status) || (IPS_SRC_NAT & status)) + { + IPACMDBG("Either Destination or Source nat flag Set\n"); + goto IGNORE; + } + + l4proto = nfct_get_attr_u8(ct, ATTR_ORIG_L4PROTO); + if(IPPROTO_UDP != l4proto && IPPROTO_TCP != l4proto) + { + IPACMDBG("Received unexpected protocl %d conntrack message\n", l4proto); + goto IGNORE; + } + + IPACMDBG("Neither Destination nor Source nat flag Set\n"); + struct nfct_attr_grp_ipv6 orig_params; + nfct_get_attr_grp(ct, ATTR_GRP_ORIG_IPV6, (void *)&orig_params); + + ipacm_event_connection lan2lan_conn; + lan2lan_conn.iptype = IPA_IP_v6; + memcpy(lan2lan_conn.src_ipv6_addr, orig_params.src, + sizeof(lan2lan_conn.src_ipv6_addr)); + IPACMDBG("Before convert, src_v6_addr: 0x%08x%08x%08x%08x\n", lan2lan_conn.src_ipv6_addr[0], lan2lan_conn.src_ipv6_addr[1], + lan2lan_conn.src_ipv6_addr[2], lan2lan_conn.src_ipv6_addr[3]); + for(int cnt=0; cnt<4; cnt++) + { + lan2lan_conn.src_ipv6_addr[cnt] = ntohl(lan2lan_conn.src_ipv6_addr[cnt]); + } + IPACMDBG("After convert src_v6_addr: 0x%08x%08x%08x%08x\n", lan2lan_conn.src_ipv6_addr[0], lan2lan_conn.src_ipv6_addr[1], + lan2lan_conn.src_ipv6_addr[2], lan2lan_conn.src_ipv6_addr[3]); + + memcpy(lan2lan_conn.dst_ipv6_addr, orig_params.dst, + sizeof(lan2lan_conn.dst_ipv6_addr)); + IPACMDBG("Before convert, dst_ipv6_addr: 0x%08x%08x%08x%08x\n", lan2lan_conn.dst_ipv6_addr[0], lan2lan_conn.dst_ipv6_addr[1], + lan2lan_conn.dst_ipv6_addr[2], lan2lan_conn.dst_ipv6_addr[3]); + for(int cnt=0; cnt<4; cnt++) + { + lan2lan_conn.dst_ipv6_addr[cnt] = ntohl(lan2lan_conn.dst_ipv6_addr[cnt]); + } + IPACMDBG("After convert, dst_ipv6_addr: 0x%08x%08x%08x%08x\n", lan2lan_conn.dst_ipv6_addr[0], lan2lan_conn.dst_ipv6_addr[1], + lan2lan_conn.dst_ipv6_addr[2], lan2lan_conn.dst_ipv6_addr[3]); + + if(((IPPROTO_UDP == l4proto) && (NFCT_T_NEW == evt_data->type)) || + ((IPPROTO_TCP == l4proto) && + (nfct_get_attr_u8(ct, ATTR_TCP_STATE) == TCP_CONNTRACK_ESTABLISHED)) + ) + { + p_lan2lan->handle_new_connection(&lan2lan_conn); + } + else if((IPPROTO_UDP == l4proto && NFCT_T_DESTROY == evt_data->type) || + (IPPROTO_TCP == l4proto && + nfct_get_attr_u8(ct, ATTR_TCP_STATE) == TCP_CONNTRACK_FIN_WAIT)) + { + p_lan2lan->handle_del_connection(&lan2lan_conn); + } + +IGNORE: + /* Cleanup item that was allocated during the original CT callback */ + nfct_destroy(ct); + return; +} +#endif + +void IPACM_ConntrackListener::ProcessCTMessage(void *param) +{ + ipacm_ct_evt_data *evt_data = (ipacm_ct_evt_data *)param; + u_int8_t l4proto = 0; + +#ifdef IPACM_DEBUG + char buf[1024]; + unsigned int out_flags; + + /* Process message and generate ioctl call to kernel thread */ + out_flags = (NFCT_OF_SHOW_LAYER3 | NFCT_OF_TIME | NFCT_OF_ID); + nfct_snprintf(buf, sizeof(buf), evt_data->ct, + evt_data->type, NFCT_O_PLAIN, out_flags); + IPACMDBG_H("%s\n", buf); + + ParseCTMessage(evt_data->ct); +#endif + + l4proto = nfct_get_attr_u8(evt_data->ct, ATTR_ORIG_L4PROTO); + if(IPPROTO_UDP != l4proto && IPPROTO_TCP != l4proto) + { + IPACMDBG("Received unexpected protocl %d conntrack message\n", l4proto); + } + else + { + ProcessTCPorUDPMsg(evt_data->ct, evt_data->type, l4proto); + } + + /* Cleanup item that was allocated during the original CT callback */ + nfct_destroy(evt_data->ct); + return; +} + + +/* conntrack send in host order and ipa expects in host order */ +void IPACM_ConntrackListener::ProcessTCPorUDPMsg( + struct nf_conntrack *ct, + enum nf_conntrack_msg_type type, + u_int8_t l4proto) +{ + nat_table_entry rule; + u_int8_t tcp_state; + uint32_t status = 0; + IPACM_Config *pConfig; + uint32_t orig_src_ip, orig_dst_ip; + bool isTempEntry = false; + + memset(&rule, 0, sizeof(rule)); + pConfig = IPACM_Config::GetInstance(); + if(pConfig == NULL) + { + IPACMERR("Unable to get Config instance\n"); + } + + IPACMDBG("Received type:%d with proto:%d\n", type, l4proto); + status = nfct_get_attr_u32(ct, ATTR_STATUS); + + /* Retrieve Protocol */ + rule.protocol = nfct_get_attr_u8(ct, ATTR_REPL_L4PROTO); + + if(IPS_DST_NAT & status) + { + status = IPS_DST_NAT; + } + else if(IPS_SRC_NAT & status) + { + status = IPS_SRC_NAT; + } + else + { + IPACMDBG("Neither Destination nor Source nat flag Set\n"); + orig_src_ip = nfct_get_attr_u32(ct, ATTR_ORIG_IPV4_SRC); + orig_src_ip = ntohl(orig_src_ip); + if(orig_src_ip == 0) + { + IPACMERR("unable to retrieve orig src ip address\n"); + return; + } + + orig_dst_ip = nfct_get_attr_u32(ct, ATTR_ORIG_IPV4_DST); + orig_dst_ip = ntohl(orig_dst_ip); + if(orig_dst_ip == 0) + { + IPACMERR("unable to retrieve orig dst ip address\n"); + return; + } + + if(orig_src_ip == wan_ipaddr) + { + IPACMDBG("orig src ip:0x%x equal to wan ip\n",orig_src_ip); + status = IPS_SRC_NAT; + } + else if(orig_dst_ip == wan_ipaddr) + { + IPACMDBG("orig Dst IP:0x%x equal to wan ip\n",orig_dst_ip); + status = IPS_DST_NAT; + } + else + { + IPACMDBG_H("Neither orig src ip:0x%x Nor orig Dst IP:0x%x equal to wan ip:0x%x\n", + orig_src_ip, orig_dst_ip, wan_ipaddr); + +#ifdef CT_OPT + if(p_lan2lan == NULL) + { + IPACMERR("Lan2Lan Instance is null\n"); + goto IGNORE; + } + + ipacm_event_connection lan2lan_conn = { 0 }; + lan2lan_conn.iptype = IPA_IP_v4; + lan2lan_conn.src_ipv4_addr = orig_src_ip; + lan2lan_conn.dst_ipv4_addr = orig_dst_ip; + + if(((IPPROTO_UDP == rule.protocol) && (NFCT_T_NEW == type)) || + ((IPPROTO_TCP == rule.protocol) && (nfct_get_attr_u8(ct, ATTR_TCP_STATE) == TCP_CONNTRACK_ESTABLISHED))) + { + p_lan2lan->handle_new_connection(&lan2lan_conn); + } + else if((IPPROTO_UDP == rule.protocol && NFCT_T_DESTROY == type) || + (IPPROTO_TCP == rule.protocol && + nfct_get_attr_u8(ct, ATTR_TCP_STATE) == TCP_CONNTRACK_FIN_WAIT)) + { + p_lan2lan->handle_del_connection(&lan2lan_conn); + } +#endif + return; + } + } + + if(IPS_DST_NAT == status) + { + IPACMDBG("Destination NAT\n"); + rule.dst_nat = true; + + IPACMDBG("Parse reply tuple\n"); + rule.target_ip = nfct_get_attr_u32(ct, ATTR_ORIG_IPV4_SRC); + rule.target_ip = ntohl(rule.target_ip); + + /* Retriev target/dst port */ + rule.target_port = nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC); + rule.target_port = ntohs(rule.target_port); + if(0 == rule.target_port) + { + IPACMDBG("unable to retrieve target port\n"); + } + + rule.public_port = nfct_get_attr_u16(ct, ATTR_ORIG_PORT_DST); + rule.public_port = ntohs(rule.public_port); + + /* Retriev src/private ip address */ + rule.private_ip = nfct_get_attr_u32(ct, ATTR_REPL_IPV4_SRC); + rule.private_ip = ntohl(rule.private_ip); + if(0 == rule.private_ip) + { + IPACMDBG("unable to retrieve private ip address\n"); + } + + /* Retriev src/private port */ + rule.private_port = nfct_get_attr_u16(ct, ATTR_REPL_PORT_SRC); + rule.private_port = ntohs(rule.private_port); + if(0 == rule.private_port) + { + IPACMDBG("unable to retrieve private port\n"); + } + } + else if(IPS_SRC_NAT == status) + { + IPACMDBG("Source NAT\n"); + rule.dst_nat = false; + + /* Retriev target/dst ip address */ + IPACMDBG("Parse source tuple\n"); + rule.target_ip = nfct_get_attr_u32(ct, ATTR_ORIG_IPV4_DST); + rule.target_ip = ntohl(rule.target_ip); + if(0 == rule.target_ip) + { + IPACMDBG("unable to retrieve target ip address\n"); + } + /* Retriev target/dst port */ + rule.target_port = nfct_get_attr_u16(ct, ATTR_ORIG_PORT_DST); + rule.target_port = ntohs(rule.target_port); + if(0 == rule.target_port) + { + IPACMDBG("unable to retrieve target port\n"); + } + + /* Retriev public port */ + rule.public_port = nfct_get_attr_u16(ct, ATTR_REPL_PORT_DST); + rule.public_port = ntohs(rule.public_port); + if(0 == rule.public_port) + { + IPACMDBG("unable to retrieve public port\n"); + } + + /* Retriev src/private ip address */ + rule.private_ip = nfct_get_attr_u32(ct, ATTR_ORIG_IPV4_SRC); + rule.private_ip = ntohl(rule.private_ip); + if(0 == rule.private_ip) + { + IPACMDBG("unable to retrieve private ip address\n"); + } + + /* Retriev src/private port */ + rule.private_port = nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC); + rule.private_port = ntohs(rule.private_port); + if(0 == rule.private_port) + { + IPACMDBG("unable to retrieve private port\n"); + } + } + else + { + IPACMDBG("Neither source Nor destination nat\n"); + goto IGNORE; + } + + if(rule.private_ip != wan_ipaddr) + { + int cnt; + for(cnt = 0; cnt < MAX_NAT_IFACES; cnt++) + { + if(nat_iface_ipv4_addr[cnt] != 0) + { + if(rule.private_ip == nat_iface_ipv4_addr[cnt] || + rule.target_ip == nat_iface_ipv4_addr[cnt]) + { + IPACMDBG("matched nat_iface_ipv4_addr entry(%d)\n", cnt); + iptodot("ProcessTCPorUDPMsg(): Nat entry match with ip addr", + nat_iface_ipv4_addr[cnt]); + break; + } + } + } + + if(cnt == MAX_NAT_IFACES) + { + IPACMDBG_H("Not mtaching with nat ifaces\n"); + if(pConfig == NULL) + { + goto IGNORE; + } + + if(pConfig->isPrivateSubnet(rule.private_ip) || + pConfig->isPrivateSubnet(rule.target_ip)) + { + IPACMDBG("Matching with Private subnet\n"); + isTempEntry = true; + } + else + { + goto IGNORE; + } + } + + } + else + { + if(isStaMode) { + IPACMDBG("In STA mode, ignore connections destinated to STA interface\n"); + goto IGNORE; + } + + IPACMDBG("For embedded connections add dummy nat rule\n"); + IPACMDBG("Change private port %d to %d\n", + rule.private_port, rule.public_port); + rule.private_port = rule.public_port; + } + + /* Check whether target is in STA client list or not + if not ignore the connection */ + int nCnt; + + if(!isStaMode || (StaClntCnt == 0)) + { + goto ADD; + } + + if((sta_clnt_ipv4_addr[0] & 0xFFFFFF00) != + (rule.target_ip & 0xFFFFFF00)) + { + IPACMDBG("STA client subnet mask not matching\n"); + goto ADD; + } + + IPACMDBG("StaClntCnt %d\n", StaClntCnt); + for(nCnt = 0; nCnt < StaClntCnt; nCnt++) + { + IPACMDBG("Comparing trgt_ip 0x%x with sta clnt ip: 0x%x\n", + rule.target_ip, sta_clnt_ipv4_addr[nCnt]); + if(rule.target_ip == sta_clnt_ipv4_addr[nCnt]) + { + IPACMDBG("Match index %d\n", nCnt); + goto ADD; + } + } + + IPACMDBG_H("Not matching with STA Clnt Ip Addrs 0x%x\n", + rule.target_ip); + isTempEntry = true; + + +ADD: + IPACMDBG_H("Nat Entry with below information will either be added or deleted\n"); + iptodot("target ip or dst ip", rule.target_ip); + IPACMDBG("target port or dst port: 0x%x Decimal:%d\n", rule.target_port, rule.target_port); + iptodot("private ip or src ip", rule.private_ip); + IPACMDBG("private port or src port: 0x%x, Decimal:%d\n", rule.private_port, rule.private_port); + IPACMDBG("public port or reply dst port: 0x%x, Decimal:%d\n", rule.public_port, rule.public_port); + IPACMDBG("Protocol: %d, destination nat flag: %d\n", rule.protocol, rule.dst_nat); + + rule.public_ip = wan_ipaddr; + if(IPPROTO_TCP == rule.protocol) + { + if(nat_inst == NULL) + { + return; + } + + tcp_state = nfct_get_attr_u8(ct, ATTR_TCP_STATE); + if(TCP_CONNTRACK_ESTABLISHED == tcp_state) + { + IPACMDBG("TCP state TCP_CONNTRACK_ESTABLISHED(%d)\n", tcp_state); + if(!CtList->isWanUp()) + { + IPACMDBG("Wan is not up, cache connections\n"); + nat_inst->CacheEntry(&rule); + } + else if(isTempEntry) + { + nat_inst->AddTempEntry(&rule); + } + else + { + nat_inst->AddEntry(&rule); + } + } + else if(TCP_CONNTRACK_FIN_WAIT == tcp_state || + type == NFCT_T_DESTROY) + { + IPACMDBG("TCP state TCP_CONNTRACK_FIN_WAIT(%d) " + "or type NFCT_T_DESTROY(%d)\n", tcp_state, type); + + nat_inst->DeleteEntry(&rule); + nat_inst->DeleteTempEntry(&rule); + } + else + { + IPACMDBG("Ignore tcp state: %d and type: %d\n", tcp_state, type); + } + + } + else if(IPPROTO_UDP == rule.protocol) + { + if(nat_inst == NULL) + { + return; + } + + if(NFCT_T_NEW == type) + { + IPACMDBG("New UDP connection at time %ld\n", time(NULL)); + if(!CtList->isWanUp()) + { + IPACMDBG("Wan is not up, cache connections\n"); + nat_inst->CacheEntry(&rule); + } + else if(isTempEntry) + { + nat_inst->AddTempEntry(&rule); + } + else + { + nat_inst->AddEntry(&rule); + } + } + else if(NFCT_T_DESTROY == type) + { + IPACMDBG("UDP connection close at time %ld\n", time(NULL)); + nat_inst->DeleteEntry(&rule); + nat_inst->DeleteTempEntry(&rule); + } + } + else + { + IPACMDBG("Ignore protocol: %d and type: %d\n", rule.protocol, type); + } + + return; + +IGNORE: + IPACMDBG_H("ignoring below Nat Entry\n"); + iptodot("target ip or dst ip", rule.target_ip); + IPACMDBG("target port or dst port: 0x%x Decimal:%d\n", rule.target_port, rule.target_port); + iptodot("private ip or src ip", rule.private_ip); + IPACMDBG("private port or src port: 0x%x, Decimal:%d\n", rule.private_port, rule.private_port); + IPACMDBG("public port or reply dst port: 0x%x, Decimal:%d\n", rule.public_port, rule.public_port); + IPACMDBG("Protocol: %d, destination nat flag: %d\n", rule.protocol, rule.dst_nat); + + return; +} + +void IPACM_ConntrackListener::HandleSTAClientAddEvt(uint32_t clnt_ip_addr) +{ + int cnt; + IPACMDBG_H("Received STA client 0x%x\n", clnt_ip_addr); + + if(StaClntCnt >= MAX_STA_CLNT_IFACES) + { + IPACMDBG("Max STA client reached, ignore 0x%x\n", clnt_ip_addr); + return; + } + + for(cnt=0; cntFlushTempEntries(clnt_ip_addr, true); + return; +} + +void IPACM_ConntrackListener::HandleSTAClientDelEvt(uint32_t clnt_ip_addr) +{ + int cnt; + IPACMDBG_H("Received STA client 0x%x\n", clnt_ip_addr); + + for(cnt=0; cntDelEntriesOnSTAClntDiscon(clnt_ip_addr); + StaClntCnt--; + IPACMDBG("STA client cnt %d\n", StaClntCnt); + break; + } + } + + nat_inst->FlushTempEntries(clnt_ip_addr, false); + return; +} diff --git a/data-ipa-cfg-mgr/ipacm/src/IPACM_Conntrack_NATApp.cpp b/data-ipa-cfg-mgr/ipacm/src/IPACM_Conntrack_NATApp.cpp new file mode 100644 index 000000000..6efb47598 --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/src/IPACM_Conntrack_NATApp.cpp @@ -0,0 +1,958 @@ +/* +Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +#include "IPACM_Conntrack_NATApp.h" +#include "IPACM_ConntrackClient.h" + +#define INVALID_IP_ADDR 0x0 + +/* NatApp class Implementation */ +NatApp *NatApp::pInstance = NULL; +NatApp::NatApp() +{ + max_entries = 0; + cache = NULL; + + nat_table_hdl = 0; + pub_ip_addr = 0; + + curCnt = 0; + + pALGPorts = NULL; + nALGPort = 0; + + ct = NULL; + ct_hdl = NULL; + + memset(temp, 0, sizeof(temp)); +} + +int NatApp::Init(void) +{ + IPACM_Config *pConfig; + int size = 0; + + pConfig = IPACM_Config::GetInstance(); + if(pConfig == NULL) + { + IPACMERR("Unable to get Config instance\n"); + return -1; + } + + max_entries = pConfig->GetNatMaxEntries(); + + size = (sizeof(nat_table_entry) * max_entries); + cache = (nat_table_entry *)malloc(size); + if(cache == NULL) + { + IPACMERR("Unable to allocate memory for cache\n"); + goto fail; + } + IPACMDBG("Allocated %d bytes for config manager nat cache\n", size); + memset(cache, 0, size); + + nALGPort = pConfig->GetAlgPortCnt(); + if(nALGPort > 0) + { + pALGPorts = (ipacm_alg *)malloc(sizeof(ipacm_alg) * nALGPort); + if(pALGPorts == NULL) + { + IPACMERR("Unable to allocate memory for alg prots\n"); + goto fail; + } + memset(pALGPorts, 0, sizeof(ipacm_alg) * nALGPort); + + if(pConfig->GetAlgPorts(nALGPort, pALGPorts) != 0) + { + IPACMERR("Unable to retrieve ALG prots\n"); + goto fail; + } + + IPACMDBG("Printing %d alg ports information\n", nALGPort); + for(int cnt=0; cntInit()) + { + delete pInstance; + return NULL; + } + } + + return pInstance; +} + +/* NAT APP related object function definitions */ + +int NatApp::AddTable(uint32_t pub_ip) +{ + int ret; + int cnt = 0; + ipa_nat_ipv4_rule nat_rule; + IPACMDBG_H("%s() %d\n", __FUNCTION__, __LINE__); + + /* Not reset the cache wait it timeout by destroy event */ +#if 0 + if (pub_ip != pub_ip_addr_pre) + { + IPACMDBG("Reset the cache because NAT-ipv4 different\n"); + memset(cache, 0, sizeof(nat_table_entry) * max_entries); + curCnt = 0; + } +#endif + ret = ipa_nat_add_ipv4_tbl(pub_ip, max_entries, &nat_table_hdl); + if(ret) + { + IPACMERR("unable to create nat table Error:%d\n", ret); + return ret; + } + + /* Add back the cashed NAT-entry */ + if (pub_ip == pub_ip_addr_pre) + { + IPACMDBG("Restore the cache to ipa NAT-table\n"); + for(cnt = 0; cnt < max_entries; cnt++) + { + if(cache[cnt].private_ip !=0) + { + memset(&nat_rule, 0 , sizeof(nat_rule)); + nat_rule.private_ip = cache[cnt].private_ip; + nat_rule.target_ip = cache[cnt].target_ip; + nat_rule.target_port = cache[cnt].target_port; + nat_rule.private_port = cache[cnt].private_port; + nat_rule.public_port = cache[cnt].public_port; + nat_rule.protocol = cache[cnt].protocol; + + if(ipa_nat_add_ipv4_rule(nat_table_hdl, &nat_rule, &cache[cnt].rule_hdl) < 0) + { + IPACMERR("unable to add the rule delete from cache\n"); + memset(&cache[cnt], 0, sizeof(cache[cnt])); + curCnt--; + continue; + } + cache[cnt].enabled = true; + + IPACMDBG("On wan-iface reset added below rule successfully\n"); + iptodot("Private IP", nat_rule.private_ip); + iptodot("Target IP", nat_rule.target_ip); + IPACMDBG("Private Port:%d \t Target Port: %d\t", nat_rule.private_port, nat_rule.target_port); + IPACMDBG("Public Port:%d\n", nat_rule.public_port); + IPACMDBG("protocol: %d\n", nat_rule.protocol); + } + } + } + + pub_ip_addr = pub_ip; + return 0; +} + +void NatApp::Reset() +{ + int cnt = 0; + + nat_table_hdl = 0; + pub_ip_addr = 0; + /* NAT tbl deleted, reset enabled bit */ + for(cnt = 0; cnt < max_entries; cnt++) + { + cache[cnt].enabled ==false; + } +} + +int NatApp::DeleteTable(uint32_t pub_ip) +{ + int ret; + IPACMDBG_H("%s() %d\n", __FUNCTION__, __LINE__); + + CHK_TBL_HDL(); + + if(pub_ip_addr != pub_ip) + { + IPACMDBG("Public ip address is not matching\n"); + IPACMERR("unable to delete the nat table\n"); + return -1; + } + + ret = ipa_nat_del_ipv4_tbl(nat_table_hdl); + if(ret) + { + IPACMERR("unable to delete nat table Error: %d\n", ret);; + return ret; + } + + pub_ip_addr_pre = pub_ip_addr; + Reset(); + return 0; +} + +/* Check for duplicate entries */ +bool NatApp::ChkForDup(const nat_table_entry *rule) +{ + int cnt = 0; + IPACMDBG("%s() %d\n", __FUNCTION__, __LINE__); + + for(; cnt < max_entries; cnt++) + { + if(cache[cnt].private_ip == rule->private_ip && + cache[cnt].target_ip == rule->target_ip && + cache[cnt].private_port == rule->private_port && + cache[cnt].target_port == rule->target_port && + cache[cnt].protocol == rule->protocol) + { + log_nat(rule->protocol,rule->private_ip,rule->target_ip,rule->private_port,\ + rule->target_port,"Duplicate Rule"); + return true; + } + } + + return false; +} + +/* Delete the entry from Nat table on connection close */ +int NatApp::DeleteEntry(const nat_table_entry *rule) +{ + int cnt = 0; + IPACMDBG("%s() %d\n", __FUNCTION__, __LINE__); + + log_nat(rule->protocol,rule->private_ip,rule->target_ip,rule->private_port,\ + rule->target_port,"for deletion"); + + + for(; cnt < max_entries; cnt++) + { + if(cache[cnt].private_ip == rule->private_ip && + cache[cnt].target_ip == rule->target_ip && + cache[cnt].private_port == rule->private_port && + cache[cnt].target_port == rule->target_port && + cache[cnt].protocol == rule->protocol) + { + + if(cache[cnt].enabled == true) + { + if(ipa_nat_del_ipv4_rule(nat_table_hdl, cache[cnt].rule_hdl) < 0) + { + IPACMERR("%s() %d deletion failed\n", __FUNCTION__, __LINE__); + } + + IPACMDBG_H("Deleted Nat entry(%d) Successfully\n", cnt); + } + else + { + IPACMDBG_H("Deleted Nat entry(%d) only from cache\n", cnt); + } + + memset(&cache[cnt], 0, sizeof(cache[cnt])); + curCnt--; + break; + } + } + + return 0; +} + +/* Add new entry to the nat table on new connection */ +int NatApp::AddEntry(const nat_table_entry *rule) +{ + + int cnt = 0; + ipa_nat_ipv4_rule nat_rule; + IPACMDBG("%s() %d\n", __FUNCTION__, __LINE__); + + CHK_TBL_HDL(); + log_nat(rule->protocol,rule->private_ip,rule->target_ip,rule->private_port,\ + rule->target_port,"for addition"); + if(isAlgPort(rule->protocol, rule->private_port) || + isAlgPort(rule->protocol, rule->target_port)) + { + IPACMERR("connection using ALG Port, ignore\n"); + return -1; + } + + if(rule->private_ip == 0 || + rule->target_ip == 0 || + rule->private_port == 0 || + rule->target_port == 0 || + rule->protocol == 0) + { + IPACMERR("Invalid Connection, ignoring it\n"); + return 0; + } + + if(!ChkForDup(rule)) + { + for(; cnt < max_entries; cnt++) + { + if(cache[cnt].private_ip == 0 && + cache[cnt].target_ip == 0 && + cache[cnt].private_port == 0 && + cache[cnt].target_port == 0 && + cache[cnt].protocol == 0) + { + break; + } + } + + if(max_entries == cnt) + { + IPACMERR("Error: Unable to add, reached maximum rules\n"); + return -1; + } + else + { + nat_rule.private_ip = rule->private_ip; + nat_rule.target_ip = rule->target_ip; + nat_rule.target_port = rule->target_port; + nat_rule.private_port = rule->private_port; + nat_rule.public_port = rule->public_port; + nat_rule.protocol = rule->protocol; + + if(isPwrSaveIf(rule->private_ip) || + isPwrSaveIf(rule->target_ip)) + { + IPACMDBG("Device is Power Save mode: Dont insert into nat table but cache\n"); + cache[cnt].enabled = false; + cache[cnt].rule_hdl = 0; + } + else + { + + if(ipa_nat_add_ipv4_rule(nat_table_hdl, &nat_rule, &cache[cnt].rule_hdl) < 0) + { + IPACMERR("unable to add the rule\n"); + return -1; + } + + cache[cnt].enabled = true; + } + + cache[cnt].private_ip = rule->private_ip; + cache[cnt].target_ip = rule->target_ip; + cache[cnt].target_port = rule->target_port; + cache[cnt].private_port = rule->private_port; + cache[cnt].protocol = rule->protocol; + cache[cnt].timestamp = 0; + cache[cnt].public_port = rule->public_port; + cache[cnt].dst_nat = rule->dst_nat; + curCnt++; + } + + } + else + { + IPACMERR("Duplicate rule. Ignore it\n"); + return -1; + } + + if(cache[cnt].enabled == true) + { + IPACMDBG_H("Added rule(%d) successfully\n", cnt); + } + else + { + IPACMDBG_H("Cached rule(%d) successfully\n", cnt); + } + + return 0; +} + +void NatApp::UpdateCTUdpTs(nat_table_entry *rule, uint32_t new_ts) +{ + int ret; + + iptodot("Private IP:", rule->private_ip); + iptodot("Target IP:", rule->target_ip); + IPACMDBG("Private Port: %d, Target Port: %d\n", rule->private_port, rule->target_port); + + if(!ct_hdl) + { + ct_hdl = nfct_open(CONNTRACK, 0); + if(!ct_hdl) + { + PERROR("nfct_open"); + return; + } + } + + if(!ct) + { + ct = nfct_new(); + if(!ct) + { + PERROR("nfct_new"); + return; + } + } + + nfct_set_attr_u8(ct, ATTR_L3PROTO, AF_INET); + if(rule->protocol == IPPROTO_UDP) + { + nfct_set_attr_u8(ct, ATTR_L4PROTO, rule->protocol); + nfct_set_attr_u32(ct, ATTR_TIMEOUT, udp_timeout); + } + else + { + nfct_set_attr_u8(ct, ATTR_L4PROTO, rule->protocol); + nfct_set_attr_u32(ct, ATTR_TIMEOUT, tcp_timeout); + } + + if(rule->dst_nat == false) + { + nfct_set_attr_u32(ct, ATTR_IPV4_SRC, htonl(rule->private_ip)); + nfct_set_attr_u16(ct, ATTR_PORT_SRC, htons(rule->private_port)); + + nfct_set_attr_u32(ct, ATTR_IPV4_DST, htonl(rule->target_ip)); + nfct_set_attr_u16(ct, ATTR_PORT_DST, htons(rule->target_port)); + + IPACMDBG("dst nat is not set\n"); + } + else + { + nfct_set_attr_u32(ct, ATTR_IPV4_SRC, htonl(rule->target_ip)); + nfct_set_attr_u16(ct, ATTR_PORT_SRC, htons(rule->target_port)); + + nfct_set_attr_u32(ct, ATTR_IPV4_DST, htonl(pub_ip_addr)); + nfct_set_attr_u16(ct, ATTR_PORT_DST, htons(rule->public_port)); + + IPACMDBG("dst nat is set\n"); + } + + iptodot("Source IP:", nfct_get_attr_u32(ct, ATTR_IPV4_SRC)); + iptodot("Destination IP:", nfct_get_attr_u32(ct, ATTR_IPV4_DST)); + IPACMDBG("Source Port: %d, Destination Port: %d\n", + nfct_get_attr_u16(ct, ATTR_PORT_SRC), nfct_get_attr_u16(ct, ATTR_PORT_DST)); + + IPACMDBG("updating %d connection with time: %d\n", + rule->protocol, nfct_get_attr_u32(ct, ATTR_TIMEOUT)); + + ret = nfct_query(ct_hdl, NFCT_Q_UPDATE, ct); + if(ret == -1) + { + IPACMERR("unable to update time stamp"); + DeleteEntry(rule); + } + else + { + rule->timestamp = new_ts; + IPACMDBG("Updated time stamp successfully\n"); + } + + return; +} + +void NatApp::UpdateUDPTimeStamp() +{ + int cnt; + uint32_t ts; + bool read_to = false; + + for(cnt = 0; cnt < max_entries; cnt++) + { + ts = 0; + if(cache[cnt].enabled == true) + { + IPACMDBG("\n"); + if(ipa_nat_query_timestamp(nat_table_hdl, cache[cnt].rule_hdl, &ts) < 0) + { + IPACMERR("unable to retrieve timeout for rule hanle: %d\n", cache[cnt].rule_hdl); + continue; + } + + if(cache[cnt].timestamp == ts) + { + IPACMDBG("No Change in Time Stamp: cahce:%d, ipahw:%d\n", + cache[cnt].timestamp, ts); + continue; + } + + if (read_to == false) { + read_to = true; + Read_TcpUdp_Timeout(); + } + + UpdateCTUdpTs(&cache[cnt], ts); + } /* end of outer if */ + + } /* end of for loop */ + +} + +bool NatApp::isAlgPort(uint8_t proto, uint16_t port) +{ + int cnt; + for(cnt = 0; cnt < nALGPort; cnt++) + { + if(proto == pALGPorts[cnt].protocol && + port == pALGPorts[cnt].port) + { + return true; + } + } + + return false; +} + +bool NatApp::isPwrSaveIf(uint32_t ip_addr) +{ + int cnt; + + for(cnt = 0; cnt < IPA_MAX_NUM_WIFI_CLIENTS; cnt++) + { + if(0 != PwrSaveIfs[cnt] && + ip_addr == PwrSaveIfs[cnt]) + { + return true; + } + } + + return false; +} + +int NatApp::UpdatePwrSaveIf(uint32_t client_lan_ip) +{ + int cnt; + IPACMDBG_H("Received IP address: 0x%x\n", client_lan_ip); + + if(client_lan_ip == INVALID_IP_ADDR) + { + IPACMERR("Invalid ip address received\n"); + return -1; + } + + /* check for duplicate events */ + for(cnt = 0; cnt < IPA_MAX_NUM_WIFI_CLIENTS; cnt++) + { + if(PwrSaveIfs[cnt] == client_lan_ip) + { + IPACMDBG("The client 0x%x is already in power save\n", client_lan_ip); + return 0; + } + } + + for(cnt = 0; cnt < IPA_MAX_NUM_WIFI_CLIENTS; cnt++) + { + if(PwrSaveIfs[cnt] == 0) + { + PwrSaveIfs[cnt] = client_lan_ip; + break; + } + } + + for(cnt = 0; cnt < max_entries; cnt++) + { + if(cache[cnt].private_ip == client_lan_ip && + cache[cnt].enabled == true) + { + if(ipa_nat_del_ipv4_rule(nat_table_hdl, cache[cnt].rule_hdl) < 0) + { + IPACMERR("unable to delete the rule\n"); + continue; + } + + cache[cnt].enabled = false; + cache[cnt].rule_hdl = 0; + } + } + + return 0; +} + +int NatApp::ResetPwrSaveIf(uint32_t client_lan_ip) +{ + int cnt; + ipa_nat_ipv4_rule nat_rule; + + IPACMDBG_H("Received ip address: 0x%x\n", client_lan_ip); + + if(client_lan_ip == INVALID_IP_ADDR) + { + IPACMERR("Invalid ip address received\n"); + return -1; + } + + for(cnt = 0; cnt < IPA_MAX_NUM_WIFI_CLIENTS; cnt++) + { + if(PwrSaveIfs[cnt] == client_lan_ip) + { + PwrSaveIfs[cnt] = 0; + break; + } + } + + for(cnt = 0; cnt < max_entries; cnt++) + { + IPACMDBG("cache (%d): enable %d, ip 0x%x\n", cnt, cache[cnt].enabled, cache[cnt].private_ip); + + if(cache[cnt].private_ip == client_lan_ip && + cache[cnt].enabled == false) + { + memset(&nat_rule, 0 , sizeof(nat_rule)); + nat_rule.private_ip = cache[cnt].private_ip; + nat_rule.target_ip = cache[cnt].target_ip; + nat_rule.target_port = cache[cnt].target_port; + nat_rule.private_port = cache[cnt].private_port; + nat_rule.public_port = cache[cnt].public_port; + nat_rule.protocol = cache[cnt].protocol; + + if(ipa_nat_add_ipv4_rule(nat_table_hdl, &nat_rule, &cache[cnt].rule_hdl) < 0) + { + IPACMERR("unable to add the rule delete from cache\n"); + memset(&cache[cnt], 0, sizeof(cache[cnt])); + curCnt--; + continue; + } + cache[cnt].enabled = true; + + IPACMDBG("On power reset added below rule successfully\n"); + iptodot("Private IP", nat_rule.private_ip); + iptodot("Target IP", nat_rule.target_ip); + IPACMDBG("Private Port:%d \t Target Port: %d\t", nat_rule.private_port, nat_rule.target_port); + IPACMDBG("Public Port:%d\n", nat_rule.public_port); + IPACMDBG("protocol: %d\n", nat_rule.protocol); + + } + } + + return -1; +} + +uint32_t NatApp::GetTableHdl(uint32_t in_ip_addr) +{ + if(in_ip_addr == pub_ip_addr) + { + return nat_table_hdl; + } + + return -1; +} + +void NatApp::AddTempEntry(const nat_table_entry *new_entry) +{ + int cnt; + + IPACMDBG("Received below Temp Nat entry\n"); + iptodot("Private IP", new_entry->private_ip); + iptodot("Target IP", new_entry->target_ip); + IPACMDBG("Private Port: %d\t Target Port: %d\t", new_entry->private_port, new_entry->target_port); + IPACMDBG("protocolcol: %d\n", new_entry->protocol); + + if(isAlgPort(new_entry->protocol, new_entry->private_port) || + isAlgPort(new_entry->protocol, new_entry->target_port)) + { + IPACMDBG("connection using ALG Port. Dont insert into nat cache\n"); + return; + } + + if(ChkForDup(new_entry)) + { + return; + } + + for(cnt=0; cntprivate_ip && + temp[cnt].target_ip == new_entry->target_ip && + temp[cnt].private_port == new_entry->private_port && + temp[cnt].target_port == new_entry->target_port && + temp[cnt].protocol == new_entry->protocol) + { + IPACMDBG("Received duplicate Temp entry\n"); + return; + } + } + + for(cnt=0; cntprivate_ip); + iptodot("Target IP", entry->target_ip); + IPACMDBG("Private Port: %d\t Target Port: %d\t", entry->private_port, entry->target_port); + IPACMDBG("protocolcol: %d\n", entry->protocol); + + for(cnt=0; cntprivate_ip && + temp[cnt].target_ip == entry->target_ip && + temp[cnt].private_port == entry->private_port && + temp[cnt].target_port == entry->target_port && + temp[cnt].protocol == entry->protocol) + { + memset(&temp[cnt], 0, sizeof(nat_table_entry)); + IPACMDBG("Delete Temp Entry\n"); + return; + } + } + + IPACMDBG("No Such Temp Entry exists\n"); + return; +} + +void NatApp::FlushTempEntries(uint32_t ip_addr, bool isAdd) +{ + int cnt; + int ret; + + IPACMDBG_H("Received below with isAdd:%d ", isAdd); + IPACMDBG_H("IP Address: (ox%x)\n", ip_addr); + + for(cnt=0; cntprivate_ip == 0 || + rule->target_ip == 0 || + rule->private_port == 0 || + rule->target_port == 0 || + rule->protocol == 0) + { + IPACMERR("Invalid Connection, ignoring it\n"); + return; + } + + if(!ChkForDup(rule)) + { + for(; cnt < max_entries; cnt++) + { + if(cache[cnt].private_ip == 0 && + cache[cnt].target_ip == 0 && + cache[cnt].private_port == 0 && + cache[cnt].target_port == 0 && + cache[cnt].protocol == 0) + { + break; + } + } + + if(max_entries == cnt) + { + IPACMERR("Error: Unable to add, reached maximum rules\n"); + return; + } + else + { + cache[cnt].enabled = false; + cache[cnt].rule_hdl = 0; + cache[cnt].private_ip = rule->private_ip; + cache[cnt].target_ip = rule->target_ip; + cache[cnt].target_port = rule->target_port; + cache[cnt].private_port = rule->private_port; + cache[cnt].protocol = rule->protocol; + cache[cnt].timestamp = 0; + cache[cnt].public_port = rule->public_port; + cache[cnt].public_ip = rule->public_ip; + cache[cnt].dst_nat = rule->dst_nat; + curCnt++; + } + + } + else + { + IPACMERR("Duplicate rule. Ignore it\n"); + return; + } + + IPACMDBG("Cached rule(%d) successfully\n", cnt); + return; +} + +void NatApp::Read_TcpUdp_Timeout(void) { + FILE *udp_fd = NULL, *tcp_fd = NULL; + + /* Read UDP timeout value */ + udp_fd = fopen(IPACM_UDP_FULL_FILE_NAME, "r"); + if (udp_fd == NULL) { + IPACMERR("unable to open %s\n", IPACM_UDP_FULL_FILE_NAME); + goto fail; + } + + if (fscanf(udp_fd, "%d", &udp_timeout) != 1) { + IPACMERR("Error reading udp timeout\n"); + } + IPACMDBG_H("udp timeout value: %d\n", udp_timeout); + + + /* Read TCP timeout value */ + tcp_fd = fopen(IPACM_TCP_FULL_FILE_NAME, "r"); + if (tcp_fd == NULL) { + IPACMERR("unable to open %s\n", IPACM_TCP_FULL_FILE_NAME); + goto fail; + } + + + if (fscanf(tcp_fd, "%d", &tcp_timeout) != 1) { + IPACMERR("Error reading tcp timeout\n"); + } + IPACMDBG_H("tcp timeout value: %d\n", tcp_timeout); + +fail: + if (udp_fd) { + fclose(udp_fd); + } + if (tcp_fd) { + fclose(tcp_fd); + } + + return; +} diff --git a/data-ipa-cfg-mgr/ipacm/src/IPACM_EvtDispatcher.cpp b/data-ipa-cfg-mgr/ipacm/src/IPACM_EvtDispatcher.cpp new file mode 100644 index 000000000..11782dfb0 --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/src/IPACM_EvtDispatcher.cpp @@ -0,0 +1,206 @@ +/* +Copyright (c) 2013, The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +/*! + @file + IPACM_EvtDispatcher.cpp + + @brief + This file implements the IPAM event dispatcher functionality + + @Author + +*/ +#include +#include +#include +#include +#include "IPACM_CmdQueue.h" +#include "IPACM_Defs.h" + + +extern pthread_mutex_t mutex; +extern pthread_cond_t cond_var; + +cmd_evts *IPACM_EvtDispatcher::head = NULL; +extern uint32_t ipacm_event_stats[IPACM_EVENT_MAX]; + +int IPACM_EvtDispatcher::PostEvt +( + ipacm_cmd_q_data *data +) +{ + Message *item = NULL; + MessageQueue *MsgQueue = NULL; + + MsgQueue = MessageQueue::getInstance(); + if(MsgQueue == NULL) + { + IPACMERR("unable to retrieve MsgQueue instance\n"); + return IPACM_FAILURE; + } + + item = new Message(); + if(item == NULL) + { + IPACMERR("unable to create new message item\n"); + return IPACM_FAILURE; + } + + IPACMDBG("Populating item to post to queue\n"); + item->evt.callback_ptr = IPACM_EvtDispatcher::ProcessEvt; + memcpy(&item->evt.data, data, sizeof(ipacm_cmd_q_data)); + + if(pthread_mutex_lock(&mutex) != 0) + { + IPACMERR("unable to lock the mutex\n"); + return IPACM_FAILURE; + } + + IPACMDBG("Enqueing item\n"); + MsgQueue->enqueue(item); + IPACMDBG("Enqueued item %p\n", item); + + if(pthread_cond_signal(&cond_var) != 0) + { + IPACMDBG("unable to lock the mutex\n"); + /* Release the mutex before you return failure */ + if(pthread_mutex_unlock(&mutex) != 0) + { + IPACMERR("unable to unlock the mutex\n"); + return IPACM_FAILURE; + } + return IPACM_FAILURE; + } + + if(pthread_mutex_unlock(&mutex) != 0) + { + IPACMERR("unable to unlock the mutex\n"); + return IPACM_FAILURE; + } + + return IPACM_SUCCESS; +} + +void IPACM_EvtDispatcher::ProcessEvt(ipacm_cmd_q_data *data) +{ + + cmd_evts *tmp = head, tmp1; + + if(head == NULL) + { + IPACMDBG("Queue is empty\n"); + } + + while(tmp != NULL) + { + memcpy(&tmp1, tmp, sizeof(tmp1)); + if(data->event == tmp1.event) + { + ipacm_event_stats[data->event]++; + tmp1.obj->event_callback(data->event, data->evt_data); + IPACMDBG(" Find matched registered events\n"); + } + tmp = tmp1.next; + } + + IPACMDBG(" Finished process events\n"); + + if(data->evt_data != NULL) + { + IPACMDBG("free the event:%d data: %p\n", data->event, data->evt_data); + free(data->evt_data); + } + return; +} + +int IPACM_EvtDispatcher::registr(ipa_cm_event_id event, IPACM_Listener *obj) +{ + cmd_evts *tmp = head,*nw; + + nw = (cmd_evts *)malloc(sizeof(cmd_evts)); + if(nw != NULL) + { + nw->event = event; + nw->obj = obj; + nw->next = NULL; + } + else + { + return IPACM_FAILURE; + } + + if(head == NULL) + { + head = nw; + } + else + { + while(tmp->next) + { + tmp = tmp->next; + } + tmp->next = nw; + } + return IPACM_SUCCESS; +} + + +int IPACM_EvtDispatcher::deregistr(IPACM_Listener *param) +{ + cmd_evts *tmp = head,*tmp1,*prev = head; + + while(tmp != NULL) + { + if(tmp->obj == param) + { + tmp1 = tmp; + if(tmp == head) + { + head = head->next; + } + else if(tmp->next == NULL) + { + prev->next = NULL; + } + else + { + prev->next = tmp->next; + } + + tmp = tmp->next; + free(tmp1); + } + else + { + prev = tmp; + tmp = tmp->next; + } + } + return IPACM_SUCCESS; +} diff --git a/data-ipa-cfg-mgr/ipacm/src/IPACM_Filtering.cpp b/data-ipa-cfg-mgr/ipacm/src/IPACM_Filtering.cpp new file mode 100644 index 000000000..bd8dadb38 --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/src/IPACM_Filtering.cpp @@ -0,0 +1,454 @@ +/* +Copyright (c) 2013, The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +/*! + @file + IPACM_Filtering.cpp + + @brief + This file implements the IPACM filtering functionality. + + @Author + Skylar Chang + +*/ +#include +#include +#include +#include +#include + +#include "IPACM_Filtering.h" +#include +#include "IPACM_Defs.h" + + +const char *IPACM_Filtering::DEVICE_NAME = "/dev/ipa"; + +IPACM_Filtering::IPACM_Filtering() +{ + fd = open(DEVICE_NAME, O_RDWR); + if (fd < 0) + { + IPACMERR("Failed opening %s.\n", DEVICE_NAME); + } +} + +IPACM_Filtering::~IPACM_Filtering() +{ + close(fd); +} + +bool IPACM_Filtering::DeviceNodeIsOpened() +{ + return fd; +} + +bool IPACM_Filtering::AddFilteringRule(struct ipa_ioc_add_flt_rule const *ruleTable) +{ + int retval = 0; + + IPACMDBG("Printing filter add attributes\n"); + IPACMDBG("ip type: %d\n", ruleTable->ip); + IPACMDBG("Number of rules: %d\n", ruleTable->num_rules); + IPACMDBG("End point: %d and global value: %d\n", ruleTable->ep, ruleTable->global); + IPACMDBG("commit value: %d\n", ruleTable->commit); + for (int cnt=0; cntnum_rules; cnt++) + { + IPACMDBG("Filter rule:%d attrib mask: 0x%x\n", + cnt, + ruleTable->rules[cnt].rule.attrib.attrib_mask); + } + + retval = ioctl(fd, IPA_IOC_ADD_FLT_RULE, ruleTable); + if (retval != 0) + { + IPACMERR("Failed adding Filtering rule %p\n", ruleTable); + PERROR("unable to add filter rule:"); + + for (int cnt = 0; cnt < ruleTable->num_rules; cnt++) + { + if (ruleTable->rules[cnt].status != 0) + { + IPACMERR("Adding Filter rule:%d failed with status:%d\n", + cnt, ruleTable->rules[cnt].status); + } + } + return false; + } + + for (int cnt = 0; cntnum_rules; cnt++) + { + if(ruleTable->rules[cnt].status != 0) + { + IPACMERR("Adding Filter rule:%d failed with status:%d\n", + cnt, ruleTable->rules[cnt].status); + } + } + + IPACMDBG("Added Filtering rule %p\n", ruleTable); + return true; +} + +bool IPACM_Filtering::DeleteFilteringRule(struct ipa_ioc_del_flt_rule *ruleTable) +{ + int retval = 0; + + retval = ioctl(fd, IPA_IOC_DEL_FLT_RULE, ruleTable); + if (retval != 0) + { + IPACMERR("Failed deleting Filtering rule %p\n", ruleTable); + return false; + } + + IPACMDBG("Deleted Filtering rule %p\n", ruleTable); + return true; +} + +bool IPACM_Filtering::Commit(enum ipa_ip_type ip) +{ + int retval = 0; + + retval = ioctl(fd, IPA_IOC_COMMIT_FLT, ip); + if (retval != 0) + { + IPACMERR("failed committing Filtering rules.\n"); + return false; + } + + IPACMDBG("Committed Filtering rules to IPA HW.\n"); + return true; +} + +bool IPACM_Filtering::Reset(enum ipa_ip_type ip) +{ + int retval = 0; + + retval = ioctl(fd, IPA_IOC_RESET_FLT, ip); + retval |= ioctl(fd, IPA_IOC_COMMIT_FLT, ip); + if (retval) + { + IPACMERR("failed resetting Filtering block.\n"); + return false; + } + + IPACMDBG("Reset command issued to IPA Filtering block.\n"); + return true; +} + +bool IPACM_Filtering::DeleteFilteringHdls +( + uint32_t *flt_rule_hdls, + ipa_ip_type ip, + uint8_t num_rules +) +{ + struct ipa_ioc_del_flt_rule *flt_rule; + bool res = true; + int len = 0, cnt = 0; + const uint8_t UNIT_RULES = 1; + + len = (sizeof(struct ipa_ioc_del_flt_rule)) + (UNIT_RULES * sizeof(struct ipa_flt_rule_del)); + flt_rule = (struct ipa_ioc_del_flt_rule *)malloc(len); + if (flt_rule == NULL) + { + IPACMERR("unable to allocate memory for del filter rule\n"); + return false; + } + + for (cnt = 0; cnt < num_rules; cnt++) + { + memset(flt_rule, 0, len); + flt_rule->commit = 1; + flt_rule->num_hdls = UNIT_RULES; + flt_rule->ip = ip; + + if (flt_rule_hdls[cnt] == 0) + { + IPACMERR("invalid filter handle passed, ignoring it: %d\n", cnt) + } + else + { + + flt_rule->hdl[0].status = -1; + flt_rule->hdl[0].hdl = flt_rule_hdls[cnt]; + IPACMDBG("Deleting filter hdl:(0x%x) with ip type: %d\n", flt_rule_hdls[cnt], ip); + + if (DeleteFilteringRule(flt_rule) == false) + { + PERROR("Filter rule deletion failed!\n"); + res = false; + goto fail; + } + else + { + + if (flt_rule->hdl[0].status != 0) + { + IPACMERR("Filter rule hdl 0x%x deletion failed with error:%d\n", + flt_rule->hdl[0].hdl, flt_rule->hdl[0].status); + res = false; + goto fail; + } + + } + } + } + +fail: + free(flt_rule); + + return res; +} + +bool IPACM_Filtering::AddWanDLFilteringRule(struct ipa_ioc_add_flt_rule const *rule_table_v4, struct ipa_ioc_add_flt_rule const * rule_table_v6, uint8_t mux_id) +{ + int ret = 0, cnt, num_rules = 0, pos = 0; + ipa_install_fltr_rule_req_msg_v01 qmi_rule_msg; + + int fd_wwan_ioctl = open(WWAN_QMI_IOCTL_DEVICE_NAME, O_RDWR); + if(fd_wwan_ioctl < 0) + { + IPACMERR("Failed to open %s.\n",WWAN_QMI_IOCTL_DEVICE_NAME); + return false; + } + + if(rule_table_v4 != NULL) + { + num_rules += rule_table_v4->num_rules; + IPACMDBG_H("Get %d WAN DL IPv4 filtering rules.\n", rule_table_v4->num_rules); + } + if(rule_table_v6 != NULL) + { + num_rules += rule_table_v6->num_rules; + IPACMDBG_H("Get %d WAN DL IPv6 filtering rules.\n", rule_table_v6->num_rules); + } + + if(num_rules > QMI_IPA_MAX_FILTERS_V01) + { + IPACMERR("The number of filtering rules exceed limit.\n"); + close(fd_wwan_ioctl); + return false; + } + else + { + memset(&qmi_rule_msg, 0, sizeof(qmi_rule_msg)); + + if (num_rules > 0) + { +#ifndef FEATURE_IPA_V3 + qmi_rule_msg.filter_spec_list_valid = true; +#else /* defined (FEATURE_IPA_V3) */ + qmi_rule_msg.filter_spec_ex_list_valid = true; +#endif + } + else + { +#ifndef FEATURE_IPA_V3 + qmi_rule_msg.filter_spec_list_valid = false; +#else /* defined (FEATURE_IPA_V3) */ + qmi_rule_msg.filter_spec_ex_list_valid = false; +#endif + } + +#ifndef FEATURE_IPA_V3 + qmi_rule_msg.filter_spec_list_len = num_rules; +#else /* defined (FEATURE_IPA_V3) */ + qmi_rule_msg.filter_spec_ex_list_len = num_rules; +#endif + + qmi_rule_msg.source_pipe_index_valid = 0; + + IPACMDBG_H("Get %d WAN DL filtering rules in total.\n", num_rules); + + if(rule_table_v4 != NULL) + { + for(cnt = rule_table_v4->num_rules - 1; cnt >= 0; cnt--) + { + if (pos < QMI_IPA_MAX_FILTERS_V01) + { +#ifndef FEATURE_IPA_V3 + qmi_rule_msg.filter_spec_list[pos].filter_spec_identifier = pos; + qmi_rule_msg.filter_spec_list[pos].ip_type = QMI_IPA_IP_TYPE_V4_V01; + qmi_rule_msg.filter_spec_list[pos].filter_action = GetQmiFilterAction(rule_table_v4->rules[cnt].rule.action); + qmi_rule_msg.filter_spec_list[pos].is_routing_table_index_valid = 1; + qmi_rule_msg.filter_spec_list[pos].route_table_index = rule_table_v4->rules[cnt].rule.rt_tbl_idx; + qmi_rule_msg.filter_spec_list[pos].is_mux_id_valid = 1; + qmi_rule_msg.filter_spec_list[pos].mux_id = mux_id; + memcpy(&qmi_rule_msg.filter_spec_list[pos].filter_rule, + &rule_table_v4->rules[cnt].rule.eq_attrib, + sizeof(struct ipa_filter_rule_type_v01)); +#else /* defined (FEATURE_IPA_V3) */ + qmi_rule_msg.filter_spec_ex_list[pos].ip_type = QMI_IPA_IP_TYPE_V4_V01; + qmi_rule_msg.filter_spec_ex_list[pos].filter_action = GetQmiFilterAction(rule_table_v4->rules[cnt].rule.action); + qmi_rule_msg.filter_spec_ex_list[pos].is_routing_table_index_valid = 1; + qmi_rule_msg.filter_spec_ex_list[pos].route_table_index = rule_table_v4->rules[cnt].rule.rt_tbl_idx; + qmi_rule_msg.filter_spec_ex_list[pos].is_mux_id_valid = 1; + qmi_rule_msg.filter_spec_ex_list[pos].mux_id = mux_id; + qmi_rule_msg.filter_spec_ex_list[pos].rule_id = rule_table_v4->rules[cnt].rule.rule_id; + qmi_rule_msg.filter_spec_ex_list[pos].is_rule_hashable = rule_table_v4->rules[cnt].rule.hashable; + memcpy(&qmi_rule_msg.filter_spec_ex_list[pos].filter_rule, + &rule_table_v4->rules[cnt].rule.eq_attrib, + sizeof(struct ipa_filter_rule_type_v01)); +#endif + pos++; + } + else + { + IPACMERR(" QMI only support max %d rules, current (%d)\n ",QMI_IPA_MAX_FILTERS_V01, pos); + } + } + } + + if(rule_table_v6 != NULL) + { + for(cnt = rule_table_v6->num_rules - 1; cnt >= 0; cnt--) + { + if (pos < QMI_IPA_MAX_FILTERS_V01) + { +#ifndef FEATURE_IPA_V3 + qmi_rule_msg.filter_spec_list[pos].filter_spec_identifier = pos; + qmi_rule_msg.filter_spec_list[pos].ip_type = QMI_IPA_IP_TYPE_V6_V01; + qmi_rule_msg.filter_spec_list[pos].filter_action = GetQmiFilterAction(rule_table_v6->rules[cnt].rule.action); + qmi_rule_msg.filter_spec_list[pos].is_routing_table_index_valid = 1; + qmi_rule_msg.filter_spec_list[pos].route_table_index = rule_table_v6->rules[cnt].rule.rt_tbl_idx; + qmi_rule_msg.filter_spec_list[pos].is_mux_id_valid = 1; + qmi_rule_msg.filter_spec_list[pos].mux_id = mux_id; + memcpy(&qmi_rule_msg.filter_spec_list[pos].filter_rule, + &rule_table_v6->rules[cnt].rule.eq_attrib, + sizeof(struct ipa_filter_rule_type_v01)); +#else /* defined (FEATURE_IPA_V3) */ + qmi_rule_msg.filter_spec_ex_list[pos].ip_type = QMI_IPA_IP_TYPE_V6_V01; + qmi_rule_msg.filter_spec_ex_list[pos].filter_action = GetQmiFilterAction(rule_table_v6->rules[cnt].rule.action); + qmi_rule_msg.filter_spec_ex_list[pos].is_routing_table_index_valid = 1; + qmi_rule_msg.filter_spec_ex_list[pos].route_table_index = rule_table_v6->rules[cnt].rule.rt_tbl_idx; + qmi_rule_msg.filter_spec_ex_list[pos].is_mux_id_valid = 1; + qmi_rule_msg.filter_spec_ex_list[pos].mux_id = mux_id; + qmi_rule_msg.filter_spec_ex_list[pos].rule_id = rule_table_v6->rules[cnt].rule.rule_id; + qmi_rule_msg.filter_spec_ex_list[pos].is_rule_hashable = rule_table_v6->rules[cnt].rule.hashable; + memcpy(&qmi_rule_msg.filter_spec_ex_list[pos].filter_rule, + &rule_table_v6->rules[cnt].rule.eq_attrib, + sizeof(struct ipa_filter_rule_type_v01)); +#endif + pos++; + } + else + { + IPACMERR(" QMI only support max %d rules, current (%d)\n ",QMI_IPA_MAX_FILTERS_V01, pos); + } + } + } + + ret = ioctl(fd_wwan_ioctl, WAN_IOC_ADD_FLT_RULE, &qmi_rule_msg); + if (ret != 0) + { + IPACMERR("Failed adding Filtering rule %p with ret %d\n ", &qmi_rule_msg, ret); + close(fd_wwan_ioctl); + return false; + } + } + IPACMDBG("Added Filtering rule %p\n", &qmi_rule_msg); + close(fd_wwan_ioctl); + return true; +} + +bool IPACM_Filtering::SendFilteringRuleIndex(struct ipa_fltr_installed_notif_req_msg_v01* table) +{ + int ret = 0; + int fd_wwan_ioctl = open(WWAN_QMI_IOCTL_DEVICE_NAME, O_RDWR); + if(fd_wwan_ioctl < 0) + { + IPACMERR("Failed to open %s.\n",WWAN_QMI_IOCTL_DEVICE_NAME); + return false; + } + + ret = ioctl(fd_wwan_ioctl, WAN_IOC_ADD_FLT_RULE_INDEX, table); + if (ret != 0) + { + IPACMERR("Failed adding filtering rule index %p with ret %d\n", table, ret); + close(fd_wwan_ioctl); + return false; + } + + IPACMDBG("Added Filtering rule index %p\n", table); + close(fd_wwan_ioctl); + return true; +} + +ipa_filter_action_enum_v01 IPACM_Filtering::GetQmiFilterAction(ipa_flt_action action) +{ + switch(action) + { + case IPA_PASS_TO_ROUTING: + return QMI_IPA_FILTER_ACTION_ROUTING_V01; + + case IPA_PASS_TO_SRC_NAT: + return QMI_IPA_FILTER_ACTION_SRC_NAT_V01; + + case IPA_PASS_TO_DST_NAT: + return QMI_IPA_FILTER_ACTION_DST_NAT_V01; + + case IPA_PASS_TO_EXCEPTION: + return QMI_IPA_FILTER_ACTION_EXCEPTION_V01; + + default: + return IPA_FILTER_ACTION_ENUM_MAX_ENUM_VAL_V01; + } +} + +bool IPACM_Filtering::ModifyFilteringRule(struct ipa_ioc_mdfy_flt_rule* ruleTable) +{ + int i, ret = 0; + + IPACMDBG("Printing filtering add attributes\n"); + IPACMDBG("IP type: %d Number of rules: %d commit value: %d\n", ruleTable->ip, ruleTable->num_rules, ruleTable->commit); + + for (i=0; inum_rules; i++) + { + IPACMDBG("Filter rule:%d attrib mask: 0x%x\n", i, ruleTable->rules[i].rule.attrib.attrib_mask); + } + + ret = ioctl(fd, IPA_IOC_MDFY_FLT_RULE, ruleTable); + if (ret != 0) + { + IPACMERR("Failed modifying filtering rule %p\n", ruleTable); + + for (i = 0; i < ruleTable->num_rules; i++) + { + if (ruleTable->rules[i].status != 0) + { + IPACMERR("Modifying filter rule %d failed\n", i); + } + } + return false; + } + + IPACMDBG("Modified filtering rule %p\n", ruleTable); + return true; +} + diff --git a/data-ipa-cfg-mgr/ipacm/src/IPACM_Header.cpp b/data-ipa-cfg-mgr/ipacm/src/IPACM_Header.cpp new file mode 100644 index 000000000..5e56a497f --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/src/IPACM_Header.cpp @@ -0,0 +1,231 @@ +/* +Copyright (c) 2013, The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +#include +#include +#include +#include +#include + +#include "IPACM_Header.h" +#include "IPACM_Log.h" + +///////////////////////////////////////////////////////////////////////////////////////////////////////// + +//All interaction through the driver are made through this inode. +static const char *DEVICE_NAME = "/dev/ipa"; + +///////////////////////////////////////////////////////////////////////////////////////////////////////// + +IPACM_Header::IPACM_Header() +{ + m_fd = open(DEVICE_NAME, O_RDWR); + if (-1 == m_fd) + { + IPACMERR("Failed to open %s in IPACM_Header test application constructor.\n", DEVICE_NAME); + } +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////// + +IPACM_Header::~IPACM_Header() +{ + if (-1 != m_fd) + { + close(m_fd); + } +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////// + +bool IPACM_Header::DeviceNodeIsOpened() +{ + return (-1 != m_fd); +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////// + +bool IPACM_Header::AddHeader(struct ipa_ioc_add_hdr *pHeaderTableToAdd) +{ + int nRetVal = 0; + //call the Driver ioctl in order to add header + nRetVal = ioctl(m_fd, IPA_IOC_ADD_HDR, pHeaderTableToAdd); + IPACMDBG("return value: %d\n", nRetVal); + return (-1 != nRetVal); +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////// + +bool IPACM_Header::DeleteHeader(struct ipa_ioc_del_hdr *pHeaderTableToDelete) +{ + int nRetVal = 0; + //call the Driver ioctl in order to remove header + nRetVal = ioctl(m_fd, IPA_IOC_DEL_HDR, pHeaderTableToDelete); + IPACMDBG("return value: %d\n", nRetVal); + return (-1 != nRetVal); +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////// + +bool IPACM_Header::Commit() +{ + int nRetVal = 0; + nRetVal = ioctl(m_fd, IPA_IOC_COMMIT_HDR); + IPACMDBG("return value: %d\n", nRetVal); + return true; +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////// + +bool IPACM_Header::Reset() +{ + int nRetVal = 0; + + nRetVal = ioctl(m_fd, IPA_IOC_RESET_HDR); + nRetVal |= ioctl(m_fd, IPA_IOC_COMMIT_HDR); + IPACMDBG("return value: %d\n", nRetVal); + return true; +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////// + +bool IPACM_Header::GetHeaderHandle(struct ipa_ioc_get_hdr *pHeaderStruct) +{ + int retval = 0; + + if (!DeviceNodeIsOpened()) return false; + + retval = ioctl(m_fd, IPA_IOC_GET_HDR, pHeaderStruct); + if (retval) + { + IPACMERR("IPA_IOC_GET_HDR ioctl failed, routingTable =0x%p, retval=0x%x.\n", pHeaderStruct, retval); + return false; + } + + IPACMDBG("IPA_IOC_GET_HDR ioctl issued to IPA header insertion block.\n"); + return true; +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////// + +bool IPACM_Header::CopyHeader(struct ipa_ioc_copy_hdr *pCopyHeaderStruct) +{ + int retval = 0; + + if (!DeviceNodeIsOpened()) return false; + + retval = ioctl(m_fd, IPA_IOC_COPY_HDR, pCopyHeaderStruct); + if (retval) + { + IPACMERR("IPA_IOC_COPY_HDR ioctl failed, retval=0x%x.\n", retval); + return false; + } + + IPACMDBG("IPA_IOC_COPY_HDR ioctl issued to IPA header insertion block.\n"); + return true; +} + +bool IPACM_Header::DeleteHeaderHdl(uint32_t hdr_hdl) +{ + const uint8_t NUM_HDLS = 1; + struct ipa_ioc_del_hdr *pHeaderDescriptor = NULL; + struct ipa_hdr_del *hd_rule_entry; + int len = 0; + bool res = true; + + if (hdr_hdl == 0) + { + IPACMERR("Invalid header handle passed. Ignoring it\n"); + return false; + } + + len = (sizeof(struct ipa_ioc_del_hdr)) + (NUM_HDLS * sizeof(struct ipa_hdr_del)); + pHeaderDescriptor = (struct ipa_ioc_del_hdr *)malloc(len); + if (pHeaderDescriptor == NULL) + { + IPACMERR("Unable to allocate memory for del header\n"); + return false; + } + + memset(pHeaderDescriptor, 0, len); + pHeaderDescriptor->commit = true; + pHeaderDescriptor->num_hdls = NUM_HDLS; + hd_rule_entry = &pHeaderDescriptor->hdl[0]; + + hd_rule_entry->hdl = hdr_hdl; + hd_rule_entry->status = -1; + + IPACMDBG("Deleting Header hdl:(%x)\n", hd_rule_entry->hdl); + if ((false == DeleteHeader(pHeaderDescriptor)) || + (hd_rule_entry->status)) + { + IPACMERR("Header hdl:(%x) deletion failed! status: %d\n", hd_rule_entry->hdl,hd_rule_entry->status); + res = false; + goto fail; + } + + IPACMDBG_H("Deleted Header hdl:(%x) successfully\n", hd_rule_entry->hdl); + +fail: + free(pHeaderDescriptor); + + return res; + +} + +bool IPACM_Header::AddHeaderProcCtx(struct ipa_ioc_add_hdr_proc_ctx* pHeader) +{ + int ret = 0; + //call the Driver ioctl to add header processing context + ret = ioctl(m_fd, IPA_IOC_ADD_HDR_PROC_CTX, pHeader); + return (ret != -1); +} + +bool IPACM_Header::DeleteHeaderProcCtx(uint32_t hdl) +{ + int len, ret; + struct ipa_ioc_del_hdr_proc_ctx* pHeaderTable = NULL; + + len = sizeof(struct ipa_ioc_del_hdr_proc_ctx) + sizeof(struct ipa_hdr_proc_ctx_del); + pHeaderTable = (struct ipa_ioc_del_hdr_proc_ctx*)malloc(len); + if(pHeaderTable == NULL) + { + IPACMERR("Failed to allocate buffer.\n"); + return false; + } + memset(pHeaderTable, 0, len); + + pHeaderTable->commit = 1; + pHeaderTable->num_hdls = 1; + pHeaderTable->hdl[0].hdl = hdl; + + ret = ioctl(m_fd, IPA_IOC_DEL_HDR_PROC_CTX, pHeaderTable); + free(pHeaderTable); + return (ret != -1); +} + diff --git a/data-ipa-cfg-mgr/ipacm/src/IPACM_Iface.cpp b/data-ipa-cfg-mgr/ipacm/src/IPACM_Iface.cpp new file mode 100644 index 000000000..5dc764796 --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/src/IPACM_Iface.cpp @@ -0,0 +1,1015 @@ +/* +Copyright (c) 2013, The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: +* Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. +* Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.Z +*/ +/*! + @file + IPACM_Iface.cpp + + @brief + This file implements the basis Iface functionality. + + @Author + Skylar Chang + +*/ +#include +#include +#include +#include +#include +#include +#include +#include + +extern "C" +{ +#include +} + + +const char *IPACM_Iface::DEVICE_NAME = "/dev/ipa"; +IPACM_Routing IPACM_Iface::m_routing; +IPACM_Filtering IPACM_Iface::m_filtering; +IPACM_Header IPACM_Iface::m_header; + +IPACM_Config *IPACM_Iface::ipacmcfg = IPACM_Config::GetInstance(); + +IPACM_Iface::IPACM_Iface(int iface_index) +{ + ip_type = IPACM_IP_NULL; /* initially set invalid */ + num_dft_rt_v6 = 0; + softwarerouting_act = false; + ipa_if_num = iface_index; + ipa_if_cate = IPACM_Iface::ipacmcfg->iface_table[iface_index].if_cat; + + iface_query = NULL; + tx_prop = NULL; + rx_prop = NULL; + + memcpy(dev_name, + IPACM_Iface::ipacmcfg->iface_table[iface_index].iface_name, + sizeof(IPACM_Iface::ipacmcfg->iface_table[iface_index].iface_name)); + + memset(dft_v4fl_rule_hdl, 0, sizeof(dft_v4fl_rule_hdl)); + memset(dft_v6fl_rule_hdl, 0, sizeof(dft_v6fl_rule_hdl)); + + memset(dft_rt_rule_hdl, 0, sizeof(dft_rt_rule_hdl)); + memset(software_routing_fl_rule_hdl, 0, sizeof(software_routing_fl_rule_hdl)); + memset(ipv6_addr, 0, sizeof(ipv6_addr)); + + query_iface_property(); + IPACMDBG_H(" create iface-index(%d) constructor\n", ipa_if_num); + return; +} + +/* software routing enable */ +int IPACM_Iface::handle_software_routing_enable(void) +{ + + int res = IPACM_SUCCESS; + struct ipa_flt_rule_add flt_rule_entry; + ipa_ioc_add_flt_rule *m_pFilteringTable; + + IPACMDBG("\n"); + if (softwarerouting_act == true) + { + IPACMDBG("already setup software_routing rule for (%s)iface ip-family %d\n", + IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].iface_name, ip_type); + return IPACM_SUCCESS; + } + + if(rx_prop == NULL) + { + IPACMDBG("No rx properties registered for iface %s\n", dev_name); + return IPACM_SUCCESS; + } + + m_pFilteringTable = (struct ipa_ioc_add_flt_rule *) + calloc(1, + sizeof(struct ipa_ioc_add_flt_rule) + + 1 * sizeof(struct ipa_flt_rule_add) + ); + if (!m_pFilteringTable) + { + IPACMERR("Error Locate ipa_flt_rule_add memory...\n"); + return IPACM_FAILURE; + } + + m_pFilteringTable->commit = 1; + m_pFilteringTable->ep = rx_prop->rx[0].src_pipe; + m_pFilteringTable->global = false; + m_pFilteringTable->num_rules = (uint8_t)1; + + + /* Configuring Software-Routing Filtering Rule */ + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); + + flt_rule_entry.at_rear = false; + flt_rule_entry.flt_rule_hdl = -1; + flt_rule_entry.status = -1; + flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION; + memcpy(&flt_rule_entry.rule.attrib, + &rx_prop->rx[0].attrib, + sizeof(flt_rule_entry.rule.attrib)); + + memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + + /* check iface is v4 or v6 or both*/ +// if (ip_type == IPA_IP_MAX) +// { + /* handle v4 */ + m_pFilteringTable->ip = IPA_IP_v4; + if (false == m_filtering.AddFilteringRule(m_pFilteringTable)) + { + IPACMERR("Error Adding Filtering rule, aborting...\n"); + res = IPACM_FAILURE; + goto fail; + } + else if (m_pFilteringTable->rules[0].status) + { + IPACMERR("adding flt rule failed status=0x%x\n", m_pFilteringTable->rules[0].status); + res = IPACM_FAILURE; + goto fail; + } + + IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, 1); + IPACMDBG("soft-routing flt rule hdl0=0x%x\n", m_pFilteringTable->rules[0].flt_rule_hdl); + /* copy filter hdls */ + software_routing_fl_rule_hdl[0] = m_pFilteringTable->rules[0].flt_rule_hdl; + + + /* handle v6*/ + m_pFilteringTable->ip = IPA_IP_v6; + if (false == m_filtering.AddFilteringRule(m_pFilteringTable)) + { + IPACMERR("Error Adding Filtering rule, aborting...\n"); + res = IPACM_FAILURE; + goto fail; + } + else if (m_pFilteringTable->rules[0].status) + { + IPACMDBG("adding flt rule failed status=0x%x\n", m_pFilteringTable->rules[0].status); + res = IPACM_FAILURE; + goto fail; + } + + IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1); + IPACMDBG("soft-routing flt rule hdl0=0x%x\n", m_pFilteringTable->rules[0].flt_rule_hdl); + /* copy filter hdls */ + software_routing_fl_rule_hdl[1] = m_pFilteringTable->rules[0].flt_rule_hdl; + softwarerouting_act = true; +#if 0 + } + else + { + if (ip_type == IPA_IP_v4) + { + m_pFilteringTable->ip = IPA_IP_v4; + } + else + { + m_pFilteringTable->ip = IPA_IP_v6; + } + + if (false == m_filtering.AddFilteringRule(m_pFilteringTable)) + { + IPACMERR("Error Adding Filtering rule, aborting...\n"); + res = IPACM_FAILURE; + goto fail; + } + else if (m_pFilteringTable->rules[0].status) + { + IPACMERR("adding flt rule failed status=0x%x\n", m_pFilteringTable->rules[0].status); + res = IPACM_FAILURE; + goto fail; + } + + IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, ip_type, 1); + IPACMDBG("soft-routing flt rule hdl0=0x%x\n", m_pFilteringTable->rules[0].flt_rule_hdl); + /* copy filter hdls */ + if (ip_type == IPA_IP_v4) + { + software_routing_fl_rule_hdl[0] = m_pFilteringTable->rules[0].flt_rule_hdl; + } + else + { + software_routing_fl_rule_hdl[1] = m_pFilteringTable->rules[0].flt_rule_hdl; + } + softwarerouting_act = true; + } +#endif + +fail: + free(m_pFilteringTable); + + return res; +} + +/* software routing disable */ +int IPACM_Iface::handle_software_routing_disable(void) +{ + int res = IPACM_SUCCESS; + ipa_ip_type ip; + uint32_t flt_hdl; + + if (rx_prop == NULL) + { + IPACMDBG("No rx properties registered for iface %s\n", dev_name); + return IPACM_SUCCESS; + } + + if (softwarerouting_act == false) + { + IPACMDBG("already delete software_routing rule for (%s)iface ip-family %d\n", IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].iface_name, ip_type); + return IPACM_SUCCESS; + } + +// if (ip_type == IPA_IP_MAX) +// { + /* ipv4 case */ + if (m_filtering.DeleteFilteringHdls(&software_routing_fl_rule_hdl[0], + IPA_IP_v4, 1) == false) + { + IPACMERR("Error Adding Filtering rule, aborting...\n"); + res = IPACM_FAILURE; + goto fail; + } + IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, 1); + + /* ipv6 case */ + if (m_filtering.DeleteFilteringHdls(&software_routing_fl_rule_hdl[1], + IPA_IP_v6, 1) == false) + { + IPACMERR("Error Adding Filtering rule, aborting...\n"); + res = IPACM_FAILURE; + goto fail; + } + IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1); + softwarerouting_act = false; +#if 0 + } + else + { + if (ip_type == IPA_IP_v4) + { + ip = IPA_IP_v4; + } + else + { + ip = IPA_IP_v6; + } + + + if (ip_type == IPA_IP_v4) + { + flt_hdl = software_routing_fl_rule_hdl[0]; + } + else + { + flt_hdl = software_routing_fl_rule_hdl[1]; + } + + if (m_filtering.DeleteFilteringHdls(&flt_hdl, ip, 1) == false) + { + IPACMERR("Error Adding Filtering rule, aborting...\n"); + res = IPACM_FAILURE; + goto fail; + } + IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, ip, 1); + softwarerouting_act = false; + } +#endif + +fail: + return res; +} + +/* Query ipa_interface_index by given linux interface_index */ +int IPACM_Iface::iface_ipa_index_query +( + int interface_index +) +{ + int fd; + int link = INVALID_IFACE; + int i = 0; + struct ifreq ifr; + + + if(IPACM_Iface::ipacmcfg->iface_table == NULL) + { + IPACMERR("Iface table in IPACM_Config is not available.\n"); + return link; + } + + /* Search known linux interface-index and map to IPA interface-index*/ + for (i = 0; i < IPACM_Iface::ipacmcfg->ipa_num_ipa_interfaces; i++) + { + if (interface_index == IPACM_Iface::ipacmcfg->iface_table[i].netlink_interface_index) + { + link = i; + IPACMDBG("Interface (%s) found: linux(%d) ipa(%d) \n", + IPACM_Iface::ipacmcfg->iface_table[i].iface_name, + IPACM_Iface::ipacmcfg->iface_table[i].netlink_interface_index, + link); + return link; + break; + } + } + + /* Search/Configure linux interface-index and map it to IPA interface-index */ + if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) + { + PERROR("get interface name socket create failed"); + return IPACM_FAILURE; + } + + memset(&ifr, 0, sizeof(struct ifreq)); + + ifr.ifr_ifindex = interface_index; + IPACMDBG_H("Interface index %d\n", interface_index); + + if (ioctl(fd, SIOCGIFNAME, &ifr) < 0) + { + PERROR("call_ioctl_on_dev: ioctl failed:"); + close(fd); + return IPACM_FAILURE; + } + close(fd); + + IPACMDBG_H("Received interface name %s\n", ifr.ifr_name); + for (i = 0; i < IPACM_Iface::ipacmcfg->ipa_num_ipa_interfaces; i++) + { + if (strncmp(ifr.ifr_name, + IPACM_Iface::ipacmcfg->iface_table[i].iface_name, + sizeof(IPACM_Iface::ipacmcfg->iface_table[i].iface_name)) == 0) + { + IPACMDBG_H("Interface (%s) linux(%d) mapped to ipa(%d) \n", ifr.ifr_name, + IPACM_Iface::ipacmcfg->iface_table[i].netlink_interface_index, i); + + link = i; + IPACM_Iface::ipacmcfg->iface_table[i].netlink_interface_index = interface_index; + break; + } + } + + return link; +} + +/* Query ipa_interface ipv4_addr by given linux interface_index */ +void IPACM_Iface::iface_addr_query +( + int interface_index +) +{ + int fd; + struct ifreq ifr; + struct ifaddrs *myaddrs, *ifa; + ipacm_cmd_q_data evt_data; + ipacm_event_data_addr *data_addr; + struct in_addr iface_ipv4; + + /* use linux interface-index to find interface name */ + if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) + { + PERROR("get interface name socket create failed"); + return ; + } + + memset(&ifr, 0, sizeof(struct ifreq)); + + ifr.ifr_ifindex = interface_index; + IPACMDBG_H("Interface index %d\n", interface_index); + + if (ioctl(fd, SIOCGIFNAME, &ifr) < 0) + { + PERROR("call_ioctl_on_dev: ioctl failed:"); + close(fd); + return ; + } + IPACMDBG_H("Interface index %d name: %s\n", interface_index,ifr.ifr_name); + close(fd); + + /* query ipv4/v6 address */ + if(getifaddrs(&myaddrs) != 0) + { + IPACMERR("getifaddrs"); + return ; + } + + for (ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next) + { + if (ifa->ifa_addr == NULL) + continue; + if (!(ifa->ifa_flags & IFF_UP)) + continue; + + if(strcmp(ifr.ifr_name,ifa->ifa_name) == 0) // find current iface + { + IPACMDBG_H("Internal post new_addr event for iface %s\n", ifa->ifa_name); + switch (ifa->ifa_addr->sa_family) + { + case AF_INET: + { + struct sockaddr_in *s4 = (struct sockaddr_in *)ifa->ifa_addr; + IPACMDBG_H("ipv4 address %s\n",inet_ntoa(s4->sin_addr)); + iface_ipv4 = s4->sin_addr; + /* post new_addr event to command queue */ + data_addr = (ipacm_event_data_addr *)malloc(sizeof(ipacm_event_data_addr)); + if(data_addr == NULL) + { + IPACMERR("unable to allocate memory for event data_addr\n"); + freeifaddrs(myaddrs); + return ; + } + data_addr->iptype = IPA_IP_v4; + data_addr->if_index = interface_index; + data_addr->ipv4_addr = iface_ipv4.s_addr; + data_addr->ipv4_addr = ntohl(data_addr->ipv4_addr); + IPACMDBG_H("Posting IPA_ADDR_ADD_EVENT with if index:%d, ipv4 addr:0x%x\n", + data_addr->if_index, + data_addr->ipv4_addr); + + evt_data.event = IPA_ADDR_ADD_EVENT; + evt_data.evt_data = data_addr; + IPACM_EvtDispatcher::PostEvt(&evt_data); + break; + } + + case AF_INET6: + { + struct sockaddr_in6 *s6 = (struct sockaddr_in6 *)ifa->ifa_addr; + /* post new_addr event to command queue */ + data_addr = (ipacm_event_data_addr *)malloc(sizeof(ipacm_event_data_addr)); + if(data_addr == NULL) + { + IPACMERR("unable to allocate memory for event data_addr\n"); + freeifaddrs(myaddrs); + return ; + } + data_addr->iptype = IPA_IP_v6; + data_addr->if_index = interface_index; + memcpy(data_addr->ipv6_addr, + &s6->sin6_addr, + sizeof(data_addr->ipv6_addr)); + data_addr->ipv6_addr[0] = ntohl(data_addr->ipv6_addr[0]); + data_addr->ipv6_addr[1] = ntohl(data_addr->ipv6_addr[1]); + data_addr->ipv6_addr[2] = ntohl(data_addr->ipv6_addr[2]); + data_addr->ipv6_addr[3] = ntohl(data_addr->ipv6_addr[3]); + IPACMDBG_H("Posting IPA_ADDR_ADD_EVENT with if index:%d, ipv6 addr:0x%x:%x:%x:%x\n", + data_addr->if_index, + data_addr->ipv6_addr[0], data_addr->ipv6_addr[1], data_addr->ipv6_addr[2], data_addr->ipv6_addr[3]); + + evt_data.event = IPA_ADDR_ADD_EVENT; + evt_data.evt_data = data_addr; + IPACM_EvtDispatcher::PostEvt(&evt_data); + break; + } + + default: + continue; + } + } + } + freeifaddrs(myaddrs); + return ; +} + +/*Query the IPA endpoint property */ +int IPACM_Iface::query_iface_property(void) +{ + int res = IPACM_SUCCESS, fd = 0; + uint32_t cnt=0; + + fd = open(DEVICE_NAME, O_RDWR); + IPACMDBG("iface query-property \n"); + if (0 == fd) + { + IPACMERR("Failed opening %s.\n", DEVICE_NAME); + return IPACM_FAILURE; + } + + iface_query = (struct ipa_ioc_query_intf *) + calloc(1, sizeof(struct ipa_ioc_query_intf)); + if(iface_query == NULL) + { + IPACMERR("Unable to allocate iface_query memory.\n"); + close(fd); + return IPACM_FAILURE; + } + IPACMDBG_H("iface name %s\n", dev_name); + memcpy(iface_query->name, dev_name, sizeof(dev_name)); + + if (ioctl(fd, IPA_IOC_QUERY_INTF, iface_query) < 0) + { + PERROR("ioctl IPA_IOC_QUERY_INTF failed\n"); + /* iface_query memory will free when iface-down*/ + res = IPACM_FAILURE; + } + + if(iface_query->num_tx_props > 0) + { + tx_prop = (struct ipa_ioc_query_intf_tx_props *) + calloc(1, sizeof(struct ipa_ioc_query_intf_tx_props) + + iface_query->num_tx_props * sizeof(struct ipa_ioc_tx_intf_prop)); + if(tx_prop == NULL) + { + IPACMERR("Unable to allocate tx_prop memory.\n"); + close(fd); + return IPACM_FAILURE; + } + memcpy(tx_prop->name, dev_name, sizeof(tx_prop->name)); + tx_prop->num_tx_props = iface_query->num_tx_props; + + if (ioctl(fd, IPA_IOC_QUERY_INTF_TX_PROPS, tx_prop) < 0) + { + PERROR("ioctl IPA_IOC_QUERY_INTF_TX_PROPS failed\n"); + /* tx_prop memory will free when iface-down*/ + res = IPACM_FAILURE; + } + + if (res != IPACM_FAILURE) + { + for (cnt = 0; cnt < tx_prop->num_tx_props; cnt++) + { + IPACMDBG_H("Tx(%d):attrib-mask:0x%x, ip-type: %d, dst_pipe: %d, alt_dst_pipe: %d, header: %s\n", + cnt, tx_prop->tx[cnt].attrib.attrib_mask, + tx_prop->tx[cnt].ip, tx_prop->tx[cnt].dst_pipe, + tx_prop->tx[cnt].alt_dst_pipe, + tx_prop->tx[cnt].hdr_name); + + if (tx_prop->tx[cnt].dst_pipe == 0) + { + IPACMERR("Tx(%d): wrong tx property: dst_pipe: 0.\n", cnt); + close(fd); + return IPACM_FAILURE; + } + if (tx_prop->tx[cnt].alt_dst_pipe == 0 && + ((memcmp(dev_name, "wlan0", sizeof("wlan0")) == 0) || + (memcmp(dev_name, "wlan1", sizeof("wlan1")) == 0))) + { + IPACMERR("Tx(%d): wrong tx property: alt_dst_pipe: 0. \n", cnt); + close(fd); + return IPACM_FAILURE; + } + + } + } + + } + + if (iface_query->num_rx_props > 0) + { + rx_prop = (struct ipa_ioc_query_intf_rx_props *) + calloc(1, sizeof(struct ipa_ioc_query_intf_rx_props) + + iface_query->num_rx_props * sizeof(struct ipa_ioc_rx_intf_prop)); + if(rx_prop == NULL) + { + IPACMERR("Unable to allocate rx_prop memory.\n"); + close(fd); + return IPACM_FAILURE; + } + memcpy(rx_prop->name, dev_name, + sizeof(rx_prop->name)); + rx_prop->num_rx_props = iface_query->num_rx_props; + + if (ioctl(fd, IPA_IOC_QUERY_INTF_RX_PROPS, rx_prop) < 0) + { + PERROR("ioctl IPA_IOC_QUERY_INTF_RX_PROPS failed\n"); + /* rx_prop memory will free when iface-down*/ + res = IPACM_FAILURE; + } + + if (res != IPACM_FAILURE) + { + for (cnt = 0; cnt < rx_prop->num_rx_props; cnt++) + { + IPACMDBG_H("Rx(%d):attrib-mask:0x%x, ip-type: %d, src_pipe: %d\n", + cnt, rx_prop->rx[cnt].attrib.attrib_mask, rx_prop->rx[cnt].ip, rx_prop->rx[cnt].src_pipe); + } + } + } + + /* Add Natting iface to IPACM_Config if there is Rx/Tx property */ + if (rx_prop != NULL || tx_prop != NULL) + { + IPACMDBG_H(" Has rx/tx properties registered for iface %s, add for NATTING \n", dev_name); + IPACM_Iface::ipacmcfg->AddNatIfaces(dev_name); + } + + close(fd); + return res; +} + +/*Configure the initial filter rules */ +int IPACM_Iface::init_fl_rule(ipa_ip_type iptype) +{ + + int res = IPACM_SUCCESS, len = 0; + struct ipa_flt_rule_add flt_rule_entry; + ipa_ioc_add_flt_rule *m_pFilteringTable; + + /* Adding this hack because WLAN may not registered for Rx-endpoint, other ifaces will always have*/ + const char *dev_wlan0="wlan0"; + const char *dev_wlan1="wlan1"; + const char *dev_ecm0="ecm0"; + + /* update the iface ip-type to be IPA_IP_v4, IPA_IP_v6 or both*/ + if (iptype == IPA_IP_v4) + { + + if ((ip_type == IPA_IP_v4) || (ip_type == IPA_IP_MAX)) + { + IPACMDBG_H(" interface(%s:%d) already in ip-type %d\n", dev_name, ipa_if_num, ip_type); + return res; + } + + if (ip_type == IPA_IP_v6) + { + ip_type = IPA_IP_MAX; + } + else + { + ip_type = IPA_IP_v4; + } + + IPACMDBG_H(" interface(%s:%d) now ip-type is %d\n", dev_name, ipa_if_num, ip_type); + } + else + { + + if ((ip_type == IPA_IP_v6) || (ip_type == IPA_IP_MAX)) + { + IPACMDBG_H(" interface(%s:%d) already in ip-type %d\n", dev_name, ipa_if_num, ip_type); + return res; + } + + if (ip_type == IPA_IP_v4) + { + ip_type = IPA_IP_MAX; + } + else + { + ip_type = IPA_IP_v6; + } + + IPACMDBG_H(" interface(%s:%d) now ip-type is %d\n", dev_name, ipa_if_num, ip_type); + } + + /* ADD corresponding ipa_rm_resource_name of RX-endpoint before adding all IPV4V6 FT-rules */ + if((IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat== WAN_IF) || (IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat== EMBMS_IF)) + { + IPACMDBG_H(" NOT add producer dependency on dev %s with registered rx-prop cat:%d \n", dev_name, IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat); + } + else + { + if(rx_prop != NULL) + { + IPACMDBG_H("dev %s add producer dependency\n", dev_name); + IPACMDBG_H("depend Got pipe %d rm index : %d \n", rx_prop->rx[0].src_pipe, IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[rx_prop->rx[0].src_pipe]); + IPACM_Iface::ipacmcfg->AddRmDepend(IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[rx_prop->rx[0].src_pipe],false); + } + else + { + /* only wlan may take software-path, not register Rx-property*/ + if(strcmp(dev_name,dev_wlan0) == 0 || strcmp(dev_name,dev_wlan1) == 0) + { + IPACMDBG_H("dev %s add producer dependency\n", dev_name); + IPACMDBG_H("depend Got piperm index : %d \n", IPA_RM_RESOURCE_HSIC_PROD); + IPACM_Iface::ipacmcfg->AddRmDepend(IPA_RM_RESOURCE_HSIC_PROD,true); + } + if(strcmp(dev_name,dev_ecm0) == 0) + { + IPACMDBG_H("dev %s add producer dependency\n", dev_name); + IPACMDBG_H("depend Got piperm index : %d \n", IPA_RM_RESOURCE_USB_PROD); + IPACM_Iface::ipacmcfg->AddRmDepend(IPA_RM_RESOURCE_USB_PROD,true); + } + } + } + if (rx_prop == NULL) + { + IPACMDBG_H("No rx properties registered for iface %s\n", dev_name); + return IPACM_SUCCESS; + } + + /* construct ipa_ioc_add_flt_rule with default filter rules */ + if (iptype == IPA_IP_v4) + { + len = sizeof(struct ipa_ioc_add_flt_rule) + + (IPV4_DEFAULT_FILTERTING_RULES * sizeof(struct ipa_flt_rule_add)); + + m_pFilteringTable = (struct ipa_ioc_add_flt_rule *)calloc(1, len); + if (!m_pFilteringTable) + { + IPACMERR("Error Locate ipa_flt_rule_add memory...\n"); + return IPACM_FAILURE; + } + + m_pFilteringTable->commit = 1; + m_pFilteringTable->ep = rx_prop->rx[0].src_pipe; + m_pFilteringTable->global = false; + m_pFilteringTable->ip = iptype; + m_pFilteringTable->num_rules = (uint8_t)IPV4_DEFAULT_FILTERTING_RULES; + + /* Configuring Fragment Filtering Rule */ + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); + + flt_rule_entry.rule.retain_hdr = 1; + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl = -1; + flt_rule_entry.status = -1; + flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION; +#ifdef FEATURE_IPA_V3 + flt_rule_entry.at_rear = false; + flt_rule_entry.rule.hashable = IPA_RULE_NON_HASHABLE; +#endif + IPACMDBG_H("rx property attrib mask:0x%x\n", rx_prop->rx[0].attrib.attrib_mask); + memcpy(&flt_rule_entry.rule.attrib, + &rx_prop->rx[0].attrib, + sizeof(flt_rule_entry.rule.attrib)); + + flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_FRAGMENT; + memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + + /* Configuring Multicast Filtering Rule */ + memcpy(&flt_rule_entry.rule.attrib, + &rx_prop->rx[0].attrib, + sizeof(flt_rule_entry.rule.attrib)); + flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; + flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0xF0000000; + flt_rule_entry.rule.attrib.u.v4.dst_addr = 0xE0000000; + memcpy(&(m_pFilteringTable->rules[1]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + + /* Configuring Broadcast Filtering Rule */ + flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF; + flt_rule_entry.rule.attrib.u.v4.dst_addr = 0xFFFFFFFF; + memcpy(&(m_pFilteringTable->rules[2]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + + if (false == m_filtering.AddFilteringRule(m_pFilteringTable)) + { + IPACMERR("Error Adding Filtering rule, aborting...\n"); + res = IPACM_FAILURE; + goto fail; + } + else + { + IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, IPV4_DEFAULT_FILTERTING_RULES); + /* copy filter hdls */ + for (int i = 0; i < IPV4_DEFAULT_FILTERTING_RULES; i++) + { + if (m_pFilteringTable->rules[i].status == 0) + { + dft_v4fl_rule_hdl[i] = m_pFilteringTable->rules[i].flt_rule_hdl; + IPACMDBG_H("Default v4 filter Rule %d HDL:0x%x\n", i, dft_v4fl_rule_hdl[i]); + } + else + { + IPACMERR("Failed adding default v4 Filtering rule %d\n", i); + } + } + } + } + else + { + len = sizeof(struct ipa_ioc_add_flt_rule) + + (IPV6_DEFAULT_FILTERTING_RULES * sizeof(struct ipa_flt_rule_add)); + + m_pFilteringTable = (struct ipa_ioc_add_flt_rule *)calloc(1, len); + if (!m_pFilteringTable) + { + IPACMERR("Error Locate ipa_flt_rule_add memory...\n"); + return IPACM_FAILURE; + } + + m_pFilteringTable->commit = 1; + m_pFilteringTable->ep = rx_prop->rx[0].src_pipe; + m_pFilteringTable->global = false; + m_pFilteringTable->ip = iptype; + m_pFilteringTable->num_rules = (uint8_t)IPV6_DEFAULT_FILTERTING_RULES; + + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); + + flt_rule_entry.rule.retain_hdr = 1; + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl = -1; + flt_rule_entry.status = -1; + flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION; + /* Configuring Multicast Filtering Rule */ + memcpy(&flt_rule_entry.rule.attrib, + &rx_prop->rx[0].attrib, + sizeof(flt_rule_entry.rule.attrib)); + flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0xFF000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[1] = 0x00000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = 0x00000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr[0] = 0XFF000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = 0x00000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = 0x00000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X00000000; + memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + + /* Configuring fe80::/10 Link-Scoped Unicast Filtering Rule */ + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0XFFC00000; + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[1] = 0x00000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = 0x00000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr[0] = 0xFE800000; + flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = 0x00000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = 0x00000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X00000000; + memcpy(&(m_pFilteringTable->rules[1]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + + /* Configuring fec0::/10 Reserved by IETF Filtering Rule */ + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0XFFC00000; + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[1] = 0x00000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = 0x00000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr[0] = 0xFEC00000; + flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = 0x00000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = 0x00000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X00000000; + memcpy(&(m_pFilteringTable->rules[2]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + +#ifdef FEATURE_IPA_ANDROID + IPACMDBG_H("Add TCP ctrl rules: total num %d\n", IPV6_DEFAULT_FILTERTING_RULES); + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); + + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl = -1; + flt_rule_entry.status = -1; + + flt_rule_entry.rule.retain_hdr = 1; + flt_rule_entry.rule.to_uc = 0; + flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION; + flt_rule_entry.rule.eq_attrib_type = 1; + flt_rule_entry.rule.eq_attrib.rule_eq_bitmap = 0; + + if(rx_prop->rx[0].attrib.attrib_mask & IPA_FLT_META_DATA) + { + flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<14); + flt_rule_entry.rule.eq_attrib.metadata_meq32_present = 1; + flt_rule_entry.rule.eq_attrib.metadata_meq32.offset = 0; + flt_rule_entry.rule.eq_attrib.metadata_meq32.value = rx_prop->rx[0].attrib.meta_data; + flt_rule_entry.rule.eq_attrib.metadata_meq32.mask = rx_prop->rx[0].attrib.meta_data_mask; + } + + flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<1); + flt_rule_entry.rule.eq_attrib.protocol_eq_present = 1; + flt_rule_entry.rule.eq_attrib.protocol_eq = IPACM_FIREWALL_IPPROTO_TCP; + + flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<8); + flt_rule_entry.rule.eq_attrib.num_ihl_offset_meq_32 = 1; + flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].offset = 12; + + /* add TCP FIN rule*/ + flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].value = (((uint32_t)1)<rules[3]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + + /* add TCP SYN rule*/ + flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].value = (((uint32_t)1)<rules[4]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + + /* add TCP RST rule*/ + flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].value = (((uint32_t)1)<rules[5]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); +#endif + if (m_filtering.AddFilteringRule(m_pFilteringTable) == false) + { + IPACMERR("Error Adding Filtering rule, aborting...\n"); + res = IPACM_FAILURE; + goto fail; + } + else + { + IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, IPV6_DEFAULT_FILTERTING_RULES); + /* copy filter hdls */ + for (int i = 0; + i < IPV6_DEFAULT_FILTERTING_RULES; + i++) + { + if (m_pFilteringTable->rules[i].status == 0) + { + dft_v6fl_rule_hdl[i] = m_pFilteringTable->rules[i].flt_rule_hdl; + IPACMDBG_H("Default v6 Filter Rule %d HDL:0x%x\n", i, dft_v6fl_rule_hdl[i]); + } + else + { + IPACMERR("Failing adding v6 default IPV6 rule %d\n", i); + } + } + } + } + + +fail: + free(m_pFilteringTable); + + return res; +} + +/* get ipa interface name */ +int IPACM_Iface::ipa_get_if_index +( + char * if_name, + int * if_index +) +{ + int fd; + struct ifreq ifr; + + if((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) + { + IPACMERR("get interface index socket create failed \n"); + return IPACM_FAILURE; + } + + memset(&ifr, 0, sizeof(struct ifreq)); + (void)strncpy(ifr.ifr_name, if_name, sizeof(ifr.ifr_name)); + IPACMDBG_H("interface name (%s)\n", if_name); + + if (ioctl(fd,SIOCGIFINDEX , &ifr) < 0) + { + IPACMERR("call_ioctl_on_dev: ioctl failed, interface name (%s):\n", ifr.ifr_name); + close(fd); + return IPACM_FAILURE; + } + + *if_index = ifr.ifr_ifindex; + IPACMDBG_H("Interface index %d\n", *if_index); + close(fd); + return IPACM_SUCCESS; +} + +size_t IPACM_Iface::strlcpy(char *dest, const char *src, size_t n) +{ + size_t ret = strlen(src); + size_t len = 0; + if (n > 0) { + if(ret >= n) + { + len = n-1; + IPACMERR(" overflow detected \n"); + } + else + { + len = ret; + } + dest[len] = '\0'; + memcpy(dest, src, len); + } + return ret; +} + +size_t IPACM_Iface::strlcat(char *dest, const char *src, size_t n) +{ + size_t dsize = strlen(dest); + size_t len = strlen(src); + size_t ret = dsize + len; + + if (dsize < n) + { + dest += dsize; + n -= dsize; + if (len >= n) + { + len = n - 1; + IPACMERR(" overflow detected \n"); + } + dest[len] = '\0'; + memcpy(dest, src, len); + } + else + { + IPACMERR(" dest buffer full\n"); + } + return ret; +} diff --git a/data-ipa-cfg-mgr/ipacm/src/IPACM_IfaceManager.cpp b/data-ipa-cfg-mgr/ipacm/src/IPACM_IfaceManager.cpp new file mode 100644 index 000000000..59884abcc --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/src/IPACM_IfaceManager.cpp @@ -0,0 +1,550 @@ +/* +Copyright (c) 2013, The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +/*! + @file + IPACM_IfaceManager.cpp + + @brief + This file implements the IPAM iface_manager functionality. + + @Author + Skylar Chang + +*/ +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +iface_instances *IPACM_IfaceManager::head = NULL; + +IPACM_IfaceManager::IPACM_IfaceManager() +{ + IPACM_EvtDispatcher::registr(IPA_CFG_CHANGE_EVENT, this); // register for IPA_CFG_CHANGE event + IPACM_EvtDispatcher::registr(IPA_LINK_UP_EVENT, this); + IPACM_EvtDispatcher::registr(IPA_WLAN_AP_LINK_UP_EVENT, this); // register for wlan AP-iface +#ifndef FEATURE_IPA_ANDROID + IPACM_EvtDispatcher::registr(IPA_WLAN_STA_LINK_UP_EVENT, this); // register for wlan STA-iface + /* only MDM targets support device on bridge mode */ + IPACM_EvtDispatcher::registr(IPA_BRIDGE_LINK_UP_EVENT, this); // register for IPA_BRIDGE_LINK_UP_EVENT event +#endif /* not defined(FEATURE_IPA_ANDROID)*/ + IPACM_EvtDispatcher::registr(IPA_USB_LINK_UP_EVENT, this); // register for USB-iface + IPACM_EvtDispatcher::registr(IPA_WAN_EMBMS_LINK_UP_EVENT, this); // register for wan eMBMS-iface + return; +} + +void IPACM_IfaceManager::event_callback(ipa_cm_event_id event, void *param) +{ + int ipa_interface_index; + ipacm_event_data_fid *evt_data = (ipacm_event_data_fid *)param; + ipacm_event_data_mac *StaData = (ipacm_event_data_mac *)param; + ipacm_event_data_all *data_all = (ipacm_event_data_all *)param; + ipacm_ifacemgr_data ifmgr_data = {0}; + + switch(event) + { + case IPA_CFG_CHANGE_EVENT: + IPACMDBG_H(" RESET IPACM_cfg \n"); + IPACM_Iface::ipacmcfg->Init(); + break; + case IPA_BRIDGE_LINK_UP_EVENT: + IPACMDBG_H(" Save the bridge0 mac info in IPACM_cfg \n"); + ipa_interface_index = IPACM_Iface::iface_ipa_index_query(data_all->if_index); + /* check if iface is bridge interface*/ + if (strcmp(IPACM_Iface::ipacmcfg->ipa_virtual_iface_name, IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name) == 0) + { + IPACM_Iface::ipacmcfg->ipa_bridge_enable = true; + memcpy(IPACM_Iface::ipacmcfg->bridge_mac, + data_all->mac_addr, + sizeof(IPACM_Iface::ipacmcfg->bridge_mac)); + IPACMDBG_H("cached bridge0 MAC %02x:%02x:%02x:%02x:%02x:%02x\n", + IPACM_Iface::ipacmcfg->bridge_mac[0], IPACM_Iface::ipacmcfg->bridge_mac[1], IPACM_Iface::ipacmcfg->bridge_mac[2], + IPACM_Iface::ipacmcfg->bridge_mac[3], IPACM_Iface::ipacmcfg->bridge_mac[4], IPACM_Iface::ipacmcfg->bridge_mac[5]); + } + break; + case IPA_LINK_UP_EVENT: + IPACMDBG_H("Recieved IPA_LINK_UP_EVENT event: link up %d: \n", evt_data->if_index); + ipa_interface_index = IPACM_Iface::iface_ipa_index_query(evt_data->if_index); + /* LTE-backhaul */ + if(IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].if_cat == EMBMS_IF) + { + IPACMDBG("WAN-EMBMS (%s) link already up, iface: %d: \n", IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name,evt_data->if_index); + } + else if(IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].if_cat == WAN_IF) + { + IPACMDBG_H("WAN-LTE (%s) link up, iface: %d: \n", IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name,evt_data->if_index); + ifmgr_data.if_index = evt_data->if_index; + ifmgr_data.if_type = Q6_WAN; + create_iface_instance(&ifmgr_data); + } + break; + + case IPA_USB_LINK_UP_EVENT: + IPACMDBG_H("Recieved IPA_USB_LINK_UP_EVENT event: link up %d: \n", evt_data->if_index); + ipa_interface_index = IPACM_Iface::iface_ipa_index_query(evt_data->if_index); + /* check if it's WAN_IF */ + if(IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].if_cat == WAN_IF) + { + /* usb-backhaul using sta_mode ECM_WAN*/ + IPACMDBG_H("WAN-usb (%s) link up, iface: %d: \n", IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name, evt_data->if_index); + ifmgr_data.if_index = evt_data->if_index; + ifmgr_data.if_type = ECM_WAN; + create_iface_instance(&ifmgr_data); + } + else + { + ifmgr_data.if_index = evt_data->if_index; + ifmgr_data.if_type = Q6_WAN; + create_iface_instance(&ifmgr_data); + } + break; + + case IPA_WLAN_AP_LINK_UP_EVENT: + ipa_interface_index = IPACM_Iface::iface_ipa_index_query(evt_data->if_index); + /* change iface category from unknown to WLAN_IF */ + if(IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].if_cat == UNKNOWN_IF) + { + IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].if_cat = WLAN_IF; + IPACMDBG_H("WLAN AP (%s) link up, iface: %d: \n", IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name,evt_data->if_index); + ifmgr_data.if_index = evt_data->if_index; + ifmgr_data.if_type = Q6_WAN; + create_iface_instance(&ifmgr_data); + } + else + { + IPACMDBG_H("iface %s already up and act as %d mode: \n",IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name,IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].if_cat); + } + break; + + case IPA_WLAN_STA_LINK_UP_EVENT: + ipa_interface_index = IPACM_Iface::iface_ipa_index_query(StaData->if_index); + /* change iface category from unknown to WAN_IF */ + if(IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].if_cat == UNKNOWN_IF) + { + /* wlan-backhaul using sta_mode WLAN_WAN */ + IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].if_cat = WAN_IF; + IPACMDBG_H("WLAN STA (%s) link up, iface: %d: \n", + IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name, StaData->if_index); + + ifmgr_data.if_index = StaData->if_index; + ifmgr_data.if_type = WLAN_WAN; + memcpy(ifmgr_data.mac_addr, StaData->mac_addr, sizeof(ifmgr_data.mac_addr)); + create_iface_instance(&ifmgr_data); + } + else + { + IPACMDBG_H("iface %s already up and act as %d mode: \n", + IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name, + IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].if_cat); + } + break; + + /* Add new instance open for eMBMS iface and wan iface */ + case IPA_WAN_EMBMS_LINK_UP_EVENT: + ipa_interface_index = IPACM_Iface::iface_ipa_index_query(evt_data->if_index); + /* change iface category from unknown to EMBMS_IF */ + if ((IPACM_Iface::ipacmcfg->ipacm_odu_enable == true) && (IPACM_Iface::ipacmcfg->ipacm_odu_embms_enable == true)) + { + IPACMDBG(" ODU-mode enable or not (%d) \n",IPACM_Iface::ipacmcfg->ipacm_odu_enable); + if(IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].if_cat == WAN_IF) + { + IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].if_cat=EMBMS_IF; + IPACMDBG("WAN eMBMS (%s) link up, iface: %d: \n", IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name,evt_data->if_index); + ifmgr_data.if_index = StaData->if_index; + ifmgr_data.if_type = Q6_WAN; + create_iface_instance(&ifmgr_data); + } + else + { + IPACMDBG("iface %s already up and act as %d mode: \n",IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name,IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].if_cat); + } + } + break; + + default: + break; + } + return; +} + +int IPACM_IfaceManager::create_iface_instance(ipacm_ifacemgr_data *param) +{ + int if_index = param->if_index; + ipacm_wan_iface_type is_sta_mode = param->if_type; + + int ipa_interface_index; + ipa_interface_index = IPACM_Iface::iface_ipa_index_query(if_index); + + if(ipa_interface_index == INVALID_IFACE) + { + IPACMDBG_H("Unhandled interface received, fid: %d\n",if_index); + return IPACM_SUCCESS; + } + + /* check if duplicate instance*/ + if(SearchInstance(ipa_interface_index) == IPA_INSTANCE_NOT_FOUND) + { + /* IPA_INSTANCE_NOT_FOUND */ + switch(IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].if_cat) + { + + case LAN_IF: + { + IPACMDBG_H("Creating Lan interface\n"); + IPACM_Lan *lan = new IPACM_Lan(ipa_interface_index); + IPACM_EvtDispatcher::registr(IPA_ADDR_ADD_EVENT, lan); + //IPACM_EvtDispatcher::registr(IPA_ROUTE_ADD_EVENT, lan); + //IPACM_EvtDispatcher::registr(IPA_ROUTE_DEL_EVENT, lan); + IPACM_EvtDispatcher::registr(IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT, lan); + IPACM_EvtDispatcher::registr(IPA_NEIGH_CLIENT_IP_ADDR_DEL_EVENT, lan); + IPACM_EvtDispatcher::registr(IPA_SW_ROUTING_ENABLE, lan); + IPACM_EvtDispatcher::registr(IPA_SW_ROUTING_DISABLE, lan); +#ifdef FEATURE_IPA_ANDROID + IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_UP_TETHER, lan); + IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_UP_V6_TETHER, lan); + IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_DOWN_TETHER, lan); + IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_DOWN_V6_TETHER, lan); +#else + IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_UP, lan); + IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_UP_V6, lan); + IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_DOWN, lan); + IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_DOWN_V6, lan); +#endif + IPACM_EvtDispatcher::registr(IPA_CFG_CHANGE_EVENT, lan); // register for IPA_CFG_CHANGE event + IPACM_EvtDispatcher::registr(IPA_PRIVATE_SUBNET_CHANGE_EVENT, lan); // register for IPA_PRIVATE_SUBNET_CHANGE_EVENT event +#ifdef FEATURE_ETH_BRIDGE_LE + IPACM_EvtDispatcher::registr(IPA_ETH_BRIDGE_LAN_CLIENT_ADD_EVENT, lan); + IPACM_EvtDispatcher::registr(IPA_ETH_BRIDGE_LAN_CLIENT_DEL_EVENT, lan); + IPACM_EvtDispatcher::registr(IPA_ETH_BRIDGE_WLAN_CLIENT_ADD_EVENT, lan); + IPACM_EvtDispatcher::registr(IPA_ETH_BRIDGE_WLAN_CLIENT_DEL_EVENT, lan); + IPACM_EvtDispatcher::registr(IPA_ETH_BRIDGE_HDR_PROC_CTX_SET_EVENT, lan); + IPACM_EvtDispatcher::registr(IPA_ETH_BRIDGE_HDR_PROC_CTX_UNSET_EVENT, lan); +#endif +#ifdef FEATURE_IPA_ANDROID + IPACM_EvtDispatcher::registr(IPA_TETHERING_STATS_UPDATE_EVENT, lan); +#endif + IPACM_EvtDispatcher::registr(IPA_CRADLE_WAN_MODE_SWITCH, lan); + IPACM_EvtDispatcher::registr(IPA_LINK_DOWN_EVENT, lan); + IPACM_EvtDispatcher::registr(IPA_LAN_DELETE_SELF, lan); + IPACMDBG_H("ipa_LAN (%s):ipa_index (%d) instance open/registr ok\n", lan->dev_name, lan->ipa_if_num); + registr(ipa_interface_index, lan); + /* solve the new_addr comes earlier issue */ + IPACM_Iface::iface_addr_query(if_index); + } + break; + + case ETH_IF: + { + IPACMDBG_H("Creating ETH interface in router mode\n"); + IPACM_Lan *ETH = new IPACM_Lan(ipa_interface_index); + IPACM_EvtDispatcher::registr(IPA_ADDR_ADD_EVENT, ETH); + IPACM_EvtDispatcher::registr(IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT, ETH); + IPACM_EvtDispatcher::registr(IPA_SW_ROUTING_ENABLE, ETH); + IPACM_EvtDispatcher::registr(IPA_SW_ROUTING_DISABLE, ETH); + IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_UP, ETH); + IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_UP_V6, ETH); + IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_DOWN, ETH); + IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_DOWN_V6, ETH); + IPACM_EvtDispatcher::registr(IPA_CRADLE_WAN_MODE_SWITCH, ETH); + IPACM_EvtDispatcher::registr(IPA_LINK_DOWN_EVENT, ETH); + IPACM_EvtDispatcher::registr(IPA_LAN_DELETE_SELF, ETH); + IPACMDBG_H("ipa_LAN (%s):ipa_index (%d) instance open/registr ok\n", ETH->dev_name, ETH->ipa_if_num); + registr(ipa_interface_index, ETH); + /* solve the new_addr comes earlier issue */ + IPACM_Iface::iface_addr_query(if_index); + } + break; + + case ODU_IF: + { + if(IPACM_Iface::ipacmcfg->ipacm_odu_router_mode == true) + { + IPACMDBG_H("Creating ODU interface in router mode\n"); + IPACM_Lan *odu = new IPACM_Lan(ipa_interface_index); + IPACM_EvtDispatcher::registr(IPA_ADDR_ADD_EVENT, odu); + IPACM_EvtDispatcher::registr(IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT, odu); + IPACM_EvtDispatcher::registr(IPA_NEIGH_CLIENT_IP_ADDR_DEL_EVENT, odu); + IPACM_EvtDispatcher::registr(IPA_SW_ROUTING_ENABLE, odu); + IPACM_EvtDispatcher::registr(IPA_SW_ROUTING_DISABLE, odu); + IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_UP, odu); + IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_UP_V6, odu); + IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_DOWN, odu); + IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_DOWN_V6, odu); +#ifdef FEATURE_ETH_BRIDGE_LE + IPACM_EvtDispatcher::registr(IPA_ETH_BRIDGE_LAN_CLIENT_ADD_EVENT, odu); + IPACM_EvtDispatcher::registr(IPA_ETH_BRIDGE_LAN_CLIENT_DEL_EVENT, odu); + IPACM_EvtDispatcher::registr(IPA_ETH_BRIDGE_WLAN_CLIENT_ADD_EVENT, odu); + IPACM_EvtDispatcher::registr(IPA_ETH_BRIDGE_WLAN_CLIENT_DEL_EVENT, odu); + IPACM_EvtDispatcher::registr(IPA_ETH_BRIDGE_HDR_PROC_CTX_SET_EVENT, odu); + IPACM_EvtDispatcher::registr(IPA_ETH_BRIDGE_HDR_PROC_CTX_UNSET_EVENT, odu); +#endif + IPACM_EvtDispatcher::registr(IPA_CRADLE_WAN_MODE_SWITCH, odu); + IPACM_EvtDispatcher::registr(IPA_LINK_DOWN_EVENT, odu); + IPACM_EvtDispatcher::registr(IPA_LAN_DELETE_SELF, odu); + IPACMDBG_H("ipa_LAN (%s):ipa_index (%d) instance open/registr ok\n", odu->dev_name, odu->ipa_if_num); + registr(ipa_interface_index, odu); + /* solve the new_addr comes earlier issue */ + IPACM_Iface::iface_addr_query(if_index); + } + else + { + IPACMDBG_H("Creating ODU interface in bridge mode\n"); + IPACM_Lan *odu = new IPACM_Lan(ipa_interface_index); + IPACM_EvtDispatcher::registr(IPA_ADDR_ADD_EVENT, odu); + IPACM_EvtDispatcher::registr(IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT, odu); + IPACM_EvtDispatcher::registr(IPA_SW_ROUTING_ENABLE, odu); + IPACM_EvtDispatcher::registr(IPA_SW_ROUTING_DISABLE, odu); + IPACM_EvtDispatcher::registr(IPA_LINK_DOWN_EVENT, odu); + IPACM_EvtDispatcher::registr(IPA_LAN_DELETE_SELF, odu); + IPACMDBG_H("ipa_LAN (%s):ipa_index (%d) instance open/registr ok\n", odu->dev_name, odu->ipa_if_num); + registr(ipa_interface_index, odu); + /* solve the new_addr comes earlier issue */ + IPACM_Iface::iface_addr_query(if_index); + } + } + break; + + case WLAN_IF: + { + IPACMDBG_H("Creating WLan interface\n"); + IPACM_Wlan *wl = new IPACM_Wlan(ipa_interface_index); + IPACM_EvtDispatcher::registr(IPA_ADDR_ADD_EVENT, wl); + IPACM_EvtDispatcher::registr(IPA_ROUTE_DEL_EVENT, wl); + IPACM_EvtDispatcher::registr(IPA_WLAN_CLIENT_ADD_EVENT, wl); + IPACM_EvtDispatcher::registr(IPA_WLAN_CLIENT_ADD_EVENT_EX, wl); + IPACM_EvtDispatcher::registr(IPA_WLAN_CLIENT_DEL_EVENT, wl); + IPACM_EvtDispatcher::registr(IPA_WLAN_CLIENT_POWER_SAVE_EVENT, wl); + IPACM_EvtDispatcher::registr(IPA_WLAN_CLIENT_RECOVER_EVENT, wl); + IPACM_EvtDispatcher::registr(IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT, wl); + IPACM_EvtDispatcher::registr(IPA_SW_ROUTING_ENABLE, wl); + IPACM_EvtDispatcher::registr(IPA_SW_ROUTING_DISABLE, wl); +#ifdef FEATURE_IPA_ANDROID + IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_UP_TETHER, wl); + IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_UP_V6_TETHER, wl); + IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_DOWN_TETHER, wl); + IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_DOWN_V6_TETHER, wl); +#else + IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_UP, wl); + IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_UP_V6, wl); + IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_DOWN, wl); + IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_DOWN_V6, wl); +#endif + IPACM_EvtDispatcher::registr(IPA_PRIVATE_SUBNET_CHANGE_EVENT, wl); // register for IPA_PRIVATE_SUBNET_CHANGE_EVENT event +#ifdef FEATURE_ETH_BRIDGE_LE + IPACM_EvtDispatcher::registr(IPA_ETH_BRIDGE_LAN_CLIENT_ADD_EVENT, wl); + IPACM_EvtDispatcher::registr(IPA_ETH_BRIDGE_LAN_CLIENT_DEL_EVENT, wl); + IPACM_EvtDispatcher::registr(IPA_ETH_BRIDGE_HDR_PROC_CTX_SET_EVENT, wl); + IPACM_EvtDispatcher::registr(IPA_ETH_BRIDGE_HDR_PROC_CTX_UNSET_EVENT, wl); + IPACM_EvtDispatcher::registr(IPA_CFG_CHANGE_EVENT, wl); +#endif + IPACM_EvtDispatcher::registr(IPA_CRADLE_WAN_MODE_SWITCH, wl); + IPACM_EvtDispatcher::registr(IPA_WLAN_LINK_DOWN_EVENT, wl); + IPACM_EvtDispatcher::registr(IPA_LAN_DELETE_SELF, wl); +#ifndef FEATURE_IPA_ANDROID + IPACM_EvtDispatcher::registr(IPA_WLAN_SWITCH_TO_SCC, wl); + IPACM_EvtDispatcher::registr(IPA_WLAN_SWITCH_TO_MCC, wl); +#else + IPACM_EvtDispatcher::registr(IPA_TETHERING_STATS_UPDATE_EVENT, wl); +#endif + IPACMDBG_H("ipa_WLAN (%s):ipa_index (%d) instance open/registr ok\n", wl->dev_name, wl->ipa_if_num); + registr(ipa_interface_index, wl); + /* solve the new_addr comes earlier issue */ + IPACM_Iface::iface_addr_query(if_index); + } + break; + + case WAN_IF: + { + if((IPACM_Iface::ipacmcfg->ipacm_odu_enable == false) || (IPACM_Iface::ipacmcfg->ipacm_odu_router_mode == true)) + { + IPACMDBG_H("Creating Wan interface\n"); + IPACM_Wan *w; + if(is_sta_mode == WLAN_WAN) + { + w = new IPACM_Wan(ipa_interface_index, is_sta_mode, param->mac_addr); + } + else + { + w = new IPACM_Wan(ipa_interface_index, is_sta_mode, NULL); + } + IPACM_EvtDispatcher::registr(IPA_ADDR_ADD_EVENT, w); +#ifdef FEATURE_IPA_ANDROID + IPACM_EvtDispatcher::registr(IPA_WAN_UPSTREAM_ROUTE_ADD_EVENT, w); + IPACM_EvtDispatcher::registr(IPA_WAN_UPSTREAM_ROUTE_DEL_EVENT, w); + if(is_sta_mode == Q6_WAN) + { + IPACM_EvtDispatcher::registr(IPA_NETWORK_STATS_UPDATE_EVENT, w); + }; +#else/* defined(FEATURE_IPA_ANDROID) */ + IPACM_EvtDispatcher::registr(IPA_ROUTE_ADD_EVENT, w); + IPACM_EvtDispatcher::registr(IPA_ROUTE_DEL_EVENT, w); +#endif /* not defined(FEATURE_IPA_ANDROID)*/ + IPACM_EvtDispatcher::registr(IPA_FIREWALL_CHANGE_EVENT, w); + IPACM_EvtDispatcher::registr(IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT, w); + IPACM_EvtDispatcher::registr(IPA_SW_ROUTING_ENABLE, w); + IPACM_EvtDispatcher::registr(IPA_SW_ROUTING_DISABLE, w); + IPACM_EvtDispatcher::registr(IPA_CFG_CHANGE_EVENT, w); // register for IPA_CFG_CHANGE event + IPACM_EvtDispatcher::registr(IPA_WAN_XLAT_CONNECT_EVENT, w); + if(is_sta_mode == WLAN_WAN) + { + IPACM_EvtDispatcher::registr(IPA_WLAN_LINK_DOWN_EVENT, w); // for STA mode +#ifndef FEATURE_IPA_ANDROI + IPACM_EvtDispatcher::registr(IPA_WLAN_SWITCH_TO_SCC, w); + IPACM_EvtDispatcher::registr(IPA_WLAN_SWITCH_TO_MCC, w); +#endif + } + else + { + IPACM_EvtDispatcher::registr(IPA_LINK_DOWN_EVENT, w); + } + + IPACMDBG_H("ipa_WAN (%s):ipa_index (%d) instance open/registr ok\n", w->dev_name, w->ipa_if_num); + registr(ipa_interface_index, w); + /* solve the new_addr comes earlier issue */ + IPACM_Iface::iface_addr_query(if_index); + } + } + break; + + /* WAN-eMBMS instance */ + case EMBMS_IF: + { + IPACMDBG("Creating Wan-eMBSM interface\n"); + IPACM_Wan *embms = new IPACM_Wan(ipa_interface_index, is_sta_mode, NULL); + IPACM_EvtDispatcher::registr(IPA_LINK_DOWN_EVENT, embms); + IPACMDBG("ipa_WAN (%s):ipa_index (%d) instance open/registr ok\n", embms->dev_name, embms->ipa_if_num); + registr(ipa_interface_index, embms); + } + break; + + default: + IPACMDBG_H("Unhandled interface category received iface name: %s, category: %d\n", + IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name, + IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].if_cat); + return IPACM_SUCCESS; + } + } + return IPACM_SUCCESS; +} + + +int IPACM_IfaceManager::registr(int ipa_if_index, IPACM_Listener *obj) +{ + iface_instances *tmp = head,*nw; + + nw = (iface_instances *)malloc(sizeof(iface_instances)); + if(nw != NULL) + { + nw->ipa_if_index = ipa_if_index; + nw->obj = obj; + nw->next = NULL; + } + else + { + return IPACM_FAILURE; + } + + if(head == NULL) + { + head = nw; + } + else + { + while(tmp->next) + { + tmp = tmp->next; + } + tmp->next = nw; + } + return IPACM_SUCCESS; +} + +int IPACM_IfaceManager::deregistr(IPACM_Listener *param) +{ + iface_instances *tmp = head,*tmp1,*prev = head; + + while(tmp != NULL) + { + if(tmp->obj == param) + { + tmp1 = tmp; + if(tmp == head) + { + head = head->next; + } + else if(tmp->next == NULL) + { + prev->next = NULL; + } + else + { + prev->next = tmp->next; + } + + tmp = tmp->next; + free(tmp1); + } + else + { + prev = tmp; + tmp = tmp->next; + } + } + return IPACM_SUCCESS; +} + + +int IPACM_IfaceManager::SearchInstance(int ipa_if_index) +{ + + iface_instances *tmp = head; + + while(tmp != NULL) + { + if(ipa_if_index == tmp->ipa_if_index) + { + IPACMDBG_H("Find existed iface-instance name: %s\n", + IPACM_Iface::ipacmcfg->iface_table[ipa_if_index].iface_name); + return IPA_INSTANCE_FOUND; + } + tmp = tmp->next; + } + + IPACMDBG_H("No existed iface-instance name: %s,\n", + IPACM_Iface::ipacmcfg->iface_table[ipa_if_index].iface_name); + + return IPA_INSTANCE_NOT_FOUND; +} diff --git a/data-ipa-cfg-mgr/ipacm/src/IPACM_Lan.cpp b/data-ipa-cfg-mgr/ipacm/src/IPACM_Lan.cpp new file mode 100644 index 000000000..8dc09949e --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/src/IPACM_Lan.cpp @@ -0,0 +1,7206 @@ +/* +Copyright (c) 2013, The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: +* Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following +disclaimer in the documentation and/or other materials provided +with the distribution. + +* Neither the name of The Linux Foundation nor the names of its +contributors may be used to endorse or promote products derived +from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +/*! + @file + IPACM_Lan.cpp + + @brief + This file implements the LAN iface functionality. + + @Author + Skylar Chang + +*/ +#include +#include +#include +#include "IPACM_Netlink.h" +#include "IPACM_Lan.h" +#include "IPACM_Wan.h" +#include "IPACM_IfaceManager.h" +#include "linux/rmnet_ipa_fd_ioctl.h" +#include "linux/ipa_qmi_service_v01.h" +#include "linux/msm_ipa.h" +#include "IPACM_ConntrackListener.h" +#include +#include + +bool IPACM_Lan::odu_up = false; + +ipa_hdr_l2_type IPACM_Lan::lan_hdr_type = IPA_HDR_L2_NONE; +ipa_hdr_l2_type IPACM_Lan::wlan_hdr_type = IPA_HDR_L2_NONE; + +uint32_t IPACM_Lan::usb_hdr_template_hdl = 0; +uint32_t IPACM_Lan::wlan_hdr_template_hdl = 0; +uint32_t IPACM_Lan::cpe_hdr_template_hdl = 0; + +hdr_proc_ctx_info IPACM_Lan::lan_to_wlan_hdr_proc_ctx; +hdr_proc_ctx_info IPACM_Lan::wlan_to_usb_hdr_proc_ctx; +hdr_proc_ctx_info IPACM_Lan::wlan_to_cpe_hdr_proc_ctx; +hdr_proc_ctx_info IPACM_Lan::wlan_to_wlan_hdr_proc_ctx; +hdr_proc_ctx_info IPACM_Lan::usb_to_cpe_hdr_proc_ctx; +hdr_proc_ctx_info IPACM_Lan::cpe_to_usb_hdr_proc_ctx; + +eth_bridge_subnet_client_info IPACM_Lan::eth_bridge_wlan_client[IPA_LAN_TO_LAN_MAX_WLAN_CLIENT]; +eth_bridge_subnet_client_info IPACM_Lan::eth_bridge_lan_client[IPA_LAN_TO_LAN_MAX_LAN_CLIENT]; + +int IPACM_Lan::num_wlan_client = 0; +int IPACM_Lan::num_lan_client = 0; +bool IPACM_Lan::is_usb_up = false; +bool IPACM_Lan::is_cpe_up = false; + +IPACM_Lan::IPACM_Lan(int iface_index) : IPACM_Iface(iface_index) +{ + num_eth_client = 0; + header_name_count = 0; + ipv6_set = 0; + ipv4_header_set = false; + ipv6_header_set = false; + odu_route_rule_v4_hdl = NULL; + odu_route_rule_v6_hdl = NULL; + eth_client = NULL; + int m_fd_odu, ret = IPACM_SUCCESS; + uint32_t* hdr_template_ptr; + + Nat_App = NatApp::GetInstance(); + if (Nat_App == NULL) + { + IPACMERR("unable to get Nat App instance \n"); + return; + } + + /* support eth multiple clients */ + if(iface_query != NULL) + { + if(IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat != WLAN_IF) + { + eth_client_len = (sizeof(ipa_eth_client)) + (iface_query->num_tx_props * sizeof(eth_client_rt_hdl)); + eth_client = (ipa_eth_client *)calloc(IPA_MAX_NUM_ETH_CLIENTS, eth_client_len); + if (eth_client == NULL) + { + IPACMERR("unable to allocate memory\n"); + return; + } + } + + IPACMDBG_H(" IPACM->IPACM_Lan(%d) constructor: Tx:%d Rx:%d \n", ipa_if_num, + iface_query->num_tx_props, iface_query->num_rx_props); +#ifdef FEATURE_ETH_BRIDGE_LE + if((IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat == LAN_IF + || IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat == ODU_IF) && tx_prop != NULL) + { + if (IPACM_Lan::lan_hdr_type != IPA_HDR_L2_NONE && tx_prop->tx[0].hdr_l2_type != IPACM_Lan::lan_hdr_type) + { + IPACMERR("The LAN header format is not consistent! Now header format is %d.\n", tx_prop->tx[0].hdr_l2_type); + } + else + { + if(IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat == LAN_IF) + { + hdr_template_ptr = &IPACM_Lan::usb_hdr_template_hdl; + IPACM_Lan::is_usb_up = true; + } + else //else it is ODU_IF (cpe) + { + hdr_template_ptr = &IPACM_Lan::cpe_hdr_template_hdl; + IPACM_Lan::is_cpe_up = true; + } + + if(eth_bridge_get_hdr_template_hdl(hdr_template_ptr) == IPACM_FAILURE) + { + IPACMERR("Failed to setup lan hdr template.\n"); + } + else + { + IPACM_Lan::lan_hdr_type = tx_prop->tx[0].hdr_l2_type; + IPACMDBG_H("The LAN header format is %d.\n", tx_prop->tx[0].hdr_l2_type); + add_hdr_proc_ctx(); + } + } + } +#endif + /* ODU routing table initilization */ + if(IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat == ODU_IF) + { + odu_route_rule_v4_hdl = (uint32_t *)calloc(iface_query->num_tx_props, sizeof(uint32_t)); + odu_route_rule_v6_hdl = (uint32_t *)calloc(iface_query->num_tx_props, sizeof(uint32_t)); + if ((odu_route_rule_v4_hdl == NULL) || (odu_route_rule_v6_hdl == NULL)) + { + IPACMERR("unable to allocate memory\n"); + return; + } + } + } + + num_wan_ul_fl_rule_v4 = 0; + num_wan_ul_fl_rule_v6 = 0; + + memset(wan_ul_fl_rule_hdl_v4, 0, MAX_WAN_UL_FILTER_RULES * sizeof(uint32_t)); + memset(wan_ul_fl_rule_hdl_v6, 0, MAX_WAN_UL_FILTER_RULES * sizeof(uint32_t)); + + memset(lan2lan_flt_rule_hdl_v4, 0, MAX_OFFLOAD_PAIR * sizeof(lan2lan_flt_rule_hdl)); + num_lan2lan_flt_rule_v4 = 0; + + memset(lan2lan_flt_rule_hdl_v6, 0, MAX_OFFLOAD_PAIR * sizeof(lan2lan_flt_rule_hdl)); + num_lan2lan_flt_rule_v6 = 0; + + memset(lan2lan_hdr_hdl_v4, 0, MAX_OFFLOAD_PAIR*sizeof(lan2lan_hdr_hdl)); + memset(lan2lan_hdr_hdl_v6, 0, MAX_OFFLOAD_PAIR*sizeof(lan2lan_hdr_hdl)); + + memset(lan_client_flt_rule_hdl_v4, 0, IPA_LAN_TO_LAN_MAX_LAN_CLIENT * sizeof(lan2lan_flt_rule_hdl)); + memset(lan_client_flt_rule_hdl_v6, 0, IPA_LAN_TO_LAN_MAX_LAN_CLIENT * sizeof(lan2lan_flt_rule_hdl)); + memset(wlan_client_flt_rule_hdl_v4, 0, IPA_LAN_TO_LAN_MAX_WLAN_CLIENT * sizeof(lan2lan_flt_rule_hdl)); + memset(wlan_client_flt_rule_hdl_v6, 0, IPA_LAN_TO_LAN_MAX_WLAN_CLIENT * sizeof(lan2lan_flt_rule_hdl)); + + is_active = true; + memset(ipv4_icmp_flt_rule_hdl, 0, NUM_IPV4_ICMP_FLT_RULE * sizeof(uint32_t)); + memset(tcp_ctl_flt_rule_hdl_v4, 0, NUM_TCP_CTL_FLT_RULE*sizeof(uint32_t)); + memset(tcp_ctl_flt_rule_hdl_v6, 0, NUM_TCP_CTL_FLT_RULE*sizeof(uint32_t)); + is_mode_switch = false; + if_ipv4_subnet =0; + memset(private_fl_rule_hdl, 0, IPA_MAX_PRIVATE_SUBNET_ENTRIES * sizeof(uint32_t)); + memset(ipv6_prefix_flt_rule_hdl, 0, NUM_IPV6_PREFIX_FLT_RULE * sizeof(uint32_t)); + memset(ipv6_icmp_flt_rule_hdl, 0, NUM_IPV6_ICMP_FLT_RULE * sizeof(uint32_t)); + modem_ul_v4_set = false; + modem_ul_v6_set = false; + +#ifdef FEATURE_ETH_BRIDGE_LE + if(IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat == LAN_IF) + { + exp_index_v4 = IPV4_DEFAULT_FILTERTING_RULES + IPA_LAN_TO_LAN_MAX_WLAN_CLIENT + IPA_LAN_TO_LAN_MAX_CPE_CLIENT + NUM_IPV4_ICMP_FLT_RULE + IPACM_Iface::ipacmcfg->ipa_num_private_subnet; + exp_index_v6 = IPV6_DEFAULT_FILTERTING_RULES + IPA_LAN_TO_LAN_MAX_WLAN_CLIENT + IPA_LAN_TO_LAN_MAX_CPE_CLIENT + NUM_IPV6_ICMP_FLT_RULE + NUM_IPV6_PREFIX_FLT_RULE; + } + if(IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat == ODU_IF) + { + exp_index_v4 = IPV4_DEFAULT_FILTERTING_RULES + IPA_LAN_TO_LAN_MAX_WLAN_CLIENT + IPA_LAN_TO_LAN_MAX_USB_CLIENT + NUM_IPV4_ICMP_FLT_RULE + IPACM_Iface::ipacmcfg->ipa_num_private_subnet; + exp_index_v6 = IPV6_DEFAULT_FILTERTING_RULES + IPA_LAN_TO_LAN_MAX_WLAN_CLIENT + IPA_LAN_TO_LAN_MAX_USB_CLIENT + NUM_IPV6_ICMP_FLT_RULE + NUM_IPV6_PREFIX_FLT_RULE; + } +#else +#ifdef CT_OPT + exp_index_v4 = IPV4_DEFAULT_FILTERTING_RULES + MAX_OFFLOAD_PAIR + NUM_TCP_CTL_FLT_RULE + NUM_IPV4_ICMP_FLT_RULE +IPACM_Iface::ipacmcfg->ipa_num_private_subnet; + exp_index_v6 = IPV6_DEFAULT_FILTERTING_RULES + NUM_TCP_CTL_FLT_RULE + MAX_OFFLOAD_PAIR + NUM_IPV6_ICMP_FLT_RULE + NUM_IPV6_PREFIX_FLT_RULE; +#else + exp_index_v4 = IPV4_DEFAULT_FILTERTING_RULES + MAX_OFFLOAD_PAIR + NUM_IPV4_ICMP_FLT_RULE + IPACM_Iface::ipacmcfg->ipa_num_private_subnet; + exp_index_v6 = IPV6_DEFAULT_FILTERTING_RULES + MAX_OFFLOAD_PAIR + NUM_IPV6_ICMP_FLT_RULE + NUM_IPV6_PREFIX_FLT_RULE; +#endif +#ifdef FEATURE_IPA_ANDROID + exp_index_v4 = exp_index_v4 - IPACM_Iface::ipacmcfg->ipa_num_private_subnet + IPA_MAX_PRIVATE_SUBNET_ENTRIES; +#endif +#endif + + /* ODU routing table initilization */ + if(IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat == ODU_IF) + { + + /* only do one time ioctl to odu-driver to infrom in router or bridge mode*/ + if (IPACM_Lan::odu_up != true) + { + m_fd_odu = open(IPACM_Iface::ipacmcfg->DEVICE_NAME_ODU, O_RDWR); + if (0 == m_fd_odu) + { + IPACMERR("Failed opening %s.\n", IPACM_Iface::ipacmcfg->DEVICE_NAME_ODU); + return ; + } + + if(IPACM_Iface::ipacmcfg->ipacm_odu_router_mode == true) + { + ret = ioctl(m_fd_odu, ODU_BRIDGE_IOC_SET_MODE, ODU_BRIDGE_MODE_ROUTER); + IPACM_Iface::ipacmcfg->ipacm_odu_enable = true; + } + else + { + ret = ioctl(m_fd_odu, ODU_BRIDGE_IOC_SET_MODE, ODU_BRIDGE_MODE_BRIDGE); + IPACM_Iface::ipacmcfg->ipacm_odu_enable = true; + } + + if (ret) + { + IPACMERR("Failed tell odu-driver the mode\n"); + } + IPACMDBG("Tell odu-driver in router-mode(%d)\n", IPACM_Iface::ipacmcfg->ipacm_odu_router_mode); + IPACMDBG_H("odu is up: odu-driver in router-mode(%d) \n", IPACM_Iface::ipacmcfg->ipacm_odu_router_mode); + close(m_fd_odu); + IPACM_Lan::odu_up = true; + } + } + + int i; + each_client_rt_rule_count_v4 = 0; + each_client_rt_rule_count_v6 = 0; + if(iface_query != NULL && tx_prop != NULL) + { + for(i=0; inum_tx_props; i++) + { + if(tx_prop->tx[i].ip == IPA_IP_v4) + { + each_client_rt_rule_count_v4++; + } + else + { + each_client_rt_rule_count_v6++; + } + } + } + IPACMDBG_H("Need to add %d IPv4 and %d IPv6 routing rules for eth bridge for each client.\n", each_client_rt_rule_count_v4, each_client_rt_rule_count_v6); + + memset(eth_bridge_lan_client_flt_info, 0, IPA_LAN_TO_LAN_MAX_LAN_CLIENT * sizeof(eth_bridge_client_flt_info)); + memset(eth_bridge_wlan_client_flt_info, 0, IPA_LAN_TO_LAN_MAX_WLAN_CLIENT * sizeof(eth_bridge_client_flt_info)); + + lan_client_flt_info_count = 0; + wlan_client_flt_info_count = 0; + + eth_bridge_lan_client_rt_from_lan_info_v4 = NULL; + eth_bridge_lan_client_rt_from_lan_info_v6 = NULL; + eth_bridge_lan_client_rt_from_wlan_info_v4 = NULL; + eth_bridge_lan_client_rt_from_wlan_info_v6 = NULL; +#ifdef FEATURE_ETH_BRIDGE_LE + if(tx_prop != NULL) + { + client_rt_info_size_v4 = sizeof(eth_bridge_client_rt_info) + each_client_rt_rule_count_v4 * sizeof(uint32_t); + eth_bridge_lan_client_rt_from_lan_info_v4 = (eth_bridge_client_rt_info*)calloc(IPA_LAN_TO_LAN_MAX_LAN_CLIENT, client_rt_info_size_v4); + eth_bridge_lan_client_rt_from_wlan_info_v4 = (eth_bridge_client_rt_info*)calloc(IPA_LAN_TO_LAN_MAX_LAN_CLIENT, client_rt_info_size_v4); + client_rt_info_size_v6 = sizeof(eth_bridge_client_rt_info) + each_client_rt_rule_count_v6 * sizeof(uint32_t); + eth_bridge_lan_client_rt_from_lan_info_v6 = (eth_bridge_client_rt_info*)calloc(IPA_LAN_TO_LAN_MAX_WLAN_CLIENT, client_rt_info_size_v6); + eth_bridge_lan_client_rt_from_wlan_info_v6 = (eth_bridge_client_rt_info*)calloc(IPA_LAN_TO_LAN_MAX_WLAN_CLIENT, client_rt_info_size_v6); + + } +#endif + lan_client_rt_from_lan_info_count_v4 = 0; + lan_client_rt_from_lan_info_count_v6 = 0; + lan_client_rt_from_wlan_info_count_v4 = 0; + lan_client_rt_from_wlan_info_count_v6 = 0; + +#ifdef FEATURE_IPA_ANDROID + /* set the IPA-client pipe enum */ + if(IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat == LAN_IF) + { + handle_tethering_client(false, IPACM_CLIENT_USB); + } +#endif + return; +} + +IPACM_Lan::~IPACM_Lan() +{ + IPACM_EvtDispatcher::deregistr(this); + IPACM_IfaceManager::deregistr(this); + return; +} + + +/* LAN-iface's callback function */ +void IPACM_Lan::event_callback(ipa_cm_event_id event, void *param) +{ + if(is_active == false && event != IPA_LAN_DELETE_SELF) + { + IPACMDBG_H("The interface is no longer active, return.\n"); + return; + } + + int ipa_interface_index; + ipacm_ext_prop* ext_prop; + ipacm_event_iface_up* data_wan; + ipacm_event_iface_up_tehter* data_wan_tether; + + switch (event) + { + case IPA_LINK_DOWN_EVENT: + { + ipacm_event_data_fid *data = (ipacm_event_data_fid *)param; + ipa_interface_index = iface_ipa_index_query(data->if_index); + if (ipa_interface_index == ipa_if_num) + { + IPACMDBG_H("Received IPA_LINK_DOWN_EVENT\n"); + handle_down_evt(); + IPACM_Iface::ipacmcfg->DelNatIfaces(dev_name); // delete NAT-iface + return; + } + } + break; + + case IPA_CFG_CHANGE_EVENT: + { + if ( IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat != ipa_if_cate) + { + IPACMDBG_H("Received IPA_CFG_CHANGE_EVENT and category changed\n"); + /* delete previous instance */ + handle_down_evt(); + IPACM_Iface::ipacmcfg->DelNatIfaces(dev_name); // delete NAT-iface + is_mode_switch = true; // need post internal usb-link up event + return; + } + /* Add Natting iface to IPACM_Config if there is Rx/Tx property */ + if (rx_prop != NULL || tx_prop != NULL) + { + IPACMDBG_H(" Has rx/tx properties registered for iface %s, add for NATTING \n", dev_name); + IPACM_Iface::ipacmcfg->AddNatIfaces(dev_name); + } + } + break; + + case IPA_PRIVATE_SUBNET_CHANGE_EVENT: + { + ipacm_event_data_fid *data = (ipacm_event_data_fid *)param; + /* internel event: data->if_index is ipa_if_index */ + if (data->if_index == ipa_if_num) + { + IPACMDBG_H("Received IPA_PRIVATE_SUBNET_CHANGE_EVENT from itself posting, ignore\n"); + return; + } + else + { + IPACMDBG_H("Received IPA_PRIVATE_SUBNET_CHANGE_EVENT from other LAN iface \n"); +#ifdef FEATURE_IPA_ANDROID + handle_private_subnet_android(IPA_IP_v4); +#endif + IPACMDBG_H(" delete old private subnet rules, use new sets \n"); + return; + } + } + break; + + case IPA_LAN_DELETE_SELF: + { + ipacm_event_data_fid *data = (ipacm_event_data_fid *)param; + if(data->if_index == ipa_if_num) + { + IPACMDBG_H("Received IPA_LAN_DELETE_SELF event.\n"); + IPACMDBG_H("ipa_LAN (%s):ipa_index (%d) instance close \n", IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].iface_name, ipa_if_num); + /* posting link-up event for cradle use-case */ + if(is_mode_switch) + { + IPACMDBG_H("Posting IPA_USB_LINK_UP_EVENT event for (%s)\n", dev_name); + ipacm_cmd_q_data evt_data; + memset(&evt_data, 0, sizeof(evt_data)); + + ipacm_event_data_fid *data_fid = NULL; + data_fid = (ipacm_event_data_fid *)malloc(sizeof(ipacm_event_data_fid)); + if(data_fid == NULL) + { + IPACMERR("unable to allocate memory for IPA_USB_LINK_UP_EVENT data_fid\n"); + return; + } + if(IPACM_Iface::ipa_get_if_index(dev_name, &(data_fid->if_index))) + { + IPACMERR("Error while getting interface index for %s device", dev_name); + } + evt_data.event = IPA_USB_LINK_UP_EVENT; + evt_data.evt_data = data_fid; + //IPACMDBG_H("Posting event:%d\n", evt_data.event); + IPACM_EvtDispatcher::PostEvt(&evt_data); + } +#ifndef FEATURE_IPA_ANDROID + if(rx_prop != NULL) + { + if(IPACM_Iface::ipacmcfg->getFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4) != 0) + { + IPACMDBG_DMESG("### WARNING ### num ipv4 flt rules on client %d is not expected: %d expected value: 0", + rx_prop->rx[0].src_pipe, IPACM_Iface::ipacmcfg->getFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4)); + } + if(IPACM_Iface::ipacmcfg->getFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6) != 0) + { + IPACMDBG_DMESG("### WARNING ### num ipv6 flt rules on client %d is not expected: %d expected value: 0", + rx_prop->rx[0].src_pipe, IPACM_Iface::ipacmcfg->getFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6)); + } + } +#endif + delete this; + } + break; + } + + case IPA_ADDR_ADD_EVENT: + { + ipacm_event_data_addr *data = (ipacm_event_data_addr *)param; + ipa_interface_index = iface_ipa_index_query(data->if_index); + + if ( (data->iptype == IPA_IP_v4 && data->ipv4_addr == 0) || + (data->iptype == IPA_IP_v6 && + data->ipv6_addr[0] == 0 && data->ipv6_addr[1] == 0 && + data->ipv6_addr[2] == 0 && data->ipv6_addr[3] == 0) ) + { + IPACMDBG_H("Invalid address, ignore IPA_ADDR_ADD_EVENT event\n"); + return; + } + + + if (ipa_interface_index == ipa_if_num) + { + IPACMDBG_H("Received IPA_ADDR_ADD_EVENT\n"); + + /* only call ioctl for ODU iface with bridge mode */ + if((IPACM_Iface::ipacmcfg->ipacm_odu_enable == true) && (IPACM_Iface::ipacmcfg->ipacm_odu_router_mode == false) + && (IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat == ODU_IF)) + { + if((data->iptype == IPA_IP_v6) && (num_dft_rt_v6 == 0)) + { + handle_addr_evt_odu_bridge(data); + } +#ifdef FEATURE_IPA_ANDROID + add_dummy_private_subnet_flt_rule(data->iptype); + handle_private_subnet_android(data->iptype); +#else + handle_private_subnet(data->iptype); +#endif + } + else + { + + /* check v4 not setup before, v6 can have 2 iface ip */ + if( ((data->iptype != ip_type) && (ip_type != IPA_IP_MAX)) + || ((data->iptype==IPA_IP_v6) && (num_dft_rt_v6!=MAX_DEFAULT_v6_ROUTE_RULES))) + { + IPACMDBG_H("Got IPA_ADDR_ADD_EVENT ip-family:%d, v6 num %d: \n",data->iptype,num_dft_rt_v6); + if(handle_addr_evt(data) == IPACM_FAILURE) + { + return; + } + /* ADD ipv4 icmp rule */ + if (data->iptype == IPA_IP_v4) + { + install_ipv4_icmp_flt_rule(); + } + /* ADD ipv6 icmp rule */ + if ((num_dft_rt_v6 == 1) && (data->iptype == IPA_IP_v6)) + { + install_ipv6_icmp_flt_rule(); + } + +#ifdef FEATURE_IPA_ANDROID + add_dummy_private_subnet_flt_rule(data->iptype); + handle_private_subnet_android(data->iptype); +#else + handle_private_subnet(data->iptype); +#endif + + if (IPACM_Wan::isWanUP(ipa_if_num)) + { + if(data->iptype == IPA_IP_v4 || data->iptype == IPA_IP_MAX) + { + if(IPACM_Wan::backhaul_is_sta_mode == false) + { + ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(IPA_IP_v4); + handle_wan_up_ex(ext_prop, IPA_IP_v4, + IPACM_Wan::getXlat_Mux_Id()); + } + else + { + handle_wan_up(IPA_IP_v4); + } + } + } + + if(IPACM_Wan::isWanUP_V6(ipa_if_num)) + { + if((data->iptype == IPA_IP_v6 || data->iptype == IPA_IP_MAX) && num_dft_rt_v6 == 1) + { + install_ipv6_prefix_flt_rule(IPACM_Wan::backhaul_ipv6_prefix); + if(IPACM_Wan::backhaul_is_sta_mode == false) + { + ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(IPA_IP_v6); + handle_wan_up_ex(ext_prop, IPA_IP_v6, 0); + } + else + { + handle_wan_up(IPA_IP_v6); + } + } + } + + /* Post event to NAT */ + if (data->iptype == IPA_IP_v4) + { + ipacm_cmd_q_data evt_data; + ipacm_event_iface_up *info; + + info = (ipacm_event_iface_up *) + malloc(sizeof(ipacm_event_iface_up)); + if (info == NULL) + { + IPACMERR("Unable to allocate memory\n"); + return; + } + + memcpy(info->ifname, dev_name, IF_NAME_LEN); + info->ipv4_addr = data->ipv4_addr; + info->addr_mask = IPACM_Iface::ipacmcfg->private_subnet_table[0].subnet_mask; + + evt_data.event = IPA_HANDLE_LAN_UP; + evt_data.evt_data = (void *)info; + + /* Insert IPA_HANDLE_LAN_UP to command queue */ + IPACMDBG_H("posting IPA_HANDLE_LAN_UP for IPv4 with below information\n"); + IPACMDBG_H("IPv4 address:0x%x, IPv4 address mask:0x%x\n", + info->ipv4_addr, info->addr_mask); + IPACM_EvtDispatcher::PostEvt(&evt_data); + } + IPACMDBG_H("Finish handling IPA_ADDR_ADD_EVENT for ip-family(%d)\n", data->iptype); + } + + IPACMDBG_H("Finish handling IPA_ADDR_ADD_EVENT for ip-family(%d)\n", data->iptype); + /* checking if SW-RT_enable */ + if (IPACM_Iface::ipacmcfg->ipa_sw_rt_enable == true) + { + /* handle software routing enable event*/ + IPACMDBG_H("IPA_SW_ROUTING_ENABLE for iface: %s \n",IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].iface_name); + handle_software_routing_enable(); + } + + } + } + } + break; +#ifdef FEATURE_IPA_ANDROID + case IPA_HANDLE_WAN_UP_TETHER: + IPACMDBG_H("Received IPA_HANDLE_WAN_UP_TETHER event\n"); + + data_wan_tether = (ipacm_event_iface_up_tehter*)param; + if(data_wan_tether == NULL) + { + IPACMERR("No event data is found.\n"); + return; + } + IPACMDBG_H("Backhaul is sta mode?%d, if_index_tether:%d tether_if_name:%s\n", data_wan_tether->is_sta, + data_wan_tether->if_index_tether, + IPACM_Iface::ipacmcfg->iface_table[data_wan_tether->if_index_tether].iface_name); + if (data_wan_tether->if_index_tether == ipa_if_num) + { + if(ip_type == IPA_IP_v4 || ip_type == IPA_IP_MAX) + { + if(data_wan_tether->is_sta == false) + { + ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(IPA_IP_v4); + handle_wan_up_ex(ext_prop, IPA_IP_v4, 0); + } + else + { + handle_wan_up(IPA_IP_v4); + } + } + } + break; + + case IPA_HANDLE_WAN_UP_V6_TETHER: + IPACMDBG_H("Received IPA_HANDLE_WAN_UP_V6_TETHER event\n"); + + data_wan_tether = (ipacm_event_iface_up_tehter*)param; + if(data_wan_tether == NULL) + { + IPACMERR("No event data is found.\n"); + return; + } + IPACMDBG_H("Backhaul is sta mode?%d, if_index_tether:%d tether_if_name:%s\n", data_wan_tether->is_sta, + data_wan_tether->if_index_tether, + IPACM_Iface::ipacmcfg->iface_table[data_wan_tether->if_index_tether].iface_name); + if (data_wan_tether->if_index_tether == ipa_if_num) + { + if(ip_type == IPA_IP_v6 || ip_type == IPA_IP_MAX) + { + install_ipv6_prefix_flt_rule(data_wan_tether->ipv6_prefix); + if(data_wan_tether->is_sta == false) + { + ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(IPA_IP_v6); + handle_wan_up_ex(ext_prop, IPA_IP_v6, 0); + } + else + { + handle_wan_up(IPA_IP_v6); + } + } + } + break; + + case IPA_HANDLE_WAN_DOWN_TETHER: + IPACMDBG_H("Received IPA_HANDLE_WAN_DOWN_TETHER event\n"); + data_wan_tether = (ipacm_event_iface_up_tehter*)param; + if(data_wan_tether == NULL) + { + IPACMERR("No event data is found.\n"); + return; + } + IPACMDBG_H("Backhaul is sta mode?%d, if_index_tether:%d tether_if_name:%s\n", data_wan_tether->is_sta, + data_wan_tether->if_index_tether, + IPACM_Iface::ipacmcfg->iface_table[data_wan_tether->if_index_tether].iface_name); + if (data_wan_tether->if_index_tether == ipa_if_num) + { + if(ip_type == IPA_IP_v4 || ip_type == IPA_IP_MAX) + { + handle_wan_down(data_wan_tether->is_sta); + } + } + break; + + case IPA_HANDLE_WAN_DOWN_V6_TETHER: + IPACMDBG_H("Received IPA_HANDLE_WAN_DOWN_V6_TETHER event\n"); + data_wan_tether = (ipacm_event_iface_up_tehter*)param; + if(data_wan_tether == NULL) + { + IPACMERR("No event data is found.\n"); + return; + } + IPACMDBG_H("Backhaul is sta mode?%d, if_index_tether:%d tether_if_name:%s\n", data_wan_tether->is_sta, + data_wan_tether->if_index_tether, + IPACM_Iface::ipacmcfg->iface_table[data_wan_tether->if_index_tether].iface_name); + if (data_wan_tether->if_index_tether == ipa_if_num) + { + /* clean up v6 RT rules*/ + IPACMDBG_H("Received IPA_HANDLE_WAN_DOWN_V6_TETHER in LAN-instance and need clean up client IPv6 address \n"); + /* reset usb-client ipv6 rt-rules */ + handle_lan_client_reset_rt(IPA_IP_v6); + + if(ip_type == IPA_IP_v6 || ip_type == IPA_IP_MAX) + { + handle_wan_down_v6(data_wan_tether->is_sta); + } + } + break; +#else + case IPA_HANDLE_WAN_UP: + IPACMDBG_H("Received IPA_HANDLE_WAN_UP event\n"); + + data_wan = (ipacm_event_iface_up*)param; + if(data_wan == NULL) + { + IPACMERR("No event data is found.\n"); + return; + } + IPACMDBG_H("Backhaul is sta mode?%d\n", data_wan->is_sta); + if(ip_type == IPA_IP_v4 || ip_type == IPA_IP_MAX) + { + if(data_wan->is_sta == false) + { + ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(IPA_IP_v4); + handle_wan_up_ex(ext_prop, IPA_IP_v4, data_wan->xlat_mux_id); + } + else + { + handle_wan_up(IPA_IP_v4); + } + } + break; + + case IPA_HANDLE_WAN_UP_V6: + IPACMDBG_H("Received IPA_HANDLE_WAN_UP_V6 event\n"); + + data_wan = (ipacm_event_iface_up*)param; + if(data_wan == NULL) + { + IPACMERR("No event data is found.\n"); + return; + } + IPACMDBG_H("Backhaul is sta mode?%d\n", data_wan->is_sta); + if(ip_type == IPA_IP_v6 || ip_type == IPA_IP_MAX) + { + install_ipv6_prefix_flt_rule(data_wan->ipv6_prefix); + if(data_wan->is_sta == false) + { + ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(IPA_IP_v6); + handle_wan_up_ex(ext_prop, IPA_IP_v6, 0); + } + else + { + handle_wan_up(IPA_IP_v6); + } + } + break; + + case IPA_HANDLE_WAN_DOWN: + IPACMDBG_H("Received IPA_HANDLE_WAN_DOWN event\n"); + data_wan = (ipacm_event_iface_up*)param; + if(data_wan == NULL) + { + IPACMERR("No event data is found.\n"); + return; + } + IPACMDBG_H("Backhaul is sta mode?%d\n", data_wan->is_sta); + if(ip_type == IPA_IP_v4 || ip_type == IPA_IP_MAX) + { + handle_wan_down(data_wan->is_sta); + } + break; + + case IPA_HANDLE_WAN_DOWN_V6: + IPACMDBG_H("Received IPA_HANDLE_WAN_DOWN_V6 event\n"); + data_wan = (ipacm_event_iface_up*)param; + if(data_wan == NULL) + { + IPACMERR("No event data is found.\n"); + return; + } + /* clean up v6 RT rules*/ + IPACMDBG_H("Received IPA_WAN_V6_DOWN in LAN-instance and need clean up client IPv6 address \n"); + /* reset usb-client ipv6 rt-rules */ + handle_lan_client_reset_rt(IPA_IP_v6); + + IPACMDBG_H("Backhaul is sta mode?%d\n", data_wan->is_sta); + if(ip_type == IPA_IP_v6 || ip_type == IPA_IP_MAX) + { + handle_wan_down_v6(data_wan->is_sta); + } + break; +#endif + + case IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT: + { + ipacm_event_data_all *data = (ipacm_event_data_all *)param; + ipa_interface_index = iface_ipa_index_query(data->if_index); + IPACMDBG_H("Recieved IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT event \n"); + IPACMDBG_H("check iface %s category: %d\n",IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].iface_name, IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat); + + if ((ipa_interface_index == ipa_if_num) && (IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat == ODU_IF)) + { + IPACMDBG_H("ODU iface got v4-ip \n"); + /* first construc ODU full header */ + if ((ipv4_header_set == false) && (ipv6_header_set == false)) + { + /* construct ODU RT tbl */ + handle_odu_hdr_init(data->mac_addr); + if (IPACM_Iface::ipacmcfg->ipacm_odu_embms_enable == true) + { + handle_odu_route_add(); + IPACMDBG_H("construct ODU header and route rules, embms_flag (%d) \n", IPACM_Iface::ipacmcfg->ipacm_odu_embms_enable); + } + else + { + IPACMDBG_H("construct ODU header only, embms_flag (%d) \n", IPACM_Iface::ipacmcfg->ipacm_odu_embms_enable); + } + } + /* if ODU in bridge mode, directly return */ + if(IPACM_Iface::ipacmcfg->ipacm_odu_router_mode == false) + { + IPACMDBG_H("ODU is in bridge mode, no action \n"); + return; + } + } + + if (ipa_interface_index == ipa_if_num) + { + IPACMDBG_H("ETH iface got client \n"); + /* first construc ETH full header */ + handle_eth_hdr_init(data->mac_addr); + handle_lan2lan_client_active(data, IPA_LAN_CLIENT_ACTIVE); + IPACMDBG_H("construct ETH header and route rules \n"); + /* Associate with IP and construct RT-rule */ + if (handle_eth_client_ipaddr(data) == IPACM_FAILURE) + { + return; + } + handle_eth_client_route_rule(data->mac_addr, data->iptype); + if (data->iptype == IPA_IP_v4) + { + /* Add NAT rules after ipv4 RT rules are set */ + CtList->HandleNeighIpAddrAddEvt(data); + } +#ifdef FEATURE_ETH_BRIDGE_LE + if (IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat == LAN_IF) + { + if (IPACM_Lan::cpe_to_usb_hdr_proc_ctx.valid == true) + { + eth_bridge_add_lan_client_rt_rule(data->mac_addr, SRC_LAN, IPA_IP_v4); + eth_bridge_add_lan_client_rt_rule(data->mac_addr, SRC_LAN, IPA_IP_v6); + } + if (IPACM_Lan::wlan_to_usb_hdr_proc_ctx.valid == true) + { + eth_bridge_add_lan_client_rt_rule(data->mac_addr, SRC_WLAN, IPA_IP_v4); + eth_bridge_add_lan_client_rt_rule(data->mac_addr, SRC_WLAN, IPA_IP_v6); + } + } + if (IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat == ODU_IF) + { + if (IPACM_Lan::usb_to_cpe_hdr_proc_ctx.valid == true) + { + eth_bridge_add_lan_client_rt_rule(data->mac_addr, SRC_LAN, IPA_IP_v4); + eth_bridge_add_lan_client_rt_rule(data->mac_addr, SRC_LAN, IPA_IP_v6); + } + if (IPACM_Lan::wlan_to_cpe_hdr_proc_ctx.valid == true) + { + eth_bridge_add_lan_client_rt_rule(data->mac_addr, SRC_WLAN, IPA_IP_v4); + eth_bridge_add_lan_client_rt_rule(data->mac_addr, SRC_WLAN, IPA_IP_v6); + } + } + eth_bridge_post_lan_client_event(data->mac_addr, IPA_ETH_BRIDGE_LAN_CLIENT_ADD_EVENT); + eth_bridge_add_lan_client(data->mac_addr); +#endif + return; + } + } + break; + + case IPA_NEIGH_CLIENT_IP_ADDR_DEL_EVENT: + { + ipacm_event_data_all *data = (ipacm_event_data_all *)param; + ipa_interface_index = iface_ipa_index_query(data->if_index); + + IPACMDBG_H("Received IPA_NEIGH_CLIENT_IP_ADDR_DEL_EVENT event. \n"); + IPACMDBG_H("check iface %s category: %d\n",IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].iface_name, IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat); + /* if ODU in bridge mode, directly return */ + if ((ipa_interface_index == ipa_if_num) && (IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat == ODU_IF) + && (IPACM_Iface::ipacmcfg->ipacm_odu_router_mode == false)) + { + IPACMDBG_H("ODU is in bridge mode, no action \n"); + return; + } + + if (ipa_interface_index == ipa_if_num) + { + if (data->iptype == IPA_IP_v6) + { + handle_del_ipv6_addr(data); + return; + } +#ifdef FEATURE_ETH_BRIDGE_LE + if (IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat == LAN_IF) + { + if (IPACM_Lan::cpe_to_usb_hdr_proc_ctx.valid == true) + { + eth_bridge_del_lan_client_rt_rule(data->mac_addr, SRC_LAN); + } + if (IPACM_Lan::wlan_to_usb_hdr_proc_ctx.valid == true) + { + eth_bridge_del_lan_client_rt_rule(data->mac_addr, SRC_WLAN); + } + } + if (IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat == ODU_IF) + { + if (IPACM_Lan::usb_to_cpe_hdr_proc_ctx.valid == true) + { + eth_bridge_del_lan_client_rt_rule(data->mac_addr, SRC_LAN); + } + if (IPACM_Lan::wlan_to_cpe_hdr_proc_ctx.valid == true) + { + eth_bridge_del_lan_client_rt_rule(data->mac_addr, SRC_WLAN); + } + } + eth_bridge_post_lan_client_event(data->mac_addr, IPA_ETH_BRIDGE_LAN_CLIENT_DEL_EVENT); + eth_bridge_del_lan_client(data->mac_addr); +#endif + IPACMDBG_H("LAN iface delete client \n"); + handle_eth_client_down_evt(data->mac_addr); + handle_lan2lan_client_active(data, IPA_LAN_CLIENT_INACTIVE); + return; + } + } + break; + + case IPA_SW_ROUTING_ENABLE: + IPACMDBG_H("Received IPA_SW_ROUTING_ENABLE\n"); + /* handle software routing enable event*/ + handle_software_routing_enable(); + break; + + case IPA_SW_ROUTING_DISABLE: + IPACMDBG_H("Received IPA_SW_ROUTING_DISABLE\n"); + /* handle software routing disable event*/ + handle_software_routing_disable(); + break; + + case IPA_ETH_BRIDGE_LAN_CLIENT_ADD_EVENT: + { + IPACMDBG_H("Received IPA_ETH_BRIDGE_LAN_CLIENT_ADD_EVENT event.\n"); + ipacm_event_data_mac* mac = (ipacm_event_data_mac*)param; + if(mac != NULL) + { + if (mac->if_index == ipa_if_num) + { + IPACMDBG_H("The event was sent by same interface, if_index: %d ignore. \n", mac->if_index); + return; + } + if(ip_type == IPA_IP_v4 || ip_type == IPA_IP_MAX) + { + eth_bridge_add_lan_client_flt_rule(mac->mac_addr, IPA_IP_v4); + } + if(ip_type == IPA_IP_v6 || ip_type == IPA_IP_MAX) + { + eth_bridge_add_lan_client_flt_rule(mac->mac_addr, IPA_IP_v6); + } + } + else + { + IPACMERR("Event MAC is empty.\n"); + } + } + break; + + case IPA_ETH_BRIDGE_LAN_CLIENT_DEL_EVENT: + { + IPACMDBG_H("Received IPA_ETH_BRIDGE_LAN_CLIENT_DEL_EVENT event.\n"); + ipacm_event_data_mac* mac = (ipacm_event_data_mac*)param; + if(mac != NULL) + { + if (mac->if_index == ipa_if_num) + { + IPACMDBG_H("The event was sent by same interface, if_index: %d ignore. \n", mac->if_index); + return; + } + if(eth_bridge_del_lan_client_flt_rule(mac->mac_addr) == IPACM_FAILURE) + { + IPACMDBG_H("Failed to delete lan client MAC based flt rule.\n"); + } + } + else + { + IPACMERR("Event MAC is empty.\n"); + } + } + break; + + case IPA_ETH_BRIDGE_WLAN_CLIENT_ADD_EVENT: + { + IPACMDBG_H("Received IPA_ETH_BRIDGE_WLAN_CLIENT_ADD_EVENT event.\n"); + ipacm_event_data_mac* mac = (ipacm_event_data_mac*)param; + if(mac != NULL) + { + if(ip_type == IPA_IP_v4 || ip_type == IPA_IP_MAX) + { + eth_bridge_add_wlan_client_flt_rule(mac->mac_addr, IPA_IP_v4); + } + if(ip_type == IPA_IP_v6 || ip_type == IPA_IP_MAX) + { + eth_bridge_add_wlan_client_flt_rule(mac->mac_addr, IPA_IP_v6); + } + } + else + { + IPACMERR("Event MAC is empty.\n"); + } + } + break; + + case IPA_ETH_BRIDGE_WLAN_CLIENT_DEL_EVENT: + { + IPACMDBG_H("Received IPA_ETH_BRIDGE_WLAN_CLIENT_DEL_EVENT event.\n"); + ipacm_event_data_mac* mac = (ipacm_event_data_mac*)param; + if(mac != NULL) + { + if(eth_bridge_del_wlan_client_flt_rule(mac->mac_addr) == IPACM_FAILURE) + { + IPACMDBG_H("Failed to delete wlan client MAC based flt rule.\n"); + } + } + else + { + IPACMERR("Event MAC is empty.\n"); + } + } + break; + + case IPA_ETH_BRIDGE_HDR_PROC_CTX_SET_EVENT: + { + IPACMDBG_H("Received IPA_ETH_BRIDGE_HDR_PROC_CTX_SET_EVENT event.\n"); + int i; + ipacm_event_data_if_cat* cat = (ipacm_event_data_if_cat*)param; + if(cat == NULL) + { + IPACMERR("Event data is empty.\n"); + return; + } + if (cat->if_cat == IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat) + { + IPACMDBG_H("The event was sent by same interface, if_cat: %d ignore. \n", cat->if_cat); + return; + } + + for(i=0; iif_cat == WLAN_IF) + { + eth_bridge_add_lan_client_rt_rule(IPACM_Lan::eth_bridge_lan_client[i].mac, SRC_WLAN, IPA_IP_v4); + eth_bridge_add_lan_client_rt_rule(IPACM_Lan::eth_bridge_lan_client[i].mac, SRC_WLAN, IPA_IP_v6); + } + else + { + eth_bridge_add_lan_client_rt_rule(IPACM_Lan::eth_bridge_lan_client[i].mac, SRC_LAN, IPA_IP_v4); + eth_bridge_add_lan_client_rt_rule(IPACM_Lan::eth_bridge_lan_client[i].mac, SRC_LAN, IPA_IP_v6); + } + } + } + } + break; + + case IPA_ETH_BRIDGE_HDR_PROC_CTX_UNSET_EVENT: + { + IPACMDBG_H("Received IPA_ETH_BRIDGE_HDR_PROC_CTX_UNSET_EVENT event.\n"); + int i; + ipacm_event_data_if_cat* cat = (ipacm_event_data_if_cat*)param; + if(cat == NULL) + { + IPACMERR("Event data is empty.\n"); + return; + } + if (cat->if_cat == IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat) + { + IPACMDBG_H("The event was sent by same interface, if_cat: %d ignore.\n", cat->if_cat); + return; + } + + for(i=0; iif_cat == WLAN_IF) + { + eth_bridge_del_lan_client_rt_rule(IPACM_Lan::eth_bridge_lan_client[i].mac, SRC_WLAN); + } + else + { + eth_bridge_del_lan_client_rt_rule(IPACM_Lan::eth_bridge_lan_client[i].mac, SRC_LAN); + } + } + } + } + break; + + case IPA_CRADLE_WAN_MODE_SWITCH: + { + IPACMDBG_H("Received IPA_CRADLE_WAN_MODE_SWITCH event.\n"); + ipacm_event_cradle_wan_mode* wan_mode = (ipacm_event_cradle_wan_mode*)param; + if(wan_mode == NULL) + { + IPACMERR("Event data is empty.\n"); + return; + } + + if(wan_mode->cradle_wan_mode == BRIDGE) + { + handle_cradle_wan_mode_switch(true); + } + else + { + handle_cradle_wan_mode_switch(false); + } + } + break; + + case IPA_TETHERING_STATS_UPDATE_EVENT: + { + IPACMDBG_H("Received IPA_TETHERING_STATS_UPDATE_EVENT event.\n"); + if (IPACM_Wan::isWanUP(ipa_if_num) || IPACM_Wan::isWanUP_V6(ipa_if_num)) + { + if(IPACM_Wan::backhaul_is_sta_mode == false) /* LTE */ + { + ipa_get_data_stats_resp_msg_v01 *data = (ipa_get_data_stats_resp_msg_v01 *)param; + IPACMDBG("Received IPA_TETHERING_STATS_UPDATE_STATS ipa_stats_type: %d\n",data->ipa_stats_type); + IPACMDBG("Received %d UL, %d DL pipe stats\n",data->ul_src_pipe_stats_list_len, + data->dl_dst_pipe_stats_list_len); + if (data->ipa_stats_type != QMI_IPA_STATS_TYPE_PIPE_V01) + { + IPACMERR("not valid pipe stats enum(%d)\n", data->ipa_stats_type); + return; + } + handle_tethering_stats_event(data); + } + } + } + break; + + default: + break; + } + + return; +} + + +int IPACM_Lan::handle_del_ipv6_addr(ipacm_event_data_all *data) +{ + uint32_t tx_index; + uint32_t rt_hdl; + int num_v6, clnt_indx; + + clnt_indx = get_eth_client_index(data->mac_addr); + if (clnt_indx == IPACM_INVALID_INDEX) + { + IPACMERR("eth client not found/attached \n"); + return IPACM_FAILURE; + } + + if(data->iptype == IPA_IP_v6) + { + if ((data->ipv6_addr[0] != 0) || (data->ipv6_addr[1] != 0) || + (data->ipv6_addr[2] != 0) || (data->ipv6_addr[3] || 0)) + { + IPACMDBG_H("ipv6 address got: 0x%x:%x:%x:%x\n", data->ipv6_addr[0], data->ipv6_addr[1], data->ipv6_addr[2], data->ipv6_addr[3]); + for(num_v6=0;num_v6 < get_client_memptr(eth_client, clnt_indx)->ipv6_set;num_v6++) + { + if( data->ipv6_addr[0] == get_client_memptr(eth_client, clnt_indx)->v6_addr[num_v6][0] && + data->ipv6_addr[1] == get_client_memptr(eth_client, clnt_indx)->v6_addr[num_v6][1] && + data->ipv6_addr[2]== get_client_memptr(eth_client, clnt_indx)->v6_addr[num_v6][2] && + data->ipv6_addr[3] == get_client_memptr(eth_client, clnt_indx)->v6_addr[num_v6][3]) + { + IPACMDBG_H("ipv6 addr is found at position:%d for client:%d\n", num_v6, clnt_indx); + break; + } + } + } + if (num_v6 == IPV6_NUM_ADDR) + { + IPACMDBG_H("ipv6 addr is not found. \n"); + return IPACM_FAILURE; + } + + for(tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++) + { + if((tx_prop->tx[tx_index].ip == IPA_IP_v6) && (get_client_memptr(eth_client, clnt_indx)->route_rule_set_v6 != 0)) + { + IPACMDBG_H("Delete client index %d ipv6 RT-rules for %d-st ipv6 for tx:%d\n", clnt_indx, num_v6, tx_index); + rt_hdl = get_client_memptr(eth_client, clnt_indx)->eth_rt_hdl[tx_index].eth_rt_rule_hdl_v6[num_v6]; + if(m_routing.DeleteRoutingHdl(rt_hdl, IPA_IP_v6) == false) + { + return IPACM_FAILURE; + } + rt_hdl = get_client_memptr(eth_client, clnt_indx)->eth_rt_hdl[tx_index].eth_rt_rule_hdl_v6_wan[num_v6]; + if(m_routing.DeleteRoutingHdl(rt_hdl, IPA_IP_v6) == false) + { + return IPACM_FAILURE; + } + get_client_memptr(eth_client, clnt_indx)->ipv6_set--; + get_client_memptr(eth_client, clnt_indx)->route_rule_set_v6--; + + for(num_v6;num_v6< get_client_memptr(eth_client, clnt_indx)->ipv6_set;num_v6++) + { + get_client_memptr(eth_client, clnt_indx)->v6_addr[num_v6][0] = + get_client_memptr(eth_client, clnt_indx)->v6_addr[num_v6+1][0]; + get_client_memptr(eth_client, clnt_indx)->v6_addr[num_v6][1] = + get_client_memptr(eth_client, clnt_indx)->v6_addr[num_v6+1][1]; + get_client_memptr(eth_client, clnt_indx)->v6_addr[num_v6][2] = + get_client_memptr(eth_client, clnt_indx)->v6_addr[num_v6+1][2]; + get_client_memptr(eth_client, clnt_indx)->v6_addr[num_v6][3] = + get_client_memptr(eth_client, clnt_indx)->v6_addr[num_v6+1][3]; + get_client_memptr(eth_client, clnt_indx)->eth_rt_hdl[tx_index].eth_rt_rule_hdl_v6[num_v6] = + get_client_memptr(eth_client, clnt_indx)->eth_rt_hdl[tx_index].eth_rt_rule_hdl_v6[num_v6+1]; + get_client_memptr(eth_client, clnt_indx)->eth_rt_hdl[tx_index].eth_rt_rule_hdl_v6_wan[num_v6] = + get_client_memptr(eth_client, clnt_indx)->eth_rt_hdl[tx_index].eth_rt_rule_hdl_v6_wan[num_v6+1]; + } + } + } + } + return IPACM_SUCCESS; +} + +/* delete filter rule for wan_down event for IPv4*/ +int IPACM_Lan::handle_wan_down(bool is_sta_mode) +{ + ipa_fltr_installed_notif_req_msg_v01 flt_index; + int fd; + + fd = open(IPA_DEVICE_NAME, O_RDWR); + if (0 == fd) + { + IPACMERR("Failed opening %s.\n", IPA_DEVICE_NAME); + return IPACM_FAILURE; + } + + if(is_sta_mode == false) + { + if (num_wan_ul_fl_rule_v4 > MAX_WAN_UL_FILTER_RULES) + { + IPACMERR("number of wan_ul_fl_rule_v4 (%d) > MAX_WAN_UL_FILTER_RULES (%d), aborting...\n", num_wan_ul_fl_rule_v4, MAX_WAN_UL_FILTER_RULES); + close(fd); + return IPACM_FAILURE; + } + if (m_filtering.DeleteFilteringHdls(wan_ul_fl_rule_hdl_v4, + IPA_IP_v4, num_wan_ul_fl_rule_v4) == false) + { + IPACMERR("Error Deleting RuleTable(1) to Filtering, aborting...\n"); + close(fd); + return IPACM_FAILURE; + } + IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, num_wan_ul_fl_rule_v4); + + memset(wan_ul_fl_rule_hdl_v4, 0, MAX_WAN_UL_FILTER_RULES * sizeof(uint32_t)); + num_wan_ul_fl_rule_v4 = 0; + modem_ul_v4_set = false; + + memset(&flt_index, 0, sizeof(flt_index)); + flt_index.source_pipe_index = ioctl(fd, IPA_IOC_QUERY_EP_MAPPING, rx_prop->rx[0].src_pipe); + flt_index.install_status = IPA_QMI_RESULT_SUCCESS_V01; +#ifndef FEATURE_IPA_V3 + flt_index.filter_index_list_len = 0; +#else /* defined (FEATURE_IPA_V3) */ + flt_index.rule_id_valid = 1; + flt_index.rule_id_len = 0; +#endif + flt_index.embedded_pipe_index_valid = 1; + flt_index.embedded_pipe_index = ioctl(fd, IPA_IOC_QUERY_EP_MAPPING, IPA_CLIENT_APPS_LAN_WAN_PROD); + flt_index.retain_header_valid = 1; + flt_index.retain_header = 0; + flt_index.embedded_call_mux_id_valid = 1; + flt_index.embedded_call_mux_id = IPACM_Iface::ipacmcfg->GetQmapId(); + + if(false == m_filtering.SendFilteringRuleIndex(&flt_index)) + { + IPACMERR("Error sending filtering rule index, aborting...\n"); + close(fd); + return IPACM_FAILURE; + } + } + else + { + if (m_filtering.DeleteFilteringHdls(&lan_wan_fl_rule_hdl[0], IPA_IP_v4, 1) == false) + { + IPACMERR("Error Adding RuleTable(1) to Filtering, aborting...\n"); + close(fd); + return IPACM_FAILURE; + } + IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, 1); + } + + close(fd); + return IPACM_SUCCESS; +} + +/* handle new_address event*/ +int IPACM_Lan::handle_addr_evt(ipacm_event_data_addr *data) +{ + struct ipa_ioc_add_rt_rule *rt_rule; + struct ipa_rt_rule_add *rt_rule_entry; + const int NUM_RULES = 1; + int num_ipv6_addr; + int res = IPACM_SUCCESS; + + IPACMDBG_H("set route/filter rule ip-type: %d \n", data->iptype); + +/* Add private subnet*/ +#ifdef FEATURE_IPA_ANDROID +if (data->iptype == IPA_IP_v4) +{ + IPACMDBG_H("current IPACM private subnet_addr number(%d)\n", IPACM_Iface::ipacmcfg->ipa_num_private_subnet); + if_ipv4_subnet = (data->ipv4_addr >> 8) << 8; + IPACMDBG_H(" Add IPACM private subnet_addr as: 0x%x \n", if_ipv4_subnet); + if(IPACM_Iface::ipacmcfg->AddPrivateSubnet(if_ipv4_subnet, ipa_if_num) == false) + { + IPACMERR(" can't Add IPACM private subnet_addr as: 0x%x \n", if_ipv4_subnet); + } +} +#endif /* defined(FEATURE_IPA_ANDROID)*/ + + if (data->iptype == IPA_IP_v4) + { + rt_rule = (struct ipa_ioc_add_rt_rule *) + calloc(1, sizeof(struct ipa_ioc_add_rt_rule) + + NUM_RULES * sizeof(struct ipa_rt_rule_add)); + + if (!rt_rule) + { + IPACMERR("Error Locate ipa_ioc_add_rt_rule memory...\n"); + return IPACM_FAILURE; + } + + rt_rule->commit = 1; + rt_rule->num_rules = NUM_RULES; + rt_rule->ip = data->iptype; + rt_rule_entry = &rt_rule->rules[0]; + rt_rule_entry->at_rear = false; + rt_rule_entry->rule.dst = IPA_CLIENT_APPS_LAN_CONS; //go to A5 + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + strlcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_lan_v4.name, sizeof(rt_rule->rt_tbl_name)); + rt_rule_entry->rule.attrib.u.v4.dst_addr = data->ipv4_addr; + rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF; + if (false == m_routing.AddRoutingRule(rt_rule)) + { + IPACMERR("Routing rule addition failed!\n"); + res = IPACM_FAILURE; + goto fail; + } + else if (rt_rule_entry->status) + { + IPACMERR("rt rule adding failed. Result=%d\n", rt_rule_entry->status); + res = rt_rule_entry->status; + goto fail; + } + dft_rt_rule_hdl[0] = rt_rule_entry->rt_rule_hdl; + IPACMDBG_H("ipv4 iface rt-rule hdl1=0x%x\n", dft_rt_rule_hdl[0]); + /* initial multicast/broadcast/fragment filter rule */ +#ifdef FEATURE_ETH_BRIDGE_LE + init_fl_rule(data->iptype); + eth_bridge_handle_dummy_wlan_client_flt_rule(data->iptype); + eth_bridge_handle_dummy_lan_client_flt_rule(data->iptype); + eth_bridge_install_cache_wlan_client_flt_rule(data->iptype); + eth_bridge_install_cache_lan_client_flt_rule(data->iptype); +#else +#ifdef CT_OPT + install_tcp_ctl_flt_rule(IPA_IP_v4); +#endif + init_fl_rule(data->iptype); + add_dummy_lan2lan_flt_rule(data->iptype); +#endif + } + else + { + /* check if see that v6-addr already or not*/ + for(num_ipv6_addr=0;num_ipv6_addripv6_addr[0]) && + (ipv6_addr[num_ipv6_addr][1] == data->ipv6_addr[1]) && + (ipv6_addr[num_ipv6_addr][2] == data->ipv6_addr[2]) && + (ipv6_addr[num_ipv6_addr][3] == data->ipv6_addr[3])) + { + return IPACM_FAILURE; + break; + } + } + + rt_rule = (struct ipa_ioc_add_rt_rule *) + calloc(1, sizeof(struct ipa_ioc_add_rt_rule) + + NUM_RULES * sizeof(struct ipa_rt_rule_add)); + + if (!rt_rule) + { + IPACMERR("Error Locate ipa_ioc_add_rt_rule memory...\n"); + return IPACM_FAILURE; + } + + rt_rule->commit = 1; + rt_rule->num_rules = NUM_RULES; + rt_rule->ip = data->iptype; + strlcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_v6.name, sizeof(rt_rule->rt_tbl_name)); + + rt_rule_entry = &rt_rule->rules[0]; + rt_rule_entry->at_rear = false; + rt_rule_entry->rule.dst = IPA_CLIENT_APPS_LAN_CONS; //go to A5 + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = data->ipv6_addr[0]; + rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = data->ipv6_addr[1]; + rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = data->ipv6_addr[2]; + rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = data->ipv6_addr[3]; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF; + ipv6_addr[num_dft_rt_v6][0] = data->ipv6_addr[0]; + ipv6_addr[num_dft_rt_v6][1] = data->ipv6_addr[1]; + ipv6_addr[num_dft_rt_v6][2] = data->ipv6_addr[2]; + ipv6_addr[num_dft_rt_v6][3] = data->ipv6_addr[3]; + if (false == m_routing.AddRoutingRule(rt_rule)) + { + IPACMERR("Routing rule addition failed!\n"); + res = IPACM_FAILURE; + goto fail; + } + else if (rt_rule_entry->status) + { + IPACMERR("rt rule adding failed. Result=%d\n", rt_rule_entry->status); + res = rt_rule_entry->status; + goto fail; + } + dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES + 2*num_dft_rt_v6] = rt_rule_entry->rt_rule_hdl; + + /* setup same rule for v6_wan table*/ + strlcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.name, sizeof(rt_rule->rt_tbl_name)); + if (false == m_routing.AddRoutingRule(rt_rule)) + { + IPACMERR("Routing rule addition failed!\n"); + res = IPACM_FAILURE; + goto fail; + } + else if (rt_rule_entry->status) + { + IPACMERR("rt rule adding failed. Result=%d\n", rt_rule_entry->status); + res = rt_rule_entry->status; + goto fail; + } + dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES + 2*num_dft_rt_v6+1] = rt_rule_entry->rt_rule_hdl; + + IPACMDBG_H("ipv6 wan iface rt-rule hdl=0x%x hdl=0x%x, num_dft_rt_v6: %d \n", + dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES + 2*num_dft_rt_v6], + dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES + 2*num_dft_rt_v6+1],num_dft_rt_v6); + + if (num_dft_rt_v6 == 0) + { + /* initial multicast/broadcast/fragment filter rule */ +#ifdef FEATURE_ETH_BRIDGE_LE + eth_bridge_handle_dummy_wlan_client_flt_rule(data->iptype); + eth_bridge_handle_dummy_lan_client_flt_rule(data->iptype); + eth_bridge_install_cache_wlan_client_flt_rule(data->iptype); + eth_bridge_install_cache_lan_client_flt_rule(data->iptype); + init_fl_rule(data->iptype); +#else +#ifdef CT_OPT + install_tcp_ctl_flt_rule(IPA_IP_v6); +#endif + add_dummy_lan2lan_flt_rule(data->iptype); + init_fl_rule(data->iptype); +#endif + } + num_dft_rt_v6++; + IPACMDBG_H("number of default route rules %d\n", num_dft_rt_v6); + } + + IPACMDBG_H("finish route/filter rule ip-type: %d, res(%d)\n", data->iptype, res); + +fail: + free(rt_rule); + return res; +} + +/* configure private subnet filter rules*/ +int IPACM_Lan::handle_private_subnet(ipa_ip_type iptype) +{ + struct ipa_flt_rule_add flt_rule_entry; + int i; + + ipa_ioc_add_flt_rule *m_pFilteringTable; + + IPACMDBG_H("lan->handle_private_subnet(); set route/filter rule \n"); + + if (rx_prop == NULL) + { + IPACMDBG_H("No rx properties registered for iface %s\n", dev_name); + return IPACM_SUCCESS; + } + + if (iptype == IPA_IP_v4) + { + + m_pFilteringTable = (struct ipa_ioc_add_flt_rule *) + calloc(1, + sizeof(struct ipa_ioc_add_flt_rule) + + (IPACM_Iface::ipacmcfg->ipa_num_private_subnet) * sizeof(struct ipa_flt_rule_add) + ); + if (!m_pFilteringTable) + { + PERROR("Error Locate ipa_flt_rule_add memory...\n"); + return IPACM_FAILURE; + } + m_pFilteringTable->commit = 1; + m_pFilteringTable->ep = rx_prop->rx[0].src_pipe; + m_pFilteringTable->global = false; + m_pFilteringTable->ip = IPA_IP_v4; + m_pFilteringTable->num_rules = (uint8_t)IPACM_Iface::ipacmcfg->ipa_num_private_subnet; + + if (false == m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_lan_v4)) + { + IPACMERR("LAN m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_lan_v4=0x%p) Failed.\n", &IPACM_Iface::ipacmcfg->rt_tbl_lan_v4); + free(m_pFilteringTable); + return IPACM_FAILURE; + } + + /* Make LAN-traffic always go A5, use default IPA-RT table */ + if (false == m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_default_v4)) + { + IPACMERR("LAN m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_default_v4=0x%p) Failed.\n", &IPACM_Iface::ipacmcfg->rt_tbl_default_v4); + free(m_pFilteringTable); + return IPACM_FAILURE; + } + + for (i = 0; i < (IPACM_Iface::ipacmcfg->ipa_num_private_subnet); i++) + { + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); + flt_rule_entry.at_rear = true; + flt_rule_entry.rule.retain_hdr = 1; + flt_rule_entry.flt_rule_hdl = -1; + flt_rule_entry.status = -1; + flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING; + /* Support private subnet feature including guest-AP can't talk to primary AP etc */ + flt_rule_entry.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_default_v4.hdl; + IPACMDBG_H(" private filter rule use table: %s\n",IPACM_Iface::ipacmcfg->rt_tbl_default_v4.name); + + memcpy(&flt_rule_entry.rule.attrib, + &rx_prop->rx[0].attrib, + sizeof(flt_rule_entry.rule.attrib)); + flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; + flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = IPACM_Iface::ipacmcfg->private_subnet_table[i].subnet_mask; + flt_rule_entry.rule.attrib.u.v4.dst_addr = IPACM_Iface::ipacmcfg->private_subnet_table[i].subnet_addr; + memcpy(&(m_pFilteringTable->rules[i]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + IPACMDBG_H("Loop %d 5\n", i); + } + + if (false == m_filtering.AddFilteringRule(m_pFilteringTable)) + { + IPACMERR("Error Adding RuleTable(0) to Filtering, aborting...\n"); + free(m_pFilteringTable); + return IPACM_FAILURE; + } + IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, IPACM_Iface::ipacmcfg->ipa_num_private_subnet); + + /* copy filter rule hdls */ + for (i = 0; i < IPACM_Iface::ipacmcfg->ipa_num_private_subnet; i++) + { + private_fl_rule_hdl[i] = m_pFilteringTable->rules[i].flt_rule_hdl; + } + free(m_pFilteringTable); + } + else + { + IPACMDBG_H("No private subnet rules for ipv6 iface %s\n", dev_name); + } + return IPACM_SUCCESS; +} + + +/* for STA mode wan up: configure filter rule for wan_up event*/ +int IPACM_Lan::handle_wan_up(ipa_ip_type ip_type) +{ + struct ipa_flt_rule_add flt_rule_entry; + int len = 0; + ipa_ioc_add_flt_rule *m_pFilteringTable; + + IPACMDBG_H("set WAN interface as default filter rule\n"); + + if (rx_prop == NULL) + { + IPACMDBG_H("No rx properties registered for iface %s\n", dev_name); + return IPACM_SUCCESS; + } + + if(ip_type == IPA_IP_v4) + { + len = sizeof(struct ipa_ioc_add_flt_rule) + (1 * sizeof(struct ipa_flt_rule_add)); + m_pFilteringTable = (struct ipa_ioc_add_flt_rule *)calloc(1, len); + if (m_pFilteringTable == NULL) + { + PERROR("Error Locate ipa_flt_rule_add memory...\n"); + return IPACM_FAILURE; + } + + m_pFilteringTable->commit = 1; + m_pFilteringTable->ep = rx_prop->rx[0].src_pipe; + m_pFilteringTable->global = false; + m_pFilteringTable->ip = IPA_IP_v4; + m_pFilteringTable->num_rules = (uint8_t)1; + + IPACMDBG_H("Retrieving routing hanle for table: %s\n", + IPACM_Iface::ipacmcfg->rt_tbl_wan_v4.name); + if (false == m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_wan_v4)) + { + IPACMERR("m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_wan_v4=0x%p) Failed.\n", + &IPACM_Iface::ipacmcfg->rt_tbl_wan_v4); + free(m_pFilteringTable); + return IPACM_FAILURE; + } + IPACMDBG_H("Routing hanle for table: %d\n", IPACM_Iface::ipacmcfg->rt_tbl_wan_v4.hdl); + + + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); // Zero All Fields + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl = -1; + flt_rule_entry.status = -1; + if(IPACM_Wan::isWan_Bridge_Mode()) + { + flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING; + } + else + { + flt_rule_entry.rule.action = IPA_PASS_TO_SRC_NAT; //IPA_PASS_TO_ROUTING + } + flt_rule_entry.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_wan_v4.hdl; + + memcpy(&flt_rule_entry.rule.attrib, + &rx_prop->rx[0].attrib, + sizeof(flt_rule_entry.rule.attrib)); + + flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; + flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0x0; + flt_rule_entry.rule.attrib.u.v4.dst_addr = 0x0; + + memcpy(&m_pFilteringTable->rules[0], &flt_rule_entry, sizeof(flt_rule_entry)); + if (false == m_filtering.AddFilteringRule(m_pFilteringTable)) + { + IPACMERR("Error Adding RuleTable(0) to Filtering, aborting...\n"); + free(m_pFilteringTable); + return IPACM_FAILURE; + } + else + { + IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, 1); + IPACMDBG_H("flt rule hdl0=0x%x, status=0x%x\n", + m_pFilteringTable->rules[0].flt_rule_hdl, + m_pFilteringTable->rules[0].status); + } + + + /* copy filter hdls */ + lan_wan_fl_rule_hdl[0] = m_pFilteringTable->rules[0].flt_rule_hdl; + free(m_pFilteringTable); + } + else if(ip_type == IPA_IP_v6) + { + /* add default v6 filter rule */ + m_pFilteringTable = (struct ipa_ioc_add_flt_rule *) + calloc(1, sizeof(struct ipa_ioc_add_flt_rule) + + 1 * sizeof(struct ipa_flt_rule_add)); + + if (!m_pFilteringTable) + { + PERROR("Error Locate ipa_flt_rule_add memory...\n"); + return IPACM_FAILURE; + } + + m_pFilteringTable->commit = 1; + m_pFilteringTable->ep = rx_prop->rx[0].src_pipe; + m_pFilteringTable->global = false; + m_pFilteringTable->ip = IPA_IP_v6; + m_pFilteringTable->num_rules = (uint8_t)1; + + if (false == m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_v6)) + { + IPACMERR("m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_v6=0x%p) Failed.\n", &IPACM_Iface::ipacmcfg->rt_tbl_v6); + free(m_pFilteringTable); + return IPACM_FAILURE; + } + + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); + + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl = -1; + flt_rule_entry.status = -1; + flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING; + flt_rule_entry.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_v6.hdl; + + memcpy(&flt_rule_entry.rule.attrib, + &rx_prop->rx[0].attrib, + sizeof(flt_rule_entry.rule.attrib)); + + flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0x00000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[1] = 0x00000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = 0x00000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr[0] = 0X00000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = 0x00000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = 0x00000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X00000000; + + memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + if (false == m_filtering.AddFilteringRule(m_pFilteringTable)) + { + IPACMERR("Error Adding Filtering rule, aborting...\n"); + free(m_pFilteringTable); + return IPACM_FAILURE; + } + else + { + IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1); + IPACMDBG_H("flt rule hdl0=0x%x, status=0x%x\n", m_pFilteringTable->rules[0].flt_rule_hdl, m_pFilteringTable->rules[0].status); + } + + /* copy filter hdls */ + dft_v6fl_rule_hdl[IPV6_DEFAULT_FILTERTING_RULES] = m_pFilteringTable->rules[0].flt_rule_hdl; + free(m_pFilteringTable); + } + + return IPACM_SUCCESS; +} + +int IPACM_Lan::handle_wan_up_ex(ipacm_ext_prop *ext_prop, ipa_ip_type iptype, uint8_t xlat_mux_id) +{ + int fd, ret = IPACM_SUCCESS, cnt; + IPACM_Config* ipacm_config = IPACM_Iface::ipacmcfg; + struct ipa_ioc_write_qmapid mux; + + if(rx_prop != NULL) + { + /* give mud ID to IPA-driver for WLAN/LAN pkts */ + fd = open(IPA_DEVICE_NAME, O_RDWR); + if (0 == fd) + { + IPACMDBG_H("Failed opening %s.\n", IPA_DEVICE_NAME); + return IPACM_FAILURE; + } + + mux.qmap_id = ipacm_config->GetQmapId(); + for(cnt=0; cntnum_rx_props; cnt++) + { + mux.client = rx_prop->rx[cnt].src_pipe; + ret = ioctl(fd, IPA_IOC_WRITE_QMAPID, &mux); + if (ret) + { + IPACMERR("Failed to write mux id %d\n", mux.qmap_id); + close(fd); + return IPACM_FAILURE; + } + } + close(fd); + } + + /* check only add static UL filter rule once */ + if (num_dft_rt_v6 ==1 && iptype ==IPA_IP_v6 && modem_ul_v6_set == false) + { + IPACMDBG_H("IPA_IP_v6 num_dft_rt_v6 %d xlat_mux_id: %d modem_ul_v6_set: %d\n", num_dft_rt_v6, xlat_mux_id, modem_ul_v6_set); + ret = handle_uplink_filter_rule(ext_prop, iptype, xlat_mux_id); + modem_ul_v6_set = true; + } else if (iptype ==IPA_IP_v4 && modem_ul_v4_set == false) { + IPACMDBG_H("IPA_IP_v4 xlat_mux_id: %d, modem_ul_v4_set %d\n", xlat_mux_id, modem_ul_v4_set); + ret = handle_uplink_filter_rule(ext_prop, iptype, xlat_mux_id); + modem_ul_v4_set = true; + } else { + IPACMDBG_H("ip-type: %d modem_ul_v4_set: %d, modem_ul_v6_set %d\n", iptype, modem_ul_v4_set, modem_ul_v6_set); + } + return ret; +} + +/* handle ETH client initial, construct full headers (tx property) */ +int IPACM_Lan::handle_eth_hdr_init(uint8_t *mac_addr) +{ + +#define ETH_IFACE_INDEX_LEN 2 + + int res = IPACM_SUCCESS, len = 0; + char index[ETH_IFACE_INDEX_LEN]; + struct ipa_ioc_copy_hdr sCopyHeader; + struct ipa_ioc_add_hdr *pHeaderDescriptor = NULL; + uint32_t cnt; + int clnt_indx; + + clnt_indx = get_eth_client_index(mac_addr); + + if (clnt_indx != IPACM_INVALID_INDEX) + { + IPACMERR("eth client is found/attached already with index %d \n", clnt_indx); + return IPACM_FAILURE; + } + + /* add header to IPA */ + if (num_eth_client >= IPA_MAX_NUM_ETH_CLIENTS) + { + IPACMERR("Reached maximum number(%d) of eth clients\n", IPA_MAX_NUM_ETH_CLIENTS); + return IPACM_FAILURE; + } + + IPACMDBG_H("ETH client number: %d\n", num_eth_client); + + memcpy(get_client_memptr(eth_client, num_eth_client)->mac, + mac_addr, + sizeof(get_client_memptr(eth_client, num_eth_client)->mac)); + + + IPACMDBG_H("Received Client MAC %02x:%02x:%02x:%02x:%02x:%02x\n", + mac_addr[0], mac_addr[1], mac_addr[2], + mac_addr[3], mac_addr[4], mac_addr[5]); + + IPACMDBG_H("stored MAC %02x:%02x:%02x:%02x:%02x:%02x\n", + get_client_memptr(eth_client, num_eth_client)->mac[0], + get_client_memptr(eth_client, num_eth_client)->mac[1], + get_client_memptr(eth_client, num_eth_client)->mac[2], + get_client_memptr(eth_client, num_eth_client)->mac[3], + get_client_memptr(eth_client, num_eth_client)->mac[4], + get_client_memptr(eth_client, num_eth_client)->mac[5]); + + /* add header to IPA */ + if(tx_prop != NULL) + { + len = sizeof(struct ipa_ioc_add_hdr) + (1 * sizeof(struct ipa_hdr_add)); + pHeaderDescriptor = (struct ipa_ioc_add_hdr *)calloc(1, len); + if (pHeaderDescriptor == NULL) + { + IPACMERR("calloc failed to allocate pHeaderDescriptor\n"); + return IPACM_FAILURE; + } + + /* copy partial header for v4*/ + for (cnt=0; cntnum_tx_props; cnt++) + { + if(tx_prop->tx[cnt].ip==IPA_IP_v4) + { + IPACMDBG_H("Got partial v4-header name from %d tx props\n", cnt); + memset(&sCopyHeader, 0, sizeof(sCopyHeader)); + memcpy(sCopyHeader.name, + tx_prop->tx[cnt].hdr_name, + sizeof(sCopyHeader.name)); + + IPACMDBG_H("header name: %s in tx:%d\n", sCopyHeader.name,cnt); + if (m_header.CopyHeader(&sCopyHeader) == false) + { + PERROR("ioctl copy header failed"); + res = IPACM_FAILURE; + goto fail; + } + + IPACMDBG_H("header length: %d, paritial: %d\n", sCopyHeader.hdr_len, sCopyHeader.is_partial); + IPACMDBG_H("header eth2_ofst_valid: %d, eth2_ofst: %d\n", sCopyHeader.is_eth2_ofst_valid, sCopyHeader.eth2_ofst); + if (sCopyHeader.hdr_len > IPA_HDR_MAX_SIZE) + { + IPACMERR("header oversize\n"); + res = IPACM_FAILURE; + goto fail; + } + else + { + memcpy(pHeaderDescriptor->hdr[0].hdr, + sCopyHeader.hdr, + sCopyHeader.hdr_len); + } + + /* copy client mac_addr to partial header */ + if (sCopyHeader.is_eth2_ofst_valid) + { + memcpy(&pHeaderDescriptor->hdr[0].hdr[sCopyHeader.eth2_ofst], + mac_addr, + IPA_MAC_ADDR_SIZE); + } + /* replace src mac to bridge mac_addr if any */ + if (IPACM_Iface::ipacmcfg->ipa_bridge_enable) + { + memcpy(&pHeaderDescriptor->hdr[0].hdr[sCopyHeader.eth2_ofst+IPA_MAC_ADDR_SIZE], + IPACM_Iface::ipacmcfg->bridge_mac, + IPA_MAC_ADDR_SIZE); + IPACMDBG_H("device is in bridge mode \n"); + } + + pHeaderDescriptor->commit = true; + pHeaderDescriptor->num_hdrs = 1; + + memset(pHeaderDescriptor->hdr[0].name, 0, + sizeof(pHeaderDescriptor->hdr[0].name)); + + snprintf(index,sizeof(index), "%d", ipa_if_num); + strlcpy(pHeaderDescriptor->hdr[0].name, index, sizeof(pHeaderDescriptor->hdr[0].name)); + pHeaderDescriptor->hdr[0].name[IPA_RESOURCE_NAME_MAX-1] = '\0'; + if (strlcat(pHeaderDescriptor->hdr[0].name, IPA_ETH_HDR_NAME_v4, sizeof(pHeaderDescriptor->hdr[0].name)) > IPA_RESOURCE_NAME_MAX) + { + IPACMERR(" header name construction failed exceed length (%d)\n", strlen(pHeaderDescriptor->hdr[0].name)); + res = IPACM_FAILURE; + goto fail; + } + + snprintf(index,sizeof(index), "%d", header_name_count); + if (strlcat(pHeaderDescriptor->hdr[0].name, index, sizeof(pHeaderDescriptor->hdr[0].name)) > IPA_RESOURCE_NAME_MAX) + { + IPACMERR(" header name construction failed exceed length (%d)\n", strlen(pHeaderDescriptor->hdr[0].name)); + res = IPACM_FAILURE; + goto fail; + } + + pHeaderDescriptor->hdr[0].hdr_len = sCopyHeader.hdr_len; + pHeaderDescriptor->hdr[0].hdr_hdl = -1; + pHeaderDescriptor->hdr[0].is_partial = 0; + pHeaderDescriptor->hdr[0].status = -1; + + if (m_header.AddHeader(pHeaderDescriptor) == false || + pHeaderDescriptor->hdr[0].status != 0) + { + IPACMERR("ioctl IPA_IOC_ADD_HDR failed: %d\n", pHeaderDescriptor->hdr[0].status); + res = IPACM_FAILURE; + goto fail; + } + + get_client_memptr(eth_client, num_eth_client)->hdr_hdl_v4 = pHeaderDescriptor->hdr[0].hdr_hdl; + IPACMDBG_H("eth-client(%d) v4 full header name:%s header handle:(0x%x)\n", + num_eth_client, + pHeaderDescriptor->hdr[0].name, + get_client_memptr(eth_client, num_eth_client)->hdr_hdl_v4); + get_client_memptr(eth_client, num_eth_client)->ipv4_header_set=true; + + break; + } + } + + + /* copy partial header for v6*/ + for (cnt=0; cntnum_tx_props; cnt++) + { + if(tx_prop->tx[cnt].ip==IPA_IP_v6) + { + + IPACMDBG_H("Got partial v6-header name from %d tx props\n", cnt); + memset(&sCopyHeader, 0, sizeof(sCopyHeader)); + memcpy(sCopyHeader.name, + tx_prop->tx[cnt].hdr_name, + sizeof(sCopyHeader.name)); + + IPACMDBG_H("header name: %s in tx:%d\n", sCopyHeader.name,cnt); + if (m_header.CopyHeader(&sCopyHeader) == false) + { + PERROR("ioctl copy header failed"); + res = IPACM_FAILURE; + goto fail; + } + + IPACMDBG_H("header length: %d, paritial: %d\n", sCopyHeader.hdr_len, sCopyHeader.is_partial); + IPACMDBG_H("header eth2_ofst_valid: %d, eth2_ofst: %d\n", sCopyHeader.is_eth2_ofst_valid, sCopyHeader.eth2_ofst); + if (sCopyHeader.hdr_len > IPA_HDR_MAX_SIZE) + { + IPACMERR("header oversize\n"); + res = IPACM_FAILURE; + goto fail; + } + else + { + memcpy(pHeaderDescriptor->hdr[0].hdr, + sCopyHeader.hdr, + sCopyHeader.hdr_len); + } + + /* copy client mac_addr to partial header */ + if (sCopyHeader.is_eth2_ofst_valid) + { + memcpy(&pHeaderDescriptor->hdr[0].hdr[sCopyHeader.eth2_ofst], + mac_addr, + IPA_MAC_ADDR_SIZE); + } + /* replace src mac to bridge mac_addr if any */ + if (IPACM_Iface::ipacmcfg->ipa_bridge_enable) + { + memcpy(&pHeaderDescriptor->hdr[0].hdr[sCopyHeader.eth2_ofst+IPA_MAC_ADDR_SIZE], + IPACM_Iface::ipacmcfg->bridge_mac, + IPA_MAC_ADDR_SIZE); + IPACMDBG_H("device is in bridge mode \n"); + } + + pHeaderDescriptor->commit = true; + pHeaderDescriptor->num_hdrs = 1; + + memset(pHeaderDescriptor->hdr[0].name, 0, + sizeof(pHeaderDescriptor->hdr[0].name)); + + snprintf(index,sizeof(index), "%d", ipa_if_num); + strlcpy(pHeaderDescriptor->hdr[0].name, index, sizeof(pHeaderDescriptor->hdr[0].name)); + pHeaderDescriptor->hdr[0].name[IPA_RESOURCE_NAME_MAX-1] = '\0'; + if (strlcat(pHeaderDescriptor->hdr[0].name, IPA_ETH_HDR_NAME_v6, sizeof(pHeaderDescriptor->hdr[0].name)) > IPA_RESOURCE_NAME_MAX) + { + IPACMERR(" header name construction failed exceed length (%d)\n", strlen(pHeaderDescriptor->hdr[0].name)); + res = IPACM_FAILURE; + goto fail; + } + snprintf(index,sizeof(index), "%d", header_name_count); + if (strlcat(pHeaderDescriptor->hdr[0].name, index, sizeof(pHeaderDescriptor->hdr[0].name)) > IPA_RESOURCE_NAME_MAX) + { + IPACMERR(" header name construction failed exceed length (%d)\n", strlen(pHeaderDescriptor->hdr[0].name)); + res = IPACM_FAILURE; + goto fail; + } + + pHeaderDescriptor->hdr[0].hdr_len = sCopyHeader.hdr_len; + pHeaderDescriptor->hdr[0].hdr_hdl = -1; + pHeaderDescriptor->hdr[0].is_partial = 0; + pHeaderDescriptor->hdr[0].status = -1; + + if (m_header.AddHeader(pHeaderDescriptor) == false || + pHeaderDescriptor->hdr[0].status != 0) + { + IPACMERR("ioctl IPA_IOC_ADD_HDR failed: %d\n", pHeaderDescriptor->hdr[0].status); + res = IPACM_FAILURE; + goto fail; + } + + get_client_memptr(eth_client, num_eth_client)->hdr_hdl_v6 = pHeaderDescriptor->hdr[0].hdr_hdl; + IPACMDBG_H("eth-client(%d) v6 full header name:%s header handle:(0x%x)\n", + num_eth_client, + pHeaderDescriptor->hdr[0].name, + get_client_memptr(eth_client, num_eth_client)->hdr_hdl_v6); + + get_client_memptr(eth_client, num_eth_client)->ipv6_header_set=true; + + break; + + } + } + /* initialize wifi client*/ + get_client_memptr(eth_client, num_eth_client)->route_rule_set_v4 = false; + get_client_memptr(eth_client, num_eth_client)->route_rule_set_v6 = 0; + get_client_memptr(eth_client, num_eth_client)->ipv4_set = false; + get_client_memptr(eth_client, num_eth_client)->ipv6_set = 0; + num_eth_client++; + header_name_count++; //keep increasing header_name_count + res = IPACM_SUCCESS; + IPACMDBG_H("eth client number: %d\n", num_eth_client); + } + else + { + return res; + } +fail: + free(pHeaderDescriptor); + return res; +} + +/*handle eth client */ +int IPACM_Lan::handle_eth_client_ipaddr(ipacm_event_data_all *data) +{ + int clnt_indx; + int v6_num; + + IPACMDBG_H("number of eth clients: %d\n", num_eth_client); + IPACMDBG_H("event MAC %02x:%02x:%02x:%02x:%02x:%02x\n", + data->mac_addr[0], + data->mac_addr[1], + data->mac_addr[2], + data->mac_addr[3], + data->mac_addr[4], + data->mac_addr[5]); + + clnt_indx = get_eth_client_index(data->mac_addr); + + if (clnt_indx == IPACM_INVALID_INDEX) + { + IPACMERR("eth client not found/attached \n"); + return IPACM_FAILURE; + } + + IPACMDBG_H("Ip-type received %d\n", data->iptype); + if (data->iptype == IPA_IP_v4) + { + IPACMDBG_H("ipv4 address: 0x%x\n", data->ipv4_addr); + if (data->ipv4_addr != 0) /* not 0.0.0.0 */ + { + if (get_client_memptr(eth_client, clnt_indx)->ipv4_set == false) + { + get_client_memptr(eth_client, clnt_indx)->v4_addr = data->ipv4_addr; + get_client_memptr(eth_client, clnt_indx)->ipv4_set = true; + } + else + { + /* check if client got new IPv4 address*/ + if(data->ipv4_addr == get_client_memptr(eth_client, clnt_indx)->v4_addr) + { + IPACMDBG_H("Already setup ipv4 addr for client:%d, ipv4 address didn't change\n", clnt_indx); + return IPACM_FAILURE; + } + else + { + IPACMDBG_H("ipv4 addr for client:%d is changed \n", clnt_indx); + /* delete NAT rules first */ + CtList->HandleNeighIpAddrDelEvt(get_client_memptr(eth_client, clnt_indx)->v4_addr); + delete_eth_rtrules(clnt_indx,IPA_IP_v4); + get_client_memptr(eth_client, clnt_indx)->route_rule_set_v4 = false; + get_client_memptr(eth_client, clnt_indx)->v4_addr = data->ipv4_addr; + } + } + } + else + { + IPACMDBG_H("Invalid client IPv4 address \n"); + return IPACM_FAILURE; + } + } + else + { + if ((data->ipv6_addr[0] != 0) || (data->ipv6_addr[1] != 0) || + (data->ipv6_addr[2] != 0) || (data->ipv6_addr[3] || 0)) /* check if all 0 not valid ipv6 address */ + { + IPACMDBG_H("ipv6 address: 0x%x:%x:%x:%x\n", data->ipv6_addr[0], data->ipv6_addr[1], data->ipv6_addr[2], data->ipv6_addr[3]); + if(get_client_memptr(eth_client, clnt_indx)->ipv6_set < IPV6_NUM_ADDR) + { + + for(v6_num=0;v6_num < get_client_memptr(eth_client, clnt_indx)->ipv6_set;v6_num++) + { + if( data->ipv6_addr[0] == get_client_memptr(eth_client, clnt_indx)->v6_addr[v6_num][0] && + data->ipv6_addr[1] == get_client_memptr(eth_client, clnt_indx)->v6_addr[v6_num][1] && + data->ipv6_addr[2]== get_client_memptr(eth_client, clnt_indx)->v6_addr[v6_num][2] && + data->ipv6_addr[3] == get_client_memptr(eth_client, clnt_indx)->v6_addr[v6_num][3]) + { + IPACMDBG_H("Already see this ipv6 addr at position: %d for client:%d\n", v6_num, clnt_indx); + return IPACM_FAILURE; /* not setup the RT rules*/ + } + } + + /* not see this ipv6 before for wifi client*/ + get_client_memptr(eth_client, clnt_indx)->v6_addr[get_client_memptr(eth_client, clnt_indx)->ipv6_set][0] = data->ipv6_addr[0]; + get_client_memptr(eth_client, clnt_indx)->v6_addr[get_client_memptr(eth_client, clnt_indx)->ipv6_set][1] = data->ipv6_addr[1]; + get_client_memptr(eth_client, clnt_indx)->v6_addr[get_client_memptr(eth_client, clnt_indx)->ipv6_set][2] = data->ipv6_addr[2]; + get_client_memptr(eth_client, clnt_indx)->v6_addr[get_client_memptr(eth_client, clnt_indx)->ipv6_set][3] = data->ipv6_addr[3]; + get_client_memptr(eth_client, clnt_indx)->ipv6_set++; + } + else + { + IPACMDBG_H("Already got 3 ipv6 addr for client:%d\n", clnt_indx); + return IPACM_FAILURE; /* not setup the RT rules*/ + } + } + } + + return IPACM_SUCCESS; +} + +/*handle eth client routing rule*/ +int IPACM_Lan::handle_eth_client_route_rule(uint8_t *mac_addr, ipa_ip_type iptype) +{ + struct ipa_ioc_add_rt_rule *rt_rule; + struct ipa_rt_rule_add *rt_rule_entry; + uint32_t tx_index; + int eth_index,v6_num; + const int NUM = 1; + + if(tx_prop == NULL) + { + IPACMDBG_H("No rx properties registered for iface %s\n", dev_name); + return IPACM_SUCCESS; + } + + IPACMDBG_H("Received mac_addr MAC %02x:%02x:%02x:%02x:%02x:%02x\n", + mac_addr[0], mac_addr[1], mac_addr[2], + mac_addr[3], mac_addr[4], mac_addr[5]); + + eth_index = get_eth_client_index(mac_addr); + if (eth_index == IPACM_INVALID_INDEX) + { + IPACMDBG_H("eth client not found/attached \n"); + return IPACM_SUCCESS; + } + + if (iptype==IPA_IP_v4) { + IPACMDBG_H("eth client index: %d, ip-type: %d, ipv4_set:%d, ipv4_rule_set:%d \n", eth_index, iptype, + get_client_memptr(eth_client, eth_index)->ipv4_set, + get_client_memptr(eth_client, eth_index)->route_rule_set_v4); + } else { + IPACMDBG_H("eth client index: %d, ip-type: %d, ipv6_set:%d, ipv6_rule_num:%d \n", eth_index, iptype, + get_client_memptr(eth_client, eth_index)->ipv6_set, + get_client_memptr(eth_client, eth_index)->route_rule_set_v6); + } + /* Add default routing rules if not set yet */ + if ((iptype == IPA_IP_v4 + && get_client_memptr(eth_client, eth_index)->route_rule_set_v4 == false + && get_client_memptr(eth_client, eth_index)->ipv4_set == true) + || (iptype == IPA_IP_v6 + && get_client_memptr(eth_client, eth_index)->route_rule_set_v6 < get_client_memptr(eth_client, eth_index)->ipv6_set + )) + { + + /* Add corresponding ipa_rm_resource_name of TX-endpoint up before IPV6 RT-rule set */ + IPACMDBG_H("dev %s add producer dependency\n", dev_name); + if (tx_prop != NULL) + { + IPACMDBG_H("depend Got pipe %d rm index : %d \n", tx_prop->tx[0].dst_pipe, IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe]); + IPACM_Iface::ipacmcfg->AddRmDepend(IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe],false); + } + rt_rule = (struct ipa_ioc_add_rt_rule *) + calloc(1, sizeof(struct ipa_ioc_add_rt_rule) + + NUM * sizeof(struct ipa_rt_rule_add)); + + if (rt_rule == NULL) + { + PERROR("Error Locate ipa_ioc_add_rt_rule memory...\n"); + return IPACM_FAILURE; + } + + rt_rule->commit = 1; + rt_rule->num_rules = (uint8_t)NUM; + rt_rule->ip = iptype; + + for (tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++) + { + if(iptype != tx_prop->tx[tx_index].ip) + { + IPACMDBG_H("Tx:%d, ip-type: %d conflict ip-type: %d no RT-rule added\n", + tx_index, tx_prop->tx[tx_index].ip,iptype); + continue; + } + + rt_rule_entry = &rt_rule->rules[0]; + rt_rule_entry->at_rear = 0; + + if (iptype == IPA_IP_v4) + { + IPACMDBG_H("client index(%d):ipv4 address: 0x%x\n", eth_index, + get_client_memptr(eth_client, eth_index)->v4_addr); + + IPACMDBG_H("client(%d): v4 header handle:(0x%x)\n", + eth_index, + get_client_memptr(eth_client, eth_index)->hdr_hdl_v4); + strlcpy(rt_rule->rt_tbl_name, + IPACM_Iface::ipacmcfg->rt_tbl_lan_v4.name, + sizeof(rt_rule->rt_tbl_name)); + rt_rule->rt_tbl_name[IPA_RESOURCE_NAME_MAX-1] = '\0'; + rt_rule_entry->rule.dst = tx_prop->tx[tx_index].dst_pipe; + memcpy(&rt_rule_entry->rule.attrib, + &tx_prop->tx[tx_index].attrib, + sizeof(rt_rule_entry->rule.attrib)); + rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; + rt_rule_entry->rule.hdr_hdl = get_client_memptr(eth_client, eth_index)->hdr_hdl_v4; + rt_rule_entry->rule.attrib.u.v4.dst_addr = get_client_memptr(eth_client, eth_index)->v4_addr; + rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF; + if (false == m_routing.AddRoutingRule(rt_rule)) + { + IPACMERR("Routing rule addition failed!\n"); + free(rt_rule); + return IPACM_FAILURE; + } + + /* copy ipv4 RT hdl */ + get_client_memptr(eth_client, eth_index)->eth_rt_hdl[tx_index].eth_rt_rule_hdl_v4 = + rt_rule->rules[0].rt_rule_hdl; + IPACMDBG_H("tx:%d, rt rule hdl=%x ip-type: %d\n", tx_index, + get_client_memptr(eth_client, eth_index)->eth_rt_hdl[tx_index].eth_rt_rule_hdl_v4, iptype); + + } else { + + for(v6_num = get_client_memptr(eth_client, eth_index)->route_rule_set_v6;v6_num < get_client_memptr(eth_client, eth_index)->ipv6_set;v6_num++) + { + IPACMDBG_H("client(%d): v6 header handle:(0x%x)\n", + eth_index, + get_client_memptr(eth_client, eth_index)->hdr_hdl_v6); + + /* v6 LAN_RT_TBL */ + strlcpy(rt_rule->rt_tbl_name, + IPACM_Iface::ipacmcfg->rt_tbl_v6.name, + sizeof(rt_rule->rt_tbl_name)); + rt_rule->rt_tbl_name[IPA_RESOURCE_NAME_MAX-1] = '\0'; + /* Support QCMAP LAN traffic feature, send to A5 */ + rt_rule_entry->rule.dst = IPA_CLIENT_APPS_LAN_CONS; + memset(&rt_rule_entry->rule.attrib, 0, sizeof(rt_rule_entry->rule.attrib)); + rt_rule_entry->rule.hdr_hdl = 0; + rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = get_client_memptr(eth_client, eth_index)->v6_addr[v6_num][0]; + rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = get_client_memptr(eth_client, eth_index)->v6_addr[v6_num][1]; + rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = get_client_memptr(eth_client, eth_index)->v6_addr[v6_num][2]; + rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = get_client_memptr(eth_client, eth_index)->v6_addr[v6_num][3]; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF; + if (false == m_routing.AddRoutingRule(rt_rule)) + { + IPACMERR("Routing rule addition failed!\n"); + free(rt_rule); + return IPACM_FAILURE; + } + + get_client_memptr(eth_client, eth_index)->eth_rt_hdl[tx_index].eth_rt_rule_hdl_v6[v6_num] = rt_rule->rules[0].rt_rule_hdl; + IPACMDBG_H("tx:%d, rt rule hdl=%x ip-type: %d\n", tx_index, + get_client_memptr(eth_client, eth_index)->eth_rt_hdl[tx_index].eth_rt_rule_hdl_v6[v6_num], iptype); + + /*Copy same rule to v6 WAN RT TBL*/ + strlcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.name, sizeof(rt_rule->rt_tbl_name)); + rt_rule->rt_tbl_name[IPA_RESOURCE_NAME_MAX-1] = '\0'; + /* Downlink traffic from Wan iface, directly through IPA */ + rt_rule_entry->rule.dst = tx_prop->tx[tx_index].dst_pipe; + memcpy(&rt_rule_entry->rule.attrib, + &tx_prop->tx[tx_index].attrib, + sizeof(rt_rule_entry->rule.attrib)); + rt_rule_entry->rule.hdr_hdl = get_client_memptr(eth_client, eth_index)->hdr_hdl_v6; + rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = get_client_memptr(eth_client, eth_index)->v6_addr[v6_num][0]; + rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = get_client_memptr(eth_client, eth_index)->v6_addr[v6_num][1]; + rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = get_client_memptr(eth_client, eth_index)->v6_addr[v6_num][2]; + rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = get_client_memptr(eth_client, eth_index)->v6_addr[v6_num][3]; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF; + if (false == m_routing.AddRoutingRule(rt_rule)) + { + IPACMERR("Routing rule addition failed!\n"); + free(rt_rule); + return IPACM_FAILURE; + } + + get_client_memptr(eth_client, eth_index)->eth_rt_hdl[tx_index].eth_rt_rule_hdl_v6_wan[v6_num] = rt_rule->rules[0].rt_rule_hdl; + IPACMDBG_H("tx:%d, rt rule hdl=%x ip-type: %d\n", tx_index, + get_client_memptr(eth_client, eth_index)->eth_rt_hdl[tx_index].eth_rt_rule_hdl_v6_wan[v6_num], iptype); + } + } + + } /* end of for loop */ + + free(rt_rule); + + if (iptype == IPA_IP_v4) + { + get_client_memptr(eth_client, eth_index)->route_rule_set_v4 = true; + } + else + { + get_client_memptr(eth_client, eth_index)->route_rule_set_v6 = get_client_memptr(eth_client, eth_index)->ipv6_set; + } + } + return IPACM_SUCCESS; +} + +/* handle odu client initial, construct full headers (tx property) */ +int IPACM_Lan::handle_odu_hdr_init(uint8_t *mac_addr) +{ + int res = IPACM_SUCCESS, len = 0; + struct ipa_ioc_copy_hdr sCopyHeader; + struct ipa_ioc_add_hdr *pHeaderDescriptor = NULL; + uint32_t cnt; + + IPACMDBG("Received Client MAC %02x:%02x:%02x:%02x:%02x:%02x\n", + mac_addr[0], mac_addr[1], mac_addr[2], + mac_addr[3], mac_addr[4], mac_addr[5]); + + /* add header to IPA */ + if(tx_prop != NULL) + { + len = sizeof(struct ipa_ioc_add_hdr) + (1 * sizeof(struct ipa_hdr_add)); + pHeaderDescriptor = (struct ipa_ioc_add_hdr *)calloc(1, len); + if (pHeaderDescriptor == NULL) + { + IPACMERR("calloc failed to allocate pHeaderDescriptor\n"); + return IPACM_FAILURE; + } + + /* copy partial header for v4*/ + for (cnt=0; cntnum_tx_props; cnt++) + { + if(tx_prop->tx[cnt].ip==IPA_IP_v4) + { + IPACMDBG("Got partial v4-header name from %d tx props\n", cnt); + memset(&sCopyHeader, 0, sizeof(sCopyHeader)); + memcpy(sCopyHeader.name, + tx_prop->tx[cnt].hdr_name, + sizeof(sCopyHeader.name)); + IPACMDBG("header name: %s in tx:%d\n", sCopyHeader.name,cnt); + if (m_header.CopyHeader(&sCopyHeader) == false) + { + PERROR("ioctl copy header failed"); + res = IPACM_FAILURE; + goto fail; + } + IPACMDBG("header length: %d, paritial: %d\n", sCopyHeader.hdr_len, sCopyHeader.is_partial); + if (sCopyHeader.hdr_len > IPA_HDR_MAX_SIZE) + { + IPACMERR("header oversize\n"); + res = IPACM_FAILURE; + goto fail; + } + else + { + memcpy(pHeaderDescriptor->hdr[0].hdr, + sCopyHeader.hdr, + sCopyHeader.hdr_len); + } + /* copy client mac_addr to partial header */ + if (sCopyHeader.is_eth2_ofst_valid) + { + memcpy(&pHeaderDescriptor->hdr[0].hdr[sCopyHeader.eth2_ofst], + mac_addr, + IPA_MAC_ADDR_SIZE); + } + /* replace src mac to bridge mac_addr if any */ + if (IPACM_Iface::ipacmcfg->ipa_bridge_enable) + { + memcpy(&pHeaderDescriptor->hdr[0].hdr[sCopyHeader.eth2_ofst+IPA_MAC_ADDR_SIZE], + IPACM_Iface::ipacmcfg->bridge_mac, + IPA_MAC_ADDR_SIZE); + IPACMDBG_H("device is in bridge mode \n"); + } + + pHeaderDescriptor->commit = true; + pHeaderDescriptor->num_hdrs = 1; + + memset(pHeaderDescriptor->hdr[0].name, 0, + sizeof(pHeaderDescriptor->hdr[0].name)); + strlcpy(pHeaderDescriptor->hdr[0].name, IPA_ODU_HDR_NAME_v4, sizeof(pHeaderDescriptor->hdr[0].name)); + pHeaderDescriptor->hdr[0].hdr_len = sCopyHeader.hdr_len; + pHeaderDescriptor->hdr[0].hdr_hdl = -1; + pHeaderDescriptor->hdr[0].is_partial = 0; + pHeaderDescriptor->hdr[0].status = -1; + + if (m_header.AddHeader(pHeaderDescriptor) == false || + pHeaderDescriptor->hdr[0].status != 0) + { + IPACMERR("ioctl IPA_IOC_ADD_HDR failed: %d\n", pHeaderDescriptor->hdr[0].status); + res = IPACM_FAILURE; + goto fail; + } + + ODU_hdr_hdl_v4 = pHeaderDescriptor->hdr[0].hdr_hdl; + ipv4_header_set = true ; + IPACMDBG(" ODU v4 full header name:%s header handle:(0x%x)\n", + pHeaderDescriptor->hdr[0].name, + ODU_hdr_hdl_v4); + break; + } + } + + + /* copy partial header for v6*/ + for (cnt=0; cntnum_tx_props; cnt++) + { + if(tx_prop->tx[cnt].ip==IPA_IP_v6) + { + + IPACMDBG("Got partial v6-header name from %d tx props\n", cnt); + memset(&sCopyHeader, 0, sizeof(sCopyHeader)); + memcpy(sCopyHeader.name, + tx_prop->tx[cnt].hdr_name, + sizeof(sCopyHeader.name)); + + IPACMDBG("header name: %s in tx:%d\n", sCopyHeader.name,cnt); + if (m_header.CopyHeader(&sCopyHeader) == false) + { + PERROR("ioctl copy header failed"); + res = IPACM_FAILURE; + goto fail; + } + + IPACMDBG("header length: %d, paritial: %d\n", sCopyHeader.hdr_len, sCopyHeader.is_partial); + if (sCopyHeader.hdr_len > IPA_HDR_MAX_SIZE) + { + IPACMERR("header oversize\n"); + res = IPACM_FAILURE; + goto fail; + } + else + { + memcpy(pHeaderDescriptor->hdr[0].hdr, + sCopyHeader.hdr, + sCopyHeader.hdr_len); + } + + /* copy client mac_addr to partial header */ + if (sCopyHeader.is_eth2_ofst_valid) + { + memcpy(&pHeaderDescriptor->hdr[0].hdr[sCopyHeader.eth2_ofst], + mac_addr, + IPA_MAC_ADDR_SIZE); + } + /* replace src mac to bridge mac_addr if any */ + if (IPACM_Iface::ipacmcfg->ipa_bridge_enable) + { + memcpy(&pHeaderDescriptor->hdr[0].hdr[sCopyHeader.eth2_ofst+IPA_MAC_ADDR_SIZE], + IPACM_Iface::ipacmcfg->bridge_mac, + IPA_MAC_ADDR_SIZE); + IPACMDBG_H("device is in bridge mode \n"); + } + + pHeaderDescriptor->commit = true; + pHeaderDescriptor->num_hdrs = 1; + + memset(pHeaderDescriptor->hdr[0].name, 0, + sizeof(pHeaderDescriptor->hdr[0].name)); + + strlcpy(pHeaderDescriptor->hdr[0].name, IPA_ODU_HDR_NAME_v6, sizeof(pHeaderDescriptor->hdr[0].name)); + pHeaderDescriptor->hdr[0].hdr_len = sCopyHeader.hdr_len; + pHeaderDescriptor->hdr[0].hdr_hdl = -1; + pHeaderDescriptor->hdr[0].is_partial = 0; + pHeaderDescriptor->hdr[0].status = -1; + + if (m_header.AddHeader(pHeaderDescriptor) == false || + pHeaderDescriptor->hdr[0].status != 0) + { + IPACMERR("ioctl IPA_IOC_ADD_HDR failed: %d\n", pHeaderDescriptor->hdr[0].status); + res = IPACM_FAILURE; + goto fail; + } + + ODU_hdr_hdl_v6 = pHeaderDescriptor->hdr[0].hdr_hdl; + ipv6_header_set = true ; + IPACMDBG(" ODU v4 full header name:%s header handle:(0x%x)\n", + pHeaderDescriptor->hdr[0].name, + ODU_hdr_hdl_v6); + break; + } + } + } +fail: + free(pHeaderDescriptor); + return res; +} + + +/* handle odu default route rule configuration */ +int IPACM_Lan::handle_odu_route_add() +{ + /* add default WAN route */ + struct ipa_ioc_add_rt_rule *rt_rule; + struct ipa_rt_rule_add *rt_rule_entry; + uint32_t tx_index; + const int NUM = 1; + + if(tx_prop == NULL) + { + IPACMDBG_H("No tx properties, ignore default route setting\n"); + return IPACM_SUCCESS; + } + + rt_rule = (struct ipa_ioc_add_rt_rule *) + calloc(1, sizeof(struct ipa_ioc_add_rt_rule) + + NUM * sizeof(struct ipa_rt_rule_add)); + + if (!rt_rule) + { + IPACMERR("Error Locate ipa_ioc_add_rt_rule memory...\n"); + return IPACM_FAILURE; + } + + rt_rule->commit = 1; + rt_rule->num_rules = (uint8_t)NUM; + + + IPACMDBG_H("WAN table created %s \n", rt_rule->rt_tbl_name); + rt_rule_entry = &rt_rule->rules[0]; + rt_rule_entry->at_rear = true; + + for (tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++) + { + + if (IPA_IP_v4 == tx_prop->tx[tx_index].ip) + { + strlcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_odu_v4.name, sizeof(rt_rule->rt_tbl_name)); + rt_rule_entry->rule.hdr_hdl = ODU_hdr_hdl_v4; + rt_rule->ip = IPA_IP_v4; + } + else + { + strlcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_odu_v6.name, sizeof(rt_rule->rt_tbl_name)); + rt_rule_entry->rule.hdr_hdl = ODU_hdr_hdl_v6; + rt_rule->ip = IPA_IP_v6; + } + + rt_rule_entry->rule.dst = tx_prop->tx[tx_index].dst_pipe; + memcpy(&rt_rule_entry->rule.attrib, + &tx_prop->tx[tx_index].attrib, + sizeof(rt_rule_entry->rule.attrib)); + + rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; + if (IPA_IP_v4 == tx_prop->tx[tx_index].ip) + { + rt_rule_entry->rule.attrib.u.v4.dst_addr = 0; + rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0; + if (false == m_routing.AddRoutingRule(rt_rule)) + { + IPACMERR("Routing rule addition failed!\n"); + free(rt_rule); + return IPACM_FAILURE; + } + odu_route_rule_v4_hdl[tx_index] = rt_rule_entry->rt_rule_hdl; + IPACMDBG_H("Got ipv4 ODU-route rule hdl:0x%x,tx:%d,ip-type: %d \n", + odu_route_rule_v4_hdl[tx_index], + tx_index, + IPA_IP_v4); + } + else + { + rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = 0; + rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = 0; + rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = 0; + rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = 0; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0; + if (false == m_routing.AddRoutingRule(rt_rule)) + { + IPACMERR("Routing rule addition failed!\n"); + free(rt_rule); + return IPACM_FAILURE; + } + odu_route_rule_v6_hdl[tx_index] = rt_rule_entry->rt_rule_hdl; + IPACMDBG_H("Set ipv6 ODU-route rule hdl for v6_lan_table:0x%x,tx:%d,ip-type: %d \n", + odu_route_rule_v6_hdl[tx_index], + tx_index, + IPA_IP_v6); + } + } + free(rt_rule); + return IPACM_SUCCESS; +} + +/* handle odu default route rule deletion */ +int IPACM_Lan::handle_odu_route_del() +{ + uint32_t tx_index; + + if(tx_prop == NULL) + { + IPACMDBG_H("No tx properties, ignore delete default route setting\n"); + return IPACM_SUCCESS; + } + + for (tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++) + { + if (tx_prop->tx[tx_index].ip == IPA_IP_v4) + { + IPACMDBG_H("Tx:%d, ip-type: %d match ip-type: %d, RT-rule deleted\n", + tx_index, tx_prop->tx[tx_index].ip,IPA_IP_v4); + + if (m_routing.DeleteRoutingHdl(odu_route_rule_v4_hdl[tx_index], IPA_IP_v4) + == false) + { + IPACMERR("IP-family:%d, Routing rule(hdl:0x%x) deletion failed with tx_index %d!\n", IPA_IP_v4, odu_route_rule_v4_hdl[tx_index], tx_index); + return IPACM_FAILURE; + } + } + else + { + IPACMDBG_H("Tx:%d, ip-type: %d match ip-type: %d, RT-rule deleted\n", + tx_index, tx_prop->tx[tx_index].ip,IPA_IP_v6); + + if (m_routing.DeleteRoutingHdl(odu_route_rule_v6_hdl[tx_index], IPA_IP_v6) + == false) + { + IPACMERR("IP-family:%d, Routing rule(hdl:0x%x) deletion failed with tx_index %d!\n", IPA_IP_v6, odu_route_rule_v6_hdl[tx_index], tx_index); + return IPACM_FAILURE; + } + } + } + + return IPACM_SUCCESS; +} + +/*handle eth client del mode*/ +int IPACM_Lan::handle_eth_client_down_evt(uint8_t *mac_addr) +{ + int clt_indx; + uint32_t tx_index; + int num_eth_client_tmp = num_eth_client; + int num_v6; + + IPACMDBG_H("total client: %d\n", num_eth_client_tmp); + + clt_indx = get_eth_client_index(mac_addr); + if (clt_indx == IPACM_INVALID_INDEX) + { + IPACMDBG_H("eth client not attached\n"); + return IPACM_SUCCESS; + } + + /* First reset nat rules and then route rules */ + if(get_client_memptr(eth_client, clt_indx)->ipv4_set == true) + { + IPACMDBG_H("Clean Nat Rules for ipv4:0x%x\n", get_client_memptr(eth_client, clt_indx)->v4_addr); + CtList->HandleNeighIpAddrDelEvt(get_client_memptr(eth_client, clt_indx)->v4_addr); + } + + if (delete_eth_rtrules(clt_indx, IPA_IP_v4)) + { + IPACMERR("unbale to delete ecm-client v4 route rules for index: %d\n", clt_indx); + return IPACM_FAILURE; + } + + if (delete_eth_rtrules(clt_indx, IPA_IP_v6)) + { + IPACMERR("unbale to delete ecm-client v6 route rules for index: %d\n", clt_indx); + return IPACM_FAILURE; + } + + /* Delete eth client header */ + if(get_client_memptr(eth_client, clt_indx)->ipv4_header_set == true) + { + if (m_header.DeleteHeaderHdl(get_client_memptr(eth_client, clt_indx)->hdr_hdl_v4) + == false) + { + return IPACM_FAILURE; + } + get_client_memptr(eth_client, clt_indx)->ipv4_header_set = false; + } + + if(get_client_memptr(eth_client, clt_indx)->ipv6_header_set == true) + { + if (m_header.DeleteHeaderHdl(get_client_memptr(eth_client, clt_indx)->hdr_hdl_v6) + == false) + { + return IPACM_FAILURE; + } + get_client_memptr(eth_client, clt_indx)->ipv6_header_set = false; + } + + /* Reset ip_set to 0*/ + get_client_memptr(eth_client, clt_indx)->ipv4_set = false; + get_client_memptr(eth_client, clt_indx)->ipv6_set = 0; + get_client_memptr(eth_client, clt_indx)->ipv4_header_set = false; + get_client_memptr(eth_client, clt_indx)->ipv6_header_set = false; + get_client_memptr(eth_client, clt_indx)->route_rule_set_v4 = false; + get_client_memptr(eth_client, clt_indx)->route_rule_set_v6 = 0; + + for (; clt_indx < num_eth_client_tmp - 1; clt_indx++) + { + memcpy(get_client_memptr(eth_client, clt_indx)->mac, + get_client_memptr(eth_client, (clt_indx + 1))->mac, + sizeof(get_client_memptr(eth_client, clt_indx)->mac)); + + get_client_memptr(eth_client, clt_indx)->hdr_hdl_v4 = get_client_memptr(eth_client, (clt_indx + 1))->hdr_hdl_v4; + get_client_memptr(eth_client, clt_indx)->hdr_hdl_v6 = get_client_memptr(eth_client, (clt_indx + 1))->hdr_hdl_v6; + get_client_memptr(eth_client, clt_indx)->v4_addr = get_client_memptr(eth_client, (clt_indx + 1))->v4_addr; + + get_client_memptr(eth_client, clt_indx)->ipv4_set = get_client_memptr(eth_client, (clt_indx + 1))->ipv4_set; + get_client_memptr(eth_client, clt_indx)->ipv6_set = get_client_memptr(eth_client, (clt_indx + 1))->ipv6_set; + get_client_memptr(eth_client, clt_indx)->ipv4_header_set = get_client_memptr(eth_client, (clt_indx + 1))->ipv4_header_set; + get_client_memptr(eth_client, clt_indx)->ipv6_header_set = get_client_memptr(eth_client, (clt_indx + 1))->ipv6_header_set; + + get_client_memptr(eth_client, clt_indx)->route_rule_set_v4 = get_client_memptr(eth_client, (clt_indx + 1))->route_rule_set_v4; + get_client_memptr(eth_client, clt_indx)->route_rule_set_v6 = get_client_memptr(eth_client, (clt_indx + 1))->route_rule_set_v6; + + for (num_v6=0;num_v6< get_client_memptr(eth_client, clt_indx)->ipv6_set;num_v6++) + { + get_client_memptr(eth_client, clt_indx)->v6_addr[num_v6][0] = get_client_memptr(eth_client, (clt_indx + 1))->v6_addr[num_v6][0]; + get_client_memptr(eth_client, clt_indx)->v6_addr[num_v6][1] = get_client_memptr(eth_client, (clt_indx + 1))->v6_addr[num_v6][1]; + get_client_memptr(eth_client, clt_indx)->v6_addr[num_v6][2] = get_client_memptr(eth_client, (clt_indx + 1))->v6_addr[num_v6][2]; + get_client_memptr(eth_client, clt_indx)->v6_addr[num_v6][3] = get_client_memptr(eth_client, (clt_indx + 1))->v6_addr[num_v6][3]; + } + + for (tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++) + { + get_client_memptr(eth_client, clt_indx)->eth_rt_hdl[tx_index].eth_rt_rule_hdl_v4 = + get_client_memptr(eth_client, (clt_indx + 1))->eth_rt_hdl[tx_index].eth_rt_rule_hdl_v4; + + for(num_v6=0;num_v6< get_client_memptr(eth_client, clt_indx)->route_rule_set_v6;num_v6++) + { + get_client_memptr(eth_client, clt_indx)->eth_rt_hdl[tx_index].eth_rt_rule_hdl_v6[num_v6] = + get_client_memptr(eth_client, (clt_indx + 1))->eth_rt_hdl[tx_index].eth_rt_rule_hdl_v6[num_v6]; + get_client_memptr(eth_client, clt_indx)->eth_rt_hdl[tx_index].eth_rt_rule_hdl_v6_wan[num_v6] = + get_client_memptr(eth_client, (clt_indx + 1))->eth_rt_hdl[tx_index].eth_rt_rule_hdl_v6_wan[num_v6]; + } + } + } + + IPACMDBG_H(" %d eth client deleted successfully \n", num_eth_client); + num_eth_client = num_eth_client - 1; + IPACMDBG_H(" Number of eth client: %d\n", num_eth_client); + + /* Del RM dependency */ + if(num_eth_client == 0) + { + /* Delete corresponding ipa_rm_resource_name of TX-endpoint after delete all IPV4V6 RT-rule*/ + IPACMDBG_H("dev %s add producer dependency\n", dev_name); + if (tx_prop != NULL) + { + IPACMDBG_H("depend Got pipe %d rm index : %d \n", tx_prop->tx[0].dst_pipe, IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe]); + IPACM_Iface::ipacmcfg->DelRmDepend(IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe]); + } + } + + return IPACM_SUCCESS; +} + +/*handle LAN iface down event*/ +int IPACM_Lan::handle_down_evt() +{ + int i; + int res = IPACM_SUCCESS; + uint32_t temp_eth_bridge_flt_rule[IPA_LAN_TO_LAN_MAX_WLAN_CLIENT]; + + IPACMDBG_H("lan handle_down_evt\n "); + if (IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat == ODU_IF) + { + /* delete ODU default RT rules */ + if (IPACM_Iface::ipacmcfg->ipacm_odu_embms_enable == true) + { + IPACMDBG_H("eMBMS enable, delete eMBMS DL RT rule\n"); + handle_odu_route_del(); + } + + /* delete full header */ + if (ipv4_header_set) + { + if (m_header.DeleteHeaderHdl(ODU_hdr_hdl_v4) + == false) + { + IPACMERR("ODU ipv4 header delete fail\n"); + res = IPACM_FAILURE; + goto fail; + } + IPACMDBG_H("ODU ipv4 header delete success\n"); + } + + if (ipv6_header_set) + { + if (m_header.DeleteHeaderHdl(ODU_hdr_hdl_v6) + == false) + { + IPACMERR("ODU ipv6 header delete fail\n"); + res = IPACM_FAILURE; + goto fail; + } + IPACMERR("ODU ipv6 header delete success\n"); + } + } + + /* no iface address up, directly close iface*/ + if (ip_type == IPACM_IP_NULL) + { + goto fail; + } + +#ifdef FEATURE_ETH_BRIDGE_LE + if(IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat == LAN_IF) + { + IPACM_Lan::usb_hdr_template_hdl = 0; + IPACM_Lan::is_usb_up = false; + if(IPACM_Lan::is_cpe_up == false) //if all LAN ifaces are down + { + IPACM_Lan::lan_hdr_type = IPA_HDR_L2_NONE; + } + } + if(IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat == ODU_IF) + { + IPACM_Lan::cpe_hdr_template_hdl = 0; + IPACM_Lan::is_cpe_up = false; + if(IPACM_Lan::is_usb_up == false) //if all LAN ifaces are down + { + IPACM_Lan::lan_hdr_type = IPA_HDR_L2_NONE; + } + } + del_hdr_proc_ctx(); +#endif + + /* delete wan filter rule */ + if (IPACM_Wan::isWanUP(ipa_if_num) && rx_prop != NULL) + { + IPACMDBG_H("LAN IF goes down, backhaul type %d\n", IPACM_Wan::backhaul_is_sta_mode); + handle_wan_down(IPACM_Wan::backhaul_is_sta_mode); + } + + if (IPACM_Wan::isWanUP_V6(ipa_if_num) && rx_prop != NULL) + { + IPACMDBG_H("LAN IF goes down, backhaul type %d\n", IPACM_Wan::backhaul_is_sta_mode); + handle_wan_down_v6(IPACM_Wan::backhaul_is_sta_mode); + } + + /* delete default filter rules */ + if (ip_type != IPA_IP_v6 && rx_prop != NULL) + { + if(m_filtering.DeleteFilteringHdls(ipv4_icmp_flt_rule_hdl, IPA_IP_v4, NUM_IPV4_ICMP_FLT_RULE) == false) + { + IPACMERR("Error Deleting ICMPv4 Filtering Rule, aborting...\n"); + res = IPACM_FAILURE; + goto fail; + } + IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, NUM_IPV4_ICMP_FLT_RULE); + + if (m_filtering.DeleteFilteringHdls(dft_v4fl_rule_hdl, IPA_IP_v4, IPV4_DEFAULT_FILTERTING_RULES) == false) + { + IPACMERR("Error Deleting Filtering Rule, aborting...\n"); + res = IPACM_FAILURE; + goto fail; + } + IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, IPV4_DEFAULT_FILTERTING_RULES); +#ifdef FEATURE_ETH_BRIDGE_LE + for(i=0; idecreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, IPA_LAN_TO_LAN_MAX_WLAN_CLIENT); + + if(IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat == LAN_IF) + { + for(i=0; idecreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, IPA_LAN_TO_LAN_MAX_CPE_CLIENT); + } + + if(IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat == ODU_IF) + { + for(i=0; idecreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, IPA_LAN_TO_LAN_MAX_USB_CLIENT); + } +#endif +#ifndef FEATURE_ETH_BRIDGE_LE +#ifdef CT_OPT + if (m_filtering.DeleteFilteringHdls(tcp_ctl_flt_rule_hdl_v4, IPA_IP_v4, NUM_TCP_CTL_FLT_RULE) == false) + { + IPACMERR("Error deleting default filtering Rule, aborting...\n"); + res = IPACM_FAILURE; + goto fail; + } + IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, NUM_TCP_CTL_FLT_RULE); +#endif + for(i=0; idecreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, 1); + } + IPACMDBG_H("Deleted lan2lan IPv4 flt rules.\n"); +#endif + + /* free private-subnet ipv4 filter rules */ + if (IPACM_Iface::ipacmcfg->ipa_num_private_subnet > IPA_PRIV_SUBNET_FILTER_RULE_HANDLES) + { + IPACMERR(" the number of rules are bigger than array, aborting...\n"); + res = IPACM_FAILURE; + goto fail; + } + +#ifdef FEATURE_IPA_ANDROID + if(m_filtering.DeleteFilteringHdls(private_fl_rule_hdl, IPA_IP_v4, IPA_MAX_PRIVATE_SUBNET_ENTRIES) == false) + { + IPACMERR("Error deleting private subnet IPv4 flt rules.\n"); + res = IPACM_FAILURE; + goto fail; + } + IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, IPA_MAX_PRIVATE_SUBNET_ENTRIES); +#else + if (m_filtering.DeleteFilteringHdls(private_fl_rule_hdl, IPA_IP_v4, IPACM_Iface::ipacmcfg->ipa_num_private_subnet) == false) + { + IPACMERR("Error Deleting RuleTable(1) to Filtering, aborting...\n"); + res = IPACM_FAILURE; + goto fail; + } + IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, IPACM_Iface::ipacmcfg->ipa_num_private_subnet); +#endif + } + IPACMDBG_H("Finished delete default iface ipv4 filtering rules \n "); + + if (ip_type != IPA_IP_v4 && rx_prop != NULL) + { + if(m_filtering.DeleteFilteringHdls(ipv6_icmp_flt_rule_hdl, IPA_IP_v6, NUM_IPV6_ICMP_FLT_RULE) == false) + { + IPACMERR("Error Deleting ICMPv6 Filtering Rule, aborting...\n"); + res = IPACM_FAILURE; + goto fail; + } + IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, NUM_IPV6_ICMP_FLT_RULE); + + if (m_filtering.DeleteFilteringHdls(dft_v6fl_rule_hdl, IPA_IP_v6, IPV6_DEFAULT_FILTERTING_RULES) == false) + { + IPACMERR("Error Adding RuleTable(1) to Filtering, aborting...\n"); + res = IPACM_FAILURE; + goto fail; + } + IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, IPV6_DEFAULT_FILTERTING_RULES); +#ifdef FEATURE_ETH_BRIDGE_LE + for(i=0; idecreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, IPA_LAN_TO_LAN_MAX_WLAN_CLIENT); + + if(IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat == LAN_IF) + { + for(i=0; idecreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, IPA_LAN_TO_LAN_MAX_CPE_CLIENT); + } + + if(IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat == ODU_IF) + { + for(i=0; idecreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, IPA_LAN_TO_LAN_MAX_USB_CLIENT); + } +#endif +#ifndef FEATURE_ETH_BRIDGE_LE +#ifdef CT_OPT + if (m_filtering.DeleteFilteringHdls(tcp_ctl_flt_rule_hdl_v6, IPA_IP_v6, NUM_TCP_CTL_FLT_RULE) == false) + { + IPACMERR("Error deleting default filtering Rule, aborting...\n"); + res = IPACM_FAILURE; + goto fail; + } + IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, NUM_TCP_CTL_FLT_RULE); +#endif + for(i=0; idecreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1); + } + IPACMDBG_H("Deleted lan2lan IPv6 flt rules.\n"); +#endif + } + IPACMDBG_H("Finished delete default iface ipv6 filtering rules \n "); + + if (ip_type != IPA_IP_v6) + { + if (m_routing.DeleteRoutingHdl(dft_rt_rule_hdl[0], IPA_IP_v4) + == false) + { + IPACMERR("Routing rule deletion failed!\n"); + res = IPACM_FAILURE; + goto fail; + } + } + IPACMDBG_H("Finished delete default iface ipv4 rules \n "); + + /* delete default v6 routing rule */ + if (ip_type != IPA_IP_v4) + { + /* may have multiple ipv6 iface-RT rules*/ + for (i = 0; i < 2*num_dft_rt_v6; i++) + { + if (m_routing.DeleteRoutingHdl(dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES + i], IPA_IP_v6) + == false) + { + IPACMERR("Routing rule deletion failed!\n"); + res = IPACM_FAILURE; + goto fail; + } + } + } + + IPACMDBG_H("Finished delete default iface ipv6 rules \n "); + /* clean eth-client header, routing rules */ + IPACMDBG_H("left %d eth clients need to be deleted \n ", num_eth_client); + for (i = 0; i < num_eth_client; i++) + { +#ifdef FEATURE_ETH_BRIDGE_LE + eth_bridge_del_lan_client_rt_rule(get_client_memptr(eth_client, i)->mac, SRC_LAN); + eth_bridge_del_lan_client_rt_rule(get_client_memptr(eth_client, i)->mac, SRC_WLAN); + eth_bridge_post_lan_client_event(get_client_memptr(eth_client, i)->mac, IPA_ETH_BRIDGE_LAN_CLIENT_DEL_EVENT); + eth_bridge_del_lan_client(get_client_memptr(eth_client, i)->mac); +#endif + + /* First reset nat rules and then route rules */ + if(get_client_memptr(eth_client, i)->ipv4_set == true) + { + IPACMDBG_H("Clean Nat Rules for ipv4:0x%x\n", get_client_memptr(eth_client, i)->v4_addr); + CtList->HandleNeighIpAddrDelEvt(get_client_memptr(eth_client, i)->v4_addr); + } + + if (delete_eth_rtrules(i, IPA_IP_v4)) + { + IPACMERR("unbale to delete ecm-client v4 route rules for index %d\n", i); + res = IPACM_FAILURE; + goto fail; + } + + if (delete_eth_rtrules(i, IPA_IP_v6)) + { + IPACMERR("unbale to delete ecm-client v6 route rules for index %d\n", i); + res = IPACM_FAILURE; + goto fail; + } + + IPACMDBG_H("Delete %d client header\n", num_eth_client); + + + if(get_client_memptr(eth_client, i)->ipv4_header_set == true) + { + if (m_header.DeleteHeaderHdl(get_client_memptr(eth_client, i)->hdr_hdl_v4) + == false) + { + res = IPACM_FAILURE; + goto fail; + } + } + + if(get_client_memptr(eth_client, i)->ipv6_header_set == true) + { + if (m_header.DeleteHeaderHdl(get_client_memptr(eth_client, i)->hdr_hdl_v6) + == false) + { + res = IPACM_FAILURE; + goto fail; + } + } + } /* end of for loop */ + + /* free the edm clients cache */ + IPACMDBG_H("Free ecm clients cache\n"); + + /* Delete corresponding ipa_rm_resource_name of TX-endpoint after delete all IPV4V6 RT-rule */ + IPACMDBG_H("dev %s delete producer dependency\n", dev_name); + if (tx_prop != NULL) + { + IPACMDBG_H("depend Got pipe %d rm index : %d \n", tx_prop->tx[0].dst_pipe, IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe]); + IPACM_Iface::ipacmcfg->DelRmDepend(IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe]); + } + /* check software routing fl rule hdl */ + if (softwarerouting_act == true && rx_prop != NULL) + { + handle_software_routing_disable(); + } + + /* posting ip to lan2lan module to delete RT/FILTER rules*/ + post_lan2lan_client_disconnect_msg(IPA_IP_v4); + post_lan2lan_client_disconnect_msg(IPA_IP_v6); + +/* Delete private subnet*/ +#ifdef FEATURE_IPA_ANDROID + if (ip_type != IPA_IP_v6) + { + IPACMDBG_H("current IPACM private subnet_addr number(%d)\n", IPACM_Iface::ipacmcfg->ipa_num_private_subnet); + IPACMDBG_H(" Delete IPACM private subnet_addr as: 0x%x \n", if_ipv4_subnet); + if(IPACM_Iface::ipacmcfg->DelPrivateSubnet(if_ipv4_subnet, ipa_if_num) == false) + { + IPACMERR(" can't Delete IPACM private subnet_addr as: 0x%x \n", if_ipv4_subnet); + } + } + + /* reset the IPA-client pipe enum */ + if(IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat != WAN_IF) + { + handle_tethering_client(true, IPACM_CLIENT_USB); + } +#endif /* defined(FEATURE_IPA_ANDROID)*/ +fail: + if (odu_route_rule_v4_hdl != NULL) + { + free(odu_route_rule_v4_hdl); + } + if (odu_route_rule_v6_hdl != NULL) + { + free(odu_route_rule_v6_hdl); + } + /* Delete corresponding ipa_rm_resource_name of RX-endpoint after delete all IPV4V6 FT-rule */ + if (rx_prop != NULL) + { + IPACMDBG_H("dev %s add producer dependency\n", dev_name); + IPACMDBG_H("depend Got pipe %d rm index : %d \n", rx_prop->rx[0].src_pipe, IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[rx_prop->rx[0].src_pipe]); + IPACM_Iface::ipacmcfg->DelRmDepend(IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[rx_prop->rx[0].src_pipe]); + IPACMDBG_H("Finished delete dependency \n "); + free(rx_prop); + } + + if (eth_client != NULL) + { + free(eth_client); + } + + if (tx_prop != NULL) + { + free(tx_prop); + } + if (iface_query != NULL) + { + free(iface_query); + } +#ifdef FEATURE_ETH_BRIDGE_LE + if(eth_bridge_lan_client_rt_from_lan_info_v4 != NULL) + { + free(eth_bridge_lan_client_rt_from_lan_info_v4); + } + if(eth_bridge_lan_client_rt_from_lan_info_v6 != NULL) + { + free(eth_bridge_lan_client_rt_from_lan_info_v6); + } + if(eth_bridge_lan_client_rt_from_wlan_info_v4 != NULL) + { + free(eth_bridge_lan_client_rt_from_wlan_info_v4); + } + if(eth_bridge_lan_client_rt_from_wlan_info_v6 != NULL) + { + free(eth_bridge_lan_client_rt_from_wlan_info_v6); + } +#endif + is_active = false; + post_del_self_evt(); + + return res; +} + +/* install UL filter rule from Q6 */ +int IPACM_Lan::handle_uplink_filter_rule(ipacm_ext_prop *prop, ipa_ip_type iptype, uint8_t xlat_mux_id) +{ + ipa_flt_rule_add flt_rule_entry; + int len = 0, cnt, ret = IPACM_SUCCESS; + ipa_ioc_add_flt_rule *pFilteringTable; + ipa_fltr_installed_notif_req_msg_v01 flt_index; + int fd; + int i, index; + uint32_t value = 0; + + IPACMDBG_H("Set extended property rules in LAN\n"); + + if (rx_prop == NULL) + { + IPACMDBG_H("No rx properties registered for iface %s\n", dev_name); + return IPACM_SUCCESS; + } + + if(prop == NULL || prop->num_ext_props <= 0) + { + IPACMDBG_H("No extended property.\n"); + return IPACM_SUCCESS; + } + + fd = open(IPA_DEVICE_NAME, O_RDWR); + if (0 == fd) + { + IPACMERR("Failed opening %s.\n", IPA_DEVICE_NAME); + return IPACM_FAILURE; + } + if (prop->num_ext_props > MAX_WAN_UL_FILTER_RULES) + { + IPACMERR("number of modem UL rules > MAX_WAN_UL_FILTER_RULES, aborting...\n"); + close(fd); + return IPACM_FAILURE; + } + + memset(&flt_index, 0, sizeof(flt_index)); + flt_index.source_pipe_index = ioctl(fd, IPA_IOC_QUERY_EP_MAPPING, rx_prop->rx[0].src_pipe); + flt_index.install_status = IPA_QMI_RESULT_SUCCESS_V01; +#ifndef FEATURE_IPA_V3 + flt_index.filter_index_list_len = prop->num_ext_props; +#else /* defined (FEATURE_IPA_V3) */ + flt_index.rule_id_valid = 1; + flt_index.rule_id_len = prop->num_ext_props; +#endif + flt_index.embedded_pipe_index_valid = 1; + flt_index.embedded_pipe_index = ioctl(fd, IPA_IOC_QUERY_EP_MAPPING, IPA_CLIENT_APPS_LAN_WAN_PROD); + flt_index.retain_header_valid = 1; + flt_index.retain_header = 0; + flt_index.embedded_call_mux_id_valid = 1; + flt_index.embedded_call_mux_id = IPACM_Iface::ipacmcfg->GetQmapId(); +#ifndef FEATURE_IPA_V3 + IPACMDBG_H("flt_index: src pipe: %d, num of rules: %d, ebd pipe: %d, mux id: %d\n", + flt_index.source_pipe_index, flt_index.filter_index_list_len, flt_index.embedded_pipe_index, flt_index.embedded_call_mux_id); +#else /* defined (FEATURE_IPA_V3) */ + IPACMDBG_H("flt_index: src pipe: %d, num of rules: %d, ebd pipe: %d, mux id: %d\n", + flt_index.source_pipe_index, flt_index.rule_id_len, flt_index.embedded_pipe_index, flt_index.embedded_call_mux_id); +#endif + len = sizeof(struct ipa_ioc_add_flt_rule) + prop->num_ext_props * sizeof(struct ipa_flt_rule_add); + pFilteringTable = (struct ipa_ioc_add_flt_rule*)malloc(len); + if (pFilteringTable == NULL) + { + IPACMERR("Error Locate ipa_flt_rule_add memory...\n"); + close(fd); + return IPACM_FAILURE; + } + memset(pFilteringTable, 0, len); + + pFilteringTable->commit = 1; + pFilteringTable->ep = rx_prop->rx[0].src_pipe; + pFilteringTable->global = false; + pFilteringTable->ip = iptype; + pFilteringTable->num_rules = prop->num_ext_props; + + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); // Zero All Fields + flt_rule_entry.at_rear = 1; +#ifdef FEATURE_IPA_V3 + if (flt_rule_entry.rule.eq_attrib.ipv4_frag_eq_present) + flt_rule_entry.at_rear = 0; +#endif + flt_rule_entry.flt_rule_hdl = -1; + flt_rule_entry.status = -1; + + flt_rule_entry.rule.retain_hdr = 0; + flt_rule_entry.rule.to_uc = 0; + flt_rule_entry.rule.eq_attrib_type = 1; + if(iptype == IPA_IP_v4) + { + if (IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat == ODU_IF && + IPACM_Wan::isWan_Bridge_Mode()) + { + IPACMDBG_H("WAN, ODU are in bridge mode \n"); + flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING; + } + else + { + flt_rule_entry.rule.action = IPA_PASS_TO_SRC_NAT; + } + } + else if(iptype == IPA_IP_v6) + flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING; + else + { + IPACMERR("IP type is not expected.\n"); + ret = IPACM_FAILURE; + goto fail; + } + + index = IPACM_Iface::ipacmcfg->getFltRuleCount(rx_prop->rx[0].src_pipe, iptype); + +#ifndef FEATURE_IPA_ANDROID + if(iptype == IPA_IP_v4 && index != exp_index_v4) + { + IPACMDBG_DMESG("### WARNING ### num flt rules for IPv4 on client %d is not expected: %d expected value: %d", + rx_prop->rx[0].src_pipe, index, exp_index_v4); + } + if(iptype == IPA_IP_v6 && index != exp_index_v6) + { + IPACMDBG_DMESG("### WARNING ### num flt rules for IPv6 on client %d is not expected: %d expected value: %d", + rx_prop->rx[0].src_pipe, index, exp_index_v6); + } +#endif + + for(cnt=0; cntnum_ext_props; cnt++) + { + memcpy(&flt_rule_entry.rule.eq_attrib, + &prop->prop[cnt].eq_attrib, + sizeof(prop->prop[cnt].eq_attrib)); + flt_rule_entry.rule.rt_tbl_idx = prop->prop[cnt].rt_tbl_idx; + + /* Handle XLAT configuration */ + if ((iptype == IPA_IP_v4) && prop->prop[cnt].is_xlat_rule && (xlat_mux_id != 0)) + { + /* fill the value of meta-data */ + value = xlat_mux_id; + flt_rule_entry.rule.eq_attrib.metadata_meq32_present = 1; + flt_rule_entry.rule.eq_attrib.metadata_meq32.offset = 0; + flt_rule_entry.rule.eq_attrib.metadata_meq32.value = (value & 0xFF) << 16; + flt_rule_entry.rule.eq_attrib.metadata_meq32.mask = 0x00FF0000; + IPACMDBG_H("xlat meta-data is modified for rule: %d has index %d with xlat_mux_id: %d\n", + cnt, index, xlat_mux_id); + } +#ifdef FEATURE_IPA_V3 + flt_rule_entry.rule.hashable = prop->prop[cnt].is_rule_hashable; + flt_rule_entry.rule.rule_id = prop->prop[cnt].rule_id; +#endif + memcpy(&pFilteringTable->rules[cnt], &flt_rule_entry, sizeof(flt_rule_entry)); + + IPACMDBG_H("Modem UL filtering rule %d has index %d\n", cnt, index); +#ifndef FEATURE_IPA_V3 + flt_index.filter_index_list[cnt].filter_index = index; + flt_index.filter_index_list[cnt].filter_handle = prop->prop[cnt].filter_hdl; +#else /* defined (FEATURE_IPA_V3) */ + flt_index.rule_id[cnt] = prop->prop[cnt].rule_id; +#endif + index++; + } + + if(false == m_filtering.SendFilteringRuleIndex(&flt_index)) + { + IPACMERR("Error sending filtering rule index, aborting...\n"); + ret = IPACM_FAILURE; + goto fail; + } + + if(false == m_filtering.AddFilteringRule(pFilteringTable)) + { + IPACMERR("Error Adding RuleTable to Filtering, aborting...\n"); + ret = IPACM_FAILURE; + goto fail; + } + else + { + if(iptype == IPA_IP_v4) + { + for(i=0; inum_rules; i++) + { + wan_ul_fl_rule_hdl_v4[num_wan_ul_fl_rule_v4] = pFilteringTable->rules[i].flt_rule_hdl; + num_wan_ul_fl_rule_v4++; + } + IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, iptype, pFilteringTable->num_rules); + } + else if(iptype == IPA_IP_v6) + { + for(i=0; inum_rules; i++) + { + wan_ul_fl_rule_hdl_v6[num_wan_ul_fl_rule_v6] = pFilteringTable->rules[i].flt_rule_hdl; + num_wan_ul_fl_rule_v6++; + } + IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, iptype, pFilteringTable->num_rules); + } + else + { + IPACMERR("IP type is not expected.\n"); + goto fail; + } + } + +fail: + free(pFilteringTable); + close(fd); + return ret; +} + +int IPACM_Lan::handle_wan_down_v6(bool is_sta_mode) +{ + ipa_fltr_installed_notif_req_msg_v01 flt_index; + int fd; + + fd = open(IPA_DEVICE_NAME, O_RDWR); + if (0 == fd) + { + IPACMERR("Failed opening %s.\n", IPA_DEVICE_NAME); + return IPACM_FAILURE; + } + + delete_ipv6_prefix_flt_rule(); + + if(is_sta_mode == false) + { + if (num_wan_ul_fl_rule_v6 > MAX_WAN_UL_FILTER_RULES) + { + IPACMERR(" the number of rules (%d) are bigger than array (%d), aborting...\n", num_wan_ul_fl_rule_v6, MAX_WAN_UL_FILTER_RULES); + close(fd); + return IPACM_FAILURE; + } + if (num_wan_ul_fl_rule_v6 == 0) + { + IPACMERR("No modem UL rules were installed, return...\n"); + close(fd); + return IPACM_FAILURE; + } + + if (m_filtering.DeleteFilteringHdls(wan_ul_fl_rule_hdl_v6, + IPA_IP_v6, num_wan_ul_fl_rule_v6) == false) + { + IPACMERR("Error Deleting RuleTable(1) to Filtering, aborting...\n"); + close(fd); + return IPACM_FAILURE; + } + IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, num_wan_ul_fl_rule_v6); + memset(wan_ul_fl_rule_hdl_v6, 0, MAX_WAN_UL_FILTER_RULES * sizeof(uint32_t)); + num_wan_ul_fl_rule_v6 = 0; + modem_ul_v6_set = false; + + memset(&flt_index, 0, sizeof(flt_index)); + flt_index.source_pipe_index = ioctl(fd, IPA_IOC_QUERY_EP_MAPPING, rx_prop->rx[0].src_pipe); + flt_index.install_status = IPA_QMI_RESULT_SUCCESS_V01; +#ifndef FEATURE_IPA_V3 + flt_index.filter_index_list_len = 0; +#else /* defined (FEATURE_IPA_V3) */ + flt_index.rule_id_valid = 1; + flt_index.rule_id_len = 0; +#endif + flt_index.embedded_pipe_index_valid = 1; + flt_index.embedded_pipe_index = ioctl(fd, IPA_IOC_QUERY_EP_MAPPING, IPA_CLIENT_APPS_LAN_WAN_PROD); + flt_index.retain_header_valid = 1; + flt_index.retain_header = 0; + flt_index.embedded_call_mux_id_valid = 1; + flt_index.embedded_call_mux_id = IPACM_Iface::ipacmcfg->GetQmapId(); + if(false == m_filtering.SendFilteringRuleIndex(&flt_index)) + { + IPACMERR("Error sending filtering rule index, aborting...\n"); + close(fd); + return IPACM_FAILURE; + } + } + else + { + if (m_filtering.DeleteFilteringHdls(&dft_v6fl_rule_hdl[IPV6_DEFAULT_FILTERTING_RULES], + IPA_IP_v6, 1) == false) + { + IPACMERR("Error Adding RuleTable(1) to Filtering, aborting...\n"); + close(fd); + return IPACM_FAILURE; + } + IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1); + } + close(fd); + return IPACM_SUCCESS; +} + + +/*handle lan2lan client active*/ +int IPACM_Lan::handle_lan2lan_client_active(ipacm_event_data_all *data, ipa_cm_event_id event) +{ + if((tx_prop == NULL) || (rx_prop == NULL)) + { + IPACMDBG_H("No tx/rx properties registered for iface %s, not posting lan2lan event(%d)\n", dev_name, event); + return IPACM_SUCCESS; + } + + if(data == NULL) + { + IPACMERR("Event data is empty.\n"); + return IPACM_FAILURE; + } + + if(data->iptype == IPA_IP_v4 && ip_type != IPA_IP_v4 && ip_type != IPA_IP_MAX) + { + IPACMERR("Client has IPv4 addr but iface does not have IPv4 up.\n"); + return IPACM_FAILURE; + } + if(data->iptype == IPA_IP_v6 && ip_type != IPA_IP_v6 && ip_type != IPA_IP_MAX) + { + IPACMERR("Client has IPv6 addr but iface does not have IPv6 up.\n"); + return IPACM_FAILURE; + } + + ipacm_cmd_q_data evt_data; + memset(&evt_data, 0, sizeof(evt_data)); + + ipacm_event_lan_client* lan_client; + lan_client = (ipacm_event_lan_client*)malloc(sizeof(ipacm_event_lan_client)); + if(lan_client == NULL) + { + IPACMERR("Unable to allocate memory.\n"); + return IPACM_FAILURE; + } + memset(lan_client, 0, sizeof(ipacm_event_lan_client)); + lan_client->iptype = data->iptype; + lan_client->ipv4_addr = data->ipv4_addr; + memcpy(lan_client->ipv6_addr, data->ipv6_addr, 4 * sizeof(uint32_t)); + memcpy(lan_client->mac_addr, data->mac_addr, 6 * sizeof(uint8_t)); + lan_client->p_iface = this; + + evt_data.event = event; + evt_data.evt_data = (void*)lan_client; + + IPACMDBG_H("Posting event: %d\n", event); + IPACM_EvtDispatcher::PostEvt(&evt_data); + return IPACM_SUCCESS; +} + +int IPACM_Lan::add_lan2lan_flt_rule(ipa_ip_type iptype, uint32_t src_v4_addr, uint32_t dst_v4_addr, uint32_t* src_v6_addr, uint32_t* dst_v6_addr, uint32_t* rule_hdl) +{ + if(rx_prop == NULL) + { + IPACMERR("There is no rx_prop for iface %s, not able to add lan2lan filtering rule.\n", dev_name); + return IPACM_FAILURE; + } + if(rule_hdl == NULL) + { + IPACMERR("Filteing rule handle is empty.\n"); + return IPACM_FAILURE; + } + + IPACMDBG_H("Got a new lan2lan flt rule with IP type: %d\n", iptype); + + int i, len, res = IPACM_SUCCESS; + struct ipa_flt_rule_mdfy flt_rule; + struct ipa_ioc_mdfy_flt_rule* pFilteringTable; + + len = sizeof(struct ipa_ioc_mdfy_flt_rule) + sizeof(struct ipa_flt_rule_mdfy); + + pFilteringTable = (struct ipa_ioc_mdfy_flt_rule*)malloc(len); + + if (pFilteringTable == NULL) + { + IPACMERR("Error allocate lan2lan flt rule memory...\n"); + return IPACM_FAILURE; + } + memset(pFilteringTable, 0, len); + + pFilteringTable->commit = 1; + pFilteringTable->ip = iptype; + pFilteringTable->num_rules = 1; + + memset(&flt_rule, 0, sizeof(struct ipa_flt_rule_mdfy)); + + if(iptype == IPA_IP_v4) + { + IPACMDBG_H("src_v4_addr: %d dst_v4_addr: %d\n", src_v4_addr, dst_v4_addr); + + if(num_lan2lan_flt_rule_v4 >= MAX_OFFLOAD_PAIR) + { + IPACMERR("Lan2lan flt rule table is full, not able to add.\n"); + res = IPACM_FAILURE; + goto fail; + } + + if(false == m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_lan2lan_v4)) + { + IPACMERR("Failed to get routing table %s handle.\n", IPACM_Iface::ipacmcfg->rt_tbl_lan2lan_v4.name); + res = IPACM_FAILURE; + goto fail; + } + IPACMDBG_H("Routing handle for table %s: %d\n", IPACM_Iface::ipacmcfg->rt_tbl_lan2lan_v4.name, + IPACM_Iface::ipacmcfg->rt_tbl_lan2lan_v4.hdl); + + flt_rule.status = -1; + for(i=0; irt_tbl_lan2lan_v4.hdl; + + memcpy(&flt_rule.rule.attrib, &rx_prop->rx[0].attrib, + sizeof(flt_rule.rule.attrib)); + IPACMDBG_H("Rx property attrib mask:0x%x\n", rx_prop->rx[0].attrib.attrib_mask); + + flt_rule.rule.attrib.attrib_mask |= IPA_FLT_SRC_ADDR; + flt_rule.rule.attrib.u.v4.src_addr = src_v4_addr; + flt_rule.rule.attrib.u.v4.src_addr_mask = 0xFFFFFFFF; + + flt_rule.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; + flt_rule.rule.attrib.u.v4.dst_addr = dst_v4_addr; + flt_rule.rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF; + + memcpy(&(pFilteringTable->rules[0]), &flt_rule, sizeof(struct ipa_flt_rule_mdfy)); + if (false == m_filtering.ModifyFilteringRule(pFilteringTable)) + { + IPACMERR("Error modifying filtering rule.\n"); + res = IPACM_FAILURE; + goto fail; + } + else + { + lan2lan_flt_rule_hdl_v4[i].valid = true; + *rule_hdl = lan2lan_flt_rule_hdl_v4[i].rule_hdl; + num_lan2lan_flt_rule_v4++; + IPACMDBG_H("Flt rule modified, hdl: 0x%x, status: %d\n", pFilteringTable->rules[0].rule_hdl, + pFilteringTable->rules[0].status); + } + } + else if(iptype == IPA_IP_v6) + { + if(num_lan2lan_flt_rule_v6 >= MAX_OFFLOAD_PAIR) + { + IPACMERR("Lan2lan flt rule table is full, not able to add.\n"); + res = IPACM_FAILURE; + goto fail; + } + if(src_v6_addr == NULL || dst_v6_addr == NULL) + { + IPACMERR("Got IPv6 flt rule but without IPv6 src/dst addr.\n"); + res = IPACM_FAILURE; + goto fail; + } + IPACMDBG_H("src_v6_addr: 0x%08x%08x%08x%08x, dst_v6_addr: 0x%08x%08x%08x%08x\n", src_v6_addr[0], src_v6_addr[1], + src_v6_addr[2], src_v6_addr[3], dst_v6_addr[0], dst_v6_addr[1], dst_v6_addr[2], dst_v6_addr[3]); + + if(false == m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_lan2lan_v6)) + { + IPACMERR("Failed to get routing table %s handle.\n", IPACM_Iface::ipacmcfg->rt_tbl_lan2lan_v6.name); + res = IPACM_FAILURE; + goto fail; + } + IPACMDBG_H("Routing handle for table %s: %d\n", IPACM_Iface::ipacmcfg->rt_tbl_lan2lan_v6.name, + IPACM_Iface::ipacmcfg->rt_tbl_lan2lan_v6.hdl); + + flt_rule.status = -1; + for(i=0; irt_tbl_lan2lan_v6.hdl; + + memcpy(&flt_rule.rule.attrib, &rx_prop->rx[0].attrib, + sizeof(flt_rule.rule.attrib)); + IPACMDBG_H("Rx property attrib mask:0x%x\n", rx_prop->rx[0].attrib.attrib_mask); + + flt_rule.rule.attrib.attrib_mask |= IPA_FLT_SRC_ADDR; + flt_rule.rule.attrib.u.v6.src_addr[0] = src_v6_addr[0]; + flt_rule.rule.attrib.u.v6.src_addr[1] = src_v6_addr[1]; + flt_rule.rule.attrib.u.v6.src_addr[2] = src_v6_addr[2]; + flt_rule.rule.attrib.u.v6.src_addr[3] = src_v6_addr[3]; + flt_rule.rule.attrib.u.v6.src_addr_mask[0] = 0xFFFFFFFF; + flt_rule.rule.attrib.u.v6.src_addr_mask[1] = 0xFFFFFFFF; + flt_rule.rule.attrib.u.v6.src_addr_mask[2] = 0xFFFFFFFF; + flt_rule.rule.attrib.u.v6.src_addr_mask[3] = 0xFFFFFFFF; + + + flt_rule.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; + flt_rule.rule.attrib.u.v6.dst_addr[0] = dst_v6_addr[0]; + flt_rule.rule.attrib.u.v6.dst_addr[1] = dst_v6_addr[1]; + flt_rule.rule.attrib.u.v6.dst_addr[2] = dst_v6_addr[2]; + flt_rule.rule.attrib.u.v6.dst_addr[3] = dst_v6_addr[3]; + flt_rule.rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF; + flt_rule.rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF; + flt_rule.rule.attrib.u.v6.dst_addr_mask[2] = 0xFFFFFFFF; + flt_rule.rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF; + + memcpy(&(pFilteringTable->rules[0]), &flt_rule, sizeof(struct ipa_flt_rule_mdfy)); + if (false == m_filtering.ModifyFilteringRule(pFilteringTable)) + { + IPACMERR("Error modifying filtering rule.\n"); + res = IPACM_FAILURE; + goto fail; + } + else + { + lan2lan_flt_rule_hdl_v6[i].valid = true; + *rule_hdl = lan2lan_flt_rule_hdl_v6[i].rule_hdl; + num_lan2lan_flt_rule_v6++; + IPACMDBG_H("Flt rule modified, hdl: 0x%x, status: %d\n", pFilteringTable->rules[0].rule_hdl, + pFilteringTable->rules[0].status); + } + } + else + { + IPACMERR("IP type is not expected.\n"); + res = IPACM_FAILURE; + goto fail; + } + +fail: + free(pFilteringTable); + return res; +} + +int IPACM_Lan::add_dummy_lan2lan_flt_rule(ipa_ip_type iptype) +{ + if(rx_prop == NULL) + { + IPACMDBG_H("There is no rx_prop for iface %s, not able to add dummy lan2lan filtering rule.\n", dev_name); + return 0; + } + + int i, len, res = IPACM_SUCCESS; + struct ipa_flt_rule_add flt_rule; + ipa_ioc_add_flt_rule* pFilteringTable; + + len = sizeof(struct ipa_ioc_add_flt_rule) + MAX_OFFLOAD_PAIR * sizeof(struct ipa_flt_rule_add); + + pFilteringTable = (struct ipa_ioc_add_flt_rule *)malloc(len); + if (pFilteringTable == NULL) + { + IPACMERR("Error allocate flt table memory...\n"); + return IPACM_FAILURE; + } + memset(pFilteringTable, 0, len); + + pFilteringTable->commit = 1; + pFilteringTable->ep = rx_prop->rx[0].src_pipe; + pFilteringTable->global = false; + pFilteringTable->ip = iptype; + pFilteringTable->num_rules = MAX_OFFLOAD_PAIR; + + memset(&flt_rule, 0, sizeof(struct ipa_flt_rule_add)); + + flt_rule.rule.retain_hdr = 0; + flt_rule.at_rear = true; + flt_rule.flt_rule_hdl = -1; + flt_rule.status = -1; + flt_rule.rule.action = IPA_PASS_TO_EXCEPTION; + memcpy(&flt_rule.rule.attrib, &rx_prop->rx[0].attrib, + sizeof(flt_rule.rule.attrib)); + + if(iptype == IPA_IP_v4) + { + flt_rule.rule.attrib.attrib_mask = IPA_FLT_SRC_ADDR | IPA_FLT_DST_ADDR; + flt_rule.rule.attrib.u.v4.src_addr_mask = ~0; + flt_rule.rule.attrib.u.v4.src_addr = ~0; + flt_rule.rule.attrib.u.v4.dst_addr_mask = ~0; + flt_rule.rule.attrib.u.v4.dst_addr = ~0; + + for(i=0; irules[i]), &flt_rule, sizeof(struct ipa_flt_rule_add)); + } + + if (false == m_filtering.AddFilteringRule(pFilteringTable)) + { + IPACMERR("Error adding dummy lan2lan v4 flt rule\n"); + res = IPACM_FAILURE; + goto fail; + } + else + { + IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, MAX_OFFLOAD_PAIR); + /* copy filter rule hdls */ + for (int i = 0; i < MAX_OFFLOAD_PAIR; i++) + { + if (pFilteringTable->rules[i].status == 0) + { + lan2lan_flt_rule_hdl_v4[i].rule_hdl = pFilteringTable->rules[i].flt_rule_hdl; + IPACMDBG_H("Lan2lan v4 flt rule %d hdl:0x%x\n", i, lan2lan_flt_rule_hdl_v4[i].rule_hdl); + } + else + { + IPACMERR("Failed adding lan2lan v4 flt rule %d\n", i); + res = IPACM_FAILURE; + goto fail; + } + } + } + } + else if(iptype == IPA_IP_v6) + { + flt_rule.rule.attrib.attrib_mask = IPA_FLT_SRC_ADDR | IPA_FLT_DST_ADDR; + flt_rule.rule.attrib.u.v6.src_addr_mask[0] = ~0; + flt_rule.rule.attrib.u.v6.src_addr_mask[1] = ~0; + flt_rule.rule.attrib.u.v6.src_addr_mask[2] = ~0; + flt_rule.rule.attrib.u.v6.src_addr_mask[3] = ~0; + flt_rule.rule.attrib.u.v6.src_addr[0] = ~0; + flt_rule.rule.attrib.u.v6.src_addr[1] = ~0; + flt_rule.rule.attrib.u.v6.src_addr[2] = ~0; + flt_rule.rule.attrib.u.v6.src_addr[3] = ~0; + flt_rule.rule.attrib.u.v6.dst_addr_mask[0] = ~0; + flt_rule.rule.attrib.u.v6.dst_addr_mask[1] = ~0; + flt_rule.rule.attrib.u.v6.dst_addr_mask[2] = ~0; + flt_rule.rule.attrib.u.v6.dst_addr_mask[3] = ~0; + flt_rule.rule.attrib.u.v6.dst_addr[0] = ~0; + flt_rule.rule.attrib.u.v6.dst_addr[1] = ~0; + flt_rule.rule.attrib.u.v6.dst_addr[2] = ~0; + flt_rule.rule.attrib.u.v6.dst_addr[3] = ~0; + + for(i=0; irules[i]), &flt_rule, sizeof(struct ipa_flt_rule_add)); + } + + if (false == m_filtering.AddFilteringRule(pFilteringTable)) + { + IPACMERR("Error adding dummy lan2lan v6 flt rule\n"); + res = IPACM_FAILURE; + goto fail; + } + else + { + IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, MAX_OFFLOAD_PAIR); + /* copy filter rule hdls */ + for (int i = 0; i < MAX_OFFLOAD_PAIR; i++) + { + if (pFilteringTable->rules[i].status == 0) + { + lan2lan_flt_rule_hdl_v6[i].rule_hdl = pFilteringTable->rules[i].flt_rule_hdl; + IPACMDBG_H("Lan2lan v6 flt rule %d hdl:0x%x\n", i, lan2lan_flt_rule_hdl_v6[i].rule_hdl); + } + else + { + IPACMERR("Failed adding lan2lan v6 flt rule %d\n", i); + res = IPACM_FAILURE; + goto fail; + } + } + } + } + else + { + IPACMERR("IP type is not expected.\n"); + goto fail; + } + +fail: + free(pFilteringTable); + return res; +} + +int IPACM_Lan::del_lan2lan_flt_rule(ipa_ip_type iptype, uint32_t rule_hdl) +{ + int i; + + IPACMDBG_H("Del lan2lan flt rule with IP type: %d hdl: %d\n", iptype, rule_hdl); + if(iptype == IPA_IP_v4) + { + for(i=0; icommit = 1; + pFilteringTable->ip = iptype; + pFilteringTable->num_rules = 1; + + memset(&flt_rule, 0, sizeof(struct ipa_flt_rule_mdfy)); + flt_rule.status = -1; + flt_rule.rule_hdl = rule_hdl; + + flt_rule.rule.retain_hdr = 0; + flt_rule.rule.action = IPA_PASS_TO_EXCEPTION; + + if(iptype == IPA_IP_v4) + { + IPACMDBG_H("Reset IPv4 flt rule to dummy\n"); + + flt_rule.rule.attrib.attrib_mask = IPA_FLT_SRC_ADDR | IPA_FLT_DST_ADDR; + flt_rule.rule.attrib.u.v4.dst_addr = ~0; + flt_rule.rule.attrib.u.v4.dst_addr_mask = ~0; + flt_rule.rule.attrib.u.v4.src_addr = ~0; + flt_rule.rule.attrib.u.v4.src_addr_mask = ~0; + + memcpy(&(pFilteringTable->rules[0]), &flt_rule, sizeof(struct ipa_flt_rule_mdfy)); + if (false == m_filtering.ModifyFilteringRule(pFilteringTable)) + { + IPACMERR("Error modifying filtering rule.\n"); + res = IPACM_FAILURE; + goto fail; + } + else + { + IPACMDBG_H("Flt rule reset to dummy, hdl: 0x%x, status: %d\n", pFilteringTable->rules[0].rule_hdl, + pFilteringTable->rules[0].status); + } + } + else if(iptype == IPA_IP_v6) + { + IPACMDBG_H("Reset IPv6 flt rule to dummy\n"); + + flt_rule.rule.attrib.attrib_mask = IPA_FLT_SRC_ADDR | IPA_FLT_DST_ADDR; + flt_rule.rule.attrib.u.v6.src_addr[0] = ~0; + flt_rule.rule.attrib.u.v6.src_addr[1] = ~0; + flt_rule.rule.attrib.u.v6.src_addr[2] = ~0; + flt_rule.rule.attrib.u.v6.src_addr[3] = ~0; + flt_rule.rule.attrib.u.v6.src_addr_mask[0] = ~0; + flt_rule.rule.attrib.u.v6.src_addr_mask[1] = ~0; + flt_rule.rule.attrib.u.v6.src_addr_mask[2] = ~0; + flt_rule.rule.attrib.u.v6.src_addr_mask[3] = ~0; + flt_rule.rule.attrib.u.v6.dst_addr[0] = ~0; + flt_rule.rule.attrib.u.v6.dst_addr[1] = ~0; + flt_rule.rule.attrib.u.v6.dst_addr[2] = ~0; + flt_rule.rule.attrib.u.v6.dst_addr[3] = ~0; + flt_rule.rule.attrib.u.v6.dst_addr_mask[0] = ~0; + flt_rule.rule.attrib.u.v6.dst_addr_mask[1] = ~0; + flt_rule.rule.attrib.u.v6.dst_addr_mask[2] = ~0; + flt_rule.rule.attrib.u.v6.dst_addr_mask[3] = ~0; + + + memcpy(&(pFilteringTable->rules[0]), &flt_rule, sizeof(struct ipa_flt_rule_mdfy)); + if (false == m_filtering.ModifyFilteringRule(pFilteringTable)) + { + IPACMERR("Error modifying filtering rule.\n"); + res = IPACM_FAILURE; + goto fail; + } + else + { + IPACMDBG_H("Flt rule reset to dummy, hdl: 0x%x, status: %d\n", pFilteringTable->rules[0].rule_hdl, + pFilteringTable->rules[0].status); + } + } + else + { + IPACMERR("IP type is not expected.\n"); + res = IPACM_FAILURE; + goto fail; + } + +fail: + free(pFilteringTable); + return res; +} + +int IPACM_Lan::add_lan2lan_hdr(ipa_ip_type iptype, uint8_t* src_mac, uint8_t* dst_mac, uint32_t* hdr_hdl) +{ + if(tx_prop == NULL) + { + IPACMERR("There is no tx_prop, cannot add header.\n"); + return IPACM_FAILURE; + } + if(src_mac == NULL || dst_mac == NULL) + { + IPACMERR("Either src_mac or dst_mac is null, cannot add header.\n"); + return IPACM_FAILURE; + } + if(hdr_hdl == NULL) + { + IPACMERR("Header handle is empty.\n"); + return IPACM_FAILURE; + } + + int i, j, len; + int res = IPACM_SUCCESS; + char index[4]; + struct ipa_ioc_copy_hdr sCopyHeader; + struct ipa_ioc_add_hdr *pHeader; + + IPACMDBG_H("Get lan2lan header request, src_mac: 0x%02x%02x%02x%02x%02x%02x dst_mac: 0x%02x%02x%02x%02x%02x%02x\n", + src_mac[0], src_mac[1], src_mac[2], src_mac[3], src_mac[4], src_mac[5], dst_mac[0], dst_mac[1], + dst_mac[2], dst_mac[3], dst_mac[4], dst_mac[5]); + + len = sizeof(struct ipa_ioc_add_hdr) + sizeof(struct ipa_hdr_add); + pHeader = (struct ipa_ioc_add_hdr *)malloc(len); + if (pHeader == NULL) + { + IPACMERR("Failed to allocate header\n"); + return IPACM_FAILURE; + } + memset(pHeader, 0, len); + + if(iptype == IPA_IP_v4) + { /* copy partial header for v4*/ + for(i=0; inum_tx_props; i++) + { + if(tx_prop->tx[i].ip == IPA_IP_v4) + { + IPACMDBG_H("Got v4-header name from %d tx props\n", i); + memset(&sCopyHeader, 0, sizeof(sCopyHeader)); + memcpy(sCopyHeader.name, tx_prop->tx[i].hdr_name, sizeof(sCopyHeader.name)); + + IPACMDBG_H("Header name: %s\n", sCopyHeader.name); + if(m_header.CopyHeader(&sCopyHeader) == false) + { + IPACMERR("Copy header failed\n"); + res = IPACM_FAILURE; + goto fail; + } + + IPACMDBG_H("Header length: %d, paritial: %d\n", sCopyHeader.hdr_len, sCopyHeader.is_partial); + if (sCopyHeader.hdr_len > IPA_HDR_MAX_SIZE) + { + IPACMERR("Header oversize\n"); + res = IPACM_FAILURE; + goto fail; + } + else + { + memcpy(pHeader->hdr[0].hdr, sCopyHeader.hdr, sCopyHeader.hdr_len); + } + + if(sCopyHeader.is_eth2_ofst_valid) + { + memcpy(&pHeader->hdr[0].hdr[sCopyHeader.eth2_ofst], dst_mac, IPA_MAC_ADDR_SIZE); + memcpy(&pHeader->hdr[0].hdr[sCopyHeader.eth2_ofst+IPA_MAC_ADDR_SIZE], src_mac, IPA_MAC_ADDR_SIZE); + } + else + { + IPACMERR("Ethernet 2 header offset is invalid.\n"); + } + + pHeader->commit = true; + pHeader->num_hdrs = 1; + + memset(pHeader->hdr[0].name, 0, sizeof(pHeader->hdr[0].name)); + strlcpy(pHeader->hdr[0].name, IPA_LAN_TO_LAN_USB_HDR_NAME_V4, sizeof(pHeader->hdr[0].name)); + pHeader->hdr[0].name[IPA_RESOURCE_NAME_MAX-1] = '\0'; + for(j=0; jhdr[0].name, index, sizeof(pHeader->hdr[0].name)) > IPA_RESOURCE_NAME_MAX) + { + IPACMERR(" header name construction failed exceed length (%d)\n", strlen(pHeader->hdr[0].name)); + res = IPACM_FAILURE; + goto fail; + } + + pHeader->hdr[0].hdr_len = sCopyHeader.hdr_len; + pHeader->hdr[0].is_partial = 0; + pHeader->hdr[0].hdr_hdl = -1; + pHeader->hdr[0].status = -1; + + if (m_header.AddHeader(pHeader) == false || pHeader->hdr[0].status != 0) + { + IPACMERR("Ioctl IPA_IOC_ADD_HDR failed with status: %d\n", pHeader->hdr[0].status); + res = IPACM_FAILURE; + goto fail; + } + IPACMDBG_H("Installed v4 full header %s header handle 0x%08x\n", pHeader->hdr[0].name, + pHeader->hdr[0].hdr_hdl); + *hdr_hdl = pHeader->hdr[0].hdr_hdl; + lan2lan_hdr_hdl_v4[j].hdr_hdl = pHeader->hdr[0].hdr_hdl; + break; + } + } + } + else if(iptype == IPA_IP_v6) + { /* copy partial header for v6*/ + for(i=0; inum_tx_props; i++) + { + if(tx_prop->tx[i].ip == IPA_IP_v6) + { + IPACMDBG_H("Got v6-header name from %d tx props\n", i); + memset(&sCopyHeader, 0, sizeof(sCopyHeader)); + memcpy(sCopyHeader.name, tx_prop->tx[i].hdr_name, sizeof(sCopyHeader.name)); + + IPACMDBG_H("Header name: %s\n", sCopyHeader.name); + if(m_header.CopyHeader(&sCopyHeader) == false) + { + IPACMERR("Copy header failed\n"); + res = IPACM_FAILURE; + goto fail; + } + + IPACMDBG_H("Header length: %d, paritial: %d\n", sCopyHeader.hdr_len, sCopyHeader.is_partial); + if (sCopyHeader.hdr_len > IPA_HDR_MAX_SIZE) + { + IPACMERR("Header oversize\n"); + res = IPACM_FAILURE; + goto fail; + } + else + { + memcpy(pHeader->hdr[0].hdr, sCopyHeader.hdr, sCopyHeader.hdr_len); + } + if(sCopyHeader.is_eth2_ofst_valid) + { + memcpy(&pHeader->hdr[0].hdr[sCopyHeader.eth2_ofst], dst_mac, IPA_MAC_ADDR_SIZE); + memcpy(&pHeader->hdr[0].hdr[sCopyHeader.eth2_ofst+IPA_MAC_ADDR_SIZE], src_mac, IPA_MAC_ADDR_SIZE); + } + else + { + IPACMERR("Ethernet 2 header offset is invalid.\n"); + } + + pHeader->commit = true; + pHeader->num_hdrs = 1; + + memset(pHeader->hdr[0].name, 0, sizeof(pHeader->hdr[0].name)); + strlcpy(pHeader->hdr[0].name, IPA_LAN_TO_LAN_USB_HDR_NAME_V6, sizeof(pHeader->hdr[0].name)); + pHeader->hdr[0].name[IPA_RESOURCE_NAME_MAX-1] = '\0'; + for(j=0; jhdr[0].name, index, sizeof(pHeader->hdr[0].name)) > IPA_RESOURCE_NAME_MAX) + { + IPACMERR(" header name construction failed exceed length (%d)\n", strlen(pHeader->hdr[0].name)); + res = IPACM_FAILURE; + goto fail; + } + + pHeader->hdr[0].hdr_len = sCopyHeader.hdr_len; + pHeader->hdr[0].is_partial = 0; + pHeader->hdr[0].hdr_hdl = -1; + pHeader->hdr[0].status = -1; + + if (m_header.AddHeader(pHeader) == false || pHeader->hdr[0].status != 0) + { + IPACMERR("Ioctl IPA_IOC_ADD_HDR failed with status: %d\n", pHeader->hdr[0].status); + res = IPACM_FAILURE; + goto fail; + } + IPACMDBG_H("Installed v6 full header %s header handle 0x%08x\n", pHeader->hdr[0].name, + pHeader->hdr[0].hdr_hdl); + *hdr_hdl = pHeader->hdr[0].hdr_hdl; + lan2lan_hdr_hdl_v6[j].hdr_hdl = pHeader->hdr[0].hdr_hdl; + break; + } + } + } + else + { + IPACMERR("IP type is not expected.\n"); + } + +fail: + free(pHeader); + return res; +} + +int IPACM_Lan::del_lan2lan_hdr(ipa_ip_type iptype, uint32_t hdr_hdl) +{ + int i; + if (m_header.DeleteHeaderHdl(hdr_hdl) == false) + { + IPACMERR("Failed to delete header %d\n", hdr_hdl); + return IPACM_FAILURE; + } + IPACMDBG_H("Deleted header %d\n", hdr_hdl); + + if(iptype == IPA_IP_v4) + { + for(i=0; icommit = 1; + rt_rule->num_rules = 1; + rt_rule->ip = iptype; + + if(iptype == IPA_IP_v4) + { + IPACMDBG_H("src_v4_addr: 0x%08x dst_v4_addr: 0x%08x\n", src_v4_addr, dst_v4_addr); + + strlcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_lan2lan_v4.name, sizeof(rt_rule->rt_tbl_name)); + rt_rule_entry = &rt_rule->rules[0]; + rt_rule_entry->at_rear = false; + rt_rule_entry->rt_rule_hdl = 0; + rt_rule_entry->status = -1; + + for (tx_index = 0; tx_indexnum_tx_props; tx_index++) + { + if(tx_prop->tx[tx_index].ip != IPA_IP_v4) + { + IPACMDBG_H("Tx:%d, iptype: %d conflict ip-type: %d bypass\n", + tx_index, tx_prop->tx[tx_index].ip, IPA_IP_v4); + continue; + } + + rt_rule_entry->rule.hdr_hdl = hdr_hdl; + rt_rule_entry->rule.dst = tx_prop->tx[tx_index].dst_pipe; + memcpy(&rt_rule_entry->rule.attrib, &tx_prop->tx[tx_index].attrib, + sizeof(rt_rule_entry->rule.attrib)); + + rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_SRC_ADDR; + rt_rule_entry->rule.attrib.u.v4.src_addr = src_v4_addr; + rt_rule_entry->rule.attrib.u.v4.src_addr_mask = 0xFFFFFFFF; + + rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v4.dst_addr = dst_v4_addr; + rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF; + if(m_routing.AddRoutingRule(rt_rule) == false) + { + IPACMERR("Routing rule addition failed\n"); + res = IPACM_FAILURE; + goto fail; + } + IPACMDBG_H("Added rt rule hdl: 0x%08x\n", rt_rule_entry->rt_rule_hdl); + rule_hdl->rule_hdl[rule_hdl->num_rule] = rt_rule_entry->rt_rule_hdl; + rule_hdl->num_rule++; + } + } + else if(iptype == IPA_IP_v6) + { + if(src_v6_addr == NULL || dst_v6_addr == NULL) + { + IPACMERR("Got IPv6 rt rule but without IPv6 src/dst addr.\n"); + res = IPACM_FAILURE; + goto fail; + } + IPACMDBG_H("src_v6_addr: 0x%08x%08x%08x%08x, dst_v6_addr: 0x%08x%08x%08x%08x\n", src_v6_addr[0], src_v6_addr[1], + src_v6_addr[2], src_v6_addr[3], dst_v6_addr[0], dst_v6_addr[1], dst_v6_addr[2], dst_v6_addr[3]); + + strlcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_lan2lan_v6.name, sizeof(rt_rule->rt_tbl_name)); + rt_rule_entry = &rt_rule->rules[0]; + rt_rule_entry->at_rear = false; + rt_rule_entry->rt_rule_hdl = 0; + rt_rule_entry->status = -1; + + for (tx_index = 0; tx_indexnum_tx_props; tx_index++) + { + if(tx_prop->tx[tx_index].ip != IPA_IP_v6) + { + IPACMDBG_H("Tx:%d, iptype: %d conflict ip-type: %d bypass\n", + tx_index, tx_prop->tx[tx_index].ip, IPA_IP_v6); + continue; + } + + rt_rule_entry->rule.hdr_hdl = hdr_hdl; + rt_rule_entry->rule.dst = tx_prop->tx[tx_index].dst_pipe; + memcpy(&rt_rule_entry->rule.attrib, &tx_prop->tx[tx_index].attrib, + sizeof(rt_rule_entry->rule.attrib)); + + rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_SRC_ADDR; + rt_rule_entry->rule.attrib.u.v6.src_addr[0] = src_v6_addr[0]; + rt_rule_entry->rule.attrib.u.v6.src_addr[1] = src_v6_addr[1]; + rt_rule_entry->rule.attrib.u.v6.src_addr[2] = src_v6_addr[2]; + rt_rule_entry->rule.attrib.u.v6.src_addr[3] = src_v6_addr[3]; + rt_rule_entry->rule.attrib.u.v6.src_addr_mask[0] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.src_addr_mask[1] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.src_addr_mask[2] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.src_addr_mask[3] = 0xFFFFFFFF; + + rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = dst_v6_addr[0]; + rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = dst_v6_addr[1]; + rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = dst_v6_addr[2]; + rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = dst_v6_addr[3]; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF; + if(m_routing.AddRoutingRule(rt_rule) == false) + { + IPACMERR("Routing rule addition failed\n"); + res = IPACM_FAILURE; + goto fail; + } + IPACMDBG_H("Added rt rule hdl: 0x%08x\n", rt_rule_entry->rt_rule_hdl); + rule_hdl->rule_hdl[rule_hdl->num_rule] = rt_rule_entry->rt_rule_hdl; + rule_hdl->num_rule++; + } + } + else + { + IPACMERR("IP type is not expected.\n"); + } + +fail: + free(rt_rule); + return res; +} + +int IPACM_Lan::del_lan2lan_rt_rule(ipa_ip_type iptype, lan_to_lan_rt_rule_hdl rule_hdl) +{ + if(rule_hdl.num_rule <= 0 || rule_hdl.num_rule > MAX_NUM_PROP) + { + IPACMERR("The number of rule handles are not correct.\n"); + return IPACM_FAILURE; + } + + int i, res = IPACM_SUCCESS; + + IPACMDBG_H("Get %d rule handles with IP type %d\n", rule_hdl.num_rule, iptype); + for(i=0; iif_index = ipa_if_num; + + evt.evt_data = (void*)fid; + evt.event = IPA_LAN_DELETE_SELF; + + IPACMDBG_H("Posting event IPA_LAN_DELETE_SELF\n"); + IPACM_EvtDispatcher::PostEvt(&evt); +} + +/*handle reset usb-client rt-rules */ +int IPACM_Lan::handle_lan_client_reset_rt(ipa_ip_type iptype) +{ + int i, res = IPACM_SUCCESS; + + /* clean eth-client routing rules */ + IPACMDBG_H("left %d eth clients need to be deleted \n ", num_eth_client); + for (i = 0; i < num_eth_client; i++) + { + res = delete_eth_rtrules(i, iptype); + if (res != IPACM_SUCCESS) + { + IPACMERR("Failed to delete old iptype(%d) rules.\n", iptype); + return res; + } + } /* end of for loop */ + + /* Pass info to LAN2LAN module */ + res = post_lan2lan_client_disconnect_msg(iptype); + if (res != IPACM_SUCCESS) + { + IPACMERR("Failed to posting delete old iptype(%d) address.\n", iptype); + return res; + } + /* Reset ip-address */ + for (i = 0; i < num_eth_client; i++) + { + if(iptype == IPA_IP_v4) + { + get_client_memptr(eth_client, i)->ipv4_set = false; + } + else + { + get_client_memptr(eth_client, i)->ipv6_set = 0; + } + } /* end of for loop */ + return res; +} + +/*handle lan2lan internal mesg posting*/ +int IPACM_Lan::post_lan2lan_client_disconnect_msg(ipa_ip_type iptype) +{ + int i, j; + ipacm_cmd_q_data evt_data; + ipacm_event_lan_client* lan_client; + + for (i = 0; i < num_eth_client; i++) + { + if((get_client_memptr(eth_client, i)->ipv4_set == true) + && (iptype == IPA_IP_v4)) + { + lan_client = (ipacm_event_lan_client*)malloc(sizeof(ipacm_event_lan_client)); + if(lan_client == NULL) + { + IPACMERR("Failed to allocate memory.\n"); + return IPACM_FAILURE; + } + memset(lan_client, 0, sizeof(ipacm_event_lan_client)); + lan_client->iptype = IPA_IP_v4; + lan_client->ipv4_addr = get_client_memptr(eth_client, i)->v4_addr; + lan_client->p_iface = this; + + memset(&evt_data, 0, sizeof(ipacm_cmd_q_data)); + evt_data.evt_data = (void*)lan_client; + evt_data.event = IPA_LAN_CLIENT_DISCONNECT; + + IPACMDBG_H("Posting event IPA_LAN_CLIENT_DISCONNECT\n"); + IPACM_EvtDispatcher::PostEvt(&evt_data); + } + + if((get_client_memptr(eth_client, i)->ipv6_set > 0) + && (iptype == IPA_IP_v6)) + { + for (j = 0; j < get_client_memptr(eth_client, i)->ipv6_set; j++) + { + lan_client = (ipacm_event_lan_client*)malloc(sizeof(ipacm_event_lan_client)); + if(lan_client == NULL) + { + IPACMERR("Failed to allocate memory.\n"); + return IPACM_FAILURE; + } + memset(lan_client, 0, sizeof(ipacm_event_lan_client)); + lan_client->iptype = IPA_IP_v6; + lan_client->ipv6_addr[0] = get_client_memptr(eth_client, i)->v6_addr[j][0]; + lan_client->ipv6_addr[1] = get_client_memptr(eth_client, i)->v6_addr[j][1]; + lan_client->ipv6_addr[2] = get_client_memptr(eth_client, i)->v6_addr[j][2]; + lan_client->ipv6_addr[3] = get_client_memptr(eth_client, i)->v6_addr[j][3]; + lan_client->p_iface = this; + + memset(&evt_data, 0, sizeof(ipacm_cmd_q_data)); + evt_data.evt_data = (void*)lan_client; + evt_data.event = IPA_LAN_CLIENT_DISCONNECT; + + IPACMDBG_H("Posting event IPA_LAN_CLIENT_DISCONNECT\n"); + IPACM_EvtDispatcher::PostEvt(&evt_data); + } + } + } /* end of for loop */ + return IPACM_SUCCESS; +} + +int IPACM_Lan::install_ipv4_icmp_flt_rule() +{ + int len; + struct ipa_ioc_add_flt_rule* flt_rule; + struct ipa_flt_rule_add flt_rule_entry; + + if(rx_prop != NULL) + { + len = sizeof(struct ipa_ioc_add_flt_rule) + sizeof(struct ipa_flt_rule_add); + + flt_rule = (struct ipa_ioc_add_flt_rule *)calloc(1, len); + if (!flt_rule) + { + IPACMERR("Error Locate ipa_flt_rule_add memory...\n"); + return IPACM_FAILURE; + } + + flt_rule->commit = 1; + flt_rule->ep = rx_prop->rx[0].src_pipe; + flt_rule->global = false; + flt_rule->ip = IPA_IP_v4; + flt_rule->num_rules = 1; + + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); + + flt_rule_entry.rule.retain_hdr = 1; + flt_rule_entry.rule.to_uc = 0; + flt_rule_entry.rule.eq_attrib_type = 0; + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl = -1; + flt_rule_entry.status = -1; + flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION; + memcpy(&flt_rule_entry.rule.attrib, &rx_prop->rx[0].attrib, sizeof(flt_rule_entry.rule.attrib)); + + flt_rule_entry.rule.attrib.attrib_mask &= ~((uint32_t)IPA_FLT_META_DATA); + flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_PROTOCOL; + flt_rule_entry.rule.attrib.u.v4.protocol = (uint8_t)IPACM_FIREWALL_IPPROTO_ICMP; + memcpy(&(flt_rule->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + + if (m_filtering.AddFilteringRule(flt_rule) == false) + { + IPACMERR("Error Adding Filtering rule, aborting...\n"); + free(flt_rule); + return IPACM_FAILURE; + } + else + { + IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, 1); + ipv4_icmp_flt_rule_hdl[0] = flt_rule->rules[0].flt_rule_hdl; + IPACMDBG_H("IPv4 icmp filter rule HDL:0x%x\n", ipv4_icmp_flt_rule_hdl[0]); + free(flt_rule); + } + } + return IPACM_SUCCESS; +} + +void IPACM_Lan::install_tcp_ctl_flt_rule(ipa_ip_type iptype) +{ + if (rx_prop == NULL) + { + IPACMDBG_H("No rx properties registered for iface %s\n", dev_name); + return; + } + + int len, i; + struct ipa_flt_rule_add flt_rule; + ipa_ioc_add_flt_rule* pFilteringTable; + + len = sizeof(struct ipa_ioc_add_flt_rule) + NUM_TCP_CTL_FLT_RULE * sizeof(struct ipa_flt_rule_add); + + pFilteringTable = (struct ipa_ioc_add_flt_rule *)malloc(len); + if (pFilteringTable == NULL) + { + IPACMERR("Error allocate flt table memory...\n"); + return; + } + memset(pFilteringTable, 0, len); + + pFilteringTable->commit = 1; + pFilteringTable->ip = iptype; + pFilteringTable->ep = rx_prop->rx[0].src_pipe; + pFilteringTable->global = false; + pFilteringTable->num_rules = NUM_TCP_CTL_FLT_RULE; + + memset(&flt_rule, 0, sizeof(struct ipa_flt_rule_add)); + + flt_rule.at_rear = true; + flt_rule.flt_rule_hdl = -1; + flt_rule.status = -1; + + flt_rule.rule.retain_hdr = 1; + flt_rule.rule.to_uc = 0; + flt_rule.rule.action = IPA_PASS_TO_EXCEPTION; +#ifdef FEATURE_IPA_V3 + flt_rule.rule.hashable = IPA_RULE_NON_HASHABLE; +#endif + flt_rule.rule.eq_attrib_type = 1; + + flt_rule.rule.eq_attrib.rule_eq_bitmap = 0; + + if(rx_prop->rx[0].attrib.attrib_mask & IPA_FLT_META_DATA) + { + flt_rule.rule.eq_attrib.rule_eq_bitmap |= (1<<14); + flt_rule.rule.eq_attrib.metadata_meq32_present = 1; + flt_rule.rule.eq_attrib.metadata_meq32.offset = 0; + flt_rule.rule.eq_attrib.metadata_meq32.value = rx_prop->rx[0].attrib.meta_data; + flt_rule.rule.eq_attrib.metadata_meq32.mask = rx_prop->rx[0].attrib.meta_data_mask; + } + + flt_rule.rule.eq_attrib.rule_eq_bitmap |= (1<<1); + flt_rule.rule.eq_attrib.protocol_eq_present = 1; + flt_rule.rule.eq_attrib.protocol_eq = IPACM_FIREWALL_IPPROTO_TCP; + + flt_rule.rule.eq_attrib.rule_eq_bitmap |= (1<<8); + flt_rule.rule.eq_attrib.num_ihl_offset_meq_32 = 1; + flt_rule.rule.eq_attrib.ihl_offset_meq_32[0].offset = 12; + + /* add TCP FIN rule*/ + flt_rule.rule.eq_attrib.ihl_offset_meq_32[0].value = (((uint32_t)1)<rules[0]), &flt_rule, sizeof(struct ipa_flt_rule_add)); + + /* add TCP SYN rule*/ + flt_rule.rule.eq_attrib.ihl_offset_meq_32[0].value = (((uint32_t)1)<rules[1]), &flt_rule, sizeof(struct ipa_flt_rule_add)); + + /* add TCP RST rule*/ + flt_rule.rule.eq_attrib.ihl_offset_meq_32[0].value = (((uint32_t)1)<rules[2]), &flt_rule, sizeof(struct ipa_flt_rule_add)); + + if (false == m_filtering.AddFilteringRule(pFilteringTable)) + { + IPACMERR("Error adding tcp control flt rule\n"); + goto fail; + } + else + { + if(iptype == IPA_IP_v4) + { + for(i=0; irules[i].flt_rule_hdl; + } + IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, iptype, NUM_TCP_CTL_FLT_RULE); + } + else + { + for(i=0; irules[i].flt_rule_hdl; + } + IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, iptype, NUM_TCP_CTL_FLT_RULE); + } + } + +fail: + free(pFilteringTable); + return; +} + +int IPACM_Lan::add_dummy_private_subnet_flt_rule(ipa_ip_type iptype) +{ + if(rx_prop == NULL) + { + IPACMDBG_H("There is no rx_prop for iface %s, not able to add dummy private subnet filtering rule.\n", dev_name); + return 0; + } + + if(iptype == IPA_IP_v6) + { + IPACMDBG_H("There is no ipv6 dummy filter rules needed for iface %s\n", dev_name); + return 0; + } + int i, len, res = IPACM_SUCCESS; + struct ipa_flt_rule_add flt_rule; + ipa_ioc_add_flt_rule* pFilteringTable; + + len = sizeof(struct ipa_ioc_add_flt_rule) + IPA_MAX_PRIVATE_SUBNET_ENTRIES * sizeof(struct ipa_flt_rule_add); + + pFilteringTable = (struct ipa_ioc_add_flt_rule *)malloc(len); + if (pFilteringTable == NULL) + { + IPACMERR("Error allocate flt table memory...\n"); + return IPACM_FAILURE; + } + memset(pFilteringTable, 0, len); + + pFilteringTable->commit = 1; + pFilteringTable->ep = rx_prop->rx[0].src_pipe; + pFilteringTable->global = false; + pFilteringTable->ip = iptype; + pFilteringTable->num_rules = IPA_MAX_PRIVATE_SUBNET_ENTRIES; + + memset(&flt_rule, 0, sizeof(struct ipa_flt_rule_add)); + + flt_rule.rule.retain_hdr = 0; + flt_rule.at_rear = true; + flt_rule.flt_rule_hdl = -1; + flt_rule.status = -1; + flt_rule.rule.action = IPA_PASS_TO_EXCEPTION; + memcpy(&flt_rule.rule.attrib, &rx_prop->rx[0].attrib, + sizeof(flt_rule.rule.attrib)); + + if(iptype == IPA_IP_v4) + { + flt_rule.rule.attrib.attrib_mask = IPA_FLT_SRC_ADDR | IPA_FLT_DST_ADDR; + flt_rule.rule.attrib.u.v4.src_addr_mask = ~0; + flt_rule.rule.attrib.u.v4.src_addr = ~0; + flt_rule.rule.attrib.u.v4.dst_addr_mask = ~0; + flt_rule.rule.attrib.u.v4.dst_addr = ~0; + + for(i=0; irules[i]), &flt_rule, sizeof(struct ipa_flt_rule_add)); + } + + if (false == m_filtering.AddFilteringRule(pFilteringTable)) + { + IPACMERR("Error adding dummy private subnet v4 flt rule\n"); + res = IPACM_FAILURE; + goto fail; + } + else + { + IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, IPA_MAX_PRIVATE_SUBNET_ENTRIES); + /* copy filter rule hdls */ + for (int i = 0; i < IPA_MAX_PRIVATE_SUBNET_ENTRIES; i++) + { + if (pFilteringTable->rules[i].status == 0) + { + private_fl_rule_hdl[i] = pFilteringTable->rules[i].flt_rule_hdl; + IPACMDBG_H("Private subnet v4 flt rule %d hdl:0x%x\n", i, private_fl_rule_hdl[i]); + } + else + { + IPACMERR("Failed adding lan2lan v4 flt rule %d\n", i); + res = IPACM_FAILURE; + goto fail; + } + } + } + } +fail: + free(pFilteringTable); + return res; +} + +int IPACM_Lan::handle_private_subnet_android(ipa_ip_type iptype) +{ + int i, len, res = IPACM_SUCCESS; + struct ipa_flt_rule_mdfy flt_rule; + struct ipa_ioc_mdfy_flt_rule* pFilteringTable; + + if (rx_prop == NULL) + { + IPACMDBG_H("No rx properties registered for iface %s\n", dev_name); + return IPACM_SUCCESS; + } + + if(iptype == IPA_IP_v6) + { + IPACMDBG_H("There is no ipv6 dummy filter rules needed for iface %s\n", dev_name); + return 0; + } + else + { + for(i=0; iipa_num_private_subnet) * sizeof(struct ipa_flt_rule_mdfy); + pFilteringTable = (struct ipa_ioc_mdfy_flt_rule*)malloc(len); + if (!pFilteringTable) + { + IPACMERR("Failed to allocate ipa_ioc_mdfy_flt_rule memory...\n"); + return IPACM_FAILURE; + } + memset(pFilteringTable, 0, len); + + pFilteringTable->commit = 1; + pFilteringTable->ip = iptype; + pFilteringTable->num_rules = (uint8_t)IPACM_Iface::ipacmcfg->ipa_num_private_subnet; + + /* Make LAN-traffic always go A5, use default IPA-RT table */ + if (false == m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_default_v4)) + { + IPACMERR("Failed to get routing table handle.\n"); + res = IPACM_FAILURE; + goto fail; + } + + memset(&flt_rule, 0, sizeof(struct ipa_flt_rule_mdfy)); + flt_rule.status = -1; + + flt_rule.rule.retain_hdr = 1; + flt_rule.rule.to_uc = 0; + flt_rule.rule.action = IPA_PASS_TO_ROUTING; + flt_rule.rule.eq_attrib_type = 0; + flt_rule.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_default_v4.hdl; + IPACMDBG_H("Private filter rule use table: %s\n",IPACM_Iface::ipacmcfg->rt_tbl_default_v4.name); + + memcpy(&flt_rule.rule.attrib, &rx_prop->rx[0].attrib, sizeof(flt_rule.rule.attrib)); + flt_rule.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; + + for (i = 0; i < (IPACM_Iface::ipacmcfg->ipa_num_private_subnet); i++) + { + flt_rule.rule_hdl = private_fl_rule_hdl[i]; + flt_rule.rule.attrib.u.v4.dst_addr_mask = IPACM_Iface::ipacmcfg->private_subnet_table[i].subnet_mask; + flt_rule.rule.attrib.u.v4.dst_addr = IPACM_Iface::ipacmcfg->private_subnet_table[i].subnet_addr; + memcpy(&(pFilteringTable->rules[i]), &flt_rule, sizeof(struct ipa_flt_rule_mdfy)); + IPACMDBG_H(" IPACM private subnet_addr as: 0x%x entry(%d)\n", flt_rule.rule.attrib.u.v4.dst_addr, i); + } + + if (false == m_filtering.ModifyFilteringRule(pFilteringTable)) + { + IPACMERR("Failed to modify private subnet filtering rules.\n"); + res = IPACM_FAILURE; + goto fail; + } + } +fail: + if(pFilteringTable != NULL) + { + free(pFilteringTable); + } + return res; +} + +int IPACM_Lan::install_ipv6_prefix_flt_rule(uint32_t* prefix) +{ + if(prefix == NULL) + { + IPACMERR("IPv6 prefix is empty.\n"); + return IPACM_FAILURE; + } + IPACMDBG_H("Receive IPv6 prefix: 0x%08x%08x.\n", prefix[0], prefix[1]); + + int len; + struct ipa_ioc_add_flt_rule* flt_rule; + struct ipa_flt_rule_add flt_rule_entry; + + if(rx_prop != NULL) + { + len = sizeof(struct ipa_ioc_add_flt_rule) + sizeof(struct ipa_flt_rule_add); + + flt_rule = (struct ipa_ioc_add_flt_rule *)calloc(1, len); + if (!flt_rule) + { + IPACMERR("Error Locate ipa_flt_rule_add memory...\n"); + return IPACM_FAILURE; + } + + flt_rule->commit = 1; + flt_rule->ep = rx_prop->rx[0].src_pipe; + flt_rule->global = false; + flt_rule->ip = IPA_IP_v6; + flt_rule->num_rules = 1; + + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); + + flt_rule_entry.rule.retain_hdr = 1; + flt_rule_entry.rule.to_uc = 0; + flt_rule_entry.rule.eq_attrib_type = 0; + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl = -1; + flt_rule_entry.status = -1; + flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION; +#ifdef FEATURE_IPA_V3 + flt_rule_entry.rule.hashable = IPA_RULE_NON_HASHABLE; +#endif + memcpy(&flt_rule_entry.rule.attrib, &rx_prop->rx[0].attrib, sizeof(flt_rule_entry.rule.attrib)); + flt_rule_entry.rule.attrib.attrib_mask = flt_rule_entry.rule.attrib.attrib_mask & ~((uint32_t)IPA_FLT_META_DATA); + flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; + flt_rule_entry.rule.attrib.u.v6.dst_addr[0] = prefix[0]; + flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = prefix[1]; + flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = 0x0; + flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0x0; + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF; + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF; + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[2] = 0x0; + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = 0x0; + memcpy(&(flt_rule->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + + if (m_filtering.AddFilteringRule(flt_rule) == false) + { + IPACMERR("Error Adding Filtering rule, aborting...\n"); + free(flt_rule); + return IPACM_FAILURE; + } + else + { + IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1); + ipv6_prefix_flt_rule_hdl[0] = flt_rule->rules[0].flt_rule_hdl; + IPACMDBG_H("IPv6 prefix filter rule HDL:0x%x\n", ipv6_prefix_flt_rule_hdl[0]); + free(flt_rule); + } + } + return IPACM_SUCCESS; +} + +void IPACM_Lan::delete_ipv6_prefix_flt_rule() +{ + if(m_filtering.DeleteFilteringHdls(ipv6_prefix_flt_rule_hdl, IPA_IP_v6, NUM_IPV6_PREFIX_FLT_RULE) == false) + { + IPACMERR("Failed to delete ipv6 prefix flt rule.\n"); + return; + } + IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, NUM_IPV6_PREFIX_FLT_RULE); + return; +} + +int IPACM_Lan::install_ipv6_icmp_flt_rule() +{ + + int len; + struct ipa_ioc_add_flt_rule* flt_rule; + struct ipa_flt_rule_add flt_rule_entry; + + if(rx_prop != NULL) + { + len = sizeof(struct ipa_ioc_add_flt_rule) + sizeof(struct ipa_flt_rule_add); + + flt_rule = (struct ipa_ioc_add_flt_rule *)calloc(1, len); + if (!flt_rule) + { + IPACMERR("Error Locate ipa_flt_rule_add memory...\n"); + return IPACM_FAILURE; + } + + flt_rule->commit = 1; + flt_rule->ep = rx_prop->rx[0].src_pipe; + flt_rule->global = false; + flt_rule->ip = IPA_IP_v6; + flt_rule->num_rules = 1; + + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); + + flt_rule_entry.rule.retain_hdr = 1; + flt_rule_entry.rule.to_uc = 0; + flt_rule_entry.rule.eq_attrib_type = 0; + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl = -1; + flt_rule_entry.status = -1; + flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION; +#ifdef FEATURE_IPA_V3 + flt_rule_entry.rule.hashable = IPA_RULE_NON_HASHABLE; +#endif + memcpy(&flt_rule_entry.rule.attrib, &rx_prop->rx[0].attrib, sizeof(flt_rule_entry.rule.attrib)); + flt_rule_entry.rule.attrib.attrib_mask = flt_rule_entry.rule.attrib.attrib_mask & ~((uint32_t)IPA_FLT_META_DATA); + flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_NEXT_HDR; + flt_rule_entry.rule.attrib.u.v6.next_hdr = (uint8_t)IPACM_FIREWALL_IPPROTO_ICMP6; + memcpy(&(flt_rule->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + + if (m_filtering.AddFilteringRule(flt_rule) == false) + { + IPACMERR("Error Adding Filtering rule, aborting...\n"); + free(flt_rule); + return IPACM_FAILURE; + } + else + { + IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1); + ipv6_icmp_flt_rule_hdl[0] = flt_rule->rules[0].flt_rule_hdl; + IPACMDBG_H("IPv6 icmp filter rule HDL:0x%x\n", ipv6_icmp_flt_rule_hdl[0]); + free(flt_rule); + } + } + return IPACM_SUCCESS; +} + +int IPACM_Lan::handle_addr_evt_odu_bridge(ipacm_event_data_addr* data) +{ + int fd, res = IPACM_SUCCESS; + struct in6_addr ipv6_addr; + if(data == NULL) + { + IPACMERR("Failed to get interface IP address.\n"); + return IPACM_FAILURE; + } + + if(data->iptype == IPA_IP_v6) + { + fd = open(IPACM_Iface::ipacmcfg->DEVICE_NAME_ODU, O_RDWR); + if(fd == 0) + { + IPACMERR("Failed to open %s.\n", IPACM_Iface::ipacmcfg->DEVICE_NAME_ODU); + return IPACM_FAILURE; + } + + memcpy(&ipv6_addr, data->ipv6_addr, sizeof(struct in6_addr)); + + if( ioctl(fd, ODU_BRIDGE_IOC_SET_LLV6_ADDR, &ipv6_addr) ) + { + IPACMERR("Failed to write IPv6 address to odu driver.\n"); + res = IPACM_FAILURE; + } + num_dft_rt_v6++; + close(fd); + } + + return res; +} + +int IPACM_Lan::eth_bridge_handle_dummy_wlan_client_flt_rule(ipa_ip_type iptype) +{ + if(rx_prop == NULL) + { + IPACMDBG_H("There is no rx_prop for iface %s, not able to add dummy wlan client specific filtering rule.\n", dev_name); + return 0; + } + + int i, len, res = IPACM_SUCCESS; + struct ipa_flt_rule_add flt_rule; + ipa_ioc_add_flt_rule* pFilteringTable; + + len = sizeof(struct ipa_ioc_add_flt_rule) + IPA_LAN_TO_LAN_MAX_WLAN_CLIENT * sizeof(struct ipa_flt_rule_add); + + pFilteringTable = (struct ipa_ioc_add_flt_rule *)malloc(len); + if (pFilteringTable == NULL) + { + IPACMERR("Error allocate flt table memory...\n"); + return IPACM_FAILURE; + } + memset(pFilteringTable, 0, len); + + pFilteringTable->commit = 1; + pFilteringTable->ep = rx_prop->rx[0].src_pipe; + pFilteringTable->global = false; + pFilteringTable->ip = iptype; + pFilteringTable->num_rules = IPA_LAN_TO_LAN_MAX_WLAN_CLIENT; + + memset(&flt_rule, 0, sizeof(struct ipa_flt_rule_add)); + + flt_rule.rule.retain_hdr = 0; + flt_rule.at_rear = true; + flt_rule.flt_rule_hdl = -1; + flt_rule.status = -1; + flt_rule.rule.action = IPA_PASS_TO_EXCEPTION; + memcpy(&flt_rule.rule.attrib, &rx_prop->rx[0].attrib, + sizeof(flt_rule.rule.attrib)); + + if(iptype == IPA_IP_v4) + { + flt_rule.rule.attrib.attrib_mask = IPA_FLT_SRC_ADDR | IPA_FLT_DST_ADDR; + flt_rule.rule.attrib.u.v4.src_addr_mask = ~0; + flt_rule.rule.attrib.u.v4.src_addr = ~0; + flt_rule.rule.attrib.u.v4.dst_addr_mask = ~0; + flt_rule.rule.attrib.u.v4.dst_addr = ~0; + + for(i=0; irules[i]), &flt_rule, sizeof(struct ipa_flt_rule_add)); + } + + if (false == m_filtering.AddFilteringRule(pFilteringTable)) + { + IPACMERR("Error adding dummy lan2lan v4 flt rule\n"); + res = IPACM_FAILURE; + goto fail; + } + else + { + IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, iptype, IPA_LAN_TO_LAN_MAX_WLAN_CLIENT); + /* copy filter rule hdls */ + for (int i = 0; i < IPA_LAN_TO_LAN_MAX_WLAN_CLIENT; i++) + { + if (pFilteringTable->rules[i].status == 0) + { + wlan_client_flt_rule_hdl_v4[i].rule_hdl = pFilteringTable->rules[i].flt_rule_hdl; + wlan_client_flt_rule_hdl_v4[i].valid = true; + IPACMDBG_H("Wlan client v4 flt rule %d hdl:0x%x\n", i, wlan_client_flt_rule_hdl_v4[i].rule_hdl); + } + else + { + IPACMERR("Failed adding wlan client v4 flt rule %d\n", i); + res = IPACM_FAILURE; + goto fail; + } + } + } + } + else if(iptype == IPA_IP_v6) + { + flt_rule.rule.attrib.attrib_mask = IPA_FLT_SRC_ADDR | IPA_FLT_DST_ADDR; + flt_rule.rule.attrib.u.v6.src_addr_mask[0] = ~0; + flt_rule.rule.attrib.u.v6.src_addr_mask[1] = ~0; + flt_rule.rule.attrib.u.v6.src_addr_mask[2] = ~0; + flt_rule.rule.attrib.u.v6.src_addr_mask[3] = ~0; + flt_rule.rule.attrib.u.v6.src_addr[0] = ~0; + flt_rule.rule.attrib.u.v6.src_addr[1] = ~0; + flt_rule.rule.attrib.u.v6.src_addr[2] = ~0; + flt_rule.rule.attrib.u.v6.src_addr[3] = ~0; + flt_rule.rule.attrib.u.v6.dst_addr_mask[0] = ~0; + flt_rule.rule.attrib.u.v6.dst_addr_mask[1] = ~0; + flt_rule.rule.attrib.u.v6.dst_addr_mask[2] = ~0; + flt_rule.rule.attrib.u.v6.dst_addr_mask[3] = ~0; + flt_rule.rule.attrib.u.v6.dst_addr[0] = ~0; + flt_rule.rule.attrib.u.v6.dst_addr[1] = ~0; + flt_rule.rule.attrib.u.v6.dst_addr[2] = ~0; + flt_rule.rule.attrib.u.v6.dst_addr[3] = ~0; + + for(i=0; irules[i]), &flt_rule, sizeof(struct ipa_flt_rule_add)); + } + + if (false == m_filtering.AddFilteringRule(pFilteringTable)) + { + IPACMERR("Error adding dummy lan2lan v6 flt rule\n"); + res = IPACM_FAILURE; + goto fail; + } + else + { + IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, iptype, IPA_LAN_TO_LAN_MAX_WLAN_CLIENT); + /* copy filter rule hdls */ + for (int i = 0; i < IPA_LAN_TO_LAN_MAX_WLAN_CLIENT; i++) + { + if (pFilteringTable->rules[i].status == 0) + { + wlan_client_flt_rule_hdl_v6[i].rule_hdl = pFilteringTable->rules[i].flt_rule_hdl; + wlan_client_flt_rule_hdl_v6[i].valid = true; + IPACMDBG_H("Wlan client v6 flt rule %d hdl:0x%x\n", i, wlan_client_flt_rule_hdl_v6[i].rule_hdl); + } + else + { + IPACMERR("Failed adding wlan client v6 flt rule %d\n", i); + res = IPACM_FAILURE; + goto fail; + } + } + } + } + else + { + IPACMERR("IP type is not expected.\n"); + goto fail; + } + +fail: + free(pFilteringTable); + return res; +} + +int IPACM_Lan::eth_bridge_handle_dummy_lan_client_flt_rule(ipa_ip_type iptype) +{ + if(rx_prop == NULL) + { + IPACMDBG_H("There is no rx_prop for iface %s, not able to add dummy lan client specific filtering rule.\n", dev_name); + return 0; + } + + int i, len, res = IPACM_SUCCESS, num_dummy_rules; + struct ipa_flt_rule_add flt_rule; + ipa_ioc_add_flt_rule* pFilteringTable; + + if (IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat == LAN_IF) + { + num_dummy_rules = IPA_LAN_TO_LAN_MAX_CPE_CLIENT; + } + if (IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat == ODU_IF) + { + num_dummy_rules = IPA_LAN_TO_LAN_MAX_USB_CLIENT; + } + + len = sizeof(struct ipa_ioc_add_flt_rule) + num_dummy_rules * sizeof(struct ipa_flt_rule_add); + + pFilteringTable = (struct ipa_ioc_add_flt_rule *)malloc(len); + if (pFilteringTable == NULL) + { + IPACMERR("Error allocate flt table memory...\n"); + return IPACM_FAILURE; + } + memset(pFilteringTable, 0, len); + + pFilteringTable->commit = 1; + pFilteringTable->ep = rx_prop->rx[0].src_pipe; + pFilteringTable->global = false; + pFilteringTable->ip = iptype; + pFilteringTable->num_rules = num_dummy_rules; + + memset(&flt_rule, 0, sizeof(struct ipa_flt_rule_add)); + + flt_rule.rule.retain_hdr = 0; + flt_rule.at_rear = true; + flt_rule.flt_rule_hdl = -1; + flt_rule.status = -1; + flt_rule.rule.action = IPA_PASS_TO_EXCEPTION; + memcpy(&flt_rule.rule.attrib, &rx_prop->rx[0].attrib, + sizeof(flt_rule.rule.attrib)); + + if(iptype == IPA_IP_v4) + { + flt_rule.rule.attrib.attrib_mask = IPA_FLT_SRC_ADDR | IPA_FLT_DST_ADDR; + flt_rule.rule.attrib.u.v4.src_addr_mask = ~0; + flt_rule.rule.attrib.u.v4.src_addr = ~0; + flt_rule.rule.attrib.u.v4.dst_addr_mask = ~0; + flt_rule.rule.attrib.u.v4.dst_addr = ~0; + + for(i=0; i < num_dummy_rules; i++) + { + memcpy(&(pFilteringTable->rules[i]), &flt_rule, sizeof(struct ipa_flt_rule_add)); + } + + if (false == m_filtering.AddFilteringRule(pFilteringTable)) + { + IPACMERR("Error adding dummy lan2lan v4 flt rule\n"); + res = IPACM_FAILURE; + goto fail; + } + else + { + IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, iptype, num_dummy_rules); + /* copy filter rule hdls */ + for (int i = 0; i < num_dummy_rules; i++) + { + if (pFilteringTable->rules[i].status == 0) + { + lan_client_flt_rule_hdl_v4[i].rule_hdl = pFilteringTable->rules[i].flt_rule_hdl; + lan_client_flt_rule_hdl_v4[i].valid = true; + IPACMDBG_H("Lan client v4 flt rule %d hdl:0x%x\n", i, lan_client_flt_rule_hdl_v4[i].rule_hdl); + } + else + { + IPACMERR("Failed adding lan client v4 flt rule %d\n", i); + res = IPACM_FAILURE; + goto fail; + } + } + } + } + else if(iptype == IPA_IP_v6) + { + flt_rule.rule.attrib.attrib_mask = IPA_FLT_SRC_ADDR | IPA_FLT_DST_ADDR; + flt_rule.rule.attrib.u.v6.src_addr_mask[0] = ~0; + flt_rule.rule.attrib.u.v6.src_addr_mask[1] = ~0; + flt_rule.rule.attrib.u.v6.src_addr_mask[2] = ~0; + flt_rule.rule.attrib.u.v6.src_addr_mask[3] = ~0; + flt_rule.rule.attrib.u.v6.src_addr[0] = ~0; + flt_rule.rule.attrib.u.v6.src_addr[1] = ~0; + flt_rule.rule.attrib.u.v6.src_addr[2] = ~0; + flt_rule.rule.attrib.u.v6.src_addr[3] = ~0; + flt_rule.rule.attrib.u.v6.dst_addr_mask[0] = ~0; + flt_rule.rule.attrib.u.v6.dst_addr_mask[1] = ~0; + flt_rule.rule.attrib.u.v6.dst_addr_mask[2] = ~0; + flt_rule.rule.attrib.u.v6.dst_addr_mask[3] = ~0; + flt_rule.rule.attrib.u.v6.dst_addr[0] = ~0; + flt_rule.rule.attrib.u.v6.dst_addr[1] = ~0; + flt_rule.rule.attrib.u.v6.dst_addr[2] = ~0; + flt_rule.rule.attrib.u.v6.dst_addr[3] = ~0; + + for(i=0; irules[i]), &flt_rule, sizeof(struct ipa_flt_rule_add)); + } + + if (false == m_filtering.AddFilteringRule(pFilteringTable)) + { + IPACMERR("Error adding dummy lan2lan v6 flt rule\n"); + res = IPACM_FAILURE; + goto fail; + } + else + { + IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, iptype, num_dummy_rules); + /* copy filter rule hdls */ + for (int i = 0; i < num_dummy_rules; i++) + { + if (pFilteringTable->rules[i].status == 0) + { + lan_client_flt_rule_hdl_v6[i].rule_hdl = pFilteringTable->rules[i].flt_rule_hdl; + lan_client_flt_rule_hdl_v6[i].valid = true; + IPACMDBG_H("Lan client v6 flt rule %d hdl:0x%x\n", i, lan_client_flt_rule_hdl_v6[i].rule_hdl); + } + else + { + IPACMERR("Failed adding lan client v6 flt rule %d\n", i); + res = IPACM_FAILURE; + goto fail; + } + } + } + } + else + { + IPACMERR("IP type is not expected.\n"); + goto fail; + } + +fail: + free(pFilteringTable); + return res; +} + +int IPACM_Lan::eth_bridge_post_lan_client_event(uint8_t* mac_addr, ipa_cm_event_id evt) +{ + if(mac_addr == NULL) + { + IPACMERR("Event mac is empty.\n"); + return IPACM_FAILURE; + } + + ipacm_cmd_q_data evt_data; + memset(&evt_data, 0, sizeof(evt_data)); + + ipacm_event_data_mac* mac; + mac = (ipacm_event_data_mac*)malloc(sizeof(ipacm_event_data_mac)); + if(mac == NULL) + { + IPACMERR("Unable to allocate memory.\n"); + return IPACM_FAILURE; + } + memset(mac, 0, sizeof(ipacm_event_data_mac)); + memcpy(mac->mac_addr, mac_addr, 6 * sizeof(uint8_t)); + mac->if_index = ipa_if_num; + + evt_data.event = evt; + evt_data.evt_data = (void*)mac; + IPACMDBG_H("Posting event: %d if_index: %d \n", evt, mac->if_index); + IPACM_EvtDispatcher::PostEvt(&evt_data); + return IPACM_SUCCESS; +} + +int IPACM_Lan::eth_bridge_add_wlan_client_flt_rule(uint8_t* mac, ipa_ip_type iptype) +{ + int i, len, res = IPACM_SUCCESS, client_position; + struct ipa_flt_rule_mdfy flt_rule; + struct ipa_ioc_mdfy_flt_rule* pFilteringTable = NULL; + bool client_is_found = false; + + if (rx_prop == NULL) + { + IPACMDBG_H("No rx properties registered for iface %s\n", dev_name); + return IPACM_FAILURE; + } + if(mac == NULL) + { + IPACMERR("MAC address is empty.\n"); + return IPACM_FAILURE; + } + if(IPACM_Lan::lan_to_wlan_hdr_proc_ctx.valid == false) + { + IPACMDBG_H("USB to WLAN hdr proc ctx has not been set, don't add client specific flt rule.\n"); + return IPACM_FAILURE; + } + + IPACMDBG_H("Received WLAN client MAC 0x%02x%02x%02x%02x%02x%02x.\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + + for(i=0; icommit = 1; + pFilteringTable->ip = iptype; + pFilteringTable->num_rules = 1; + + memset(&flt_rule, 0, sizeof(struct ipa_flt_rule_mdfy)); + flt_rule.status = -1; + + flt_rule.rule.retain_hdr = 0; + flt_rule.rule.to_uc = 0; + flt_rule.rule.action = IPA_PASS_TO_ROUTING; + flt_rule.rule.eq_attrib_type = 0; + + /* point to USB-WLAN routing table */ + if(iptype == IPA_IP_v4) + { + if (false == m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_eth_bridge_lan_wlan_v4)) + { + IPACMERR("Failed to get routing table handle.\n"); + res = IPACM_FAILURE; + goto fail; + } + flt_rule.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_eth_bridge_lan_wlan_v4.hdl; + IPACMDBG_H("LAN->WLAN filter rule use table: %s\n",IPACM_Iface::ipacmcfg->rt_tbl_eth_bridge_lan_wlan_v4.name); + } + else + { + if (false == m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_eth_bridge_lan_wlan_v6)) + { + IPACMERR("Failed to get routing table handle.\n"); + res = IPACM_FAILURE; + goto fail; + } + flt_rule.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_eth_bridge_lan_wlan_v6.hdl; + IPACMDBG_H("LAN->WLAN filter rule use table: %s\n",IPACM_Iface::ipacmcfg->rt_tbl_eth_bridge_lan_wlan_v6.name); + } + + memcpy(&flt_rule.rule.attrib, &rx_prop->rx[0].attrib, sizeof(flt_rule.rule.attrib)); + if(IPACM_Lan::lan_hdr_type == IPA_HDR_L2_ETHERNET_II) + { + flt_rule.rule.attrib.attrib_mask |= IPA_FLT_MAC_DST_ADDR_ETHER_II; + } + else if(IPACM_Lan::lan_hdr_type == IPA_HDR_L2_802_3) + { + flt_rule.rule.attrib.attrib_mask |= IPA_FLT_MAC_DST_ADDR_802_3; + } + else + { + IPACMERR("USB hdr type is not expected.\n"); + res = IPACM_FAILURE; + goto fail; + } + memcpy(flt_rule.rule.attrib.dst_mac_addr, mac, sizeof(flt_rule.rule.attrib.dst_mac_addr)); + memset(flt_rule.rule.attrib.dst_mac_addr_mask, 0xFF, sizeof(flt_rule.rule.attrib.dst_mac_addr_mask)); + + if(iptype == IPA_IP_v4) + { + for(i=0; irules[0]), &flt_rule, sizeof(struct ipa_flt_rule_mdfy)); + if (false == m_filtering.ModifyFilteringRule(pFilteringTable)) + { + IPACMERR("Failed to add wlan client filtering rules.\n"); + res = IPACM_FAILURE; + goto fail; + } + + if(client_is_found == false) + { + client_position = wlan_client_flt_info_count; + wlan_client_flt_info_count++; + } + + memcpy(eth_bridge_wlan_client_flt_info[client_position].mac, mac, sizeof(eth_bridge_wlan_client_flt_info[client_position].mac)); + if(iptype == IPA_IP_v4) + { + eth_bridge_wlan_client_flt_info[client_position].flt_rule_set_v4 = true; + eth_bridge_wlan_client_flt_info[client_position].flt_rule_hdl_v4 = wlan_client_flt_rule_hdl_v4[i].rule_hdl; + } + else + { + eth_bridge_wlan_client_flt_info[client_position].flt_rule_set_v6 = true; + eth_bridge_wlan_client_flt_info[client_position].flt_rule_hdl_v6 = wlan_client_flt_rule_hdl_v6[i].rule_hdl; + } + +fail: + free(pFilteringTable); + + return res; +} + +int IPACM_Lan::eth_bridge_del_wlan_client_flt_rule(uint8_t* mac) +{ + if(mac == NULL) + { + IPACMERR("Client MAC address is empty.\n"); + return IPACM_FAILURE; + } + + IPACMDBG_H("Received WLAN client MAC 0x%02x%02x%02x%02x%02x%02x.\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + + int i, j, res = IPACM_SUCCESS; + for(i=0; iiface_table[ipa_if_num].if_cat); + + for (i=0; icommit = 1; + pFilteringTable->ip = iptype; + pFilteringTable->num_rules = 1; + + memset(&flt_rule, 0, sizeof(struct ipa_flt_rule_mdfy)); + flt_rule.status = -1; + + flt_rule.rule.retain_hdr = 0; + flt_rule.rule.to_uc = 0; + flt_rule.rule.action = IPA_PASS_TO_ROUTING; + flt_rule.rule.eq_attrib_type = 0; + + /* point to LAN-LAN routing table */ + if (iptype == IPA_IP_v4) + { + if (false == m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_eth_bridge_lan_lan_v4)) + { + IPACMERR("Failed to get routing table handle.\n"); + res = IPACM_FAILURE; + goto fail; + } + flt_rule.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_eth_bridge_lan_lan_v4.hdl; + IPACMDBG_H("LAN->LAN filter rule use table: %s\n", IPACM_Iface::ipacmcfg->rt_tbl_eth_bridge_lan_lan_v4.name); + } + else + { + if (false == m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_eth_bridge_lan_lan_v6)) + { + IPACMERR("Failed to get routing table handle.\n"); + res = IPACM_FAILURE; + goto fail; + } + flt_rule.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_eth_bridge_lan_lan_v6.hdl; + IPACMDBG_H("LAN->LAN filter rule use table: %s\n", IPACM_Iface::ipacmcfg->rt_tbl_eth_bridge_lan_lan_v6.name); + } + + memcpy(&flt_rule.rule.attrib, &rx_prop->rx[0].attrib, sizeof(flt_rule.rule.attrib)); + + if (IPACM_Lan::lan_hdr_type == IPA_HDR_L2_ETHERNET_II) + { + flt_rule.rule.attrib.attrib_mask |= IPA_FLT_MAC_DST_ADDR_ETHER_II; + } + else if (IPACM_Lan::lan_hdr_type == IPA_HDR_L2_802_3) + { + flt_rule.rule.attrib.attrib_mask |= IPA_FLT_MAC_DST_ADDR_802_3; + } + else + { + IPACMERR("LAN hdr type is not expected.\n"); + res = IPACM_FAILURE; + goto fail; + } + + memcpy(flt_rule.rule.attrib.dst_mac_addr, mac, sizeof(flt_rule.rule.attrib.dst_mac_addr)); + memset(flt_rule.rule.attrib.dst_mac_addr_mask, 0xFF, sizeof(flt_rule.rule.attrib.dst_mac_addr_mask)); + + if (iptype == IPA_IP_v4) + { + for (i=0; irules[0]), &flt_rule, sizeof(struct ipa_flt_rule_mdfy)); + + if (false == m_filtering.ModifyFilteringRule(pFilteringTable)) + { + IPACMERR("Failed to add wlan client filtering rules.\n"); + res = IPACM_FAILURE; + goto fail; + } + + if (client_is_found == false) + { + client_position = lan_client_flt_info_count; + lan_client_flt_info_count++; + } + + memcpy(eth_bridge_lan_client_flt_info[client_position].mac, mac, sizeof(eth_bridge_lan_client_flt_info[client_position].mac)); + + if (iptype == IPA_IP_v4) + { + eth_bridge_lan_client_flt_info[client_position].flt_rule_set_v4 = true; + eth_bridge_lan_client_flt_info[client_position].flt_rule_hdl_v4 = lan_client_flt_rule_hdl_v4[i].rule_hdl; + } + else + { + eth_bridge_lan_client_flt_info[client_position].flt_rule_set_v6 = true; + eth_bridge_lan_client_flt_info[client_position].flt_rule_hdl_v6 = lan_client_flt_rule_hdl_v6[i].rule_hdl; + } + +fail: + free(pFilteringTable); + + return res; +} + +int IPACM_Lan::eth_bridge_del_lan_client_flt_rule(uint8_t* mac) +{ + if (mac == NULL) + { + IPACMERR("Client MAC address is empty.\n"); + return IPACM_FAILURE; + } + + IPACMDBG_H("Received LAN client MAC 0x%02x%02x%02x%02x%02x%02x.\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + + int i, j, res = IPACM_SUCCESS; + for (i=0; iiface_table[ipa_if_num].if_cat == WLAN_IF) + { + if(IPACM_Lan::wlan_to_wlan_hdr_proc_ctx.valid == false) + { + memset(pHeaderProcTable, 0, len); + pHeaderProcTable->commit = 1; + pHeaderProcTable->num_proc_ctxs = 1; + pHeaderProcTable->proc_ctx[0].type = get_hdr_proc_type(IPACM_Lan::wlan_hdr_type, IPACM_Lan::wlan_hdr_type); + pHeaderProcTable->proc_ctx[0].hdr_hdl = IPACM_Lan::wlan_hdr_template_hdl; + if (m_header.AddHeaderProcCtx(pHeaderProcTable) == false) + { + IPACMERR("Adding WLAN to WLAN hdr proc ctx failed with status: %d\n", pHeaderProcTable->proc_ctx[0].status); + res = IPACM_FAILURE; + } + else + { + IPACM_Lan::wlan_to_wlan_hdr_proc_ctx.proc_ctx_hdl = pHeaderProcTable->proc_ctx[0].proc_ctx_hdl; + IPACM_Lan::wlan_to_wlan_hdr_proc_ctx.valid = true; + IPACMDBG_H("WLAN to WLAN hdr proc ctx is added successfully. \n"); + } + } + } + + if(IPACM_Lan::lan_hdr_type != IPA_HDR_L2_NONE) + { + if(IPACM_Lan::lan_to_wlan_hdr_proc_ctx.valid == false) + { + memset(pHeaderProcTable, 0, len); + pHeaderProcTable->commit = 1; + pHeaderProcTable->num_proc_ctxs = 1; + pHeaderProcTable->proc_ctx[0].type = get_hdr_proc_type(IPACM_Lan::lan_hdr_type, IPACM_Lan::wlan_hdr_type); + pHeaderProcTable->proc_ctx[0].hdr_hdl = IPACM_Lan::wlan_hdr_template_hdl; + if (m_header.AddHeaderProcCtx(pHeaderProcTable) == false) + { + IPACMERR("Adding LAN to WLAN hdr proc ctx failed with status: %d\n", pHeaderProcTable->proc_ctx[0].status); + res = IPACM_FAILURE; + goto fail; + } + else + { + IPACM_Lan::lan_to_wlan_hdr_proc_ctx.proc_ctx_hdl = pHeaderProcTable->proc_ctx[0].proc_ctx_hdl; + IPACM_Lan::lan_to_wlan_hdr_proc_ctx.valid = true; + IPACMDBG_H("LAN to WLAN hdr proc ctx is added successfully. \n"); + } + + ipacm_cmd_q_data evt_data; + memset(&evt_data, 0, sizeof(ipacm_cmd_q_data)); + + ipacm_event_data_if_cat* cat; + cat = (ipacm_event_data_if_cat*)malloc(sizeof(ipacm_event_data_if_cat)); + if(cat == NULL) + { + IPACMERR("Unable to allocate memory.\n"); + return IPACM_FAILURE; + } + memset(cat, 0, sizeof(ipacm_event_data_if_cat)); + cat->if_cat = IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat; + + evt_data.evt_data = cat; + evt_data.event = IPA_ETH_BRIDGE_HDR_PROC_CTX_SET_EVENT; + IPACMDBG_H("Posting event IPA_ETH_BRIDGE_HDR_PROC_CTX_SET_EVENT\n"); + IPACM_EvtDispatcher::PostEvt(&evt_data); + } + + if(IPACM_Lan::is_usb_up == true && IPACM_Lan::wlan_to_usb_hdr_proc_ctx.valid == false) + { + memset(pHeaderProcTable, 0, len); + pHeaderProcTable->commit = 1; + pHeaderProcTable->num_proc_ctxs = 1; + pHeaderProcTable->proc_ctx[0].type = get_hdr_proc_type(IPACM_Lan::wlan_hdr_type, IPACM_Lan::lan_hdr_type); + pHeaderProcTable->proc_ctx[0].hdr_hdl = IPACM_Lan::usb_hdr_template_hdl; + if (m_header.AddHeaderProcCtx(pHeaderProcTable) == false) + { + IPACMERR("Adding WLAN to USB hdr proc ctx failed with status: %d\n", pHeaderProcTable->proc_ctx[0].status); + res = IPACM_FAILURE; + goto fail; + } + else + { + IPACM_Lan::wlan_to_usb_hdr_proc_ctx.proc_ctx_hdl = pHeaderProcTable->proc_ctx[0].proc_ctx_hdl; + IPACM_Lan::wlan_to_usb_hdr_proc_ctx.valid = true; + IPACMDBG_H("WLAN to USB hdr proc ctx is added successfully. \n"); + } + } + + if(IPACM_Lan::is_cpe_up == true && IPACM_Lan::wlan_to_cpe_hdr_proc_ctx.valid == false) + { + memset(pHeaderProcTable, 0, len); + pHeaderProcTable->commit = 1; + pHeaderProcTable->num_proc_ctxs = 1; + pHeaderProcTable->proc_ctx[0].type = get_hdr_proc_type(IPACM_Lan::wlan_hdr_type, IPACM_Lan::lan_hdr_type); + pHeaderProcTable->proc_ctx[0].hdr_hdl = IPACM_Lan::cpe_hdr_template_hdl; + if (m_header.AddHeaderProcCtx(pHeaderProcTable) == false) + { + IPACMERR("Adding WLAN to CPE hdr proc ctx failed with status: %d\n", pHeaderProcTable->proc_ctx[0].status); + res = IPACM_FAILURE; + goto fail; + } + else + { + IPACM_Lan::wlan_to_cpe_hdr_proc_ctx.proc_ctx_hdl = pHeaderProcTable->proc_ctx[0].proc_ctx_hdl; + IPACM_Lan::wlan_to_cpe_hdr_proc_ctx.valid = true; + IPACMDBG_H("WLAN to CPE hdr proc ctx is added successfully. \n"); + + } + } + } + } + + if(IPACM_Lan::lan_hdr_type != IPA_HDR_L2_NONE) + { + if(IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat == LAN_IF || + (IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat == ODU_IF)) + { + if(IPACM_Iface::ipacmcfg->ipacm_odu_router_mode == false) + { + IPACMDBG_H("ODU is in bridge mode, do not set CPE to USB and USB to CPE hdr proc ctx.\n"); + return res; + } + if(IPACM_Lan::is_cpe_up == true && IPACM_Lan::is_usb_up == true && + IPACM_Lan::cpe_to_usb_hdr_proc_ctx.valid == false && IPACM_Lan::usb_to_cpe_hdr_proc_ctx.valid == false) + { + memset(pHeaderProcTable, 0, len); + pHeaderProcTable->commit = 1; + pHeaderProcTable->num_proc_ctxs = 1; + pHeaderProcTable->proc_ctx[0].type = get_hdr_proc_type(IPACM_Lan::lan_hdr_type, IPACM_Lan::lan_hdr_type); + pHeaderProcTable->proc_ctx[0].hdr_hdl = IPACM_Lan::usb_hdr_template_hdl; + if (m_header.AddHeaderProcCtx(pHeaderProcTable) == false) + { + IPACMERR("Adding CPE to USB hdr proc ctx failed with status: %d\n", pHeaderProcTable->proc_ctx[0].status); + res = IPACM_FAILURE; + goto fail; + } + else + { + IPACM_Lan::cpe_to_usb_hdr_proc_ctx.proc_ctx_hdl = pHeaderProcTable->proc_ctx[0].proc_ctx_hdl; + IPACM_Lan::cpe_to_usb_hdr_proc_ctx.valid = true; + IPACMDBG_H("CPE to USB hdr proc ctx is added successfully. \n"); + } + + pHeaderProcTable->commit = 1; + pHeaderProcTable->num_proc_ctxs = 1; + pHeaderProcTable->proc_ctx[0].type = get_hdr_proc_type(IPACM_Lan::lan_hdr_type, IPACM_Lan::lan_hdr_type); + pHeaderProcTable->proc_ctx[0].hdr_hdl = IPACM_Lan::cpe_hdr_template_hdl; + if (m_header.AddHeaderProcCtx(pHeaderProcTable) == false) + { + IPACMERR("Adding USB to CPE hdr proc ctx failed with status: %d\n", pHeaderProcTable->proc_ctx[0].status); + res = IPACM_FAILURE; + goto fail; + } + else + { + IPACM_Lan::usb_to_cpe_hdr_proc_ctx.proc_ctx_hdl = pHeaderProcTable->proc_ctx[0].proc_ctx_hdl; + IPACM_Lan::usb_to_cpe_hdr_proc_ctx.valid = true; + IPACMDBG_H("USB to CPE hdr proc ctx is added successfully. \n"); + } + + ipacm_cmd_q_data evt_data; + memset(&evt_data, 0, sizeof(ipacm_cmd_q_data)); + + ipacm_event_data_if_cat* cat; + cat = (ipacm_event_data_if_cat*)malloc(sizeof(ipacm_event_data_if_cat)); + if(cat == NULL) + { + IPACMERR("Unable to allocate memory.\n"); + return IPACM_FAILURE; + } + memset(cat, 0, sizeof(ipacm_event_data_if_cat)); + cat->if_cat = IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat; + + evt_data.evt_data = cat; + evt_data.event = IPA_ETH_BRIDGE_HDR_PROC_CTX_SET_EVENT; + IPACMDBG_H("Posting event IPA_ETH_BRIDGE_HDR_PROC_CTX_SET_EVENT\n"); + IPACM_EvtDispatcher::PostEvt(&evt_data); + } + } + } + else + { + IPACMDBG_H("Not adding header processing context.\n"); + } + +fail: + free(pHeaderProcTable); + return res; +} + +ipa_hdr_proc_type IPACM_Lan::get_hdr_proc_type(ipa_hdr_l2_type t1, ipa_hdr_l2_type t2) +{ + if(t1 == IPA_HDR_L2_ETHERNET_II) + { + if(t2 == IPA_HDR_L2_ETHERNET_II) + { + return IPA_HDR_PROC_ETHII_TO_ETHII; + } + if(t2 == IPA_HDR_L2_802_3) + { + return IPA_HDR_PROC_ETHII_TO_802_3; + } + } + + if(t1 == IPA_HDR_L2_802_3) + { + if(t2 == IPA_HDR_L2_ETHERNET_II) + { + return IPA_HDR_PROC_802_3_TO_ETHII; + } + if(t2 == IPA_HDR_L2_802_3) + { + return IPA_HDR_PROC_802_3_TO_802_3; + } + } + + return IPA_HDR_PROC_NONE; +} + +int IPACM_Lan::eth_bridge_install_cache_wlan_client_flt_rule(ipa_ip_type iptype) +{ + int i; + + IPACMDBG_H("There are %d wlan clients cached.\n",IPACM_Lan::num_wlan_client); + for(i=0; iiface_table[ipa_if_num].if_cat ); + + if (src == SRC_WLAN && IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat == LAN_IF + && IPACM_Lan::wlan_to_usb_hdr_proc_ctx.valid == false) + { + IPACMDBG_H("WLAN to USB hdr proc ctx has not been set, don't add USB routing rule.\n"); + return IPACM_FAILURE; + } + if (src == SRC_WLAN && IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat == ODU_IF + && IPACM_Lan::wlan_to_cpe_hdr_proc_ctx.valid == false) + { + IPACMDBG_H("WLAN to CPE hdr proc ctx has not been set, don't add CPE routing rule.\n"); + return IPACM_FAILURE; + } + + if (src == SRC_LAN && IPACM_Lan::usb_to_cpe_hdr_proc_ctx.valid == false + && IPACM_Lan::cpe_to_usb_hdr_proc_ctx.valid == false) + { + IPACMDBG_H("hdr proc ctx between USB and CPE has not been set, don't add routing rule.\n"); + return IPACM_FAILURE; + } + + if(iptype == IPA_IP_v4) + { + if((src == SRC_LAN && lan_client_rt_from_lan_info_count_v4 == IPA_LAN_TO_LAN_MAX_LAN_CLIENT) + || (src == SRC_WLAN && lan_client_rt_from_wlan_info_count_v4 == IPA_LAN_TO_LAN_MAX_WLAN_CLIENT)) + { + IPACMDBG_H("client number has reached maximum.\n"); + return IPACM_FAILURE; + } + } + else + { + if ((src == SRC_LAN && lan_client_rt_from_lan_info_count_v6 == IPA_LAN_TO_LAN_MAX_LAN_CLIENT) + || (src == SRC_WLAN && lan_client_rt_from_wlan_info_count_v6 == IPA_LAN_TO_LAN_MAX_WLAN_CLIENT)) + { + IPACMDBG_H("client number has reached maximum.\n"); + return IPACM_FAILURE; + } + } + + int i, len, res = IPACM_SUCCESS; + struct ipa_ioc_add_rt_rule* rt_rule_table = NULL; + struct ipa_rt_rule_add rt_rule; + int position, num_rt_rule; + + if (src == SRC_LAN) + { + if (iptype == IPA_IP_v4) + { + for (i=0; imac, mac, sizeof(eth_bridge_get_client_rt_info_ptr(i, src, iptype)->mac)) == 0) + { + IPACMDBG_H("The client's routing rule was added before.\n"); + return IPACM_SUCCESS; + } + } + memcpy(eth_bridge_get_client_rt_info_ptr(lan_client_rt_from_lan_info_count_v4, src, iptype)->mac, mac, + sizeof(eth_bridge_get_client_rt_info_ptr(lan_client_rt_from_lan_info_count_v4, src, iptype)->mac)); + } + else + { + for (i=0; imac, mac, sizeof(eth_bridge_get_client_rt_info_ptr(i, src, iptype)->mac)) == 0) + { + IPACMDBG_H("The client's routing rule was added before.\n"); + return IPACM_SUCCESS; + } + } + memcpy(eth_bridge_get_client_rt_info_ptr(lan_client_rt_from_lan_info_count_v6, src, iptype)->mac, mac, + sizeof(eth_bridge_get_client_rt_info_ptr(lan_client_rt_from_lan_info_count_v6, src, iptype)->mac)); + } + } + else + { + if (iptype == IPA_IP_v4) + { + for (i=0; imac, mac, sizeof(eth_bridge_get_client_rt_info_ptr(i, src, iptype)->mac)) == 0) + { + IPACMDBG_H("The client's routing rule was added before.\n"); + return IPACM_SUCCESS; + } + } + memcpy(eth_bridge_get_client_rt_info_ptr(lan_client_rt_from_wlan_info_count_v4, src, iptype)->mac, mac, + sizeof(eth_bridge_get_client_rt_info_ptr(lan_client_rt_from_wlan_info_count_v4, src, iptype)->mac)); + } + else + { + for (i=0; imac, mac, sizeof(eth_bridge_get_client_rt_info_ptr(i, src, iptype)->mac)) == 0) + { + IPACMDBG_H("The client's routing rule was added before.\n"); + return IPACM_SUCCESS; + } + } + memcpy(eth_bridge_get_client_rt_info_ptr(lan_client_rt_from_wlan_info_count_v6, src, iptype)->mac, mac, + sizeof(eth_bridge_get_client_rt_info_ptr(lan_client_rt_from_wlan_info_count_v6, src, iptype)->mac)); + } + } + + if (iptype == IPA_IP_v4) + { + num_rt_rule = each_client_rt_rule_count_v4; + } + else + { + num_rt_rule = each_client_rt_rule_count_v6; + } + + len = sizeof(ipa_ioc_add_rt_rule) + num_rt_rule * sizeof(ipa_rt_rule_add); + rt_rule_table = (ipa_ioc_add_rt_rule*)malloc(len); + if (rt_rule_table == NULL) + { + IPACMERR("Failed to allocate memory.\n"); + return IPACM_FAILURE; + } + memset(rt_rule_table, 0, len); + + rt_rule_table->commit = 1; + rt_rule_table->ip = iptype; + rt_rule_table->num_rules = num_rt_rule; + if (src == SRC_LAN) + { + if (iptype == IPA_IP_v4) + { + strlcpy(rt_rule_table->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_eth_bridge_lan_lan_v4.name, sizeof(rt_rule_table->rt_tbl_name)); + } + else + { + strlcpy(rt_rule_table->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_eth_bridge_lan_lan_v6.name, sizeof(rt_rule_table->rt_tbl_name)); + } + } + else + { + if (iptype == IPA_IP_v4) + { + strlcpy(rt_rule_table->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_eth_bridge_lan_wlan_v4.name, sizeof(rt_rule_table->rt_tbl_name)); + } + else + { + strlcpy(rt_rule_table->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_eth_bridge_lan_wlan_v6.name, sizeof(rt_rule_table->rt_tbl_name)); + } + } + rt_rule_table->rt_tbl_name[IPA_RESOURCE_NAME_MAX-1] = '\0'; + memset(&rt_rule, 0, sizeof(ipa_rt_rule_add)); + rt_rule.at_rear = false; + rt_rule.status = -1; + rt_rule.rt_rule_hdl = -1; + + rt_rule.rule.hdr_hdl = 0; + if(src == SRC_LAN) + { + if (IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat == LAN_IF) + { + rt_rule.rule.hdr_proc_ctx_hdl = IPACM_Lan::cpe_to_usb_hdr_proc_ctx.proc_ctx_hdl; + } + else if (IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat == ODU_IF) + { + rt_rule.rule.hdr_proc_ctx_hdl = IPACM_Lan::usb_to_cpe_hdr_proc_ctx.proc_ctx_hdl; + } + else + { + IPACMERR("Iface category is not expected.\n"); + res = IPACM_FAILURE; + goto fail; + } + } + else + { + if(IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat == LAN_IF) + { + rt_rule.rule.hdr_proc_ctx_hdl = IPACM_Lan::wlan_to_usb_hdr_proc_ctx.proc_ctx_hdl; + } + else if(IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat == ODU_IF) + { + rt_rule.rule.hdr_proc_ctx_hdl = IPACM_Lan::wlan_to_cpe_hdr_proc_ctx.proc_ctx_hdl; + } + else + { + IPACMERR("Iface category is not expected.\n"); + res = IPACM_FAILURE; + goto fail; + } + } + position = 0; + for(i=0; inum_tx_props; i++) + { + if(tx_prop->tx[i].ip == iptype) + { + if(position >= num_rt_rule) + { + IPACMERR("Number of routing rules already exceeds limit.\n"); + res = IPACM_FAILURE; + goto fail; + } + rt_rule.rule.dst = tx_prop->tx[i].dst_pipe; + + memcpy(&rt_rule.rule.attrib, &tx_prop->tx[i].attrib, sizeof(rt_rule.rule.attrib)); + if(src == SRC_WLAN) //src is WLAN means packet is from WLAN + { + if(IPACM_Lan::wlan_hdr_type == IPA_HDR_L2_ETHERNET_II) + { + rt_rule.rule.attrib.attrib_mask |= IPA_FLT_MAC_DST_ADDR_ETHER_II; + } + else + { + rt_rule.rule.attrib.attrib_mask |= IPA_FLT_MAC_DST_ADDR_802_3; + } + } + else //packet is from LAN + { + if(IPACM_Lan::lan_hdr_type == IPA_HDR_L2_ETHERNET_II) + { + rt_rule.rule.attrib.attrib_mask |= IPA_FLT_MAC_DST_ADDR_ETHER_II; + } + else + { + rt_rule.rule.attrib.attrib_mask |= IPA_FLT_MAC_DST_ADDR_802_3; + } + } + memcpy(rt_rule.rule.attrib.dst_mac_addr, mac, sizeof(rt_rule.rule.attrib.dst_mac_addr)); + memset(rt_rule.rule.attrib.dst_mac_addr_mask, 0xFF, sizeof(rt_rule.rule.attrib.dst_mac_addr_mask)); + + memcpy(&(rt_rule_table->rules[position]), &rt_rule, sizeof(rt_rule_table->rules[position])); + position++; + } + } + if(false == m_routing.AddRoutingRule(rt_rule_table)) + { + IPACMERR("Routing rule addition failed!\n"); + res = IPACM_FAILURE; + goto fail; + } + else + { + if(src == SRC_LAN) + { + for(i=0; irt_rule_hdl[i] = rt_rule_table->rules[i].rt_rule_hdl; + } + else + { + eth_bridge_get_client_rt_info_ptr(lan_client_rt_from_lan_info_count_v6, src, iptype)->rt_rule_hdl[i] = rt_rule_table->rules[i].rt_rule_hdl; + } + } + if(iptype == IPA_IP_v4) + { + lan_client_rt_from_lan_info_count_v4++; + IPACMDBG_H("Now the number of IPv4 rt rule on lan-lan rt table is %d.\n", lan_client_rt_from_lan_info_count_v4); + } + else + { + lan_client_rt_from_lan_info_count_v6++; + IPACMDBG_H("Now the number of IPv6 rt rule on lan-lan rt table is %d.\n", lan_client_rt_from_lan_info_count_v6); + } + } + else + { + for(i=0; irt_rule_hdl[i] = rt_rule_table->rules[i].rt_rule_hdl; + } + else + { + eth_bridge_get_client_rt_info_ptr(lan_client_rt_from_wlan_info_count_v6, src, iptype)->rt_rule_hdl[i] = rt_rule_table->rules[i].rt_rule_hdl; + } + } + if(iptype == IPA_IP_v4) + { + lan_client_rt_from_wlan_info_count_v4++; + IPACMDBG_H("Now the number of IPv4 rt rule on lan-wlan rt table is %d.\n", lan_client_rt_from_wlan_info_count_v4); + } + else + { + lan_client_rt_from_wlan_info_count_v6++; + IPACMDBG_H("Now the number of IPv6 rt rule on lan-wlan rt table is %d.\n", lan_client_rt_from_wlan_info_count_v6); + } + } + } + +fail: + if(rt_rule_table != NULL) + { + free(rt_rule_table); + } + return res; +} + +int IPACM_Lan::eth_bridge_del_lan_client_rt_rule(uint8_t* mac, eth_bridge_src_iface src) +{ + if(tx_prop == NULL) + { + IPACMDBG_H("Tx prop is empty, not deleting routing rule.\n"); + return IPACM_SUCCESS; + } + if(mac == NULL) + { + IPACMERR("Client MAC address is empty.\n"); + return IPACM_FAILURE; + } + + IPACMDBG_H("Received client MAC 0x%02x%02x%02x%02x%02x%02x. src_iface: %d \n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], src); + + int i, position; + + /* first delete the rt rules from IPv4 rt table*/ + if(src == SRC_LAN) + { + for(i=0; imac, mac, sizeof(eth_bridge_get_client_rt_info_ptr(i, src, IPA_IP_v4)->mac)) == 0) + { + position = i; + IPACMDBG_H("The client is found at position %d.\n", position); + break; + } + } + if(i == lan_client_rt_from_lan_info_count_v4) + { + IPACMERR("The client is not found.\n"); + return IPACM_FAILURE; + } + } + else + { + for(i=0; imac, mac, sizeof(eth_bridge_get_client_rt_info_ptr(i, src, IPA_IP_v4)->mac)) == 0) + { + position = i; + IPACMDBG_H("The client is found at position %d.\n", position); + break; + } + } + if(i == lan_client_rt_from_wlan_info_count_v4) + { + IPACMERR("The client is not found.\n"); + return IPACM_FAILURE; + } + } + + for(i=0; irt_rule_hdl[i], IPA_IP_v4) == false) + { + IPACMERR("Failed to delete routing rule %d.\n", i); + return IPACM_FAILURE; + } + } + + if(src == SRC_LAN) + { + for(i=position+1; imac, mac, sizeof(eth_bridge_get_client_rt_info_ptr(i, src, IPA_IP_v6)->mac)) == 0) + { + position = i; + IPACMDBG_H("The client is found at position %d.\n", position); + break; + } + } + if(i == lan_client_rt_from_lan_info_count_v6) + { + IPACMERR("The client is not found.\n"); + return IPACM_FAILURE; + } + } + else + { + for(i=0; imac, mac, sizeof(eth_bridge_get_client_rt_info_ptr(i, src, IPA_IP_v6)->mac)) == 0) + { + position = i; + IPACMDBG_H("The client is found at position %d.\n", position); + break; + } + } + if(i == lan_client_rt_from_wlan_info_count_v6) + { + IPACMERR("The client is not found.\n"); + return IPACM_FAILURE; + } + } + + for(i=0; irt_rule_hdl[i], IPA_IP_v6) == false) + { + IPACMERR("Failed to delete routing rule %d.\n", i); + return IPACM_FAILURE; + } + } + + if(src == SRC_LAN) + { + for(i=position+1; itx[0].hdr_name, sizeof(hdr.name)); + if(m_header.GetHeaderHandle(&hdr) == false) + { + IPACMERR("Failed to get template hdr hdl.\n"); + return IPACM_FAILURE; + } + + *hdr_hdl = hdr.hdl; + return IPACM_SUCCESS; +} + +int IPACM_Lan::del_hdr_proc_ctx() +{ + if(IPACM_Lan::lan_to_wlan_hdr_proc_ctx.valid == true) + { + if((IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat == WLAN_IF) + || (IPACM_Lan::is_usb_up == false && IPACM_Lan::is_cpe_up == false)) + { + if(m_header.DeleteHeaderProcCtx(IPACM_Lan::lan_to_wlan_hdr_proc_ctx.proc_ctx_hdl) == false) + { + IPACMERR("Failed to delete usb to wlan hdr proc ctx.\n"); + return IPACM_FAILURE; + } + IPACM_Lan::lan_to_wlan_hdr_proc_ctx.valid = false; + + ipacm_cmd_q_data evt_data; + memset(&evt_data, 0, sizeof(ipacm_cmd_q_data)); + + ipacm_event_data_if_cat* cat; + cat = (ipacm_event_data_if_cat*)malloc(sizeof(ipacm_event_data_if_cat)); + if(cat == NULL) + { + IPACMERR("Unable to allocate memory.\n"); + return IPACM_FAILURE; + } + memset(cat, 0, sizeof(ipacm_event_data_if_cat)); + cat->if_cat = IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat; + + evt_data.evt_data = cat; + evt_data.event = IPA_ETH_BRIDGE_HDR_PROC_CTX_UNSET_EVENT; + IPACMDBG_H("Posting event IPA_ETH_BRIDGE_HDR_PROC_CTX_UNSET_EVENT\n"); + IPACM_EvtDispatcher::PostEvt(&evt_data); + } + } + + if(IPACM_Lan::wlan_to_usb_hdr_proc_ctx.valid == true) + { + if(IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat == WLAN_IF || IPACM_Lan::is_usb_up == false) + { + if(m_header.DeleteHeaderProcCtx(IPACM_Lan::wlan_to_usb_hdr_proc_ctx.proc_ctx_hdl) == false) + { + IPACMERR("Failed to delete wlan to usb hdr proc ctx.\n"); + return IPACM_FAILURE; + } + IPACM_Lan::wlan_to_usb_hdr_proc_ctx.valid = false; + } + } + + if(IPACM_Lan::wlan_to_cpe_hdr_proc_ctx.valid == true) + { + if(IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat == WLAN_IF || IPACM_Lan::is_cpe_up == false) + { + if(m_header.DeleteHeaderProcCtx(IPACM_Lan::wlan_to_cpe_hdr_proc_ctx.proc_ctx_hdl) == false) + { + IPACMERR("Failed to delete wlan to cpe hdr proc ctx.\n"); + return IPACM_FAILURE; + } + IPACM_Lan::wlan_to_cpe_hdr_proc_ctx.valid = false; + } + } + + if(IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat == WLAN_IF) + { + if(IPACM_Lan::wlan_to_wlan_hdr_proc_ctx.valid == true) + { + if(m_header.DeleteHeaderProcCtx(IPACM_Lan::wlan_to_wlan_hdr_proc_ctx.proc_ctx_hdl) == false) + { + IPACMERR("Failed to delete wlan to wlan hdr proc ctx.\n"); + return IPACM_FAILURE; + } + IPACM_Lan::wlan_to_wlan_hdr_proc_ctx.valid = false; + } + } + + if(IPACM_Lan::cpe_to_usb_hdr_proc_ctx.valid == true && IPACM_Lan::usb_to_cpe_hdr_proc_ctx.valid == true) + { + if((IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat == LAN_IF) + || (IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat == ODU_IF)) + { + if(m_header.DeleteHeaderProcCtx(IPACM_Lan::cpe_to_usb_hdr_proc_ctx.proc_ctx_hdl) == false) + { + IPACMERR("Failed to delete cpe to usb hdr proc ctx.\n"); + return IPACM_FAILURE; + } + IPACM_Lan::cpe_to_usb_hdr_proc_ctx.valid = false; + + if(m_header.DeleteHeaderProcCtx(IPACM_Lan::usb_to_cpe_hdr_proc_ctx.proc_ctx_hdl) == false) + { + IPACMERR("Failed to delete usb to cpe hdr proc ctx.\n"); + return IPACM_FAILURE; + } + IPACM_Lan::usb_to_cpe_hdr_proc_ctx.valid = false; + + ipacm_cmd_q_data evt_data; + memset(&evt_data, 0, sizeof(ipacm_cmd_q_data)); + + ipacm_event_data_if_cat* cat; + cat = (ipacm_event_data_if_cat*)malloc(sizeof(ipacm_event_data_if_cat)); + if(cat == NULL) + { + IPACMERR("Unable to allocate memory.\n"); + return IPACM_FAILURE; + } + memset(cat, 0, sizeof(ipacm_event_data_if_cat)); + cat->if_cat = IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat; + + evt_data.evt_data = cat; + evt_data.event = IPA_ETH_BRIDGE_HDR_PROC_CTX_UNSET_EVENT; + IPACMDBG_H("Posting event IPA_ETH_BRIDGE_HDR_PROC_CTX_UNSET_EVENT\n"); + IPACM_EvtDispatcher::PostEvt(&evt_data); + } + } + return IPACM_SUCCESS; +} + +int IPACM_Lan::handle_cradle_wan_mode_switch(bool is_wan_bridge_mode) +{ + struct ipa_flt_rule_mdfy flt_rule_entry; + int len = 0; + ipa_ioc_mdfy_flt_rule *m_pFilteringTable; + + IPACMDBG_H("Handle wan mode swtich: is wan bridge mode?%d\n", is_wan_bridge_mode); + + if (rx_prop == NULL) + { + IPACMDBG_H("No rx properties registered for iface %s\n", dev_name); + return IPACM_SUCCESS; + } + + len = sizeof(struct ipa_ioc_mdfy_flt_rule) + (1 * sizeof(struct ipa_flt_rule_mdfy)); + m_pFilteringTable = (struct ipa_ioc_mdfy_flt_rule *)calloc(1, len); + if (m_pFilteringTable == NULL) + { + PERROR("Error Locate ipa_ioc_mdfy_flt_rule memory...\n"); + return IPACM_FAILURE; + } + + m_pFilteringTable->commit = 1; + m_pFilteringTable->ip = IPA_IP_v4; + m_pFilteringTable->num_rules = (uint8_t)1; + + IPACMDBG_H("Retrieving routing hanle for table: %s\n", + IPACM_Iface::ipacmcfg->rt_tbl_wan_v4.name); + if (false == m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_wan_v4)) + { + IPACMERR("m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_wan_v4=0x%p) Failed.\n", + &IPACM_Iface::ipacmcfg->rt_tbl_wan_v4); + free(m_pFilteringTable); + return IPACM_FAILURE; + } + IPACMDBG_H("Routing handle for table: %d\n", IPACM_Iface::ipacmcfg->rt_tbl_wan_v4.hdl); + + + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_mdfy)); // Zero All Fields + flt_rule_entry.status = -1; + flt_rule_entry.rule_hdl = lan_wan_fl_rule_hdl[0]; + + flt_rule_entry.rule.retain_hdr = 0; + flt_rule_entry.rule.to_uc = 0; + flt_rule_entry.rule.eq_attrib_type = 0; + if(is_wan_bridge_mode) + { + flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING; + } + else + { + flt_rule_entry.rule.action = IPA_PASS_TO_SRC_NAT; + } + flt_rule_entry.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_wan_v4.hdl; + + memcpy(&flt_rule_entry.rule.attrib, + &rx_prop->rx[0].attrib, + sizeof(flt_rule_entry.rule.attrib)); + + flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; + flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0x0; + flt_rule_entry.rule.attrib.u.v4.dst_addr = 0x0; + + memcpy(&m_pFilteringTable->rules[0], &flt_rule_entry, sizeof(flt_rule_entry)); + if (false == m_filtering.ModifyFilteringRule(m_pFilteringTable)) + { + IPACMERR("Error Modifying RuleTable(0) to Filtering, aborting...\n"); + free(m_pFilteringTable); + return IPACM_FAILURE; + } + else + { + IPACMDBG_H("flt rule hdl = %d, status = %d\n", + m_pFilteringTable->rules[0].rule_hdl, + m_pFilteringTable->rules[0].status); + } + free(m_pFilteringTable); + return IPACM_SUCCESS; +} + +/*handle reset usb-client rt-rules */ +int IPACM_Lan::handle_tethering_stats_event(ipa_get_data_stats_resp_msg_v01 *data) +{ + int cnt, pipe_len, fd; + uint64_t num_ul_packets, num_ul_bytes; + uint64_t num_dl_packets, num_dl_bytes; + bool ul_pipe_found, dl_pipe_found; + FILE *fp = NULL; + + fd = open(IPA_DEVICE_NAME, O_RDWR); + if (fd < 0) + { + IPACMERR("Failed opening %s.\n", IPA_DEVICE_NAME); + return IPACM_FAILURE; + } + + + ul_pipe_found = false; + dl_pipe_found = false; + num_ul_packets = 0; + num_dl_packets = 0; + num_ul_bytes = 0; + num_dl_bytes = 0; + + if (data->dl_dst_pipe_stats_list_valid) + { + if(tx_prop != NULL) + { + for (pipe_len = 0; pipe_len < data->dl_dst_pipe_stats_list_len; pipe_len++) + { + IPACMDBG_H("Check entry(%d) dl_dst_pipe(%d)\n", pipe_len, data->dl_dst_pipe_stats_list[pipe_len].pipe_index); + for (cnt=0; cntnum_tx_props; cnt++) + { + IPACMDBG_H("Check Tx_prop_entry(%d) pipe(%d)\n", cnt, ioctl(fd, IPA_IOC_QUERY_EP_MAPPING, tx_prop->tx[cnt].dst_pipe)); + if(ioctl(fd, IPA_IOC_QUERY_EP_MAPPING, tx_prop->tx[cnt].dst_pipe) == data->dl_dst_pipe_stats_list[pipe_len].pipe_index) + { + /* update the DL stats */ + dl_pipe_found = true; + num_dl_packets += data->dl_dst_pipe_stats_list[pipe_len].num_ipv4_packets; + num_dl_packets += data->dl_dst_pipe_stats_list[pipe_len].num_ipv6_packets; + num_dl_bytes += data->dl_dst_pipe_stats_list[pipe_len].num_ipv4_bytes; + num_dl_bytes += data->dl_dst_pipe_stats_list[pipe_len].num_ipv6_bytes; + IPACMDBG_H("Got matched dst-pipe (%d) from %d tx props\n", data->dl_dst_pipe_stats_list[pipe_len].pipe_index, cnt); + IPACMDBG_H("DL_packets:(%lu) DL_bytes:(%lu) \n", num_dl_packets, num_dl_bytes); + break; + } + } + } + } + } + + if (data->ul_src_pipe_stats_list_valid) + { + if(rx_prop != NULL) + { + for (pipe_len = 0; pipe_len < data->ul_src_pipe_stats_list_len; pipe_len++) + { + IPACMDBG_H("Check entry(%d) dl_dst_pipe(%d)\n", pipe_len, data->ul_src_pipe_stats_list[pipe_len].pipe_index); + for (cnt=0; cnt < rx_prop->num_rx_props; cnt++) + { + IPACMDBG_H("Check Rx_prop_entry(%d) pipe(%d)\n", cnt, ioctl(fd, IPA_IOC_QUERY_EP_MAPPING, rx_prop->rx[cnt].src_pipe)); + if(ioctl(fd, IPA_IOC_QUERY_EP_MAPPING, rx_prop->rx[cnt].src_pipe) == data->ul_src_pipe_stats_list[pipe_len].pipe_index) + { + /* update the UL stats */ + ul_pipe_found = true; + num_ul_packets += data->ul_src_pipe_stats_list[pipe_len].num_ipv4_packets; + num_ul_packets += data->ul_src_pipe_stats_list[pipe_len].num_ipv6_packets; + num_ul_bytes += data->ul_src_pipe_stats_list[pipe_len].num_ipv4_bytes; + num_ul_bytes += data->ul_src_pipe_stats_list[pipe_len].num_ipv6_bytes; + IPACMDBG_H("Got matched dst-pipe (%d) from %d tx props\n", data->ul_src_pipe_stats_list[pipe_len].pipe_index, cnt); + IPACMDBG_H("UL_packets:(%lu) UL_bytes:(%lu) \n", num_ul_packets, num_ul_bytes); + break; + } + } + } + } + } + close(fd); + + if (ul_pipe_found || dl_pipe_found) + { + IPACMDBG_H("Update IPA_TETHERING_STATS_UPDATE_EVENT, TX(P%lu/B%lu) RX(P%lu/B%lu) DEV(%s) to LTE(%s) \n", + num_ul_packets, + num_ul_bytes, + num_dl_packets, + num_dl_bytes, + dev_name, + IPACM_Wan::wan_up_dev_name); + fp = fopen(IPA_PIPE_STATS_FILE_NAME, "w"); + if ( fp == NULL ) + { + IPACMERR("Failed to write pipe stats to %s, error is %d - %s\n", + IPA_PIPE_STATS_FILE_NAME, errno, strerror(errno)); + return IPACM_FAILURE; + } + + fprintf(fp, PIPE_STATS, + dev_name, + IPACM_Wan::wan_up_dev_name, + num_ul_bytes, + num_ul_packets, + num_dl_bytes, + num_dl_packets); + fclose(fp); + } + return IPACM_SUCCESS; +} + +/*handle tether client */ +int IPACM_Lan::handle_tethering_client(bool reset, ipacm_client_enum ipa_client) +{ + int cnt, fd, ret = IPACM_SUCCESS; + int fd_wwan_ioctl = open(WWAN_QMI_IOCTL_DEVICE_NAME, O_RDWR); + wan_ioctl_set_tether_client_pipe tether_client; + + if(fd_wwan_ioctl < 0) + { + IPACMERR("Failed to open %s.\n",WWAN_QMI_IOCTL_DEVICE_NAME); + return IPACM_FAILURE; + } + + fd = open(IPA_DEVICE_NAME, O_RDWR); + if (fd < 0) + { + IPACMERR("Failed opening %s.\n", IPA_DEVICE_NAME); + close(fd_wwan_ioctl); + return IPACM_FAILURE; + } + + memset(&tether_client, 0, sizeof(tether_client)); + tether_client.reset_client = reset; + tether_client.ipa_client = ipa_client; + + if(tx_prop != NULL) + { + tether_client.dl_dst_pipe_len = tx_prop->num_tx_props; + for (cnt = 0; cnt < tx_prop->num_tx_props; cnt++) + { + IPACMDBG_H("Tx(%d), dst_pipe: %d, ipa_pipe: %d\n", + cnt, tx_prop->tx[cnt].dst_pipe, + ioctl(fd, IPA_IOC_QUERY_EP_MAPPING, tx_prop->tx[cnt].dst_pipe)); + tether_client.dl_dst_pipe_list[cnt] = ioctl(fd, IPA_IOC_QUERY_EP_MAPPING, tx_prop->tx[cnt].dst_pipe); + } + } + + if(rx_prop != NULL) + { + tether_client.ul_src_pipe_len = rx_prop->num_rx_props; + for (cnt = 0; cnt < rx_prop->num_rx_props; cnt++) + { + IPACMDBG_H("Rx(%d), src_pipe: %d, ipa_pipe: %d\n", + cnt, rx_prop->rx[cnt].src_pipe, + ioctl(fd, IPA_IOC_QUERY_EP_MAPPING, rx_prop->rx[cnt].src_pipe)); + tether_client.ul_src_pipe_list[cnt] = ioctl(fd, IPA_IOC_QUERY_EP_MAPPING, rx_prop->rx[cnt].src_pipe); + } + } + + ret = ioctl(fd_wwan_ioctl, WAN_IOC_SET_TETHER_CLIENT_PIPE, &tether_client); + if (ret != 0) + { + IPACMERR("Failed set tether-client-pipe %p with ret %d\n ", &tether_client, ret); + } + IPACMDBG("Set tether-client-pipe %p\n", &tether_client); + close(fd); + close(fd_wwan_ioctl); + return ret; +} diff --git a/data-ipa-cfg-mgr/ipacm/src/IPACM_LanToLan.cpp b/data-ipa-cfg-mgr/ipacm/src/IPACM_LanToLan.cpp new file mode 100644 index 000000000..0abfc422f --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/src/IPACM_LanToLan.cpp @@ -0,0 +1,1605 @@ +/* +Copyright (c) 2014, The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +/*! + @file + IPACM_LanToLan.cpp + + @brief + This file implements the functionality of offloading LAN to LAN traffic. + + @Author + Shihuan Liu + +*/ + +#include +#include +#include "IPACM_LanToLan.h" +#include "IPACM_Wlan.h" + +#define ipv6_multicast_addr 0xff000000 +#define ipv6_multicast_mask 0xff000000 + +#define max_cache_connection 20 + +IPACM_LanToLan* IPACM_LanToLan::p_instance = NULL; + +IPACM_LanToLan::IPACM_LanToLan() +{ + num_offload_pair_v4_ = 0; + num_offload_pair_v6_ = 0; + client_info_v4_.reserve(IPA_LAN_TO_LAN_MAX_WLAN_CLIENT + IPA_LAN_TO_LAN_MAX_LAN_CLIENT); + client_info_v6_.reserve(3*(IPA_LAN_TO_LAN_MAX_WLAN_CLIENT + IPA_LAN_TO_LAN_MAX_LAN_CLIENT)); + p_instance = this; + + IPACM_EvtDispatcher::registr(IPA_LAN_CLIENT_ACTIVE, this); + IPACM_EvtDispatcher::registr(IPA_LAN_CLIENT_INACTIVE, this); + IPACM_EvtDispatcher::registr(IPA_LAN_CLIENT_DISCONNECT, this); + IPACM_EvtDispatcher::registr(IPA_LAN_CLIENT_POWER_SAVE, this); + IPACM_EvtDispatcher::registr(IPA_LAN_CLIENT_POWER_RECOVER, this); + IPACM_EvtDispatcher::registr(IPA_LAN_TO_LAN_NEW_CONNECTION, this); + IPACM_EvtDispatcher::registr(IPA_LAN_TO_LAN_DEL_CONNECTION, this); + return; +} + +IPACM_LanToLan::~IPACM_LanToLan() +{ + client_table_v4::iterator it_v4; + for(it_v4 = client_info_v4_.begin(); it_v4 != client_info_v4_.end(); it_v4++) + { + turnoff_offload_links(IPA_IP_v4, &(it_v4->second)); + clear_peer_list(&(it_v4->second)); + } + client_info_v4_.clear(); + IPACMDBG("Clear IPv4 hash table in Lan2Lan distructor.\n"); + + client_table_v6::iterator it_v6; + for(it_v6 = client_info_v6_.begin(); it_v6 != client_info_v6_.end(); it_v6++) + { + turnoff_offload_links(IPA_IP_v6, &(it_v6->second)); + clear_peer_list(&(it_v6->second)); + } + client_info_v6_.clear(); + IPACMDBG("Clear IPv6 hash table in Lan2Lan distructor.\n"); + + return; +} + +void IPACM_LanToLan::event_callback(ipa_cm_event_id event, void* param) +{ + switch(event) + { + case IPA_LAN_CLIENT_ACTIVE: + { + IPACMDBG_H("Get IPA_LAN_CLIENT_ACTIVE event.\n"); + ipacm_event_lan_client* data = (ipacm_event_lan_client*)param; + handle_client_active(data); + break; + } + + case IPA_LAN_CLIENT_INACTIVE: + { + IPACMDBG_H("Get IPA_LAN_CLIENT_INACTIVE event.\n"); + ipacm_event_lan_client* data = (ipacm_event_lan_client*)param; + handle_client_inactive(data); + break; + } + + case IPA_LAN_CLIENT_DISCONNECT: + { + IPACMDBG_H("Get IPA_LAN_CLIENT_DISCONNECT event.\n"); + ipacm_event_lan_client* data = (ipacm_event_lan_client*)param; + handle_client_disconnect(data); + break; + } + + case IPA_LAN_TO_LAN_NEW_CONNECTION: + { + IPACMDBG_H("Get IPA_LAN_TO_LAN_NEW_CONNECTION event.\n"); + ipacm_event_connection* data = (ipacm_event_connection*)param; + handle_new_lan2lan_connection(data); + break; + } + + case IPA_LAN_TO_LAN_DEL_CONNECTION: + { + IPACMDBG_H("Get IPA_LAN_TO_LAN_DEL_CONNECTION event.\n"); + ipacm_event_connection* data = (ipacm_event_connection*)param; + handle_del_lan2lan_connection(data); + break; + } + case IPA_LAN_CLIENT_POWER_SAVE: + { + IPACMDBG_H("Get IPA_LAN_CLIENT_POWER_SAVE event.\n"); + ipacm_event_lan_client* data = (ipacm_event_lan_client*)param; + handle_client_power_save(data); + break; + } + case IPA_LAN_CLIENT_POWER_RECOVER: + { + IPACMDBG_H("Get IPA_LAN_CLIENT_POWER_RECOVER event.\n"); + ipacm_event_lan_client* data = (ipacm_event_lan_client*)param; + handle_client_power_recover(data); + break; + } + default: + break; + } + return; +} + +void IPACM_LanToLan::handle_client_active(ipacm_event_lan_client* data) +{ + if(data == NULL) + { + IPACMERR("No client info is found.\n"); + return; + } + if(data->mac_addr == NULL || data->ipv6_addr == NULL || data->p_iface == NULL) + { + IPACMERR("Event data is not populated properly.\n"); + return; + } + if(data->iptype != IPA_IP_v4 && data->iptype != IPA_IP_v6) + { + IPACMERR("IP type is not expected.\n"); + return; + } + + IPACMDBG_H("New client info: iface %s, iptype: %d, mac: 0x%02x%02x%02x%02x%02x%02x, v4_addr: 0x%08x, v6_addr: 0x%08x%08x%08x%08x \n", + data->p_iface->dev_name, data->iptype, + data->mac_addr[0], data->mac_addr[1], data->mac_addr[2], data->mac_addr[3], data->mac_addr[4], data->mac_addr[5], + data->ipv4_addr, data->ipv6_addr[0], data->ipv6_addr[1], data->ipv6_addr[2], data->ipv6_addr[3]); + + bool client_not_found; + client_info* client_ptr; + + if(data->iptype == IPA_IP_v4) + { + client_not_found = (client_info_v4_.count(data->ipv4_addr) == 0); + IPACMDBG_H("Is the client not found? %d\n", client_not_found); + client_info& client = client_info_v4_[data->ipv4_addr]; + client_ptr = &client; + } + else + { + uint64_t v6_addr; + memcpy(&v6_addr, &(data->ipv6_addr[2]), sizeof(uint64_t)); + + client_not_found = (client_info_v6_.count(v6_addr) == 0); + IPACMDBG_H("Is the client not found? %d\n", client_not_found); + client_info& client = client_info_v6_[v6_addr]; + client_ptr = &client; + } + + if(client_not_found == true) + { + if(data->iptype == IPA_IP_v4) + { + client_ptr->ip.ipv4_addr = data->ipv4_addr; + } + else + { + memcpy(client_ptr->ip.ipv6_addr, data->ipv6_addr, sizeof(client_ptr->ip.ipv6_addr)); + } + memcpy(client_ptr->mac_addr, data->mac_addr, sizeof(client_ptr->mac_addr)); + client_ptr->is_active = true; + client_ptr->is_powersave = false; + client_ptr->p_iface = data->p_iface; + + generate_new_connection(data->iptype, client_ptr); + check_cache_connection(data->iptype, client_ptr); + } + else //the client is found + { + if(client_ptr->is_active == true) //the client is active + { + IPACMDBG_H("The client is active.\n"); + if(memcmp(client_ptr->mac_addr, data->mac_addr, sizeof(client_ptr->mac_addr)) == 0) + { + IPACMDBG_H("Mac addr is the same, do nothing.\n"); + } + else + { + IPACMERR("The new client has same IP but differenc mac.\n"); + turnoff_offload_links(data->iptype, client_ptr); + clear_peer_list(client_ptr); + + if(data->iptype == IPA_IP_v4) + { + client_ptr->ip.ipv4_addr = data->ipv4_addr; + } + else + { + memcpy(client_ptr->ip.ipv6_addr, data->ipv6_addr, sizeof(client_ptr->ip.ipv6_addr)); + } + memcpy(client_ptr->mac_addr, data->mac_addr, sizeof(client_ptr->mac_addr)); + client_ptr->is_active = true; + client_ptr->is_powersave = false; + client_ptr->p_iface = data->p_iface; + + generate_new_connection(data->iptype, client_ptr); + check_cache_connection(data->iptype, client_ptr); + } + } + else //the client is inactive + { + IPACMDBG_H("The client is inactive.\n"); + if(data->iptype == IPA_IP_v4) + { + client_ptr->ip.ipv4_addr = data->ipv4_addr; + } + else + { + memcpy(client_ptr->ip.ipv6_addr, data->ipv6_addr, sizeof(client_ptr->ip.ipv6_addr)); + } + memcpy(client_ptr->mac_addr, data->mac_addr, sizeof(client_ptr->mac_addr)); + client_ptr->is_active = true; + client_ptr->is_powersave = false; + client_ptr->p_iface = data->p_iface; + + check_potential_link(data->iptype, client_ptr); + generate_new_connection(data->iptype, client_ptr); + check_cache_connection(data->iptype, client_ptr); + } + } + IPACMDBG_H("There are %d clients in v4 table and %d clients in v6 table.\n", client_info_v4_.size(), client_info_v6_.size()); + return; +} + +void IPACM_LanToLan::check_potential_link(ipa_ip_type iptype, client_info* client) +{ + if(client == NULL) + { + IPACMERR("Client is NULL.\n"); + return; + } + + IPACMDBG_H("Check client's peer list.\n"); + IPACMDBG_H("Client: IP type: %d, IPv4 addr: 0x%08x, IPv6 addr: 0x%08x%08x%08x%08x\n", iptype, client->ip.ipv4_addr, + client->ip.ipv6_addr[0], client->ip.ipv6_addr[1], client->ip.ipv6_addr[2], client->ip.ipv6_addr[3]); + + peer_info_list::iterator peer_it; + int res, num = 0; + + for(peer_it = client->peer.begin(); peer_it != client->peer.end(); peer_it++) + { + if(peer_it->peer_pointer->is_active == true && peer_it->num_connection > 0) + { + res = IPACM_SUCCESS; + res = add_offload_link(iptype, client, peer_it->peer_pointer); + res = add_offload_link(iptype, peer_it->peer_pointer, client); + if(res == IPACM_SUCCESS) + { + if(iptype == IPA_IP_v4) + { + num_offload_pair_v4_ ++; + IPACMDBG_H("Now the number of v4 offload links is %d.\n", num_offload_pair_v4_); + } + else + { + num_offload_pair_v6_ ++; + IPACMDBG_H("Now the number of v6 offload links is %d.\n", num_offload_pair_v6_); + } + num++; + } + } + } + IPACMDBG_H("Added %d offload links in total.\n", num); + return; +} + +int IPACM_LanToLan::add_offload_link(ipa_ip_type iptype, client_info* client, client_info* peer) +{ + if( (iptype == IPA_IP_v4 && num_offload_pair_v4_ >= MAX_OFFLOAD_PAIR) + || (iptype == IPA_IP_v6 && num_offload_pair_v6_ >= MAX_OFFLOAD_PAIR) ) + { + IPACMDBG_H("The number of offload pairs already reaches maximum.\n"); + return IPACM_FAILURE; + } + if(client == NULL || peer == NULL) + { + IPACMERR("Either client or peer is NULL.\n"); + return IPACM_FAILURE; + } + + uint32_t hdr_hdl, flt_hdl; + lan_to_lan_rt_rule_hdl rt_rule_hdl; + + offload_link_info link_info; + + + if(iptype == IPA_IP_v4) + { + IPACMDBG_H("Add offload link for IPv4, client IP: 0x%08x, peer IP: 0x%08x \n", client->ip.ipv4_addr, peer->ip.ipv4_addr); + } + else if(iptype == IPA_IP_v6) + { + IPACMDBG_H("Add offload link for IPv6, client IP: 0x%08x%08x%08x%08x, peer IP: 0x%08x%08x%08x%08x \n", + client->ip.ipv6_addr[0], client->ip.ipv6_addr[1], client->ip.ipv6_addr[2], client->ip.ipv6_addr[3], + peer->ip.ipv6_addr[0], peer->ip.ipv6_addr[1], peer->ip.ipv6_addr[2], peer->ip.ipv6_addr[3]); + } + else + { + IPACMERR("IP type is not expected.\n"); + return IPACM_FAILURE; + } + + //add lan2lan header + if(peer->p_iface->add_lan2lan_hdr(iptype, client->mac_addr, peer->mac_addr, &hdr_hdl) == IPACM_FAILURE) + { + IPACMERR("Failed to create lan2lan header.\n"); + return IPACM_FAILURE; + } + IPACMDBG_H("Created lan2lan hdr with hdl %d.\n", hdr_hdl); + + //add lan2lan routing/filtering rules + if(peer->p_iface->add_lan2lan_rt_rule(iptype, client->ip.ipv4_addr, peer->ip.ipv4_addr, + client->ip.ipv6_addr, peer->ip.ipv6_addr, hdr_hdl, &rt_rule_hdl) == IPACM_FAILURE) + { + IPACMERR("Failed to create lan2lan rt rule.\n"); + goto rt_fail; + } + IPACMDBG_H("Created %d lan2lan rt rules.\n", rt_rule_hdl.num_rule); + IPACMDBG_H("Created lan2lan rt rules with hdl: %d.\n", rt_rule_hdl.rule_hdl[0]); + + if(client->p_iface->add_lan2lan_flt_rule(iptype, client->ip.ipv4_addr, peer->ip.ipv4_addr, + client->ip.ipv6_addr, peer->ip.ipv6_addr, &flt_hdl) == IPACM_FAILURE) + { + IPACMERR("Failed to create lan2lan flt rule.\n"); + goto flt_fail; + } + IPACMDBG_H("Created lan2lan flt rule with hdl %d.\n", flt_hdl); + + link_info.peer_pointer = peer; + link_info.flt_rule_hdl = flt_hdl; + link_info.hdr_hdl = hdr_hdl; + memcpy(&link_info.rt_rule_hdl, &rt_rule_hdl, sizeof(lan_to_lan_rt_rule_hdl)); + + client->link.push_back(link_info); + + return IPACM_SUCCESS; + +flt_fail: + peer->p_iface->del_lan2lan_rt_rule(iptype, rt_rule_hdl); + +rt_fail: + peer->p_iface->del_lan2lan_hdr(iptype, hdr_hdl); + + return IPACM_FAILURE; +} + +void IPACM_LanToLan::handle_client_inactive(ipacm_event_lan_client* data) +{ + if(data == NULL) + { + IPACMERR("No client info is found.\n"); + return; + } + if(data->mac_addr == NULL || data->ipv6_addr == NULL || data->p_iface == NULL) + { + IPACMERR("Event data is not populated properly.\n"); + return; + } + if(data->iptype != IPA_IP_v4 && data->iptype != IPA_IP_v6) + { + IPACMERR("IP type is not expected: %d.\n", data->iptype); + return; + } + + IPACMDBG_H("Del client info: iface %s, iptype: %d, mac: 0x%02x%02x%02x%02x%02x%02x, v4_addr: 0x%08x, v6_addr: 0x%08x%08x%08x%08x \n", + data->p_iface->dev_name, data->iptype, + data->mac_addr[0], data->mac_addr[1], data->mac_addr[2], data->mac_addr[3], data->mac_addr[4], data->mac_addr[5], + data->ipv4_addr, data->ipv6_addr[0], data->ipv6_addr[1], data->ipv6_addr[2], data->ipv6_addr[3]); + + client_info* client_ptr; + uint64_t v6_addr; + + if(data->iptype == IPA_IP_v4) + { + if(client_info_v4_.count(data->ipv4_addr) == 0)//if not found the client, return + { + IPACMERR("The client is not found the client, return.\n"); + return; + } + IPACMDBG_H("The client is found.\n"); + client_info& client = client_info_v4_[data->ipv4_addr]; + client_ptr = &client; + } + else + { + memcpy(&v6_addr, &(data->ipv6_addr[2]), sizeof(uint64_t)); + if(client_info_v6_.count(v6_addr) == 0) //if not found the client, insert it in table + { + IPACMERR("The client is not found the client, return.\n"); + return; + } + IPACMDBG_H("The client is found.\n"); + client_info& client = client_info_v6_[v6_addr]; + client_ptr = &client; + } + + turnoff_offload_links(data->iptype, client_ptr); + client_ptr->is_active = false; + if(client_ptr->peer.size() == 0) + { + IPACMDBG_H("Peer list is empty, remove client entry.\n"); + if(data->iptype == IPA_IP_v4) + { + client_info_v4_.erase(data->ipv4_addr); + } + else + { + client_info_v6_.erase(v6_addr); + } + } + return; +} + +int IPACM_LanToLan::turnoff_offload_links(ipa_ip_type iptype, client_info* client) +{ + if(client == NULL) + { + IPACMERR("Client is NULL.\n"); + return IPACM_FAILURE; + } + + bool err_flag; + offload_link_info_list::iterator client_it; + offload_link_info_list::iterator peer_it; + client_info* peer; + + for(client_it = client->link.begin(); client_it != client->link.end(); client_it++) + { + peer = client_it->peer_pointer; + if(del_offload_link(iptype, client->p_iface, peer->p_iface, &(*client_it)) == IPACM_FAILURE) + { + IPACMERR("Failed to delete client's offload link.\n"); + return IPACM_FAILURE; + } + + err_flag = true; + for(peer_it = peer->link.begin(); peer_it != peer->link.end(); peer_it++) + { + if(peer_it->peer_pointer == client) + { + if(del_offload_link(iptype, peer->p_iface, client->p_iface, &(*peer_it)) == IPACM_FAILURE) + { + IPACMERR("Failed to delete peer's offload link.\n"); + return IPACM_FAILURE; + } + peer->link.erase(peer_it); + err_flag = false; + break; + } + } + if(err_flag) + { + IPACMERR("Unable to find corresponding offload link in peer's entry.\n"); + return IPACM_FAILURE; + } + if(iptype == IPA_IP_v4) + { + num_offload_pair_v4_ --; + IPACMDBG_H("Now the number of v4 offload pair is %d\n", num_offload_pair_v4_); + } + else + { + num_offload_pair_v6_ --; + IPACMDBG_H("Now the number of v6 offload pair is %d\n", num_offload_pair_v6_); + } + } + + client->link.clear(); + return IPACM_SUCCESS; +} + +int IPACM_LanToLan::del_offload_link(ipa_ip_type iptype, IPACM_Lan* client, IPACM_Lan* peer, offload_link_info* link) +{ + if(client == NULL || peer == NULL || link == NULL) + { + IPACMERR("Either iface or link is NULL.\n"); + return IPACM_FAILURE; + } + + IPACMDBG_H("Delete an offload link for IP type: %d\n", iptype); + + int res = IPACM_SUCCESS; + + if(client->del_lan2lan_flt_rule(iptype, link->flt_rule_hdl) == IPACM_FAILURE) + { + IPACMERR("Failed to delete flt rule.\n"); + res = IPACM_FAILURE; + } + + if(peer->del_lan2lan_rt_rule(iptype, link->rt_rule_hdl) == IPACM_FAILURE) + { + IPACMERR("Failed to delete rt rules.\n"); + res = IPACM_FAILURE; + } + + if(peer->del_lan2lan_hdr(iptype, link->hdr_hdl) == IPACM_FAILURE) + { + IPACMERR("Failed to delete header.\n"); + res = IPACM_FAILURE; + } + + return res; +} + +void IPACM_LanToLan::handle_client_disconnect(ipacm_event_lan_client* data) +{ + if(data == NULL) + { + IPACMERR("No client info is found.\n"); + return; + } + if(data->mac_addr == NULL || data->ipv6_addr == NULL || data->p_iface == NULL) + { + IPACMERR("Event data is not populated properly.\n"); + return; + } + if(data->iptype != IPA_IP_v4 && data->iptype != IPA_IP_v6) + { + IPACMERR("IP type is not expected: %d.\n", data->iptype); + return; + } + + IPACMDBG_H("Del client info: iface %s, iptype: %d, mac: 0x%02x%02x%02x%02x%02x%02x, v4_addr: 0x%08x, v6_addr: 0x%08x%08x%08x%08x \n", + data->p_iface->dev_name, data->iptype, + data->mac_addr[0], data->mac_addr[1], data->mac_addr[2], data->mac_addr[3], data->mac_addr[4], data->mac_addr[5], + data->ipv4_addr, data->ipv6_addr[0], data->ipv6_addr[1], data->ipv6_addr[2], data->ipv6_addr[3]); + + client_info* client_ptr; + uint64_t v6_addr; + if(data->iptype == IPA_IP_v4) + { + if(client_info_v4_.count(data->ipv4_addr) == 0) //if not found the client, return + { + IPACMERR("The client is not found the client, return.\n"); + return; + } + IPACMDBG_H("The client is found.\n"); + client_info& client = client_info_v4_[data->ipv4_addr]; + client_ptr = &client; + } + else + { + memcpy(&v6_addr, &(data->ipv6_addr[2]), sizeof(uint64_t)); + if(client_info_v6_.count(v6_addr) == 0) //if not found the client, insert it in table + { + IPACMERR("The client is not found the client, return.\n"); + return; + } + IPACMDBG_H("The client is found.\n"); + client_info& client = client_info_v6_[v6_addr]; + client_ptr = &client; + } + + turnoff_offload_links(data->iptype, client_ptr); + clear_peer_list(client_ptr); + if(data->iptype == IPA_IP_v4) + { + client_info_v4_.erase(data->ipv4_addr); + } + else + { + client_info_v6_.erase(v6_addr); + } + return; +} + +int IPACM_LanToLan::clear_peer_list(client_info* client) +{ + if(client == NULL) + { + IPACMERR("Client is NULL.\n"); + return IPACM_FAILURE; + } + + bool err_flag; + peer_info_list::iterator client_it; + peer_info_list::iterator peer_it; + client_info* peer; + + for(client_it = client->peer.begin(); client_it != client->peer.end(); client_it++) + { + err_flag = true; + peer = client_it->peer_pointer; + for(peer_it = peer->peer.begin(); peer_it != peer->peer.end(); peer_it++) + { + if(peer_it->peer_pointer == client) + { + peer->peer.erase(peer_it); + err_flag = false; + break; + } + } + if(err_flag == true) + { + IPACMERR("Failed to find peer info.\n"); + return IPACM_FAILURE; + } + } + client->peer.clear(); + return IPACM_SUCCESS; +} + +void IPACM_LanToLan::handle_client_power_save(ipacm_event_lan_client* data) +{ + if(data == NULL) + { + IPACMERR("No client info is found.\n"); + return; + } + if(data->mac_addr == NULL || data->ipv6_addr == NULL || data->p_iface == NULL) + { + IPACMERR("Event data is not populated properly.\n"); + return; + } + if(data->iptype != IPA_IP_v4 && data->iptype != IPA_IP_v6) + { + IPACMERR("IP type is not expected: %d.\n", data->iptype); + return; + } + + IPACMDBG_H("Client power save info: iface %s, iptype: %d, mac: 0x%02x%02x%02x%02x%02x%02x, v4_addr: 0x%08x, v6_addr: 0x%08x%08x%08x%08x \n", + data->p_iface->dev_name, data->iptype, + data->mac_addr[0], data->mac_addr[1], data->mac_addr[2], data->mac_addr[3], data->mac_addr[4], data->mac_addr[5], + data->ipv4_addr, data->ipv6_addr[0], data->ipv6_addr[1], data->ipv6_addr[2], data->ipv6_addr[3]); + + client_info* client_ptr; + uint64_t v6_addr; + + if(data->iptype == IPA_IP_v4) + { + if(client_info_v4_.count(data->ipv4_addr) == 0)//if not found the client, return + { + IPACMERR("The client is not found the client, return.\n"); + return; + } + IPACMDBG_H("The client is found.\n"); + client_info& client = client_info_v4_[data->ipv4_addr]; + client_ptr = &client; + } + else + { + memcpy(&v6_addr, &(data->ipv6_addr[2]), sizeof(uint64_t)); + if(client_info_v6_.count(v6_addr) == 0) //if not found the client, insert it in table + { + IPACMERR("The client is not found the client, return.\n"); + return; + } + IPACMDBG_H("The client is found.\n"); + client_info& client = client_info_v6_[v6_addr]; + client_ptr = &client; + } + + if(remove_flt_rules(data->iptype, client_ptr) == IPACM_FAILURE) + { + IPACMERR("Failed to remove flt rules when power save.\n"); + return; + } + client_ptr->is_active = false; + client_ptr->is_powersave = true; + return; +} + +void IPACM_LanToLan::handle_new_lan2lan_connection(ipacm_event_connection* data) +{ + IPACMDBG_H("New lan2lan connection info: IP type: %d, src_v4_addr: 0x%08x, dst_v4_addr: 0x%08x\n", data->iptype, data->src_ipv4_addr, data->dst_ipv4_addr); + IPACMDBG_H("src_v6_addr: 0x%08x%08x%08x%08x, dst_v6_addr: 0x%08x%08x%08x%08x", data->src_ipv6_addr[0], data->src_ipv6_addr[1], data->src_ipv6_addr[2], + data->src_ipv6_addr[3], data->dst_ipv6_addr[0], data->dst_ipv6_addr[1], data->dst_ipv6_addr[2], data->dst_ipv6_addr[3]); + + client_info* src_client_ptr; + client_info* dst_client_ptr; + + if(data->iptype == IPA_IP_v4) + { + if(client_info_v4_.count(data->src_ipv4_addr) == 0 || client_info_v4_.count(data->dst_ipv4_addr) == 0) + { + IPACMERR("Either source or destination is not in table.\n"); + return; + } + client_info& src_client = client_info_v4_[data->src_ipv4_addr]; + src_client_ptr = &src_client; + client_info& dst_client = client_info_v4_[data->dst_ipv4_addr]; + dst_client_ptr = &dst_client; + } + else //ipv6 case + { + uint64_t src_ipv6_addr; + uint64_t dst_ipv6_addr; + memcpy(&src_ipv6_addr, &(data->src_ipv6_addr[2]), sizeof(uint64_t)); + memcpy(&dst_ipv6_addr, &(data->dst_ipv6_addr[2]), sizeof(uint64_t)); + + if(client_info_v6_.count(src_ipv6_addr) == 0 || client_info_v6_.count(dst_ipv6_addr) == 0) + { + IPACMERR("Either source or destination is not in table.\n"); + return; + } + client_info& src_client = client_info_v6_[src_ipv6_addr]; + src_client_ptr = &src_client; + client_info& dst_client = client_info_v6_[dst_ipv6_addr]; + dst_client_ptr = &dst_client; + } + + IPACMDBG_H("Both src and dst are already in table.\n"); + bool is_first_connection; + is_first_connection = add_connection(src_client_ptr, dst_client_ptr); + + if(is_first_connection && src_client_ptr->is_active && dst_client_ptr->is_active) + { + IPACMDBG_H("This is first connection, add offload links.\n"); + + if(add_offload_link(data->iptype, src_client_ptr, dst_client_ptr) == IPACM_FAILURE) + { + IPACMERR("Failed to add offload link for src->dst direction.\n"); + return; + } + if(add_offload_link(data->iptype, dst_client_ptr, src_client_ptr) == IPACM_FAILURE) + { + IPACMERR("Failed to add offload link for dst->src direction.\n"); + return; + } + + if(data->iptype == IPA_IP_v4) + { + num_offload_pair_v4_ ++; + IPACMDBG_H("Added offload links, now num_offload_pair_v4_: %d\n", num_offload_pair_v4_); + } + else + { + num_offload_pair_v6_ ++; + IPACMDBG_H("Added offload links, now num_offload_pair_v6_: %d\n", num_offload_pair_v6_); + } + } + return; +} + +//If need to insert an entry in peer list, return true, otherwise return false +bool IPACM_LanToLan::add_connection(client_info* src_client, client_info* dst_client) +{ + if(src_client == NULL || dst_client == NULL) + { + IPACMERR("Either source or dest client is NULL.\n"); + return false; + } + + peer_info_list::iterator it; + peer_info new_peer; + bool ret = false; + + for(it = src_client->peer.begin(); it != src_client->peer.end(); it++) + { + if(it->peer_pointer == dst_client) + { + it->num_connection++; + IPACMDBG_H("Find dst client entry in peer list, connection count: %d\n", it->num_connection); + break; + } + } + if(it == src_client->peer.end()) + { + IPACMDBG_H("Not finding dst client entry, insert a new one in peer list.\n"); + new_peer.peer_pointer = dst_client; + new_peer.num_connection = 1; + src_client->peer.push_back(new_peer); + ret = true; + } + + for(it = dst_client->peer.begin(); it != dst_client->peer.end(); it++) + { + if(it->peer_pointer == src_client) + { + it->num_connection++; + IPACMDBG_H("Find dst client entry in peer list, connection count: %d\n", it->num_connection); + break; + } + } + if(it == dst_client->peer.end()) + { + IPACMDBG_H("Not finding src client entry, insert a new one in peer list.\n"); + new_peer.peer_pointer = src_client; + new_peer.num_connection = 1; + dst_client->peer.push_back(new_peer); + ret = true; + } + return ret; +} + +void IPACM_LanToLan::handle_del_lan2lan_connection(ipacm_event_connection* data) +{ + IPACMDBG_H("Del lan2lan connection info: IP type: %d, src_v4_addr: 0x%08x, dst_v4_addr: 0x%08x\n", data->iptype, data->src_ipv4_addr, data->dst_ipv4_addr); + IPACMDBG_H("src_v6_addr: 0x%08x%08x%08x%08x, dst_v6_addr: 0x%08x%08x%08x%08x", data->src_ipv6_addr[0], data->src_ipv6_addr[1], data->src_ipv6_addr[2], + data->src_ipv6_addr[3], data->dst_ipv6_addr[0], data->dst_ipv6_addr[1], data->dst_ipv6_addr[2], data->dst_ipv6_addr[3]); + + bool res; + uint64_t src_ipv6_addr, dst_ipv6_addr; + client_info* src_client_ptr; + client_info* dst_client_ptr; + + if(data->iptype == IPA_IP_v4) + { + if(client_info_v4_.count(data->src_ipv4_addr) == 0 + || client_info_v4_.count(data->dst_ipv4_addr) == 0) //if not found the client + { + IPACMDBG_H("Not found either source or dest client, return.\n"); + return; + } + client_info& src_client = client_info_v4_[data->src_ipv4_addr]; + client_info& dst_client = client_info_v4_[data->dst_ipv4_addr]; + src_client_ptr = &src_client; + dst_client_ptr = &dst_client; + } + else + { + memcpy(&src_ipv6_addr, &(data->src_ipv6_addr[2]), sizeof(uint64_t)); + memcpy(&dst_ipv6_addr, &(data->dst_ipv6_addr[2]), sizeof(uint64_t)); + if(client_info_v6_.count(src_ipv6_addr) == 0 + || client_info_v6_.count(dst_ipv6_addr) == 0)//if not found the client + { + IPACMDBG_H("Not found either source or dest client, return.\n"); + return; + } + client_info& src_client = client_info_v6_[src_ipv6_addr]; + client_info& dst_client = client_info_v6_[dst_ipv6_addr]; + src_client_ptr = &src_client; + dst_client_ptr = &dst_client; + } + + res = remove_connection(src_client_ptr, dst_client_ptr); + + if(res && src_client_ptr->is_active && dst_client_ptr->is_active) + { + IPACMDBG_H("Erase link info for both src and dst entries.\n"); + erase_offload_link(data->iptype, src_client_ptr, dst_client_ptr); + } + else + { + if(res && src_client_ptr->is_powersave && (dst_client_ptr->is_active || dst_client_ptr->is_powersave)) + { + IPACMDBG_H("Erase link info for both src and dst entries due to src powersave.\n"); + erase_offload_link(data->iptype, src_client_ptr, dst_client_ptr); + } + if(res && dst_client_ptr->is_powersave && (src_client_ptr->is_active || src_client_ptr->is_powersave)) + { + IPACMDBG_H("Erase link info for both src and dst entries due to dst powersave.\n"); + erase_offload_link(data->iptype, dst_client_ptr, src_client_ptr); + } + } + + //if the src client is not active and not powersave mode, if peer list is empty, remove client entry + if(res && src_client_ptr->is_active == false && src_client_ptr->is_powersave == false && src_client_ptr->peer.size() == 0) + { + IPACMDBG_H("Peer list of src is empty, remove src entry.\n"); + if(data->iptype == IPA_IP_v4) + { + client_info_v4_.erase(data->src_ipv4_addr); + } + else + { + client_info_v6_.erase(src_ipv6_addr); + } + } + + //if the dst client is not active and not powersave mode, if peer list is empty, remove client entry + if(res && dst_client_ptr->is_active == false && dst_client_ptr->is_powersave == false && dst_client_ptr->peer.size() == 0) + { + IPACMDBG_H("Peer list of dst is empty, remove dst entry.\n"); + if(data->iptype == IPA_IP_v4) + { + client_info_v4_.erase(data->dst_ipv4_addr); + } + else + { + client_info_v6_.erase(dst_ipv6_addr); + } + } + return; +} + +//If need to remove an entry in peer list, return true, otherwise return false +bool IPACM_LanToLan::remove_connection(client_info* src_client, client_info* dst_client) +{ + if(src_client == NULL || dst_client == NULL) + { + IPACMERR("Either source or dest client is NULL.\n"); + return false; + } + + peer_info_list::iterator it; + bool ret = false; + + for(it = src_client->peer.begin(); it != src_client->peer.end(); it++) + { + if(it->peer_pointer == dst_client) + { + it->num_connection--; + IPACMDBG_H("Find dst client entry in src peer list, connection count: %d\n", it->num_connection); + if(it->num_connection == 0) + { + IPACMDBG_H("Need to remove dst entry in src peer list.\n"); + ret = true; + } + break; + } + } + if(ret == true) + { + src_client->peer.erase(it); + } + + ret = false; + for(it = dst_client->peer.begin(); it != dst_client->peer.end(); it++) + { + if(it->peer_pointer == src_client) + { + it->num_connection--; + IPACMDBG_H("Find src client entry in dst peer list, connection count: %d\n", it->num_connection); + if(it->num_connection == 0) + { + IPACMDBG_H("Need to remove src entry in dst peer list.\n"); + ret = true; + } + break; + } + } + if(ret == true) + { + dst_client->peer.erase(it); + } + return ret; +} + +void IPACM_LanToLan::erase_offload_link(ipa_ip_type iptype, client_info* src_client, client_info* dst_client) +{ + if(src_client == NULL || dst_client == NULL) + { + IPACMERR("Either source or dest client is NULL.\n"); + return; + } + + offload_link_info_list::iterator it; + int res_src = IPACM_FAILURE, res_dst = IPACM_FAILURE; + + for(it = src_client->link.begin(); it != src_client->link.end(); it++) + { + if(it->peer_pointer == dst_client) + { + res_src = IPACM_SUCCESS; + IPACMDBG_H("Find dst client entry in src link list\n"); + res_src = del_offload_link(iptype, src_client->p_iface, dst_client->p_iface, &(*it)); + src_client->link.erase(it); + break; + } + } + + for(it = dst_client->link.begin(); it != dst_client->link.end(); it++) + { + if(it->peer_pointer == src_client) + { + res_dst = IPACM_SUCCESS; + IPACMDBG_H("Find src client entry in dst link list\n"); + res_dst = del_offload_link(iptype, dst_client->p_iface, src_client->p_iface, &(*it)); + dst_client->link.erase(it); + break; + } + } + + if(res_src == IPACM_SUCCESS && res_dst == IPACM_SUCCESS) + { + if(iptype == IPA_IP_v4) + { + num_offload_pair_v4_ --; + IPACMDBG_H("Decrease num of v4 offload pairs to %d\n", num_offload_pair_v4_); + } + else + { + num_offload_pair_v6_ --; + IPACMDBG_H("Decrease num of v6 offload pairs to %d\n", num_offload_pair_v6_); + } + } + return; +} + +void IPACM_LanToLan::generate_new_connection(ipa_ip_type iptype, client_info* client) +{ +#ifndef CT_OPT + if(client == NULL) + { + IPACMERR("Client is NULL.\n"); + return; + } + + IPACMDBG_H("Generate new connection events for IP type %d\n", iptype); + + int num = 0; + ipacm_cmd_q_data evt; + ipacm_event_connection* new_conn; + ipacm_iface_type client_type, peer_type; + client_type = IPACM_Iface::ipacmcfg->iface_table[client->p_iface->ipa_if_num].if_cat; + + IPACMDBG_H("Client's iface type is %d.\n", client_type); + + if(iptype == IPA_IP_v4) + { + client_table_v4::iterator it; + for(it = client_info_v4_.begin(); it != client_info_v4_.end(); it++) + { + peer_type = IPACM_Iface::ipacmcfg->iface_table[it->second.p_iface->ipa_if_num].if_cat; + if(peer_type != client_type && it->second.is_active == true) + { + IPACMDBG_H("Find a qualified peer to generate new_conn event.\n"); + IPACMDBG_H("Peer's iface type is %d.\n", peer_type); + new_conn = (ipacm_event_connection*)malloc(sizeof(ipacm_event_connection)); + if(new_conn == NULL) + { + IPACMERR("Failed to allocate memory for new_connection event.\n"); + return; + } + memset(new_conn, 0, sizeof(ipacm_event_connection)); + new_conn->iptype = IPA_IP_v4; + new_conn->src_ipv4_addr = client->ip.ipv4_addr; + new_conn->dst_ipv4_addr = it->second.ip.ipv4_addr; + + memset(&evt, 0, sizeof(evt)); + evt.event = IPA_LAN_TO_LAN_NEW_CONNECTION; + evt.evt_data = (void*)new_conn; + IPACM_EvtDispatcher::PostEvt(&evt); + num++; + } + } + } + else if(iptype == IPA_IP_v6) + { + client_table_v6::iterator it; + for(it = client_info_v6_.begin(); it != client_info_v6_.end(); it++) + { + peer_type = IPACM_Iface::ipacmcfg->iface_table[it->second.p_iface->ipa_if_num].if_cat; + if(peer_type != client_type && it->second.is_active == true) + { + IPACMDBG_H("Find a qualified peer to generate new_conn event.\n"); + IPACMDBG_H("Peer's iface type is %d.\n", peer_type); + new_conn = (ipacm_event_connection*)malloc(sizeof(ipacm_event_connection)); + if(new_conn == NULL) + { + IPACMERR("Failed to allocate memory for new_connection event.\n"); + return; + } + memset(new_conn, 0, sizeof(ipacm_event_connection)); + new_conn->iptype = IPA_IP_v6; + memcpy(new_conn->src_ipv6_addr, client->ip.ipv6_addr, sizeof(new_conn->src_ipv6_addr)); + memcpy(new_conn->dst_ipv6_addr, it->second.ip.ipv6_addr, sizeof(new_conn->dst_ipv6_addr)); + + memset(&evt, 0, sizeof(evt)); + evt.event = IPA_LAN_TO_LAN_NEW_CONNECTION; + evt.evt_data = (void*)new_conn; + IPACM_EvtDispatcher::PostEvt(&evt); + num++; + } + } + } + else + { + IPACMERR("IP type is not expected.\n"); + } + IPACMDBG_H("Generate %d new connection events in total.\n", num); +#endif + return; +} + +void IPACM_LanToLan::handle_client_power_recover(ipacm_event_lan_client* data) +{ + if(data == NULL) + { + IPACMERR("No client info is found.\n"); + return; + } + if(data->mac_addr == NULL || data->ipv6_addr == NULL || data->p_iface == NULL) + { + IPACMERR("Event data is not populated properly.\n"); + return; + } + if(data->iptype != IPA_IP_v4 && data->iptype != IPA_IP_v6) + { + IPACMERR("IP type is not expected: %d\n", data->iptype); + return; + } + + IPACMDBG_H("New client info: iface %s, iptype: %d, mac: 0x%02x%02x%02x%02x%02x%02x, v4_addr: 0x%08x, v6_addr: 0x%08x%08x%08x%08x \n", + data->p_iface->dev_name, data->iptype, + data->mac_addr[0], data->mac_addr[1], data->mac_addr[2], data->mac_addr[3], data->mac_addr[4], data->mac_addr[5], + data->ipv4_addr, data->ipv6_addr[0], data->ipv6_addr[1], data->ipv6_addr[2], data->ipv6_addr[3]); + + client_info* client_ptr; + if(data->iptype == IPA_IP_v4) + { + if(client_info_v4_.count(data->ipv4_addr) == 0) + { + IPACMERR("Client is not found.\n"); + return; + } + client_info& client = client_info_v4_[data->ipv4_addr]; + client_ptr = &client; + } + else + { + uint64_t v6_addr; + memcpy(&v6_addr, &(data->ipv6_addr[2]), sizeof(uint64_t)); + if(client_info_v6_.count(v6_addr) == 0) + { + IPACMERR("Client is not found.\n"); + return; + } + client_info& client = client_info_v6_[v6_addr]; + client_ptr = &client; + } + + if(client_ptr->is_active == true || client_ptr->is_powersave != true) //the client is in wrong state + { + IPACMERR("The client is in wrong state: active %d, powersave %d.\n", client_ptr->is_active, client_ptr->is_powersave); + return; + } + else + { + if(add_flt_rules(data->iptype, client_ptr) == IPACM_FAILURE) + { + IPACMERR("Failed to add back flt rules when power recovery.\n"); + return; + } + client_ptr->is_active = true; + client_ptr->is_powersave = false; + + check_potential_link(data->iptype, client_ptr); + generate_new_connection(data->iptype, client_ptr); + } + IPACMDBG_H("There are %d clients in v4 table and %d clients in v6 table.\n", client_info_v4_.size(), client_info_v6_.size()); + return; +} + +//This function is called when power save: remove filtering rules only +int IPACM_LanToLan::remove_flt_rules(ipa_ip_type iptype, client_info* client) +{ + if(client == NULL) + { + IPACMERR("No client info is found.\n"); + return IPACM_FAILURE; + } + + bool err_flag; + offload_link_info_list::iterator client_it; + offload_link_info_list::iterator peer_it; + client_info* peer; + + for(client_it = client->link.begin(); client_it != client->link.end(); client_it++) + { + if(client->p_iface->del_lan2lan_flt_rule(iptype, client_it->flt_rule_hdl) == IPACM_FAILURE) + { + IPACMERR("Failed to delete client's filtering rule.\n"); + } + + err_flag = true; + peer = client_it->peer_pointer; + for(peer_it = peer->link.begin(); peer_it != peer->link.end(); peer_it++) + { + if(peer_it->peer_pointer == client) + { + if(peer->p_iface->del_lan2lan_flt_rule(iptype, peer_it->flt_rule_hdl) == IPACM_FAILURE) + { + IPACMERR("Failed to delete peer's offload link.\n"); + } + err_flag = false; + break; + } + } + if(err_flag) + { + IPACMERR("Unable to find corresponding offload link in peer's entry.\n"); + return IPACM_FAILURE; + } + } + return IPACM_SUCCESS; +} + +int IPACM_LanToLan::add_flt_rules(ipa_ip_type iptype, client_info* client) +{ + if(client == NULL) + { + IPACMERR("No client info is found.\n"); + return IPACM_FAILURE; + } + + bool err_flag; + offload_link_info_list::iterator client_it; + offload_link_info_list::iterator peer_it; + client_info* peer; + + for(client_it = client->link.begin(); client_it != client->link.end(); client_it++) + { + peer = client_it->peer_pointer; + if(client->p_iface->add_lan2lan_flt_rule(iptype, client->ip.ipv4_addr, peer->ip.ipv4_addr, + client->ip.ipv6_addr, peer->ip.ipv6_addr, &(client_it->flt_rule_hdl)) == IPACM_FAILURE) + { + IPACMERR("Failed to add client's filtering rule.\n"); + return IPACM_FAILURE; + } + + err_flag = true; + for(peer_it = peer->link.begin(); peer_it != peer->link.end(); peer_it++) + { + if(peer_it->peer_pointer == client) + { + if(peer->p_iface->add_lan2lan_flt_rule(iptype, peer->ip.ipv4_addr, client->ip.ipv4_addr, + peer->ip.ipv6_addr, client->ip.ipv6_addr, &(peer_it->flt_rule_hdl)) == IPACM_FAILURE) + { + IPACMERR("Failed to delete peer's offload link.\n"); + return IPACM_FAILURE; + } + err_flag = false; + break; + } + } + if(err_flag) + { + IPACMERR("Unable to find corresponding offload link in peer's entry.\n"); + return IPACM_FAILURE; + } + } + return IPACM_SUCCESS; +} + +void IPACM_LanToLan::handle_new_connection(ipacm_event_connection* new_conn) +{ +#ifdef CT_OPT + if(new_conn == NULL) + { + IPACMERR("No connection info is found.\n"); + return; + } + if(new_conn->iptype != IPA_IP_v4 && new_conn->iptype != IPA_IP_v6) + { + IPACMERR("IP type is not expected: %d.\n", new_conn->iptype); + return; + } + + IPACMDBG_H("New connection info: IP type: %d, src_v4_addr: 0x%08x, dst_v4_addr: 0x%08x\n", new_conn->iptype, new_conn->src_ipv4_addr, new_conn->dst_ipv4_addr); + IPACMDBG_H("src_v6_addr: 0x%08x%08x%08x%08x, dst_v6_addr: 0x%08x%08x%08x%08x", new_conn->src_ipv6_addr[0], new_conn->src_ipv6_addr[1], new_conn->src_ipv6_addr[2], + new_conn->src_ipv6_addr[3], new_conn->dst_ipv6_addr[0], new_conn->dst_ipv6_addr[1], new_conn->dst_ipv6_addr[2], new_conn->dst_ipv6_addr[3]); + + if(is_lan2lan_connection(new_conn) == false) + { + IPACMDBG_H("The connection is not lan2lan connection.\n"); + cache_new_connection(new_conn); + return; + } + + ipacm_cmd_q_data evt; + ipacm_event_connection* conn; + + conn = (ipacm_event_connection*)malloc(sizeof(ipacm_event_connection)); + if(conn == NULL) + { + IPACMERR("Failed to allocate memory for new_connection event.\n"); + return; + } + memcpy(conn, new_conn, sizeof(ipacm_event_connection)); + + memset(&evt, 0, sizeof(evt)); + evt.event = IPA_LAN_TO_LAN_NEW_CONNECTION; + evt.evt_data = (void*)conn; + IPACM_EvtDispatcher::PostEvt(&evt); +#endif + return; +} + +void IPACM_LanToLan::handle_del_connection(ipacm_event_connection* new_conn) +{ +#ifdef CT_OPT + if(new_conn == NULL) + { + IPACMERR("No connection info is found.\n"); + return; + } + if(new_conn->iptype != IPA_IP_v4 && new_conn->iptype != IPA_IP_v6) + { + IPACMERR("IP type is not expected: %d.\n", new_conn->iptype); + return; + } + + IPACMDBG_H("Del connection info: IP type: %d, src_v4_addr: 0x%08x, dst_v4_addr: 0x%08x\n", new_conn->iptype, new_conn->src_ipv4_addr, new_conn->dst_ipv4_addr); + IPACMDBG_H("src_v6_addr: 0x%08x%08x%08x%08x, dst_v6_addr: 0x%08x%08x%08x%08x", new_conn->src_ipv6_addr[0], new_conn->src_ipv6_addr[1], new_conn->src_ipv6_addr[2], + new_conn->src_ipv6_addr[3], new_conn->dst_ipv6_addr[0], new_conn->dst_ipv6_addr[1], new_conn->dst_ipv6_addr[2], new_conn->dst_ipv6_addr[3]); + + if(is_lan2lan_connection(new_conn) == false) + { + IPACMDBG_H("The connection is not lan2lan connection.\n"); + remove_cache_connection(new_conn); + return; + } + + ipacm_cmd_q_data evt; + ipacm_event_connection* conn; + + conn = (ipacm_event_connection*)malloc(sizeof(ipacm_event_connection)); + if(conn == NULL) + { + IPACMERR("Failed to allocate memory for del_connection event.\n"); + return; + } + memcpy(conn, new_conn, sizeof(ipacm_event_connection)); + + memset(&evt, 0, sizeof(evt)); + evt.event = IPA_LAN_TO_LAN_DEL_CONNECTION; + evt.evt_data = (void*)conn; + IPACM_EvtDispatcher::PostEvt(&evt); +#endif + return; +} + +bool IPACM_LanToLan::is_lan2lan_connection(ipacm_event_connection* data) +{ + if(data->iptype == IPA_IP_v4) + { + if(client_info_v4_.count(data->src_ipv4_addr) == 0 || client_info_v4_.count(data->dst_ipv4_addr) == 0) + { + IPACMDBG("Either source or destination is not in client table\n"); + return false; + } + + ipacm_iface_type src_type, dst_type; + src_type = IPACM_Iface::ipacmcfg->iface_table[client_info_v4_[data->src_ipv4_addr].p_iface->ipa_if_num].if_cat; + dst_type = IPACM_Iface::ipacmcfg->iface_table[client_info_v4_[data->dst_ipv4_addr].p_iface->ipa_if_num].if_cat; + + return (src_type != dst_type); + } + else + { + uint64_t src_v6_addr, dst_v6_addr; + memcpy(&src_v6_addr, &(data->src_ipv6_addr[2]), sizeof(uint64_t)); + memcpy(&dst_v6_addr, &(data->dst_ipv6_addr[2]), sizeof(uint64_t)); + + if(client_info_v6_.count(src_v6_addr) == 0 || client_info_v6_.count(dst_v6_addr) == 0) + { + IPACMDBG("Either source or destination is not in client table\n"); + return false; + } + + ipacm_iface_type src_type, dst_type; + src_type = IPACM_Iface::ipacmcfg->iface_table[client_info_v6_[src_v6_addr].p_iface->ipa_if_num].if_cat; + dst_type = IPACM_Iface::ipacmcfg->iface_table[client_info_v6_[dst_v6_addr].p_iface->ipa_if_num].if_cat; + + return (src_type != dst_type); + } +} + +IPACM_LanToLan* IPACM_LanToLan::getLan2LanInstance() +{ + return p_instance; +} + +bool IPACM_LanToLan::is_potential_lan2lan_connection(ipacm_event_connection* new_conn) +{ + int i, num_private_subnet; + bool src_is_valid = false; + bool dst_is_valid = false; + + if(new_conn->iptype == IPA_IP_v4) + { + num_private_subnet = IPACM_Iface::ipacmcfg->ipa_num_private_subnet; + for(i=0; isrc_ipv4_addr & IPACM_Iface::ipacmcfg->private_subnet_table[i].subnet_mask) + == (IPACM_Iface::ipacmcfg->private_subnet_table[i].subnet_addr & IPACM_Iface::ipacmcfg->private_subnet_table[i].subnet_mask) ) + { + src_is_valid = true; + } + if( (new_conn->dst_ipv4_addr & IPACM_Iface::ipacmcfg->private_subnet_table[i].subnet_mask) + == (IPACM_Iface::ipacmcfg->private_subnet_table[i].subnet_addr & IPACM_Iface::ipacmcfg->private_subnet_table[i].subnet_mask) ) + { + dst_is_valid = true; + } + } + + if(src_is_valid && dst_is_valid) + { + IPACMDBG("Both src and dst are potentially in subnet.\n"); + return true; + } + } + else + { + if( (new_conn->src_ipv6_addr[0] & ipv6_multicast_mask) != (ipv6_multicast_addr & ipv6_multicast_mask) ) + { + src_is_valid = true; + } + if( (new_conn->dst_ipv6_addr[0] & ipv6_multicast_mask) != (ipv6_multicast_addr & ipv6_multicast_mask) ) + { + dst_is_valid = true; + } + + if(src_is_valid && dst_is_valid) + { + IPACMDBG("Both src and dst are potentially in subnet.\n"); + return true; + } + } + + IPACMDBG("This connection is not a lan2lan connection potentially.\n"); + return false; +} + +void IPACM_LanToLan::cache_new_connection(ipacm_event_connection* new_conn) +{ + if(is_potential_lan2lan_connection(new_conn) == true) + { + if(new_conn->iptype == IPA_IP_v4) + { + if(connection_v4_.size() == max_cache_connection) + { + IPACMDBG_H("Cached ipv4 connections already reach maximum, clear up the list.\n"); + connection_v4_.clear(); + } + + connection_v4_.push_back(*new_conn); + IPACMDBG_H("Cache an ipv4 connection, now the number of ipv4 cache connection is %d.\n", connection_v4_.size()); + } + else + { + if(connection_v6_.size() == max_cache_connection) + { + IPACMDBG_H("Cached ipv6 connections already reach maximum, clear up the list.\n"); + connection_v6_.clear(); + } + + connection_v6_.push_back(*new_conn); + IPACMDBG_H("Cache an ipv6 connection, now the number of ipv6 cache connection is %d.\n", connection_v6_.size()); + } + } + return; +} + +void IPACM_LanToLan::remove_cache_connection(ipacm_event_connection* del_conn) +{ + connection_list::iterator it; + if(is_potential_lan2lan_connection(del_conn) == true) + { + if(del_conn->iptype == IPA_IP_v4) + { + for(it = connection_v4_.begin(); it != connection_v4_.end(); it++) + { + if(it->src_ipv4_addr == del_conn->src_ipv4_addr && it->dst_ipv4_addr == del_conn->dst_ipv4_addr) + { + IPACMDBG("Find the cached ipv4 connection, remove it from list.\n"); + connection_v4_.erase(it); + IPACMDBG_H("Now the number of ipv4 cache connection is %d.\n", connection_v4_.size()); + return; + } + } + IPACMDBG_H("Do not find the cached ipv4 connection, do nothing.\n"); + } + else + { + for(it = connection_v6_.begin(); it != connection_v6_.end(); it++) + { + if(memcmp(it->src_ipv6_addr, del_conn->src_ipv6_addr, 4*sizeof(uint32_t)) == 0 + && memcmp(it->dst_ipv6_addr, del_conn->dst_ipv6_addr, 4*sizeof(uint32_t)) == 0 ) + { + IPACMDBG("Find the cached ipv6 connection, remove it from list.\n"); + connection_v6_.erase(it); + IPACMDBG_H("Now the number of ipv6 cache connection is %d.\n", connection_v6_.size()); + return; + } + } + IPACMDBG_H("Do not find the cached ipv6 connection, do nothing.\n"); + } + } + return; +} + +void IPACM_LanToLan::check_cache_connection(ipa_ip_type iptype, client_info* client) +{ +#ifdef CT_OPT + connection_list::iterator it; + if(iptype == IPA_IP_v4) + { + it = connection_v4_.begin(); + while(it != connection_v4_.end()) + { + if( (it->src_ipv4_addr == client->ip.ipv4_addr && client_info_v4_.count(it->dst_ipv4_addr) > 0) + || (it->dst_ipv4_addr == client->ip.ipv4_addr && client_info_v4_.count(it->src_ipv4_addr) > 0) ) + { + IPACMDBG("Found a cache connection for src client 0x%08x and dst client 0x%08x.\n", it->src_ipv4_addr, it->dst_ipv4_addr); + ipacm_cmd_q_data evt; + ipacm_event_connection* conn; + + conn = (ipacm_event_connection*)malloc(sizeof(ipacm_event_connection)); + if(conn == NULL) + { + IPACMERR("Failed to allocate memory for new_connection event.\n"); + return; + } + memcpy(conn, &(*it), sizeof(ipacm_event_connection)); + + memset(&evt, 0, sizeof(evt)); + evt.event = IPA_LAN_TO_LAN_NEW_CONNECTION; + evt.evt_data = (void*)conn; + IPACM_EvtDispatcher::PostEvt(&evt); + + it = connection_v4_.erase(it); + IPACMDBG_H("Now the number of cache connections is %d.\n", connection_v4_.size()); + } + else + { + it++; + } + } + } + else + { + uint64_t src_v6_addr, dst_v6_addr; + it = connection_v6_.begin(); + while(it != connection_v6_.end()) + { + memcpy(&src_v6_addr, &(it->src_ipv6_addr[2]), sizeof(uint64_t)); + memcpy(&dst_v6_addr, &(it->dst_ipv6_addr[2]), sizeof(uint64_t)); + if( (memcmp(it->src_ipv6_addr, client->ip.ipv6_addr, 4*sizeof(uint32_t)) == 0 && client_info_v6_.count(dst_v6_addr) > 0) + || (memcmp(it->dst_ipv6_addr, client->ip.ipv6_addr, 4*sizeof(uint32_t)) == 0 && client_info_v6_.count(src_v6_addr) > 0) ) + { + IPACMDBG("Found a cache connection with src client 0x%08x%08x%08x%08x and dst client 0x%08x%08x%08x%08x.\n", it->src_ipv6_addr[0], + it->src_ipv6_addr[1], it->src_ipv6_addr[2], it->src_ipv6_addr[3], it->dst_ipv6_addr[0], it->dst_ipv6_addr[1], + it->dst_ipv6_addr[2], it->dst_ipv6_addr[3]); + ipacm_cmd_q_data evt; + ipacm_event_connection* conn; + + conn = (ipacm_event_connection*)malloc(sizeof(ipacm_event_connection)); + if(conn == NULL) + { + IPACMERR("Failed to allocate memory for new_connection event.\n"); + return; + } + memcpy(conn, &(*it), sizeof(ipacm_event_connection)); + + memset(&evt, 0, sizeof(evt)); + evt.event = IPA_LAN_TO_LAN_NEW_CONNECTION; + evt.evt_data = (void*)conn; + IPACM_EvtDispatcher::PostEvt(&evt); + + it = connection_v6_.erase(it); + IPACMDBG_H("Now the number of cache connections is %d.\n", connection_v6_.size()); + } + else + { + it++; + } + } + } +#endif + return; +} diff --git a/data-ipa-cfg-mgr/ipacm/src/IPACM_Log.cpp b/data-ipa-cfg-mgr/ipacm/src/IPACM_Log.cpp new file mode 100644 index 000000000..20dd26c07 --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/src/IPACM_Log.cpp @@ -0,0 +1,107 @@ +/* +Copyright (c) 2013, The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +/*! + @file + IPACM_log.cpp + + @brief + This file implements the IPAM log functionality. + + @Author + Skylar Chang + +*/ +#include "IPACM_Log.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void logmessage(int log_level) +{ + return; +} + +/* start IPACMDIAG socket*/ +int create_socket(unsigned int *sockfd) +{ + + if ((*sockfd = socket(AF_UNIX, SOCK_DGRAM, 0)) == IPACM_FAILURE) + { + perror("Error creating ipacm_log socket\n"); + return IPACM_FAILURE; + } + + if(fcntl(*sockfd, F_SETFD, FD_CLOEXEC) < 0) + { + perror("Couldn't set ipacm_log Close on Exec\n"); + } + + return IPACM_SUCCESS; +} + +void ipacm_log_send( void * user_data) +{ + ipacm_log_buffer_t ipacm_log_buffer; + int numBytes=0, len; + struct sockaddr_un ipacmlog_socket; + static unsigned int ipacm_log_sockfd = 0; + + if(ipacm_log_sockfd == 0) + { + /* start ipacm_log socket */ + if(create_socket(&ipacm_log_sockfd) < 0) + { + printf("unable to create ipacm_log socket\n"); + return; + } + printf("create ipacm_log socket successfully\n"); + } + ipacmlog_socket.sun_family = AF_UNIX; + strcpy(ipacmlog_socket.sun_path, IPACMLOG_FILE); + len = strlen(ipacmlog_socket.sun_path) + sizeof(ipacmlog_socket.sun_family); + + memcpy(ipacm_log_buffer.user_data, user_data, MAX_BUF_LEN); + + //printf("send : %s\n", ipacm_log_buffer.user_data); + if ((numBytes = sendto(ipacm_log_sockfd, (void *)&ipacm_log_buffer, sizeof(ipacm_log_buffer.user_data), 0, + (struct sockaddr *)&ipacmlog_socket, len)) == -1) + { + printf("Send Failed(%d) %s \n",errno,strerror(errno)); + return; + } + return; +} diff --git a/data-ipa-cfg-mgr/ipacm/src/IPACM_Main.cpp b/data-ipa-cfg-mgr/ipacm/src/IPACM_Main.cpp new file mode 100644 index 000000000..fa8756ea3 --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/src/IPACM_Main.cpp @@ -0,0 +1,979 @@ +/* +Copyright (c) 2013, The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +/*! + @file + IPACM_Main.cpp + + @brief + This file implements the IPAM functionality. + + @Author + Skylar Chang + +*/ +/****************************************************************************** + + IPCM_MAIN.C + +******************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "linux/ipa_qmi_service_v01.h" + +#define __stringify_1(x...) #x +#define __stringify(x...) __stringify_1(x) + +#include "IPACM_CmdQueue.h" +#include "IPACM_EvtDispatcher.h" +#include "IPACM_Defs.h" +#include "IPACM_Neighbor.h" +#include "IPACM_IfaceManager.h" +#include "IPACM_Log.h" + +#include "IPACM_ConntrackListener.h" +#include "IPACM_ConntrackClient.h" +#include "IPACM_Netlink.h" + +/* not defined(FEATURE_IPA_ANDROID)*/ +#ifndef FEATURE_IPA_ANDROID +#include "IPACM_LanToLan.h" +#endif + + +const char *ipacm_event_name[] = { + __stringify(IPA_CFG_CHANGE_EVENT), /* 1 NULL */ + __stringify(IPA_LINK_UP_EVENT), /* 2 ipacm_event_data_fid */ + __stringify(IPA_LINK_DOWN_EVENT), /* 3 ipacm_event_data_fid */ + __stringify(IPA_ADDR_ADD_EVENT), /* 4 ipacm_event_data_addr */ + __stringify(IPA_ADDR_DEL_EVENT), /* 5 no use */ + __stringify(IPA_ROUTE_ADD_EVENT), /* 6 ipacm_event_data_addr */ + __stringify(IPA_ROUTE_DEL_EVENT), /* 7 ipacm_event_data_addr */ + __stringify(IPA_FIREWALL_CHANGE_EVENT), /* 8 NULL */ + __stringify(IPA_WLAN_AP_LINK_UP_EVENT), /* 9 ipacm_event_data_mac */ + __stringify(IPA_WLAN_STA_LINK_UP_EVENT), /* 10 ipacm_event_data_mac */ + __stringify(IPA_WLAN_CLIENT_ADD_EVENT), /* 11 ipacm_event_data_mac */ + __stringify(IPA_WLAN_CLIENT_DEL_EVENT), /* 12 ipacm_event_data_mac */ + __stringify(IPA_WLAN_CLIENT_POWER_SAVE_EVENT), /* 13 ipacm_event_data_mac */ + __stringify(IPA_WLAN_CLIENT_RECOVER_EVENT), /* 14 ipacm_event_data_mac */ + __stringify(IPA_NEW_NEIGH_EVENT), /* 15 ipacm_event_data_all */ + __stringify(IPA_DEL_NEIGH_EVENT), /* 16 ipacm_event_data_all */ + __stringify(IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT), /* 17 ipacm_event_data_all */ + __stringify(IPA_NEIGH_CLIENT_IP_ADDR_DEL_EVENT), /* 18 ipacm_event_data_all */ + __stringify(IPA_SW_ROUTING_ENABLE), /* 19 NULL */ + __stringify(IPA_SW_ROUTING_DISABLE), /* 20 NULL */ + __stringify(IPA_PROCESS_CT_MESSAGE), /* 21 ipacm_ct_evt_data */ + __stringify(IPA_HANDLE_WAN_UP), /* 22 ipacm_event_iface_up */ + __stringify(IPA_HANDLE_WAN_DOWN), /* 23 ipacm_event_iface_up */ + __stringify(IPA_HANDLE_WLAN_UP), /* 24 ipacm_event_iface_up */ + __stringify(IPA_HANDLE_LAN_UP), /* 25 ipacm_event_iface_up */ + __stringify(IPA_WLAN_CLIENT_ADD_EVENT_EX), /* 26 ipacm_event_data_wlan_ex */ + __stringify(IPA_HANDLE_WAN_UP_V6), /* 27 NULL */ + __stringify(IPA_HANDLE_WAN_DOWN_V6), /* 28 NULL */ + __stringify(IPA_LAN_CLIENT_ACTIVE), /* 29 ipacm_event_lan_client*/ + __stringify(IPA_LAN_CLIENT_INACTIVE), /* 30 ipacm_event_lan_client*/ + __stringify(IPA_LAN_CLIENT_DISCONNECT), /* 31 ipacm_event_lan_client*/ + __stringify(IPA_LAN_CLIENT_POWER_SAVE), /* 32 ipacm_event_lan_client*/ + __stringify(IPA_LAN_CLIENT_POWER_RECOVER), /* 33 ipacm_event_lan_client*/ + __stringify(IPA_LAN_TO_LAN_NEW_CONNECTION), /* 34 ipacm_event_connection */ + __stringify(IPA_LAN_TO_LAN_DEL_CONNECTION), /* 35 ipacm_event_connection */ + __stringify(IPA_LAN_DELETE_SELF), /* 36 ipacm_event_data_fid */ + __stringify(IPA_WLAN_LINK_DOWN_EVENT), /* 37 ipacm_event_data_mac */ + __stringify(IPA_USB_LINK_UP_EVENT), /* 38 ipacm_event_data_fid */ + __stringify(IPA_PROCESS_CT_MESSAGE_V6), /* 39 ipacm_ct_evt_data */ + __stringify(IPA_PRIVATE_SUBNET_CHANGE_EVENT), /* 40 ipacm_event_data_fid */ + __stringify(IPA_WAN_UPSTREAM_ROUTE_ADD_EVENT), /* 41 ipacm_event_data_fid */ + __stringify(IPA_WAN_UPSTREAM_ROUTE_DEL_EVENT), /* 42 ipacm_event_data_fid */ + __stringify(IPA_WAN_XLAT_CONNECT_EVENT), /* 43 ipacm_event_data_fid */ +}; + +#define IPA_DRIVER "/dev/ipa" + +#define IPACM_FIREWALL_FILE_NAME "mobileap_firewall.xml" +#define IPACM_CFG_FILE_NAME "IPACM_cfg.xml" +#ifdef FEATURE_IPA_ANDROID +#define IPACM_PID_FILE "/data/misc/ipa/ipacm.pid" +#define IPACM_DIR_NAME "/data" +#else/* defined(FEATURE_IPA_ANDROID) */ +#define IPACM_PID_FILE "/etc/ipacm.pid" +#define IPACM_DIR_NAME "/etc" +#endif /* defined(NOT FEATURE_IPA_ANDROID)*/ +#define IPACM_NAME "ipacm" + +#define INOTIFY_EVENT_SIZE (sizeof(struct inotify_event)) +#define INOTIFY_BUF_LEN (INOTIFY_EVENT_SIZE + 2*sizeof(IPACM_FIREWALL_FILE_NAME)) + +#define IPA_DRIVER_WLAN_EVENT_MAX_OF_ATTRIBS 3 +#define IPA_DRIVER_WLAN_EVENT_SIZE (sizeof(struct ipa_wlan_msg_ex)+ IPA_DRIVER_WLAN_EVENT_MAX_OF_ATTRIBS*sizeof(ipa_wlan_hdr_attrib_val)) +#define IPA_DRIVER_PIPE_STATS_EVENT_SIZE (sizeof(struct ipa_get_data_stats_resp_msg_v01)) +#define IPA_DRIVER_WLAN_META_MSG (sizeof(struct ipa_msg_meta)) +#define IPA_DRIVER_WLAN_BUF_LEN (IPA_DRIVER_PIPE_STATS_EVENT_SIZE + IPA_DRIVER_WLAN_META_MSG) + +uint32_t ipacm_event_stats[IPACM_EVENT_MAX]; +bool ipacm_logging = true; + +void ipa_is_ipacm_running(void); +int ipa_get_if_index(char *if_name, int *if_index); + +/* start netlink socket monitor*/ +void* netlink_start(void *param) +{ + ipa_nl_sk_fd_set_info_t sk_fdset; + int ret_val = 0; + memset(&sk_fdset, 0, sizeof(ipa_nl_sk_fd_set_info_t)); + IPACMDBG_H("netlink starter memset sk_fdset succeeds\n"); + ret_val = ipa_nl_listener_init(NETLINK_ROUTE, (RTMGRP_IPV4_ROUTE | RTMGRP_IPV6_ROUTE | RTMGRP_LINK | + RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR | RTMGRP_NEIGH | + RTNLGRP_IPV6_PREFIX), + &sk_fdset, ipa_nl_recv_msg); + + if (ret_val != IPACM_SUCCESS) + { + IPACMERR("Failed to initialize IPA netlink event listener\n"); + return NULL; + } + + return NULL; +} + +/* start firewall-rule monitor*/ +void* firewall_monitor(void *param) +{ + int length; + int wd; + char buffer[INOTIFY_BUF_LEN]; + int inotify_fd; + ipacm_cmd_q_data evt_data; + uint32_t mask = IN_MODIFY | IN_MOVE; + + inotify_fd = inotify_init(); + if (inotify_fd < 0) + { + PERROR("inotify_init"); + } + + IPACMDBG_H("Waiting for nofications in dir %s with mask: 0x%x\n", IPACM_DIR_NAME, mask); + + wd = inotify_add_watch(inotify_fd, + IPACM_DIR_NAME, + mask); + + while (1) + { + length = read(inotify_fd, buffer, INOTIFY_BUF_LEN); + if (length < 0) + { + IPACMERR("inotify read() error return length: %d and mask: 0x%x\n", length, mask); + continue; + } + + struct inotify_event* event; + event = (struct inotify_event*)malloc(length); + if(event == NULL) + { + IPACMERR("Failed to allocate memory.\n"); + return NULL; + } + memset(event, 0, length); + memcpy(event, buffer, length); + + if (event->len > 0) + { + if ( (event->mask & IN_MODIFY) || (event->mask & IN_MOVE)) + { + if (event->mask & IN_ISDIR) + { + IPACMDBG_H("The directory %s was 0x%x\n", event->name, event->mask); + } + else if (!strncmp(event->name, IPACM_FIREWALL_FILE_NAME, event->len)) // firewall_rule change + { + IPACMDBG_H("File \"%s\" was 0x%x\n", event->name, event->mask); + IPACMDBG_H("The interested file %s .\n", IPACM_FIREWALL_FILE_NAME); + + evt_data.event = IPA_FIREWALL_CHANGE_EVENT; + evt_data.evt_data = NULL; + + /* Insert IPA_FIREWALL_CHANGE_EVENT to command queue */ + IPACM_EvtDispatcher::PostEvt(&evt_data); + } + else if (!strncmp(event->name, IPACM_CFG_FILE_NAME, event->len)) // IPACM_configuration change + { + IPACMDBG_H("File \"%s\" was 0x%x\n", event->name, event->mask); + IPACMDBG_H("The interested file %s .\n", IPACM_CFG_FILE_NAME); + + evt_data.event = IPA_CFG_CHANGE_EVENT; + evt_data.evt_data = NULL; + + /* Insert IPA_FIREWALL_CHANGE_EVENT to command queue */ + IPACM_EvtDispatcher::PostEvt(&evt_data); + } + } + IPACMDBG_H("Received monitoring event %s.\n", event->name); + } + free(event); + } + + (void)inotify_rm_watch(inotify_fd, wd); + (void)close(inotify_fd); + return NULL; +} + + +/* start IPACM wan-driver notifier */ +void* ipa_driver_msg_notifier(void *param) +{ + int length, fd, cnt; + char buffer[IPA_DRIVER_WLAN_BUF_LEN]; + struct ipa_msg_meta event_hdr; + struct ipa_ecm_msg event_ecm; + struct ipa_wan_msg event_wan; + struct ipa_wlan_msg_ex event_ex_o; + struct ipa_wlan_msg *event_wlan=NULL; + struct ipa_wlan_msg_ex *event_ex= NULL; + struct ipa_get_data_stats_resp_msg_v01 event_data_stats; + struct ipa_get_apn_data_stats_resp_msg_v01 event_network_stats; + + ipacm_cmd_q_data evt_data; + ipacm_event_data_mac *data = NULL; + ipacm_event_data_fid *data_fid = NULL; + ipacm_event_data_iptype *data_iptype = NULL; + ipacm_event_data_wlan_ex *data_ex; + ipa_get_data_stats_resp_msg_v01 *data_tethering_stats = NULL; + ipa_get_apn_data_stats_resp_msg_v01 *data_network_stats = NULL; + + ipacm_cmd_q_data new_neigh_evt; + ipacm_event_data_all* new_neigh_data; + + fd = open(IPA_DRIVER, O_RDWR); + if (fd < 0) + { + IPACMERR("Failed opening %s.\n", IPA_DRIVER); + return NULL; + } + + while (1) + { + IPACMDBG_H("Waiting for nofications from IPA driver \n"); + memset(buffer, 0, sizeof(buffer)); + memset(&evt_data, 0, sizeof(evt_data)); + memset(&new_neigh_evt, 0, sizeof(ipacm_cmd_q_data)); + new_neigh_data = NULL; + data = NULL; + data_fid = NULL; + data_tethering_stats = NULL; + data_network_stats = NULL; + + length = read(fd, buffer, IPA_DRIVER_WLAN_BUF_LEN); + if (length < 0) + { + PERROR("didn't read IPA_driver correctly"); + continue; + } + + memcpy(&event_hdr, buffer,sizeof(struct ipa_msg_meta)); + IPACMDBG_H("Message type: %d\n", event_hdr.msg_type); + IPACMDBG_H("Event header length received: %d\n",event_hdr.msg_len); + + /* Insert WLAN_DRIVER_EVENT to command queue */ + switch (event_hdr.msg_type) + { + + case SW_ROUTING_ENABLE: + IPACMDBG_H("Received SW_ROUTING_ENABLE\n"); + evt_data.event = IPA_SW_ROUTING_ENABLE; + IPACMDBG_H("Not supported anymore\n"); + continue; + + case SW_ROUTING_DISABLE: + IPACMDBG_H("Received SW_ROUTING_DISABLE\n"); + evt_data.event = IPA_SW_ROUTING_DISABLE; + IPACMDBG_H("Not supported anymore\n"); + continue; + + case WLAN_AP_CONNECT: + event_wlan = (struct ipa_wlan_msg *) (buffer + sizeof(struct ipa_msg_meta)); + IPACMDBG_H("Received WLAN_AP_CONNECT name: %s\n",event_wlan->name); + IPACMDBG_H("AP Mac Address %02x:%02x:%02x:%02x:%02x:%02x\n", + event_wlan->mac_addr[0], event_wlan->mac_addr[1], event_wlan->mac_addr[2], + event_wlan->mac_addr[3], event_wlan->mac_addr[4], event_wlan->mac_addr[5]); + data_fid = (ipacm_event_data_fid *)malloc(sizeof(ipacm_event_data_fid)); + if(data_fid == NULL) + { + IPACMERR("unable to allocate memory for event_wlan data_fid\n"); + return NULL; + } + ipa_get_if_index(event_wlan->name, &(data_fid->if_index)); + evt_data.event = IPA_WLAN_AP_LINK_UP_EVENT; + evt_data.evt_data = data_fid; + break; + + case WLAN_AP_DISCONNECT: + event_wlan = (struct ipa_wlan_msg *)(buffer + sizeof(struct ipa_msg_meta)); + IPACMDBG_H("Received WLAN_AP_DISCONNECT name: %s\n",event_wlan->name); + IPACMDBG_H("AP Mac Address %02x:%02x:%02x:%02x:%02x:%02x\n", + event_wlan->mac_addr[0], event_wlan->mac_addr[1], event_wlan->mac_addr[2], + event_wlan->mac_addr[3], event_wlan->mac_addr[4], event_wlan->mac_addr[5]); + data_fid = (ipacm_event_data_fid *)malloc(sizeof(ipacm_event_data_fid)); + if(data_fid == NULL) + { + IPACMERR("unable to allocate memory for event_wlan data_fid\n"); + return NULL; + } + ipa_get_if_index(event_wlan->name, &(data_fid->if_index)); + evt_data.event = IPA_WLAN_LINK_DOWN_EVENT; + evt_data.evt_data = data_fid; + break; + case WLAN_STA_CONNECT: + event_wlan = (struct ipa_wlan_msg *)(buffer + sizeof(struct ipa_msg_meta)); + IPACMDBG_H("Received WLAN_STA_CONNECT name: %s\n",event_wlan->name); + IPACMDBG_H("STA Mac Address %02x:%02x:%02x:%02x:%02x:%02x\n", + event_wlan->mac_addr[0], event_wlan->mac_addr[1], event_wlan->mac_addr[2], + event_wlan->mac_addr[3], event_wlan->mac_addr[4], event_wlan->mac_addr[5]); + data = (ipacm_event_data_mac *)malloc(sizeof(ipacm_event_data_mac)); + if(data == NULL) + { + IPACMERR("unable to allocate memory for event_wlan data_fid\n"); + return NULL; + } + memcpy(data->mac_addr, + event_wlan->mac_addr, + sizeof(event_wlan->mac_addr)); + ipa_get_if_index(event_wlan->name, &(data->if_index)); + evt_data.event = IPA_WLAN_STA_LINK_UP_EVENT; + evt_data.evt_data = data; + break; + + case WLAN_STA_DISCONNECT: + event_wlan = (struct ipa_wlan_msg *)(buffer + sizeof(struct ipa_msg_meta)); + IPACMDBG_H("Received WLAN_STA_DISCONNECT name: %s\n",event_wlan->name); + IPACMDBG_H("STA Mac Address %02x:%02x:%02x:%02x:%02x:%02x\n", + event_wlan->mac_addr[0], event_wlan->mac_addr[1], event_wlan->mac_addr[2], + event_wlan->mac_addr[3], event_wlan->mac_addr[4], event_wlan->mac_addr[5]); + data_fid = (ipacm_event_data_fid *)malloc(sizeof(ipacm_event_data_fid)); + if(data_fid == NULL) + { + IPACMERR("unable to allocate memory for event_wlan data_fid\n"); + return NULL; + } + ipa_get_if_index(event_wlan->name, &(data_fid->if_index)); + evt_data.event = IPA_WLAN_LINK_DOWN_EVENT; + evt_data.evt_data = data_fid; + break; + + case WLAN_CLIENT_CONNECT: + event_wlan = (struct ipa_wlan_msg *)(buffer + sizeof(struct ipa_msg_meta)); + IPACMDBG_H("Received WLAN_CLIENT_CONNECT\n"); + IPACMDBG_H("Mac Address %02x:%02x:%02x:%02x:%02x:%02x\n", + event_wlan->mac_addr[0], event_wlan->mac_addr[1], event_wlan->mac_addr[2], + event_wlan->mac_addr[3], event_wlan->mac_addr[4], event_wlan->mac_addr[5]); + data = (ipacm_event_data_mac *)malloc(sizeof(ipacm_event_data_mac)); + if (data == NULL) + { + IPACMERR("unable to allocate memory for event_wlan data\n"); + return NULL; + } + memcpy(data->mac_addr, + event_wlan->mac_addr, + sizeof(event_wlan->mac_addr)); + ipa_get_if_index(event_wlan->name, &(data->if_index)); + evt_data.event = IPA_WLAN_CLIENT_ADD_EVENT; + evt_data.evt_data = data; + break; + + case WLAN_CLIENT_CONNECT_EX: + IPACMDBG_H("Received WLAN_CLIENT_CONNECT_EX\n"); + + memcpy(&event_ex_o, buffer + sizeof(struct ipa_msg_meta),sizeof(struct ipa_wlan_msg_ex)); + if(event_ex_o.num_of_attribs > IPA_DRIVER_WLAN_EVENT_MAX_OF_ATTRIBS) + { + IPACMERR("buffer size overflow\n"); + return NULL; + } + length = sizeof(ipa_wlan_msg_ex)+ event_ex_o.num_of_attribs * sizeof(ipa_wlan_hdr_attrib_val); + IPACMDBG_H("num_of_attribs %d, length %d\n", event_ex_o.num_of_attribs, length); + event_ex = (ipa_wlan_msg_ex *)malloc(length); + if(event_ex == NULL ) + { + IPACMERR("Unable to allocate memory\n"); + return NULL; + } + memcpy(event_ex, buffer + sizeof(struct ipa_msg_meta), length); + data_ex = (ipacm_event_data_wlan_ex *)malloc(sizeof(ipacm_event_data_wlan_ex) + event_ex_o.num_of_attribs * sizeof(ipa_wlan_hdr_attrib_val)); + if (data_ex == NULL) + { + IPACMERR("unable to allocate memory for event data\n"); + return NULL; + } + data_ex->num_of_attribs = event_ex->num_of_attribs; + + memcpy(data_ex->attribs, + event_ex->attribs, + event_ex->num_of_attribs * sizeof(ipa_wlan_hdr_attrib_val)); + + ipa_get_if_index(event_ex->name, &(data_ex->if_index)); + evt_data.event = IPA_WLAN_CLIENT_ADD_EVENT_EX; + evt_data.evt_data = data_ex; + + /* Construct new_neighbor msg with netdev device internally */ + new_neigh_data = (ipacm_event_data_all*)malloc(sizeof(ipacm_event_data_all)); + if(new_neigh_data == NULL) + { + IPACMERR("Failed to allocate memory.\n"); + return NULL; + } + memset(new_neigh_data, 0, sizeof(ipacm_event_data_all)); + new_neigh_data->iptype = IPA_IP_v6; + for(cnt = 0; cnt < event_ex->num_of_attribs; cnt++) + { + if(event_ex->attribs[cnt].attrib_type == WLAN_HDR_ATTRIB_MAC_ADDR) + { + memcpy(new_neigh_data->mac_addr, event_ex->attribs[cnt].u.mac_addr, sizeof(new_neigh_data->mac_addr)); + IPACMDBG_H("Mac Address %02x:%02x:%02x:%02x:%02x:%02x\n", + event_ex->attribs[cnt].u.mac_addr[0], event_ex->attribs[cnt].u.mac_addr[1], event_ex->attribs[cnt].u.mac_addr[2], + event_ex->attribs[cnt].u.mac_addr[3], event_ex->attribs[cnt].u.mac_addr[4], event_ex->attribs[cnt].u.mac_addr[5]); + } + else if(event_ex->attribs[cnt].attrib_type == WLAN_HDR_ATTRIB_STA_ID) + { + IPACMDBG_H("Wlan client id %d\n",event_ex->attribs[cnt].u.sta_id); + } + else + { + IPACMDBG_H("Wlan message has unexpected type!\n"); + } + } + new_neigh_data->if_index = data_ex->if_index; + new_neigh_evt.evt_data = (void*)new_neigh_data; + new_neigh_evt.event = IPA_NEW_NEIGH_EVENT; + free(event_ex); + break; + + case WLAN_CLIENT_DISCONNECT: + IPACMDBG_H("Received WLAN_CLIENT_DISCONNECT\n"); + event_wlan = (struct ipa_wlan_msg *)(buffer + sizeof(struct ipa_msg_meta)); + IPACMDBG_H("Mac Address %02x:%02x:%02x:%02x:%02x:%02x\n", + event_wlan->mac_addr[0], event_wlan->mac_addr[1], event_wlan->mac_addr[2], + event_wlan->mac_addr[3], event_wlan->mac_addr[4], event_wlan->mac_addr[5]); + data = (ipacm_event_data_mac *)malloc(sizeof(ipacm_event_data_mac)); + if (data == NULL) + { + IPACMERR("unable to allocate memory for event_wlan data\n"); + return NULL; + } + memcpy(data->mac_addr, + event_wlan->mac_addr, + sizeof(event_wlan->mac_addr)); + ipa_get_if_index(event_wlan->name, &(data->if_index)); + evt_data.event = IPA_WLAN_CLIENT_DEL_EVENT; + evt_data.evt_data = data; + break; + + case WLAN_CLIENT_POWER_SAVE_MODE: + IPACMDBG_H("Received WLAN_CLIENT_POWER_SAVE_MODE\n"); + event_wlan = (struct ipa_wlan_msg *)(buffer + sizeof(struct ipa_msg_meta)); + IPACMDBG_H("Mac Address %02x:%02x:%02x:%02x:%02x:%02x\n", + event_wlan->mac_addr[0], event_wlan->mac_addr[1], event_wlan->mac_addr[2], + event_wlan->mac_addr[3], event_wlan->mac_addr[4], event_wlan->mac_addr[5]); + data = (ipacm_event_data_mac *)malloc(sizeof(ipacm_event_data_mac)); + if (data == NULL) + { + IPACMERR("unable to allocate memory for event_wlan data\n"); + return NULL; + } + memcpy(data->mac_addr, + event_wlan->mac_addr, + sizeof(event_wlan->mac_addr)); + ipa_get_if_index(event_wlan->name, &(data->if_index)); + evt_data.event = IPA_WLAN_CLIENT_POWER_SAVE_EVENT; + evt_data.evt_data = data; + break; + + case WLAN_CLIENT_NORMAL_MODE: + IPACMDBG_H("Received WLAN_CLIENT_NORMAL_MODE\n"); + event_wlan = (struct ipa_wlan_msg *)(buffer + sizeof(struct ipa_msg_meta)); + IPACMDBG_H("Mac Address %02x:%02x:%02x:%02x:%02x:%02x\n", + event_wlan->mac_addr[0], event_wlan->mac_addr[1], event_wlan->mac_addr[2], + event_wlan->mac_addr[3], event_wlan->mac_addr[4], event_wlan->mac_addr[5]); + data = (ipacm_event_data_mac *)malloc(sizeof(ipacm_event_data_mac)); + if (data == NULL) + { + IPACMERR("unable to allocate memory for event_wlan data\n"); + return NULL; + } + memcpy(data->mac_addr, + event_wlan->mac_addr, + sizeof(event_wlan->mac_addr)); + ipa_get_if_index(event_wlan->name, &(data->if_index)); + evt_data.evt_data = data; + evt_data.event = IPA_WLAN_CLIENT_RECOVER_EVENT; + break; + + case ECM_CONNECT: + memcpy(&event_ecm, buffer + sizeof(struct ipa_msg_meta), sizeof(struct ipa_ecm_msg)); + IPACMDBG_H("Received ECM_CONNECT name: %s\n",event_ecm.name); + data_fid = (ipacm_event_data_fid *)malloc(sizeof(ipacm_event_data_fid)); + if(data_fid == NULL) + { + IPACMERR("unable to allocate memory for event_ecm data_fid\n"); + return NULL; + } + data_fid->if_index = event_ecm.ifindex; + evt_data.event = IPA_USB_LINK_UP_EVENT; + evt_data.evt_data = data_fid; + break; + + case ECM_DISCONNECT: + memcpy(&event_ecm, buffer + sizeof(struct ipa_msg_meta), sizeof(struct ipa_ecm_msg)); + IPACMDBG_H("Received ECM_DISCONNECT name: %s\n",event_ecm.name); + data_fid = (ipacm_event_data_fid *)malloc(sizeof(ipacm_event_data_fid)); + if(data_fid == NULL) + { + IPACMERR("unable to allocate memory for event_ecm data_fid\n"); + return NULL; + } + data_fid->if_index = event_ecm.ifindex; + evt_data.event = IPA_LINK_DOWN_EVENT; + evt_data.evt_data = data_fid; + break; + /* Add for 8994 Android case */ + case WAN_UPSTREAM_ROUTE_ADD: + memcpy(&event_wan, buffer + sizeof(struct ipa_msg_meta), sizeof(struct ipa_wan_msg)); + IPACMDBG_H("Received WAN_UPSTREAM_ROUTE_ADD name: %s, tethered name: %s\n", event_wan.upstream_ifname, event_wan.tethered_ifname); + data_iptype = (ipacm_event_data_iptype *)malloc(sizeof(ipacm_event_data_iptype)); + if(data_iptype == NULL) + { + IPACMERR("unable to allocate memory for event_ecm data_iptype\n"); + return NULL; + } + ipa_get_if_index(event_wan.upstream_ifname, &(data_iptype->if_index)); + ipa_get_if_index(event_wan.tethered_ifname, &(data_iptype->if_index_tether)); + data_iptype->iptype = event_wan.ip; + IPACMDBG_H("Received WAN_UPSTREAM_ROUTE_ADD: fid(%d) tether_fid(%d) ip-type(%d)\n", data_iptype->if_index, + data_iptype->if_index_tether, data_iptype->iptype); + evt_data.event = IPA_WAN_UPSTREAM_ROUTE_ADD_EVENT; + evt_data.evt_data = data_iptype; + break; + case WAN_UPSTREAM_ROUTE_DEL: + memcpy(&event_wan, buffer + sizeof(struct ipa_msg_meta), sizeof(struct ipa_wan_msg)); + IPACMDBG_H("Received WAN_UPSTREAM_ROUTE_DEL name: %s, tethered name: %s\n", event_wan.upstream_ifname, event_wan.tethered_ifname); + data_iptype = (ipacm_event_data_iptype *)malloc(sizeof(ipacm_event_data_iptype)); + if(data_iptype == NULL) + { + IPACMERR("unable to allocate memory for event_ecm data_iptype\n"); + return NULL; + } + ipa_get_if_index(event_wan.upstream_ifname, &(data_iptype->if_index)); + ipa_get_if_index(event_wan.tethered_ifname, &(data_iptype->if_index_tether)); + data_iptype->iptype = event_wan.ip; + IPACMDBG_H("Received WAN_UPSTREAM_ROUTE_DEL: fid(%d) ip-type(%d)\n", data_iptype->if_index, data_iptype->iptype); + evt_data.event = IPA_WAN_UPSTREAM_ROUTE_DEL_EVENT; + evt_data.evt_data = data_iptype; + break; + /* End of adding for 8994 Android case */ + + /* Add for embms case */ + case WAN_EMBMS_CONNECT: + memcpy(&event_wan, buffer + sizeof(struct ipa_msg_meta), sizeof(struct ipa_wan_msg)); + IPACMDBG("Received WAN_EMBMS_CONNECT name: %s\n",event_wan.upstream_ifname); + data_fid = (ipacm_event_data_fid *)malloc(sizeof(ipacm_event_data_fid)); + if(data_fid == NULL) + { + IPACMERR("unable to allocate memory for event data_fid\n"); + return NULL; + } + ipa_get_if_index(event_wan.upstream_ifname, &(data_fid->if_index)); + evt_data.event = IPA_WAN_EMBMS_LINK_UP_EVENT; + evt_data.evt_data = data_fid; + break; + + case WLAN_SWITCH_TO_SCC: + IPACMDBG_H("Received WLAN_SWITCH_TO_SCC\n"); + case WLAN_WDI_ENABLE: + IPACMDBG_H("Received WLAN_WDI_ENABLE\n"); + if (IPACM_Iface::ipacmcfg->isMCC_Mode == true) + { + IPACM_Iface::ipacmcfg->isMCC_Mode = false; + evt_data.event = IPA_WLAN_SWITCH_TO_SCC; + break; + } + continue; + case WLAN_SWITCH_TO_MCC: + IPACMDBG_H("Received WLAN_SWITCH_TO_MCC\n"); + case WLAN_WDI_DISABLE: + IPACMDBG_H("Received WLAN_WDI_DISABLE\n"); + if (IPACM_Iface::ipacmcfg->isMCC_Mode == false) + { + IPACM_Iface::ipacmcfg->isMCC_Mode = true; + evt_data.event = IPA_WLAN_SWITCH_TO_MCC; + break; + } + continue; + + case WAN_XLAT_CONNECT: + memcpy(&event_wan, buffer + sizeof(struct ipa_msg_meta), + sizeof(struct ipa_wan_msg)); + IPACMDBG_H("Received WAN_XLAT_CONNECT name: %s\n", + event_wan.upstream_ifname); + + /* post IPA_LINK_UP_EVENT event + * may be WAN interface is not up + */ + data_fid = (ipacm_event_data_fid *)calloc(1, sizeof(ipacm_event_data_fid)); + if(data_fid == NULL) + { + IPACMERR("unable to allocate memory for xlat event\n"); + return NULL; + } + ipa_get_if_index(event_wan.upstream_ifname, &(data_fid->if_index)); + evt_data.event = IPA_LINK_UP_EVENT; + evt_data.evt_data = data_fid; + IPACMDBG_H("Posting IPA_LINK_UP_EVENT event:%d\n", evt_data.event); + IPACM_EvtDispatcher::PostEvt(&evt_data); + + /* post IPA_WAN_XLAT_CONNECT_EVENT event */ + memset(&evt_data, 0, sizeof(evt_data)); + data_fid = (ipacm_event_data_fid *)calloc(1, sizeof(ipacm_event_data_fid)); + if(data_fid == NULL) + { + IPACMERR("unable to allocate memory for xlat event\n"); + return NULL; + } + ipa_get_if_index(event_wan.upstream_ifname, &(data_fid->if_index)); + evt_data.event = IPA_WAN_XLAT_CONNECT_EVENT; + evt_data.evt_data = data_fid; + IPACMDBG_H("Posting IPA_WAN_XLAT_CONNECT_EVENT event:%d\n", evt_data.event); + break; + + case IPA_TETHERING_STATS_UPDATE_STATS: + memcpy(&event_data_stats, buffer + sizeof(struct ipa_msg_meta), sizeof(struct ipa_get_data_stats_resp_msg_v01)); + data_tethering_stats = (ipa_get_data_stats_resp_msg_v01 *)malloc(sizeof(struct ipa_get_data_stats_resp_msg_v01)); + if(data_tethering_stats == NULL) + { + IPACMERR("unable to allocate memory for event data_tethering_stats\n"); + return NULL; + } + memcpy(data_tethering_stats, + &event_data_stats, + sizeof(struct ipa_get_data_stats_resp_msg_v01)); + IPACMDBG("Received IPA_TETHERING_STATS_UPDATE_STATS ipa_stats_type: %d\n",data_tethering_stats->ipa_stats_type); + IPACMDBG("Received %d UL, %d DL pipe stats\n",data_tethering_stats->ul_src_pipe_stats_list_len, data_tethering_stats->dl_dst_pipe_stats_list_len); + evt_data.event = IPA_TETHERING_STATS_UPDATE_EVENT; + evt_data.evt_data = data_tethering_stats; + break; + + case IPA_TETHERING_STATS_UPDATE_NETWORK_STATS: + memcpy(&event_network_stats, buffer + sizeof(struct ipa_msg_meta), sizeof(struct ipa_get_apn_data_stats_resp_msg_v01)); + data_network_stats = (ipa_get_apn_data_stats_resp_msg_v01 *)malloc(sizeof(ipa_get_apn_data_stats_resp_msg_v01)); + if(data_network_stats == NULL) + { + IPACMERR("unable to allocate memory for event data_network_stats\n"); + return NULL; + } + memcpy(data_network_stats, + &event_network_stats, + sizeof(struct ipa_get_apn_data_stats_resp_msg_v01)); + IPACMDBG("Received %d apn network stats \n", data_network_stats->apn_data_stats_list_len); + evt_data.event = IPA_NETWORK_STATS_UPDATE_EVENT; + evt_data.evt_data = data_network_stats; + break; + + default: + IPACMDBG_H("Unhandled message type: %d\n", event_hdr.msg_type); + continue; + + } + /* finish command queue */ + IPACMDBG_H("Posting event:%d\n", evt_data.event); + IPACM_EvtDispatcher::PostEvt(&evt_data); + /* push new_neighbor with netdev device internally */ + if(new_neigh_data != NULL) + { + IPACMDBG_H("Internally post event IPA_NEW_NEIGH_EVENT\n"); + IPACM_EvtDispatcher::PostEvt(&new_neigh_evt); + } + } + + (void)close(fd); + return NULL; +} + +void IPACM_Sig_Handler(int sig) +{ + int cnt; + ipacm_cmd_q_data evt_data; + + printf("Received Signal: %d\n", sig); + memset(&evt_data, 0, sizeof(evt_data)); + + switch(sig) + { + case SIGUSR1: + IPACMDBG_H("Received SW_ROUTING_ENABLE request \n"); + evt_data.event = IPA_SW_ROUTING_ENABLE; + IPACM_Iface::ipacmcfg->ipa_sw_rt_enable = true; + break; + + case SIGUSR2: + IPACMDBG_H("Received SW_ROUTING_DISABLE request \n"); + evt_data.event = IPA_SW_ROUTING_DISABLE; + IPACM_Iface::ipacmcfg->ipa_sw_rt_enable = false; + break; + } + /* finish command queue */ + IPACMDBG_H("Posting event:%d\n", evt_data.event); + IPACM_EvtDispatcher::PostEvt(&evt_data); + return; +} + +void RegisterForSignals(void) +{ + + signal(SIGUSR1, IPACM_Sig_Handler); + signal(SIGUSR2, IPACM_Sig_Handler); +} + + +int main(int argc, char **argv) +{ + int ret; + pthread_t netlink_thread = 0, monitor_thread = 0, ipa_driver_thread = 0; + pthread_t cmd_queue_thread = 0; + + /* check if ipacm is already running or not */ + ipa_is_ipacm_running(); + + IPACMDBG_H("In main()\n"); + IPACM_Neighbor *neigh = new IPACM_Neighbor(); + IPACM_IfaceManager *ifacemgr = new IPACM_IfaceManager(); +#ifndef FEATURE_ETH_BRIDGE_LE +#ifndef FEATURE_IPA_ANDROID + IPACM_LanToLan* lan2lan = new IPACM_LanToLan(); +#endif /* defined(FEATURE_IPA_ANDROID)*/ +#endif + IPACM_ConntrackClient *cc = IPACM_ConntrackClient::GetInstance(); + CtList = new IPACM_ConntrackListener(); + + IPACMDBG_H("Staring IPA main\n"); + IPACMDBG_H("ipa_cmdq_successful\n"); + + + RegisterForSignals(); + + if (IPACM_SUCCESS == cmd_queue_thread) + { + ret = pthread_create(&cmd_queue_thread, NULL, MessageQueue::Process, NULL); + if (IPACM_SUCCESS != ret) + { + IPACMERR("unable to command queue thread\n"); + return ret; + } + IPACMDBG_H("created command queue thread\n"); + if(pthread_setname_np(cmd_queue_thread, "cmd queue process") != 0) + { + IPACMERR("unable to set thread name\n"); + } + } + + if (IPACM_SUCCESS == netlink_thread) + { + ret = pthread_create(&netlink_thread, NULL, netlink_start, NULL); + if (IPACM_SUCCESS != ret) + { + IPACMERR("unable to create netlink thread\n"); + return ret; + } + IPACMDBG_H("created netlink thread\n"); + if(pthread_setname_np(netlink_thread, "netlink socket") != 0) + { + IPACMERR("unable to set thread name\n"); + } + } + + /* Enable Firewall support only on MDM targets */ +#ifndef FEATURE_IPA_ANDROID + if (IPACM_SUCCESS == monitor_thread) + { + ret = pthread_create(&monitor_thread, NULL, firewall_monitor, NULL); + if (IPACM_SUCCESS != ret) + { + IPACMERR("unable to create monitor thread\n"); + return ret; + } + IPACMDBG_H("created firewall monitor thread\n"); + if(pthread_setname_np(monitor_thread, "firewall cfg process") != 0) + { + IPACMERR("unable to set thread name\n"); + } + } +#endif + + if (IPACM_SUCCESS == ipa_driver_thread) + { + ret = pthread_create(&ipa_driver_thread, NULL, ipa_driver_msg_notifier, NULL); + if (IPACM_SUCCESS != ret) + { + IPACMERR("unable to create ipa_driver_wlan thread\n"); + return ret; + } + IPACMDBG_H("created ipa_driver_wlan thread\n"); + if(pthread_setname_np(ipa_driver_thread, "ipa driver ntfy") != 0) + { + IPACMERR("unable to set thread name\n"); + } + } + + pthread_join(cmd_queue_thread, NULL); + pthread_join(netlink_thread, NULL); + pthread_join(monitor_thread, NULL); + pthread_join(ipa_driver_thread, NULL); + return IPACM_SUCCESS; +} + +/*=========================================================================== + FUNCTION ipa_is_ipacm_running +===========================================================================*/ +/*! +@brief + Determine whether there's already an IPACM process running, if so, terminate + the current one + +@return + None + +@note + +- Dependencies + - None + +- Side Effects + - None +*/ +/*=========================================================================*/ + +void ipa_is_ipacm_running(void) { + + int fd; + struct flock lock; + int retval; + + fd = open(IPACM_PID_FILE, O_RDWR | O_CREAT, 0600); + if ( fd <= 0 ) + { + IPACMERR("Failed to open %s, error is %d - %s\n", + IPACM_PID_FILE, errno, strerror(errno)); + exit(0); + } + + /* + * Getting an exclusive Write lock on the file, if it fails, + * it means that another instance of IPACM is running and it + * got the lock before us. + */ + memset(&lock, 0, sizeof(lock)); + lock.l_type = F_WRLCK; + retval = fcntl(fd, F_SETLK, &lock); + + if (retval != 0) + { + retval = fcntl(fd, F_GETLK, &lock); + if (retval == 0) + { + IPACMERR("Unable to get lock on file %s (my PID %d), PID %d already has it\n", + IPACM_PID_FILE, getpid(), lock.l_pid); + close(fd); + exit(0); + } + } + else + { + IPACMERR("PID %d is IPACM main process\n", getpid()); + } + + return; +} + +/*=========================================================================== + FUNCTION ipa_get_if_index +===========================================================================*/ +/*! +@brief + get ipa interface index by given the interface name + +@return + IPACM_SUCCESS or IPA_FALUIRE + +@note + +- Dependencies + - None + +- Side Effects + - None +*/ +/*=========================================================================*/ +int ipa_get_if_index +( + char *if_name, + int *if_index + ) +{ + int fd; + struct ifreq ifr; + + if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) + { + PERROR("get interface index socket create failed"); + return IPACM_FAILURE; + } + + memset(&ifr, 0, sizeof(struct ifreq)); + + (void)strncpy(ifr.ifr_name, if_name, sizeof(ifr.ifr_name)); + + if (ioctl(fd, SIOCGIFINDEX, &ifr) < 0) + { + IPACMERR("call_ioctl_on_dev: ioctl failed: can't find device %s",if_name); + *if_index = -1; + close(fd); + return IPACM_FAILURE; + } + + *if_index = ifr.ifr_ifindex; + close(fd); + return IPACM_SUCCESS; +} diff --git a/data-ipa-cfg-mgr/ipacm/src/IPACM_Neighbor.cpp b/data-ipa-cfg-mgr/ipacm/src/IPACM_Neighbor.cpp new file mode 100644 index 000000000..6a4950242 --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/src/IPACM_Neighbor.cpp @@ -0,0 +1,566 @@ +/* +Copyright (c) 2013, The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +/*! + @file + IPACM_Neighbor.cpp + + @brief + This file implements the functionality of handling IPACM Neighbor events. + + @Author + Skylar Chang + +*/ + +#include +#include +#include +#include "IPACM_Defs.h" +#include "IPACM_Log.h" + + +IPACM_Neighbor::IPACM_Neighbor() +{ + num_neighbor_client = 0; + circular_index = 0; + memset(neighbor_client, 0, IPA_MAX_NUM_NEIGHBOR_CLIENTS * sizeof(ipa_neighbor_client)); + IPACM_EvtDispatcher::registr(IPA_WLAN_CLIENT_ADD_EVENT_EX, this); + IPACM_EvtDispatcher::registr(IPA_NEW_NEIGH_EVENT, this); + IPACM_EvtDispatcher::registr(IPA_DEL_NEIGH_EVENT, this); + return; +} + +void IPACM_Neighbor::event_callback(ipa_cm_event_id event, void *param) +{ + ipacm_event_data_all *data_all = NULL; + int i, ipa_interface_index; + ipacm_cmd_q_data evt_data; + int num_neighbor_client_temp = num_neighbor_client; + + IPACMDBG("Recieved event %d\n", event); + + switch (event) + { + case IPA_WLAN_CLIENT_ADD_EVENT_EX: + { + ipacm_event_data_wlan_ex *data = (ipacm_event_data_wlan_ex *)param; + ipa_interface_index = IPACM_Iface::iface_ipa_index_query(data->if_index); + uint8_t client_mac_addr[6]; + + IPACMDBG_H("Received IPA_WLAN_CLIENT_ADD_EVENT\n"); + for(i = 0; i < data->num_of_attribs; i++) + { + if(data->attribs[i].attrib_type == WLAN_HDR_ATTRIB_MAC_ADDR) + { + memcpy(client_mac_addr, + data->attribs[i].u.mac_addr, + sizeof(client_mac_addr)); + IPACMDBG_H("AP Mac Address %02x:%02x:%02x:%02x:%02x:%02x\n", + client_mac_addr[0], client_mac_addr[1], client_mac_addr[2], + client_mac_addr[3], client_mac_addr[4], client_mac_addr[5]); + } + else + { + IPACMDBG_H("The attribute type is not expected!\n"); + } + } + + for (i = 0; i < num_neighbor_client_temp; i++) + { + /* find the client */ + if (memcmp(neighbor_client[i].mac_addr, client_mac_addr, sizeof(neighbor_client[i].mac_addr)) == 0) + { + /* check if iface is not bridge interface*/ + if (strcmp(IPACM_Iface::ipacmcfg->ipa_virtual_iface_name, IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name) != 0) + { + /* use previous ipv4 first */ + if(data->if_index != neighbor_client[i].iface_index) + { + IPACMERR("update new kernel iface index \n"); + neighbor_client[i].iface_index = data->if_index; + } + + /* check if client associated with previous network interface */ + if(ipa_interface_index != neighbor_client[i].ipa_if_num) + { + IPACMERR("client associate to different AP \n"); + return; + } + + if (neighbor_client[i].v4_addr != 0) /* not 0.0.0.0 */ + { + evt_data.event = IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT; + data_all = (ipacm_event_data_all *)malloc(sizeof(ipacm_event_data_all)); + if (data_all == NULL) + { + IPACMERR("Unable to allocate memory\n"); + return; + } + data_all->iptype = IPA_IP_v4; + data_all->if_index = neighbor_client[i].iface_index; + data_all->ipv4_addr = neighbor_client[i].v4_addr; //use previous ipv4 address + memcpy(data_all->mac_addr, + neighbor_client[i].mac_addr, + sizeof(data_all->mac_addr)); + evt_data.evt_data = (void *)data_all; + IPACM_EvtDispatcher::PostEvt(&evt_data); + /* ask for replaced iface name*/ + ipa_interface_index = IPACM_Iface::iface_ipa_index_query(data_all->if_index); + IPACMDBG_H("Posted event %d, with %s for ipv4 client re-connect\n", + evt_data.event, + IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name); + } + } + break; + } + } + } + break; + + default: + { + if (event == IPA_NEW_NEIGH_EVENT) + { + IPACMDBG_H("Received IPA_NEW_NEIGH_EVENT\n"); + } + else + { + IPACMDBG_H("Received IPA_DEL_NEIGH_EVENT\n"); + } + + ipacm_event_data_all *data = (ipacm_event_data_all *)param; + ipa_interface_index = IPACM_Iface::iface_ipa_index_query(data->if_index); + + if (data->iptype == IPA_IP_v4) + { + if (data->ipv4_addr != 0) /* not 0.0.0.0 */ + { + IPACMDBG("Got Neighbor event with ipv4 address: 0x%x \n", data->ipv4_addr); + /* check if ipv4 address is link local(169.254.xxx.xxx) */ + if ((data->ipv4_addr & IPV4_ADDR_LINKLOCAL_MASK) == IPV4_ADDR_LINKLOCAL) + { + IPACMDBG_H("This is link local ipv4 address: 0x%x : ignore this NEIGH_EVENT\n", data->ipv4_addr); + return; + } + /* check if iface is bridge interface*/ + if (strcmp(IPACM_Iface::ipacmcfg->ipa_virtual_iface_name, IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name) == 0) + { + /* searh if seen this client or not*/ + for (i = 0; i < num_neighbor_client_temp; i++) + { + if (memcmp(neighbor_client[i].mac_addr, data->mac_addr, sizeof(neighbor_client[i].mac_addr)) == 0) + { + data->if_index = neighbor_client[i].iface_index; + neighbor_client[i].v4_addr = data->ipv4_addr; // cache client's previous ipv4 address + /* construct IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT command and insert to command-queue */ + if (event == IPA_NEW_NEIGH_EVENT) + evt_data.event = IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT; + else + { + evt_data.event = IPA_NEIGH_CLIENT_IP_ADDR_DEL_EVENT; + /* do the clean-up*/ + IPACMDBG_H("Clean %d-st Cached client-MAC %02x:%02x:%02x:%02x:%02x:%02x\n, total client: %d\n", + i, + neighbor_client[i].mac_addr[0], + neighbor_client[i].mac_addr[1], + neighbor_client[i].mac_addr[2], + neighbor_client[i].mac_addr[3], + neighbor_client[i].mac_addr[4], + neighbor_client[i].mac_addr[5], + num_neighbor_client); + + memset(neighbor_client[i].mac_addr, 0, sizeof(neighbor_client[i].mac_addr)); + neighbor_client[i].iface_index = 0; + neighbor_client[i].v4_addr = 0; + neighbor_client[i].ipa_if_num = 0; + + for (; i < num_neighbor_client_temp - 1; i++) + { + memcpy(neighbor_client[i].mac_addr, + neighbor_client[i+1].mac_addr, + sizeof(neighbor_client[i].mac_addr)); + neighbor_client[i].iface_index = neighbor_client[i+1].iface_index; + neighbor_client[i].v4_addr = neighbor_client[i+1].v4_addr; + neighbor_client[i].ipa_if_num = neighbor_client[i+1].ipa_if_num; + } + num_neighbor_client--; + IPACMDBG_H(" total number of left cased clients: %d\n", num_neighbor_client); + } + data_all = (ipacm_event_data_all *)malloc(sizeof(ipacm_event_data_all)); + if (data_all == NULL) + { + IPACMERR("Unable to allocate memory\n"); + return; + } + memcpy(data_all, data, sizeof(ipacm_event_data_all)); + evt_data.evt_data = (void *)data_all; + IPACM_EvtDispatcher::PostEvt(&evt_data); + + /* ask for replaced iface name*/ + ipa_interface_index = IPACM_Iface::iface_ipa_index_query(data_all->if_index); + IPACMDBG_H("Posted event %d, with %s for ipv4\n", + evt_data.event, + IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name); + break; + } + } + } + else + { + /* construct IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT command and insert to command-queue */ + if (event == IPA_NEW_NEIGH_EVENT) + { + evt_data.event = IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT; + /* Also save to cache for ipv4 */ + /*searh if seen this client or not*/ + for (i = 0; i < num_neighbor_client_temp; i++) + { + /* find the client */ + if (memcmp(neighbor_client[i].mac_addr, data->mac_addr, sizeof(neighbor_client[i].mac_addr)) == 0) + { + /* update the network interface client associated */ + neighbor_client[i].iface_index = data->if_index; + neighbor_client[i].ipa_if_num = ipa_interface_index; + neighbor_client[i].v4_addr = data->ipv4_addr; // cache client's previous ipv4 address + IPACMDBG_H("update cache %d-entry, with %s iface, ipv4 address: 0x%x\n", + i, + IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name, + data->ipv4_addr); + break; + } + } + /* not find client */ + if (i == num_neighbor_client_temp) + { + if (num_neighbor_client_temp < IPA_MAX_NUM_NEIGHBOR_CLIENTS) + { + memcpy(neighbor_client[num_neighbor_client_temp].mac_addr, + data->mac_addr, + sizeof(data->mac_addr)); + neighbor_client[num_neighbor_client_temp].iface_index = data->if_index; + /* cache the network interface client associated */ + neighbor_client[num_neighbor_client_temp].ipa_if_num = ipa_interface_index; + neighbor_client[num_neighbor_client_temp].v4_addr = data->ipv4_addr; + num_neighbor_client++; + IPACMDBG_H("Cache client MAC %02x:%02x:%02x:%02x:%02x:%02x\n, total client: %d\n", + neighbor_client[num_neighbor_client_temp].mac_addr[0], + neighbor_client[num_neighbor_client_temp].mac_addr[1], + neighbor_client[num_neighbor_client_temp].mac_addr[2], + neighbor_client[num_neighbor_client_temp].mac_addr[3], + neighbor_client[num_neighbor_client_temp].mac_addr[4], + neighbor_client[num_neighbor_client_temp].mac_addr[5], + num_neighbor_client); + } + else + { + + IPACMERR("error: neighbor client oversize! recycle %d-st entry ! \n", circular_index); + memcpy(neighbor_client[circular_index].mac_addr, + data->mac_addr, + sizeof(data->mac_addr)); + neighbor_client[circular_index].iface_index = data->if_index; + /* cache the network interface client associated */ + neighbor_client[circular_index].ipa_if_num = ipa_interface_index; + neighbor_client[circular_index].v4_addr = 0; + IPACMDBG_H("Copy wlan-iface client MAC %02x:%02x:%02x:%02x:%02x:%02x\n, total client: %d, circular %d\n", + neighbor_client[circular_index].mac_addr[0], + neighbor_client[circular_index].mac_addr[1], + neighbor_client[circular_index].mac_addr[2], + neighbor_client[circular_index].mac_addr[3], + neighbor_client[circular_index].mac_addr[4], + neighbor_client[circular_index].mac_addr[5], + num_neighbor_client, + circular_index); + circular_index++; + } + } + } + else + { + evt_data.event = IPA_NEIGH_CLIENT_IP_ADDR_DEL_EVENT; + /*searh if seen this client or not*/ + for (i = 0; i < num_neighbor_client_temp; i++) + { + /* find the client */ + if (memcmp(neighbor_client[i].mac_addr, data->mac_addr, sizeof(neighbor_client[i].mac_addr)) == 0) + { + IPACMDBG_H("Clean %d-st Cached client-MAC %02x:%02x:%02x:%02x:%02x:%02x\n, total client: %d\n", + i, + neighbor_client[i].mac_addr[0], + neighbor_client[i].mac_addr[1], + neighbor_client[i].mac_addr[2], + neighbor_client[i].mac_addr[3], + neighbor_client[i].mac_addr[4], + neighbor_client[i].mac_addr[5], + num_neighbor_client); + + memset(neighbor_client[i].mac_addr, 0, sizeof(neighbor_client[i].mac_addr)); + neighbor_client[i].iface_index = 0; + neighbor_client[i].v4_addr = 0; + neighbor_client[i].ipa_if_num = 0; + for (; i < num_neighbor_client_temp - 1; i++) + { + memcpy(neighbor_client[i].mac_addr, + neighbor_client[i+1].mac_addr, + sizeof(neighbor_client[i].mac_addr)); + neighbor_client[i].iface_index = neighbor_client[i+1].iface_index; + neighbor_client[i].v4_addr = neighbor_client[i+1].v4_addr; + neighbor_client[i].ipa_if_num = neighbor_client[i+1].ipa_if_num; + } + num_neighbor_client--; + IPACMDBG_H(" total number of left cased clients: %d\n", num_neighbor_client); + break; + } + } + /* not find client, no need clean-up */ + } + + data_all = (ipacm_event_data_all *)malloc(sizeof(ipacm_event_data_all)); + if (data_all == NULL) + { + IPACMERR("Unable to allocate memory\n"); + return; + } + memcpy(data_all, data, sizeof(ipacm_event_data_all)); + evt_data.evt_data = (void *)data_all; + IPACM_EvtDispatcher::PostEvt(&evt_data); + IPACMDBG_H("Posted event %d with %s for ipv4\n", + evt_data.event, + IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name); + } + } + } + else + { //ipv6 starts + + if ((data->ipv6_addr[0]) || (data->ipv6_addr[1]) || (data->ipv6_addr[2]) || (data->ipv6_addr[3])) + { + IPACMDBG("Got New_Neighbor event with ipv6 address \n"); + /* check if iface is bridge interface*/ + if (strcmp(IPACM_Iface::ipacmcfg->ipa_virtual_iface_name, IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name) == 0) + { + /* searh if seen this client or not*/ + for (i = 0; i < num_neighbor_client_temp; i++) + { + if (memcmp(neighbor_client[i].mac_addr, data->mac_addr, sizeof(neighbor_client[i].mac_addr)) == 0) + { + data->if_index = neighbor_client[i].iface_index; + /* construct IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT command and insert to command-queue */ + if (event == IPA_NEW_NEIGH_EVENT) evt_data.event = IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT; + else evt_data.event = IPA_NEIGH_CLIENT_IP_ADDR_DEL_EVENT; + data_all = (ipacm_event_data_all *)malloc(sizeof(ipacm_event_data_all)); + if (data_all == NULL) + { + IPACMERR("Unable to allocate memory\n"); + return; + } + memcpy(data_all, data, sizeof(ipacm_event_data_all)); + evt_data.evt_data = (void *)data_all; + IPACM_EvtDispatcher::PostEvt(&evt_data); + /* ask for replaced iface name*/ + ipa_interface_index = IPACM_Iface::iface_ipa_index_query(data_all->if_index); + IPACMDBG_H("Posted event %d, with %s for ipv6\n", + evt_data.event, + IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name); + break; + }; + } + } + else + { + /* construct IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT command and insert to command-queue */ + if (event == IPA_NEW_NEIGH_EVENT) + evt_data.event = IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT; + else + evt_data.event = IPA_NEIGH_CLIENT_IP_ADDR_DEL_EVENT; + data_all = (ipacm_event_data_all *)malloc(sizeof(ipacm_event_data_all)); + if (data_all == NULL) + { + IPACMERR("Unable to allocate memory\n"); + return; + } + memcpy(data_all, data, sizeof(ipacm_event_data_all)); + evt_data.evt_data = (void *)data_all; + IPACM_EvtDispatcher::PostEvt(&evt_data); + IPACMDBG_H("Posted event %d with %s for ipv6\n", + evt_data.event, + IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name); + } + } + else + { + IPACMDBG(" Got Neighbor event with no ipv6/ipv4 address \n"); + /*no ipv6 in data searh if seen this client or not*/ + for (i = 0; i < num_neighbor_client_temp; i++) + { + /* find the client */ + if (memcmp(neighbor_client[i].mac_addr, data->mac_addr, sizeof(neighbor_client[i].mac_addr)) == 0) + { + IPACMDBG_H(" find %d-st client, MAC %02x:%02x:%02x:%02x:%02x:%02x\n, total client: %d\n", + i, + neighbor_client[i].mac_addr[0], + neighbor_client[i].mac_addr[1], + neighbor_client[i].mac_addr[2], + neighbor_client[i].mac_addr[3], + neighbor_client[i].mac_addr[4], + neighbor_client[i].mac_addr[5], + num_neighbor_client); + /* check if iface is not bridge interface*/ + if (strcmp(IPACM_Iface::ipacmcfg->ipa_virtual_iface_name, IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name) != 0) + { + /* use previous ipv4 first */ + if(data->if_index != neighbor_client[i].iface_index) + { + IPACMDBG_H("update new kernel iface index \n"); + neighbor_client[i].iface_index = data->if_index; + } + + /* check if client associated with previous network interface */ + if(ipa_interface_index != neighbor_client[i].ipa_if_num) + { + IPACMDBG_H("client associate to different AP \n"); + } + + if (neighbor_client[i].v4_addr != 0) /* not 0.0.0.0 */ + { + /* construct IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT command and insert to command-queue */ + if (event == IPA_NEW_NEIGH_EVENT) + evt_data.event = IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT; + else + evt_data.event = IPA_NEIGH_CLIENT_IP_ADDR_DEL_EVENT; + data_all = (ipacm_event_data_all *)malloc(sizeof(ipacm_event_data_all)); + if (data_all == NULL) + { + IPACMERR("Unable to allocate memory\n"); + return; + } + data_all->iptype = IPA_IP_v4; + data_all->if_index = neighbor_client[i].iface_index; + data_all->ipv4_addr = neighbor_client[i].v4_addr; //use previous ipv4 address + memcpy(data_all->mac_addr, + neighbor_client[i].mac_addr, + sizeof(data_all->mac_addr)); + evt_data.evt_data = (void *)data_all; + IPACM_EvtDispatcher::PostEvt(&evt_data); + /* ask for replaced iface name*/ + ipa_interface_index = IPACM_Iface::iface_ipa_index_query(data_all->if_index); + IPACMDBG_H("Posted event %d, with %s for ipv4 client re-connect\n", + evt_data.event, + IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name); + } + } + /* delete cache neighbor entry */ + if (event == IPA_DEL_NEIGH_EVENT) + { + IPACMDBG_H("Clean %d-st Cached client-MAC %02x:%02x:%02x:%02x:%02x:%02x\n, total client: %d\n", + i, + neighbor_client[i].mac_addr[0], + neighbor_client[i].mac_addr[1], + neighbor_client[i].mac_addr[2], + neighbor_client[i].mac_addr[3], + neighbor_client[i].mac_addr[4], + neighbor_client[i].mac_addr[5], + num_neighbor_client); + + memset(neighbor_client[i].mac_addr, 0, sizeof(neighbor_client[i].mac_addr)); + neighbor_client[i].iface_index = 0; + neighbor_client[i].v4_addr = 0; + neighbor_client[i].ipa_if_num = 0; + for (; i < num_neighbor_client_temp - 1; i++) + { + memcpy(neighbor_client[i].mac_addr, + neighbor_client[i+1].mac_addr, + sizeof(neighbor_client[i].mac_addr)); + neighbor_client[i].iface_index = neighbor_client[i+1].iface_index; + neighbor_client[i].v4_addr = neighbor_client[i+1].v4_addr; + neighbor_client[i].ipa_if_num = neighbor_client[i+1].ipa_if_num; + } + num_neighbor_client--; + IPACMDBG_H(" total number of left cased clients: %d\n", num_neighbor_client); + } + break; + } + } + /* not find client */ + if ((i == num_neighbor_client_temp) && (event == IPA_NEW_NEIGH_EVENT)) + { + /* check if iface is not bridge interface*/ + if (strcmp(IPACM_Iface::ipacmcfg->ipa_virtual_iface_name, IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name) != 0) + { + if (num_neighbor_client_temp < IPA_MAX_NUM_NEIGHBOR_CLIENTS) + { + memcpy(neighbor_client[num_neighbor_client_temp].mac_addr, + data->mac_addr, + sizeof(data->mac_addr)); + neighbor_client[num_neighbor_client_temp].iface_index = data->if_index; + /* cache the network interface client associated */ + neighbor_client[num_neighbor_client_temp].ipa_if_num = ipa_interface_index; + neighbor_client[num_neighbor_client_temp].v4_addr = 0; + num_neighbor_client++; + IPACMDBG_H("Copy client MAC %02x:%02x:%02x:%02x:%02x:%02x\n, total client: %d\n", + neighbor_client[num_neighbor_client_temp].mac_addr[0], + neighbor_client[num_neighbor_client_temp].mac_addr[1], + neighbor_client[num_neighbor_client_temp].mac_addr[2], + neighbor_client[num_neighbor_client_temp].mac_addr[3], + neighbor_client[num_neighbor_client_temp].mac_addr[4], + neighbor_client[num_neighbor_client_temp].mac_addr[5], + num_neighbor_client); + return; + } + else + { + IPACMERR("error: neighbor client oversize! recycle %d-st entry ! \n", circular_index); + memcpy(neighbor_client[circular_index].mac_addr, + data->mac_addr, + sizeof(data->mac_addr)); + neighbor_client[circular_index].iface_index = data->if_index; + /* cache the network interface client associated */ + neighbor_client[circular_index].ipa_if_num = ipa_interface_index; + neighbor_client[circular_index].v4_addr = 0; + IPACMDBG_H("Copy wlan-iface client MAC %02x:%02x:%02x:%02x:%02x:%02x\n, total client: %d, circular %d\n", + neighbor_client[circular_index].mac_addr[0], + neighbor_client[circular_index].mac_addr[1], + neighbor_client[circular_index].mac_addr[2], + neighbor_client[circular_index].mac_addr[3], + neighbor_client[circular_index].mac_addr[4], + neighbor_client[circular_index].mac_addr[5], + num_neighbor_client, + circular_index); + circular_index++; + return; + } + } + } + } + } //ipv6 ends + } + break; + } + return; +} diff --git a/data-ipa-cfg-mgr/ipacm/src/IPACM_Netlink.cpp b/data-ipa-cfg-mgr/ipacm/src/IPACM_Netlink.cpp new file mode 100644 index 000000000..30295b115 --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/src/IPACM_Netlink.cpp @@ -0,0 +1,1773 @@ +/* +Copyright (c) 2013, The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: +* Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. +* Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +/*! + @file + IPACM_Netlink.cpp + + @brief + This file implements the IPAM Netlink Socket Parer functionality. + + @Author + Skylar Chang + +*/ +#include +#include +#include +#include +#include "IPACM_CmdQueue.h" +#include "IPACM_Defs.h" +#include "IPACM_Netlink.h" +#include "IPACM_EvtDispatcher.h" +#include "IPACM_Log.h" + +int ipa_get_if_name(char *if_name, int if_index); +int find_mask(int ip_v4_last, int *mask_value); + +#ifdef FEATURE_IPA_ANDROID + +#define IPACM_NL_COPY_ADDR( event_info, element ) \ + memcpy( &event_info->attr_info.element.__data, \ + RTA_DATA(rtah), \ + sizeof(event_info->attr_info.element.__data) ); + +#define IPACM_EVENT_COPY_ADDR_v6( event_data, element) \ + memcpy( event_data, element.__data, sizeof(event_data)); + +#define IPACM_EVENT_COPY_ADDR_v4( event_data, element) \ + memcpy( &event_data, element.__data, sizeof(event_data)); + +#define IPACM_NL_REPORT_ADDR( prefix, addr ) \ + if( AF_INET6 == (addr).ss_family ) { \ + IPACM_LOG_IPV6_ADDR( prefix, addr.__data); \ + } else { \ + IPACM_LOG_IPV4_ADDR( prefix, (*(unsigned int*)&(addr).__data) ); \ + } + +#else/* defined(FEATURE_IPA_ANDROID) */ + +#define IPACM_NL_COPY_ADDR( event_info, element ) \ + memcpy( &event_info->attr_info.element.__ss_padding, \ + RTA_DATA(rtah), \ + sizeof(event_info->attr_info.element.__ss_padding) ); + +#define IPACM_EVENT_COPY_ADDR_v6( event_data, element) \ + memcpy( event_data, element.__ss_padding, sizeof(event_data)); + +#define IPACM_EVENT_COPY_ADDR_v4( event_data, element) \ + memcpy( &event_data, element.__ss_padding, sizeof(event_data)); + +#define IPACM_NL_REPORT_ADDR( prefix, addr ) \ + if( AF_INET6 == (addr).ss_family ) { \ + IPACM_LOG_IPV6_ADDR( prefix, addr.__ss_padding); \ + } else { \ + IPACM_LOG_IPV4_ADDR( prefix, (*(unsigned int*)&(addr).__ss_padding) ); \ + } +#endif /* defined(FEATURE_IPA_ANDROID)*/ + +#define NDA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ndmsg)))) +#define IPACM_LOG_IPV6_ADDR(prefix, ip_addr) \ + IPACMDBG_H(prefix); \ + IPACMDBG_H(" IPV6 Address %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x\n", \ + (int)ip_addr[0], (int)ip_addr[1], \ + (int)ip_addr[2], (int)ip_addr[3], \ + (int)ip_addr[4], (int)ip_addr[5], \ + (int)ip_addr[6], (int)ip_addr[7], \ + (int)ip_addr[8], (int)ip_addr[9], \ + (int)ip_addr[10], (int)ip_addr[11], \ + (int)ip_addr[12], (int)ip_addr[13], \ + (int)ip_addr[14], (int)ip_addr[15]); + +#define IPACM_LOG_IPV4_ADDR(prefix, ip_addr) \ + IPACMDBG_H(prefix); \ + IPACMDBG_H(" IPV4 Address %d.%d.%d.%d\n", \ + (unsigned char)(ip_addr), \ + (unsigned char)(ip_addr >> 8), \ + (unsigned char)(ip_addr >> 16) , \ + (unsigned char)(ip_addr >> 24)); + +/* Opens a netlink socket*/ +static int ipa_nl_open_socket +( + ipa_nl_sk_info_t *sk_info, + int protocol, + unsigned int grps + ) +{ + int *p_sk_fd; + int buf_size = 6669999, sendbuff=0, res; + struct sockaddr_nl *p_sk_addr_loc; + socklen_t optlen; + + p_sk_fd = &(sk_info->sk_fd); + p_sk_addr_loc = &(sk_info->sk_addr_loc); + + /* Open netlink socket for specified protocol */ + if((*p_sk_fd = socket(AF_NETLINK, SOCK_RAW, protocol)) < 0) + { + IPACMERR("cannot open netlink socket\n"); + return IPACM_FAILURE; + } + + optlen = sizeof(sendbuff); + res = getsockopt(*p_sk_fd, SOL_SOCKET, SO_SNDBUF, &sendbuff, &optlen); + + if(res == -1) { + IPACMDBG("Error getsockopt one"); + } else { + IPACMDBG("orignal send buffer size = %d\n", sendbuff); + } + IPACMDBG("sets the send buffer to %d\n", buf_size); + if (setsockopt(*p_sk_fd, SOL_SOCKET, SO_RCVBUF, &buf_size, sizeof(int)) == -1) { + IPACMERR("Error setting socket opts\n"); + } + + /* Initialize socket addresses to null */ + memset(p_sk_addr_loc, 0, sizeof(struct sockaddr_nl)); + + /* Populate local socket address using specified groups */ + p_sk_addr_loc->nl_family = AF_NETLINK; + p_sk_addr_loc->nl_pid = getpid(); + p_sk_addr_loc->nl_groups = grps; + + /* Bind socket to the local address, i.e. specified groups. This ensures + that multicast messages for these groups are delivered over this + socket. */ + + if(bind(*p_sk_fd, + (struct sockaddr *)p_sk_addr_loc, + sizeof(struct sockaddr_nl)) < 0) + { + IPACMERR("Socket bind failed\n"); + return IPACM_FAILURE; + } + + return IPACM_SUCCESS; +} + +/* Add fd to fdmap array and store read handler function ptr (up to MAX_NUM_OF_FD).*/ +static int ipa_nl_addfd_map +( + ipa_nl_sk_fd_set_info_t *info, + int fd, + ipa_sock_thrd_fd_read_f read_f + ) +{ + if(info->num_fd < MAX_NUM_OF_FD) + { + FD_SET(fd, &info->fdset); + + /* Add fd to fdmap array and store read handler function ptr */ + info->sk_fds[info->num_fd].sk_fd = fd; + info->sk_fds[info->num_fd].read_func = read_f; + + /* Increment number of fds stored in fdmap */ + info->num_fd++; + if(info->max_fd < fd) + info->max_fd = fd; + } + else + { + return IPACM_FAILURE; + } + + return IPACM_SUCCESS; +} + +/* start socket listener */ +static int ipa_nl_sock_listener_start +( + ipa_nl_sk_fd_set_info_t *sk_fd_set + ) +{ + int i, ret; + + while(true) + { + for(i = 0; i < sk_fd_set->num_fd; i++ ) + { + FD_SET(sk_fd_set->sk_fds[i].sk_fd, &(sk_fd_set->fdset)); + } + + if((ret = select(sk_fd_set->max_fd + 1, &(sk_fd_set->fdset), NULL, NULL, NULL)) < 0) + { + IPACMERR("ipa_nl select failed\n"); + } + else + { + for(i = 0; i < sk_fd_set->num_fd; i++) + { + + if(FD_ISSET(sk_fd_set->sk_fds[i].sk_fd, &(sk_fd_set->fdset))) + { + + if(sk_fd_set->sk_fds[i].read_func) + { + if(IPACM_SUCCESS != ((sk_fd_set->sk_fds[i].read_func)(sk_fd_set->sk_fds[i].sk_fd))) + { + IPACMERR("Error on read callback[%d] fd=%d\n", + i, + sk_fd_set->sk_fds[i].sk_fd); + } + FD_CLR(sk_fd_set->sk_fds[i].sk_fd, &(sk_fd_set->fdset)); + } + else + { + IPACMERR("No read function\n"); + } + } + + } /* end of for loop*/ + } /* end of else */ + } /* end of while */ + + return IPACM_SUCCESS; +} + +/* allocate memory for ipa_nl__msg */ +static struct msghdr* ipa_nl_alloc_msg +( + uint32_t msglen + ) +{ + unsigned char *buf = NULL; + struct sockaddr_nl *nladdr = NULL; + struct iovec *iov = NULL; + struct msghdr *msgh = NULL; + + if(IPA_NL_MSG_MAX_LEN < msglen) + { + IPACMERR("Netlink message exceeds maximum length\n"); + return NULL; + } + + msgh = (struct msghdr *)malloc(sizeof(struct msghdr)); + if(msgh == NULL) + { + IPACMERR("Failed malloc for msghdr\n"); + return NULL; + } + + nladdr = (struct sockaddr_nl *)malloc(sizeof(struct sockaddr_nl)); + if(nladdr == NULL) + { + IPACMERR("Failed malloc for sockaddr\n"); + free(msgh); + return NULL; + } + + iov = (struct iovec *)malloc(sizeof(struct iovec)); + if(iov == NULL) + { + PERROR("Failed malloc for iovec"); + free(nladdr); + free(msgh); + return NULL; + } + + buf = (unsigned char *)malloc(msglen); + if(buf == NULL) + { + IPACMERR("Failed malloc for mglen\n"); + free(iov); + free(nladdr); + free(msgh); + return NULL; + } + + memset(nladdr, 0, sizeof(struct sockaddr_nl)); + nladdr->nl_family = AF_NETLINK; + + memset(msgh, 0x0, sizeof(struct msghdr)); + msgh->msg_name = nladdr; + msgh->msg_namelen = sizeof(struct sockaddr_nl); + msgh->msg_iov = iov; + msgh->msg_iovlen = 1; + + memset(iov, 0x0, sizeof(struct iovec)); + iov->iov_base = buf; + iov->iov_len = msglen; + + return msgh; +} + +/* release IPA message */ +static void ipa_nl_release_msg +( + struct msghdr *msgh + ) +{ + unsigned char *buf = NULL; + struct sockaddr_nl *nladdr = NULL; + struct iovec *iov = NULL; + + if(NULL == msgh) + { + return; + } + + nladdr = (struct sockaddr_nl *)msgh->msg_name; + iov = msgh->msg_iov; + if(msgh->msg_iov) + { + buf = (unsigned char *)msgh->msg_iov->iov_base; + } + + if(buf) + { + free(buf); + } + if(iov) + { + free(iov); + } + if(nladdr) + { + free(nladdr); + } + if(msgh) + { + free(msgh); + } + return; +} + +/* receive and process nl message */ +static int ipa_nl_recv +( + int fd, + struct msghdr **msg_pptr, + unsigned int *msglen_ptr + ) +{ + struct msghdr *msgh = NULL; + int rmsgl; + + msgh = ipa_nl_alloc_msg(IPA_NL_MSG_MAX_LEN); + if(NULL == msgh) + { + IPACMERR("Failed to allocate NL message\n"); + goto error; + } + + + /* Receive message over the socket */ + rmsgl = recvmsg(fd, msgh, 0); + + /* Verify that something was read */ + if(rmsgl <= 0) + { + PERROR("NL recv error"); + goto error; + } + + /* Verify that NL address length in the received message is expected value */ + if(sizeof(struct sockaddr_nl) != msgh->msg_namelen) + { + IPACMERR("rcvd msg with namelen != sizeof sockaddr_nl\n"); + goto error; + } + + /* Verify that message was not truncated. This should not occur */ + if(msgh->msg_flags & MSG_TRUNC) + { + IPACMERR("Rcvd msg truncated!\n"); + goto error; + } + + *msg_pptr = msgh; + *msglen_ptr = rmsgl; + + return IPACM_SUCCESS; + +/* An error occurred while receiving the message. Free all memory before + returning. */ +error: + ipa_nl_release_msg(msgh); + *msg_pptr = NULL; + *msglen_ptr = 0; + + return IPACM_FAILURE; +} + +/* decode the rtm netlink message */ +static int ipa_nl_decode_rtm_link +( + const char *buffer, + unsigned int buflen, + ipa_nl_link_info_t *link_info +) +{ + struct rtattr; + /* NL message header */ + struct nlmsghdr *nlh = (struct nlmsghdr *)buffer; + + /* Extract the header data */ + link_info->metainfo = *(struct ifinfomsg *)NLMSG_DATA(nlh); + buflen -= sizeof(struct nlmsghdr); + + return IPACM_SUCCESS; +} + +/* Decode kernel address message parameters from Netlink attribute TLVs. */ +static int ipa_nl_decode_rtm_addr +( + const char *buffer, + unsigned int buflen, + ipa_nl_addr_info_t *addr_info + ) +{ + struct nlmsghdr *nlh = (struct nlmsghdr *)buffer; /* NL message header */ + struct rtattr *rtah = NULL; + + /* Extract the header data */ + addr_info->metainfo = *((struct ifaddrmsg *)NLMSG_DATA(nlh)); + buflen -= sizeof(struct nlmsghdr); + + /* Extract the available attributes */ + addr_info->attr_info.param_mask = IPA_NLA_PARAM_NONE; + + rtah = IFA_RTA(NLMSG_DATA(nlh)); + + while(RTA_OK(rtah, buflen)) + { + switch(rtah->rta_type) + { + + case IFA_ADDRESS: + addr_info->attr_info.prefix_addr.ss_family = addr_info->metainfo.ifa_family; + IPACM_NL_COPY_ADDR( addr_info, prefix_addr ); + addr_info->attr_info.param_mask |= IPA_NLA_PARAM_PREFIXADDR; + break; + default: + break; + + } + /* Advance to next attribute */ + rtah = RTA_NEXT(rtah, buflen); + } + + return IPACM_SUCCESS; +} + +/* Decode kernel neighbor message parameters from Netlink attribute TLVs. */ +static int ipa_nl_decode_rtm_neigh +( + const char *buffer, + unsigned int buflen, + ipa_nl_neigh_info_t *neigh_info + ) +{ + struct nlmsghdr *nlh = (struct nlmsghdr *)buffer; /* NL message header */ + struct rtattr *rtah = NULL; + + /* Extract the header data */ + neigh_info->metainfo = *((struct ndmsg *)NLMSG_DATA(nlh)); + buflen -= sizeof(struct nlmsghdr); + + /* Extract the available attributes */ + neigh_info->attr_info.param_mask = IPA_NLA_PARAM_NONE; + + rtah = NDA_RTA(NLMSG_DATA(nlh)); + + while(RTA_OK(rtah, buflen)) + { + switch(rtah->rta_type) + { + + case NDA_DST: + neigh_info->attr_info.local_addr.ss_family = neigh_info->metainfo.ndm_family; + IPACM_NL_COPY_ADDR( neigh_info, local_addr ); + break; + + case NDA_LLADDR: + memcpy(neigh_info->attr_info.lladdr_hwaddr.sa_data, + RTA_DATA(rtah), + sizeof(neigh_info->attr_info.lladdr_hwaddr.sa_data)); + break; + + default: + break; + + } + + /* Advance to next attribute */ + rtah = RTA_NEXT(rtah, buflen); + } + + return IPACM_SUCCESS; +} + +/* Decode kernel route message parameters from Netlink attribute TLVs. */ +static int ipa_nl_decode_rtm_route +( + const char *buffer, + unsigned int buflen, + ipa_nl_route_info_t *route_info + ) +{ + struct nlmsghdr *nlh = (struct nlmsghdr *)buffer; /* NL message header */ + struct rtattr *rtah = NULL; + + /* Extract the header data */ + route_info->metainfo = *((struct rtmsg *)NLMSG_DATA(nlh)); + buflen -= sizeof(struct nlmsghdr); + + route_info->attr_info.param_mask = IPA_RTA_PARAM_NONE; + rtah = RTM_RTA(NLMSG_DATA(nlh)); + + while(RTA_OK(rtah, buflen)) + { + switch(rtah->rta_type) + { + + case RTA_DST: + route_info->attr_info.dst_addr.ss_family = route_info->metainfo.rtm_family; + IPACM_NL_COPY_ADDR( route_info, dst_addr ); + route_info->attr_info.param_mask |= IPA_RTA_PARAM_DST; + break; + + case RTA_SRC: + route_info->attr_info.src_addr.ss_family = route_info->metainfo.rtm_family; + IPACM_NL_COPY_ADDR( route_info, src_addr ); + route_info->attr_info.param_mask |= IPA_RTA_PARAM_SRC; + break; + + case RTA_GATEWAY: + route_info->attr_info.gateway_addr.ss_family = route_info->metainfo.rtm_family; + IPACM_NL_COPY_ADDR( route_info, gateway_addr ); + route_info->attr_info.param_mask |= IPA_RTA_PARAM_GATEWAY; + break; + + case RTA_IIF: + memcpy(&route_info->attr_info.iif_index, + RTA_DATA(rtah), + sizeof(route_info->attr_info.iif_index)); + route_info->attr_info.param_mask |= IPA_RTA_PARAM_IIF; + break; + + case RTA_OIF: + memcpy(&route_info->attr_info.oif_index, + RTA_DATA(rtah), + sizeof(route_info->attr_info.oif_index)); + route_info->attr_info.param_mask |= IPA_RTA_PARAM_OIF; + break; + + case RTA_PRIORITY: + memcpy(&route_info->attr_info.priority, + RTA_DATA(rtah), + sizeof(route_info->attr_info.priority)); + route_info->attr_info.param_mask |= IPA_RTA_PARAM_PRIORITY; + break; + + default: + break; + + } + + /* Advance to next attribute */ + rtah = RTA_NEXT(rtah, buflen); + } + + return IPACM_SUCCESS; +} + +/* decode the ipa nl-message */ +static int ipa_nl_decode_nlmsg +( + const char *buffer, + unsigned int buflen, + ipa_nl_msg_t *msg_ptr + ) +{ + char dev_name[IF_NAME_LEN]={0}; + int ret_val, mask_value, mask_index, mask_value_v6; + struct nlmsghdr *nlh = (struct nlmsghdr *)buffer; + + uint32_t if_ipv4_addr =0, if_ipipv4_addr_mask =0, temp =0, if_ipv4_addr_gw =0; + + ipacm_cmd_q_data evt_data; + ipacm_event_data_all *data_all; + ipacm_event_data_fid *data_fid; + ipacm_event_data_addr *data_addr; + + + while(NLMSG_OK(nlh, buflen)) + { + memset(dev_name,0,IF_NAME_LEN); + IPACMDBG("Received msg:%d from netlink\n", nlh->nlmsg_type) + switch(nlh->nlmsg_type) + { + case RTM_NEWLINK: + msg_ptr->type = nlh->nlmsg_type; + msg_ptr->link_event = true; + if(IPACM_SUCCESS != ipa_nl_decode_rtm_link(buffer, buflen, &(msg_ptr->nl_link_info))) + { + IPACMERR("Failed to decode rtm link message\n"); + return IPACM_FAILURE; + } + else + { + IPACMDBG("Got RTM_NEWLINK with below values\n"); + IPACMDBG("RTM_NEWLINK, ifi_change:%d\n", msg_ptr->nl_link_info.metainfo.ifi_change); + IPACMDBG("RTM_NEWLINK, ifi_flags:%d\n", msg_ptr->nl_link_info.metainfo.ifi_flags); + IPACMDBG("RTM_NEWLINK, ifi_index:%d\n", msg_ptr->nl_link_info.metainfo.ifi_index); + IPACMDBG("RTM_NEWLINK, family:%d\n", msg_ptr->nl_link_info.metainfo.ifi_family); + /* RTM_NEWLINK event with AF_BRIDGE family should be ignored in Android + but this should be processed in case of MDM for Ehernet interface. + */ +#ifdef FEATURE_IPA_ANDROID + if (msg_ptr->nl_link_info.metainfo.ifi_family == AF_BRIDGE) + { + IPACMERR(" ignore this RTM_NEWLINK msg \n"); + return IPACM_SUCCESS; + } +#endif + if(IFF_UP & msg_ptr->nl_link_info.metainfo.ifi_change) + { + IPACMDBG("GOT useful newlink event\n"); + ret_val = ipa_get_if_name(dev_name, msg_ptr->nl_link_info.metainfo.ifi_index); + if(ret_val != IPACM_SUCCESS) + { + IPACMERR("Error while getting interface name\n"); + return IPACM_FAILURE; + } + + data_fid = (ipacm_event_data_fid *)malloc(sizeof(ipacm_event_data_fid)); + if(data_fid == NULL) + { + IPACMERR("unable to allocate memory for event data_fid\n"); + return IPACM_FAILURE; + } + data_fid->if_index = msg_ptr->nl_link_info.metainfo.ifi_index; + + if(msg_ptr->nl_link_info.metainfo.ifi_flags & IFF_UP) + { + IPACMDBG_H("Interface %s bring up with IP-family: %d \n", dev_name, msg_ptr->nl_link_info.metainfo.ifi_family); + /* post link up to command queue */ + evt_data.event = IPA_LINK_UP_EVENT; + IPACMDBG_H("Posting IPA_LINK_UP_EVENT with if index: %d\n", + msg_ptr->nl_link_info.metainfo.ifi_index); + } + else + { + IPACMDBG_H("Interface %s bring down with IP-family: %d \n", dev_name, msg_ptr->nl_link_info.metainfo.ifi_family); + /* post link down to command queue */ + evt_data.event = IPA_LINK_DOWN_EVENT; + IPACMDBG_H("Posting IPA_LINK_DOWN_EVENT with if index: %d\n", + data_fid->if_index); + } + evt_data.evt_data = data_fid; + IPACM_EvtDispatcher::PostEvt(&evt_data); + } + + /* Add IPACM support for ECM plug-in/plug_out */ + /*-------------------------------------------------------------------------- + Check if the interface is running.If its a RTM_NEWLINK and the interface + is running then it means that its a link up event + ---------------------------------------------------------------------------*/ + if((msg_ptr->nl_link_info.metainfo.ifi_flags & IFF_RUNNING) && + (msg_ptr->nl_link_info.metainfo.ifi_flags & IFF_LOWER_UP)) + { + + data_fid = (ipacm_event_data_fid *)malloc(sizeof(ipacm_event_data_fid)); + if(data_fid == NULL) + { + IPACMERR("unable to allocate memory for event data_fid\n"); + return IPACM_FAILURE; + } + data_fid->if_index = msg_ptr->nl_link_info.metainfo.ifi_index; + + ret_val = ipa_get_if_name(dev_name, msg_ptr->nl_link_info.metainfo.ifi_index); + if(ret_val != IPACM_SUCCESS) + { + IPACMERR("Error while getting interface name\n"); + return IPACM_FAILURE; + } + IPACMDBG("Got a usb link_up event (Interface %s, %d) \n", dev_name, msg_ptr->nl_link_info.metainfo.ifi_index); + + /*-------------------------------------------------------------------------- + Post LAN iface (ECM) link up event + ---------------------------------------------------------------------------*/ + evt_data.event = IPA_USB_LINK_UP_EVENT; + evt_data.evt_data = data_fid; + IPACM_EvtDispatcher::PostEvt(&evt_data); + IPACMDBG_H("Posting usb IPA_LINK_UP_EVENT with if index: %d\n", + data_fid->if_index); + } + else if(!(msg_ptr->nl_link_info.metainfo.ifi_flags & IFF_LOWER_UP)) + { + data_fid = (ipacm_event_data_fid *)malloc(sizeof(ipacm_event_data_fid)); + if(data_fid == NULL) + { + IPACMERR("unable to allocate memory for event data_fid\n"); + return IPACM_FAILURE; + } + data_fid->if_index = msg_ptr->nl_link_info.metainfo.ifi_index; + + ret_val = ipa_get_if_name(dev_name, msg_ptr->nl_link_info.metainfo.ifi_index); + if(ret_val != IPACM_SUCCESS) + { + IPACMERR("Error while getting interface name\n"); + return IPACM_FAILURE; + } + IPACMDBG_H("Got a usb link_down event (Interface %s) \n", dev_name); + + /*-------------------------------------------------------------------------- + Post LAN iface (ECM) link down event + ---------------------------------------------------------------------------*/ + evt_data.event = IPA_LINK_DOWN_EVENT; + evt_data.evt_data = data_fid; + IPACM_EvtDispatcher::PostEvt(&evt_data); + IPACMDBG_H("Posting usb IPA_LINK_DOWN_EVENT with if index: %d\n", + data_fid->if_index); + } + } + break; + + case RTM_DELLINK: + IPACMDBG("\n GOT dellink event\n"); + msg_ptr->type = nlh->nlmsg_type; + msg_ptr->link_event = true; + IPACMDBG("entering rtm decode\n"); + if(IPACM_SUCCESS != ipa_nl_decode_rtm_link(buffer, buflen, &(msg_ptr->nl_link_info))) + { + IPACMERR("Failed to decode rtm link message\n"); + return IPACM_FAILURE; + } + else + { + IPACMDBG("Got RTM_DELLINK with below values\n"); + IPACMDBG("RTM_DELLINK, ifi_change:%d\n", msg_ptr->nl_link_info.metainfo.ifi_change); + IPACMDBG("RTM_DELLINK, ifi_flags:%d\n", msg_ptr->nl_link_info.metainfo.ifi_flags); + IPACMDBG("RTM_DELLINK, ifi_index:%d\n", msg_ptr->nl_link_info.metainfo.ifi_index); + IPACMDBG("RTM_DELLINK, family:%d\n", msg_ptr->nl_link_info.metainfo.ifi_family); + /* RTM_NEWLINK event with AF_BRIDGE family should be ignored in Android + but this should be processed in case of MDM for Ehernet interface. + */ +#ifdef FEATURE_IPA_ANDROID + if (msg_ptr->nl_link_info.metainfo.ifi_family == AF_BRIDGE) + { + IPACMERR(" ignore this RTM_DELLINK msg \n"); + return IPACM_SUCCESS; + } +#endif + ret_val = ipa_get_if_name(dev_name, msg_ptr->nl_link_info.metainfo.ifi_index); + if(ret_val != IPACM_SUCCESS) + { + IPACMERR("Error while getting interface name\n"); + return IPACM_FAILURE; + } + IPACMDBG("Interface %s bring down \n", dev_name); + + /* post link down to command queue */ + evt_data.event = IPA_LINK_DOWN_EVENT; + data_fid = (ipacm_event_data_fid *)malloc(sizeof(ipacm_event_data_fid)); + if(data_fid == NULL) + { + IPACMERR("unable to allocate memory for event data_fid\n"); + return IPACM_FAILURE; + } + + data_fid->if_index = msg_ptr->nl_link_info.metainfo.ifi_index; + + IPACMDBG_H("posting IPA_LINK_DOWN_EVENT with if idnex:%d\n", + data_fid->if_index); + evt_data.evt_data = data_fid; + IPACM_EvtDispatcher::PostEvt(&evt_data); + /* finish command queue */ + } + break; + + case RTM_NEWADDR: + IPACMDBG("\n GOT RTM_NEWADDR event\n"); + if(IPACM_SUCCESS != ipa_nl_decode_rtm_addr(buffer, buflen, &(msg_ptr->nl_addr_info))) + { + IPACMERR("Failed to decode rtm addr message\n"); + return IPACM_FAILURE; + } + else + { + ret_val = ipa_get_if_name(dev_name, msg_ptr->nl_addr_info.metainfo.ifa_index); + if(ret_val != IPACM_SUCCESS) + { + IPACMERR("Error while getting interface name\n"); + } + IPACMDBG("Interface %s \n", dev_name); + + data_addr = (ipacm_event_data_addr *)malloc(sizeof(ipacm_event_data_addr)); + if(data_addr == NULL) + { + IPACMERR("unable to allocate memory for event data_addr\n"); + return IPACM_FAILURE; + } + + if(AF_INET6 == msg_ptr->nl_addr_info.attr_info.prefix_addr.ss_family) + { + data_addr->iptype = IPA_IP_v6; + IPACM_NL_REPORT_ADDR( "IFA_ADDRESS:", msg_ptr->nl_addr_info.attr_info.prefix_addr ); + IPACM_EVENT_COPY_ADDR_v6( data_addr->ipv6_addr, msg_ptr->nl_addr_info.attr_info.prefix_addr); + data_addr->ipv6_addr[0] = ntohl(data_addr->ipv6_addr[0]); + data_addr->ipv6_addr[1] = ntohl(data_addr->ipv6_addr[1]); + data_addr->ipv6_addr[2] = ntohl(data_addr->ipv6_addr[2]); + data_addr->ipv6_addr[3] = ntohl(data_addr->ipv6_addr[3]); + } + else + { + data_addr->iptype = IPA_IP_v4; + IPACM_NL_REPORT_ADDR( "IFA_ADDRESS:", msg_ptr->nl_addr_info.attr_info.prefix_addr ); + IPACM_EVENT_COPY_ADDR_v4( data_addr->ipv4_addr, msg_ptr->nl_addr_info.attr_info.prefix_addr); + data_addr->ipv4_addr = ntohl(data_addr->ipv4_addr); + + } + + evt_data.event = IPA_ADDR_ADD_EVENT; + data_addr->if_index = msg_ptr->nl_addr_info.metainfo.ifa_index; + if(AF_INET6 == msg_ptr->nl_addr_info.attr_info.prefix_addr.ss_family) + { + IPACMDBG("Posting IPA_ADDR_ADD_EVENT with if index:%d, ipv6 addr:0x%x:%x:%x:%x\n", + data_addr->if_index, + data_addr->ipv6_addr[0], + data_addr->ipv6_addr[1], + data_addr->ipv6_addr[2], + data_addr->ipv6_addr[3]); + } + else + { + IPACMDBG("Posting IPA_ADDR_ADD_EVENT with if index:%d, ipv4 addr:0x%x\n", + data_addr->if_index, + data_addr->ipv4_addr); + } + evt_data.evt_data = data_addr; + IPACM_EvtDispatcher::PostEvt(&evt_data); + } + break; + + case RTM_NEWROUTE: + + if(IPACM_SUCCESS != ipa_nl_decode_rtm_route(buffer, buflen, &(msg_ptr->nl_route_info))) + { + IPACMERR("Failed to decode rtm route message\n"); + return IPACM_FAILURE; + } + + IPACMDBG("In case RTM_NEWROUTE\n"); + IPACMDBG("rtm_type: %d\n", msg_ptr->nl_route_info.metainfo.rtm_type); + IPACMDBG("protocol: %d\n", msg_ptr->nl_route_info.metainfo.rtm_protocol); + IPACMDBG("rtm_scope: %d\n", msg_ptr->nl_route_info.metainfo.rtm_scope); + IPACMDBG("rtm_table: %d\n", msg_ptr->nl_route_info.metainfo.rtm_table); + IPACMDBG("rtm_family: %d\n", msg_ptr->nl_route_info.metainfo.rtm_family); + IPACMDBG("param_mask: 0x%x\n", msg_ptr->nl_route_info.attr_info.param_mask); + + /* take care of route add default route & uniroute */ + if((msg_ptr->nl_route_info.metainfo.rtm_type == RTN_UNICAST) && + ((msg_ptr->nl_route_info.metainfo.rtm_protocol == RTPROT_BOOT) || + (msg_ptr->nl_route_info.metainfo.rtm_protocol == RTPROT_RA)) && + (msg_ptr->nl_route_info.metainfo.rtm_scope == RT_SCOPE_UNIVERSE) && + (msg_ptr->nl_route_info.metainfo.rtm_table == RT_TABLE_MAIN)) + { + IPACMDBG("\n GOT RTM_NEWROUTE event\n"); + + if(msg_ptr->nl_route_info.attr_info.param_mask & IPA_RTA_PARAM_DST) + { + ret_val = ipa_get_if_name(dev_name, msg_ptr->nl_route_info.attr_info.oif_index); + if(ret_val != IPACM_SUCCESS) + { + IPACMERR("Error while getting interface name\n"); + return IPACM_FAILURE; + } + + IPACM_NL_REPORT_ADDR( "route add -host", msg_ptr->nl_route_info.attr_info.dst_addr ); + IPACM_NL_REPORT_ADDR( "gw", msg_ptr->nl_route_info.attr_info.gateway_addr ); + IPACMDBG("dev %s\n",dev_name ); + /* insert to command queue */ + IPACM_EVENT_COPY_ADDR_v4( if_ipv4_addr, msg_ptr->nl_route_info.attr_info.dst_addr); + temp = (-1); + + evt_data.event = IPA_ROUTE_ADD_EVENT; + data_addr = (ipacm_event_data_addr *)malloc(sizeof(ipacm_event_data_addr)); + if(data_addr == NULL) + { + IPACMERR("unable to allocate memory for event data_addr\n"); + return IPACM_FAILURE; + } + + data_addr->if_index = msg_ptr->nl_route_info.attr_info.oif_index; + data_addr->iptype = IPA_IP_v4; + data_addr->ipv4_addr = ntohl(if_ipv4_addr); + data_addr->ipv4_addr_mask = ntohl(if_ipipv4_addr_mask); + + IPACMDBG("Posting IPA_ROUTE_ADD_EVENT with if index:%d, ipv4 address 0x%x, mask:0x%x\n", + data_addr->if_index, + data_addr->ipv4_addr, + data_addr->ipv4_addr_mask); + evt_data.evt_data = data_addr; + IPACM_EvtDispatcher::PostEvt(&evt_data); + /* finish command queue */ + + } + else + { + ret_val = ipa_get_if_name(dev_name, msg_ptr->nl_route_info.attr_info.oif_index); + if(ret_val != IPACM_SUCCESS) + { + IPACMERR("Error while getting interface name\n"); + return IPACM_FAILURE; + } + + if(AF_INET6 == msg_ptr->nl_route_info.metainfo.rtm_family) + { + /* insert to command queue */ + data_addr = (ipacm_event_data_addr *)malloc(sizeof(ipacm_event_data_addr)); + if(data_addr == NULL) + { + IPACMERR("unable to allocate memory for event data_addr\n"); + return IPACM_FAILURE; + } + + if(msg_ptr->nl_route_info.attr_info.param_mask & IPA_RTA_PARAM_PRIORITY) + { + IPACMDBG_H("ip -6 route add default dev %s metric %d\n", + dev_name, + msg_ptr->nl_route_info.attr_info.priority); + } + else + { + IPACMDBG_H("ip -6 route add default dev %s\n", dev_name); + } + + IPACM_EVENT_COPY_ADDR_v6( data_addr->ipv6_addr, msg_ptr->nl_route_info.attr_info.dst_addr); + data_addr->ipv6_addr[0] = ntohl(data_addr->ipv6_addr[0]); + data_addr->ipv6_addr[1] = ntohl(data_addr->ipv6_addr[1]); + data_addr->ipv6_addr[2] = ntohl(data_addr->ipv6_addr[2]); + data_addr->ipv6_addr[3] = ntohl(data_addr->ipv6_addr[3]); + + IPACM_EVENT_COPY_ADDR_v6( data_addr->ipv6_addr_mask, msg_ptr->nl_route_info.attr_info.dst_addr); + data_addr->ipv6_addr_mask[0] = ntohl(data_addr->ipv6_addr_mask[0]); + data_addr->ipv6_addr_mask[1] = ntohl(data_addr->ipv6_addr_mask[1]); + data_addr->ipv6_addr_mask[2] = ntohl(data_addr->ipv6_addr_mask[2]); + data_addr->ipv6_addr_mask[3] = ntohl(data_addr->ipv6_addr_mask[3]); + + IPACM_EVENT_COPY_ADDR_v6( data_addr->ipv6_addr_gw, msg_ptr->nl_route_info.attr_info.gateway_addr); + data_addr->ipv6_addr_gw[0] = ntohl(data_addr->ipv6_addr_gw[0]); + data_addr->ipv6_addr_gw[1] = ntohl(data_addr->ipv6_addr_gw[1]); + data_addr->ipv6_addr_gw[2] = ntohl(data_addr->ipv6_addr_gw[2]); + data_addr->ipv6_addr_gw[3] = ntohl(data_addr->ipv6_addr_gw[3]); + IPACM_NL_REPORT_ADDR( " ", msg_ptr->nl_route_info.attr_info.gateway_addr); + + evt_data.event = IPA_ROUTE_ADD_EVENT; + data_addr->if_index = msg_ptr->nl_route_info.attr_info.oif_index; + data_addr->iptype = IPA_IP_v6; + + IPACMDBG("Posting IPA_ROUTE_ADD_EVENT with if index:%d, ipv6 address\n", + data_addr->if_index); + evt_data.evt_data = data_addr; + IPACM_EvtDispatcher::PostEvt(&evt_data); + /* finish command queue */ + + } + else + { + IPACM_NL_REPORT_ADDR( "route add default gw \n", msg_ptr->nl_route_info.attr_info.gateway_addr ); + IPACMDBG_H("dev %s \n", dev_name); + IPACM_NL_REPORT_ADDR( "dstIP:", msg_ptr->nl_route_info.attr_info.dst_addr ); + + /* insert to command queue */ + data_addr = (ipacm_event_data_addr *)malloc(sizeof(ipacm_event_data_addr)); + if(data_addr == NULL) + { + IPACMERR("unable to allocate memory for event data_addr\n"); + return IPACM_FAILURE; + } + + IPACM_EVENT_COPY_ADDR_v4( if_ipv4_addr, msg_ptr->nl_route_info.attr_info.dst_addr); + IPACM_EVENT_COPY_ADDR_v4( if_ipipv4_addr_mask, msg_ptr->nl_route_info.attr_info.dst_addr); + IPACM_EVENT_COPY_ADDR_v4( if_ipv4_addr_gw, msg_ptr->nl_route_info.attr_info.gateway_addr); + + evt_data.event = IPA_ROUTE_ADD_EVENT; + data_addr->if_index = msg_ptr->nl_route_info.attr_info.oif_index; + data_addr->iptype = IPA_IP_v4; + data_addr->ipv4_addr = ntohl(if_ipv4_addr); + data_addr->ipv4_addr_gw = ntohl(if_ipv4_addr_gw); + data_addr->ipv4_addr_mask = ntohl(if_ipipv4_addr_mask); + + IPACMDBG_H("Posting IPA_ROUTE_ADD_EVENT with if index:%d, ipv4 addr:0x%x, mask: 0x%x and gw: 0x%x\n", + data_addr->if_index, + data_addr->ipv4_addr, + data_addr->ipv4_addr_mask, + data_addr->ipv4_addr_gw); + evt_data.evt_data = data_addr; + IPACM_EvtDispatcher::PostEvt(&evt_data); + /* finish command queue */ + } + } + } + + /* ipv6 routing table */ + if((AF_INET6 == msg_ptr->nl_route_info.metainfo.rtm_family) && + (msg_ptr->nl_route_info.metainfo.rtm_type == RTN_UNICAST) && + (msg_ptr->nl_route_info.metainfo.rtm_protocol == RTPROT_KERNEL) && + (msg_ptr->nl_route_info.metainfo.rtm_table == RT_TABLE_MAIN)) + { + IPACMDBG("\n GOT valid v6-RTM_NEWROUTE event\n"); + ret_val = ipa_get_if_name(dev_name, msg_ptr->nl_route_info.attr_info.oif_index); + if(ret_val != IPACM_SUCCESS) + { + IPACMERR("Error while getting interface name\n"); + return IPACM_FAILURE; + } + + if(msg_ptr->nl_route_info.attr_info.param_mask & IPA_RTA_PARAM_DST) + { + IPACM_NL_REPORT_ADDR( "Route ADD DST:", msg_ptr->nl_route_info.attr_info.dst_addr ); + IPACMDBG("%d, metric %d, dev %s\n", + msg_ptr->nl_route_info.metainfo.rtm_dst_len, + msg_ptr->nl_route_info.attr_info.priority, + dev_name); + + /* insert to command queue */ + data_addr = (ipacm_event_data_addr *)malloc(sizeof(ipacm_event_data_addr)); + if(data_addr == NULL) + { + IPACMERR("unable to allocate memory for event data_addr\n"); + return IPACM_FAILURE; + } + + IPACM_EVENT_COPY_ADDR_v6( data_addr->ipv6_addr, msg_ptr->nl_route_info.attr_info.dst_addr); + + data_addr->ipv6_addr[0] = ntohl(data_addr->ipv6_addr[0]); + data_addr->ipv6_addr[1] = ntohl(data_addr->ipv6_addr[1]); + data_addr->ipv6_addr[2] = ntohl(data_addr->ipv6_addr[2]); + data_addr->ipv6_addr[3] = ntohl(data_addr->ipv6_addr[3]); + + mask_value_v6 = msg_ptr->nl_route_info.metainfo.rtm_dst_len; + for(mask_index = 0; mask_index < 4; mask_index++) + { + if(mask_value_v6 >= 32) + { + mask_v6(32, &data_addr->ipv6_addr_mask[mask_index]); + mask_value_v6 -= 32; + } + else + { + mask_v6(mask_value_v6, &data_addr->ipv6_addr_mask[mask_index]); + mask_value_v6 = 0; + } + } + + IPACMDBG("ADD IPV6 MASK %d: %08x:%08x:%08x:%08x \n", + msg_ptr->nl_route_info.metainfo.rtm_dst_len, + data_addr->ipv6_addr_mask[0], + data_addr->ipv6_addr_mask[1], + data_addr->ipv6_addr_mask[2], + data_addr->ipv6_addr_mask[3]); + + data_addr->ipv6_addr_mask[0] = ntohl(data_addr->ipv6_addr_mask[0]); + data_addr->ipv6_addr_mask[1] = ntohl(data_addr->ipv6_addr_mask[1]); + data_addr->ipv6_addr_mask[2] = ntohl(data_addr->ipv6_addr_mask[2]); + data_addr->ipv6_addr_mask[3] = ntohl(data_addr->ipv6_addr_mask[3]); + + evt_data.event = IPA_ROUTE_ADD_EVENT; + data_addr->if_index = msg_ptr->nl_route_info.attr_info.oif_index; + data_addr->iptype = IPA_IP_v6; + + IPACMDBG("Posting IPA_ROUTE_ADD_EVENT with if index:%d, ipv6 addr\n", + data_addr->if_index); + evt_data.evt_data = data_addr; + IPACM_EvtDispatcher::PostEvt(&evt_data); + /* finish command queue */ + } + if(msg_ptr->nl_route_info.attr_info.param_mask & IPA_RTA_PARAM_GATEWAY) + { + IPACM_NL_REPORT_ADDR( "Route ADD ::/0 Next Hop:", msg_ptr->nl_route_info.attr_info.gateway_addr ); + IPACMDBG(" metric %d, dev %s\n", + msg_ptr->nl_route_info.attr_info.priority, + dev_name); + + /* insert to command queue */ + data_addr = (ipacm_event_data_addr *)malloc(sizeof(ipacm_event_data_addr)); + if(data_addr == NULL) + { + IPACMERR("unable to allocate memory for event data_addr\n"); + return IPACM_FAILURE; + } + + IPACM_EVENT_COPY_ADDR_v6( data_addr->ipv6_addr, msg_ptr->nl_route_info.attr_info.dst_addr); + + data_addr->ipv6_addr[0]=ntohl(data_addr->ipv6_addr[0]); + data_addr->ipv6_addr[1]=ntohl(data_addr->ipv6_addr[1]); + data_addr->ipv6_addr[2]=ntohl(data_addr->ipv6_addr[2]); + data_addr->ipv6_addr[3]=ntohl(data_addr->ipv6_addr[3]); + + IPACM_EVENT_COPY_ADDR_v6( data_addr->ipv6_addr_mask, msg_ptr->nl_route_info.attr_info.dst_addr); + + data_addr->ipv6_addr_mask[0]=ntohl(data_addr->ipv6_addr_mask[0]); + data_addr->ipv6_addr_mask[1]=ntohl(data_addr->ipv6_addr_mask[1]); + data_addr->ipv6_addr_mask[2]=ntohl(data_addr->ipv6_addr_mask[2]); + data_addr->ipv6_addr_mask[3]=ntohl(data_addr->ipv6_addr_mask[3]); + + evt_data.event = IPA_ROUTE_ADD_EVENT; + data_addr->if_index = msg_ptr->nl_route_info.attr_info.oif_index; + data_addr->iptype = IPA_IP_v6; + + IPACMDBG("posting IPA_ROUTE_ADD_EVENT with if index:%d, ipv6 address\n", + data_addr->if_index); + evt_data.evt_data = data_addr; + IPACM_EvtDispatcher::PostEvt(&evt_data); + /* finish command queue */ + } + } + break; + + case RTM_DELROUTE: + if(IPACM_SUCCESS != ipa_nl_decode_rtm_route(buffer, buflen, &(msg_ptr->nl_route_info))) + { + IPACMERR("Failed to decode rtm route message\n"); + return IPACM_FAILURE; + } + /* take care of route delete of default route & uniroute */ + if((msg_ptr->nl_route_info.metainfo.rtm_type == RTN_UNICAST) && + ((msg_ptr->nl_route_info.metainfo.rtm_protocol == RTPROT_BOOT) || + (msg_ptr->nl_route_info.metainfo.rtm_protocol == RTPROT_RA)) && + (msg_ptr->nl_route_info.metainfo.rtm_scope == 0) && + (msg_ptr->nl_route_info.metainfo.rtm_table == RT_TABLE_MAIN)) + { + + if(msg_ptr->nl_route_info.attr_info.param_mask & IPA_RTA_PARAM_DST) + { + ret_val = ipa_get_if_name(dev_name, msg_ptr->nl_route_info.attr_info.oif_index); + if(ret_val != IPACM_SUCCESS) + { + IPACMERR("Error while getting interface name\n"); + return IPACM_FAILURE; + } + IPACM_NL_REPORT_ADDR( "route del -host ", msg_ptr->nl_route_info.attr_info.dst_addr); + IPACM_NL_REPORT_ADDR( " gw ", msg_ptr->nl_route_info.attr_info.gateway_addr); + IPACMDBG("dev %s\n", dev_name); + + /* insert to command queue */ + data_addr = (ipacm_event_data_addr *)malloc(sizeof(ipacm_event_data_addr)); + if(data_addr == NULL) + { + IPACMERR("unable to allocate memory for event data_addr\n"); + return IPACM_FAILURE; + } + IPACM_EVENT_COPY_ADDR_v4( if_ipv4_addr, msg_ptr->nl_route_info.attr_info.dst_addr); + temp = (-1); + if_ipipv4_addr_mask = ntohl(temp); + + evt_data.event = IPA_ROUTE_DEL_EVENT; + data_addr->if_index = msg_ptr->nl_route_info.attr_info.oif_index; + data_addr->iptype = IPA_IP_v4; + data_addr->ipv4_addr = ntohl(if_ipv4_addr); + data_addr->ipv4_addr_mask = ntohl(if_ipipv4_addr_mask); + + IPACMDBG_H("Posting event IPA_ROUTE_DEL_EVENT with if index:%d, ipv4 address 0x%x, mask:0x%x\n", + data_addr->if_index, + data_addr->ipv4_addr, + data_addr->ipv4_addr_mask); + evt_data.evt_data = data_addr; + IPACM_EvtDispatcher::PostEvt(&evt_data); + /* finish command queue */ + } + else + { + ret_val = ipa_get_if_name(dev_name, msg_ptr->nl_route_info.attr_info.oif_index); + if(ret_val != IPACM_SUCCESS) + { + IPACMERR("Error while getting interface name\n"); + return IPACM_FAILURE; + } + + /* insert to command queue */ + data_addr = (ipacm_event_data_addr *)malloc(sizeof(ipacm_event_data_addr)); + if(data_addr == NULL) + { + IPACMERR("unable to allocate memory for event data_addr\n"); + return IPACM_FAILURE; + } + + if(AF_INET6 == msg_ptr->nl_route_info.metainfo.rtm_family) + { + if(msg_ptr->nl_route_info.attr_info.param_mask & IPA_RTA_PARAM_PRIORITY) + { + IPACMDBG("ip -6 route del default dev %s metric %d\n", + dev_name, + msg_ptr->nl_route_info.attr_info.priority); + } + else + { + IPACMDBG("ip -6 route del default dev %s\n", dev_name); + } + IPACM_EVENT_COPY_ADDR_v6( data_addr->ipv6_addr, msg_ptr->nl_route_info.attr_info.dst_addr); + data_addr->ipv6_addr[0] = ntohl(data_addr->ipv6_addr[0]); + data_addr->ipv6_addr[1] = ntohl(data_addr->ipv6_addr[1]); + data_addr->ipv6_addr[2] = ntohl(data_addr->ipv6_addr[2]); + data_addr->ipv6_addr[3] = ntohl(data_addr->ipv6_addr[3]); + + IPACM_EVENT_COPY_ADDR_v6( data_addr->ipv6_addr_mask, msg_ptr->nl_route_info.attr_info.dst_addr); + data_addr->ipv6_addr_mask[0] = ntohl(data_addr->ipv6_addr_mask[0]); + data_addr->ipv6_addr_mask[1] = ntohl(data_addr->ipv6_addr_mask[1]); + data_addr->ipv6_addr_mask[2] = ntohl(data_addr->ipv6_addr_mask[2]); + data_addr->ipv6_addr_mask[3] = ntohl(data_addr->ipv6_addr_mask[3]); + + IPACM_EVENT_COPY_ADDR_v6( data_addr->ipv6_addr_gw, msg_ptr->nl_route_info.attr_info.gateway_addr); + data_addr->ipv6_addr_gw[0] = ntohl(data_addr->ipv6_addr_gw[0]); + data_addr->ipv6_addr_gw[1] = ntohl(data_addr->ipv6_addr_gw[1]); + data_addr->ipv6_addr_gw[2] = ntohl(data_addr->ipv6_addr_gw[2]); + data_addr->ipv6_addr_gw[3] = ntohl(data_addr->ipv6_addr_gw[3]); + IPACM_NL_REPORT_ADDR( " ", msg_ptr->nl_route_info.attr_info.gateway_addr); + data_addr->iptype = IPA_IP_v6; + } + else + { + IPACM_NL_REPORT_ADDR( "route del default gw", msg_ptr->nl_route_info.attr_info.gateway_addr); + IPACMDBG("dev %s\n", dev_name); + + IPACM_EVENT_COPY_ADDR_v4( data_addr->ipv4_addr, msg_ptr->nl_route_info.attr_info.dst_addr); + data_addr->ipv4_addr = ntohl(data_addr->ipv4_addr); + + IPACM_EVENT_COPY_ADDR_v4( data_addr->ipv4_addr_mask, msg_ptr->nl_route_info.attr_info.dst_addr); + data_addr->ipv4_addr_mask = ntohl(data_addr->ipv4_addr_mask); + + data_addr->iptype = IPA_IP_v4; + } + + evt_data.event = IPA_ROUTE_DEL_EVENT; + data_addr->if_index = msg_ptr->nl_route_info.attr_info.oif_index; + + IPACMDBG_H("Posting IPA_ROUTE_DEL_EVENT with if index:%d\n", + data_addr->if_index); + evt_data.evt_data = data_addr; + IPACM_EvtDispatcher::PostEvt(&evt_data); + /* finish command queue */ + } + } + + /* ipv6 routing table */ + if((AF_INET6 == msg_ptr->nl_route_info.metainfo.rtm_family) && + (msg_ptr->nl_route_info.metainfo.rtm_type == RTN_UNICAST) && + (msg_ptr->nl_route_info.metainfo.rtm_protocol == RTPROT_KERNEL) && + (msg_ptr->nl_route_info.metainfo.rtm_table == RT_TABLE_MAIN)) + { + IPACMDBG("\n GOT valid v6-RTM_DELROUTE event\n"); + ret_val = ipa_get_if_name(dev_name, msg_ptr->nl_route_info.attr_info.oif_index); + if(ret_val != IPACM_SUCCESS) + { + IPACMERR("Error while getting interface name"); + return IPACM_FAILURE; + } + + if(msg_ptr->nl_route_info.attr_info.param_mask & IPA_RTA_PARAM_DST) + { + IPACM_NL_REPORT_ADDR( "DEL", msg_ptr->nl_route_info.attr_info.dst_addr); + IPACMDBG("/%d, metric %d, dev %s\n", + msg_ptr->nl_route_info.metainfo.rtm_dst_len, + msg_ptr->nl_route_info.attr_info.priority, + dev_name); + + /* insert to command queue */ + data_addr = (ipacm_event_data_addr *)malloc(sizeof(ipacm_event_data_addr)); + if(data_addr == NULL) + { + IPACMERR("unable to allocate memory for event data_addr\n"); + return IPACM_FAILURE; + } + + IPACM_EVENT_COPY_ADDR_v6( data_addr->ipv6_addr, msg_ptr->nl_route_info.attr_info.dst_addr); + + data_addr->ipv6_addr[0] = ntohl(data_addr->ipv6_addr[0]); + data_addr->ipv6_addr[1] = ntohl(data_addr->ipv6_addr[1]); + data_addr->ipv6_addr[2] = ntohl(data_addr->ipv6_addr[2]); + data_addr->ipv6_addr[3] = ntohl(data_addr->ipv6_addr[3]); + + mask_value_v6 = msg_ptr->nl_route_info.metainfo.rtm_dst_len; + for(mask_index = 0; mask_index < 4; mask_index++) + { + IPACMDBG("%dst %d \n", + mask_index, + mask_value_v6); + if(mask_value_v6 >= 32) + { + mask_v6(32, &data_addr->ipv6_addr_mask[mask_index]); + mask_value_v6 -= 32; + IPACMDBG("%dst: %08x \n", + mask_index, + data_addr->ipv6_addr_mask[mask_index]); + } + else + { + mask_v6(mask_value_v6, data_addr->ipv6_addr_mask); + mask_value_v6 = 0; + IPACMDBG("%dst: %08x \n", + mask_index, + data_addr->ipv6_addr_mask[mask_index]); + } + } + + IPACMDBG("DEL IPV6 MASK 0st: %08x ", + data_addr->ipv6_addr_mask[0]); + IPACMDBG("1st: %08x ", + data_addr->ipv6_addr_mask[1]); + IPACMDBG("2st: %08x ", + data_addr->ipv6_addr_mask[2]); + IPACMDBG("3st: %08x \n", + data_addr->ipv6_addr_mask[3]); + + data_addr->ipv6_addr_mask[0] = ntohl(data_addr->ipv6_addr_mask[0]); + data_addr->ipv6_addr_mask[1] = ntohl(data_addr->ipv6_addr_mask[1]); + data_addr->ipv6_addr_mask[2] = ntohl(data_addr->ipv6_addr_mask[2]); + data_addr->ipv6_addr_mask[3] = ntohl(data_addr->ipv6_addr_mask[3]); + + evt_data.event = IPA_ROUTE_DEL_EVENT; + data_addr->if_index = msg_ptr->nl_route_info.attr_info.oif_index; + data_addr->iptype = IPA_IP_v6; + + IPACMDBG_H("posting event IPA_ROUTE_DEL_EVENT with if index:%d, ipv4 address\n", + data_addr->if_index); + evt_data.evt_data = data_addr; + IPACM_EvtDispatcher::PostEvt(&evt_data); + /* finish command queue */ + } + } + break; + + case RTM_NEWNEIGH: + if(IPACM_SUCCESS != ipa_nl_decode_rtm_neigh(buffer, buflen, &(msg_ptr->nl_neigh_info))) + { + IPACMERR("Failed to decode rtm neighbor message\n"); + return IPACM_FAILURE; + } + + ret_val = ipa_get_if_name(dev_name, msg_ptr->nl_neigh_info.metainfo.ndm_ifindex); + if(ret_val != IPACM_SUCCESS) + { + IPACMERR("Error while getting interface index\n"); + return IPACM_FAILURE; + } + else + { + IPACMDBG("\n GOT RTM_NEWNEIGH event (%s) ip %d\n",dev_name,msg_ptr->nl_neigh_info.attr_info.local_addr.ss_family); + } + + /* insert to command queue */ + data_all = (ipacm_event_data_all *)malloc(sizeof(ipacm_event_data_all)); + if(data_all == NULL) + { + IPACMERR("unable to allocate memory for event data_all\n"); + return IPACM_FAILURE; + } + + memset(data_all, 0, sizeof(ipacm_event_data_all)); + if(msg_ptr->nl_neigh_info.attr_info.local_addr.ss_family == AF_INET6) + { + IPACM_NL_REPORT_ADDR( " ", msg_ptr->nl_neigh_info.attr_info.local_addr); + IPACM_EVENT_COPY_ADDR_v6( data_all->ipv6_addr, msg_ptr->nl_neigh_info.attr_info.local_addr); + + data_all->ipv6_addr[0]=ntohl(data_all->ipv6_addr[0]); + data_all->ipv6_addr[1]=ntohl(data_all->ipv6_addr[1]); + data_all->ipv6_addr[2]=ntohl(data_all->ipv6_addr[2]); + data_all->ipv6_addr[3]=ntohl(data_all->ipv6_addr[3]); + data_all->iptype = IPA_IP_v6; + } + else if (msg_ptr->nl_neigh_info.attr_info.local_addr.ss_family == AF_INET) + { + IPACM_NL_REPORT_ADDR( " ", msg_ptr->nl_neigh_info.attr_info.local_addr); + IPACM_EVENT_COPY_ADDR_v4( data_all->ipv4_addr, msg_ptr->nl_neigh_info.attr_info.local_addr); + data_all->ipv4_addr = ntohl(data_all->ipv4_addr); + data_all->iptype = IPA_IP_v4; + } + else + { + data_all->iptype = IPA_IP_v6; + } + + IPACMDBG("NDA_LLADDR:MAC %02x:%02x:%02x:%02x:%02x:%02x\n", + (unsigned char)(msg_ptr->nl_neigh_info.attr_info.lladdr_hwaddr).sa_data[0], + (unsigned char)(msg_ptr->nl_neigh_info.attr_info.lladdr_hwaddr).sa_data[1], + (unsigned char)(msg_ptr->nl_neigh_info.attr_info.lladdr_hwaddr).sa_data[2], + (unsigned char)(msg_ptr->nl_neigh_info.attr_info.lladdr_hwaddr).sa_data[3], + (unsigned char)(msg_ptr->nl_neigh_info.attr_info.lladdr_hwaddr).sa_data[4], + (unsigned char)(msg_ptr->nl_neigh_info.attr_info.lladdr_hwaddr).sa_data[5]); + + + memcpy(data_all->mac_addr, + msg_ptr->nl_neigh_info.attr_info.lladdr_hwaddr.sa_data, + sizeof(data_all->mac_addr)); + data_all->if_index = msg_ptr->nl_neigh_info.metainfo.ndm_ifindex; + /* Add support to replace src-mac as bridge0 mac */ + if((msg_ptr->nl_neigh_info.metainfo.ndm_family == AF_BRIDGE) && + (msg_ptr->nl_neigh_info.metainfo.ndm_state == NUD_PERMANENT)) + { + /* Posting IPA_BRIDGE_LINK_UP_EVENT event */ + evt_data.event = IPA_BRIDGE_LINK_UP_EVENT; + IPACMDBG_H("posting IPA_BRIDGE_LINK_UP_EVENT (%s):index:%d \n", + dev_name, + data_all->if_index); + } + else + { + /* Posting new_neigh events for all LAN/WAN clients */ + evt_data.event = IPA_NEW_NEIGH_EVENT; + IPACMDBG_H("posting IPA_NEW_NEIGH_EVENT (%s):index:%d ip-family: %d\n", + dev_name, + data_all->if_index, + msg_ptr->nl_neigh_info.attr_info.local_addr.ss_family); + } + evt_data.evt_data = data_all; + IPACM_EvtDispatcher::PostEvt(&evt_data); + /* finish command queue */ + break; + + case RTM_DELNEIGH: + if(IPACM_SUCCESS != ipa_nl_decode_rtm_neigh(buffer, buflen, &(msg_ptr->nl_neigh_info))) + { + IPACMERR("Failed to decode rtm neighbor message\n"); + return IPACM_FAILURE; + } + + ret_val = ipa_get_if_name(dev_name, msg_ptr->nl_neigh_info.metainfo.ndm_ifindex); + if(ret_val != IPACM_SUCCESS) + { + IPACMERR("Error while getting interface index\n"); + return IPACM_FAILURE; + } + else + { + IPACMDBG("\n GOT RTM_DELNEIGH event (%s) ip %d\n",dev_name,msg_ptr->nl_neigh_info.attr_info.local_addr.ss_family); + } + + /* insert to command queue */ + data_all = (ipacm_event_data_all *)malloc(sizeof(ipacm_event_data_all)); + if(data_all == NULL) + { + IPACMERR("unable to allocate memory for event data_all\n"); + return IPACM_FAILURE; + } + + memset(data_all, 0, sizeof(ipacm_event_data_all)); + if(msg_ptr->nl_neigh_info.attr_info.local_addr.ss_family == AF_INET6) + { + IPACM_NL_REPORT_ADDR( " ", msg_ptr->nl_neigh_info.attr_info.local_addr); + IPACM_EVENT_COPY_ADDR_v6( data_all->ipv6_addr, msg_ptr->nl_neigh_info.attr_info.local_addr); + + data_all->ipv6_addr[0] = ntohl(data_all->ipv6_addr[0]); + data_all->ipv6_addr[1] = ntohl(data_all->ipv6_addr[1]); + data_all->ipv6_addr[2] = ntohl(data_all->ipv6_addr[2]); + data_all->ipv6_addr[3] = ntohl(data_all->ipv6_addr[3]); + data_all->iptype = IPA_IP_v6; + } + else if (msg_ptr->nl_neigh_info.attr_info.local_addr.ss_family == AF_INET) + { + IPACM_NL_REPORT_ADDR( " ", msg_ptr->nl_neigh_info.attr_info.local_addr); + IPACM_EVENT_COPY_ADDR_v4( data_all->ipv4_addr, msg_ptr->nl_neigh_info.attr_info.local_addr); + data_all->ipv4_addr = ntohl(data_all->ipv4_addr); + data_all->iptype = IPA_IP_v4; + } + else + { + data_all->iptype = IPA_IP_v6; + } + + IPACMDBG("NDA_LLADDR:MAC %02x:%02x:%02x:%02x:%02x:%02x\n", + (unsigned char)(msg_ptr->nl_neigh_info.attr_info.lladdr_hwaddr).sa_data[0], + (unsigned char)(msg_ptr->nl_neigh_info.attr_info.lladdr_hwaddr).sa_data[1], + (unsigned char)(msg_ptr->nl_neigh_info.attr_info.lladdr_hwaddr).sa_data[2], + (unsigned char)(msg_ptr->nl_neigh_info.attr_info.lladdr_hwaddr).sa_data[3], + (unsigned char)(msg_ptr->nl_neigh_info.attr_info.lladdr_hwaddr).sa_data[4], + (unsigned char)(msg_ptr->nl_neigh_info.attr_info.lladdr_hwaddr).sa_data[5]); + + memcpy(data_all->mac_addr, + msg_ptr->nl_neigh_info.attr_info.lladdr_hwaddr.sa_data, + sizeof(data_all->mac_addr)); + evt_data.event = IPA_DEL_NEIGH_EVENT; + data_all->if_index = msg_ptr->nl_neigh_info.metainfo.ndm_ifindex; + + IPACMDBG_H("posting IPA_DEL_NEIGH_EVENT (%s):index:%d ip-family: %d\n", + dev_name, + data_all->if_index, + msg_ptr->nl_neigh_info.attr_info.local_addr.ss_family); + evt_data.evt_data = data_all; + IPACM_EvtDispatcher::PostEvt(&evt_data); + /* finish command queue */ + break; + + default: + IPACMDBG(" ignore NL event %d!!!\n ", nlh->nlmsg_type); + break; + + } + nlh = NLMSG_NEXT(nlh, buflen); + } + + return IPACM_SUCCESS; +} + + +/* Virtual function registered to receive incoming messages over the NETLINK routing socket*/ +int ipa_nl_recv_msg(int fd) +{ + struct msghdr *msghdr = NULL; + struct iovec *iov = NULL; + unsigned int msglen = 0; + ipa_nl_msg_t *nlmsg = NULL; + + nlmsg = (ipa_nl_msg_t *)malloc(sizeof(ipa_nl_msg_t)); + if(NULL == nlmsg) + { + IPACMERR("Failed alloc of nlmsg \n"); + goto error; + } + else + { + if(IPACM_SUCCESS != ipa_nl_recv(fd, &msghdr, &msglen)) + { + IPACMERR("Failed to receive nl message \n"); + goto error; + } + + if(msghdr== NULL) + { + IPACMERR(" failed to get msghdr\n"); + goto error; + } + + iov = msghdr->msg_iov; + + memset(nlmsg, 0, sizeof(ipa_nl_msg_t)); + if(IPACM_SUCCESS != ipa_nl_decode_nlmsg((char *)iov->iov_base, msglen, nlmsg)) + { + IPACMERR("Failed to decode nl message \n"); + goto error; + } + /* Release NetLink message buffer */ + if(msghdr) + { + ipa_nl_release_msg(msghdr); + } + if(nlmsg) + { + free(nlmsg); + } + } + + return IPACM_SUCCESS; + +error: + if(msghdr) + { + ipa_nl_release_msg(msghdr); + } + if(nlmsg) + { + free(nlmsg); + } + + return IPACM_FAILURE; +} + +/* get ipa interface name */ +int ipa_get_if_name +( + char *if_name, + int if_index + ) +{ + int fd; + struct ifreq ifr; + + if((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) + { + IPACMERR("get interface name socket create failed \n"); + return IPACM_FAILURE; + } + + memset(&ifr, 0, sizeof(struct ifreq)); + ifr.ifr_ifindex = if_index; + IPACMDBG("Interface index %d\n", if_index); + + if(ioctl(fd, SIOCGIFNAME, &ifr) < 0) + { + IPACMERR("call_ioctl_on_dev: ioctl failed:\n"); + close(fd); + return IPACM_FAILURE; + } + + (void)strncpy(if_name, ifr.ifr_name, sizeof(ifr.ifr_name)); + IPACMDBG("interface name %s\n", ifr.ifr_name); + close(fd); + + return IPACM_SUCCESS; +} + +/* Initialization routine for listener on NetLink sockets interface */ +int ipa_nl_listener_init +( + unsigned int nl_type, + unsigned int nl_groups, + ipa_nl_sk_fd_set_info_t *sk_fdset, + ipa_sock_thrd_fd_read_f read_f + ) +{ + ipa_nl_sk_info_t sk_info; + int ret_val; + + memset(&sk_info, 0, sizeof(ipa_nl_sk_info_t)); + IPACMDBG_H("Entering IPA NL listener init\n"); + + if(ipa_nl_open_socket(&sk_info, nl_type, nl_groups) == IPACM_SUCCESS) + { + IPACMDBG_H("IPA Open netlink socket succeeds\n"); + } + else + { + IPACMERR("Netlink socket open failed\n"); + return IPACM_FAILURE; + } + + /* Add NETLINK socket to the list of sockets that the listener + thread should listen on. */ + + if(ipa_nl_addfd_map(sk_fdset, sk_info.sk_fd, read_f) != IPACM_SUCCESS) + { + IPACMERR("cannot add nl routing sock for reading\n"); + close(sk_info.sk_fd); + return IPACM_FAILURE; + } + + /* Start the socket listener thread */ + ret_val = ipa_nl_sock_listener_start(sk_fdset); + + if(ret_val != IPACM_SUCCESS) + { + IPACMERR("Failed to start NL listener\n"); + } + + return IPACM_SUCCESS; +} + +/* find the newroute subnet mask */ +int find_mask(int ip_v4_last, int *mask_value) +{ + + switch(ip_v4_last) + { + + case 3: + *mask_value = 252; + return IPACM_SUCCESS; + break; + + case 7: + *mask_value = 248; + return IPACM_SUCCESS; + break; + + case 15: + *mask_value = 240; + return IPACM_SUCCESS; + break; + + case 31: + *mask_value = 224; + return IPACM_SUCCESS; + break; + + case 63: + *mask_value = 192; + return IPACM_SUCCESS; + break; + + case 127: + *mask_value = 128; + return IPACM_SUCCESS; + break; + + case 255: + *mask_value = 0; + return IPACM_SUCCESS; + break; + + default: + return IPACM_FAILURE; + break; + + } +} + +/* map mask value for ipv6 */ +int mask_v6(int index, uint32_t *mask) +{ + switch(index) + { + + case 0: + *mask = 0x00000000; + return IPACM_SUCCESS; + break; + case 4: + *mask = 0xf0000000; + return IPACM_SUCCESS; + break; + case 8: + *mask = 0xff000000; + return IPACM_SUCCESS; + break; + case 12: + *mask = 0xfff00000; + return IPACM_SUCCESS; + break; + case 16: + *mask = 0xffff0000; + return IPACM_SUCCESS; + break; + case 20: + *mask = 0xfffff000; + return IPACM_SUCCESS; + break; + case 24: + *mask = 0xffffff00; + return IPACM_SUCCESS; + break; + case 28: + *mask = 0xfffffff0; + return IPACM_SUCCESS; + break; + case 32: + *mask = 0xffffffff; + return IPACM_SUCCESS; + break; + default: + return IPACM_FAILURE; + break; + + } +} + + diff --git a/data-ipa-cfg-mgr/ipacm/src/IPACM_Routing.cpp b/data-ipa-cfg-mgr/ipacm/src/IPACM_Routing.cpp new file mode 100644 index 000000000..7ae61313f --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/src/IPACM_Routing.cpp @@ -0,0 +1,274 @@ +/* +Copyright (c) 2013, The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +/*! + @file + IPACM_Routing.cpp + + @brief + This file implements the IPACM routing functionality. + + @Author + +*/ + +#include +#include +#include +#include +#include + +#include "IPACM_Routing.h" +#include + +const char *IPACM_Routing::DEVICE_NAME = "/dev/ipa"; + +IPACM_Routing::IPACM_Routing() +{ + m_fd = open(DEVICE_NAME, O_RDWR); + if (0 == m_fd) + { + IPACMERR("Failed opening %s.\n", DEVICE_NAME); + } +} + +IPACM_Routing::~IPACM_Routing() +{ + close(m_fd); +} + +bool IPACM_Routing::DeviceNodeIsOpened() +{ + int res = fcntl(m_fd, F_GETFL); + + if (m_fd > 0 && res >= 0) return true; + else return false; + +} + +bool IPACM_Routing::AddRoutingRule(struct ipa_ioc_add_rt_rule *ruleTable) +{ + int retval = 0, cnt=0; + bool isInvalid = false; + + if (!DeviceNodeIsOpened()) + { + IPACMERR("Device is not opened\n"); + return false; + } + + for(cnt=0; cntnum_rules; cnt++) + { + if(ruleTable->rules[cnt].rule.dst > IPA_CLIENT_MAX) + { + IPACMERR("Invalid dst pipe, Rule:%d dst_pipe:%d\n", cnt, ruleTable->rules[cnt].rule.dst); + isInvalid = true; + } + } + + if(isInvalid) + { + return false; + } + + retval = ioctl(m_fd, IPA_IOC_ADD_RT_RULE, ruleTable); + if (retval) + { + IPACMERR("Failed adding routing rule %p\n", ruleTable); + return false; + } + + for(cnt=0; cntnum_rules; cnt++) + { + IPACMDBG("Rule:%d dst_pipe:%d\n", cnt, ruleTable->rules[cnt].rule.dst); + } + + IPACMDBG_H("Added routing rule %p\n", ruleTable); + return true; +} + +bool IPACM_Routing::DeleteRoutingRule(struct ipa_ioc_del_rt_rule *ruleTable) +{ + int retval = 0; + + if (!DeviceNodeIsOpened()) return false; + + retval = ioctl(m_fd, IPA_IOC_DEL_RT_RULE, ruleTable); + if (retval) + { + IPACMERR("Failed deleting routing rule table %p\n", ruleTable); + return false; + } + + IPACMDBG_H("Deleted routing rule %p\n", ruleTable); + return true; +} + +bool IPACM_Routing::Commit(enum ipa_ip_type ip) +{ + int retval = 0; + + if (!DeviceNodeIsOpened()) return false; + + retval = ioctl(m_fd, IPA_IOC_COMMIT_RT, ip); + if (retval) + { + IPACMERR("Failed commiting routing rules.\n"); + return false; + } + + IPACMDBG_H("Commited routing rules to IPA HW.\n"); + return true; +} + +bool IPACM_Routing::Reset(enum ipa_ip_type ip) +{ + int retval = 0; + + if (!DeviceNodeIsOpened()) return false; + + retval = ioctl(m_fd, IPA_IOC_RESET_RT, ip); + retval |= ioctl(m_fd, IPA_IOC_COMMIT_RT, ip); + if (retval) + { + IPACMERR("Failed resetting routing block.\n"); + return false; + } + + IPACMDBG_H("Reset command issued to IPA routing block.\n"); + return true; +} + +bool IPACM_Routing::GetRoutingTable(struct ipa_ioc_get_rt_tbl *routingTable) +{ + int retval = 0; + + if (!DeviceNodeIsOpened()) return false; + + retval = ioctl(m_fd, IPA_IOC_GET_RT_TBL, routingTable); + if (retval) + { + IPACMERR("IPA_IOCTL_GET_RT_TBL ioctl failed, routingTable =0x%p, retval=0x%x.\n", routingTable, retval); + return false; + } + + IPACMDBG_H("IPA_IOCTL_GET_RT_TBL ioctl issued to IPA routing block.\n"); + return true; +} + +bool IPACM_Routing::PutRoutingTable(uint32_t routingTableHandle) +{ + int retval = 0; + + if (!DeviceNodeIsOpened()) return false; + + retval = ioctl(m_fd, IPA_IOC_PUT_RT_TBL, routingTableHandle); + if (retval) + { + IPACMERR("IPA_IOCTL_PUT_RT_TBL ioctl failed.\n"); + return false; + } + + IPACMDBG_H("IPA_IOCTL_PUT_RT_TBL ioctl issued to IPA routing block.\n"); + return true; +} + +bool IPACM_Routing::DeleteRoutingHdl(uint32_t rt_rule_hdl, ipa_ip_type ip) +{ + const uint8_t NUM_RULES = 1; + struct ipa_ioc_del_rt_rule *rt_rule; + struct ipa_rt_rule_del *rt_rule_entry; + bool res = true; + int len = 0; + + if (rt_rule_hdl == 0) + { + IPACMERR(" No route handle passed. Ignoring it\n"); + return res; + } + + len = (sizeof(struct ipa_ioc_del_rt_rule)) + (NUM_RULES * sizeof(struct ipa_rt_rule_del)); + rt_rule = (struct ipa_ioc_del_rt_rule *)malloc(len); + if (rt_rule == NULL) + { + IPACMERR("unable to allocate memory for del route rule\n"); + return false; + } + + memset(rt_rule, 0, len); + rt_rule->commit = 1; + rt_rule->num_hdls = NUM_RULES; + rt_rule->ip = ip; + + rt_rule_entry = &rt_rule->hdl[0]; + rt_rule_entry->status = -1; + rt_rule_entry->hdl = rt_rule_hdl; + + IPACMDBG_H("Deleting Route hdl:(0x%x) with ip type: %d\n", rt_rule_entry->hdl, ip); + if ((false == DeleteRoutingRule(rt_rule)) || + (rt_rule_entry->status)) + { + PERROR("Routing rule deletion failed!\n"); + goto fail; + res = false; + } + +fail: + free(rt_rule); + + return res; +} + +bool IPACM_Routing::ModifyRoutingRule(struct ipa_ioc_mdfy_rt_rule *mdfyRules) +{ + int retval = 0, cnt; + + if (!DeviceNodeIsOpened()) + { + IPACMERR("Device is not opened\n"); + return false; + } + + retval = ioctl(m_fd, IPA_IOC_MDFY_RT_RULE, mdfyRules); + if (retval) + { + IPACMERR("Failed modifying routing rules %p\n", mdfyRules); + return false; + } + + for(cnt=0; cntnum_rules; cnt++) + { + if(mdfyRules->rules[cnt].status != 0) + { + IPACMERR("Unable to modify rule: %d\n", cnt); + } + } + + IPACMDBG_H("Modified routing rules %p\n", mdfyRules); + return true; +} diff --git a/data-ipa-cfg-mgr/ipacm/src/IPACM_Wan.cpp b/data-ipa-cfg-mgr/ipacm/src/IPACM_Wan.cpp new file mode 100644 index 000000000..575879f79 --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/src/IPACM_Wan.cpp @@ -0,0 +1,5925 @@ +/* +Copyright (c) 2013, The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +/*! + @file + IPACM_Wan.cpp + + @brief + This file implements the WAN iface functionality. + + @Author + Skylar Chang + +*/ +#include +#include +#include +#include +#include +#include +#include "IPACM_EvtDispatcher.h" +#include +#include "linux/rmnet_ipa_fd_ioctl.h" +#include "IPACM_Config.h" +#include "IPACM_Defs.h" +#include +#include "linux/ipa_qmi_service_v01.h" + +bool IPACM_Wan::wan_up = false; +bool IPACM_Wan::wan_up_v6 = false; +uint8_t IPACM_Wan::xlat_mux_id = 0; + +int IPACM_Wan::num_v4_flt_rule = 0; +int IPACM_Wan::num_v6_flt_rule = 0; + +struct ipa_flt_rule_add IPACM_Wan::flt_rule_v4[IPA_MAX_FLT_RULE]; +struct ipa_flt_rule_add IPACM_Wan::flt_rule_v6[IPA_MAX_FLT_RULE]; + +char IPACM_Wan::wan_up_dev_name[IF_NAME_LEN]; + +bool IPACM_Wan::backhaul_is_sta_mode = false; +bool IPACM_Wan::is_ext_prop_set = false; + +int IPACM_Wan::num_ipv4_modem_pdn = 0; +int IPACM_Wan::num_ipv6_modem_pdn = 0; + +bool IPACM_Wan::embms_is_on = false; +bool IPACM_Wan::backhaul_is_wan_bridge = false; + +uint32_t IPACM_Wan::backhaul_ipv6_prefix[2]; + +#ifdef FEATURE_IPA_ANDROID +int IPACM_Wan::ipa_if_num_tether_v4_total = 0; +int IPACM_Wan::ipa_if_num_tether_v6_total = 0; + +int IPACM_Wan::ipa_if_num_tether_v4[IPA_MAX_IFACE_ENTRIES]; +int IPACM_Wan::ipa_if_num_tether_v6[IPA_MAX_IFACE_ENTRIES]; +#endif + +IPACM_Wan::IPACM_Wan(int iface_index, + ipacm_wan_iface_type is_sta_mode, + uint8_t *mac_addr) : IPACM_Iface(iface_index) +{ + num_firewall_v4 = 0; + num_firewall_v6 = 0; + wan_route_rule_v4_hdl = NULL; + wan_route_rule_v6_hdl = NULL; + wan_route_rule_v6_hdl_a5 = NULL; + wan_client = NULL; + + if(iface_query != NULL) + { + wan_route_rule_v4_hdl = (uint32_t *)calloc(iface_query->num_tx_props, sizeof(uint32_t)); + wan_route_rule_v6_hdl = (uint32_t *)calloc(iface_query->num_tx_props, sizeof(uint32_t)); + wan_route_rule_v6_hdl_a5 = (uint32_t *)calloc(iface_query->num_tx_props, sizeof(uint32_t)); + IPACMDBG_H("IPACM->IPACM_Wan(%d) constructor: Tx:%d\n", ipa_if_num, iface_query->num_tx_props); + } + m_is_sta_mode = is_sta_mode; + + wan_v4_addr_set = false; + wan_v4_addr_gw_set = false; + wan_v6_addr_gw_set = false; + active_v4 = false; + active_v6 = false; + header_set_v4 = false; + header_set_v6 = false; + header_partial_default_wan_v4 = false; + header_partial_default_wan_v6 = false; + hdr_hdl_sta_v4 = 0; + hdr_hdl_sta_v6 = 0; + num_ipv6_dest_flt_rule = 0; + memset(ipv6_dest_flt_rule_hdl, 0, MAX_DEFAULT_v6_ROUTE_RULES*sizeof(uint32_t)); + memset(ipv6_prefix, 0, sizeof(ipv6_prefix)); + memset(wan_v6_addr_gw, 0, sizeof(wan_v6_addr_gw)); + ext_prop = NULL; + + num_wan_client = 0; + header_name_count = 0; + memset(invalid_mac, 0, sizeof(invalid_mac)); + + is_xlat = false; + + if(iface_query != NULL) + { + wan_client_len = (sizeof(ipa_wan_client)) + (iface_query->num_tx_props * sizeof(wan_client_rt_hdl)); + wan_client = (ipa_wan_client *)calloc(IPA_MAX_NUM_WAN_CLIENTS, wan_client_len); + if (wan_client == NULL) + { + IPACMERR("unable to allocate memory\n"); + return; + } + IPACMDBG_H("index:%d constructor: Tx properties:%d\n", iface_index, iface_query->num_tx_props); + } + + + if(m_is_sta_mode == Q6_WAN) + { + IPACMDBG_H("The new WAN interface is modem.\n"); + is_default_gateway = false; + query_ext_prop(); + } + else + { + IPACMDBG_H("The new WAN interface is WLAN STA.\n"); + } + + if(m_is_sta_mode == WLAN_WAN) + { + memcpy(ext_router_mac_addr, mac_addr, + sizeof(ext_router_mac_addr)); + } + + m_fd_ipa = open(IPA_DEVICE_NAME, O_RDWR); + if(0 == m_fd_ipa) + { + IPACMERR("Failed to open %s\n",IPA_DEVICE_NAME); + } + + if(IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat == EMBMS_IF) + { + IPACMDBG(" IPACM->IPACM_Wan_eMBMS(%d)\n", ipa_if_num); + embms_is_on = true; + install_wan_filtering_rule(false); + /* Add corresponding ipa_rm_resource_name of TX-endpoint up before IPV6 RT-rule set */ + if(tx_prop != NULL) + { + IPACMDBG_H("dev %s add producer dependency\n", dev_name); + IPACMDBG_H("depend Got pipe %d rm index : %d \n", tx_prop->tx[0].dst_pipe, IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe]); + IPACM_Iface::ipacmcfg->AddRmDepend(IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe],false); + } + } + else + { + IPACMDBG(" IPACM->IPACM_Wan(%d)\n", ipa_if_num); + } + return; +} + +IPACM_Wan::~IPACM_Wan() +{ + IPACM_EvtDispatcher::deregistr(this); + IPACM_IfaceManager::deregistr(this); + return; +} + +/* handle new_address event */ +int IPACM_Wan::handle_addr_evt(ipacm_event_data_addr *data) +{ + struct ipa_ioc_add_rt_rule *rt_rule; + struct ipa_rt_rule_add *rt_rule_entry; + struct ipa_ioc_add_flt_rule *flt_rule; + struct ipa_flt_rule_add flt_rule_entry; + struct ipa_ioc_get_hdr hdr; + + const int NUM_RULES = 1; + int num_ipv6_addr, len; + int res = IPACM_SUCCESS; + + memset(&hdr, 0, sizeof(hdr)); + if(tx_prop == NULL || rx_prop == NULL) + { + IPACMDBG_H("Either tx or rx property is NULL, return.\n"); + return IPACM_SUCCESS; + } + + if (data->iptype == IPA_IP_v6) + { + for(num_ipv6_addr=0;num_ipv6_addripv6_addr[0]) && + (ipv6_addr[num_ipv6_addr][1] == data->ipv6_addr[1]) && + (ipv6_addr[num_ipv6_addr][2] == data->ipv6_addr[2]) && + (ipv6_addr[num_ipv6_addr][3] == data->ipv6_addr[3])) + { + IPACMDBG_H("find matched ipv6 address, index:%d \n", num_ipv6_addr); + return IPACM_SUCCESS; + break; + } + } + rt_rule = (struct ipa_ioc_add_rt_rule *) + calloc(1, sizeof(struct ipa_ioc_add_rt_rule) + + NUM_RULES * sizeof(struct ipa_rt_rule_add)); + + if (!rt_rule) + { + IPACMERR("Error Locate ipa_ioc_add_rt_rule memory...\n"); + return IPACM_FAILURE; + } + + rt_rule->commit = 1; + rt_rule->num_rules = NUM_RULES; + rt_rule->ip = data->iptype; + strlcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_v6.name, sizeof(rt_rule->rt_tbl_name)); + + rt_rule_entry = &rt_rule->rules[0]; + if(m_is_sta_mode == Q6_WAN) + { + strlcpy(hdr.name, tx_prop->tx[0].hdr_name, sizeof(hdr.name)); + hdr.name[IPA_RESOURCE_NAME_MAX-1] = '\0'; + if(m_header.GetHeaderHandle(&hdr) == false) + { + IPACMERR("Failed to get QMAP header.\n"); + return IPACM_FAILURE; + } + rt_rule_entry->rule.hdr_hdl = hdr.hdl; + } + rt_rule_entry->at_rear = false; + if(m_is_sta_mode == Q6_WAN) + { + rt_rule_entry->rule.dst = IPA_CLIENT_APPS_WAN_CONS; + } + else + { + rt_rule_entry->rule.dst = IPA_CLIENT_APPS_LAN_CONS; + } + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = data->ipv6_addr[0]; + rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = data->ipv6_addr[1]; + rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = data->ipv6_addr[2]; + rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = data->ipv6_addr[3]; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF; + ipv6_addr[num_dft_rt_v6][0] = data->ipv6_addr[0]; + ipv6_addr[num_dft_rt_v6][1] = data->ipv6_addr[1]; + ipv6_addr[num_dft_rt_v6][2] = data->ipv6_addr[2]; + ipv6_addr[num_dft_rt_v6][3] = data->ipv6_addr[3]; +#ifdef FEATURE_IPA_V3 + rt_rule_entry->rule.hashable = IPA_RULE_NON_HASHABLE; +#endif + if (false == m_routing.AddRoutingRule(rt_rule)) + { + IPACMERR("Routing rule addition failed!\n"); + res = IPACM_FAILURE; + goto fail; + } + else if (rt_rule_entry->status) + { + IPACMERR("rt rule adding failed. Result=%d\n", rt_rule_entry->status); + res = rt_rule_entry->status; + goto fail; + } + dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES + 2*num_dft_rt_v6] = rt_rule_entry->rt_rule_hdl; + + /* setup same rule for v6_wan table*/ + strlcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.name, sizeof(rt_rule->rt_tbl_name)); + if (false == m_routing.AddRoutingRule(rt_rule)) + { + IPACMERR("Routing rule addition failed!\n"); + res = IPACM_FAILURE; + goto fail; + } + else if (rt_rule_entry->status) + { + IPACMERR("rt rule adding failed. Result=%d\n", rt_rule_entry->status); + res = rt_rule_entry->status; + goto fail; + } + dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES + 2*num_dft_rt_v6+1] = rt_rule_entry->rt_rule_hdl; + + IPACMDBG_H("ipv6 wan iface rt-rule hdl=0x%x hdl=0x%x, num_dft_rt_v6: %d \n", + dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES + 2*num_dft_rt_v6], + dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES + 2*num_dft_rt_v6+1],num_dft_rt_v6); + + /* Update the IP Type. */ + config_ip_type(data->iptype); + + /* add default filtering rules when wan-iface get global v6-prefix */ + if (num_dft_rt_v6 == 1) + { + if(m_is_sta_mode == Q6_WAN) + { + modem_ipv6_pdn_index = num_ipv6_modem_pdn; + num_ipv6_modem_pdn++; + IPACMDBG_H("Now the number of modem ipv6 pdn is %d.\n", num_ipv6_modem_pdn); + init_fl_rule_ex(data->iptype); + } + else + { + init_fl_rule(data->iptype); + } + } + + /* add WAN DL interface IP specific flt rule for IPv6 when backhaul is not Q6 */ + if(m_is_sta_mode != Q6_WAN) + { + if(rx_prop != NULL && is_global_ipv6_addr(data->ipv6_addr) + && num_ipv6_dest_flt_rule < MAX_DEFAULT_v6_ROUTE_RULES) + { + len = sizeof(struct ipa_ioc_add_flt_rule) + sizeof(struct ipa_flt_rule_add); + + flt_rule = (struct ipa_ioc_add_flt_rule *)calloc(1, len); + if (!flt_rule) + { + IPACMERR("Error Locate ipa_flt_rule_add memory...\n"); + return IPACM_FAILURE; + } + + flt_rule->commit = 1; + flt_rule->ep = rx_prop->rx[0].src_pipe; + flt_rule->global = false; + flt_rule->ip = IPA_IP_v6; + flt_rule->num_rules = 1; + + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); + + flt_rule_entry.rule.retain_hdr = 1; + flt_rule_entry.rule.to_uc = 0; + flt_rule_entry.rule.eq_attrib_type = 0; + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl = -1; + flt_rule_entry.status = -1; + flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION; + memcpy(&flt_rule_entry.rule.attrib, &rx_prop->rx[0].attrib, sizeof(flt_rule_entry.rule.attrib)); + + flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; + memcpy(flt_rule_entry.rule.attrib.u.v6.dst_addr, data->ipv6_addr, sizeof(flt_rule_entry.rule.attrib.u.v6.dst_addr)); + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF; + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF; + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[2] = 0xFFFFFFFF; + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF; + memcpy(&(flt_rule->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + + if (m_filtering.AddFilteringRule(flt_rule) == false) + { + IPACMERR("Error Adding Filtering rule, aborting...\n"); + free(flt_rule); + res = IPACM_FAILURE; + goto fail; + } + else + { + IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1); + ipv6_dest_flt_rule_hdl[num_ipv6_dest_flt_rule] = flt_rule->rules[0].flt_rule_hdl; + IPACMDBG_H("IPv6 dest filter rule %d HDL:0x%x\n", num_ipv6_dest_flt_rule, ipv6_dest_flt_rule_hdl[num_ipv6_dest_flt_rule]); + num_ipv6_dest_flt_rule++; + free(flt_rule); + } + } + } + /* store ipv6 prefix if the ipv6 address is not link local */ + if(is_global_ipv6_addr(data->ipv6_addr)) + { + memcpy(ipv6_prefix, data->ipv6_addr, sizeof(ipv6_prefix)); + } + num_dft_rt_v6++; + } + else + { + if(wan_v4_addr_set) + { + /* check iface ipv4 same or not */ + if(data->ipv4_addr == wan_v4_addr) + { + IPACMDBG_H("Already setup device (%s) ipv4 and it didn't change(0x%x)\n", dev_name, data->ipv4_addr); + return IPACM_SUCCESS; + } + else + { + IPACMDBG_H(" device (%s) ipv4 addr is changed\n", dev_name); + /* Delete default v4 RT rule */ + IPACMDBG_H("Delete default v4 routing rules\n"); + if (m_routing.DeleteRoutingHdl(dft_rt_rule_hdl[0], IPA_IP_v4) == false) + { + IPACMERR("Routing old RT rule deletion failed!\n"); + res = IPACM_FAILURE; + goto fail; + } + } + } + + rt_rule = (struct ipa_ioc_add_rt_rule *) + calloc(1, sizeof(struct ipa_ioc_add_rt_rule) + + NUM_RULES * sizeof(struct ipa_rt_rule_add)); + + if (!rt_rule) + { + IPACMERR("Error Locate ipa_ioc_add_rt_rule memory...\n"); + return IPACM_FAILURE; + } + + rt_rule->commit = 1; + rt_rule->num_rules = NUM_RULES; + rt_rule->ip = data->iptype; + rt_rule_entry = &rt_rule->rules[0]; + if(m_is_sta_mode == Q6_WAN) + { + strlcpy(hdr.name, tx_prop->tx[0].hdr_name, sizeof(hdr.name)); + hdr.name[IPA_RESOURCE_NAME_MAX-1] = '\0'; + if(m_header.GetHeaderHandle(&hdr) == false) + { + IPACMERR("Failed to get QMAP header.\n"); + return IPACM_FAILURE; + } + rt_rule_entry->rule.hdr_hdl = hdr.hdl; + rt_rule_entry->rule.dst = IPA_CLIENT_APPS_WAN_CONS; + } + else + { + rt_rule_entry->rule.dst = IPA_CLIENT_APPS_LAN_CONS; + } + rt_rule_entry->at_rear = false; + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + /* still need setup v4 default routing rule to A5*/ + strlcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_lan_v4.name, sizeof(rt_rule->rt_tbl_name)); + rt_rule_entry->rule.attrib.u.v4.dst_addr = data->ipv4_addr; + rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF; +#ifdef FEATURE_IPA_V3 + rt_rule_entry->rule.hashable = IPA_RULE_NON_HASHABLE; +#endif + if (false == m_routing.AddRoutingRule(rt_rule)) + { + IPACMERR("Routing rule addition failed!\n"); + res = IPACM_FAILURE; + goto fail; + } + else if (rt_rule_entry->status) + { + IPACMERR("rt rule adding failed. Result=%d\n", rt_rule_entry->status); + res = rt_rule_entry->status; + goto fail; + } + dft_rt_rule_hdl[0] = rt_rule_entry->rt_rule_hdl; + IPACMDBG_H("ipv4 wan iface rt-rule hdll=0x%x\n", dft_rt_rule_hdl[0]); + /* initial multicast/broadcast/fragment filter rule */ + + /* Update the IP Type. */ + config_ip_type(data->iptype); + + /* only do one time */ + if(!wan_v4_addr_set) + { + /* initial multicast/broadcast/fragment filter rule */ + if(m_is_sta_mode == Q6_WAN) + { + modem_ipv4_pdn_index = num_ipv4_modem_pdn; + num_ipv4_modem_pdn++; + IPACMDBG_H("Now the number of modem ipv4 pdn is %d.\n", num_ipv4_modem_pdn); + init_fl_rule_ex(data->iptype); + } + else + { + init_fl_rule(data->iptype); + } + } + + wan_v4_addr = data->ipv4_addr; + wan_v4_addr_set = true; + IPACMDBG_H("Receved wan ipv4-addr:0x%x\n",wan_v4_addr); + } + + IPACMDBG_H("number of default route rules %d\n", num_dft_rt_v6); + +fail: + free(rt_rule); + + return res; +} + +void IPACM_Wan::event_callback(ipa_cm_event_id event, void *param) +{ + int ipa_interface_index; + + switch (event) + { + case IPA_WLAN_LINK_DOWN_EVENT: + { + if(m_is_sta_mode == WLAN_WAN) + { + ipacm_event_data_fid *data = (ipacm_event_data_fid *)param; + ipa_interface_index = iface_ipa_index_query(data->if_index); + if (ipa_interface_index == ipa_if_num) + { + IPACMDBG_H("Received IPA_WLAN_LINK_DOWN_EVENT\n"); + handle_down_evt(); + /* reset the STA-iface category to unknown */ + IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat = UNKNOWN_IF; + IPACMDBG_H("IPA_WAN_STA (%s):ipa_index (%d) instance close \n", IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].iface_name, ipa_if_num); + IPACM_Iface::ipacmcfg->DelNatIfaces(dev_name); // delete NAT-iface + delete this; + return; + } + } + } + break; + + case IPA_WAN_XLAT_CONNECT_EVENT: + { + IPACMDBG_H("Recieved IPA_WAN_XLAT_CONNECT_EVENT\n"); + ipacm_event_data_fid *data = (ipacm_event_data_fid *)param; + ipa_interface_index = IPACM_Iface::iface_ipa_index_query(data->if_index); + if ((ipa_interface_index == ipa_if_num) && (m_is_sta_mode == Q6_WAN)) + { + is_xlat = true; + IPACMDBG_H("WAN-LTE (%s) link up, iface: %d is_xlat: \n", + IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name,data->if_index, is_xlat); + } + break; + } + case IPA_CFG_CHANGE_EVENT: + { + if ( (IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat == ipa_if_cate) && + (m_is_sta_mode ==ECM_WAN)) + { + IPACMDBG_H("Received IPA_CFG_CHANGE_EVENT and category did not change(wan_mode:%d)\n", m_is_sta_mode); + IPACMDBG_H("Now the cradle wan mode is %d.\n", IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_mode); + if(is_default_gateway == true) + { + if(backhaul_is_wan_bridge == false && IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_mode == BRIDGE) + { + IPACMDBG_H("Cradle wan mode switch to bridge mode.\n"); + backhaul_is_wan_bridge = true; + } + else if(backhaul_is_wan_bridge == true && IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_mode == ROUTER) + { + IPACMDBG_H("Cradle wan mode switch to router mode.\n"); + backhaul_is_wan_bridge = false; + } + else + { + IPACMDBG_H("No cradle mode switch, return.\n"); + return; + } + /* post wan mode change event to LAN/WLAN */ + if(IPACM_Wan::wan_up == true) + { + IPACMDBG_H("This interface is default GW.\n"); + ipacm_cmd_q_data evt_data; + memset(&evt_data, 0, sizeof(evt_data)); + + ipacm_event_cradle_wan_mode *data_wan_mode = NULL; + data_wan_mode = (ipacm_event_cradle_wan_mode *)malloc(sizeof(ipacm_event_cradle_wan_mode)); + if(data_wan_mode == NULL) + { + IPACMERR("unable to allocate memory.\n"); + return; + } + data_wan_mode->cradle_wan_mode = IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_mode; + evt_data.event = IPA_CRADLE_WAN_MODE_SWITCH; + evt_data.evt_data = data_wan_mode; + IPACMDBG_H("Posting IPA_CRADLE_WAN_MODE_SWITCH event.\n"); + IPACM_EvtDispatcher::PostEvt(&evt_data); + } + /* update the firewall flt rule actions */ + if(active_v4) + { + del_dft_firewall_rules(IPA_IP_v4); + config_dft_firewall_rules(IPA_IP_v4); + } + if(active_v6) + { + del_dft_firewall_rules(IPA_IP_v6); + config_dft_firewall_rules(IPA_IP_v6); + } + } + else + { + IPACMDBG_H("This interface is not default GW, ignore.\n"); + } + } + else if ( (IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat != ipa_if_cate) && + (m_is_sta_mode ==ECM_WAN)) + { + IPACMDBG_H("Received IPA_CFG_CHANGE_EVENT and category changed(wan_mode:%d)\n", m_is_sta_mode); + /* posting link-up event for cradle use-case */ + ipacm_cmd_q_data evt_data; + memset(&evt_data, 0, sizeof(evt_data)); + + ipacm_event_data_fid *data_fid = NULL; + data_fid = (ipacm_event_data_fid *)malloc(sizeof(ipacm_event_data_fid)); + if(data_fid == NULL) + { + IPACMERR("unable to allocate memory for IPA_USB_LINK_UP_EVENT data_fid\n"); + return; + } + if(IPACM_Iface::ipa_get_if_index(dev_name, &(data_fid->if_index))) + { + IPACMERR("Error while getting interface index for %s device", dev_name); + } + evt_data.event = IPA_USB_LINK_UP_EVENT; + evt_data.evt_data = data_fid; + IPACMDBG_H("Posting event:%d\n", evt_data.event); + IPACM_EvtDispatcher::PostEvt(&evt_data); + + /* delete previous instance */ + handle_down_evt(); + IPACM_Iface::ipacmcfg->DelNatIfaces(dev_name); // delete NAT-iface + delete this; + return; + } + } + break; + + case IPA_LINK_DOWN_EVENT: + { + ipacm_event_data_fid *data = (ipacm_event_data_fid *)param; + ipa_interface_index = iface_ipa_index_query(data->if_index); + if (ipa_interface_index == ipa_if_num) + { + if(m_is_sta_mode == Q6_WAN) + { + IPACMDBG_H("Received IPA_LINK_DOWN_EVENT\n"); + handle_down_evt_ex(); + IPACMDBG_H("IPA_WAN_Q6 (%s):ipa_index (%d) instance close \n", IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].iface_name, ipa_if_num); + IPACM_Iface::ipacmcfg->DelNatIfaces(dev_name); // delete NAT-iface + delete this; + return; + } + else if (m_is_sta_mode == ECM_WAN) + { + IPACMDBG_H("Received IPA_LINK_DOWN_EVENT(wan_mode:%d)\n", m_is_sta_mode); + /* delete previous instance */ + handle_down_evt(); + IPACMDBG_H("IPA_WAN_CRADLE (%s):ipa_index (%d) instance close \n", IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].iface_name, ipa_if_num); + IPACM_Iface::ipacmcfg->DelNatIfaces(dev_name); // delete NAT-iface + delete this; + return; + } + } + } + break; + + case IPA_ADDR_ADD_EVENT: + { + ipacm_event_data_addr *data = (ipacm_event_data_addr *)param; + ipa_interface_index = iface_ipa_index_query(data->if_index); + + if ( (data->iptype == IPA_IP_v4 && data->ipv4_addr == 0) || + (data->iptype == IPA_IP_v6 && + data->ipv6_addr[0] == 0 && data->ipv6_addr[1] == 0 && + data->ipv6_addr[2] == 0 && data->ipv6_addr[3] == 0) ) + { + IPACMDBG_H("Invalid address, ignore IPA_ADDR_ADD_EVENT event\n"); + return; + } + + if (ipa_interface_index == ipa_if_num) + { + IPACMDBG_H("Get IPA_ADDR_ADD_EVENT: IF ip type %d, incoming ip type %d\n", ip_type, data->iptype); + /* check v4 not setup before, v6 can have 2 iface ip */ + if( (data->iptype == IPA_IP_v4) + || ((data->iptype==IPA_IP_v6) && (num_dft_rt_v6!=MAX_DEFAULT_v6_ROUTE_RULES))) + { + IPACMDBG_H("Got IPA_ADDR_ADD_EVENT ip-family:%d, v6 num %d: \n",data->iptype,num_dft_rt_v6); + handle_addr_evt(data); + /* checking if SW-RT_enable */ + if (IPACM_Iface::ipacmcfg->ipa_sw_rt_enable == true && + m_is_sta_mode != Q6_WAN) + { + /* handle software routing enable event*/ + IPACMDBG_H("IPA_SW_ROUTING_ENABLE for iface: %s \n",IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].iface_name); + handle_software_routing_enable(); + } + + } + } + } + break; + + + case IPA_WAN_UPSTREAM_ROUTE_ADD_EVENT: + { + ipacm_event_data_iptype *data = (ipacm_event_data_iptype *)param; + ipa_interface_index = iface_ipa_index_query(data->if_index); + if (ipa_interface_index == ipa_if_num) + { + IPACMDBG_H("Received IPA_WAN_UPSTREAM_ROUTE_ADD_EVENT (Android) for ip-type (%d)\n", data->iptype); + /* The special below condition is to handle default gateway */ + if ((data->iptype == IPA_IP_v4) && (ip_type == IPA_IP_v4 || ip_type == IPA_IP_MAX)) + { + if (active_v4 == false) + { + IPACMDBG_H("adding routing table(upstream), dev (%s) ip-type(%d)\n", dev_name,data->iptype); + handle_route_add_evt(data->iptype); + } +#ifdef FEATURE_IPA_ANDROID + /* using ipa_if_index, not netdev_index */ + post_wan_up_tether_evt(data->iptype, iface_ipa_index_query(data->if_index_tether)); +#endif + } + else if ((data->iptype == IPA_IP_v6) && (ip_type == IPA_IP_v6 || ip_type == IPA_IP_MAX)) + { + if (active_v6 == false) + { + IPACMDBG_H("\n get default v6 route (dst:00.00.00.00) upstream\n"); + handle_route_add_evt(data->iptype); + } +#ifdef FEATURE_IPA_ANDROID + /* using ipa_if_index, not netdev_index */ + post_wan_up_tether_evt(data->iptype, iface_ipa_index_query(data->if_index_tether)); +#endif + } + } + else /* double check if current default iface is not itself */ + { + if ((data->iptype == IPA_IP_v4) && (active_v4 == true)) + { + IPACMDBG_H("Received v4 IPA_WAN_UPSTREAM_ROUTE_ADD_EVENT for other iface (%s)\n", IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name); + IPACMDBG_H("need clean default v4 route (dst:0.0.0.0) for old iface (%s)\n", dev_name); +// wan_v4_addr_gw_set = false; /* android requires CnE change too */ + if(m_is_sta_mode == Q6_WAN) + { + del_wan_firewall_rule(IPA_IP_v4); + install_wan_filtering_rule(false); + handle_route_del_evt_ex(IPA_IP_v4); + } + else + { + del_dft_firewall_rules(IPA_IP_v4); + handle_route_del_evt(IPA_IP_v4); + } + } + else if ((data->iptype == IPA_IP_v6) && (active_v6 == true)) + { + IPACMDBG_H("Received v6 IPA_WAN_UPSTREAM_ROUTE_ADD_EVENT for other iface (%s)\n", IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name); + IPACMDBG_H("need clean default v6 route for old iface (%s)\n", dev_name); + if(m_is_sta_mode == Q6_WAN) + { + del_wan_firewall_rule(IPA_IP_v6); + install_wan_filtering_rule(false); + handle_route_del_evt_ex(IPA_IP_v6); + } + else + { + del_dft_firewall_rules(IPA_IP_v6); + handle_route_del_evt(IPA_IP_v6); + } + } + } + } + break; + + case IPA_WAN_UPSTREAM_ROUTE_DEL_EVENT: + { + ipacm_event_data_iptype *data = (ipacm_event_data_iptype *)param; + ipa_interface_index = iface_ipa_index_query(data->if_index); + if (ipa_interface_index == ipa_if_num) + { + IPACMDBG_H("Received IPA_WAN_UPSTREAM_ROUTE_DEL_EVENT\n"); + if ((data->iptype == IPA_IP_v4) && (active_v4 == true)) + { + IPACMDBG_H("get del default v4 route (dst:0.0.0.0)\n"); +// wan_v4_addr_gw_set = false; /* android requires CnE change too */ +#ifdef FEATURE_IPA_ANDROID + /* using ipa_if_index, not netdev_index */ + post_wan_down_tether_evt(data->iptype, iface_ipa_index_query(data->if_index_tether)); + /* no any ipv4 tether iface support*/ + if(IPACM_Wan::ipa_if_num_tether_v4_total != 0) + { + IPACMDBG_H("still have tether ipv4 client on upsteam iface\n"); + return; + } +#endif + if(m_is_sta_mode == Q6_WAN) + { + del_wan_firewall_rule(IPA_IP_v4); + install_wan_filtering_rule(false); + handle_route_del_evt_ex(IPA_IP_v4); + } + else + { + del_dft_firewall_rules(IPA_IP_v4); + handle_route_del_evt(IPA_IP_v4); + } + } + else if ((data->iptype == IPA_IP_v6) && (active_v6 == true)) + { +#ifdef FEATURE_IPA_ANDROID + /* using ipa_if_index, not netdev_index */ + post_wan_down_tether_evt(data->iptype, iface_ipa_index_query(data->if_index_tether)); + /* no any ipv6 tether iface support*/ + if(IPACM_Wan::ipa_if_num_tether_v6_total != 0) + { + IPACMDBG_H("still have tether ipv6 client on upsteam iface\n"); + return; + } +#endif + if(m_is_sta_mode == Q6_WAN) + { + del_wan_firewall_rule(IPA_IP_v6); + install_wan_filtering_rule(false); + handle_route_del_evt_ex(IPA_IP_v6); + } + else + { + del_dft_firewall_rules(IPA_IP_v6); + handle_route_del_evt(IPA_IP_v6); + } + } + } + } + break; + case IPA_NETWORK_STATS_UPDATE_EVENT: + { + ipa_get_apn_data_stats_resp_msg_v01 *data = (ipa_get_apn_data_stats_resp_msg_v01 *)param; + if (!data->apn_data_stats_list_valid) + { + IPACMERR("not valid APN\n"); + return; + } + else + { + handle_network_stats_update(data); + } + } + break; + case IPA_ROUTE_ADD_EVENT: + { + ipacm_event_data_addr *data = (ipacm_event_data_addr *)param; + ipa_interface_index = iface_ipa_index_query(data->if_index); + if (ipa_interface_index == ipa_if_num) + { + IPACMDBG_H("Received IPA_ROUTE_ADD_EVENT\n"); + IPACMDBG_H("ipv4 addr 0x%x\n", data->ipv4_addr); + IPACMDBG_H("ipv4 addr mask 0x%x\n", data->ipv4_addr_mask); + + /* The special below condition is to handle default gateway */ + if ((data->iptype == IPA_IP_v4) && (!data->ipv4_addr) && (!data->ipv4_addr_mask) && (active_v4 == false) + && (ip_type == IPA_IP_v4 || ip_type == IPA_IP_MAX)) + { + wan_v4_addr_gw = data->ipv4_addr_gw; + wan_v4_addr_gw_set = true; + IPACMDBG_H("adding routing table, dev (%s) ip-type(%d), default gw (%x)\n", dev_name,data->iptype, wan_v4_addr_gw); + /* Check & construct STA header */ + handle_sta_header_add_evt(); + handle_route_add_evt(data->iptype); + /* Add IPv6 routing table if XLAT is enabled */ + if(is_xlat && (m_is_sta_mode == Q6_WAN) && (active_v6 == false)) + { + IPACMDBG_H("XLAT enabled: adding IPv6 routing table dev (%s)\n", dev_name); + handle_route_add_evt(IPA_IP_v6); + } + } + else if ((data->iptype == IPA_IP_v6) && + (!data->ipv6_addr[0]) && (!data->ipv6_addr[1]) && (!data->ipv6_addr[2]) && (!data->ipv6_addr[3]) && + (active_v6 == false) && (ip_type == IPA_IP_v6 || ip_type == IPA_IP_MAX)) + { + IPACMDBG_H("\n get default v6 route (dst:00.00.00.00)\n"); + IPACMDBG_H(" IPV6 dst: %08x:%08x:%08x:%08x \n", + data->ipv6_addr[0], data->ipv6_addr[1], data->ipv6_addr[2], data->ipv6_addr[3]); + IPACMDBG_H(" IPV6 gateway: %08x:%08x:%08x:%08x \n", + data->ipv6_addr_gw[0], data->ipv6_addr_gw[1], data->ipv6_addr_gw[2], data->ipv6_addr_gw[3]); + wan_v6_addr_gw[0] = data->ipv6_addr_gw[0]; + wan_v6_addr_gw[1] = data->ipv6_addr_gw[1]; + wan_v6_addr_gw[2] = data->ipv6_addr_gw[2]; + wan_v6_addr_gw[3] = data->ipv6_addr_gw[3]; + wan_v6_addr_gw_set = true; + /* Check & construct STA header */ + handle_sta_header_add_evt(); + handle_route_add_evt(data->iptype); + } + } + else /* double check if current default iface is not itself */ + { + if ((data->iptype == IPA_IP_v4) && (!data->ipv4_addr) && (!data->ipv4_addr_mask) && (active_v4 == true)) + { + IPACMDBG_H("Received v4 IPA_ROUTE_ADD_EVENT for other iface (%s)\n", IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name); + IPACMDBG_H("ipv4 addr 0x%x\n", data->ipv4_addr); + IPACMDBG_H("ipv4 addr mask 0x%x\n", data->ipv4_addr_mask); + IPACMDBG_H("need clean default v4 route (dst:0.0.0.0) for old iface (%s)\n", dev_name); + wan_v4_addr_gw_set = false; + if(m_is_sta_mode == Q6_WAN) + { + del_wan_firewall_rule(IPA_IP_v4); + install_wan_filtering_rule(false); + handle_route_del_evt_ex(IPA_IP_v4); + } + else + { + del_dft_firewall_rules(IPA_IP_v4); + handle_route_del_evt(IPA_IP_v4); + } + } + else if ((data->iptype == IPA_IP_v6) && (!data->ipv6_addr[0]) && (!data->ipv6_addr[1]) && (!data->ipv6_addr[2]) && (!data->ipv6_addr[3]) && (active_v6 == true)) + { + IPACMDBG_H("Received v6 IPA_ROUTE_ADD_EVENT for other iface (%s)\n", IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name); + IPACMDBG_H("need clean default v6 route for old iface (%s)\n", dev_name); + if(m_is_sta_mode == Q6_WAN) + { + del_wan_firewall_rule(IPA_IP_v6); + install_wan_filtering_rule(false); + handle_route_del_evt_ex(IPA_IP_v6); + } + else + { + del_dft_firewall_rules(IPA_IP_v6); + handle_route_del_evt(IPA_IP_v6); + } + } + } + } + break; + + case IPA_ROUTE_DEL_EVENT: + { + ipacm_event_data_addr *data = (ipacm_event_data_addr *)param; + ipa_interface_index = iface_ipa_index_query(data->if_index); + if (ipa_interface_index == ipa_if_num) + { + IPACMDBG_H("Received IPA_ROUTE_DEL_EVENT\n"); + if ((data->iptype == IPA_IP_v4) && (!data->ipv4_addr) && (!data->ipv4_addr_mask) && (active_v4 == true)) + { + IPACMDBG_H("get del default v4 route (dst:0.0.0.0)\n"); + wan_v4_addr_gw_set = false; + if(m_is_sta_mode == Q6_WAN) + { + del_wan_firewall_rule(IPA_IP_v4); + install_wan_filtering_rule(false); + handle_route_del_evt_ex(IPA_IP_v4); + + if(is_xlat && active_v6 == true) + { + IPACMDBG_H("XLAT enabled: Delete IPv6 routing table dev (%s)\n", dev_name); + del_wan_firewall_rule(IPA_IP_v6); + install_wan_filtering_rule(false); + handle_route_del_evt_ex(IPA_IP_v6); + } + } + else + { + del_dft_firewall_rules(IPA_IP_v4); + handle_route_del_evt(IPA_IP_v4); + } + } + else if ((data->iptype == IPA_IP_v6) && (!data->ipv6_addr[0]) && (!data->ipv6_addr[1]) && (!data->ipv6_addr[2]) && (!data->ipv6_addr[3]) && (active_v6 == true)) + { + + IPACMDBG_H("get del default v6 route (dst:00.00.00.00)\n"); + if(m_is_sta_mode == Q6_WAN) + { + del_wan_firewall_rule(IPA_IP_v6); + install_wan_filtering_rule(false); + handle_route_del_evt_ex(IPA_IP_v6); + } + else + { + del_dft_firewall_rules(IPA_IP_v6); + handle_route_del_evt(IPA_IP_v6); + } + } + } + } + break; + + case IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT: + { + ipacm_event_data_all *data = (ipacm_event_data_all *)param; + ipa_interface_index = iface_ipa_index_query(data->if_index); + + if (ipa_interface_index == ipa_if_num) + { + IPACMDBG_H("Received IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT in STA mode\n"); + + if (m_is_sta_mode == WLAN_WAN) + { + if (data->iptype == IPA_IP_v4 && data->ipv4_addr == wan_v4_addr) + { + IPACMDBG_H("Ignore IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT in STA mode\n"); + IPACMDBG_H("for its own ipv4 address\n"); + return; + } + else if (data->iptype == IPA_IP_v6) + { + for (int num_ipv6_addr = 0; num_ipv6_addr < num_dft_rt_v6; num_ipv6_addr++) + { + if ((ipv6_addr[num_ipv6_addr][0] == data->ipv6_addr[0]) && + (ipv6_addr[num_ipv6_addr][1] == data->ipv6_addr[1]) && + (ipv6_addr[num_ipv6_addr][2] == data->ipv6_addr[2]) && + (ipv6_addr[num_ipv6_addr][3] == data->ipv6_addr[3])) + { + IPACMDBG_H("Ignore IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT in STA mode\n"); + IPACMDBG_H("for its own ipv6 address\n"); + return; + } + } + } + } + + IPACMDBG_H("wan-iface got client \n"); + /* first construc WAN-client full header */ + if(memcmp(data->mac_addr, + invalid_mac, + sizeof(data->mac_addr)) == 0) + { + IPACMDBG_H("Received invalid Client MAC %02x:%02x:%02x:%02x:%02x:%02x\n", + data->mac_addr[0], data->mac_addr[1], data->mac_addr[2], + data->mac_addr[3], data->mac_addr[4], data->mac_addr[5]); + return; + } + + handle_wan_hdr_init(data->mac_addr); + IPACMDBG_H("construct wan-client header and route rules \n"); + /* Associate with IP and construct RT-rule */ + if (handle_wan_client_ipaddr(data) == IPACM_FAILURE) + { + return; + } + handle_wan_client_route_rule(data->mac_addr, data->iptype); + /* Check & construct STA header */ + handle_sta_header_add_evt(); + return; + } + } + break; + + case IPA_SW_ROUTING_ENABLE: + IPACMDBG_H("Received IPA_SW_ROUTING_ENABLE\n"); + /* handle software routing enable event */ + if(m_is_sta_mode == Q6_WAN) + { + install_wan_filtering_rule(true); + } + else + { + handle_software_routing_enable(); + } + break; + + case IPA_SW_ROUTING_DISABLE: + IPACMDBG_H("Received IPA_SW_ROUTING_DISABLE\n"); + /* handle software routing disable event */ + if(m_is_sta_mode == Q6_WAN) + { + /* send current DL rules to modem */ + install_wan_filtering_rule(false); + softwarerouting_act = false; + } + else + { + handle_software_routing_disable(); + } + break; + + case IPA_FIREWALL_CHANGE_EVENT: + IPACMDBG_H("Received IPA_FIREWALL_CHANGE_EVENT\n"); + + if(m_is_sta_mode == Q6_WAN) + { + if(is_default_gateway == false) + { + IPACMDBG_H("Interface %s is not default gw, return.\n", dev_name); + return; + } + + if(ip_type == IPA_IP_v4) + { + del_wan_firewall_rule(IPA_IP_v4); + config_wan_firewall_rule(IPA_IP_v4); + install_wan_filtering_rule(false); + } + else if(ip_type == IPA_IP_v6) + { + del_wan_firewall_rule(IPA_IP_v6); + config_wan_firewall_rule(IPA_IP_v6); + install_wan_filtering_rule(false); + } + else if(ip_type == IPA_IP_MAX) + { + del_wan_firewall_rule(IPA_IP_v4); + config_wan_firewall_rule(IPA_IP_v4); + + del_wan_firewall_rule(IPA_IP_v6); + config_wan_firewall_rule(IPA_IP_v6); + install_wan_filtering_rule(false); + } + else + { + IPACMERR("IP type is not expected.\n"); + } + } + else + { + if (active_v4) + { + del_dft_firewall_rules(IPA_IP_v4); + config_dft_firewall_rules(IPA_IP_v4); + } + if (active_v6) + { + + del_dft_firewall_rules(IPA_IP_v6); + config_dft_firewall_rules(IPA_IP_v6); + } + } + break; + + case IPA_WLAN_SWITCH_TO_SCC: + if(IPACM_Wan::backhaul_is_sta_mode == true) + { + IPACMDBG_H("Received IPA_WLAN_SWITCH_TO_SCC\n"); + if(ip_type == IPA_IP_MAX) + { + handle_wlan_SCC_MCC_switch(true, IPA_IP_v4); + handle_wlan_SCC_MCC_switch(true, IPA_IP_v6); + handle_wan_client_SCC_MCC_switch(true, IPA_IP_v4); + handle_wan_client_SCC_MCC_switch(true, IPA_IP_v6); + } + else + { + handle_wlan_SCC_MCC_switch(true, ip_type); + handle_wan_client_SCC_MCC_switch(true, ip_type); + } + } + break; + + case IPA_WLAN_SWITCH_TO_MCC: + if(IPACM_Wan::backhaul_is_sta_mode == true) + { + IPACMDBG_H("Received IPA_WLAN_SWITCH_TO_MCC\n"); + if(ip_type == IPA_IP_MAX) + { + handle_wlan_SCC_MCC_switch(false, IPA_IP_v4); + handle_wlan_SCC_MCC_switch(false, IPA_IP_v6); + handle_wan_client_SCC_MCC_switch(false, IPA_IP_v4); + handle_wan_client_SCC_MCC_switch(false, IPA_IP_v6); + } + else + { + handle_wlan_SCC_MCC_switch(false, ip_type); + handle_wan_client_SCC_MCC_switch(false, ip_type); + } + } + break; + + default: + break; + } + + return; +} + +/* wan default route/filter rule configuration */ +int IPACM_Wan::handle_route_add_evt(ipa_ip_type iptype) +{ + + /* add default WAN route */ + struct ipa_ioc_add_rt_rule *rt_rule = NULL; + struct ipa_rt_rule_add *rt_rule_entry; + struct ipa_ioc_get_hdr sRetHeader; + uint32_t cnt, tx_index = 0; + const int NUM = 1; + ipacm_cmd_q_data evt_data; + struct ipa_ioc_copy_hdr sCopyHeader; /* checking if partial header*/ + struct ipa_ioc_get_hdr hdr; + + IPACMDBG_H("ip-type:%d\n", iptype); + + /* copy header from tx-property, see if partial or not */ + /* assume all tx-property uses the same header name for v4 or v6*/ + + if(tx_prop == NULL) + { + IPACMDBG_H("No tx properties, ignore default route setting\n"); + return IPACM_SUCCESS; + } + + is_default_gateway = true; + IPACMDBG_H("Default route is added to iface %s.\n", dev_name); + memcpy(backhaul_ipv6_prefix, ipv6_prefix, sizeof(backhaul_ipv6_prefix)); + IPACMDBG_H("Setup backhaul ipv6 prefix to be 0x%08x%08x.\n", backhaul_ipv6_prefix[0], backhaul_ipv6_prefix[1]); + + if(IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_mode == BRIDGE) + { + IPACM_Wan::backhaul_is_wan_bridge = true; + } + else + { + IPACM_Wan::backhaul_is_wan_bridge = false; + } + IPACMDBG_H("backhaul_is_wan_bridge ?: %d \n", IPACM_Wan::backhaul_is_wan_bridge); + + if (m_is_sta_mode !=Q6_WAN) + { + IPACM_Wan::backhaul_is_sta_mode = true; + + if((iptype==IPA_IP_v4) && (header_set_v4 != true)) + { + header_partial_default_wan_v4 = true; + IPACMDBG_H("STA ipv4-header haven't constructed \n"); + return IPACM_SUCCESS; + } + else if((iptype==IPA_IP_v6) && (header_set_v6 != true)) + { + header_partial_default_wan_v6 = true; + IPACMDBG_H("STA ipv6-header haven't constructed \n"); + return IPACM_SUCCESS; + } + } + else + { + IPACM_Wan::backhaul_is_sta_mode = false; + IPACMDBG_H("reset backhaul to LTE \n"); + + if (iface_query != NULL && iface_query->num_ext_props > 0) + { + if(ext_prop == NULL) + { + IPACMERR("Extended property is empty.\n"); + return IPACM_FAILURE; + } + else + { + IPACM_Iface::ipacmcfg->SetQmapId(ext_prop->ext[0].mux_id); + IPACMDBG_H("Setting up QMAP ID %d.\n", ext_prop->ext[0].mux_id); + } + } + else + { + IPACMERR("iface_query is empty.\n"); + return IPACM_FAILURE; + } + } +#if 0 + for (cnt=0; cntnum_tx_props; cnt++) + { + if(tx_prop->tx[cnt].ip==iptype) + break; + } + + if(tx_prop->tx[cnt].hdr_name != NULL) + { + memset(&sCopyHeader, 0, sizeof(sCopyHeader)); + memcpy(sCopyHeader.name, + tx_prop->tx[cnt].hdr_name, + sizeof(sCopyHeader.name)); + + IPACMDBG_H("header name: %s\n", sCopyHeader.name); + if (m_header.CopyHeader(&sCopyHeader) == false) + { + IPACMERR("ioctl copy header failed"); + return IPACM_FAILURE; + } + IPACMDBG_H("header length: %d, paritial: %d\n", sCopyHeader.hdr_len, sCopyHeader.is_partial); + if(sCopyHeader.is_partial) + { + IPACMDBG_H("Not setup default WAN routing rules cuz the header is not complete\n"); + if(iptype==IPA_IP_v4) + { + header_partial_default_wan_v4 = true; + } + else + { + header_partial_default_wan_v6 = true; + } + return IPACM_SUCCESS; + } + else + { + if(iptype==IPA_IP_v4) + { + header_partial_default_wan_v4 = false; + } + else + { + header_partial_default_wan_v6 = false; + } + } + } +#endif + + rt_rule = (struct ipa_ioc_add_rt_rule *) + calloc(1, sizeof(struct ipa_ioc_add_rt_rule) + + NUM * sizeof(struct ipa_rt_rule_add)); + + if (!rt_rule) + { + IPACMERR("Error Locate ipa_ioc_add_rt_rule memory...\n"); + return IPACM_FAILURE; + } + + rt_rule->commit = 1; + rt_rule->num_rules = (uint8_t)NUM; + rt_rule->ip = iptype; + + + IPACMDBG_H(" WAN table created %s \n", rt_rule->rt_tbl_name); + rt_rule_entry = &rt_rule->rules[0]; + rt_rule_entry->at_rear = true; + + if(m_is_sta_mode != Q6_WAN) + { + IPACMDBG_H(" WAN instance is in STA mode \n"); + for (tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++) + { + if(iptype != tx_prop->tx[tx_index].ip) + { + IPACMDBG_H("Tx:%d, ip-type: %d conflict ip-type: %d no RT-rule added\n", + tx_index, tx_prop->tx[tx_index].ip,iptype); + continue; + } + + /* use the STA-header handler */ + if (iptype == IPA_IP_v4) + { + strlcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_wan_v4.name, sizeof(rt_rule->rt_tbl_name)); + rt_rule_entry->rule.hdr_hdl = hdr_hdl_sta_v4; + } + else + { + strlcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_v6.name, sizeof(rt_rule->rt_tbl_name)); + rt_rule_entry->rule.hdr_hdl = hdr_hdl_sta_v6; + } + + if(IPACM_Iface::ipacmcfg->isMCC_Mode == true) + { + IPACMDBG_H("In MCC mode, use alt dst pipe: %d\n", + tx_prop->tx[tx_index].alt_dst_pipe); + rt_rule_entry->rule.dst = tx_prop->tx[tx_index].alt_dst_pipe; + } + else + { + rt_rule_entry->rule.dst = tx_prop->tx[tx_index].dst_pipe; + } + memcpy(&rt_rule_entry->rule.attrib, + &tx_prop->tx[tx_index].attrib, + sizeof(rt_rule_entry->rule.attrib)); + + rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; + if (iptype == IPA_IP_v4) + { + rt_rule_entry->rule.attrib.u.v4.dst_addr = 0; + rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0; + if (false == m_routing.AddRoutingRule(rt_rule)) + { + IPACMERR("Routing rule addition failed!\n"); + free(rt_rule); + return IPACM_FAILURE; + } + wan_route_rule_v4_hdl[tx_index] = rt_rule_entry->rt_rule_hdl; + IPACMDBG_H("Got ipv4 wan-route rule hdl:0x%x,tx:%d,ip-type: %d \n", + wan_route_rule_v4_hdl[tx_index], + tx_index, + iptype); + } + else + { + rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = 0; + rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = 0; + rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = 0; + rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = 0; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0; + if (false == m_routing.AddRoutingRule(rt_rule)) + { + IPACMERR("Routing rule addition failed!\n"); + free(rt_rule); + return IPACM_FAILURE; + } + wan_route_rule_v6_hdl[tx_index] = rt_rule_entry->rt_rule_hdl; + IPACMDBG_H("Set ipv6 wan-route rule hdl for v6_lan_table:0x%x,tx:%d,ip-type: %d \n", + wan_route_rule_v6_hdl[tx_index], + tx_index, + iptype); + } + } + } + + /* add a catch-all rule in wan dl routing table */ + + if (iptype == IPA_IP_v6) + { + strlcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.name, sizeof(rt_rule->rt_tbl_name)); + memset(rt_rule_entry, 0, sizeof(struct ipa_rt_rule_add)); + rt_rule_entry->at_rear = true; + if(m_is_sta_mode == Q6_WAN) + { + memset(&hdr, 0, sizeof(hdr)); + strlcpy(hdr.name, tx_prop->tx[0].hdr_name, sizeof(hdr.name)); + hdr.name[IPA_RESOURCE_NAME_MAX-1] = '\0'; + if(m_header.GetHeaderHandle(&hdr) == false) + { + IPACMERR("Failed to get QMAP header.\n"); + return IPACM_FAILURE; + } + rt_rule_entry->rule.hdr_hdl = hdr.hdl; + rt_rule_entry->rule.dst = IPA_CLIENT_APPS_WAN_CONS; + } + else + { + rt_rule_entry->rule.dst = IPA_CLIENT_APPS_LAN_CONS; + } + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = 0; + rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = 0; + rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = 0; + rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = 0; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0; + if (false == m_routing.AddRoutingRule(rt_rule)) + { + IPACMERR("Routing rule addition failed!\n"); + free(rt_rule); + return IPACM_FAILURE; + } + wan_route_rule_v6_hdl_a5[0] = rt_rule_entry->rt_rule_hdl; + IPACMDBG_H("Set ipv6 wan-route rule hdl for v6_wan_table:0x%x,tx:%d,ip-type: %d \n", + wan_route_rule_v6_hdl_a5[0], 0, iptype); + } + + ipacm_event_iface_up *wanup_data; + wanup_data = (ipacm_event_iface_up *)malloc(sizeof(ipacm_event_iface_up)); + if (wanup_data == NULL) + { + IPACMERR("Unable to allocate memory\n"); + free(rt_rule); + return IPACM_FAILURE; + } + memset(wanup_data, 0, sizeof(ipacm_event_iface_up)); + + if (iptype == IPA_IP_v4) + { + IPACM_Wan::wan_up = true; + active_v4 = true; + memcpy(IPACM_Wan::wan_up_dev_name, + dev_name, + sizeof(IPACM_Wan::wan_up_dev_name)); + + if(m_is_sta_mode == Q6_WAN) + { + config_wan_firewall_rule(IPA_IP_v4); + install_wan_filtering_rule(false); + } + else + { + config_dft_firewall_rules(IPA_IP_v4); + } + + memcpy(wanup_data->ifname, dev_name, sizeof(wanup_data->ifname)); + wanup_data->ipv4_addr = wan_v4_addr; + if (m_is_sta_mode!=Q6_WAN) + { + wanup_data->is_sta = true; + } + else + { + wanup_data->is_sta = false; + } + IPACMDBG_H("Posting IPA_HANDLE_WAN_UP with below information:\n"); + IPACMDBG_H("if_name:%s, ipv4_address:0x%x, is sta mode:%d\n", + wanup_data->ifname, wanup_data->ipv4_addr, wanup_data->is_sta); + memset(&evt_data, 0, sizeof(evt_data)); + + /* send xlat configuration for installing uplink rules */ + if(is_xlat && (m_is_sta_mode == Q6_WAN)) + { + IPACM_Wan::xlat_mux_id = ext_prop->ext[0].mux_id; + wanup_data->xlat_mux_id = IPACM_Wan::xlat_mux_id; + IPACMDBG_H("Set xlat configuraiton with below information:\n"); + IPACMDBG_H("xlat_enabled: xlat_mux_id: %d \n", + is_xlat, xlat_mux_id); + } + else + { + IPACM_Wan::xlat_mux_id = 0; + wanup_data->xlat_mux_id = 0; + IPACMDBG_H("No xlat configuratio:\n"); + } + evt_data.event = IPA_HANDLE_WAN_UP; + evt_data.evt_data = (void *)wanup_data; + IPACM_EvtDispatcher::PostEvt(&evt_data); + } + else + { + IPACM_Wan::wan_up_v6 = true; + active_v6 = true; + memcpy(IPACM_Wan::wan_up_dev_name, + dev_name, + sizeof(IPACM_Wan::wan_up_dev_name)); + + if(m_is_sta_mode == Q6_WAN) + { + config_wan_firewall_rule(IPA_IP_v6); + install_wan_filtering_rule(false); + } + else + { + config_dft_firewall_rules(IPA_IP_v6); + } + + memcpy(wanup_data->ifname, dev_name, sizeof(wanup_data->ifname)); + if (m_is_sta_mode!=Q6_WAN) + { + wanup_data->is_sta = true; + } + else + { + wanup_data->is_sta = false; + } + memcpy(wanup_data->ipv6_prefix, ipv6_prefix, sizeof(wanup_data->ipv6_prefix)); + IPACMDBG_H("Posting IPA_HANDLE_WAN_UP_V6 with below information:\n"); + IPACMDBG_H("if_name:%s, is sta mode: %d\n", wanup_data->ifname, wanup_data->is_sta); + IPACMDBG_H("ipv6 prefix: 0x%08x%08x.\n", ipv6_prefix[0], ipv6_prefix[1]); + memset(&evt_data, 0, sizeof(evt_data)); + evt_data.event = IPA_HANDLE_WAN_UP_V6; + evt_data.evt_data = (void *)wanup_data; + IPACM_EvtDispatcher::PostEvt(&evt_data); + } + + /* Add corresponding ipa_rm_resource_name of TX-endpoint up before IPV6 RT-rule set */ + IPACMDBG_H("dev %s add producer dependency\n", dev_name); + IPACMDBG_H("depend Got pipe %d rm index : %d \n", tx_prop->tx[0].dst_pipe, IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe]); + IPACM_Iface::ipacmcfg->AddRmDepend(IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe],false); + + if(rt_rule != NULL) + { + free(rt_rule); + } + return IPACM_SUCCESS; +} + +#ifdef FEATURE_IPA_ANDROID +/* wan default route/filter rule configuration */ +int IPACM_Wan::post_wan_up_tether_evt(ipa_ip_type iptype, int ipa_if_num_tether) +{ + ipacm_cmd_q_data evt_data; + ipacm_event_iface_up_tehter *wanup_data; + + wanup_data = (ipacm_event_iface_up_tehter *)malloc(sizeof(ipacm_event_iface_up_tehter)); + if (wanup_data == NULL) + { + IPACMERR("Unable to allocate memory\n"); + return IPACM_FAILURE; + } + memset(wanup_data, 0, sizeof(ipacm_event_iface_up_tehter)); + + wanup_data->if_index_tether = ipa_if_num_tether; + if (m_is_sta_mode!=Q6_WAN) + { + wanup_data->is_sta = true; + } + else + { + wanup_data->is_sta = false; + } + IPACMDBG_H("Posting IPA_HANDLE_WAN_UP_TETHER with below information:\n"); + IPACMDBG_H("tether_if_name:%s, is sta mode:%d\n", + IPACM_Iface::ipacmcfg->iface_table[ipa_if_num_tether].iface_name, wanup_data->is_sta); + memset(&evt_data, 0, sizeof(evt_data)); + + if (iptype == IPA_IP_v4) + { + evt_data.event = IPA_HANDLE_WAN_UP_TETHER; + /* Add support tether ifaces to its array*/ + IPACM_Wan::ipa_if_num_tether_v4[IPACM_Wan::ipa_if_num_tether_v4_total] = ipa_if_num_tether; + IPACMDBG_H("adding tether iface(%s) ipa_if_num_tether_v4_total(%d) on wan_iface(%s)\n", + IPACM_Iface::ipacmcfg->iface_table[ipa_if_num_tether].iface_name, + IPACM_Wan::ipa_if_num_tether_v4_total, + IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].iface_name); + IPACM_Wan::ipa_if_num_tether_v4_total++; + } + else + { + evt_data.event = IPA_HANDLE_WAN_UP_V6_TETHER; + memcpy(wanup_data->ipv6_prefix, ipv6_prefix, sizeof(wanup_data->ipv6_prefix)); + /* Add support tether ifaces to its array*/ + IPACM_Wan::ipa_if_num_tether_v6[IPACM_Wan::ipa_if_num_tether_v6_total] = ipa_if_num_tether; + IPACMDBG_H("adding tether iface(%s) ipa_if_num_tether_v6_total(%d) on wan_iface(%s)\n", + IPACM_Iface::ipacmcfg->iface_table[ipa_if_num_tether].iface_name, + IPACM_Wan::ipa_if_num_tether_v6_total, + IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].iface_name); + IPACM_Wan::ipa_if_num_tether_v6_total++; + } + evt_data.evt_data = (void *)wanup_data; + IPACM_EvtDispatcher::PostEvt(&evt_data); + + return IPACM_SUCCESS; +} + +/* wan default route/filter rule configuration */ +int IPACM_Wan::post_wan_down_tether_evt(ipa_ip_type iptype, int ipa_if_num_tether) +{ + ipacm_cmd_q_data evt_data; + ipacm_event_iface_up_tehter *wandown_data; + int i, j; + + wandown_data = (ipacm_event_iface_up_tehter *)malloc(sizeof(ipacm_event_iface_up_tehter)); + if (wandown_data == NULL) + { + IPACMERR("Unable to allocate memory\n"); + return IPACM_FAILURE; + } + memset(wandown_data, 0, sizeof(ipacm_event_iface_up_tehter)); + + wandown_data->if_index_tether = ipa_if_num_tether; + if (m_is_sta_mode!=Q6_WAN) + { + wandown_data->is_sta = true; + } + else + { + wandown_data->is_sta = false; + } + IPACMDBG_H("Posting IPA_HANDLE_WAN_DOWN_TETHER with below information:\n"); + IPACMDBG_H("tether_if_name:%s, is sta mode:%d\n", + IPACM_Iface::ipacmcfg->iface_table[ipa_if_num_tether].iface_name, wandown_data->is_sta); + memset(&evt_data, 0, sizeof(evt_data)); + + if (iptype == IPA_IP_v4) + { + evt_data.event = IPA_HANDLE_WAN_DOWN_TETHER; + /* delete support tether ifaces to its array*/ + for (i=0; i < IPACM_Wan::ipa_if_num_tether_v4_total; i++) + { + if(IPACM_Wan::ipa_if_num_tether_v4[i] == ipa_if_num_tether) + { + IPACMDBG_H("Found tether client at position %d name(%s)\n", i, + IPACM_Iface::ipacmcfg->iface_table[ipa_if_num_tether].iface_name); + break; + } + } + if(i == IPACM_Wan::ipa_if_num_tether_v4_total) + { + IPACMDBG_H("Not finding the tether client.\n"); + free(wandown_data); + return IPACM_SUCCESS; + } + for(j = i+1; j < IPACM_Wan::ipa_if_num_tether_v4_total; j++) + { + IPACM_Wan::ipa_if_num_tether_v4[j-1] = IPACM_Wan::ipa_if_num_tether_v4[j]; + } + IPACM_Wan::ipa_if_num_tether_v4_total--; + IPACMDBG_H("Now the total num of ipa_if_num_tether_v4_total is %d on wan-iface(%s)\n", + IPACM_Wan::ipa_if_num_tether_v4_total, + IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].iface_name); + } + else + { + evt_data.event = IPA_HANDLE_WAN_DOWN_V6_TETHER; + /* delete support tether ifaces to its array*/ + for (i=0; i < IPACM_Wan::ipa_if_num_tether_v6_total; i++) + { + if(IPACM_Wan::ipa_if_num_tether_v6[i] == ipa_if_num_tether) + { + IPACMDBG_H("Found tether client at position %d name(%s)\n", i, + IPACM_Iface::ipacmcfg->iface_table[ipa_if_num_tether].iface_name); + break; + } + } + if(i == IPACM_Wan::ipa_if_num_tether_v6_total) + { + IPACMDBG_H("Not finding the tether client.\n"); + free(wandown_data); + return IPACM_SUCCESS; + } + for(j = i+1; j < IPACM_Wan::ipa_if_num_tether_v6_total; j++) + { + IPACM_Wan::ipa_if_num_tether_v6[j-1] = IPACM_Wan::ipa_if_num_tether_v6[j]; + } + IPACM_Wan::ipa_if_num_tether_v6_total--; + IPACMDBG_H("Now the total num of ipa_if_num_tether_v6_total is %d on wan-iface(%s)\n", + IPACM_Wan::ipa_if_num_tether_v6_total, + IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].iface_name); + } + evt_data.evt_data = (void *)wandown_data; + IPACM_EvtDispatcher::PostEvt(&evt_data); + return IPACM_SUCCESS; +} +#endif + +/* construct complete ethernet header */ +int IPACM_Wan::handle_sta_header_add_evt() +{ + int res = IPACM_SUCCESS, index = IPACM_INVALID_INDEX; + if((header_set_v4 == true) || (header_set_v6 == true)) + { + IPACMDBG_H("Already add STA full header\n"); + return IPACM_SUCCESS; + } + + /* checking if the ipv4 same as default route */ + if(wan_v4_addr_gw_set) + { + index = get_wan_client_index_ipv4(wan_v4_addr_gw); + if (index != IPACM_INVALID_INDEX) + { + IPACMDBG_H("Matched client index: %d\n", index); + IPACMDBG_H("Received Client MAC %02x:%02x:%02x:%02x:%02x:%02x\n", + get_client_memptr(wan_client, index)->mac[0], + get_client_memptr(wan_client, index)->mac[1], + get_client_memptr(wan_client, index)->mac[2], + get_client_memptr(wan_client, index)->mac[3], + get_client_memptr(wan_client, index)->mac[4], + get_client_memptr(wan_client, index)->mac[5]); + if(get_client_memptr(wan_client, index)->ipv4_header_set) + { + hdr_hdl_sta_v4 = get_client_memptr(wan_client, index)->hdr_hdl_v4; + header_set_v4 = true; + IPACMDBG_H("add full ipv4 header hdl: (%x)\n", get_client_memptr(wan_client, index)->hdr_hdl_v4); + } + else + { + IPACMERR(" wan-client got ipv4 however didn't construct complete ipv4 header \n"); + return IPACM_FAILURE; + } + + if(get_client_memptr(wan_client, index)->ipv6_header_set) + { + hdr_hdl_sta_v6 = get_client_memptr(wan_client, index)->hdr_hdl_v6; + header_set_v6 = true; + IPACMDBG_H("add full ipv6 header hdl: (%x)\n", get_client_memptr(wan_client, index)->hdr_hdl_v6); + } + else + { + IPACMERR(" wan-client got ipv6 however didn't construct complete ipv6 header \n"); + return IPACM_FAILURE; + } + } + else + { + IPACMDBG_H(" currently can't find matched wan-client's MAC-addr, waiting for header construction\n"); + return IPACM_SUCCESS; + } + } + + /* checking if the ipv4 same as default route */ + if(wan_v6_addr_gw_set) + { + index = get_wan_client_index_ipv6(wan_v6_addr_gw); + if (index != IPACM_INVALID_INDEX) + { + IPACMDBG_H("Matched client index: %d\n", index); + IPACMDBG_H("Received Client MAC %02x:%02x:%02x:%02x:%02x:%02x\n", + get_client_memptr(wan_client, index)->mac[0], + get_client_memptr(wan_client, index)->mac[1], + get_client_memptr(wan_client, index)->mac[2], + get_client_memptr(wan_client, index)->mac[3], + get_client_memptr(wan_client, index)->mac[4], + get_client_memptr(wan_client, index)->mac[5]); + if(get_client_memptr(wan_client, index)->ipv6_header_set) + { + hdr_hdl_sta_v6 = get_client_memptr(wan_client, index)->hdr_hdl_v6; + header_set_v6 = true; + IPACMDBG_H("add full ipv6 header hdl: (%x)\n", get_client_memptr(wan_client, index)->hdr_hdl_v6); + } + else + { + IPACMERR(" wan-client got ipv6 however didn't construct complete ipv4 header \n"); + return IPACM_FAILURE; + } + + if(get_client_memptr(wan_client, index)->ipv4_header_set) + { + hdr_hdl_sta_v4 = get_client_memptr(wan_client, index)->hdr_hdl_v4; + header_set_v4 = true; + IPACMDBG_H("add full ipv4 header hdl: (%x)\n", get_client_memptr(wan_client, index)->hdr_hdl_v4); + } + else + { + IPACMERR(" wan-client got ipv4 however didn't construct complete ipv4 header \n"); + return IPACM_FAILURE; + } + } + else + { + IPACMDBG_H(" currently can't find matched wan-client's MAC-addr, waiting for header construction\n"); + return IPACM_SUCCESS; + } + } + + /* see if default routes are setup before constructing full header */ + if(header_partial_default_wan_v4 == true) + { + handle_route_add_evt(IPA_IP_v4); + } + + if(header_partial_default_wan_v6 == true) + { + handle_route_add_evt(IPA_IP_v6); + } + return res; +} + +/* For checking attribute mask field in firewall rules for IPv6 only */ +bool IPACM_Wan::check_dft_firewall_rules_attr_mask(IPACM_firewall_conf_t *firewall_config) +{ + uint32_t attrib_mask = 0ul; + attrib_mask = IPA_FLT_SRC_PORT_RANGE | + IPA_FLT_DST_PORT_RANGE | + IPA_FLT_TYPE | + IPA_FLT_CODE | + IPA_FLT_SPI | + IPA_FLT_SRC_PORT | + IPA_FLT_DST_PORT; + + for (int i = 0; i < firewall_config->num_extd_firewall_entries; i++) + { + if (firewall_config->extd_firewall_entries[i].ip_vsn == 6) + { + if (firewall_config->extd_firewall_entries[i].attrib.attrib_mask & attrib_mask) + { + IPACMDBG_H("IHL based attribute mask is found: install IPv6 frag firewall rule \n"); + return true; + } + } + } + IPACMDBG_H("IHL based attribute mask is not found: no IPv6 frag firewall rule \n"); + return false; +} + +/* for STA mode: add firewall rules */ +int IPACM_Wan::config_dft_firewall_rules(ipa_ip_type iptype) +{ + struct ipa_flt_rule_add flt_rule_entry; + int i, rule_v4 = 0, rule_v6 = 0, len; + + IPACMDBG_H("ip-family: %d; \n", iptype); + + if (rx_prop == NULL) + { + IPACMDBG_H("No rx properties registered for iface %s\n", dev_name); + return IPACM_SUCCESS; + } + + /* default firewall is disable and the rule action is drop */ + memset(&firewall_config, 0, sizeof(firewall_config)); + strlcpy(firewall_config.firewall_config_file, "/etc/mobileap_firewall.xml", sizeof(firewall_config.firewall_config_file)); + + if (firewall_config.firewall_config_file) + { + IPACMDBG_H("Firewall XML file is %s \n", firewall_config.firewall_config_file); + if (IPACM_SUCCESS == IPACM_read_firewall_xml(firewall_config.firewall_config_file, &firewall_config)) + { + IPACMDBG_H("QCMAP Firewall XML read OK \n"); + /* find the number of v4/v6 firewall rules */ + for (i = 0; i < firewall_config.num_extd_firewall_entries; i++) + { + if (firewall_config.extd_firewall_entries[i].ip_vsn == 4) + { + rule_v4++; + } + else + { + rule_v6++; + } + } + IPACMDBG_H("firewall rule v4:%d v6:%d total:%d\n", rule_v4, rule_v6, firewall_config.num_extd_firewall_entries); + } + else + { + IPACMERR("QCMAP Firewall XML read failed, no that file, use default configuration \n"); + } + } + else + { + IPACMERR("No firewall xml mentioned \n"); + return IPACM_FAILURE; + } + + /* construct ipa_ioc_add_flt_rule with N firewall rules */ + ipa_ioc_add_flt_rule *m_pFilteringTable = NULL; + len = sizeof(struct ipa_ioc_add_flt_rule) + 1 * sizeof(struct ipa_flt_rule_add); + m_pFilteringTable = (struct ipa_ioc_add_flt_rule *)calloc(1, len); + if (!m_pFilteringTable) + { + IPACMERR("Error Locate ipa_flt_rule_add memory...\n"); + return IPACM_FAILURE; + } + + if(iptype == IPA_IP_v6 && + firewall_config.firewall_enable == true && + check_dft_firewall_rules_attr_mask(&firewall_config)) + { + m_pFilteringTable->commit = 1; + m_pFilteringTable->ep = rx_prop->rx[0].src_pipe; + m_pFilteringTable->global = false; + m_pFilteringTable->ip = IPA_IP_v6; + m_pFilteringTable->num_rules = (uint8_t)1; + + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); + flt_rule_entry.at_rear = true; +#ifdef FEATURE_IPA_V3 + flt_rule_entry.at_rear = false; + flt_rule_entry.rule.hashable = IPA_RULE_NON_HASHABLE; +#endif + flt_rule_entry.flt_rule_hdl = -1; + flt_rule_entry.status = -1; + flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION; + memcpy(&flt_rule_entry.rule.attrib, &rx_prop->rx[0].attrib, sizeof(struct ipa_rule_attrib)); + flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_FRAGMENT; + + memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + if (false == m_filtering.AddFilteringRule(m_pFilteringTable)) + { + IPACMERR("Error Adding RuleTable(0) to Filtering, aborting...\n"); + free(m_pFilteringTable); + return IPACM_FAILURE; + } + else + { + IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1); + ipv6_frag_firewall_flt_rule_hdl = m_pFilteringTable->rules[0].flt_rule_hdl; + IPACMDBG_H("Installed IPv6 frag firewall rule, handle %d.\n", ipv6_frag_firewall_flt_rule_hdl); + } + } + + if (iptype == IPA_IP_v4) + { + if (rule_v4 == 0) + { + memset(m_pFilteringTable, 0, len); + + m_pFilteringTable->commit = 1; + m_pFilteringTable->ep = rx_prop->rx[0].src_pipe; + m_pFilteringTable->global = false; + m_pFilteringTable->ip = IPA_IP_v4; + m_pFilteringTable->num_rules = (uint8_t)1; + + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); + + if (false == m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_lan_v4)) + { + IPACMERR("m_routing.GetRoutingTable(rt_tbl_lan_v4) Failed.\n"); + free(m_pFilteringTable); + return IPACM_FAILURE; + } + + flt_rule_entry.flt_rule_hdl = -1; + flt_rule_entry.status = -1; + + /* firewall disable, all traffic are allowed */ + if(firewall_config.firewall_enable == true) + { + flt_rule_entry.at_rear = true; + + /* default action for v4 is go DST_NAT unless user set to exception*/ + if(firewall_config.rule_action_accept == true) + { + flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION; + } + else + { + if(IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_mode == ROUTER) + { + flt_rule_entry.rule.action = IPA_PASS_TO_DST_NAT; + } + else + { + flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING; + } + } + } + else + { + flt_rule_entry.at_rear = true; + if(IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_mode == ROUTER) + { + flt_rule_entry.rule.action = IPA_PASS_TO_DST_NAT; + } + else + { + flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING; + } + } +#ifdef FEATURE_IPA_V3 + flt_rule_entry.at_rear = true; +#endif + flt_rule_entry.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_lan_v4.hdl; + memcpy(&flt_rule_entry.rule.attrib, + &rx_prop->rx[0].attrib, + sizeof(struct ipa_rule_attrib)); + flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; + flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0x00000000; + flt_rule_entry.rule.attrib.u.v4.dst_addr = 0x00000000; + + memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + + if (false == m_filtering.AddFilteringRule(m_pFilteringTable)) + { + IPACMERR("Error Adding RuleTable(0) to Filtering, aborting...\n"); + free(m_pFilteringTable); + return IPACM_FAILURE; + } + else + { + IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, 1); + IPACMDBG_H("flt rule hdl0=0x%x, status=0x%x\n", m_pFilteringTable->rules[0].flt_rule_hdl, m_pFilteringTable->rules[0].status); + } + + /* copy filter hdls */ + dft_wan_fl_hdl[0] = m_pFilteringTable->rules[0].flt_rule_hdl; + } + else + { + memset(m_pFilteringTable, 0, len); + + m_pFilteringTable->commit = 1; + m_pFilteringTable->ep = rx_prop->rx[0].src_pipe; + m_pFilteringTable->global = false; + m_pFilteringTable->ip = IPA_IP_v4; + m_pFilteringTable->num_rules = (uint8_t)1; + + IPACMDBG_H("Retreiving Routing handle for routing table name:%s\n", + IPACM_Iface::ipacmcfg->rt_tbl_lan_v4.name); + if (false == m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_lan_v4)) + { + IPACMERR("m_routing.GetRoutingTable(&rt_tbl_lan_v4=0x%p) Failed.\n", &IPACM_Iface::ipacmcfg->rt_tbl_lan_v4); + free(m_pFilteringTable); + return IPACM_FAILURE; + } + IPACMDBG_H("Routing handle for wan routing table:0x%x\n", IPACM_Iface::ipacmcfg->rt_tbl_lan_v4.hdl); + + if(firewall_config.firewall_enable == true) + { + rule_v4 = 0; + for (i = 0; i < firewall_config.num_extd_firewall_entries; i++) + { + if (firewall_config.extd_firewall_entries[i].ip_vsn == 4) + { + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); + + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl = -1; + flt_rule_entry.status = -1; + flt_rule_entry.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_lan_v4.hdl; + + /* Accept v4 matched rules*/ + if(firewall_config.rule_action_accept == true) + { + if(IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_mode == ROUTER) + { + flt_rule_entry.rule.action = IPA_PASS_TO_DST_NAT; + } + else + { + flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING; + } + } + else + { + flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION; + } + memcpy(&flt_rule_entry.rule.attrib, + &firewall_config.extd_firewall_entries[i].attrib, + sizeof(struct ipa_rule_attrib)); + + IPACMDBG_H("rx property attrib mask: 0x%x\n", rx_prop->rx[0].attrib.attrib_mask); + flt_rule_entry.rule.attrib.attrib_mask |= rx_prop->rx[0].attrib.attrib_mask; + flt_rule_entry.rule.attrib.meta_data_mask = rx_prop->rx[0].attrib.meta_data_mask; + flt_rule_entry.rule.attrib.meta_data = rx_prop->rx[0].attrib.meta_data; + + /* check if the rule is define as TCP_UDP, split into 2 rules, 1 for TCP and 1 UDP */ + if (firewall_config.extd_firewall_entries[i].attrib.u.v4.protocol + == IPACM_FIREWALL_IPPROTO_TCP_UDP) + { + /* insert TCP rule*/ + flt_rule_entry.rule.attrib.u.v4.protocol = IPACM_FIREWALL_IPPROTO_TCP; + memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + + IPACMDBG_H("Filter rule attrib mask: 0x%x\n", + m_pFilteringTable->rules[0].rule.attrib.attrib_mask); + if (false == m_filtering.AddFilteringRule(m_pFilteringTable)) + { + IPACMERR("Error Adding RuleTable(0) to Filtering, aborting...\n"); + free(m_pFilteringTable); + return IPACM_FAILURE; + } + else + { + IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, 1); + /* save v4 firewall filter rule handler */ + IPACMDBG_H("flt rule hdl0=0x%x, status=0x%x\n", + m_pFilteringTable->rules[rule_v4].flt_rule_hdl, + m_pFilteringTable->rules[rule_v4].status); + firewall_hdl_v4[rule_v4] = m_pFilteringTable->rules[0].flt_rule_hdl; + num_firewall_v4++; + rule_v4++; + } + + /* insert UDP rule*/ + flt_rule_entry.rule.attrib.u.v4.protocol = IPACM_FIREWALL_IPPROTO_UDP; + memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + + IPACMDBG_H("Filter rule attrib mask: 0x%x\n", + m_pFilteringTable->rules[0].rule.attrib.attrib_mask); + if (false == m_filtering.AddFilteringRule(m_pFilteringTable)) + { + IPACMERR("Error Adding RuleTable(0) to Filtering, aborting...\n"); + free(m_pFilteringTable); + return IPACM_FAILURE; + } + else + { + IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, 1); + /* save v4 firewall filter rule handler */ + IPACMDBG_H("flt rule hdl0=0x%x, status=0x%x\n", + m_pFilteringTable->rules[rule_v4].flt_rule_hdl, + m_pFilteringTable->rules[rule_v4].status); + firewall_hdl_v4[rule_v4] = m_pFilteringTable->rules[0].flt_rule_hdl; + num_firewall_v4++; + rule_v4++; + } + } + else + { + memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + + IPACMDBG_H("Filter rule attrib mask: 0x%x\n", + m_pFilteringTable->rules[0].rule.attrib.attrib_mask); + if (false == m_filtering.AddFilteringRule(m_pFilteringTable)) + { + IPACMERR("Error Adding RuleTable(0) to Filtering, aborting...\n"); + free(m_pFilteringTable); + return IPACM_FAILURE; + } + else + { + IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, 1); + /* save v4 firewall filter rule handler */ + IPACMDBG_H("flt rule hdl0=0x%x, status=0x%x\n", + m_pFilteringTable->rules[rule_v4].flt_rule_hdl, + m_pFilteringTable->rules[rule_v4].status); + firewall_hdl_v4[rule_v4] = m_pFilteringTable->rules[0].flt_rule_hdl; + num_firewall_v4++; + rule_v4++; + } + } + } + } /* end of firewall ipv4 filter rule add for loop*/ + } + /* configure default filter rule */ + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); + + flt_rule_entry.flt_rule_hdl = -1; + flt_rule_entry.status = -1; + + /* firewall disable, all traffic are allowed */ + if(firewall_config.firewall_enable == true) + { + flt_rule_entry.at_rear = true; + + /* default action for v4 is go DST_NAT unless user set to exception*/ + if(firewall_config.rule_action_accept == true) + { + flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION; + } + else + { + if(IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_mode == ROUTER) + { + flt_rule_entry.rule.action = IPA_PASS_TO_DST_NAT; + } + else + { + flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING; + } + } + } + else + { + flt_rule_entry.at_rear = true; + if(IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_mode == ROUTER) + { + flt_rule_entry.rule.action = IPA_PASS_TO_DST_NAT; + } + else + { + flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING; + } + } + flt_rule_entry.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_lan_v4.hdl; + memcpy(&flt_rule_entry.rule.attrib, + &rx_prop->rx[0].attrib, + sizeof(struct ipa_rule_attrib)); + flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; + flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0x00000000; + flt_rule_entry.rule.attrib.u.v4.dst_addr = 0x00000000; + + memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + + IPACMDBG_H("Filter rule attrib mask: 0x%x\n", + m_pFilteringTable->rules[0].rule.attrib.attrib_mask); + if (false == m_filtering.AddFilteringRule(m_pFilteringTable)) + { + IPACMERR("Error Adding RuleTable(0) to Filtering, aborting...\n"); + free(m_pFilteringTable); + return IPACM_FAILURE; + } + else + { + IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, 1); + IPACMDBG_H("flt rule hdl0=0x%x, status=0x%x\n", m_pFilteringTable->rules[0].flt_rule_hdl, m_pFilteringTable->rules[0].status); + } + + /* copy filter hdls */ + dft_wan_fl_hdl[0] = m_pFilteringTable->rules[0].flt_rule_hdl; + } + + } + else + { + if (rule_v6 == 0) + { + memset(m_pFilteringTable, 0, len); + + m_pFilteringTable->commit = 1; + m_pFilteringTable->ep = rx_prop->rx[0].src_pipe; + m_pFilteringTable->global = false; + m_pFilteringTable->ip = IPA_IP_v6; + m_pFilteringTable->num_rules = (uint8_t)1; + + /* Construct ICMP rule */ + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl = -1; + flt_rule_entry.status = -1; + flt_rule_entry.rule.retain_hdr = 1; + flt_rule_entry.rule.eq_attrib_type = 0; + flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION; + memcpy(&flt_rule_entry.rule.attrib, + &rx_prop->rx[0].attrib, + sizeof(struct ipa_rule_attrib)); + flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_NEXT_HDR; + flt_rule_entry.rule.attrib.u.v6.next_hdr = (uint8_t)IPACM_FIREWALL_IPPROTO_ICMP6; + memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + + if (false == m_filtering.AddFilteringRule(m_pFilteringTable)) + { + IPACMERR("Error Adding Filtering rules, aborting...\n"); + free(m_pFilteringTable); + return IPACM_FAILURE; + } + else + { + IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1); + IPACMDBG_H("flt rule hdl0=0x%x, status=0x%x\n", m_pFilteringTable->rules[0].flt_rule_hdl, m_pFilteringTable->rules[0].status); + } + /* copy filter hdls */ + dft_wan_fl_hdl[2] = m_pFilteringTable->rules[0].flt_rule_hdl; + + /* End of construct ICMP rule */ + + /* v6 default route */ + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); + if (false == m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_wan_v6)) //rt_tbl_wan_v6 rt_tbl_v6 + { + IPACMERR("m_routing.GetRoutingTable(rt_tbl_wan_v6) Failed.\n"); + free(m_pFilteringTable); + return IPACM_FAILURE; + } + + flt_rule_entry.flt_rule_hdl = -1; + flt_rule_entry.status = -1; + flt_rule_entry.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.hdl; + + /* firewall disable, all traffic are allowed */ + if(firewall_config.firewall_enable == true) + { + flt_rule_entry.at_rear = true; + + /* default action for v6 is PASS_TO_ROUTE unless user set to exception*/ + if(firewall_config.rule_action_accept == true) + { + flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION; + } + else + { + flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING; + } + } + else + { + flt_rule_entry.at_rear = true; + flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING; + } + memcpy(&flt_rule_entry.rule.attrib, + &rx_prop->rx[0].attrib, + sizeof(struct ipa_rule_attrib)); + flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0x00000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[1] = 0x00000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = 0x00000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr[0] = 0X00000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = 0x00000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = 0x00000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X00000000; + + memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + + if (false == m_filtering.AddFilteringRule(m_pFilteringTable)) + { + IPACMERR("Error Adding Filtering rules, aborting...\n"); + free(m_pFilteringTable); + return IPACM_FAILURE; + } + else + { + IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1); + IPACMDBG_H("flt rule hdl0=0x%x, status=0x%x\n", m_pFilteringTable->rules[0].flt_rule_hdl, m_pFilteringTable->rules[0].status); + } + + /* copy filter hdls */ + dft_wan_fl_hdl[1] = m_pFilteringTable->rules[0].flt_rule_hdl; + } + else + { + memset(m_pFilteringTable, 0, len); + + m_pFilteringTable->commit = 1; + m_pFilteringTable->ep = rx_prop->rx[0].src_pipe; + m_pFilteringTable->global = false; + m_pFilteringTable->ip = IPA_IP_v6; + m_pFilteringTable->num_rules = (uint8_t)1; + + if (false == m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_wan_v6)) + { + IPACMERR("m_routing.GetRoutingTable(rt_tbl_wan_v6) Failed.\n"); + free(m_pFilteringTable); + return IPACM_FAILURE; + } + + if(firewall_config.firewall_enable == true) + { + rule_v6 = 0; + for (i = 0; i < firewall_config.num_extd_firewall_entries; i++) + { + if (firewall_config.extd_firewall_entries[i].ip_vsn == 6) + { + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); + + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl = -1; + flt_rule_entry.status = -1; + + /* matched rules for v6 go PASS_TO_ROUTE */ + if(firewall_config.rule_action_accept == true) + { + flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING; + } + else + { + flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION; + } + flt_rule_entry.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.hdl; + memcpy(&flt_rule_entry.rule.attrib, + &firewall_config.extd_firewall_entries[i].attrib, + sizeof(struct ipa_rule_attrib)); + flt_rule_entry.rule.attrib.attrib_mask |= rx_prop->rx[0].attrib.attrib_mask; + flt_rule_entry.rule.attrib.meta_data_mask = rx_prop->rx[0].attrib.meta_data_mask; + flt_rule_entry.rule.attrib.meta_data = rx_prop->rx[0].attrib.meta_data; + + /* check if the rule is define as TCP/UDP */ + if (firewall_config.extd_firewall_entries[i].attrib.u.v6.next_hdr == IPACM_FIREWALL_IPPROTO_TCP_UDP) + { + /* insert TCP rule*/ + flt_rule_entry.rule.attrib.u.v6.next_hdr = IPACM_FIREWALL_IPPROTO_TCP; + memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + if (false == m_filtering.AddFilteringRule(m_pFilteringTable)) + { + IPACMERR("Error Adding Filtering rules, aborting...\n"); + free(m_pFilteringTable); + return IPACM_FAILURE; + } + else + { + IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1); + /* save v4 firewall filter rule handler */ + IPACMDBG_H("flt rule hdl0=0x%x, status=0x%x\n", m_pFilteringTable->rules[0].flt_rule_hdl, m_pFilteringTable->rules[0].status); + firewall_hdl_v6[rule_v6] = m_pFilteringTable->rules[0].flt_rule_hdl; + num_firewall_v6++; + rule_v6++; + } + + /* insert UDP rule*/ + flt_rule_entry.rule.attrib.u.v6.next_hdr = IPACM_FIREWALL_IPPROTO_UDP; + memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + if (false == m_filtering.AddFilteringRule(m_pFilteringTable)) + { + IPACMERR("Error Adding Filtering rules, aborting...\n"); + free(m_pFilteringTable); + return IPACM_FAILURE; + } + else + { + IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1); + /* save v6 firewall filter rule handler */ + IPACMDBG_H("flt rule hdl0=0x%x, status=0x%x\n", m_pFilteringTable->rules[0].flt_rule_hdl, m_pFilteringTable->rules[0].status); + firewall_hdl_v6[rule_v6] = m_pFilteringTable->rules[0].flt_rule_hdl; + num_firewall_v6++; + rule_v6++; + } + } + else + { + memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + if (false == m_filtering.AddFilteringRule(m_pFilteringTable)) + { + IPACMERR("Error Adding Filtering rules, aborting...\n"); + free(m_pFilteringTable); + return IPACM_FAILURE; + } + else + { + IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1); + /* save v6 firewall filter rule handler */ + IPACMDBG_H("flt rule hdl0=0x%x, status=0x%x\n", m_pFilteringTable->rules[0].flt_rule_hdl, m_pFilteringTable->rules[0].status); + firewall_hdl_v6[rule_v6] = m_pFilteringTable->rules[0].flt_rule_hdl; + num_firewall_v6++; + rule_v6++; + } + } + } + } /* end of firewall ipv6 filter rule add for loop*/ + } + + /* Construct ICMP rule */ + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl = -1; + flt_rule_entry.status = -1; + flt_rule_entry.rule.retain_hdr = 1; + flt_rule_entry.rule.eq_attrib_type = 0; + flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION; + memcpy(&flt_rule_entry.rule.attrib, + &rx_prop->rx[0].attrib, + sizeof(struct ipa_rule_attrib)); + flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_NEXT_HDR; + flt_rule_entry.rule.attrib.u.v6.next_hdr = (uint8_t)IPACM_FIREWALL_IPPROTO_ICMP6; + memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + + if (false == m_filtering.AddFilteringRule(m_pFilteringTable)) + { + IPACMERR("Error Adding Filtering rules, aborting...\n"); + free(m_pFilteringTable); + return IPACM_FAILURE; + } + else + { + IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1); + IPACMDBG_H("flt rule hdl0=0x%x, status=0x%x\n", m_pFilteringTable->rules[0].flt_rule_hdl, m_pFilteringTable->rules[0].status); + } + /* copy filter hdls */ + dft_wan_fl_hdl[2] = m_pFilteringTable->rules[0].flt_rule_hdl; + /* End of construct ICMP rule */ + + /* setup default wan filter rule */ + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); + + flt_rule_entry.flt_rule_hdl = -1; + flt_rule_entry.status = -1; + flt_rule_entry.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.hdl; + + /* firewall disable, all traffic are allowed */ + if(firewall_config.firewall_enable == true) + { + flt_rule_entry.at_rear = true; + + /* default action for v6 is PASS_TO_ROUTE unless user set to exception*/ + if(firewall_config.rule_action_accept == true) + { + flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION; + } + else + { + flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING; + } + } + else + { + flt_rule_entry.at_rear = true; + flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING; + } + memcpy(&flt_rule_entry.rule.attrib, + &rx_prop->rx[0].attrib, + sizeof(struct ipa_rule_attrib)); + flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0x00000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[1] = 0x00000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = 0x00000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr[0] = 0X00000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = 0x00000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = 0x00000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X00000000; + + memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + + if (false == m_filtering.AddFilteringRule(m_pFilteringTable)) + { + IPACMERR("Error Adding Filtering rules, aborting...\n"); + free(m_pFilteringTable); + return IPACM_FAILURE; + } + else + { + IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1); + IPACMDBG_H("flt rule hdl0=0x%x, status=0x%x\n", m_pFilteringTable->rules[0].flt_rule_hdl, m_pFilteringTable->rules[0].status); + } + /* copy filter hdls*/ + dft_wan_fl_hdl[1] = m_pFilteringTable->rules[0].flt_rule_hdl; + } + } + + if(m_pFilteringTable != NULL) + { + free(m_pFilteringTable); + } + return IPACM_SUCCESS; +} + +/* configure the initial firewall filter rules */ +int IPACM_Wan::config_dft_firewall_rules_ex(struct ipa_flt_rule_add *rules, int rule_offset, ipa_ip_type iptype) +{ + struct ipa_flt_rule_add flt_rule_entry; + int i; + int num_rules = 0, original_num_rules = 0; + ipa_ioc_get_rt_tbl_indx rt_tbl_idx; + ipa_ioc_generate_flt_eq flt_eq; + int pos = rule_offset; + + IPACMDBG_H("ip-family: %d; \n", iptype); + + if (rx_prop == NULL) + { + IPACMDBG_H("No rx properties registered for iface %s\n", dev_name); + return IPACM_SUCCESS; + } + + if(rules == NULL || rule_offset < 0) + { + IPACMERR("No filtering table is available.\n"); + return IPACM_FAILURE; + } + + /* default firewall is disable and the rule action is drop */ + memset(&firewall_config, 0, sizeof(firewall_config)); + strlcpy(firewall_config.firewall_config_file, "/etc/mobileap_firewall.xml", sizeof(firewall_config.firewall_config_file)); + + if (firewall_config.firewall_config_file) + { + IPACMDBG_H("Firewall XML file is %s \n", firewall_config.firewall_config_file); + if (IPACM_SUCCESS == IPACM_read_firewall_xml(firewall_config.firewall_config_file, &firewall_config)) + { + IPACMDBG_H("QCMAP Firewall XML read OK \n"); + } + else + { + IPACMERR("QCMAP Firewall XML read failed, no that file, use default configuration \n"); + } + } + else + { + IPACMERR("No firewall xml mentioned \n"); + return IPACM_FAILURE; + } + + /* add IPv6 frag rule when firewall is enabled*/ + if(iptype == IPA_IP_v6 && + firewall_config.firewall_enable == true && + check_dft_firewall_rules_attr_mask(&firewall_config)) + { + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); + flt_rule_entry.at_rear = true; +#ifdef FEATURE_IPA_V3 + flt_rule_entry.at_rear = false; +#endif + flt_rule_entry.flt_rule_hdl = -1; + flt_rule_entry.status = -1; + + flt_rule_entry.rule.retain_hdr = 1; + flt_rule_entry.rule.to_uc = 0; + flt_rule_entry.rule.eq_attrib_type = 1; + flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING; +#ifdef FEATURE_IPA_V3 + flt_rule_entry.at_rear = false; + flt_rule_entry.rule.hashable = IPA_RULE_NON_HASHABLE; +#endif + memset(&rt_tbl_idx, 0, sizeof(rt_tbl_idx)); + rt_tbl_idx.ip = IPA_IP_v6; + strlcpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_dl.name, IPA_RESOURCE_NAME_MAX); + rt_tbl_idx.name[IPA_RESOURCE_NAME_MAX-1] = '\0'; + if(0 != ioctl(m_fd_ipa, IPA_IOC_QUERY_RT_TBL_INDEX, &rt_tbl_idx)) + { + IPACMERR("Failed to get routing table index from name\n"); + return IPACM_FAILURE; + } + flt_rule_entry.rule.rt_tbl_idx = rt_tbl_idx.idx; + IPACMDBG_H("IPv6 frag flt rule uses routing table index %d\n", rt_tbl_idx.idx); + + flt_rule_entry.rule.attrib.attrib_mask |= rx_prop->rx[0].attrib.attrib_mask; + flt_rule_entry.rule.attrib.meta_data_mask = rx_prop->rx[0].attrib.meta_data_mask; + flt_rule_entry.rule.attrib.meta_data = rx_prop->rx[0].attrib.meta_data; + + flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_FRAGMENT; + + change_to_network_order(IPA_IP_v6, &flt_rule_entry.rule.attrib); + + memset(&flt_eq, 0, sizeof(flt_eq)); + memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib)); + flt_eq.ip = IPA_IP_v6; + if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq)) + { + IPACMERR("Failed to get eq_attrib\n"); + return IPACM_FAILURE; + } + memcpy(&flt_rule_entry.rule.eq_attrib, + &flt_eq.eq_attrib, + sizeof(flt_rule_entry.rule.eq_attrib)); + + memcpy(&(rules[pos]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + pos++; + IPACM_Wan::num_v6_flt_rule++; + } + + if (iptype == IPA_IP_v4) + { + original_num_rules = IPACM_Wan::num_v4_flt_rule; + if(firewall_config.firewall_enable == true) + { + for (i = 0; i < firewall_config.num_extd_firewall_entries; i++) + { + if (firewall_config.extd_firewall_entries[i].ip_vsn == 4) + { + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); + + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl = -1; + flt_rule_entry.status = -1; + + flt_rule_entry.rule.retain_hdr = 1; + flt_rule_entry.rule.to_uc = 0; + flt_rule_entry.rule.eq_attrib_type = 1; + + /* Accept v4 matched rules*/ + if(firewall_config.rule_action_accept == true) + { + flt_rule_entry.rule.action = IPA_PASS_TO_DST_NAT; + } + else + { + flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING; + } + memset(&rt_tbl_idx, 0, sizeof(rt_tbl_idx)); + rt_tbl_idx.ip = iptype; + if(flt_rule_entry.rule.action == IPA_PASS_TO_ROUTING) + { + strlcpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_dl.name, IPA_RESOURCE_NAME_MAX); + } + else /*pass to dst nat*/ + { + strlcpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_lan_v4.name, IPA_RESOURCE_NAME_MAX); + } + rt_tbl_idx.name[IPA_RESOURCE_NAME_MAX-1] = '\0'; + if(0 != ioctl(m_fd_ipa, IPA_IOC_QUERY_RT_TBL_INDEX, &rt_tbl_idx)) + { + IPACMERR("Failed to get routing table index from name\n"); + return IPACM_FAILURE; + } + flt_rule_entry.rule.rt_tbl_idx = rt_tbl_idx.idx; + + IPACMDBG_H("Routing table %s has index %d\n", rt_tbl_idx.name, rt_tbl_idx.idx); + + memcpy(&flt_rule_entry.rule.attrib, + &firewall_config.extd_firewall_entries[i].attrib, + sizeof(struct ipa_rule_attrib)); + + flt_rule_entry.rule.attrib.attrib_mask |= rx_prop->rx[0].attrib.attrib_mask; + flt_rule_entry.rule.attrib.meta_data_mask = rx_prop->rx[0].attrib.meta_data_mask; + flt_rule_entry.rule.attrib.meta_data = rx_prop->rx[0].attrib.meta_data; + + change_to_network_order(IPA_IP_v4, &flt_rule_entry.rule.attrib); + + /* check if the rule is define as TCP_UDP, split into 2 rules, 1 for TCP and 1 UDP */ + if (firewall_config.extd_firewall_entries[i].attrib.u.v4.protocol == IPACM_FIREWALL_IPPROTO_TCP_UDP) + { + /* insert TCP rule*/ + flt_rule_entry.rule.attrib.u.v4.protocol = IPACM_FIREWALL_IPPROTO_TCP; + + memset(&flt_eq, 0, sizeof(flt_eq)); + memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib)); + flt_eq.ip = iptype; + if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq)) + { + IPACMERR("Failed to get eq_attrib\n"); + return IPACM_FAILURE; + } + memcpy(&flt_rule_entry.rule.eq_attrib, + &flt_eq.eq_attrib, + sizeof(flt_rule_entry.rule.eq_attrib)); + + memcpy(&(rules[pos]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + IPACMDBG_H("Filter rule attrib mask: 0x%x\n", rules[pos].rule.attrib.attrib_mask); + pos++; + num_firewall_v4++; + IPACM_Wan::num_v4_flt_rule++; + + /* insert UDP rule*/ + flt_rule_entry.rule.attrib.u.v4.protocol = IPACM_FIREWALL_IPPROTO_UDP; + + memset(&flt_eq, 0, sizeof(flt_eq)); + memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib)); + flt_eq.ip = iptype; + if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq)) + { + IPACMERR("Failed to get eq_attrib\n"); + return IPACM_FAILURE; + } + memcpy(&flt_rule_entry.rule.eq_attrib, + &flt_eq.eq_attrib, + sizeof(flt_rule_entry.rule.eq_attrib)); + + memcpy(&(rules[pos]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + IPACMDBG_H("Filter rule attrib mask: 0x%x\n", rules[pos].rule.attrib.attrib_mask); + pos++; + num_firewall_v4++; + IPACM_Wan::num_v4_flt_rule++; + } + else + { + memset(&flt_eq, 0, sizeof(flt_eq)); + memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib)); + flt_eq.ip = iptype; + if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq)) + { + IPACMERR("Failed to get eq_attrib\n"); + return IPACM_FAILURE; + } + memcpy(&flt_rule_entry.rule.eq_attrib, + &flt_eq.eq_attrib, + sizeof(flt_rule_entry.rule.eq_attrib)); + + memcpy(&(rules[pos]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + IPACMDBG_H("Filter rule attrib mask: 0x%x\n", rules[pos].rule.attrib.attrib_mask); + pos++; + num_firewall_v4++; + IPACM_Wan::num_v4_flt_rule++; + } + } + } /* end of firewall ipv4 filter rule add for loop*/ + } + /* configure default filter rule */ + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); + + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl = -1; + flt_rule_entry.status = -1; + + flt_rule_entry.rule.retain_hdr = 1; + flt_rule_entry.rule.to_uc = 0; + flt_rule_entry.rule.eq_attrib_type = 1; + + /* firewall disable, all traffic are allowed */ + if(firewall_config.firewall_enable == true) + { + /* default action for v4 is go DST_NAT unless user set to exception*/ + if(firewall_config.rule_action_accept == true) + { + flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING; + } + else + { + flt_rule_entry.rule.action = IPA_PASS_TO_DST_NAT; + } + } + else + { + if(isWan_Bridge_Mode()) + { + IPACMDBG_H("ODU is in bridge mode. \n"); + flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING; + } + else + { + flt_rule_entry.rule.action = IPA_PASS_TO_DST_NAT; + } + } + memset(&rt_tbl_idx, 0, sizeof(rt_tbl_idx)); + rt_tbl_idx.ip = iptype; + + if(flt_rule_entry.rule.action == IPA_PASS_TO_ROUTING) + { + strlcpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_dl.name, IPA_RESOURCE_NAME_MAX); + } + else /*pass to dst nat*/ + { + strlcpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_lan_v4.name, IPA_RESOURCE_NAME_MAX); + } + rt_tbl_idx.name[IPA_RESOURCE_NAME_MAX-1] = '\0'; + + if(0 != ioctl(m_fd_ipa, IPA_IOC_QUERY_RT_TBL_INDEX, &rt_tbl_idx)) + { + IPACMERR("Failed to get routing table index from name\n"); + return IPACM_FAILURE; + } + flt_rule_entry.rule.rt_tbl_idx = rt_tbl_idx.idx; + + IPACMDBG_H("Routing table %s has index %d\n", rt_tbl_idx.name, rt_tbl_idx.idx); + + memcpy(&flt_rule_entry.rule.attrib, + &rx_prop->rx[0].attrib, + sizeof(struct ipa_rule_attrib)); + flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; + flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0x00000000; + flt_rule_entry.rule.attrib.u.v4.dst_addr = 0x00000000; + + change_to_network_order(IPA_IP_v4, &flt_rule_entry.rule.attrib); + + memset(&flt_eq, 0, sizeof(flt_eq)); + memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib)); + flt_eq.ip = iptype; + if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq)) + { + IPACMERR("Failed to get eq_attrib\n"); + return IPACM_FAILURE; + } + + memcpy(&flt_rule_entry.rule.eq_attrib, + &flt_eq.eq_attrib, + sizeof(flt_rule_entry.rule.eq_attrib)); + + memcpy(&(rules[pos]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + IPACMDBG_H("Filter rule attrib mask: 0x%x\n", rules[pos].rule.attrib.attrib_mask); + pos++; + num_firewall_v4++; + IPACM_Wan::num_v4_flt_rule++; + + num_rules = IPACM_Wan::num_v4_flt_rule - original_num_rules - 1; + } + else + { + original_num_rules = IPACM_Wan::num_v6_flt_rule; + + if(firewall_config.firewall_enable == true) + { + for (i = 0; i < firewall_config.num_extd_firewall_entries; i++) + { + if (firewall_config.extd_firewall_entries[i].ip_vsn == 6) + { + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); + + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl = -1; + flt_rule_entry.status = -1; + + flt_rule_entry.rule.retain_hdr = 1; + flt_rule_entry.rule.to_uc = 0; + flt_rule_entry.rule.eq_attrib_type = 1; + flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING; + memset(&rt_tbl_idx, 0, sizeof(rt_tbl_idx)); + rt_tbl_idx.ip = iptype; + + /* matched rules for v6 go PASS_TO_ROUTE */ + if(firewall_config.rule_action_accept == true) + { + strlcpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.name, IPA_RESOURCE_NAME_MAX); + } + else + { + strlcpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_dl.name, IPA_RESOURCE_NAME_MAX); + } + rt_tbl_idx.name[IPA_RESOURCE_NAME_MAX-1] = '\0'; + + if(0 != ioctl(m_fd_ipa, IPA_IOC_QUERY_RT_TBL_INDEX, &rt_tbl_idx)) + { + IPACMERR("Failed to get routing table index from name\n"); + return IPACM_FAILURE; + } + flt_rule_entry.rule.rt_tbl_idx = rt_tbl_idx.idx; + + IPACMDBG_H("Routing table %s has index %d\n", rt_tbl_idx.name, rt_tbl_idx.idx); + + memcpy(&flt_rule_entry.rule.attrib, + &firewall_config.extd_firewall_entries[i].attrib, + sizeof(struct ipa_rule_attrib)); + + flt_rule_entry.rule.attrib.attrib_mask |= rx_prop->rx[0].attrib.attrib_mask; + flt_rule_entry.rule.attrib.meta_data_mask = rx_prop->rx[0].attrib.meta_data_mask; + flt_rule_entry.rule.attrib.meta_data = rx_prop->rx[0].attrib.meta_data; + + change_to_network_order(IPA_IP_v6, &flt_rule_entry.rule.attrib); + + /* check if the rule is define as TCP/UDP */ + if (firewall_config.extd_firewall_entries[i].attrib.u.v6.next_hdr == IPACM_FIREWALL_IPPROTO_TCP_UDP) + { + /* insert TCP rule*/ + flt_rule_entry.rule.attrib.u.v6.next_hdr = IPACM_FIREWALL_IPPROTO_TCP; + + memset(&flt_eq, 0, sizeof(flt_eq)); + memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib)); + flt_eq.ip = iptype; + if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq)) + { + IPACMERR("Failed to get eq_attrib\n"); + return IPACM_FAILURE; + } + + memcpy(&flt_rule_entry.rule.eq_attrib, + &flt_eq.eq_attrib, + sizeof(flt_rule_entry.rule.eq_attrib)); + memcpy(&(rules[pos]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + pos++; + num_firewall_v6++; + IPACM_Wan::num_v6_flt_rule++; + + /* insert UDP rule*/ + flt_rule_entry.rule.attrib.u.v6.next_hdr = IPACM_FIREWALL_IPPROTO_UDP; + + memset(&flt_eq, 0, sizeof(flt_eq)); + memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib)); + flt_eq.ip = iptype; + if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq)) + { + IPACMERR("Failed to get eq_attrib\n"); + return IPACM_FAILURE; + } + + memcpy(&flt_rule_entry.rule.eq_attrib, + &flt_eq.eq_attrib, + sizeof(flt_rule_entry.rule.eq_attrib)); + memcpy(&(rules[pos]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + pos++; + num_firewall_v6++; + IPACM_Wan::num_v6_flt_rule++; + } + else + { + memset(&flt_eq, 0, sizeof(flt_eq)); + memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib)); + flt_eq.ip = iptype; + if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq)) + { + IPACMERR("Failed to get eq_attrib\n"); + return IPACM_FAILURE; + } + + memcpy(&flt_rule_entry.rule.eq_attrib, + &flt_eq.eq_attrib, + sizeof(flt_rule_entry.rule.eq_attrib)); + memcpy(&(rules[pos]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + pos++; + num_firewall_v6++; + IPACM_Wan::num_v6_flt_rule++; + } + } + } /* end of firewall ipv6 filter rule add for loop*/ + } + + /* setup default wan filter rule */ + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); + + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl = -1; + flt_rule_entry.status = -1; + + flt_rule_entry.rule.retain_hdr = 1; + flt_rule_entry.rule.to_uc = 0; + flt_rule_entry.rule.eq_attrib_type = 1; + flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING; + memset(&rt_tbl_idx, 0, sizeof(rt_tbl_idx)); + rt_tbl_idx.ip = iptype; + /* firewall disable, all traffic are allowed */ + if(firewall_config.firewall_enable == true) + { + /* default action for v6 is PASS_TO_ROUTE unless user set to exception*/ + if(firewall_config.rule_action_accept == true) + { + strlcpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_dl.name, IPA_RESOURCE_NAME_MAX); + } + else + { + strlcpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.name, IPA_RESOURCE_NAME_MAX); + } + } + else + { + strlcpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.name, IPA_RESOURCE_NAME_MAX); + } + rt_tbl_idx.name[IPA_RESOURCE_NAME_MAX-1] = '\0'; + if(0 != ioctl(m_fd_ipa, IPA_IOC_QUERY_RT_TBL_INDEX, &rt_tbl_idx)) + { + IPACMERR("Failed to get routing table index from name\n"); + return IPACM_FAILURE; + } + flt_rule_entry.rule.rt_tbl_idx = rt_tbl_idx.idx; + + IPACMDBG_H("Routing table %s has index %d\n", rt_tbl_idx.name, rt_tbl_idx.idx); + + memcpy(&flt_rule_entry.rule.attrib, + &rx_prop->rx[1].attrib, + sizeof(struct ipa_rule_attrib)); + flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0x00000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[1] = 0x00000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = 0x00000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr[0] = 0X00000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = 0x00000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = 0x00000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X00000000; + + change_to_network_order(IPA_IP_v6, &flt_rule_entry.rule.attrib); + + memset(&flt_eq, 0, sizeof(flt_eq)); + memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib)); + flt_eq.ip = iptype; + if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq)) + { + IPACMERR("Failed to get eq_attrib\n"); + return IPACM_FAILURE; + } + memcpy(&flt_rule_entry.rule.eq_attrib, + &flt_eq.eq_attrib, + sizeof(flt_rule_entry.rule.eq_attrib)); + memcpy(&(rules[pos]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + pos++; + num_firewall_v6++; + IPACM_Wan::num_v6_flt_rule++; + + num_rules = IPACM_Wan::num_v6_flt_rule - original_num_rules - 1; + } + IPACMDBG_H("Constructed %d firewall rules for ip type %d\n", num_rules, iptype); + return IPACM_SUCCESS; +} + +void IPACM_Wan::config_ip_type(ipa_ip_type iptype) +{ + + /* update the iface ip-type to be IPA_IP_v4, IPA_IP_v6 or both*/ + if (iptype == IPA_IP_v4) + { + + if ((ip_type == IPA_IP_v4) || (ip_type == IPA_IP_MAX)) + { + IPACMDBG_H(" interface(%s:%d) already in ip-type %d\n", dev_name, ipa_if_num, ip_type); + return; + } + + if (ip_type == IPA_IP_v6) + { + ip_type = IPA_IP_MAX; + } + else + { + ip_type = IPA_IP_v4; + } + IPACMDBG_H(" interface(%s:%d) now ip-type is %d\n", dev_name, ipa_if_num, ip_type); + } + else + { + if ((ip_type == IPA_IP_v6) || (ip_type == IPA_IP_MAX)) + { + IPACMDBG_H(" interface(%s:%d) already in ip-type %d\n", dev_name, ipa_if_num, ip_type); + return; + } + + if (ip_type == IPA_IP_v4) + { + ip_type = IPA_IP_MAX; + } + else + { + ip_type = IPA_IP_v6; + } + + IPACMDBG_H(" interface(%s:%d) now ip-type is %d\n", dev_name, ipa_if_num, ip_type); + } + + return; +} + +int IPACM_Wan::init_fl_rule_ex(ipa_ip_type iptype) +{ + int res = IPACM_SUCCESS; + + char *dev_wlan0="wlan0"; + char *dev_wlan1="wlan1"; + char *dev_ecm0="ecm0"; + + /* ADD corresponding ipa_rm_resource_name of RX-endpoint before adding all IPV4V6 FT-rules */ + IPACMDBG_H(" dun add producer dependency from %s with registered rx-prop\n", dev_name); + + if(iptype == IPA_IP_v4) + { + if(modem_ipv4_pdn_index == 0) /* install ipv4 default modem DL filtering rules only once */ + { + /* reset the num_v4_flt_rule*/ + IPACM_Wan::num_v4_flt_rule = 0; + add_dft_filtering_rule(flt_rule_v4, IPACM_Wan::num_v4_flt_rule, IPA_IP_v4); + } + } + else if(iptype == IPA_IP_v6) + { + if(modem_ipv6_pdn_index == 0) /* install ipv6 default modem DL filtering rules only once */ + { + /* reset the num_v6_flt_rule*/ + IPACM_Wan::num_v6_flt_rule = 0; + add_dft_filtering_rule(flt_rule_v6, IPACM_Wan::num_v6_flt_rule, IPA_IP_v6); + } + } + else + { + IPACMERR("IP type is not expected.\n"); + res = IPACM_FAILURE; + goto fail; + } + install_wan_filtering_rule(false); + +fail: + return res; +} + +int IPACM_Wan::add_icmp_alg_rules(struct ipa_flt_rule_add *rules, int rule_offset, ipa_ip_type iptype) +{ + int res = IPACM_SUCCESS, i, original_num_rules = 0, num_rules = 0; + struct ipa_flt_rule_add flt_rule_entry; + IPACM_Config* ipacm_config = IPACM_Iface::ipacmcfg; + ipa_ioc_generate_flt_eq flt_eq; + ipa_ioc_get_rt_tbl_indx rt_tbl_idx; + + if(rules == NULL || rule_offset < 0) + { + IPACMERR("No filtering table is available.\n"); + return IPACM_FAILURE; + } + + if(iptype == IPA_IP_v4) + { + original_num_rules = IPACM_Wan::num_v4_flt_rule; + + memset(&rt_tbl_idx, 0, sizeof(rt_tbl_idx)); + strlcpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_dl.name, IPA_RESOURCE_NAME_MAX); + rt_tbl_idx.name[IPA_RESOURCE_NAME_MAX-1] = '\0'; + rt_tbl_idx.ip = iptype; + if(0 != ioctl(m_fd_ipa, IPA_IOC_QUERY_RT_TBL_INDEX, &rt_tbl_idx)) + { + IPACMERR("Failed to get routing table index from name\n"); + res = IPACM_FAILURE; + goto fail; + } + + IPACMDBG_H("WAN DL routing table %s has index %d\n", IPACM_Iface::ipacmcfg->rt_tbl_wan_dl.name, rt_tbl_idx.idx); + + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); + + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl = -1; + flt_rule_entry.status = -1; + + flt_rule_entry.rule.retain_hdr = 1; + flt_rule_entry.rule.to_uc = 0; + flt_rule_entry.rule.eq_attrib_type = 1; + flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING; + flt_rule_entry.rule.rt_tbl_idx = rt_tbl_idx.idx; + + /* Configuring ICMP filtering rule */ + memcpy(&flt_rule_entry.rule.attrib, + &rx_prop->rx[0].attrib, + sizeof(flt_rule_entry.rule.attrib)); + /* Multiple PDNs may exist so keep meta-data */ + flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_PROTOCOL; + flt_rule_entry.rule.attrib.u.v4.protocol = (uint8_t)IPACM_FIREWALL_IPPROTO_ICMP; + + memset(&flt_eq, 0, sizeof(flt_eq)); + memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib)); + flt_eq.ip = iptype; + if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq)) + { + IPACMERR("Failed to get eq_attrib\n"); + res = IPACM_FAILURE; + goto fail; + } + + memcpy(&flt_rule_entry.rule.eq_attrib, + &flt_eq.eq_attrib, + sizeof(flt_rule_entry.rule.eq_attrib)); + + memcpy(&(rules[rule_offset]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + + IPACM_Wan::num_v4_flt_rule++; + + /* Configure ALG filtering rules */ + memcpy(&flt_rule_entry.rule.attrib, + &rx_prop->rx[0].attrib, + sizeof(flt_rule_entry.rule.attrib)); + /* remove meta data mask */ + flt_rule_entry.rule.attrib.attrib_mask &= ~((uint32_t)IPA_FLT_META_DATA); + flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_SRC_PORT; + flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_PROTOCOL; + for(i = 0; i < ipacm_config->ipa_num_alg_ports; i++) + { + flt_rule_entry.rule.attrib.src_port = ipacm_config->alg_table[i].port; + flt_rule_entry.rule.attrib.u.v4.protocol = ipacm_config->alg_table[i].protocol; + + memset(&flt_eq, 0, sizeof(flt_eq)); + memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib)); + flt_eq.ip = iptype; + if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq)) + { + IPACMERR("Failed to get eq_attrib\n"); + res = IPACM_FAILURE; + goto fail; + } + memcpy(&flt_rule_entry.rule.eq_attrib, + &flt_eq.eq_attrib, + sizeof(flt_rule_entry.rule.eq_attrib)); + memcpy(&(rules[rule_offset + 1 + i]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + IPACM_Wan::num_v4_flt_rule++; + } + + memcpy(&flt_rule_entry.rule.attrib, + &rx_prop->rx[0].attrib, + sizeof(flt_rule_entry.rule.attrib)); + /* remove meta data mask */ + flt_rule_entry.rule.attrib.attrib_mask &= ~((uint32_t)IPA_FLT_META_DATA); + flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_PORT; + flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_PROTOCOL; + for(i = 0; i < ipacm_config->ipa_num_alg_ports; i++) + { + flt_rule_entry.rule.attrib.dst_port = ipacm_config->alg_table[i].port; + flt_rule_entry.rule.attrib.u.v4.protocol = ipacm_config->alg_table[i].protocol; + + memset(&flt_eq, 0, sizeof(flt_eq)); + memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib)); + flt_eq.ip = iptype; + if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq)) + { + IPACMERR("Failed to get eq_attrib\n"); + res = IPACM_FAILURE; + goto fail; + } + + memcpy(&flt_rule_entry.rule.eq_attrib, + &flt_eq.eq_attrib, + sizeof(flt_rule_entry.rule.eq_attrib)); + + memcpy(&(rules[rule_offset + ipacm_config->ipa_num_alg_ports + 1 + i]), + &flt_rule_entry, + sizeof(struct ipa_flt_rule_add)); + IPACM_Wan::num_v4_flt_rule++; + } + num_rules = IPACM_Wan::num_v4_flt_rule - original_num_rules; + } + else /* IPv6 case */ + { + original_num_rules = IPACM_Wan::num_v6_flt_rule; + + memset(&rt_tbl_idx, 0, sizeof(rt_tbl_idx)); + strlcpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_dl.name, IPA_RESOURCE_NAME_MAX); + rt_tbl_idx.name[IPA_RESOURCE_NAME_MAX-1] = '\0'; + rt_tbl_idx.ip = iptype; + if(0 != ioctl(m_fd_ipa, IPA_IOC_QUERY_RT_TBL_INDEX, &rt_tbl_idx)) + { + IPACMERR("Failed to get routing table index from name\n"); + res = IPACM_FAILURE; + goto fail; + } + + IPACMDBG_H("WAN DL routing table %s has index %d\n", IPACM_Iface::ipacmcfg->rt_tbl_wan_dl.name, rt_tbl_idx.idx); + + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); + + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl = -1; + flt_rule_entry.status = -1; + + flt_rule_entry.rule.retain_hdr = 1; + flt_rule_entry.rule.to_uc = 0; + flt_rule_entry.rule.eq_attrib_type = 1; + flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING; + flt_rule_entry.rule.rt_tbl_idx = rt_tbl_idx.idx; + + /* Configuring ICMP filtering rule */ + memcpy(&flt_rule_entry.rule.attrib, + &rx_prop->rx[1].attrib, + sizeof(flt_rule_entry.rule.attrib)); + /* Multiple PDNs may exist so keep meta-data */ + flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_NEXT_HDR; + flt_rule_entry.rule.attrib.u.v6.next_hdr = (uint8_t)IPACM_FIREWALL_IPPROTO_ICMP6; + + memset(&flt_eq, 0, sizeof(flt_eq)); + memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib)); + flt_eq.ip = iptype; + if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq)) + { + IPACMERR("Failed to get eq_attrib\n"); + res = IPACM_FAILURE; + goto fail; + } + + memcpy(&flt_rule_entry.rule.eq_attrib, + &flt_eq.eq_attrib, + sizeof(flt_rule_entry.rule.eq_attrib)); + + memcpy(&(rules[rule_offset]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + IPACM_Wan::num_v6_flt_rule++; + + num_rules = IPACM_Wan::num_v6_flt_rule - original_num_rules; + } + +fail: + IPACMDBG_H("Constructed %d ICMP/ALG rules for ip type %d\n", num_rules, iptype); + return res; +} + +int IPACM_Wan::query_ext_prop() +{ + int fd, ret = IPACM_SUCCESS, cnt; + + if (iface_query->num_ext_props > 0) + { + fd = open(IPA_DEVICE_NAME, O_RDWR); + IPACMDBG_H("iface query-property \n"); + if (0 == fd) + { + IPACMERR("Failed opening %s.\n", IPA_DEVICE_NAME); + return IPACM_FAILURE; + } + + ext_prop = (struct ipa_ioc_query_intf_ext_props *) + calloc(1, sizeof(struct ipa_ioc_query_intf_ext_props) + + iface_query->num_ext_props * sizeof(struct ipa_ioc_ext_intf_prop)); + if(ext_prop == NULL) + { + IPACMERR("Unable to allocate memory.\n"); + return IPACM_FAILURE; + } + memcpy(ext_prop->name, dev_name, + sizeof(dev_name)); + ext_prop->num_ext_props = iface_query->num_ext_props; + + IPACMDBG_H("Query extended property for iface %s\n", ext_prop->name); + + ret = ioctl(fd, IPA_IOC_QUERY_INTF_EXT_PROPS, ext_prop); + if (ret < 0) + { + IPACMERR("ioctl IPA_IOC_QUERY_INTF_EXT_PROPS failed\n"); + /* ext_prop memory will free when iface-down*/ + free(ext_prop); + close(fd); + return ret; + } + + IPACMDBG_H("Wan interface has %d tx props, %d rx props and %d ext props\n", + iface_query->num_tx_props, iface_query->num_rx_props, iface_query->num_ext_props); + + for (cnt = 0; cnt < ext_prop->num_ext_props; cnt++) + { +#ifndef FEATURE_IPA_V3 + IPACMDBG_H("Ex(%d): ip-type: %d, mux_id: %d, flt_action: %d\n, rt_tbl_idx: %d, is_xlat_rule: %d flt_hdl: %d\n", + cnt, ext_prop->ext[cnt].ip, ext_prop->ext[cnt].mux_id, ext_prop->ext[cnt].action, + ext_prop->ext[cnt].rt_tbl_idx, ext_prop->ext[cnt].is_xlat_rule, ext_prop->ext[cnt].filter_hdl); +#else /* defined (FEATURE_IPA_V3) */ + IPACMDBG_H("Ex(%d): ip-type: %d, mux_id: %d, flt_action: %d\n, rt_tbl_idx: %d, is_xlat_rule: %d rule_id: %d\n", + cnt, ext_prop->ext[cnt].ip, ext_prop->ext[cnt].mux_id, ext_prop->ext[cnt].action, + ext_prop->ext[cnt].rt_tbl_idx, ext_prop->ext[cnt].is_xlat_rule, ext_prop->ext[cnt].rule_id); +#endif + } + + if(IPACM_Wan::is_ext_prop_set == false) + { + IPACM_Iface::ipacmcfg->SetExtProp(ext_prop); + IPACM_Wan::is_ext_prop_set = true; + } + close(fd); + } + return IPACM_SUCCESS; +} + +int IPACM_Wan::config_wan_firewall_rule(ipa_ip_type iptype) +{ + int res = IPACM_SUCCESS; + + IPACMDBG_H("Configure WAN DL firewall rules.\n"); + + if(iptype == IPA_IP_v4) + { + IPACM_Wan::num_v4_flt_rule = IPA_V2_NUM_DEFAULT_WAN_FILTER_RULE_IPV4; + if(IPACM_FAILURE == add_icmp_alg_rules(flt_rule_v4, IPACM_Wan::num_v4_flt_rule, IPA_IP_v4)) + { + IPACMERR("Failed to add ICMP and ALG port filtering rules.\n"); + res = IPACM_FAILURE; + goto fail; + } + IPACMDBG_H("Succeded in constructing ICMP/ALG rules for ip type %d\n", iptype); + + if(IPACM_FAILURE == config_dft_firewall_rules_ex(flt_rule_v4, IPACM_Wan::num_v4_flt_rule, IPA_IP_v4)) + { + IPACMERR("Failed to add firewall filtering rules.\n"); + res = IPACM_FAILURE; + goto fail; + } + IPACMDBG_H("Succeded in constructing firewall rules for ip type %d\n", iptype); + } + else if(iptype == IPA_IP_v6) + { + IPACM_Wan::num_v6_flt_rule = IPA_V2_NUM_DEFAULT_WAN_FILTER_RULE_IPV6; + if(IPACM_FAILURE == add_icmp_alg_rules(flt_rule_v6, IPACM_Wan::num_v6_flt_rule, IPA_IP_v6)) + { + IPACMERR("Failed to add ICMP and ALG port filtering rules.\n"); + res = IPACM_FAILURE; + goto fail; + } + IPACMDBG_H("Succeded in constructing ICMP/ALG rules for ip type %d\n", iptype); + + if(IPACM_FAILURE == config_dft_firewall_rules_ex(flt_rule_v6, IPACM_Wan::num_v6_flt_rule, IPA_IP_v6)) + { + IPACMERR("Failed to add firewall filtering rules.\n"); + res = IPACM_FAILURE; + goto fail; + } + IPACMDBG_H("Succeded in constructing firewall rules for ip type %d\n", iptype); + } + else + { + IPACMERR("IP type is not expected.\n"); + return IPACM_FAILURE; + } + +fail: + return res; +} + +int IPACM_Wan::add_dft_filtering_rule(struct ipa_flt_rule_add *rules, int rule_offset, ipa_ip_type iptype) +{ + struct ipa_ioc_get_rt_tbl_indx rt_tbl_idx; + struct ipa_flt_rule_add flt_rule_entry; + struct ipa_ioc_generate_flt_eq flt_eq; + int res = IPACM_SUCCESS; + + if(rules == NULL) + { + IPACMERR("No filtering table available.\n"); + return IPACM_FAILURE; + } + if(rx_prop == NULL) + { + IPACMERR("No tx property.\n"); + return IPACM_FAILURE; + } + + if (iptype == IPA_IP_v4) + { + memset(&rt_tbl_idx, 0, sizeof(rt_tbl_idx)); + strlcpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_dl.name, IPA_RESOURCE_NAME_MAX); + rt_tbl_idx.name[IPA_RESOURCE_NAME_MAX-1] = '\0'; + rt_tbl_idx.ip = iptype; + if(0 != ioctl(m_fd_ipa, IPA_IOC_QUERY_RT_TBL_INDEX, &rt_tbl_idx)) + { + IPACMERR("Failed to get routing table index from name\n"); + res = IPACM_FAILURE; + goto fail; + } + + IPACMDBG_H("Routing table %s has index %d\n", rt_tbl_idx.name, rt_tbl_idx.idx); + + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); + + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl = -1; + flt_rule_entry.status = -1; + + flt_rule_entry.rule.retain_hdr = 1; + flt_rule_entry.rule.to_uc = 0; + flt_rule_entry.rule.eq_attrib_type = 1; + flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING; + flt_rule_entry.rule.rt_tbl_idx = rt_tbl_idx.idx; + + IPACMDBG_H("rx property attrib mask:0x%x\n", rx_prop->rx[0].attrib.attrib_mask); + + /* Configuring Multicast Filtering Rule */ + memcpy(&flt_rule_entry.rule.attrib, + &rx_prop->rx[0].attrib, + sizeof(flt_rule_entry.rule.attrib)); + /* remove meta data mask since we only install default flt rules once for all modem PDN*/ + flt_rule_entry.rule.attrib.attrib_mask &= ~((uint32_t)IPA_FLT_META_DATA); + flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; + flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0xF0000000; + flt_rule_entry.rule.attrib.u.v4.dst_addr = 0xE0000000; + + change_to_network_order(IPA_IP_v4, &flt_rule_entry.rule.attrib); + + memset(&flt_eq, 0, sizeof(flt_eq)); + memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib)); + flt_eq.ip = iptype; + if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq)) + { + IPACMERR("Failed to get eq_attrib\n"); + res = IPACM_FAILURE; + goto fail; + } + + memcpy(&flt_rule_entry.rule.eq_attrib, + &flt_eq.eq_attrib, + sizeof(flt_rule_entry.rule.eq_attrib)); + memcpy(&(rules[rule_offset]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + + /* Configuring Broadcast Filtering Rule */ + flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF; + flt_rule_entry.rule.attrib.u.v4.dst_addr = 0xFFFFFFFF; + + change_to_network_order(IPA_IP_v4, &flt_rule_entry.rule.attrib); + + memset(&flt_eq, 0, sizeof(flt_eq)); + memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib)); + flt_eq.ip = iptype; + if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq)) + { + IPACMERR("Failed to get eq_attrib\n"); + res = IPACM_FAILURE; + goto fail; + } + + memcpy(&flt_rule_entry.rule.eq_attrib, + &flt_eq.eq_attrib, + sizeof(flt_rule_entry.rule.eq_attrib)); + memcpy(&(rules[rule_offset + 1]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + + IPACM_Wan::num_v4_flt_rule += IPA_V2_NUM_DEFAULT_WAN_FILTER_RULE_IPV4; + IPACMDBG_H("Constructed %d default filtering rules for ip type %d\n", IPA_V2_NUM_DEFAULT_WAN_FILTER_RULE_IPV4, iptype); + } + else /*insert rules for ipv6*/ + { + memset(&rt_tbl_idx, 0, sizeof(rt_tbl_idx)); + strlcpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_dl.name, IPA_RESOURCE_NAME_MAX); + rt_tbl_idx.name[IPA_RESOURCE_NAME_MAX-1] = '\0'; + rt_tbl_idx.ip = iptype; + if(0 != ioctl(m_fd_ipa, IPA_IOC_QUERY_RT_TBL_INDEX, &rt_tbl_idx)) + { + IPACMERR("Failed to get routing table index from name\n"); + res = IPACM_FAILURE; + goto fail; + } + + IPACMDBG_H("Routing table %s has index %d\n", rt_tbl_idx.name, rt_tbl_idx.idx); + + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); + + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl = -1; + flt_rule_entry.status = -1; + + flt_rule_entry.rule.retain_hdr = 1; + flt_rule_entry.rule.to_uc = 0; + flt_rule_entry.rule.eq_attrib_type = 1; + flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING; + flt_rule_entry.rule.rt_tbl_idx = rt_tbl_idx.idx; + + /* Configuring Multicast Filtering Rule */ + memcpy(&flt_rule_entry.rule.attrib, + &rx_prop->rx[0].attrib, + sizeof(flt_rule_entry.rule.attrib)); + /* remove meta data mask since we only install default flt rules once for all modem PDN*/ + flt_rule_entry.rule.attrib.attrib_mask &= ~((uint32_t)IPA_FLT_META_DATA); + flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0xFF000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[1] = 0x00000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = 0x00000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr[0] = 0xFF000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = 0x00000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = 0x00000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0x00000000; + + change_to_network_order(IPA_IP_v6, &flt_rule_entry.rule.attrib); + + memset(&flt_eq, 0, sizeof(flt_eq)); + memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib)); + flt_eq.ip = iptype; + if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq)) + { + IPACMERR("Failed to get eq_attrib\n"); + res = IPACM_FAILURE; + goto fail; + } + + memcpy(&flt_rule_entry.rule.eq_attrib, + &flt_eq.eq_attrib, + sizeof(flt_rule_entry.rule.eq_attrib)); + memcpy(&(rules[rule_offset]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + + /* Configuring fe80::/10 Link-Scoped Unicast Filtering Rule */ + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0xFFC00000; + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[1] = 0x00000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = 0x00000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr[0] = 0xFE800000; + flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = 0x00000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = 0x00000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0x00000000; + + change_to_network_order(IPA_IP_v6, &flt_rule_entry.rule.attrib); + + memset(&flt_eq, 0, sizeof(flt_eq)); + memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib)); + flt_eq.ip = iptype; + if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq)) + { + IPACMERR("Failed to get eq_attrib\n"); + res = IPACM_FAILURE; + goto fail; + } + + memcpy(&flt_rule_entry.rule.eq_attrib, + &flt_eq.eq_attrib, + sizeof(flt_rule_entry.rule.eq_attrib)); + + memcpy(&(rules[rule_offset + 1]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + + /* Configuring fec0::/10 Reserved by IETF Filtering Rule */ + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0xFFC00000; + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[1] = 0x00000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = 0x00000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr[0] = 0xFEC00000; + flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = 0x00000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = 0x00000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0x00000000; + + change_to_network_order(IPA_IP_v6, &flt_rule_entry.rule.attrib); + + memset(&flt_eq, 0, sizeof(flt_eq)); + memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib)); + flt_eq.ip = iptype; + if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq)) + { + IPACMERR("Failed to get eq_attrib\n"); + res = IPACM_FAILURE; + goto fail; + } + + memcpy(&flt_rule_entry.rule.eq_attrib, + &flt_eq.eq_attrib, + sizeof(flt_rule_entry.rule.eq_attrib)); + + memcpy(&(rules[rule_offset + 2]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + +#ifdef FEATURE_IPA_ANDROID + IPACMDBG_H("Add TCP ctrl rules: total num %d\n", IPA_V2_NUM_DEFAULT_WAN_FILTER_RULE_IPV6); + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); + + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl = -1; + flt_rule_entry.status = -1; + + flt_rule_entry.rule.retain_hdr = 1; + flt_rule_entry.rule.to_uc = 0; + flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING; + flt_rule_entry.rule.rt_tbl_idx = rt_tbl_idx.idx; + flt_rule_entry.rule.eq_attrib_type = 1; + + flt_rule_entry.rule.eq_attrib.rule_eq_bitmap = 0; + + flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<1); + flt_rule_entry.rule.eq_attrib.protocol_eq_present = 1; + flt_rule_entry.rule.eq_attrib.protocol_eq = IPACM_FIREWALL_IPPROTO_TCP; + + flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<8); + flt_rule_entry.rule.eq_attrib.num_ihl_offset_meq_32 = 1; + flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].offset = 12; + + /* add TCP FIN rule*/ + flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].value = (((uint32_t)1)< IPACM_MAX_FIREWALL_ENTRIES) + { + IPACMERR("the number of v4 firewall entries overflow, aborting...\n"); + return IPACM_FAILURE; + } + if (num_firewall_v4 != 0) + { + if (m_filtering.DeleteFilteringHdls(firewall_hdl_v4, + IPA_IP_v4, num_firewall_v4) == false) + { + IPACMERR("Error Deleting Filtering rules, aborting...\n"); + return IPACM_FAILURE; + } + IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, num_firewall_v4); + } + else + { + IPACMDBG_H("No ipv4 firewall rules, no need deleted\n"); + } + + if (m_filtering.DeleteFilteringHdls(dft_wan_fl_hdl, + IPA_IP_v4, 1) == false) + { + IPACMERR("Error Deleting Filtering rules, aborting...\n"); + return IPACM_FAILURE; + } + IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, 1); + + num_firewall_v4 = 0; + } + + /* free v6 firewall filter rule */ + if ((iptype == IPA_IP_v6) && (active_v6 == true)) + { + if (num_firewall_v6 > IPACM_MAX_FIREWALL_ENTRIES) + { + IPACMERR("the number of v6 firewall entries overflow, aborting...\n"); + return IPACM_FAILURE; + } + if (num_firewall_v6 != 0) + { + if (m_filtering.DeleteFilteringHdls(firewall_hdl_v6, + IPA_IP_v6, num_firewall_v6) == false) + { + IPACMERR("Error Deleting Filtering rules, aborting...\n"); + return IPACM_FAILURE; + } + IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, num_firewall_v6); + } + else + { + IPACMDBG_H("No ipv6 firewall rules, no need deleted\n"); + } + + if (m_filtering.DeleteFilteringHdls(&dft_wan_fl_hdl[1], + IPA_IP_v6, 1) == false) + { + IPACMERR("Error Deleting Filtering rules, aborting...\n"); + return IPACM_FAILURE; + } + IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1); + if (m_filtering.DeleteFilteringHdls(&dft_wan_fl_hdl[2], + IPA_IP_v6, 1) == false) + { + IPACMERR("Error Deleting Filtering rules, aborting...\n"); + return IPACM_FAILURE; + } + IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1); + + if (firewall_config.firewall_enable == true && + check_dft_firewall_rules_attr_mask(&firewall_config)) + { + if (m_filtering.DeleteFilteringHdls(&ipv6_frag_firewall_flt_rule_hdl, IPA_IP_v6, 1) == false) + { + IPACMERR("Error deleting IPv6 frag filtering rules.\n"); + return IPACM_FAILURE; + } + IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1); + } + num_firewall_v6 = 0; + } + + return IPACM_SUCCESS; +} + +/* for STA mode: wan default route/filter rule delete */ +int IPACM_Wan::handle_route_del_evt(ipa_ip_type iptype) +{ + uint32_t tx_index; + ipacm_cmd_q_data evt_data; + + IPACMDBG_H("got handle_route_del_evt for STA-mode with ip-family:%d \n", iptype); + + if(tx_prop == NULL) + { + IPACMDBG_H("No tx properties, ignore delete default route setting\n"); + return IPACM_SUCCESS; + } + + is_default_gateway = false; + IPACMDBG_H("Default route is deleted to iface %s.\n", dev_name); + + if (((iptype == IPA_IP_v4) && (active_v4 == true)) || + ((iptype == IPA_IP_v6) && (active_v6 == true))) + { + + /* Delete corresponding ipa_rm_resource_name of TX-endpoint after delete IPV4/V6 RT-rule */ + IPACMDBG_H("dev %s add producer dependency\n", dev_name); + IPACMDBG_H("depend Got pipe %d rm index : %d \n", tx_prop->tx[0].dst_pipe, IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe]); + IPACM_Iface::ipacmcfg->DelRmDepend(IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe]); + + for (tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++) + { + if(iptype != tx_prop->tx[tx_index].ip) + { + IPACMDBG_H("Tx:%d, ip-type: %d conflict ip-type: %d, no RT-rule deleted\n", + tx_index, tx_prop->tx[tx_index].ip,iptype); + continue; + } + + if (iptype == IPA_IP_v4) + { + IPACMDBG_H("Tx:%d, ip-type: %d match ip-type: %d, RT-rule deleted\n", tx_index, tx_prop->tx[tx_index].ip,iptype); + + if (m_routing.DeleteRoutingHdl(wan_route_rule_v4_hdl[tx_index], IPA_IP_v4) == false) + { + IPACMDBG_H("IP-family:%d, Routing rule(hdl:0x%x) deletion failed with tx_index %d!\n", IPA_IP_v4, wan_route_rule_v4_hdl[tx_index], tx_index); + return IPACM_FAILURE; + } + } + else + { + IPACMDBG_H("Tx:%d, ip-type: %d match ip-type: %d, RT-rule deleted\n", tx_index, tx_prop->tx[tx_index].ip,iptype); + + if (m_routing.DeleteRoutingHdl(wan_route_rule_v6_hdl[tx_index], IPA_IP_v6) == false) + { + IPACMDBG_H("IP-family:%d, Routing rule(hdl:0x%x) deletion failed with tx_index %d!\n", IPA_IP_v6, wan_route_rule_v6_hdl[tx_index], tx_index); + return IPACM_FAILURE; + } + } + } + + /* Delete the default wan route*/ + if (iptype == IPA_IP_v6) + { + IPACMDBG_H("ip-type %d: default v6 wan RT-rule deleted\n",iptype); + if (m_routing.DeleteRoutingHdl(wan_route_rule_v6_hdl_a5[0], IPA_IP_v6) == false) + { + IPACMDBG_H("IP-family:%d, Routing rule(hdl:0x%x) deletion failed!\n",IPA_IP_v6,wan_route_rule_v6_hdl_a5[0]); + return IPACM_FAILURE; + } + } + ipacm_event_iface_up *wandown_data; + wandown_data = (ipacm_event_iface_up *)malloc(sizeof(ipacm_event_iface_up)); + if (wandown_data == NULL) + { + IPACMERR("Unable to allocate memory\n"); + return IPACM_FAILURE; + } + memset(wandown_data, 0, sizeof(ipacm_event_iface_up)); + + if (iptype == IPA_IP_v4) + { + wandown_data->ipv4_addr = wan_v4_addr; + if (m_is_sta_mode!=Q6_WAN) + { + wandown_data->is_sta = true; + } + else + { + wandown_data->is_sta = false; + } + evt_data.event = IPA_HANDLE_WAN_DOWN; + evt_data.evt_data = (void *)wandown_data; + /* Insert IPA_HANDLE_WAN_DOWN to command queue */ + IPACMDBG_H("posting IPA_HANDLE_WAN_DOWN for IPv4 (%d.%d.%d.%d) \n", + (unsigned char)(wandown_data->ipv4_addr), + (unsigned char)(wandown_data->ipv4_addr >> 8), + (unsigned char)(wandown_data->ipv4_addr >> 16), + (unsigned char)(wandown_data->ipv4_addr >> 24)); + + IPACM_EvtDispatcher::PostEvt(&evt_data); + IPACMDBG_H("setup wan_up/active_v4= false \n"); + IPACM_Wan::wan_up = false; + active_v4 = false; + if(IPACM_Wan::wan_up_v6) + { + IPACMDBG_H("modem v6-call still up(%s), not reset\n", IPACM_Wan::wan_up_dev_name); + } + else + { + memset(IPACM_Wan::wan_up_dev_name, 0, sizeof(IPACM_Wan::wan_up_dev_name)); + } + } + else + { + if (m_is_sta_mode!=Q6_WAN) + { + wandown_data->is_sta = true; + } + else + { + wandown_data->is_sta = false; + } + memcpy(wandown_data->ipv6_prefix, ipv6_prefix, sizeof(wandown_data->ipv6_prefix)); + evt_data.event = IPA_HANDLE_WAN_DOWN_V6; + evt_data.evt_data = (void *)wandown_data; + /* Insert IPA_HANDLE_WAN_DOWN to command queue */ + IPACMDBG_H("posting IPA_HANDLE_WAN_DOWN for IPv6 with prefix 0x%08x%08x\n", ipv6_prefix[0], ipv6_prefix[1]); + IPACM_EvtDispatcher::PostEvt(&evt_data); + IPACMDBG_H("setup wan_up_v6/active_v6= false \n"); + IPACM_Wan::wan_up_v6 = false; + active_v6 = false; + if(IPACM_Wan::wan_up) + { + IPACMDBG_H("modem v4-call still up(%s), not reset\n", IPACM_Wan::wan_up_dev_name); + } + else + { + memset(IPACM_Wan::wan_up_dev_name, 0, sizeof(IPACM_Wan::wan_up_dev_name)); + } + } + } + else + { + IPACMDBG_H(" The default WAN routing rules are deleted already \n"); + } + + return IPACM_SUCCESS; +} + +int IPACM_Wan::handle_route_del_evt_ex(ipa_ip_type iptype) +{ + ipacm_cmd_q_data evt_data; + + IPACMDBG_H("got handle_route_del_evt_ex with ip-family:%d \n", iptype); + + if(tx_prop == NULL) + { + IPACMDBG_H("No tx properties, ignore delete default route setting\n"); + return IPACM_SUCCESS; + } + + is_default_gateway = false; + IPACMDBG_H("Default route is deleted to iface %s.\n", dev_name); + + if (((iptype == IPA_IP_v4) && (active_v4 == true)) || + ((iptype == IPA_IP_v6) && (active_v6 == true))) + { + + /* Delete corresponding ipa_rm_resource_name of TX-endpoint after delete IPV4/V6 RT-rule */ + IPACMDBG_H("dev %s add producer dependency\n", dev_name); + IPACMDBG_H("depend Got pipe %d rm index : %d \n", tx_prop->tx[0].dst_pipe, IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe]); + IPACM_Iface::ipacmcfg->DelRmDepend(IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe]); + + /* Delete the default route*/ + if (iptype == IPA_IP_v6) + { + IPACMDBG_H("ip-type %d: default v6 wan RT-rule deleted\n",iptype); + if (m_routing.DeleteRoutingHdl(wan_route_rule_v6_hdl_a5[0], IPA_IP_v6) == false) + { + IPACMDBG_H("IP-family:%d, Routing rule(hdl:0x%x) deletion failed!\n",IPA_IP_v6,wan_route_rule_v6_hdl_a5[0]); + return IPACM_FAILURE; + } + } + + ipacm_event_iface_up *wandown_data; + wandown_data = (ipacm_event_iface_up *)malloc(sizeof(ipacm_event_iface_up)); + if (wandown_data == NULL) + { + IPACMERR("Unable to allocate memory\n"); + return IPACM_FAILURE; + } + memset(wandown_data, 0, sizeof(ipacm_event_iface_up)); + + if (iptype == IPA_IP_v4) + { + wandown_data->ipv4_addr = wan_v4_addr; + if (m_is_sta_mode!=Q6_WAN) + { + wandown_data->is_sta = true; + } + else + { + wandown_data->is_sta = false; + } + evt_data.event = IPA_HANDLE_WAN_DOWN; + evt_data.evt_data = (void *)wandown_data; + /* Insert IPA_HANDLE_WAN_DOWN to command queue */ + IPACMDBG_H("posting IPA_HANDLE_WAN_DOWN for IPv4 with address: 0x%x\n", wan_v4_addr); + IPACM_EvtDispatcher::PostEvt(&evt_data); + + IPACMDBG_H("setup wan_up/active_v4= false \n"); + IPACM_Wan::wan_up = false; + active_v4 = false; + if(IPACM_Wan::wan_up_v6) + { + IPACMDBG_H("modem v6-call still up(%s), not reset\n", IPACM_Wan::wan_up_dev_name); + } + else + { + memset(IPACM_Wan::wan_up_dev_name, 0, sizeof(IPACM_Wan::wan_up_dev_name)); + } + } + else + { + if (m_is_sta_mode!=Q6_WAN) + { + wandown_data->is_sta = true; + } + else + { + wandown_data->is_sta = false; + } + memcpy(wandown_data->ipv6_prefix, ipv6_prefix, sizeof(wandown_data->ipv6_prefix)); + evt_data.event = IPA_HANDLE_WAN_DOWN_V6; + evt_data.evt_data = (void *)wandown_data; + IPACMDBG_H("posting IPA_HANDLE_WAN_DOWN_V6 for IPv6 with prefix 0x%08x%08x\n", ipv6_prefix[0], ipv6_prefix[1]); + IPACM_EvtDispatcher::PostEvt(&evt_data); + + IPACMDBG_H("setup wan_up_v6/active_v6= false \n"); + IPACM_Wan::wan_up_v6 = false; + active_v6 = false; + if(IPACM_Wan::wan_up) + { + IPACMDBG_H("modem v4-call still up(%s), not reset\n", IPACM_Wan::wan_up_dev_name); + } + else + { + memset(IPACM_Wan::wan_up_dev_name, 0, sizeof(IPACM_Wan::wan_up_dev_name)); + } + } + } + else + { + IPACMDBG_H(" The default WAN routing rules are deleted already \n"); + } + + return IPACM_SUCCESS; +} + +/* configure the initial embms filter rules */ +int IPACM_Wan::config_dft_embms_rules(ipa_ioc_add_flt_rule *pFilteringTable_v4, ipa_ioc_add_flt_rule *pFilteringTable_v6) +{ + struct ipa_flt_rule_add flt_rule_entry; + struct ipa_ioc_get_rt_tbl_indx rt_tbl_idx; + struct ipa_ioc_generate_flt_eq flt_eq; + + if (rx_prop == NULL) + { + IPACMDBG("No rx properties registered for iface %s\n", dev_name); + return IPACM_SUCCESS; + } + + if(pFilteringTable_v4 == NULL || pFilteringTable_v6 == NULL) + { + IPACMERR("Either v4 or v6 filtering table is empty.\n"); + return IPACM_FAILURE; + } + + /* set up ipv4 odu rule*/ + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); + + /* get eMBMS ODU tbl index*/ + memset(&rt_tbl_idx, 0, sizeof(rt_tbl_idx)); + strlcpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_odu_v4.name, IPA_RESOURCE_NAME_MAX); + rt_tbl_idx.name[IPA_RESOURCE_NAME_MAX-1] = '\0'; + rt_tbl_idx.ip = IPA_IP_v4; + if(0 != ioctl(m_fd_ipa, IPA_IOC_QUERY_RT_TBL_INDEX, &rt_tbl_idx)) + { + IPACMERR("Failed to get routing table index from name\n"); + return IPACM_FAILURE; + } + IPACMDBG_H("Odu routing table %s has index %d\n", rt_tbl_idx.name, rt_tbl_idx.idx); + + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); + flt_rule_entry.flt_rule_hdl = -1; + flt_rule_entry.status = -1; + flt_rule_entry.at_rear = false; + + flt_rule_entry.rule.retain_hdr = 0; + flt_rule_entry.rule.to_uc = 0; + flt_rule_entry.rule.eq_attrib_type = 1; + flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING; + flt_rule_entry.rule.rt_tbl_idx = rt_tbl_idx.idx; + + memcpy(&flt_rule_entry.rule.attrib, + &rx_prop->rx[0].attrib, + sizeof(struct ipa_rule_attrib)); + flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; + flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0x00000000; + flt_rule_entry.rule.attrib.u.v4.dst_addr = 0x00000000; + + memset(&flt_eq, 0, sizeof(flt_eq)); + memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib)); + flt_eq.ip = IPA_IP_v4; + if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq)) + { + IPACMERR("Failed to get eq_attrib\n"); + return IPACM_FAILURE; + } + memcpy(&flt_rule_entry.rule.eq_attrib, + &flt_eq.eq_attrib, + sizeof(flt_rule_entry.rule.eq_attrib)); + + memcpy(&(pFilteringTable_v4->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + + /* construc v6 rule */ + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); + /* get eMBMS ODU tbl*/ + memset(&rt_tbl_idx, 0, sizeof(rt_tbl_idx)); + strlcpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_odu_v6.name, IPA_RESOURCE_NAME_MAX); + rt_tbl_idx.name[IPA_RESOURCE_NAME_MAX-1] = '\0'; + rt_tbl_idx.ip = IPA_IP_v6; + if(0 != ioctl(m_fd_ipa, IPA_IOC_QUERY_RT_TBL_INDEX, &rt_tbl_idx)) + { + IPACMERR("Failed to get routing table index from name\n"); + return IPACM_FAILURE; + } + IPACMDBG_H("Odu routing table %s has index %d\n", rt_tbl_idx.name, rt_tbl_idx.idx); + + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); + flt_rule_entry.flt_rule_hdl = -1; + flt_rule_entry.status = -1; + flt_rule_entry.at_rear = false; + + flt_rule_entry.rule.retain_hdr = 0; + flt_rule_entry.rule.to_uc = 0; + flt_rule_entry.rule.eq_attrib_type = 1; + flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING; + flt_rule_entry.rule.rt_tbl_idx = rt_tbl_idx.idx; + + memcpy(&flt_rule_entry.rule.attrib, + &rx_prop->rx[0].attrib, + sizeof(struct ipa_rule_attrib)); + flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0x00000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[1] = 0x00000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = 0x00000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr[0] = 0X00000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = 0x00000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = 0x00000000; + flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X00000000; + + memset(&flt_eq, 0, sizeof(flt_eq)); + memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib)); + flt_eq.ip = IPA_IP_v6; + if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq)) + { + IPACMERR("Failed to get eq_attrib\n"); + return IPACM_FAILURE; + } + memcpy(&flt_rule_entry.rule.eq_attrib, + &flt_eq.eq_attrib, + sizeof(flt_rule_entry.rule.eq_attrib)); + + memcpy(&(pFilteringTable_v6->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + + return IPACM_SUCCESS; +} + + +/*for STA mode: handle wan-iface down event */ +int IPACM_Wan::handle_down_evt() +{ + int res = IPACM_SUCCESS; + int i; + + IPACMDBG_H(" wan handle_down_evt \n"); + + /* Delete corresponding ipa_rm_resource_name of TX-endpoint after delete IPV4/V6 RT-rule */ + IPACMDBG_H("dev %s add producer dependency\n", dev_name); + if (tx_prop != NULL) + { + IPACMDBG_H("depend Got pipe %d rm index : %d \n", tx_prop->tx[0].dst_pipe, IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe]); + IPACM_Iface::ipacmcfg->DelRmDepend(IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe]); + } + + /* no iface address up, directly close iface*/ + if (ip_type == IPACM_IP_NULL) + { + goto fail; + } + + /* make sure default routing rules and firewall rules are deleted*/ + if (active_v4) + { + if (rx_prop != NULL) + { + del_dft_firewall_rules(IPA_IP_v4); + } + handle_route_del_evt(IPA_IP_v4); + IPACMDBG_H("Delete default v4 routing rules\n"); + } + + if (active_v6) + { + if (rx_prop != NULL) + { + del_dft_firewall_rules(IPA_IP_v6); + } + handle_route_del_evt(IPA_IP_v6); + IPACMDBG_H("Delete default v6 routing rules\n"); + } + + /* Delete default v4 RT rule */ + if (ip_type != IPA_IP_v6) + { + IPACMDBG_H("Delete default v4 routing rules\n"); + if (m_routing.DeleteRoutingHdl(dft_rt_rule_hdl[0], IPA_IP_v4) == false) + { + IPACMERR("Routing rule deletion failed!\n"); + res = IPACM_FAILURE; + goto fail; + } + } + + /* delete default v6 RT rule */ + if (ip_type != IPA_IP_v4) + { + IPACMDBG_H("Delete default v6 routing rules\n"); + /* May have multiple ipv6 iface-routing rules*/ + for (i = 0; i < 2*num_dft_rt_v6; i++) + { + if (m_routing.DeleteRoutingHdl(dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES+i], IPA_IP_v6) == false) + { + IPACMERR("Routing rule deletion failed!\n"); + res = IPACM_FAILURE; + goto fail; + } + } + + IPACMDBG_H("finished delete default v6 RT rules\n "); + } + + + /* clean wan-client header, routing rules */ + IPACMDBG_H("left %d wan clients need to be deleted \n ", num_wan_client); + for (i = 0; i < num_wan_client; i++) + { + /* Del NAT rules before ipv4 RT rules are delete */ + if(get_client_memptr(wan_client, i)->ipv4_set == true) + { + IPACMDBG_H("Clean Nat Rules for ipv4:0x%x\n", get_client_memptr(wan_client, i)->v4_addr); + CtList->HandleSTAClientDelEvt(get_client_memptr(wan_client, i)->v4_addr); + } + + if (delete_wan_rtrules(i, IPA_IP_v4)) + { + IPACMERR("unbale to delete wan-client v4 route rules for index %d\n", i); + res = IPACM_FAILURE; + goto fail; + } + + if (delete_wan_rtrules(i, IPA_IP_v6)) + { + IPACMERR("unbale to delete ecm-client v6 route rules for index %d\n", i); + res = IPACM_FAILURE; + goto fail; + } + + IPACMDBG_H("Delete %d client header\n", num_wan_client); + + + if(get_client_memptr(wan_client, i)->ipv4_header_set == true) + { + if (m_header.DeleteHeaderHdl(get_client_memptr(wan_client, i)->hdr_hdl_v4) + == false) + { + res = IPACM_FAILURE; + goto fail; + } + } + + if(get_client_memptr(wan_client, i)->ipv6_header_set == true) + { + if (m_header.DeleteHeaderHdl(get_client_memptr(wan_client, i)->hdr_hdl_v6) + == false) + { + res = IPACM_FAILURE; + goto fail; + } + } + } /* end of for loop */ + + /* free the edm clients cache */ + IPACMDBG_H("Free wan clients cache\n"); + + /* check software routing fl rule hdl */ + if (softwarerouting_act == true) + { + handle_software_routing_disable(); + } + + /* free filter rule handlers */ + if (ip_type != IPA_IP_v6 && rx_prop != NULL) + { + if (m_filtering.DeleteFilteringHdls(dft_v4fl_rule_hdl, + IPA_IP_v4, + IPV4_DEFAULT_FILTERTING_RULES) == false) + { + IPACMERR("Error Delete Filtering rules, aborting...\n"); + res = IPACM_FAILURE; + goto fail; + } + IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, IPV4_DEFAULT_FILTERTING_RULES); + + IPACMDBG_H("finished delete default v4 filtering rules\n "); + } + + + if (ip_type != IPA_IP_v4 && rx_prop != NULL) + { + if (m_filtering.DeleteFilteringHdls(dft_v6fl_rule_hdl, + IPA_IP_v6, + IPV6_DEFAULT_FILTERTING_RULES) == false) + { + IPACMERR("ErrorDeleting Filtering rule, aborting...\n"); + res = IPACM_FAILURE; + goto fail; + } + IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, IPV6_DEFAULT_FILTERTING_RULES); + + if(num_ipv6_dest_flt_rule > 0 && num_ipv6_dest_flt_rule <= MAX_DEFAULT_v6_ROUTE_RULES) + { + if(m_filtering.DeleteFilteringHdls(ipv6_dest_flt_rule_hdl, IPA_IP_v6, num_ipv6_dest_flt_rule) == false) + { + IPACMERR("Failed to delete ipv6 dest flt rules.\n"); + res = IPACM_FAILURE; + goto fail; + } + IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, num_ipv6_dest_flt_rule); + } + IPACMDBG_H("finished delete default v6 filtering rules\n "); + } + +fail: + if (tx_prop != NULL) + { + free(tx_prop); + } + if (rx_prop != NULL) + { + free(rx_prop); + } + if (iface_query != NULL) + { + free(iface_query); + } + if (wan_route_rule_v4_hdl != NULL) + { + free(wan_route_rule_v4_hdl); + } + if (wan_route_rule_v6_hdl != NULL) + { + free(wan_route_rule_v6_hdl); + } + if (wan_route_rule_v6_hdl_a5 != NULL) + { + free(wan_route_rule_v6_hdl_a5); + } + if (wan_client != NULL) + { + free(wan_client); + } + close(m_fd_ipa); + return res; +} + +int IPACM_Wan::handle_down_evt_ex() +{ + int res = IPACM_SUCCESS; + int i, tether_total; + int ipa_if_num_tether_tmp[IPA_MAX_IFACE_ENTRIES]; + + IPACMDBG_H(" wan handle_down_evt \n"); + + /* free ODU filter rule handlers */ + if(IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat == EMBMS_IF) + { + embms_is_on = false; + /* Delete corresponding ipa_rm_resource_name of TX-endpoint after delete IPV4/V6 RT-rule */ + IPACMDBG_H("dev %s add producer dependency\n", dev_name); + if (tx_prop != NULL) + { + IPACMDBG_H("depend Got pipe %d rm index : %d \n", tx_prop->tx[0].dst_pipe, IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe]); + IPACM_Iface::ipacmcfg->DelRmDepend(IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe]); + } + + if (rx_prop != NULL) + { + install_wan_filtering_rule(false); + IPACMDBG("finished delete embms filtering rule\n "); + } + goto fail; + } + + /* no iface address up, directly close iface*/ + if (ip_type == IPACM_IP_NULL) + { + goto fail; + } + + if(ip_type == IPA_IP_v4) + { + num_ipv4_modem_pdn--; + IPACMDBG_H("Now the number of ipv4 modem pdn is %d.\n", num_ipv4_modem_pdn); + /* only when default gw goes down we post WAN_DOWN event*/ + if(is_default_gateway == true) + { + IPACM_Wan::wan_up = false; + del_wan_firewall_rule(IPA_IP_v4); + install_wan_filtering_rule(false); + handle_route_del_evt_ex(IPA_IP_v4); +#ifdef FEATURE_IPA_ANDROID + /* posting wan_down_tether for all lan clients */ + for (i=0; i < IPACM_Wan::ipa_if_num_tether_v4_total; i++) + { + ipa_if_num_tether_tmp[i] = IPACM_Wan::ipa_if_num_tether_v4[i]; + } + tether_total = IPACM_Wan::ipa_if_num_tether_v4_total; + for (i=0; i < tether_total; i++) + { + post_wan_down_tether_evt(IPA_IP_v4, ipa_if_num_tether_tmp[i]); + IPACMDBG_H("post_wan_down_tether_v4 iface(%d: %s)\n", + i, IPACM_Iface::ipacmcfg->iface_table[ipa_if_num_tether_tmp[i]].iface_name); + } +#endif + if(IPACM_Wan::wan_up_v6) + { + IPACMDBG_H("modem v6-call still up(%s), not reset\n", IPACM_Wan::wan_up_dev_name); + } + else + { + memset(IPACM_Wan::wan_up_dev_name, 0, sizeof(IPACM_Wan::wan_up_dev_name)); + } + } + + /* only when the last ipv4 modem interface goes down, delete ipv4 default flt rules*/ + if(num_ipv4_modem_pdn == 0) + { + IPACMDBG_H("Now the number of modem ipv4 interface is 0, delete default flt rules.\n"); + IPACM_Wan::num_v4_flt_rule = 0; + memset(IPACM_Wan::flt_rule_v4, 0, IPA_MAX_FLT_RULE * sizeof(struct ipa_flt_rule_add)); + install_wan_filtering_rule(false); + } + + if (m_routing.DeleteRoutingHdl(dft_rt_rule_hdl[0], IPA_IP_v4) == false) + { + IPACMERR("Routing rule deletion failed!\n"); + res = IPACM_FAILURE; + goto fail; + } + } + else if(ip_type == IPA_IP_v6) + { + if (num_dft_rt_v6 > 1) + num_ipv6_modem_pdn--; + IPACMDBG_H("Now the number of ipv6 modem pdn is %d.\n", num_ipv6_modem_pdn); + /* only when default gw goes down we post WAN_DOWN event*/ + if(is_default_gateway == true) + { + IPACM_Wan::wan_up_v6 = false; + del_wan_firewall_rule(IPA_IP_v6); + install_wan_filtering_rule(false); + handle_route_del_evt_ex(IPA_IP_v6); +#ifdef FEATURE_IPA_ANDROID //sky + /* posting wan_down_tether for all lan clients */ + for (i=0; i < IPACM_Wan::ipa_if_num_tether_v6_total; i++) + { + ipa_if_num_tether_tmp[i] = IPACM_Wan::ipa_if_num_tether_v6[i]; + } + tether_total = IPACM_Wan::ipa_if_num_tether_v6_total; + for (i=0; i < tether_total; i++) + { + post_wan_down_tether_evt(IPA_IP_v6, ipa_if_num_tether_tmp[i]); + IPACMDBG_H("post_wan_down_tether_v6 iface(%d: %s)\n", + i, IPACM_Iface::ipacmcfg->iface_table[ipa_if_num_tether_tmp[i]].iface_name); + } +#endif + if(IPACM_Wan::wan_up) + { + IPACMDBG_H("modem v4-call still up(%s), not reset\n", IPACM_Wan::wan_up_dev_name); + } + else + { + memset(IPACM_Wan::wan_up_dev_name, 0, sizeof(IPACM_Wan::wan_up_dev_name)); + } + } + + /* only when the last ipv6 modem interface goes down, delete ipv6 default flt rules*/ + if(num_ipv6_modem_pdn == 0) + { + IPACMDBG_H("Now the number of modem ipv6 interface is 0, delete default flt rules.\n"); + IPACM_Wan::num_v6_flt_rule = 0; + memset(IPACM_Wan::flt_rule_v6, 0, IPA_MAX_FLT_RULE * sizeof(struct ipa_flt_rule_add)); + install_wan_filtering_rule(false); + } + + for (i = 0; i < 2*num_dft_rt_v6; i++) + { + if (m_routing.DeleteRoutingHdl(dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES+i], IPA_IP_v6) == false) + { + IPACMERR("Routing rule deletion failed!\n"); + res = IPACM_FAILURE; + goto fail; + } + } + } + else + { + num_ipv4_modem_pdn--; + IPACMDBG_H("Now the number of ipv4 modem pdn is %d.\n", num_ipv4_modem_pdn); + if (num_dft_rt_v6 > 1) + num_ipv6_modem_pdn--; + IPACMDBG_H("Now the number of ipv6 modem pdn is %d.\n", num_ipv6_modem_pdn); + /* only when default gw goes down we post WAN_DOWN event*/ + if(is_default_gateway == true) + { + IPACM_Wan::wan_up = false; + del_wan_firewall_rule(IPA_IP_v4); + handle_route_del_evt_ex(IPA_IP_v4); +#ifdef FEATURE_IPA_ANDROID + /* posting wan_down_tether for all lan clients */ + for (i=0; i < IPACM_Wan::ipa_if_num_tether_v4_total; i++) + { + ipa_if_num_tether_tmp[i] = IPACM_Wan::ipa_if_num_tether_v4[i]; + } + tether_total = IPACM_Wan::ipa_if_num_tether_v4_total; + for (i=0; i < tether_total; i++) + { + post_wan_down_tether_evt(IPA_IP_v4, ipa_if_num_tether_tmp[i]); + IPACMDBG_H("post_wan_down_tether_v4 iface(%d: %s)\n", + i, IPACM_Iface::ipacmcfg->iface_table[ipa_if_num_tether_tmp[i]].iface_name); + } +#endif + IPACM_Wan::wan_up_v6 = false; + del_wan_firewall_rule(IPA_IP_v6); + handle_route_del_evt_ex(IPA_IP_v6); +#ifdef FEATURE_IPA_ANDROID + /* posting wan_down_tether for all lan clients */ + for (i=0; i < IPACM_Wan::ipa_if_num_tether_v6_total; i++) + { + ipa_if_num_tether_tmp[i] = IPACM_Wan::ipa_if_num_tether_v6[i]; + } + tether_total = IPACM_Wan::ipa_if_num_tether_v6_total; + for (i=0; i < tether_total; i++) + { + post_wan_down_tether_evt(IPA_IP_v6, ipa_if_num_tether_tmp[i]); + IPACMDBG_H("post_wan_down_tether_v6 iface(%d: %s)\n", + i, IPACM_Iface::ipacmcfg->iface_table[ipa_if_num_tether_tmp[i]].iface_name); + } +#endif + memset(IPACM_Wan::wan_up_dev_name, 0, sizeof(IPACM_Wan::wan_up_dev_name)); + + install_wan_filtering_rule(false); + } + + /* only when the last ipv4 modem interface goes down, delete ipv4 default flt rules*/ + if(num_ipv4_modem_pdn == 0) + { + IPACMDBG_H("Now the number of modem ipv4 interface is 0, delete default flt rules.\n"); + IPACM_Wan::num_v4_flt_rule = 0; + memset(IPACM_Wan::flt_rule_v4, 0, IPA_MAX_FLT_RULE * sizeof(struct ipa_flt_rule_add)); + install_wan_filtering_rule(false); + } + /* only when the last ipv6 modem interface goes down, delete ipv6 default flt rules*/ + if(num_ipv6_modem_pdn == 0) + { + IPACMDBG_H("Now the number of modem ipv6 interface is 0, delete default flt rules.\n"); + IPACM_Wan::num_v6_flt_rule = 0; + memset(IPACM_Wan::flt_rule_v6, 0, IPA_MAX_FLT_RULE * sizeof(struct ipa_flt_rule_add)); + install_wan_filtering_rule(false); + } + + if (m_routing.DeleteRoutingHdl(dft_rt_rule_hdl[0], IPA_IP_v4) == false) + { + IPACMERR("Routing rule deletion failed!\n"); + res = IPACM_FAILURE; + goto fail; + } + + for (i = 0; i < 2*num_dft_rt_v6; i++) + { + if (m_routing.DeleteRoutingHdl(dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES+i], IPA_IP_v6) == false) + { + IPACMERR("Routing rule deletion failed!\n"); + res = IPACM_FAILURE; + goto fail; + } + } + } + + /* check software routing fl rule hdl */ + if (softwarerouting_act == true) + { + handle_software_routing_disable(); + } + +fail: + if (tx_prop != NULL) + { + free(tx_prop); + } + if (rx_prop != NULL) + { + free(rx_prop); + } + if (ext_prop != NULL) + { + free(ext_prop); + } + if (iface_query != NULL) + { + free(iface_query); + } + if (wan_route_rule_v4_hdl != NULL) + { + free(wan_route_rule_v4_hdl); + } + if (wan_route_rule_v6_hdl != NULL) + { + free(wan_route_rule_v6_hdl); + } + if (wan_route_rule_v6_hdl_a5 != NULL) + { + free(wan_route_rule_v6_hdl_a5); + } + if (wan_client != NULL) + { + free(wan_client); + } + close(m_fd_ipa); + return res; +} + +int IPACM_Wan::install_wan_filtering_rule(bool is_sw_routing) +{ + int len, res = IPACM_SUCCESS; + uint8_t mux_id; + ipa_ioc_add_flt_rule *pFilteringTable_v4 = NULL; + ipa_ioc_add_flt_rule *pFilteringTable_v6 = NULL; + + mux_id = IPACM_Iface::ipacmcfg->GetQmapId(); + if(rx_prop == NULL) + { + IPACMDBG_H("No rx properties registered for iface %s\n", dev_name); + return IPACM_SUCCESS; + } + if (is_sw_routing == true || + IPACM_Iface::ipacmcfg->ipa_sw_rt_enable == true) + { + /* contruct SW-RT rules to Q6*/ + struct ipa_flt_rule_add flt_rule_entry; + struct ipa_ioc_get_rt_tbl_indx rt_tbl_idx; + ipa_ioc_generate_flt_eq flt_eq; + + IPACMDBG("\n"); + if (softwarerouting_act == true) + { + IPACMDBG("already setup software_routing rule for (%s)iface ip-family %d\n", + IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].iface_name, ip_type); + return IPACM_SUCCESS; + } + + len = sizeof(struct ipa_ioc_add_flt_rule) + sizeof(struct ipa_flt_rule_add); + pFilteringTable_v4 = (struct ipa_ioc_add_flt_rule*)malloc(len); + if (pFilteringTable_v4 == NULL) + { + IPACMERR("Error Locate ipa_flt_rule_add memory...\n"); + return IPACM_FAILURE; + } + memset(pFilteringTable_v4, 0, len); + IPACMDBG_H("Total number of WAN DL filtering rule for IPv4 is 1\n"); + + pFilteringTable_v4->commit = 1; + pFilteringTable_v4->ep = rx_prop->rx[0].src_pipe; + pFilteringTable_v4->global = false; + pFilteringTable_v4->ip = IPA_IP_v4; + pFilteringTable_v4->num_rules = (uint8_t)1; + + /* Configuring Software-Routing Filtering Rule */ + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); + memset(&rt_tbl_idx, 0, sizeof(rt_tbl_idx)); + strlcpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_dl.name, IPA_RESOURCE_NAME_MAX); + rt_tbl_idx.name[IPA_RESOURCE_NAME_MAX-1] = '\0'; + rt_tbl_idx.ip = IPA_IP_v4; + if(ioctl(m_fd_ipa, IPA_IOC_QUERY_RT_TBL_INDEX, &rt_tbl_idx) < 0) + { + IPACMERR("Failed to get routing table index from name\n"); + res = IPACM_FAILURE; + goto fail; + } + IPACMDBG_H("Routing table %s has index %d\n", rt_tbl_idx.name, rt_tbl_idx.idx); + + flt_rule_entry.at_rear = false; + flt_rule_entry.flt_rule_hdl = -1; + flt_rule_entry.status = -1; + flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING; + flt_rule_entry.rule.rt_tbl_idx = rt_tbl_idx.idx; + + memcpy(&flt_rule_entry.rule.attrib, + &rx_prop->rx[0].attrib, + sizeof(flt_rule_entry.rule.attrib)); + flt_rule_entry.rule.retain_hdr = 0; + flt_rule_entry.rule.to_uc = 0; + flt_rule_entry.rule.eq_attrib_type = 1; + + memset(&flt_eq, 0, sizeof(flt_eq)); + memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib)); + flt_eq.ip = IPA_IP_v4; + if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq)) + { + IPACMERR("Failed to get eq_attrib\n"); + res = IPACM_FAILURE; + goto fail; + } + memcpy(&flt_rule_entry.rule.eq_attrib, + &flt_eq.eq_attrib, + sizeof(flt_rule_entry.rule.eq_attrib)); + memcpy(&(pFilteringTable_v4->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + + len = sizeof(struct ipa_ioc_add_flt_rule) + sizeof(struct ipa_flt_rule_add); + pFilteringTable_v6 = (struct ipa_ioc_add_flt_rule*)malloc(len); + if (pFilteringTable_v6 == NULL) + { + IPACMERR("Error Locate ipa_flt_rule_add memory...\n"); + free(pFilteringTable_v4); + return IPACM_FAILURE; + } + memset(pFilteringTable_v6, 0, len); + IPACMDBG_H("Total number of WAN DL filtering rule for IPv6 is 1\n"); + + pFilteringTable_v6->commit = 1; + pFilteringTable_v6->ep = rx_prop->rx[0].src_pipe; + pFilteringTable_v6->global = false; + pFilteringTable_v6->ip = IPA_IP_v6; + pFilteringTable_v6->num_rules = (uint8_t)1; + + /* Configuring Software-Routing Filtering Rule */ + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); + memset(&rt_tbl_idx, 0, sizeof(rt_tbl_idx)); + strlcpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_dl.name, IPA_RESOURCE_NAME_MAX); + rt_tbl_idx.name[IPA_RESOURCE_NAME_MAX-1] = '\0'; + rt_tbl_idx.ip = IPA_IP_v6; + if(ioctl(m_fd_ipa, IPA_IOC_QUERY_RT_TBL_INDEX, &rt_tbl_idx) < 0) + { + IPACMERR("Failed to get routing table index from name\n"); + res = IPACM_FAILURE; + goto fail; + } + IPACMDBG_H("Routing table %s has index %d\n", rt_tbl_idx.name, rt_tbl_idx.idx); + + flt_rule_entry.at_rear = false; + flt_rule_entry.flt_rule_hdl = -1; + flt_rule_entry.status = -1; + flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING; + flt_rule_entry.rule.rt_tbl_idx = rt_tbl_idx.idx; + memcpy(&flt_rule_entry.rule.attrib, + &rx_prop->rx[0].attrib, + sizeof(flt_rule_entry.rule.attrib)); + flt_rule_entry.rule.retain_hdr = 0; + flt_rule_entry.rule.to_uc = 0; + flt_rule_entry.rule.eq_attrib_type = 1; + + memset(&flt_eq, 0, sizeof(flt_eq)); + memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib)); + flt_eq.ip = IPA_IP_v6; + if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq)) + { + IPACMERR("Failed to get eq_attrib\n"); + res = IPACM_FAILURE; + goto fail; + } + memcpy(&flt_rule_entry.rule.eq_attrib, + &flt_eq.eq_attrib, + sizeof(flt_rule_entry.rule.eq_attrib)); + memcpy(&(pFilteringTable_v6->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + softwarerouting_act = true; + /* end of contruct SW-RT rules to Q6*/ + } + else + { + if(embms_is_on == false) + { + if(IPACM_Wan::num_v4_flt_rule > 0) + { + len = sizeof(struct ipa_ioc_add_flt_rule) + IPACM_Wan::num_v4_flt_rule * sizeof(struct ipa_flt_rule_add); + pFilteringTable_v4 = (struct ipa_ioc_add_flt_rule*)malloc(len); + + IPACMDBG_H("Total number of WAN DL filtering rule for IPv4 is %d\n", IPACM_Wan::num_v4_flt_rule); + + if (pFilteringTable_v4 == NULL) + { + IPACMERR("Error Locate ipa_flt_rule_add memory...\n"); + return IPACM_FAILURE; + } + memset(pFilteringTable_v4, 0, len); + pFilteringTable_v4->commit = 1; + pFilteringTable_v4->ep = rx_prop->rx[0].src_pipe; + pFilteringTable_v4->global = false; + pFilteringTable_v4->ip = IPA_IP_v4; + pFilteringTable_v4->num_rules = (uint8_t)IPACM_Wan::num_v4_flt_rule; + + memcpy(pFilteringTable_v4->rules, IPACM_Wan::flt_rule_v4, IPACM_Wan::num_v4_flt_rule * sizeof(ipa_flt_rule_add)); + } + + if(IPACM_Wan::num_v6_flt_rule > 0) + { + len = sizeof(struct ipa_ioc_add_flt_rule) + IPACM_Wan::num_v6_flt_rule * sizeof(struct ipa_flt_rule_add); + pFilteringTable_v6 = (struct ipa_ioc_add_flt_rule*)malloc(len); + + IPACMDBG_H("Total number of WAN DL filtering rule for IPv6 is %d\n", IPACM_Wan::num_v6_flt_rule); + + if (pFilteringTable_v6 == NULL) + { + IPACMERR("Error Locate ipa_flt_rule_add memory...\n"); + free(pFilteringTable_v4); + return IPACM_FAILURE; + } + memset(pFilteringTable_v6, 0, len); + pFilteringTable_v6->commit = 1; + pFilteringTable_v6->ep = rx_prop->rx[0].src_pipe; + pFilteringTable_v6->global = false; + pFilteringTable_v6->ip = IPA_IP_v6; + pFilteringTable_v6->num_rules = (uint8_t)IPACM_Wan::num_v6_flt_rule; + + memcpy(pFilteringTable_v6->rules, IPACM_Wan::flt_rule_v6, IPACM_Wan::num_v6_flt_rule * sizeof(ipa_flt_rule_add)); + } + } + else //embms is on, always add 1 embms rule on top of WAN DL flt table + { + /* allocate ipv4 filtering table */ + len = sizeof(struct ipa_ioc_add_flt_rule) + (1 + IPACM_Wan::num_v4_flt_rule) * sizeof(struct ipa_flt_rule_add); + pFilteringTable_v4 = (struct ipa_ioc_add_flt_rule*)malloc(len); + IPACMDBG_H("Total number of WAN DL filtering rule for IPv4 is %d\n", IPACM_Wan::num_v4_flt_rule + 1); + if (pFilteringTable_v4 == NULL) + { + IPACMERR("Error Locate ipa_flt_rule_add memory...\n"); + return IPACM_FAILURE; + } + memset(pFilteringTable_v4, 0, len); + pFilteringTable_v4->commit = 1; + pFilteringTable_v4->ep = rx_prop->rx[0].src_pipe; + pFilteringTable_v4->global = false; + pFilteringTable_v4->ip = IPA_IP_v4; + pFilteringTable_v4->num_rules = (uint8_t)IPACM_Wan::num_v4_flt_rule + 1; + + /* allocate ipv6 filtering table */ + len = sizeof(struct ipa_ioc_add_flt_rule) + (1 + IPACM_Wan::num_v6_flt_rule) * sizeof(struct ipa_flt_rule_add); + pFilteringTable_v6 = (struct ipa_ioc_add_flt_rule*)malloc(len); + IPACMDBG_H("Total number of WAN DL filtering rule for IPv6 is %d\n", IPACM_Wan::num_v6_flt_rule + 1); + if (pFilteringTable_v6 == NULL) + { + IPACMERR("Error Locate ipa_flt_rule_add memory...\n"); + free(pFilteringTable_v4); + return IPACM_FAILURE; + } + memset(pFilteringTable_v6, 0, len); + pFilteringTable_v6->commit = 1; + pFilteringTable_v6->ep = rx_prop->rx[0].src_pipe; + pFilteringTable_v6->global = false; + pFilteringTable_v6->ip = IPA_IP_v6; + pFilteringTable_v6->num_rules = (uint8_t)IPACM_Wan::num_v6_flt_rule + 1; + + config_dft_embms_rules(pFilteringTable_v4, pFilteringTable_v6); + if(IPACM_Wan::num_v4_flt_rule > 0) + { + memcpy(&(pFilteringTable_v4->rules[1]), IPACM_Wan::flt_rule_v4, IPACM_Wan::num_v4_flt_rule * sizeof(ipa_flt_rule_add)); + } + + if(IPACM_Wan::num_v6_flt_rule > 0) + { + memcpy(&(pFilteringTable_v6->rules[1]), IPACM_Wan::flt_rule_v6, IPACM_Wan::num_v6_flt_rule * sizeof(ipa_flt_rule_add)); + } + } + } + + if(false == m_filtering.AddWanDLFilteringRule(pFilteringTable_v4, pFilteringTable_v6, mux_id)) + { + IPACMERR("Failed to install WAN DL filtering table.\n"); + res = IPACM_FAILURE; + goto fail; + } + +fail: + if(pFilteringTable_v4 != NULL) + { + free(pFilteringTable_v4); + } + if(pFilteringTable_v6 != NULL) + { + free(pFilteringTable_v6); + } + return res; +} + +void IPACM_Wan::change_to_network_order(ipa_ip_type iptype, ipa_rule_attrib* attrib) +{ + if(attrib == NULL) + { + IPACMERR("Attribute pointer is NULL.\n"); + return; + } + + if(iptype == IPA_IP_v6) + { + int i; + for(i=0; i<4; i++) + { + attrib->u.v6.src_addr[i] = htonl(attrib->u.v6.src_addr[i]); + attrib->u.v6.src_addr_mask[i] = htonl(attrib->u.v6.src_addr_mask[i]); + attrib->u.v6.dst_addr[i] = htonl(attrib->u.v6.dst_addr[i]); + attrib->u.v6.dst_addr_mask[i] = htonl(attrib->u.v6.dst_addr_mask[i]); + } + } + else + { + IPACMDBG_H("IP type is not IPv6, do nothing: %d\n", iptype); + } + + return; +} + +bool IPACM_Wan::is_global_ipv6_addr(uint32_t* ipv6_addr) +{ + if(ipv6_addr == NULL) + { + IPACMERR("IPv6 address is empty.\n"); + return false; + } + IPACMDBG_H("Get ipv6 address with first word 0x%08x.\n", ipv6_addr[0]); + + uint32_t ipv6_link_local_prefix, ipv6_link_local_prefix_mask; + ipv6_link_local_prefix = 0xFE800000; + ipv6_link_local_prefix_mask = 0xFFC00000; + if((ipv6_addr[0] & ipv6_link_local_prefix_mask) == (ipv6_link_local_prefix & ipv6_link_local_prefix_mask)) + { + IPACMDBG_H("This IPv6 address is link local.\n"); + return false; + } + else + { + IPACMDBG_H("This IPv6 address is not link local.\n"); + return true; + } +} + +/* handle STA WAN-client */ +/* handle WAN client initial, construct full headers (tx property) */ +int IPACM_Wan::handle_wan_hdr_init(uint8_t *mac_addr) +{ + +#define WAN_IFACE_INDEX_LEN 2 + + int res = IPACM_SUCCESS, len = 0; + char index[WAN_IFACE_INDEX_LEN]; + struct ipa_ioc_copy_hdr sCopyHeader; + struct ipa_ioc_add_hdr *pHeaderDescriptor = NULL; + uint32_t cnt; + int clnt_indx; + + clnt_indx = get_wan_client_index(mac_addr); + + if (clnt_indx != IPACM_INVALID_INDEX) + { + IPACMERR("eth client is found/attached already with index %d \n", clnt_indx); + return IPACM_FAILURE; + } + + /* add header to IPA */ + if (num_wan_client >= IPA_MAX_NUM_WAN_CLIENTS) + { + IPACMERR("Reached maximum number(%d) of eth clients\n", IPA_MAX_NUM_WAN_CLIENTS); + return IPACM_FAILURE; + } + + IPACMDBG_H("WAN client number: %d\n", num_wan_client); + + memcpy(get_client_memptr(wan_client, num_wan_client)->mac, + mac_addr, + sizeof(get_client_memptr(wan_client, num_wan_client)->mac)); + + + IPACMDBG_H("Received Client MAC %02x:%02x:%02x:%02x:%02x:%02x\n", + mac_addr[0], mac_addr[1], mac_addr[2], + mac_addr[3], mac_addr[4], mac_addr[5]); + + IPACMDBG_H("stored MAC %02x:%02x:%02x:%02x:%02x:%02x\n", + get_client_memptr(wan_client, num_wan_client)->mac[0], + get_client_memptr(wan_client, num_wan_client)->mac[1], + get_client_memptr(wan_client, num_wan_client)->mac[2], + get_client_memptr(wan_client, num_wan_client)->mac[3], + get_client_memptr(wan_client, num_wan_client)->mac[4], + get_client_memptr(wan_client, num_wan_client)->mac[5]); + + /* add header to IPA */ + if(tx_prop != NULL) + { + len = sizeof(struct ipa_ioc_add_hdr) + (1 * sizeof(struct ipa_hdr_add)); + pHeaderDescriptor = (struct ipa_ioc_add_hdr *)calloc(1, len); + if (pHeaderDescriptor == NULL) + { + IPACMERR("calloc failed to allocate pHeaderDescriptor\n"); + return IPACM_FAILURE; + } + + /* copy partial header for v4*/ + for (cnt=0; cntnum_tx_props; cnt++) + { + if(tx_prop->tx[cnt].ip==IPA_IP_v4) + { + IPACMDBG_H("Got partial v4-header name from %d tx props\n", cnt); + memset(&sCopyHeader, 0, sizeof(sCopyHeader)); + memcpy(sCopyHeader.name, + tx_prop->tx[cnt].hdr_name, + sizeof(sCopyHeader.name)); + + IPACMDBG_H("header name: %s in tx:%d\n", sCopyHeader.name,cnt); + if (m_header.CopyHeader(&sCopyHeader) == false) + { + PERROR("ioctl copy header failed"); + res = IPACM_FAILURE; + goto fail; + } + + IPACMDBG_H("header length: %d, paritial: %d\n", sCopyHeader.hdr_len, sCopyHeader.is_partial); + IPACMDBG_H("header eth2_ofst_valid: %d, eth2_ofst: %d\n", sCopyHeader.is_eth2_ofst_valid, sCopyHeader.eth2_ofst); + if (sCopyHeader.hdr_len > IPA_HDR_MAX_SIZE) + { + IPACMERR("header oversize\n"); + res = IPACM_FAILURE; + goto fail; + } + else + { + memcpy(pHeaderDescriptor->hdr[0].hdr, + sCopyHeader.hdr, + sCopyHeader.hdr_len); + } + + /* copy client mac_addr to partial header */ + IPACMDBG_H("header eth2_ofst_valid: %d, eth2_ofst: %d\n", + sCopyHeader.is_eth2_ofst_valid, sCopyHeader.eth2_ofst); + + /* only copy 6 bytes mac-address */ + if(sCopyHeader.is_eth2_ofst_valid == false) + { + memcpy(&pHeaderDescriptor->hdr[0].hdr[0], + mac_addr, IPA_MAC_ADDR_SIZE); + } + else + { + memcpy(&pHeaderDescriptor->hdr[0].hdr[sCopyHeader.eth2_ofst], + mac_addr, IPA_MAC_ADDR_SIZE); + } + + + pHeaderDescriptor->commit = true; + pHeaderDescriptor->num_hdrs = 1; + + memset(pHeaderDescriptor->hdr[0].name, 0, + sizeof(pHeaderDescriptor->hdr[0].name)); + + snprintf(index,sizeof(index), "%d", ipa_if_num); + strlcpy(pHeaderDescriptor->hdr[0].name, index, sizeof(pHeaderDescriptor->hdr[0].name)); + pHeaderDescriptor->hdr[0].name[IPA_RESOURCE_NAME_MAX-1] = '\0'; + if (strlcat(pHeaderDescriptor->hdr[0].name, IPA_WAN_PARTIAL_HDR_NAME_v4, sizeof(pHeaderDescriptor->hdr[0].name)) > IPA_RESOURCE_NAME_MAX) + { + IPACMERR(" header name construction failed exceed length (%d)\n", strlen(pHeaderDescriptor->hdr[0].name)); + res = IPACM_FAILURE; + goto fail; + } + + snprintf(index,sizeof(index), "%d", header_name_count); + if (strlcat(pHeaderDescriptor->hdr[0].name, index, sizeof(pHeaderDescriptor->hdr[0].name)) > IPA_RESOURCE_NAME_MAX) + { + IPACMERR(" header name construction failed exceed length (%d)\n", strlen(pHeaderDescriptor->hdr[0].name)); + res = IPACM_FAILURE; + goto fail; + } + + pHeaderDescriptor->hdr[0].hdr_len = sCopyHeader.hdr_len; + pHeaderDescriptor->hdr[0].hdr_hdl = -1; + pHeaderDescriptor->hdr[0].is_partial = 0; + pHeaderDescriptor->hdr[0].status = -1; + + if (m_header.AddHeader(pHeaderDescriptor) == false || + pHeaderDescriptor->hdr[0].status != 0) + { + IPACMERR("ioctl IPA_IOC_ADD_HDR failed: %d\n", pHeaderDescriptor->hdr[0].status); + res = IPACM_FAILURE; + goto fail; + } + + get_client_memptr(wan_client, num_wan_client)->hdr_hdl_v4 = pHeaderDescriptor->hdr[0].hdr_hdl; + IPACMDBG_H("eth-client(%d) v4 full header name:%s header handle:(0x%x)\n", + num_wan_client, + pHeaderDescriptor->hdr[0].name, + get_client_memptr(wan_client, num_wan_client)->hdr_hdl_v4); + get_client_memptr(wan_client, num_wan_client)->ipv4_header_set=true; + + break; + } + } + + + /* copy partial header for v6*/ + for (cnt=0; cntnum_tx_props; cnt++) + { + if(tx_prop->tx[cnt].ip==IPA_IP_v6) + { + + IPACMDBG_H("Got partial v6-header name from %d tx props\n", cnt); + memset(&sCopyHeader, 0, sizeof(sCopyHeader)); + memcpy(sCopyHeader.name, + tx_prop->tx[cnt].hdr_name, + sizeof(sCopyHeader.name)); + + IPACMDBG_H("header name: %s in tx:%d\n", sCopyHeader.name,cnt); + if (m_header.CopyHeader(&sCopyHeader) == false) + { + PERROR("ioctl copy header failed"); + res = IPACM_FAILURE; + goto fail; + } + + IPACMDBG_H("header length: %d, paritial: %d\n", sCopyHeader.hdr_len, sCopyHeader.is_partial); + IPACMDBG_H("header eth2_ofst_valid: %d, eth2_ofst: %d\n", sCopyHeader.is_eth2_ofst_valid, sCopyHeader.eth2_ofst); + if (sCopyHeader.hdr_len > IPA_HDR_MAX_SIZE) + { + IPACMERR("header oversize\n"); + res = IPACM_FAILURE; + goto fail; + } + else + { + memcpy(pHeaderDescriptor->hdr[0].hdr, + sCopyHeader.hdr, + sCopyHeader.hdr_len); + } + + /* copy client mac_addr to partial header */ + if(sCopyHeader.is_eth2_ofst_valid == false) + { + memcpy(&pHeaderDescriptor->hdr[0].hdr[0], + mac_addr, IPA_MAC_ADDR_SIZE); /* only copy 6 bytes mac-address */ + } + else + { + memcpy(&pHeaderDescriptor->hdr[0].hdr[sCopyHeader.eth2_ofst], + mac_addr, IPA_MAC_ADDR_SIZE); /* only copy 6 bytes mac-address */ + } + + + pHeaderDescriptor->commit = true; + pHeaderDescriptor->num_hdrs = 1; + + memset(pHeaderDescriptor->hdr[0].name, 0, + sizeof(pHeaderDescriptor->hdr[0].name)); + + snprintf(index,sizeof(index), "%d", ipa_if_num); + strlcpy(pHeaderDescriptor->hdr[0].name, index, sizeof(pHeaderDescriptor->hdr[0].name)); + pHeaderDescriptor->hdr[0].name[IPA_RESOURCE_NAME_MAX-1] = '\0'; + if (strlcat(pHeaderDescriptor->hdr[0].name, IPA_WAN_PARTIAL_HDR_NAME_v6, sizeof(pHeaderDescriptor->hdr[0].name)) > IPA_RESOURCE_NAME_MAX) + { + IPACMERR(" header name construction failed exceed length (%d)\n", strlen(pHeaderDescriptor->hdr[0].name)); + res = IPACM_FAILURE; + goto fail; + } + snprintf(index,sizeof(index), "%d", header_name_count); + if (strlcat(pHeaderDescriptor->hdr[0].name, index, sizeof(pHeaderDescriptor->hdr[0].name)) > IPA_RESOURCE_NAME_MAX) + { + IPACMERR(" header name construction failed exceed length (%d)\n", strlen(pHeaderDescriptor->hdr[0].name)); + res = IPACM_FAILURE; + goto fail; + } + + pHeaderDescriptor->hdr[0].hdr_len = sCopyHeader.hdr_len; + pHeaderDescriptor->hdr[0].hdr_hdl = -1; + pHeaderDescriptor->hdr[0].is_partial = 0; + pHeaderDescriptor->hdr[0].status = -1; + + if (m_header.AddHeader(pHeaderDescriptor) == false || + pHeaderDescriptor->hdr[0].status != 0) + { + IPACMERR("ioctl IPA_IOC_ADD_HDR failed: %d\n", pHeaderDescriptor->hdr[0].status); + res = IPACM_FAILURE; + goto fail; + } + + get_client_memptr(wan_client, num_wan_client)->hdr_hdl_v6 = pHeaderDescriptor->hdr[0].hdr_hdl; + IPACMDBG_H("eth-client(%d) v6 full header name:%s header handle:(0x%x)\n", + num_wan_client, + pHeaderDescriptor->hdr[0].name, + get_client_memptr(wan_client, num_wan_client)->hdr_hdl_v6); + + get_client_memptr(wan_client, num_wan_client)->ipv6_header_set=true; + + break; + + } + } + /* initialize wifi client*/ + get_client_memptr(wan_client, num_wan_client)->route_rule_set_v4 = false; + get_client_memptr(wan_client, num_wan_client)->route_rule_set_v6 = 0; + get_client_memptr(wan_client, num_wan_client)->ipv4_set = false; + get_client_memptr(wan_client, num_wan_client)->ipv6_set = 0; + num_wan_client++; + header_name_count++; //keep increasing header_name_count + res = IPACM_SUCCESS; + IPACMDBG_H("eth client number: %d\n", num_wan_client); + } + else + { + return res; + } +fail: + free(pHeaderDescriptor); + + return res; +} + +/*handle eth client */ +int IPACM_Wan::handle_wan_client_ipaddr(ipacm_event_data_all *data) +{ + int clnt_indx; + int v6_num; + + IPACMDBG_H("number of wan clients: %d\n", num_wan_client); + IPACMDBG_H(" event MAC %02x:%02x:%02x:%02x:%02x:%02x\n", + data->mac_addr[0], + data->mac_addr[1], + data->mac_addr[2], + data->mac_addr[3], + data->mac_addr[4], + data->mac_addr[5]); + + clnt_indx = get_wan_client_index(data->mac_addr); + + if (clnt_indx == IPACM_INVALID_INDEX) + { + IPACMERR("wan client not found/attached \n"); + return IPACM_FAILURE; + } + + IPACMDBG_H("Ip-type received %d\n", data->iptype); + if (data->iptype == IPA_IP_v4) + { + IPACMDBG_H("ipv4 address: 0x%x\n", data->ipv4_addr); + if (data->ipv4_addr != 0) /* not 0.0.0.0 */ + { + if (get_client_memptr(wan_client, clnt_indx)->ipv4_set == false) + { + get_client_memptr(wan_client, clnt_indx)->v4_addr = data->ipv4_addr; + get_client_memptr(wan_client, clnt_indx)->ipv4_set = true; + /* Add NAT rules after ipv4 RT rules are set */ + CtList->HandleSTAClientAddEvt(data->ipv4_addr); + } + else + { + /* check if client got new IPv4 address*/ + if(data->ipv4_addr == get_client_memptr(wan_client, clnt_indx)->v4_addr) + { + IPACMDBG_H("Already setup ipv4 addr for client:%d, ipv4 address didn't change\n", clnt_indx); + return IPACM_FAILURE; + } + else + { + IPACMDBG_H("ipv4 addr for client:%d is changed \n", clnt_indx); + /* Del NAT rules before ipv4 RT rules are delete */ + CtList->HandleSTAClientDelEvt(get_client_memptr(wan_client, clnt_indx)->v4_addr); + delete_wan_rtrules(clnt_indx,IPA_IP_v4); + get_client_memptr(wan_client, clnt_indx)->route_rule_set_v4 = false; + get_client_memptr(wan_client, clnt_indx)->v4_addr = data->ipv4_addr; + /* Add NAT rules after ipv4 RT rules are set */ + CtList->HandleSTAClientAddEvt(data->ipv4_addr); + } + } + } + else + { + IPACMDBG_H("Invalid client IPv4 address \n"); + return IPACM_FAILURE; + } + } + else + { + if ((data->ipv6_addr[0] != 0) || (data->ipv6_addr[1] != 0) || + (data->ipv6_addr[2] != 0) || (data->ipv6_addr[3] || 0)) /* check if all 0 not valid ipv6 address */ + { + IPACMDBG_H("ipv6 address: 0x%x:%x:%x:%x\n", data->ipv6_addr[0], data->ipv6_addr[1], data->ipv6_addr[2], data->ipv6_addr[3]); + if(get_client_memptr(wan_client, clnt_indx)->ipv6_set < IPV6_NUM_ADDR) + { + + for(v6_num=0;v6_num < get_client_memptr(wan_client, clnt_indx)->ipv6_set;v6_num++) + { + if( data->ipv6_addr[0] == get_client_memptr(wan_client, clnt_indx)->v6_addr[v6_num][0] && + data->ipv6_addr[1] == get_client_memptr(wan_client, clnt_indx)->v6_addr[v6_num][1] && + data->ipv6_addr[2]== get_client_memptr(wan_client, clnt_indx)->v6_addr[v6_num][2] && + data->ipv6_addr[3] == get_client_memptr(wan_client, clnt_indx)->v6_addr[v6_num][3]) + { + IPACMDBG_H("Already see this ipv6 addr for client:%d\n", clnt_indx); + return IPACM_FAILURE; /* not setup the RT rules*/ + } + } + + /* not see this ipv6 before for wifi client*/ + get_client_memptr(wan_client, clnt_indx)->v6_addr[get_client_memptr(wan_client, clnt_indx)->ipv6_set][0] = data->ipv6_addr[0]; + get_client_memptr(wan_client, clnt_indx)->v6_addr[get_client_memptr(wan_client, clnt_indx)->ipv6_set][1] = data->ipv6_addr[1]; + get_client_memptr(wan_client, clnt_indx)->v6_addr[get_client_memptr(wan_client, clnt_indx)->ipv6_set][2] = data->ipv6_addr[2]; + get_client_memptr(wan_client, clnt_indx)->v6_addr[get_client_memptr(wan_client, clnt_indx)->ipv6_set][3] = data->ipv6_addr[3]; + get_client_memptr(wan_client, clnt_indx)->ipv6_set++; + } + else + { + IPACMDBG_H("Already got 3 ipv6 addr for client:%d\n", clnt_indx); + return IPACM_FAILURE; /* not setup the RT rules*/ + } + } + } + + return IPACM_SUCCESS; +} + +/*handle wan client routing rule*/ +int IPACM_Wan::handle_wan_client_route_rule(uint8_t *mac_addr, ipa_ip_type iptype) +{ + struct ipa_ioc_add_rt_rule *rt_rule; + struct ipa_rt_rule_add *rt_rule_entry; + uint32_t tx_index; + int wan_index,v6_num; + const int NUM = 1; + + if(tx_prop == NULL) + { + IPACMDBG_H("No rx properties registered for iface %s\n", dev_name); + return IPACM_SUCCESS; + } + + IPACMDBG_H("Received mac_addr MAC %02x:%02x:%02x:%02x:%02x:%02x\n", + mac_addr[0], mac_addr[1], mac_addr[2], + mac_addr[3], mac_addr[4], mac_addr[5]); + + wan_index = get_wan_client_index(mac_addr); + if (wan_index == IPACM_INVALID_INDEX) + { + IPACMDBG_H("wan client not found/attached \n"); + return IPACM_SUCCESS; + } + + if (iptype==IPA_IP_v4) { + IPACMDBG_H("wan client index: %d, ip-type: %d, ipv4_set:%d, ipv4_rule_set:%d \n", wan_index, iptype, + get_client_memptr(wan_client, wan_index)->ipv4_set, + get_client_memptr(wan_client, wan_index)->route_rule_set_v4); + } else { + IPACMDBG_H("wan client index: %d, ip-type: %d, ipv6_set:%d, ipv6_rule_num:%d \n", wan_index, iptype, + get_client_memptr(wan_client, wan_index)->ipv6_set, + get_client_memptr(wan_client, wan_index)->route_rule_set_v6); + } + + /* Add default routing rules if not set yet */ + if ((iptype == IPA_IP_v4 + && get_client_memptr(wan_client, wan_index)->route_rule_set_v4 == false + && get_client_memptr(wan_client, wan_index)->ipv4_set == true) + || (iptype == IPA_IP_v6 + && get_client_memptr(wan_client, wan_index)->route_rule_set_v6 < get_client_memptr(wan_client, wan_index)->ipv6_set + )) + { + + /* Add corresponding ipa_rm_resource_name of TX-endpoint up before IPV6 RT-rule set */ + IPACMDBG_H("dev %s add producer dependency\n", dev_name); + IPACMDBG_H("depend Got pipe %d rm index : %d \n", tx_prop->tx[0].dst_pipe, IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe]); + IPACM_Iface::ipacmcfg->AddRmDepend(IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe],false); + + rt_rule = (struct ipa_ioc_add_rt_rule *) + calloc(1, sizeof(struct ipa_ioc_add_rt_rule) + + NUM * sizeof(struct ipa_rt_rule_add)); + + if (rt_rule == NULL) + { + PERROR("Error Locate ipa_ioc_add_rt_rule memory...\n"); + return IPACM_FAILURE; + } + + rt_rule->commit = 1; + rt_rule->num_rules = (uint8_t)NUM; + rt_rule->ip = iptype; + + for (tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++) + { + if(iptype != tx_prop->tx[tx_index].ip) + { + IPACMDBG_H("Tx:%d, ip-type: %d conflict ip-type: %d no RT-rule added\n", + tx_index, tx_prop->tx[tx_index].ip,iptype); + continue; + } + + rt_rule_entry = &rt_rule->rules[0]; + rt_rule_entry->at_rear = 0; + + if (iptype == IPA_IP_v4) + { + IPACMDBG_H("client index(%d):ipv4 address: 0x%x\n", wan_index, + get_client_memptr(wan_client, wan_index)->v4_addr); + + IPACMDBG_H("client(%d): v4 header handle:(0x%x)\n", + wan_index, + get_client_memptr(wan_client, wan_index)->hdr_hdl_v4); + strlcpy(rt_rule->rt_tbl_name, + IPACM_Iface::ipacmcfg->rt_tbl_wan_v4.name, + sizeof(rt_rule->rt_tbl_name)); + rt_rule->rt_tbl_name[IPA_RESOURCE_NAME_MAX-1] = '\0'; + if (IPACM_Iface::ipacmcfg->isMCC_Mode == true) + { + IPACMDBG_H("In MCC mode, use alt dst pipe: %d\n", + tx_prop->tx[tx_index].alt_dst_pipe); + rt_rule_entry->rule.dst = tx_prop->tx[tx_index].alt_dst_pipe; + } + else + { + rt_rule_entry->rule.dst = tx_prop->tx[tx_index].dst_pipe; + } + memcpy(&rt_rule_entry->rule.attrib, + &tx_prop->tx[tx_index].attrib, + sizeof(rt_rule_entry->rule.attrib)); + rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; + rt_rule_entry->rule.hdr_hdl = get_client_memptr(wan_client, wan_index)->hdr_hdl_v4; + rt_rule_entry->rule.attrib.u.v4.dst_addr = get_client_memptr(wan_client, wan_index)->v4_addr; + rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF; + if (false == m_routing.AddRoutingRule(rt_rule)) + { + IPACMERR("Routing rule addition failed!\n"); + free(rt_rule); + return IPACM_FAILURE; + } + + /* copy ipv4 RT hdl */ + get_client_memptr(wan_client, wan_index)->wan_rt_hdl[tx_index].wan_rt_rule_hdl_v4 = + rt_rule->rules[0].rt_rule_hdl; + IPACMDBG_H("tx:%d, rt rule hdl=%x ip-type: %d\n", tx_index, + get_client_memptr(wan_client, wan_index)->wan_rt_hdl[tx_index].wan_rt_rule_hdl_v4, iptype); + } else { + + for(v6_num = get_client_memptr(wan_client, wan_index)->route_rule_set_v6;v6_num < get_client_memptr(wan_client, wan_index)->ipv6_set;v6_num++) + { + IPACMDBG_H("client(%d): v6 header handle:(0x%x)\n", + wan_index, + get_client_memptr(wan_client, wan_index)->hdr_hdl_v6); + + /* v6 LAN_RT_TBL */ + strlcpy(rt_rule->rt_tbl_name, + IPACM_Iface::ipacmcfg->rt_tbl_v6.name, + sizeof(rt_rule->rt_tbl_name)); + rt_rule->rt_tbl_name[IPA_RESOURCE_NAME_MAX-1] = '\0'; + /* Uplink going to wan clients should go to IPA */ + if (IPACM_Iface::ipacmcfg->isMCC_Mode == true) + { + IPACMDBG_H("In MCC mode, use alt dst pipe: %d\n", + tx_prop->tx[tx_index].alt_dst_pipe); + rt_rule_entry->rule.dst = tx_prop->tx[tx_index].alt_dst_pipe; + } + else + { + rt_rule_entry->rule.dst = tx_prop->tx[tx_index].dst_pipe; + } + memset(&rt_rule_entry->rule.attrib, 0, sizeof(rt_rule_entry->rule.attrib)); + rt_rule_entry->rule.hdr_hdl = get_client_memptr(wan_client, wan_index)->hdr_hdl_v6;; + rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = get_client_memptr(wan_client, wan_index)->v6_addr[v6_num][0]; + rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = get_client_memptr(wan_client, wan_index)->v6_addr[v6_num][1]; + rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = get_client_memptr(wan_client, wan_index)->v6_addr[v6_num][2]; + rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = get_client_memptr(wan_client, wan_index)->v6_addr[v6_num][3]; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF; + if (false == m_routing.AddRoutingRule(rt_rule)) + { + IPACMERR("Routing rule addition failed!\n"); + free(rt_rule); + return IPACM_FAILURE; + } + + get_client_memptr(wan_client, wan_index)->wan_rt_hdl[tx_index].wan_rt_rule_hdl_v6[v6_num] = rt_rule->rules[0].rt_rule_hdl; + IPACMDBG_H("tx:%d, rt rule hdl=%x ip-type: %d\n", tx_index, + get_client_memptr(wan_client, wan_index)->wan_rt_hdl[tx_index].wan_rt_rule_hdl_v6[v6_num], iptype); + + /*Copy same rule to v6 WAN RT TBL*/ + strlcpy(rt_rule->rt_tbl_name, + IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.name, + sizeof(rt_rule->rt_tbl_name)); + rt_rule->rt_tbl_name[IPA_RESOURCE_NAME_MAX-1] = '\0'; + /* Downlink traffic from Wan clients, should go exception */ + rt_rule_entry->rule.dst = iface_query->excp_pipe; + memcpy(&rt_rule_entry->rule.attrib, + &tx_prop->tx[tx_index].attrib, + sizeof(rt_rule_entry->rule.attrib)); + rt_rule_entry->rule.hdr_hdl = 0; + rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = get_client_memptr(wan_client, wan_index)->v6_addr[v6_num][0]; + rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = get_client_memptr(wan_client, wan_index)->v6_addr[v6_num][1]; + rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = get_client_memptr(wan_client, wan_index)->v6_addr[v6_num][2]; + rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = get_client_memptr(wan_client, wan_index)->v6_addr[v6_num][3]; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF; + if (false == m_routing.AddRoutingRule(rt_rule)) + { + IPACMERR("Routing rule addition failed!\n"); + free(rt_rule); + return IPACM_FAILURE; + } + + get_client_memptr(wan_client, wan_index)->wan_rt_hdl[tx_index].wan_rt_rule_hdl_v6_wan[v6_num] = rt_rule->rules[0].rt_rule_hdl; + IPACMDBG_H("tx:%d, rt rule hdl=%x ip-type: %d\n", tx_index, + get_client_memptr(wan_client, wan_index)->wan_rt_hdl[tx_index].wan_rt_rule_hdl_v6_wan[v6_num], iptype); + } + } + + } /* end of for loop */ + + free(rt_rule); + + if (iptype == IPA_IP_v4) + { + get_client_memptr(wan_client, wan_index)->route_rule_set_v4 = true; + } + else + { + get_client_memptr(wan_client, wan_index)->route_rule_set_v6 = get_client_memptr(wan_client, wan_index)->ipv6_set; + } + } + + return IPACM_SUCCESS; +} + +/* TODO Handle wan client routing rules also */ +void IPACM_Wan::handle_wlan_SCC_MCC_switch(bool isSCCMode, ipa_ip_type iptype) +{ + struct ipa_ioc_mdfy_rt_rule *rt_rule = NULL; + struct ipa_rt_rule_mdfy *rt_rule_entry; + uint32_t tx_index = 0; + + IPACMDBG("\n"); + if (tx_prop == NULL || is_default_gateway == false) + { + IPACMDBG_H("No tx properties or no default route set yet\n"); + return; + } + + const int NUM = tx_prop->num_tx_props; + + for (tx_index = 0; tx_index < tx_prop->num_tx_props; tx_index++) + { + if (tx_prop->tx[tx_index].ip != iptype) + { + IPACMDBG_H("Tx:%d, ip-type: %d ip-type not matching: %d Ignore\n", + tx_index, tx_prop->tx[tx_index].ip, iptype); + continue; + } + + if (rt_rule == NULL) + { + rt_rule = (struct ipa_ioc_mdfy_rt_rule *) + calloc(1, sizeof(struct ipa_ioc_mdfy_rt_rule) + + NUM * sizeof(struct ipa_rt_rule_mdfy)); + + if (rt_rule == NULL) + { + IPACMERR("Unable to allocate memory for modify rt rule\n"); + return; + } + IPACMDBG("Allocated memory for %d rules successfully\n", NUM); + + rt_rule->commit = 1; + rt_rule->num_rules = 0; + rt_rule->ip = iptype; + } + + rt_rule_entry = &rt_rule->rules[rt_rule->num_rules]; + + memcpy(&rt_rule_entry->rule.attrib, + &tx_prop->tx[tx_index].attrib, + sizeof(rt_rule_entry->rule.attrib)); + rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; + + if (iptype == IPA_IP_v4) + { + rt_rule_entry->rule.attrib.u.v4.dst_addr = 0; + rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0; + rt_rule_entry->rule.hdr_hdl = hdr_hdl_sta_v4; + rt_rule_entry->rt_rule_hdl = wan_route_rule_v4_hdl[tx_index]; + } + else + { + rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = 0; + rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = 0; + rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = 0; + rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = 0; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0; + + rt_rule_entry->rule.hdr_hdl = hdr_hdl_sta_v6; + rt_rule_entry->rt_rule_hdl = wan_route_rule_v6_hdl[tx_index]; + } + IPACMDBG_H("Header handle: 0x%x\n", rt_rule_entry->rule.hdr_hdl); + + if (isSCCMode) + { + rt_rule_entry->rule.dst = tx_prop->tx[tx_index].dst_pipe; + } + else + { + IPACMDBG_H("In MCC mode, use alt dst pipe: %d\n", + tx_prop->tx[tx_index].alt_dst_pipe); + rt_rule_entry->rule.dst = tx_prop->tx[tx_index].alt_dst_pipe; + } + + rt_rule->num_rules++; + } + + if (rt_rule != NULL) + { + + if (rt_rule->num_rules > 0) + { + if (false == m_routing.ModifyRoutingRule(rt_rule)) + { + IPACMERR("Routing rule modify failed!\n"); + free(rt_rule); + return; + } + + IPACMDBG("Routing rule modified successfully \n"); + } + + free(rt_rule); + } + + return; +} + +void IPACM_Wan::handle_wan_client_SCC_MCC_switch(bool isSCCMode, ipa_ip_type iptype) +{ + struct ipa_ioc_mdfy_rt_rule *rt_rule = NULL; + struct ipa_rt_rule_mdfy *rt_rule_entry; + + uint32_t tx_index = 0, clnt_index =0; + int v6_num = 0; + const int NUM_RULES = 1; + + int size = sizeof(struct ipa_ioc_mdfy_rt_rule) + + NUM_RULES * sizeof(struct ipa_rt_rule_mdfy); + + IPACMDBG("\n"); + + if (tx_prop == NULL || is_default_gateway == false) + { + IPACMDBG_H("No tx properties or no default route set yet\n"); + return; + } + + rt_rule = (struct ipa_ioc_mdfy_rt_rule *)calloc(1, size); + if (rt_rule == NULL) + { + IPACMERR("Unable to allocate memory for modify rt rule\n"); + return; + } + + + for (clnt_index = 0; clnt_index < num_wan_client; clnt_index++) + { + if (iptype == IPA_IP_v4) + { + IPACMDBG_H("wan client index: %d, ip-type: %d, ipv4_set:%d, ipv4_rule_set:%d \n", + clnt_index, iptype, + get_client_memptr(wan_client, clnt_index)->ipv4_set, + get_client_memptr(wan_client, clnt_index)->route_rule_set_v4); + + if( get_client_memptr(wan_client, clnt_index)->route_rule_set_v4 == false || + get_client_memptr(wan_client, clnt_index)->ipv4_set == false) + { + continue; + } + + for (tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++) + { + if (iptype != tx_prop->tx[tx_index].ip) + { + IPACMDBG_H("Tx:%d, ip-type: %d conflict ip-type: %d skip\n", + tx_index, tx_prop->tx[tx_index].ip, iptype); + continue; + } + + memset(rt_rule, 0, size); + rt_rule->commit = 1; + rt_rule->num_rules = NUM_RULES; + rt_rule->ip = iptype; + rt_rule_entry = &rt_rule->rules[0]; + + IPACMDBG_H("client index(%d):ipv4 address: 0x%x\n", clnt_index, + get_client_memptr(wan_client, clnt_index)->v4_addr); + + IPACMDBG_H("client(%d): v4 header handle:(0x%x)\n", + clnt_index, + get_client_memptr(wan_client, clnt_index)->hdr_hdl_v4); + + if (IPACM_Iface::ipacmcfg->isMCC_Mode == true) + { + IPACMDBG_H("In MCC mode, use alt dst pipe: %d\n", + tx_prop->tx[tx_index].alt_dst_pipe); + rt_rule_entry->rule.dst = tx_prop->tx[tx_index].alt_dst_pipe; + } + else + { + rt_rule_entry->rule.dst = tx_prop->tx[tx_index].dst_pipe; + } + + memcpy(&rt_rule_entry->rule.attrib, + &tx_prop->tx[tx_index].attrib, + sizeof(rt_rule_entry->rule.attrib)); + rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; + + rt_rule_entry->rule.hdr_hdl = get_client_memptr(wan_client, clnt_index)->hdr_hdl_v4; + rt_rule_entry->rule.attrib.u.v4.dst_addr = get_client_memptr(wan_client, clnt_index)->v4_addr; + rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF; + + /* copy ipv4 RT rule hdl */ + IPACMDBG_H("rt rule hdl=%x\n", + get_client_memptr(wan_client, clnt_index)->wan_rt_hdl[tx_index].wan_rt_rule_hdl_v4); + + rt_rule_entry->rt_rule_hdl = + get_client_memptr(wan_client, clnt_index)->wan_rt_hdl[tx_index].wan_rt_rule_hdl_v4; + + if (false == m_routing.ModifyRoutingRule(rt_rule)) + { + IPACMERR("Routing rule modify failed!\n"); + free(rt_rule); + return; + } + } + } + else + { + IPACMDBG_H("wan client index: %d, ip-type: %d, ipv6_set:%d, ipv6_rule_num:%d \n", clnt_index, iptype, + get_client_memptr(wan_client, clnt_index)->ipv6_set, + get_client_memptr(wan_client, clnt_index)->route_rule_set_v6); + + if( get_client_memptr(wan_client, clnt_index)->route_rule_set_v6 == 0) + { + continue; + } + + for (tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++) + { + if (iptype != tx_prop->tx[tx_index].ip) + { + IPACMDBG_H("Tx:%d, ip-type: %d conflict ip-type: %d skip\n", + tx_index, tx_prop->tx[tx_index].ip, iptype); + continue; + } + + memset(rt_rule, 0, size); + rt_rule->commit = 1; + rt_rule->num_rules = NUM_RULES; + rt_rule->ip = iptype; + rt_rule_entry = &rt_rule->rules[0]; + + /* Modify only rules in v6 WAN RT TBL*/ + for (v6_num = 0; + v6_num < get_client_memptr(wan_client, clnt_index)->route_rule_set_v6; + v6_num++) + { + IPACMDBG_H("client(%d): v6 header handle:(0x%x)\n", + clnt_index, + get_client_memptr(wan_client, clnt_index)->hdr_hdl_v6); + + /* Downlink traffic from Wan iface, directly through IPA */ + if (IPACM_Iface::ipacmcfg->isMCC_Mode == true) + { + IPACMDBG_H("In MCC mode, use alt dst pipe: %d\n", + tx_prop->tx[tx_index].alt_dst_pipe); + rt_rule_entry->rule.dst = tx_prop->tx[tx_index].alt_dst_pipe; + } + else + { + rt_rule_entry->rule.dst = tx_prop->tx[tx_index].dst_pipe; + } + + memcpy(&rt_rule_entry->rule.attrib, + &tx_prop->tx[tx_index].attrib, + sizeof(rt_rule_entry->rule.attrib)); + + rt_rule_entry->rule.hdr_hdl = get_client_memptr(wan_client, clnt_index)->hdr_hdl_v6; + rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = get_client_memptr(wan_client, clnt_index)->v6_addr[v6_num][0]; + rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = get_client_memptr(wan_client, clnt_index)->v6_addr[v6_num][1]; + rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = get_client_memptr(wan_client, clnt_index)->v6_addr[v6_num][2]; + rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = get_client_memptr(wan_client, clnt_index)->v6_addr[v6_num][3]; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF; + + IPACMDBG_H("rt rule hdl=%x\n", + get_client_memptr(wan_client, clnt_index)->wan_rt_hdl[tx_index].wan_rt_rule_hdl_v6_wan[v6_num]); + + rt_rule_entry->rt_rule_hdl = + get_client_memptr(wan_client, clnt_index)->wan_rt_hdl[tx_index].wan_rt_rule_hdl_v6_wan[v6_num]; + + if (false == m_routing.ModifyRoutingRule(rt_rule)) + { + IPACMERR("Routing rule Modify failed!\n"); + free(rt_rule); + return; + } + } + } /* end of for loop */ + } + + } + + free(rt_rule); + return; +} + +/*handle eth client */ +int IPACM_Wan::handle_network_stats_update(ipa_get_apn_data_stats_resp_msg_v01 *data) +{ + FILE *fp = NULL; + + for (int apn_index =0; apn_index < data->apn_data_stats_list_len; apn_index++) + { + if(data->apn_data_stats_list[apn_index].mux_id == ext_prop->ext[0].mux_id) + { + IPACMDBG_H("Received IPA_TETHERING_STATS_UPDATE_NETWORK_STATS, MUX ID %d TX (P%lu/B%lu) RX (P%lu/B%lu)\n", + data->apn_data_stats_list[apn_index].mux_id, + data->apn_data_stats_list[apn_index].num_ul_packets, + data->apn_data_stats_list[apn_index].num_ul_bytes, + data->apn_data_stats_list[apn_index].num_dl_packets, + data->apn_data_stats_list[apn_index].num_dl_bytes); + fp = fopen(IPA_NETWORK_STATS_FILE_NAME, "w"); + if ( fp == NULL ) + { + IPACMERR("Failed to write pipe stats to %s, error is %d - %s\n", + IPA_NETWORK_STATS_FILE_NAME, errno, strerror(errno)); + return IPACM_FAILURE; + } + + fprintf(fp, NETWORK_STATS, + dev_name, + data->apn_data_stats_list[apn_index].num_ul_packets, + data->apn_data_stats_list[apn_index].num_ul_bytes, + data->apn_data_stats_list[apn_index].num_dl_packets, + data->apn_data_stats_list[apn_index].num_dl_bytes); + fclose(fp); + break; + }; + } + return IPACM_SUCCESS; +} diff --git a/data-ipa-cfg-mgr/ipacm/src/IPACM_Wlan.cpp b/data-ipa-cfg-mgr/ipacm/src/IPACM_Wlan.cpp new file mode 100644 index 000000000..bb707244e --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/src/IPACM_Wlan.cpp @@ -0,0 +1,5610 @@ +/* +Copyright (c) 2013, The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: +* Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. +* Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +/*! +@file +IPACM_Wlan.cpp + +@brief +This file implements the WLAN iface functionality. + +@Author +Skylar Chang + +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/* static member to store the number of total wifi clients within all APs*/ +int IPACM_Wlan::total_num_wifi_clients = 0; + +uint32_t* IPACM_Wlan::dummy_flt_rule_hdl_v4 = NULL; +uint32_t* IPACM_Wlan::dummy_flt_rule_hdl_v6 = NULL; +int IPACM_Wlan::num_wlan_ap_iface = 0; + +lan2lan_flt_rule_hdl IPACM_Wlan::self_client_flt_rule_hdl_v4[IPA_LAN_TO_LAN_MAX_WLAN_CLIENT]; +lan2lan_flt_rule_hdl IPACM_Wlan::self_client_flt_rule_hdl_v6[IPA_LAN_TO_LAN_MAX_WLAN_CLIENT]; + +lan2lan_flt_rule_hdl IPACM_Wlan::lan_client_flt_rule_hdl_v4[IPA_LAN_TO_LAN_MAX_LAN_CLIENT]; +lan2lan_flt_rule_hdl IPACM_Wlan::lan_client_flt_rule_hdl_v6[IPA_LAN_TO_LAN_MAX_LAN_CLIENT]; + +IPACM_Wlan::IPACM_Wlan(int iface_index) : IPACM_Lan(iface_index) +{ +#define WLAN_AMPDU_DEFAULT_FILTER_RULES 3 + + wlan_ap_index = IPACM_Wlan::num_wlan_ap_iface; + if(wlan_ap_index < 0 || wlan_ap_index > 1) + { + IPACMERR("Wlan_ap_index is not correct: %d, not creating instance.\n", wlan_ap_index); + if (tx_prop != NULL) + { + free(tx_prop); + } + if (rx_prop != NULL) + { + free(rx_prop); + } + if (iface_query != NULL) + { + free(iface_query); + } + delete this; + return; + } + + num_wifi_client = 0; + header_name_count = 0; + wlan_client = NULL; + + if(iface_query != NULL) + { + wlan_client_len = (sizeof(ipa_wlan_client)) + (iface_query->num_tx_props * sizeof(wlan_client_rt_hdl)); + wlan_client = (ipa_wlan_client *)calloc(IPA_MAX_NUM_WIFI_CLIENTS, wlan_client_len); + if (wlan_client == NULL) + { + IPACMERR("unable to allocate memory\n"); + return; + } + IPACMDBG_H("index:%d constructor: Tx properties:%d\n", iface_index, iface_query->num_tx_props); + } + Nat_App = NatApp::GetInstance(); + if (Nat_App == NULL) + { + IPACMERR("unable to get Nat App instance \n"); + return; + } + +#ifdef FEATURE_ETH_BRIDGE_LE + exp_index_v4 = IPV4_DEFAULT_FILTERTING_RULES + IPACM_Iface::ipacmcfg->ipa_num_private_subnet + + IPA_LAN_TO_LAN_MAX_WLAN_CLIENT + IPA_LAN_TO_LAN_MAX_LAN_CLIENT + NUM_IPV4_ICMP_FLT_RULE; + exp_index_v6 = IPV6_DEFAULT_FILTERTING_RULES + IPA_LAN_TO_LAN_MAX_WLAN_CLIENT + IPA_LAN_TO_LAN_MAX_LAN_CLIENT + + 2 * NUM_IPV6_PREFIX_FLT_RULE + NUM_IPV6_ICMP_FLT_RULE; +#else +#ifndef CT_OPT + exp_index_v4 = 2*(IPV4_DEFAULT_FILTERTING_RULES + MAX_OFFLOAD_PAIR + IPACM_Iface::ipacmcfg->ipa_num_private_subnet) + NUM_IPV4_ICMP_FLT_RULE; + exp_index_v6 = 2*(IPV6_DEFAULT_FILTERTING_RULES + MAX_OFFLOAD_PAIR + NUM_IPV6_PREFIX_FLT_RULE) + NUM_IPV6_ICMP_FLT_RULE; +#else + exp_index_v4 = 2*(IPV4_DEFAULT_FILTERTING_RULES + NUM_TCP_CTL_FLT_RULE + MAX_OFFLOAD_PAIR + IPACM_Iface::ipacmcfg->ipa_num_private_subnet) + NUM_IPV4_ICMP_FLT_RULE; + exp_index_v6 = 2*(IPV6_DEFAULT_FILTERTING_RULES + NUM_TCP_CTL_FLT_RULE + MAX_OFFLOAD_PAIR + NUM_IPV6_PREFIX_FLT_RULE) + NUM_IPV6_ICMP_FLT_RULE; +#endif +#ifdef FEATURE_IPA_ANDROID + exp_index_v4 = exp_index_v4 + 2 * (IPA_MAX_PRIVATE_SUBNET_ENTRIES - IPACM_Iface::ipacmcfg->ipa_num_private_subnet); +#endif +#endif + + IPACM_Wlan::num_wlan_ap_iface++; + IPACMDBG_H("Now the number of wlan AP iface is %d\n", IPACM_Wlan::num_wlan_ap_iface); + add_dummy_flt_rule(); + + is_guest_ap = false; + + memset(eth_bridge_lan_client_flt_info, 0, IPA_LAN_TO_LAN_MAX_LAN_CLIENT * sizeof(eth_bridge_client_flt_info)); + lan_client_flt_info_count = 0; + eth_bridge_wlan_client_rt_from_lan_info_v4 = NULL; + eth_bridge_wlan_client_rt_from_lan_info_v6 = NULL; + eth_bridge_wlan_client_rt_from_wlan_info_v4 = NULL; + eth_bridge_wlan_client_rt_from_wlan_info_v6 = NULL; + if(tx_prop != NULL) + { +#ifdef FEATURE_ETH_BRIDGE_LE + client_rt_info_size_v4 = sizeof(eth_bridge_client_rt_info) + each_client_rt_rule_count_v4 * sizeof(uint32_t); + eth_bridge_wlan_client_rt_from_lan_info_v4 = (eth_bridge_client_rt_info*)calloc(IPA_LAN_TO_LAN_MAX_WLAN_CLIENT, client_rt_info_size_v4); + eth_bridge_wlan_client_rt_from_wlan_info_v4 = (eth_bridge_client_rt_info*)calloc(IPA_LAN_TO_LAN_MAX_WLAN_CLIENT, client_rt_info_size_v4); + + client_rt_info_size_v6 = sizeof(eth_bridge_client_rt_info) + each_client_rt_rule_count_v6 * sizeof(uint32_t); + eth_bridge_wlan_client_rt_from_lan_info_v6 = (eth_bridge_client_rt_info*)calloc(IPA_LAN_TO_LAN_MAX_WLAN_CLIENT, client_rt_info_size_v6); + eth_bridge_wlan_client_rt_from_wlan_info_v6 = (eth_bridge_client_rt_info*)calloc(IPA_LAN_TO_LAN_MAX_WLAN_CLIENT, client_rt_info_size_v6); +#endif + } + wlan_client_rt_from_lan_info_count_v4 = 0; + wlan_client_rt_from_lan_info_count_v6 = 0; + wlan_client_rt_from_wlan_info_count_v4 = 0; + wlan_client_rt_from_wlan_info_count_v6 = 0; +#ifdef FEATURE_ETH_BRIDGE_LE + if(iface_query != NULL) + { + if(IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat == WLAN_IF && tx_prop != NULL) + { + if(IPACM_Lan::wlan_hdr_type != IPA_HDR_L2_NONE && tx_prop->tx[0].hdr_l2_type != IPACM_Lan::wlan_hdr_type) + { + IPACMERR("The WLAN header format is not consistent! Now header format is %d.\n", tx_prop->tx[0].hdr_l2_type); + } + else + { + if(wlan_ap_index == 0) + { + if(eth_bridge_get_hdr_template_hdl(&IPACM_Lan::wlan_hdr_template_hdl) == IPACM_FAILURE) + { + IPACMERR("Failed to setup wlan hdr template.\n"); + } + else + { + IPACM_Lan::wlan_hdr_type = tx_prop->tx[0].hdr_l2_type; + add_hdr_proc_ctx(); + } + } + } + if (IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].wlan_mode == INTERNET) + { + is_guest_ap = true; + } + IPACMDBG_H("%s: guest ap enable: %d \n", + IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].iface_name, is_guest_ap); + } + } +#endif + +#ifdef FEATURE_IPA_ANDROID + /* set the IPA-client pipe enum */ + if(IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat == WLAN_IF) + { + handle_tethering_client(false, IPACM_CLIENT_WLAN); + } +#endif + return; +} + + +IPACM_Wlan::~IPACM_Wlan() +{ + IPACM_EvtDispatcher::deregistr(this); + IPACM_IfaceManager::deregistr(this); + return; +} + +void IPACM_Wlan::event_callback(ipa_cm_event_id event, void *param) +{ + if(is_active == false && event != IPA_LAN_DELETE_SELF) + { + IPACMDBG_H("The interface is no longer active, return.\n"); + return; + } + + int ipa_interface_index; + int wlan_index; + ipacm_ext_prop* ext_prop; + ipacm_event_iface_up* data_wan; + ipacm_event_iface_up_tehter* data_wan_tether; + + switch (event) + { + + case IPA_WLAN_LINK_DOWN_EVENT: + { + ipacm_event_data_fid *data = (ipacm_event_data_fid *)param; + ipa_interface_index = iface_ipa_index_query(data->if_index); + if (ipa_interface_index == ipa_if_num) + { + IPACMDBG_H("Received IPA_WLAN_LINK_DOWN_EVENT\n"); + handle_down_evt(); + /* reset the AP-iface category to unknown */ + IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat=UNKNOWN_IF; + IPACM_Iface::ipacmcfg->DelNatIfaces(dev_name); // delete NAT-iface + IPACM_Wlan::total_num_wifi_clients = (IPACM_Wlan::total_num_wifi_clients) - \ + (num_wifi_client); + return; + } + } + break; + + case IPA_PRIVATE_SUBNET_CHANGE_EVENT: + { + ipacm_event_data_fid *data = (ipacm_event_data_fid *)param; + /* internel event: data->if_index is ipa_if_index */ + if (data->if_index == ipa_if_num) + { + IPACMDBG_H("Received IPA_PRIVATE_SUBNET_CHANGE_EVENT from itself posting, ignore\n"); + return; + } + else + { + IPACMDBG_H("Received IPA_PRIVATE_SUBNET_CHANGE_EVENT from other LAN iface \n"); +#ifdef FEATURE_IPA_ANDROID + handle_private_subnet_android(IPA_IP_v4); +#endif + IPACMDBG_H(" delete old private subnet rules, use new sets \n"); + return; + } + } + break; + + case IPA_LAN_DELETE_SELF: + { + ipacm_event_data_fid *data = (ipacm_event_data_fid *)param; + if(data->if_index == ipa_if_num) + { + IPACM_Wlan::num_wlan_ap_iface--; + IPACMDBG_H("Now the number of wlan AP iface is %d\n", IPACM_Wlan::num_wlan_ap_iface); + del_dummy_flt_rule(); + + IPACMDBG_H("Received IPA_LAN_DELETE_SELF event.\n"); + IPACMDBG_H("ipa_WLAN (%s):ipa_index (%d) instance close \n", IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].iface_name, ipa_if_num); + delete this; + } + break; + } + + case IPA_ADDR_ADD_EVENT: + { + ipacm_event_data_addr *data = (ipacm_event_data_addr *)param; + ipa_interface_index = iface_ipa_index_query(data->if_index); + + if ( (data->iptype == IPA_IP_v4 && data->ipv4_addr == 0) || + (data->iptype == IPA_IP_v6 && + data->ipv6_addr[0] == 0 && data->ipv6_addr[1] == 0 && + data->ipv6_addr[2] == 0 && data->ipv6_addr[3] == 0) ) + { + IPACMDBG_H("Invalid address, ignore IPA_ADDR_ADD_EVENT event\n"); + return; + } + + if (ipa_interface_index == ipa_if_num) + { + /* check v4 not setup before, v6 can have 2 iface ip */ + if( ((data->iptype != ip_type) && (ip_type != IPA_IP_MAX)) + || ((data->iptype==IPA_IP_v6) && (num_dft_rt_v6!=MAX_DEFAULT_v6_ROUTE_RULES))) + { + IPACMDBG_H("Got IPA_ADDR_ADD_EVENT ip-family:%d, v6 num %d: \n",data->iptype,num_dft_rt_v6); + /* Post event to NAT */ + if (data->iptype == IPA_IP_v4) + { + ipacm_cmd_q_data evt_data; + ipacm_event_iface_up *info; + + info = (ipacm_event_iface_up *) + malloc(sizeof(ipacm_event_iface_up)); + if (info == NULL) + { + IPACMERR("Unable to allocate memory\n"); + return; + } + + memcpy(info->ifname, dev_name, IF_NAME_LEN); + info->ipv4_addr = data->ipv4_addr; + info->addr_mask = IPACM_Iface::ipacmcfg->private_subnet_table[0].subnet_mask; + + evt_data.event = IPA_HANDLE_WLAN_UP; + evt_data.evt_data = (void *)info; + + /* Insert IPA_HANDLE_WLAN_UP to command queue */ + IPACMDBG_H("posting IPA_HANDLE_WLAN_UP for IPv4 with below information\n"); + IPACMDBG_H("IPv4 address:0x%x, IPv4 address mask:0x%x\n", + info->ipv4_addr, info->addr_mask); + IPACM_EvtDispatcher::PostEvt(&evt_data); + } + if(handle_addr_evt(data) == IPACM_FAILURE) + { + return; + } + if ((data->iptype == IPA_IP_v4) && (wlan_ap_index == 0)) + { + IPACM_Lan::install_ipv4_icmp_flt_rule(); + } + if ((num_dft_rt_v6 == 1) && (data->iptype == IPA_IP_v6) && (wlan_ap_index == 0)) + { + install_ipv6_icmp_flt_rule(); + } + +#ifdef FEATURE_IPA_ANDROID + add_dummy_private_subnet_flt_rule(data->iptype); + handle_private_subnet_android(data->iptype); +#else + if(wlan_ap_index == 0) + { + handle_private_subnet(data->iptype); + } +#endif + + if (IPACM_Wan::isWanUP(ipa_if_num)) + { + if(data->iptype == IPA_IP_v4 || data->iptype == IPA_IP_MAX) + { + if(IPACM_Wan::backhaul_is_sta_mode == false) + { + ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(IPA_IP_v4); + IPACM_Lan::handle_wan_up_ex(ext_prop, IPA_IP_v4, + IPACM_Wan::getXlat_Mux_Id()); + } + else + { + IPACM_Lan::handle_wan_up(IPA_IP_v4); + } + } + } + + if(IPACM_Wan::isWanUP_V6(ipa_if_num)) + { + if((data->iptype == IPA_IP_v6 || data->iptype == IPA_IP_MAX) && num_dft_rt_v6 == 1) + { + install_ipv6_prefix_flt_rule(IPACM_Wan::backhaul_ipv6_prefix); + + if(IPACM_Wan::backhaul_is_sta_mode == false) + { + ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(IPA_IP_v6); + IPACM_Lan::handle_wan_up_ex(ext_prop, IPA_IP_v6, 0); + } + else + { + IPACM_Lan::handle_wan_up(IPA_IP_v6); + } + } + } + + IPACMDBG_H("posting IPA_HANDLE_WLAN_UP:Finished checking wan_up\n"); + /* checking if SW-RT_enable */ + if (IPACM_Iface::ipacmcfg->ipa_sw_rt_enable == true) + { + /* handle software routing enable event*/ + IPACMDBG_H("IPA_SW_ROUTING_ENABLE for iface: %s \n",IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].iface_name); + handle_software_routing_enable(); + } + } + } + } + break; +#ifdef FEATURE_IPA_ANDROID + case IPA_HANDLE_WAN_UP_TETHER: + IPACMDBG_H("Received IPA_HANDLE_WAN_UP_TETHER event\n"); + + data_wan_tether = (ipacm_event_iface_up_tehter*)param; + if(data_wan_tether == NULL) + { + IPACMERR("No event data is found.\n"); + return; + } + IPACMDBG_H("Backhaul is sta mode?%d, if_index_tether:%d tether_if_name:%s\n", data_wan_tether->is_sta, + data_wan_tether->if_index_tether, + IPACM_Iface::ipacmcfg->iface_table[data_wan_tether->if_index_tether].iface_name); + if (data_wan_tether->if_index_tether == ipa_if_num) + { + if(ip_type == IPA_IP_v4 || ip_type == IPA_IP_MAX) + { + if(data_wan_tether->is_sta == false) + { + ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(IPA_IP_v4); + IPACM_Lan::handle_wan_up_ex(ext_prop, IPA_IP_v4, 0); + } + else + { + IPACM_Lan::handle_wan_up(IPA_IP_v4); + } + } + } + break; + + case IPA_HANDLE_WAN_UP_V6_TETHER: + IPACMDBG_H("Received IPA_HANDLE_WAN_UP_V6_TETHER event\n"); + + data_wan_tether = (ipacm_event_iface_up_tehter*)param; + if(data_wan_tether == NULL) + { + IPACMERR("No event data is found.\n"); + return; + } + IPACMDBG_H("Backhaul is sta mode?%d, if_index_tether:%d tether_if_name:%s\n", data_wan_tether->is_sta, + data_wan_tether->if_index_tether, + IPACM_Iface::ipacmcfg->iface_table[data_wan_tether->if_index_tether].iface_name); + if (data_wan_tether->if_index_tether == ipa_if_num) + { + if(ip_type == IPA_IP_v6 || ip_type == IPA_IP_MAX) + { + install_ipv6_prefix_flt_rule(data_wan_tether->ipv6_prefix); + + if(data_wan_tether->is_sta == false) + { + ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(IPA_IP_v6); + IPACM_Lan::handle_wan_up_ex(ext_prop, IPA_IP_v6, 0); + } + else + { + IPACM_Lan::handle_wan_up(IPA_IP_v6); + } + } + } + break; + + case IPA_HANDLE_WAN_DOWN_TETHER: + IPACMDBG_H("Received IPA_HANDLE_WAN_DOWN_TETHER event\n"); + data_wan_tether = (ipacm_event_iface_up_tehter*)param; + if(data_wan_tether == NULL) + { + IPACMERR("No event data is found.\n"); + return; + } + IPACMDBG_H("Backhaul is sta mode?%d, if_index_tether:%d tether_if_name:%s\n", data_wan_tether->is_sta, + data_wan_tether->if_index_tether, + IPACM_Iface::ipacmcfg->iface_table[data_wan_tether->if_index_tether].iface_name); + if (data_wan_tether->if_index_tether == ipa_if_num) + { + if(data_wan_tether->is_sta == false && wlan_ap_index > 0) + { + IPACMDBG_H("This is not the first AP instance and not STA mode, ignore WAN_DOWN event.\n"); + return; + } + if (rx_prop != NULL) + { + if(ip_type == IPA_IP_v4 || ip_type == IPA_IP_MAX) + { + handle_wan_down(data_wan_tether->is_sta); + } + } + } + break; + + case IPA_HANDLE_WAN_DOWN_V6_TETHER: + IPACMDBG_H("Received IPA_HANDLE_WAN_DOWN_V6_TETHER event\n"); + data_wan_tether = (ipacm_event_iface_up_tehter*)param; + if(data_wan_tether == NULL) + { + IPACMERR("No event data is found.\n"); + return; + } + IPACMDBG_H("Backhaul is sta mode?%d, if_index_tether:%d tether_if_name:%s\n", data_wan_tether->is_sta, + data_wan_tether->if_index_tether, + IPACM_Iface::ipacmcfg->iface_table[data_wan_tether->if_index_tether].iface_name); + if (data_wan_tether->if_index_tether == ipa_if_num) + { + /* clean up v6 RT rules*/ + IPACMDBG_H("Received IPA_WAN_V6_DOWN in WLAN-instance and need clean up client IPv6 address \n"); + /* reset wifi-client ipv6 rt-rules */ + handle_wlan_client_reset_rt(IPA_IP_v6); + + if (rx_prop != NULL) + { + if(ip_type == IPA_IP_v6 || ip_type == IPA_IP_MAX) + { + handle_wan_down_v6(data_wan_tether->is_sta); + } + } + } + break; +#else + case IPA_HANDLE_WAN_UP: + IPACMDBG_H("Received IPA_HANDLE_WAN_UP event\n"); + + data_wan = (ipacm_event_iface_up*)param; + if(data_wan == NULL) + { + IPACMERR("No event data is found.\n"); + return; + } + IPACMDBG_H("Backhaul is sta mode?%d\n", data_wan->is_sta); + if(ip_type == IPA_IP_v4 || ip_type == IPA_IP_MAX) + { + if(data_wan->is_sta == false) + { + ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(IPA_IP_v4); + IPACM_Lan::handle_wan_up_ex(ext_prop, IPA_IP_v4, data_wan->xlat_mux_id); + } + else + { + IPACM_Lan::handle_wan_up(IPA_IP_v4); + } + } + break; + + case IPA_HANDLE_WAN_UP_V6: + IPACMDBG_H("Received IPA_HANDLE_WAN_UP_V6 event\n"); + + data_wan = (ipacm_event_iface_up*)param; + if(data_wan == NULL) + { + IPACMERR("No event data is found.\n"); + return; + } + IPACMDBG_H("Backhaul is sta mode?%d\n", data_wan->is_sta); + if(ip_type == IPA_IP_v6 || ip_type == IPA_IP_MAX) + { + install_ipv6_prefix_flt_rule(data_wan->ipv6_prefix); + + if(data_wan->is_sta == false) + { + ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(IPA_IP_v6); + IPACM_Lan::handle_wan_up_ex(ext_prop, IPA_IP_v6, 0); + } + else + { + IPACM_Lan::handle_wan_up(IPA_IP_v6); + } + } + break; + + case IPA_HANDLE_WAN_DOWN: + IPACMDBG_H("Received IPA_HANDLE_WAN_DOWN event\n"); + data_wan = (ipacm_event_iface_up*)param; + if(data_wan == NULL) + { + IPACMERR("No event data is found.\n"); + return; + } + IPACMDBG_H("Backhaul is sta mode?%d\n", data_wan->is_sta); + if(data_wan->is_sta == false && wlan_ap_index > 0) + { + IPACMDBG_H("This is not the first AP instance and not STA mode, ignore WAN_DOWN event.\n"); + return; + } + if (rx_prop != NULL) + { + if(ip_type == IPA_IP_v4 || ip_type == IPA_IP_MAX) + { + handle_wan_down(data_wan->is_sta); + } + } + break; + + case IPA_HANDLE_WAN_DOWN_V6: + IPACMDBG_H("Received IPA_HANDLE_WAN_DOWN_V6 event\n"); + data_wan = (ipacm_event_iface_up*)param; + if(data_wan == NULL) + { + IPACMERR("No event data is found.\n"); + return; + } + /* clean up v6 RT rules*/ + IPACMDBG_H("Received IPA_WAN_V6_DOWN in WLAN-instance and need clean up client IPv6 address \n"); + /* reset wifi-client ipv6 rt-rules */ + handle_wlan_client_reset_rt(IPA_IP_v6); + IPACMDBG_H("Backhaul is sta mode ? %d\n", data_wan->is_sta); + if (rx_prop != NULL) + { + if(ip_type == IPA_IP_v6 || ip_type == IPA_IP_MAX) + { + handle_wan_down_v6(data_wan->is_sta); + } + } + break; +#endif + + case IPA_WLAN_CLIENT_ADD_EVENT_EX: + { + ipacm_event_data_wlan_ex *data = (ipacm_event_data_wlan_ex *)param; + ipa_interface_index = iface_ipa_index_query(data->if_index); + if (ipa_interface_index == ipa_if_num) + { +#ifdef FEATURE_ETH_BRIDGE_LE + int i; + for(i=0; inum_of_attribs; i++) + { + if(data->attribs[i].attrib_type == WLAN_HDR_ATTRIB_MAC_ADDR) + { + if(IPACM_Lan::wlan_to_wlan_hdr_proc_ctx.valid == true) + { + eth_bridge_add_wlan_client_rt_rule(data->attribs[i].u.mac_addr, SRC_WLAN, IPA_IP_v4); + eth_bridge_add_wlan_client_rt_rule(data->attribs[i].u.mac_addr, SRC_WLAN, IPA_IP_v6); + } + if(ip_type == IPA_IP_v4 || ip_type == IPA_IP_MAX) + { + eth_bridge_add_self_client_flt_rule(data->attribs[i].u.mac_addr, IPA_IP_v4); + } + if(ip_type == IPA_IP_v6 || ip_type == IPA_IP_MAX) + { + eth_bridge_add_self_client_flt_rule(data->attribs[i].u.mac_addr, IPA_IP_v6); + } + if (is_guest_ap == false) + { + if(IPACM_Lan::lan_to_wlan_hdr_proc_ctx.valid == true) + { + eth_bridge_add_wlan_client_rt_rule(data->attribs[i].u.mac_addr, SRC_LAN, IPA_IP_v4); + eth_bridge_add_wlan_client_rt_rule(data->attribs[i].u.mac_addr, SRC_LAN, IPA_IP_v6); + } + eth_bridge_post_lan_client_event(data->attribs[i].u.mac_addr, IPA_ETH_BRIDGE_WLAN_CLIENT_ADD_EVENT); + } + eth_bridge_add_wlan_client(data->attribs[i].u.mac_addr, ipa_if_num); + break; + } + } +#endif + IPACMDBG_H("Received IPA_WLAN_CLIENT_ADD_EVENT\n"); + handle_wlan_client_init_ex(data); + } + } + break; + + case IPA_WLAN_CLIENT_DEL_EVENT: + { + ipacm_event_data_mac *data = (ipacm_event_data_mac *)param; + ipa_interface_index = iface_ipa_index_query(data->if_index); + if (ipa_interface_index == ipa_if_num) + { + IPACMDBG_H("Received IPA_WLAN_CLIENT_DEL_EVENT\n"); +#ifdef FEATURE_ETH_BRIDGE_LE + eth_bridge_del_self_client_flt_rule(data->mac_addr); + eth_bridge_del_wlan_client_rt_rule(data->mac_addr, SRC_WLAN); + if (is_guest_ap == false) + { + if(IPACM_Lan::lan_to_wlan_hdr_proc_ctx.valid == true) + { + eth_bridge_del_wlan_client_rt_rule(data->mac_addr, SRC_LAN); + } + eth_bridge_post_lan_client_event(data->mac_addr, IPA_ETH_BRIDGE_WLAN_CLIENT_DEL_EVENT); + } + eth_bridge_del_wlan_client(data->mac_addr); +#endif + /* support lan2lan ipa-HW feature*/ + handle_lan2lan_msg_post(data->mac_addr, IPA_LAN_CLIENT_DISCONNECT, IPA_IP_v4); + handle_lan2lan_msg_post(data->mac_addr, IPA_LAN_CLIENT_DISCONNECT, IPA_IP_v6); + handle_wlan_client_down_evt(data->mac_addr); + } + } + break; + + case IPA_WLAN_CLIENT_POWER_SAVE_EVENT: + { + ipacm_event_data_mac *data = (ipacm_event_data_mac *)param; + ipa_interface_index = iface_ipa_index_query(data->if_index); + if (ipa_interface_index == ipa_if_num) + { + IPACMDBG_H("Received IPA_WLAN_CLIENT_POWER_SAVE_EVENT\n"); + /* support lan2lan ipa-HW feature*/ + handle_lan2lan_msg_post(data->mac_addr, IPA_LAN_CLIENT_POWER_SAVE, IPA_IP_v4); + handle_lan2lan_msg_post(data->mac_addr, IPA_LAN_CLIENT_POWER_SAVE, IPA_IP_v6); + handle_wlan_client_pwrsave(data->mac_addr); + } + } + break; + + case IPA_WLAN_CLIENT_RECOVER_EVENT: + { + ipacm_event_data_mac *data = (ipacm_event_data_mac *)param; + ipa_interface_index = iface_ipa_index_query(data->if_index); + if (ipa_interface_index == ipa_if_num) + { + IPACMDBG_H("Received IPA_WLAN_CLIENT_RECOVER_EVENT\n"); + /* support lan2lan ipa-HW feature*/ + handle_lan2lan_msg_post(data->mac_addr, IPA_LAN_CLIENT_POWER_RECOVER, IPA_IP_v4); + handle_lan2lan_msg_post(data->mac_addr, IPA_LAN_CLIENT_POWER_RECOVER, IPA_IP_v6); + + wlan_index = get_wlan_client_index(data->mac_addr); + if ((wlan_index != IPACM_INVALID_INDEX) && + (get_client_memptr(wlan_client, wlan_index)->power_save_set == true)) + { + + IPACMDBG_H("change wlan client out of power safe mode \n"); + get_client_memptr(wlan_client, wlan_index)->power_save_set = false; + + /* First add route rules and then nat rules */ + if(get_client_memptr(wlan_client, wlan_index)->ipv4_set == true) /* for ipv4 */ + { + IPACMDBG_H("recover client index(%d):ipv4 address: 0x%x\n", + wlan_index, + get_client_memptr(wlan_client, wlan_index)->v4_addr); + + IPACMDBG_H("Adding Route Rules\n"); + handle_wlan_client_route_rule(data->mac_addr, IPA_IP_v4); + IPACMDBG_H("Adding Nat Rules\n"); + Nat_App->ResetPwrSaveIf(get_client_memptr(wlan_client, wlan_index)->v4_addr); + } + + if(get_client_memptr(wlan_client, wlan_index)->ipv6_set != 0) /* for ipv6 */ + { + handle_wlan_client_route_rule(data->mac_addr, IPA_IP_v6); + } + } + } + } + break; + + case IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT: + { + ipacm_event_data_all *data = (ipacm_event_data_all *)param; + ipa_interface_index = iface_ipa_index_query(data->if_index); + if (ipa_interface_index == ipa_if_num) + { + IPACMDBG_H("Received IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT\n"); + if (handle_wlan_client_ipaddr(data) == IPACM_FAILURE) + { + return; + } + /* support lan2lan ipa-hw feature */ + handle_lan2lan_client_active(data, IPA_LAN_CLIENT_ACTIVE); + + handle_wlan_client_route_rule(data->mac_addr, data->iptype); + if (data->iptype == IPA_IP_v4) + { + /* Add NAT rules after ipv4 RT rules are set */ + CtList->HandleNeighIpAddrAddEvt(data); + //Nat_App->ResetPwrSaveIf(data->ipv4_addr); + } + } + } + break; + + /* handle software routing enable event, iface will update softwarerouting_act to true*/ + case IPA_SW_ROUTING_ENABLE: + IPACMDBG_H("Received IPA_SW_ROUTING_ENABLE\n"); + IPACM_Iface::handle_software_routing_enable(); + break; + + /* handle software routing disable event, iface will update softwarerouting_act to false*/ + case IPA_SW_ROUTING_DISABLE: + IPACMDBG_H("Received IPA_SW_ROUTING_DISABLE\n"); + IPACM_Iface::handle_software_routing_disable(); + break; + + case IPA_ETH_BRIDGE_LAN_CLIENT_ADD_EVENT: + { + IPACMDBG_H("Received IPA_ETH_BRIDGE_LAN_CLIENT_ADD_EVENT event.\n"); + ipacm_event_data_mac* mac = (ipacm_event_data_mac*)param; + if(mac != NULL) + { + if(ip_type == IPA_IP_v4 || ip_type == IPA_IP_MAX) + { + eth_bridge_add_lan_client_flt_rule(mac->mac_addr, IPA_IP_v4); + } + if(ip_type == IPA_IP_v6 || ip_type == IPA_IP_MAX) + { + eth_bridge_add_lan_client_flt_rule(mac->mac_addr, IPA_IP_v6); + } + } + else + { + IPACMERR("Event MAC is empty.\n"); + } + } + break; + + case IPA_ETH_BRIDGE_LAN_CLIENT_DEL_EVENT: + { + IPACMDBG_H("Received IPA_ETH_BRIDGE_LAN_CLIENT_DEL_EVENT event.\n"); + ipacm_event_data_mac* mac = (ipacm_event_data_mac*)param; + if(mac != NULL) + { + if(wlan_ap_index == 0) + { + if(eth_bridge_del_lan_client_flt_rule(mac->mac_addr) == IPACM_FAILURE) + { + IPACMDBG_H("Failed to delete lan client MAC based flt rule.\n"); + } + } + } + else + { + IPACMERR("Event MAC is empty.\n"); + } + } + break; + + case IPA_ETH_BRIDGE_HDR_PROC_CTX_SET_EVENT: + { + IPACMDBG_H("Received IPA_ETH_BRIDGE_HDR_PROC_CTX_SET_EVENT event.\n"); + int i; + ipacm_event_data_if_cat* cat = (ipacm_event_data_if_cat*)param; + if(cat == NULL) + { + IPACMERR("Event data is empty.\n"); + return; + } + if(cat->if_cat != LAN_IF && cat->if_cat != ODU_IF) + { + IPACMDBG_H("The event was not sent by LAN interface, ignore.\n"); + return; + } + if (IPACM_Lan::is_usb_up == true && IPACM_Lan::is_cpe_up == true) + { + IPACMDBG_H("USB and CPE both are up, lan-wlan routing rules are already installed. \n"); + return; + } + for(i=0; iif_cat != LAN_IF && cat->if_cat != ODU_IF) + { + IPACMDBG_H("The event was not sent by LAN interface, ignore.\n"); + return; + } + if (IPACM_Lan::is_usb_up == true || IPACM_Lan::is_cpe_up == true) + { + IPACMDBG_H("USB or CPE is still up, so keep lan-wlan routing rule. \n"); + return; + } + for(i=0; icradle_wan_mode == BRIDGE) + { + handle_cradle_wan_mode_switch(true); + } + else + { + handle_cradle_wan_mode_switch(false); + } + } + break; + case IPA_CFG_CHANGE_EVENT: + { + int i; + IPACMDBG_H("Received IPA_CFG_CHANGE_EVENT event for %s with new wlan-mode: %s old wlan-mode: %s", + IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].iface_name, + (IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].wlan_mode == 0) ? "full" : "internet", + (is_guest_ap == true) ? "internet" : "full"); + /* Add Natting iface to IPACM_Config if there is Rx/Tx property */ + if (rx_prop != NULL || tx_prop != NULL) + { + IPACMDBG_H(" Has rx/tx properties registered for iface %s, add for NATTING \n", dev_name); + IPACM_Iface::ipacmcfg->AddNatIfaces(dev_name); + } + + if (is_guest_ap == true && (IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].wlan_mode == FULL)) + { + is_guest_ap = false; + IPACMDBG_H("wlan mode is switched to full access mode. \n"); + eth_bridge_handle_wlan_mode_switch(); + } + else if (is_guest_ap == false && (IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].wlan_mode == INTERNET)) + { + is_guest_ap = true; + IPACMDBG_H("wlan mode is switched to internet only access mode. \n"); + eth_bridge_handle_wlan_mode_switch(); + } + else + { + IPACMDBG_H("No change in %s access mode. \n", + IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].iface_name); + + /* Handle the WLAN filtering rule */ + for (i=0; iipa_stats_type != QMI_IPA_STATS_TYPE_PIPE_V01) + { + IPACMERR("not valid pipe stats\n"); + return; + } + handle_tethering_stats_event(data); + }; + } + } + break; + default: + break; + } + return; +} + +/*Configure the initial filter rules */ +int IPACM_Wlan::init_fl_rule(ipa_ip_type iptype) +{ + int res = IPACM_SUCCESS, len, offset; + struct ipa_flt_rule_mdfy flt_rule; + struct ipa_ioc_mdfy_flt_rule* pFilteringTable; + + /* update the iface ip-type to be IPA_IP_v4, IPA_IP_v6 or both*/ + if (iptype == IPA_IP_v4) + { + if ((ip_type == IPA_IP_v4) || (ip_type == IPA_IP_MAX)) + { + IPACMDBG_H("Interface(%s:%d) already in ip-type %d\n", dev_name, ipa_if_num, ip_type); + return res; + } + + if (ip_type == IPA_IP_v6) + { + ip_type = IPA_IP_MAX; + } + else + { + ip_type = IPA_IP_v4; + } + IPACMDBG_H("Interface(%s:%d) now ip-type is %d\n", dev_name, ipa_if_num, ip_type); + } + else + { + if ((ip_type == IPA_IP_v6) || (ip_type == IPA_IP_MAX)) + { + IPACMDBG_H("Interface(%s:%d) already in ip-type %d\n", dev_name, ipa_if_num, ip_type); + return res; + } + + if (ip_type == IPA_IP_v4) + { + ip_type = IPA_IP_MAX; + } + else + { + ip_type = IPA_IP_v6; + } + + IPACMDBG_H("Interface(%s:%d) now ip-type is %d\n", dev_name, ipa_if_num, ip_type); + } + + /* ADD corresponding ipa_rm_resource_name of RX-endpoint before adding all IPV4V6 FT-rules */ + if(rx_prop != NULL) + { + IPACMDBG_H("dev %s add producer dependency\n", dev_name); + IPACMDBG_H("depend Got pipe %d rm index : %d \n", rx_prop->rx[0].src_pipe, IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[rx_prop->rx[0].src_pipe]); + IPACM_Iface::ipacmcfg->AddRmDepend(IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[rx_prop->rx[0].src_pipe],false); + IPACMDBG_H("Add producer dependency from %s with registered rx-prop\n", dev_name); + } + else + { + /* Adding the check if no Rx property registered, no filter rules will be added */ + IPACMDBG_H("No rx properties registered for iface %s\n", dev_name); + return IPACM_SUCCESS; + } +#ifdef FEATURE_ETH_BRIDGE_LE + if(wlan_ap_index != 0) + { + IPACMDBG_H("Install frag/multicast/broadcast rules only for the first AP.\n"); + return IPACM_SUCCESS; + } +#endif + + /* construct ipa_ioc_add_flt_rule with default filter rules */ + if (iptype == IPA_IP_v4) + { + if(IPACM_Wlan::dummy_flt_rule_hdl_v4 == NULL) + { + IPACMERR("Dummy ipv4 flt rule has not been installed.\n"); + return IPACM_FAILURE; + } +#ifdef FEATURE_ETH_BRIDGE_LE + offset = 0; +#else +#ifndef CT_OPT + offset = wlan_ap_index * (IPV4_DEFAULT_FILTERTING_RULES + MAX_OFFLOAD_PAIR + IPACM_Iface::ipacmcfg->ipa_num_private_subnet); +#else + offset = wlan_ap_index * (IPV4_DEFAULT_FILTERTING_RULES + NUM_TCP_CTL_FLT_RULE + MAX_OFFLOAD_PAIR + IPACM_Iface::ipacmcfg->ipa_num_private_subnet) + + NUM_TCP_CTL_FLT_RULE; +#endif +#endif + +#ifdef FEATURE_IPA_ANDROID + offset = offset + wlan_ap_index * (IPA_MAX_PRIVATE_SUBNET_ENTRIES - IPACM_Iface::ipacmcfg->ipa_num_private_subnet); +#endif + len = sizeof(struct ipa_ioc_mdfy_flt_rule) + (IPV4_DEFAULT_FILTERTING_RULES * sizeof(struct ipa_flt_rule_mdfy)); + pFilteringTable = (struct ipa_ioc_mdfy_flt_rule *)calloc(1, len); + if (!pFilteringTable) + { + IPACMERR("Error Locate ipa_ioc_mdfy_flt_rule memory...\n"); + return IPACM_FAILURE; + } + memset(pFilteringTable, 0, len); + + pFilteringTable->commit = 1; + pFilteringTable->ip = iptype; + pFilteringTable->num_rules = (uint8_t)IPV4_DEFAULT_FILTERTING_RULES; + + memset(&flt_rule, 0, sizeof(struct ipa_flt_rule_mdfy)); + + flt_rule.status = -1; + + flt_rule.rule.retain_hdr = 1; + flt_rule.rule.to_uc = 0; + flt_rule.rule.action = IPA_PASS_TO_EXCEPTION; + flt_rule.rule.eq_attrib_type = 0; + + /* Configuring Fragment Filtering Rule */ + IPACMDBG_H("rx property attrib mask:0x%x\n", rx_prop->rx[0].attrib.attrib_mask); + memcpy(&flt_rule.rule.attrib, &rx_prop->rx[0].attrib, sizeof(flt_rule.rule.attrib)); +#ifdef FEATURE_ETH_BRIDGE_LE + /* remove meta data mask */ + flt_rule.rule.attrib.attrib_mask &= ~((uint32_t)IPA_FLT_META_DATA); +#endif + flt_rule.rule.attrib.attrib_mask |= IPA_FLT_FRAGMENT; + flt_rule.rule_hdl = IPACM_Wlan::dummy_flt_rule_hdl_v4[offset]; + memcpy(&(pFilteringTable->rules[0]), &flt_rule, sizeof(struct ipa_flt_rule_mdfy)); + + /* Configuring Multicast Filtering Rule */ + memcpy(&flt_rule.rule.attrib, &rx_prop->rx[0].attrib, sizeof(flt_rule.rule.attrib)); +#ifdef FEATURE_ETH_BRIDGE_LE + /* remove meta data mask */ + flt_rule.rule.attrib.attrib_mask &= ~((uint32_t)IPA_FLT_META_DATA); +#endif + flt_rule.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; + flt_rule.rule.attrib.u.v4.dst_addr_mask = 0xF0000000; + flt_rule.rule.attrib.u.v4.dst_addr = 0xE0000000; + flt_rule.rule_hdl = IPACM_Wlan::dummy_flt_rule_hdl_v4[offset+1]; + memcpy(&(pFilteringTable->rules[1]), &flt_rule, sizeof(struct ipa_flt_rule_mdfy)); + + /* Configuring Broadcast Filtering Rule */ + flt_rule.rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF; + flt_rule.rule.attrib.u.v4.dst_addr = 0xFFFFFFFF; + flt_rule.rule_hdl = IPACM_Wlan::dummy_flt_rule_hdl_v4[offset+2]; + memcpy(&(pFilteringTable->rules[2]), &flt_rule, sizeof(struct ipa_flt_rule_mdfy)); + + if (false == m_filtering.ModifyFilteringRule(pFilteringTable)) + { + IPACMERR("Failed to modify default ipv4 filtering rules.\n"); + res = IPACM_FAILURE; + goto fail; + } + else + { + /* copy filter hdls */ + for (int i = 0; i < IPV4_DEFAULT_FILTERTING_RULES; i++) + { + if (pFilteringTable->rules[i].status == 0) + { + dft_v4fl_rule_hdl[i] = pFilteringTable->rules[i].rule_hdl; + IPACMDBG_H("Default v4 filter Rule %d HDL:0x%x\n", i, dft_v4fl_rule_hdl[i]); + } + else + { + IPACMERR("Failed adding default v4 Filtering rule %d\n", i); + } + } + } + } + else + { + if(IPACM_Wlan::dummy_flt_rule_hdl_v6 == NULL) + { + IPACMERR("Dummy ipv6 flt rule has not been installed.\n"); + return IPACM_FAILURE; + } +#ifdef FEATURE_ETH_BRIDGE_LE + offset = IPA_LAN_TO_LAN_MAX_WLAN_CLIENT + IPA_LAN_TO_LAN_MAX_LAN_CLIENT; +#else +#ifndef CT_OPT + offset = wlan_ap_index * (IPV6_DEFAULT_FILTERTING_RULES + MAX_OFFLOAD_PAIR) + MAX_OFFLOAD_PAIR; +#else + offset = wlan_ap_index * (IPV6_DEFAULT_FILTERTING_RULES + NUM_TCP_CTL_FLT_RULE + MAX_OFFLOAD_PAIR) + + NUM_TCP_CTL_FLT_RULE + MAX_OFFLOAD_PAIR; +#endif +#endif + + len = sizeof(struct ipa_ioc_mdfy_flt_rule) + (IPV6_DEFAULT_FILTERTING_RULES * sizeof(struct ipa_flt_rule_mdfy)); + pFilteringTable = (struct ipa_ioc_mdfy_flt_rule *)calloc(1, len); + if (!pFilteringTable) + { + IPACMERR("Error Locate ipa_ioc_mdfy_flt_rule memory...\n"); + return IPACM_FAILURE; + } + memset(pFilteringTable, 0, len); + + pFilteringTable->commit = 1; + pFilteringTable->ip = iptype; + pFilteringTable->num_rules = (uint8_t)IPV6_DEFAULT_FILTERTING_RULES; + + memset(&flt_rule, 0, sizeof(struct ipa_flt_rule_mdfy)); + + flt_rule.status = -1; + + flt_rule.rule.retain_hdr = 1; + flt_rule.rule.to_uc = 0; + flt_rule.rule.action = IPA_PASS_TO_EXCEPTION; + flt_rule.rule.eq_attrib_type = 0; + + /* Configuring Multicast Filtering Rule */ + memcpy(&flt_rule.rule.attrib, &rx_prop->rx[0].attrib, sizeof(flt_rule.rule.attrib)); +#ifdef FEATURE_ETH_BRIDGE_LE + /* remove meta data mask */ + flt_rule.rule.attrib.attrib_mask &= ~((uint32_t)IPA_FLT_META_DATA); +#endif + flt_rule.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; + flt_rule.rule.attrib.u.v6.dst_addr_mask[0] = 0xFF000000; + flt_rule.rule.attrib.u.v6.dst_addr_mask[1] = 0x00000000; + flt_rule.rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000; + flt_rule.rule.attrib.u.v6.dst_addr_mask[3] = 0x00000000; + flt_rule.rule.attrib.u.v6.dst_addr[0] = 0XFF000000; + flt_rule.rule.attrib.u.v6.dst_addr[1] = 0x00000000; + flt_rule.rule.attrib.u.v6.dst_addr[2] = 0x00000000; + flt_rule.rule.attrib.u.v6.dst_addr[3] = 0X00000000; + flt_rule.rule_hdl = IPACM_Wlan::dummy_flt_rule_hdl_v6[offset]; + memcpy(&(pFilteringTable->rules[0]), &flt_rule, sizeof(struct ipa_flt_rule_mdfy)); + + /* Configuring fe80::/10 Link-Scoped Unicast Filtering Rule */ + flt_rule.rule.attrib.u.v6.dst_addr_mask[0] = 0XFFC00000; + flt_rule.rule.attrib.u.v6.dst_addr_mask[1] = 0x00000000; + flt_rule.rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000; + flt_rule.rule.attrib.u.v6.dst_addr_mask[3] = 0x00000000; + flt_rule.rule.attrib.u.v6.dst_addr[0] = 0xFE800000; + flt_rule.rule.attrib.u.v6.dst_addr[1] = 0x00000000; + flt_rule.rule.attrib.u.v6.dst_addr[2] = 0x00000000; + flt_rule.rule.attrib.u.v6.dst_addr[3] = 0X00000000; + flt_rule.rule_hdl = IPACM_Wlan::dummy_flt_rule_hdl_v6[offset+1]; + memcpy(&(pFilteringTable->rules[1]), &flt_rule, sizeof(struct ipa_flt_rule_mdfy)); + + /* Configuring fec0::/10 Reserved by IETF Filtering Rule */ + flt_rule.rule.attrib.u.v6.dst_addr_mask[0] = 0XFFC00000; + flt_rule.rule.attrib.u.v6.dst_addr_mask[1] = 0x00000000; + flt_rule.rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000; + flt_rule.rule.attrib.u.v6.dst_addr_mask[3] = 0x00000000; + flt_rule.rule.attrib.u.v6.dst_addr[0] = 0xFEC00000; + flt_rule.rule.attrib.u.v6.dst_addr[1] = 0x00000000; + flt_rule.rule.attrib.u.v6.dst_addr[2] = 0x00000000; + flt_rule.rule.attrib.u.v6.dst_addr[3] = 0X00000000; + flt_rule.rule_hdl = IPACM_Wlan::dummy_flt_rule_hdl_v6[offset+2]; + memcpy(&(pFilteringTable->rules[2]), &flt_rule, sizeof(struct ipa_flt_rule_mdfy)); + +#ifdef FEATURE_IPA_ANDROID + memset(&flt_rule, 0, sizeof(struct ipa_flt_rule_mdfy)); + + flt_rule.status = -1; + + flt_rule.rule.retain_hdr = 1; + flt_rule.rule.to_uc = 0; + flt_rule.rule.action = IPA_PASS_TO_EXCEPTION; + flt_rule.rule.eq_attrib_type = 1; + + flt_rule.rule.eq_attrib.rule_eq_bitmap = 0; + + if(rx_prop->rx[0].attrib.attrib_mask & IPA_FLT_META_DATA) + { + flt_rule.rule.eq_attrib.rule_eq_bitmap |= (1<<14); + flt_rule.rule.eq_attrib.metadata_meq32_present = 1; + flt_rule.rule.eq_attrib.metadata_meq32.offset = 0; + flt_rule.rule.eq_attrib.metadata_meq32.value = rx_prop->rx[0].attrib.meta_data; + flt_rule.rule.eq_attrib.metadata_meq32.mask = rx_prop->rx[0].attrib.meta_data_mask; + } + + flt_rule.rule.eq_attrib.rule_eq_bitmap |= (1<<1); + flt_rule.rule.eq_attrib.protocol_eq_present = 1; + flt_rule.rule.eq_attrib.protocol_eq = IPACM_FIREWALL_IPPROTO_TCP; + + flt_rule.rule.eq_attrib.rule_eq_bitmap |= (1<<8); + flt_rule.rule.eq_attrib.num_ihl_offset_meq_32 = 1; + flt_rule.rule.eq_attrib.ihl_offset_meq_32[0].offset = 12; + + /* add TCP FIN rule*/ + flt_rule.rule.eq_attrib.ihl_offset_meq_32[0].value = (((uint32_t)1)<rules[3]), &flt_rule, sizeof(struct ipa_flt_rule_mdfy)); + + /* add TCP SYN rule*/ + flt_rule.rule.eq_attrib.ihl_offset_meq_32[0].value = (((uint32_t)1)<rules[4]), &flt_rule, sizeof(struct ipa_flt_rule_mdfy)); + + /* add TCP RST rule*/ + flt_rule.rule.eq_attrib.ihl_offset_meq_32[0].value = (((uint32_t)1)<rules[5]), &flt_rule, sizeof(struct ipa_flt_rule_mdfy)); +#endif + + if (m_filtering.ModifyFilteringRule(pFilteringTable) == false) + { + IPACMERR("Failed to modify default ipv6 filtering rules.\n"); + res = IPACM_FAILURE; + goto fail; + } + else + { + for (int i = 0; i < IPV6_DEFAULT_FILTERTING_RULES; i++) + { + if (pFilteringTable->rules[i].status == 0) + { + dft_v6fl_rule_hdl[i] = pFilteringTable->rules[i].rule_hdl; + IPACMDBG_H("Default v6 Filter Rule %d HDL:0x%x\n", i, dft_v6fl_rule_hdl[i]); + } + else + { + IPACMERR("Failing adding v6 default IPV6 rule %d\n", i); + } + } + } + } + +fail: + free(pFilteringTable); + return res; +} + +int IPACM_Wlan::add_dummy_lan2lan_flt_rule(ipa_ip_type iptype) +{ + if(rx_prop == NULL) + { + IPACMDBG_H("There is no rx_prop for iface %s, not able to add dummy lan2lan filtering rule.\n", dev_name); + return IPACM_FAILURE; + } + + int offset; + if(iptype == IPA_IP_v4) + { + if(IPACM_Wlan::dummy_flt_rule_hdl_v4 == NULL) + { + IPACMERR("Dummy ipv4 flt rule has not been installed.\n"); + return IPACM_FAILURE; + } + +#ifndef CT_OPT + offset = wlan_ap_index * (IPV4_DEFAULT_FILTERTING_RULES + MAX_OFFLOAD_PAIR + IPACM_Iface::ipacmcfg->ipa_num_private_subnet) + + IPV4_DEFAULT_FILTERTING_RULES; +#else + offset = wlan_ap_index * (IPV4_DEFAULT_FILTERTING_RULES + NUM_TCP_CTL_FLT_RULE + MAX_OFFLOAD_PAIR + IPACM_Iface::ipacmcfg->ipa_num_private_subnet) + + NUM_TCP_CTL_FLT_RULE + IPV4_DEFAULT_FILTERTING_RULES; +#endif + +#ifdef FEATURE_IPA_ANDROID + offset = offset + wlan_ap_index * (IPA_MAX_PRIVATE_SUBNET_ENTRIES - IPACM_Iface::ipacmcfg->ipa_num_private_subnet); +#endif + for (int i = 0; i < MAX_OFFLOAD_PAIR; i++) + { + lan2lan_flt_rule_hdl_v4[i].rule_hdl = IPACM_Wlan::dummy_flt_rule_hdl_v4[offset+i]; + lan2lan_flt_rule_hdl_v4[i].valid = false; + IPACMDBG_H("Lan2lan v4 flt rule %d hdl:0x%x\n", i, lan2lan_flt_rule_hdl_v4[i].rule_hdl); + } + } + else if(iptype == IPA_IP_v6) + { + if(IPACM_Wlan::dummy_flt_rule_hdl_v6 == NULL) + { + IPACMERR("Dummy ipv6 flt rule has not been installed.\n"); + return IPACM_FAILURE; + } + +#ifndef CT_OPT + offset = wlan_ap_index * (IPV6_DEFAULT_FILTERTING_RULES + MAX_OFFLOAD_PAIR); +#else + offset = wlan_ap_index * (IPV6_DEFAULT_FILTERTING_RULES + NUM_TCP_CTL_FLT_RULE + MAX_OFFLOAD_PAIR) + + NUM_TCP_CTL_FLT_RULE; +#endif + + for (int i = 0; i < MAX_OFFLOAD_PAIR; i++) + { + lan2lan_flt_rule_hdl_v6[i].rule_hdl = IPACM_Wlan::dummy_flt_rule_hdl_v6[offset+i]; + lan2lan_flt_rule_hdl_v6[i].valid = false; + IPACMDBG_H("Lan2lan v6 flt rule %d hdl:0x%x\n", i, lan2lan_flt_rule_hdl_v6[i].rule_hdl); + } + } + else + { + IPACMERR("IP type is not expected.\n"); + return IPACM_FAILURE; + } + + return IPACM_SUCCESS; +} + +/* configure private subnet filter rules*/ +int IPACM_Wlan::handle_private_subnet(ipa_ip_type iptype) +{ + int i, len, res = IPACM_SUCCESS, offset; + struct ipa_flt_rule_mdfy flt_rule; + struct ipa_ioc_mdfy_flt_rule* pFilteringTable; + + if (rx_prop == NULL) + { + IPACMDBG_H("No rx properties registered for iface %s\n", dev_name); + return IPACM_SUCCESS; + } + + if (iptype == IPA_IP_v4) + { + if(IPACM_Wlan::dummy_flt_rule_hdl_v4 == NULL) + { + IPACMERR("Dummy ipv4 flt rule has not been installed.\n"); + return IPACM_FAILURE; + } +#ifdef FEATURE_ETH_BRIDGE_LE + offset = IPV4_DEFAULT_FILTERTING_RULES + IPACM_Iface::ipacmcfg->ipa_num_private_subnet + IPA_LAN_TO_LAN_MAX_WLAN_CLIENT + IPA_LAN_TO_LAN_MAX_LAN_CLIENT; +#else +#ifndef CT_OPT + offset = wlan_ap_index * (IPV4_DEFAULT_FILTERTING_RULES + MAX_OFFLOAD_PAIR + IPACM_Iface::ipacmcfg->ipa_num_private_subnet) + + IPV4_DEFAULT_FILTERTING_RULES + MAX_OFFLOAD_PAIR; +#else + offset = wlan_ap_index * (IPV4_DEFAULT_FILTERTING_RULES + NUM_TCP_CTL_FLT_RULE + MAX_OFFLOAD_PAIR + IPACM_Iface::ipacmcfg->ipa_num_private_subnet) + + IPV4_DEFAULT_FILTERTING_RULES + NUM_TCP_CTL_FLT_RULE + MAX_OFFLOAD_PAIR; +#endif +#endif + + len = sizeof(struct ipa_ioc_mdfy_flt_rule) + (IPACM_Iface::ipacmcfg->ipa_num_private_subnet) * sizeof(struct ipa_flt_rule_mdfy); + pFilteringTable = (struct ipa_ioc_mdfy_flt_rule*)malloc(len); + if (!pFilteringTable) + { + IPACMERR("Failed to allocate ipa_ioc_mdfy_flt_rule memory...\n"); + return IPACM_FAILURE; + } + memset(pFilteringTable, 0, len); + + pFilteringTable->commit = 1; + pFilteringTable->ip = iptype; + pFilteringTable->num_rules = (uint8_t)IPACM_Iface::ipacmcfg->ipa_num_private_subnet; + + /* Make LAN-traffic always go A5, use default IPA-RT table */ + if (false == m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_default_v4)) + { + IPACMERR("Failed to get routing table handle.\n"); + res = IPACM_FAILURE; + goto fail; + } + + memset(&flt_rule, 0, sizeof(struct ipa_flt_rule_mdfy)); + flt_rule.status = -1; + + flt_rule.rule.retain_hdr = 1; + flt_rule.rule.to_uc = 0; + flt_rule.rule.action = IPA_PASS_TO_ROUTING; + flt_rule.rule.eq_attrib_type = 0; + flt_rule.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_default_v4.hdl; + IPACMDBG_H("Private filter rule use table: %s\n",IPACM_Iface::ipacmcfg->rt_tbl_default_v4.name); + + memcpy(&flt_rule.rule.attrib, &rx_prop->rx[0].attrib, sizeof(flt_rule.rule.attrib)); + flt_rule.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; +#ifdef FEATURE_ETH_BRIDGE_LE + /* remove meta data mask */ + flt_rule.rule.attrib.attrib_mask &= ~((uint32_t)IPA_FLT_META_DATA); +#endif + + for (i = 0; i < (IPACM_Iface::ipacmcfg->ipa_num_private_subnet); i++) + { + flt_rule.rule_hdl = IPACM_Wlan::dummy_flt_rule_hdl_v4[offset+i]; + flt_rule.rule.attrib.u.v4.dst_addr_mask = IPACM_Iface::ipacmcfg->private_subnet_table[i].subnet_mask; + flt_rule.rule.attrib.u.v4.dst_addr = IPACM_Iface::ipacmcfg->private_subnet_table[i].subnet_addr; + memcpy(&(pFilteringTable->rules[i]), &flt_rule, sizeof(struct ipa_flt_rule_mdfy)); + } + + if (false == m_filtering.ModifyFilteringRule(pFilteringTable)) + { + IPACMERR("Failed to modify private subnet filtering rules.\n"); + res = IPACM_FAILURE; + goto fail; + } + + /* copy filter rule hdls */ + for (i = 0; i < IPACM_Iface::ipacmcfg->ipa_num_private_subnet; i++) + { + private_fl_rule_hdl[i] = pFilteringTable->rules[i].rule_hdl; + } + } + else + { + return IPACM_SUCCESS; + } +fail: + free(pFilteringTable); + return res; +} + +/* install UL filter rule from Q6 */ +int IPACM_Wlan::handle_uplink_filter_rule(ipacm_ext_prop *prop, ipa_ip_type iptype, uint8_t xlat_mux_id) +{ + ipa_flt_rule_add flt_rule_entry; + int len = 0, cnt, ret = IPACM_SUCCESS, index; + ipa_ioc_add_flt_rule *pFilteringTable; + ipa_fltr_installed_notif_req_msg_v01 flt_index; + int fd, i; + uint32_t value = 0; + + IPACMDBG_H("Set extended property rules in WLAN\n"); + + if (rx_prop == NULL) + { + IPACMDBG_H("No rx properties registered for iface %s\n", dev_name); + return IPACM_SUCCESS; + } + + if(prop == NULL || prop->num_ext_props <= 0) + { + IPACMDBG_H("No extended property.\n"); + return IPACM_SUCCESS; + } + + if(wlan_ap_index > 0) + { + IPACMDBG_H("This is not the first WLAN AP, do not install modem UL rules.\n"); + return IPACM_SUCCESS; + } + + fd = open(IPA_DEVICE_NAME, O_RDWR); + if (0 == fd) + { + IPACMERR("Failed opening %s.\n", IPA_DEVICE_NAME); + return IPACM_FAILURE; + } + if (prop->num_ext_props > MAX_WAN_UL_FILTER_RULES) + { + IPACMERR("number of modem UL rules > MAX_WAN_UL_FILTER_RULES, aborting...\n"); + close(fd); + return IPACM_FAILURE; + } + + memset(&flt_index, 0, sizeof(flt_index)); + flt_index.source_pipe_index = ioctl(fd, IPA_IOC_QUERY_EP_MAPPING, rx_prop->rx[0].src_pipe); + flt_index.install_status = IPA_QMI_RESULT_SUCCESS_V01; +#ifndef FEATURE_IPA_V3 + flt_index.filter_index_list_len = prop->num_ext_props; +#else /* defined (FEATURE_IPA_V3) */ + flt_index.rule_id_valid = 1; + flt_index.rule_id_len = prop->num_ext_props; +#endif + flt_index.embedded_pipe_index_valid = 1; + flt_index.embedded_pipe_index = ioctl(fd, IPA_IOC_QUERY_EP_MAPPING, IPA_CLIENT_APPS_LAN_WAN_PROD); + flt_index.retain_header_valid = 1; + flt_index.retain_header = 0; + flt_index.embedded_call_mux_id_valid = 1; + flt_index.embedded_call_mux_id = IPACM_Iface::ipacmcfg->GetQmapId(); +#ifndef FEATURE_IPA_V3 + IPACMDBG_H("flt_index: src pipe: %d, num of rules: %d, ebd pipe: %d, mux id: %d\n", + flt_index.source_pipe_index, flt_index.filter_index_list_len, flt_index.embedded_pipe_index, flt_index.embedded_call_mux_id); +#else /* defined (FEATURE_IPA_V3) */ + IPACMDBG_H("flt_index: src pipe: %d, num of rules: %d, ebd pipe: %d, mux id: %d\n", + flt_index.source_pipe_index, flt_index.rule_id_len, flt_index.embedded_pipe_index, flt_index.embedded_call_mux_id); +#endif + len = sizeof(struct ipa_ioc_add_flt_rule) + prop->num_ext_props * sizeof(struct ipa_flt_rule_add); + pFilteringTable = (struct ipa_ioc_add_flt_rule*)malloc(len); + if (pFilteringTable == NULL) + { + IPACMERR("Error Locate ipa_flt_rule_add memory...\n"); + close(fd); + return IPACM_FAILURE; + } + memset(pFilteringTable, 0, len); + + pFilteringTable->commit = 1; + pFilteringTable->ep = rx_prop->rx[0].src_pipe; + pFilteringTable->global = false; + pFilteringTable->ip = iptype; + pFilteringTable->num_rules = prop->num_ext_props; + + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); // Zero All Fields + flt_rule_entry.at_rear = 1; +#ifdef FEATURE_IPA_V3 + if (flt_rule_entry.rule.eq_attrib.ipv4_frag_eq_present) + flt_rule_entry.at_rear = 0; +#endif + flt_rule_entry.flt_rule_hdl = -1; + flt_rule_entry.status = -1; + + flt_rule_entry.rule.retain_hdr = 0; + flt_rule_entry.rule.to_uc = 0; + flt_rule_entry.rule.eq_attrib_type = 1; + if(iptype == IPA_IP_v4) + flt_rule_entry.rule.action = IPA_PASS_TO_SRC_NAT; + else if(iptype == IPA_IP_v6) + flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING; + else + { + IPACMERR("IP type is not expected.\n"); + ret = IPACM_FAILURE; + goto fail; + } + + index = IPACM_Iface::ipacmcfg->getFltRuleCount(rx_prop->rx[0].src_pipe, iptype); + +#ifndef FEATURE_IPA_ANDROID + if(iptype == IPA_IP_v4 && index != exp_index_v4) + { + IPACMDBG_DMESG("### WARNING ### num flt rules for IPv4 on client %d is not expected: %d expected value: %d", + rx_prop->rx[0].src_pipe, index, exp_index_v4); + } + if(iptype == IPA_IP_v6 && index != exp_index_v6) + { + IPACMDBG_DMESG("### WARNING ### num flt rules for IPv6 on client %d is not expected: %d expected value: %d", + rx_prop->rx[0].src_pipe, index, exp_index_v6); + } +#endif + + for(cnt=0; cntnum_ext_props; cnt++) + { + memcpy(&flt_rule_entry.rule.eq_attrib, + &prop->prop[cnt].eq_attrib, + sizeof(prop->prop[cnt].eq_attrib)); + flt_rule_entry.rule.rt_tbl_idx = prop->prop[cnt].rt_tbl_idx; + + /* Handle XLAT configuration */ + if ((iptype == IPA_IP_v4) && prop->prop[cnt].is_xlat_rule && (xlat_mux_id != 0)) + { + /* fill the value of meta-data */ + value = xlat_mux_id; + flt_rule_entry.rule.eq_attrib.metadata_meq32_present = 1; + flt_rule_entry.rule.eq_attrib.metadata_meq32.offset = 0; + flt_rule_entry.rule.eq_attrib.metadata_meq32.value = (value & 0xFF) << 16; + flt_rule_entry.rule.eq_attrib.metadata_meq32.mask = 0x00FF0000; + IPACMDBG_H("xlat meta-data is modified for rule: %d has index: %d with xlat_mux_id: %d\n", + cnt, index, xlat_mux_id); + } +#ifdef FEATURE_IPA_V3 + flt_rule_entry.rule.hashable = prop->prop[cnt].is_rule_hashable; + flt_rule_entry.rule.rule_id = prop->prop[cnt].rule_id; +#endif + memcpy(&pFilteringTable->rules[cnt], &flt_rule_entry, sizeof(flt_rule_entry)); + + IPACMDBG_H("Modem UL filtering rule %d has index %d\n", cnt, index); +#ifndef FEATURE_IPA_V3 + flt_index.filter_index_list[cnt].filter_index = index; + flt_index.filter_index_list[cnt].filter_handle = prop->prop[cnt].filter_hdl; +#else /* defined (FEATURE_IPA_V3) */ + flt_index.rule_id[cnt] = prop->prop[cnt].rule_id; +#endif + index++; + } + + if(false == m_filtering.SendFilteringRuleIndex(&flt_index)) + { + IPACMERR("Error sending filtering rule index, aborting...\n"); + ret = IPACM_FAILURE; + goto fail; + } + + if(false == m_filtering.AddFilteringRule(pFilteringTable)) + { + IPACMERR("Error Adding RuleTable to Filtering, aborting...\n"); + ret = IPACM_FAILURE; + goto fail; + } + else + { + if(iptype == IPA_IP_v4) + { + for(i=0; inum_rules; i++) + { + wan_ul_fl_rule_hdl_v4[num_wan_ul_fl_rule_v4] = pFilteringTable->rules[i].flt_rule_hdl; + num_wan_ul_fl_rule_v4++; + } + IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, iptype, pFilteringTable->num_rules); + } + else if(iptype == IPA_IP_v6) + { + for(i=0; inum_rules; i++) + { + wan_ul_fl_rule_hdl_v6[num_wan_ul_fl_rule_v6] = pFilteringTable->rules[i].flt_rule_hdl; + num_wan_ul_fl_rule_v6++; + } + IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, iptype, pFilteringTable->num_rules); + } + else + { + IPACMERR("IP type is not expected.\n"); + goto fail; + } + } + +fail: + free(pFilteringTable); + close(fd); + return ret; +} + +/* handle wifi client initial,copy all partial headers (tx property) */ +int IPACM_Wlan::handle_wlan_client_init_ex(ipacm_event_data_wlan_ex *data) +{ + +#define WLAN_IFACE_INDEX_LEN 2 + + int res = IPACM_SUCCESS, len = 0, i, evt_size; + char index[WLAN_IFACE_INDEX_LEN]; + struct ipa_ioc_copy_hdr sCopyHeader; + struct ipa_ioc_add_hdr *pHeaderDescriptor = NULL; + uint32_t cnt; + + /* start of adding header */ + IPACMDBG_H("Wifi client number for this iface: %d & total number of wlan clients: %d\n", + num_wifi_client,IPACM_Wlan::total_num_wifi_clients); + + if ((num_wifi_client >= IPA_MAX_NUM_WIFI_CLIENTS) || + (IPACM_Wlan::total_num_wifi_clients >= IPA_MAX_NUM_WIFI_CLIENTS)) + { + IPACMERR("Reached maximum number of wlan clients\n"); + return IPACM_FAILURE; + } + + IPACMDBG_H("Wifi client number: %d\n", num_wifi_client); + + /* add header to IPA */ + if(tx_prop != NULL) + { + len = sizeof(struct ipa_ioc_add_hdr) + (1 * sizeof(struct ipa_hdr_add)); + pHeaderDescriptor = (struct ipa_ioc_add_hdr *)calloc(1, len); + if (pHeaderDescriptor == NULL) + { + IPACMERR("calloc failed to allocate pHeaderDescriptor\n"); + return IPACM_FAILURE; + } + + evt_size = sizeof(ipacm_event_data_wlan_ex) + data->num_of_attribs * sizeof(struct ipa_wlan_hdr_attrib_val); + get_client_memptr(wlan_client, num_wifi_client)->p_hdr_info = (ipacm_event_data_wlan_ex*)malloc(evt_size); + memcpy(get_client_memptr(wlan_client, num_wifi_client)->p_hdr_info, data, evt_size); + + /* copy partial header for v4*/ + for (cnt=0; cntnum_tx_props; cnt++) + { + if(tx_prop->tx[cnt].ip==IPA_IP_v4) + { + IPACMDBG_H("Got partial v4-header name from %d tx props\n", cnt); + memset(&sCopyHeader, 0, sizeof(sCopyHeader)); + memcpy(sCopyHeader.name, + tx_prop->tx[cnt].hdr_name, + sizeof(sCopyHeader.name)); + + IPACMDBG_H("header name: %s in tx:%d\n", sCopyHeader.name,cnt); + if (m_header.CopyHeader(&sCopyHeader) == false) + { + PERROR("ioctl copy header failed"); + res = IPACM_FAILURE; + goto fail; + } + + IPACMDBG_H("header length: %d, paritial: %d\n", sCopyHeader.hdr_len, sCopyHeader.is_partial); + if (sCopyHeader.hdr_len > IPA_HDR_MAX_SIZE) + { + IPACMERR("header oversize\n"); + res = IPACM_FAILURE; + goto fail; + } + else + { + memcpy(pHeaderDescriptor->hdr[0].hdr, + sCopyHeader.hdr, + sCopyHeader.hdr_len); + } + + for(i = 0; i < data->num_of_attribs; i++) + { + if(data->attribs[i].attrib_type == WLAN_HDR_ATTRIB_MAC_ADDR) + { + memcpy(get_client_memptr(wlan_client, num_wifi_client)->mac, + data->attribs[i].u.mac_addr, + sizeof(get_client_memptr(wlan_client, num_wifi_client)->mac)); + + /* copy client mac_addr to partial header */ + memcpy(&pHeaderDescriptor->hdr[0].hdr[data->attribs[i].offset], + get_client_memptr(wlan_client, num_wifi_client)->mac, + IPA_MAC_ADDR_SIZE); + /* replace src mac to bridge mac_addr if any */ + if (IPACM_Iface::ipacmcfg->ipa_bridge_enable) + { + memcpy(&pHeaderDescriptor->hdr[0].hdr[data->attribs[i].offset+IPA_MAC_ADDR_SIZE], + IPACM_Iface::ipacmcfg->bridge_mac, + IPA_MAC_ADDR_SIZE); + IPACMDBG_H("device is in bridge mode \n"); + } + + } + else if(data->attribs[i].attrib_type == WLAN_HDR_ATTRIB_STA_ID) + { + /* copy client id to header */ + memcpy(&pHeaderDescriptor->hdr[0].hdr[data->attribs[i].offset], + &data->attribs[i].u.sta_id, sizeof(data->attribs[i].u.sta_id)); + } + else + { + IPACMDBG_H("The attribute type is not expected!\n"); + } + } + + pHeaderDescriptor->commit = true; + pHeaderDescriptor->num_hdrs = 1; + + memset(pHeaderDescriptor->hdr[0].name, 0, + sizeof(pHeaderDescriptor->hdr[0].name)); + + snprintf(index,sizeof(index), "%d", ipa_if_num); + strlcpy(pHeaderDescriptor->hdr[0].name, index, sizeof(pHeaderDescriptor->hdr[0].name)); + pHeaderDescriptor->hdr[0].name[IPA_RESOURCE_NAME_MAX-1] = '\0'; + + if (strlcat(pHeaderDescriptor->hdr[0].name, IPA_WLAN_PARTIAL_HDR_NAME_v4, sizeof(pHeaderDescriptor->hdr[0].name)) > IPA_RESOURCE_NAME_MAX) + { + IPACMERR(" header name construction failed exceed length (%d)\n", strlen(pHeaderDescriptor->hdr[0].name)); + res = IPACM_FAILURE; + goto fail; + } + snprintf(index,sizeof(index), "%d", header_name_count); + if (strlcat(pHeaderDescriptor->hdr[0].name, index, sizeof(pHeaderDescriptor->hdr[0].name)) > IPA_RESOURCE_NAME_MAX) + { + IPACMERR(" header name construction failed exceed length (%d)\n", strlen(pHeaderDescriptor->hdr[0].name)); + res = IPACM_FAILURE; + goto fail; + } + + + pHeaderDescriptor->hdr[0].hdr_len = sCopyHeader.hdr_len; + pHeaderDescriptor->hdr[0].hdr_hdl = -1; + pHeaderDescriptor->hdr[0].is_partial = 0; + pHeaderDescriptor->hdr[0].status = -1; + + if (m_header.AddHeader(pHeaderDescriptor) == false || + pHeaderDescriptor->hdr[0].status != 0) + { + IPACMERR("ioctl IPA_IOC_ADD_HDR failed: %d\n", pHeaderDescriptor->hdr[0].status); + res = IPACM_FAILURE; + goto fail; + } + + get_client_memptr(wlan_client, num_wifi_client)->hdr_hdl_v4 = pHeaderDescriptor->hdr[0].hdr_hdl; + IPACMDBG_H("client(%d) v4 full header name:%s header handle:(0x%x)\n", + num_wifi_client, + pHeaderDescriptor->hdr[0].name, + get_client_memptr(wlan_client, num_wifi_client)->hdr_hdl_v4); + get_client_memptr(wlan_client, num_wifi_client)->ipv4_header_set=true; + break; + } + } + + /* copy partial header for v6*/ + for (cnt=0; cntnum_tx_props; cnt++) + { + if(tx_prop->tx[cnt].ip==IPA_IP_v6) + { + IPACMDBG_H("Got partial v6-header name from %d tx props\n", cnt); + memset(&sCopyHeader, 0, sizeof(sCopyHeader)); + memcpy(sCopyHeader.name, + tx_prop->tx[cnt].hdr_name, + sizeof(sCopyHeader.name)); + + IPACMDBG_H("header name: %s in tx:%d\n", sCopyHeader.name,cnt); + if (m_header.CopyHeader(&sCopyHeader) == false) + { + PERROR("ioctl copy header failed"); + res = IPACM_FAILURE; + goto fail; + } + + IPACMDBG_H("header length: %d, paritial: %d\n", sCopyHeader.hdr_len, sCopyHeader.is_partial); + if (sCopyHeader.hdr_len > IPA_HDR_MAX_SIZE) + { + IPACMERR("header oversize\n"); + res = IPACM_FAILURE; + goto fail; + } + else + { + memcpy(pHeaderDescriptor->hdr[0].hdr, + sCopyHeader.hdr, + sCopyHeader.hdr_len); + } + + for(i = 0; i < data->num_of_attribs; i++) + { + if(data->attribs[i].attrib_type == WLAN_HDR_ATTRIB_MAC_ADDR) + { + memcpy(get_client_memptr(wlan_client, num_wifi_client)->mac, + data->attribs[i].u.mac_addr, + sizeof(get_client_memptr(wlan_client, num_wifi_client)->mac)); + + /* copy client mac_addr to partial header */ + memcpy(&pHeaderDescriptor->hdr[0].hdr[data->attribs[i].offset], + get_client_memptr(wlan_client, num_wifi_client)->mac, + IPA_MAC_ADDR_SIZE); + + /* replace src mac to bridge mac_addr if any */ + if (IPACM_Iface::ipacmcfg->ipa_bridge_enable) + { + memcpy(&pHeaderDescriptor->hdr[0].hdr[data->attribs[i].offset+IPA_MAC_ADDR_SIZE], + IPACM_Iface::ipacmcfg->bridge_mac, + IPA_MAC_ADDR_SIZE); + IPACMDBG_H("device is in bridge mode \n"); + } + } + else if (data->attribs[i].attrib_type == WLAN_HDR_ATTRIB_STA_ID) + { + /* copy client id to header */ + memcpy(&pHeaderDescriptor->hdr[0].hdr[data->attribs[i].offset], + &data->attribs[i].u.sta_id, sizeof(data->attribs[i].u.sta_id)); + } + else + { + IPACMDBG_H("The attribute type is not expected!\n"); + } + } + + pHeaderDescriptor->commit = true; + pHeaderDescriptor->num_hdrs = 1; + + memset(pHeaderDescriptor->hdr[0].name, 0, + sizeof(pHeaderDescriptor->hdr[0].name)); + + snprintf(index,sizeof(index), "%d", ipa_if_num); + strlcpy(pHeaderDescriptor->hdr[0].name, index, sizeof(pHeaderDescriptor->hdr[0].name)); + pHeaderDescriptor->hdr[0].name[IPA_RESOURCE_NAME_MAX-1] = '\0'; + if (strlcat(pHeaderDescriptor->hdr[0].name, IPA_WLAN_PARTIAL_HDR_NAME_v6, sizeof(pHeaderDescriptor->hdr[0].name)) > IPA_RESOURCE_NAME_MAX) + { + IPACMERR(" header name construction failed exceed length (%d)\n", strlen(pHeaderDescriptor->hdr[0].name)); + res = IPACM_FAILURE; + goto fail; + } + + snprintf(index,sizeof(index), "%d", header_name_count); + if (strlcat(pHeaderDescriptor->hdr[0].name, index, sizeof(pHeaderDescriptor->hdr[0].name)) > IPA_RESOURCE_NAME_MAX) + { + IPACMERR(" header name construction failed exceed length (%d)\n", strlen(pHeaderDescriptor->hdr[0].name)); + res = IPACM_FAILURE; + goto fail; + } + + pHeaderDescriptor->hdr[0].hdr_len = sCopyHeader.hdr_len; + pHeaderDescriptor->hdr[0].hdr_hdl = -1; + pHeaderDescriptor->hdr[0].is_partial = 0; + pHeaderDescriptor->hdr[0].status = -1; + + if (m_header.AddHeader(pHeaderDescriptor) == false || + pHeaderDescriptor->hdr[0].status != 0) + { + IPACMERR("ioctl IPA_IOC_ADD_HDR failed: %d\n", pHeaderDescriptor->hdr[0].status); + res = IPACM_FAILURE; + goto fail; + } + + get_client_memptr(wlan_client, num_wifi_client)->hdr_hdl_v6 = pHeaderDescriptor->hdr[0].hdr_hdl; + IPACMDBG_H("client(%d) v6 full header name:%s header handle:(0x%x)\n", + num_wifi_client, + pHeaderDescriptor->hdr[0].name, + get_client_memptr(wlan_client, num_wifi_client)->hdr_hdl_v6); + + get_client_memptr(wlan_client, num_wifi_client)->ipv6_header_set=true; + break; + } + } + + /* initialize wifi client*/ + get_client_memptr(wlan_client, num_wifi_client)->route_rule_set_v4 = false; + get_client_memptr(wlan_client, num_wifi_client)->route_rule_set_v6 = 0; + get_client_memptr(wlan_client, num_wifi_client)->ipv4_set = false; + get_client_memptr(wlan_client, num_wifi_client)->ipv6_set = 0; + get_client_memptr(wlan_client, num_wifi_client)->power_save_set=false; + num_wifi_client++; + header_name_count++; //keep increasing header_name_count + IPACM_Wlan::total_num_wifi_clients++; + res = IPACM_SUCCESS; + IPACMDBG_H("Wifi client number: %d\n", num_wifi_client); + } + else + { + return res; + } + +fail: + free(pHeaderDescriptor); + return res; +} + +/*handle wifi client */ +int IPACM_Wlan::handle_wlan_client_ipaddr(ipacm_event_data_all *data) +{ + int clnt_indx; + int v6_num; + + IPACMDBG_H("number of wifi clients: %d\n", num_wifi_client); + IPACMDBG_H(" event MAC %02x:%02x:%02x:%02x:%02x:%02x\n", + data->mac_addr[0], + data->mac_addr[1], + data->mac_addr[2], + data->mac_addr[3], + data->mac_addr[4], + data->mac_addr[5]); + + clnt_indx = get_wlan_client_index(data->mac_addr); + + if (clnt_indx == IPACM_INVALID_INDEX) + { + IPACMERR("wlan client not found/attached \n"); + return IPACM_FAILURE; + } + + IPACMDBG_H("Ip-type received %d\n", data->iptype); + if (data->iptype == IPA_IP_v4) + { + IPACMDBG_H("ipv4 address: 0x%x\n", data->ipv4_addr); + if (data->ipv4_addr != 0) /* not 0.0.0.0 */ + { + if (get_client_memptr(wlan_client, clnt_indx)->ipv4_set == false) + { + get_client_memptr(wlan_client, clnt_indx)->v4_addr = data->ipv4_addr; + get_client_memptr(wlan_client, clnt_indx)->ipv4_set = true; + } + else + { + /* check if client got new IPv4 address*/ + if(data->ipv4_addr == get_client_memptr(wlan_client, clnt_indx)->v4_addr) + { + IPACMDBG_H("Already setup ipv4 addr for client:%d, ipv4 address didn't change\n", clnt_indx); + return IPACM_FAILURE; + } + else + { + IPACMDBG_H("ipv4 addr for client:%d is changed \n", clnt_indx); + /* delete NAT rules first */ + CtList->HandleNeighIpAddrDelEvt(get_client_memptr(wlan_client, clnt_indx)->v4_addr); + delete_default_qos_rtrules(clnt_indx,IPA_IP_v4); + get_client_memptr(wlan_client, clnt_indx)->route_rule_set_v4 = false; + get_client_memptr(wlan_client, clnt_indx)->v4_addr = data->ipv4_addr; + } + } + } + else + { + IPACMDBG_H("Invalid client IPv4 address \n"); + return IPACM_FAILURE; + } + } + else + { + if ((data->ipv6_addr[0] != 0) || (data->ipv6_addr[1] != 0) || + (data->ipv6_addr[2] != 0) || (data->ipv6_addr[3] || 0)) /* check if all 0 not valid ipv6 address */ + { + IPACMDBG_H("ipv6 address: 0x%x:%x:%x:%x\n", data->ipv6_addr[0], data->ipv6_addr[1], data->ipv6_addr[2], data->ipv6_addr[3]); + if(get_client_memptr(wlan_client, clnt_indx)->ipv6_set < IPV6_NUM_ADDR) + { + + for(v6_num=0;v6_num < get_client_memptr(wlan_client, clnt_indx)->ipv6_set;v6_num++) + { + if( data->ipv6_addr[0] == get_client_memptr(wlan_client, clnt_indx)->v6_addr[v6_num][0] && + data->ipv6_addr[1] == get_client_memptr(wlan_client, clnt_indx)->v6_addr[v6_num][1] && + data->ipv6_addr[2]== get_client_memptr(wlan_client, clnt_indx)->v6_addr[v6_num][2] && + data->ipv6_addr[3] == get_client_memptr(wlan_client, clnt_indx)->v6_addr[v6_num][3]) + { + IPACMDBG_H("Already see this ipv6 addr for client:%d\n", clnt_indx); + return IPACM_FAILURE; /* not setup the RT rules*/ + break; + } + } + + /* not see this ipv6 before for wifi client*/ + get_client_memptr(wlan_client, clnt_indx)->v6_addr[get_client_memptr(wlan_client, clnt_indx)->ipv6_set][0] = data->ipv6_addr[0]; + get_client_memptr(wlan_client, clnt_indx)->v6_addr[get_client_memptr(wlan_client, clnt_indx)->ipv6_set][1] = data->ipv6_addr[1]; + get_client_memptr(wlan_client, clnt_indx)->v6_addr[get_client_memptr(wlan_client, clnt_indx)->ipv6_set][2] = data->ipv6_addr[2]; + get_client_memptr(wlan_client, clnt_indx)->v6_addr[get_client_memptr(wlan_client, clnt_indx)->ipv6_set][3] = data->ipv6_addr[3]; + get_client_memptr(wlan_client, clnt_indx)->ipv6_set++; + } + else + { + IPACMDBG_H("Already got 3 ipv6 addr for client:%d\n", clnt_indx); + return IPACM_FAILURE; /* not setup the RT rules*/ + } + } + } + + return IPACM_SUCCESS; +} + +/*handle wifi client routing rule*/ +int IPACM_Wlan::handle_wlan_client_route_rule(uint8_t *mac_addr, ipa_ip_type iptype) +{ + struct ipa_ioc_add_rt_rule *rt_rule; + struct ipa_rt_rule_add *rt_rule_entry; + uint32_t tx_index; + int wlan_index,v6_num; + const int NUM = 1; + + if(tx_prop == NULL) + { + IPACMDBG_H("No rx properties registered for iface %s\n", dev_name); + return IPACM_SUCCESS; + } + + IPACMDBG_H("Received mac_addr MAC %02x:%02x:%02x:%02x:%02x:%02x\n", + mac_addr[0], mac_addr[1], mac_addr[2], + mac_addr[3], mac_addr[4], mac_addr[5]); + + wlan_index = get_wlan_client_index(mac_addr); + if (wlan_index == IPACM_INVALID_INDEX) + { + IPACMDBG_H("wlan client not found/attached \n"); + return IPACM_SUCCESS; + } + + /* during power_save mode, even receive IP_ADDR_ADD, not setting RT rules*/ + if (get_client_memptr(wlan_client, wlan_index)->power_save_set == true) + { + IPACMDBG_H("wlan client is in power safe mode \n"); + return IPACM_SUCCESS; + } + + if (iptype==IPA_IP_v4) + { + IPACMDBG_H("wlan client index: %d, ip-type: %d, ipv4_set:%d, ipv4_rule_set:%d \n", wlan_index, iptype, + get_client_memptr(wlan_client, wlan_index)->ipv4_set, + get_client_memptr(wlan_client, wlan_index)->route_rule_set_v4); + } + else + { + IPACMDBG_H("wlan client index: %d, ip-type: %d, ipv6_set:%d, ipv6_rule_num:%d \n", wlan_index, iptype, + get_client_memptr(wlan_client, wlan_index)->ipv6_set, + get_client_memptr(wlan_client, wlan_index)->route_rule_set_v6); + } + + + /* Add default Qos routing rules if not set yet */ + if ((iptype == IPA_IP_v4 + && get_client_memptr(wlan_client, wlan_index)->route_rule_set_v4 == false + && get_client_memptr(wlan_client, wlan_index)->ipv4_set == true) + || (iptype == IPA_IP_v6 + && get_client_memptr(wlan_client, wlan_index)->route_rule_set_v6 < get_client_memptr(wlan_client, wlan_index)->ipv6_set + )) + { + rt_rule = (struct ipa_ioc_add_rt_rule *) + calloc(1, sizeof(struct ipa_ioc_add_rt_rule) + + NUM * sizeof(struct ipa_rt_rule_add)); + + if (rt_rule == NULL) + { + PERROR("Error Locate ipa_ioc_add_rt_rule memory...\n"); + return IPACM_FAILURE; + } + + rt_rule->commit = 1; + rt_rule->num_rules = (uint8_t)NUM; + rt_rule->ip = iptype; + + + for (tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++) + { + + if(iptype != tx_prop->tx[tx_index].ip) + { + IPACMDBG_H("Tx:%d, ip-type: %d conflict ip-type: %d no RT-rule added\n", + tx_index, tx_prop->tx[tx_index].ip,iptype); + continue; + } + + rt_rule_entry = &rt_rule->rules[0]; + rt_rule_entry->at_rear = 0; + + if (iptype == IPA_IP_v4) + { + IPACMDBG_H("client index(%d):ipv4 address: 0x%x\n", wlan_index, + get_client_memptr(wlan_client, wlan_index)->v4_addr); + + IPACMDBG_H("client(%d): v4 header handle:(0x%x)\n", + wlan_index, + get_client_memptr(wlan_client, wlan_index)->hdr_hdl_v4); + strlcpy(rt_rule->rt_tbl_name, + IPACM_Iface::ipacmcfg->rt_tbl_lan_v4.name, + sizeof(rt_rule->rt_tbl_name)); + rt_rule->rt_tbl_name[IPA_RESOURCE_NAME_MAX-1] = '\0'; + + if(IPACM_Iface::ipacmcfg->isMCC_Mode) + { + IPACMDBG_H("In MCC mode, use alt dst pipe: %d\n", + tx_prop->tx[tx_index].alt_dst_pipe); + rt_rule_entry->rule.dst = tx_prop->tx[tx_index].alt_dst_pipe; + } + else + { + rt_rule_entry->rule.dst = tx_prop->tx[tx_index].dst_pipe; + } + + memcpy(&rt_rule_entry->rule.attrib, + &tx_prop->tx[tx_index].attrib, + sizeof(rt_rule_entry->rule.attrib)); + rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; + rt_rule_entry->rule.hdr_hdl = get_client_memptr(wlan_client, wlan_index)->hdr_hdl_v4; + rt_rule_entry->rule.attrib.u.v4.dst_addr = get_client_memptr(wlan_client, wlan_index)->v4_addr; + rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF; + if (false == m_routing.AddRoutingRule(rt_rule)) + { + IPACMERR("Routing rule addition failed!\n"); + free(rt_rule); + return IPACM_FAILURE; + } + + /* copy ipv4 RT hdl */ + get_client_memptr(wlan_client, wlan_index)->wifi_rt_hdl[tx_index].wifi_rt_rule_hdl_v4 = + rt_rule->rules[0].rt_rule_hdl; + IPACMDBG_H("tx:%d, rt rule hdl=%x ip-type: %d\n", tx_index, + get_client_memptr(wlan_client, wlan_index)->wifi_rt_hdl[tx_index].wifi_rt_rule_hdl_v4, iptype); + } + else + { + for(v6_num = get_client_memptr(wlan_client, wlan_index)->route_rule_set_v6;v6_num < get_client_memptr(wlan_client, wlan_index)->ipv6_set;v6_num++) + { + IPACMDBG_H("client(%d): v6 header handle:(0x%x)\n", + wlan_index, + get_client_memptr(wlan_client, wlan_index)->hdr_hdl_v6); + + /* v6 LAN_RT_TBL */ + strlcpy(rt_rule->rt_tbl_name, + IPACM_Iface::ipacmcfg->rt_tbl_v6.name, + sizeof(rt_rule->rt_tbl_name)); + rt_rule->rt_tbl_name[IPA_RESOURCE_NAME_MAX-1] = '\0'; + /* Support QCMAP LAN traffic feature, send to A5 */ + rt_rule_entry->rule.dst = iface_query->excp_pipe; + memset(&rt_rule_entry->rule.attrib, 0, sizeof(rt_rule_entry->rule.attrib)); + rt_rule_entry->rule.hdr_hdl = 0; + rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = get_client_memptr(wlan_client, wlan_index)->v6_addr[v6_num][0]; + rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = get_client_memptr(wlan_client, wlan_index)->v6_addr[v6_num][1]; + rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = get_client_memptr(wlan_client, wlan_index)->v6_addr[v6_num][2]; + rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = get_client_memptr(wlan_client, wlan_index)->v6_addr[v6_num][3]; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF; + if (false == m_routing.AddRoutingRule(rt_rule)) + { + IPACMERR("Routing rule addition failed!\n"); + free(rt_rule); + return IPACM_FAILURE; + } + + get_client_memptr(wlan_client, wlan_index)->wifi_rt_hdl[tx_index].wifi_rt_rule_hdl_v6[v6_num] = rt_rule->rules[0].rt_rule_hdl; + IPACMDBG_H("tx:%d, rt rule hdl=%x ip-type: %d\n", tx_index, + get_client_memptr(wlan_client, wlan_index)->wifi_rt_hdl[tx_index].wifi_rt_rule_hdl_v6[v6_num], iptype); + + /*Copy same rule to v6 WAN RT TBL*/ + strlcpy(rt_rule->rt_tbl_name, + IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.name, + sizeof(rt_rule->rt_tbl_name)); + rt_rule->rt_tbl_name[IPA_RESOURCE_NAME_MAX-1] = '\0'; + /* Downlink traffic from Wan iface, directly through IPA */ + if(IPACM_Iface::ipacmcfg->isMCC_Mode) + { + IPACMDBG_H("In MCC mode, use alt dst pipe: %d\n", + tx_prop->tx[tx_index].alt_dst_pipe); + rt_rule_entry->rule.dst = tx_prop->tx[tx_index].alt_dst_pipe; + } + else + { + rt_rule_entry->rule.dst = tx_prop->tx[tx_index].dst_pipe; + } + memcpy(&rt_rule_entry->rule.attrib, + &tx_prop->tx[tx_index].attrib, + sizeof(rt_rule_entry->rule.attrib)); + rt_rule_entry->rule.hdr_hdl = get_client_memptr(wlan_client, wlan_index)->hdr_hdl_v6; + rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = get_client_memptr(wlan_client, wlan_index)->v6_addr[v6_num][0]; + rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = get_client_memptr(wlan_client, wlan_index)->v6_addr[v6_num][1]; + rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = get_client_memptr(wlan_client, wlan_index)->v6_addr[v6_num][2]; + rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = get_client_memptr(wlan_client, wlan_index)->v6_addr[v6_num][3]; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF; + if (false == m_routing.AddRoutingRule(rt_rule)) + { + IPACMERR("Routing rule addition failed!\n"); + free(rt_rule); + return IPACM_FAILURE; + } + + get_client_memptr(wlan_client, wlan_index)->wifi_rt_hdl[tx_index].wifi_rt_rule_hdl_v6_wan[v6_num] = rt_rule->rules[0].rt_rule_hdl; + + IPACMDBG_H("tx:%d, rt rule hdl=%x ip-type: %d\n", tx_index, + get_client_memptr(wlan_client, wlan_index)->wifi_rt_hdl[tx_index].wifi_rt_rule_hdl_v6_wan[v6_num], iptype); + } + } + + } /* end of for loop */ + + free(rt_rule); + + if (iptype == IPA_IP_v4) + { + get_client_memptr(wlan_client, wlan_index)->route_rule_set_v4 = true; + } + else + { + get_client_memptr(wlan_client, wlan_index)->route_rule_set_v6 = get_client_memptr(wlan_client, wlan_index)->ipv6_set; + } + } + + return IPACM_SUCCESS; +} + +/*handle wifi client power-save mode*/ +int IPACM_Wlan::handle_wlan_client_pwrsave(uint8_t *mac_addr) +{ + int clt_indx; + IPACMDBG_H("wlan->handle_wlan_client_pwrsave();\n"); + + clt_indx = get_wlan_client_index(mac_addr); + if (clt_indx == IPACM_INVALID_INDEX) + { + IPACMDBG_H("wlan client not attached\n"); + return IPACM_SUCCESS; + } + + if (get_client_memptr(wlan_client, clt_indx)->power_save_set == false) + { + /* First reset nat rules and then route rules */ + if(get_client_memptr(wlan_client, clt_indx)->ipv4_set == true) + { + IPACMDBG_H("Deleting Nat Rules\n"); + Nat_App->UpdatePwrSaveIf(get_client_memptr(wlan_client, clt_indx)->v4_addr); + } + + IPACMDBG_H("Deleting default qos Route Rules\n"); + delete_default_qos_rtrules(clt_indx, IPA_IP_v4); + delete_default_qos_rtrules(clt_indx, IPA_IP_v6); + get_client_memptr(wlan_client, clt_indx)->power_save_set = true; + } + else + { + IPACMDBG_H("wlan client already in power-save mode\n"); + } + return IPACM_SUCCESS; +} + +/*handle wifi client del mode*/ +int IPACM_Wlan::handle_wlan_client_down_evt(uint8_t *mac_addr) +{ + int clt_indx; + uint32_t tx_index; + int num_wifi_client_tmp = num_wifi_client; + int num_v6; + + IPACMDBG_H("total client: %d\n", num_wifi_client_tmp); + + clt_indx = get_wlan_client_index(mac_addr); + if (clt_indx == IPACM_INVALID_INDEX) + { + IPACMDBG_H("wlan client not attached\n"); + return IPACM_SUCCESS; + } + + /* First reset nat rules and then route rules */ + if(get_client_memptr(wlan_client, clt_indx)->ipv4_set == true) + { + IPACMDBG_H("Clean Nat Rules for ipv4:0x%x\n", get_client_memptr(wlan_client, clt_indx)->v4_addr); + CtList->HandleNeighIpAddrDelEvt(get_client_memptr(wlan_client, clt_indx)->v4_addr); + } + + if (delete_default_qos_rtrules(clt_indx, IPA_IP_v4)) + { + IPACMERR("unbale to delete v4 default qos route rules for index: %d\n", clt_indx); + return IPACM_FAILURE; + } + + if (delete_default_qos_rtrules(clt_indx, IPA_IP_v6)) + { + IPACMERR("unbale to delete v6 default qos route rules for indexn: %d\n", clt_indx); + return IPACM_FAILURE; + } + + /* Delete wlan client header */ + if(get_client_memptr(wlan_client, clt_indx)->ipv4_header_set == true) + { + if (m_header.DeleteHeaderHdl(get_client_memptr(wlan_client, clt_indx)->hdr_hdl_v4) + == false) + { + return IPACM_FAILURE; + } + get_client_memptr(wlan_client, clt_indx)->ipv4_header_set = false; + } + + if(get_client_memptr(wlan_client, clt_indx)->ipv6_header_set == true) + { + if (m_header.DeleteHeaderHdl(get_client_memptr(wlan_client, clt_indx)->hdr_hdl_v6) + == false) + { + return IPACM_FAILURE; + } + get_client_memptr(wlan_client, clt_indx)->ipv6_header_set = false; + } + + /* Reset ip_set to 0*/ + get_client_memptr(wlan_client, clt_indx)->ipv4_set = false; + get_client_memptr(wlan_client, clt_indx)->ipv6_set = 0; + get_client_memptr(wlan_client, clt_indx)->ipv4_header_set = false; + get_client_memptr(wlan_client, clt_indx)->ipv6_header_set = false; + get_client_memptr(wlan_client, clt_indx)->route_rule_set_v4 = false; + get_client_memptr(wlan_client, clt_indx)->route_rule_set_v6 = 0; + free(get_client_memptr(wlan_client, clt_indx)->p_hdr_info); + + for (; clt_indx < num_wifi_client_tmp - 1; clt_indx++) + { + get_client_memptr(wlan_client, clt_indx)->p_hdr_info = get_client_memptr(wlan_client, (clt_indx + 1))->p_hdr_info; + + memcpy(get_client_memptr(wlan_client, clt_indx)->mac, + get_client_memptr(wlan_client, (clt_indx + 1))->mac, + sizeof(get_client_memptr(wlan_client, clt_indx)->mac)); + + get_client_memptr(wlan_client, clt_indx)->hdr_hdl_v4 = get_client_memptr(wlan_client, (clt_indx + 1))->hdr_hdl_v4; + get_client_memptr(wlan_client, clt_indx)->hdr_hdl_v6 = get_client_memptr(wlan_client, (clt_indx + 1))->hdr_hdl_v6; + get_client_memptr(wlan_client, clt_indx)->v4_addr = get_client_memptr(wlan_client, (clt_indx + 1))->v4_addr; + + get_client_memptr(wlan_client, clt_indx)->ipv4_set = get_client_memptr(wlan_client, (clt_indx + 1))->ipv4_set; + get_client_memptr(wlan_client, clt_indx)->ipv6_set = get_client_memptr(wlan_client, (clt_indx + 1))->ipv6_set; + get_client_memptr(wlan_client, clt_indx)->ipv4_header_set = get_client_memptr(wlan_client, (clt_indx + 1))->ipv4_header_set; + get_client_memptr(wlan_client, clt_indx)->ipv6_header_set = get_client_memptr(wlan_client, (clt_indx + 1))->ipv6_header_set; + + get_client_memptr(wlan_client, clt_indx)->route_rule_set_v4 = get_client_memptr(wlan_client, (clt_indx + 1))->route_rule_set_v4; + get_client_memptr(wlan_client, clt_indx)->route_rule_set_v6 = get_client_memptr(wlan_client, (clt_indx + 1))->route_rule_set_v6; + + for(num_v6=0;num_v6< get_client_memptr(wlan_client, clt_indx)->ipv6_set;num_v6++) + { + get_client_memptr(wlan_client, clt_indx)->v6_addr[num_v6][0] = get_client_memptr(wlan_client, (clt_indx + 1))->v6_addr[num_v6][0]; + get_client_memptr(wlan_client, clt_indx)->v6_addr[num_v6][1] = get_client_memptr(wlan_client, (clt_indx + 1))->v6_addr[num_v6][1]; + get_client_memptr(wlan_client, clt_indx)->v6_addr[num_v6][2] = get_client_memptr(wlan_client, (clt_indx + 1))->v6_addr[num_v6][2]; + get_client_memptr(wlan_client, clt_indx)->v6_addr[num_v6][3] = get_client_memptr(wlan_client, (clt_indx + 1))->v6_addr[num_v6][3]; + } + + for (tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++) + { + get_client_memptr(wlan_client, clt_indx)->wifi_rt_hdl[tx_index].wifi_rt_rule_hdl_v4 = + get_client_memptr(wlan_client, (clt_indx + 1))->wifi_rt_hdl[tx_index].wifi_rt_rule_hdl_v4; + + for(num_v6=0;num_v6< get_client_memptr(wlan_client, clt_indx)->route_rule_set_v6;num_v6++) + { + get_client_memptr(wlan_client, clt_indx)->wifi_rt_hdl[tx_index].wifi_rt_rule_hdl_v6[num_v6] = + get_client_memptr(wlan_client, (clt_indx + 1))->wifi_rt_hdl[tx_index].wifi_rt_rule_hdl_v6[num_v6]; + get_client_memptr(wlan_client, clt_indx)->wifi_rt_hdl[tx_index].wifi_rt_rule_hdl_v6_wan[num_v6] = + get_client_memptr(wlan_client, (clt_indx + 1))->wifi_rt_hdl[tx_index].wifi_rt_rule_hdl_v6_wan[num_v6]; + } + } + } + + IPACMDBG_H(" %d wifi client deleted successfully \n", num_wifi_client); + num_wifi_client = num_wifi_client - 1; + IPACM_Wlan::total_num_wifi_clients = IPACM_Wlan::total_num_wifi_clients - 1; + IPACMDBG_H(" Number of wifi client: %d\n", num_wifi_client); + + return IPACM_SUCCESS; +} + +/*handle wlan iface down event*/ +int IPACM_Wlan::handle_down_evt() +{ + int res = IPACM_SUCCESS, i; + + IPACMDBG_H("WLAN ip-type: %d \n", ip_type); + /* no iface address up, directly close iface*/ + if (ip_type == IPACM_IP_NULL) + { + IPACMERR("Invalid iptype: 0x%x\n", ip_type); + goto fail; + } +#ifdef FEATURE_ETH_BRIDGE_LE + if(wlan_ap_index == 0) + { + IPACM_Lan::wlan_hdr_type = IPA_HDR_L2_NONE; + IPACM_Lan::wlan_hdr_template_hdl = 0; + del_hdr_proc_ctx(); + } +#endif + + /* delete wan filter rule */ + if (IPACM_Wan::isWanUP(ipa_if_num) && rx_prop != NULL) + { + IPACMDBG_H("LAN IF goes down, backhaul type %d\n", IPACM_Wan::backhaul_is_sta_mode); + IPACM_Lan::handle_wan_down(IPACM_Wan::backhaul_is_sta_mode); + } + + if (IPACM_Wan::isWanUP_V6(ipa_if_num) && rx_prop != NULL) + { + IPACMDBG_H("LAN IF goes down, backhaul type %d\n", IPACM_Wan::backhaul_is_sta_mode); + handle_wan_down_v6(IPACM_Wan::backhaul_is_sta_mode); + } + IPACMDBG_H("finished deleting wan filtering rules\n "); + + /* Delete v4 filtering rules */ + if (ip_type != IPA_IP_v6 && rx_prop != NULL) + { + /* delete IPv4 icmp filter rules */ + if(wlan_ap_index == 0) + { + if(m_filtering.DeleteFilteringHdls(ipv4_icmp_flt_rule_hdl, IPA_IP_v4, NUM_IPV4_ICMP_FLT_RULE) == false) + { + IPACMERR("Error Deleting ICMPv4 Filtering Rule, aborting...\n"); + res = IPACM_FAILURE; + goto fail; + } + IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, NUM_IPV4_ICMP_FLT_RULE); + } +#ifdef FEATURE_ETH_BRIDGE_LE + if(wlan_ap_index == 0) + { + /* delete default filter rules */ + for(i=0; iipa_num_private_subnet; i++) + { + if(reset_to_dummy_flt_rule(IPA_IP_v4, private_fl_rule_hdl[i]) == IPACM_FAILURE) + { + IPACMERR("Error deleting private subnet IPv4 flt rules.\n"); + res = IPACM_FAILURE; + goto fail; + } + } + } + IPACMDBG_H("Deleted private subnet v4 filter rules successfully.\n"); +#endif + } + + /* Delete v6 filtering rules */ + if (ip_type != IPA_IP_v4 && rx_prop != NULL) + { + /* delete icmp filter rules */ + if(wlan_ap_index == 0) + { + if(m_filtering.DeleteFilteringHdls(ipv6_icmp_flt_rule_hdl, IPA_IP_v6, NUM_IPV6_ICMP_FLT_RULE) == false) + { + IPACMERR("Error Deleting ICMPv6 Filtering Rule, aborting...\n"); + res = IPACM_FAILURE; + goto fail; + } + IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, NUM_IPV6_ICMP_FLT_RULE); + } + IPACMDBG_H("Delete default %d v6 filter rules\n", IPV6_DEFAULT_FILTERTING_RULES); + /* delete default filter rules */ +#ifdef FEATURE_ETH_BRIDGE_LE + if(wlan_ap_index == 0) + { + for(i=0; imac); + eth_bridge_del_wlan_client_rt_rule(get_client_memptr(wlan_client, i)->mac, SRC_WLAN); + eth_bridge_del_wlan_client(get_client_memptr(wlan_client, i)->mac); + if (is_guest_ap == false) + { + eth_bridge_del_wlan_client_rt_rule(get_client_memptr(wlan_client, i)->mac, SRC_LAN); + eth_bridge_post_lan_client_event(get_client_memptr(wlan_client, i)->mac, IPA_ETH_BRIDGE_WLAN_CLIENT_DEL_EVENT); + } +#endif + /* First reset nat rules and then route rules */ + if(get_client_memptr(wlan_client, i)->ipv4_set == true) + { + IPACMDBG_H("Clean Nat Rules for ipv4:0x%x\n", get_client_memptr(wlan_client, i)->v4_addr); + CtList->HandleNeighIpAddrDelEvt(get_client_memptr(wlan_client, i)->v4_addr); + } + + if (delete_default_qos_rtrules(i, IPA_IP_v4)) + { + IPACMERR("unbale to delete v4 default qos route rules for index: %d\n", i); + res = IPACM_FAILURE; + goto fail; + } + + if (delete_default_qos_rtrules(i, IPA_IP_v6)) + { + IPACMERR("unbale to delete v6 default qos route rules for index: %d\n", i); + res = IPACM_FAILURE; + goto fail; + } + + IPACMDBG_H("Delete %d client header\n", num_wifi_client); + + handle_lan2lan_msg_post(get_client_memptr(wlan_client, i)->mac, IPA_LAN_CLIENT_DISCONNECT, IPA_IP_v4); + handle_lan2lan_msg_post(get_client_memptr(wlan_client, i)->mac, IPA_LAN_CLIENT_DISCONNECT, IPA_IP_v6); + + if(get_client_memptr(wlan_client, i)->ipv4_header_set == true) + { + if (m_header.DeleteHeaderHdl(get_client_memptr(wlan_client, i)->hdr_hdl_v4) + == false) + { + res = IPACM_FAILURE; + goto fail; + } + } + + if(get_client_memptr(wlan_client, i)->ipv6_header_set == true) + { + if (m_header.DeleteHeaderHdl(get_client_memptr(wlan_client, i)->hdr_hdl_v6) + == false) + { + res = IPACM_FAILURE; + goto fail; + } + } + } /* end of for loop */ + + /* free the wlan clients cache */ + IPACMDBG_H("Free wlan clients cache\n"); + + /* Delete private subnet*/ +#ifdef FEATURE_IPA_ANDROID + if (ip_type != IPA_IP_v6) + { + IPACMDBG_H("current IPACM private subnet_addr number(%d)\n", IPACM_Iface::ipacmcfg->ipa_num_private_subnet); + IPACMDBG_H(" Delete IPACM private subnet_addr as: 0x%x \n", if_ipv4_subnet); + if(IPACM_Iface::ipacmcfg->DelPrivateSubnet(if_ipv4_subnet, ipa_if_num) == false) + { + IPACMERR(" can't Delete IPACM private subnet_addr as: 0x%x \n", if_ipv4_subnet); + } + } + /* reset the IPA-client pipe enum */ + handle_tethering_client(true, IPACM_CLIENT_WLAN); +#endif /* defined(FEATURE_IPA_ANDROID)*/ + +fail: + /* Delete corresponding ipa_rm_resource_name of RX-endpoint after delete all IPV4V6 FT-rule */ + if (rx_prop != NULL) + { + IPACMDBG_H("dev %s add producer dependency\n", dev_name); + IPACMDBG_H("depend Got pipe %d rm index : %d \n", rx_prop->rx[0].src_pipe, IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[rx_prop->rx[0].src_pipe]); + IPACM_Iface::ipacmcfg->DelRmDepend(IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[rx_prop->rx[0].src_pipe]); + free(rx_prop); + } + + for (i = 0; i < num_wifi_client; i++) + { + if(get_client_memptr(wlan_client, i)->p_hdr_info != NULL) + { + free(get_client_memptr(wlan_client, i)->p_hdr_info); + } + } + if(wlan_client != NULL) + { + free(wlan_client); + } + if (tx_prop != NULL) + { + free(tx_prop); + } + + if (iface_query != NULL) + { + free(iface_query); + } +#ifdef FEATURE_ETH_BRIDGE_LE + if(eth_bridge_lan_client_rt_from_lan_info_v4 != NULL) + { + free(eth_bridge_lan_client_rt_from_lan_info_v4); + } + if(eth_bridge_lan_client_rt_from_lan_info_v6 != NULL) + { + free(eth_bridge_lan_client_rt_from_lan_info_v6); + } + if(eth_bridge_lan_client_rt_from_wlan_info_v4 != NULL) + { + free(eth_bridge_lan_client_rt_from_wlan_info_v4); + } + if(eth_bridge_lan_client_rt_from_wlan_info_v6 != NULL) + { + free(eth_bridge_lan_client_rt_from_wlan_info_v6); + } + if(eth_bridge_wlan_client_rt_from_lan_info_v4 != NULL) + { + free(eth_bridge_wlan_client_rt_from_lan_info_v4); + } + if(eth_bridge_wlan_client_rt_from_lan_info_v6 != NULL) + { + free(eth_bridge_wlan_client_rt_from_lan_info_v6); + } + if(eth_bridge_wlan_client_rt_from_wlan_info_v4 != NULL) + { + free(eth_bridge_wlan_client_rt_from_wlan_info_v4); + } + if(eth_bridge_wlan_client_rt_from_wlan_info_v6 != NULL) + { + free(eth_bridge_wlan_client_rt_from_wlan_info_v6); + } +#endif + is_active = false; + post_del_self_evt(); + + return res; +} + +/*handle reset wifi-client rt-rules */ +int IPACM_Wlan::handle_wlan_client_reset_rt(ipa_ip_type iptype) +{ + int i, res = IPACM_SUCCESS; + + /* clean wifi-client routing rules */ + IPACMDBG_H("left %d wifi clients to reset ip-type(%d) rules \n ", num_wifi_client, iptype); + + for (i = 0; i < num_wifi_client; i++) + { + /* Reset RT rules */ + res = delete_default_qos_rtrules(i, iptype); + if (res != IPACM_SUCCESS) + { + IPACMERR("Failed to delete old iptype(%d) rules.\n", iptype); + return res; + } + /* Pass info to LAN2LAN module */ + res = handle_lan2lan_msg_post(get_client_memptr(wlan_client, i)->mac, IPA_LAN_CLIENT_DISCONNECT, iptype); + if (res != IPACM_SUCCESS) + { + IPACMERR("Failed to posting delete old iptype(%d) address.\n", iptype); + return res; + } + /* Reset ip-address */ + if(iptype == IPA_IP_v4) + { + get_client_memptr(wlan_client, i)->ipv4_set = false; + } + else + { + get_client_memptr(wlan_client, i)->ipv6_set = 0; + } + } /* end of for loop */ + return res; +} + +/*handle lan2lan internal mesg posting*/ +int IPACM_Wlan::handle_lan2lan_msg_post(uint8_t *mac_addr, ipa_cm_event_id event,ipa_ip_type iptype) +{ + int client_index; + client_index = get_wlan_client_index(mac_addr); + if (client_index == IPACM_INVALID_INDEX) + { + IPACMDBG_H("wlan client not attached\n"); + return IPACM_SUCCESS; + } + + ipacm_event_lan_client* lan_client; + ipacm_cmd_q_data evt_data; + if((get_client_memptr(wlan_client, client_index)->ipv4_set == true) + && (iptype == IPA_IP_v4)) /* handle ipv4 case*/ + { + if(ip_type != IPA_IP_v4 && ip_type != IPA_IP_MAX) + { + IPACMERR("Client has IPv4 addr but iface does not have IPv4 up.\n"); + return IPACM_FAILURE; + } + + lan_client = (ipacm_event_lan_client*)malloc(sizeof(ipacm_event_lan_client)); + if(lan_client == NULL) + { + IPACMERR("Unable to allocate memory.\n"); + return IPACM_FAILURE; + } + memset(lan_client, 0, sizeof(ipacm_event_lan_client)); + + lan_client->iptype = IPA_IP_v4; + lan_client->ipv4_addr = get_client_memptr(wlan_client, client_index)->v4_addr; + lan_client->p_iface = this; + + memset(&evt_data, 0, sizeof(evt_data)); + evt_data.event = event; + evt_data.evt_data = (void*)lan_client; + + IPACMDBG_H("Posting event: %d\n",event); + IPACM_EvtDispatcher::PostEvt(&evt_data); + } + + if((get_client_memptr(wlan_client, client_index)->ipv6_set > 0) + && (iptype == IPA_IP_v6)) /* handle v6 case: may be multiple v6 addr */ + { + if(ip_type != IPA_IP_v6 && ip_type != IPA_IP_MAX) + { + IPACMERR("Client has IPv6 addr but iface does not have IPv6 up.\n"); + return IPACM_FAILURE; + } + int i; + + for(i=0; iipv6_set; i++) + { + lan_client = (ipacm_event_lan_client*)malloc(sizeof(ipacm_event_lan_client)); + if(lan_client == NULL) + { + IPACMERR("Unable to allocate memory.\n"); + return IPACM_FAILURE; + } + memset(lan_client, 0, sizeof(ipacm_event_lan_client)); + + lan_client->iptype = IPA_IP_v6; + memcpy(lan_client->ipv6_addr, get_client_memptr(wlan_client, client_index)->v6_addr[i], 4*sizeof(uint32_t)); + lan_client->p_iface = this; + + memset(&evt_data, 0, sizeof(evt_data)); + evt_data.event = event; + evt_data.evt_data = (void*)lan_client; + + IPACMDBG_H("Posting event: %d\n",event); + IPACM_EvtDispatcher::PostEvt(&evt_data); + } + } + return IPACM_SUCCESS; +} + +int IPACM_Wlan::add_lan2lan_hdr(ipa_ip_type iptype, uint8_t* src_mac, uint8_t* dst_mac, uint32_t* hdr_hdl) +{ + if(tx_prop == NULL) + { + IPACMERR("There is no tx_prop, cannot add header.\n"); + return IPACM_FAILURE; + } + if(src_mac == NULL || dst_mac == NULL) + { + IPACMERR("Either src_mac or dst_mac is null, cannot add header.\n"); + return IPACM_FAILURE; + } + if(hdr_hdl == NULL) + { + IPACMERR("Header handle is empty.\n"); + return IPACM_FAILURE; + } + + int i, j, k, len; + int res = IPACM_SUCCESS; + char index[4]; + struct ipa_ioc_copy_hdr sCopyHeader; + struct ipa_ioc_add_hdr *pHeader; + + IPACMDBG_H("Get lan2lan header request, src_mac: 0x%02x%02x%02x%02x%02x%02x dst_mac: 0x%02x%02x%02x%02x%02x%02x\n", + src_mac[0], src_mac[1], src_mac[2], src_mac[3], src_mac[4], src_mac[5], dst_mac[0], dst_mac[1], + dst_mac[2], dst_mac[3], dst_mac[4], dst_mac[5]); + + len = sizeof(struct ipa_ioc_add_hdr) + sizeof(struct ipa_hdr_add); + pHeader = (struct ipa_ioc_add_hdr *)malloc(len); + if (pHeader == NULL) + { + IPACMERR("Failed to allocate header\n"); + return IPACM_FAILURE; + } + memset(pHeader, 0, len); + + if(iptype == IPA_IP_v4) + { /* copy partial header for v4*/ + for(i=0; inum_tx_props; i++) + { + if(tx_prop->tx[i].ip == IPA_IP_v4) + { + IPACMDBG_H("Got v4-header name from %d tx props\n", i); + memset(&sCopyHeader, 0, sizeof(sCopyHeader)); + memcpy(sCopyHeader.name, tx_prop->tx[i].hdr_name, sizeof(sCopyHeader.name)); + + IPACMDBG_H("Header name: %s\n", sCopyHeader.name); + if(m_header.CopyHeader(&sCopyHeader) == false) + { + IPACMERR("Copy header failed\n"); + res = IPACM_FAILURE; + goto fail; + } + + IPACMDBG_H("Header length: %d, paritial: %d\n", sCopyHeader.hdr_len, sCopyHeader.is_partial); + if (sCopyHeader.hdr_len > IPA_HDR_MAX_SIZE) + { + IPACMERR("Header oversize\n"); + res = IPACM_FAILURE; + goto fail; + } + else + { + memcpy(pHeader->hdr[0].hdr, sCopyHeader.hdr, sCopyHeader.hdr_len); + } + + for(j=0; jmac, IPA_MAC_ADDR_SIZE) == 0) + { + break; + } + } + if(j == num_wifi_client) + { + IPACMERR("Not able to find the wifi client from mac addr.\n"); + res = IPACM_FAILURE; + goto fail; + } + else + { + IPACMDBG_H("Find wifi client at position %d\n", j); + for(k = 0; k < get_client_memptr(wlan_client, j)->p_hdr_info->num_of_attribs; k++) + { + if(get_client_memptr(wlan_client, j)->p_hdr_info->attribs[k].attrib_type == WLAN_HDR_ATTRIB_MAC_ADDR) + { + memcpy(&pHeader->hdr[0].hdr[get_client_memptr(wlan_client, j)->p_hdr_info->attribs[k].offset], + dst_mac, IPA_MAC_ADDR_SIZE); + memcpy(&pHeader->hdr[0].hdr[get_client_memptr(wlan_client, j)->p_hdr_info->attribs[k].offset + IPA_MAC_ADDR_SIZE], + src_mac, IPA_MAC_ADDR_SIZE); + } + else if(get_client_memptr(wlan_client, j)->p_hdr_info->attribs[k].attrib_type == WLAN_HDR_ATTRIB_STA_ID) + { + memcpy(&pHeader->hdr[0].hdr[get_client_memptr(wlan_client, j)->p_hdr_info->attribs[k].offset], + &get_client_memptr(wlan_client, j)->p_hdr_info->attribs[k].u.sta_id, + sizeof(get_client_memptr(wlan_client, j)->p_hdr_info->attribs[k].u.sta_id)); + } + else + { + IPACMDBG_H("The attribute type is not expected!\n"); + } + } + } + + pHeader->commit = true; + pHeader->num_hdrs = 1; + + memset(pHeader->hdr[0].name, 0, sizeof(pHeader->hdr[0].name)); + strlcpy(pHeader->hdr[0].name, IPA_LAN_TO_LAN_WLAN_HDR_NAME_V4, sizeof(pHeader->hdr[0].name)); + pHeader->hdr[0].name[IPA_RESOURCE_NAME_MAX-1] = '\0'; + for(j=0; jhdr[0].name, index, sizeof(pHeader->hdr[0].name)) > IPA_RESOURCE_NAME_MAX) + { + IPACMERR(" header name construction failed exceed length (%d)\n", strlen(pHeader->hdr[0].name)); + res = IPACM_FAILURE; + goto fail; + } + + pHeader->hdr[0].hdr_len = sCopyHeader.hdr_len; + pHeader->hdr[0].is_partial = 0; + pHeader->hdr[0].hdr_hdl = -1; + pHeader->hdr[0].status = -1; + + if (m_header.AddHeader(pHeader) == false || pHeader->hdr[0].status != 0) + { + IPACMERR("Ioctl IPA_IOC_ADD_HDR failed with status: %d\n", pHeader->hdr[0].status); + res = IPACM_FAILURE; + goto fail; + } + IPACMDBG_H("Installed v4 full header %s header handle 0x%08x\n", pHeader->hdr[0].name, + pHeader->hdr[0].hdr_hdl); + *hdr_hdl = pHeader->hdr[0].hdr_hdl; + lan2lan_hdr_hdl_v4[j].hdr_hdl = pHeader->hdr[0].hdr_hdl; + break; + } + } + } + else if(iptype == IPA_IP_v6) + { /* copy partial header for v6*/ + for(i=0; inum_tx_props; i++) + { + if(tx_prop->tx[i].ip == IPA_IP_v6) + { + IPACMDBG_H("Got v6-header name from %d tx props\n", i); + memset(&sCopyHeader, 0, sizeof(sCopyHeader)); + memcpy(sCopyHeader.name, tx_prop->tx[i].hdr_name, sizeof(sCopyHeader.name)); + + IPACMDBG_H("Header name: %s\n", sCopyHeader.name); + if(m_header.CopyHeader(&sCopyHeader) == false) + { + IPACMERR("Copy header failed\n"); + res = IPACM_FAILURE; + goto fail; + } + + IPACMDBG_H("Header length: %d, paritial: %d\n", sCopyHeader.hdr_len, sCopyHeader.is_partial); + if (sCopyHeader.hdr_len > IPA_HDR_MAX_SIZE) + { + IPACMERR("Header oversize\n"); + res = IPACM_FAILURE; + goto fail; + } + else + { + memcpy(pHeader->hdr[0].hdr, sCopyHeader.hdr, sCopyHeader.hdr_len); + } + + for(j=0; jmac, IPA_MAC_ADDR_SIZE) == 0) + { + break; + } + } + if(j == num_wifi_client) + { + IPACMERR("Not able to find the wifi client from mac addr.\n"); + res = IPACM_FAILURE; + goto fail; + } + else + { + IPACMDBG_H("Find wifi client at position %d\n", j); + for(k = 0; k < get_client_memptr(wlan_client, j)->p_hdr_info->num_of_attribs; k++) + { + if(get_client_memptr(wlan_client, j)->p_hdr_info->attribs[k].attrib_type == WLAN_HDR_ATTRIB_MAC_ADDR) + { + memcpy(&pHeader->hdr[0].hdr[get_client_memptr(wlan_client, j)->p_hdr_info->attribs[k].offset], + dst_mac, IPA_MAC_ADDR_SIZE); + memcpy(&pHeader->hdr[0].hdr[get_client_memptr(wlan_client, j)->p_hdr_info->attribs[k].offset + IPA_MAC_ADDR_SIZE], + src_mac, IPA_MAC_ADDR_SIZE); + } + else if(get_client_memptr(wlan_client, j)->p_hdr_info->attribs[k].attrib_type == WLAN_HDR_ATTRIB_STA_ID) + { + memcpy(&pHeader->hdr[0].hdr[get_client_memptr(wlan_client, j)->p_hdr_info->attribs[k].offset], + &get_client_memptr(wlan_client, j)->p_hdr_info->attribs[k].u.sta_id, + sizeof(get_client_memptr(wlan_client, j)->p_hdr_info->attribs[k].u.sta_id)); + } + else + { + IPACMDBG_H("The attribute type is not expected!\n"); + } + } + } + + pHeader->commit = true; + pHeader->num_hdrs = 1; + + memset(pHeader->hdr[0].name, 0, sizeof(pHeader->hdr[0].name)); + strlcpy(pHeader->hdr[0].name, IPA_LAN_TO_LAN_WLAN_HDR_NAME_V6, sizeof(pHeader->hdr[0].name)); + pHeader->hdr[0].name[IPA_RESOURCE_NAME_MAX-1] = '\0'; + + for(j=0; jhdr[0].name, index, sizeof(pHeader->hdr[0].name)) > IPA_RESOURCE_NAME_MAX) + { + IPACMERR(" header name construction failed exceed length (%d)\n", strlen(pHeader->hdr[0].name)); + res = IPACM_FAILURE; + goto fail; + } + pHeader->hdr[0].hdr_len = sCopyHeader.hdr_len; + pHeader->hdr[0].is_partial = 0; + pHeader->hdr[0].hdr_hdl = -1; + pHeader->hdr[0].status = -1; + + if (m_header.AddHeader(pHeader) == false || pHeader->hdr[0].status != 0) + { + IPACMERR("Ioctl IPA_IOC_ADD_HDR failed with status: %d\n", pHeader->hdr[0].status); + res = IPACM_FAILURE; + goto fail; + } + IPACMDBG_H("Installed v6 full header %s header handle 0x%08x\n", pHeader->hdr[0].name, + pHeader->hdr[0].hdr_hdl); + *hdr_hdl = pHeader->hdr[0].hdr_hdl; + lan2lan_hdr_hdl_v6[j].hdr_hdl = pHeader->hdr[0].hdr_hdl; + break; + } + } + } + else + { + IPACMERR("IP type is not expected.\n"); + } + +fail: + free(pHeader); + return res; +} + +/* add dummy filtering rules for WLAN AP-AP mode support */ +void IPACM_Wlan::add_dummy_flt_rule() +{ + int num_v4_dummy_rule, num_v6_dummy_rule; + + if(IPACM_Wlan::num_wlan_ap_iface == 1) + { + if(IPACM_Wlan::dummy_flt_rule_hdl_v4 != NULL || IPACM_Wlan::dummy_flt_rule_hdl_v6 != NULL) + { + IPACMERR("Either v4 or v6 dummy filtering rule handle is not empty.\n"); + return; + } +#ifdef FEATURE_ETH_BRIDGE_LE + num_v4_dummy_rule = IPV4_DEFAULT_FILTERTING_RULES + IPA_LAN_TO_LAN_MAX_WLAN_CLIENT + IPA_LAN_TO_LAN_MAX_LAN_CLIENT + IPACM_Iface::ipacmcfg->ipa_num_private_subnet; + num_v6_dummy_rule = IPV6_DEFAULT_FILTERTING_RULES + IPA_LAN_TO_LAN_MAX_WLAN_CLIENT + IPA_LAN_TO_LAN_MAX_LAN_CLIENT + 2 * NUM_IPV6_PREFIX_FLT_RULE; +#else +#ifndef CT_OPT + num_v4_dummy_rule = 2*(IPV4_DEFAULT_FILTERTING_RULES + MAX_OFFLOAD_PAIR + IPACM_Iface::ipacmcfg->ipa_num_private_subnet); + num_v6_dummy_rule = 2*(IPV6_DEFAULT_FILTERTING_RULES + MAX_OFFLOAD_PAIR + NUM_IPV6_PREFIX_FLT_RULE); +#else + num_v4_dummy_rule = 2*(IPV4_DEFAULT_FILTERTING_RULES + NUM_TCP_CTL_FLT_RULE + MAX_OFFLOAD_PAIR + IPACM_Iface::ipacmcfg->ipa_num_private_subnet); + num_v6_dummy_rule = 2*(IPV6_DEFAULT_FILTERTING_RULES + NUM_TCP_CTL_FLT_RULE + MAX_OFFLOAD_PAIR + NUM_IPV6_PREFIX_FLT_RULE); +#endif +#ifdef FEATURE_IPA_ANDROID + num_v4_dummy_rule = num_v4_dummy_rule - 2* IPACM_Iface::ipacmcfg->ipa_num_private_subnet + 2 * IPA_MAX_PRIVATE_SUBNET_ENTRIES; +#endif +#endif + + IPACM_Wlan::dummy_flt_rule_hdl_v4 = (uint32_t*)malloc(num_v4_dummy_rule * sizeof(uint32_t)); + if(IPACM_Wlan::dummy_flt_rule_hdl_v4 == NULL) + { + IPACMERR("Failed to allocate memory.\n"); + return; + } + IPACM_Wlan::dummy_flt_rule_hdl_v6 = (uint32_t*)malloc(num_v6_dummy_rule * sizeof(uint32_t)); + if(IPACM_Wlan::dummy_flt_rule_hdl_v6 == NULL) + { + IPACMERR("Failed to allocate memory.\n"); + free(IPACM_Wlan::dummy_flt_rule_hdl_v4); + IPACM_Wlan::dummy_flt_rule_hdl_v4 = NULL; + return; + } + memset(IPACM_Wlan::dummy_flt_rule_hdl_v4, 0, num_v4_dummy_rule * sizeof(uint32_t)); + memset(IPACM_Wlan::dummy_flt_rule_hdl_v6, 0, num_v6_dummy_rule * sizeof(uint32_t)); + + install_dummy_flt_rule(IPA_IP_v4, num_v4_dummy_rule); + install_dummy_flt_rule(IPA_IP_v6, num_v6_dummy_rule); + } + return; +} + +/* install dummy filtering rules for WLAN AP-AP mode support */ +int IPACM_Wlan::install_dummy_flt_rule(ipa_ip_type iptype, int num_rule) +{ + if(rx_prop == NULL) + { + IPACMDBG_H("There is no rx_prop for iface %s, not able to add dummy filtering rule.\n", dev_name); + return IPACM_FAILURE; + } + + int i, len, res = IPACM_SUCCESS; + struct ipa_flt_rule_add flt_rule; + ipa_ioc_add_flt_rule* pFilteringTable; + + len = sizeof(struct ipa_ioc_add_flt_rule) + num_rule * sizeof(struct ipa_flt_rule_add); + + pFilteringTable = (struct ipa_ioc_add_flt_rule *)malloc(len); + if (pFilteringTable == NULL) + { + IPACMERR("Error allocate flt table memory...\n"); + return IPACM_FAILURE; + } + memset(pFilteringTable, 0, len); + + pFilteringTable->commit = 1; + pFilteringTable->ep = rx_prop->rx[0].src_pipe; + pFilteringTable->global = false; + pFilteringTable->ip = iptype; + pFilteringTable->num_rules = num_rule; + + memset(&flt_rule, 0, sizeof(struct ipa_flt_rule_add)); + + flt_rule.rule.retain_hdr = 0; + flt_rule.at_rear = true; + flt_rule.flt_rule_hdl = -1; + flt_rule.status = -1; + flt_rule.rule.action = IPA_PASS_TO_EXCEPTION; + memcpy(&flt_rule.rule.attrib, &rx_prop->rx[0].attrib, + sizeof(flt_rule.rule.attrib)); + + if(iptype == IPA_IP_v4) + { + flt_rule.rule.attrib.attrib_mask = IPA_FLT_SRC_ADDR | IPA_FLT_DST_ADDR; + flt_rule.rule.attrib.u.v4.src_addr_mask = ~0; + flt_rule.rule.attrib.u.v4.src_addr = ~0; + flt_rule.rule.attrib.u.v4.dst_addr_mask = ~0; + flt_rule.rule.attrib.u.v4.dst_addr = ~0; + + for(i=0; irules[i]), &flt_rule, sizeof(struct ipa_flt_rule_add)); + } + + if (false == m_filtering.AddFilteringRule(pFilteringTable)) + { + IPACMERR("Error adding dummy ipv4 flt rule\n"); + res = IPACM_FAILURE; + goto fail; + } + else + { + IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, iptype, num_rule); + /* copy filter rule hdls */ + for (int i = 0; i < num_rule; i++) + { + if (pFilteringTable->rules[i].status == 0) + { + IPACM_Wlan::dummy_flt_rule_hdl_v4[i] = pFilteringTable->rules[i].flt_rule_hdl; + IPACMDBG("Dummy v4 flt rule %d hdl:0x%x\n", i, IPACM_Wlan::dummy_flt_rule_hdl_v4[i]); + } + else + { + IPACMERR("Failed adding dummy v4 flt rule %d\n", i); + res = IPACM_FAILURE; + goto fail; + } + } + } + } + else if(iptype == IPA_IP_v6) + { + flt_rule.rule.attrib.attrib_mask = IPA_FLT_SRC_ADDR | IPA_FLT_DST_ADDR; + flt_rule.rule.attrib.u.v6.src_addr_mask[0] = ~0; + flt_rule.rule.attrib.u.v6.src_addr_mask[1] = ~0; + flt_rule.rule.attrib.u.v6.src_addr_mask[2] = ~0; + flt_rule.rule.attrib.u.v6.src_addr_mask[3] = ~0; + flt_rule.rule.attrib.u.v6.src_addr[0] = ~0; + flt_rule.rule.attrib.u.v6.src_addr[1] = ~0; + flt_rule.rule.attrib.u.v6.src_addr[2] = ~0; + flt_rule.rule.attrib.u.v6.src_addr[3] = ~0; + flt_rule.rule.attrib.u.v6.dst_addr_mask[0] = ~0; + flt_rule.rule.attrib.u.v6.dst_addr_mask[1] = ~0; + flt_rule.rule.attrib.u.v6.dst_addr_mask[2] = ~0; + flt_rule.rule.attrib.u.v6.dst_addr_mask[3] = ~0; + flt_rule.rule.attrib.u.v6.dst_addr[0] = ~0; + flt_rule.rule.attrib.u.v6.dst_addr[1] = ~0; + flt_rule.rule.attrib.u.v6.dst_addr[2] = ~0; + flt_rule.rule.attrib.u.v6.dst_addr[3] = ~0; + + for(i=0; irules[i]), &flt_rule, sizeof(struct ipa_flt_rule_add)); + } + + if (false == m_filtering.AddFilteringRule(pFilteringTable)) + { + IPACMERR("Error adding dummy ipv6 flt rule\n"); + res = IPACM_FAILURE; + goto fail; + } + else + { + IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, iptype, num_rule); + /* copy filter rule hdls */ + for (int i = 0; i < num_rule; i++) + { + if (pFilteringTable->rules[i].status == 0) + { + IPACM_Wlan::dummy_flt_rule_hdl_v6[i] = pFilteringTable->rules[i].flt_rule_hdl; + IPACMDBG("Lan2lan v6 flt rule %d hdl:0x%x\n", i, IPACM_Wlan::dummy_flt_rule_hdl_v6[i]); + } + else + { + IPACMERR("Failed adding v6 flt rule %d\n", i); + res = IPACM_FAILURE; + goto fail; + } + } + } + } + else + { + IPACMERR("IP type is not expected.\n"); + goto fail; + } + +fail: + free(pFilteringTable); + return res; +} + +/* delete dummy flt rule for WLAN AP-AP mode support*/ +void IPACM_Wlan::del_dummy_flt_rule() +{ + int num_v4_dummy_rule, num_v6_dummy_rule; + + if(IPACM_Wlan::num_wlan_ap_iface == 0) + { + if(IPACM_Wlan::dummy_flt_rule_hdl_v4 == NULL || IPACM_Wlan::dummy_flt_rule_hdl_v4 == NULL) + { + IPACMERR("Either v4 or v6 dummy flt rule is empty.\n"); + return; + } +#ifndef CT_OPT + num_v4_dummy_rule = 2*(IPV4_DEFAULT_FILTERTING_RULES + MAX_OFFLOAD_PAIR + IPACM_Iface::ipacmcfg->ipa_num_private_subnet); + num_v6_dummy_rule = 2*(IPV6_DEFAULT_FILTERTING_RULES + MAX_OFFLOAD_PAIR + NUM_IPV6_PREFIX_FLT_RULE); +#else + num_v4_dummy_rule = 2*(IPV4_DEFAULT_FILTERTING_RULES + NUM_TCP_CTL_FLT_RULE + MAX_OFFLOAD_PAIR + IPACM_Iface::ipacmcfg->ipa_num_private_subnet); + num_v6_dummy_rule = 2*(IPV6_DEFAULT_FILTERTING_RULES + NUM_TCP_CTL_FLT_RULE + MAX_OFFLOAD_PAIR + NUM_IPV6_PREFIX_FLT_RULE); +#endif +#ifdef FEATURE_IPA_ANDROID + num_v4_dummy_rule = num_v4_dummy_rule - 2* IPACM_Iface::ipacmcfg->ipa_num_private_subnet + 2 * IPA_MAX_PRIVATE_SUBNET_ENTRIES; +#endif + +#ifdef FEATURE_ETH_BRIDGE_LE + num_v4_dummy_rule = IPV4_DEFAULT_FILTERTING_RULES + IPA_LAN_TO_LAN_MAX_WLAN_CLIENT + IPA_LAN_TO_LAN_MAX_LAN_CLIENT + IPACM_Iface::ipacmcfg->ipa_num_private_subnet; + num_v6_dummy_rule = IPV6_DEFAULT_FILTERTING_RULES + IPA_LAN_TO_LAN_MAX_WLAN_CLIENT + IPA_LAN_TO_LAN_MAX_LAN_CLIENT + 2 * NUM_IPV6_PREFIX_FLT_RULE; +#endif + + if(m_filtering.DeleteFilteringHdls(IPACM_Wlan::dummy_flt_rule_hdl_v4, IPA_IP_v4, num_v4_dummy_rule) == false) + { + IPACMERR("Failed to delete ipv4 dummy flt rules.\n"); + return; + } + IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, num_v4_dummy_rule); + if(m_filtering.DeleteFilteringHdls(IPACM_Wlan::dummy_flt_rule_hdl_v6, IPA_IP_v6, num_v6_dummy_rule) == false) + { + IPACMERR("Failed to delete ipv6 dummy flt rules.\n"); + return; + } + IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, num_v6_dummy_rule); + + free(IPACM_Wlan::dummy_flt_rule_hdl_v4); + IPACM_Wlan::dummy_flt_rule_hdl_v4 = NULL; + free(IPACM_Wlan::dummy_flt_rule_hdl_v6); + IPACM_Wlan::dummy_flt_rule_hdl_v6 = NULL; +#ifdef FEATURE_ETH_BRIDGE_LE + memset(self_client_flt_rule_hdl_v4, 0, IPA_LAN_TO_LAN_MAX_WLAN_CLIENT * sizeof(lan2lan_flt_rule_hdl)); + memset(self_client_flt_rule_hdl_v6, 0, IPA_LAN_TO_LAN_MAX_WLAN_CLIENT * sizeof(lan2lan_flt_rule_hdl)); + memset(lan_client_flt_rule_hdl_v4, 0, IPA_LAN_TO_LAN_MAX_LAN_CLIENT * sizeof(lan2lan_flt_rule_hdl)); + memset(lan_client_flt_rule_hdl_v6, 0, IPA_LAN_TO_LAN_MAX_LAN_CLIENT * sizeof(lan2lan_flt_rule_hdl)); +#endif + } + return; +} + +/* install TCP control filter rules */ +void IPACM_Wlan::install_tcp_ctl_flt_rule(ipa_ip_type iptype) +{ + if (rx_prop == NULL) + { + IPACMDBG_H("No rx properties registered for iface %s\n", dev_name); + return; + } + + int i, len, res = IPACM_SUCCESS, offset; + struct ipa_flt_rule_mdfy flt_rule; + struct ipa_ioc_mdfy_flt_rule* pFilteringTable; + + if (iptype == IPA_IP_v4) + { + if(IPACM_Wlan::dummy_flt_rule_hdl_v4 == NULL) + { + IPACMERR("Dummy ipv4 flt rule has not been installed.\n"); + return; + } + offset = wlan_ap_index * (IPV4_DEFAULT_FILTERTING_RULES + NUM_TCP_CTL_FLT_RULE + MAX_OFFLOAD_PAIR + IPACM_Iface::ipacmcfg->ipa_num_private_subnet); +#ifdef FEATURE_IPA_ANDROID + offset = offset + wlan_ap_index * (IPA_MAX_PRIVATE_SUBNET_ENTRIES - IPACM_Iface::ipacmcfg->ipa_num_private_subnet); +#endif + } + else + { + if(IPACM_Wlan::dummy_flt_rule_hdl_v6 == NULL) + { + IPACMERR("Dummy ipv6 flt rule has not been installed.\n"); + return; + } + offset = wlan_ap_index * (IPV6_DEFAULT_FILTERTING_RULES + NUM_TCP_CTL_FLT_RULE + MAX_OFFLOAD_PAIR); + } + + len = sizeof(struct ipa_ioc_mdfy_flt_rule) + NUM_TCP_CTL_FLT_RULE * sizeof(struct ipa_flt_rule_mdfy); + pFilteringTable = (struct ipa_ioc_mdfy_flt_rule*)malloc(len); + if (!pFilteringTable) + { + IPACMERR("Failed to allocate ipa_ioc_mdfy_flt_rule memory...\n"); + return; + } + memset(pFilteringTable, 0, len); + + pFilteringTable->commit = 1; + pFilteringTable->ip = iptype; + pFilteringTable->num_rules = NUM_TCP_CTL_FLT_RULE; + + memset(&flt_rule, 0, sizeof(struct ipa_flt_rule_mdfy)); + flt_rule.status = -1; + + flt_rule.rule.retain_hdr = 1; + flt_rule.rule.to_uc = 0; + flt_rule.rule.action = IPA_PASS_TO_EXCEPTION; + flt_rule.rule.eq_attrib_type = 1; + + flt_rule.rule.eq_attrib.rule_eq_bitmap = 0; + + if(rx_prop->rx[0].attrib.attrib_mask & IPA_FLT_META_DATA) + { + flt_rule.rule.eq_attrib.rule_eq_bitmap |= (1<<14); + flt_rule.rule.eq_attrib.metadata_meq32_present = 1; + flt_rule.rule.eq_attrib.metadata_meq32.offset = 0; + flt_rule.rule.eq_attrib.metadata_meq32.value = rx_prop->rx[0].attrib.meta_data; + flt_rule.rule.eq_attrib.metadata_meq32.mask = rx_prop->rx[0].attrib.meta_data_mask; + } + + flt_rule.rule.eq_attrib.rule_eq_bitmap |= (1<<1); + flt_rule.rule.eq_attrib.protocol_eq_present = 1; + flt_rule.rule.eq_attrib.protocol_eq = IPACM_FIREWALL_IPPROTO_TCP; + + /* add TCP FIN rule*/ + flt_rule.rule.eq_attrib.rule_eq_bitmap |= (1<<8); + flt_rule.rule.eq_attrib.ihl_offset_meq_32[0].offset = 12; + flt_rule.rule.eq_attrib.ihl_offset_meq_32[0].value = (((uint32_t)1)<rules[0]), &flt_rule, sizeof(struct ipa_flt_rule_mdfy)); + + /* add TCP SYN rule*/ + flt_rule.rule.eq_attrib.ihl_offset_meq_32[0].value = (((uint32_t)1)<rules[1]), &flt_rule, sizeof(struct ipa_flt_rule_mdfy)); + + /* add TCP RST rule*/ + flt_rule.rule.eq_attrib.ihl_offset_meq_32[0].value = (((uint32_t)1)<rules[2]), &flt_rule, sizeof(struct ipa_flt_rule_mdfy)); + + if (false == m_filtering.ModifyFilteringRule(pFilteringTable)) + { + IPACMERR("Failed to modify tcp control filtering rules.\n"); + goto fail; + } + else + { + if(iptype == IPA_IP_v4) + { + for(i=0; irules[i].rule_hdl; + } + } + else + { + for(i=0; irules[i].rule_hdl; + } + } + } + +fail: + free(pFilteringTable); + return; +} + +int IPACM_Wlan::add_dummy_private_subnet_flt_rule(ipa_ip_type iptype) +{ + if(rx_prop == NULL) + { + IPACMDBG_H("There is no rx_prop for iface %s, not able to add dummy lan2lan filtering rule.\n", dev_name); + return IPACM_FAILURE; + } + + int offset; + if(iptype == IPA_IP_v4) + { + if(IPACM_Wlan::dummy_flt_rule_hdl_v4 == NULL) + { + IPACMERR("Dummy ipv4 flt rule has not been installed.\n"); + return IPACM_FAILURE; + } + +#ifndef CT_OPT + offset = wlan_ap_index * (IPV4_DEFAULT_FILTERTING_RULES + MAX_OFFLOAD_PAIR + IPACM_Iface::ipacmcfg->ipa_num_private_subnet) + + IPV4_DEFAULT_FILTERTING_RULES + MAX_OFFLOAD_PAIR; +#else + offset = wlan_ap_index * (IPV4_DEFAULT_FILTERTING_RULES + NUM_TCP_CTL_FLT_RULE + MAX_OFFLOAD_PAIR + IPACM_Iface::ipacmcfg->ipa_num_private_subnet) + + IPV4_DEFAULT_FILTERTING_RULES + MAX_OFFLOAD_PAIR + NUM_TCP_CTL_FLT_RULE; +#endif + +#ifdef FEATURE_IPA_ANDROID + offset = offset + wlan_ap_index * (IPA_MAX_PRIVATE_SUBNET_ENTRIES - IPACM_Iface::ipacmcfg->ipa_num_private_subnet); +#endif + for (int i = 0; i < IPA_MAX_PRIVATE_SUBNET_ENTRIES; i++) + { + private_fl_rule_hdl[i] = IPACM_Wlan::dummy_flt_rule_hdl_v4[offset+i]; + IPACMDBG_H("Private subnet v4 flt rule %d hdl:0x%x\n", i, private_fl_rule_hdl[i]); + } + } + return IPACM_SUCCESS; +} + +int IPACM_Wlan::eth_bridge_handle_dummy_wlan_client_flt_rule(ipa_ip_type iptype) +{ + int i, offset; + if(wlan_ap_index == 0) + { + if(iptype == IPA_IP_v4) + { + offset = IPV4_DEFAULT_FILTERTING_RULES; + for(i=0; icommit = 1; + pFilteringTable->ip = iptype; + pFilteringTable->num_rules = 1; + + /* point to LAN-WLAN routing table */ + memset(&flt_rule, 0, sizeof(struct ipa_flt_rule_mdfy)); + flt_rule.status = -1; + + flt_rule.rule.retain_hdr = 0; + flt_rule.rule.to_uc = 0; + flt_rule.rule.action = IPA_PASS_TO_ROUTING; + flt_rule.rule.eq_attrib_type = 0; + + if(iptype == IPA_IP_v4) + { + if (false == m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_eth_bridge_lan_wlan_v4)) + { + IPACMERR("Failed to get routing table handle.\n"); + res = IPACM_FAILURE; + goto fail; + } + flt_rule.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_eth_bridge_lan_wlan_v4.hdl; + IPACMDBG_H("WLAN->LAN IPv4 filter rule use table: %s\n",IPACM_Iface::ipacmcfg->rt_tbl_eth_bridge_lan_wlan_v4.name); + } + else + { + if (false == m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_eth_bridge_lan_wlan_v6)) + { + IPACMERR("Failed to get routing table handle.\n"); + res = IPACM_FAILURE; + goto fail; + } + flt_rule.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_eth_bridge_lan_wlan_v6.hdl; + IPACMDBG_H("WLAN->LAN IPv6 filter rule use table: %s\n",IPACM_Iface::ipacmcfg->rt_tbl_eth_bridge_lan_wlan_v6.name); + } + + memcpy(&flt_rule.rule.attrib, &rx_prop->rx[0].attrib, sizeof(flt_rule.rule.attrib)); + + /* Install meta-data if self or other ap is guest ap */ + if ((is_guest_ap == false && IPACM_Wlan::num_wlan_ap_iface == 1) || + IPACM_Iface::ipacmcfg->ipa_num_wlan_guest_ap == 0) + { + flt_rule.rule.attrib.attrib_mask &= ~((uint32_t)IPA_FLT_META_DATA); //remove meta data mask + } + + if(IPACM_Lan::wlan_hdr_type == IPA_HDR_L2_ETHERNET_II) + { + flt_rule.rule.attrib.attrib_mask |= IPA_FLT_MAC_DST_ADDR_ETHER_II; + } + else if(IPACM_Lan::wlan_hdr_type == IPA_HDR_L2_802_3) + { + flt_rule.rule.attrib.attrib_mask |= IPA_FLT_MAC_DST_ADDR_802_3; + } + else + { + IPACMERR("WLAN hdr type is not expected.\n"); + res = IPACM_FAILURE; + goto fail; + } + memcpy(flt_rule.rule.attrib.dst_mac_addr, mac, sizeof(flt_rule.rule.attrib.dst_mac_addr)); + memset(flt_rule.rule.attrib.dst_mac_addr_mask, 0xFF, sizeof(flt_rule.rule.attrib.dst_mac_addr_mask)); + + if(iptype == IPA_IP_v4) + { + for(i=0; irules[0]), &flt_rule, sizeof(struct ipa_flt_rule_mdfy)); + if (false == m_filtering.ModifyFilteringRule(pFilteringTable)) + { + IPACMERR("Failed to add wlan client filtering rules.\n"); + res = IPACM_FAILURE; + goto fail; + } + + if(client_is_found == false) + { + client_position = lan_client_flt_info_count; + lan_client_flt_info_count++; + } + + memcpy(eth_bridge_lan_client_flt_info[client_position].mac, mac, sizeof(eth_bridge_lan_client_flt_info[client_position].mac)); + if(iptype == IPA_IP_v4) + { + eth_bridge_lan_client_flt_info[client_position].flt_rule_set_v4 = true; + eth_bridge_lan_client_flt_info[client_position].flt_rule_hdl_v4 = lan_client_flt_rule_hdl_v4[i].rule_hdl; + } + else + { + eth_bridge_lan_client_flt_info[client_position].flt_rule_set_v6 = true; + eth_bridge_lan_client_flt_info[client_position].flt_rule_hdl_v6 = lan_client_flt_rule_hdl_v6[i].rule_hdl; + } + +fail: + free(pFilteringTable); + return res; +} + +int IPACM_Wlan::eth_bridge_del_lan_client_flt_rule(uint8_t* mac) +{ + if(mac == NULL) + { + IPACMERR("Client MAC address is empty.\n"); + return IPACM_FAILURE; + } + + IPACMDBG_H("Receive LAN client MAC 0x%02x%02x%02x%02x%02x%02x.\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + + int i, j, res = IPACM_SUCCESS; + for(i=0; icommit = 1; + pFilteringTable->ip = iptype; + pFilteringTable->num_rules = 1; + + /* point to LAN-WLAN routing table */ + memset(&flt_rule, 0, sizeof(struct ipa_flt_rule_mdfy)); + flt_rule.status = -1; + + flt_rule.rule.retain_hdr = 0; + flt_rule.rule.to_uc = 0; + flt_rule.rule.action = IPA_PASS_TO_ROUTING; + flt_rule.rule.eq_attrib_type = 0; + + if(iptype == IPA_IP_v4) + { + if (false == m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_eth_bridge_wlan_wlan_v4)) + { + IPACMERR("Failed to get routing table handle.\n"); + res = IPACM_FAILURE; + goto fail; + } + flt_rule.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_eth_bridge_wlan_wlan_v4.hdl; + IPACMDBG_H("WLAN->WLAN IPv4 filter rule use table: %s\n",IPACM_Iface::ipacmcfg->rt_tbl_eth_bridge_wlan_wlan_v4.name); + } + else + { + if (false == m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_eth_bridge_wlan_wlan_v6)) + { + IPACMERR("Failed to get routing table handle.\n"); + res = IPACM_FAILURE; + goto fail; + } + flt_rule.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_eth_bridge_wlan_wlan_v6.hdl; + IPACMDBG_H("WLAN->WLAN IPv4 filter rule use table: %s\n",IPACM_Iface::ipacmcfg->rt_tbl_eth_bridge_wlan_wlan_v6.name); + } + + memcpy(&flt_rule.rule.attrib, &rx_prop->rx[0].attrib, sizeof(flt_rule.rule.attrib)); + + /* Install meta-data if self or other ap is guest ap */ + if ((is_guest_ap == false && IPACM_Wlan::num_wlan_ap_iface == 1) || + IPACM_Iface::ipacmcfg->ipa_num_wlan_guest_ap == 0) + { + flt_rule.rule.attrib.attrib_mask &= ~((uint32_t)IPA_FLT_META_DATA); //remove meta data mask + } + + if(IPACM_Lan::wlan_hdr_type == IPA_HDR_L2_ETHERNET_II) + { + flt_rule.rule.attrib.attrib_mask |= IPA_FLT_MAC_DST_ADDR_ETHER_II; + } + else if(IPACM_Lan::wlan_hdr_type == IPA_HDR_L2_802_3) + { + flt_rule.rule.attrib.attrib_mask |= IPA_FLT_MAC_DST_ADDR_802_3; + } + else + { + IPACMERR("WLAN hdr type is not expected.\n"); + res = IPACM_FAILURE; + goto fail; + } + memcpy(flt_rule.rule.attrib.dst_mac_addr, mac, sizeof(flt_rule.rule.attrib.dst_mac_addr)); + memset(flt_rule.rule.attrib.dst_mac_addr_mask, 0xFF, sizeof(flt_rule.rule.attrib.dst_mac_addr_mask)); + + if(iptype == IPA_IP_v4) + { + for(i=0; irules[0]), &flt_rule, sizeof(struct ipa_flt_rule_mdfy)); + if (false == m_filtering.ModifyFilteringRule(pFilteringTable)) + { + IPACMERR("Failed to add self client filtering rules.\n"); + res = IPACM_FAILURE; + goto fail; + } + + if(client_is_found == false) + { + client_position = wlan_client_flt_info_count; + wlan_client_flt_info_count++; + } + + memcpy(eth_bridge_wlan_client_flt_info[client_position].mac, mac, sizeof(eth_bridge_wlan_client_flt_info[client_position].mac)); + if(iptype == IPA_IP_v4) + { + eth_bridge_wlan_client_flt_info[client_position].flt_rule_set_v4 = true; + eth_bridge_wlan_client_flt_info[client_position].flt_rule_hdl_v4 = self_client_flt_rule_hdl_v4[i].rule_hdl; + } + else + { + eth_bridge_wlan_client_flt_info[client_position].flt_rule_set_v6 = true; + eth_bridge_wlan_client_flt_info[client_position].flt_rule_hdl_v6 = self_client_flt_rule_hdl_v6[i].rule_hdl; + } + +fail: + free(pFilteringTable); + return res; +} + +int IPACM_Wlan::eth_bridge_del_self_client_flt_rule(uint8_t* mac) +{ + if(mac == NULL) + { + IPACMERR("Client MAC address is empty.\n"); + return IPACM_FAILURE; + } + + IPACMDBG_H("Receive WLAN client MAC 0x%02x%02x%02x%02x%02x%02x.\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + + int i, j, res = IPACM_SUCCESS; + for(i=0; imac, mac, sizeof(eth_bridge_get_client_rt_info_ptr(i, SRC_WLAN, iptype)->mac)) == 0) + { + IPACMDBG_H("The client's routing rule was added before.\n"); + return IPACM_SUCCESS; + } + } + memcpy(eth_bridge_get_client_rt_info_ptr(wlan_client_rt_from_wlan_info_count_v4, src, iptype)->mac, mac, + sizeof(eth_bridge_get_client_rt_info_ptr(wlan_client_rt_from_wlan_info_count_v4, src, iptype)->mac)); + } + else + { + for(i=0; imac, mac, sizeof(eth_bridge_get_client_rt_info_ptr(i, SRC_WLAN, iptype)->mac)) == 0) + { + IPACMDBG_H("The client's routing rule was added before.\n"); + return IPACM_SUCCESS; + } + } + memcpy(eth_bridge_get_client_rt_info_ptr(wlan_client_rt_from_wlan_info_count_v6, src, iptype)->mac, mac, + sizeof(eth_bridge_get_client_rt_info_ptr(wlan_client_rt_from_wlan_info_count_v6, src, iptype)->mac)); + } + } + else + { + if(iptype == IPA_IP_v4) + { + for(i=0; imac, mac, sizeof(eth_bridge_get_client_rt_info_ptr(i, SRC_LAN, iptype)->mac)) == 0) + { + IPACMDBG_H("The client's routing rule was added before.\n"); + return IPACM_SUCCESS; + } + } + memcpy(eth_bridge_get_client_rt_info_ptr(wlan_client_rt_from_lan_info_count_v4, src, iptype)->mac, mac, + sizeof(eth_bridge_get_client_rt_info_ptr(wlan_client_rt_from_lan_info_count_v4, src, iptype)->mac)); + } + else + { + for(i=0; imac, mac, sizeof(eth_bridge_get_client_rt_info_ptr(i, SRC_LAN, iptype)->mac)) == 0) + { + IPACMDBG_H("The client's routing rule was added before.\n"); + return IPACM_SUCCESS; + } + } + memcpy(eth_bridge_get_client_rt_info_ptr(wlan_client_rt_from_lan_info_count_v6, src, iptype)->mac, mac, + sizeof(eth_bridge_get_client_rt_info_ptr(wlan_client_rt_from_lan_info_count_v6, src, iptype)->mac)); + } + } + + if(iptype == IPA_IP_v4) + { + num_rt_rule = each_client_rt_rule_count_v4; + } + else + { + num_rt_rule = each_client_rt_rule_count_v6; + } + + len = sizeof(ipa_ioc_add_rt_rule) + num_rt_rule * sizeof(ipa_rt_rule_add); + rt_rule_table = (ipa_ioc_add_rt_rule*)malloc(len); + if(rt_rule_table == NULL) + { + IPACMERR("Failed to allocate memory.\n"); + return IPACM_FAILURE; + } + memset(rt_rule_table, 0, len); + + rt_rule_table->commit = 1; + rt_rule_table->ip = iptype; + rt_rule_table->num_rules = num_rt_rule; + if(src == SRC_WLAN) + { + if(iptype == IPA_IP_v4) + { + strlcpy(rt_rule_table->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_eth_bridge_wlan_wlan_v4.name, sizeof(rt_rule_table->rt_tbl_name)); + } + else + { + strlcpy(rt_rule_table->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_eth_bridge_wlan_wlan_v6.name, sizeof(rt_rule_table->rt_tbl_name)); + } + } + else + { + if(iptype == IPA_IP_v4) + { + strlcpy(rt_rule_table->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_eth_bridge_lan_wlan_v4.name, sizeof(rt_rule_table->rt_tbl_name)); + } + else + { + strlcpy(rt_rule_table->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_eth_bridge_lan_wlan_v6.name, sizeof(rt_rule_table->rt_tbl_name)); + } + } + rt_rule_table->rt_tbl_name[IPA_RESOURCE_NAME_MAX-1] = '\0'; + memset(&rt_rule, 0, sizeof(ipa_rt_rule_add)); + rt_rule.at_rear = false; + rt_rule.status = -1; + rt_rule.rt_rule_hdl = -1; + + rt_rule.rule.hdr_hdl = 0; + if(src == SRC_WLAN) + { + rt_rule.rule.hdr_proc_ctx_hdl = IPACM_Lan::wlan_to_wlan_hdr_proc_ctx.proc_ctx_hdl; + } + else + { + rt_rule.rule.hdr_proc_ctx_hdl = IPACM_Lan::lan_to_wlan_hdr_proc_ctx.proc_ctx_hdl; + } + position = 0; + for(i=0; inum_tx_props; i++) + { + if(tx_prop->tx[i].ip == iptype) + { + if(position >= num_rt_rule) + { + IPACMERR("Number of routing rules already exceeds limit.\n"); + res = IPACM_FAILURE; + goto fail; + } + /* Handle MCC Mode case */ + if (IPACM_Iface::ipacmcfg->isMCC_Mode == true) + { + IPACMDBG_H("In MCC mode, use alt dst pipe: %d\n", + tx_prop->tx[i].alt_dst_pipe); + rt_rule.rule.dst = tx_prop->tx[i].alt_dst_pipe; + } + else + { + rt_rule.rule.dst = tx_prop->tx[i].dst_pipe; + } + + memcpy(&rt_rule.rule.attrib, &tx_prop->tx[i].attrib, sizeof(rt_rule.rule.attrib)); + if(src == SRC_WLAN) //src is WLAN means packet is from WLAN + { + if(IPACM_Lan::wlan_hdr_type == IPA_HDR_L2_ETHERNET_II) + { + rt_rule.rule.attrib.attrib_mask |= IPA_FLT_MAC_DST_ADDR_ETHER_II; + } + else + { + rt_rule.rule.attrib.attrib_mask |= IPA_FLT_MAC_DST_ADDR_802_3; + } + } + else //packet is from LAN + { + if(IPACM_Lan::lan_hdr_type == IPA_HDR_L2_ETHERNET_II) + { + rt_rule.rule.attrib.attrib_mask |= IPA_FLT_MAC_DST_ADDR_ETHER_II; + } + else + { + rt_rule.rule.attrib.attrib_mask |= IPA_FLT_MAC_DST_ADDR_802_3; + } + } + memcpy(rt_rule.rule.attrib.dst_mac_addr, mac, sizeof(rt_rule.rule.attrib.dst_mac_addr)); + memset(rt_rule.rule.attrib.dst_mac_addr_mask, 0xFF, sizeof(rt_rule.rule.attrib.dst_mac_addr_mask)); + + memcpy(&(rt_rule_table->rules[position]), &rt_rule, sizeof(rt_rule_table->rules[position])); + position++; + } + } + if(false == m_routing.AddRoutingRule(rt_rule_table)) + { + IPACMERR("Routing rule addition failed!\n"); + res = IPACM_FAILURE; + goto fail; + } + else + { + if(src == SRC_WLAN) + { + for(i=0; irt_rule_hdl[i] = rt_rule_table->rules[i].rt_rule_hdl; + } + else + { + eth_bridge_get_client_rt_info_ptr(wlan_client_rt_from_wlan_info_count_v6, src, iptype)->rt_rule_hdl[i] = rt_rule_table->rules[i].rt_rule_hdl; + } + } + if(iptype == IPA_IP_v4) + { + wlan_client_rt_from_wlan_info_count_v4++; + IPACMDBG_H("Now the number of IPv4 rt rule on wlan-wlan rt table is %d.\n", wlan_client_rt_from_wlan_info_count_v4); + } + else + { + wlan_client_rt_from_wlan_info_count_v6++; + IPACMDBG_H("Now the number of IPv6 rt rule on wlan-wlan rt table is %d.\n", wlan_client_rt_from_wlan_info_count_v6); + } + } + else + { + for(i=0; irt_rule_hdl[i] = rt_rule_table->rules[i].rt_rule_hdl; + } + else + { + eth_bridge_get_client_rt_info_ptr(wlan_client_rt_from_lan_info_count_v6, src, iptype)->rt_rule_hdl[i] = rt_rule_table->rules[i].rt_rule_hdl; + } + } + if(iptype == IPA_IP_v4) + { + wlan_client_rt_from_lan_info_count_v4++; + IPACMDBG_H("Now the number of IPv4 rt rule on lan-wlan rt table is %d.\n", wlan_client_rt_from_lan_info_count_v4); + } + else + { + wlan_client_rt_from_lan_info_count_v6++; + IPACMDBG_H("Now the number of IPv6 rt rule on lan-wlan rt table is %d.\n", wlan_client_rt_from_lan_info_count_v6); + } + } + } + +fail: + if(rt_rule_table != NULL) + { + free(rt_rule_table); + } + return res; +} + +int IPACM_Wlan::eth_bridge_del_wlan_client_rt_rule(uint8_t* mac, eth_bridge_src_iface src) +{ + if(tx_prop == NULL) + { + IPACMDBG_H("Tx prop is empty, not deleting routing rule.\n"); + return IPACM_SUCCESS; + } + if(mac == NULL) + { + IPACMERR("Client MAC address is empty.\n"); + return IPACM_FAILURE; + } + + IPACMDBG_H("Receive WLAN client MAC 0x%02x%02x%02x%02x%02x%02x.\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + + int i, position; + + /* first delete the rt rules from IPv4 rt table*/ + if(src == SRC_WLAN) + { + for(i=0; imac, mac, sizeof(eth_bridge_get_client_rt_info_ptr(i, src, IPA_IP_v4)->mac)) == 0) + { + position = i; + IPACMDBG_H("The client is found at position %d.\n", position); + break; + } + } + if(i == wlan_client_rt_from_wlan_info_count_v4) + { + IPACMERR("The client is not found.\n"); + return IPACM_FAILURE; + } + } + else + { + for(i=0; imac, mac, sizeof(eth_bridge_get_client_rt_info_ptr(i, src, IPA_IP_v4)->mac)) == 0) + { + position = i; + IPACMDBG_H("The client is found at position %d.\n", position); + break; + } + } + if(i == wlan_client_rt_from_lan_info_count_v4) + { + IPACMERR("The client is not found.\n"); + return IPACM_FAILURE; + } + } + + for(i=0; irt_rule_hdl[i], IPA_IP_v4) == false) + { + IPACMERR("Failed to delete routing rule %d.\n", i); + return IPACM_FAILURE; + } + } + + if(src == SRC_WLAN) + { + for(i=position+1; imac, mac, sizeof(eth_bridge_get_client_rt_info_ptr(i, src, IPA_IP_v6)->mac)) == 0) + { + position = i; + IPACMDBG_H("The client is found at position %d.\n", position); + break; + } + } + if(i == wlan_client_rt_from_wlan_info_count_v6) + { + IPACMERR("The client is not found.\n"); + return IPACM_FAILURE; + } + } + else + { + for(i=0; imac, mac, sizeof(eth_bridge_get_client_rt_info_ptr(i, src, IPA_IP_v6)->mac)) == 0) + { + position = i; + IPACMDBG_H("The client is found at position %d.\n", position); + break; + } + } + if(i == wlan_client_rt_from_lan_info_count_v6) + { + IPACMERR("The client is not found.\n"); + return IPACM_FAILURE; + } + } + + for(i=0; irt_rule_hdl[i], IPA_IP_v6) == false) + { + IPACMERR("Failed to delete routing rule %d.\n", i); + return IPACM_FAILURE; + } + } + + if(src == SRC_WLAN) + { + for(i=position+1; icommit = 0; + rt_rule->num_rules = NUM; + rt_rule->ip = iptype; + } + rt_rule_entry = &rt_rule->rules[0]; + + /* modify ipv4 routing rule */ + if (iptype == IPA_IP_v4) + { + for (wlan_index = 0; wlan_index < num_wifi_client_tmp; wlan_index++) + { + IPACMDBG_H("wlan client index: %d, ip-type: %d, ipv4_set:%d, ipv4_rule_set:%d \n", + wlan_index, iptype, + get_client_memptr(wlan_client, wlan_index)->ipv4_set, + get_client_memptr(wlan_client, wlan_index)->route_rule_set_v4); + + if (get_client_memptr(wlan_client, wlan_index)->power_save_set == true || + get_client_memptr(wlan_client, wlan_index)->route_rule_set_v4 == false) + { + IPACMDBG_H("client %d route rules not set\n", wlan_index); + continue; + } + + IPACMDBG_H("Modify client %d route rule\n", wlan_index); + for (tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++) + { + if (iptype != tx_prop->tx[tx_index].ip) + { + IPACMDBG_H("Tx:%d, ip-type: %d ip-type not matching: %d ignore\n", + tx_index, tx_prop->tx[tx_index].ip, iptype); + continue; + } + + IPACMDBG_H("client index(%d):ipv4 address: 0x%x\n", wlan_index, + get_client_memptr(wlan_client, wlan_index)->v4_addr); + + IPACMDBG_H("client(%d): v4 header handle:(0x%x)\n", + wlan_index, + get_client_memptr(wlan_client, wlan_index)->hdr_hdl_v4); + + if (IPACM_Iface::ipacmcfg->isMCC_Mode) + { + IPACMDBG_H("In MCC mode, use alt dst pipe: %d\n", + tx_prop->tx[tx_index].alt_dst_pipe); + rt_rule_entry->rule.dst = tx_prop->tx[tx_index].alt_dst_pipe; + } + else + { + rt_rule_entry->rule.dst = tx_prop->tx[tx_index].dst_pipe; + } + + memcpy(&rt_rule_entry->rule.attrib, + &tx_prop->tx[tx_index].attrib, + sizeof(rt_rule_entry->rule.attrib)); + + rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; + rt_rule_entry->rule.hdr_hdl = get_client_memptr(wlan_client, wlan_index)->hdr_hdl_v4; + + rt_rule_entry->rule.attrib.u.v4.dst_addr = get_client_memptr(wlan_client, wlan_index)->v4_addr; + rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF; + + IPACMDBG_H("tx:%d, rt rule hdl=%x ip-type: %d\n", tx_index, + get_client_memptr(wlan_client, wlan_index)->wifi_rt_hdl[tx_index].wifi_rt_rule_hdl_v4, iptype); + + rt_rule_entry->rt_rule_hdl = + get_client_memptr(wlan_client, wlan_index)->wifi_rt_hdl[tx_index].wifi_rt_rule_hdl_v4; + + if (false == m_routing.ModifyRoutingRule(rt_rule)) + { + IPACMERR("Routing rule modify failed!\n"); + free(rt_rule); + return; + } + isAdded = true; + } + + } + } + + /* modify ipv6 routing rule */ + if (iptype == IPA_IP_v6) + { + for (wlan_index = 0; wlan_index < num_wifi_client_tmp; wlan_index++) + { + + IPACMDBG_H("wlan client index: %d, ip-type: %d, ipv6_set:%d, ipv6_rule_num:%d \n", wlan_index, iptype, + get_client_memptr(wlan_client, wlan_index)->ipv6_set, + get_client_memptr(wlan_client, wlan_index)->route_rule_set_v6); + + if (get_client_memptr(wlan_client, wlan_index)->power_save_set == true || + (get_client_memptr(wlan_client, wlan_index)->route_rule_set_v6 < + get_client_memptr(wlan_client, wlan_index)->ipv6_set) ) + { + IPACMDBG_H("client %d route rules not set\n", wlan_index); + continue; + } + + IPACMDBG_H("Modify client %d route rule\n", wlan_index); + for (tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++) + { + if (iptype != tx_prop->tx[tx_index].ip) + { + IPACMDBG_H("Tx:%d, ip-type: %d ip-type not matching: %d Ignore\n", + tx_index, tx_prop->tx[tx_index].ip, iptype); + continue; + } + + for (v6_num = get_client_memptr(wlan_client, wlan_index)->route_rule_set_v6; + v6_num < get_client_memptr(wlan_client, wlan_index)->ipv6_set; + v6_num++) + { + + IPACMDBG_H("client(%d): v6 header handle:(0x%x)\n", + wlan_index, + get_client_memptr(wlan_client, wlan_index)->hdr_hdl_v6); + + if (IPACM_Iface::ipacmcfg->isMCC_Mode) + { + IPACMDBG_H("In MCC mode, use alt dst pipe: %d\n", + tx_prop->tx[tx_index].alt_dst_pipe); + rt_rule_entry->rule.dst = tx_prop->tx[tx_index].alt_dst_pipe; + } + else + { + rt_rule_entry->rule.dst = tx_prop->tx[tx_index].dst_pipe; + } + + memcpy(&rt_rule_entry->rule.attrib, + &tx_prop->tx[tx_index].attrib, + sizeof(rt_rule_entry->rule.attrib)); + + rt_rule_entry->rule.hdr_hdl = get_client_memptr(wlan_client, wlan_index)->hdr_hdl_v6; + rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; + + rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = get_client_memptr(wlan_client, wlan_index)->v6_addr[v6_num][0]; + rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = get_client_memptr(wlan_client, wlan_index)->v6_addr[v6_num][1]; + rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = get_client_memptr(wlan_client, wlan_index)->v6_addr[v6_num][2]; + rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = get_client_memptr(wlan_client, wlan_index)->v6_addr[v6_num][3]; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0xFFFFFFFF; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF; + + rt_rule_entry->rt_rule_hdl = + get_client_memptr(wlan_client, wlan_index)->wifi_rt_hdl[tx_index].wifi_rt_rule_hdl_v6_wan[v6_num]; + + if (false == m_routing.ModifyRoutingRule(rt_rule)) + { + IPACMERR("Routing rule modify failed!\n"); + free(rt_rule); + return; + } + isAdded = true; + } + } + + } + } + + + if (isAdded) + { + if (false == m_routing.Commit(iptype)) + { + IPACMERR("Routing rule modify commit failed!\n"); + free(rt_rule); + return; + } + + IPACMDBG("Routing rule modified successfully \n"); + } + + if(rt_rule) + { + free(rt_rule); + } + return; +} + +void IPACM_Wlan::eth_bridge_handle_wlan_SCC_MCC_switch(ipa_ip_type iptype) +{ + + for (int i= 0; i < IPACM_Lan::num_wlan_client; i++) + { + if (IPACM_Lan::eth_bridge_wlan_client[i].ipa_if_num == ipa_if_num) + { + if (IPACM_Lan::wlan_to_wlan_hdr_proc_ctx.valid == true) + { + if (eth_bridge_modify_wlan_rt_rule(IPACM_Lan::eth_bridge_wlan_client[i].mac, SRC_WLAN, iptype) == IPACM_FAILURE) + { + IPACMDBG_H("SCC/MCC switch is failed for iptype: %d src_iface: %d \n", iptype, SRC_WLAN); + return; + } + } + if (IPACM_Lan::lan_to_wlan_hdr_proc_ctx.valid == true) + { + if (eth_bridge_modify_wlan_rt_rule(IPACM_Lan::eth_bridge_wlan_client[i].mac, SRC_LAN, iptype) == IPACM_FAILURE) + { + IPACMDBG_H("SCC/MCC switch is failed for iptype: %d src_iface: %d \n", iptype, SRC_LAN); + return; + } + } + } + } + + IPACMDBG_H("SCC/MCC switch is successful for iptype: %d\n", iptype); +} + +int IPACM_Wlan::eth_bridge_modify_wlan_rt_rule(uint8_t* mac, eth_bridge_src_iface src_iface, ipa_ip_type iptype) +{ + struct ipa_ioc_mdfy_rt_rule *rt_rule = NULL; + struct ipa_rt_rule_mdfy *rt_rule_entry; + uint32_t index = 0, num_rt_rule = 0, position; + + if (tx_prop == NULL) + { + IPACMDBG_H("No tx properties \n"); + return IPACM_FAILURE; + } + + if (mac == NULL) + { + IPACMERR("Client MAC address is empty.\n"); + return IPACM_FAILURE; + } + + IPACMDBG_H("Receive WLAN client MAC 0x%02x%02x%02x%02x%02x%02x. src_iface: %d\n", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], src_iface); + + if (iptype == IPA_IP_v4) + { + num_rt_rule = each_client_rt_rule_count_v4; + } + else + { + num_rt_rule = each_client_rt_rule_count_v6; + } + + if (src_iface == SRC_WLAN) + { + if (iptype == IPA_IP_v4) + { + for (index = 0; index < wlan_client_rt_from_wlan_info_count_v4; index++) + { + if (memcmp(eth_bridge_get_client_rt_info_ptr(index, src_iface, IPA_IP_v4)->mac, mac, + sizeof(eth_bridge_get_client_rt_info_ptr(index, src_iface, IPA_IP_v4)->mac)) == 0) + { + position = index; + IPACMDBG_H("The client is found at position %d.\n", position); + break; + } + } + if (index == wlan_client_rt_from_wlan_info_count_v4) + { + IPACMERR("The client is not found.\n"); + return IPACM_FAILURE; + } + } + else + { + for (index =0 ; index < wlan_client_rt_from_wlan_info_count_v6; index++) + { + if (memcmp(eth_bridge_get_client_rt_info_ptr(index, src_iface, IPA_IP_v6)->mac, mac, + sizeof(eth_bridge_get_client_rt_info_ptr(index, src_iface, IPA_IP_v6)->mac)) == 0) + { + position = index; + IPACMDBG_H("The client is found at position %d.\n", position); + break; + } + } + if (index == wlan_client_rt_from_wlan_info_count_v6) + { + IPACMERR("The client is not found.\n"); + return IPACM_FAILURE; + } + } + } + else + { + if (iptype == IPA_IP_v4) + { + for (index = 0; index < wlan_client_rt_from_lan_info_count_v4; index++) + { + if (memcmp(eth_bridge_get_client_rt_info_ptr(index, src_iface, IPA_IP_v4)->mac, mac, + sizeof(eth_bridge_get_client_rt_info_ptr(index, src_iface, IPA_IP_v4)->mac)) == 0) + { + position = index; + IPACMDBG_H("The client is found at position %d.\n", position); + break; + } + } + if (index == wlan_client_rt_from_lan_info_count_v4) + { + IPACMERR("The client is not found.\n"); + return IPACM_FAILURE; + } + } + else + { + for (index = 0; index < wlan_client_rt_from_lan_info_count_v6; index++) + { + if (memcmp(eth_bridge_get_client_rt_info_ptr(index, src_iface, IPA_IP_v6)->mac, mac, + sizeof(eth_bridge_get_client_rt_info_ptr(index, src_iface, IPA_IP_v6)->mac)) == 0) + { + position = index; + IPACMDBG_H("The client is found at position %d.\n", position); + break; + } + } + if (index == wlan_client_rt_from_lan_info_count_v6) + { + IPACMERR("The client is not found.\n"); + return IPACM_FAILURE; + } + } + } + + rt_rule = (struct ipa_ioc_mdfy_rt_rule *) + calloc(1, sizeof(struct ipa_ioc_mdfy_rt_rule) + + (num_rt_rule) * sizeof(struct ipa_rt_rule_mdfy)); + + if (rt_rule == NULL) + { + IPACMERR("Unable to allocate memory for modify rt rule\n"); + return IPACM_FAILURE; + } + IPACMDBG("Allocated memory for %d rules successfully\n", num_rt_rule); + + rt_rule->commit = 1; + rt_rule->num_rules = 0; + rt_rule->ip = iptype; + + for (index = 0; index < tx_prop->num_tx_props; index++) + { + if (tx_prop->tx[index].ip == iptype) + { + if (rt_rule->num_rules >= num_rt_rule) + { + IPACMERR("Number of routing rules exceeds limit.\n"); + free(rt_rule); + return IPACM_FAILURE; + } + + rt_rule_entry = &rt_rule->rules[rt_rule->num_rules]; + + if (IPACM_Iface::ipacmcfg->isMCC_Mode) + { + IPACMDBG_H("In MCC mode, use alt dst pipe: %d\n", + tx_prop->tx[index].alt_dst_pipe); + rt_rule_entry->rule.dst = tx_prop->tx[index].alt_dst_pipe; + } + else + { + rt_rule_entry->rule.dst = tx_prop->tx[index].dst_pipe; + } + + rt_rule_entry->rule.hdr_hdl = 0; + + if (src_iface == SRC_WLAN) + { + rt_rule_entry->rule.hdr_proc_ctx_hdl = + IPACM_Lan::wlan_to_wlan_hdr_proc_ctx.proc_ctx_hdl; + } + else + { + rt_rule_entry->rule.hdr_proc_ctx_hdl = + IPACM_Lan::lan_to_wlan_hdr_proc_ctx.proc_ctx_hdl; + } + + memcpy(&rt_rule_entry->rule.attrib, + &tx_prop->tx[index].attrib, + sizeof(rt_rule_entry->rule.attrib)); + + if (src_iface == SRC_WLAN) //src is WLAN means packet is from WLAN + { + if (IPACM_Lan::wlan_hdr_type == IPA_HDR_L2_ETHERNET_II) + { + rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_MAC_DST_ADDR_ETHER_II; + } + else + { + rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_MAC_DST_ADDR_802_3; + } + } + else //packet is from LAN + { + if (IPACM_Lan::lan_hdr_type == IPA_HDR_L2_ETHERNET_II) + { + rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_MAC_DST_ADDR_ETHER_II; + } + else + { + rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_MAC_DST_ADDR_802_3; + } + } + memcpy(rt_rule_entry->rule.attrib.dst_mac_addr, mac, + sizeof(rt_rule_entry->rule.attrib.dst_mac_addr)); + memset(rt_rule_entry->rule.attrib.dst_mac_addr_mask, 0xFF, + sizeof(rt_rule_entry->rule.attrib.dst_mac_addr_mask)); + + rt_rule_entry->rt_rule_hdl = + eth_bridge_get_client_rt_info_ptr(position, src_iface, iptype)->rt_rule_hdl[rt_rule->num_rules]; + IPACMDBG_H("tx:%d, rt rule hdl=%x ip-type: %d\n", index, + eth_bridge_get_client_rt_info_ptr(position, src_iface, iptype)->rt_rule_hdl[rt_rule->num_rules], iptype); + + rt_rule->num_rules++; + } + } + + if (rt_rule->num_rules > 0) + { + if (false == m_routing.ModifyRoutingRule(rt_rule)) + { + IPACMERR("Routing rule modify failed!\n"); + free(rt_rule); + return IPACM_FAILURE; + } + if (false == m_routing.Commit(iptype)) + { + IPACMERR("Routing rule modify commit failed!\n"); + free(rt_rule); + return IPACM_FAILURE; + } + IPACMDBG("Routing rule modified successfully \n"); + } + + if (rt_rule) + { + free(rt_rule); + } + return IPACM_SUCCESS; +} + +void IPACM_Wlan::eth_bridge_handle_wlan_mode_switch() +{ + int i; + + for (i=0; icommit = 1; + pFilteringTable->ip = iptype; + pFilteringTable->num_rules = 1; + + /* point to WLAN-WLAN routing table */ + memset(&flt_rule, 0, sizeof(struct ipa_flt_rule_mdfy)); + flt_rule.status = -1; + flt_rule.rule.retain_hdr = 0; + flt_rule.rule.to_uc = 0; + flt_rule.rule.action = IPA_PASS_TO_ROUTING; + flt_rule.rule.eq_attrib_type = 0; + + if (dst_iface == DST_WLAN) + { + if(iptype == IPA_IP_v4) + { + if (false == m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_eth_bridge_wlan_wlan_v4)) + { + IPACMERR("Failed to get routing table handle.\n"); + res = IPACM_FAILURE; + goto fail; + } + flt_rule.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_eth_bridge_wlan_wlan_v4.hdl; + IPACMDBG_H("WLAN->WLAN IPv4 filter rule use table: %s\n",IPACM_Iface::ipacmcfg->rt_tbl_eth_bridge_wlan_wlan_v4.name); + } + else + { + if (false == m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_eth_bridge_wlan_wlan_v6)) + { + IPACMERR("Failed to get routing table handle.\n"); + res = IPACM_FAILURE; + goto fail; + } + flt_rule.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_eth_bridge_wlan_wlan_v6.hdl; + IPACMDBG_H("WLAN->WLAN IPv6 filter rule use table: %s\n",IPACM_Iface::ipacmcfg->rt_tbl_eth_bridge_wlan_wlan_v6.name); + } + } + else + { + if(iptype == IPA_IP_v4) + { + if (false == m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_eth_bridge_lan_wlan_v4)) + { + IPACMERR("Failed to get routing table handle.\n"); + res = IPACM_FAILURE; + goto fail; + } + flt_rule.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_eth_bridge_lan_wlan_v4.hdl; + IPACMDBG_H("WLAN->LAN IPv4 filter rule use table: %s\n",IPACM_Iface::ipacmcfg->rt_tbl_eth_bridge_lan_wlan_v4.name); + } + else + { + if (false == m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_eth_bridge_lan_wlan_v6)) + { + IPACMERR("Failed to get routing table handle.\n"); + res = IPACM_FAILURE; + } + flt_rule.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_eth_bridge_lan_wlan_v6.hdl; + IPACMDBG_H("WLAN->LAN IPv6 filter rule use table: %s\n",IPACM_Iface::ipacmcfg->rt_tbl_eth_bridge_lan_wlan_v6.name); + } + } + + memcpy(&flt_rule.rule.attrib, &rx_prop->rx[0].attrib, sizeof(flt_rule.rule.attrib)); + + /* Install meta-data if self or other ap is guest ap */ + if ((is_guest_ap == false && IPACM_Wlan::num_wlan_ap_iface == 1) || + IPACM_Iface::ipacmcfg->ipa_num_wlan_guest_ap == 0) + { + flt_rule.rule.attrib.attrib_mask &= ~((uint32_t)IPA_FLT_META_DATA); //remove meta data mask + } + + if(IPACM_Lan::wlan_hdr_type == IPA_HDR_L2_ETHERNET_II) + { + flt_rule.rule.attrib.attrib_mask |= IPA_FLT_MAC_DST_ADDR_ETHER_II; + } + else if(IPACM_Lan::wlan_hdr_type == IPA_HDR_L2_802_3) + { + flt_rule.rule.attrib.attrib_mask |= IPA_FLT_MAC_DST_ADDR_802_3; + } + else + { + IPACMERR("WLAN hdr type is not expected.\n"); + res = IPACM_FAILURE; + goto fail; + } + memcpy(flt_rule.rule.attrib.dst_mac_addr, mac, sizeof(flt_rule.rule.attrib.dst_mac_addr)); + memset(flt_rule.rule.attrib.dst_mac_addr_mask, 0xFF, sizeof(flt_rule.rule.attrib.dst_mac_addr_mask)); + + if (dst_iface == DST_WLAN) + { + if(iptype == IPA_IP_v4) + { + flt_rule.rule_hdl = eth_bridge_wlan_client_flt_info[client_position].flt_rule_hdl_v4; + } + else + { + flt_rule.rule_hdl = eth_bridge_wlan_client_flt_info[client_position].flt_rule_hdl_v6; + } + } + else + { + if(iptype == IPA_IP_v4) + { + flt_rule.rule_hdl = eth_bridge_lan_client_flt_info[client_position].flt_rule_hdl_v4; + } + else + { + flt_rule.rule_hdl = eth_bridge_lan_client_flt_info[client_position].flt_rule_hdl_v6; + } + } + memcpy(&(pFilteringTable->rules[0]), &flt_rule, sizeof(struct ipa_flt_rule_mdfy)); + if (false == m_filtering.ModifyFilteringRule(pFilteringTable)) + { + IPACMERR("Failed to modify wlan client filtering rule.\n"); + res = IPACM_FAILURE; + goto fail; + } +fail: + free(pFilteringTable); + return res; +} + +int IPACM_Wlan::install_ipv6_prefix_flt_rule(uint32_t* prefix) +{ + int i, len, res = IPACM_SUCCESS, offset; + struct ipa_flt_rule_mdfy flt_rule; + struct ipa_ioc_mdfy_flt_rule* pFilteringTable; + + if (rx_prop == NULL) + { + IPACMDBG_H("No rx properties registered for iface %s\n", dev_name); + return IPACM_SUCCESS; + } + + if(IPACM_Wlan::dummy_flt_rule_hdl_v6 == NULL) + { + IPACMERR("Dummy ipv6 flt rule has not been installed.\n"); + return IPACM_FAILURE; + } + if(wlan_ap_index >= 2) + { + IPACMERR("Cannot support more than 2 WLAN AP, abort.\n"); + return IPACM_FAILURE; + } + +#ifdef FEATURE_ETH_BRIDGE_LE + offset = IPV6_DEFAULT_FILTERTING_RULES + IPA_LAN_TO_LAN_MAX_WLAN_CLIENT + IPA_LAN_TO_LAN_MAX_LAN_CLIENT + wlan_ap_index; +#else +#ifndef CT_OPT + offset = 2*(IPV6_DEFAULT_FILTERTING_RULES + MAX_OFFLOAD_PAIR) + wlan_ap_index; +#else + offset = 2*(IPV6_DEFAULT_FILTERTING_RULES + NUM_TCP_CTL_FLT_RULE + MAX_OFFLOAD_PAIR) + wlan_ap_index; +#endif +#endif + + len = sizeof(struct ipa_ioc_mdfy_flt_rule) + sizeof(struct ipa_flt_rule_mdfy); + pFilteringTable = (struct ipa_ioc_mdfy_flt_rule*)malloc(len); + if (!pFilteringTable) + { + IPACMERR("Failed to allocate ipa_ioc_mdfy_flt_rule memory...\n"); + return IPACM_FAILURE; + } + memset(pFilteringTable, 0, len); + + pFilteringTable->commit = 1; + pFilteringTable->ip = IPA_IP_v6; + pFilteringTable->num_rules = 1; + + memset(&flt_rule, 0, sizeof(flt_rule)); + flt_rule.status = -1; + flt_rule.rule_hdl = IPACM_Wlan::dummy_flt_rule_hdl_v6[offset]; + + flt_rule.rule.retain_hdr = 1; + flt_rule.rule.to_uc = 0; + flt_rule.rule.action = IPA_PASS_TO_EXCEPTION; + flt_rule.rule.eq_attrib_type = 0; + + memcpy(&flt_rule.rule.attrib, &rx_prop->rx[0].attrib, sizeof(flt_rule.rule.attrib)); + flt_rule.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; + flt_rule.rule.attrib.u.v6.dst_addr[0] = prefix[0]; + flt_rule.rule.attrib.u.v6.dst_addr[1] = prefix[1]; + flt_rule.rule.attrib.u.v6.dst_addr[2] = 0x0; + flt_rule.rule.attrib.u.v6.dst_addr[3] = 0x0; + flt_rule.rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF; + flt_rule.rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF; + flt_rule.rule.attrib.u.v6.dst_addr_mask[2] = 0x0; + flt_rule.rule.attrib.u.v6.dst_addr_mask[3] = 0x0; + memcpy(&(pFilteringTable->rules[0]), &flt_rule, sizeof(flt_rule)); + + if (false == m_filtering.ModifyFilteringRule(pFilteringTable)) + { + IPACMERR("Failed to modify tcp control filtering rules.\n"); + free(pFilteringTable); + return IPACM_FAILURE; + } + else + { + ipv6_prefix_flt_rule_hdl[0] = IPACM_Wlan::dummy_flt_rule_hdl_v6[offset]; + IPACMDBG_H("IPv6 prefix filter rule HDL:0x%x\n", ipv6_prefix_flt_rule_hdl[0]); + } + + free(pFilteringTable); + return IPACM_SUCCESS; +} + +void IPACM_Wlan::delete_ipv6_prefix_flt_rule() +{ + if(reset_to_dummy_flt_rule(IPA_IP_v6, ipv6_prefix_flt_rule_hdl[0]) == IPACM_FAILURE) + { + IPACMERR("Failed to delete ipv6 prefix flt rule.\n"); + } + return; +} diff --git a/data-ipa-cfg-mgr/ipacm/src/IPACM_Xml.cpp b/data-ipa-cfg-mgr/ipacm/src/IPACM_Xml.cpp new file mode 100644 index 000000000..bcb5b6b07 --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/src/IPACM_Xml.cpp @@ -0,0 +1,1154 @@ +/* +Copyright (c) 2013, The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +/*! + @file + IPACM_Xml.cpp + + @brief + This file implements the XML specific parsing functionality. + + @Author + Skylar Chang/Shihuan Liu +*/ + +#include +#include +#include + +#include "IPACM_Xml.h" +#include "IPACM_Log.h" +#include "IPACM_Netlink.h" + +static char* IPACM_read_content_element +( + xmlNode* element +); + +static int32_t IPACM_util_icmp_string +( + const char* xml_str, + const char* str +); + +static int ipacm_cfg_xml_parse_tree +( + xmlNode* xml_node, + IPACM_conf_t *config +); + +static int IPACM_firewall_xml_parse_tree +( + xmlNode* xml_node, + IPACM_firewall_conf_t *config +); + +/*Reads content (stored as child) of the element */ +static char* IPACM_read_content_element +( + xmlNode* element +) +{ + xmlNode* child_ptr; + + for (child_ptr = element->children; + child_ptr != NULL; + child_ptr = child_ptr->next) + { + if (child_ptr->type == XML_TEXT_NODE) + { + return (char*)child_ptr->content; + } + } + return NULL; +} + +/* insensitive comparison of a libxml's string (xml_str) and a regular string (str)*/ +static int32_t IPACM_util_icmp_string +( + const char* xml_str, + const char* str +) +{ + int32_t ret = -1; + + if (NULL != xml_str && NULL != str) + { + uint32_t len1 = strlen(str); + uint32_t len2 = strlen(xml_str); + /* If the lengths match, do the string comparison */ + if (len1 == len2) + { + ret = strncasecmp(xml_str, str, len1); + } + } + + return ret; +} + +/* This function read IPACM XML and populate the IPA CM Cfg */ +int ipacm_read_cfg_xml(char *xml_file, IPACM_conf_t *config) +{ + xmlDocPtr doc = NULL; + xmlNode* root = NULL; + int ret_val = IPACM_SUCCESS; + + /* Invoke the XML parser and obtain the parse tree */ + doc = xmlReadFile(xml_file, "UTF-8", XML_PARSE_NOBLANKS); + if (doc == NULL) { + IPACMDBG_H("IPACM_xml_parse: libxml returned parse error!\n"); + return IPACM_FAILURE; + } + + /*Get the root of the tree*/ + root = xmlDocGetRootElement(doc); + + memset(config, 0, sizeof(IPACM_conf_t)); + + /* parse the xml tree returned by libxml */ + ret_val = ipacm_cfg_xml_parse_tree(root, config); + + if (ret_val != IPACM_SUCCESS) + { + IPACMDBG_H("IPACM_xml_parse: ipacm_cfg_xml_parse_tree returned parse error!\n"); + } + + /* Free up the libxml's parse tree */ + xmlFreeDoc(doc); + + return ret_val; +} + +/* This function traverses the xml tree*/ +static int ipacm_cfg_xml_parse_tree +( + xmlNode* xml_node, + IPACM_conf_t *config +) +{ + int32_t ret_val = IPACM_SUCCESS; + int str_size; + char* content; + char content_buf[MAX_XML_STR_LEN]; + + if (NULL == xml_node) + return ret_val; + while ( xml_node != NULL && + ret_val == IPACM_SUCCESS) + { + switch (xml_node->type) + { + case XML_ELEMENT_NODE: + { + if (IPACM_util_icmp_string((char*)xml_node->name, system_TAG) == 0 || + IPACM_util_icmp_string((char*)xml_node->name, ODU_TAG) == 0 || + IPACM_util_icmp_string((char*)xml_node->name, IPACMCFG_TAG) == 0 || + IPACM_util_icmp_string((char*)xml_node->name, IPACMIFACECFG_TAG) == 0 || + IPACM_util_icmp_string((char*)xml_node->name, IFACE_TAG) == 0 || + IPACM_util_icmp_string((char*)xml_node->name, IPACMPRIVATESUBNETCFG_TAG) == 0 || + IPACM_util_icmp_string((char*)xml_node->name, SUBNET_TAG) == 0 || + IPACM_util_icmp_string((char*)xml_node->name, IPACMALG_TAG) == 0 || + IPACM_util_icmp_string((char*)xml_node->name, ALG_TAG) == 0 || + IPACM_util_icmp_string((char*)xml_node->name, IPACMNat_TAG) == 0) + { + if (0 == IPACM_util_icmp_string((char*)xml_node->name, IFACE_TAG)) + { + /* increase iface entry number */ + config->iface_config.num_iface_entries++; + } + + if (0 == IPACM_util_icmp_string((char*)xml_node->name, SUBNET_TAG)) + { + /* increase iface entry number */ + config->private_subnet_config.num_subnet_entries++; + } + + if (0 == IPACM_util_icmp_string((char*)xml_node->name, ALG_TAG)) + { + /* increase iface entry number */ + config->alg_config.num_alg_entries++; + } + /* go to child */ + ret_val = ipacm_cfg_xml_parse_tree(xml_node->children, config); + } + else if (IPACM_util_icmp_string((char*)xml_node->name, ODUMODE_TAG) == 0) + { + IPACMDBG_H("inside ODU-XML\n"); + content = IPACM_read_content_element(xml_node); + if (content) + { + str_size = strlen(content); + memset(content_buf, 0, sizeof(content_buf)); + memcpy(content_buf, (void *)content, str_size); + if (0 == strncasecmp(content_buf, ODU_ROUTER_TAG, str_size)) + { + config->router_mode_enable = true; + IPACMDBG_H("router-mode enable %d\n", config->router_mode_enable); + } + else if (0 == strncasecmp(content_buf, ODU_BRIDGE_TAG, str_size)) + { + config->router_mode_enable = false; + IPACMDBG_H("router-mode enable %d\n", config->router_mode_enable); + } + } + } + else if (IPACM_util_icmp_string((char*)xml_node->name, ODUEMBMS_OFFLOAD_TAG) == 0) + { + IPACMDBG_H("inside ODU-XML\n"); + content = IPACM_read_content_element(xml_node); + if (content) + { + str_size = strlen(content); + memset(content_buf, 0, sizeof(content_buf)); + memcpy(content_buf, (void *)content, str_size); + if (atoi(content_buf)) + { + config->odu_embms_enable = true; + IPACMDBG_H("router-mode enable %d buf(%d)\n", config->odu_embms_enable, atoi(content_buf)); + } + else + { + config->odu_embms_enable = false; + IPACMDBG_H("router-mode enable %d buf(%d)\n", config->odu_embms_enable, atoi(content_buf)); + } + } + } + else if (IPACM_util_icmp_string((char*)xml_node->name, NAME_TAG) == 0) + { + content = IPACM_read_content_element(xml_node); + if (content) + { + str_size = strlen(content); + memset(content_buf, 0, sizeof(content_buf)); + memcpy(content_buf, (void *)content, str_size); + strncpy(config->iface_config.iface_entries[config->iface_config.num_iface_entries - 1].iface_name, content_buf, str_size); + IPACMDBG_H("Name %s\n", config->iface_config.iface_entries[config->iface_config.num_iface_entries - 1].iface_name); + } + } + else if (IPACM_util_icmp_string((char*)xml_node->name, CATEGORY_TAG) == 0) + { + content = IPACM_read_content_element(xml_node); + if (content) + { + str_size = strlen(content); + memset(content_buf, 0, sizeof(content_buf)); + memcpy(content_buf, (void *)content, str_size); + if (0 == strncasecmp(content_buf, WANIF_TAG, str_size)) + { + config->iface_config.iface_entries[config->iface_config.num_iface_entries - 1].if_cat = WAN_IF; + IPACMDBG_H("Category %d\n", config->iface_config.iface_entries[config->iface_config.num_iface_entries - 1].if_cat); + } + else if (0 == strncasecmp(content_buf, LANIF_TAG, str_size)) + { + config->iface_config.iface_entries[config->iface_config.num_iface_entries - 1].if_cat = LAN_IF; + IPACMDBG_H("Category %d\n", config->iface_config.iface_entries[config->iface_config.num_iface_entries - 1].if_cat); + } + else if (0 == strncasecmp(content_buf, WLANIF_TAG, str_size)) + { + config->iface_config.iface_entries[config->iface_config.num_iface_entries - 1].if_cat = WLAN_IF; + IPACMDBG_H("Category %d\n", config->iface_config.iface_entries[config->iface_config.num_iface_entries - 1].if_cat); + } + else if (0 == strncasecmp(content_buf, VIRTUALIF_TAG, str_size)) + { + config->iface_config.iface_entries[config->iface_config.num_iface_entries - 1].if_cat = VIRTUAL_IF; + IPACMDBG_H("Category %d\n", config->iface_config.iface_entries[config->iface_config.num_iface_entries - 1].if_cat); + } + else if (0 == strncasecmp(content_buf, UNKNOWNIF_TAG, str_size)) + { + config->iface_config.iface_entries[config->iface_config.num_iface_entries - 1].if_cat = UNKNOWN_IF; + IPACMDBG_H("Category %d\n", config->iface_config.iface_entries[config->iface_config.num_iface_entries - 1].if_cat); + } + else if (0 == strncasecmp(content_buf, ETHIF_TAG, str_size)) + { + config->iface_config.iface_entries[config->iface_config.num_iface_entries - 1].if_cat = ETH_IF; + IPACMDBG_H("Category %d\n", config->iface_config.iface_entries[config->iface_config.num_iface_entries - 1].if_cat); + } + else if (0 == strncasecmp(content_buf, ODUIF_TAG, str_size)) + { + config->iface_config.iface_entries[config->iface_config.num_iface_entries - 1].if_cat = ODU_IF; + IPACMDBG("Category %d\n", config->iface_config.iface_entries[config->iface_config.num_iface_entries - 1].if_cat); + } + } + } + else if (IPACM_util_icmp_string((char*)xml_node->name, MODE_TAG) == 0) + { + content = IPACM_read_content_element(xml_node); + if (content) + { + str_size = strlen(content); + memset(content_buf, 0, sizeof(content_buf)); + memcpy(content_buf, (void *)content, str_size); + if (0 == strncasecmp(content_buf, IFACE_ROUTER_MODE_TAG, str_size)) + { + config->iface_config.iface_entries[config->iface_config.num_iface_entries - 1].if_mode = ROUTER; + IPACMDBG_H("Iface mode %d\n", config->iface_config.iface_entries[config->iface_config.num_iface_entries - 1].if_mode); + } + else if (0 == strncasecmp(content_buf, IFACE_BRIDGE_MODE_TAG, str_size)) + { + config->iface_config.iface_entries[config->iface_config.num_iface_entries - 1].if_mode = BRIDGE; + IPACMDBG_H("Iface mode %d\n", config->iface_config.iface_entries[config->iface_config.num_iface_entries - 1].if_mode); + } + } + } + else if (IPACM_util_icmp_string((char*)xml_node->name, WLAN_MODE_TAG) == 0) + { + IPACMDBG_H("Inside WLAN-XML\n"); + content = IPACM_read_content_element(xml_node); + if (content) + { + str_size = strlen(content); + memset(content_buf, 0, sizeof(content_buf)); + memcpy(content_buf, (void *)content, str_size); + + if (0 == strncasecmp(content_buf, WLAN_FULL_MODE_TAG, str_size)) + { + config->iface_config.iface_entries[config->iface_config.num_iface_entries - 1].wlan_mode = FULL; + IPACMDBG_H("Wlan-mode full(%d)\n", + config->iface_config.iface_entries[config->iface_config.num_iface_entries - 1].wlan_mode); + } + else if (0 == strncasecmp(content_buf, WLAN_INTERNET_MODE_TAG, str_size)) + { + config->iface_config.iface_entries[config->iface_config.num_iface_entries - 1].wlan_mode = INTERNET; + config->num_wlan_guest_ap++; + IPACMDBG_H("Wlan-mode internet(%d)\n", + config->iface_config.iface_entries[config->iface_config.num_iface_entries - 1].wlan_mode); + } + } + } + else if (IPACM_util_icmp_string((char*)xml_node->name, SUBNETADDRESS_TAG) == 0) + { + content = IPACM_read_content_element(xml_node); + if (content) + { + str_size = strlen(content); + memset(content_buf, 0, sizeof(content_buf)); + memcpy(content_buf, (void *)content, str_size); + content_buf[MAX_XML_STR_LEN-1] = '\0'; + config->private_subnet_config.private_subnet_entries[config->private_subnet_config.num_subnet_entries - 1].subnet_addr + = ntohl(inet_addr(content_buf)); + IPACMDBG_H("subnet_addr: %s \n", content_buf); + } + } + else if (IPACM_util_icmp_string((char*)xml_node->name, SUBNETMASK_TAG) == 0) + { + content = IPACM_read_content_element(xml_node); + if (content) + { + str_size = strlen(content); + memset(content_buf, 0, sizeof(content_buf)); + memcpy(content_buf, (void *)content, str_size); + content_buf[MAX_XML_STR_LEN-1] = '\0'; + config->private_subnet_config.private_subnet_entries[config->private_subnet_config.num_subnet_entries - 1].subnet_mask + = ntohl(inet_addr(content_buf)); + IPACMDBG_H("subnet_mask: %s \n", content_buf); + } + } + else if (IPACM_util_icmp_string((char*)xml_node->name, Protocol_TAG) == 0) + { + content = IPACM_read_content_element(xml_node); + if (content) + { + str_size = strlen(content); + memset(content_buf, 0, sizeof(content_buf)); + memcpy(content_buf, (void *)content, str_size); + content_buf[MAX_XML_STR_LEN-1] = '\0'; + + if (0 == strncasecmp(content_buf, TCP_PROTOCOL_TAG, str_size)) + { + config->alg_config.alg_entries[config->alg_config.num_alg_entries - 1].protocol = IPPROTO_TCP; + IPACMDBG_H("Protocol %s: %d\n", + content_buf, config->alg_config.alg_entries[config->alg_config.num_alg_entries - 1].protocol); + } + else if (0 == strncasecmp(content_buf, UDP_PROTOCOL_TAG, str_size)) + { + config->alg_config.alg_entries[config->alg_config.num_alg_entries - 1].protocol = IPPROTO_UDP; + IPACMDBG_H("Protocol %s: %d\n", + content_buf, config->alg_config.alg_entries[config->alg_config.num_alg_entries - 1].protocol); + } + } + } + else if (IPACM_util_icmp_string((char*)xml_node->name, Port_TAG) == 0) + { + content = IPACM_read_content_element(xml_node); + if (content) + { + str_size = strlen(content); + memset(content_buf, 0, sizeof(content_buf)); + memcpy(content_buf, (void *)content, str_size); + config->alg_config.alg_entries[config->alg_config.num_alg_entries - 1].port + = atoi(content_buf); + IPACMDBG_H("port %d\n", config->alg_config.alg_entries[config->alg_config.num_alg_entries - 1].port); + } + } + else if (IPACM_util_icmp_string((char*)xml_node->name, NAT_MaxEntries_TAG) == 0) + { + content = IPACM_read_content_element(xml_node); + if (content) + { + str_size = strlen(content); + memset(content_buf, 0, sizeof(content_buf)); + memcpy(content_buf, (void *)content, str_size); + config->nat_max_entries = atoi(content_buf); + IPACMDBG_H("Nat Table Max Entries %d\n", config->nat_max_entries); + } + } + } + break; + default: + break; + } + /* go to sibling */ + xml_node = xml_node->next; + } /* end while */ + return ret_val; +} + +/* This function read QCMAP CM Firewall XML and populate the QCMAP CM Cfg */ +int IPACM_read_firewall_xml(char *xml_file, IPACM_firewall_conf_t *config) +{ + xmlDocPtr doc = NULL; + xmlNode* root = NULL; + int ret_val; + + IPACM_ASSERT(xml_file != NULL); + IPACM_ASSERT(config != NULL); + + /* invoke the XML parser and obtain the parse tree */ + doc = xmlReadFile(xml_file, "UTF-8", XML_PARSE_NOBLANKS); + if (doc == NULL) { + IPACMDBG_H("IPACM_xml_parse: libxml returned parse error\n"); + return IPACM_FAILURE; + } + /*get the root of the tree*/ + root = xmlDocGetRootElement(doc); + + /* parse the xml tree returned by libxml*/ + ret_val = IPACM_firewall_xml_parse_tree(root, config); + + if (ret_val != IPACM_SUCCESS) + { + IPACMDBG_H("IPACM_xml_parse: ipacm_firewall_xml_parse_tree returned parse error!\n"); + } + + /* free the tree */ + xmlFreeDoc(doc); + + return ret_val; +} + + +/* This function traverses the firewall xml tree */ +static int IPACM_firewall_xml_parse_tree +( + xmlNode* xml_node, + IPACM_firewall_conf_t *config +) +{ + int mask_value_v6, mask_index; + int32_t ret_val = IPACM_SUCCESS; + char *content; + int str_size; + char content_buf[MAX_XML_STR_LEN]; + struct in6_addr ip6_addr; + + IPACM_ASSERT(config != NULL); + + if (NULL == xml_node) + return ret_val; + + while ( xml_node != NULL && + ret_val == IPACM_SUCCESS) + { + switch (xml_node->type) + { + + case XML_ELEMENT_NODE: + { + if (0 == IPACM_util_icmp_string((char*)xml_node->name, system_TAG) || + 0 == IPACM_util_icmp_string((char*)xml_node->name, MobileAPFirewallCfg_TAG) || + 0 == IPACM_util_icmp_string((char*)xml_node->name, Firewall_TAG) || + 0 == IPACM_util_icmp_string((char*)xml_node->name, FirewallEnabled_TAG) || + 0 == IPACM_util_icmp_string((char*)xml_node->name, FirewallPktsAllowed_TAG)) + { + if (0 == IPACM_util_icmp_string((char*)xml_node->name, Firewall_TAG)) + { + /* increase firewall entry num */ + config->num_extd_firewall_entries++; + } + + if (0 == IPACM_util_icmp_string((char*)xml_node->name, FirewallPktsAllowed_TAG)) + { + /* setup action of matched rules */ + content = IPACM_read_content_element(xml_node); + if (content) + { + str_size = strlen(content); + memset(content_buf, 0, sizeof(content_buf)); + memcpy(content_buf, (void *)content, str_size); + if (atoi(content_buf)==1) + { + config->rule_action_accept = true; + } + else + { + config->rule_action_accept = false; + } + IPACMDBG_H(" Allow traffic which matches rules ?:%d\n",config->rule_action_accept); + } + } + + if (0 == IPACM_util_icmp_string((char*)xml_node->name, FirewallEnabled_TAG)) + { + /* setup if firewall enable or not */ + content = IPACM_read_content_element(xml_node); + if (content) + { + str_size = strlen(content); + memset(content_buf, 0, sizeof(content_buf)); + memcpy(content_buf, (void *)content, str_size); + if (atoi(content_buf)==1) + { + config->firewall_enable = true; + } + else + { + config->firewall_enable = false; + } + IPACMDBG_H(" Firewall Enable?:%d\n", config->firewall_enable); + } + } + /* go to child */ + ret_val = IPACM_firewall_xml_parse_tree(xml_node->children, config); + } + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, IPFamily_TAG)) + { + content = IPACM_read_content_element(xml_node); + if (content) + { + str_size = strlen(content); + memset(content_buf, 0, sizeof(content_buf)); + memcpy(content_buf, (void *)content, str_size); + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].ip_vsn + = (firewall_ip_version_enum)atoi(content_buf); + IPACMDBG_H("\n IP family type is %d \n", + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].ip_vsn); + } + } + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, IPV4SourceAddress_TAG)) + { + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.attrib_mask |= IPA_FLT_SRC_ADDR; + /* go to child */ + ret_val = IPACM_firewall_xml_parse_tree(xml_node->children, config); + } + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, IPV4SourceIPAddress_TAG)) + { + content = IPACM_read_content_element(xml_node); + if (content) + { + str_size = strlen(content); + memset(content_buf, 0, sizeof(content_buf)); + memcpy(content_buf, (void *)content, str_size); + content_buf[MAX_XML_STR_LEN-1] = '\0'; + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v4.src_addr + = ntohl(inet_addr(content_buf)); + IPACMDBG_H("IPv4 source address is: %s \n", content_buf); + } + } + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, IPV4SourceSubnetMask_TAG)) + { + content = IPACM_read_content_element(xml_node); + if (content) + { + str_size = strlen(content); + memset(content_buf, 0, sizeof(content_buf)); + memcpy(content_buf, (void *)content, str_size); + content_buf[MAX_XML_STR_LEN-1] = '\0'; + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v4.src_addr_mask + = ntohl(inet_addr(content_buf)); + IPACMDBG_H("IPv4 source subnet mask is: %s \n", content_buf); + } + } + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, IPV4DestinationAddress_TAG)) + { + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.attrib_mask |= IPA_FLT_DST_ADDR; + /* go to child */ + ret_val = IPACM_firewall_xml_parse_tree(xml_node->children, config); + } + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, IPV4DestinationIPAddress_TAG)) + { + content = IPACM_read_content_element(xml_node); + if (content) + { + str_size = strlen(content); + memset(content_buf, 0, sizeof(content_buf)); + memcpy(content_buf, (void *)content, str_size); + content_buf[MAX_XML_STR_LEN-1] = '\0'; + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v4.dst_addr + = ntohl(inet_addr(content_buf)); + IPACMDBG_H("IPv4 destination address is: %s \n", content_buf); + } + } + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, IPV4DestinationSubnetMask_TAG)) + { + content = IPACM_read_content_element(xml_node); + if (content) + { + str_size = strlen(content); + memset(content_buf, 0, sizeof(content_buf)); + memcpy(content_buf, (void *)content, str_size); + content_buf[MAX_XML_STR_LEN-1] = '\0'; + if (content_buf > 0) + { + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v4.dst_addr_mask + = ntohl(inet_addr(content_buf)); + IPACMDBG_H("IPv4 destination subnet mask is: %s \n", content_buf); + } + } + } + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, IPV4TypeOfService_TAG)) + { + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.attrib_mask |= IPA_FLT_TOS; + /* go to child */ + ret_val = IPACM_firewall_xml_parse_tree(xml_node->children, config); + } + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, TOSValue_TAG)) + { + content = IPACM_read_content_element(xml_node); + if (content) + { + str_size = strlen(content); + memset(content_buf, 0, sizeof(content_buf)); + memcpy(content_buf, (void *)content, str_size); + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v4.tos + = atoi(content_buf); + IPACMDBG_H("\n IPV4 TOS val is %d \n", + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v4.tos); + } + } + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, TOSMask_TAG)) + { + content = IPACM_read_content_element(xml_node); + if (content) + { + str_size = strlen(content); + memset(content_buf, 0, sizeof(content_buf)); + memcpy(content_buf, (void *)content, str_size); + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v4.tos + &= atoi(content_buf); + IPACMDBG_H("\n IPv4 TOS mask is %d \n", + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v4.tos); + } + } + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, IPV4NextHeaderProtocol_TAG)) + { + content = IPACM_read_content_element(xml_node); + if (content) + { + str_size = strlen(content); + memset(content_buf, 0, sizeof(content_buf)); + memcpy(content_buf, (void *)content, str_size); + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.attrib_mask |= IPA_FLT_PROTOCOL; + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v4.protocol = atoi(content_buf); + IPACMDBG_H("\n IPv4 next header prot is %d \n", + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v4.protocol); + } + } + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, IPV6SourceAddress_TAG)) + { + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.attrib_mask |= + IPA_FLT_SRC_ADDR; + /* go to child */ + ret_val = IPACM_firewall_xml_parse_tree(xml_node->children, config); + } + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, IPV6SourceIPAddress_TAG)) + { + content = IPACM_read_content_element(xml_node); + if (content) + { + str_size = strlen(content); + memset(content_buf, 0, sizeof(content_buf)); + memcpy(content_buf, (void *)content, str_size); + inet_pton(AF_INET6, content_buf, &ip6_addr); + memcpy(config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v6.src_addr, + ip6_addr.s6_addr, IPACM_IPV6_ADDR_LEN * sizeof(uint8_t)); + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v6.src_addr[0]=ntohl(config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v6.src_addr[0]); + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v6.src_addr[1]=ntohl(config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v6.src_addr[1]); + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v6.src_addr[2]=ntohl(config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v6.src_addr[2]); + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v6.src_addr[3]=ntohl(config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v6.src_addr[3]); + + IPACMDBG_H("\n ipv6 source addr is %d \n ", + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v6.src_addr[0]); + } + } + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, IPV6SourcePrefix_TAG)) + { + content = IPACM_read_content_element(xml_node); + if (content) + { + str_size = strlen(content); + memset(content_buf, 0, sizeof(content_buf)); + memcpy(content_buf, (void *)content, str_size); + mask_value_v6 = atoi(content_buf); + for (mask_index = 0; mask_index < 4; mask_index++) + { + if (mask_value_v6 >= 32) + { + mask_v6(32, &(config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v6.src_addr_mask[mask_index])); + mask_value_v6 -= 32; + } + else + { + mask_v6(mask_value_v6, &(config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v6.src_addr_mask[mask_index])); + mask_value_v6 = 0; + } + } + IPACMDBG_H("\n ipv6 source prefix is %d \n", atoi(content_buf)); + } + } + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, IPV6DestinationAddress_TAG)) + { + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.attrib_mask |= + IPA_FLT_DST_ADDR; + /* go to child */ + ret_val = IPACM_firewall_xml_parse_tree(xml_node->children, config); + } + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, IPV6DestinationIPAddress_TAG)) + { + content = IPACM_read_content_element(xml_node); + if (content) + { + str_size = strlen(content); + memset(content_buf, 0, sizeof(content_buf)); + memcpy(content_buf, (void *)content, str_size); + inet_pton(AF_INET6, content_buf, &ip6_addr); + memcpy(config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v6.dst_addr, + ip6_addr.s6_addr, IPACM_IPV6_ADDR_LEN * sizeof(uint8_t)); + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v6.dst_addr[0]=ntohl(config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v6.dst_addr[0]); + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v6.dst_addr[1]=ntohl(config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v6.dst_addr[1]); + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v6.dst_addr[2]=ntohl(config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v6.dst_addr[2]); + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v6.dst_addr[3]=ntohl(config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v6.dst_addr[3]); + IPACMDBG_H("\n ipv6 dest addr is %d \n", + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v6.dst_addr[0]); + } + } + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, IPV6DestinationPrefix_TAG)) + { + content = IPACM_read_content_element(xml_node); + if (content) + { + str_size = strlen(content); + memset(content_buf, 0, sizeof(content_buf)); + memcpy(content_buf, (void *)content, str_size); + mask_value_v6 = atoi(content_buf); + for (mask_index = 0; mask_index < 4; mask_index++) + { + if (mask_value_v6 >= 32) + { + mask_v6(32, &(config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v6.dst_addr_mask[mask_index])); + mask_value_v6 -= 32; + } + else + { + mask_v6(mask_value_v6, &(config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v6.dst_addr_mask[mask_index])); + mask_value_v6 = 0; + } + } + IPACMDBG_H("\n ipv6 dest prefix is %d \n", atoi(content_buf)); + } + } + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, IPV6TrafficClass_TAG)) + { + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.attrib_mask |= IPA_FLT_TC; + /* go to child */ + ret_val = IPACM_firewall_xml_parse_tree(xml_node->children, config); + } + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, TrfClsValue_TAG)) + { + content = IPACM_read_content_element(xml_node); + if (content) + { + str_size = strlen(content); + memset(content_buf, 0, sizeof(content_buf)); + memcpy(content_buf, (void *)content, str_size); + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v6.tc + = atoi(content_buf); + IPACMDBG_H("\n ipv6 trf class val is %d \n", + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v6.tc); + } + } + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, TrfClsMask_TAG)) + { + content = IPACM_read_content_element(xml_node); + if (content) + { + str_size = strlen(content); + memset(content_buf, 0, sizeof(content_buf)); + memcpy(content_buf, (void *)content, str_size); + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v6.tc + &= atoi(content_buf); + IPACMDBG_H("\n ipv6 trf class mask is %d \n", atoi(content_buf)); + } + } + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, IPV6NextHeaderProtocol_TAG)) + { + content = IPACM_read_content_element(xml_node); + if (content) + { + str_size = strlen(content); + memset(content_buf, 0, sizeof(content_buf)); + memcpy(content_buf, (void *)content, str_size); + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.attrib_mask |= IPA_FLT_NEXT_HDR; + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v6.next_hdr + = atoi(content_buf); + IPACMDBG_H("\n ipv6 next header protocol is %d \n", + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v6.next_hdr); + } + } + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, TCPSource_TAG)) + { + /* go to child */ + ret_val = IPACM_firewall_xml_parse_tree(xml_node->children, config); + } + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, TCPSourcePort_TAG)) + { + content = IPACM_read_content_element(xml_node); + if (content) + { + str_size = strlen(content); + memset(content_buf, 0, sizeof(content_buf)); + memcpy(content_buf, (void *)content, str_size); + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.src_port + = atoi(content_buf); + } + } + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, TCPSourceRange_TAG)) + { + content = IPACM_read_content_element(xml_node); + if (content) + { + str_size = strlen(content); + memset(content_buf, 0, sizeof(content_buf)); + memcpy(content_buf, (void *)content, str_size); + if (atoi(content_buf) != 0) + { + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.attrib_mask |= IPA_FLT_SRC_PORT_RANGE; + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.src_port_lo + = config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.src_port; + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.src_port_hi + = config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.src_port + atoi(content_buf); + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.src_port = 0; + IPACMDBG_H("\n tcp source port from %d to %d \n", + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.src_port_lo, + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.src_port_hi); + } + else + { + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.attrib_mask |= IPA_FLT_SRC_PORT; + IPACMDBG_H("\n tcp source port= %d \n", + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.src_port); + } + } + } + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, TCPDestination_TAG)) + { + /* go to child */ + ret_val = IPACM_firewall_xml_parse_tree(xml_node->children, config); + } + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, TCPDestinationPort_TAG)) + { + content = IPACM_read_content_element(xml_node); + if (content) + { + str_size = strlen(content); + memset(content_buf, 0, sizeof(content_buf)); + memcpy(content_buf, (void *)content, str_size); + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.dst_port + = atoi(content_buf); + } + } + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, TCPDestinationRange_TAG)) + { + content = IPACM_read_content_element(xml_node); + if (content) + { + str_size = strlen(content); + memset(content_buf, 0, sizeof(content_buf)); + memcpy(content_buf, (void *)content, str_size); + if(atoi(content_buf)!=0) + { + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.attrib_mask |= IPA_FLT_DST_PORT_RANGE; + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.dst_port_lo + = config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.dst_port; + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.dst_port_hi + = config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.dst_port + atoi(content_buf); + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.dst_port = 0; + IPACMDBG_H("\n tcp dest port from %d to %d \n", + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.dst_port_lo, + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.dst_port_hi); + } + else + { + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.attrib_mask |= IPA_FLT_DST_PORT; + IPACMDBG_H("\n tcp dest port= %d \n", + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.dst_port); + } + } + } + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, UDPSource_TAG)) + { + /* go to child */ + ret_val = IPACM_firewall_xml_parse_tree(xml_node->children, config); + } + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, UDPSourcePort_TAG)) + { + content = IPACM_read_content_element(xml_node); + if (content) + { + str_size = strlen(content); + memset(content_buf, 0, sizeof(content_buf)); + memcpy(content_buf, (void *)content, str_size); + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.src_port + = atoi(content_buf); + } + } + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, UDPSourceRange_TAG)) + { + content = IPACM_read_content_element(xml_node); + if (content) + { + str_size = strlen(content); + memset(content_buf, 0, sizeof(content_buf)); + memcpy(content_buf, (void *)content, str_size); + if(atoi(content_buf)!=0) + { + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.attrib_mask |= IPA_FLT_SRC_PORT_RANGE; + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.src_port_lo + = config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.src_port; + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.src_port_hi + = config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.src_port + atoi(content_buf); + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.src_port = 0; + IPACMDBG_H("\n udp source port from %d to %d \n", + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.src_port_lo, + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.src_port_hi); + } + else + { + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.attrib_mask |= IPA_FLT_SRC_PORT; + IPACMDBG_H("\n udp source port= %d \n", + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.src_port); + } + } + } + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, UDPDestination_TAG)) + { + /* go to child */ + ret_val = IPACM_firewall_xml_parse_tree(xml_node->children, config); + } + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, UDPDestinationPort_TAG)) + { + content = IPACM_read_content_element(xml_node); + if (content) + { + str_size = strlen(content); + memset(content_buf, 0, sizeof(content_buf)); + memcpy(content_buf, (void *)content, str_size); + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.dst_port + = atoi(content_buf); + } + } + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, UDPDestinationRange_TAG)) + { + content = IPACM_read_content_element(xml_node); + if (content) + { + str_size = strlen(content); + memset(content_buf, 0, sizeof(content_buf)); + memcpy(content_buf, (void *)content, str_size); + if(atoi(content_buf)!=0) + { + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.attrib_mask |= IPA_FLT_DST_PORT_RANGE; + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.dst_port_lo + = config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.dst_port; + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.dst_port_hi + = config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.dst_port + atoi(content_buf); + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.dst_port = 0; + IPACMDBG_H("\n UDP dest port from %d to %d \n", + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.dst_port_lo, + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.dst_port_hi); + } + else + { + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.attrib_mask |= IPA_FLT_DST_PORT; + IPACMDBG_H("\n UDP dest port= %d \n", + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.dst_port); + } + } + } + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, ICMPType_TAG)) + { + content = IPACM_read_content_element(xml_node); + if (content) + { + str_size = strlen(content); + memset(content_buf, 0, sizeof(content_buf)); + memcpy(content_buf, (void *)content, str_size); + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.type = atoi(content_buf); + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.attrib_mask |= IPA_FLT_TYPE; + IPACMDBG_H("\n icmp type is %d \n", + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.type); + } + } + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, ICMPCode_TAG)) + { + content = IPACM_read_content_element(xml_node); + if (content) + { + str_size = strlen(content); + memset(content_buf, 0, sizeof(content_buf)); + memcpy(content_buf, (void *)content, str_size); + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.code = atoi(content_buf); + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.attrib_mask |= IPA_FLT_CODE; + IPACMDBG_H("\n icmp code is %d \n", + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.code); + } + } + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, ESPSPI_TAG)) + { + content = IPACM_read_content_element(xml_node); + if (content) + { + str_size = strlen(content); + memset(content_buf, 0, sizeof(content_buf)); + memcpy(content_buf, (void *)content, str_size); + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.spi = atoi(content_buf); + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.attrib_mask |= IPA_FLT_SPI; + IPACMDBG_H("\n esp spi is %d \n", + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.spi); + } + } + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, TCP_UDPSource_TAG)) + { + /* go to child */ + ret_val = IPACM_firewall_xml_parse_tree(xml_node->children, config); + } + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, TCP_UDPSourcePort_TAG)) + { + content = IPACM_read_content_element(xml_node); + if (content) + { + str_size = strlen(content); + memset(content_buf, 0, sizeof(content_buf)); + memcpy(content_buf, (void *)content,str_size); + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.src_port + = atoi(content_buf); + } + } + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, TCP_UDPSourceRange_TAG)) + { + content = IPACM_read_content_element(xml_node); + if (content) + { + str_size = strlen(content); + memset(content_buf, 0, sizeof(content_buf)); + memcpy(content_buf, (void *)content, str_size); + if(atoi(content_buf)!=0) + { + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.attrib_mask |= IPA_FLT_SRC_PORT_RANGE; + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.src_port_lo + = config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.src_port; + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.src_port_hi + = config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.src_port + atoi(content_buf); + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.src_port = 0; + IPACMDBG_H("\n tcp_udp source port from %d to %d \n", + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.src_port_lo, + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.src_port_hi); + } + else + { + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.attrib_mask |= IPA_FLT_SRC_PORT; + IPACMDBG_H("\n tcp_udp source port= %d \n", + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.src_port); + + } + } + } + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, TCP_UDPDestination_TAG)) + { + ret_val = IPACM_firewall_xml_parse_tree(xml_node->children, config); + } + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, TCP_UDPDestinationPort_TAG)) + { + content = IPACM_read_content_element(xml_node); + if (content) + { + str_size = strlen(content); + memset(content_buf, 0, sizeof(content_buf)); + memcpy(content_buf, (void *)content, str_size); + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.dst_port + = atoi(content_buf); + } + } + else if (0 == IPACM_util_icmp_string((char*)xml_node->name, TCP_UDPDestinationRange_TAG)) + { + content = IPACM_read_content_element(xml_node); + if (content) + { + str_size = strlen(content); + memset(content_buf, 0, sizeof(content_buf)); + memcpy(content_buf, (void *)content, str_size); + if(atoi(content_buf)!=0) + { + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.attrib_mask |= IPA_FLT_DST_PORT_RANGE; + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.dst_port_lo + = config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.dst_port; + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.dst_port_hi + = config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.dst_port + atoi(content_buf); + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.dst_port = 0; + IPACMDBG_H("\n tcp_udp dest port from %d to %d \n", + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.dst_port_lo, + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.dst_port_hi); + } + else + { + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.attrib_mask |= IPA_FLT_DST_PORT; + IPACMDBG_H("\n tcp_udp dest port= %d \n", + config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.dst_port); + } + } + } + } + break; + + default: + break; + } + /* go to sibling */ + xml_node = xml_node->next; + } /* end while */ + return ret_val; +} diff --git a/data-ipa-cfg-mgr/ipacm/src/IPACM_cfg.xml b/data-ipa-cfg-mgr/ipacm/src/IPACM_cfg.xml new file mode 100644 index 000000000..d16d2ed6f --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/src/IPACM_cfg.xml @@ -0,0 +1,157 @@ + + + + router + 0 + + + + + rndis0 + LAN + + + ecm0 + LAN + ROUTER + + + rmnet_data0 + WAN + ROUTER + + + rmnet_data1 + WAN + + + rmnet_data2 + WAN + + + rmnet_data3 + WAN + + + rmnet_data4 + WAN + + + rmnet_data5 + WAN + + + rmnet_data6 + WAN + + + rmnet_data7 + WAN + + + wlan0 + UNKNOWN + full + + + wlan1 + UNKNOWN + full + + + eth0 + ODU + + + bridge0 + VIRTUAL + + + + + 192.168.225.0 + 255.255.255.0 + + + + + TCP + 21 + FTP + + + TCP + 554 + RTSP + + + TCP + 5060 + SIP + + + UDP + 5060 + SIP + + + TCP + 1723 + PPTP + + + UDP + 69 + TFTP + + + UDP + 53 + DNS + + + TCP + 53 + DNS + + + UDP + 10080 + AMANDA + + + UDP + 1719 + H323 + + + TCP + 1720 + H323 + + + TCP + 6667 + IRC + + + UDP + 137 + NETBIOS_NS + + + UDP + 138 + NETBIOS_NS + + + TCP + 6566 + SANE + + + + 500 + + + diff --git a/data-ipa-cfg-mgr/ipacm/src/Makefile.am b/data-ipa-cfg-mgr/ipacm/src/Makefile.am new file mode 100644 index 000000000..2fdb3f882 --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/src/Makefile.am @@ -0,0 +1,46 @@ +AM_CPPFLAGS = -I./../inc \ + -I$(top_srcdir)/ipanat/inc \ + ${LIBXML_CFLAGS} +AM_CPPFLAGS += -Wall -Wundef -Wno-trigraphs +AM_CPPFLAGS += -DDEBUG -g -DFEATURE_ETH_BRIDGE_LE +AM_CPPFLAGS += -DFEATURE_IPA_V3 + +ipacm_SOURCES = IPACM_Main.cpp \ + IPACM_Conntrack_NATApp.cpp\ + IPACM_ConntrackClient.cpp \ + IPACM_ConntrackListener.cpp \ + IPACM_EvtDispatcher.cpp \ + IPACM_Config.cpp \ + IPACM_CmdQueue.cpp \ + IPACM_Log.cpp \ + IPACM_Filtering.cpp \ + IPACM_Routing.cpp \ + IPACM_Header.cpp \ + IPACM_Lan.cpp \ + IPACM_Iface.cpp \ + IPACM_Wlan.cpp \ + IPACM_Wan.cpp \ + IPACM_IfaceManager.cpp \ + IPACM_Neighbor.cpp \ + IPACM_Netlink.cpp \ + IPACM_Xml.cpp \ + IPACM_LanToLan.cpp + +bin_PROGRAMS = ipacm + +requiredlibs = ${LIBXML_LIB} -lxml2 -lpthread -lnetfilter_conntrack -lnfnetlink\ + ../../ipanat/src/libipanat.la + +ipacm_LDADD = $(requiredlibs) + +AM_CPPFLAGS += "-std=c++0x" + +LOCAL_MODULE := libipanat +LOCAL_PRELINK_MODULE := false +include $(BUILD_SHARED_LIBRARY) + +etcdir = ${sysconfdir} +etc_SCRIPTS = IPACM_cfg.xml + +init_ddir = ${sysconfdir}/init.d +init_d_SCRIPTS = start_ipacm_le diff --git a/data-ipa-cfg-mgr/ipacm/src/mobileap_firewall.xml b/data-ipa-cfg-mgr/ipacm/src/mobileap_firewall.xml new file mode 100644 index 000000000..84da52790 --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/src/mobileap_firewall.xml @@ -0,0 +1,7 @@ + + + + 1 + 0 + + diff --git a/data-ipa-cfg-mgr/ipacm/src/start_ipacm_le b/data-ipa-cfg-mgr/ipacm/src/start_ipacm_le new file mode 100644 index 000000000..3541a0b33 --- /dev/null +++ b/data-ipa-cfg-mgr/ipacm/src/start_ipacm_le @@ -0,0 +1,57 @@ +#! /bin/sh +# +################################ +# Copyright (c) 2013, The Linux Foundation. All rights reserved. + +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials provided +# with the distribution. +# * Neither the name of The Linux Foundation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. + +# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +################################ + +# ipacm init.d script to start the data-ipa Software's ipacm daemon + +set -e + +case "$1" in + start) + echo -n "Starting ipacm: " + start-stop-daemon -S -b -a ipacm + echo "done" + ;; + stop) + echo -n "Stopping ipacm: " + start-stop-daemon -K -n ipacm + echo "done" + ;; + restart) + $0 stop + $0 start + ;; + *) + echo "Usage ipacm { start | stop | restart}" >&2 + exit 1 + ;; +esac + +exit 0 diff --git a/data-ipa-cfg-mgr/ipanat/Android.mk b/data-ipa-cfg-mgr/ipanat/Android.mk new file mode 100644 index 000000000..5053e7d64 --- /dev/null +++ b/data-ipa-cfg-mgr/ipanat/Android.mk @@ -0,0 +1 @@ +include $(call all-subdir-makefiles) diff --git a/data-ipa-cfg-mgr/ipanat/inc/ipa_nat_drv.h b/data-ipa-cfg-mgr/ipanat/inc/ipa_nat_drv.h new file mode 100644 index 000000000..04e3af97a --- /dev/null +++ b/data-ipa-cfg-mgr/ipanat/inc/ipa_nat_drv.h @@ -0,0 +1,116 @@ +/* +Copyright (c) 2013, The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "string.h" /* memset */ +#include "stdlib.h" /* free, malloc */ +#include "stdint.h" /* uint32_t */ + +/** + * struct ipa_nat_ipv4_rule - To hold ipv4 nat rule + * @target_ip: destination ip address + * @private_ip: private ip address + * @target_port: destination port + * @private_port: private port + * @protocol: protocol of rule (tcp/udp) + */ +typedef struct { + uint32_t target_ip; + uint32_t private_ip; + uint16_t target_port; + uint16_t private_port; + uint16_t public_port; + uint8_t protocol; +} ipa_nat_ipv4_rule; + +/** + * ipa_nat_add_ipv4_tbl() - create ipv4 nat table + * @public_ip_addr: [in] public ipv4 address + * @number_of_entries: [in] number of nat entries + * @table_handle: [out] Handle of new ipv4 nat table + * + * To create new ipv4 nat table + * + * Returns: 0 On Success, negative on failure + */ +int ipa_nat_add_ipv4_tbl(uint32_t public_ip_addr, + uint16_t number_of_entries, + uint32_t *table_handle); + +/** + * ipa_nat_del_ipv4_tbl() - delete ipv4 table + * @table_handle: [in] Handle of ipv4 nat table + * + * To delete given ipv4 nat table + * + * Returns: 0 On Success, negative on failure + */ +int ipa_nat_del_ipv4_tbl(uint32_t table_handle); + +/** + * ipa_nat_add_ipv4_rule() - to insert new ipv4 rule + * @table_handle: [in] handle of ipv4 nat table + * @rule: [in] Pointer to new rule + * @rule_handle: [out] Return the handle to rule + * + * To insert new ipv4 nat rule into ipv4 nat table + * + * Returns: 0 On Success, negative on failure + */ +int ipa_nat_add_ipv4_rule(uint32_t table_handle, + const ipa_nat_ipv4_rule * rule, + uint32_t *rule_handle); + +/** + * ipa_nat_del_ipv4_rule() - to delete ipv4 nat rule + * @table_handle: [in] handle of ipv4 nat table + * @rule_handle: [in] ipv4 nat rule handle + * + * To insert new ipv4 nat rule into ipv4 nat table + * + * Returns: 0 On Success, negative on failure + */ +int ipa_nat_del_ipv4_rule(uint32_t table_handle, + uint32_t rule_handle); + + +/** + * ipa_nat_query_timestamp() - to query timestamp + * @table_handle: [in] handle of ipv4 nat table + * @rule_handle: [in] ipv4 nat rule handle + * @time_stamp: [out] time stamp of rule + * + * To retrieve the timestamp that lastly the + * nat rule was accessed + * + * Returns: 0 On Success, negative on failure + */ +int ipa_nat_query_timestamp(uint32_t table_handle, + uint32_t rule_handle, + uint32_t *time_stamp); + diff --git a/data-ipa-cfg-mgr/ipanat/inc/ipa_nat_drvi.h b/data-ipa-cfg-mgr/ipanat/inc/ipa_nat_drvi.h new file mode 100644 index 000000000..002c0251e --- /dev/null +++ b/data-ipa-cfg-mgr/ipanat/inc/ipa_nat_drvi.h @@ -0,0 +1,481 @@ +/* +Copyright (c) 2013, The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef IPA_NAT_DRVI_H +#define IPA_NAT_DRVI_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ipa_nat_logi.h" + +#define NAT_DUMP + +/*======= IMPLEMENTATION related data structures and functions ======= */ +#ifdef IPA_ON_R3PC +#define NAT_MMAP_MEM_SIZE (2 * 1024UL * 1024UL - 1) +#endif + +#define IPA_DEV_NAME "/dev/ipa" +#define NAT_DEV_DIR "/dev" +#define NAT_DEV_NAME "ipaNatTable" +#define NAT_DEV_FULL_NAME "/dev/ipaNatTable" + +#define IPA_NAT_TABLE_VALID 1 +#define IPA_NAT_MAX_IP4_TBLS 1 +#define IPA_NAT_BASE_TABLE_PERCENTAGE .8 +#define IPA_NAT_EXPANSION_TABLE_PERCENTAGE .2 + +#define IPA_NAT_NUM_OF_BASE_TABLES 2 +#define IPA_NAT_UNUSED_BASE_ENTRIES 2 + +#define IPA_NAT_RULE_FLAG_FIELD_OFFSET 18 +#define IPA_NAT_RULE_NEXT_FIELD_OFFSET 8 +#define IPA_NAT_RULE_PROTO_FIELD_OFFSET 22 + +#define IPA_NAT_INDEX_RULE_NEXT_FIELD_OFFSET 2 +#define IPA_NAT_INDEX_RULE_NAT_INDEX_FIELD_OFFSET 0 + +#define IPA_NAT_RULE_FLAG_FIELD_SIZE 2 +#define IPA_NAT_RULE_NEXTFIELD_FIELD_SIZE 2 + +#define IPA_NAT_FLAG_ENABLE_BIT_MASK 0x8000 +#define IPA_NAT_FLAG_DISABLE_BIT_MASK 0x0000 + +#define IPA_NAT_FLAG_ENABLE_BIT 1 +#define IPA_NAT_FLAG_DISABLE_BIT 0 + +#define IPA_NAT_INVALID_PROTO_FIELD_VALUE 0xFF00 +#define IPA_NAT_INVALID_PROTO_FIELD_CMP 0xFF + +#define IPA_NAT_INVALID_INDEX 0xFF +#define IPA_NAT_INVALID_NAT_ENTRY 0x0 + +#define INDX_TBL_ENTRY_SIZE_IN_BITS 16 + +/* ----------- Rule id ----------------------- + + ------------------------------------------------ + | 3bits | 12 bits | 1 bit | + ------------------------------------------------ + | reserved | index into table | 0 - base | + | | | 1 - expansion | + ------------------------------------------------ + +*/ +#define IPA_NAT_RULE_HDL_TBL_TYPE_BITS 0x1 +#define IPA_NAT_RULE_HDL_TBL_TYPE_MASK 0x1 + +/* ----------- sw specif parameter ----- + ------------------------------------ + | 16 bits | 16 bits | + ------------------------------------ + | index table | prev index | + | entry | | + ------------------------------------ +-----------------------------------------*/ +#define IPA_NAT_SW_PARAM_PREV_INDX_BYTE 0 +#define IPA_NAT_SW_PARAM_INDX_TBL_ENTRY_BYTE 1 + +typedef enum { + IPA_NAT_BASE_TBL = 0, + IPA_NAT_EXPN_TBL = 1, + IPA_NAT_INDX_TBL = 2, + IPA_NAT_INDEX_EXPN_TBL = 3, +} nat_table_type; + +typedef enum { + NEXT_INDEX_FIELD, + PUBLIC_PORT_FILED, + PRIVATE_PORT_FIELD, + TARGET_PORT_FIELD, + IP_CHKSUM_FIELD, + ENABLE_FIELD, + TIME_STAMP_FIELD, + PROTOCOL_FIELD, + TCP_UDP_CHKSUM_FIELD, + SW_SPEC_PARAM_PREV_INDEX_FIELD, + SW_SPEC_PARAM_INDX_TBL_ENTRY_FIELD, + INDX_TBL_TBL_ENTRY_FIELD, + INDX_TBL_NEXT_INDEX_FILED +} ipa_nat_rule_field_type; + +/* + --------------------------------------------- + | 3 | 2 | 1 | 0 | + --------------------------------------------- + | Public Port(2B) | Next Index(2B) | + --------------------------------------------- +*/ +typedef struct { + uint32_t next_index:16; + uint32_t public_port:16; +} next_index_pub_port; + + +/* + --------------------------------------------- + | 3 | 2 | 1 | 0 | + --------------------------------------------- + | Flags(2B) | IP check sum Diff(2B)| + |EN|FIN|Resv | | | + --------------------------------------------- +*/ +typedef struct { + uint32_t ip_chksum:16; + uint32_t rsvd1:14; + uint32_t redirect:1; + uint32_t enable:1; +} ipcksum_enbl; + + +/* + --------------------------------------- + | 7 | 6 | 5 | 4 | + --------------------------------------- + | Proto | TimeStamp(3B) | + | (1B) | | + --------------------------------------- +*/ +typedef struct { + uint32_t time_stamp:24; + uint32_t protocol:8; +} time_stamp_proto; + + +/* + --------------------------------------------- + | 3 | 2 | 1 | 0 | + --------------------------------------------- + | next_index | Table entry | + ---------------------------------------------- +*/ +typedef struct { + uint16_t tbl_entry; + uint16_t next_index; +} tbl_ent_nxt_indx; + +/*-------------------------------------------------- + 32 bit sw_spec_params is interpreted as follows + ------------------------------------ + | 16 bits | 16 bits | + ------------------------------------ + | index table | prev index | + | entry | | + ------------------------------------ +--------------------------------------------------*/ +typedef struct { + uint16_t prev_index; + uint16_t index_table_entry; +} sw_spec_params; + +/*------------------------ NAT Table Entry --------------------------------------- + + ----------------------------------------------------------------------------------- + | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | + ----------------------------------------------------------------------------------- + | Target IP(4B) | Private IP(4B) | + ----------------------------------------------------------------------------------- + |Target Port(2B) | Private Port(2B) | Public Port(2B) | Next Index(2B) | + ----------------------------------------------------------------------------------- + | Proto | TimeStamp(3B) | Flags(2B) | IP check sum Diff(2B)| + | (1B) | |EN|FIN|Resv | | | + ----------------------------------------------------------------------------------- + | TCP/UDP checksum | Reserved(2B) | SW Specific Parameters(4B) | + | diff (2B) | | + ----------------------------------------------------------------------------------- + + Dont change below structure definition. + It should be same as above(little endian order) + -------------------------------------------------------------------------------*/ +struct ipa_nat_rule { + uint64_t private_ip:32; + uint64_t target_ip:32; + + uint64_t nxt_indx_pub_port:32; + uint64_t private_port:16; + uint64_t target_port:16; + + uint64_t ip_cksm_enbl:32; + uint64_t ts_proto:32; + + /*-------------------------------------------------- + 32 bit sw_spec_params is interpreted as follows + ------------------------------------ + | 16 bits | 16 bits | + ------------------------------------ + | index table | prev index | + | entry | | + ------------------------------------ + --------------------------------------------------*/ + uint64_t sw_spec_params:32; + + uint64_t rsvd2:16; + uint64_t tcp_udp_chksum:16; +}; + +struct ipa_nat_sw_rule { + uint64_t private_ip:32; + uint64_t target_ip:32; + + uint64_t next_index:16; + uint64_t public_port:16; + uint64_t private_port:16; + uint64_t target_port:16; + + uint64_t ip_chksum:16; + uint64_t rsvd1:14; + uint64_t redirect:1; + uint64_t enable:1; + uint64_t time_stamp:24; + uint64_t protocol:8; + + /*-------------------------------------------------- + 32 bit sw_spec_params is interpreted as follows + ------------------------------------ + | 16 bits | 16 bits | + ------------------------------------ + | index table | prev index | + | entry | | + ------------------------------------ + --------------------------------------------------*/ + uint64_t prev_index:16; + uint64_t indx_tbl_entry:16; + uint64_t rsvd2:16; + uint64_t tcp_udp_chksum:16; +}; +#define IPA_NAT_TABLE_ENTRY_SIZE 32 +#define IPA_NAT_INDEX_TABLE_ENTRY_SIZE 4 + +struct ipa_nat_indx_tbl_rule { + uint32_t tbl_entry_nxt_indx; +}; + +struct ipa_nat_sw_indx_tbl_rule { + uint16_t tbl_entry; + uint16_t next_index; +}; + +struct ipa_nat_indx_tbl_meta_info { + uint16_t prev_index; +}; + +struct ipa_nat_ip4_table_cache { + uint8_t valid; + uint32_t public_addr; + + int nat_fd; + int size; + uint32_t tbl_addr_offset; + char table_name[IPA_RESOURCE_NAME_MAX]; + + char *ipv4_rules_addr; + char *index_table_addr; + uint16_t table_entries; + + char *ipv4_expn_rules_addr; + char *index_table_expn_addr; + uint16_t expn_table_entries; + + struct ipa_nat_indx_tbl_meta_info *index_expn_table_meta; + + uint16_t *rule_id_array; +#ifdef IPA_ON_R3PC + uint32_t mmap_offset; +#endif + + uint16_t cur_tbl_cnt; + uint16_t cur_expn_tbl_cnt; +}; + +struct ipa_nat_cache { + struct ipa_nat_ip4_table_cache ip4_tbl[IPA_NAT_MAX_IP4_TBLS]; + int ipa_fd; + uint8_t table_cnt; +}; + +struct ipa_nat_indx_tbl_sw_rule { + uint16_t tbl_entry; + uint16_t next_index; + uint16_t prev_index; +}; + +typedef enum { + IPA_NAT_DEL_TYPE_ONLY_ONE, + IPA_NAT_DEL_TYPE_HEAD, + IPA_NAT_DEL_TYPE_MIDDLE, + IPA_NAT_DEL_TYPE_LAST, +} del_type; + +/** + * ipa_nati_parse_ipv4_rule_hdl() - prase rule handle + * @tbl_hdl: [in] nat table rule + * @rule_hdl: [in] nat rule handle + * @expn_tbl: [out] expansion table or not + * @tbl_entry: [out] index into table + * + * Parse the rule handle to retrieve the nat table + * type and entry of nat table + * + * Returns: None + */ +void ipa_nati_parse_ipv4_rule_hdl(uint8_t tbl_hdl, + uint16_t rule_hdl, + uint8_t *expn_tbl, + uint16_t *tbl_entry); + +/** + * ipa_nati_make_rule_hdl() - makes nat rule handle + * @tbl_hdl: [in] nat table handle + * @tbl_entry: [in] nat table entry + * + * Calculate the nat rule handle which from + * nat entry which will be returned to client of + * nat driver + * + * Returns: >0 nat rule handle + */ +uint16_t ipa_nati_make_rule_hdl(uint16_t tbl_hdl, + uint16_t tbl_entry); + +uint32_t ipa_nati_get_index_entry_offset( + struct ipa_nat_ip4_table_cache*, + nat_table_type tbl_type, + uint16_t indx_tbl_entry); +uint32_t ipa_nati_get_entry_offset( + struct ipa_nat_ip4_table_cache*, + nat_table_type tbl_type, + uint16_t tbl_entry); + +int ipa_nati_add_ipv4_tbl(uint32_t public_ip_addr, + uint16_t number_of_entries, + uint32_t *table_hanle); + +int ipa_nati_alloc_table(uint16_t number_of_entries, + struct ipa_ioc_nat_alloc_mem *mem, + uint16_t*, uint16_t*); + +int ipa_nati_update_cache(struct ipa_ioc_nat_alloc_mem *, + uint32_t public_ip_addr, + uint16_t tbl_entries, + uint16_t expn_tbl_entries); + +int ipa_nati_del_ipv4_table(uint32_t tbl_hdl); +int ipa_nati_reset_ipv4_table(uint32_t tbl_hdl); +int ipa_nati_post_ipv4_init_cmd(uint8_t tbl_index); + +int ipa_nati_query_timestamp(uint32_t tbl_hdl, + uint32_t rule_hdl, + uint32_t *time_stamp); + +int ipa_nati_add_ipv4_rule(uint32_t tbl_hdl, + const ipa_nat_ipv4_rule *clnt_rule, + uint32_t *rule_hdl); + +int ipa_nati_generate_rule(uint32_t tbl_hdl, + const ipa_nat_ipv4_rule *clnt_rule, + struct ipa_nat_sw_rule *rule, + struct ipa_nat_indx_tbl_sw_rule *index_sw_rule, + uint16_t *tbl_entry, + uint16_t *indx_tbl_entry); + +uint16_t ipa_nati_expn_tbl_free_entry(struct ipa_nat_rule *expn_tbl, + uint16_t size); + +uint16_t ipa_nati_generate_tbl_rule(const ipa_nat_ipv4_rule *clnt_rule, + struct ipa_nat_sw_rule *sw_rule, + struct ipa_nat_ip4_table_cache *tbl_ptr); + +uint16_t ipa_nati_generate_index_rule(const ipa_nat_ipv4_rule *clnt_rule, + struct ipa_nat_indx_tbl_sw_rule *sw_rule, + struct ipa_nat_ip4_table_cache *tbl_ptr); + +uint16_t ipa_nati_index_expn_get_free_entry(struct ipa_nat_indx_tbl_rule *tbl, + uint16_t size); + +void ipa_nati_copy_ipv4_rule_to_hw( + struct ipa_nat_ip4_table_cache *ipv4_cache, + struct ipa_nat_sw_rule *rule, + uint16_t entry, uint8_t tbl_index); + +void ipa_nati_copy_ipv4_index_rule_to_hw( + struct ipa_nat_ip4_table_cache *ipv4_cache, + struct ipa_nat_indx_tbl_sw_rule *indx_sw_rule, + uint16_t entry, uint8_t tbl_index); + +void ipa_nati_write_next_index(uint8_t tbl_indx, + nat_table_type tbl_type, + uint16_t value, + uint32_t offset); + +int ipa_nati_post_ipv4_dma_cmd(uint8_t tbl_indx, + uint16_t entry); + +int ipa_nati_del_ipv4_rule(uint32_t tbl_hdl, + uint32_t rule_hdl); + +int ipa_nati_post_del_dma_cmd(uint8_t tbl_indx, + uint16_t tbl_entry, + uint8_t expn_tbl, + del_type rule_pos); + +void ipa_nati_find_index_rule_pos( + struct ipa_nat_ip4_table_cache *cache_ptr, + uint16_t tbl_entry, + del_type *rule_pos); + +void ipa_nati_del_dead_ipv4_head_nodes(uint8_t tbl_indx); +void ipa_nati_find_rule_pos(struct ipa_nat_ip4_table_cache *cache_ptr, + uint8_t expn_tbl, + uint16_t tbl_entry, + del_type *rule_pos); +void ipa_nati_del_dead_ipv4_head_nodes(uint8_t tbl_indx); + +uint16_t Read16BitFieldValue(uint32_t param, + ipa_nat_rule_field_type fld_type); + +/* ======================================================== + Debug functions + ========================================================*/ +#ifdef NAT_DUMP +void ipa_nati_print_rule(struct ipa_nat_rule*, uint32_t); +void ipa_nat_dump_ipv4_table(uint32_t); +void ipa_nati_print_index_rule(struct ipa_nat_indx_tbl_rule*, + uint32_t, uint16_t); +int ipa_nati_query_nat_rules(uint32_t, nat_table_type); +#endif + +#endif /* #ifndef IPA_NAT_DRVI_H */ diff --git a/data-ipa-cfg-mgr/ipanat/inc/ipa_nat_logi.h b/data-ipa-cfg-mgr/ipanat/inc/ipa_nat_logi.h new file mode 100644 index 000000000..5f79cc62e --- /dev/null +++ b/data-ipa-cfg-mgr/ipanat/inc/ipa_nat_logi.h @@ -0,0 +1,73 @@ +/* +Copyright (c) 2013, The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +/*! + @file + ipa_nat_logi.h + + @brief + This file implements the IPAM log functionality. + + @Author + + +*/ + +#ifndef IPA_NAT_LOGI_H +#define IPA_NAT_LOGI_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include +#include +#include + +#define PERROR(fmt) printf("%s:%d %s()", __FILE__, __LINE__, __FUNCTION__);\ + perror(fmt); + +#define IPAERR(fmt, ...) printf("ERR: %s:%d %s() " fmt, __FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__); + +#ifdef DEBUG +#define IPADBG(fmt, ...) printf("%s:%d %s() " fmt, __FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__); + +#define IPADUMP(fmt, ...) printf(fmt, ##__VA_ARGS__); + +#else +#define IPADBG(fmt, ...) +#define IPADUMP(fmt, ...) +#endif + + +#ifdef __cplusplus +} +#endif + +#endif /* IPA_NAT_LOGI_H */ diff --git a/data-ipa-cfg-mgr/ipanat/src/Android.mk b/data-ipa-cfg-mgr/ipanat/src/Android.mk new file mode 100644 index 000000000..ecc64c437 --- /dev/null +++ b/data-ipa-cfg-mgr/ipanat/src/Android.mk @@ -0,0 +1,18 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_C_INCLUDES := $(LOCAL_PATH)/../inc +LOCAL_C_INCLUDES += $(LOCAL_PATH) +LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include +LOCAL_ADDITIONAL_DEPENDENCIES := $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr + +LOCAL_SRC_FILES := ipa_nat_drv.c \ + ipa_nat_drvi.c + +LOCAL_CFLAGS := -DDEBUG +LOCAL_MODULE := libipanat +LOCAL_MODULE_TAGS := optional +LOCAL_PRELINK_MODULE := false + +include $(BUILD_SHARED_LIBRARY) diff --git a/data-ipa-cfg-mgr/ipanat/src/Makefile.am b/data-ipa-cfg-mgr/ipanat/src/Makefile.am new file mode 100644 index 000000000..8bdb9b8ca --- /dev/null +++ b/data-ipa-cfg-mgr/ipanat/src/Makefile.am @@ -0,0 +1,21 @@ +AM_CFLAGS = -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs +AM_CFLAGS += -I./../inc +#AM_CFLAGS += -DDEBUG -g + +common_CFLAGS = -DUSE_GLIB @GLIB_CFLAGS@ +common_LDFLAGS = -lrt @GLIB_LIBS@ + +c_sources = ipa_nat_drv.c \ + ipa_nat_drvi.c \ + ipa_nat_logi.c + +library_includedir = $(pkgincludedir) +library_include_HEADERS = ./../inc/ipa_nat_drvi.h \ + ./../inc/ipa_nat_drv.h \ + ./../inc/ipa_nat_logi.h + +lib_LTLIBRARIES = libipanat.la +libipanat_la_C = @C@ +libipanat_la_SOURCES = $(c_sources) +libipanat_la_CFLAGS = $(AM_CFLAGS) $(common_CFLAGS) +libipanat_la_LDFLAGS = -shared $(common_LDFLAGS) -version-info 1:0:0 diff --git a/data-ipa-cfg-mgr/ipanat/src/ipa_nat_drv.c b/data-ipa-cfg-mgr/ipanat/src/ipa_nat_drv.c new file mode 100644 index 000000000..66504e107 --- /dev/null +++ b/data-ipa-cfg-mgr/ipanat/src/ipa_nat_drv.c @@ -0,0 +1,175 @@ +/* +Copyright (c) 2013, The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "ipa_nat_drv.h" +#include "ipa_nat_drvi.h" + +/** + * ipa_nat_add_ipv4_tbl() - create ipv4 nat table + * @public_ip_addr: [in] public ipv4 address + * @number_of_entries: [in] number of nat entries + * @table_handle: [out] Handle of new ipv4 nat table + * + * To create new ipv4 nat table + * + * Returns: 0 On Success, negative on failure + */ +int ipa_nat_add_ipv4_tbl(uint32_t public_ip_addr, + uint16_t number_of_entries, + uint32_t *tbl_hdl) +{ + int ret; + + if (NULL == tbl_hdl || 0 == number_of_entries) { + IPAERR("Invalid parameters \n"); + return -EINVAL; + } + + ret = ipa_nati_add_ipv4_tbl(public_ip_addr, + number_of_entries, + tbl_hdl); + if (ret != 0) { + IPAERR("unable to add table \n"); + return -EINVAL; + } + IPADBG("Returning table handle 0x%x\n", *tbl_hdl); + + return ret; +} /* __ipa_nat_add_ipv4_tbl() */ + +/** + * ipa_nat_del_ipv4_tbl() - delete ipv4 table + * @table_handle: [in] Handle of ipv4 nat table + * + * To delete given ipv4 nat table + * + * Returns: 0 On Success, negative on failure + */ +int ipa_nat_del_ipv4_tbl(uint32_t tbl_hdl) +{ + if (IPA_NAT_INVALID_NAT_ENTRY == tbl_hdl || + tbl_hdl > IPA_NAT_MAX_IP4_TBLS) { + IPAERR("invalid table handle passed \n"); + return -EINVAL; + } + IPADBG("Passed Table Handle: 0x%x\n", tbl_hdl); + + return ipa_nati_del_ipv4_table(tbl_hdl); +} + +/** + * ipa_nat_add_ipv4_rule() - to insert new ipv4 rule + * @table_handle: [in] handle of ipv4 nat table + * @rule: [in] Pointer to new rule + * @rule_handle: [out] Return the handle to rule + * + * To insert new ipv4 nat rule into ipv4 nat table + * + * Returns: 0 On Success, negative on failure + */ +int ipa_nat_add_ipv4_rule(uint32_t tbl_hdl, + const ipa_nat_ipv4_rule *clnt_rule, + uint32_t *rule_hdl) +{ + int result = -EINVAL; + + if (IPA_NAT_INVALID_NAT_ENTRY == tbl_hdl || + tbl_hdl > IPA_NAT_MAX_IP4_TBLS || NULL == rule_hdl || + NULL == clnt_rule) { + IPAERR("invalide table handle passed \n"); + return result; + } + IPADBG("Passed Table handle: 0x%x\n", tbl_hdl); + + if (ipa_nati_add_ipv4_rule(tbl_hdl, clnt_rule, rule_hdl) != 0) { + return result; + } + + IPADBG("returning rule handle 0x%x\n", *rule_hdl); + return 0; +} + + +/** + * ipa_nat_del_ipv4_rule() - to delete ipv4 nat rule + * @table_handle: [in] handle of ipv4 nat table + * @rule_handle: [in] ipv4 nat rule handle + * + * To insert new ipv4 nat rule into ipv4 nat table + * + * Returns: 0 On Success, negative on failure + */ +int ipa_nat_del_ipv4_rule(uint32_t tbl_hdl, + uint32_t rule_hdl) +{ + int result = -EINVAL; + + if (IPA_NAT_INVALID_NAT_ENTRY == tbl_hdl || + IPA_NAT_INVALID_NAT_ENTRY == rule_hdl) { + IPAERR("invalide parameters\n"); + return result; + } + IPADBG("Passed Table: 0x%x and rule handle 0x%x\n", tbl_hdl, rule_hdl); + + result = ipa_nati_del_ipv4_rule(tbl_hdl, rule_hdl); + if (result) { + IPAERR("unable to delete rule from hw \n"); + return result; + } + + return 0; +} + +/** + * ipa_nat_query_timestamp() - to query timestamp + * @table_handle: [in] handle of ipv4 nat table + * @rule_handle: [in] ipv4 nat rule handle + * @time_stamp: [out] time stamp of rule + * + * To retrieve the timestamp that lastly the + * nat rule was accessed + * + * Returns: 0 On Success, negative on failure + */ +int ipa_nat_query_timestamp(uint32_t tbl_hdl, + uint32_t rule_hdl, + uint32_t *time_stamp) +{ + + if (0 == tbl_hdl || tbl_hdl > IPA_NAT_MAX_IP4_TBLS || + NULL == time_stamp) { + IPAERR("invalid parameters passed \n"); + return -EINVAL; + } + IPADBG("Passed Table: 0x%x and rule handle 0x%x\n", tbl_hdl, rule_hdl); + + return ipa_nati_query_timestamp(tbl_hdl, rule_hdl, time_stamp); +} + + diff --git a/data-ipa-cfg-mgr/ipanat/src/ipa_nat_drvi.c b/data-ipa-cfg-mgr/ipanat/src/ipa_nat_drvi.c new file mode 100644 index 000000000..cfda3e378 --- /dev/null +++ b/data-ipa-cfg-mgr/ipanat/src/ipa_nat_drvi.c @@ -0,0 +1,2300 @@ +/* +Copyright (c) 2013, The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "ipa_nat_drv.h" +#include "ipa_nat_drvi.h" + +#ifdef USE_GLIB +#include +#define strlcpy g_strlcpy +#endif + +struct ipa_nat_cache ipv4_nat_cache; + +/* ------------------------------------------ + UTILITY FUNCTIONS START + --------------------------------------------*/ + +/** + * UpdateSwSpecParams() - updates sw specific params + * @rule: [in/out] nat table rule + * @param_type: [in] which param need to update + * @value: [in] value of param + * + * Update SW specific params in the passed rule. + * + * Returns: None + */ +void UpdateSwSpecParams(struct ipa_nat_rule *rule, + uint8_t param_type, + uint32_t value) +{ + uint32_t temp = rule->sw_spec_params; + + if (IPA_NAT_SW_PARAM_INDX_TBL_ENTRY_BYTE == param_type) { + value = (value << INDX_TBL_ENTRY_SIZE_IN_BITS); + temp &= 0x0000FFFF; + } else { + temp &= 0xFFFF0000; + } + + temp = (temp | value); + rule->sw_spec_params = temp; + return; +} + +/** + * Read8BitFieldValue() + * @rule: [in/out] + * @param_type: [in] + * @value: [in] + * + * + * + * Returns: None + */ + +uint8_t Read8BitFieldValue(uint32_t param, + ipa_nat_rule_field_type fld_type) +{ + void *temp = (void *)¶m; + + switch (fld_type) { + + case PROTOCOL_FIELD: + return ((time_stamp_proto *)temp)->protocol; + + default: + IPAERR("Invalid Field type passed\n"); + return 0; + } +} + +uint16_t Read16BitFieldValue(uint32_t param, + ipa_nat_rule_field_type fld_type) +{ + void *temp = (void *)¶m; + + switch (fld_type) { + + case NEXT_INDEX_FIELD: + return ((next_index_pub_port *)temp)->next_index; + + case PUBLIC_PORT_FILED: + return ((next_index_pub_port *)temp)->public_port; + + case ENABLE_FIELD: + return ((ipcksum_enbl *)temp)->enable; + + case SW_SPEC_PARAM_PREV_INDEX_FIELD: + return ((sw_spec_params *)temp)->prev_index; + + case SW_SPEC_PARAM_INDX_TBL_ENTRY_FIELD: + return ((sw_spec_params *)temp)->index_table_entry; + + case INDX_TBL_TBL_ENTRY_FIELD: + return ((tbl_ent_nxt_indx *)temp)->tbl_entry; + + case INDX_TBL_NEXT_INDEX_FILED: + return ((tbl_ent_nxt_indx *)temp)->next_index; + +#ifdef NAT_DUMP + case IP_CHKSUM_FIELD: + return ((ipcksum_enbl *)temp)->ip_chksum; +#endif + + default: + IPAERR("Invalid Field type passed\n"); + return 0; + } +} + +uint32_t Read32BitFieldValue(uint32_t param, + ipa_nat_rule_field_type fld_type) +{ + + void *temp = (void *)¶m; + + switch (fld_type) { + + case TIME_STAMP_FIELD: + return ((time_stamp_proto *)temp)->time_stamp; + + default: + IPAERR("Invalid Field type passed\n"); + return 0; + } +} + + +/** + * CreateNatDevice() - Create nat devices + * @mem: [in] name of device that need to create + * + * Create Nat device and Register for file create + * notification in given directory and wait till + * receive notification + * + * Returns: 0 on success, negative on failure + */ +int CreateNatDevice(struct ipa_ioc_nat_alloc_mem *mem) +{ + int ret; + + ret = ioctl(ipv4_nat_cache.ipa_fd, IPA_IOC_ALLOC_NAT_MEM, mem); + if (ret != 0) { + perror("CreateNatDevice(): ioctl error value"); + IPAERR("unable to post nat mem init. Error ;%d\n", ret); + IPADBG("ipa fd %d\n", ipv4_nat_cache.ipa_fd); + return -EINVAL; + } + IPADBG("posted IPA_IOC_ALLOC_NAT_MEM to kernel successfully\n"); + return 0; +} + +/** + * GetNearest2Power() - Returns the nearest power of 2 + * @num: [in] given number + * @ret: [out] nearest power of 2 + * + * Returns the nearest power of 2 for a + * given number + * + * Returns: 0 on success, negative on failure + */ +int GetNearest2Power(uint16_t num, uint16_t *ret) +{ + uint16_t number = num; + uint16_t tmp = 1; + *ret = 0; + + if (0 == num) { + return -EINVAL; + } + + if (1 == num) { + *ret = 2; + return 0; + } + + for (;;) { + if (1 == num) { + if (number != tmp) { + tmp *= 2; + } + + *ret = tmp; + return 0; + } + + num >>= 1; + tmp *= 2; + } + + return -EINVAL; +} + +/** + * GetNearestEven() - Returns the nearest even number + * @num: [in] given number + * @ret: [out] nearest even number + * + * Returns the nearest even number for a given number + * + * Returns: 0 on success, negative on failure + */ +void GetNearestEven(uint16_t num, uint16_t *ret) +{ + + if (num < 2) { + *ret = 2; + return; + } + + while ((num % 2) != 0) { + num = num + 1; + } + + *ret = num; + return; +} + +/** + * dst_hash() - Find the index into ipv4 base table + * @trgt_ip: [in] Target IP address + * @trgt_port: [in] Target port + * @public_port: [in] Public port + * @proto: [in] Protocol (TCP/IP) + * @size: [in] size of the ipv4 base Table + * + * This hash method is used to find the hash index of new nat + * entry into ipv4 base table. In case of zero index, the + * new entry will be stored into N-1 index where N is size of + * ipv4 base table + * + * Returns: >0 index into ipv4 base table, negative on failure + */ +static uint16_t dst_hash(uint32_t trgt_ip, uint16_t trgt_port, + uint16_t public_port, uint8_t proto, + uint16_t size) +{ + uint16_t hash = ((uint16_t)(trgt_ip)) ^ ((uint16_t)(trgt_ip >> 16)) ^ + (trgt_port) ^ (public_port) ^ (proto); + + IPADBG("trgt_ip: 0x%x trgt_port: 0x%x\n", trgt_ip, trgt_port); + IPADBG("public_port: 0x%x\n", public_port); + IPADBG("proto: 0x%x size: 0x%x\n", proto, size); + + hash = (hash & size); + + /* If the hash resulted to zero then set it to maximum value + as zero is unused entry in nat tables */ + if (0 == hash) { + return size; + } + + IPADBG("dst_hash returning value: %d\n", hash); + return hash; +} + +/** + * src_hash() - Find the index into ipv4 index base table + * @priv_ip: [in] Private IP address + * @priv_port: [in] Private port + * @trgt_ip: [in] Target IP address + * @trgt_port: [in] Target Port + * @proto: [in] Protocol (TCP/IP) + * @size: [in] size of the ipv4 index base Table + * + * This hash method is used to find the hash index of new nat + * entry into ipv4 index base table. In case of zero index, the + * new entry will be stored into N-1 index where N is size of + * ipv4 index base table + * + * Returns: >0 index into ipv4 index base table, negative on failure + */ +static uint16_t src_hash(uint32_t priv_ip, uint16_t priv_port, + uint32_t trgt_ip, uint16_t trgt_port, + uint8_t proto, uint16_t size) +{ + uint16_t hash = ((uint16_t)(priv_ip)) ^ ((uint16_t)(priv_ip >> 16)) ^ + (priv_port) ^ + ((uint16_t)(trgt_ip)) ^ ((uint16_t)(trgt_ip >> 16)) ^ + (trgt_port) ^ (proto); + + IPADBG("priv_ip: 0x%x priv_port: 0x%x\n", priv_ip, priv_port); + IPADBG("trgt_ip: 0x%x trgt_port: 0x%x\n", trgt_ip, trgt_port); + IPADBG("proto: 0x%x size: 0x%x\n", proto, size); + + hash = (hash & size); + + /* If the hash resulted to zero then set it to maximum value + as zero is unused entry in nat tables */ + if (0 == hash) { + return size; + } + + IPADBG("src_hash returning value: %d\n", hash); + return hash; +} + +/** + * ipa_nati_calc_ip_cksum() - Calculate the source nat + * IP checksum diff + * @pub_ip_addr: [in] public ip address + * @priv_ip_addr: [in] Private ip address + * + * source nat ip checksum different is calculated as + * public_ip_addr - private_ip_addr + * Here we are using 1's complement to represent -ve number. + * So take 1's complement of private ip addr and add it + * to public ip addr. + * + * Returns: >0 ip checksum diff + */ +static uint16_t ipa_nati_calc_ip_cksum(uint32_t pub_ip_addr, + uint32_t priv_ip_addr) +{ + uint16_t ret; + uint32_t cksum = 0; + + /* Add LSB(2 bytes) of public ip address to cksum */ + cksum += (pub_ip_addr & 0xFFFF); + + /* Add MSB(2 bytes) of public ip address to cksum + and check for carry forward(CF), if any add it + */ + cksum += (pub_ip_addr>>16); + if (cksum >> 16) { + cksum = (cksum & 0x0000FFFF); + cksum += 1; + } + + /* Calculate the 1's complement of private ip address */ + priv_ip_addr = (~priv_ip_addr); + + /* Add LSB(2 bytes) of private ip address to cksum + and check for carry forward(CF), if any add it + */ + cksum += (priv_ip_addr & 0xFFFF); + if (cksum >> 16) { + cksum = (cksum & 0x0000FFFF); + cksum += 1; + } + + /* Add MSB(2 bytes) of private ip address to cksum + and check for carry forward(CF), if any add it + */ + cksum += (priv_ip_addr>>16); + if (cksum >> 16) { + cksum = (cksum & 0x0000FFFF); + cksum += 1; + } + + /* Return the LSB(2 bytes) of checksum */ + ret = (uint16_t)cksum; + return ret; +} + +/** + * ipa_nati_calc_tcp_udp_cksum() - Calculate the source nat + * TCP/UDP checksum diff + * @pub_ip_addr: [in] public ip address + * @pub_port: [in] public tcp/udp port + * @priv_ip_addr: [in] Private ip address + * @priv_port: [in] Private tcp/udp prot + * + * source nat tcp/udp checksum is calculated as + * (pub_ip_addr + pub_port) - (priv_ip_addr + priv_port) + * Here we are using 1's complement to represent -ve number. + * So take 1's complement of prviate ip addr &private port + * and add it public ip addr & public port. + * + * Returns: >0 tcp/udp checksum diff + */ +static uint16_t ipa_nati_calc_tcp_udp_cksum(uint32_t pub_ip_addr, + uint16_t pub_port, + uint32_t priv_ip_addr, + uint16_t priv_port) +{ + uint16_t ret = 0; + uint32_t cksum = 0; + + /* Add LSB(2 bytes) of public ip address to cksum */ + cksum += (pub_ip_addr & 0xFFFF); + + /* Add MSB(2 bytes) of public ip address to cksum + and check for carry forward(CF), if any add it + */ + cksum += (pub_ip_addr>>16); + if (cksum >> 16) { + cksum = (cksum & 0x0000FFFF); + cksum += 1; + } + + /* Add public port to cksum and + check for carry forward(CF), if any add it */ + cksum += pub_port; + if (cksum >> 16) { + cksum = (cksum & 0x0000FFFF); + cksum += 1; + } + + /* Calculate the 1's complement of private ip address */ + priv_ip_addr = (~priv_ip_addr); + + /* Add LSB(2 bytes) of private ip address to cksum + and check for carry forward(CF), if any add it + */ + cksum += (priv_ip_addr & 0xFFFF); + if (cksum >> 16) { + cksum = (cksum & 0x0000FFFF); + cksum += 1; + } + + /* Add MSB(2 bytes) of private ip address to cksum + and check for carry forward(CF), if any add + */ + cksum += (priv_ip_addr>>16); + if (cksum >> 16) { + cksum = (cksum & 0x0000FFFF); + cksum += 1; + } + + /* Calculate the 1's complement of private port */ + priv_port = (~priv_port); + + /* Add public port to cksum and + check for carry forward(CF), if any add it */ + cksum += priv_port; + if (cksum >> 16) { + cksum = (cksum & 0x0000FFFF); + cksum += 1; + } + + /* return the LSB(2 bytes) of checksum */ + ret = (uint16_t)cksum; + return ret; +} + +/** + * ipa_nati_make_rule_hdl() - makes nat rule handle + * @tbl_hdl: [in] nat table handle + * @tbl_entry: [in] nat table entry + * + * Calculate the nat rule handle which from + * nat entry which will be returned to client of + * nat driver + * + * Returns: >0 nat rule handle + */ +uint16_t ipa_nati_make_rule_hdl(uint16_t tbl_hdl, + uint16_t tbl_entry) +{ + struct ipa_nat_ip4_table_cache *tbl_ptr; + uint16_t rule_hdl = 0; + uint16_t cnt = 0; + + tbl_ptr = &ipv4_nat_cache.ip4_tbl[tbl_hdl-1]; + + if (tbl_entry >= tbl_ptr->table_entries) { + /* Increase the current expansion table count */ + tbl_ptr->cur_expn_tbl_cnt++; + + /* Update the index into table */ + rule_hdl = tbl_entry - tbl_ptr->table_entries; + rule_hdl = (rule_hdl << IPA_NAT_RULE_HDL_TBL_TYPE_BITS); + /* Update the table type mask */ + rule_hdl = (rule_hdl | IPA_NAT_RULE_HDL_TBL_TYPE_MASK); + } else { + /* Increase the current count */ + tbl_ptr->cur_tbl_cnt++; + + rule_hdl = tbl_entry; + rule_hdl = (rule_hdl << IPA_NAT_RULE_HDL_TBL_TYPE_BITS); + } + + for (; cnt < (tbl_ptr->table_entries + tbl_ptr->expn_table_entries); cnt++) { + if (IPA_NAT_INVALID_NAT_ENTRY == tbl_ptr->rule_id_array[cnt]) { + tbl_ptr->rule_id_array[cnt] = rule_hdl; + return cnt + 1; + } + } + + return 0; +} + +/** + * ipa_nati_parse_ipv4_rule_hdl() - prase rule handle + * @tbl_hdl: [in] nat table rule + * @rule_hdl: [in] nat rule handle + * @expn_tbl: [out] expansion table or not + * @tbl_entry: [out] index into table + * + * Parse the rule handle to retrieve the nat table + * type and entry of nat table + * + * Returns: None + */ +void ipa_nati_parse_ipv4_rule_hdl(uint8_t tbl_index, + uint16_t rule_hdl, uint8_t *expn_tbl, + uint16_t *tbl_entry) +{ + struct ipa_nat_ip4_table_cache *tbl_ptr; + uint16_t rule_id; + + *expn_tbl = 0; + *tbl_entry = IPA_NAT_INVALID_NAT_ENTRY; + tbl_ptr = &ipv4_nat_cache.ip4_tbl[tbl_index]; + + if (rule_hdl >= (tbl_ptr->table_entries + tbl_ptr->expn_table_entries)) { + IPAERR("invalid rule handle\n"); + return; + } + + rule_id = tbl_ptr->rule_id_array[rule_hdl-1]; + + /* Retrieve the table type */ + *expn_tbl = 0; + if (rule_id & IPA_NAT_RULE_HDL_TBL_TYPE_MASK) { + *expn_tbl = 1; + } + + /* Retrieve the table entry */ + *tbl_entry = (rule_id >> IPA_NAT_RULE_HDL_TBL_TYPE_BITS); + return; +} + +uint32_t ipa_nati_get_entry_offset(struct ipa_nat_ip4_table_cache *cache_ptr, + nat_table_type tbl_type, + uint16_t tbl_entry) +{ + struct ipa_nat_rule *tbl_ptr; + uint32_t ret = 0; + + if (IPA_NAT_EXPN_TBL == tbl_type) { + tbl_ptr = (struct ipa_nat_rule *)cache_ptr->ipv4_expn_rules_addr; + } else { + tbl_ptr = (struct ipa_nat_rule *)cache_ptr->ipv4_rules_addr; + } + + ret = (char *)&tbl_ptr[tbl_entry] - (char *)tbl_ptr; + ret += cache_ptr->tbl_addr_offset; + return ret; +} + +uint32_t ipa_nati_get_index_entry_offset(struct ipa_nat_ip4_table_cache *cache_ptr, + nat_table_type tbl_type, + uint16_t indx_tbl_entry) +{ + struct ipa_nat_indx_tbl_rule *indx_tbl_ptr; + uint32_t ret = 0; + + if (IPA_NAT_INDEX_EXPN_TBL == tbl_type) { + indx_tbl_ptr = + (struct ipa_nat_indx_tbl_rule *)cache_ptr->index_table_expn_addr; + } else { + indx_tbl_ptr = + (struct ipa_nat_indx_tbl_rule *)cache_ptr->index_table_addr; + } + + ret = (char *)&indx_tbl_ptr[indx_tbl_entry] - (char *)indx_tbl_ptr; + ret += cache_ptr->tbl_addr_offset; + return ret; +} + +/* ------------------------------------------ + UTILITY FUNCTIONS END +--------------------------------------------*/ + +/* ------------------------------------------ + Main Functions +--------------------------------------------**/ +void ipa_nati_reset_tbl(uint8_t tbl_indx) +{ + uint16_t table_entries = ipv4_nat_cache.ip4_tbl[tbl_indx].table_entries; + uint16_t expn_table_entries = ipv4_nat_cache.ip4_tbl[tbl_indx].expn_table_entries; + + /* Base table */ + IPADBG("memset() base table to 0, %p\n", + ipv4_nat_cache.ip4_tbl[tbl_indx].ipv4_rules_addr); + + memset(ipv4_nat_cache.ip4_tbl[tbl_indx].ipv4_rules_addr, + 0, + IPA_NAT_TABLE_ENTRY_SIZE * table_entries); + + /* Base expansino table */ + IPADBG("memset() expn base table to 0, %p\n", + ipv4_nat_cache.ip4_tbl[tbl_indx].ipv4_expn_rules_addr); + + memset(ipv4_nat_cache.ip4_tbl[tbl_indx].ipv4_expn_rules_addr, + 0, + IPA_NAT_TABLE_ENTRY_SIZE * expn_table_entries); + + /* Index table */ + IPADBG("memset() index table to 0, %p\n", + ipv4_nat_cache.ip4_tbl[tbl_indx].index_table_addr); + + memset(ipv4_nat_cache.ip4_tbl[tbl_indx].index_table_addr, + 0, + IPA_NAT_INDEX_TABLE_ENTRY_SIZE * table_entries); + + /* Index expansion table */ + IPADBG("memset() index expn table to 0, %p\n", + ipv4_nat_cache.ip4_tbl[tbl_indx].index_table_expn_addr); + + memset(ipv4_nat_cache.ip4_tbl[tbl_indx].index_table_expn_addr, + 0, + IPA_NAT_INDEX_TABLE_ENTRY_SIZE * expn_table_entries); + + IPADBG("returning from ipa_nati_reset_tbl()\n"); + return; +} + +int ipa_nati_add_ipv4_tbl(uint32_t public_ip_addr, + uint16_t number_of_entries, + uint32_t *tbl_hdl) +{ + struct ipa_ioc_nat_alloc_mem mem; + uint8_t tbl_indx = ipv4_nat_cache.table_cnt; + uint16_t table_entries, expn_table_entries; + int ret; + + *tbl_hdl = 0; + /* Allocate table */ + memset(&mem, 0, sizeof(mem)); + ret = ipa_nati_alloc_table(number_of_entries, + &mem, + &table_entries, + &expn_table_entries); + if (0 != ret) { + IPAERR("unable to allocate nat table\n"); + return -ENOMEM; + } + + /* Update the cache + The (IPA_NAT_UNUSED_BASE_ENTRIES/2) indicates zero entry entries + for both base and expansion table + */ + ret = ipa_nati_update_cache(&mem, + public_ip_addr, + table_entries, + expn_table_entries); + if (0 != ret) { + IPAERR("unable to update cache Error: %d\n", ret); + return -EINVAL; + } + + /* Reset the nat table before posting init cmd */ + ipa_nati_reset_tbl(tbl_indx); + + /* Initialize the ipa hw with nat table dimensions */ + ret = ipa_nati_post_ipv4_init_cmd(tbl_indx); + if (0 != ret) { + IPAERR("unable to post nat_init command Error %d\n", ret); + return -EINVAL; + } + + /* Return table handle */ + ipv4_nat_cache.table_cnt++; + *tbl_hdl = ipv4_nat_cache.table_cnt; + +#ifdef NAT_DUMP + ipa_nat_dump_ipv4_table(*tbl_hdl); +#endif + return 0; +} + +int ipa_nati_alloc_table(uint16_t number_of_entries, + struct ipa_ioc_nat_alloc_mem *mem, + uint16_t *table_entries, + uint16_t *expn_table_entries) +{ + int fd = 0, ret; + uint16_t total_entries; + + /* Copy the table name */ + strlcpy(mem->dev_name, NAT_DEV_NAME, IPA_RESOURCE_NAME_MAX); + + /* Calculate the size for base table and expansion table */ + *table_entries = (uint16_t)(number_of_entries * IPA_NAT_BASE_TABLE_PERCENTAGE); + if (*table_entries == 0) { + *table_entries = 1; + } + if (GetNearest2Power(*table_entries, table_entries)) { + IPAERR("unable to calculate power of 2\n"); + return -EINVAL; + } + + *expn_table_entries = (uint16_t)(number_of_entries * IPA_NAT_EXPANSION_TABLE_PERCENTAGE); + GetNearestEven(*expn_table_entries, expn_table_entries); + + total_entries = (*table_entries)+(*expn_table_entries); + + /* Calclate the memory size for both table and index table entries */ + mem->size = (IPA_NAT_TABLE_ENTRY_SIZE * total_entries); + IPADBG("Nat Table size: %d\n", mem->size); + mem->size += (IPA_NAT_INDEX_TABLE_ENTRY_SIZE * total_entries); + IPADBG("Nat Base and Index Table size: %d\n", mem->size); + + if (!ipv4_nat_cache.ipa_fd) { + fd = open(IPA_DEV_NAME, O_RDONLY); + if (fd < 0) { + perror("ipa_nati_alloc_table(): open error value:"); + IPAERR("unable to open ipa device\n"); + return -EIO; + } + ipv4_nat_cache.ipa_fd = fd; + } + + ret = CreateNatDevice(mem); + return ret; +} + + +int ipa_nati_update_cache(struct ipa_ioc_nat_alloc_mem *mem, + uint32_t public_addr, + uint16_t tbl_entries, + uint16_t expn_tbl_entries) +{ + uint32_t index = ipv4_nat_cache.table_cnt; + char *ipv4_rules_addr = NULL; + + int fd = 0; + int flags = MAP_SHARED; + int prot = PROT_READ | PROT_WRITE; + off_t offset = 0; +#ifdef IPA_ON_R3PC + int ret = 0; + uint32_t nat_mem_offset = 0; +#endif + + ipv4_nat_cache.ip4_tbl[index].valid = IPA_NAT_TABLE_VALID; + ipv4_nat_cache.ip4_tbl[index].public_addr = public_addr; + ipv4_nat_cache.ip4_tbl[index].size = mem->size; + ipv4_nat_cache.ip4_tbl[index].tbl_addr_offset = mem->offset; + + ipv4_nat_cache.ip4_tbl[index].table_entries = tbl_entries; + ipv4_nat_cache.ip4_tbl[index].expn_table_entries = expn_tbl_entries; + + IPADBG("num of ipv4 rules:%d\n", tbl_entries); + IPADBG("num of ipv4 expn rules:%d\n", expn_tbl_entries); + + /* allocate memory for nat index expansion table */ + if (NULL == ipv4_nat_cache.ip4_tbl[index].index_expn_table_meta) { + ipv4_nat_cache.ip4_tbl[index].index_expn_table_meta = + malloc(sizeof(struct ipa_nat_indx_tbl_meta_info) * expn_tbl_entries); + + if (NULL == ipv4_nat_cache.ip4_tbl[index].index_expn_table_meta) { + IPAERR("Fail to allocate ipv4 index expansion table meta\n"); + return 0; + } + + memset(ipv4_nat_cache.ip4_tbl[index].index_expn_table_meta, + 0, + sizeof(struct ipa_nat_indx_tbl_meta_info) * expn_tbl_entries); + } + + /* Allocate memory for rule_id_array */ + if (NULL == ipv4_nat_cache.ip4_tbl[index].rule_id_array) { + ipv4_nat_cache.ip4_tbl[index].rule_id_array = + malloc(sizeof(uint16_t) * (tbl_entries + expn_tbl_entries)); + + if (NULL == ipv4_nat_cache.ip4_tbl[index].rule_id_array) { + IPAERR("Fail to allocate rule id array\n"); + return 0; + } + + memset(ipv4_nat_cache.ip4_tbl[index].rule_id_array, + 0, + sizeof(uint16_t) * (tbl_entries + expn_tbl_entries)); + } + + + /* open the nat table */ + strlcpy(mem->dev_name, NAT_DEV_FULL_NAME, IPA_RESOURCE_NAME_MAX); + fd = open(mem->dev_name, O_RDWR); + if (fd < 0) { + perror("ipa_nati_update_cache(): open error value:"); + IPAERR("unable to open nat device. Error:%d\n", fd); + return -EIO; + } + + /* copy the nat table name */ + strlcpy(ipv4_nat_cache.ip4_tbl[index].table_name, + mem->dev_name, + IPA_RESOURCE_NAME_MAX); + ipv4_nat_cache.ip4_tbl[index].nat_fd = fd; + + /* open the nat device Table */ +#ifndef IPA_ON_R3PC + ipv4_rules_addr = (void *)mmap(NULL, mem->size, + prot, flags, + fd, offset); +#else + IPADBG("user space r3pc\n"); + ipv4_rules_addr = (void *)mmap((caddr_t)0, NAT_MMAP_MEM_SIZE, + prot, flags, + fd, offset); +#endif + if (MAP_FAILED == ipv4_rules_addr) { + perror("unable to mmap the memory\n"); + return -EINVAL; + } + +#ifdef IPA_ON_R3PC + ret = ioctl(ipv4_nat_cache.ipa_fd, IPA_IOC_GET_NAT_OFFSET, &nat_mem_offset); + if (ret != 0) { + perror("ipa_nati_post_ipv4_init_cmd(): ioctl error value"); + IPAERR("unable to post ant offset cmd Error: %d\n", ret); + IPADBG("ipa fd %d\n", ipv4_nat_cache.ipa_fd); + return -EIO; + } + ipv4_rules_addr += nat_mem_offset; + ipv4_nat_cache.ip4_tbl[index].mmap_offset = nat_mem_offset; +#endif + + IPADBG("mmap return value 0x%lx\n", (long unsigned int)ipv4_rules_addr); + + ipv4_nat_cache.ip4_tbl[index].ipv4_rules_addr = ipv4_rules_addr; + + ipv4_nat_cache.ip4_tbl[index].ipv4_expn_rules_addr = + ipv4_rules_addr + (IPA_NAT_TABLE_ENTRY_SIZE * tbl_entries); + + ipv4_nat_cache.ip4_tbl[index].index_table_addr = + ipv4_rules_addr + (IPA_NAT_TABLE_ENTRY_SIZE * (tbl_entries + expn_tbl_entries)); + + ipv4_nat_cache.ip4_tbl[index].index_table_expn_addr = + ipv4_rules_addr + + (IPA_NAT_TABLE_ENTRY_SIZE * (tbl_entries + expn_tbl_entries))+ + (IPA_NAT_INDEX_TABLE_ENTRY_SIZE * tbl_entries); + + return 0; +} + +/* comment: check the implementation once + offset should be in terms of byes */ +int ipa_nati_post_ipv4_init_cmd(uint8_t tbl_index) +{ + struct ipa_ioc_v4_nat_init cmd; + uint32_t offset = ipv4_nat_cache.ip4_tbl[tbl_index].tbl_addr_offset; + int ret; + + cmd.tbl_index = tbl_index; + + cmd.ipv4_rules_offset = offset; + cmd.expn_rules_offset = cmd.ipv4_rules_offset + + (ipv4_nat_cache.ip4_tbl[tbl_index].table_entries * IPA_NAT_TABLE_ENTRY_SIZE); + + cmd.index_offset = cmd.expn_rules_offset + + (ipv4_nat_cache.ip4_tbl[tbl_index].expn_table_entries * IPA_NAT_TABLE_ENTRY_SIZE); + + cmd.index_expn_offset = cmd.index_offset + + (ipv4_nat_cache.ip4_tbl[tbl_index].table_entries * IPA_NAT_INDEX_TABLE_ENTRY_SIZE); + + cmd.table_entries = ipv4_nat_cache.ip4_tbl[tbl_index].table_entries - 1; + cmd.expn_table_entries = ipv4_nat_cache.ip4_tbl[tbl_index].expn_table_entries; + + cmd.ip_addr = ipv4_nat_cache.ip4_tbl[tbl_index].public_addr; + + ret = ioctl(ipv4_nat_cache.ipa_fd, IPA_IOC_V4_INIT_NAT, &cmd); + if (ret != 0) { + perror("ipa_nati_post_ipv4_init_cmd(): ioctl error value"); + IPAERR("unable to post init cmd Error: %d\n", ret); + IPADBG("ipa fd %d\n", ipv4_nat_cache.ipa_fd); + return -EINVAL; + } + IPADBG("Posted IPA_IOC_V4_INIT_NAT to kernel successfully\n"); + + return 0; +} + +int ipa_nati_del_ipv4_table(uint32_t tbl_hdl) +{ + uint8_t index = (uint8_t)(tbl_hdl - 1); + void *addr = (void *)ipv4_nat_cache.ip4_tbl[index].ipv4_rules_addr; + struct ipa_ioc_v4_nat_del del_cmd; + int ret; + + if (!ipv4_nat_cache.ip4_tbl[index].valid) { + IPAERR("invalid table handle passed\n"); + return -EINVAL; + } + + /* unmap the device memory from user space */ +#ifndef IPA_ON_R3PC + munmap(addr, ipv4_nat_cache.ip4_tbl[index].size); +#else + addr = (char *)addr - ipv4_nat_cache.ip4_tbl[index].mmap_offset; + munmap(addr, NAT_MMAP_MEM_SIZE); +#endif + + /* close the file descriptor of nat device */ + if (close(ipv4_nat_cache.ip4_tbl[index].nat_fd)) { + IPAERR("unable to close the file descriptor\n"); + return -EINVAL; + } + + del_cmd.table_index = index; + del_cmd.public_ip_addr = ipv4_nat_cache.ip4_tbl[index].public_addr; + ret = ioctl(ipv4_nat_cache.ipa_fd, IPA_IOC_V4_DEL_NAT, &del_cmd); + if (ret != 0) { + perror("ipa_nati_del_ipv4_table(): ioctl error value"); + IPAERR("unable to post nat del command init Error: %d\n", ret); + IPADBG("ipa fd %d\n", ipv4_nat_cache.ipa_fd); + return -EINVAL; + } + IPADBG("posted IPA_IOC_V4_DEL_NAT to kernel successfully\n"); + + free(ipv4_nat_cache.ip4_tbl[index].index_expn_table_meta); + free(ipv4_nat_cache.ip4_tbl[index].rule_id_array); + + memset(&ipv4_nat_cache.ip4_tbl[index], + 0, + sizeof(ipv4_nat_cache.ip4_tbl[index])); + + /* Decrease the table count by 1*/ + ipv4_nat_cache.table_cnt--; + + return 0; +} + +int ipa_nati_query_timestamp(uint32_t tbl_hdl, + uint32_t rule_hdl, + uint32_t *time_stamp) +{ + uint8_t tbl_index = (uint8_t)(tbl_hdl - 1); + uint8_t expn_tbl = 0; + uint16_t tbl_entry = 0; + struct ipa_nat_rule *tbl_ptr = NULL; + + if (!ipv4_nat_cache.ip4_tbl[tbl_index].valid) { + IPAERR("invalid table handle\n"); + return -EINVAL; + } + + ipa_nati_parse_ipv4_rule_hdl(tbl_index, (uint16_t)rule_hdl, + &expn_tbl, &tbl_entry); + + tbl_ptr = + (struct ipa_nat_rule *)ipv4_nat_cache.ip4_tbl[tbl_index].ipv4_rules_addr; + if (expn_tbl) { + tbl_ptr = + (struct ipa_nat_rule *)ipv4_nat_cache.ip4_tbl[tbl_index].ipv4_expn_rules_addr; + } + + *time_stamp = Read32BitFieldValue(tbl_ptr[tbl_entry].ts_proto, + TIME_STAMP_FIELD); + return 0; +} + +int ipa_nati_add_ipv4_rule(uint32_t tbl_hdl, + const ipa_nat_ipv4_rule *clnt_rule, + uint32_t *rule_hdl) +{ + struct ipa_nat_ip4_table_cache *tbl_ptr; + struct ipa_nat_sw_rule sw_rule; + struct ipa_nat_indx_tbl_sw_rule index_sw_rule; + uint16_t new_entry, new_index_tbl_entry; + + memset(&sw_rule, 0, sizeof(sw_rule)); + memset(&index_sw_rule, 0, sizeof(index_sw_rule)); + + /* Generate rule from client input */ + if (ipa_nati_generate_rule(tbl_hdl, clnt_rule, + &sw_rule, &index_sw_rule, + &new_entry, &new_index_tbl_entry)) { + IPAERR("unable to generate rule\n"); + return -EINVAL; + } + + tbl_ptr = &ipv4_nat_cache.ip4_tbl[tbl_hdl-1]; + ipa_nati_copy_ipv4_rule_to_hw(tbl_ptr, &sw_rule, new_entry, (uint8_t)(tbl_hdl-1)); + ipa_nati_copy_ipv4_index_rule_to_hw(tbl_ptr, + &index_sw_rule, + new_index_tbl_entry, + (uint8_t)(tbl_hdl-1)); + + IPADBG("new entry:%d, new index entry: %d\n", new_entry, new_index_tbl_entry); + if (ipa_nati_post_ipv4_dma_cmd((uint8_t)(tbl_hdl - 1), new_entry)) { + IPAERR("unable to post dma command\n"); + return -EIO; + } + + /* Generate rule handle */ + *rule_hdl = ipa_nati_make_rule_hdl((uint16_t)tbl_hdl, new_entry); + if (!(*rule_hdl)) { + IPAERR("unable to generate rule handle\n"); + return -EINVAL; + } + +#ifdef NAT_DUMP + ipa_nat_dump_ipv4_table(tbl_hdl); +#endif + + return 0; +} + +int ipa_nati_generate_rule(uint32_t tbl_hdl, + const ipa_nat_ipv4_rule *clnt_rule, + struct ipa_nat_sw_rule *rule, + struct ipa_nat_indx_tbl_sw_rule *index_sw_rule, + uint16_t *tbl_entry, + uint16_t *indx_tbl_entry) +{ + struct ipa_nat_ip4_table_cache *tbl_ptr; + uint16_t tmp; + + if (NULL == clnt_rule || NULL == index_sw_rule || + NULL == rule || NULL == tbl_entry || + NULL == indx_tbl_entry) { + IPAERR("invalid parameters\n"); + return -EINVAL; + } + + tbl_ptr = &ipv4_nat_cache.ip4_tbl[tbl_hdl-1]; + + *tbl_entry = ipa_nati_generate_tbl_rule(clnt_rule, + rule, + tbl_ptr); + if (IPA_NAT_INVALID_NAT_ENTRY == *tbl_entry) { + IPAERR("unable to generate table entry\n"); + return -EINVAL; + } + + index_sw_rule->tbl_entry = *tbl_entry; + *indx_tbl_entry = ipa_nati_generate_index_rule(clnt_rule, + index_sw_rule, + tbl_ptr); + if (IPA_NAT_INVALID_NAT_ENTRY == *indx_tbl_entry) { + IPAERR("unable to generate index table entry\n"); + return -EINVAL; + } + + rule->indx_tbl_entry = *indx_tbl_entry; + if (*indx_tbl_entry >= tbl_ptr->table_entries) { + tmp = *indx_tbl_entry - tbl_ptr->table_entries; + tbl_ptr->index_expn_table_meta[tmp].prev_index = index_sw_rule->prev_index; + } + + return 0; +} + +uint16_t ipa_nati_generate_tbl_rule(const ipa_nat_ipv4_rule *clnt_rule, + struct ipa_nat_sw_rule *sw_rule, + struct ipa_nat_ip4_table_cache *tbl_ptr) +{ + uint32_t pub_ip_addr; + uint16_t prev = 0, nxt_indx = 0, new_entry; + struct ipa_nat_rule *tbl = NULL, *expn_tbl = NULL; + + pub_ip_addr = tbl_ptr->public_addr; + + tbl = (struct ipa_nat_rule *)tbl_ptr->ipv4_rules_addr; + expn_tbl = (struct ipa_nat_rule *)tbl_ptr->ipv4_expn_rules_addr; + + /* copy the values from client rule to sw rule */ + sw_rule->private_ip = clnt_rule->private_ip; + sw_rule->private_port = clnt_rule->private_port; + sw_rule->protocol = clnt_rule->protocol; + sw_rule->public_port = clnt_rule->public_port; + sw_rule->target_ip = clnt_rule->target_ip; + sw_rule->target_port = clnt_rule->target_port; + + /* consider only public and private ip fields */ + sw_rule->ip_chksum = ipa_nati_calc_ip_cksum(pub_ip_addr, + clnt_rule->private_ip); + + if (IPPROTO_TCP == sw_rule->protocol || + IPPROTO_UDP == sw_rule->protocol) { + /* consider public and private ip & port fields */ + sw_rule->tcp_udp_chksum = ipa_nati_calc_tcp_udp_cksum( + pub_ip_addr, + clnt_rule->public_port, + clnt_rule->private_ip, + clnt_rule->private_port); + } + + sw_rule->rsvd1 = 0; + sw_rule->enable = IPA_NAT_FLAG_DISABLE_BIT; + sw_rule->next_index = 0; + + /* + SW sets this timer to 0. + The assumption is that 0 is an invalid clock value and no clock + wraparounds are expected + */ + sw_rule->time_stamp = 0; + sw_rule->rsvd2 = 0; + sw_rule->prev_index = 0; + sw_rule->indx_tbl_entry = 0; + + new_entry = dst_hash(clnt_rule->target_ip, + clnt_rule->target_port, + clnt_rule->public_port, + clnt_rule->protocol, + tbl_ptr->table_entries-1); + + /* check whether there is any collision + if no collision return */ + if (!Read16BitFieldValue(tbl[new_entry].ip_cksm_enbl, + ENABLE_FIELD)) { + sw_rule->prev_index = 0; + IPADBG("Destination Nat New Entry Index %d\n", new_entry); + return new_entry; + } + + /* First collision */ + if (Read16BitFieldValue(tbl[new_entry].nxt_indx_pub_port, + NEXT_INDEX_FIELD) == IPA_NAT_INVALID_NAT_ENTRY) { + sw_rule->prev_index = new_entry; + } else { /* check for more than one collision */ + /* Find the IPA_NAT_DEL_TYPE_LAST entry in list */ + nxt_indx = Read16BitFieldValue(tbl[new_entry].nxt_indx_pub_port, + NEXT_INDEX_FIELD); + + while (nxt_indx != IPA_NAT_INVALID_NAT_ENTRY) { + prev = nxt_indx; + + nxt_indx -= tbl_ptr->table_entries; + nxt_indx = Read16BitFieldValue(expn_tbl[nxt_indx].nxt_indx_pub_port, + NEXT_INDEX_FIELD); + + /* Handling error case */ + if (prev == nxt_indx) { + IPAERR("Error: Prev index:%d and next:%d index should not be same\n", prev, nxt_indx); + return IPA_NAT_INVALID_NAT_ENTRY; + } + } + + sw_rule->prev_index = prev; + } + + /* On collision check for the free entry in expansion table */ + new_entry = ipa_nati_expn_tbl_free_entry(expn_tbl, + tbl_ptr->expn_table_entries); + + if (IPA_NAT_INVALID_NAT_ENTRY == new_entry) { + /* Expansion table is full return*/ + IPAERR("Expansion table is full\n"); + IPAERR("Current Table: %d & Expn Entries: %d\n", + tbl_ptr->cur_tbl_cnt, tbl_ptr->cur_expn_tbl_cnt); + return IPA_NAT_INVALID_NAT_ENTRY; + } + new_entry += tbl_ptr->table_entries; + + IPADBG("new entry index %d\n", new_entry); + return new_entry; +} + +/* returns expn table entry index */ +uint16_t ipa_nati_expn_tbl_free_entry(struct ipa_nat_rule *expn_tbl, + uint16_t size) +{ + int cnt; + + for (cnt = 1; cnt < size; cnt++) { + if (!Read16BitFieldValue(expn_tbl[cnt].ip_cksm_enbl, + ENABLE_FIELD)) { + IPADBG("new expansion table entry index %d\n", cnt); + return cnt; + } + } + + IPAERR("nat expansion table is full\n"); + return 0; +} + +uint16_t ipa_nati_generate_index_rule(const ipa_nat_ipv4_rule *clnt_rule, + struct ipa_nat_indx_tbl_sw_rule *sw_rule, + struct ipa_nat_ip4_table_cache *tbl_ptr) +{ + struct ipa_nat_indx_tbl_rule *indx_tbl, *indx_expn_tbl; + uint16_t prev = 0, nxt_indx = 0, new_entry; + + indx_tbl = + (struct ipa_nat_indx_tbl_rule *)tbl_ptr->index_table_addr; + indx_expn_tbl = + (struct ipa_nat_indx_tbl_rule *)tbl_ptr->index_table_expn_addr; + + new_entry = src_hash(clnt_rule->private_ip, + clnt_rule->private_port, + clnt_rule->target_ip, + clnt_rule->target_port, + clnt_rule->protocol, + tbl_ptr->table_entries-1); + + /* check whether there is any collision + if no collision return */ + if (!Read16BitFieldValue(indx_tbl[new_entry].tbl_entry_nxt_indx, + INDX_TBL_TBL_ENTRY_FIELD)) { + sw_rule->prev_index = 0; + IPADBG("Source Nat Index Table Entry %d\n", new_entry); + return new_entry; + } + + /* check for more than one collision */ + if (Read16BitFieldValue(indx_tbl[new_entry].tbl_entry_nxt_indx, + INDX_TBL_NEXT_INDEX_FILED) == IPA_NAT_INVALID_NAT_ENTRY) { + sw_rule->prev_index = new_entry; + IPADBG("First collosion. Entry %d\n", new_entry); + } else { + /* Find the IPA_NAT_DEL_TYPE_LAST entry in list */ + nxt_indx = Read16BitFieldValue(indx_tbl[new_entry].tbl_entry_nxt_indx, + INDX_TBL_NEXT_INDEX_FILED); + + while (nxt_indx != IPA_NAT_INVALID_NAT_ENTRY) { + prev = nxt_indx; + + nxt_indx -= tbl_ptr->table_entries; + nxt_indx = Read16BitFieldValue(indx_expn_tbl[nxt_indx].tbl_entry_nxt_indx, + INDX_TBL_NEXT_INDEX_FILED); + + /* Handling error case */ + if (prev == nxt_indx) { + IPAERR("Error: Prev:%d and next:%d index should not be same\n", prev, nxt_indx); + return IPA_NAT_INVALID_NAT_ENTRY; + } + } + + sw_rule->prev_index = prev; + } + + /* On collision check for the free entry in expansion table */ + new_entry = ipa_nati_index_expn_get_free_entry(indx_expn_tbl, + tbl_ptr->expn_table_entries); + + if (IPA_NAT_INVALID_NAT_ENTRY == new_entry) { + /* Expansion table is full return*/ + IPAERR("Index expansion table is full\n"); + IPAERR("Current Table: %d & Expn Entries: %d\n", + tbl_ptr->cur_tbl_cnt, tbl_ptr->cur_expn_tbl_cnt); + return IPA_NAT_INVALID_NAT_ENTRY; + } + new_entry += tbl_ptr->table_entries; + + + if (sw_rule->prev_index == new_entry) { + IPAERR("Error: prev_entry:%d ", sw_rule->prev_index); + IPAERR("and new_entry:%d should not be same ", new_entry); + IPAERR("infinite loop detected\n"); + return IPA_NAT_INVALID_NAT_ENTRY; + } + + IPADBG("index table entry %d\n", new_entry); + return new_entry; +} + +/* returns index expn table entry index */ +uint16_t ipa_nati_index_expn_get_free_entry( + struct ipa_nat_indx_tbl_rule *indx_tbl, + uint16_t size) +{ + int cnt; + for (cnt = 1; cnt < size; cnt++) { + if (!Read16BitFieldValue(indx_tbl[cnt].tbl_entry_nxt_indx, + INDX_TBL_TBL_ENTRY_FIELD)) { + return cnt; + } + } + + IPAERR("nat index expansion table is full\n"); + return 0; +} + +void ipa_nati_write_next_index(uint8_t tbl_indx, + nat_table_type tbl_type, + uint16_t value, + uint32_t offset) +{ + struct ipa_ioc_nat_dma_cmd *cmd; + + IPADBG("Updating next index field of table %d on collosion using dma\n", tbl_type); + IPADBG("table index: %d, value: %d offset;%d\n", tbl_indx, value, offset); + + cmd = (struct ipa_ioc_nat_dma_cmd *) + malloc(sizeof(struct ipa_ioc_nat_dma_cmd)+ + sizeof(struct ipa_ioc_nat_dma_one)); + if (NULL == cmd) { + IPAERR("unable to allocate memory\n"); + return; + } + + cmd->dma[0].table_index = tbl_indx; + cmd->dma[0].base_addr = tbl_type; + cmd->dma[0].data = value; + cmd->dma[0].offset = offset; + + cmd->entries = 1; + if (ioctl(ipv4_nat_cache.ipa_fd, IPA_IOC_NAT_DMA, cmd)) { + perror("ipa_nati_post_ipv4_dma_cmd(): ioctl error value"); + IPAERR("unable to call dma icotl to update next index\n"); + IPAERR("ipa fd %d\n", ipv4_nat_cache.ipa_fd); + goto fail; + } + +fail: + free(cmd); + + return; +} + +void ipa_nati_copy_ipv4_rule_to_hw( + struct ipa_nat_ip4_table_cache *ipv4_cache, + struct ipa_nat_sw_rule *rule, + uint16_t entry, uint8_t tbl_index) +{ + struct ipa_nat_rule *tbl_ptr; + uint16_t prev_entry = rule->prev_index; + nat_table_type tbl_type; + uint32_t offset = 0; + + if (entry < ipv4_cache->table_entries) { + tbl_ptr = (struct ipa_nat_rule *)ipv4_cache->ipv4_rules_addr; + + memcpy(&tbl_ptr[entry], + rule, + sizeof(struct ipa_nat_rule)); + } else { + tbl_ptr = (struct ipa_nat_rule *)ipv4_cache->ipv4_expn_rules_addr; + memcpy(&tbl_ptr[entry - ipv4_cache->table_entries], + rule, + sizeof(struct ipa_nat_rule)); + } + + /* Update the previos entry next_index */ + if (IPA_NAT_INVALID_NAT_ENTRY != prev_entry) { + + if (prev_entry < ipv4_cache->table_entries) { + tbl_type = IPA_NAT_BASE_TBL; + tbl_ptr = (struct ipa_nat_rule *)ipv4_cache->ipv4_rules_addr; + } else { + tbl_type = IPA_NAT_EXPN_TBL; + /* tbp_ptr is already pointing to expansion table + no need to initialize it */ + prev_entry = prev_entry - ipv4_cache->table_entries; + } + + offset = ipa_nati_get_entry_offset(ipv4_cache, tbl_type, prev_entry); + offset += IPA_NAT_RULE_NEXT_FIELD_OFFSET; + + ipa_nati_write_next_index(tbl_index, tbl_type, entry, offset); + } + + return; +} + +void ipa_nati_copy_ipv4_index_rule_to_hw( + struct ipa_nat_ip4_table_cache *ipv4_cache, + struct ipa_nat_indx_tbl_sw_rule *indx_sw_rule, + uint16_t entry, + uint8_t tbl_index) +{ + struct ipa_nat_indx_tbl_rule *tbl_ptr; + struct ipa_nat_sw_indx_tbl_rule sw_rule; + uint16_t prev_entry = indx_sw_rule->prev_index; + nat_table_type tbl_type; + uint16_t offset = 0; + + sw_rule.next_index = indx_sw_rule->next_index; + sw_rule.tbl_entry = indx_sw_rule->tbl_entry; + + if (entry < ipv4_cache->table_entries) { + tbl_ptr = (struct ipa_nat_indx_tbl_rule *)ipv4_cache->index_table_addr; + + memcpy(&tbl_ptr[entry], + &sw_rule, + sizeof(struct ipa_nat_indx_tbl_rule)); + } else { + tbl_ptr = (struct ipa_nat_indx_tbl_rule *)ipv4_cache->index_table_expn_addr; + + memcpy(&tbl_ptr[entry - ipv4_cache->table_entries], + &sw_rule, + sizeof(struct ipa_nat_indx_tbl_rule)); + } + + /* Update the next field of previous entry on collosion */ + if (IPA_NAT_INVALID_NAT_ENTRY != prev_entry) { + if (prev_entry < ipv4_cache->table_entries) { + tbl_type = IPA_NAT_INDX_TBL; + tbl_ptr = (struct ipa_nat_indx_tbl_rule *)ipv4_cache->index_table_addr; + } else { + tbl_type = IPA_NAT_INDEX_EXPN_TBL; + /* tbp_ptr is already pointing to expansion table + no need to initialize it */ + prev_entry = prev_entry - ipv4_cache->table_entries; + } + + offset = ipa_nati_get_index_entry_offset(ipv4_cache, tbl_type, prev_entry); + offset += IPA_NAT_INDEX_RULE_NEXT_FIELD_OFFSET; + + IPADBG("Updating next index field of index table on collosion using dma()\n"); + ipa_nati_write_next_index(tbl_index, tbl_type, entry, offset); + } + + return; +} + +int ipa_nati_post_ipv4_dma_cmd(uint8_t tbl_indx, + uint16_t entry) +{ + struct ipa_ioc_nat_dma_cmd *cmd; + struct ipa_nat_rule *tbl_ptr; + uint32_t offset = ipv4_nat_cache.ip4_tbl[tbl_indx].tbl_addr_offset; + int ret = 0; + + cmd = (struct ipa_ioc_nat_dma_cmd *) + malloc(sizeof(struct ipa_ioc_nat_dma_cmd)+ + sizeof(struct ipa_ioc_nat_dma_one)); + if (NULL == cmd) { + IPAERR("unable to allocate memory\n"); + return -ENOMEM; + } + + if (entry < ipv4_nat_cache.ip4_tbl[tbl_indx].table_entries) { + tbl_ptr = + (struct ipa_nat_rule *)ipv4_nat_cache.ip4_tbl[tbl_indx].ipv4_rules_addr; + + cmd->dma[0].table_index = tbl_indx; + cmd->dma[0].base_addr = IPA_NAT_BASE_TBL; + cmd->dma[0].data = IPA_NAT_FLAG_ENABLE_BIT_MASK; + + cmd->dma[0].offset = (char *)&tbl_ptr[entry] - (char *)tbl_ptr; + cmd->dma[0].offset += IPA_NAT_RULE_FLAG_FIELD_OFFSET; + } else { + tbl_ptr = + (struct ipa_nat_rule *)ipv4_nat_cache.ip4_tbl[tbl_indx].ipv4_expn_rules_addr; + entry = entry - ipv4_nat_cache.ip4_tbl[tbl_indx].table_entries; + + cmd->dma[0].table_index = tbl_indx; + cmd->dma[0].base_addr = IPA_NAT_EXPN_TBL; + cmd->dma[0].data = IPA_NAT_FLAG_ENABLE_BIT_MASK; + + cmd->dma[0].offset = (char *)&tbl_ptr[entry] - (char *)tbl_ptr; + cmd->dma[0].offset += IPA_NAT_RULE_FLAG_FIELD_OFFSET; + cmd->dma[0].offset += offset; + } + + cmd->entries = 1; + if (ioctl(ipv4_nat_cache.ipa_fd, IPA_IOC_NAT_DMA, cmd)) { + perror("ipa_nati_post_ipv4_dma_cmd(): ioctl error value"); + IPAERR("unable to call dma icotl\n"); + IPADBG("ipa fd %d\n", ipv4_nat_cache.ipa_fd); + ret = -EIO; + goto fail; + } + IPADBG("posted IPA_IOC_NAT_DMA to kernel successfully during add operation\n"); + + +fail: + free(cmd); + + return ret; +} + + +int ipa_nati_del_ipv4_rule(uint32_t tbl_hdl, + uint32_t rule_hdl) +{ + uint8_t expn_tbl; + uint16_t tbl_entry; + struct ipa_nat_ip4_table_cache *tbl_ptr; + del_type rule_pos; + uint8_t tbl_indx = (uint8_t)(tbl_hdl - 1); + + /* Parse the rule handle */ + ipa_nati_parse_ipv4_rule_hdl(tbl_indx, (uint16_t)rule_hdl, + &expn_tbl, &tbl_entry); + if (IPA_NAT_INVALID_NAT_ENTRY == tbl_entry) { + IPAERR("Invalid Rule Entry\n"); + return -EINVAL; + } + + IPADBG("Delete below rule\n"); + IPADBG("tbl_entry:%d expn_tbl:%d\n", tbl_entry, expn_tbl); + + tbl_ptr = &ipv4_nat_cache.ip4_tbl[tbl_indx]; + if (!tbl_ptr->valid) { + IPAERR("invalid table handle\n"); + return -EINVAL; + } + + ipa_nati_find_rule_pos(tbl_ptr, expn_tbl, + tbl_entry, &rule_pos); + IPADBG("rule_pos:%d\n", rule_pos); + + if (ipa_nati_post_del_dma_cmd(tbl_indx, tbl_entry, + expn_tbl, rule_pos)) { + return -EINVAL; + } + + ipa_nati_del_dead_ipv4_head_nodes(tbl_indx); + + /* Reset rule_id_array entry */ + ipv4_nat_cache.ip4_tbl[tbl_indx].rule_id_array[rule_hdl-1] = + IPA_NAT_INVALID_NAT_ENTRY; + +#ifdef NAT_DUMP + IPADBG("Dumping Table after deleting rule\n"); + ipa_nat_dump_ipv4_table(tbl_hdl); +#endif + + return 0; +} + +void ReorderCmds(struct ipa_ioc_nat_dma_cmd *cmd, int size) +{ + int indx_tbl_start = 0, cnt, cnt1; + struct ipa_ioc_nat_dma_cmd *tmp; + + IPADBG("called ReorderCmds() with entries :%d\n", cmd->entries); + + for (cnt = 0; cnt < cmd->entries; cnt++) { + if (cmd->dma[cnt].base_addr == IPA_NAT_INDX_TBL || + cmd->dma[cnt].base_addr == IPA_NAT_INDEX_EXPN_TBL) { + indx_tbl_start = cnt; + break; + } + } + + if (indx_tbl_start == 0) { + IPADBG("Reorder not needed\n"); + return; + } + + tmp = (struct ipa_ioc_nat_dma_cmd *)malloc(size); + if (tmp == NULL) { + IPAERR("unable to allocate memory\n"); + return; + } + + cnt1 = 0; + tmp->entries = cmd->entries; + for (cnt = indx_tbl_start; cnt < cmd->entries; cnt++) { + tmp->dma[cnt1] = cmd->dma[cnt]; + cnt1++; + } + + for (cnt = 0; cnt < indx_tbl_start; cnt++) { + tmp->dma[cnt1] = cmd->dma[cnt]; + cnt1++; + } + + memset(cmd, 0, size); + memcpy(cmd, tmp, size); + free(tmp); + + return; +} + +int ipa_nati_post_del_dma_cmd(uint8_t tbl_indx, + uint16_t cur_tbl_entry, + uint8_t expn_tbl, + del_type rule_pos) +{ + +#define MAX_DMA_ENTRIES_FOR_DEL 3 + + struct ipa_nat_ip4_table_cache *cache_ptr; + struct ipa_nat_indx_tbl_rule *indx_tbl_ptr; + struct ipa_nat_rule *tbl_ptr; + int ret = 0, size = 0; + + uint16_t indx_tbl_entry = IPA_NAT_INVALID_NAT_ENTRY; + del_type indx_rule_pos; + + struct ipa_ioc_nat_dma_cmd *cmd; + uint8_t no_of_cmds = 0; + + uint16_t prev_entry = IPA_NAT_INVALID_NAT_ENTRY; + uint16_t next_entry = IPA_NAT_INVALID_NAT_ENTRY; + uint16_t indx_next_entry = IPA_NAT_INVALID_NAT_ENTRY; + uint16_t indx_next_next_entry = IPA_NAT_INVALID_NAT_ENTRY; + uint16_t table_entry; + + size = sizeof(struct ipa_ioc_nat_dma_cmd)+ + (MAX_DMA_ENTRIES_FOR_DEL * sizeof(struct ipa_ioc_nat_dma_one)); + + cmd = (struct ipa_ioc_nat_dma_cmd *)malloc(size); + if (NULL == cmd) { + IPAERR("unable to allocate memory\n"); + return -ENOMEM; + } + + cache_ptr = &ipv4_nat_cache.ip4_tbl[tbl_indx]; + if (!expn_tbl) { + tbl_ptr = (struct ipa_nat_rule *)cache_ptr->ipv4_rules_addr; + } else { + tbl_ptr = (struct ipa_nat_rule *)cache_ptr->ipv4_expn_rules_addr; + } + + + if (!Read16BitFieldValue(tbl_ptr[cur_tbl_entry].ip_cksm_enbl, + ENABLE_FIELD)) { + IPAERR("Deleting invalid(not enabled) rule\n"); + ret = -EINVAL; + goto fail; + } + + indx_tbl_entry = + Read16BitFieldValue(tbl_ptr[cur_tbl_entry].sw_spec_params, + SW_SPEC_PARAM_INDX_TBL_ENTRY_FIELD); + + /* ================================================ + Base Table rule Deletion + ================================================*/ + /* Just delete the current rule by disabling the flag field */ + if (IPA_NAT_DEL_TYPE_ONLY_ONE == rule_pos) { + cmd->dma[no_of_cmds].table_index = tbl_indx; + cmd->dma[no_of_cmds].base_addr = IPA_NAT_BASE_TBL; + cmd->dma[no_of_cmds].data = IPA_NAT_FLAG_DISABLE_BIT_MASK; + + cmd->dma[no_of_cmds].offset = + ipa_nati_get_entry_offset(cache_ptr, + cmd->dma[no_of_cmds].base_addr, + cur_tbl_entry); + cmd->dma[no_of_cmds].offset += IPA_NAT_RULE_FLAG_FIELD_OFFSET; + } + + /* Just update the protocol field to invalid */ + else if (IPA_NAT_DEL_TYPE_HEAD == rule_pos) { + cmd->dma[no_of_cmds].table_index = tbl_indx; + cmd->dma[no_of_cmds].base_addr = IPA_NAT_BASE_TBL; + cmd->dma[no_of_cmds].data = IPA_NAT_INVALID_PROTO_FIELD_VALUE; + + cmd->dma[no_of_cmds].offset = + ipa_nati_get_entry_offset(cache_ptr, + cmd->dma[no_of_cmds].base_addr, + cur_tbl_entry); + cmd->dma[no_of_cmds].offset += IPA_NAT_RULE_PROTO_FIELD_OFFSET; + + IPADBG("writing invalid proto: 0x%x\n", cmd->dma[no_of_cmds].data); + } + + /* + Update the previous entry of next_index field value + with current entry next_index field value + */ + else if (IPA_NAT_DEL_TYPE_MIDDLE == rule_pos) { + prev_entry = + Read16BitFieldValue(tbl_ptr[cur_tbl_entry].sw_spec_params, + SW_SPEC_PARAM_PREV_INDEX_FIELD); + + cmd->dma[no_of_cmds].table_index = tbl_indx; + cmd->dma[no_of_cmds].data = + Read16BitFieldValue(tbl_ptr[cur_tbl_entry].nxt_indx_pub_port, + NEXT_INDEX_FIELD); + + cmd->dma[no_of_cmds].base_addr = IPA_NAT_BASE_TBL; + if (prev_entry >= cache_ptr->table_entries) { + cmd->dma[no_of_cmds].base_addr = IPA_NAT_EXPN_TBL; + prev_entry -= cache_ptr->table_entries; + } + + cmd->dma[no_of_cmds].offset = + ipa_nati_get_entry_offset(cache_ptr, + cmd->dma[no_of_cmds].base_addr, prev_entry); + + cmd->dma[no_of_cmds].offset += IPA_NAT_RULE_NEXT_FIELD_OFFSET; + } + + /* + Reset the previous entry of next_index field with 0 + */ + else if (IPA_NAT_DEL_TYPE_LAST == rule_pos) { + prev_entry = + Read16BitFieldValue(tbl_ptr[cur_tbl_entry].sw_spec_params, + SW_SPEC_PARAM_PREV_INDEX_FIELD); + + cmd->dma[no_of_cmds].table_index = tbl_indx; + cmd->dma[no_of_cmds].data = IPA_NAT_INVALID_NAT_ENTRY; + + cmd->dma[no_of_cmds].base_addr = IPA_NAT_BASE_TBL; + if (prev_entry >= cache_ptr->table_entries) { + cmd->dma[no_of_cmds].base_addr = IPA_NAT_EXPN_TBL; + prev_entry -= cache_ptr->table_entries; + } + + cmd->dma[no_of_cmds].offset = + ipa_nati_get_entry_offset(cache_ptr, + cmd->dma[no_of_cmds].base_addr, prev_entry); + + cmd->dma[no_of_cmds].offset += IPA_NAT_RULE_NEXT_FIELD_OFFSET; + } + + /* ================================================ + Base Table rule Deletion End + ================================================*/ + + /* ================================================ + Index Table rule Deletion + ================================================*/ + ipa_nati_find_index_rule_pos(cache_ptr, + indx_tbl_entry, + &indx_rule_pos); + IPADBG("Index table entry: 0x%x\n", indx_tbl_entry); + IPADBG("and position: %d\n", indx_rule_pos); + if (indx_tbl_entry >= cache_ptr->table_entries) { + indx_tbl_entry -= cache_ptr->table_entries; + indx_tbl_ptr = + (struct ipa_nat_indx_tbl_rule *)cache_ptr->index_table_expn_addr; + } else { + indx_tbl_ptr = + (struct ipa_nat_indx_tbl_rule *)cache_ptr->index_table_addr; + } + + /* Just delete the current rule by resetting nat_table_index field to 0 */ + if (IPA_NAT_DEL_TYPE_ONLY_ONE == indx_rule_pos) { + no_of_cmds++; + cmd->dma[no_of_cmds].base_addr = IPA_NAT_INDX_TBL; + cmd->dma[no_of_cmds].table_index = tbl_indx; + cmd->dma[no_of_cmds].data = IPA_NAT_INVALID_NAT_ENTRY; + + cmd->dma[no_of_cmds].offset = + ipa_nati_get_index_entry_offset(cache_ptr, + cmd->dma[no_of_cmds].base_addr, + indx_tbl_entry); + + cmd->dma[no_of_cmds].offset += + IPA_NAT_INDEX_RULE_NAT_INDEX_FIELD_OFFSET; + } + + /* copy the next entry values to current entry */ + else if (IPA_NAT_DEL_TYPE_HEAD == indx_rule_pos) { + next_entry = + Read16BitFieldValue(indx_tbl_ptr[indx_tbl_entry].tbl_entry_nxt_indx, + INDX_TBL_NEXT_INDEX_FILED); + + next_entry -= cache_ptr->table_entries; + + no_of_cmds++; + cmd->dma[no_of_cmds].base_addr = IPA_NAT_INDX_TBL; + cmd->dma[no_of_cmds].table_index = tbl_indx; + + /* Copy the nat_table_index field value of next entry */ + indx_tbl_ptr = + (struct ipa_nat_indx_tbl_rule *)cache_ptr->index_table_expn_addr; + cmd->dma[no_of_cmds].data = + Read16BitFieldValue(indx_tbl_ptr[next_entry].tbl_entry_nxt_indx, + INDX_TBL_TBL_ENTRY_FIELD); + + cmd->dma[no_of_cmds].offset = + ipa_nati_get_index_entry_offset(cache_ptr, + cmd->dma[no_of_cmds].base_addr, + indx_tbl_entry); + + cmd->dma[no_of_cmds].offset += + IPA_NAT_INDEX_RULE_NAT_INDEX_FIELD_OFFSET; + + /* Copy the next_index field value of next entry */ + no_of_cmds++; + cmd->dma[no_of_cmds].base_addr = IPA_NAT_INDX_TBL; + cmd->dma[no_of_cmds].table_index = tbl_indx; + cmd->dma[no_of_cmds].data = + Read16BitFieldValue(indx_tbl_ptr[next_entry].tbl_entry_nxt_indx, + INDX_TBL_NEXT_INDEX_FILED); + + cmd->dma[no_of_cmds].offset = + ipa_nati_get_index_entry_offset(cache_ptr, + cmd->dma[no_of_cmds].base_addr, indx_tbl_entry); + + cmd->dma[no_of_cmds].offset += + IPA_NAT_INDEX_RULE_NEXT_FIELD_OFFSET; + indx_next_entry = next_entry; + } + + /* + Update the previous entry of next_index field value + with current entry next_index field value + */ + else if (IPA_NAT_DEL_TYPE_MIDDLE == indx_rule_pos) { + prev_entry = cache_ptr->index_expn_table_meta[indx_tbl_entry].prev_index; + + no_of_cmds++; + cmd->dma[no_of_cmds].table_index = tbl_indx; + cmd->dma[no_of_cmds].data = + Read16BitFieldValue(indx_tbl_ptr[indx_tbl_entry].tbl_entry_nxt_indx, + INDX_TBL_NEXT_INDEX_FILED); + + cmd->dma[no_of_cmds].base_addr = IPA_NAT_INDX_TBL; + if (prev_entry >= cache_ptr->table_entries) { + cmd->dma[no_of_cmds].base_addr = IPA_NAT_INDEX_EXPN_TBL; + prev_entry -= cache_ptr->table_entries; + } + + IPADBG("prev_entry: %d update with cur next_index: %d\n", + prev_entry, cmd->dma[no_of_cmds].data); + IPADBG("prev_entry: %d exist in table_type:%d\n", + prev_entry, cmd->dma[no_of_cmds].base_addr); + + cmd->dma[no_of_cmds].offset = + ipa_nati_get_index_entry_offset(cache_ptr, + cmd->dma[no_of_cmds].base_addr, prev_entry); + + cmd->dma[no_of_cmds].offset += + IPA_NAT_INDEX_RULE_NEXT_FIELD_OFFSET; + } + + /* Reset the previous entry next_index field with 0 */ + else if (IPA_NAT_DEL_TYPE_LAST == indx_rule_pos) { + prev_entry = cache_ptr->index_expn_table_meta[indx_tbl_entry].prev_index; + + no_of_cmds++; + cmd->dma[no_of_cmds].table_index = tbl_indx; + cmd->dma[no_of_cmds].data = IPA_NAT_INVALID_NAT_ENTRY; + + cmd->dma[no_of_cmds].base_addr = IPA_NAT_INDX_TBL; + if (prev_entry >= cache_ptr->table_entries) { + cmd->dma[no_of_cmds].base_addr = IPA_NAT_INDEX_EXPN_TBL; + prev_entry -= cache_ptr->table_entries; + } + + IPADBG("Reseting prev_entry: %d next_index\n", prev_entry); + IPADBG("prev_entry: %d exist in table_type:%d\n", + prev_entry, cmd->dma[no_of_cmds].base_addr); + + cmd->dma[no_of_cmds].offset = + ipa_nati_get_index_entry_offset(cache_ptr, + cmd->dma[no_of_cmds].base_addr, prev_entry); + + cmd->dma[no_of_cmds].offset += + IPA_NAT_INDEX_RULE_NEXT_FIELD_OFFSET; + } + + /* ================================================ + Index Table rule Deletion End + ================================================*/ + cmd->entries = no_of_cmds + 1; + + if (cmd->entries > 1) { + ReorderCmds(cmd, size); + } + if (ioctl(ipv4_nat_cache.ipa_fd, IPA_IOC_NAT_DMA, cmd)) { + perror("ipa_nati_post_del_dma_cmd(): ioctl error value"); + IPAERR("unable to post cmd\n"); + IPADBG("ipa fd %d\n", ipv4_nat_cache.ipa_fd); + ret = -EIO; + goto fail; + } + + /* if entry exist in IPA_NAT_DEL_TYPE_MIDDLE of list + Update the previous entry in sw specific parameters + */ + if (IPA_NAT_DEL_TYPE_MIDDLE == rule_pos) { + /* Retrieve the current entry prev_entry value */ + prev_entry = + Read16BitFieldValue(tbl_ptr[cur_tbl_entry].sw_spec_params, + SW_SPEC_PARAM_PREV_INDEX_FIELD); + + /* Retrieve the next entry */ + next_entry = + Read16BitFieldValue(tbl_ptr[cur_tbl_entry].nxt_indx_pub_port, + NEXT_INDEX_FIELD); + + next_entry -= cache_ptr->table_entries; + tbl_ptr = (struct ipa_nat_rule *)cache_ptr->ipv4_expn_rules_addr; + + /* copy the current entry prev_entry value to next entry*/ + UpdateSwSpecParams(&tbl_ptr[next_entry], + IPA_NAT_SW_PARAM_PREV_INDX_BYTE, + prev_entry); + } + + /* Reset the other field values of current delete entry + In case of IPA_NAT_DEL_TYPE_HEAD, don't reset */ + if (IPA_NAT_DEL_TYPE_HEAD != rule_pos) { + memset(&tbl_ptr[cur_tbl_entry], 0, sizeof(struct ipa_nat_rule)); + } + + if (indx_rule_pos == IPA_NAT_DEL_TYPE_HEAD) { + + /* Update next next entry previous value to current + entry as we moved the next entry values + to current entry */ + indx_next_next_entry = + Read16BitFieldValue(indx_tbl_ptr[indx_next_entry].tbl_entry_nxt_indx, + INDX_TBL_NEXT_INDEX_FILED); + + if (indx_next_next_entry != 0 && + indx_next_next_entry >= cache_ptr->table_entries) { + + IPADBG("Next Next entry: %d\n", indx_next_next_entry); + indx_next_next_entry -= cache_ptr->table_entries; + + IPADBG("Updating entry: %d prev index to: %d\n", + indx_next_next_entry, indx_tbl_entry); + cache_ptr->index_expn_table_meta[indx_next_next_entry].prev_index = + indx_tbl_entry; + } + + /* Now reset the next entry as we copied + the next entry to current entry */ + IPADBG("Resetting, index table entry(Proper): %d\n", + (cache_ptr->table_entries + indx_next_entry)); + + /* This resets both table entry and next index values */ + indx_tbl_ptr[indx_next_entry].tbl_entry_nxt_indx = 0; + + /* + In case of IPA_NAT_DEL_TYPE_HEAD, update the sw specific parameters + (index table entry) of base table entry + */ + indx_tbl_ptr = + (struct ipa_nat_indx_tbl_rule *)cache_ptr->index_table_addr; + table_entry = + Read16BitFieldValue(indx_tbl_ptr[indx_tbl_entry].tbl_entry_nxt_indx, + INDX_TBL_TBL_ENTRY_FIELD); + + if (table_entry >= cache_ptr->table_entries) { + tbl_ptr = (struct ipa_nat_rule *)cache_ptr->ipv4_expn_rules_addr; + table_entry -= cache_ptr->table_entries; + } else { + tbl_ptr = (struct ipa_nat_rule *)cache_ptr->ipv4_rules_addr; + } + + UpdateSwSpecParams(&tbl_ptr[table_entry], + IPA_NAT_SW_PARAM_INDX_TBL_ENTRY_BYTE, + indx_tbl_entry); + } else { + /* Update the prev_entry value (in index_expn_table_meta) + for the next_entry in list with current entry prev_entry value + */ + if (IPA_NAT_DEL_TYPE_MIDDLE == indx_rule_pos) { + next_entry = + Read16BitFieldValue(indx_tbl_ptr[indx_tbl_entry].tbl_entry_nxt_indx, + INDX_TBL_NEXT_INDEX_FILED); + + if (next_entry >= cache_ptr->table_entries) { + next_entry -= cache_ptr->table_entries; + } + + cache_ptr->index_expn_table_meta[next_entry].prev_index = + cache_ptr->index_expn_table_meta[indx_tbl_entry].prev_index; + + cache_ptr->index_expn_table_meta[indx_tbl_entry].prev_index = + IPA_NAT_INVALID_NAT_ENTRY; + } + + IPADBG("At, indx_tbl_entry value: %d\n", indx_tbl_entry); + IPADBG("At, indx_tbl_entry member address: %p\n", + &indx_tbl_ptr[indx_tbl_entry].tbl_entry_nxt_indx); + + indx_tbl_ptr[indx_tbl_entry].tbl_entry_nxt_indx = 0; + + } + +fail: + free(cmd); + + return ret; +} + +void ipa_nati_find_index_rule_pos( + struct ipa_nat_ip4_table_cache *cache_ptr, + uint16_t tbl_entry, + del_type *rule_pos) +{ + struct ipa_nat_indx_tbl_rule *tbl_ptr; + + if (tbl_entry >= cache_ptr->table_entries) { + tbl_ptr = + (struct ipa_nat_indx_tbl_rule *)cache_ptr->index_table_expn_addr; + + tbl_entry -= cache_ptr->table_entries; + if (Read16BitFieldValue(tbl_ptr[tbl_entry].tbl_entry_nxt_indx, + INDX_TBL_NEXT_INDEX_FILED) == IPA_NAT_INVALID_NAT_ENTRY) { + *rule_pos = IPA_NAT_DEL_TYPE_LAST; + } else { + *rule_pos = IPA_NAT_DEL_TYPE_MIDDLE; + } + } else { + tbl_ptr = + (struct ipa_nat_indx_tbl_rule *)cache_ptr->index_table_addr; + + if (Read16BitFieldValue(tbl_ptr[tbl_entry].tbl_entry_nxt_indx, + INDX_TBL_NEXT_INDEX_FILED) == IPA_NAT_INVALID_NAT_ENTRY) { + *rule_pos = IPA_NAT_DEL_TYPE_ONLY_ONE; + } else { + *rule_pos = IPA_NAT_DEL_TYPE_HEAD; + } + } +} + +void ipa_nati_find_rule_pos(struct ipa_nat_ip4_table_cache *cache_ptr, + uint8_t expn_tbl, + uint16_t tbl_entry, + del_type *rule_pos) +{ + struct ipa_nat_rule *tbl_ptr; + + if (expn_tbl) { + tbl_ptr = (struct ipa_nat_rule *)cache_ptr->ipv4_expn_rules_addr; + if (Read16BitFieldValue(tbl_ptr[tbl_entry].nxt_indx_pub_port, + NEXT_INDEX_FIELD) == IPA_NAT_INVALID_NAT_ENTRY) { + *rule_pos = IPA_NAT_DEL_TYPE_LAST; + } else { + *rule_pos = IPA_NAT_DEL_TYPE_MIDDLE; + } + } else { + tbl_ptr = (struct ipa_nat_rule *)cache_ptr->ipv4_rules_addr; + if (Read16BitFieldValue(tbl_ptr[tbl_entry].nxt_indx_pub_port, + NEXT_INDEX_FIELD) == IPA_NAT_INVALID_NAT_ENTRY) { + *rule_pos = IPA_NAT_DEL_TYPE_ONLY_ONE; + } else { + *rule_pos = IPA_NAT_DEL_TYPE_HEAD; + } + } +} + +void ipa_nati_del_dead_ipv4_head_nodes(uint8_t tbl_indx) +{ + struct ipa_nat_rule *tbl_ptr; + uint16_t cnt; + + tbl_ptr = + (struct ipa_nat_rule *)ipv4_nat_cache.ip4_tbl[tbl_indx].ipv4_rules_addr; + + for (cnt = 0; + cnt < ipv4_nat_cache.ip4_tbl[tbl_indx].table_entries; + cnt++) { + + if (Read8BitFieldValue(tbl_ptr[cnt].ts_proto, + PROTOCOL_FIELD) == IPA_NAT_INVALID_PROTO_FIELD_CMP + && + Read16BitFieldValue(tbl_ptr[cnt].nxt_indx_pub_port, + NEXT_INDEX_FIELD) == IPA_NAT_INVALID_NAT_ENTRY) { + /* Delete the IPA_NAT_DEL_TYPE_HEAD node */ + IPADBG("deleting the dead node 0x%x\n", cnt); + memset(&tbl_ptr[cnt], 0, sizeof(struct ipa_nat_rule)); + } + } /* end of for loop */ + + return; +} + + +/* ======================================================== + Debug functions + ========================================================*/ +#ifdef NAT_DUMP +void ipa_nat_dump_ipv4_table(uint32_t tbl_hdl) +{ + struct ipa_nat_rule *tbl_ptr; + struct ipa_nat_indx_tbl_rule *indx_tbl_ptr; + int cnt; + uint8_t atl_one = 0; + + if (IPA_NAT_INVALID_NAT_ENTRY == tbl_hdl || + tbl_hdl > IPA_NAT_MAX_IP4_TBLS) { + IPAERR("invalid table handle passed\n"); + return; + } + + /* Print ipv4 rules */ + IPADBG("Dumping ipv4 active rules:\n"); + tbl_ptr = (struct ipa_nat_rule *) + ipv4_nat_cache.ip4_tbl[tbl_hdl-1].ipv4_rules_addr; + for (cnt = 0; + cnt < ipv4_nat_cache.ip4_tbl[tbl_hdl - 1].table_entries; + cnt++) { + if (Read16BitFieldValue(tbl_ptr[cnt].ip_cksm_enbl, + ENABLE_FIELD)) { + atl_one = 1; + ipa_nati_print_rule(&tbl_ptr[cnt], cnt); + } + } + if (!atl_one) { + IPADBG("No active base rules, total: %d\n", + ipv4_nat_cache.ip4_tbl[tbl_hdl - 1].table_entries); + } + atl_one = 0; + + /* Print ipv4 expansion rules */ + IPADBG("Dumping ipv4 active expansion rules:\n"); + tbl_ptr = (struct ipa_nat_rule *) + ipv4_nat_cache.ip4_tbl[tbl_hdl-1].ipv4_expn_rules_addr; + for (cnt = 0; + cnt <= ipv4_nat_cache.ip4_tbl[tbl_hdl - 1].expn_table_entries; + cnt++) { + if (Read16BitFieldValue(tbl_ptr[cnt].ip_cksm_enbl, + ENABLE_FIELD)) { + atl_one = 1; + ipa_nati_print_rule(&tbl_ptr[cnt], + (cnt + ipv4_nat_cache.ip4_tbl[tbl_hdl - 1].table_entries)); + } + } + if (!atl_one) { + IPADBG("No active base expansion rules, total: %d\n", + ipv4_nat_cache.ip4_tbl[tbl_hdl - 1].expn_table_entries); + } + atl_one = 0; + + /* Print ipv4 index rules */ + IPADBG("Dumping ipv4 index active rules:\n"); + indx_tbl_ptr = (struct ipa_nat_indx_tbl_rule *) + ipv4_nat_cache.ip4_tbl[tbl_hdl-1].index_table_addr; + for (cnt = 0; + cnt < ipv4_nat_cache.ip4_tbl[tbl_hdl - 1].table_entries; + cnt++) { + if (Read16BitFieldValue(indx_tbl_ptr[cnt].tbl_entry_nxt_indx, + INDX_TBL_TBL_ENTRY_FIELD)) { + atl_one = 1; + ipa_nati_print_index_rule(&indx_tbl_ptr[cnt], cnt, 0); + } + } + if (!atl_one) { + IPADBG("No active index table rules, total:%d\n", + ipv4_nat_cache.ip4_tbl[tbl_hdl - 1].table_entries); + } + atl_one = 0; + + + /* Print ipv4 index expansion rules */ + IPADBG("Dumping ipv4 index expansion active rules:\n"); + indx_tbl_ptr = (struct ipa_nat_indx_tbl_rule *) + ipv4_nat_cache.ip4_tbl[tbl_hdl-1].index_table_expn_addr; + for (cnt = 0; + cnt <= ipv4_nat_cache.ip4_tbl[tbl_hdl - 1].expn_table_entries; + cnt++) { + if (Read16BitFieldValue(indx_tbl_ptr[cnt].tbl_entry_nxt_indx, + INDX_TBL_TBL_ENTRY_FIELD)) { + atl_one = 1; + ipa_nati_print_index_rule(&indx_tbl_ptr[cnt], + (cnt + ipv4_nat_cache.ip4_tbl[tbl_hdl - 1].table_entries), + ipv4_nat_cache.ip4_tbl[tbl_hdl-1].index_expn_table_meta[cnt].prev_index); + } + } + if (!atl_one) { + IPADBG("No active index expansion rules, total:%d\n", + ipv4_nat_cache.ip4_tbl[tbl_hdl - 1].expn_table_entries); + } + atl_one = 0; + +} + +void ipa_nati_print_rule( + struct ipa_nat_rule *param, + uint32_t rule_id) +{ + struct ipa_nat_sw_rule sw_rule; + memcpy(&sw_rule, param, sizeof(sw_rule)); + uint32_t ip_addr; + + IPADUMP("rule-id:%d ", rule_id); + ip_addr = sw_rule.target_ip; + IPADUMP("Trgt-IP:%d.%d.%d.%d ", + ((ip_addr & 0xFF000000) >> 24), ((ip_addr & 0x00FF0000) >> 16), + ((ip_addr & 0x0000FF00) >> 8), ((ip_addr & 0x000000FF))); + + IPADUMP("Trgt-Port:%d Priv-Port:%d ", sw_rule.target_port, sw_rule.private_port); + + ip_addr = sw_rule.private_ip; + IPADUMP("Priv-IP:%d.%d.%d.%d ", + ((ip_addr & 0xFF000000) >> 24), ((ip_addr & 0x00FF0000) >> 16), + ((ip_addr & 0x0000FF00) >> 8), ((ip_addr & 0x000000FF))); + + IPADUMP("Pub-Port:%d Nxt-indx:%d ", sw_rule.public_port, sw_rule.next_index); + IPADUMP("IP-cksm-delta:0x%x En-bit:0x%x ", sw_rule.ip_chksum, sw_rule.enable); + IPADUMP("TS:0x%x Proto:0x%x ", sw_rule.time_stamp, sw_rule.protocol); + IPADUMP("Prv-indx:%d indx_tbl_entry:%d ", sw_rule.prev_index, sw_rule.indx_tbl_entry); + IPADUMP("Tcp-udp-cksum-delta:0x%x", sw_rule.tcp_udp_chksum); + IPADUMP("\n"); + return; +} + +void ipa_nati_print_index_rule( + struct ipa_nat_indx_tbl_rule *param, + uint32_t rule_id, uint16_t prev_indx) +{ + struct ipa_nat_sw_indx_tbl_rule sw_rule; + memcpy(&sw_rule, param, sizeof(sw_rule)); + + IPADUMP("rule-id:%d Table_entry:%d Next_index:%d, prev_indx:%d", + rule_id, sw_rule.tbl_entry, sw_rule.next_index, prev_indx); + IPADUMP("\n"); + return; +} + +int ipa_nati_query_nat_rules( + uint32_t tbl_hdl, + nat_table_type tbl_type) +{ + struct ipa_nat_rule *tbl_ptr; + struct ipa_nat_indx_tbl_rule *indx_tbl_ptr; + int cnt = 0, ret = 0; + + if (IPA_NAT_INVALID_NAT_ENTRY == tbl_hdl || + tbl_hdl > IPA_NAT_MAX_IP4_TBLS) { + IPAERR("invalid table handle passed\n"); + return ret; + } + + /* Print ipv4 rules */ + if (tbl_type == IPA_NAT_BASE_TBL) { + IPADBG("Counting ipv4 active rules:\n"); + tbl_ptr = (struct ipa_nat_rule *) + ipv4_nat_cache.ip4_tbl[tbl_hdl - 1].ipv4_rules_addr; + for (cnt = 0; + cnt < ipv4_nat_cache.ip4_tbl[tbl_hdl - 1].table_entries; + cnt++) { + if (Read16BitFieldValue(tbl_ptr[cnt].ip_cksm_enbl, + ENABLE_FIELD)) { + ret++; + } + } + if (!ret) { + IPADBG("No active base rules\n"); + } + + IPADBG("Number of active base rules: %d\n", ret); + } + + /* Print ipv4 expansion rules */ + if (tbl_type == IPA_NAT_EXPN_TBL) { + IPADBG("Counting ipv4 active expansion rules:\n"); + tbl_ptr = (struct ipa_nat_rule *) + ipv4_nat_cache.ip4_tbl[tbl_hdl - 1].ipv4_expn_rules_addr; + for (cnt = 0; + cnt < ipv4_nat_cache.ip4_tbl[tbl_hdl - 1].expn_table_entries; + cnt++) { + if (Read16BitFieldValue(tbl_ptr[cnt].ip_cksm_enbl, + ENABLE_FIELD)) { + ret++; + } + } + if (!ret) { + IPADBG("No active base expansion rules\n"); + } + + IPADBG("Number of active base expansion rules: %d\n", ret); + } + + /* Print ipv4 index rules */ + if (tbl_type == IPA_NAT_INDX_TBL) { + IPADBG("Counting ipv4 index active rules:\n"); + indx_tbl_ptr = (struct ipa_nat_indx_tbl_rule *) + ipv4_nat_cache.ip4_tbl[tbl_hdl - 1].index_table_addr; + for (cnt = 0; + cnt < ipv4_nat_cache.ip4_tbl[tbl_hdl - 1].table_entries; + cnt++) { + if (Read16BitFieldValue(indx_tbl_ptr[cnt].tbl_entry_nxt_indx, + INDX_TBL_TBL_ENTRY_FIELD)) { + ret++; + } + } + if (!ret) { + IPADBG("No active index table rules\n"); + } + + IPADBG("Number of active index table rules: %d\n", ret); + } + + /* Print ipv4 index expansion rules */ + if (tbl_type == IPA_NAT_INDEX_EXPN_TBL) { + IPADBG("Counting ipv4 index expansion active rules:\n"); + indx_tbl_ptr = (struct ipa_nat_indx_tbl_rule *) + ipv4_nat_cache.ip4_tbl[tbl_hdl - 1].index_table_expn_addr; + for (cnt = 0; + cnt < ipv4_nat_cache.ip4_tbl[tbl_hdl - 1].expn_table_entries; + cnt++) { + if (Read16BitFieldValue(indx_tbl_ptr[cnt].tbl_entry_nxt_indx, + INDX_TBL_TBL_ENTRY_FIELD)) { + ret++; + } + } + + if (!ret) + IPADBG("No active index expansion rules\n"); + + IPADBG("Number of active index expansion rules: %d\n", ret); + } + + return ret; +} +#endif diff --git a/data-ipa-cfg-mgr/ipanat/src/ipa_nat_logi.c b/data-ipa-cfg-mgr/ipanat/src/ipa_nat_logi.c new file mode 100644 index 000000000..b829b7844 --- /dev/null +++ b/data-ipa-cfg-mgr/ipanat/src/ipa_nat_logi.c @@ -0,0 +1,49 @@ +/* +Copyright (c) 2013, The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +/*! + @file + IPACM_log.cpp + + @brief + This file implements the IPAM log functionality. + + @Author + Skylar Chang + +*/ +#include "ipa_nat_logi.h" +#include +#include + +void log_nat_message(char *msg) +{ + return; +} + + diff --git a/data-ipa-cfg-mgr/ipanat/test/Android.mk b/data-ipa-cfg-mgr/ipanat/test/Android.mk new file mode 100644 index 000000000..4c94b5699 --- /dev/null +++ b/data-ipa-cfg-mgr/ipanat/test/Android.mk @@ -0,0 +1,53 @@ +BOARD_PLATFORM_LIST := msm8916 +BOARD_PLATFORM_LIST += msm8909 +ifneq ($(call is-board-platform-in-list,$(BOARD_PLATFORM_LIST)),true) +ifneq (,$(filter $(QCOM_BOARD_PLATFORMS),$(TARGET_BOARD_PLATFORM))) +ifneq (, $(filter aarch64 arm arm64, $(TARGET_ARCH))) + +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_C_INCLUDES := $(LOCAL_PATH)/ +LOCAL_C_INCLUDES += $(LOCAL_PATH)/../../ipanat/inc + +LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include +LOCAL_ADDITIONAL_DEPENDENCIES := $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr + +LOCAL_MODULE := ipa_nat_test +LOCAL_SRC_FILES := ipa_nat_test000.c \ + ipa_nat_test001.c \ + ipa_nat_test002.c \ + ipa_nat_test003.c \ + ipa_nat_test004.c \ + ipa_nat_test005.c \ + ipa_nat_test006.c \ + ipa_nat_test007.c \ + ipa_nat_test008.c \ + ipa_nat_test009.c \ + ipa_nat_test010.c \ + ipa_nat_test011.c \ + ipa_nat_test012.c \ + ipa_nat_test013.c \ + ipa_nat_test014.c \ + ipa_nat_test015.c \ + ipa_nat_test016.c \ + ipa_nat_test017.c \ + ipa_nat_test018.c \ + ipa_nat_test019.c \ + ipa_nat_test020.c \ + ipa_nat_test021.c \ + ipa_nat_test022.c \ + main.c + + +LOCAL_SHARED_LIBRARIES := libipanat + +LOCAL_MODULE_TAGS := debug +LOCAL_MODULE_PATH := $(TARGET_OUT_DATA)/kernel-tests/ip_accelerator + +include $(BUILD_EXECUTABLE) + +endif # $(TARGET_ARCH) +endif +endif \ No newline at end of file diff --git a/data-ipa-cfg-mgr/ipanat/test/Makefile.am b/data-ipa-cfg-mgr/ipanat/test/Makefile.am new file mode 100644 index 000000000..3aec070e2 --- /dev/null +++ b/data-ipa-cfg-mgr/ipanat/test/Makefile.am @@ -0,0 +1,42 @@ +AM_CPPFLAGS = -I./../inc \ + -I$(top_srcdir)/ipanat/inc + +AM_CPPFLAGS += -Wall -Wundef -Wno-trigraphs +AM_CPPFLAGS += -g + +ipanattest_SOURCES = ipa_nat_test000.c \ + ipa_nat_test001.c \ + ipa_nat_test002.c \ + ipa_nat_test003.c \ + ipa_nat_test004.c \ + ipa_nat_test005.c \ + ipa_nat_test006.c \ + ipa_nat_test007.c \ + ipa_nat_test008.c \ + ipa_nat_test009.c \ + ipa_nat_test010.c \ + ipa_nat_test011.c \ + ipa_nat_test012.c \ + ipa_nat_test013.c \ + ipa_nat_test014.c \ + ipa_nat_test015.c \ + ipa_nat_test016.c \ + ipa_nat_test017.c \ + ipa_nat_test018.c \ + ipa_nat_test019.c \ + ipa_nat_test020.c \ + ipa_nat_test021.c \ + ipa_nat_test022.c \ + main.c + + +bin_PROGRAMS = ipanattest + +requiredlibs = ../src/libipanat.la + +ipanattest_LDADD = $(requiredlibs) + +LOCAL_MODULE := libipanat +LOCAL_PRELINK_MODULE := false +include $(BUILD_SHARED_LIBRARY) + diff --git a/data-ipa-cfg-mgr/ipanat/test/README.txt b/data-ipa-cfg-mgr/ipanat/test/README.txt new file mode 100644 index 000000000..4e871216b --- /dev/null +++ b/data-ipa-cfg-mgr/ipanat/test/README.txt @@ -0,0 +1,18 @@ +1 To run this suite separately(each test case creates table and delete table) use below command + - To execute test suite nt times with n entries, command "ipanatest sep nt n" + + Example: To execute test suite 1 time with 100 entries, command "ipanattest sep 100" + + +2. To run test suite not separately(creates table and delete table only once) use below command + - To execute test suite nt times with n entries, command "ipanatest reg nt n" + + Example: To execute test suite 5 times with 32 entries, command "ipanattest reg 5 32" + + +3. To run inotify regression test use command, "ipanattest inotify nt" + + Example: To execute inotify 5 times, command "ipanattest inotify 5" + + +4. if we just give command "ipanattest", runs test suite 1 time with 100 entries (non separate) diff --git a/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test.h b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test.h new file mode 100644 index 000000000..d5ac0d52b --- /dev/null +++ b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test.h @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2014, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/*=========================================================================== + + INCLUDE FILES FOR MODULE + +===========================================================================*/ +#include "stdint.h" /* uint32_t */ +#include "stdio.h" +#include /* for proto definitions */ + +#define u32 uint32_t +#define u16 uint16_t +#define u8 uint8_t + +/*============ Preconditions to run NAT Test cases =========*/ +#define IPA_NAT_TEST_PRE_COND_TE 20 + +#define CHECK_ERR1(x, tbl_hdl) \ + if(ipa_nat_validate_ipv4_table(tbl_hdl)) { \ + if(sep) {\ + ipa_nat_del_ipv4_tbl(tbl_hdl); \ + }\ + return -1;\ + }\ + if(x) { \ + IPAERR("%d\n", ret); \ + if(sep) {\ + ipa_nat_del_ipv4_tbl(tbl_hdl); \ + }\ + return -1; \ + } + +#define CHECK_ERR(x) if(x) { \ + IPAERR("%d\n", ret); \ + return -1;\ + } + +#if 0 +#define CHECK_ERR(x) if(x) { \ + IPAERR("%d\n", ret); \ + if(sep) {\ + ipa_nat_del_ipv4_tbl(tbl_hdl); \ + }\ + return -1;\ + } +#endif + +#define IPADBG(fmt, args...) printf(" %s:%d " fmt, __FUNCTION__, __LINE__, ## args) +#define IPAERR(fmt, args...) printf(" %s:%d " fmt, __FUNCTION__, __LINE__, ## args) + +#define NAT_DUMP +int ipa_nat_validate_ipv4_table(u32); + +int ipa_nat_test000(int, u32, u8); +int ipa_nat_test001(int, u32, u8); +int ipa_nat_test002(int, u32, u8); +int ipa_nat_test003(int, u32, u8); +int ipa_nat_test004(int, u32, u8); +int ipa_nat_test005(int, u32, u8); +int ipa_nat_test006(int, u32, u8); +int ipa_nat_test007(int, u32, u8); +int ipa_nat_test008(int, u32, u8); +int ipa_nat_test009(int, u32, u8); +int ipa_nat_test010(int, u32, u8); +int ipa_nat_test011(int, u32, u8); +int ipa_nat_test012(int, u32, u8); +int ipa_nat_test013(int, u32, u8); +int ipa_nat_test014(int, u32, u8); +int ipa_nat_test015(int, u32, u8); +int ipa_nat_test016(int, u32, u8); +int ipa_nat_test017(int, u32, u8); +int ipa_nat_test018(int, u32, u8); +int ipa_nat_test019(int, u32, u8); +int ipa_nat_test020(int, u32, u8); +int ipa_nat_test021(int, int); +int ipa_nat_test022(int, u32, u8); diff --git a/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test000.c b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test000.c new file mode 100644 index 000000000..09914ea94 --- /dev/null +++ b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test000.c @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2014, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/*=========================================================================*/ +/*! + @file + ipa_nat_test000.c + + @brief + Verify the following scenario: + 1. Add ipv4 table + 2. Delete ipv4 table +*/ +/*===========================================================================*/ + +#include "ipa_nat_test.h" +#include "ipa_nat_drv.h" + +int ipa_nat_test000(int total_entries, u32 tbl_hdl, u8 sep) +{ + + int ret; + u32 pub_ip_add = 0x011617c0; /* "192.23.22.1" */ + + ret = ipa_nat_add_ipv4_tbl(pub_ip_add, total_entries, &tbl_hdl); + if (0 != ret) + { + IPAERR("unable to create ipv4 nat table and returning Error:%d\n", ret); + return -1; + } + IPADBG("create nat ipv4 table successfully() \n"); + + IPADBG("calling ipa_nat_del_ipv4_tbl() \n"); + ret = ipa_nat_del_ipv4_tbl(tbl_hdl); + if (0 != ret) + { + IPAERR("Unable to delete ipv4 nat table %d\n", ret); + return -1; + } + IPADBG("deleted ipv4 nat table successfully. Test passed \n"); + + return 0; +} diff --git a/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test001.c b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test001.c new file mode 100644 index 000000000..8daef331e --- /dev/null +++ b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test001.c @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2014, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/*=========================================================================*/ +/*! + @file + ipa_nat_test001.c + + @brief + Verify the following scenario: + 1. Add ipv4 table + 2. Add ipv4 rule + 3. Delete ipv4 table +*/ +/*===========================================================================*/ + +#include "ipa_nat_test.h" +#include "ipa_nat_drv.h" + +int ipa_nat_test001(int total_entries, u32 tbl_hdl, u8 sep) +{ + int ret; + u32 rule_hdl; + ipa_nat_ipv4_rule ipv4_rule; + + u32 pub_ip_add = 0x011617c0; /* "192.23.22.1" */ + ipv4_rule.target_ip = 0xC1171601; /* 193.23.22.1 */ + ipv4_rule.target_port = 1234; + + ipv4_rule.private_ip = 0xC2171601; /* 194.23.22.1 */ + ipv4_rule.private_port = 5678; + + ipv4_rule.protocol = IPPROTO_TCP; + ipv4_rule.public_port = 9050; + + IPADBG("%s()\n",__FUNCTION__); + + if(sep) + { + ret = ipa_nat_add_ipv4_tbl(pub_ip_add, total_entries, &tbl_hdl); + CHECK_ERR(ret); + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule, &rule_hdl); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_tbl(tbl_hdl); + CHECK_ERR(ret); + } + + return 0; +} diff --git a/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test002.c b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test002.c new file mode 100644 index 000000000..e6f5ae37f --- /dev/null +++ b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test002.c @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2014, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/*=========================================================================*/ +/*! + @file + ipa_nat_test002.c + + @brief + Verify the following scenario: + 1. Add ipv4 table + 2. Add ipv4 rule + 3. delete ipv4 rule + 4. Delete ipv4 table +*/ +/*=========================================================================*/ + +#include "ipa_nat_test.h" +#include "ipa_nat_drv.h" + +int ipa_nat_test002(int total_entries, u32 tbl_hdl, u8 sep) +{ + int ret; + u32 rule_hdl; + ipa_nat_ipv4_rule ipv4_rule; + + u32 pub_ip_add = 0x011617c0; /* "192.23.22.1" */ + + ipv4_rule.target_ip = 0xC1171601; /* 193.23.22.1 */ + ipv4_rule.target_port = 1234; + + ipv4_rule.private_ip = 0xC2171601; /* 194.23.22.1 */ + ipv4_rule.private_port = 5678; + + ipv4_rule.protocol = IPPROTO_TCP; + ipv4_rule.public_port = 9050; + + IPADBG("%s()\n",__FUNCTION__); + + if(sep) + { + ret = ipa_nat_add_ipv4_tbl(pub_ip_add, total_entries, &tbl_hdl); + CHECK_ERR(ret); + } + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule, &rule_hdl); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl); + CHECK_ERR(ret); + + if(sep) + { + ret = ipa_nat_del_ipv4_tbl(tbl_hdl); + CHECK_ERR(ret); + } + + return 0; +} diff --git a/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test003.c b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test003.c new file mode 100644 index 000000000..0634265ec --- /dev/null +++ b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test003.c @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2014, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +/*=========================================================================*/ +/*! + @file + IPA_NAT_ipa_nat_test003.cpp + + @brief + Verify the following scenario: + 1. Add ipv4 table + 2. Add ipv4 rule + 3. Add ipv4 rule + 4. Delete ipv4 table +*/ +/*=========================================================================*/ + +#include "ipa_nat_test.h" +#include "ipa_nat_drv.h" + +int ipa_nat_test003(int total_entries, u32 tbl_hdl, u8 sep) +{ + int ret; + u32 rule_hdl, rule_hdl1; + ipa_nat_ipv4_rule ipv4_rule; + u32 pub_ip_add = 0x011617c0; /* "192.23.22.1" */ + + ipv4_rule.target_ip = 0xC1171601; /* 193.23.22.1 */ + ipv4_rule.target_port = 1234; + + ipv4_rule.private_ip = 0xC2171601; /* 194.23.22.1 */ + ipv4_rule.private_port = 5678; + + ipv4_rule.protocol = IPPROTO_TCP; + ipv4_rule.public_port = 9050; + + IPADBG("%s():\n",__FUNCTION__); + + if(sep) + { + ret = ipa_nat_add_ipv4_tbl(pub_ip_add, total_entries, &tbl_hdl); + CHECK_ERR(ret); + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule, &rule_hdl); + CHECK_ERR(ret); + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule, &rule_hdl1); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_tbl(tbl_hdl); + CHECK_ERR(ret); + } + + return 0; +} diff --git a/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test004.c b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test004.c new file mode 100644 index 000000000..02378ff27 --- /dev/null +++ b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test004.c @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2014, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/*=========================================================================*/ +/*! + @file + ipa_nat_test004.cpp + + @brief + Verify the following scenario: + 1. Add ipv4 table + 2. Query nat table handle + 3. Delete ipv4 table +*/ +/*===========================================================================*/ + +#include "ipa_nat_test.h" +#include "ipa_nat_drv.h" + +int ipa_nat_test004(int total_entries, u32 tbl_hdl, u8 sep) +{ + int ret = 0; + u32 tbl_hdl1 = 0; + u32 pub_ip_add = 0x011617c0; /* "192.23.22.1" */ + + IPADBG("%s():\n",__FUNCTION__); + + if(sep) + { + ret = ipa_nat_add_ipv4_tbl(pub_ip_add, total_entries, &tbl_hdl); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_tbl(tbl_hdl); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_tbl(tbl_hdl1); + if(ret == 0) + { + IPAERR("able to delete table using invalid table handle\n"); + return -1; + } + } + return 0; +} diff --git a/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test005.c b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test005.c new file mode 100644 index 000000000..12228d154 --- /dev/null +++ b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test005.c @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2014, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/*=========================================================================*/ +/*! + @file + ipa_nat_test005.c + + @brief + Verify the following scenario: + 1. Add ipv4 table + 2. Add ipv4 rule + 3. Delete ipv4 rule + 4. Add ipv4 rule + 5. Delete ipv4 table +*/ +/*=========================================================================*/ + +#include "ipa_nat_test.h" +#include "ipa_nat_drv.h" + +int ipa_nat_test005(int total_entries, u32 tbl_hdl, u8 sep) +{ + int ret = 0; + u32 rule_hdl, rule_hdl1; + ipa_nat_ipv4_rule ipv4_rule; + u32 pub_ip_add = 0x011617c0; /* "192.23.22.1" */ + + ipv4_rule.target_ip = 0xC1171601; /* 193.23.22.1 */ + ipv4_rule.target_port = 1234; + + ipv4_rule.private_ip = 0xC2171601; /* 194.23.22.1 */ + ipv4_rule.private_port = 5678; + + ipv4_rule.protocol = IPPROTO_TCP; + ipv4_rule.public_port = 9050; + + if (sep) + { + ret = ipa_nat_add_ipv4_tbl(pub_ip_add, total_entries, &tbl_hdl); + CHECK_ERR(ret); + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule, &rule_hdl); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl); + CHECK_ERR(ret); + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule, &rule_hdl1); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_tbl(tbl_hdl); + CHECK_ERR(ret); + } + + return 0; +} diff --git a/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test006.c b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test006.c new file mode 100644 index 000000000..36f0171d1 --- /dev/null +++ b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test006.c @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2014, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/*=========================================================================*/ +/*! + @file + ipa_nat_test006.c + + @brief + Verify the following scenario: + 1. Add ipv4 table + 2. add same ipv rules + 3. delete first followed by second + 4. Delete ipv4 table +*/ +/*=========================================================================*/ + +#include "ipa_nat_test.h" +#include "ipa_nat_drv.h" + +int ipa_nat_test006(int total_entries, u32 tbl_hdl, u8 sep) +{ + int ret=0; + u32 rule_hdl, rule_hdl1; + ipa_nat_ipv4_rule ipv4_rule; + + u32 pub_ip_add = 0x011617c0; /* "192.23.22.1" */ + + ipv4_rule.target_ip = 0xC1171601; /* 193.23.22.1 */ + ipv4_rule.target_port = 1234; + + ipv4_rule.private_ip = 0xC2171601; /* 194.23.22.1 */ + ipv4_rule.private_port = 5678; + + ipv4_rule.protocol = IPPROTO_TCP; + ipv4_rule.public_port = 9050; + + IPADBG("%s():\n",__FUNCTION__); + + if(sep) + { + ret = ipa_nat_add_ipv4_tbl(pub_ip_add, total_entries, &tbl_hdl); + CHECK_ERR(ret); + } + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule, &rule_hdl); + CHECK_ERR(ret); + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule, &rule_hdl1); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl1); + CHECK_ERR(ret); + + if(sep) + { + ret = ipa_nat_del_ipv4_tbl(tbl_hdl); + CHECK_ERR(ret); + } + + return 0; +} diff --git a/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test007.c b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test007.c new file mode 100644 index 000000000..4160c028e --- /dev/null +++ b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test007.c @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2014, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/*=========================================================================*/ +/*! + @file + ipa_nat_test007.cpp + + @brief + Verify the following scenario: + 1. Add ipv4 table + 2. add same ipv rules + 3. delete second followed by first + 4. Delete ipv4 table +*/ +/*=========================================================================*/ + +#include "ipa_nat_test.h" +#include "ipa_nat_drv.h" + +int ipa_nat_test007(int total_entries, u32 tbl_hdl, u8 sep) +{ + int ret; + u32 rule_hdl, rule_hdl1; + ipa_nat_ipv4_rule ipv4_rule; + + u32 pub_ip_add = 0x011617c0; /* "192.23.22.1" */ + + ipv4_rule.target_ip = 0xC1171601; /* 193.23.22.1 */ + ipv4_rule.target_port = 1234; + ipv4_rule.private_ip = 0xC2171601; /* 194.23.22.1 */ + ipv4_rule.private_port = 5678; + ipv4_rule.protocol = IPPROTO_TCP; + ipv4_rule.public_port = 9050; + + IPADBG("%s():\n",__FUNCTION__); + + if(sep) + { + ret = ipa_nat_add_ipv4_tbl(pub_ip_add, total_entries, &tbl_hdl); + CHECK_ERR(ret); + } + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule, &rule_hdl); + CHECK_ERR(ret); + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule, &rule_hdl1); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl1); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl); + CHECK_ERR(ret); + + if(sep) + { + ret = ipa_nat_del_ipv4_tbl(tbl_hdl); + CHECK_ERR(ret); + } + return 0; +} diff --git a/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test008.c b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test008.c new file mode 100644 index 000000000..d016055b7 --- /dev/null +++ b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test008.c @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2014, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/*=========================================================================*/ +/*! + @file + ipa_nat_test008.c + + @brief + Verify the following scenario: + 1. Add ipv4 table + 2. add 2 distinct rules + 3. delete first followed by second + 4. Delete ipv4 table +*/ +/*=========================================================================*/ + +#include "ipa_nat_test.h" +#include "ipa_nat_drv.h" + +int ipa_nat_test008(int total_entries, u32 tbl_hdl, u8 sep) +{ + int ret; + u32 rule_hdl, rule_hdl1; + ipa_nat_ipv4_rule ipv4_rule, ipv4_rule1; + + u32 pub_ip_add = 0x011617c0; /* "192.23.22.1" */ + + ipv4_rule.target_ip = 0xC1171601; /* 193.23.22.1 */ + ipv4_rule.target_port = 1234; + ipv4_rule.private_ip = 0xC2171601; /* 194.23.22.1 */ + ipv4_rule.private_port = 5678; + ipv4_rule.protocol = IPPROTO_TCP; + ipv4_rule.public_port = 9050; + ipv4_rule1.target_ip = 0xC1171602; /* 193.23.22.2 */ + ipv4_rule1.target_port = 1234; + ipv4_rule1.private_ip = 0xC2171602; /* 194.23.22.2 */ + ipv4_rule1.private_port = 5678; + ipv4_rule1.protocol = IPPROTO_TCP; + ipv4_rule1.public_port = 9050; + + IPADBG("%s():\n",__FUNCTION__); + + if(sep) + { + ret = ipa_nat_add_ipv4_tbl(pub_ip_add, total_entries, &tbl_hdl); + CHECK_ERR(ret); + } + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule, &rule_hdl); + CHECK_ERR(ret); + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule1, &rule_hdl1); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl1); + CHECK_ERR(ret); + + if(sep) + { + ret = ipa_nat_del_ipv4_tbl(tbl_hdl); + CHECK_ERR(ret); + } + return 0; +} diff --git a/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test009.c b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test009.c new file mode 100644 index 000000000..cf3c40f28 --- /dev/null +++ b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test009.c @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2014, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/*=========================================================================*/ +/*! + @file + ipa_nat_test009.cpp + + @brief + Verify the following scenario: + 1. Add ipv4 table + 2. add 2 distinct rules + 3. delete second followed by first + 4. Delete ipv4 table +*/ +/*=========================================================================*/ + +#include "ipa_nat_test.h" +#include "ipa_nat_drv.h" + +int ipa_nat_test009(int total_entries, u32 tbl_hdl, u8 sep) +{ + int ret; + u32 rule_hdl, rule_hdl1; + ipa_nat_ipv4_rule ipv4_rule, ipv4_rule1; + + u32 pub_ip_add = 0x011617c0; /* "192.23.22.1" */ + + ipv4_rule.target_ip = 0xC1171601; /* 193.23.22.1 */ + ipv4_rule.target_port = 1234; + ipv4_rule.private_ip = 0xC2171601; /* 194.23.22.1 */ + ipv4_rule.private_port = 5678; + ipv4_rule.protocol = IPPROTO_TCP; + ipv4_rule.public_port = 9050; + + ipv4_rule1.target_ip = 0xC1171602; /* 193.23.22.2 */ + ipv4_rule1.target_port = 1234; + ipv4_rule1.private_ip = 0xC2171602; /* 194.23.22.2 */ + ipv4_rule1.private_port = 5678; + ipv4_rule1.protocol = IPPROTO_TCP; + ipv4_rule1.public_port = 9050; + + IPADBG("%s():\n",__FUNCTION__); + + if(sep) + { + ret = ipa_nat_add_ipv4_tbl(pub_ip_add, total_entries, &tbl_hdl); + CHECK_ERR(ret); + } + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule, &rule_hdl); + CHECK_ERR(ret); + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule1, &rule_hdl1); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl1); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl); + CHECK_ERR(ret); + + if(sep) + { + ret = ipa_nat_del_ipv4_tbl(tbl_hdl); + CHECK_ERR(ret); + } + + return 0; +} diff --git a/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test010.c b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test010.c new file mode 100644 index 000000000..42d7fee17 --- /dev/null +++ b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test010.c @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2014, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/*=========================================================================*/ +/*! + @file + ipa_nat_test010.c + + @brief + Verify the following scenario: + 1. Add ipv4 table + 2. add 3 distinct ipv4 rules + 3. delete first, second followed by last + 4. Delete ipv4 table +*/ +/*=========================================================================*/ + +#include "ipa_nat_test.h" +#include "ipa_nat_drv.h" + +int ipa_nat_test010(int total_entries, u32 tbl_hdl, u8 sep) +{ + int ret; + u32 rule_hdl, rule_hdl1, rule_hdl2; + ipa_nat_ipv4_rule ipv4_rule, ipv4_rule1, ipv4_rule2; + + u32 pub_ip_add = 0x011617c0; /* "192.23.22.1" */ + + ipv4_rule.target_ip = 0xC1171601; /* 193.23.22.1 */ + ipv4_rule.target_port = 1234; + ipv4_rule.private_ip = 0xC2171601; /* 194.23.22.1 */ + ipv4_rule.private_port = 5678; + ipv4_rule.protocol = IPPROTO_TCP; + ipv4_rule.public_port = 9050; + + ipv4_rule1.target_ip = 0xC1171601; /* 193.23.22.1 */ + ipv4_rule1.target_port = 1235; + ipv4_rule1.private_ip = 0xC2171601; /* 194.23.22.1 */ + ipv4_rule1.private_port = 5679; + ipv4_rule1.protocol = IPPROTO_TCP; + ipv4_rule1.public_port = 9051; + + ipv4_rule2.target_ip = 0xC1171602; /* 193.23.22.2 */ + ipv4_rule2.target_port = 1235; + ipv4_rule2.private_ip = 0xC2171602; /* 194.23.22.2 */ + ipv4_rule2.private_port = 5679; + ipv4_rule2.protocol = IPPROTO_TCP; + ipv4_rule2.public_port = 9051; + + IPADBG("%s():\n",__FUNCTION__); + if(sep) + { + ret = ipa_nat_add_ipv4_tbl(pub_ip_add, total_entries, &tbl_hdl); + CHECK_ERR(ret); + } + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule, &rule_hdl); + CHECK_ERR(ret); + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule1, &rule_hdl1); + CHECK_ERR(ret); + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule2, &rule_hdl2); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl1); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl2); + CHECK_ERR(ret); + + if(sep) + { + ret = ipa_nat_del_ipv4_tbl(tbl_hdl); + CHECK_ERR(ret); + } + + return 0; +} diff --git a/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test011.c b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test011.c new file mode 100644 index 000000000..bcce76c5f --- /dev/null +++ b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test011.c @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2014, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/*=========================================================================*/ +/*! + @file + ipa_nat_test011.cpp + + @brief + Verify the following scenario: + 1. Add ipv4 table + 2. add 3 distinct ipv4 rules + 3. delete second, first followed by last + 4. Delete ipv4 table +*/ +/*=========================================================================*/ + +#include "ipa_nat_test.h" +#include "ipa_nat_drv.h" + +int ipa_nat_test011(int total_entries, u32 tbl_hdl, u8 sep) +{ + int ret; + u32 rule_hdl, rule_hdl1, rule_hdl2; + ipa_nat_ipv4_rule ipv4_rule, ipv4_rule1, ipv4_rule2; + u32 pub_ip_add = 0x011617c0; /* "192.23.22.1" */ + + ipv4_rule.target_ip = 0xC1171601; /* 193.23.22.1 */ + ipv4_rule.target_port = 1234; + ipv4_rule.private_ip = 0xC2171601; /* 194.23.22.1 */ + ipv4_rule.private_port = 5678; + ipv4_rule.protocol = IPPROTO_TCP; + ipv4_rule.public_port = 9050; + + ipv4_rule1.target_ip = 0xF1181601; + ipv4_rule1.target_port = 1555; + ipv4_rule1.private_ip = 0xF2151601; + ipv4_rule1.private_port = 5999; + ipv4_rule1.protocol = IPPROTO_TCP; + ipv4_rule1.public_port = 9111; + + ipv4_rule2.target_ip = 0xC1166602; + ipv4_rule2.target_port = 1555; + ipv4_rule2.private_ip = 0xC2155602; + ipv4_rule2.private_port = 5777; + ipv4_rule2.protocol = IPPROTO_TCP; + ipv4_rule2.public_port = 9000; + + IPADBG("%s():\n",__FUNCTION__); + + if(sep) + { + ret = ipa_nat_add_ipv4_tbl(pub_ip_add, total_entries, &tbl_hdl); + CHECK_ERR(ret); + } + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule, &rule_hdl); + CHECK_ERR(ret); + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule1, &rule_hdl1); + CHECK_ERR(ret); + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule2, &rule_hdl2); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl1); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl2); + CHECK_ERR(ret); + + if(sep) + { + ret = ipa_nat_del_ipv4_tbl(tbl_hdl); + CHECK_ERR(ret); + } + + return 0; +} diff --git a/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test012.c b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test012.c new file mode 100644 index 000000000..9d3c8357c --- /dev/null +++ b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test012.c @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2014, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/*=========================================================================*/ +/*! + @file + ipa_nat_test012.cpp + + @brief + Verify the following scenario: + 1. Add ipv4 table + 2. add 3 distinct ipv4 rules + 3. Delete third, second, first + 4. Delete ipv4 table +*/ +/*=========================================================================*/ + +#include "ipa_nat_test.h" +#include "ipa_nat_drv.h" + + +int ipa_nat_test012(int totoal_entries, u32 tbl_hdl, u8 sep) +{ + int ret; + u32 rule_hdl, rule_hdl1, rule_hdl2; + ipa_nat_ipv4_rule ipv4_rule, ipv4_rule1, ipv4_rule2; + u32 pub_ip_add = 0x011617c0; /* "192.23.22.1" */ + + ipv4_rule.target_ip = 0xC1171601; /* 193.23.22.1 */ + ipv4_rule.target_port = 1234; + ipv4_rule.private_ip = 0xC2171601; /* 194.23.22.1 */ + ipv4_rule.private_port = 5678; + ipv4_rule.protocol = IPPROTO_TCP; + ipv4_rule.public_port = 9050; + + ipv4_rule1.target_ip = 0xD1171601; + ipv4_rule1.target_port = 3512; + ipv4_rule1.private_ip = 0xD2471601; + ipv4_rule1.private_port = 9997; + ipv4_rule1.protocol = IPPROTO_TCP; + ipv4_rule1.public_port = 8881; + + ipv4_rule2.target_ip = 0xC1172452; + ipv4_rule2.target_port = 1895; + ipv4_rule2.private_ip = 0xC2172452; + ipv4_rule2.private_port = 6668; + ipv4_rule2.protocol = IPPROTO_TCP; + ipv4_rule2.public_port = 5551; + + IPADBG("%s():\n",__FUNCTION__); + + if(sep) + { + ret = ipa_nat_add_ipv4_tbl(pub_ip_add, totoal_entries, &tbl_hdl); + CHECK_ERR(ret); + } + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule, &rule_hdl); + CHECK_ERR(ret); + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule1, &rule_hdl1); + CHECK_ERR(ret); + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule2, &rule_hdl2); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl2); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl1); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl); + CHECK_ERR(ret); + + if(sep) + { + ret = ipa_nat_del_ipv4_tbl(tbl_hdl); + CHECK_ERR(ret); + } + + return 0; +} diff --git a/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test013.c b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test013.c new file mode 100644 index 000000000..2b9b005de --- /dev/null +++ b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test013.c @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2014, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/*=========================================================================*/ +/*! + @file + ipa_nat_test013.cpp + + @brief + Verify the following scenario: + 1. Add ipv4 table + 2. add 3 distinct ipv4 rules + 3. Delete third, first and second + 4. Delete ipv4 table +*/ +/*=========================================================================*/ + +#include "ipa_nat_test.h" +#include "ipa_nat_drv.h" + +int ipa_nat_test013(int total_entries, u32 tbl_hdl, u8 sep) +{ + int ret; + u32 rule_hdl, rule_hdl1, rule_hdl2; + ipa_nat_ipv4_rule ipv4_rule, ipv4_rule1, ipv4_rule2; + u32 pub_ip_add = 0x011617c0; /* "192.23.22.1" */ + + ipv4_rule.target_ip = 0xC1171601; /* 193.23.22.1 */ + ipv4_rule.target_port = 1234; + ipv4_rule.private_ip = 0xC2171601; /* 194.23.22.1 */ + ipv4_rule.private_port = 5678; + ipv4_rule.protocol = IPPROTO_TCP; + ipv4_rule.public_port = 9050; + + ipv4_rule1.target_ip = 0xC1171609; /* 193.23.22.9 */ + ipv4_rule1.target_port = 1235; + ipv4_rule1.private_ip = 0xC2171609; /* 194.23.22.9 */ + ipv4_rule1.private_port = 6579; + ipv4_rule1.protocol = IPPROTO_TCP; + ipv4_rule1.public_port = 8951; + + ipv4_rule2.target_ip = 0xC1171606; /* 193.23.22.6 */ + ipv4_rule2.target_port = 1235; + ipv4_rule2.private_ip = 0xC2171606; /* 194.23.22.6 */ + ipv4_rule2.private_port = 7956; + ipv4_rule2.protocol = IPPROTO_TCP; + ipv4_rule2.public_port = 5109; + + IPADBG("%s():\n",__FUNCTION__); + + if(sep) + { + ret = ipa_nat_add_ipv4_tbl(pub_ip_add, total_entries, &tbl_hdl); + CHECK_ERR(ret); + } + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule, &rule_hdl); + CHECK_ERR(ret); + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule1, &rule_hdl1); + CHECK_ERR(ret); + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule2, &rule_hdl2); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl2); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl1); + CHECK_ERR(ret); + + if(sep) + { + ret = ipa_nat_del_ipv4_tbl(tbl_hdl); + CHECK_ERR(ret); + } + + return 0; +} diff --git a/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test014.c b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test014.c new file mode 100644 index 000000000..fd303171d --- /dev/null +++ b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test014.c @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2014, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +/*=========================================================================*/ +/*! + @file + ipa_nat_test014.cpp + @brief + Verify the following scenario: + 1. Add ipv4 table + 2. add same 3 ipv rules + 3. delete first, second and third + 4. Delete ipv4 table +*/ +/*=========================================================================*/ + +#include "ipa_nat_test.h" +#include "ipa_nat_drv.h" + +int ipa_nat_test014(int total_entries, u32 tbl_hdl, u8 sep) +{ + int ret; + u32 rule_hdl1, rule_hdl2, rule_hdl3; + ipa_nat_ipv4_rule ipv4_rule; + + u32 pub_ip_add = 0x011617c0; /* "192.23.22.1" */ + + ipv4_rule.target_ip = 0xC1171601; /* 193.23.22.1 */ + ipv4_rule.target_port = 1234; + ipv4_rule.private_ip = 0xC2171601; /* 194.23.22.1 */ + ipv4_rule.private_port = 5678; + ipv4_rule.protocol = IPPROTO_TCP; + ipv4_rule.public_port = 9050; + + IPADBG("%s()\n", __FUNCTION__); + + if(sep) + { + ret = ipa_nat_add_ipv4_tbl(pub_ip_add, total_entries, &tbl_hdl); + CHECK_ERR(ret); + } + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule, &rule_hdl1); + CHECK_ERR(ret); + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule, &rule_hdl2); + CHECK_ERR(ret); + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule, &rule_hdl3); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl1); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl2); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl3); + CHECK_ERR(ret); + + if(sep) + { + ret = ipa_nat_del_ipv4_tbl(tbl_hdl); + CHECK_ERR(ret); + } + + return 0; +} diff --git a/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test015.c b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test015.c new file mode 100644 index 000000000..eaef92364 --- /dev/null +++ b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test015.c @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2014, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +/*=========================================================================*/ +/*! + @file + ipa_nat_test015.cpp + + @brief + Verify the following scenario: + 1. Add ipv4 table + 2. add same 3 ipv rules + 3. delete first, third and second + 4. Delete ipv4 table +*/ +/*=========================================================================*/ + +#include "ipa_nat_test.h" +#include "ipa_nat_drv.h" + + +int ipa_nat_test015(int total_entries, u32 tbl_hdl, u8 sep) +{ + int ret; + u32 rule_hdl1, rule_hdl2, rule_hdl3; + ipa_nat_ipv4_rule ipv4_rule; + + u32 pub_ip_add = 0x011617c0; /* "192.23.22.1" */ + + ipv4_rule.target_ip = 0xC1171601; /* 193.23.22.1 */ + ipv4_rule.target_port = 1234; + + ipv4_rule.private_ip = 0xC2171601; /* 194.23.22.1 */ + ipv4_rule.private_port = 5678; + ipv4_rule.protocol = IPPROTO_TCP; + ipv4_rule.public_port = 9050; + + IPADBG("%s():\n",__FUNCTION__); + + if(sep) + { + ret = ipa_nat_add_ipv4_tbl(pub_ip_add, total_entries, &tbl_hdl); + CHECK_ERR(ret); + } + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule, &rule_hdl1); + CHECK_ERR(ret); + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule, &rule_hdl2); + CHECK_ERR(ret); + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule, &rule_hdl3); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl1); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl3); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl2); + CHECK_ERR(ret); + if(sep) + { + ret = ipa_nat_del_ipv4_tbl(tbl_hdl); + CHECK_ERR(ret); + } + + return 0; +} diff --git a/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test016.c b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test016.c new file mode 100644 index 000000000..23157e230 --- /dev/null +++ b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test016.c @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2014, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +/*=========================================================================*/ +/*! + @file + ipa_nat_test016.cpp + + @brief + Verify the following scenario: + 1. Add ipv4 table + 2. add same 3 ipv rules + 3. delete second, first and third + 4. Delete ipv4 table +*/ +/*=========================================================================*/ + +#include "ipa_nat_test.h" +#include "ipa_nat_drv.h" + +int ipa_nat_test016(int total_entries, u32 tbl_hdl, u8 sep) +{ + int ret; + u32 rule_hdl1, rule_hdl2, rule_hdl3; + ipa_nat_ipv4_rule ipv4_rule; + + u32 pub_ip_add = 0x011617c0; /* "192.23.22.1" */ + + ipv4_rule.target_ip = 0xC1171601; /* 193.23.22.1 */ + ipv4_rule.target_port = 1234; + ipv4_rule.private_ip = 0xC2171601; /* 194.23.22.1 */ + ipv4_rule.private_port = 5678; + ipv4_rule.protocol = IPPROTO_TCP; + ipv4_rule.public_port = 9050; + + IPADBG("%s():\n",__FUNCTION__); + + if(sep) + { + ret = ipa_nat_add_ipv4_tbl(pub_ip_add, total_entries, &tbl_hdl); + CHECK_ERR(ret); + } + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule, &rule_hdl1); + CHECK_ERR(ret); + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule, &rule_hdl2); + CHECK_ERR(ret); + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule, &rule_hdl3); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl2); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl1); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl3); + CHECK_ERR(ret); + + if(sep) + { + ret = ipa_nat_del_ipv4_tbl(tbl_hdl); + CHECK_ERR(ret); + } + + return 0; +} diff --git a/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test017.c b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test017.c new file mode 100644 index 000000000..d88e61137 --- /dev/null +++ b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test017.c @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2014, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +/*=========================================================================*/ +/*! + @file + ipa_nat_test017.cpp + + @brief + Verify the following scenario: + 1. Add ipv4 table + 2. add same 3 ipv rules + 3. delete second, third and first + 4. Delete ipv4 table +*/ +/*=========================================================================*/ + +#include "ipa_nat_test.h" +#include "ipa_nat_drv.h" + +int ipa_nat_test017(int total_entries, u32 tbl_hdl, u8 sep) +{ + int ret; + u32 rule_hdl1, rule_hdl2, rule_hdl3; + ipa_nat_ipv4_rule ipv4_rule; + + u32 pub_ip_add = 0x011617c0; /* "192.23.22.1" */ + + ipv4_rule.target_ip = 0xC1171601; /* 193.23.22.1 */ + ipv4_rule.target_port = 1234; + ipv4_rule.private_ip = 0xC2171601; /* 194.23.22.1 */ + ipv4_rule.private_port = 5678; + ipv4_rule.protocol = IPPROTO_TCP; + ipv4_rule.public_port = 9050; + + IPADBG("%s():\n",__FUNCTION__); + + if(sep) + { + ret = ipa_nat_add_ipv4_tbl(pub_ip_add, total_entries, &tbl_hdl); + CHECK_ERR(ret); + } + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule, &rule_hdl1); + CHECK_ERR(ret); + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule, &rule_hdl2); + CHECK_ERR(ret); + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule, &rule_hdl3); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl2); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl3); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl1); + CHECK_ERR(ret); + + if(sep) + { + ret = ipa_nat_del_ipv4_tbl(tbl_hdl); + CHECK_ERR(ret); + } + + return 0; +} diff --git a/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test018.c b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test018.c new file mode 100644 index 000000000..c885d4dbc --- /dev/null +++ b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test018.c @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2014, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +/*=========================================================================*/ +/*! + @file + ipa_nat_test018.c + + @brief + Verify the following scenario: + 1. Add ipv4 table + 2. add same 3 ipv rules + 3. delete third, second and first + 4. Delete ipv4 table +*/ +/*=========================================================================*/ + +#include "ipa_nat_test.h" +#include "ipa_nat_drv.h" + +int ipa_nat_test018(int total_entries, u32 tbl_hdl, u8 sep) +{ + int ret; + u32 rule_hdl1, rule_hdl2, rule_hdl3; + ipa_nat_ipv4_rule ipv4_rule; + + u32 pub_ip_add = 0x011617c0; /* "192.23.22.1" */ + + ipv4_rule.target_ip = 0xC1171601; /* 193.23.22.1 */ + ipv4_rule.target_port = 1234; + ipv4_rule.private_ip = 0xC2171601; /* 194.23.22.1 */ + ipv4_rule.private_port = 5678; + ipv4_rule.protocol = IPPROTO_TCP; + ipv4_rule.public_port = 9050; + + IPADBG("%s():\n",__FUNCTION__); + + if(sep) + { + ret = ipa_nat_add_ipv4_tbl(pub_ip_add, total_entries, &tbl_hdl); + CHECK_ERR(ret); + } + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule, &rule_hdl1); + CHECK_ERR(ret); + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule, &rule_hdl2); + CHECK_ERR(ret); + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule, &rule_hdl3); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl3); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl2); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl1); + CHECK_ERR(ret); + + if(sep) + { + ret = ipa_nat_del_ipv4_tbl(tbl_hdl); + CHECK_ERR(ret); + } + + return 0; +} diff --git a/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test019.c b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test019.c new file mode 100644 index 000000000..3ba311925 --- /dev/null +++ b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test019.c @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2014, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +/*=========================================================================*/ +/*! + @file + ipa_nat_test019.c + + @brief + Verify the following scenario: + 1. Add ipv4 table + 2. add same 3 ipv rules + 3. delete third, first and second + 4. Delete ipv4 table +*/ +/*=========================================================================*/ + +#include "ipa_nat_test.h" +#include "ipa_nat_drv.h" + +int ipa_nat_test019(int total_entries, u32 tbl_hdl, u8 sep) +{ + int ret; + u32 rule_hdl1, rule_hdl2, rule_hdl3; + ipa_nat_ipv4_rule ipv4_rule; + + u32 pub_ip_add = 0x011617c0; /* "192.23.22.1" */ + + ipv4_rule.target_ip = 0xC1171601; /* 193.23.22.1 */ + ipv4_rule.target_port = 1234; + ipv4_rule.private_ip = 0xC2171601; /* 194.23.22.1 */ + ipv4_rule.private_port = 5678; + ipv4_rule.protocol = IPPROTO_TCP; + ipv4_rule.public_port = 9050; + + IPADBG("%s():\n",__FUNCTION__); + + if(sep) + { + ret = ipa_nat_add_ipv4_tbl(pub_ip_add, total_entries, &tbl_hdl); + CHECK_ERR(ret); + } + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule, &rule_hdl1); + CHECK_ERR(ret); + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule, &rule_hdl2); + CHECK_ERR(ret); + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule, &rule_hdl3); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl3); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl1); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl2); + CHECK_ERR(ret); + + if(sep) + { + ret = ipa_nat_del_ipv4_tbl(tbl_hdl); + CHECK_ERR(ret); + } + + return 0; +} diff --git a/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test020.c b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test020.c new file mode 100644 index 000000000..e6871b58c --- /dev/null +++ b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test020.c @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2014, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/*=========================================================================*/ +/*! + @file + ipa_nat_test020.c + + @brief + Verify the following scenario: + 1. Add ipv4 table + 2. add same 4 ipv rules + 3. delete third, second, fourth and first + 4. Delete ipv4 table +*/ +/*=========================================================================*/ + +#include "ipa_nat_test.h" +#include "ipa_nat_drv.h" + +int ipa_nat_test020(int total_entries, u32 tbl_hdl, u8 sep) +{ + int ret; + u32 rule_hdl1, rule_hdl2, rule_hdl3, rule_hdl4; + ipa_nat_ipv4_rule ipv4_rule; + u32 pub_ip_add = 0x011617c0; /* "192.23.22.1" */ + + ipv4_rule.target_ip = 0xC1171601; /* 193.23.22.1 */ + ipv4_rule.target_port = 1234; + ipv4_rule.private_ip = 0xC2171601; /* 194.23.22.1 */ + ipv4_rule.private_port = 5678; + ipv4_rule.protocol = IPPROTO_TCP; + ipv4_rule.public_port = 9050; + + IPADBG("%s():\n",__FUNCTION__); + + if(sep) + { + ret = ipa_nat_add_ipv4_tbl(pub_ip_add, total_entries, &tbl_hdl); + CHECK_ERR(ret); + } + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule, &rule_hdl1); + CHECK_ERR(ret); + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule, &rule_hdl2); + CHECK_ERR(ret); + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule, &rule_hdl3); + CHECK_ERR(ret); + + ret = ipa_nat_add_ipv4_rule(tbl_hdl, &ipv4_rule, &rule_hdl4); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl3); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl2); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl4); + CHECK_ERR(ret); + + ret = ipa_nat_del_ipv4_rule(tbl_hdl, rule_hdl1); + CHECK_ERR(ret); + + if(sep) + { + ret = ipa_nat_del_ipv4_tbl(tbl_hdl); + CHECK_ERR(ret); + } + + return 0; +} diff --git a/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test021.c b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test021.c new file mode 100644 index 000000000..48c432195 --- /dev/null +++ b/data-ipa-cfg-mgr/ipanat/test/ipa_nat_test021.c @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2014, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/*=========================================================================*/ +/*! + @file + ipa_nat_test021.c + + @brief + Verify the following scenario: + 1. Add ipv4 table + 2. Delete ipv4 table +*/ +/*=========================================================================*/ + +#include "ipa_nat_test.h" +#include "ipa_nat_drv.h" + +int ipa_nat_test021(int total_entries, int reg) +{ + + int ret, i; + u32 tbl_hdl; + u32 pub_ip_add = 0x011617c0; /* "192.23.22.1" */ + + IPADBG("%s():\n",__FUNCTION__); + + for(i=0; i +#include +#include +#include +#include +#include + +#include "ipa_nat_drv.h" +#include "ipa_nat_drvi.h" +#include "ipa_nat_test.h" + +extern struct ipa_nat_cache ipv4_nat_cache; + +int chk_for_loop(u32 tbl_hdl) +{ + struct ipa_nat_rule *tbl_ptr; + struct ipa_nat_indx_tbl_rule *indx_tbl_ptr; + int cnt; + uint16_t cur_entry; + + if (IPA_NAT_INVALID_NAT_ENTRY == tbl_hdl || + tbl_hdl > IPA_NAT_MAX_IP4_TBLS) { + IPAERR("invalid table handle passed \n"); + return -EINVAL; + } + + IPADBG("checking ipv4 rules:\n"); + tbl_ptr = (struct ipa_nat_rule *) + ipv4_nat_cache.ip4_tbl[tbl_hdl-1].ipv4_rules_addr; + for (cnt = 0; + cnt < ipv4_nat_cache.ip4_tbl[tbl_hdl - 1].table_entries; + cnt++) { + if (Read16BitFieldValue(tbl_ptr[cnt].ip_cksm_enbl,ENABLE_FIELD)) { + if(Read16BitFieldValue(tbl_ptr[cnt].nxt_indx_pub_port, + NEXT_INDEX_FIELD) == cnt) + { + IPAERR("Infinite loop detected, entry\n"); + ipa_nati_print_rule(&tbl_ptr[cnt], cnt); + return -EINVAL; + } + } + } + + /* Print ipv4 expansion rules */ + IPADBG("checking ipv4 active expansion rules:\n"); + tbl_ptr = (struct ipa_nat_rule *) + ipv4_nat_cache.ip4_tbl[tbl_hdl-1].ipv4_expn_rules_addr; + for (cnt = 0; + cnt <= ipv4_nat_cache.ip4_tbl[tbl_hdl - 1].expn_table_entries; + cnt++) { + if (Read16BitFieldValue(tbl_ptr[cnt].ip_cksm_enbl, + ENABLE_FIELD)) { + cur_entry = + cnt + ipv4_nat_cache.ip4_tbl[tbl_hdl - 1].table_entries; + if (Read16BitFieldValue(tbl_ptr[cnt].nxt_indx_pub_port, + NEXT_INDEX_FIELD) == cur_entry) + { + IPAERR("Infinite loop detected\n"); + ipa_nati_print_rule(&tbl_ptr[cnt], + (cnt + ipv4_nat_cache.ip4_tbl[tbl_hdl - 1].table_entries)); + return -EINVAL; + } + } + } + + /* Print ipv4 index rules */ + IPADBG("checking ipv4 index active rules: \n"); + indx_tbl_ptr = (struct ipa_nat_indx_tbl_rule *) + ipv4_nat_cache.ip4_tbl[tbl_hdl-1].index_table_addr; + for (cnt = 0; + cnt < ipv4_nat_cache.ip4_tbl[tbl_hdl - 1].table_entries; + cnt++) { + if (Read16BitFieldValue(indx_tbl_ptr[cnt].tbl_entry_nxt_indx, + INDX_TBL_TBL_ENTRY_FIELD)) { + if (Read16BitFieldValue(indx_tbl_ptr[cnt].tbl_entry_nxt_indx, + INDX_TBL_NEXT_INDEX_FILED) == cnt) + { + IPAERR("Infinite loop detected\n"); + ipa_nati_print_index_rule(&indx_tbl_ptr[cnt], cnt, 0); + return -EINVAL; + } + } + } + + /* Print ipv4 index expansion rules */ + IPADBG("Checking ipv4 index expansion active rules: \n"); + indx_tbl_ptr = (struct ipa_nat_indx_tbl_rule *) + ipv4_nat_cache.ip4_tbl[tbl_hdl-1].index_table_expn_addr; + for (cnt = 0; + cnt <= ipv4_nat_cache.ip4_tbl[tbl_hdl - 1].expn_table_entries; + cnt++) { + if (Read16BitFieldValue(indx_tbl_ptr[cnt].tbl_entry_nxt_indx, + INDX_TBL_TBL_ENTRY_FIELD)) { + cur_entry = + cnt + ipv4_nat_cache.ip4_tbl[tbl_hdl - 1].table_entries; + if (Read16BitFieldValue(indx_tbl_ptr[cnt].tbl_entry_nxt_indx, + INDX_TBL_NEXT_INDEX_FILED) == cur_entry) + { + IPAERR("Infinite loop detected\n"); + ipa_nati_print_index_rule(&indx_tbl_ptr[cnt], + (cnt + ipv4_nat_cache.ip4_tbl[tbl_hdl - 1].table_entries), + ipv4_nat_cache.ip4_tbl[tbl_hdl - 1].index_expn_table_meta[cnt].prev_index); + return -EINVAL; + } + } + } + return 0; +} + +uint8_t is_base_entry_valid(u32 tbl_hdl, u16 entry) +{ + struct ipa_nat_rule *tbl_ptr; + + if (entry > + ipv4_nat_cache.ip4_tbl[tbl_hdl - 1].table_entries) + { + tbl_ptr = (struct ipa_nat_rule *) + ipv4_nat_cache.ip4_tbl[tbl_hdl-1].ipv4_expn_rules_addr; + entry -= + ipv4_nat_cache.ip4_tbl[tbl_hdl - 1].table_entries; + } + else + { + tbl_ptr = (struct ipa_nat_rule *) + ipv4_nat_cache.ip4_tbl[tbl_hdl-1].ipv4_rules_addr; + } + return (Read16BitFieldValue(tbl_ptr[entry].ip_cksm_enbl, + ENABLE_FIELD)); +} + +uint8_t is_index_entry_valid(u32 tbl_hdl, u16 entry) +{ + struct ipa_nat_indx_tbl_rule *tbl_ptr; + + if (entry > + ipv4_nat_cache.ip4_tbl[tbl_hdl - 1].table_entries) + { + tbl_ptr = (struct ipa_nat_indx_tbl_rule *) + ipv4_nat_cache.ip4_tbl[tbl_hdl-1].index_table_expn_addr; + entry -= + ipv4_nat_cache.ip4_tbl[tbl_hdl - 1].table_entries; + } + else + { + tbl_ptr = (struct ipa_nat_indx_tbl_rule *) + ipv4_nat_cache.ip4_tbl[tbl_hdl-1].index_table_addr; + } + if (Read16BitFieldValue(tbl_ptr[entry].tbl_entry_nxt_indx, + INDX_TBL_TBL_ENTRY_FIELD)) { + return 1; + } + else + { + return 0; + } +} + +int chk_for_validity(u32 tbl_hdl) +{ + struct ipa_nat_rule *tbl_ptr; + struct ipa_nat_indx_tbl_rule *indx_tbl_ptr; + uint16_t nxt_index, prv_index; + int cnt; + + if (IPA_NAT_INVALID_NAT_ENTRY == tbl_hdl || + tbl_hdl > IPA_NAT_MAX_IP4_TBLS) { + IPAERR("invalid table handle passed \n"); + return -EINVAL; + } + + /* Validate base table next_indx and prev_indx values */ + IPADBG("Validating ipv4 active rules: \n"); + tbl_ptr = (struct ipa_nat_rule *) + ipv4_nat_cache.ip4_tbl[tbl_hdl-1].ipv4_rules_addr; + for (cnt = 0; + cnt < ipv4_nat_cache.ip4_tbl[tbl_hdl - 1].table_entries; + cnt++) { + if (Read16BitFieldValue(tbl_ptr[cnt].ip_cksm_enbl, + ENABLE_FIELD)) { + nxt_index = + Read16BitFieldValue(tbl_ptr[cnt].nxt_indx_pub_port, + NEXT_INDEX_FIELD); + if (!is_base_entry_valid(tbl_hdl, nxt_index)) { + IPAERR("Invalid next index found, entry:%d\n", cnt); + } + } + } + + IPADBG("Validating ipv4 expansion active rules: \n"); + tbl_ptr = (struct ipa_nat_rule *) + ipv4_nat_cache.ip4_tbl[tbl_hdl-1].ipv4_expn_rules_addr; + for (cnt = 0; + cnt <= ipv4_nat_cache.ip4_tbl[tbl_hdl - 1].expn_table_entries; + cnt++) { + if (Read16BitFieldValue(tbl_ptr[cnt].ip_cksm_enbl, + ENABLE_FIELD)) { + /* Validate next index */ + nxt_index = + Read16BitFieldValue(tbl_ptr[cnt].nxt_indx_pub_port, + NEXT_INDEX_FIELD); + if (!is_base_entry_valid(tbl_hdl, nxt_index)) { + IPAERR("Invalid next index found, entry:%d\n", cnt); + } + /* Validate previous index */ + prv_index = + Read16BitFieldValue(tbl_ptr[cnt].sw_spec_params, + SW_SPEC_PARAM_PREV_INDEX_FIELD); + if (!is_base_entry_valid(tbl_hdl, prv_index)) { + IPAERR("Invalid Previous index found, entry:%d\n", cnt); + } + } + } + + IPADBG("Validating ipv4 index active rules: \n"); + indx_tbl_ptr = (struct ipa_nat_indx_tbl_rule *) + ipv4_nat_cache.ip4_tbl[tbl_hdl-1].index_table_addr; + for (cnt = 0; + cnt < ipv4_nat_cache.ip4_tbl[tbl_hdl - 1].table_entries; + cnt++) { + if (Read16BitFieldValue(indx_tbl_ptr[cnt].tbl_entry_nxt_indx, + INDX_TBL_TBL_ENTRY_FIELD)) { + nxt_index = + Read16BitFieldValue(indx_tbl_ptr[cnt].tbl_entry_nxt_indx, + INDX_TBL_NEXT_INDEX_FILED); + if (!is_index_entry_valid(tbl_hdl, nxt_index)) { + IPAERR("Invalid next index found, entry:%d\n", cnt); + } + } + } + + IPADBG("Validating ipv4 index expansion active rules: \n"); + indx_tbl_ptr = (struct ipa_nat_indx_tbl_rule *) + ipv4_nat_cache.ip4_tbl[tbl_hdl-1].index_table_expn_addr; + for (cnt = 0; + cnt <= ipv4_nat_cache.ip4_tbl[tbl_hdl - 1].expn_table_entries; + cnt++) { + if (Read16BitFieldValue(indx_tbl_ptr[cnt].tbl_entry_nxt_indx, + INDX_TBL_TBL_ENTRY_FIELD)) { + /* Validate next index*/ + nxt_index = + Read16BitFieldValue(indx_tbl_ptr[cnt].tbl_entry_nxt_indx, + INDX_TBL_NEXT_INDEX_FILED); + if (!is_index_entry_valid(tbl_hdl, nxt_index)) { + IPAERR("Invalid next index found, entry:%d\n", cnt); + } + + /* Validate previous index*/ + prv_index = + ipv4_nat_cache.ip4_tbl[tbl_hdl-1].index_expn_table_meta[cnt].prev_index; + + if (!is_index_entry_valid(tbl_hdl, prv_index)) { + IPAERR("Invalid Previous index found, entry:%d\n", cnt); + } + } + } + + return 0; +} + +int ipa_nat_validate_ipv4_table(u32 tbl_hdl) +{ + int ret = 0; + + ret = chk_for_loop(tbl_hdl); + if (ret) + return ret; + ret = chk_for_validity(tbl_hdl); + + return ret; +} + +int main(int argc, char* argv[]) +{ + int exec = 0, pass = 0, ret; + int cnt, nt=1; + int total_entries = 100; + u8 sep = 0; + u32 tbl_hdl = 0; + u32 pub_ip_add = 0x011617c0; /* "192.23.22.1" */ + + IPADBG("ipa_nat_testing user space nat driver\n"); + + if (argc == 4) + { + if (!strncmp(argv[1], "reg", 3)) + { + nt = atoi(argv[2]); + total_entries = atoi(argv[3]); + IPADBG("Reg: %d, Nat Entries: %d\n", nt, total_entries); + } + else if (!strncmp(argv[1], "sep", 3)) + { + sep = 1; + nt = atoi(argv[2]); + total_entries = atoi(argv[3]); + } + } + else if (argc == 3) + { + if (!strncmp(argv[1], "inotify", 7)) + { + ipa_nat_test021(total_entries, atoi(argv[2])); + return 0; + } + else if (!strncmp(argv[1], "sep", 3)) + { + sep = 1; + total_entries = atoi(argv[2]); + } + } + else if (argc == 2) + { + total_entries = atoi(argv[1]); + IPADBG("Nat Entries: %d\n", total_entries); + } + + + for (cnt=0; cnt= IPA_NAT_TEST_PRE_COND_TE) + { + IPADBG("\n\nExecuting ipa_nat_test0%d\n", exec); + ret = ipa_nat_test010(total_entries, tbl_hdl, sep); + if (!ret) + { + pass++; + } + else + { + IPAERR("ipa_nat_test0%d Fail\n", exec); + } + exec++; + + IPADBG("\n\nExecuting ipa_nat_test0%d\n", exec); + ret = ipa_nat_test011(total_entries, tbl_hdl, sep); + if (!ret) + { + pass++; + } + else + { + IPAERR("ipa_nat_test0%d Fail\n", exec); + } + exec++; + + IPADBG("\n\nExecuting ipa_nat_test0%d\n", exec); + ret = ipa_nat_test012(total_entries, tbl_hdl, sep); + if (!ret) + { + pass++; + } + else + { + IPAERR("ipa_nat_test0%d Fail\n", exec); + } + exec++; + + IPADBG("\n\nExecuting ipa_nat_test0%d\n", exec); + ret = ipa_nat_test013(total_entries, tbl_hdl, sep); + if (!ret) + { + pass++; + } + else + { + IPAERR("ipa_nat_test0%d Fail\n", exec); + } + exec++; + + IPADBG("\n\nExecuting ipa_nat_test0%d\n", exec); + ret = ipa_nat_test014(total_entries, tbl_hdl, sep); + if (!ret) + { + pass++; + } + else + { + IPAERR("ipa_nat_test0%d Fail\n", exec); + } + exec++; + + IPADBG("\n\nExecuting ipa_nat_test0%d\n", exec); + ret = ipa_nat_test015(total_entries, tbl_hdl, sep); + if (!ret) + { + pass++; + } + else + { + IPAERR("ipa_nat_test0%d Fail\n", exec); + } + exec++; + + IPADBG("\n\nExecuting ipa_nat_test0%d\n", exec); + ret = ipa_nat_test016(total_entries, tbl_hdl, sep); + if (!ret) + { + pass++; + } + else + { + IPAERR("ipa_nat_test0%d Fail\n", exec); + } + exec++; + + IPADBG("\n\nExecuting ipa_nat_test0%d\n", exec); + ret = ipa_nat_test017(total_entries, tbl_hdl, sep); + if (!ret) + { + pass++; + } + else + { + IPAERR("ipa_nat_test0%d Fail\n", exec); + } + exec++; + + IPADBG("\n\nExecuting ipa_nat_test0%d\n", exec); + ret = ipa_nat_test018(total_entries, tbl_hdl, sep); + if (!ret) + { + pass++; + } + else + { + IPAERR("ipa_nat_test0%d Fail\n", exec); + } + exec++; + + IPADBG("\n\nExecuting ipa_nat_test0%d\n", exec); + ret = ipa_nat_test019(total_entries, tbl_hdl, sep); + if (!ret) + { + pass++; + } + else + { + IPAERR("ipa_nat_test0%d Fail\n", exec); + } + exec++; + + IPADBG("\n\nExecuting ipa_nat_test0%d\n", exec); + ret = ipa_nat_test020(total_entries, tbl_hdl, sep); + if (!ret) + { + pass++; + } + else + { + IPAERR("ipa_nat_test0%d Fail\n", exec); + } + exec++; + + IPADBG("\n\nExecuting ipa_nat_test0%d\n", exec); + ret = ipa_nat_test022(total_entries, tbl_hdl, sep); + if (!ret) + { + pass++; + } + else + { + IPAERR("ipa_nat_test0%d Fail\n", exec); + } + exec++; + } + + if (!sep) + { + ret = ipa_nat_del_ipv4_tbl(tbl_hdl); + CHECK_ERR(ret); + } + } + /*======= Printing Results ==========*/ + IPADBG("Total ipa_nat Tests Run:%d, Pass:%d, Fail:%d\n",exec, pass, exec-pass); + return 0; +} diff --git a/device.mk b/device.mk new file mode 100644 index 000000000..5adec3bd6 --- /dev/null +++ b/device.mk @@ -0,0 +1,301 @@ +# Copyright (C) 2016 The CyanogenMod Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# +# This file sets variables that control the way modules are built +# thorughout the system. It should not be used to conditionally +# disable makefiles (the proper mechanism to control what gets +# included in a build is to use PRODUCT_PACKAGES in a product +# definition file). +# + +$(call inherit-product-if-exists, vendor/zuk/z2_plus/z2_plus-vendor.mk) +$(call inherit-product-if-exists, device/zuk/z2_plus/vendor/copyfiles.mk) + +# Overlays +DEVICE_PACKAGE_OVERLAYS += $(LOCAL_PATH)/overlay + +# Permissions +PRODUCT_COPY_FILES += \ + frameworks/native/data/etc/android.hardware.audio.low_latency.xml:system/etc/permissions/android.hardware.audio.low_latency.xml \ + frameworks/native/data/etc/android.hardware.bluetooth_le.xml:system/etc/permissions/android.hardware.bluetooth_le.xml \ + frameworks/native/data/etc/android.hardware.bluetooth.xml:system/etc/permissions/android.hardware.bluetooth.xml \ + frameworks/native/data/etc/android.hardware.camera.flash-autofocus.xml:system/etc/permissions/android.hardware.camera.flash-autofocus.xml \ + frameworks/native/data/etc/android.hardware.camera.front.xml:system/etc/permissions/android.hardware.camera.front.xml \ + frameworks/native/data/etc/android.hardware.camera.full.xml:system/etc/permissions/android.hardware.camera.full.xml \ + frameworks/native/data/etc/android.hardware.camera.raw.xml:system/etc/permissions/android.hardware.camera.raw.xml \ + frameworks/native/data/etc/android.hardware.fingerprint.xml:system/etc/permissions/android.hardware.fingerprint.xml \ + frameworks/native/data/etc/android.hardware.location.gps.xml:system/etc/permissions/android.hardware.location.gps.xml \ + frameworks/native/data/etc/android.hardware.opengles.aep.xml:system/etc/permissions/android.hardware.opengles.aep.xml \ + frameworks/native/data/etc/android.hardware.sensor.accelerometer.xml:system/etc/permissions/android.hardware.sensor.accelerometer.xml \ + frameworks/native/data/etc/android.hardware.sensor.ambient_temperature.xml:system/etc/permissions/android.hardware.sensor.ambient_temperature.xml \ + frameworks/native/data/etc/android.hardware.sensor.barometer.xml:system/etc/permissions/android.hardware.sensor.barometer.xml \ + frameworks/native/data/etc/android.hardware.sensor.compass.xml:system/etc/permissions/android.hardware.sensor.compass.xml \ + frameworks/native/data/etc/android.hardware.sensor.gyroscope.xml:system/etc/permissions/android.hardware.sensor.gyroscope.xml \ + frameworks/native/data/etc/android.hardware.sensor.hifi_sensors.xml:system/etc/permissions/android.hardware.sensor.hifi_sensors.xml \ + frameworks/native/data/etc/android.hardware.sensor.light.xml:system/etc/permissions/android.hardware.sensor.light.xml \ + frameworks/native/data/etc/android.hardware.sensor.proximity.xml:system/etc/permissions/android.hardware.sensor.proximity.xml \ + frameworks/native/data/etc/android.hardware.sensor.relative_humidity.xml:system/etc/permissions/android.hardware.sensor.relative_humidity.xml \ + frameworks/native/data/etc/android.hardware.sensor.stepcounter.xml:system/etc/permissions/android.hardware.sensor.stepcounter.xml \ + frameworks/native/data/etc/android.hardware.sensor.stepdetector.xml:system/etc/permissions/android.hardware.sensor.stepdetector.xml \ + frameworks/native/data/etc/android.hardware.telephony.cdma.xml:system/etc/permissions/android.hardware.telephony.cdma.xml \ + frameworks/native/data/etc/android.hardware.telephony.gsm.xml:system/etc/permissions/android.hardware.telephony.gsm.xml \ + frameworks/native/data/etc/android.hardware.touchscreen.multitouch.jazzhand.xml:system/etc/permissions/android.hardware.touchscreen.multitouch.jazzhand.xml \ + frameworks/native/data/etc/android.hardware.usb.accessory.xml:system/etc/permissions/android.hardware.usb.accessory.xml \ + frameworks/native/data/etc/android.hardware.usb.host.xml:system/etc/permissions/android.hardware.usb.host.xml \ + frameworks/native/data/etc/android.hardware.wifi.direct.xml:system/etc/permissions/android.hardware.wifi.direct.xml \ + frameworks/native/data/etc/android.hardware.wifi.xml:system/etc/permissions/android.hardware.wifi.xml \ + frameworks/native/data/etc/android.software.midi.xml:system/etc/permissions/android.software.midi.xml \ + frameworks/native/data/etc/android.software.sip.voip.xml:system/etc/permissions/android.software.sip.voip.xml \ + frameworks/native/data/etc/com.nxp.mifare.xml:system/etc/permissions/com.nxp.mifare.xml \ + frameworks/native/data/etc/handheld_core_hardware.xml:system/etc/permissions/handheld_core_hardware.xml + +# Device uses high-density artwork where available +PRODUCT_AAPT_CONFIG := normal +PRODUCT_AAPT_PREF_CONFIG := xxhdpi + +# Boot animation +TARGET_SCREEN_HEIGHT := 1920 +TARGET_SCREEN_WIDTH := 1080 + +PRODUCT_PROPERTY_OVERRIDES += \ + dalvik.vm.heapstartsize=8m \ + dalvik.vm.heapgrowthlimit=256m \ + dalvik.vm.heapsize=512m \ + dalvik.vm.heaptargetutilization=0.75 \ + dalvik.vm.heapminfree=512k \ + dalvik.vm.heapmaxfree=8m + +PRODUCT_PROPERTY_OVERRIDES += \ + ro.hwui.texture_cache_size=96 \ + ro.hwui.layer_cache_size=64 \ + ro.hwui.r_buffer_cache_size=12 \ + ro.hwui.path_cache_size=39 \ + ro.hwui.gradient_cache_size=1 \ + ro.hwui.drop_shadow_cache_size=7 \ + ro.hwui.texture_cache_flushrate=0.4 \ + ro.hwui.text_small_cache_width=2048 \ + ro.hwui.text_small_cache_height=2048 \ + ro.hwui.text_large_cache_width=3072 \ + ro.hwui.text_large_cache_height=2048 + +# Haters gonna hate.. +PRODUCT_CHARACTERISTICS := nosdcard + +# Alipay +PRODUCT_PACKAGES += \ + org.ifaa.android.manager + +PRODUCT_BOOT_JARS += \ + org.ifaa.android.manager + +# Audio +PRODUCT_PACKAGES += \ + audiod \ + audio.a2dp.default \ + audio.primary.msm8996 \ + audio.r_submix.default \ + audio.usb.default \ + libaudio-resampler \ + libqcompostprocbundle \ + libqcomvisualizer \ + libqcomvoiceprocessing \ + libvolumelistener \ + tinymix + +PRODUCT_COPY_FILES += \ + $(LOCAL_PATH)/audio/audio_effects.conf:system/vendor/etc/audio_effects.conf \ + $(LOCAL_PATH)/audio/audio_output_policy.conf:system/vendor/etc/audio_output_policy.conf \ + $(LOCAL_PATH)/audio/audio_platform_info.xml:system/etc/audio_platform_info.xml \ + $(LOCAL_PATH)/audio/audio_policy.conf:system/etc/audio_policy.conf \ + $(LOCAL_PATH)/audio/listen_platform_info.xml:system/etc/listen_platform_info.xml \ + $(LOCAL_PATH)/audio/mixer_paths_tasha.xml:system/etc/mixer_paths_tasha.xml \ + $(LOCAL_PATH)/audio/mixer_paths_tasha_z2_plus.xml:system/etc/mixer_paths_tasha_z2_plus.xml \ + $(LOCAL_PATH)/audio/sound_trigger_mixer_paths_wcd9330.xml:system/etc/sound_trigger_mixer_paths_wcd9330.xml \ + $(LOCAL_PATH)/audio/sound_trigger_mixer_paths.xml:system/etc/sound_trigger_mixer_paths.xml \ + $(LOCAL_PATH)/audio/sound_trigger_platform_info.xml:system/etc/sound_trigger_platform_info.xml \ + $(LOCAL_PATH)/audio/aanc_tuning_mixer.txt:system/etc/aanc_tuning_mixer.txt \ + + +# ANT+ +PRODUCT_PACKAGES += \ + AntHalService \ + com.dsi.ant.antradio_library \ + libantradio + +PRODUCT_COPY_FILES += \ + external/ant-wireless/antradio-library/com.dsi.ant.antradio_library.xml:system/etc/permissions/com.dsi.ant.antradio_library.xml + +# Camera +PRODUCT_PACKAGES += \ + Snap \ + +# Gestures +PRODUCT_PACKAGES += \ + com.cyanogenmod.keyhandler + +# Charger +PRODUCT_PACKAGES += \ + charger_res_images + +# Connectivity Engine support (CNE) +PRODUCT_PACKAGES += \ + cneapiclient \ + com.quicinc.cne \ + services-ext + +# CNE +PRODUCT_PACKAGES += \ + libcnefeatureconfig + +# Display +PRODUCT_PACKAGES += \ + copybit.msm8996 \ + gralloc.msm8996 \ + hwcomposer.msm8996 \ + memtrack.msm8996 \ + liboverlay \ + libtinyxml + +# Doze mode +PRODUCT_PACKAGES += \ + ZukDoze + +# Fingerprint sensor +PRODUCT_PACKAGES += \ + fingerprintd + +# Gello +PRODUCT_PACKAGES += \ + Gello + +# GPS +PRODUCT_PACKAGES += \ + gps.msm8996 \ + libcurl + +PRODUCT_COPY_FILES += \ + $(LOCAL_PATH)/gps/etc/flp.conf:system/etc/flp.conf \ + $(LOCAL_PATH)/gps/etc/gps.conf:system/etc/gps.conf \ + $(LOCAL_PATH)/gps/etc/izat.conf:system/etc/izat.conf \ + $(LOCAL_PATH)/gps/etc/lowi.conf:system/etc/lowi.conf \ + $(LOCAL_PATH)/gps/etc/sap.conf:system/etc/sap.conf \ + $(LOCAL_PATH)/gps/etc/xtwifi.conf:system/etc/xtwifi.conf + +# IPv6 +PRODUCT_PACKAGES += \ + ebtables \ + ethertypes + +# IRQ +PRODUCT_COPY_FILES += \ + $(LOCAL_PATH)/configs/msm_irqbalance.conf:system/vendor/etc/msm_irqbalance.conf + +# IRSC +PRODUCT_COPY_FILES += \ + $(LOCAL_PATH)/configs/sec_config:system/etc/sec_config + +# Keylayouts +PRODUCT_COPY_FILES += \ + $(LOCAL_PATH)/keylayout/fpc1020tp.kl:system/usr/keylayout/fpc1020tp.kl \ + $(LOCAL_PATH)/keylayout/goodix-ts.kl:system/usr/keylayout/goodix-ts.kl \ + $(LOCAL_PATH)/keylayout/gpio-keys.kl:system/usr/keylayout/gpio-keys.kl \ + $(LOCAL_PATH)/keylayout/synaptics_dsx.kl:system/usr/keylayout/synaptics_dsx.kl \ + $(LOCAL_PATH)/keylayout/msm8996-tasha-mtp-snd-card_Button_Jack.kl:system/usr/keylayout/msm8996-tasha-mtp-snd-card_Button_Jack.kl \ + $(LOCAL_PATH)/keylayout/qpnp_pon.kl:system/usr/keylayout/qpnp_pon.kl + +# Lights +PRODUCT_PACKAGES += \ + lights.msm8996 + +# Media +PRODUCT_COPY_FILES += \ + $(LOCAL_PATH)/configs/calib.cfg:system/etc/calib.cfg \ + $(LOCAL_PATH)/configs/capability.xml:system/etc/capability.xml + +# ca +PRODUCT_COPY_FILES += \ + $(LOCAL_PATH)/configs/media_codecs.xml:system/etc/media_codecs.xml \ + $(LOCAL_PATH)/configs/media_codecs_performance.xml:system/etc/media_codecs_performance.xml \ + $(LOCAL_PATH)/configs/media_profiles.xml:system/etc/media_profiles.xml + +PRODUCT_COPY_FILES += \ + frameworks/av/media/libstagefright/data/media_codecs_google_audio.xml:system/etc/media_codecs_google_audio.xml \ + frameworks/av/media/libstagefright/data/media_codecs_google_telephony.xml:system/etc/media_codecs_google_telephony.xml \ + frameworks/av/media/libstagefright/data/media_codecs_google_video.xml:system/etc/media_codecs_google_video.xml + +# OMX +PRODUCT_PACKAGES += \ + libc2dcolorconvert \ + libextmedia_jni \ + libOmxAacEnc \ + libOmxAmrEnc \ + libOmxCore \ + libOmxEvrcEnc \ + libOmxQcelp13Enc \ + libOmxVdec \ + libOmxVenc \ + libstagefrighthw + +# Power +PRODUCT_PACKAGES += \ + power.msm8996 + +# QMI +PRODUCT_PACKAGES += \ + libjson + +# Ramdisk +PRODUCT_PACKAGES += \ + fstab.qcom \ + init.qcom.bt.sh \ + init.qcom.power.rc \ + init.qcom.rc \ + init.qcom.sh \ + init.qcom.usb.rc \ + init.qcom.usb.sh \ + ueventd.qcom.rc + +# RIL +PRODUCT_PACKAGES += \ + librmnetctl \ + libxml2 + +# Sensors +PRODUCT_PACKAGES += \ + sensors.msm8996 + +# Wifi +PRODUCT_PACKAGES += \ + ipacm \ + ipacm-diag \ + IPACM_cfg.xml \ + libqsap_sdk \ + libQWiFiSoftApCfg \ + libwpa_client \ + hostapd \ + dhcpcd.conf \ + wpa_supplicant \ + wpa_supplicant.conf + +PRODUCT_COPY_FILES += \ + $(LOCAL_PATH)/wifi/hostapd.accept:system/etc/hostapd/hostapd.accept \ + $(LOCAL_PATH)/wifi/hostapd.conf:system/etc/hostapd/hostapd_default.conf \ + $(LOCAL_PATH)/wifi/hostapd.deny:system/etc/hostapd/hostapd.deny \ + $(LOCAL_PATH)/wifi/p2p_supplicant_overlay.conf:system/etc/wifi/p2p_supplicant_overlay.conf \ + $(LOCAL_PATH)/wifi/wpa_supplicant_overlay.conf:system/etc/wifi/wpa_supplicant_overlay.conf + +PRODUCT_COPY_FILES += \ + $(LOCAL_PATH)/wifi/WCNSS_qcom_cfg.ini:system/etc/wifi/WCNSS_qcom_cfg.ini \ + $(LOCAL_PATH)/wifi/WCNSS_cfg.dat:system/etc/firmware/wlan/qca_cld/WCNSS_cfg.dat diff --git a/doze/Android.mk b/doze/Android.mk new file mode 100644 index 000000000..de136ea94 --- /dev/null +++ b/doze/Android.mk @@ -0,0 +1,16 @@ +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := optional + +LOCAL_SRC_FILES := $(call all-java-files-under, src) + +LOCAL_PACKAGE_NAME := ZukDoze +LOCAL_CERTIFICATE := platform +LOCAL_PRIVILEGED_MODULE := true + +LOCAL_PROGUARD_FLAG_FILES := proguard.flags + +include $(BUILD_PACKAGE) + +include $(call all-makefiles-under,$(LOCAL_PATH)) diff --git a/doze/AndroidManifest.xml b/doze/AndroidManifest.xml new file mode 100644 index 000000000..54783ebf2 --- /dev/null +++ b/doze/AndroidManifest.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doze/proguard.flags b/doze/proguard.flags new file mode 100644 index 000000000..a21e62fb2 --- /dev/null +++ b/doze/proguard.flags @@ -0,0 +1,3 @@ +-keep class com.cyanogenmod.settings.doze.* { + *; +} diff --git a/doze/res/drawable/ic_settings_doze.xml b/doze/res/drawable/ic_settings_doze.xml new file mode 100644 index 000000000..838602457 --- /dev/null +++ b/doze/res/drawable/ic_settings_doze.xml @@ -0,0 +1,51 @@ + + + + + + + diff --git a/doze/res/values-af/strings.xml b/doze/res/values-af/strings.xml new file mode 100644 index 000000000..c023c0891 --- /dev/null +++ b/doze/res/values-af/strings.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/doze/res/values-am/strings.xml b/doze/res/values-am/strings.xml new file mode 100644 index 000000000..c023c0891 --- /dev/null +++ b/doze/res/values-am/strings.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/doze/res/values-ar/strings.xml b/doze/res/values-ar/strings.xml new file mode 100644 index 000000000..c023c0891 --- /dev/null +++ b/doze/res/values-ar/strings.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/doze/res/values-as-rIN/strings.xml b/doze/res/values-as-rIN/strings.xml new file mode 100644 index 000000000..c023c0891 --- /dev/null +++ b/doze/res/values-as-rIN/strings.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/doze/res/values-ast-rES/strings.xml b/doze/res/values-ast-rES/strings.xml new file mode 100644 index 000000000..c023c0891 --- /dev/null +++ b/doze/res/values-ast-rES/strings.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/doze/res/values-az-rAZ/strings.xml b/doze/res/values-az-rAZ/strings.xml new file mode 100644 index 000000000..c023c0891 --- /dev/null +++ b/doze/res/values-az-rAZ/strings.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/doze/res/values-be/strings.xml b/doze/res/values-be/strings.xml new file mode 100644 index 000000000..c023c0891 --- /dev/null +++ b/doze/res/values-be/strings.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/doze/res/values-bg/strings.xml b/doze/res/values-bg/strings.xml new file mode 100644 index 000000000..404898bc5 --- /dev/null +++ b/doze/res/values-bg/strings.xml @@ -0,0 +1,34 @@ + + + + + Атмосферен екран + Събуждане на екрана при получаване на известие + Винаги разрешено + Останете на линия за събития, веднага след като екранът се изключи + + Сензор за наклон + Отговор + Светлинна индикация, когато устройството е вдигнато + + Сензор за близост + Махане с ръка + Показва известията при прекарване на ръка над екрана + Джоб + Показва известията, когато извадите устройството от джоба си + + ОK + Помощ + Тези функции използват сензорни събития да показват известия, когато устройството е в състояние на покой. Избраният сензор се активира само когато устройството получава уведомление, което помага за намаляване на използването на батерията. Има и опция за активиране на избрания сензор, така че екранът се изключва, което ще доведе до увеличаване на използването на батерията. + diff --git a/doze/res/values-bn-rBD/strings.xml b/doze/res/values-bn-rBD/strings.xml new file mode 100644 index 000000000..c023c0891 --- /dev/null +++ b/doze/res/values-bn-rBD/strings.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/doze/res/values-br-rFR/strings.xml b/doze/res/values-br-rFR/strings.xml new file mode 100644 index 000000000..c023c0891 --- /dev/null +++ b/doze/res/values-br-rFR/strings.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/doze/res/values-bs-rBA/strings.xml b/doze/res/values-bs-rBA/strings.xml new file mode 100644 index 000000000..c023c0891 --- /dev/null +++ b/doze/res/values-bs-rBA/strings.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/doze/res/values-ca/strings.xml b/doze/res/values-ca/strings.xml new file mode 100644 index 000000000..a94881416 --- /dev/null +++ b/doze/res/values-ca/strings.xml @@ -0,0 +1,34 @@ + + + + + Pantalla ambient + Encen la pantalla quan rebis notificacions + Sempre habilitat + Estigues atent als esdeveniments del sensor tan aviat com s\'apagui la pantalla + + Sensor d\'inclinació + Contesta + Mostra les notificacions quan es reculli el dispositiu + + Sensor de proximitat + Passa la mà + Mostra notificacions quan es passi la mà + Butxaca + Mostra notificacions quan te\'l treguis de la butxaca + + D\'ACORD + Ajuda + Aquestes característiques utilitzen esdeveniments dels sensors per llançar una notificació latent. El sensor escollit només serà habilitat quan el dispositiu rebi una notificació, això ajuda a reduir l\'ús de la bateria. També hi ha una opció per habilitar el sensor escollit tan aviat com s\'apagui la pantalla, això causarà un major ús de la bateria. + diff --git a/doze/res/values-cs/strings.xml b/doze/res/values-cs/strings.xml new file mode 100644 index 000000000..47388288c --- /dev/null +++ b/doze/res/values-cs/strings.xml @@ -0,0 +1,34 @@ + + + + + Ambientní displej + Probudit obrazovku při upozornění + Vždy povolit + Naslouchat událostem senzoru ihned po vypnutí obrazovky + + Senzor náklonu + Sebrání + Pulzovat oznámení při zvednutí zařízení + + Senzor přiblížení + Mávání rukou + Upozornit pulsováním při zamáváním rukou + Kapsa + Upozornit pulsováním při vyjmutí z kapsy + + OK + Uživatelská příručka + Tyto funkce používají události senzorů ke spuštění pulzování oznámení. Vybraný senzor je zapnut pouze v případě přijetí upozornění, což vede k úspoře baterie. Je zde i možnost zapnout daný senzor ihned po vypnutí obrazovky, ale dochází k většímu vybíjení. + diff --git a/doze/res/values-csb-rPL/strings.xml b/doze/res/values-csb-rPL/strings.xml new file mode 100644 index 000000000..c023c0891 --- /dev/null +++ b/doze/res/values-csb-rPL/strings.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/doze/res/values-cy/strings.xml b/doze/res/values-cy/strings.xml new file mode 100644 index 000000000..c023c0891 --- /dev/null +++ b/doze/res/values-cy/strings.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/doze/res/values-da/strings.xml b/doze/res/values-da/strings.xml new file mode 100644 index 000000000..fffc2be70 --- /dev/null +++ b/doze/res/values-da/strings.xml @@ -0,0 +1,34 @@ + + + + + Inaktivitetsvisning + Tænder skærmen, når du modtager notifikationer + Aktiver altid + Lyt efter sensoraktiviteter så snart skærmen slukkes + + Tilt-sensor + Samle op + Blink med notifikationerne når enheden tages op + + Berøringssensor + Vink med hånden + Vibrér, hvis der er notifikationer, når du vinker over skærmen + Lomme + Vibrér, hvis der er notifikationer, når telefonen tages op ad lommen + + OK + Hjælp + Disse funktioner bruger sensoraktiviteter til at starte en doze-notifikation. Den valgte sensor er kun aktiveret, når enheden modtager en notifikation, dette hjælper med at reducere batteriforbruget. Der er også en mulighed for at aktivere den valgte sensor, så snart skærmen slukkes, dette vil medføre højere batteribrug. + diff --git a/doze/res/values-de/strings.xml b/doze/res/values-de/strings.xml new file mode 100644 index 000000000..cf7c98e02 --- /dev/null +++ b/doze/res/values-de/strings.xml @@ -0,0 +1,34 @@ + + + + + Inaktivitätsdisplay + Bildschirm einschalten, wenn Sie Benachrichtigungen erhalten + Immer aktiviert + Auf den Sensor reagieren, sobald der Bildschirm ausgeschaltet wird + + Neigungssensor + Aufnehmen + Benachrichtigungen kurz einblenden, wenn das Gerät aufgenommen wird + + Näherungssensor + Winken + Beim Winken Benachrichtigungen kurzzeitig einblenden + Tasche + Benachrichtigungen kurz einblenden, wenn das Gerät aus der Tasche genommen wird + + OK + Hilfe + Diese Features verwenden Sensoren, um im Standby kurz Benachrichtigungen einzublenden. Der gewählte Sensor wird nur bei Eingang einer Benachrichtigung aktiviert. Dies hilft dabei, den Stromverbrauch zu reduzieren. Alternativ kann der Sensor sofort beim Abschalten des Bildschirms aktiviert werden, wodurch sich jedoch der Stromverbrauch erhöht. + diff --git a/doze/res/values-el/strings.xml b/doze/res/values-el/strings.xml new file mode 100644 index 000000000..dff5c1498 --- /dev/null +++ b/doze/res/values-el/strings.xml @@ -0,0 +1,31 @@ + + + + + Οθόνη ambient + Ενεργοποίηση της οθόνης όταν λαμβάνετε ειδοποιήσεις + + Αισθητήρας κλίσης + Σήκωμα συσκευής + Παλμός ειδοποιήσεων κατά το σήκωμα της συσκευής + + Αισθητήρας εγγύτητας + Αιώρηση χεριού + Παλμός ειδοποιήσεων κατά την αιώρηση του χεριού + Τσέπη + Παλμός ειδοποιήσεων κατά την έξοδο από την τσέπη + + OK + Βοήθεια + diff --git a/doze/res/values-en-rAU/strings.xml b/doze/res/values-en-rAU/strings.xml new file mode 100644 index 000000000..c023c0891 --- /dev/null +++ b/doze/res/values-en-rAU/strings.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/doze/res/values-en-rGB/strings.xml b/doze/res/values-en-rGB/strings.xml new file mode 100644 index 000000000..c023c0891 --- /dev/null +++ b/doze/res/values-en-rGB/strings.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/doze/res/values-en-rIN/strings.xml b/doze/res/values-en-rIN/strings.xml new file mode 100644 index 000000000..c023c0891 --- /dev/null +++ b/doze/res/values-en-rIN/strings.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/doze/res/values-en-rPT/strings.xml b/doze/res/values-en-rPT/strings.xml new file mode 100644 index 000000000..c023c0891 --- /dev/null +++ b/doze/res/values-en-rPT/strings.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/doze/res/values-eo/strings.xml b/doze/res/values-eo/strings.xml new file mode 100644 index 000000000..c023c0891 --- /dev/null +++ b/doze/res/values-eo/strings.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/doze/res/values-es-rCO/strings.xml b/doze/res/values-es-rCO/strings.xml new file mode 100644 index 000000000..c023c0891 --- /dev/null +++ b/doze/res/values-es-rCO/strings.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/doze/res/values-es-rMX/strings.xml b/doze/res/values-es-rMX/strings.xml new file mode 100644 index 000000000..c023c0891 --- /dev/null +++ b/doze/res/values-es-rMX/strings.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/doze/res/values-es-rUS/strings.xml b/doze/res/values-es-rUS/strings.xml new file mode 100644 index 000000000..c023c0891 --- /dev/null +++ b/doze/res/values-es-rUS/strings.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/doze/res/values-es/strings.xml b/doze/res/values-es/strings.xml new file mode 100644 index 000000000..c023c0891 --- /dev/null +++ b/doze/res/values-es/strings.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/doze/res/values-et-rEE/strings.xml b/doze/res/values-et-rEE/strings.xml new file mode 100644 index 000000000..c023c0891 --- /dev/null +++ b/doze/res/values-et-rEE/strings.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/doze/res/values-eu-rES/strings.xml b/doze/res/values-eu-rES/strings.xml new file mode 100644 index 000000000..5a2ad3538 --- /dev/null +++ b/doze/res/values-eu-rES/strings.xml @@ -0,0 +1,34 @@ + + + + + Ambient display + Piztu pantaila jakinarazpenak jasotzean + Gaitu beti + Sentsoreen gertakizunei entzun pantaila itzali eta berehala + + Inklinazio sentsorea + Hartu + Led jakinarazpenak gailua hartzean + + Hurbiltasun sentsorea + Agurtu eskuarekin + Jakinarazpen argia eskuarekin agurtzean + Poltsikoratu + Jakinarazpen argia poltsikotik ateratzean + + Ados + Laguntza + Ezaugarri hauek sentsoreen gertakizunak erabiltzen dituzte jakinarazpen argi bat pizteko. Sentsorea jakinarazpen bat jasotzean gaituko da, honi esker bateria erabilera murrizten da. Badago ere pantaila itzali eta berehala sentsorea pizteko aukera, honek bateria gehiago erabiliko du. + diff --git a/doze/res/values-fa/strings.xml b/doze/res/values-fa/strings.xml new file mode 100644 index 000000000..c023c0891 --- /dev/null +++ b/doze/res/values-fa/strings.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/doze/res/values-fi/strings.xml b/doze/res/values-fi/strings.xml new file mode 100644 index 000000000..680697854 --- /dev/null +++ b/doze/res/values-fi/strings.xml @@ -0,0 +1,34 @@ + + + + + Ambient-näyttö + Herätä näyttö kun saat ilmoituksia + Käytä aina + Havaitse sensorin tapahtumia kun näyttö sammuu + + Kallistussensori + Nosto + Väläytä ilmoituksia kun laite nostetaan + + Läheisyysanturi + Käden heilautus + Näytä ilmoitukset heilautettaessa kättä + Tasku + Näytä ilmoitukset kun laite otetaan taskusta + + OK + Apua + Ominaisuudet käyttää sensorin tapahtumia näyttääkseen ilmoituksia. Valittu sensori on vain käytössä kun laite saa ilmoituksen, tämä auttaa vähentämään akun kulutusta. Voit myös ottaa sensorit käyttöön kun näyttö on suljettu, mutta tämä kasvattaa akun kulutusta. + diff --git a/doze/res/values-fil-rPH/strings.xml b/doze/res/values-fil-rPH/strings.xml new file mode 100644 index 000000000..c023c0891 --- /dev/null +++ b/doze/res/values-fil-rPH/strings.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/doze/res/values-fr-rCA/strings.xml b/doze/res/values-fr-rCA/strings.xml new file mode 100644 index 000000000..c023c0891 --- /dev/null +++ b/doze/res/values-fr-rCA/strings.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/doze/res/values-fr/strings.xml b/doze/res/values-fr/strings.xml new file mode 100644 index 000000000..81cbcab48 --- /dev/null +++ b/doze/res/values-fr/strings.xml @@ -0,0 +1,27 @@ + + + + + Affichage ambiant + Toujours activer + + Capteur d’inclinaison + Prise en main + + Capteur de proximité + Passage de la main + Poche + + OK + diff --git a/doze/res/values-frp-rIT/strings.xml b/doze/res/values-frp-rIT/strings.xml new file mode 100644 index 000000000..c023c0891 --- /dev/null +++ b/doze/res/values-frp-rIT/strings.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/doze/res/values-fy-rNL/strings.xml b/doze/res/values-fy-rNL/strings.xml new file mode 100644 index 000000000..c023c0891 --- /dev/null +++ b/doze/res/values-fy-rNL/strings.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/doze/res/values-ga-rIE/strings.xml b/doze/res/values-ga-rIE/strings.xml new file mode 100644 index 000000000..c023c0891 --- /dev/null +++ b/doze/res/values-ga-rIE/strings.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/doze/res/values-gd-rGB/strings.xml b/doze/res/values-gd-rGB/strings.xml new file mode 100644 index 000000000..c023c0891 --- /dev/null +++ b/doze/res/values-gd-rGB/strings.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/doze/res/values-gl-rES/strings.xml b/doze/res/values-gl-rES/strings.xml new file mode 100644 index 000000000..809934c7b --- /dev/null +++ b/doze/res/values-gl-rES/strings.xml @@ -0,0 +1,34 @@ + + + + + Visualización ambiente + Activar a pantalla ao recibir notificacións + Sempre activo + Atender ao eventos do sensor así que se apague a pantalla + + Sensor de inclinación + Coller + Amosar notificacións ao coller o dispositivo + + Sensor de proximidade + Pasar a man + Amosar notificacións ao pasar a man + Peto + Amosar notificacións ao sacar do peto + + ACEPTAR + Axuda + Estas características usan eventos do sensor para amosar unha notificación latente. O sensor seleccionado habilitarase só cando reciba unha notificación axudando a reducir o consumo da batería. Tamén existe unha opción para activar o sensor así que se apague a pantalla, pero isto causará un maior uso da batería. + diff --git a/doze/res/values-gu-rIN/strings.xml b/doze/res/values-gu-rIN/strings.xml new file mode 100644 index 000000000..c023c0891 --- /dev/null +++ b/doze/res/values-gu-rIN/strings.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/doze/res/values-hi/strings.xml b/doze/res/values-hi/strings.xml new file mode 100644 index 000000000..c023c0891 --- /dev/null +++ b/doze/res/values-hi/strings.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/doze/res/values-hr/strings.xml b/doze/res/values-hr/strings.xml new file mode 100644 index 000000000..1742320c8 --- /dev/null +++ b/doze/res/values-hr/strings.xml @@ -0,0 +1,34 @@ + + + + + Ambijentni zaslon + Probudi zaslon kada primite obavijesti + Uvijek omogući + Praćenje senzora čim se zaslon isključi + + Senzor nagiba + Podizanje + Prikazuj obavijesti kada je uređaj podignut + + Senzor blizine + Zamah rukom + Prikaz obavijesti na zamah rukom + Džep + Prikaz obavijesti kada izvadite uređaj iz džepa + + OK + Pomoć + Te značajke koriste događaje senzora za pokretanje pulsiranja obavijesti. Odabrani senzor je omogućen jedino kada uređaj primi obavijest, to pomaže smanjenju potrošnje baterije. Tu je i opcija omogućenja odabranog senzora čim se zaslon isključi, to će uzrokovati veću potrošnju baterije. + diff --git a/doze/res/values-hu/strings.xml b/doze/res/values-hu/strings.xml new file mode 100644 index 000000000..d4ac1cc5e --- /dev/null +++ b/doze/res/values-hu/strings.xml @@ -0,0 +1,34 @@ + + + + + Környezeti kijelző + Képernyő felébresztése értesítések fogadásakor + Mindig engedélyezze + Figyelje az érzékelő eseményeket, amint a képernyő kikapcsol + + Dőlés érzékelő + Kézbevétel + Villantsa fel az értesítéseket kézbevételkor + + Közelség érzékelő + Lebegő simítás + Értesítések felvillantása lebegő simításnál + Zseb + Értesítések felvillantása zsebből való kivételkor + + Rendben + Súgó + Ezen funkció az érzékelő eseményeket használja a környezeti kijelző értesítési impulzusaihoz. A választott érzékelő csak akkor engedélyezett, ha a készülék értesítést kap, ez segít csökkenteni az akkumulátor használatát. Lehetőség van a választott érzékelő engedélyezésére is, amint a képernyő kikapcsol, de ez nagyobb akkumulátor használatot jelent. + diff --git a/doze/res/values-hy-rAM/strings.xml b/doze/res/values-hy-rAM/strings.xml new file mode 100644 index 000000000..c023c0891 --- /dev/null +++ b/doze/res/values-hy-rAM/strings.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/doze/res/values-in/strings.xml b/doze/res/values-in/strings.xml new file mode 100644 index 000000000..c023c0891 --- /dev/null +++ b/doze/res/values-in/strings.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/doze/res/values-is-rIS/strings.xml b/doze/res/values-is-rIS/strings.xml new file mode 100644 index 000000000..c023c0891 --- /dev/null +++ b/doze/res/values-is-rIS/strings.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/doze/res/values-it/strings.xml b/doze/res/values-it/strings.xml new file mode 100644 index 000000000..15530e709 --- /dev/null +++ b/doze/res/values-it/strings.xml @@ -0,0 +1,34 @@ + + + + + Display Ambient + Accendi lo schermo quando ricevi una notifica + Sempre attivo + Attiva i sensori per gli eventi appena lo schermo si spegne + + Sensore inclinazione + Solleva + Mostra le notifiche quando il dispositivo viene sollevato + + Sensore prossimità + Movimento della mano + Mostra le notifiche al passaggio della mano + Tasca + Mostra le notifiche quando il telefono viene rimosso dalla tasca + + OK + Guida + Queste funzioni utilizzano i sensori per mostrare le notifiche. Il sensore selezionato verrà attivato solo quando il dispositivo riceve una notifica, questo consentirà di ridurre l\'utilizzo della batteria. È anche possibile attivare il sensore selezionato appena lo schermo si spegne, ma ciò comporterà ad un utilizzo maggiore della batteria. + diff --git a/doze/res/values-iw/strings.xml b/doze/res/values-iw/strings.xml new file mode 100644 index 000000000..b3ba98fad --- /dev/null +++ b/doze/res/values-iw/strings.xml @@ -0,0 +1,31 @@ + + + + + תצוגת התראות עמומה + הפעל את המסך כשמתקבלות התראות + אפשר תמיד + + חיישן הטייה + + חיישן קרבה + הנפת יד + הדגש התראות בהנפת יד + כיס + הצג התראות בהוצאה מהכיס + + אישור + עזרה + התכונות נעזרות בחיישני אירועים כדי להפעיל הדגשת התראות עם Doze. החיישן הנבחר מופעל רק כאשר המכשיר מקבל התראה, מה שעוזר להקטין את השימוש בסוללה. בנוסף, יש אפשרות להפעיל את החיישן הנבחר ברגע שהמסך נכבה, מה שעלול לגרום לשימוש רב יותר בסוללה. + diff --git a/doze/res/values-ja/strings.xml b/doze/res/values-ja/strings.xml new file mode 100644 index 000000000..7a07c4cf7 --- /dev/null +++ b/doze/res/values-ja/strings.xml @@ -0,0 +1,34 @@ + + + + + 常に画面表示ディスプレイ + 通知を受信したときに画面を点灯する + 常に有効 + 画面を消灯した直後からセンサーイベントをリッスンする + + 傾きセンサー + 持ち上げ + 端末を持ち上げたときに通知を点滅表示する + + 接近センサー + 手を振る + 手を振ったときに通知を点滅表示する + ポケット + ポケットから取り出したときに通知を点滅表示する + + OK + ヘルプ + これらの機能はdoze通知点滅表示を起動するためにセンサーイベントを使用します。電池の使用量を削減するために、端末が通知を受信した時にのみ選択したセンサーが有効になります。画面を消灯した直後から選択したセンサーを有効にするオプションもありますが、電池の使用量が多くなります。 + diff --git a/doze/res/values-ka-rGE/strings.xml b/doze/res/values-ka-rGE/strings.xml new file mode 100644 index 000000000..c023c0891 --- /dev/null +++ b/doze/res/values-ka-rGE/strings.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/doze/res/values-kk-rKZ/strings.xml b/doze/res/values-kk-rKZ/strings.xml new file mode 100644 index 000000000..c023c0891 --- /dev/null +++ b/doze/res/values-kk-rKZ/strings.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/doze/res/values-km-rKH/strings.xml b/doze/res/values-km-rKH/strings.xml new file mode 100644 index 000000000..c023c0891 --- /dev/null +++ b/doze/res/values-km-rKH/strings.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/doze/res/values-kn-rIN/strings.xml b/doze/res/values-kn-rIN/strings.xml new file mode 100644 index 000000000..c023c0891 --- /dev/null +++ b/doze/res/values-kn-rIN/strings.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/doze/res/values-ko/strings.xml b/doze/res/values-ko/strings.xml new file mode 100644 index 000000000..c023c0891 --- /dev/null +++ b/doze/res/values-ko/strings.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/doze/res/values-ku/strings.xml b/doze/res/values-ku/strings.xml new file mode 100644 index 000000000..c023c0891 --- /dev/null +++ b/doze/res/values-ku/strings.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/doze/res/values-ky-rKG/strings.xml b/doze/res/values-ky-rKG/strings.xml new file mode 100644 index 000000000..c023c0891 --- /dev/null +++ b/doze/res/values-ky-rKG/strings.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/doze/res/values-lb/strings.xml b/doze/res/values-lb/strings.xml new file mode 100644 index 000000000..c023c0891 --- /dev/null +++ b/doze/res/values-lb/strings.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/doze/res/values-lo-rLA/strings.xml b/doze/res/values-lo-rLA/strings.xml new file mode 100644 index 000000000..c023c0891 --- /dev/null +++ b/doze/res/values-lo-rLA/strings.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/doze/res/values-lt/strings.xml b/doze/res/values-lt/strings.xml new file mode 100644 index 000000000..c023c0891 --- /dev/null +++ b/doze/res/values-lt/strings.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/doze/res/values-lv/strings.xml b/doze/res/values-lv/strings.xml new file mode 100644 index 000000000..c023c0891 --- /dev/null +++ b/doze/res/values-lv/strings.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/doze/res/values-mk-rMK/strings.xml b/doze/res/values-mk-rMK/strings.xml new file mode 100644 index 000000000..c023c0891 --- /dev/null +++ b/doze/res/values-mk-rMK/strings.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/doze/res/values-ml-rIN/strings.xml b/doze/res/values-ml-rIN/strings.xml new file mode 100644 index 000000000..c023c0891 --- /dev/null +++ b/doze/res/values-ml-rIN/strings.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/doze/res/values-mn-rMN/strings.xml b/doze/res/values-mn-rMN/strings.xml new file mode 100644 index 000000000..c023c0891 --- /dev/null +++ b/doze/res/values-mn-rMN/strings.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/doze/res/values-mr-rIN/strings.xml b/doze/res/values-mr-rIN/strings.xml new file mode 100644 index 000000000..c023c0891 --- /dev/null +++ b/doze/res/values-mr-rIN/strings.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/doze/res/values-ms-rMY/strings.xml b/doze/res/values-ms-rMY/strings.xml new file mode 100644 index 000000000..c023c0891 --- /dev/null +++ b/doze/res/values-ms-rMY/strings.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/doze/res/values-my-rMM/strings.xml b/doze/res/values-my-rMM/strings.xml new file mode 100644 index 000000000..c023c0891 --- /dev/null +++ b/doze/res/values-my-rMM/strings.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/doze/res/values-nb/strings.xml b/doze/res/values-nb/strings.xml new file mode 100644 index 000000000..fb4db6e9b --- /dev/null +++ b/doze/res/values-nb/strings.xml @@ -0,0 +1,34 @@ + + + + + Ambient visning + Våkne skjermen når du får varsler + Alltid aktivere + Lete etter sensor aktivitet etter at skjermen slår seg av + + Tilt sensor + Opp-plukking + Pulseringsnotifikasjon når telefonen er plukket opp + + Avstandsmåler + Håndvink + Pulseringsnotifikasjon ved håndvink + Lomme + Pulseringsnotifikasjon når telefonen er tatt opp av lommen + + OK + Hjelp + Disse funksjonene bruker sensor aktiviteter for å åpne en doze pulseringsnotifikasjon. Den valgte sensoren er bare slått på når du har fått et varsel, for å spare batteriet. Du kan også slå på så sensoren slår seg på når skjermen slår seg av, som vill tappe mer strøm. + diff --git a/doze/res/values-ne-rNP/strings.xml b/doze/res/values-ne-rNP/strings.xml new file mode 100644 index 000000000..c023c0891 --- /dev/null +++ b/doze/res/values-ne-rNP/strings.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/doze/res/values-nl/strings.xml b/doze/res/values-nl/strings.xml new file mode 100644 index 000000000..b803eebf6 --- /dev/null +++ b/doze/res/values-nl/strings.xml @@ -0,0 +1,34 @@ + + + + + Omgevingsdisplay + Scherm aan bij het ontvangen van meldingen + Altijd inschakelen + Sensoren gebruiken zodra het scherm uit is + + Hellingssensor + Oppakken + Meldingen laten knipperen bij oppakken + + Nabijheidssensor + Handgebaar + Meldingen laten knipperen bij handgebaar + Broekzak + Meldingen laten knipperen bij verwijderen uit broekzak + + OK + Help + Deze functies gebruiken sensoren om een Doze-puls te versturen. De gekozen sensor is alleen ingeschakeld als het apparaat een melding ontvangt. Dit helpt het accugebruik te verminderen. Er is ook een optie om de sensor te activeren zodra het scherm uitschakelt, maar dit leidt tot hoger accugebruik. + diff --git a/doze/res/values-oc-rFR/strings.xml b/doze/res/values-oc-rFR/strings.xml new file mode 100644 index 000000000..c023c0891 --- /dev/null +++ b/doze/res/values-oc-rFR/strings.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/doze/res/values-or-rIN/strings.xml b/doze/res/values-or-rIN/strings.xml new file mode 100644 index 000000000..c023c0891 --- /dev/null +++ b/doze/res/values-or-rIN/strings.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/doze/res/values-pa-rIN/strings.xml b/doze/res/values-pa-rIN/strings.xml new file mode 100644 index 000000000..c023c0891 --- /dev/null +++ b/doze/res/values-pa-rIN/strings.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/doze/res/values-pl/strings.xml b/doze/res/values-pl/strings.xml new file mode 100644 index 000000000..ec0b8c64f --- /dev/null +++ b/doze/res/values-pl/strings.xml @@ -0,0 +1,33 @@ + + + + + Aktywny wyświetlacz + Wybudź ekran po odebraniu powiadomienia + Zawsze włączone + Nasłuchiwanie zdarzeń z czujników zaraz po wyłączeniu ekranu + + Czujnik pochylenia + Pokaż powiadomienia, gdy urządzenie zostało podniesione + + Czujnik zbliżeniowy + Gest fali + Pokaż powiadomienia po geście fali + Wyjęcie z kieszeni + Pokaż powiadomienia po wyjęciu z kieszeni + + OK + Pomoc + Te funkcje używają czujników, aby pokazywać powiadomienia tylko w odpowiednim momencie. Czujniki są wykorzystywane, kiedy telefon odbierze powiadomienie. Pozwala to w oszczędzaniu baterii. Istnieje również możliwość, aby włączyć wybrany czujnik zaraz po wyłączeniu ekranu, spowoduje to większe zużycie baterii. + diff --git a/doze/res/values-pt-rBR/strings.xml b/doze/res/values-pt-rBR/strings.xml new file mode 100644 index 000000000..957fec16f --- /dev/null +++ b/doze/res/values-pt-rBR/strings.xml @@ -0,0 +1,34 @@ + + + + + Tela ambiente + Ligar a tela ao receber notificações + Sempre habilitado + Monitorar o sensor assim que a tela for desligada + + Sensor de inclinação + Pegar + Pulsar notificações ao pegar o dispositivo + + Sensor de proximidade + Acenar com a mão + Pulsar notificações ao acenar com a mão + Bolso + Pulsar notificações ao retirar do bolso + + OK + Ajuda + Esses recursos monitoram o sensor para que o dispositivo possa despertar do estado de repouso e pulsar notificações. O sensor escolhido só é habilitado quando o dispositivo recebe uma notificação, isso ajuda a reduzir o uso de bateria. Há também uma opção para ativar o sensor escolhido assim que a tela desliga, isso causará o maior uso da bateria. + diff --git a/doze/res/values-pt-rPT/strings.xml b/doze/res/values-pt-rPT/strings.xml new file mode 100644 index 000000000..688003d57 --- /dev/null +++ b/doze/res/values-pt-rPT/strings.xml @@ -0,0 +1,34 @@ + + + + + Visualização de ambiente + Ligar o ecrã quando receber notificações + Permitir sempre + Prestar atenção a eventos dos sensores assim que o ecrã é desligado + + Sensor de inclinação + Pegar + Mostrar as notificações ao pegar no dispositivo + + Sensor de proximidade + Passar a mão + Mostrar notificações ao passar a mão + Bolso + Mostrar notificações ao retirar do bolso + + OK + Ajuda + Estes recursos utilizam eventos de sensores para mostrarem notificações enquanto o dispositivo está em repouso. O sensor escolhido só é ativado quando o dispositivo recebe uma notificação, o que ajuda a reduzir a utilização da bateria. Há também uma opção para ativar o sensor escolhido assim que o ecrã se desliga, o que resultará numa maior utilização da bateria. + diff --git a/doze/res/values-rm/strings.xml b/doze/res/values-rm/strings.xml new file mode 100644 index 000000000..c023c0891 --- /dev/null +++ b/doze/res/values-rm/strings.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/doze/res/values-ro/strings.xml b/doze/res/values-ro/strings.xml new file mode 100644 index 000000000..c023c0891 --- /dev/null +++ b/doze/res/values-ro/strings.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/doze/res/values-ru/strings.xml b/doze/res/values-ru/strings.xml new file mode 100644 index 000000000..dce20e48e --- /dev/null +++ b/doze/res/values-ru/strings.xml @@ -0,0 +1,34 @@ + + + + + Индикация событий + Включать экран при получении уведомлений + Всегда включено + Прослушивать события сенсора сразу после отключения экрана + + Датчик наклона + Поднять + Отображать уведомления при поднятии устройства + + Датчик приближения + Взмах + Проведите ладонью над экраном для просмотра уведомлений + Карман + Отображать уведомления при извлечении устройства из кармана + + OK + Информация + Эти функции используют события датчиков для отображения уведомлений. Датчик проверяется только при поступлении нового уведомления, что помогает сэкономить заряд батареи. Можно активировать включение датчика сразу при отключении экрана устройства, однако это может ускорить разряд батареи. + diff --git a/doze/res/values-si-rLK/strings.xml b/doze/res/values-si-rLK/strings.xml new file mode 100644 index 000000000..c023c0891 --- /dev/null +++ b/doze/res/values-si-rLK/strings.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/doze/res/values-sk/strings.xml b/doze/res/values-sk/strings.xml new file mode 100644 index 000000000..c023c0891 --- /dev/null +++ b/doze/res/values-sk/strings.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/doze/res/values-sl/strings.xml b/doze/res/values-sl/strings.xml new file mode 100644 index 000000000..690ae7cb6 --- /dev/null +++ b/doze/res/values-sl/strings.xml @@ -0,0 +1,34 @@ + + + + + Okoliški zaslon + Zbudi zaslon ob prejemu obvestila + Vedno omogoči + Poslušaj za dogodke tipal, takoj ko se zaslon izklopi + + Tipalo nagiba + Dvig + Utripaj obvestila ob dvigu naprave + + Tipalo bližine + Mahanje z roko + Utripaj obvestila ob mahanju z roko + Žep + Utripaj obvestila ob odstranitvi iz žepa + + V redu + Pomoč + Te značilnosti uporabljajo dogodke tipal za sprožitev utripanja obvestil ob spanju. Izbrano tipalo se omogoči samo, ko naprava prejme obvestilo. To pomaga zmanjšati porabo energije. Obstaja tudi možnost omogočanja izbranega tipala, takoj ko se zaslon izklopi, vendar bo to povzročilo večjo porabo energije. + diff --git a/doze/res/values-sq-rAL/strings.xml b/doze/res/values-sq-rAL/strings.xml new file mode 100644 index 000000000..c023c0891 --- /dev/null +++ b/doze/res/values-sq-rAL/strings.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/doze/res/values-sr/strings.xml b/doze/res/values-sr/strings.xml new file mode 100644 index 000000000..5ab93dc8f --- /dev/null +++ b/doze/res/values-sr/strings.xml @@ -0,0 +1,34 @@ + + + + + Амбијент приказ + Пробуди екран кад добијеш обавештење + Увек омогући + Праћење сензора чим се екран искључи + + Тилт сензор + Купљење + Пулсно обавештење када је уређај покупљен + + Сензор близине + Покрет руком + Пулсно обавештење при покрету руком + Џеп + Пулсно обавештење при уклањању из џепа + + У реду + Помоћ + Ова функција користи активирање сензора да покрене пулсно обавештење. Изабрани сензор је омогућен једино када уређај прима обавештење, то помаже смањењу потрожње батерије. Ту је и опција омогућења изабраног сензора чим се екран искључи, то ће узроковати већој потрожњи батерије. + diff --git a/doze/res/values-sv/strings.xml b/doze/res/values-sv/strings.xml new file mode 100644 index 000000000..225a2b8bf --- /dev/null +++ b/doze/res/values-sv/strings.xml @@ -0,0 +1,25 @@ + + + + + + Plocka upp + Pulsera aviseringarna när enheten plockas upp + + Närhetscensor + Pulsera aviseringar när telefonen tas upp ur fickan + + OK + Hjälp + diff --git a/doze/res/values-sw/strings.xml b/doze/res/values-sw/strings.xml new file mode 100644 index 000000000..c023c0891 --- /dev/null +++ b/doze/res/values-sw/strings.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/doze/res/values-ta-rIN/strings.xml b/doze/res/values-ta-rIN/strings.xml new file mode 100644 index 000000000..c023c0891 --- /dev/null +++ b/doze/res/values-ta-rIN/strings.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/doze/res/values-te-rIN/strings.xml b/doze/res/values-te-rIN/strings.xml new file mode 100644 index 000000000..c023c0891 --- /dev/null +++ b/doze/res/values-te-rIN/strings.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/doze/res/values-th/strings.xml b/doze/res/values-th/strings.xml new file mode 100644 index 000000000..c023c0891 --- /dev/null +++ b/doze/res/values-th/strings.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/doze/res/values-tr/strings.xml b/doze/res/values-tr/strings.xml new file mode 100644 index 000000000..c023c0891 --- /dev/null +++ b/doze/res/values-tr/strings.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/doze/res/values-ug/strings.xml b/doze/res/values-ug/strings.xml new file mode 100644 index 000000000..c023c0891 --- /dev/null +++ b/doze/res/values-ug/strings.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/doze/res/values-uk/strings.xml b/doze/res/values-uk/strings.xml new file mode 100644 index 000000000..c023c0891 --- /dev/null +++ b/doze/res/values-uk/strings.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/doze/res/values-ur-rPK/strings.xml b/doze/res/values-ur-rPK/strings.xml new file mode 100644 index 000000000..c023c0891 --- /dev/null +++ b/doze/res/values-ur-rPK/strings.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/doze/res/values-uz-rUZ/strings.xml b/doze/res/values-uz-rUZ/strings.xml new file mode 100644 index 000000000..c023c0891 --- /dev/null +++ b/doze/res/values-uz-rUZ/strings.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/doze/res/values-vi/strings.xml b/doze/res/values-vi/strings.xml new file mode 100644 index 000000000..c023c0891 --- /dev/null +++ b/doze/res/values-vi/strings.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/doze/res/values-zh-rCN/strings.xml b/doze/res/values-zh-rCN/strings.xml new file mode 100644 index 000000000..6d8f43754 --- /dev/null +++ b/doze/res/values-zh-rCN/strings.xml @@ -0,0 +1,34 @@ + + + + + 环境显示 + 当接收到通知时唤醒屏幕 + 始终启用 + 当屏幕关闭后立即监听传感器事件 + + 倾斜传感器 + 拿起 + 当拿起设备时闪烁通知灯 + + 距离传感器 + 挥手 + 挥手时闪烁通知呼吸灯 + 口袋 + 从口袋中拿出时闪烁通知呼吸灯 + + 确定 + 帮助 + 这些功能使用传感器启用打盹通知指示灯,选择的传感器将仅在设备收到通知时开启,这将有助于优化电池用量。还有一个选项是当屏幕关闭后立即启用传感器,这会导致更多的电池用量。 + diff --git a/doze/res/values-zh-rHK/strings.xml b/doze/res/values-zh-rHK/strings.xml new file mode 100644 index 000000000..c023c0891 --- /dev/null +++ b/doze/res/values-zh-rHK/strings.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/doze/res/values-zh-rTW/strings.xml b/doze/res/values-zh-rTW/strings.xml new file mode 100644 index 000000000..c023c0891 --- /dev/null +++ b/doze/res/values-zh-rTW/strings.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/doze/res/values-zu/strings.xml b/doze/res/values-zu/strings.xml new file mode 100644 index 000000000..c023c0891 --- /dev/null +++ b/doze/res/values-zu/strings.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/doze/res/values/strings.xml b/doze/res/values/strings.xml new file mode 100644 index 000000000..964319054 --- /dev/null +++ b/doze/res/values/strings.xml @@ -0,0 +1,38 @@ + + + + + Ambient display + Wake screen when you receive notifications + + Always enable + Listen for sensor events as soon as the screen turns off + + + Tilt sensor + Pick up + Pulse notifications when device is picked up + + + Proximity sensor + Hand wave + Pulse notifications on hand wave + Pocket + Pulse notifications on removal from pocket + + + OK + Help + These features use sensor events to launch a doze notification pulse. The chosen sensor is only enabled when the device receives a notification, this helps to reduce battery usage. There is also an option to enable the chosen sensor as soon as the screen turns off, this will cause higher battery usage. + diff --git a/doze/res/xml/doze_settings.xml b/doze/res/xml/doze_settings.xml new file mode 100644 index 000000000..09e27b509 --- /dev/null +++ b/doze/res/xml/doze_settings.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doze/src/com/cyanogenmod/settings/doze/BootCompletedReceiver.java b/doze/src/com/cyanogenmod/settings/doze/BootCompletedReceiver.java new file mode 100644 index 000000000..e1b2b5053 --- /dev/null +++ b/doze/src/com/cyanogenmod/settings/doze/BootCompletedReceiver.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2015 The CyanogenMod Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.cyanogenmod.settings.doze; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.util.Log; + +public class BootCompletedReceiver extends BroadcastReceiver { + + private static final boolean DEBUG = false; + private static final String TAG = "ZukDoze"; + + @Override + public void onReceive(final Context context, Intent intent) { + if (Utils.isDozeEnabled(context) && Utils.sensorsEnabled(context)) { + if (DEBUG) Log.d(TAG, "Starting service"); + Utils.startService(context); + } + } + +} diff --git a/doze/src/com/cyanogenmod/settings/doze/DozeService.java b/doze/src/com/cyanogenmod/settings/doze/DozeService.java new file mode 100644 index 000000000..354d97f1b --- /dev/null +++ b/doze/src/com/cyanogenmod/settings/doze/DozeService.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2015 The CyanogenMod Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.cyanogenmod.settings.doze; + +import android.app.Service; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.os.IBinder; +import android.util.Log; + +public class DozeService extends Service { + private static final String TAG = "DozeService"; + private static final boolean DEBUG = false; + + private ProximitySensor mProximitySensor; + private TiltSensor mTiltSensor; + + @Override + public void onCreate() { + if (DEBUG) Log.d(TAG, "Creating service"); + mProximitySensor = new ProximitySensor(this); + mTiltSensor = new TiltSensor(this); + + IntentFilter screenStateFilter = new IntentFilter(Intent.ACTION_SCREEN_ON); + screenStateFilter.addAction(Intent.ACTION_SCREEN_OFF); + registerReceiver(mScreenStateReceiver, screenStateFilter); + } + + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + if (DEBUG) Log.d(TAG, "Starting service"); + return START_STICKY; + } + + @Override + public void onDestroy() { + if (DEBUG) Log.d(TAG, "Destroying service"); + super.onDestroy(); + this.unregisterReceiver(mScreenStateReceiver); + mProximitySensor.disable(); + mTiltSensor.disable(); + } + + @Override + public IBinder onBind(Intent intent) { + return null; + } + + private void onDisplayOn() { + if (DEBUG) Log.d(TAG, "Display on"); + if (Utils.pickUpEnabled(this)) { + mTiltSensor.disable(); + } + if (Utils.handwaveGestureEnabled(this) || + Utils.pocketGestureEnabled(this)) { + mProximitySensor.disable(); + } + } + + private void onDisplayOff() { + if (DEBUG) Log.d(TAG, "Display off"); + if (Utils.pickUpEnabled(this) && Utils.tiltAlwaysEnabled(this)) { + mTiltSensor.enable(); + } + if (Utils.proximityAlwaysEnabled(this) && (Utils.handwaveGestureEnabled(this) || + Utils.pocketGestureEnabled(this))) { + mProximitySensor.enable(); + } + } + + private BroadcastReceiver mScreenStateReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) { + onDisplayOn(); + } else if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) { + onDisplayOff(); + } + } + }; +} diff --git a/doze/src/com/cyanogenmod/settings/doze/DozeSettings.java b/doze/src/com/cyanogenmod/settings/doze/DozeSettings.java new file mode 100644 index 000000000..d2c408ae0 --- /dev/null +++ b/doze/src/com/cyanogenmod/settings/doze/DozeSettings.java @@ -0,0 +1,178 @@ +/* + * Copyright (C) 2015 The CyanogenMod Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.cyanogenmod.settings.doze; + +import android.app.ActionBar; +import android.app.Activity; +import android.app.AlertDialog; +import android.app.Dialog; +import android.app.DialogFragment; +import android.content.Context; +import android.content.DialogInterface; +import android.content.SharedPreferences; +import android.os.Bundle; +import android.preference.Preference; +import android.preference.Preference.OnPreferenceChangeListener; +import android.preference.PreferenceActivity; +import android.preference.PreferenceScreen; +import android.preference.SwitchPreference; +import android.provider.Settings; +import android.view.Menu; +import android.view.MenuItem; + +public class DozeSettings extends PreferenceActivity implements OnPreferenceChangeListener { + + private Context mContext; + private SharedPreferences mPreferences; + + private SwitchPreference mAmbientDisplayPreference; + private SwitchPreference mPickUpPreference; + private SwitchPreference mTiltAlwaysPreference; + private SwitchPreference mHandwavePreference; + private SwitchPreference mPocketPreference; + private SwitchPreference mProximityAlwaysPreference; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + addPreferencesFromResource(R.xml.doze_settings); + mContext = getApplicationContext(); + boolean dozeEnabled = Utils.isDozeEnabled(mContext); + + // get shared preference + mPreferences = mContext.getSharedPreferences("doze_settings", Activity.MODE_PRIVATE); + if (savedInstanceState == null && !mPreferences.getBoolean("first_help_shown", false)) { + showHelp(); + } + + mAmbientDisplayPreference = + (SwitchPreference) findPreference(Utils.AMBIENT_DISPLAY_KEY); + // Read from DOZE_ENABLED secure setting + mAmbientDisplayPreference.setChecked(dozeEnabled); + mAmbientDisplayPreference.setOnPreferenceChangeListener(this); + + mTiltAlwaysPreference = + (SwitchPreference) findPreference(Utils.TILT_ALWAYS_KEY); + mTiltAlwaysPreference.setOnPreferenceChangeListener(this); + + mPickUpPreference = + (SwitchPreference) findPreference(Utils.PICK_UP_KEY); + mPickUpPreference.setOnPreferenceChangeListener(this); + + mHandwavePreference = + (SwitchPreference) findPreference(Utils.GESTURE_HAND_WAVE_KEY); + mHandwavePreference.setOnPreferenceChangeListener(this); + + mPocketPreference = + (SwitchPreference) findPreference(Utils.GESTURE_POCKET_KEY); + mPocketPreference.setOnPreferenceChangeListener(this); + + mProximityAlwaysPreference = + (SwitchPreference) findPreference(Utils.PROXIMITY_ALWAYS_KEY); + mProximityAlwaysPreference.setOnPreferenceChangeListener(this); + + final ActionBar actionBar = getActionBar(); + actionBar.setDisplayHomeAsUpEnabled(true); + + updateAlwaysEnabledPreference(); + } + + @Override + protected void onResume() { + super.onResume(); + updateAlwaysEnabledPreference(); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + if (item.getItemId() == android.R.id.home) { + onBackPressed(); + return true; + } + return false; + } + + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) { + final String key = preference.getKey(); + final boolean value = (Boolean) newValue; + if (Utils.AMBIENT_DISPLAY_KEY.equals(key)) { + mAmbientDisplayPreference.setChecked(value); + Utils.enableDoze(value, mContext); + return true; + } else if (Utils.PICK_UP_KEY.equals(key)) { + mPickUpPreference.setChecked(value); + updateAlwaysEnabledPreference(); + Utils.startService(mContext); + return true; + } else if (Utils.TILT_ALWAYS_KEY.equals(key)) { + mTiltAlwaysPreference.setChecked(value); + return true; + } else if (Utils.GESTURE_HAND_WAVE_KEY.equals(key)) { + mHandwavePreference.setChecked(value); + updateAlwaysEnabledPreference(); + Utils.startService(mContext); + return true; + } else if (Utils.GESTURE_POCKET_KEY.equals(key)) { + mPocketPreference.setChecked(value); + updateAlwaysEnabledPreference(); + Utils.startService(mContext); + return true; + } else if (Utils.PROXIMITY_ALWAYS_KEY.equals(key)) { + mProximityAlwaysPreference.setChecked(value); + return true; + } + return false; + } + + public static class HelpDialogFragment extends DialogFragment { + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + return new AlertDialog.Builder(getActivity()) + .setTitle(R.string.doze_settings_help_title) + .setMessage(R.string.doze_settings_help_text) + .setNegativeButton(R.string.dlg_ok, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + dialog.cancel(); + } + }) + .create(); + } + + @Override + public void onCancel(DialogInterface dialog) { + getActivity().getSharedPreferences("doze_settings", Activity.MODE_PRIVATE) + .edit() + .putBoolean("first_help_shown", true) + .commit(); + } + } + + private void showHelp() { + HelpDialogFragment fragment = new HelpDialogFragment(); + fragment.show(getFragmentManager(), "help_dialog"); + } + + private void updateAlwaysEnabledPreference() { + boolean tiltEnabled = Utils.pickUpEnabled(mContext); + boolean proximityEnabled = Utils.handwaveGestureEnabled(mContext) + || Utils.pocketGestureEnabled(mContext); + mTiltAlwaysPreference.setEnabled(tiltEnabled); + mProximityAlwaysPreference.setEnabled(proximityEnabled); + } +} diff --git a/doze/src/com/cyanogenmod/settings/doze/ProximitySensor.java b/doze/src/com/cyanogenmod/settings/doze/ProximitySensor.java new file mode 100644 index 000000000..0f62b11b5 --- /dev/null +++ b/doze/src/com/cyanogenmod/settings/doze/ProximitySensor.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2015 The CyanogenMod Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.cyanogenmod.settings.doze; + +import android.content.Context; +import android.hardware.Sensor; +import android.hardware.SensorEvent; +import android.hardware.SensorEventListener; +import android.hardware.SensorManager; +import android.util.Log; + +public class ProximitySensor implements SensorEventListener { + + private static final boolean DEBUG = false; + private static final String TAG = "ProximitySensor"; + + private static final int POCKET_DELTA_NS = 1000 * 1000 * 1000; + + private SensorManager mSensorManager; + private Sensor mSensor; + private Context mContext; + + private boolean mSawNear = false; + private long mInPocketTime = 0; + + public ProximitySensor(Context context) { + mContext = context; + mSensorManager = (SensorManager) + mContext.getSystemService(Context.SENSOR_SERVICE); + mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY); + } + + @Override + public void onSensorChanged(SensorEvent event) { + boolean isNear = event.values[0] < mSensor.getMaximumRange(); + if (mSawNear && !isNear) { + if (shouldPulse(event.timestamp)) { + Utils.launchDozePulse(mContext); + } + } else { + mInPocketTime = event.timestamp; + } + mSawNear = isNear; + } + + private boolean shouldPulse(long timestamp) { + long delta = timestamp - mInPocketTime; + + if (Utils.handwaveGestureEnabled(mContext) + && Utils.pocketGestureEnabled(mContext)) { + return true; + } else if (Utils.handwaveGestureEnabled(mContext) + && !Utils.pocketGestureEnabled(mContext)) { + return delta < POCKET_DELTA_NS; + } else if (!Utils.handwaveGestureEnabled(mContext) + && Utils.pocketGestureEnabled(mContext)) { + return delta >= POCKET_DELTA_NS; + } + return false; + } + + @Override + public void onAccuracyChanged(Sensor sensor, int accuracy) { + /* Empty */ + } + + protected void enable() { + if (DEBUG) Log.d(TAG, "Enabling"); + mSensorManager.registerListener(this, mSensor, + SensorManager.SENSOR_DELAY_NORMAL); + } + + protected void disable() { + if (DEBUG) Log.d(TAG, "Disabling"); + mSensorManager.unregisterListener(this, mSensor); + } +} diff --git a/doze/src/com/cyanogenmod/settings/doze/TiltSensor.java b/doze/src/com/cyanogenmod/settings/doze/TiltSensor.java new file mode 100644 index 000000000..443a10d78 --- /dev/null +++ b/doze/src/com/cyanogenmod/settings/doze/TiltSensor.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2015 The CyanogenMod Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.cyanogenmod.settings.doze; + +import android.content.Context; +import android.hardware.Sensor; +import android.hardware.SensorEvent; +import android.hardware.SensorEventListener; +import android.hardware.SensorManager; +import android.os.PowerManager; +import android.os.PowerManager.WakeLock; +import android.os.SystemClock; +import android.util.Log; + +public class TiltSensor implements SensorEventListener { + + private static final boolean DEBUG = false; + private static final String TAG = "TiltSensor"; + + private static final int SENSOR_WAKELOCK_DURATION = 200; + private static final int BATCH_LATENCY_IN_MS = 100; + private static final int MIN_PULSE_INTERVAL_MS = 2500; + + private PowerManager mPowerManager; + private SensorManager mSensorManager; + private Sensor mSensor; + private WakeLock mSensorWakeLock; + private Context mContext; + + private long mEntryTimestamp; + + public TiltSensor(Context context) { + mContext = context; + mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); + mSensorManager = (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE); + mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_TILT_DETECTOR); + mSensorWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, + "SensorWakeLock"); + } + + @Override + public void onSensorChanged(SensorEvent event) { + if (DEBUG) Log.d(TAG, "Got sensor event: " + event.values[0]); + + long delta = SystemClock.elapsedRealtime() - mEntryTimestamp; + if (delta < MIN_PULSE_INTERVAL_MS) { + return; + } else { + mEntryTimestamp = SystemClock.elapsedRealtime(); + } + + if (event.values[0] == 1) { + Utils.launchDozePulse(mContext); + } + } + + @Override + public void onAccuracyChanged(Sensor sensor, int accuracy) { + /* Empty */ + } + + protected void enable() { + if (DEBUG) Log.d(TAG, "Enabling"); + mSensorManager.registerListener(this, mSensor, + SensorManager.SENSOR_DELAY_NORMAL, BATCH_LATENCY_IN_MS * 1000); + mEntryTimestamp = SystemClock.elapsedRealtime(); + } + + protected void disable() { + if (DEBUG) Log.d(TAG, "Disabling"); + mSensorManager.unregisterListener(this, mSensor); + } +} diff --git a/doze/src/com/cyanogenmod/settings/doze/Utils.java b/doze/src/com/cyanogenmod/settings/doze/Utils.java new file mode 100644 index 000000000..bdc696b4e --- /dev/null +++ b/doze/src/com/cyanogenmod/settings/doze/Utils.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2015 The CyanogenMod Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.cyanogenmod.settings.doze; + +import android.app.ActivityManager; +import android.app.ActivityManager.RunningServiceInfo; +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.os.UserHandle; +import android.preference.PreferenceManager; +import android.provider.Settings; +import android.util.Log; + +public final class Utils { + + private static final String TAG = "DozeUtils"; + private static final boolean DEBUG = false; + + private static final String DOZE_INTENT = "com.android.systemui.doze.pulse"; + + protected static final String AMBIENT_DISPLAY_KEY = "ambient_display"; + protected static final String PICK_UP_KEY = "pick_up"; + protected static final String TILT_ALWAYS_KEY = "tilt_always"; + protected static final String GESTURE_HAND_WAVE_KEY = "gesture_hand_wave"; + protected static final String GESTURE_POCKET_KEY = "gesture_pocket"; + protected static final String PROXIMITY_ALWAYS_KEY = "proximity_always"; + + protected static void startService(Context context) { + if (DEBUG) Log.d(TAG, "Starting service"); + context.startService(new Intent(context, DozeService.class)); + } + + protected static void stopService(Context context) { + if (DEBUG) Log.d(TAG, "Stopping service"); + context.stopService(new Intent(context, DozeService.class)); + } + + protected static boolean isDozeEnabled(Context context) { + return Settings.Secure.getInt(context.getContentResolver(), + Settings.Secure.DOZE_ENABLED, 1) != 0; + } + + protected static boolean enableDoze(boolean enable, Context context) { + boolean dozeEnabled = Settings.Secure.putInt(context.getContentResolver(), + Settings.Secure.DOZE_ENABLED, enable ? 1 : 0); + if (enable) { + startService(context); + } else { + stopService(context); + } + return dozeEnabled; + } + + protected static void launchDozePulse(Context context) { + if (DEBUG) Log.d(TAG, "Launch doze pulse"); + context.sendBroadcastAsUser(new Intent(DOZE_INTENT), + new UserHandle(UserHandle.USER_CURRENT)); + } + + protected static boolean pickUpEnabled(Context context) { + return PreferenceManager.getDefaultSharedPreferences(context) + .getBoolean(PICK_UP_KEY, false); + } + + protected static boolean tiltAlwaysEnabled(Context context) { + return PreferenceManager.getDefaultSharedPreferences(context) + .getBoolean(TILT_ALWAYS_KEY, false); + } + + protected static boolean handwaveGestureEnabled(Context context) { + return PreferenceManager.getDefaultSharedPreferences(context) + .getBoolean(GESTURE_HAND_WAVE_KEY, false); + } + + protected static boolean pocketGestureEnabled(Context context) { + return PreferenceManager.getDefaultSharedPreferences(context) + .getBoolean(GESTURE_POCKET_KEY, false); + } + + protected static boolean proximityAlwaysEnabled(Context context) { + return PreferenceManager.getDefaultSharedPreferences(context) + .getBoolean(PROXIMITY_ALWAYS_KEY, false); + } + + protected static boolean sensorsEnabled(Context context) { + return pickUpEnabled(context) || handwaveGestureEnabled(context) + || pocketGestureEnabled(context); + } +} diff --git a/extract-files.sh b/extract-files.sh new file mode 100755 index 000000000..2ed934d91 --- /dev/null +++ b/extract-files.sh @@ -0,0 +1,59 @@ +#!/bin/bash + +set -e + +export DEVICE=z2_plus +export VENDOR=zuk + +function extract() { + for FILE in `egrep -v '(^#|^$)' $1`; do + OLDIFS=$IFS IFS=":" PARSING_ARRAY=($FILE) IFS=$OLDIFS + FILE=`echo ${PARSING_ARRAY[0]} | sed -e "s/^-//g"` + DEST=${PARSING_ARRAY[1]} + if [ -z $DEST ]; then + DEST=$FILE + fi + echo "Extracting /system/$FILE ..." + DIR=`dirname $FILE` + if [ ! -d $2/$DIR ]; then + mkdir -p $2/$DIR + fi + if [ "$SRC" = "adb" ]; then + # Try CM target first + adb pull /system/$DEST $2/$DEST + # if file does not exist try OEM target + if [ "$?" != "0" ]; then + adb pull /system/$FILE $2/$DEST + fi + else + cp $SRC/system/$FILE $2/$DEST + # if file dot not exist try destination + if [ "$?" != "0" ]; then + cp $SRC/system/$DEST $2/$DEST + fi + fi + done +} + +if [ $# -eq 0 ]; then + SRC=adb +else + if [ $# -eq 1 ]; then + SRC=$1 + else + echo "$0: bad number of arguments" + echo "" + echo "usage: $0 [PATH_TO_EXPANDED_ROM]" + echo "" + echo "If PATH_TO_EXPANDED_ROM is not specified, blobs will be extracted from" + echo "the device using adb pull." + exit 1 + fi +fi + +BASE=../../../vendor/$VENDOR/$DEVICE/proprietary +rm -rf $BASE/* + +extract ../../$VENDOR/$DEVICE/proprietary-files.txt $BASE + +./setup-makefiles.sh diff --git a/gps/Android.mk b/gps/Android.mk new file mode 100644 index 000000000..ca5347d95 --- /dev/null +++ b/gps/Android.mk @@ -0,0 +1,19 @@ +# +# Copyright (C) 2016 The CyanogenMod Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +LOCAL_PATH := $(call my-dir) + +include $(call all-subdir-makefiles,$(LOCAL_PATH)) diff --git a/gps/CleanSpec.mk b/gps/CleanSpec.mk new file mode 100644 index 000000000..dd1849db3 --- /dev/null +++ b/gps/CleanSpec.mk @@ -0,0 +1,50 @@ +# Copyright (C) 2007 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# If you don't need to do a full clean build but would like to touch +# a file or delete some intermediate files, add a clean step to the end +# of the list. These steps will only be run once, if they haven't been +# run before. +# +# E.g.: +# $(call add-clean-step, touch -c external/sqlite/sqlite3.h) +# $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libz_intermediates) +# +# Always use "touch -c" and "rm -f" or "rm -rf" to gracefully deal with +# files that are missing or have been moved. +# +# Use $(PRODUCT_OUT) to get to the "out/target/product/blah/" directory. +# Use $(OUT_DIR) to refer to the "out" directory. +# +# If you need to re-do something that's already mentioned, just copy +# the command and add it to the bottom of the list. E.g., if a change +# that you made last week required touching a file and a change you +# made today requires touching the same file, just copy the old +# touch step and add it to the end of the list. +# +# ************************************************ +# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST +# ************************************************ + +# For example: +#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/AndroidTests_intermediates) +#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/core_intermediates) +#$(call add-clean-step, find $(OUT_DIR) -type f -name "IGTalkSession*" -print0 | xargs -0 rm -f) +#$(call add-clean-step, rm -rf $(PRODUCT_OUT)/data/*) + +# ************************************************ +# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST +# ************************************************ +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libloc_api*) diff --git a/gps/Makefile.am b/gps/Makefile.am new file mode 100644 index 000000000..f374a5c5d --- /dev/null +++ b/gps/Makefile.am @@ -0,0 +1,10 @@ +# Makefile.am - Automake script for gps loc_api +# + +ACLOCAL_AMFLAGS = -I m4 + +SUBDIRS = utils loc_api/libloc_api_50001 loc_api/loc_api_v02 + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = loc-api.pc +EXTRA_DIST = $(pkgconfig_DATA) diff --git a/gps/configure.ac b/gps/configure.ac new file mode 100644 index 000000000..dca18a191 --- /dev/null +++ b/gps/configure.ac @@ -0,0 +1,85 @@ +# configure.ac -- Autoconf script for gps loc_api +# +# Process this file with autoconf to produce a configure script + +# Requires autoconf tool later than 2.61 +AC_PREREQ(2.61) +# Initialize the gps loc_api package version 1.0.0 +AC_INIT([loc-api],1.0.0) +# Does not strictly follow GNU Coding standards +AM_INIT_AUTOMAKE([foreign]) +# Disables auto rebuilding of configure, Makefile.ins +AM_MAINTAINER_MODE +# Verifies the --srcdir is correct by checking for the path +AC_CONFIG_SRCDIR([utils/loc_cfg.cpp]) +# defines some macros variable to be included by source +AC_CONFIG_HEADERS([config.h]) +AC_CONFIG_MACRO_DIR([m4]) + +# Checks for programs. +AC_PROG_LIBTOOL +AC_PROG_CXX +AC_PROG_CC +AM_PROG_CC_C_O +AC_PROG_AWK +AC_PROG_CPP +AC_PROG_INSTALL +AC_PROG_LN_S +AC_PROG_MAKE_SET +PKG_PROG_PKG_CONFIG + +# Checks for libraries. +PKG_CHECK_MODULES([QMIF], [qmi-framework]) +AC_SUBST([QMIF_CFLAGS]) +AC_SUBST([QMIF_LIBS]) + +AC_ARG_WITH([libhardware_includes], + AC_HELP_STRING([--with-libhardware-includes=@<:@dir@:>@], + [Specify the location of the libhardware headers]), + [libhardware_incdir=$withval], + with_libhardware_includes=no) + +if test "x$with_libhardware_includes" != "xno"; then + CPPFLAGS="${CPPFLAGS} -I${libhardware_incdir}" +fi + +AC_ARG_WITH([core_includes], + AC_HELP_STRING([--with-core-includes=@<:@dir@:>@], + [Specify the location of the core headers]), + [core_incdir=$withval], + with_core_includes=no) + +if test "x$with_core_includes" != "xno"; then + CPPFLAGS="${CPPFLAGS} -I${core_incdir}" +fi + +AC_SUBST([CPPFLAGS]) + +AC_ARG_WITH([glib], + AC_HELP_STRING([--with-glib], + [enable glib, building HLOS systems which use glib])) + +if (test "x${with_glib}" = "xyes"); then + AC_DEFINE(ENABLE_USEGLIB, 1, [Define if HLOS systems uses glib]) + PKG_CHECK_MODULES(GTHREAD, gthread-2.0 >= 2.16, dummy=yes, + AC_MSG_ERROR(GThread >= 2.16 is required)) + PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.16, dummy=yes, + AC_MSG_ERROR(GLib >= 2.16 is required)) + GLIB_CFLAGS="$GLIB_CFLAGS $GTHREAD_CFLAGS" + GLIB_LIBS="$GLIB_LIBS $GTHREAD_LIBS" + + AC_SUBST(GLIB_CFLAGS) + AC_SUBST(GLIB_LIBS) +fi + +AM_CONDITIONAL(USE_GLIB, test "x${with_glib}" = "xyes") + +AC_CONFIG_FILES([ \ + Makefile \ + utils/Makefile \ + loc_api/libloc_api_50001/Makefile \ + loc_api/loc_api_v02/Makefile \ + loc-api.pc \ + ]) + +AC_OUTPUT diff --git a/gps/core/Android.mk b/gps/core/Android.mk new file mode 100644 index 000000000..35a267f5e --- /dev/null +++ b/gps/core/Android.mk @@ -0,0 +1,56 @@ +ifneq ($(BUILD_TINY_ANDROID),true) + +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE := libloc_core +LOCAL_MODULE_OWNER := qcom + +LOCAL_MODULE_TAGS := optional + +ifeq ($(TARGET_DEVICE),apq8026_lw) +LOCAL_CFLAGS += -DPDK_FEATURE_SET +else ifeq ($(BOARD_VENDOR_QCOM_LOC_PDK_FEATURE_SET),true) +LOCAL_CFLAGS += -DPDK_FEATURE_SET +endif + +LOCAL_SHARED_LIBRARIES := \ + libutils \ + libcutils \ + libgps.utils \ + libdl + +LOCAL_SRC_FILES += \ + LocApiBase.cpp \ + LocAdapterBase.cpp \ + ContextBase.cpp \ + LocDualContext.cpp \ + loc_core_log.cpp + +LOCAL_CFLAGS += \ + -fno-short-enums \ + -D_ANDROID_ + +LOCAL_C_INCLUDES:= \ + $(TARGET_OUT_HEADERS)/gps.utils \ + $(TARGET_OUT_HEADERS)/libflp + +LOCAL_COPY_HEADERS_TO:= libloc_core/ +LOCAL_COPY_HEADERS:= \ + LocApiBase.h \ + LocAdapterBase.h \ + ContextBase.h \ + LocDualContext.h \ + LBSProxyBase.h \ + UlpProxyBase.h \ + gps_extended_c.h \ + gps_extended.h \ + loc_core_log.h \ + LocAdapterProxyBase.h + +LOCAL_PRELINK_MODULE := false + +include $(BUILD_SHARED_LIBRARY) + +endif # not BUILD_TINY_ANDROID diff --git a/gps/core/ContextBase.cpp b/gps/core/ContextBase.cpp new file mode 100644 index 000000000..9f6c4aabb --- /dev/null +++ b/gps/core/ContextBase.cpp @@ -0,0 +1,114 @@ +/* Copyright (c) 2011-2014, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#define LOG_NDDEBUG 0 +#define LOG_TAG "LocSvc_CtxBase" + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace loc_core { + +LBSProxyBase* ContextBase::getLBSProxy(const char* libName) +{ + LBSProxyBase* proxy = NULL; + LOC_LOGD("%s:%d]: getLBSProxy libname: %s\n", __func__, __LINE__, libName); + void* lib = dlopen(libName, RTLD_NOW); + + if ((void*)NULL != lib) { + getLBSProxy_t* getter = (getLBSProxy_t*)dlsym(lib, "getLBSProxy"); + if (NULL != getter) { + proxy = (*getter)(); + } + } + if (NULL == proxy) { + proxy = new LBSProxyBase(); + } + LOC_LOGD("%s:%d]: Exiting\n", __func__, __LINE__); + return proxy; +} + +LocApiBase* ContextBase::createLocApi(LOC_API_ADAPTER_EVENT_MASK_T exMask) +{ + LocApiBase* locApi = NULL; + + // first if can not be MPQ + if (TARGET_MPQ != loc_get_target()) { + if (NULL == (locApi = mLBSProxy->getLocApi(mMsgTask, exMask, this))) { + void *handle = NULL; + //try to see if LocApiV02 is present + if((handle = dlopen("libloc_api_v02.so", RTLD_NOW)) != NULL) { + LOC_LOGD("%s:%d]: libloc_api_v02.so is present", __func__, __LINE__); + getLocApi_t* getter = (getLocApi_t*)dlsym(handle, "getLocApi"); + if(getter != NULL) { + LOC_LOGD("%s:%d]: getter is not NULL for LocApiV02", __func__, __LINE__); + locApi = (*getter)(mMsgTask, exMask, this); + } + } + // only RPC is the option now + else { + LOC_LOGD("%s:%d]: libloc_api_v02.so is NOT present. Trying RPC", + __func__, __LINE__); + handle = dlopen("libloc_api-rpc-qc.so", RTLD_NOW); + if (NULL != handle) { + getLocApi_t* getter = (getLocApi_t*)dlsym(handle, "getLocApi"); + if (NULL != getter) { + LOC_LOGD("%s:%d]: getter is not NULL in RPC", __func__, __LINE__); + locApi = (*getter)(mMsgTask, exMask, this); + } + } + } + } + } + + // locApi could still be NULL at this time + // we would then create a dummy one + if (NULL == locApi) { + locApi = new LocApiBase(mMsgTask, exMask, this); + } + + return locApi; +} + +ContextBase::ContextBase(const MsgTask* msgTask, + LOC_API_ADAPTER_EVENT_MASK_T exMask, + const char* libName) : + mLBSProxy(getLBSProxy(libName)), + mMsgTask(msgTask), + mLocApi(createLocApi(exMask)), + mLocApiProxy(mLocApi->getLocApiProxy()) +{ +} + +} diff --git a/gps/core/ContextBase.h b/gps/core/ContextBase.h new file mode 100644 index 000000000..fe0b86060 --- /dev/null +++ b/gps/core/ContextBase.h @@ -0,0 +1,74 @@ +/* Copyright (c) 2011-2015, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef __LOC_CONTEXT_BASE__ +#define __LOC_CONTEXT_BASE__ + +#include +#include +#include +#include +#include + +namespace loc_core { + +class LocAdapterBase; + +class ContextBase { + static LBSProxyBase* getLBSProxy(const char* libName); + LocApiBase* createLocApi(LOC_API_ADAPTER_EVENT_MASK_T excludedMask); +protected: + const LBSProxyBase* mLBSProxy; + const MsgTask* mMsgTask; + LocApiBase* mLocApi; + LocApiProxyBase *mLocApiProxy; +public: + ContextBase(const MsgTask* msgTask, + LOC_API_ADAPTER_EVENT_MASK_T exMask, + const char* libName); + inline virtual ~ContextBase() { delete mLocApi; delete mLBSProxy; } + + inline const MsgTask* getMsgTask() { return mMsgTask; } + inline LocApiBase* getLocApi() { return mLocApi; } + inline LocApiProxyBase* getLocApiProxy() { return mLocApiProxy; } + inline bool hasAgpsExtendedCapabilities() { return mLBSProxy->hasAgpsExtendedCapabilities(); } + inline bool hasCPIExtendedCapabilities() { return mLBSProxy->hasCPIExtendedCapabilities(); } + inline void modemPowerVote(bool power) const { return mLBSProxy->modemPowerVote(power); } + inline void requestUlp(LocAdapterBase* adapter, + unsigned long capabilities) { + mLBSProxy->requestUlp(adapter, capabilities); + } + inline IzatDevId_t getIzatDevId() const { + return mLBSProxy->getIzatDevId(); + } + inline void sendMsg(const LocMsg *msg) { getMsgTask()->sendMsg(msg); } +}; + +} // namespace loc_core + +#endif //__LOC_CONTEXT_BASE__ diff --git a/gps/core/LBSProxyBase.h b/gps/core/LBSProxyBase.h new file mode 100644 index 000000000..0faf80129 --- /dev/null +++ b/gps/core/LBSProxyBase.h @@ -0,0 +1,65 @@ +/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef IZAT_PROXY_BASE_H +#define IZAT_PROXY_BASE_H +#include +#include + +namespace loc_core { + +class LocApiBase; +class LocAdapterBase; +class ContextBase; + +class LBSProxyBase { + friend class ContextBase; + inline virtual LocApiBase* + getLocApi(const MsgTask* msgTask, + LOC_API_ADAPTER_EVENT_MASK_T exMask, + ContextBase* context) const { + return NULL; + } +protected: + inline LBSProxyBase() {} +public: + inline virtual ~LBSProxyBase() {} + inline virtual void requestUlp(LocAdapterBase* adapter, + unsigned long capabilities) const {} + inline virtual bool hasAgpsExtendedCapabilities() const { return false; } + inline virtual bool hasCPIExtendedCapabilities() const { return false; } + inline virtual void modemPowerVote(bool power) const {} + virtual void injectFeatureConfig(ContextBase* context) const {} + inline virtual IzatDevId_t getIzatDevId() const { return 0; } +}; + +typedef LBSProxyBase* (getLBSProxy_t)(); + +} // namespace loc_core + +#endif // IZAT_PROXY_BASE_H diff --git a/gps/core/LocAdapterBase.cpp b/gps/core/LocAdapterBase.cpp new file mode 100644 index 000000000..8fdb8cbbf --- /dev/null +++ b/gps/core/LocAdapterBase.cpp @@ -0,0 +1,142 @@ +/* Copyright (c) 2011-2014, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#define LOG_NDDEBUG 0 +#define LOG_TAG "LocSvc_LocAdapterBase" + +#include +#include +#include +#include +#include + +namespace loc_core { + +// This is the top level class, so the constructor will +// always gets called. Here we prepare for the default. +// But if getLocApi(targetEnumType target) is overriden, +// the right locApi should get created. +LocAdapterBase::LocAdapterBase(const LOC_API_ADAPTER_EVENT_MASK_T mask, + ContextBase* context, LocAdapterProxyBase *adapterProxyBase) : + mEvtMask(mask), mContext(context), + mLocApi(context->getLocApi()), mLocAdapterProxyBase(adapterProxyBase), + mMsgTask(context->getMsgTask()) +{ + mLocApi->addAdapter(this); +} + +void LocAdapterBase::handleEngineUpEvent() +{ + if (mLocAdapterProxyBase) { + mLocAdapterProxyBase->handleEngineUpEvent(); + } +} + +void LocAdapterBase::handleEngineDownEvent() +{ + if (mLocAdapterProxyBase) { + mLocAdapterProxyBase->handleEngineDownEvent(); + } +} + +void LocAdapterBase:: + reportPosition(UlpLocation &location, + GpsLocationExtended &locationExtended, + void* locationExt, + enum loc_sess_status status, + LocPosTechMask loc_technology_mask) { + if (mLocAdapterProxyBase == NULL || + !mLocAdapterProxyBase->reportPosition(location, + locationExtended, + status, + loc_technology_mask)) { + DEFAULT_IMPL() + } +} + +void LocAdapterBase:: + reportSv(GnssSvStatus &svStatus, + GpsLocationExtended &locationExtended, + void* svExt) +DEFAULT_IMPL() + + +void LocAdapterBase:: + reportStatus(GpsStatusValue status) +DEFAULT_IMPL() + + +void LocAdapterBase:: + reportNmea(const char* nmea, int length) +DEFAULT_IMPL() + +bool LocAdapterBase:: + reportXtraServer(const char* url1, const char* url2, + const char* url3, const int maxlength) +DEFAULT_IMPL(false) + +bool LocAdapterBase:: + requestXtraData() +DEFAULT_IMPL(false) + +bool LocAdapterBase:: + requestTime() +DEFAULT_IMPL(false) + +bool LocAdapterBase:: + requestLocation() +DEFAULT_IMPL(false) + +bool LocAdapterBase:: + requestATL(int connHandle, AGpsType agps_type) +DEFAULT_IMPL(false) + +bool LocAdapterBase:: + releaseATL(int connHandle) +DEFAULT_IMPL(false) + +bool LocAdapterBase:: + requestSuplES(int connHandle) +DEFAULT_IMPL(false) + +bool LocAdapterBase:: + reportDataCallOpened() +DEFAULT_IMPL(false) + +bool LocAdapterBase:: + reportDataCallClosed() +DEFAULT_IMPL(false) + +bool LocAdapterBase:: + requestNiNotify(GpsNiNotification ¬ify, const void* data) +DEFAULT_IMPL(false) + +void LocAdapterBase:: + reportGpsMeasurementData(GpsData &gpsMeasurementData) +DEFAULT_IMPL() +} // namespace loc_core diff --git a/gps/core/LocAdapterBase.h b/gps/core/LocAdapterBase.h new file mode 100644 index 000000000..5f4660b85 --- /dev/null +++ b/gps/core/LocAdapterBase.h @@ -0,0 +1,119 @@ +/* Copyright (c) 2011-2014, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef LOC_API_ADAPTER_BASE_H +#define LOC_API_ADAPTER_BASE_H + +#include +#include +#include + +namespace loc_core { + +class LocAdapterProxyBase; + +class LocAdapterBase { +protected: + LOC_API_ADAPTER_EVENT_MASK_T mEvtMask; + ContextBase* mContext; + LocApiBase* mLocApi; + LocAdapterProxyBase* mLocAdapterProxyBase; + const MsgTask* mMsgTask; + + inline LocAdapterBase(const MsgTask* msgTask) : + mEvtMask(0), mContext(NULL), mLocApi(NULL), + mLocAdapterProxyBase(NULL), mMsgTask(msgTask) {} +public: + inline virtual ~LocAdapterBase() { mLocApi->removeAdapter(this); } + LocAdapterBase(const LOC_API_ADAPTER_EVENT_MASK_T mask, + ContextBase* context, LocAdapterProxyBase *adapterProxyBase = NULL); + inline LOC_API_ADAPTER_EVENT_MASK_T + checkMask(LOC_API_ADAPTER_EVENT_MASK_T mask) const { + return mEvtMask & mask; + } + + inline LOC_API_ADAPTER_EVENT_MASK_T getEvtMask() const { + return mEvtMask; + } + + inline void sendMsg(const LocMsg* msg) const { + mMsgTask->sendMsg(msg); + } + + inline void sendMsg(const LocMsg* msg) { + mMsgTask->sendMsg(msg); + } + + inline void updateEvtMask(LOC_API_ADAPTER_EVENT_MASK_T event, + loc_registration_mask_status isEnabled) + { + mEvtMask = + isEnabled == LOC_REGISTRATION_MASK_ENABLED ? (mEvtMask|event):(mEvtMask&~event); + + mLocApi->updateEvtMask(); + } + + // This will be overridden by the individual adapters + // if necessary. + inline virtual void setUlpProxy(UlpProxyBase* ulp) {} + virtual void handleEngineUpEvent(); + virtual void handleEngineDownEvent(); + inline virtual void setPositionModeInt(LocPosMode& posMode) {} + virtual void startFixInt() {} + virtual void stopFixInt() {} + virtual void getZppInt() {} + virtual void reportPosition(UlpLocation &location, + GpsLocationExtended &locationExtended, + void* locationExt, + enum loc_sess_status status, + LocPosTechMask loc_technology_mask); + virtual void reportSv(GnssSvStatus &svStatus, + GpsLocationExtended &locationExtended, + void* svExt); + virtual void reportStatus(GpsStatusValue status); + virtual void reportNmea(const char* nmea, int length); + virtual bool reportXtraServer(const char* url1, const char* url2, + const char* url3, const int maxlength); + virtual bool requestXtraData(); + virtual bool requestTime(); + virtual bool requestLocation(); + virtual bool requestATL(int connHandle, AGpsType agps_type); + virtual bool releaseATL(int connHandle); + virtual bool requestSuplES(int connHandle); + virtual bool reportDataCallOpened(); + virtual bool reportDataCallClosed(); + virtual bool requestNiNotify(GpsNiNotification ¬ify, + const void* data); + inline virtual bool isInSession() { return false; } + ContextBase* getContext() const { return mContext; } + virtual void reportGpsMeasurementData(GpsData &gpsMeasurementData); +}; + +} // namespace loc_core + +#endif //LOC_API_ADAPTER_BASE_H diff --git a/gps/core/LocAdapterProxyBase.h b/gps/core/LocAdapterProxyBase.h new file mode 100644 index 000000000..1ddcca4cc --- /dev/null +++ b/gps/core/LocAdapterProxyBase.h @@ -0,0 +1,70 @@ +/* Copyright (c) 2014 The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef LOC_ADAPTER_PROXY_BASE_H +#define LOC_ADAPTER_PROXY_BASE_H + +#include +#include + +namespace loc_core { + +class LocAdapterProxyBase { +private: + LocAdapterBase *mLocAdapterBase; +protected: + inline LocAdapterProxyBase(const LOC_API_ADAPTER_EVENT_MASK_T mask, + ContextBase* context): + mLocAdapterBase(new LocAdapterBase(mask, context, this)) { + } + inline virtual ~LocAdapterProxyBase() { + delete mLocAdapterBase; + } + ContextBase* getContext() const { + return mLocAdapterBase->getContext(); + } + inline void updateEvtMask(LOC_API_ADAPTER_EVENT_MASK_T event, + loc_registration_mask_status isEnabled) { + mLocAdapterBase->updateEvtMask(event,isEnabled); + } + +public: + inline virtual void handleEngineUpEvent() {}; + inline virtual void handleEngineDownEvent() {}; + inline virtual bool reportPosition(UlpLocation &location, + GpsLocationExtended &locationExtended, + enum loc_sess_status status, + LocPosTechMask loc_technology_mask) { + return false; + } +}; + +} // namespace loc_core + +#endif //LOC_ADAPTER_PROXY_BASE_H diff --git a/gps/core/LocApiBase.cpp b/gps/core/LocApiBase.cpp new file mode 100644 index 000000000..dcd35fecd --- /dev/null +++ b/gps/core/LocApiBase.cpp @@ -0,0 +1,553 @@ +/* Copyright (c) 2011-2014, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#define LOG_NDDEBUG 0 +#define LOG_TAG "LocSvc_LocApiBase" + +#include +#include +#include +#include +#include + +namespace loc_core { + +#define TO_ALL_LOCADAPTERS(call) TO_ALL_ADAPTERS(mLocAdapters, (call)) +#define TO_1ST_HANDLING_LOCADAPTERS(call) TO_1ST_HANDLING_ADAPTER(mLocAdapters, (call)) + +int hexcode(char *hexstring, int string_size, + const char *data, int data_size) +{ + int i; + for (i = 0; i < data_size; i++) + { + char ch = data[i]; + if (i*2 + 3 <= string_size) + { + snprintf(&hexstring[i*2], 3, "%02X", ch); + } + else { + break; + } + } + return i; +} + +int decodeAddress(char *addr_string, int string_size, + const char *data, int data_size) +{ + const char addr_prefix = 0x91; + int i, idxOutput = 0; + + if (!data || !addr_string) { return 0; } + + if (data[0] != addr_prefix) + { + LOC_LOGW("decodeAddress: address prefix is not 0x%x but 0x%x", addr_prefix, data[0]); + addr_string[0] = '\0'; + return 0; // prefix not correct + } + + for (i = 1; i < data_size; i++) + { + unsigned char ch = data[i], low = ch & 0x0F, hi = ch >> 4; + if (low <= 9 && idxOutput < string_size - 1) { addr_string[idxOutput++] = low + '0'; } + if (hi <= 9 && idxOutput < string_size - 1) { addr_string[idxOutput++] = hi + '0'; } + } + + addr_string[idxOutput] = '\0'; // Terminates the string + + return idxOutput; +} + +struct LocSsrMsg : public LocMsg { + LocApiBase* mLocApi; + inline LocSsrMsg(LocApiBase* locApi) : + LocMsg(), mLocApi(locApi) + { + locallog(); + } + inline virtual void proc() const { + mLocApi->close(); + mLocApi->open(mLocApi->getEvtMask()); + } + inline void locallog() { + LOC_LOGV("LocSsrMsg"); + } + inline virtual void log() { + locallog(); + } +}; + +struct LocOpenMsg : public LocMsg { + LocApiBase* mLocApi; + LOC_API_ADAPTER_EVENT_MASK_T mMask; + inline LocOpenMsg(LocApiBase* locApi, + LOC_API_ADAPTER_EVENT_MASK_T mask) : + LocMsg(), mLocApi(locApi), mMask(mask) + { + locallog(); + } + inline virtual void proc() const { + mLocApi->open(mMask); + } + inline void locallog() { + LOC_LOGV("%s:%d]: LocOpen Mask: %x\n", + __func__, __LINE__, mMask); + } + inline virtual void log() { + locallog(); + } +}; + +LocApiBase::LocApiBase(const MsgTask* msgTask, + LOC_API_ADAPTER_EVENT_MASK_T excludedMask, + ContextBase* context) : + mExcludedMask(excludedMask), mMsgTask(msgTask), + mMask(0), mSupportedMsg(0), mContext(context) +{ + memset(mLocAdapters, 0, sizeof(mLocAdapters)); +} + +LOC_API_ADAPTER_EVENT_MASK_T LocApiBase::getEvtMask() +{ + LOC_API_ADAPTER_EVENT_MASK_T mask = 0; + + TO_ALL_LOCADAPTERS(mask |= mLocAdapters[i]->getEvtMask()); + + return mask & ~mExcludedMask; +} + +bool LocApiBase::isInSession() +{ + bool inSession = false; + + for (int i = 0; + !inSession && i < MAX_ADAPTERS && NULL != mLocAdapters[i]; + i++) { + inSession = mLocAdapters[i]->isInSession(); + } + + return inSession; +} + +void LocApiBase::addAdapter(LocAdapterBase* adapter) +{ + for (int i = 0; i < MAX_ADAPTERS && mLocAdapters[i] != adapter; i++) { + if (mLocAdapters[i] == NULL) { + mLocAdapters[i] = adapter; + mMsgTask->sendMsg(new LocOpenMsg(this, + (adapter->getEvtMask()))); + break; + } + } +} + +void LocApiBase::removeAdapter(LocAdapterBase* adapter) +{ + for (int i = 0; + i < MAX_ADAPTERS && NULL != mLocAdapters[i]; + i++) { + if (mLocAdapters[i] == adapter) { + mLocAdapters[i] = NULL; + + // shift the rest of the adapters up so that the pointers + // in the array do not have holes. This should be more + // performant, because the array maintenance is much much + // less frequent than event handlings, which need to linear + // search all the adapters + int j = i; + while (++i < MAX_ADAPTERS && mLocAdapters[i] != NULL); + + // i would be MAX_ADAPTERS or point to a NULL + i--; + // i now should point to a none NULL adapter within valid + // range although i could be equal to j, but it won't hurt. + // No need to check it, as it gains nothing. + mLocAdapters[j] = mLocAdapters[i]; + // this makes sure that we exit the for loop + mLocAdapters[i] = NULL; + + // if we have an empty list of adapters + if (0 == i) { + close(); + } else { + // else we need to remove the bit + mMsgTask->sendMsg(new LocOpenMsg(this, getEvtMask())); + } + } + } +} + +void LocApiBase::updateEvtMask() +{ + mMsgTask->sendMsg(new LocOpenMsg(this, getEvtMask())); +} + +void LocApiBase::handleEngineUpEvent() +{ + // This will take care of renegotiating the loc handle + mMsgTask->sendMsg(new LocSsrMsg(this)); + + LocDualContext::injectFeatureConfig(mContext); + + // loop through adapters, and deliver to all adapters. + TO_ALL_LOCADAPTERS(mLocAdapters[i]->handleEngineUpEvent()); +} + +void LocApiBase::handleEngineDownEvent() +{ + // loop through adapters, and deliver to all adapters. + TO_ALL_LOCADAPTERS(mLocAdapters[i]->handleEngineDownEvent()); +} + +void LocApiBase::reportPosition(UlpLocation &location, + GpsLocationExtended &locationExtended, + void* locationExt, + enum loc_sess_status status, + LocPosTechMask loc_technology_mask) +{ + // print the location info before delivering + LOC_LOGV("flags: %d\n source: %d\n latitude: %f\n longitude: %f\n " + "altitude: %f\n speed: %f\n bearing: %f\n accuracy: %f\n " + "timestamp: %lld\n rawDataSize: %d\n rawData: %p\n " + "Session status: %d\n Technology mask: %u", + location.gpsLocation.flags, location.position_source, + location.gpsLocation.latitude, location.gpsLocation.longitude, + location.gpsLocation.altitude, location.gpsLocation.speed, + location.gpsLocation.bearing, location.gpsLocation.accuracy, + location.gpsLocation.timestamp, location.rawDataSize, + location.rawData, status, loc_technology_mask); + // loop through adapters, and deliver to all adapters. + TO_ALL_LOCADAPTERS( + mLocAdapters[i]->reportPosition(location, + locationExtended, + locationExt, + status, + loc_technology_mask) + ); +} + +void LocApiBase::reportSv(GnssSvStatus &svStatus, + GpsLocationExtended &locationExtended, + void* svExt) +{ + // print the SV info before delivering + LOC_LOGV("num sv: %d\n ephemeris mask: %dxn almanac mask: %x\n gps/glo/bds in use" + " mask: %x/%x/%x\n sv: prn snr elevation azimuth", + svStatus.num_svs, svStatus.ephemeris_mask, + svStatus.almanac_mask, svStatus.gps_used_in_fix_mask, + svStatus.glo_used_in_fix_mask, svStatus.bds_used_in_fix_mask); + for (int i = 0; i < svStatus.num_svs && i < GPS_MAX_SVS; i++) { + LOC_LOGV(" %d: %d %f %f %f", + i, + svStatus.sv_list[i].prn, + svStatus.sv_list[i].snr, + svStatus.sv_list[i].elevation, + svStatus.sv_list[i].azimuth); + } + // loop through adapters, and deliver to all adapters. + TO_ALL_LOCADAPTERS( + mLocAdapters[i]->reportSv(svStatus, + locationExtended, + svExt) + ); +} + +void LocApiBase::reportStatus(GpsStatusValue status) +{ + // loop through adapters, and deliver to all adapters. + TO_ALL_LOCADAPTERS(mLocAdapters[i]->reportStatus(status)); +} + +void LocApiBase::reportNmea(const char* nmea, int length) +{ + // loop through adapters, and deliver to all adapters. + TO_ALL_LOCADAPTERS(mLocAdapters[i]->reportNmea(nmea, length)); +} + +void LocApiBase::reportXtraServer(const char* url1, const char* url2, + const char* url3, const int maxlength) +{ + // loop through adapters, and deliver to the first handling adapter. + TO_1ST_HANDLING_LOCADAPTERS(mLocAdapters[i]->reportXtraServer(url1, url2, url3, maxlength)); + +} + +void LocApiBase::requestXtraData() +{ + // loop through adapters, and deliver to the first handling adapter. + TO_1ST_HANDLING_LOCADAPTERS(mLocAdapters[i]->requestXtraData()); +} + +void LocApiBase::requestTime() +{ + // loop through adapters, and deliver to the first handling adapter. + TO_1ST_HANDLING_LOCADAPTERS(mLocAdapters[i]->requestTime()); +} + +void LocApiBase::requestLocation() +{ + // loop through adapters, and deliver to the first handling adapter. + TO_1ST_HANDLING_LOCADAPTERS(mLocAdapters[i]->requestLocation()); +} + +void LocApiBase::requestATL(int connHandle, AGpsType agps_type) +{ + // loop through adapters, and deliver to the first handling adapter. + TO_1ST_HANDLING_LOCADAPTERS(mLocAdapters[i]->requestATL(connHandle, agps_type)); +} + +void LocApiBase::releaseATL(int connHandle) +{ + // loop through adapters, and deliver to the first handling adapter. + TO_1ST_HANDLING_LOCADAPTERS(mLocAdapters[i]->releaseATL(connHandle)); +} + +void LocApiBase::requestSuplES(int connHandle) +{ + // loop through adapters, and deliver to the first handling adapter. + TO_1ST_HANDLING_LOCADAPTERS(mLocAdapters[i]->requestSuplES(connHandle)); +} + +void LocApiBase::reportDataCallOpened() +{ + // loop through adapters, and deliver to the first handling adapter. + TO_1ST_HANDLING_LOCADAPTERS(mLocAdapters[i]->reportDataCallOpened()); +} + +void LocApiBase::reportDataCallClosed() +{ + // loop through adapters, and deliver to the first handling adapter. + TO_1ST_HANDLING_LOCADAPTERS(mLocAdapters[i]->reportDataCallClosed()); +} + +void LocApiBase::requestNiNotify(GpsNiNotification ¬ify, const void* data) +{ + // loop through adapters, and deliver to the first handling adapter. + TO_1ST_HANDLING_LOCADAPTERS(mLocAdapters[i]->requestNiNotify(notify, data)); +} + +void LocApiBase::saveSupportedMsgList(uint64_t supportedMsgList) +{ + mSupportedMsg = supportedMsgList; +} + +void* LocApiBase :: getSibling() + DEFAULT_IMPL(NULL) + +LocApiProxyBase* LocApiBase :: getLocApiProxy() + DEFAULT_IMPL(NULL) + +void LocApiBase::reportGpsMeasurementData(GpsData &gpsMeasurementData) +{ + // loop through adapters, and deliver to all adapters. + TO_ALL_LOCADAPTERS(mLocAdapters[i]->reportGpsMeasurementData(gpsMeasurementData)); +} + +enum loc_api_adapter_err LocApiBase:: + open(LOC_API_ADAPTER_EVENT_MASK_T mask) +DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) + +enum loc_api_adapter_err LocApiBase:: + close() +DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) + +enum loc_api_adapter_err LocApiBase:: + startFix(const LocPosMode& posMode) +DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) + +enum loc_api_adapter_err LocApiBase:: + stopFix() +DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) + +enum loc_api_adapter_err LocApiBase:: + deleteAidingData(GpsAidingData f) +DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) + +enum loc_api_adapter_err LocApiBase:: + enableData(int enable) +DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) + +enum loc_api_adapter_err LocApiBase:: + setAPN(char* apn, int len) +DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) + +enum loc_api_adapter_err LocApiBase:: + injectPosition(double latitude, double longitude, float accuracy) +DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) + +enum loc_api_adapter_err LocApiBase:: + setTime(GpsUtcTime time, int64_t timeReference, int uncertainty) +DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) + +enum loc_api_adapter_err LocApiBase:: + setXtraData(char* data, int length) +DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) + +enum loc_api_adapter_err LocApiBase:: + requestXtraServer() +DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) + +enum loc_api_adapter_err LocApiBase:: + atlOpenStatus(int handle, int is_succ, char* apn, + AGpsBearerType bear, AGpsType agpsType) +DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) + +enum loc_api_adapter_err LocApiBase:: + atlCloseStatus(int handle, int is_succ) +DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) + +enum loc_api_adapter_err LocApiBase:: + setPositionMode(const LocPosMode& posMode) +DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) + +enum loc_api_adapter_err LocApiBase:: + setServer(const char* url, int len) +DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) + +enum loc_api_adapter_err LocApiBase:: + setServer(unsigned int ip, int port, + LocServerType type) +DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) + +enum loc_api_adapter_err LocApiBase:: + informNiResponse(GpsUserResponseType userResponse, + const void* passThroughData) +DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) + +enum loc_api_adapter_err LocApiBase:: + setSUPLVersion(uint32_t version) +DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) + +enum loc_api_adapter_err LocApiBase:: + setLPPConfig(uint32_t profile) +DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) + +enum loc_api_adapter_err LocApiBase:: + setSensorControlConfig(int sensorUsage, + int sensorProvider) +DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) + +enum loc_api_adapter_err LocApiBase:: + setSensorProperties(bool gyroBiasVarianceRandomWalk_valid, + float gyroBiasVarianceRandomWalk, + bool accelBiasVarianceRandomWalk_valid, + float accelBiasVarianceRandomWalk, + bool angleBiasVarianceRandomWalk_valid, + float angleBiasVarianceRandomWalk, + bool rateBiasVarianceRandomWalk_valid, + float rateBiasVarianceRandomWalk, + bool velocityBiasVarianceRandomWalk_valid, + float velocityBiasVarianceRandomWalk) +DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) + +enum loc_api_adapter_err LocApiBase:: + setSensorPerfControlConfig(int controlMode, + int accelSamplesPerBatch, + int accelBatchesPerSec, + int gyroSamplesPerBatch, + int gyroBatchesPerSec, + int accelSamplesPerBatchHigh, + int accelBatchesPerSecHigh, + int gyroSamplesPerBatchHigh, + int gyroBatchesPerSecHigh, + int algorithmConfig) +DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) + +enum loc_api_adapter_err LocApiBase:: + setExtPowerConfig(int isBatteryCharging) +DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) + +enum loc_api_adapter_err LocApiBase:: + setAGLONASSProtocol(unsigned long aGlonassProtocol) +DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) + +enum loc_api_adapter_err LocApiBase:: + getWwanZppFix(GpsLocation& zppLoc) +DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) + +enum loc_api_adapter_err LocApiBase:: + getBestAvailableZppFix(GpsLocation& zppLoc) +{ + memset(&zppLoc, 0, sizeof(zppLoc)); + DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) +} + +enum loc_api_adapter_err LocApiBase:: + getBestAvailableZppFix(GpsLocation & zppLoc, LocPosTechMask & tech_mask) +{ + memset(&zppLoc, 0, sizeof(zppLoc)); + memset(&tech_mask, 0, sizeof(tech_mask)); + DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) +} + +int LocApiBase:: + initDataServiceClient() +DEFAULT_IMPL(-1) + +int LocApiBase:: + openAndStartDataCall() +DEFAULT_IMPL(-1) + +void LocApiBase:: + stopDataCall() +DEFAULT_IMPL() + +void LocApiBase:: + closeDataCall() +DEFAULT_IMPL() + +int LocApiBase:: + setGpsLock(LOC_GPS_LOCK_MASK lock) +DEFAULT_IMPL(-1) + +void LocApiBase:: + installAGpsCert(const DerEncodedCertificate* pData, + size_t length, + uint32_t slotBitMask) +DEFAULT_IMPL() + +int LocApiBase:: + getGpsLock() +DEFAULT_IMPL(-1) + +enum loc_api_adapter_err LocApiBase:: + setXtraVersionCheck(enum xtra_version_check check) +DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) + +int LocApiBase:: + updateRegistrationMask(LOC_API_ADAPTER_EVENT_MASK_T event, + loc_registration_mask_status isEnabled) +DEFAULT_IMPL(-1) + +bool LocApiBase:: + gnssConstellationConfig() +DEFAULT_IMPL(false) + +} // namespace loc_core diff --git a/gps/core/LocApiBase.h b/gps/core/LocApiBase.h new file mode 100644 index 000000000..b1c3d30ad --- /dev/null +++ b/gps/core/LocApiBase.h @@ -0,0 +1,261 @@ +/* Copyright (c) 2011-2014, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef LOC_API_BASE_H +#define LOC_API_BASE_H + +#include +#include +#include +#include +#include + +namespace loc_core { +class ContextBase; + +int hexcode(char *hexstring, int string_size, + const char *data, int data_size); +int decodeAddress(char *addr_string, int string_size, + const char *data, int data_size); + +#define MAX_ADAPTERS 10 + +#define TO_ALL_ADAPTERS(adapters, call) \ + for (int i = 0; i < MAX_ADAPTERS && NULL != (adapters)[i]; i++) { \ + call; \ + } + +#define TO_1ST_HANDLING_ADAPTER(adapters, call) \ + for (int i = 0; i sendMsg(msg); + } + + void addAdapter(LocAdapterBase* adapter); + void removeAdapter(LocAdapterBase* adapter); + + // upward calls + void handleEngineUpEvent(); + void handleEngineDownEvent(); + void reportPosition(UlpLocation &location, + GpsLocationExtended &locationExtended, + void* locationExt, + enum loc_sess_status status, + LocPosTechMask loc_technology_mask = + LOC_POS_TECH_MASK_DEFAULT); + void reportSv(GnssSvStatus &svStatus, + GpsLocationExtended &locationExtended, + void* svExt); + void reportStatus(GpsStatusValue status); + void reportNmea(const char* nmea, int length); + void reportXtraServer(const char* url1, const char* url2, + const char* url3, const int maxlength); + void requestXtraData(); + void requestTime(); + void requestLocation(); + void requestATL(int connHandle, AGpsType agps_type); + void releaseATL(int connHandle); + void requestSuplES(int connHandle); + void reportDataCallOpened(); + void reportDataCallClosed(); + void requestNiNotify(GpsNiNotification ¬ify, const void* data); + void saveSupportedMsgList(uint64_t supportedMsgList); + void reportGpsMeasurementData(GpsData &gpsMeasurementData); + + // downward calls + // All below functions are to be defined by adapter specific modules: + // RPC, QMI, etc. The default implementation is empty. + + virtual void* getSibling(); + virtual LocApiProxyBase* getLocApiProxy(); + virtual enum loc_api_adapter_err + startFix(const LocPosMode& posMode); + virtual enum loc_api_adapter_err + stopFix(); + virtual enum loc_api_adapter_err + deleteAidingData(GpsAidingData f); + virtual enum loc_api_adapter_err + enableData(int enable); + virtual enum loc_api_adapter_err + setAPN(char* apn, int len); + virtual enum loc_api_adapter_err + injectPosition(double latitude, double longitude, float accuracy); + virtual enum loc_api_adapter_err + setTime(GpsUtcTime time, int64_t timeReference, int uncertainty); + virtual enum loc_api_adapter_err + setXtraData(char* data, int length); + virtual enum loc_api_adapter_err + requestXtraServer(); + virtual enum loc_api_adapter_err + atlOpenStatus(int handle, int is_succ, char* apn, AGpsBearerType bear, AGpsType agpsType); + virtual enum loc_api_adapter_err + atlCloseStatus(int handle, int is_succ); + virtual enum loc_api_adapter_err + setPositionMode(const LocPosMode& posMode); + virtual enum loc_api_adapter_err + setServer(const char* url, int len); + virtual enum loc_api_adapter_err + setServer(unsigned int ip, int port, + LocServerType type); + virtual enum loc_api_adapter_err + informNiResponse(GpsUserResponseType userResponse, const void* passThroughData); + virtual enum loc_api_adapter_err + setSUPLVersion(uint32_t version); + virtual enum loc_api_adapter_err + setLPPConfig(uint32_t profile); + virtual enum loc_api_adapter_err + setSensorControlConfig(int sensorUsage, int sensorProvider); + virtual enum loc_api_adapter_err + setSensorProperties(bool gyroBiasVarianceRandomWalk_valid, + float gyroBiasVarianceRandomWalk, + bool accelBiasVarianceRandomWalk_valid, + float accelBiasVarianceRandomWalk, + bool angleBiasVarianceRandomWalk_valid, + float angleBiasVarianceRandomWalk, + bool rateBiasVarianceRandomWalk_valid, + float rateBiasVarianceRandomWalk, + bool velocityBiasVarianceRandomWalk_valid, + float velocityBiasVarianceRandomWalk); + virtual enum loc_api_adapter_err + setSensorPerfControlConfig(int controlMode, + int accelSamplesPerBatch, + int accelBatchesPerSec, + int gyroSamplesPerBatch, + int gyroBatchesPerSec, + int accelSamplesPerBatchHigh, + int accelBatchesPerSecHigh, + int gyroSamplesPerBatchHigh, + int gyroBatchesPerSecHigh, + int algorithmConfig); + virtual enum loc_api_adapter_err + setExtPowerConfig(int isBatteryCharging); + virtual enum loc_api_adapter_err + setAGLONASSProtocol(unsigned long aGlonassProtocol); + virtual enum loc_api_adapter_err + getWwanZppFix(GpsLocation & zppLoc); + virtual enum loc_api_adapter_err + getBestAvailableZppFix(GpsLocation & zppLoc); + virtual enum loc_api_adapter_err + getBestAvailableZppFix(GpsLocation & zppLoc, LocPosTechMask & tech_mask); + virtual int initDataServiceClient(); + virtual int openAndStartDataCall(); + virtual void stopDataCall(); + virtual void closeDataCall(); + virtual void installAGpsCert(const DerEncodedCertificate* pData, + size_t length, + uint32_t slotBitMask); + inline virtual void setInSession(bool inSession) {} + inline bool isMessageSupported (LocCheckingMessagesID msgID) const { + if (msgID > (sizeof(mSupportedMsg) << 3)) { + return false; + } else { + uint32_t messageChecker = 1 << msgID; + return (messageChecker & mSupportedMsg) == messageChecker; + } + } + void updateEvtMask(); + + /*Values for lock + 1 = Do not lock any position sessions + 2 = Lock MI position sessions + 3 = Lock MT position sessions + 4 = Lock all position sessions + */ + virtual int setGpsLock(LOC_GPS_LOCK_MASK lock); + /* + Returns + Current value of GPS Lock on success + -1 on failure + */ + virtual int getGpsLock(void); + + virtual enum loc_api_adapter_err setXtraVersionCheck(enum xtra_version_check check); + + /* + Update gps reporting events + */ + virtual int updateRegistrationMask(LOC_API_ADAPTER_EVENT_MASK_T event, + loc_registration_mask_status isEnabled); + /* + Check if the modem support the service + */ + virtual bool gnssConstellationConfig(); +}; + +typedef LocApiBase* (getLocApi_t)(const MsgTask* msgTask, + LOC_API_ADAPTER_EVENT_MASK_T exMask, + ContextBase *context); + +} // namespace loc_core + +#endif //LOC_API_BASE_H diff --git a/gps/core/LocDualContext.cpp b/gps/core/LocDualContext.cpp new file mode 100644 index 000000000..578421cda --- /dev/null +++ b/gps/core/LocDualContext.cpp @@ -0,0 +1,147 @@ +/* Copyright (c) 2011-2014, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#define LOG_NDDEBUG 0 +#define LOG_TAG "LocSvc_DualCtx" + +#include +#include +#include +#include +#include +#include + +namespace loc_core { + +// nothing exclude for foreground +const LOC_API_ADAPTER_EVENT_MASK_T +LocDualContext::mFgExclMask = 0; +// excluded events for background clients +const LOC_API_ADAPTER_EVENT_MASK_T +LocDualContext::mBgExclMask = + (LOC_API_ADAPTER_BIT_PARSED_POSITION_REPORT | + LOC_API_ADAPTER_BIT_SATELLITE_REPORT | + LOC_API_ADAPTER_BIT_NMEA_1HZ_REPORT | + LOC_API_ADAPTER_BIT_NMEA_POSITION_REPORT | + LOC_API_ADAPTER_BIT_IOCTL_REPORT | + LOC_API_ADAPTER_BIT_STATUS_REPORT | + LOC_API_ADAPTER_BIT_GEOFENCE_GEN_ALERT | + LOC_API_ADAPTER_BIT_GNSS_MEASUREMENT); + +const MsgTask* LocDualContext::mMsgTask = NULL; +ContextBase* LocDualContext::mFgContext = NULL; +ContextBase* LocDualContext::mBgContext = NULL; +ContextBase* LocDualContext::mInjectContext = NULL; +// the name must be shorter than 15 chars +const char* LocDualContext::mLocationHalName = "Loc_hal_worker"; +const char* LocDualContext::mLBSLibName = "liblbs_core.so"; + +pthread_mutex_t LocDualContext::mGetLocContextMutex = PTHREAD_MUTEX_INITIALIZER; + +const MsgTask* LocDualContext::getMsgTask(LocThread::tCreate tCreator, + const char* name, bool joinable) +{ + if (NULL == mMsgTask) { + mMsgTask = new MsgTask(tCreator, name, joinable); + } + return mMsgTask; +} + +inline +const MsgTask* LocDualContext::getMsgTask(const char* name, bool joinable) { + return getMsgTask((LocThread::tCreate)NULL, name, joinable); +} + +ContextBase* LocDualContext::getLocFgContext(LocThread::tCreate tCreator, + LocMsg* firstMsg, const char* name, bool joinable) +{ + pthread_mutex_lock(&LocDualContext::mGetLocContextMutex); + LOC_LOGD("%s:%d]: querying ContextBase with tCreator", __func__, __LINE__); + if (NULL == mFgContext) { + LOC_LOGD("%s:%d]: creating msgTask with tCreator", __func__, __LINE__); + const MsgTask* msgTask = getMsgTask(tCreator, name, joinable); + mFgContext = new LocDualContext(msgTask, + mFgExclMask); + } + if(NULL == mInjectContext) { + LOC_LOGD("%s:%d]: mInjectContext is FgContext", __func__, __LINE__); + mInjectContext = mFgContext; + injectFeatureConfig(mInjectContext); + } + pthread_mutex_unlock(&LocDualContext::mGetLocContextMutex); + + if (firstMsg) { + mFgContext->sendMsg(firstMsg); + } + + return mFgContext; +} + +ContextBase* LocDualContext::getLocBgContext(LocThread::tCreate tCreator, + LocMsg* firstMsg, const char* name, bool joinable) +{ + pthread_mutex_lock(&LocDualContext::mGetLocContextMutex); + LOC_LOGD("%s:%d]: querying ContextBase with tCreator", __func__, __LINE__); + if (NULL == mBgContext) { + LOC_LOGD("%s:%d]: creating msgTask with tCreator", __func__, __LINE__); + const MsgTask* msgTask = getMsgTask(tCreator, name, joinable); + mBgContext = new LocDualContext(msgTask, + mBgExclMask); + } + if(NULL == mInjectContext) { + LOC_LOGD("%s:%d]: mInjectContext is BgContext", __func__, __LINE__); + mInjectContext = mBgContext; + injectFeatureConfig(mInjectContext); + } + pthread_mutex_unlock(&LocDualContext::mGetLocContextMutex); + + if (firstMsg) { + mBgContext->sendMsg(firstMsg); + } + + return mBgContext; +} + +void LocDualContext :: injectFeatureConfig(ContextBase *curContext) +{ + LOC_LOGD("%s:%d]: Enter", __func__, __LINE__); + if(curContext == mInjectContext) { + LOC_LOGD("%s:%d]: Calling LBSProxy (%p) to inject feature config", + __func__, __LINE__, ((LocDualContext *)mInjectContext)->mLBSProxy); + ((LocDualContext *)mInjectContext)->mLBSProxy->injectFeatureConfig(curContext); + } + LOC_LOGD("%s:%d]: Exit", __func__, __LINE__); +} + +LocDualContext::LocDualContext(const MsgTask* msgTask, + LOC_API_ADAPTER_EVENT_MASK_T exMask) : + ContextBase(msgTask, exMask, mLBSLibName) +{ +} + +} diff --git a/gps/core/LocDualContext.h b/gps/core/LocDualContext.h new file mode 100644 index 000000000..ce77a1aae --- /dev/null +++ b/gps/core/LocDualContext.h @@ -0,0 +1,76 @@ +/* Copyright (c) 2011-2014, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef __LOC_ENG_CONTEXT__ +#define __LOC_ENG_CONTEXT__ + +#include +#include +#include +#include + +namespace loc_core { + +class LocDualContext : public ContextBase { + static const MsgTask* mMsgTask; + static ContextBase* mFgContext; + static ContextBase* mBgContext; + static ContextBase* mInjectContext; + static const MsgTask* getMsgTask(LocThread::tCreate tCreator, + const char* name, bool joinable = true); + static const MsgTask* getMsgTask(const char* name, bool joinable = true); + static pthread_mutex_t mGetLocContextMutex; + +protected: + LocDualContext(const MsgTask* msgTask, + LOC_API_ADAPTER_EVENT_MASK_T exMask); + inline virtual ~LocDualContext() {} + +public: + static const char* mLBSLibName; + static const LOC_API_ADAPTER_EVENT_MASK_T mFgExclMask; + static const LOC_API_ADAPTER_EVENT_MASK_T mBgExclMask; + static const char* mLocationHalName; + + static ContextBase* getLocFgContext(LocThread::tCreate tCreator, LocMsg* firstMsg, + const char* name, bool joinable = true); + inline static ContextBase* getLocFgContext(const char* name, bool joinable = true) { + return getLocFgContext(NULL, NULL, name, joinable); + } + static ContextBase* getLocBgContext(LocThread::tCreate tCreator, LocMsg* firstMsg, + const char* name, bool joinable = true); + inline static ContextBase* getLocBgContext(const char* name, bool joinable = true) { + return getLocBgContext(NULL, NULL, name, joinable); + } + + static void injectFeatureConfig(ContextBase *context); +}; + +} + +#endif //__LOC_ENG_CONTEXT__ diff --git a/gps/core/UlpProxyBase.h b/gps/core/UlpProxyBase.h new file mode 100644 index 000000000..efcf98a75 --- /dev/null +++ b/gps/core/UlpProxyBase.h @@ -0,0 +1,86 @@ +/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef ULP_PROXY_BASE_H +#define ULP_PROXY_BASE_H + +#include + +struct FlpExtLocation_s; +struct FlpExtBatchOptions; + +namespace loc_core { + +class LocAdapterBase; + +class UlpProxyBase { +public: + LocPosMode mPosMode; + bool mFixSet; + inline UlpProxyBase() { + mPosMode.mode = LOC_POSITION_MODE_INVALID; + mFixSet = false; + } + inline virtual ~UlpProxyBase() {} + inline virtual bool sendStartFix() { mFixSet = true; return false; } + inline virtual bool sendStopFix() { mFixSet = false; return false; } + inline virtual bool sendFixMode(LocPosMode ¶ms) { + mPosMode = params; + return false; + } + + inline virtual bool reportPosition(UlpLocation &location, + GpsLocationExtended &locationExtended, + void* locationExt, + enum loc_sess_status status, + LocPosTechMask loc_technology_mask) { + return false; + } + inline virtual bool reportSv(GnssSvStatus &svStatus, + GpsLocationExtended &locationExtended, + void* svExt) { + return false; + } + inline virtual bool reportStatus(GpsStatusValue status) { + return false; + } + inline virtual void setAdapter(LocAdapterBase* adapter) {} + inline virtual void setCapabilities(unsigned long capabilities) {} + inline virtual bool reportBatchingSession(FlpExtBatchOptions &options, + bool active) { + return false; + } + inline virtual bool reportPositions(const struct FlpExtLocation_s* locations, + int32_t number_of_locations) { + return false; + } +}; + +} // namespace loc_core + +#endif // ULP_PROXY_BASE_H diff --git a/gps/core/gps_extended.h b/gps/core/gps_extended.h new file mode 100644 index 000000000..88b0415b7 --- /dev/null +++ b/gps/core/gps_extended.h @@ -0,0 +1,92 @@ +/* Copyright (c) 2013, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef GPS_EXTENDED_H +#define GPS_EXTENDED_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include + +struct LocPosMode +{ + LocPositionMode mode; + GpsPositionRecurrence recurrence; + uint32_t min_interval; + uint32_t preferred_accuracy; + uint32_t preferred_time; + char credentials[14]; + char provider[8]; + LocPosMode(LocPositionMode m, GpsPositionRecurrence recr, + uint32_t gap, uint32_t accu, uint32_t time, + const char* cred, const char* prov) : + mode(m), recurrence(recr), + min_interval(gap < MIN_POSSIBLE_FIX_INTERVAL ? MIN_POSSIBLE_FIX_INTERVAL : gap), + preferred_accuracy(accu), preferred_time(time) { + memset(credentials, 0, sizeof(credentials)); + memset(provider, 0, sizeof(provider)); + if (NULL != cred) { + memcpy(credentials, cred, sizeof(credentials)-1); + } + if (NULL != prov) { + memcpy(provider, prov, sizeof(provider)-1); + } + } + + inline LocPosMode() : + mode(LOC_POSITION_MODE_MS_BASED), + recurrence(GPS_POSITION_RECURRENCE_PERIODIC), + min_interval(MIN_POSSIBLE_FIX_INTERVAL), + preferred_accuracy(50), preferred_time(120000) { + memset(credentials, 0, sizeof(credentials)); + memset(provider, 0, sizeof(provider)); + } + + inline bool equals(const LocPosMode &anotherMode) const + { + return anotherMode.mode == mode && + anotherMode.recurrence == recurrence && + anotherMode.min_interval == min_interval && + anotherMode.preferred_accuracy == preferred_accuracy && + anotherMode.preferred_time == preferred_time && + !strncmp(anotherMode.credentials, credentials, sizeof(credentials)-1) && + !strncmp(anotherMode.provider, provider, sizeof(provider)-1); + } + + void logv() const; +}; + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* GPS_EXTENDED_H */ + diff --git a/gps/core/gps_extended_c.h b/gps/core/gps_extended_c.h new file mode 100644 index 000000000..75ee17e3e --- /dev/null +++ b/gps/core/gps_extended_c.h @@ -0,0 +1,438 @@ +/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef GPS_EXTENDED_C_H +#define GPS_EXTENDED_C_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include +#include +#include +#include +#include + +/** Location has valid source information. */ +#define LOCATION_HAS_SOURCE_INFO 0x0020 +/** GpsLocation has valid "is indoor?" flag */ +#define GPS_LOCATION_HAS_IS_INDOOR 0x0040 +/** GpsLocation has valid floor number */ +#define GPS_LOCATION_HAS_FLOOR_NUMBER 0x0080 +/** GpsLocation has valid map URL*/ +#define GPS_LOCATION_HAS_MAP_URL 0x0100 +/** GpsLocation has valid map index */ +#define GPS_LOCATION_HAS_MAP_INDEX 0x0200 + +/** Sizes for indoor fields */ +#define GPS_LOCATION_MAP_URL_SIZE 400 +#define GPS_LOCATION_MAP_INDEX_SIZE 16 + +/** Position source is ULP */ +#define ULP_LOCATION_IS_FROM_HYBRID 0x0001 +/** Position source is GNSS only */ +#define ULP_LOCATION_IS_FROM_GNSS 0x0002 +/** Position source is ZPP only */ +#define ULP_LOCATION_IS_FROM_ZPP 0x0004 +/** Position is from a Geofence Breach Event */ +#define ULP_LOCATION_IS_FROM_GEOFENCE 0X0008 +/** Position is from Hardware FLP */ +#define ULP_LOCATION_IS_FROM_HW_FLP 0x0010 +/** Position is from NLP */ +#define ULP_LOCATION_IS_FROM_NLP 0x0020 +/** Position is from PIP */ +#define ULP_LOCATION_IS_FROM_PIP 0x0040 + +#define ULP_MIN_INTERVAL_INVALID 0xffffffff + +/*Emergency SUPL*/ +#define GPS_NI_TYPE_EMERGENCY_SUPL 4 + +#define AGPS_CERTIFICATE_MAX_LENGTH 2000 +#define AGPS_CERTIFICATE_MAX_SLOTS 10 + +enum loc_registration_mask_status { + LOC_REGISTRATION_MASK_ENABLED, + LOC_REGISTRATION_MASK_DISABLED +}; + +typedef struct { + /** set to sizeof(UlpLocation) */ + size_t size; + GpsLocation gpsLocation; + /* Provider indicator for HYBRID or GPS */ + uint16_t position_source; + /*allows HAL to pass additional information related to the location */ + int rawDataSize; /* in # of bytes */ + void * rawData; + bool is_indoor; + float floor_number; + char map_url[GPS_LOCATION_MAP_URL_SIZE]; + unsigned char map_index[GPS_LOCATION_MAP_INDEX_SIZE]; +} UlpLocation; + +/** AGPS type */ +typedef int16_t AGpsExtType; +#define AGPS_TYPE_INVALID -1 +#define AGPS_TYPE_ANY 0 +#define AGPS_TYPE_SUPL 1 +#define AGPS_TYPE_C2K 2 +#define AGPS_TYPE_WWAN_ANY 3 +#define AGPS_TYPE_WIFI 4 +#define AGPS_TYPE_SUPL_ES 5 + +/** SSID length */ +#define SSID_BUF_SIZE (32+1) + +typedef int16_t AGpsBearerType; +#define AGPS_APN_BEARER_INVALID -1 +#define AGPS_APN_BEARER_IPV4 0 +#define AGPS_APN_BEARER_IPV6 1 +#define AGPS_APN_BEARER_IPV4V6 2 + +/** GPS extended callback structure. */ +typedef struct { + /** set to sizeof(GpsCallbacks) */ + size_t size; + gps_set_capabilities set_capabilities_cb; + gps_acquire_wakelock acquire_wakelock_cb; + gps_release_wakelock release_wakelock_cb; + gps_create_thread create_thread_cb; + gps_request_utc_time request_utc_time_cb; +} GpsExtCallbacks; + +/** Callback to report the xtra server url to the client. + * The client should use this url when downloading xtra unless overwritten + * in the gps.conf file + */ +typedef void (* report_xtra_server)(const char*, const char*, const char*); + +/** Callback structure for the XTRA interface. */ +typedef struct { + gps_xtra_download_request download_request_cb; + gps_create_thread create_thread_cb; + report_xtra_server report_xtra_server_cb; +} GpsXtraExtCallbacks; + +/** Represents the status of AGPS. */ +typedef struct { + /** set to sizeof(AGpsExtStatus) */ + size_t size; + + AGpsExtType type; + AGpsStatusValue status; + uint32_t ipv4_addr; + struct sockaddr_storage addr; + char ssid[SSID_BUF_SIZE]; + char password[SSID_BUF_SIZE]; +} AGpsExtStatus; + +/** Callback with AGPS status information. + * Can only be called from a thread created by create_thread_cb. + */ +typedef void (* agps_status_extended)(AGpsExtStatus* status); + +/** Callback structure for the AGPS interface. */ +typedef struct { + agps_status_extended status_cb; + gps_create_thread create_thread_cb; +} AGpsExtCallbacks; + + +/** GPS NI callback structure. */ +typedef struct +{ + /** + * Sends the notification request from HAL to GPSLocationProvider. + */ + gps_ni_notify_callback notify_cb; + gps_create_thread create_thread_cb; +} GpsNiExtCallbacks; + +typedef enum loc_server_type { + LOC_AGPS_CDMA_PDE_SERVER, + LOC_AGPS_CUSTOM_PDE_SERVER, + LOC_AGPS_MPC_SERVER, + LOC_AGPS_SUPL_SERVER +} LocServerType; + +typedef enum loc_position_mode_type { + LOC_POSITION_MODE_INVALID = -1, + LOC_POSITION_MODE_STANDALONE = 0, + LOC_POSITION_MODE_MS_BASED, + LOC_POSITION_MODE_MS_ASSISTED, + LOC_POSITION_MODE_RESERVED_1, + LOC_POSITION_MODE_RESERVED_2, + LOC_POSITION_MODE_RESERVED_3, + LOC_POSITION_MODE_RESERVED_4, + LOC_POSITION_MODE_RESERVED_5 + +} LocPositionMode; + +#define MIN_POSSIBLE_FIX_INTERVAL 1000 /* msec */ + +/** Flags to indicate which values are valid in a GpsLocationExtended. */ +typedef uint16_t GpsLocationExtendedFlags; +/** GpsLocationExtended has valid pdop, hdop, vdop. */ +#define GPS_LOCATION_EXTENDED_HAS_DOP 0x0001 +/** GpsLocationExtended has valid altitude mean sea level. */ +#define GPS_LOCATION_EXTENDED_HAS_ALTITUDE_MEAN_SEA_LEVEL 0x0002 +/** UlpLocation has valid magnetic deviation. */ +#define GPS_LOCATION_EXTENDED_HAS_MAG_DEV 0x0004 +/** UlpLocation has valid mode indicator. */ +#define GPS_LOCATION_EXTENDED_HAS_MODE_IND 0x0008 +/** GpsLocationExtended has valid vertical uncertainty */ +#define GPS_LOCATION_EXTENDED_HAS_VERT_UNC 0x0010 +/** GpsLocationExtended has valid speed uncertainty */ +#define GPS_LOCATION_EXTENDED_HAS_SPEED_UNC 0x0020 +/** GpsLocationExtended has valid heading uncertainty */ +#define GPS_LOCATION_EXTENDED_HAS_BEARING_UNC 0x0040 +/** GpsLocationExtended has valid horizontal reliability */ +#define GPS_LOCATION_EXTENDED_HAS_HOR_RELIABILITY 0x0080 +/** GpsLocationExtended has valid vertical reliability */ +#define GPS_LOCATION_EXTENDED_HAS_VERT_RELIABILITY 0x0100 + +typedef enum { + LOC_RELIABILITY_NOT_SET = 0, + LOC_RELIABILITY_VERY_LOW = 1, + LOC_RELIABILITY_LOW = 2, + LOC_RELIABILITY_MEDIUM = 3, + LOC_RELIABILITY_HIGH = 4 +}LocReliability; + +/** Represents gps location extended. */ +typedef struct { + /** set to sizeof(GpsLocationExtended) */ + size_t size; + /** Contains GpsLocationExtendedFlags bits. */ + uint16_t flags; + /** Contains the Altitude wrt mean sea level */ + float altitudeMeanSeaLevel; + /** Contains Position Dilusion of Precision. */ + float pdop; + /** Contains Horizontal Dilusion of Precision. */ + float hdop; + /** Contains Vertical Dilusion of Precision. */ + float vdop; + /** Contains Magnetic Deviation. */ + float magneticDeviation; + /** vertical uncertainty in meters */ + float vert_unc; + /** speed uncertainty in m/s */ + float speed_unc; + /** heading uncertainty in degrees (0 to 359.999) */ + float bearing_unc; + /** horizontal reliability. */ + LocReliability horizontal_reliability; + /** vertical reliability. */ + LocReliability vertical_reliability; +} GpsLocationExtended; + +/** Represents SV status. */ +typedef struct { + /** set to sizeof(GnssSvStatus) */ + size_t size; + + /** Number of SVs currently visible. */ + int num_svs; + + /** Contains an array of SV information. */ + GpsSvInfo sv_list[GPS_MAX_SVS]; + + /** Represents a bit mask indicating which SVs + * have ephemeris data. + */ + uint32_t ephemeris_mask; + + /** Represents a bit mask indicating which SVs + * have almanac data. + */ + uint32_t almanac_mask; + + /** + * Represents a bit mask indicating which GPS SVs + * were used for computing the most recent position fix. + */ + uint32_t gps_used_in_fix_mask; + + /** + * Represents a bit mask indicating which GLONASS SVs + * were used for computing the most recent position fix. + */ + uint32_t glo_used_in_fix_mask; + + /** + * Represents a bit mask indicating which BDS SVs + * were used for computing the most recent position fix. + */ + uint64_t bds_used_in_fix_mask; + +} GnssSvStatus; + +enum loc_sess_status { + LOC_SESS_SUCCESS, + LOC_SESS_INTERMEDIATE, + LOC_SESS_FAILURE +}; + +typedef uint32_t LocPosTechMask; +#define LOC_POS_TECH_MASK_DEFAULT ((LocPosTechMask)0x00000000) +#define LOC_POS_TECH_MASK_SATELLITE ((LocPosTechMask)0x00000001) +#define LOC_POS_TECH_MASK_CELLID ((LocPosTechMask)0x00000002) +#define LOC_POS_TECH_MASK_WIFI ((LocPosTechMask)0x00000004) +#define LOC_POS_TECH_MASK_SENSORS ((LocPosTechMask)0x00000008) +#define LOC_POS_TECH_MASK_REFERENCE_LOCATION ((LocPosTechMask)0x00000010) +#define LOC_POS_TECH_MASK_INJECTED_COARSE_POSITION ((LocPosTechMask)0x00000020) +#define LOC_POS_TECH_MASK_AFLT ((LocPosTechMask)0x00000040) +#define LOC_POS_TECH_MASK_HYBRID ((LocPosTechMask)0x00000080) + +typedef enum { + LOC_ENG_IF_REQUEST_SENDER_ID_QUIPC = 0, + LOC_ENG_IF_REQUEST_SENDER_ID_MSAPM, + LOC_ENG_IF_REQUEST_SENDER_ID_MSAPU, + LOC_ENG_IF_REQUEST_SENDER_ID_GPSONE_DAEMON, + LOC_ENG_IF_REQUEST_SENDER_ID_MODEM, + LOC_ENG_IF_REQUEST_SENDER_ID_UNKNOWN +} loc_if_req_sender_id_e_type; + + +#define smaller_of(a, b) (((a) > (b)) ? (b) : (a)) +#define MAX_APN_LEN 100 + +// This will be overridden by the individual adapters +// if necessary. +#define DEFAULT_IMPL(rtv) \ +{ \ + LOC_LOGD("%s: default implementation invoked", __func__); \ + return rtv; \ +} + +enum loc_api_adapter_err { + LOC_API_ADAPTER_ERR_SUCCESS = 0, + LOC_API_ADAPTER_ERR_GENERAL_FAILURE = 1, + LOC_API_ADAPTER_ERR_UNSUPPORTED = 2, + LOC_API_ADAPTER_ERR_INVALID_HANDLE = 4, + LOC_API_ADAPTER_ERR_INVALID_PARAMETER = 5, + LOC_API_ADAPTER_ERR_ENGINE_BUSY = 6, + LOC_API_ADAPTER_ERR_PHONE_OFFLINE = 7, + LOC_API_ADAPTER_ERR_TIMEOUT = 8, + LOC_API_ADAPTER_ERR_SERVICE_NOT_PRESENT = 9, + LOC_API_ADAPTER_ERR_INTERNAL = 10, + + /* equating engine down to phone offline, as they are the same errror */ + LOC_API_ADAPTER_ERR_ENGINE_DOWN = LOC_API_ADAPTER_ERR_PHONE_OFFLINE, + LOC_API_ADAPTER_ERR_FAILURE = 101, + LOC_API_ADAPTER_ERR_UNKNOWN +}; + +enum loc_api_adapter_event_index { + LOC_API_ADAPTER_REPORT_POSITION = 0, // Position report comes in loc_parsed_position_s_type + LOC_API_ADAPTER_REPORT_SATELLITE, // Satellite in view report + LOC_API_ADAPTER_REPORT_NMEA_1HZ, // NMEA report at 1HZ rate + LOC_API_ADAPTER_REPORT_NMEA_POSITION, // NMEA report at position report rate + LOC_API_ADAPTER_REQUEST_NI_NOTIFY_VERIFY, // NI notification/verification request + LOC_API_ADAPTER_REQUEST_ASSISTANCE_DATA, // Assistance data, eg: time, predicted orbits request + LOC_API_ADAPTER_REQUEST_LOCATION_SERVER, // Request for location server + LOC_API_ADAPTER_REPORT_IOCTL, // Callback report for loc_ioctl + LOC_API_ADAPTER_REPORT_STATUS, // Misc status report: eg, engine state + LOC_API_ADAPTER_REQUEST_WIFI, // + LOC_API_ADAPTER_SENSOR_STATUS, // + LOC_API_ADAPTER_REQUEST_TIME_SYNC, // + LOC_API_ADAPTER_REPORT_SPI, // + LOC_API_ADAPTER_REPORT_NI_GEOFENCE, // + LOC_API_ADAPTER_GEOFENCE_GEN_ALERT, // + LOC_API_ADAPTER_REPORT_GENFENCE_BREACH, // + LOC_API_ADAPTER_PEDOMETER_CTRL, // + LOC_API_ADAPTER_MOTION_CTRL, // + LOC_API_ADAPTER_REQUEST_WIFI_AP_DATA, // Wifi ap data + LOC_API_ADAPTER_BATCH_FULL, // Batching on full + LOC_API_ADAPTER_BATCHED_POSITION_REPORT, // Batching on fix + LOC_API_ADAPTER_BATCHED_GENFENCE_BREACH_REPORT, // + LOC_API_ADAPTER_GDT_UPLOAD_BEGIN_REQ, // GDT upload start request + LOC_API_ADAPTER_GDT_UPLOAD_END_REQ, // GDT upload end request + LOC_API_ADAPTER_GNSS_MEASUREMENT, // GNSS Measurement report + LOC_API_ADAPTER_REQUEST_TIMEZONE, // Timezone injection request + LOC_API_ADAPTER_REPORT_GENFENCE_DWELL_REPORT, // Geofence dwell report + LOC_API_ADAPTER_EVENT_MAX +}; + +#define LOC_API_ADAPTER_BIT_PARSED_POSITION_REPORT (1< +#include +#include + +void LocPosMode::logv() const +{ + LOC_LOGV ("Position mode: %s\n Position recurrence: %s\n " + "min interval: %d\n preferred accuracy: %d\n " + "preferred time: %d\n credentials: %s provider: %s", + loc_get_position_mode_name(mode), + loc_get_position_recurrence_name(recurrence), + min_interval, + preferred_accuracy, + preferred_time, + credentials, + provider); +} + +/* GPS status names */ +static const loc_name_val_s_type gps_status_name[] = +{ + NAME_VAL( GPS_STATUS_NONE ), + NAME_VAL( GPS_STATUS_SESSION_BEGIN ), + NAME_VAL( GPS_STATUS_SESSION_END ), + NAME_VAL( GPS_STATUS_ENGINE_ON ), + NAME_VAL( GPS_STATUS_ENGINE_OFF ), +}; +static const int gps_status_num = sizeof(gps_status_name) / sizeof(loc_name_val_s_type); + +/* Find Android GPS status name */ +const char* loc_get_gps_status_name(GpsStatusValue gps_status) +{ + return loc_get_name_from_val(gps_status_name, gps_status_num, + (long) gps_status); +} + + + +static const loc_name_val_s_type loc_eng_position_modes[] = +{ + NAME_VAL( LOC_POSITION_MODE_STANDALONE ), + NAME_VAL( LOC_POSITION_MODE_MS_BASED ), + NAME_VAL( LOC_POSITION_MODE_MS_ASSISTED ), + NAME_VAL( LOC_POSITION_MODE_RESERVED_1 ), + NAME_VAL( LOC_POSITION_MODE_RESERVED_2 ), + NAME_VAL( LOC_POSITION_MODE_RESERVED_3 ), + NAME_VAL( LOC_POSITION_MODE_RESERVED_4 ), + NAME_VAL( LOC_POSITION_MODE_RESERVED_5 ) +}; +static const int loc_eng_position_mode_num = sizeof(loc_eng_position_modes) / sizeof(loc_name_val_s_type); + +const char* loc_get_position_mode_name(GpsPositionMode mode) +{ + return loc_get_name_from_val(loc_eng_position_modes, loc_eng_position_mode_num, (long) mode); +} + + + +static const loc_name_val_s_type loc_eng_position_recurrences[] = +{ + NAME_VAL( GPS_POSITION_RECURRENCE_PERIODIC ), + NAME_VAL( GPS_POSITION_RECURRENCE_SINGLE ) +}; +static const int loc_eng_position_recurrence_num = sizeof(loc_eng_position_recurrences) / sizeof(loc_name_val_s_type); + +const char* loc_get_position_recurrence_name(GpsPositionRecurrence recur) +{ + return loc_get_name_from_val(loc_eng_position_recurrences, loc_eng_position_recurrence_num, (long) recur); +} + + + +static const loc_name_val_s_type loc_eng_aiding_data_bits[] = +{ + NAME_VAL( GPS_DELETE_EPHEMERIS ), + NAME_VAL( GPS_DELETE_ALMANAC ), + NAME_VAL( GPS_DELETE_POSITION ), + NAME_VAL( GPS_DELETE_TIME ), + NAME_VAL( GPS_DELETE_IONO ), + NAME_VAL( GPS_DELETE_UTC ), + NAME_VAL( GPS_DELETE_HEALTH ), + NAME_VAL( GPS_DELETE_SVDIR ), + NAME_VAL( GPS_DELETE_SVSTEER ), + NAME_VAL( GPS_DELETE_SADATA ), + NAME_VAL( GPS_DELETE_RTI ), + NAME_VAL( GPS_DELETE_CELLDB_INFO ), + NAME_VAL( GPS_DELETE_ALL) +}; +static const int loc_eng_aiding_data_bit_num = sizeof(loc_eng_aiding_data_bits) / sizeof(loc_name_val_s_type); + +const char* loc_get_aiding_data_mask_names(GpsAidingData data) +{ + return NULL; +} + + +static const loc_name_val_s_type loc_eng_agps_types[] = +{ + NAME_VAL( AGPS_TYPE_INVALID ), + NAME_VAL( AGPS_TYPE_ANY ), + NAME_VAL( AGPS_TYPE_SUPL ), + NAME_VAL( AGPS_TYPE_C2K ), + NAME_VAL( AGPS_TYPE_WWAN_ANY ) +}; +static const int loc_eng_agps_type_num = sizeof(loc_eng_agps_types) / sizeof(loc_name_val_s_type); + +const char* loc_get_agps_type_name(AGpsType type) +{ + return loc_get_name_from_val(loc_eng_agps_types, loc_eng_agps_type_num, (long) type); +} + + +static const loc_name_val_s_type loc_eng_ni_types[] = +{ + NAME_VAL( GPS_NI_TYPE_VOICE ), + NAME_VAL( GPS_NI_TYPE_UMTS_SUPL ), + NAME_VAL( GPS_NI_TYPE_UMTS_CTRL_PLANE ), + NAME_VAL( GPS_NI_TYPE_EMERGENCY_SUPL ) +}; +static const int loc_eng_ni_type_num = sizeof(loc_eng_ni_types) / sizeof(loc_name_val_s_type); + +const char* loc_get_ni_type_name(GpsNiType type) +{ + return loc_get_name_from_val(loc_eng_ni_types, loc_eng_ni_type_num, (long) type); +} + + +static const loc_name_val_s_type loc_eng_ni_responses[] = +{ + NAME_VAL( GPS_NI_RESPONSE_ACCEPT ), + NAME_VAL( GPS_NI_RESPONSE_DENY ), + NAME_VAL( GPS_NI_RESPONSE_DENY ) +}; +static const int loc_eng_ni_reponse_num = sizeof(loc_eng_ni_responses) / sizeof(loc_name_val_s_type); + +const char* loc_get_ni_response_name(GpsUserResponseType response) +{ + return loc_get_name_from_val(loc_eng_ni_responses, loc_eng_ni_reponse_num, (long) response); +} + + +static const loc_name_val_s_type loc_eng_ni_encodings[] = +{ + NAME_VAL( GPS_ENC_NONE ), + NAME_VAL( GPS_ENC_SUPL_GSM_DEFAULT ), + NAME_VAL( GPS_ENC_SUPL_UTF8 ), + NAME_VAL( GPS_ENC_SUPL_UCS2 ), + NAME_VAL( GPS_ENC_UNKNOWN ) +}; +static const int loc_eng_ni_encoding_num = sizeof(loc_eng_ni_encodings) / sizeof(loc_name_val_s_type); + +const char* loc_get_ni_encoding_name(GpsNiEncodingType encoding) +{ + return loc_get_name_from_val(loc_eng_ni_encodings, loc_eng_ni_encoding_num, (long) encoding); +} + +static const loc_name_val_s_type loc_eng_agps_bears[] = +{ + NAME_VAL( AGPS_APN_BEARER_INVALID ), + NAME_VAL( AGPS_APN_BEARER_IPV4 ), + NAME_VAL( AGPS_APN_BEARER_IPV6 ), + NAME_VAL( AGPS_APN_BEARER_IPV4V6 ) +}; +static const int loc_eng_agps_bears_num = sizeof(loc_eng_agps_bears) / sizeof(loc_name_val_s_type); + +const char* loc_get_agps_bear_name(AGpsBearerType bearer) +{ + return loc_get_name_from_val(loc_eng_agps_bears, loc_eng_agps_bears_num, (long) bearer); +} + +static const loc_name_val_s_type loc_eng_server_types[] = +{ + NAME_VAL( LOC_AGPS_CDMA_PDE_SERVER ), + NAME_VAL( LOC_AGPS_CUSTOM_PDE_SERVER ), + NAME_VAL( LOC_AGPS_MPC_SERVER ), + NAME_VAL( LOC_AGPS_SUPL_SERVER ) +}; +static const int loc_eng_server_types_num = sizeof(loc_eng_server_types) / sizeof(loc_name_val_s_type); + +const char* loc_get_server_type_name(LocServerType type) +{ + return loc_get_name_from_val(loc_eng_server_types, loc_eng_server_types_num, (long) type); +} + +static const loc_name_val_s_type loc_eng_position_sess_status_types[] = +{ + NAME_VAL( LOC_SESS_SUCCESS ), + NAME_VAL( LOC_SESS_INTERMEDIATE ), + NAME_VAL( LOC_SESS_FAILURE ) +}; +static const int loc_eng_position_sess_status_num = sizeof(loc_eng_position_sess_status_types) / sizeof(loc_name_val_s_type); + +const char* loc_get_position_sess_status_name(enum loc_sess_status status) +{ + return loc_get_name_from_val(loc_eng_position_sess_status_types, loc_eng_position_sess_status_num, (long) status); +} + +static const loc_name_val_s_type loc_eng_agps_status_names[] = +{ + NAME_VAL( GPS_REQUEST_AGPS_DATA_CONN ), + NAME_VAL( GPS_RELEASE_AGPS_DATA_CONN ), + NAME_VAL( GPS_AGPS_DATA_CONNECTED ), + NAME_VAL( GPS_AGPS_DATA_CONN_DONE ), + NAME_VAL( GPS_AGPS_DATA_CONN_FAILED ) +}; +static const int loc_eng_agps_status_num = sizeof(loc_eng_agps_status_names) / sizeof(loc_name_val_s_type); + +const char* loc_get_agps_status_name(AGpsStatusValue status) +{ + return loc_get_name_from_val(loc_eng_agps_status_names, loc_eng_agps_status_num, (long) status); +} diff --git a/gps/core/loc_core_log.h b/gps/core/loc_core_log.h new file mode 100644 index 000000000..8a1825ac3 --- /dev/null +++ b/gps/core/loc_core_log.h @@ -0,0 +1,58 @@ +/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef LOC_CORE_LOG_H +#define LOC_CORE_LOG_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include +#include + +const char* loc_get_gps_status_name(GpsStatusValue gps_status); +const char* loc_get_position_mode_name(GpsPositionMode mode); +const char* loc_get_position_recurrence_name(GpsPositionRecurrence recur); +const char* loc_get_aiding_data_mask_names(GpsAidingData data); +const char* loc_get_agps_type_name(AGpsType type); +const char* loc_get_ni_type_name(GpsNiType type); +const char* loc_get_ni_response_name(GpsUserResponseType response); +const char* loc_get_ni_encoding_name(GpsNiEncodingType encoding); +const char* loc_get_agps_bear_name(AGpsBearerType bear); +const char* loc_get_server_type_name(LocServerType type); +const char* loc_get_position_sess_status_name(enum loc_sess_status status); +const char* loc_get_agps_status_name(AGpsStatusValue status); + +#ifdef __cplusplus +} +#endif + +#endif /* LOC_CORE_LOG_H */ diff --git a/gps/etc/flp.conf b/gps/etc/flp.conf new file mode 100644 index 000000000..7d6002ff8 --- /dev/null +++ b/gps/etc/flp.conf @@ -0,0 +1,60 @@ +################################### +##### FLP settings ##### +################################### + +################################### +# FLP BATCHING SIZE +################################### +# The number of batched locations +# requested to modem. The desired number +# defined below may not be satisfied, as +# the modem can only return the number +# of batched locations that can be allocated, +# which is limited by memory. The default +# batch size defined as 20 as below. +BATCH_SIZE=20 + +################################### +# FLP BATCHING SESSION TIMEOUT +################################### +# Duration with which batch session timeout +# happens in milliseconds. If not specified +# or set to zero, batching session timeout +# defaults to 20 seconds by the modem. +# BATCH_SESSION_TIMEOUT=20000 + +################################### +# FLP CAPABILITIES BIT MASK +################################### +# GEOFENCE = 0x01 +# BATCHING = 0x02 +# default = GEOFENCE | BATCHING +CAPABILITIES=0x03 + +################################### +# FLP BATCHING ACCURACY +################################### +# Set to one of the defined values below +# to define the accuracy of batching. +# If not specified, accuracy defaults +# to LOW. +# FLP BATCHING ACCURACY values: +# Low accuracy = 0 +# Medium accuracy = 1 +# High accuracy = 2 +ACCURACY=0 + +################################### +# FLP GEOFENCE RESPONSIVENESS +################################### +# If set to one of the defined values below, +# it will override the responsiveness for +# FLP geofence, which implements the fused +# location API. If not set to a value defined +# below, which is default, it will not +# override the responsivness. +# FLP_GEOFENCE_RESPONSIVENESS_OVERRIDE Values: +# 1: LOW responsiveness +# 2: MEDIUM responsiveness +# 3: HIGH responsiveness +FLP_GEOFENCE_RESPONSIVENESS_OVERRIDE = 0 diff --git a/gps/etc/gps.conf b/gps/etc/gps.conf new file mode 100644 index 000000000..ea1b9aca3 --- /dev/null +++ b/gps/etc/gps.conf @@ -0,0 +1,127 @@ +#Uncommenting these urls would only enable +#the power up auto injection and force injection(test case). +#XTRA_SERVER_1=http://xtrapath1.izatcloud.net/xtra2.bin +#XTRA_SERVER_2=http://xtrapath2.izatcloud.net/xtra2.bin +#XTRA_SERVER_3=http://xtrapath3.izatcloud.net/xtra2.bin + +#ifdef VENDOR_EDIT +XTRA_SERVER_1=http://xtrapath1.izatcloud.net/xtra3grc.bin +XTRA_SERVER_2=http://xtrapath2.izatcloud.net/xtra3grc.bin +XTRA_SERVER_3=http://xtrapath3.izatcloud.net/xtra3grc.bin +#endif + +#Version check for XTRA +#DISABLE = 0 +#AUTO = 1 +#XTRA2 = 2 +#XTRA3 = 3 +XTRA_VERSION_CHECK=0 + +# Error Estimate +# _SET = 1 +# _CLEAR = 0 +ERR_ESTIMATE=0 + +#Test +NTP_SERVER=time.gpsonextra.net +#Asia +# NTP_SERVER=asia.pool.ntp.org +#Europe +# NTP_SERVER=europe.pool.ntp.org +#North America +# NTP_SERVER=north-america.pool.ntp.org + +# DEBUG LEVELS: 0 - none, 1 - Error, 2 - Warning, 3 - Info +# 4 - Debug, 5 - Verbose +# If DEBUG_LEVEL is commented, Android's logging levels will be used +DEBUG_LEVEL = 2 + +# Intermediate position report, 1=enable, 0=disable +INTERMEDIATE_POS=0 + +# Below bit mask configures how GPS functionalities +# should be locked when user turns off GPS on Settings +# Set bit 0x1 if MO GPS functionalities are to be locked +# Set bit 0x2 if NI GPS functionalities are to be locked +# default - non is locked for backward compatibility +#GPS_LOCK = 0 + +# supl version 1.0 +SUPL_VER=0x10000 + +# Emergency SUPL, 1=enable, 0=disable +SUPL_ES=0 + +#Choose PDN for Emergency SUPL +#1 - Use emergency PDN +#0 - Use regular SUPL PDN for Emergency SUPL +USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL=1 + +#SUPL_MODE is a bit mask set in config.xml per carrier by default. +#If it is uncommented here, this value will overwrite the value from +#config.xml. +#MSA=0X2 +#MSB=0X1 +#SUPL_MODE= + +# GPS Capabilities bit mask +# SCHEDULING = 0x01 +# MSB = 0x02 +# MSA = 0x04 +# ON_DEMAND_TIME = 0x10 +# GEOFENCE = 0x20 +# default = ON_DEMAND_TIME | MSA | MSB | SCHEDULING | GEOFENCE +CAPABILITIES=0x37 + +# Accuracy threshold for intermediate positions +# less accurate positions are ignored, 0 for passing all positions +# ACCURACY_THRES=5000 + +################################ +##### AGPS server settings ##### +################################ + +# FOR SUPL SUPPORT, set the following +# SUPL_HOST=supl.host.com or IP +# SUPL_PORT=1234 + +# FOR C2K PDE SUPPORT, set the following +# C2K_HOST=c2k.pde.com or IP +# C2K_PORT=1234 + +# Bitmask of slots that are available +# for write/install to, where 1s indicate writable, +# and the default value is 0 where no slots +# are writable. For example, AGPS_CERT_WRITABLE_MASK +# of b1000001010 makes 3 slots available +# and the remaining 7 slots unwritable. +#AGPS_CERT_WRITABLE_MASK=0 + +#################################### +# LTE Positioning Profile Settings +#################################### +# 0: Enable RRLP on LTE(Default) +# 1: Enable LPP_User_Plane on LTE +# 2: Enable LPP_Control_Plane +# 3: Enable both LPP_User_Plane and LPP_Control_Plane +LPP_PROFILE = 2 + +################################ +# EXTRA SETTINGS +################################ +# NMEA provider (1=Modem Processor, 0=Application Processor) +NMEA_PROVIDER=0 +# Mark if it is a SGLTE target (1=SGLTE, 0=nonSGLTE) +SGLTE_TARGET=0 + +################################################## +# Select Positioning Protocol on A-GLONASS system +################################################## +# 0x1: RRC CPlane +# 0x2: RRLP UPlane +# 0x4: LLP Uplane +#ifndef zuoyonghua@oneplus.cn enable all bit mask for GLONASS +#A_GLONASS_POS_PROTOCOL_SELECT = 0 +#else +A_GLONASS_POS_PROTOCOL_SELECT = 15 +#endif diff --git a/gps/etc/izat.conf b/gps/etc/izat.conf new file mode 100644 index 000000000..1877099f1 --- /dev/null +++ b/gps/etc/izat.conf @@ -0,0 +1,198 @@ +######################################### +# Log verbosity control for izat modules +######################################### +# OFF = 0, ERROR = 1, WARNING = 2, INFO = 3, DEBUG = 4, VERBOSE = 5 +IZAT_DEBUG_LEVEL = 2 + +################################################## +# Select WIFI Wait Timeout value in seconds for SUPL +################################################## +WIFI_WAIT_TIMEOUT_SELECT = 0 + +################################ +# NLP Settings +################################ +# NLP_MODE 1: GNP Only, 2: QNP Only, 3: Combo +# NLP_TOLERANCE_TIME_FIRST: Time in ms used in Combo mode +# to determine how much Tolerance for first position +# NLP_TOLERANCE_TIME_AFTER: Time in ms used in Combo mode +# to determine how much Tolerance for positions after first +# NLP_THRESHOLD: Sets how many failures needed before +# switching preferred NLP in Combo mode +# NLP_ACCURACY_MULTIPLE: Determines how far off the accuracy +# must be, in multiples, between two NLP location reports to +# be considered much worse accuracy. Used in switching logic +# NLP COMBO MODE USES QNP WITH NO EULA CONSENT: Determines +# whether or not to still send network location requests to +# QNP when the EULA is not consented to by the user. QNP can +# still return ZPP locations or injected locations even +# without EULA consent, but the uncertainty can be high. +NLP_MODE = 1 +NLP_TOLERANCE_TIME_FIRST = 5000 +NLP_TOLERANCE_TIME_AFTER = 20000 +NLP_THRESHOLD = 3 +NLP_ACCURACY_MULTIPLE = 2 +NLP_COMBO_MODE_USES_QNP_WITH_NO_EULA_CONSENT = 1 + +# Threshold period for ZPP triggers +ZPP_TRIGGER_THRESHOLD=60000 + +################################### +# GEOFENCE SERVICES +################################### +# If set to one of the defined values below, it will override +# the responsiveness for geofence services, which implements +# the Proximity Alert API. If not set to a value defined below, +# which is default, it will not override the responsivness. +# The geofence HAL API is unaffected by this value. +# GEOFENCE_SERVICES_RESPONSIVENESS_OVERRIDE Values: +# 1: LOW responsiveness +# 2: MEDIUM responsiveness +# 3: HIGH responsiveness +GEOFENCE_SERVICES_RESPONSIVENESS_OVERRIDE = 0 + +##################################### +# IZAT PREMIUM FEATURE SETTINGS +##################################### +#Possible states of a feature: +#DISABLED +#BASIC +#PREMIUM + +#GTP_CELL_PROC valid options: +# AP +# MODEM +GTP_CELL_PROC=MODEM + +#GTP_CELL valid modes: +# DISABLED +# BASIC +GTP_CELL=DISABLED + +#GTP_WIFI valid modes: +# DISABLED +# BASIC +GTP_WIFI=DISABLED + +#GTP_WAA valid modes: +# DISABLED +# BASIC +GTP_WAA=DISABLED + +#SAP valid modes: +# DISABLED +# BASIC +# PREMIUM +SAP=BASIC + +#ODCPI valid modes: +#DISABLED +#BASIC +ODCPI=DISABLED + +#FREE_WIFI_SCAN_INJECT valid modes: +#DISABLED +#BASIC +FREE_WIFI_SCAN_INJECT=DISABLED + +#SUPL_WIFI valid modes: +#DISABLED +#BASIC +SUPL_WIFI=DISABLED + +#WIFI_SUPPLICANT_INFO valid modes: +#DISABLED +#BASIC +WIFI_SUPPLICANT_INFO=DISABLED + +##################################### +# Location process launcher settings +##################################### + +#Values for PROCESS_STATE: +# ENABLED +# DISABLED + +#FEATURE MASKS: +# GTP-WIFI 0X03 +# GTP-AP-CELL 0X0c +# GTP-MP-CELL 0xc00 +# GTP-WAA 0X300 +# SAP 0Xc0 +# ODCPI 0x1000 +# FREE_WIFI_SCAN_INJECT 0x2000 +# SUPL_WIFI 0x4000 +# WIFI_SUPPLICANT_INFO 0x8000 + +#Values for PLATFORMS can be: +#1. Any valid values obtained from ro.board.platform separated by single space. For example: msm8960 msm8226 +#2. 'all' or 'all exclude' -> for All platforms +#3. 'all exclude XXXX' -> All platforms exclude XXXX. For example: all exclude msm8937 + +#Values for BASEBAND can be: +#1. Any valid values obtained from ro.baseband separated by single space. For example: sglte sglte2 +#2. 'all' or 'all exclude' -> for all basebands +#3. 'all exclude XXXX' -> All basebands exclude XXXX. For example: all exclude sglte + +#Valyes for LEAN_TARGETS can be: +#ENABLED -> if this process is supposed to run on lean and mean targets +#DISABLED -> if this process is to be disabled on lean and mean targets +PROCESS_NAME=/system/bin/garden_app +PROCESS_ARGUMENT=-u 0 -q 0 -j 0 -g 0 -l 0 -Z 0 -T 1 +PROCESS_STATE=DISABLED +PROCESS_GROUPS=gps net_raw +PREMIUM_FEATURE=0 +IZAT_FEATURE_MASK=0 +PLATFORMS=all +BASEBAND=auto +LEAN_TARGETS=DISABLED + +PROCESS_NAME=/system/bin/gpsone_daemon +PROCESS_ARGUMENT= +PROCESS_STATE=DISABLED +PROCESS_GROUPS=inet net_raw +PREMIUM_FEATURE=0 +IZAT_FEATURE_MASK=0 +PLATFORMS=msm7630_fusion +BASEBAND=svlte2a sglte sglte2 +LEAN_TARGETS=DISABLED + +PROCESS_NAME=/system/bin/lowi-server +PROCESS_ARGUMENT= +PROCESS_STATE=DISABLED +PROCESS_GROUPS=gps net_admin wifi inet qcom_diag net_raw +PREMIUM_FEATURE=0 +IZAT_FEATURE_MASK=0xf303 +PLATFORMS=all +BASEBAND=all +LEAN_TARGETS=DISABLED + +PROCESS_NAME=/system/bin/xtwifi-inet-agent +PROCESS_ARGUMENT= +PROCESS_STATE=DISABLED +PROCESS_GROUPS=inet gps +PREMIUM_FEATURE=1 +IZAT_FEATURE_MASK=0xc0f +PLATFORMS=all +BASEBAND=all +LEAN_TARGETS=DISABLED + +PROCESS_NAME=/system/bin/xtwifi-client +PROCESS_ARGUMENT= +PROCESS_STATE=DISABLED +PROCESS_GROUPS=net_admin wifi inet gps net_raw rfs_shared +PREMIUM_FEATURE=1 +IZAT_FEATURE_MASK=0xf0f +PLATFORMS=all +BASEBAND=all +LEAN_TARGETS=DISABLED + +PROCESS_NAME=/system/vendor/bin/slim_daemon +PROCESS_ARGUMENT= +PROCESS_STATE=ENABLED +PROCESS_GROUPS=gps net_raw qcom_diag +PREMIUM_FEATURE=1 +IZAT_FEATURE_MASK=0xf0 +PLATFORMS=all +BASEBAND=all +LEAN_TARGETS=DISABLED diff --git a/gps/etc/lowi.conf b/gps/etc/lowi.conf new file mode 100644 index 000000000..cfadcb218 --- /dev/null +++ b/gps/etc/lowi.conf @@ -0,0 +1,51 @@ +#*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====* +# +# LOWI Config file +# +# GENERAL DESCRIPTION +# This file contains the config params for LOWI +# +# Copyright (c) 2012-2013 Qualcomm Atheros, Inc. +# All Rights Reserved. +# Qualcomm Atheros Confidential and Proprietary. +# +# Export of this technology or software is regulated by the U.S. Government. +# Diversion contrary to U.S. law prohibited. +#=============================================================================*/ + +# X86 ONLY - UBUNTU: +# Copy this file in the same directory where the executable is + +# The RSSI threshold used in the RTT outlier detection in half decibels. Default value recommended by the +# system team currently is -140 (corresponding to -70 dB). +LOWI_RSSI_THRESHOLD_FOR_RTT = -140 + +# Number of measurment per AP for RTS/CTS +LOWI_RTS_CTS_NUM_MEAS = 5 + +# Maximum Number of Outstanding Requests supported +LOWI_MAX_OUTSTANDING_REQUEST = 255 + +# Maximum number of records in Cache +LOWI_MAX_NUM_CACHE_RECORDS = 200 + +# Default threshold before issuing another fresh scan (ms) +LOWI_FRESH_SCAN_THRESHOLD = 500 + +# Timeout in case no result is reported by the driver (seconds) +LOWI_NO_RESULT_WAIT_TOLERANCE = 10 + +# Use Fake Wifi driver. Only valid for engineering builds +LOWI_USE_FAKE_WIFI_DRIVER = 0 + +# Use ROME Wifi driver. Only valid for engineering builds +# Will be removed later only for development support +LOWI_USE_ROME_WIFI_DRIVER = 0 + +# Use LOWI LP. +# When enabled the Discovery Request will be routed to LOWI-LP +LOWI_USE_LOWI_LP = 1 + +# Log level +# EL_LOG_OFF = 0, EL_ERROR = 1, EL_WARNING = 2, EL_INFO = 3, EL_DEBUG = 4, EL_VERBOSE = 5, EL_LOG_ALL = 100 +LOWI_LOG_LEVEL = 2 diff --git a/gps/etc/sap.conf b/gps/etc/sap.conf new file mode 100644 index 000000000..3e5b508d5 --- /dev/null +++ b/gps/etc/sap.conf @@ -0,0 +1,53 @@ +################################ +# Sensor Settings +################################ +#The following parameters are optional. +#Internal defaults support MEMS sensors +#native to most handset devices. +#Device specific sensor characterization +#for improved performance is possible as +#described in SAP application notes. +#GYRO_BIAS_RANDOM_WALK= +#ACCEL_RANDOM_WALK_SPECTRAL_DENSITY= +#ANGLE_RANDOM_WALK_SPECTRAL_DENSITY= +#RATE_RANDOM_WALK_SPECTRAL_DENSITY= +#VELOCITY_RANDOM_WALK_SPECTRAL_DENSITY= + +# Sensor Sampling Rate Parameters for Low-Data Rate Filter (should be greater than 0) +# used in loc_eng_reinit +SENSOR_ACCEL_BATCHES_PER_SEC=2 +SENSOR_ACCEL_SAMPLES_PER_BATCH=5 +SENSOR_GYRO_BATCHES_PER_SEC=2 +SENSOR_GYRO_SAMPLES_PER_BATCH=5 +# Sensor Sampling Rate Parameters for High-Data Rate Filter (should be greater than 0) +SENSOR_ACCEL_BATCHES_PER_SEC_HIGH=4 +SENSOR_ACCEL_SAMPLES_PER_BATCH_HIGH=25 +SENSOR_GYRO_BATCHES_PER_SEC_HIGH=4 +SENSOR_GYRO_SAMPLES_PER_BATCH_HIGH=25 + +# Sensor Control Mode (0=AUTO, 1=FORCE_ON) +# used in loc_eng_reinit +SENSOR_CONTROL_MODE=1 + +# Enable or Disable Sensors for GPS use (0=Enable, 1=Disable) +# used in loc_eng_reinit +SENSOR_USAGE=0 + +# Choose GSIFF sensor provider (1=Snapdragon Sensors Core, 2=Android NDK) +SENSOR_PROVIDER=1 + +# Bit mask used to define which sensor algorithms are used. +# Setting each bit has the following definition: +# 0x1 - DISABLE_INS_POSITIONING_FILTER +# 0x0 - ENABLE_INS_POSITIONING_FILTER +SENSOR_ALGORITHM_CONFIG_MASK=0x00 + +# Time source used by Sensor HAL +# Setting this value controls accuracy of location sensor services. +# 0 - Unknown +# 1 - CLOCK_BOOTTIME +# 2 - CLOCK_MONOTONIC +# 3 - CLOCK_REALTIME +# 4 - CLOCK_BOOTTIME using Alarm timer interface +NDK_PROVIDER_TIME_SOURCE=1 + diff --git a/gps/etc/xtwifi.conf b/gps/etc/xtwifi.conf new file mode 100644 index 000000000..fc17faaf0 --- /dev/null +++ b/gps/etc/xtwifi.conf @@ -0,0 +1,82 @@ +#GTP AP Project client core config file +# +#GENERAL DESCRIPTION +#This is used by client core +# +#Copyright (c) 2012-2014 Qualcomm Atheros, Inc. +#All Rights Reserved. +#Qualcomm Atheros Confidential and Proprietary. + +# Log verbosity control for most of the GTP WiFi system, including native and +# Java componenets +# OFF = 0, ERROR = 1, WARNING = 2, INFO = 3, DEBUG = 4, VERBOSE = 5, ALL = 100 +DEBUG_GLOBAL_LOG_LEVEL = 2 + +# this is used at the server side to distinguish uploads from different maker/model +# default "Qualcomm" +OEM_ID_IN_REQUEST_TO_SERVER = "Qualcomm" + +# this is used at the server side to distinguish uploads from different maker/model +# default "UNKNOWN" +MODEL_ID_IN_REQUEST_TO_SERVER = "UNKNOWN" + +############################################################################## +# GTP-WiFi positioning config # +############################################################################## + +# URL for the server position request +XT_SERVER_ROOT_URL = https://gtpa1.izatcloud.net:443/uds/v2 + +# size, in bytes, of the cache on device +SIZE_BYTE_TOTAL_CACHE = 5000000 + +# value 0: (default) use the async LOWI wifi scanner +# value 10: FAKE AP wifi scanner +WIFI_SCANNER_CHOICE = 0 + +############################################################################## +# XT-WiFi crowd sourcing config # +############################################################################## +# Use server suggestion for crowd sourcing configuration +ENABLE_SERVER_SUGGESTION_FOR_CROWD_SOURCING = 1 + +# Maximum number of APs to be collected for upload +NUM_MAX_AP_PER_UPLOAD = 16383 +# Number of minutes between upload: 24 hours +INTERVAL_MIN_UPLOAD = 1440 +# Number of minutes between forced upload: 5 days +INTERVAL_MIN_FORCED_UPLOAD = 7200 + +# The minimum time between two collected AP data sets in seconds +INTERVAL_SEC_AP_SETS_COLLECT = 10 +# Timeout for scan interval when phone is on: 600 seconds (10 minute) +INTERVAL_SEC_SCAN = 600 +# Timeout for scan interval when phone has not continusouly on for INTERVAL_MIN_SCAN +INTERVAL_MIN_FORCED_SCAN = 480 + +# Maximum number of Cell DB records for upload +WWAN_MAX_CELLDB_RECORDS_PER_UPLOAD = 1000 + +############################################################################## +# GTP AP cell config # +############################################################################## +# This item specifies the RIL server name. +# This configure item can not be removed in Android target. +XTRAT_WWAN_LITE_LOC_RIL_SERVER_NAME = "OS-Agent" + +# Maximum total number of SNA records cached in mobile storage. +# Max allowed value is 10000 +# Min value is 100 +XTRAT_WWAN_LITE_MAX_DL_SNA = 10000 + +# Maximum total number of BSA records cached in mobile storage. +# Max allowed value is 65000 +# Min value is 100 +XTRAT_WWAN_LITE_MAX_DL_BSA = 65000 + +############################################################################## +# Qualcomm Network Location Provider config # +############################################################################## +# Accuracy Threshold for NLP position. Position exceeds thsi threshold will be filtered out. +# Default is 25000 meters. +LARGE_ACCURACY_THRESHOLD_TO_FILTER_NLP_POSITION = 25000 \ No newline at end of file diff --git a/gps/loc-api.pc.in b/gps/loc-api.pc.in new file mode 100644 index 000000000..3b4f81bfb --- /dev/null +++ b/gps/loc-api.pc.in @@ -0,0 +1,10 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: loc-api +Description: Qualcomm GPS Location API +Version: @VERSION@ +Libs: -L${libdir} -lgps_utils_so -lloc_adapter_so -lloc_eng_so -lgps_default_so -lloc_api +Cflags: -I${includedir}/loc-api/libloc_api_50001 -I${includedir}/loc-api/utils -I${includedir}/ -I${includedir}/loc-api diff --git a/gps/loc_api/Android.mk b/gps/loc_api/Android.mk new file mode 100644 index 000000000..8bfdd1b98 --- /dev/null +++ b/gps/loc_api/Android.mk @@ -0,0 +1,13 @@ +LOCAL_PATH := $(call my-dir) + +# add RPC dirs if RPC is available +ifneq ($(TARGET_NO_RPC),true) + +GPS_DIR_LIST += $(LOCAL_PATH)/libloc_api-rpc-50001/ + +endif #TARGET_NO_RPC + +GPS_DIR_LIST += $(LOCAL_PATH)/libloc_api_50001/ + +#call the subfolders +include $(addsuffix Android.mk, $(GPS_DIR_LIST)) diff --git a/gps/loc_api/libloc_api-rpc-50001/Android.mk b/gps/loc_api/libloc_api-rpc-50001/Android.mk new file mode 100644 index 000000000..6c5d53399 --- /dev/null +++ b/gps/loc_api/libloc_api-rpc-50001/Android.mk @@ -0,0 +1,3 @@ +ifeq ($(BOARD_VENDOR_QCOM_GPS_LOC_API_AMSS_VERSION),50001) +include $(call all-subdir-makefiles) +endif diff --git a/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-glue/Android.mk b/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-glue/Android.mk new file mode 100644 index 000000000..bb3d924bc --- /dev/null +++ b/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-glue/Android.mk @@ -0,0 +1,60 @@ +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +RPC_INC:=rpc_inc + +source_files:= \ + src/loc_api_rpc_glue.c \ + src/loc_api_sync_call.c \ + src/loc_apicb_appinit.c \ + src/loc_api_fixup.c \ + src/loc_api_log.c \ + src/LocApiRpc.cpp + +LOCAL_SRC_FILES:= $(source_files) + +LOCAL_CFLAGS:=-fno-short-enums +LOCAL_CFLAGS+=-DDEBUG -DUSE_QCOM_AUTO_RPC -DUSE_QCOM_AUTO_RPC +LOCAL_CFLAGS+=$(GPS_FEATURES) + +# for loc_api_fixup.c +LOCAL_CFLAGS+=-DADD_XDR_FLOAT -DADD_XDR_BOOL + +LOCAL_SHARED_LIBRARIES:= \ + librpc \ + libutils \ + libcutils \ + libcommondefs \ + libgps.utils \ + libloc_core + +LOCAL_STATIC_LIBRARIES := \ + libloc_api_rpcgen + +LOCAL_PRELINK_MODULE:= false + +LOCAL_C_INCLUDES:= \ + $(LOCAL_PATH) \ + $(LOCAL_PATH)/rpc_inc \ + $(TARGET_OUT_HEADERS)/gps.utils \ + $(TARGET_OUT_HEADERS)/libloc_core \ + $(TARGET_OUT_HEADERS)/loc_api/rpcgen/inc \ + $(TARGET_OUT_HEADERS)/libcommondefs/rpcgen/inc \ + $(TARGET_OUT_HEADERS)/librpc \ + $(TARGET_OUT_HEADERS)/libloc-rpc/rpc_inc \ + $(TOP)/hardware/msm7k/librpc + +LOCAL_COPY_HEADERS_TO:= libloc_api-rpc-qc/$(RPC_INC) +LOCAL_COPY_HEADERS:= \ + $(RPC_INC)/loc_api_rpc_glue.h \ + $(RPC_INC)/loc_api_fixup.h \ + $(RPC_INC)/loc_api_sync_call.h \ + $(RPC_INC)/loc_apicb_appinit.h \ + $(RPC_INC)/LocApiRpc.h + +LOCAL_MODULE:= libloc_api-rpc-qc +LOCAL_MODULE_OWNER := qcom + +LOCAL_MODULE_TAGS := optional + +include $(BUILD_SHARED_LIBRARY) diff --git a/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-glue/Makefile.am b/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-glue/Makefile.am new file mode 100644 index 000000000..f5c513690 --- /dev/null +++ b/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-glue/Makefile.am @@ -0,0 +1,46 @@ +AM_CFLAGS = \ + -I../../../utils \ + -I../../../platform_lib_abstractions \ + -I./rpc_inc \ + -I../libloc_api-rpc-stub/inc \ + -I../../libloc_api_50001 \ + $(MSM7K_CFLAGS) \ + -DUSE_QCOM_AUTO_RPC + +requiredlibs = \ + ../../../utils/libgps_utils_so.la \ + $(MSM7K_LIBS) + +h_sources = \ + rpc_inc/loc_api_rpc_glue.h \ + rpc_inc/loc_api_fixup.h \ + rpc_inc/loc_api_sync_call.h \ + rpc_inc/loc_apicb_appinit.h \ + +c_sources = \ + src/loc_api_rpc_glue.c \ + src/loc_api_sync_call.c \ + src/loc_apicb_appinit.c \ + src/loc_api_fixup.c \ + src/loc_api_log.c \ + src/LocApiRpcAdapter.cpp \ + + +library_includedir = $(pkgincludedir)/libloc_api-rpc-50001/libloc_api-rpc-glue/rpc_inc +library_include_HEADERS = $(h_sources) +libloc_api_rpc_qc_la_SOURCES = $(c_sources) $(h_sources) + +if USE_GLIB +libloc_api_rpc_qc_la_CFLAGS = -DUSE_GLIB $(AM_CFLAGS) @GLIB_CFLAGS@ +libloc_api_rpc_qc_la_LDFLAGS = -lstdc++ -lpthread @GLIB_LIBS@ -shared -version-info 1:0:0 +libloc_api_rpc_qc_la_CPPFLAGS = -DUSE_GLIB $(AM_CFLAGS) $(AM_CPPFLAGS) @GLIB_CFLAGS@ +else +libloc_api_rpc_qc_la_CFLAGS = $(AM_CFLAGS) +libloc_api_rpc_qc_la_LDFLAGS = -lpthread -shared -version-info 1:0:0 +libloc_api_rpc_qc_la_CPPFLAGS = $(AM_CFLAGS) $(AM_CPPFLAGS) +endif + +libloc_api_rpc_qc_la_LIBADD = $(requiredlibs) -lstdc++ + +#Create and Install Libraries +lib_LTLIBRARIES = libloc_api_rpc_qc.la diff --git a/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-glue/rpc_inc/LocApiRpc.h b/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-glue/rpc_inc/LocApiRpc.h new file mode 100644 index 000000000..01d67f4cc --- /dev/null +++ b/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-glue/rpc_inc/LocApiRpc.h @@ -0,0 +1,140 @@ +/* Copyright (c) 2011,2014, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef LOC_API_RPC_H +#define LOC_API_RPC_H + +#include +#include +#include +#include +#include + +using namespace loc_core; + +class LocApiRpc : public LocApiBase { +protected: + // RPC communication establishment + rpc_loc_client_handle_type client_handle; + +private: + int dataEnableLastSet; + char apnLastSet[MAX_APN_LEN]; + + static const LOC_API_ADAPTER_EVENT_MASK_T maskAll; + static const rpc_loc_event_mask_type locBits[]; + static rpc_loc_event_mask_type convertMask(LOC_API_ADAPTER_EVENT_MASK_T mask); + static rpc_loc_lock_e_type convertGpsLockMask(LOC_GPS_LOCK_MASK lockMask); + static enum loc_api_adapter_err convertErr(int rpcErr); + static GpsNiEncodingType convertNiEncodingType(int loc_encoding); + static int NIEventFillVerfiyType(GpsNiNotification ¬if, + rpc_loc_ni_notify_verify_e_type notif_priv); + + void reportPosition(const rpc_loc_parsed_position_s_type *location_report_ptr); + void reportSv(const rpc_loc_gnss_info_s_type *gnss_report_ptr); + void reportStatus(const rpc_loc_status_event_s_type *status_report_ptr); + void reportNmea(const rpc_loc_nmea_report_s_type *nmea_report_ptr); + void ATLEvent(const rpc_loc_server_request_s_type *server_request_ptr); + void NIEvent(const rpc_loc_ni_event_s_type *ni_req_ptr); + +protected: + virtual enum loc_api_adapter_err + open(LOC_API_ADAPTER_EVENT_MASK_T mask); + virtual enum loc_api_adapter_err + close(); + +public: + LocApiRpc(const MsgTask* msgTask, + LOC_API_ADAPTER_EVENT_MASK_T exMask); + ~LocApiRpc(); + + virtual int locEventCB(rpc_loc_client_handle_type client_handle, + rpc_loc_event_mask_type loc_event, + const rpc_loc_event_payload_u_type* loc_event_payload); + + void locRpcGlobalCB(CLIENT* clnt, enum rpc_reset_event event); + + // RPC adapter interface implementations + virtual enum loc_api_adapter_err + startFix(const LocPosMode& posMode); + virtual enum loc_api_adapter_err + stopFix(); + virtual enum loc_api_adapter_err + setPositionMode(const LocPosMode& mode); + inline virtual enum loc_api_adapter_err + enableData(int enable) { return enableData(enable, false); } + virtual enum loc_api_adapter_err + enableData(int enable, boolean force); + virtual enum loc_api_adapter_err + setTime(GpsUtcTime time, int64_t timeReference, int uncertainty); + virtual enum loc_api_adapter_err + injectPosition(double latitude, double longitude, float accuracy); + virtual enum loc_api_adapter_err + deleteAidingData(GpsAidingData f); + virtual enum loc_api_adapter_err + informNiResponse(GpsUserResponseType userResponse, const void* passThroughData); + inline virtual enum loc_api_adapter_err + setAPN(char* apn, int len) { return setAPN(apn, len, false); } + virtual enum loc_api_adapter_err + setAPN(char* apn, int len, boolean force); + virtual enum loc_api_adapter_err + setServer(const char* url, int len); + virtual enum loc_api_adapter_err + setServer(unsigned int ip, int port, LocServerType type); + virtual enum loc_api_adapter_err + setXtraData(char* data, int length); + virtual enum loc_api_adapter_err + requestXtraServer(); + virtual enum loc_api_adapter_err + atlOpenStatus(int handle, int is_succ, char* apn, AGpsBearerType bear, AGpsType agpsType); + virtual enum loc_api_adapter_err + atlCloseStatus(int handle, int is_succ); + virtual enum loc_api_adapter_err + setSUPLVersion(uint32_t version); + virtual void setInSession(bool inSession); + + /*Values for lock + 1 = Do not lock any position sessions + 2 = Lock MI position sessions + 3 = Lock MT position sessions + 4 = Lock all position sessions + */ + virtual int setGpsLock(LOC_GPS_LOCK_MASK lock); + /* + Returns + Current value of GPS Lock on success + -1 on failure + */ + virtual int getGpsLock(void); +}; + +extern "C" LocApiBase* getLocApi(const MsgTask* msgTask, + LOC_API_ADAPTER_EVENT_MASK_T exMask, + ContextBase *context); + +#endif //LOC_API_RPC_H diff --git a/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-glue/rpc_inc/debug.h b/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-glue/rpc_inc/debug.h new file mode 100644 index 000000000..49a6d0bed --- /dev/null +++ b/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-glue/rpc_inc/debug.h @@ -0,0 +1,69 @@ +/* Copyright (c) 2011, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef DEBUG_H +#define DEBUG_H + +#include + +#define LOG_TAG "LocSvc_rpc" +#include + +#define PRINT(x...) do { \ + fprintf(stdout, "%s(%d) ", __FUNCTION__, __LINE__); \ + fprintf(stdout, ##x); \ + ALOGD(x); \ + } while(0) + +#ifdef DEBUG +#define D PRINT +#else +#define D(x...) do { } while(0) +#endif + +#ifdef VERBOSE +#define V PRINT +#else +#define V(x...) do { } while(0) +#endif + +#define E(x...) do { \ + fprintf(stderr, "%s(%d) ", __FUNCTION__, __LINE__); \ + fprintf(stderr, ##x); \ + ALOGE(x); \ + } while(0) + +#define FAILIF(cond, msg...) do { \ + if (__builtin_expect (cond, 0)) { \ + fprintf(stderr, "%s:%s:(%d): ", __FILE__, __FUNCTION__, __LINE__); \ + fprintf(stderr, ##msg); \ + ALOGE(##msg); \ + } \ + } while(0) + +#endif/*DEBUG_H*/ diff --git a/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-glue/rpc_inc/loc_api_fixup.h b/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-glue/rpc_inc/loc_api_fixup.h new file mode 100644 index 000000000..c483b4a16 --- /dev/null +++ b/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-glue/rpc_inc/loc_api_fixup.h @@ -0,0 +1,226 @@ +/* Copyright (c) 2011, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef LOC_API_FIXUP_H +#define LOC_API_FIXUP_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +#ifndef NULLPROC +#define NULLPROC 0 +#endif /* NULLPROC */ + +#ifdef ADD_XDR_FLOAT + +extern bool_t xdr_float (XDR *__xdrs, float *__fp); +extern bool_t xdr_double (XDR *__xdrs, double *__dp); + +#endif /* ADD_XDR_FLOAT */ + +#ifdef ADD_XDR_BOOL +extern bool_t xdr_bool(XDR *__xdrs, int *__bp); +#endif /* ADD_XDR_BOOL */ + +#define RPC_LOC_API_MAJOR_VERSION_NUMBER 1 +#define RPC_LOC_API_MINOR_VERSION_NUMBER 0 + +// Return value for loc_open in case of failure. +#define RPC_LOC_CLIENT_HANDLE_INVALID -1 + +// Return value of loc api calls for loc_close, loc_start_fix, loc_stop_fix and loc_ioctl +// These are also the status for the ioctl callback +#define RPC_LOC_API_SUCCESS 0 +#define RPC_LOC_API_GENERAL_FAILURE 1 +#define RPC_LOC_API_UNSUPPORTED 2 +#define RPC_LOC_API_INVALID_HANDLE 4 +#define RPC_LOC_API_INVALID_PARAMETER 5 +#define RPC_LOC_API_ENGINE_BUSY 6 +#define RPC_LOC_API_PHONE_OFFLINE 7 +#define RPC_LOC_API_TIMEOUT 8 + +// Special return value for loc api calls in case of RPC failure +#define RPC_LOC_API_RPC_FAILURE (-1234) +// Special return value for modem restart incurred RPC failure +#define RPC_LOC_API_RPC_MODEM_RESTART (-1235) + +#define RPC_LOC_API_MAX_SV_COUNT 80 +#define RPC_LOC_API_MAX_NMEA_STRING_LENGTH 1200 + +// Maximum server address that will be used in location API +#define RPC_LOC_API_MAX_SERVER_ADDR_LENGTH 256 +#define RPC_LOC_API_MAX_NUM_PREDICTED_ORBITS_SERVERS 3 +#define RPC_LOC_API_MAX_NUM_NTP_SERVERS 3 + +#define RPC_LOC_EVENT_PARSED_POSITION_REPORT 0x00000001 // Position report comes in loc_parsed_position_s_type +#define RPC_LOC_EVENT_SATELLITE_REPORT 0x00000002 // Satellite in view report +#define RPC_LOC_EVENT_NMEA_1HZ_REPORT 0x00000004 // NMEA report at 1HZ rate +#define RPC_LOC_EVENT_NMEA_POSITION_REPORT 0x00000008 // NMEA report at position report rate +#define RPC_LOC_EVENT_NI_NOTIFY_VERIFY_REQUEST 0x00000010 // NI notification/verification request +#define RPC_LOC_EVENT_ASSISTANCE_DATA_REQUEST 0x00000020 // Assistance data, eg: time, predicted orbits request +#define RPC_LOC_EVENT_LOCATION_SERVER_REQUEST 0x00000040 // Request for location server +#define RPC_LOC_EVENT_IOCTL_REPORT 0x00000080 // Callback report for loc_ioctl +#define RPC_LOC_EVENT_STATUS_REPORT 0x00000100 // Misc status report: eg, engine state + +#define RPC_LOC_POS_VALID_SESSION_STATUS 0x00000001 +#define RPC_LOC_POS_VALID_TIMESTAMP_CALENDAR 0x00000002 +#define RPC_LOC_POS_VALID_TIMESTAMP_UTC 0x00000004 +#define RPC_LOC_POS_VALID_LEAP_SECONDS 0x00000008 +#define RPC_LOC_POS_VALID_TIME_UNC 0x00000010 +#define RPC_LOC_POS_VALID_LATITUDE 0x00000020 +#define RPC_LOC_POS_VALID_LONGITUDE 0x00000040 +#define RPC_LOC_POS_VALID_ALTITUDE_WRT_ELLIPSOID 0x00000080 +#define RPC_LOC_POS_VALID_ALTITUDE_WRT_MEAN_SEA_LEVEL 0x00000100 +#define RPC_LOC_POS_VALID_SPEED_HORIZONTAL 0x00000200 +#define RPC_LOC_POS_VALID_SPEED_VERTICAL 0x00000400 +#define RPC_LOC_POS_VALID_HEADING 0x00000800 +#define RPC_LOC_POS_VALID_HOR_UNC_CIRCULAR 0x00001000 +#define RPC_LOC_POS_VALID_HOR_UNC_ELLI_SEMI_MAJ 0x00002000 +#define RPC_LOC_POS_VALID_HOR_UNC_ELLI_SEMI_MIN 0x00004000 +#define RPC_LOC_POS_VALID_HOR_UNC_ELLI_ORIENT_AZIMUTH 0x00008000 +#define RPC_LOC_POS_VALID_VERTICAL_UNC 0x00010000 +#define RPC_LOC_POS_VALID_SPEED_UNC 0x00020000 +#define RPC_LOC_POS_VALID_HEADING_UNC 0x00040000 +#define RPC_LOC_POS_VALID_CONFIDENCE_HORIZONTAL 0x00080000 +#define RPC_LOC_POS_VALID_CONFIDENCE_VERTICAL 0x00100000 +#define RPC_LOC_POS_VALID_MAGNETIC_VARIATION 0x00200000 +#define RPC_LOC_POS_VALID_TECHNOLOGY_MASK 0x00400000 + +#define RPC_LOC_POS_TECH_SATELLITE 0x00000001 +#define RPC_LOC_POS_TECH_CELLID 0x00000002 +#define RPC_LOC_POS_TECH_WIFI 0x00000004 + +#define RPC_LOC_SV_INFO_VALID_SYSTEM 0x00000001 +#define RPC_LOC_SV_INFO_VALID_PRN 0x00000002 +#define RPC_LOC_SV_INFO_VALID_HEALTH_STATUS 0x00000004 +#define RPC_LOC_SV_INFO_VALID_PROCESS_STATUS 0x00000008 +#define RPC_LOC_SV_INFO_VALID_HAS_EPH 0x00000010 +#define RPC_LOC_SV_INFO_VALID_HAS_ALM 0x00000020 +#define RPC_LOC_SV_INFO_VALID_ELEVATION 0x00000040 +#define RPC_LOC_SV_INFO_VALID_AZIMUTH 0x00000080 +#define RPC_LOC_SV_INFO_VALID_SNR 0x00000100 + +#define RPC_LOC_GNSS_INFO_VALID_POS_DOP 0x00000001 +#define RPC_LOC_GNSS_INFO_VALID_HOR_DOP 0x00000002 +#define RPC_LOC_GNSS_INFO_VALID_VERT_DOP 0x00000004 +#define RPC_LOC_GNSS_INFO_VALID_ALTITUDE_ASSUMED 0x00000008 +#define RPC_LOC_GNSS_INFO_VALID_SV_COUNT 0x00000010 +#define RPC_LOC_GNSS_INFO_VALID_SV_LIST 0x00000020 + +#define RPC_LOC_NI_MAX_REQUESTOR_ID_LENGTH 200 +#define RPC_LOC_NI_SUPL_HASH_LENGTH 8 +#define RPC_LOC_NI_SUPL_SLP_SESSION_ID_BYTE_LENGTH 4 +#define RPC_LOC_NI_MAX_CLIENT_NAME_LENGTH 64 +#define RPC_LOC_NI_MAX_EXT_CLIENT_ADDRESS 20 +#define RPC_LOC_NI_CODEWORD_LENGTH 20 + +#define RPC_LOC_NI_SUPL_QOP_VALID 0x01 +#define RPC_LOC_NI_SUPL_QOP_VERACC_VALID 0x02 +#define RPC_LOC_NI_SUPL_QOP_MAXAGE_VALID 0x04 +#define RPC_LOC_NI_SUPL_QOP_DELAY_VALID 0x08 + +#define RPC_LOC_FIX_CRIT_VALID_RECURRENCE_TYPE 0x00000001 +#define RPC_LOC_FIX_CRIT_VALID_PREFERRED_OPERATION_MODE 0x00000002 +#define RPC_LOC_FIX_CRIT_VALID_PREFERRED_ACCURACY 0x00000004 +#define RPC_LOC_FIX_CRIT_VALID_PREFERRED_RESPONSE_TIME 0x00000008 +#define RPC_LOC_FIX_CRIT_VALID_INTERMEDIATE_POS_REPORT_ENABLED 0x00000010 +#define RPC_LOC_FIX_CRIT_VALID_NOTIFY_TYPE 0x00000020 +#define RPC_LOC_FIX_CRIT_VALID_MIN_INTERVAL 0x00000040 +#define RPC_LOC_FIX_CRIT_VALID_MIN_DISTANCE 0x00000080 +#define RPC_LOC_FIX_CRIT_VALID_MIN_DIST_SAMPLE_INTERVAL 0x00000100 + +#define RPC_LOC_ASSIST_POS_VALID_TIMESTAMP_UTC 0x00000001 +#define RPC_LOC_ASSIST_POS_VALID_LATITUDE 0x00000002 +#define RPC_LOC_ASSIST_POS_VALID_LONGITUDE 0x00000004 +#define RPC_LOC_ASSIST_POS_VALID_ALTITUDE_WRT_ELLIPSOID 0x00000008 +#define RPC_LOC_ASSIST_POS_VALID_ALTITUDE_WRT_MEAN_SEA_LEVEL 0x00000010 +#define RPC_LOC_ASSIST_POS_VALID_HOR_UNC_CIRCULAR 0x00000020 +#define RPC_LOC_ASSIST_POS_VALID_VERT_UNC 0x00000040 +#define RPC_LOC_ASSIST_POS_VALID_CONFIDENCE_HORIZONTAL 0x00000080 +#define RPC_LOC_ASSIST_POS_VALID_CONFIDENCE_VERTICAL 0x00000100 +#define RPC_LOC_ASSIST_POS_VALID_TIMESTAMP_AGE 0x00000200 + +#define RPC_LOC_ASSIST_DATA_ALL 0xFFFFFFFF + +#define RPC_LOC_NMEA_MASK_ALL 0xffff +#define RPC_LOC_NMEA_MASK_GGA 0x0001 +#define RPC_LOC_NMEA_MASK_RMC 0x0002 +#define RPC_LOC_NMEA_MASK_GSV 0x0004 +#define RPC_LOC_NMEA_MASK_GSA 0x0008 +#define RPC_LOC_NMEA_MASK_VTG 0x0010 + +/* EFS data access */ +#define RPC_LOC_EFS_MAX_PATH_LEN_BYTES 64 /* Max file name length in bytes that can be written*/ +#define RPC_LOC_EFS_MAX_FILE_LEN_BYTES 2000 /* Max file size in bytes that can be written */ + +/* WIPER valid information flag in log report */ +#define RPC_LOC_WIPER_LOG_TIME_VALID 0x01 +#define RPC_LOC_WIPER_LOG_POS_VALID 0x02 +#define RPC_LOC_WIPER_LOG_AP_SET_VALID 0x04 + +/* General WIPER defines */ +#define RPC_LOC_WIPER_MAC_ADDR_LENGTH 6 // Do not change this number since it affects RPC and log packet sizes +#define RPC_LOC_WIPER_MAX_REPORTED_APS_PER_LOG_MSG 50 // Do not change this number since it affects RPC and log packet sizes + +/* WIPER AP Qualifier */ +#define RPC_LOC_WIPER_AP_QUALIFIER_BEING_USED 0x1 /* AP is being used by WPS */ +#define RPC_LOC_WIPER_AP_QUALIFIER_HIDDEN_SSID 0x2 /* AP does not broadcast SSID */ +#define RPC_LOC_WIPER_AP_QUALIFIER_PRIVATE 0x4 /* AP has encryption turned on */ +#define RPC_LOC_WIPER_AP_QUALIFIER_INFRASTRUCTURE_MODE 0x8 /* AP is in infrastructure mode and not in ad-hoc/unknown mode */ + +/* flags for notification */ +#define RPC_LOC_NI_CLIENT_NAME_PRESENT 0x0001 +#define RPC_LOC_NI_CLIENT_EXTADDR_PRESENT 0x0002 +#define RPC_LOC_NI_DEF_LOCATION_TYPE_PRESENT 0x0010 +#define RPC_LOC_NI_REQUESTOR_ID_PRESENT 0x0020 +#define RPC_LOC_NI_CODEWORD_PRESENT 0x0040 +#define RPC_LOC_NI_SERVICE_TYPE_ID_PRESENT 0x0080 +#define RPC_LOC_NI_ENCODING_TYPE_PRESENT 0x0100 + +/* below are for RPC_LOC_IOCTL_SET_LBS_APN_PROFILE data */ +/* values for apn_profiles[0].srv_system_type */ +#define LOC_APN_PROFILE_SRV_SYS_CDMA 0x01 +#define LOC_APN_PROFILE_SRV_SYS_HDR 0x02 +#define LOC_APN_PROFILE_SRV_SYS_GSM 0x04 +#define LOC_APN_PROFILE_SRV_SYS_WCDMA 0x08 +#define LOC_APN_PROFILE_SRV_SYS_LTE 0x10 +#define LOC_APN_PROFILE_SRV_SYS_MAX 0x1F +/* values for apn_profiles[0].pdp_type */ +#define LOC_APN_PROFILE_PDN_TYPE_IPV4 0x01 +#define LOC_APN_PROFILE_PDN_TYPE_IPV6 0x02 +#define LOC_APN_PROFILE_PDN_TYPE_IPV4V6 0x03 +#define LOC_APN_PROFILE_PDN_TYPE_PPP 0x04 +#define LOC_APN_PROFILE_PDN_TYPE_MAX 0x04 + +#ifdef __cplusplus +} +#endif + +#endif /* LOC_API_FIXUP_H */ diff --git a/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-glue/rpc_inc/loc_api_log.h b/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-glue/rpc_inc/loc_api_log.h new file mode 100644 index 000000000..f0374280e --- /dev/null +++ b/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-glue/rpc_inc/loc_api_log.h @@ -0,0 +1,59 @@ +/* Copyright (c) 2011 The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef LOC_API_LOG_H +#define LOC_API_LOG_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include +#include "loc_api_rpcgen_common_rpc.h" + +extern int loc_callback_log( + rpc_loc_event_mask_type loc_event, /* event mask */ + const rpc_loc_event_payload_u_type* loc_event_payload /* payload */ +); + +extern const char* loc_get_event_atl_open_name(rpc_loc_server_request_e_type loc_event_atl_open); +extern const char* loc_get_event_name(rpc_loc_event_mask_type loc_event_mask); +extern const char* loc_get_ioctl_type_name(rpc_loc_ioctl_e_type ioctl_type); +extern const char* loc_get_ioctl_status_name(uint32 status); +extern const char* loc_get_sess_status_name(rpc_loc_session_status_e_type status); +extern const char* loc_get_engine_state_name(rpc_loc_engine_state_e_type state); +extern const char* loc_get_fix_session_state_name(rpc_loc_fix_session_state_e_type state); +extern const char* loc_get_rpc_reset_event_name(enum rpc_reset_event event); + +#ifdef __cplusplus +} +#endif + +#endif /* LOC_API_LOG_H */ diff --git a/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-glue/rpc_inc/loc_api_rpc_glue.h b/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-glue/rpc_inc/loc_api_rpc_glue.h new file mode 100644 index 000000000..6df33ae1a --- /dev/null +++ b/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-glue/rpc_inc/loc_api_rpc_glue.h @@ -0,0 +1,123 @@ +/* Copyright (c) 2011, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef LOC_API_RPC_GLUE_H +#define LOC_API_RPC_GLUE_H + +/* Include RPC headers */ +#ifdef USE_LOCAL_RPC +#include "rpc_inc/loc_api_common.h" +#include "rpc_inc/loc_api.h" +#include "rpc_inc/loc_api_cb.h" +#endif + +#ifdef USE_QCOM_AUTO_RPC +#include "loc_api_rpcgen_rpc.h" +#include "loc_api_rpcgen_common_rpc.h" +#include "loc_api_rpcgen_cb_rpc.h" +#endif + +/* Boolean */ +/* Other data types in comdef.h are defined in rpc stubs, so fix it here */ +typedef unsigned char boolean; +#define TRUE 1 +#define FALSE 0 + +#include "loc_api_fixup.h" +#include "loc_api_sync_call.h" +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +extern int loc_api_glue_init(void); +extern int loc_api_null(void); + +typedef int32 (loc_event_cb_f_type)( + void* userData, + rpc_loc_client_handle_type loc_handle, /* handle of the client */ + rpc_loc_event_mask_type loc_event, /* event mask */ + const rpc_loc_event_payload_u_type* loc_event_payload /* payload */ +); + +typedef void (loc_reset_notif_cb_f_type)( + void* userData, + CLIENT* clnt, + enum rpc_reset_event event +); + +extern rpc_loc_client_handle_type loc_open( + rpc_loc_event_mask_type event_reg_mask, + loc_event_cb_f_type *event_callback, + loc_reset_notif_cb_f_type *rpc_global_cb, + void* userData +); + +extern int32 loc_close +( + rpc_loc_client_handle_type handle +); + +extern void loc_clear +( + rpc_loc_client_handle_type handle +); + +extern int32 loc_start_fix +( + rpc_loc_client_handle_type handle +); + +extern int32 loc_stop_fix +( + rpc_loc_client_handle_type handle +); + +extern int32 loc_ioctl +( + rpc_loc_client_handle_type handle, + rpc_loc_ioctl_e_type ioctl_type, + rpc_loc_ioctl_data_u_type* ioctl_data +); + +extern int loc_eng_ioctl +( + rpc_loc_client_handle_type handle, + rpc_loc_ioctl_e_type ioctl_type, + rpc_loc_ioctl_data_u_type* ioctl_data_ptr, + uint32 timeout_msec, + rpc_loc_ioctl_callback_s_type *cb_data_ptr +); + +#ifdef __cplusplus +} +#endif + +#endif /* LOC_API_RPC_GLUE_H */ diff --git a/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-glue/rpc_inc/loc_api_sync_call.h b/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-glue/rpc_inc/loc_api_sync_call.h new file mode 100644 index 000000000..43208bda0 --- /dev/null +++ b/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-glue/rpc_inc/loc_api_sync_call.h @@ -0,0 +1,90 @@ +/* Copyright (c) 2011, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef LOC_API_CB_SYNC_H +#define LOC_API_CB_SYNC_H + +#ifdef __cplusplus +extern "C" +{ +#endif +#include "loc_api_rpc_glue.h" +#define LOC_SYNC_CALL_SLOTS_MAX 8 + +typedef struct { + pthread_mutex_t lock; + + /* Client ID */ + rpc_loc_client_handle_type loc_handle; + + /* Callback waiting conditional variable */ + pthread_cond_t loc_cb_arrived_cond; + + /* Callback waiting data block, protected by loc_cb_data_mutex */ + boolean in_use; + boolean signal_sent; + boolean not_available; + rpc_loc_event_mask_type loc_cb_wait_event_mask; /* event to wait for */ + rpc_loc_ioctl_e_type ioctl_type; /* ioctl to wait for */ + rpc_loc_event_payload_u_type loc_cb_received_payload; /* received payload */ + rpc_loc_event_mask_type loc_cb_received_event_mask; /* received event */ +} loc_sync_call_slot_s_type; + +typedef struct { + int num_of_slots; + loc_sync_call_slot_s_type slots[LOC_SYNC_CALL_SLOTS_MAX]; +} loc_sync_call_slot_array_s_type; + +/* Init function */ +void loc_api_sync_call_init(); + +/* Destroy function */ +void loc_api_sync_call_destroy(); + +/* Process Loc API callbacks to wake up blocked user threads */ +void loc_api_callback_process_sync_call( + rpc_loc_client_handle_type loc_handle, /* handle of the client */ + rpc_loc_event_mask_type loc_event, /* event mask */ + const rpc_loc_event_payload_u_type* loc_event_payload /* payload */ +); + +/* Reentrant synchronous IOCTL call, using Loc API return code */ +int loc_api_sync_ioctl +( + rpc_loc_client_handle_type handle, + rpc_loc_ioctl_e_type ioctl_type, + rpc_loc_ioctl_data_u_type* ioctl_data_ptr, + uint32 timeout_msec, + rpc_loc_ioctl_callback_s_type *cb_data_ptr +); + +#ifdef __cplusplus +} +#endif + +#endif /* LOC_API_CB_SYNC_H */ diff --git a/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-glue/rpc_inc/loc_apicb_appinit.h b/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-glue/rpc_inc/loc_apicb_appinit.h new file mode 100644 index 000000000..ba41d08b2 --- /dev/null +++ b/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-glue/rpc_inc/loc_apicb_appinit.h @@ -0,0 +1,45 @@ +/* Copyright (c) 2011, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef LOC_APICB_APPINIT_H +#define LOC_APICB_APPINIT_H + +#ifdef __cplusplus +extern "C" +{ +#endif + + /* Initialization function for callbacks */ +extern int loc_apicb_app_init(); +extern void loc_apicb_app_deinit(); + +#ifdef __cplusplus +} +#endif + +#endif /* LOC_APICB_APPINIT_H */ diff --git a/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-glue/src/LocApiRpc.cpp b/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-glue/src/LocApiRpc.cpp new file mode 100644 index 000000000..c74475431 --- /dev/null +++ b/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-glue/src/LocApiRpc.cpp @@ -0,0 +1,1465 @@ +/* Copyright (c) 2011-2014, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#define LOG_NDDEBUG 0 +#define LOG_TAG "LocSvc_api_rpc" + +#include +#include +#ifndef USE_GLIB +#include +#endif /* USE_GLIB */ +#include +#include +#include +#include +#include +#include +#include +#ifdef USE_GLIB +#include +#endif +#include +#include + +using namespace loc_core; + +#define LOC_XTRA_INJECT_DEFAULT_TIMEOUT (3100) +#define XTRA_BLOCK_SIZE (3072) +#define LOC_IOCTL_DEFAULT_TIMEOUT 1000 // 1000 milli-seconds +#define LOC_NI_NOTIF_KEY_ADDRESS "Address" + +/*=========================================================================== +FUNCTION loc_event_cb + +DESCRIPTION + This is the callback function registered by loc_open. + +DEPENDENCIES + N/A + +RETURN VALUE + RPC_LOC_API_SUCCESS + +SIDE EFFECTS + N/A + +===========================================================================*/ +static int32 loc_event_cb +( + void* user, + rpc_loc_client_handle_type client_handle, + rpc_loc_event_mask_type loc_event, + const rpc_loc_event_payload_u_type* loc_event_payload +) +{ + MODEM_LOG_CALLFLOW(%s, loc_get_event_name(loc_event)); + loc_callback_log(loc_event, loc_event_payload); + int32 ret_val = ((LocApiRpc*)user)->locEventCB(client_handle, loc_event, loc_event_payload); + EXIT_LOG(%d, ret_val); + return ret_val; +} + +/*=========================================================================== +FUNCTION loc_eng_rpc_global_cb + +DESCRIPTION + This is the callback function registered by loc_open for RPC global events + +DEPENDENCIES + N/A + +RETURN VALUE + RPC_LOC_API_SUCCESS + +SIDE EFFECTS + N/A + +===========================================================================*/ +static void loc_rpc_global_cb(void* user, CLIENT* clnt, enum rpc_reset_event event) +{ + MODEM_LOG_CALLFLOW(%s, loc_get_rpc_reset_event_name(event)); + ((LocApiRpc*)user)->locRpcGlobalCB(clnt, event); + EXIT_LOG(%p, VOID_RET); +} + +const LOC_API_ADAPTER_EVENT_MASK_T LocApiRpc::maskAll = + LOC_API_ADAPTER_BIT_PARSED_POSITION_REPORT | + LOC_API_ADAPTER_BIT_SATELLITE_REPORT | + LOC_API_ADAPTER_BIT_LOCATION_SERVER_REQUEST | + LOC_API_ADAPTER_BIT_ASSISTANCE_DATA_REQUEST | + LOC_API_ADAPTER_BIT_IOCTL_REPORT | + LOC_API_ADAPTER_BIT_STATUS_REPORT | + LOC_API_ADAPTER_BIT_NMEA_1HZ_REPORT | + LOC_API_ADAPTER_BIT_NI_NOTIFY_VERIFY_REQUEST; + +const rpc_loc_event_mask_type LocApiRpc::locBits[] = +{ + RPC_LOC_EVENT_PARSED_POSITION_REPORT, + RPC_LOC_EVENT_SATELLITE_REPORT, + RPC_LOC_EVENT_NMEA_1HZ_REPORT, + RPC_LOC_EVENT_NMEA_POSITION_REPORT, + RPC_LOC_EVENT_NI_NOTIFY_VERIFY_REQUEST, + RPC_LOC_EVENT_ASSISTANCE_DATA_REQUEST, + RPC_LOC_EVENT_LOCATION_SERVER_REQUEST, + RPC_LOC_EVENT_IOCTL_REPORT, + RPC_LOC_EVENT_STATUS_REPORT, + RPC_LOC_EVENT_WPS_NEEDED_REQUEST +}; + +// constructor +LocApiRpc::LocApiRpc(const MsgTask* msgTask, + LOC_API_ADAPTER_EVENT_MASK_T exMask, + ContextBase* context) : + LocApiBase(msgTask, exMask, context), + client_handle(RPC_LOC_CLIENT_HANDLE_INVALID), + dataEnableLastSet(-1) +{ + memset(apnLastSet, 0, sizeof(apnLastSet)); + loc_api_glue_init(); +} + +LocApiRpc::~LocApiRpc() +{ + close(); +} + +rpc_loc_event_mask_type +LocApiRpc::convertMask(LOC_API_ADAPTER_EVENT_MASK_T mask) +{ + rpc_loc_event_mask_type newMask = 0; + + for (unsigned int i = 0, bit=1; 0 != mask; i++, bit<<=1) { + if (mask & bit) { + newMask |= locBits[i]; + mask ^= bit; + } + } + + return newMask; +} + +rpc_loc_lock_e_type +LocApiRpc::convertGpsLockMask(LOC_GPS_LOCK_MASK lockMask) +{ + if (isGpsLockAll(lockMask)) + return RPC_LOC_LOCK_ALL; + if (isGpsLockMO(lockMask)) + return RPC_LOC_LOCK_MI; + if (isGpsLockMT(lockMask)) + return RPC_LOC_LOCK_MT; + if (isGpsLockNone(lockMask)) + return RPC_LOC_LOCK_NONE; + return (rpc_loc_lock_e_type)lockMask; +} + +enum loc_api_adapter_err +LocApiRpc::convertErr(int rpcErr) +{ + switch(rpcErr) + { + case RPC_LOC_API_SUCCESS: + return LOC_API_ADAPTER_ERR_SUCCESS; + case RPC_LOC_API_GENERAL_FAILURE: + return LOC_API_ADAPTER_ERR_GENERAL_FAILURE; + case RPC_LOC_API_UNSUPPORTED: + return LOC_API_ADAPTER_ERR_UNSUPPORTED; + case RPC_LOC_API_INVALID_HANDLE: + return LOC_API_ADAPTER_ERR_INVALID_HANDLE; + case RPC_LOC_API_INVALID_PARAMETER: + return LOC_API_ADAPTER_ERR_INVALID_PARAMETER; + case RPC_LOC_API_ENGINE_BUSY: + return LOC_API_ADAPTER_ERR_ENGINE_BUSY; + case RPC_LOC_API_PHONE_OFFLINE: + return LOC_API_ADAPTER_ERR_PHONE_OFFLINE; + case RPC_LOC_API_TIMEOUT: + return LOC_API_ADAPTER_ERR_TIMEOUT; + case RPC_LOC_API_RPC_MODEM_RESTART: + return LOC_API_ADAPTER_ERR_ENGINE_DOWN; + case RPC_LOC_API_RPC_FAILURE: + return LOC_API_ADAPTER_ERR_FAILURE; + default: + return LOC_API_ADAPTER_ERR_UNKNOWN; + } +} + +void LocApiRpc::locRpcGlobalCB(CLIENT* clnt, enum rpc_reset_event event) +{ + static rpc_loc_engine_state_e_type last_state = RPC_LOC_ENGINE_STATE_MAX; + + switch (event) { + case RPC_SUBSYSTEM_RESTART_BEGIN: + if (RPC_LOC_ENGINE_STATE_OFF != last_state) { + last_state = RPC_LOC_ENGINE_STATE_OFF; + handleEngineDownEvent(); + } + break; + case RPC_SUBSYSTEM_RESTART_END: + if (RPC_LOC_ENGINE_STATE_ON != last_state) { + last_state = RPC_LOC_ENGINE_STATE_ON; + handleEngineUpEvent(); + } + break; + } +} + +int32 LocApiRpc::locEventCB(rpc_loc_client_handle_type client_handle, + rpc_loc_event_mask_type loc_event, + const rpc_loc_event_payload_u_type* loc_event_payload) +{ + // Parsed report + if (loc_event & RPC_LOC_EVENT_PARSED_POSITION_REPORT) + { + reportPosition(&loc_event_payload->rpc_loc_event_payload_u_type_u. + parsed_location_report); + } + + // Satellite report + if (loc_event & RPC_LOC_EVENT_SATELLITE_REPORT) + { + reportSv(&loc_event_payload->rpc_loc_event_payload_u_type_u.gnss_report); + } + + // Status report + if (loc_event & RPC_LOC_EVENT_STATUS_REPORT) + { + reportStatus(&loc_event_payload->rpc_loc_event_payload_u_type_u.status_report); + } + + // NMEA + if (loc_event & RPC_LOC_EVENT_NMEA_1HZ_REPORT) + { + reportNmea(&(loc_event_payload->rpc_loc_event_payload_u_type_u.nmea_report)); + } + // XTRA support: supports only XTRA download + if (loc_event & RPC_LOC_EVENT_ASSISTANCE_DATA_REQUEST) + { + if (loc_event_payload->rpc_loc_event_payload_u_type_u.assist_data_request.event == + RPC_LOC_ASSIST_DATA_PREDICTED_ORBITS_REQ) + { + requestXtraData(); + } else if (loc_event_payload->rpc_loc_event_payload_u_type_u.assist_data_request.event == + RPC_LOC_ASSIST_DATA_TIME_REQ) + { + requestTime(); + } else if (loc_event_payload->rpc_loc_event_payload_u_type_u.assist_data_request.event == + RPC_LOC_ASSIST_DATA_POSITION_INJECTION_REQ) + { + requestLocation(); + } + } + + // AGPS data request + if (loc_event & RPC_LOC_EVENT_LOCATION_SERVER_REQUEST) + { + ATLEvent(&loc_event_payload->rpc_loc_event_payload_u_type_u. + loc_server_request); + } + + // NI notify request + if (loc_event & RPC_LOC_EVENT_NI_NOTIFY_VERIFY_REQUEST) + { + NIEvent(&loc_event_payload->rpc_loc_event_payload_u_type_u.ni_request); + } + + return RPC_LOC_API_SUCCESS;//We simply want to return sucess here as we do not want to + // cause any issues in RPC thread context +} + +enum loc_api_adapter_err +LocApiRpc::open(LOC_API_ADAPTER_EVENT_MASK_T mask) +{ + enum loc_api_adapter_err ret_val = LOC_API_ADAPTER_ERR_SUCCESS; + + // RPC does not dynamically update the event mask. And in the + // case of RPC, all we support are positioning (gps + agps) + // masks anyways, so we simply mask all of them on always. + // After doing so the first time in a power cycle, we know there + // will the following if condition will never be true any more. + mask = maskAll; + + if (mask != mMask) { + if (RPC_LOC_CLIENT_HANDLE_INVALID != client_handle) { + close(); + } + + mMask = mask; + // it is important to cap the mask here, because not all LocApi's + // can enable the same bits, e.g. foreground and bckground. + client_handle = loc_open(convertMask(mask), + loc_event_cb, + loc_rpc_global_cb, this); + + if (client_handle < 0) { + mMask = 0; + client_handle = RPC_LOC_CLIENT_HANDLE_INVALID; + ret_val = LOC_API_ADAPTER_ERR_INVALID_HANDLE; + } + } + + return ret_val; +} + +enum loc_api_adapter_err +LocApiRpc::close() +{ + if (RPC_LOC_CLIENT_HANDLE_INVALID != client_handle) { + loc_clear(client_handle); + } + + loc_close(client_handle); + mMask = 0; + client_handle = RPC_LOC_CLIENT_HANDLE_INVALID; + + return LOC_API_ADAPTER_ERR_SUCCESS; +} + +enum loc_api_adapter_err +LocApiRpc::startFix(const LocPosMode& posMode) { + LOC_LOGD("LocApiRpc::startFix() called"); + return convertErr( + loc_start_fix(client_handle) + ); +} + +enum loc_api_adapter_err +LocApiRpc::stopFix() { + LOC_LOGD("LocApiRpc::stopFix() called"); + return convertErr( + loc_stop_fix(client_handle) + ); +} + +enum loc_api_adapter_err +LocApiRpc::setPositionMode(const LocPosMode& posMode) +{ + rpc_loc_ioctl_data_u_type ioctl_data; + rpc_loc_fix_criteria_s_type *fix_criteria_ptr = + &ioctl_data.rpc_loc_ioctl_data_u_type_u.fix_criteria; + rpc_loc_ioctl_e_type ioctl_type = RPC_LOC_IOCTL_SET_FIX_CRITERIA; + rpc_loc_operation_mode_e_type op_mode; + int ret_val; + const LocPosMode* fixCriteria = &posMode; + + ALOGD ("loc_eng_set_position mode, client = %d, interval = %d, mode = %d\n", + (int32) client_handle, fixCriteria->min_interval, fixCriteria->mode); + + switch (fixCriteria->mode) + { + case LOC_POSITION_MODE_MS_BASED: + op_mode = RPC_LOC_OPER_MODE_MSB; + break; + case LOC_POSITION_MODE_MS_ASSISTED: + op_mode = RPC_LOC_OPER_MODE_MSA; + break; + case LOC_POSITION_MODE_RESERVED_1: + op_mode = RPC_LOC_OPER_MODE_SPEED_OPTIMAL; + break; + case LOC_POSITION_MODE_RESERVED_2: + op_mode = RPC_LOC_OPER_MODE_ACCURACY_OPTIMAL; + break; + case LOC_POSITION_MODE_RESERVED_3: + op_mode = RPC_LOC_OPER_MODE_DATA_OPTIMAL; + break; + case LOC_POSITION_MODE_RESERVED_4: + case LOC_POSITION_MODE_RESERVED_5: + op_mode = RPC_LOC_OPER_MODE_MSA; + fix_criteria_ptr->preferred_response_time = 0; + break; + default: + op_mode = RPC_LOC_OPER_MODE_STANDALONE; + } + + fix_criteria_ptr->valid_mask = RPC_LOC_FIX_CRIT_VALID_PREFERRED_OPERATION_MODE | + RPC_LOC_FIX_CRIT_VALID_RECURRENCE_TYPE; + fix_criteria_ptr->min_interval = fixCriteria->min_interval; + fix_criteria_ptr->preferred_operation_mode = op_mode; + + fix_criteria_ptr->min_interval = fixCriteria->min_interval; + fix_criteria_ptr->valid_mask |= RPC_LOC_FIX_CRIT_VALID_MIN_INTERVAL; + + if (fixCriteria->preferred_accuracy > 0) { + fix_criteria_ptr->preferred_accuracy = fixCriteria->preferred_accuracy; + fix_criteria_ptr->valid_mask |= RPC_LOC_FIX_CRIT_VALID_PREFERRED_ACCURACY; + } + if (fixCriteria->preferred_time > 0) { + fix_criteria_ptr->preferred_response_time = fixCriteria->preferred_time; + fix_criteria_ptr->valid_mask |= RPC_LOC_FIX_CRIT_VALID_PREFERRED_RESPONSE_TIME; + } + + switch (fixCriteria->recurrence) { + case GPS_POSITION_RECURRENCE_SINGLE: + fix_criteria_ptr->recurrence_type = RPC_LOC_SINGLE_FIX; + break; + case GPS_POSITION_RECURRENCE_PERIODIC: + default: + fix_criteria_ptr->recurrence_type = RPC_LOC_PERIODIC_FIX; + break; + } + ioctl_data.disc = ioctl_type; + + ret_val = loc_eng_ioctl (client_handle, + ioctl_type, + &ioctl_data, + LOC_IOCTL_DEFAULT_TIMEOUT, + NULL /* No output information is expected*/); + + return convertErr(ret_val); +} + +enum loc_api_adapter_err +LocApiRpc::setTime(GpsUtcTime time, int64_t timeReference, int uncertainty) +{ + rpc_loc_ioctl_data_u_type ioctl_data; + rpc_loc_assist_data_time_s_type *time_info_ptr; + rpc_loc_ioctl_e_type ioctl_type = RPC_LOC_IOCTL_INJECT_UTC_TIME; + int ret_val; + + LOC_LOGD ("loc_eng_inject_time, uncertainty = %d\n", uncertainty); + + time_info_ptr = &ioctl_data.rpc_loc_ioctl_data_u_type_u.assistance_data_time; + time_info_ptr->time_utc = time; + time_info_ptr->time_utc += (int64_t)(ELAPSED_MILLIS_SINCE_BOOT_PLATFORM_LIB_ABSTRACTION - timeReference); + time_info_ptr->uncertainty = uncertainty; // Uncertainty in ms + + ioctl_data.disc = ioctl_type; + + ret_val = loc_eng_ioctl (client_handle, + ioctl_type, + &ioctl_data, + LOC_IOCTL_DEFAULT_TIMEOUT, + NULL /* No output information is expected*/); + + return convertErr(ret_val); +} + +enum loc_api_adapter_err +LocApiRpc::injectPosition(double latitude, double longitude, float accuracy) +{ + /* IOCTL data */ + rpc_loc_ioctl_data_u_type ioctl_data; + rpc_loc_assist_data_pos_s_type *assistance_data_position = + &ioctl_data.rpc_loc_ioctl_data_u_type_u.assistance_data_position; + int ret_val; + + /************************************************ + * Fill in latitude, longitude & accuracy + ************************************************/ + + /* This combo is required */ + assistance_data_position->valid_mask = + RPC_LOC_ASSIST_POS_VALID_LATITUDE | + RPC_LOC_ASSIST_POS_VALID_LONGITUDE | + RPC_LOC_ASSIST_POS_VALID_HOR_UNC_CIRCULAR | + RPC_LOC_ASSIST_POS_VALID_CONFIDENCE_HORIZONTAL; + + assistance_data_position->latitude = latitude; + assistance_data_position->longitude = longitude; + assistance_data_position->hor_unc_circular = accuracy; /* Meters assumed */ + assistance_data_position->confidence_horizontal = 63; /* 63% (1 std dev) assumed */ + + /* Log */ + LOC_LOGD("Inject coarse position Lat=%lf, Lon=%lf, Acc=%.2lf\n", + (double) assistance_data_position->latitude, + (double) assistance_data_position->longitude, + (double) assistance_data_position->hor_unc_circular); + + ret_val = loc_eng_ioctl( client_handle, + RPC_LOC_IOCTL_INJECT_POSITION, + &ioctl_data, + LOC_IOCTL_DEFAULT_TIMEOUT, + NULL /* No output information is expected*/); + return convertErr(ret_val); +} + +enum loc_api_adapter_err +LocApiRpc::informNiResponse(GpsUserResponseType userResponse, + const void* passThroughData) +{ + rpc_loc_ioctl_data_u_type data; + rpc_loc_ioctl_callback_s_type callback_payload; + + memcpy(&data.rpc_loc_ioctl_data_u_type_u.user_verify_resp.ni_event_pass_back, + passThroughData, sizeof (rpc_loc_ni_event_s_type)); + + rpc_loc_ni_user_resp_e_type resp; + switch (userResponse) + { + case GPS_NI_RESPONSE_ACCEPT: + data.rpc_loc_ioctl_data_u_type_u.user_verify_resp.user_resp = + RPC_LOC_NI_LCS_NOTIFY_VERIFY_ACCEPT; + break; + case GPS_NI_RESPONSE_DENY: + data.rpc_loc_ioctl_data_u_type_u.user_verify_resp.user_resp = + RPC_LOC_NI_LCS_NOTIFY_VERIFY_DENY; + break; + case GPS_NI_RESPONSE_NORESP: + default: + data.rpc_loc_ioctl_data_u_type_u.user_verify_resp.user_resp = + RPC_LOC_NI_LCS_NOTIFY_VERIFY_NORESP; + break; + } + + return convertErr( + loc_eng_ioctl(client_handle, + RPC_LOC_IOCTL_INFORM_NI_USER_RESPONSE, + &data, + LOC_IOCTL_DEFAULT_TIMEOUT, + &callback_payload) + ); +} + +enum loc_api_adapter_err +LocApiRpc::setAPN(char* apn, int len, boolean force) +{ + enum loc_api_adapter_err rtv = LOC_API_ADAPTER_ERR_SUCCESS; + int size = sizeof(apnLastSet); + if (force || memcmp(apnLastSet, apn, size)) { + if (len < size) { + // size will be not larger than its original value + size = len + 1; + } + memcpy(apnLastSet, apn, size); + + if (!isInSession()) { + rpc_loc_ioctl_data_u_type ioctl_data = {RPC_LOC_IOCTL_SET_LBS_APN_PROFILE, {0}}; + ioctl_data.rpc_loc_ioctl_data_u_type_u.apn_profiles[0].srv_system_type = LOC_APN_PROFILE_SRV_SYS_MAX; + ioctl_data.rpc_loc_ioctl_data_u_type_u.apn_profiles[0].pdp_type = LOC_APN_PROFILE_PDN_TYPE_IPV4; + memcpy(&(ioctl_data.rpc_loc_ioctl_data_u_type_u.apn_profiles[0].apn_name), apn, size); + + rtv = convertErr( + loc_eng_ioctl (client_handle, + RPC_LOC_IOCTL_SET_LBS_APN_PROFILE, + &ioctl_data, + LOC_IOCTL_DEFAULT_TIMEOUT, + NULL) + ); + } + } + return rtv; +} + +void LocApiRpc::setInSession(bool inSession) +{ + if (!inSession) { + enableData(dataEnableLastSet, true); + setAPN(apnLastSet, sizeof(apnLastSet)-1, true); + } +} + +enum loc_api_adapter_err +LocApiRpc::setServer(const char* url, int len) +{ + rpc_loc_ioctl_data_u_type ioctl_data; + rpc_loc_server_info_s_type *server_info_ptr; + rpc_loc_ioctl_e_type ioctl_cmd; + + ioctl_cmd = RPC_LOC_IOCTL_SET_UMTS_SLP_SERVER_ADDR; + ioctl_data.disc = ioctl_cmd; + server_info_ptr = &ioctl_data.rpc_loc_ioctl_data_u_type_u.server_addr; + server_info_ptr->addr_type = RPC_LOC_SERVER_ADDR_URL; + server_info_ptr->addr_info.disc = server_info_ptr->addr_type; + server_info_ptr->addr_info.rpc_loc_server_addr_u_type_u.url.length = len; +#if (AMSS_VERSION==3200) + server_info_ptr->addr_info.rpc_loc_server_addr_u_type_u.url.addr.addr_val = (char*) url; + server_info_ptr->addr_info.rpc_loc_server_addr_u_type_u.url.addr.addr_len= len; +#else + strlcpy(server_info_ptr->addr_info.rpc_loc_server_addr_u_type_u.url.addr, url, + sizeof server_info_ptr->addr_info.rpc_loc_server_addr_u_type_u.url.addr); +#endif /* #if (AMSS_VERSION==3200) */ + LOC_LOGD ("loc_eng_set_server, addr = %s\n", url); + + return convertErr( + loc_eng_ioctl (client_handle, + ioctl_cmd, + &ioctl_data, + LOC_IOCTL_DEFAULT_TIMEOUT, + NULL /* No output information is expected*/) + ); +} + +enum loc_api_adapter_err +LocApiRpc::setServer(unsigned int ip, int port, LocServerType type) +{ + rpc_loc_ioctl_data_u_type ioctl_data; + rpc_loc_server_info_s_type *server_info_ptr; + rpc_loc_ioctl_e_type ioctl_cmd; + + switch (type) { + case LOC_AGPS_MPC_SERVER: + ioctl_cmd = RPC_LOC_IOCTL_SET_CDMA_MPC_SERVER_ADDR; + break; + case LOC_AGPS_CUSTOM_PDE_SERVER: + ioctl_cmd = RPC_LOC_IOCTL_SET_CUSTOM_PDE_SERVER_ADDR; + break; + default: + ioctl_cmd = RPC_LOC_IOCTL_SET_CDMA_PDE_SERVER_ADDR; + break; + } + ioctl_data.disc = ioctl_cmd; + server_info_ptr = &ioctl_data.rpc_loc_ioctl_data_u_type_u.server_addr; + server_info_ptr->addr_type = RPC_LOC_SERVER_ADDR_IPV4; + server_info_ptr->addr_info.disc = server_info_ptr->addr_type; + server_info_ptr->addr_info.rpc_loc_server_addr_u_type_u.ipv4.addr = ip; + server_info_ptr->addr_info.rpc_loc_server_addr_u_type_u.ipv4.port = port; + LOC_LOGD ("setServer, addr = %X:%d\n", (unsigned int) ip, (unsigned int) port); + + return convertErr( + loc_eng_ioctl (client_handle, + ioctl_cmd, + &ioctl_data, + LOC_IOCTL_DEFAULT_TIMEOUT, + NULL /* No output information is expected*/) + ); +} + +enum loc_api_adapter_err +LocApiRpc::enableData(int enable, boolean force) +{ + enum loc_api_adapter_err rtv = LOC_API_ADAPTER_ERR_SUCCESS; + if (force || dataEnableLastSet != enable) { + dataEnableLastSet = enable; + + if (!isInSession()) { + rpc_loc_ioctl_data_u_type ioctl_data = {RPC_LOC_IOCTL_SET_DATA_ENABLE, {0}}; + + ioctl_data.rpc_loc_ioctl_data_u_type_u.data_enable = enable; + rtv = convertErr( + loc_eng_ioctl (client_handle, + RPC_LOC_IOCTL_SET_DATA_ENABLE, + &ioctl_data, + LOC_IOCTL_DEFAULT_TIMEOUT, + NULL) + ); + } + } + return rtv; +} + +enum loc_api_adapter_err +LocApiRpc::deleteAidingData(GpsAidingData bits) +{ + rpc_loc_ioctl_data_u_type ioctl_data = {RPC_LOC_IOCTL_DELETE_ASSIST_DATA, {0}}; + ioctl_data.rpc_loc_ioctl_data_u_type_u.assist_data_delete.type = bits; + + return convertErr( + loc_eng_ioctl (client_handle, + RPC_LOC_IOCTL_DELETE_ASSIST_DATA, + &ioctl_data, + LOC_IOCTL_DEFAULT_TIMEOUT, + NULL) + ); +} + +void LocApiRpc::reportPosition(const rpc_loc_parsed_position_s_type *location_report_ptr) +{ + LocPosTechMask tech_Mask = LOC_POS_TECH_MASK_DEFAULT; + + UlpLocation location = {0}; + GpsLocationExtended locationExtended = {0}; + + location.size = sizeof(location); + locationExtended.size = sizeof(locationExtended); + if (location_report_ptr->valid_mask & RPC_LOC_POS_VALID_SESSION_STATUS) + { + // Process the position from final and intermediate reports + if (location_report_ptr->session_status == RPC_LOC_SESS_STATUS_SUCCESS || + location_report_ptr->session_status == RPC_LOC_SESS_STATUS_IN_PROGESS) + { + // Latitude & Longitude + if ((location_report_ptr->valid_mask & RPC_LOC_POS_VALID_LATITUDE) && + (location_report_ptr->valid_mask & RPC_LOC_POS_VALID_LONGITUDE) && + (location_report_ptr->latitude != 0 || + location_report_ptr->longitude != 0)) + { + location.gpsLocation.flags |= GPS_LOCATION_HAS_LAT_LONG; + location.gpsLocation.latitude = location_report_ptr->latitude; + location.gpsLocation.longitude = location_report_ptr->longitude; + + // Time stamp (UTC) + if (location_report_ptr->valid_mask & RPC_LOC_POS_VALID_TIMESTAMP_UTC) + { + location.gpsLocation.timestamp = location_report_ptr->timestamp_utc; + } + + // Altitude + if (location_report_ptr->valid_mask & RPC_LOC_POS_VALID_ALTITUDE_WRT_ELLIPSOID ) + { + location.gpsLocation.flags |= GPS_LOCATION_HAS_ALTITUDE; + location.gpsLocation.altitude = location_report_ptr->altitude_wrt_ellipsoid; + } + + // Speed + if (location_report_ptr->valid_mask & RPC_LOC_POS_VALID_SPEED_HORIZONTAL) + { + location.gpsLocation.flags |= GPS_LOCATION_HAS_SPEED; + location.gpsLocation.speed = location_report_ptr->speed_horizontal; + } + + // Heading + if (location_report_ptr->valid_mask & RPC_LOC_POS_VALID_HEADING) + { + location.gpsLocation.flags |= GPS_LOCATION_HAS_BEARING; + location.gpsLocation.bearing = location_report_ptr->heading; + } + + // Uncertainty (circular) + if ( (location_report_ptr->valid_mask & RPC_LOC_POS_VALID_HOR_UNC_CIRCULAR) ) + { + location.gpsLocation.flags |= GPS_LOCATION_HAS_ACCURACY; + location.gpsLocation.accuracy = location_report_ptr->hor_unc_circular; + } + + // Technology Mask + + tech_Mask |= location_report_ptr->technology_mask; + //Mark the location source as from GNSS + location.gpsLocation.flags |= LOCATION_HAS_SOURCE_INFO; + location.position_source = ULP_LOCATION_IS_FROM_GNSS; + if (location_report_ptr->valid_mask & RPC_LOC_POS_VALID_ALTITUDE_WRT_MEAN_SEA_LEVEL) + { + locationExtended.flags |= GPS_LOCATION_EXTENDED_HAS_ALTITUDE_MEAN_SEA_LEVEL; + locationExtended.altitudeMeanSeaLevel = location_report_ptr->altitude_wrt_mean_sea_level; + } + + if (location_report_ptr->valid_mask & RPC_LOC_POS_VALID_MAGNETIC_VARIATION ) + { + locationExtended.flags |= GPS_LOCATION_EXTENDED_HAS_MAG_DEV; + locationExtended.magneticDeviation = location_report_ptr->magnetic_deviation; + } + + if (location_report_ptr->valid_mask & RPC_LOC_POS_VALID_VERTICAL_UNC) + { + locationExtended.flags |= GPS_LOCATION_EXTENDED_HAS_VERT_UNC; + locationExtended.vert_unc = location_report_ptr->vert_unc; + } + + if (location_report_ptr->valid_mask & RPC_LOC_POS_VALID_SPEED_UNC) + { + locationExtended.flags |= GPS_LOCATION_EXTENDED_HAS_SPEED_UNC; + locationExtended.speed_unc = location_report_ptr->speed_unc; + } + + LOC_LOGV("reportPosition: fire callback\n"); + enum loc_sess_status fixStatus = + (location_report_ptr->session_status + == RPC_LOC_SESS_STATUS_IN_PROGESS ? + LOC_SESS_INTERMEDIATE : LOC_SESS_SUCCESS); + LocApiBase::reportPosition(location, + locationExtended, + (void*)location_report_ptr, + fixStatus, + tech_Mask); + } + } + else + { + LocApiBase::reportPosition(location, + locationExtended, + NULL, + LOC_SESS_FAILURE); + LOC_LOGV("loc_eng_report_position: ignore position report " + "when session status = %d\n", + location_report_ptr->session_status); + } + } + else + { + LOC_LOGV("loc_eng_report_position: ignore position report " + "when session status is not set\n"); + } +} + +void LocApiRpc::reportSv(const rpc_loc_gnss_info_s_type *gnss_report_ptr) +{ + GnssSvStatus SvStatus = {0}; + GpsLocationExtended locationExtended = {0}; + locationExtended.size = sizeof(locationExtended); + int num_svs_max = 0; + const rpc_loc_sv_info_s_type *sv_info_ptr; + + if (gnss_report_ptr->valid_mask & RPC_LOC_GNSS_INFO_VALID_SV_COUNT) + { + num_svs_max = gnss_report_ptr->sv_count; + if (num_svs_max > GPS_MAX_SVS) + { + num_svs_max = GPS_MAX_SVS; + } + } + + if (gnss_report_ptr->valid_mask & RPC_LOC_GNSS_INFO_VALID_SV_LIST) + { + SvStatus.num_svs = 0; + + for (int i = 0; i < num_svs_max; i++) + { + sv_info_ptr = &(gnss_report_ptr->sv_list.sv_list_val[i]); + if (sv_info_ptr->valid_mask & RPC_LOC_SV_INFO_VALID_SYSTEM) + { + if (sv_info_ptr->system == RPC_LOC_SV_SYSTEM_GPS) + { + SvStatus.sv_list[SvStatus.num_svs].size = sizeof(GpsSvInfo); + SvStatus.sv_list[SvStatus.num_svs].prn = sv_info_ptr->prn; + + // We only have the data field to report gps eph and alm mask + if ((sv_info_ptr->valid_mask & RPC_LOC_SV_INFO_VALID_HAS_EPH) && + (sv_info_ptr->has_eph == 1)) + { + SvStatus.ephemeris_mask |= (1 << (sv_info_ptr->prn-1)); + } + + if ((sv_info_ptr->valid_mask & RPC_LOC_SV_INFO_VALID_HAS_ALM) && + (sv_info_ptr->has_alm == 1)) + { + SvStatus.almanac_mask |= (1 << (sv_info_ptr->prn-1)); + } + + if ((sv_info_ptr->valid_mask & RPC_LOC_SV_INFO_VALID_PROCESS_STATUS) && + (sv_info_ptr->process_status == RPC_LOC_SV_STATUS_TRACK)) + { + SvStatus.gps_used_in_fix_mask |= (1 << (sv_info_ptr->prn-1)); + } + } + // SBAS: GPS RPN: 120-151, + // In exteneded measurement report, we follow nmea standard, which is from 33-64. + else if (sv_info_ptr->system == RPC_LOC_SV_SYSTEM_SBAS) + { + SvStatus.sv_list[SvStatus.num_svs].prn = sv_info_ptr->prn + 33 - 120; + } + // Gloness: Slot id: 1-32 + // In extended measurement report, we follow nmea standard, which is 65-96 + else if (sv_info_ptr->system == RPC_LOC_SV_SYSTEM_GLONASS) + { + if ((sv_info_ptr->valid_mask & RPC_LOC_SV_INFO_VALID_PROCESS_STATUS) && + (sv_info_ptr->process_status == RPC_LOC_SV_STATUS_TRACK)) + { + SvStatus.glo_used_in_fix_mask |= (1 << (sv_info_ptr->prn-1)); + } + + SvStatus.sv_list[SvStatus.num_svs].prn = sv_info_ptr->prn + (65-1); + } + // Unsupported SV system + else + { + continue; + } + } + + if (sv_info_ptr->valid_mask & RPC_LOC_SV_INFO_VALID_SNR) + { + SvStatus.sv_list[SvStatus.num_svs].snr = sv_info_ptr->snr; + } + + if (sv_info_ptr->valid_mask & RPC_LOC_SV_INFO_VALID_ELEVATION) + { + SvStatus.sv_list[SvStatus.num_svs].elevation = sv_info_ptr->elevation; + } + + if (sv_info_ptr->valid_mask & RPC_LOC_SV_INFO_VALID_AZIMUTH) + { + SvStatus.sv_list[SvStatus.num_svs].azimuth = sv_info_ptr->azimuth; + } + + SvStatus.num_svs++; + } + } + + if ((gnss_report_ptr->valid_mask & RPC_LOC_GNSS_INFO_VALID_POS_DOP) && + (gnss_report_ptr->valid_mask & RPC_LOC_GNSS_INFO_VALID_HOR_DOP) && + (gnss_report_ptr->valid_mask & RPC_LOC_GNSS_INFO_VALID_VERT_DOP)) + { + locationExtended.flags |= GPS_LOCATION_EXTENDED_HAS_DOP; + locationExtended.pdop = gnss_report_ptr->position_dop; + locationExtended.hdop = gnss_report_ptr->horizontal_dop; + locationExtended.vdop = gnss_report_ptr->vertical_dop; + } + + if (SvStatus.num_svs >= 0) + { + LocApiBase::reportSv(SvStatus, + locationExtended, + (void*)gnss_report_ptr); + } +} + +void LocApiRpc::reportStatus(const rpc_loc_status_event_s_type *status_report_ptr) +{ + + if (status_report_ptr->event == RPC_LOC_STATUS_EVENT_ENGINE_STATE) { + if (status_report_ptr->payload.rpc_loc_status_event_payload_u_type_u.engine_state == RPC_LOC_ENGINE_STATE_ON) + { + LocApiBase::reportStatus(GPS_STATUS_ENGINE_ON); + LocApiBase::reportStatus(GPS_STATUS_SESSION_BEGIN); + } + else if (status_report_ptr->payload.rpc_loc_status_event_payload_u_type_u.engine_state == RPC_LOC_ENGINE_STATE_OFF) + { + LocApiBase::reportStatus(GPS_STATUS_SESSION_END); + LocApiBase::reportStatus(GPS_STATUS_ENGINE_OFF); + } + else + { + LocApiBase::reportStatus(GPS_STATUS_NONE); + } + } + +} + +void LocApiRpc::reportNmea(const rpc_loc_nmea_report_s_type *nmea_report_ptr) +{ + +#if (AMSS_VERSION==3200) + LocApiBase::reportNmea(nmea_report_ptr->nmea_sentences.nmea_sentences_val, + nmea_report_ptr->nmea_sentences.nmea_sentences_len); +#else + LocApiBase::reportNmea(nmea_report_ptr->nmea_sentences, + nmea_report_ptr->length); + LOC_LOGD("loc_eng_report_nmea: $%c%c%c\n", + nmea_report_ptr->nmea_sentences[3], + nmea_report_ptr->nmea_sentences[4], + nmea_report_ptr->nmea_sentences[5]); +#endif /* #if (AMSS_VERSION==3200) */ +} + +enum loc_api_adapter_err +LocApiRpc::setXtraData(char* data, int length) +{ + int rpc_ret_val = RPC_LOC_API_GENERAL_FAILURE; + int total_parts; + uint8 part; + uint16 part_len; + uint16 len_injected; + rpc_loc_ioctl_data_u_type ioctl_data; + rpc_loc_ioctl_e_type ioctl_type = RPC_LOC_IOCTL_INJECT_PREDICTED_ORBITS_DATA; + rpc_loc_predicted_orbits_data_s_type *predicted_orbits_data_ptr; + + LOC_LOGD("qct_loc_eng_inject_xtra_data, xtra size = %d, data ptr = 0x%lx\n", length, (long) data); + + predicted_orbits_data_ptr = &ioctl_data.rpc_loc_ioctl_data_u_type_u.predicted_orbits_data; + predicted_orbits_data_ptr->format_type = RPC_LOC_PREDICTED_ORBITS_XTRA; + predicted_orbits_data_ptr->total_size = length; + total_parts = (length - 1) / XTRA_BLOCK_SIZE + 1; + predicted_orbits_data_ptr->total_parts = total_parts; + + len_injected = 0; // O bytes injected + ioctl_data.disc = ioctl_type; + + // XTRA injection starts with part 1 + for (part = 1; part <= total_parts; part++) + { + predicted_orbits_data_ptr->part = part; + predicted_orbits_data_ptr->part_len = XTRA_BLOCK_SIZE; + if (XTRA_BLOCK_SIZE > (length - len_injected)) + { + predicted_orbits_data_ptr->part_len = length - len_injected; + } + predicted_orbits_data_ptr->data_ptr.data_ptr_len = predicted_orbits_data_ptr->part_len; + predicted_orbits_data_ptr->data_ptr.data_ptr_val = data + len_injected; + + LOC_LOGD("qct_loc_eng_inject_xtra_data, part %d/%d, len = %d, total = %d\n", + predicted_orbits_data_ptr->part, + total_parts, + predicted_orbits_data_ptr->part_len, + len_injected); + + if (part < total_parts) + { + // No callback in this case + rpc_ret_val = loc_ioctl (client_handle, + ioctl_type, + &ioctl_data); + + if (rpc_ret_val != RPC_LOC_API_SUCCESS) + { + LOC_LOGE("loc_ioctl for xtra error: %s\n", loc_get_ioctl_status_name(rpc_ret_val)); + break; + } + //Add a delay of 10 ms so that repeated RPC calls dont starve the modem processor + usleep(10 * 1000); + } + else // part == total_parts + { + // Last part injection, will need to wait for callback + if (!loc_eng_ioctl(client_handle, + ioctl_type, + &ioctl_data, + LOC_XTRA_INJECT_DEFAULT_TIMEOUT, + NULL)) + { + rpc_ret_val = RPC_LOC_API_GENERAL_FAILURE; + } + break; // done with injection + } + + len_injected += predicted_orbits_data_ptr->part_len; + LOC_LOGD("loc_ioctl XTRA injected length: %d\n", len_injected); + } + + return convertErr(rpc_ret_val); +} + +/* Request the Xtra Server Url from the modem */ +enum loc_api_adapter_err +LocApiRpc::requestXtraServer() +{ + loc_api_adapter_err err; + rpc_loc_ioctl_data_u_type data; + rpc_loc_ioctl_callback_s_type callback_data; + + err = convertErr(loc_eng_ioctl(client_handle, + RPC_LOC_IOCTL_QUERY_PREDICTED_ORBITS_DATA_SOURCE, + &data, + LOC_IOCTL_DEFAULT_TIMEOUT, + &callback_data)); + + if (LOC_API_ADAPTER_ERR_SUCCESS != err) + { + LOC_LOGE("RPC_LOC_IOCTL_QUERY_PREDICTED_ORBITS_DATA_SOURCE failed!: err=%d\n", err); + return err; + } + else if (RPC_LOC_SESS_STATUS_SUCCESS != callback_data.status) + { + LOC_LOGE("RPC_LOC_IOCTL_QUERY_PREDICTED_ORBITS_DATA_SOURCE failed!: status=%ld\n", callback_data.status); + return LOC_API_ADAPTER_ERR_GENERAL_FAILURE; + } + else if (RPC_LOC_IOCTL_QUERY_PREDICTED_ORBITS_DATA_SOURCE != callback_data.type) + { + LOC_LOGE("RPC_LOC_IOCTL_QUERY_PREDICTED_ORBITS_DATA_SOURCE is not the type expected! type=%d\n", callback_data.type); + return LOC_API_ADAPTER_ERR_GENERAL_FAILURE; + } + else if (RPC_LOC_IOCTL_QUERY_PREDICTED_ORBITS_DATA_SOURCE != callback_data.data.disc) + { + LOC_LOGE("RPC_LOC_IOCTL_QUERY_PREDICTED_ORBITS_DATA_SOURCE is not the disc expected! disc=%d\n", callback_data.data.disc); + return LOC_API_ADAPTER_ERR_GENERAL_FAILURE; + } + + reportXtraServer(callback_data.data.rpc_loc_ioctl_callback_data_u_type_u. + predicted_orbits_data_source.servers[0], + callback_data.data.rpc_loc_ioctl_callback_data_u_type_u. + predicted_orbits_data_source.servers[1], + callback_data.data.rpc_loc_ioctl_callback_data_u_type_u. + predicted_orbits_data_source.servers[2], + 255); + + return LOC_API_ADAPTER_ERR_SUCCESS; +} + +enum loc_api_adapter_err +LocApiRpc::atlOpenStatus(int handle, int is_succ, char* apn, AGpsBearerType bearer, AGpsType agpsType) +{ + rpc_loc_server_open_status_e_type open_status = is_succ ? RPC_LOC_SERVER_OPEN_SUCCESS : RPC_LOC_SERVER_OPEN_FAIL; + rpc_loc_ioctl_data_u_type ioctl_data; + + if (AGPS_TYPE_INVALID == agpsType) { + rpc_loc_server_open_status_s_type *conn_open_status_ptr = + &ioctl_data.rpc_loc_ioctl_data_u_type_u.conn_open_status; + + // Fill in data + ioctl_data.disc = RPC_LOC_IOCTL_INFORM_SERVER_OPEN_STATUS; + conn_open_status_ptr->conn_handle = handle; + conn_open_status_ptr->open_status = open_status; +#if (AMSS_VERSION==3200) + conn_open_status_ptr->apn_name = apn; /* requires APN */ +#else + if (is_succ) { + strlcpy(conn_open_status_ptr->apn_name, apn, + sizeof conn_open_status_ptr->apn_name); + } else { + conn_open_status_ptr->apn_name[0] = 0; + } +#endif /* #if (AMSS_VERSION==3200) */ + + LOC_LOGD("ATL RPC_LOC_IOCTL_INFORM_SERVER_OPEN_STATUS open %s, APN name = [%s]\n", + log_succ_fail_string(is_succ), + apn); + } else { + rpc_loc_server_multi_open_status_s_type *conn_multi_open_status_ptr = + &ioctl_data.rpc_loc_ioctl_data_u_type_u.multi_conn_open_status; + + // Fill in data + ioctl_data.disc = RPC_LOC_IOCTL_INFORM_SERVER_MULTI_OPEN_STATUS; + conn_multi_open_status_ptr->conn_handle = handle; + conn_multi_open_status_ptr->open_status = open_status; + if (is_succ) { + strlcpy(conn_multi_open_status_ptr->apn_name, apn, + sizeof conn_multi_open_status_ptr->apn_name); + } else { + conn_multi_open_status_ptr->apn_name[0] = 0; + } + + switch(bearer) + { + case AGPS_APN_BEARER_IPV4: + conn_multi_open_status_ptr->pdp_type = RPC_LOC_SERVER_PDP_IP; + break; + case AGPS_APN_BEARER_IPV6: + conn_multi_open_status_ptr->pdp_type = RPC_LOC_SERVER_PDP_IPV6; + break; + case AGPS_APN_BEARER_IPV4V6: + conn_multi_open_status_ptr->pdp_type = RPC_LOC_SERVER_PDP_IPV4V6; + break; + default: + conn_multi_open_status_ptr->pdp_type = RPC_LOC_SERVER_PDP_PPP; + } + + LOC_LOGD("ATL RPC_LOC_IOCTL_INFORM_SERVER_MULTI_OPEN_STATUS open %s, APN name = [%s], pdp_type = %d\n", + log_succ_fail_string(is_succ), + apn, + conn_multi_open_status_ptr->pdp_type); + } + + // Make the IOCTL call + return convertErr( + loc_eng_ioctl(client_handle, + ioctl_data.disc, + &ioctl_data, + LOC_IOCTL_DEFAULT_TIMEOUT, + NULL) + ); +} + +enum loc_api_adapter_err +LocApiRpc::atlCloseStatus(int handle, int is_succ) +{ + rpc_loc_ioctl_data_u_type ioctl_data; + ioctl_data.disc = RPC_LOC_IOCTL_INFORM_SERVER_CLOSE_STATUS; + + rpc_loc_server_close_status_s_type *conn_close_status_ptr = + &ioctl_data.rpc_loc_ioctl_data_u_type_u.conn_close_status; + conn_close_status_ptr->conn_handle = handle; + conn_close_status_ptr->close_status = is_succ ? RPC_LOC_SERVER_CLOSE_SUCCESS : RPC_LOC_SERVER_CLOSE_FAIL; + + // Make the IOCTL call + return convertErr( + loc_eng_ioctl(client_handle, + ioctl_data.disc, + &ioctl_data, + LOC_IOCTL_DEFAULT_TIMEOUT, + NULL) + ); +} + +void LocApiRpc::ATLEvent(const rpc_loc_server_request_s_type *server_request_ptr) +{ + int connHandle; + AGpsType agps_type; + + LOC_LOGV("RPC_LOC_EVENT_ASSISTANCE_DATA_REQUEST event %s)", + loc_get_event_atl_open_name(server_request_ptr->event)); + switch (server_request_ptr->event) + { + case RPC_LOC_SERVER_REQUEST_MULTI_OPEN: + connHandle = server_request_ptr->payload.rpc_loc_server_request_u_type_u.multi_open_req.conn_handle; + if (server_request_ptr->payload.rpc_loc_server_request_u_type_u.multi_open_req.connection_type + == RPC_LOC_SERVER_CONNECTION_LBS) { + agps_type = AGPS_TYPE_SUPL; + LOC_LOGV("ATLEvent: event - RPC_LOC_SERVER_REQUEST_MULTI_OPEN\n type - AGPS_TYPE_SUPL\n handle - %d", connHandle); + } else { + agps_type = AGPS_TYPE_WWAN_ANY; + LOC_LOGV("ATLEvent: event - RPC_LOC_SERVER_REQUEST_MULTI_OPEN\n type - AGPS_TYPE_WWAN_ANY\n handle - %d", connHandle); + } + requestATL(connHandle, agps_type); + break; + case RPC_LOC_SERVER_REQUEST_OPEN: + connHandle = server_request_ptr->payload.rpc_loc_server_request_u_type_u.open_req.conn_handle; + LOC_LOGV("ATLEvent: event - RPC_LOC_SERVER_REQUEST_OPEN\n handle - %d", connHandle); + requestATL(connHandle, AGPS_TYPE_INVALID); + break; + case RPC_LOC_SERVER_REQUEST_CLOSE: + connHandle = server_request_ptr->payload.rpc_loc_server_request_u_type_u.close_req.conn_handle; + LOC_LOGV("ATLEvent: event - RPC_LOC_SERVER_REQUEST_CLOSE\n handle - %d", connHandle); + releaseATL(connHandle); + break; + default: + LOC_LOGE("ATLEvent: event type %d invalid", server_request_ptr->event); + } +} + +void LocApiRpc::NIEvent(const rpc_loc_ni_event_s_type *ni_req) +{ + GpsNiNotification notif = {0}; + + switch (ni_req->event) + { + case RPC_LOC_NI_EVENT_VX_NOTIFY_VERIFY_REQ: + { + const rpc_loc_ni_vx_notify_verify_req_s_type *vx_req = + &ni_req->payload.rpc_loc_ni_event_payload_u_type_u.vx_req; + LOC_LOGI("VX Notification"); + notif.ni_type = GPS_NI_TYPE_VOICE; + // Requestor ID + hexcode(notif.requestor_id, sizeof notif.requestor_id, + vx_req->requester_id.requester_id, + vx_req->requester_id.requester_id_length); + notif.text_encoding = 0; // No text and no encoding + notif.requestor_id_encoding = convertNiEncodingType(vx_req->encoding_scheme); + NIEventFillVerfiyType(notif, vx_req->notification_priv_type); + } + break; + + case RPC_LOC_NI_EVENT_UMTS_CP_NOTIFY_VERIFY_REQ: + { + const rpc_loc_ni_umts_cp_notify_verify_req_s_type *umts_cp_req = + &ni_req->payload.rpc_loc_ni_event_payload_u_type_u.umts_cp_req; + LOC_LOGI("UMTS CP Notification\n"); + notif.ni_type= GPS_NI_TYPE_UMTS_CTRL_PLANE; // Stores notification text +#if (AMSS_VERSION==3200) + hexcode(notif.text, sizeof notif.text, + umts_cp_req->notification_text.notification_text_val, + umts_cp_req->notification_length); + hexcode(notif.requestor_id, sizeof notif.requestor_id, + umts_cp_req->requestor_id.requestor_id_string.requestor_id_string_val, + umts_cp_req->requestor_id.string_len); +#else + hexcode(notif.text, sizeof notif.text, + umts_cp_req->notification_text, + umts_cp_req->notification_length); + hexcode(notif.requestor_id, sizeof notif.requestor_id, + umts_cp_req->requestor_id.requestor_id_string, + umts_cp_req->requestor_id.string_len); +#endif + notif.text_encoding = convertNiEncodingType(umts_cp_req->datacoding_scheme); + notif.requestor_id_encoding = notif.text_encoding; + NIEventFillVerfiyType(notif, umts_cp_req->notification_priv_type); + + // LCS address (using extras field) + if (umts_cp_req->ext_client_address_data.ext_client_address_len != 0) + { + // Copy LCS Address into notif.extras in the format: Address = 012345 + strlcat(notif.extras, LOC_NI_NOTIF_KEY_ADDRESS, sizeof notif.extras); + strlcat(notif.extras, " = ", sizeof notif.extras); + int addr_len = 0; + const char *address_source = NULL; + +#if (AMSS_VERSION==3200) + address_source = umts_cp_req->ext_client_address_data.ext_client_address.ext_client_address_val; +#else + address_source = umts_cp_req->ext_client_address_data.ext_client_address; +#endif /* #if (AMSS_VERSION==3200) */ + + char lcs_addr[32]; // Decoded LCS address for UMTS CP NI + addr_len = decodeAddress(lcs_addr, sizeof lcs_addr, address_source, + umts_cp_req->ext_client_address_data.ext_client_address_len); + + // The address is ASCII string + if (addr_len) + { + strlcat(notif.extras, lcs_addr, sizeof notif.extras); + } + } + } + break; + + case RPC_LOC_NI_EVENT_SUPL_NOTIFY_VERIFY_REQ: + { + const rpc_loc_ni_supl_notify_verify_req_s_type *supl_req = + &ni_req->payload.rpc_loc_ni_event_payload_u_type_u.supl_req; + LOC_LOGI("SUPL Notification\n"); + notif.ni_type = GPS_NI_TYPE_UMTS_SUPL; + + if (supl_req->flags & RPC_LOC_NI_CLIENT_NAME_PRESENT) + { +#if (AMSS_VERSION==3200) + hexcode(notif.text, sizeof notif.text, + supl_req->client_name.client_name_string.client_name_string_val, /* buffer */ + supl_req->client_name.string_len /* length */ + ); +#else + hexcode(notif.text, sizeof notif.text, + supl_req->client_name.client_name_string, /* buffer */ + supl_req->client_name.string_len /* length */ + ); +#endif /* #if (AMSS_VERSION==3200) */ + LOC_LOGV("SUPL NI: client_name: %s len=%d", notif.text, supl_req->client_name.string_len); + } + else { + LOC_LOGV("SUPL NI: client_name not present."); + } + + // Requestor ID + if (supl_req->flags & RPC_LOC_NI_REQUESTOR_ID_PRESENT) + { +#if (AMSS_VERSION==3200) + hexcode(notif.requestor_id, sizeof notif.requestor_id, + supl_req->requestor_id.requestor_id_string.requestor_id_string_val, /* buffer */ + supl_req->requestor_id.string_len /* length */ + ); +#else + hexcode(notif.requestor_id, sizeof notif.requestor_id, + supl_req->requestor_id.requestor_id_string, /* buffer */ + supl_req->requestor_id.string_len /* length */ + ); +#endif /* #if (AMSS_VERSION==3200) */ + LOC_LOGV("SUPL NI: requestor_id: %s len=%d", notif.requestor_id, supl_req->requestor_id.string_len); + } + else { + LOC_LOGV("SUPL NI: requestor_id not present."); + } + + // Encoding type + if (supl_req->flags & RPC_LOC_NI_ENCODING_TYPE_PRESENT) + { + notif.text_encoding = convertNiEncodingType(supl_req->datacoding_scheme); + notif.requestor_id_encoding = notif.text_encoding; + } + else { + notif.text_encoding = notif.requestor_id_encoding = GPS_ENC_UNKNOWN; + } + + NIEventFillVerfiyType(notif, ni_req->payload.rpc_loc_ni_event_payload_u_type_u.supl_req.notification_priv_type); + } + break; + + default: + LOC_LOGE("Unknown NI event: %x\n", (int) ni_req->event); + return; + } + + // this copy will get freed in loc_eng_ni when loc_ni_respond() is called + rpc_loc_ni_event_s_type *copy = (rpc_loc_ni_event_s_type *)malloc(sizeof(*copy)); + memcpy(copy, ni_req, sizeof(*copy)); + requestNiNotify(notif, (const void*)copy); +} + +int LocApiRpc::NIEventFillVerfiyType(GpsNiNotification ¬if, + rpc_loc_ni_notify_verify_e_type notif_priv) +{ + switch (notif_priv) + { + case RPC_LOC_NI_USER_NO_NOTIFY_NO_VERIFY: + notif.notify_flags = 0; + notif.default_response = GPS_NI_RESPONSE_NORESP; + return 1; + case RPC_LOC_NI_USER_NOTIFY_ONLY: + notif.notify_flags = GPS_NI_NEED_NOTIFY; + notif.default_response = GPS_NI_RESPONSE_NORESP; + return 1; + case RPC_LOC_NI_USER_NOTIFY_VERIFY_ALLOW_NO_RESP: + notif.notify_flags = GPS_NI_NEED_NOTIFY | GPS_NI_NEED_VERIFY; + notif.default_response = GPS_NI_RESPONSE_ACCEPT; + return 1; + case RPC_LOC_NI_USER_NOTIFY_VERIFY_NOT_ALLOW_NO_RESP: + notif.notify_flags = GPS_NI_NEED_NOTIFY | GPS_NI_NEED_VERIFY; + notif.default_response = GPS_NI_RESPONSE_DENY; + return 1; + case RPC_LOC_NI_USER_PRIVACY_OVERRIDE: + notif.notify_flags = GPS_NI_PRIVACY_OVERRIDE; + notif.default_response = GPS_NI_RESPONSE_NORESP; + return 1; + default: + return 0; + } +} + +enum loc_api_adapter_err +LocApiRpc::setSUPLVersion(uint32_t version) +{ + rpc_loc_ioctl_data_u_type ioctl_data = {RPC_LOC_IOCTL_SET_SUPL_VERSION, {0}}; + ioctl_data.rpc_loc_ioctl_data_u_type_u.supl_version = (int)version; + return convertErr( + loc_eng_ioctl (client_handle, + RPC_LOC_IOCTL_SET_SUPL_VERSION, + &ioctl_data, + LOC_IOCTL_DEFAULT_TIMEOUT, + NULL) + ); +} + +GpsNiEncodingType LocApiRpc::convertNiEncodingType(int loc_encoding) +{ + switch (loc_encoding) + { + case RPC_LOC_NI_SUPL_UTF8: + return GPS_ENC_SUPL_UTF8; + case RPC_LOC_NI_SUPL_UCS2: + return GPS_ENC_SUPL_UCS2; + case RPC_LOC_NI_SUPL_GSM_DEFAULT: + return GPS_ENC_SUPL_GSM_DEFAULT; + case RPC_LOC_NI_SS_LANGUAGE_UNSPEC: + return GPS_ENC_SUPL_GSM_DEFAULT; // SS_LANGUAGE_UNSPEC = GSM + default: + return GPS_ENC_UNKNOWN; + } +} + +LocApiBase* getLocApi(const MsgTask* msgTask, + LOC_API_ADAPTER_EVENT_MASK_T exMask, + ContextBase *context) { + return new LocApiRpc(msgTask, exMask, context); +} + +/*Values for lock + 1 = Do not lock any position sessions + 2 = Lock MI position sessions + 3 = Lock MT position sessions + 4 = Lock all position sessions +*/ +int LocApiRpc::setGpsLock(LOC_GPS_LOCK_MASK lockMask) +{ + rpc_loc_ioctl_data_u_type ioctl_data; + boolean ret_val; + LOC_LOGD("%s:%d]: lock: %x\n", __func__, __LINE__, lockMask); + ioctl_data.rpc_loc_ioctl_data_u_type_u.engine_lock = convertGpsLockMask(lockMask); + ioctl_data.disc = RPC_LOC_IOCTL_SET_ENGINE_LOCK; + ret_val = loc_eng_ioctl (loc_eng_data.client_handle, + RPC_LOC_IOCTL_SET_ENGINE_LOCK, + &ioctl_data, + LOC_IOCTL_DEFAULT_TIMEOUT, + NULL /* No output information is expected*/); + + LOC_LOGD("%s:%d]: ret_val: %d\n", __func__, __LINE__, (int)ret_val); + return (ret_val == TRUE ? 0 : -1); +} + +/* + Returns + Current value of GPS lock on success + -1 on failure +*/ +int LocApiRpc :: getGpsLock() +{ + rpc_loc_ioctl_data_u_type ioctl_data; + rpc_loc_ioctl_callback_s_type callback_payload; + boolean ret_val; + int ret=0; + LOC_LOGD("%s:%d]: Enter\n", __func__, __LINE__); + ret_val = loc_eng_ioctl (loc_eng_data.client_handle, + RPC_LOC_IOCTL_GET_ENGINE_LOCK, + &ioctl_data, + LOC_IOCTL_DEFAULT_TIMEOUT, + &callback_payload); + if(ret_val == TRUE) { + ret = (int)callback_payload.data.engine_lock; + LOC_LOGD("%s:%d]: Lock type: %d\n", __func__, __LINE__, ret); + } + else { + LOC_LOGE("%s:%d]: Ioctl failed", __func__, __LINE__); + ret = -1; + } + LOC_LOGD("%s:%d]: Exit\n", __func__, __LINE__); + return ret; +} diff --git a/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-glue/src/loc_api_fixup.c b/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-glue/src/loc_api_fixup.c new file mode 100644 index 000000000..837ef1139 --- /dev/null +++ b/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-glue/src/loc_api_fixup.c @@ -0,0 +1,52 @@ +/* Copyright (c) 2011, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#include "loc_api_fixup.h" + +#ifdef ADD_XDR_FLOAT + +int +xdr_float(xdrp, fp) + XDR *xdrp; + float *fp; +{ + return xdr_long(xdrp, (long*)fp); +} + +int +xdr_double(xdrp, dp) + XDR *xdrp; + double *dp; +{ + return xdr_long(xdrp, (long*)dp + 1) + && xdr_long(xdrp, (long*)dp); +} + +#endif /* ADD_XDR_FLOAT */ diff --git a/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-glue/src/loc_api_log.c b/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-glue/src/loc_api_log.c new file mode 100644 index 000000000..1c4823251 --- /dev/null +++ b/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-glue/src/loc_api_log.c @@ -0,0 +1,345 @@ +/* Copyright (c) 2011 The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#define LOG_NDDEBUG 0 +#define LOG_TAG "LocSvc_api_rpc_glue" + +#include "loc_api_log.h" +#include "loc_log.h" +#include "log_util.h" +#include "platform_lib_includes.h" +#include "rpc/rpc.h" +#include "loc_api_fixup.h" + +/* Event names */ +loc_name_val_s_type loc_event_name[] = + { + NAME_VAL( RPC_LOC_EVENT_PARSED_POSITION_REPORT ), + NAME_VAL( RPC_LOC_EVENT_SATELLITE_REPORT ), + NAME_VAL( RPC_LOC_EVENT_NMEA_1HZ_REPORT ), + NAME_VAL( RPC_LOC_EVENT_NMEA_POSITION_REPORT ), + NAME_VAL( RPC_LOC_EVENT_NI_NOTIFY_VERIFY_REQUEST ), + NAME_VAL( RPC_LOC_EVENT_ASSISTANCE_DATA_REQUEST ), + NAME_VAL( RPC_LOC_EVENT_LOCATION_SERVER_REQUEST ), + NAME_VAL( RPC_LOC_EVENT_IOCTL_REPORT ), + NAME_VAL( RPC_LOC_EVENT_STATUS_REPORT ), + NAME_VAL( RPC_LOC_EVENT_WPS_NEEDED_REQUEST ), + }; +int loc_event_num = sizeof loc_event_name / sizeof(loc_name_val_s_type); + +/* Event names */ +loc_name_val_s_type loc_event_atl_open_name[] = + { + NAME_VAL( RPC_LOC_SERVER_REQUEST_OPEN ), + NAME_VAL( RPC_LOC_SERVER_REQUEST_CLOSE ), + NAME_VAL( RPC_LOC_SERVER_REQUEST_MULTI_OPEN ) + }; +int loc_event_atl_open_num = sizeof loc_event_atl_open_name / sizeof(loc_name_val_s_type); + +/* Finds the first event found in the mask */ +const char* loc_get_event_atl_open_name(rpc_loc_server_request_e_type loc_event_atl_open) +{ + return loc_get_name_from_val(loc_event_atl_open_name, loc_event_atl_open_num, + (long) loc_event_atl_open); +} + +/* IOCTL Type names */ +loc_name_val_s_type loc_ioctl_type_name[] = + { + NAME_VAL( RPC_LOC_IOCTL_GET_API_VERSION ), + NAME_VAL( RPC_LOC_IOCTL_SET_FIX_CRITERIA ), + NAME_VAL( RPC_LOC_IOCTL_GET_FIX_CRITERIA ), + NAME_VAL( RPC_LOC_IOCTL_INFORM_NI_USER_RESPONSE ), + NAME_VAL( RPC_LOC_IOCTL_INJECT_PREDICTED_ORBITS_DATA ), + NAME_VAL( RPC_LOC_IOCTL_QUERY_PREDICTED_ORBITS_DATA_VALIDITY ), + NAME_VAL( RPC_LOC_IOCTL_QUERY_PREDICTED_ORBITS_DATA_SOURCE ), + NAME_VAL( RPC_LOC_IOCTL_SET_PREDICTED_ORBITS_DATA_AUTO_DOWNLOAD ), + NAME_VAL( RPC_LOC_IOCTL_INJECT_UTC_TIME ), + NAME_VAL( RPC_LOC_IOCTL_INJECT_RTC_VALUE ), + NAME_VAL( RPC_LOC_IOCTL_INJECT_POSITION ), + NAME_VAL( RPC_LOC_IOCTL_QUERY_ENGINE_STATE ), + NAME_VAL( RPC_LOC_IOCTL_ERROR_ESTIMATE_CONFIG), + NAME_VAL( RPC_LOC_IOCTL_INFORM_SERVER_MULTI_OPEN_STATUS ), + NAME_VAL( RPC_LOC_IOCTL_INFORM_SERVER_OPEN_STATUS ), + NAME_VAL( RPC_LOC_IOCTL_INFORM_SERVER_CLOSE_STATUS ), + NAME_VAL( RPC_LOC_IOCTL_SEND_WIPER_POSITION_REPORT ), + NAME_VAL( RPC_LOC_IOCTL_NOTIFY_WIPER_STATUS ), + NAME_VAL( RPC_LOC_IOCTL_SET_ENGINE_LOCK ), + NAME_VAL( RPC_LOC_IOCTL_GET_ENGINE_LOCK ), + NAME_VAL( RPC_LOC_IOCTL_SET_SBAS_CONFIG ), + NAME_VAL( RPC_LOC_IOCTL_GET_SBAS_CONFIG ), + NAME_VAL( RPC_LOC_IOCTL_SET_NMEA_TYPES ), + NAME_VAL( RPC_LOC_IOCTL_GET_NMEA_TYPES ), + NAME_VAL( RPC_LOC_IOCTL_SET_CDMA_PDE_SERVER_ADDR ), + NAME_VAL( RPC_LOC_IOCTL_GET_CDMA_PDE_SERVER_ADDR ), + NAME_VAL( RPC_LOC_IOCTL_SET_CDMA_MPC_SERVER_ADDR ), + NAME_VAL( RPC_LOC_IOCTL_GET_CDMA_MPC_SERVER_ADDR ), + NAME_VAL( RPC_LOC_IOCTL_SET_UMTS_SLP_SERVER_ADDR ), + NAME_VAL( RPC_LOC_IOCTL_GET_UMTS_SLP_SERVER_ADDR ), + NAME_VAL( RPC_LOC_IOCTL_SET_ON_DEMAND_LPM ), + NAME_VAL( RPC_LOC_IOCTL_GET_ON_DEMAND_LPM ), + NAME_VAL( RPC_LOC_IOCTL_SET_XTRA_T_SESSION_CONTROL ), + NAME_VAL( RPC_LOC_IOCTL_GET_XTRA_T_SESSION_CONTROL ), + NAME_VAL( RPC_LOC_IOCTL_SET_LBS_APN_PROFILE ), + NAME_VAL( RPC_LOC_IOCTL_GET_LBS_APN_PROFILE ), + NAME_VAL( RPC_LOC_IOCTL_SET_XTRA_APN_PROFILE ), + NAME_VAL( RPC_LOC_IOCTL_GET_XTRA_APN_PROFILE ), + NAME_VAL( RPC_LOC_IOCTL_SET_DATA_ENABLE ), + NAME_VAL( RPC_LOC_IOCTL_SET_SUPL_VERSION ), + NAME_VAL( RPC_LOC_IOCTL_GET_SUPL_VERSION ), + NAME_VAL( RPC_LOC_IOCTL_DELETE_ASSIST_DATA ), + NAME_VAL( RPC_LOC_IOCTL_SET_CUSTOM_PDE_SERVER_ADDR ), + NAME_VAL( RPC_LOC_IOCTL_GET_CUSTOM_PDE_SERVER_ADDR ), + }; +int loc_ioctl_type_num = sizeof loc_ioctl_type_name / sizeof(loc_name_val_s_type); + +/* IOCTL Status names */ +loc_name_val_s_type loc_ioctl_status_name[] = + { + NAME_VAL( RPC_LOC_API_SUCCESS ), + NAME_VAL( RPC_LOC_API_GENERAL_FAILURE ), + NAME_VAL( RPC_LOC_API_UNSUPPORTED ), + NAME_VAL( RPC_LOC_API_INVALID_HANDLE ), + NAME_VAL( RPC_LOC_API_INVALID_PARAMETER ), + NAME_VAL( RPC_LOC_API_ENGINE_BUSY ), + NAME_VAL( RPC_LOC_API_PHONE_OFFLINE ), + NAME_VAL( RPC_LOC_API_TIMEOUT ), + NAME_VAL( RPC_LOC_API_RPC_FAILURE ), + NAME_VAL( RPC_LOC_API_RPC_MODEM_RESTART ) + }; +int loc_ioctl_status_num = sizeof loc_ioctl_status_name / sizeof(loc_name_val_s_type); + +/* Fix session status names */ +loc_name_val_s_type loc_sess_status_name[] = + { + NAME_VAL( RPC_LOC_SESS_STATUS_SUCCESS ), + NAME_VAL( RPC_LOC_SESS_STATUS_IN_PROGESS ), + NAME_VAL( RPC_LOC_SESS_STATUS_GENERAL_FAILURE ), + NAME_VAL( RPC_LOC_SESS_STATUS_TIMEOUT ), + NAME_VAL( RPC_LOC_SESS_STATUS_USER_END ), + NAME_VAL( RPC_LOC_SESS_STATUS_BAD_PARAMETER ), + NAME_VAL( RPC_LOC_SESS_STATUS_PHONE_OFFLINE ), + NAME_VAL( RPC_LOC_SESS_STATUS_USER_END ), + NAME_VAL( RPC_LOC_SESS_STATUS_ENGINE_LOCKED ) + }; +int loc_sess_status_num = sizeof loc_sess_status_name / sizeof(loc_name_val_s_type); + +/* Engine state names */ +loc_name_val_s_type loc_engine_state_name[] = + { + NAME_VAL( RPC_LOC_ENGINE_STATE_ON ), + NAME_VAL( RPC_LOC_ENGINE_STATE_OFF ) + }; +int loc_engine_state_num = sizeof loc_engine_state_name / sizeof(loc_name_val_s_type); + +/* Fix session state names */ +loc_name_val_s_type loc_fix_session_state_name[] = + { + NAME_VAL( RPC_LOC_FIX_SESSION_STATE_BEGIN ), + NAME_VAL( RPC_LOC_FIX_SESSION_STATE_END ) + }; +int loc_fix_session_state_num = sizeof loc_fix_session_state_name / sizeof(loc_name_val_s_type); + + +static const char* log_final_interm_string(int is_final) +{ + return is_final ? "final" : "intermediate"; +} + +/* Logs parsed report */ +static void log_parsed_report(const rpc_loc_parsed_position_s_type *parsed_report) +{ + rpc_loc_session_status_e_type status = parsed_report->session_status; + LOC_LOGD("Session status: %s Valid mask: 0x%X\n", + loc_get_sess_status_name(status), + (uint) parsed_report->valid_mask); + LOC_LOGD("Latitude: %.7f (%s)\n", parsed_report->latitude, + log_final_interm_string( + (parsed_report->valid_mask & RPC_LOC_POS_VALID_LATITUDE) && + parsed_report->session_status == RPC_LOC_SESS_STATUS_SUCCESS)); + LOC_LOGD("Longitude: %.7f\n", parsed_report->longitude); + LOC_LOGD("Accuracy: %.7f\n", parsed_report->hor_unc_circular); +} + +/* Logs status report */ +static void log_status_report(const rpc_loc_status_event_s_type *status_event) +{ + rpc_loc_status_event_e_type event = status_event->event; + switch (event) { + case RPC_LOC_STATUS_EVENT_ENGINE_STATE: + LOC_LOGD("Engine state: %s\n", + loc_get_engine_state_name( + status_event->payload.rpc_loc_status_event_payload_u_type_u.engine_state)); + break; + case RPC_LOC_STATUS_EVENT_FIX_SESSION_STATE: + LOC_LOGD("Fix session state: %s\n", + loc_get_fix_session_state_name( + status_event->payload.rpc_loc_status_event_payload_u_type_u.fix_session_state)); + break; + default: + break; + } +} + +/* Logs valid fields in the GNSS SV constellation report */ +static void log_satellite_report(const rpc_loc_gnss_info_s_type *gnss) +{ + if (gnss->valid_mask & RPC_LOC_GNSS_INFO_VALID_POS_DOP) + { + LOC_LOGV("position dop: %.3f\n", (float) gnss->position_dop); + } + if (gnss->valid_mask & RPC_LOC_GNSS_INFO_VALID_HOR_DOP) + { + LOC_LOGV("horizontal dop: %.3f\n", (float) gnss->horizontal_dop); + } + if (gnss->valid_mask & RPC_LOC_GNSS_INFO_VALID_VERT_DOP) + { + LOC_LOGV("vertical dop: %.3f\n", (float) gnss->vertical_dop); + } + if (gnss->valid_mask & RPC_LOC_GNSS_INFO_VALID_ALTITUDE_ASSUMED) + { + LOC_LOGV("altitude assumed: %d\n", (int) gnss->altitude_assumed); + } + if (gnss->valid_mask & RPC_LOC_GNSS_INFO_VALID_SV_COUNT) + { + LOC_LOGD("sv count: %d\n", (int) gnss->sv_count); + } + if (gnss->valid_mask & RPC_LOC_GNSS_INFO_VALID_SV_LIST) + { + LOC_LOGV("sv list: "); + + if (gnss->sv_count) + { + LOC_LOGV("\n\tsys\tprn\thlth\tproc\teph\talm\telev\tazi\tsnr\n"); + } + else { + LOC_LOGV("empty\n"); + } + + int i; + for (i = 0; i < gnss->sv_count; i++) + { + const rpc_loc_sv_info_s_type *sv = &gnss->sv_list.sv_list_val[i]; + rpc_loc_sv_info_valid_mask_type mask = sv->valid_mask; + LOC_LOGV(" %d: \t%d\t%d\t%d\t%d\t%d\t%d\t%.3f\t%.3f\t%.3f\n", i, + CHECK_MASK(int, sv->system, mask, RPC_LOC_SV_INFO_VALID_SYSTEM), + CHECK_MASK(int, sv->prn, mask, RPC_LOC_SV_INFO_VALID_PRN), + CHECK_MASK(int, sv->health_status, mask, RPC_LOC_SV_INFO_VALID_HEALTH_STATUS), + CHECK_MASK(int, sv->process_status, mask, RPC_LOC_SV_INFO_VALID_PROCESS_STATUS), + CHECK_MASK(int, sv->has_eph, mask, RPC_LOC_SV_INFO_VALID_HAS_EPH), + CHECK_MASK(int, sv->has_alm, mask, RPC_LOC_SV_INFO_VALID_HAS_ALM), + CHECK_MASK(float, sv->elevation, mask, RPC_LOC_SV_INFO_VALID_ELEVATION), + CHECK_MASK(float, sv->azimuth, mask, RPC_LOC_SV_INFO_VALID_AZIMUTH), + CHECK_MASK(float, sv->snr, mask, RPC_LOC_SV_INFO_VALID_SNR) + ); + } + } +} + +/* Logs a callback event */ +int loc_callback_log( + rpc_loc_event_mask_type loc_event, /* event mask */ + const rpc_loc_event_payload_u_type* loc_event_payload /* payload */ +) +{ + switch (loc_event) + { + case RPC_LOC_EVENT_SATELLITE_REPORT: + log_satellite_report(&loc_event_payload-> + rpc_loc_event_payload_u_type_u.gnss_report); + break; + case RPC_LOC_EVENT_STATUS_REPORT: + log_status_report(&loc_event_payload-> + rpc_loc_event_payload_u_type_u.status_report); + break; + case RPC_LOC_EVENT_PARSED_POSITION_REPORT: + log_parsed_report(&loc_event_payload-> + rpc_loc_event_payload_u_type_u.parsed_location_report); + break; + default: + break; + } + + return 0; +} + +/* Finds the first event found in the mask */ +const char* loc_get_event_name(rpc_loc_event_mask_type loc_event_mask) +{ + return loc_get_name_from_mask(loc_event_name, loc_event_num, + (long) loc_event_mask); +} + +/* Finds IOCTL type name */ +const char* loc_get_ioctl_type_name(rpc_loc_ioctl_e_type ioctl_type) +{ + return loc_get_name_from_val(loc_ioctl_type_name, loc_ioctl_type_num, + (long) ioctl_type); +} + +/* Finds IOCTL status name */ +const char* loc_get_ioctl_status_name(uint32 status) +{ + return loc_get_name_from_val(loc_ioctl_status_name, loc_ioctl_status_num, + (long) status); +} + +/* Finds session status name */ +const char* loc_get_sess_status_name(rpc_loc_session_status_e_type status) +{ + return loc_get_name_from_val(loc_sess_status_name, loc_sess_status_num, + (long) status); +} + +/* Find engine state name */ +const char* loc_get_engine_state_name(rpc_loc_engine_state_e_type state) +{ + return loc_get_name_from_val(loc_engine_state_name, loc_engine_state_num, + (long) state); +} + +/* Find engine state name */ +const char* loc_get_fix_session_state_name(rpc_loc_fix_session_state_e_type state) +{ + return loc_get_name_from_val(loc_fix_session_state_name, loc_fix_session_state_num, + (long) state); +} + +/* Event names */ +loc_name_val_s_type rpc_reset_event_name[] = +{ + NAME_VAL( RPC_SUBSYSTEM_RESTART_BEGIN ), + NAME_VAL( RPC_SUBSYSTEM_RESTART_END ) +}; +int rpc_reset_event_num = sizeof rpc_reset_event_name / sizeof(loc_name_val_s_type); + +const char* loc_get_rpc_reset_event_name(enum rpc_reset_event event) +{ + return loc_get_name_from_val(rpc_reset_event_name, rpc_reset_event_num, event); +} diff --git a/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-glue/src/loc_api_rpc_glue.c b/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-glue/src/loc_api_rpc_glue.c new file mode 100644 index 000000000..e0f400cf9 --- /dev/null +++ b/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-glue/src/loc_api_rpc_glue.c @@ -0,0 +1,636 @@ +/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/*===================================================================== + + INCLUDE FILES FOR MODULE + +======================================================================*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* Include RPC headers */ +#include "rpc_inc/loc_api_rpc_glue.h" + +/* Callback init */ +#include "rpc_inc/loc_apicb_appinit.h" + +/* Logging */ +#define LOG_TAG "LocSvc_api_rpc_glue" +#define LOG_NDDEBUG 0 +#ifndef USE_GLIB +#include +#endif /* USE_GLIB */ + +/* Logging Improvement */ +#include "log_util.h" +#include "platform_lib_includes.h" +/*Maximum number of Modem init*/ +#define RPC_TRY_NUM 10 + +/*Maximum number of Modem init*/ +#define RPC_TRY_NUM 10 + +/* Uncomment to force ALOGD messages */ +// #define ALOGD ALOGI + +/*===================================================================== + External declarations +======================================================================*/ + +CLIENT* loc_api_clnt = NULL; + +/* Callback ID and pointer */ +#define LOC_API_CB_MAX_CLIENTS 16 +typedef struct +{ + uint32 cb_id; /* same as rpc/types.h */ + loc_event_cb_f_type *cb_func; /* callback func */ + loc_reset_notif_cb_f_type *rpc_cb; /* callback from RPC */ + rpc_loc_client_handle_type handle; /* stores handle for client closing */ + void* user; /* user's own data handle */ +} loc_glue_cb_entry_s_type; + +loc_glue_cb_entry_s_type loc_glue_callback_table[LOC_API_CB_MAX_CLIENTS]; + +#define RPC_FUNC_VERSION_BASE(a,b) a ## b +#define RPC_FUNC_VERSION(a,b) RPC_FUNC_VERSION_BASE(a,b) + +#define RPC_CALLBACK_FUNC_VERSION_BASE(a,v,b) a ## v ## b +#define RPC_CALLBACK_FUNC_VERSION(a,v,b) RPC_CALLBACK_FUNC_VERSION_BASE(a,v,b) + +#define LOC_GLUE_CHECK_INIT(ret_type) \ + if (loc_api_clnt == NULL) { EXIT_LOG_CALLFLOW(%d, RPC_LOC_API_RPC_FAILURE); return (ret_type) RPC_LOC_API_RPC_FAILURE; } + +#define LOC_GLUE_CHECK_RESULT(stat, ret_type) \ + if (stat != RPC_SUCCESS) { \ + LOC_LOGE("%s:%d] failure code %d", __func__, __LINE__, stat); \ + return (ret_type)((stat == RPC_SUBSYSTEM_RESTART) ? \ + RPC_LOC_API_RPC_MODEM_RESTART : RPC_LOC_API_RPC_FAILURE); \ + } + +/* Callback functions */ +/* Returns 1 if successful */ +bool_t rpc_loc_event_cb_f_type_svc( + rpc_loc_event_cb_f_type_args *argp, + rpc_loc_event_cb_f_type_rets *ret, + struct svc_req *req) +{ + // The lower word of cd_id is the index + int index = argp->cb_id & 0xFFFF; + + /* Callback not registered, or unexpected ID (shouldn't happen) */ + if (index >= LOC_API_CB_MAX_CLIENTS || loc_glue_callback_table[index].cb_func == NULL) + { + LOC_LOGE("Warning: No callback handler %d.\n", index); + ret->loc_event_cb_f_type_result = 0; + return 1; /* simply return */ + } + + LOC_LOGV("proc: %x prog: %x vers: %x\n", + (int) req->rq_proc, + (int) req->rq_prog, + (int) req->rq_vers); + + LOC_LOGV("Callback received: %x (cb_id=%p handle=%d ret_ptr=%d)\n", + (int) argp->loc_event, + argp->cb_id, + (int) argp->loc_handle, + (int) ret); + + /* Forward callback to real callback procedure */ + rpc_loc_client_handle_type loc_handle = argp->loc_handle; + rpc_loc_event_mask_type loc_event = argp->loc_event; + const rpc_loc_event_payload_u_type* loc_event_payload = + (const rpc_loc_event_payload_u_type*) argp->loc_event_payload; + + /* Gives control to synchronous call handler */ + loc_api_callback_process_sync_call(loc_handle, loc_event, loc_event_payload); + + int32 rc = (loc_glue_callback_table[index].cb_func)(loc_glue_callback_table[index].user, + loc_handle, loc_event, loc_event_payload); + + LOC_LOGV("cb_func=%p", loc_glue_callback_table[index].cb_func); + + ret->loc_event_cb_f_type_result = rc; + + return 1; /* ok */ +} + +int loc_apicbprog_freeresult (SVCXPRT *transp, xdrproc_t xdr_result, caddr_t result) +{ + xdr_free (xdr_result, result); + + /* + * Insert additional freeing code here, if needed + */ + // LOC_LOGD("***** loc_apicbprog_freeresult\n"); + + return 1; +} + +/*=========================================================================== + +FUNCTION rpc_loc_event_cb_f_type__svc (MACRO) + +DESCRIPTION + Callback function for Loc API + +RETURN VALUE + 1 for success + 0 for failure + +===========================================================================*/ +bool_t RPC_CALLBACK_FUNC_VERSION(rpc_loc_event_cb_f_type_, RPC_LOC_EVENT_CB_F_TYPE_VERSION, _svc) ( + rpc_loc_event_cb_f_type_args *argp, + rpc_loc_event_cb_f_type_rets *ret, + struct svc_req *req) +{ + return rpc_loc_event_cb_f_type_svc(argp, ret, req); +} + +/*=========================================================================== + +FUNCTION loc_apicbprog__freeresult (MACRO) + +DESCRIPTION + Free up RPC data structure + +RETURN VALUE + 1 for success + 0 for failure + +===========================================================================*/ +#define VERSION_CONCAT(MAJOR,MINOR) MAJOR##MINOR +#define loc_apicb_prog_VER_freeresult(M,N) \ +int RPC_CALLBACK_FUNC_VERSION(loc_apicbprog_, VERSION_CONCAT(M,N), _freeresult) \ +(SVCXPRT *transp, xdrproc_t xdr_result, caddr_t result) \ +{ \ + return loc_apicbprog_freeresult(transp, xdr_result, result); \ +} + +/* Define all of the possible minors */ +loc_apicb_prog_VER_freeresult(RPC_LOC_API_API_MAJOR_NUM, 0001); +loc_apicb_prog_VER_freeresult(RPC_LOC_API_API_MAJOR_NUM, 0002); +loc_apicb_prog_VER_freeresult(RPC_LOC_API_API_MAJOR_NUM, 0003); +loc_apicb_prog_VER_freeresult(RPC_LOC_API_API_MAJOR_NUM, 0004); +loc_apicb_prog_VER_freeresult(RPC_LOC_API_API_MAJOR_NUM, 0005); +loc_apicb_prog_VER_freeresult(RPC_LOC_API_API_MAJOR_NUM, 0006); + +/*=========================================================================== + +FUNCTION rpc_loc_api_cb_null__svc (MACRO) [Patch for wrong RPCGEN stubs] + +DESCRIPTION + Null callback function for Loc API + +RETURN VALUE + 1 for success + +===========================================================================*/ +#define rpc_loc_api_cb_null_VER_svc(M,N) \ +bool_t RPC_CALLBACK_FUNC_VERSION(rpc_loc_api_cb_null_, VERSION_CONCAT(M,N), _svc) ( \ + void *a, int *b, struct svc_req *req) \ +{ \ + return 1; \ +} + +/* Define all of the possible minors */ +rpc_loc_api_cb_null_VER_svc(RPC_LOC_API_API_MAJOR_NUM, 0001); +rpc_loc_api_cb_null_VER_svc(RPC_LOC_API_API_MAJOR_NUM, 0002); +rpc_loc_api_cb_null_VER_svc(RPC_LOC_API_API_MAJOR_NUM, 0003); +rpc_loc_api_cb_null_VER_svc(RPC_LOC_API_API_MAJOR_NUM, 0004); +rpc_loc_api_cb_null_VER_svc(RPC_LOC_API_API_MAJOR_NUM, 0005); +rpc_loc_api_cb_null_VER_svc(RPC_LOC_API_API_MAJOR_NUM, 0006); + +static void loc_api_glue_rpc_cb(CLIENT* client, enum rpc_reset_event event) +{ + int i; + for (i = 0; i < LOC_API_CB_MAX_CLIENTS; i++) { + if (NULL != loc_glue_callback_table[i].rpc_cb) { + loc_glue_callback_table[i].rpc_cb(loc_glue_callback_table[i].user, client, event); + } + } +} + +/*=========================================================================== + +FUNCTION loc_api_glue_init + +DESCRIPTION + Initiates the RPC client + +RETURN VALUE + 1 for success + 0 for failure + +===========================================================================*/ +int loc_api_glue_init(void) +{ + if (loc_api_clnt == NULL) + { + /* Initialize data */ + int i; + int pid = getpid(); + for (i = 0; i < LOC_API_CB_MAX_CLIENTS; i++) + { + loc_glue_callback_table[i].cb_id = i | (pid << 16); + loc_glue_callback_table[i].cb_func = NULL; + loc_glue_callback_table[i].handle = -1; + loc_glue_callback_table[i].rpc_cb = NULL; + loc_glue_callback_table[i].user = NULL; + } + + /* Print msg */ + LOC_LOGV("Trying to create RPC client...\n"); + loc_api_clnt = clnt_create(NULL, LOC_APIPROG, LOC_APIVERS, NULL); + LOC_LOGV("Created loc_api_clnt ---- %x\n", (unsigned int)loc_api_clnt); + + if (loc_api_clnt == NULL) + { + LOC_LOGE("Error: cannot create RPC client.\n"); + return 0; + } + + /* Init RPC callbacks */ + loc_api_sync_call_init(); + + int rc = loc_apicb_app_init(); + if (rc >= 0) + { + LOC_LOGD("Loc API RPC client initialized.\n"); + clnt_register_reset_notification_cb(loc_api_clnt, loc_api_glue_rpc_cb); + } + else { + LOC_LOGE("Loc API callback initialization failed.\n"); + return 0; + } + } + + return 1; +} + +rpc_loc_client_handle_type loc_open ( + rpc_loc_event_mask_type event_reg_mask, + loc_event_cb_f_type *event_callback, + loc_reset_notif_cb_f_type *rpc_cb, + void* userData +) +{ + int try_num = RPC_TRY_NUM; + ENTRY_LOG(); + LOC_GLUE_CHECK_INIT(rpc_loc_client_handle_type); + + rpc_loc_client_handle_type ret_val; + + rpc_loc_open_args args; + args.event_reg_mask = event_reg_mask; + + int i, j = LOC_API_CB_MAX_CLIENTS; + for (i = 0; i < LOC_API_CB_MAX_CLIENTS; i++) + { + if (loc_glue_callback_table[i].user == userData) + { + LOC_LOGW("Client already opened service (callback=%p)...\n", + event_callback); + break; + } else if (j == LOC_API_CB_MAX_CLIENTS && + loc_glue_callback_table[i].user == NULL) { + j = i; + } + } + + if (i == LOC_API_CB_MAX_CLIENTS) + { + i = j; + } + + if (i == LOC_API_CB_MAX_CLIENTS) + { + LOC_LOGE("Too many clients opened at once...\n"); + return RPC_LOC_CLIENT_HANDLE_INVALID; + } + + loc_glue_callback_table[i].cb_func = event_callback; + loc_glue_callback_table[i].rpc_cb = rpc_cb; + loc_glue_callback_table[i].user = userData; + + args.event_callback = loc_glue_callback_table[i].cb_id; + LOC_LOGV("cb_id=%d, func=0x%x", i, (unsigned int) event_callback); + + rpc_loc_open_rets rets; + enum clnt_stat stat = RPC_SUCCESS; + + EXIT_LOG_CALLFLOW(%s, "loc client open"); + + /*try more for rpc_loc_open_xx()*/ + + do + { + stat = RPC_FUNC_VERSION(rpc_loc_open_, RPC_LOC_OPEN_VERSION)(&args, &rets, loc_api_clnt); + ret_val = (rpc_loc_client_handle_type) rets.loc_open_result; + try_num--; + + }while( (RPC_SUCCESS != stat||0 > ret_val) && 0 != try_num ); + + LOC_GLUE_CHECK_RESULT(stat, int32); + + /* save the handle in the table */ + loc_glue_callback_table[i].handle = (rpc_loc_client_handle_type) rets.loc_open_result; + + return ret_val; + +} + +int32 loc_close +( + rpc_loc_client_handle_type handle +) +{ + ENTRY_LOG(); + LOC_GLUE_CHECK_INIT(int32); + + int32 ret_val; + + rpc_loc_close_args args; + args.handle = handle; + + rpc_loc_close_rets rets; + enum clnt_stat stat = RPC_SUCCESS; + + EXIT_LOG_CALLFLOW(%s, "loc client close"); + stat = RPC_FUNC_VERSION(rpc_loc_close_, RPC_LOC_CLOSE_VERSION)(&args, &rets, loc_api_clnt); + + loc_clear(handle); + + LOC_GLUE_CHECK_RESULT(stat, int32); + ret_val = (int32) rets.loc_close_result; + + return ret_val; +} + +void loc_clear(rpc_loc_client_handle_type handle) { + /* Clean the client's callback function in callback table */ + int i; + for (i = 0; i < LOC_API_CB_MAX_CLIENTS; i++) + { + if (loc_glue_callback_table[i].handle == handle) + { + /* Found the client */ + loc_glue_callback_table[i].cb_func = NULL; + loc_glue_callback_table[i].rpc_cb = NULL; + loc_glue_callback_table[i].handle = -1; + loc_glue_callback_table[i].user = NULL; + break; + } + } + + if (i == LOC_API_CB_MAX_CLIENTS) + { + LOC_LOGW("Handle not found (handle=%d)...\n", (int) handle); + } +} + +int32 loc_start_fix +( + rpc_loc_client_handle_type handle +) +{ + ENTRY_LOG(); + LOC_GLUE_CHECK_INIT(int32); + + int32 ret_val; + + rpc_loc_start_fix_args args; + args.handle = handle; + + rpc_loc_start_fix_rets rets; + enum clnt_stat stat = RPC_SUCCESS; + + EXIT_LOG_CALLFLOW(%s, "loc start fix"); + stat = RPC_FUNC_VERSION(rpc_loc_start_fix_, RPC_LOC_START_FIX_VERSION)(&args, &rets, loc_api_clnt); + LOC_GLUE_CHECK_RESULT(stat, int32); + + ret_val = (int32) rets.loc_start_fix_result; + + return ret_val; +} + +int32 loc_stop_fix +( + rpc_loc_client_handle_type handle +) +{ + ENTRY_LOG(); + LOC_GLUE_CHECK_INIT(int32); + + int32 ret_val; + + rpc_loc_stop_fix_args args; + args.handle = handle; + + rpc_loc_stop_fix_rets rets; + enum clnt_stat stat = RPC_SUCCESS; + + EXIT_LOG_CALLFLOW(%s, "loc stop fix"); + stat = RPC_FUNC_VERSION(rpc_loc_stop_fix_, RPC_LOC_STOP_FIX_VERSION)(&args, &rets, loc_api_clnt); + LOC_GLUE_CHECK_RESULT(stat, int32); + + ret_val = (int32) rets.loc_stop_fix_result; + + return ret_val; +} + +int32 loc_ioctl +( + rpc_loc_client_handle_type handle, + rpc_loc_ioctl_e_type ioctl_type, + rpc_loc_ioctl_data_u_type* ioctl_data +) +{ + ENTRY_LOG(); + LOC_GLUE_CHECK_INIT(int32); + + int32 ret_val; + + rpc_loc_ioctl_args args; + args.handle = handle; + args.ioctl_data = ioctl_data; + args.ioctl_type = ioctl_type; + if (ioctl_data != NULL) + { + /* Assign ioctl union discriminator */ + ioctl_data->disc = ioctl_type; + + /* In case the user hasn't filled in other disc fields, + automatically fill them in here */ + switch (ioctl_type) + { + case RPC_LOC_IOCTL_GET_API_VERSION: + break; + case RPC_LOC_IOCTL_SET_FIX_CRITERIA: + break; + case RPC_LOC_IOCTL_GET_FIX_CRITERIA: + break; + case RPC_LOC_IOCTL_INFORM_NI_USER_RESPONSE: + break; + case RPC_LOC_IOCTL_INJECT_PREDICTED_ORBITS_DATA: + break; + case RPC_LOC_IOCTL_QUERY_PREDICTED_ORBITS_DATA_VALIDITY: + break; + case RPC_LOC_IOCTL_QUERY_PREDICTED_ORBITS_DATA_SOURCE: + break; + case RPC_LOC_IOCTL_SET_PREDICTED_ORBITS_DATA_AUTO_DOWNLOAD: + break; + case RPC_LOC_IOCTL_INJECT_UTC_TIME: + break; + case RPC_LOC_IOCTL_INJECT_RTC_VALUE: + break; + case RPC_LOC_IOCTL_INJECT_POSITION: + break; + case RPC_LOC_IOCTL_QUERY_ENGINE_STATE: + break; + case RPC_LOC_IOCTL_INFORM_SERVER_OPEN_STATUS: + break; + case RPC_LOC_IOCTL_INFORM_SERVER_CLOSE_STATUS: + break; + case RPC_LOC_IOCTL_SET_ENGINE_LOCK: + break; + case RPC_LOC_IOCTL_GET_ENGINE_LOCK: + break; + case RPC_LOC_IOCTL_SET_SBAS_CONFIG: + break; + case RPC_LOC_IOCTL_GET_SBAS_CONFIG: + break; + case RPC_LOC_IOCTL_SET_NMEA_TYPES: + break; + case RPC_LOC_IOCTL_GET_NMEA_TYPES: + break; + case RPC_LOC_IOCTL_SET_CDMA_PDE_SERVER_ADDR: + case RPC_LOC_IOCTL_SET_CDMA_MPC_SERVER_ADDR: + case RPC_LOC_IOCTL_SET_UMTS_SLP_SERVER_ADDR: + case RPC_LOC_IOCTL_SET_CUSTOM_PDE_SERVER_ADDR: + args.ioctl_data->rpc_loc_ioctl_data_u_type_u.server_addr.addr_info.disc = + args.ioctl_data->rpc_loc_ioctl_data_u_type_u.server_addr.addr_type; + break; + case RPC_LOC_IOCTL_GET_CDMA_PDE_SERVER_ADDR: + case RPC_LOC_IOCTL_GET_CDMA_MPC_SERVER_ADDR: + case RPC_LOC_IOCTL_GET_UMTS_SLP_SERVER_ADDR: + case RPC_LOC_IOCTL_GET_CUSTOM_PDE_SERVER_ADDR: + break; + case RPC_LOC_IOCTL_SET_ON_DEMAND_LPM: + break; + case RPC_LOC_IOCTL_GET_ON_DEMAND_LPM: + break; + case RPC_LOC_IOCTL_DELETE_ASSIST_DATA: + break; + default: + break; + } /* switch */ + } /* ioctl_data != NULL */ + + rpc_loc_ioctl_rets rets; + enum clnt_stat stat = RPC_SUCCESS; + + EXIT_LOG_CALLFLOW(%s, loc_get_ioctl_type_name(ioctl_type)); + stat = RPC_FUNC_VERSION(rpc_loc_ioctl_, RPC_LOC_IOCTL_VERSION)(&args, &rets, loc_api_clnt); + LOC_GLUE_CHECK_RESULT(stat, int32); + + ret_val = (int32) rets.loc_ioctl_result; + + return ret_val; +} + +/* Returns 0 if error */ +int32 loc_api_null(void) +{ + LOC_GLUE_CHECK_INIT(int32); + + int32 rets; + enum clnt_stat stat = RPC_SUCCESS; + + clnt_unregister_reset_notification_cb(loc_api_clnt); + stat = RPC_FUNC_VERSION(rpc_loc_api_null_, RPC_LOC_API_NULL_VERSION)(NULL, &rets, loc_api_clnt); + LOC_GLUE_CHECK_RESULT(stat, int32); + + return (int32) rets; +} + +/*=========================================================================== + +FUNCTION loc_eng_ioctl + +DESCRIPTION + This function calls loc_ioctl and waits for the callback result before + returning back to the user. + +DEPENDENCIES + N/A + +RETURN VALUE + TRUE if successful + FALSE if failed + +SIDE EFFECTS + N/A + +===========================================================================*/ +int loc_eng_ioctl +( + rpc_loc_client_handle_type handle, + rpc_loc_ioctl_e_type ioctl_type, + rpc_loc_ioctl_data_u_type* ioctl_data_ptr, + uint32 timeout_msec, + rpc_loc_ioctl_callback_s_type *cb_data_ptr +) +{ + int ret_val = RPC_LOC_API_SUCCESS; + + ret_val = loc_api_sync_ioctl(handle, ioctl_type, ioctl_data_ptr, timeout_msec, cb_data_ptr); + + LOC_LOGD("loc_eng_ioctl result: client = %d, ioctl_type = %s, returt %s\n", + (int32) handle, + loc_get_ioctl_type_name(ioctl_type), + loc_get_ioctl_status_name(ret_val) ); + + return ret_val; +} diff --git a/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-glue/src/loc_api_sync_call.c b/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-glue/src/loc_api_sync_call.c new file mode 100644 index 000000000..ae629d7c5 --- /dev/null +++ b/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-glue/src/loc_api_sync_call.c @@ -0,0 +1,565 @@ +/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include "loc_api_sync_call.h" + +/* Logging */ +#define LOG_TAG "LocSvc_api_rpc_glue" +// #define LOG_NDDEBUG 0 +#ifndef USE_GLIB +#include +#endif /* USE_GLIB */ + +/*************************************************************************** + * DATA FOR ASYNCHRONOUS RPC PROCESSING + **************************************************************************/ +loc_sync_call_slot_array_s_type loc_sync_data; + +pthread_mutex_t loc_sync_call_mutex = PTHREAD_MUTEX_INITIALIZER; +boolean loc_sync_call_inited = 0; + +/*=========================================================================== + +FUNCTION loc_api_sync_call_init + +DESCRIPTION + Initialize this module + +DEPENDENCIES + N/A + +RETURN VALUE + none + +SIDE EFFECTS + N/A + +===========================================================================*/ +void loc_api_sync_call_init() +{ + pthread_mutex_lock(&loc_sync_call_mutex); + if (loc_sync_call_inited == 1) { + pthread_mutex_unlock(&loc_sync_call_mutex); + return; + } + loc_sync_call_inited = 1; + + loc_sync_data.num_of_slots = LOC_SYNC_CALL_SLOTS_MAX; + + int i; + for (i = 0; i < loc_sync_data.num_of_slots; i++) + { + loc_sync_call_slot_s_type *slot = &loc_sync_data.slots[i]; + + pthread_mutex_init(&slot->lock, NULL); + pthread_cond_init(&slot->loc_cb_arrived_cond, NULL); + + slot->not_available = 0; + slot->in_use = 0; + slot->loc_handle = -1; + slot->loc_cb_wait_event_mask = 0; /* event to wait */ + slot->loc_cb_received_event_mask = 0; /* received event */ + } + + pthread_mutex_unlock(&loc_sync_call_mutex); +} + +/*=========================================================================== + +FUNCTION loc_api_sync_call_destroy + +DESCRIPTION + Initialize this module + +DEPENDENCIES + N/A + +RETURN VALUE + none + +SIDE EFFECTS + N/A + +===========================================================================*/ +void loc_api_sync_call_destroy() +{ + int i; + + pthread_mutex_lock(&loc_sync_call_mutex); + if (loc_sync_call_inited == 0) { + pthread_mutex_unlock(&loc_sync_call_mutex); + return; + } + loc_sync_call_inited = 0; + + for (i = 0; i < loc_sync_data.num_of_slots; i++) + { + loc_sync_call_slot_s_type *slot = &loc_sync_data.slots[i]; + + pthread_mutex_lock(&slot->lock); + + slot->not_available = 1; + + pthread_mutex_unlock(&slot->lock); + + pthread_cond_destroy(&slot->loc_cb_arrived_cond); + pthread_mutex_destroy(&slot->lock); + } + + pthread_mutex_unlock(&loc_sync_call_mutex); +} + +/*=========================================================================== + +FUNCTION loc_match_callback + +DESCRIPTION + Checks if an awaited event has arrived + +RETURN VALUE + TRUE arrived + FALSE not matching + +===========================================================================*/ +static boolean loc_match_callback( + rpc_loc_event_mask_type wait_mask, + rpc_loc_ioctl_e_type wait_ioctl, + rpc_loc_event_mask_type event_mask, + const rpc_loc_event_payload_u_type *callback_payload +) +{ + if ((event_mask & wait_mask) == 0) return FALSE; + + if (event_mask != RPC_LOC_EVENT_IOCTL_REPORT || wait_ioctl == 0 || + ( (callback_payload != NULL) && + callback_payload->rpc_loc_event_payload_u_type_u.ioctl_report.type == wait_ioctl) ) + return TRUE; + + return FALSE; +} + +/*=========================================================================== + +FUNCTION loc_api_callback_process_sync_call + +DESCRIPTION + Wakes up blocked API calls to check if the needed callback has arrived + +DEPENDENCIES + N/A + +RETURN VALUE + none + +SIDE EFFECTS + N/A + +===========================================================================*/ +void loc_api_callback_process_sync_call( + rpc_loc_client_handle_type loc_handle, /* handle of the client */ + rpc_loc_event_mask_type loc_event, /* event mask */ + const rpc_loc_event_payload_u_type* loc_event_payload /* payload */ +) +{ + int i; + + ALOGV("loc_handle = 0x%lx, loc_event = 0x%lx", loc_handle, loc_event); + for (i = 0; i < loc_sync_data.num_of_slots; i++) + { + loc_sync_call_slot_s_type *slot = &loc_sync_data.slots[i]; + + pthread_mutex_lock(&slot->lock); + + if (slot->in_use && + slot->signal_sent == 0 && + slot->loc_handle == loc_handle && + loc_match_callback(slot->loc_cb_wait_event_mask, slot->ioctl_type, loc_event, loc_event_payload)) + { + memcpy(&slot->loc_cb_received_payload, loc_event_payload, sizeof (rpc_loc_event_payload_u_type)); + + slot->loc_cb_received_event_mask = loc_event; + + ALOGV("signal slot %d in_use %d, loc_handle 0x%lx, event_mask 0x%1x, ioctl_type %d", i, slot->in_use, slot->loc_handle, (int) slot->loc_cb_wait_event_mask, (int) slot->ioctl_type); + pthread_cond_signal(&slot->loc_cb_arrived_cond); + slot->signal_sent = 1; + + pthread_mutex_unlock(&slot->lock); + break; + } else { + /* do nothing */ + } + + pthread_mutex_unlock(&slot->lock); + } +} + +/*=========================================================================== + +FUNCTION loc_lock_a_slot + +DESCRIPTION + Allocates a buffer slot for the synchronous API call + +DEPENDENCIES + N/A + +RETURN VALUE + Select ID (>=0) : successful + -1 : buffer full + +SIDE EFFECTS + N/A + +===========================================================================*/ +static int loc_lock_a_slot() +{ + int i, select_id = -1; /* no free buffer */ + + for (i = 0; i < loc_sync_data.num_of_slots; i++) + { + loc_sync_call_slot_s_type *slot = &loc_sync_data.slots[i]; + if (pthread_mutex_trylock(&slot->lock) == EBUSY) + { + ALOGV("trylock EBUSY : %d", i); + continue; + } + + if (!slot->in_use && !slot->not_available) + { + select_id = i; + /* Return from here and leave the mutex locked. + * will unlock it in loc_unlock_slot() + */ + break; + } + /* ALOGV("slot %d in_use = %d, not_available = %d : %d", i, slot->in_use, slot->not_available, i); */ + pthread_mutex_unlock(&slot->lock); + } + + return select_id; +} + +/*=========================================================================== + +FUNCTION loc_unlock_slot + +DESCRIPTION + Unlocks a buffer slot + +DEPENDENCIES + N/A + +RETURN VALUE + None + +SIDE EFFECTS + N/A + +===========================================================================*/ +static void loc_unlock_slot(int select_id) +{ + pthread_mutex_unlock(&loc_sync_data.slots[select_id].lock); +} + +/*=========================================================================== + +FUNCTION loc_lock_slot + +DESCRIPTION + Locks a specific slot that was previously locked from loc_lock_a_slot + +DEPENDENCIES + N/A + +RETURN VALUE + None + +SIDE EFFECTS + N/A + +===========================================================================*/ +static void loc_lock_slot(int select_id) +{ + pthread_mutex_lock(&loc_sync_data.slots[select_id].lock); +} + +/*=========================================================================== + +FUNCTION loc_set_slot_in_use + +DESCRIPTION + Sets the in_use flag of slot to true or false. + Should be called only after the slot is locked + +DEPENDENCIES + N/A + +RETURN VALUE + None + +SIDE EFFECTS + N/A + +===========================================================================*/ +static void loc_set_slot_in_use(int select_id, boolean in_use) +{ + loc_sync_data.slots[select_id].in_use = in_use; + if (in_use == 1) + loc_sync_data.slots[select_id].signal_sent = 0; +} + +/*=========================================================================== + +FUNCTION loc_api_save_callback + +DESCRIPTION + Selects which callback or IOCTL event to wait for. + + The event_mask specifies the event(s). If it is RPC_LOC_EVENT_IOCTL_REPORT, + then ioctl_type specifies the IOCTL event. + + If ioctl_type is non-zero, RPC_LOC_EVENT_IOCTL_REPORT is automatically added. + +DEPENDENCIES + N/A + +RETURN VALUE + Select ID (>=0) : successful + -1 : out of buffer + +SIDE EFFECTS + N/A + +===========================================================================*/ +static void loc_api_save_callback( + int select_id, /* Selected slot */ + rpc_loc_client_handle_type loc_handle, /* Client handle */ + rpc_loc_event_mask_type event_mask, /* Event mask to wait for */ + rpc_loc_ioctl_e_type ioctl_type /* IOCTL type to wait for */ +) +{ + loc_sync_call_slot_s_type *slot = &loc_sync_data.slots[select_id]; + + slot->loc_handle = loc_handle; + + slot->loc_cb_wait_event_mask = event_mask; + slot->ioctl_type = ioctl_type; + if (ioctl_type) slot->loc_cb_wait_event_mask |= RPC_LOC_EVENT_IOCTL_REPORT; + + return; +} + +/*=========================================================================== + +FUNCTION loc_save_user_payload + +DESCRIPTION + Saves received payload into user data structures + +RETURN VALUE + None + +===========================================================================*/ +static void loc_save_user_payload( + rpc_loc_event_payload_u_type *user_cb_payload, + rpc_loc_ioctl_callback_s_type *user_ioctl_buffer, + const rpc_loc_event_payload_u_type *received_cb_payload +) +{ + if (user_cb_payload) + { + memcpy(user_cb_payload, received_cb_payload, + sizeof (rpc_loc_event_payload_u_type)); + } + if (user_ioctl_buffer) + { + memcpy(user_ioctl_buffer, + &received_cb_payload->rpc_loc_event_payload_u_type_u.ioctl_report, + sizeof *user_ioctl_buffer); + } +} + +/*=========================================================================== + +FUNCTION loc_api_wait_callback + +DESCRIPTION + Waits for a selected callback. The wait expires in timeout_seconds seconds. + + If the function is called before an existing wait has finished, it will + immediately return EBUSY. + +DEPENDENCIES + N/A + +RETURN VALUE + RPC_LOC_API_SUCCESS if successful (0) + RPC_LOC_API_TIMEOUT if timed out + RPC_LOC_API_ENGINE_BUSY if already in a wait + RPC_LOC_API_INVALID_PARAMETER if callback is not yet selected + +SIDE EFFECTS + N/A + +===========================================================================*/ +static int loc_api_wait_callback( + int select_id, /* ID from loc_select_callback() */ + int timeout_seconds, /* Timeout in this number of seconds */ + rpc_loc_event_payload_u_type *callback_payload, /* Pointer to callback payload buffer, can be NULL */ + rpc_loc_ioctl_callback_s_type *ioctl_payload /* Pointer to IOCTL payload, can be NULL */ +) +{ + int ret_val = RPC_LOC_API_SUCCESS; /* the return value of this function: 0 = no error */ + int rc = 0; /* return code from pthread calls */ + + struct timespec expire_time; + + loc_sync_call_slot_s_type *slot = &loc_sync_data.slots[select_id]; + + clock_gettime(CLOCK_REALTIME, &expire_time); + expire_time.tv_sec += timeout_seconds; + + /* Waiting */ + while (slot->signal_sent == 0 && rc != ETIMEDOUT) { + rc = pthread_cond_timedwait(&slot->loc_cb_arrived_cond, + &slot->lock, &expire_time); + } + + if (rc == ETIMEDOUT) + { + ret_val = RPC_LOC_API_TIMEOUT; /* Timed out */ + ALOGE("TIMEOUT: %d", select_id); + } + else { + /* Obtained the first awaited callback */ + ret_val = RPC_LOC_API_SUCCESS; /* Successful */ + loc_save_user_payload(callback_payload, ioctl_payload, &slot->loc_cb_received_payload); + } + + return ret_val; +} + +/*=========================================================================== + +FUNCTION loc_api_sync_ioctl + +DESCRIPTION + Synchronous IOCTL call (reentrant version) + +DEPENDENCIES + N/A + +RETURN VALUE + Loc API error code (0 = success) + +SIDE EFFECTS + N/A + +===========================================================================*/ +int loc_api_sync_ioctl +( + rpc_loc_client_handle_type handle, + rpc_loc_ioctl_e_type ioctl_type, + rpc_loc_ioctl_data_u_type* ioctl_data_ptr, + uint32 timeout_msec, + rpc_loc_ioctl_callback_s_type *cb_data_ptr +) +{ + int rc = -1; + int select_id; + rpc_loc_ioctl_callback_s_type callback_data; + + select_id = loc_lock_a_slot(); + + if (select_id < 0 || select_id >= loc_sync_data.num_of_slots) + { + ALOGE("slot not available ioctl_type = %s", + loc_get_ioctl_type_name(ioctl_type)); + return rc; + } + + loc_set_slot_in_use(select_id, 1); // set slot in use to true + + // Select the callback we are waiting for + loc_api_save_callback(select_id, handle, 0, ioctl_type); + + loc_unlock_slot(select_id); // slot is unlocked, but in_use is still true + + // we want to avoid keeping the slot locked during the loc_ioctl because the rpc + // framework will also lock a different mutex during this call, and typically + // locking two different mutexes at the same time can lead to deadlock. + rc = loc_ioctl(handle, ioctl_type, ioctl_data_ptr); + + loc_lock_slot(select_id); + + if (rc != RPC_LOC_API_SUCCESS) + { + ALOGE("loc_ioctl failed select_id = %d, ioctl_type %s, returned %s", + select_id, loc_get_ioctl_type_name(ioctl_type), loc_get_ioctl_status_name(rc)); + } + else { + ALOGV("select_id = %d, ioctl_type %d, returned RPC_LOC_API_SUCCESS", + select_id, ioctl_type); + // Wait for the callback of loc_ioctl + if ((rc = loc_api_wait_callback(select_id, timeout_msec / 1000, NULL, &callback_data)) != 0) + { + // Callback waiting failed + ALOGE("callback wait failed select_id = %d, ioctl_type %s, returned %s", + select_id, loc_get_ioctl_type_name(ioctl_type), loc_get_ioctl_status_name(rc)); + } + else + { + if (cb_data_ptr) memcpy(cb_data_ptr, &callback_data, sizeof *cb_data_ptr); + if (callback_data.status != RPC_LOC_API_SUCCESS) + { + rc = callback_data.status; + ALOGE("callback status failed select_id = %d, ioctl_type %s, returned %s", + select_id, loc_get_ioctl_type_name(ioctl_type), loc_get_ioctl_status_name(rc)); + } else { + ALOGV("callback status success select_id = %d, ioctl_type %d, returned %d", + select_id, ioctl_type, rc); + } + } /* wait callback */ + } /* loc_ioctl */ + + loc_set_slot_in_use(select_id, 0); // set slot in use to false + loc_unlock_slot(select_id); + + return rc; +} + + diff --git a/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-glue/src/loc_apicb_appinit.c b/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-glue/src/loc_apicb_appinit.c new file mode 100644 index 000000000..db5b291a9 --- /dev/null +++ b/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-glue/src/loc_apicb_appinit.c @@ -0,0 +1,86 @@ +/* Copyright (c) 2011, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "rpc/rpc.h" + +/* Include RPC headers */ +#ifdef USE_LOCAL_RPC +#include "rpc_inc/loc_api_common.h" +#include "rpc_inc/loc_api.h" +#include "rpc_inc/loc_api_cb.h" +#endif + +#ifdef USE_QCOM_AUTO_RPC +#include "loc_api_rpcgen_rpc.h" +#include "loc_api_rpcgen_common_rpc.h" +#include "loc_api_rpcgen_cb_rpc.h" +#endif + +#include "rpc_inc/loc_api_fixup.h" +#include "loc_apicb_appinit.h" + +#define RPC_FUNC_VERSION_BASE(a,b) a ## b +#define RPC_CB_FUNC_VERS(a,b) RPC_FUNC_VERSION_BASE(a,b) + +static SVCXPRT* svrPort = NULL; + +extern void RPC_CB_FUNC_VERS(loc_apicbprog_,LOC_APICBVERS_0001)(struct svc_req *rqstp, register SVCXPRT *transp); + +int loc_apicb_app_init(void) +{ + + /* Register a callback server to use the loc_apicbprog_* function */ + if (svrPort == NULL) { + svrPort = svcrtr_create(); + } + if (!svrPort) return -1; + + xprt_register(svrPort); + if(svc_register(svrPort, LOC_APICBPROG, LOC_APICBVERS_0001, RPC_CB_FUNC_VERS(loc_apicbprog_,LOC_APICBVERS_0001),0)) + { + return 0; + } + else + { + return -1; + } +} + +void loc_apicb_app_deinit(void) +{ + if (svrPort == NULL) + { + return; + } + + svc_unregister(svrPort, LOC_APICBPROG, LOC_APICBVERS_0001); + xprt_unregister(svrPort); + svc_destroy(svrPort); + svrPort = NULL; +} + diff --git a/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-stub/Android.mk b/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-stub/Android.mk new file mode 100644 index 000000000..c0987e6d3 --- /dev/null +++ b/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-stub/Android.mk @@ -0,0 +1,36 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +# functions +LOC_RPCGEN_APIS_PATH := $(TARGET_OUT_INTERMEDIATES)/loc_api/libloc_api_rpcgen_intermediates +LOC_RPCGEN_APIS_PATH_FL := ../../../../../$(TARGET_OUT_INTERMEDIATES)/loc_api/libloc_api_rpcgen_intermediates + +LOCAL_MODULE := libloc_api_rpcgen +LOCAL_MODULE_OWNER := qcom + +LOCAL_SHARED_LIBRARIES := \ + librpc \ + libcommondefs + +LOCAL_SRC_FILES += \ + src/loc_api_rpcgen_cb_xdr.c \ + src/loc_api_rpcgen_common_xdr.c \ + src/loc_api_rpcgen_cb_svc.c \ + src/loc_api_rpcgen_clnt.c \ + src/loc_api_rpcgen_xdr.c + +LOCAL_C_INCLUDES += hardware/msm7k/librpc +LOCAL_C_INCLUDES += $(LOC_RPCGEN_APIS_PATH)/../../SHARED_LIBRARIES/libcommondefs_intermediates/inc +LOCAL_C_INCLUDES += $(LOCAL_PATH)/inc +LOCAL_C_INCLUDES += $(TARGET_OUT_HEADERS)/libcommondefs/rpcgen/inc + +LOCAL_COPY_HEADERS_TO := loc_api/rpcgen/inc +LOCAL_COPY_HEADERS := inc/loc_api_rpcgen_rpc.h +LOCAL_COPY_HEADERS += inc/loc_api_rpcgen_common_rpc.h +LOCAL_COPY_HEADERS += inc/loc_api_rpcgen_cb_rpc.h +LOCAL_COPY_HEADERS += inc/loc_apicb_appinit.h + +LOCAL_LDLIBS += -lpthread +LOCAL_PRELINK_MODULE := false +include $(BUILD_STATIC_LIBRARY) diff --git a/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-stub/Makefile.am b/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-stub/Makefile.am new file mode 100644 index 000000000..4ac8c8a40 --- /dev/null +++ b/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-stub/Makefile.am @@ -0,0 +1,42 @@ +AM_CFLAGS = \ + -I../../../utils \ + -I./inc \ + $(MSM7K_CFLAGS) + +requiredlibs = \ + ../../../utils/libgps_utils_so.la \ + $(MSM7K_LIBS) + +h_sources = \ + inc/loc_api_rpcgen_rpc.h \ + inc/loc_api_rpcgen_common_rpc.h \ + inc/loc_api_rpcgen_cb_rpc.h \ + inc/loc_apicb_appinit.h + +c_sources = \ + src/loc_api_rpcgen_cb_xdr.c \ + src/loc_api_rpcgen_common_xdr.c \ + src/loc_api_rpcgen_cb_svc.c \ + src/loc_api_rpcgen_clnt.c \ + src/loc_api_rpcgen_xdr.c + + + +library_includedir = $(pkgincludedir)/libloc_api-rpc-50001/libloc_api-rpc-stub/inc +library_include_HEADERS = $(h_sources) +libloc_api_rpcgen_la_SOURCES = $(c_sources) $(h_sources) + +if USE_GLIB +libloc_api_rpcgen_la_CFLAGS = -DUSE_GLIB $(AM_CFLAGS) @GLIB_CFLAGS@ +libloc_api_rpcgen_la_LDFLAGS = -lstdc++ -lpthread @GLIB_LIBS@ -shared -version-info 1:0:0 +libloc_api_rpcgen_la_CPPFLAGS = -DUSE_GLIB $(AM_CFLAGS) $(AM_CPPFLAGS) @GLIB_CFLAGS@ +else +libloc_api_rpcgen_la_CFLAGS = $(AM_CFLAGS) +libloc_api_rpcgen_la_LDFLAGS = -lpthread -shared -version-info 1:0:0 +libloc_api_rpcgen_la_CPPFLAGS = $(AM_CFLAGS) $(AM_CPPFLAGS) +endif + +libloc_api_rpcgen_la_LIBADD = $(requiredlibs) -lstdc++ + +#Create and Install Libraries +lib_LTLIBRARIES = libloc_api_rpcgen.la diff --git a/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-stub/inc/loc_api_rpcgen_cb_rpc.h b/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-stub/inc/loc_api_rpcgen_cb_rpc.h new file mode 100644 index 000000000..87f2c377b --- /dev/null +++ b/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-stub/inc/loc_api_rpcgen_cb_rpc.h @@ -0,0 +1,156 @@ +/* Copyright (c) 2011, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/* + * Please do not edit this file. + * It was generated using rpcgen. + */ + +#ifndef _LOC_API_CB_RPC_H_RPCGEN +#define _LOC_API_CB_RPC_H_RPCGEN + +#include "librpc.h" +#include "commondefs_rpcgen_rpc.h" +#include "loc_api_rpcgen_common_rpc.h" + +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +struct rpc_loc_event_cb_f_type_args { + rpc_uint32 cb_id; + rpc_loc_client_handle_type loc_handle; + rpc_loc_event_mask_type loc_event; + rpc_loc_event_payload_u_type *loc_event_payload; +}; +typedef struct rpc_loc_event_cb_f_type_args rpc_loc_event_cb_f_type_args; + +struct rpc_loc_event_cb_f_type_rets { + rpc_int32 loc_event_cb_f_type_result; +}; +typedef struct rpc_loc_event_cb_f_type_rets rpc_loc_event_cb_f_type_rets; +#define LOC_APICBVERS 0x00050006 + +#define LOC_APICBPROG 0x3100008C +#define LOC_APICBVERS_0001 0x00050001 + +#if defined(__STDC__) || defined(__cplusplus) +#define rpc_loc_event_cb_f_type 1 +extern enum clnt_stat rpc_loc_event_cb_f_type_0x00050001(rpc_loc_event_cb_f_type_args *, rpc_loc_event_cb_f_type_rets *, CLIENT *); +extern bool_t rpc_loc_event_cb_f_type_0x00050001_svc(rpc_loc_event_cb_f_type_args *, rpc_loc_event_cb_f_type_rets *, struct svc_req *); +extern int loc_apicbprog_0x00050001_freeresult (SVCXPRT *, xdrproc_t, caddr_t); + +#else /* K&R C */ +#define rpc_loc_event_cb_f_type 1 +extern enum clnt_stat rpc_loc_event_cb_f_type_0x00050001(); +extern bool_t rpc_loc_event_cb_f_type_0x00050001_svc(); +extern int loc_apicbprog_0x00050001_freeresult (); +#endif /* K&R C */ +#define LOC_APICBVERS_0002 0x00050002 + +#if defined(__STDC__) || defined(__cplusplus) +#define rpc_loc_api_cb_null 0xffffff00 +extern enum clnt_stat rpc_loc_api_cb_null_0x00050002(void *, int *, CLIENT *); +extern bool_t rpc_loc_api_cb_null_0x00050002_svc(void *, int *, struct svc_req *); +extern int loc_apicbprog_0x00050002_freeresult (SVCXPRT *, xdrproc_t, caddr_t); + +#else /* K&R C */ +#define rpc_loc_api_cb_null 0xffffff00 +extern enum clnt_stat rpc_loc_api_cb_null_0x00050002(); +extern bool_t rpc_loc_api_cb_null_0x00050002_svc(); +extern int loc_apicbprog_0x00050002_freeresult (); +#endif /* K&R C */ +#define LOC_APICBVERS_0003 0x00050003 + +#if defined(__STDC__) || defined(__cplusplus) +extern enum clnt_stat rpc_loc_api_cb_null_0x00050003(void *, int *, CLIENT *); +extern bool_t rpc_loc_api_cb_null_0x00050003_svc(void *, int *, struct svc_req *); +extern int loc_apicbprog_0x00050003_freeresult (SVCXPRT *, xdrproc_t, caddr_t); + +#else /* K&R C */ +extern enum clnt_stat rpc_loc_api_cb_null_0x00050003(); +extern bool_t rpc_loc_api_cb_null_0x00050003_svc(); +extern int loc_apicbprog_0x00050003_freeresult (); +#endif /* K&R C */ +#define LOC_APICBVERS_0004 0x00050004 + +#if defined(__STDC__) || defined(__cplusplus) +extern enum clnt_stat rpc_loc_api_cb_null_0x00050004(void *, int *, CLIENT *); +extern bool_t rpc_loc_api_cb_null_0x00050004_svc(void *, int *, struct svc_req *); +extern int loc_apicbprog_0x00050004_freeresult (SVCXPRT *, xdrproc_t, caddr_t); + +#else /* K&R C */ +extern enum clnt_stat rpc_loc_api_cb_null_0x00050004(); +extern bool_t rpc_loc_api_cb_null_0x00050004_svc(); +extern int loc_apicbprog_0x00050004_freeresult (); +#endif /* K&R C */ +#define LOC_APICBVERS_0005 0x00050005 + +#if defined(__STDC__) || defined(__cplusplus) +extern enum clnt_stat rpc_loc_api_cb_null_0x00050005(void *, int *, CLIENT *); +extern bool_t rpc_loc_api_cb_null_0x00050005_svc(void *, int *, struct svc_req *); +extern int loc_apicbprog_0x00050005_freeresult (SVCXPRT *, xdrproc_t, caddr_t); + +#else /* K&R C */ +extern enum clnt_stat rpc_loc_api_cb_null_0x00050005(); +extern bool_t rpc_loc_api_cb_null_0x00050005_svc(); +extern int loc_apicbprog_0x00050005_freeresult (); +#endif /* K&R C */ +#define LOC_APICBVERS_0006 0x00050006 + +#if defined(__STDC__) || defined(__cplusplus) +extern enum clnt_stat rpc_loc_api_cb_null_0x00050006(void *, int *, CLIENT *); +extern bool_t rpc_loc_api_cb_null_0x00050006_svc(void *, int *, struct svc_req *); +extern int loc_apicbprog_0x00050006_freeresult (SVCXPRT *, xdrproc_t, caddr_t); + +#else /* K&R C */ +extern enum clnt_stat rpc_loc_api_cb_null_0x00050006(); +extern bool_t rpc_loc_api_cb_null_0x00050006_svc(); +extern int loc_apicbprog_0x00050006_freeresult (); +#endif /* K&R C */ + +/* the xdr functions */ + +#if defined(__STDC__) || defined(__cplusplus) +extern bool_t xdr_rpc_loc_event_cb_f_type_args (XDR *, rpc_loc_event_cb_f_type_args*); +extern bool_t xdr_rpc_loc_event_cb_f_type_rets (XDR *, rpc_loc_event_cb_f_type_rets*); + +#else /* K&R C */ +extern bool_t xdr_rpc_loc_event_cb_f_type_args (); +extern bool_t xdr_rpc_loc_event_cb_f_type_rets (); + +#endif /* K&R C */ + +#ifdef __cplusplus +} +#endif + +#endif /* !_LOC_API_CB_RPC_H_RPCGEN */ diff --git a/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-stub/inc/loc_api_rpcgen_common_rpc.h b/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-stub/inc/loc_api_rpcgen_common_rpc.h new file mode 100644 index 000000000..8107de2a9 --- /dev/null +++ b/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-stub/inc/loc_api_rpcgen_common_rpc.h @@ -0,0 +1,1261 @@ +/* Copyright (c) 2011, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/* + * Please do not edit this file. + * It was generated using rpcgen. + */ + +#ifndef _LOC_API_COMMON_RPC_H_RPCGEN +#define _LOC_API_COMMON_RPC_H_RPCGEN + +#include "librpc.h" +#include "commondefs_rpcgen_rpc.h" + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define LOC_API_TOOLVERS 0x00040030 +#define LOC_API_FEATURES 0x00000001 +#define RPC_LOC_EVENT_STATUS_REPORT 0x00000100 +#define RPC_LOC_EVENT_ASSISTANCE_DATA_REQUEST 0x00000020 +#define RPC_LOC_EVENT_WPS_NEEDED_REQUEST 0x00000200 +#define RPC_LOC_EVENT_SATELLITE_REPORT 0x00000002 +#define RPC_LOC_EVENT_PARSED_POSITION_REPORT 0x00000001 +#define RPC_LOC_EVENT_RESERVED 0x8000000000000000 +#define RPC_LOC_EVENT_LOCATION_SERVER_REQUEST 0x00000040 +#define RPC_LOC_EVENT_NMEA_POSITION_REPORT 0x00000008 +#define RPC_LOC_EVENT_IOCTL_REPORT 0x00000080 +#define RPC_LOC_EVENT_NMEA_1HZ_REPORT 0x00000004 +#define RPC_LOC_EVENT_NI_NOTIFY_VERIFY_REQUEST 0x00000010 +#define RPC_LOC_API_CB_NULL_VERSION 0x00050002 +#define RPC_LOC_EVENT_CB_F_TYPE_VERSION 0x00050001 +#define RPC_LOC_API_API_VERSIONS_VERSION 0x00050001 +#define RPC_LOC_STOP_FIX_VERSION 0x00050001 +#define RPC_LOC_START_FIX_VERSION 0x00050001 +#define RPC_LOC_IOCTL_VERSION 0x00050001 +#define RPC_LOC_CLOSE_VERSION 0x00050001 +#define RPC_LOC_API_RPC_GLUE_CODE_INFO_REMOTE_VERSION 0x00050001 +#define RPC_LOC_OPEN_VERSION 0x00050001 +#define RPC_LOC_API_NULL_VERSION 0x00050001 +#define RPC_LOC_API_API_MAJOR_NUM 0x0005 +#define RPC_LOC_APIAPI_VERSION_IS_HASHKEY 0 + +typedef rpc_int32 rpc_loc_client_handle_type; + +typedef rpc_uint64 rpc_loc_event_mask_type; + +typedef rpc_uint64 rpc_loc_position_valid_mask_type; + +typedef rpc_uint32 rpc_loc_pos_technology_mask_type; + +enum rpc_loc_session_status_e_type { + RPC_LOC_SESS_STATUS_SUCCESS = 0, + RPC_LOC_SESS_STATUS_IN_PROGESS = 1, + RPC_LOC_SESS_STATUS_GENERAL_FAILURE = 2, + RPC_LOC_SESS_STATUS_TIMEOUT = 3, + RPC_LOC_SESS_STATUS_USER_END = 4, + RPC_LOC_SESS_STATUS_BAD_PARAMETER = 5, + RPC_LOC_SESS_STATUS_PHONE_OFFLINE = 6, + RPC_LOC_SESS_STATUS_ENGINE_LOCKED = 7, + RPC_LOC_SESS_STATUS_MAX = 268435456, +}; +typedef enum rpc_loc_session_status_e_type rpc_loc_session_status_e_type; + +struct rpc_loc_calendar_time_s_type { + rpc_uint16 year; + u_char month; + u_char day_of_week; + u_char day; + u_char hour; + u_char minute; + u_char second; + rpc_uint16 millisecond; +}; +typedef struct rpc_loc_calendar_time_s_type rpc_loc_calendar_time_s_type; + +struct rpc_loc_parsed_position_s_type { + rpc_loc_position_valid_mask_type valid_mask; + rpc_loc_session_status_e_type session_status; + rpc_loc_calendar_time_s_type timestamp_calendar; + rpc_uint64 timestamp_utc; + rpc_uint8 leap_seconds; + float time_unc; + double latitude; + double longitude; + float altitude_wrt_ellipsoid; + float altitude_wrt_mean_sea_level; + float speed_horizontal; + float speed_vertical; + float heading; + float hor_unc_circular; + float hor_unc_ellipse_semi_major; + float hor_unc_ellipse_semi_minor; + float hor_unc_ellipse_orient_azimuth; + float vert_unc; + float speed_unc; + float heading_unc; + u_char confidence_horizontal; + u_char confidence_vertical; + float magnetic_deviation; + rpc_loc_pos_technology_mask_type technology_mask; +}; +typedef struct rpc_loc_parsed_position_s_type rpc_loc_parsed_position_s_type; + +enum rpc_loc_sv_system_e_type { + RPC_LOC_SV_SYSTEM_GPS = 1, + RPC_LOC_SV_SYSTEM_GALILEO = 2, + RPC_LOC_SV_SYSTEM_SBAS = 3, + RPC_LOC_SV_SYSTEM_COMPASS = 4, + RPC_LOC_SV_SYSTEM_GLONASS = 5, + RPC_LOC_SV_SYSTEM_MAX = 268435456, +}; +typedef enum rpc_loc_sv_system_e_type rpc_loc_sv_system_e_type; + +enum rpc_loc_sv_status_e_type { + RPC_LOC_SV_STATUS_IDLE = 1, + RPC_LOC_SV_STATUS_SEARCH = 2, + RPC_LOC_SV_STATUS_TRACK = 3, + RPC_LOC_SV_STATUS_MAX = 268435456, +}; +typedef enum rpc_loc_sv_status_e_type rpc_loc_sv_status_e_type; + +typedef rpc_uint32 rpc_loc_sv_info_valid_mask_type; + +struct rpc_loc_sv_info_s_type { + rpc_loc_sv_info_valid_mask_type valid_mask; + rpc_loc_sv_system_e_type system; + rpc_uint8 prn; + rpc_uint8 health_status; + rpc_loc_sv_status_e_type process_status; + rpc_boolean has_eph; + rpc_boolean has_alm; + float elevation; + float azimuth; + float snr; +}; +typedef struct rpc_loc_sv_info_s_type rpc_loc_sv_info_s_type; + +typedef rpc_uint32 rpc_loc_gnss_info_valid_mask_type; + +struct rpc_loc_gnss_info_s_type { + rpc_loc_gnss_info_valid_mask_type valid_mask; + float position_dop; + float horizontal_dop; + float vertical_dop; + rpc_boolean altitude_assumed; + rpc_uint16 sv_count; + struct { + u_int sv_list_len; + rpc_loc_sv_info_s_type *sv_list_val; + } sv_list; +}; +typedef struct rpc_loc_gnss_info_s_type rpc_loc_gnss_info_s_type; + +struct rpc_loc_nmea_report_s_type { + rpc_uint16 length; + char nmea_sentences[200]; +}; +typedef struct rpc_loc_nmea_report_s_type rpc_loc_nmea_report_s_type; + +enum rpc_loc_status_event_e_type { + RPC_LOC_STATUS_EVENT_ENGINE_STATE = 1, + RPC_LOC_STATUS_EVENT_FIX_SESSION_STATE = 2, + RPC_LOC_STATUS_EVENT_MAX = 268435456, +}; +typedef enum rpc_loc_status_event_e_type rpc_loc_status_event_e_type; + +enum rpc_loc_engine_state_e_type { + RPC_LOC_ENGINE_STATE_ON = 1, + RPC_LOC_ENGINE_STATE_OFF = 2, + RPC_LOC_ENGINE_STATE_MAX = 268435456, +}; +typedef enum rpc_loc_engine_state_e_type rpc_loc_engine_state_e_type; + +enum rpc_loc_fix_session_state_e_type { + RPC_LOC_FIX_SESSION_STATE_BEGIN = 1, + RPC_LOC_FIX_SESSION_STATE_END = 2, + RPC_LOC_FIX_SESSION_STATE_MAX = 268435456, +}; +typedef enum rpc_loc_fix_session_state_e_type rpc_loc_fix_session_state_e_type; + +struct rpc_loc_status_event_payload_u_type { + rpc_loc_status_event_e_type disc; + union { + rpc_loc_engine_state_e_type engine_state; + rpc_loc_fix_session_state_e_type fix_session_state; + } rpc_loc_status_event_payload_u_type_u; +}; +typedef struct rpc_loc_status_event_payload_u_type rpc_loc_status_event_payload_u_type; + +struct rpc_loc_status_event_s_type { + rpc_loc_status_event_e_type event; + rpc_loc_status_event_payload_u_type payload; +}; +typedef struct rpc_loc_status_event_s_type rpc_loc_status_event_s_type; + +enum rpc_loc_server_addr_e_type { + RPC_LOC_SERVER_ADDR_IPV4 = 1, + RPC_LOC_SERVER_ADDR_URL = 2, + RPC_LOC_SERVER_ADDR_IPV6 = 3, + RPC_LOC_SERVER_ADDR_MAX = 268435456, +}; +typedef enum rpc_loc_server_addr_e_type rpc_loc_server_addr_e_type; + +struct rpc_loc_server_addr_ipv4_type { + rpc_uint32 addr; + rpc_uint16 port; +}; +typedef struct rpc_loc_server_addr_ipv4_type rpc_loc_server_addr_ipv4_type; + +struct rpc_loc_server_addr_url_type { + rpc_uint16 length; + char addr[256]; +}; +typedef struct rpc_loc_server_addr_url_type rpc_loc_server_addr_url_type; + +struct rpc_loc_server_addr_ipv6_type { + rpc_uint16 addr[8]; + rpc_uint32 port; +}; +typedef struct rpc_loc_server_addr_ipv6_type rpc_loc_server_addr_ipv6_type; + +struct rpc_loc_server_addr_u_type { + rpc_loc_server_addr_e_type disc; + union { + rpc_loc_server_addr_ipv4_type ipv4; + rpc_loc_server_addr_url_type url; + rpc_loc_server_addr_ipv6_type ipv6; + } rpc_loc_server_addr_u_type_u; +}; +typedef struct rpc_loc_server_addr_u_type rpc_loc_server_addr_u_type; + +struct rpc_loc_server_info_s_type { + rpc_loc_server_addr_e_type addr_type; + rpc_loc_server_addr_u_type addr_info; +}; +typedef struct rpc_loc_server_info_s_type rpc_loc_server_info_s_type; + +enum rpc_loc_ni_notify_verify_e_type { + RPC_LOC_NI_USER_NO_NOTIFY_NO_VERIFY = 1, + RPC_LOC_NI_USER_NOTIFY_ONLY = 2, + RPC_LOC_NI_USER_NOTIFY_VERIFY_ALLOW_NO_RESP = 3, + RPC_LOC_NI_USER_NOTIFY_VERIFY_NOT_ALLOW_NO_RESP = 4, + RPC_LOC_NI_USER_PRIVACY_OVERRIDE = 5, + RPC_LOC_NI_USER_NOTIFY_VERITY_TYPE_MAX = 268435456, +}; +typedef enum rpc_loc_ni_notify_verify_e_type rpc_loc_ni_notify_verify_e_type; + +enum rpc_loc_ni_event_e_type { + RPC_LOC_NI_EVENT_VX_NOTIFY_VERIFY_REQ = 1, + RPC_LOC_NI_EVENT_SUPL_NOTIFY_VERIFY_REQ = 2, + RPC_LOC_NI_EVENT_UMTS_CP_NOTIFY_VERIFY_REQ = 3, + RPC_LOC_NI_EVENT_VX_SERVICE_INTERACTION_REQ = 4, + RPC_LOC_NI_EVENT_MAX = 268435456, +}; +typedef enum rpc_loc_ni_event_e_type rpc_loc_ni_event_e_type; + +enum rpc_loc_ni_datacoding_scheme_e_type { + RPC_LOC_NI_PRESUPL_ISO646IRV = 0, + RPC_LOC_NI_PRESUPL_ISO8859 = 1, + RPC_LOC_NI_PRESUPL_UTF8 = 2, + RPC_LOC_NI_PRESUPL_UTF16 = 3, + RPC_LOC_NI_PRESUPL_UCS2 = 4, + RPC_LOC_NI_PRESUPL_GSM_DEFAULT = 5, + RPC_LOC_NI_PRESUPL_SHIFT_JIS = 6, + RPC_LOC_NI_PRESUPL_JIS = 7, + RPC_LOC_NI_PRESUPL_EUC = 8, + RPC_LOC_NI_PRESUPL_GB2312 = 9, + RPC_LOC_NI_PRESUPL_CNS11643 = 10, + RPC_LOC_NI_PRESUPL_KSC1001 = 11, + RPC_LOC_NI_PRESUPL_ENCODING_UNKNOWN = 2147483647, + RPC_LOC_NI_SS_GERMAN = 12, + RPC_LOC_NI_SS_ENGLISH = 13, + RPC_LOC_NI_SS_ITALIAN = 14, + RPC_LOC_NI_SS_FRENCH = 15, + RPC_LOC_NI_SS_SPANISH = 16, + RPC_LOC_NI_SS_DUTCH = 17, + RPC_LOC_NI_SS_SWEDISH = 18, + RPC_LOC_NI_SS_DANISH = 19, + RPC_LOC_NI_SS_PORTUGUESE = 20, + RPC_LOC_NI_SS_FINNISH = 21, + RPC_LOC_NI_SS_NORWEGIAN = 22, + RPC_LOC_NI_SS_GREEK = 23, + RPC_LOC_NI_SS_TURKISH = 24, + RPC_LOC_NI_SS_HUNGARIAN = 25, + RPC_LOC_NI_SS_POLISH = 26, + RPC_LOC_NI_SS_LANGUAGE_UNSPEC = 27, + RPC_LOC_NI_SUPL_UTF8 = 28, + RPC_LOC_NI_SUPL_UCS2 = 29, + RPC_LOC_NI_SUPL_GSM_DEFAULT = 30, + RPC_LOC_NI_SUPL_ENCODING_UNKNOWN = 2147483647, +}; +typedef enum rpc_loc_ni_datacoding_scheme_e_type rpc_loc_ni_datacoding_scheme_e_type; + +enum rpc_loc_ni_vx_requester_id_encoding_scheme_e_type { + RPC_LOC_NI_VX_OCTET = 0, + RPC_LOC_NI_VX_EXN_PROTOCOL_MSG = 1, + RPC_LOC_NI_VX_ASCII = 2, + RPC_LOC_NI_VX_IA5 = 3, + RPC_LOC_NI_VX_UNICODE = 4, + RPC_LOC_NI_VX_SHIFT_JIS = 5, + RPC_LOC_NI_VX_KOREAN = 6, + RPC_LOC_NI_VX_LATIN_HEBREW = 7, + RPC_LOC_NI_VX_LATIN = 8, + RPC_LOC_NI_VX_GSM = 9, + RPC_LOC_NI_VX_ENCODING_TYPE_MAX = 268435456, +}; +typedef enum rpc_loc_ni_vx_requester_id_encoding_scheme_e_type rpc_loc_ni_vx_requester_id_encoding_scheme_e_type; + +enum rpc_loc_ni_vx_pos_mode_e_type { + RPC_LOC_VX_MS_ASSISTED_ONLY = 1, + RPC_LOC_VX_MS_BASED_ONLY = 2, + RPC_LOC_VX_MS_ASSISTED_PREF_MSBASED_ALLWD = 3, + RPC_LOC_VX_MS_BASED_PREF_ASSISTED_ALLWD = 4, + RPC_LOC_VX_POS_MODE_MAX = 268435456, +}; +typedef enum rpc_loc_ni_vx_pos_mode_e_type rpc_loc_ni_vx_pos_mode_e_type; + +struct rpc_loc_ni_vx_requester_id_s_type { + u_char requester_id_length; + char requester_id[200]; +}; +typedef struct rpc_loc_ni_vx_requester_id_s_type rpc_loc_ni_vx_requester_id_s_type; + +struct rpc_loc_ni_vx_notify_verify_req_s_type { + rpc_loc_ni_notify_verify_e_type notification_priv_type; + u_char pos_qos_incl; + u_char pos_qos; + rpc_uint32 num_fixes; + rpc_uint32 tbf; + rpc_loc_ni_vx_pos_mode_e_type pos_mode; + rpc_loc_ni_vx_requester_id_encoding_scheme_e_type encoding_scheme; + rpc_loc_ni_vx_requester_id_s_type requester_id; + rpc_uint16 user_resp_timer_val; +}; +typedef struct rpc_loc_ni_vx_notify_verify_req_s_type rpc_loc_ni_vx_notify_verify_req_s_type; + +enum rpc_loc_ni_supl_pos_method_e_type { + RPC_LOC_NI_POSMETHOD_AGPS_SETASSISTED = 1, + RPC_LOC_NI_POSMETHOD_AGPS_SETBASED = 2, + RPC_LOC_NI_POSMETHOD_AGPS_SETASSISTED_PREF = 3, + RPC_LOC_NI_POSMETHOD_AGPS_SETBASED_PREF = 4, + RPC_LOC_NI_POSMETHOD_AUTONOMOUS_GPS = 5, + RPC_LOC_NI_POSMETHOD_AFLT = 6, + RPC_LOC_NI_POSMETHOD_ECID = 7, + RPC_LOC_NI_POSMETHOD_EOTD = 8, + RPC_LOC_NI_POSMETHOD_OTDOA = 9, + RPC_LOC_NI_POSMETHOD_NO_POSITION = 10, + RPC_LOC_NI_POSMETHOD_MAX = 268435456, +}; +typedef enum rpc_loc_ni_supl_pos_method_e_type rpc_loc_ni_supl_pos_method_e_type; + +struct rpc_loc_ni_supl_slp_session_id_s_type { + u_char presence; + char session_id[4]; + rpc_loc_server_info_s_type slp_address; +}; +typedef struct rpc_loc_ni_supl_slp_session_id_s_type rpc_loc_ni_supl_slp_session_id_s_type; + +struct rpc_loc_ni_requestor_id_s_type { + u_char data_coding_scheme; + char requestor_id_string[200]; + u_char string_len; +}; +typedef struct rpc_loc_ni_requestor_id_s_type rpc_loc_ni_requestor_id_s_type; + +struct rpc_loc_ni_supl_client_name_s_type { + u_char data_coding_scheme; + char client_name_string[64]; + u_char string_len; +}; +typedef struct rpc_loc_ni_supl_client_name_s_type rpc_loc_ni_supl_client_name_s_type; + +struct rpc_loc_ni_supl_qop_s_type { + u_char bit_mask; + u_char horacc; + u_char veracc; + rpc_uint16 maxLocAge; + u_char delay; +}; +typedef struct rpc_loc_ni_supl_qop_s_type rpc_loc_ni_supl_qop_s_type; + +struct rpc_loc_ni_supl_notify_verify_req_s_type { + rpc_loc_ni_notify_verify_e_type notification_priv_type; + rpc_uint16 flags; + rpc_loc_ni_supl_slp_session_id_s_type supl_slp_session_id; + char supl_hash[8]; + rpc_loc_ni_datacoding_scheme_e_type datacoding_scheme; + rpc_loc_ni_supl_pos_method_e_type pos_method; + rpc_loc_ni_requestor_id_s_type requestor_id; + rpc_loc_ni_supl_client_name_s_type client_name; + rpc_loc_ni_supl_qop_s_type supl_qop; + rpc_uint16 user_response_timer; +}; +typedef struct rpc_loc_ni_supl_notify_verify_req_s_type rpc_loc_ni_supl_notify_verify_req_s_type; + +struct rpc_loc_ni_ext_client_address_s_type { + u_char ext_client_address_len; + char ext_client_address[20]; +}; +typedef struct rpc_loc_ni_ext_client_address_s_type rpc_loc_ni_ext_client_address_s_type; + +enum rpc_loc_ni_location_type_e_type { + RPC_LOC_NI_LOCATIONTYPE_CURRENT_LOCATION = 1, + RPC_LOC_NI_LOCATIONTYPE_CURRENT_OR_LAST_KNOWN_LOCATION = 2, + RPC_LOC_NI_LOCATIONTYPE_INITIAL_LOCATION = 3, + RPC_LOC_NI_LOCATIONTYPE_MAX = 268435456, +}; +typedef enum rpc_loc_ni_location_type_e_type rpc_loc_ni_location_type_e_type; + +struct rpc_loc_ni_deferred_location_s_type { + u_char unused_bits; + u_char ms_available; +}; +typedef struct rpc_loc_ni_deferred_location_s_type rpc_loc_ni_deferred_location_s_type; + +struct rpc_loc_ni_codeword_string_s_type { + u_char data_coding_scheme; + char lcs_codeword_string[20]; + u_char string_len; +}; +typedef struct rpc_loc_ni_codeword_string_s_type rpc_loc_ni_codeword_string_s_type; + +struct rpc_loc_ni_service_type_id_s_type { + u_char lcs_service_type_id; +}; +typedef struct rpc_loc_ni_service_type_id_s_type rpc_loc_ni_service_type_id_s_type; + +struct rpc_loc_ni_umts_cp_notify_verify_req_s_type { + rpc_loc_ni_notify_verify_e_type notification_priv_type; + u_char invoke_id; + rpc_uint16 flags; + u_char notification_length; + char notification_text[64]; + rpc_loc_ni_datacoding_scheme_e_type datacoding_scheme; + rpc_loc_ni_ext_client_address_s_type ext_client_address_data; + rpc_loc_ni_location_type_e_type location_type; + rpc_loc_ni_deferred_location_s_type deferred_location; + rpc_loc_ni_requestor_id_s_type requestor_id; + rpc_loc_ni_codeword_string_s_type codeword_string; + rpc_loc_ni_service_type_id_s_type service_type_id; + rpc_uint16 user_response_timer; +}; +typedef struct rpc_loc_ni_umts_cp_notify_verify_req_s_type rpc_loc_ni_umts_cp_notify_verify_req_s_type; + +enum rpc_loc_ni_service_interaction_e_type { + RPC_LOC_NI_SERVICE_INTERACTION_ONGOING_NI_INCOMING_MO = 1, + RPC_LOC_NI_SERVICE_INTERACTION_MAX = 268435456, +}; +typedef enum rpc_loc_ni_service_interaction_e_type rpc_loc_ni_service_interaction_e_type; + +struct rpc_loc_ni_vx_service_interaction_req_s_type { + rpc_loc_ni_vx_notify_verify_req_s_type ni_vx_req; + rpc_loc_ni_service_interaction_e_type service_interation_type; +}; +typedef struct rpc_loc_ni_vx_service_interaction_req_s_type rpc_loc_ni_vx_service_interaction_req_s_type; + +struct rpc_loc_ni_event_payload_u_type { + rpc_loc_ni_event_e_type disc; + union { + rpc_loc_ni_vx_notify_verify_req_s_type vx_req; + rpc_loc_ni_supl_notify_verify_req_s_type supl_req; + rpc_loc_ni_umts_cp_notify_verify_req_s_type umts_cp_req; + rpc_loc_ni_vx_service_interaction_req_s_type service_interaction_req; + } rpc_loc_ni_event_payload_u_type_u; +}; +typedef struct rpc_loc_ni_event_payload_u_type rpc_loc_ni_event_payload_u_type; + +struct rpc_loc_ni_event_s_type { + rpc_loc_ni_event_e_type event; + rpc_loc_ni_event_payload_u_type payload; +}; +typedef struct rpc_loc_ni_event_s_type rpc_loc_ni_event_s_type; + +enum rpc_loc_assist_data_request_e_type { + RPC_LOC_ASSIST_DATA_TIME_REQ = 1, + RPC_LOC_ASSIST_DATA_PREDICTED_ORBITS_REQ = 2, + RPC_LOC_ASSIST_DATA_POSITION_INJECTION_REQ = 3, + RPC_LOC_ASSIST_DATA_MAX = 268435456, +}; +typedef enum rpc_loc_assist_data_request_e_type rpc_loc_assist_data_request_e_type; + +typedef char *rpc_struct_loc_time_download_source_s_type_servers_ptr; + +typedef rpc_struct_loc_time_download_source_s_type_servers_ptr rpc_struct_loc_time_download_source_s_type_servers[3]; + +struct rpc_loc_time_download_source_s_type { + rpc_uint32 delay_threshold; + rpc_struct_loc_time_download_source_s_type_servers servers; +}; +typedef struct rpc_loc_time_download_source_s_type rpc_loc_time_download_source_s_type; + +typedef char *rpc_struct_loc_predicted_orbits_data_source_s_type_servers_ptr; + +typedef rpc_struct_loc_predicted_orbits_data_source_s_type_servers_ptr rpc_struct_loc_predicted_orbits_data_source_s_type_servers[3]; + +struct rpc_loc_predicted_orbits_data_source_s_type { + rpc_uint32 max_file_size; + rpc_uint32 max_part_size; + rpc_struct_loc_predicted_orbits_data_source_s_type_servers servers; +}; +typedef struct rpc_loc_predicted_orbits_data_source_s_type rpc_loc_predicted_orbits_data_source_s_type; + +struct rpc_loc_pos_inj_request_s_type { + rpc_uint32 flags; + double latitude; + double longitude; + rpc_uint32 position_uncertainty; + rpc_uint64 timestamp; +}; +typedef struct rpc_loc_pos_inj_request_s_type rpc_loc_pos_inj_request_s_type; + +struct rpc_loc_assist_data_request_payload_u_type { + rpc_loc_assist_data_request_e_type disc; + union { + rpc_loc_time_download_source_s_type time_download; + rpc_loc_predicted_orbits_data_source_s_type data_download; + rpc_loc_pos_inj_request_s_type pos_injection; + } rpc_loc_assist_data_request_payload_u_type_u; +}; +typedef struct rpc_loc_assist_data_request_payload_u_type rpc_loc_assist_data_request_payload_u_type; + +struct rpc_loc_assist_data_request_s_type { + rpc_loc_assist_data_request_e_type event; + rpc_loc_assist_data_request_payload_u_type payload; +}; +typedef struct rpc_loc_assist_data_request_s_type rpc_loc_assist_data_request_s_type; + +typedef rpc_uint32 rpc_loc_server_connection_handle; + +enum rpc_loc_server_protocol_e_type { + RPC_LOC_SERVER_PROTOCOL_DEFAULT = 0, + RPC_LOC_SERVER_PROTOCOL_SUPL = 1, + RPC_LOC_SERVER_PROTOCOL_VX_MPC = 2, + RPC_LOC_SERVER_PROTOCOL_VX_PDE = 3, + RPC_LOC_SERVER_PROTOCOL_MAX = 16777216, +}; +typedef enum rpc_loc_server_protocol_e_type rpc_loc_server_protocol_e_type; + +enum rpc_loc_server_connection_e_type { + RPC_LOC_SERVER_CONNECTION_LBS = 0, + RPC_LOC_SERVER_CONNECTION_WWAN_INTERNET = 0 + 1, + RPC_LOC_SERVER_CONNECTION_MAX = 16777216, +}; +typedef enum rpc_loc_server_connection_e_type rpc_loc_server_connection_e_type; + +enum rpc_loc_server_request_e_type { + RPC_LOC_SERVER_REQUEST_OPEN = 1, + RPC_LOC_SERVER_REQUEST_CLOSE = 2, + RPC_LOC_SERVER_REQUEST_MULTI_OPEN = 3, + RPC_LOC_SERVER_REQUEST_MAX = 268435456, +}; +typedef enum rpc_loc_server_request_e_type rpc_loc_server_request_e_type; + +struct rpc_loc_server_open_req_s_type { + rpc_loc_server_connection_handle conn_handle; + rpc_loc_server_protocol_e_type protocol; +}; +typedef struct rpc_loc_server_open_req_s_type rpc_loc_server_open_req_s_type; + +struct rpc_loc_server_multi_open_req_s_type { + rpc_loc_server_connection_handle conn_handle; + rpc_loc_server_protocol_e_type protocol; + rpc_loc_server_connection_e_type connection_type; +}; +typedef struct rpc_loc_server_multi_open_req_s_type rpc_loc_server_multi_open_req_s_type; + +struct rpc_loc_server_close_req_s_type { + rpc_loc_server_connection_handle conn_handle; +}; +typedef struct rpc_loc_server_close_req_s_type rpc_loc_server_close_req_s_type; + +struct rpc_loc_server_request_u_type { + rpc_loc_server_request_e_type disc; + union { + rpc_loc_server_open_req_s_type open_req; + rpc_loc_server_close_req_s_type close_req; + rpc_loc_server_multi_open_req_s_type multi_open_req; + } rpc_loc_server_request_u_type_u; +}; +typedef struct rpc_loc_server_request_u_type rpc_loc_server_request_u_type; + +struct rpc_loc_server_request_s_type { + rpc_loc_server_request_e_type event; + rpc_loc_server_request_u_type payload; +}; +typedef struct rpc_loc_server_request_s_type rpc_loc_server_request_s_type; + +enum rpc_loc_qwip_request_e_type { + RPC_LOC_QWIP_START_PERIODIC_HI_FREQ_FIXES = 0, + RPC_LOC_QWIP_START_PERIODIC_KEEP_WARM = 0 + 1, + RPC_LOC_QWIP_STOP_PERIODIC_FIXES = 0 + 2, + RPC_LOC_QWIP_SUSPEND = 0 + 3, + RPC_LOC_QWIP_REQUEST_MAX = 268435456, +}; +typedef enum rpc_loc_qwip_request_e_type rpc_loc_qwip_request_e_type; + +struct rpc_loc_qwip_request_s_type { + rpc_loc_qwip_request_e_type request_type; + rpc_uint16 tbf_ms; +}; +typedef struct rpc_loc_qwip_request_s_type rpc_loc_qwip_request_s_type; + +struct rpc_loc_reserved_payload_s_type { + rpc_uint16 data_size; + struct { + u_int data_len; + char *data_val; + } data; +}; +typedef struct rpc_loc_reserved_payload_s_type rpc_loc_reserved_payload_s_type; + +enum rpc_loc_ioctl_e_type { + RPC_LOC_IOCTL_GET_API_VERSION = 1, + RPC_LOC_IOCTL_SET_FIX_CRITERIA = 2, + RPC_LOC_IOCTL_GET_FIX_CRITERIA = 3, + RPC_LOC_IOCTL_SERVICE_START_INDEX = 400, + RPC_LOC_IOCTL_INFORM_NI_USER_RESPONSE = 400, + RPC_LOC_IOCTL_INJECT_PREDICTED_ORBITS_DATA = 401, + RPC_LOC_IOCTL_QUERY_PREDICTED_ORBITS_DATA_VALIDITY = 402, + RPC_LOC_IOCTL_QUERY_PREDICTED_ORBITS_DATA_SOURCE = 403, + RPC_LOC_IOCTL_SET_PREDICTED_ORBITS_DATA_AUTO_DOWNLOAD = 404, + RPC_LOC_IOCTL_INJECT_UTC_TIME = 405, + RPC_LOC_IOCTL_INJECT_RTC_VALUE = 406, + RPC_LOC_IOCTL_INJECT_POSITION = 407, + RPC_LOC_IOCTL_QUERY_ENGINE_STATE = 408, + RPC_LOC_IOCTL_INFORM_SERVER_OPEN_STATUS = 409, + RPC_LOC_IOCTL_INFORM_SERVER_CLOSE_STATUS = 410, + RPC_LOC_IOCTL_SEND_WIPER_POSITION_REPORT = 411, + RPC_LOC_IOCTL_NOTIFY_WIPER_STATUS = 412, + RPC_LOC_IOCTL_ACCESS_EFS_DATA = 413, + RPC_LOC_IOCTL_ERROR_ESTIMATE_CONFIG = 414, + RPC_LOC_IOCTL_INFORM_SERVER_MULTI_OPEN_STATUS = 415, + RPC_LOC_IOCTL_NV_SETTINGS_START_INDEX = 800, + RPC_LOC_IOCTL_SET_ENGINE_LOCK = 800, + RPC_LOC_IOCTL_GET_ENGINE_LOCK = 801, + RPC_LOC_IOCTL_SET_SBAS_CONFIG = 802, + RPC_LOC_IOCTL_GET_SBAS_CONFIG = 803, + RPC_LOC_IOCTL_SET_NMEA_TYPES = 804, + RPC_LOC_IOCTL_GET_NMEA_TYPES = 805, + RPC_LOC_IOCTL_SET_CDMA_PDE_SERVER_ADDR = 806, + RPC_LOC_IOCTL_GET_CDMA_PDE_SERVER_ADDR = 807, + RPC_LOC_IOCTL_SET_CDMA_MPC_SERVER_ADDR = 808, + RPC_LOC_IOCTL_GET_CDMA_MPC_SERVER_ADDR = 809, + RPC_LOC_IOCTL_SET_UMTS_SLP_SERVER_ADDR = 810, + RPC_LOC_IOCTL_GET_UMTS_SLP_SERVER_ADDR = 811, + RPC_LOC_IOCTL_SET_ON_DEMAND_LPM = 812, + RPC_LOC_IOCTL_GET_ON_DEMAND_LPM = 813, + RPC_LOC_IOCTL_SET_XTRA_T_SESSION_CONTROL = 814, + RPC_LOC_IOCTL_GET_XTRA_T_SESSION_CONTROL = 815, + RPC_LOC_IOCTL_SET_LBS_APN_PROFILE = 816, + RPC_LOC_IOCTL_GET_LBS_APN_PROFILE = 817, + RPC_LOC_IOCTL_SET_XTRA_APN_PROFILE = 818, + RPC_LOC_IOCTL_GET_XTRA_APN_PROFILE = 819, + RPC_LOC_IOCTL_SET_DATA_ENABLE = 820, + RPC_LOC_IOCTL_SET_SUPL_VERSION = 821, + RPC_LOC_IOCTL_GET_SUPL_VERSION = 822, + RPC_LOC_IOCTL_PROPRIETARY_START_INDEX = 1000, + RPC_LOC_IOCTL_DELETE_ASSIST_DATA = 1000, + RPC_LOC_IOCTL_SET_CUSTOM_PDE_SERVER_ADDR = 1001, + RPC_LOC_IOCTL_GET_CUSTOM_PDE_SERVER_ADDR = 1002, + RPC_LOC_IOCTL_RESERVED_CMD = 8000, + RPC_LOC_IOCTL_THIRD_PARTY_START_INDEX = 1073741824, +}; +typedef enum rpc_loc_ioctl_e_type rpc_loc_ioctl_e_type; + +struct rpc_loc_api_version_s_type { + u_char major; + u_char minor; +}; +typedef struct rpc_loc_api_version_s_type rpc_loc_api_version_s_type; + +enum rpc_loc_fix_recurrence_e_type { + RPC_LOC_PERIODIC_FIX = 1, + RPC_LOC_SINGLE_FIX = 2, + RPC_LOC_FIX_SESSION_TYPE_MAX = 268435456, +}; +typedef enum rpc_loc_fix_recurrence_e_type rpc_loc_fix_recurrence_e_type; + +enum rpc_loc_operation_mode_e_type { + RPC_LOC_OPER_MODE_DEFAULT = 1, + RPC_LOC_OPER_MODE_MSB = 2, + RPC_LOC_OPER_MODE_MSA = 3, + RPC_LOC_OPER_MODE_STANDALONE = 4, + RPC_LOC_OPER_MODE_SPEED_OPTIMAL = 5, + RPC_LOC_OPER_MODE_ACCURACY_OPTIMAL = 6, + RPC_LOC_OPER_MODE_DATA_OPTIMAL = 7, + RPC_LOC_OPER_MODE_CELL_ID = 8, + RPC_LOC_OPER_MODE_MAX = 268435456, +}; +typedef enum rpc_loc_operation_mode_e_type rpc_loc_operation_mode_e_type; + +enum rpc_loc_notify_e_type { + RPC_LOC_NOTIFY_ON_INTERVAL = 1, + RPC_LOC_NOTIFY_ON_DISTANCE = 2, + RPC_LOC_NOTIFY_ON_ANY = 3, + RPC_LOC_NOTIFY_ON_ALL = 4, + RPC_LOC_NOTIFY_TYPE_MAX = 268435456, +}; +typedef enum rpc_loc_notify_e_type rpc_loc_notify_e_type; + +struct rpc_loc_fix_criteria_s_type { + rpc_uint32 valid_mask; + rpc_loc_fix_recurrence_e_type recurrence_type; + rpc_loc_operation_mode_e_type preferred_operation_mode; + rpc_uint32 preferred_accuracy; + rpc_uint32 preferred_response_time; + rpc_boolean intermediate_pos_report_enabled; + rpc_loc_notify_e_type notify_type; + rpc_uint32 min_interval; + float min_distance; + rpc_uint32 min_dist_sample_interval; +}; +typedef struct rpc_loc_fix_criteria_s_type rpc_loc_fix_criteria_s_type; + +enum rpc_loc_ni_user_resp_e_type { + RPC_LOC_NI_LCS_NOTIFY_VERIFY_ACCEPT = 1, + RPC_LOC_NI_LCS_NOTIFY_VERIFY_DENY = 2, + RPC_LOC_NI_LCS_NOTIFY_VERIFY_NORESP = 3, + RPC_LOC_NI_LCS_NOTIFY_VERIFY_MAX = 268435456, +}; +typedef enum rpc_loc_ni_user_resp_e_type rpc_loc_ni_user_resp_e_type; + +struct rpc_loc_user_verify_s_type { + rpc_loc_ni_user_resp_e_type user_resp; + rpc_loc_ni_event_s_type ni_event_pass_back; +}; +typedef struct rpc_loc_user_verify_s_type rpc_loc_user_verify_s_type; + +enum rpc_loc_predicted_orbits_data_format_e_type { + RPC_LOC_PREDICTED_ORBITS_XTRA = 0, + RPC_LOC_PREDICTED_ORBITS_FORMAT_MAX = 268435456, +}; +typedef enum rpc_loc_predicted_orbits_data_format_e_type rpc_loc_predicted_orbits_data_format_e_type; + +struct rpc_loc_predicted_orbits_data_s_type { + rpc_loc_predicted_orbits_data_format_e_type format_type; + rpc_uint32 total_size; + rpc_uint8 total_parts; + rpc_uint8 part; + rpc_uint16 part_len; + struct { + u_int data_ptr_len; + char *data_ptr_val; + } data_ptr; +}; +typedef struct rpc_loc_predicted_orbits_data_s_type rpc_loc_predicted_orbits_data_s_type; + +struct rpc_loc_predicted_orbits_data_validity_report_s_type { + rpc_uint64 start_time_utc; + rpc_uint16 valid_duration_hrs; +}; +typedef struct rpc_loc_predicted_orbits_data_validity_report_s_type rpc_loc_predicted_orbits_data_validity_report_s_type; + +struct rpc_loc_predicted_orbits_auto_download_config_s_type { + rpc_boolean enable; + u_char auto_check_every_hrs; +}; +typedef struct rpc_loc_predicted_orbits_auto_download_config_s_type rpc_loc_predicted_orbits_auto_download_config_s_type; + +struct rpc_loc_assist_data_time_s_type { + rpc_uint64 time_utc; + rpc_uint32 uncertainty; +}; +typedef struct rpc_loc_assist_data_time_s_type rpc_loc_assist_data_time_s_type; + +typedef rpc_uint64 rpc_loc_assist_pos_valid_mask_type; + +struct rpc_loc_assist_data_pos_s_type { + rpc_loc_assist_pos_valid_mask_type valid_mask; + rpc_uint64 timestamp_utc; + double latitude; + double longitude; + float altitude_wrt_ellipsoid; + float altitude_wrt_mean_sea_level; + float hor_unc_circular; + float vert_unc; + u_char confidence_horizontal; + u_char confidence_vertical; + rpc_int32 timestamp_age; +}; +typedef struct rpc_loc_assist_data_pos_s_type rpc_loc_assist_data_pos_s_type; + +enum rpc_loc_server_open_status_e_type { + RPC_LOC_SERVER_OPEN_SUCCESS = 1, + RPC_LOC_SERVER_OPEN_FAIL = 2, + RPC_LOC_SERVER_OPEN_STATUS_MAX = 268435456, +}; +typedef enum rpc_loc_server_open_status_e_type rpc_loc_server_open_status_e_type; + +enum rpc_loc_server_pdp_type_e_type { + RPC_LOC_SERVER_PDP_IP = 0, + RPC_LOC_SERVER_PDP_PPP = 0 + 1, + RPC_LOC_SERVER_PDP_IPV6 = 0 + 2, + RPC_LOC_SERVER_PDP_IPV4V6 = 0 + 3, + RPC_LOC_SERVER_PDP_MAX = 268435456, +}; +typedef enum rpc_loc_server_pdp_type_e_type rpc_loc_server_pdp_type_e_type; + +struct rpc_loc_server_open_status_s_type { + rpc_loc_server_connection_handle conn_handle; + rpc_loc_server_open_status_e_type open_status; + char apn_name[100]; +}; +typedef struct rpc_loc_server_open_status_s_type rpc_loc_server_open_status_s_type; + +struct rpc_loc_server_multi_open_status_s_type { + rpc_loc_server_connection_handle conn_handle; + rpc_loc_server_open_status_e_type open_status; + rpc_loc_server_pdp_type_e_type pdp_type; + char apn_name[100]; +}; +typedef struct rpc_loc_server_multi_open_status_s_type rpc_loc_server_multi_open_status_s_type; + +enum rpc_loc_server_close_status_e_type { + RPC_LOC_SERVER_CLOSE_SUCCESS = 1, + RPC_LOC_SERVER_CLOSE_FAIL = 2, + RPC_LOC_SERVER_CLOSE_STATUS_MAX = 268435456, +}; +typedef enum rpc_loc_server_close_status_e_type rpc_loc_server_close_status_e_type; + +struct rpc_loc_server_close_status_s_type { + rpc_loc_server_connection_handle conn_handle; + rpc_loc_server_close_status_e_type close_status; +}; +typedef struct rpc_loc_server_close_status_s_type rpc_loc_server_close_status_s_type; + +struct rpc_loc_wiper_fix_time_s_type { + rpc_uint32 slow_clock_count; +}; +typedef struct rpc_loc_wiper_fix_time_s_type rpc_loc_wiper_fix_time_s_type; + +struct rpc_loc_wiper_fix_pos_s_type { + rpc_int32 lat; + rpc_int32 lon; + rpc_uint16 HEPE; + rpc_uint8 num_of_aps_used; + rpc_uint8 fix_error_code; +}; +typedef struct rpc_loc_wiper_fix_pos_s_type rpc_loc_wiper_fix_pos_s_type; + +struct rpc_loc_wiper_ap_info_s_type { + char mac_addr[6]; + rpc_int32 rssi; + rpc_uint16 channel; + rpc_uint8 ap_qualifier; +}; +typedef struct rpc_loc_wiper_ap_info_s_type rpc_loc_wiper_ap_info_s_type; + +struct rpc_loc_wiper_ap_set_s_type { + rpc_uint8 num_of_aps; + rpc_loc_wiper_ap_info_s_type ap_info[50]; +}; +typedef struct rpc_loc_wiper_ap_set_s_type rpc_loc_wiper_ap_set_s_type; + +struct rpc_loc_wiper_position_report_s_type { + rpc_uint8 wiper_valid_info_flag; + rpc_loc_wiper_fix_time_s_type wiper_fix_time; + rpc_loc_wiper_fix_pos_s_type wiper_fix_position; + rpc_loc_wiper_ap_set_s_type wiper_ap_set; +}; +typedef struct rpc_loc_wiper_position_report_s_type rpc_loc_wiper_position_report_s_type; + +enum rpc_loc_wiper_status_e_type { + RPC_LOC_WIPER_STATUS_AVAILABLE = 1, + RPC_LOC_WIPER_STATUS_UNAVAILABLE = 2, + RPC_LOC_WIPER_STATUS_E_SIZE = 268435456, +}; +typedef enum rpc_loc_wiper_status_e_type rpc_loc_wiper_status_e_type; + +enum rpc_loc_fs_operation_e_type { + RPC_LOC_FS_CREATE_WRITE_FILE = 1, + RPC_LOC_FS_APPEND_FILE = 2, + RPC_LOC_FS_DELETE_FILE = 3, + RPC_LOC_FS_READ_FILE = 4, + RPC_LOC_FS_MAX = 268435456, +}; +typedef enum rpc_loc_fs_operation_e_type rpc_loc_fs_operation_e_type; + +struct rpc_loc_efs_data_s_type { + char filename[64]; + rpc_loc_fs_operation_e_type operation; + rpc_uint32 total_size; + struct { + u_int data_ptr_len; + char *data_ptr_val; + } data_ptr; + rpc_uint32 part_len; + rpc_uint8 part; + rpc_uint8 total_parts; + rpc_uint32 reserved; +}; +typedef struct rpc_loc_efs_data_s_type rpc_loc_efs_data_s_type; + +enum rpc_loc_error_estimate_config_e_type { + RPC_LOC_ERROR_ESTIMATE_CONFIG_SET = 1, + RPC_LOC_ERROR_ESTIMATE_CONFIG_CLEAR = 2, + RPC_LOC_ERROR_ESTIMATE_MAX = 268435456, +}; +typedef enum rpc_loc_error_estimate_config_e_type rpc_loc_error_estimate_config_e_type; + +struct rpc_loc_apn_profiles_type { + rpc_uint32 srv_system_type; + rpc_uint32 pdp_type; + rpc_uint32 reserved; + char apn_name[100]; +}; +typedef struct rpc_loc_apn_profiles_type rpc_loc_apn_profiles_type; + +enum rpc_loc_lock_e_type { + RPC_LOC_LOCK_NONE = 1, + RPC_LOC_LOCK_MI = 2, + RPC_LOC_LOCK_MT = 3, + RPC_LOC_LOCK_ALL = 4, + RPC_LOC_LOCK_MAX = 268435456, +}; +typedef enum rpc_loc_lock_e_type rpc_loc_lock_e_type; + +typedef rpc_uint32 rpc_loc_nmea_sentence_type; + +typedef rpc_uint32 rpc_loc_assist_data_type; + +struct rpc_loc_assist_data_delete_s_type { + rpc_loc_assist_data_type type; + rpc_uint32 reserved[8]; +}; +typedef struct rpc_loc_assist_data_delete_s_type rpc_loc_assist_data_delete_s_type; + +struct rpc_loc_ioctl_data_u_type { + rpc_loc_ioctl_e_type disc; + union { + rpc_loc_fix_criteria_s_type fix_criteria; + rpc_loc_user_verify_s_type user_verify_resp; + rpc_loc_predicted_orbits_data_s_type predicted_orbits_data; + rpc_loc_predicted_orbits_auto_download_config_s_type predicted_orbits_auto_download; + rpc_loc_assist_data_time_s_type assistance_data_time; + rpc_loc_assist_data_pos_s_type assistance_data_position; + rpc_loc_server_open_status_s_type conn_open_status; + rpc_loc_server_close_status_s_type conn_close_status; + rpc_loc_wiper_position_report_s_type wiper_pos; + rpc_loc_wiper_status_e_type wiper_status; + rpc_loc_lock_e_type engine_lock; + rpc_boolean sbas_mode; + rpc_loc_nmea_sentence_type nmea_types; + rpc_boolean on_demand_lpm; + rpc_loc_server_info_s_type server_addr; + rpc_loc_assist_data_delete_s_type assist_data_delete; + rpc_loc_efs_data_s_type efs_data; + rpc_loc_error_estimate_config_e_type error_estimate_config; + rpc_uint8 xtra_t_session_control; + rpc_loc_apn_profiles_type apn_profiles[6]; + rpc_boolean data_enable; + rpc_uint32 supl_version; + rpc_loc_server_multi_open_status_s_type multi_conn_open_status; + rpc_loc_reserved_payload_s_type reserved; + } rpc_loc_ioctl_data_u_type_u; +}; +typedef struct rpc_loc_ioctl_data_u_type rpc_loc_ioctl_data_u_type; + +struct rpc_loc_ioctl_callback_data_u_type { + rpc_loc_ioctl_e_type disc; + union { + rpc_loc_api_version_s_type api_version; + rpc_loc_fix_criteria_s_type fix_criteria; + rpc_loc_lock_e_type engine_lock; + rpc_boolean sbas_mode; + rpc_loc_nmea_sentence_type nmea_types; + rpc_boolean on_demand_lpm; + rpc_loc_server_info_s_type server_addr; + rpc_loc_predicted_orbits_data_source_s_type predicted_orbits_data_source; + rpc_loc_predicted_orbits_data_validity_report_s_type predicted_orbits_data_validity; + rpc_uint8 xtra_t_session_control; + rpc_loc_apn_profiles_type apn_profiles[6]; + rpc_uint32 supl_version; + } rpc_loc_ioctl_callback_data_u_type_u; +}; +typedef struct rpc_loc_ioctl_callback_data_u_type rpc_loc_ioctl_callback_data_u_type; + +struct rpc_loc_ioctl_callback_s_type { + rpc_loc_ioctl_e_type type; + rpc_int32 status; + rpc_loc_ioctl_callback_data_u_type data; +}; +typedef struct rpc_loc_ioctl_callback_s_type rpc_loc_ioctl_callback_s_type; + +struct rpc_loc_event_payload_u_type { + u_quad_t disc; + union { + rpc_loc_parsed_position_s_type parsed_location_report; + rpc_loc_gnss_info_s_type gnss_report; + rpc_loc_nmea_report_s_type nmea_report; + rpc_loc_ni_event_s_type ni_request; + rpc_loc_assist_data_request_s_type assist_data_request; + rpc_loc_server_request_s_type loc_server_request; + rpc_loc_ioctl_callback_s_type ioctl_report; + rpc_loc_status_event_s_type status_report; + rpc_loc_qwip_request_s_type qwip_request; + rpc_loc_reserved_payload_s_type reserved; + } rpc_loc_event_payload_u_type_u; +}; +typedef struct rpc_loc_event_payload_u_type rpc_loc_event_payload_u_type; + +/* the xdr functions */ + +#if defined(__STDC__) || defined(__cplusplus) +extern bool_t xdr_rpc_loc_client_handle_type (XDR *, rpc_loc_client_handle_type*); +extern bool_t xdr_rpc_loc_event_mask_type (XDR *, rpc_loc_event_mask_type*); +extern bool_t xdr_rpc_loc_position_valid_mask_type (XDR *, rpc_loc_position_valid_mask_type*); +extern bool_t xdr_rpc_loc_pos_technology_mask_type (XDR *, rpc_loc_pos_technology_mask_type*); +extern bool_t xdr_rpc_loc_session_status_e_type (XDR *, rpc_loc_session_status_e_type*); +extern bool_t xdr_rpc_loc_calendar_time_s_type (XDR *, rpc_loc_calendar_time_s_type*); +extern bool_t xdr_rpc_loc_parsed_position_s_type (XDR *, rpc_loc_parsed_position_s_type*); +extern bool_t xdr_rpc_loc_sv_system_e_type (XDR *, rpc_loc_sv_system_e_type*); +extern bool_t xdr_rpc_loc_sv_status_e_type (XDR *, rpc_loc_sv_status_e_type*); +extern bool_t xdr_rpc_loc_sv_info_valid_mask_type (XDR *, rpc_loc_sv_info_valid_mask_type*); +extern bool_t xdr_rpc_loc_sv_info_s_type (XDR *, rpc_loc_sv_info_s_type*); +extern bool_t xdr_rpc_loc_gnss_info_valid_mask_type (XDR *, rpc_loc_gnss_info_valid_mask_type*); +extern bool_t xdr_rpc_loc_gnss_info_s_type (XDR *, rpc_loc_gnss_info_s_type*); +extern bool_t xdr_rpc_loc_nmea_report_s_type (XDR *, rpc_loc_nmea_report_s_type*); +extern bool_t xdr_rpc_loc_status_event_e_type (XDR *, rpc_loc_status_event_e_type*); +extern bool_t xdr_rpc_loc_engine_state_e_type (XDR *, rpc_loc_engine_state_e_type*); +extern bool_t xdr_rpc_loc_fix_session_state_e_type (XDR *, rpc_loc_fix_session_state_e_type*); +extern bool_t xdr_rpc_loc_status_event_payload_u_type (XDR *, rpc_loc_status_event_payload_u_type*); +extern bool_t xdr_rpc_loc_status_event_s_type (XDR *, rpc_loc_status_event_s_type*); +extern bool_t xdr_rpc_loc_server_addr_e_type (XDR *, rpc_loc_server_addr_e_type*); +extern bool_t xdr_rpc_loc_server_addr_ipv4_type (XDR *, rpc_loc_server_addr_ipv4_type*); +extern bool_t xdr_rpc_loc_server_addr_url_type (XDR *, rpc_loc_server_addr_url_type*); +extern bool_t xdr_rpc_loc_server_addr_ipv6_type (XDR *, rpc_loc_server_addr_ipv6_type*); +extern bool_t xdr_rpc_loc_server_addr_u_type (XDR *, rpc_loc_server_addr_u_type*); +extern bool_t xdr_rpc_loc_server_info_s_type (XDR *, rpc_loc_server_info_s_type*); +extern bool_t xdr_rpc_loc_ni_notify_verify_e_type (XDR *, rpc_loc_ni_notify_verify_e_type*); +extern bool_t xdr_rpc_loc_ni_event_e_type (XDR *, rpc_loc_ni_event_e_type*); +extern bool_t xdr_rpc_loc_ni_datacoding_scheme_e_type (XDR *, rpc_loc_ni_datacoding_scheme_e_type*); +extern bool_t xdr_rpc_loc_ni_vx_requester_id_encoding_scheme_e_type (XDR *, rpc_loc_ni_vx_requester_id_encoding_scheme_e_type*); +extern bool_t xdr_rpc_loc_ni_vx_pos_mode_e_type (XDR *, rpc_loc_ni_vx_pos_mode_e_type*); +extern bool_t xdr_rpc_loc_ni_vx_requester_id_s_type (XDR *, rpc_loc_ni_vx_requester_id_s_type*); +extern bool_t xdr_rpc_loc_ni_vx_notify_verify_req_s_type (XDR *, rpc_loc_ni_vx_notify_verify_req_s_type*); +extern bool_t xdr_rpc_loc_ni_supl_pos_method_e_type (XDR *, rpc_loc_ni_supl_pos_method_e_type*); +extern bool_t xdr_rpc_loc_ni_supl_slp_session_id_s_type (XDR *, rpc_loc_ni_supl_slp_session_id_s_type*); +extern bool_t xdr_rpc_loc_ni_requestor_id_s_type (XDR *, rpc_loc_ni_requestor_id_s_type*); +extern bool_t xdr_rpc_loc_ni_supl_client_name_s_type (XDR *, rpc_loc_ni_supl_client_name_s_type*); +extern bool_t xdr_rpc_loc_ni_supl_qop_s_type (XDR *, rpc_loc_ni_supl_qop_s_type*); +extern bool_t xdr_rpc_loc_ni_supl_notify_verify_req_s_type (XDR *, rpc_loc_ni_supl_notify_verify_req_s_type*); +extern bool_t xdr_rpc_loc_ni_ext_client_address_s_type (XDR *, rpc_loc_ni_ext_client_address_s_type*); +extern bool_t xdr_rpc_loc_ni_location_type_e_type (XDR *, rpc_loc_ni_location_type_e_type*); +extern bool_t xdr_rpc_loc_ni_deferred_location_s_type (XDR *, rpc_loc_ni_deferred_location_s_type*); +extern bool_t xdr_rpc_loc_ni_codeword_string_s_type (XDR *, rpc_loc_ni_codeword_string_s_type*); +extern bool_t xdr_rpc_loc_ni_service_type_id_s_type (XDR *, rpc_loc_ni_service_type_id_s_type*); +extern bool_t xdr_rpc_loc_ni_umts_cp_notify_verify_req_s_type (XDR *, rpc_loc_ni_umts_cp_notify_verify_req_s_type*); +extern bool_t xdr_rpc_loc_ni_service_interaction_e_type (XDR *, rpc_loc_ni_service_interaction_e_type*); +extern bool_t xdr_rpc_loc_ni_vx_service_interaction_req_s_type (XDR *, rpc_loc_ni_vx_service_interaction_req_s_type*); +extern bool_t xdr_rpc_loc_ni_event_payload_u_type (XDR *, rpc_loc_ni_event_payload_u_type*); +extern bool_t xdr_rpc_loc_ni_event_s_type (XDR *, rpc_loc_ni_event_s_type*); +extern bool_t xdr_rpc_loc_assist_data_request_e_type (XDR *, rpc_loc_assist_data_request_e_type*); +extern bool_t xdr_rpc_struct_loc_time_download_source_s_type_servers_ptr (XDR *, rpc_struct_loc_time_download_source_s_type_servers_ptr*); +extern bool_t xdr_rpc_struct_loc_time_download_source_s_type_servers (XDR *, rpc_struct_loc_time_download_source_s_type_servers); +extern bool_t xdr_rpc_loc_time_download_source_s_type (XDR *, rpc_loc_time_download_source_s_type*); +extern bool_t xdr_rpc_struct_loc_predicted_orbits_data_source_s_type_servers_ptr (XDR *, rpc_struct_loc_predicted_orbits_data_source_s_type_servers_ptr*); +extern bool_t xdr_rpc_struct_loc_predicted_orbits_data_source_s_type_servers (XDR *, rpc_struct_loc_predicted_orbits_data_source_s_type_servers); +extern bool_t xdr_rpc_loc_predicted_orbits_data_source_s_type (XDR *, rpc_loc_predicted_orbits_data_source_s_type*); +extern bool_t xdr_rpc_loc_pos_inj_request_s_type (XDR *, rpc_loc_pos_inj_request_s_type*); +extern bool_t xdr_rpc_loc_assist_data_request_payload_u_type (XDR *, rpc_loc_assist_data_request_payload_u_type*); +extern bool_t xdr_rpc_loc_assist_data_request_s_type (XDR *, rpc_loc_assist_data_request_s_type*); +extern bool_t xdr_rpc_loc_server_connection_handle (XDR *, rpc_loc_server_connection_handle*); +extern bool_t xdr_rpc_loc_server_protocol_e_type (XDR *, rpc_loc_server_protocol_e_type*); +extern bool_t xdr_rpc_loc_server_connection_e_type (XDR *, rpc_loc_server_connection_e_type*); +extern bool_t xdr_rpc_loc_server_request_e_type (XDR *, rpc_loc_server_request_e_type*); +extern bool_t xdr_rpc_loc_server_open_req_s_type (XDR *, rpc_loc_server_open_req_s_type*); +extern bool_t xdr_rpc_loc_server_multi_open_req_s_type (XDR *, rpc_loc_server_multi_open_req_s_type*); +extern bool_t xdr_rpc_loc_server_close_req_s_type (XDR *, rpc_loc_server_close_req_s_type*); +extern bool_t xdr_rpc_loc_server_request_u_type (XDR *, rpc_loc_server_request_u_type*); +extern bool_t xdr_rpc_loc_server_request_s_type (XDR *, rpc_loc_server_request_s_type*); +extern bool_t xdr_rpc_loc_qwip_request_e_type (XDR *, rpc_loc_qwip_request_e_type*); +extern bool_t xdr_rpc_loc_qwip_request_s_type (XDR *, rpc_loc_qwip_request_s_type*); +extern bool_t xdr_rpc_loc_reserved_payload_s_type (XDR *, rpc_loc_reserved_payload_s_type*); +extern bool_t xdr_rpc_loc_ioctl_e_type (XDR *, rpc_loc_ioctl_e_type*); +extern bool_t xdr_rpc_loc_api_version_s_type (XDR *, rpc_loc_api_version_s_type*); +extern bool_t xdr_rpc_loc_fix_recurrence_e_type (XDR *, rpc_loc_fix_recurrence_e_type*); +extern bool_t xdr_rpc_loc_operation_mode_e_type (XDR *, rpc_loc_operation_mode_e_type*); +extern bool_t xdr_rpc_loc_notify_e_type (XDR *, rpc_loc_notify_e_type*); +extern bool_t xdr_rpc_loc_fix_criteria_s_type (XDR *, rpc_loc_fix_criteria_s_type*); +extern bool_t xdr_rpc_loc_ni_user_resp_e_type (XDR *, rpc_loc_ni_user_resp_e_type*); +extern bool_t xdr_rpc_loc_user_verify_s_type (XDR *, rpc_loc_user_verify_s_type*); +extern bool_t xdr_rpc_loc_predicted_orbits_data_format_e_type (XDR *, rpc_loc_predicted_orbits_data_format_e_type*); +extern bool_t xdr_rpc_loc_predicted_orbits_data_s_type (XDR *, rpc_loc_predicted_orbits_data_s_type*); +extern bool_t xdr_rpc_loc_predicted_orbits_data_validity_report_s_type (XDR *, rpc_loc_predicted_orbits_data_validity_report_s_type*); +extern bool_t xdr_rpc_loc_predicted_orbits_auto_download_config_s_type (XDR *, rpc_loc_predicted_orbits_auto_download_config_s_type*); +extern bool_t xdr_rpc_loc_assist_data_time_s_type (XDR *, rpc_loc_assist_data_time_s_type*); +extern bool_t xdr_rpc_loc_assist_pos_valid_mask_type (XDR *, rpc_loc_assist_pos_valid_mask_type*); +extern bool_t xdr_rpc_loc_assist_data_pos_s_type (XDR *, rpc_loc_assist_data_pos_s_type*); +extern bool_t xdr_rpc_loc_server_open_status_e_type (XDR *, rpc_loc_server_open_status_e_type*); +extern bool_t xdr_rpc_loc_server_pdp_type_e_type (XDR *, rpc_loc_server_pdp_type_e_type*); +extern bool_t xdr_rpc_loc_server_open_status_s_type (XDR *, rpc_loc_server_open_status_s_type*); +extern bool_t xdr_rpc_loc_server_multi_open_status_s_type (XDR *, rpc_loc_server_multi_open_status_s_type*); +extern bool_t xdr_rpc_loc_server_close_status_e_type (XDR *, rpc_loc_server_close_status_e_type*); +extern bool_t xdr_rpc_loc_server_close_status_s_type (XDR *, rpc_loc_server_close_status_s_type*); +extern bool_t xdr_rpc_loc_wiper_fix_time_s_type (XDR *, rpc_loc_wiper_fix_time_s_type*); +extern bool_t xdr_rpc_loc_wiper_fix_pos_s_type (XDR *, rpc_loc_wiper_fix_pos_s_type*); +extern bool_t xdr_rpc_loc_wiper_ap_info_s_type (XDR *, rpc_loc_wiper_ap_info_s_type*); +extern bool_t xdr_rpc_loc_wiper_ap_set_s_type (XDR *, rpc_loc_wiper_ap_set_s_type*); +extern bool_t xdr_rpc_loc_wiper_position_report_s_type (XDR *, rpc_loc_wiper_position_report_s_type*); +extern bool_t xdr_rpc_loc_wiper_status_e_type (XDR *, rpc_loc_wiper_status_e_type*); +extern bool_t xdr_rpc_loc_fs_operation_e_type (XDR *, rpc_loc_fs_operation_e_type*); +extern bool_t xdr_rpc_loc_efs_data_s_type (XDR *, rpc_loc_efs_data_s_type*); +extern bool_t xdr_rpc_loc_error_estimate_config_e_type (XDR *, rpc_loc_error_estimate_config_e_type*); +extern bool_t xdr_rpc_loc_apn_profiles_type (XDR *, rpc_loc_apn_profiles_type*); +extern bool_t xdr_rpc_loc_lock_e_type (XDR *, rpc_loc_lock_e_type*); +extern bool_t xdr_rpc_loc_nmea_sentence_type (XDR *, rpc_loc_nmea_sentence_type*); +extern bool_t xdr_rpc_loc_assist_data_type (XDR *, rpc_loc_assist_data_type*); +extern bool_t xdr_rpc_loc_assist_data_delete_s_type (XDR *, rpc_loc_assist_data_delete_s_type*); +extern bool_t xdr_rpc_loc_ioctl_data_u_type (XDR *, rpc_loc_ioctl_data_u_type*); +extern bool_t xdr_rpc_loc_ioctl_callback_data_u_type (XDR *, rpc_loc_ioctl_callback_data_u_type*); +extern bool_t xdr_rpc_loc_ioctl_callback_s_type (XDR *, rpc_loc_ioctl_callback_s_type*); +extern bool_t xdr_rpc_loc_event_payload_u_type (XDR *, rpc_loc_event_payload_u_type*); + +#else /* K&R C */ +extern bool_t xdr_rpc_loc_client_handle_type (); +extern bool_t xdr_rpc_loc_event_mask_type (); +extern bool_t xdr_rpc_loc_position_valid_mask_type (); +extern bool_t xdr_rpc_loc_pos_technology_mask_type (); +extern bool_t xdr_rpc_loc_session_status_e_type (); +extern bool_t xdr_rpc_loc_calendar_time_s_type (); +extern bool_t xdr_rpc_loc_parsed_position_s_type (); +extern bool_t xdr_rpc_loc_sv_system_e_type (); +extern bool_t xdr_rpc_loc_sv_status_e_type (); +extern bool_t xdr_rpc_loc_sv_info_valid_mask_type (); +extern bool_t xdr_rpc_loc_sv_info_s_type (); +extern bool_t xdr_rpc_loc_gnss_info_valid_mask_type (); +extern bool_t xdr_rpc_loc_gnss_info_s_type (); +extern bool_t xdr_rpc_loc_nmea_report_s_type (); +extern bool_t xdr_rpc_loc_status_event_e_type (); +extern bool_t xdr_rpc_loc_engine_state_e_type (); +extern bool_t xdr_rpc_loc_fix_session_state_e_type (); +extern bool_t xdr_rpc_loc_status_event_payload_u_type (); +extern bool_t xdr_rpc_loc_status_event_s_type (); +extern bool_t xdr_rpc_loc_server_addr_e_type (); +extern bool_t xdr_rpc_loc_server_addr_ipv4_type (); +extern bool_t xdr_rpc_loc_server_addr_url_type (); +extern bool_t xdr_rpc_loc_server_addr_ipv6_type (); +extern bool_t xdr_rpc_loc_server_addr_u_type (); +extern bool_t xdr_rpc_loc_server_info_s_type (); +extern bool_t xdr_rpc_loc_ni_notify_verify_e_type (); +extern bool_t xdr_rpc_loc_ni_event_e_type (); +extern bool_t xdr_rpc_loc_ni_datacoding_scheme_e_type (); +extern bool_t xdr_rpc_loc_ni_vx_requester_id_encoding_scheme_e_type (); +extern bool_t xdr_rpc_loc_ni_vx_pos_mode_e_type (); +extern bool_t xdr_rpc_loc_ni_vx_requester_id_s_type (); +extern bool_t xdr_rpc_loc_ni_vx_notify_verify_req_s_type (); +extern bool_t xdr_rpc_loc_ni_supl_pos_method_e_type (); +extern bool_t xdr_rpc_loc_ni_supl_slp_session_id_s_type (); +extern bool_t xdr_rpc_loc_ni_requestor_id_s_type (); +extern bool_t xdr_rpc_loc_ni_supl_client_name_s_type (); +extern bool_t xdr_rpc_loc_ni_supl_qop_s_type (); +extern bool_t xdr_rpc_loc_ni_supl_notify_verify_req_s_type (); +extern bool_t xdr_rpc_loc_ni_ext_client_address_s_type (); +extern bool_t xdr_rpc_loc_ni_location_type_e_type (); +extern bool_t xdr_rpc_loc_ni_deferred_location_s_type (); +extern bool_t xdr_rpc_loc_ni_codeword_string_s_type (); +extern bool_t xdr_rpc_loc_ni_service_type_id_s_type (); +extern bool_t xdr_rpc_loc_ni_umts_cp_notify_verify_req_s_type (); +extern bool_t xdr_rpc_loc_ni_service_interaction_e_type (); +extern bool_t xdr_rpc_loc_ni_vx_service_interaction_req_s_type (); +extern bool_t xdr_rpc_loc_ni_event_payload_u_type (); +extern bool_t xdr_rpc_loc_ni_event_s_type (); +extern bool_t xdr_rpc_loc_assist_data_request_e_type (); +extern bool_t xdr_rpc_struct_loc_time_download_source_s_type_servers_ptr (); +extern bool_t xdr_rpc_struct_loc_time_download_source_s_type_servers (); +extern bool_t xdr_rpc_loc_time_download_source_s_type (); +extern bool_t xdr_rpc_struct_loc_predicted_orbits_data_source_s_type_servers_ptr (); +extern bool_t xdr_rpc_struct_loc_predicted_orbits_data_source_s_type_servers (); +extern bool_t xdr_rpc_loc_predicted_orbits_data_source_s_type (); +extern bool_t xdr_rpc_loc_pos_inj_request_s_type (); +extern bool_t xdr_rpc_loc_assist_data_request_payload_u_type (); +extern bool_t xdr_rpc_loc_assist_data_request_s_type (); +extern bool_t xdr_rpc_loc_server_connection_handle (); +extern bool_t xdr_rpc_loc_server_protocol_e_type (); +extern bool_t xdr_rpc_loc_server_connection_e_type (); +extern bool_t xdr_rpc_loc_server_request_e_type (); +extern bool_t xdr_rpc_loc_server_open_req_s_type (); +extern bool_t xdr_rpc_loc_server_multi_open_req_s_type (); +extern bool_t xdr_rpc_loc_server_close_req_s_type (); +extern bool_t xdr_rpc_loc_server_request_u_type (); +extern bool_t xdr_rpc_loc_server_request_s_type (); +extern bool_t xdr_rpc_loc_qwip_request_e_type (); +extern bool_t xdr_rpc_loc_qwip_request_s_type (); +extern bool_t xdr_rpc_loc_reserved_payload_s_type (); +extern bool_t xdr_rpc_loc_ioctl_e_type (); +extern bool_t xdr_rpc_loc_api_version_s_type (); +extern bool_t xdr_rpc_loc_fix_recurrence_e_type (); +extern bool_t xdr_rpc_loc_operation_mode_e_type (); +extern bool_t xdr_rpc_loc_notify_e_type (); +extern bool_t xdr_rpc_loc_fix_criteria_s_type (); +extern bool_t xdr_rpc_loc_ni_user_resp_e_type (); +extern bool_t xdr_rpc_loc_user_verify_s_type (); +extern bool_t xdr_rpc_loc_predicted_orbits_data_format_e_type (); +extern bool_t xdr_rpc_loc_predicted_orbits_data_s_type (); +extern bool_t xdr_rpc_loc_predicted_orbits_data_validity_report_s_type (); +extern bool_t xdr_rpc_loc_predicted_orbits_auto_download_config_s_type (); +extern bool_t xdr_rpc_loc_assist_data_time_s_type (); +extern bool_t xdr_rpc_loc_assist_pos_valid_mask_type (); +extern bool_t xdr_rpc_loc_assist_data_pos_s_type (); +extern bool_t xdr_rpc_loc_server_open_status_e_type (); +extern bool_t xdr_rpc_loc_server_pdp_type_e_type (); +extern bool_t xdr_rpc_loc_server_open_status_s_type (); +extern bool_t xdr_rpc_loc_server_multi_open_status_s_type (); +extern bool_t xdr_rpc_loc_server_close_status_e_type (); +extern bool_t xdr_rpc_loc_server_close_status_s_type (); +extern bool_t xdr_rpc_loc_wiper_fix_time_s_type (); +extern bool_t xdr_rpc_loc_wiper_fix_pos_s_type (); +extern bool_t xdr_rpc_loc_wiper_ap_info_s_type (); +extern bool_t xdr_rpc_loc_wiper_ap_set_s_type (); +extern bool_t xdr_rpc_loc_wiper_position_report_s_type (); +extern bool_t xdr_rpc_loc_wiper_status_e_type (); +extern bool_t xdr_rpc_loc_fs_operation_e_type (); +extern bool_t xdr_rpc_loc_efs_data_s_type (); +extern bool_t xdr_rpc_loc_error_estimate_config_e_type (); +extern bool_t xdr_rpc_loc_apn_profiles_type (); +extern bool_t xdr_rpc_loc_lock_e_type (); +extern bool_t xdr_rpc_loc_nmea_sentence_type (); +extern bool_t xdr_rpc_loc_assist_data_type (); +extern bool_t xdr_rpc_loc_assist_data_delete_s_type (); +extern bool_t xdr_rpc_loc_ioctl_data_u_type (); +extern bool_t xdr_rpc_loc_ioctl_callback_data_u_type (); +extern bool_t xdr_rpc_loc_ioctl_callback_s_type (); +extern bool_t xdr_rpc_loc_event_payload_u_type (); + +#endif /* K&R C */ + +#ifdef __cplusplus +} +#endif + +#endif /* !_LOC_API_COMMON_RPC_H_RPCGEN */ diff --git a/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-stub/inc/loc_api_rpcgen_rpc.h b/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-stub/inc/loc_api_rpcgen_rpc.h new file mode 100644 index 000000000..6138432e8 --- /dev/null +++ b/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-stub/inc/loc_api_rpcgen_rpc.h @@ -0,0 +1,288 @@ +/* Copyright (c) 2011, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/* + * Please do not edit this file. + * It was generated using rpcgen. + */ + +#ifndef _LOC_API_RPC_H_RPCGEN +#define _LOC_API_RPC_H_RPCGEN + +#include "librpc.h" +#include "commondefs_rpcgen_rpc.h" +#include "loc_api_rpcgen_common_rpc.h" + +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +typedef struct { + u_int rpc_loc_api_api_versions_return_type_len; + rpc_uint32 *rpc_loc_api_api_versions_return_type_val; +} rpc_loc_api_api_versions_return_type; + +typedef rpc_uint32 rpc_loc_event_cb_f_type; + +struct rpc_loc_open_args { + rpc_loc_event_mask_type event_reg_mask; + rpc_loc_event_cb_f_type event_callback; +}; +typedef struct rpc_loc_open_args rpc_loc_open_args; + +struct rpc_loc_close_args { + rpc_loc_client_handle_type handle; +}; +typedef struct rpc_loc_close_args rpc_loc_close_args; + +struct rpc_loc_start_fix_args { + rpc_loc_client_handle_type handle; +}; +typedef struct rpc_loc_start_fix_args rpc_loc_start_fix_args; + +struct rpc_loc_stop_fix_args { + rpc_loc_client_handle_type handle; +}; +typedef struct rpc_loc_stop_fix_args rpc_loc_stop_fix_args; + +struct rpc_loc_ioctl_args { + rpc_loc_client_handle_type handle; + rpc_loc_ioctl_e_type ioctl_type; + rpc_loc_ioctl_data_u_type *ioctl_data; +}; +typedef struct rpc_loc_ioctl_args rpc_loc_ioctl_args; + +struct rpc_loc_api_api_version_s_args { + rpc_boolean len_not_null; +}; +typedef struct rpc_loc_api_api_version_s_args rpc_loc_api_api_version_s_args; + +struct rpc_loc_api_rpc_glue_code_info_remote_rets { + rpc_uint32 toolvers; + rpc_uint32 features; + rpc_uint32 proghash; + rpc_uint32 cbproghash; +}; +typedef struct rpc_loc_api_rpc_glue_code_info_remote_rets rpc_loc_api_rpc_glue_code_info_remote_rets; + +struct rpc_loc_open_rets { + rpc_loc_client_handle_type loc_open_result; +}; +typedef struct rpc_loc_open_rets rpc_loc_open_rets; + +struct rpc_loc_close_rets { + rpc_int32 loc_close_result; +}; +typedef struct rpc_loc_close_rets rpc_loc_close_rets; + +struct rpc_loc_start_fix_rets { + rpc_int32 loc_start_fix_result; +}; +typedef struct rpc_loc_start_fix_rets rpc_loc_start_fix_rets; + +struct rpc_loc_stop_fix_rets { + rpc_int32 loc_stop_fix_result; +}; +typedef struct rpc_loc_stop_fix_rets rpc_loc_stop_fix_rets; + +struct rpc_loc_ioctl_rets { + rpc_int32 loc_ioctl_result; +}; +typedef struct rpc_loc_ioctl_rets rpc_loc_ioctl_rets; + +struct rpc_loc_api_api_versions_rets { + rpc_loc_api_api_versions_return_type loc_api_api_versions_result; + rpc_uint32 *len; +}; +typedef struct rpc_loc_api_api_versions_rets rpc_loc_api_api_versions_rets; +#define LOC_APIVERS 0x00050006 + +#define LOC_APIPROG 0x3000008C +#define LOC_APIVERS_0001 0x00050001 + +#if defined(__STDC__) || defined(__cplusplus) +#define rpc_loc_api_null 0 +extern enum clnt_stat rpc_loc_api_null_0x00050001(void *, void *, CLIENT *); +extern bool_t rpc_loc_api_null_0x00050001_svc(void *, void *, struct svc_req *); +#define rpc_loc_api_rpc_glue_code_info_remote 1 +extern enum clnt_stat rpc_loc_api_rpc_glue_code_info_remote_0x00050001(void *, rpc_loc_api_rpc_glue_code_info_remote_rets *, CLIENT *); +extern bool_t rpc_loc_api_rpc_glue_code_info_remote_0x00050001_svc(void *, rpc_loc_api_rpc_glue_code_info_remote_rets *, struct svc_req *); +#define rpc_loc_open 2 +extern enum clnt_stat rpc_loc_open_0x00050001(rpc_loc_open_args *, rpc_loc_open_rets *, CLIENT *); +extern bool_t rpc_loc_open_0x00050001_svc(rpc_loc_open_args *, rpc_loc_open_rets *, struct svc_req *); +#define rpc_loc_close 3 +extern enum clnt_stat rpc_loc_close_0x00050001(rpc_loc_close_args *, rpc_loc_close_rets *, CLIENT *); +extern bool_t rpc_loc_close_0x00050001_svc(rpc_loc_close_args *, rpc_loc_close_rets *, struct svc_req *); +#define rpc_loc_start_fix 4 +extern enum clnt_stat rpc_loc_start_fix_0x00050001(rpc_loc_start_fix_args *, rpc_loc_start_fix_rets *, CLIENT *); +extern bool_t rpc_loc_start_fix_0x00050001_svc(rpc_loc_start_fix_args *, rpc_loc_start_fix_rets *, struct svc_req *); +#define rpc_loc_stop_fix 5 +extern enum clnt_stat rpc_loc_stop_fix_0x00050001(rpc_loc_stop_fix_args *, rpc_loc_stop_fix_rets *, CLIENT *); +extern bool_t rpc_loc_stop_fix_0x00050001_svc(rpc_loc_stop_fix_args *, rpc_loc_stop_fix_rets *, struct svc_req *); +#define rpc_loc_ioctl 6 +extern enum clnt_stat rpc_loc_ioctl_0x00050001(rpc_loc_ioctl_args *, rpc_loc_ioctl_rets *, CLIENT *); +extern bool_t rpc_loc_ioctl_0x00050001_svc(rpc_loc_ioctl_args *, rpc_loc_ioctl_rets *, struct svc_req *); +#define rpc_loc_api_api_versions 0xFFFFFFFF +extern enum clnt_stat rpc_loc_api_api_versions_0x00050001(void *, rpc_loc_api_api_versions_rets *, CLIENT *); +extern bool_t rpc_loc_api_api_versions_0x00050001_svc(void *, rpc_loc_api_api_versions_rets *, struct svc_req *); +extern int loc_apiprog_0x00050001_freeresult (SVCXPRT *, xdrproc_t, caddr_t); + +#else /* K&R C */ +#define rpc_loc_api_null 0 +extern enum clnt_stat rpc_loc_api_null_0x00050001(); +extern bool_t rpc_loc_api_null_0x00050001_svc(); +#define rpc_loc_api_rpc_glue_code_info_remote 1 +extern enum clnt_stat rpc_loc_api_rpc_glue_code_info_remote_0x00050001(); +extern bool_t rpc_loc_api_rpc_glue_code_info_remote_0x00050001_svc(); +#define rpc_loc_open 2 +extern enum clnt_stat rpc_loc_open_0x00050001(); +extern bool_t rpc_loc_open_0x00050001_svc(); +#define rpc_loc_close 3 +extern enum clnt_stat rpc_loc_close_0x00050001(); +extern bool_t rpc_loc_close_0x00050001_svc(); +#define rpc_loc_start_fix 4 +extern enum clnt_stat rpc_loc_start_fix_0x00050001(); +extern bool_t rpc_loc_start_fix_0x00050001_svc(); +#define rpc_loc_stop_fix 5 +extern enum clnt_stat rpc_loc_stop_fix_0x00050001(); +extern bool_t rpc_loc_stop_fix_0x00050001_svc(); +#define rpc_loc_ioctl 6 +extern enum clnt_stat rpc_loc_ioctl_0x00050001(); +extern bool_t rpc_loc_ioctl_0x00050001_svc(); +#define rpc_loc_api_api_versions 0xFFFFFFFF +extern enum clnt_stat rpc_loc_api_api_versions_0x00050001(); +extern bool_t rpc_loc_api_api_versions_0x00050001_svc(); +extern int loc_apiprog_0x00050001_freeresult (); +#endif /* K&R C */ +#define LOC_APIVERS_0002 0x00050002 + +#if defined(__STDC__) || defined(__cplusplus) +extern enum clnt_stat rpc_loc_api_null_0x00050002(void *, void *, CLIENT *); +extern bool_t rpc_loc_api_null_0x00050002_svc(void *, void *, struct svc_req *); +extern int loc_apiprog_0x00050002_freeresult (SVCXPRT *, xdrproc_t, caddr_t); + +#else /* K&R C */ +extern enum clnt_stat rpc_loc_api_null_0x00050002(); +extern bool_t rpc_loc_api_null_0x00050002_svc(); +extern int loc_apiprog_0x00050002_freeresult (); +#endif /* K&R C */ +#define LOC_APIVERS_0003 0x00050003 + +#if defined(__STDC__) || defined(__cplusplus) +extern enum clnt_stat rpc_loc_api_null_0x00050003(void *, void *, CLIENT *); +extern bool_t rpc_loc_api_null_0x00050003_svc(void *, void *, struct svc_req *); +extern int loc_apiprog_0x00050003_freeresult (SVCXPRT *, xdrproc_t, caddr_t); + +#else /* K&R C */ +extern enum clnt_stat rpc_loc_api_null_0x00050003(); +extern bool_t rpc_loc_api_null_0x00050003_svc(); +extern int loc_apiprog_0x00050003_freeresult (); +#endif /* K&R C */ +#define LOC_APIVERS_0004 0x00050004 + +#if defined(__STDC__) || defined(__cplusplus) +extern enum clnt_stat rpc_loc_api_null_0x00050004(void *, void *, CLIENT *); +extern bool_t rpc_loc_api_null_0x00050004_svc(void *, void *, struct svc_req *); +extern int loc_apiprog_0x00050004_freeresult (SVCXPRT *, xdrproc_t, caddr_t); + +#else /* K&R C */ +extern enum clnt_stat rpc_loc_api_null_0x00050004(); +extern bool_t rpc_loc_api_null_0x00050004_svc(); +extern int loc_apiprog_0x00050004_freeresult (); +#endif /* K&R C */ +#define LOC_APIVERS_0005 0x00050005 + +#if defined(__STDC__) || defined(__cplusplus) +extern enum clnt_stat rpc_loc_api_null_0x00050005(void *, void *, CLIENT *); +extern bool_t rpc_loc_api_null_0x00050005_svc(void *, void *, struct svc_req *); +extern int loc_apiprog_0x00050005_freeresult (SVCXPRT *, xdrproc_t, caddr_t); + +#else /* K&R C */ +extern enum clnt_stat rpc_loc_api_null_0x00050005(); +extern bool_t rpc_loc_api_null_0x00050005_svc(); +extern int loc_apiprog_0x00050005_freeresult (); +#endif /* K&R C */ +#define LOC_APIVERS_0006 0x00050006 + +#if defined(__STDC__) || defined(__cplusplus) +extern enum clnt_stat rpc_loc_api_null_0x00050006(void *, void *, CLIENT *); +extern bool_t rpc_loc_api_null_0x00050006_svc(void *, void *, struct svc_req *); +extern int loc_apiprog_0x00050006_freeresult (SVCXPRT *, xdrproc_t, caddr_t); + +#else /* K&R C */ +extern enum clnt_stat rpc_loc_api_null_0x00050006(); +extern bool_t rpc_loc_api_null_0x00050006_svc(); +extern int loc_apiprog_0x00050006_freeresult (); +#endif /* K&R C */ + +/* the xdr functions */ + +#if defined(__STDC__) || defined(__cplusplus) +extern bool_t xdr_rpc_loc_api_api_versions_return_type (XDR *, rpc_loc_api_api_versions_return_type*); +extern bool_t xdr_rpc_loc_event_cb_f_type (XDR *, rpc_loc_event_cb_f_type*); +extern bool_t xdr_rpc_loc_open_args (XDR *, rpc_loc_open_args*); +extern bool_t xdr_rpc_loc_close_args (XDR *, rpc_loc_close_args*); +extern bool_t xdr_rpc_loc_start_fix_args (XDR *, rpc_loc_start_fix_args*); +extern bool_t xdr_rpc_loc_stop_fix_args (XDR *, rpc_loc_stop_fix_args*); +extern bool_t xdr_rpc_loc_ioctl_args (XDR *, rpc_loc_ioctl_args*); +extern bool_t xdr_rpc_loc_api_api_version_s_args (XDR *, rpc_loc_api_api_version_s_args*); +extern bool_t xdr_rpc_loc_api_rpc_glue_code_info_remote_rets (XDR *, rpc_loc_api_rpc_glue_code_info_remote_rets*); +extern bool_t xdr_rpc_loc_open_rets (XDR *, rpc_loc_open_rets*); +extern bool_t xdr_rpc_loc_close_rets (XDR *, rpc_loc_close_rets*); +extern bool_t xdr_rpc_loc_start_fix_rets (XDR *, rpc_loc_start_fix_rets*); +extern bool_t xdr_rpc_loc_stop_fix_rets (XDR *, rpc_loc_stop_fix_rets*); +extern bool_t xdr_rpc_loc_ioctl_rets (XDR *, rpc_loc_ioctl_rets*); +extern bool_t xdr_rpc_loc_api_api_versions_rets (XDR *, rpc_loc_api_api_versions_rets*); + +#else /* K&R C */ +extern bool_t xdr_rpc_loc_api_api_versions_return_type (); +extern bool_t xdr_rpc_loc_event_cb_f_type (); +extern bool_t xdr_rpc_loc_open_args (); +extern bool_t xdr_rpc_loc_close_args (); +extern bool_t xdr_rpc_loc_start_fix_args (); +extern bool_t xdr_rpc_loc_stop_fix_args (); +extern bool_t xdr_rpc_loc_ioctl_args (); +extern bool_t xdr_rpc_loc_api_api_version_s_args (); +extern bool_t xdr_rpc_loc_api_rpc_glue_code_info_remote_rets (); +extern bool_t xdr_rpc_loc_open_rets (); +extern bool_t xdr_rpc_loc_close_rets (); +extern bool_t xdr_rpc_loc_start_fix_rets (); +extern bool_t xdr_rpc_loc_stop_fix_rets (); +extern bool_t xdr_rpc_loc_ioctl_rets (); +extern bool_t xdr_rpc_loc_api_api_versions_rets (); + +#endif /* K&R C */ + +#ifdef __cplusplus +} +#endif + +#endif /* !_LOC_API_RPC_H_RPCGEN */ diff --git a/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-stub/inc/loc_apicb_appinit.h b/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-stub/inc/loc_apicb_appinit.h new file mode 100644 index 000000000..875c4f08d --- /dev/null +++ b/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-stub/inc/loc_apicb_appinit.h @@ -0,0 +1,34 @@ +/* Copyright (c) 2011, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/* Initialization function for callbacks */ +int loc_apicb_app_init(); + +void loc_apicb_app_deinit(); + diff --git a/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-stub/src/loc_api_rpcgen_cb_svc.c b/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-stub/src/loc_api_rpcgen_cb_svc.c new file mode 100644 index 000000000..2ef5852e6 --- /dev/null +++ b/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-stub/src/loc_api_rpcgen_cb_svc.c @@ -0,0 +1,327 @@ +/* Copyright (c) 2011, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/* + * Please do not edit this file. + * It was generated using rpcgen. + */ + +#include "loc_api_rpcgen_cb_rpc.h" +#include +#include +#include +#include +#include +#include +#include + +#ifndef SIG_PF +#define SIG_PF void(*)(int) +#endif + +void +loc_apicbprog_0x00050001(struct svc_req *rqstp, register SVCXPRT *transp) +{ + union { + rpc_loc_event_cb_f_type_args rpc_loc_event_cb_f_type_0x00050001_arg; + } argument; + union { + rpc_loc_event_cb_f_type_rets rpc_loc_event_cb_f_type_0x00050001_res; + } result; + bool_t retval; + xdrproc_t _xdr_argument, _xdr_result; + bool_t (*local)(char *, void *, struct svc_req *); + + switch (rqstp->rq_proc) { + case NULLPROC: + (void) svc_sendreply (transp, (xdrproc_t) xdr_void, (char *)NULL); + return; + + case rpc_loc_event_cb_f_type: + _xdr_argument = (xdrproc_t) xdr_rpc_loc_event_cb_f_type_args; + _xdr_result = (xdrproc_t) xdr_rpc_loc_event_cb_f_type_rets; + local = (bool_t (*) (char *, void *, struct svc_req *))rpc_loc_event_cb_f_type_0x00050001_svc; + break; + + default: + svcerr_noproc (transp); + return; + } + memset ((char *)&argument, 0, sizeof (argument)); + if (!svc_getargs (transp, (xdrproc_t) _xdr_argument, (caddr_t) &argument)) { + svcerr_decode (transp); + return; + } + retval = (bool_t) (*local)((char *)&argument, (void *)&result, rqstp); + if (retval > 0 && !svc_sendreply(transp, (xdrproc_t) _xdr_result, (char *)&result)) { + svcerr_systemerr (transp); + } + if (!svc_freeargs (transp, (xdrproc_t) _xdr_argument, (caddr_t) &argument)) { + fprintf (stderr, "%s", "unable to free arguments"); + exit (1); + } + if (!loc_apicbprog_0x00050001_freeresult (transp, _xdr_result, (caddr_t) &result)) + fprintf (stderr, "%s", "unable to free results"); + + return; +} + +void +loc_apicbprog_0x00050002(struct svc_req *rqstp, register SVCXPRT *transp) +{ + union { + int fill; + } argument; + union { + int rpc_loc_api_cb_null_0x00050002_res; + } result; + bool_t retval; + xdrproc_t _xdr_argument, _xdr_result; + bool_t (*local)(char *, void *, struct svc_req *); + + switch (rqstp->rq_proc) { + case NULLPROC: + (void) svc_sendreply (transp, (xdrproc_t) xdr_void, (char *)NULL); + return; + + case rpc_loc_api_cb_null: + _xdr_argument = (xdrproc_t) xdr_void; + _xdr_result = (xdrproc_t) xdr_int; + local = (bool_t (*) (char *, void *, struct svc_req *))rpc_loc_api_cb_null_0x00050002_svc; + break; + + default: + svcerr_noproc (transp); + return; + } + memset ((char *)&argument, 0, sizeof (argument)); + if (!svc_getargs (transp, (xdrproc_t) _xdr_argument, (caddr_t) &argument)) { + svcerr_decode (transp); + return; + } + retval = (bool_t) (*local)((char *)&argument, (void *)&result, rqstp); + if (retval > 0 && !svc_sendreply(transp, (xdrproc_t) _xdr_result, (char *)&result)) { + svcerr_systemerr (transp); + } + if (!svc_freeargs (transp, (xdrproc_t) _xdr_argument, (caddr_t) &argument)) { + fprintf (stderr, "%s", "unable to free arguments"); + exit (1); + } + if (!loc_apicbprog_0x00050002_freeresult (transp, _xdr_result, (caddr_t) &result)) + fprintf (stderr, "%s", "unable to free results"); + + return; +} + +void +loc_apicbprog_0x00050003(struct svc_req *rqstp, register SVCXPRT *transp) +{ + union { + int fill; + } argument; + union { + int rpc_loc_api_cb_null_0x00050003_res; + } result; + bool_t retval; + xdrproc_t _xdr_argument, _xdr_result; + bool_t (*local)(char *, void *, struct svc_req *); + + switch (rqstp->rq_proc) { + case NULLPROC: + (void) svc_sendreply (transp, (xdrproc_t) xdr_void, (char *)NULL); + return; + + case rpc_loc_api_cb_null: + _xdr_argument = (xdrproc_t) xdr_void; + _xdr_result = (xdrproc_t) xdr_int; + local = (bool_t (*) (char *, void *, struct svc_req *))rpc_loc_api_cb_null_0x00050003_svc; + break; + + default: + svcerr_noproc (transp); + return; + } + memset ((char *)&argument, 0, sizeof (argument)); + if (!svc_getargs (transp, (xdrproc_t) _xdr_argument, (caddr_t) &argument)) { + svcerr_decode (transp); + return; + } + retval = (bool_t) (*local)((char *)&argument, (void *)&result, rqstp); + if (retval > 0 && !svc_sendreply(transp, (xdrproc_t) _xdr_result, (char *)&result)) { + svcerr_systemerr (transp); + } + if (!svc_freeargs (transp, (xdrproc_t) _xdr_argument, (caddr_t) &argument)) { + fprintf (stderr, "%s", "unable to free arguments"); + exit (1); + } + if (!loc_apicbprog_0x00050003_freeresult (transp, _xdr_result, (caddr_t) &result)) + fprintf (stderr, "%s", "unable to free results"); + + return; +} + +void +loc_apicbprog_0x00050004(struct svc_req *rqstp, register SVCXPRT *transp) +{ + union { + int fill; + } argument; + union { + int rpc_loc_api_cb_null_0x00050004_res; + } result; + bool_t retval; + xdrproc_t _xdr_argument, _xdr_result; + bool_t (*local)(char *, void *, struct svc_req *); + + switch (rqstp->rq_proc) { + case NULLPROC: + (void) svc_sendreply (transp, (xdrproc_t) xdr_void, (char *)NULL); + return; + + case rpc_loc_api_cb_null: + _xdr_argument = (xdrproc_t) xdr_void; + _xdr_result = (xdrproc_t) xdr_int; + local = (bool_t (*) (char *, void *, struct svc_req *))rpc_loc_api_cb_null_0x00050004_svc; + break; + + default: + svcerr_noproc (transp); + return; + } + memset ((char *)&argument, 0, sizeof (argument)); + if (!svc_getargs (transp, (xdrproc_t) _xdr_argument, (caddr_t) &argument)) { + svcerr_decode (transp); + return; + } + retval = (bool_t) (*local)((char *)&argument, (void *)&result, rqstp); + if (retval > 0 && !svc_sendreply(transp, (xdrproc_t) _xdr_result, (char *)&result)) { + svcerr_systemerr (transp); + } + if (!svc_freeargs (transp, (xdrproc_t) _xdr_argument, (caddr_t) &argument)) { + fprintf (stderr, "%s", "unable to free arguments"); + exit (1); + } + if (!loc_apicbprog_0x00050004_freeresult (transp, _xdr_result, (caddr_t) &result)) + fprintf (stderr, "%s", "unable to free results"); + + return; +} + +void +loc_apicbprog_0x00050005(struct svc_req *rqstp, register SVCXPRT *transp) +{ + union { + int fill; + } argument; + union { + int rpc_loc_api_cb_null_0x00050005_res; + } result; + bool_t retval; + xdrproc_t _xdr_argument, _xdr_result; + bool_t (*local)(char *, void *, struct svc_req *); + + switch (rqstp->rq_proc) { + case NULLPROC: + (void) svc_sendreply (transp, (xdrproc_t) xdr_void, (char *)NULL); + return; + + case rpc_loc_api_cb_null: + _xdr_argument = (xdrproc_t) xdr_void; + _xdr_result = (xdrproc_t) xdr_int; + local = (bool_t (*) (char *, void *, struct svc_req *))rpc_loc_api_cb_null_0x00050005_svc; + break; + + default: + svcerr_noproc (transp); + return; + } + memset ((char *)&argument, 0, sizeof (argument)); + if (!svc_getargs (transp, (xdrproc_t) _xdr_argument, (caddr_t) &argument)) { + svcerr_decode (transp); + return; + } + retval = (bool_t) (*local)((char *)&argument, (void *)&result, rqstp); + if (retval > 0 && !svc_sendreply(transp, (xdrproc_t) _xdr_result, (char *)&result)) { + svcerr_systemerr (transp); + } + if (!svc_freeargs (transp, (xdrproc_t) _xdr_argument, (caddr_t) &argument)) { + fprintf (stderr, "%s", "unable to free arguments"); + exit (1); + } + if (!loc_apicbprog_0x00050005_freeresult (transp, _xdr_result, (caddr_t) &result)) + fprintf (stderr, "%s", "unable to free results"); + + return; +} + +void +loc_apicbprog_0x00050006(struct svc_req *rqstp, register SVCXPRT *transp) +{ + union { + int fill; + } argument; + union { + int rpc_loc_api_cb_null_0x00050006_res; + } result; + bool_t retval; + xdrproc_t _xdr_argument, _xdr_result; + bool_t (*local)(char *, void *, struct svc_req *); + + switch (rqstp->rq_proc) { + case NULLPROC: + (void) svc_sendreply (transp, (xdrproc_t) xdr_void, (char *)NULL); + return; + + case rpc_loc_api_cb_null: + _xdr_argument = (xdrproc_t) xdr_void; + _xdr_result = (xdrproc_t) xdr_int; + local = (bool_t (*) (char *, void *, struct svc_req *))rpc_loc_api_cb_null_0x00050006_svc; + break; + + default: + svcerr_noproc (transp); + return; + } + memset ((char *)&argument, 0, sizeof (argument)); + if (!svc_getargs (transp, (xdrproc_t) _xdr_argument, (caddr_t) &argument)) { + svcerr_decode (transp); + return; + } + retval = (bool_t) (*local)((char *)&argument, (void *)&result, rqstp); + if (retval > 0 && !svc_sendreply(transp, (xdrproc_t) _xdr_result, (char *)&result)) { + svcerr_systemerr (transp); + } + if (!svc_freeargs (transp, (xdrproc_t) _xdr_argument, (caddr_t) &argument)) { + fprintf (stderr, "%s", "unable to free arguments"); + exit (1); + } + if (!loc_apicbprog_0x00050006_freeresult (transp, _xdr_result, (caddr_t) &result)) + fprintf (stderr, "%s", "unable to free results"); + + return; +} diff --git a/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-stub/src/loc_api_rpcgen_cb_xdr.c b/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-stub/src/loc_api_rpcgen_cb_xdr.c new file mode 100644 index 000000000..ad171dc4e --- /dev/null +++ b/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-stub/src/loc_api_rpcgen_cb_xdr.c @@ -0,0 +1,60 @@ +/* Copyright (c) 2011, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/* + * Please do not edit this file. + * It was generated using rpcgen. + */ + +#include "loc_api_rpcgen_cb_rpc.h" + +bool_t +xdr_rpc_loc_event_cb_f_type_args (XDR *xdrs, rpc_loc_event_cb_f_type_args *objp) +{ +; + + if (!xdr_rpc_uint32 (xdrs, &objp->cb_id)) + return FALSE; + if (!xdr_rpc_loc_client_handle_type (xdrs, &objp->loc_handle)) + return FALSE; + if (!xdr_rpc_loc_event_mask_type (xdrs, &objp->loc_event)) + return FALSE; + if (!xdr_pointer (xdrs, (char **)&objp->loc_event_payload, sizeof (rpc_loc_event_payload_u_type), (xdrproc_t) xdr_rpc_loc_event_payload_u_type)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_event_cb_f_type_rets (XDR *xdrs, rpc_loc_event_cb_f_type_rets *objp) +{ +; + + if (!xdr_rpc_int32 (xdrs, &objp->loc_event_cb_f_type_result)) + return FALSE; + return TRUE; +} diff --git a/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-stub/src/loc_api_rpcgen_clnt.c b/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-stub/src/loc_api_rpcgen_clnt.c new file mode 100644 index 000000000..3e39576b1 --- /dev/null +++ b/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-stub/src/loc_api_rpcgen_clnt.c @@ -0,0 +1,155 @@ +/* Copyright (c) 2011, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/* + * Please do not edit this file. + * It was generated using rpcgen. + */ + +#include /* for memset */ +#include "loc_api_rpcgen_rpc.h" + +/* Default timeout can be changed using clnt_control() */ +static struct timeval TIMEOUT = { 25, 0 }; + +enum clnt_stat +rpc_loc_api_null_0x00050001(void *argp, void *clnt_res, CLIENT *clnt) +{ + return (clnt_call(clnt, rpc_loc_api_null, + (xdrproc_t) xdr_void, (caddr_t) argp, + (xdrproc_t) xdr_void, (caddr_t) clnt_res, + TIMEOUT)); +} + +enum clnt_stat +rpc_loc_api_rpc_glue_code_info_remote_0x00050001(void *argp, rpc_loc_api_rpc_glue_code_info_remote_rets *clnt_res, CLIENT *clnt) +{ + return (clnt_call(clnt, rpc_loc_api_rpc_glue_code_info_remote, + (xdrproc_t) xdr_void, (caddr_t) argp, + (xdrproc_t) xdr_rpc_loc_api_rpc_glue_code_info_remote_rets, (caddr_t) clnt_res, + TIMEOUT)); +} + +enum clnt_stat +rpc_loc_open_0x00050001(rpc_loc_open_args *argp, rpc_loc_open_rets *clnt_res, CLIENT *clnt) +{ + return (clnt_call(clnt, rpc_loc_open, + (xdrproc_t) xdr_rpc_loc_open_args, (caddr_t) argp, + (xdrproc_t) xdr_rpc_loc_open_rets, (caddr_t) clnt_res, + TIMEOUT)); +} + +enum clnt_stat +rpc_loc_close_0x00050001(rpc_loc_close_args *argp, rpc_loc_close_rets *clnt_res, CLIENT *clnt) +{ + return (clnt_call(clnt, rpc_loc_close, + (xdrproc_t) xdr_rpc_loc_close_args, (caddr_t) argp, + (xdrproc_t) xdr_rpc_loc_close_rets, (caddr_t) clnt_res, + TIMEOUT)); +} + +enum clnt_stat +rpc_loc_start_fix_0x00050001(rpc_loc_start_fix_args *argp, rpc_loc_start_fix_rets *clnt_res, CLIENT *clnt) +{ + return (clnt_call(clnt, rpc_loc_start_fix, + (xdrproc_t) xdr_rpc_loc_start_fix_args, (caddr_t) argp, + (xdrproc_t) xdr_rpc_loc_start_fix_rets, (caddr_t) clnt_res, + TIMEOUT)); +} + +enum clnt_stat +rpc_loc_stop_fix_0x00050001(rpc_loc_stop_fix_args *argp, rpc_loc_stop_fix_rets *clnt_res, CLIENT *clnt) +{ + return (clnt_call(clnt, rpc_loc_stop_fix, + (xdrproc_t) xdr_rpc_loc_stop_fix_args, (caddr_t) argp, + (xdrproc_t) xdr_rpc_loc_stop_fix_rets, (caddr_t) clnt_res, + TIMEOUT)); +} + +enum clnt_stat +rpc_loc_ioctl_0x00050001(rpc_loc_ioctl_args *argp, rpc_loc_ioctl_rets *clnt_res, CLIENT *clnt) +{ + return (clnt_call(clnt, rpc_loc_ioctl, + (xdrproc_t) xdr_rpc_loc_ioctl_args, (caddr_t) argp, + (xdrproc_t) xdr_rpc_loc_ioctl_rets, (caddr_t) clnt_res, + TIMEOUT)); +} + +enum clnt_stat +rpc_loc_api_api_versions_0x00050001(void *argp, rpc_loc_api_api_versions_rets *clnt_res, CLIENT *clnt) +{ + return (clnt_call(clnt, rpc_loc_api_api_versions, + (xdrproc_t) xdr_void, (caddr_t) argp, + (xdrproc_t) xdr_rpc_loc_api_api_versions_rets, (caddr_t) clnt_res, + TIMEOUT)); +} + +enum clnt_stat +rpc_loc_api_null_0x00050002(void *argp, void *clnt_res, CLIENT *clnt) +{ + return (clnt_call(clnt, rpc_loc_api_null, + (xdrproc_t) xdr_void, (caddr_t) argp, + (xdrproc_t) xdr_void, (caddr_t) clnt_res, + TIMEOUT)); +} + +enum clnt_stat +rpc_loc_api_null_0x00050003(void *argp, void *clnt_res, CLIENT *clnt) +{ + return (clnt_call(clnt, rpc_loc_api_null, + (xdrproc_t) xdr_void, (caddr_t) argp, + (xdrproc_t) xdr_void, (caddr_t) clnt_res, + TIMEOUT)); +} + +enum clnt_stat +rpc_loc_api_null_0x00050004(void *argp, void *clnt_res, CLIENT *clnt) +{ + return (clnt_call(clnt, rpc_loc_api_null, + (xdrproc_t) xdr_void, (caddr_t) argp, + (xdrproc_t) xdr_void, (caddr_t) clnt_res, + TIMEOUT)); +} + +enum clnt_stat +rpc_loc_api_null_0x00050005(void *argp, void *clnt_res, CLIENT *clnt) +{ + return (clnt_call(clnt, rpc_loc_api_null, + (xdrproc_t) xdr_void, (caddr_t) argp, + (xdrproc_t) xdr_void, (caddr_t) clnt_res, + TIMEOUT)); +} + +enum clnt_stat +rpc_loc_api_null_0x00050006(void *argp, void *clnt_res, CLIENT *clnt) +{ + return (clnt_call(clnt, rpc_loc_api_null, + (xdrproc_t) xdr_void, (caddr_t) argp, + (xdrproc_t) xdr_void, (caddr_t) clnt_res, + TIMEOUT)); +} diff --git a/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-stub/src/loc_api_rpcgen_common_xdr.c b/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-stub/src/loc_api_rpcgen_common_xdr.c new file mode 100644 index 000000000..21be8f431 --- /dev/null +++ b/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-stub/src/loc_api_rpcgen_common_xdr.c @@ -0,0 +1,1775 @@ +/* Copyright (c) 2011, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/* + * Please do not edit this file. + * It was generated using rpcgen. + */ + +#include "loc_api_rpcgen_common_rpc.h" + +bool_t +xdr_rpc_loc_client_handle_type (XDR *xdrs, rpc_loc_client_handle_type *objp) +{ + register int32_t *buf; + + if (!xdr_rpc_int32 (xdrs, objp)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_event_mask_type (XDR *xdrs, rpc_loc_event_mask_type *objp) +{ + register int32_t *buf; + + if (!xdr_rpc_uint64 (xdrs, objp)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_position_valid_mask_type (XDR *xdrs, rpc_loc_position_valid_mask_type *objp) +{ + register int32_t *buf; + + if (!xdr_rpc_uint64 (xdrs, objp)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_pos_technology_mask_type (XDR *xdrs, rpc_loc_pos_technology_mask_type *objp) +{ + register int32_t *buf; + + if (!xdr_rpc_uint32 (xdrs, objp)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_session_status_e_type (XDR *xdrs, rpc_loc_session_status_e_type *objp) +{ + register int32_t *buf; + + if (!xdr_enum (xdrs, (enum_t *) objp)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_calendar_time_s_type (XDR *xdrs, rpc_loc_calendar_time_s_type *objp) +{ + register int32_t *buf; + + if (!xdr_rpc_uint16 (xdrs, &objp->year)) + return FALSE; + if (!xdr_u_char (xdrs, &objp->month)) + return FALSE; + if (!xdr_u_char (xdrs, &objp->day_of_week)) + return FALSE; + if (!xdr_u_char (xdrs, &objp->day)) + return FALSE; + if (!xdr_u_char (xdrs, &objp->hour)) + return FALSE; + if (!xdr_u_char (xdrs, &objp->minute)) + return FALSE; + if (!xdr_u_char (xdrs, &objp->second)) + return FALSE; + if (!xdr_rpc_uint16 (xdrs, &objp->millisecond)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_parsed_position_s_type (XDR *xdrs, rpc_loc_parsed_position_s_type *objp) +{ + register int32_t *buf; + + if (!xdr_rpc_loc_position_valid_mask_type (xdrs, &objp->valid_mask)) + return FALSE; + if (!xdr_rpc_loc_session_status_e_type (xdrs, &objp->session_status)) + return FALSE; + if (!xdr_rpc_loc_calendar_time_s_type (xdrs, &objp->timestamp_calendar)) + return FALSE; + if (!xdr_rpc_uint64 (xdrs, &objp->timestamp_utc)) + return FALSE; + if (!xdr_rpc_uint8 (xdrs, &objp->leap_seconds)) + return FALSE; + if (!xdr_float (xdrs, &objp->time_unc)) + return FALSE; + if (!xdr_double (xdrs, &objp->latitude)) + return FALSE; + if (!xdr_double (xdrs, &objp->longitude)) + return FALSE; + if (!xdr_float (xdrs, &objp->altitude_wrt_ellipsoid)) + return FALSE; + if (!xdr_float (xdrs, &objp->altitude_wrt_mean_sea_level)) + return FALSE; + if (!xdr_float (xdrs, &objp->speed_horizontal)) + return FALSE; + if (!xdr_float (xdrs, &objp->speed_vertical)) + return FALSE; + if (!xdr_float (xdrs, &objp->heading)) + return FALSE; + if (!xdr_float (xdrs, &objp->hor_unc_circular)) + return FALSE; + if (!xdr_float (xdrs, &objp->hor_unc_ellipse_semi_major)) + return FALSE; + if (!xdr_float (xdrs, &objp->hor_unc_ellipse_semi_minor)) + return FALSE; + if (!xdr_float (xdrs, &objp->hor_unc_ellipse_orient_azimuth)) + return FALSE; + if (!xdr_float (xdrs, &objp->vert_unc)) + return FALSE; + if (!xdr_float (xdrs, &objp->speed_unc)) + return FALSE; + if (!xdr_float (xdrs, &objp->heading_unc)) + return FALSE; + if (!xdr_u_char (xdrs, &objp->confidence_horizontal)) + return FALSE; + if (!xdr_u_char (xdrs, &objp->confidence_vertical)) + return FALSE; + if (!xdr_float (xdrs, &objp->magnetic_deviation)) + return FALSE; + if (!xdr_rpc_loc_pos_technology_mask_type (xdrs, &objp->technology_mask)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_sv_system_e_type (XDR *xdrs, rpc_loc_sv_system_e_type *objp) +{ + register int32_t *buf; + + if (!xdr_enum (xdrs, (enum_t *) objp)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_sv_status_e_type (XDR *xdrs, rpc_loc_sv_status_e_type *objp) +{ + register int32_t *buf; + + if (!xdr_enum (xdrs, (enum_t *) objp)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_sv_info_valid_mask_type (XDR *xdrs, rpc_loc_sv_info_valid_mask_type *objp) +{ + register int32_t *buf; + + if (!xdr_rpc_uint32 (xdrs, objp)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_sv_info_s_type (XDR *xdrs, rpc_loc_sv_info_s_type *objp) +{ + register int32_t *buf; + + if (!xdr_rpc_loc_sv_info_valid_mask_type (xdrs, &objp->valid_mask)) + return FALSE; + if (!xdr_rpc_loc_sv_system_e_type (xdrs, &objp->system)) + return FALSE; + if (!xdr_rpc_uint8 (xdrs, &objp->prn)) + return FALSE; + if (!xdr_rpc_uint8 (xdrs, &objp->health_status)) + return FALSE; + if (!xdr_rpc_loc_sv_status_e_type (xdrs, &objp->process_status)) + return FALSE; + if (!xdr_rpc_boolean (xdrs, &objp->has_eph)) + return FALSE; + if (!xdr_rpc_boolean (xdrs, &objp->has_alm)) + return FALSE; + if (!xdr_float (xdrs, &objp->elevation)) + return FALSE; + if (!xdr_float (xdrs, &objp->azimuth)) + return FALSE; + if (!xdr_float (xdrs, &objp->snr)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_gnss_info_valid_mask_type (XDR *xdrs, rpc_loc_gnss_info_valid_mask_type *objp) +{ + register int32_t *buf; + + if (!xdr_rpc_uint32 (xdrs, objp)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_gnss_info_s_type (XDR *xdrs, rpc_loc_gnss_info_s_type *objp) +{ + register int32_t *buf; + + if (!xdr_rpc_loc_gnss_info_valid_mask_type (xdrs, &objp->valid_mask)) + return FALSE; + if (!xdr_float (xdrs, &objp->position_dop)) + return FALSE; + if (!xdr_float (xdrs, &objp->horizontal_dop)) + return FALSE; + if (!xdr_float (xdrs, &objp->vertical_dop)) + return FALSE; + if (!xdr_rpc_boolean (xdrs, &objp->altitude_assumed)) + return FALSE; + if (!xdr_rpc_uint16 (xdrs, &objp->sv_count)) + return FALSE; + if (!xdr_array (xdrs, (char **)&objp->sv_list.sv_list_val, (u_int *) &objp->sv_list.sv_list_len, 80, + sizeof (rpc_loc_sv_info_s_type), (xdrproc_t) xdr_rpc_loc_sv_info_s_type)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_nmea_report_s_type (XDR *xdrs, rpc_loc_nmea_report_s_type *objp) +{ + register int32_t *buf; + + int i; + if (!xdr_rpc_uint16 (xdrs, &objp->length)) + return FALSE; + if (!xdr_opaque (xdrs, objp->nmea_sentences, 200)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_status_event_e_type (XDR *xdrs, rpc_loc_status_event_e_type *objp) +{ + register int32_t *buf; + + if (!xdr_enum (xdrs, (enum_t *) objp)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_engine_state_e_type (XDR *xdrs, rpc_loc_engine_state_e_type *objp) +{ + register int32_t *buf; + + if (!xdr_enum (xdrs, (enum_t *) objp)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_fix_session_state_e_type (XDR *xdrs, rpc_loc_fix_session_state_e_type *objp) +{ + register int32_t *buf; + + if (!xdr_enum (xdrs, (enum_t *) objp)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_status_event_payload_u_type (XDR *xdrs, rpc_loc_status_event_payload_u_type *objp) +{ + register int32_t *buf; + + if (!xdr_rpc_loc_status_event_e_type (xdrs, &objp->disc)) + return FALSE; + switch (objp->disc) { + case RPC_LOC_STATUS_EVENT_ENGINE_STATE: + if (!xdr_rpc_loc_engine_state_e_type (xdrs, &objp->rpc_loc_status_event_payload_u_type_u.engine_state)) + return FALSE; + break; + case RPC_LOC_STATUS_EVENT_FIX_SESSION_STATE: + if (!xdr_rpc_loc_fix_session_state_e_type (xdrs, &objp->rpc_loc_status_event_payload_u_type_u.fix_session_state)) + return FALSE; + break; + default: + break; + } + return TRUE; +} + +bool_t +xdr_rpc_loc_status_event_s_type (XDR *xdrs, rpc_loc_status_event_s_type *objp) +{ + register int32_t *buf; + + if (!xdr_rpc_loc_status_event_e_type (xdrs, &objp->event)) + return FALSE; + if (!xdr_rpc_loc_status_event_payload_u_type (xdrs, &objp->payload)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_server_addr_e_type (XDR *xdrs, rpc_loc_server_addr_e_type *objp) +{ + register int32_t *buf; + + if (!xdr_enum (xdrs, (enum_t *) objp)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_server_addr_ipv4_type (XDR *xdrs, rpc_loc_server_addr_ipv4_type *objp) +{ + register int32_t *buf; + + if (!xdr_rpc_uint32 (xdrs, &objp->addr)) + return FALSE; + if (!xdr_rpc_uint16 (xdrs, &objp->port)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_server_addr_url_type (XDR *xdrs, rpc_loc_server_addr_url_type *objp) +{ + register int32_t *buf; + + int i; + if (!xdr_rpc_uint16 (xdrs, &objp->length)) + return FALSE; + if (!xdr_opaque (xdrs, objp->addr, 256)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_server_addr_ipv6_type (XDR *xdrs, rpc_loc_server_addr_ipv6_type *objp) +{ + register int32_t *buf; + + int i; + if (!xdr_vector (xdrs, (char *)objp->addr, 8, + sizeof (rpc_uint16), (xdrproc_t) xdr_rpc_uint16)) + return FALSE; + if (!xdr_rpc_uint32 (xdrs, &objp->port)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_server_addr_u_type (XDR *xdrs, rpc_loc_server_addr_u_type *objp) +{ + register int32_t *buf; + + if (!xdr_rpc_loc_server_addr_e_type (xdrs, &objp->disc)) + return FALSE; + switch (objp->disc) { + case RPC_LOC_SERVER_ADDR_IPV4: + if (!xdr_rpc_loc_server_addr_ipv4_type (xdrs, &objp->rpc_loc_server_addr_u_type_u.ipv4)) + return FALSE; + break; + case RPC_LOC_SERVER_ADDR_URL: + if (!xdr_rpc_loc_server_addr_url_type (xdrs, &objp->rpc_loc_server_addr_u_type_u.url)) + return FALSE; + break; + case RPC_LOC_SERVER_ADDR_IPV6: + if (!xdr_rpc_loc_server_addr_ipv6_type (xdrs, &objp->rpc_loc_server_addr_u_type_u.ipv6)) + return FALSE; + break; + default: + break; + } + return TRUE; +} + +bool_t +xdr_rpc_loc_server_info_s_type (XDR *xdrs, rpc_loc_server_info_s_type *objp) +{ + register int32_t *buf; + + if (!xdr_rpc_loc_server_addr_e_type (xdrs, &objp->addr_type)) + return FALSE; + if (!xdr_rpc_loc_server_addr_u_type (xdrs, &objp->addr_info)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_ni_notify_verify_e_type (XDR *xdrs, rpc_loc_ni_notify_verify_e_type *objp) +{ + register int32_t *buf; + + if (!xdr_enum (xdrs, (enum_t *) objp)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_ni_event_e_type (XDR *xdrs, rpc_loc_ni_event_e_type *objp) +{ + register int32_t *buf; + + if (!xdr_enum (xdrs, (enum_t *) objp)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_ni_datacoding_scheme_e_type (XDR *xdrs, rpc_loc_ni_datacoding_scheme_e_type *objp) +{ + register int32_t *buf; + + if (!xdr_enum (xdrs, (enum_t *) objp)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_ni_vx_requester_id_encoding_scheme_e_type (XDR *xdrs, rpc_loc_ni_vx_requester_id_encoding_scheme_e_type *objp) +{ + register int32_t *buf; + + if (!xdr_enum (xdrs, (enum_t *) objp)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_ni_vx_pos_mode_e_type (XDR *xdrs, rpc_loc_ni_vx_pos_mode_e_type *objp) +{ + register int32_t *buf; + + if (!xdr_enum (xdrs, (enum_t *) objp)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_ni_vx_requester_id_s_type (XDR *xdrs, rpc_loc_ni_vx_requester_id_s_type *objp) +{ + register int32_t *buf; + + int i; + if (!xdr_u_char (xdrs, &objp->requester_id_length)) + return FALSE; + if (!xdr_opaque (xdrs, objp->requester_id, 200)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_ni_vx_notify_verify_req_s_type (XDR *xdrs, rpc_loc_ni_vx_notify_verify_req_s_type *objp) +{ + register int32_t *buf; + + if (!xdr_rpc_loc_ni_notify_verify_e_type (xdrs, &objp->notification_priv_type)) + return FALSE; + if (!xdr_u_char (xdrs, &objp->pos_qos_incl)) + return FALSE; + if (!xdr_u_char (xdrs, &objp->pos_qos)) + return FALSE; + if (!xdr_rpc_uint32 (xdrs, &objp->num_fixes)) + return FALSE; + if (!xdr_rpc_uint32 (xdrs, &objp->tbf)) + return FALSE; + if (!xdr_rpc_loc_ni_vx_pos_mode_e_type (xdrs, &objp->pos_mode)) + return FALSE; + if (!xdr_rpc_loc_ni_vx_requester_id_encoding_scheme_e_type (xdrs, &objp->encoding_scheme)) + return FALSE; + if (!xdr_rpc_loc_ni_vx_requester_id_s_type (xdrs, &objp->requester_id)) + return FALSE; + if (!xdr_rpc_uint16 (xdrs, &objp->user_resp_timer_val)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_ni_supl_pos_method_e_type (XDR *xdrs, rpc_loc_ni_supl_pos_method_e_type *objp) +{ + register int32_t *buf; + + if (!xdr_enum (xdrs, (enum_t *) objp)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_ni_supl_slp_session_id_s_type (XDR *xdrs, rpc_loc_ni_supl_slp_session_id_s_type *objp) +{ + register int32_t *buf; + + int i; + if (!xdr_u_char (xdrs, &objp->presence)) + return FALSE; + if (!xdr_opaque (xdrs, objp->session_id, 4)) + return FALSE; + if (!xdr_rpc_loc_server_info_s_type (xdrs, &objp->slp_address)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_ni_requestor_id_s_type (XDR *xdrs, rpc_loc_ni_requestor_id_s_type *objp) +{ + register int32_t *buf; + + int i; + if (!xdr_u_char (xdrs, &objp->data_coding_scheme)) + return FALSE; + if (!xdr_opaque (xdrs, objp->requestor_id_string, 200)) + return FALSE; + if (!xdr_u_char (xdrs, &objp->string_len)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_ni_supl_client_name_s_type (XDR *xdrs, rpc_loc_ni_supl_client_name_s_type *objp) +{ + register int32_t *buf; + + int i; + if (!xdr_u_char (xdrs, &objp->data_coding_scheme)) + return FALSE; + if (!xdr_opaque (xdrs, objp->client_name_string, 64)) + return FALSE; + if (!xdr_u_char (xdrs, &objp->string_len)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_ni_supl_qop_s_type (XDR *xdrs, rpc_loc_ni_supl_qop_s_type *objp) +{ + register int32_t *buf; + + if (!xdr_u_char (xdrs, &objp->bit_mask)) + return FALSE; + if (!xdr_u_char (xdrs, &objp->horacc)) + return FALSE; + if (!xdr_u_char (xdrs, &objp->veracc)) + return FALSE; + if (!xdr_rpc_uint16 (xdrs, &objp->maxLocAge)) + return FALSE; + if (!xdr_u_char (xdrs, &objp->delay)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_ni_supl_notify_verify_req_s_type (XDR *xdrs, rpc_loc_ni_supl_notify_verify_req_s_type *objp) +{ + register int32_t *buf; + + int i; + if (!xdr_rpc_loc_ni_notify_verify_e_type (xdrs, &objp->notification_priv_type)) + return FALSE; + if (!xdr_rpc_uint16 (xdrs, &objp->flags)) + return FALSE; + if (!xdr_rpc_loc_ni_supl_slp_session_id_s_type (xdrs, &objp->supl_slp_session_id)) + return FALSE; + if (!xdr_opaque (xdrs, objp->supl_hash, 8)) + return FALSE; + if (!xdr_rpc_loc_ni_datacoding_scheme_e_type (xdrs, &objp->datacoding_scheme)) + return FALSE; + if (!xdr_rpc_loc_ni_supl_pos_method_e_type (xdrs, &objp->pos_method)) + return FALSE; + if (!xdr_rpc_loc_ni_requestor_id_s_type (xdrs, &objp->requestor_id)) + return FALSE; + if (!xdr_rpc_loc_ni_supl_client_name_s_type (xdrs, &objp->client_name)) + return FALSE; + if (!xdr_rpc_loc_ni_supl_qop_s_type (xdrs, &objp->supl_qop)) + return FALSE; + if (!xdr_rpc_uint16 (xdrs, &objp->user_response_timer)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_ni_ext_client_address_s_type (XDR *xdrs, rpc_loc_ni_ext_client_address_s_type *objp) +{ + register int32_t *buf; + + int i; + if (!xdr_u_char (xdrs, &objp->ext_client_address_len)) + return FALSE; + if (!xdr_opaque (xdrs, objp->ext_client_address, 20)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_ni_location_type_e_type (XDR *xdrs, rpc_loc_ni_location_type_e_type *objp) +{ + register int32_t *buf; + + if (!xdr_enum (xdrs, (enum_t *) objp)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_ni_deferred_location_s_type (XDR *xdrs, rpc_loc_ni_deferred_location_s_type *objp) +{ + register int32_t *buf; + + if (!xdr_u_char (xdrs, &objp->unused_bits)) + return FALSE; + if (!xdr_u_char (xdrs, &objp->ms_available)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_ni_codeword_string_s_type (XDR *xdrs, rpc_loc_ni_codeword_string_s_type *objp) +{ + register int32_t *buf; + + int i; + if (!xdr_u_char (xdrs, &objp->data_coding_scheme)) + return FALSE; + if (!xdr_opaque (xdrs, objp->lcs_codeword_string, 20)) + return FALSE; + if (!xdr_u_char (xdrs, &objp->string_len)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_ni_service_type_id_s_type (XDR *xdrs, rpc_loc_ni_service_type_id_s_type *objp) +{ + register int32_t *buf; + + if (!xdr_u_char (xdrs, &objp->lcs_service_type_id)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_ni_umts_cp_notify_verify_req_s_type (XDR *xdrs, rpc_loc_ni_umts_cp_notify_verify_req_s_type *objp) +{ + register int32_t *buf; + + int i; + if (!xdr_rpc_loc_ni_notify_verify_e_type (xdrs, &objp->notification_priv_type)) + return FALSE; + if (!xdr_u_char (xdrs, &objp->invoke_id)) + return FALSE; + if (!xdr_rpc_uint16 (xdrs, &objp->flags)) + return FALSE; + if (!xdr_u_char (xdrs, &objp->notification_length)) + return FALSE; + if (!xdr_opaque (xdrs, objp->notification_text, 64)) + return FALSE; + if (!xdr_rpc_loc_ni_datacoding_scheme_e_type (xdrs, &objp->datacoding_scheme)) + return FALSE; + if (!xdr_rpc_loc_ni_ext_client_address_s_type (xdrs, &objp->ext_client_address_data)) + return FALSE; + if (!xdr_rpc_loc_ni_location_type_e_type (xdrs, &objp->location_type)) + return FALSE; + if (!xdr_rpc_loc_ni_deferred_location_s_type (xdrs, &objp->deferred_location)) + return FALSE; + if (!xdr_rpc_loc_ni_requestor_id_s_type (xdrs, &objp->requestor_id)) + return FALSE; + if (!xdr_rpc_loc_ni_codeword_string_s_type (xdrs, &objp->codeword_string)) + return FALSE; + if (!xdr_rpc_loc_ni_service_type_id_s_type (xdrs, &objp->service_type_id)) + return FALSE; + if (!xdr_rpc_uint16 (xdrs, &objp->user_response_timer)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_ni_service_interaction_e_type (XDR *xdrs, rpc_loc_ni_service_interaction_e_type *objp) +{ + register int32_t *buf; + + if (!xdr_enum (xdrs, (enum_t *) objp)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_ni_vx_service_interaction_req_s_type (XDR *xdrs, rpc_loc_ni_vx_service_interaction_req_s_type *objp) +{ + register int32_t *buf; + + if (!xdr_rpc_loc_ni_vx_notify_verify_req_s_type (xdrs, &objp->ni_vx_req)) + return FALSE; + if (!xdr_rpc_loc_ni_service_interaction_e_type (xdrs, &objp->service_interation_type)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_ni_event_payload_u_type (XDR *xdrs, rpc_loc_ni_event_payload_u_type *objp) +{ + register int32_t *buf; + + if (!xdr_rpc_loc_ni_event_e_type (xdrs, &objp->disc)) + return FALSE; + switch (objp->disc) { + case RPC_LOC_NI_EVENT_VX_NOTIFY_VERIFY_REQ: + if (!xdr_rpc_loc_ni_vx_notify_verify_req_s_type (xdrs, &objp->rpc_loc_ni_event_payload_u_type_u.vx_req)) + return FALSE; + break; + case RPC_LOC_NI_EVENT_SUPL_NOTIFY_VERIFY_REQ: + if (!xdr_rpc_loc_ni_supl_notify_verify_req_s_type (xdrs, &objp->rpc_loc_ni_event_payload_u_type_u.supl_req)) + return FALSE; + break; + case RPC_LOC_NI_EVENT_UMTS_CP_NOTIFY_VERIFY_REQ: + if (!xdr_rpc_loc_ni_umts_cp_notify_verify_req_s_type (xdrs, &objp->rpc_loc_ni_event_payload_u_type_u.umts_cp_req)) + return FALSE; + break; + case RPC_LOC_NI_EVENT_VX_SERVICE_INTERACTION_REQ: + if (!xdr_rpc_loc_ni_vx_service_interaction_req_s_type (xdrs, &objp->rpc_loc_ni_event_payload_u_type_u.service_interaction_req)) + return FALSE; + break; + default: + break; + } + return TRUE; +} + +bool_t +xdr_rpc_loc_ni_event_s_type (XDR *xdrs, rpc_loc_ni_event_s_type *objp) +{ + register int32_t *buf; + + if (!xdr_rpc_loc_ni_event_e_type (xdrs, &objp->event)) + return FALSE; + if (!xdr_rpc_loc_ni_event_payload_u_type (xdrs, &objp->payload)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_assist_data_request_e_type (XDR *xdrs, rpc_loc_assist_data_request_e_type *objp) +{ + register int32_t *buf; + + if (!xdr_enum (xdrs, (enum_t *) objp)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_struct_loc_time_download_source_s_type_servers_ptr (XDR *xdrs, rpc_struct_loc_time_download_source_s_type_servers_ptr *objp) +{ + register int32_t *buf; + + if (!xdr_string (xdrs, objp, 256)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_struct_loc_time_download_source_s_type_servers (XDR *xdrs, rpc_struct_loc_time_download_source_s_type_servers objp) +{ + register int32_t *buf; + + if (!xdr_vector (xdrs, (char *)objp, 3, + sizeof (rpc_struct_loc_time_download_source_s_type_servers_ptr), (xdrproc_t) xdr_rpc_struct_loc_time_download_source_s_type_servers_ptr)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_time_download_source_s_type (XDR *xdrs, rpc_loc_time_download_source_s_type *objp) +{ + register int32_t *buf; + + if (!xdr_rpc_uint32 (xdrs, &objp->delay_threshold)) + return FALSE; + if (!xdr_rpc_struct_loc_time_download_source_s_type_servers (xdrs, objp->servers)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_struct_loc_predicted_orbits_data_source_s_type_servers_ptr (XDR *xdrs, rpc_struct_loc_predicted_orbits_data_source_s_type_servers_ptr *objp) +{ + register int32_t *buf; + + if (!xdr_string (xdrs, objp, 256)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_struct_loc_predicted_orbits_data_source_s_type_servers (XDR *xdrs, rpc_struct_loc_predicted_orbits_data_source_s_type_servers objp) +{ + register int32_t *buf; + + if (!xdr_vector (xdrs, (char *)objp, 3, + sizeof (rpc_struct_loc_predicted_orbits_data_source_s_type_servers_ptr), (xdrproc_t) xdr_rpc_struct_loc_predicted_orbits_data_source_s_type_servers_ptr)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_predicted_orbits_data_source_s_type (XDR *xdrs, rpc_loc_predicted_orbits_data_source_s_type *objp) +{ + register int32_t *buf; + + if (!xdr_rpc_uint32 (xdrs, &objp->max_file_size)) + return FALSE; + if (!xdr_rpc_uint32 (xdrs, &objp->max_part_size)) + return FALSE; + if (!xdr_rpc_struct_loc_predicted_orbits_data_source_s_type_servers (xdrs, objp->servers)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_pos_inj_request_s_type (XDR *xdrs, rpc_loc_pos_inj_request_s_type *objp) +{ + register int32_t *buf; + + if (!xdr_rpc_uint32 (xdrs, &objp->flags)) + return FALSE; + if (!xdr_double (xdrs, &objp->latitude)) + return FALSE; + if (!xdr_double (xdrs, &objp->longitude)) + return FALSE; + if (!xdr_rpc_uint32 (xdrs, &objp->position_uncertainty)) + return FALSE; + if (!xdr_rpc_uint64 (xdrs, &objp->timestamp)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_assist_data_request_payload_u_type (XDR *xdrs, rpc_loc_assist_data_request_payload_u_type *objp) +{ + register int32_t *buf; + + if (!xdr_rpc_loc_assist_data_request_e_type (xdrs, &objp->disc)) + return FALSE; + switch (objp->disc) { + case RPC_LOC_ASSIST_DATA_TIME_REQ: + if (!xdr_rpc_loc_time_download_source_s_type (xdrs, &objp->rpc_loc_assist_data_request_payload_u_type_u.time_download)) + return FALSE; + break; + case RPC_LOC_ASSIST_DATA_PREDICTED_ORBITS_REQ: + if (!xdr_rpc_loc_predicted_orbits_data_source_s_type (xdrs, &objp->rpc_loc_assist_data_request_payload_u_type_u.data_download)) + return FALSE; + break; + case RPC_LOC_ASSIST_DATA_POSITION_INJECTION_REQ: + if (!xdr_rpc_loc_pos_inj_request_s_type (xdrs, &objp->rpc_loc_assist_data_request_payload_u_type_u.pos_injection)) + return FALSE; + break; + default: + break; + } + return TRUE; +} + +bool_t +xdr_rpc_loc_assist_data_request_s_type (XDR *xdrs, rpc_loc_assist_data_request_s_type *objp) +{ + register int32_t *buf; + + if (!xdr_rpc_loc_assist_data_request_e_type (xdrs, &objp->event)) + return FALSE; + if (!xdr_rpc_loc_assist_data_request_payload_u_type (xdrs, &objp->payload)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_server_connection_handle (XDR *xdrs, rpc_loc_server_connection_handle *objp) +{ + register int32_t *buf; + + if (!xdr_rpc_uint32 (xdrs, objp)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_server_protocol_e_type (XDR *xdrs, rpc_loc_server_protocol_e_type *objp) +{ + register int32_t *buf; + + if (!xdr_enum (xdrs, (enum_t *) objp)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_server_connection_e_type (XDR *xdrs, rpc_loc_server_connection_e_type *objp) +{ + register int32_t *buf; + + if (!xdr_enum (xdrs, (enum_t *) objp)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_server_request_e_type (XDR *xdrs, rpc_loc_server_request_e_type *objp) +{ + register int32_t *buf; + + if (!xdr_enum (xdrs, (enum_t *) objp)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_server_open_req_s_type (XDR *xdrs, rpc_loc_server_open_req_s_type *objp) +{ + register int32_t *buf; + + if (!xdr_rpc_loc_server_connection_handle (xdrs, &objp->conn_handle)) + return FALSE; + if (!xdr_rpc_loc_server_protocol_e_type (xdrs, &objp->protocol)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_server_multi_open_req_s_type (XDR *xdrs, rpc_loc_server_multi_open_req_s_type *objp) +{ + register int32_t *buf; + + if (!xdr_rpc_loc_server_connection_handle (xdrs, &objp->conn_handle)) + return FALSE; + if (!xdr_rpc_loc_server_protocol_e_type (xdrs, &objp->protocol)) + return FALSE; + if (!xdr_rpc_loc_server_connection_e_type (xdrs, &objp->connection_type)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_server_close_req_s_type (XDR *xdrs, rpc_loc_server_close_req_s_type *objp) +{ + register int32_t *buf; + + if (!xdr_rpc_loc_server_connection_handle (xdrs, &objp->conn_handle)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_server_request_u_type (XDR *xdrs, rpc_loc_server_request_u_type *objp) +{ + register int32_t *buf; + + if (!xdr_rpc_loc_server_request_e_type (xdrs, &objp->disc)) + return FALSE; + switch (objp->disc) { + case RPC_LOC_SERVER_REQUEST_OPEN: + if (!xdr_rpc_loc_server_open_req_s_type (xdrs, &objp->rpc_loc_server_request_u_type_u.open_req)) + return FALSE; + break; + case RPC_LOC_SERVER_REQUEST_CLOSE: + if (!xdr_rpc_loc_server_close_req_s_type (xdrs, &objp->rpc_loc_server_request_u_type_u.close_req)) + return FALSE; + break; + case RPC_LOC_SERVER_REQUEST_MULTI_OPEN: + if (!xdr_rpc_loc_server_multi_open_req_s_type (xdrs, &objp->rpc_loc_server_request_u_type_u.multi_open_req)) + return FALSE; + break; + default: + break; + } + return TRUE; +} + +bool_t +xdr_rpc_loc_server_request_s_type (XDR *xdrs, rpc_loc_server_request_s_type *objp) +{ + register int32_t *buf; + + if (!xdr_rpc_loc_server_request_e_type (xdrs, &objp->event)) + return FALSE; + if (!xdr_rpc_loc_server_request_u_type (xdrs, &objp->payload)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_qwip_request_e_type (XDR *xdrs, rpc_loc_qwip_request_e_type *objp) +{ + register int32_t *buf; + + if (!xdr_enum (xdrs, (enum_t *) objp)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_qwip_request_s_type (XDR *xdrs, rpc_loc_qwip_request_s_type *objp) +{ + register int32_t *buf; + + if (!xdr_rpc_loc_qwip_request_e_type (xdrs, &objp->request_type)) + return FALSE; + if (!xdr_rpc_uint16 (xdrs, &objp->tbf_ms)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_reserved_payload_s_type (XDR *xdrs, rpc_loc_reserved_payload_s_type *objp) +{ + register int32_t *buf; + + if (!xdr_rpc_uint16 (xdrs, &objp->data_size)) + return FALSE; + if (!xdr_bytes (xdrs, (char **)&objp->data.data_val, (u_int *) &objp->data.data_len, ~0)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_ioctl_e_type (XDR *xdrs, rpc_loc_ioctl_e_type *objp) +{ + register int32_t *buf; + + if (!xdr_enum (xdrs, (enum_t *) objp)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_api_version_s_type (XDR *xdrs, rpc_loc_api_version_s_type *objp) +{ + register int32_t *buf; + + if (!xdr_u_char (xdrs, &objp->major)) + return FALSE; + if (!xdr_u_char (xdrs, &objp->minor)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_fix_recurrence_e_type (XDR *xdrs, rpc_loc_fix_recurrence_e_type *objp) +{ + register int32_t *buf; + + if (!xdr_enum (xdrs, (enum_t *) objp)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_operation_mode_e_type (XDR *xdrs, rpc_loc_operation_mode_e_type *objp) +{ + register int32_t *buf; + + if (!xdr_enum (xdrs, (enum_t *) objp)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_notify_e_type (XDR *xdrs, rpc_loc_notify_e_type *objp) +{ + register int32_t *buf; + + if (!xdr_enum (xdrs, (enum_t *) objp)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_fix_criteria_s_type (XDR *xdrs, rpc_loc_fix_criteria_s_type *objp) +{ + register int32_t *buf; + + if (!xdr_rpc_uint32 (xdrs, &objp->valid_mask)) + return FALSE; + if (!xdr_rpc_loc_fix_recurrence_e_type (xdrs, &objp->recurrence_type)) + return FALSE; + if (!xdr_rpc_loc_operation_mode_e_type (xdrs, &objp->preferred_operation_mode)) + return FALSE; + if (!xdr_rpc_uint32 (xdrs, &objp->preferred_accuracy)) + return FALSE; + if (!xdr_rpc_uint32 (xdrs, &objp->preferred_response_time)) + return FALSE; + if (!xdr_rpc_boolean (xdrs, &objp->intermediate_pos_report_enabled)) + return FALSE; + if (!xdr_rpc_loc_notify_e_type (xdrs, &objp->notify_type)) + return FALSE; + if (!xdr_rpc_uint32 (xdrs, &objp->min_interval)) + return FALSE; + if (!xdr_float (xdrs, &objp->min_distance)) + return FALSE; + if (!xdr_rpc_uint32 (xdrs, &objp->min_dist_sample_interval)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_ni_user_resp_e_type (XDR *xdrs, rpc_loc_ni_user_resp_e_type *objp) +{ + register int32_t *buf; + + if (!xdr_enum (xdrs, (enum_t *) objp)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_user_verify_s_type (XDR *xdrs, rpc_loc_user_verify_s_type *objp) +{ + register int32_t *buf; + + if (!xdr_rpc_loc_ni_user_resp_e_type (xdrs, &objp->user_resp)) + return FALSE; + if (!xdr_rpc_loc_ni_event_s_type (xdrs, &objp->ni_event_pass_back)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_predicted_orbits_data_format_e_type (XDR *xdrs, rpc_loc_predicted_orbits_data_format_e_type *objp) +{ + register int32_t *buf; + + if (!xdr_enum (xdrs, (enum_t *) objp)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_predicted_orbits_data_s_type (XDR *xdrs, rpc_loc_predicted_orbits_data_s_type *objp) +{ + register int32_t *buf; + + if (!xdr_rpc_loc_predicted_orbits_data_format_e_type (xdrs, &objp->format_type)) + return FALSE; + if (!xdr_rpc_uint32 (xdrs, &objp->total_size)) + return FALSE; + if (!xdr_rpc_uint8 (xdrs, &objp->total_parts)) + return FALSE; + if (!xdr_rpc_uint8 (xdrs, &objp->part)) + return FALSE; + if (!xdr_rpc_uint16 (xdrs, &objp->part_len)) + return FALSE; + if (!xdr_bytes (xdrs, (char **)&objp->data_ptr.data_ptr_val, (u_int *) &objp->data_ptr.data_ptr_len, ~0)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_predicted_orbits_data_validity_report_s_type (XDR *xdrs, rpc_loc_predicted_orbits_data_validity_report_s_type *objp) +{ + register int32_t *buf; + + if (!xdr_rpc_uint64 (xdrs, &objp->start_time_utc)) + return FALSE; + if (!xdr_rpc_uint16 (xdrs, &objp->valid_duration_hrs)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_predicted_orbits_auto_download_config_s_type (XDR *xdrs, rpc_loc_predicted_orbits_auto_download_config_s_type *objp) +{ + register int32_t *buf; + + if (!xdr_rpc_boolean (xdrs, &objp->enable)) + return FALSE; + if (!xdr_u_char (xdrs, &objp->auto_check_every_hrs)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_assist_data_time_s_type (XDR *xdrs, rpc_loc_assist_data_time_s_type *objp) +{ + register int32_t *buf; + + if (!xdr_rpc_uint64 (xdrs, &objp->time_utc)) + return FALSE; + if (!xdr_rpc_uint32 (xdrs, &objp->uncertainty)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_assist_pos_valid_mask_type (XDR *xdrs, rpc_loc_assist_pos_valid_mask_type *objp) +{ + register int32_t *buf; + + if (!xdr_rpc_uint64 (xdrs, objp)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_assist_data_pos_s_type (XDR *xdrs, rpc_loc_assist_data_pos_s_type *objp) +{ + register int32_t *buf; + + if (!xdr_rpc_loc_assist_pos_valid_mask_type (xdrs, &objp->valid_mask)) + return FALSE; + if (!xdr_rpc_uint64 (xdrs, &objp->timestamp_utc)) + return FALSE; + if (!xdr_double (xdrs, &objp->latitude)) + return FALSE; + if (!xdr_double (xdrs, &objp->longitude)) + return FALSE; + if (!xdr_float (xdrs, &objp->altitude_wrt_ellipsoid)) + return FALSE; + if (!xdr_float (xdrs, &objp->altitude_wrt_mean_sea_level)) + return FALSE; + if (!xdr_float (xdrs, &objp->hor_unc_circular)) + return FALSE; + if (!xdr_float (xdrs, &objp->vert_unc)) + return FALSE; + if (!xdr_u_char (xdrs, &objp->confidence_horizontal)) + return FALSE; + if (!xdr_u_char (xdrs, &objp->confidence_vertical)) + return FALSE; + if (!xdr_rpc_int32 (xdrs, &objp->timestamp_age)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_server_open_status_e_type (XDR *xdrs, rpc_loc_server_open_status_e_type *objp) +{ + register int32_t *buf; + + if (!xdr_enum (xdrs, (enum_t *) objp)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_server_pdp_type_e_type (XDR *xdrs, rpc_loc_server_pdp_type_e_type *objp) +{ + register int32_t *buf; + + if (!xdr_enum (xdrs, (enum_t *) objp)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_server_open_status_s_type (XDR *xdrs, rpc_loc_server_open_status_s_type *objp) +{ + register int32_t *buf; + + int i; + if (!xdr_rpc_loc_server_connection_handle (xdrs, &objp->conn_handle)) + return FALSE; + if (!xdr_rpc_loc_server_open_status_e_type (xdrs, &objp->open_status)) + return FALSE; + if (!xdr_opaque (xdrs, objp->apn_name, 100)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_server_multi_open_status_s_type (XDR *xdrs, rpc_loc_server_multi_open_status_s_type *objp) +{ + register int32_t *buf; + + int i; + if (!xdr_rpc_loc_server_connection_handle (xdrs, &objp->conn_handle)) + return FALSE; + if (!xdr_rpc_loc_server_open_status_e_type (xdrs, &objp->open_status)) + return FALSE; + if (!xdr_rpc_loc_server_pdp_type_e_type (xdrs, &objp->pdp_type)) + return FALSE; + if (!xdr_opaque (xdrs, objp->apn_name, 100)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_server_close_status_e_type (XDR *xdrs, rpc_loc_server_close_status_e_type *objp) +{ + register int32_t *buf; + + if (!xdr_enum (xdrs, (enum_t *) objp)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_server_close_status_s_type (XDR *xdrs, rpc_loc_server_close_status_s_type *objp) +{ + register int32_t *buf; + + if (!xdr_rpc_loc_server_connection_handle (xdrs, &objp->conn_handle)) + return FALSE; + if (!xdr_rpc_loc_server_close_status_e_type (xdrs, &objp->close_status)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_wiper_fix_time_s_type (XDR *xdrs, rpc_loc_wiper_fix_time_s_type *objp) +{ + register int32_t *buf; + + if (!xdr_rpc_uint32 (xdrs, &objp->slow_clock_count)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_wiper_fix_pos_s_type (XDR *xdrs, rpc_loc_wiper_fix_pos_s_type *objp) +{ + register int32_t *buf; + + if (!xdr_rpc_int32 (xdrs, &objp->lat)) + return FALSE; + if (!xdr_rpc_int32 (xdrs, &objp->lon)) + return FALSE; + if (!xdr_rpc_uint16 (xdrs, &objp->HEPE)) + return FALSE; + if (!xdr_rpc_uint8 (xdrs, &objp->num_of_aps_used)) + return FALSE; + if (!xdr_rpc_uint8 (xdrs, &objp->fix_error_code)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_wiper_ap_info_s_type (XDR *xdrs, rpc_loc_wiper_ap_info_s_type *objp) +{ + register int32_t *buf; + + int i; + if (!xdr_opaque (xdrs, objp->mac_addr, 6)) + return FALSE; + if (!xdr_rpc_int32 (xdrs, &objp->rssi)) + return FALSE; + if (!xdr_rpc_uint16 (xdrs, &objp->channel)) + return FALSE; + if (!xdr_rpc_uint8 (xdrs, &objp->ap_qualifier)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_wiper_ap_set_s_type (XDR *xdrs, rpc_loc_wiper_ap_set_s_type *objp) +{ + register int32_t *buf; + + int i; + if (!xdr_rpc_uint8 (xdrs, &objp->num_of_aps)) + return FALSE; + if (!xdr_vector (xdrs, (char *)objp->ap_info, 50, + sizeof (rpc_loc_wiper_ap_info_s_type), (xdrproc_t) xdr_rpc_loc_wiper_ap_info_s_type)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_wiper_position_report_s_type (XDR *xdrs, rpc_loc_wiper_position_report_s_type *objp) +{ + register int32_t *buf; + + if (!xdr_rpc_uint8 (xdrs, &objp->wiper_valid_info_flag)) + return FALSE; + if (!xdr_rpc_loc_wiper_fix_time_s_type (xdrs, &objp->wiper_fix_time)) + return FALSE; + if (!xdr_rpc_loc_wiper_fix_pos_s_type (xdrs, &objp->wiper_fix_position)) + return FALSE; + if (!xdr_rpc_loc_wiper_ap_set_s_type (xdrs, &objp->wiper_ap_set)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_wiper_status_e_type (XDR *xdrs, rpc_loc_wiper_status_e_type *objp) +{ + register int32_t *buf; + + if (!xdr_enum (xdrs, (enum_t *) objp)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_fs_operation_e_type (XDR *xdrs, rpc_loc_fs_operation_e_type *objp) +{ + register int32_t *buf; + + if (!xdr_enum (xdrs, (enum_t *) objp)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_efs_data_s_type (XDR *xdrs, rpc_loc_efs_data_s_type *objp) +{ + register int32_t *buf; + + int i; + if (!xdr_opaque (xdrs, objp->filename, 64)) + return FALSE; + if (!xdr_rpc_loc_fs_operation_e_type (xdrs, &objp->operation)) + return FALSE; + if (!xdr_rpc_uint32 (xdrs, &objp->total_size)) + return FALSE; + if (!xdr_bytes (xdrs, (char **)&objp->data_ptr.data_ptr_val, (u_int *) &objp->data_ptr.data_ptr_len, ~0)) + return FALSE; + if (!xdr_rpc_uint32 (xdrs, &objp->part_len)) + return FALSE; + if (!xdr_rpc_uint8 (xdrs, &objp->part)) + return FALSE; + if (!xdr_rpc_uint8 (xdrs, &objp->total_parts)) + return FALSE; + if (!xdr_rpc_uint32 (xdrs, &objp->reserved)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_error_estimate_config_e_type (XDR *xdrs, rpc_loc_error_estimate_config_e_type *objp) +{ + register int32_t *buf; + + if (!xdr_enum (xdrs, (enum_t *) objp)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_apn_profiles_type (XDR *xdrs, rpc_loc_apn_profiles_type *objp) +{ + register int32_t *buf; + + int i; + if (!xdr_rpc_uint32 (xdrs, &objp->srv_system_type)) + return FALSE; + if (!xdr_rpc_uint32 (xdrs, &objp->pdp_type)) + return FALSE; + if (!xdr_rpc_uint32 (xdrs, &objp->reserved)) + return FALSE; + if (!xdr_opaque (xdrs, objp->apn_name, 100)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_lock_e_type (XDR *xdrs, rpc_loc_lock_e_type *objp) +{ + register int32_t *buf; + + if (!xdr_enum (xdrs, (enum_t *) objp)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_nmea_sentence_type (XDR *xdrs, rpc_loc_nmea_sentence_type *objp) +{ + register int32_t *buf; + + if (!xdr_rpc_uint32 (xdrs, objp)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_assist_data_type (XDR *xdrs, rpc_loc_assist_data_type *objp) +{ + register int32_t *buf; + + if (!xdr_rpc_uint32 (xdrs, objp)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_assist_data_delete_s_type (XDR *xdrs, rpc_loc_assist_data_delete_s_type *objp) +{ + register int32_t *buf; + + int i; + if (!xdr_rpc_loc_assist_data_type (xdrs, &objp->type)) + return FALSE; + if (!xdr_vector (xdrs, (char *)objp->reserved, 8, + sizeof (rpc_uint32), (xdrproc_t) xdr_rpc_uint32)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_ioctl_data_u_type (XDR *xdrs, rpc_loc_ioctl_data_u_type *objp) +{ + register int32_t *buf; + + if (!xdr_rpc_loc_ioctl_e_type (xdrs, &objp->disc)) + return FALSE; + switch (objp->disc) { + case RPC_LOC_IOCTL_SET_FIX_CRITERIA: + if (!xdr_rpc_loc_fix_criteria_s_type (xdrs, &objp->rpc_loc_ioctl_data_u_type_u.fix_criteria)) + return FALSE; + break; + case RPC_LOC_IOCTL_INFORM_NI_USER_RESPONSE: + if (!xdr_rpc_loc_user_verify_s_type (xdrs, &objp->rpc_loc_ioctl_data_u_type_u.user_verify_resp)) + return FALSE; + break; + case RPC_LOC_IOCTL_INJECT_PREDICTED_ORBITS_DATA: + if (!xdr_rpc_loc_predicted_orbits_data_s_type (xdrs, &objp->rpc_loc_ioctl_data_u_type_u.predicted_orbits_data)) + return FALSE; + break; + case RPC_LOC_IOCTL_SET_PREDICTED_ORBITS_DATA_AUTO_DOWNLOAD: + if (!xdr_rpc_loc_predicted_orbits_auto_download_config_s_type (xdrs, &objp->rpc_loc_ioctl_data_u_type_u.predicted_orbits_auto_download)) + return FALSE; + break; + case RPC_LOC_IOCTL_INJECT_UTC_TIME: + if (!xdr_rpc_loc_assist_data_time_s_type (xdrs, &objp->rpc_loc_ioctl_data_u_type_u.assistance_data_time)) + return FALSE; + break; + case RPC_LOC_IOCTL_INJECT_POSITION: + if (!xdr_rpc_loc_assist_data_pos_s_type (xdrs, &objp->rpc_loc_ioctl_data_u_type_u.assistance_data_position)) + return FALSE; + break; + case RPC_LOC_IOCTL_INFORM_SERVER_OPEN_STATUS: + if (!xdr_rpc_loc_server_open_status_s_type (xdrs, &objp->rpc_loc_ioctl_data_u_type_u.conn_open_status)) + return FALSE; + break; + case RPC_LOC_IOCTL_INFORM_SERVER_CLOSE_STATUS: + if (!xdr_rpc_loc_server_close_status_s_type (xdrs, &objp->rpc_loc_ioctl_data_u_type_u.conn_close_status)) + return FALSE; + break; + case RPC_LOC_IOCTL_SEND_WIPER_POSITION_REPORT: + if (!xdr_rpc_loc_wiper_position_report_s_type (xdrs, &objp->rpc_loc_ioctl_data_u_type_u.wiper_pos)) + return FALSE; + break; + case RPC_LOC_IOCTL_NOTIFY_WIPER_STATUS: + if (!xdr_rpc_loc_wiper_status_e_type (xdrs, &objp->rpc_loc_ioctl_data_u_type_u.wiper_status)) + return FALSE; + break; + case RPC_LOC_IOCTL_SET_ENGINE_LOCK: + if (!xdr_rpc_loc_lock_e_type (xdrs, &objp->rpc_loc_ioctl_data_u_type_u.engine_lock)) + return FALSE; + break; + case RPC_LOC_IOCTL_SET_SBAS_CONFIG: + if (!xdr_rpc_boolean (xdrs, &objp->rpc_loc_ioctl_data_u_type_u.sbas_mode)) + return FALSE; + break; + case RPC_LOC_IOCTL_SET_NMEA_TYPES: + if (!xdr_rpc_loc_nmea_sentence_type (xdrs, &objp->rpc_loc_ioctl_data_u_type_u.nmea_types)) + return FALSE; + break; + case RPC_LOC_IOCTL_SET_ON_DEMAND_LPM: + if (!xdr_rpc_boolean (xdrs, &objp->rpc_loc_ioctl_data_u_type_u.on_demand_lpm)) + return FALSE; + break; + case RPC_LOC_IOCTL_SET_CDMA_PDE_SERVER_ADDR: + case RPC_LOC_IOCTL_SET_CDMA_MPC_SERVER_ADDR: + case RPC_LOC_IOCTL_SET_UMTS_SLP_SERVER_ADDR: + case RPC_LOC_IOCTL_SET_CUSTOM_PDE_SERVER_ADDR: + if (!xdr_rpc_loc_server_info_s_type (xdrs, &objp->rpc_loc_ioctl_data_u_type_u.server_addr)) + return FALSE; + break; + case RPC_LOC_IOCTL_DELETE_ASSIST_DATA: + if (!xdr_rpc_loc_assist_data_delete_s_type (xdrs, &objp->rpc_loc_ioctl_data_u_type_u.assist_data_delete)) + return FALSE; + break; + case RPC_LOC_IOCTL_ACCESS_EFS_DATA: + if (!xdr_rpc_loc_efs_data_s_type (xdrs, &objp->rpc_loc_ioctl_data_u_type_u.efs_data)) + return FALSE; + break; + case RPC_LOC_IOCTL_ERROR_ESTIMATE_CONFIG: + if (!xdr_rpc_loc_error_estimate_config_e_type (xdrs, &objp->rpc_loc_ioctl_data_u_type_u.error_estimate_config)) + return FALSE; + break; + case RPC_LOC_IOCTL_SET_XTRA_T_SESSION_CONTROL: + if (!xdr_rpc_uint8 (xdrs, &objp->rpc_loc_ioctl_data_u_type_u.xtra_t_session_control)) + return FALSE; + break; + case RPC_LOC_IOCTL_SET_LBS_APN_PROFILE: + case RPC_LOC_IOCTL_SET_XTRA_APN_PROFILE: + if (!xdr_vector (xdrs, (char *)objp->rpc_loc_ioctl_data_u_type_u.apn_profiles, 6, + sizeof (rpc_loc_apn_profiles_type), (xdrproc_t) xdr_rpc_loc_apn_profiles_type)) + return FALSE; + break; + case RPC_LOC_IOCTL_SET_DATA_ENABLE: + if (!xdr_rpc_boolean (xdrs, &objp->rpc_loc_ioctl_data_u_type_u.data_enable)) + return FALSE; + break; + case RPC_LOC_IOCTL_SET_SUPL_VERSION: + if (!xdr_rpc_uint32 (xdrs, &objp->rpc_loc_ioctl_data_u_type_u.supl_version)) + return FALSE; + break; + case RPC_LOC_IOCTL_INFORM_SERVER_MULTI_OPEN_STATUS: + if (!xdr_rpc_loc_server_multi_open_status_s_type (xdrs, &objp->rpc_loc_ioctl_data_u_type_u.multi_conn_open_status)) + return FALSE; + break; + case RPC_LOC_IOCTL_RESERVED_CMD: + if (!xdr_rpc_loc_reserved_payload_s_type (xdrs, &objp->rpc_loc_ioctl_data_u_type_u.reserved)) + return FALSE; + break; + default: + break; + } + return TRUE; +} + +bool_t +xdr_rpc_loc_ioctl_callback_data_u_type (XDR *xdrs, rpc_loc_ioctl_callback_data_u_type *objp) +{ + register int32_t *buf; + + if (!xdr_rpc_loc_ioctl_e_type (xdrs, &objp->disc)) + return FALSE; + switch (objp->disc) { + case RPC_LOC_IOCTL_GET_API_VERSION: + if (!xdr_rpc_loc_api_version_s_type (xdrs, &objp->rpc_loc_ioctl_callback_data_u_type_u.api_version)) + return FALSE; + break; + case RPC_LOC_IOCTL_GET_FIX_CRITERIA: + if (!xdr_rpc_loc_fix_criteria_s_type (xdrs, &objp->rpc_loc_ioctl_callback_data_u_type_u.fix_criteria)) + return FALSE; + break; + case RPC_LOC_IOCTL_GET_ENGINE_LOCK: + if (!xdr_rpc_loc_lock_e_type (xdrs, &objp->rpc_loc_ioctl_callback_data_u_type_u.engine_lock)) + return FALSE; + break; + case RPC_LOC_IOCTL_GET_SBAS_CONFIG: + if (!xdr_rpc_boolean (xdrs, &objp->rpc_loc_ioctl_callback_data_u_type_u.sbas_mode)) + return FALSE; + break; + case RPC_LOC_IOCTL_GET_NMEA_TYPES: + if (!xdr_rpc_loc_nmea_sentence_type (xdrs, &objp->rpc_loc_ioctl_callback_data_u_type_u.nmea_types)) + return FALSE; + break; + case RPC_LOC_IOCTL_GET_ON_DEMAND_LPM: + if (!xdr_rpc_boolean (xdrs, &objp->rpc_loc_ioctl_callback_data_u_type_u.on_demand_lpm)) + return FALSE; + break; + case RPC_LOC_IOCTL_GET_CDMA_PDE_SERVER_ADDR: + case RPC_LOC_IOCTL_GET_CDMA_MPC_SERVER_ADDR: + case RPC_LOC_IOCTL_GET_UMTS_SLP_SERVER_ADDR: + case RPC_LOC_IOCTL_GET_CUSTOM_PDE_SERVER_ADDR: + if (!xdr_rpc_loc_server_info_s_type (xdrs, &objp->rpc_loc_ioctl_callback_data_u_type_u.server_addr)) + return FALSE; + break; + case RPC_LOC_IOCTL_QUERY_PREDICTED_ORBITS_DATA_SOURCE: + if (!xdr_rpc_loc_predicted_orbits_data_source_s_type (xdrs, &objp->rpc_loc_ioctl_callback_data_u_type_u.predicted_orbits_data_source)) + return FALSE; + break; + case RPC_LOC_IOCTL_QUERY_PREDICTED_ORBITS_DATA_VALIDITY: + if (!xdr_rpc_loc_predicted_orbits_data_validity_report_s_type (xdrs, &objp->rpc_loc_ioctl_callback_data_u_type_u.predicted_orbits_data_validity)) + return FALSE; + break; + case RPC_LOC_IOCTL_GET_XTRA_T_SESSION_CONTROL: + if (!xdr_rpc_uint8 (xdrs, &objp->rpc_loc_ioctl_callback_data_u_type_u.xtra_t_session_control)) + return FALSE; + break; + case RPC_LOC_IOCTL_GET_LBS_APN_PROFILE: + case RPC_LOC_IOCTL_GET_XTRA_APN_PROFILE: + if (!xdr_vector (xdrs, (char *)objp->rpc_loc_ioctl_callback_data_u_type_u.apn_profiles, 6, + sizeof (rpc_loc_apn_profiles_type), (xdrproc_t) xdr_rpc_loc_apn_profiles_type)) + return FALSE; + break; + case RPC_LOC_IOCTL_GET_SUPL_VERSION: + if (!xdr_rpc_uint32 (xdrs, &objp->rpc_loc_ioctl_callback_data_u_type_u.supl_version)) + return FALSE; + break; + default: + break; + } + return TRUE; +} + +bool_t +xdr_rpc_loc_ioctl_callback_s_type (XDR *xdrs, rpc_loc_ioctl_callback_s_type *objp) +{ + register int32_t *buf; + + if (!xdr_rpc_loc_ioctl_e_type (xdrs, &objp->type)) + return FALSE; + if (!xdr_rpc_int32 (xdrs, &objp->status)) + return FALSE; + if (!xdr_rpc_loc_ioctl_callback_data_u_type (xdrs, &objp->data)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_event_payload_u_type (XDR *xdrs, rpc_loc_event_payload_u_type *objp) +{ + register int32_t *buf; + + if (!xdr_u_quad_t (xdrs, &objp->disc)) + return FALSE; + switch (objp->disc) { + case RPC_LOC_EVENT_PARSED_POSITION_REPORT: + if (!xdr_rpc_loc_parsed_position_s_type (xdrs, &objp->rpc_loc_event_payload_u_type_u.parsed_location_report)) + return FALSE; + break; + case RPC_LOC_EVENT_SATELLITE_REPORT: + if (!xdr_rpc_loc_gnss_info_s_type (xdrs, &objp->rpc_loc_event_payload_u_type_u.gnss_report)) + return FALSE; + break; + case RPC_LOC_EVENT_NMEA_POSITION_REPORT: + case RPC_LOC_EVENT_NMEA_1HZ_REPORT: + if (!xdr_rpc_loc_nmea_report_s_type (xdrs, &objp->rpc_loc_event_payload_u_type_u.nmea_report)) + return FALSE; + break; + case RPC_LOC_EVENT_NI_NOTIFY_VERIFY_REQUEST: + if (!xdr_rpc_loc_ni_event_s_type (xdrs, &objp->rpc_loc_event_payload_u_type_u.ni_request)) + return FALSE; + break; + case RPC_LOC_EVENT_ASSISTANCE_DATA_REQUEST: + if (!xdr_rpc_loc_assist_data_request_s_type (xdrs, &objp->rpc_loc_event_payload_u_type_u.assist_data_request)) + return FALSE; + break; + case RPC_LOC_EVENT_LOCATION_SERVER_REQUEST: + if (!xdr_rpc_loc_server_request_s_type (xdrs, &objp->rpc_loc_event_payload_u_type_u.loc_server_request)) + return FALSE; + break; + case RPC_LOC_EVENT_IOCTL_REPORT: + if (!xdr_rpc_loc_ioctl_callback_s_type (xdrs, &objp->rpc_loc_event_payload_u_type_u.ioctl_report)) + return FALSE; + break; + case RPC_LOC_EVENT_STATUS_REPORT: + if (!xdr_rpc_loc_status_event_s_type (xdrs, &objp->rpc_loc_event_payload_u_type_u.status_report)) + return FALSE; + break; + case RPC_LOC_EVENT_WPS_NEEDED_REQUEST: + if (!xdr_rpc_loc_qwip_request_s_type (xdrs, &objp->rpc_loc_event_payload_u_type_u.qwip_request)) + return FALSE; + break; + case RPC_LOC_EVENT_RESERVED: + if (!xdr_rpc_loc_reserved_payload_s_type (xdrs, &objp->rpc_loc_event_payload_u_type_u.reserved)) + return FALSE; + break; + default: + break; + } + return TRUE; +} diff --git a/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-stub/src/loc_api_rpcgen_xdr.c b/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-stub/src/loc_api_rpcgen_xdr.c new file mode 100644 index 000000000..a0fdcabef --- /dev/null +++ b/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-stub/src/loc_api_rpcgen_xdr.c @@ -0,0 +1,199 @@ +/* Copyright (c) 2011, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/* + * Please do not edit this file. + * It was generated using rpcgen. + */ + +#include "loc_api_rpcgen_rpc.h" + +bool_t +xdr_rpc_loc_api_api_versions_return_type (XDR *xdrs, rpc_loc_api_api_versions_return_type *objp) +{ +; + + if (!xdr_array (xdrs, (char **)&objp->rpc_loc_api_api_versions_return_type_val, (u_int *) &objp->rpc_loc_api_api_versions_return_type_len, ~0, + sizeof (rpc_uint32), (xdrproc_t) xdr_rpc_uint32)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_event_cb_f_type (XDR *xdrs, rpc_loc_event_cb_f_type *objp) +{ +; + + if (!xdr_rpc_uint32 (xdrs, objp)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_open_args (XDR *xdrs, rpc_loc_open_args *objp) +{ +; + + if (!xdr_rpc_loc_event_mask_type (xdrs, &objp->event_reg_mask)) + return FALSE; + if (!xdr_rpc_loc_event_cb_f_type (xdrs, &objp->event_callback)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_close_args (XDR *xdrs, rpc_loc_close_args *objp) +{ +; + + if (!xdr_rpc_loc_client_handle_type (xdrs, &objp->handle)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_start_fix_args (XDR *xdrs, rpc_loc_start_fix_args *objp) +{ +; + + if (!xdr_rpc_loc_client_handle_type (xdrs, &objp->handle)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_stop_fix_args (XDR *xdrs, rpc_loc_stop_fix_args *objp) +{ +; + + if (!xdr_rpc_loc_client_handle_type (xdrs, &objp->handle)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_ioctl_args (XDR *xdrs, rpc_loc_ioctl_args *objp) +{ +; + + if (!xdr_rpc_loc_client_handle_type (xdrs, &objp->handle)) + return FALSE; + if (!xdr_rpc_loc_ioctl_e_type (xdrs, &objp->ioctl_type)) + return FALSE; + if (!xdr_pointer (xdrs, (char **)&objp->ioctl_data, sizeof (rpc_loc_ioctl_data_u_type), (xdrproc_t) xdr_rpc_loc_ioctl_data_u_type)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_api_api_version_s_args (XDR *xdrs, rpc_loc_api_api_version_s_args *objp) +{ +; + + if (!xdr_rpc_boolean (xdrs, &objp->len_not_null)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_api_rpc_glue_code_info_remote_rets (XDR *xdrs, rpc_loc_api_rpc_glue_code_info_remote_rets *objp) +{ +; + + if (!xdr_rpc_uint32 (xdrs, &objp->toolvers)) + return FALSE; + if (!xdr_rpc_uint32 (xdrs, &objp->features)) + return FALSE; + if (!xdr_rpc_uint32 (xdrs, &objp->proghash)) + return FALSE; + if (!xdr_rpc_uint32 (xdrs, &objp->cbproghash)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_open_rets (XDR *xdrs, rpc_loc_open_rets *objp) +{ +; + + if (!xdr_rpc_loc_client_handle_type (xdrs, &objp->loc_open_result)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_close_rets (XDR *xdrs, rpc_loc_close_rets *objp) +{ +; + + if (!xdr_rpc_int32 (xdrs, &objp->loc_close_result)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_start_fix_rets (XDR *xdrs, rpc_loc_start_fix_rets *objp) +{ +; + + if (!xdr_rpc_int32 (xdrs, &objp->loc_start_fix_result)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_stop_fix_rets (XDR *xdrs, rpc_loc_stop_fix_rets *objp) +{ +; + + if (!xdr_rpc_int32 (xdrs, &objp->loc_stop_fix_result)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_ioctl_rets (XDR *xdrs, rpc_loc_ioctl_rets *objp) +{ +; + + if (!xdr_rpc_int32 (xdrs, &objp->loc_ioctl_result)) + return FALSE; + return TRUE; +} + +bool_t +xdr_rpc_loc_api_api_versions_rets (XDR *xdrs, rpc_loc_api_api_versions_rets *objp) +{ +; + + if (!xdr_rpc_loc_api_api_versions_return_type (xdrs, &objp->loc_api_api_versions_result)) + return FALSE; + if (!xdr_pointer (xdrs, (char **)&objp->len, sizeof (rpc_uint32), (xdrproc_t) xdr_rpc_uint32)) + return FALSE; + return TRUE; +} diff --git a/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-stub/src/loc_apicb_appinit.c b/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-stub/src/loc_apicb_appinit.c new file mode 100644 index 000000000..b469eb0a3 --- /dev/null +++ b/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-stub/src/loc_apicb_appinit.c @@ -0,0 +1,74 @@ +/* Copyright (c) 2011, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "librpc.h" +#include "loc_api_rpcgen_rpc.h" +#include "loc_api_rpcgen_cb_rpc.h" + + +#define RPC_FUNC_VERSION_BASE(a,b) a ## b +#define RPC_CB_FUNC_VERS(a,b) RPC_FUNC_VERSION_BASE(a,b) + + +static SVCXPRT* svrPort = NULL; + +extern void RPC_CB_FUNC_VERS(loc_apicbprog_,LOC_APICBVERS_0001)(struct svc_req *rqstp, register SVCXPRT *transp); + +int loc_apicb_app_init(void) +{ + + /* Register a callback server to use the loc_apicbprog_0x00010001 */ + if (svrPort == NULL) { + svrPort = svcrtr_create(); + } + if (!svrPort) return -1; + + xprt_register(svrPort); + + + + if(svc_register(svrPort, LOC_APICBPROG,LOC_APICBVERS_0001, RPC_CB_FUNC_VERS(loc_apicbprog_,LOC_APICBVERS_0001),0)) + { + return 0; + } + else + { + return -1; + } +} +void loc_apicb_app_deinit(void) +{ + + if (svrPort == NULL) + { + return; + } + + + svc_unregister(svrPort, LOC_APICBPROG,LOC_APICBVERS_0001); +} diff --git a/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-stub/xdr/loc_api.xdr b/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-stub/xdr/loc_api.xdr new file mode 100644 index 000000000..82dca569c --- /dev/null +++ b/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-stub/xdr/loc_api.xdr @@ -0,0 +1,261 @@ +/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/* LOC_API TOOL VERSION: 4.48 */ +/* GENERATED: TUE JUN 14 2011 */ +/*============================================================================= + L O C _ A P I . X D R + +GENERAL DESCRIPTION + This is an AUTO GENERATED file that provides an xdr compatible definition of + the loc_api API. + + --------------------------------------------------------------------------- + + + --------------------------------------------------------------------------- +=============================================================================*/ + +/*============================================================================= + + Edit History + + AUTO GENERATED + +Generated by following versions of Htorpc modules: +Id: //source/qcom/qct/core/mproc/tools/rel/2h09/htorpc/htorpc.pl#1 +Id: //source/qcom/qct/core/mproc/tools/rel/2h09/htorpc/lib/Htorpc/Start.pm#1 +Id: //source/qcom/qct/core/mproc/tools/rel/2h09/htorpc/lib/Htorpc/Htoxdr.pm#1 +Id: //source/qcom/qct/core/mproc/tools/rel/2h09/htorpc/lib/Htorpc/XDR.pm#3 +Id: //source/qcom/qct/core/mproc/tools/rel/2h09/htorpc/lib/Htorpc/Output.pm#5 +Id: //source/qcom/qct/core/mproc/tools/rel/2h09/htorpc/lib/Htorpc/Parser.pm#1 +Id: //source/qcom/qct/core/mproc/tools/rel/2h09/htorpc/lib/Htorpc/Metacomments.pm#1 +Id: //source/qcom/qct/core/mproc/tools/rel/2h09/htorpc/lib/Htorpc/SymbolTable.pm#1 + +loc_api Definition File(s): +Id: //source/qcom/qct/modem/api/gps/main/latest/loc_api.h#24 +=============================================================================*/ +/*============================================================================= +$Header$ +=============================================================================*/ + + + +typedef rpc_uint32 rpc_loc_api_api_versions_return_type<>; + +/* + * Declare an rpc_uint32 type for each callback type in the API + */ +typedef rpc_uint32 rpc_loc_event_cb_f_type; + + + +/* + * These are struct declarations for the function arguments + */ + +struct rpc_loc_open_args { + rpc_loc_event_mask_type event_reg_mask; + rpc_loc_event_cb_f_type event_callback; +}; + +struct rpc_loc_close_args { + rpc_loc_client_handle_type handle; +}; + +struct rpc_loc_start_fix_args { + rpc_loc_client_handle_type handle; +}; + +struct rpc_loc_stop_fix_args { + rpc_loc_client_handle_type handle; +}; + +struct rpc_loc_ioctl_args { + rpc_loc_client_handle_type handle; + rpc_loc_ioctl_e_type ioctl_type; + rpc_loc_ioctl_data_u_type *ioctl_data; +}; + + + +struct rpc_loc_api_api_version_s_args { + rpc_boolean len_not_null; +}; + +/* + * These are struct declarations for the function results + */ + +struct rpc_loc_api_rpc_glue_code_info_remote_rets { + rpc_uint32 toolvers; /* Tool version */ + rpc_uint32 features; /* Features turned on in the code. + * 0x00000001 ONCRPC Server Cleanup Support + */ + rpc_uint32 proghash; /* Unique hash value for the API XDR definition */ + rpc_uint32 cbproghash; /* Unique hash value for the Callbacks' XDR definition */ +}; + +struct rpc_loc_open_rets { + rpc_loc_client_handle_type loc_open_result; +}; + +struct rpc_loc_close_rets { + rpc_int32 loc_close_result; +}; + +struct rpc_loc_start_fix_rets { + rpc_int32 loc_start_fix_result; +}; + +struct rpc_loc_stop_fix_rets { + rpc_int32 loc_stop_fix_result; +}; + +struct rpc_loc_ioctl_rets { + rpc_int32 loc_ioctl_result; +}; + + struct rpc_loc_api_api_versions_rets { + rpc_loc_api_api_versions_return_type loc_api_api_versions_result; + rpc_uint32 *len; +}; + +/* + * XDR definition of the LOC_API program ( vers. 0x00050006 ) + */ + +program LOC_APIPROG { + version LOC_APIVERS_0001 { + + void + rpc_loc_api_null( void ) = 0; + + rpc_loc_api_rpc_glue_code_info_remote_rets + rpc_loc_api_rpc_glue_code_info_remote( void ) = 1; + + rpc_loc_open_rets + rpc_loc_open( rpc_loc_open_args ) = 2; + + rpc_loc_close_rets + rpc_loc_close( rpc_loc_close_args ) = 3; + + rpc_loc_start_fix_rets + rpc_loc_start_fix( rpc_loc_start_fix_args ) = 4; + + rpc_loc_stop_fix_rets + rpc_loc_stop_fix( rpc_loc_stop_fix_args ) = 5; + + rpc_loc_ioctl_rets + rpc_loc_ioctl( rpc_loc_ioctl_args ) = 6; + + rpc_loc_api_api_versions_rets + rpc_loc_api_api_versions( void ) = 0xFFFFFFFF; + + + + + } = 0x00050001; + +version LOC_APIVERS_0002 { + +/* Following elements added in enum rpc_loc_assist_data_request_e_type in 0x00050002 +RPC_LOC_ASSIST_DATA_POSITION_INJECTION_REQ +*/ +/* Following elements added in enum rpc_loc_ioctl_e_type in 0x00050002 +RPC_LOC_IOCTL_GET_XTRA_T_SESSION_CONTROL +RPC_LOC_IOCTL_RESERVED_CMD +RPC_LOC_IOCTL_SET_XTRA_T_SESSION_CONTROL +*/ + + void + rpc_loc_api_null( void ) = 0; + + } = 0x00050002; + +version LOC_APIVERS_0003 { + +/* Following elements added in enum rpc_loc_ioctl_e_type in 0x00050003 +RPC_LOC_IOCTL_SET_DATA_ENABLE +RPC_LOC_IOCTL_SET_LBS_APN_PROFILE +RPC_LOC_IOCTL_GET_XTRA_APN_PROFILE +RPC_LOC_IOCTL_GET_LBS_APN_PROFILE +RPC_LOC_IOCTL_SET_XTRA_APN_PROFILE +*/ + + void + rpc_loc_api_null( void ) = 0; + + } = 0x00050003; + +version LOC_APIVERS_0004 { + +/* Following elements added in enum rpc_loc_ioctl_e_type in 0x00050004 +RPC_LOC_IOCTL_GET_SUPL_VERSION +RPC_LOC_IOCTL_SET_SUPL_VERSION +*/ + + void + rpc_loc_api_null( void ) = 0; + + } = 0x00050004; + +version LOC_APIVERS_0005 { + +/* Following elements added in enum rpc_loc_server_addr_e_type in 0x00050005 +RPC_LOC_SERVER_ADDR_IPV6 +*/ +/* Following elements added in enum rpc_loc_ioctl_e_type in 0x00050005 +RPC_LOC_IOCTL_ERROR_ESTIMATE_CONFIG +*/ + + void + rpc_loc_api_null( void ) = 0; + + } = 0x00050005; + + + + version LOC_APIVERS_0006 { + +/* Following elements added in enum rpc_loc_ioctl_e_type in 0x00050006 +RPC_LOC_IOCTL_INFORM_SERVER_MULTI_OPEN_STATUS +*/ +/* Following elements added in enum rpc_loc_server_request_e_type in 0x00050006 +RPC_LOC_SERVER_REQUEST_MULTI_OPEN +*/ + + void + rpc_loc_api_null( void ) = 0; + + } = 0x00050006; + + +} = 0x3000008C; + +const LOC_APIVERS = 0x00050006; diff --git a/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-stub/xdr/loc_api_cb.xdr b/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-stub/xdr/loc_api_cb.xdr new file mode 100644 index 000000000..4756c6c5a --- /dev/null +++ b/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-stub/xdr/loc_api_cb.xdr @@ -0,0 +1,187 @@ +/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/* LOC_API TOOL VERSION: 4.48 */ +/* GENERATED: TUE JUN 14 2011 */ +/*============================================================================= + L O C _ A P I _ C B . X D R + +GENERAL DESCRIPTION + This is an AUTO GENERATED file that provides an xdr compatible definition of + an api that represents the grouping of the different callback functions the + loc_api API supports. + + --------------------------------------------------------------------------- + + + --------------------------------------------------------------------------- +=============================================================================*/ + +/*============================================================================= + + Edit History + + AUTO GENERATED + +Generated by following versions of Htorpc modules: +Id: //source/qcom/qct/core/mproc/tools/rel/2h09/htorpc/htorpc.pl#1 +Id: //source/qcom/qct/core/mproc/tools/rel/2h09/htorpc/lib/Htorpc/Start.pm#1 +Id: //source/qcom/qct/core/mproc/tools/rel/2h09/htorpc/lib/Htorpc/Htoxdr.pm#1 +Id: //source/qcom/qct/core/mproc/tools/rel/2h09/htorpc/lib/Htorpc/XDR.pm#3 +Id: //source/qcom/qct/core/mproc/tools/rel/2h09/htorpc/lib/Htorpc/Output.pm#5 +Id: //source/qcom/qct/core/mproc/tools/rel/2h09/htorpc/lib/Htorpc/Parser.pm#1 +Id: //source/qcom/qct/core/mproc/tools/rel/2h09/htorpc/lib/Htorpc/Metacomments.pm#1 +Id: //source/qcom/qct/core/mproc/tools/rel/2h09/htorpc/lib/Htorpc/SymbolTable.pm#1 + +loc_api Definition File(s): +Id: //source/qcom/qct/modem/api/gps/main/latest/loc_api.h#24 +=============================================================================*/ +/*============================================================================= +$Header$ +=============================================================================*/ + + + + +/* + * These are struct declarations for the function arguments + */ + +struct rpc_loc_event_cb_f_type_args { + rpc_uint32 cb_id; + rpc_loc_client_handle_type loc_handle; + rpc_loc_event_mask_type loc_event; + rpc_loc_event_payload_u_type *loc_event_payload; +}; + + + + + +/* + * These are struct declaratios for the function results + */ + +struct rpc_loc_event_cb_f_type_rets { + rpc_int32 loc_event_cb_f_type_result; +}; + + + +/* + * XDR definition of the LOC_API callback program ( vers. 0x00050006 ) + */ + +program LOC_APICBPROG { + version LOC_APICBVERS_0001 { + + rpc_loc_event_cb_f_type_rets + rpc_loc_event_cb_f_type( rpc_loc_event_cb_f_type_args ) = 1; + + + + + } = 0x00050001; + +version LOC_APICBVERS_0002 { + +/* Following elements added in enum rpc_loc_assist_data_request_e_type in 0x00050002 +RPC_LOC_ASSIST_DATA_POSITION_INJECTION_REQ +*/ +/* Following elements added in enum rpc_loc_ioctl_e_type in 0x00050002 +RPC_LOC_IOCTL_GET_XTRA_T_SESSION_CONTROL +RPC_LOC_IOCTL_RESERVED_CMD +RPC_LOC_IOCTL_SET_XTRA_T_SESSION_CONTROL +*/ + + int + rpc_loc_api_cb_null( void ) = 0xffffff00; + + } = 0x00050002; + +version LOC_APICBVERS_0003 { + +/* Following elements added in enum rpc_loc_ioctl_e_type in 0x00050003 +RPC_LOC_IOCTL_SET_DATA_ENABLE +RPC_LOC_IOCTL_SET_LBS_APN_PROFILE +RPC_LOC_IOCTL_GET_XTRA_APN_PROFILE +RPC_LOC_IOCTL_GET_LBS_APN_PROFILE +RPC_LOC_IOCTL_SET_XTRA_APN_PROFILE +*/ + + int + rpc_loc_api_cb_null( void ) = 0xffffff00; + + } = 0x00050003; + +version LOC_APICBVERS_0004 { + +/* Following elements added in enum rpc_loc_ioctl_e_type in 0x00050004 +RPC_LOC_IOCTL_GET_SUPL_VERSION +RPC_LOC_IOCTL_SET_SUPL_VERSION +*/ + + int + rpc_loc_api_cb_null( void ) = 0xffffff00; + + } = 0x00050004; + +version LOC_APICBVERS_0005 { + +/* Following elements added in enum rpc_loc_server_addr_e_type in 0x00050005 +RPC_LOC_SERVER_ADDR_IPV6 +*/ +/* Following elements added in enum rpc_loc_ioctl_e_type in 0x00050005 +RPC_LOC_IOCTL_ERROR_ESTIMATE_CONFIG +*/ + + int + rpc_loc_api_cb_null( void ) = 0xffffff00; + + } = 0x00050005; + + + + version LOC_APICBVERS_0006 { + +/* Following elements added in enum rpc_loc_ioctl_e_type in 0x00050006 +RPC_LOC_IOCTL_INFORM_SERVER_MULTI_OPEN_STATUS +*/ +/* Following elements added in enum rpc_loc_server_request_e_type in 0x00050006 +RPC_LOC_SERVER_REQUEST_MULTI_OPEN +*/ + + int + rpc_loc_api_cb_null( void ) = 0xffffff00; + + } = 0x00050006; + + +} = 0x3100008C; + +const LOC_APICBVERS = 0x00050006; diff --git a/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-stub/xdr/loc_api_common.xdr b/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-stub/xdr/loc_api_common.xdr new file mode 100644 index 000000000..e059c661c --- /dev/null +++ b/gps/loc_api/libloc_api-rpc-50001/libloc_api-rpc-stub/xdr/loc_api_common.xdr @@ -0,0 +1,1021 @@ +/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/* LOC_API TOOL VERSION: 4.48 */ +/* GENERATED: TUE JUN 14 2011 */ +/*============================================================================= + L O C _ A P I _ C O M M O N . X D R + +GENERAL DESCRIPTION + This is an AUTO GENERATED file that provides an xdr compatible definition of + an api that represents the grouping of the different callback functions the + loc_api API supports. + + --------------------------------------------------------------------------- + + + --------------------------------------------------------------------------- +=============================================================================*/ + +/*============================================================================= + + Edit History + + AUTO GENERATED + +Generated by following versions of Htorpc modules: +Id: //source/qcom/qct/core/mproc/tools/rel/2h09/htorpc/htorpc.pl#1 +Id: //source/qcom/qct/core/mproc/tools/rel/2h09/htorpc/lib/Htorpc/Start.pm#1 +Id: //source/qcom/qct/core/mproc/tools/rel/2h09/htorpc/lib/Htorpc/Htoxdr.pm#1 +Id: //source/qcom/qct/core/mproc/tools/rel/2h09/htorpc/lib/Htorpc/XDR.pm#3 +Id: //source/qcom/qct/core/mproc/tools/rel/2h09/htorpc/lib/Htorpc/Output.pm#5 +Id: //source/qcom/qct/core/mproc/tools/rel/2h09/htorpc/lib/Htorpc/Parser.pm#1 +Id: //source/qcom/qct/core/mproc/tools/rel/2h09/htorpc/lib/Htorpc/Metacomments.pm#1 +Id: //source/qcom/qct/core/mproc/tools/rel/2h09/htorpc/lib/Htorpc/SymbolTable.pm#1 + +loc_api Definition File(s): +Id: //source/qcom/qct/modem/api/gps/main/latest/loc_api.h#24 +=============================================================================*/ +/*============================================================================= +$Header$ +=============================================================================*/ + + + +const LOC_API_TOOLVERS = 0x00040030; +const LOC_API_FEATURES = 0x00000001; + +const RPC_LOC_EVENT_STATUS_REPORT = 0x00000100; + +const RPC_LOC_EVENT_ASSISTANCE_DATA_REQUEST = 0x00000020; + +const RPC_LOC_EVENT_WPS_NEEDED_REQUEST = 0x00000200; + +const RPC_LOC_EVENT_SATELLITE_REPORT = 0x00000002; + +const RPC_LOC_EVENT_PARSED_POSITION_REPORT = 0x00000001; + +const RPC_LOC_EVENT_RESERVED = 0x8000000000000000; + +const RPC_LOC_EVENT_LOCATION_SERVER_REQUEST = 0x00000040; + +const RPC_LOC_EVENT_NMEA_POSITION_REPORT = 0x00000008; + +const RPC_LOC_EVENT_IOCTL_REPORT = 0x00000080; + +const RPC_LOC_EVENT_NMEA_1HZ_REPORT = 0x00000004; + +const RPC_LOC_EVENT_NI_NOTIFY_VERIFY_REQUEST = 0x00000010; + +const RPC_LOC_API_CB_NULL_VERSION = 0x00050002; +const RPC_LOC_EVENT_CB_F_TYPE_VERSION = 0x00050001; +const RPC_LOC_API_API_VERSIONS_VERSION = 0x00050001; +const RPC_LOC_STOP_FIX_VERSION = 0x00050001; +const RPC_LOC_START_FIX_VERSION = 0x00050001; +const RPC_LOC_IOCTL_VERSION = 0x00050001; +const RPC_LOC_CLOSE_VERSION = 0x00050001; +const RPC_LOC_API_RPC_GLUE_CODE_INFO_REMOTE_VERSION = 0x00050001; +const RPC_LOC_OPEN_VERSION = 0x00050001; +const RPC_LOC_API_NULL_VERSION = 0x00050001; +const RPC_LOC_API_API_MAJOR_NUM = 0x0005; +const RPC_LOC_APIAPI_VERSION_IS_HASHKEY = 0; + +typedef rpc_int32 rpc_loc_client_handle_type; + +typedef rpc_uint64 rpc_loc_event_mask_type; + +typedef rpc_uint64 rpc_loc_position_valid_mask_type; + +typedef rpc_uint32 rpc_loc_pos_technology_mask_type; + +enum rpc_loc_session_status_e_type { + RPC_LOC_SESS_STATUS_SUCCESS = 0, + RPC_LOC_SESS_STATUS_IN_PROGESS = 1, + RPC_LOC_SESS_STATUS_GENERAL_FAILURE = 2, + RPC_LOC_SESS_STATUS_TIMEOUT = 3, + RPC_LOC_SESS_STATUS_USER_END = 4, + RPC_LOC_SESS_STATUS_BAD_PARAMETER = 5, + RPC_LOC_SESS_STATUS_PHONE_OFFLINE = 6, + RPC_LOC_SESS_STATUS_ENGINE_LOCKED = 7, + RPC_LOC_SESS_STATUS_MAX = 268435456 +}; + +struct rpc_loc_calendar_time_s_type { + rpc_uint16 year; + unsigned char month; + unsigned char day_of_week; + unsigned char day; + unsigned char hour; + unsigned char minute; + unsigned char second; + rpc_uint16 millisecond; +}; + +struct rpc_loc_parsed_position_s_type { + rpc_loc_position_valid_mask_type valid_mask; + rpc_loc_session_status_e_type session_status; + rpc_loc_calendar_time_s_type timestamp_calendar; + rpc_uint64 timestamp_utc; + rpc_uint8 leap_seconds; + float time_unc; + double latitude; + double longitude; + float altitude_wrt_ellipsoid; + float altitude_wrt_mean_sea_level; + float speed_horizontal; + float speed_vertical; + float heading; + float hor_unc_circular; + float hor_unc_ellipse_semi_major; + float hor_unc_ellipse_semi_minor; + float hor_unc_ellipse_orient_azimuth; + float vert_unc; + float speed_unc; + float heading_unc; + unsigned char confidence_horizontal; + unsigned char confidence_vertical; + float magnetic_deviation; + rpc_loc_pos_technology_mask_type technology_mask; +}; + +enum rpc_loc_sv_system_e_type { + RPC_LOC_SV_SYSTEM_GPS = 1, + RPC_LOC_SV_SYSTEM_GALILEO = 2, + RPC_LOC_SV_SYSTEM_SBAS = 3, + RPC_LOC_SV_SYSTEM_COMPASS = 4, + RPC_LOC_SV_SYSTEM_GLONASS = 5, + RPC_LOC_SV_SYSTEM_MAX = 268435456 +}; + +enum rpc_loc_sv_status_e_type { + RPC_LOC_SV_STATUS_IDLE = 1, + RPC_LOC_SV_STATUS_SEARCH = 2, + RPC_LOC_SV_STATUS_TRACK = 3, + RPC_LOC_SV_STATUS_MAX = 268435456 +}; + +typedef rpc_uint32 rpc_loc_sv_info_valid_mask_type; + +struct rpc_loc_sv_info_s_type { + rpc_loc_sv_info_valid_mask_type valid_mask; + rpc_loc_sv_system_e_type system; + rpc_uint8 prn; + rpc_uint8 health_status; + rpc_loc_sv_status_e_type process_status; + rpc_boolean has_eph; + rpc_boolean has_alm; + float elevation; + float azimuth; + float snr; +}; + +typedef rpc_uint32 rpc_loc_gnss_info_valid_mask_type; + +struct rpc_loc_gnss_info_s_type { + rpc_loc_gnss_info_valid_mask_type valid_mask; + float position_dop; + float horizontal_dop; + float vertical_dop; + rpc_boolean altitude_assumed; + rpc_uint16 sv_count; + rpc_loc_sv_info_s_type sv_list<80>; /* EVAL:[LOC_API_MAX_SV_COUNT]*/ +}; + +struct rpc_loc_nmea_report_s_type { + rpc_uint16 length; + opaque nmea_sentences[200]; +}; + +enum rpc_loc_status_event_e_type { + RPC_LOC_STATUS_EVENT_ENGINE_STATE = 1, + RPC_LOC_STATUS_EVENT_FIX_SESSION_STATE = 2, + RPC_LOC_STATUS_EVENT_MAX = 268435456 +}; + +enum rpc_loc_engine_state_e_type { + RPC_LOC_ENGINE_STATE_ON = 1, + RPC_LOC_ENGINE_STATE_OFF = 2, + RPC_LOC_ENGINE_STATE_MAX = 268435456 +}; + +enum rpc_loc_fix_session_state_e_type { + RPC_LOC_FIX_SESSION_STATE_BEGIN = 1, + RPC_LOC_FIX_SESSION_STATE_END = 2, + RPC_LOC_FIX_SESSION_STATE_MAX = 268435456 +}; + +union rpc_loc_status_event_payload_u_type switch (rpc_loc_status_event_e_type disc) { + case RPC_LOC_STATUS_EVENT_ENGINE_STATE: + rpc_loc_engine_state_e_type engine_state; + case RPC_LOC_STATUS_EVENT_FIX_SESSION_STATE: + rpc_loc_fix_session_state_e_type fix_session_state; + default: + void; +}; + +struct rpc_loc_status_event_s_type { + rpc_loc_status_event_e_type event; + rpc_loc_status_event_payload_u_type payload; +}; + +enum rpc_loc_server_addr_e_type { + RPC_LOC_SERVER_ADDR_IPV4 = 1, + RPC_LOC_SERVER_ADDR_URL = 2, + RPC_LOC_SERVER_ADDR_IPV6 = 3, + RPC_LOC_SERVER_ADDR_MAX = 268435456 +}; + +struct rpc_loc_server_addr_ipv4_type { + rpc_uint32 addr; + rpc_uint16 port; +}; + +struct rpc_loc_server_addr_url_type { + rpc_uint16 length; + opaque addr[256]; +}; + +struct rpc_loc_server_addr_ipv6_type { + rpc_uint16 addr[8]; + rpc_uint32 port; +}; + +union rpc_loc_server_addr_u_type switch (rpc_loc_server_addr_e_type disc) { + case RPC_LOC_SERVER_ADDR_IPV4: + rpc_loc_server_addr_ipv4_type ipv4; + case RPC_LOC_SERVER_ADDR_URL: + rpc_loc_server_addr_url_type url; + case RPC_LOC_SERVER_ADDR_IPV6: + rpc_loc_server_addr_ipv6_type ipv6; + default: + void; +}; + +struct rpc_loc_server_info_s_type { + rpc_loc_server_addr_e_type addr_type; + rpc_loc_server_addr_u_type addr_info; +}; + +enum rpc_loc_ni_notify_verify_e_type { + RPC_LOC_NI_USER_NO_NOTIFY_NO_VERIFY = 1, + RPC_LOC_NI_USER_NOTIFY_ONLY = 2, + RPC_LOC_NI_USER_NOTIFY_VERIFY_ALLOW_NO_RESP = 3, + RPC_LOC_NI_USER_NOTIFY_VERIFY_NOT_ALLOW_NO_RESP = 4, + RPC_LOC_NI_USER_PRIVACY_OVERRIDE = 5, + RPC_LOC_NI_USER_NOTIFY_VERITY_TYPE_MAX = 268435456 +}; + +enum rpc_loc_ni_event_e_type { + RPC_LOC_NI_EVENT_VX_NOTIFY_VERIFY_REQ = 1, + RPC_LOC_NI_EVENT_SUPL_NOTIFY_VERIFY_REQ = 2, + RPC_LOC_NI_EVENT_UMTS_CP_NOTIFY_VERIFY_REQ = 3, + RPC_LOC_NI_EVENT_VX_SERVICE_INTERACTION_REQ = 4, + RPC_LOC_NI_EVENT_MAX = 268435456 +}; + +enum rpc_loc_ni_datacoding_scheme_e_type { + RPC_LOC_NI_PRESUPL_ISO646IRV = 0, + RPC_LOC_NI_PRESUPL_ISO8859 = 1, + RPC_LOC_NI_PRESUPL_UTF8 = 2, + RPC_LOC_NI_PRESUPL_UTF16 = 3, + RPC_LOC_NI_PRESUPL_UCS2 = 4, + RPC_LOC_NI_PRESUPL_GSM_DEFAULT = 5, + RPC_LOC_NI_PRESUPL_SHIFT_JIS = 6, + RPC_LOC_NI_PRESUPL_JIS = 7, + RPC_LOC_NI_PRESUPL_EUC = 8, + RPC_LOC_NI_PRESUPL_GB2312 = 9, + RPC_LOC_NI_PRESUPL_CNS11643 = 10, + RPC_LOC_NI_PRESUPL_KSC1001 = 11, + RPC_LOC_NI_PRESUPL_ENCODING_UNKNOWN = 2147483647, + RPC_LOC_NI_SS_GERMAN = 12, + RPC_LOC_NI_SS_ENGLISH = 13, + RPC_LOC_NI_SS_ITALIAN = 14, + RPC_LOC_NI_SS_FRENCH = 15, + RPC_LOC_NI_SS_SPANISH = 16, + RPC_LOC_NI_SS_DUTCH = 17, + RPC_LOC_NI_SS_SWEDISH = 18, + RPC_LOC_NI_SS_DANISH = 19, + RPC_LOC_NI_SS_PORTUGUESE = 20, + RPC_LOC_NI_SS_FINNISH = 21, + RPC_LOC_NI_SS_NORWEGIAN = 22, + RPC_LOC_NI_SS_GREEK = 23, + RPC_LOC_NI_SS_TURKISH = 24, + RPC_LOC_NI_SS_HUNGARIAN = 25, + RPC_LOC_NI_SS_POLISH = 26, + RPC_LOC_NI_SS_LANGUAGE_UNSPEC = 27, + RPC_LOC_NI_SUPL_UTF8 = 28, + RPC_LOC_NI_SUPL_UCS2 = 29, + RPC_LOC_NI_SUPL_GSM_DEFAULT = 30, + RPC_LOC_NI_SUPL_ENCODING_UNKNOWN = 2147483647 +}; + +enum rpc_loc_ni_vx_requester_id_encoding_scheme_e_type { + RPC_LOC_NI_VX_OCTET = 0, + RPC_LOC_NI_VX_EXN_PROTOCOL_MSG = 1, + RPC_LOC_NI_VX_ASCII = 2, + RPC_LOC_NI_VX_IA5 = 3, + RPC_LOC_NI_VX_UNICODE = 4, + RPC_LOC_NI_VX_SHIFT_JIS = 5, + RPC_LOC_NI_VX_KOREAN = 6, + RPC_LOC_NI_VX_LATIN_HEBREW = 7, + RPC_LOC_NI_VX_LATIN = 8, + RPC_LOC_NI_VX_GSM = 9, + RPC_LOC_NI_VX_ENCODING_TYPE_MAX = 268435456 +}; + +enum rpc_loc_ni_vx_pos_mode_e_type { + RPC_LOC_VX_MS_ASSISTED_ONLY = 1, + RPC_LOC_VX_MS_BASED_ONLY = 2, + RPC_LOC_VX_MS_ASSISTED_PREF_MSBASED_ALLWD = 3, + RPC_LOC_VX_MS_BASED_PREF_ASSISTED_ALLWD = 4, + RPC_LOC_VX_POS_MODE_MAX = 268435456 +}; + +struct rpc_loc_ni_vx_requester_id_s_type { + unsigned char requester_id_length; + opaque requester_id[200]; +}; + +struct rpc_loc_ni_vx_notify_verify_req_s_type { + rpc_loc_ni_notify_verify_e_type notification_priv_type; + unsigned char pos_qos_incl; + unsigned char pos_qos; + rpc_uint32 num_fixes; + rpc_uint32 tbf; + rpc_loc_ni_vx_pos_mode_e_type pos_mode; + rpc_loc_ni_vx_requester_id_encoding_scheme_e_type encoding_scheme; + rpc_loc_ni_vx_requester_id_s_type requester_id; + rpc_uint16 user_resp_timer_val; +}; + +enum rpc_loc_ni_supl_pos_method_e_type { + RPC_LOC_NI_POSMETHOD_AGPS_SETASSISTED = 1, + RPC_LOC_NI_POSMETHOD_AGPS_SETBASED = 2, + RPC_LOC_NI_POSMETHOD_AGPS_SETASSISTED_PREF = 3, + RPC_LOC_NI_POSMETHOD_AGPS_SETBASED_PREF = 4, + RPC_LOC_NI_POSMETHOD_AUTONOMOUS_GPS = 5, + RPC_LOC_NI_POSMETHOD_AFLT = 6, + RPC_LOC_NI_POSMETHOD_ECID = 7, + RPC_LOC_NI_POSMETHOD_EOTD = 8, + RPC_LOC_NI_POSMETHOD_OTDOA = 9, + RPC_LOC_NI_POSMETHOD_NO_POSITION = 10, + RPC_LOC_NI_POSMETHOD_MAX = 268435456 +}; + +struct rpc_loc_ni_supl_slp_session_id_s_type { + unsigned char presence; + opaque session_id[4]; + rpc_loc_server_info_s_type slp_address; +}; + +struct rpc_loc_ni_requestor_id_s_type { + unsigned char data_coding_scheme; + opaque requestor_id_string[200]; + unsigned char string_len; +}; + +struct rpc_loc_ni_supl_client_name_s_type { + unsigned char data_coding_scheme; + opaque client_name_string[64]; + unsigned char string_len; +}; + +struct rpc_loc_ni_supl_qop_s_type { + unsigned char bit_mask; + unsigned char horacc; + unsigned char veracc; + rpc_uint16 maxLocAge; + unsigned char delay; +}; + +struct rpc_loc_ni_supl_notify_verify_req_s_type { + rpc_loc_ni_notify_verify_e_type notification_priv_type; + rpc_uint16 flags; + rpc_loc_ni_supl_slp_session_id_s_type supl_slp_session_id; + opaque supl_hash[8]; + rpc_loc_ni_datacoding_scheme_e_type datacoding_scheme; + rpc_loc_ni_supl_pos_method_e_type pos_method; + rpc_loc_ni_requestor_id_s_type requestor_id; + rpc_loc_ni_supl_client_name_s_type client_name; + rpc_loc_ni_supl_qop_s_type supl_qop; + rpc_uint16 user_response_timer; +}; + +struct rpc_loc_ni_ext_client_address_s_type { + unsigned char ext_client_address_len; + opaque ext_client_address[20]; +}; + +enum rpc_loc_ni_location_type_e_type { + RPC_LOC_NI_LOCATIONTYPE_CURRENT_LOCATION = 1, + RPC_LOC_NI_LOCATIONTYPE_CURRENT_OR_LAST_KNOWN_LOCATION = 2, + RPC_LOC_NI_LOCATIONTYPE_INITIAL_LOCATION = 3, + RPC_LOC_NI_LOCATIONTYPE_MAX = 268435456 +}; + +struct rpc_loc_ni_deferred_location_s_type { + unsigned char unused_bits; + unsigned char ms_available; +}; + +struct rpc_loc_ni_codeword_string_s_type { + unsigned char data_coding_scheme; + opaque lcs_codeword_string[20]; + unsigned char string_len; +}; + +struct rpc_loc_ni_service_type_id_s_type { + unsigned char lcs_service_type_id; +}; + +struct rpc_loc_ni_umts_cp_notify_verify_req_s_type { + rpc_loc_ni_notify_verify_e_type notification_priv_type; + unsigned char invoke_id; + rpc_uint16 flags; + unsigned char notification_length; + opaque notification_text[64]; + rpc_loc_ni_datacoding_scheme_e_type datacoding_scheme; + rpc_loc_ni_ext_client_address_s_type ext_client_address_data; + rpc_loc_ni_location_type_e_type location_type; + rpc_loc_ni_deferred_location_s_type deferred_location; + rpc_loc_ni_requestor_id_s_type requestor_id; + rpc_loc_ni_codeword_string_s_type codeword_string; + rpc_loc_ni_service_type_id_s_type service_type_id; + rpc_uint16 user_response_timer; +}; + +enum rpc_loc_ni_service_interaction_e_type { + RPC_LOC_NI_SERVICE_INTERACTION_ONGOING_NI_INCOMING_MO = 1, + RPC_LOC_NI_SERVICE_INTERACTION_MAX = 268435456 +}; + +struct rpc_loc_ni_vx_service_interaction_req_s_type { + rpc_loc_ni_vx_notify_verify_req_s_type ni_vx_req; + rpc_loc_ni_service_interaction_e_type service_interation_type; +}; + +union rpc_loc_ni_event_payload_u_type switch (rpc_loc_ni_event_e_type disc) { + case RPC_LOC_NI_EVENT_VX_NOTIFY_VERIFY_REQ: + rpc_loc_ni_vx_notify_verify_req_s_type vx_req; + case RPC_LOC_NI_EVENT_SUPL_NOTIFY_VERIFY_REQ: + rpc_loc_ni_supl_notify_verify_req_s_type supl_req; + case RPC_LOC_NI_EVENT_UMTS_CP_NOTIFY_VERIFY_REQ: + rpc_loc_ni_umts_cp_notify_verify_req_s_type umts_cp_req; + case RPC_LOC_NI_EVENT_VX_SERVICE_INTERACTION_REQ: + rpc_loc_ni_vx_service_interaction_req_s_type service_interaction_req; + default: + void; +}; + +struct rpc_loc_ni_event_s_type { + rpc_loc_ni_event_e_type event; + rpc_loc_ni_event_payload_u_type payload; +}; + +enum rpc_loc_assist_data_request_e_type { + RPC_LOC_ASSIST_DATA_TIME_REQ = 1, + RPC_LOC_ASSIST_DATA_PREDICTED_ORBITS_REQ = 2, + RPC_LOC_ASSIST_DATA_POSITION_INJECTION_REQ = 3, + RPC_LOC_ASSIST_DATA_MAX = 268435456 +}; + +typedef string rpc_struct_loc_time_download_source_s_type_servers_ptr<256>; /* EVAL:[LOC_API_MAX_SERVER_ADDR_LENGTH]*/ + +typedef rpc_struct_loc_time_download_source_s_type_servers_ptr rpc_struct_loc_time_download_source_s_type_servers[3]; + +struct rpc_loc_time_download_source_s_type { + rpc_uint32 delay_threshold; + rpc_struct_loc_time_download_source_s_type_servers servers; +}; + +typedef string rpc_struct_loc_predicted_orbits_data_source_s_type_servers_ptr; + +typedef rpc_struct_loc_predicted_orbits_data_source_s_type_servers_ptr rpc_struct_loc_predicted_orbits_data_source_s_type_servers[3]; + +struct rpc_loc_predicted_orbits_data_source_s_type { + rpc_uint32 max_file_size; + rpc_uint32 max_part_size; + rpc_struct_loc_predicted_orbits_data_source_s_type_servers servers; +}; + +struct rpc_loc_pos_inj_request_s_type { + rpc_uint32 flags; + double latitude; + double longitude; + rpc_uint32 position_uncertainty; + rpc_uint64 timestamp; +}; + +union rpc_loc_assist_data_request_payload_u_type switch (rpc_loc_assist_data_request_e_type disc) { + case RPC_LOC_ASSIST_DATA_TIME_REQ: + rpc_loc_time_download_source_s_type time_download; + case RPC_LOC_ASSIST_DATA_PREDICTED_ORBITS_REQ: + rpc_loc_predicted_orbits_data_source_s_type data_download; + case RPC_LOC_ASSIST_DATA_POSITION_INJECTION_REQ: + rpc_loc_pos_inj_request_s_type pos_injection; + default: + void; +}; + +struct rpc_loc_assist_data_request_s_type { + rpc_loc_assist_data_request_e_type event; + rpc_loc_assist_data_request_payload_u_type payload; +}; + +typedef rpc_uint32 rpc_loc_server_connection_handle; + +enum rpc_loc_server_protocol_e_type { + RPC_LOC_SERVER_PROTOCOL_DEFAULT = 0, + RPC_LOC_SERVER_PROTOCOL_SUPL = 1, + RPC_LOC_SERVER_PROTOCOL_VX_MPC = 2, + RPC_LOC_SERVER_PROTOCOL_VX_PDE = 3, + RPC_LOC_SERVER_PROTOCOL_MAX = 16777216 +}; + +enum rpc_loc_server_connection_e_type { + RPC_LOC_SERVER_CONNECTION_LBS = 0, + RPC_LOC_SERVER_CONNECTION_WWAN_INTERNET, + RPC_LOC_SERVER_CONNECTION_MAX = 16777216 +}; + +enum rpc_loc_server_request_e_type { + RPC_LOC_SERVER_REQUEST_OPEN = 1, + RPC_LOC_SERVER_REQUEST_CLOSE = 2, + RPC_LOC_SERVER_REQUEST_MULTI_OPEN = 3, + RPC_LOC_SERVER_REQUEST_MAX = 268435456 +}; + +struct rpc_loc_server_open_req_s_type { + rpc_loc_server_connection_handle conn_handle; + rpc_loc_server_protocol_e_type protocol; +}; + +struct rpc_loc_server_multi_open_req_s_type { + rpc_loc_server_connection_handle conn_handle; + rpc_loc_server_protocol_e_type protocol; + rpc_loc_server_connection_e_type connection_type; +}; + +struct rpc_loc_server_close_req_s_type { + rpc_loc_server_connection_handle conn_handle; +}; + +union rpc_loc_server_request_u_type switch (rpc_loc_server_request_e_type disc) { + case RPC_LOC_SERVER_REQUEST_OPEN: + rpc_loc_server_open_req_s_type open_req; + case RPC_LOC_SERVER_REQUEST_CLOSE: + rpc_loc_server_close_req_s_type close_req; + case RPC_LOC_SERVER_REQUEST_MULTI_OPEN: + rpc_loc_server_multi_open_req_s_type multi_open_req; + default: + void; +}; + +struct rpc_loc_server_request_s_type { + rpc_loc_server_request_e_type event; + rpc_loc_server_request_u_type payload; +}; + +enum rpc_loc_qwip_request_e_type { + RPC_LOC_QWIP_START_PERIODIC_HI_FREQ_FIXES = 0, + RPC_LOC_QWIP_START_PERIODIC_KEEP_WARM, + RPC_LOC_QWIP_STOP_PERIODIC_FIXES, + RPC_LOC_QWIP_SUSPEND, + RPC_LOC_QWIP_REQUEST_MAX = 268435456 +}; + +struct rpc_loc_qwip_request_s_type { + rpc_loc_qwip_request_e_type request_type; + rpc_uint16 tbf_ms; +}; + +struct rpc_loc_reserved_payload_s_type { + rpc_uint16 data_size; + opaque data<>; +}; + +enum rpc_loc_ioctl_e_type { + RPC_LOC_IOCTL_GET_API_VERSION = 1, + RPC_LOC_IOCTL_SET_FIX_CRITERIA = 2, + RPC_LOC_IOCTL_GET_FIX_CRITERIA = 3, + RPC_LOC_IOCTL_SERVICE_START_INDEX = 400, + RPC_LOC_IOCTL_INFORM_NI_USER_RESPONSE = 400, + RPC_LOC_IOCTL_INJECT_PREDICTED_ORBITS_DATA = 401, + RPC_LOC_IOCTL_QUERY_PREDICTED_ORBITS_DATA_VALIDITY = 402, + RPC_LOC_IOCTL_QUERY_PREDICTED_ORBITS_DATA_SOURCE = 403, + RPC_LOC_IOCTL_SET_PREDICTED_ORBITS_DATA_AUTO_DOWNLOAD = 404, + RPC_LOC_IOCTL_INJECT_UTC_TIME = 405, + RPC_LOC_IOCTL_INJECT_RTC_VALUE = 406, + RPC_LOC_IOCTL_INJECT_POSITION = 407, + RPC_LOC_IOCTL_QUERY_ENGINE_STATE = 408, + RPC_LOC_IOCTL_INFORM_SERVER_OPEN_STATUS = 409, + RPC_LOC_IOCTL_INFORM_SERVER_CLOSE_STATUS = 410, + RPC_LOC_IOCTL_SEND_WIPER_POSITION_REPORT = 411, + RPC_LOC_IOCTL_NOTIFY_WIPER_STATUS = 412, + RPC_LOC_IOCTL_ACCESS_EFS_DATA = 413, + RPC_LOC_IOCTL_ERROR_ESTIMATE_CONFIG = 414, + RPC_LOC_IOCTL_INFORM_SERVER_MULTI_OPEN_STATUS = 415, + RPC_LOC_IOCTL_NV_SETTINGS_START_INDEX = 800, + RPC_LOC_IOCTL_SET_ENGINE_LOCK = 800, + RPC_LOC_IOCTL_GET_ENGINE_LOCK = 801, + RPC_LOC_IOCTL_SET_SBAS_CONFIG = 802, + RPC_LOC_IOCTL_GET_SBAS_CONFIG = 803, + RPC_LOC_IOCTL_SET_NMEA_TYPES = 804, + RPC_LOC_IOCTL_GET_NMEA_TYPES = 805, + RPC_LOC_IOCTL_SET_CDMA_PDE_SERVER_ADDR = 806, + RPC_LOC_IOCTL_GET_CDMA_PDE_SERVER_ADDR = 807, + RPC_LOC_IOCTL_SET_CDMA_MPC_SERVER_ADDR = 808, + RPC_LOC_IOCTL_GET_CDMA_MPC_SERVER_ADDR = 809, + RPC_LOC_IOCTL_SET_UMTS_SLP_SERVER_ADDR = 810, + RPC_LOC_IOCTL_GET_UMTS_SLP_SERVER_ADDR = 811, + RPC_LOC_IOCTL_SET_ON_DEMAND_LPM = 812, + RPC_LOC_IOCTL_GET_ON_DEMAND_LPM = 813, + RPC_LOC_IOCTL_SET_XTRA_T_SESSION_CONTROL = 814, + RPC_LOC_IOCTL_GET_XTRA_T_SESSION_CONTROL = 815, + RPC_LOC_IOCTL_SET_LBS_APN_PROFILE = 816, + RPC_LOC_IOCTL_GET_LBS_APN_PROFILE = 817, + RPC_LOC_IOCTL_SET_XTRA_APN_PROFILE = 818, + RPC_LOC_IOCTL_GET_XTRA_APN_PROFILE = 819, + RPC_LOC_IOCTL_SET_DATA_ENABLE = 820, + RPC_LOC_IOCTL_SET_SUPL_VERSION = 821, + RPC_LOC_IOCTL_GET_SUPL_VERSION = 822, + RPC_LOC_IOCTL_PROPRIETARY_START_INDEX = 1000, + RPC_LOC_IOCTL_DELETE_ASSIST_DATA = 1000, + RPC_LOC_IOCTL_SET_CUSTOM_PDE_SERVER_ADDR = 1001, + RPC_LOC_IOCTL_GET_CUSTOM_PDE_SERVER_ADDR = 1002, + RPC_LOC_IOCTL_RESERVED_CMD = 8000, + RPC_LOC_IOCTL_THIRD_PARTY_START_INDEX = 1073741824 +}; + +struct rpc_loc_api_version_s_type { + unsigned char major; + unsigned char minor; +}; + +enum rpc_loc_fix_recurrence_e_type { + RPC_LOC_PERIODIC_FIX = 1, + RPC_LOC_SINGLE_FIX = 2, + RPC_LOC_FIX_SESSION_TYPE_MAX = 268435456 +}; + +enum rpc_loc_operation_mode_e_type { + RPC_LOC_OPER_MODE_DEFAULT = 1, + RPC_LOC_OPER_MODE_MSB = 2, + RPC_LOC_OPER_MODE_MSA = 3, + RPC_LOC_OPER_MODE_STANDALONE = 4, + RPC_LOC_OPER_MODE_SPEED_OPTIMAL = 5, + RPC_LOC_OPER_MODE_ACCURACY_OPTIMAL = 6, + RPC_LOC_OPER_MODE_DATA_OPTIMAL = 7, + RPC_LOC_OPER_MODE_CELL_ID = 8, + RPC_LOC_OPER_MODE_MAX = 268435456 +}; + +enum rpc_loc_notify_e_type { + RPC_LOC_NOTIFY_ON_INTERVAL = 1, + RPC_LOC_NOTIFY_ON_DISTANCE = 2, + RPC_LOC_NOTIFY_ON_ANY = 3, + RPC_LOC_NOTIFY_ON_ALL = 4, + RPC_LOC_NOTIFY_TYPE_MAX = 268435456 +}; + +struct rpc_loc_fix_criteria_s_type { + rpc_uint32 valid_mask; + rpc_loc_fix_recurrence_e_type recurrence_type; + rpc_loc_operation_mode_e_type preferred_operation_mode; + rpc_uint32 preferred_accuracy; + rpc_uint32 preferred_response_time; + rpc_boolean intermediate_pos_report_enabled; + rpc_loc_notify_e_type notify_type; + rpc_uint32 min_interval; + float min_distance; + rpc_uint32 min_dist_sample_interval; +}; + +enum rpc_loc_ni_user_resp_e_type { + RPC_LOC_NI_LCS_NOTIFY_VERIFY_ACCEPT = 1, + RPC_LOC_NI_LCS_NOTIFY_VERIFY_DENY = 2, + RPC_LOC_NI_LCS_NOTIFY_VERIFY_NORESP = 3, + RPC_LOC_NI_LCS_NOTIFY_VERIFY_MAX = 268435456 +}; + +struct rpc_loc_user_verify_s_type { + rpc_loc_ni_user_resp_e_type user_resp; + rpc_loc_ni_event_s_type ni_event_pass_back; +}; + +enum rpc_loc_predicted_orbits_data_format_e_type { + RPC_LOC_PREDICTED_ORBITS_XTRA = 0, + RPC_LOC_PREDICTED_ORBITS_FORMAT_MAX = 268435456 +}; + +struct rpc_loc_predicted_orbits_data_s_type { + rpc_loc_predicted_orbits_data_format_e_type format_type; + rpc_uint32 total_size; + rpc_uint8 total_parts; + rpc_uint8 part; + rpc_uint16 part_len; + opaque data_ptr<>; +}; + +struct rpc_loc_predicted_orbits_data_validity_report_s_type { + rpc_uint64 start_time_utc; + rpc_uint16 valid_duration_hrs; +}; + +struct rpc_loc_predicted_orbits_auto_download_config_s_type { + rpc_boolean enable; + unsigned char auto_check_every_hrs; +}; + +struct rpc_loc_assist_data_time_s_type { + rpc_uint64 time_utc; + rpc_uint32 uncertainty; +}; + +typedef rpc_uint64 rpc_loc_assist_pos_valid_mask_type; + +struct rpc_loc_assist_data_pos_s_type { + rpc_loc_assist_pos_valid_mask_type valid_mask; + rpc_uint64 timestamp_utc; + double latitude; + double longitude; + float altitude_wrt_ellipsoid; + float altitude_wrt_mean_sea_level; + float hor_unc_circular; + float vert_unc; + unsigned char confidence_horizontal; + unsigned char confidence_vertical; + rpc_int32 timestamp_age; +}; + +enum rpc_loc_server_open_status_e_type { + RPC_LOC_SERVER_OPEN_SUCCESS = 1, + RPC_LOC_SERVER_OPEN_FAIL = 2, + RPC_LOC_SERVER_OPEN_STATUS_MAX = 268435456 +}; + +enum rpc_loc_server_pdp_type_e_type { + RPC_LOC_SERVER_PDP_IP = 0, + RPC_LOC_SERVER_PDP_PPP, + RPC_LOC_SERVER_PDP_IPV6, + RPC_LOC_SERVER_PDP_IPV4V6, + RPC_LOC_SERVER_PDP_MAX = 268435456 +}; + +struct rpc_loc_server_open_status_s_type { + rpc_loc_server_connection_handle conn_handle; + rpc_loc_server_open_status_e_type open_status; + opaque apn_name[100]; +}; + +struct rpc_loc_server_multi_open_status_s_type { + rpc_loc_server_connection_handle conn_handle; + rpc_loc_server_open_status_e_type open_status; + rpc_loc_server_pdp_type_e_type pdp_type; + opaque apn_name[100]; +}; + +enum rpc_loc_server_close_status_e_type { + RPC_LOC_SERVER_CLOSE_SUCCESS = 1, + RPC_LOC_SERVER_CLOSE_FAIL = 2, + RPC_LOC_SERVER_CLOSE_STATUS_MAX = 268435456 +}; + +struct rpc_loc_server_close_status_s_type { + rpc_loc_server_connection_handle conn_handle; + rpc_loc_server_close_status_e_type close_status; +}; + +struct rpc_loc_wiper_fix_time_s_type { + rpc_uint32 slow_clock_count; +}; + +struct rpc_loc_wiper_fix_pos_s_type { + rpc_int32 lat; + rpc_int32 lon; + rpc_uint16 HEPE; + rpc_uint8 num_of_aps_used; + rpc_uint8 fix_error_code; +}; + +struct rpc_loc_wiper_ap_info_s_type { + opaque mac_addr[6]; + rpc_int32 rssi; + rpc_uint16 channel; + rpc_uint8 ap_qualifier; +}; + +struct rpc_loc_wiper_ap_set_s_type { + rpc_uint8 num_of_aps; + rpc_loc_wiper_ap_info_s_type ap_info[50]; +}; + +struct rpc_loc_wiper_position_report_s_type { + rpc_uint8 wiper_valid_info_flag; + rpc_loc_wiper_fix_time_s_type wiper_fix_time; + rpc_loc_wiper_fix_pos_s_type wiper_fix_position; + rpc_loc_wiper_ap_set_s_type wiper_ap_set; +}; + +enum rpc_loc_wiper_status_e_type { + RPC_LOC_WIPER_STATUS_AVAILABLE = 1, + RPC_LOC_WIPER_STATUS_UNAVAILABLE = 2, + RPC_LOC_WIPER_STATUS_E_SIZE = 268435456 +}; + +enum rpc_loc_fs_operation_e_type { + RPC_LOC_FS_CREATE_WRITE_FILE = 1, + RPC_LOC_FS_APPEND_FILE = 2, + RPC_LOC_FS_DELETE_FILE = 3, + RPC_LOC_FS_READ_FILE = 4, + RPC_LOC_FS_MAX = 268435456 +}; + +struct rpc_loc_efs_data_s_type { + opaque filename[64]; + rpc_loc_fs_operation_e_type operation; + rpc_uint32 total_size; + opaque data_ptr<>; + rpc_uint32 part_len; + rpc_uint8 part; + rpc_uint8 total_parts; + rpc_uint32 reserved; +}; + +enum rpc_loc_error_estimate_config_e_type { + RPC_LOC_ERROR_ESTIMATE_CONFIG_SET = 1, + RPC_LOC_ERROR_ESTIMATE_CONFIG_CLEAR = 2, + RPC_LOC_ERROR_ESTIMATE_MAX = 268435456 +}; + +struct rpc_loc_apn_profiles_type { + rpc_uint32 srv_system_type; + rpc_uint32 pdp_type; + rpc_uint32 reserved; + opaque apn_name[100]; +}; + +enum rpc_loc_lock_e_type { + RPC_LOC_LOCK_NONE = 1, + RPC_LOC_LOCK_MI = 2, + RPC_LOC_LOCK_MT = 3, + RPC_LOC_LOCK_ALL = 4, + RPC_LOC_LOCK_MAX = 268435456 +}; + +typedef rpc_uint32 rpc_loc_nmea_sentence_type; + +typedef rpc_uint32 rpc_loc_assist_data_type; + +struct rpc_loc_assist_data_delete_s_type { + rpc_loc_assist_data_type type; + rpc_uint32 reserved[8]; +}; + +union rpc_loc_ioctl_data_u_type switch (rpc_loc_ioctl_e_type disc) { + case RPC_LOC_IOCTL_SET_FIX_CRITERIA: + rpc_loc_fix_criteria_s_type fix_criteria; + case RPC_LOC_IOCTL_INFORM_NI_USER_RESPONSE: + rpc_loc_user_verify_s_type user_verify_resp; + case RPC_LOC_IOCTL_INJECT_PREDICTED_ORBITS_DATA: + rpc_loc_predicted_orbits_data_s_type predicted_orbits_data; + case RPC_LOC_IOCTL_SET_PREDICTED_ORBITS_DATA_AUTO_DOWNLOAD: + rpc_loc_predicted_orbits_auto_download_config_s_type predicted_orbits_auto_download; + case RPC_LOC_IOCTL_INJECT_UTC_TIME: + rpc_loc_assist_data_time_s_type assistance_data_time; + case RPC_LOC_IOCTL_INJECT_POSITION: + rpc_loc_assist_data_pos_s_type assistance_data_position; + case RPC_LOC_IOCTL_INFORM_SERVER_OPEN_STATUS: + rpc_loc_server_open_status_s_type conn_open_status; + case RPC_LOC_IOCTL_INFORM_SERVER_CLOSE_STATUS: + rpc_loc_server_close_status_s_type conn_close_status; + case RPC_LOC_IOCTL_SEND_WIPER_POSITION_REPORT: + rpc_loc_wiper_position_report_s_type wiper_pos; + case RPC_LOC_IOCTL_NOTIFY_WIPER_STATUS: + rpc_loc_wiper_status_e_type wiper_status; + case RPC_LOC_IOCTL_SET_ENGINE_LOCK: + rpc_loc_lock_e_type engine_lock; + case RPC_LOC_IOCTL_SET_SBAS_CONFIG: + rpc_boolean sbas_mode; + case RPC_LOC_IOCTL_SET_NMEA_TYPES: + rpc_loc_nmea_sentence_type nmea_types; + case RPC_LOC_IOCTL_SET_ON_DEMAND_LPM: + rpc_boolean on_demand_lpm; + case RPC_LOC_IOCTL_SET_CDMA_PDE_SERVER_ADDR: + case RPC_LOC_IOCTL_SET_CDMA_MPC_SERVER_ADDR: + case RPC_LOC_IOCTL_SET_UMTS_SLP_SERVER_ADDR: + case RPC_LOC_IOCTL_SET_CUSTOM_PDE_SERVER_ADDR: + rpc_loc_server_info_s_type server_addr; + case RPC_LOC_IOCTL_DELETE_ASSIST_DATA: + rpc_loc_assist_data_delete_s_type assist_data_delete; + case RPC_LOC_IOCTL_ACCESS_EFS_DATA: + rpc_loc_efs_data_s_type efs_data; + case RPC_LOC_IOCTL_ERROR_ESTIMATE_CONFIG: + rpc_loc_error_estimate_config_e_type error_estimate_config; + case RPC_LOC_IOCTL_SET_XTRA_T_SESSION_CONTROL: + rpc_uint8 xtra_t_session_control; + case RPC_LOC_IOCTL_SET_LBS_APN_PROFILE: + case RPC_LOC_IOCTL_SET_XTRA_APN_PROFILE: + rpc_loc_apn_profiles_type apn_profiles[6]; + case RPC_LOC_IOCTL_SET_DATA_ENABLE: + rpc_boolean data_enable; + case RPC_LOC_IOCTL_SET_SUPL_VERSION: + rpc_uint32 supl_version; + case RPC_LOC_IOCTL_INFORM_SERVER_MULTI_OPEN_STATUS: + rpc_loc_server_multi_open_status_s_type multi_conn_open_status; + case RPC_LOC_IOCTL_RESERVED_CMD: + rpc_loc_reserved_payload_s_type reserved; + default: + void; +}; + +union rpc_loc_ioctl_callback_data_u_type switch (rpc_loc_ioctl_e_type disc) { + case RPC_LOC_IOCTL_GET_API_VERSION: + rpc_loc_api_version_s_type api_version; + case RPC_LOC_IOCTL_GET_FIX_CRITERIA: + rpc_loc_fix_criteria_s_type fix_criteria; + case RPC_LOC_IOCTL_GET_ENGINE_LOCK: + rpc_loc_lock_e_type engine_lock; + case RPC_LOC_IOCTL_GET_SBAS_CONFIG: + rpc_boolean sbas_mode; + case RPC_LOC_IOCTL_GET_NMEA_TYPES: + rpc_loc_nmea_sentence_type nmea_types; + case RPC_LOC_IOCTL_GET_ON_DEMAND_LPM: + rpc_boolean on_demand_lpm; + case RPC_LOC_IOCTL_GET_CDMA_PDE_SERVER_ADDR: + case RPC_LOC_IOCTL_GET_CDMA_MPC_SERVER_ADDR: + case RPC_LOC_IOCTL_GET_UMTS_SLP_SERVER_ADDR: + case RPC_LOC_IOCTL_GET_CUSTOM_PDE_SERVER_ADDR: + rpc_loc_server_info_s_type server_addr; + case RPC_LOC_IOCTL_QUERY_PREDICTED_ORBITS_DATA_SOURCE: + rpc_loc_predicted_orbits_data_source_s_type predicted_orbits_data_source; + case RPC_LOC_IOCTL_QUERY_PREDICTED_ORBITS_DATA_VALIDITY: + rpc_loc_predicted_orbits_data_validity_report_s_type predicted_orbits_data_validity; + case RPC_LOC_IOCTL_GET_XTRA_T_SESSION_CONTROL: + rpc_uint8 xtra_t_session_control; + case RPC_LOC_IOCTL_GET_LBS_APN_PROFILE: + case RPC_LOC_IOCTL_GET_XTRA_APN_PROFILE: + rpc_loc_apn_profiles_type apn_profiles[6]; + case RPC_LOC_IOCTL_GET_SUPL_VERSION: + rpc_uint32 supl_version; + default: + void; +}; + +struct rpc_loc_ioctl_callback_s_type { + rpc_loc_ioctl_e_type type; + rpc_int32 status; + rpc_loc_ioctl_callback_data_u_type data; +}; + +union rpc_loc_event_payload_u_type switch (unsigned hyper disc) { + case RPC_LOC_EVENT_PARSED_POSITION_REPORT: + rpc_loc_parsed_position_s_type parsed_location_report; + case RPC_LOC_EVENT_SATELLITE_REPORT: + rpc_loc_gnss_info_s_type gnss_report; + case RPC_LOC_EVENT_NMEA_POSITION_REPORT: + case RPC_LOC_EVENT_NMEA_1HZ_REPORT: + rpc_loc_nmea_report_s_type nmea_report; + case RPC_LOC_EVENT_NI_NOTIFY_VERIFY_REQUEST: + rpc_loc_ni_event_s_type ni_request; + case RPC_LOC_EVENT_ASSISTANCE_DATA_REQUEST: + rpc_loc_assist_data_request_s_type assist_data_request; + case RPC_LOC_EVENT_LOCATION_SERVER_REQUEST: + rpc_loc_server_request_s_type loc_server_request; + case RPC_LOC_EVENT_IOCTL_REPORT: + rpc_loc_ioctl_callback_s_type ioctl_report; + case RPC_LOC_EVENT_STATUS_REPORT: + rpc_loc_status_event_s_type status_report; + case RPC_LOC_EVENT_WPS_NEEDED_REQUEST: + rpc_loc_qwip_request_s_type qwip_request; + case RPC_LOC_EVENT_RESERVED: + rpc_loc_reserved_payload_s_type reserved; + default: + void; +}; + diff --git a/gps/loc_api/libloc_api_50001/Android.mk b/gps/loc_api/libloc_api_50001/Android.mk new file mode 100644 index 000000000..a6d04f932 --- /dev/null +++ b/gps/loc_api/libloc_api_50001/Android.mk @@ -0,0 +1,106 @@ +ifneq ($(BUILD_TINY_ANDROID),true) +#Compile this library only for builds with the latest modem image + +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE := libloc_eng +LOCAL_MODULE_OWNER := qcom + +LOCAL_MODULE_TAGS := optional + +LOCAL_SHARED_LIBRARIES := \ + libutils \ + libcutils \ + libdl \ + liblog \ + libloc_core \ + libgps.utils + +LOCAL_SRC_FILES += \ + loc_eng.cpp \ + loc_eng_agps.cpp \ + loc_eng_xtra.cpp \ + loc_eng_ni.cpp \ + loc_eng_log.cpp \ + loc_eng_nmea.cpp \ + LocEngAdapter.cpp + +LOCAL_SRC_FILES += \ + loc_eng_dmn_conn.cpp \ + loc_eng_dmn_conn_handler.cpp \ + loc_eng_dmn_conn_thread_helper.c \ + loc_eng_dmn_conn_glue_msg.c \ + loc_eng_dmn_conn_glue_pipe.c + +LOCAL_CFLAGS += \ + -fno-short-enums \ + -D_ANDROID_ + +LOCAL_C_INCLUDES:= \ + $(TARGET_OUT_HEADERS)/gps.utils \ + $(TARGET_OUT_HEADERS)/libloc_core \ + $(LOCAL_PATH) \ + $(TARGET_OUT_HEADERS)/libflp + +LOCAL_COPY_HEADERS_TO:= libloc_eng/ +LOCAL_COPY_HEADERS:= \ + LocEngAdapter.h \ + loc.h \ + loc_eng.h \ + loc_eng_xtra.h \ + loc_eng_ni.h \ + loc_eng_agps.h \ + loc_eng_msg.h \ + loc_eng_log.h + +LOCAL_PRELINK_MODULE := false + +include $(BUILD_SHARED_LIBRARY) + +include $(CLEAR_VARS) + +LOCAL_MODULE := gps.$(TARGET_BOARD_PLATFORM) +LOCAL_MODULE_OWNER := qcom + +LOCAL_MODULE_TAGS := optional + +## Libs + +LOCAL_SHARED_LIBRARIES := \ + libutils \ + libcutils \ + liblog \ + libloc_eng \ + libloc_core \ + libgps.utils \ + libdl + +ifneq ($(filter $(TARGET_DEVICE), apq8084 msm8960), false) +endif + +LOCAL_SRC_FILES += \ + loc.cpp \ + gps.c + +LOCAL_CFLAGS += \ + -fno-short-enums \ + -D_ANDROID_ \ + +ifeq ($(TARGET_USES_QCOM_BSP), true) +LOCAL_CFLAGS += -DTARGET_USES_QCOM_BSP +endif + +## Includes +LOCAL_C_INCLUDES:= \ + $(TARGET_OUT_HEADERS)/gps.utils \ + $(TARGET_OUT_HEADERS)/libloc_core \ + $(TARGET_OUT_HEADERS)/libflp + +LOCAL_PRELINK_MODULE := false +LOCAL_MODULE_RELATIVE_PATH := hw + +include $(BUILD_SHARED_LIBRARY) + +endif # not BUILD_TINY_ANDROID diff --git a/gps/loc_api/libloc_api_50001/LocEngAdapter.cpp b/gps/loc_api/libloc_api_50001/LocEngAdapter.cpp new file mode 100644 index 000000000..e0f21ecee --- /dev/null +++ b/gps/loc_api/libloc_api_50001/LocEngAdapter.cpp @@ -0,0 +1,600 @@ +/* Copyright (c) 2011-2015, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#define LOG_NDDEBUG 0 +#define LOG_TAG "LocSvc_EngAdapter" + +#include +#include +#include +#include +#include +#include "loc_eng_msg.h" +#include "loc_log.h" + +#define CHIPSET_SERIAL_NUMBER_MAX_LEN 16 +#define USER_AGENT_MAX_LEN 512 + +using namespace loc_core; + +LocInternalAdapter::LocInternalAdapter(LocEngAdapter* adapter) : + LocAdapterBase(adapter->getMsgTask()), + mLocEngAdapter(adapter) +{ +} +void LocInternalAdapter::setPositionModeInt(LocPosMode& posMode) { + sendMsg(new LocEngPositionMode(mLocEngAdapter, posMode)); +} +void LocInternalAdapter::startFixInt() { + sendMsg(new LocEngStartFix(mLocEngAdapter)); +} +void LocInternalAdapter::stopFixInt() { + sendMsg(new LocEngStopFix(mLocEngAdapter)); +} +void LocInternalAdapter::getZppInt() { + sendMsg(new LocEngGetZpp(mLocEngAdapter)); +} + +LocEngAdapter::LocEngAdapter(LOC_API_ADAPTER_EVENT_MASK_T mask, + void* owner, ContextBase* context, + LocThread::tCreate tCreator) : + LocAdapterBase(mask, + //Get the AFW context if VzW context has not already been intialized in + //loc_ext + context == NULL? + LocDualContext::getLocFgContext(tCreator, + NULL, + LocDualContext::mLocationHalName, + false) + :context), + mOwner(owner), mInternalAdapter(new LocInternalAdapter(this)), + mUlp(new UlpProxyBase()), mNavigating(false), + mSupportsAgpsRequests(false), + mSupportsPositionInjection(false), + mSupportsTimeInjection(false), + mPowerVote(0) +{ + memset(&mFixCriteria, 0, sizeof(mFixCriteria)); + mFixCriteria.mode = LOC_POSITION_MODE_INVALID; + LOC_LOGD("LocEngAdapter created"); +} + +inline +LocEngAdapter::~LocEngAdapter() +{ + delete mInternalAdapter; + LOC_LOGV("LocEngAdapter deleted"); +} + +void LocEngAdapter::setXtraUserAgent() { + struct LocSetXtraUserAgent : public LocMsg { + const ContextBase* const mContext; + inline LocSetXtraUserAgent(ContextBase* context) : + LocMsg(), mContext(context) { + } + virtual void proc() const { + char release[PROPERTY_VALUE_MAX]; + char manufacture[PROPERTY_VALUE_MAX]; + char model[PROPERTY_VALUE_MAX]; + char board[PROPERTY_VALUE_MAX]; + char brand[PROPERTY_VALUE_MAX]; + char chipsetsn[CHIPSET_SERIAL_NUMBER_MAX_LEN]; + char userAgent[USER_AGENT_MAX_LEN]; + const char defVal[] = "-"; + + property_get("ro.build.version.release", release, defVal); + property_get("ro.product.manufacturer", manufacture, defVal); + property_get("ro.product.model", model, defVal); + property_get("ro.product.board", board, defVal); + property_get("ro.product.brand", brand, defVal); + getChipsetSerialNo(chipsetsn, sizeof(chipsetsn), defVal); + + encodeInPlace(release, PROPERTY_VALUE_MAX); + encodeInPlace(manufacture, PROPERTY_VALUE_MAX); + encodeInPlace(model, PROPERTY_VALUE_MAX); + encodeInPlace(board, PROPERTY_VALUE_MAX); + encodeInPlace(brand, PROPERTY_VALUE_MAX); + + snprintf(userAgent, sizeof(userAgent), "A/%s/%s/%s/%s/-/QCX3/s%u/-/%s/-/%s/-/-/-", + release, manufacture, model, board, + mContext->getIzatDevId(), chipsetsn, brand); + + for (int i = 0; i < sizeof(userAgent) && userAgent[i]; i++) { + if (' ' == userAgent[i]) userAgent[i] = '#'; + } + + saveUserAgentString(userAgent, strlen(userAgent)); + LOC_LOGV("%s] UserAgent %s", __func__, userAgent); + } + + void saveUserAgentString(const char* data, const int len) const { + const char XTRA_FOLDER[] = "/data/misc/location/xtra"; + const char USER_AGENT_FILE[] = "/data/misc/location/xtra/useragent.txt"; + + if (data == NULL || len < 1) { + LOC_LOGE("%s:%d]: invalid input data = %p len = %d", __func__, __LINE__, data, len); + return; + } + + struct stat s; + int err = stat(XTRA_FOLDER, &s); + if (err < 0) { + if (ENOENT == errno) { + if (mkdir(XTRA_FOLDER, 0700) < 0) { + LOC_LOGE("%s:%d]: make XTRA_FOLDER failed", __func__, __LINE__); + return; + } + } else { + LOC_LOGE("%s:%d]: XTRA_FOLDER invalid", __func__, __LINE__); + return; + } + } + + FILE* file = fopen(USER_AGENT_FILE, "wt"); + if (file == NULL) { + LOC_LOGE("%s:%d]: open USER_AGENT_FILE failed", __func__, __LINE__); + return; + } + + size_t written = fwrite(data, 1, len, file); + fclose(file); + file = NULL; + + // set file permission + chmod(USER_AGENT_FILE, 0600); + + if (written != len) { + LOC_LOGE("%s:%d]: write USER_AGENT_FILE failed", __func__, __LINE__); + } + } + + void getChipsetSerialNo(char buf[], int buflen, const char def[]) const { + const char SOC_SERIAL_NUMBER[] = "/sys/devices/soc0/serial_number"; + + FILE* file = fopen(SOC_SERIAL_NUMBER, "rt"); + if (file == NULL) { + // use default upon unreadable file + strlcpy(buf, def, buflen); + + } else { + size_t size = fread(buf, 1, buflen - 1, file); + if (size == 0) { + // use default upon empty file + strlcpy(buf, def, buflen); + + } else { + buf[size] = '\0'; + } + + fclose(file); + + // remove trailing spaces + char *s; + s = buf + strlen(buf); + while (--s >= buf) { + if (!isspace(*s)) break; + *s = 0; + } + } + + return; + } + + /** + * encode the given string value such that all separator characters ('/','+','|','%') + * in the string are repaced by their corresponding encodings (%2F","%2B","%7C", "%25") + */ + static void encodeInPlace(char value[], const int size) { + char buffer[size]; + + struct ENCODE { + const char ch; + const char *code; + }; + + const ENCODE encodings[] = { {'/', "%2F"}, {'+', "%2B"}, {'|', "%7C",}, {'%', "%25"} }; + const int nencodings = (int)sizeof(encodings) / sizeof(encodings[0]); + + int inpos = 0, outpos = 0; + while(value[inpos] != '\0' && outpos < size - 1) { + // check if escaped character + int escchar = 0; + while(escchar < nencodings && encodings[escchar].ch != value[inpos]) { + escchar++; + } + + if (escchar == nencodings) { + // non escaped character + buffer[outpos++] = value[inpos++]; + continue; + } + + // escaped character + int codepos = 0; + #define NUM_CHARS_IN_CODE 3 + + if (outpos + NUM_CHARS_IN_CODE >= size) { + // skip last character if there is insufficient space + break; + } + + while(outpos < size - 1 && codepos < NUM_CHARS_IN_CODE) { + buffer[outpos++] = encodings[escchar].code[codepos++]; + } + inpos++; + } + + // copy to ouput + value[outpos] = '\0'; + while(--outpos >= 0) { + value[outpos] = buffer[outpos]; + } + } + }; + + sendMsg(new LocSetXtraUserAgent(mContext)); +} + +void LocInternalAdapter::setUlpProxy(UlpProxyBase* ulp) { + struct LocSetUlpProxy : public LocMsg { + LocAdapterBase* mAdapter; + UlpProxyBase* mUlp; + inline LocSetUlpProxy(LocAdapterBase* adapter, UlpProxyBase* ulp) : + LocMsg(), mAdapter(adapter), mUlp(ulp) { + } + virtual void proc() const { + LOC_LOGV("%s] ulp %p adapter %p", __func__, + mUlp, mAdapter); + mAdapter->setUlpProxy(mUlp); + } + }; + + sendMsg(new LocSetUlpProxy(mLocEngAdapter, ulp)); +} + +void LocEngAdapter::setUlpProxy(UlpProxyBase* ulp) +{ + if (ulp == mUlp) { + //This takes care of the case when double initalization happens + //and we get the same object back for UlpProxyBase . Do nothing + return; + } + + LOC_LOGV("%s] %p", __func__, ulp); + if (NULL == ulp) { + LOC_LOGE("%s:%d]: ulp pointer is NULL", __func__, __LINE__); + ulp = new UlpProxyBase(); + } + + if (LOC_POSITION_MODE_INVALID != mUlp->mPosMode.mode) { + // need to send this mode and start msg to ULP + ulp->sendFixMode(mUlp->mPosMode); + } + + if(mUlp->mFixSet) { + ulp->sendStartFix(); + } + + delete mUlp; + mUlp = ulp; +} + +int LocEngAdapter::setGpsLockMsg(LOC_GPS_LOCK_MASK lockMask) +{ + struct LocEngAdapterGpsLock : public LocMsg { + LocEngAdapter* mAdapter; + LOC_GPS_LOCK_MASK mLockMask; + inline LocEngAdapterGpsLock(LocEngAdapter* adapter, LOC_GPS_LOCK_MASK lockMask) : + LocMsg(), mAdapter(adapter), mLockMask(lockMask) + { + locallog(); + } + inline virtual void proc() const { + mAdapter->setGpsLock(mLockMask); + } + inline void locallog() const { + LOC_LOGV("LocEngAdapterGpsLock - mLockMask: %x", mLockMask); + } + inline virtual void log() const { + locallog(); + } + }; + sendMsg(new LocEngAdapterGpsLock(this, lockMask)); + return 0; +} + +void LocEngAdapter::requestPowerVote() +{ + if (getPowerVoteRight()) { + /* Power voting without engine lock: + * 101: vote down, 102-104 - vote up + * These codes are used not to confuse with actual engine lock + * functionality, that can't be used in SSR scenario, as it + * conflicts with initialization sequence. + */ + bool powerUp = getPowerVote(); + LOC_LOGV("LocEngAdapterVotePower - Vote Power: %d", (int)powerUp); + setGpsLock(powerUp ? 103 : 101); + } +} + +void LocInternalAdapter::reportPosition(UlpLocation &location, + GpsLocationExtended &locationExtended, + void* locationExt, + enum loc_sess_status status, + LocPosTechMask loc_technology_mask) +{ + sendMsg(new LocEngReportPosition(mLocEngAdapter, + location, + locationExtended, + locationExt, + status, + loc_technology_mask)); +} + + +void LocEngAdapter::reportPosition(UlpLocation &location, + GpsLocationExtended &locationExtended, + void* locationExt, + enum loc_sess_status status, + LocPosTechMask loc_technology_mask) +{ + if (! mUlp->reportPosition(location, + locationExtended, + locationExt, + status, + loc_technology_mask )) { + mInternalAdapter->reportPosition(location, + locationExtended, + locationExt, + status, + loc_technology_mask); + } +} + +void LocInternalAdapter::reportSv(GnssSvStatus &svStatus, + GpsLocationExtended &locationExtended, + void* svExt){ + sendMsg(new LocEngReportSv(mLocEngAdapter, svStatus, + locationExtended, svExt)); +} + +void LocEngAdapter::reportSv(GnssSvStatus &svStatus, + GpsLocationExtended &locationExtended, + void* svExt) +{ + + // We want to send SV info to ULP to help it in determining GNSS + // signal strength ULP will forward the SV reports to HAL without + // any modifications + if (! mUlp->reportSv(svStatus, locationExtended, svExt)) { + mInternalAdapter->reportSv(svStatus, locationExtended, svExt); + } +} + +void LocEngAdapter::setInSession(bool inSession) +{ + mNavigating = inSession; + mLocApi->setInSession(inSession); + if (!mNavigating) { + mFixCriteria.mode = LOC_POSITION_MODE_INVALID; + } +} + +void LocInternalAdapter::reportStatus(GpsStatusValue status) +{ + sendMsg(new LocEngReportStatus(mLocEngAdapter, status)); +} + +void LocEngAdapter::reportStatus(GpsStatusValue status) +{ + if (!mUlp->reportStatus(status)) { + mInternalAdapter->reportStatus(status); + } +} + +inline +void LocEngAdapter::reportNmea(const char* nmea, int length) +{ + sendMsg(new LocEngReportNmea(mOwner, nmea, length)); +} + +inline +bool LocEngAdapter::reportXtraServer(const char* url1, + const char* url2, + const char* url3, + const int maxlength) +{ + if (mSupportsAgpsRequests) { + sendMsg(new LocEngReportXtraServer(mOwner, url1, + url2, url3, maxlength)); + } + return mSupportsAgpsRequests; +} + +inline +bool LocEngAdapter::requestATL(int connHandle, AGpsType agps_type) +{ + if (mSupportsAgpsRequests) { + sendMsg(new LocEngRequestATL(mOwner, + connHandle, agps_type)); + } + return mSupportsAgpsRequests; +} + +inline +bool LocEngAdapter::releaseATL(int connHandle) +{ + if (mSupportsAgpsRequests) { + sendMsg(new LocEngReleaseATL(mOwner, connHandle)); + } + return mSupportsAgpsRequests; +} + +inline +bool LocEngAdapter::requestXtraData() +{ + if (mSupportsAgpsRequests) { + sendMsg(new LocEngRequestXtra(mOwner)); + } + return mSupportsAgpsRequests; +} + +inline +bool LocEngAdapter::requestTime() +{ + if (mSupportsAgpsRequests) { + sendMsg(new LocEngRequestTime(mOwner)); + } + return mSupportsAgpsRequests; +} + +inline +bool LocEngAdapter::requestNiNotify(GpsNiNotification ¬if, const void* data) +{ + if (mSupportsAgpsRequests) { + notif.size = sizeof(notif); + notif.timeout = LOC_NI_NO_RESPONSE_TIME; + + sendMsg(new LocEngRequestNi(mOwner, notif, data)); + } + return mSupportsAgpsRequests; +} + +inline +bool LocEngAdapter::requestSuplES(int connHandle) +{ + if (mSupportsAgpsRequests) + sendMsg(new LocEngRequestSuplEs(mOwner, connHandle)); + return mSupportsAgpsRequests; +} + +inline +bool LocEngAdapter::reportDataCallOpened() +{ + if(mSupportsAgpsRequests) + sendMsg(new LocEngSuplEsOpened(mOwner)); + return mSupportsAgpsRequests; +} + +inline +bool LocEngAdapter::reportDataCallClosed() +{ + if(mSupportsAgpsRequests) + sendMsg(new LocEngSuplEsClosed(mOwner)); + return mSupportsAgpsRequests; +} + +inline +void LocEngAdapter::handleEngineDownEvent() +{ + sendMsg(new LocEngDown(mOwner)); +} + +inline +void LocEngAdapter::handleEngineUpEvent() +{ + sendMsg(new LocEngUp(mOwner)); +} + +enum loc_api_adapter_err LocEngAdapter::setTime(GpsUtcTime time, + int64_t timeReference, + int uncertainty) +{ + loc_api_adapter_err result = LOC_API_ADAPTER_ERR_SUCCESS; + + LOC_LOGD("%s:%d]: mSupportsTimeInjection is %d", + __func__, __LINE__, mSupportsTimeInjection); + + if (mSupportsTimeInjection) { + LOC_LOGD("%s:%d]: Injecting time", __func__, __LINE__); + result = mLocApi->setTime(time, timeReference, uncertainty); + } else { + mSupportsTimeInjection = true; + } + return result; +} + +enum loc_api_adapter_err LocEngAdapter::setXtraVersionCheck(int check) +{ + enum loc_api_adapter_err ret; + ENTRY_LOG(); + enum xtra_version_check eCheck; + switch (check) { + case 0: + eCheck = DISABLED; + break; + case 1: + eCheck = AUTO; + break; + case 2: + eCheck = XTRA2; + break; + case 3: + eCheck = XTRA3; + break; + default: + eCheck = DISABLED; + } + ret = mLocApi->setXtraVersionCheck(eCheck); + EXIT_LOG(%d, ret); + return ret; +} + +void LocEngAdapter::reportGpsMeasurementData(GpsData &gpsMeasurementData) +{ + sendMsg(new LocEngReportGpsMeasurement(mOwner, + gpsMeasurementData)); +} + +/* + Update Registration Mask + */ +void LocEngAdapter::updateRegistrationMask(LOC_API_ADAPTER_EVENT_MASK_T event, + loc_registration_mask_status isEnabled) +{ + LOC_LOGD("entering %s", __func__); + int result = LOC_API_ADAPTER_ERR_FAILURE; + result = mLocApi->updateRegistrationMask(event, isEnabled); + if (result == LOC_API_ADAPTER_ERR_SUCCESS) { + LOC_LOGD("%s] update registration mask succeed.", __func__); + } else { + LOC_LOGE("%s] update registration mask failed.", __func__); + } +} + +/* + Set Gnss Constellation Config + */ +bool LocEngAdapter::gnssConstellationConfig() +{ + LOC_LOGD("entering %s", __func__); + bool result = false; + result = mLocApi->gnssConstellationConfig(); + return result; +} diff --git a/gps/loc_api/libloc_api_50001/LocEngAdapter.h b/gps/loc_api/libloc_api_50001/LocEngAdapter.h new file mode 100644 index 000000000..a193e8189 --- /dev/null +++ b/gps/loc_api/libloc_api_50001/LocEngAdapter.h @@ -0,0 +1,351 @@ +/* Copyright (c) 2011-2015, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef LOC_API_ENG_ADAPTER_H +#define LOC_API_ENG_ADAPTER_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_URL_LEN 256 + +using namespace loc_core; + +class LocEngAdapter; + +class LocInternalAdapter : public LocAdapterBase { + LocEngAdapter* mLocEngAdapter; +public: + LocInternalAdapter(LocEngAdapter* adapter); + + virtual void reportPosition(UlpLocation &location, + GpsLocationExtended &locationExtended, + void* locationExt, + enum loc_sess_status status, + LocPosTechMask loc_technology_mask); + virtual void reportSv(GnssSvStatus &svStatus, + GpsLocationExtended &locationExtended, + void* svExt); + virtual void reportStatus(GpsStatusValue status); + virtual void setPositionModeInt(LocPosMode& posMode); + virtual void startFixInt(); + virtual void stopFixInt(); + virtual void getZppInt(); + virtual void setUlpProxy(UlpProxyBase* ulp); +}; + +typedef void (*loc_msg_sender)(void* loc_eng_data_p, void* msgp); + +class LocEngAdapter : public LocAdapterBase { + void* mOwner; + LocInternalAdapter* mInternalAdapter; + UlpProxyBase* mUlp; + LocPosMode mFixCriteria; + bool mNavigating; + // mPowerVote is encoded as + // mPowerVote & 0x20 -- powerVoteRight + // mPowerVote & 0x10 -- power On / Off + unsigned int mPowerVote; + static const unsigned int POWER_VOTE_RIGHT = 0x20; + static const unsigned int POWER_VOTE_VALUE = 0x10; + +public: + bool mSupportsAgpsRequests; + bool mSupportsPositionInjection; + bool mSupportsTimeInjection; + + LocEngAdapter(LOC_API_ADAPTER_EVENT_MASK_T mask, + void* owner, ContextBase* context, + LocThread::tCreate tCreator); + virtual ~LocEngAdapter(); + + virtual void setUlpProxy(UlpProxyBase* ulp); + void setXtraUserAgent(); + inline void requestUlp(unsigned long capabilities) { + mContext->requestUlp(mInternalAdapter, capabilities); + } + inline LocInternalAdapter* getInternalAdapter() { return mInternalAdapter; } + inline UlpProxyBase* getUlpProxy() { return mUlp; } + inline void* getOwner() { return mOwner; } + inline bool hasAgpsExtendedCapabilities() { + return mContext->hasAgpsExtendedCapabilities(); + } + inline bool hasCPIExtendedCapabilities() { + return mContext->hasCPIExtendedCapabilities(); + } + inline const MsgTask* getMsgTask() { return mMsgTask; } + + inline enum loc_api_adapter_err + startFix() + { + return mLocApi->startFix(mFixCriteria); + } + inline enum loc_api_adapter_err + stopFix() + { + return mLocApi->stopFix(); + } + inline enum loc_api_adapter_err + deleteAidingData(GpsAidingData f) + { + return mLocApi->deleteAidingData(f); + } + inline enum loc_api_adapter_err + enableData(int enable) + { + return mLocApi->enableData(enable); + } + inline enum loc_api_adapter_err + setAPN(char* apn, int len) + { + return mLocApi->setAPN(apn, len); + } + inline enum loc_api_adapter_err + injectPosition(double latitude, double longitude, float accuracy) + { + return mLocApi->injectPosition(latitude, longitude, accuracy); + } + inline enum loc_api_adapter_err + setXtraData(char* data, int length) + { + return mLocApi->setXtraData(data, length); + } + inline enum loc_api_adapter_err + requestXtraServer() + { + return mLocApi->requestXtraServer(); + } + inline enum loc_api_adapter_err + atlOpenStatus(int handle, int is_succ, char* apn, AGpsBearerType bearer, AGpsType agpsType) + { + return mLocApi->atlOpenStatus(handle, is_succ, apn, bearer, agpsType); + } + inline enum loc_api_adapter_err + atlCloseStatus(int handle, int is_succ) + { + return mLocApi->atlCloseStatus(handle, is_succ); + } + inline enum loc_api_adapter_err + setPositionMode(const LocPosMode *posMode) + { + if (NULL != posMode) { + mFixCriteria = *posMode; + } + return mLocApi->setPositionMode(mFixCriteria); + } + inline enum loc_api_adapter_err + setServer(const char* url, int len) + { + return mLocApi->setServer(url, len); + } + inline enum loc_api_adapter_err + setServer(unsigned int ip, int port, + LocServerType type) + { + return mLocApi->setServer(ip, port, type); + } + inline enum loc_api_adapter_err + informNiResponse(GpsUserResponseType userResponse, const void* passThroughData) + { + return mLocApi->informNiResponse(userResponse, passThroughData); + } + inline enum loc_api_adapter_err + setSUPLVersion(uint32_t version) + { + return mLocApi->setSUPLVersion(version); + } + inline enum loc_api_adapter_err + setLPPConfig(uint32_t profile) + { + return mLocApi->setLPPConfig(profile); + } + inline enum loc_api_adapter_err + setSensorControlConfig(int sensorUsage, int sensorProvider) + { + return mLocApi->setSensorControlConfig(sensorUsage, sensorProvider); + } + inline enum loc_api_adapter_err + setSensorProperties(bool gyroBiasVarianceRandomWalk_valid, float gyroBiasVarianceRandomWalk, + bool accelBiasVarianceRandomWalk_valid, float accelBiasVarianceRandomWalk, + bool angleBiasVarianceRandomWalk_valid, float angleBiasVarianceRandomWalk, + bool rateBiasVarianceRandomWalk_valid, float rateBiasVarianceRandomWalk, + bool velocityBiasVarianceRandomWalk_valid, float velocityBiasVarianceRandomWalk) + { + return mLocApi->setSensorProperties(gyroBiasVarianceRandomWalk_valid, gyroBiasVarianceRandomWalk, + accelBiasVarianceRandomWalk_valid, accelBiasVarianceRandomWalk, + angleBiasVarianceRandomWalk_valid, angleBiasVarianceRandomWalk, + rateBiasVarianceRandomWalk_valid, rateBiasVarianceRandomWalk, + velocityBiasVarianceRandomWalk_valid, velocityBiasVarianceRandomWalk); + } + inline virtual enum loc_api_adapter_err + setSensorPerfControlConfig(int controlMode, int accelSamplesPerBatch, int accelBatchesPerSec, + int gyroSamplesPerBatch, int gyroBatchesPerSec, + int accelSamplesPerBatchHigh, int accelBatchesPerSecHigh, + int gyroSamplesPerBatchHigh, int gyroBatchesPerSecHigh, int algorithmConfig) + { + return mLocApi->setSensorPerfControlConfig(controlMode, accelSamplesPerBatch, accelBatchesPerSec, + gyroSamplesPerBatch, gyroBatchesPerSec, + accelSamplesPerBatchHigh, accelBatchesPerSecHigh, + gyroSamplesPerBatchHigh, gyroBatchesPerSecHigh, + algorithmConfig); + } + inline virtual enum loc_api_adapter_err + setExtPowerConfig(int isBatteryCharging) + { + return mLocApi->setExtPowerConfig(isBatteryCharging); + } + inline virtual enum loc_api_adapter_err + setAGLONASSProtocol(unsigned long aGlonassProtocol) + { + return mLocApi->setAGLONASSProtocol(aGlonassProtocol); + } + inline virtual int initDataServiceClient() + { + return mLocApi->initDataServiceClient(); + } + inline virtual int openAndStartDataCall() + { + return mLocApi->openAndStartDataCall(); + } + inline virtual void stopDataCall() + { + mLocApi->stopDataCall(); + } + inline virtual void closeDataCall() + { + mLocApi->closeDataCall(); + } + inline enum loc_api_adapter_err + getZpp(GpsLocation &zppLoc, LocPosTechMask &tech_mask) + { + return mLocApi->getBestAvailableZppFix(zppLoc, tech_mask); + } + enum loc_api_adapter_err setTime(GpsUtcTime time, + int64_t timeReference, + int uncertainty); + enum loc_api_adapter_err setXtraVersionCheck(int check); + inline virtual void installAGpsCert(const DerEncodedCertificate* pData, + size_t length, + uint32_t slotBitMask) + { + mLocApi->installAGpsCert(pData, length, slotBitMask); + } + virtual void handleEngineDownEvent(); + virtual void handleEngineUpEvent(); + virtual void reportPosition(UlpLocation &location, + GpsLocationExtended &locationExtended, + void* locationExt, + enum loc_sess_status status, + LocPosTechMask loc_technology_mask); + virtual void reportSv(GnssSvStatus &svStatus, + GpsLocationExtended &locationExtended, + void* svExt); + virtual void reportStatus(GpsStatusValue status); + virtual void reportNmea(const char* nmea, int length); + virtual bool reportXtraServer(const char* url1, const char* url2, + const char* url3, const int maxlength); + virtual bool requestXtraData(); + virtual bool requestTime(); + virtual bool requestATL(int connHandle, AGpsType agps_type); + virtual bool releaseATL(int connHandle); + virtual bool requestNiNotify(GpsNiNotification ¬ify, const void* data); + virtual bool requestSuplES(int connHandle); + virtual bool reportDataCallOpened(); + virtual bool reportDataCallClosed(); + virtual void reportGpsMeasurementData(GpsData &gpsMeasurementData); + + inline const LocPosMode& getPositionMode() const + {return mFixCriteria;} + inline virtual bool isInSession() + { return mNavigating; } + void setInSession(bool inSession); + + // Permit/prohibit power voting + inline void setPowerVoteRight(bool powerVoteRight) { + mPowerVote = powerVoteRight ? (mPowerVote | POWER_VOTE_RIGHT) : + (mPowerVote & ~POWER_VOTE_RIGHT); + } + inline bool getPowerVoteRight() const { + return (mPowerVote & POWER_VOTE_RIGHT) != 0 ; + } + // Set the power voting up/down and do actual operation if permitted + inline void setPowerVote(bool powerOn) { + mPowerVote = powerOn ? (mPowerVote | POWER_VOTE_VALUE) : + (mPowerVote & ~POWER_VOTE_VALUE); + requestPowerVote(); + mContext->modemPowerVote(powerOn); + } + inline bool getPowerVote() const { + return (mPowerVote & POWER_VOTE_VALUE) != 0 ; + } + // Do power voting according to last settings if permitted + void requestPowerVote(); + + /*Values for lock + 1 = Do not lock any position sessions + 2 = Lock MI position sessions + 3 = Lock MT position sessions + 4 = Lock all position sessions + */ + inline int setGpsLock(LOC_GPS_LOCK_MASK lock) + { + return mLocApi->setGpsLock(lock); + } + + int setGpsLockMsg(LOC_GPS_LOCK_MASK lock); + + /* + Returns + Current value of GPS lock on success + -1 on failure + */ + inline int getGpsLock() + { + return mLocApi->getGpsLock(); + } + + /* + Update Registration Mask + */ + void updateRegistrationMask(LOC_API_ADAPTER_EVENT_MASK_T event, + loc_registration_mask_status isEnabled); + + /* + Set Gnss Constellation Config + */ + bool gnssConstellationConfig(); +}; + +#endif //LOC_API_ENG_ADAPTER_H diff --git a/gps/loc_api/libloc_api_50001/Makefile.am b/gps/loc_api/libloc_api_50001/Makefile.am new file mode 100644 index 000000000..237435704 --- /dev/null +++ b/gps/loc_api/libloc_api_50001/Makefile.am @@ -0,0 +1,76 @@ +AM_CFLAGS = \ + -I../../utils \ + -I../../platform_lib_abstractions \ + -fno-short-enums \ + -DFEATURE_GNSS_BIT_API + +libloc_adapter_so_la_SOURCES = loc_eng_log.cpp LocEngAdapter.cpp + +if USE_GLIB +libloc_adapter_so_la_CFLAGS = -DUSE_GLIB $(AM_CFLAGS) @GLIB_CFLAGS@ +libloc_adapter_so_la_LDFLAGS = -lstdc++ -lpthread @GLIB_LIBS@ -shared -version-info 1:0:0 +libloc_adapter_so_la_CPPFLAGS = -DUSE_GLIB $(AM_CFLAGS) $(AM_CPPFLAGS) @GLIB_CFLAGS@ +else +libloc_adapter_so_la_CFLAGS = $(AM_CFLAGS) +libloc_adapter_so_la_LDFLAGS = -lpthread -shared -version-info 1:0:0 +libloc_adapter_so_la_CPPFLAGS = $(AM_CFLAGS) $(AM_CPPFLAGS) +endif +libloc_adapter_so_la_LIBADD = -lstdc++ -lcutils ../../utils/libgps_utils_so.la + + +libloc_eng_so_la_SOURCES = \ + loc_eng.cpp \ + loc_eng_agps.cpp \ + loc_eng_xtra.cpp \ + loc_eng_ni.cpp \ + loc_eng_log.cpp \ + loc_eng_dmn_conn.cpp \ + loc_eng_dmn_conn_handler.cpp \ + loc_eng_dmn_conn_thread_helper.c \ + loc_eng_dmn_conn_glue_msg.c \ + loc_eng_dmn_conn_glue_pipe.c + + +if USE_GLIB +libloc_eng_so_la_CFLAGS = -DUSE_GLIB $(AM_CFLAGS) @GLIB_CFLAGS@ +libloc_eng_so_la_LDFLAGS = -lstdc++ -lpthread @GLIB_LIBS@ -shared -version-info 1:0:0 +libloc_eng_so_la_CPPFLAGS = -DUSE_GLIB $(AM_CFLAGS) $(AM_CPPFLAGS) @GLIB_CFLAGS@ +else +libloc_eng_so_la_CFLAGS = $(AM_CFLAGS) +libloc_eng_so_la_LDFLAGS = -lpthread -shared -version-info 1:0:0 +libloc_eng_so_la_CPPFLAGS = $(AM_CFLAGS) $(AM_CPPFLAGS) +endif + +libloc_eng_so_la_LIBADD = -lstdc++ -lcutils -ldl ../../utils/libgps_utils_so.la libloc_adapter_so.la + + +libgps_default_so_la_SOURCES = \ + loc.cpp \ + gps.c + +if USE_GLIB +libgps_default_so_la_CFLAGS = -DUSE_GLIB $(AM_CFLAGS) @GLIB_CFLAGS@ +libgps_default_so_la_LDFLAGS = -lstdc++ -lpthread @GLIB_LIBS@ -shared -version-info 1:0:0 +libgps_default_so_la_CPPFLAGS = -DUSE_GLIB $(AM_CFLAGS) $(AM_CPPFLAGS) @GLIB_CFLAGS@ +else +libgps_default_so_la_CFLAGS = $(AM_CFLAGS) +libgps_default_so_la_LDFLAGS = -lpthread -shared -version-info 1:0:0 +libgps_default_so_la_CPPFLAGS = $(AM_CFLAGS) $(AM_CPPFLAGS) +endif + +libgps_default_so_la_LIBADD = -lstdc++ -lcutils ../../utils/libgps_utils_so.la -ldl libloc_eng_so.la + +library_include_HEADERS = \ + LocEngAdapter.h \ + loc.h \ + loc_eng.h \ + loc_eng_xtra.h \ + loc_eng_ni.h \ + loc_eng_agps.h \ + loc_eng_msg.h \ + loc_eng_log.h + +library_includedir = $(pkgincludedir)/libloc_api_50001 + +#Create and Install libraries +lib_LTLIBRARIES = libloc_adapter_so.la libloc_eng_so.la libgps_default_so.la diff --git a/gps/loc_api/libloc_api_50001/gps.c b/gps/loc_api/libloc_api_50001/gps.c new file mode 100644 index 000000000..29f20f42d --- /dev/null +++ b/gps/loc_api/libloc_api_50001/gps.c @@ -0,0 +1,73 @@ +/* Copyright (c) 2011,2015 The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include + +#include +#include + +extern const GpsInterface* get_gps_interface(); + +const GpsInterface* gps__get_gps_interface(struct gps_device_t* dev) +{ + return get_gps_interface(); +} + +static int open_gps(const struct hw_module_t* module, char const* name, + struct hw_device_t** device) +{ + struct gps_device_t *dev = (struct gps_device_t *) malloc(sizeof(struct gps_device_t)); + + if(dev == NULL) + return -1; + + memset(dev, 0, sizeof(*dev)); + + dev->common.tag = HARDWARE_DEVICE_TAG; + dev->common.version = 0; + dev->common.module = (struct hw_module_t*)module; + dev->get_gps_interface = gps__get_gps_interface; + + *device = (struct hw_device_t*)dev; + return 0; +} + +static struct hw_module_methods_t gps_module_methods = { + .open = open_gps +}; + +struct hw_module_t HAL_MODULE_INFO_SYM = { + .tag = HARDWARE_MODULE_TAG, + .module_api_version = 1, + .hal_api_version = 0, + .id = GPS_HARDWARE_MODULE_ID, + .name = "loc_api GPS Module", + .author = "Qualcomm USA, Inc.", + .methods = &gps_module_methods, +}; diff --git a/gps/loc_api/libloc_api_50001/loc.cpp b/gps/loc_api/libloc_api_50001/loc.cpp new file mode 100644 index 000000000..505fc940d --- /dev/null +++ b/gps/loc_api/libloc_api_50001/loc.cpp @@ -0,0 +1,1077 @@ +/* Copyright (c) 2011-2015, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#define LOG_NDDEBUG 0 +#define LOG_TAG "LocSvc_afw" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace loc_core; + +#define LOC_PM_CLIENT_NAME "GPS" + +//Globals defns +static gps_location_callback gps_loc_cb = NULL; +static gps_sv_status_callback gps_sv_cb = NULL; + +static void local_loc_cb(UlpLocation* location, void* locExt); +static void local_sv_cb(GpsSvStatus* sv_status, void* svExt); + +static const GpsGeofencingInterface* get_geofence_interface(void); + +// Function declarations for sLocEngInterface +static int loc_init(GpsCallbacks* callbacks); +static int loc_start(); +static int loc_stop(); +static void loc_cleanup(); +static int loc_inject_time(GpsUtcTime time, int64_t timeReference, int uncertainty); +static int loc_inject_location(double latitude, double longitude, float accuracy); +static void loc_delete_aiding_data(GpsAidingData f); +static int loc_set_position_mode(GpsPositionMode mode, GpsPositionRecurrence recurrence, + uint32_t min_interval, uint32_t preferred_accuracy, + uint32_t preferred_time); +static const void* loc_get_extension(const char* name); +// Defines the GpsInterface in gps.h +static const GpsInterface sLocEngInterface = +{ + sizeof(GpsInterface), + loc_init, + loc_start, + loc_stop, + loc_cleanup, + loc_inject_time, + loc_inject_location, + loc_delete_aiding_data, + loc_set_position_mode, + loc_get_extension +}; + +// Function declarations for sLocEngAGpsInterface +static void loc_agps_init(AGpsCallbacks* callbacks); +static int loc_agps_open(const char* apn); +static int loc_agps_closed(); +static int loc_agps_open_failed(); +static int loc_agps_set_server(AGpsType type, const char *hostname, int port); +static int loc_agps_open_with_apniptype( const char* apn, ApnIpType apnIpType); + +static const AGpsInterface sLocEngAGpsInterface = +{ + sizeof(AGpsInterface), + loc_agps_init, + loc_agps_open, + loc_agps_closed, + loc_agps_open_failed, + loc_agps_set_server, + loc_agps_open_with_apniptype +}; + +static int loc_xtra_init(GpsXtraCallbacks* callbacks); +static int loc_xtra_inject_data(char* data, int length); + +static const GpsXtraInterface sLocEngXTRAInterface = +{ + sizeof(GpsXtraInterface), + loc_xtra_init, + loc_xtra_inject_data +}; + +static void loc_ni_init(GpsNiCallbacks *callbacks); +static void loc_ni_respond(int notif_id, GpsUserResponseType user_response); + +static const GpsNiInterface sLocEngNiInterface = +{ + sizeof(GpsNiInterface), + loc_ni_init, + loc_ni_respond, +}; + +static int loc_gps_measurement_init(GpsMeasurementCallbacks* callbacks); +static void loc_gps_measurement_close(); + +static const GpsMeasurementInterface sLocEngGpsMeasurementInterface = +{ + sizeof(GpsMeasurementInterface), + loc_gps_measurement_init, + loc_gps_measurement_close +}; + +static void loc_agps_ril_init( AGpsRilCallbacks* callbacks ); +static void loc_agps_ril_set_ref_location(const AGpsRefLocation *agps_reflocation, size_t sz_struct); +static void loc_agps_ril_set_set_id(AGpsSetIDType type, const char* setid); +static void loc_agps_ril_ni_message(uint8_t *msg, size_t len); +static void loc_agps_ril_update_network_state(int connected, int type, int roaming, const char* extra_info); +static void loc_agps_ril_update_network_availability(int avaiable, const char* apn); + +static const AGpsRilInterface sLocEngAGpsRilInterface = +{ + sizeof(AGpsRilInterface), + loc_agps_ril_init, + loc_agps_ril_set_ref_location, + loc_agps_ril_set_set_id, + loc_agps_ril_ni_message, + loc_agps_ril_update_network_state, + loc_agps_ril_update_network_availability +}; + +static int loc_agps_install_certificates(const DerEncodedCertificate* certificates, + size_t length); +static int loc_agps_revoke_certificates(const Sha1CertificateFingerprint* fingerprints, + size_t length); + +static const SuplCertificateInterface sLocEngAGpsCertInterface = +{ + sizeof(SuplCertificateInterface), + loc_agps_install_certificates, + loc_agps_revoke_certificates +}; + +static void loc_configuration_update(const char* config_data, int32_t length); + +static const GnssConfigurationInterface sLocEngConfigInterface = +{ + sizeof(GnssConfigurationInterface), + loc_configuration_update +}; + +static loc_eng_data_s_type loc_afw_data; +static int gss_fd = -1; +static int sGnssType = GNSS_UNKNOWN; +/*=========================================================================== +FUNCTION gps_get_hardware_interface + +DESCRIPTION + Returns the GPS hardware interaface based on LOC API + if GPS is enabled. + +DEPENDENCIES + None + +RETURN VALUE + 0: success + +SIDE EFFECTS + N/A + +===========================================================================*/ +const GpsInterface* gps_get_hardware_interface () +{ + ENTRY_LOG_CALLFLOW(); + const GpsInterface* ret_val; + + char propBuf[PROPERTY_VALUE_MAX]; + + loc_eng_read_config(); + + // check to see if GPS should be disabled + property_get("gps.disable", propBuf, ""); + if (propBuf[0] == '1') + { + LOC_LOGD("gps_get_interface returning NULL because gps.disable=1\n"); + ret_val = NULL; + } else { + ret_val = &sLocEngInterface; + } + + loc_eng_read_config(); + + EXIT_LOG(%p, ret_val); + return ret_val; +} + +// for gps.c +extern "C" const GpsInterface* get_gps_interface() +{ + unsigned int target = TARGET_DEFAULT; + loc_eng_read_config(); + + target = loc_get_target(); + LOC_LOGD("Target name check returned %s", loc_get_target_name(target)); + + sGnssType = getTargetGnssType(target); + switch (sGnssType) + { + case GNSS_GSS: + case GNSS_AUTO: + //APQ8064 + gps_conf.CAPABILITIES &= ~(GPS_CAPABILITY_MSA | GPS_CAPABILITY_MSB); + gss_fd = open("/dev/gss", O_RDONLY); + if (gss_fd < 0) { + LOC_LOGE("GSS open failed: %s\n", strerror(errno)); + } + else { + LOC_LOGD("GSS open success! CAPABILITIES %0lx\n", + gps_conf.CAPABILITIES); + } + break; + case GNSS_NONE: + //MPQ8064 + LOC_LOGE("No GPS HW on this target. Not returning interface."); + return NULL; + case GNSS_QCA1530: + // qca1530 chip is present + gps_conf.CAPABILITIES &= ~(GPS_CAPABILITY_MSA | GPS_CAPABILITY_MSB); + LOC_LOGD("qca1530 present: CAPABILITIES %0lx\n", gps_conf.CAPABILITIES); + break; + } + return &sLocEngInterface; +} + +/*=========================================================================== +FUNCTION loc_init + +DESCRIPTION + Initialize the location engine, this include setting up global datas + and registers location engien with loc api service. + +DEPENDENCIES + None + +RETURN VALUE + 0: success + +SIDE EFFECTS + N/Ax + +===========================================================================*/ +static int loc_init(GpsCallbacks* callbacks) +{ + int retVal = -1; + ENTRY_LOG(); + LOC_API_ADAPTER_EVENT_MASK_T event; + + if (NULL == callbacks) { + LOC_LOGE("loc_init failed. cb = NULL\n"); + EXIT_LOG(%d, retVal); + return retVal; + } + + event = LOC_API_ADAPTER_BIT_PARSED_POSITION_REPORT | + LOC_API_ADAPTER_BIT_SATELLITE_REPORT | + LOC_API_ADAPTER_BIT_LOCATION_SERVER_REQUEST | + LOC_API_ADAPTER_BIT_ASSISTANCE_DATA_REQUEST | + LOC_API_ADAPTER_BIT_IOCTL_REPORT | + LOC_API_ADAPTER_BIT_STATUS_REPORT | + LOC_API_ADAPTER_BIT_NMEA_1HZ_REPORT | + LOC_API_ADAPTER_BIT_NI_NOTIFY_VERIFY_REQUEST; + + LocCallbacks clientCallbacks = {local_loc_cb, /* location_cb */ + callbacks->status_cb, /* status_cb */ + local_sv_cb, /* sv_status_cb */ + callbacks->nmea_cb, /* nmea_cb */ + callbacks->set_capabilities_cb, /* set_capabilities_cb */ + callbacks->acquire_wakelock_cb, /* acquire_wakelock_cb */ + callbacks->release_wakelock_cb, /* release_wakelock_cb */ + callbacks->create_thread_cb, /* create_thread_cb */ + NULL, /* location_ext_parser */ + NULL, /* sv_ext_parser */ + callbacks->request_utc_time_cb, /* request_utc_time_cb */ + }; + + gps_loc_cb = callbacks->location_cb; + gps_sv_cb = callbacks->sv_status_cb; + + retVal = loc_eng_init(loc_afw_data, &clientCallbacks, event, NULL); + loc_afw_data.adapter->mSupportsAgpsRequests = !loc_afw_data.adapter->hasAgpsExtendedCapabilities(); + loc_afw_data.adapter->mSupportsPositionInjection = !loc_afw_data.adapter->hasCPIExtendedCapabilities(); + loc_afw_data.adapter->mSupportsTimeInjection = !loc_afw_data.adapter->hasCPIExtendedCapabilities(); + loc_afw_data.adapter->setGpsLockMsg(0); + loc_afw_data.adapter->requestUlp(getCarrierCapabilities()); + loc_afw_data.adapter->setXtraUserAgent(); + + if(retVal) { + LOC_LOGE("loc_eng_init() fail!"); + goto err; + } + + loc_afw_data.adapter->setPowerVoteRight(loc_get_target() == TARGET_QCA1530); + loc_afw_data.adapter->setPowerVote(true); + + LOC_LOGD("loc_eng_init() success!"); + +err: + EXIT_LOG(%d, retVal); + return retVal; +} + +/*=========================================================================== +FUNCTION loc_cleanup + +DESCRIPTION + Cleans location engine. The location client handle will be released. + +DEPENDENCIES + None + +RETURN VALUE + None + +SIDE EFFECTS + N/A + +===========================================================================*/ +static void loc_cleanup() +{ + ENTRY_LOG(); + + loc_afw_data.adapter->setPowerVote(false); + loc_afw_data.adapter->setGpsLockMsg(gps_conf.GPS_LOCK); + + loc_eng_cleanup(loc_afw_data); + gps_loc_cb = NULL; + gps_sv_cb = NULL; + + EXIT_LOG(%s, VOID_RET); +} + +/*=========================================================================== +FUNCTION loc_start + +DESCRIPTION + Starts the tracking session + +DEPENDENCIES + None + +RETURN VALUE + 0: success + +SIDE EFFECTS + N/A + +===========================================================================*/ +static int loc_start() +{ + ENTRY_LOG(); + int ret_val = loc_eng_start(loc_afw_data); + + EXIT_LOG(%d, ret_val); + return ret_val; +} + +/*=========================================================================== +FUNCTION loc_stop + +DESCRIPTION + Stops the tracking session + +DEPENDENCIES + None + +RETURN VALUE + 0: success + +SIDE EFFECTS + N/A + +===========================================================================*/ +static int loc_stop() +{ + ENTRY_LOG(); + int ret_val = -1; + ret_val = loc_eng_stop(loc_afw_data); + + EXIT_LOG(%d, ret_val); + return ret_val; +} + +/*=========================================================================== +FUNCTION loc_set_position_mode + +DESCRIPTION + Sets the mode and fix frequency for the tracking session. + +DEPENDENCIES + None + +RETURN VALUE + 0: success + +SIDE EFFECTS + N/A + +===========================================================================*/ +static int loc_set_position_mode(GpsPositionMode mode, + GpsPositionRecurrence recurrence, + uint32_t min_interval, + uint32_t preferred_accuracy, + uint32_t preferred_time) +{ + ENTRY_LOG(); + int ret_val = -1; + LocPositionMode locMode; + switch (mode) { + case GPS_POSITION_MODE_MS_BASED: + locMode = LOC_POSITION_MODE_MS_BASED; + break; + case GPS_POSITION_MODE_MS_ASSISTED: + locMode = LOC_POSITION_MODE_MS_ASSISTED; + break; + default: + locMode = LOC_POSITION_MODE_STANDALONE; + break; + } + + LocPosMode params(locMode, recurrence, min_interval, + preferred_accuracy, preferred_time, NULL, NULL); + ret_val = loc_eng_set_position_mode(loc_afw_data, params); + + EXIT_LOG(%d, ret_val); + return ret_val; +} + +/*=========================================================================== +FUNCTION loc_inject_time + +DESCRIPTION + This is used by Java native function to do time injection. + +DEPENDENCIES + None + +RETURN VALUE + 0 + +SIDE EFFECTS + N/A + +===========================================================================*/ +static int loc_inject_time(GpsUtcTime time, int64_t timeReference, int uncertainty) +{ + ENTRY_LOG(); + int ret_val = 0; + + ret_val = loc_eng_inject_time(loc_afw_data, time, + timeReference, uncertainty); + + EXIT_LOG(%d, ret_val); + return ret_val; +} + + +/*=========================================================================== +FUNCTION loc_inject_location + +DESCRIPTION + This is used by Java native function to do location injection. + +DEPENDENCIES + None + +RETURN VALUE + 0 : Successful + error code : Failure + +SIDE EFFECTS + N/A +===========================================================================*/ +static int loc_inject_location(double latitude, double longitude, float accuracy) +{ + ENTRY_LOG(); + + int ret_val = 0; + ret_val = loc_eng_inject_location(loc_afw_data, latitude, longitude, accuracy); + + EXIT_LOG(%d, ret_val); + return ret_val; +} + + +/*=========================================================================== +FUNCTION loc_delete_aiding_data + +DESCRIPTION + This is used by Java native function to delete the aiding data. The function + updates the global variable for the aiding data to be deleted. If the GPS + engine is off, the aiding data will be deleted. Otherwise, the actual action + will happen when gps engine is turned off. + +DEPENDENCIES + Assumes the aiding data type specified in GpsAidingData matches with + LOC API specification. + +RETURN VALUE + None + +SIDE EFFECTS + N/A + +===========================================================================*/ +static void loc_delete_aiding_data(GpsAidingData f) +{ + ENTRY_LOG(); + loc_eng_delete_aiding_data(loc_afw_data, f); + + EXIT_LOG(%s, VOID_RET); +} + +const GpsGeofencingInterface* get_geofence_interface(void) +{ + ENTRY_LOG(); + void *handle; + const char *error; + typedef const GpsGeofencingInterface* (*get_gps_geofence_interface_function) (void); + get_gps_geofence_interface_function get_gps_geofence_interface; + static const GpsGeofencingInterface* geofence_interface = NULL; + + dlerror(); /* Clear any existing error */ + + handle = dlopen ("libgeofence.so", RTLD_NOW); + + if (!handle) + { + if ((error = dlerror()) != NULL) { + LOC_LOGE ("%s, dlopen for libgeofence.so failed, error = %s\n", __func__, error); + } + goto exit; + } + dlerror(); /* Clear any existing error */ + get_gps_geofence_interface = (get_gps_geofence_interface_function)dlsym(handle, "gps_geofence_get_interface"); + if ((error = dlerror()) != NULL || NULL == get_gps_geofence_interface) { + LOC_LOGE ("%s, dlsym for get_gps_geofence_interface failed, error = %s\n", __func__, error); + goto exit; + } + + geofence_interface = get_gps_geofence_interface(); + +exit: + EXIT_LOG(%d, geofence_interface == NULL); + return geofence_interface; +} +/*=========================================================================== +FUNCTION loc_get_extension + +DESCRIPTION + Get the gps extension to support XTRA. + +DEPENDENCIES + N/A + +RETURN VALUE + The GPS extension interface. + +SIDE EFFECTS + N/A + +===========================================================================*/ +const void* loc_get_extension(const char* name) +{ + ENTRY_LOG(); + const void* ret_val = NULL; + + LOC_LOGD("%s:%d] For Interface = %s\n",__func__, __LINE__, name); + if (strcmp(name, GPS_XTRA_INTERFACE) == 0) + { + ret_val = &sLocEngXTRAInterface; + } + else if (strcmp(name, AGPS_INTERFACE) == 0) + { + ret_val = &sLocEngAGpsInterface; + } + else if (strcmp(name, GPS_NI_INTERFACE) == 0) + { + ret_val = &sLocEngNiInterface; + } + else if (strcmp(name, AGPS_RIL_INTERFACE) == 0) + { + char baseband[PROPERTY_VALUE_MAX]; + property_get("ro.baseband", baseband, "msm"); + if (strcmp(baseband, "csfb") == 0) + { + ret_val = &sLocEngAGpsRilInterface; + } + } + else if (strcmp(name, GPS_GEOFENCING_INTERFACE) == 0) + { + if ((gps_conf.CAPABILITIES | GPS_CAPABILITY_GEOFENCING) == gps_conf.CAPABILITIES ){ + ret_val = get_geofence_interface(); + } + } + else if (strcmp(name, SUPL_CERTIFICATE_INTERFACE) == 0) + { + ret_val = &sLocEngAGpsCertInterface; + } + else if (strcmp(name, GNSS_CONFIGURATION_INTERFACE) == 0) + { + ret_val = &sLocEngConfigInterface; + } + else if (strcmp(name, GPS_MEASUREMENT_INTERFACE) == 0) + { + ret_val = &sLocEngGpsMeasurementInterface; + } + else + { + LOC_LOGE ("get_extension: Invalid interface passed in\n"); + } + EXIT_LOG(%p, ret_val); + return ret_val; +} + +/*=========================================================================== +FUNCTION loc_agps_init + +DESCRIPTION + Initialize the AGps interface. + +DEPENDENCIES + NONE + +RETURN VALUE + 0 + +SIDE EFFECTS + N/A + +===========================================================================*/ +static void loc_agps_init(AGpsCallbacks* callbacks) +{ + ENTRY_LOG(); + loc_eng_agps_init(loc_afw_data, (AGpsExtCallbacks*)callbacks); + EXIT_LOG(%s, VOID_RET); +} + +/*=========================================================================== +FUNCTION loc_agps_open + +DESCRIPTION + This function is called when on-demand data connection opening is successful. +It should inform ARM 9 about the data open result. + +DEPENDENCIES + NONE + +RETURN VALUE + 0 + +SIDE EFFECTS + N/A + +===========================================================================*/ +static int loc_agps_open(const char* apn) +{ + ENTRY_LOG(); + AGpsType agpsType = AGPS_TYPE_SUPL; + AGpsBearerType bearerType = AGPS_APN_BEARER_IPV4; + int ret_val = loc_eng_agps_open(loc_afw_data, agpsType, apn, bearerType); + + EXIT_LOG(%d, ret_val); + return ret_val; +} + +/*=========================================================================== +FUNCTION loc_agps_open_with_apniptype + +DESCRIPTION + This function is called when on-demand data connection opening is successful. +It should inform ARM 9 about the data open result. + +DEPENDENCIES + NONE + +RETURN VALUE + 0 + +SIDE EFFECTS + N/A + +===========================================================================*/ +static int loc_agps_open_with_apniptype(const char* apn, ApnIpType apnIpType) +{ + ENTRY_LOG(); + AGpsType agpsType = AGPS_TYPE_SUPL; + AGpsBearerType bearerType; + + switch (apnIpType) { + case APN_IP_IPV4: + bearerType = AGPS_APN_BEARER_IPV4; + break; + case APN_IP_IPV6: + bearerType = AGPS_APN_BEARER_IPV6; + break; + case APN_IP_IPV4V6: + bearerType = AGPS_APN_BEARER_IPV4V6; + break; + default: + bearerType = AGPS_APN_BEARER_INVALID; + break; + } + + int ret_val = loc_eng_agps_open(loc_afw_data, agpsType, apn, bearerType); + + EXIT_LOG(%d, ret_val); + return ret_val; +} + +/*=========================================================================== +FUNCTION loc_agps_closed + +DESCRIPTION + This function is called when on-demand data connection closing is done. +It should inform ARM 9 about the data close result. + +DEPENDENCIES + NONE + +RETURN VALUE + 0 + +SIDE EFFECTS + N/A + +===========================================================================*/ +static int loc_agps_closed() +{ + ENTRY_LOG(); + AGpsType agpsType = AGPS_TYPE_SUPL; + int ret_val = loc_eng_agps_closed(loc_afw_data, agpsType); + + EXIT_LOG(%d, ret_val); + return ret_val; +} + +/*=========================================================================== +FUNCTION loc_agps_open_failed + +DESCRIPTION + This function is called when on-demand data connection opening has failed. +It should inform ARM 9 about the data open result. + +DEPENDENCIES + NONE + +RETURN VALUE + 0 + +SIDE EFFECTS + N/A + +===========================================================================*/ +int loc_agps_open_failed() +{ + ENTRY_LOG(); + AGpsType agpsType = AGPS_TYPE_SUPL; + int ret_val = loc_eng_agps_open_failed(loc_afw_data, agpsType); + + EXIT_LOG(%d, ret_val); + return ret_val; +} + +/*=========================================================================== +FUNCTION loc_agps_set_server + +DESCRIPTION + If loc_eng_set_server is called before loc_eng_init, it doesn't work. This + proxy buffers server settings and calls loc_eng_set_server when the client is + open. + +DEPENDENCIES + NONE + +RETURN VALUE + 0 + +SIDE EFFECTS + N/A + +===========================================================================*/ +static int loc_agps_set_server(AGpsType type, const char* hostname, int port) +{ + ENTRY_LOG(); + LocServerType serverType; + switch (type) { + case AGPS_TYPE_SUPL: + serverType = LOC_AGPS_SUPL_SERVER; + break; + case AGPS_TYPE_C2K: + serverType = LOC_AGPS_CDMA_PDE_SERVER; + break; + default: + serverType = LOC_AGPS_SUPL_SERVER; + } + int ret_val = loc_eng_set_server_proxy(loc_afw_data, serverType, hostname, port); + + EXIT_LOG(%d, ret_val); + return ret_val; +} + +/*=========================================================================== +FUNCTIONf571 + loc_xtra_init + +DESCRIPTION + Initialize XTRA module. + +DEPENDENCIES + None + +RETURN VALUE + 0: success + +SIDE EFFECTS + N/A + +===========================================================================*/ +static int loc_xtra_init(GpsXtraCallbacks* callbacks) +{ + ENTRY_LOG(); + GpsXtraExtCallbacks extCallbacks; + memset(&extCallbacks, 0, sizeof(extCallbacks)); + extCallbacks.download_request_cb = callbacks->download_request_cb; + int ret_val = loc_eng_xtra_init(loc_afw_data, &extCallbacks); + + EXIT_LOG(%d, ret_val); + return ret_val; +} + + +/*=========================================================================== +FUNCTION loc_xtra_inject_data + +DESCRIPTION + Initialize XTRA module. + +DEPENDENCIES + None + +RETURN VALUE + 0: success + +SIDE EFFECTS + N/A + +===========================================================================*/ +static int loc_xtra_inject_data(char* data, int length) +{ + ENTRY_LOG(); + int ret_val = -1; + if( (data != NULL) && ((unsigned int)length <= XTRA_DATA_MAX_SIZE)) + ret_val = loc_eng_xtra_inject_data(loc_afw_data, data, length); + else + LOC_LOGE("%s, Could not inject XTRA data. Buffer address: %p, length: %d", + __func__, data, length); + EXIT_LOG(%d, ret_val); + return ret_val; +} + +/*=========================================================================== +FUNCTION loc_gps_measurement_init + +DESCRIPTION + This function initializes the gps measurement interface + +DEPENDENCIES + NONE + +RETURN VALUE + None + +SIDE EFFECTS + N/A + +===========================================================================*/ +static int loc_gps_measurement_init(GpsMeasurementCallbacks* callbacks) +{ + ENTRY_LOG(); + int ret_val = loc_eng_gps_measurement_init(loc_afw_data, + callbacks); + + EXIT_LOG(%d, ret_val); + return ret_val; +} + +/*=========================================================================== +FUNCTION loc_gps_measurement_close + +DESCRIPTION + This function closes the gps measurement interface + +DEPENDENCIES + NONE + +RETURN VALUE + None + +SIDE EFFECTS + N/A + +===========================================================================*/ +static void loc_gps_measurement_close() +{ + ENTRY_LOG(); + loc_eng_gps_measurement_close(loc_afw_data); + + EXIT_LOG(%s, VOID_RET); +} + +/*=========================================================================== +FUNCTION loc_ni_init + +DESCRIPTION + This function initializes the NI interface + +DEPENDENCIES + NONE + +RETURN VALUE + None + +SIDE EFFECTS + N/A + +===========================================================================*/ +void loc_ni_init(GpsNiCallbacks *callbacks) +{ + ENTRY_LOG(); + loc_eng_ni_init(loc_afw_data,(GpsNiExtCallbacks*) callbacks); + EXIT_LOG(%s, VOID_RET); +} + +/*=========================================================================== +FUNCTION loc_ni_respond + +DESCRIPTION + This function sends an NI respond to the modem processor + +DEPENDENCIES + NONE + +RETURN VALUE + None + +SIDE EFFECTS + N/A + +===========================================================================*/ +void loc_ni_respond(int notif_id, GpsUserResponseType user_response) +{ + ENTRY_LOG(); + loc_eng_ni_respond(loc_afw_data, notif_id, user_response); + EXIT_LOG(%s, VOID_RET); +} + +// Below stub functions are members of sLocEngAGpsRilInterface +static void loc_agps_ril_init( AGpsRilCallbacks* callbacks ) {} +static void loc_agps_ril_set_ref_location(const AGpsRefLocation *agps_reflocation, size_t sz_struct) {} +static void loc_agps_ril_set_set_id(AGpsSetIDType type, const char* setid) {} +static void loc_agps_ril_ni_message(uint8_t *msg, size_t len) {} +static void loc_agps_ril_update_network_state(int connected, int type, int roaming, const char* extra_info) {} + +/*=========================================================================== +FUNCTION loc_agps_ril_update_network_availability + +DESCRIPTION + Sets data call allow vs disallow flag to modem + This is the only member of sLocEngAGpsRilInterface implemented. + +DEPENDENCIES + None + +RETURN VALUE + 0: success + +SIDE EFFECTS + N/A + +===========================================================================*/ +static void loc_agps_ril_update_network_availability(int available, const char* apn) +{ + ENTRY_LOG(); + loc_eng_agps_ril_update_network_availability(loc_afw_data, available, apn); + EXIT_LOG(%s, VOID_RET); +} + +static int loc_agps_install_certificates(const DerEncodedCertificate* certificates, + size_t length) +{ + ENTRY_LOG(); + int ret_val = loc_eng_agps_install_certificates(loc_afw_data, certificates, length); + EXIT_LOG(%d, ret_val); + return ret_val; +} +static int loc_agps_revoke_certificates(const Sha1CertificateFingerprint* fingerprints, + size_t length) +{ + ENTRY_LOG(); + LOC_LOGE("%s:%d]: agps_revoke_certificates not supported"); + int ret_val = AGPS_CERTIFICATE_ERROR_GENERIC; + EXIT_LOG(%d, ret_val); + return ret_val; +} + +static void loc_configuration_update(const char* config_data, int32_t length) +{ + ENTRY_LOG(); + loc_eng_configuration_update(loc_afw_data, config_data, length); + switch (sGnssType) + { + case GNSS_GSS: + case GNSS_AUTO: + case GNSS_QCA1530: + //APQ + gps_conf.CAPABILITIES &= ~(GPS_CAPABILITY_MSA | GPS_CAPABILITY_MSB); + break; + } + EXIT_LOG(%s, VOID_RET); +} + +static void local_loc_cb(UlpLocation* location, void* locExt) +{ + ENTRY_LOG(); + if (NULL != location) { + CALLBACK_LOG_CALLFLOW("location_cb - from", %d, location->position_source); + + if (NULL != gps_loc_cb) { + gps_loc_cb(&location->gpsLocation); + } + } + EXIT_LOG(%s, VOID_RET); +} + +static void local_sv_cb(GpsSvStatus* sv_status, void* svExt) +{ + ENTRY_LOG(); + if (NULL != gps_sv_cb) { + CALLBACK_LOG_CALLFLOW("sv_status_cb -", %d, sv_status->num_svs); + gps_sv_cb(sv_status); + } + EXIT_LOG(%s, VOID_RET); +} + diff --git a/gps/loc_api/libloc_api_50001/loc.h b/gps/loc_api/libloc_api_50001/loc.h new file mode 100644 index 000000000..e56fdcf8c --- /dev/null +++ b/gps/loc_api/libloc_api_50001/loc.h @@ -0,0 +1,66 @@ +/* Copyright (c) 2011,2014 The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef __LOC_H__ +#define __LOC_H__ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include +#include +#include +#include + +#define XTRA_DATA_MAX_SIZE 100000 /*bytes*/ + +typedef void (*loc_location_cb_ext) (UlpLocation* location, void* locExt); +typedef void (*loc_sv_status_cb_ext) (GpsSvStatus* sv_status, void* svExt); +typedef void* (*loc_ext_parser)(void* data); + +typedef struct { + loc_location_cb_ext location_cb; + gps_status_callback status_cb; + loc_sv_status_cb_ext sv_status_cb; + gps_nmea_callback nmea_cb; + gps_set_capabilities set_capabilities_cb; + gps_acquire_wakelock acquire_wakelock_cb; + gps_release_wakelock release_wakelock_cb; + gps_create_thread create_thread_cb; + loc_ext_parser location_ext_parser; + loc_ext_parser sv_ext_parser; + gps_request_utc_time request_utc_time_cb; +} LocCallbacks; + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif //__LOC_H__ diff --git a/gps/loc_api/libloc_api_50001/loc_eng.cpp b/gps/loc_api/libloc_api_50001/loc_eng.cpp new file mode 100644 index 000000000..2ba6f9826 --- /dev/null +++ b/gps/loc_api/libloc_api_50001/loc_eng.cpp @@ -0,0 +1,2999 @@ +/* Copyright (c) 2009-2015, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#define LOG_NDDEBUG 0 +#define LOG_TAG "LocSvc_eng" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* struct sockaddr_in */ +#include +#include +#include +#include +#include +#include + +#include +#ifndef USE_GLIB +#include +#include +#endif /* USE_GLIB */ + +#ifdef USE_GLIB +#include +#include +#endif /* USE_GLIB */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include "log_util.h" +#include "platform_lib_includes.h" +#include "loc_core_log.h" +#include "loc_eng_log.h" + +#define SUCCESS TRUE +#define FAILURE FALSE + +#ifndef GPS_CONF_FILE +#define GPS_CONF_FILE "/etc/gps.conf" //??? platform independent +#endif + +#ifndef SAP_CONF_FILE +#define SAP_CONF_FILE "/etc/sap.conf" +#endif + +#define XTRA1_GPSONEXTRA "xtra1.gpsonextra.net" + +using namespace loc_core; + +boolean configAlreadyRead = false; +unsigned int agpsStatus = 0; +loc_gps_cfg_s_type gps_conf; +loc_sap_cfg_s_type sap_conf; + +/* Parameter spec table */ +static const loc_param_s_type gps_conf_table[] = +{ + {"GPS_LOCK", &gps_conf.GPS_LOCK, NULL, 'n'}, + {"SUPL_VER", &gps_conf.SUPL_VER, NULL, 'n'}, + {"LPP_PROFILE", &gps_conf.LPP_PROFILE, NULL, 'n'}, + {"A_GLONASS_POS_PROTOCOL_SELECT", &gps_conf.A_GLONASS_POS_PROTOCOL_SELECT, NULL, 'n'}, + {"AGPS_CERT_WRITABLE_MASK", &gps_conf.AGPS_CERT_WRITABLE_MASK, NULL, 'n'}, + {"SUPL_MODE", &gps_conf.SUPL_MODE, NULL, 'n'}, + {"INTERMEDIATE_POS", &gps_conf.INTERMEDIATE_POS, NULL, 'n'}, + {"ACCURACY_THRES", &gps_conf.ACCURACY_THRES, NULL, 'n'}, + {"NMEA_PROVIDER", &gps_conf.NMEA_PROVIDER, NULL, 'n'}, + {"CAPABILITIES", &gps_conf.CAPABILITIES, NULL, 'n'}, + {"XTRA_VERSION_CHECK", &gps_conf.XTRA_VERSION_CHECK, NULL, 'n'}, + {"XTRA_SERVER_1", &gps_conf.XTRA_SERVER_1, NULL, 's'}, + {"XTRA_SERVER_2", &gps_conf.XTRA_SERVER_2, NULL, 's'}, + {"XTRA_SERVER_3", &gps_conf.XTRA_SERVER_3, NULL, 's'}, + {"USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL", &gps_conf.USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL, NULL, 'n'}, +}; + +static const loc_param_s_type sap_conf_table[] = +{ + {"GYRO_BIAS_RANDOM_WALK", &sap_conf.GYRO_BIAS_RANDOM_WALK, &sap_conf.GYRO_BIAS_RANDOM_WALK_VALID, 'f'}, + {"ACCEL_RANDOM_WALK_SPECTRAL_DENSITY", &sap_conf.ACCEL_RANDOM_WALK_SPECTRAL_DENSITY, &sap_conf.ACCEL_RANDOM_WALK_SPECTRAL_DENSITY_VALID, 'f'}, + {"ANGLE_RANDOM_WALK_SPECTRAL_DENSITY", &sap_conf.ANGLE_RANDOM_WALK_SPECTRAL_DENSITY, &sap_conf.ANGLE_RANDOM_WALK_SPECTRAL_DENSITY_VALID, 'f'}, + {"RATE_RANDOM_WALK_SPECTRAL_DENSITY", &sap_conf.RATE_RANDOM_WALK_SPECTRAL_DENSITY, &sap_conf.RATE_RANDOM_WALK_SPECTRAL_DENSITY_VALID, 'f'}, + {"VELOCITY_RANDOM_WALK_SPECTRAL_DENSITY", &sap_conf.VELOCITY_RANDOM_WALK_SPECTRAL_DENSITY, &sap_conf.VELOCITY_RANDOM_WALK_SPECTRAL_DENSITY_VALID, 'f'}, + {"SENSOR_ACCEL_BATCHES_PER_SEC", &sap_conf.SENSOR_ACCEL_BATCHES_PER_SEC, NULL, 'n'}, + {"SENSOR_ACCEL_SAMPLES_PER_BATCH", &sap_conf.SENSOR_ACCEL_SAMPLES_PER_BATCH, NULL, 'n'}, + {"SENSOR_GYRO_BATCHES_PER_SEC", &sap_conf.SENSOR_GYRO_BATCHES_PER_SEC, NULL, 'n'}, + {"SENSOR_GYRO_SAMPLES_PER_BATCH", &sap_conf.SENSOR_GYRO_SAMPLES_PER_BATCH, NULL, 'n'}, + {"SENSOR_ACCEL_BATCHES_PER_SEC_HIGH", &sap_conf.SENSOR_ACCEL_BATCHES_PER_SEC_HIGH, NULL, 'n'}, + {"SENSOR_ACCEL_SAMPLES_PER_BATCH_HIGH", &sap_conf.SENSOR_ACCEL_SAMPLES_PER_BATCH_HIGH, NULL, 'n'}, + {"SENSOR_GYRO_BATCHES_PER_SEC_HIGH", &sap_conf.SENSOR_GYRO_BATCHES_PER_SEC_HIGH, NULL, 'n'}, + {"SENSOR_GYRO_SAMPLES_PER_BATCH_HIGH", &sap_conf.SENSOR_GYRO_SAMPLES_PER_BATCH_HIGH, NULL, 'n'}, + {"SENSOR_CONTROL_MODE", &sap_conf.SENSOR_CONTROL_MODE, NULL, 'n'}, + {"SENSOR_USAGE", &sap_conf.SENSOR_USAGE, NULL, 'n'}, + {"SENSOR_ALGORITHM_CONFIG_MASK", &sap_conf.SENSOR_ALGORITHM_CONFIG_MASK, NULL, 'n'}, + {"SENSOR_PROVIDER", &sap_conf.SENSOR_PROVIDER, NULL, 'n'} +}; + +static void loc_default_parameters(void) +{ + /*Defaults for gps.conf*/ + gps_conf.INTERMEDIATE_POS = 0; + gps_conf.ACCURACY_THRES = 0; + gps_conf.NMEA_PROVIDER = 0; + gps_conf.GPS_LOCK = 0; + gps_conf.SUPL_VER = 0x10000; + gps_conf.SUPL_MODE = 0x3; + gps_conf.CAPABILITIES = 0x7; + /* LTE Positioning Profile configuration is disable by default*/ + gps_conf.LPP_PROFILE = 0; + /*By default no positioning protocol is selected on A-GLONASS system*/ + gps_conf.A_GLONASS_POS_PROTOCOL_SELECT = 0; + /*XTRA version check is disabled by default*/ + gps_conf.XTRA_VERSION_CHECK=0; + /*Use emergency PDN by default*/ + gps_conf.USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL = 1; + + /*Defaults for sap.conf*/ + sap_conf.GYRO_BIAS_RANDOM_WALK = 0; + sap_conf.SENSOR_ACCEL_BATCHES_PER_SEC = 2; + sap_conf.SENSOR_ACCEL_SAMPLES_PER_BATCH = 5; + sap_conf.SENSOR_GYRO_BATCHES_PER_SEC = 2; + sap_conf.SENSOR_GYRO_SAMPLES_PER_BATCH = 5; + sap_conf.SENSOR_ACCEL_BATCHES_PER_SEC_HIGH = 4; + sap_conf.SENSOR_ACCEL_SAMPLES_PER_BATCH_HIGH = 25; + sap_conf.SENSOR_GYRO_BATCHES_PER_SEC_HIGH = 4; + sap_conf.SENSOR_GYRO_SAMPLES_PER_BATCH_HIGH = 25; + sap_conf.SENSOR_CONTROL_MODE = 0; /* AUTO */ + sap_conf.SENSOR_USAGE = 0; /* Enabled */ + sap_conf.SENSOR_ALGORITHM_CONFIG_MASK = 0; /* INS Disabled = FALSE*/ + /* Values MUST be set by OEMs in configuration for sensor-assisted + navigation to work. There are NO default values */ + sap_conf.ACCEL_RANDOM_WALK_SPECTRAL_DENSITY = 0; + sap_conf.ANGLE_RANDOM_WALK_SPECTRAL_DENSITY = 0; + sap_conf.RATE_RANDOM_WALK_SPECTRAL_DENSITY = 0; + sap_conf.VELOCITY_RANDOM_WALK_SPECTRAL_DENSITY = 0; + sap_conf.GYRO_BIAS_RANDOM_WALK_VALID = 0; + sap_conf.ACCEL_RANDOM_WALK_SPECTRAL_DENSITY_VALID = 0; + sap_conf.ANGLE_RANDOM_WALK_SPECTRAL_DENSITY_VALID = 0; + sap_conf.RATE_RANDOM_WALK_SPECTRAL_DENSITY_VALID = 0; + sap_conf.VELOCITY_RANDOM_WALK_SPECTRAL_DENSITY_VALID = 0; + /* default provider is SSC */ + sap_conf.SENSOR_PROVIDER = 1; + + /* None of the 10 slots for agps certificates are writable by default */ + gps_conf.AGPS_CERT_WRITABLE_MASK = 0; +} + +// 2nd half of init(), singled out for +// modem restart to use. +static int loc_eng_reinit(loc_eng_data_s_type &loc_eng_data); +static void loc_eng_agps_reinit(loc_eng_data_s_type &loc_eng_data); + +static int loc_eng_set_server(loc_eng_data_s_type &loc_eng_data, + LocServerType type, const char *hostname, int port); +// Internal functions +static void loc_inform_gps_status(loc_eng_data_s_type &loc_eng_data, + GpsStatusValue status); +static void loc_eng_report_status(loc_eng_data_s_type &loc_eng_data, + GpsStatusValue status); +static void loc_eng_process_conn_request(loc_eng_data_s_type &loc_eng_data, + int connHandle, AGpsType agps_type); +static void loc_eng_agps_close_status(loc_eng_data_s_type &loc_eng_data, int is_succ); +static void loc_eng_handle_engine_down(loc_eng_data_s_type &loc_eng_data) ; +static void loc_eng_handle_engine_up(loc_eng_data_s_type &loc_eng_data) ; + +static int loc_eng_start_handler(loc_eng_data_s_type &loc_eng_data); +static int loc_eng_stop_handler(loc_eng_data_s_type &loc_eng_data); +static int loc_eng_get_zpp_handler(loc_eng_data_s_type &loc_eng_data); +static void deleteAidingData(loc_eng_data_s_type &logEng); +static AgpsStateMachine* +getAgpsStateMachine(loc_eng_data_s_type& logEng, AGpsExtType agpsType); +static int dataCallCb(void *cb_data); +static void update_aiding_data_for_deletion(loc_eng_data_s_type& loc_eng_data) { + if (loc_eng_data.engine_status != GPS_STATUS_ENGINE_ON && + loc_eng_data.aiding_data_for_deletion != 0) + { + loc_eng_data.adapter->deleteAidingData(loc_eng_data.aiding_data_for_deletion); + loc_eng_data.aiding_data_for_deletion = 0; + } +} + +static void* noProc(void* data) +{ + return NULL; +} + +/********************************************************************* + * definitions of the static messages used in the file + *********************************************************************/ +// case LOC_ENG_MSG_REQUEST_NI: +LocEngRequestNi::LocEngRequestNi(void* locEng, + GpsNiNotification ¬if, + const void* data) : + LocMsg(), mLocEng(locEng), mNotify(notif), mPayload(data) { + locallog(); +} +void LocEngRequestNi::proc() const { + loc_eng_ni_request_handler(*((loc_eng_data_s_type*)mLocEng), + &mNotify, mPayload); +} +void LocEngRequestNi::locallog() const +{ + LOC_LOGV("id: %d\n type: %s\n flags: %d\n time out: %d\n " + "default response: %s\n requestor id encoding: %s\n" + " text encoding: %s\n passThroughData: %p", + mNotify.notification_id, + loc_get_ni_type_name(mNotify.ni_type), + mNotify.notify_flags, + mNotify.timeout, + loc_get_ni_response_name(mNotify.default_response), + loc_get_ni_encoding_name(mNotify.requestor_id_encoding), + loc_get_ni_encoding_name(mNotify.text_encoding), + mPayload); +} +inline void LocEngRequestNi::log() const { + locallog(); +} + +// case LOC_ENG_MSG_INFORM_NI_RESPONSE: +// in loc_eng_ni.cpp + +// case LOC_ENG_MSG_START_FIX: +LocEngStartFix::LocEngStartFix(LocEngAdapter* adapter) : + LocMsg(), mAdapter(adapter) +{ + locallog(); +} +inline void LocEngStartFix::proc() const +{ + loc_eng_data_s_type* locEng = (loc_eng_data_s_type*)mAdapter->getOwner(); + loc_eng_start_handler(*locEng); +} +inline void LocEngStartFix::locallog() const +{ + LOC_LOGV("LocEngStartFix"); +} +inline void LocEngStartFix::log() const +{ + locallog(); +} +void LocEngStartFix::send() const { + mAdapter->sendMsg(this); +} + +// case LOC_ENG_MSG_STOP_FIX: +LocEngStopFix::LocEngStopFix(LocEngAdapter* adapter) : + LocMsg(), mAdapter(adapter) +{ + locallog(); +} +inline void LocEngStopFix::proc() const +{ + loc_eng_data_s_type* locEng = (loc_eng_data_s_type*)mAdapter->getOwner(); + loc_eng_stop_handler(*locEng); +} +inline void LocEngStopFix::locallog() const +{ + LOC_LOGV("LocEngStopFix"); +} +inline void LocEngStopFix::log() const +{ + locallog(); +} +void LocEngStopFix::send() const { + mAdapter->sendMsg(this); +} + +// case LOC_ENG_MSG_SET_POSITION_MODE: +LocEngPositionMode::LocEngPositionMode(LocEngAdapter* adapter, + LocPosMode &mode) : + LocMsg(), mAdapter(adapter), mPosMode(mode) +{ + mPosMode.logv(); +} +inline void LocEngPositionMode::proc() const { + mAdapter->setPositionMode(&mPosMode); +} +inline void LocEngPositionMode::log() const { + mPosMode.logv(); +} +void LocEngPositionMode::send() const { + mAdapter->sendMsg(this); +} + +LocEngGetZpp::LocEngGetZpp(LocEngAdapter* adapter) : + LocMsg(), mAdapter(adapter) +{ + locallog(); +} +inline void LocEngGetZpp::proc() const +{ + loc_eng_data_s_type* locEng = (loc_eng_data_s_type*)mAdapter->getOwner(); + loc_eng_get_zpp_handler(*locEng); +} +inline void LocEngGetZpp::locallog() const +{ + LOC_LOGV("LocEngGetZpp"); +} +inline void LocEngGetZpp::log() const +{ + locallog(); +} +void LocEngGetZpp::send() const { + mAdapter->sendMsg(this); +} + +struct LocEngSetTime : public LocMsg { + LocEngAdapter* mAdapter; + const GpsUtcTime mTime; + const int64_t mTimeReference; + const int mUncertainty; + inline LocEngSetTime(LocEngAdapter* adapter, + GpsUtcTime t, int64_t tf, int unc) : + LocMsg(), mAdapter(adapter), + mTime(t), mTimeReference(tf), mUncertainty(unc) + { + locallog(); + } + inline virtual void proc() const { + mAdapter->setTime(mTime, mTimeReference, mUncertainty); + } + inline void locallog() const { + LOC_LOGV("time: %lld\n timeReference: %lld\n uncertainty: %d", + mTime, mTimeReference, mUncertainty); + } + inline virtual void log() const { + locallog(); + } +}; + + // case LOC_ENG_MSG_INJECT_LOCATION: +struct LocEngInjectLocation : public LocMsg { + LocEngAdapter* mAdapter; + const double mLatitude; + const double mLongitude; + const float mAccuracy; + inline LocEngInjectLocation(LocEngAdapter* adapter, + double lat, double lon, float accur) : + LocMsg(), mAdapter(adapter), + mLatitude(lat), mLongitude(lon), mAccuracy(accur) + { + locallog(); + } + inline virtual void proc() const { + mAdapter->injectPosition(mLatitude, mLongitude, mAccuracy); + } + inline void locallog() const { + LOC_LOGV("latitude: %f\n longitude: %f\n accuracy: %f", + mLatitude, mLongitude, mAccuracy); + } + inline virtual void log() const { + locallog(); + } +}; + +// case LOC_ENG_MSG_SET_SERVER_IPV4: +struct LocEngSetServerIpv4 : public LocMsg { + LocEngAdapter* mAdapter; + const unsigned int mNlAddr; + const int mPort; + const LocServerType mServerType; + inline LocEngSetServerIpv4(LocEngAdapter* adapter, + unsigned int ip, + int port, + LocServerType type) : + LocMsg(), mAdapter(adapter), + mNlAddr(ip), mPort(port), mServerType(type) + { + locallog(); + } + inline virtual void proc() const { + mAdapter->setServer(mNlAddr, mPort, mServerType); + } + inline void locallog() const { + LOC_LOGV("LocEngSetServerIpv4 - addr: %x, port: %d, type: %s", + mNlAddr, mPort, loc_get_server_type_name(mServerType)); + } + inline virtual void log() const { + locallog(); + } +}; + +// case LOC_ENG_MSG_SET_SERVER_URL: +struct LocEngSetServerUrl : public LocMsg { + LocEngAdapter* mAdapter; + const int mLen; + char* mUrl; + inline LocEngSetServerUrl(LocEngAdapter* adapter, + char* urlString, + int url_len) : + LocMsg(), mAdapter(adapter), + mLen(url_len), mUrl(new char[mLen+1]) + { + memcpy((void*)mUrl, (void*)urlString, url_len); + mUrl[mLen] = 0; + locallog(); + } + inline ~LocEngSetServerUrl() + { + delete[] mUrl; + } + inline virtual void proc() const { + mAdapter->setServer(mUrl, mLen); + } + inline void locallog() const { + LOC_LOGV("LocEngSetServerUrl - url: %s", mUrl); + } + inline virtual void log() const { + locallog(); + } +}; + +// case LOC_ENG_MSG_A_GLONASS_PROTOCOL: +struct LocEngAGlonassProtocol : public LocMsg { + LocEngAdapter* mAdapter; + const unsigned long mAGlonassProtocl; + inline LocEngAGlonassProtocol(LocEngAdapter* adapter, + unsigned long protocol) : + LocMsg(), mAdapter(adapter), mAGlonassProtocl(protocol) + { + locallog(); + } + inline virtual void proc() const { + mAdapter->setAGLONASSProtocol(mAGlonassProtocl); + } + inline void locallog() const { + LOC_LOGV("A-GLONASS protocol: 0x%lx", mAGlonassProtocl); + } + inline virtual void log() const { + locallog(); + } +}; + +// case LOC_ENG_MSG_SUPL_VERSION: +struct LocEngSuplVer : public LocMsg { + LocEngAdapter* mAdapter; + const int mSuplVer; + inline LocEngSuplVer(LocEngAdapter* adapter, + int suplVer) : + LocMsg(), mAdapter(adapter), mSuplVer(suplVer) + { + locallog(); + } + inline virtual void proc() const { + mAdapter->setSUPLVersion(mSuplVer); + } + inline void locallog() const { + LOC_LOGV("SUPL Version: %d", mSuplVer); + } + inline virtual void log() const { + locallog(); + } +}; + +struct LocEngSuplMode : public LocMsg { + UlpProxyBase* mUlp; + + inline LocEngSuplMode(UlpProxyBase* ulp) : + LocMsg(), mUlp(ulp) + { + locallog(); + } + inline virtual void proc() const { + mUlp->setCapabilities(getCarrierCapabilities()); + } + inline void locallog() const { + } + inline virtual void log() const { + locallog(); + } +}; + +// case LOC_ENG_MSG_LPP_CONFIG: +struct LocEngLppConfig : public LocMsg { + LocEngAdapter* mAdapter; + const int mLppConfig; + inline LocEngLppConfig(LocEngAdapter* adapter, + int lppConfig) : + LocMsg(), mAdapter(adapter), mLppConfig(lppConfig) + { + locallog(); + } + inline virtual void proc() const { + mAdapter->setLPPConfig(mLppConfig); + } + inline void locallog() const { + LOC_LOGV("LocEngLppConfig - profile: %d", mLppConfig); + } + inline virtual void log() const { + locallog(); + } +}; + +// case LOC_ENG_MSG_SET_SENSOR_CONTROL_CONFIG: +struct LocEngSensorControlConfig : public LocMsg { + LocEngAdapter* mAdapter; + const int mSensorsDisabled; + const int mSensorProvider; + inline LocEngSensorControlConfig(LocEngAdapter* adapter, + int sensorsDisabled, int sensorProvider) : + LocMsg(), mAdapter(adapter), mSensorsDisabled(sensorsDisabled), + mSensorProvider(sensorProvider) + { + locallog(); + } + inline virtual void proc() const { + mAdapter->setSensorControlConfig(mSensorsDisabled, mSensorProvider); + } + inline void locallog() const { + LOC_LOGV("LocEngSensorControlConfig - Sensors Disabled: %d, Sensor Provider: %d", + mSensorsDisabled, mSensorProvider); + } + inline virtual void log() const { + locallog(); + } +}; + +// case LOC_ENG_MSG_SET_SENSOR_PROPERTIES: +struct LocEngSensorProperties : public LocMsg { + LocEngAdapter* mAdapter; + const bool mGyroBiasVarianceRandomWalkValid; + const float mGyroBiasVarianceRandomWalk; + const bool mAccelRandomWalkValid; + const float mAccelRandomWalk; + const bool mAngleRandomWalkValid; + const float mAngleRandomWalk; + const bool mRateRandomWalkValid; + const float mRateRandomWalk; + const bool mVelocityRandomWalkValid; + const float mVelocityRandomWalk; + inline LocEngSensorProperties(LocEngAdapter* adapter, + bool gyroBiasRandomWalk_valid, + float gyroBiasRandomWalk, + bool accelRandomWalk_valid, + float accelRandomWalk, + bool angleRandomWalk_valid, + float angleRandomWalk, + bool rateRandomWalk_valid, + float rateRandomWalk, + bool velocityRandomWalk_valid, + float velocityRandomWalk) : + LocMsg(), mAdapter(adapter), + mGyroBiasVarianceRandomWalkValid(gyroBiasRandomWalk_valid), + mGyroBiasVarianceRandomWalk(gyroBiasRandomWalk), + mAccelRandomWalkValid(accelRandomWalk_valid), + mAccelRandomWalk(accelRandomWalk), + mAngleRandomWalkValid(angleRandomWalk_valid), + mAngleRandomWalk(angleRandomWalk), + mRateRandomWalkValid(rateRandomWalk_valid), + mRateRandomWalk(rateRandomWalk), + mVelocityRandomWalkValid(velocityRandomWalk_valid), + mVelocityRandomWalk(velocityRandomWalk) + { + locallog(); + } + inline virtual void proc() const { + mAdapter->setSensorProperties(mGyroBiasVarianceRandomWalkValid, + mGyroBiasVarianceRandomWalk, + mAccelRandomWalkValid, + mAccelRandomWalk, + mAngleRandomWalkValid, + mAngleRandomWalk, + mRateRandomWalkValid, + mRateRandomWalk, + mVelocityRandomWalkValid, + mVelocityRandomWalk); + } + inline void locallog() const { + LOC_LOGV("Sensor properties validity, Gyro Random walk: %d " + "Accel Random Walk: %d " + "Angle Random Walk: %d Rate Random Walk: %d " + "Velocity Random Walk: %d\n" + "Sensor properties, Gyro Random walk: %f " + "Accel Random Walk: %f " + "Angle Random Walk: %f Rate Random Walk: %f " + "Velocity Random Walk: %f", + mGyroBiasVarianceRandomWalkValid, + mAccelRandomWalkValid, + mAngleRandomWalkValid, + mRateRandomWalkValid, + mVelocityRandomWalkValid, + mGyroBiasVarianceRandomWalk, + mAccelRandomWalk, + mAngleRandomWalk, + mRateRandomWalk, + mVelocityRandomWalk + ); + } + inline virtual void log() const { + locallog(); + } +}; + +// case LOC_ENG_MSG_SET_SENSOR_PERF_CONTROL_CONFIG: +struct LocEngSensorPerfControlConfig : public LocMsg { + LocEngAdapter* mAdapter; + const int mControlMode; + const int mAccelSamplesPerBatch; + const int mAccelBatchesPerSec; + const int mGyroSamplesPerBatch; + const int mGyroBatchesPerSec; + const int mAccelSamplesPerBatchHigh; + const int mAccelBatchesPerSecHigh; + const int mGyroSamplesPerBatchHigh; + const int mGyroBatchesPerSecHigh; + const int mAlgorithmConfig; + inline LocEngSensorPerfControlConfig(LocEngAdapter* adapter, + int controlMode, + int accelSamplesPerBatch, + int accelBatchesPerSec, + int gyroSamplesPerBatch, + int gyroBatchesPerSec, + int accelSamplesPerBatchHigh, + int accelBatchesPerSecHigh, + int gyroSamplesPerBatchHigh, + int gyroBatchesPerSecHigh, + int algorithmConfig) : + LocMsg(), mAdapter(adapter), + mControlMode(controlMode), + mAccelSamplesPerBatch(accelSamplesPerBatch), + mAccelBatchesPerSec(accelBatchesPerSec), + mGyroSamplesPerBatch(gyroSamplesPerBatch), + mGyroBatchesPerSec(gyroBatchesPerSec), + mAccelSamplesPerBatchHigh(accelSamplesPerBatchHigh), + mAccelBatchesPerSecHigh(accelBatchesPerSecHigh), + mGyroSamplesPerBatchHigh(gyroSamplesPerBatchHigh), + mGyroBatchesPerSecHigh(gyroBatchesPerSecHigh), + mAlgorithmConfig(algorithmConfig) + { + locallog(); + } + inline virtual void proc() const { + mAdapter->setSensorPerfControlConfig(mControlMode, + mAccelSamplesPerBatch, + mAccelBatchesPerSec, + mGyroSamplesPerBatch, + mGyroBatchesPerSec, + mAccelSamplesPerBatchHigh, + mAccelBatchesPerSecHigh, + mGyroSamplesPerBatchHigh, + mGyroBatchesPerSecHigh, + mAlgorithmConfig); + } + inline void locallog() const { + LOC_LOGV("Sensor Perf Control Config (performanceControlMode)(%u) " + "accel(#smp,#batches) (%u,%u) " + "gyro(#smp,#batches) (%u,%u), " + "accel_high(#smp,#batches) (%u,%u) " + "gyro_high(#smp,#batches) (%u,%u), " + "algorithmConfig(%u)\n", + mControlMode, + mAccelSamplesPerBatch, mAccelBatchesPerSec, + mGyroSamplesPerBatch, mGyroBatchesPerSec, + mAccelSamplesPerBatchHigh, mAccelBatchesPerSecHigh, + mGyroSamplesPerBatchHigh, mGyroBatchesPerSecHigh, + mAlgorithmConfig); + } + inline virtual void log() const { + locallog(); + } +}; + +// case LOC_ENG_MSG_EXT_POWER_CONFIG: +struct LocEngExtPowerConfig : public LocMsg { + LocEngAdapter* mAdapter; + const int mIsBatteryCharging; + inline LocEngExtPowerConfig(LocEngAdapter* adapter, + int isBatteryCharging) : + LocMsg(), mAdapter(adapter), + mIsBatteryCharging(isBatteryCharging) + { + locallog(); + } + inline virtual void proc() const { + mAdapter->setExtPowerConfig(mIsBatteryCharging); + } + inline void locallog() const { + LOC_LOGV("LocEngExtPowerConfig - isBatteryCharging: %d", + mIsBatteryCharging); + } + inline virtual void log() const { + locallog(); + } +}; + +// case LOC_ENG_MSG_REPORT_POSITION: +LocEngReportPosition::LocEngReportPosition(LocAdapterBase* adapter, + UlpLocation &loc, + GpsLocationExtended &locExtended, + void* locExt, + enum loc_sess_status st, + LocPosTechMask technology) : + LocMsg(), mAdapter(adapter), mLocation(loc), + mLocationExtended(locExtended), + mLocationExt(((loc_eng_data_s_type*) + ((LocEngAdapter*) + (mAdapter))->getOwner())->location_ext_parser(locExt)), + mStatus(st), mTechMask(technology) +{ + locallog(); +} +void LocEngReportPosition::proc() const { + LocEngAdapter* adapter = (LocEngAdapter*)mAdapter; + loc_eng_data_s_type* locEng = (loc_eng_data_s_type*)adapter->getOwner(); + + if (locEng->mute_session_state != LOC_MUTE_SESS_IN_SESSION) { + bool reported = false; + if (locEng->location_cb != NULL) { + if (LOC_SESS_FAILURE == mStatus) { + // in case we want to handle the failure case + locEng->location_cb(NULL, NULL); + reported = true; + } + // what's in the else if is... (line by line) + // 1. this is a final fix; and + // 1.1 it is a Satellite fix; or + // 1.2 it is a sensor fix + // 2. (must be intermediate fix... implicit) + // 2.1 we accepte intermediate; and + // 2.2 it is NOT the case that + // 2.2.1 there is inaccuracy; and + // 2.2.2 we care about inaccuracy; and + // 2.2.3 the inaccuracy exceeds our tolerance + else if ((LOC_SESS_SUCCESS == mStatus && + ((LOC_POS_TECH_MASK_SATELLITE | + LOC_POS_TECH_MASK_SENSORS | + LOC_POS_TECH_MASK_HYBRID) & + mTechMask)) || + (LOC_SESS_INTERMEDIATE == locEng->intermediateFix && + !((mLocation.gpsLocation.flags & + GPS_LOCATION_HAS_ACCURACY) && + (gps_conf.ACCURACY_THRES != 0) && + (mLocation.gpsLocation.accuracy > + gps_conf.ACCURACY_THRES)))) { + locEng->location_cb((UlpLocation*)&(mLocation), + (void*)mLocationExt); + reported = true; + } + } + + // if we have reported this fix + if (reported && + // and if this is a singleshot + GPS_POSITION_RECURRENCE_SINGLE == + locEng->adapter->getPositionMode().recurrence) { + if (LOC_SESS_INTERMEDIATE == mStatus) { + // modem could be still working for a final fix, + // although we no longer need it. So stopFix(). + locEng->adapter->stopFix(); + } + // turn off the session flag. + locEng->adapter->setInSession(false); + } + + LOC_LOGV("LocEngReportPosition::proc() - generateNmea: %d, position source: %d, " + "engine_status: %d, isInSession: %d", + locEng->generateNmea, mLocation.position_source, + locEng->engine_status, locEng->adapter->isInSession()); + + if (locEng->generateNmea && + locEng->adapter->isInSession()) + { + unsigned char generate_nmea = reported && + (mStatus != LOC_SESS_FAILURE); + loc_eng_nmea_generate_pos(locEng, mLocation, mLocationExtended, + generate_nmea); + } + + // Free the allocated memory for rawData + UlpLocation* gp = (UlpLocation*)&(mLocation); + if (gp != NULL && gp->rawData != NULL) + { + delete (char*)gp->rawData; + gp->rawData = NULL; + gp->rawDataSize = 0; + } + } +} +void LocEngReportPosition::locallog() const { + LOC_LOGV("LocEngReportPosition"); +} +void LocEngReportPosition::log() const { + locallog(); +} +void LocEngReportPosition::send() const { + mAdapter->sendMsg(this); +} + + +// case LOC_ENG_MSG_REPORT_SV: +LocEngReportSv::LocEngReportSv(LocAdapterBase* adapter, + GnssSvStatus &sv, + GpsLocationExtended &locExtended, + void* svExt) : + LocMsg(), mAdapter(adapter), mSvStatus(sv), + mLocationExtended(locExtended), + mSvExt(((loc_eng_data_s_type*) + ((LocEngAdapter*) + (mAdapter))->getOwner())->sv_ext_parser(svExt)) +{ + locallog(); +} +void LocEngReportSv::proc() const { + LocEngAdapter* adapter = (LocEngAdapter*)mAdapter; + loc_eng_data_s_type* locEng = (loc_eng_data_s_type*)adapter->getOwner(); + + if (locEng->mute_session_state != LOC_MUTE_SESS_IN_SESSION) + { + if (locEng->sv_status_cb != NULL) { + locEng->sv_status_cb((GpsSvStatus*)&(mSvStatus), + (void*)mSvExt); + } + + if (locEng->generateNmea) + { + loc_eng_nmea_generate_sv(locEng, mSvStatus, mLocationExtended); + } + } +} +void LocEngReportSv::locallog() const { + LOC_LOGV("%s:%d] LocEngReportSv",__func__, __LINE__); +} +inline void LocEngReportSv::log() const { + locallog(); +} +void LocEngReportSv::send() const { + mAdapter->sendMsg(this); +} + +// case LOC_ENG_MSG_REPORT_STATUS: +LocEngReportStatus::LocEngReportStatus(LocAdapterBase* adapter, + GpsStatusValue engineStatus) : + LocMsg(), mAdapter(adapter), mStatus(engineStatus) +{ + locallog(); +} +inline void LocEngReportStatus::proc() const +{ + LocEngAdapter* adapter = (LocEngAdapter*)mAdapter; + loc_eng_data_s_type* locEng = (loc_eng_data_s_type*)adapter->getOwner(); + + loc_eng_report_status(*locEng, mStatus); + update_aiding_data_for_deletion(*locEng); +} +inline void LocEngReportStatus::locallog() const { + LOC_LOGV("LocEngReportStatus"); +} +inline void LocEngReportStatus::log() const { + locallog(); +} + +// case LOC_ENG_MSG_REPORT_NMEA: +LocEngReportNmea::LocEngReportNmea(void* locEng, + const char* data, int len) : + LocMsg(), mLocEng(locEng), mNmea(new char[len]), mLen(len) +{ + memcpy((void*)mNmea, (void*)data, len); + locallog(); +} +void LocEngReportNmea::proc() const { + loc_eng_data_s_type* locEng = (loc_eng_data_s_type*) mLocEng; + + struct timeval tv; + gettimeofday(&tv, (struct timezone *) NULL); + int64_t now = tv.tv_sec * 1000LL + tv.tv_usec / 1000; + CALLBACK_LOG_CALLFLOW("nmea_cb", %d, mLen); + + if (locEng->nmea_cb != NULL) + locEng->nmea_cb(now, mNmea, mLen); +} +inline void LocEngReportNmea::locallog() const { + LOC_LOGV("LocEngReportNmea"); +} +inline void LocEngReportNmea::log() const { + locallog(); +} + +// case LOC_ENG_MSG_REPORT_XTRA_SERVER: +LocEngReportXtraServer::LocEngReportXtraServer(void* locEng, + const char *url1, + const char *url2, + const char *url3, + const int maxlength) : + LocMsg(), mLocEng(locEng), mMaxLen(maxlength), + mServers(new char[3*(mMaxLen+1)]) +{ + char * cptr = mServers; + memset(mServers, 0, 3*(mMaxLen+1)); + + // Override modem URLs with uncommented gps.conf urls + if( gps_conf.XTRA_SERVER_1[0] != '\0' ) { + url1 = &gps_conf.XTRA_SERVER_1[0]; + } + if( gps_conf.XTRA_SERVER_2[0] != '\0' ) { + url2 = &gps_conf.XTRA_SERVER_2[0]; + } + if( gps_conf.XTRA_SERVER_3[0] != '\0' ) { + url3 = &gps_conf.XTRA_SERVER_3[0]; + } + // copy non xtra1.gpsonextra.net URLs into the forwarding buffer. + if( NULL == strcasestr(url1, XTRA1_GPSONEXTRA) ) { + strlcpy(cptr, url1, mMaxLen + 1); + cptr += mMaxLen + 1; + } + if( NULL == strcasestr(url2, XTRA1_GPSONEXTRA) ) { + strlcpy(cptr, url2, mMaxLen + 1); + cptr += mMaxLen + 1; + } + if( NULL == strcasestr(url3, XTRA1_GPSONEXTRA) ) { + strlcpy(cptr, url3, mMaxLen + 1); + } + locallog(); +} + +void LocEngReportXtraServer::proc() const { + loc_eng_xtra_data_s_type* locEngXtra = + &(((loc_eng_data_s_type*)mLocEng)->xtra_module_data); + + if (locEngXtra->report_xtra_server_cb != NULL) { + CALLBACK_LOG_CALLFLOW("report_xtra_server_cb", %s, mServers); + locEngXtra->report_xtra_server_cb(mServers, + &(mServers[mMaxLen+1]), + &(mServers[(mMaxLen+1)<<1])); + } else { + LOC_LOGE("Callback function for request xtra is NULL"); + } +} +inline void LocEngReportXtraServer::locallog() const { + LOC_LOGV("LocEngReportXtraServers: server1: %s\n server2: %s\n" + " server3: %s\n", + mServers, &mServers[mMaxLen+1], &mServers[(mMaxLen+1)<<1]); +} +inline void LocEngReportXtraServer::log() const { + locallog(); +} + +// case LOC_ENG_MSG_REQUEST_BIT: +// case LOC_ENG_MSG_RELEASE_BIT: +LocEngReqRelBIT::LocEngReqRelBIT(void* locEng, AGpsExtType type, + int ipv4, char* ipv6, bool isReq) : + LocMsg(), mLocEng(locEng), mType(type), mIPv4Addr(ipv4), + mIPv6Addr(ipv6 ? new char[16] : NULL), mIsReq(isReq) { + if (NULL != ipv6) + memcpy(mIPv6Addr, ipv6, 16); + locallog(); +} +inline LocEngReqRelBIT::~LocEngReqRelBIT() { + if (mIPv6Addr) { + delete[] mIPv6Addr; + } +} +void LocEngReqRelBIT::proc() const { + loc_eng_data_s_type* locEng = (loc_eng_data_s_type*)mLocEng; + BITSubscriber s(getAgpsStateMachine(*locEng, mType), + mIPv4Addr, mIPv6Addr); + AgpsStateMachine* sm = (AgpsStateMachine*)s.mStateMachine; + + if (mIsReq) { + sm->subscribeRsrc((Subscriber*)&s); + } else { + sm->unsubscribeRsrc((Subscriber*)&s); + } +} +inline void LocEngReqRelBIT::locallog() const { + LOC_LOGV("LocEngRequestBIT - ipv4: %d.%d.%d.%d, ipv6: %s", + (unsigned char)mIPv4Addr, + (unsigned char)(mIPv4Addr>>8), + (unsigned char)(mIPv4Addr>>16), + (unsigned char)(mIPv4Addr>>24), + NULL != mIPv6Addr ? mIPv6Addr : ""); +} +inline void LocEngReqRelBIT::log() const { + locallog(); +} +void LocEngReqRelBIT::send() const { + loc_eng_data_s_type* locEng = (loc_eng_data_s_type*)mLocEng; + locEng->adapter->sendMsg(this); +} + +// case LOC_ENG_MSG_RELEASE_BIT: +struct LocEngReleaseBIT : public LocMsg { + const BITSubscriber mSubscriber; + inline LocEngReleaseBIT(const AgpsStateMachine* stateMachine, + unsigned int ipv4, char* ipv6) : + LocMsg(), + mSubscriber(stateMachine, ipv4, ipv6) + { + locallog(); + } + inline virtual void proc() const + { + AgpsStateMachine* sm = (AgpsStateMachine*)mSubscriber.mStateMachine; + sm->unsubscribeRsrc((Subscriber*)&mSubscriber); + } + inline void locallog() const { + LOC_LOGV("LocEngReleaseBIT - ipv4: %d.%d.%d.%d, ipv6: %s", + (unsigned char)(mSubscriber.ID>>24), + (unsigned char)(mSubscriber.ID>>16), + (unsigned char)(mSubscriber.ID>>8), + (unsigned char)mSubscriber.ID, + NULL != mSubscriber.mIPv6Addr ? mSubscriber.mIPv6Addr : ""); + } + virtual void log() const { + locallog(); + } +}; + +// LocEngSuplEsOpened +LocEngSuplEsOpened::LocEngSuplEsOpened(void* locEng) : + LocMsg(), mLocEng(locEng) { + locallog(); +} +void LocEngSuplEsOpened::proc() const { + loc_eng_data_s_type* locEng = (loc_eng_data_s_type*)mLocEng; + if (locEng->ds_nif) { + AgpsStateMachine* sm = locEng->ds_nif; + sm->onRsrcEvent(RSRC_GRANTED); + } +} +void LocEngSuplEsOpened::locallog() const { + LOC_LOGV("LocEngSuplEsOpened"); +} +void LocEngSuplEsOpened::log() const { + locallog(); +} + +// LocEngSuplEsClosed +LocEngSuplEsClosed::LocEngSuplEsClosed(void* locEng) : + LocMsg(), mLocEng(locEng) { + locallog(); +} +void LocEngSuplEsClosed::proc() const { + loc_eng_data_s_type* locEng = (loc_eng_data_s_type*)mLocEng; + if (locEng->ds_nif) { + AgpsStateMachine* sm = locEng->ds_nif; + sm->onRsrcEvent(RSRC_RELEASED); + } +} +void LocEngSuplEsClosed::locallog() const { + LOC_LOGV("LocEngSuplEsClosed"); +} +void LocEngSuplEsClosed::log() const { + locallog(); +} + + +// case LOC_ENG_MSG_REQUEST_SUPL_ES: +LocEngRequestSuplEs::LocEngRequestSuplEs(void* locEng, int id) : + LocMsg(), mLocEng(locEng), mID(id) { + locallog(); +} +void LocEngRequestSuplEs::proc() const { + loc_eng_data_s_type* locEng = (loc_eng_data_s_type*)mLocEng; + if (locEng->ds_nif) { + AgpsStateMachine* sm = locEng->ds_nif; + DSSubscriber s(sm, mID); + sm->subscribeRsrc((Subscriber*)&s); + } + else if (locEng->agnss_nif) { + AgpsStateMachine *sm = locEng->agnss_nif; + ATLSubscriber s(mID, + sm, + locEng->adapter, + false); + sm->subscribeRsrc((Subscriber*)&s); + LOC_LOGD("%s:%d]: Using regular ATL for SUPL ES", __func__, __LINE__); + } + else { + locEng->adapter->atlOpenStatus(mID, 0, NULL, -1, -1); + } +} +inline void LocEngRequestSuplEs::locallog() const { + LOC_LOGV("LocEngRequestSuplEs"); +} +inline void LocEngRequestSuplEs::log() const { + locallog(); +} + +// case LOC_ENG_MSG_REQUEST_ATL: +LocEngRequestATL::LocEngRequestATL(void* locEng, int id, + AGpsExtType agps_type) : + LocMsg(), mLocEng(locEng), mID(id), mType(agps_type) { + locallog(); +} +void LocEngRequestATL::proc() const { + loc_eng_data_s_type* locEng = (loc_eng_data_s_type*)mLocEng; + AgpsStateMachine* sm = (AgpsStateMachine*) + getAgpsStateMachine(*locEng, mType); + if (sm) { + ATLSubscriber s(mID, + sm, + locEng->adapter, + AGPS_TYPE_INVALID == mType); + sm->subscribeRsrc((Subscriber*)&s); + } else { + locEng->adapter->atlOpenStatus(mID, 0, NULL, -1, mType); + } +} +inline void LocEngRequestATL::locallog() const { + LOC_LOGV("LocEngRequestATL"); +} +inline void LocEngRequestATL::log() const { + locallog(); +} + +// case LOC_ENG_MSG_RELEASE_ATL: +LocEngReleaseATL::LocEngReleaseATL(void* locEng, int id) : + LocMsg(), mLocEng(locEng), mID(id) { + locallog(); +} +void LocEngReleaseATL::proc() const { + loc_eng_data_s_type* locEng = (loc_eng_data_s_type*)mLocEng; + + if (locEng->agnss_nif) { + ATLSubscriber s1(mID, locEng->agnss_nif, locEng->adapter, false); + if (locEng->agnss_nif->unsubscribeRsrc((Subscriber*)&s1)) { + LOC_LOGD("%s:%d]: Unsubscribed from agnss_nif", + __func__, __LINE__); + return; + } + } + + if (locEng->internet_nif) { + ATLSubscriber s2(mID, locEng->internet_nif, locEng->adapter, false); + if (locEng->internet_nif->unsubscribeRsrc((Subscriber*)&s2)) { + LOC_LOGD("%s:%d]: Unsubscribed from internet_nif", + __func__, __LINE__); + return; + } + } + + if (locEng->ds_nif) { + DSSubscriber s3(locEng->ds_nif, mID); + if (locEng->ds_nif->unsubscribeRsrc((Subscriber*)&s3)) { + LOC_LOGD("%s:%d]: Unsubscribed from ds_nif", + __func__, __LINE__); + return; + } + } + + LOC_LOGW("%s:%d]: Could not release ATL. " + "No subscribers found\n", + __func__, __LINE__); + locEng->adapter->atlCloseStatus(mID, 0); +} +inline void LocEngReleaseATL::locallog() const { + LOC_LOGV("LocEngReleaseATL"); +} +inline void LocEngReleaseATL::log() const { + locallog(); +} + +// case LOC_ENG_MSG_REQUEST_WIFI: +// case LOC_ENG_MSG_RELEASE_WIFI: +LocEngReqRelWifi::LocEngReqRelWifi(void* locEng, AGpsExtType type, + loc_if_req_sender_id_e_type sender_id, + char* s, char* p, bool isReq) : + LocMsg(), mLocEng(locEng), mType(type), mSenderId(sender_id), + mSSID(NULL == s ? NULL : new char[SSID_BUF_SIZE]), + mPassword(NULL == p ? NULL : new char[SSID_BUF_SIZE]), + mIsReq(isReq) { + if (NULL != s) + strlcpy(mSSID, s, SSID_BUF_SIZE); + if (NULL != p) + strlcpy(mPassword, p, SSID_BUF_SIZE); + locallog(); +} +LocEngReqRelWifi::~LocEngReqRelWifi() { + if (NULL != mSSID) { + delete[] mSSID; + } + if (NULL != mPassword) { + delete[] mPassword; + } +} +void LocEngReqRelWifi::proc() const { + loc_eng_data_s_type* locEng = (loc_eng_data_s_type*)mLocEng; + if (locEng->wifi_nif) { + WIFISubscriber s(locEng->wifi_nif, mSSID, mPassword, mSenderId); + if (mIsReq) { + locEng->wifi_nif->subscribeRsrc((Subscriber*)&s); + } else { + locEng->wifi_nif->unsubscribeRsrc((Subscriber*)&s); + } + } else { + locEng->adapter->atlOpenStatus(mSenderId, 0, NULL, -1, mType); + } +} +inline void LocEngReqRelWifi::locallog() const { + LOC_LOGV("%s - senderId: %d, ssid: %s, password: %s", + mIsReq ? "LocEngRequestWifi" : "LocEngReleaseWifi", + mSenderId, + NULL != mSSID ? mSSID : "", + NULL != mPassword ? mPassword : ""); +} +inline void LocEngReqRelWifi::log() const { + locallog(); +} +void LocEngReqRelWifi::send() const { + loc_eng_data_s_type* locEng = (loc_eng_data_s_type*)mLocEng; + locEng->adapter->sendMsg(this); +} + +// case LOC_ENG_MSG_REQUEST_XTRA_DATA: +LocEngRequestXtra::LocEngRequestXtra(void* locEng) : + mLocEng(locEng) { + locallog(); +} +void LocEngRequestXtra::proc() const +{ + loc_eng_xtra_data_s_type* locEngXtra = + &(((loc_eng_data_s_type*)mLocEng)->xtra_module_data); + + if (locEngXtra->download_request_cb != NULL) { + CALLBACK_LOG_CALLFLOW("download_request_cb", %p, mLocEng); + locEngXtra->download_request_cb(); + } else { + LOC_LOGE("Callback function for request xtra is NULL"); + } +} +inline void LocEngRequestXtra::locallog() const { + LOC_LOGV("LocEngReqXtra"); +} +inline void LocEngRequestXtra::log() const { + locallog(); +} + +// case LOC_ENG_MSG_REQUEST_TIME: +LocEngRequestTime::LocEngRequestTime(void* locEng) : + LocMsg(), mLocEng(locEng) +{ + locallog(); +} +void LocEngRequestTime::proc() const { + loc_eng_data_s_type* locEng = (loc_eng_data_s_type*)mLocEng; + if (gps_conf.CAPABILITIES & GPS_CAPABILITY_ON_DEMAND_TIME) { + if (locEng->request_utc_time_cb != NULL) { + locEng->request_utc_time_cb(); + } else { + LOC_LOGE("Callback function for request time is NULL"); + } + } +} +inline void LocEngRequestTime::locallog() const { + LOC_LOGV("LocEngReqTime"); +} +inline void LocEngRequestTime::log() const { + locallog(); +} + +// case LOC_ENG_MSG_DELETE_AIDING_DATA: +struct LocEngDelAidData : public LocMsg { + loc_eng_data_s_type* mLocEng; + const GpsAidingData mType; + inline LocEngDelAidData(loc_eng_data_s_type* locEng, + GpsAidingData f) : + LocMsg(), mLocEng(locEng), mType(f) + { + locallog(); + } + inline virtual void proc() const { + mLocEng->aiding_data_for_deletion = mType; + update_aiding_data_for_deletion(*mLocEng); + } + inline void locallog() const { + LOC_LOGV("aiding data msak %d", mType); + } + virtual void log() const { + locallog(); + } +}; + +// case LOC_ENG_MSG_ENABLE_DATA: +struct LocEngEnableData : public LocMsg { + LocEngAdapter* mAdapter; + const int mEnable; + char* mAPN; + const int mLen; + inline LocEngEnableData(LocEngAdapter* adapter, + const char* name, int len, int enable) : + LocMsg(), mAdapter(adapter), + mEnable(enable), mAPN(NULL), mLen(len) + { + if (NULL != name) { + mAPN = new char[len+1]; + memcpy((void*)mAPN, (void*)name, len); + mAPN[len] = 0; + } + locallog(); + } + inline ~LocEngEnableData() { + if (NULL != mAPN) { + delete[] mAPN; + } + } + inline virtual void proc() const { + mAdapter->enableData(mEnable); + if (NULL != mAPN) { + mAdapter->setAPN(mAPN, mLen); + } + } + inline void locallog() const { + LOC_LOGV("apn: %s\n enable: %d", + (NULL == mAPN) ? "NULL" : mAPN, mEnable); + } + inline virtual void log() const { + locallog(); + } +}; + +// case LOC_ENG_MSG_INJECT_XTRA_DATA: +// loc_eng_xtra.cpp + +// case LOC_ENG_MSG_SET_CAPABILITIES: +struct LocEngSetCapabilities : public LocMsg { + loc_eng_data_s_type* mLocEng; + inline LocEngSetCapabilities(loc_eng_data_s_type* locEng) : + LocMsg(), mLocEng(locEng) + { + locallog(); + } + inline virtual void proc() const { + if (NULL != mLocEng->set_capabilities_cb) { + LOC_LOGV("calling set_capabilities_cb 0x%x", + gps_conf.CAPABILITIES); + mLocEng->set_capabilities_cb(gps_conf.CAPABILITIES); + } else { + LOC_LOGV("set_capabilities_cb is NULL.\n"); + } + } + inline void locallog() const + { + LOC_LOGV("LocEngSetCapabilities"); + } + inline virtual void log() const + { + locallog(); + } +}; + +// case LOC_ENG_MSG_LOC_INIT: +struct LocEngInit : public LocMsg { + loc_eng_data_s_type* mLocEng; + inline LocEngInit(loc_eng_data_s_type* locEng) : + LocMsg(), mLocEng(locEng) + { + locallog(); + } + inline virtual void proc() const { + loc_eng_reinit(*mLocEng); + // set the capabilities + mLocEng->adapter->sendMsg(new LocEngSetCapabilities(mLocEng)); + } + inline void locallog() const + { + LOC_LOGV("LocEngInit"); + } + inline virtual void log() const + { + locallog(); + } +}; + +// case LOC_ENG_MSG_REQUEST_XTRA_SERVER: +// loc_eng_xtra.cpp + +// case LOC_ENG_MSG_ATL_OPEN_SUCCESS: +struct LocEngAtlOpenSuccess : public LocMsg { + AgpsStateMachine* mStateMachine; + const int mLen; + char* mAPN; + const AGpsBearerType mBearerType; + inline LocEngAtlOpenSuccess(AgpsStateMachine* statemachine, + const char* name, + int len, + AGpsBearerType btype) : + LocMsg(), + mStateMachine(statemachine), mLen(len), + mAPN(new char[len+1]), mBearerType(btype) + { + memcpy((void*)mAPN, (void*)name, len); + mAPN[len] = 0; + locallog(); + } + inline ~LocEngAtlOpenSuccess() + { + delete[] mAPN; + } + inline virtual void proc() const { + mStateMachine->setBearer(mBearerType); + mStateMachine->setAPN(mAPN, mLen); + mStateMachine->onRsrcEvent(RSRC_GRANTED); + } + inline void locallog() const { + LOC_LOGV("LocEngAtlOpenSuccess agps type: %s\n apn: %s\n" + " bearer type: %s", + loc_get_agps_type_name(mStateMachine->getType()), + mAPN, + loc_get_agps_bear_name(mBearerType)); + } + inline virtual void log() const { + locallog(); + } +}; + +// case LOC_ENG_MSG_ATL_CLOSED: +struct LocEngAtlClosed : public LocMsg { + AgpsStateMachine* mStateMachine; + inline LocEngAtlClosed(AgpsStateMachine* statemachine) : + LocMsg(), mStateMachine(statemachine) { + locallog(); + } + inline virtual void proc() const { + mStateMachine->onRsrcEvent(RSRC_RELEASED); + } + inline void locallog() const { + LOC_LOGV("LocEngAtlClosed"); + } + inline virtual void log() const { + locallog(); + } +}; + +// case LOC_ENG_MSG_ATL_OPEN_FAILED: +struct LocEngAtlOpenFailed : public LocMsg { + AgpsStateMachine* mStateMachine; + inline LocEngAtlOpenFailed(AgpsStateMachine* statemachine) : + LocMsg(), mStateMachine(statemachine) { + locallog(); + } + inline virtual void proc() const { + mStateMachine->onRsrcEvent(RSRC_DENIED); + } + inline void locallog() const { + LOC_LOGV("LocEngAtlOpenFailed"); + } + inline virtual void log() const { + locallog(); + } +}; + +// case LOC_ENG_MSG_ENGINE_DOWN: +LocEngDown::LocEngDown(void* locEng) : + LocMsg(), mLocEng(locEng) { + locallog(); +} +inline void LocEngDown::proc() const { + loc_eng_data_s_type* locEng = (loc_eng_data_s_type*)mLocEng; + loc_eng_handle_engine_down(*locEng); +} +inline void LocEngDown::locallog() const { + LOC_LOGV("LocEngDown"); +} +inline void LocEngDown::log() const { + locallog(); +} + +// case LOC_ENG_MSG_ENGINE_UP: +LocEngUp::LocEngUp(void* locEng) : + LocMsg(), mLocEng(locEng) { + locallog(); +} +inline void LocEngUp::proc() const { + loc_eng_data_s_type* locEng = (loc_eng_data_s_type*)mLocEng; + loc_eng_handle_engine_up(*locEng); +} +inline void LocEngUp::locallog() const { + LOC_LOGV("LocEngUp"); +} +inline void LocEngUp::log() const { + locallog(); +} + +struct LocEngDataClientInit : public LocMsg { + loc_eng_data_s_type* mLocEng; + inline LocEngDataClientInit(loc_eng_data_s_type* locEng) : + LocMsg(), mLocEng(locEng) { + locallog(); + } + virtual void proc() const { + loc_eng_data_s_type *locEng = (loc_eng_data_s_type *)mLocEng; + if(!locEng->adapter->initDataServiceClient()) { + locEng->ds_nif = new DSStateMachine(servicerTypeExt, + (void *)dataCallCb, + locEng->adapter); + } + } + void locallog() const { + LOC_LOGV("LocEngDataClientInit\n"); + } + virtual void log() const { + locallog(); + } +}; + +struct LocEngInstallAGpsCert : public LocMsg { + LocEngAdapter* mpAdapter; + const size_t mNumberOfCerts; + const uint32_t mSlotBitMask; + DerEncodedCertificate* mpData; + inline LocEngInstallAGpsCert(LocEngAdapter* adapter, + const DerEncodedCertificate* pData, + size_t numberOfCerts, + uint32_t slotBitMask) : + LocMsg(), mpAdapter(adapter), + mNumberOfCerts(numberOfCerts), mSlotBitMask(slotBitMask), + mpData(new DerEncodedCertificate[mNumberOfCerts]) + { + for (int i=0; i < mNumberOfCerts; i++) { + mpData[i].data = new u_char[pData[i].length]; + if (mpData[i].data) { + memcpy(mpData[i].data, (void*)pData[i].data, pData[i].length); + mpData[i].length = pData[i].length; + } else { + LOC_LOGE("malloc failed for cert#%d", i); + break; + } + } + locallog(); + } + inline ~LocEngInstallAGpsCert() + { + for (int i=0; i < mNumberOfCerts; i++) { + if (mpData[i].data) { + delete[] mpData[i].data; + } + } + delete[] mpData; + } + inline virtual void proc() const { + mpAdapter->installAGpsCert(mpData, mNumberOfCerts, mSlotBitMask); + } + inline void locallog() const { + LOC_LOGV("LocEngInstallAGpsCert - certs=%u mask=%u", + mNumberOfCerts, mSlotBitMask); + } + inline virtual void log() const { + locallog(); + } +}; + +struct LocEngUpdateRegistrationMask : public LocMsg { + loc_eng_data_s_type* mLocEng; + LOC_API_ADAPTER_EVENT_MASK_T mMask; + loc_registration_mask_status mIsEnabled; + inline LocEngUpdateRegistrationMask(loc_eng_data_s_type* locEng, + LOC_API_ADAPTER_EVENT_MASK_T mask, + loc_registration_mask_status isEnabled) : + LocMsg(), mLocEng(locEng), mMask(mask), mIsEnabled(isEnabled) { + locallog(); + } + inline virtual void proc() const { + loc_eng_data_s_type *locEng = (loc_eng_data_s_type *)mLocEng; + locEng->adapter->updateRegistrationMask(mMask, + mIsEnabled); + } + void locallog() const { + LOC_LOGV("LocEngUpdateRegistrationMask\n"); + } + virtual void log() const { + locallog(); + } +}; + +struct LocEngGnssConstellationConfig : public LocMsg { + LocEngAdapter* mAdapter; + inline LocEngGnssConstellationConfig(LocEngAdapter* adapter) : + LocMsg(), mAdapter(adapter) { + locallog(); + } + inline virtual void proc() const { + if (mAdapter->gnssConstellationConfig()) { + LOC_LOGV("Modem supports GNSS measurements\n"); + gps_conf.CAPABILITIES |= GPS_CAPABILITY_MEASUREMENTS; + } else { + LOC_LOGV("Modem does not support GNSS measurements\n"); + } + } + void locallog() const { + LOC_LOGV("LocEngGnssConstellationConfig\n"); + } + virtual void log() const { + locallog(); + } +}; + +// case LOC_ENG_MSG_REPORT_GNSS_MEASUREMENT: +LocEngReportGpsMeasurement::LocEngReportGpsMeasurement(void* locEng, + GpsData &gpsData) : + LocMsg(), mLocEng(locEng), mGpsData(gpsData) +{ + locallog(); +} +void LocEngReportGpsMeasurement::proc() const { + loc_eng_data_s_type* locEng = (loc_eng_data_s_type*) mLocEng; + if (locEng->mute_session_state != LOC_MUTE_SESS_IN_SESSION) + { + if (locEng->gps_measurement_cb != NULL) { + locEng->gps_measurement_cb((GpsData*)&(mGpsData)); + } + } +} +void LocEngReportGpsMeasurement::locallog() const { + IF_LOC_LOGV { + LOC_LOGV("%s:%d]: Received in GPS HAL." + "GNSS Measurements count: %d \n", + __func__, __LINE__, mGpsData.measurement_count); + for (int i =0; i< mGpsData.measurement_count && i < GPS_MAX_SVS; i++) { + LOC_LOGV(" GNSS measurement data in GPS HAL: \n" + " GPS_HAL => Measurement ID | prn | time_offset_ns | state |" + " received_gps_tow_ns| c_n0_dbhz | pseudorange_rate_mps |" + " pseudorange_rate_uncertainty_mps |" + " accumulated_delta_range_state | flags \n" + " GPS_HAL => %d | %d | %f | %d | %lld | %f | %f | %f | %d | %d \n", + i, + mGpsData.measurements[i].prn, + mGpsData.measurements[i].time_offset_ns, + mGpsData.measurements[i].state, + mGpsData.measurements[i].received_gps_tow_ns, + mGpsData.measurements[i].c_n0_dbhz, + mGpsData.measurements[i].pseudorange_rate_mps, + mGpsData.measurements[i].pseudorange_rate_uncertainty_mps, + mGpsData.measurements[i].accumulated_delta_range_state, + mGpsData.measurements[i].flags); + } + LOC_LOGV(" GPS_HAL => Clocks Info: type | time_ns \n" + " GPS_HAL => Clocks Info: %d | %lld", mGpsData.clock.type, + mGpsData.clock.time_ns); + } +} +inline void LocEngReportGpsMeasurement::log() const { + locallog(); +} + +/********************************************************************* + * Initialization checking macros + *********************************************************************/ +#define STATE_CHECK(ctx, x, ret) \ + if (!(ctx)) \ + { \ + /* Not intialized, abort */\ + LOC_LOGE("%s: log_eng state error: %s", __func__, x); \ + EXIT_LOG(%s, x); \ + ret; \ + } +#define INIT_CHECK(ctx, ret) STATE_CHECK(ctx, "instance not initialized", ret) + +uint32_t getCarrierCapabilities() { + #define carrierMSA (uint32_t)0x2 + #define carrierMSB (uint32_t)0x1 + #define gpsConfMSA (uint32_t)0x4 + #define gpsConfMSB (uint32_t)0x2 + uint32_t capabilities = gps_conf.CAPABILITIES; + if ((gps_conf.SUPL_MODE & carrierMSA) != carrierMSA) { + capabilities &= ~gpsConfMSA; + } + if ((gps_conf.SUPL_MODE & carrierMSB) != carrierMSB) { + capabilities &= ~gpsConfMSB; + } + + LOC_LOGV("getCarrierCapabilities: CAPABILITIES %x, SUPL_MODE %x, carrier capabilities %x", + gps_conf.CAPABILITIES, gps_conf.SUPL_MODE, capabilities); + return capabilities; +} + +/*=========================================================================== +FUNCTION loc_eng_init + +DESCRIPTION + Initialize the location engine, this include setting up global datas + and registers location engien with loc api service. + +DEPENDENCIES + None + +RETURN VALUE + 0: success + +SIDE EFFECTS + N/A + +===========================================================================*/ +int loc_eng_init(loc_eng_data_s_type &loc_eng_data, LocCallbacks* callbacks, + LOC_API_ADAPTER_EVENT_MASK_T event, ContextBase* context) + +{ + int ret_val = 0; + + ENTRY_LOG_CALLFLOW(); + if (NULL == callbacks || 0 == event) { + LOC_LOGE("loc_eng_init: bad parameters cb %p eMask %d", callbacks, event); + ret_val = -1; + EXIT_LOG(%d, ret_val); + return ret_val; + } + + STATE_CHECK((NULL == loc_eng_data.adapter), + "instance already initialized", return 0); + + memset(&loc_eng_data, 0, sizeof (loc_eng_data)); + + // Save callbacks + loc_eng_data.location_cb = callbacks->location_cb; + loc_eng_data.sv_status_cb = callbacks->sv_status_cb; + loc_eng_data.status_cb = callbacks->status_cb; + loc_eng_data.nmea_cb = callbacks->nmea_cb; + loc_eng_data.set_capabilities_cb = callbacks->set_capabilities_cb; + loc_eng_data.acquire_wakelock_cb = callbacks->acquire_wakelock_cb; + loc_eng_data.release_wakelock_cb = callbacks->release_wakelock_cb; + loc_eng_data.request_utc_time_cb = callbacks->request_utc_time_cb; + loc_eng_data.location_ext_parser = callbacks->location_ext_parser ? + callbacks->location_ext_parser : noProc; + loc_eng_data.sv_ext_parser = callbacks->sv_ext_parser ? + callbacks->sv_ext_parser : noProc; + loc_eng_data.intermediateFix = gps_conf.INTERMEDIATE_POS; + // initial states taken care of by the memset above + // loc_eng_data.engine_status -- GPS_STATUS_NONE; + // loc_eng_data.fix_session_status -- GPS_STATUS_NONE; + // loc_eng_data.mute_session_state -- LOC_MUTE_SESS_NONE; + + if ((event & LOC_API_ADAPTER_BIT_NMEA_1HZ_REPORT) && (gps_conf.NMEA_PROVIDER == NMEA_PROVIDER_AP)) + { + event = event ^ LOC_API_ADAPTER_BIT_NMEA_1HZ_REPORT; // unregister for modem NMEA report + loc_eng_data.generateNmea = true; + } + else + { + loc_eng_data.generateNmea = false; + } + + loc_eng_data.adapter = + new LocEngAdapter(event, &loc_eng_data, context, + (LocThread::tCreate)callbacks->create_thread_cb); + + LOC_LOGD("loc_eng_init created client, id = %p\n", + loc_eng_data.adapter); + loc_eng_data.adapter->sendMsg(new LocEngInit(&loc_eng_data)); + + EXIT_LOG(%d, ret_val); + return ret_val; +} + +static int loc_eng_reinit(loc_eng_data_s_type &loc_eng_data) +{ + ENTRY_LOG(); + int ret_val = LOC_API_ADAPTER_ERR_SUCCESS; + LocEngAdapter* adapter = loc_eng_data.adapter; + + adapter->sendMsg(new LocEngGnssConstellationConfig(adapter)); + adapter->sendMsg(new LocEngSuplVer(adapter, gps_conf.SUPL_VER)); + adapter->sendMsg(new LocEngLppConfig(adapter, gps_conf.LPP_PROFILE)); + adapter->sendMsg(new LocEngSensorControlConfig(adapter, sap_conf.SENSOR_USAGE, + sap_conf.SENSOR_PROVIDER)); + adapter->sendMsg(new LocEngAGlonassProtocol(adapter, gps_conf.A_GLONASS_POS_PROTOCOL_SELECT)); + + /* Make sure at least one of the sensor property is specified by the user in the gps.conf file. */ + if( sap_conf.GYRO_BIAS_RANDOM_WALK_VALID || + sap_conf.ACCEL_RANDOM_WALK_SPECTRAL_DENSITY_VALID || + sap_conf.ANGLE_RANDOM_WALK_SPECTRAL_DENSITY_VALID || + sap_conf.RATE_RANDOM_WALK_SPECTRAL_DENSITY_VALID || + sap_conf.VELOCITY_RANDOM_WALK_SPECTRAL_DENSITY_VALID ) { + adapter->sendMsg(new LocEngSensorProperties(adapter, + sap_conf.GYRO_BIAS_RANDOM_WALK_VALID, + sap_conf.GYRO_BIAS_RANDOM_WALK, + sap_conf.ACCEL_RANDOM_WALK_SPECTRAL_DENSITY_VALID, + sap_conf.ACCEL_RANDOM_WALK_SPECTRAL_DENSITY, + sap_conf.ANGLE_RANDOM_WALK_SPECTRAL_DENSITY_VALID, + sap_conf.ANGLE_RANDOM_WALK_SPECTRAL_DENSITY, + sap_conf.RATE_RANDOM_WALK_SPECTRAL_DENSITY_VALID, + sap_conf.RATE_RANDOM_WALK_SPECTRAL_DENSITY, + sap_conf.VELOCITY_RANDOM_WALK_SPECTRAL_DENSITY_VALID, + sap_conf.VELOCITY_RANDOM_WALK_SPECTRAL_DENSITY)); + } + + adapter->sendMsg(new LocEngSensorPerfControlConfig(adapter, + sap_conf.SENSOR_CONTROL_MODE, + sap_conf.SENSOR_ACCEL_SAMPLES_PER_BATCH, + sap_conf.SENSOR_ACCEL_BATCHES_PER_SEC, + sap_conf.SENSOR_GYRO_SAMPLES_PER_BATCH, + sap_conf.SENSOR_GYRO_BATCHES_PER_SEC, + sap_conf.SENSOR_ACCEL_SAMPLES_PER_BATCH_HIGH, + sap_conf.SENSOR_ACCEL_BATCHES_PER_SEC_HIGH, + sap_conf.SENSOR_GYRO_SAMPLES_PER_BATCH_HIGH, + sap_conf.SENSOR_GYRO_BATCHES_PER_SEC_HIGH, + sap_conf.SENSOR_ALGORITHM_CONFIG_MASK)); + + adapter->sendMsg(new LocEngEnableData(adapter, NULL, 0, (agpsStatus ? 1:0))); + + loc_eng_xtra_version_check(loc_eng_data, gps_conf.XTRA_VERSION_CHECK); + + LOC_LOGD("loc_eng_reinit reinit() successful"); + EXIT_LOG(%d, ret_val); + return ret_val; +} + +/*=========================================================================== +FUNCTION loc_eng_cleanup + +DESCRIPTION + Cleans location engine. The location client handle will be released. + +DEPENDENCIES + None + +RETURN VALUE + None + +SIDE EFFECTS + N/A + +===========================================================================*/ +void loc_eng_cleanup(loc_eng_data_s_type &loc_eng_data) +{ + ENTRY_LOG_CALLFLOW(); + INIT_CHECK(loc_eng_data.adapter, return); + + // XTRA has no state, so we are fine with it. + + // we need to check and clear NI +#if 0 + // we need to check and clear ATL + if (NULL != loc_eng_data.agnss_nif) { + delete loc_eng_data.agnss_nif; + loc_eng_data.agnss_nif = NULL; + } + if (NULL != loc_eng_data.internet_nif) { + delete loc_eng_data.internet_nif; + loc_eng_data.internet_nif = NULL; + } +#endif + if (loc_eng_data.adapter->isInSession()) + { + LOC_LOGD("loc_eng_cleanup: fix not stopped. stop it now."); + loc_eng_stop(loc_eng_data); + } + +#if 0 // can't afford to actually clean up, for many reason. + + LOC_LOGD("loc_eng_init: client opened. close it now."); + delete loc_eng_data.adapter; + loc_eng_data.adapter = NULL; + + loc_eng_dmn_conn_loc_api_server_unblock(); + loc_eng_dmn_conn_loc_api_server_join(); + +#endif + + EXIT_LOG(%s, VOID_RET); +} + + +/*=========================================================================== +FUNCTION loc_eng_start + +DESCRIPTION + Starts the tracking session + +DEPENDENCIES + None + +RETURN VALUE + 0: success + +SIDE EFFECTS + N/A + +===========================================================================*/ +int loc_eng_start(loc_eng_data_s_type &loc_eng_data) +{ + ENTRY_LOG_CALLFLOW(); + INIT_CHECK(loc_eng_data.adapter, return -1); + + if(! loc_eng_data.adapter->getUlpProxy()->sendStartFix()) + { + loc_eng_data.adapter->sendMsg(new LocEngStartFix(loc_eng_data.adapter)); + } + + EXIT_LOG(%d, 0); + return 0; +} + +static int loc_eng_start_handler(loc_eng_data_s_type &loc_eng_data) +{ + ENTRY_LOG(); + int ret_val = LOC_API_ADAPTER_ERR_SUCCESS; + + if (!loc_eng_data.adapter->isInSession()) { + ret_val = loc_eng_data.adapter->startFix(); + + if (ret_val == LOC_API_ADAPTER_ERR_SUCCESS || + ret_val == LOC_API_ADAPTER_ERR_ENGINE_DOWN || + ret_val == LOC_API_ADAPTER_ERR_PHONE_OFFLINE || + ret_val == LOC_API_ADAPTER_ERR_INTERNAL) + { + loc_eng_data.adapter->setInSession(TRUE); + } + } + + EXIT_LOG(%d, ret_val); + return ret_val; +} + +/*=========================================================================== +FUNCTION loc_eng_stop_wrapper + +DESCRIPTION + Stops the tracking session + +DEPENDENCIES + None + +RETURN VALUE + 0: success + +SIDE EFFECTS + N/A + +===========================================================================*/ +int loc_eng_stop(loc_eng_data_s_type &loc_eng_data) +{ + ENTRY_LOG_CALLFLOW(); + INIT_CHECK(loc_eng_data.adapter, return -1); + + if(! loc_eng_data.adapter->getUlpProxy()->sendStopFix()) + { + loc_eng_data.adapter->sendMsg(new LocEngStopFix(loc_eng_data.adapter)); + } + + EXIT_LOG(%d, 0); + return 0; +} + +static int loc_eng_stop_handler(loc_eng_data_s_type &loc_eng_data) +{ + ENTRY_LOG(); + int ret_val = LOC_API_ADAPTER_ERR_SUCCESS; + + if (loc_eng_data.adapter->isInSession()) { + + ret_val = loc_eng_data.adapter->stopFix(); + loc_eng_data.adapter->setInSession(FALSE); + } + + EXIT_LOG(%d, ret_val); + return ret_val; +} + +/*=========================================================================== +FUNCTION loc_eng_mute_one_session + +DESCRIPTION + Mutes one session + +DEPENDENCIES + None + +RETURN VALUE + 0: Success + +SIDE EFFECTS + N/A + +===========================================================================*/ +void loc_eng_mute_one_session(loc_eng_data_s_type &loc_eng_data) +{ + ENTRY_LOG(); + loc_eng_data.mute_session_state = LOC_MUTE_SESS_WAIT; + EXIT_LOG(%s, VOID_RET); +} + +/*=========================================================================== +FUNCTION loc_eng_set_position_mode + +DESCRIPTION + Sets the mode and fix frequency for the tracking session. + +DEPENDENCIES + None + +RETURN VALUE + 0: success + +SIDE EFFECTS + N/A + +===========================================================================*/ +int loc_eng_set_position_mode(loc_eng_data_s_type &loc_eng_data, + LocPosMode ¶ms) +{ + ENTRY_LOG_CALLFLOW(); + INIT_CHECK(loc_eng_data.adapter, return -1); + + // The position mode for AUTO/GSS/QCA1530 can only be standalone + if (!(gps_conf.CAPABILITIES & GPS_CAPABILITY_MSB) && + !(gps_conf.CAPABILITIES & GPS_CAPABILITY_MSA) && + (params.mode != LOC_POSITION_MODE_STANDALONE)) { + params.mode = LOC_POSITION_MODE_STANDALONE; + LOC_LOGD("Position mode changed to standalone for target with AUTO/GSS/qca1530."); + } + + if(! loc_eng_data.adapter->getUlpProxy()->sendFixMode(params)) + { + LocEngAdapter* adapter = loc_eng_data.adapter; + adapter->sendMsg(new LocEngPositionMode(adapter, params)); + } + + EXIT_LOG(%d, 0); + return 0; +} + +/*=========================================================================== +FUNCTION loc_eng_inject_time + +DESCRIPTION + This is used by Java native function to do time injection. + +DEPENDENCIES + None + +RETURN VALUE + 0 + +SIDE EFFECTS + N/A + +===========================================================================*/ +int loc_eng_inject_time(loc_eng_data_s_type &loc_eng_data, GpsUtcTime time, + int64_t timeReference, int uncertainty) +{ + ENTRY_LOG_CALLFLOW(); + INIT_CHECK(loc_eng_data.adapter, return -1); + LocEngAdapter* adapter = loc_eng_data.adapter; + + adapter->sendMsg(new LocEngSetTime(adapter, time, timeReference, + uncertainty)); + + EXIT_LOG(%d, 0); + return 0; +} + + +/*=========================================================================== +FUNCTION loc_eng_inject_location + +DESCRIPTION + This is used by Java native function to do location injection. + +DEPENDENCIES + None + +RETURN VALUE + 0 : Successful + error code : Failure + +SIDE EFFECTS + N/A +===========================================================================*/ +int loc_eng_inject_location(loc_eng_data_s_type &loc_eng_data, double latitude, + double longitude, float accuracy) +{ + ENTRY_LOG_CALLFLOW(); + INIT_CHECK(loc_eng_data.adapter, return -1); + LocEngAdapter* adapter = loc_eng_data.adapter; + if(adapter->mSupportsPositionInjection) + { + adapter->sendMsg(new LocEngInjectLocation(adapter, latitude, longitude, + accuracy)); + } + + EXIT_LOG(%d, 0); + return 0; +} + + +/*=========================================================================== +FUNCTION loc_eng_delete_aiding_data + +DESCRIPTION + This is used by Java native function to delete the aiding data. The function + updates the global variable for the aiding data to be deleted. If the GPS + engine is off, the aiding data will be deleted. Otherwise, the actual action + will happen when gps engine is turned off. + +DEPENDENCIES + Assumes the aiding data type specified in GpsAidingData matches with + LOC API specification. + +RETURN VALUE + None + +SIDE EFFECTS + N/A + +===========================================================================*/ +void loc_eng_delete_aiding_data(loc_eng_data_s_type &loc_eng_data, GpsAidingData f) +{ + ENTRY_LOG_CALLFLOW(); + INIT_CHECK(loc_eng_data.adapter, return); + + loc_eng_data.adapter->sendMsg(new LocEngDelAidData(&loc_eng_data, f)); + + EXIT_LOG(%s, VOID_RET); +} + +/*=========================================================================== + +FUNCTION loc_inform_gps_state + +DESCRIPTION + Informs the GPS Provider about the GPS status + +DEPENDENCIES + None + +RETURN VALUE + None + +SIDE EFFECTS + N/A + +===========================================================================*/ +static void loc_inform_gps_status(loc_eng_data_s_type &loc_eng_data, GpsStatusValue status) +{ + ENTRY_LOG(); + + if (loc_eng_data.status_cb) + { + GpsStatus gs = { sizeof(gs),status }; + CALLBACK_LOG_CALLFLOW("status_cb", %s, + loc_get_gps_status_name(gs.status)); + loc_eng_data.status_cb(&gs); + } + + EXIT_LOG(%s, VOID_RET); +} + +static int loc_eng_get_zpp_handler(loc_eng_data_s_type &loc_eng_data) +{ + ENTRY_LOG(); + int ret_val = LOC_API_ADAPTER_ERR_SUCCESS; + UlpLocation location; + LocPosTechMask tech_mask = LOC_POS_TECH_MASK_DEFAULT; + GpsLocationExtended locationExtended; + memset(&locationExtended, 0, sizeof (GpsLocationExtended)); + locationExtended.size = sizeof(locationExtended); + + ret_val = loc_eng_data.adapter->getZpp(location.gpsLocation, tech_mask); + //Mark the location source as from ZPP + location.gpsLocation.flags |= LOCATION_HAS_SOURCE_INFO; + location.position_source = ULP_LOCATION_IS_FROM_ZPP; + + loc_eng_data.adapter->getUlpProxy()->reportPosition(location, + locationExtended, + NULL, + LOC_SESS_SUCCESS, + tech_mask); + + EXIT_LOG(%d, ret_val); + return ret_val; +} + +/* + Callback function passed to Data Services State Machine + This becomes part of the state machine's servicer and + is used to send requests to the data services client +*/ +static int dataCallCb(void *cb_data) +{ + LOC_LOGD("Enter dataCallCb\n"); + int ret=0; + if(cb_data != NULL) { + dsCbData *cbData = (dsCbData *)cb_data; + LocEngAdapter *locAdapter = (LocEngAdapter *)cbData->mAdapter; + if(cbData->action == GPS_REQUEST_AGPS_DATA_CONN) { + LOC_LOGD("dataCallCb GPS_REQUEST_AGPS_DATA_CONN\n"); + ret = locAdapter->openAndStartDataCall(); + } + else if(cbData->action == GPS_RELEASE_AGPS_DATA_CONN) { + LOC_LOGD("dataCallCb GPS_RELEASE_AGPS_DATA_CONN\n"); + locAdapter->stopDataCall(); + } + } + else { + LOC_LOGE("NULL argument received. Failing.\n"); + ret = -1; + goto err; + } + +err: + LOC_LOGD("Exit dataCallCb ret = %d\n", ret); + return ret; +} + +/*=========================================================================== +FUNCTION loc_eng_agps_reinit + +DESCRIPTION + 2nd half of loc_eng_agps_init(), singled out for modem restart to use. + +DEPENDENCIES + NONE + +RETURN VALUE + 0 + +SIDE EFFECTS + N/A + +===========================================================================*/ +static void loc_eng_agps_reinit(loc_eng_data_s_type &loc_eng_data) +{ + ENTRY_LOG(); + + // Set server addresses which came before init + if (loc_eng_data.supl_host_set) + { + loc_eng_set_server(loc_eng_data, LOC_AGPS_SUPL_SERVER, + loc_eng_data.supl_host_buf, + loc_eng_data.supl_port_buf); + } + + if (loc_eng_data.c2k_host_set) + { + loc_eng_set_server(loc_eng_data, LOC_AGPS_CDMA_PDE_SERVER, + loc_eng_data.c2k_host_buf, + loc_eng_data.c2k_port_buf); + } + EXIT_LOG(%s, VOID_RET); +} +/*=========================================================================== +FUNCTION loc_eng_agps_init + +DESCRIPTION + Initialize the AGps interface. + +DEPENDENCIES + NONE + +RETURN VALUE + 0 + +SIDE EFFECTS + N/A + +===========================================================================*/ +void loc_eng_agps_init(loc_eng_data_s_type &loc_eng_data, AGpsExtCallbacks* callbacks) +{ + ENTRY_LOG_CALLFLOW(); + INIT_CHECK(loc_eng_data.adapter, return); + STATE_CHECK((NULL == loc_eng_data.agps_status_cb), + "agps instance already initialized", + return); + if (callbacks == NULL) { + LOC_LOGE("loc_eng_agps_init: bad parameters cb %p", callbacks); + EXIT_LOG(%s, VOID_RET); + return; + } + LocEngAdapter* adapter = loc_eng_data.adapter; + loc_eng_data.agps_status_cb = callbacks->status_cb; + + loc_eng_data.internet_nif = new AgpsStateMachine(servicerTypeAgps, + (void *)loc_eng_data.agps_status_cb, + AGPS_TYPE_WWAN_ANY, + false); + loc_eng_data.wifi_nif = new AgpsStateMachine(servicerTypeAgps, + (void *)loc_eng_data.agps_status_cb, + AGPS_TYPE_WIFI, + true); + + if ((gps_conf.CAPABILITIES & GPS_CAPABILITY_MSA) || + (gps_conf.CAPABILITIES & GPS_CAPABILITY_MSB)) { + loc_eng_data.agnss_nif = new AgpsStateMachine(servicerTypeAgps, + (void *)loc_eng_data.agps_status_cb, + AGPS_TYPE_SUPL, + false); + + if (adapter->mSupportsAgpsRequests) { + if(gps_conf.USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL) { + loc_eng_data.adapter->sendMsg(new LocEngDataClientInit(&loc_eng_data)); + } + loc_eng_dmn_conn_loc_api_server_launch(callbacks->create_thread_cb, + NULL, NULL, &loc_eng_data); + } + loc_eng_agps_reinit(loc_eng_data); + } + + EXIT_LOG(%s, VOID_RET); +} + +static void deleteAidingData(loc_eng_data_s_type &logEng) { + if (logEng.engine_status != GPS_STATUS_ENGINE_ON && + logEng.aiding_data_for_deletion != 0) { + logEng.adapter->deleteAidingData(logEng.aiding_data_for_deletion); + logEng.aiding_data_for_deletion = 0; + } +} + +static AgpsStateMachine* +getAgpsStateMachine(loc_eng_data_s_type &locEng, AGpsExtType agpsType) { + AgpsStateMachine* stateMachine; + switch (agpsType) { + case AGPS_TYPE_WIFI: { + stateMachine = locEng.wifi_nif; + break; + } + case AGPS_TYPE_INVALID: + case AGPS_TYPE_SUPL: { + stateMachine = locEng.agnss_nif; + break; + } + case AGPS_TYPE_SUPL_ES: { + locEng.ds_nif ? + stateMachine = locEng.ds_nif: + stateMachine = locEng.agnss_nif; + break; + } + default: + stateMachine = locEng.internet_nif; + } + return stateMachine; +} + +/*=========================================================================== +FUNCTION loc_eng_agps_open + +DESCRIPTION + This function is called when on-demand data connection opening is successful. +It should inform engine about the data open result. + +DEPENDENCIES + NONE + +RETURN VALUE + 0 + +SIDE EFFECTS + N/A + +===========================================================================*/ +int loc_eng_agps_open(loc_eng_data_s_type &loc_eng_data, AGpsExtType agpsType, + const char* apn, AGpsBearerType bearerType) +{ + ENTRY_LOG_CALLFLOW(); + INIT_CHECK(loc_eng_data.adapter && loc_eng_data.agps_status_cb, + return -1); + + if (apn == NULL) + { + LOC_LOGE("APN Name NULL\n"); + return 0; + } + + LOC_LOGD("loc_eng_agps_open APN name = [%s]", apn); + + int apn_len = smaller_of(strlen (apn), MAX_APN_LEN); + AgpsStateMachine* sm = getAgpsStateMachine(loc_eng_data, agpsType); + + loc_eng_data.adapter->sendMsg( + new LocEngAtlOpenSuccess(sm, apn, apn_len, bearerType)); + + EXIT_LOG(%d, 0); + return 0; +} + +/*=========================================================================== +FUNCTION loc_eng_agps_closed + +DESCRIPTION + This function is called when on-demand data connection closing is done. +It should inform engine about the data close result. + +DEPENDENCIES + NONE + +RETURN VALUE + 0 + +SIDE EFFECTS + N/A + +===========================================================================*/ +int loc_eng_agps_closed(loc_eng_data_s_type &loc_eng_data, AGpsExtType agpsType) +{ + ENTRY_LOG_CALLFLOW(); + INIT_CHECK(loc_eng_data.adapter && loc_eng_data.agps_status_cb, + return -1); + + AgpsStateMachine* sm = getAgpsStateMachine(loc_eng_data, agpsType); + loc_eng_data.adapter->sendMsg(new LocEngAtlClosed(sm)); + + EXIT_LOG(%d, 0); + return 0; +} + +/*=========================================================================== +FUNCTION loc_eng_agps_open_failed + +DESCRIPTION + This function is called when on-demand data connection opening has failed. +It should inform engine about the data open result. + +DEPENDENCIES + NONE + +RETURN VALUE + 0 + +SIDE EFFECTS + N/A + +===========================================================================*/ +int loc_eng_agps_open_failed(loc_eng_data_s_type &loc_eng_data, AGpsExtType agpsType) +{ + ENTRY_LOG_CALLFLOW(); + INIT_CHECK(loc_eng_data.adapter && loc_eng_data.agps_status_cb, + return -1); + + AgpsStateMachine* sm = getAgpsStateMachine(loc_eng_data, agpsType); + loc_eng_data.adapter->sendMsg(new LocEngAtlOpenFailed(sm)); + + EXIT_LOG(%d, 0); + return 0; +} + +/*=========================================================================== + +FUNCTION resolve_in_addr + +DESCRIPTION + Translates a hostname to in_addr struct + +DEPENDENCIES + n/a + +RETURN VALUE + TRUE if successful + +SIDE EFFECTS + n/a + +===========================================================================*/ +static boolean resolve_in_addr(const char *host_addr, struct in_addr *in_addr_ptr) +{ + ENTRY_LOG(); + boolean ret_val = TRUE; + + struct hostent *hp; + hp = gethostbyname(host_addr); + if (hp != NULL) /* DNS OK */ + { + memcpy(in_addr_ptr, hp->h_addr_list[0], hp->h_length); + } + else + { + /* Try IP representation */ + if (inet_aton(host_addr, in_addr_ptr) == 0) + { + /* IP not valid */ + LOC_LOGE("DNS query on '%s' failed\n", host_addr); + ret_val = FALSE; + } + } + + EXIT_LOG(%s, loc_logger_boolStr[ret_val!=0]); + return ret_val; +} + +/*=========================================================================== +FUNCTION loc_eng_set_server + +DESCRIPTION + This is used to set the default AGPS server. Server address is obtained + from gps.conf. + +DEPENDENCIES + NONE + +RETURN VALUE + 0 + +SIDE EFFECTS + N/A + +===========================================================================*/ +static int loc_eng_set_server(loc_eng_data_s_type &loc_eng_data, + LocServerType type, const char* hostname, int port) +{ + ENTRY_LOG(); + int ret = 0; + LocEngAdapter* adapter = loc_eng_data.adapter; + + if (LOC_AGPS_SUPL_SERVER == type) { + char url[MAX_URL_LEN]; + unsigned int len = 0; + const char nohost[] = "NONE"; + if (hostname == NULL || + strncasecmp(nohost, hostname, sizeof(nohost)) == 0) { + url[0] = NULL; + } else { + len = snprintf(url, sizeof(url), "%s:%u", hostname, (unsigned) port); + } + + if (sizeof(url) > len) { + adapter->sendMsg(new LocEngSetServerUrl(adapter, url, len)); + } + } else if (LOC_AGPS_CDMA_PDE_SERVER == type || + LOC_AGPS_CUSTOM_PDE_SERVER == type || + LOC_AGPS_MPC_SERVER == type) { + struct in_addr addr; + if (!resolve_in_addr(hostname, &addr)) + { + LOC_LOGE("loc_eng_set_server, hostname %s cannot be resolved.\n", hostname); + ret = -2; + } else { + unsigned int ip = htonl(addr.s_addr); + adapter->sendMsg(new LocEngSetServerIpv4(adapter, ip, port, type)); + } + } else { + LOC_LOGE("loc_eng_set_server, type %d cannot be resolved.\n", type); + } + + EXIT_LOG(%d, ret); + return ret; +} + +/*=========================================================================== +FUNCTION loc_eng_set_server_proxy + +DESCRIPTION + If loc_eng_set_server is called before loc_eng_init, it doesn't work. This + proxy buffers server settings and calls loc_eng_set_server when the client is + open. + +DEPENDENCIES + NONE + +RETURN VALUE + 0 + +SIDE EFFECTS + N/A + +===========================================================================*/ +int loc_eng_set_server_proxy(loc_eng_data_s_type &loc_eng_data, + LocServerType type, + const char* hostname, int port) +{ + ENTRY_LOG_CALLFLOW(); + int ret_val = 0; + + LOC_LOGV("save the address, type: %d, hostname: %s, port: %d", + (int) type, hostname, port); + switch (type) + { + case LOC_AGPS_SUPL_SERVER: + strlcpy(loc_eng_data.supl_host_buf, hostname, + sizeof(loc_eng_data.supl_host_buf)); + loc_eng_data.supl_port_buf = port; + loc_eng_data.supl_host_set = 1; + break; + case LOC_AGPS_CDMA_PDE_SERVER: + strlcpy(loc_eng_data.c2k_host_buf, hostname, + sizeof(loc_eng_data.c2k_host_buf)); + loc_eng_data.c2k_port_buf = port; + loc_eng_data.c2k_host_set = 1; + break; + default: + LOC_LOGE("loc_eng_set_server_proxy, unknown server type = %d", (int) type); + } + + if (NULL != loc_eng_data.adapter) + { + ret_val = loc_eng_set_server(loc_eng_data, type, hostname, port); + } + + EXIT_LOG(%d, ret_val); + return ret_val; +} + +/*=========================================================================== +FUNCTION loc_eng_agps_ril_update_network_availability + +DESCRIPTION + Sets data call allow vs disallow flag to modem + This is the only member of sLocEngAGpsRilInterface implemented. + +DEPENDENCIES + None + +RETURN VALUE + 0: success + +SIDE EFFECTS + N/A + +===========================================================================*/ +void loc_eng_agps_ril_update_network_availability(loc_eng_data_s_type &loc_eng_data, + int available, const char* apn) +{ + ENTRY_LOG_CALLFLOW(); + + //This is to store the status of data availability over the network. + //If GPS is not enabled, the INIT_CHECK will fail and the modem will + //not be updated with the network's availability. Since the data status + //can change before GPS is enabled the, storing the status will enable + //us to inform the modem after GPS is enabled + agpsStatus = available; + + INIT_CHECK(loc_eng_data.adapter, return); + if (apn != NULL) + { + LOC_LOGD("loc_eng_agps_ril_update_network_availability: APN Name = [%s]\n", apn); + int apn_len = smaller_of(strlen (apn), MAX_APN_LEN); + LocEngAdapter* adapter = loc_eng_data.adapter; + adapter->sendMsg(new LocEngEnableData(adapter, apn, apn_len, available)); + } + EXIT_LOG(%s, VOID_RET); +} + +int loc_eng_agps_install_certificates(loc_eng_data_s_type &loc_eng_data, + const DerEncodedCertificate* certificates, + size_t numberOfCerts) +{ + ENTRY_LOG_CALLFLOW(); + int ret_val = AGPS_CERTIFICATE_OPERATION_SUCCESS; + + uint32_t slotBitMask = gps_conf.AGPS_CERT_WRITABLE_MASK; + uint32_t slotCount = 0; + for (uint32_t slotBitMaskCounter=slotBitMask; slotBitMaskCounter; slotCount++) { + slotBitMaskCounter &= slotBitMaskCounter - 1; + } + LOC_LOGD("SlotBitMask=%u SlotCount=%u NumberOfCerts=%u", + slotBitMask, slotCount, numberOfCerts); + + LocEngAdapter* adapter = loc_eng_data.adapter; + + if (numberOfCerts == 0) { + LOC_LOGE("No certs to install, since numberOfCerts is zero"); + ret_val = AGPS_CERTIFICATE_OPERATION_SUCCESS; + } else if (!adapter) { + LOC_LOGE("adapter is null!"); + ret_val = AGPS_CERTIFICATE_ERROR_GENERIC; + } else if (slotCount < numberOfCerts) { + LOC_LOGE("Not enough cert slots (%u) to install %u certs!", + slotCount, numberOfCerts); + ret_val = AGPS_CERTIFICATE_ERROR_TOO_MANY_CERTIFICATES; + } else { + for (int i=0; i < numberOfCerts; ++i) + { + if (certificates[i].length > AGPS_CERTIFICATE_MAX_LENGTH) { + LOC_LOGE("cert#(%u) length of %u is too big! greater than %u", + certificates[i].length, AGPS_CERTIFICATE_MAX_LENGTH); + ret_val = AGPS_CERTIFICATE_ERROR_GENERIC; + break; + } + } + + if (ret_val == AGPS_CERTIFICATE_OPERATION_SUCCESS) { + adapter->sendMsg(new LocEngInstallAGpsCert(adapter, + certificates, + numberOfCerts, + slotBitMask)); + } + } + + EXIT_LOG(%d, ret_val); + return ret_val; +} + +void loc_eng_configuration_update (loc_eng_data_s_type &loc_eng_data, + const char* config_data, int32_t length) +{ + ENTRY_LOG_CALLFLOW(); + + if (config_data && length > 0) { + loc_gps_cfg_s_type gps_conf_tmp = gps_conf; + UTIL_UPDATE_CONF(config_data, length, gps_conf_table); + LocEngAdapter* adapter = loc_eng_data.adapter; + + // it is possible that HAL is not init'ed at this time + if (adapter) { + if (gps_conf_tmp.SUPL_VER != gps_conf.SUPL_VER) { + adapter->sendMsg(new LocEngSuplVer(adapter, gps_conf.SUPL_VER)); + } + if (gps_conf_tmp.LPP_PROFILE != gps_conf.LPP_PROFILE) { + adapter->sendMsg(new LocEngLppConfig(adapter, gps_conf.LPP_PROFILE)); + } + if (gps_conf_tmp.A_GLONASS_POS_PROTOCOL_SELECT != gps_conf.A_GLONASS_POS_PROTOCOL_SELECT) { + adapter->sendMsg(new LocEngAGlonassProtocol(adapter, + gps_conf.A_GLONASS_POS_PROTOCOL_SELECT)); + } + if (gps_conf_tmp.SUPL_MODE != gps_conf.SUPL_MODE) { + adapter->sendMsg(new LocEngSuplMode(adapter->getUlpProxy())); + } + } + + gps_conf_tmp.SUPL_VER = gps_conf.SUPL_VER; + gps_conf_tmp.LPP_PROFILE = gps_conf.LPP_PROFILE; + gps_conf_tmp.A_GLONASS_POS_PROTOCOL_SELECT = gps_conf.A_GLONASS_POS_PROTOCOL_SELECT; + gps_conf_tmp.GPS_LOCK = gps_conf.GPS_LOCK; + gps_conf = gps_conf_tmp; + } + + EXIT_LOG(%s, VOID_RET); +} + +/*=========================================================================== +FUNCTION loc_eng_report_status + +DESCRIPTION + Reports GPS engine state to Java layer. + +DEPENDENCIES + N/A + +RETURN VALUE + N/A + +SIDE EFFECTS + N/A + +===========================================================================*/ +static void loc_eng_report_status (loc_eng_data_s_type &loc_eng_data, GpsStatusValue status) +{ + ENTRY_LOG(); + // Switch from WAIT to MUTE, for "engine on" or "session begin" event + if (status == GPS_STATUS_SESSION_BEGIN || status == GPS_STATUS_ENGINE_ON) + { + if (loc_eng_data.mute_session_state == LOC_MUTE_SESS_WAIT) + { + LOC_LOGD("loc_eng_report_status: mute_session_state changed from WAIT to IN SESSION"); + loc_eng_data.mute_session_state = LOC_MUTE_SESS_IN_SESSION; + } + } + + // Switch off MUTE session + if (loc_eng_data.mute_session_state == LOC_MUTE_SESS_IN_SESSION && + (status == GPS_STATUS_SESSION_END || status == GPS_STATUS_ENGINE_OFF)) + { + LOC_LOGD("loc_eng_report_status: mute_session_state changed from IN SESSION to NONE"); + loc_eng_data.mute_session_state = LOC_MUTE_SESS_NONE; + } + + // Session End is not reported during Android navigating state + boolean navigating = loc_eng_data.adapter->isInSession(); + if (status != GPS_STATUS_NONE && + !(status == GPS_STATUS_SESSION_END && navigating) && + !(status == GPS_STATUS_SESSION_BEGIN && !navigating)) + { + if (loc_eng_data.mute_session_state != LOC_MUTE_SESS_IN_SESSION) + { + // Inform GpsLocationProvider about mNavigating status + loc_inform_gps_status(loc_eng_data, status); + } + else { + LOC_LOGD("loc_eng_report_status: muting the status report."); + } + } + + // Only keeps ENGINE ON/OFF in engine_status + if (status == GPS_STATUS_ENGINE_ON || status == GPS_STATUS_ENGINE_OFF) + { + loc_eng_data.engine_status = status; + } + + // Only keeps SESSION BEGIN/END in fix_session_status + if (status == GPS_STATUS_SESSION_BEGIN || status == GPS_STATUS_SESSION_END) + { + loc_eng_data.fix_session_status = status; + } + EXIT_LOG(%s, VOID_RET); +} + +/*=========================================================================== +FUNCTION loc_eng_handle_engine_down + loc_eng_handle_engine_up + +DESCRIPTION + Calls this function when it is detected that modem restart is happening. + Either we detected the modem is down or received modem up event. + This must be called from the deferred thread to avoid race condition. + +DEPENDENCIES + None + +RETURN VALUE + None + +SIDE EFFECTS + N/A + +===========================================================================*/ +void loc_eng_handle_engine_down(loc_eng_data_s_type &loc_eng_data) +{ + ENTRY_LOG(); + loc_eng_ni_reset_on_engine_restart(loc_eng_data); + loc_eng_report_status(loc_eng_data, GPS_STATUS_ENGINE_OFF); + EXIT_LOG(%s, VOID_RET); +} + +void loc_eng_handle_engine_up(loc_eng_data_s_type &loc_eng_data) +{ + ENTRY_LOG(); + loc_eng_reinit(loc_eng_data); + + loc_eng_data.adapter->requestPowerVote(); + + if (loc_eng_data.agps_status_cb != NULL) { + if (loc_eng_data.agnss_nif) + loc_eng_data.agnss_nif->dropAllSubscribers(); + if (loc_eng_data.internet_nif) + loc_eng_data.internet_nif->dropAllSubscribers(); + + loc_eng_agps_reinit(loc_eng_data); + } + + // modem is back up. If we crashed in the middle of navigating, we restart. + if (loc_eng_data.adapter->isInSession()) { + // This sets the copy in adapter to modem + loc_eng_data.adapter->setInSession(false); + loc_eng_data.adapter->sendMsg(new LocEngStartFix(loc_eng_data.adapter)); + } + EXIT_LOG(%s, VOID_RET); +} + +#ifdef USE_GLIB +/*=========================================================================== +FUNCTION set_sched_policy + +DESCRIPTION + Local copy of this function which bypasses android set_sched_policy + +DEPENDENCIES + None + +RETURN VALUE + 0 + +SIDE EFFECTS + N/A + +===========================================================================*/ +static int set_sched_policy(int tid, SchedPolicy policy) +{ + return 0; +} +#endif /* USE_GLIB */ + +/*=========================================================================== +FUNCTION loc_eng_read_config + +DESCRIPTION + Initiates the reading of the gps config file stored in /etc dir + +DEPENDENCIES + None + +RETURN VALUE + 0: success + +SIDE EFFECTS + N/A + +===========================================================================*/ +int loc_eng_read_config(void) +{ + ENTRY_LOG_CALLFLOW(); + if(configAlreadyRead == false) + { + // Initialize our defaults before reading of configuration file overwrites them. + loc_default_parameters(); + // We only want to parse the conf file once. This is a good place to ensure that. + // In fact one day the conf file should go into context. + UTIL_READ_CONF(GPS_CONF_FILE, gps_conf_table); + UTIL_READ_CONF(SAP_CONF_FILE, sap_conf_table); + configAlreadyRead = true; + } else { + LOC_LOGV("GPS Config file has already been read\n"); + } + + EXIT_LOG(%d, 0); + return 0; +} + +/*=========================================================================== +FUNCTION loc_eng_gps_measurement_init + +DESCRIPTION + Initialize gps measurement module. + +DEPENDENCIES + N/A + +RETURN VALUE + 0: success + +SIDE EFFECTS + N/A + +===========================================================================*/ +int loc_eng_gps_measurement_init(loc_eng_data_s_type &loc_eng_data, + GpsMeasurementCallbacks* callbacks) +{ + ENTRY_LOG_CALLFLOW(); + + STATE_CHECK((NULL == loc_eng_data.gps_measurement_cb), + "gps measurement already initialized", + return GPS_MEASUREMENT_ERROR_ALREADY_INIT); + STATE_CHECK((callbacks != NULL), + "callbacks can not be NULL", + return GPS_MEASUREMENT_ERROR_GENERIC); + STATE_CHECK(loc_eng_data.adapter, + "GpsInterface must be initialized first", + return GPS_MEASUREMENT_ERROR_GENERIC); + + // updated the mask + LOC_API_ADAPTER_EVENT_MASK_T event = LOC_API_ADAPTER_BIT_GNSS_MEASUREMENT; + loc_eng_data.adapter->sendMsg(new LocEngUpdateRegistrationMask( + &loc_eng_data, + event, + LOC_REGISTRATION_MASK_ENABLED)); + // set up the callback + loc_eng_data.gps_measurement_cb = callbacks->measurement_callback; + LOC_LOGD ("%s, event masks updated successfully", __func__); + + return GPS_MEASUREMENT_OPERATION_SUCCESS; +} + +/*=========================================================================== +FUNCTION loc_eng_gps_measurement_close + +DESCRIPTION + Close gps measurement module. + +DEPENDENCIES + N/A + +RETURN VALUE + N/A + +SIDE EFFECTS + N/A + +===========================================================================*/ +void loc_eng_gps_measurement_close(loc_eng_data_s_type &loc_eng_data) +{ + ENTRY_LOG_CALLFLOW(); + + INIT_CHECK(loc_eng_data.adapter, return); + + // updated the mask + LOC_API_ADAPTER_EVENT_MASK_T event = LOC_API_ADAPTER_BIT_GNSS_MEASUREMENT; + loc_eng_data.adapter->sendMsg(new LocEngUpdateRegistrationMask( + &loc_eng_data, + event, + LOC_REGISTRATION_MASK_DISABLED)); + // set up the callback + loc_eng_data.gps_measurement_cb = NULL; + EXIT_LOG(%d, 0); +} diff --git a/gps/loc_api/libloc_api_50001/loc_eng.h b/gps/loc_api/libloc_api_50001/loc_eng.h new file mode 100644 index 000000000..a203e6bb6 --- /dev/null +++ b/gps/loc_api/libloc_api_50001/loc_eng.h @@ -0,0 +1,270 @@ +/* Copyright (c) 2009-2014, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef LOC_ENG_H +#define LOC_ENG_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +// Uncomment to keep all LOG messages (LOGD, LOGI, LOGV, etc.) +#define MAX_NUM_ATL_CONNECTIONS 2 + +// Define boolean type to be used by libgps on loc api module +typedef unsigned char boolean; + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// The data connection minimal open time +#define DATA_OPEN_MIN_TIME 1 /* sec */ + +// The system sees GPS engine turns off after inactive for this period of time +#define GPS_AUTO_OFF_TIME 2 /* secs */ +#define SUCCESS TRUE +#define FAILURE FALSE +#define INVALID_ATL_CONNECTION_HANDLE -1 + +#define MAX_XTRA_SERVER_URL_LENGTH 256 + +enum loc_nmea_provider_e_type { + NMEA_PROVIDER_AP = 0, // Application Processor Provider of NMEA + NMEA_PROVIDER_MP // Modem Processor Provider of NMEA +}; + +enum loc_mute_session_e_type { + LOC_MUTE_SESS_NONE = 0, + LOC_MUTE_SESS_WAIT, + LOC_MUTE_SESS_IN_SESSION +}; + +// Module data +typedef struct loc_eng_data_s +{ + LocEngAdapter *adapter; + loc_location_cb_ext location_cb; + gps_status_callback status_cb; + loc_sv_status_cb_ext sv_status_cb; + agps_status_extended agps_status_cb; + gps_nmea_callback nmea_cb; + gps_ni_notify_callback ni_notify_cb; + gps_set_capabilities set_capabilities_cb; + gps_acquire_wakelock acquire_wakelock_cb; + gps_release_wakelock release_wakelock_cb; + gps_request_utc_time request_utc_time_cb; + gps_measurement_callback gps_measurement_cb; + boolean intermediateFix; + AGpsStatusValue agps_status; + loc_eng_xtra_data_s_type xtra_module_data; + loc_eng_ni_data_s_type loc_eng_ni_data; + + // AGPS state machines + AgpsStateMachine* agnss_nif; + AgpsStateMachine* internet_nif; + AgpsStateMachine* wifi_nif; + //State machine for Data Services + AgpsStateMachine* ds_nif; + + // GPS engine status + GpsStatusValue engine_status; + GpsStatusValue fix_session_status; + + // Aiding data information to be deleted, aiding data can only be deleted when GPS engine is off + GpsAidingData aiding_data_for_deletion; + + // For muting session broadcast + loc_mute_session_e_type mute_session_state; + + // For nmea generation + boolean generateNmea; + uint32_t sv_used_mask; + float hdop; + float pdop; + float vdop; + + // Address buffers, for addressing setting before init + int supl_host_set; + char supl_host_buf[101]; + int supl_port_buf; + int c2k_host_set; + char c2k_host_buf[101]; + int c2k_port_buf; + int mpc_host_set; + char mpc_host_buf[101]; + int mpc_port_buf; + + loc_ext_parser location_ext_parser; + loc_ext_parser sv_ext_parser; +} loc_eng_data_s_type; + +/* GPS.conf support */ +/* NOTE: the implementaiton of the parser casts number + fields to 32 bit. To ensure all 'n' fields working, + they must all be 32 bit fields. */ +typedef struct loc_gps_cfg_s +{ + uint32_t INTERMEDIATE_POS; + uint32_t ACCURACY_THRES; + uint32_t SUPL_VER; + uint32_t SUPL_MODE; + uint32_t CAPABILITIES; + uint32_t LPP_PROFILE; + uint32_t XTRA_VERSION_CHECK; + char XTRA_SERVER_1[MAX_XTRA_SERVER_URL_LENGTH]; + char XTRA_SERVER_2[MAX_XTRA_SERVER_URL_LENGTH]; + char XTRA_SERVER_3[MAX_XTRA_SERVER_URL_LENGTH]; + uint32_t USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL; + uint32_t NMEA_PROVIDER; + uint32_t GPS_LOCK; + uint32_t A_GLONASS_POS_PROTOCOL_SELECT; + uint32_t AGPS_CERT_WRITABLE_MASK; +} loc_gps_cfg_s_type; + +/* NOTE: the implementaiton of the parser casts number + fields to 32 bit. To ensure all 'n' fields working, + they must all be 32 bit fields. */ +/* Meanwhile, *_valid fields are 8 bit fields, and 'f' + fields are double. Rigid as they are, it is the + the status quo, until the parsing mechanism is + change, that is. */ +typedef struct +{ + uint8_t GYRO_BIAS_RANDOM_WALK_VALID; + double GYRO_BIAS_RANDOM_WALK; + uint32_t SENSOR_ACCEL_BATCHES_PER_SEC; + uint32_t SENSOR_ACCEL_SAMPLES_PER_BATCH; + uint32_t SENSOR_GYRO_BATCHES_PER_SEC; + uint32_t SENSOR_GYRO_SAMPLES_PER_BATCH; + uint32_t SENSOR_ACCEL_BATCHES_PER_SEC_HIGH; + uint32_t SENSOR_ACCEL_SAMPLES_PER_BATCH_HIGH; + uint32_t SENSOR_GYRO_BATCHES_PER_SEC_HIGH; + uint32_t SENSOR_GYRO_SAMPLES_PER_BATCH_HIGH; + uint32_t SENSOR_CONTROL_MODE; + uint32_t SENSOR_USAGE; + uint32_t SENSOR_ALGORITHM_CONFIG_MASK; + uint8_t ACCEL_RANDOM_WALK_SPECTRAL_DENSITY_VALID; + double ACCEL_RANDOM_WALK_SPECTRAL_DENSITY; + uint8_t ANGLE_RANDOM_WALK_SPECTRAL_DENSITY_VALID; + double ANGLE_RANDOM_WALK_SPECTRAL_DENSITY; + uint8_t RATE_RANDOM_WALK_SPECTRAL_DENSITY_VALID; + double RATE_RANDOM_WALK_SPECTRAL_DENSITY; + uint8_t VELOCITY_RANDOM_WALK_SPECTRAL_DENSITY_VALID; + double VELOCITY_RANDOM_WALK_SPECTRAL_DENSITY; + uint32_t SENSOR_PROVIDER; +} loc_sap_cfg_s_type; + +extern loc_gps_cfg_s_type gps_conf; +extern loc_sap_cfg_s_type sap_conf; + + +uint32_t getCarrierCapabilities(); + +//loc_eng functions +int loc_eng_init(loc_eng_data_s_type &loc_eng_data, + LocCallbacks* callbacks, + LOC_API_ADAPTER_EVENT_MASK_T event, + ContextBase* context); +int loc_eng_start(loc_eng_data_s_type &loc_eng_data); +int loc_eng_stop(loc_eng_data_s_type &loc_eng_data); +void loc_eng_cleanup(loc_eng_data_s_type &loc_eng_data); +int loc_eng_inject_time(loc_eng_data_s_type &loc_eng_data, + GpsUtcTime time, int64_t timeReference, + int uncertainty); +int loc_eng_inject_location(loc_eng_data_s_type &loc_eng_data, + double latitude, double longitude, + float accuracy); +void loc_eng_delete_aiding_data(loc_eng_data_s_type &loc_eng_data, + GpsAidingData f); +int loc_eng_set_position_mode(loc_eng_data_s_type &loc_eng_data, + LocPosMode ¶ms); +const void* loc_eng_get_extension(loc_eng_data_s_type &loc_eng_data, + const char* name); +int loc_eng_set_server_proxy(loc_eng_data_s_type &loc_eng_data, + LocServerType type, const char *hostname, int port); +void loc_eng_mute_one_session(loc_eng_data_s_type &loc_eng_data); +int loc_eng_read_config(void); + +//loc_eng_agps functions +void loc_eng_agps_init(loc_eng_data_s_type &loc_eng_data, + AGpsExtCallbacks* callbacks); +int loc_eng_agps_open(loc_eng_data_s_type &loc_eng_data, AGpsExtType agpsType, + const char* apn, AGpsBearerType bearerType); +int loc_eng_agps_closed(loc_eng_data_s_type &loc_eng_data, AGpsExtType agpsType); +int loc_eng_agps_open_failed(loc_eng_data_s_type &loc_eng_data, AGpsExtType agpsType); +void loc_eng_agps_ril_update_network_availability(loc_eng_data_s_type &loc_eng_data, + int avaiable, const char* apn); +int loc_eng_agps_install_certificates(loc_eng_data_s_type &loc_eng_data, + const DerEncodedCertificate* certificates, + size_t length); + +//loc_eng_xtra functions +int loc_eng_xtra_init (loc_eng_data_s_type &loc_eng_data, + GpsXtraExtCallbacks* callbacks); +int loc_eng_xtra_inject_data(loc_eng_data_s_type &loc_eng_data, + char* data, int length); +int loc_eng_xtra_request_server(loc_eng_data_s_type &loc_eng_data); +void loc_eng_xtra_version_check(loc_eng_data_s_type &loc_eng_data, int check); + +//loc_eng_ni functions +extern void loc_eng_ni_init(loc_eng_data_s_type &loc_eng_data, + GpsNiExtCallbacks *callbacks); +extern void loc_eng_ni_respond(loc_eng_data_s_type &loc_eng_data, + int notif_id, GpsUserResponseType user_response); +extern void loc_eng_ni_request_handler(loc_eng_data_s_type &loc_eng_data, + const GpsNiNotification *notif, + const void* passThrough); +extern void loc_eng_ni_reset_on_engine_restart(loc_eng_data_s_type &loc_eng_data); + +void loc_eng_configuration_update (loc_eng_data_s_type &loc_eng_data, + const char* config_data, int32_t length); +int loc_eng_gps_measurement_init(loc_eng_data_s_type &loc_eng_data, + GpsMeasurementCallbacks* callbacks); +void loc_eng_gps_measurement_close(loc_eng_data_s_type &loc_eng_data); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif // LOC_ENG_H diff --git a/gps/loc_api/libloc_api_50001/loc_eng_agps.cpp b/gps/loc_api/libloc_api_50001/loc_eng_agps.cpp new file mode 100644 index 000000000..5016b5c4e --- /dev/null +++ b/gps/loc_api/libloc_api_50001/loc_eng_agps.cpp @@ -0,0 +1,970 @@ +/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#define LOG_NDDEBUG 0 +#define LOG_TAG "LocSvc_eng" + +#include +#include +#include +#include +#include +#include +#include + +//====================================================================== +// C callbacks +//====================================================================== + +// This is given to linked_list_add as the dealloc callback +// data -- an instance of Subscriber +static void deleteObj(void* data) +{ + delete (Subscriber*)data; +} + +// This is given to linked_list_search() as the comparison callback +// when the state manchine needs to process for particular subscriber +// fromCaller -- caller provides this obj +// fromList -- linked_list_search() function take this one from list +static bool hasSubscriber(void* fromCaller, void* fromList) +{ + Notification* notification = (Notification*)fromCaller; + Subscriber* s1 = (Subscriber*)fromList; + + return s1->forMe(*notification); +} + +// This is gvien to linked_list_search() to notify subscriber objs +// when the state machine needs to inform all subscribers of resource +// status changes, e.g. when resource is GRANTED. +// fromCaller -- caller provides this ptr to a Notification obj. +// fromList -- linked_list_search() function take this one from list +static bool notifySubscriber(void* fromCaller, void* fromList) +{ + Notification* notification = (Notification*)fromCaller; + Subscriber* s1 = (Subscriber*)fromList; + + // we notify every subscriber indiscriminatively + // each subscriber decides if this notification is interesting. + return s1->notifyRsrcStatus(*notification) && + // if we do not want to delete the subscriber from the + // the list, we must set this to false so this function + // returns false + notification->postNotifyDelete; +} + +//====================================================================== +// Notification +//====================================================================== +const int Notification::BROADCAST_ALL = 0x80000000; +const int Notification::BROADCAST_ACTIVE = 0x80000001; +const int Notification::BROADCAST_INACTIVE = 0x80000002; +const unsigned char DSStateMachine::MAX_START_DATA_CALL_RETRIES = 4; +const unsigned int DSStateMachine::DATA_CALL_RETRY_DELAY_MSEC = 500; +//====================================================================== +// Subscriber: BITSubscriber / ATLSubscriber / WIFISubscriber +//====================================================================== +bool Subscriber::forMe(Notification ¬ification) +{ + if (NULL != notification.rcver) { + return equals(notification.rcver); + } else { + return Notification::BROADCAST_ALL == notification.groupID || + (Notification::BROADCAST_ACTIVE == notification.groupID && + !isInactive()) || + (Notification::BROADCAST_INACTIVE == notification.groupID && + isInactive()); + } +} +bool BITSubscriber::equals(const Subscriber *s) const +{ + BITSubscriber* bitS = (BITSubscriber*)s; + + return (ID == bitS->ID && + (INADDR_NONE != (unsigned int)ID || + 0 == strncmp(mIPv6Addr, bitS->mIPv6Addr, sizeof(mIPv6Addr)))); +} + +bool BITSubscriber::notifyRsrcStatus(Notification ¬ification) +{ + bool notify = forMe(notification); + + if (notify) { + switch(notification.rsrcStatus) + { + case RSRC_UNSUBSCRIBE: + case RSRC_RELEASED: + loc_eng_dmn_conn_loc_api_server_data_conn( + LOC_ENG_IF_REQUEST_SENDER_ID_GPSONE_DAEMON, + GPSONE_LOC_API_IF_RELEASE_SUCCESS); + break; + case RSRC_DENIED: + loc_eng_dmn_conn_loc_api_server_data_conn( + LOC_ENG_IF_REQUEST_SENDER_ID_GPSONE_DAEMON, + GPSONE_LOC_API_IF_FAILURE); + break; + case RSRC_GRANTED: + loc_eng_dmn_conn_loc_api_server_data_conn( + LOC_ENG_IF_REQUEST_SENDER_ID_GPSONE_DAEMON, + GPSONE_LOC_API_IF_REQUEST_SUCCESS); + break; + default: + notify = false; + } + } + + return notify; +} + +bool ATLSubscriber::notifyRsrcStatus(Notification ¬ification) +{ + bool notify = forMe(notification); + + if (notify) { + switch(notification.rsrcStatus) + { + case RSRC_UNSUBSCRIBE: + case RSRC_RELEASED: + ((LocEngAdapter*)mLocAdapter)->atlCloseStatus(ID, 1); + break; + case RSRC_DENIED: + { + AGpsExtType type = mBackwardCompatibleMode ? + AGPS_TYPE_INVALID : mStateMachine->getType(); + ((LocEngAdapter*)mLocAdapter)->atlOpenStatus(ID, 0, + (char*)mStateMachine->getAPN(), + mStateMachine->getBearer(), + type); + } + break; + case RSRC_GRANTED: + { + AGpsExtType type = mBackwardCompatibleMode ? + AGPS_TYPE_INVALID : mStateMachine->getType(); + ((LocEngAdapter*)mLocAdapter)->atlOpenStatus(ID, 1, + (char*)mStateMachine->getAPN(), + mStateMachine->getBearer(), + type); + } + break; + default: + notify = false; + } + } + + return notify; +} + +bool WIFISubscriber::notifyRsrcStatus(Notification ¬ification) +{ + bool notify = forMe(notification); + + if (notify) { + switch(notification.rsrcStatus) + { + case RSRC_UNSUBSCRIBE: + break; + case RSRC_RELEASED: + loc_eng_dmn_conn_loc_api_server_data_conn( + senderId, + GPSONE_LOC_API_IF_RELEASE_SUCCESS); + break; + case RSRC_DENIED: + loc_eng_dmn_conn_loc_api_server_data_conn( + senderId, + GPSONE_LOC_API_IF_FAILURE); + break; + case RSRC_GRANTED: + loc_eng_dmn_conn_loc_api_server_data_conn( + senderId, + GPSONE_LOC_API_IF_REQUEST_SUCCESS); + break; + default: + notify = false; + } + } + + return notify; +} +bool DSSubscriber::notifyRsrcStatus(Notification ¬ification) +{ + bool notify = forMe(notification); + LOC_LOGD("DSSubscriber::notifyRsrcStatus. notify:%d \n",(int)(notify)); + if(notify) { + switch(notification.rsrcStatus) { + case RSRC_UNSUBSCRIBE: + case RSRC_RELEASED: + case RSRC_DENIED: + case RSRC_GRANTED: + ((DSStateMachine *)mStateMachine)->informStatus(notification.rsrcStatus, ID); + break; + default: + notify = false; + } + } + return notify; +} +void DSSubscriber :: setInactive() +{ + mIsInactive = true; + ((DSStateMachine *)mStateMachine)->informStatus(RSRC_UNSUBSCRIBE, ID); +} +//====================================================================== +// AgpsState: AgpsReleasedState / AgpsPendingState / AgpsAcquiredState +//====================================================================== + +// AgpsReleasedState +class AgpsReleasedState : public AgpsState +{ + friend class AgpsStateMachine; + + inline AgpsReleasedState(AgpsStateMachine* stateMachine) : + AgpsState(stateMachine) + { mReleasedState = this; } + + inline ~AgpsReleasedState() {} +public: + virtual AgpsState* onRsrcEvent(AgpsRsrcStatus event, void* data); + inline virtual char* whoami() {return (char*)"AgpsReleasedState";} +}; + +AgpsState* AgpsReleasedState::onRsrcEvent(AgpsRsrcStatus event, void* data) +{ + LOC_LOGD("AgpsReleasedState::onRsrcEvent; event:%d\n", (int)event); + if (mStateMachine->hasSubscribers()) { + LOC_LOGE("Error: %s subscriber list not empty!!!", whoami()); + // I don't know how to recover from it. I am adding this rather + // for debugging purpose. + } + + AgpsState* nextState = this; + switch (event) + { + case RSRC_SUBSCRIBE: + { + // no notification until we get RSRC_GRANTED + // but we need to add subscriber to the list + mStateMachine->addSubscriber((Subscriber*)data); + // request from connecivity service for NIF + //The if condition is added so that if the data call setup fails + //for DS State Machine, we want to retry in released state. + //for AGps State Machine, sendRsrcRequest() will always return success + if(!mStateMachine->sendRsrcRequest(GPS_REQUEST_AGPS_DATA_CONN)) { + // move the state to PENDING + nextState = mPendingState; + } + } + break; + + case RSRC_UNSUBSCRIBE: + { + // the list should really be empty, nothing to remove. + // but we might as well just tell the client it is + // unsubscribed. False tolerance, right? + Subscriber* subscriber = (Subscriber*) data; + Notification notification(subscriber, event, false); + subscriber->notifyRsrcStatus(notification); + } + // break; + case RSRC_GRANTED: + case RSRC_RELEASED: + case RSRC_DENIED: + default: + LOC_LOGW("%s: unrecognized event %d", whoami(), event); + // no state change. + break; + } + + LOC_LOGD("onRsrcEvent, old state %s, new state %s, event %d", + whoami(), nextState->whoami(), event); + return nextState; +} + +// AgpsPendingState +class AgpsPendingState : public AgpsState +{ + friend class AgpsStateMachine; + + inline AgpsPendingState(AgpsStateMachine* stateMachine) : + AgpsState(stateMachine) + { mPendingState = this; } + + inline ~AgpsPendingState() {} +public: + virtual AgpsState* onRsrcEvent(AgpsRsrcStatus event, void* data); + inline virtual char* whoami() {return (char*)"AgpsPendingState";} +}; + +AgpsState* AgpsPendingState::onRsrcEvent(AgpsRsrcStatus event, void* data) +{ + AgpsState* nextState = this;; + LOC_LOGD("AgpsPendingState::onRsrcEvent; event:%d\n", (int)event); + switch (event) + { + case RSRC_SUBSCRIBE: + { + // already requested for NIF resource, + // do nothing until we get RSRC_GRANTED indication + // but we need to add subscriber to the list + mStateMachine->addSubscriber((Subscriber*)data); + // no state change. + } + break; + + case RSRC_UNSUBSCRIBE: + { + Subscriber* subscriber = (Subscriber*) data; + if (subscriber->waitForCloseComplete()) { + subscriber->setInactive(); + } else { + // auto notify this subscriber of the unsubscribe + Notification notification(subscriber, event, true); + mStateMachine->notifySubscribers(notification); + } + + // now check if there is any subscribers left + if (!mStateMachine->hasSubscribers()) { + // no more subscribers, move to RELEASED state + nextState = mReleasedState; + + // tell connecivity service we can release NIF + mStateMachine->sendRsrcRequest(GPS_RELEASE_AGPS_DATA_CONN); + } else if (!mStateMachine->hasActiveSubscribers()) { + // only inactive subscribers, move to RELEASING state + nextState = mReleasingState; + + // tell connecivity service we can release NIF + mStateMachine->sendRsrcRequest(GPS_RELEASE_AGPS_DATA_CONN); + } + } + break; + + case RSRC_GRANTED: + { + nextState = mAcquiredState; + Notification notification(Notification::BROADCAST_ACTIVE, event, false); + // notify all subscribers NIF resource GRANTED + // by setting false, we keep subscribers on the linked list + mStateMachine->notifySubscribers(notification); + } + break; + + case RSRC_RELEASED: + // no state change. + // we are expecting either GRANTED or DENIED. Handling RELEASED + // may like break our state machine in race conditions. + break; + + case RSRC_DENIED: + { + nextState = mReleasedState; + Notification notification(Notification::BROADCAST_ALL, event, true); + // notify all subscribers NIF resource RELEASED or DENIED + // by setting true, we remove subscribers from the linked list + mStateMachine->notifySubscribers(notification); + } + break; + + default: + LOC_LOGE("%s: unrecognized event %d", whoami(), event); + // no state change. + } + + LOC_LOGD("onRsrcEvent, old state %s, new state %s, event %d", + whoami(), nextState->whoami(), event); + return nextState; +} + + +class AgpsAcquiredState : public AgpsState +{ + friend class AgpsStateMachine; + + inline AgpsAcquiredState(AgpsStateMachine* stateMachine) : + AgpsState(stateMachine) + { mAcquiredState = this; } + + inline ~AgpsAcquiredState() {} +public: + virtual AgpsState* onRsrcEvent(AgpsRsrcStatus event, void* data); + inline virtual char* whoami() { return (char*)"AgpsAcquiredState"; } +}; + + +AgpsState* AgpsAcquiredState::onRsrcEvent(AgpsRsrcStatus event, void* data) +{ + AgpsState* nextState = this; + LOC_LOGD("AgpsAcquiredState::onRsrcEvent; event:%d\n", (int)event); + switch (event) + { + case RSRC_SUBSCRIBE: + { + // we already have the NIF resource, simply notify subscriber + Subscriber* subscriber = (Subscriber*) data; + // we have rsrc in hand, so grant it right away + Notification notification(subscriber, RSRC_GRANTED, false); + subscriber->notifyRsrcStatus(notification); + // add subscriber to the list + mStateMachine->addSubscriber(subscriber); + // no state change. + } + break; + + case RSRC_UNSUBSCRIBE: + { + Subscriber* subscriber = (Subscriber*) data; + if (subscriber->waitForCloseComplete()) { + subscriber->setInactive(); + } else { + // auto notify this subscriber of the unsubscribe + Notification notification(subscriber, event, true); + mStateMachine->notifySubscribers(notification); + } + + // now check if there is any subscribers left + if (!mStateMachine->hasSubscribers()) { + // no more subscribers, move to RELEASED state + nextState = mReleasedState; + + // tell connecivity service we can release NIF + mStateMachine->sendRsrcRequest(GPS_RELEASE_AGPS_DATA_CONN); + } else if (!mStateMachine->hasActiveSubscribers()) { + // only inactive subscribers, move to RELEASING state + nextState = mReleasingState; + + // tell connecivity service we can release NIF + mStateMachine->sendRsrcRequest(GPS_RELEASE_AGPS_DATA_CONN); + } + } + break; + + case RSRC_GRANTED: + LOC_LOGW("%s: %d, RSRC_GRANTED already received", whoami(), event); + // no state change. + break; + + case RSRC_RELEASED: + { + LOC_LOGW("%s: %d, a force rsrc release", whoami(), event); + nextState = mReleasedState; + Notification notification(Notification::BROADCAST_ALL, event, true); + // by setting true, we remove subscribers from the linked list + mStateMachine->notifySubscribers(notification); + } + break; + + case RSRC_DENIED: + // no state change. + // we are expecting RELEASED. Handling DENIED + // may like break our state machine in race conditions. + break; + + default: + LOC_LOGE("%s: unrecognized event %d", whoami(), event); + // no state change. + } + + LOC_LOGD("onRsrcEvent, old state %s, new state %s, event %d", + whoami(), nextState->whoami(), event); + return nextState; +} + +// AgpsPendingState +class AgpsReleasingState : public AgpsState +{ + friend class AgpsStateMachine; + + inline AgpsReleasingState(AgpsStateMachine* stateMachine) : + AgpsState(stateMachine) + { mReleasingState = this; } + + inline ~AgpsReleasingState() {} +public: + virtual AgpsState* onRsrcEvent(AgpsRsrcStatus event, void* data); + inline virtual char* whoami() {return (char*)"AgpsReleasingState";} +}; + +AgpsState* AgpsReleasingState::onRsrcEvent(AgpsRsrcStatus event, void* data) +{ + AgpsState* nextState = this;; + LOC_LOGD("AgpsReleasingState::onRsrcEvent; event:%d\n", (int)event); + + switch (event) + { + case RSRC_SUBSCRIBE: + { + // already requested for NIF resource, + // do nothing until we get RSRC_GRANTED indication + // but we need to add subscriber to the list + mStateMachine->addSubscriber((Subscriber*)data); + // no state change. + } + break; + + case RSRC_UNSUBSCRIBE: + { + Subscriber* subscriber = (Subscriber*) data; + if (subscriber->waitForCloseComplete()) { + subscriber->setInactive(); + } else { + // auto notify this subscriber of the unsubscribe + Notification notification(subscriber, event, true); + mStateMachine->notifySubscribers(notification); + } + + // now check if there is any subscribers left + if (!mStateMachine->hasSubscribers()) { + // no more subscribers, move to RELEASED state + nextState = mReleasedState; + } + } + break; + + case RSRC_DENIED: + // A race condition subscriber unsubscribes before AFW denies resource. + case RSRC_RELEASED: + { + nextState = mAcquiredState; + Notification notification(Notification::BROADCAST_INACTIVE, event, true); + // notify all subscribers that are active NIF resource RELEASE + // by setting false, we keep subscribers on the linked list + mStateMachine->notifySubscribers(notification); + + if (mStateMachine->hasActiveSubscribers()) { + nextState = mPendingState; + // request from connecivity service for NIF + mStateMachine->sendRsrcRequest(GPS_REQUEST_AGPS_DATA_CONN); + } else { + nextState = mReleasedState; + } + } + break; + + case RSRC_GRANTED: + default: + LOC_LOGE("%s: unrecognized event %d", whoami(), event); + // no state change. + } + + LOC_LOGD("onRsrcEvent, old state %s, new state %s, event %d", + whoami(), nextState->whoami(), event); + return nextState; +} +//====================================================================== +//Servicer +//====================================================================== +Servicer* Servicer :: getServicer(servicerType type, void *cb_func) +{ + LOC_LOGD(" Enter getServicer type:%d\n", (int)type); + switch(type) { + case servicerTypeNoCbParam: + return (new Servicer(cb_func)); + case servicerTypeExt: + return (new ExtServicer(cb_func)); + case servicerTypeAgps: + return (new AGpsServicer(cb_func)); + default: + return NULL; + } +} + +int Servicer :: requestRsrc(void *cb_data) +{ + callback(); + return 0; +} + +int ExtServicer :: requestRsrc(void *cb_data) +{ + int ret=-1; + LOC_LOGD("Enter ExtServicer :: requestRsrc\n"); + ret = callbackExt(cb_data); + LOC_LOGD("Exit ExtServicer :: requestRsrc\n"); + return(ret); +} + +int AGpsServicer :: requestRsrc(void *cb_data) +{ + callbackAGps((AGpsStatus *)cb_data); + return 0; +} + +//====================================================================== +// AgpsStateMachine +//====================================================================== + +AgpsStateMachine::AgpsStateMachine(servicerType servType, + void *cb_func, + AGpsExtType type, + bool enforceSingleSubscriber) : + mStatePtr(new AgpsReleasedState(this)),mType(type), + mAPN(NULL), + mAPNLen(0), + mBearer(AGPS_APN_BEARER_INVALID), + mEnforceSingleSubscriber(enforceSingleSubscriber), + mServicer(Servicer :: getServicer(servType, (void *)cb_func)) +{ + linked_list_init(&mSubscribers); + + // setting up mReleasedState + mStatePtr->mPendingState = new AgpsPendingState(this); + mStatePtr->mAcquiredState = new AgpsAcquiredState(this); + mStatePtr->mReleasingState = new AgpsReleasingState(this); + + // setting up mAcquiredState + mStatePtr->mAcquiredState->mReleasedState = mStatePtr; + mStatePtr->mAcquiredState->mPendingState = mStatePtr->mPendingState; + mStatePtr->mAcquiredState->mReleasingState = mStatePtr->mReleasingState; + + // setting up mPendingState + mStatePtr->mPendingState->mAcquiredState = mStatePtr->mAcquiredState; + mStatePtr->mPendingState->mReleasedState = mStatePtr; + mStatePtr->mPendingState->mReleasingState = mStatePtr->mReleasingState; + + // setting up mReleasingState + mStatePtr->mReleasingState->mReleasedState = mStatePtr; + mStatePtr->mReleasingState->mPendingState = mStatePtr->mPendingState; + mStatePtr->mReleasingState->mAcquiredState = mStatePtr->mAcquiredState; +} + +AgpsStateMachine::~AgpsStateMachine() +{ + dropAllSubscribers(); + + // free the 3 states. We must read out all 3 pointers first. + // Otherwise we run the risk of getting pointers from already + // freed memory. + AgpsState* acquiredState = mStatePtr->mAcquiredState; + AgpsState* releasedState = mStatePtr->mReleasedState; + AgpsState* pendindState = mStatePtr->mPendingState; + AgpsState* releasingState = mStatePtr->mReleasingState; + + delete acquiredState; + delete releasedState; + delete pendindState; + delete releasingState; + delete mServicer; + linked_list_destroy(&mSubscribers); + + if (NULL != mAPN) { + delete[] mAPN; + mAPN = NULL; + } +} + +void AgpsStateMachine::setAPN(const char* apn, unsigned int len) +{ + if (NULL != mAPN) { + delete mAPN; + } + + if (NULL != apn) { + mAPN = new char[len+1]; + memcpy(mAPN, apn, len); + mAPN[len] = NULL; + + mAPNLen = len; + } else { + mAPN = NULL; + mAPNLen = 0; + } +} + +void AgpsStateMachine::onRsrcEvent(AgpsRsrcStatus event) +{ + switch (event) + { + case RSRC_GRANTED: + case RSRC_RELEASED: + case RSRC_DENIED: + mStatePtr = mStatePtr->onRsrcEvent(event, NULL); + break; + default: + LOC_LOGW("AgpsStateMachine: unrecognized event %d", event); + break; + } +} + +void AgpsStateMachine::notifySubscribers(Notification& notification) const +{ + if (notification.postNotifyDelete) { + // just any non NULL value to get started + Subscriber* s = (Subscriber*)~0; + while (NULL != s) { + s = NULL; + // if the last param sets to true, _search will delete + // the node from the list for us. But the problem is + // once that is done, _search returns, leaving the + // rest of the list unprocessed. So we need a loop. + linked_list_search(mSubscribers, (void**)&s, notifySubscriber, + (void*)¬ification, true); + delete s; + } + } else { + // no loop needed if it the last param sets to false, which + // mean nothing gets deleted from the list. + linked_list_search(mSubscribers, NULL, notifySubscriber, + (void*)¬ification, false); + } +} + +void AgpsStateMachine::addSubscriber(Subscriber* subscriber) const +{ + Subscriber* s = NULL; + Notification notification((const Subscriber*)subscriber); + linked_list_search(mSubscribers, (void**)&s, + hasSubscriber, (void*)¬ification, false); + + if (NULL == s) { + linked_list_add(mSubscribers, subscriber->clone(), deleteObj); + } +} + +int AgpsStateMachine::sendRsrcRequest(AGpsStatusValue action) const +{ + Subscriber* s = NULL; + Notification notification(Notification::BROADCAST_ACTIVE); + linked_list_search(mSubscribers, (void**)&s, hasSubscriber, + (void*)¬ification, false); + + if ((NULL == s) == (GPS_RELEASE_AGPS_DATA_CONN == action)) { + AGpsExtStatus nifRequest; + nifRequest.size = sizeof(nifRequest); + nifRequest.type = mType; + nifRequest.status = action; + + if (s == NULL) { + nifRequest.ipv4_addr = INADDR_NONE; + memset(&nifRequest.addr, 0, sizeof(nifRequest.addr)); + nifRequest.ssid[0] = '\0'; + nifRequest.password[0] = '\0'; + } else { + s->setIPAddresses(nifRequest.addr); + s->setWifiInfo(nifRequest.ssid, nifRequest.password); + } + + CALLBACK_LOG_CALLFLOW("agps_cb", %s, loc_get_agps_status_name(action)); + mServicer->requestRsrc((void *)&nifRequest); + } + return 0; +} + +void AgpsStateMachine::subscribeRsrc(Subscriber *subscriber) +{ + if (mEnforceSingleSubscriber && hasSubscribers()) { + Notification notification(Notification::BROADCAST_ALL, RSRC_DENIED, true); + notifySubscriber(¬ification, subscriber); + } else { + mStatePtr = mStatePtr->onRsrcEvent(RSRC_SUBSCRIBE, (void*)subscriber); + } +} + +bool AgpsStateMachine::unsubscribeRsrc(Subscriber *subscriber) +{ + Subscriber* s = NULL; + Notification notification((const Subscriber*)subscriber); + linked_list_search(mSubscribers, (void**)&s, + hasSubscriber, (void*)¬ification, false); + + if (NULL != s) { + mStatePtr = mStatePtr->onRsrcEvent(RSRC_UNSUBSCRIBE, (void*)s); + return true; + } + return false; +} + +bool AgpsStateMachine::hasActiveSubscribers() const +{ + Subscriber* s = NULL; + Notification notification(Notification::BROADCAST_ACTIVE); + linked_list_search(mSubscribers, (void**)&s, + hasSubscriber, (void*)¬ification, false); + return NULL != s; +} + +//====================================================================== +// DSStateMachine +//====================================================================== +void delay_callback(void *callbackData, int result) +{ + if(callbackData) { + DSStateMachine *DSSMInstance = (DSStateMachine *)callbackData; + DSSMInstance->retryCallback(); + } + else { + LOC_LOGE(" NULL argument received. Failing.\n"); + goto err; + } +err: + return; +} + +DSStateMachine :: DSStateMachine(servicerType type, void *cb_func, + LocEngAdapter* adapterHandle): + AgpsStateMachine(type, cb_func, AGPS_TYPE_INVALID,false), + mLocAdapter(adapterHandle) +{ + LOC_LOGD("%s:%d]: New DSStateMachine\n", __func__, __LINE__); + mRetries = 0; +} + +void DSStateMachine :: retryCallback(void) +{ + DSSubscriber *subscriber = NULL; + Notification notification(Notification::BROADCAST_ACTIVE); + linked_list_search(mSubscribers, (void**)&subscriber, hasSubscriber, + (void*)¬ification, false); + if(subscriber) + mLocAdapter->requestSuplES(subscriber->ID); + else + LOC_LOGE("DSStateMachine :: retryCallback: No subscriber found." \ + "Cannot retry data call\n"); + return; +} + +int DSStateMachine :: sendRsrcRequest(AGpsStatusValue action) const +{ + DSSubscriber* s = NULL; + dsCbData cbData; + int ret=-1; + int connHandle=-1; + LOC_LOGD("Enter DSStateMachine :: sendRsrcRequest\n"); + Notification notification(Notification::BROADCAST_ACTIVE); + linked_list_search(mSubscribers, (void**)&s, hasSubscriber, + (void*)¬ification, false); + if(s) { + connHandle = s->ID; + LOC_LOGD("DSStateMachine :: sendRsrcRequest - subscriber found\n"); + } + else + LOC_LOGD("DSStateMachine :: sendRsrcRequest - No subscriber found\n"); + + cbData.action = action; + cbData.mAdapter = mLocAdapter; + ret = mServicer->requestRsrc((void *)&cbData); + //Only the request to start data call returns a success/failure + //The request to stop data call will always succeed + //Hence, the below block will only be executed when the + //request to start the data call fails + switch(ret) { + case LOC_API_ADAPTER_ERR_ENGINE_BUSY: + LOC_LOGD("DSStateMachine :: sendRsrcRequest - Failure returned: %d\n",ret); + ((DSStateMachine *)this)->incRetries(); + if(mRetries > MAX_START_DATA_CALL_RETRIES) { + LOC_LOGE(" Failed to start Data call. Fallback to normal ATL SUPL\n"); + informStatus(RSRC_DENIED, connHandle); + } + else { + if(loc_timer_start(DATA_CALL_RETRY_DELAY_MSEC, delay_callback, (void *)this)) { + LOC_LOGE("Error: Could not start delay thread\n"); + ret = -1; + goto err; + } + } + break; + case LOC_API_ADAPTER_ERR_UNSUPPORTED: + LOC_LOGE("No profile found for emergency call. Fallback to normal SUPL ATL\n"); + informStatus(RSRC_DENIED, connHandle); + break; + case LOC_API_ADAPTER_ERR_SUCCESS: + LOC_LOGD("%s:%d]: Request to start data call sent\n", __func__, __LINE__); + break; + case -1: + //One of the ways this case can be encountered is if the callback function + //receives a null argument, it just exits with -1 error + LOC_LOGE("Error: Something went wrong somewhere. Falling back to normal SUPL ATL\n"); + informStatus(RSRC_DENIED, connHandle); + break; + default: + LOC_LOGE("%s:%d]: Unrecognized return value\n", __func__, __LINE__); + } +err: + LOC_LOGD("EXIT DSStateMachine :: sendRsrcRequest; ret = %d\n", ret); + return ret; +} + +void DSStateMachine :: onRsrcEvent(AgpsRsrcStatus event) +{ + void* currState = (void *)mStatePtr; + LOC_LOGD("Enter DSStateMachine :: onRsrcEvent. event = %d\n", (int)event); + switch (event) + { + case RSRC_GRANTED: + LOC_LOGD("DSStateMachine :: onRsrcEvent RSRC_GRANTED\n"); + mStatePtr = mStatePtr->onRsrcEvent(event, NULL); + break; + case RSRC_RELEASED: + LOC_LOGD("DSStateMachine :: onRsrcEvent RSRC_RELEASED\n"); + mStatePtr = mStatePtr->onRsrcEvent(event, NULL); + //To handle the case where we get a RSRC_RELEASED in + //pending state, we translate that to a RSRC_DENIED state + //since the callback from DSI is either RSRC_GRANTED or RSRC_RELEASED + //for when the call is connected or disconnected respectively. + if((void *)mStatePtr != currState) + break; + else { + event = RSRC_DENIED; + LOC_LOGE(" Switching event to RSRC_DENIED\n"); + } + case RSRC_DENIED: + mStatePtr = mStatePtr->onRsrcEvent(event, NULL); + break; + default: + LOC_LOGW("AgpsStateMachine: unrecognized event %d", event); + break; + } + LOC_LOGD("Exit DSStateMachine :: onRsrcEvent. event = %d\n", (int)event); +} + +void DSStateMachine :: informStatus(AgpsRsrcStatus status, int ID) const +{ + LOC_LOGD("DSStateMachine :: informStatus. Status=%d\n",(int)status); + switch(status) { + case RSRC_UNSUBSCRIBE: + mLocAdapter->atlCloseStatus(ID, 1); + break; + case RSRC_RELEASED: + mLocAdapter->closeDataCall(); + break; + case RSRC_DENIED: + ((DSStateMachine *)this)->mRetries = 0; + mLocAdapter->requestATL(ID, AGPS_TYPE_SUPL); + break; + case RSRC_GRANTED: + mLocAdapter->atlOpenStatus(ID, 1, + NULL, + AGPS_APN_BEARER_INVALID, + AGPS_TYPE_INVALID); + break; + default: + LOC_LOGW("DSStateMachine :: informStatus - unknown status"); + } + return; +} diff --git a/gps/loc_api/libloc_api_50001/loc_eng_agps.h b/gps/loc_api/libloc_api_50001/loc_eng_agps.h new file mode 100644 index 000000000..2d689ceed --- /dev/null +++ b/gps/loc_api/libloc_api_50001/loc_eng_agps.h @@ -0,0 +1,431 @@ +/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef __LOC_ENG_AGPS_H__ +#define __LOC_ENG_AGPS_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// forward declaration +class AgpsStateMachine; +class Subscriber; + +// NIF resource events +typedef enum { + RSRC_SUBSCRIBE, + RSRC_UNSUBSCRIBE, + RSRC_GRANTED, + RSRC_RELEASED, + RSRC_DENIED, + RSRC_STATUS_MAX +} AgpsRsrcStatus; + +typedef enum { + servicerTypeNoCbParam, + servicerTypeAgps, + servicerTypeExt +}servicerType; + +//DS Callback struct +typedef struct { + LocEngAdapter *mAdapter; + AGpsStatusValue action; +}dsCbData; + +// information bundle for subscribers +struct Notification { + // goes to every subscriber + static const int BROADCAST_ALL; + // goes to every ACTIVE subscriber + static const int BROADCAST_ACTIVE; + // goes to every INACTIVE subscriber + static const int BROADCAST_INACTIVE; + + // go to a specific subscriber + const Subscriber* rcver; + // broadcast + const int groupID; + // the new resource status event + const AgpsRsrcStatus rsrcStatus; + // should the subscriber be deleted after the notification + const bool postNotifyDelete; + + // convenient constructor + inline Notification(const int broadcast, + const AgpsRsrcStatus status, + const bool deleteAfterwards) : + rcver(NULL), groupID(broadcast), rsrcStatus(status), + postNotifyDelete(deleteAfterwards) {} + + // convenient constructor + inline Notification(const Subscriber* subscriber, + const AgpsRsrcStatus status, + const bool deleteAfterwards) : + rcver(subscriber), groupID(-1), rsrcStatus(status), + postNotifyDelete(deleteAfterwards) {} + + // convenient constructor + inline Notification(const int broadcast) : + rcver(NULL), groupID(broadcast), rsrcStatus(RSRC_STATUS_MAX), + postNotifyDelete(false) {} + + // convenient constructor + inline Notification(const Subscriber* subscriber) : + rcver(subscriber), groupID(-1), rsrcStatus(RSRC_STATUS_MAX), + postNotifyDelete(false) {} +}; + +class AgpsState { + // allows AgpsStateMachine to access private data + // no class members are public. We don't want + // anyone but state machine to use state. + friend class AgpsStateMachine; + friend class DSStateMachine; + // state transitions are done here. + // Each state implements its own transitions (of course). + inline virtual AgpsState* onRsrcEvent(AgpsRsrcStatus event, void* data) = 0; + +protected: + // handle back to state machine + const AgpsStateMachine* mStateMachine; + // each state has pointers to all 3 states + // one of which is to itself. + AgpsState* mReleasedState; + AgpsState* mAcquiredState; + AgpsState* mPendingState; + AgpsState* mReleasingState; + + inline AgpsState(const AgpsStateMachine *stateMachine) : + mStateMachine(stateMachine), + mReleasedState(NULL), + mAcquiredState(NULL), + mPendingState(NULL), + mReleasingState(NULL) {} + virtual ~AgpsState() {} + +public: + // for logging purpose + inline virtual char* whoami() = 0; +}; + +class Servicer { + void (*callback)(void); +public: + static Servicer* getServicer(servicerType type, void *cb_func); + virtual int requestRsrc(void *cb_data); + Servicer() {} + Servicer(void *cb_func) + { callback = (void(*)(void))(cb_func); } + virtual ~Servicer(){} + inline virtual char *whoami() {return (char*)"Servicer";} +}; + +class ExtServicer : public Servicer { + int (*callbackExt)(void *cb_data); +public: + int requestRsrc(void *cb_data); + ExtServicer() {} + ExtServicer(void *cb_func) + { callbackExt = (int(*)(void *))(cb_func); } + virtual ~ExtServicer(){} + inline virtual char *whoami() {return (char*)"ExtServicer";} +}; + +class AGpsServicer : public Servicer { + void (*callbackAGps)(AGpsStatus* status); +public: + int requestRsrc(void *cb_data); + AGpsServicer() {} + AGpsServicer(void *cb_func) + { callbackAGps = (void(*)(AGpsStatus *))(cb_func); } + virtual ~AGpsServicer(){} + inline virtual char *whoami() {return (char*)"AGpsServicer";} +}; + +class AgpsStateMachine { +protected: + // a linked list of subscribers. + void* mSubscribers; + //handle to whoever provides the service + Servicer *mServicer; + // allows AgpsState to access private data + // each state is really internal data to the + // state machine, so it should be able to + // access anything within the state machine. + friend class AgpsState; + // pointer to the current state. + AgpsState* mStatePtr; +private: + // NIF type: AGNSS or INTERNET. + const AGpsExtType mType; + // apn to the NIF. Each state machine tracks + // resource state of a particular NIF. For each + // NIF, there is also an active APN. + char* mAPN; + // for convenience, we don't do strlen each time. + unsigned int mAPNLen; + // bear + AGpsBearerType mBearer; + // ipv4 address for routing + bool mEnforceSingleSubscriber; + +public: + AgpsStateMachine(servicerType servType, void *cb_func, + AGpsExtType type, bool enforceSingleSubscriber); + virtual ~AgpsStateMachine(); + + // self explanatory methods below + void setAPN(const char* apn, unsigned int len); + inline const char* getAPN() const { return (const char*)mAPN; } + inline void setBearer(AGpsBearerType bearer) { mBearer = bearer; } + inline AGpsBearerType getBearer() const { return mBearer; } + inline AGpsExtType getType() const { return (AGpsExtType)mType; } + + // someone, a ATL client or BIT, is asking for NIF + void subscribeRsrc(Subscriber *subscriber); + + // someone, a ATL client or BIT, is done with NIF + bool unsubscribeRsrc(Subscriber *subscriber); + + // add a subscriber in the linked list, if not already there. + void addSubscriber(Subscriber* subscriber) const; + + virtual void onRsrcEvent(AgpsRsrcStatus event); + + // put the data together and send the FW + virtual int sendRsrcRequest(AGpsStatusValue action) const; + + //if list is empty, linked_list_empty returns 1 + //else if list is not empty, returns 0 + //so hasSubscribers() returns 1 if list is not empty + //and returns 0 if list is empty + inline bool hasSubscribers() const + { return !linked_list_empty(mSubscribers); } + + bool hasActiveSubscribers() const; + + inline void dropAllSubscribers() const + { linked_list_flush(mSubscribers); } + + // private. Only a state gets to call this. + void notifySubscribers(Notification& notification) const; + +}; + +class DSStateMachine : public AgpsStateMachine { + static const unsigned char MAX_START_DATA_CALL_RETRIES; + static const unsigned int DATA_CALL_RETRY_DELAY_MSEC; + LocEngAdapter* mLocAdapter; + unsigned char mRetries; +public: + DSStateMachine(servicerType type, + void *cb_func, + LocEngAdapter* adapterHandle); + int sendRsrcRequest(AGpsStatusValue action) const; + void onRsrcEvent(AgpsRsrcStatus event); + void retryCallback(); + void informStatus(AgpsRsrcStatus status, int ID) const; + inline void incRetries() {mRetries++;} + inline virtual char *whoami() {return (char*)"DSStateMachine";} +}; + +// each subscriber is a AGPS client. In the case of ATL, there could be +// multiple clients from modem. In the case of BIT, there is only one +// cilent from BIT daemon. +struct Subscriber { + const uint32_t ID; + const AgpsStateMachine* mStateMachine; + inline Subscriber(const int id, + const AgpsStateMachine* stateMachine) : + ID(id), mStateMachine(stateMachine) {} + inline virtual ~Subscriber() {} + + virtual void setIPAddresses(uint32_t &v4, char* v6) = 0; + virtual void setIPAddresses(struct sockaddr_storage& addr) = 0; + inline virtual void setWifiInfo(char* ssid, char* password) + { ssid[0] = 0; password[0] = 0; } + + inline virtual bool equals(const Subscriber *s) const + { return ID == s->ID; } + + // notifies a subscriber a new NIF resource status, usually + // either GRANTE, DENIED, or RELEASED + virtual bool notifyRsrcStatus(Notification ¬ification) = 0; + + virtual bool waitForCloseComplete() { return false; } + virtual void setInactive() {} + virtual bool isInactive() { return false; } + + virtual Subscriber* clone() = 0; + // checks if this notification is for me, i.e. + // either has my id, or has a broadcast id. + bool forMe(Notification ¬ification); +}; + +// BITSubscriber, created with requests from BIT daemon +struct BITSubscriber : public Subscriber { + char mIPv6Addr[16]; + + inline BITSubscriber(const AgpsStateMachine* stateMachine, + unsigned int ipv4, char* ipv6) : + Subscriber(ipv4, stateMachine) + { + if (NULL == ipv6) { + mIPv6Addr[0] = 0; + } else { + memcpy(mIPv6Addr, ipv6, sizeof(mIPv6Addr)); + } + } + + virtual bool notifyRsrcStatus(Notification ¬ification); + + inline virtual void setIPAddresses(uint32_t &v4, char* v6) + { v4 = ID; memcpy(v6, mIPv6Addr, sizeof(mIPv6Addr)); } + + inline virtual void setIPAddresses(struct sockaddr_storage& addr) + { addr.ss_family = AF_INET6;/*todo: convert mIPv6Addr into addr */ } + + virtual Subscriber* clone() + { + return new BITSubscriber(mStateMachine, ID, mIPv6Addr); + } + + virtual bool equals(const Subscriber *s) const; + inline virtual ~BITSubscriber(){} +}; + +// ATLSubscriber, created with requests from ATL +struct ATLSubscriber : public Subscriber { + const LocEngAdapter* mLocAdapter; + const bool mBackwardCompatibleMode; + inline ATLSubscriber(const int id, + const AgpsStateMachine* stateMachine, + const LocEngAdapter* adapter, + const bool compatibleMode) : + Subscriber(id, stateMachine), mLocAdapter(adapter), + mBackwardCompatibleMode(compatibleMode){} + virtual bool notifyRsrcStatus(Notification ¬ification); + + inline virtual void setIPAddresses(uint32_t &v4, char* v6) + { v4 = INADDR_NONE; v6[0] = 0; } + + inline virtual void setIPAddresses(struct sockaddr_storage& addr) + { addr.ss_family = AF_INET6; } + + inline virtual Subscriber* clone() + { + return new ATLSubscriber(ID, mStateMachine, mLocAdapter, + mBackwardCompatibleMode); + } + inline virtual ~ATLSubscriber(){} +}; + +// WIFISubscriber, created with requests from MSAPM or QuIPC +struct WIFISubscriber : public Subscriber { + char * mSSID; + char * mPassword; + loc_if_req_sender_id_e_type senderId; + bool mIsInactive; + inline WIFISubscriber(const AgpsStateMachine* stateMachine, + char * ssid, char * password, loc_if_req_sender_id_e_type sender_id) : + Subscriber(sender_id, stateMachine), + mSSID(NULL == ssid ? NULL : new char[SSID_BUF_SIZE]), + mPassword(NULL == password ? NULL : new char[SSID_BUF_SIZE]), + senderId(sender_id) + { + if (NULL != mSSID) + strlcpy(mSSID, ssid, SSID_BUF_SIZE); + if (NULL != mPassword) + strlcpy(mPassword, password, SSID_BUF_SIZE); + mIsInactive = false; + } + + virtual bool notifyRsrcStatus(Notification ¬ification); + + inline virtual void setIPAddresses(uint32_t &v4, char* v6) {} + + inline virtual void setIPAddresses(struct sockaddr_storage& addr) + { addr.ss_family = AF_INET6; } + + inline virtual void setWifiInfo(char* ssid, char* password) + { + if (NULL != mSSID) + strlcpy(ssid, mSSID, SSID_BUF_SIZE); + else + ssid[0] = '\0'; + if (NULL != mPassword) + strlcpy(password, mPassword, SSID_BUF_SIZE); + else + password[0] = '\0'; + } + + inline virtual bool waitForCloseComplete() { return true; } + + inline virtual void setInactive() { mIsInactive = true; } + inline virtual bool isInactive() { return mIsInactive; } + + virtual Subscriber* clone() + { + return new WIFISubscriber(mStateMachine, mSSID, mPassword, senderId); + } + inline virtual ~WIFISubscriber(){} +}; + +struct DSSubscriber : public Subscriber { + bool mIsInactive; + inline DSSubscriber(const AgpsStateMachine *stateMachine, + const int id) : + Subscriber(id, stateMachine) + { + mIsInactive = false; + } + inline virtual void setIPAddresses(uint32_t &v4, char* v6) {} + inline virtual void setIPAddresses(struct sockaddr_storage& addr) + { addr.ss_family = AF_INET6; } + virtual Subscriber* clone() + {return new DSSubscriber(mStateMachine, ID);} + virtual bool notifyRsrcStatus(Notification ¬ification); + inline virtual bool waitForCloseComplete() { return true; } + virtual void setInactive(); + inline virtual bool isInactive() + { return mIsInactive; } + inline virtual ~DSSubscriber(){} + inline virtual char *whoami() {return (char*)"DSSubscriber";} +}; + +#endif //__LOC_ENG_AGPS_H__ diff --git a/gps/loc_api/libloc_api_50001/loc_eng_dmn_conn.cpp b/gps/loc_api/libloc_api_50001/loc_eng_dmn_conn.cpp new file mode 100644 index 000000000..c257dff44 --- /dev/null +++ b/gps/loc_api/libloc_api_50001/loc_eng_dmn_conn.cpp @@ -0,0 +1,270 @@ +/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "log_util.h" +#include "platform_lib_includes.h" +#include "loc_eng_dmn_conn_glue_msg.h" +#include "loc_eng_dmn_conn_handler.h" +#include "loc_eng_dmn_conn.h" +#include "loc_eng_msg.h" + +static int loc_api_server_msgqid; +static int loc_api_resp_msgqid; +static int quipc_msgqid; +static int msapm_msgqid; +static int msapu_msgqid; + +static const char * global_loc_api_q_path = GPSONE_LOC_API_Q_PATH; +static const char * global_loc_api_resp_q_path = GPSONE_LOC_API_RESP_Q_PATH; +static const char * global_quipc_ctrl_q_path = QUIPC_CTRL_Q_PATH; +static const char * global_msapm_ctrl_q_path = MSAPM_CTRL_Q_PATH; +static const char * global_msapu_ctrl_q_path = MSAPU_CTRL_Q_PATH; + +static int loc_api_server_proc_init(void *context) +{ + loc_api_server_msgqid = loc_eng_dmn_conn_glue_msgget(global_loc_api_q_path, O_RDWR); + //change mode/group for the global_loc_api_q_path pipe + int result = chmod (global_loc_api_q_path, 0660); + if (result != 0) + { + LOC_LOGE("failed to change mode for %s, error = %s\n", global_loc_api_q_path, strerror(errno)); + } + + struct group * gps_group = getgrnam("gps"); + if (gps_group != NULL) + { + result = chown (global_loc_api_q_path, -1, gps_group->gr_gid); + if (result != 0) + { + LOC_LOGE("chown for pipe failed, pipe %s, gid = %d, result = %d, error = %s\n", + global_loc_api_q_path, gps_group->gr_gid, result, strerror(errno)); + } + } + else + { + LOC_LOGE("getgrnam for gps failed, error code = %d\n", errno); + } + + loc_api_resp_msgqid = loc_eng_dmn_conn_glue_msgget(global_loc_api_resp_q_path, O_RDWR); + + //change mode/group for the global_loc_api_resp_q_path pipe + result = chmod (global_loc_api_resp_q_path, 0660); + if (result != 0) + { + LOC_LOGE("failed to change mode for %s, error = %s\n", global_loc_api_resp_q_path, strerror(errno)); + } + + if (gps_group != NULL) + { + result = chown (global_loc_api_resp_q_path, -1, gps_group->gr_gid); + if (result != 0) + { + LOC_LOGE("chown for pipe failed, pipe %s, gid = %d, result = %d, error = %s\n", + global_loc_api_resp_q_path, + gps_group->gr_gid, result, strerror(errno)); + } + } + + quipc_msgqid = loc_eng_dmn_conn_glue_msgget(global_quipc_ctrl_q_path, O_RDWR); + msapm_msgqid = loc_eng_dmn_conn_glue_msgget(global_msapm_ctrl_q_path , O_RDWR); + msapu_msgqid = loc_eng_dmn_conn_glue_msgget(global_msapu_ctrl_q_path , O_RDWR); + + LOC_LOGD("%s:%d] loc_api_server_msgqid = %d\n", __func__, __LINE__, loc_api_server_msgqid); + return 0; +} + +static int loc_api_server_proc_pre(void *context) +{ + return 0; +} + +static int loc_api_server_proc(void *context) +{ + int length, sz; + int result = 0; + static int cnt = 0; + struct ctrl_msgbuf * p_cmsgbuf; + struct ctrl_msgbuf cmsg_resp; + + sz = sizeof(struct ctrl_msgbuf) + 256; + p_cmsgbuf = (struct ctrl_msgbuf *) malloc(sz); + + if (!p_cmsgbuf) { + LOC_LOGE("%s:%d] Out of memory\n", __func__, __LINE__); + return -1; + } + + cnt ++; + LOC_LOGD("%s:%d] %d listening on %s...\n", __func__, __LINE__, cnt, (char *) context); + length = loc_eng_dmn_conn_glue_msgrcv(loc_api_server_msgqid, p_cmsgbuf, sz); + if (length <= 0) { + free(p_cmsgbuf); + LOC_LOGE("%s:%d] fail receiving msg from gpsone_daemon, retry later\n", __func__, __LINE__); + usleep(1000); + return -1; + } + + LOC_LOGD("%s:%d] received ctrl_type = %d\n", __func__, __LINE__, p_cmsgbuf->ctrl_type); + switch(p_cmsgbuf->ctrl_type) { + case GPSONE_LOC_API_IF_REQUEST: + result = loc_eng_dmn_conn_loc_api_server_if_request_handler(p_cmsgbuf, length); + break; + + case GPSONE_LOC_API_IF_RELEASE: + result = loc_eng_dmn_conn_loc_api_server_if_release_handler(p_cmsgbuf, length); + break; + + case GPSONE_UNBLOCK: + LOC_LOGD("%s:%d] GPSONE_UNBLOCK\n", __func__, __LINE__); + break; + + default: + LOC_LOGE("%s:%d] unsupported ctrl_type = %d\n", + __func__, __LINE__, p_cmsgbuf->ctrl_type); + break; + } + + free(p_cmsgbuf); + return 0; +} + +static int loc_api_server_proc_post(void *context) +{ + LOC_LOGD("%s:%d]\n", __func__, __LINE__); + loc_eng_dmn_conn_glue_msgremove( global_loc_api_q_path, loc_api_server_msgqid); + loc_eng_dmn_conn_glue_msgremove( global_loc_api_resp_q_path, loc_api_resp_msgqid); + loc_eng_dmn_conn_glue_msgremove( global_quipc_ctrl_q_path, quipc_msgqid); + loc_eng_dmn_conn_glue_msgremove( global_msapm_ctrl_q_path, msapm_msgqid); + loc_eng_dmn_conn_glue_msgremove( global_msapu_ctrl_q_path, msapu_msgqid); + return 0; +} + +static int loc_eng_dmn_conn_unblock_proc(void) +{ + struct ctrl_msgbuf cmsgbuf; + cmsgbuf.ctrl_type = GPSONE_UNBLOCK; + LOC_LOGD("%s:%d]\n", __func__, __LINE__); + loc_eng_dmn_conn_glue_msgsnd(loc_api_server_msgqid, & cmsgbuf, sizeof(cmsgbuf)); + return 0; +} + +static struct loc_eng_dmn_conn_thelper thelper; + +int loc_eng_dmn_conn_loc_api_server_launch(thelper_create_thread create_thread_cb, + const char * loc_api_q_path, const char * resp_q_path, void *agps_handle) +{ + int result; + + loc_api_handle = agps_handle; + + if (loc_api_q_path) global_loc_api_q_path = loc_api_q_path; + if (resp_q_path) global_loc_api_resp_q_path = resp_q_path; + + result = loc_eng_dmn_conn_launch_thelper( &thelper, + loc_api_server_proc_init, + loc_api_server_proc_pre, + loc_api_server_proc, + loc_api_server_proc_post, + create_thread_cb, + (char *) global_loc_api_q_path); + if (result != 0) { + LOC_LOGE("%s:%d]\n", __func__, __LINE__); + return -1; + } + return 0; +} + +int loc_eng_dmn_conn_loc_api_server_unblock(void) +{ + loc_eng_dmn_conn_unblock_thelper(&thelper); + loc_eng_dmn_conn_unblock_proc(); + return 0; +} + +int loc_eng_dmn_conn_loc_api_server_join(void) +{ + loc_eng_dmn_conn_join_thelper(&thelper); + return 0; +} + +int loc_eng_dmn_conn_loc_api_server_data_conn(int sender_id, int status) { + struct ctrl_msgbuf cmsgbuf; + LOC_LOGD("%s:%d] quipc_msgqid = %d\n", __func__, __LINE__, quipc_msgqid); + cmsgbuf.ctrl_type = GPSONE_LOC_API_RESPONSE; + cmsgbuf.cmsg.cmsg_response.result = status; + switch (sender_id) { + case LOC_ENG_IF_REQUEST_SENDER_ID_QUIPC: { + LOC_LOGD("%s:%d] sender_id = LOC_ENG_IF_REQUEST_SENDER_ID_QUIPC", __func__, __LINE__); + if (loc_eng_dmn_conn_glue_msgsnd(quipc_msgqid, & cmsgbuf, sizeof(struct ctrl_msgbuf)) < 0) { + LOC_LOGD("%s:%d] error! conn_glue_msgsnd failed\n", __func__, __LINE__); + return -1; + } + break; + } + case LOC_ENG_IF_REQUEST_SENDER_ID_MSAPM: { + LOC_LOGD("%s:%d] sender_id = LOC_ENG_IF_REQUEST_SENDER_ID_MSAPM", __func__, __LINE__); + if (loc_eng_dmn_conn_glue_msgsnd(msapm_msgqid, & cmsgbuf, sizeof(struct ctrl_msgbuf)) < 0) { + LOC_LOGD("%s:%d] error! conn_glue_msgsnd failed\n", __func__, __LINE__); + return -1; + } + break; + } + case LOC_ENG_IF_REQUEST_SENDER_ID_MSAPU: { + LOC_LOGD("%s:%d] sender_id = LOC_ENG_IF_REQUEST_SENDER_ID_MSAPU", __func__, __LINE__); + if (loc_eng_dmn_conn_glue_msgsnd(msapu_msgqid, & cmsgbuf, sizeof(struct ctrl_msgbuf)) < 0) { + LOC_LOGD("%s:%d] error! conn_glue_msgsnd failed\n", __func__, __LINE__); + return -1; + } + break; + } + case LOC_ENG_IF_REQUEST_SENDER_ID_GPSONE_DAEMON: { + LOC_LOGD("%s:%d] sender_id = LOC_ENG_IF_REQUEST_SENDER_ID_GPSONE_DAEMON", __func__, __LINE__); + if (loc_eng_dmn_conn_glue_msgsnd(loc_api_resp_msgqid, & cmsgbuf, sizeof(struct ctrl_msgbuf)) < 0) { + LOC_LOGD("%s:%d] error! conn_glue_msgsnd failed\n", __func__, __LINE__); + return -1; + } + break; + } + default: { + LOC_LOGD("%s:%d] invalid sender ID!", __func__, __LINE__); + } + } + return 0; +} + diff --git a/gps/loc_api/libloc_api_50001/loc_eng_dmn_conn.h b/gps/loc_api/libloc_api_50001/loc_eng_dmn_conn.h new file mode 100644 index 000000000..1d8c14283 --- /dev/null +++ b/gps/loc_api/libloc_api_50001/loc_eng_dmn_conn.h @@ -0,0 +1,59 @@ +/* Copyright (c) 2011-2012,2014 The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef LOC_ENG_DATA_SERVER_H +#define LOC_ENG_DATA_SERVER_H + +#include "loc_eng_dmn_conn_thread_helper.h" + +#ifdef _ANDROID_ + +#define GPSONE_LOC_API_Q_PATH "/data/misc/location/gpsone_d/gpsone_loc_api_q" +#define GPSONE_LOC_API_RESP_Q_PATH "/data/misc/location/gpsone_d/gpsone_loc_api_resp_q" +#define QUIPC_CTRL_Q_PATH "/data/misc/location/gpsone_d/quipc_ctrl_q" +#define MSAPM_CTRL_Q_PATH "/data/misc/location/gpsone_d/msapm_ctrl_q" +#define MSAPU_CTRL_Q_PATH "/data/misc/location/gpsone_d/msapu_ctrl_q" + +#else + +#define GPSONE_LOC_API_Q_PATH "/tmp/gpsone_loc_api_q" +#define GPSONE_LOC_API_RESP_Q_PATH "/tmp/gpsone_loc_api_resp_q" +#define QUIPC_CTRL_Q_PATH "/tmp/quipc_ctrl_q" +#define MSAPM_CTRL_Q_PATH "/tmp/msapm_ctrl_q" +#define MSAPU_CTRL_Q_PATH "/tmp/msapu_ctrl_q" + +#endif + +int loc_eng_dmn_conn_loc_api_server_launch(thelper_create_thread create_thread_cb, + const char * loc_api_q_path, const char * ctrl_q_path, void *agps_handle); +int loc_eng_dmn_conn_loc_api_server_unblock(void); +int loc_eng_dmn_conn_loc_api_server_join(void); +int loc_eng_dmn_conn_loc_api_server_data_conn(int, int); + +#endif /* LOC_ENG_DATA_SERVER_H */ + diff --git a/gps/loc_api/libloc_api_50001/loc_eng_dmn_conn_glue_msg.c b/gps/loc_api/libloc_api_50001/loc_eng_dmn_conn_glue_msg.c new file mode 100644 index 000000000..a1076ff91 --- /dev/null +++ b/gps/loc_api/libloc_api_50001/loc_eng_dmn_conn_glue_msg.c @@ -0,0 +1,223 @@ +/* Copyright (c) 2011, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include +#include + +#include + +#include "log_util.h" +#include "platform_lib_includes.h" +#include "loc_eng_dmn_conn_glue_msg.h" +#include "loc_eng_dmn_conn_handler.h" + +/*=========================================================================== +FUNCTION loc_eng_dmn_conn_glue_msgget + +DESCRIPTION + This function get a message queue + + q_path - name path of the message queue + mode - + +DEPENDENCIES + None + +RETURN VALUE + message queue id + +SIDE EFFECTS + N/A + +===========================================================================*/ +int loc_eng_dmn_conn_glue_msgget(const char * q_path, int mode) +{ + int msgqid; + msgqid = loc_eng_dmn_conn_glue_pipeget(q_path, mode); + return msgqid; +} + +/*=========================================================================== +FUNCTION loc_eng_dmn_conn_glue_msgremove + +DESCRIPTION + remove a message queue + + q_path - name path of the message queue + msgqid - message queue id + +DEPENDENCIES + None + +RETURN VALUE + 0: success or negative value for failure + +SIDE EFFECTS + N/A + +===========================================================================*/ +int loc_eng_dmn_conn_glue_msgremove(const char * q_path, int msgqid) +{ + int result; + result = loc_eng_dmn_conn_glue_piperemove(q_path, msgqid); + return result; +} + +/*=========================================================================== +FUNCTION loc_eng_dmn_conn_glue_msgsnd + +DESCRIPTION + Send a message + + msgqid - message queue id + msgp - pointer to the message to be sent + msgsz - size of the message + +DEPENDENCIES + None + +RETURN VALUE + number of bytes sent out or negative value for failure + +SIDE EFFECTS + N/A + +===========================================================================*/ +int loc_eng_dmn_conn_glue_msgsnd(int msgqid, const void * msgp, size_t msgsz) +{ + int result; + struct ctrl_msgbuf *pmsg = (struct ctrl_msgbuf *) msgp; + pmsg->msgsz = msgsz; + + result = loc_eng_dmn_conn_glue_pipewrite(msgqid, msgp, msgsz); + if (result != (int) msgsz) { + LOC_LOGE("%s:%d] pipe broken %d, msgsz = %d\n", __func__, __LINE__, result, (int) msgsz); + return -1; + } + + return result; +} + +/*=========================================================================== +FUNCTION loc_eng_dmn_conn_glue_msgrcv + +DESCRIPTION + receive a message + + msgqid - message queue id + msgp - pointer to the buffer to hold the message + msgsz - size of the buffer + +DEPENDENCIES + None + +RETURN VALUE + number of bytes received or negative value for failure + +SIDE EFFECTS + N/A + +===========================================================================*/ +int loc_eng_dmn_conn_glue_msgrcv(int msgqid, void *msgp, size_t msgbufsz) +{ + int result; + struct ctrl_msgbuf *pmsg = (struct ctrl_msgbuf *) msgp; + + result = loc_eng_dmn_conn_glue_piperead(msgqid, &(pmsg->msgsz), sizeof(pmsg->msgsz)); + if (result != sizeof(pmsg->msgsz)) { + LOC_LOGE("%s:%d] pipe broken %d\n", __func__, __LINE__, result); + return -1; + } + + if (msgbufsz < pmsg->msgsz) { + LOC_LOGE("%s:%d] msgbuf is too small %d < %d\n", __func__, __LINE__, (int) msgbufsz, (int) pmsg->msgsz); + return -1; + } + + result = loc_eng_dmn_conn_glue_piperead(msgqid, (uint8_t *) msgp + sizeof(pmsg->msgsz), pmsg->msgsz - sizeof(pmsg->msgsz)); + if (result != (int) (pmsg->msgsz - sizeof(pmsg->msgsz))) { + LOC_LOGE("%s:%d] pipe broken %d, msgsz = %d\n", __func__, __LINE__, result, (int) pmsg->msgsz); + return -1; + } + + return pmsg->msgsz; +} + +/*=========================================================================== +FUNCTION loc_eng_dmn_conn_glue_msgunblock + +DESCRIPTION + unblock a message queue + + msgqid - message queue id + +DEPENDENCIES + None + +RETURN VALUE + 0: success + +SIDE EFFECTS + N/A + +===========================================================================*/ +int loc_eng_dmn_conn_glue_msgunblock(int msgqid) +{ + return loc_eng_dmn_conn_glue_pipeunblock(msgqid); +} + +/*=========================================================================== +FUNCTION loc_eng_dmn_conn_glue_msgflush + +DESCRIPTION + flush out the message in a queue + + msgqid - message queue id + +DEPENDENCIES + None + +RETURN VALUE + number of bytes that are flushed out. + +SIDE EFFECTS + N/A + +===========================================================================*/ +int loc_eng_dmn_conn_glue_msgflush(int msgqid) +{ + int length; + char buf[128]; + + do { + length = loc_eng_dmn_conn_glue_piperead(msgqid, buf, 128); + LOC_LOGD("%s:%d] %s\n", __func__, __LINE__, buf); + } while(length); + return length; +} + diff --git a/gps/loc_api/libloc_api_50001/loc_eng_dmn_conn_glue_msg.h b/gps/loc_api/libloc_api_50001/loc_eng_dmn_conn_glue_msg.h new file mode 100644 index 000000000..d685c87e2 --- /dev/null +++ b/gps/loc_api/libloc_api_50001/loc_eng_dmn_conn_glue_msg.h @@ -0,0 +1,51 @@ +/* Copyright (c) 2011, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef LOC_ENG_DMN_CONN_GLUE_MSG_H +#define LOC_ENG_DMN_CONN_GLUE_MSG_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +#include +#include "loc_eng_dmn_conn_glue_pipe.h" + +int loc_eng_dmn_conn_glue_msgget(const char * q_path, int mode); +int loc_eng_dmn_conn_glue_msgremove(const char * q_path, int msgqid); +int loc_eng_dmn_conn_glue_msgsnd(int msgqid, const void * msgp, size_t msgsz); +int loc_eng_dmn_conn_glue_msgrcv(int msgqid, void *msgp, size_t msgsz); +int loc_eng_dmn_conn_glue_msgflush(int msgqid); +int loc_eng_dmn_conn_glue_msgunblock(int msgqid); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* LOC_ENG_DMN_CONN_GLUE_MSG_H */ diff --git a/gps/loc_api/libloc_api_50001/loc_eng_dmn_conn_glue_pipe.c b/gps/loc_api/libloc_api_50001/loc_eng_dmn_conn_glue_pipe.c new file mode 100644 index 000000000..dffcad06b --- /dev/null +++ b/gps/loc_api/libloc_api_50001/loc_eng_dmn_conn_glue_pipe.c @@ -0,0 +1,214 @@ +/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include +#include +#include + +// #include +#include +// #include +#include +#include + +#include "loc_eng_dmn_conn_glue_pipe.h" +#include "log_util.h" +#include "platform_lib_includes.h" +/*=========================================================================== +FUNCTION loc_eng_dmn_conn_glue_pipeget + +DESCRIPTION + create a named pipe. + + pipe_name - pipe name path + mode - mode + +DEPENDENCIES + None + +RETURN VALUE + 0: success or negative value for failure + +SIDE EFFECTS + N/A + +===========================================================================*/ +int loc_eng_dmn_conn_glue_pipeget(const char * pipe_name, int mode) +{ + int fd; + int result; + + LOC_LOGD("%s, mode = %d\n", pipe_name, mode); + result = mkfifo(pipe_name, 0660); + + if ((result == -1) && (errno != EEXIST)) { + LOC_LOGE("failed: %s\n", strerror(errno)); + return result; + } + + // The mode in mkfifo is not honoured and does not provide the + // group permissions. Doing chmod to add group permissions. + result = chmod (pipe_name, 0660); + if (result != 0){ + LOC_LOGE ("%s failed to change mode for %s, error = %s\n", __func__, + pipe_name, strerror(errno)); + } + + fd = open(pipe_name, mode); + if (fd <= 0) + { + LOC_LOGE("failed: %s\n", strerror(errno)); + } + LOC_LOGD("fd = %d, %s\n", fd, pipe_name); + return fd; +} + +/*=========================================================================== +FUNCTION loc_eng_dmn_conn_glue_piperemove + +DESCRIPTION + remove a pipe + + pipe_name - pipe name path + fd - fd for the pipe + +DEPENDENCIES + None + +RETURN VALUE + 0: success + +SIDE EFFECTS + N/A + +===========================================================================*/ +int loc_eng_dmn_conn_glue_piperemove(const char * pipe_name, int fd) +{ + close(fd); + if (pipe_name) unlink(pipe_name); + LOC_LOGD("fd = %d, %s\n", fd, pipe_name); + return 0; +} + +/*=========================================================================== +FUNCTION loc_eng_dmn_conn_glue_pipewrite + +DESCRIPTION + write to a pipe + + fd - fd of a pipe + buf - buffer for the data to write + sz - size of the data in buffer + +DEPENDENCIES + None + +RETURN VALUE + number of bytes written or negative value for failure + +SIDE EFFECTS + N/A + +===========================================================================*/ +int loc_eng_dmn_conn_glue_pipewrite(int fd, const void * buf, size_t sz) +{ + int result; + + result = write(fd, buf, sz); + + /* @todo check for non EINTR & EAGAIN, shall not do select again, select_tut Law 7) */ + + /* LOC_LOGD("fd = %d, buf = 0x%lx, size = %d, result = %d\n", fd, (long) buf, (int) sz, (int) result); */ + return result; +} + +/*=========================================================================== +FUNCTION loc_eng_dmn_conn_glue_piperead + +DESCRIPTION + read from a pipe + + fd - fd for the pipe + buf - buffer to hold the data read from pipe + sz - size of the buffer + +DEPENDENCIES + None + +RETURN VALUE + number of bytes read from pipe or negative value for failure + +SIDE EFFECTS + N/A + +===========================================================================*/ +int loc_eng_dmn_conn_glue_piperead(int fd, void * buf, size_t sz) +{ + int len; + + len = read(fd, buf, sz); + + /* @todo check for non EINTR & EAGAIN, shall not do select again, select_tut Law 7) */ + + /* LOC_LOGD("fd = %d, buf = 0x%lx, size = %d, len = %d\n", fd, (long) buf, (int) sz, len); */ + return len; +} + +/*=========================================================================== +FUNCTION loc_eng_dmn_conn_glue_pipeunblock + +DESCRIPTION + unblock a pipe + + fd - fd for the pipe + +DEPENDENCIES + None + +RETURN VALUE + 0 for success or negative value for failure + +SIDE EFFECTS + N/A + +===========================================================================*/ +int loc_eng_dmn_conn_glue_pipeunblock(int fd) +{ + int result; + struct flock flock_v; + LOC_LOGD("\n"); +// result = fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NDELAY); + flock_v.l_type = F_UNLCK; + flock_v.l_len = 32; + result = fcntl(fd, F_SETLK, &flock_v); + if (result < 0) { + LOC_LOGE("fcntl failure, %s\n", strerror(errno)); + } + + return result; +} diff --git a/gps/loc_api/libloc_api_50001/loc_eng_dmn_conn_glue_pipe.h b/gps/loc_api/libloc_api_50001/loc_eng_dmn_conn_glue_pipe.h new file mode 100644 index 000000000..b2fa3a034 --- /dev/null +++ b/gps/loc_api/libloc_api_50001/loc_eng_dmn_conn_glue_pipe.h @@ -0,0 +1,50 @@ +/* Copyright (c) 2011, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef LOC_ENG_DMN_CONN_GLUE_PIPE_H +#define LOC_ENG_DMN_CONN_GLUE_PIPE_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include + +int loc_eng_dmn_conn_glue_pipeget(const char * pipe_name, int mode); +int loc_eng_dmn_conn_glue_piperemove(const char * pipe_name, int fd); +int loc_eng_dmn_conn_glue_pipewrite(int fd, const void * buf, size_t sz); +int loc_eng_dmn_conn_glue_piperead(int fd, void * buf, size_t sz); + +int loc_eng_dmn_conn_glue_pipeflush(int fd); +int loc_eng_dmn_conn_glue_pipeunblock(int fd); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* LOC_ENG_DMN_CONN_GLUE_PIPE_H */ diff --git a/gps/loc_api/libloc_api_50001/loc_eng_dmn_conn_handler.cpp b/gps/loc_api/libloc_api_50001/loc_eng_dmn_conn_handler.cpp new file mode 100644 index 000000000..edd53f218 --- /dev/null +++ b/gps/loc_api/libloc_api_50001/loc_eng_dmn_conn_handler.cpp @@ -0,0 +1,237 @@ +/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include +#include +#include +#include + +#include "log_util.h" +#include "platform_lib_includes.h" +#include "loc_eng_msg.h" +#include "loc_eng_dmn_conn.h" +#include "loc_eng_dmn_conn_handler.h" + +void* loc_api_handle = NULL; + +int loc_eng_dmn_conn_loc_api_server_if_request_handler(struct ctrl_msgbuf *pmsg, int len) +{ + LOC_LOGD("%s:%d]\n", __func__, __LINE__); +#ifndef DEBUG_DMN_LOC_API + if (NULL == loc_api_handle) { + LOC_LOGE("%s:%d] NO agps data handle\n", __func__, __LINE__); + return 1; + } + + if (NULL != loc_api_handle) { + AGpsExtType type; + switch (pmsg->cmsg.cmsg_if_request.type) { + case IF_REQUEST_TYPE_SUPL: + { + LOC_LOGD("IF_REQUEST_TYPE_SUPL"); + type = AGPS_TYPE_SUPL; + break; + } + case IF_REQUEST_TYPE_WIFI: + { + LOC_LOGD("IF_REQUEST_TYPE_WIFI"); + type = AGPS_TYPE_WIFI; + break; + } + case IF_REQUEST_TYPE_ANY: + { + LOC_LOGD("IF_REQUEST_TYPE_ANY"); + type = AGPS_TYPE_ANY; + break; + } + default: + { + LOC_LOGD("invalid IF_REQUEST_TYPE!"); + return -1; + } + } + switch (pmsg->cmsg.cmsg_if_request.sender_id) { + case IF_REQUEST_SENDER_ID_QUIPC: + { + LOC_LOGD("IF_REQUEST_SENDER_ID_QUIPC"); + LocEngReqRelWifi* msg = + new LocEngReqRelWifi(loc_api_handle, + type, + LOC_ENG_IF_REQUEST_SENDER_ID_QUIPC, + (char*)pmsg->cmsg.cmsg_if_request.ssid, + (char*)pmsg->cmsg.cmsg_if_request.password, + true); + msg->send(); + break; + } + case IF_REQUEST_SENDER_ID_MSAPM: + { + LOC_LOGD("IF_REQUEST_SENDER_ID_MSAPM"); + LocEngReqRelWifi* msg = + new LocEngReqRelWifi(loc_api_handle, + type, + LOC_ENG_IF_REQUEST_SENDER_ID_MSAPM, + (char*)pmsg->cmsg.cmsg_if_request.ssid, + (char*)pmsg->cmsg.cmsg_if_request.password, + true); + msg->send(); + break; + } + case IF_REQUEST_SENDER_ID_MSAPU: + { + LOC_LOGD("IF_REQUEST_SENDER_ID_MSAPU"); + LocEngReqRelWifi* msg = + new LocEngReqRelWifi(loc_api_handle, + type, + LOC_ENG_IF_REQUEST_SENDER_ID_MSAPU, + (char*)pmsg->cmsg.cmsg_if_request.ssid, + (char*)pmsg->cmsg.cmsg_if_request.password, + true); + msg->send(); + break; + } + case IF_REQUEST_SENDER_ID_GPSONE_DAEMON: + { + LOC_LOGD("IF_REQUEST_SENDER_ID_GPSONE_DAEMON"); + LocEngReqRelBIT* msg = + new LocEngReqRelBIT(loc_api_handle, + type, + pmsg->cmsg.cmsg_if_request.ipv4_addr, + (char*)pmsg->cmsg.cmsg_if_request.ipv6_addr, + true); + msg->send(); + break; + } + default: + { + LOC_LOGD("invalid IF_REQUEST_SENDER_ID!"); + return -1; + } + } + } + +#else + loc_eng_dmn_conn_loc_api_server_data_conn(LOC_ENG_IF_REQUEST_SENDER_ID_GPSONE_DAEMON, GPSONE_LOC_API_IF_REQUEST_SUCCESS); +#endif + return 0; +} + +int loc_eng_dmn_conn_loc_api_server_if_release_handler(struct ctrl_msgbuf *pmsg, int len) +{ + LOC_LOGD("%s:%d]\n", __func__, __LINE__); +#ifndef DEBUG_DMN_LOC_API + AGpsExtType type; + switch (pmsg->cmsg.cmsg_if_request.type) { + case IF_REQUEST_TYPE_SUPL: + { + LOC_LOGD("IF_REQUEST_TYPE_SUPL"); + type = AGPS_TYPE_SUPL; + break; + } + case IF_REQUEST_TYPE_WIFI: + { + LOC_LOGD("IF_REQUEST_TYPE_WIFI"); + type = AGPS_TYPE_WIFI; + break; + } + case IF_REQUEST_TYPE_ANY: + { + LOC_LOGD("IF_REQUEST_TYPE_ANY"); + type = AGPS_TYPE_ANY; + break; + } + default: + { + LOC_LOGD("invalid IF_REQUEST_TYPE!"); + return -1; + } + } + switch (pmsg->cmsg.cmsg_if_request.sender_id) { + case IF_REQUEST_SENDER_ID_QUIPC: + { + LOC_LOGD("IF_REQUEST_SENDER_ID_QUIPC"); + LocEngReqRelWifi* msg = + new LocEngReqRelWifi(loc_api_handle, + type, + LOC_ENG_IF_REQUEST_SENDER_ID_QUIPC, + (char*)pmsg->cmsg.cmsg_if_request.ssid, + (char*)pmsg->cmsg.cmsg_if_request.password, + false); + msg->send(); + break; + } + case IF_REQUEST_SENDER_ID_MSAPM: + { + LOC_LOGD("IF_REQUEST_SENDER_ID_MSAPM"); + LocEngReqRelWifi* msg = + new LocEngReqRelWifi(loc_api_handle, + type, + LOC_ENG_IF_REQUEST_SENDER_ID_MSAPM, + (char*)pmsg->cmsg.cmsg_if_request.ssid, + (char*)pmsg->cmsg.cmsg_if_request.password, + false); + msg->send(); + break; + } + case IF_REQUEST_SENDER_ID_MSAPU: + { + LOC_LOGD("IF_REQUEST_SENDER_ID_MSAPU"); + LocEngReqRelWifi* msg = + new LocEngReqRelWifi(loc_api_handle, + type, + LOC_ENG_IF_REQUEST_SENDER_ID_MSAPU, + (char*)pmsg->cmsg.cmsg_if_request.ssid, + (char*)pmsg->cmsg.cmsg_if_request.password, + false); + msg->send(); + break; + } + case IF_REQUEST_SENDER_ID_GPSONE_DAEMON: + { + LOC_LOGD("IF_REQUEST_SENDER_ID_GPSONE_DAEMON"); + LocEngReqRelBIT* msg = + new LocEngReqRelBIT(loc_api_handle, + type, + pmsg->cmsg.cmsg_if_request.ipv4_addr, + (char*)pmsg->cmsg.cmsg_if_request.ipv6_addr, + false); + msg->send(); + break; + } + default: + { + LOC_LOGD("invalid IF_REQUEST_SENDER_ID!"); + return -1; + } + } +#else + loc_eng_dmn_conn_loc_api_server_data_conn(LOC_ENG_IF_REQUEST_SENDER_ID_GPSONE_DAEMON, GPSONE_LOC_API_IF_RELEASE_SUCCESS); +#endif + return 0; +} + diff --git a/gps/loc_api/libloc_api_50001/loc_eng_dmn_conn_handler.h b/gps/loc_api/libloc_api_50001/loc_eng_dmn_conn_handler.h new file mode 100644 index 000000000..1c0edd551 --- /dev/null +++ b/gps/loc_api/libloc_api_50001/loc_eng_dmn_conn_handler.h @@ -0,0 +1,106 @@ +/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef LOC_ENG_DATA_SERVER_HANDLER +#define LOC_ENG_DATA_SERVER_HANDLER + +#include +#include + +//for SSID_BUF_SIZE +#include + +#ifndef SSID_BUF_SIZE + #define SSID_BUF_SIZE (32+1) +#endif + +enum { + /* 0x0 - 0xEF is reserved for daemon internal */ + GPSONE_LOC_API_IF_REQUEST = 0xF0, + GPSONE_LOC_API_IF_RELEASE, + GPSONE_LOC_API_RESPONSE, + GPSONE_UNBLOCK, +}; + +enum { + GPSONE_LOC_API_IF_REQUEST_SUCCESS = 0xF0, + GPSONE_LOC_API_IF_RELEASE_SUCCESS, + GPSONE_LOC_API_IF_FAILURE, +}; + + +struct ctrl_msg_response { + int result; +}; + +struct ctrl_msg_unblock { + int reserved; +}; + +typedef enum { + IF_REQUEST_TYPE_SUPL = 0, + IF_REQUEST_TYPE_WIFI, + IF_REQUEST_TYPE_ANY +} ctrl_if_req_type_e_type; + +typedef enum { + IF_REQUEST_SENDER_ID_QUIPC = 0, + IF_REQUEST_SENDER_ID_MSAPM, + IF_REQUEST_SENDER_ID_MSAPU, + IF_REQUEST_SENDER_ID_GPSONE_DAEMON, + IF_REQUEST_SENDER_ID_MODEM +} ctrl_if_req_sender_id_e_type; + +struct ctrl_msg_if_request { + ctrl_if_req_type_e_type type; + ctrl_if_req_sender_id_e_type sender_id; + unsigned long ipv4_addr; + unsigned char ipv6_addr[16]; + char ssid[SSID_BUF_SIZE]; + char password[SSID_BUF_SIZE]; +}; + +/* do not change this structure */ +struct ctrl_msgbuf { + size_t msgsz; + uint16_t reserved1; + uint32_t reserved2; + uint8_t ctrl_type; + union { + struct ctrl_msg_response cmsg_response; + struct ctrl_msg_unblock cmsg_unblock; + struct ctrl_msg_if_request cmsg_if_request; + } cmsg; +}; + +extern void* loc_api_handle; + +int loc_eng_dmn_conn_loc_api_server_if_request_handler(struct ctrl_msgbuf *pmsg, int len); +int loc_eng_dmn_conn_loc_api_server_if_release_handler(struct ctrl_msgbuf *pmsg, int len); + +#endif /* LOC_ENG_DATA_SERVER_HANDLER */ diff --git a/gps/loc_api/libloc_api_50001/loc_eng_dmn_conn_thread_helper.c b/gps/loc_api/libloc_api_50001/loc_eng_dmn_conn_thread_helper.c new file mode 100644 index 000000000..9fed9d424 --- /dev/null +++ b/gps/loc_api/libloc_api_50001/loc_eng_dmn_conn_thread_helper.c @@ -0,0 +1,399 @@ +/* Copyright (c) 2011, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include + +#include "log_util.h" +#include "platform_lib_includes.h" +#include "loc_eng_dmn_conn_thread_helper.h" + +/*=========================================================================== +FUNCTION thelper_signal_init + +DESCRIPTION + This function will initialize the conditional variable resources. + + thelper - thelper instance + +DEPENDENCIES + None + +RETURN VALUE + 0: success or negative value for failure + +SIDE EFFECTS + N/A + +===========================================================================*/ +int thelper_signal_init(struct loc_eng_dmn_conn_thelper * thelper) +{ + int result; + thelper->thread_exit = 0; + thelper->thread_ready = 0; + result = pthread_cond_init( &thelper->thread_cond, NULL); + if (result) { + return result; + } + + result = pthread_mutex_init(&thelper->thread_mutex, NULL); + if (result) { + pthread_cond_destroy(&thelper->thread_cond); + } + return result; +} + +/*=========================================================================== +FUNCTION + +DESCRIPTION + This function will destroy the conditional variable resources + + thelper - pointer to thelper instance + +DEPENDENCIES + None + +RETURN VALUE + 0: success or negative value for failure + +SIDE EFFECTS + N/A + +===========================================================================*/ +int thelper_signal_destroy(struct loc_eng_dmn_conn_thelper * thelper) +{ + int result, ret_result = 0; + result = pthread_cond_destroy( &thelper->thread_cond); + if (result) { + ret_result = result; + } + + result = pthread_mutex_destroy(&thelper->thread_mutex); + if (result) { + ret_result = result; + } + + return ret_result; +} + +/*=========================================================================== +FUNCTION thelper_signal_wait + +DESCRIPTION + This function will be blocked on the conditional variable until thelper_signal_ready + is called + + thelper - pointer to thelper instance + +DEPENDENCIES + None + +RETURN VALUE + 0: success or negative value for failure + +SIDE EFFECTS + N/A + +===========================================================================*/ +int thelper_signal_wait(struct loc_eng_dmn_conn_thelper * thelper) +{ + int result = 0; + + pthread_mutex_lock(&thelper->thread_mutex); + if (!thelper->thread_ready && !thelper->thread_exit) { + result = pthread_cond_wait(&thelper->thread_cond, &thelper->thread_mutex); + } + + if (thelper->thread_exit) { + result = -1; + } + pthread_mutex_unlock(&thelper->thread_mutex); + + return result; +} + +/*=========================================================================== +FUNCTION thelper_signal_ready + +DESCRIPTION + This function will wake up the conditional variable + + thelper - pointer to thelper instance + +DEPENDENCIES + None + +RETURN VALUE + 0: success or negative value for failure + +SIDE EFFECTS + N/A + +===========================================================================*/ +int thelper_signal_ready(struct loc_eng_dmn_conn_thelper * thelper) +{ + int result; + + LOC_LOGD("%s:%d] 0x%lx\n", __func__, __LINE__, (long) thelper); + + pthread_mutex_lock(&thelper->thread_mutex); + thelper->thread_ready = 1; + result = pthread_cond_signal(&thelper->thread_cond); + pthread_mutex_unlock(&thelper->thread_mutex); + + return result; +} + +/*=========================================================================== +FUNCTION thelper_signal_block + +DESCRIPTION + This function will set the thread ready to 0 to block the thelper_signal_wait + + thelper - pointer to thelper instance + +DEPENDENCIES + None + +RETURN VALUE + if thread_ready is set + +SIDE EFFECTS + N/A + +===========================================================================*/ +int thelper_signal_block(struct loc_eng_dmn_conn_thelper * thelper) +{ + int result = thelper->thread_ready; + + LOC_LOGD("%s:%d] 0x%lx\n", __func__, __LINE__, (long) thelper); + + pthread_mutex_lock(&thelper->thread_mutex); + thelper->thread_ready = 0; + pthread_mutex_unlock(&thelper->thread_mutex); + + return result; +} + +/*=========================================================================== +FUNCTION thelper_main + +DESCRIPTION + This function is the main thread. It will be launched as a child thread + + data - pointer to the instance + +DEPENDENCIES + None + +RETURN VALUE + NULL + +SIDE EFFECTS + N/A + +===========================================================================*/ +static void * thelper_main(void *data) +{ + int result = 0; + struct loc_eng_dmn_conn_thelper * thelper = (struct loc_eng_dmn_conn_thelper *) data; + + if (thelper->thread_proc_init) { + result = thelper->thread_proc_init(thelper->thread_context); + if (result < 0) { + thelper->thread_exit = 1; + thelper_signal_ready(thelper); + LOC_LOGE("%s:%d] error: 0x%lx\n", __func__, __LINE__, (long) thelper); + return NULL; + } + } + + thelper_signal_ready(thelper); + + if (thelper->thread_proc_pre) { + result = thelper->thread_proc_pre(thelper->thread_context); + if (result < 0) { + thelper->thread_exit = 1; + LOC_LOGE("%s:%d] error: 0x%lx\n", __func__, __LINE__, (long) thelper); + return NULL; + } + } + + do { + if (thelper->thread_proc) { + result = thelper->thread_proc(thelper->thread_context); + if (result < 0) { + thelper->thread_exit = 1; + LOC_LOGE("%s:%d] error: 0x%lx\n", __func__, __LINE__, (long) thelper); + } + } + } while (thelper->thread_exit == 0); + + if (thelper->thread_proc_post) { + result = thelper->thread_proc_post(thelper->thread_context); + } + + if (result != 0) { + LOC_LOGE("%s:%d] error: 0x%lx\n", __func__, __LINE__, (long) thelper); + } + return NULL; +} + +static void thelper_main_2(void *data) +{ + thelper_main(data); + return; +} + + +/*=========================================================================== +FUNCTION loc_eng_dmn_conn_launch_thelper + +DESCRIPTION + This function will initialize the thread context and launch the thelper_main + + thelper - pointer to thelper instance + thread_proc_init - The initialization function pointer + thread_proc_pre - The function to call before task loop and after initialization + thread_proc - The task loop + thread_proc_post - The function to call after the task loop + context - the context for the above four functions + +DEPENDENCIES + None + +RETURN VALUE + 0: success or negative value for failure + +SIDE EFFECTS + N/A + +===========================================================================*/ +int loc_eng_dmn_conn_launch_thelper(struct loc_eng_dmn_conn_thelper * thelper, + int (*thread_proc_init) (void * context), + int (*thread_proc_pre) (void * context), + int (*thread_proc) (void * context), + int (*thread_proc_post) (void * context), + thelper_create_thread create_thread_cb, + void * context) +{ + int result; + + thelper_signal_init(thelper); + + if (context) { + thelper->thread_context = context; + } + + thelper->thread_proc_init = thread_proc_init; + thelper->thread_proc_pre = thread_proc_pre; + thelper->thread_proc = thread_proc; + thelper->thread_proc_post = thread_proc_post; + + LOC_LOGD("%s:%d] 0x%lx call pthread_create\n", __func__, __LINE__, (long) thelper); + if (create_thread_cb) { + result = 0; + thelper->thread_id = create_thread_cb("loc_eng_dmn_conn", + thelper_main_2, (void *)thelper); + } else { + result = pthread_create(&thelper->thread_id, NULL, + thelper_main, (void *)thelper); + } + + if (result != 0) { + LOC_LOGE("%s:%d] 0x%lx\n", __func__, __LINE__, (long) thelper); + return -1; + } + + LOC_LOGD("%s:%d] 0x%lx pthread_create done\n", __func__, __LINE__, (long) thelper); + + thelper_signal_wait(thelper); + + LOC_LOGD("%s:%d] 0x%lx pthread ready\n", __func__, __LINE__, (long) thelper); + return thelper->thread_exit; +} + +/*=========================================================================== +FUNCTION loc_eng_dmn_conn_unblock_thelper + +DESCRIPTION + This function unblocks thelper_main to release the thread + + thelper - pointer to thelper instance + +DEPENDENCIES + None + +RETURN VALUE + 0: success + +SIDE EFFECTS + N/A + +===========================================================================*/ +int loc_eng_dmn_conn_unblock_thelper(struct loc_eng_dmn_conn_thelper * thelper) +{ + LOC_LOGD("%s:%d] 0x%lx\n", __func__, __LINE__, (long) thelper); + thelper->thread_exit = 1; + return 0; +} + +/*=========================================================================== +FUNCTION loc_eng_dmn_conn_join_thelper + + thelper - pointer to thelper instance + +DESCRIPTION + This function will wait for the thread of thelper_main to finish + +DEPENDENCIES + None + +RETURN VALUE + 0: success or negative value for failure + +SIDE EFFECTS + N/A + +===========================================================================*/ +int loc_eng_dmn_conn_join_thelper(struct loc_eng_dmn_conn_thelper * thelper) +{ + int result; + + LOC_LOGD("%s:%d] 0x%lx\n", __func__, __LINE__, (long) thelper); + result = pthread_join(thelper->thread_id, NULL); + if (result != 0) { + LOC_LOGE("%s:%d] 0x%lx\n", __func__, __LINE__, (long) thelper); + } + LOC_LOGD("%s:%d] 0x%lx\n", __func__, __LINE__, (long) thelper); + + thelper_signal_destroy(thelper); + + return result; +} + diff --git a/gps/loc_api/libloc_api_50001/loc_eng_dmn_conn_thread_helper.h b/gps/loc_api/libloc_api_50001/loc_eng_dmn_conn_thread_helper.h new file mode 100644 index 000000000..89e598b53 --- /dev/null +++ b/gps/loc_api/libloc_api_50001/loc_eng_dmn_conn_thread_helper.h @@ -0,0 +1,74 @@ +/* Copyright (c) 2011, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef __LOC_ENG_DMN_CONN_THREAD_HELPER_H__ +#define __LOC_ENG_DMN_CONN_THREAD_HELPER_H__ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include + +struct loc_eng_dmn_conn_thelper { + unsigned char thread_exit; + unsigned char thread_ready; + pthread_cond_t thread_cond; + pthread_mutex_t thread_mutex; + pthread_t thread_id; + void * thread_context; + int (*thread_proc_init) (void * context); + int (*thread_proc_pre) (void * context); + int (*thread_proc) (void * context); + int (*thread_proc_post) (void * context); +}; + +typedef pthread_t (* thelper_create_thread)(const char* name, void (*start)(void *), void* arg); +int loc_eng_dmn_conn_launch_thelper(struct loc_eng_dmn_conn_thelper * thelper, + int (*thread_proc_init) (void * context), + int (*thread_proc_pre) (void * context), + int (*thread_proc) (void * context), + int (*thread_proc_post) (void * context), + thelper_create_thread create_thread_cb, + void * context); + +int loc_eng_dmn_conn_unblock_thelper(struct loc_eng_dmn_conn_thelper * thelper); +int loc_eng_dmn_conn_join_thelper(struct loc_eng_dmn_conn_thelper * thelper); + +/* if only need to use signal */ +int thelper_signal_init(struct loc_eng_dmn_conn_thelper * thelper); +int thelper_signal_destroy(struct loc_eng_dmn_conn_thelper * thelper); +int thelper_signal_wait(struct loc_eng_dmn_conn_thelper * thelper); +int thelper_signal_ready(struct loc_eng_dmn_conn_thelper * thelper); +int thelper_signal_block(struct loc_eng_dmn_conn_thelper * thelper); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __LOC_ENG_DMN_CONN_THREAD_HELPER_H__ */ diff --git a/gps/loc_api/libloc_api_50001/loc_eng_log.cpp b/gps/loc_api/libloc_api_50001/loc_eng_log.cpp new file mode 100644 index 000000000..3a34167a2 --- /dev/null +++ b/gps/loc_api/libloc_api_50001/loc_eng_log.cpp @@ -0,0 +1,35 @@ +/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#define LOG_NDDEBUG 0 +#define LOG_TAG "LocSvc_eng" + +#include "loc_log.h" +#include "loc_eng_log.h" + diff --git a/gps/loc_api/libloc_api_50001/loc_eng_log.h b/gps/loc_api/libloc_api_50001/loc_eng_log.h new file mode 100644 index 000000000..a68bd8472 --- /dev/null +++ b/gps/loc_api/libloc_api_50001/loc_eng_log.h @@ -0,0 +1,44 @@ +/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef LOC_ENG_LOG_H +#define LOC_ENG_LOG_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include + +#ifdef __cplusplus +} +#endif + +#endif /* LOC_ENG_LOG_H */ diff --git a/gps/loc_api/libloc_api_50001/loc_eng_msg.h b/gps/loc_api/libloc_api_50001/loc_eng_msg.h new file mode 100644 index 000000000..9c7b9bcd8 --- /dev/null +++ b/gps/loc_api/libloc_api_50001/loc_eng_msg.h @@ -0,0 +1,306 @@ +/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef LOC_ENG_MSG_H +#define LOC_ENG_MSG_H + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef SSID_BUF_SIZE + #define SSID_BUF_SIZE (32+1) +#endif +#ifdef USE_GLIB + +#include + +#endif /* USE_GLIB */ +#include "platform_lib_includes.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +using namespace loc_core; + +struct LocEngPositionMode : public LocMsg { + LocEngAdapter* mAdapter; + const LocPosMode mPosMode; + LocEngPositionMode(LocEngAdapter* adapter, LocPosMode &mode); + virtual void proc() const; + virtual void log() const; + void send() const; +}; + + +struct LocEngStartFix : public LocMsg { + LocEngAdapter* mAdapter; + LocEngStartFix(LocEngAdapter* adapter); + virtual void proc() const; + void locallog() const; + virtual void log() const; + void send() const; +}; + +struct LocEngStopFix : public LocMsg { + LocEngAdapter* mAdapter; + LocEngStopFix(LocEngAdapter* adapter); + virtual void proc() const; + void locallog() const; + virtual void log() const; + void send() const; +}; + +struct LocEngReportPosition : public LocMsg { + LocAdapterBase* mAdapter; + const UlpLocation mLocation; + const GpsLocationExtended mLocationExtended; + const void* mLocationExt; + const enum loc_sess_status mStatus; + const LocPosTechMask mTechMask; + LocEngReportPosition(LocAdapterBase* adapter, + UlpLocation &loc, + GpsLocationExtended &locExtended, + void* locExt, + enum loc_sess_status st, + LocPosTechMask technology); + virtual void proc() const; + void locallog() const; + virtual void log() const; + void send() const; +}; + +struct LocEngReportSv : public LocMsg { + LocAdapterBase* mAdapter; + const GnssSvStatus mSvStatus; + const GpsLocationExtended mLocationExtended; + const void* mSvExt; + LocEngReportSv(LocAdapterBase* adapter, + GnssSvStatus &sv, + GpsLocationExtended &locExtended, + void* svExtended); + virtual void proc() const; + void locallog() const; + virtual void log() const; + void send() const; +}; + +struct LocEngReportStatus : public LocMsg { + LocAdapterBase* mAdapter; + const GpsStatusValue mStatus; + LocEngReportStatus(LocAdapterBase* adapter, + GpsStatusValue engineStatus); + virtual void proc() const; + void locallog() const; + virtual void log() const; +}; + +struct LocEngReportNmea : public LocMsg { + void* mLocEng; + char* const mNmea; + const int mLen; + LocEngReportNmea(void* locEng, + const char* data, int len); + inline virtual ~LocEngReportNmea() + { + delete[] mNmea; + } + virtual void proc() const; + void locallog() const; + virtual void log() const; +}; + +struct LocEngReportXtraServer : public LocMsg { + void* mLocEng; + int mMaxLen; + char *mServers; + LocEngReportXtraServer(void* locEng, + const char *url1, const char *url2, + const char *url3, const int maxlength); + inline virtual ~LocEngReportXtraServer() + { + delete[] mServers; + } + virtual void proc() const; + void locallog() const; + virtual void log() const; +}; + +struct LocEngSuplEsOpened : public LocMsg { + void* mLocEng; + LocEngSuplEsOpened(void* locEng); + virtual void proc() const; + void locallog() const; + virtual void log() const; +}; + +struct LocEngSuplEsClosed : public LocMsg { + void* mLocEng; + LocEngSuplEsClosed(void* locEng); + virtual void proc() const; + void locallog() const; + virtual void log() const; +}; + +struct LocEngRequestSuplEs : public LocMsg { + void* mLocEng; + const int mID; + LocEngRequestSuplEs(void* locEng, int id); + virtual void proc() const; + void locallog() const; + virtual void log() const; +}; + +struct LocEngRequestATL : public LocMsg { + void* mLocEng; + const int mID; + const AGpsExtType mType; + LocEngRequestATL(void* locEng, int id, + AGpsExtType agps_type); + virtual void proc() const; + void locallog() const; + virtual void log() const; +}; + +struct LocEngReleaseATL : public LocMsg { + void* mLocEng; + const int mID; + LocEngReleaseATL(void* locEng, int id); + virtual void proc() const; + void locallog() const; + virtual void log() const; +}; + +struct LocEngReqRelBIT : public LocMsg { + void* mLocEng; + const AGpsExtType mType; + const int mIPv4Addr; + char* const mIPv6Addr; + const bool mIsReq; + LocEngReqRelBIT(void* instance, AGpsExtType type, + int ipv4, char* ipv6, bool isReq); + virtual ~LocEngReqRelBIT(); + virtual void proc() const; + void locallog() const; + virtual void log() const; + void send() const; +}; + +struct LocEngReqRelWifi : public LocMsg { + void* mLocEng; + const AGpsExtType mType; + const loc_if_req_sender_id_e_type mSenderId; + char* const mSSID; + char* const mPassword; + const bool mIsReq; + LocEngReqRelWifi(void* locEng, AGpsExtType type, + loc_if_req_sender_id_e_type sender_id, + char* s, char* p, bool isReq); + virtual ~LocEngReqRelWifi(); + virtual void proc() const; + void locallog() const; + virtual void log() const; + void send() const; +}; + +struct LocEngRequestXtra : public LocMsg { + void* mLocEng; + LocEngRequestXtra(void* locEng); + virtual void proc() const; + void locallog() const; + virtual void log() const; +}; + +struct LocEngRequestTime : public LocMsg { + void* mLocEng; + LocEngRequestTime(void* locEng); + virtual void proc() const; + void locallog() const; + virtual void log() const; +}; + +struct LocEngRequestNi : public LocMsg { + void* mLocEng; + const GpsNiNotification mNotify; + const void *mPayload; + LocEngRequestNi(void* locEng, + GpsNiNotification ¬if, + const void* data); + virtual void proc() const; + void locallog() const; + virtual void log() const; +}; + +struct LocEngDown : public LocMsg { + void* mLocEng; + LocEngDown(void* locEng); + virtual void proc() const; + void locallog() const; + virtual void log() const; +}; + +struct LocEngUp : public LocMsg { + void* mLocEng; + LocEngUp(void* locEng); + virtual void proc() const; + void locallog() const; + virtual void log() const; +}; + +struct LocEngGetZpp : public LocMsg { + LocEngAdapter* mAdapter; + LocEngGetZpp(LocEngAdapter* adapter); + virtual void proc() const; + void locallog() const; + virtual void log() const; + void send() const; +}; + +struct LocEngReportGpsMeasurement : public LocMsg { + void* mLocEng; + const GpsData mGpsData; + LocEngReportGpsMeasurement(void* locEng, + GpsData &gpsData); + virtual void proc() const; + void locallog() const; + virtual void log() const; +}; + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* LOC_ENG_MSG_H */ diff --git a/gps/loc_api/libloc_api_50001/loc_eng_ni.cpp b/gps/loc_api/libloc_api_50001/loc_eng_ni.cpp new file mode 100644 index 000000000..4597b983f --- /dev/null +++ b/gps/loc_api/libloc_api_50001/loc_eng_ni.cpp @@ -0,0 +1,414 @@ +/* Copyright (c) 2009-2014, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#define LOG_NDDEBUG 0 +#define LOG_TAG "LocSvc_eng" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "log_util.h" +#include "platform_lib_includes.h" + +using namespace loc_core; + +/*============================================================================= + * + * DATA DECLARATION + * + *============================================================================*/ + +/*============================================================================= + * + * FUNCTION DECLARATIONS + * + *============================================================================*/ +static void* ni_thread_proc(void *args); + +struct LocEngInformNiResponse : public LocMsg { + LocEngAdapter* mAdapter; + const GpsUserResponseType mResponse; + const void *mPayload; + inline LocEngInformNiResponse(LocEngAdapter* adapter, + GpsUserResponseType resp, + const void* data) : + LocMsg(), mAdapter(adapter), + mResponse(resp), mPayload(data) + { + locallog(); + } + inline ~LocEngInformNiResponse() + { + // this is a bit weird since mPayload is not + // allocated by this class. But there is no better way. + // mPayload actually won't be NULL here. + free((void*)mPayload); + } + inline virtual void proc() const + { + mAdapter->informNiResponse(mResponse, mPayload); + } + inline void locallog() const + { + LOC_LOGV("LocEngInformNiResponse - " + "response: %s\n mPayload: %p", + loc_get_ni_response_name(mResponse), + mPayload); + } + inline virtual void log() const + { + locallog(); + } +}; + +/*=========================================================================== + +FUNCTION loc_eng_ni_request_handler + +DESCRIPTION + Displays the NI request and awaits user input. If a previous request is + in session, it is ignored. + +RETURN VALUE + none + +===========================================================================*/ +void loc_eng_ni_request_handler(loc_eng_data_s_type &loc_eng_data, + const GpsNiNotification *notif, + const void* passThrough) +{ + ENTRY_LOG(); + char lcs_addr[32]; // Decoded LCS address for UMTS CP NI + loc_eng_ni_data_s_type* loc_eng_ni_data_p = &loc_eng_data.loc_eng_ni_data; + loc_eng_ni_session_s_type* pSession = NULL; + + if (NULL == loc_eng_data.ni_notify_cb) { + EXIT_LOG(%s, "loc_eng_ni_init hasn't happened yet."); + return; + } + + if (notif->ni_type == GPS_NI_TYPE_EMERGENCY_SUPL) { + if (NULL != loc_eng_ni_data_p->sessionEs.rawRequest) { + LOC_LOGW("loc_eng_ni_request_handler, supl es NI in progress, new supl es NI ignored, type: %d", + notif->ni_type); + if (NULL != passThrough) { + free((void*)passThrough); + } + } else { + pSession = &loc_eng_ni_data_p->sessionEs; + } + } else { + if (NULL != loc_eng_ni_data_p->session.rawRequest || + NULL != loc_eng_ni_data_p->sessionEs.rawRequest) { + LOC_LOGW("loc_eng_ni_request_handler, supl NI in progress, new supl NI ignored, type: %d", + notif->ni_type); + if (NULL != passThrough) { + free((void*)passThrough); + } + } else { + pSession = &loc_eng_ni_data_p->session; + } + } + + + if (pSession) { + /* Save request */ + pSession->rawRequest = (void*)passThrough; + pSession->reqID = ++loc_eng_ni_data_p->reqIDCounter; + pSession->adapter = loc_eng_data.adapter; + + /* Fill in notification */ + ((GpsNiNotification*)notif)->notification_id = pSession->reqID; + + if (notif->notify_flags == GPS_NI_PRIVACY_OVERRIDE) + { + loc_eng_mute_one_session(loc_eng_data); + } + + /* Log requestor ID and text for debugging */ + LOC_LOGI("Notification: notif_type: %d, timeout: %d, default_resp: %d", notif->ni_type, notif->timeout, notif->default_response); + LOC_LOGI(" requestor_id: %s (encoding: %d)", notif->requestor_id, notif->requestor_id_encoding); + LOC_LOGI(" text: %s text (encoding: %d)", notif->text, notif->text_encoding); + if (notif->extras[0]) + { + LOC_LOGI(" extras: %s", notif->extras); + } + + /* For robustness, spawn a thread at this point to timeout to clear up the notification status, even though + * the OEM layer in java does not do so. + **/ + pSession->respTimeLeft = 5 + (notif->timeout != 0 ? notif->timeout : LOC_NI_NO_RESPONSE_TIME); + LOC_LOGI("Automatically sends 'no response' in %d seconds (to clear status)\n", pSession->respTimeLeft); + + int rc = 0; + rc = pthread_create(&pSession->thread, NULL, ni_thread_proc, pSession); + if (rc) + { + LOC_LOGE("Loc NI thread is not created.\n"); + } + rc = pthread_detach(pSession->thread); + if (rc) + { + LOC_LOGE("Loc NI thread is not detached.\n"); + } + + CALLBACK_LOG_CALLFLOW("ni_notify_cb - id", %d, notif->notification_id); + loc_eng_data.ni_notify_cb((GpsNiNotification*)notif); + } + EXIT_LOG(%s, VOID_RET); +} + +/*=========================================================================== + +FUNCTION ni_thread_proc + +===========================================================================*/ +static void* ni_thread_proc(void *args) +{ + ENTRY_LOG(); + + loc_eng_ni_session_s_type* pSession = (loc_eng_ni_session_s_type*)args; + int rc = 0; /* return code from pthread calls */ + + struct timeval present_time; + struct timespec expire_time; + + LOC_LOGD("Starting Loc NI thread...\n"); + pthread_mutex_lock(&pSession->tLock); + /* Calculate absolute expire time */ + gettimeofday(&present_time, NULL); + expire_time.tv_sec = present_time.tv_sec + pSession->respTimeLeft; + expire_time.tv_nsec = present_time.tv_usec * 1000; + LOC_LOGD("ni_thread_proc-Time out set for abs time %ld with delay %d sec\n", + (long) expire_time.tv_sec, pSession->respTimeLeft ); + + while (!pSession->respRecvd) + { + rc = pthread_cond_timedwait(&pSession->tCond, + &pSession->tLock, + &expire_time); + if (rc == ETIMEDOUT) + { + pSession->resp = GPS_NI_RESPONSE_NORESP; + LOC_LOGD("ni_thread_proc-Thread time out after valting for specified time. Ret Val %d\n",rc ); + break; + } + } + LOC_LOGD("ni_thread_proc-Java layer has sent us a user response and return value from " + "pthread_cond_timedwait = %d\n",rc ); + pSession->respRecvd = FALSE; /* Reset the user response flag for the next session*/ + + LOC_LOGD("pSession->resp is %d\n",pSession->resp); + + // adding this check to support modem restart, in which case, we need the thread + // to exit without calling sending data. We made sure that rawRequest is NULL in + // loc_eng_ni_reset_on_engine_restart() + LocEngAdapter* adapter = pSession->adapter; + LocEngInformNiResponse *msg = NULL; + + if (NULL != pSession->rawRequest) { + if (pSession->resp != GPS_NI_RESPONSE_IGNORE) { + LOC_LOGD("pSession->resp != GPS_NI_RESPONSE_IGNORE \n"); + msg = new LocEngInformNiResponse(adapter, + pSession->resp, + pSession->rawRequest); + } else { + LOC_LOGD("this is the ignore reply for SUPL ES\n"); + free(pSession->rawRequest); + } + pSession->rawRequest = NULL; + } + pthread_mutex_unlock(&pSession->tLock); + + pSession->respTimeLeft = 0; + pSession->reqID = 0; + + if (NULL != msg) { + LOC_LOGD("ni_thread_proc: adapter->sendMsg(msg)\n"); + adapter->sendMsg(msg); + } + + EXIT_LOG(%s, VOID_RET); + return NULL; +} + +void loc_eng_ni_reset_on_engine_restart(loc_eng_data_s_type &loc_eng_data) +{ + ENTRY_LOG(); + loc_eng_ni_data_s_type* loc_eng_ni_data_p = &loc_eng_data.loc_eng_ni_data; + + if (NULL == loc_eng_data.ni_notify_cb) { + EXIT_LOG(%s, "loc_eng_ni_init hasn't happened yet."); + return; + } + + // only if modem has requested but then died. + if (NULL != loc_eng_ni_data_p->sessionEs.rawRequest) { + free(loc_eng_ni_data_p->sessionEs.rawRequest); + loc_eng_ni_data_p->sessionEs.rawRequest = NULL; + + pthread_mutex_lock(&loc_eng_ni_data_p->sessionEs.tLock); + // the goal is to wake up ni_thread_proc + // and let it exit. + loc_eng_ni_data_p->sessionEs.respRecvd = TRUE; + pthread_cond_signal(&loc_eng_ni_data_p->sessionEs.tCond); + pthread_mutex_unlock(&loc_eng_ni_data_p->sessionEs.tLock); + } + + if (NULL != loc_eng_ni_data_p->session.rawRequest) { + free(loc_eng_ni_data_p->session.rawRequest); + loc_eng_ni_data_p->session.rawRequest = NULL; + + pthread_mutex_lock(&loc_eng_ni_data_p->session.tLock); + // the goal is to wake up ni_thread_proc + // and let it exit. + loc_eng_ni_data_p->session.respRecvd = TRUE; + pthread_cond_signal(&loc_eng_ni_data_p->session.tCond); + pthread_mutex_unlock(&loc_eng_ni_data_p->session.tLock); + } + + EXIT_LOG(%s, VOID_RET); +} + +/*=========================================================================== +FUNCTION loc_eng_ni_init + +DESCRIPTION + This function initializes the NI interface + +DEPENDENCIES + NONE + +RETURN VALUE + None + +SIDE EFFECTS + N/A + +===========================================================================*/ +void loc_eng_ni_init(loc_eng_data_s_type &loc_eng_data, GpsNiExtCallbacks *callbacks) +{ + ENTRY_LOG_CALLFLOW(); + + if(callbacks == NULL) + EXIT_LOG(%s, "loc_eng_ni_init: failed, cb is NULL"); + else if (NULL == callbacks->notify_cb) { + EXIT_LOG(%s, "loc_eng_ni_init: failed, no cb."); + } else if (NULL != loc_eng_data.ni_notify_cb) { + EXIT_LOG(%s, "loc_eng_ni_init: already inited."); + } else { + loc_eng_ni_data_s_type* loc_eng_ni_data_p = &loc_eng_data.loc_eng_ni_data; + loc_eng_ni_data_p->sessionEs.respTimeLeft = 0; + loc_eng_ni_data_p->sessionEs.respRecvd = FALSE; + loc_eng_ni_data_p->sessionEs.rawRequest = NULL; + loc_eng_ni_data_p->sessionEs.reqID = 0; + pthread_cond_init(&loc_eng_ni_data_p->sessionEs.tCond, NULL); + pthread_mutex_init(&loc_eng_ni_data_p->sessionEs.tLock, NULL); + + loc_eng_ni_data_p->session.respTimeLeft = 0; + loc_eng_ni_data_p->session.respRecvd = FALSE; + loc_eng_ni_data_p->session.rawRequest = NULL; + loc_eng_ni_data_p->session.reqID = 0; + pthread_cond_init(&loc_eng_ni_data_p->session.tCond, NULL); + pthread_mutex_init(&loc_eng_ni_data_p->session.tLock, NULL); + + loc_eng_data.ni_notify_cb = callbacks->notify_cb; + EXIT_LOG(%s, VOID_RET); + } +} + +/*=========================================================================== +FUNCTION loc_eng_ni_respond + +DESCRIPTION + This function receives user response from upper layer framework + +DEPENDENCIES + NONE + +RETURN VALUE + None + +SIDE EFFECTS + N/A + +===========================================================================*/ +void loc_eng_ni_respond(loc_eng_data_s_type &loc_eng_data, + int notif_id, GpsUserResponseType user_response) +{ + ENTRY_LOG_CALLFLOW(); + loc_eng_ni_data_s_type* loc_eng_ni_data_p = &loc_eng_data.loc_eng_ni_data; + loc_eng_ni_session_s_type* pSession = NULL; + + if (NULL == loc_eng_data.ni_notify_cb) { + EXIT_LOG(%s, "loc_eng_ni_init hasn't happened yet."); + return; + } + + if (notif_id == loc_eng_ni_data_p->sessionEs.reqID && + NULL != loc_eng_ni_data_p->sessionEs.rawRequest) { + pSession = &loc_eng_ni_data_p->sessionEs; + // ignore any SUPL NI non-Es session if a SUPL NI ES is accepted + if (user_response == GPS_NI_RESPONSE_ACCEPT && + NULL != loc_eng_ni_data_p->session.rawRequest) { + pthread_mutex_lock(&loc_eng_ni_data_p->session.tLock); + loc_eng_ni_data_p->session.resp = GPS_NI_RESPONSE_IGNORE; + loc_eng_ni_data_p->session.respRecvd = TRUE; + pthread_cond_signal(&loc_eng_ni_data_p->session.tCond); + pthread_mutex_unlock(&loc_eng_ni_data_p->session.tLock); + } + } else if (notif_id == loc_eng_ni_data_p->session.reqID && + NULL != loc_eng_ni_data_p->session.rawRequest) { + pSession = &loc_eng_ni_data_p->session; + } + + if (pSession) { + LOC_LOGI("loc_eng_ni_respond: send user response %d for notif %d", user_response, notif_id); + pthread_mutex_lock(&pSession->tLock); + pSession->resp = user_response; + pSession->respRecvd = TRUE; + pthread_cond_signal(&pSession->tCond); + pthread_mutex_unlock(&pSession->tLock); + } + else { + LOC_LOGE("loc_eng_ni_respond: notif_id %d not an active session", notif_id); + } + + EXIT_LOG(%s, VOID_RET); +} diff --git a/gps/loc_api/libloc_api_50001/loc_eng_ni.h b/gps/loc_api/libloc_api_50001/loc_eng_ni.h new file mode 100644 index 000000000..068f5cdd7 --- /dev/null +++ b/gps/loc_api/libloc_api_50001/loc_eng_ni.h @@ -0,0 +1,59 @@ +/* Copyright (c) 2009,2011,2014 The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef LOC_ENG_NI_H +#define LOC_ENG_NI_H + +#include +#include + +#define LOC_NI_NO_RESPONSE_TIME 20 /* secs */ +#define LOC_NI_NOTIF_KEY_ADDRESS "Address" +#define GPS_NI_RESPONSE_IGNORE 4 + +typedef struct { + pthread_t thread; /* NI thread */ + int respTimeLeft; /* examine time for NI response */ + bool respRecvd; /* NI User reponse received or not from Java layer*/ + void* rawRequest; + int reqID; /* ID to check against response */ + GpsUserResponseType resp; + pthread_cond_t tCond; + pthread_mutex_t tLock; + LocEngAdapter* adapter; +} loc_eng_ni_session_s_type; + +typedef struct { + loc_eng_ni_session_s_type session; /* SUPL NI Session */ + loc_eng_ni_session_s_type sessionEs; /* Emergency SUPL NI Session */ + int reqIDCounter; +} loc_eng_ni_data_s_type; + + +#endif /* LOC_ENG_NI_H */ diff --git a/gps/loc_api/libloc_api_50001/loc_eng_nmea.cpp b/gps/loc_api/libloc_api_50001/loc_eng_nmea.cpp new file mode 100644 index 000000000..126a97f0c --- /dev/null +++ b/gps/loc_api/libloc_api_50001/loc_eng_nmea.cpp @@ -0,0 +1,814 @@ +/* Copyright (c) 2012, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#define LOG_NDDEBUG 0 +#define LOG_TAG "LocSvc_eng_nmea" +#define GPS_PRN_START 1 +#define GPS_PRN_END 32 +#define GLONASS_PRN_START 65 +#define GLONASS_PRN_END 96 +#include +#include +#include +#include "log_util.h" + +/*=========================================================================== +FUNCTION loc_eng_nmea_send + +DESCRIPTION + send out NMEA sentence + +DEPENDENCIES + NONE + +RETURN VALUE + Total length of the nmea sentence + +SIDE EFFECTS + N/A + +===========================================================================*/ +void loc_eng_nmea_send(char *pNmea, int length, loc_eng_data_s_type *loc_eng_data_p) +{ + struct timeval tv; + gettimeofday(&tv, (struct timezone *) NULL); + int64_t now = tv.tv_sec * 1000LL + tv.tv_usec / 1000; + CALLBACK_LOG_CALLFLOW("nmea_cb", %p, pNmea); + if (loc_eng_data_p->nmea_cb != NULL) + loc_eng_data_p->nmea_cb(now, pNmea, length); + LOC_LOGD("NMEA <%s", pNmea); +} + +/*=========================================================================== +FUNCTION loc_eng_nmea_put_checksum + +DESCRIPTION + Generate NMEA sentences generated based on position report + +DEPENDENCIES + NONE + +RETURN VALUE + Total length of the nmea sentence + +SIDE EFFECTS + N/A + +===========================================================================*/ +int loc_eng_nmea_put_checksum(char *pNmea, int maxSize) +{ + uint8_t checksum = 0; + int length = 0; + + pNmea++; //skip the $ + while (*pNmea != '\0') + { + checksum ^= *pNmea++; + length++; + } + + int checksumLength = snprintf(pNmea,(maxSize-length-1),"*%02X\r\n", checksum); + return (length + checksumLength); +} + +/*=========================================================================== +FUNCTION loc_eng_nmea_generate_pos + +DESCRIPTION + Generate NMEA sentences generated based on position report + +DEPENDENCIES + NONE + +RETURN VALUE + 0 + +SIDE EFFECTS + N/A + +===========================================================================*/ +void loc_eng_nmea_generate_pos(loc_eng_data_s_type *loc_eng_data_p, + const UlpLocation &location, + const GpsLocationExtended &locationExtended, + unsigned char generate_nmea) +{ + ENTRY_LOG(); + time_t utcTime(location.gpsLocation.timestamp/1000); + tm * pTm = gmtime(&utcTime); + if (NULL == pTm) { + LOC_LOGE("gmtime failed"); + return; + } + + char sentence[NMEA_SENTENCE_MAX_LENGTH] = {0}; + char* pMarker = sentence; + int lengthRemaining = sizeof(sentence); + int length = 0; + int utcYear = pTm->tm_year % 100; // 2 digit year + int utcMonth = pTm->tm_mon + 1; // tm_mon starts at zero + int utcDay = pTm->tm_mday; + int utcHours = pTm->tm_hour; + int utcMinutes = pTm->tm_min; + int utcSeconds = pTm->tm_sec; + + if (generate_nmea) { + // ------------------ + // ------$GPGSA------ + // ------------------ + + uint32_t svUsedCount = 0; + uint32_t svUsedList[32] = {0}; + uint32_t mask = loc_eng_data_p->sv_used_mask; + for (uint8_t i = 1; mask > 0 && svUsedCount < 32; i++) + { + if (mask & 1) + svUsedList[svUsedCount++] = i; + mask = mask >> 1; + } + // clear the cache so they can't be used again + loc_eng_data_p->sv_used_mask = 0; + + char fixType; + if (svUsedCount == 0) + fixType = '1'; // no fix + else if (svUsedCount <= 3) + fixType = '2'; // 2D fix + else + fixType = '3'; // 3D fix + + length = snprintf(pMarker, lengthRemaining, "$GPGSA,A,%c,", fixType); + + if (length < 0 || length >= lengthRemaining) + { + LOC_LOGE("NMEA Error in string formatting"); + return; + } + pMarker += length; + lengthRemaining -= length; + + for (uint8_t i = 0; i < 12; i++) // only the first 12 sv go in sentence + { + if (i < svUsedCount) + length = snprintf(pMarker, lengthRemaining, "%02d,", svUsedList[i]); + else + length = snprintf(pMarker, lengthRemaining, ","); + + if (length < 0 || length >= lengthRemaining) + { + LOC_LOGE("NMEA Error in string formatting"); + return; + } + pMarker += length; + lengthRemaining -= length; + } + + if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_DOP) + { // dop is in locationExtended, (QMI) + length = snprintf(pMarker, lengthRemaining, "%.1f,%.1f,%.1f", + locationExtended.pdop, + locationExtended.hdop, + locationExtended.vdop); + } + else if (loc_eng_data_p->pdop > 0 && loc_eng_data_p->hdop > 0 && loc_eng_data_p->vdop > 0) + { // dop was cached from sv report (RPC) + length = snprintf(pMarker, lengthRemaining, "%.1f,%.1f,%.1f", + loc_eng_data_p->pdop, + loc_eng_data_p->hdop, + loc_eng_data_p->vdop); + } + else + { // no dop + length = snprintf(pMarker, lengthRemaining, ",,"); + } + + length = loc_eng_nmea_put_checksum(sentence, sizeof(sentence)); + loc_eng_nmea_send(sentence, length, loc_eng_data_p); + + // ------------------ + // ------$GPVTG------ + // ------------------ + + pMarker = sentence; + lengthRemaining = sizeof(sentence); + + if (location.gpsLocation.flags & GPS_LOCATION_HAS_BEARING) + { + float magTrack = location.gpsLocation.bearing; + if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_MAG_DEV) + { + float magTrack = location.gpsLocation.bearing - locationExtended.magneticDeviation; + if (magTrack < 0.0) + magTrack += 360.0; + else if (magTrack > 360.0) + magTrack -= 360.0; + } + + length = snprintf(pMarker, lengthRemaining, "$GPVTG,%.1lf,T,%.1lf,M,", location.gpsLocation.bearing, magTrack); + } + else + { + length = snprintf(pMarker, lengthRemaining, "$GPVTG,,T,,M,"); + } + + if (length < 0 || length >= lengthRemaining) + { + LOC_LOGE("NMEA Error in string formatting"); + return; + } + pMarker += length; + lengthRemaining -= length; + + if (location.gpsLocation.flags & GPS_LOCATION_HAS_SPEED) + { + float speedKnots = location.gpsLocation.speed * (3600.0/1852.0); + float speedKmPerHour = location.gpsLocation.speed * 3.6; + + length = snprintf(pMarker, lengthRemaining, "%.1lf,N,%.1lf,K,", speedKnots, speedKmPerHour); + } + else + { + length = snprintf(pMarker, lengthRemaining, ",N,,K,"); + } + + if (length < 0 || length >= lengthRemaining) + { + LOC_LOGE("NMEA Error in string formatting"); + return; + } + pMarker += length; + lengthRemaining -= length; + + if (!(location.gpsLocation.flags & GPS_LOCATION_HAS_LAT_LONG)) + length = snprintf(pMarker, lengthRemaining, "%c", 'N'); // N means no fix + else if (LOC_POSITION_MODE_STANDALONE == loc_eng_data_p->adapter->getPositionMode().mode) + length = snprintf(pMarker, lengthRemaining, "%c", 'A'); // A means autonomous + else + length = snprintf(pMarker, lengthRemaining, "%c", 'D'); // D means differential + + length = loc_eng_nmea_put_checksum(sentence, sizeof(sentence)); + loc_eng_nmea_send(sentence, length, loc_eng_data_p); + + // ------------------ + // ------$GPRMC------ + // ------------------ + + pMarker = sentence; + lengthRemaining = sizeof(sentence); + + length = snprintf(pMarker, lengthRemaining, "$GPRMC,%02d%02d%02d,A," , + utcHours, utcMinutes, utcSeconds); + + if (length < 0 || length >= lengthRemaining) + { + LOC_LOGE("NMEA Error in string formatting"); + return; + } + pMarker += length; + lengthRemaining -= length; + + if (location.gpsLocation.flags & GPS_LOCATION_HAS_LAT_LONG) + { + double latitude = location.gpsLocation.latitude; + double longitude = location.gpsLocation.longitude; + char latHemisphere; + char lonHemisphere; + double latMinutes; + double lonMinutes; + + if (latitude > 0) + { + latHemisphere = 'N'; + } + else + { + latHemisphere = 'S'; + latitude *= -1.0; + } + + if (longitude < 0) + { + lonHemisphere = 'W'; + longitude *= -1.0; + } + else + { + lonHemisphere = 'E'; + } + + latMinutes = fmod(latitude * 60.0 , 60.0); + lonMinutes = fmod(longitude * 60.0 , 60.0); + + length = snprintf(pMarker, lengthRemaining, "%02d%09.6lf,%c,%03d%09.6lf,%c,", + (uint8_t)floor(latitude), latMinutes, latHemisphere, + (uint8_t)floor(longitude),lonMinutes, lonHemisphere); + } + else + { + length = snprintf(pMarker, lengthRemaining,",,,,"); + } + + if (length < 0 || length >= lengthRemaining) + { + LOC_LOGE("NMEA Error in string formatting"); + return; + } + pMarker += length; + lengthRemaining -= length; + + if (location.gpsLocation.flags & GPS_LOCATION_HAS_SPEED) + { + float speedKnots = location.gpsLocation.speed * (3600.0/1852.0); + length = snprintf(pMarker, lengthRemaining, "%.1lf,", speedKnots); + } + else + { + length = snprintf(pMarker, lengthRemaining, ","); + } + + if (length < 0 || length >= lengthRemaining) + { + LOC_LOGE("NMEA Error in string formatting"); + return; + } + pMarker += length; + lengthRemaining -= length; + + if (location.gpsLocation.flags & GPS_LOCATION_HAS_BEARING) + { + length = snprintf(pMarker, lengthRemaining, "%.1lf,", location.gpsLocation.bearing); + } + else + { + length = snprintf(pMarker, lengthRemaining, ","); + } + + if (length < 0 || length >= lengthRemaining) + { + LOC_LOGE("NMEA Error in string formatting"); + return; + } + pMarker += length; + lengthRemaining -= length; + + length = snprintf(pMarker, lengthRemaining, "%2.2d%2.2d%2.2d,", + utcDay, utcMonth, utcYear); + + if (length < 0 || length >= lengthRemaining) + { + LOC_LOGE("NMEA Error in string formatting"); + return; + } + pMarker += length; + lengthRemaining -= length; + + if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_MAG_DEV) + { + float magneticVariation = locationExtended.magneticDeviation; + char direction; + if (magneticVariation < 0.0) + { + direction = 'W'; + magneticVariation *= -1.0; + } + else + { + direction = 'E'; + } + + length = snprintf(pMarker, lengthRemaining, "%.1lf,%c,", + magneticVariation, direction); + } + else + { + length = snprintf(pMarker, lengthRemaining, ",,"); + } + + if (length < 0 || length >= lengthRemaining) + { + LOC_LOGE("NMEA Error in string formatting"); + return; + } + pMarker += length; + lengthRemaining -= length; + + if (!(location.gpsLocation.flags & GPS_LOCATION_HAS_LAT_LONG)) + length = snprintf(pMarker, lengthRemaining, "%c", 'N'); // N means no fix + else if (LOC_POSITION_MODE_STANDALONE == loc_eng_data_p->adapter->getPositionMode().mode) + length = snprintf(pMarker, lengthRemaining, "%c", 'A'); // A means autonomous + else + length = snprintf(pMarker, lengthRemaining, "%c", 'D'); // D means differential + + length = loc_eng_nmea_put_checksum(sentence, sizeof(sentence)); + loc_eng_nmea_send(sentence, length, loc_eng_data_p); + + // ------------------ + // ------$GPGGA------ + // ------------------ + + pMarker = sentence; + lengthRemaining = sizeof(sentence); + + length = snprintf(pMarker, lengthRemaining, "$GPGGA,%02d%02d%02d," , + utcHours, utcMinutes, utcSeconds); + + if (length < 0 || length >= lengthRemaining) + { + LOC_LOGE("NMEA Error in string formatting"); + return; + } + pMarker += length; + lengthRemaining -= length; + + if (location.gpsLocation.flags & GPS_LOCATION_HAS_LAT_LONG) + { + double latitude = location.gpsLocation.latitude; + double longitude = location.gpsLocation.longitude; + char latHemisphere; + char lonHemisphere; + double latMinutes; + double lonMinutes; + + if (latitude > 0) + { + latHemisphere = 'N'; + } + else + { + latHemisphere = 'S'; + latitude *= -1.0; + } + + if (longitude < 0) + { + lonHemisphere = 'W'; + longitude *= -1.0; + } + else + { + lonHemisphere = 'E'; + } + + latMinutes = fmod(latitude * 60.0 , 60.0); + lonMinutes = fmod(longitude * 60.0 , 60.0); + + length = snprintf(pMarker, lengthRemaining, "%02d%09.6lf,%c,%03d%09.6lf,%c,", + (uint8_t)floor(latitude), latMinutes, latHemisphere, + (uint8_t)floor(longitude),lonMinutes, lonHemisphere); + } + else + { + length = snprintf(pMarker, lengthRemaining,",,,,"); + } + + if (length < 0 || length >= lengthRemaining) + { + LOC_LOGE("NMEA Error in string formatting"); + return; + } + pMarker += length; + lengthRemaining -= length; + + char gpsQuality; + if (!(location.gpsLocation.flags & GPS_LOCATION_HAS_LAT_LONG)) + gpsQuality = '0'; // 0 means no fix + else if (LOC_POSITION_MODE_STANDALONE == loc_eng_data_p->adapter->getPositionMode().mode) + gpsQuality = '1'; // 1 means GPS fix + else + gpsQuality = '2'; // 2 means DGPS fix + + if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_DOP) + { // dop is in locationExtended, (QMI) + length = snprintf(pMarker, lengthRemaining, "%c,%02d,%.1f,", + gpsQuality, svUsedCount, locationExtended.hdop); + } + else if (loc_eng_data_p->pdop > 0 && loc_eng_data_p->hdop > 0 && loc_eng_data_p->vdop > 0) + { // dop was cached from sv report (RPC) + length = snprintf(pMarker, lengthRemaining, "%c,%02d,%.1f,", + gpsQuality, svUsedCount, loc_eng_data_p->hdop); + } + else + { // no hdop + length = snprintf(pMarker, lengthRemaining, "%c,%02d,,", + gpsQuality, svUsedCount); + } + + if (length < 0 || length >= lengthRemaining) + { + LOC_LOGE("NMEA Error in string formatting"); + return; + } + pMarker += length; + lengthRemaining -= length; + + if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_ALTITUDE_MEAN_SEA_LEVEL) + { + length = snprintf(pMarker, lengthRemaining, "%.1lf,M,", + locationExtended.altitudeMeanSeaLevel); + } + else + { + length = snprintf(pMarker, lengthRemaining,",,"); + } + + if (length < 0 || length >= lengthRemaining) + { + LOC_LOGE("NMEA Error in string formatting"); + return; + } + pMarker += length; + lengthRemaining -= length; + + if ((location.gpsLocation.flags & GPS_LOCATION_HAS_ALTITUDE) && + (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_ALTITUDE_MEAN_SEA_LEVEL)) + { + length = snprintf(pMarker, lengthRemaining, "%.1lf,M,,", + location.gpsLocation.altitude - locationExtended.altitudeMeanSeaLevel); + } + else + { + length = snprintf(pMarker, lengthRemaining,",,,"); + } + + length = loc_eng_nmea_put_checksum(sentence, sizeof(sentence)); + loc_eng_nmea_send(sentence, length, loc_eng_data_p); + + } + //Send blank NMEA reports for non-final fixes + else { + strlcpy(sentence, "$GPGSA,A,1,,,,,,,,,,,,,,,", sizeof(sentence)); + length = loc_eng_nmea_put_checksum(sentence, sizeof(sentence)); + loc_eng_nmea_send(sentence, length, loc_eng_data_p); + + strlcpy(sentence, "$GPVTG,,T,,M,,N,,K,N", sizeof(sentence)); + length = loc_eng_nmea_put_checksum(sentence, sizeof(sentence)); + loc_eng_nmea_send(sentence, length, loc_eng_data_p); + + strlcpy(sentence, "$GPRMC,,V,,,,,,,,,,N", sizeof(sentence)); + length = loc_eng_nmea_put_checksum(sentence, sizeof(sentence)); + loc_eng_nmea_send(sentence, length, loc_eng_data_p); + + strlcpy(sentence, "$GPGGA,,,,,,0,,,,,,,,", sizeof(sentence)); + length = loc_eng_nmea_put_checksum(sentence, sizeof(sentence)); + loc_eng_nmea_send(sentence, length, loc_eng_data_p); + } + // clear the dop cache so they can't be used again + loc_eng_data_p->pdop = 0; + loc_eng_data_p->hdop = 0; + loc_eng_data_p->vdop = 0; + + EXIT_LOG(%d, 0); +} + + + +/*=========================================================================== +FUNCTION loc_eng_nmea_generate_sv + +DESCRIPTION + Generate NMEA sentences generated based on sv report + +DEPENDENCIES + NONE + +RETURN VALUE + 0 + +SIDE EFFECTS + N/A + +===========================================================================*/ +void loc_eng_nmea_generate_sv(loc_eng_data_s_type *loc_eng_data_p, + const GnssSvStatus &svStatus, const GpsLocationExtended &locationExtended) +{ + ENTRY_LOG(); + + char sentence[NMEA_SENTENCE_MAX_LENGTH] = {0}; + char* pMarker = sentence; + int lengthRemaining = sizeof(sentence); + int length = 0; + int svCount = svStatus.num_svs; + int sentenceCount = 0; + int sentenceNumber = 1; + int svNumber = 1; + int gpsCount = 0; + int glnCount = 0; + + //Count GPS SVs for saparating GPS from GLONASS and throw others + + for(svNumber=1; svNumber <= svCount; svNumber++) { + if( (svStatus.sv_list[svNumber-1].prn >= GPS_PRN_START)&& + (svStatus.sv_list[svNumber-1].prn <= GPS_PRN_END) ) + { + gpsCount++; + } + else if( (svStatus.sv_list[svNumber-1].prn >= GLONASS_PRN_START) && + (svStatus.sv_list[svNumber-1].prn <= GLONASS_PRN_END) ) + { + glnCount++; + } + } + + // ------------------ + // ------$GPGSV------ + // ------------------ + + if (gpsCount <= 0) + { + // no svs in view, so just send a blank $GPGSV sentence + strlcpy(sentence, "$GPGSV,1,1,0,", sizeof(sentence)); + length = loc_eng_nmea_put_checksum(sentence, sizeof(sentence)); + loc_eng_nmea_send(sentence, length, loc_eng_data_p); + } + else + { + svNumber = 1; + sentenceNumber = 1; + sentenceCount = gpsCount/4 + (gpsCount % 4 != 0); + + while (sentenceNumber <= sentenceCount) + { + pMarker = sentence; + lengthRemaining = sizeof(sentence); + + length = snprintf(pMarker, lengthRemaining, "$GPGSV,%d,%d,%02d", + sentenceCount, sentenceNumber, gpsCount); + + if (length < 0 || length >= lengthRemaining) + { + LOC_LOGE("NMEA Error in string formatting"); + return; + } + pMarker += length; + lengthRemaining -= length; + + for (int i=0; (svNumber <= svCount) && (i < 4); svNumber++) + { + if( (svStatus.sv_list[svNumber-1].prn >= GPS_PRN_START) && + (svStatus.sv_list[svNumber-1].prn <= GPS_PRN_END) ) + { + length = snprintf(pMarker, lengthRemaining,",%02d,%02d,%03d,", + svStatus.sv_list[svNumber-1].prn, + (int)(0.5 + svStatus.sv_list[svNumber-1].elevation), //float to int + (int)(0.5 + svStatus.sv_list[svNumber-1].azimuth)); //float to int + + if (length < 0 || length >= lengthRemaining) + { + LOC_LOGE("NMEA Error in string formatting"); + return; + } + pMarker += length; + lengthRemaining -= length; + + if (svStatus.sv_list[svNumber-1].snr > 0) + { + length = snprintf(pMarker, lengthRemaining,"%02d", + (int)(0.5 + svStatus.sv_list[svNumber-1].snr)); //float to int + + if (length < 0 || length >= lengthRemaining) + { + LOC_LOGE("NMEA Error in string formatting"); + return; + } + pMarker += length; + lengthRemaining -= length; + } + + i++; + } + + } + + length = loc_eng_nmea_put_checksum(sentence, sizeof(sentence)); + loc_eng_nmea_send(sentence, length, loc_eng_data_p); + sentenceNumber++; + + } //while + + } //if + + // ------------------ + // ------$GLGSV------ + // ------------------ + + if (glnCount <= 0) + { + // no svs in view, so just send a blank $GLGSV sentence + strlcpy(sentence, "$GLGSV,1,1,0,", sizeof(sentence)); + length = loc_eng_nmea_put_checksum(sentence, sizeof(sentence)); + loc_eng_nmea_send(sentence, length, loc_eng_data_p); + } + else + { + svNumber = 1; + sentenceNumber = 1; + sentenceCount = glnCount/4 + (glnCount % 4 != 0); + + while (sentenceNumber <= sentenceCount) + { + pMarker = sentence; + lengthRemaining = sizeof(sentence); + + length = snprintf(pMarker, lengthRemaining, "$GLGSV,%d,%d,%02d", + sentenceCount, sentenceNumber, glnCount); + + if (length < 0 || length >= lengthRemaining) + { + LOC_LOGE("NMEA Error in string formatting"); + return; + } + pMarker += length; + lengthRemaining -= length; + + for (int i=0; (svNumber <= svCount) && (i < 4); svNumber++) + { + if( (svStatus.sv_list[svNumber-1].prn >= GLONASS_PRN_START) && + (svStatus.sv_list[svNumber-1].prn <= GLONASS_PRN_END) ) { + + length = snprintf(pMarker, lengthRemaining,",%02d,%02d,%03d,", + svStatus.sv_list[svNumber-1].prn, + (int)(0.5 + svStatus.sv_list[svNumber-1].elevation), //float to int + (int)(0.5 + svStatus.sv_list[svNumber-1].azimuth)); //float to int + + if (length < 0 || length >= lengthRemaining) + { + LOC_LOGE("NMEA Error in string formatting"); + return; + } + pMarker += length; + lengthRemaining -= length; + + if (svStatus.sv_list[svNumber-1].snr > 0) + { + length = snprintf(pMarker, lengthRemaining,"%02d", + (int)(0.5 + svStatus.sv_list[svNumber-1].snr)); //float to int + + if (length < 0 || length >= lengthRemaining) + { + LOC_LOGE("NMEA Error in string formatting"); + return; + } + pMarker += length; + lengthRemaining -= length; + } + + i++; + } + + } + + length = loc_eng_nmea_put_checksum(sentence, sizeof(sentence)); + loc_eng_nmea_send(sentence, length, loc_eng_data_p); + sentenceNumber++; + + } //while + + }//if + + // cache the used in fix mask, as it will be needed to send $GPGSA + // during the position report + loc_eng_data_p->sv_used_mask = svStatus.gps_used_in_fix_mask; + + // For RPC, the DOP are sent during sv report, so cache them + // now to be sent during position report. + // For QMI, the DOP will be in position report. + if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_DOP) + { + loc_eng_data_p->pdop = locationExtended.pdop; + loc_eng_data_p->hdop = locationExtended.hdop; + loc_eng_data_p->vdop = locationExtended.vdop; + } + else + { + loc_eng_data_p->pdop = 0; + loc_eng_data_p->hdop = 0; + loc_eng_data_p->vdop = 0; + } + + EXIT_LOG(%d, 0); +} diff --git a/gps/loc_api/libloc_api_50001/loc_eng_nmea.h b/gps/loc_api/libloc_api_50001/loc_eng_nmea.h new file mode 100644 index 000000000..066943aa2 --- /dev/null +++ b/gps/loc_api/libloc_api_50001/loc_eng_nmea.h @@ -0,0 +1,43 @@ +/* Copyright (c) 2012, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef LOC_ENG_NMEA_H +#define LOC_ENG_NMEA_H + +#include +#include + +#define NMEA_SENTENCE_MAX_LENGTH 200 + +void loc_eng_nmea_send(char *pNmea, int length, loc_eng_data_s_type *loc_eng_data_p); +int loc_eng_nmea_put_checksum(char *pNmea, int maxSize); +void loc_eng_nmea_generate_sv(loc_eng_data_s_type *loc_eng_data_p, const GnssSvStatus &svStatus, const GpsLocationExtended &locationExtended); +void loc_eng_nmea_generate_pos(loc_eng_data_s_type *loc_eng_data_p, const UlpLocation &location, const GpsLocationExtended &locationExtended, unsigned char generate_nmea); + +#endif // LOC_ENG_NMEA_H diff --git a/gps/loc_api/libloc_api_50001/loc_eng_xtra.cpp b/gps/loc_api/libloc_api_50001/loc_eng_xtra.cpp new file mode 100644 index 000000000..7bb808390 --- /dev/null +++ b/gps/loc_api/libloc_api_50001/loc_eng_xtra.cpp @@ -0,0 +1,213 @@ +/* Copyright (c) 2009-2013, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#define LOG_NDDEBUG 0 +#define LOG_TAG "LocSvc_eng" + +#include +#include +#include "log_util.h" +#include "platform_lib_includes.h" + +using namespace loc_core; + +struct LocEngRequestXtraServer : public LocMsg { + LocEngAdapter* mAdapter; + inline LocEngRequestXtraServer(LocEngAdapter* adapter) : + LocMsg(), mAdapter(adapter) + { + locallog(); + } + inline virtual void proc() const { + mAdapter->requestXtraServer(); + } + inline void locallog() const { + LOC_LOGV("LocEngRequestXtraServer"); + } + inline virtual void log() const { + locallog(); + } +}; + +struct LocEngInjectXtraData : public LocMsg { + LocEngAdapter* mAdapter; + char* mData; + const int mLen; + inline LocEngInjectXtraData(LocEngAdapter* adapter, + char* data, int len): + LocMsg(), mAdapter(adapter), + mData(new char[len]), mLen(len) + { + memcpy((void*)mData, (void*)data, len); + locallog(); + } + inline ~LocEngInjectXtraData() + { + delete[] mData; + } + inline virtual void proc() const { + mAdapter->setXtraData(mData, mLen); + } + inline void locallog() const { + LOC_LOGV("length: %d\n data: %p", mLen, mData); + } + inline virtual void log() const { + locallog(); + } +}; + +struct LocEngSetXtraVersionCheck : public LocMsg { + LocEngAdapter *mAdapter; + int mCheck; + inline LocEngSetXtraVersionCheck(LocEngAdapter* adapter, + int check): + mAdapter(adapter), mCheck(check) {} + inline virtual void proc() const { + locallog(); + mAdapter->setXtraVersionCheck(mCheck); + } + inline void locallog() const { + LOC_LOGD("%s:%d]: mCheck: %d", + __func__, __LINE__, mCheck); + } + inline virtual void log() const { + locallog(); + } +}; + +/*=========================================================================== +FUNCTION loc_eng_xtra_init + +DESCRIPTION + Initialize XTRA module. + +DEPENDENCIES + N/A + +RETURN VALUE + 0: success + +SIDE EFFECTS + N/A + +===========================================================================*/ +int loc_eng_xtra_init (loc_eng_data_s_type &loc_eng_data, + GpsXtraExtCallbacks* callbacks) +{ + int ret_val = -1; + loc_eng_xtra_data_s_type *xtra_module_data_ptr; + ENTRY_LOG(); + + if(callbacks == NULL) { + LOC_LOGE("loc_eng_xtra_init: failed, cb is NULL"); + } else { + xtra_module_data_ptr = &loc_eng_data.xtra_module_data; + xtra_module_data_ptr->download_request_cb = callbacks->download_request_cb; + xtra_module_data_ptr->report_xtra_server_cb = callbacks->report_xtra_server_cb; + + ret_val = 0; + } + EXIT_LOG(%d, ret_val); + return ret_val; +} + +/*=========================================================================== +FUNCTION loc_eng_xtra_inject_data + +DESCRIPTION + Injects XTRA file into the engine but buffers the data if engine is busy. + +DEPENDENCIES + N/A + +RETURN VALUE + 0 + +SIDE EFFECTS + N/A + +===========================================================================*/ +int loc_eng_xtra_inject_data(loc_eng_data_s_type &loc_eng_data, + char* data, int length) +{ + ENTRY_LOG(); + LocEngAdapter* adapter = loc_eng_data.adapter; + adapter->sendMsg(new LocEngInjectXtraData(adapter, data, length)); + EXIT_LOG(%d, 0); + return 0; +} +/*=========================================================================== +FUNCTION loc_eng_xtra_request_server + +DESCRIPTION + Request the Xtra server url from the modem + +DEPENDENCIES + N/A + +RETURN VALUE + 0 + +SIDE EFFECTS + N/A + +===========================================================================*/ +int loc_eng_xtra_request_server(loc_eng_data_s_type &loc_eng_data) +{ + ENTRY_LOG(); + LocEngAdapter* adapter = loc_eng_data.adapter; + adapter->sendMsg(new LocEngRequestXtraServer(adapter)); + EXIT_LOG(%d, 0); + return 0; +} +/*=========================================================================== +FUNCTION loc_eng_xtra_version_check + +DESCRIPTION + Injects the enable/disable value for checking XTRA version + that is specified in gps.conf + +DEPENDENCIES + N/A + +RETURN VALUE + none + +SIDE EFFECTS + N/A + +===========================================================================*/ +void loc_eng_xtra_version_check(loc_eng_data_s_type &loc_eng_data, + int check) +{ + ENTRY_LOG(); + LocEngAdapter *adapter = loc_eng_data.adapter; + adapter->sendMsg(new LocEngSetXtraVersionCheck(adapter, check)); + EXIT_LOG(%d, 0); +} diff --git a/gps/loc_api/libloc_api_50001/loc_eng_xtra.h b/gps/loc_api/libloc_api_50001/loc_eng_xtra.h new file mode 100644 index 000000000..175f497df --- /dev/null +++ b/gps/loc_api/libloc_api_50001/loc_eng_xtra.h @@ -0,0 +1,47 @@ +/* Copyright (c) 2009,2011 The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef LOC_ENG_XTRA_H +#define LOC_ENG_XTRA_H + +#include + +// Module data +typedef struct +{ + // loc_eng_ioctl_cb_data_s_type ioctl_cb_data; + gps_xtra_download_request download_request_cb; + report_xtra_server report_xtra_server_cb; + + // XTRA data buffer + char *xtra_data_for_injection; // NULL if no pending data + int xtra_data_len; +} loc_eng_xtra_data_s_type; + +#endif // LOC_ENG_XTRA_H diff --git a/gps/utils/Android.mk b/gps/utils/Android.mk new file mode 100644 index 000000000..103e52429 --- /dev/null +++ b/gps/utils/Android.mk @@ -0,0 +1,69 @@ +ifneq ($(BUILD_TINY_ANDROID),true) +#Compile this library only for builds with the latest modem image + +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +## Libs +LOCAL_SHARED_LIBRARIES := \ + libutils \ + libcutils \ + liblog + +LOCAL_SRC_FILES += \ + loc_log.cpp \ + loc_cfg.cpp \ + msg_q.c \ + linked_list.c \ + loc_target.cpp \ + platform_lib_abstractions/elapsed_millis_since_boot.cpp \ + LocHeap.cpp \ + LocTimer.cpp \ + LocThread.cpp \ + MsgTask.cpp \ + loc_misc_utils.cpp + +LOCAL_CFLAGS += \ + -fno-short-enums \ + -D_ANDROID_ \ + -std=c++11 + +ifeq ($(TARGET_BUILD_VARIANT),user) + LOCAL_CFLAGS += -DTARGET_BUILD_VARIANT_USER +endif + +LOCAL_LDFLAGS += -Wl,--export-dynamic + +## Includes +LOCAL_C_INCLUDES:= \ + $(LOCAL_PATH)/platform_lib_abstractions + +LOCAL_COPY_HEADERS_TO:= gps.utils/ +LOCAL_COPY_HEADERS:= \ + loc_log.h \ + loc_cfg.h \ + log_util.h \ + linked_list.h \ + msg_q.h \ + MsgTask.h \ + LocHeap.h \ + LocThread.h \ + LocTimer.h \ + loc_target.h \ + loc_timer.h \ + LocSharedLock.h \ + platform_lib_abstractions/platform_lib_includes.h \ + platform_lib_abstractions/platform_lib_time.h \ + platform_lib_abstractions/platform_lib_macros.h \ + loc_misc_utils.h + +LOCAL_MODULE := libgps.utils +LOCAL_CLANG := false + +LOCAL_MODULE_TAGS := optional + +LOCAL_PRELINK_MODULE := false + +include $(BUILD_SHARED_LIBRARY) +endif # not BUILD_TINY_ANDROID diff --git a/gps/utils/LocHeap.cpp b/gps/utils/LocHeap.cpp new file mode 100644 index 000000000..d667f14f9 --- /dev/null +++ b/gps/utils/LocHeap.cpp @@ -0,0 +1,354 @@ +/* Copyright (c) 2015, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include + +class LocHeapNode { + friend class LocHeap; + + // size of of the subtree, excluding self, 1 if no subtree + int mSize; + LocHeapNode* mLeft; + LocHeapNode* mRight; + LocRankable* mData; +public: + inline LocHeapNode(LocRankable& data) : + mSize(1), mLeft(NULL), mRight(NULL), mData(&data) {} + ~LocHeapNode(); + + // this only swaps the data of the two nodes, so no + // detach / re-attached is necessary + void swap(LocHeapNode& node); + + LocRankable* detachData(); + + // push a node into the tree stucture, keeping sorted by rank + void push(LocHeapNode& node); + + // pop the head node out of the tree stucture. keeping sorted by rank + static LocHeapNode* pop(LocHeapNode*& top); + + // remove a specific node from the tree + // returns the pointer to the node removed, which would be either the + // same as input (if successfully removed); or NULL (if failed). + static LocHeapNode* remove(LocHeapNode*& top, LocRankable& data); + + // convenience method to compare data ranking + inline bool outRanks(LocHeapNode& node) { return mData->outRanks(*node.mData); } + inline bool outRanks(LocRankable& data) { return mData->outRanks(data); } + + // checks if mSize is correct, AND this node is the highest ranking + // of the entire subtree + bool checkNodes(); + + inline int getSize() { return mSize; } +}; + +inline +LocHeapNode::~LocHeapNode() { + if (mLeft) { + delete mLeft; + mLeft = NULL; + } + if (mRight) { + delete mRight; + mRight = NULL; + } + if (mData) { + mData = NULL; + } +} + +inline +void LocHeapNode::swap(LocHeapNode& node) { + LocRankable* tmpData = node.mData; + node.mData = mData; + mData = tmpData; +} + +inline +LocRankable* LocHeapNode::detachData() { + LocRankable* data = mData; + mData = NULL; + return data; +} + +// push keeps the tree sorted by rank, it also tries to balance the +// tree by adding the new node to the smaller of the subtrees. +// The pointer to the tree and internal links never change. If the +// mData of tree top ranks lower than that of the incoming node, +// mData will be swapped with that of the incoming node to ensure +// ranking, no restructuring the container nodes. +void LocHeapNode::push(LocHeapNode& node) { + // ensure the current node ranks higher than in the incoming one + if (node.outRanks(*this)) { + swap(node); + } + + // now drop the new node (ensured lower than *this) into a subtree + if (NULL == mLeft) { + mLeft = &node; + } else if (NULL == mRight) { + mRight = &node; + } else if (mLeft->mSize <= mRight->mSize) { + mLeft->push(node); + } else { + mRight->push(node); + } + mSize++; +} + +// pop keeps the tree sorted by rank, but it does not try to balance +// the tree. It recursively swaps with the higher ranked top of the +// subtrees. +// The return is a popped out node from leaf level, that has the data +// swapped all the way down from the top. The pinter to the tree and +// internal links will not be changed or restructured, except for the +// node that is popped out. +// If the return pointer == this, this the last node in the tree. +LocHeapNode* LocHeapNode::pop(LocHeapNode*& top) { + // we know the top has the highest ranking at this point, else + // the tree is broken. This top will be popped out. But we need + // a node from the left or right child, whichever ranks higher, + // to replace the current top. This then will need to be done + // recursively to the leaf level. So we swap the mData of the + // current top node all the way down to the leaf level. + LocHeapNode* poppedNode = top; + // top is losing a node in its subtree + top->mSize--; + if (top->mLeft || top->mRight) { + // if mLeft is NULL, mRight for sure is NOT NULL, take that; + // else if mRight is NULL, mLeft for sure is NOT, take that; + // else we take the address of whatever has higher ranking mData + LocHeapNode*& subTop = (NULL == top->mLeft) ? top->mRight : + ((NULL == top->mRight) ? top->mLeft : + (top->mLeft->outRanks(*(top->mRight)) ? top->mLeft : top->mRight)); + // swap mData, the tree top gets updated with the new data. + top->swap(*subTop); + // pop out from the subtree + poppedNode = pop(subTop); + } else { + // if the top has only single node + // detach the poppedNode from the tree + // subTop is the reference of ether mLeft or mRight + // NOT a local stack pointer. so it MUST be NULL'ed here. + top = NULL; + } + + return poppedNode; +} + +// navigating through the tree and find the node that hass the input +// data. Since this is a heap, we do recursive linear search. +// returns the pointer to the node removed, which would be either the +// same as input (if successfully removed); or NULL (if failed). +LocHeapNode* LocHeapNode::remove(LocHeapNode*& top, LocRankable& data) { + LocHeapNode* removedNode = NULL; + // this is the node, by address + if (&data == (LocRankable*)(top->mData)) { + // pop this node out + removedNode = pop(top); + } else if (!data.outRanks(*top->mData)) { + // subtrees might have this node + if (top->mLeft) { + removedNode = remove(top->mLeft, data); + } + // if we did not find in mLeft, and mRight is not empty + if (!removedNode && top->mRight) { + removedNode = remove(top->mRight, data); + } + + // top lost a node in its subtree + if (removedNode) { + top->mSize--; + } + } + + return removedNode; +} + +// checks if mSize is correct, AND this node is the highest ranking +// of the entire subtree +bool LocHeapNode::checkNodes() { + // size of the current subtree + int totalSize = mSize; + if (mLeft) { + // check the consistency of left subtree + if (mLeft->outRanks(*this) || !mLeft->checkNodes()) { + return false; + } + // subtract the size of left subtree (with subtree head) + totalSize -= mLeft->mSize; + } + + if (mRight) { + // check the consistency of right subtree + if (mRight->outRanks(*this) || !mRight->checkNodes()) { + return false; + } + // subtract the size of right subtree (with subtree head) + totalSize -= mRight->mSize; + } + + // for the tree nodes to consistent, totalSize must be 1 now + return totalSize == 1; +} + +LocHeap::~LocHeap() { + if (mTree) { + delete mTree; + } +} + +void LocHeap::push(LocRankable& node) { + LocHeapNode* heapNode = new LocHeapNode(node); + if (!mTree) { + mTree = heapNode; + } else { + mTree->push(*heapNode); + } +} + +LocRankable* LocHeap::peek() { + LocRankable* top = NULL; + if (mTree) { + top = mTree->mData; + } + return top; +} + +LocRankable* LocHeap::pop() { + LocRankable* locNode = NULL; + if (mTree) { + // mTree may become NULL after this call + LocHeapNode* heapNode = LocHeapNode::pop(mTree); + locNode = heapNode->detachData(); + delete heapNode; + } + return locNode; +} + +LocRankable* LocHeap::remove(LocRankable& rankable) { + LocRankable* locNode = NULL; + if (mTree) { + // mTree may become NULL after this call + LocHeapNode* heapNode = LocHeapNode::remove(mTree, rankable); + if (heapNode) { + locNode = heapNode->detachData(); + delete heapNode; + } + } + return locNode; +} + +#ifdef __LOC_UNIT_TEST__ +bool LocHeap::checkTree() { + return ((NULL == mTree) || mTree->checkNodes()); +} +uint32_t LocHeap::getTreeSize() { + return (NULL == mTree) ? 0 : mTree->getSize(); +} +#endif + +#ifdef __LOC_DEBUG__ + +#include +#include +#include + +class LocHeapDebug : public LocHeap { +public: + bool checkTree() { + return ((NULL == mTree) || mTree->checkNodes()); + } + + uint32_t getTreeSize() { + return (NULL == mTree) ? 0 : (mTree->getSize()); + } +}; + +class LocHeapDebugData : public LocRankable { + const int mID; +public: + LocHeapDebugData(int id) : mID(id) {} + inline virtual int ranks(LocRankable& rankable) { + LocHeapDebugData* testData = dynamic_cast(&rankable); + return testData->mID - mID; + } +}; + +// For Linux command line testing: +// compilation: g++ -D__LOC_HOST_DEBUG__ -D__LOC_DEBUG__ -g -I. -I../../../../vendor/qcom/proprietary/gps-internal/unit-tests/fakes_for_host -I../../../../system/core/include LocHeap.cpp +// test: valgrind --leak-check=full ./a.out 100 +int main(int argc, char** argv) { + srand(time(NULL)); + int tries = atoi(argv[1]); + int checks = tries >> 3; + LocHeapDebug heap; + int treeSize = 0; + + for (int i = 0; i < tries; i++) { + if (i % checks == 0 && !heap.checkTree()) { + printf("tree check failed before %dth op\n", i); + } + int r = rand(); + + if (r & 1) { + LocHeapDebugData* data = new LocHeapDebugData(r >> 1); + heap.push(dynamic_cast(*data)); + treeSize++; + } else { + LocRankable* rankable = heap.pop(); + if (rankable) { + delete rankable; + } + treeSize ? treeSize-- : 0; + } + + printf("%s: %d == %d\n", (r&1)?"push":"pop", treeSize, heap.getTreeSize()); + if (treeSize != heap.getTreeSize()) { + printf("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); + tries = i+1; + break; + } + } + + if (!heap.checkTree()) { + printf("!!!!!!!!!!tree check failed at the end after %d ops!!!!!!!\n", tries); + } else { + printf("success!\n"); + } + + for (LocRankable* data = heap.pop(); NULL != data; data = heap.pop()) { + delete data; + } + + return 0; +} + +#endif diff --git a/gps/utils/LocHeap.h b/gps/utils/LocHeap.h new file mode 100644 index 000000000..b491948a2 --- /dev/null +++ b/gps/utils/LocHeap.h @@ -0,0 +1,96 @@ +/* Copyright (c) 2015, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef __LOC_HEAP__ +#define __LOC_HEAP__ + +#include +#include + +// abstract class to be implemented by client to provide a rankable class +class LocRankable { +public: + virtual inline ~LocRankable() {} + + // method to rank objects of such type for sorting purposes. + // The pointer of the input node would be stored in the heap. + // >0 if ranks higher than the input; + // ==0 if equally ranks with the input; + // <0 if ranks lower than the input + virtual int ranks(LocRankable& rankable) = 0; + + // convenient method to rank objects of such type for sorting purposes. + inline bool outRanks(LocRankable& rankable) { return ranks(rankable) > 0; } +}; + +// opaque class to provide service implementation. +class LocHeapNode; + +// a heap whose left and right children are not sorted. It is sorted only vertically, +// i.e. parent always ranks higher than children, if they exist. Ranking algorithm is +// implemented in Rankable. The reason that there is no sort between children is to +// help beter balance the tree with lower cost. When a node is pushed to the tree, +// it is guaranteed that the subtree that is smaller gets to have the new node. +class LocHeap { +protected: + LocHeapNode* mTree; +public: + inline LocHeap() : mTree(NULL) {} + ~LocHeap(); + + // push keeps the tree sorted by rank, it also tries to balance the + // tree by adding the new node to the smaller of the subtrees. + // node is reference to an obj that is managed by client, that client + // creates and destroyes. The destroy should happen after the + // node is popped out from the heap. + void push(LocRankable& node); + + // Peeks the node data on tree top, which has currently the highest ranking + // There is no change the tree structure with this operation + // Returns NULL if the tree is empty, otherwise pointer to the node data of + // the tree top. + LocRankable* peek(); + + // pop keeps the tree sorted by rank, but it does not try to balance + // the tree. + // Return - pointer to the node popped out, or NULL if heap is already empty + LocRankable* pop(); + + // navigating through the tree and find the node that ranks the same + // as the input data, then remove it from the tree. Rank is implemented + // by rankable obj. + // returns the pointer to the node removed; or NULL (if failed). + LocRankable* remove(LocRankable& rankable); + +#ifdef __LOC_UNIT_TEST__ + bool checkTree(); + uint32_t getTreeSize(); +#endif +}; + +#endif //__LOC_HEAP__ diff --git a/gps/utils/LocSharedLock.h b/gps/utils/LocSharedLock.h new file mode 100644 index 000000000..6b9e27f18 --- /dev/null +++ b/gps/utils/LocSharedLock.h @@ -0,0 +1,58 @@ +/* Copyright (c) 2015, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef __LOC_SHARED_LOCK__ +#define __LOC_SHARED_LOCK__ + +#include +#include + +// This is a utility created for use cases such that there are more than +// one client who need to share the same lock, but it is not predictable +// which of these clients is to last to go away. This shared lock deletes +// itself when the last client calls its drop() method. To add a cient, +// this share lock's share() method has to be called, so that the obj +// can maintain an accurate client count. +class LocSharedLock { + uint32_t mRef; + pthread_mutex_t mMutex; + inline ~LocSharedLock() { pthread_mutex_destroy(&mMutex); } +public: + // first client to create this LockSharedLock + inline LocSharedLock() : mRef(1) { pthread_mutex_init(&mMutex, NULL); } + // following client(s) are to *share()* this lock created by the first client + inline LocSharedLock* share() { mRef++; return this; } + // whe a client no longer needs this shared lock, drop() shall be called. + inline void drop() { if (0 == --mRef) delete this; } + // locking the lock to enter critical section + inline void lock() { pthread_mutex_lock(&mMutex); } + // unlocking the lock to leave the critical section + inline void unlock() { pthread_mutex_unlock(&mMutex); } +}; + +#endif //__LOC_SHARED_LOCK__ diff --git a/gps/utils/LocThread.cpp b/gps/utils/LocThread.cpp new file mode 100644 index 000000000..19bf101a9 --- /dev/null +++ b/gps/utils/LocThread.cpp @@ -0,0 +1,264 @@ +/* Copyright (c) 2015, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include +#include +#include + +class LocThreadDelegate { + LocRunnable* mRunnable; + bool mJoinable; + pthread_t mThandle; + pthread_mutex_t mMutex; + int mRefCount; + ~LocThreadDelegate(); + LocThreadDelegate(LocThread::tCreate creator, const char* threadName, + LocRunnable* runnable, bool joinable); + void destroy(); +public: + static LocThreadDelegate* create(LocThread::tCreate creator, + const char* threadName, LocRunnable* runnable, bool joinable); + void stop(); + // bye() is for the parent thread to go away. if joinable, + // parent must stop the spawned thread, join, and then + // destroy(); if detached, the parent can go straight + // ahead to destroy() + inline void bye() { mJoinable ? stop() : destroy(); } + inline bool isRunning() { return (NULL != mRunnable); } + static void* threadMain(void* arg); +}; + +// it is important to note that internal members must be +// initialized to values as if pthread_create succeeds. +// This is to avoid the race condition between the threads, +// once the thread is created, some of these values will +// be check in the spawned thread, and must set correctly +// then and there. +// However, upon pthread_create failure, the data members +// must be set to indicate failure, e.g. mRunnable, and +// threashold approprietly for destroy(), e.g. mRefCount. +LocThreadDelegate::LocThreadDelegate(LocThread::tCreate creator, + const char* threadName, LocRunnable* runnable, bool joinable) : + mRunnable(runnable), mJoinable(joinable), mThandle(NULL), + mMutex(PTHREAD_MUTEX_INITIALIZER), mRefCount(2) { + + // set up thread name, if nothing is passed in + if (!threadName) { + threadName = "LocThread"; + } + + // create the thread here, then if successful + // and a name is given, we set the thread name + if (creator) { + mThandle = creator(threadName, threadMain, this); + } else if (pthread_create(&mThandle, NULL, threadMain, this)) { + // pthread_create() failed + mThandle = NULL; + } + + if (mThandle) { + // set thread name + char lname[16]; + int len = sizeof(lname) - 1; + memcpy(lname, threadName, len); + lname[len] = 0; + // set the thread name here + pthread_setname_np(mThandle, lname); + + // detach, if not joinable + if (!joinable) { + pthread_detach(mThandle); + } + } else { + // must set these values upon failure + mRunnable = NULL; + mJoinable = false; + mRefCount = 1; + } +} + +inline +LocThreadDelegate::~LocThreadDelegate() { + // at this point nothing should need done any more +} + +// factory method so that we could return NULL upon failure +LocThreadDelegate* LocThreadDelegate::create(LocThread::tCreate creator, + const char* threadName, LocRunnable* runnable, bool joinable) { + LocThreadDelegate* thread = NULL; + if (runnable) { + thread = new LocThreadDelegate(creator, threadName, runnable, joinable); + if (thread && !thread->isRunning()) { + thread->destroy(); + thread = NULL; + } + } + + return thread; +} + +// The order is importang +// NULLing mRunnalbe stops the while loop in threadMain() +// join() if mJoinble must come before destroy() call, as +// the obj must remain alive at this time so that mThandle +// remains valud. +void LocThreadDelegate::stop() { + // mRunnable and mJoinable are reset on different triggers. + // mRunnable may get nulled on the spawned thread's way out; + // or here. + // mJouinable (if ever been true) gets falsed when client + // thread triggers stop, with either a stop() + // call or the client releases thread obj handle. + if (mRunnable) { + mRunnable = NULL; + } + if (mJoinable) { + mJoinable = false; + pthread_join(mThandle, NULL); + } + // call destroy() to possibly delete the obj + destroy(); +} + +// method for clients to call to release the obj +// when it is a detached thread, the client thread +// and the spawned thread can both try to destroy() +// asynchronously. And we delete this obj when +// mRefCount becomes 0. +void LocThreadDelegate::destroy() { + // else case shouldn't happen, unless there is a + // leaking obj. But only our code here has such + // obj, so if we test our code well, else case + // will never happen + if (mRefCount > 0) { + // we need a flag on the stack + bool callDelete = false; + + // critical section between threads + pthread_mutex_lock(&mMutex); + // last destroy() call + callDelete = (1 == mRefCount--); + pthread_mutex_unlock(&mMutex); + + // upon last destroy() call we delete this obj + if (callDelete) { + delete this; + } + } +} + +void* LocThreadDelegate::threadMain(void* arg) { + LocThreadDelegate* locThread = (LocThreadDelegate*)(arg); + + if (locThread) { + LocRunnable* runnable = locThread->mRunnable; + + if (runnable) { + if (locThread->isRunning()) { + runnable->prerun(); + } + + while (locThread->isRunning() && runnable->run()); + + if (locThread->isRunning()) { + runnable->postrun(); + } + + // at this time, locThread->mRunnable may or may not be NULL + // NULL it just to be safe and clean, as we want the field + // in the released memory slot to be NULL. + locThread->mRunnable = NULL; + delete runnable; + } + locThread->destroy(); + } + + return NULL; +} + +LocThread::~LocThread() { + if (mThread) { + mThread->bye(); + mThread = NULL; + } +} + +bool LocThread::start(tCreate creator, const char* threadName, LocRunnable* runnable, bool joinable) { + bool success = false; + if (!mThread) { + mThread = LocThreadDelegate::create(creator, threadName, runnable, joinable); + // true only if thread is created successfully + success = (NULL != mThread); + } + return success; +} + +void LocThread::stop() { + if (mThread) { + mThread->stop(); + mThread = NULL; + } +} + +#ifdef __LOC_DEBUG__ + +#include +#include +#include + +class LocRunnableTest1 : public LocRunnable { + int mID; +public: + LocRunnableTest1(int id) : LocRunnable(), mID(id) {} + virtual bool run() { + printf("LocRunnableTest1: %d\n", mID++); + sleep(1); + return true; + } +}; + +// on linux command line: +// compile: g++ -D__LOC_HOST_DEBUG__ -D__LOC_DEBUG__ -g -std=c++0x -I. -I../../../../vendor/qcom/proprietary/gps-internal/unit-tests/fakes_for_host -I../../../../system/core/include -lpthread LocThread.cpp +// test detached thread: valgrind ./a.out 0 +// test joinable thread: valgrind ./a.out 1 +int main(int argc, char** argv) { + LocRunnableTest1 test(10); + + LocThread thread; + thread.start("LocThreadTest", test, atoi(argv[1])); + + sleep(10); + + thread.stop(); + + sleep(5); + + return 0; +} + +#endif diff --git a/gps/utils/LocThread.h b/gps/utils/LocThread.h new file mode 100644 index 000000000..2a65d8fa6 --- /dev/null +++ b/gps/utils/LocThread.h @@ -0,0 +1,92 @@ +/* Copyright (c) 2015, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef __LOC_THREAD__ +#define __LOC_THREAD__ + +#include +#include + +// abstract class to be implemented by client to provide a runnable class +// which gets scheduled by LocThread +class LocRunnable { +public: + inline LocRunnable() {} + inline virtual ~LocRunnable() {} + + // The method to be implemented by thread clients + // and be scheduled by LocThread + // This method will be repeated called until it returns false; or + // until thread is stopped. + virtual bool run() = 0; + + // The method to be run before thread loop (conditionally repeatedly) + // calls run() + inline virtual void prerun() {} + + // The method to be run after thread loop (conditionally repeatedly) + // calls run() + inline virtual void postrun() {} +}; + +// opaque class to provide service implementation. +class LocThreadDelegate; + +// A utility class to create a thread and run LocRunnable +// caller passes in. +class LocThread { + LocThreadDelegate* mThread; +public: + inline LocThread() : mThread(NULL) {} + virtual ~LocThread(); + + typedef pthread_t (*tCreate)(const char* name, void* (*start)(void*), void* arg); + // client starts thread with a runnable, which implements + // the logics to fun in the created thread context. + // The thread could be either joinable or detached. + // runnable is an obj managed by client. Client creates and + // frees it (but must be after stop() is called, or + // this LocThread obj is deleted). + // The obj will be deleted by LocThread if start() + // returns true. Else it is client's responsibility + // to delete the object + // Returns 0 if success; false if failure. + bool start(tCreate creator, const char* threadName, LocRunnable* runnable, bool joinable = true); + inline bool start(const char* threadName, LocRunnable* runnable, bool joinable = true) { + return start(NULL, threadName, runnable, joinable); + } + + // NOTE: if this is a joinable thread, this stop may block + // for a while until the thread is joined. + void stop(); + + // thread status check + inline bool isRunning() { return NULL != mThread; } +}; + +#endif //__LOC_THREAD__ diff --git a/gps/utils/LocTimer.cpp b/gps/utils/LocTimer.cpp new file mode 100644 index 000000000..70904b2a5 --- /dev/null +++ b/gps/utils/LocTimer.cpp @@ -0,0 +1,737 @@ +/* Copyright (c) 2015, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __HOST_UNIT_TEST__ +#define EPOLLWAKEUP 0 +#define CLOCK_BOOTTIME CLOCK_MONOTONIC +#define CLOCK_BOOTTIME_ALARM CLOCK_MONOTONIC +#endif + +/* +There are implementations of 5 classes in this file: +LocTimer, LocTimerDelegate, LocTimerContainer, LocTimerPollTask, LocTimerWrapper + +LocTimer - client front end, interface for client to start / stop timers, also + to provide a callback. +LocTimerDelegate - an internal timer entity, which also is a LocRankable obj. + Its life cycle is different than that of LocTimer. It gets + created when LocTimer::start() is called, and gets deleted + when it expires or clients calls the hosting LocTimer obj's + stop() method. When a LocTimerDelegate obj is ticking, it + stays in the corresponding LocTimerContainer. When expired + or stopped, the obj is removed from the container. Since it + is also a LocRankable obj, and LocTimerContainer also is a + heap, its ranks() implementation decides where it is placed + in the heap. +LocTimerContainer - core of the timer service. It is a container (derived from + LocHeap) for LocTimerDelegate (implements LocRankable) objs. + There are 2 of such containers, one for sw timers (or Linux + timers) one for hw timers (or Linux alarms). It adds one of + each (those that expire the soonest) to kernel via services + provided by LocTimerPollTask. All the heap management on the + LocTimerDelegate objs are done in the MsgTask context, such + that synchronization is ensured. +LocTimerPollTask - is a class that wraps timerfd and epoll POXIS APIs. It also + both implements LocRunnalbe with epoll_wait() in the run() + method. It is also a LocThread client, so as to loop the run + method. +LocTimerWrapper - a LocTimer client itself, to implement the existing C API with + APIs, loc_timer_start() and loc_timer_stop(). + +*/ + +class LocTimerPollTask; + +// This is a multi-functaional class that: +// * extends the LocHeap class for the detection of head update upon add / remove +// events. When that happens, soonest time out changes, so timerfd needs update. +// * contains the timers, and add / remove them into the heap +// * provides and maps 2 of such containers, one for timers (or mSwTimers), one +// for alarms (or mHwTimers); +// * provides a polling thread; +// * provides a MsgTask thread for synchronized add / remove / timer client callback. +class LocTimerContainer : public LocHeap { + // mutex to synchronize getters of static members + static pthread_mutex_t mMutex; + // Container of timers + static LocTimerContainer* mSwTimers; + // Container of alarms + static LocTimerContainer* mHwTimers; + // Msg task to provider msg Q, sender and reader. + static MsgTask* mMsgTask; + // Poll task to provide epoll call and threading to poll. + static LocTimerPollTask* mPollTask; + // timer / alarm fd + int mDevFd; + // ctor + LocTimerContainer(bool wakeOnExpire); + // dtor + ~LocTimerContainer(); + static MsgTask* getMsgTaskLocked(); + static LocTimerPollTask* getPollTaskLocked(); + // extend LocHeap and pop if the top outRanks input + LocTimerDelegate* popIfOutRanks(LocTimerDelegate& timer); + // update the timer POSIX calls with updated soonest timer spec + void updateSoonestTime(LocTimerDelegate* priorTop); + +public: + // factory method to control the creation of mSwTimers / mHwTimers + static LocTimerContainer* get(bool wakeOnExpire); + + LocTimerDelegate* getSoonestTimer(); + int getTimerFd(); + // add a timer / alarm obj into the container + void add(LocTimerDelegate& timer); + // remove a timer / alarm obj from the container + void remove(LocTimerDelegate& timer); + // handling of timer / alarm expiration + void expire(); +}; + +// This class implements the polling thread that epolls imer / alarm fds. +// The LocRunnable::run() contains the actual polling. The other methods +// will be run in the caller's thread context to add / remove timer / alarm +// fds the kernel, while the polling is blocked on epoll_wait() call. +// Since the design is that we have maximally 2 polls, one for all the +// timers; one for all the alarms, we will poll at most on 2 fds. But it +// is possile that all we have are only timers or alarms at one time, so we +// allow dynamically add / remove fds we poll on. The design decision of +// having 1 fd per container of timer / alarm is such that, we may not need +// to make a system call each time a timer / alarm is added / removed, unless +// that changes the "soonest" time out of that of all the timers / alarms. +class LocTimerPollTask : public LocRunnable { + // the epoll fd + const int mFd; + // the thread that calls run() method + LocThread* mThread; + friend class LocThreadDelegate; + // dtor + ~LocTimerPollTask(); +public: + // ctor + LocTimerPollTask(); + // this obj will be deleted once thread is deleted + void destroy(); + // add a container of timers. Each contain has a unique device fd, i.e. + // either timer or alarm fd, and a heap of timers / alarms. It is expected + // that container would have written to the device fd with the soonest + // time out value in the heap at the time of calling this method. So all + // this method does is to add the fd of the input container to the poll + // and also add the pointer of the container to the event data ptr, such + // when poll_wait wakes up on events, we know who is the owner of the fd. + void addPoll(LocTimerContainer& timerContainer); + // remove a fd that is assciated with a container. The expectation is that + // the atual timer would have been removed from the container. + void removePoll(LocTimerContainer& timerContainer); + // The polling thread context will call this method. This is where + // epoll_wait() is blocking and waiting for events.. + virtual bool run(); +}; + +// Internal class of timer obj. It gets born when client calls LocTimer::start(); +// and gets deleted when client calls LocTimer::stop() or when the it expire()'s. +// This class implements LocRankable::ranks() so that when an obj is added into +// the container (of LocHeap), it gets placed in sorted order. +class LocTimerDelegate : public LocRankable { + friend class LocTimerContainer; + friend class LocTimer; + LocTimer* mClient; + LocSharedLock* mLock; + struct timespec mFutureTime; + LocTimerContainer* mContainer; + // not a complete obj, just ctor for LocRankable comparisons + inline LocTimerDelegate(struct timespec& delay) + : mClient(NULL), mLock(NULL), mFutureTime(delay), mContainer(NULL) {} + inline ~LocTimerDelegate() { if (mLock) { mLock->drop(); mLock = NULL; } } +public: + LocTimerDelegate(LocTimer& client, struct timespec& futureTime, bool wakeOnExpire); + void destroyLocked(); + // LocRankable virtual method + virtual int ranks(LocRankable& rankable); + void expire(); + inline struct timespec getFutureTime() { return mFutureTime; } +}; + +/***************************LocTimerContainer methods***************************/ + +// Most of these static recources are created on demand. They however are never +// destoyed. The theory is that there are processes that link to this util lib +// but never use timer, then these resources would never need to be created. +// For those processes that do use timer, it will likely also need to every +// once in a while. It might be cheaper keeping them around. +pthread_mutex_t LocTimerContainer::mMutex = PTHREAD_MUTEX_INITIALIZER; +LocTimerContainer* LocTimerContainer::mSwTimers = NULL; +LocTimerContainer* LocTimerContainer::mHwTimers = NULL; +MsgTask* LocTimerContainer::mMsgTask = NULL; +LocTimerPollTask* LocTimerContainer::mPollTask = NULL; + +// ctor - initialize timer heaps +// A container for swTimer (timer) is created, when wakeOnExpire is true; or +// HwTimer (alarm), when wakeOnExpire is false. +LocTimerContainer::LocTimerContainer(bool wakeOnExpire) : + mDevFd(timerfd_create(wakeOnExpire ? CLOCK_BOOTTIME_ALARM : CLOCK_BOOTTIME, 0)) { + + if ((-1 == mDevFd) && (errno == EINVAL)) { + LOC_LOGW("%s: timerfd_create failure, fallback to CLOCK_MONOTONIC - %s", + __FUNCTION__, strerror(errno)); + mDevFd = timerfd_create(CLOCK_MONOTONIC, 0); + } + + if (-1 != mDevFd) { + // ensure we have the necessary resources created + LocTimerContainer::getPollTaskLocked(); + LocTimerContainer::getMsgTaskLocked(); + } else { + LOC_LOGE("%s: timerfd_create failure - %s", __FUNCTION__, strerror(errno)); + } +} + +// dtor +// we do not ever destroy the static resources. +inline +LocTimerContainer::~LocTimerContainer() { + close(mDevFd); +} + +LocTimerContainer* LocTimerContainer::get(bool wakeOnExpire) { + // get the reference of either mHwTimer or mSwTimers per wakeOnExpire + LocTimerContainer*& container = wakeOnExpire ? mHwTimers : mSwTimers; + // it is cheap to check pointer first than locking mutext unconditionally + if (!container) { + pthread_mutex_lock(&mMutex); + // let's check one more time to be safe + if (!container) { + container = new LocTimerContainer(wakeOnExpire); + // timerfd_create failure + if (-1 == container->getTimerFd()) { + delete container; + container = NULL; + } + } + pthread_mutex_unlock(&mMutex); + } + return container; +} + +MsgTask* LocTimerContainer::getMsgTaskLocked() { + // it is cheap to check pointer first than locking mutext unconditionally + if (!mMsgTask) { + mMsgTask = new MsgTask("LocTimerMsgTask", false); + } + return mMsgTask; +} + +LocTimerPollTask* LocTimerContainer::getPollTaskLocked() { + // it is cheap to check pointer first than locking mutext unconditionally + if (!mPollTask) { + mPollTask = new LocTimerPollTask(); + } + return mPollTask; +} + +inline +LocTimerDelegate* LocTimerContainer::getSoonestTimer() { + return (LocTimerDelegate*)(peek()); +} + +inline +int LocTimerContainer::getTimerFd() { + return mDevFd; +} + +void LocTimerContainer::updateSoonestTime(LocTimerDelegate* priorTop) { + LocTimerDelegate* curTop = getSoonestTimer(); + + // check if top has changed + if (curTop != priorTop) { + struct itimerspec delay = {0}; + bool toSetTime = false; + // if tree is empty now, we remove poll and disarm timer + if (!curTop) { + mPollTask->removePoll(*this); + // setting the values to disarm timer + delay.it_value.tv_sec = 0; + delay.it_value.tv_nsec = 0; + toSetTime = true; + } else if (!priorTop || curTop->outRanks(*priorTop)) { + // do this first to avoid race condition, in case settime is called + // with too small an interval + mPollTask->addPoll(*this); + delay.it_value = curTop->getFutureTime(); + toSetTime = true; + } + if (toSetTime) { + timerfd_settime(getTimerFd(), TFD_TIMER_ABSTIME, &delay, NULL); + } + } +} + +// all the heap management is done in the MsgTask context. +inline +void LocTimerContainer::add(LocTimerDelegate& timer) { + struct MsgTimerPush : public LocMsg { + LocTimerContainer* mTimerContainer; + LocHeapNode* mTree; + LocTimerDelegate* mTimer; + inline MsgTimerPush(LocTimerContainer& container, LocTimerDelegate& timer) : + LocMsg(), mTimerContainer(&container), mTimer(&timer) {} + inline virtual void proc() const { + LocTimerDelegate* priorTop = mTimerContainer->getSoonestTimer(); + mTimerContainer->push((LocRankable&)(*mTimer)); + mTimerContainer->updateSoonestTime(priorTop); + } + }; + + mMsgTask->sendMsg(new MsgTimerPush(*this, timer)); +} + +// all the heap management is done in the MsgTask context. +void LocTimerContainer::remove(LocTimerDelegate& timer) { + struct MsgTimerRemove : public LocMsg { + LocTimerContainer* mTimerContainer; + LocTimerDelegate* mTimer; + inline MsgTimerRemove(LocTimerContainer& container, LocTimerDelegate& timer) : + LocMsg(), mTimerContainer(&container), mTimer(&timer) {} + inline virtual void proc() const { + LocTimerDelegate* priorTop = mTimerContainer->getSoonestTimer(); + + // update soonest timer only if mTimer is actually removed from + // mTimerContainer AND mTimer is not priorTop. + if (priorTop == ((LocHeap*)mTimerContainer)->remove((LocRankable&)*mTimer)) { + // if passing in NULL, we tell updateSoonestTime to update + // kernel with the current top timer interval. + mTimerContainer->updateSoonestTime(NULL); + } + // all timers are deleted here, and only here. + delete mTimer; + } + }; + + mMsgTask->sendMsg(new MsgTimerRemove(*this, timer)); +} + +// all the heap management is done in the MsgTask context. +// Upon expire, we check and continuously pop the heap until +// the top node's timeout is in the future. +void LocTimerContainer::expire() { + struct MsgTimerExpire : public LocMsg { + LocTimerContainer* mTimerContainer; + inline MsgTimerExpire(LocTimerContainer& container) : + LocMsg(), mTimerContainer(&container) {} + inline virtual void proc() const { + struct timespec now; + // get time spec of now + clock_gettime(CLOCK_BOOTTIME, &now); + LocTimerDelegate timerOfNow(now); + // pop everything in the heap that outRanks now, i.e. has time older than now + // and then call expire() on that timer. + for (LocTimerDelegate* timer = (LocTimerDelegate*)mTimerContainer->pop(); + NULL != timer; + timer = mTimerContainer->popIfOutRanks(timerOfNow)) { + // the timer delegate obj will be deleted before the return of this call + timer->expire(); + } + mTimerContainer->updateSoonestTime(NULL); + } + }; + + struct itimerspec delay = {0}; + timerfd_settime(getTimerFd(), TFD_TIMER_ABSTIME, &delay, NULL); + mPollTask->removePoll(*this); + mMsgTask->sendMsg(new MsgTimerExpire(*this)); +} + +LocTimerDelegate* LocTimerContainer::popIfOutRanks(LocTimerDelegate& timer) { + LocTimerDelegate* poppedNode = NULL; + if (mTree && !timer.outRanks(*peek())) { + poppedNode = (LocTimerDelegate*)(pop()); + } + + return poppedNode; +} + + +/***************************LocTimerPollTask methods***************************/ + +inline +LocTimerPollTask::LocTimerPollTask() + : mFd(epoll_create(2)), mThread(new LocThread()) { + // before a next call returens, a thread will be created. The run() method + // could already be running in parallel. Also, since each of the objs + // creates a thread, the container will make sure that there will be only + // one of such obj for our timer implementation. + if (!mThread->start("LocTimerPollTask", this)) { + delete mThread; + mThread = NULL; + } +} + +inline +LocTimerPollTask::~LocTimerPollTask() { + // when fs is closed, epoll_wait() should fail run() should return false + // and the spawned thread should exit. + close(mFd); +} + +void LocTimerPollTask::destroy() { + if (mThread) { + LocThread* thread = mThread; + mThread = NULL; + delete thread; + } else { + delete this; + } +} + +void LocTimerPollTask::addPoll(LocTimerContainer& timerContainer) { + struct epoll_event ev; + memset(&ev, 0, sizeof(ev)); + + ev.events = EPOLLIN | EPOLLWAKEUP; + ev.data.fd = timerContainer.getTimerFd(); + // it is important that we set this context pointer with the input + // timer container this is how we know which container should handle + // which expiration. + ev.data.ptr = &timerContainer; + + epoll_ctl(mFd, EPOLL_CTL_ADD, timerContainer.getTimerFd(), &ev); +} + +inline +void LocTimerPollTask::removePoll(LocTimerContainer& timerContainer) { + epoll_ctl(mFd, EPOLL_CTL_DEL, timerContainer.getTimerFd(), NULL); +} + +// The polling thread context will call this method. If run() method needs to +// be repetitvely called, it must return true from the previous call. +bool LocTimerPollTask::run() { + struct epoll_event ev[2]; + + // we have max 2 descriptors to poll from + int fds = epoll_wait(mFd, ev, 2, -1); + + // we pretty much want to continually poll until the fd is closed + bool rerun = (fds > 0) || (errno == EINTR); + + if (fds > 0) { + // we may have 2 events + for (int i = 0; i < fds; i++) { + // each fd has a context pointer associated with the right timer container + LocTimerContainer* container = (LocTimerContainer*)(ev[i].data.ptr); + if (container) { + container->expire(); + } else { + epoll_ctl(mFd, EPOLL_CTL_DEL, ev[i].data.fd, NULL); + } + } + } + + // if rerun is true, we are requesting to be scheduled again + return rerun; +} + +/***************************LocTimerDelegate methods***************************/ + +inline +LocTimerDelegate::LocTimerDelegate(LocTimer& client, struct timespec& futureTime, bool wakeOnExpire) + : mClient(&client), + mLock(mClient->mLock->share()), + mFutureTime(futureTime), + mContainer(LocTimerContainer::get(wakeOnExpire)) { + // adding the timer into the container + mContainer->add(*this); +} + +inline +void LocTimerDelegate::destroyLocked() { + // client handle will likely be deleted soon after this + // method returns. Nulling this handle so that expire() + // won't call the callback on the dead handle any more. + mClient = NULL; + + if (mContainer) { + LocTimerContainer* container = mContainer; + mContainer = NULL; + if (container) { + container->remove(*this); + } + } // else we do not do anything. No such *this* can be + // created and reached here with mContainer ever been + // a non NULL. So *this* must have reached the if clause + // once, and we want it reach there only once. +} + +int LocTimerDelegate::ranks(LocRankable& rankable) { + int rank = -1; + LocTimerDelegate* timer = (LocTimerDelegate*)(&rankable); + if (timer) { + // larger time ranks lower!!! + // IOW, if input obj has bigger tv_sec, this obj outRanks higher + rank = timer->mFutureTime.tv_sec - mFutureTime.tv_sec; + } + return rank; +} + +inline +void LocTimerDelegate::expire() { + // keeping a copy of client pointer to be safe + // when timeOutCallback() is called at the end of this + // method, *this* obj may be already deleted. + LocTimer* client = mClient; + // force a stop, which will lead to delete of this obj + if (client && client->stop()) { + // calling client callback with a pointer save on the stack + // only if stop() returns true, i.e. it hasn't been stopped + // already. + client->timeOutCallback(); + } +} + + +/***************************LocTimer methods***************************/ +LocTimer::LocTimer() : mTimer(NULL), mLock(new LocSharedLock()) { +} + +LocTimer::~LocTimer() { + stop(); + if (mLock) { + mLock->drop(); + mLock = NULL; + } +} + +bool LocTimer::start(unsigned int timeOutInMs, bool wakeOnExpire) { + bool success = false; + mLock->lock(); + if (!mTimer) { + struct timespec futureTime; + clock_gettime(CLOCK_BOOTTIME, &futureTime); + futureTime.tv_sec += timeOutInMs / 1000; + futureTime.tv_nsec += (timeOutInMs % 1000) * 1000000; + if (futureTime.tv_nsec >= 1000000000) { + futureTime.tv_sec += futureTime.tv_nsec / 1000000000; + futureTime.tv_nsec %= 1000000000; + } + mTimer = new LocTimerDelegate(*this, futureTime, wakeOnExpire); + // if mTimer is non 0, success should be 0; or vice versa + success = (NULL != mTimer); + } + mLock->unlock(); + return success; +} + +bool LocTimer::stop() { + bool success = false; + mLock->lock(); + if (mTimer) { + LocTimerDelegate* timer = mTimer; + mTimer = NULL; + if (timer) { + timer->destroyLocked(); + success = true; + } + } + mLock->unlock(); + return success; +} + +/***************************LocTimerWrapper methods***************************/ +////////////////////////////////////////////////////////////////////////// +// This section below wraps for the C style APIs +////////////////////////////////////////////////////////////////////////// +class LocTimerWrapper : public LocTimer { + loc_timer_callback mCb; + void* mCallerData; + LocTimerWrapper* mMe; + static pthread_mutex_t mMutex; + inline ~LocTimerWrapper() { mCb = NULL; mMe = NULL; } +public: + inline LocTimerWrapper(loc_timer_callback cb, void* callerData) : + mCb(cb), mCallerData(callerData), mMe(this) { + } + void destroy() { + pthread_mutex_lock(&mMutex); + if (NULL != mCb && this == mMe) { + delete this; + } + pthread_mutex_unlock(&mMutex); + } + virtual void timeOutCallback() { + loc_timer_callback cb = mCb; + void* callerData = mCallerData; + if (cb) { + cb(callerData, 0); + } + destroy(); + } +}; + +pthread_mutex_t LocTimerWrapper::mMutex = PTHREAD_MUTEX_INITIALIZER; + +void* loc_timer_start(uint64_t msec, loc_timer_callback cb_func, + void *caller_data, bool wake_on_expire) +{ + LocTimerWrapper* locTimerWrapper = NULL; + + if (cb_func) { + locTimerWrapper = new LocTimerWrapper(cb_func, caller_data); + + if (locTimerWrapper) { + locTimerWrapper->start(msec, wake_on_expire); + } + } + + return locTimerWrapper; +} + +void loc_timer_stop(void*& handle) +{ + if (handle) { + LocTimerWrapper* locTimerWrapper = (LocTimerWrapper*)(handle); + locTimerWrapper->destroy(); + handle = NULL; + } +} + +////////////////////////////////////////////////////////////////////////// +// This section above wraps for the C style APIs +////////////////////////////////////////////////////////////////////////// + +#ifdef __LOC_DEBUG__ + +double getDeltaSeconds(struct timespec from, struct timespec to) { + return (double)to.tv_sec + (double)to.tv_nsec / 1000000000 + - from.tv_sec - (double)from.tv_nsec / 1000000000; +} + +struct timespec getNow() { + struct timespec now; + clock_gettime(CLOCK_BOOTTIME, &now); + return now; +} + +class LocTimerTest : public LocTimer, public LocRankable { + int mTimeOut; + const struct timespec mTimeOfBirth; + inline struct timespec getTimerWrapper(int timeout) { + struct timespec now; + clock_gettime(CLOCK_BOOTTIME, &now); + now.tv_sec += timeout; + return now; + } +public: + inline LocTimerTest(int timeout) : LocTimer(), LocRankable(), + mTimeOut(timeout), mTimeOfBirth(getTimerWrapper(0)) {} + inline virtual int ranks(LocRankable& rankable) { + LocTimerTest* timer = dynamic_cast(&rankable); + return timer->mTimeOut - mTimeOut; + } + inline virtual void timeOutCallback() { + printf("timeOutCallback() - "); + deviation(); + } + double deviation() { + struct timespec now = getTimerWrapper(0); + double delta = getDeltaSeconds(mTimeOfBirth, now); + printf("%lf: %lf\n", delta, delta * 100 / mTimeOut); + return delta / mTimeOut; + } +}; + +// For Linux command line testing: +// compilation: +// g++ -D__LOC_HOST_DEBUG__ -D__LOC_DEBUG__ -g -I. -I../../../../system/core/include -o LocHeap.o LocHeap.cpp +// g++ -D__LOC_HOST_DEBUG__ -D__LOC_DEBUG__ -g -std=c++0x -I. -I../../../../system/core/include -lpthread -o LocThread.o LocThread.cpp +// g++ -D__LOC_HOST_DEBUG__ -D__LOC_DEBUG__ -g -I. -I../../../../system/core/include -o LocTimer.o LocTimer.cpp +int main(int argc, char** argv) { + struct timespec timeOfStart=getNow(); + srand(time(NULL)); + int tries = atoi(argv[1]); + int checks = tries >> 3; + LocTimerTest** timerArray = new LocTimerTest*[tries]; + memset(timerArray, NULL, tries); + + for (int i = 0; i < tries; i++) { + int r = rand() % tries; + LocTimerTest* timer = new LocTimerTest(r); + if (timerArray[r]) { + if (!timer->stop()) { + printf("%lf:\n", getDeltaSeconds(timeOfStart, getNow())); + printf("ERRER: %dth timer, id %d, not running when it should be\n", i, r); + exit(0); + } else { + printf("stop() - %d\n", r); + delete timer; + timerArray[r] = NULL; + } + } else { + if (!timer->start(r, false)) { + printf("%lf:\n", getDeltaSeconds(timeOfStart, getNow())); + printf("ERRER: %dth timer, id %d, running when it should not be\n", i, r); + exit(0); + } else { + printf("stop() - %d\n", r); + timerArray[r] = timer; + } + } + } + + for (int i = 0; i < tries; i++) { + if (timerArray[i]) { + if (!timerArray[i]->stop()) { + printf("%lf:\n", getDeltaSeconds(timeOfStart, getNow())); + printf("ERRER: %dth timer, not running when it should be\n", i); + exit(0); + } else { + printf("stop() - %d\n", i); + delete timerArray[i]; + timerArray[i] = NULL; + } + } + } + + delete[] timerArray; + + return 0; +} + +#endif diff --git a/gps/utils/LocTimer.h b/gps/utils/LocTimer.h new file mode 100644 index 000000000..c1468524b --- /dev/null +++ b/gps/utils/LocTimer.h @@ -0,0 +1,74 @@ +/* Copyright (c) 2015, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef __LOC_TIMER_CPP_H__ +#define __LOC_TIMER_CPP_H__ + +#include +#include + +// opaque class to provide service implementation. +class LocTimerDelegate; +class LocSharedLock; + +// LocTimer client must extend this class and implementthe callback. +// start() / stop() methods are to arm / disarm timer. +class LocTimer +{ + LocTimerDelegate* mTimer; + LocSharedLock* mLock; + // don't really want mLock to be manipulated by clients, yet LocTimer + // has to have a reference to the lock so that the delete of LocTimer + // and LocTimerDelegate can work together on their share resources. + friend class LocTimerDelegate; + +public: + LocTimer(); + virtual ~LocTimer(); + + // timeOutInMs: timeout delay in ms + // wakeOnExpire: true if to wake up CPU (if sleeping) upon timer + // expiration and notify the client. + // false if to wait until next time CPU wakes up (if + // sleeping) and then notify the client. + // return: true on success; + // false on failure, e.g. timer is already running. + bool start(uint32_t timeOutInMs, bool wakeOnExpire); + + // return: true on success; + // false on failure, e.g. timer is not running. + bool stop(); + + // LocTimer client Should implement this method. + // This method is used for timeout calling back to client. This method + // should be short enough (eg: send a message to your own thread). + virtual void timeOutCallback() = 0; +}; + +#endif //__LOC_DELAY_H__ diff --git a/gps/utils/Makefile.am b/gps/utils/Makefile.am new file mode 100644 index 000000000..e5935f050 --- /dev/null +++ b/gps/utils/Makefile.am @@ -0,0 +1,44 @@ +AM_CFLAGS = -Wundef \ + -MD \ + -Wno-trigraphs \ + -g -O0 \ + -fno-inline \ + -fno-short-enums \ + -fpic \ + -I../platform_lib_abstractions + +libgps_utils_so_la_h_sources = log_util.h \ + msg_q.h \ + linked_list.h \ + loc_cfg.h \ + loc_log.h \ + ../platform_lib_abstractions/platform_lib_includes.h \ + ../platform_lib_abstractions/platform_lib_time.h \ + ../platform_lib_abstractions/platform_lib_macros.h + +libgps_utils_so_la_c_sources = linked_list.c \ + msg_q.c \ + loc_cfg.cpp \ + loc_log.cpp \ + ../platform_lib_abstractions/elapsed_millis_since_boot.cpp + +library_includedir = $(pkgincludedir)/utils + +library_include_HEADERS = $(libgps_utils_so_la_h_sources) + +libgps_utils_so_la_SOURCES = $(libgps_utils_so_la_c_sources) + +if USE_GLIB +libgps_utils_so_la_CFLAGS = -DUSE_GLIB $(AM_CFLAGS) @GLIB_CFLAGS@ +libgps_utils_so_la_LDFLAGS = -lstdc++ -lpthread @GLIB_LIBS@ -shared -version-info 1:0:0 +libgps_utils_so_la_CPPFLAGS = -DUSE_GLIB $(AM_CFLAGS) $(AM_CPPFLAGS) @GLIB_CFLAGS@ +else +libgps_utils_so_la_CFLAGS = $(AM_CFLAGS) +libgps_utils_so_la_LDFLAGS = -lpthread -shared -version-info 1:0:0 +libgps_utils_so_la_CPPFLAGS = $(AM_CFLAGS) $(AM_CPPFLAGS) +endif + +libgps_utils_so_la_LIBADD = -lstdc++ -lcutils + +#Create and Install libraries +lib_LTLIBRARIES = libgps_utils_so.la diff --git a/gps/utils/MsgTask.cpp b/gps/utils/MsgTask.cpp new file mode 100644 index 000000000..6f9d0e909 --- /dev/null +++ b/gps/utils/MsgTask.cpp @@ -0,0 +1,102 @@ +/* Copyright (c) 2011-2013,2015 The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#define LOG_NDDEBUG 0 +#define LOG_TAG "LocSvc_MsgTask" + +#include +#include +#include +#include +#include +#include + +static void LocMsgDestroy(void* msg) { + delete (LocMsg*)msg; +} + +MsgTask::MsgTask(LocThread::tCreate tCreator, + const char* threadName, bool joinable) : + mQ(msg_q_init2()), mThread(new LocThread()) { + if (!mThread->start(tCreator, threadName, this, joinable)) { + delete mThread; + mThread = NULL; + } +} + +MsgTask::MsgTask(const char* threadName, bool joinable) : + mQ(msg_q_init2()), mThread(new LocThread()) { + if (!mThread->start(threadName, this, joinable)) { + delete mThread; + mThread = NULL; + } +} + +MsgTask::~MsgTask() { + msg_q_flush((void*)mQ); + msg_q_destroy((void**)&mQ); +} + +void MsgTask::destroy() { + msg_q_unblock((void*)mQ); + if (mThread) { + LocThread* thread = mThread; + mThread = NULL; + delete thread; + } else { + delete this; + } +} + +void MsgTask::sendMsg(const LocMsg* msg) const { + msg_q_snd((void*)mQ, (void*)msg, LocMsgDestroy); +} + +void MsgTask::prerun() { + // make sure we do not run in background scheduling group + set_sched_policy(gettid(), SP_FOREGROUND); +} + +bool MsgTask::run() { + LOC_LOGV("MsgTask::loop() listening ...\n"); + LocMsg* msg; + msq_q_err_type result = msg_q_rcv((void*)mQ, (void **)&msg); + if (eMSG_Q_SUCCESS != result) { + LOC_LOGE("%s:%d] fail receiving msg: %s\n", __func__, __LINE__, + loc_get_msg_q_status(result)); + return false; + } + + msg->log(); + // there is where each individual msg handling is invoked + msg->proc(); + + delete msg; + + return true; +} diff --git a/gps/utils/MsgTask.h b/gps/utils/MsgTask.h new file mode 100644 index 000000000..9eb1f5671 --- /dev/null +++ b/gps/utils/MsgTask.h @@ -0,0 +1,67 @@ +/* Copyright (c) 2011-2013,2015 The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef __MSG_TASK__ +#define __MSG_TASK__ + +#include + +struct LocMsg { + inline LocMsg() {} + inline virtual ~LocMsg() {} + virtual void proc() const = 0; + inline virtual void log() const {} +}; + +class MsgTask : public LocRunnable { + const void* mQ; + LocThread* mThread; + friend class LocThreadDelegate; +protected: + virtual ~MsgTask(); +public: + MsgTask(LocThread::tCreate tCreator, const char* threadName = NULL, bool joinable = true); + MsgTask(const char* threadName = NULL, bool joinable = true); + // this obj will be deleted once thread is deleted + void destroy(); + void sendMsg(const LocMsg* msg) const; + // Overrides of LocRunnable methods + // This method will be repeated called until it returns false; or + // until thread is stopped. + virtual bool run(); + + // The method to be run before thread loop (conditionally repeatedly) + // calls run() + virtual void prerun(); + + // The method to be run after thread loop (conditionally repeatedly) + // calls run() + inline virtual void postrun() {} +}; + +#endif //__MSG_TASK__ diff --git a/gps/utils/linked_list.c b/gps/utils/linked_list.c new file mode 100644 index 000000000..2c91714b9 --- /dev/null +++ b/gps/utils/linked_list.c @@ -0,0 +1,328 @@ +/* Copyright (c) 2011, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "linked_list.h" +#include +#include + +#define LOG_TAG "LocSvc_utils_ll" +#include "log_util.h" +#include "platform_lib_includes.h" +#include +#include + +typedef struct list_element { + struct list_element* next; + struct list_element* prev; + void* data_ptr; + void (*dealloc_func)(void*); +}list_element; + +typedef struct list_state { + list_element* p_head; + list_element* p_tail; +} list_state; + +/* ----------------------- END INTERNAL FUNCTIONS ---------------------------------------- */ + +/*=========================================================================== + + FUNCTION: linked_list_init + + ===========================================================================*/ +linked_list_err_type linked_list_init(void** list_data) +{ + if( list_data == NULL ) + { + LOC_LOGE("%s: Invalid list parameter!\n", __FUNCTION__); + return eLINKED_LIST_INVALID_PARAMETER; + } + + list_state* tmp_list; + tmp_list = (list_state*)calloc(1, sizeof(list_state)); + if( tmp_list == NULL ) + { + LOC_LOGE("%s: Unable to allocate space for list!\n", __FUNCTION__); + return eLINKED_LIST_FAILURE_GENERAL; + } + + tmp_list->p_head = NULL; + tmp_list->p_tail = NULL; + + *list_data = tmp_list; + + return eLINKED_LIST_SUCCESS; +} + +/*=========================================================================== + + FUNCTION: linked_list_destroy + + ===========================================================================*/ +linked_list_err_type linked_list_destroy(void** list_data) +{ + if( list_data == NULL ) + { + LOC_LOGE("%s: Invalid list parameter!\n", __FUNCTION__); + return eLINKED_LIST_INVALID_HANDLE; + } + + list_state* p_list = (list_state*)*list_data; + + linked_list_flush(p_list); + + free(*list_data); + *list_data = NULL; + + return eLINKED_LIST_SUCCESS; +} + +/*=========================================================================== + + FUNCTION: linked_list_add + + ===========================================================================*/ +linked_list_err_type linked_list_add(void* list_data, void *data_obj, void (*dealloc)(void*)) +{ + LOC_LOGV("%s: Adding to list data_obj = 0x%08X\n", __FUNCTION__, data_obj); + if( list_data == NULL ) + { + LOC_LOGE("%s: Invalid list parameter!\n", __FUNCTION__); + return eLINKED_LIST_INVALID_HANDLE; + } + + if( data_obj == NULL ) + { + LOC_LOGE("%s: Invalid input parameter!\n", __FUNCTION__); + return eLINKED_LIST_INVALID_PARAMETER; + } + + list_state* p_list = (list_state*)list_data; + list_element* elem = (list_element*)malloc(sizeof(list_element)); + if( elem == NULL ) + { + LOC_LOGE("%s: Memory allocation failed\n", __FUNCTION__); + return eLINKED_LIST_FAILURE_GENERAL; + } + + /* Copy data to newly created element */ + elem->data_ptr = data_obj; + elem->next = NULL; + elem->prev = NULL; + elem->dealloc_func = dealloc; + + /* Replace head element */ + list_element* tmp = p_list->p_head; + p_list->p_head = elem; + /* Point next to the previous head element */ + p_list->p_head->next = tmp; + + if( tmp != NULL ) + { + tmp->prev = p_list->p_head; + } + else + { + p_list->p_tail = p_list->p_head; + } + + return eLINKED_LIST_SUCCESS; +} + +/*=========================================================================== + + FUNCTION: linked_list_remove + + ===========================================================================*/ +linked_list_err_type linked_list_remove(void* list_data, void **data_obj) +{ + LOC_LOGV("%s: Removing from list\n", __FUNCTION__); + if( list_data == NULL ) + { + LOC_LOGE("%s: Invalid list parameter!\n", __FUNCTION__); + return eLINKED_LIST_INVALID_HANDLE; + } + + if( data_obj == NULL ) + { + LOC_LOGE("%s: Invalid input parameter!\n", __FUNCTION__); + return eLINKED_LIST_INVALID_PARAMETER; + } + + list_state* p_list = (list_state*)list_data; + if( p_list->p_tail == NULL ) + { + return eLINKED_LIST_UNAVAILABLE_RESOURCE; + } + + list_element* tmp = p_list->p_tail; + + /* Replace tail element */ + p_list->p_tail = tmp->prev; + + if( p_list->p_tail != NULL ) + { + p_list->p_tail->next = NULL; + } + else + { + p_list->p_head = p_list->p_tail; + } + + /* Copy data to output param */ + *data_obj = tmp->data_ptr; + + /* Free allocated list element */ + free(tmp); + + return eLINKED_LIST_SUCCESS; +} + +/*=========================================================================== + + FUNCTION: linked_list_empty + + ===========================================================================*/ +int linked_list_empty(void* list_data) +{ + if( list_data == NULL ) + { + LOC_LOGE("%s: Invalid list parameter!\n", __FUNCTION__); + return (int)eLINKED_LIST_INVALID_HANDLE; + } + else + { + list_state* p_list = (list_state*)list_data; + return p_list->p_head == NULL ? 1 : 0; + } +} + +/*=========================================================================== + + FUNCTION: linked_list_flush + + ===========================================================================*/ +linked_list_err_type linked_list_flush(void* list_data) +{ + if( list_data == NULL ) + { + LOC_LOGE("%s: Invalid list parameter!\n", __FUNCTION__); + return eLINKED_LIST_INVALID_HANDLE; + } + + list_state* p_list = (list_state*)list_data; + + /* Remove all dynamically allocated elements */ + while( p_list->p_head != NULL ) + { + list_element* tmp = p_list->p_head->next; + + /* Free data pointer if told to do so. */ + if( p_list->p_head->dealloc_func != NULL ) + { + p_list->p_head->dealloc_func(p_list->p_head->data_ptr); + } + + /* Free list element */ + free(p_list->p_head); + + p_list->p_head = tmp; + } + + p_list->p_tail = NULL; + + return eLINKED_LIST_SUCCESS; +} + +/*=========================================================================== + + FUNCTION: linked_list_search + + ===========================================================================*/ +linked_list_err_type linked_list_search(void* list_data, void **data_p, + bool (*equal)(void* data_0, void* data), + void* data_0, bool rm_if_found) +{ + LOC_LOGV("%s: Search the list\n", __FUNCTION__); + if( list_data == NULL || NULL == equal ) + { + LOC_LOGE("%s: Invalid list parameter! list_data %p equal %p\n", + __FUNCTION__, list_data, equal); + return eLINKED_LIST_INVALID_HANDLE; + } + + list_state* p_list = (list_state*)list_data; + if( p_list->p_tail == NULL ) + { + return eLINKED_LIST_UNAVAILABLE_RESOURCE; + } + + list_element* tmp = p_list->p_head; + + if (NULL != data_p) { + *data_p = NULL; + } + + while (NULL != tmp) { + if ((*equal)(data_0, tmp->data_ptr)) { + if (NULL != data_p) { + *data_p = tmp->data_ptr; + } + + if (rm_if_found) { + if (NULL == tmp->prev) { + p_list->p_head = tmp->next; + } else { + tmp->prev->next = tmp->next; + } + + if (NULL == tmp->next) { + p_list->p_tail = tmp->prev; + } else { + tmp->next->prev = tmp->prev; + } + + tmp->prev = tmp->next = NULL; + + // dealloc data if it is not copied out && caller + // has given us a dealloc function pointer. + if (NULL == data_p && NULL != tmp->dealloc_func) { + tmp->dealloc_func(tmp->data_ptr); + } + free(tmp); + } + + tmp = NULL; + } else { + tmp = tmp->next; + } + } + + return eLINKED_LIST_SUCCESS; +} + diff --git a/gps/utils/linked_list.h b/gps/utils/linked_list.h new file mode 100644 index 000000000..a85f09a39 --- /dev/null +++ b/gps/utils/linked_list.h @@ -0,0 +1,217 @@ +/* Copyright (c) 2011, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef __LINKED_LIST_H__ +#define __LINKED_LIST_H__ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include +#include + +/** Linked List Return Codes */ +typedef enum +{ + eLINKED_LIST_SUCCESS = 0, + /**< Request was successful. */ + eLINKED_LIST_FAILURE_GENERAL = -1, + /**< Failed because of a general failure. */ + eLINKED_LIST_INVALID_PARAMETER = -2, + /**< Failed because the request contained invalid parameters. */ + eLINKED_LIST_INVALID_HANDLE = -3, + /**< Failed because an invalid handle was specified. */ + eLINKED_LIST_UNAVAILABLE_RESOURCE = -4, + /**< Failed because an there were not enough resources. */ + eLINKED_LIST_INSUFFICIENT_BUFFER = -5, + /**< Failed because an the supplied buffer was too small. */ +}linked_list_err_type; + +/*=========================================================================== +FUNCTION linked_list_init + +DESCRIPTION + Initializes internal structures for linked list. + + list_data: State of list to be initialized. + +DEPENDENCIES + N/A + +RETURN VALUE + Look at error codes above. + +SIDE EFFECTS + N/A + +===========================================================================*/ +linked_list_err_type linked_list_init(void** list_data); + +/*=========================================================================== +FUNCTION linked_list_destroy + +DESCRIPTION + Destroys internal structures for linked list. + + p_list_data: State of list to be destroyed. + +DEPENDENCIES + N/A + +RETURN VALUE + Look at error codes above. + +SIDE EFFECTS + N/A + +===========================================================================*/ +linked_list_err_type linked_list_destroy(void** list_data); + +/*=========================================================================== +FUNCTION linked_list_add + +DESCRIPTION + Adds an element to the head of the linked list. The passed in data pointer + is not modified or freed. Passed in data_obj is expected to live throughout + the use of the linked_list (i.e. data is not allocated internally) + + p_list_data: List to add data to the head of. + data_obj: Pointer to data to add into list + dealloc: Function used to deallocate memory for this element. Pass NULL + if you do not want data deallocated during a flush operation + +DEPENDENCIES + N/A + +RETURN VALUE + Look at error codes above. + +SIDE EFFECTS + N/A + +===========================================================================*/ +linked_list_err_type linked_list_add(void* list_data, void *data_obj, void (*dealloc)(void*)); + +/*=========================================================================== +FUNCTION linked_list_remove + +DESCRIPTION + Retrieves data from the list tail. data_obj is the tail element from the list + passed in by linked_list_add. + + p_list_data: List to remove the tail from. + data_obj: Pointer to data removed from list + +DEPENDENCIES + N/A + +RETURN VALUE + Look at error codes above. + +SIDE EFFECTS + N/A + +===========================================================================*/ +linked_list_err_type linked_list_remove(void* list_data, void **data_obj); + +/*=========================================================================== +FUNCTION linked_list_empty + +DESCRIPTION + Tells whether the list currently contains any elements + + p_list_data: List to check if empty. + +DEPENDENCIES + N/A + +RETURN VALUE + 0/FALSE : List contains elements + 1/TRUE : List is Empty + Otherwise look at error codes above. + +SIDE EFFECTS + N/A + +===========================================================================*/ +int linked_list_empty(void* list_data); + +/*=========================================================================== +FUNCTION linked_list_flush + +DESCRIPTION + Removes all elements from the list and deallocates them using the provided + dealloc function while adding elements. + + p_list_data: List to remove all elements from. + +DEPENDENCIES + N/A + +RETURN VALUE + Look at error codes above. + +SIDE EFFECTS + N/A + +===========================================================================*/ +linked_list_err_type linked_list_flush(void* list_data); + +/*=========================================================================== +FUNCTION linked_list_search + +DESCRIPTION + Searches for an element in the linked list. + + p_list_data: List handle. + data_p: to be stored with the data found; NUll if no match. + if data_p passed in as NULL, then no write to it. + equal: Function ptr takes in a list element, and returns + indication if this the one looking for. + data_0: The data being compared against. + rm_if_found: Should data be removed if found? + +DEPENDENCIES + N/A + +RETURN VALUE + Look at error codes above. + +SIDE EFFECTS + N/A + +===========================================================================*/ +linked_list_err_type linked_list_search(void* list_data, void **data_p, + bool (*equal)(void* data_0, void* data), + void* data_0, bool rm_if_found); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __LINKED_LIST_H__ */ diff --git a/gps/utils/loc_cfg.cpp b/gps/utils/loc_cfg.cpp new file mode 100644 index 000000000..967d2f307 --- /dev/null +++ b/gps/utils/loc_cfg.cpp @@ -0,0 +1,400 @@ +/* Copyright (c) 2011-2015, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#define LOG_NDDEBUG 0 +#define LOG_TAG "LocSvc_utils_cfg" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef USE_GLIB +#include +#endif +#include "platform_lib_includes.h" + +/*============================================================================= + * + * GLOBAL DATA DECLARATION + * + *============================================================================*/ + +/* Parameter data */ +static uint32_t DEBUG_LEVEL = 0xff; +static uint32_t TIMESTAMP = 0; + +/* Parameter spec table */ +static const loc_param_s_type loc_param_table[] = +{ + {"DEBUG_LEVEL", &DEBUG_LEVEL, NULL, 'n'}, + {"TIMESTAMP", &TIMESTAMP, NULL, 'n'}, +}; +static const int loc_param_num = sizeof(loc_param_table) / sizeof(loc_param_s_type); + +typedef struct loc_param_v_type +{ + char* param_name; + char* param_str_value; + int param_int_value; + double param_double_value; +}loc_param_v_type; + +/*=========================================================================== +FUNCTION loc_set_config_entry + +DESCRIPTION + Potentially sets a given configuration table entry based on the passed in + configuration value. This is done by using a string comparison of the + parameter names and those found in the configuration file. + +PARAMETERS: + config_entry: configuration entry in the table to possibly set + config_value: value to store in the entry if the parameter names match + +DEPENDENCIES + N/A + +RETURN VALUE + None + +SIDE EFFECTS + N/A +===========================================================================*/ +int loc_set_config_entry(const loc_param_s_type* config_entry, loc_param_v_type* config_value) +{ + int ret=-1; + if(NULL == config_entry || NULL == config_value) + { + LOC_LOGE("%s: INVALID config entry or parameter", __FUNCTION__); + return ret; + } + + if (strcmp(config_entry->param_name, config_value->param_name) == 0 && + config_entry->param_ptr) + { + switch (config_entry->param_type) + { + case 's': + if (strcmp(config_value->param_str_value, "NULL") == 0) + { + *((char*)config_entry->param_ptr) = '\0'; + } + else { + strlcpy((char*) config_entry->param_ptr, + config_value->param_str_value, + LOC_MAX_PARAM_STRING + 1); + } + /* Log INI values */ + LOC_LOGD("%s: PARAM %s = %s", __FUNCTION__, + config_entry->param_name, (char*)config_entry->param_ptr); + + if(NULL != config_entry->param_set) + { + *(config_entry->param_set) = 1; + } + ret = 0; + break; + case 'n': + *((int *)config_entry->param_ptr) = config_value->param_int_value; + /* Log INI values */ + LOC_LOGD("%s: PARAM %s = %d", __FUNCTION__, + config_entry->param_name, config_value->param_int_value); + + if(NULL != config_entry->param_set) + { + *(config_entry->param_set) = 1; + } + ret = 0; + break; + case 'f': + *((double *)config_entry->param_ptr) = config_value->param_double_value; + /* Log INI values */ + LOC_LOGD("%s: PARAM %s = %f", __FUNCTION__, + config_entry->param_name, config_value->param_double_value); + + if(NULL != config_entry->param_set) + { + *(config_entry->param_set) = 1; + } + ret = 0; + break; + default: + LOC_LOGE("%s: PARAM %s parameter type must be n, f, or s", + __FUNCTION__, config_entry->param_name); + } + } + return ret; +} + +/*=========================================================================== +FUNCTION loc_fill_conf_item + +DESCRIPTION + Takes a line of configuration item and sets defined values based on + the passed in configuration table. This table maps strings to values to + set along with the type of each of these values. + +PARAMETERS: + input_buf : buffer contanis config item + config_table: table definition of strings to places to store information + table_length: length of the configuration table + +DEPENDENCIES + N/A + +RETURN VALUE + 0: Number of records in the config_table filled with input_buf + +SIDE EFFECTS + N/A +===========================================================================*/ +int loc_fill_conf_item(char* input_buf, + const loc_param_s_type* config_table, uint32_t table_length) +{ + int ret = 0; + + if (input_buf && config_table) { + char *lasts; + loc_param_v_type config_value; + memset(&config_value, 0, sizeof(config_value)); + + /* Separate variable and value */ + config_value.param_name = strtok_r(input_buf, "=", &lasts); + /* skip lines that do not contain "=" */ + if (config_value.param_name) { + config_value.param_str_value = strtok_r(NULL, "=", &lasts); + + /* skip lines that do not contain two operands */ + if (config_value.param_str_value) { + /* Trim leading and trailing spaces */ + loc_util_trim_space(config_value.param_name); + loc_util_trim_space(config_value.param_str_value); + + /* Parse numerical value */ + if ((strlen(config_value.param_str_value) >=3) && + (config_value.param_str_value[0] == '0') && + (tolower(config_value.param_str_value[1]) == 'x')) + { + /* hex */ + config_value.param_int_value = (int) strtol(&config_value.param_str_value[2], + (char**) NULL, 16); + } + else { + config_value.param_double_value = (double) atof(config_value.param_str_value); /* float */ + config_value.param_int_value = atoi(config_value.param_str_value); /* dec */ + } + + for(uint32_t i = 0; NULL != config_table && i < table_length; i++) + { + if(!loc_set_config_entry(&config_table[i], &config_value)) { + ret += 1; + } + } + } + } + } + + return ret; +} + +/*=========================================================================== +FUNCTION loc_read_conf_r (repetitive) + +DESCRIPTION + Reads the specified configuration file and sets defined values based on + the passed in configuration table. This table maps strings to values to + set along with the type of each of these values. + The difference between this and loc_read_conf is that this function returns + the file pointer position at the end of filling a config table. Also, it + reads a fixed number of parameters at a time which is equal to the length + of the configuration table. This functionality enables the caller to + repeatedly call the function to read data from the same file. + +PARAMETERS: + conf_fp : file pointer + config_table: table definition of strings to places to store information + table_length: length of the configuration table + +DEPENDENCIES + N/A + +RETURN VALUE + 0: Table filled successfully + 1: No more parameters to read + -1: Error filling table + +SIDE EFFECTS + N/A +===========================================================================*/ +int loc_read_conf_r(FILE *conf_fp, const loc_param_s_type* config_table, uint32_t table_length) +{ + int ret=0; + + unsigned int num_params=table_length; + if(conf_fp == NULL) { + LOC_LOGE("%s:%d]: ERROR: File pointer is NULL\n", __func__, __LINE__); + ret = -1; + goto err; + } + + /* Clear all validity bits */ + for(uint32_t i = 0; NULL != config_table && i < table_length; i++) + { + if(NULL != config_table[i].param_set) + { + *(config_table[i].param_set) = 0; + } + } + + char input_buf[LOC_MAX_PARAM_LINE]; /* declare a char array */ + + LOC_LOGD("%s:%d]: num_params: %d\n", __func__, __LINE__, num_params); + while(num_params) + { + if(!fgets(input_buf, LOC_MAX_PARAM_LINE, conf_fp)) { + LOC_LOGD("%s:%d]: fgets returned NULL\n", __func__, __LINE__); + break; + } + + num_params -= loc_fill_conf_item(input_buf, config_table, table_length); + } + +err: + return ret; +} + +/*=========================================================================== +FUNCTION loc_udpate_conf + +DESCRIPTION + Parses the passed in buffer for configuration items, and update the table + that is also passed in. + +Reads the specified configuration file and sets defined values based on + the passed in configuration table. This table maps strings to values to + set along with the type of each of these values. + +PARAMETERS: + conf_data: configuration items in bufferas a string + length: strlen(conf_data) + config_table: table definition of strings to places to store information + table_length: length of the configuration table + +DEPENDENCIES + N/A + +RETURN VALUE + number of the records in the table that is updated at time of return. + +SIDE EFFECTS + N/A +===========================================================================*/ +int loc_update_conf(const char* conf_data, int32_t length, + const loc_param_s_type* config_table, uint32_t table_length) +{ + int ret = -1; + + if (conf_data && length && config_table && table_length) { + // make a copy, so we do not tokenize the original data + char* conf_copy = (char*)malloc(length+1); + + if (conf_copy != NULL) + { + memcpy(conf_copy, conf_data, length); + // we hard NULL the end of string to be safe + conf_copy[length] = 0; + + // start with one record off + uint32_t num_params = table_length - 1; + char* saveptr = NULL; + char* input_buf = strtok_r(conf_copy, "\n", &saveptr); + ret = 0; + + LOC_LOGD("%s:%d]: num_params: %d\n", __func__, __LINE__, num_params); + while(num_params && input_buf) { + ret++; + num_params -= loc_fill_conf_item(input_buf, config_table, table_length); + input_buf = strtok_r(NULL, "\n", &saveptr); + } + free(conf_copy); + } + } + + return ret; +} + +/*=========================================================================== +FUNCTION loc_read_conf + +DESCRIPTION + Reads the specified configuration file and sets defined values based on + the passed in configuration table. This table maps strings to values to + set along with the type of each of these values. + +PARAMETERS: + conf_file_name: configuration file to read + config_table: table definition of strings to places to store information + table_length: length of the configuration table + +DEPENDENCIES + N/A + +RETURN VALUE + None + +SIDE EFFECTS + N/A +===========================================================================*/ +void loc_read_conf(const char* conf_file_name, const loc_param_s_type* config_table, + uint32_t table_length) +{ + FILE *conf_fp = NULL; + char *lasts; + loc_param_v_type config_value; + uint32_t i; + + if((conf_fp = fopen(conf_file_name, "r")) != NULL) + { + LOC_LOGD("%s: using %s", __FUNCTION__, conf_file_name); + if(table_length && config_table) { + loc_read_conf_r(conf_fp, config_table, table_length); + rewind(conf_fp); + } + loc_read_conf_r(conf_fp, loc_param_table, loc_param_num); + fclose(conf_fp); + } + /* Initialize logging mechanism with parsed data */ + loc_logger_init(DEBUG_LEVEL, TIMESTAMP); +} diff --git a/gps/utils/loc_cfg.h b/gps/utils/loc_cfg.h new file mode 100644 index 000000000..9045e1d56 --- /dev/null +++ b/gps/utils/loc_cfg.h @@ -0,0 +1,91 @@ +/* Copyright (c) 2011-2015, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef LOC_CFG_H +#define LOC_CFG_H + +#include +#include + +#define LOC_MAX_PARAM_NAME 80 +#define LOC_MAX_PARAM_STRING 80 +#define LOC_MAX_PARAM_LINE (LOC_MAX_PARAM_NAME + LOC_MAX_PARAM_STRING) + +#define UTIL_UPDATE_CONF(conf_data, len, config_table) \ + loc_update_conf((conf_data), (len), (config_table), \ + sizeof(config_table) / sizeof(config_table[0])) + +#define UTIL_READ_CONF_DEFAULT(filename) \ + loc_read_conf((filename), NULL, 0); + +#define UTIL_READ_CONF(filename, config_table) \ + loc_read_conf((filename), (config_table), sizeof(config_table) / sizeof(config_table[0])) + +/*============================================================================= + * + * MODULE TYPE DECLARATION + * + *============================================================================*/ +typedef struct +{ + const char *param_name; + void *param_ptr; + uint8_t *param_set; /* was this value set by config file? */ + char param_type; /* 'n' for number, + 's' for string, + 'f' for float */ +} loc_param_s_type; + +/*============================================================================= + * + * MODULE EXTERNAL DATA + * + *============================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + +/*============================================================================= + * + * MODULE EXPORTED FUNCTIONS + * + *============================================================================*/ +void loc_read_conf(const char* conf_file_name, + const loc_param_s_type* config_table, + uint32_t table_length); +int loc_read_conf_r(FILE *conf_fp, const loc_param_s_type* config_table, + uint32_t table_length); +int loc_update_conf(const char* conf_data, int32_t length, + const loc_param_s_type* config_table, uint32_t table_length); +#ifdef __cplusplus +} +#endif + +#endif /* LOC_CFG_H */ diff --git a/gps/utils/loc_log.cpp b/gps/utils/loc_log.cpp new file mode 100644 index 000000000..76f0c532c --- /dev/null +++ b/gps/utils/loc_log.cpp @@ -0,0 +1,242 @@ +/* Copyright (c) 2011-2012, 2015, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#define LOG_NDDEBUG 0 + +#include +#include +#include +#include "loc_log.h" +#include "msg_q.h" +#ifdef USE_GLIB +#include +#endif /* USE_GLIB */ +#include "log_util.h" +#include "platform_lib_includes.h" + +#define BUFFER_SIZE 120 + +// Logging Improvements +const char *loc_logger_boolStr[]={"False","True"}; +const char VOID_RET[] = "None"; +const char FROM_AFW[] = "===>"; +const char TO_MODEM[] = "--->"; +const char FROM_MODEM[] = "<---"; +const char TO_AFW[] = "<==="; +const char EXIT_TAG[] = "Exiting"; +const char ENTRY_TAG[] = "Entering"; +const char EXIT_ERROR_TAG[] = "Exiting with error"; + +/* Logging Mechanism */ +loc_logger_s_type loc_logger; + +/* Get names from value */ +const char* loc_get_name_from_mask(const loc_name_val_s_type table[], size_t table_size, long mask) +{ + size_t i; + for (i = 0; i < table_size; i++) + { + if (table[i].val & (long) mask) + { + return table[i].name; + } + } + return UNKNOWN_STR; +} + +/* Get names from value */ +const char* loc_get_name_from_val(const loc_name_val_s_type table[], size_t table_size, long value) +{ + size_t i; + for (i = 0; i < table_size; i++) + { + if (table[i].val == (long) value) + { + return table[i].name; + } + } + return UNKNOWN_STR; +} + +static const loc_name_val_s_type loc_msg_q_status[] = +{ + NAME_VAL( eMSG_Q_SUCCESS ), + NAME_VAL( eMSG_Q_FAILURE_GENERAL ), + NAME_VAL( eMSG_Q_INVALID_PARAMETER ), + NAME_VAL( eMSG_Q_INVALID_HANDLE ), + NAME_VAL( eMSG_Q_UNAVAILABLE_RESOURCE ), + NAME_VAL( eMSG_Q_INSUFFICIENT_BUFFER ) +}; +static const size_t loc_msg_q_status_num = LOC_TABLE_SIZE(loc_msg_q_status); + +/* Find msg_q status name */ +const char* loc_get_msg_q_status(int status) +{ + return loc_get_name_from_val(loc_msg_q_status, loc_msg_q_status_num, (long) status); +} + +const char* log_succ_fail_string(int is_succ) +{ + return is_succ? "successful" : "failed"; +} + +//Target names +static const loc_name_val_s_type target_name[] = +{ + NAME_VAL(GNSS_NONE), + NAME_VAL(GNSS_MSM), + NAME_VAL(GNSS_GSS), + NAME_VAL(GNSS_MDM), + NAME_VAL(GNSS_QCA1530), + NAME_VAL(GNSS_AUTO), + NAME_VAL(GNSS_UNKNOWN) +}; + +static const size_t target_name_num = LOC_TABLE_SIZE(target_name); + +/*=========================================================================== + +FUNCTION loc_get_target_name + +DESCRIPTION + Returns pointer to a string that contains name of the target + + XX:XX:XX.000\0 + +RETURN VALUE + The target name string + +===========================================================================*/ +const char *loc_get_target_name(unsigned int target) +{ + int index = 0; + static char ret[BUFFER_SIZE]; + + index = getTargetGnssType(target); + if( index < 0 || (unsigned)index >= target_name_num ) + index = target_name_num - 1; + + if( (target & HAS_SSC) == HAS_SSC ) { + snprintf(ret, sizeof(ret), " %s with SSC", + loc_get_name_from_val(target_name, target_name_num, (long)index) ); + } + else { + snprintf(ret, sizeof(ret), " %s without SSC", + loc_get_name_from_val(target_name, target_name_num, (long)index) ); + } + return ret; +} + + +/*=========================================================================== + +FUNCTION loc_get_time + +DESCRIPTION + Logs a callback event header. + The pointer time_string should point to a buffer of at least 13 bytes: + + XX:XX:XX.000\0 + +RETURN VALUE + The time string + +===========================================================================*/ +char *loc_get_time(char *time_string, size_t buf_size) +{ + struct timeval now; /* sec and usec */ + struct tm now_tm; /* broken-down time */ + char hms_string[80]; /* HH:MM:SS */ + + gettimeofday(&now, NULL); + localtime_r(&now.tv_sec, &now_tm); + + strftime(hms_string, sizeof hms_string, "%H:%M:%S", &now_tm); + snprintf(time_string, buf_size, "%s.%03d", hms_string, (int) (now.tv_usec / 1000)); + + return time_string; +} + + +/*=========================================================================== +FUNCTION loc_logger_init + +DESCRIPTION + Initializes the state of DEBUG_LEVEL and TIMESTAMP + +DEPENDENCIES + N/A + +RETURN VALUE + None + +SIDE EFFECTS + N/A +===========================================================================*/ +void loc_logger_init(unsigned long debug, unsigned long timestamp) +{ + loc_logger.DEBUG_LEVEL = debug; +#ifdef TARGET_BUILD_VARIANT_USER + // force user builds to 2 or less + if (loc_logger.DEBUG_LEVEL > 2) { + loc_logger.DEBUG_LEVEL = 2; + } +#endif + loc_logger.TIMESTAMP = timestamp; +} + + +/*=========================================================================== +FUNCTION get_timestamp + +DESCRIPTION + Generates a timestamp using the current system time + +DEPENDENCIES + N/A + +RETURN VALUE + Char pointer to the parameter str + +SIDE EFFECTS + N/A +===========================================================================*/ +char * get_timestamp(char *str, unsigned long buf_size) +{ + struct timeval tv; + struct timezone tz; + int hh, mm, ss; + gettimeofday(&tv, &tz); + hh = tv.tv_sec/3600%24; + mm = (tv.tv_sec%3600)/60; + ss = tv.tv_sec%60; + snprintf(str, buf_size, "%02d:%02d:%02d.%06ld", hh, mm, ss, tv.tv_usec); + return str; +} + diff --git a/gps/utils/loc_log.h b/gps/utils/loc_log.h new file mode 100644 index 000000000..be492b11d --- /dev/null +++ b/gps/utils/loc_log.h @@ -0,0 +1,71 @@ +/* Copyright (c) 2011-2012, 2015 The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef LOC_LOG_H +#define LOC_LOG_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include +#include +#include "loc_target.h" + +typedef struct +{ + const char *name; + long val; +} loc_name_val_s_type; + +#define NAME_VAL(x) {"" #x "", x } + +#define UNKNOWN_STR "UNKNOWN" + +#define CHECK_MASK(type, value, mask_var, mask) \ + (((mask_var) & (mask)) ? (type) (value) : (type) (-1)) + +#define LOC_TABLE_SIZE(table) (sizeof(table)/sizeof((table)[0])) + +/* Get names from value */ +const char* loc_get_name_from_mask(const loc_name_val_s_type table[], size_t table_size, long mask); +const char* loc_get_name_from_val(const loc_name_val_s_type table[], size_t table_size, long value); +const char* loc_get_msg_q_status(int status); +const char* loc_get_target_name(unsigned int target); + +extern const char* log_succ_fail_string(int is_succ); + +extern char *loc_get_time(char *time_string, size_t buf_size); + +#ifdef __cplusplus +} +#endif + +#endif /* LOC_LOG_H */ diff --git a/gps/utils/loc_misc_utils.cpp b/gps/utils/loc_misc_utils.cpp new file mode 100644 index 000000000..7e96313ff --- /dev/null +++ b/gps/utils/loc_misc_utils.cpp @@ -0,0 +1,114 @@ +/* Copyright (c) 2014, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include +#include +#include +#include +#include + +#define LOG_NDDEBUG 0 +#define LOG_TAG "LocSvc_misc_utils" + +int loc_util_split_string(char *raw_string, char **split_strings_ptr, + int max_num_substrings, char delimiter) +{ + int raw_string_index=0; + int num_split_strings=0; + unsigned char end_string=0; + int raw_string_length=0; + + if(!raw_string || !split_strings_ptr) { + LOC_LOGE("%s:%d]: NULL parameters", __func__, __LINE__); + num_split_strings = -1; + goto err; + } + LOC_LOGD("%s:%d]: raw string: %s\n", __func__, __LINE__, raw_string); + raw_string_length = strlen(raw_string) + 1; + split_strings_ptr[num_split_strings] = &raw_string[raw_string_index]; + for(raw_string_index=0; raw_string_index < raw_string_length; raw_string_index++) { + if(raw_string[raw_string_index] == '\0') + end_string=1; + if((raw_string[raw_string_index] == delimiter) || end_string) { + raw_string[raw_string_index] = '\0'; + LOC_LOGD("%s:%d]: split string: %s\n", + __func__, __LINE__, split_strings_ptr[num_split_strings]); + num_split_strings++; + if(((raw_string_index + 1) < raw_string_length) && + (num_split_strings < max_num_substrings)) { + split_strings_ptr[num_split_strings] = &raw_string[raw_string_index+1]; + } + else { + break; + } + } + if(end_string) + break; + } +err: + LOC_LOGD("%s:%d]: num_split_strings: %d\n", __func__, __LINE__, num_split_strings); + return num_split_strings; +} + +void loc_util_trim_space(char *org_string) +{ + char *scan_ptr, *write_ptr; + char *first_nonspace = NULL, *last_nonspace = NULL; + + if(org_string == NULL) { + LOC_LOGE("%s:%d]: NULL parameter", __func__, __LINE__); + goto err; + } + + scan_ptr = write_ptr = org_string; + + while (*scan_ptr) { + //Find the first non-space character + if ( !isspace(*scan_ptr) && first_nonspace == NULL) { + first_nonspace = scan_ptr; + } + //Once the first non-space character is found in the + //above check, keep shifting the characters to the left + //to replace the spaces + if (first_nonspace != NULL) { + *(write_ptr++) = *scan_ptr; + //Keep track of which was the last non-space character + //encountered + //last_nonspace will not be updated in the case where + //the string ends with spaces + if ( !isspace(*scan_ptr)) { + last_nonspace = write_ptr; + } + } + scan_ptr++; + } + //Add NULL terminator after the last non-space character + if (last_nonspace) { *last_nonspace = '\0'; } +err: + return; +} diff --git a/gps/utils/loc_misc_utils.h b/gps/utils/loc_misc_utils.h new file mode 100644 index 000000000..7d66d8426 --- /dev/null +++ b/gps/utils/loc_misc_utils.h @@ -0,0 +1,99 @@ +/* Copyright (c) 2014, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef _LOC_MISC_UTILS_H_ +#define _LOC_MISC_UTILS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/*=========================================================================== +FUNCTION loc_split_string + +DESCRIPTION: + This function is used to split a delimiter separated string into + sub-strings. This function does not allocate new memory to store the split + strings. Instead, it places '\0' in places of delimiters and assings the + starting address of the substring within the raw string as the string address + The input raw_string no longer remains to be a collection of sub-strings + after this function is executed. + Please make a copy of the input string before calling this function if + necessary + +PARAMETERS: + char *raw_string: is the original string with delimiter separated substrings + char **split_strings_ptr: is the arraw of pointers which will hold the addresses + of individual substrings + int max_num_substrings: is the maximum number of substrings that are expected + by the caller. The array of pointers in the above parameter + is usually this long + char delimiter: is the delimiter that separates the substrings. Examples: ' ', ';' + +DEPENDENCIES + N/A + +RETURN VALUE + int Number of split strings + +SIDE EFFECTS + The input raw_string no longer remains a delimiter separated single string. + +EXAMPLE + delimiter = ' ' //space + raw_string = "hello new user" //delimiter is space ' ' + addresses = 0123456789abcd + split_strings_ptr[0] = &raw_string[0]; //split_strings_ptr[0] contains "hello" + split_strings_ptr[1] = &raw_string[6]; //split_strings_ptr[1] contains "new" + split_strings_ptr[2] = &raw_string[a]; //split_strings_ptr[2] contains "user" + +===========================================================================*/ +int loc_util_split_string(char *raw_string, char **split_strings_ptr, int max_num_substrings, + char delimiter); + +/*=========================================================================== +FUNCTION trim_space + +DESCRIPTION + Removes leading and trailing spaces of the string + +DEPENDENCIES + N/A + +RETURN VALUE + None + +SIDE EFFECTS + N/A +===========================================================================*/ +void loc_util_trim_space(char *org_string); +#ifdef __cplusplus +} +#endif + +#endif //_LOC_MISC_UTILS_H_ diff --git a/gps/utils/loc_target.cpp b/gps/utils/loc_target.cpp new file mode 100644 index 000000000..faaedf6ca --- /dev/null +++ b/gps/utils/loc_target.cpp @@ -0,0 +1,261 @@ +/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "loc_target.h" +#include "loc_log.h" +#include "log_util.h" + +#define APQ8064_ID_1 "109" +#define APQ8064_ID_2 "153" +#define MPQ8064_ID_1 "130" +#define MSM8930_ID_1 "142" +#define MSM8930_ID_2 "116" +#define APQ8030_ID_1 "157" +#define APQ8074_ID_1 "184" + +#define LINE_LEN 100 +#define STR_LIQUID "Liquid" +#define STR_SURF "Surf" +#define STR_MTP "MTP" +#define STR_APQ "apq" +#define STR_AUTO "auto" +#define IS_STR_END(c) ((c) == '\0' || (c) == '\n' || (c) == '\r') +#define LENGTH(s) (sizeof(s) - 1) +#define GPS_CHECK_NO_ERROR 0 +#define GPS_CHECK_NO_GPS_HW 1 +/* When system server is started, it uses 20 seconds as ActivityManager + * timeout. After that it sends SIGSTOP signal to process. + */ +#define QCA1530_DETECT_TIMEOUT 15 +#define QCA1530_DETECT_PRESENT "yes" +#define QCA1530_DETECT_PROGRESS "detect" + +static unsigned int gTarget = (unsigned int)-1; + +static int read_a_line(const char * file_path, char * line, int line_size) +{ + FILE *fp; + int result = 0; + + * line = '\0'; + fp = fopen(file_path, "r" ); + if( fp == NULL ) { + LOC_LOGE("open failed: %s: %s\n", file_path, strerror(errno)); + result = -1; + } else { + int len; + fgets(line, line_size, fp); + len = strlen(line); + len = len < line_size - 1? len : line_size - 1; + line[len] = '\0'; + LOC_LOGD("cat %s: %s", file_path, line); + fclose(fp); + } + return result; +} + +/*! + * \brief Checks if QCA1530 is avalable. + * + * Function verifies if qca1530 SoC is configured on the device. The test is + * based on property value. For 1530 scenario, the value shall be one of the + * following: "yes", "no", "detect". All other values are treated equally to + * "no". When the value is "detect" the system waits for SoC detection to + * finish before returning result. + * + * \retval true - QCA1530 is available. + * \retval false - QCA1530 is not available. + */ +static bool is_qca1530(void) +{ + static const char qca1530_property_name[] = "sys.qca1530"; + bool res = false; + int ret, i; + char buf[PROPERTY_VALUE_MAX]; + + memset(buf, 0, sizeof(buf)); + + for (i = 0; i < QCA1530_DETECT_TIMEOUT; ++i) + { + ret = property_get(qca1530_property_name, buf, NULL); + if (ret < 0) + { + LOC_LOGV( "qca1530: property %s is not accessible, ret=%d", + qca1530_property_name, + ret); + + break; + } + + LOC_LOGV( "qca1530: property %s is set to %s", + qca1530_property_name, + buf); + + if (!memcmp(buf, QCA1530_DETECT_PRESENT, + sizeof(QCA1530_DETECT_PRESENT))) + { + res = true; + break; + } + if (!memcmp(buf, QCA1530_DETECT_PROGRESS, + sizeof(QCA1530_DETECT_PROGRESS))) + { + LOC_LOGV("qca1530: SoC detection is in progress."); + sleep(1); + continue; + } + break; + } + + LOC_LOGD("qca1530: detected=%s", res ? "true" : "false"); + return res; +} + +/*The character array passed to this function should have length + of atleast PROPERTY_VALUE_MAX*/ +void loc_get_target_baseband(char *baseband, int array_length) +{ + if(baseband && (array_length >= PROPERTY_VALUE_MAX)) { + property_get("ro.baseband", baseband, ""); + LOC_LOGD("%s:%d]: Baseband: %s\n", __func__, __LINE__, baseband); + } + else { + LOC_LOGE("%s:%d]: NULL parameter or array length less than PROPERTY_VALUE_MAX\n", + __func__, __LINE__); + } +} + +/*The character array passed to this function should have length + of atleast PROPERTY_VALUE_MAX*/ +void loc_get_platform_name(char *platform_name, int array_length) +{ + if(platform_name && (array_length >= PROPERTY_VALUE_MAX)) { + property_get("ro.board.platform", platform_name, ""); + LOC_LOGD("%s:%d]: Target name: %s\n", __func__, __LINE__, platform_name); + } + else { + LOC_LOGE("%s:%d]: Null parameter or array length less than PROPERTY_VALUE_MAX\n", + __func__, __LINE__); + } +} + +unsigned int loc_get_target(void) +{ + if (gTarget != (unsigned int)-1) + return gTarget; + + static const char hw_platform[] = "/sys/devices/soc0/hw_platform"; + static const char id[] = "/sys/devices/soc0/soc_id"; + static const char hw_platform_dep[] = + "/sys/devices/system/soc/soc0/hw_platform"; + static const char id_dep[] = "/sys/devices/system/soc/soc0/id"; + static const char mdm[] = "/dev/mdm"; // No such file or directory + + char rd_hw_platform[LINE_LEN]; + char rd_id[LINE_LEN]; + char rd_mdm[LINE_LEN]; + char baseband[LINE_LEN]; + + if (is_qca1530()) { + gTarget = TARGET_QCA1530; + goto detected; + } + + loc_get_target_baseband(baseband, sizeof(baseband)); + + if (!access(hw_platform, F_OK)) { + read_a_line(hw_platform, rd_hw_platform, LINE_LEN); + } else { + read_a_line(hw_platform_dep, rd_hw_platform, LINE_LEN); + } + if (!access(id, F_OK)) { + read_a_line(id, rd_id, LINE_LEN); + } else { + read_a_line(id_dep, rd_id, LINE_LEN); + } + if( !memcmp(baseband, STR_AUTO, LENGTH(STR_AUTO)) ) + { + gTarget = TARGET_AUTO; + goto detected; + } + if( !memcmp(baseband, STR_APQ, LENGTH(STR_APQ)) ){ + + if( !memcmp(rd_id, MPQ8064_ID_1, LENGTH(MPQ8064_ID_1)) + && IS_STR_END(rd_id[LENGTH(MPQ8064_ID_1)]) ) + gTarget = TARGET_MPQ; + else + gTarget = TARGET_APQ_SA; + } + else { + if( (!memcmp(rd_hw_platform, STR_LIQUID, LENGTH(STR_LIQUID)) + && IS_STR_END(rd_hw_platform[LENGTH(STR_LIQUID)])) || + (!memcmp(rd_hw_platform, STR_SURF, LENGTH(STR_SURF)) + && IS_STR_END(rd_hw_platform[LENGTH(STR_SURF)])) || + (!memcmp(rd_hw_platform, STR_MTP, LENGTH(STR_MTP)) + && IS_STR_END(rd_hw_platform[LENGTH(STR_MTP)]))) { + + if (!read_a_line( mdm, rd_mdm, LINE_LEN)) + gTarget = TARGET_MDM; + } + else if( (!memcmp(rd_id, MSM8930_ID_1, LENGTH(MSM8930_ID_1)) + && IS_STR_END(rd_id[LENGTH(MSM8930_ID_1)])) || + (!memcmp(rd_id, MSM8930_ID_2, LENGTH(MSM8930_ID_2)) + && IS_STR_END(rd_id[LENGTH(MSM8930_ID_2)])) ) + gTarget = TARGET_MSM_NO_SSC; + else + gTarget = TARGET_UNKNOWN; + } + +detected: + LOC_LOGD("HAL: %s returned %d", __FUNCTION__, gTarget); + return gTarget; +} + +/*Reads the property ro.lean to identify if this is a lean target + Returns: + 0 if not a lean and mean target + 1 if this is a lean and mean target +*/ +int loc_identify_lean_target() +{ + int ret = 0; + char lean_target[PROPERTY_VALUE_MAX]; + property_get("ro.lean", lean_target, ""); + LOC_LOGD("%s:%d]: lean target: %s\n", __func__, __LINE__, lean_target); + return !(strncmp(lean_target, "true", PROPERTY_VALUE_MAX)); +} diff --git a/gps/utils/loc_target.h b/gps/utils/loc_target.h new file mode 100644 index 000000000..3bb3b5e29 --- /dev/null +++ b/gps/utils/loc_target.h @@ -0,0 +1,82 @@ +/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef LOC_TARGET_H +#define LOC_TARGET_H +#define TARGET_SET(gnss,ssc) ( (gnss<<1)|ssc ) +#define TARGET_DEFAULT TARGET_SET(GNSS_MSM, HAS_SSC) +#define TARGET_MDM TARGET_SET(GNSS_MDM, HAS_SSC) +#define TARGET_APQ_SA TARGET_SET(GNSS_GSS, NO_SSC) +#define TARGET_MPQ TARGET_SET(GNSS_NONE,NO_SSC) +#define TARGET_MSM_NO_SSC TARGET_SET(GNSS_MSM, NO_SSC) +#define TARGET_QCA1530 TARGET_SET(GNSS_QCA1530, NO_SSC) +#define TARGET_AUTO TARGET_SET(GNSS_AUTO, NO_SSC) +#define TARGET_UNKNOWN TARGET_SET(GNSS_UNKNOWN, NO_SSC) +#define getTargetGnssType(target) (target>>1) + +#ifdef __cplusplus +extern "C" +{ +#endif + +unsigned int loc_get_target(void); + +/*The character array passed to this function should have length + of atleast PROPERTY_VALUE_MAX*/ +void loc_get_target_baseband(char *baseband, int array_length); +/*The character array passed to this function should have length + of atleast PROPERTY_VALUE_MAX*/ +void loc_get_platform_name(char *platform_name, int array_length); +/*Reads the property ro.lean to identify if this is a lean target + Returns: + 0 if not a lean and mean target + 1 if this is a lean and mean target*/ +int loc_identify_lean_target(); + +/* Please remember to update 'target_name' in loc_log.cpp, + if do any changes to this enum. */ +typedef enum { + GNSS_NONE = 0, + GNSS_MSM, + GNSS_GSS, + GNSS_MDM, + GNSS_QCA1530, + GNSS_AUTO, + GNSS_UNKNOWN +}GNSS_TARGET; + +typedef enum { + NO_SSC = 0, + HAS_SSC +}SSC_TYPE; + +#ifdef __cplusplus +} +#endif + +#endif /*LOC_TARGET_H*/ diff --git a/gps/utils/loc_timer.h b/gps/utils/loc_timer.h new file mode 100644 index 000000000..2967858ea --- /dev/null +++ b/gps/utils/loc_timer.h @@ -0,0 +1,73 @@ +/* Copyright (c) 2013,2015 The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef __LOC_DELAY_H__ +#define __LOC_DELAY_H__ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ +#include + +/* + user_data: client context pointer, passthrough. Originally received + from calling client when loc_timer_start() is called. + result: 0 if timer successfully timed out; else timer failed. +*/ +typedef void (*loc_timer_callback)(void *user_data, int32_t result); + + +/* + delay_msec: timeout value for the timer. + cb_func: callback function pointer, implemented by client. + Can not be NULL. + user_data: client context pointer, passthrough. Will be + returned when loc_timer_callback() is called. + wakeOnExpire: true if to wake up CPU (if sleeping) upon timer + expiration and notify the client. + false if to wait until next time CPU wakes up (if + sleeping) and then notify the client. + Returns the handle, which can be used to stop the timer + NULL, if timer start fails (e.g. if cb_func is NULL). +*/ +void* loc_timer_start(uint64_t delay_msec, + loc_timer_callback cb_func, + void *user_data, + bool wake_on_expire=false); + +/* + handle becomes invalid upon the return of the callback +*/ +void loc_timer_stop(void*& handle); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif //__LOC_DELAY_H__ diff --git a/gps/utils/log_util.h b/gps/utils/log_util.h new file mode 100644 index 000000000..ffd5ca979 --- /dev/null +++ b/gps/utils/log_util.h @@ -0,0 +1,189 @@ +/* Copyright (c) 2011-2014 The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef __LOG_UTIL_H__ +#define __LOG_UTIL_H__ + +#ifndef USE_GLIB +#include +#endif /* USE_GLIB */ + +#ifdef USE_GLIB + +#include +#include +#include + +#ifndef LOG_TAG +#define LOG_TAG "GPS_UTILS" + +#endif // LOG_TAG + +#endif /* USE_GLIB */ + +#ifdef __cplusplus +extern "C" +{ +#endif +/*============================================================================= + * + * LOC LOGGER TYPE DECLARATION + * + *============================================================================*/ +/* LOC LOGGER */ +typedef struct loc_logger_s +{ + unsigned long DEBUG_LEVEL; + unsigned long TIMESTAMP; +} loc_logger_s_type; + +/*============================================================================= + * + * EXTERNAL DATA + * + *============================================================================*/ +extern loc_logger_s_type loc_logger; + +// Logging Improvements +extern const char *loc_logger_boolStr[]; + +extern const char *boolStr[]; +extern const char VOID_RET[]; +extern const char FROM_AFW[]; +extern const char TO_MODEM[]; +extern const char FROM_MODEM[]; +extern const char TO_AFW[]; +extern const char EXIT_TAG[]; +extern const char ENTRY_TAG[]; +extern const char EXIT_ERROR_TAG[]; + +/*============================================================================= + * + * MODULE EXPORTED FUNCTIONS + * + *============================================================================*/ +extern void loc_logger_init(unsigned long debug, unsigned long timestamp); +extern char* get_timestamp(char* str, unsigned long buf_size); + +#ifndef DEBUG_DMN_LOC_API + +/* LOGGING MACROS */ +/*loc_logger.DEBUG_LEVEL is initialized to 0xff in loc_cfg.cpp + if that value remains unchanged, it means gps.conf did not + provide a value and we default to the initial value to use + Android's logging levels*/ +#define IF_LOC_LOGE if((loc_logger.DEBUG_LEVEL >= 1) && (loc_logger.DEBUG_LEVEL <= 5)) + +#define IF_LOC_LOGW if((loc_logger.DEBUG_LEVEL >= 2) && (loc_logger.DEBUG_LEVEL <= 5)) + +#define IF_LOC_LOGI if((loc_logger.DEBUG_LEVEL >= 3) && (loc_logger.DEBUG_LEVEL <= 5)) + +#define IF_LOC_LOGD if((loc_logger.DEBUG_LEVEL >= 4) && (loc_logger.DEBUG_LEVEL <= 5)) + +#define IF_LOC_LOGV if((loc_logger.DEBUG_LEVEL >= 5) && (loc_logger.DEBUG_LEVEL <= 5)) + +#define LOC_LOGE(...) \ +IF_LOC_LOGE { ALOGE("E/" __VA_ARGS__); } \ +else if (loc_logger.DEBUG_LEVEL == 0xff) { ALOGE("E/" __VA_ARGS__); } + +#define LOC_LOGW(...) \ +IF_LOC_LOGW { ALOGE("W/" __VA_ARGS__); } \ +else if (loc_logger.DEBUG_LEVEL == 0xff) { ALOGW("W/" __VA_ARGS__); } + +#define LOC_LOGI(...) \ +IF_LOC_LOGI { ALOGE("I/" __VA_ARGS__); } \ +else if (loc_logger.DEBUG_LEVEL == 0xff) { ALOGI("I/" __VA_ARGS__); } + +#define LOC_LOGD(...) \ +IF_LOC_LOGD { ALOGE("D/" __VA_ARGS__); } \ +else if (loc_logger.DEBUG_LEVEL == 0xff) { ALOGD("D/" __VA_ARGS__); } + +#define LOC_LOGV(...) \ +IF_LOC_LOGV { ALOGE("V/" __VA_ARGS__); } \ +else if (loc_logger.DEBUG_LEVEL == 0xff) { ALOGV("V/" __VA_ARGS__); } + +#else /* DEBUG_DMN_LOC_API */ + +#define LOC_LOGE(...) ALOGE("E/" __VA_ARGS__) + +#define LOC_LOGW(...) ALOGW("W/" __VA_ARGS__) + +#define LOC_LOGI(...) ALOGI("I/" __VA_ARGS__) + +#define LOC_LOGD(...) ALOGD("D/" __VA_ARGS__) + +#define LOC_LOGV(...) ALOGV("V/" __VA_ARGS__) + +#endif /* DEBUG_DMN_LOC_API */ + +/*============================================================================= + * + * LOGGING IMPROVEMENT MACROS + * + *============================================================================*/ +#define LOG_(LOC_LOG, ID, WHAT, SPEC, VAL) \ + do { \ + if (loc_logger.TIMESTAMP) { \ + char ts[32]; \ + LOC_LOG("[%s] %s %s line %d " #SPEC, \ + get_timestamp(ts, sizeof(ts)), ID, WHAT, __LINE__, VAL); \ + } else { \ + LOC_LOG("%s %s line %d " #SPEC, \ + ID, WHAT, __LINE__, VAL); \ + } \ + } while(0) + +#define LOG_I(ID, WHAT, SPEC, VAL) LOG_(LOC_LOGI, ID, WHAT, SPEC, VAL) +#define LOG_V(ID, WHAT, SPEC, VAL) LOG_(LOC_LOGV, ID, WHAT, SPEC, VAL) +#define LOG_E(ID, WHAT, SPEC, VAL) LOG_(LOC_LOGE, ID, WHAT, SPEC, VAL) + +#define ENTRY_LOG() LOG_V(ENTRY_TAG, __func__, %s, "") +#define EXIT_LOG(SPEC, VAL) LOG_V(EXIT_TAG, __func__, SPEC, VAL) +#define EXIT_LOG_WITH_ERROR(SPEC, VAL) \ + if (VAL != 0) { \ + LOG_E(EXIT_ERROR_TAG, __func__, SPEC, VAL); \ + } else { \ + LOG_V(EXIT_TAG, __func__, SPEC, VAL); \ + } + + +// Used for logging callflow from Android Framework +#define ENTRY_LOG_CALLFLOW() LOG_I(FROM_AFW, __func__, %s, "") +// Used for logging callflow to Modem +#define EXIT_LOG_CALLFLOW(SPEC, VAL) LOG_I(TO_MODEM, __func__, SPEC, VAL) +// Used for logging callflow from Modem(TO_MODEM, __func__, %s, "") +#define MODEM_LOG_CALLFLOW(SPEC, VAL) LOG_I(FROM_MODEM, __func__, SPEC, VAL) +// Used for logging callflow to Android Framework +#define CALLBACK_LOG_CALLFLOW(CB, SPEC, VAL) LOG_I(TO_AFW, CB, SPEC, VAL) + +#ifdef __cplusplus +} +#endif + +#endif // __LOG_UTIL_H__ diff --git a/gps/utils/msg_q.c b/gps/utils/msg_q.c new file mode 100644 index 000000000..5be8547e5 --- /dev/null +++ b/gps/utils/msg_q.c @@ -0,0 +1,336 @@ +/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "msg_q.h" + +#define LOG_TAG "LocSvc_utils_q" +#include "log_util.h" +#include "platform_lib_includes.h" +#include "linked_list.h" +#include +#include +#include + +typedef struct msg_q { + void* msg_list; /* Linked list to store information */ + pthread_cond_t list_cond; /* Condition variable for waiting on msg queue */ + pthread_mutex_t list_mutex; /* Mutex for exclusive access to message queue */ + int unblocked; /* Has this message queue been unblocked? */ +} msg_q; + +/*=========================================================================== +FUNCTION convert_linked_list_err_type + +DESCRIPTION + Converts from one set of enum values to another. + + linked_list_val: Value to convert to msg_q_enum_type + +DEPENDENCIES + N/A + +RETURN VALUE + Corresponding linked_list_enum_type in msg_q_enum_type + +SIDE EFFECTS + N/A + +===========================================================================*/ +static msq_q_err_type convert_linked_list_err_type(linked_list_err_type linked_list_val) +{ + switch( linked_list_val ) + { + case eLINKED_LIST_SUCCESS: + return eMSG_Q_SUCCESS; + case eLINKED_LIST_INVALID_PARAMETER: + return eMSG_Q_INVALID_PARAMETER; + case eLINKED_LIST_INVALID_HANDLE: + return eMSG_Q_INVALID_HANDLE; + case eLINKED_LIST_UNAVAILABLE_RESOURCE: + return eMSG_Q_UNAVAILABLE_RESOURCE; + case eLINKED_LIST_INSUFFICIENT_BUFFER: + return eMSG_Q_INSUFFICIENT_BUFFER; + + case eLINKED_LIST_FAILURE_GENERAL: + default: + return eMSG_Q_FAILURE_GENERAL; + } +} + +/* ----------------------- END INTERNAL FUNCTIONS ---------------------------------------- */ + +/*=========================================================================== + + FUNCTION: msg_q_init + + ===========================================================================*/ +msq_q_err_type msg_q_init(void** msg_q_data) +{ + if( msg_q_data == NULL ) + { + LOC_LOGE("%s: Invalid msg_q_data parameter!\n", __FUNCTION__); + return eMSG_Q_INVALID_PARAMETER; + } + + msg_q* tmp_msg_q; + tmp_msg_q = (msg_q*)calloc(1, sizeof(msg_q)); + if( tmp_msg_q == NULL ) + { + LOC_LOGE("%s: Unable to allocate space for message queue!\n", __FUNCTION__); + return eMSG_Q_FAILURE_GENERAL; + } + + if( linked_list_init(&tmp_msg_q->msg_list) != 0 ) + { + LOC_LOGE("%s: Unable to initialize storage list!\n", __FUNCTION__); + free(tmp_msg_q); + return eMSG_Q_FAILURE_GENERAL; + } + + if( pthread_mutex_init(&tmp_msg_q->list_mutex, NULL) != 0 ) + { + LOC_LOGE("%s: Unable to initialize list mutex!\n", __FUNCTION__); + linked_list_destroy(&tmp_msg_q->msg_list); + free(tmp_msg_q); + return eMSG_Q_FAILURE_GENERAL; + } + + if( pthread_cond_init(&tmp_msg_q->list_cond, NULL) != 0 ) + { + LOC_LOGE("%s: Unable to initialize msg q cond var!\n", __FUNCTION__); + linked_list_destroy(&tmp_msg_q->msg_list); + pthread_mutex_destroy(&tmp_msg_q->list_mutex); + free(tmp_msg_q); + return eMSG_Q_FAILURE_GENERAL; + } + + tmp_msg_q->unblocked = 0; + + *msg_q_data = tmp_msg_q; + + return eMSG_Q_SUCCESS; +} + +/*=========================================================================== + + FUNCTION: msg_q_init2 + + ===========================================================================*/ +const void* msg_q_init2() +{ + void* q = NULL; + if (eMSG_Q_SUCCESS != msg_q_init(&q)) { + q = NULL; + } + return q; +} + +/*=========================================================================== + + FUNCTION: msg_q_destroy + + ===========================================================================*/ +msq_q_err_type msg_q_destroy(void** msg_q_data) +{ + if( msg_q_data == NULL ) + { + LOC_LOGE("%s: Invalid msg_q_data parameter!\n", __FUNCTION__); + return eMSG_Q_INVALID_HANDLE; + } + + msg_q* p_msg_q = (msg_q*)*msg_q_data; + + linked_list_destroy(&p_msg_q->msg_list); + pthread_mutex_destroy(&p_msg_q->list_mutex); + pthread_cond_destroy(&p_msg_q->list_cond); + + p_msg_q->unblocked = 0; + + free(*msg_q_data); + *msg_q_data = NULL; + + return eMSG_Q_SUCCESS; +} + +/*=========================================================================== + + FUNCTION: msg_q_snd + + ===========================================================================*/ +msq_q_err_type msg_q_snd(void* msg_q_data, void* msg_obj, void (*dealloc)(void*)) +{ + msq_q_err_type rv; + if( msg_q_data == NULL ) + { + LOC_LOGE("%s: Invalid msg_q_data parameter!\n", __FUNCTION__); + return eMSG_Q_INVALID_HANDLE; + } + if( msg_obj == NULL ) + { + LOC_LOGE("%s: Invalid msg_obj parameter!\n", __FUNCTION__); + return eMSG_Q_INVALID_PARAMETER; + } + + msg_q* p_msg_q = (msg_q*)msg_q_data; + + pthread_mutex_lock(&p_msg_q->list_mutex); + LOC_LOGV("%s: Sending message with handle = 0x%08X\n", __FUNCTION__, msg_obj); + + if( p_msg_q->unblocked ) + { + LOC_LOGE("%s: Message queue has been unblocked.\n", __FUNCTION__); + pthread_mutex_unlock(&p_msg_q->list_mutex); + return eMSG_Q_UNAVAILABLE_RESOURCE; + } + + rv = convert_linked_list_err_type(linked_list_add(p_msg_q->msg_list, msg_obj, dealloc)); + + /* Show data is in the message queue. */ + pthread_cond_signal(&p_msg_q->list_cond); + + pthread_mutex_unlock(&p_msg_q->list_mutex); + + LOC_LOGV("%s: Finished Sending message with handle = 0x%08X\n", __FUNCTION__, msg_obj); + + return rv; +} + +/*=========================================================================== + + FUNCTION: msg_q_rcv + + ===========================================================================*/ +msq_q_err_type msg_q_rcv(void* msg_q_data, void** msg_obj) +{ + msq_q_err_type rv; + if( msg_q_data == NULL ) + { + LOC_LOGE("%s: Invalid msg_q_data parameter!\n", __FUNCTION__); + return eMSG_Q_INVALID_HANDLE; + } + + if( msg_obj == NULL ) + { + LOC_LOGE("%s: Invalid msg_obj parameter!\n", __FUNCTION__); + return eMSG_Q_INVALID_PARAMETER; + } + + msg_q* p_msg_q = (msg_q*)msg_q_data; + + LOC_LOGV("%s: Waiting on message\n", __FUNCTION__); + + pthread_mutex_lock(&p_msg_q->list_mutex); + + if( p_msg_q->unblocked ) + { + LOC_LOGE("%s: Message queue has been unblocked.\n", __FUNCTION__); + pthread_mutex_unlock(&p_msg_q->list_mutex); + return eMSG_Q_UNAVAILABLE_RESOURCE; + } + + /* Wait for data in the message queue */ + while( linked_list_empty(p_msg_q->msg_list) && !p_msg_q->unblocked ) + { + pthread_cond_wait(&p_msg_q->list_cond, &p_msg_q->list_mutex); + } + + rv = convert_linked_list_err_type(linked_list_remove(p_msg_q->msg_list, msg_obj)); + + pthread_mutex_unlock(&p_msg_q->list_mutex); + + LOC_LOGV("%s: Received message 0x%08X rv = %d\n", __FUNCTION__, *msg_obj, rv); + + return rv; +} + +/*=========================================================================== + + FUNCTION: msg_q_flush + + ===========================================================================*/ +msq_q_err_type msg_q_flush(void* msg_q_data) +{ + msq_q_err_type rv; + if ( msg_q_data == NULL ) + { + LOC_LOGE("%s: Invalid msg_q_data parameter!\n", __FUNCTION__); + return eMSG_Q_INVALID_HANDLE; + } + + msg_q* p_msg_q = (msg_q*)msg_q_data; + + LOC_LOGD("%s: Flushing Message Queue\n", __FUNCTION__); + + pthread_mutex_lock(&p_msg_q->list_mutex); + + /* Remove all elements from the list */ + rv = convert_linked_list_err_type(linked_list_flush(p_msg_q->msg_list)); + + pthread_mutex_unlock(&p_msg_q->list_mutex); + + LOC_LOGD("%s: Message Queue flushed\n", __FUNCTION__); + + return rv; +} + +/*=========================================================================== + + FUNCTION: msg_q_unblock + + ===========================================================================*/ +msq_q_err_type msg_q_unblock(void* msg_q_data) +{ + if ( msg_q_data == NULL ) + { + LOC_LOGE("%s: Invalid msg_q_data parameter!\n", __FUNCTION__); + return eMSG_Q_INVALID_HANDLE; + } + + msg_q* p_msg_q = (msg_q*)msg_q_data; + pthread_mutex_lock(&p_msg_q->list_mutex); + + if( p_msg_q->unblocked ) + { + LOC_LOGE("%s: Message queue has been unblocked.\n", __FUNCTION__); + pthread_mutex_unlock(&p_msg_q->list_mutex); + return eMSG_Q_UNAVAILABLE_RESOURCE; + } + + LOC_LOGD("%s: Unblocking Message Queue\n", __FUNCTION__); + /* Unblocking message queue */ + p_msg_q->unblocked = 1; + + /* Allow all the waiters to wake up */ + pthread_cond_broadcast(&p_msg_q->list_cond); + + pthread_mutex_unlock(&p_msg_q->list_mutex); + + LOC_LOGD("%s: Message Queue unblocked\n", __FUNCTION__); + + return eMSG_Q_SUCCESS; +} diff --git a/gps/utils/msg_q.h b/gps/utils/msg_q.h new file mode 100644 index 000000000..453b8ce3a --- /dev/null +++ b/gps/utils/msg_q.h @@ -0,0 +1,207 @@ +/* Copyright (c) 2011, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __MSG_Q_H__ +#define __MSG_Q_H__ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include + +/** Linked List Return Codes */ +typedef enum +{ + eMSG_Q_SUCCESS = 0, + /**< Request was successful. */ + eMSG_Q_FAILURE_GENERAL = -1, + /**< Failed because of a general failure. */ + eMSG_Q_INVALID_PARAMETER = -2, + /**< Failed because the request contained invalid parameters. */ + eMSG_Q_INVALID_HANDLE = -3, + /**< Failed because an invalid handle was specified. */ + eMSG_Q_UNAVAILABLE_RESOURCE = -4, + /**< Failed because an there were not enough resources. */ + eMSG_Q_INSUFFICIENT_BUFFER = -5, + /**< Failed because an the supplied buffer was too small. */ +}msq_q_err_type; + +/*=========================================================================== +FUNCTION msg_q_init + +DESCRIPTION + Initializes internal structures for message queue. + + msg_q_data: pointer to an opaque Q handle to be returned; NULL if fails + +DEPENDENCIES + N/A + +RETURN VALUE + Look at error codes above. + +SIDE EFFECTS + N/A + +===========================================================================*/ +msq_q_err_type msg_q_init(void** msg_q_data); + +/*=========================================================================== +FUNCTION msg_q_init2 + +DESCRIPTION + Initializes internal structures for message queue. + +DEPENDENCIES + N/A + +RETURN VALUE + opaque handle to the Q created; NULL if create fails + +SIDE EFFECTS + N/A + +===========================================================================*/ +const void* msg_q_init2(); + +/*=========================================================================== +FUNCTION msg_q_destroy + +DESCRIPTION + Releases internal structures for message queue. + + msg_q_data: State of message queue to be released. + +DEPENDENCIES + N/A + +RETURN VALUE + Look at error codes above. + +SIDE EFFECTS + N/A + +===========================================================================*/ +msq_q_err_type msg_q_destroy(void** msg_q_data); + +/*=========================================================================== +FUNCTION msg_q_snd + +DESCRIPTION + Sends data to the message queue. The passed in data pointer + is not modified or freed. Passed in msg_obj is expected to live throughout + the use of the msg_q (i.e. data is not allocated internally) + + msg_q_data: Message Queue to add the element to. + msgp: Pointer to data to add into message queue. + dealloc: Function used to deallocate memory for this element. Pass NULL + if you do not want data deallocated during a flush operation + +DEPENDENCIES + N/A + +RETURN VALUE + Look at error codes above. + +SIDE EFFECTS + N/A + +===========================================================================*/ +msq_q_err_type msg_q_snd(void* msg_q_data, void* msg_obj, void (*dealloc)(void*)); + +/*=========================================================================== +FUNCTION msg_q_rcv + +DESCRIPTION + Retrieves data from the message queue. msg_obj is the oldest message received + and pointer is simply removed from message queue. + + msg_q_data: Message Queue to copy data from into msgp. + msg_obj: Pointer to space to copy msg_q contents to. + +DEPENDENCIES + N/A + +RETURN VALUE + Look at error codes above. + +SIDE EFFECTS + N/A + +===========================================================================*/ +msq_q_err_type msg_q_rcv(void* msg_q_data, void** msg_obj); + +/*=========================================================================== +FUNCTION msg_q_flush + +DESCRIPTION + Function removes all elements from the message queue. + + msg_q_data: Message Queue to remove elements from. + +DEPENDENCIES + N/A + +RETURN VALUE + Look at error codes above. + +SIDE EFFECTS + N/A + +===========================================================================*/ +msq_q_err_type msg_q_flush(void* msg_q_data); + +/*=========================================================================== +FUNCTION msg_q_unblock + +DESCRIPTION + This function will stop use of the message queue. All waiters will wake up + and likely receive nothing from the queue resulting in a negative return + value. The message queue can no longer be used until it is destroyed + and initialized again after calling this function. + + msg_q_data: Message queue to unblock. + +DEPENDENCIES + N/A + +RETURN VALUE + Look at error codes above. + +SIDE EFFECTS + N/A + +===========================================================================*/ +msq_q_err_type msg_q_unblock(void* msg_q_data); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __MSG_Q_H__ */ diff --git a/gps/utils/platform_lib_abstractions/elapsed_millis_since_boot.cpp b/gps/utils/platform_lib_abstractions/elapsed_millis_since_boot.cpp new file mode 100644 index 000000000..e8cb93a9b --- /dev/null +++ b/gps/utils/platform_lib_abstractions/elapsed_millis_since_boot.cpp @@ -0,0 +1,46 @@ +/* Copyright (c) 2013, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include "platform_lib_time.h" + +int64_t systemTime(int clock) +{ + struct timeval t; + t.tv_sec = t.tv_usec = 0; + gettimeofday(&t, NULL); + return t.tv_sec*1000000LL + t.tv_usec; +} + + +int64_t elapsedMillisSinceBoot() +{ + int64_t t_us = systemTime(0); + return (int64_t) t_us / 1000LL; +} diff --git a/gps/utils/platform_lib_abstractions/platform_lib_includes.h b/gps/utils/platform_lib_abstractions/platform_lib_includes.h new file mode 100644 index 000000000..5858674f0 --- /dev/null +++ b/gps/utils/platform_lib_abstractions/platform_lib_includes.h @@ -0,0 +1,35 @@ +/* Copyright (c) 2013, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _PLATFORM_LIB_INCLUDES_H_ +#define _PLATFORM_LIB_INCLUDES_H_ + +#include "platform_lib_time.h" +#include "platform_lib_macros.h" + +#endif diff --git a/gps/utils/platform_lib_abstractions/platform_lib_macros.h b/gps/utils/platform_lib_abstractions/platform_lib_macros.h new file mode 100644 index 000000000..bc48dd99d --- /dev/null +++ b/gps/utils/platform_lib_abstractions/platform_lib_macros.h @@ -0,0 +1,81 @@ +/* Copyright (c) 2013, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __PLATFORM_LIB_MACROS_H__ +#define __PLATFORM_LIB_MACROS_H__ + +#include + +#define TS_PRINTF(format, x...) \ +{ \ + struct timeval tv; \ + struct timezone tz; \ + int hh, mm, ss; \ + gettimeofday(&tv, &tz); \ + hh = tv.tv_sec/3600%24; \ + mm = (tv.tv_sec%3600)/60; \ + ss = tv.tv_sec%60; \ + fprintf(stdout,"%02d:%02d:%02d.%06ld]" format "\n", hh, mm, ss, tv.tv_usec,##x); \ +} + + +#ifdef USE_GLIB + +#define strlcat g_strlcat +#define strlcpy g_strlcpy + +#define ALOGE(format, x...) TS_PRINTF("E/%s (%d): " format , LOG_TAG, getpid(), ##x) +#define ALOGW(format, x...) TS_PRINTF("W/%s (%d): " format , LOG_TAG, getpid(), ##x) +#define ALOGI(format, x...) TS_PRINTF("I/%s (%d): " format , LOG_TAG, getpid(), ##x) +#define ALOGD(format, x...) TS_PRINTF("D/%s (%d): " format , LOG_TAG, getpid(), ##x) +#define ALOGV(format, x...) TS_PRINTF("V/%s (%d): " format , LOG_TAG, getpid(), ##x) + +#define GETTID_PLATFORM_LIB_ABSTRACTION (syscall(SYS_gettid)) + +#define LOC_EXT_CREATE_THREAD_CB_PLATFORM_LIB_ABSTRACTION createPthread +#define ELAPSED_MILLIS_SINCE_BOOT_PLATFORM_LIB_ABSTRACTION (elapsedMillisSinceBoot()) + + +#else + +#ifdef __cplusplus +extern "C" { +#endif +pid_t gettid(void); + +#ifdef __cplusplus +} +#endif + +#define GETTID_PLATFORM_LIB_ABSTRACTION (gettid()) +#define LOC_EXT_CREATE_THREAD_CB_PLATFORM_LIB_ABSTRACTION android::AndroidRuntime::createJavaThread +#define ELAPSED_MILLIS_SINCE_BOOT_PLATFORM_LIB_ABSTRACTION (android::elapsedRealtime()) + +#endif + +#endif diff --git a/gps/utils/platform_lib_abstractions/platform_lib_time.h b/gps/utils/platform_lib_abstractions/platform_lib_time.h new file mode 100644 index 000000000..ce013afc4 --- /dev/null +++ b/gps/utils/platform_lib_abstractions/platform_lib_time.h @@ -0,0 +1,35 @@ +/* Copyright (c) 2013, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _PLATFORM_LIB_TIME_H_ +#define _PLATFORM_LIB_TIME_H_ + +int64_t systemTime(int clock); +int64_t elapsedMillisSinceBoot(); + +#endif diff --git a/healthd/Android.mk b/healthd/Android.mk new file mode 100755 index 000000000..b162bb4f5 --- /dev/null +++ b/healthd/Android.mk @@ -0,0 +1,8 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) +LOCAL_SRC_FILES := healthd_board_msm.cpp +LOCAL_MODULE := libhealthd.zuk +LOCAL_CFLAGS := -Werror +LOCAL_C_INCLUDES := system/core/healthd bootable/recovery +include $(BUILD_STATIC_LIBRARY) diff --git a/healthd/healthd_board_msm.cpp b/healthd/healthd_board_msm.cpp new file mode 100755 index 000000000..d035d0f39 --- /dev/null +++ b/healthd/healthd_board_msm.cpp @@ -0,0 +1,140 @@ +/* + *Copyright (c) 2015, The Linux Foundation. All rights reserved. + * + *Redistribution and use in source and binary forms, with or without + *modification, are permitted provided that the following conditions are + *met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + *THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + *WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + *ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + *BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + *CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + *SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + *BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + *WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + *OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + *IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "minui/minui.h" + +#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0])) + +#define BACKLIGHT_PATH "/sys/class/leds/lcd-backlight/brightness" + +#define CHARGING_ENABLED_PATH "/sys/class/power_supply/battery/charging_enabled" + +#define LOGE(x...) do { KLOG_ERROR("charger", x); } while (0) +#define LOGW(x...) do { KLOG_WARNING("charger", x); } while (0) +#define LOGV(x...) do { KLOG_DEBUG("charger", x); } while (0) + +#define STR_LEN 8 +void healthd_board_mode_charger_draw_battery( + struct android::BatteryProperties *batt_prop) +{ + char cap_str[STR_LEN]; + int x, y; + int str_len_px; + static int char_height = -1, char_width = -1; + + if (char_height == -1 && char_width == -1) + gr_font_size(&char_width, &char_height); + snprintf(cap_str, (STR_LEN - 1), "%d%%", batt_prop->batteryLevel); + str_len_px = gr_measure(cap_str); + x = (gr_fb_width() - str_len_px) / 2; + y = (gr_fb_height() + char_height) / 2; + gr_color(0xa4, 0xc6, 0x39, 255); + gr_text(x, y, cap_str, 0); +} + +void healthd_board_mode_charger_battery_update( + struct android::BatteryProperties*) +{ + +} + +#define BACKLIGHT_ON_LEVEL 100 +#define BACKLIGHT_OFF_LEVEL 0 +void healthd_board_mode_charger_set_backlight(bool en) +{ + int fd; + char buffer[10]; + + if (access(BACKLIGHT_PATH, R_OK | W_OK) != 0) + { + LOGW("Backlight control not support\n"); + return; + } + + memset(buffer, '\0', sizeof(buffer)); + fd = open(BACKLIGHT_PATH, O_RDWR); + if (fd < 0) { + LOGE("Could not open backlight node : %s\n", strerror(errno)); + goto cleanup; + } + LOGV("set backlight status to %d\n", en); + if (en) + snprintf(buffer, sizeof(buffer), "%d\n", BACKLIGHT_ON_LEVEL); + else + snprintf(buffer, sizeof(buffer), "%d\n", BACKLIGHT_OFF_LEVEL); + + if (write(fd, buffer,strlen(buffer)) < 0) { + LOGE("Could not write to backlight node : %s\n", strerror(errno)); + goto cleanup; + } +cleanup: + if (fd >= 0) + close(fd); +} + +void healthd_board_mode_charger_init() +{ + int ret; + char buff[8] = "\0"; + int charging_enabled = 0; + int fd; + + /* check the charging is enabled or not */ + fd = open(CHARGING_ENABLED_PATH, O_RDONLY); + if (fd < 0) + return; + ret = read(fd, buff, sizeof(buff)); + close(fd); + if (ret > 0 && sscanf(buff, "%d\n", &charging_enabled)) { + /* if charging is disabled, reboot and exit power off charging */ + if (charging_enabled) + return; + LOGW("android charging is disabled, exit!\n"); + android_reboot(ANDROID_RB_RESTART, 0, 0); + } +} + +void healthd_board_init(struct healthd_config*) +{ + // use defaults +} + +int healthd_board_battery_update(struct android::BatteryProperties*) +{ + // return 0 to log periodic polled battery status to kernel log + return 1; +} diff --git a/init/Android.mk b/init/Android.mk new file mode 100644 index 000000000..ce0e39a7d --- /dev/null +++ b/init/Android.mk @@ -0,0 +1,25 @@ +# +# Copyright (C) 2016 The CyanogenMod Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := optional +LOCAL_C_INCLUDES := system/core/init +LOCAL_SRC_FILES := init_z2_plus.cpp +LOCAL_MODULE := libinit_z2_plus + +include $(BUILD_STATIC_LIBRARY) diff --git a/init/init_z2_plus.cpp b/init/init_z2_plus.cpp new file mode 100644 index 000000000..4046d0b66 --- /dev/null +++ b/init/init_z2_plus.cpp @@ -0,0 +1,108 @@ +/* + Copyright (c) 2016, The CyanogenMod Project + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +#include "vendor_init.h" +#include "property_service.h" +#include "log.h" +#include "util.h" + +static int read_file2(const char *fname, char *data, int max_size) +{ + int fd, rc; + + if (max_size < 1) + return 0; + + fd = open(fname, O_RDONLY); + if (fd < 0) { + ERROR("failed to open '%s'\n", fname); + return 0; + } + + rc = read(fd, data, max_size - 1); + if ((rc > 0) && (rc < max_size)) + data[rc] = '\0'; + else + data[0] = '\0'; + close(fd); + + return 1; +} + +void init_alarm_boot_properties() +{ + char const *alarm_file = "/proc/sys/kernel/boot_reason"; + char buf[64]; + + if(read_file2(alarm_file, buf, sizeof(buf))) { + + /* + * Setup ro.alarm_boot value to true when it is RTC triggered boot up + * For existing PMIC chips, the following mapping applies + * for the value of boot_reason: + * + * 0 -> unknown + * 1 -> hard reset + * 2 -> sudden momentary power loss (SMPL) + * 3 -> real time clock (RTC) + * 4 -> DC charger inserted + * 5 -> USB charger insertd + * 6 -> PON1 pin toggled (for secondary PMICs) + * 7 -> CBLPWR_N pin toggled (for external power supply) + * 8 -> KPDPWR_N pin toggled (power key pressed) + */ + if(buf[0] == '3') + { + property_set("debug.sf.nobootanimation", "1"); + property_set("ro.alarm_boot", "true"); + } + else + property_set("ro.alarm_boot", "false"); + } +} + +void vendor_load_properties() { + char device[PROP_VALUE_MAX]; + char rf_version[PROP_VALUE_MAX]; + int rc; + + rc = property_get("ro.cm.device", device); + if (!rc || strncmp(device, "z2_plus", PROP_VALUE_MAX)) + return; + + + property_set("ro.product.model", "z2_plus"); + + + init_alarm_boot_properties(); +} + diff --git a/keylayout/fpc1020tp.kl b/keylayout/fpc1020tp.kl new file mode 100644 index 000000000..cb6998a06 --- /dev/null +++ b/keylayout/fpc1020tp.kl @@ -0,0 +1,5 @@ +key 158 BACK VIRTUAL +key 249 MENU +key 254 APP_SWITCH +key 183 HOME VIRTUAL + diff --git a/keylayout/goodix-ts.kl b/keylayout/goodix-ts.kl new file mode 100644 index 000000000..39b9e69c4 --- /dev/null +++ b/keylayout/goodix-ts.kl @@ -0,0 +1,28 @@ +# Copyright (c) 2012, 2014 The Linux Foundation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials provided +# with the distribution. +# * Neither the name of The Linux Foundation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +key 542 WAKEUP diff --git a/keylayout/gpio-keys.kl b/keylayout/gpio-keys.kl new file mode 100644 index 000000000..aaf17aba8 --- /dev/null +++ b/keylayout/gpio-keys.kl @@ -0,0 +1,5 @@ +key 115 VOLUME_UP +key 114 VOLUME_DOWN +key 102 HOME +key 528 FOCUS +key 766 CAMERA diff --git a/keylayout/msm8996-tasha-mtp-snd-card_Button_Jack.kl b/keylayout/msm8996-tasha-mtp-snd-card_Button_Jack.kl new file mode 100644 index 000000000..4ada77b58 --- /dev/null +++ b/keylayout/msm8996-tasha-mtp-snd-card_Button_Jack.kl @@ -0,0 +1,3 @@ +key 256 HEADSETHOOK +key 258 VOLUME_UP +key 259 VOLUME_DOWN diff --git a/keylayout/qpnp_pon.kl b/keylayout/qpnp_pon.kl new file mode 100644 index 000000000..280b3f0c8 --- /dev/null +++ b/keylayout/qpnp_pon.kl @@ -0,0 +1,29 @@ +# Copyright (c) 2015, The Linux Foundation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials provided +# with the distribution. +# * Neither the name of The Linux Foundation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +key 114 VOLUME_DOWN +key 116 POWER diff --git a/keylayout/synaptics_dsx.kl b/keylayout/synaptics_dsx.kl new file mode 100644 index 000000000..dc476bff4 --- /dev/null +++ b/keylayout/synaptics_dsx.kl @@ -0,0 +1,31 @@ +# Copyright (c) 2015, The Linux Foundation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials provided +# with the distribution. +# * Neither the name of The Linux Foundation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +key 158 BACK +key 139 MENU +key 102 HOME +key 217 SEARCH diff --git a/liblight/Android.mk b/liblight/Android.mk new file mode 100644 index 000000000..0b0404aa9 --- /dev/null +++ b/liblight/Android.mk @@ -0,0 +1,27 @@ +# Copyright (C) 2014 The CyanogenMod Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +LOCAL_PATH:= $(call my-dir) +# HAL module implemenation stored in +# hw/..so +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := lights.c +LOCAL_MODULE_RELATIVE_PATH := hw +LOCAL_SHARED_LIBRARIES := liblog libcutils + +LOCAL_MODULE := lights.msm8996 +LOCAL_MODULE_TAGS := optional + +include $(BUILD_SHARED_LIBRARY) diff --git a/liblight/NOTICE b/liblight/NOTICE new file mode 100644 index 000000000..7340b9e35 --- /dev/null +++ b/liblight/NOTICE @@ -0,0 +1,190 @@ + + Copyright (c) 2008, The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + diff --git a/liblight/lights.c b/liblight/lights.c new file mode 100644 index 000000000..4dc4abbe9 --- /dev/null +++ b/liblight/lights.c @@ -0,0 +1,300 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * Copyright (C) 2014 The Linux Foundation. All rights reserved. + * Copyright (C) 2016 The CyanogenMod Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "lights" + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +static pthread_once_t g_init = PTHREAD_ONCE_INIT; +static pthread_mutex_t g_lock = PTHREAD_MUTEX_INITIALIZER; + +static struct light_state_t g_attention; +static struct light_state_t g_notification; +static struct light_state_t g_battery; + +static const char RED_LED_FILE[] + = "/sys/class/leds/led:rgb_red/brightness"; + +static const char LCD_FILE[] + = "/sys/class/leds/lcd-backlight/brightness"; + +static const char RED_BLINK_FILE[] + = "/sys/class/leds/led:rgb_red/rgbbreath"; + +#define RAMP_SIZE 8 +static int BRIGHTNESS_RAMP[RAMP_SIZE] + = { 0, 12, 25, 37, 50, 72, 85, 100 }; +#define RAMP_STEP_DURATION 50 + +/** + * Device methods + */ + +static void init_globals(void) +{ + // Init the mutex + pthread_mutex_init(&g_lock, NULL); +} + +static int write_int(char const* path, int value) +{ + int fd; + static int already_warned = 0; + + fd = open(path, O_RDWR); + if (fd >= 0) { + char buffer[20]; + int bytes = snprintf(buffer, sizeof(buffer), "%d\n", value); + ssize_t amt = write(fd, buffer, (size_t)bytes); + close(fd); + return amt == -1 ? -errno : 0; + } else { + if (already_warned == 0) { + ALOGE("write_int failed to open %s\n", path); + already_warned = 1; + } + return -errno; + } +} + +static int write_str(char const* path, char* value) +{ + int fd; + static int already_warned = 0; + + fd = open(path, O_RDWR); + if (fd >= 0) { + char buffer[1024]; + int bytes = snprintf(buffer, sizeof(buffer), "%s\n", value); + ssize_t amt = write(fd, buffer, (size_t)bytes); + close(fd); + return amt == -1 ? -errno : 0; + } else { + if (already_warned == 0) { + ALOGE("write_str failed to open %s\n", path); + already_warned = 1; + } + return -errno; + } +} + +static int is_lit(struct light_state_t const* state) +{ + return state->color & 0x00ffffff; +} + +static int rgb_to_brightness(struct light_state_t const* state) +{ + int color = state->color & 0x00ffffff; + return ((77*((color>>16)&0x00ff)) + + (150*((color>>8)&0x00ff)) + (29*(color&0x00ff))) >> 8; +} + +static int set_light_backlight(struct light_device_t* dev, + struct light_state_t const* state) +{ + int err = 0; + int brightness = rgb_to_brightness(state); + if(!dev) { + return -1; + } + pthread_mutex_lock(&g_lock); + err = write_int(LCD_FILE, brightness); + pthread_mutex_unlock(&g_lock); + return err; +} + +static int set_speaker_light_locked(struct light_device_t* dev, + struct light_state_t const* state) +{ + int red; + int blink; + int onMS, offMS, stepDuration, pauseHi; + unsigned int colorRGB; + char *duty; + + if(!dev) { + return -1; + } + + switch (state->flashMode) { + case LIGHT_FLASH_TIMED: + onMS = state->flashOnMS; + offMS = state->flashOffMS; + break; + case LIGHT_FLASH_NONE: + default: + onMS = 0; + offMS = 0; + break; + } + + colorRGB = state->color; + + ALOGV("set_speaker_light_locked mode %d, colorRGB=%08X, onMS=%d, offMS=%d\n", + state->flashMode, colorRGB, onMS, offMS); + + red = (colorRGB >> 16) & 0xFF; + + blink = onMS > 0 && offMS > 0; + + // Disable all blinking to start + write_int(RED_BLINK_FILE, 0); + + if (blink) { + stepDuration = RAMP_STEP_DURATION; + pauseHi = onMS - (stepDuration * RAMP_SIZE * 2); + if (stepDuration * RAMP_SIZE * 2 > onMS) { + stepDuration = onMS / (RAMP_SIZE * 2); + pauseHi = 0; + } + + // Start the party + write_int(RED_BLINK_FILE, red); + + } else { + write_int(RED_LED_FILE, red); + } + + + return 0; +} + +static void handle_speaker_light_locked(struct light_device_t* dev) +{ + if (is_lit(&g_attention)) { + set_speaker_light_locked(dev, &g_attention); + } else if (is_lit(&g_notification)) { + set_speaker_light_locked(dev, &g_notification); + } else { + set_speaker_light_locked(dev, &g_battery); + } +} + +static int set_light_battery(struct light_device_t* dev, + struct light_state_t const* state) +{ + pthread_mutex_lock(&g_lock); + g_battery = *state; + handle_speaker_light_locked(dev); + pthread_mutex_unlock(&g_lock); + return 0; +} + +static int set_light_notifications(struct light_device_t* dev, + struct light_state_t const* state) +{ + pthread_mutex_lock(&g_lock); + + g_notification = *state; + + handle_speaker_light_locked(dev); + pthread_mutex_unlock(&g_lock); + return 0; +} + +static int set_light_attention(struct light_device_t* dev, + struct light_state_t const* state) +{ + pthread_mutex_lock(&g_lock); + g_attention = *state; + handle_speaker_light_locked(dev); + pthread_mutex_unlock(&g_lock); + return 0; +} + +/** Close the lights device */ +static int close_lights(struct light_device_t *dev) +{ + if (dev) { + free(dev); + } + return 0; +} + + +/** + * Module methods + */ + +/** Open a new instance of a lights device using name */ +static int open_lights(const struct hw_module_t* module, char const* name, + struct hw_device_t** device) +{ + int (*set_light)(struct light_device_t* dev, + struct light_state_t const* state); + + if (0 == strcmp(LIGHT_ID_BACKLIGHT, name)) + set_light = set_light_backlight; + else if (0 == strcmp(LIGHT_ID_BATTERY, name)) + set_light = set_light_battery; + else if (0 == strcmp(LIGHT_ID_NOTIFICATIONS, name)) + set_light = set_light_notifications; + else if (0 == strcmp(LIGHT_ID_ATTENTION, name)) + set_light = set_light_attention; + else + return -EINVAL; + + pthread_once(&g_init, init_globals); + + struct light_device_t *dev = malloc(sizeof(struct light_device_t)); + + if(!dev) + return -ENOMEM; + + memset(dev, 0, sizeof(*dev)); + + dev->common.tag = HARDWARE_DEVICE_TAG; + dev->common.version = 0; + dev->common.module = (struct hw_module_t*)module; + dev->common.close = (int (*)(struct hw_device_t*))close_lights; + dev->set_light = set_light; + + *device = (struct hw_device_t*)dev; + return 0; +} + +static struct hw_module_methods_t lights_module_methods = { + .open = open_lights, +}; + +/* + * The lights Module + */ +struct hw_module_t HAL_MODULE_INFO_SYM = { + .tag = HARDWARE_MODULE_TAG, + .version_major = 1, + .version_minor = 0, + .id = LIGHTS_HARDWARE_MODULE_ID, + .name = "ZUK Z2 Lights Module", + .author = "The CyanogenMod Project", + .methods = &lights_module_methods, +}; diff --git a/org.ifaa.android.manager/Android.mk b/org.ifaa.android.manager/Android.mk new file mode 100644 index 000000000..4847383db --- /dev/null +++ b/org.ifaa.android.manager/Android.mk @@ -0,0 +1,27 @@ +# +# Copyright (C) 2016 The CyanogenMod Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := $(call all-java-files-under, src) + +LOCAL_MODULE := org.ifaa.android.manager +LOCAL_MODULE_TAGS := optional +LOCAL_JAVA_LIBRARIES := bouncycastle + +include $(BUILD_JAVA_LIBRARY) diff --git a/org.ifaa.android.manager/src/android/security/keystore/SoterKeyStoreKeyPairRSAGeneratorSpi.java b/org.ifaa.android.manager/src/android/security/keystore/SoterKeyStoreKeyPairRSAGeneratorSpi.java new file mode 100644 index 000000000..eaa89d9f9 --- /dev/null +++ b/org.ifaa.android.manager/src/android/security/keystore/SoterKeyStoreKeyPairRSAGeneratorSpi.java @@ -0,0 +1,524 @@ +package android.security.keystore; + +import android.app.ActivityThread; +import android.app.Application; +import android.content.Context; +import android.os.Process; +import android.security.Credentials; +import android.security.KeyPairGeneratorSpec; +import android.security.KeyStore; +import android.security.KeyStore.State; +import android.security.keymaster.KeyCharacteristics; +import android.security.keymaster.KeymasterArguments; +import android.security.keystore.KeyProperties.BlockMode; +import android.security.keystore.KeyProperties.Digest; +import android.security.keystore.KeyProperties.EncryptionPadding; +import android.security.keystore.KeyProperties.KeyAlgorithm; +import android.security.keystore.KeyProperties.Purpose; +import android.security.keystore.KeyProperties.SignaturePadding; +import android.util.Log; +import com.android.internal.util.ArrayUtils; +import com.android.org.bouncycastle.asn1.ASN1EncodableVector; +import com.android.org.bouncycastle.asn1.ASN1InputStream; +import com.android.org.bouncycastle.asn1.ASN1Integer; +import com.android.org.bouncycastle.asn1.DERBitString; +import com.android.org.bouncycastle.asn1.DERInteger; +import com.android.org.bouncycastle.asn1.DERNull; +import com.android.org.bouncycastle.asn1.DERSequence; +import com.android.org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; +import com.android.org.bouncycastle.asn1.x509.AlgorithmIdentifier; +import com.android.org.bouncycastle.asn1.x509.Certificate; +import com.android.org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; +import com.android.org.bouncycastle.asn1.x509.TBSCertificate; +import com.android.org.bouncycastle.asn1.x509.Time; +import com.android.org.bouncycastle.asn1.x509.V3TBSCertificateGenerator; +import com.android.org.bouncycastle.asn1.x9.X9ObjectIdentifiers; +import com.android.org.bouncycastle.jce.X509Principal; +import com.android.org.bouncycastle.jce.provider.X509CertificateObject; +import com.android.org.bouncycastle.x509.X509V3CertificateGenerator; +import java.math.BigInteger; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.security.InvalidAlgorithmParameterException; +import java.security.KeyPair; +import java.security.KeyPairGeneratorSpi; +import java.security.PrivateKey; +import java.security.ProviderException; +import java.security.PublicKey; +import java.security.SecureRandom; +import java.security.UnrecoverableKeyException; +import java.security.cert.CertificateEncodingException; +import java.security.cert.X509Certificate; +import java.security.spec.AlgorithmParameterSpec; +import java.security.spec.RSAKeyGenParameterSpec; +import java.util.HashSet; +import java.util.Set; +import libcore.util.EmptyArray; + +public class SoterKeyStoreKeyPairRSAGeneratorSpi extends KeyPairGeneratorSpi { + private static final int RSA_DEFAULT_KEY_SIZE = 2048; + private static final int RSA_MAX_KEY_SIZE = 8192; + private static final int RSA_MIN_KEY_SIZE = 512; + public static final long UINT32_MAX_VALUE = 4294967295L; + private static final long UINT32_RANGE = 4294967296L; + private static final BigInteger UINT64_RANGE = BigInteger.ONE.shiftLeft(64); + public static final BigInteger UINT64_MAX_VALUE = UINT64_RANGE.subtract(BigInteger.ONE); + private static volatile SecureRandom sRng; + private boolean isAutoAddCounterWhenGetPublicKey = false; + private boolean isAutoSignedWithAttkWhenGetPublicKey = false; + private boolean isAutoSignedWithCommonkWhenGetPublicKey = false; + private boolean isForSoter = false; + private boolean isNeedNextAttk = false; + private boolean isSecmsgFidCounterSignedWhenSign = false; + private String mAutoSignedKeyNameWhenGetPublicKey = ""; + private boolean mEncryptionAtRestRequired; + private String mEntryAlias; + private String mJcaKeyAlgorithm; + private int mKeySizeBits; + private KeyStore mKeyStore; + private int mKeymasterAlgorithm = -1; + private int[] mKeymasterBlockModes; + private int[] mKeymasterDigests; + private int[] mKeymasterEncryptionPaddings; + private int[] mKeymasterPurposes; + private int[] mKeymasterSignaturePaddings; + private final int mOriginalKeymasterAlgorithm = 1; + private BigInteger mRSAPublicExponent; + private SecureRandom mRng; + private KeyGenParameterSpec mSpec; + + public void initialize(int keysize, SecureRandom random) { + throw new IllegalArgumentException(KeyGenParameterSpec.class.getName() + " required to initialize this KeyPairGenerator"); + } + + public void initialize(AlgorithmParameterSpec params, SecureRandom random) throws InvalidAlgorithmParameterException { + resetAll(); + if (params == null) { + try { + throw new InvalidAlgorithmParameterException("Must supply params of type " + KeyGenParameterSpec.class.getName() + " or " + KeyPairGeneratorSpec.class.getName()); + } catch (Throwable th) { + if (!false) { + resetAll(); + } + } + } else { + int keymasterAlgorithm = this.mOriginalKeymasterAlgorithm; + if (params instanceof KeyGenParameterSpec) { + KeyGenParameterSpec spec = (KeyGenParameterSpec) params; + this.mEntryAlias = SoterUtil.getPureKeyAliasFromKeyName(spec.getKeystoreAlias()); + this.mSpec = spec; + this.mKeymasterAlgorithm = keymasterAlgorithm; + this.mEncryptionAtRestRequired = false; + this.mKeySizeBits = spec.getKeySize(); + initAlgorithmSpecificParameters(); + if (this.mKeySizeBits == -1) { + this.mKeySizeBits = getDefaultKeySize(keymasterAlgorithm); + } + checkValidKeySize(keymasterAlgorithm, this.mKeySizeBits); + if (spec.getKeystoreAlias() == null) { + throw new InvalidAlgorithmParameterException("KeyStore entry alias not provided"); + } + try { + String jcaKeyAlgorithm = KeyAlgorithm.fromKeymasterAsymmetricKeyAlgorithm(keymasterAlgorithm); + this.mKeymasterPurposes = Purpose.allToKeymaster(spec.getPurposes()); + this.mKeymasterBlockModes = BlockMode.allToKeymaster(spec.getBlockModes()); + this.mKeymasterEncryptionPaddings = EncryptionPadding.allToKeymaster(spec.getEncryptionPaddings()); + if ((spec.getPurposes() & 1) != 0 && spec.isRandomizedEncryptionRequired()) { + int[] arr$ = this.mKeymasterEncryptionPaddings; + int len$ = arr$.length; + int i$ = 0; + while (i$ < len$) { + int keymasterPadding = arr$[i$]; + if (isKeymasterPaddingSchemeIndCpaCompatibleWithAsymmetricCrypto(keymasterPadding)) { + i$++; + } else { + throw new InvalidAlgorithmParameterException("Randomized encryption (IND-CPA) required but may be violated by padding scheme: " + EncryptionPadding.fromKeymaster(keymasterPadding) + ". See " + KeyGenParameterSpec.class.getName() + " documentation."); + } + } + } + this.mKeymasterSignaturePaddings = SignaturePadding.allToKeymaster(spec.getSignaturePaddings()); + if (spec.isDigestsSpecified()) { + this.mKeymasterDigests = Digest.allToKeymaster(spec.getDigests()); + } else { + this.mKeymasterDigests = EmptyArray.INT; + } + KeymasterUtils.addUserAuthArgs(new KeymasterArguments(), this.mSpec.isUserAuthenticationRequired(), this.mSpec.getUserAuthenticationValidityDurationSeconds()); + this.mJcaKeyAlgorithm = jcaKeyAlgorithm; + this.mRng = random; + this.mKeyStore = KeyStore.getInstance(); + if (!true) { + resetAll(); + return; + } + return; + } catch (RuntimeException e) { + throw new InvalidAlgorithmParameterException(e); + } + } + throw new InvalidAlgorithmParameterException("Unsupported params class: " + params.getClass().getName() + ". Supported: " + KeyGenParameterSpec.class.getName() + ", " + KeyPairGeneratorSpec.class.getName()); + } + } + + private void resetAll() { + this.mEntryAlias = null; + this.mJcaKeyAlgorithm = null; + this.mKeymasterAlgorithm = -1; + this.mKeymasterPurposes = null; + this.mKeymasterBlockModes = null; + this.mKeymasterEncryptionPaddings = null; + this.mKeymasterSignaturePaddings = null; + this.mKeymasterDigests = null; + this.mKeySizeBits = 0; + this.mSpec = null; + this.mRSAPublicExponent = null; + this.mEncryptionAtRestRequired = false; + this.mRng = null; + this.mKeyStore = null; + this.isForSoter = false; + this.isAutoSignedWithAttkWhenGetPublicKey = false; + this.isAutoSignedWithCommonkWhenGetPublicKey = false; + this.mAutoSignedKeyNameWhenGetPublicKey = ""; + this.isSecmsgFidCounterSignedWhenSign = false; + this.isAutoAddCounterWhenGetPublicKey = false; + this.isNeedNextAttk = false; + } + + private void initAlgorithmSpecificParameters() throws InvalidAlgorithmParameterException { + AlgorithmParameterSpec algSpecificSpec = this.mSpec.getAlgorithmParameterSpec(); + BigInteger publicExponent = RSAKeyGenParameterSpec.F4; + if (algSpecificSpec instanceof RSAKeyGenParameterSpec) { + RSAKeyGenParameterSpec rsaSpec = (RSAKeyGenParameterSpec) algSpecificSpec; + if (this.mKeySizeBits == -1) { + this.mKeySizeBits = rsaSpec.getKeysize(); + } else if (this.mKeySizeBits != rsaSpec.getKeysize()) { + throw new InvalidAlgorithmParameterException("RSA key size must match between " + this.mSpec + " and " + algSpecificSpec + ": " + this.mKeySizeBits + " vs " + rsaSpec.getKeysize()); + } + publicExponent = rsaSpec.getPublicExponent(); + if (publicExponent.compareTo(BigInteger.ZERO) < 1) { + throw new InvalidAlgorithmParameterException("RSA public exponent must be positive: " + publicExponent); + } else if (publicExponent.compareTo(UINT64_MAX_VALUE) > 0) { + throw new InvalidAlgorithmParameterException("Unsupported RSA public exponent: " + publicExponent + ". Maximum supported value: " + UINT64_MAX_VALUE); + } + } + this.mRSAPublicExponent = publicExponent; + SoterRSAKeyGenParameterSpec soterSpec = SoterUtil.convertKeyNameToParameterSpec(this.mSpec.getKeystoreAlias()); + if (soterSpec != null) { + this.isForSoter = soterSpec.isForSoter(); + this.isAutoSignedWithAttkWhenGetPublicKey = soterSpec.isAutoSignedWithAttkWhenGetPublicKey(); + this.isAutoSignedWithCommonkWhenGetPublicKey = soterSpec.isAutoSignedWithCommonkWhenGetPublicKey(); + this.mAutoSignedKeyNameWhenGetPublicKey = soterSpec.getAutoSignedKeyNameWhenGetPublicKey(); + this.isSecmsgFidCounterSignedWhenSign = soterSpec.isSecmsgFidCounterSignedWhenSign(); + this.isAutoAddCounterWhenGetPublicKey = soterSpec.isAutoAddCounterWhenGetPublicKey(); + this.isNeedNextAttk = soterSpec.isNeedUseNextAttk(); + } + } + + public KeyPair generateKeyPair() { + if (this.mKeyStore == null || this.mSpec == null) { + throw new IllegalStateException("Not initialized"); + } + int flags = this.mEncryptionAtRestRequired ? 1 : 0; + if ((flags & 1) == 0 || this.mKeyStore.state() == State.UNLOCKED) { + KeymasterArguments args = new KeymasterArguments(); + args.addUnsignedInt(805306371, (long) this.mKeySizeBits); + args.addEnum(268435458, this.mKeymasterAlgorithm); + args.addEnums(536870913, this.mKeymasterPurposes); + args.addEnums(536870916, this.mKeymasterBlockModes); + args.addEnums(536870918, this.mKeymasterEncryptionPaddings); + args.addEnums(536870918, this.mKeymasterSignaturePaddings); + args.addEnums(536870917, this.mKeymasterDigests); + KeymasterUtils.addUserAuthArgs(args, this.mSpec.isUserAuthenticationRequired(), this.mSpec.getUserAuthenticationValidityDurationSeconds()); + if (this.mSpec.getKeyValidityStart() != null) { + args.addDate(1610613136, this.mSpec.getKeyValidityStart()); + } + if (this.mSpec.getKeyValidityForOriginationEnd() != null) { + args.addDate(1610613137, this.mSpec.getKeyValidityForOriginationEnd()); + } + if (this.mSpec.getKeyValidityForConsumptionEnd() != null) { + args.addDate(1610613138, this.mSpec.getKeyValidityForConsumptionEnd()); + } + addAlgorithmSpecificParameters(args); + byte[] additionalEntropy = getRandomBytesToMixIntoKeystoreRng(this.mRng, (this.mKeySizeBits + 7) / 8); + String privateKeyAlias = "USRPKEY_" + this.mEntryAlias; + try { + Credentials.deleteAllTypesForAlias(this.mKeyStore, this.mEntryAlias); + int errorCode = this.mKeyStore.generateKey(privateKeyAlias, args, additionalEntropy, flags, new KeyCharacteristics()); + if (errorCode != 1) { + throw new ProviderException("Failed to generate key pair", KeyStore.getKeyStoreException(errorCode)); + } + KeyPair result = SoterKeyStoreProvider.loadAndroidKeyStoreKeyPairFromKeystore(this.mKeyStore, privateKeyAlias); + if (this.mJcaKeyAlgorithm.equalsIgnoreCase(result.getPrivate().getAlgorithm())) { + if (this.mKeyStore.put("USRCERT_" + this.mEntryAlias, generateSelfSignedCertificate(result.getPrivate(), result.getPublic()).getEncoded(), -1, flags)) { + if (!true) { + Credentials.deleteAllTypesForAlias(this.mKeyStore, this.mEntryAlias); + } + return result; + } + throw new ProviderException("Failed to store self-signed certificate"); + } + throw new ProviderException("Generated key pair algorithm does not match requested algorithm: " + result.getPrivate().getAlgorithm() + " vs " + this.mJcaKeyAlgorithm); + } catch (CertificateEncodingException e) { + throw new ProviderException("Failed to obtain encoded form of self-signed certificate", e); + } catch (UnrecoverableKeyException e) { + throw new ProviderException("Failed to load generated key pair from keystore", e); + } catch (Exception e) { + Credentials.deleteAllTypesForAlias(this.mKeyStore, this.mEntryAlias); + throw new ProviderException("Failed to generate self-signed certificate", e); + } + } else { + throw new IllegalStateException("Encryption at rest using secure lock screen credential requested for key pair, but the user has not yet entered the credential"); + } + } + + static byte[] getRandomBytesToMixIntoKeystoreRng(SecureRandom rng, int sizeBytes) { + if (sizeBytes <= 0) { + return EmptyArray.BYTE; + } + if (rng == null) { + rng = getRng(); + } + byte[] result = new byte[sizeBytes]; + rng.nextBytes(result); + return result; + } + + private static SecureRandom getRng() { + if (sRng == null) { + sRng = new SecureRandom(); + } + return sRng; + } + + private void addAlgorithmSpecificParameters(KeymasterArguments keymasterArgs) { + if (this.mRSAPublicExponent != null) { + keymasterArgs.addUnsignedLong(1342177480, this.mRSAPublicExponent); + } + if (this.isForSoter) { + keymasterArgs.addBoolean(1879059192); + keymasterArgs.addUnsignedInt(805317375, (long) Process.myUid()); + } + if (this.isAutoSignedWithAttkWhenGetPublicKey) { + keymasterArgs.addBoolean(1879059193); + } + if (this.isAutoSignedWithCommonkWhenGetPublicKey) { + keymasterArgs.addBoolean(1879059194); + if (!SoterUtil.isNullOrNil(this.mAutoSignedKeyNameWhenGetPublicKey)) { + keymasterArgs.addBytes(-1879037189, ("USRPKEY_" + this.mAutoSignedKeyNameWhenGetPublicKey).getBytes()); + } + } + if (this.isAutoAddCounterWhenGetPublicKey) { + keymasterArgs.addBoolean(1879059196); + } + if (this.isSecmsgFidCounterSignedWhenSign) { + keymasterArgs.addBoolean(1879059197); + } + if (this.isNeedNextAttk) { + keymasterArgs.addBoolean(1879059198); + } + } + + private X509Certificate generateSelfSignedCertificate(PrivateKey privateKey, PublicKey publicKey) throws Exception { + Log.d("Soter", "generateSelfSignedCertificate"); + String signatureAlgorithm = getCertificateSignatureAlgorithm(this.mKeymasterAlgorithm, this.mKeySizeBits, this.mSpec); + if (signatureAlgorithm == null) { + Log.d("Soter", "generateSelfSignedCertificateWithFakeSignature1"); + return generateSelfSignedCertificateWithFakeSignature(publicKey); + } + try { + Log.d("Soter", "generateSelfSignedCertificateWithValidSignature"); + return generateSelfSignedCertificateWithValidSignature(privateKey, publicKey, signatureAlgorithm); + } catch (Exception e) { + Log.d("Soter", "generateSelfSignedCertificateWithFakeSignature2"); + return generateSelfSignedCertificateWithFakeSignature(publicKey); + } + } + + private byte[] getRealKeyBlobByKeyName(String keyName) { + Log.d("Soter", "start retrieve key blob by key name: " + keyName); + return this.mKeyStore.get("USRPKEY_" + keyName); + } + + private X509Certificate generateSelfSignedCertificateWithValidSignature(PrivateKey privateKey, PublicKey publicKey, String signatureAlgorithm) throws Exception { + X509V3CertificateGenerator certGen = new X509V3CertificateGenerator(); + certGen.setPublicKey(publicKey); + certGen.setSerialNumber(this.mSpec.getCertificateSerialNumber()); + certGen.setSubjectDN(this.mSpec.getCertificateSubject()); + certGen.setIssuerDN(this.mSpec.getCertificateSubject()); + certGen.setNotBefore(this.mSpec.getCertificateNotBefore()); + certGen.setNotAfter(this.mSpec.getCertificateNotAfter()); + certGen.setSignatureAlgorithm(signatureAlgorithm); + return certGen.generate(privateKey); + } + + private X509Certificate generateSelfSignedCertificateWithFakeSignature(PublicKey publicKey) throws Exception { + AlgorithmIdentifier sigAlgId; + byte[] signature; + V3TBSCertificateGenerator tbsGenerator = new V3TBSCertificateGenerator(); + switch (this.mKeymasterAlgorithm) { + case 1: + sigAlgId = new AlgorithmIdentifier(PKCSObjectIdentifiers.sha256WithRSAEncryption, DERNull.INSTANCE); + signature = new byte[1]; + break; + case 3: + sigAlgId = new AlgorithmIdentifier(X9ObjectIdentifiers.ecdsa_with_SHA256); + ASN1EncodableVector v = new ASN1EncodableVector(); + v.add(new DERInteger(0)); + v.add(new DERInteger(0)); + signature = new DERSequence().getEncoded(); + break; + default: + throw new ProviderException("Unsupported key algorithm: " + this.mKeymasterAlgorithm); + } + ASN1InputStream publicKeyInfoIn = new ASN1InputStream(publicKey.getEncoded()); + Throwable th2 = null; + try { + tbsGenerator.setSubjectPublicKeyInfo(SubjectPublicKeyInfo.getInstance(publicKeyInfoIn.readObject())); + if (publicKeyInfoIn != null) { + if (th2 != null) { + try { + publicKeyInfoIn.close(); + } catch (Throwable x2) { + th2.addSuppressed(x2); + } + } else { + publicKeyInfoIn.close(); + } + } + tbsGenerator.setSerialNumber(new ASN1Integer(this.mSpec.getCertificateSerialNumber())); + X509Principal subject = new X509Principal(this.mSpec.getCertificateSubject().getEncoded()); + tbsGenerator.setSubject(subject); + tbsGenerator.setIssuer(subject); + tbsGenerator.setStartDate(new Time(this.mSpec.getCertificateNotBefore())); + tbsGenerator.setEndDate(new Time(this.mSpec.getCertificateNotAfter())); + tbsGenerator.setSignature(sigAlgId); + TBSCertificate tbsCertificate = tbsGenerator.generateTBSCertificate(); + ASN1EncodableVector result = new ASN1EncodableVector(); + result.add(tbsCertificate); + result.add(sigAlgId); + result.add(new DERBitString(signature)); + return new X509CertificateObject(Certificate.getInstance(new DERSequence(result))); + } finally { + if (publicKeyInfoIn != null) { + publicKeyInfoIn.close(); + } + } + } + + private static int getDefaultKeySize(int keymasterAlgorithm) { + return RSA_DEFAULT_KEY_SIZE; + } + + private static void checkValidKeySize(int keymasterAlgorithm, int keySize) throws InvalidAlgorithmParameterException { + if (keySize < RSA_MIN_KEY_SIZE || keySize > RSA_MAX_KEY_SIZE) { + throw new InvalidAlgorithmParameterException("RSA key size must be >= 512 and <= 8192"); + } + } + + private static String getCertificateSignatureAlgorithm(int keymasterAlgorithm, int keySizeBits, KeyGenParameterSpec spec) { + if ((spec.getPurposes() & 4) == 0) { + return null; + } + if (spec.isUserAuthenticationRequired()) { + return null; + } + if (!spec.isDigestsSpecified()) { + return null; + } + if (!ArrayUtils.contains(SignaturePadding.allToKeymaster(spec.getSignaturePaddings()), 5)) { + return null; + } + int maxDigestOutputSizeBits = keySizeBits - 240; + int bestKeymasterDigest = -1; + int bestDigestOutputSizeBits = -1; + for (Integer intValue : getAvailableKeymasterSignatureDigests(spec.getDigests(), getSupportedEcdsaSignatureDigests())) { + int keymasterDigest = intValue.intValue(); + int outputSizeBits = getDigestOutputSizeBits(keymasterDigest); + if (outputSizeBits <= maxDigestOutputSizeBits) { + if (bestKeymasterDigest == -1) { + bestKeymasterDigest = keymasterDigest; + bestDigestOutputSizeBits = outputSizeBits; + } else if (outputSizeBits > bestDigestOutputSizeBits) { + bestKeymasterDigest = keymasterDigest; + bestDigestOutputSizeBits = outputSizeBits; + } + } + } + if (bestKeymasterDigest == -1) { + return null; + } + return Digest.fromKeymasterToSignatureAlgorithmDigest(bestKeymasterDigest) + "WithRSA"; + } + + private static String[] getSupportedEcdsaSignatureDigests() { + return new String[]{"NONE", "SHA-1", "SHA-224", "SHA-256", "SHA-384", "SHA-512"}; + } + + private static Set getAvailableKeymasterSignatureDigests(String[] authorizedKeyDigests, String[] supportedSignatureDigests) { + Set authorizedKeymasterKeyDigests = new HashSet(); + for (int keymasterDigest : Digest.allToKeymaster(authorizedKeyDigests)) { + authorizedKeymasterKeyDigests.add(Integer.valueOf(keymasterDigest)); + } + Set supportedKeymasterSignatureDigests = new HashSet(); + for (int keymasterDigest2 : Digest.allToKeymaster(supportedSignatureDigests)) { + supportedKeymasterSignatureDigests.add(Integer.valueOf(keymasterDigest2)); + } + Set result = new HashSet(supportedKeymasterSignatureDigests); + result.retainAll(authorizedKeymasterKeyDigests); + return result; + } + + public static int getDigestOutputSizeBits(int keymasterDigest) { + switch (keymasterDigest) { + case 0: + return -1; + case 1: + return 128; + case 2: + return 160; + case 3: + return 224; + case 4: + return 256; + case 5: + return 384; + case 6: + return RSA_MIN_KEY_SIZE; + default: + throw new IllegalArgumentException("Unknown digest: " + keymasterDigest); + } + } + + public static BigInteger toUint64(long value) { + if (value >= 0) { + return BigInteger.valueOf(value); + } + return BigInteger.valueOf(value).add(UINT64_RANGE); + } + + public static boolean isKeymasterPaddingSchemeIndCpaCompatibleWithAsymmetricCrypto(int keymasterPadding) { + switch (keymasterPadding) { + case 1: + return false; + case 2: + case 4: + return true; + default: + throw new IllegalArgumentException("Unsupported asymmetric encryption padding scheme: " + keymasterPadding); + } + } + + public static Context getApplicationContext() { + Application application = ActivityThread.currentApplication(); + if (application != null) { + return application; + } + throw new IllegalStateException("Failed to obtain application Context from ActivityThread"); + } + + public static byte[] intToByteArray(int value) { + ByteBuffer converter = ByteBuffer.allocate(4); + converter.order(ByteOrder.nativeOrder()); + converter.putInt(value); + return converter.array(); + } +} diff --git a/org.ifaa.android.manager/src/android/security/keystore/SoterKeyStoreProvider.java b/org.ifaa.android.manager/src/android/security/keystore/SoterKeyStoreProvider.java new file mode 100644 index 000000000..7b3cbdc2d --- /dev/null +++ b/org.ifaa.android.manager/src/android/security/keystore/SoterKeyStoreProvider.java @@ -0,0 +1,160 @@ +package android.security.keystore; + +import android.security.KeyStore; +import android.security.keymaster.ExportResult; +import android.security.keymaster.KeyCharacteristics; +import android.security.keystore.KeyProperties.KeyAlgorithm; +import android.util.Log; +import java.security.KeyFactory; +import java.security.KeyPair; +import java.security.NoSuchAlgorithmException; +import java.security.Provider; +import java.security.ProviderException; +import java.security.PublicKey; +import java.security.Security; +import java.security.UnrecoverableKeyException; +import java.security.interfaces.ECKey; +import java.security.interfaces.ECPublicKey; +import java.security.interfaces.RSAKey; +import java.security.interfaces.RSAPublicKey; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.X509EncodedKeySpec; +import org.json.JSONException; + +public class SoterKeyStoreProvider extends Provider { + private static final String ANDROID_PACKAGE_NAME = "android.security.keystore"; + public static final String PROVIDER_NAME = "SoterKeyStore"; + private static final String SOTER_PACKAGE_NAME = "android.security.keystore"; + + public SoterKeyStoreProvider() { + super(PROVIDER_NAME, 1.0d, "provider for soter"); + put("KeyPairGenerator.RSA", "android.security.keystore.SoterKeyStoreKeyPairRSAGeneratorSpi"); + put("KeyStore.SoterKeyStore", "android.security.keystore.SoterKeyStoreSpi"); + putKeyFactoryImpl("RSA"); + } + + private void putKeyFactoryImpl(String algorithm) { + put("KeyFactory." + algorithm, "android.security.keystore.AndroidKeyStoreKeyFactorySpi"); + } + + public static void install() { + Security.addProvider(new SoterKeyStoreProvider()); + } + + public static AndroidKeyStorePrivateKey getAndroidKeyStorePrivateKey(AndroidKeyStorePublicKey publicKey) { + String keyAlgorithm = publicKey.getAlgorithm(); + if ("EC".equalsIgnoreCase(keyAlgorithm)) { + return new AndroidKeyStoreECPrivateKey(publicKey.getAlias(), ((ECKey) publicKey).getParams()); + } + if ("RSA".equalsIgnoreCase(keyAlgorithm)) { + return new AndroidKeyStoreRSAPrivateKey(publicKey.getAlias(), ((RSAKey) publicKey).getModulus()); + } + throw new ProviderException("Unsupported Android Keystore public key algorithm: " + keyAlgorithm); + } + + public static AndroidKeyStorePublicKey loadAndroidKeyStorePublicKeyFromKeystore(KeyStore keyStore, String privateKeyAlias) throws UnrecoverableKeyException { + KeyCharacteristics keyCharacteristics = new KeyCharacteristics(); + int errorCode = keyStore.getKeyCharacteristics(privateKeyAlias, null, null, keyCharacteristics); + if (errorCode != 1) { + throw ((UnrecoverableKeyException) new UnrecoverableKeyException("Failed to obtain information about private key").initCause(KeyStore.getKeyStoreException(errorCode))); + } + ExportResult exportResult = keyStore.exportKey(privateKeyAlias, 0, null, null); + if (exportResult.resultCode != 1) { + throw ((UnrecoverableKeyException) new UnrecoverableKeyException("Failed to obtain X.509 form of public key").initCause(KeyStore.getKeyStoreException(errorCode))); + } + byte[] x509EncodedPublicKey = exportResult.exportData; + Integer keymasterAlgorithm = keyCharacteristics.getEnum(268435458); + if (keymasterAlgorithm == null) { + throw new UnrecoverableKeyException("Key algorithm unknown"); + } + try { + return getAndroidKeyStorePublicKey(privateKeyAlias, KeyAlgorithm.fromKeymasterAsymmetricKeyAlgorithm(keymasterAlgorithm.intValue()), x509EncodedPublicKey); + } catch (IllegalArgumentException e) { + throw ((UnrecoverableKeyException) new UnrecoverableKeyException("Failed to load private key").initCause(e)); + } + } + + public static KeyPair loadAndroidKeyStoreKeyPairFromKeystore(KeyStore keyStore, String privateKeyAlias) throws UnrecoverableKeyException { + AndroidKeyStorePublicKey publicKey = loadAndroidKeyStorePublicKeyFromKeystore(keyStore, privateKeyAlias); + return new KeyPair(publicKey, getAndroidKeyStorePrivateKey(publicKey)); + } + + public static AndroidKeyStorePublicKey getAndroidKeyStorePublicKey(String alias, String keyAlgorithm, byte[] x509EncodedForm) { + try { + KeyFactory keyFactory = KeyFactory.getInstance(keyAlgorithm); + byte[] realPublicKey = SoterUtil.getDataFromRaw(x509EncodedForm, SoterUtil.JSON_KEY_PUBLIC); + if (realPublicKey != null) { + PublicKey publicKey = keyFactory.generatePublic(new X509EncodedKeySpec(realPublicKey)); + if ("EC".equalsIgnoreCase(keyAlgorithm)) { + Log.d("Soter", "AndroidKeyStoreECPublicKey"); + return new AndroidKeyStoreECPublicKey(alias, (ECPublicKey) publicKey); + } else if ("RSA".equalsIgnoreCase(keyAlgorithm)) { + Log.d("Soter", "AndroidKeyStoreRSAPublicKey"); + return new AndroidKeyStoreRSAPublicKey(alias, (RSAPublicKey) publicKey); + } else { + throw new ProviderException("Unsupported Android Keystore public key algorithm: " + keyAlgorithm); + } + } + throw new NullPointerException("invalid soter public key"); + } catch (NoSuchAlgorithmException e) { + throw new ProviderException("Failed to obtain " + keyAlgorithm + " KeyFactory", e); + } catch (InvalidKeySpecException e2) { + throw new ProviderException("Invalid X.509 encoding of public key", e2); + } catch (JSONException e3) { + throw new ProviderException("Not in json format"); + } + } + + public static AndroidKeyStorePrivateKey loadAndroidKeyStorePrivateKeyFromKeystore(KeyStore keyStore, String privateKeyAlias) throws UnrecoverableKeyException { + return (AndroidKeyStorePrivateKey) loadAndroidKeyStoreKeyPairFromKeystore(keyStore, privateKeyAlias).getPrivate(); + } + + public static AndroidKeyStorePublicKey loadJsonPublicKeyFromKeystore(KeyStore keyStore, String privateKeyAlias) throws UnrecoverableKeyException { + KeyCharacteristics keyCharacteristics = new KeyCharacteristics(); + int errorCode = keyStore.getKeyCharacteristics(privateKeyAlias, null, null, keyCharacteristics); + if (errorCode != 1) { + throw ((UnrecoverableKeyException) new UnrecoverableKeyException("Failed to obtain information about private key").initCause(KeyStore.getKeyStoreException(errorCode))); + } + ExportResult exportResult = keyStore.exportKey(privateKeyAlias, 0, null, null); + if (exportResult.resultCode != 1) { + throw ((UnrecoverableKeyException) new UnrecoverableKeyException("Failed to obtain X.509 form of public key").initCause(KeyStore.getKeyStoreException(errorCode))); + } + byte[] x509EncodedPublicKey = exportResult.exportData; + Integer keymasterAlgorithm = keyCharacteristics.getEnum(268435458); + if (keymasterAlgorithm == null) { + throw new UnrecoverableKeyException("Key algorithm unknown"); + } + try { + return getJsonPublicKey(privateKeyAlias, KeyAlgorithm.fromKeymasterAsymmetricKeyAlgorithm(keymasterAlgorithm.intValue()), x509EncodedPublicKey); + } catch (IllegalArgumentException e) { + throw ((UnrecoverableKeyException) new UnrecoverableKeyException("Failed to load private key").initCause(e)); + } + } + + public static AndroidKeyStorePublicKey getJsonPublicKey(String alias, String keyAlgorithm, byte[] x509EncodedForm) { + try { + KeyFactory keyFactory = KeyFactory.getInstance(keyAlgorithm); + byte[] realPublicKey = SoterUtil.getDataFromRaw(x509EncodedForm, SoterUtil.JSON_KEY_PUBLIC); + if (realPublicKey != null) { + PublicKey publicKey = keyFactory.generatePublic(new X509EncodedKeySpec(realPublicKey)); + if ("EC".equalsIgnoreCase(keyAlgorithm)) { + Log.d("Soter", "AndroidKeyStoreECPublicKey"); + return new AndroidKeyStoreECPublicKey(alias, (ECPublicKey) publicKey); + } else if ("RSA".equalsIgnoreCase(keyAlgorithm)) { + Log.d("Soter", "getJsonPublicKey"); + RSAPublicKey rsaPubKey = (RSAPublicKey) publicKey; + return new AndroidKeyStoreRSAPublicKey(alias, x509EncodedForm, rsaPubKey.getModulus(), rsaPubKey.getPublicExponent()); + } else { + throw new ProviderException("Unsupported Android Keystore public key algorithm: " + keyAlgorithm); + } + } + throw new NullPointerException("invalid soter public key"); + } catch (NoSuchAlgorithmException e) { + throw new ProviderException("Failed to obtain " + keyAlgorithm + " KeyFactory", e); + } catch (InvalidKeySpecException e2) { + throw new ProviderException("Invalid X.509 encoding of public key", e2); + } catch (JSONException e3) { + throw new ProviderException("Not in json format"); + } + } +} diff --git a/org.ifaa.android.manager/src/android/security/keystore/SoterKeyStoreSpi.java b/org.ifaa.android.manager/src/android/security/keystore/SoterKeyStoreSpi.java new file mode 100644 index 000000000..52b19660a --- /dev/null +++ b/org.ifaa.android.manager/src/android/security/keystore/SoterKeyStoreSpi.java @@ -0,0 +1,60 @@ +package android.security.keystore; + +import android.security.KeyStore; +import java.security.Key; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.UnrecoverableKeyException; + +public class SoterKeyStoreSpi extends AndroidKeyStoreSpi { + private KeyStore mKeyStore; + + public SoterKeyStoreSpi() { + this.mKeyStore = null; + this.mKeyStore = KeyStore.getInstance(); + } + + public Key engineGetKey(String alias, char[] password) throws NoSuchAlgorithmException, UnrecoverableKeyException { + if (isPrivateKeyEntry(alias)) { + String privateKeyAlias = "USRPKEY_" + alias; + if (password == null || !"from_soter_ui".equals(String.valueOf(password))) { + return SoterKeyStoreProvider.loadAndroidKeyStorePrivateKeyFromKeystore(this.mKeyStore, privateKeyAlias); + } + return SoterKeyStoreProvider.loadJsonPublicKeyFromKeystore(this.mKeyStore, privateKeyAlias); + } else if (!isSecretKeyEntry(alias)) { + return null; + } else { + return AndroidKeyStoreProvider.loadAndroidKeyStoreSecretKeyFromKeystore(this.mKeyStore, "USRSKEY_" + alias); + } + } + + private boolean isPrivateKeyEntry(String alias) { + if (alias != null) { + return this.mKeyStore.contains("USRPKEY_" + alias); + } + throw new NullPointerException("alias == null"); + } + + private boolean isSecretKeyEntry(String alias) { + if (alias != null) { + return this.mKeyStore.contains("USRSKEY_" + alias); + } + throw new NullPointerException("alias == null"); + } + + public void engineDeleteEntry(String alias) throws KeyStoreException { + boolean deletePkey = this.mKeyStore.delete("USRPKEY_" + alias); + boolean deleteCert = this.mKeyStore.delete("USRCERT_" + alias); + if (engineContainsAlias(alias) && !(deletePkey || deleteCert)) { + throw new KeyStoreException("Failed to delete entry: " + alias); + } + } + + public boolean engineContainsAlias(String alias) { + if (alias != null) { + return this.mKeyStore.contains(new StringBuilder().append("USRPKEY_").append(alias).toString()) || this.mKeyStore.contains("USRCERT_" + alias); + } else { + throw new NullPointerException("alias == null"); + } + } +} diff --git a/org.ifaa.android.manager/src/android/security/keystore/SoterRSAKeyGenParameterSpec.java b/org.ifaa.android.manager/src/android/security/keystore/SoterRSAKeyGenParameterSpec.java new file mode 100644 index 000000000..36988284e --- /dev/null +++ b/org.ifaa.android.manager/src/android/security/keystore/SoterRSAKeyGenParameterSpec.java @@ -0,0 +1,96 @@ +package android.security.keystore; + +import java.math.BigInteger; +import java.security.spec.RSAKeyGenParameterSpec; + +public class SoterRSAKeyGenParameterSpec extends RSAKeyGenParameterSpec { + private boolean isAutoAddCounterWhenGetPublicKey; + private boolean isAutoSignedWithAttkWhenGetPublicKey; + private boolean isAutoSignedWithCommonkWhenGetPublicKey; + private boolean isForSoter; + private boolean isNeedUseNextAttk; + private boolean isSecmsgFidCounterSignedWhenSign; + private String mAutoSignedKeyNameWhenGetPublicKey; + + public SoterRSAKeyGenParameterSpec(int keysize, BigInteger publicExponent, boolean isForSoter, boolean isAutoSignedWithAttkWhenGetPublicKey, boolean isAutoSignedWithCommonkWhenGetPublicKey, String signedKeyNameWhenGetPublicKey, boolean isSecmsgFidCounterSignedWhenSign, boolean isAutoAddCounterWhenGetPublicKey, boolean isNeedNextAttk) { + super(keysize, publicExponent); + this.isForSoter = false; + this.isAutoSignedWithAttkWhenGetPublicKey = false; + this.isAutoSignedWithCommonkWhenGetPublicKey = false; + this.mAutoSignedKeyNameWhenGetPublicKey = ""; + this.isSecmsgFidCounterSignedWhenSign = false; + this.isAutoAddCounterWhenGetPublicKey = false; + this.isNeedUseNextAttk = false; + this.isForSoter = isForSoter; + this.isAutoSignedWithAttkWhenGetPublicKey = isAutoSignedWithAttkWhenGetPublicKey; + this.isAutoSignedWithCommonkWhenGetPublicKey = isAutoSignedWithCommonkWhenGetPublicKey; + this.mAutoSignedKeyNameWhenGetPublicKey = signedKeyNameWhenGetPublicKey; + this.isSecmsgFidCounterSignedWhenSign = isSecmsgFidCounterSignedWhenSign; + this.isAutoAddCounterWhenGetPublicKey = isAutoAddCounterWhenGetPublicKey; + this.isNeedUseNextAttk = isNeedNextAttk; + } + + public SoterRSAKeyGenParameterSpec(boolean isForSoter, boolean isAutoSignedWithAttkWhenGetPublicKey, boolean isAutoSignedWithCommonkWhenGetPublicKey, String signedKeyNameWhenGetPublicKey, boolean isSecmsgFidCounterSignedWhenSign, boolean isAutoAddCounterWhenGetPubli, boolean isNeedNextAttkcKey) { + this(2048, RSAKeyGenParameterSpec.F4, isForSoter, isAutoSignedWithAttkWhenGetPublicKey, isAutoSignedWithCommonkWhenGetPublicKey, signedKeyNameWhenGetPublicKey, isSecmsgFidCounterSignedWhenSign, isAutoAddCounterWhenGetPubli, isNeedNextAttkcKey); + } + + public boolean isForSoter() { + return this.isForSoter; + } + + public void setIsForSoter(boolean isForSoter) { + this.isForSoter = isForSoter; + } + + public boolean isAutoSignedWithAttkWhenGetPublicKey() { + return this.isAutoSignedWithAttkWhenGetPublicKey; + } + + public void setIsAutoSignedWithAttkWhenGetPublicKey(boolean isAutoSignedWithAttkWhenGetPublicKey) { + this.isAutoSignedWithAttkWhenGetPublicKey = isAutoSignedWithAttkWhenGetPublicKey; + } + + public boolean isAutoSignedWithCommonkWhenGetPublicKey() { + return this.isAutoSignedWithCommonkWhenGetPublicKey; + } + + public void setIsAutoSignedWithCommonkWhenGetPublicKey(boolean isAutoSignedWithCommonkWhenGetPublicKey) { + this.isAutoSignedWithCommonkWhenGetPublicKey = isAutoSignedWithCommonkWhenGetPublicKey; + } + + public String getAutoSignedKeyNameWhenGetPublicKey() { + return this.mAutoSignedKeyNameWhenGetPublicKey; + } + + public void setAutoSignedKeyNameWhenGetPublicKey(String mAutoSignedKeyNameWhenGetPublicKey) { + this.mAutoSignedKeyNameWhenGetPublicKey = mAutoSignedKeyNameWhenGetPublicKey; + } + + public boolean isSecmsgFidCounterSignedWhenSign() { + return this.isSecmsgFidCounterSignedWhenSign; + } + + public void setIsSecmsgFidCounterSignedWhenSign(boolean isSecmsgFidCounterSignedWhenSign) { + this.isSecmsgFidCounterSignedWhenSign = isSecmsgFidCounterSignedWhenSign; + } + + public boolean isAutoAddCounterWhenGetPublicKey() { + return this.isAutoAddCounterWhenGetPublicKey; + } + + public void setIsAutoAddCounterWhenGetPublicKey(boolean isAutoAddCounterWhenGetPublicKey) { + this.isAutoAddCounterWhenGetPublicKey = isAutoAddCounterWhenGetPublicKey; + } + + public boolean isNeedUseNextAttk() { + return this.isNeedUseNextAttk; + } + + public void setIsNeedUseNextAttk(boolean isNeedUseNextAttk) { + this.isNeedUseNextAttk = isNeedUseNextAttk; + } + + public String toString() { + return "SoterRSAKeyGenParameterSpec{isForSoter=" + this.isForSoter + ", isAutoSignedWithAttkWhenGetPublicKey=" + this.isAutoSignedWithAttkWhenGetPublicKey + ", isAutoSignedWithCommonkWhenGetPublicKey=" + this.isAutoSignedWithCommonkWhenGetPublicKey + ", mAutoSignedKeyNameWhenGetPublicKey='" + this.mAutoSignedKeyNameWhenGetPublicKey + '\'' + ", isSecmsgFidCounterSignedWhenSign=" + this.isSecmsgFidCounterSignedWhenSign + ", isAutoAddCounterWhenGetPublicKey=" + this.isAutoAddCounterWhenGetPublicKey + ", isNeedUseNextAttk=" + this.isNeedUseNextAttk + '}'; + } +} diff --git a/org.ifaa.android.manager/src/android/security/keystore/SoterUtil.java b/org.ifaa.android.manager/src/android/security/keystore/SoterUtil.java new file mode 100644 index 000000000..16c809bb4 --- /dev/null +++ b/org.ifaa.android.manager/src/android/security/keystore/SoterUtil.java @@ -0,0 +1,166 @@ +package android.security.keystore; + +import android.util.Base64; +import android.util.Log; +import org.json.JSONException; +import org.json.JSONObject; + +public class SoterUtil { + public static final String JSON_KEY_PUBLIC = "pub_key"; + private static final String PARAM_NEED_AUTO_ADD_COUNTER_WHEN_GET_PUBLIC_KEY = "addcounter"; + private static final String PARAM_NEED_AUTO_ADD_SECMSG_FID_COUNTER_WHEN_SIGN = "secmsg_and_counter_signed_when_sign"; + private static final String PARAM_NEED_AUTO_SIGNED_WITH_ATTK_WHEN_GET_PUBLIC_KEY = "auto_signed_when_get_pubkey_attk"; + private static final String PARAM_NEED_AUTO_SIGNED_WITH_COMMON_KEY_WHEN_GET_PUBLIC_KEY = "auto_signed_when_get_pubkey"; + private static final String PARAM_NEED_NEXT_ATTK = "next_attk"; + private static final int RAW_LENGTH_PREFIX = 4; + public static final String TAG = "Soter.Util"; + + public static SoterRSAKeyGenParameterSpec convertKeyNameToParameterSpec(String name) { + if (isNullOrNil(name)) { + Log.e(TAG, "hy: null or nil when convert key name to parameter"); + return null; + } + String[] splits = name.split("\\."); + if (splits == null || splits.length <= 1) { + Log.w(TAG, "hy: pure alias, no parameter"); + return null; + } + boolean isAutoSignedWithAttkWhenGetPublicKey = false; + boolean isAutoSignedWithCommonkWhenGetPublicKey = false; + String mAutoSignedKeyNameWhenGetPublicKey = ""; + boolean isSecmsgFidCounterSignedWhenSign = false; + boolean isAutoAddCounterWhenGetPublicKey = false; + boolean isNeedNextAttk = false; + if (contains(PARAM_NEED_AUTO_SIGNED_WITH_ATTK_WHEN_GET_PUBLIC_KEY, splits)) { + isAutoSignedWithAttkWhenGetPublicKey = true; + } else { + String entireCommonKeyExpr = containsPrefix(PARAM_NEED_AUTO_SIGNED_WITH_COMMON_KEY_WHEN_GET_PUBLIC_KEY, splits); + if (!isNullOrNil(entireCommonKeyExpr)) { + String commonKeyName = retrieveKeyNameFromExpr(entireCommonKeyExpr); + if (!isNullOrNil(commonKeyName)) { + isAutoSignedWithCommonkWhenGetPublicKey = true; + mAutoSignedKeyNameWhenGetPublicKey = commonKeyName; + } + } + } + if (contains(PARAM_NEED_AUTO_ADD_SECMSG_FID_COUNTER_WHEN_SIGN, splits)) { + isSecmsgFidCounterSignedWhenSign = true; + } + if (contains(PARAM_NEED_AUTO_ADD_COUNTER_WHEN_GET_PUBLIC_KEY, splits)) { + isAutoAddCounterWhenGetPublicKey = true; + if (contains(PARAM_NEED_NEXT_ATTK, splits)) { + isNeedNextAttk = true; + } + } + SoterRSAKeyGenParameterSpec spec = new SoterRSAKeyGenParameterSpec(true, isAutoSignedWithAttkWhenGetPublicKey, isAutoSignedWithCommonkWhenGetPublicKey, mAutoSignedKeyNameWhenGetPublicKey, isSecmsgFidCounterSignedWhenSign, isAutoAddCounterWhenGetPublicKey, isNeedNextAttk); + Log.i(TAG, "hy: spec: " + spec.toString()); + return spec; + } + + private static String retrieveKeyNameFromExpr(String expr) { + if (isNullOrNil(expr)) { + Log.e(TAG, "hy: expr is null"); + return null; + } + int startPos = expr.indexOf("("); + int endPos = expr.indexOf(")"); + if (startPos >= 0 && endPos > startPos) { + return expr.substring(startPos + 1, endPos); + } + Log.e(TAG, "hy: no key name"); + return null; + } + + private static boolean contains(String target, String[] src) { + if (src == null || src.length == 0 || isNullOrNil(target)) { + Log.e(TAG, "hy: param error"); + throw new IllegalArgumentException("param error"); + } + for (String item : src) { + if (target.equals(item)) { + return true; + } + } + return false; + } + + private static String containsPrefix(String prefix, String[] src) { + if (src == null || src.length == 0 || isNullOrNil(prefix)) { + Log.e(TAG, "hy: param error"); + throw new IllegalArgumentException("param error"); + } + for (String item : src) { + if (!isNullOrNil(item) && item.startsWith(prefix)) { + return item; + } + } + return null; + } + + public static String getPureKeyAliasFromKeyName(String name) { + Log.i(TAG, "hy: retrieving pure name from: " + name); + if (isNullOrNil(name)) { + Log.e(TAG, "hy: null or nil when get pure key alias"); + return null; + } + String[] splits = name.split("\\."); + if (splits != null && splits.length > 1) { + return splits[0]; + } + Log.d(TAG, "hy: pure alias"); + return name; + } + + public static boolean isNullOrNil(String str) { + return str == null || str.equals(""); + } + + public static byte[] getDataFromRaw(byte[] origin, String jsonKey) throws JSONException { + if (isNullOrNil(jsonKey)) { + Log.e("Soter", "hy: json keyname error"); + return null; + } else if (origin == null) { + Log.e("Soter", "hy: json origin null"); + return null; + } else { + JSONObject jsonObj = retriveJsonFromExportedData(origin); + if (jsonObj == null || !jsonObj.has(jsonKey)) { + return null; + } + return Base64.decode(jsonObj.getString(jsonKey).replace("-----BEGIN PUBLIC KEY-----", "").replace("-----END PUBLIC KEY-----", "").replace("\\n", ""), 0); + } + } + + private static JSONObject retriveJsonFromExportedData(byte[] origin) { + if (origin == null) { + Log.e("Soter", "raw data is null"); + return null; + } + if (origin.length < RAW_LENGTH_PREFIX) { + Log.e("Soter", "raw data length smaller than 4"); + } + byte[] lengthBytes = new byte[RAW_LENGTH_PREFIX]; + System.arraycopy(origin, 0, lengthBytes, 0, RAW_LENGTH_PREFIX); + int rawLength = toInt(lengthBytes); + byte[] rawJsonBytes = new byte[rawLength]; + if (origin.length <= rawLength + RAW_LENGTH_PREFIX) { + Log.e("Soter", "length not correct 2"); + return null; + } + System.arraycopy(origin, RAW_LENGTH_PREFIX, rawJsonBytes, 0, rawLength); + try { + return new JSONObject(new String(rawJsonBytes)); + } catch (JSONException e) { + Log.e("Soter", "hy: can not convert to json"); + return null; + } + } + + public static int toInt(byte[] bRefArr) { + int iOutcome = 0; + for (int i = 0; i < bRefArr.length; i++) { + iOutcome += (bRefArr[i] & 255) << (i * 8); + } + return iOutcome; + } +} diff --git a/org.ifaa.android.manager/src/org/ifaa/android/manager/IFAAManager.java b/org.ifaa.android.manager/src/org/ifaa/android/manager/IFAAManager.java new file mode 100644 index 000000000..5a945c3c2 --- /dev/null +++ b/org.ifaa.android.manager/src/org/ifaa/android/manager/IFAAManager.java @@ -0,0 +1,23 @@ +package org.ifaa.android.manager; + +import android.content.Context; +import android.hardware.fingerprint.FingerprintManager; +import android.os.Build; + +public abstract class IFAAManager +{ + static + { + System.loadLibrary("ifaa_jni"); + } + + public abstract String getDeviceModel(); + + public abstract int getSupportBIOTypes(Context paramContext); + + public abstract int getVersion(); + + public native byte[] processCmd(Context paramContext, byte[] paramArrayOfByte); + + public abstract int startBIOManager(Context paramContext, int paramInt); +} diff --git a/org.ifaa.android.manager/src/org/ifaa/android/manager/IFAAManagerFactory.java b/org.ifaa.android.manager/src/org/ifaa/android/manager/IFAAManagerFactory.java new file mode 100644 index 000000000..a747b13d4 --- /dev/null +++ b/org.ifaa.android.manager/src/org/ifaa/android/manager/IFAAManagerFactory.java @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2016 The CyanogenMod Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.ifaa.android.manager; + +import android.content.ActivityNotFoundException; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; + +public class IFAAManagerFactory extends IFAAManager { + private static final int ACTIVITY_START_FAILED = -1; + private static final int ACTIVITY_START_SUCCESS = 0; + private static final int BIOTypeFingerprint = 1; + private static final int BIOTypeIris = 2; + private static final String TAG = "IFAAManagerFactory"; + public static IFAAManagerFactory mIFAAManagerFactory = null; + + public int getSupportBIOTypes(Context context) { + return BIOTypeFingerprint; + } + + public int startBIOManager(Context context, int authType) { + try { + Intent intent = new Intent(); + intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND); + intent.setComponent(new ComponentName("com.android.settings", "com.android.settings.Settings$SecuritySettingsActivity")); + context.startActivity(intent); + } catch (ActivityNotFoundException e) { + e.printStackTrace(); + } catch (Throwable th) { + } + return ACTIVITY_START_SUCCESS; + } + + public String getDeviceModel() { + return "ZUK-Z2131"; + } + + public int getVersion() { + return BIOTypeFingerprint; + } + + public static IFAAManager getIFAAManager(Context context, int authType) { + if (mIFAAManagerFactory != null) { + return mIFAAManagerFactory; + } + mIFAAManagerFactory = new IFAAManagerFactory(); + return mIFAAManagerFactory; + } +} diff --git a/overlay/frameworks/base/core/res/res/values/config.xml b/overlay/frameworks/base/core/res/res/values/config.xml new file mode 100644 index 000000000..1c9380f5e --- /dev/null +++ b/overlay/frameworks/base/core/res/res/values/config.xml @@ -0,0 +1,430 @@ + + + + + + + + 1 + 11 + 25 + 50 + 100 + 200 + 300 + 500 + 750 + 1000 + 5000 + 10000 + + + + + 7 + 12 + 17 + 29 + 35 + 47 + 75 + 114 + 130 + 170 + 195 + 220 + 255 + + + + 6 + + + 1 + + + 53 + + true + + + false + + + false + + true + + + true + + true + + + true + + + + 0 + 1 + 20 + 21 + + + + + 0 + 10 + 20 + 30 + + + + + 40 + + + + true + + + true + + + 83 + + + 64 + + + 1 + + + 3 + + + 0 + + + true + + + true + + + true + + + + + + + wifi,1,1,1,-1,true + mobile,0,0,0,-1,true + mobile_mms,2,0,4,60000,true + mobile_supl,3,0,2,60000,true + mobile_dun,4,0,2,60000,true + mobile_hipri,5,0,3,60000,true + mobile_fota,10,0,2,60000,true + mobile_ims,11,0,2,60000,true + mobile_cbs,12,0,2,60000,true + bluetooth,7,7,2,-1,true + ethernet,9,9,9,-1,true + + + + + + "1,1" + "0,1" + "7,1" + + + + + "usb\\d" + "rndis\\d" + + + + + "wlan0" + + + + + "bnep\\d" + "bt-pan" + + + + + + 0 + 1 + 4 + 5 + 7 + + + + + true + + + Android-Mms/2.0 + + + http://www.google.com/oha/rdf/ua-profile-kila.xml + + + true + + + true + + + true + + + true + + + + + true + + + true + + + true + + + true + + + false + + + true + + + true + + + false + + + 4 + + true + + + false + + com.google.android.gms + + + 17 + + + true + + + true + + com.android.systemui/com.android.systemui.doze.DozeService + + + lte:2097152,4194304,8388608,262144,524288,1048576 + lte_ca:2097152,4194304,8388608,4096,1048576,2097152 + umts:4094,87380,1220608,4096,16384,1220608 + hspa:4094,87380,1220608,4096,16384,1220608 + hsupa:4094,87380,1220608,4096,16384,1220608 + hsdpa:4094,87380,1220608,4096,16384,1220608 + hspap:4094,87380,1220608,4096,16384,1220608 + edge:4093,26280,35040,4096,16384,35040 + gprs:4092,8760,11680,4096,8760,11680 + evdo:4094,87380,524288,4096,16384,262144 + + + + 524288,1048576,2097152,262144,524288,1048576 + + + true + + + 3300 + + + true + + + true + + + com.qualcomm.location + com.qualcomm.location + + + true + diff --git a/overlay/frameworks/base/core/res/res/xml/power_profile.xml b/overlay/frameworks/base/core/res/res/xml/power_profile.xml new file mode 100644 index 000000000..fd5922119 --- /dev/null +++ b/overlay/frameworks/base/core/res/res/xml/power_profile.xml @@ -0,0 +1,126 @@ + + + 0 + 68 + 218 + 17 + 0.6 + 3 + 155 + 110 + 37.7 + 56 + 100 + 548 + 133 + 67 + 60 + + 3 + 2 + + + 2 + 2 + + + 307200 + 422400 + 480000 + 556800 + 652800 + 729600 + 844800 + 960000 + 1036800 + 1113600 + 1190400 + 1228800 + 1324800 + 1401600 + 1478400 + 1593600 + + + 307200 + 403200 + 480000 + 556800 + 652800 + 729600 + 806400 + 883200 + 940800 + 1036800 + 1113600 + 1190400 + 1248000 + 1324800 + 1401600 + 1478400 + 1555200 + 1632000 + 1708800 + 1785600 + 1824000 + 1920000 + 1996800 + 2073600 + 2150400 + + + 50 + 59 + 66 + 75.5 + 90.5 + 101.5 + 92 + 142.5 + 94.5 + 177 + 196 + 207 + 242 + 272 + 306 + 356 + + + 53 + 63 + 70 + 77 + 92.5 + 104 + 118.5 + 110 + 113 + 156 + 176 + 188 + 199 + 125 + 243 + 151 + 255 + 315 + 349 + 383 + 410 + 458 + 515 + 559 + 655 + + 4.1 + 16 + 3500 + + .0002 + .002 + .02 + .2 + 2 + + diff --git a/overlay/frameworks/base/packages/SettingsProvider/res/values/defaults.xml b/overlay/frameworks/base/packages/SettingsProvider/res/values/defaults.xml new file mode 100644 index 000000000..764d30e23 --- /dev/null +++ b/overlay/frameworks/base/packages/SettingsProvider/res/values/defaults.xml @@ -0,0 +1,26 @@ + + + + + 240000 + + true + + 53 + diff --git a/overlay/frameworks/base/packages/SystemUI/res/values/config.xml b/overlay/frameworks/base/packages/SystemUI/res/values/config.xml new file mode 100644 index 000000000..55de98324 --- /dev/null +++ b/overlay/frameworks/base/packages/SystemUI/res/values/config.xml @@ -0,0 +1,49 @@ + + + + + + + + true + + + true + + + true + + true + + + 10s,30s,60s,180s + + + true + + + 0 + + + 0 + + + diff --git a/overlay/frameworks/opt/telephony/resources/res/values/config.xml b/overlay/frameworks/opt/telephony/resources/res/values/config.xml new file mode 100644 index 000000000..688da8022 --- /dev/null +++ b/overlay/frameworks/opt/telephony/resources/res/values/config.xml @@ -0,0 +1,34 @@ + + + + + + qti-telephony-common.jar + + com.qti.internal.telephony.QtiTelephonyPlugin + diff --git a/overlay/packages/apps/CarrierConfig/res/xml/vendor.xml b/overlay/packages/apps/CarrierConfig/res/xml/vendor.xml new file mode 100644 index 000000000..1b3fad6fa --- /dev/null +++ b/overlay/packages/apps/CarrierConfig/res/xml/vendor.xml @@ -0,0 +1,11 @@ + + + + + + + true + + + + diff --git a/overlay/packages/apps/Dialer/res/values/config.xml b/overlay/packages/apps/Dialer/res/values/config.xml new file mode 100644 index 000000000..da46c3142 --- /dev/null +++ b/overlay/packages/apps/Dialer/res/values/config.xml @@ -0,0 +1,20 @@ + + + + true + 4 + diff --git a/overlay/packages/apps/Settings/res/values/config.xml b/overlay/packages/apps/Settings/res/values/config.xml new file mode 100644 index 000000000..88ade9fcd --- /dev/null +++ b/overlay/packages/apps/Settings/res/values/config.xml @@ -0,0 +1,27 @@ + + + + + true + + + 1 + diff --git a/overlay/packages/apps/Settings/res/values/dimens.xml b/overlay/packages/apps/Settings/res/values/dimens.xml new file mode 100644 index 000000000..3018619b3 --- /dev/null +++ b/overlay/packages/apps/Settings/res/values/dimens.xml @@ -0,0 +1,17 @@ + + + + + 5dp + 94.68% + diff --git a/overlay/packages/apps/Snap/res/values/config.xml b/overlay/packages/apps/Snap/res/values/config.xml new file mode 100644 index 000000000..b05f13137 --- /dev/null +++ b/overlay/packages/apps/Snap/res/values/config.xml @@ -0,0 +1,24 @@ + + + + + + + 100 + + + true + diff --git a/overlay/packages/apps/Snap/res/values/qcomstrings.xml b/overlay/packages/apps/Snap/res/values/qcomstrings.xml new file mode 100644 index 000000000..513b49e44 --- /dev/null +++ b/overlay/packages/apps/Snap/res/values/qcomstrings.xml @@ -0,0 +1,26 @@ + + + + + false + 1920x1080 + diff --git a/overlay/packages/services/Telecomm/res/values/config.xml b/overlay/packages/services/Telecomm/res/values/config.xml new file mode 100644 index 000000000..f9b8d7d26 --- /dev/null +++ b/overlay/packages/services/Telecomm/res/values/config.xml @@ -0,0 +1,39 @@ + + + + + + true + + diff --git a/overlay/packages/services/Telephony/res/values/config.xml b/overlay/packages/services/Telephony/res/values/config.xml new file mode 100644 index 000000000..88e35e728 --- /dev/null +++ b/overlay/packages/services/Telephony/res/values/config.xml @@ -0,0 +1,57 @@ + + + + + + + 1 + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + false + diff --git a/overlay/vendor/cmsdk/cm/res/res/values/config.xml b/overlay/vendor/cmsdk/cm/res/res/values/config.xml new file mode 100644 index 000000000..99747e3dd --- /dev/null +++ b/overlay/vendor/cmsdk/cm/res/res/values/config.xml @@ -0,0 +1,40 @@ + + + + + + true + 100 + true + + + + true + + + 2000 + 10000 + + + 7000 + 5000 + + 20000 + diff --git a/proprietary-files.txt b/proprietary-files.txt new file mode 100644 index 000000000..2e992b6d2 --- /dev/null +++ b/proprietary-files.txt @@ -0,0 +1,696 @@ +# ADSP +bin/adsprpcd +vendor/lib/libadsprpc.so +vendor/lib/libfastcvopt.so +vendor/lib64/libadsprpc.so +vendor/lib64/libadsp_default_listener.so + +# Audio +etc/firmware/tfa98xx.cnt +vendor/lib/libacdb-fts.so +vendor/lib/libacdbloader.so +vendor/lib/libacdbrtac.so +vendor/lib/libadiertac.so +vendor/lib/libadm.so +vendor/lib/libaudcal.so +vendor/lib/libaudiodevarb.so +vendor/lib/soundfx/libqcbassboost.so +vendor/lib/soundfx/libqcreverb.so +vendor/lib/soundfx/libqcvirt.so +vendor/lib64/libacdb-fts.so +vendor/lib64/libacdbloader.so +vendor/lib64/libacdbrtac.so +vendor/lib64/libadiertac.so +vendor/lib64/libaudcal.so +vendor/lib64/libaudiodevarb.so + +# Audio ACDB +etc/acdbdata/MTP/MTP_Bluetooth_cal.acdb +etc/acdbdata/MTP/MTP_General_cal.acdb +etc/acdbdata/MTP/MTP_Global_cal.acdb +etc/acdbdata/MTP/MTP_Handset_cal.acdb +etc/acdbdata/MTP/MTP_Hdmi_cal.acdb +etc/acdbdata/MTP/MTP_Headset_cal.acdb +etc/acdbdata/MTP/MTP_Speaker_cal.acdb + +# Bluetooth +bin/btnvtool +bin/hci_qcomm_init +bin/wcnss_filter +etc/firmware/nvm_tlv.bin +etc/firmware/nvm_tlv_1.3.bin +etc/firmware/nvm_tlv_2.1.bin +etc/firmware/nvm_tlv_3.0.bin +etc/firmware/nvm_tlv_3.2.bin +etc/firmware/rampatch_tlv.img +etc/firmware/rampatch_tlv_1.3.tlv +etc/firmware/rampatch_tlv_2.1.tlv +etc/firmware/rampatch_tlv_3.0.tlv +etc/firmware/rampatch_tlv_3.2.tlv +vendor/lib/libbtnv.so +vendor/lib64/libbtnv.so + +# Camera +bin/mm-qcamera-daemon +etc/camera/imx179_chromatix.xml +etc/camera/imx298_chromatix.xml +etc/camera/msm8996_camera.xml +lib/hw/camera.msm8996.so +lib/libFNVfbEngineHAL.so +lib/libmm-qcamera.so +lib/libmmcamera_interface.so +lib/libmmjpeg_interface.so +lib/libmorpho_image_stab4.so +lib/libmorpho_video_refiner.so +lib/libopcamera.so +lib/libopcamerahw_interface.so +lib/libopcameralib.so +lib/libqomx_core.so +vendor/lib/libSonyIMX298PdafLibrary.so +vendor/lib/libfastcvadsp_stub.so +vendor/lib/libfastcvopt.so +vendor/lib/libflash_pmic.so +vendor/lib/libjpegdhw.so +vendor/lib/libjpegdmahw.so +vendor/lib/libjpegehw.so +vendor/lib/libllvd_smore.so +vendor/lib/libmmcamera2_c2d_module.so +vendor/lib/libmmcamera2_cpp_module.so +vendor/lib/libmmcamera2_frame_algorithm.so +vendor/lib/libmmcamera2_iface_modules.so +vendor/lib/libmmcamera2_imglib_modules.so +vendor/lib/libmmcamera2_is.so +vendor/lib/libmmcamera2_isp_modules.so +vendor/lib/libmmcamera2_mct.so +vendor/lib/libmmcamera2_pp_buf_mgr.so +vendor/lib/libmmcamera2_pproc_modules.so +vendor/lib/libmmcamera2_q3a_core.so +vendor/lib/libmmcamera2_sensor_modules.so +vendor/lib/libmmcamera2_stats_algorithm.so +vendor/lib/libmmcamera2_stats_modules.so +vendor/lib/libmmcamera2_vpe_module.so +vendor/lib/libmmcamera2_wnr_module.so +vendor/lib/libmmcamera_dbg.so +vendor/lib/libmmcamera_dummyalgo.so +vendor/lib/libmmcamera_eebinparse.so +vendor/lib/libmmcamera_eeprom_util.so +vendor/lib/libmmcamera_eztune_module.so +vendor/lib/libmmcamera_faceproc.so +vendor/lib/libmmcamera_hdr_gb_lib.so +vendor/lib/libmmcamera_hvx_add_constant.so +vendor/lib/libmmcamera_hvx_grid_sum.so +vendor/lib/libmmcamera_hvx_zzHDR.so +vendor/lib/libmmcamera_imglib.so +vendor/lib/libmmcamera_imglib_faceproc_adspstub.so +vendor/lib/libmmcamera_imx179.so +vendor/lib/libmmcamera_imx298.so +vendor/lib/libmmcamera_llvd.so +vendor/lib/libmmcamera_pdaf.so +vendor/lib/libmmcamera_pdafcamif.so +vendor/lib/libmmcamera_ppbase_module.so +vendor/lib/libmmcamera_sony_imx179_eeprom.so +vendor/lib/libmmcamera_sony_imx298_eeprom.so +vendor/lib/libmmcamera_stillmore_lib.so +vendor/lib/libmmcamera_thread_services.so +vendor/lib/libmmcamera_tintless_algo.so +vendor/lib/libmmcamera_tintless_bg_pca_algo.so +vendor/lib/libmmcamera_tuning.so +vendor/lib/libmmcamera_tuning_lookup.so +vendor/lib/libmmcamera_vpu_module.so +vendor/lib/libmmjpeg.so +vendor/lib/libmmqjpeg_codec.so +vendor/lib/libmmqjpegdma.so +vendor/lib/libois_rohm_bu63165gwl.so +vendor/lib/libqomx_jpegdec.so +vendor/lib/libqomx_jpegenc_pipe.so +vendor/lib/libseemore.so + +# Camera actuators +vendor/lib/libactuator_rohm_bu63165gwl.so + +# Camera chromatix +vendor/lib/libchromatix_imx179_3a_1640x924_30fps_preview.so +vendor/lib/libchromatix_imx179_3a_1640x924_30fps_video.so +vendor/lib/libchromatix_imx179_3a_3280x1846_30fps_preview.so +vendor/lib/libchromatix_imx179_3a_3280x1846_30fps_video.so +vendor/lib/libchromatix_imx179_3a_3280x2464_30fps_facebeauty.so +vendor/lib/libchromatix_imx179_3a_3280x2464_30fps_preview.so +vendor/lib/libchromatix_imx179_3a_3280x2464_30fps_video.so +vendor/lib/libchromatix_imx179_common.so +vendor/lib/libchromatix_imx179_cpp_1640x924_30fps_liveshot.so +vendor/lib/libchromatix_imx179_cpp_1640x924_30fps_preview.so +vendor/lib/libchromatix_imx179_cpp_1640x924_30fps_snapshot.so +vendor/lib/libchromatix_imx179_cpp_1640x924_30fps_video.so +vendor/lib/libchromatix_imx179_cpp_3280x1846_30fps_liveshot.so +vendor/lib/libchromatix_imx179_cpp_3280x1846_30fps_preview.so +vendor/lib/libchromatix_imx179_cpp_3280x1846_30fps_snapshot.so +vendor/lib/libchromatix_imx179_cpp_3280x1846_30fps_video.so +vendor/lib/libchromatix_imx179_cpp_3280x2464_30fps_facebeauty.so +vendor/lib/libchromatix_imx179_cpp_3280x2464_30fps_liveshot.so +vendor/lib/libchromatix_imx179_cpp_3280x2464_30fps_nomultiframe.so +vendor/lib/libchromatix_imx179_cpp_3280x2464_30fps_preview.so +vendor/lib/libchromatix_imx179_cpp_3280x2464_30fps_snapshot.so +vendor/lib/libchromatix_imx179_cpp_3280x2464_30fps_video.so +vendor/lib/libchromatix_imx179_isp_1640x924_30fps_preview.so +vendor/lib/libchromatix_imx179_isp_1640x924_30fps_snapshot.so +vendor/lib/libchromatix_imx179_isp_1640x924_30fps_video.so +vendor/lib/libchromatix_imx179_isp_3280x1846_30fps_preview.so +vendor/lib/libchromatix_imx179_isp_3280x1846_30fps_snapshot.so +vendor/lib/libchromatix_imx179_isp_3280x1846_30fps_video.so +vendor/lib/libchromatix_imx179_isp_3280x2464_30fps_facebeauty.so +vendor/lib/libchromatix_imx179_isp_3280x2464_30fps_preview.so +vendor/lib/libchromatix_imx179_isp_3280x2464_30fps_snapshot.so +vendor/lib/libchromatix_imx179_isp_3280x2464_30fps_video.so +vendor/lib/libchromatix_imx179_postproc.so +vendor/lib/libchromatix_imx298_3a_clearshot.so +vendor/lib/libchromatix_imx298_3a_panorama.so +vendor/lib/libchromatix_imx298_4K_preview.so +vendor/lib/libchromatix_imx298_4K_video.so +vendor/lib/libchromatix_imx298_common.so +vendor/lib/libchromatix_imx298_common_manual.so +vendor/lib/libchromatix_imx298_cpp_hfr_120.so +vendor/lib/libchromatix_imx298_cpp_hfr_60.so +vendor/lib/libchromatix_imx298_cpp_hfr_90.so +vendor/lib/libchromatix_imx298_cpp_liveshot.so +vendor/lib/libchromatix_imx298_cpp_panorama_preview.so +vendor/lib/libchromatix_imx298_cpp_panorama_snapshot.so +vendor/lib/libchromatix_imx298_cpp_preview.so +vendor/lib/libchromatix_imx298_cpp_snapshot.so +vendor/lib/libchromatix_imx298_cpp_snapshot_clearshot.so +vendor/lib/libchromatix_imx298_cpp_snapshot_flash.so +vendor/lib/libchromatix_imx298_cpp_snapshot_hdr.so +vendor/lib/libchromatix_imx298_cpp_snapshot_manual.so +vendor/lib/libchromatix_imx298_cpp_snapshot_nomultiframe.so +vendor/lib/libchromatix_imx298_cpp_video.so +vendor/lib/libchromatix_imx298_cpp_video_hdr.so +vendor/lib/libchromatix_imx298_default_preview.so +vendor/lib/libchromatix_imx298_default_video.so +vendor/lib/libchromatix_imx298_hdr_snapshot_3a.so +vendor/lib/libchromatix_imx298_hdr_video_3a.so +vendor/lib/libchromatix_imx298_hfr_120.so +vendor/lib/libchromatix_imx298_hfr_120_3a.so +vendor/lib/libchromatix_imx298_hfr_60.so +vendor/lib/libchromatix_imx298_hfr_60_3a.so +vendor/lib/libchromatix_imx298_hfr_90.so +vendor/lib/libchromatix_imx298_hfr_90_3a.so +vendor/lib/libchromatix_imx298_isp_panorama.so +vendor/lib/libchromatix_imx298_liveshot.so +vendor/lib/libchromatix_imx298_postproc.so +vendor/lib/libchromatix_imx298_preview.so +vendor/lib/libchromatix_imx298_snapshot.so +vendor/lib/libchromatix_imx298_snapshot_hdr.so +vendor/lib/libchromatix_imx298_video.so +vendor/lib/libchromatix_imx298_video_hdr.so +vendor/lib/libchromatix_imx298_zsl_preview.so +vendor/lib/libchromatix_imx298_zsl_video.so + +# Camera firmware +etc/firmware/cpp_firmware_v1_1_6.fw +etc/firmware/cpp_firmware_v1_8_0.fw +etc/firmware/cpp_firmware_v1_5_2.fw +etc/firmware/cpp_firmware_v1_4_0.fw +etc/firmware/cpp_firmware_v1_5_0.fw +etc/firmware/cpp_firmware_v1_2_0.fw +etc/firmware/cpp_firmware_v1_1_1.fw +etc/firmware/cpp_firmware_v1_6_0.fw +etc/firmware/cpp_firmware_v1_10_0.fw + +# Camera sensors +vendor/lib/libmmcamera_isp_abf47.so +vendor/lib/libmmcamera_isp_aec_bg_stats47.so +vendor/lib/libmmcamera_isp_bf_stats47.so +vendor/lib/libmmcamera_isp_bg_stats46.so +vendor/lib/libmmcamera_isp_bhist_stats44.so +vendor/lib/libmmcamera_isp_black_level47.so +vendor/lib/libmmcamera_isp_bpc47.so +vendor/lib/libmmcamera_isp_cac47.so +vendor/lib/libmmcamera_isp_chroma_enhan40.so +vendor/lib/libmmcamera_isp_chroma_suppress40.so +vendor/lib/libmmcamera_isp_clamp_encoder40.so +vendor/lib/libmmcamera_isp_clamp_video40.so +vendor/lib/libmmcamera_isp_clamp_viewfinder40.so +vendor/lib/libmmcamera_isp_color_correct46.so +vendor/lib/libmmcamera_isp_color_xform_encoder46.so +vendor/lib/libmmcamera_isp_color_xform_video46.so +vendor/lib/libmmcamera_isp_color_xform_viewfinder46.so +vendor/lib/libmmcamera_isp_cs_stats46.so +vendor/lib/libmmcamera_isp_demosaic47.so +vendor/lib/libmmcamera_isp_demux40.so +vendor/lib/libmmcamera_isp_fovcrop_encoder46.so +vendor/lib/libmmcamera_isp_fovcrop_video46.so +vendor/lib/libmmcamera_isp_fovcrop_viewfinder46.so +vendor/lib/libmmcamera_isp_gamma44.so +vendor/lib/libmmcamera_isp_gic46.so +vendor/lib/libmmcamera_isp_gtm46.so +vendor/lib/libmmcamera_isp_hdr46.so +vendor/lib/libmmcamera_isp_hdr_be_stats46.so +vendor/lib/libmmcamera_isp_ihist_stats46.so +vendor/lib/libmmcamera_isp_linearization40.so +vendor/lib/libmmcamera_isp_ltm47.so +vendor/lib/libmmcamera_isp_mce40.so +vendor/lib/libmmcamera_isp_mesh_rolloff44.so +vendor/lib/libmmcamera_isp_pedestal_correct46.so +vendor/lib/libmmcamera_isp_rs_stats46.so +vendor/lib/libmmcamera_isp_scaler_encoder46.so +vendor/lib/libmmcamera_isp_scaler_video46.so +vendor/lib/libmmcamera_isp_scaler_viewfinder46.so +vendor/lib/libmmcamera_isp_sce40.so +vendor/lib/libmmcamera_isp_snr47.so +vendor/lib/libmmcamera_isp_sub_module.so + +# CNE +bin/cnd +etc/cne/SwimConfig.xml +etc/cne/andsfCne.xml +etc/permissions/ConnectivityExt.xml +etc/permissions/cneapiclient.xml +etc/permissions/com.quicinc.cne.xml +framework/ConnectivityExt.jar +framework/cneapiclient.jar +framework/com.quicinc.cne.jar +-priv-app/CNEService/CNEService.apk +vendor/lib/libNimsWrap.so +vendor/lib/libcne.so +vendor/lib/libcneapiclient.so +vendor/lib/libcneconn.so +vendor/lib/libcneqmiutils.so +vendor/lib/libvendorconn.so +vendor/lib/libwqe.so +vendor/lib/libxml.so +vendor/lib64/libNimsWrap.so +vendor/lib64/libcne.so +vendor/lib64/libcneapiclient.so +vendor/lib64/libcneconn.so +vendor/lib64/libcneqmiutils.so +vendor/lib64/libvendorconn.so +vendor/lib64/libwqe.so +vendor/lib64/libxml.so + +# Display calibration +-etc/qdcm_calib_data_samsung_s6e3fa3_1080p_cmd_mode_dsi_panel.xml +-etc/qdcm_calib_data_samsung_s6e3fa3_1080p_video_mode_dsi_panel.xml + +# DPM +bin/dpmd +etc/dpm/dpm.conf +etc/dpm/nsrm/NsrmConfiguration.xml +etc/permissions/com.qti.dpmframework.xml +etc/permissions/dpmapi.xml +framework/com.qti.dpmframework.jar +framework/dpmapi.jar +framework/tcmclient.jar +-priv-app/dpmserviceapp/dpmserviceapp.apk +vendor/lib/libdpmctmgr.so +vendor/lib/libdpmfdmgr.so +vendor/lib/libdpmframework.so +vendor/lib/libdpmnsrm.so +vendor/lib/libdpmtcm.so +vendor/lib64/libdpmctmgr.so +vendor/lib64/libdpmfdmgr.so +vendor/lib64/libdpmframework.so +vendor/lib64/libdpmnsrm.so +vendor/lib64/libdpmtcm.so + +# DRM +bin/qseecomd +vendor/bin/qseeproxydaemon +vendor/lib/libQSEEComAPI.so +vendor/lib64/lib-sec-disp.so +vendor/lib64/libGPreqcancel.so +vendor/lib64/libGPreqcancel_svc.so +vendor/lib64/libQSEEComAPI.so +vendor/lib64/libSecureUILib.so +vendor/lib64/libStDrvInt.so +vendor/lib64/libdrmfs.so +vendor/lib64/libdrmtime.so +vendor/lib64/libqisl.so +vendor/lib64/librpmb.so +vendor/lib64/libsecureui.so +vendor/lib64/libsecureui_svcsock.so +vendor/lib64/libssd.so + +# Fingerprint sensor +bin/qfp-daemon +lib64/hw/fingerprint.msm8996.so +lib64/lib_fpc_tac_shared.so +vendor/lib64/libqfp-service.so +vendor/lib64/qfp.wakeup.so + +# Gatekeeper +vendor/lib/hw/gatekeeper.msm8996.so +vendor/lib64/hw/gatekeeper.msm8996.so + +# GPS +bin/loc_launcher +etc/permissions/com.qti.location.sdk.xml +etc/permissions/com.qualcomm.location.xml +framework/com.qti.location.sdk.jar +-lib/libloc_api_v02.so +-lib64/libloc_api_v02.so +-priv-app/com.qualcomm.location/com.qualcomm.location.apk +vendor/bin/slim_daemon +vendor/lib/hw/flp.default.so +vendor/lib/libalarmservice_jni.so +vendor/lib/libdataitems.so +vendor/lib/libflp.so +vendor/lib/libgeofence.so +vendor/lib/libizat_core.so +vendor/lib/liblbs_core.so +vendor/lib/libloc_ext.so +vendor/lib/liblocationservice.so +vendor/lib/liblocationservice_glue.so +vendor/lib/liblowi_client.so +vendor/lib/libquipc_os_api.so +vendor/lib/libulp2.so +vendor/lib/libxtadapter.so +vendor/lib/libxtwifi_ulp_adaptor.so +vendor/lib/libxt_native.so +vendor/lib64/hw/flp.default.so +vendor/lib64/libalarmservice_jni.so +vendor/lib64/libdataitems.so +vendor/lib64/libflp.so +vendor/lib64/libgeofence.so +vendor/lib64/libizat_core.so +vendor/lib64/liblbs_core.so +vendor/lib64/libloc_ext.so +vendor/lib64/libloc_xtra.so +vendor/lib64/liblocationservice.so +vendor/lib64/liblocationservice_glue.so +vendor/lib64/liblowi_client.so +vendor/lib64/liblowi_wifihal.so +vendor/lib64/liblowi_wifihal_nl.so +vendor/lib64/libquipc_os_api.so +vendor/lib64/libulp2.so +vendor/lib64/libxtadapter.so +vendor/lib64/libxtwifi_ulp_adaptor.so + +# Graphics +vendor/lib/egl/eglSubDriverAndroid.so +vendor/lib/egl/libEGL_adreno.so +vendor/lib/egl/libGLESv1_CM_adreno.so +vendor/lib/egl/libGLESv2_adreno.so +vendor/lib/egl/libQTapGLES.so +vendor/lib/egl/libq3dtools_adreno.so +vendor/lib/egl/libq3dtools_esx.so +vendor/lib/libC2D2.so +vendor/lib/libCB.so +vendor/lib/libOpenCL.so +vendor/lib/libRSDriver_adreno.so +vendor/lib/libadreno_utils.so +vendor/lib/libbccQTI.so +vendor/lib/libc2d30-a5xx.so +vendor/lib/libc2d30_bltlib.so +vendor/lib/libgsl.so +vendor/lib/libllvm-glnext.so +vendor/lib/libllvm-qcom.so +vendor/lib/libmm-disp-apis.so +vendor/lib/libmm-qdcm.so +vendor/lib/libmmQSM.so +vendor/lib/librs_adreno.so +vendor/lib/librs_adreno_sha1.so +vendor/lib/libsd_sdk_display.so +-vendor/lib/libsdm-disp-apis.so +vendor/lib64/egl/eglSubDriverAndroid.so +vendor/lib64/egl/libEGL_adreno.so +vendor/lib64/egl/libGLESv1_CM_adreno.so +vendor/lib64/egl/libGLESv2_adreno.so +vendor/lib64/egl/libQTapGLES.so +vendor/lib64/egl/libq3dtools_adreno.so +vendor/lib64/egl/libq3dtools_esx.so +vendor/lib64/libC2D2.so +vendor/lib64/libCB.so +vendor/lib64/libOpenCL.so +vendor/lib64/libRSDriver_adreno.so +vendor/lib64/libadreno_utils.so +vendor/lib64/libbccQTI.so +vendor/lib64/libc2d30-a5xx.so +vendor/lib64/libc2d30_bltlib.so +vendor/lib64/libgsl.so +vendor/lib64/libllvm-glnext.so +vendor/lib64/libllvm-qcom.so +vendor/lib64/libmm-disp-apis.so +vendor/lib64/libmm-qdcm.so +vendor/lib64/libmmQSM.so +vendor/lib64/librs_adreno.so +vendor/lib64/librs_adreno_sha1.so +vendor/lib64/libscalar.so +vendor/lib64/libsd_sdk_display.so +vendor/lib64/libsdm-color.so +vendor/lib64/libsdm-diag.so +-vendor/lib64/libsdm-disp-apis.so +vendor/lib64/libsdmextension.so + +# Graphics firmware +etc/firmware/a530_gpmu.fw2 +etc/firmware/a530_pfp.fw +etc/firmware/a530_pm4.fw +etc/firmware/a530_zap.b00 +etc/firmware/a530_zap.b01 +etc/firmware/a530_zap.b02 +etc/firmware/a530_zap.elf +etc/firmware/a530_zap.mdt +etc/firmware/a530v1_pfp.fw +etc/firmware/a530v1_pm4.fw +etc/firmware/a530v2_seq.fw2 +etc/firmware/a530v3_gpmu.fw2 +etc/firmware/a530v3_seq.fw2 + +# Keystore +vendor/lib/hw/keystore.msm8996.so +vendor/lib64/hw/keystore.msm8996.so + +# Listen +vendor/lib/hw/sound_trigger.primary.msm8996.so +vendor/lib/libadpcmdec.so +vendor/lib/libsmwrapper.so + +# Media +vendor/lib/libI420colorconvert.so +vendor/lib/libOmxAacDec.so +vendor/lib/libOmxEvrcDec.so +vendor/lib/libOmxQcelp13Dec.so +vendor/lib/libmm-color-convertor.so +vendor/lib/libmmosal.so + +# Network +-priv-app/QtiTetherService/QtiTetherService.apk +vendor/lib/libconnctrl.so +vendor/lib64/libconnctrl.so +vendor/lib64/libQtiTether.so + +# NFC firmware +vendor/firmware/libpn548ad_fw.so + +# Perf +bin/energy-awareness +bin/iop +bin/msm_irqbalance +lib64/libqti-iop.so +vendor/bin/perfd +vendor/etc/perf-profile0.conf +vendor/etc/perf-profile1.conf +vendor/etc/perf-profile2.conf +vendor/etc/perf-profile3.conf +vendor/etc/perf-profile4.conf +vendor/etc/perf-profile5.conf +vendor/etc/perf-profile6.conf +vendor/lib/libqc-opt.so +vendor/lib/libqti-iop-client.so +vendor/lib/libqti-perfd-client.so +vendor/lib64/libqc-opt.so +vendor/lib64/libqti-iop-client.so +vendor/lib64/libqti-perfd-client.so + +# Peripheral manager +bin/pm-proxy +bin/pm-service +vendor/lib/libperipheral_client.so +vendor/lib64/libperipheral_client.so + +# Postprocessing +etc/permissions/com.qti.snapdragon.sdk.display.xml +framework/com.qti.snapdragon.sdk.display.jar +-vendor/app/colorservice/colorservice.apk +vendor/bin/mm-pp-daemon +vendor/lib/libdisp-aba.so +vendor/lib/libmm-als.so +vendor/lib/libmm-disp-apis.so +vendor/lib/libmm-qdcm.so +vendor/lib64/libdisp-aba.so +vendor/lib64/libmm-als.so +vendor/lib64/libmm-disp-apis.so +vendor/lib64/libmm-dspp-utils.so +vendor/lib64/libmm-qdcm.so +vendor/lib64/libmm-qdcm-diag.so + +# QMI +bin/irsc_util +etc/permissions/qti_permissions.xml +vendor/bin/pd-mapper +vendor/lib/libdiag.so +vendor/lib/libdsi_netctrl.so +vendor/lib/libdsutils.so +vendor/lib/libidl.so +vendor/lib/libqcci_legacy.so +vendor/lib/libqcmaputils.so +vendor/lib/libqdi.so +vendor/lib/libqdp.so +vendor/lib/libqmi.so +vendor/lib/libqmi_cci.so +vendor/lib/libqmi_client_helper.so +vendor/lib/libqmi_client_qmux.so +vendor/lib/libqmi_common_so.so +vendor/lib/libqmi_csi.so +vendor/lib/libqmi_encdec.so +vendor/lib/libqmiservices.so +vendor/lib/libqti-wl.so +vendor/lib/libquipc_os_api.so +vendor/lib/libsmemlog.so +vendor/lib/libvqzip.so +vendor/lib64/libdiag.so +vendor/lib64/libdsi_netctrl.so +vendor/lib64/libdsutils.so +vendor/lib64/libidl.so +vendor/lib64/libqcci_legacy.so +vendor/lib64/libqcmaputils.so +vendor/lib64/libqdi.so +vendor/lib64/libqdp.so +vendor/lib64/libqmi.so +vendor/lib64/libqmi_cci.so +vendor/lib64/libqmi_client_helper.so +vendor/lib64/libqmi_client_qmux.so +vendor/lib64/libqmi_common_so.so +vendor/lib64/libqmi_csi.so +vendor/lib64/libqmi_encdec.so +vendor/lib64/libqmiservices.so +vendor/lib64/libqti-wl.so +vendor/lib64/libquipc_os_api.so +vendor/lib64/libsmemlog.so + +# Radio +-app/datastatusnotification/datastatusnotification.apk +-app/embms/embms.apk +-app/fastdormancy/fastdormancy.apk +-app/QtiTelephonyService/QtiTelephonyService.apk +-app/shutdownlistener/shutdownlistener.apk +bin/ipacm-diag +bin/netmgrd +bin/qmuxd +bin/radish +bin/rmt_storage +etc/data/dsi_config.xml +etc/data/netmgr_config.xml +etc/data/qmi_config.xml +etc/permissions/embms.xml +etc/permissions/qcnvitems.xml +etc/permissions/qcrilhook.xml +etc/permissions/telephonyservice.xml +framework/embmslibrary.jar +-framework/qcnvitems.jar +-framework/qcrilhook.jar +framework/qti-telephony-common.jar +framework/QtiTelephonyServicelibrary.jar +lib64/libparam.so +-priv-app/qcrilmsgtunnel/qcrilmsgtunnel.apk +vendor/bin/qti +vendor/lib64/libconfigdb.so +vendor/lib64/liblqe.so +vendor/lib64/libmdmdetect.so +vendor/lib64/libnetmgr.so +vendor/lib64/libqcmaputils.so +vendor/lib64/libril-qc-qmi-1.so +vendor/lib64/libril-qc-radioconfig.so +vendor/lib64/libril-qcril-hook-oem.so +vendor/lib64/libsystem_health_mon.so +vendor/qcril.db + +# Radio - IMS +bin/ims_rtp_daemon +bin/imscmservice +bin/imsdatadaemon +bin/imsqmidaemon +-vendor/app/ims/ims.apk +-vendor/app/imssettings/imssettings.apk +vendor/lib64/lib-dplmedia.so +vendor/lib64/lib-ims-rcscmjni.so +vendor/lib64/lib-imsSDP.so +vendor/lib64/lib-imscamera.so +vendor/lib64/lib-imsdpl.so +vendor/lib64/lib-imsqimf.so +vendor/lib64/lib-imsrcs.so +vendor/lib64/lib-imsrcscm.so +vendor/lib64/lib-imsrcscmclient.so +vendor/lib64/lib-imsrcscmservice.so +vendor/lib64/lib-imss.so +vendor/lib64/lib-imsvt.so +vendor/lib64/lib-imsxml.so +vendor/lib64/lib-rcsimssjni.so +vendor/lib64/lib-rcsjni.so +vendor/lib64/lib-rtpcommon.so +vendor/lib64/lib-rtpcore.so +vendor/lib64/lib-rtpdaemoninterface.so +vendor/lib64/lib-rtpsl.so +vendor/lib64/libimscamera_jni.so +vendor/lib64/libimsmedia_jni.so +vendor/lib64/librcc.so +vendor/lib64/libvoice-svc.so + +# Radio - MBN +etc/firmware/mbn_ota/mcfg_sw/mcfg_sw_ATT-VoLTE.mbn +etc/firmware/mbn_ota/mcfg_sw/mcfg_sw_CMCC_Volte_OpenMkt-Commercial.mbn +etc/firmware/mbn_ota/mcfg_sw/mcfg_sw_CT_OpenMkt-Commercial.mbn +etc/firmware/mbn_ota/mcfg_sw/mcfg_sw_CU_OpenMkt-Commercial.mbn +etc/firmware/mbn_ota/mcfg_sw/mcfg_sw_OEM_CDMA-Commercial.mbn +etc/firmware/mbn_ota/mcfg_sw/mcfg_sw_TMO-Commercial.mbn +etc/firmware/mbn_ota/mcfg_sw_NoCDMA/mcfg_sw_CMCC_Volte_OpenMkt-Commercial.mbn +etc/firmware/mbn_ota/mcfg_sw_NoCDMA/mcfg_sw_CU_OpenMkt-Commercial.mbn +etc/firmware/mbn_ota/mcfg_sw_NoCDMA/mcfg_sw_OEM_NoCDMA-Commercial.mbn +etc/firmware/mbn_ota/mcfg_sw_NoCDMA/mcfg_sw_Reliance-Commercial.mbn +etc/firmware/mbn_ota/mcfg_sw_NoCDMA/mcfg_sw_YTL-Commercial.mbn + +# Sensors +bin/sensors.qcom +etc/sensors/hals.conf +etc/sensors/sensor_def_qcomdev.conf +vendor/lib/hw/activity_recognition.msm8996.so +vendor/lib/libsensor1.so +vendor/lib/libsensor_reg.so +vendor/lib/libsensor_thresh.so +vendor/lib/libsensor_user_cal.so +vendor/lib/sensors.oem.so +vendor/lib/sensors.ssc.so +vendor/lib64/hw/activity_recognition.msm8996.so +vendor/lib64/libsensor1.so +vendor/lib64/libsensor_reg.so +vendor/lib64/libsensor_thresh.so +vendor/lib64/libsensor_user_cal.so +vendor/lib64/sensors.oem.so +vendor/lib64/sensors.ssc.so + +# Thermal +vendor/bin/thermal-engine +-vendor/lib/libthermalclient.so +-vendor/lib64/libthermalclient.so +vendor/lib64/libthermalioctl.so + +# Time services +-app/TimeService/TimeService.apk +bin/time_daemon +-vendor/lib/libtime_genoff.so +vendor/lib/libTimeService.so +-vendor/lib64/libtime_genoff.so +vendor/lib64/libTimeService.so + +# TP firmware +etc/firmware/tp/fw_synaptics_15801.img +etc/firmware/tp/fw_synaptics_15801b.img +etc/firmware/tp/fw_synaptics_touchkey.img + +# Widevine +vendor/lib/libWVStreamControlAPI_L3.so +vendor/lib/libwvdrm_L3.so +vendor/lib/mediadrm/libwvdrmengine.so + +# Wifi +bin/cnss-daemon +bin/cnss_diag diff --git a/rootdir/Android.mk b/rootdir/Android.mk new file mode 100644 index 000000000..cb613003c --- /dev/null +++ b/rootdir/Android.mk @@ -0,0 +1,77 @@ +LOCAL_PATH := $(call my-dir) + +# Device init scripts + + +include $(CLEAR_VARS) +LOCAL_MODULE := fstab.qcom +LOCAL_MODULE_TAGS := optional eng +LOCAL_MODULE_CLASS := ETC +LOCAL_SRC_FILES := etc/fstab.qcom +LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT) +include $(BUILD_PREBUILT) + +include $(CLEAR_VARS) +LOCAL_MODULE := init.qcom.power.rc +LOCAL_MODULE_TAGS := optional eng +LOCAL_MODULE_CLASS := ETC +LOCAL_SRC_FILES := etc/init.qcom.power.rc +LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT) +include $(BUILD_PREBUILT) + +include $(CLEAR_VARS) +LOCAL_MODULE := init.target.rc +LOCAL_MODULE_TAGS := optional eng +LOCAL_MODULE_CLASS := ETC +LOCAL_SRC_FILES := etc/init.target.rc +LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT) +include $(BUILD_PREBUILT) + +include $(CLEAR_VARS) +LOCAL_MODULE := init.qcom.rc +LOCAL_MODULE_TAGS := optional eng +LOCAL_MODULE_CLASS := ETC +LOCAL_SRC_FILES := etc/init.qcom.rc +LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT) +include $(BUILD_PREBUILT) + +include $(CLEAR_VARS) +LOCAL_MODULE := init.qcom.sh +LOCAL_MODULE_TAGS := optional eng +LOCAL_MODULE_CLASS := ETC +LOCAL_SRC_FILES := etc/init.qcom.sh +LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT) +include $(BUILD_PREBUILT) + +include $(CLEAR_VARS) +LOCAL_MODULE := init.qcom.usb.rc +LOCAL_MODULE_TAGS := optional eng +LOCAL_MODULE_CLASS := ETC +LOCAL_SRC_FILES := etc/init.qcom.usb.rc +LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT) +include $(BUILD_PREBUILT) + +include $(CLEAR_VARS) +LOCAL_MODULE := init.qcom.usb.sh +LOCAL_MODULE_TAGS := optional eng +LOCAL_MODULE_CLASS := ETC +LOCAL_SRC_FILES := etc/init.qcom.usb.sh +LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT) +include $(BUILD_PREBUILT) + +include $(CLEAR_VARS) +LOCAL_MODULE := ueventd.qcom.rc +LOCAL_MODULE_TAGS := optional eng +LOCAL_MODULE_CLASS := ETC +LOCAL_SRC_FILES := etc/ueventd.qcom.rc +LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT) +include $(BUILD_PREBUILT) + +# Configuration scripts + +include $(CLEAR_VARS) +LOCAL_MODULE := init.qcom.bt.sh +LOCAL_MODULE_TAGS := optional eng +LOCAL_MODULE_CLASS := ETC +LOCAL_SRC_FILES := etc/init.qcom.bt.sh +include $(BUILD_PREBUILT) diff --git a/rootdir/etc/fstab.qcom b/rootdir/etc/fstab.qcom new file mode 100644 index 000000000..55e26698a --- /dev/null +++ b/rootdir/etc/fstab.qcom @@ -0,0 +1,21 @@ +# Android fstab file. +# The filesystem that contains the filesystem checker binary (typically /system) cannot +# specify MF_CHECK, and must come before any filesystems that do specify MF_CHECK + +#TODO: Add 'check' as fs_mgr_flags with data partition. +# Currently we dont have e2fsck compiled. So fs check would failed. + +# +/dev/block/bootdevice/by-name/boot /boot emmc defaults defaults +/dev/block/bootdevice/by-name/recovery /recovery emmc defaults defaults +/dev/block/bootdevice/by-name/system /system ext4 ro,barrier=1,discard wait +/dev/block/bootdevice/by-name/userdata /data f2fs nosuid,nodev,noatime,nodiratime,inline_xattr,data_flush wait,check,encryptable=footer,formattable,length=-16384 +/dev/block/bootdevice/by-name/userdata /data ext4 nosuid,nodev,noatime,nodiratime,barrier=1,noauto_da_alloc wait,check,encryptable=footer,formattable,length=-16384 +/dev/block/bootdevice/by-name/cache /cache f2fs nosuid,nodev,noatime,nodiratime,inline_xattr,flush_merge,data_flush wait,check,formattable +/dev/block/bootdevice/by-name/cache /cache ext4 nosuid,nodev,noatime,nodiratime,barrier=1 wait,check,formattable +/dev/block/bootdevice/by-name/persist /persist ext4 nosuid,nodev,barrier=1 wait +/dev/block/bootdevice/by-name/dsp /dsp ext4 ro,nosuid,nodev,barrier=1 wait +/dev/block/bootdevice/by-name/modem /firmware vfat ro,shortname=lower,uid=1000,gid=1000,dmask=227,fmask=337,context=u:object_r:firmware_file:s0 wait +/dev/block/bootdevice/by-name/bluetooth /bt_firmware vfat ro,shortname=lower,uid=1002,gid=3002,dmask=222,fmask=333,context=u:object_r:bt_firmware_file:s0 wait + +/devices/soc/6a00000.ssusb/6a00000.dwc3/xhci-hcd.0.auto/usb* auto auto defaults voldmanaged=usbdisk:auto diff --git a/rootdir/etc/init.qcom.bt.sh b/rootdir/etc/init.qcom.bt.sh new file mode 100644 index 000000000..0cc5dc76c --- /dev/null +++ b/rootdir/etc/init.qcom.bt.sh @@ -0,0 +1,334 @@ +#!/system/bin/sh +# Copyright (c) 2009-2013, The Linux Foundation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of The Linux Foundation nor +# the names of its contributors may be used to endorse or promote +# products derived from this software without specific prior written +# permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +#Read the arguments passed to the script +config="$1" + +BLUETOOTH_SLEEP_PATH=/proc/bluetooth/sleep/proto +LOG_TAG="qcom-bluetooth" +LOG_NAME="${0}:" + +hciattach_pid="" + +loge () +{ + /system/bin/log -t $LOG_TAG -p e "$LOG_NAME $@" +} + +logi () +{ + /system/bin/log -t $LOG_TAG -p i "$LOG_NAME $@" +} + +failed () +{ + loge "$1: exit code $2" + exit $2 +} + +# +# enable bluetooth profiles dynamically +# +config_bt () +{ + baseband=`getprop ro.baseband` + target=`getprop ro.board.platform` + if [ -f /sys/devices/soc0/soc_id ]; then + soc_hwid=`cat /sys/devices/soc0/soc_id` + else + soc_hwid=`cat /sys/devices/system/soc/soc0/id` + fi + btsoc=`getprop qcom.bluetooth.soc` + + case $baseband in + "apq") + setprop ro.qualcomm.bluetooth.opp true + setprop ro.qualcomm.bluetooth.ftp true + setprop ro.qualcomm.bluetooth.nap false + setprop ro.bluetooth.sap false + setprop ro.bluetooth.dun false + # For MPQ as baseband is same for both + case $soc_hwid in + "130") + setprop ro.qualcomm.bluetooth.hsp true + setprop ro.qualcomm.bluetooth.hfp true + setprop ro.qualcomm.bluetooth.pbap false + setprop ro.qualcomm.bluetooth.map false + ;; + *) + setprop ro.qualcomm.bluetooth.hsp false + setprop ro.qualcomm.bluetooth.hfp false + setprop ro.qualcomm.bluetooth.pbap true + setprop ro.qualcomm.bluetooth.map true + ;; + esac + ;; + "mdm" | "svlte2a" | "svlte1" | "csfb") + setprop ro.qualcomm.bluetooth.opp true + setprop ro.qualcomm.bluetooth.hfp true + setprop ro.qualcomm.bluetooth.hsp true + setprop ro.qualcomm.bluetooth.pbap true + setprop ro.qualcomm.bluetooth.ftp true + setprop ro.qualcomm.bluetooth.map true + setprop ro.qualcomm.bluetooth.nap true + setprop ro.bluetooth.sap true + case $target in + "apq8084") + setprop ro.bluetooth.dun true + logi "Enabling BT-DUN for APQ8084" + ;; + *) + setprop ro.bluetooth.dun false + ;; + esac + ;; + "msm") + setprop ro.qualcomm.bluetooth.opp true + setprop ro.qualcomm.bluetooth.hfp true + setprop ro.qualcomm.bluetooth.hsp true + setprop ro.qualcomm.bluetooth.pbap true + setprop ro.qualcomm.bluetooth.ftp true + setprop ro.qualcomm.bluetooth.nap true + setprop ro.bluetooth.sap true + setprop ro.bluetooth.dun true + case $btsoc in + "ath3k") + setprop ro.qualcomm.bluetooth.map false + ;; + *) + setprop ro.qualcomm.bluetooth.map true + ;; + esac + ;; + *) + setprop ro.qualcomm.bluetooth.opp true + setprop ro.qualcomm.bluetooth.hfp true + setprop ro.qualcomm.bluetooth.hsp true + setprop ro.qualcomm.bluetooth.pbap true + setprop ro.qualcomm.bluetooth.ftp true + setprop ro.qualcomm.bluetooth.map true + setprop ro.qualcomm.bluetooth.nap true + setprop ro.bluetooth.sap true + setprop ro.bluetooth.dun true + ;; + esac + + #Enable Bluetooth Profiles specific to target Dynamically + case $target in + "msm8960") + if [ "$btsoc" != "ath3k" ] && [ "$soc_hwid" != "130" ] + then + setprop ro.bluetooth.hfp.ver 1.6 + setprop ro.qualcomm.bt.hci_transport smd + fi + ;; + "msm8974" | "msm8226" | "msm8610" | "msm8916" | "msm8909" | "msm8952" | "msm8937" ) + if [ "$btsoc" != "ath3k" ] + then + setprop ro.bluetooth.hfp.ver 1.7 + setprop ro.qualcomm.bt.hci_transport smd + fi + ;; + "apq8084" | "mpq8092" | "msm8994" | "msm8992" | "msm8996" ) + if [ "$btsoc" != "rome" ] + then + setprop ro.qualcomm.bt.hci_transport smd + elif [ "$btsoc" = "rome" ] + then + setprop ro.bluetooth.hfp.ver 1.6 + fi + ;; + *) + ;; + esac + +if [ -f /system/etc/bluetooth/stack.conf ]; then +stack=`cat /system/etc/bluetooth/stack.conf` +fi + +case "$stack" in + "bluez") + logi "Bluetooth stack is $stack" + setprop ro.qc.bluetooth.stack $stack + reason=`getprop vold.decrypt` + case "$reason" in + "trigger_restart_framework") + start dbus + ;; + esac + ;; + *) + logi "Bluetooth stack is Bluedroid" + ;; +esac + +} + +start_hciattach () +{ + /system/bin/hciattach -n $BTS_DEVICE $BTS_TYPE $BTS_BAUD & + hciattach_pid=$! + logi "start_hciattach: pid = $hciattach_pid" + echo 1 > $BLUETOOTH_SLEEP_PATH +} + +kill_hciattach () +{ + echo 0 > $BLUETOOTH_SLEEP_PATH + logi "kill_hciattach: pid = $hciattach_pid" + ## careful not to kill zero or null! + kill -TERM $hciattach_pid + # this shell doesn't exit now -- wait returns for normal exit +} + +logi "init.qcom.bt.sh config = $config" +case "$config" in + "onboot") + config_bt + exit 0 + ;; + *) + ;; +esac + +# mimic hciattach options parsing -- maybe a waste of effort +USAGE="hciattach [-n] [-p] [-b] [-t timeout] [-s initial_speed] [speed] [flow|noflow] [bdaddr]" + +while getopts "blnpt:s:" f +do + case $f in + b | l | n | p) opt_flags="$opt_flags -$f" ;; + t) timeout=$OPTARG;; + s) initial_speed=$OPTARG;; + \?) echo $USAGE; exit 1;; + esac +done +shift $(($OPTIND-1)) + +# Note that "hci_qcomm_init -e" prints expressions to set the shell variables +# BTS_DEVICE, BTS_TYPE, BTS_BAUD, and BTS_ADDRESS. + +#Selectively Disable sleep +BOARD=`getprop ro.board.platform` +STACK=`getprop ro.qc.bluetooth.stack` + +# BR/EDR & LE power class configurations +POWER_CLASS=`getprop qcom.bt.dev_power_class` +LE_POWER_CLASS=`getprop qcom.bt.le_dev_pwr_class` + +#find the transport type +TRANSPORT=`getprop ro.qualcomm.bt.hci_transport` +logi "Transport : $TRANSPORT" +case $STACK in + "bluez") + logi "** Bluez stack **" + ;; + *) + logi "** Bluedroid stack **" + setprop bluetooth.status off + ;; +esac + + +case $POWER_CLASS in + 1) PWR_CLASS="-p 0" ; + logi "Power Class: 1";; + 2) PWR_CLASS="-p 1" ; + logi "Power Class: 2";; + 3) PWR_CLASS="-p 2" ; + logi "Power Class: CUSTOM";; + *) PWR_CLASS=""; + logi "Power Class: Ignored. Default(1) used (1-CLASS1/2-CLASS2/3-CUSTOM)"; + logi "Power Class: To override, Before turning BT ON; setprop qcom.bt.dev_power_class <1 or 2 or 3>";; +esac + +case $LE_POWER_CLASS in + 1) LE_PWR_CLASS="-P 0" ; + logi "LE Power Class: 1";; + 2) LE_PWR_CLASS="-P 1" ; + logi "LE Power Class: 2";; + 3) LE_PWR_CLASS="-P 2" ; + logi "LE Power Class: CUSTOM";; + *) LE_PWR_CLASS="-P 1"; + logi "LE Power Class: Ignored. Default(2) used (1-CLASS1/2-CLASS2/3-CUSTOM)"; + logi "LE Power Class: To override, Before turning BT ON; setprop qcom.bt.le_dev_pwr_class <1 or 2 or 3>";; +esac + +eval $(/system/bin/hci_qcomm_init -e $PWR_CLASS $LE_PWR_CLASS && echo "exit_code_hci_qcomm_init=0" || echo "exit_code_hci_qcomm_init=1") + +case $exit_code_hci_qcomm_init in + 0) logi "Bluetooth QSoC firmware download succeeded, $BTS_DEVICE $BTS_TYPE $BTS_BAUD $BTS_ADDRESS";; + *) failed "Bluetooth QSoC firmware download failed" $exit_code_hci_qcomm_init; + case $STACK in + "bluez") + logi "** Bluez stack **" + ;; + *) + logi "** Bluedroid stack **" + setprop bluetooth.status off + ;; + esac + + exit $exit_code_hci_qcomm_init;; +esac + +# init does SIGTERM on ctl.stop for service +trap "kill_hciattach" TERM INT + +case $TRANSPORT in + "smd") + case $STACK in + "bluez") + logi "** Bluez stack **" + echo 1 > /sys/module/hci_smd/parameters/hcismd_set + ;; + *) + logi "** Bluedroid stack **" + setprop bluetooth.status on + ;; + esac + ;; + *) + logi "start hciattach" + start_hciattach + case $STACK in + "bluez") + logi "Bluetooth is turning On with Bluez stack " + ;; + *) + logi "** Bluedroid stack **" + setprop bluetooth.status on + ;; + esac + + wait $hciattach_pid + logi "Bluetooth stopped" + ;; +esac + +exit 0 diff --git a/rootdir/etc/init.qcom.power.rc b/rootdir/etc/init.qcom.power.rc new file mode 100644 index 000000000..293e7dea8 --- /dev/null +++ b/rootdir/etc/init.qcom.power.rc @@ -0,0 +1,129 @@ +on boot + # Update foreground and background cpusets + write /dev/cpuset/foreground/cpus 0-3 + write /dev/cpuset/foreground/boost/cpus 2-3 + write /dev/cpuset/background/cpus 0-1 + write /dev/cpuset/system-background/cpus 0-3 + + # Enable sched boost + write /proc/sys/kernel/sched_boost 1 + +on enable-low-power + # Disable thermal bcl hotplug to switch governor + write /sys/module/msm_thermal/core_control/enabled 0 + write /sys/devices/soc/soc:qcom,bcl/mode "disable" + write /sys/devices/soc/soc:qcom,bcl/hotplug_mask 0 + write /sys/devices/soc/soc:qcom,bcl/hotplug_soc_mask 0 + write /sys/devices/soc/soc:qcom,bcl/mode "enable" + + # Enable Adaptive LMK + write /sys/module/lowmemorykiller/parameters/enable_adaptive_lmk 1 + write /sys/module/lowmemorykiller/parameters/vmpressure_file_min 81250 + + # Configure governor settings for little cluster + write /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor "interactive" + write /sys/devices/system/cpu/cpu0/cpufreq/interactive/use_sched_load 1 + write /sys/devices/system/cpu/cpu0/cpufreq/interactive/use_migration_notif 1 + write /sys/devices/system/cpu/cpu0/cpufreq/interactive/above_hispeed_delay 19000 + write /sys/devices/system/cpu/cpu0/cpufreq/interactive/go_hispeed_load 90 + write /sys/devices/system/cpu/cpu0/cpufreq/interactive/timer_rate 20000 + write /sys/devices/system/cpu/cpu0/cpufreq/interactive/hispeed_freq 960000 + write /sys/devices/system/cpu/cpu0/cpufreq/interactive/io_is_busy 1 + write /sys/devices/system/cpu/cpu0/cpufreq/interactive/target_loads 80 + write /sys/devices/system/cpu/cpu0/cpufreq/interactive/min_sample_time 19000 + write /sys/devices/system/cpu/cpu0/cpufreq/interactive/max_freq_hysteresis 79000 + write /sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq 307200 + write /sys/devices/system/cpu/cpu0/cpufreq/interactive/ignore_hispeed_on_notif 1 + write /sys/devices/system/cpu/cpu0/cpufreq/interactive/enable_prediction 1 + + # Online CPU2 + write /sys/devices/system/cpu/cpu2/online 1 + + # Configure governor settings for big cluster + write /sys/devices/system/cpu/cpu2/cpufreq/scaling_governor "interactive" + write /sys/devices/system/cpu/cpu2/cpufreq/interactive/use_sched_load 1 + write /sys/devices/system/cpu/cpu2/cpufreq/interactive/use_migration_notif 1 + write /sys/devices/system/cpu/cpu2/cpufreq/interactive/above_hispeed_delay "19000 1400000:39000 1700000:19000 2100000:79000" + write /sys/devices/system/cpu/cpu2/cpufreq/interactive/go_hispeed_load 90 + write /sys/devices/system/cpu/cpu2/cpufreq/interactive/timer_rate 20000 + write /sys/devices/system/cpu/cpu2/cpufreq/interactive/hispeed_freq 1248000 + write /sys/devices/system/cpu/cpu2/cpufreq/interactive/io_is_busy 1 + write /sys/devices/system/cpu/cpu2/cpufreq/interactive/target_loads "85 1500000:90 1800000:70 2100000:95" + write /sys/devices/system/cpu/cpu2/cpufreq/interactive/min_sample_time 19000 + write /sys/devices/system/cpu/cpu2/cpufreq/interactive/max_freq_hysteresis 79000 + write /sys/devices/system/cpu/cpu2/cpufreq/scaling_min_freq 307200 + write /sys/devices/system/cpu/cpu2/cpufreq/interactive/ignore_hispeed_on_notif 1 + write /sys/devices/system/cpu/cpu2/cpufreq/interactive/enable_prediction 1 + + # Re-enable thermal and BCL hotplug + write /sys/module/msm_thermal/core_control/enabled 1 + write /sys/devices/soc/soc:qcom,bcl/mode "disable" + write /sys/devices/soc/soc:qcom,bcl/hotplug_mask 12 + write /sys/devices/soc/soc:qcom,bcl/hotplug_soc_mask 8 + write /sys/devices/soc/soc:qcom,bcl/mode "enable" + + # Input boost configuration + write /sys/module/cpu_boost/parameters/input_boost_freq "0:1324800 2:1324800" + write /sys/module/cpu_boost/parameters/input_boost_ms 40 + + # Setting b.L scheduler parameters + write /proc/sys/kernel/sched_boost 0 + write /proc/sys/kernel/sched_downmigrate 45 + write /proc/sys/kernel/sched_upmigrate 45 + write /proc/sys/kernel/sched_freq_inc_notify 400000 + write /proc/sys/kernel/sched_freq_dec_notify 400000 + write /proc/sys/kernel/sched_spill_nr_run 3 + write /proc/sys/kernel/sched_init_task_load 100 + write /proc/sys/kernel/sched_upmigrate_min_nice 9 + + # Enable bus-dcvs + write /sys/class/devfreq/soc:qcom,cpubw/governor "bw_hwmon" + write /sys/class/devfreq/soc:qcom,cpubw/polling_interval 50 + write /sys/class/devfreq/soc:qcom,cpubw/min_freq 1525 + write /sys/class/devfreq/soc:qcom,cpubw/bw_hwmon/mbps_zones "1525 5195 11863 13763" + write /sys/class/devfreq/soc:qcom,cpubw/bw_hwmon/sample_ms 4 + write /sys/class/devfreq/soc:qcom,cpubw/bw_hwmon/io_percent 34 + write /sys/class/devfreq/soc:qcom,cpubw/bw_hwmon/hist_memory 20 + write /sys/class/devfreq/soc:qcom,cpubw/bw_hwmon/hyst_length 10 + write /sys/class/devfreq/soc:qcom,cpubw/bw_hwmon/low_power_ceil_mbps 0 + write /sys/class/devfreq/soc:qcom,cpubw/bw_hwmon/low_power_io_percent 34 + write /sys/class/devfreq/soc:qcom,cpubw/bw_hwmon/low_power_delay 20 + write /sys/class/devfreq/soc:qcom,cpubw/bw_hwmon/guard_band_mbps 0 + write /sys/class/devfreq/soc:qcom,cpubw/bw_hwmon/up_scale 250 + write /sys/class/devfreq/soc:qcom,cpubw/bw_hwmon/idle_mbps 1600 + + write /sys/class/devfreq/soc:qcom,memlat-cpu0/governor "mem_latency" + write /sys/class/devfreq/soc:qcom,memlat-cpu0/polling_interval 10 + write /sys/class/devfreq/soc:qcom,memlat-cpu2/governor "mem_latency" + write /sys/class/devfreq/soc:qcom,memlat-cpu2/polling_interval 10 + write /sys/class/devfreq/soc:qcom,mincpubw/governor "cpufreq" + + write /sys/module/lpm_levels/parameters/sleep_disabled "N" + + # Set perfd properties + rm /data/system/perfd/default_values + start perfd + + # Starting io prefetcher service + start iop + +on charger + write /sys/devices/system/cpu/cpu1/online 0 + write /sys/devices/system/cpu/cpu2/online 0 + write /sys/devices/system/cpu/cpu3/online 0 + write /sys/module/msm_thermal/core_control/cpus_offlined 14 + write /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor "powersave" + write /sys/module/lpm_levels/parameters/sleep_disabled 0 + +on class_start:late_start + write /proc/sys/kernel/sched_boost 1 + + + trigger enable-low-power + +on property:init.svc.recovery=running + trigger enable-low-power + +on property:dev.bootcomplete=1 + write /proc/sys/kernel/sched_boost 0 + setprop sys.io.scheduler "bfq" diff --git a/rootdir/etc/init.qcom.rc b/rootdir/etc/init.qcom.rc new file mode 100755 index 000000000..f6e0c03f6 --- /dev/null +++ b/rootdir/etc/init.qcom.rc @@ -0,0 +1,1418 @@ +# Copyright (c) 2009-2012, 2014-2015, The Linux Foundation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of The Linux Foundation nor +# the names of its contributors may be used to endorse or promote +# products derived from this software without specific prior written +# permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +import init.qcom.power.rc +import init.qcom.usb.rc + +on early-init + mkdir /firmware 0771 system system + mkdir /bt_firmware 0771 system system + symlink /data/tombstones /tombstones + mkdir /dsp 0771 media media + chmod 0755 /sys/kernel/debug + +on init + + # Set permissions for persist partition + mkdir /persist 0771 system system + + # Support legacy paths + symlink /sdcard /mnt/sdcard + symlink /sdcard /storage/sdcard0 + +on early-boot + # set RLIMIT_MEMLOCK to 64MB + setrlimit 8 67108864 67108864 + + # set aggressive read ahead during boot up. + write /sys/block/dm-0/queue/read_ahead_kb 2048 + write /sys/block/sda/queue/read_ahead_kb 2048 + write /sys/block/sde/queue/read_ahead_kb 2048 + + # Allow subsystem (modem etc) debugging + write /sys/module/subsystem_restart/parameters/enable_debug ${persist.sys.ssr.enable_debug} + write /sys/module/pil_msa/parameters/pbl_mba_boot_timeout_ms ${persist.sys.mba_boot_timeout} + write /sys/module/pil_msa/parameters/modem_auth_timeout_ms ${persist.sys.modem_auth_timeout} + write /sys/module/peripheral_loader/parameters/proxy_timeout_ms ${persist.sys.pil_proxy_timeout} + write /sys/kernel/boot_adsp/boot 1 + write /sys/kernel/boot_slpi/boot 1 + +on fs + wait /dev/block/bootdevice + mount_all fstab.qcom + +on boot + # Update foreground and background cpusets + write /dev/cpuset/foreground/cpus 0-3 + write /dev/cpuset/foreground/boost/cpus 2-3 + write /dev/cpuset/background/cpus 0-1 + write /dev/cpuset/system-background/cpus 0-3 + + # Secure touch + chmod 0660 /sys/devices/soc/75ba000.i2c/i2c-12/12-004a/secure_touch_enable + chmod 0440 /sys/devices/soc/75ba000.i2c/i2c-12/12-004a/secure_touch + chown system drmrpc /sys/devices/soc/75ba000.i2c/i2c-12/12-004a/secure_touch_enable + chown system drmrpc /sys/devices/soc/75ba000.i2c/i2c-12/12-004a/secure_touch + write /sys/devices/soc/75ba000.i2c/i2c-12/12-0020/input/input0/update_fw 1 + + # Torch + chown system system /sys/class/leds/led:torch_0/brightness + chmod 666 /sys/class/leds/led:torch_0/brightness + chown system system /sys/class/leds/led:torch_1/brightness + chmod 666 /sys/class/leds/led:torch_1/brightness + chown system system /sys/class/leds/led:switch/brightness + chmod 666 /sys/class/leds/led:switch/brightness + + # Touchscreen + chown system radio /proc/touchpanel/double_tap_enable + chmod 0660 /proc/touchpanel/double_tap_enable + + chown root system /proc/touchpanel/camera_enable + chmod 0660 /proc/touchpanel/camera_enable + + chown root system /proc/touchpanel/music_enable + chmod 0660 /proc/touchpanel/music_enable + + chown root system /proc/touchpanel/flashlight_enable + chmod 0660 /proc/touchpanel/flashlight_enable + + # Buttons + chown root system /proc/s1302/key_rep + chmod 0660 /proc/s1302/key_rep + + chown root system /proc/s1302/virtual_key + chmod 0660 /proc/s1302/virtual_key + + chown root system /proc/tri-state-key/keyCode_top + chmod 0660 /proc/tri-state-key/keyCode_top + + chown root system /proc/tri-state-key/keyCode_middle + chmod 0660 /proc/tri-state-key/keyCode_middle + + chown root system /proc/tri-state-key/keyCode_bottom + chmod 0660 /proc/tri-state-key/keyCode_bottom + + # Graphics + chown system graphics /sys/class/graphics/fb0/dyn_pu + chmod 0664 /sys/class/graphics/fb0/dyn_pu + chown system graphics /sys/class/graphics/fb0/dynamic_fps + chmod 0664 /sys/class/graphics/fb0/dynamic_fps + chown system graphics /sys/class/graphics/fb0/idle_time + chmod 0664 /sys/class/graphics/fb0/idle_time + chown system graphics /sys/class/graphics/fb0/mode + chmod 0664 /sys/class/graphics/fb0/mode + chown system graphics /sys/class/graphics/fb0/modes + chmod 0664 /sys/class/graphics/fb0/modes + chown system graphics /sys/class/graphics/fb0/sre + chmod 0664 /sys/class/graphics/fb0/sre + + symlink /data/local /local + + # Fingerprint + chown system system /sys/devices/soc/soc:fpc1020/irq + chmod 0660 /sys/devices/soc/soc:fpc1020/irq + chown system system /sys/devices/soc/soc:fpc1020/wakeup + chmod 0660 /sys/devices/soc/soc:fpc1020/wakeup + chown system system /sys/devices/soc/soc:fpc1020/key + chmod 0660 /sys/devices/soc/soc:fpc1020/key + chown system system /sys/devices/soc/soc:fpc1020/wl + chmod 0660 /sys/devices/soc/soc:fpc1020/wl + chown system system /sys/devices/soc/soc:fpc1020/screen + chmod 0660 /sys/devices/soc/soc:fpc1020/screen + chmod 0666 /dev/qseecom + + #add for board test + chown root root /dev/i2c-5 + chmod 0660 /dev/i2c-5 + + #added touch gesture wake node permission + chown system system /sys/devices/virtual/touch/tp_dev/gesture_on + chmod 0660 /sys/devices/virtual/touch/tp_dev/gesture_on + + # USB + chown system system /sys/module/dwc3/parameters/usb30_disabled + chmod 0660 /sys/module/dwc3/parameters/usb30_disabled + + # RGB light + chown system system /sys/class/leds/led:rgb_red/brightness + chmod 0660 /sys/class/leds/led:rgb_red/brightness + chown system system /sys/class/leds/led:rgb_red/rgbblink + chmod 0660 /sys/class/leds/led:rgb_red/rgbblink + chown system system /sys/class/leds/led:rgb_red/rgbbreath + chmod 0660 /sys/class/leds/led:rgb_red/rgbbreath + + chown bluetooth bluetooth /sys/module/bluetooth_power/parameters/power + chown bluetooth net_bt /sys/class/rfkill/rfkill0/type + chown bluetooth net_bt /sys/class/rfkill/rfkill0/state + chown bluetooth bluetooth /proc/bluetooth/sleep/proto + chown bluetooth bluetooth /sys/module/hci_uart/parameters/ath_lpm + chown bluetooth bluetooth /sys/module/hci_uart/parameters/ath_btwrite + chown system system /sys/module/sco/parameters/disable_esco + chown bluetooth bluetooth /sys/module/hci_smd/parameters/hcismd_set + chown system system /sys/module/radio_iris_transport/parameters/fmsmd_set + chmod 0660 /sys/module/bluetooth_power/parameters/power + chmod 0660 /sys/module/hci_smd/parameters/hcismd_set + chmod 0660 /sys/module/radio_iris_transport/parameters/fmsmd_set + chmod 0660 /sys/class/rfkill/rfkill0/state + chmod 0660 /proc/bluetooth/sleep/proto + chown bluetooth net_bt /dev/ttyHS0 + chmod 0660 /sys/module/hci_uart/parameters/ath_lpm + chmod 0660 /sys/module/hci_uart/parameters/ath_btwrite + chmod 0660 /dev/ttyHS0 + chown bluetooth bluetooth /sys/devices/platform/msm_serial_hs.0/clock + chmod 0660 /sys/devices/platform/msm_serial_hs.0/clock + + chmod 0660 /dev/ttyHS2 + chown bluetooth bluetooth /dev/ttyHS2 + + chown bluetooth net_bt /sys/class/rfkill/rfkill0/device/extldo + chmod 0660 /sys/class/rfkill/rfkill0/device/extldo + + # Create QMUX deamon socket area + mkdir /dev/socket/qmux_radio 0770 radio radio + chmod 2770 /dev/socket/qmux_radio + mkdir /dev/socket/qmux_audio 0770 media audio + chmod 2770 /dev/socket/qmux_audio + mkdir /dev/socket/qmux_bluetooth 0770 bluetooth bluetooth + chmod 2770 /dev/socket/qmux_bluetooth + mkdir /dev/socket/qmux_gps 0770 gps gps + chmod 2770 /dev/socket/qmux_gps + + mkdir /persist/drm 0770 system system + + mkdir /persist/bluetooth 0770 bluetooth bluetooth + + # Create NETMGR daemon socket area + mkdir /dev/socket/netmgr 0750 radio radio + + setprop wifi.interface wlan0 + +# Define TCP buffer sizes for various networks +# ReadMin, ReadInitial, ReadMax, WriteMin, WriteInitial, WriteMax, + setprop net.tcp.buffersize.wifi 524288,2097152,4194304,262144,524288,1048576 + + + setprop ro.telephony.call_ring.multiple false + + #Remove SUID bit for iproute2 ip tool + chmod 0755 /system/bin/ip + + chmod 0444 /sys/devices/platform/msm_hsusb/gadget/usb_state + + # For bridgemgr daemon to inform the USB driver of the correct transport + chown radio radio /sys/class/android_usb/f_rmnet_smd_sdio/transport + +# Define TCP buffer sizes for various networks +# ReadMin, ReadInitial, ReadMax, WriteMin, WriteInitial, WriteMax, + setprop net.tcp.buffersize.default 4096,87380,524288,4096,16384,110208 + setprop net.tcp.buffersize.lte 2097152,4194304,8388608,262144,524288,1048576 + setprop net.tcp.buffersize.umts 4094,87380,110208,4096,16384,110208 + setprop net.tcp.buffersize.hspa 4094,87380,1220608,4096,16384,1220608 + setprop net.tcp.buffersize.hsupa 4094,87380,1220608,4096,16384,1220608 + setprop net.tcp.buffersize.hsdpa 4094,87380,1220608,4096,16384,1220608 + setprop net.tcp.buffersize.hspap 4094,87380,1220608,4096,16384,1220608 + setprop net.tcp.buffersize.edge 4093,26280,35040,4096,16384,35040 + setprop net.tcp.buffersize.gprs 4092,8760,11680,4096,8760,11680 + setprop net.tcp.buffersize.evdo 4094,87380,524288,4096,16384,262144 + + setprop net.tcp.2g_init_rwnd 10 + +# Assign TCP buffer thresholds to be ceiling value of technology maximums +# Increased technology maximums should be reflected here. + write /proc/sys/net/core/rmem_max 8388608 + write /proc/sys/net/core/wmem_max 8388608 + + # To allow interfaces to get v6 address when tethering is enabled + write /proc/sys/net/ipv6/conf/rmnet0/accept_ra 2 + write /proc/sys/net/ipv6/conf/rmnet1/accept_ra 2 + write /proc/sys/net/ipv6/conf/rmnet2/accept_ra 2 + write /proc/sys/net/ipv6/conf/rmnet3/accept_ra 2 + write /proc/sys/net/ipv6/conf/rmnet4/accept_ra 2 + write /proc/sys/net/ipv6/conf/rmnet5/accept_ra 2 + write /proc/sys/net/ipv6/conf/rmnet6/accept_ra 2 + write /proc/sys/net/ipv6/conf/rmnet7/accept_ra 2 + write /proc/sys/net/ipv6/conf/rmnet_sdio0/accept_ra 2 + write /proc/sys/net/ipv6/conf/rmnet_sdio1/accept_ra 2 + write /proc/sys/net/ipv6/conf/rmnet_sdio2/accept_ra 2 + write /proc/sys/net/ipv6/conf/rmnet_sdio3/accept_ra 2 + write /proc/sys/net/ipv6/conf/rmnet_sdio4/accept_ra 2 + write /proc/sys/net/ipv6/conf/rmnet_sdio5/accept_ra 2 + write /proc/sys/net/ipv6/conf/rmnet_sdio6/accept_ra 2 + write /proc/sys/net/ipv6/conf/rmnet_sdio7/accept_ra 2 + write /proc/sys/net/ipv6/conf/rmnet_usb0/accept_ra 2 + write /proc/sys/net/ipv6/conf/rmnet_usb1/accept_ra 2 + write /proc/sys/net/ipv6/conf/rmnet_usb2/accept_ra 2 + write /proc/sys/net/ipv6/conf/rmnet_usb3/accept_ra 2 + + # To prevent out of order acknowledgements from making + # connection tracking to treat them as not belonging to + # the connection they belong to. + # Otherwise, a weird issue happens in which some long + # connections on high-throughput links get dropped when + # an ack packet comes out of order + write /proc/sys/net/netfilter/nf_conntrack_tcp_be_liberal 1 + + # Set the console loglevel to < KERN_INFO + # Set the default message loglevel to KERN_INFO + write /proc/sys/kernel/printk "6 6 1 7" + + # Allow access for CCID command/response timeout configuration + chown system system /sys/module/ccid_bridge/parameters/bulk_msg_timeout + + # bond0 used by FST Manager + chown wifi wifi /sys/class/net/bond0/bonding/queue_id + +# msm specific files that need to be created on /data +on post-fs-data + mkdir /data/tombstones 0771 system system + mkdir /tombstones/modem 0771 system system + mkdir /tombstones/lpass 0771 system system + mkdir /tombstones/wcnss 0771 system system + mkdir /tombstones/dsps 0771 system system + mkdir /persist/data/sfs 0700 system system + mkdir /persist/data/tz 0700 system system + mkdir /persist/qc_senseid 0700 system system + mkdir /data/misc/dts 0770 media audio + mkdir /data/usf 0700 system system + mkdir /data/misc/tloc/ 0700 system drmrpc + mkdir /data/misc/qvop 0660 system system + mkdir /data/misc/audio_pp 0771 media audio + + # Sensors + mkdir /data/misc/sensors + chmod 0775 /data/misc/sensors + chmod 0755 /persist/sensors + chmod 0644 /persist/sensors/sensors_settings + chmod 0644 /persist/sensors/gyro_sensitity_cal + chown system root /persist/sensors/sensors_settings + chown system root /persist/sensors/gyro_sensitity_cal + + # Create directories for Fingerprint + mkdir /data/fpc_images 0770 system system + mkdir /data/fpc_images/verify 0770 system system + mkdir /data/fpc_images/enroll 0770 system system + mkdir /data/fpc 0770 system system + mkdir /data/misc/stargate 0770 system system + mkdir /data/misc/stargate/bg_estimation 0770 system system + mkdir /data/misc/stargate/calib_test 0770 system system + mkdir /data/misc/stargate/database 0770 system system + + # Create directory for TZ Apps + mkdir /data/misc/qsee 0770 system system + + # Create folder for mm-qcamera-daemon + mkdir /data/misc/camera 0770 camera camera + + mkdir /data/media 0770 media_rw media_rw + chown media_rw media_rw /data/media + + mkdir /data/misc/ipa 0700 net_admin net_admin + + mkdir /data/misc/bluetooth 0770 bluetooth bluetooth + + # Create the directories used by the Wireless subsystem + mkdir /data/misc/wifi 0770 wifi wifi + mkdir /data/misc/wifi/sockets 0770 wifi wifi + mkdir /data/misc/wifi/wpa_supplicant 0770 wifi wifi + mkdir /data/misc/dhcp 0770 dhcp dhcp + chown dhcp dhcp /data/misc/dhcp + + # Create port-bridge log dir + mkdir /data/misc/port_bridge 0770 radio radio + chmod 0770 /data/misc/port_bridge + + # Create the directories used by CnE subsystem + mkdir /data/connectivity 0771 system system + chown system system /data/connectivity + + # Create the directories used by DPM subsystem + mkdir /data/dpm 0771 system system + chown system system /data/dpm + + mkdir /data/dpm/nsrm 0771 system system + chown system system /data/dpm/nsrm + + # Create directory used by audio subsystem + mkdir /data/misc/audio 0770 audio audio + + # Create directory for audio delta files + mkdir /data/misc/audio/acdbdata 0770 media audio + mkdir /data/misc/audio/acdbdata/delta 0770 media audio + + # Create directory used by the DASH client + mkdir /data/misc/dash 0770 media audio + + # Create directory used by display clients + mkdir /data/misc/display 0770 system graphics + + # Mounting of persist is moved to 'on emmc-fs' and 'on fs' sections + # We chown/chmod /persist again so because mount is run as root + defaults + chown system system /persist + chmod 0771 /persist + chmod 0664 /sys/devices/platform/msm_sdcc.1/polling + chmod 0664 /sys/devices/platform/msm_sdcc.2/polling + chmod 0664 /sys/devices/platform/msm_sdcc.3/polling + chmod 0664 /sys/devices/platform/msm_sdcc.4/polling + + # Chown polling nodes as needed from UI running on system server + chown system system /sys/devices/platform/msm_sdcc.1/polling + chown system system /sys/devices/platform/msm_sdcc.2/polling + chown system system /sys/devices/platform/msm_sdcc.3/polling + chown system system /sys/devices/platform/msm_sdcc.4/polling + + # Create the symlink to qcn wpa_supplicant folder for ar6000 wpa_supplicant + mkdir /data/system 0775 system system + #symlink /data/misc/wifi/wpa_supplicant /data/system/wpa_supplicant + + # Create directories for Location services + mkdir /data/misc/location 0770 gps gps + mkdir /data/misc/location/mq 0770 gps gps + mkdir /data/misc/location/xtwifi 0770 gps gps + mkdir /data/misc/location/gpsone_d 0770 system gps + mkdir /data/misc/location/quipc 0770 gps system + mkdir /data/misc/location/gsiff 0770 gps gps + + # Create directory from IMS services + mkdir /data/shared 0755 + chown system system /data/shared + + # Create directory for FOTA + mkdir /data/fota 0771 + chown system system /data/fota + + # Create directory for hostapd + mkdir /data/hostapd 0770 system wifi + + # Create /data/time folder for time-services + mkdir /data/time/ 0700 system system + + mkdir /data/audio/ 0770 media audio + + # Create a folder for audio delta files + mkdir /data/audio/acdbdata 0770 media audio + mkdir /data/audio/acdbdata/delta 0770 media audio + + setprop vold.post_fs_data_done 1 + + # Create a folder for SRS to be able to create a usercfg file + mkdir /data/data/media 0770 media media + + # Create FM dir for patchdownloader + mkdir /data/misc/fm 0770 system system + chmod 0770 /data/misc/fm + + # RIDL data + mkdir /data/misc/SelfHost/ 0710 system shell + mkdir /data/misc/SelfHost/QCLogs/ 2750 system shell + mkdir /data/misc/SelfHost/QCLogs/temp/ 0700 system shell + mkdir /data/misc/SelfHost/storage/ 0700 system shell + mkdir /data/misc/SelfHost/Running/ 2750 system shell + mkdir /data/misc/SelfHost/socket/ 2770 system system + + # Create PERFD deamon related dirs + mkdir /data/misc/perfd 0755 root system + chmod 2755 /data/misc/perfd + mkdir /data/system/perfd 0770 root system + chmod 2770 /data/system/perfd + + # NFC local data and nfcee xml storage + mkdir /data/nfc 0770 nfc nfc + mkdir /data/nfc/param 0770 nfc nfc + + #Create IOP deamon related dirs + mkdir /data/misc/iop 0770 root system + + # Mark the copy complete flag to not completed + write /data/misc/radio/copy_complete 0 + chown radio radio /data/misc/radio/copy_complete + chmod 0660 /data/misc/radio/copy_complete + + # File flags for prebuilt ril db file + write /data/misc/radio/prebuilt_db_support 1 + chown radio radio /data/misc/radio/prebuilt_db_support + chmod 0400 /data/misc/radio/prebuilt_db_support + write /data/misc/radio/db_check_done 0 + chown radio radio /data/misc/radio/db_check_done + chmod 0660 /data/misc/radio/db_check_done + +# start camera server as daemon +service qcamerasvr /system/bin/mm-qcamera-daemon + class main + user camera + group camera system inet input graphics + writepid /dev/cpuset/system-background/tasks + +# fingerprint service +service fingerprintd /system/bin/fingerprintd + class late_start + user system + group system + +service qfp-daemon /system/bin/qfp-daemon + class late_start + user system + group system drmrpc diag input + +service qvop-daemon /system/bin/qvop-daemon + class late_start + user system + group system drmrpc + +# start up peripheral manager +service per_mgr system/bin/pm-service + class late_start + user system + group system net_raw + ioprio rt 4 + +service per_proxy /system/bin/pm-proxy + class late_start + user system + group system + disabled + +on property:init.svc.per_mgr=running + start per_proxy + +on property:sys.shutdown.requested=* + stop per_proxy + +service qseecomd /system/bin/qseecomd + class core + user root + group root + +service perfd /system/vendor/bin/perfd + class main + user root + socket perfd seqpacket 0666 root system + disabled + writepid /dev/cpuset/system-background/tasks + +service seempd /system/bin/seempd + class late_start + user system + group system + socket seempdw dgram 0666 system system + +service secotad /system/bin/secotad + class late_start + user system + group system + +service thermal-engine /system/vendor/bin/thermal-engine + class main + user root + socket thermal-send-client stream 0666 system system + socket thermal-recv-client stream 0660 system system + socket thermal-recv-passive-client stream 0666 system system + group root + socket thermal-send-client stream 0666 system system + socket thermal-recv-client stream 0660 system system + socket thermal-recv-passive-client stream 0666 system system + +service time_daemon /system/bin/time_daemon + class late_start + user root + group root + +service adsprpcd /system/bin/adsprpcd + class main + user media + group media + +service audiod /system/bin/audiod + class late_start + user system + group system + +service usf_tester /system/bin/usf_tester + user system + group system inet + disabled + oneshot + +service usf_epos /system/bin/usf_epos + class main + user system + group system inet + disabled + oneshot + +service usf_gesture /system/bin/usf_gesture + user system + group system inet + disabled + oneshot + +service usf_sync_gesture /system/bin/usf_sync_gesture + user system + group system inet audio + disabled + oneshot + +service usf_p2p /system/bin/usf_p2p + user system + group system inet + disabled + oneshot + +service usf_hovering /system/bin/usf_hovering + user system + group system inet + disabled + oneshot + +service usf_proximity /system/bin/usf_proximity + class late_start + user system + group system inet audio + +service usf_pairing /system/bin/usf_pairing + user system + group system inet + disabled + oneshot + +service usf_sw_calib /system/bin/usf_sw_calib + user system + group system inet + disabled + oneshot + +service usf-post-boot /system/bin/sh /system/etc/usf_post_boot.sh + class late_start + user root + disabled + oneshot + +on property:init.svc.bootanim=stopped + start usf-post-boot + +service imsqmidaemon /system/bin/imsqmidaemon + class main + user system + socket ims_qmid stream 0660 system radio + group radio net_raw log diag + +service imsdatadaemon /system/bin/imsdatadaemon + class main + user system + socket ims_datad stream 0660 system radio + group system wifi radio inet net_raw log diag net_admin + disabled + +service pd_mapper /system/vendor/bin/pd-mapper + class core + disabled + +on property:persist.sys.pd_enable=1 + start pd_mapper + write /sys/class/service_locator/service_locator_status 1 + +on property:persist.sys.pd_enable=0 + write /sys/class/service_locator/service_locator_status 0 + +on property:sys.ims.QMI_DAEMON_STATUS=1 + start imsdatadaemon + +service ims_rtp_daemon /system/bin/ims_rtp_daemon + class main + user system + socket ims_rtpd stream 0660 system radio + group radio net_raw diag inet log + disabled + +service imscmservice /system/bin/imscmservice + class main + user system + group radio net_raw diag diag log + disabled + +on property:sys.ims.DATA_DAEMON_STATUS=1 + start ims_rtp_daemon + start imscmservice + +service dts_configurator /system/bin/dts_configurator + class late_start + user system + group system media audio + oneshot + +service dtseagleservice /system/bin/dts_eagle_service + class late_start + user system + group audio media + disabled + +on property:init.svc.dts_configurator=stopped + start dtseagleservice + +service ppd /system/vendor/bin/mm-pp-dpps + class late_start + user system + group system graphics + socket pps stream 0660 system system + disabled + +on property:init.svc.surfaceflinger=stopped + stop ppd + +on property:init.svc.surfaceflinger=running + start ppd + +on property:init.svc.surfaceflinger=restarting + stop ppd + +on property:init.svc.zygote=stopped + stop ppd + +on property:init.svc.zygote=running + start ppd + +on property:init.svc.zygote=restarting + stop ppd + +service tlocd /system/bin/tloc_daemon + class late_start + user system + group drmrpc gps net_raw + +service energy-awareness /system/bin/energy-awareness + class main + user root + group system + oneshot + +service mdtpd /system/vendor/bin/mdtpd + class late_start + user root + group system radio drmrpc + +service iop /system/bin/iop + class main + user root + group root + disabled + socket iop seqpacket 0666 root system + writepid /dev/cpuset/system-background/tasks + +service qcomsysd /system/bin/qcom-system-daemon + class main + user root + group root qcom_diag + +service ssr_setup /system/bin/ssr_setup + oneshot + disabled + +service ss_ramdump /system/bin/subsystem_ramdump + class main + user system + group system + disabled + +on property:persist.sys.ssr.restart_level=* + start ssr_setup + +on property:persist.sys.ssr.enable_ramdumps=1 + write /sys/module/subsystem_restart/parameters/enable_ramdumps 1 + mkdir /data/ramdump 770 system system + start ss_ramdump + +on property:persist.sys.ssr.enable_ramdumps=0 + write /sys/module/subsystem_restart/parameters/enable_ramdumps 0 + +on property:sys.boot_completed=1 + write /dev/kmsg "Boot completed " + # Reset the read_ahead_kb to 512 + write /sys/block/dm-0/queue/read_ahead_kb 512 + write /sys/block/sda/queue/read_ahead_kb 512 + write /sys/block/sde/queue/read_ahead_kb 512 + + # CPE fw_name used by sound trigger HAL + chown media audio /sys/kernel/wcd_cpe0/fw_name + +on property:persist.radio.atfwd.start=false + stop atfwd + +on property:radio.atfwd.start=false + stop atfwd + +# corefile limit +on property:persist.debug.trace=1 + mkdir /data/core 0777 root root + write /proc/sys/kernel/core_pattern "/data/core/%E.%p.%e" + +on property:init.svc.wpa_supplicant=stopped + stop dhcpcd + +on property:bluetooth.isEnabled=true + start btwlancoex + write /sys/class/bluetooth/hci0/idle_timeout 7000 + +on property:bluetooth.sap.status=running + start bt-sap + +on property:bluetooth.sap.status=stopped + stop bt-sap + +on property:bluetooth.dun.status=running + start bt-dun + +on property:bluetooth.dun.status=stopped + stop bt-dun + +on property:ro.bluetooth.ftm_enabled=true + start ftmd + +on property:bluetooth.startbtsnoop=true + start btsnoop + +on property:bluetooth.startbtsnoop=false + stop btsnoop + +service qcom-c_core-sh /system/bin/sh /init.qcom.class_core.sh + class core + user root + oneshot + +service qcom-c_main-sh /system/bin/sh /init.class_main.sh + class main + user root + oneshot + +on property:vold.decrypt=trigger_restart_framework + start qcom-c_main-sh + start config_bt_addr + start config_bluetooth + +on property:persist.env.fastdorm.enabled=true + setprop persist.radio.data_no_toggle 1 + +service cnd /system/bin/cnd + class main + socket cnd stream 660 root inet + +service dpmd /system/bin/dpmd + class late_start + socket dpmd stream 660 root system + +service irsc_util /system/bin/irsc_util "/etc/sec_config" + class core + user root + oneshot + +service rmt_storage /system/bin/rmt_storage + class core + user root + +service rfs_access /system/bin/rfs_access + class core + user root + group system net_raw + +service tftp_server /system/bin/tftp_server + class main + user root + +on property:wc_transport.start_hci=true + start start_hci_filter + +on property:wc_transport.start_hci=false + stop start_hci_filter + +service start_hci_filter /system/bin/wcnss_filter + class late_start + user bluetooth + group bluetooth qcom_diag + disabled + +service config_bt_addr /system/bin/btnvtool -O + class core + user bluetooth + group bluetooth radio + oneshot + +on property:wc_transport.start_root=true + start hci_filter_root + +on property:wc_transport.start_root=false + stop hci_filter_root + +service hci_filter_root /system/bin/wcnss_filter + class late_start + user bluetooth + group bluetooth qcom_diag system + disabled + +service config_bluetooth /system/bin/sh /system/etc/init.qcom.bt.sh "onboot" + class core + user root + oneshot + +service hciattach /system/bin/sh /system/etc/init.qcom.bt.sh + class late_start + user bluetooth + group bluetooth net_bt_admin + disabled + oneshot + +on property:bluetooth.hciattach=true + start hciattach + +on property:bluetooth.hciattach=false + setprop bluetooth.status off + +service hciattach_ath3k /system/bin/sh /system/etc/init.ath3k.bt.sh + class late_start + user bluetooth + group system bluetooth net_bt_admin misc + disabled + oneshot + +service bt-dun /system/bin/dun-server /dev/smd7 /dev/rfcomm0 + class late_start + user bluetooth + group bluetooth net_bt_admin inet + disabled + oneshot + +service bt-sap /system/bin/sapd 15 + user bluetooth + group bluetooth net_bt_admin + class late_start + disabled + oneshot + +service btsnoop /system/bin/btsnoop + user bluetooth + group bluetooth net_bt_admin sdcard_rw sdcard_r media_rw + class late_start + disabled + oneshot + +service ftmd /system/bin/logwrapper /system/bin/ftmdaemon + class late_start + user root + group bluetooth net_bt_admin misc net_bt_stack qcom_diag net_bt + disabled + oneshot + +service bridgemgrd /system/bin/bridgemgrd + class late_start + user radio + group radio qcom_diag + disabled + +service port-bridge /system/bin/port-bridge + class main + user radio system + group radio system inet + oneshot + +service qmiproxy /system/bin/qmiproxy + class main + user radio + group radio qcom_diag + disabled + +# QMUX must be in multiple groups to support external process connections +service qmuxd /system/bin/qmuxd + class main + user root + group radio audio bluetooth gps nfc qcom_diag + +service netmgrd /system/bin/netmgrd + class main + +service ipacm-diag /system/bin/ipacm-diag + class main + user system + socket ipacm_log_file dgram 660 system net_admin + group net_admin qcom_diag + +service ipacm /system/bin/ipacm + class main + user net_admin + group net_admin inet + +service qti /system/vendor/bin/qti + class main + user radio + group radio net_raw qcom_diag usb net_admin + +service sensors /system/bin/sensors.qcom + class core + user root + group root + +on property:ro.use_data_netmgrd=false + # netmgr not supported on specific target + stop netmgrd + +# Adjust socket buffer to enlarge TCP receive window for high bandwidth +# but only if ro.data.large_tcp_window_size property is set. +on property:ro.data.large_tcp_window_size=true + write /proc/sys/net/ipv4/tcp_adv_win_scale 2 + +on property:sys.sysctl.tcp_adv_win_scale=* + write /proc/sys/net/ipv4/tcp_adv_win_scale ${sys.sysctl.tcp_adv_win_scale} + +service btwlancoex /system/bin/sh /system/etc/init.qcom.coex.sh + class late_start + user bluetooth + group bluetooth net_bt_admin inet net_admin net_raw + disabled + oneshot + +service amp_init /system/bin/amploader -i + class late_start + user root + disabled + oneshot + +service amp_load /system/bin/amploader -l 7000 + class late_start + user root + disabled + oneshot + +service amp_unload /system/bin/amploader -u + class late_start + user root + disabled + oneshot + +service p2p_supplicant /system/bin/wpa_supplicant \ + -ip2p0 -Dnl80211 -c/data/misc/wifi/p2p_supplicant.conf \ + -I/system/etc/wifi/p2p_supplicant_overlay.conf -N \ + -iwlan0 -Dnl80211 -c/data/misc/wifi/wpa_supplicant.conf \ + -I/system/etc/wifi/wpa_supplicant_overlay.conf \ + -O/data/misc/wifi/sockets -puse_p2p_group_interface=1 -dd \ + -e/data/misc/wifi/entropy.bin -g@android:wpa_wlan0 +# we will start as root and wpa_supplicant will switch to user wifi +# after setting up the capabilities required for WEXT +# user wifi +# group wifi inet keystore + class main + socket wpa_wlan0 dgram 660 wifi wifi + disabled + oneshot + +service wpa_supplicant /system/bin/wpa_supplicant \ + -iwlan0 -Dnl80211 -c/data/misc/wifi/wpa_supplicant.conf \ + -I/system/etc/wifi/wpa_supplicant_overlay.conf \ + -O/data/misc/wifi/sockets -dd \ + -e/data/misc/wifi/entropy.bin -g@android:wpa_wlan0 + # we will start as root and wpa_supplicant will switch to user wifi + # after setting up the capabilities required for WEXT + # user wifi + # group wifi inet keystore + class main + socket wpa_wlan0 dgram 660 wifi wifi + disabled + oneshot + +service wigig_supplicant /system/bin/wpa_supplicant \ + -iwigig0 -Dnl80211 -c/data/misc/wifi/wigig_supplicant.conf \ + -m/data/misc/wifi/wigig_p2p_supplicant.conf \ + -O/data/misc/wifi/wigig_sockets -dd \ + -e/data/misc/wifi/wigig_entropy.bin -g@android:wpa_wigig0 + # we will start as root and wpa_supplicant will switch to user wifi + # after setting up the capabilities required for WEXT + # user wifi + # group wifi inet keystore + class main + socket wpa_wigig0 dgram 660 wifi wifi + disabled + oneshot + +# FST Manager can be started by property_set("ctl.start", "fstman:"); +service fstman /system/bin/fstman -B -ddd -c /data/misc/wifi/fstman.ini + user wifi + group wifi net_admin net_raw + class main + disabled + oneshot + +on property:netd.fstman.start=true + start fstman + +on property:netd.fstman.start=false + stop fstman + +service dhcpcd_wlan0 /system/bin/dhcpcd -ABKLG + class late_start + disabled + oneshot + +service dhcpcd_bond0 /system/bin/dhcpcd -ABKLG + class late_start + disabled + oneshot + +service dhcpcd_p2p /system/bin/dhcpcd -ABKLG + class late_start + disabled + oneshot + +service iprenew_wlan0 /system/bin/dhcpcd -n + class late_start + disabled + oneshot + +service iprenew_bond0 /system/bin/dhcpcd -n + class late_start + disabled + oneshot + +service iprenew_p2p /system/bin/dhcpcd -n + class late_start + disabled + oneshot + +service ptt_socket_app /system/bin/ptt_socket_app -d + class main + user root + group root + oneshot + +service ptt_ffbm /system/bin/ptt_socket_app -f -d + user root + group root + disabled + oneshot + +service wifi_fccutild /system/bin/wifi_fccutild + user system + group system inet net_admin + socket wififccutild_server dgram 0660 system system + disabled + oneshot + +on property:wifi.fccutild.load.qcacld=true + insmod /system/lib/modules/qca_cld/qca_cld_wlan.ko con_mode=5 + +service cnss_diag /system/bin/cnss_diag -q -f + class main + user root + group root + #ifdef VENDOR_EDIT + # cnss diag cause power consumption bigger sometimes, so disable it until solve it + disabled + #endif + oneshot + +service cnss-daemon /system/bin/cnss-daemon -n -l + class late_start + +service dhcpcd_bt-pan /system/bin/dhcpcd -BKLG + class late_start + disabled + oneshot + +service iprenew_bt-pan /system/bin/dhcpcd -n + class late_start + disabled + oneshot + +service dhcpcd_bnep0 /system/bin/dhcpcd -BKLG + disabled + oneshot + +service dhcpcd_bnep1 /system/bin/dhcpcd -BKLG + disabled + oneshot + +service dhcpcd_bnep2 /system/bin/dhcpcd -BKLG + disabled + oneshot + +service dhcpcd_bnep3 /system/bin/dhcpcd -BKLG + disabled + oneshot + +service dhcpcd_bnep4 /system/bin/dhcpcd -BKLG + disabled + oneshot + +service loc_launcher /system/bin/loc_launcher + # loc_launcher will start as root and set its uid to gps + class late_start + group gps inet net_raw qcom_diag net_admin wifi + +service fm_dl /system/bin/sh /system/etc/init.qcom.fm.sh + class late_start + user system + group system + disabled + oneshot + +on property:crypto.driver.load=1 + insmod /system/lib/modules/qce.ko + insmod /system/lib/modules/qcedev.ko + +service drmdiag /system/bin/drmdiagapp + class late_start + user root + disabled + oneshot + +on property:drmdiag.load=1 + start drmdiag + +on property:drmdiag.load=0 + stop drmdiag + +service qcom-sh /system/bin/sh /init.qcom.sh + class late_start + user root + oneshot + +service sensor-sh /system/bin/sh /init.qcom.sensors.sh + class core + user root + oneshot + +service qcom-post-boot /system/bin/sh /system/etc/init.qcom.post_boot.sh + class late_start + user root + disabled + oneshot + +service qti-testscripts /system/bin/sh /system/etc/init.qcom.testscripts.sh + class late_start + user root + disabled + oneshot + seclabel u:r:qti-testscripts:s0 + +service wifi-sdio-on /system/bin/sh /system/etc/init.qcom.sdio.sh + class late_start + group wifi inet + disabled + oneshot + +service wifi-crda /system/bin/sh /system/etc/init.crda.sh + class late_start + user root + disabled + oneshot + +service config-zram /system/bin/sh /system/etc/init.qcom.zram.sh + class late_start + user root + disabled + oneshot + +on property:sys.boot_completed=1 + start qcom-post-boot + start qti-testscripts + start config-zram + +service atfwd /system/bin/ATFWD-daemon + class late_start + user system + group system radio + +service hostapd /system/bin/hostapd /data/hostapd/hostapd.conf + class late_start + user root + group root + oneshot + disabled + +service ds_fmc_appd /system/bin/ds_fmc_appd -p "rmnet0" -D + class late_start + group radio wifi inet + disabled + oneshot + +on property:persist.data.ds_fmc_app.mode=1 + start ds_fmc_appd + +service ims_regmanager /system/bin/exe-ims-regmanagerprocessnative + class late_start + group net_bt_admin inet radio wifi + disabled + +on property:persist.ims.regmanager.mode=1 + start ims_regmanager + +on property:ro.data.large_tcp_window_size=true + # Adjust socket buffer to enlarge TCP receive window for high bandwidth (e.g. DO-RevB) + write /proc/sys/net/ipv4/tcp_adv_win_scale 2 + +service battery_monitor /system/bin/battery_monitor + user system + group system + disabled + +service ril-daemon2 /system/bin/rild -c 2 + class late_start + socket rild2 stream 660 root radio + socket rild-debug2 stream 660 radio system + user root + group radio cache inet misc audio sdcard_r sdcard_rw qcom_diag diag log net_raw + +service usb_uicc_enable /system/bin/sh /system/etc/init.qcom.uicc.sh + class late_start + user root + disabled + oneshot + +service usb_uicc_daemon /system/bin/usb_uicc_client + class main + user system + group system log net_raw + oneshot + +on property:sys.usb_uicc.enabled=1 + start usb_uicc_enable + +on property:sys.usb_uicc.enabled=0 + start usb_uicc_enable + +service profiler_daemon /system/bin/profiler_daemon + class late_start + user root + group root + disabled + +service hcidump /system/bin/sh /system/etc/hcidump.sh + user bluetooth + group bluetooth system net_bt_admin net_admin + disabled + oneshot + +service charger /charger + class charger + seclabel u:r:healthd:s0 + +service ssr_diag /system/bin/ssr_diag + class late_start + user system + group system + disabled + +service hvdcp /system/bin/hvdcp + class core + user root + disabled + +on property:persist.usb.hvdcp.detect=true + start hvdcp + +on property:persist.usb.hvdcp.detect=false + stop hvdcp + +service charger_monitor /system/bin/charger_monitor + user root + group root + disabled + +service qbcharger /charger -m 1 + disabled + oneshot + +on property:sys.qbcharger.enable=true + start qbcharger + +on property:sys.qbcharger.enable=false + stop qbcharger + +service diag_mdlog_start /system/bin/diag_mdlog -c + class late_start + user shell + group system qcom_diag sdcard_rw sdcard_r media_rw + disabled + oneshot + +service diag_mdlog_stop /system/bin/diag_mdlog -k + class late_start + user shell + group system qcom_diag sdcard_rw sdcard_r media_rw + disabled + oneshot + +service vm_bms /system/bin/vm_bms + user root + group root + disabled + +service msm_irqbalance /system/bin/msm_irqbalance -f /system/vendor/etc/msm_irqbalance.conf + class main + user root + group root + disabled + writepid /dev/cpuset/system-background/tasks + +service wfdservice /system/bin/wfdservice + class main + user system + group audio camera inet net_bt_stack drmrpc media_rw media input net_admin + # removed these because of limit of 12 groups + #graphics net_bt net_bt_admin bluetooth + +# Coresight early boot service +service cs-early-boot /system/bin/sh /persist/coresight/qdss.agent.sh early-boot /system/etc/init.qcom.debug.sh + class core + user root + oneshot + +# Coresight post boot servive +service cs-post-boot /system/bin/sh /persist/coresight/qdss.agent.sh + user root + disabled + oneshot + +on property:sys.boot_completed=1 + start cs-post-boot + +on property:sys.dbg.coresight.enable=1 + write /persist/coresight/enable 1 + +on property:sys.dbg.coresight.enable=0 + write /persist/coresight/enable 0 + +service qseeproxydaemon /system/vendor/bin/qseeproxydaemon + class late_start + user system + group system + +# Seemp health service +service seemp_healthd /system/vendor/bin/seemp_healthd + class late_start + user system + group system + +#IFAA service +service ifaad /system/bin/ifaad + class late_start + user system + group system diff --git a/rootdir/etc/init.qcom.sh b/rootdir/etc/init.qcom.sh new file mode 100755 index 000000000..c3511f636 --- /dev/null +++ b/rootdir/etc/init.qcom.sh @@ -0,0 +1,83 @@ +#!/system/bin/sh +# Copyright (c) 2009-2015, The Linux Foundation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of The Linux Foundation nor +# the names of its contributors may be used to endorse or promote +# products derived from this software without specific prior written +# permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +start_msm_irqbalance() +{ + if [ -f /system/bin/msm_irqbalance ]; then + start msm_irqbalance + fi +} + +start_copying_prebuilt_qcril_db() +{ + if [ -f /system/vendor/qcril.db -a ! -f /data/misc/radio/qcril.db ]; then + cp /system/vendor/qcril.db /data/misc/radio/qcril.db + chown -h radio.radio /data/misc/radio/qcril.db + fi +} + +bootmode=`getprop ro.bootmode` +emmc_boot=`getprop ro.boot.emmc` +case "$emmc_boot" + in "true") + if [ "$bootmode" != "charger" ]; then # start rmt_storage and rfs_access + start rmt_storage + start rfs_access + fi + ;; +esac + +# +# Copy qcril.db if needed for RIL +# +start_copying_prebuilt_qcril_db +echo 1 > /data/misc/radio/db_check_done + +# +# Make modem config folder and copy firmware config to that folder for RIL +# +if [ -f /data/misc/radio/ver_info.txt ]; then + prev_version_info=`cat /data/misc/radio/ver_info.txt` +else + prev_version_info="" +fi + +cur_version_info=`cat /firmware/verinfo/ver_info.txt` +if [ ! -f /firmware/verinfo/ver_info.txt -o "$prev_version_info" != "$cur_version_info" ]; then + rm -rf /data/misc/radio/modem_config + mkdir /data/misc/radio/modem_config + chmod 770 /data/misc/radio/modem_config +#[Begin][public][PLAT-127][modem][mbn][wangxg7][20160121] Modify default mbn location + #cp -r /firmware/image/modem_pr/mcfg/configs/* /data/misc/radio/modem_config + cp -r /firmware/image/modem_pr/mcfg/fancy_co/* /data/misc/radio/modem_config +#[End][public][PLAT-127][modem][mbn][wangxg7][20160121] Modify default mbn location + chown -hR radio.radio /data/misc/radio/modem_config + cp /firmware/verinfo/ver_info.txt /data/misc/radio/ver_info.txt + chown radio.radio /data/misc/radio/ver_info.txt +fi +echo 1 > /data/misc/radio/copy_complete diff --git a/rootdir/etc/init.qcom.usb.rc b/rootdir/etc/init.qcom.usb.rc new file mode 100755 index 000000000..9fe0e25b9 --- /dev/null +++ b/rootdir/etc/init.qcom.usb.rc @@ -0,0 +1,1342 @@ +# Copyright (c) 2011-2012, The Linux Foundation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of The Linux Foundation nor +# the names of its contributors may be used to endorse or promote +# products derived from this software without specific prior written +# permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +on init + write /sys/class/android_usb/android0/f_rndis/wceis 1 + write /sys/class/android_usb/android0/iSerial ${ro.serialno} + +on fs + mkdir /dev/usb-ffs 0770 shell shell + mkdir /dev/usb-ffs/adb 0770 shell shell + mount functionfs adb /dev/usb-ffs/adb uid=2000,gid=2000 + write /sys/class/android_usb/android0/f_ffs/aliases adb + +service qcom-usb-sh /system/bin/sh /init.qcom.usb.sh + class core + user root + oneshot + +# Following are the parameters required for usb functionality. They provide configurable options like +# product_id/vendor id and allows specifying required functions: +# +# Required parameters: +# +# /sys/class/android_usb/android0/enable: Enables/disables usb composition +# Value: 0 (disable), 1 (enable) +# +# /sys/class/android_usb/android0/idVendor: Stores Vendor ID +# Value: 05c6 (Vendor id for Qualcomm Inc) +# +# /sys/class/android_usb/android0/idProduct: Stores Product id corresponding to usb composition +# Value: 0x9xxx for composite interface, 0xFxxx for single interface +# +# /sys/class/android_usb/android0/f_diag/clients: Stores name of clients representing a diag interface. +# Value: Passed one per interface. e.g. diag[,diag_mdm, diag_qsc, diag_mdm2] +# +# /sys/class/android_usb/android0/functions: Stores name of the function drivers used in usb composition. +# Value: Passed one per function driver. e.g. diag[,adb] +# +#Optional parameters: +# +# /sys/class/android_usb/android0/f_serial/transports: Stores type of underlying transports used to +# communicate to serial interface. +# Value: Passed one per interface. One value represents control and data transport together. +# e.g. smd[,sdio,tty,hsic] +# Only required if serial interface is present. +# +# /sys/class/android_usb/android0/f_serial/transport_names: Stores name of the underlying transports +# used to communicate to serial interface. This is used to distinguish between more than one interface +# using same transport type. +# Value: Passed one per interface. One value represents control and data transport together. +# e.g. serial_hsic[,serial_hsusb] +# Only required for transport type hsic, optional for other transport types. +# +# /sys/class/android_usb/android0/f_rmnet/transports: Stores type of underlying transports used to +# communicate to rmnet interface. +# Value: Passed two per interface as control, data transport type pair. +# e.g. smd,bam[,hsuart,hsuart] +# Only required if rmnet interface is present. +# +# /sys/class/android_usb/android0/f_rmnet/transport_names: Stores name of the underlying transports +# used to communicate to rmnet interface. This is used to distinguish between more than one interface +# using same transport type. +# Value: Passed one per interface. One value represents control and data transport together. +# e.g. rmnet_hsic[,rmnet_hsusb] +# Only required for transport type hsic, optional for other transport types. + +# USB compositions +on property:sys.usb.config=diag,serial_tty,serial_smd + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 9002 + write /sys/class/android_usb/android0/f_diag/clients diag + write /sys/class/android_usb/android0/f_serial/transports tty,smd + write /sys/class/android_usb/android0/functions diag,serial + write /sys/class/android_usb/android0/enable 1 + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=diag,serial_tty,serial_smd,adb + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 9020 + write /sys/class/android_usb/android0/f_diag/clients diag + write /sys/class/android_usb/android0/f_serial/transports smd,tty + write /sys/class/android_usb/android0/functions diag,adb,serial + write /sys/class/android_usb/android0/enable 1 + start adbd + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=diag,adb + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 676C + write /sys/class/android_usb/android0/f_diag/clients diag + write /sys/class/android_usb/android0/functions diag,adb + write /sys/class/android_usb/android0/enable 1 + start adbd + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=diag + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 900E + write /sys/class/android_usb/android0/f_diag/clients diag + write /sys/class/android_usb/android0/functions diag + write /sys/class/android_usb/android0/enable 1 + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=diag,serial_smd,rmnet_bam,adb + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 9091 + write /sys/class/android_usb/android0/f_diag/clients diag + write /sys/class/android_usb/android0/f_serial/transports smd + write /sys/class/android_usb/android0/f_rmnet/transports smd,bam + write /sys/class/android_usb/android0/functions diag,serial,rmnet,adb + write /sys/class/android_usb/android0/enable 1 + start adbd + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=diag,serial_smd,rmnet_qti_bam,adb + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 9091 + write /sys/class/android_usb/android0/f_diag/clients diag + write /sys/class/android_usb/android0/f_serial/transports smd + write /sys/class/android_usb/android0/f_rmnet/transports qti,bam + write /sys/class/android_usb/android0/functions diag,serial,rmnet,adb + write /sys/class/android_usb/android0/enable 1 + start adbd + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=diag,serial_smd,rmnet_bam + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 9092 + write /sys/class/android_usb/android0/f_diag/clients diag + write /sys/class/android_usb/android0/f_serial/transports smd + write /sys/class/android_usb/android0/f_rmnet/transports smd,bam + write /sys/class/android_usb/android0/functions diag,serial,rmnet + write /sys/class/android_usb/android0/enable 1 + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=diag,serial_smd,rmnet_qti_bam + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 9092 + write /sys/class/android_usb/android0/f_diag/clients diag + write /sys/class/android_usb/android0/f_serial/transports smd + write /sys/class/android_usb/android0/f_rmnet/transports qti,bam + write /sys/class/android_usb/android0/functions diag,serial,rmnet + write /sys/class/android_usb/android0/enable 1 + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=diag,serial_cdev,serial_tty,rmnet_ipa,mass_storage,adb + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 9025 + write /sys/class/android_usb/android0/f_diag/clients diag + write /sys/class/android_usb/android0/f_serial/transports char_bridge,tty + write /sys/class/android_usb/android0/f_rmnet/transports qti,bam2bam_ipa + write /sys/class/android_usb/android0/functions diag,adb,serial,rmnet,mass_storage + write /sys/class/android_usb/android0/enable 1 + start adbd + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=diag,serial_cdev,serial_tty,rmnet_ipa,mass_storage + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 9026 + write /sys/class/android_usb/android0/f_diag/clients diag + write /sys/class/android_usb/android0/f_serial/transports char_bridge,tty + write /sys/class/android_usb/android0/f_rmnet/transports qti,bam2bam_ipa + write /sys/class/android_usb/android0/functions diag,serial,rmnet,mass_storage + write /sys/class/android_usb/android0/enable 1 + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=diag,serial_smd,serial_tty,rmnet_bam,mass_storage,adb + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 9025 + write /sys/class/android_usb/android0/f_diag/clients diag + write /sys/class/android_usb/android0/f_serial/transports smd,tty + write /sys/class/android_usb/android0/f_rmnet/transports smd,bam + write /sys/class/android_usb/android0/functions diag,adb,serial,rmnet,mass_storage + write /sys/class/android_usb/android0/enable 1 + start adbd + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=diag,acm_smd,acm_tty,rmnet_bam,mass_storage,adb + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 903D + write /sys/class/android_usb/android0/f_diag/clients diag + write /sys/class/android_usb/android0/f_acm/acm_transports smd,tty + write /sys/class/android_usb/android0/f_rmnet/transports smd,bam + write /sys/class/android_usb/android0/functions diag,adb,acm,rmnet,mass_storage + write /sys/class/android_usb/android0/enable 1 + start adbd + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=diag,serial_smd,serial_tty,rmnet_bam,mass_storage + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 9026 + write /sys/class/android_usb/android0/f_diag/clients diag + write /sys/class/android_usb/android0/f_serial/transports smd,tty + write /sys/class/android_usb/android0/f_rmnet/transports smd,bam + write /sys/class/android_usb/android0/functions diag,serial,rmnet,mass_storage + write /sys/class/android_usb/android0/enable 1 + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=diag,acm_smd,acm_tty,rmnet_bam,mass_storage + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 903E + write /sys/class/android_usb/android0/f_diag/clients diag + write /sys/class/android_usb/android0/f_acm/acm_transports smd,tty + write /sys/class/android_usb/android0/f_rmnet/transports smd,bam + write /sys/class/android_usb/android0/functions diag,serial,rmnet,mass_storage + write /sys/class/android_usb/android0/enable 1 + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=diag,diag_mdm,serial_sdio,serial_smd,rmnet_smd_sdio,mass_storage,adb + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 9037 + write /sys/class/android_usb/android0/f_diag/clients diag,diag_mdm + write /sys/class/android_usb/android0/f_serial/transports sdio,smd + write /sys/class/android_usb/android0/functions diag,adb,serial,rmnet_smd_sdio,mass_storage + write /sys/class/android_usb/android0/enable 1 + start adbd + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=diag,diag_mdm,acm_sdio,acm_smd,rmnet_smd_sdio,mass_storage,adb + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 903B + write /sys/class/android_usb/android0/f_diag/clients diag,diag_mdm + write /sys/class/android_usb/android0/f_acm/acm_transports sdio,smd + write /sys/class/android_usb/android0/functions diag,adb,acm,rmnet_smd_sdio,mass_storage + write /sys/class/android_usb/android0/enable 1 + start adbd + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=diag,diag_mdm,serial_sdio,serial_smd,rmnet_smd_sdio,mass_storage + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 9038 + write /sys/class/android_usb/android0/f_diag/clients diag,diag_mdm + write /sys/class/android_usb/android0/f_serial/transports sdio,smd + write /sys/class/android_usb/android0/functions diag,serial,rmnet_smd_sdio,mass_storage + write /sys/class/android_usb/android0/enable 1 + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=diag,diag_mdm,acm_sdio,acm_smd,rmnet_smd_sdio,mass_storage + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 903C + write /sys/class/android_usb/android0/f_diag/clients diag,diag_mdm + write /sys/class/android_usb/android0/f_acm/acm_transports sdio,smd + write /sys/class/android_usb/android0/functions diag,acm,rmnet_smd_sdio,mass_storage + write /sys/class/android_usb/android0/enable 1 + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=diag,diag_mdm,serial_sdio,serial_tty,rmnet_sdio,mass_storage,adb + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 9031 + write /sys/class/android_usb/android0/f_diag/clients diag,diag_mdm + write /sys/class/android_usb/android0/f_serial/transports sdio,tty + write /sys/class/android_usb/android0/functions diag,adb,serial,rmnet_sdio,mass_storage + write /sys/class/android_usb/android0/enable 1 + start adbd + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=diag,diag_mdm,acm_sdio,acm_tty,rmnet_sdio,mass_storage,adb + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 903B + write /sys/class/android_usb/android0/f_diag/clients diag,diag_mdm + write /sys/class/android_usb/android0/f_acm/acm_transports sdio,tty + write /sys/class/android_usb/android0/functions diag,adb,acm,rmnet_sdio,mass_storage + write /sys/class/android_usb/android0/enable 1 + start adbd + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=diag,diag_mdm,serial_sdio,serial_tty,rmnet_sdio,mass_storage + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 9032 + write /sys/class/android_usb/android0/f_diag/clients diag,diag_mdm + write /sys/class/android_usb/android0/f_serial/transports sdio,tty + write /sys/class/android_usb/android0/functions diag,serial,rmnet_sdio,mass_storage + write /sys/class/android_usb/android0/enable 1 + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=diag,diag_mdm,acm_sdio,acm_tty,rmnet_sdio,mass_storage + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 903C + write /sys/class/android_usb/android0/f_diag/clients diag,diag_mdm + write /sys/class/android_usb/android0/f_acm/acm_transports sdio,tty + write /sys/class/android_usb/android0/functions diag,acm,rmnet_sdio,mass_storage + write /sys/class/android_usb/android0/enable 1 + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=diag,serial_tty,serial_tty,rmnet_smd,mass_storage,adb + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 9025 + write /sys/class/android_usb/android0/f_diag/clients diag + write /sys/class/android_usb/android0/f_serial/transports tty,tty + write /sys/class/android_usb/android0/functions diag,adb,serial,rmnet_smd,mass_storage + write /sys/class/android_usb/android0/enable 1 + start adbd + start port-bridge + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=diag,acm_tty,acm_tty,rmnet_smd,mass_storage,adb + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 903D + write /sys/class/android_usb/android0/f_diag/clients diag + write /sys/class/android_usb/android0/f_acm/acm_transports tty,tty + write /sys/class/android_usb/android0/functions diag,adb,acm,rmnet_smd,mass_storage + write /sys/class/android_usb/android0/enable 1 + start adbd + start port-bridge + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=diag,serial_tty,serial_tty,rmnet_smd,mass_storage + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 9026 + write /sys/class/android_usb/android0/f_diag/clients diag + write /sys/class/android_usb/android0/f_serial/transports tty,tty + write /sys/class/android_usb/android0/functions diag,serial,rmnet_smd,mass_storage + write /sys/class/android_usb/android0/enable 1 + start port-bridge + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=diag,acm_tty,acm_tty,rmnet_smd,mass_storage + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 903E + write /sys/class/android_usb/android0/f_diag/clients diag + write /sys/class/android_usb/android0/f_acm/acm_transports tty,tty + write /sys/class/android_usb/android0/functions diag,serial,rmnet_smd,mass_storage + write /sys/class/android_usb/android0/enable 1 + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=diag,serial_smd,serial_tty,rmnet_smd,mass_storage,adb + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 9025 + write /sys/class/android_usb/android0/f_diag/clients diag + write /sys/class/android_usb/android0/f_serial/transports smd,tty + write /sys/class/android_usb/android0/functions diag,adb,serial,rmnet_smd,mass_storage + write /sys/class/android_usb/android0/enable 1 + start adbd + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=diag,acm_smd,acm_tty,rmnet_smd,mass_storage,adb + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 903D + write /sys/class/android_usb/android0/f_diag/clients diag + write /sys/class/android_usb/android0/f_acm/acm_transports smd,tty + write /sys/class/android_usb/android0/functions diag,adb,acm,rmnet_smd,mass_storage + write /sys/class/android_usb/android0/enable 1 + start adbd + start port-bridge + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=diag,serial_smd,serial_tty,rmnet_smd,mass_storage + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 9026 + write /sys/class/android_usb/android0/f_diag/clients diag + write /sys/class/android_usb/android0/f_serial/transports smd,tty + write /sys/class/android_usb/android0/functions diag,serial,rmnet_smd,mass_storage + write /sys/class/android_usb/android0/enable 1 + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=diag,acm_smd,acm_tty,rmnet_smd,mass_storage + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 903E + write /sys/class/android_usb/android0/f_diag/clients diag + write /sys/class/android_usb/android0/f_acm/acm_transports smd,tty + write /sys/class/android_usb/android0/functions diag,serial,rmnet_smd,mass_storage + write /sys/class/android_usb/android0/enable 1 + setprop sys.usb.state ${sys.usb.config} + +# RmNet using USB BAM to IPA BAM +on property:sys.usb.config=diag,serial_smd,serial_tty,rmnet_ipa,mass_storage,adb + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 9025 + write /sys/class/android_usb/android0/f_diag/clients diag + write /sys/class/android_usb/android0/f_serial/transports smd,tty + write /sys/class/android_usb/android0/f_rmnet/transports qti,bam2bam_ipa + write /sys/class/android_usb/android0/functions diag,adb,serial,rmnet,mass_storage + write /sys/class/android_usb/android0/enable 1 + start adbd + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=diag,serial_smd,serial_tty,rmnet_ipa,mass_storage + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 9026 + write /sys/class/android_usb/android0/f_diag/clients diag + write /sys/class/android_usb/android0/f_serial/transports smd,tty + write /sys/class/android_usb/android0/f_rmnet/transports qti,bam2bam_ipa + write /sys/class/android_usb/android0/functions diag,serial,rmnet,mass_storage + write /sys/class/android_usb/android0/enable 1 + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=diag,serial_smd,rmnet_ipa,adb + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 9091 + write /sys/class/android_usb/android0/f_diag/clients diag + write /sys/class/android_usb/android0/f_serial/transports smd + write /sys/class/android_usb/android0/f_rmnet/transports qti,bam2bam_ipa + write /sys/class/android_usb/android0/functions diag,serial,rmnet,adb + write /sys/class/android_usb/android0/enable 1 + start adbd + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=diag,serial_smd,rmnet_ipa + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 9092 + write /sys/class/android_usb/android0/f_diag/clients diag + write /sys/class/android_usb/android0/f_serial/transports smd + write /sys/class/android_usb/android0/f_rmnet/transports qti,bam2bam_ipa + write /sys/class/android_usb/android0/functions diag,serial,rmnet + write /sys/class/android_usb/android0/enable 1 + setprop sys.usb.state ${sys.usb.config} + +# Fusion 3 composition +on property:sys.usb.config=diag,serial_hsic,serial_tty,rmnet_hsic,mass_storage,adb + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 9025 + write /sys/class/android_usb/android0/f_diag/clients diag + write /sys/class/android_usb/android0/f_serial/transports hsic,tty + write /sys/class/android_usb/android0/f_serial/transport_names serial_hsic + write /sys/class/android_usb/android0/f_rmnet/transports hsic,hsic + write /sys/class/android_usb/android0/f_rmnet/transport_names rmnet_hsic + write /sys/class/android_usb/android0/functions diag,adb,serial,rmnet,mass_storage + write /sys/module/mdm_bridge/parameters/rx_rmnet_buffer_size 16384 + write /sys/module/mdm_bridge/parameters/max_rx_urbs 20 + write /sys/module/g_android/parameters/ghsic_data_rx_req_size 16384 + write /sys/module/g_android/parameters/ghsic_data_rmnet_rx_q_size 20 + write /sys/class/android_usb/android0/enable 1 + start adbd + setprop sys.usb.state ${sys.usb.config} + +# Fusion 3 composition with diag_mdm and adb +on property:sys.usb.config=diag,diag_mdm,serial_hsic,serial_tty,rmnet_hsic,mass_storage,adb + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 9031 + write /sys/class/android_usb/android0/f_diag/clients diag,diag_mdm + write /sys/class/android_usb/android0/f_serial/transports hsic,tty + write /sys/class/android_usb/android0/f_serial/transport_names serial_hsic + write /sys/class/android_usb/android0/f_rmnet/transports hsic,hsic + write /sys/class/android_usb/android0/f_rmnet/transport_names rmnet_hsic + write /sys/class/android_usb/android0/functions diag,adb,serial,rmnet,mass_storage + write /sys/module/mdm_bridge/parameters/rx_rmnet_buffer_size 16384 + write /sys/module/mdm_bridge/parameters/max_rx_urbs 20 + write /sys/module/g_android/parameters/ghsic_data_rx_req_size 16384 + write /sys/module/g_android/parameters/ghsic_data_rmnet_rx_q_size 20 + write /sys/class/android_usb/android0/enable 1 + start adbd + setprop sys.usb.state ${sys.usb.config} + +# Fusion 3 composition with diag_mdm +on property:sys.usb.config=diag,diag_mdm,serial_hsic,serial_tty,rmnet_hsic,mass_storage + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 9032 + write /sys/class/android_usb/android0/f_diag/clients diag,diag_mdm + write /sys/class/android_usb/android0/f_serial/transports hsic,tty + write /sys/class/android_usb/android0/f_serial/transport_names serial_hsic + write /sys/class/android_usb/android0/f_rmnet/transports hsic,hsic + write /sys/class/android_usb/android0/f_rmnet/transport_names rmnet_hsic + write /sys/class/android_usb/android0/functions diag,serial,rmnet,mass_storage + write /sys/module/mdm_bridge/parameters/rx_rmnet_buffer_size 16384 + write /sys/module/mdm_bridge/parameters/max_rx_urbs 20 + write /sys/module/g_android/parameters/ghsic_data_rx_req_size 16384 + write /sys/module/g_android/parameters/ghsic_data_rmnet_rx_q_size 20 + write /sys/class/android_usb/android0/enable 1 + setprop sys.usb.state ${sys.usb.config} + +# Fusion 3 DSDA composition with adb +on property:sys.usb.config=diag,diag_mdm,diag_qsc,serial_hsic,serial_hsuart,rmnet_hsic,rmnet_hsuart,mass_storage,adb + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 9065 + write /sys/class/android_usb/android0/f_diag/clients diag,diag_mdm,diag_qsc + write /sys/class/android_usb/android0/f_serial/transports hsic,hsuart + write /sys/class/android_usb/android0/f_serial/transport_names serial_hsic,serial_hsuart + write /sys/class/android_usb/android0/f_rmnet/transports hsic,hsic,hsuart,hsuart + write /sys/class/android_usb/android0/f_rmnet/transport_names rmnet_hsic,rmnet_hsuart + write /sys/class/android_usb/android0/functions diag,adb,serial,rmnet,mass_storage + write /sys/module/mdm_bridge/parameters/rx_rmnet_buffer_size 16384 + write /sys/module/mdm_bridge/parameters/max_rx_urbs 20 + write /sys/module/g_android/parameters/ghsic_data_rx_req_size 16384 + write /sys/module/g_android/parameters/ghsic_data_rmnet_rx_q_size 20 + write /sys/class/android_usb/android0/enable 1 + start adbd + setprop sys.usb.state ${sys.usb.config} + +# Fusion 3 DSDA composition without adb +on property:sys.usb.config=diag,diag_mdm,diag_qsc,serial_hsic,serial_hsuart,rmnet_hsic,rmnet_hsuart,mass_storage + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 9066 + write /sys/class/android_usb/android0/f_diag/clients diag,diag_mdm,diag_qsc + write /sys/class/android_usb/android0/f_serial/transports hsic,hsuart + write /sys/class/android_usb/android0/f_serial/transport_names serial_hsic,serial_hsuart + write /sys/class/android_usb/android0/f_rmnet/transports hsic,hsic,hsuart,hsuart + write /sys/class/android_usb/android0/f_rmnet/transport_names rmnet_hsic,rmnet_hsuart + write /sys/class/android_usb/android0/functions diag,serial,rmnet,mass_storage + write /sys/module/mdm_bridge/parameters/rx_rmnet_buffer_size 16384 + write /sys/module/mdm_bridge/parameters/max_rx_urbs 20 + write /sys/module/g_android/parameters/ghsic_data_rx_req_size 16384 + write /sys/module/g_android/parameters/ghsic_data_rmnet_rx_q_size 20 + write /sys/class/android_usb/android0/enable 1 + setprop sys.usb.state ${sys.usb.config} + +# Fusion 3 DSDA2 composition with adb +on property:sys.usb.config=diag,diag_mdm,diag_mdm2,serial_hsic,serial_hsusb,rmnet_hsic,rmnet_hsusb,mass_storage,adb + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 9065 + write /sys/class/android_usb/android0/f_diag/clients diag,diag_mdm,diag_mdm2 + write /sys/class/android_usb/android0/f_serial/transports hsic,hsic + write /sys/class/android_usb/android0/f_serial/transport_names serial_hsic,serial_hsusb + write /sys/class/android_usb/android0/f_rmnet/transports hsic,hsic,hsic,hsic + write /sys/class/android_usb/android0/f_rmnet/transport_names rmnet_hsic,rmnet_hsusb + write /sys/class/android_usb/android0/functions diag,adb,serial,rmnet,mass_storage + write /sys/module/mdm_bridge/parameters/rx_rmnet_buffer_size 16384 + write /sys/module/mdm_bridge/parameters/max_rx_urbs 20 + write /sys/module/g_android/parameters/ghsic_data_rx_req_size 16384 + write /sys/module/g_android/parameters/ghsic_data_rmnet_rx_q_size 20 + write /sys/class/android_usb/android0/enable 1 + start adbd + setprop sys.usb.state ${sys.usb.config} + +# Fusion 3 DSDA2 composition without adb +on property:sys.usb.config=diag,diag_mdm,diag_mdm2,serial_hsic,serial_hsusb,rmnet_hsic,rmnet_hsusb,mass_storage + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 9066 + write /sys/class/android_usb/android0/f_diag/clients diag,diag_mdm,diag_mdm2 + write /sys/class/android_usb/android0/f_serial/transports hsic,hsic + write /sys/class/android_usb/android0/f_serial/transport_names serial_hsic,serial_hsusb + write /sys/class/android_usb/android0/f_rmnet/transports hsic,hsic,hsic,hsic + write /sys/class/android_usb/android0/f_rmnet/transport_names rmnet_hsic,rmnet_hsusb + write /sys/class/android_usb/android0/functions diag,serial,rmnet,mass_storage + write /sys/module/mdm_bridge/parameters/rx_rmnet_buffer_size 16384 + write /sys/module/mdm_bridge/parameters/max_rx_urbs 20 + write /sys/module/g_android/parameters/ghsic_data_rx_req_size 16384 + write /sys/module/g_android/parameters/ghsic_data_rmnet_rx_q_size 20 + write /sys/class/android_usb/android0/enable 1 + setprop sys.usb.state ${sys.usb.config} + +# Fusion PCIe composition with diag_mdm and adb +# Serial & RmNet bridged in userspace with tty and qti/ether +on property:sys.usb.config=diag,diag_mdm,serial_tty,rmnet_qti_ether,mass_storage,adb + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 9035 + write /sys/class/android_usb/android0/f_diag/clients diag,diag_mdm + write /sys/class/android_usb/android0/f_serial/transports tty + write /sys/class/android_usb/android0/f_rmnet/transports qti,ether + write /sys/class/android_usb/android0/functions diag,adb,serial,rmnet,mass_storage + write /sys/class/android_usb/android0/enable 1 + start adbd + setprop sys.usb.state ${sys.usb.config} + +# Fusion PCIe composition with diag_mdm +# Serial & RmNet bridged in userspace with tty and qti/ether +on property:sys.usb.config=diag,diag_mdm,serial_hsic,rmnet_hsic,mass_storage + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 9036 + write /sys/class/android_usb/android0/f_diag/clients diag,diag_mdm + write /sys/class/android_usb/android0/f_serial/transports tty + write /sys/class/android_usb/android0/f_rmnet/transports qti,ether + write /sys/class/android_usb/android0/functions diag,serial,rmnet,mass_storage + write /sys/class/android_usb/android0/enable 1 + setprop sys.usb.state ${sys.usb.config} + +# Fusion HSIC/PCIe Hybrid composition with diag_mdm and adb +# RmNet is bridged over PCIe using qti,ether ctrl/data transports +on property:sys.usb.config=diag,diag_mdm,serial_hsic,rmnet_qti_ether,mass_storage,adb + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 9035 + write /sys/class/android_usb/android0/f_diag/clients diag,diag_mdm + write /sys/class/android_usb/android0/f_serial/transports hsic + write /sys/class/android_usb/android0/f_serial/transport_names serial_hsic + write /sys/class/android_usb/android0/f_rmnet/transports qti,ether + write /sys/class/android_usb/android0/functions diag,adb,serial,rmnet,mass_storage + write /sys/class/android_usb/android0/enable 1 + start adbd + setprop sys.usb.state ${sys.usb.config} + +# Fusion HSIC/PCIe Hybrid composition with diag_mdm +# RmNet is bridged over PCIe using qti,ether ctrl/data transports +on property:sys.usb.config=diag,diag_mdm,serial_hsic,rmnet_hsic,mass_storage + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 9036 + write /sys/class/android_usb/android0/f_diag/clients diag,diag_mdm + write /sys/class/android_usb/android0/f_serial/transports hsic + write /sys/class/android_usb/android0/f_serial/transport_names serial_hsic + write /sys/class/android_usb/android0/f_rmnet/transports qti,ether + write /sys/class/android_usb/android0/functions diag,serial,rmnet,mass_storage + write /sys/class/android_usb/android0/enable 1 + setprop sys.usb.state ${sys.usb.config} + +# Fusion PCIe composition with diag_mdm +# Serial & RmNet bridged in userspace with port bridge and qti/ether +on property:sys.usb.config=diag,diag_mdm,serial_cdev,rmnet_qti_ether,mass_storage + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 9036 + write /sys/class/android_usb/android0/f_diag/clients diag,diag_mdm + write /sys/class/android_usb/android0/f_serial/transports char_bridge + write /sys/class/android_usb/android0/f_rmnet/transports qti,ether + write /sys/class/android_usb/android0/functions diag,serial,rmnet,mass_storage + write /sys/class/android_usb/android0/enable 1 + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=diag,diag_mdm,serial_cdev,rmnet_qti_ether,mass_storage,adb + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 9035 + write /sys/class/android_usb/android0/f_diag/clients diag,diag_mdm + write /sys/class/android_usb/android0/f_serial/transports char_bridge + write /sys/class/android_usb/android0/f_rmnet/transports qti,ether + write /sys/class/android_usb/android0/functions diag,adb,serial,rmnet,mass_storage + write /sys/class/android_usb/android0/enable 1 + start adbd + setprop sys.usb.state ${sys.usb.config} + +# Fusion 2.2 composition with diag_qsc and adb +on property:sys.usb.config=diag,diag_qsc,serial_smd,serial_tty,serial_hsuart,rmnet_hsuart,mass_storage,adb + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 9053 + write /sys/class/android_usb/android0/f_diag/clients diag,diag_qsc + write /sys/class/android_usb/android0/f_serial/transports smd,tty,hsuart + write /sys/class/android_usb/android0/f_rmnet/transports smd,bam,hsuart,hsuart + write /sys/class/android_usb/android0/functions diag,adb,serial,rmnet,mass_storage + write /sys/class/android_usb/android0/enable 1 + start adbd + setprop sys.usb.state ${sys.usb.config} + +# Fusion 2.2 composition with diag_qsc +on property:sys.usb.config=diag,diag_qsc,serial_smd,serial_tty,serial_hsuart,rmnet_hsuart,mass_storage + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 9054 + write /sys/class/android_usb/android0/f_diag/clients diag,diag_qsc + write /sys/class/android_usb/android0/f_serial/transports smd,tty,hsuart + write /sys/class/android_usb/android0/f_rmnet/transports smd,bam,hsuart,hsuart + write /sys/class/android_usb/android0/functions diag,serial,rmnet,mass_storage + write /sys/class/android_usb/android0/enable 1 + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.tethering=true + write /sys/class/net/rndis0/queues/rx-0/rps_cpus ${sys.usb.rps_mask} + +on property:sys.usb.config=rndis + setprop sys.usb.config rndis,${persist.sys.usb.config.extra} + +on property:sys.usb.config=rndis,none + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 2A70#modify from 05C6 to 2A70 by jiachenghui for USB VID customized,2015-10-23 #VENDOR_EDIT + write /sys/class/android_usb/android0/idProduct F00E + write /sys/class/android_usb/android0/functions rndis + write /sys/class/android_usb/android0/enable 1 + setprop sys.usb.state rndis + +on property:sys.usb.config=rndis,adb + setprop sys.usb.config rndis,${persist.sys.usb.config.extra},adb + +on property:sys.usb.config=rndis,none,adb + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 9024 + write /sys/class/android_usb/android0/functions rndis,adb + write /sys/class/android_usb/android0/enable 1 + start adbd + setprop sys.usb.state rndis,adb + +on property:sys.usb.config=rndis,diag + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 902C + write /sys/class/android_usb/android0/f_diag/clients diag + write /sys/class/android_usb/android0/functions rndis,diag + write /sys/class/android_usb/android0/enable 1 + setprop sys.usb.state rndis + +on property:sys.usb.config=rndis,diag,adb + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 902D + write /sys/class/android_usb/android0/f_diag/clients diag + write /sys/class/android_usb/android0/functions rndis,diag,adb + write /sys/class/android_usb/android0/enable 1 + start adbd + setprop sys.usb.state rndis,adb + +on property:sys.usb.config=rndis,serial_smd + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 90B3 + write /sys/class/android_usb/android0/f_serial/transports smd + write /sys/class/android_usb/android0/functions rndis,serial + write /sys/class/android_usb/android0/enable 1 + setprop sys.usb.state rndis + +on property:sys.usb.config=rndis,serial_smd,adb + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 90B4 + write /sys/class/android_usb/android0/f_serial/transports smd + write /sys/class/android_usb/android0/functions rndis,serial,adb + write /sys/class/android_usb/android0/enable 1 + start adbd + setprop sys.usb.state rndis,adb + +on property:sys.usb.config=rndis,serial_smd,diag + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 90B5 + write /sys/class/android_usb/android0/f_diag/clients diag + write /sys/class/android_usb/android0/f_serial/transports smd + write /sys/class/android_usb/android0/functions rndis,serial,diag + write /sys/class/android_usb/android0/enable 1 + setprop sys.usb.state rndis + +on property:sys.usb.config=rndis,serial_smd,diag,adb + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 90B6 + write /sys/class/android_usb/android0/f_diag/clients diag + write /sys/class/android_usb/android0/f_serial/transports smd + write /sys/class/android_usb/android0/functions rndis,serial,diag,adb + write /sys/class/android_usb/android0/enable 1 + start adbd + setprop sys.usb.state rndis,adb + +on property:sys.usb.config=rndis,serial_cdev,diag + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 90B5 + write /sys/class/android_usb/android0/f_diag/clients diag + write /sys/class/android_usb/android0/f_serial/transports char_bridge + write /sys/class/android_usb/android0/functions rndis,serial,diag + write /sys/class/android_usb/android0/enable 1 + setprop sys.usb.state rndis + +on property:sys.usb.config=rndis,serial_cdev,diag,adb + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 90B6 + write /sys/class/android_usb/android0/f_diag/clients diag + write /sys/class/android_usb/android0/f_serial/transports char_bridge + write /sys/class/android_usb/android0/functions rndis,serial,diag,adb + write /sys/class/android_usb/android0/enable 1 + start adbd + setprop sys.usb.state rndis,adb + +on property:sys.usb.config=rndis,diag,diag_mdm + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 9041 + write /sys/class/android_usb/android0/f_diag/clients diag,diag_mdm + write /sys/class/android_usb/android0/functions rndis,diag + write /sys/class/android_usb/android0/enable 1 + setprop sys.usb.state rndis + +on property:sys.usb.config=rndis,diag,diag_mdm,adb + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 9042 + write /sys/class/android_usb/android0/f_diag/clients diag,diag_mdm + write /sys/class/android_usb/android0/functions rndis,diag,adb + write /sys/class/android_usb/android0/enable 1 + start adbd + setprop sys.usb.state rndis,adb + +on property:sys.usb.config=rndis,diag,diag_mdm,diag_qsc + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 9086 + write /sys/class/android_usb/android0/f_diag/clients diag,diag_mdm,diag_qsc + write /sys/class/android_usb/android0/functions rndis,diag + write /sys/class/android_usb/android0/enable 1 + setprop sys.usb.state rndis + +on property:sys.usb.config=rndis,diag,diag_mdm,diag_qsc,adb + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 9087 + write /sys/class/android_usb/android0/f_diag/clients diag,diag_mdm,diag_qsc + write /sys/class/android_usb/android0/functions rndis,diag,adb + write /sys/class/android_usb/android0/enable 1 + start adbd + setprop sys.usb.state rndis,adb + +on property:sys.usb.config=ptp + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 2A70#modify from 05C6 to 2A70 by jiachenghui for USB VID customized,2015-10-23 #VENDOR_EDIT + write /sys/class/android_usb/android0/idProduct 904D + write /sys/class/android_usb/android0/functions ptp + write /sys/class/android_usb/android0/enable 1 + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=ptp,adb + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 904E + write /sys/class/android_usb/android0/functions ptp,adb + write /sys/class/android_usb/android0/enable 1 + start adbd + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=mtp + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 2A70#modify from 05C6 to 2A70 by jiachenghui for USB VID customized,2015-10-23 #VENDOR_EDIT + write /sys/class/android_usb/android0/idProduct F003 + write /sys/class/android_usb/android0/functions mtp + write /sys/class/android_usb/android0/enable 1 + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=mtp,adb + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 9039 + write /sys/class/android_usb/android0/functions mtp,adb + write /sys/class/android_usb/android0/enable 1 + start adbd + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=mtp,diag + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 901B + write /sys/class/android_usb/android0/f_diag/clients diag + write /sys/class/android_usb/android0/functions mtp,diag + write /sys/class/android_usb/android0/enable 1 + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=mtp,diag,adb + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 903A + write /sys/class/android_usb/android0/f_diag/clients diag + write /sys/class/android_usb/android0/functions mtp,diag,adb + write /sys/class/android_usb/android0/enable 1 + start adbd + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=mtp,diag,diag_mdm + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 9040 + write /sys/class/android_usb/android0/f_diag/clients diag,diag_mdm + write /sys/class/android_usb/android0/functions mtp,diag + write /sys/class/android_usb/android0/enable 1 + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=mtp,diag,diag_mdm,adb + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 903F + write /sys/class/android_usb/android0/f_diag/clients diag,diag_mdm + write /sys/class/android_usb/android0/functions mtp,diag,adb + write /sys/class/android_usb/android0/enable 1 + start adbd + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=mtp,diag,diag_mdm,diag_qsc + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 9088 + write /sys/class/android_usb/android0/f_diag/clients diag,diag_mdm,diag_qsc + write /sys/class/android_usb/android0/functions mtp,diag + write /sys/class/android_usb/android0/enable 1 + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=mtp,diag,diag_mdm,diag_qsc,adb + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 9089 + write /sys/class/android_usb/android0/f_diag/clients diag,diag_mdm,diag_qsc + write /sys/class/android_usb/android0/functions mtp,diag,adb + write /sys/class/android_usb/android0/enable 1 + start adbd + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=diag,diag_mdm,ccid + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 9045 + write /sys/class/android_usb/android0/f_diag/clients diag,diag_mdm + write /sys/class/android_usb/android0/functions diag,ccid + write /sys/class/android_usb/android0/enable 1 + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=diag,diag_mdm,ccid,adb + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 9044 + write /sys/class/android_usb/android0/f_diag/clients diag,diag_mdm + write /sys/class/android_usb/android0/functions diag,adb,ccid + write /sys/class/android_usb/android0/enable 1 + start adbd + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=mass_storage,adb + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 9015 + write /sys/class/android_usb/android0/functions adb,mass_storage + write /sys/class/android_usb/android0/enable 1 + start adbd + setprop sys.usb.state ${sys.usb.config} + +#Mass-storage only composition +on property:sys.usb.config=mass_storage + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct F000 + write /sys/class/android_usb/android0/functions mass_storage + write /sys/class/android_usb/android0/enable 1 + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=diag,qdss + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 904A + write /sys/class/android_usb/android0/f_diag/clients diag + write /sys/class/android_usb/android0/f_qdss/debug_intf 1 + write /sys/class/android_usb/android0/f_qdss/transports bam + write /sys/class/android_usb/android0/f_qdss/transport_names qdss_bam + write /sys/class/android_usb/android0/functions diag,qdss + write /sys/class/android_usb/android0/enable 1 + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=diag,qdss,adb + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 9060 + write /sys/class/android_usb/android0/f_diag/clients diag + write /sys/class/android_usb/android0/f_qdss/debug_intf 1 + write /sys/class/android_usb/android0/f_qdss/transports bam + write /sys/class/android_usb/android0/f_qdss/transport_names qdss_bam + write /sys/class/android_usb/android0/functions diag,qdss,adb + write /sys/class/android_usb/android0/enable 1 + start adbd + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=diag,diag_mdm,qdss + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 9099 + write /sys/class/android_usb/android0/f_diag/clients diag,diag_mdm + write /sys/class/android_usb/android0/f_qdss/debug_intf 1 + write /sys/class/android_usb/android0/f_qdss/transports bam + write /sys/class/android_usb/android0/f_qdss/transport_names qdss_bam + write /sys/class/android_usb/android0/functions diag,qdss + write /sys/class/android_usb/android0/enable 1 + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=diag,diag_mdm,qdss,adb + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 9098 + write /sys/class/android_usb/android0/f_diag/clients diag,diag_mdm + write /sys/class/android_usb/android0/f_qdss/debug_intf 1 + write /sys/class/android_usb/android0/f_qdss/transports bam + write /sys/class/android_usb/android0/f_qdss/transport_names qdss_bam + write /sys/class/android_usb/android0/functions diag,qdss,adb + write /sys/class/android_usb/android0/enable 1 + start adbd + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=diag,qdss,rmnet_bam + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 9083 + write /sys/class/android_usb/android0/f_diag/clients diag + write /sys/class/android_usb/android0/f_rmnet/transports smd,bam + write /sys/class/android_usb/android0/f_qdss/debug_intf 1 + write /sys/class/android_usb/android0/f_qdss/transports bam + write /sys/class/android_usb/android0/f_qdss/transport_names qdss_bam + write /sys/class/android_usb/android0/functions diag,qdss,rmnet + write /sys/class/android_usb/android0/enable 1 + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=diag,qdss,rmnet_qti_bam + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 9083 + write /sys/class/android_usb/android0/f_diag/clients diag + write /sys/class/android_usb/android0/f_rmnet/transports qti,bam + write /sys/class/android_usb/android0/f_qdss/debug_intf 1 + write /sys/class/android_usb/android0/f_qdss/transports bam + write /sys/class/android_usb/android0/f_qdss/transport_names qdss_bam + write /sys/class/android_usb/android0/functions diag,qdss,rmnet + write /sys/class/android_usb/android0/enable 1 + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=diag,qdss,rmnet_bam,adb + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 9084 + write /sys/class/android_usb/android0/f_diag/clients diag + write /sys/class/android_usb/android0/f_rmnet/transports smd,bam + write /sys/class/android_usb/android0/f_qdss/debug_intf 1 + write /sys/class/android_usb/android0/f_qdss/transports bam + write /sys/class/android_usb/android0/f_qdss/transport_names qdss_bam + write /sys/class/android_usb/android0/functions diag,qdss,adb,rmnet + write /sys/module/dwc3/parameters/tx_fifo_resize_enable 1 + write /sys/class/android_usb/android0/enable 1 + start adbd + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=diag,qdss,rmnet_qti_bam,adb + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 9084 + write /sys/class/android_usb/android0/f_diag/clients diag + write /sys/class/android_usb/android0/f_rmnet/transports qti,bam + write /sys/class/android_usb/android0/f_qdss/debug_intf 1 + write /sys/class/android_usb/android0/f_qdss/transports bam + write /sys/class/android_usb/android0/f_qdss/transport_names qdss_bam + write /sys/class/android_usb/android0/functions diag,qdss,adb,rmnet + write /sys/module/dwc3/parameters/tx_fifo_resize_enable 1 + write /sys/class/android_usb/android0/enable 1 + start adbd + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=diag,qdss,rmnet_ipa + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 9083 + write /sys/class/android_usb/android0/f_diag/clients diag + write /sys/class/android_usb/android0/f_rmnet/transports qti,bam2bam_ipa + write /sys/class/android_usb/android0/f_qdss/debug_intf 1 + write /sys/class/android_usb/android0/f_qdss/transports bam + write /sys/class/android_usb/android0/f_qdss/transport_names qdss_bam + write /sys/class/android_usb/android0/functions diag,qdss,rmnet + write /sys/class/android_usb/android0/enable 1 + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=diag,qdss,rmnet_ipa,adb + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 9084 + write /sys/class/android_usb/android0/f_diag/clients diag + write /sys/class/android_usb/android0/f_rmnet/transports qti,bam2bam_ipa + write /sys/class/android_usb/android0/f_qdss/debug_intf 1 + write /sys/class/android_usb/android0/f_qdss/transports bam + write /sys/class/android_usb/android0/f_qdss/transport_names qdss_bam + write /sys/class/android_usb/android0/functions diag,qdss,adb,rmnet + write /sys/module/dwc3/parameters/tx_fifo_resize_enable 1 + write /sys/class/android_usb/android0/enable 1 + start adbd + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=diag,diag_mdm,qdss,rmnet_hsic + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 909B + write /sys/class/android_usb/android0/f_diag/clients diag,diag_mdm + write /sys/class/android_usb/android0/f_rmnet/transports hsic,hsic + write /sys/class/android_usb/android0/f_qdss/debug_intf 1 + write /sys/class/android_usb/android0/f_qdss/transports bam + write /sys/class/android_usb/android0/f_qdss/transport_names qdss_bam + write /sys/class/android_usb/android0/functions diag,qdss,rmnet + write /sys/class/android_usb/android0/enable 1 + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=diag,diag_mdm,qdss,rmnet_hsic,adb + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 909A + write /sys/class/android_usb/android0/f_diag/clients diag,diag_mdm + write /sys/class/android_usb/android0/f_rmnet/transports hsic,hsic + write /sys/class/android_usb/android0/f_qdss/debug_intf 1 + write /sys/class/android_usb/android0/f_qdss/transports bam + write /sys/class/android_usb/android0/f_qdss/transport_names qdss_bam + write /sys/class/android_usb/android0/functions diag,qdss,adb,rmnet + write /sys/module/dwc3/parameters/tx_fifo_resize_enable 1 + write /sys/class/android_usb/android0/enable 1 + start adbd + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=diag,diag_mdm,qdss_apq,qdss_mdm,rmnet_hsic + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 90A3 + write /sys/class/android_usb/android0/f_diag/clients diag,diag_mdm + write /sys/class/android_usb/android0/f_rmnet/transports hsic,hsic + write /sys/class/android_usb/android0/f_qdss/debug_intf 0 + write /sys/class/android_usb/android0/f_qdss/transports bam,hsic + write /sys/class/android_usb/android0/f_qdss/transport_names qdss_bam,qdss_hsic + write /sys/class/android_usb/android0/functions diag,qdss,rmnet + write /sys/class/android_usb/android0/enable 1 + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=diag,diag_mdm,qdss_apq,qdss_mdm,rmnet_hsic,adb + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 90A2 + write /sys/class/android_usb/android0/f_diag/clients diag,diag_mdm + write /sys/class/android_usb/android0/f_rmnet/transports hsic,hsic + write /sys/class/android_usb/android0/f_qdss/debug_intf 0 + write /sys/class/android_usb/android0/f_qdss/transports bam,hsic + write /sys/class/android_usb/android0/f_qdss/transport_names qdss_bam,qdss_hsic + write /sys/class/android_usb/android0/functions diag,qdss,adb,rmnet + write /sys/module/dwc3/parameters/tx_fifo_resize_enable 1 + write /sys/class/android_usb/android0/enable 1 + start adbd + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=rndis,diag,qdss + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 9081 + write /sys/class/android_usb/android0/f_diag/clients diag + write /sys/class/android_usb/android0/f_qdss/debug_intf 1 + write /sys/class/android_usb/android0/f_qdss/transports bam + write /sys/class/android_usb/android0/f_qdss/transport_names qdss_bam + write /sys/class/android_usb/android0/functions rndis,diag,qdss + write /sys/class/android_usb/android0/enable 1 + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=rndis,diag,qdss,adb + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 9082 + write /sys/class/android_usb/android0/f_diag/clients diag + write /sys/class/android_usb/android0/f_qdss/debug_intf 1 + write /sys/class/android_usb/android0/f_qdss/transports bam + write /sys/class/android_usb/android0/f_qdss/transport_names qdss_bam + write /sys/class/android_usb/android0/functions rndis,diag,qdss,adb + write /sys/module/dwc3/parameters/tx_fifo_resize_enable 1 + write /sys/class/android_usb/android0/enable 1 + start adbd + setprop sys.usb.state ${sys.usb.config} + +# same as 9025, plus data packet logging (DPL) using QDSS +on property:sys.usb.config=diag,serial_smd,serial_tty,rmnet_ipa,mass_storage,dpl,adb + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 90AD + write /sys/class/android_usb/android0/f_diag/clients diag + write /sys/class/android_usb/android0/f_serial/transports smd,tty +# DPL is implemented using QDSS + write /sys/class/android_usb/android0/f_qdss/debug_intf 0 + write /sys/class/android_usb/android0/f_qdss/transports qti,bam2bam_ipa + write /sys/class/android_usb/android0/f_qdss/transport_names qdss_bam + write /sys/class/android_usb/android0/f_rmnet/transports qti,bam2bam_ipa + write /sys/class/android_usb/android0/functions diag,adb,serial,rmnet,mass_storage,qdss + write /sys/class/android_usb/android0/enable 1 + start adbd + setprop sys.usb.state ${sys.usb.config} + +# same as 9026, plus data packet logging (DPL) +on property:sys.usb.config=diag,serial_smd,serial_tty,rmnet_ipa,mass_storage,dpl + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 90B0 + write /sys/class/android_usb/android0/f_diag/clients diag + write /sys/class/android_usb/android0/f_serial/transports smd,tty +# DPL is implemented using QDSS + write /sys/class/android_usb/android0/f_qdss/debug_intf 0 + write /sys/class/android_usb/android0/f_qdss/transports qti,bam2bam_ipa + write /sys/class/android_usb/android0/f_qdss/transport_names qdss_bam + write /sys/class/android_usb/android0/f_rmnet/transports qti,bam2bam_ipa + write /sys/class/android_usb/android0/functions diag,serial,rmnet,mass_storage,qdss + write /sys/class/android_usb/android0/enable 1 + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=diag,serial_cdev,serial_tty,rmnet_ipa,mass_storage,dpl,adb + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 90AD + write /sys/class/android_usb/android0/f_diag/clients diag + write /sys/class/android_usb/android0/f_serial/transports char_bridge,tty +# DPL is implemented using QDSS + write /sys/class/android_usb/android0/f_qdss/debug_intf 0 + write /sys/class/android_usb/android0/f_qdss/transports qti,bam2bam_ipa + write /sys/class/android_usb/android0/f_qdss/transport_names qdss_bam + write /sys/class/android_usb/android0/f_rmnet/transports qti,bam2bam_ipa + write /sys/class/android_usb/android0/functions diag,adb,serial,rmnet,mass_storage,qdss + write /sys/class/android_usb/android0/enable 1 + start adbd + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=diag,serial_cdev,serial_tty,rmnet_ipa,mass_storage,dpl + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 90B0 + write /sys/class/android_usb/android0/f_diag/clients diag + write /sys/class/android_usb/android0/f_serial/transports char_bridge,tty +# DPL is implemented using QDSS + write /sys/class/android_usb/android0/f_qdss/debug_intf 0 + write /sys/class/android_usb/android0/f_qdss/transports qti,bam2bam_ipa + write /sys/class/android_usb/android0/f_qdss/transport_names qdss_bam + write /sys/class/android_usb/android0/f_rmnet/transports qti,bam2bam_ipa + write /sys/class/android_usb/android0/functions diag,serial,rmnet,mass_storage,qdss + write /sys/class/android_usb/android0/enable 1 + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=ncm + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 0525 + write /sys/class/android_usb/android0/idProduct A4A1 + write /sys/class/android_usb/android0/functions ncm + write /sys/class/android_usb/android0/enable 1 + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=ncm,adb + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 908C + write /sys/class/android_usb/android0/functions ncm,adb + write /sys/class/android_usb/android0/enable 1 + start adbd + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=charging + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct F006 + write /sys/class/android_usb/android0/functions charging + write /sys/class/android_usb/android0/enable 1 + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=diag,serial_smd,rmnet_qti_bam,dpl_qti_bam_dmux + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 90B7 + write /sys/class/android_usb/android0/f_diag/clients diag + write /sys/class/android_usb/android0/f_serial/transports smd + write /sys/class/android_usb/android0/f_rmnet/transports qti,bam + write /sys/class/android_usb/android0/f_qdss/transports qti,bam_dmux + write /sys/class/android_usb/android0/functions diag,serial,rmnet,qdss + write /sys/class/android_usb/android0/enable 1 + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=diag,serial_smd,rmnet_qti_bam,dpl_qti_bam_dmux,adb + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 90B8 + write /sys/class/android_usb/android0/f_diag/clients diag + write /sys/class/android_usb/android0/f_serial/transports smd + write /sys/class/android_usb/android0/f_rmnet/transports qti,bam + write /sys/class/android_usb/android0/f_qdss/transports qti,bam_dmux + write /sys/class/android_usb/android0/functions diag,serial,rmnet,qdss,adb + write /sys/class/android_usb/android0/enable 1 + start adbd + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=diag,diag_cnss,serial_smd,serial_tty,rmnet_bam,mass_storage,adb + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 90B2 + write /sys/class/android_usb/android0/f_diag/clients diag,diag_cnss + write /sys/class/android_usb/android0/f_serial/transports smd,tty + write /sys/class/android_usb/android0/f_rmnet/transports smd,bam + write /sys/class/android_usb/android0/functions diag,diag_cnss,adb,serial,rmnet,mass_storage + write /sys/class/android_usb/android0/enable 1 + start adbd + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=diag,diag_cnss,serial_smd,serial_tty,rmnet_bam,mass_storage + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 90B3 + write /sys/class/android_usb/android0/f_diag/clients diag,diag_cnss + write /sys/class/android_usb/android0/f_serial/transports smd,tty + write /sys/class/android_usb/android0/f_rmnet/transports smd,bam + write /sys/class/android_usb/android0/functions diag,diag_cnss,serial,rmnet,mass_storage + write /sys/class/android_usb/android0/enable 1 + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=midi + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 90BA + write /sys/class/android_usb/android0/functions midi + write /sys/class/android_usb/android0/enable 1 + setprop sys.usb.state ${sys.usb.config} + +on property:sys.usb.config=midi,adb + write /sys/class/android_usb/android0/enable 0 + write /sys/class/android_usb/android0/idVendor 05C6 + write /sys/class/android_usb/android0/idProduct 90BB + write /sys/class/android_usb/android0/functions midi,adb + write /sys/class/android_usb/android0/enable 1 + start adbd + setprop sys.usb.state ${sys.usb.config} diff --git a/rootdir/etc/init.qcom.usb.sh b/rootdir/etc/init.qcom.usb.sh new file mode 100755 index 000000000..6d31504aa --- /dev/null +++ b/rootdir/etc/init.qcom.usb.sh @@ -0,0 +1,281 @@ +#!/system/bin/sh +# Copyright (c) 2012, The Linux Foundation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials provided +# with the distribution. +# * Neither the name of The Linux Foundation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# +chown -h root.system /sys/devices/platform/msm_hsusb/gadget/wakeup +chmod -h 220 /sys/devices/platform/msm_hsusb/gadget/wakeup + +# Set platform variables +if [ -f /sys/devices/soc0/hw_platform ]; then + soc_hwplatform=`cat /sys/devices/soc0/hw_platform` 2> /dev/null +else + soc_hwplatform=`cat /sys/devices/system/soc/soc0/hw_platform` 2> /dev/null +fi + +# Get hardware revision +if [ -f /sys/devices/soc0/revision ]; then + soc_revision=`cat /sys/devices/soc0/revision` 2> /dev/null +else + soc_revision=`cat /sys/devices/system/soc/soc0/revision` 2> /dev/null +fi + +# +# Allow persistent usb charging disabling +# User needs to set usb charging disabled in persist.usb.chgdisabled +# +target=`getprop ro.board.platform` +usbchgdisabled=`getprop persist.usb.chgdisabled` +case "$usbchgdisabled" in + "") ;; #Do nothing here + * ) + case $target in + "msm8660") + echo "$usbchgdisabled" > /sys/module/pmic8058_charger/parameters/disabled + echo "$usbchgdisabled" > /sys/module/smb137b/parameters/disabled + ;; + "msm8960") + echo "$usbchgdisabled" > /sys/module/pm8921_charger/parameters/disabled + ;; + esac +esac + +usbcurrentlimit=`getprop persist.usb.currentlimit` +case "$usbcurrentlimit" in + "") ;; #Do nothing here + * ) + case $target in + "msm8960") + echo "$usbcurrentlimit" > /sys/module/pm8921_charger/parameters/usb_max_current + ;; + esac +esac + +# +# Check ESOC for external MDM +# +# Note: currently only a single MDM is supported +# +if [ -d /sys/bus/esoc/devices ]; then +for f in /sys/bus/esoc/devices/*; do + if [ -d $f ]; then + if [ `grep "^MDM" $f/esoc_name` ]; then + esoc_link=`cat $f/esoc_link` + break + fi + fi +done +fi + +target=`getprop ro.board.platform` + +#ifdef VENDOR_EDIT +boot_mode=`getprop ro.boot.ftm_mode` +echo "boot_mode: $boot_mode" > /dev/kmsg +case "$boot_mode" in + "ftm_at" | "ftm_rf" | "ftm_wlan" | "ftm_mos") + usb_config=`getprop persist.sys.usb.config` + echo "BEFORE boot_mode: $usb_config" > /dev/kmsg + if [ "$usb_config" != "diag,adb" ] ; then + setprop persist.sys.usb.config diag,adb + fi + ;; +esac +usb_config=`getprop persist.sys.usb.config` +echo "AFTER boot_mode: $usb_config" > /dev/kmsg +#endif + +# +# Allow USB enumeration with default PID/VID +# +baseband=`getprop ro.baseband` +echo 1 > /sys/class/android_usb/f_mass_storage/lun/nofua +usb_config=`getprop persist.sys.usb.config` +echo "BEFORE: $usb_config" > /dev/kmsg +case "$usb_config" in + "" | "adb" | "none") #USB persist config not set, select default configuration + case "$esoc_link" in + "PCIe") + setprop persist.sys.usb.config diag,diag_mdm,serial_cdev,rmnet_qti_ether,mass_storage,adb + ;; + *) + case "$soc_hwplatform" in + "Dragon") + setprop persist.sys.usb.config diag,adb + ;; + *) + case "$target" in + "msm8916") + setprop persist.sys.usb.config diag,serial_smd,rmnet_bam,adb + ;; + "msm8994" | "msm8992") + if [ "$soc_hwplatform" == "Dragon" ]; then + setprop persist.sys.usb.config diag,adb + else + setprop persist.sys.usb.config diag,serial_smd,serial_tty,rmnet_ipa,mass_storage,adb + fi + ;; + "msm8996") + if [ "$soc_revision" == "1.0" -o "$soc_hwplatform" == "Dragon" ] + then + setprop persist.sys.usb.config diag,adb + #[BSP-66]-Anderson-Disable_set_the_property. + #This will ause BSP-66 issue and cause all the port enable in default. + #else + #setprop persist.sys.usb.config diag,serial_cdev,serial_tty,rmnet_ipa,mass_storage,adb + fi + ;; + "msm8909" | "msm8937") + setprop persist.sys.usb.config diag,serial_smd,rmnet_qti_bam,adb + ;; + "msm8952" | "titanium") + setprop persist.sys.usb.config diag,serial_smd,rmnet_ipa,adb + ;; + *) + setprop persist.sys.usb.config diag,adb + ;; + esac + ;; + esac + ;; + esac + ;; + * ) ;; #USB persist config exists, do nothing +esac + + + +# +# Do target specific things +# +case "$target" in + "msm8974") +# Select USB BAM - 2.0 or 3.0 + echo ssusb > /sys/bus/platform/devices/usb_bam/enable + ;; + "apq8084") + if [ "$baseband" == "apq" ]; then + echo "msm_hsic_host" > /sys/bus/platform/drivers/xhci_msm_hsic/unbind + fi + ;; + "msm8226") + if [ -e /sys/bus/platform/drivers/msm_hsic_host ]; then + if [ ! -L /sys/bus/usb/devices/1-1 ]; then + echo msm_hsic_host > /sys/bus/platform/drivers/msm_hsic_host/unbind + fi + fi + ;; + "msm8994" | "msm8992" | "msm8996" | "titanium") + echo BAM2BAM_IPA > /sys/class/android_usb/android0/f_rndis_qc/rndis_transports + echo 131072 > /sys/module/g_android/parameters/mtp_tx_req_len + echo 131072 > /sys/module/g_android/parameters/mtp_rx_req_len + ;; +esac + +# +# set module params for embedded rmnet devices +# +rmnetmux=`getprop persist.rmnet.mux` +case "$baseband" in + "mdm" | "dsda" | "sglte2") + case "$rmnetmux" in + "enabled") + echo 1 > /sys/module/rmnet_usb/parameters/mux_enabled + echo 8 > /sys/module/rmnet_usb/parameters/no_fwd_rmnet_links + echo 17 > /sys/module/rmnet_usb/parameters/no_rmnet_insts_per_dev + ;; + esac + echo 1 > /sys/module/rmnet_usb/parameters/rmnet_data_init + # Allow QMUX daemon to assign port open wait time + chown -h radio.radio /sys/devices/virtual/hsicctl/hsicctl0/modem_wait + ;; + "dsda2") + echo 2 > /sys/module/rmnet_usb/parameters/no_rmnet_devs + echo hsicctl,hsusbctl > /sys/module/rmnet_usb/parameters/rmnet_dev_names + case "$rmnetmux" in + "enabled") #mux is neabled on both mdms + echo 3 > /sys/module/rmnet_usb/parameters/mux_enabled + echo 8 > /sys/module/rmnet_usb/parameters/no_fwd_rmnet_links + echo 17 > write /sys/module/rmnet_usb/parameters/no_rmnet_insts_per_dev + ;; + "enabled_hsic") #mux is enabled on hsic mdm + echo 1 > /sys/module/rmnet_usb/parameters/mux_enabled + echo 8 > /sys/module/rmnet_usb/parameters/no_fwd_rmnet_links + echo 17 > /sys/module/rmnet_usb/parameters/no_rmnet_insts_per_dev + ;; + "enabled_hsusb") #mux is enabled on hsusb mdm + echo 2 > /sys/module/rmnet_usb/parameters/mux_enabled + echo 8 > /sys/module/rmnet_usb/parameters/no_fwd_rmnet_links + echo 17 > /sys/module/rmnet_usb/parameters/no_rmnet_insts_per_dev + ;; + esac + echo 1 > /sys/module/rmnet_usb/parameters/rmnet_data_init + # Allow QMUX daemon to assign port open wait time + chown -h radio.radio /sys/devices/virtual/hsicctl/hsicctl0/modem_wait + ;; +esac + +# +# Add support for exposing lun0 as cdrom in mass-storage +# +cdromname="/system/etc/cdrom_install.iso" +platformver=`cat /sys/devices/soc0/hw_platform` +case "$target" in + "msm8226" | "msm8610" | "msm8916") + case $platformver in + "QRD") + echo "mounting usbcdrom lun" + echo $cdromname > /sys/class/android_usb/android0/f_mass_storage/rom/file + chmod 0444 /sys/class/android_usb/android0/f_mass_storage/rom/file + ;; + esac + ;; +esac + +# +# Initialize RNDIS Diag option. If unset, set it to 'none'. +# +diag_extra=`getprop persist.sys.usb.config.extra` +if [ "$diag_extra" == "" ]; then + setprop persist.sys.usb.config.extra none +fi + +# soc_ids for 8937 +if [ -f /sys/devices/soc0/soc_id ]; then + soc_id=`cat /sys/devices/soc0/soc_id` +else + soc_id=`cat /sys/devices/system/soc/soc0/id` +fi + +# enable rps cpus on msm8937 target +setprop sys.usb.rps_mask 0 +case "$soc_id" in + "294" | "295") + setprop sys.usb.rps_mask 10 + ;; +esac + diff --git a/rootdir/etc/init.target.rc b/rootdir/etc/init.target.rc new file mode 100755 index 000000000..628c6a5e9 --- /dev/null +++ b/rootdir/etc/init.target.rc @@ -0,0 +1,280 @@ +# Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials provided +# with the distribution. +# * Neither the name of The Linux Foundation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# + +on early-init + mkdir /firmware 0771 system system + mkdir /bt_firmware 0771 system system + symlink /data/tombstones /tombstones + mkdir /dsp 0771 media media + chown system root /sys/module/msm_thermal/core_control/cpus_offlined + chmod 666 /sys/module/msm_thermal/core_control/cpus_offlined + +on post-fs + export LD_PRELOAD libNimsWrap.so + +on init + write /sys/module/qpnp_rtc/parameters/poweron_alarm 1 + +on fs + wait /dev/block/bootdevice + mount_all fstab.qcom + swapon_all fstab.qcom + + restorecon_recursive /persist + mkdir /persist/data 0700 system system + mkdir /persist/wlan_bt 0700 system system + mkdir /persist/audio 0777 media audio + +on post-fs-data + mkdir /data/tombstones 0771 system system + mkdir /tombstones/modem 0771 system system + mkdir /tombstones/lpass 0771 system system + mkdir /tombstones/wcnss 0771 system system + mkdir /tombstones/dsps 0771 system system + mkdir /persist/data/sfs 0700 system system + mkdir /persist/data/tz 0700 system system + mkdir /persist/qc_senseid 0700 system system + mkdir /data/misc/dts 0770 media audio + mkdir /data/nfc 0770 nfc nfc + mkdir /data/misc/tloc/ 0700 system drmrpc + mkdir /data/misc/qvop 0660 system system + mkdir /data/misc/qvr 0770 system system + mkdir /data/misc/audio_pp 0771 media audio + chown system system /dev/sysmatdrv + chmod 0660 /dev/sysmatdrv + mkdir /data/fpc 0770 system system + mkdir /data/fpc/s 0770 system system + +on boot + start rmt_storage + + # Access permission for secure touch + chmod 0660 /sys/devices/soc/75ba000.i2c/i2c-12/12-0020/secure_touch_enable + chmod 0440 /sys/devices/soc/75ba000.i2c/i2c-12/12-0020/secure_touch + chown system drmrpc /sys/devices/soc/75ba000.i2c/i2c-12/12-0020/secure_touch_enable + chown system drmrpc /sys/devices/soc/75ba000.i2c/i2c-12/12-0020/secure_touch + + # Access permission for led torch + chmod 0666 /sys/class/leds/led:torch_0/brightness + chmod 0666 /sys/class/leds/led:torch_1/brightness + chmod 0666 /sys/class/leds/led:switch/brightness + + # Access permission for smartPA + chmod 0666 /dev/i2c-3 + chmod 0666 /dev/i2c-9 + +# Audio smartPA cold boot +service tfa_cold_boot /system/bin/sh /system/bin/tfa_coldboot.sh /etc/silence_short.wav 15 1 + class main + user system + group system + disabled + oneshot + +on property:service.soundcard.detected=1 + start tfa_cold_boot + +# Start camera server as daemon +service qcamerasvr /system/bin/mm-qcamera-daemon + class late_start + user camera + group camera system inet input graphics + writepid /dev/cpuset/system-background/tasks + +# Fingerprint service +service fingerprintd /system/bin/fingerprintd + class late_start + user system + group system sdcard_rw + +service qvop-daemon /system/bin/qvop-daemon + class late_start + user system + group system drmrpc + +# Start up peripheral manager +service per_mgr system/bin/pm-service + class core + user system + group system net_raw + ioprio rt 4 + +service per_proxy /system/bin/pm-proxy + class core + user system + group system + disabled + +on property:init.svc.per_mgr=running + start per_proxy + +on property:sys.shutdown.requested=* + stop per_proxy + +service qseecomd /system/bin/qseecomd + class core + user root + group root + +service thermal-engine /system/vendor/bin/thermal-engine + class main + user root + socket thermal-send-client stream 0666 system system + socket thermal-recv-client stream 0660 system system + socket thermal-recv-passive-client stream 0666 system system + group root + +service time_daemon /system/bin/time_daemon + class late_start + user root + group root + +service adsprpcd /system/bin/adsprpcd + class main + user media + group media + +service audiod /system/bin/audiod + class late_start + user system + group system + +service imsqmidaemon /system/bin/imsqmidaemon + class main + user system + socket ims_qmid stream 0660 system radio + group radio net_raw log diag + +service imsdatadaemon /system/bin/imsdatadaemon + class main + user system + socket ims_datad stream 0660 system radio + group system wifi radio inet net_raw log diag net_admin + disabled + +service pd_mapper /system/vendor/bin/pd-mapper + class core + disabled + +on property:persist.sys.pd_enable=1 + start pd_mapper + write /sys/class/service_locator/service_locator_status 1 + +on property:persist.sys.pd_enable=0 + write /sys/class/service_locator/service_locator_status 0 + +on property:sys.ims.QMI_DAEMON_STATUS=1 + start imsdatadaemon + +service ims_rtp_daemon /system/bin/ims_rtp_daemon + class main + user system + socket ims_rtpd stream 0660 system radio + group radio net_raw diag inet log + disabled + +service imscmservice /system/bin/imscmservice + class main + user system + group radio net_raw diag diag log + disabled + +on property:sys.ims.DATA_DAEMON_STATUS=1 + start ims_rtp_daemon + start imscmservice + +service ppd /system/vendor/bin/mm-pp-dpps + class late_start + user system + group system graphics + socket pps stream 0660 system system + disabled + +on property:init.svc.surfaceflinger=stopped + stop displayfeature + stop ppd + +on property:init.svc.surfaceflinger=running + start displayfeature + start ppd + +on property:init.svc.surfaceflinger=restarting + stop displayfeature + stop ppd + +on property:init.svc.zygote=stopped + stop displayfeature + stop ppd + +on property:init.svc.zygote=running + start displayfeature + start ppd + +on property:init.svc.zygote=restarting + stop displayfeature + stop ppd + +service tlocd /system/bin/tloc_daemon + class late_start + user system + group drmrpc gps net_raw + +service displayfeature /system/bin/displayfeature + class late_start + user root + group root + +service qpaydaemon /system/vendor/bin/qpaydaemon + class late_start + user system + group system + +service nv_fem /system/bin/nv_fem + class main + user root + group net_raw + oneshot + +service nv_mac /system/bin/nv_mac + class main + user root + group net_raw + oneshot + +service mmbn-daemon /system/bin/mmbn-daemon + class main + oneshot + +on property:slpi.restart=1 + write /sys/kernel/debug/msm_subsys/slpi restart + +on property:persist.sys.display_oled_hbm=0 + write /sys/devices/virtual/graphics/fb0/msm_fb_dispparam 0xE00 + +on property:persist.sys.display_oled_hbm=1 + write /sys/devices/virtual/graphics/fb0/msm_fb_dispparam 0xD00 diff --git a/rootdir/etc/recovery/recovery.fstab b/rootdir/etc/recovery/recovery.fstab new file mode 100644 index 000000000..55e26698a --- /dev/null +++ b/rootdir/etc/recovery/recovery.fstab @@ -0,0 +1,21 @@ +# Android fstab file. +# The filesystem that contains the filesystem checker binary (typically /system) cannot +# specify MF_CHECK, and must come before any filesystems that do specify MF_CHECK + +#TODO: Add 'check' as fs_mgr_flags with data partition. +# Currently we dont have e2fsck compiled. So fs check would failed. + +# +/dev/block/bootdevice/by-name/boot /boot emmc defaults defaults +/dev/block/bootdevice/by-name/recovery /recovery emmc defaults defaults +/dev/block/bootdevice/by-name/system /system ext4 ro,barrier=1,discard wait +/dev/block/bootdevice/by-name/userdata /data f2fs nosuid,nodev,noatime,nodiratime,inline_xattr,data_flush wait,check,encryptable=footer,formattable,length=-16384 +/dev/block/bootdevice/by-name/userdata /data ext4 nosuid,nodev,noatime,nodiratime,barrier=1,noauto_da_alloc wait,check,encryptable=footer,formattable,length=-16384 +/dev/block/bootdevice/by-name/cache /cache f2fs nosuid,nodev,noatime,nodiratime,inline_xattr,flush_merge,data_flush wait,check,formattable +/dev/block/bootdevice/by-name/cache /cache ext4 nosuid,nodev,noatime,nodiratime,barrier=1 wait,check,formattable +/dev/block/bootdevice/by-name/persist /persist ext4 nosuid,nodev,barrier=1 wait +/dev/block/bootdevice/by-name/dsp /dsp ext4 ro,nosuid,nodev,barrier=1 wait +/dev/block/bootdevice/by-name/modem /firmware vfat ro,shortname=lower,uid=1000,gid=1000,dmask=227,fmask=337,context=u:object_r:firmware_file:s0 wait +/dev/block/bootdevice/by-name/bluetooth /bt_firmware vfat ro,shortname=lower,uid=1002,gid=3002,dmask=222,fmask=333,context=u:object_r:bt_firmware_file:s0 wait + +/devices/soc/6a00000.ssusb/6a00000.dwc3/xhci-hcd.0.auto/usb* auto auto defaults voldmanaged=usbdisk:auto diff --git a/rootdir/etc/ueventd.qcom.rc b/rootdir/etc/ueventd.qcom.rc new file mode 100644 index 000000000..185151828 --- /dev/null +++ b/rootdir/etc/ueventd.qcom.rc @@ -0,0 +1,246 @@ +# Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of The Linux Foundation nor +# the names of its contributors may be used to endorse or promote +# products derived from this software without specific prior written +# permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# the DIAG device node is not world writable/readable. +/dev/diag 0660 system qcom_diag + +/dev/genlock 0666 system system +/dev/kgsl 0666 system system +/dev/kgsl-3d0 0666 system system +/dev/kgsl-2d0 0666 root root +/dev/kgsl-2d1 0666 root root +/dev/ion 0664 system system +/dev/rtc0 0600 system system +/dev/smd0 0660 system system +/dev/smd4 0660 system system +/dev/smd_cxm_qmi 0640 radio radio +/dev/smd5 0660 system system +/dev/smd6 0660 system system +/dev/smd7 0660 bluetooth bluetooth +/dev/ccid_bridge 0660 system system +/dev/ipa 0660 system net_admin +/dev/wwan_ioctl 0660 system net_admin +/dev/ipaNatTable 0660 net_admin net_admin +/dev/rmnet_ctrl 0660 usb usb +/dev/dpl_ctrl 0660 usb usb + +#permissions for CSVT +/dev/smd11 0660 radio radio + +/dev/radio0 0640 system system +/dev/rfcomm0 0660 bluetooth bluetooth +/dev/ttyUSB0 0660 bluetooth bluetooth +/dev/smdcntl0 0640 radio radio +/dev/smdcntl1 0640 radio radio +/dev/smdcntl2 0640 radio radio +/dev/smdcntl3 0640 radio radio +/dev/smdcntl4 0640 radio radio +/dev/smdcntl5 0640 radio radio +/dev/smdcntl6 0640 radio radio +/dev/smdcntl7 0640 radio radio +/dev/smdcntl8 0640 radio radio +/dev/smdcnt_rev0 0640 radio radio +/dev/smdcnt_rev1 0640 radio radio +/dev/smdcnt_rev2 0640 radio radio +/dev/smdcnt_rev3 0640 radio radio +/dev/smdcnt_rev4 0640 radio radio +/dev/smdcnt_rev5 0640 radio radio +/dev/smdcnt_rev6 0640 radio radio +/dev/smdcnt_rev7 0640 radio radio +/dev/smdcnt_rev8 0640 radio radio +/dev/smuxctl32 0640 radio radio +/dev/sdioctl0 0640 radio radio +/dev/sdioctl1 0640 radio radio +/dev/sdioctl2 0640 radio radio +/dev/sdioctl3 0640 radio radio +/dev/sdioctl4 0640 radio radio +/dev/sdioctl5 0640 radio radio +/dev/sdioctl6 0640 radio radio +/dev/sdioctl7 0640 radio radio +/dev/sdioctl8 0640 radio radio +/dev/rmnet_mux_ctrl 0640 radio radio +/dev/hsicctl0 0640 radio radio +/dev/hsicctl1 0640 radio radio +/dev/hsicctl2 0640 radio radio +/dev/hsicctl3 0640 radio radio +/dev/hsicctl4 0640 radio radio +/dev/hsicctl5 0640 radio radio +/dev/hsicctl6 0640 radio radio +/dev/hsicctl7 0640 radio radio +/dev/hsicctl8 0640 radio radio +/dev/hsicctl9 0640 radio radio +/dev/hsicctl10 0640 radio radio +/dev/hsicctl11 0640 radio radio +/dev/hsicctl12 0640 radio radio +/dev/hsicctl13 0640 radio radio +/dev/hsicctl14 0640 radio radio +/dev/hsicctl15 0640 radio radio +/dev/hsicctl16 0640 radio radio +/dev/mhi_pipe_14 0640 radio radio +/dev/mhi_pipe_16 0640 radio radio +/dev/mhi_pipe_32 0640 radio radio +/dev/video* 0660 system camera +/dev/media* 0660 system camera +/dev/v4l-subdev* 0660 system camera +/dev/qseecom 0660 system drmrpc +/dev/seemplog 0660 system system +/dev/pft 0660 system drmrpc +/dev/gemini0 0660 system camera +/dev/jpeg0 0660 system camera +/dev/jpeg1 0660 system camera +/dev/jpeg2 0660 system camera +/dev/jpeg3 0660 system camera +/dev/adsprpc-smd 0664 system system +/dev/system_health_monitor 0644 radio system +/dev/mdss_rotator 0664 system system +/dev/msm_camera/* 0660 system camera +/dev/gemini/ 0660 system camera +/dev/mercury0 0660 system camera +/dev/msm_vidc_reg 0660 system audio +/dev/msm_vidc_dec 0660 system audio +/dev/msm_vidc_dec_sec 0660 system audio +/dev/msm_vidc_enc 0660 system audio +/dev/msm_rotator 0660 system system +/dev/hw_random 0600 root root +/dev/adsprpc-smd 0664 system system + +#permissions for audio +/dev/audio_slimslave 0660 system audio +/dev/msm_qcelp 0660 system audio +/dev/msm_evrc 0660 system audio +/dev/msm_wma 0660 system audio +/dev/msm_wmapro 0660 system audio +/dev/msm_alac 0660 system audio +/dev/msm_ape 0660 system audio +/dev/msm_amrnb 0660 system audio +/dev/msm_amrwb 0660 system audio +/dev/msm_amrwbplus 0660 system audio +/dev/msm_aac 0660 system audio +/dev/msm_multi_aac 0660 system audio +/dev/msm_aac_in 0660 system audio +/dev/msm_qcelp_in 0660 system audio +/dev/msm_evrc_in 0660 system audio +/dev/msm_amrnb_in 0640 system audio +/dev/msm_a2dp_in 0660 system audio +/dev/msm_ac3 0660 system audio +/dev/msm_audio_cal 0660 system audio +/dev/msm_hweffects 0660 system audio +/dev/msm_cad 0660 system audio +/dev/msm_fm 0660 system audio +/dev/msm_mvs 0660 system audio +/dev/msm_pcm_lp_dec 0660 system audio +/dev/msm_preproc_ctl 0660 system audio +/dev/msm_rtac 0660 system audio +/dev/msm_voicememo 0660 system audio +/dev/smd3 0660 bluetooth net_bt_stack +/dev/smd2 0660 bluetooth net_bt_stack +/dev/ttyHSL1 0660 system system +/dev/ttyHS1 0660 system system +/dev/ttyGS1 0660 system system +/dev/smd8 0660 system system +/dev/mdm 0660 system radio +/sys/devices/virtual/smdpkt/smdcntl* open_timeout 0664 radio radio +/dev/sdio_tty_ciq_00 0660 system system +/dev/tty_sdio_00 0660 system system +/dev/ttyGS0 0660 system system +/dev/i2c-5 0660 media media +/dev/voice_svc 0660 system audio +/dev/avtimer 0660 system audio + +# DVB devices +/dev/dvb/adapter0/demux* 0440 media media +/dev/dvb/adapter0/dvr* 0660 media media +/dev/dvb/adapter0/video* 0660 media media + +# Broadcast devices +/dev/tsc_mux0 0660 media media +/dev/tsc_ci0 0660 media media + +# ultrasonic fingerprint +/sys/devices/soc/757a000.i2c/i2c-6/* eeprom 0440 system system + +# sensors +/sys/devices/i2c-12/12-* pollrate_ms 0664 system system +/sys/devices/f9925000.i2c/i2c-0/0-* enable 0660 input system +/sys/devices/f9925000.i2c/i2c-0/0-* poll_delay 0660 input system +/sys/devices/soc.0/78b6000.i2c/i2c-0/0-* enable 0660 input system +/sys/devices/soc.0/78b6000.i2c/i2c-0/0-* poll_delay 0660 input system +/sys/devices/soc.0/78b6000.i2c/i2c-0/0-* enable_wakeup 0660 input system +/sys/devices/soc.0/78b6000.i2c/i2c-0/0-* max_latency 0660 input system +/sys/devices/soc.0/78b6000.i2c/i2c-0/0-* flush 0660 input system +/sys/devices/soc.0/78b6000.i2c/i2c-0/0-* calibrate 0660 input system +/sys/devices/soc.0/78b5000.i2c/i2c-1/1-* enable 0660 input system +/sys/devices/soc.0/78b5000.i2c/i2c-1/1-* poll_delay 0660 input system +/sys/devices/soc.0/78b5000.i2c/i2c-1/1-* enable_wakeup 0660 input system +/sys/devices/soc.0/78b5000.i2c/i2c-1/1-* max_latency 0660 input system +/sys/devices/soc.0/78b5000.i2c/i2c-1/1-* flush 0660 input system +/sys/devices/soc.0/78b5000.i2c/i2c-1/1-* calibrate 0660 input system +/sys/devices/virtual/optical_sensors/proximity ps_adc 0660 input system +/sys/devices/virtual/optical_sensors/proximity ps_poll_delay 0660 input system +/sys/devices/virtual/optical_sensors/lightsensor ls_auto 0660 input system +/sys/devices/virtual/optical_sensors/lightsensor ls_poll_delay 0660 input system +/sys/devices/virtual/input/input* poll 0660 input system +/sys/devices/virtual/input/input* pollrate_ms 0660 input system + +# vm_bms +/dev/vm_bms 0660 system system +/dev/battery_data 0660 system system + +# wlan +/dev/wcnss_wlan 0660 system system +/dev/wcnss_ctrl 0660 system system +/sys/devices/soc/600000.qcom,pcie/pci0000:00/0000:00:00.0/0000:01:00.0/net/wlan0/queues/rx-* rps_cpus 0660 system system +/sys/devices/soc/600000.qcom,pcie/pci0000:00/0000:00:00.0/0000:01:00.0/net/p2p0/queues/rx-* rps_cpus 0660 system system + +# nfc permissions +/dev/nfc-nci 0660 nfc nfc +/dev/nq-nci 0660 nfc nfc +/dev/assd 0660 nfc nfc + +# UIO devices +/dev/uio0 0660 system system +/dev/uio1 0660 system system +/dev/uio2 0660 system system + +# SSR devices +/dev/subsys_* 0640 system system + +# Ultrasound device +/dev/usf1 0660 system system + +# Ramdump devices +/dev/ramdump* 0640 system system + +# Fingerprint device +/dev/qbt1000 0660 system system + +# ImproveTouch device +/dev/hbtp_input 0660 system system +/dev/hbtp_vm 0660 system system + +# TFA9890 FOR SMARTPA +/dev/tfa9890 0660 media media diff --git a/sepolicy/alipay_app.te b/sepolicy/alipay_app.te new file mode 100644 index 000000000..6cc3ad2eb --- /dev/null +++ b/sepolicy/alipay_app.te @@ -0,0 +1,56 @@ +# Generally based on untrusted_app.te + +type alipay_app, domain; +app_domain(alipay_app) +net_domain(alipay_app) +bluetooth_domain(alipay_app) + +# Some apps ship with shared libraries and binaries that they write out +# to their sandbox directory and then execute. +allow alipay_app app_data_file:file { rx_file_perms execmod }; + +# Used by Finsky / Android "Verify Apps" functionality when +# running "adb install foo.apk". +# TODO: Long term, we don't want apps probing into shell data files. +# Figure out a way to remove these rules. +allow alipay_app shell_data_file:file r_file_perms; +allow alipay_app shell_data_file:dir r_dir_perms; + +# Read and write system app data files passed over Binder. +# Motivating case was /data/data/com.android.settings/cache/*.jpg for +# cropping or taking user photos. +allow alipay_app system_app_data_file:file { read write getattr }; + +# +# Rules migrated from old app domains coalesced into alipay_app. +# This includes what used to be media_app, shared_app, and release_app. +# + +# Access to /data/media. +allow alipay_app media_rw_data_file:dir create_dir_perms; +allow alipay_app media_rw_data_file:file create_file_perms; + +# Traverse into /mnt/media_rw for bypassing FUSE daemon +# TODO: narrow this to just MediaProvider +allow alipay_app mnt_media_rw_file:dir search; + +# Write to /cache. +allow alipay_app cache_file:dir create_dir_perms; +allow alipay_app cache_file:file create_file_perms; + +allow alipay_app battery_service:service_manager find; +allow alipay_app drmserver_service:service_manager find; +allow alipay_app healthd_service:service_manager find; +allow alipay_app mediaserver_service:service_manager find; +allow alipay_app nfc_service:service_manager find; +allow alipay_app radio_service:service_manager find; +allow alipay_app surfaceflinger_service:service_manager find; +allow alipay_app app_api_service:service_manager find; +allow alipay_app ifaadaemon_service:service_manager find; + +# TODO: remove this once priv-apps are no longer running in alipay_app +allow alipay_app system_api_service:service_manager find; + +# Programs routinely attempt to scan through /system, looking +# for files. Suppress the denials when they occur. +dontaudit alipay_app exec_type:file getattr; diff --git a/sepolicy/bluetooth_loader.te b/sepolicy/bluetooth_loader.te new file mode 100644 index 000000000..0f287d78f --- /dev/null +++ b/sepolicy/bluetooth_loader.te @@ -0,0 +1,6 @@ +# Bluetooth executables and scripts +type bluetooth_loader, domain; +type bluetooth_loader_exec, exec_type, file_type; + +# Start bdAddrLoader from init +init_daemon_domain(bluetooth_loader) diff --git a/sepolicy/cnd.te b/sepolicy/cnd.te new file mode 100644 index 000000000..e325e4035 --- /dev/null +++ b/sepolicy/cnd.te @@ -0,0 +1 @@ +allow cnd diag_prop:property_service set; diff --git a/sepolicy/device.te b/sepolicy/device.te new file mode 100644 index 000000000..e27112956 --- /dev/null +++ b/sepolicy/device.te @@ -0,0 +1 @@ +type fpc1020_device, dev_type; diff --git a/sepolicy/file.te b/sepolicy/file.te new file mode 100644 index 000000000..139812a05 --- /dev/null +++ b/sepolicy/file.te @@ -0,0 +1,5 @@ +type fpc_data_file, file_type; +type fpc_images_file, file_type; +type sysfs_fpc_irq, sysfs_type, fs_type; +type proc_touchpanel, fs_type; +type nv_data_file, file_type; diff --git a/sepolicy/file_contexts b/sepolicy/file_contexts new file mode 100644 index 000000000..b89c4d049 --- /dev/null +++ b/sepolicy/file_contexts @@ -0,0 +1,20 @@ +# We have a couple of non-standard NV partitions +/dev/block/bootdevice/by-name/oem_dycnvbk u:object_r:modem_efs_partition_device:s0 +/dev/block/bootdevice/by-name/oem_stanvbk u:object_r:modem_efs_partition_device:s0 + +# FRP partition +/dev/block/bootdevice/by-name/config u:object_r:frp_block_device:s0 + +/system/etc/init\.qcom\.bt\.sh u:object_r:bluetooth_loader_exec:s0 + +/persist/sensors/gyro_sensitity_cal u:object_r:sensors_persist_file:s0 + +/data/oemnvitems(/.*)? u:object_r:nv_data_file:s0 + +/dev/fpc1020 u:object_r:fpc1020_device:s0 +/data/fpc(/.*)? u:object_r:fpc_data_file:s0 +/data/fpc_images(/.*)? u:object_r:fpc_images_file:s0 +/sys/devices/soc/soc:fpc_fpc1020/irq u:object_r:sysfs_fpc_irq:s0 + +#IFAA +/system/bin/ifaad u:object_r:ifaad_exec:s0 diff --git a/sepolicy/fingerprintd.te b/sepolicy/fingerprintd.te new file mode 100644 index 000000000..29e56af50 --- /dev/null +++ b/sepolicy/fingerprintd.te @@ -0,0 +1,12 @@ +allow fingerprintd firmware_file:file { read getattr open }; +allow fingerprintd firmware_file:dir search; +allow fingerprintd fpc_data_file:dir { write remove_name add_name search read open }; +allow fingerprintd fpc_data_file:sock_file { create unlink setattr }; +allow fingerprintd fpc_images_file:dir { read write open add_name search }; +allow fingerprintd fpc_images_file:file { write create open getattr }; +allow fingerprintd sysfs_fpc_irq:file { read write open }; +allow fingerprintd tee_device:chr_file { read write ioctl open }; +allow fingerprintd sysfs:file write; +allow fingerprintd proc_touchpanel:dir search; +allow fingerprintd proc_touchpanel:file { read open }; +allow fingerprintd vfat:file { read getattr open }; diff --git a/sepolicy/genfs_contexts b/sepolicy/genfs_contexts new file mode 100644 index 000000000..cfc50b622 --- /dev/null +++ b/sepolicy/genfs_contexts @@ -0,0 +1,3 @@ +genfscon proc /touchpanel u:object_r:proc_touchpanel:s0 +genfscon proc /s1302 u:object_r:proc_touchpanel:s0 +genfscon proc /tri-state-key u:object_r:proc_touchpanel:s0 diff --git a/sepolicy/ifaad.te b/sepolicy/ifaad.te new file mode 100644 index 000000000..3650eaa17 --- /dev/null +++ b/sepolicy/ifaad.te @@ -0,0 +1,26 @@ +type ifaad, domain; +type ifaad_exec, exec_type, file_type; + +#Allow for transition from init domain to ifaad +init_daemon_domain(ifaad) + +#Allow ifaad to use Binder IPC +binder_use(ifaad) + +#Allow servicemanager to interact with ifaad +binder_call(ifaad, servicemanager) + +#Allow alipay_app to interact with ifaad +binder_call(ifaad, alipay_app) + +#Mark ifaad as a Binder service domain +binder_service(ifaad) + +#Allow ifaad to be registered with service manager +allow ifaad ifaadaemon_service:service_manager add; + +#Allow access to tee device +allow ifaad tee_device:chr_file rw_file_perms; + +#Allow access to firmware +r_dir_file(ifaad, firmware_file) diff --git a/sepolicy/ims.te b/sepolicy/ims.te new file mode 100644 index 000000000..d7338bd39 --- /dev/null +++ b/sepolicy/ims.te @@ -0,0 +1 @@ +allow ims diag_prop:property_service set; diff --git a/sepolicy/init.te b/sepolicy/init.te new file mode 100644 index 000000000..ee83502b1 --- /dev/null +++ b/sepolicy/init.te @@ -0,0 +1,2 @@ +allow init vfat:file { read open }; +allow init socket_device:sock_file { create setattr unlink }; diff --git a/sepolicy/ipacm-diag.te b/sepolicy/ipacm-diag.te new file mode 100644 index 000000000..70bc11391 --- /dev/null +++ b/sepolicy/ipacm-diag.te @@ -0,0 +1,4 @@ +allow ipacm-diag init:unix_stream_socket connectto; +allow ipacm-diag property_socket:sock_file write; +allow ipacm-diag system_prop:property_service set; +allow ipacm-diag diag_prop:property_service set; diff --git a/sepolicy/kernel.te b/sepolicy/kernel.te new file mode 100644 index 000000000..70a2ac8cc --- /dev/null +++ b/sepolicy/kernel.te @@ -0,0 +1,3 @@ +allow kernel vfat:file open; +allow kernel self:capability { dac_read_search dac_override }; +allow kernel self:socket create; diff --git a/sepolicy/location.te b/sepolicy/location.te new file mode 100644 index 000000000..756bb2611 --- /dev/null +++ b/sepolicy/location.te @@ -0,0 +1 @@ +allow location permission_service:service_manager find; diff --git a/sepolicy/log.te b/sepolicy/log.te new file mode 100644 index 000000000..2e9f1eb20 --- /dev/null +++ b/sepolicy/log.te @@ -0,0 +1 @@ +allow logd unlabeled:dir search; diff --git a/sepolicy/mac_permissions.xml b/sepolicy/mac_permissions.xml new file mode 100644 index 000000000..a0251440a --- /dev/null +++ b/sepolicy/mac_permissions.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/sepolicy/mm-qcamerad.te b/sepolicy/mm-qcamerad.te new file mode 100644 index 000000000..e8cdb14e4 --- /dev/null +++ b/sepolicy/mm-qcamerad.te @@ -0,0 +1,2 @@ +allow mm-qcamerad camera_prop:property_service set; +allow mm-qcamerad permission_service:service_manager find; diff --git a/sepolicy/netd.te b/sepolicy/netd.te new file mode 100644 index 000000000..5d204e529 --- /dev/null +++ b/sepolicy/netd.te @@ -0,0 +1,3 @@ +allow netd firmware_file:file { read open }; +allow netd firmware_file:dir search; +allow netd vfat:file { read open }; diff --git a/sepolicy/netmgrd.te b/sepolicy/netmgrd.te new file mode 100644 index 000000000..8dab413a1 --- /dev/null +++ b/sepolicy/netmgrd.te @@ -0,0 +1 @@ +allow netmgrd diag_prop:property_service set; diff --git a/sepolicy/per_mgr.te b/sepolicy/per_mgr.te new file mode 100644 index 000000000..d5f2aa5c1 --- /dev/null +++ b/sepolicy/per_mgr.te @@ -0,0 +1 @@ +allow per_mgr vfat:file { read open }; diff --git a/sepolicy/perfd.te b/sepolicy/perfd.te new file mode 100644 index 000000000..458f70f8f --- /dev/null +++ b/sepolicy/perfd.te @@ -0,0 +1 @@ +allow perfd system_server:file write; diff --git a/sepolicy/platform_app.te b/sepolicy/platform_app.te new file mode 100644 index 000000000..84de19fbe --- /dev/null +++ b/sepolicy/platform_app.te @@ -0,0 +1,2 @@ +allow platform_app battery_service:service_manager find; +allow platform_app healthd_service:service_manager find; diff --git a/sepolicy/property.te b/sepolicy/property.te new file mode 100644 index 000000000..85dcb7879 --- /dev/null +++ b/sepolicy/property.te @@ -0,0 +1 @@ +type diag_prop, property_type; diff --git a/sepolicy/property_contexts b/sepolicy/property_contexts new file mode 100644 index 000000000..854b44503 --- /dev/null +++ b/sepolicy/property_contexts @@ -0,0 +1 @@ +persist.sys.diag.max.size u:object_r:diag_prop:s0 diff --git a/sepolicy/qmuxd.te b/sepolicy/qmuxd.te new file mode 100644 index 000000000..e3fe26b20 --- /dev/null +++ b/sepolicy/qmuxd.te @@ -0,0 +1,3 @@ +allow qmuxd diag_prop:property_service set; +allow qmuxd init:unix_stream_socket connectto; +allow qmuxd property_socket:sock_file write; diff --git a/sepolicy/qti.te b/sepolicy/qti.te new file mode 100644 index 000000000..2121a58e1 --- /dev/null +++ b/sepolicy/qti.te @@ -0,0 +1,3 @@ +allow qti diag_prop:property_service set; +allow qti init:unix_stream_socket connectto; +allow qti property_socket:sock_file write; diff --git a/sepolicy/qti_init_shell.te b/sepolicy/qti_init_shell.te new file mode 100644 index 000000000..18f7ecc1d --- /dev/null +++ b/sepolicy/qti_init_shell.te @@ -0,0 +1,7 @@ +allow qti_init_shell kmsg_device:chr_file { write open }; +allow qti_init_shell bluetooth_loader_exec:file r_file_perms; +allow qti_init_shell diag_prop:property_service set; +allow qti_init_shell qmuxd:unix_stream_socket connectto; +allow qti_init_shell qmuxd_socket:dir { write add_name search remove_name }; +allow qti_init_shell qmuxd_socket:sock_file { write create unlink }; +allow qti_init_shell self:socket { write getopt create read ioctl }; diff --git a/sepolicy/rild.te b/sepolicy/rild.te new file mode 100644 index 000000000..c176c4855 --- /dev/null +++ b/sepolicy/rild.te @@ -0,0 +1,3 @@ +allow rild nv_data_file:dir { getattr search write add_name }; +allow rild nv_data_file:file { write open create }; +allow rild diag_prop:property_service set; diff --git a/sepolicy/sdcardd.te b/sepolicy/sdcardd.te new file mode 100644 index 000000000..0f4c71d72 --- /dev/null +++ b/sepolicy/sdcardd.te @@ -0,0 +1 @@ +allow sdcardd userdata_block_device:blk_file r_file_perms; diff --git a/sepolicy/seapp_contexts b/sepolicy/seapp_contexts new file mode 100644 index 000000000..c69f55782 --- /dev/null +++ b/sepolicy/seapp_contexts @@ -0,0 +1,2 @@ +user=_app seinfo=alipay name=com.eg.android.AlipayGphone* domain=alipay_app type=app_data_file +user=_app seinfo=taobao name=com.taobao.taobao* domain=alipay_app type=app_data_file diff --git a/sepolicy/sensors.te b/sepolicy/sensors.te new file mode 100644 index 000000000..fc45cddd9 --- /dev/null +++ b/sepolicy/sensors.te @@ -0,0 +1,3 @@ +allow sensors property_socket:sock_file write; +allow sensors init:unix_stream_socket connectto; +allow sensors diag_prop:property_service set; diff --git a/sepolicy/service.te b/sepolicy/service.te new file mode 100644 index 000000000..86f362730 --- /dev/null +++ b/sepolicy/service.te @@ -0,0 +1 @@ +type ifaadaemon_service, service_manager_type; diff --git a/sepolicy/service_contexts b/sepolicy/service_contexts new file mode 100644 index 000000000..118cacd3b --- /dev/null +++ b/sepolicy/service_contexts @@ -0,0 +1,2 @@ +#IFAA +android.hardware.ifaa.IIfaaDaemon u:object_r:ifaadaemon_service:s0 diff --git a/sepolicy/servicemanager.te b/sepolicy/servicemanager.te new file mode 100644 index 000000000..2df4dc053 --- /dev/null +++ b/sepolicy/servicemanager.te @@ -0,0 +1,3 @@ +allow servicemanager ifaad:dir r_dir_perms; +allow servicemanager ifaad:file r_file_perms; +allow servicemanager ifaad:process getattr; diff --git a/sepolicy/system_app.te b/sepolicy/system_app.te new file mode 100644 index 000000000..d4f37b15c --- /dev/null +++ b/sepolicy/system_app.te @@ -0,0 +1,2 @@ +allow system_app proc_touchpanel:dir search; +allow system_app proc_touchpanel:file { write read getattr open read }; diff --git a/sepolicy/system_server.te b/sepolicy/system_server.te new file mode 100644 index 000000000..503b1df9f --- /dev/null +++ b/sepolicy/system_server.te @@ -0,0 +1,5 @@ +allow system_server persist_file:dir { read write }; +allow system_server proc_touchpanel:dir search; +allow system_server proc_touchpanel:file { write open getattr read }; +allow system_server sensors_persist_file:file { read getattr open }; +allow system_server sensors_persist_file:dir search; diff --git a/sepolicy/thermal-engine.te b/sepolicy/thermal-engine.te new file mode 100644 index 000000000..d57ef05df --- /dev/null +++ b/sepolicy/thermal-engine.te @@ -0,0 +1,3 @@ +allow thermal-engine diag_prop:property_service set; +allow thermal-engine init:unix_stream_socket connectto; +allow thermal-engine property_socket:sock_file write; diff --git a/sepolicy/time_daemon.te b/sepolicy/time_daemon.te new file mode 100644 index 000000000..29af0803f --- /dev/null +++ b/sepolicy/time_daemon.te @@ -0,0 +1 @@ +allow time_daemon property_socket:sock_file write; diff --git a/sepolicy/ueventd.te b/sepolicy/ueventd.te new file mode 100644 index 000000000..ea55aa459 --- /dev/null +++ b/sepolicy/ueventd.te @@ -0,0 +1 @@ +allow ueventd vfat:file { read open }; diff --git a/sepolicy/untrusted_app.te b/sepolicy/untrusted_app.te new file mode 100644 index 000000000..70de2b0fd --- /dev/null +++ b/sepolicy/untrusted_app.te @@ -0,0 +1 @@ +allow untrusted_app ifaadaemon_service:service_manager { find }; diff --git a/sepolicy/vold.te b/sepolicy/vold.te new file mode 100644 index 000000000..9dfc1e9cf --- /dev/null +++ b/sepolicy/vold.te @@ -0,0 +1,2 @@ +allow vold proc_touchpanel:dir { read open }; +allow vold system_block_device:blk_file getattr; diff --git a/sepolicy/zygote.te b/sepolicy/zygote.te new file mode 100644 index 000000000..d9874bc74 --- /dev/null +++ b/sepolicy/zygote.te @@ -0,0 +1,2 @@ +allow zygote input_device:dir { r_file_perms search }; +allow zygote input_device:chr_file rw_file_perms; diff --git a/setup-makefiles.sh b/setup-makefiles.sh new file mode 100755 index 000000000..076171d72 --- /dev/null +++ b/setup-makefiles.sh @@ -0,0 +1,374 @@ +#!/bin/bash + +DEVICE=z2_plus +VENDOR=zuk + +OUTDIR=vendor/$VENDOR/$DEVICE +MAKEFILE=../../../$OUTDIR/$DEVICE-vendor-blobs.mk + +(cat << EOF) > $MAKEFILE +# Copyright (C) 2016 The CyanogenMod Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This file is generated by device/$VENDOR/$DEVICE/setup-makefiles.sh + +PRODUCT_COPY_FILES += \\ +EOF + +LINEEND=" \\" +COUNT=`wc -l proprietary-files.txt | awk {'print $1'}` +DISM=`egrep -c '(^#|^$)' proprietary-files.txt` +COUNT=`expr $COUNT - $DISM` +for FILE in `egrep -v '(^#|^$)' ../$DEVICE/proprietary-files.txt`; do + COUNT=`expr $COUNT - 1` + if [[ ! "$FILE" =~ ^-.* ]]; then + echo " $OUTDIR/proprietary/$FILE:/system/$FILE$LINEEND" >> $MAKEFILE + fi +done + +(cat << EOF) > ../../../$OUTDIR/$DEVICE-vendor.mk +# Copyright (C) 2016 The CyanogenMod Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This file is generated by device/$VENDOR/$DEVICE/setup-makefiles.sh + +# Pick up overlay for features that depend on non-open-source files +PRODUCT_PACKAGES += \\ + CNEService \\ + com.qualcomm.location \\ + datastatusnotification \\ + embms \\ + dpmserviceapp \\ + fastdormancy \\ + ims \\ + imssettings \\ + QtiTelephonyService \\ + QtiTetherService \\ + shutdownlistener \\ + TimeService + +PRODUCT_PACKAGES += \\ + qcnvitems \\ + qcrilhook \\ + qcrilmsgtunnel + +PRODUCT_PACKAGES += \\ + libloc_api_v02 + +PRODUCT_PACKAGES += \\ + libsdm-disp-apis \\ + libtime_genoff \\ + libthermalclient + +PRODUCT_PACKAGES += \\ + colorservice \\ + qdcm_calib_data_samsung_s6e3fa3_1080p_cmd_mode_dsi_panel.xml \\ + qdcm_calib_data_samsung_s6e3fa3_1080p_video_mode_dsi_panel.xml + +\$(call inherit-product, vendor/$VENDOR/$DEVICE/$DEVICE-vendor-blobs.mk) +EOF + +(cat << EOF) > ../../../$OUTDIR/BoardConfigVendor.mk +# Copyright (C) 2016 The CyanogenMod Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This file is generated by device/$VENDOR/$DEVICE/setup-makefiles.sh +EOF + +(cat << EOF) > ../../../$OUTDIR/Android.mk +# Copyright (C) 2016 The CyanogenMod Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This file is generated by device/$VENDOR/$DEVICE/setup-makefiles.sh + +LOCAL_PATH := \$(call my-dir) + +ifeq (\$(TARGET_DEVICE),$DEVICE) + +include \$(CLEAR_VARS) +LOCAL_MODULE := CNEService +LOCAL_MODULE_OWNER := $VENDOR +LOCAL_SRC_FILES := proprietary/priv-app/CNEService/CNEService.apk +LOCAL_MODULE_TAGS := optional +LOCAL_MODULE_SUFFIX := \$(COMMON_ANDROID_PACKAGE_SUFFIX) +LOCAL_MODULE_CLASS := APPS +LOCAL_PRIVILEGED_MODULE := true +LOCAL_CERTIFICATE := platform +include \$(BUILD_PREBUILT) + +include \$(CLEAR_VARS) +LOCAL_MODULE := colorservice +LOCAL_MODULE_OWNER := $VENDOR +LOCAL_SRC_FILES := proprietary/vendor/app/colorservice/colorservice.apk +LOCAL_MODULE_TAGS := optional +LOCAL_MODULE_SUFFIX := \$(COMMON_ANDROID_PACKAGE_SUFFIX) +LOCAL_MODULE_CLASS := APPS +LOCAL_CERTIFICATE := platform +LOCAL_PROPRIETARY_MODULE := true +include \$(BUILD_PREBUILT) + +include \$(CLEAR_VARS) +LOCAL_MODULE := com.qualcomm.location +LOCAL_MODULE_OWNER := $VENDOR +LOCAL_SRC_FILES := proprietary/priv-app/com.qualcomm.location/com.qualcomm.location.apk +LOCAL_MODULE_TAGS := optional +LOCAL_MODULE_SUFFIX := \$(COMMON_ANDROID_PACKAGE_SUFFIX) +LOCAL_MODULE_CLASS := APPS +LOCAL_PRIVILEGED_MODULE := true +LOCAL_CERTIFICATE := platform +include \$(BUILD_PREBUILT) + +include \$(CLEAR_VARS) +LOCAL_MODULE := datastatusnotification +LOCAL_MODULE_OWNER := $VENDOR +LOCAL_SRC_FILES := proprietary/app/datastatusnotification/datastatusnotification.apk +LOCAL_MODULE_TAGS := optional +LOCAL_MODULE_SUFFIX := \$(COMMON_ANDROID_PACKAGE_SUFFIX) +LOCAL_MODULE_CLASS := APPS +LOCAL_CERTIFICATE := platform +include \$(BUILD_PREBUILT) + +include \$(CLEAR_VARS) +LOCAL_MODULE := dpmserviceapp +LOCAL_MODULE_OWNER := $VENDOR +LOCAL_SRC_FILES := proprietary/priv-app/dpmserviceapp/dpmserviceapp.apk +LOCAL_MODULE_TAGS := optional +LOCAL_MODULE_SUFFIX := \$(COMMON_ANDROID_PACKAGE_SUFFIX) +LOCAL_MODULE_CLASS := APPS +LOCAL_PRIVILEGED_MODULE := true +LOCAL_CERTIFICATE := platform +include \$(BUILD_PREBUILT) + +include \$(CLEAR_VARS) +LOCAL_MODULE := embms +LOCAL_MODULE_OWNER := $VENDOR +LOCAL_SRC_FILES := proprietary/app/embms/embms.apk +LOCAL_MODULE_TAGS := optional +LOCAL_MODULE_SUFFIX := \$(COMMON_ANDROID_PACKAGE_SUFFIX) +LOCAL_MODULE_CLASS := APPS +LOCAL_CERTIFICATE := platform +include \$(BUILD_PREBUILT) + +include \$(CLEAR_VARS) +LOCAL_MODULE := fastdormancy +LOCAL_MODULE_OWNER := $VENDOR +LOCAL_SRC_FILES := proprietary/app/fastdormancy/fastdormancy.apk +LOCAL_MODULE_TAGS := optional +LOCAL_MODULE_SUFFIX := \$(COMMON_ANDROID_PACKAGE_SUFFIX) +LOCAL_MODULE_CLASS := APPS +LOCAL_CERTIFICATE := platform +include \$(BUILD_PREBUILT) + +include \$(CLEAR_VARS) +LOCAL_MODULE := ims +LOCAL_MODULE_OWNER := $VENDOR +LOCAL_SRC_FILES := proprietary/vendor/app/ims/ims.apk +LOCAL_MODULE_TAGS := optional +LOCAL_MODULE_SUFFIX := \$(COMMON_ANDROID_PACKAGE_SUFFIX) +LOCAL_MODULE_CLASS := APPS +LOCAL_CERTIFICATE := platform +LOCAL_PROPRIETARY_MODULE := true +include \$(BUILD_PREBUILT) + +include \$(CLEAR_VARS) +LOCAL_MODULE := imssettings +LOCAL_MODULE_OWNER := $VENDOR +LOCAL_SRC_FILES := proprietary/vendor/app/imssettings/imssettings.apk +LOCAL_MODULE_TAGS := optional +LOCAL_MODULE_SUFFIX := \$(COMMON_ANDROID_PACKAGE_SUFFIX) +LOCAL_MODULE_CLASS := APPS +LOCAL_CERTIFICATE := platform +LOCAL_PROPRIETARY_MODULE := true +include \$(BUILD_PREBUILT) + +include \$(CLEAR_VARS) +LOCAL_MODULE := qcrilmsgtunnel +LOCAL_MODULE_OWNER := $VENDOR +LOCAL_SRC_FILES := proprietary/priv-app/qcrilmsgtunnel/qcrilmsgtunnel.apk +LOCAL_MODULE_TAGS := optional +LOCAL_MODULE_SUFFIX := \$(COMMON_ANDROID_PACKAGE_SUFFIX) +LOCAL_MODULE_CLASS := APPS +LOCAL_PRIVILEGED_MODULE := true +LOCAL_CERTIFICATE := platform +include \$(BUILD_PREBUILT) + +include \$(CLEAR_VARS) +LOCAL_MODULE := QtiTelephonyService +LOCAL_MODULE_OWNER := $VENDOR +LOCAL_SRC_FILES := proprietary/app/QtiTelephonyService/QtiTelephonyService.apk +LOCAL_MODULE_TAGS := optional +LOCAL_MODULE_SUFFIX := \$(COMMON_ANDROID_PACKAGE_SUFFIX) +LOCAL_MODULE_CLASS := APPS +LOCAL_CERTIFICATE := platform +include \$(BUILD_PREBUILT) + +include \$(CLEAR_VARS) +LOCAL_MODULE := QtiTetherService +LOCAL_MODULE_OWNER := $VENDOR +LOCAL_SRC_FILES := proprietary/priv-app/QtiTetherService/QtiTetherService.apk +LOCAL_MODULE_TAGS := optional +LOCAL_MODULE_SUFFIX := \$(COMMON_ANDROID_PACKAGE_SUFFIX) +LOCAL_MODULE_CLASS := APPS +LOCAL_PRIVILEGED_MODULE := true +LOCAL_CERTIFICATE := platform +include \$(BUILD_PREBUILT) + +include \$(CLEAR_VARS) +LOCAL_MODULE := shutdownlistener +LOCAL_MODULE_OWNER := $VENDOR +LOCAL_SRC_FILES := proprietary/app/shutdownlistener/shutdownlistener.apk +LOCAL_MODULE_TAGS := optional +LOCAL_MODULE_SUFFIX := \$(COMMON_ANDROID_PACKAGE_SUFFIX) +LOCAL_MODULE_CLASS := APPS +LOCAL_CERTIFICATE := platform +include \$(BUILD_PREBUILT) + +include \$(CLEAR_VARS) +LOCAL_MODULE := TimeService +LOCAL_MODULE_OWNER := $VENDOR +LOCAL_SRC_FILES := proprietary/app/TimeService/TimeService.apk +LOCAL_MODULE_TAGS := optional +LOCAL_MODULE_SUFFIX := \$(COMMON_ANDROID_PACKAGE_SUFFIX) +LOCAL_MODULE_CLASS := APPS +LOCAL_CERTIFICATE := platform +include \$(BUILD_PREBUILT) + +include \$(CLEAR_VARS) +LOCAL_MODULE := qcnvitems +LOCAL_MODULE_OWNER := $VENDOR +LOCAL_SRC_FILES := proprietary/framework/qcnvitems.jar +LOCAL_MODULE_TAGS := optional +LOCAL_MODULE_SUFFIX := \$(COMMON_JAVA_PACKAGE_SUFFIX) +LOCAL_MODULE_CLASS := JAVA_LIBRARIES +LOCAL_CERTIFICATE := PRESIGNED +include \$(BUILD_PREBUILT) + +include \$(CLEAR_VARS) +LOCAL_MODULE := qcrilhook +LOCAL_MODULE_OWNER := $VENDOR +LOCAL_SRC_FILES := proprietary/framework/qcrilhook.jar +LOCAL_MODULE_TAGS := optional +LOCAL_MODULE_SUFFIX := \$(COMMON_JAVA_PACKAGE_SUFFIX) +LOCAL_MODULE_CLASS := JAVA_LIBRARIES +LOCAL_CERTIFICATE := PRESIGNED +include \$(BUILD_PREBUILT) + +include \$(CLEAR_VARS) +LOCAL_MODULE := libloc_api_v02 +LOCAL_MODULE_OWNER := $VENDOR +LOCAL_SRC_FILES_64 := proprietary/lib64/libloc_api_v02.so +LOCAL_SRC_FILES_32 := proprietary/lib/libloc_api_v02.so +LOCAL_MODULE_TAGS := optional +LOCAL_MODULE_SUFFIX := .so +LOCAL_MODULE_CLASS := SHARED_LIBRARIES +LOCAL_MODULE_PATH_64 := \$(TARGET_OUT_SHARED_LIBRARIES) +LOCAL_MODULE_PATH_32 := \$(2ND_TARGET_OUT_SHARED_LIBRARIES) +LOCAL_MULTILIB := both +include \$(BUILD_PREBUILT) + +include \$(CLEAR_VARS) +LOCAL_MODULE := libsdm-disp-apis +LOCAL_MODULE_OWNER := $VENDOR +LOCAL_SRC_FILES_64 := proprietary/vendor/lib64/libsdm-disp-apis.so +LOCAL_SRC_FILES_32 := proprietary/vendor/lib/libsdm-disp-apis.so +LOCAL_MODULE_TAGS := optional +LOCAL_MODULE_SUFFIX := .so +LOCAL_MODULE_CLASS := SHARED_LIBRARIES +LOCAL_MODULE_PATH_64 := \$(TARGET_OUT_VENDOR_SHARED_LIBRARIES) +LOCAL_MODULE_PATH_32 := \$(2ND_TARGET_OUT_VENDOR_SHARED_LIBRARIES) +LOCAL_MULTILIB := both +LOCAL_PROPRIETARY_MODULE := true +include \$(BUILD_PREBUILT) + +include \$(CLEAR_VARS) +LOCAL_MODULE := libtime_genoff +LOCAL_MODULE_OWNER := $VENDOR +LOCAL_SRC_FILES_64 := proprietary/vendor/lib64/libtime_genoff.so +LOCAL_SRC_FILES_32 := proprietary/vendor/lib/libtime_genoff.so +LOCAL_MODULE_TAGS := optional +LOCAL_MODULE_SUFFIX := .so +LOCAL_MODULE_CLASS := SHARED_LIBRARIES +LOCAL_MODULE_PATH_64 := \$(TARGET_OUT_VENDOR_SHARED_LIBRARIES) +LOCAL_MODULE_PATH_32 := \$(2ND_TARGET_OUT_VENDOR_SHARED_LIBRARIES) +LOCAL_MULTILIB := both +LOCAL_PROPRIETARY_MODULE := true +include \$(BUILD_PREBUILT) + +include \$(CLEAR_VARS) +LOCAL_MODULE := libthermalclient +LOCAL_MODULE_OWNER := $VENDOR +LOCAL_SRC_FILES_64 := proprietary/vendor/lib64/libthermalclient.so +LOCAL_SRC_FILES_32 := proprietary/vendor/lib/libthermalclient.so +LOCAL_MODULE_TAGS := optional +LOCAL_MODULE_SUFFIX := .so +LOCAL_MODULE_CLASS := SHARED_LIBRARIES +LOCAL_MODULE_PATH_64 := \$(TARGET_OUT_VENDOR_SHARED_LIBRARIES) +LOCAL_MODULE_PATH_32 := \$(2ND_TARGET_OUT_VENDOR_SHARED_LIBRARIES) +LOCAL_MULTILIB := both +LOCAL_PROPRIETARY_MODULE := true +include \$(BUILD_PREBUILT) + +include \$(CLEAR_VARS) +LOCAL_MODULE := qdcm_calib_data_samsung_s6e3fa3_1080p_cmd_mode_dsi_panel.xml +LOCAL_MODULE_TAGS := optional +LOCAL_MODULE_CLASS := ETC +LOCAL_SRC_FILES := proprietary/etc/qdcm_calib_data_samsung_s6e3fa3_1080p_cmd_mode_dsi_panel.xml +include \$(BUILD_PREBUILT) + +include \$(CLEAR_VARS) +LOCAL_MODULE := qdcm_calib_data_samsung_s6e3fa3_1080p_video_mode_dsi_panel.xml +LOCAL_MODULE_TAGS := optional +LOCAL_MODULE_CLASS := ETC +LOCAL_SRC_FILES := proprietary/etc/qdcm_calib_data_samsung_s6e3fa3_1080p_video_mode_dsi_panel.xml +include \$(BUILD_PREBUILT) + +\$(shell mkdir -p \$(PRODUCT_OUT)/system/vendor/lib/egl && pushd \$(PRODUCT_OUT)/system/vendor/lib > /dev/null && ln -s egl/libEGL_adreno.so libEGL_adreno.so && popd > /dev/null) +\$(shell mkdir -p \$(PRODUCT_OUT)/system/vendor/lib64/egl && pushd \$(PRODUCT_OUT)/system/vendor/lib64 > /dev/null && ln -s egl/libEGL_adreno.so libEGL_adreno.so && popd > /dev/null) + +endif + +EOF diff --git a/system.prop b/system.prop new file mode 100644 index 000000000..90ba366b8 --- /dev/null +++ b/system.prop @@ -0,0 +1,294 @@ +# +# system.prop for msm8996 +# + +#rild.libpath=/system/lib/libreference-ril.so +rild.libpath=/vendor/lib64/libril-qc-qmi-1.so +#rild.libargs=-d /dev/smd0 +persist.rild.nitz_plmn= +persist.rild.nitz_long_ons_0= +persist.rild.nitz_long_ons_1= +persist.rild.nitz_long_ons_2= +persist.rild.nitz_long_ons_3= +persist.rild.nitz_short_ons_0= +persist.rild.nitz_short_ons_1= +persist.rild.nitz_short_ons_2= +persist.rild.nitz_short_ons_3= +ril.subscription.types=NV,RUIM +DEVICE_PROVISIONED=1 +persist.radio.multisim.config=dsds +persist.volte_enalbed_by_hw=1 +persist.radio.data_ltd_sys_ind=1 +ro.telephony.default_network=22,22 + +#Flip panel +persist.panel.inversemounted=1 +persist.panel.mountflip=3 + +debug.sf.hw=1 +debug.egl.hw=1 +debug.gralloc.enable_fb_ubwc=1 +dalvik.vm.heapsize=36m +dev.pm.dyn_samplingrate=1 +persist.demo.hdmirotationlock=false + +#ro.hdmi.enable=true +persist.speaker.prot.enable=true +qcom.hw.aac.encoder=true +# +# system props for the cne module +# +persist.cne.feature=1 + +#system prop for enabling/disabling Android XLAT +persist.net.doxlat=true + +#system props for the MM modules +media.stagefright.enable-player=true +media.stagefright.enable-http=true +media.stagefright.enable-aac=true +media.stagefright.enable-qcp=true +media.stagefright.enable-fma2dp=true +media.stagefright.enable-scan=true +mmp.enable.3g2=true +media.aac_51_output_enabled=true +mm.enable.sec.smoothstreaming=true +av.debug.disable.pers.cache=true +#185971 is decimal sum of supported parsers in AAL +#37491 is decimal sum of supported codecs in AAL +#codecs:(PARSER_)AAC AC3 AMR_NB AMR_WB ASF AVI DTS FLV 3GP 3G2 MKV MP2PS MP2TS MP3 OGG QCP WAV FLAC AIFF APE +mm.enable.qcom_parser=1048575 +persist.mm.enable.prefetch=true + +# Additional i/p buffer in case of encoder DCVS +vidc.enc.dcvs.extra-buff-count=2 + +# Set default power mode to low power for encoder +vidc.debug.perf.mode=2 + +# +# system props for the data modules +# +ro.use_data_netmgrd=true +persist.data.netmgrd.qos.enable=true +persist.data.mode=concurrent + +#system props for time-services +persist.timed.enable=true + +# +# system prop for opengles version +# +# 196608 is decimal for 0x30000 to report version 3.0 +# 196609 is decimal for 0x30001 to report version 3.1 +ro.opengles.version=196609 + +# system property for maximum number of HFP client connections +bt.max.hfpclient.connections=1 + +# System property for cabl +ro.qualcomm.cabl=2 +# System property for AD +ro.qcom.ad=1 +ro.qcom.ad.sensortype=2 +ro.qcom.ad.calib.data=/system/etc/calib.cfg + +# +# System props for telephony +# System prop to turn on CdmaLTEPhone always +telephony.lteOnCdmaDevice=1 + +#Simulate sdcard on /data/media +# +persist.fuse_sdcard=true + +#system prop for Bluetooth SOC type +qcom.bluetooth.soc=rome + +#system prop for wipower support +ro.bluetooth.wipower=true + +#Set this true as ROME which is programmed +#as embedded wipower mode by deafult +ro.bluetooth.emb_wp_mode=true + +# +#snapdragon value add features +# +ro.qc.sdk.audio.ssr=false + +##fluencetype can be "fluence" or "fluencepro" or "none" +ro.qc.sdk.audio.fluencetype=fluence +persist.audio.fluence.voicecall=true +persist.audio.fluence.voicerec=false +persist.audio.fluence.speaker=true + +#system prop for RmNet Data +persist.rmnet.data.enable=true +persist.data.wda.enable=true +persist.data.df.dl_mode=5 +persist.data.df.ul_mode=5 +persist.data.df.agg.dl_pkt=10 +persist.data.df.agg.dl_size=4096 +persist.data.df.mux_count=8 +persist.data.df.iwlan_mux=9 +persist.data.df.dev_name=rmnet_usb0 + +#property to enable user to access Google WFD settings +persist.debug.wfd.enable=1 +##property to choose between virtual/external wfd display +persist.sys.wfd.virtual=0 + +#property to enable sde downscale feature for external display +#sdm.debug.downscale_external=1 + +#property to specify the number of frames to skip before setting hint +sdm.perf_hint_window=50 + +#disable tunnel encoding +tunnel.audio.encode=false + +#Buffer size in kbytes for compress offload playback +audio.offload.buffer.size.kb=32 + +#Enable offload audio video playback by default +audio.offload.video=true + +#Enable 16 bit PCM offload by default +audio.offload.pcm.16bit.enable=true + +#Enable 24 bit PCM offload by default +audio.offload.pcm.24bit.enable=true + +#Enable audio track offload by default +audio.offload.track.enable=true + +#Enable music through deep buffer +audio.deep_buffer.media=true + +#enable voice path for PCM VoIP by default +use.voice.path.for.pcm.voip=true + +#Enable multi channel aac through offload +audio.offload.multiaac.enable=true + +#enable dsp gapless mode by default +audio.offload.gapless.enabled=true + +#enable pbe effects +audio.safx.pbe.enabled=true + +#parser input buffer size(256kb) in byte stream mode +audio.parser.ip.buffer.size=262144 + +#property to enable WFD WL solution +ro.vendor.wl_library=libqti-wl.so + +#property for vendor specific library +ro.vendor.gt_library=libqti-gt.so +ro.vendor.at_library=libqti-at.so +sys.games.gt.prof=1 + +#hwui properties +ro.hwui.texture_cache_size=72 +ro.hwui.layer_cache_size=48 +ro.hwui.r_buffer_cache_size=8 +ro.hwui.path_cache_size=32 +ro.hwui.gradient_cache_size=1 +ro.hwui.drop_shadow_cache_size=6 +ro.hwui.texture_cache_flushrate=0.4 +ro.hwui.text_small_cache_width=1024 +ro.hwui.text_small_cache_height=1024 +ro.hwui.text_large_cache_width=2048 +ro.hwui.text_large_cache_height=1024 + +#Disable property for Dolby ds2 +audio.dolby.ds2.enabled=false + +#Disable property for hard bypass +audio.dolby.ds2.hardbypass=false + +audio.offload.passthrough=false +audio.offload.multiple.enabled=false + +# enable navigation bar +qemu.hw.mainkeys=1 + +#property to enable VDS WFD solution +persist.hwc.enable_vds=1 + +#Enable stm events +ro.dbg.coresight.config=stm_events +#property to enable fingerprint +persist.qfp=false + +#default pd_enable value +persist.sys.pd_enable=0 +#Disable rotator split feature +sdm.debug.disable_rotator_split=1 + +#Increase cached app limit +ro.sys.fw.bg_apps_limit=60 + +#Camera fullscreen doesn't show navigation bar +Camera.no_navigation_bar=true + +#[Begin][public][PLAT-127][modem][mbn][wangxg7][20160121] Enable mbn & VoLTE & VT & dsds property +persist.radio.sw_mbn_update=1 +persist.radio.sw_mbn_volte=1 +persist.radio.sw_mbn_openmkt=1 +persist.radio.hw_mbn_update=1 +persist.dbg.volte_avail_ovr=1 +persist.dbg.vt_avail_ovr=1 +persist.radio.custom_ecc=1 +persist.radio.process_sups_ind=1 +persist.radio.multisim.config=dsds +#[End][public][PLAT-127][modem][mbn][wangxg7][20160121] Enable mbn & VoLTE & VT & dsds property + +#enable flex mapping +persist.radio.primarycard=true +persist.radio.flexmap_type=dds + +#liujb2 add +persist.dpm.feature=3 +persist.radio.add_power_save=1 + +persist.radio.rat_on=combine + +#add for mms apn restore delay +android.telephony.apn-restore=240000 + +#add for roaming vendor property +ro.roaming.vendor=redtea + +#add for leds +persist.sys.leds.enabled=false + +ro.vendor.extension_library=libqti-perfd-client.so +persist.radio.apm_sim_not_pwdn=1 +persist.radio.sib16_support=1 +persist.radio.custom_ecc=1 +af.fast_track_multiplier=1 +audio_hal.period_size=192 + +ro.sf.lcd_density=480 + +persist.lcd.saturation=0 +persist.lcd.temperature=1 +persist.lcd.careeyes=0 +persist.lcd.cabccustom=1 +persist.lcd.cabcinternal=0 +persist.lcd.sunlight=0 +persist.lcd.autosunlight=0 +persist.lcd.imageenhance=1 +persist.lcd.ppmode=0 +persist.radio.data_ltd_sys_ind=1 +vidc.debug.level=0 + +persist.gps.qc_nlp_in_use=1 +persist.loc.nlp_name=com.qualcomm.location +ro.gps.agps_provider=1 + +#add for CMCC FT UE did not camp on IMS after TDS moving to LTE. +persist.radio.apn_ff_delay=20000 + diff --git a/tftp.mk b/tftp.mk new file mode 100644 index 000000000..568f0fa2b --- /dev/null +++ b/tftp.mk @@ -0,0 +1,66 @@ +######################################################################### +# Create Folder Structure +######################################################################### + +$(shell rm -rf $(TARGET_OUT)/rfs/) + +#To be enabled when prepopulation support is needed for the read_write folder +# $(shell rm -rf $(TARGET_OUT_DATA)/rfs/) +# $(shell mkdir -p $(TARGET_OUT_DATA)/rfs/msm/mpss/) +# $(shell mkdir -p $(TARGET_OUT_DATA)/rfs/msm/adsp/) +# $(shell mkdir -p $(TARGET_OUT_DATA)/rfs/mdm/mpss/) +# $(shell mkdir -p $(TARGET_OUT_DATA)/rfs/mdm/adsp/) + +######################################################################### +# MSM Folders +######################################################################### +$(shell mkdir -p $(TARGET_OUT)/rfs/msm/mpss/readonly) +$(shell mkdir -p $(TARGET_OUT)/rfs/msm/adsp/readonly) + +$(shell ln -s /data/tombstones/modem $(TARGET_OUT)/rfs/msm/mpss/ramdumps) +$(shell ln -s /persist/rfs/msm/mpss $(TARGET_OUT)/rfs/msm/mpss/readwrite) +$(shell ln -s /persist/rfs/shared $(TARGET_OUT)/rfs/msm/mpss/shared) +$(shell ln -s /persist/hlos_rfs/shared $(TARGET_OUT)/rfs/msm/mpss/hlos) +$(shell ln -s /firmware $(TARGET_OUT)/rfs/msm/mpss/readonly/firmware) + +$(shell ln -s /data/tombstones/lpass $(TARGET_OUT)/rfs/msm/adsp/ramdumps) +$(shell ln -s /persist/rfs/msm/adsp $(TARGET_OUT)/rfs/msm/adsp/readwrite) +$(shell ln -s /persist/rfs/shared $(TARGET_OUT)/rfs/msm/adsp/shared) +$(shell ln -s /persist/hlos_rfs/shared $(TARGET_OUT)/rfs/msm/adsp/hlos) +$(shell ln -s /firmware $(TARGET_OUT)/rfs/msm/adsp/readonly/firmware) + +######################################################################### +# MDM Folders +######################################################################### +$(shell mkdir -p $(TARGET_OUT)/rfs/mdm/mpss/readonly) +$(shell mkdir -p $(TARGET_OUT)/rfs/mdm/adsp/readonly) +$(shell mkdir -p $(TARGET_OUT)/rfs/mdm/sparrow/readonly) + +$(shell ln -s /data/tombstones/modem $(TARGET_OUT)/rfs/mdm/mpss/ramdumps) +$(shell ln -s /persist/rfs/mdm/mpss $(TARGET_OUT)/rfs/mdm/mpss/readwrite) +$(shell ln -s /persist/rfs/shared $(TARGET_OUT)/rfs/mdm/mpss/shared) +$(shell ln -s /persist/hlos_rfs/shared $(TARGET_OUT)/rfs/mdm/mpss/hlos) +$(shell ln -s /firmware $(TARGET_OUT)/rfs/mdm/mpss/readonly/firmware) + +$(shell ln -s /data/tombstones/lpass $(TARGET_OUT)/rfs/mdm/adsp/ramdumps) +$(shell ln -s /persist/rfs/mdm/adsp $(TARGET_OUT)/rfs/mdm/adsp/readwrite) +$(shell ln -s /persist/rfs/shared $(TARGET_OUT)/rfs/mdm/adsp/shared) +$(shell ln -s /persist/hlos_rfs/shared $(TARGET_OUT)/rfs/mdm/adsp/hlos) +$(shell ln -s /firmware $(TARGET_OUT)/rfs/mdm/adsp/readonly/firmware) + +$(shell ln -s /data/tombstones/sparrow $(TARGET_OUT)/rfs/mdm/sparrow/ramdumps) +$(shell ln -s /persist/rfs/mdm/sparrow $(TARGET_OUT)/rfs/mdm/sparrow/readwrite) +$(shell ln -s /persist/rfs/shared $(TARGET_OUT)/rfs/mdm/sparrow/shared) +$(shell ln -s /persist/hlos_rfs/shared $(TARGET_OUT)/rfs/mdm/sparrow/hlos) +$(shell ln -s /firmware $(TARGET_OUT)/rfs/mdm/sparrow/readonly/firmware) + +######################################################################### +# APQ Folders +######################################################################### +$(shell mkdir -p $(TARGET_OUT)/rfs/apq/gnss/readonly) + +$(shell ln -s /data/tombstones/modem $(TARGET_OUT)/rfs/apq/gnss/ramdumps) +$(shell ln -s /persist/rfs/apq/gnss $(TARGET_OUT)/rfs/apq/gnss/readwrite) +$(shell ln -s /persist/rfs/shared $(TARGET_OUT)/rfs/apq/gnss/shared) +$(shell ln -s /persist/hlos_rfs/shared $(TARGET_OUT)/rfs/apq/gnss/hlos) +$(shell ln -s /firmware $(TARGET_OUT)/rfs/apq/gnss/readonly/firmware) diff --git a/vendor/copyfiles.mk b/vendor/copyfiles.mk new file mode 100755 index 000000000..bb3104836 --- /dev/null +++ b/vendor/copyfiles.mk @@ -0,0 +1,30 @@ +# Copyright (C) 2016 The Cyanogen Mod Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# +# This file sets variables that control the way modules are built +# thorughout the system. It should not be used to conditionally +# disable makefiles (the proper mechanism to control what gets +# included in a build is to use PRODUCT_PACKAGES in a product +# definition file). +# + +copy_files := $(subst $(LOCAL_PATH)/,, \ + $(filter-out %.mk,\ + $(patsubst ./%,%, \ + $(shell find $(LOCAL_PATH) -type f -name "*" -and -not -name ".*") \ + ))) + +PRODUCT_COPY_FILES += $(foreach file,$(copy_files),\ + $(LOCAL_PATH)/$(file):$(file)) diff --git a/vendorsetup.sh b/vendorsetup.sh new file mode 100644 index 000000000..aaf748843 --- /dev/null +++ b/vendorsetup.sh @@ -0,0 +1 @@ +add_lunch_combo cm_z2_plus-userdebug diff --git a/wifi/WCNSS_cfg.dat b/wifi/WCNSS_cfg.dat new file mode 100644 index 000000000..08aaf2bfd Binary files /dev/null and b/wifi/WCNSS_cfg.dat differ diff --git a/wifi/WCNSS_qcom_cfg.ini b/wifi/WCNSS_qcom_cfg.ini new file mode 100644 index 000000000..083683b84 --- /dev/null +++ b/wifi/WCNSS_qcom_cfg.ini @@ -0,0 +1,635 @@ +# This file allows user to override the factory + +# defaults for the WLAN Driver + + +# Enable IMPS or not +gEnableImps=1 + +# Enable/Disable Idle Scan + +gEnableIdleScan=0 + + +# Increase sleep duration (seconds) during IMPS +# 0 implies no periodic wake up from IMPS. Periodic wakeup is +# unnecessary if Idle Scan is disabled. +gImpsModSleepTime=0 + + +# Enable BMPS or not +gEnableBmps=1 + +# Enable suspend or not + +# 1: Enable standby, 2: Enable Deep sleep, 3: Enable Mcast/Bcast Filter + +gEnableSuspend=3 + + +# Phy Mode (auto, b, g, n, etc) +# Valid values are 0-9, with 0 = Auto, 4 = 11n, 9 = 11ac +# 1 = 11abg, 2 = 11b, 3 = 11g, 5 = 11g only, 6 = 11n only +# 7 = 11b only 8 = 11ac only. +gDot11Mode=0 + + +# CSR Roaming Enable(1) Disable(0) + +gRoamingTime=0 + + +# Assigned MAC Addresses - This will be used until NV items are in place + +# Each byte of MAC address is represented in Hex format as XX + +Intf0MacAddress=000AF58989FF +Intf1MacAddress=000AF58989FE +Intf2MacAddress=000AF58989FD + +Intf3MacAddress=000AF58989FC + + +# UAPSD service interval for VO,VI, BE, BK traffic + +InfraUapsdVoSrvIntv=0 + +InfraUapsdViSrvIntv=0 + +InfraUapsdBeSrvIntv=0 + +InfraUapsdBkSrvIntv=0 + +# Flag to allow STA send AddTspec even when ACM is Off +gAddTSWhenACMIsOff=1 + +# Make 1x1 the default antenna configuration + +gNumRxAnt=1 + + +# Beacon filtering frequency (unit in beacon intervals) + +gNthBeaconFilter=50 + + +# Enable WAPI or not + +WAPIIsEnabled=1 + + +# Flags to filter Mcast abd Bcast RX packets. + +# Value 0: No filtering, 1: Filter all Multicast. + +# 2: Filter all Broadcast. 3: Filter all Mcast abd Bcast + +McastBcastFilter=3 + + +#Flag to enable HostARPOffload feature or not + +hostArpOffload=1 + +#Flag to enable TCPChkSumOffld feature or not + +gEnableTCPChkSumOffld=1 + +#Flag to enable HostNSOffload feature or not + +hostNSOffload=1 + +#Flag to enable IPChkSumOffld feature or not + +gEnableIPChecksumOffload=1 + +#SoftAP Related Parameters + +# AP MAc addr + +gAPMacAddr=000AF589dcab + + +# 802.11n Protection flag + +gEnableApProt=1 + + +#Enable OBSS protection + +gEnableApOBSSProt=1 + + +#Enable/Disable UAPSD for SoftAP + +gEnableApUapsd=1 + + +# Fixed Rate + +gFixedRate=0 + + +# Maximum Tx power + +# gTxPowerCap=30 + + +# Fragmentation Threshold + +# gFragmentationThreshold=2346 + + +# RTS threshold + +RTSThreshold=1048576 + + +# Intra-BSS forward + +gDisableIntraBssFwd=0 + + +# WMM Enable/Disable + +WmmIsEnabled=0 + + +# 802.11d support + +g11dSupportEnabled=1 + +# 802.11h support + +g11hSupportEnabled=1 + +# DFS Master Capability +gEnableDFSMasterCap=1 + +# ESE Support and fast transition +EseEnabled=0 +ImplicitQosIsEnabled=0 +gNeighborScanTimerPeriod=200 + +gNeighborLookupThreshold=76 +gNeighborReassocThreshold=81 + +gNeighborScanChannelMinTime=20 +gNeighborScanChannelMaxTime=30 +gMaxNeighborReqTries=3 + +# Legacy (non-ESE, non-802.11r) Fast Roaming Support +# To enable, set FastRoamEnabled=1 +# To disable, set FastRoamEnabled=0 +FastRoamEnabled=1 + +#Check if the AP to which we are roaming is better than current AP in terms of RSSI. +#Checking is disabled if set to Zero.Otherwise it will use this value as to how better +#the RSSI of the new/roamable AP should be for roaming +RoamRssiDiff=5 + +# If the RSSI of any available candidate is better than currently associated +# AP by at least gImmediateRoamRssiDiff, then being to roam immediately (without +# registering for reassoc threshold). +# NOTE: Value of 0 means that we would register for reassoc threshold. +gImmediateRoamRssiDiff=10 + +# To enable, set gRoamIntraBand=1 (Roaming within band) +# To disable, set gRoamIntraBand=0 (Roaming across band) +gRoamIntraBand=0 + +# SAP Country code + +# Default Country Code is 2 bytes, 3rd byte is optional indoor or out door. + +# Example + +# US Indoor, USI + +# Korea Outdoor, KRO + +# Japan without optional byte, JP + +# France without optional byte, FR + +#gAPCntryCode=USI + + +#Short Guard Interval Enable/disable + +gShortGI20Mhz=1 + +gShortGI40Mhz=1 + + +#Auto Shutdown Value in seconds. A value of 0 means Auto shutoff is disabled + +gAPAutoShutOff=0 + + +# SAP auto channel selection configuration + +# 0 = disable auto channel selection + +# 1 = enable auto channel selection, channel provided by supplicant will be ignored + +gApAutoChannelSelection=1 +gAPChannelSelectStartChannel=8 +gAPChannelSelectEndChannel=8 +gAPChannelSelectOperatingBand=0 + +#Auto Shutdown wlan : Value in Seconds. 0 means disabled. Max 1 day = 86400 sec +gWlanAutoShutdown = 0 + + +# Listen Energy Detect Mode Configuration + +# Valid values 0-128 + +# 128 means disable Energy Detect feature + +# 0-9 are threshold code and 7 is recommended value from system if feature is to be enabled. + +# 10-128 are reserved. + +# The EDET threshold mapping is as follows in 3dB step: + +# 0 = -60 dBm + +# 1 = -63 dBm + +# 2 = -66 dBm + +# ... + +# 7 = -81 dBm + +# 8 = -84 dBm + +# 9 = -87 dBm + +# Note: Any of these settings are valid. Setting 0 would yield the highest power saving (in a noisy environment) at the cost of more range. The range impact is approximately #calculated as: + +# + +# Range Loss (dB) = EDET threshold level (dBm) + 97 dBm. + +# + +gEnablePhyAgcListenMode=128 + + +#Preferred band (both or 2.4 only or 5 only) + +BandCapability=0 + + +#Beacon Early Termination (1 = enable the BET feature, 0 = disable) + +enableBeaconEarlyTermination=0 + +beaconEarlyTerminationWakeInterval=11 + + +#Channel Bonding +gChannelBondingMode5GHz=1 +gChannelBondingMode24GHz=1 + + +#Enable Keep alive with non-zero period value + +gStaKeepAlivePeriod = 30 + +#If set will start with active scan after driver load, otherwise will start with + +#passive scan to find out the domain + +gEnableBypass11d=1 + + +#If set to 0, will not scan DFS channels + +gEnableDFSChnlScan=1 + + +gVhtChannelWidth=2 + + +gGoKeepAlivePeriod = 30 +gApKeepAlivePeriod = 10 +# Enable Automatic Tx Power control + +gEnableAutomaticTxPowerControl=1 + +# 0 for OLPC 1 for CLPC and SCPC +gEnableCloseLoop=1 + +#Data Inactivity Timeout when in powersave (in ms) +gDataInactivityTimeout=200 + +# VHT Tx/Rx MCS values +# Valid values are 0,1,2. If commented out, the default value is 0. +# 0=MCS0-7, 1=MCS0-8, 2=MCS0-9 +gVhtRxMCS=2 +gVhtTxMCS=2 + +gEnableLpwrImgTransition=1 + +# VHT Tx/Rx MCS values for 2x2 +# Valid values are 0,1,2. If commented out, the default value is 0. +# 0=MCS0-7, 1=MCS0-8, 2=MCS0-9 +#gVhtRxMCS2x2=2 +#gVhtTxMCS2x2=2 + +# Enable Tx beamforming +gTxBFEnable=1 + +# Enable Tx beamforming in VHT20MHz +# Valid values are 0,1. If commented out, the default value is 0. +# 0=disable, 1=enable +gEnableTxBFin20MHz=1 + +gTxChainMask1ss=0 + +# Scan Timing Parameters +# gPassiveMaxChannelTime=110 +# gPassiveMinChannelTime=60 +gActiveMaxChannelTime=40 +gActiveMinChannelTime=20 + +gEnableDynamicDTIM=3 + +#If set to 0, MCC is not allowed. +gEnableMCCMode=1 + +# MCC to SCC Switch mode: 0-Disable 1-Enable 2-Force SCC if same band +gWlanMccToSccSwitchMode = 0 + +# 1=enable STBC; 0=disable STBC +gEnableRXSTBC=1 + +# 1=enable tx STBC; 0=disable +gEnableTXSTBC=1 + +# 1=enable rx LDPC; 0=disable +gEnableRXLDPC=1 + +# Enable Active mode offload +gEnableActiveModeOffload=1 + +#Enable Scan Results Aging based on timer +#Timer value is in seconds +#If Set to 0 it will not enable the feature +gScanAgingTime=0 + +#Enable Scan Results Aging based on number of scans +gScanResultAgeCount=1 + +#Enable Power saving mechanism Based on Android Framework +#If set to 0 Driver internally control the Power saving mechanism +#If set to 1 Android Framwrok control the Power saving mechanism +isAndroidPsEn=0 + +#Enable thermal mitigation +gThermalMitigationEnable=0 + +gEnableFastRoamInConcurrency=1 + +#List of Country codes for which 11ac needs to be disabled +#Each country code must be delimited by comma(,) +gListOfNon11acCountryCode=RU,UA,ZA + +#Maxium Channel time in msec +gMaxMediumTime = 6000 + +# 802.11K support +gRrmEnable=1 +gRrmOperChanMax=8 +gRrmNonOperChanMax=8 +gRrmRandIntvl=100 + +#Scan offload +gEnableDirectedScanOffload=1 + +#FlexConnect Power Factor +#Default is set to 0 (disable) +gFlexConnectPowerFactor=0 + +#Disable split scan, the FW will take care of it +gNumChanCombinedConc=60 + +#Enable Power Save offload +gEnablePowerSaveOffload=1 + +#Enable firmware uart print +gEnablefwprint=0 + +#Enable firmware log +gEnablefwlog=1 +# Additional firmware log levels +gFwDebugLogLevel=1 +gFwDebugModuleLoglevel=1,0,2,0,4,0,5,0,6,0,7,4,8,0,9,0,11,0,13,0,17,0,18,0,19,0,27,0,29,0,31,0,35,0,36,0,38,0 + +#IPA config +gIPADescSize=800 +gIPAPreFilterEnable=1 +gIPARMEnable=1 +gIPAIPv6Enable=1 + +#P2P Listen offload +gEnableP2pListenOffload=1 + +# Maximum Receive AMPDU size (VHT only. Valid values: 0->8k 1->16k 2->32k 3->64k 4->128k) +gVhtAmpduLenExponent=7 + +# Maximum MPDU length (VHT only. Valid values: 0->3895 octets, 1->7991 octets, 2->11454 octets) +gVhtMpduLen=2 + +# Maximum number of wow filters required +#gMaxWoWFilters=22 + +# WOW Enable/Disable. +# 0 - Disable both magic pattern match and pattern byte match. +# 1 - Enable magic pattern match on all interfaces. +# 2 - Enable pattern byte match on all interfaces. +# 3 - Enable both magic patter and pattern byte match on all interfaces. +# Default value of gEnableWoW is 3. +# gEnableWoW=0 + +# Enable or Disable MCC Adaptive Scheduler at the FW +# 1=Enable (default), 0=Disable +gEnableMCCAdaptiveScheduler=1 + +#Enable or Disable p2p device address administered +isP2pDeviceAddrAdministrated=1 + +# RX packet handling options +# 0: no rx thread, no RPS, for MDM +# 1: RX thread +# 2: RPS +rxhandle=2 + +#RPS CPU map, core 2 and 3 +rpsRxQueueCpuMapList=c + +# Set Thermal Power limit +TxPower2g=10 +TxPower5g=10 + +# Remove Overlap channel restriction +gEnableOverLapCh=0 + +#Enable VHT on 2.4Ghz +gEnableVhtFor24GHzBand=1 + +#Enable or Disable 5G early beacon termination +gEnable5gEBT=1 + +#Maximum number of offload peers supported +# gMaxOffloadPeers=2 + +# controlling the following offload patterns +# through ini parameter. Default value is 1 +# to disable set it to zero. ssdp = 0 +# Setup multicast pattern for mDNS 224.0.0.251, +# SSDP 239.255.255.250 and LLMNR 224.0.0.252 + + +ssdp = 0 + +# Bus bandwidth threshold values in terms of number of packets +gBusBandwidthHighThreshold=2000 +gBusBandwidthMediumThreshold=500 +gBusBandwidthLowThreshold=150 + +# IPA bandwidth voting +gIPAHighBandwidthMbps=800 +gIPAMediumBandwidthMbps=400 +gIPALowBandwidthMbps=200 + +# Bus bandwidth compute timeout value in ms +gBusBandwidthComputeInterval=100 + +# Regulatory Setting; 0=STRICT; 1=CUSTOM +gRegulatoryChangeCountry=1 + +# Maximum number of concurrent connections +gMaxConcurrentActiveSessions=2 + +# Radar PRI multiplier +gDFSradarMappingPriMultiplier=4 + +gPNOScanSupport=1 + +# Enable/Disable RX full reorder offload +gReorderOffloadSupported=1 + +# userspace country code setting shld take priority +gCountryCodePriority=1 + +# Enable/Disable LPASS support +# 0 to disable, 1 to enable +gEnableLpassSupport=1 + +# Enable(1)/Disable(0) SIFS burst +gEnableSifsBurst=1 + +# Enable or Disable Multi-user MIMO +# 1=Enable (default), 0=Disable +gEnableMuBformee=1 + +# Enable/Disable channel avoidance for SAP in SCC scenario +# 0 - disable +# 1 - enable +gSapSccChanAvoidance=0 + +# RA filtering rate limit param, the current value would not +# help if the lifetime in RA is less than 3*60=3min. Then +# we need to change it, though it is uncommon. +# gRAFilterEnable=0 +gRArateLimitInterval=60 + +# Inactivity time (in ms) to end TX Service Period while in IBSS power save mode +gIbssTxSpEndInactivityTime=10 + +# Enable support for TDLS +# 0 - disable +# 1 - enable +gEnableTDLSSupport=1 + +# Enable support for Implicit Trigger of TDLS. That is, wlan driver shall +# initiate TDLS Discovery towards a peer whenever setup criteria (throughput +# and RSSI) is met and then will initiate teardown when teardown criteria +# (idle packet count and RSSI) is met. +# 0 - disable +# 1 - enable +gEnableTDLSImplicitTrigger=1 + +# Enable TDLS External Control. That is, user space application has to +# first configure a peer MAC in wlan driver towards which TDLS is desired. +# Device will establish TDLS only towards those configured peers whenever +# TDLS criteria (throughput and RSSI threshold) is met and teardown TDLS +# when teardown criteria (idle packet count and RSSI) is met. However, +# device will accept TDLS connection if it is initiated from any other peer, +# even if that peer is not configured. +# 0 - disable +# 1 - enable +# For TDLS External Control, Implicit Trigger must also be enabled. +gTDLSExternalControl=1 + +# Enable support for TDLS off-channel operation +# 0 - disable +# 1 - enable +# TDLS off-channel operation will be invoked when there is only one +# TDLS connection. +gEnableTDLSOffChannel=1 + +# Enable/Disable Roaming Offload Support (a.k.a Key Management Offload) +# 0 to disable, 1 to enable +gRoamOffloadEnabled=0 + +gEnableSelfRecovery=1 + +#Enable RA filtering offload +gRAFilterEnable=1 + +gAllowDFSChannelRoam=1 + +gChainMask_2g=3 +gChainMask_5g=3 +gVdevTypeNss_2g=43690 +gVdevTypeNss_5g=43690 + +gEnableMemDeepSleep=1 + +gIPAConfig=0x1d +IpaUcOffloadEnabled=1 +gIpaUcStaOffload=0 + +# Enable Runtime PM Feature. +# Enabling this feature will put target wow and shutdown pcie link +# when inactivity is detected in WLAN Driver. +# This feature is inactive when beaconing interfaces are active with +# clients associated. +# 0 - disable +# 1 - enable +gRuntimePM=0 + +# When gRuntimePM is disabled gRuntimeAutoTime won't take effect. +# The Time is in msec. +# 100 is min, 10000 is max, 500 is default. +gRuntimePMDelay=500 + +gEnablePacketLog=0 + +gTxLdpcEnable=3 + +gMulticastHostFwMsgs=0 +#vosTraceEnableWDA=255 +#vosTraceEnableHDD=255 +#vosTraceEnableSME=255 + +END + +# Note: Configuration parser would not read anything past the END marker + diff --git a/wifi/hostapd.accept b/wifi/hostapd.accept new file mode 100644 index 000000000..923eab6fe --- /dev/null +++ b/wifi/hostapd.accept @@ -0,0 +1,3 @@ +# List of MAC addresses that are allowed to authenticate (IEEE 802.11) +# with the AP. Optional VLAN ID can be assigned for clients based on the +# MAC address if dynamic VLANs (hostapd.conf dynamic_vlan option) are used. diff --git a/wifi/hostapd.conf b/wifi/hostapd.conf new file mode 100644 index 000000000..915ceffca --- /dev/null +++ b/wifi/hostapd.conf @@ -0,0 +1,1043 @@ +##### hostapd configuration file ############################################## +# Empty lines and lines starting with # are ignored + +# AP netdevice name (without 'ap' postfix, i.e., wlan0 uses wlan0ap for +# management frames); ath0 for madwifi +interface=wlan0 + +# In case of madwifi and nl80211 driver interfaces, an additional configuration +# parameter, bridge, must be used to notify hostapd if the interface is +# included in a bridge. This parameter is not used with Host AP driver. +#bridge=br0 + +# Driver interface type (hostap/wired/madwifi/prism54/test/none/nl80211/bsd); +# default: hostap). nl80211 is used with all Linux mac80211 drivers. +# Use driver=none if building hostapd as a standalone RADIUS server that does +# not control any wireless/wired driver. +driver=nl80211 + +# hostapd event logger configuration +# +# Two output method: syslog and stdout (only usable if not forking to +# background). +# +# Module bitfield (ORed bitfield of modules that will be logged; -1 = all +# modules): +# bit 0 (1) = IEEE 802.11 +# bit 1 (2) = IEEE 802.1X +# bit 2 (4) = RADIUS +# bit 3 (8) = WPA +# bit 4 (16) = driver interface +# bit 5 (32) = IAPP +# bit 6 (64) = MLME +# +# Levels (minimum value for logged events): +# 0 = verbose debugging +# 1 = debugging +# 2 = informational messages +# 3 = notification +# 4 = warning +# +logger_syslog=-1 +logger_syslog_level=2 +logger_stdout=-1 +logger_stdout_level=2 + +# Dump file for state information (on SIGUSR1) +dump_file=/tmp/hostapd.dump + +# Interface for separate control program. If this is specified, hostapd +# will create this directory and a UNIX domain socket for listening to requests +# from external programs (CLI/GUI, etc.) for status information and +# configuration. The socket file will be named based on the interface name, so +# multiple hostapd processes/interfaces can be run at the same time if more +# than one interface is used. +# /var/run/hostapd is the recommended directory for sockets and by default, +# hostapd_cli will use it when trying to connect with hostapd. +ctrl_interface=/data/misc/wifi/hostapd + + +# Access control for the control interface can be configured by setting the +# directory to allow only members of a group to use sockets. This way, it is +# possible to run hostapd as root (since it needs to change network +# configuration and open raw sockets) and still allow GUI/CLI components to be +# run as non-root users. However, since the control interface can be used to +# change the network configuration, this access needs to be protected in many +# cases. By default, hostapd is configured to use gid 0 (root). If you +# want to allow non-root users to use the contron interface, add a new group +# and change this value to match with that group. Add users that should have +# control interface access to this group. +# +# This variable can be a group name or gid. +#ctrl_interface_group=wheel +#ctrl_interface_group=0 + + +##### IEEE 802.11 related configuration ####################################### + +# SSID to be used in IEEE 802.11 management frames +ssid=QualcommSoftAP + +# Country code (ISO/IEC 3166-1). Used to set regulatory domain. +# Set as needed to indicate country in which device is operating. +# This can limit available channels and transmit power. +#country_code=US + +# Enable IEEE 802.11d. This advertises the country_code and the set of allowed +# channels and transmit power levels based on the regulatory limits. The +# country_code setting must be configured with the correct country for +# IEEE 802.11d functions. +# (default: 0 = disabled) +#ieee80211d=1 + +# Operation mode (a = IEEE 802.11a, b = IEEE 802.11b, g = IEEE 802.11g, +# n = IEEE 802.11n, g_only = IEEE 802.11g_only, n_only = IEEE 802.11n_only, +# Default: IEEE 802.11n +hw_mode=g + +# Channel number (IEEE 802.11) +# (default: 0, i.e., not set) +# Please note that some drivers (e.g., madwifi) do not use this value from +# hostapd and the channel will need to be configuration separately with +# iwconfig. +channel=6 + +# Beacon interval in kus (1.024 ms) (default: 100; range 15..65535) +beacon_int=100 + +# DTIM (delivery trafic information message) period (range 1..255): +# number of beacons between DTIMs (1 = every beacon includes DTIM element) +# (default: 2) +dtim_period=2 + +# Maximum number of stations allowed in station table. New stations will be +# rejected after the station table is full. IEEE 802.11 has a limit of 2007 +# different association IDs, so this number should not be larger than that. +# (default: 2007) +max_num_sta=255 + +# RTS/CTS threshold; 2347 = disabled (default); range 0..2347 +# If this field is not included in hostapd.conf, hostapd will not control +# RTS threshold and 'iwconfig wlan# rts ' can be used to set it. +#rts_threshold=2347 + +# Fragmentation threshold; 2346 = disabled (default); range 256..2346 +# If this field is not included in hostapd.conf, hostapd will not control +# fragmentation threshold and 'iwconfig wlan# frag ' can be used to set +# it. +#fragm_threshold=2346 + +# Rate configuration +# Default is to enable all rates supported by the hardware. This configuration +# item allows this list be filtered so that only the listed rates will be left +# in the list. If the list is empty, all rates are used. This list can have +# entries that are not in the list of rates the hardware supports (such entries +# are ignored). The entries in this list are in 100 kbps, i.e., 11 Mbps = 110. +# If this item is present, at least one rate have to be matching with the rates +# hardware supports. +# default: use the most common supported rate setting for the selected +# hw_mode (i.e., this line can be removed from configuration file in most +# cases) +#supported_rates=10 20 55 110 60 90 120 180 240 360 480 540 + +# Basic rate set configuration +# List of rates (in 100 kbps) that are included in the basic rate set. +# If this item is not included, usually reasonable default set is used. +# This basic rates set is currently used for g-only profile +#basic_rates=60 + +# Short Preamble +# This parameter can be used to enable optional use of short preamble for +# frames sent at 2 Mbps, 5.5 Mbps, and 11 Mbps to improve network performance. +# This applies only to IEEE 802.11b-compatible networks and this should only be +# enabled if the local hardware supports use of short preamble. If any of the +# associated STAs do not support short preamble, use of short preamble will be +# disabled (and enabled when such STAs disassociate) dynamically. +# 0 = do not allow use of short preamble (default) +# 1 = allow use of short preamble +#preamble=1 + +# Station MAC address -based authentication +# Please note that this kind of access control requires a driver that uses +# hostapd to take care of management frame processing and as such, this can be +# used with driver=hostap or driver=nl80211, but not with driver=madwifi. +# 0 = accept unless in deny list +# 1 = deny unless in accept list +# 2 = use external RADIUS server (accept/deny lists are searched first) +macaddr_acl=0 + +# Accept/deny lists are read from separate files (containing list of +# MAC addresses, one per line). Use absolute path name to make sure that the +# files can be read on SIGHUP configuration reloads. +accept_mac_file=/data/misc/wifi/hostapd.accept +deny_mac_file=/data/misc/wifi/hostapd.deny + +# IEEE 802.11 specifies two authentication algorithms. hostapd can be +# configured to allow both of these or only one. Open system authentication +# should be used with IEEE 802.1X. +# Bit fields of allowed authentication algorithms: +# bit 0 = Open System Authentication +# bit 1 = Shared Key Authentication (requires WEP) +auth_algs=3 + +# Send empty SSID in beacons and ignore probe request frames that do not +# specify full SSID, i.e., require stations to know SSID. +# default: disabled (0) +# 1 = send empty (length=0) SSID in beacon and ignore probe request for +# broadcast SSID +# 2 = clear SSID (ASCII 0), but keep the original length (this may be required +# with some clients that do not support empty SSID) and ignore probe +# requests for broadcast SSID +ignore_broadcast_ssid=0 + +# TX queue parameters (EDCF / bursting) +# default for all these fields: not set, use hardware defaults +# tx_queue__ +# queues: data0, data1, data2, data3, after_beacon, beacon +# (data0 is the highest priority queue) +# parameters: +# aifs: AIFS (default 2) +# cwmin: cwMin (1, 3, 7, 15, 31, 63, 127, 255, 511, 1023) +# cwmax: cwMax (1, 3, 7, 15, 31, 63, 127, 255, 511, 1023); cwMax >= cwMin +# burst: maximum length (in milliseconds with precision of up to 0.1 ms) for +# bursting +# +# Default WMM parameters (IEEE 802.11 draft; 11-03-0504-03-000e): +# These parameters are used by the access point when transmitting frames +# to the clients. +# +# Low priority / AC_BK = background +#tx_queue_data3_aifs=7 +#tx_queue_data3_cwmin=15 +#tx_queue_data3_cwmax=1023 +#tx_queue_data3_burst=0 +# Note: for IEEE 802.11b mode: cWmin=31 cWmax=1023 burst=0 +# +# Normal priority / AC_BE = best effort +#tx_queue_data2_aifs=3 +#tx_queue_data2_cwmin=15 +#tx_queue_data2_cwmax=63 +#tx_queue_data2_burst=0 +# Note: for IEEE 802.11b mode: cWmin=31 cWmax=127 burst=0 +# +# High priority / AC_VI = video +#tx_queue_data1_aifs=1 +#tx_queue_data1_cwmin=7 +#tx_queue_data1_cwmax=15 +#tx_queue_data1_burst=3.0 +# Note: for IEEE 802.11b mode: cWmin=15 cWmax=31 burst=6.0 +# +# Highest priority / AC_VO = voice +#tx_queue_data0_aifs=1 +#tx_queue_data0_cwmin=3 +#tx_queue_data0_cwmax=7 +#tx_queue_data0_burst=1.5 +# Note: for IEEE 802.11b mode: cWmin=7 cWmax=15 burst=3.3 +# +# Special queues; normally not user configurable +# +#tx_queue_after_beacon_aifs=2 +#tx_queue_after_beacon_cwmin=15 +#tx_queue_after_beacon_cwmax=1023 +#tx_queue_after_beacon_burst=0 +# +#tx_queue_beacon_aifs=2 +#tx_queue_beacon_cwmin=3 +#tx_queue_beacon_cwmax=7 +#tx_queue_beacon_burst=1.5 + +# 802.1D Tag (= UP) to AC mappings +# WMM specifies following mapping of data frames to different ACs. This mapping +# can be configured using Linux QoS/tc and sch_pktpri.o module. +# 802.1D Tag 802.1D Designation Access Category WMM Designation +# 1 BK AC_BK Background +# 2 - AC_BK Background +# 0 BE AC_BE Best Effort +# 3 EE AC_BE Best Effort +# 4 CL AC_VI Video +# 5 VI AC_VI Video +# 6 VO AC_VO Voice +# 7 NC AC_VO Voice +# Data frames with no priority information: AC_BE +# Management frames: AC_VO +# PS-Poll frames: AC_BE + +# Default WMM parameters (IEEE 802.11 draft; 11-03-0504-03-000e): +# for 802.11a or 802.11g networks +# These parameters are sent to WMM clients when they associate. +# The parameters will be used by WMM clients for frames transmitted to the +# access point. +# +# note - txop_limit is in units of 32microseconds +# note - acm is admission control mandatory flag. 0 = admission control not +# required, 1 = mandatory +# note - here cwMin and cmMax are in exponent form. the actual cw value used +# will be (2^n)-1 where n is the value given here +# +wmm_enabled=1 +# +# Low priority / AC_BK = background +wmm_ac_bk_cwmin=4 +wmm_ac_bk_cwmax=10 +wmm_ac_bk_aifs=7 +wmm_ac_bk_txop_limit=0 +wmm_ac_bk_acm=0 +# Note: for IEEE 802.11b mode: cWmin=5 cWmax=10 +# +# Normal priority / AC_BE = best effort +wmm_ac_be_aifs=3 +wmm_ac_be_cwmin=4 +wmm_ac_be_cwmax=10 +wmm_ac_be_txop_limit=0 +wmm_ac_be_acm=0 +# Note: for IEEE 802.11b mode: cWmin=5 cWmax=7 +# +# High priority / AC_VI = video +wmm_ac_vi_aifs=2 +wmm_ac_vi_cwmin=3 +wmm_ac_vi_cwmax=4 +wmm_ac_vi_txop_limit=94 +wmm_ac_vi_acm=0 +# Note: for IEEE 802.11b mode: cWmin=4 cWmax=5 txop_limit=188 +# +# Highest priority / AC_VO = voice +wmm_ac_vo_aifs=2 +wmm_ac_vo_cwmin=2 +wmm_ac_vo_cwmax=3 +wmm_ac_vo_txop_limit=47 +wmm_ac_vo_acm=0 +# Note: for IEEE 802.11b mode: cWmin=3 cWmax=4 burst=102 + +# Static WEP key configuration +# +# The key number to use when transmitting. +# It must be between 0 and 3, and the corresponding key must be set. +# default: not set +#wep_default_key=0 +# The WEP keys to use. +# A key may be a quoted string or unquoted hexadecimal digits. +# The key length should be 5, 13, or 16 characters, or 10, 26, or 32 +# digits, depending on whether 40-bit (64-bit), 104-bit (128-bit), or +# 128-bit (152-bit) WEP is used. +# Only the default key must be supplied; the others are optional. +# default: not set +#wep_key0=1234567890 +#wep_key1=1234567890 +#wep_key2=1234567890 +#wep_key3=1234567890 + +# Station inactivity limit +# +# If a station does not send anything in ap_max_inactivity seconds, an +# empty data frame is sent to it in order to verify whether it is +# still in range. If this frame is not ACKed, the station will be +# disassociated and then deauthenticated. This feature is used to +# clear station table of old entries when the STAs move out of the +# range. +# +# The station can associate again with the AP if it is still in range; +# this inactivity poll is just used as a nicer way of verifying +# inactivity; i.e., client will not report broken connection because +# disassociation frame is not sent immediately without first polling +# the STA with a data frame. +# default: 300 (i.e., 5 minutes) +#ap_max_inactivity=300 + +# Enable/disable internal bridge for packets between associated stations. +# +# When IEEE 802.11 is used in managed mode, packets are usually send through +# the AP even if they are from a wireless station to another wireless station. +# This functionality requires that the AP has a bridge functionality that sends +# frames back to the same interface if their destination is another associated +# station. In addition, broadcast/multicast frames from wireless stations will +# be sent both to the host system net stack (e.g., to eventually wired network) +# and back to the wireless interface. +# +# The internal bridge is implemented within the wireless kernel module and it +# bypasses kernel filtering (netfilter/iptables/ebtables). If direct +# communication between the stations needs to be prevented, the internal +# bridge can be disabled by setting bridge_packets=0. +# +# Note: If this variable is not included in hostapd.conf, hostapd does not +# change the configuration and iwpriv can be used to set the value with +# 'iwpriv wlan# param 10 0' command. If the variable is in hostapd.conf, +# hostapd will override possible iwpriv configuration whenever configuration +# file is reloaded. +# +# default: do not control from hostapd (80211.o defaults to 1=enabled) +#bridge_packets=1 + +# Maximum allowed Listen Interval (how many Beacon periods STAs are allowed to +# remain asleep). Default: 65535 (no limit apart from field size) +#max_listen_interval=100 + +# Client isolation can be used to prevent low-level bridging of frames between +# associated stations in the BSS. By default, this bridging is allowed. +#ap_isolate=1 + +##### IEEE 802.11n related configuration ###################################### + +# ieee80211n: Whether IEEE 802.11n (HT) is enabled +# 0 = disabled (default) +# 1 = enabled +# Note: You will also need to enable WMM for full HT functionality. +ieee80211n=1 + +#require_ht=1 + +# ht_capab: HT capabilities (list of flags) +# LDPC coding capability: [LDPC] = supported +# Supported channel width set: [HT40-] = both 20 MHz and 40 MHz with secondary +# channel below the primary channel; [HT40+] = both 20 MHz and 40 MHz +# with secondary channel below the primary channel +# (20 MHz only if neither is set) +# Note: There are limits on which channels can be used with HT40- and +# HT40+. Following table shows the channels that may be available for +# HT40- and HT40+ use per IEEE 802.11n Annex J: +# freq HT40- HT40+ +# 2.4 GHz 5-13 1-7 (1-9 in Europe/Japan) +# 5 GHz 40,48,56,64 36,44,52,60 +# (depending on the location, not all of these channels may be available +# for use) +# Spatial Multiplexing (SM) Power Save: [SMPS-STATIC] or [SMPS-DYNAMIC] +# (SMPS disabled if neither is set) +# HT-greenfield: [GF] (disabled if not set) +# Short GI for 20 MHz: [SHORT-GI-20] (disabled if not set) +# Short GI for 40 MHz: [SHORT-GI-40] (disabled if not set) +# Tx STBC: [TX-STBC] (disabled if not set) +# Rx STBC: [RX-STBC1] (one spatial stream), [RX-STBC12] (one or two spatial +# streams), or [RX-STBC123] (one, two, or three spatial streams); Rx STBC +# disabled if none of these set +# HT-delayed Block Ack: [DELAYED-BA] (disabled if not set) +# Maximum A-MSDU length: [MAX-AMSDU-7935] for 7935 octets (3839 octets if not +# set) +# DSSS/CCK Mode in 40 MHz: [DSSS_CCK-40] = allowed (not allowed if not set) +# PSMP support: [PSMP] (disabled if not set) +# L-SIG TXOP protection support: [LSIG-TXOP-PROT] (disabled if not set) +# QcHostapd: +# LOWER byte for associated stations +# UPPER byte for overlapping stations +# each byte will have the following info +# bit15 bit14 bit13 bit12 bit11 bit10 bit9 bit8 +# OBSS RIFS LSIG_TXOP NON_GF HT20 FROM_11G FROM_11B FROM_11A +# bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 +# OBSS RIFS LSIG_TXOP NON_GF HT_20 FROM_11G FROM_11B FROM_11A +#ht_capab=[HT40-] [SHORT-GI-20] [SHORT-GI-40] +ht_capab=[SHORT-GI-20] [GF] [DSSS_CCK-40] [LSIG-TXOP-PROT] +#ht_capab=[LDPC] [HT40-] [HT40+] [SMPS-STATIC] [SMPS-DYNAMIC] [GF] [SHORT-GI-20] [SHORT-GI-40] [TX-STBC] [RX-STBC1] [RX-STBC12] [RX-STBC123] [DELAYED-BA] [MAX-AMSDU-7935] [DSSS_CCK-40] [PSMP] [LSIG-TXOP-PROT] + +##### IEEE 802.1X-2004 related configuration ################################## + +# Require IEEE 802.1X authorization +#ieee8021x=1 + +# IEEE 802.1X/EAPOL version +# hostapd is implemented based on IEEE Std 802.1X-2004 which defines EAPOL +# version 2. However, there are many client implementations that do not handle +# the new version number correctly (they seem to drop the frames completely). +# In order to make hostapd interoperate with these clients, the version number +# can be set to the older version (1) with this configuration value. +#eapol_version=2 + +# Optional displayable message sent with EAP Request-Identity. The first \0 +# in this string will be converted to ASCII-0 (nul). This can be used to +# separate network info (comma separated list of attribute=value pairs); see, +# e.g., RFC 4284. +#eap_message=hello +#eap_message=hello\0networkid=netw,nasid=foo,portid=0,NAIRealms=example.com + +# WEP rekeying (disabled if key lengths are not set or are set to 0) +# Key lengths for default/broadcast and individual/unicast keys: +# 5 = 40-bit WEP (also known as 64-bit WEP with 40 secret bits) +# 13 = 104-bit WEP (also known as 128-bit WEP with 104 secret bits) +#wep_key_len_broadcast=5 +#wep_key_len_unicast=5 +# Rekeying period in seconds. 0 = do not rekey (i.e., set keys only once) +#wep_rekey_period=300 + +# EAPOL-Key index workaround (set bit7) for WinXP Supplicant (needed only if +# only broadcast keys are used) +eapol_key_index_workaround=0 + +# EAP reauthentication period in seconds (default: 3600 seconds; 0 = disable +# reauthentication). +#eap_reauth_period=3600 + +# Use PAE group address (01:80:c2:00:00:03) instead of individual target +# address when sending EAPOL frames with driver=wired. This is the most common +# mechanism used in wired authentication, but it also requires that the port +# is only used by one station. +#use_pae_group_addr=1 + +##### Integrated EAP server ################################################### + +# Optionally, hostapd can be configured to use an integrated EAP server +# to process EAP authentication locally without need for an external RADIUS +# server. This functionality can be used both as a local authentication server +# for IEEE 802.1X/EAPOL and as a RADIUS server for other devices. + +# Use integrated EAP server instead of external RADIUS authentication +# server. This is also needed if hostapd is configured to act as a RADIUS +# authentication server. +eap_server=1 + +# Path for EAP server user database +#eap_user_file=/etc/hostapd.eap_user + +# CA certificate (PEM or DER file) for EAP-TLS/PEAP/TTLS +#ca_cert=/etc/hostapd.ca.pem + +# Server certificate (PEM or DER file) for EAP-TLS/PEAP/TTLS +#server_cert=/etc/hostapd.server.pem + +# Private key matching with the server certificate for EAP-TLS/PEAP/TTLS +# This may point to the same file as server_cert if both certificate and key +# are included in a single file. PKCS#12 (PFX) file (.p12/.pfx) can also be +# used by commenting out server_cert and specifying the PFX file as the +# private_key. +#private_key=/etc/hostapd.server.prv + +# Passphrase for private key +#private_key_passwd=secret passphrase + +# Enable CRL verification. +# Note: hostapd does not yet support CRL downloading based on CDP. Thus, a +# valid CRL signed by the CA is required to be included in the ca_cert file. +# This can be done by using PEM format for CA certificate and CRL and +# concatenating these into one file. Whenever CRL changes, hostapd needs to be +# restarted to take the new CRL into use. +# 0 = do not verify CRLs (default) +# 1 = check the CRL of the user certificate +# 2 = check all CRLs in the certificate path +#check_crl=1 + +# dh_file: File path to DH/DSA parameters file (in PEM format) +# This is an optional configuration file for setting parameters for an +# ephemeral DH key exchange. In most cases, the default RSA authentication does +# not use this configuration. However, it is possible setup RSA to use +# ephemeral DH key exchange. In addition, ciphers with DSA keys always use +# ephemeral DH keys. This can be used to achieve forward secrecy. If the file +# is in DSA parameters format, it will be automatically converted into DH +# params. This parameter is required if anonymous EAP-FAST is used. +# You can generate DH parameters file with OpenSSL, e.g., +# "openssl dhparam -out /etc/hostapd.dh.pem 1024" +#dh_file=/etc/hostapd.dh.pem + +# Configuration data for EAP-SIM database/authentication gateway interface. +# This is a text string in implementation specific format. The example +# implementation in eap_sim_db.c uses this as the UNIX domain socket name for +# the HLR/AuC gateway (e.g., hlr_auc_gw). In this case, the path uses "unix:" +# prefix. +#eap_sim_db=unix:/tmp/hlr_auc_gw.sock + +# Encryption key for EAP-FAST PAC-Opaque values. This key must be a secret, +# random value. It is configured as a 16-octet value in hex format. It can be +# generated, e.g., with the following command: +# od -tx1 -v -N16 /dev/random | colrm 1 8 | tr -d ' ' +#pac_opaque_encr_key=000102030405060708090a0b0c0d0e0f + +# EAP-FAST authority identity (A-ID) +# A-ID indicates the identity of the authority that issues PACs. The A-ID +# should be unique across all issuing servers. In theory, this is a variable +# length field, but due to some existing implementations required A-ID to be +# 16 octets in length, it is strongly recommended to use that length for the +# field to provided interoperability with deployed peer implementation. This +# field is configured in hex format. +#eap_fast_a_id=101112131415161718191a1b1c1d1e1f + +# EAP-FAST authority identifier information (A-ID-Info) +# This is a user-friendly name for the A-ID. For example, the enterprise name +# and server name in a human-readable format. This field is encoded as UTF-8. +#eap_fast_a_id_info=test server + +# Enable/disable different EAP-FAST provisioning modes: +#0 = provisioning disabled +#1 = only anonymous provisioning allowed +#2 = only authenticated provisioning allowed +#3 = both provisioning modes allowed (default) +#eap_fast_prov=3 + +# EAP-FAST PAC-Key lifetime in seconds (hard limit) +#pac_key_lifetime=604800 + +# EAP-FAST PAC-Key refresh time in seconds (soft limit on remaining hard +# limit). The server will generate a new PAC-Key when this number of seconds +# (or fewer) of the lifetime remains. +#pac_key_refresh_time=86400 + +# EAP-SIM and EAP-AKA protected success/failure indication using AT_RESULT_IND +# (default: 0 = disabled). +#eap_sim_aka_result_ind=1 + +# Trusted Network Connect (TNC) +# If enabled, TNC validation will be required before the peer is allowed to +# connect. Note: This is only used with EAP-TTLS and EAP-FAST. If any other +# EAP method is enabled, the peer will be allowed to connect without TNC. +#tnc=1 + + +##### IEEE 802.11f - Inter-Access Point Protocol (IAPP) ####################### + +# Interface to be used for IAPP broadcast packets +#iapp_interface=eth0 + + +##### RADIUS client configuration ############################################# +# for IEEE 802.1X with external Authentication Server, IEEE 802.11 +# authentication with external ACL for MAC addresses, and accounting + +# The own IP address of the access point (used as NAS-IP-Address) +own_ip_addr=127.0.0.1 + +# Optional NAS-Identifier string for RADIUS messages. When used, this should be +# a unique to the NAS within the scope of the RADIUS server. For example, a +# fully qualified domain name can be used here. +# When using IEEE 802.11r, nas_identifier must be set and must be between 1 and +# 48 octets long. +#nas_identifier=ap.example.com + +# RADIUS authentication server +#auth_server_addr=127.0.0.1 +#auth_server_port=1812 +#auth_server_shared_secret=secret + +# RADIUS accounting server +#acct_server_addr=127.0.0.1 +#acct_server_port=1813 +#acct_server_shared_secret=secret + +# Secondary RADIUS servers; to be used if primary one does not reply to +# RADIUS packets. These are optional and there can be more than one secondary +# server listed. +#auth_server_addr=127.0.0.2 +#auth_server_port=1812 +#auth_server_shared_secret=secret2 +# +#acct_server_addr=127.0.0.2 +#acct_server_port=1813 +#acct_server_shared_secret=secret2 + +# Retry interval for trying to return to the primary RADIUS server (in +# seconds). RADIUS client code will automatically try to use the next server +# when the current server is not replying to requests. If this interval is set, +# primary server will be retried after configured amount of time even if the +# currently used secondary server is still working. +#radius_retry_primary_interval=600 + + +# Interim accounting update interval +# If this is set (larger than 0) and acct_server is configured, hostapd will +# send interim accounting updates every N seconds. Note: if set, this overrides +# possible Acct-Interim-Interval attribute in Access-Accept message. Thus, this +# value should not be configured in hostapd.conf, if RADIUS server is used to +# control the interim interval. +# This value should not be less 600 (10 minutes) and must not be less than +# 60 (1 minute). +#radius_acct_interim_interval=600 + +# Dynamic VLAN mode; allow RADIUS authentication server to decide which VLAN +# is used for the stations. This information is parsed from following RADIUS +# attributes based on RFC 3580 and RFC 2868: Tunnel-Type (value 13 = VLAN), +# Tunnel-Medium-Type (value 6 = IEEE 802), Tunnel-Private-Group-ID (value +# VLANID as a string). vlan_file option below must be configured if dynamic +# VLANs are used. Optionally, the local MAC ACL list (accept_mac_file) can be +# used to set static client MAC address to VLAN ID mapping. +# 0 = disabled (default) +# 1 = option; use default interface if RADIUS server does not include VLAN ID +# 2 = required; reject authentication if RADIUS server does not include VLAN ID +#dynamic_vlan=0 + +# VLAN interface list for dynamic VLAN mode is read from a separate text file. +# This list is used to map VLAN ID from the RADIUS server to a network +# interface. Each station is bound to one interface in the same way as with +# multiple BSSIDs or SSIDs. Each line in this text file is defining a new +# interface and the line must include VLAN ID and interface name separated by +# white space (space or tab). +#vlan_file=/etc/hostapd.vlan + +# Interface where 802.1q tagged packets should appear when a RADIUS server is +# used to determine which VLAN a station is on. hostapd creates a bridge for +# each VLAN. Then hostapd adds a VLAN interface (associated with the interface +# indicated by 'vlan_tagged_interface') and the appropriate wireless interface +# to the bridge. +#vlan_tagged_interface=eth0 + + +##### RADIUS authentication server configuration ############################## + +# hostapd can be used as a RADIUS authentication server for other hosts. This +# requires that the integrated EAP server is also enabled and both +# authentication services are sharing the same configuration. + +# File name of the RADIUS clients configuration for the RADIUS server. If this +# commented out, RADIUS server is disabled. +#radius_server_clients=/etc/hostapd.radius_clients + +# The UDP port number for the RADIUS authentication server +#radius_server_auth_port=1812 + +# Use IPv6 with RADIUS server (IPv4 will also be supported using IPv6 API) +#radius_server_ipv6=1 + + +##### WPA/IEEE 802.11i configuration ########################################## + +# Enable WPA. Setting this variable configures the AP to require WPA (either +# WPA-PSK or WPA-RADIUS/EAP based on other configuration). For WPA-PSK, either +# wpa_psk or wpa_passphrase must be set and wpa_key_mgmt must include WPA-PSK. +# For WPA-RADIUS/EAP, ieee8021x must be set (but without dynamic WEP keys), +# RADIUS authentication server must be configured, and WPA-EAP must be included +# in wpa_key_mgmt. +# This field is a bit field that can be used to enable WPA (IEEE 802.11i/D3.0) +# and/or WPA2 (full IEEE 802.11i/RSN): +# bit0 = WPA +# bit1 = IEEE 802.11i/RSN (WPA2) (dot11RSNAEnabled) +#wpa=1 + +# WPA pre-shared keys for WPA-PSK. This can be either entered as a 256-bit +# secret in hex format (64 hex digits), wpa_psk, or as an ASCII passphrase +# (8..63 characters) that will be converted to PSK. This conversion uses SSID +# so the PSK changes when ASCII passphrase is used and the SSID is changed. +# wpa_psk (dot11RSNAConfigPSKValue) +# wpa_passphrase (dot11RSNAConfigPSKPassPhrase) +#wpa_psk=0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef +#wpa_passphrase=qualcomm + +# Optionally, WPA PSKs can be read from a separate text file (containing list +# of (PSK,MAC address) pairs. This allows more than one PSK to be configured. +# Use absolute path name to make sure that the files can be read on SIGHUP +# configuration reloads. +#wpa_psk_file=/etc/hostapd.wpa_psk + +# Set of accepted key management algorithms (WPA-PSK, WPA-EAP, or both). The +# entries are separated with a space. WPA-PSK-SHA256 and WPA-EAP-SHA256 can be +# added to enable SHA256-based stronger algorithms. +# (dot11RSNAConfigAuthenticationSuitesTable) +#wpa_key_mgmt=WPA-PSK +#wpa_key_mgmt=WPA-EAP + +# Set of accepted cipher suites (encryption algorithms) for pairwise keys +# (unicast packets). This is a space separated list of algorithms: +# CCMP = AES in Counter mode with CBC-MAC [RFC 3610, IEEE 802.11i/D7.0] +# TKIP = Temporal Key Integrity Protocol [IEEE 802.11i/D7.0] +# Group cipher suite (encryption algorithm for broadcast and multicast frames) +# is automatically selected based on this configuration. If only CCMP is +# allowed as the pairwise cipher, group cipher will also be CCMP. Otherwise, +# TKIP will be used as the group cipher. +# (dot11RSNAConfigPairwiseCiphersTable) +# Pairwise cipher for WPA (v1) (default: TKIP) +#wpa_pairwise=TKIP CCMP +# Pairwise cipher for RSN/WPA2 (default: use wpa_pairwise value) +#rsn_pairwise=CCMP + +# Time interval for rekeying GTK (broadcast/multicast encryption keys) in +# seconds. (dot11RSNAConfigGroupRekeyTime) +wpa_group_rekey=86400 + +# Rekey GTK when any STA that possesses the current GTK is leaving the BSS. +# (dot11RSNAConfigGroupRekeyStrict) +#wpa_strict_rekey=1 + +# Time interval for rekeying GMK (master key used internally to generate GTKs +# (in seconds). +#wpa_gmk_rekey=86400 + +# Maximum lifetime for PTK in seconds. This can be used to enforce rekeying of +# PTK to mitigate some attacks against TKIP deficiencies. +#wpa_ptk_rekey=600 + +# Enable IEEE 802.11i/RSN/WPA2 pre-authentication. This is used to speed up +# roaming be pre-authenticating IEEE 802.1X/EAP part of the full RSN +# authentication and key handshake before actually associating with a new AP. +# (dot11RSNAPreauthenticationEnabled) +#rsn_preauth=1 +# +# Space separated list of interfaces from which pre-authentication frames are +# accepted (e.g., 'eth0' or 'eth0 wlan0wds0'. This list should include all +# interface that are used for connections to other APs. This could include +# wired interfaces and WDS links. The normal wireless data interface towards +# associated stations (e.g., wlan0) should not be added, since +# pre-authentication is only used with APs other than the currently associated +# one. +#rsn_preauth_interfaces=eth0 + +# peerkey: Whether PeerKey negotiation for direct links (IEEE 802.11e) is +# allowed. This is only used with RSN/WPA2. +# 0 = disabled (default) +# 1 = enabled +#peerkey=1 + +# ieee80211w: Whether management frame protection (MFP) is enabled +# 0 = disabled (default) +# 1 = optional +# 2 = required +#ieee80211w=0 + +# Association SA Query maximum timeout (in TU = 1.024 ms; for MFP) +# (maximum time to wait for a SA Query response) +# dot11AssociationSAQueryMaximumTimeout, 1...4294967295 +#assoc_sa_query_max_timeout=1000 + +# Association SA Query retry timeout (in TU = 1.024 ms; for MFP) +# (time between two subsequent SA Query requests) +# dot11AssociationSAQueryRetryTimeout, 1...4294967295 +#assoc_sa_query_retry_timeout=201 + + +# okc: Opportunistic Key Caching (aka Proactive Key Caching) +# Allow PMK cache to be shared opportunistically among configured interfaces +# and BSSes (i.e., all configurations within a single hostapd process). +# 0 = disabled (default) +# 1 = enabled +#okc=1 + + +##### IEEE 802.11r configuration ############################################## + +# Mobility Domain identifier (dot11FTMobilityDomainID, MDID) +# MDID is used to indicate a group of APs (within an ESS, i.e., sharing the +# same SSID) between which a STA can use Fast BSS Transition. +# 2-octet identifier as a hex string. +#mobility_domain=a1b2 + +# PMK-R0 Key Holder identifier (dot11FTR0KeyHolderID) +# 1 to 48 octet identifier. +# This is configured with nas_identifier (see RADIUS client section above). + +# Default lifetime of the PMK-RO in minutes; range 1..65535 +# (dot11FTR0KeyLifetime) +#r0_key_lifetime=10000 + +# PMK-R1 Key Holder identifier (dot11FTR1KeyHolderID) +# 6-octet identifier as a hex string. +#r1_key_holder=000102030405 + +# Reassociation deadline in time units (TUs / 1.024 ms; range 1000..65535) +# (dot11FTReassociationDeadline) +#reassociation_deadline=1000 + +# List of R0KHs in the same Mobility Domain +# format: <128-bit key as hex string> +# This list is used to map R0KH-ID (NAS Identifier) to a destination MAC +# address when requesting PMK-R1 key from the R0KH that the STA used during the +# Initial Mobility Domain Association. +#r0kh=02:01:02:03:04:05 r0kh-1.example.com 000102030405060708090a0b0c0d0e0f +#r0kh=02:01:02:03:04:06 r0kh-2.example.com 00112233445566778899aabbccddeeff +# And so on.. One line per R0KH. + +# List of R1KHs in the same Mobility Domain +# format: <128-bit key as hex string> +# This list is used to map R1KH-ID to a destination MAC address when sending +# PMK-R1 key from the R0KH. This is also the list of authorized R1KHs in the MD +# that can request PMK-R1 keys. +#r1kh=02:01:02:03:04:05 02:11:22:33:44:55 000102030405060708090a0b0c0d0e0f +#r1kh=02:01:02:03:04:06 02:11:22:33:44:66 00112233445566778899aabbccddeeff +# And so on.. One line per R1KH. + +# Whether PMK-R1 push is enabled at R0KH +# 0 = do not push PMK-R1 to all configured R1KHs (default) +# 1 = push PMK-R1 to all configured R1KHs whenever a new PMK-R0 is derived +#pmk_r1_push=1 + +##### Passive scanning ######################################################## +# Scan different channels every N seconds. 0 = disable passive scanning. +#passive_scan_interval=60 + +# Listen N usecs on each channel when doing passive scanning. +# This value plus the time needed for changing channels should be less than +# 32 milliseconds (i.e. 32000 usec) to avoid interruptions to normal +# operations. Time needed for channel changing varies based on the used wlan +# hardware. +# default: disabled (0) +#passive_scan_listen=10000 + +# Passive scanning mode: +# 0 = scan all supported modes (802.11a/b/g/Turbo) (default) +# 1 = scan only the mode that is currently used for normal operations +#passive_scan_mode=1 + +# Maximum number of entries kept in AP table (either for passive scanning or +# for detecting Overlapping Legacy BSS Condition). The oldest entry will be +# removed when adding a new entry that would make the list grow over this +# limit. Note! Wi-Fi certification for IEEE 802.11g requires that OLBC is +# enabled, so this field should not be set to 0 when using IEEE 802.11g. +# default: 255 +#ap_table_max_size=255 + +# Number of seconds of no frames received after which entries may be deleted +# from the AP table. Since passive scanning is not usually performed frequently +# this should not be set to very small value. In addition, there is no +# guarantee that every scan cycle will receive beacon frames from the +# neighboring APs. +# default: 60 +#ap_table_expiration_time=3600 + + +##### Wi-Fi Protected Setup (WPS) ############################################# + +# WPS state +# 0 = WPS disabled (default) +# 1 = WPS enabled, not configured +# 2 = WPS enabled, configured +#wps_state=2 + +# AP can be configured into a locked state where new WPS Registrar are not +# accepted, but previously authorized Registrars (including the internal one) +# can continue to add new Enrollees. +ap_setup_locked=1 + +# Universally Unique IDentifier (UUID; see RFC 4122) of the device +# This value is used as the UUID for the internal WPS Registrar. If the AP +# is also using UPnP, this value should be set to the device's UPnP UUID. +# If not configured, UUID will be generated based on the local MAC address. +#uuid=12345678-9abc-def0-1234-56789abcdef0 + +# Note: If wpa_psk_file is set, WPS is used to generate random, per-device PSKs +# that will be appended to the wpa_psk_file. If wpa_psk_file is not set, the +# default PSK (wpa_psk/wpa_passphrase) will be delivered to Enrollees. Use of +# per-device PSKs is recommended as the more secure option (i.e., make sure to +# set wpa_psk_file when using WPS with WPA-PSK). + +# When an Enrollee requests access to the network with PIN method, the Enrollee +# PIN will need to be entered for the Registrar. PIN request notifications are +# sent to hostapd ctrl_iface monitor. In addition, they can be written to a +# text file that could be used, e.g., to populate the AP administration UI with +# pending PIN requests. If the following variable is set, the PIN requests will +# be written to the configured file. +#wps_pin_requests=/var/run/hostapd_wps_pin_requests + +# Device Name +# User-friendly description of device; up to 32 octets encoded in UTF-8 +#device_name=Wireless AP + +# Manufacturer +# The manufacturer of the device (up to 64 ASCII characters) +#manufacturer=Qualcomm + +# Model Name +# Model of the device (up to 32 ASCII characters) +#model_name=QualcommSoftAP + +# Model Number +# Additional device description (up to 32 ASCII characters) +#model_number=123 + +# Serial Number +# Serial number of the device (up to 32 characters) +#serial_number=12345 + +# Primary Device Type +# Used format: -- +# categ = Category as an integer value +# OUI = OUI and type octet as a 4-octet hex-encoded value; 0050F204 for +# default WPS OUI +# subcateg = OUI-specific Sub Category as an integer value +# Examples: +# 1-0050F204-1 (Computer / PC) +# 1-0050F204-2 (Computer / Server) +# 5-0050F204-1 (Storage / NAS) +# 6-0050F204-1 (Network Infrastructure / AP) +#device_type=6-0050F204-1 + +# OS Version +# 4-octet operating system version number (hex string) +#os_version=01020300 + +# Config Methods +# List of the supported configuration methods +config_methods=label display push_button keypad + +# Access point PIN for initial configuration and adding Registrars +# If not set, hostapd will not allow external WPS Registrars to control the +# access point. +#ap_pin=12345670 + +# Skip building of automatic WPS credential +# This can be used to allow the automatically generated Credential attribute to +# be replaced with pre-configured Credential(s). +#skip_cred_build=1 + +# Additional Credential attribute(s) +# This option can be used to add pre-configured Credential attributes into M8 +# message when acting as a Registrar. If skip_cred_build=1, this data will also +# be able to override the Credential attribute that would have otherwise been +# automatically generated based on network configuration. This configuration +# option points to an external file that much contain the WPS Credential +# attribute(s) as binary data. +#extra_cred=hostapd.cred + +# Credential processing +# 0 = process received credentials internally (default) +# 1 = do not process received credentials; just pass them over ctrl_iface to +# external program(s) +# 2 = process received credentials internally and pass them over ctrl_iface +# to external program(s) +# Note: With wps_cred_processing=1, skip_cred_build should be set to 1 and +# extra_cred be used to provide the Credential data for Enrollees. +# +# wps_cred_processing=1 will disabled automatic updates of hostapd.conf file +# both for Credential processing and for marking AP Setup Locked based on +# validation failures of AP PIN. An external program is responsible on updating +# the configuration appropriately in this case. +#wps_cred_processing=0 + +# AP Settings Attributes for M7 +# By default, hostapd generates the AP Settings Attributes for M7 based on the +# current configuration. It is possible to override this by providing a file +# with pre-configured attributes. This is similar to extra_cred file format, +# but the AP Settings attributes are not encapsulated in a Credential +# attribute. +#ap_settings=hostapd.ap_settings + +# WPS UPnP interface +# If set, support for external Registrars is enabled. +#upnp_iface=br0 + +# Friendly Name (required for UPnP) +# Short description for end use. Should be less than 64 characters. +#friendly_name=Qualcomm Access Point + +# Manufacturer URL (optional for UPnP) +#manufacturer_url=http://www.qualcomm.com/ + +# Model Description (recommended for UPnP) +# Long description for end user. Should be less than 128 characters. +#model_description=Wireless Access Point + +# Model URL (optional for UPnP) +#model_url=http://www.qualcomm.com/ + +# Universal Product Code (optional for UPnP) +# 12-digit, all-numeric code that identifies the consumer package. +#upc=123456789012 + +##### Multiple BSSID support ################################################## +# +# Above configuration is using the default interface (wlan#, or multi-SSID VLAN +# interfaces). Other BSSIDs can be added by using separator 'bss' with +# default interface name to be allocated for the data packets of the new BSS. +# +# hostapd will generate BSSID mask based on the BSSIDs that are +# configured. hostapd will verify that dev_addr & MASK == dev_addr. If this is +# not the case, the MAC address of the radio must be changed before starting +# hostapd (ifconfig wlan0 hw ether ). +# +# BSSIDs are assigned in order to each BSS, unless an explicit BSSID is +# specified using the 'bssid' parameter. +# If an explicit BSSID is specified, it must be chosen such that it: +# - results in a valid MASK that covers it and the dev_addr +# - is not the same as the MAC address of the radio +# - is not the same as any other explicitly specified BSSID +# +# Please note that hostapd uses some of the values configured for the first BSS +# as the defaults for the following BSSes. However, it is recommended that all +# BSSes include explicit configuration of all relevant configuration items. +# +#bss=wlan0_0 +#ssid=test2 +# most of the above items can be used here (apart from radio interface specific +# items, like channel) + +#bss=wlan0_1 +#bssid=00:13:10:95:fe:0b +# ... diff --git a/wifi/hostapd.deny b/wifi/hostapd.deny new file mode 100644 index 000000000..e4b6c09c1 --- /dev/null +++ b/wifi/hostapd.deny @@ -0,0 +1,2 @@ +# List of MAC addresses that are not allowed to authenticate (IEEE 802.11) +# with the AP. diff --git a/wifi/p2p_supplicant_overlay.conf b/wifi/p2p_supplicant_overlay.conf new file mode 100644 index 000000000..acbace22c --- /dev/null +++ b/wifi/p2p_supplicant_overlay.conf @@ -0,0 +1 @@ +disable_scan_offload=1 diff --git a/wifi/wpa_supplicant_overlay.conf b/wifi/wpa_supplicant_overlay.conf new file mode 100644 index 000000000..58c2639e7 --- /dev/null +++ b/wifi/wpa_supplicant_overlay.conf @@ -0,0 +1,2 @@ +disable_scan_offload=1 +p2p_disabled=1