A750FNPUU4CTE3
This commit is contained in:
parent
7bf46eb137
commit
671d649fa8
|
@ -2118,9 +2118,9 @@
|
|||
status = "okay";
|
||||
|
||||
bootc {
|
||||
bootc,time_spec_user = <50000>; /* user binary user build */
|
||||
bootc,time_spec_eng = <80000>; /* user binary eng build */
|
||||
bootc,time_spec_fac = <50000>; /* factory binary */
|
||||
bootc,time_spec_user = <100000>; /* user binary user build */
|
||||
bootc,time_spec_eng = <100000>; /* user binary eng build */
|
||||
bootc,time_spec_fac = <100000>; /* factory binary */
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -115,7 +115,7 @@ CONFIG_RCU_STALL_COMMON=y
|
|||
CONFIG_BUILD_BIN2C=y
|
||||
CONFIG_IKCONFIG=y
|
||||
CONFIG_IKCONFIG_PROC=y
|
||||
CONFIG_LOG_BUF_SHIFT=20
|
||||
CONFIG_LOG_BUF_SHIFT=19
|
||||
CONFIG_LOG_CPU_MAX_BUF_SHIFT=12
|
||||
CONFIG_GENERIC_SCHED_CLOCK=y
|
||||
CONFIG_CGROUPS=y
|
||||
|
@ -1345,10 +1345,7 @@ CONFIG_SCSC_PLATFORM=y
|
|||
# CONFIG_SCSC_CLK20MHZ is not set
|
||||
CONFIG_SCSC_MMAP=y
|
||||
# CONFIG_SCSC_DBG_SAMPLER is not set
|
||||
CONFIG_SCSC_DEBUG=y
|
||||
CONFIG_SCSC_DEBUG_COMPATIBILITY=y
|
||||
CONFIG_SCSC_STATIC_RING=y
|
||||
CONFIG_SCSC_STATIC_RING_SIZE=4194304
|
||||
# CONFIG_SCSC_DEBUG is not set
|
||||
# CONFIG_SCSC_CHV_SUPPORT is not set
|
||||
# CONFIG_SCSC_GPR4_CON_DEBUG is not set
|
||||
CONFIG_SCSC_BUILD_TYPE="User"
|
||||
|
@ -1863,6 +1860,7 @@ CONFIG_TOUCHSCREEN_SEC_TS_GLOVEMODE=y
|
|||
# CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_TD4X00_J2CORESPR is not set
|
||||
# CONFIG_TOUCHSCREEN_MELFAS_MMS438 is not set
|
||||
# CONFIG_TOUCHSCREEN_MELFAS_MSS100 is not set
|
||||
# CONFIG_TOUCHSCREEN_MELFAS_MSS100_A30KOR is not set
|
||||
# CONFIG_TOUCHSCREEN_FTS is not set
|
||||
# CONFIG_TOUCHSCREEN_FTS1BA90A is not set
|
||||
# CONFIG_TOUCHSCREEN_IST30XXC is not set
|
||||
|
@ -3936,6 +3934,7 @@ CONFIG_SEC_DEBUG_AVOID_UNNECESSARY_TRAP=y
|
|||
#
|
||||
CONFIG_SEC_PARAM=y
|
||||
CONFIG_CM_OFFSET=7340596
|
||||
CONFIG_FMM_LOCK_OFFSET=7340680
|
||||
CONFIG_SEC_EVENT_LOG=y
|
||||
CONFIG_SEC_BOOTSTAT=y
|
||||
CONFIG_ARGOS=y
|
||||
|
@ -3982,6 +3981,7 @@ CONFIG_SEC_GPIO=y
|
|||
#
|
||||
# CONFIG_SEC_VTS_TEST is not set
|
||||
# CONFIG_SEC_PERIPHERAL_SECURE_CHK is not set
|
||||
# CONFIG_SEC_DEBUG_SNAPSHOT_DISABLE is not set
|
||||
CONFIG_VNSWAP=y
|
||||
CONFIG_SEC_STI=y
|
||||
|
||||
|
@ -4571,6 +4571,7 @@ CONFIG_SENSORS_LSM6DSL_I2C=y
|
|||
# CONFIG_SENSORS_LIS2DS_SPI is not set
|
||||
# CONFIG_SENSORS_K2HH is not set
|
||||
CONFIG_SENSORS_YAS539=y
|
||||
# CONFIG_SENSORS_YAS539_A20E is not set
|
||||
# CONFIG_SENSORS_GP2AP070S is not set
|
||||
# CONFIG_SENSORS_GP2AP110S is not set
|
||||
# CONFIG_SENSORS_STK3013 is not set
|
||||
|
@ -5348,4 +5349,4 @@ CONFIG_LIBFDT=y
|
|||
CONFIG_OID_REGISTRY=y
|
||||
# CONFIG_SG_SPLIT is not set
|
||||
CONFIG_ARCH_HAS_SG_CHAIN=y
|
||||
CONFIG_FPSIMD_CORRUPTION_DETECT=y
|
||||
# CONFIG_FPSIMD_CORRUPTION_DETECT is not set
|
||||
|
|
|
@ -647,7 +647,7 @@ static void max77865_set_otg(struct max77865_charger_data *charger, int enable)
|
|||
/* Update CHG_CNFG_11 to 0x00(3.485V) */
|
||||
max77865_write_reg(charger->i2c,
|
||||
MAX77865_CHG_REG_CNFG_11, 0x00);
|
||||
mdelay(50);
|
||||
msleep(50);
|
||||
|
||||
/* enable charger interrupt */
|
||||
max77865_write_reg(charger->i2c,
|
||||
|
@ -1165,7 +1165,7 @@ static int max77865_chg_set_property(struct power_supply *psy,
|
|||
/* Update CHG_CNFG_11 to 0x00(3.485V) */
|
||||
max77865_write_reg(charger->i2c,
|
||||
MAX77865_CHG_REG_CNFG_11, 0x00);
|
||||
mdelay(50);
|
||||
msleep(50);
|
||||
|
||||
/* enable charger interrupt */
|
||||
max77865_write_reg(charger->i2c,
|
||||
|
@ -1401,7 +1401,7 @@ static void wpc_detect_work(struct work_struct *work)
|
|||
psy_do_property(charger->pdata->wireless_charger_name, set,
|
||||
POWER_SUPPLY_PROP_STATUS, value);
|
||||
}
|
||||
mdelay(50);
|
||||
msleep(50);
|
||||
} while (!wcin_state && !wcin_dtls && wcin_cnt < 2);
|
||||
}
|
||||
|
||||
|
@ -1525,7 +1525,7 @@ static void max77865_aicl_isr_work(struct work_struct *work)
|
|||
reduce_input_current(charger, REDUCE_CURRENT_STEP);
|
||||
aicl_cnt = 0;
|
||||
}
|
||||
mdelay(50);
|
||||
msleep(50);
|
||||
max77865_read_reg(charger->i2c, MAX77865_CHG_REG_INT_OK, &aicl_state);
|
||||
if (max77865_get_input_current(charger) <= MINIMUM_INPUT_CURRENT)
|
||||
break;
|
||||
|
|
|
@ -871,7 +871,7 @@ int max77865_fg_alert_init(struct max77865_fuelgauge_data *fuelgauge, int soc)
|
|||
pr_err("%s: TALRT_THRESHOLD_REG is not valid (0x%x)\n",
|
||||
__func__, read_data);
|
||||
|
||||
/*mdelay(100);*/
|
||||
/*msleep(100);*/
|
||||
|
||||
/* Enable SOC alerts */
|
||||
if (max77865_bulk_read(fuelgauge->i2c, CONFIG_REG,
|
||||
|
|
|
@ -2746,7 +2746,7 @@ void mfc_mst_routine(struct mfc_charger_data *charger, u8 *irq_src)
|
|||
mfc_reg_write(charger->client, MFC_INT_A_CLEAR_H_REG, irq_src[1]); // clear int
|
||||
mfc_set_cmd_l_reg(charger, 0x20, MFC_CMD_CLEAR_INT_MASK); // command
|
||||
|
||||
mdelay(10);
|
||||
msleep(10);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -322,7 +322,7 @@ static void s2mu004_enable_charger_switch(
|
|||
/* forced ASYNC */
|
||||
s2mu004_update_reg(charger->i2c, 0x30, 0x03, 0x03);
|
||||
|
||||
mdelay(30);
|
||||
msleep(30);
|
||||
|
||||
s2mu004_update_reg(charger->i2c, S2MU004_CHG_CTRL0, CHG_MODE, REG_MODE_MASK);
|
||||
|
||||
|
@ -331,7 +331,7 @@ static void s2mu004_enable_charger_switch(
|
|||
S2MU004_FC_CHG_TIMER_16hr << SET_TIME_CHG_SHIFT,
|
||||
SET_TIME_CHG_MASK);
|
||||
|
||||
mdelay(100);
|
||||
msleep(100);
|
||||
|
||||
/* Auto SYNC to ASYNC - default */
|
||||
s2mu004_update_reg(charger->i2c, 0x30, 0x01, 0x03);
|
||||
|
@ -347,12 +347,12 @@ static void s2mu004_enable_charger_switch(
|
|||
s2mu004_analog_ivr_switch(charger, DISABLE);
|
||||
}
|
||||
#endif
|
||||
mdelay(30);
|
||||
msleep(30);
|
||||
s2mu004_update_reg(charger->i2c, S2MU004_CHG_CTRL0, BUCK_MODE, REG_MODE_MASK);
|
||||
|
||||
/* async on */
|
||||
s2mu004_update_reg(charger->i2c, 0x96, 0x01 << 3, 0x01 << 3);
|
||||
mdelay(100);
|
||||
msleep(100);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -375,7 +375,7 @@ static void s2mu004_set_buck(struct s2mu004_charger_data *charger, int enable)
|
|||
|
||||
/* async on */
|
||||
s2mu004_update_reg(charger->i2c, 0x96, 0x01 << 3, 0x01 << 3);
|
||||
mdelay(100);
|
||||
msleep(100);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1538,7 +1538,7 @@ static void s2mu004_ivr_irq_work(struct work_struct *work)
|
|||
reduce_input_current(charger);
|
||||
ivr_cnt = 0;
|
||||
}
|
||||
mdelay(50);
|
||||
msleep(50);
|
||||
|
||||
if (!(ivr_state & IVR_STATUS)) {
|
||||
pr_info("%s: EXIT IVR WORK: check value (0x0D:0x%02x, input current:%d)\n", __func__,
|
||||
|
|
|
@ -799,7 +799,7 @@ static int s2mu004_get_rawsoc(struct s2mu004_fuelgauge_data *fuelgauge)
|
|||
/* SOC VM Monitoring For debugging SOC error */
|
||||
s2mu004_read_reg_byte(fuelgauge->i2c, S2MU004_REG_MONOUT_SEL, &r_monoutsel);
|
||||
s2mu004_write_reg_byte(fuelgauge->i2c, S2MU004_REG_MONOUT_SEL, 0x02);
|
||||
mdelay(10);
|
||||
msleep(10);
|
||||
if (s2mu004_read_reg(fuelgauge->i2c, S2MU004_REG_MONOUT, mount_data) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
|
@ -1144,7 +1144,7 @@ static int s2mu004_get_monout_avgvbat(struct s2mu004_fuelgauge_data *fuelgauge)
|
|||
|
||||
s2mu004_write_reg_byte(fuelgauge->i2c, S2MU004_REG_MONOUT_SEL, 0x27);
|
||||
|
||||
mdelay(50);
|
||||
msleep(50);
|
||||
|
||||
if (s2mu004_read_reg(fuelgauge->i2c, S2MU004_REG_MONOUT, data) < 0)
|
||||
goto err;
|
||||
|
@ -1682,7 +1682,7 @@ static int s2mu004_fg_set_property(struct power_supply *psy,
|
|||
temp &= 0xCF;
|
||||
temp |= 0x10;
|
||||
s2mu004_write_reg_byte(fuelgauge->i2c, S2MU004_REG_CTRL0, temp);
|
||||
mdelay(1000);
|
||||
msleep(1000);
|
||||
s2mu004_restart_gauging(fuelgauge);
|
||||
s2mu004_fg_reset_capacity_by_jig_connection(fuelgauge);
|
||||
} else if (val->intval == SEC_BAT_INBAT_FGSRC_SWITCHING_OFF) {
|
||||
|
@ -1694,7 +1694,7 @@ static int s2mu004_fg_set_property(struct power_supply *psy,
|
|||
else
|
||||
temp |= 0x10;
|
||||
s2mu004_write_reg_byte(fuelgauge->i2c, S2MU004_REG_CTRL0, temp);
|
||||
mdelay(1000);
|
||||
msleep(1000);
|
||||
s2mu004_restart_gauging(fuelgauge);
|
||||
}
|
||||
s2mu004_read_reg_byte(fuelgauge->i2c, S2MU004_REG_CTRL0, &temp);
|
||||
|
|
|
@ -77,7 +77,7 @@ static void s2mu005_test_read(struct i2c_client *i2c)
|
|||
static int reg_list[] = {
|
||||
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11,
|
||||
0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x2A,
|
||||
0x51, 0x7E, 0x55, 0x5E, 0x7B
|
||||
0x51, 0x7E, 0x55, 0x5E, 0x7B, 0x23, 0x26, 0xA7
|
||||
};
|
||||
u8 data;
|
||||
char str[1016] = {0,};
|
||||
|
@ -169,7 +169,7 @@ static void s2mu005_charger_otg_control(struct s2mu005_charger_data *charger,
|
|||
s2mu005_update_reg(charger->client, S2MU005_CHG_CTRL0,
|
||||
5 << REG_MODE_SHIFT, REG_MODE_MASK);
|
||||
|
||||
mdelay(150);
|
||||
msleep(150);
|
||||
pr_info("%s: EVT4 OTG Control for factory mode\n", __func__);
|
||||
|
||||
/* set mode to Charger mode */
|
||||
|
@ -1804,6 +1804,7 @@ static int s2mu005_charger_probe(struct platform_device *pdev)
|
|||
charger->ivr_on = false;
|
||||
charger->slow_charging = false;
|
||||
charger->input_current = 1000;
|
||||
charger->cable_type = SEC_BATTERY_CABLE_NONE;
|
||||
|
||||
charger->pdata = devm_kzalloc(&pdev->dev, sizeof(*(charger->pdata)),
|
||||
GFP_KERNEL);
|
||||
|
|
|
@ -1426,7 +1426,7 @@ static int s2mu005_get_monout_avgvbat(struct s2mu005_fuelgauge_data *fuelgauge)
|
|||
s2mu005_write_and_verify_reg_byte(fuelgauge->i2c, S2MU005_REG_MONOUT_SEL, 0x27);
|
||||
}
|
||||
|
||||
mdelay(50);
|
||||
msleep(50);
|
||||
|
||||
if (s2mu005_read_reg(fuelgauge->i2c, S2MU005_REG_MONOUT, data) < 0)
|
||||
goto err;
|
||||
|
@ -2023,7 +2023,7 @@ static int s2mu005_fg_set_property(struct power_supply *psy,
|
|||
if (fuelgauge->revision >= 3) {
|
||||
u8 reg_0x41 = 0, reg_0x27 = 0, reg_0x26 = 0, temp = 0;
|
||||
pr_info("%s, swelling SOC jump issue W/A\n", __func__);
|
||||
mdelay(250);
|
||||
msleep(250);
|
||||
|
||||
s2mu005_read_reg_byte(fuelgauge->i2c, 0x41, ®_0x41);
|
||||
s2mu005_read_reg_byte(fuelgauge->i2c, 0x27, ®_0x27);
|
||||
|
@ -2036,7 +2036,7 @@ static int s2mu005_fg_set_property(struct power_supply *psy,
|
|||
s2mu005_write_and_verify_reg_byte(fuelgauge->i2c, 0x27, temp);
|
||||
s2mu005_write_and_verify_reg_byte(fuelgauge->i2c, 0x26, 0xFD);
|
||||
|
||||
mdelay(260);
|
||||
msleep(260);
|
||||
|
||||
s2mu005_write_and_verify_reg_byte(fuelgauge->i2c, 0x26, reg_0x26);
|
||||
s2mu005_write_and_verify_reg_byte(fuelgauge->i2c, 0x27, reg_0x27);
|
||||
|
@ -2098,7 +2098,7 @@ static int s2mu005_fg_set_property(struct power_supply *psy,
|
|||
temp &= 0xCF;
|
||||
temp |= 0x10;
|
||||
s2mu005_write_and_verify_reg_byte(fuelgauge->i2c, 0x25, temp);
|
||||
mdelay(1000);
|
||||
msleep(1000);
|
||||
s2mu005_restart_gauging(fuelgauge);
|
||||
s2mu005_fg_reset_capacity_by_jig_connection(fuelgauge);
|
||||
s2mu005_fg_test_read(fuelgauge->i2c);
|
||||
|
@ -2109,7 +2109,7 @@ static int s2mu005_fg_set_property(struct power_supply *psy,
|
|||
temp &= 0xCF;
|
||||
temp |= 0x30;
|
||||
s2mu005_write_and_verify_reg_byte(fuelgauge->i2c, 0x25, temp);
|
||||
mdelay(1000);
|
||||
msleep(1000);
|
||||
s2mu005_restart_gauging(fuelgauge);
|
||||
s2mu005_fg_test_read(fuelgauge->i2c);
|
||||
pr_info("%s: SEC_BAT_INBAT_FGSRC_SWITCHING_OFF : 0x25 = %x\n",
|
||||
|
|
|
@ -116,11 +116,11 @@ static int s2mu106_charger_otg_control(
|
|||
msleep(30);
|
||||
/* 5. QBAT On even if BAT OCP occure */
|
||||
s2mu106_update_reg(charger->i2c, S2MU106_CHG_CTRL9, 0x0, 0x10);
|
||||
mdelay(10);
|
||||
msleep(10);
|
||||
/* 6. OTG Enable */
|
||||
s2mu106_update_reg(charger->i2c,
|
||||
S2MU106_CHG_CTRL0, OTG_BST_MODE, REG_MODE_MASK);
|
||||
mdelay(20);
|
||||
msleep(20);
|
||||
|
||||
/* OTG Fault debounce time set 15ms */
|
||||
s2mu106_update_reg(charger->i2c, 0x94, 0x0C, 0x0C);
|
||||
|
@ -190,10 +190,10 @@ static void s2mu106_set_buck(
|
|||
pr_info("[DEBUG]%s: check input current(%d, %d)\n",
|
||||
__func__, prev_current, charger->input_current);
|
||||
s2mu106_set_input_current_limit(charger, 50);
|
||||
mdelay(50);
|
||||
msleep(50);
|
||||
/* async mode */
|
||||
s2mu106_update_reg(charger->i2c, 0x3A, 0x03, 0x03);
|
||||
mdelay(50);
|
||||
msleep(50);
|
||||
s2mu106_update_reg(charger->i2c, S2MU106_CHG_CTRL0, CHARGER_OFF_MODE, REG_MODE_MASK);
|
||||
/* auto async mode */
|
||||
s2mu106_update_reg(charger->i2c, 0x3A, 0x01, 0x03);
|
||||
|
|
|
@ -266,7 +266,7 @@ static void s2mu106_reset_fg(struct s2mu106_fuelgauge_data *fuelgauge)
|
|||
|
||||
/* Dumpdone. Re-calculate SOC */
|
||||
s2mu106_write_and_verify_reg_byte(fuelgauge->i2c, 0x1E, 0x0F);
|
||||
mdelay(300);
|
||||
msleep(300);
|
||||
|
||||
/* If it was voltage mode, recover it */
|
||||
if (fuelgauge->mode == HIGH_SOC_VOLTAGE_MODE) {
|
||||
|
@ -644,7 +644,7 @@ static int s2mu106_get_cycle(struct s2mu106_fuelgauge_data *fuelgauge)
|
|||
|
||||
s2mu106_write_and_verify_reg_byte(fuelgauge->i2c, S2MU106_REG_MONOUT_SEL, 0x27);
|
||||
|
||||
mdelay(50);
|
||||
msleep(50);
|
||||
|
||||
if (s2mu106_read_reg(fuelgauge->i2c, S2MU106_REG_MONOUT, data) < 0)
|
||||
goto err;
|
||||
|
@ -1114,7 +1114,7 @@ batcap_learn_init:
|
|||
|
||||
/* Dumpdone. Re-calculate SOC */
|
||||
s2mu106_write_and_verify_reg_byte(fuelgauge->i2c, 0x1E, 0x0F);
|
||||
mdelay(300);
|
||||
msleep(300);
|
||||
|
||||
s2mu106_write_and_verify_reg_byte(fuelgauge->i2c, 0x24, 0x00);
|
||||
|
||||
|
@ -1321,7 +1321,7 @@ static int s2mu106_get_avgvbat(struct s2mu106_fuelgauge_data *fuelgauge)
|
|||
|
||||
s2mu106_write_and_verify_reg_byte(fuelgauge->i2c, S2MU106_REG_MONOUT_SEL, 0x16);
|
||||
|
||||
mdelay(50);
|
||||
msleep(50);
|
||||
|
||||
if (s2mu106_read_reg(fuelgauge->i2c, S2MU106_REG_MONOUT, data) < 0)
|
||||
goto err;
|
||||
|
@ -1784,7 +1784,7 @@ static int s2mu106_fg_set_property(struct power_supply *psy,
|
|||
temp &= 0xCF;
|
||||
temp |= 0x10;
|
||||
s2mu106_write_and_verify_reg_byte(fuelgauge->i2c, 0x25, temp);
|
||||
mdelay(1000);
|
||||
msleep(1000);
|
||||
if (val->intval == SEC_BAT_INBAT_FGSRC_SWITCHING_ON)
|
||||
s2mu106_restart_gauging(fuelgauge);
|
||||
s2mu106_fg_reset_capacity_by_jig_connection(fuelgauge);
|
||||
|
@ -1797,7 +1797,7 @@ static int s2mu106_fg_set_property(struct power_supply *psy,
|
|||
temp &= 0xCF;
|
||||
temp |= 0x30;
|
||||
s2mu106_write_and_verify_reg_byte(fuelgauge->i2c, 0x25, temp);
|
||||
mdelay(1000);
|
||||
msleep(1000);
|
||||
if (val->intval == SEC_BAT_INBAT_FGSRC_SWITCHING_OFF)
|
||||
s2mu106_restart_gauging(fuelgauge);
|
||||
s2mu106_fg_reset_capacity_by_jig_connection(fuelgauge);
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
#define ENABLE 1
|
||||
#define DISABLE 0
|
||||
|
||||
#define IVR_WORK_DELAY 50
|
||||
#define IVR_WORK_DELAY 150
|
||||
|
||||
static char *s2mu205_supplied_to[] = {
|
||||
"battery",
|
||||
|
@ -895,6 +895,24 @@ static int s2mu205_chg_set_property(struct power_supply *psy,
|
|||
pr_info("%s: reset fuelgauge when surge occur!\n", __func__);
|
||||
*/
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX:
|
||||
{
|
||||
u8 temp = 0;
|
||||
if (!factory_mode) {
|
||||
s2mu205_read_reg(charger->i2c, S2MU205_CHG_STATUS3, &temp);
|
||||
if (temp & IVR_STATUS) {
|
||||
pr_info("%s: IVR Start\n", __func__);
|
||||
wake_lock(&charger->ivr_wake_lock);
|
||||
/* Mask IRQ */
|
||||
s2mu205_update_reg(charger->i2c,
|
||||
S2MU205_CHG_INT2M, 1 << IVR_M_SHIFT, IVR_M_MASK);
|
||||
queue_delayed_work(charger->charger_wqueue, &charger->ivr_work,
|
||||
msecs_to_jiffies(IVR_WORK_DELAY));
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case POWER_SUPPLY_PROP_MAX ... POWER_SUPPLY_EXT_PROP_MAX:
|
||||
switch (ext_psp) {
|
||||
case POWER_SUPPLY_EXT_PROP_FACTORY_VOLTAGE_REGULATION:
|
||||
|
@ -925,7 +943,7 @@ static int s2mu205_chg_set_property(struct power_supply *psy,
|
|||
s2mu205_write_reg(charger->i2c, 0x70, 0x0);
|
||||
s2mu205_update_reg(charger->i2c, S2MU205_CHG_CTRL0, 0x30, 0x30);
|
||||
|
||||
mdelay(100);
|
||||
msleep(100);
|
||||
|
||||
/* QBAT off for prevent SMPL when detach cable */
|
||||
s2mu205_update_reg(charger->i2c, 0x2A, 0xC0, 0xC0);
|
||||
|
@ -1207,7 +1225,7 @@ static void s2mu205_ivr_irq_work(struct work_struct *work)
|
|||
reduce_input_current(charger);
|
||||
ivr_cnt = 0;
|
||||
}
|
||||
mdelay(50);
|
||||
msleep(50);
|
||||
|
||||
if (!(ivr_state & IVR_STATUS)) {
|
||||
pr_info("%s: EXIT IVR WORK: check value (0x13:0x%02x, input current:%d)\n", __func__,
|
||||
|
@ -1390,6 +1408,7 @@ static int s2mu205_charger_probe(struct platform_device *pdev)
|
|||
charger->otg_on = false;
|
||||
charger->ivr_on = false;
|
||||
charger->slow_charging = false;
|
||||
charger->cable_type = SEC_BATTERY_CABLE_NONE;
|
||||
|
||||
charger->dev = &pdev->dev;
|
||||
charger->i2c = s2mu205->i2c;
|
||||
|
|
|
@ -289,7 +289,7 @@ static void s2mu205_reset_fg(struct s2mu205_fuelgauge_data *fuelgauge)
|
|||
|
||||
/* Dumpdone. Re-calculate SOC */
|
||||
s2mu205_write_and_verify_reg_byte(fuelgauge->i2c, 0x1E, 0x0F);
|
||||
mdelay(300);
|
||||
msleep(300);
|
||||
|
||||
/* If it was voltage mode, recover it */
|
||||
if (fuelgauge->mode == HIGH_SOC_VOLTAGE_MODE) {
|
||||
|
@ -561,7 +561,7 @@ static int s2mu205_get_cycle(struct s2mu205_fuelgauge_data *fuelgauge)
|
|||
mutex_lock(&fuelgauge->fg_lock);
|
||||
|
||||
s2mu205_write_and_verify_reg_byte(fuelgauge->i2c, S2MU205_REG_MONOUT_SEL, 0x27);
|
||||
mdelay(50);
|
||||
msleep(50);
|
||||
|
||||
if (s2mu205_read_reg(fuelgauge->i2c, S2MU205_REG_MONOUT, data) < 0)
|
||||
goto err;
|
||||
|
@ -1055,7 +1055,7 @@ batcap_learn_init:
|
|||
s2mu205_write_and_verify_reg_byte(fuelgauge->i2c, 0x24, 0x01);
|
||||
/* Dumpdone. Re-calculate SOC */
|
||||
s2mu205_write_and_verify_reg_byte(fuelgauge->i2c, 0x1E, 0x0F);
|
||||
mdelay(300);
|
||||
msleep(300);
|
||||
s2mu205_write_and_verify_reg_byte(fuelgauge->i2c, 0x24, 0x00);
|
||||
|
||||
/* Make report SOC 0% */
|
||||
|
@ -1742,7 +1742,7 @@ static int s2mu205_fg_set_property(struct power_supply *psy,
|
|||
(val->intval == SEC_BAT_FGSRC_SWITCHING_ON)) {
|
||||
/* Get Battery voltage (by I2C control) */
|
||||
s2mu205_update_reg_byte(fuelgauge->i2c, 0x25, 0x10, 0x30);
|
||||
mdelay(1000);
|
||||
msleep(1000);
|
||||
s2mu205_read_reg_byte(fuelgauge->i2c, 0x25, &temp);
|
||||
pr_info("%s: SW Vbat: fgsrc_switching_on: REG25:0x%02x, 0x25[5:4]=0x%x\n", __func__, temp, (temp & 0x30) >> 4);
|
||||
if (val->intval == SEC_BAT_INBAT_FGSRC_SWITCHING_ON)
|
||||
|
@ -1752,7 +1752,7 @@ static int s2mu205_fg_set_property(struct power_supply *psy,
|
|||
} else if ((val->intval == SEC_BAT_INBAT_FGSRC_SWITCHING_OFF) ||
|
||||
(val->intval == SEC_BAT_FGSRC_SWITCHING_OFF)) {
|
||||
s2mu205_update_reg_byte(fuelgauge->i2c, 0x25, 0x30, 0x30);
|
||||
mdelay(1000);
|
||||
msleep(1000);
|
||||
s2mu205_read_reg_byte(fuelgauge->i2c, 0x25, &temp);
|
||||
pr_info("%s: SW Vsys: fgsrc_switching_off: REG25:0x%02x, 0x25[5:4]=0x%x\n", __func__, temp, (temp & 0x30) >> 4);
|
||||
if (val->intval == SEC_BAT_INBAT_FGSRC_SWITCHING_OFF)
|
||||
|
|
|
@ -4943,7 +4943,7 @@ ssize_t sec_bat_show_attrs(struct device *dev,
|
|||
POWER_SUPPLY_EXT_PROP_INBAT_VOLTAGE_FGSRC_SWITCHING, value);
|
||||
|
||||
for (j = 0; j < 5; j++) {
|
||||
mdelay(200);
|
||||
msleep(200);
|
||||
psy_do_property(battery->pdata->fuelgauge_name, get,
|
||||
POWER_SUPPLY_PROP_VOLTAGE_NOW, value);
|
||||
ocv_data[j] = value.intval;
|
||||
|
|
|
@ -210,8 +210,12 @@ static void s2mu004_pr_swap(void *_data, int val)
|
|||
struct s2mu004_usbpd_data *pdic_data = data->phy_driver_data;
|
||||
|
||||
if (val == USBPD_SINK_OFF) {
|
||||
pd_noti.event = PDIC_NOTIFY_EVENT_PD_PRSWAP_SNKTOSRC;
|
||||
pd_noti.sink_status.selected_pdo_num = 0;
|
||||
pd_noti.sink_status.available_pdo_num = 0;
|
||||
pd_noti.sink_status.current_pdo_num = 0;
|
||||
ccic_event_work(pdic_data, CCIC_NOTIFY_DEV_BATTERY,
|
||||
CCIC_NOTIFY_ID_ATTACH, 0, 0);
|
||||
CCIC_NOTIFY_ID_POWER_STATUS, 0, 0);
|
||||
} else if (val == USBPD_SOURCE_ON) {
|
||||
#if defined(CONFIG_DUAL_ROLE_USB_INTF)
|
||||
pdic_data->power_role_dual = DUAL_ROLE_PROP_PR_SRC;
|
||||
|
@ -222,8 +226,6 @@ static void s2mu004_pr_swap(void *_data, int val)
|
|||
ccic_event_work(pdic_data, CCIC_NOTIFY_DEV_MUIC,
|
||||
CCIC_NOTIFY_ID_ROLE_SWAP, 1/* source */, 0);
|
||||
} else if (val == USBPD_SOURCE_OFF) {
|
||||
ccic_event_work(pdic_data, CCIC_NOTIFY_DEV_BATTERY,
|
||||
CCIC_NOTIFY_ID_ATTACH, 0, 0);
|
||||
#if defined(CONFIG_DUAL_ROLE_USB_INTF)
|
||||
pdic_data->power_role_dual = DUAL_ROLE_PROP_PR_SNK;
|
||||
#elif defined(CONFIG_TYPEC)
|
||||
|
@ -1051,14 +1053,17 @@ static int s2mu004_set_power_role(void *_data, int val)
|
|||
|
||||
if (val == USBPD_SINK) {
|
||||
pdic_data->is_pr_swap = true;
|
||||
data->is_prswap = true;
|
||||
s2mu004_assert_rd(data);
|
||||
s2mu004_snk(pdic_data->i2c);
|
||||
} else if (val == USBPD_SOURCE) {
|
||||
pdic_data->is_pr_swap = true;
|
||||
data->is_prswap = true;
|
||||
s2mu004_assert_rp(data);
|
||||
s2mu004_src(pdic_data->i2c);
|
||||
} else if (val == USBPD_DRP) {
|
||||
pdic_data->is_pr_swap = false;
|
||||
data->is_prswap = false;
|
||||
s2mu004_assert_drp(data);
|
||||
return 0;
|
||||
} else
|
||||
|
@ -2445,7 +2450,9 @@ static int s2mu004_check_port_detect(struct s2mu004_usbpd_data *pdic_data)
|
|||
|
||||
s2mu004_set_vconn_source(pd_data, USBPD_VCONN_ON);
|
||||
|
||||
msleep(tTypeCSinkWaitCap); /* dont over 310~620ms(tTypeCSinkWaitCap) */
|
||||
s2mu004_assert_rp(pd_data);
|
||||
msleep(100); /* dont over 310~620ms(tTypeCSinkWaitCap) */
|
||||
s2mu004_assert_drp(pd_data);
|
||||
} else {
|
||||
dev_err(dev, "%s, PLUG Error\n", __func__);
|
||||
return -1;
|
||||
|
|
|
@ -129,6 +129,20 @@ static void s2mu106_usbpd_test_read(struct s2mu106_usbpd_data *usbpd_data)
|
|||
data[5], data[6], data[7], data[8]);
|
||||
}
|
||||
|
||||
static void s2mu106_usbpd_init_tx_hard_reset(struct s2mu106_usbpd_data *usbpd_data)
|
||||
{
|
||||
struct i2c_client *i2c = usbpd_data->i2c;
|
||||
|
||||
s2mu106_usbpd_write_reg(i2c, S2MU106_REG_MSG_SEND_CON, S2MU106_REG_MSG_SEND_CON_SOP_HardRST
|
||||
| S2MU106_REG_MSG_SEND_CON_OP_MODE);
|
||||
|
||||
s2mu106_usbpd_write_reg(i2c, S2MU106_REG_MSG_SEND_CON, S2MU106_REG_MSG_SEND_CON_SOP_HardRST
|
||||
| S2MU106_REG_MSG_SEND_CON_OP_MODE
|
||||
| S2MU106_REG_MSG_SEND_CON_SEND_MSG_EN);
|
||||
|
||||
pr_info("%s, \n", __func__);
|
||||
}
|
||||
|
||||
void s2mu106_rprd_mode_change(struct s2mu106_usbpd_data *usbpd_data, u8 mode)
|
||||
{
|
||||
u8 data = 0;
|
||||
|
@ -1260,7 +1274,8 @@ static int s2mu106_set_power_role(void *_data, int val)
|
|||
struct usbpd_data *data = (struct usbpd_data *) _data;
|
||||
struct s2mu106_usbpd_data *pdic_data = data->phy_driver_data;
|
||||
|
||||
pr_info("%s, power_role(%d)\n", __func__, val);
|
||||
pr_info("%s, power_role(%d->%d)\n", __func__,
|
||||
pdic_data->power_role, val);
|
||||
|
||||
if (val == USBPD_SINK) {
|
||||
pdic_data->is_pr_swap = true;
|
||||
|
@ -3318,7 +3333,7 @@ static void s2mu106_usbpd_init_configure(struct s2mu106_usbpd_data *_data)
|
|||
s2mu106_set_normal_mode(_data);
|
||||
msleep(25);
|
||||
_data->detach_valid = true;
|
||||
s2mu106_set_lpm_mode(_data);
|
||||
s2mu106_usbpd_init_tx_hard_reset(_data);
|
||||
_data->detach_valid = false;
|
||||
s2mu106_usbpd_set_cc_control(_data, USBPD_CC_OFF);
|
||||
_data->lpm_mode = true;
|
||||
|
|
|
@ -596,6 +596,7 @@ void usbpd_reinit(struct device *dev)
|
|||
usbpd_init_manager_val(pd_data);
|
||||
reinit_completion(&pd_data->msg_arrived);
|
||||
pd_data->wait_for_msg_arrived = 0;
|
||||
pd_data->is_prswap = false;
|
||||
complete(&pd_data->msg_arrived);
|
||||
}
|
||||
|
||||
|
@ -642,6 +643,7 @@ int usbpd_init(struct device *dev, void *phy_driver_data)
|
|||
INIT_WORK(&pd_data->worker, usbpd_policy_work);
|
||||
|
||||
init_completion(&pd_data->msg_arrived);
|
||||
pd_data->is_prswap = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -910,19 +910,18 @@ void usbpd_manager_acc_detach(struct device *dev)
|
|||
static int usbpd_manager_support_vdm(struct usbpd_data *pd_data,
|
||||
usbpd_manager_command_type command)
|
||||
{
|
||||
struct policy_data *policy = &pd_data->policy;
|
||||
struct usbpd_manager_data *manager = &pd_data->manager;
|
||||
|
||||
switch (command) {
|
||||
case MANAGER_REQ_VDM_DISCOVER_SVID:
|
||||
/* Product Type 101b == AMA */
|
||||
if (policy->rx_data_obj[1].id_header_vdo.Product_Type == 0x5) {
|
||||
pr_info("%s, Discover ID == AMA\n", __func__);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
case MANAGER_REQ_VDM_DISCOVER_MODE:
|
||||
case MANAGER_REQ_VDM_ENTER_MODE:
|
||||
case MANAGER_REQ_VDM_STATUS_UPDATE:
|
||||
case MANAGER_REQ_VDM_DisplayPort_Configure:
|
||||
if (manager->Vendor_ID == SAMSUNG_VENDOR_ID) {
|
||||
pr_info("%s, Discover ID, VendorID == SAMSUNG \n", __func__);
|
||||
return 1;
|
||||
}
|
||||
#if defined(CONFIG_CCIC_ALTERNATE_MODE)
|
||||
return 1;
|
||||
#else
|
||||
|
|
|
@ -56,6 +56,7 @@ policy_state usbpd_policy_src_startup(struct policy_data *policy)
|
|||
/* PD Protocol Initialization */
|
||||
usbpd_init_protocol(pd_data);
|
||||
pd_data->phy_ops.soft_reset(pd_data);
|
||||
pd_data->phy_ops.set_rp_control(pd_data, PLUG_CTRL_RP80);
|
||||
|
||||
/* Fro tSrcrecover after PE_SRC_Transition_to_default */
|
||||
if (policy->txhardresetflag == 1) {
|
||||
|
@ -942,6 +943,7 @@ policy_state usbpd_policy_snk_startup(struct policy_data *policy)
|
|||
|
||||
/* PD Protocol Initialization */
|
||||
usbpd_init_protocol(pd_data);
|
||||
pd_data->phy_ops.set_rp_control(pd_data, PLUG_CTRL_RP80);
|
||||
|
||||
/* Configuration Channel On */
|
||||
//pd_data->phy_ops.set_cc_control(pd_data, USBPD_CC_ON);
|
||||
|
@ -1190,7 +1192,7 @@ policy_state usbpd_policy_snk_select_capability(struct policy_data *policy)
|
|||
policy_state usbpd_policy_snk_transition_sink(struct policy_data *policy)
|
||||
{
|
||||
struct usbpd_data *pd_data = policy_to_usbpd(policy);
|
||||
struct usbpd_manager_data *manager = &pd_data->manager;
|
||||
struct usbpd_manager_data *manager = &pd_data->manager;
|
||||
int ret = PE_SNK_Transition_Sink;
|
||||
int ms = 0;
|
||||
bool vbus_short = 0;
|
||||
|
@ -2077,7 +2079,7 @@ policy_state usbpd_policy_prs_src_snk_reject_pr_swap(struct policy_data *policy)
|
|||
|
||||
/* PD State Inform for AP */
|
||||
dev_info(pd_data->dev, "%s\n", __func__);
|
||||
|
||||
|
||||
|
||||
pd_data->phy_ops.get_data_role(pd_data, &data_role);
|
||||
|
||||
|
@ -2222,6 +2224,9 @@ policy_state usbpd_policy_prs_src_snk_transition_to_off(struct policy_data *poli
|
|||
if (ret == PE_PRS_SRC_SNK_Transition_off)
|
||||
return ret;
|
||||
|
||||
#if defined CONFIG_CCIC_S2MU004
|
||||
pd_data->phy_ops.set_power_role(pd_data, USBPD_SOURCE);
|
||||
#endif
|
||||
pd_data->phy_ops.pr_swap(pd_data, USBPD_SOURCE_OFF);
|
||||
|
||||
/* VBUS off */
|
||||
|
@ -2246,6 +2251,10 @@ policy_state usbpd_policy_prs_src_snk_transition_to_off(struct policy_data *poli
|
|||
if (manager->acc_type != CCIC_DOCK_HMT || manager->SVID_0 == 0)
|
||||
msleep(600);
|
||||
#endif
|
||||
#if defined CONFIG_CCIC_S2MU004
|
||||
if (ret == PE_PRS_SRC_SNK_Transition_off)
|
||||
pd_data->phy_ops.set_power_role(pd_data, USBPD_DRP);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -2474,6 +2483,8 @@ policy_state usbpd_policy_prs_snk_src_transition_to_off(struct policy_data *poli
|
|||
|
||||
while (1) {
|
||||
if (policy->plug_valid == 0) {
|
||||
pr_info("%s, plug_valid == 0\n", __func__);
|
||||
pd_data->phy_ops.set_power_role(pd_data, USBPD_DRP);
|
||||
ret = PE_PRS_SNK_SRC_Transition_off;
|
||||
break;
|
||||
}
|
||||
|
@ -6122,6 +6133,11 @@ void usbpd_policy_work(struct work_struct *work)
|
|||
dev_info(pd_data->dev, "%s saved state %x next_state %x \n", __func__, saved_state, next_state);
|
||||
} while (saved_state != next_state);
|
||||
|
||||
#if defined CONFIG_CCIC_S2MU004
|
||||
if (pd_data->is_prswap)
|
||||
pd_data->phy_ops.set_power_role(pd_data, USBPD_DRP);
|
||||
#endif
|
||||
|
||||
policy->state = next_state;
|
||||
dev_info(pd_data->dev, "%s Finished\n", __func__);
|
||||
}
|
||||
|
|
|
@ -768,7 +768,7 @@ void gfspi_hw_power_enable(struct gf_device *gf_dev, u8 onoff)
|
|||
exynos_smc(FP_CSMC_HANDLER_ID, FP_HANDLER_MAIN, FP_SET_POWERON_INACTIVE, 0));
|
||||
#endif
|
||||
if (gf_dev->reset_gpio) {
|
||||
mdelay(11);
|
||||
usleep_range(11000, 11050);
|
||||
gpio_set_value(gf_dev->reset_gpio, 1);
|
||||
}
|
||||
gf_dev->ldo_onoff = 1;
|
||||
|
@ -787,7 +787,7 @@ void gfspi_hw_power_enable(struct gf_device *gf_dev, u8 onoff)
|
|||
#endif
|
||||
if (gf_dev->reset_gpio) {
|
||||
gpio_set_value(gf_dev->reset_gpio, 0);
|
||||
mdelay(11);
|
||||
usleep_range(11000, 11050);
|
||||
}
|
||||
if (gf_dev->pwr_gpio)
|
||||
gpio_set_value(gf_dev->pwr_gpio, 0);
|
||||
|
@ -811,9 +811,9 @@ void gfspi_hw_reset(struct gf_device *gf_dev, u8 delay)
|
|||
}
|
||||
gpio_direction_output(gf_dev->reset_gpio, 1);
|
||||
gpio_set_value(gf_dev->reset_gpio, 0);
|
||||
mdelay(3);
|
||||
usleep_range(3000, 3050);
|
||||
gpio_set_value(gf_dev->reset_gpio, 1);
|
||||
mdelay(delay);
|
||||
usleep_range((delay * 1000), ((delay * 1000) + 50));
|
||||
gf_dev->reset_count++;
|
||||
}
|
||||
|
||||
|
|
95
drivers/gpu/arm/tMIx/r10p0/build.bp
Normal file
95
drivers/gpu/arm/tMIx/r10p0/build.bp
Normal file
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* Copyright:
|
||||
* ----------------------------------------------------------------------------
|
||||
* This confidential and proprietary software may be used only as authorized
|
||||
* by a licensing agreement from ARM Limited.
|
||||
* (C) COPYRIGHT 2017 ARM Limited, ALL RIGHTS RESERVED
|
||||
* The entire notice above must be reproduced on all authorized copies and
|
||||
* copies may only be made to the extent permitted by a licensing agreement
|
||||
* from ARM Limited.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
bob_defaults {
|
||||
name: "mali_kbase_shared_config_defaults",
|
||||
no_mali: {
|
||||
kbuild_options: ["CONFIG_MALI_NO_MALI=y"],
|
||||
},
|
||||
mali_corestack: {
|
||||
kbuild_options: ["CONFIG_MALI_CORESTACK=y"],
|
||||
},
|
||||
mali_devfreq: {
|
||||
kbuild_options: ["CONFIG_MALI_DEVFREQ=y"],
|
||||
},
|
||||
|
||||
defaults: ["kernel_defaults"],
|
||||
}
|
||||
|
||||
bob_kernel_module {
|
||||
name: "mali_kbase",
|
||||
srcs: [
|
||||
"*.c",
|
||||
"*.h",
|
||||
"Kbuild",
|
||||
"backend/gpu/*.c",
|
||||
"backend/gpu/*.h",
|
||||
"backend/gpu/Kbuild",
|
||||
"ipa/*.c",
|
||||
"ipa/*.h",
|
||||
"ipa/Kbuild",
|
||||
"platform/*.h",
|
||||
"platform/*/*.c",
|
||||
"platform/*/*.h",
|
||||
"platform/*/Kbuild",
|
||||
"thirdparty/*.c",
|
||||
],
|
||||
kbuild_options: [
|
||||
"CONFIG_MALI_KUTF=n",
|
||||
"CONFIG_MALI_MIDGARD=m",
|
||||
"CONFIG_MALI_NO_MALI_DEFAULT_GPU={{.gpu}}",
|
||||
"CONFIG_MALI_PLATFORM_NAME={{.mali_platform_name}}",
|
||||
"MALI_KERNEL_TEST_API={{.unit_test_code}}",
|
||||
"MALI_MOCK_TEST={{.mali_mock_test}}",
|
||||
"MALI_UNIT_TEST={{.unit_test_code}}",
|
||||
],
|
||||
cinstr_job_dump: {
|
||||
kbuild_options: ["CONFIG_MALI_JOB_DUMP=y"],
|
||||
},
|
||||
mali_debug: {
|
||||
kbuild_options: ["CONFIG_MALI_DEBUG=y"],
|
||||
},
|
||||
mali_gator_support: {
|
||||
kbuild_options: ["CONFIG_MALI_GATOR_SUPPORT=y"],
|
||||
},
|
||||
mali_system_trace: {
|
||||
kbuild_options: ["CONFIG_MALI_SYSTEM_TRACE=y"],
|
||||
},
|
||||
mali_error_inject: {
|
||||
kbuild_options: ["CONFIG_MALI_ERROR_INJECT=y"],
|
||||
},
|
||||
mali_error_inject_random: {
|
||||
kbuild_options: ["CONFIG_MALI_ERROR_INJECT_RANDOM=y"],
|
||||
},
|
||||
mali_trace_timeline: {
|
||||
kbuild_options: ["CONFIG_MALI_TRACE_TIMELINE=y"],
|
||||
},
|
||||
mali_prfcnt_set_secondary: {
|
||||
kbuild_options: ["CONFIG_MALI_PRFCNT_SET_SECONDARY=y"],
|
||||
},
|
||||
mali_fpga_bus_logger: {
|
||||
kbuild_options: ["CONFIG_MALI_FPGA_BUS_LOGGER=y"],
|
||||
},
|
||||
mali_midgard_dvfs: {
|
||||
kbuild_options: ["CONFIG_MALI_MIDGARD_DVFS=y"],
|
||||
},
|
||||
mali_2mb_alloc: {
|
||||
kbuild_options: ["CONFIG_MALI_2MB_ALLOC=y"],
|
||||
},
|
||||
mali_mock_test: {
|
||||
srcs: ["tests/internal/src/mock/mali_kbase_pm_driver_mock.c"],
|
||||
},
|
||||
ump: {
|
||||
extra_symbols: ["ump"],
|
||||
},
|
||||
defaults: ["mali_kbase_shared_config_defaults"],
|
||||
}
|
|
@ -843,7 +843,9 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
|
|||
if (!td->mtclass.export_all_inputs &&
|
||||
field->application != HID_DG_TOUCHSCREEN &&
|
||||
field->application != HID_DG_PEN &&
|
||||
field->application != HID_DG_TOUCHPAD)
|
||||
field->application != HID_DG_TOUCHPAD &&
|
||||
field->application != HID_GD_KEYBOARD &&
|
||||
field->application != HID_CP_CONSUMER_CONTROL)
|
||||
return -1;
|
||||
|
||||
/*
|
||||
|
|
|
@ -508,7 +508,7 @@ static void ml_ff_destroy(struct ff_device *ff)
|
|||
* do not actually stop the timer, and therefore we should
|
||||
* do it here.
|
||||
*/
|
||||
del_timer_sync(&ml->timer);
|
||||
del_timer_sync(&ml->timer);
|
||||
|
||||
kfree(ml->private);
|
||||
}
|
||||
|
|
|
@ -104,9 +104,10 @@ obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_TD4X00_J2CORESPR) += synaptics_td4x00/
|
|||
obj-$(CONFIG_TOUCHSCREEN_SEC_INCELL_TS) += sec_incell_ts/
|
||||
obj-$(CONFIG_TOUCHSCREEN_MELFAS_MMS438) += melfas_mms400/
|
||||
obj-$(CONFIG_TOUCHSCREEN_MELFAS_MSS100) += melfas_mss100/
|
||||
obj-$(CONFIG_TOUCHSCREEN_MELFAS_MSS100_A30KOR) += melfas_mss100/
|
||||
obj-$(CONFIG_TOUCHSCREEN_IST3038H) += imagis_30xxh/
|
||||
obj-$(CONFIG_TOUCHSCREEN_IST40XX) += imagis_40xx/
|
||||
obj-$(CONFIG_TOUCHSCREEN_IST4050) += imagis/ist4050/
|
||||
obj-$(CONFIG_TOUCHSCREEN_NT36xxx) += novatek_nt36xx/
|
||||
obj-$(CONFIG_TOUCHSCREEN_HIMAX_INCELL) += himax_83xxx/
|
||||
obj-$(CONFIG_TOUCHSCREEN_HIMAX_CHIPSET) += himax/himax_83102P/
|
||||
obj-$(CONFIG_TOUCHSCREEN_HIMAX_CHIPSET) += himax/himax_83102P/
|
||||
|
|
|
@ -1167,7 +1167,7 @@ static int ist40xx_suspend(struct device *dev)
|
|||
#endif
|
||||
|
||||
mutex_lock(&data->lock);
|
||||
if (data->lpm_mode) {
|
||||
if (data->lpm_mode || data->fod_lp_mode) {
|
||||
ist40xx_disable_irq(data);
|
||||
ist40xx_cmd_gesture(data, IST40XX_ENABLE);
|
||||
|
||||
|
|
|
@ -724,6 +724,7 @@ struct ist40xx_data {
|
|||
int report_rate;
|
||||
int idle_rate;
|
||||
u8 lpm_mode;
|
||||
u8 fod_lp_mode;
|
||||
u16 rect_data[4];
|
||||
u16 rejectzone_t;
|
||||
u16 rejectzone_b;
|
||||
|
|
|
@ -1154,6 +1154,24 @@ err:
|
|||
(int)strnlen(buf, sizeof(buf)));
|
||||
}
|
||||
|
||||
static void fod_lp_mode(void *dev_data)
|
||||
{
|
||||
char buf[32] = { 0 };
|
||||
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
||||
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
||||
|
||||
sec_cmd_set_default_result(sec);
|
||||
|
||||
data->fod_lp_mode = sec->cmd_param[0];
|
||||
|
||||
input_info(true, &data->client->dev, "%s: fod_lp_mode %d\n", __func__, data->fod_lp_mode);
|
||||
|
||||
snprintf(buf, sizeof(buf), "%s", "OK");
|
||||
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
||||
sec->cmd_state = SEC_CMD_STATUS_OK;
|
||||
sec_cmd_set_cmd_exit(sec);
|
||||
}
|
||||
|
||||
static void get_threshold(void *dev_data)
|
||||
{
|
||||
char buf[16] = { 0 };
|
||||
|
@ -5030,6 +5048,7 @@ struct sec_cmd sec_cmds[] = {
|
|||
{SEC_CMD("get_aod_rect", get_aod_rect),},
|
||||
{SEC_CMD("singletap_enable", singletap_enable),},
|
||||
{SEC_CMD("fod_enable", fod_enable),},
|
||||
{SEC_CMD_H("fod_lp_mode", fod_lp_mode),},
|
||||
{SEC_CMD("get_cp_array", get_cp_array),},
|
||||
{SEC_CMD("get_self_cp_array", get_self_cp_array),},
|
||||
{SEC_CMD("get_prox_cp_array", get_prox_cp_array),},
|
||||
|
|
|
@ -14,5 +14,14 @@ config TOUCHSCREEN_MELFAS_MSS100
|
|||
|
||||
# To compile this driver as a module, choose M here: the module will be called mms_ts.
|
||||
|
||||
config TOUCHSCREEN_MELFAS_MSS100_A30KOR
|
||||
tristate "MELFAS MSS100 Touchscreen"
|
||||
depends on I2C
|
||||
help
|
||||
Say Y here if you have a MELFAS MSS100 touchscreen device in your system.
|
||||
|
||||
# If unsure, say N.
|
||||
|
||||
# To compile this driver as a module, choose M here: the module will be called mms_ts.
|
||||
endif
|
||||
|
||||
|
|
|
@ -3,10 +3,11 @@
|
|||
#
|
||||
|
||||
obj-$(CONFIG_TOUCHSCREEN_MELFAS_MSS100) += melfas_mss100.o melfas_mss100_mod.o melfas_mss100_test.o melfas_mss100_cmd.o melfas_mss100_fw_update.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_MELFAS_MSS100_A30KOR) += melfas_mss100.o melfas_mss100_mod.o melfas_mss100_test.o melfas_mss100_cmd.o melfas_mss100_fw_update.o
|
||||
|
||||
#CFLAGS_melfas_mss100.o += -Wno-unused-variable -Wno-unused-but-set-variable -Wno-unused-function -Wno-unused-label
|
||||
#CFLAGS_melfas_mss100_test.o += -Wno-unused-variable -Wno-unused-but-set-variable -Wno-unused-function -Wno-unused-label
|
||||
#CFLAGS_melfas_mss100_cmd.o += -Wno-unused-variable -Wno-unused-but-set-variable -Wno-unused-function -Wno-unused-label
|
||||
#CFLAGS_melfas_mss100_fw_update.o += -Wno-unused-variable -Wno-unused-but-set-variable -Wno-unused-function -Wno-unused-label
|
||||
|
||||
ccflags-$(CONFIG_SAMSUNG_TUI) += -Idrivers/misc/tui
|
||||
ccflags-$(CONFIG_SAMSUNG_TUI) += -Idrivers/misc/tui
|
||||
|
|
|
@ -445,7 +445,7 @@ static void mms_input_close(struct input_dev *dev)
|
|||
}
|
||||
#endif
|
||||
|
||||
if (info->lowpower_mode) {
|
||||
if (info->lowpower_mode || info->fod_lp_mode) {
|
||||
mms_lowpower_mode(info, TO_LOWPOWER_MODE);
|
||||
if (device_may_wakeup(&info->client->dev))
|
||||
enable_irq_wake(info->client->irq);
|
||||
|
@ -1695,8 +1695,7 @@ static int mms_suspend(struct device *dev)
|
|||
{
|
||||
struct mms_ts_info *info = dev_get_drvdata(dev);
|
||||
|
||||
if (info->lowpower_mode)
|
||||
reinit_completion(&info->resume_done);
|
||||
reinit_completion(&info->resume_done);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1705,8 +1704,7 @@ static int mms_resume(struct device *dev)
|
|||
{
|
||||
struct mms_ts_info *info = dev_get_drvdata(dev);
|
||||
|
||||
if (info->lowpower_mode)
|
||||
complete_all(&info->resume_done);
|
||||
complete_all(&info->resume_done);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -316,6 +316,7 @@ struct mms_ts_info {
|
|||
u8 glove_mode;
|
||||
u8 charger_mode;
|
||||
u8 cover_mode;
|
||||
u8 fod_lp_mode;
|
||||
|
||||
u8 esd_cnt;
|
||||
bool disable_esd;
|
||||
|
|
|
@ -1492,6 +1492,24 @@ err_grip_data:
|
|||
sec_cmd_set_cmd_exit(sec);
|
||||
}
|
||||
|
||||
static void fod_lp_mode(void *device_data)
|
||||
{
|
||||
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||||
struct mms_ts_info *info = container_of(sec, struct mms_ts_info, sec);
|
||||
char buff[64] = { 0 };
|
||||
|
||||
sec_cmd_set_default_result(sec);
|
||||
|
||||
info->fod_lp_mode = sec->cmd_param[0];
|
||||
|
||||
input_info(true, &info->client->dev, "%s: fod_lp_mode %d\n", __func__, info->fod_lp_mode);
|
||||
|
||||
snprintf(buff, sizeof(buff), "%s", "OK");
|
||||
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
||||
sec->cmd_state = SEC_CMD_STATUS_OK;
|
||||
sec_cmd_set_cmd_exit(sec);
|
||||
}
|
||||
|
||||
static void fod_enable(void *device_data)
|
||||
{
|
||||
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
|
||||
|
@ -1964,7 +1982,8 @@ static struct sec_cmd sec_cmds[] = {
|
|||
{SEC_CMD_H("aod_enable", aod_enable),},
|
||||
{SEC_CMD_H("singletap_enable", singletap_enable),},
|
||||
{SEC_CMD_H("aot_enable", aot_enable),},
|
||||
{SEC_CMD_H("fod_enable", fod_enable),},
|
||||
{SEC_CMD("fod_enable", fod_enable),},
|
||||
{SEC_CMD_H("fod_lp_mode", fod_lp_mode),},
|
||||
{SEC_CMD("set_aod_rect", set_aod_rect),},
|
||||
{SEC_CMD("get_aod_rect", get_aod_rect),},
|
||||
{SEC_CMD("set_grip_data", set_grip_data),},
|
||||
|
|
|
@ -663,8 +663,22 @@ no_prefetch_cluster:
|
|||
|
||||
static void verity_submit_prefetch(struct dm_verity *v, struct dm_verity_io *io)
|
||||
{
|
||||
sector_t block = io->block;
|
||||
unsigned int n_blocks = io->n_blocks;
|
||||
struct dm_verity_prefetch_work *pw;
|
||||
|
||||
if (v->validated_blocks) {
|
||||
while (n_blocks && test_bit(block, v->validated_blocks)) {
|
||||
block++;
|
||||
n_blocks--;
|
||||
}
|
||||
while (n_blocks && test_bit(block + n_blocks - 1,
|
||||
v->validated_blocks))
|
||||
n_blocks--;
|
||||
if (!n_blocks)
|
||||
return;
|
||||
}
|
||||
|
||||
pw = kmalloc(sizeof(struct dm_verity_prefetch_work),
|
||||
GFP_NOIO | __GFP_NORETRY | __GFP_NOMEMALLOC | __GFP_NOWARN);
|
||||
|
||||
|
@ -673,8 +687,8 @@ static void verity_submit_prefetch(struct dm_verity *v, struct dm_verity_io *io)
|
|||
|
||||
INIT_WORK(&pw->work, verity_prefetch_io);
|
||||
pw->v = v;
|
||||
pw->block = io->block;
|
||||
pw->n_blocks = io->n_blocks;
|
||||
pw->block = block;
|
||||
pw->n_blocks = n_blocks;
|
||||
queue_work(v->verify_wq, &pw->work);
|
||||
}
|
||||
|
||||
|
|
|
@ -4090,7 +4090,7 @@ int fimc_is_ischain_3aa_close(struct fimc_is_device_ischain *device,
|
|||
if (test_bit(FIMC_IS_GROUP_START, &group->state)) {
|
||||
mgwarn("sudden group close", device, group);
|
||||
if (!test_bit(FIMC_IS_ISCHAIN_REPROCESSING, &device->state))
|
||||
fimc_is_itf_sudden_stop_wrap(device, device->instance);
|
||||
fimc_is_itf_sudden_stop_wrap(device, device->instance, group);
|
||||
set_bit(FIMC_IS_GROUP_REQUEST_FSTOP, &group->state);
|
||||
if (test_bit(FIMC_IS_HAL_DEBUG_SUDDEN_DEAD_DETECT, &sysfs_debug.hal_debug_mode)) {
|
||||
msleep(sysfs_debug.hal_debug_delay);
|
||||
|
@ -4101,7 +4101,7 @@ int fimc_is_ischain_3aa_close(struct fimc_is_device_ischain *device,
|
|||
if (group->head && test_bit(FIMC_IS_GROUP_START, &group->head->state)) {
|
||||
mgwarn("sudden group close", device, group);
|
||||
if (!test_bit(FIMC_IS_ISCHAIN_REPROCESSING, &device->state))
|
||||
fimc_is_itf_sudden_stop_wrap(device, device->instance);
|
||||
fimc_is_itf_sudden_stop_wrap(device, device->instance, group);
|
||||
set_bit(FIMC_IS_GROUP_REQUEST_FSTOP, &group->state);
|
||||
if (test_bit(FIMC_IS_HAL_DEBUG_SUDDEN_DEAD_DETECT, &sysfs_debug.hal_debug_mode)) {
|
||||
msleep(sysfs_debug.hal_debug_delay);
|
||||
|
@ -4382,7 +4382,7 @@ int fimc_is_ischain_isp_close(struct fimc_is_device_ischain *device,
|
|||
if (test_bit(FIMC_IS_GROUP_START, &group->state)) {
|
||||
mgwarn("sudden group close", device, group);
|
||||
if (!test_bit(FIMC_IS_ISCHAIN_REPROCESSING, &device->state))
|
||||
fimc_is_itf_sudden_stop_wrap(device, device->instance);
|
||||
fimc_is_itf_sudden_stop_wrap(device, device->instance, group);
|
||||
set_bit(FIMC_IS_GROUP_REQUEST_FSTOP, &group->state);
|
||||
if (test_bit(FIMC_IS_HAL_DEBUG_SUDDEN_DEAD_DETECT, &sysfs_debug.hal_debug_mode)) {
|
||||
msleep(sysfs_debug.hal_debug_delay);
|
||||
|
@ -4393,7 +4393,7 @@ int fimc_is_ischain_isp_close(struct fimc_is_device_ischain *device,
|
|||
if (group->head && test_bit(FIMC_IS_GROUP_START, &group->head->state)) {
|
||||
mgwarn("sudden group close", device, group);
|
||||
if (!test_bit(FIMC_IS_ISCHAIN_REPROCESSING, &device->state))
|
||||
fimc_is_itf_sudden_stop_wrap(device, device->instance);
|
||||
fimc_is_itf_sudden_stop_wrap(device, device->instance, group);
|
||||
set_bit(FIMC_IS_GROUP_REQUEST_FSTOP, &group->state);
|
||||
if (test_bit(FIMC_IS_HAL_DEBUG_SUDDEN_DEAD_DETECT, &sysfs_debug.hal_debug_mode)) {
|
||||
msleep(sysfs_debug.hal_debug_delay);
|
||||
|
@ -4676,7 +4676,7 @@ int fimc_is_ischain_dis_close(struct fimc_is_device_ischain *device,
|
|||
if (test_bit(FIMC_IS_GROUP_START, &group->state)) {
|
||||
mgwarn("sudden group close", device, group);
|
||||
if (!test_bit(FIMC_IS_ISCHAIN_REPROCESSING, &device->state))
|
||||
fimc_is_itf_sudden_stop_wrap(device, device->instance);
|
||||
fimc_is_itf_sudden_stop_wrap(device, device->instance, group);
|
||||
set_bit(FIMC_IS_GROUP_REQUEST_FSTOP, &group->state);
|
||||
if (test_bit(FIMC_IS_HAL_DEBUG_SUDDEN_DEAD_DETECT, &sysfs_debug.hal_debug_mode)) {
|
||||
msleep(sysfs_debug.hal_debug_delay);
|
||||
|
@ -4687,7 +4687,7 @@ int fimc_is_ischain_dis_close(struct fimc_is_device_ischain *device,
|
|||
if (group->head && test_bit(FIMC_IS_GROUP_START, &group->head->state)) {
|
||||
mgwarn("sudden group close", device, group);
|
||||
if (!test_bit(FIMC_IS_ISCHAIN_REPROCESSING, &device->state))
|
||||
fimc_is_itf_sudden_stop_wrap(device, device->instance);
|
||||
fimc_is_itf_sudden_stop_wrap(device, device->instance, group);
|
||||
set_bit(FIMC_IS_GROUP_REQUEST_FSTOP, &group->state);
|
||||
if (test_bit(FIMC_IS_HAL_DEBUG_SUDDEN_DEAD_DETECT, &sysfs_debug.hal_debug_mode)) {
|
||||
msleep(sysfs_debug.hal_debug_delay);
|
||||
|
@ -4970,7 +4970,7 @@ int fimc_is_ischain_mcs_close(struct fimc_is_device_ischain *device,
|
|||
if (test_bit(FIMC_IS_GROUP_START, &group->state)) {
|
||||
mgwarn("sudden group close", device, group);
|
||||
if (!test_bit(FIMC_IS_ISCHAIN_REPROCESSING, &device->state))
|
||||
fimc_is_itf_sudden_stop_wrap(device, device->instance);
|
||||
fimc_is_itf_sudden_stop_wrap(device, device->instance, group);
|
||||
set_bit(FIMC_IS_GROUP_REQUEST_FSTOP, &group->state);
|
||||
if (test_bit(FIMC_IS_HAL_DEBUG_SUDDEN_DEAD_DETECT, &sysfs_debug.hal_debug_mode)) {
|
||||
msleep(sysfs_debug.hal_debug_delay);
|
||||
|
@ -4981,7 +4981,7 @@ int fimc_is_ischain_mcs_close(struct fimc_is_device_ischain *device,
|
|||
if (group->head && test_bit(FIMC_IS_GROUP_START, &group->head->state)) {
|
||||
mgwarn("sudden group close", device, group);
|
||||
if (!test_bit(FIMC_IS_ISCHAIN_REPROCESSING, &device->state))
|
||||
fimc_is_itf_sudden_stop_wrap(device, device->instance);
|
||||
fimc_is_itf_sudden_stop_wrap(device, device->instance, group);
|
||||
set_bit(FIMC_IS_GROUP_REQUEST_FSTOP, &group->state);
|
||||
if (test_bit(FIMC_IS_HAL_DEBUG_SUDDEN_DEAD_DETECT, &sysfs_debug.hal_debug_mode)) {
|
||||
msleep(sysfs_debug.hal_debug_delay);
|
||||
|
@ -5258,7 +5258,7 @@ int fimc_is_ischain_vra_close(struct fimc_is_device_ischain *device,
|
|||
if (test_bit(FIMC_IS_GROUP_START, &group->state)) {
|
||||
mgwarn("sudden group close", device, group);
|
||||
if (!test_bit(FIMC_IS_ISCHAIN_REPROCESSING, &device->state))
|
||||
fimc_is_itf_sudden_stop_wrap(device, device->instance);
|
||||
fimc_is_itf_sudden_stop_wrap(device, device->instance, group);
|
||||
set_bit(FIMC_IS_GROUP_REQUEST_FSTOP, &group->state);
|
||||
if (test_bit(FIMC_IS_HAL_DEBUG_SUDDEN_DEAD_DETECT, &sysfs_debug.hal_debug_mode)) {
|
||||
msleep(sysfs_debug.hal_debug_delay);
|
||||
|
@ -5269,7 +5269,7 @@ int fimc_is_ischain_vra_close(struct fimc_is_device_ischain *device,
|
|||
if (group->head && test_bit(FIMC_IS_GROUP_START, &group->head->state)) {
|
||||
mgwarn("sudden group close", device, group);
|
||||
if (!test_bit(FIMC_IS_ISCHAIN_REPROCESSING, &device->state))
|
||||
fimc_is_itf_sudden_stop_wrap(device, device->instance);
|
||||
fimc_is_itf_sudden_stop_wrap(device, device->instance, group);
|
||||
set_bit(FIMC_IS_GROUP_REQUEST_FSTOP, &group->state);
|
||||
if (test_bit(FIMC_IS_HAL_DEBUG_SUDDEN_DEAD_DETECT, &sysfs_debug.hal_debug_mode)) {
|
||||
msleep(sysfs_debug.hal_debug_delay);
|
||||
|
|
|
@ -429,7 +429,7 @@ int fimc_is_itf_process_off_wrap(struct fimc_is_device_ischain *device, u32 grou
|
|||
return ret;
|
||||
}
|
||||
|
||||
void fimc_is_itf_sudden_stop_wrap(struct fimc_is_device_ischain *device, u32 instance)
|
||||
void fimc_is_itf_sudden_stop_wrap(struct fimc_is_device_ischain *device, u32 instance, struct fimc_is_group *group)
|
||||
{
|
||||
int ret = 0;
|
||||
struct fimc_is_device_sensor *sensor;
|
||||
|
@ -453,6 +453,18 @@ void fimc_is_itf_sudden_stop_wrap(struct fimc_is_device_ischain *device, u32 ins
|
|||
merr("fimc_is_sensor_front_stop is fail(%d)", sensor, ret);
|
||||
}
|
||||
|
||||
if (group) {
|
||||
if (test_bit(FIMC_IS_GROUP_FORCE_STOP, &group->state)) {
|
||||
ret = fimc_is_itf_force_stop(device, GROUP_ID(group->id));
|
||||
if (ret)
|
||||
mgerr("fimc_is_itf_force_stop is fail(%d)", device, group, ret);
|
||||
} else {
|
||||
ret = fimc_is_itf_process_stop(device, GROUP_ID(group->id));
|
||||
if (ret)
|
||||
mgerr("fimc_is_itf_process_stop is fail(%d)", device, group, ret);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -472,7 +484,7 @@ int fimc_is_itf_power_down_wrap(struct fimc_is_interface *interface, u32 instanc
|
|||
return ret;
|
||||
}
|
||||
|
||||
fimc_is_itf_sudden_stop_wrap(&core->ischain[instance], instance);
|
||||
fimc_is_itf_sudden_stop_wrap(&core->ischain[instance], instance, NULL);
|
||||
|
||||
#ifdef USE_DDK_SHUT_DOWN_FUNC
|
||||
#ifdef ENABLE_FPSIMD_FOR_USER
|
||||
|
|
|
@ -40,7 +40,7 @@ int fimc_is_itf_stream_off_wrap(struct fimc_is_device_ischain *device);
|
|||
int fimc_is_itf_process_on_wrap(struct fimc_is_device_ischain *device, u32 group);
|
||||
int fimc_is_itf_process_off_wrap(struct fimc_is_device_ischain *device, u32 group,
|
||||
u32 fstop);
|
||||
void fimc_is_itf_sudden_stop_wrap(struct fimc_is_device_ischain *device, u32 instance);
|
||||
void fimc_is_itf_sudden_stop_wrap(struct fimc_is_device_ischain *device, u32 instance, struct fimc_is_group *group);
|
||||
int fimc_is_itf_power_down_wrap(struct fimc_is_interface *interface, u32 instance);
|
||||
int fimc_is_itf_sys_ctl_wrap(struct fimc_is_device_ischain *device,
|
||||
int cmd, int val);
|
||||
|
|
|
@ -1571,13 +1571,22 @@ int fimc_is_hw_mcsc_poly_phase(struct fimc_is_hw_ip *hw_ip, struct param_mcs_inp
|
|||
fimc_is_scaler_set_poly_src_size(hw_ip->regs, output_id, src_pos_x, src_pos_y,
|
||||
src_width, src_height);
|
||||
|
||||
if ((src_width <= (out_width * MCSC_POLY_RATIO_DOWN))
|
||||
&& (out_width <= (src_width * MCSC_POLY_RATIO_UP))) {
|
||||
if (((src_width <= (out_width * MCSC_POLY_QUALITY_RATIO_DOWN))
|
||||
&& (out_width <= (src_width * MCSC_POLY_RATIO_UP)))
|
||||
|| (output_id == MCSC_OUTPUT3 || output_id == MCSC_OUTPUT4)) {
|
||||
poly_dst_width = out_width;
|
||||
post_en = false;
|
||||
} else if ((src_width <= (out_width * MCSC_POLY_QUALITY_RATIO_DOWN * MCSC_POST_RATIO_DOWN))
|
||||
&& ((out_width * MCSC_POLY_QUALITY_RATIO_DOWN) < src_width)) {
|
||||
poly_dst_width = MCSC_ROUND_UP(src_width / MCSC_POLY_QUALITY_RATIO_DOWN, 2);
|
||||
if (poly_dst_width > MCSC_POST_MAX_WIDTH)
|
||||
poly_dst_width = MCSC_POST_MAX_WIDTH;
|
||||
post_en = true;
|
||||
} else if ((src_width <= (out_width * MCSC_POLY_RATIO_DOWN * MCSC_POST_RATIO_DOWN))
|
||||
&& ((out_width * MCSC_POLY_RATIO_DOWN) < src_width)) {
|
||||
poly_dst_width = MCSC_ROUND_UP(src_width / MCSC_POLY_RATIO_DOWN, 2);
|
||||
&& ((out_width * MCSC_POLY_QUALITY_RATIO_DOWN * MCSC_POST_RATIO_DOWN) < src_width)) {
|
||||
poly_dst_width = MCSC_ROUND_UP(out_width * MCSC_POST_RATIO_DOWN, 2);
|
||||
if (poly_dst_width > MCSC_POST_MAX_WIDTH)
|
||||
poly_dst_width = MCSC_POST_MAX_WIDTH;
|
||||
post_en = true;
|
||||
} else {
|
||||
mserr_hw("hw_mcsc_poly_phase: Unsupported H ratio, (%dx%d)->(%dx%d)\n",
|
||||
|
@ -1586,16 +1595,21 @@ int fimc_is_hw_mcsc_poly_phase(struct fimc_is_hw_ip *hw_ip, struct param_mcs_inp
|
|||
post_en = true;
|
||||
}
|
||||
|
||||
if ((src_height <= (out_height * MCSC_POLY_RATIO_DOWN))
|
||||
&& (out_height <= (src_height * MCSC_POLY_RATIO_UP))) {
|
||||
if (((src_height <= (out_height * MCSC_POLY_QUALITY_RATIO_DOWN))
|
||||
&& (out_height <= (src_height * MCSC_POLY_RATIO_UP)))
|
||||
|| (output_id == MCSC_OUTPUT3 || output_id == MCSC_OUTPUT4)) {
|
||||
poly_dst_height = out_height;
|
||||
post_en = false;
|
||||
} else if ((src_height <= (out_height * MCSC_POLY_QUALITY_RATIO_DOWN * MCSC_POST_RATIO_DOWN))
|
||||
&& ((out_height * MCSC_POLY_QUALITY_RATIO_DOWN) < src_height)) {
|
||||
poly_dst_height = (src_height / MCSC_POLY_QUALITY_RATIO_DOWN);
|
||||
post_en = true;
|
||||
} else if ((src_height <= (out_height * MCSC_POLY_RATIO_DOWN * MCSC_POST_RATIO_DOWN))
|
||||
&& ((out_height * MCSC_POLY_RATIO_DOWN) < src_height)) {
|
||||
poly_dst_height = (src_height / MCSC_POLY_RATIO_DOWN);
|
||||
&& ((out_height * MCSC_POLY_QUALITY_RATIO_DOWN * MCSC_POST_RATIO_DOWN) < src_height)) {
|
||||
poly_dst_height = (out_height * MCSC_POST_RATIO_DOWN);
|
||||
post_en = true;
|
||||
} else {
|
||||
mserr_hw("hw_mcsc_poly_phase: Unsupported H ratio, (%dx%d)->(%dx%d)\n",
|
||||
mserr_hw("hw_mcsc_poly_phase: Unsupported V ratio, (%dx%d)->(%dx%d)\n",
|
||||
instance, hw_ip, src_width, src_height, out_width, out_height);
|
||||
poly_dst_height = (src_height / MCSC_POLY_RATIO_DOWN);
|
||||
post_en = true;
|
||||
|
|
|
@ -93,12 +93,15 @@ enum hwip_interrupt_map {
|
|||
/* Specific interrupt map belonged to each IP */
|
||||
|
||||
/* MC-Scaler */
|
||||
#define MCSC_INTR_MASK (0x00000034)
|
||||
#define USE_DMA_BUFFER_INDEX (0) /* 0 ~ 7 */
|
||||
#define MCSC_PRECISION (20)
|
||||
#define MCSC_POLY_RATIO_UP (8)
|
||||
#define MCSC_POLY_RATIO_DOWN (16)
|
||||
#define MCSC_POST_RATIO_DOWN (16)
|
||||
#define MCSC_INTR_MASK (0x00000034)
|
||||
#define USE_DMA_BUFFER_INDEX (0) /* 0 ~ 7 */
|
||||
#define MCSC_PRECISION (20)
|
||||
#define MCSC_POLY_RATIO_UP (8)
|
||||
#define MCSC_POLY_QUALITY_RATIO_DOWN (4)
|
||||
#define MCSC_POLY_RATIO_DOWN (16)
|
||||
#define MCSC_POLY_MAX_RATIO_DOWN (256)
|
||||
#define MCSC_POST_RATIO_DOWN (16)
|
||||
#define MCSC_POST_MAX_WIDTH (1344)
|
||||
/* #define MCSC_POST_WA */
|
||||
#define MCSC_POST_WA_SHIFT (8) /* 256 = 2^8 */
|
||||
|
||||
|
|
|
@ -200,6 +200,7 @@ static int sensor_zc535_init_position(struct i2c_client *client,
|
|||
int i;
|
||||
int ret = 0;
|
||||
int init_step = 0;
|
||||
int init_delay_us = 0;
|
||||
|
||||
init_step = sensor_zc535_valid_check(client);
|
||||
|
||||
|
@ -209,7 +210,10 @@ static int sensor_zc535_init_position(struct i2c_client *client,
|
|||
if (ret < 0)
|
||||
goto p_err;
|
||||
|
||||
mdelay(sysfs_actuator.init_delays[i]);
|
||||
//mdelay(sysfs_actuator.init_delays[i]);
|
||||
init_delay_us = sysfs_actuator.init_delays[i] * 1000;
|
||||
usleep_range(init_delay_us, init_delay_us);
|
||||
init_delay_us = 0;
|
||||
}
|
||||
|
||||
actuator->position = sysfs_actuator.init_positions[i];
|
||||
|
@ -221,13 +225,15 @@ static int sensor_zc535_init_position(struct i2c_client *client,
|
|||
if (ret < 0)
|
||||
goto p_err;
|
||||
|
||||
mdelay(DEF_ZC535_FIRST_DELAY_MS);
|
||||
//mdelay(DEF_ZC535_FIRST_DELAY_MS);
|
||||
usleep_range((DEF_ZC535_FIRST_DELAY_MS*1000), (DEF_ZC535_FIRST_DELAY_MS*1000));
|
||||
|
||||
ret = sensor_zc535_write_position(client, DEF_ZC535_SECOND_POSITION);
|
||||
if (ret < 0)
|
||||
goto p_err;
|
||||
|
||||
mdelay(DEF_ZC535_SECOND_DELAY_MS);
|
||||
//mdelay(DEF_ZC535_SECOND_DELAY_MS);
|
||||
usleep_range((DEF_ZC535_SECOND_DELAY_MS*1000), (DEF_ZC535_SECOND_DELAY_MS*1000));
|
||||
|
||||
actuator->position = DEF_ZC535_SECOND_POSITION;
|
||||
|
||||
|
|
|
@ -1790,10 +1790,13 @@ int sensor_3l6_cis_wait_streamoff(struct v4l2_subdev *subdev)
|
|||
dbg_sensor(1, "[MOD:D:%d] %s, sensor_fcount(%d), (wait_limit(%d) < time_out(%d))\n",
|
||||
cis->id, __func__, sensor_fcount, wait_cnt, time_out_cnt);
|
||||
}
|
||||
#if defined(CONFIG_CAMERA_AAS_V20E)
|
||||
msleep(7);
|
||||
#endif
|
||||
|
||||
do_gettimeofday (&t_end);
|
||||
|
||||
u_delay = (t_end.tv_sec * 1000000 + t_end.tv_usec) - (t_start.tv_sec * 1000000 + t_start.tv_usec);
|
||||
u_delay = (t_end.tv_sec * 1000000 + t_end.tv_usec) - (t_start.tv_sec * 1000000 + t_start.tv_usec);
|
||||
info("%s:%d timediff min_delay[%ld] u_delay[%ld][required_sleep[%ld]] sensor_fcount(%d)\n", __func__, __LINE__,
|
||||
min_delay, u_delay, min_delay - u_delay, sensor_fcount);
|
||||
|
||||
|
|
|
@ -1033,6 +1033,47 @@ void fimc_is_sensor_flash_expire_work(struct work_struct *data)
|
|||
}
|
||||
}
|
||||
|
||||
void fimc_is_sensor_flash_muic_ctrl_and_fire(struct work_struct *data)
|
||||
{
|
||||
#if defined(CONFIG_LEDS_S2MU106_FLASH)
|
||||
struct fimc_is_flash *flash;
|
||||
struct fimc_is_flash_data *flash_data;
|
||||
struct fimc_is_device_sensor_peri *sensor_peri;
|
||||
|
||||
FIMC_BUG_VOID(!data);
|
||||
|
||||
flash_data = container_of(data, struct fimc_is_flash_data,
|
||||
work_flash_muic_ctrl_and_fire);
|
||||
FIMC_BUG_VOID(!flash_data);
|
||||
|
||||
flash = container_of(flash_data, struct fimc_is_flash, flash_data);
|
||||
FIMC_BUG_VOID(!flash);
|
||||
|
||||
sensor_peri = flash->sensor_peri;
|
||||
|
||||
/* Pre-flash on */
|
||||
if (flash->flash_data.mode == 3) {
|
||||
muic_afc_set_voltage(5);
|
||||
pdo_ctrl_by_flash(1);
|
||||
info("[%s]%d Down Volatge set On \n" ,__func__,__LINE__);
|
||||
}
|
||||
|
||||
info("[%s] pre-flash mode(%d), pow(%d), time(%d)\n", __func__,
|
||||
flash->flash_data.mode,
|
||||
flash->flash_data.intensity, flash->flash_data.firing_time_us);
|
||||
|
||||
/* If pre-flash on failed, set voltage to 9V */
|
||||
if (fimc_is_sensor_flash_fire(sensor_peri, flash->flash_data.intensity)) {
|
||||
err("failed to turn off flash at flash expired handler\n");
|
||||
if(flash->flash_data.mode == 3) {
|
||||
pdo_ctrl_by_flash(0);
|
||||
muic_afc_set_voltage(9);
|
||||
info("[%s]%d Down Volatge set Clear \n" ,__func__,__LINE__);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int fimc_is_sensor_flash_fire(struct fimc_is_device_sensor_peri *device,
|
||||
u32 on)
|
||||
{
|
||||
|
@ -1369,27 +1410,12 @@ int fimc_is_sensor_peri_pre_flash_fire(struct v4l2_subdev *subdev, void *arg)
|
|||
flash->flash_data.firing_time_us = flash_uctl->firingTime;
|
||||
|
||||
#if defined(CONFIG_LEDS_S2MU106_FLASH)
|
||||
/* Pre-flash on */
|
||||
if(flash->flash_data.mode == 3) {
|
||||
muic_afc_set_voltage(5);
|
||||
pdo_ctrl_by_flash(1);
|
||||
info("[%s]%d Down Volatge set On \n" ,__func__,__LINE__);
|
||||
}
|
||||
#endif
|
||||
schedule_work(&sensor_peri->flash->flash_data.work_flash_muic_ctrl_and_fire);
|
||||
#else
|
||||
info("[%s](%d) pre-flash mode(%d), pow(%d), time(%d)\n", __func__,
|
||||
vsync_count, flash->flash_data.mode,
|
||||
flash->flash_data.intensity, flash->flash_data.firing_time_us);
|
||||
ret = fimc_is_sensor_flash_fire(sensor_peri, flash->flash_data.intensity);
|
||||
#if defined(CONFIG_LEDS_S2MU106_FLASH)
|
||||
/* If pre-flash on failed, set voltage to 9V */
|
||||
if (ret) {
|
||||
err("failed to turn off flash at flash expired handler\n");
|
||||
if(flash->flash_data.mode == 3) {
|
||||
pdo_ctrl_by_flash(0);
|
||||
muic_afc_set_voltage(9);
|
||||
info("[%s]%d Down Volatge set Clear \n" ,__func__,__LINE__);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -1617,6 +1643,8 @@ void fimc_is_sensor_peri_init_work(struct fimc_is_device_sensor_peri *sensor_per
|
|||
if (sensor_peri->flash) {
|
||||
INIT_WORK(&sensor_peri->flash->flash_data.flash_fire_work, fimc_is_sensor_flash_fire_work);
|
||||
INIT_WORK(&sensor_peri->flash->flash_data.flash_expire_work, fimc_is_sensor_flash_expire_work);
|
||||
INIT_WORK(&sensor_peri->flash->flash_data.work_flash_muic_ctrl_and_fire,
|
||||
fimc_is_sensor_flash_muic_ctrl_and_fire);
|
||||
}
|
||||
|
||||
INIT_WORK(&sensor_peri->cis.cis_status_dump_work, fimc_is_sensor_cis_status_dump_work);
|
||||
|
@ -2382,7 +2410,7 @@ int fimc_is_sensor_peri_actuator_softlanding(struct fimc_is_device_sensor_peri *
|
|||
actuator_itf->hw_pos = soft_landing_table->hw_table[i];
|
||||
|
||||
/* The actuator needs a delay time when lens moving for soft landing. */
|
||||
mdelay(soft_landing_table->step_delay);
|
||||
msleep(soft_landing_table->step_delay);
|
||||
|
||||
ret = fimc_is_sensor_peri_actuator_check_move_done(device);
|
||||
if (ret) {
|
||||
|
|
|
@ -182,6 +182,7 @@ struct fimc_is_flash_data {
|
|||
struct work_struct flash_fire_work;
|
||||
struct timer_list flash_expire_timer;
|
||||
struct work_struct flash_expire_work;
|
||||
struct work_struct work_flash_muic_ctrl_and_fire;
|
||||
};
|
||||
|
||||
struct fimc_is_flash {
|
||||
|
|
|
@ -200,6 +200,7 @@ static int sensor_zc535_init_position(struct i2c_client *client,
|
|||
int i;
|
||||
int ret = 0;
|
||||
int init_step = 0;
|
||||
int init_delay_us = 0;
|
||||
|
||||
init_step = sensor_zc535_valid_check(client);
|
||||
|
||||
|
@ -209,7 +210,10 @@ static int sensor_zc535_init_position(struct i2c_client *client,
|
|||
if (ret < 0)
|
||||
goto p_err;
|
||||
|
||||
mdelay(sysfs_actuator.init_delays[i]);
|
||||
//mdelay(sysfs_actuator.init_delays[i]);
|
||||
init_delay_us = sysfs_actuator.init_delays[i] * 1000;
|
||||
usleep_range(init_delay_us, init_delay_us);
|
||||
init_delay_us = 0;
|
||||
}
|
||||
|
||||
actuator->position = sysfs_actuator.init_positions[i];
|
||||
|
@ -221,13 +225,15 @@ static int sensor_zc535_init_position(struct i2c_client *client,
|
|||
if (ret < 0)
|
||||
goto p_err;
|
||||
|
||||
mdelay(DEF_ZC535_FIRST_DELAY_MS);
|
||||
//mdelay(DEF_ZC535_FIRST_DELAY_MS);
|
||||
usleep_range((DEF_ZC535_FIRST_DELAY_MS*1000), (DEF_ZC535_FIRST_DELAY_MS*1000));
|
||||
|
||||
ret = sensor_zc535_write_position(client, DEF_ZC535_SECOND_POSITION);
|
||||
if (ret < 0)
|
||||
goto p_err;
|
||||
|
||||
mdelay(DEF_ZC535_SECOND_DELAY_MS);
|
||||
//mdelay(DEF_ZC535_SECOND_DELAY_MS);
|
||||
usleep_range((DEF_ZC535_SECOND_DELAY_MS*1000), (DEF_ZC535_SECOND_DELAY_MS*1000));
|
||||
|
||||
actuator->position = DEF_ZC535_SECOND_POSITION;
|
||||
|
||||
|
|
|
@ -1793,6 +1793,8 @@ int fimc_is_sensor_peri_s_stream(struct fimc_is_device_sensor *device,
|
|||
memset(&sensor_peri->cis.sensor_ctls[i].cur_cam20_sensor_udctrl, 0, sizeof(camera2_sensor_uctl_t));
|
||||
sensor_peri->cis.sensor_ctls[i].valid_sensor_ctrl = 0;
|
||||
sensor_peri->cis.sensor_ctls[i].force_update = false;
|
||||
memset(&sensor_peri->cis.sensor_ctls[i].cur_cam20_flash_udctrl, 0, sizeof(camera2_flash_uctl_t));
|
||||
sensor_peri->cis.sensor_ctls[i].valid_flash_udctrl = false;
|
||||
}
|
||||
sensor_peri->use_sensor_work = false;
|
||||
}
|
||||
|
@ -2300,7 +2302,7 @@ int fimc_is_sensor_peri_actuator_softlanding(struct fimc_is_device_sensor_peri *
|
|||
actuator_itf->hw_pos = soft_landing_table->hw_table[i];
|
||||
|
||||
/* The actuator needs a delay time when lens moving for soft landing. */
|
||||
mdelay(soft_landing_table->step_delay);
|
||||
msleep(soft_landing_table->step_delay);
|
||||
|
||||
ret = fimc_is_sensor_peri_actuator_check_move_done(device);
|
||||
if (ret) {
|
||||
|
|
|
@ -1675,7 +1675,7 @@ bool fm_aux_pll_initialize(void)
|
|||
void fm_ds_set(u32 data)
|
||||
{
|
||||
fmspeedy_set_reg_field(0xFFF390, 7, (0x0003 << 7), data);
|
||||
mdelay(10);
|
||||
msleep(10);
|
||||
dev_info(gradio->v4l2dev.dev,
|
||||
"%s: DS set: 0x%xh, reg val: 0x%xh\n", __func__,
|
||||
data, fmspeedy_get_reg(0xFFF390));
|
||||
|
|
|
@ -549,7 +549,7 @@ static long misc_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
|||
return -EINVAL;
|
||||
}
|
||||
gc->ops.gnss_release_reset(gc);
|
||||
mdelay(50);
|
||||
msleep(50);
|
||||
return 0;
|
||||
|
||||
case GNSS_IOCTL_REQ_FAULT_INFO:
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include <linux/exynos-ss.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/smc.h>
|
||||
#include <linux/sec_debug.h>
|
||||
#include <soc/samsung/pmu-cp.h>
|
||||
#include <soc/samsung/exynos-modem-ctrl.h>
|
||||
|
||||
|
@ -1238,7 +1239,17 @@ void mif_set_snapshot(bool enable)
|
|||
{
|
||||
if (!enable)
|
||||
acpm_stop_log();
|
||||
exynos_ss_set_enable("log_kevents", enable);
|
||||
|
||||
#ifdef CONFIG_SEC_DEBUG
|
||||
#ifdef CONFIG_SEC_DEBUG_SNAPSHOT_DISABLE
|
||||
if (sec_debug_get_debug_level() == 0)
|
||||
pr_err("%s: log_kevents disabled by debug level\n", __func__);
|
||||
else
|
||||
#endif
|
||||
#endif
|
||||
{
|
||||
exynos_ss_set_enable("log_kevents", enable);
|
||||
}
|
||||
}
|
||||
|
||||
struct mif_buff_mng *init_mif_buff_mng(unsigned char *buffer_start,
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
****************************************************************************/
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/wakelock.h>
|
||||
#include <linux/string.h>
|
||||
|
||||
#include "scsc_wlbtd.h"
|
||||
|
||||
|
@ -15,6 +16,8 @@
|
|||
*/
|
||||
#define MAX_TIMEOUT 18000 /* in milisecounds */
|
||||
#define WRITE_FILE_TIMEOUT 1000 /* in milisecounds */
|
||||
#define MAX_RSP_STRING_SIZE 128
|
||||
#define PROP_VALUE_MAX 92
|
||||
|
||||
/* completion to indicate when moredump is done */
|
||||
static DECLARE_COMPLETION(event_done);
|
||||
|
@ -30,7 +33,7 @@ static struct wake_lock wlbtd_wakelock;
|
|||
/* module parameter controlling recovery handling */
|
||||
extern int disable_recovery_handling;
|
||||
|
||||
const char *response_code_to_str(int response_code)
|
||||
const char *response_code_to_str(enum scsc_wlbtd_response_codes response_code)
|
||||
{
|
||||
switch (response_code) {
|
||||
case SCSC_WLBTD_ERR_PARSE_FAILED:
|
||||
|
@ -74,35 +77,50 @@ const char *response_code_to_str(int response_code)
|
|||
*/
|
||||
static int msg_from_wlbtd_cb(struct sk_buff *skb, struct genl_info *info)
|
||||
{
|
||||
int status = 0;
|
||||
unsigned int status = 0;
|
||||
int ret_code = 0;
|
||||
|
||||
if (info->attrs[1])
|
||||
SCSC_TAG_INFO(WLBTD, "ATTR_STR: %s\n",
|
||||
(char *)nla_data(info->attrs[1]));
|
||||
if (!info || !info->attrs[1] || !info->attrs[2] ||
|
||||
(nla_len(info->attrs[1]) > MAX_RSP_STRING_SIZE) ||
|
||||
(nla_len(info->attrs[2]) < sizeof(status))) {
|
||||
|
||||
if (info->attrs[2]) {
|
||||
status = *((__u32 *)nla_data(info->attrs[2]));
|
||||
if (status)
|
||||
SCSC_TAG_ERR(WLBTD, "ATTR_INT: %u\n", status);
|
||||
SCSC_TAG_ERR(WLBTD, "Error parsing arguments\n");
|
||||
ret_code = -EINVAL;
|
||||
goto error_complete;
|
||||
}
|
||||
|
||||
SCSC_TAG_INFO(WLBTD, "ATTR_STR: %s\n", (char *)nla_data(info->attrs[1]));
|
||||
|
||||
status = nla_get_u32(info->attrs[2]);
|
||||
if (status)
|
||||
SCSC_TAG_INFO(WLBTD, "ATTR_INT: %u\n", status);
|
||||
|
||||
error_complete:
|
||||
if (!completion_done(&event_done))
|
||||
complete(&event_done);
|
||||
|
||||
return 0;
|
||||
return ret_code;
|
||||
}
|
||||
|
||||
static int msg_from_wlbtd_sable_cb(struct sk_buff *skb, struct genl_info *info)
|
||||
{
|
||||
int status = 0;
|
||||
const char *data = (const char *)nla_data(info->attrs[1]);
|
||||
unsigned short status;
|
||||
|
||||
if (info->attrs[1])
|
||||
SCSC_TAG_INFO(WLBTD, "%s\n", data);
|
||||
if (!info || !info->attrs[1] || !info->attrs[2] ||
|
||||
(nla_len(info->attrs[1]) > MAX_RSP_STRING_SIZE) ||
|
||||
(nla_len(info->attrs[2]) < sizeof(status))) {
|
||||
|
||||
if (info->attrs[2]) {
|
||||
status = nla_get_u16(info->attrs[2]);
|
||||
SCSC_TAG_ERR(WLBTD, "%s\n", response_code_to_str(status));
|
||||
SCSC_TAG_ERR(WLBTD, "Error parsing arguments\n");
|
||||
goto error_complete;
|
||||
}
|
||||
|
||||
SCSC_TAG_INFO(WLBTD, "%s\n", (char *)nla_data(info->attrs[1]));
|
||||
status = nla_get_u16(info->attrs[2]);
|
||||
|
||||
if ((enum scsc_wlbtd_response_codes)status < SCSC_WLBTD_LAST_RESPONSE_CODE)
|
||||
SCSC_TAG_ERR(WLBTD, "%s\n", response_code_to_str((enum scsc_wlbtd_response_codes)status));
|
||||
else {
|
||||
SCSC_TAG_INFO(WLBTD, "Received invalid status value");
|
||||
goto error_complete;
|
||||
}
|
||||
|
||||
/* completion cases :
|
||||
|
@ -174,35 +192,74 @@ static int msg_from_wlbtd_sable_cb(struct sk_buff *skb, struct genl_info *info)
|
|||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error_complete:
|
||||
if (!completion_done(&fw_panic_done)) {
|
||||
SCSC_TAG_INFO(WLBTD, "completing fw_panic_done\n");
|
||||
complete(&fw_panic_done);
|
||||
}
|
||||
if (!completion_done(&event_done)) {
|
||||
SCSC_TAG_INFO(WLBTD, "completing event_done\n");
|
||||
complete(&event_done);
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int msg_from_wlbtd_build_type_cb(struct sk_buff *skb, struct genl_info *info)
|
||||
{
|
||||
char *build_type_str = NULL;
|
||||
|
||||
mutex_lock(&build_type_lock);
|
||||
if (build_type) {
|
||||
SCSC_TAG_INFO(WLBTD, "ro.build.type = %s\n", build_type);
|
||||
mutex_unlock(&build_type_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!info) {
|
||||
SCSC_TAG_ERR(WLBTD, "info is NULL\n");
|
||||
mutex_unlock(&build_type_lock);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!info->attrs[1]) {
|
||||
SCSC_TAG_WARNING(WLBTD, "info->attrs[1] = NULL\n");
|
||||
return -1;
|
||||
SCSC_TAG_ERR(WLBTD, "info->attrs[1] = NULL\n");
|
||||
mutex_unlock(&build_type_lock);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!nla_len(info->attrs[1])) {
|
||||
SCSC_TAG_WARNING(WLBTD, "nla_len = 0\n");
|
||||
return -1;
|
||||
SCSC_TAG_ERR(WLBTD, "nla_len = 0\n");
|
||||
mutex_unlock(&build_type_lock);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mutex_lock(&build_type_lock);
|
||||
if (build_type) {
|
||||
SCSC_TAG_WARNING(WLBTD, "ro.build.type = %s\n", build_type);
|
||||
if (nla_len(info->attrs[1]) > PROP_VALUE_MAX) {
|
||||
SCSC_TAG_ERR(WLBTD, "Received invalid length of data\n");
|
||||
mutex_unlock(&build_type_lock);
|
||||
return 0;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* nla_len includes trailing zero. Tested.*/
|
||||
build_type = kmalloc(info->attrs[1]->nla_len, GFP_KERNEL);
|
||||
build_type = kmalloc(nla_len(info->attrs[1]), GFP_KERNEL);
|
||||
if (!build_type) {
|
||||
SCSC_TAG_WARNING(WLBTD, "kmalloc failed: build_type = NULL\n");
|
||||
SCSC_TAG_ERR(WLBTD, "kmalloc failed: build_type = NULL\n");
|
||||
mutex_unlock(&build_type_lock);
|
||||
return -1;
|
||||
return -ENOMEM;
|
||||
}
|
||||
memcpy(build_type, (char *)nla_data(info->attrs[1]), info->attrs[1]->nla_len);
|
||||
SCSC_TAG_WARNING(WLBTD, "ro.build.type = %s\n", build_type);
|
||||
|
||||
build_type_str = nla_data(info->attrs[1]);
|
||||
SCSC_TAG_INFO(WLBTD, "build_type_str = %s\n", build_type_str);
|
||||
|
||||
if (!build_type_str) {
|
||||
SCSC_TAG_ERR(WLBTD, "Failed to retrieve build type attribute\n");
|
||||
mutex_unlock(&build_type_lock);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
strncpy(build_type, (const char *)build_type_str, PROP_VALUE_MAX);
|
||||
SCSC_TAG_INFO(WLBTD, "ro.build.type = %s\n", build_type);
|
||||
mutex_unlock(&build_type_lock);
|
||||
return 0;
|
||||
|
||||
|
@ -210,11 +267,19 @@ static int msg_from_wlbtd_build_type_cb(struct sk_buff *skb, struct genl_info *i
|
|||
|
||||
static int msg_from_wlbtd_write_file_cb(struct sk_buff *skb, struct genl_info *info)
|
||||
{
|
||||
if (info->attrs[3])
|
||||
SCSC_TAG_INFO(WLBTD, "%s\n", (char *)nla_data(info->attrs[3]));
|
||||
int ret_code = 0;
|
||||
|
||||
if (!info || !info->attrs[3] ||
|
||||
(nla_len(info->attrs[3]) > MAX_RSP_STRING_SIZE)){
|
||||
ret_code = -EINVAL;
|
||||
goto error_complete;
|
||||
}
|
||||
|
||||
SCSC_TAG_INFO(WLBTD, "%s\n", (char *)nla_data(info->attrs[3]));
|
||||
|
||||
error_complete:
|
||||
complete(&write_file_done);
|
||||
return 0;
|
||||
return ret_code;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -70,6 +70,9 @@ enum scsc_wlbtd_response_codes {
|
|||
SCSC_WLBTD_OTHER_ERR_SABLE_FILE,
|
||||
SCSC_WLBTD_OTHER_ERR_TAR,
|
||||
SCSC_WLBTD_OTHER_IGNORE_TRIGGER,
|
||||
|
||||
/* Keep this as last entry */
|
||||
SCSC_WLBTD_LAST_RESPONSE_CODE,
|
||||
};
|
||||
|
||||
static const struct genl_multicast_group scsc_mcgrp[] = {
|
||||
|
|
|
@ -87,15 +87,15 @@ static irqreturn_t usim_dt_interrupt0(int irq, void *dev_id)
|
|||
if (value == 0) {
|
||||
/* Check HIGH -> LOW */
|
||||
flag = 0;
|
||||
for (i = 0; i < USIM_LOW_DETECT_COUNT; i++) {
|
||||
msleep_interruptible(100);
|
||||
for (i = 0; i < udd->usim_low_detect_count; i++) {
|
||||
msleep_interruptible(udd->usim_check_delay_msec);
|
||||
value = gpio_get_value(udd->gpio_usim_det0);
|
||||
if (value == 0)
|
||||
flag++;
|
||||
else
|
||||
break;
|
||||
}
|
||||
if (flag == USIM_LOW_DETECT_COUNT) {
|
||||
if (flag == udd->usim_low_detect_count) {
|
||||
usim_det_set_det0_value(udd, 0);
|
||||
pr_err("%s: USIM0_DET: HIGH -> LOW\n", __func__);
|
||||
} else {
|
||||
|
@ -105,15 +105,15 @@ static irqreturn_t usim_dt_interrupt0(int irq, void *dev_id)
|
|||
} else {
|
||||
/* Check LOW -> HIGH */
|
||||
flag = 0;
|
||||
for (i = 0; i < USIM_HIGH_DETECT_COUNT; i++) {
|
||||
msleep_interruptible(100);
|
||||
for (i = 0; i < udd->usim_high_detect_count; i++) {
|
||||
msleep_interruptible(udd->usim_check_delay_msec);
|
||||
value = gpio_get_value(udd->gpio_usim_det0);
|
||||
if (value == 1)
|
||||
flag++;
|
||||
else
|
||||
break;
|
||||
}
|
||||
if (flag == USIM_HIGH_DETECT_COUNT) {
|
||||
if (flag == udd->usim_high_detect_count) {
|
||||
usim_det_set_det0_value(udd, 1);
|
||||
pr_err("%s: USIM0_DET: LOW -> HIGH\n", __func__);
|
||||
} else {
|
||||
|
@ -140,15 +140,15 @@ static irqreturn_t usim_dt_interrupt1(int irq, void *dev_id)
|
|||
if (value == 0) {
|
||||
/* Check HIGH -> LOW */
|
||||
flag = 0;
|
||||
for (i = 0; i < USIM_LOW_DETECT_COUNT; i++) {
|
||||
msleep_interruptible(100);
|
||||
for (i = 0; i < udd->usim_low_detect_count; i++) {
|
||||
msleep_interruptible(udd->usim_check_delay_msec);
|
||||
value = gpio_get_value(udd->gpio_usim_det1);
|
||||
if (value == 0)
|
||||
flag++;
|
||||
else
|
||||
break;
|
||||
}
|
||||
if (flag == USIM_LOW_DETECT_COUNT) {
|
||||
if (flag == udd->usim_low_detect_count) {
|
||||
usim_det_set_det1_value(udd, 0);
|
||||
pr_err("%s: USIM1_DET: HIGH -> LOW\n", __func__);
|
||||
} else {
|
||||
|
@ -157,15 +157,15 @@ static irqreturn_t usim_dt_interrupt1(int irq, void *dev_id)
|
|||
} else {
|
||||
/* Check LOW -> HIGH */
|
||||
flag = 0;
|
||||
for (i = 0; i < USIM_HIGH_DETECT_COUNT; i++) {
|
||||
msleep_interruptible(100);
|
||||
for (i = 0; i < udd->usim_high_detect_count; i++) {
|
||||
msleep_interruptible(udd->usim_check_delay_msec);
|
||||
value = gpio_get_value(udd->gpio_usim_det1);
|
||||
if (value == 1)
|
||||
flag++;
|
||||
else
|
||||
break;
|
||||
}
|
||||
if (flag == USIM_HIGH_DETECT_COUNT) {
|
||||
if (flag == udd->usim_high_detect_count) {
|
||||
usim_det_set_det1_value(udd, 1);
|
||||
pr_err("%s: USIM1_DET: LOW -> HIGH\n", __func__);
|
||||
} else {
|
||||
|
@ -217,6 +217,33 @@ static int usim_detect_probe(struct platform_device *pdev)
|
|||
|
||||
if (udd->num_of_usim_det == 0 || udd->num_of_usim_det > 2)
|
||||
goto exit_err;
|
||||
|
||||
/* USIM delay check */
|
||||
err = of_property_read_u32(dev->of_node, "usim_check_delay_msec",
|
||||
&udd->usim_check_delay_msec);
|
||||
if (err) {
|
||||
udd->usim_check_delay_msec = USIM_CHECK_DELAY_MSEC_DEFAULT;
|
||||
}
|
||||
|
||||
pr_err("usim_check_delay_msec: %d\n", udd->usim_check_delay_msec);
|
||||
|
||||
/* USIM high detect count */
|
||||
err = of_property_read_u32(dev->of_node, "usim_high_detect_count",
|
||||
&udd->usim_high_detect_count);
|
||||
if (err) {
|
||||
udd->usim_high_detect_count = USIM_HIGH_DETECT_COUNT_DEFAULT;
|
||||
}
|
||||
|
||||
pr_err("usim_high_detect_count: %d\n", udd->usim_high_detect_count);
|
||||
|
||||
/* USIM low detect count */
|
||||
err = of_property_read_u32(dev->of_node, "usim_low_detect_count",
|
||||
&udd->usim_low_detect_count);
|
||||
if (err) {
|
||||
udd->usim_low_detect_count = USIM_LOW_DETECT_COUNT_DEFAULT;
|
||||
}
|
||||
|
||||
pr_err("usim_low_detect_count: %d\n", udd->usim_low_detect_count);
|
||||
|
||||
/* USIM0_DET */
|
||||
err = of_property_read_u32(dev->of_node,
|
||||
|
|
|
@ -1966,7 +1966,7 @@ static int dw_mci_switch_voltage(struct mmc_host *mmc, struct mmc_ios *ios)
|
|||
}
|
||||
out:
|
||||
/* waiting for stable */
|
||||
mdelay(10);
|
||||
msleep(10);
|
||||
|
||||
ret = mmc_regulator_set_vqmmc(mmc, ios);
|
||||
|
||||
|
|
|
@ -20,6 +20,22 @@
|
|||
#include "nl80211_vendor.h"
|
||||
|
||||
#define SLSI_MAX_CHAN_2G_BAND 14
|
||||
/* TODO: Remove after FAPI update */
|
||||
#define SLSI_SCANTYPE_SINGLE_CHANNEL_SCAN 0x0013
|
||||
|
||||
|
||||
/* Ext capab is decided by firmware. But there are certain bits
|
||||
* which are set by supplicant. So we set the capab and mask in
|
||||
* such way so that supplicant sets only the bits our solution supports
|
||||
*/
|
||||
|
||||
static const u8 slsi_extended_cap[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
static const u8 slsi_extended_cap_mask[] = {
|
||||
0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
|
||||
};
|
||||
|
||||
static uint keep_alive_period = SLSI_P2PGO_KEEP_ALIVE_PERIOD_SEC;
|
||||
module_param(keep_alive_period, uint, S_IRUGO | S_IWUSR);
|
||||
|
@ -426,6 +442,8 @@ int slsi_scan(struct wiphy *wiphy, struct net_device *dev,
|
|||
bool strip_p2p = false;
|
||||
struct ieee80211_channel *channels[64];
|
||||
int i, chan_count = 0;
|
||||
bool wps_sta = false;
|
||||
|
||||
#ifdef CONFIG_SCSC_WLAN_ENABLE_MAC_RANDOMISATION
|
||||
u8 mac_addr_mask[ETH_ALEN] = {0xFF};
|
||||
#endif
|
||||
|
@ -459,7 +477,7 @@ int slsi_scan(struct wiphy *wiphy, struct net_device *dev,
|
|||
int ret = 0;
|
||||
|
||||
SLSI_NET_DBG3(dev, SLSI_CFG80211, "Scan invokes DRIVER_BCN_ABORT\n");
|
||||
ret = slsi_mlme_set_forward_beacon(sdev, dev, FAPI_ACTION_STOP);
|
||||
ret = slsi_mlme_set_forward_beacon(sdev, dev, FAPI_WIPSACTION_STOP);
|
||||
|
||||
if (!ret) {
|
||||
ret = slsi_send_forward_beacon_abort_vendor_event(sdev,
|
||||
|
@ -474,11 +492,14 @@ int slsi_scan(struct wiphy *wiphy, struct net_device *dev,
|
|||
channels[i] = request->channels[i];
|
||||
chan_count = request->n_channels;
|
||||
|
||||
if (SLSI_IS_VIF_INDEX_WLAN(ndev_vif))
|
||||
if (sdev->initial_scan) {
|
||||
if (SLSI_IS_VIF_INDEX_WLAN(ndev_vif)) {
|
||||
if (chan_count == 1)
|
||||
scan_type = SLSI_SCANTYPE_SINGLE_CHANNEL_SCAN;
|
||||
else if (sdev->initial_scan) {
|
||||
sdev->initial_scan = false;
|
||||
scan_type = FAPI_SCANTYPE_INITIAL_SCAN;
|
||||
}
|
||||
}
|
||||
|
||||
/* Update scan timing for P2P social channels scan. */
|
||||
if ((request->ie) &&
|
||||
|
@ -502,20 +523,21 @@ int slsi_scan(struct wiphy *wiphy, struct net_device *dev,
|
|||
#endif
|
||||
const u8 *ie;
|
||||
|
||||
/* check HS2 related bits in extended capabilties (interworking, WNM,QoS Map, BSS transition) and set in MIB*/
|
||||
r = slsi_mlme_set_hs2_ext_cap(sdev, dev, request->ie, request->ie_len);
|
||||
if (r)
|
||||
goto exit;
|
||||
|
||||
/* Supplicant adds wsc and p2p in Station scan at the end of scan request ie.
|
||||
* for non-wps case remove both wps and p2p IEs
|
||||
* for wps case remove only p2p IE
|
||||
*/
|
||||
|
||||
ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, WLAN_OUI_TYPE_MICROSOFT_WPS, request->ie, request->ie_len);
|
||||
if (ie && ie[1] > SLSI_WPS_REQUEST_TYPE_POS &&
|
||||
ie[SLSI_WPS_REQUEST_TYPE_POS] == SLSI_WPS_REQUEST_TYPE_ENROLEE_INFO_ONLY)
|
||||
strip_wsc = true;
|
||||
if (ie && ie[1] > SLSI_WPS_REQUEST_TYPE_POS) {
|
||||
/* Check whether scan is wps_scan or not, if not a wps_scan set strip_wsc to true
|
||||
* to strip WPS IE else wps_sta to true to disable mac radomization for wps_scan
|
||||
*/
|
||||
if (ie[SLSI_WPS_REQUEST_TYPE_POS] == SLSI_WPS_REQUEST_TYPE_ENROLEE_INFO_ONLY)
|
||||
strip_wsc = true;
|
||||
else
|
||||
wps_sta = true;
|
||||
}
|
||||
|
||||
ie = cfg80211_find_vendor_ie(WLAN_OUI_WFA, WLAN_OUI_TYPE_WFA_P2P, request->ie, request->ie_len);
|
||||
if (ie)
|
||||
|
@ -543,17 +565,21 @@ int slsi_scan(struct wiphy *wiphy, struct net_device *dev,
|
|||
|
||||
#ifdef CONFIG_SCSC_WLAN_ENABLE_MAC_RANDOMISATION
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0))
|
||||
if (request->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) {
|
||||
if (sdev->fw_mac_randomization_enabled) {
|
||||
memcpy(sdev->scan_mac_addr, request->mac_addr, ETH_ALEN);
|
||||
r = slsi_set_mac_randomisation_mask(sdev, request->mac_addr_mask);
|
||||
if (!r)
|
||||
sdev->scan_addr_set = 1;
|
||||
} else {
|
||||
SLSI_NET_INFO(dev, "Mac Randomization is not enabled in Firmware\n");
|
||||
sdev->scan_addr_set = 0;
|
||||
}
|
||||
} else
|
||||
/* If Supplicant triggers WPS scan on station interface,
|
||||
* mac radomization for scan should be disbaled to avoid WPS overlap.
|
||||
* Firmware also disables Mac Randomization for WPS Scan.
|
||||
*/
|
||||
if (request->flags & NL80211_SCAN_FLAG_RANDOM_ADDR && !wps_sta) {
|
||||
if (sdev->fw_mac_randomization_enabled) {
|
||||
memcpy(sdev->scan_mac_addr, request->mac_addr, ETH_ALEN);
|
||||
r = slsi_set_mac_randomisation_mask(sdev, request->mac_addr_mask);
|
||||
if (!r)
|
||||
sdev->scan_addr_set = 1;
|
||||
} else {
|
||||
SLSI_NET_INFO(dev, "Mac Randomization is not enabled in Firmware\n");
|
||||
sdev->scan_addr_set = 0;
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
if (sdev->scan_addr_set) {
|
||||
memset(mac_addr_mask, 0xFF, ETH_ALEN);
|
||||
|
@ -1042,6 +1068,10 @@ int slsi_connect(struct wiphy *wiphy, struct net_device *dev,
|
|||
netif_carrier_on(dev);
|
||||
ndev_vif->sta.vif_status = SLSI_VIF_STATUS_CONNECTING;
|
||||
|
||||
r = slsi_set_ext_cap(sdev, dev, sme->ie, sme->ie_len, slsi_extended_cap_mask);
|
||||
if (r != 0)
|
||||
SLSI_NET_ERR(dev, "Failed to set extended capability MIB: %d\n", r);
|
||||
|
||||
#ifdef CONFIG_SCSC_WLAN_SAE_CONFIG
|
||||
if (sme->auth_type == NL80211_AUTHTYPE_SAE && (sme->flags & CONNECT_REQ_EXTERNAL_AUTH_SUPPORT)) {
|
||||
const u8 *rsn;
|
||||
|
@ -3437,6 +3467,10 @@ struct slsi_dev *slsi_cfg80211_new(struct device *dev)
|
|||
wiphy->cipher_suites = slsi_cipher_suites;
|
||||
wiphy->n_cipher_suites = ARRAY_SIZE(slsi_cipher_suites);
|
||||
|
||||
wiphy->extended_capabilities = slsi_extended_cap;
|
||||
wiphy->extended_capabilities_mask = slsi_extended_cap_mask;
|
||||
wiphy->extended_capabilities_len = ARRAY_SIZE(slsi_extended_cap);
|
||||
|
||||
wiphy->mgmt_stypes = ieee80211_default_mgmt_stypes;
|
||||
|
||||
/* Driver interface combinations */
|
||||
|
@ -3525,13 +3559,20 @@ void slsi_cfg80211_free(struct slsi_dev *sdev)
|
|||
|
||||
void slsi_cfg80211_update_wiphy(struct slsi_dev *sdev)
|
||||
{
|
||||
/* Band 2G probably be disabled by slsi_band_cfg_update() while factory test or NCHO.
|
||||
* So, we need to make sure that Band 2.4G enabled when initialized. */
|
||||
sdev->wiphy->bands[NL80211_BAND_2GHZ] = &slsi_band_2ghz;
|
||||
sdev->device_config.band_2G = &slsi_band_2ghz;
|
||||
|
||||
/* update supported Bands */
|
||||
if (sdev->band_5g_supported) {
|
||||
sdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &slsi_band_5ghz;
|
||||
sdev->device_config.band_5G = &slsi_band_5ghz;
|
||||
sdev->device_config.supported_band = SLSI_FREQ_BAND_AUTO;
|
||||
} else {
|
||||
sdev->wiphy->bands[IEEE80211_BAND_5GHZ] = NULL;
|
||||
sdev->device_config.band_5G = NULL;
|
||||
sdev->device_config.supported_band = SLSI_FREQ_BAND_2GHZ;
|
||||
}
|
||||
|
||||
/* update HT features */
|
||||
|
|
|
@ -128,7 +128,7 @@ static const u16 slsi_rates_table[3][2][10] = {
|
|||
#define SLSI_RX_WAKELOCK_TIME (1000)
|
||||
#define MAX_BA_BUFFER_SIZE 64
|
||||
#define NUM_BA_SESSIONS_PER_PEER 8
|
||||
#define MAX_CHANNEL_LIST 20
|
||||
#define SLSI_NCHO_MAX_CHANNEL_LIST 20
|
||||
#define SLSI_MAX_RX_BA_SESSIONS (8)
|
||||
#define SLSI_STA_ACTION_FRAME_BITMAP (SLSI_ACTION_FRAME_PUBLIC | SLSI_ACTION_FRAME_WMM | SLSI_ACTION_FRAME_WNM |\
|
||||
SLSI_ACTION_FRAME_QOS | SLSI_ACTION_FRAME_PROTECTED_DUAL |\
|
||||
|
@ -840,7 +840,7 @@ struct slsi_apf_capabilities {
|
|||
#ifdef CONFIG_SCSC_WLAN_WES_NCHO
|
||||
struct slsi_wes_mode_roam_scan_channels {
|
||||
int n;
|
||||
u8 channels[MAX_CHANNEL_LIST];
|
||||
u8 channels[SLSI_NCHO_MAX_CHANNEL_LIST];
|
||||
};
|
||||
#endif
|
||||
|
||||
|
@ -892,15 +892,16 @@ struct slsi_dev_config {
|
|||
|
||||
int roam_scan_mode;
|
||||
|
||||
int dfs_scan_mode;
|
||||
|
||||
int ncho_mode;
|
||||
|
||||
/*WES mode roam scan channels*/
|
||||
struct slsi_wes_mode_roam_scan_channels wes_roam_scan_list;
|
||||
#endif
|
||||
struct slsi_802_11d_reg_domain domain_info;
|
||||
|
||||
int ap_disconnect_ind_timeout;
|
||||
|
||||
u8 host_state;
|
||||
|
||||
int rssi_boost_5g;
|
||||
int rssi_boost_2g;
|
||||
bool disable_ch12_ch13;
|
||||
|
@ -1179,6 +1180,8 @@ struct slsi_dev {
|
|||
#ifdef CONFIG_SCSC_WLAN_ENHANCED_PKT_FILTER
|
||||
bool enhanced_pkt_filter_enabled;
|
||||
#endif
|
||||
u8 fw_ext_cap_ie[9]; /*extended capability IE length is 9 */
|
||||
u32 fw_ext_cap_ie_len;
|
||||
};
|
||||
|
||||
/* Compact representation of channels a ESS has been seen on
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -349,7 +349,7 @@ static void slsi_fw_test_connect_start_ap(struct slsi_dev *sdev, struct net_devi
|
|||
if (WARN_ON(!ieee80211_is_assoc_req(mgmt->frame_control) &&
|
||||
!ieee80211_is_reassoc_req(mgmt->frame_control)))
|
||||
return;
|
||||
peer_index = fapi_get_u16(skb, u.mlme_procedure_started_ind.association_identifier);
|
||||
peer_index = fapi_get_u16(skb, u.mlme_procedure_started_ind.peer_index);
|
||||
|
||||
peer = slsi_peer_add(sdev, dev, mgmt->sa, peer_index);
|
||||
if (WARN_ON(!peer))
|
||||
|
@ -363,23 +363,23 @@ static void slsi_fw_test_connected_network(struct slsi_dev *sdev, struct net_dev
|
|||
{
|
||||
struct netdev_vif *ndev_vif = netdev_priv(dev);
|
||||
struct slsi_peer *peer = NULL;
|
||||
u16 aid = fapi_get_u16(skb, u.mlme_connected_ind.association_identifier);
|
||||
u16 peer_index = fapi_get_u16(skb, u.mlme_connected_ind.peer_index);
|
||||
|
||||
SLSI_UNUSED_PARAMETER(fwtest);
|
||||
|
||||
WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex));
|
||||
|
||||
SLSI_NET_DBG1(dev, SLSI_FW_TEST, "Network Peer Connect(vif:%d, aid:%d)\n", ndev_vif->ifnum, aid);
|
||||
SLSI_NET_DBG1(dev, SLSI_FW_TEST, "Network Peer Connect(vif:%d, peer_index:%d)\n", ndev_vif->ifnum, peer_index);
|
||||
WARN(!ndev_vif->is_fw_test, "!is_fw_test");
|
||||
|
||||
if (WARN(!ndev_vif->activated, "Not Activated"))
|
||||
return;
|
||||
|
||||
if (WARN_ON(aid > SLSI_PEER_INDEX_MAX))
|
||||
if (WARN_ON(peer_index > SLSI_PEER_INDEX_MAX))
|
||||
return;
|
||||
|
||||
peer = slsi_get_peer_from_qs(sdev, dev, aid - 1);
|
||||
if (WARN(!peer, "Peer(aid:%d) Not Found", aid))
|
||||
peer = slsi_get_peer_from_qs(sdev, dev, peer_index - 1);
|
||||
if (WARN(!peer, "Peer(peer_index:%d) Not Found", peer_index))
|
||||
return;
|
||||
|
||||
slsi_ps_port_control(sdev, dev, peer, SLSI_STA_CONN_STATE_CONNECTED);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1361,7 +1361,7 @@ static int slsi_mib_initial_get(struct slsi_dev *sdev)
|
|||
|
||||
{ SLSI_PSID_UNIFI_HARDWARE_PLATFORM, {0, 0} },
|
||||
{ SLSI_PSID_UNIFI_REG_DOM_VERSION, {0, 0} },
|
||||
{ SLSI_PSID_UNIFI_NAN_ENABLED, {0, 0} },
|
||||
{ SLSI_PSID_UNIFI_NAN_ACTIVATED, {0, 0} },
|
||||
{ SLSI_PSID_UNIFI_DEFAULT_DWELL_TIME, {0, 0} },
|
||||
#ifdef CONFIG_SCSC_WLAN_WIFI_SHARING
|
||||
{ SLSI_PSID_UNIFI_WI_FI_SHARING5_GHZ_CHANNEL, {0, 0} },
|
||||
|
@ -1377,15 +1377,18 @@ static int slsi_mib_initial_get(struct slsi_dev *sdev)
|
|||
#ifdef CONFIG_SCSC_WLAN_STA_ENHANCED_ARP_DETECT
|
||||
{ SLSI_PSID_UNIFI_ARP_DETECT_ACTIVATED, {0, 0} },
|
||||
#endif
|
||||
{ SLSI_PSID_UNIFI_APF_ENABLED, {0, 0} },
|
||||
{ SLSI_PSID_UNIFI_SOFT_AP40_MHZ_ON24G, {0, 0} }
|
||||
#ifdef CONFIG_SCSC_WLAN_STA_APF
|
||||
{ SLSI_PSID_UNIFI_APF_ACTIVATED, {0, 0} },
|
||||
#endif
|
||||
{ SLSI_PSID_UNIFI_SOFT_AP40_MHZ_ON24G, {0, 0} },
|
||||
{ SLSI_PSID_UNIFI_EXTENDED_CAPABILITIES, {0, 0} },
|
||||
};/*Check the mibrsp.dataLength when a new mib is added*/
|
||||
|
||||
r = slsi_mib_encode_get_list(&mibreq, sizeof(get_values) / sizeof(struct slsi_mib_get_entry), get_values);
|
||||
if (r != SLSI_MIB_STATUS_SUCCESS)
|
||||
return -ENOMEM;
|
||||
|
||||
mibrsp.dataLength = 194;
|
||||
mibrsp.dataLength = 204;
|
||||
mibrsp.data = kmalloc(mibrsp.dataLength, GFP_KERNEL);
|
||||
if (!mibrsp.data) {
|
||||
kfree(mibreq.data);
|
||||
|
@ -1576,15 +1579,23 @@ static int slsi_mib_initial_get(struct slsi_dev *sdev)
|
|||
else
|
||||
SLSI_DBG2(sdev, SLSI_MLME, "Enhanced Arp Detect is disabled!\n");
|
||||
#endif
|
||||
#ifdef CONFIG_SCSC_WLAN_STA_APF
|
||||
if (values[++mib_index].type != SLSI_MIB_TYPE_NONE) /* APF Support */
|
||||
sdev->device_config.fw_apf_supported = values[mib_index].u.boolValue;
|
||||
else
|
||||
SLSI_DBG2(sdev, SLSI_MLME, "APF Support is disabled!\n");
|
||||
|
||||
#endif
|
||||
if (values[++mib_index].type != SLSI_MIB_TYPE_NONE) /* 40MHz for Soft AP */
|
||||
sdev->fw_SoftAp_2g_40mhz_enabled = values[mib_index].u.boolValue;
|
||||
else
|
||||
SLSI_DBG2(sdev, SLSI_MLME, "40MHz for Soft AP is disabled!\n");
|
||||
if (values[++mib_index].type != SLSI_MIB_TYPE_NONE) {
|
||||
sdev->fw_ext_cap_ie_len = values[mib_index].u.octetValue.dataLength;
|
||||
memset(sdev->fw_ext_cap_ie, 0, sizeof(sdev->fw_ext_cap_ie));
|
||||
memcpy(sdev->fw_ext_cap_ie, values[mib_index].u.octetValue.data,
|
||||
sdev->fw_ext_cap_ie_len);
|
||||
} else
|
||||
SLSI_DBG2(sdev, SLSI_MLME, "Failed to read Extended capabilities\n");
|
||||
|
||||
kfree(values);
|
||||
}
|
||||
|
@ -1769,6 +1780,7 @@ int slsi_mib_get_gscan_cap(struct slsi_dev *sdev, struct slsi_nl_gscan_capabilit
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SCSC_WLAN_STA_APF
|
||||
int slsi_mib_get_apf_cap(struct slsi_dev *sdev, struct net_device *dev)
|
||||
{
|
||||
struct slsi_mib_data mibreq = { 0, NULL };
|
||||
|
@ -1826,6 +1838,7 @@ int slsi_mib_get_apf_cap(struct slsi_dev *sdev, struct net_device *dev)
|
|||
kfree(values);
|
||||
return r;
|
||||
}
|
||||
#endif
|
||||
|
||||
int slsi_mib_get_rtt_cap(struct slsi_dev *sdev, struct net_device *dev, struct slsi_rtt_capabilities *cap)
|
||||
{
|
||||
|
@ -2138,6 +2151,32 @@ int slsi_test_send_hanged_vendor_event(struct net_device *dev)
|
|||
}
|
||||
#endif
|
||||
|
||||
int slsi_set_ext_cap(struct slsi_dev *sdev, struct net_device *dev, const u8 *ies, int ie_len, const u8 *ext_cap_mask)
|
||||
{
|
||||
const u8 *ext_capab_ie;
|
||||
int r = 0;
|
||||
|
||||
ext_capab_ie = cfg80211_find_ie(WLAN_EID_EXT_CAPABILITY, ies, ie_len);
|
||||
if (ext_capab_ie) {
|
||||
u8 ext_cap_ie_len = ext_capab_ie[1];
|
||||
int i = 0;
|
||||
bool set_ext_cap = false;
|
||||
|
||||
ext_capab_ie += 2; /* skip the EID and length*/
|
||||
for (i = 0; i < ext_cap_ie_len; i++) {
|
||||
/* Checking Supplicant's extended capability BITS with driver advertised mask.
|
||||
*/
|
||||
if ((~ext_cap_mask[i] & ext_capab_ie[i]) && !(~ext_cap_mask[i] & sdev->fw_ext_cap_ie[i])) {
|
||||
set_ext_cap = true;
|
||||
sdev->fw_ext_cap_ie[i] = sdev->fw_ext_cap_ie[i] | ext_capab_ie[i];
|
||||
}
|
||||
}
|
||||
if (set_ext_cap)
|
||||
r = slsi_mlme_set_ext_capab(sdev, dev, sdev->fw_ext_cap_ie, sdev->fw_ext_cap_ie_len);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
static bool slsi_search_ies_for_qos_indicators(struct slsi_dev *sdev, u8 *ies, int ies_len)
|
||||
{
|
||||
SLSI_UNUSED_PARAMETER_NOT_DEBUG(sdev);
|
||||
|
@ -2854,6 +2893,15 @@ int slsi_handle_disconnect(struct slsi_dev *sdev, struct net_device *dev, u8 *pe
|
|||
memset(&ndev_vif->enhanced_arp_stats, 0, sizeof(ndev_vif->enhanced_arp_stats));
|
||||
ndev_vif->enhanced_arp_detect_enabled = false;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SCSC_WLAN_WES_NCHO
|
||||
SLSI_MUTEX_LOCK(sdev->device_config_mutex);
|
||||
sdev->device_config.ncho_mode = 0;
|
||||
sdev->device_config.roam_scan_mode = 0;
|
||||
sdev->device_config.dfs_scan_mode = 0;
|
||||
sdev->device_config.dfs_scan_mode = 0;
|
||||
SLSI_MUTEX_UNLOCK(sdev->device_config_mutex);
|
||||
#endif
|
||||
slsi_mlme_del_vif(sdev, dev);
|
||||
slsi_vif_deactivated(sdev, dev);
|
||||
break;
|
||||
|
@ -2868,10 +2916,12 @@ int slsi_handle_disconnect(struct slsi_dev *sdev, struct net_device *dev, u8 *pe
|
|||
goto exit;
|
||||
}
|
||||
|
||||
SLSI_NET_DBG3(dev, SLSI_MLME, "MAC:%pM\n", peer_address);
|
||||
SLSI_NET_DBG3(dev, SLSI_MLME, "MAC:%pM is_wps:%d Peer State = %d\n", peer_address, peer->is_wps, peer->connected_state);
|
||||
slsi_fill_last_disconnected_sta_info(sdev, dev, peer_address, reason);
|
||||
slsi_ps_port_control(sdev, dev, peer, SLSI_STA_CONN_STATE_DISCONNECTED);
|
||||
if ((peer->connected_state == SLSI_STA_CONN_STATE_CONNECTED) || (peer->connected_state == SLSI_STA_CONN_STATE_DOING_KEY_CONFIG))
|
||||
if (((peer->connected_state == SLSI_STA_CONN_STATE_CONNECTED) ||
|
||||
(peer->connected_state == SLSI_STA_CONN_STATE_DOING_KEY_CONFIG)) &&
|
||||
!(peer->is_wps))
|
||||
cfg80211_del_sta(dev, peer->address, GFP_KERNEL);
|
||||
|
||||
slsi_spinlock_lock(&ndev_vif->peer_lock);
|
||||
|
|
|
@ -466,6 +466,7 @@ void slsi_vif_deactivated(struct slsi_dev *sdev, struct net_device *dev);
|
|||
int slsi_handle_disconnect(struct slsi_dev *sdev, struct net_device *dev, u8 *peer_address, u16 reason,
|
||||
u8 *disassoc_rsp_ie, u32 disassoc_rsp_ie_len);
|
||||
int slsi_band_update(struct slsi_dev *sdev, int band);
|
||||
void slsi_band_cfg_update(struct slsi_dev *sdev, int band);
|
||||
int slsi_ip_address_changed(struct slsi_dev *sdev, struct net_device *dev, __be32 ipaddress);
|
||||
int slsi_send_gratuitous_arp(struct slsi_dev *sdev, struct net_device *dev);
|
||||
struct ieee80211_channel *slsi_find_scan_channel(struct slsi_dev *sdev, struct ieee80211_mgmt *mgmt, size_t mgmt_len, u16 freq);
|
||||
|
@ -556,6 +557,7 @@ void slsi_vif_cleanup(struct slsi_dev *sdev, struct net_device *dev, bool hw_ava
|
|||
void slsi_scan_cleanup(struct slsi_dev *sdev, struct net_device *dev);
|
||||
void slsi_dump_stats(struct net_device *dev);
|
||||
int slsi_send_hanged_vendor_event(struct slsi_dev *sdev, u16 scsc_panic_code);
|
||||
int slsi_set_ext_cap(struct slsi_dev *sdev, struct net_device *dev, const u8 *ies, int ie_len, const u8 *ext_cap_mask);
|
||||
void slsi_update_supported_channels_regd_flags(struct slsi_dev *sdev);
|
||||
#ifdef CONFIG_SCSC_WLAN_HANG_TEST
|
||||
int slsi_test_send_hanged_vendor_event(struct net_device *dev);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -888,6 +888,53 @@ int slsi_mlme_set_forward_beacon(struct slsi_dev *sdev, struct net_device *dev,
|
|||
}
|
||||
#endif
|
||||
|
||||
int slsi_mlme_set_roaming_parameters(struct slsi_dev *sdev, struct net_device *dev, u16 psid, int mib_value, int mib_length)
|
||||
{
|
||||
struct netdev_vif *ndev_vif = netdev_priv(dev);
|
||||
struct sk_buff *req;
|
||||
struct sk_buff *cfm;
|
||||
int ret = 0;
|
||||
|
||||
SLSI_NET_DBG1(dev, SLSI_MLME, "mlme_set_roaming_parameters_req(vif:%d value:%d)\n", ndev_vif->ifnum, mib_value);
|
||||
req = fapi_alloc(mlme_set_roaming_parameters_req, MLME_SET_ROAMING_PARAMETERS_REQ, ndev_vif->ifnum, 0);
|
||||
if (!req) {
|
||||
SLSI_NET_ERR(dev, "fapi alloc failure\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
fapi_set_u16(req, u.mlme_set_roaming_parameters_req.vif, ndev_vif->ifnum);
|
||||
fapi_append_data_u16(req, psid);
|
||||
fapi_append_data_u16(req, mib_length);
|
||||
|
||||
switch (mib_length) {
|
||||
case 1:
|
||||
fapi_append_data_u8(req, mib_value);
|
||||
break;
|
||||
case 2:
|
||||
fapi_append_data_u16(req, mib_value);
|
||||
break;
|
||||
case 4:
|
||||
fapi_append_data_u32(req, mib_value);
|
||||
break;
|
||||
default:
|
||||
slsi_kfree_skb(req);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
cfm = slsi_mlme_req_cfm(sdev, dev, req, MLME_SET_ROAMING_PARAMETERS_CFM);
|
||||
if (!cfm) {
|
||||
SLSI_NET_ERR(dev, "mlme_set_roaming_parameters_cfm failure\n");
|
||||
return -EIO;
|
||||
}
|
||||
if (fapi_get_u16(cfm, u.mlme_set_roaming_parameters_cfm.result_code) != FAPI_RESULTCODE_SUCCESS) {
|
||||
SLSI_NET_ERR(dev, "mlme_set_roaming_parameters_cfm(result:0x%04x) ERROR\n",
|
||||
fapi_get_u16(cfm, u.mlme_set_roaming_type_cfm.result_code));
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
slsi_kfree_skb(cfm);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int slsi_mlme_set_channel(struct slsi_dev *sdev, struct net_device *dev, struct ieee80211_channel *chan, u16 duration, u16 interval, u16 count)
|
||||
{
|
||||
struct netdev_vif *ndev_vif = netdev_priv(dev);
|
||||
|
@ -2198,7 +2245,7 @@ void slsi_mlme_connected_resp(struct slsi_dev *sdev, struct net_device *dev, u16
|
|||
return;
|
||||
}
|
||||
|
||||
fapi_set_u16(req, u.mlme_connected_res.association_identifier, peer_index);
|
||||
fapi_set_u16(req, u.mlme_connected_res.peer_index, peer_index);
|
||||
slsi_mlme_req_no_cfm(sdev, dev, req);
|
||||
}
|
||||
|
||||
|
@ -3496,12 +3543,12 @@ int slsi_mlme_del_traffic_parameters(struct slsi_dev *sdev, struct net_device *d
|
|||
return r;
|
||||
}
|
||||
|
||||
int slsi_mlme_set_ext_capab(struct slsi_dev *sdev, struct net_device *dev, struct slsi_mib_value *mib_val)
|
||||
int slsi_mlme_set_ext_capab(struct slsi_dev *sdev, struct net_device *dev, u8 *data, int datalength)
|
||||
{
|
||||
struct slsi_mib_data mib_data = { 0, NULL };
|
||||
int error = 0;
|
||||
|
||||
error = slsi_mib_encode_octet(&mib_data, SLSI_PSID_UNIFI_EXTENDED_CAPABILITIES, mib_val->u.octetValue.dataLength, mib_val->u.octetValue.data, 0);
|
||||
error = slsi_mib_encode_octet(&mib_data, SLSI_PSID_UNIFI_EXTENDED_CAPABILITIES, datalength, data, 0);
|
||||
if (error != SLSI_MIB_STATUS_SUCCESS) {
|
||||
error = -ENOMEM;
|
||||
goto exit;
|
||||
|
@ -3523,88 +3570,6 @@ exit:
|
|||
return error;
|
||||
}
|
||||
|
||||
int slsi_mlme_set_hs2_ext_cap(struct slsi_dev *sdev, struct net_device *dev, const u8 *ies, int ie_len)
|
||||
{
|
||||
struct slsi_mib_entry mib_entry;
|
||||
struct slsi_mib_data mibreq = { 0, NULL };
|
||||
struct slsi_mib_data mibrsp = { 0, NULL };
|
||||
const u8 *ext_capab_ie;
|
||||
int r = 0;
|
||||
int rx_length = 0;
|
||||
int len = 0;
|
||||
|
||||
slsi_mib_encode_get(&mibreq, SLSI_PSID_UNIFI_EXTENDED_CAPABILITIES, 0);
|
||||
|
||||
/* 5 (header) + 9 (data) + 2 (mlme expects 16 (??))*/
|
||||
mibrsp.dataLength = 16;
|
||||
mibrsp.data = kmalloc(mibrsp.dataLength, GFP_KERNEL);
|
||||
|
||||
if (!mibrsp.data) {
|
||||
SLSI_ERR(sdev, "Failed to alloc for Mib response\n");
|
||||
kfree(mibreq.data);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
r = slsi_mlme_get(sdev, NULL, mibreq.data, mibreq.dataLength,
|
||||
mibrsp.data, mibrsp.dataLength, &rx_length);
|
||||
kfree(mibreq.data);
|
||||
|
||||
if (r == 0) {
|
||||
mibrsp.dataLength = rx_length;
|
||||
len = slsi_mib_decode(&mibrsp, &mib_entry);
|
||||
if (len == 0) {
|
||||
SLSI_ERR(sdev, "Mib decode error\n");
|
||||
r = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
} else {
|
||||
SLSI_NET_DBG1(dev, SLSI_MLME, "Mib read failed (error: %d)\n", r);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ext_capab_ie = cfg80211_find_ie(WLAN_EID_EXT_CAPABILITY, ies, ie_len);
|
||||
|
||||
if (ext_capab_ie) {
|
||||
u8 ext_capab_ie_len = ext_capab_ie[1];
|
||||
|
||||
ext_capab_ie += 2; /* skip the EID and length*/
|
||||
|
||||
/*BSS Transition bit is bit 19 ,ie length must be >= 3 */
|
||||
if ((ext_capab_ie_len >= 3) && (ext_capab_ie[2] & SLSI_WLAN_EXT_CAPA2_BSS_TRANSISITION_ENABLED))
|
||||
mib_entry.value.u.octetValue.data[2] |= SLSI_WLAN_EXT_CAPA2_BSS_TRANSISITION_ENABLED;
|
||||
else
|
||||
mib_entry.value.u.octetValue.data[2] &= ~SLSI_WLAN_EXT_CAPA2_BSS_TRANSISITION_ENABLED;
|
||||
|
||||
/*interworking bit is bit 31 ,ie length must be >= 4 */
|
||||
if ((ext_capab_ie_len >= 4) && (ext_capab_ie[3] & SLSI_WLAN_EXT_CAPA3_INTERWORKING_ENABLED))
|
||||
mib_entry.value.u.octetValue.data[3] |= SLSI_WLAN_EXT_CAPA3_INTERWORKING_ENABLED;
|
||||
else
|
||||
mib_entry.value.u.octetValue.data[3] &= ~SLSI_WLAN_EXT_CAPA3_INTERWORKING_ENABLED;
|
||||
|
||||
/*QoS MAP is bit 32 ,ie length must be >= 5 */
|
||||
if ((ext_capab_ie_len >= 5) && (ext_capab_ie[4] & SLSI_WLAN_EXT_CAPA4_QOS_MAP_ENABLED))
|
||||
mib_entry.value.u.octetValue.data[4] |= SLSI_WLAN_EXT_CAPA4_QOS_MAP_ENABLED;
|
||||
else
|
||||
mib_entry.value.u.octetValue.data[4] &= ~SLSI_WLAN_EXT_CAPA4_QOS_MAP_ENABLED;
|
||||
|
||||
/*WNM- Notification bit is bit 46 ,ie length must be >= 6 */
|
||||
if ((ext_capab_ie_len >= 6) && (ext_capab_ie[5] & SLSI_WLAN_EXT_CAPA5_WNM_NOTIF_ENABLED))
|
||||
mib_entry.value.u.octetValue.data[5] |= SLSI_WLAN_EXT_CAPA5_WNM_NOTIF_ENABLED;
|
||||
else
|
||||
mib_entry.value.u.octetValue.data[5] &= ~SLSI_WLAN_EXT_CAPA5_WNM_NOTIF_ENABLED;
|
||||
} else {
|
||||
mib_entry.value.u.octetValue.data[2] &= ~SLSI_WLAN_EXT_CAPA2_BSS_TRANSISITION_ENABLED;
|
||||
mib_entry.value.u.octetValue.data[3] &= ~SLSI_WLAN_EXT_CAPA3_INTERWORKING_ENABLED;
|
||||
mib_entry.value.u.octetValue.data[4] &= ~SLSI_WLAN_EXT_CAPA4_QOS_MAP_ENABLED;
|
||||
mib_entry.value.u.octetValue.data[5] &= ~SLSI_WLAN_EXT_CAPA5_WNM_NOTIF_ENABLED;
|
||||
}
|
||||
|
||||
r = slsi_mlme_set_ext_capab(sdev, dev, &mib_entry.value);
|
||||
exit:
|
||||
kfree(mibrsp.data);
|
||||
return r;
|
||||
}
|
||||
|
||||
int slsi_mlme_tdls_peer_resp(struct slsi_dev *sdev, struct net_device *dev, u16 pid, u16 tdls_event)
|
||||
{
|
||||
struct netdev_vif *ndev_vif = netdev_priv(dev);
|
||||
|
@ -3718,7 +3683,7 @@ int slsi_mlme_add_range_req(struct slsi_dev *sdev, u8 count,
|
|||
struct sk_buff *rx;
|
||||
int r = 0, i;
|
||||
size_t alloc_data_size = 0;
|
||||
u8 fapi_ie_generic[] = { 0xdd, 0x1c, 0x00, 0x16, 0x32, 0x0a, 0x01 };
|
||||
u8 fapi_ie_generic[] = { 0xdd, 0x24, 0x00, 0x16, 0x32, 0x0a, 0x01 };
|
||||
/* calculate data size */
|
||||
alloc_data_size += count * (fapi_ie_generic[1] + 2);
|
||||
|
||||
|
@ -3732,12 +3697,13 @@ int slsi_mlme_add_range_req(struct slsi_dev *sdev, u8 count,
|
|||
/*fill the data */
|
||||
fapi_set_u16(req, u.mlme_add_range_req.vif, vif_idx);
|
||||
fapi_set_u16(req, u.mlme_add_range_req.rtt_id, rtt_id);
|
||||
fapi_set_memcpy(req, u.mlme_add_range_req.device_address, source_addr);
|
||||
for (i = 0; i < count; i++) {
|
||||
fapi_append_data(req, fapi_ie_generic, sizeof(fapi_ie_generic));
|
||||
fapi_append_data(req, source_addr, ETH_ALEN);
|
||||
fapi_append_data(req, nl_rtt_params[i].peer_addr, ETH_ALEN);
|
||||
fapi_append_data(req, (u8 *)&nl_rtt_params[i].type, 2);
|
||||
fapi_append_data(req, (u8 *)&nl_rtt_params[i].channel_freq, 2);
|
||||
fapi_append_data(req, (u8 *)&nl_rtt_params[i].channel_info, 2);
|
||||
fapi_append_data(req, (u8 *)&nl_rtt_params[i].burst_period, 1);
|
||||
fapi_append_data(req, (u8 *)&nl_rtt_params[i].num_burst, 1);
|
||||
fapi_append_data(req, (u8 *)&nl_rtt_params[i].num_frames_per_burst, 1);
|
||||
|
@ -4166,6 +4132,7 @@ int slsi_mlme_set_host_state(struct slsi_dev *sdev, struct net_device *dev, u8 h
|
|||
return r;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SCSC_WLAN_STA_APF
|
||||
int slsi_mlme_read_apf_request(struct slsi_dev *sdev, struct net_device *dev, u8 **host_dst, int *datalen)
|
||||
{
|
||||
struct netdev_vif *ndev_vif = netdev_priv(dev);
|
||||
|
@ -4264,6 +4231,7 @@ exit:
|
|||
SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
|
||||
return r;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SCSC_WLAN_STA_ENHANCED_ARP_DETECT
|
||||
int slsi_mlme_arp_detect_request(struct slsi_dev *sdev, struct net_device *dev, u16 action, u8 *target_ipaddr)
|
||||
|
|
|
@ -257,8 +257,7 @@ int slsi_mlme_ndp_terminate(struct slsi_dev *sdev, struct net_device *dev, u16 n
|
|||
#endif
|
||||
#endif
|
||||
|
||||
int slsi_mlme_set_ext_capab(struct slsi_dev *sdev, struct net_device *dev, struct slsi_mib_value *mib_val);
|
||||
int slsi_mlme_set_hs2_ext_cap(struct slsi_dev *sdev, struct net_device *dev, const u8 *ies, int ie_len);
|
||||
int slsi_mlme_set_ext_capab(struct slsi_dev *sdev, struct net_device *dev, u8 *data, int datalength);
|
||||
int slsi_mlme_reassociate(struct slsi_dev *sdev, struct net_device *dev);
|
||||
void slsi_mlme_reassociate_resp(struct slsi_dev *sdev, struct net_device *dev);
|
||||
int slsi_modify_ies(struct net_device *dev, u8 eid, u8 *ies, int ies_len, u8 ie_index, u8 ie_value);
|
||||
|
@ -278,4 +277,6 @@ void slsi_decode_fw_rate(u16 fw_rate, struct rate_info *rate, unsigned long *dat
|
|||
int slsi_test_sap_configure_monitor_mode(struct slsi_dev *sdev, struct net_device *dev, struct cfg80211_chan_def *chandef);
|
||||
|
||||
struct sk_buff *slsi_mlme_req_cfm(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb, u16 cfm_id);
|
||||
int slsi_mlme_set_roaming_parameters(struct slsi_dev *sdev, struct net_device *dev, u16 psid, int mib_value, int mib_length);
|
||||
|
||||
#endif /*__SLSI_MLME_H__*/
|
||||
|
|
|
@ -1029,7 +1029,7 @@ static int slsi_gscan_add_mlme(struct slsi_dev *sdev, struct slsi_nl_gscan_param
|
|||
if (gscan_param.bucket->report_events & SLSI_REPORT_EVENTS_NO_BATCH)
|
||||
report_mode |= FAPI_REPORTMODE_NO_BATCH;
|
||||
} else {
|
||||
report_mode = FAPI_REPORTMODE_RESERVED;
|
||||
report_mode = FAPI_REPORTMODE_BUFFER_FULL;
|
||||
}
|
||||
|
||||
if (report_mode == 0) {
|
||||
|
@ -1428,6 +1428,10 @@ static int slsi_set_bssid_blacklist(struct wiphy *wiphy, struct wireless_dev *wd
|
|||
goto exit;
|
||||
}
|
||||
|
||||
if (nla_len(attr) < ETH_ALEN) {
|
||||
ret = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
bssid = (u8 *)nla_data(attr);
|
||||
|
||||
SLSI_ETHER_COPY(acl_data->mac_addrs[i].addr, bssid);
|
||||
|
@ -1515,6 +1519,10 @@ static int slsi_start_keepalive_offload(struct wiphy *wiphy, struct wireless_dev
|
|||
break;
|
||||
|
||||
case MKEEP_ALIVE_ATTRIBUTE_IP_PKT:
|
||||
if (nla_len(attr) < ip_pkt_len) {
|
||||
r = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
ip_pkt = (u8 *)nla_data(attr);
|
||||
break;
|
||||
|
||||
|
@ -1526,10 +1534,18 @@ static int slsi_start_keepalive_offload(struct wiphy *wiphy, struct wireless_dev
|
|||
break;
|
||||
|
||||
case MKEEP_ALIVE_ATTRIBUTE_DST_MAC_ADDR:
|
||||
if (nla_len(attr) < ETH_ALEN) {
|
||||
r = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
dst_mac_addr = (u8 *)nla_data(attr);
|
||||
break;
|
||||
|
||||
case MKEEP_ALIVE_ATTRIBUTE_SRC_MAC_ADDR:
|
||||
if (nla_len(attr) < ETH_ALEN) {
|
||||
r = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
src_mac_addr = (u8 *)nla_data(attr);
|
||||
break;
|
||||
|
||||
|
@ -1556,7 +1572,7 @@ static int slsi_start_keepalive_offload(struct wiphy *wiphy, struct wireless_dev
|
|||
*/
|
||||
slsi_mlme_send_frame_mgmt(sdev, net_dev, NULL, 0,
|
||||
FAPI_DATAUNITDESCRIPTOR_IEEE802_3_FRAME,
|
||||
FAPI_MESSAGETYPE_ANY_OTHER,
|
||||
FAPI_MESSAGETYPE_PERIODIC_OFFLOAD,
|
||||
ndev_vif->sta.keepalive_host_tag[index - 1], 0, 0, 0);
|
||||
|
||||
skb = slsi_alloc_skb(sizeof(struct ethhdr) + ip_pkt_len, GFP_KERNEL);
|
||||
|
@ -1595,7 +1611,7 @@ static int slsi_start_keepalive_offload(struct wiphy *wiphy, struct wireless_dev
|
|||
ip_send_check(ip_hdr(skb));
|
||||
|
||||
host_tag = slsi_tx_mgmt_host_tag(sdev);
|
||||
r = slsi_mlme_send_frame_data(sdev, net_dev, skb, FAPI_MESSAGETYPE_ANY_OTHER, host_tag,
|
||||
r = slsi_mlme_send_frame_data(sdev, net_dev, skb, FAPI_MESSAGETYPE_PERIODIC_OFFLOAD, host_tag,
|
||||
0, (period * 1000));
|
||||
if (r == 0)
|
||||
ndev_vif->sta.keepalive_host_tag[index - 1] = host_tag;
|
||||
|
@ -1669,7 +1685,7 @@ static int slsi_stop_keepalive_offload(struct wiphy *wiphy, struct wireless_dev
|
|||
}
|
||||
|
||||
r = slsi_mlme_send_frame_mgmt(sdev, net_dev, NULL, 0, FAPI_DATAUNITDESCRIPTOR_IEEE802_3_FRAME,
|
||||
FAPI_MESSAGETYPE_ANY_OTHER, ndev_vif->sta.keepalive_host_tag[index - 1], 0, 0, 0);
|
||||
FAPI_MESSAGETYPE_PERIODIC_OFFLOAD, ndev_vif->sta.keepalive_host_tag[index - 1], 0, 0, 0);
|
||||
ndev_vif->sta.keepalive_host_tag[index - 1] = 0;
|
||||
|
||||
exit:
|
||||
|
@ -1761,25 +1777,46 @@ static int slsi_set_epno_ssid(struct wiphy *wiphy,
|
|||
type = nla_type(iter);
|
||||
switch (type) {
|
||||
case SLSI_ATTRIBUTE_EPNO_MINIMUM_5G_RSSI:
|
||||
slsi_util_nla_get_u16(iter, &epno_params->min_5g_rssi);
|
||||
if (slsi_util_nla_get_u16(iter, &epno_params->min_5g_rssi)) {
|
||||
r = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
break;
|
||||
case SLSI_ATTRIBUTE_EPNO_MINIMUM_2G_RSSI:
|
||||
slsi_util_nla_get_u16(iter, &epno_params->min_2g_rssi);
|
||||
if (slsi_util_nla_get_u16(iter, &epno_params->min_2g_rssi)) {
|
||||
r = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
break;
|
||||
case SLSI_ATTRIBUTE_EPNO_INITIAL_SCORE_MAX:
|
||||
slsi_util_nla_get_u16(iter, &epno_params->initial_score_max);
|
||||
if (slsi_util_nla_get_u16(iter, &epno_params->initial_score_max)) {
|
||||
r = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
break;
|
||||
case SLSI_ATTRIBUTE_EPNO_CUR_CONN_BONUS:
|
||||
slsi_util_nla_get_u8(iter, &epno_params->current_connection_bonus);
|
||||
if (slsi_util_nla_get_u8(iter, &epno_params->current_connection_bonus)) {
|
||||
r = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
break;
|
||||
case SLSI_ATTRIBUTE_EPNO_SAME_NETWORK_BONUS:
|
||||
slsi_util_nla_get_u8(iter, &epno_params->same_network_bonus);
|
||||
if (slsi_util_nla_get_u8(iter, &epno_params->same_network_bonus)) {
|
||||
r = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
break;
|
||||
case SLSI_ATTRIBUTE_EPNO_SECURE_BONUS:
|
||||
slsi_util_nla_get_u8(iter, &epno_params->secure_bonus);
|
||||
if (slsi_util_nla_get_u8(iter, &epno_params->secure_bonus)) {
|
||||
r = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
break;
|
||||
case SLSI_ATTRIBUTE_EPNO_5G_BONUS:
|
||||
slsi_util_nla_get_u8(iter, &epno_params->band_5g_bonus);
|
||||
if (slsi_util_nla_get_u8(iter, &epno_params->band_5g_bonus)) {
|
||||
r = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
break;
|
||||
case SLSI_ATTRIBUTE_EPNO_SSID_LIST:
|
||||
nla_for_each_nested(outer, iter, tmp) {
|
||||
|
@ -1792,7 +1829,10 @@ static int slsi_set_epno_ssid(struct wiphy *wiphy,
|
|||
}
|
||||
break;
|
||||
case SLSI_ATTRIBUTE_EPNO_SSID_NUM:
|
||||
slsi_util_nla_get_u8(iter, &val);
|
||||
if (slsi_util_nla_get_u8(iter, &val)) {
|
||||
r = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
num = (int)val;
|
||||
if (num > SLSI_GSCAN_MAX_EPNO_SSIDS) {
|
||||
SLSI_ERR(sdev, "Cannot support %d SSIDs. max %d\n", num, SLSI_GSCAN_MAX_EPNO_SSIDS);
|
||||
|
@ -2778,6 +2818,7 @@ static int slsi_set_country_code(struct wiphy *wiphy, struct wireless_dev *wdev,
|
|||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SCSC_WLAN_STA_APF
|
||||
static int slsi_apf_read_filter(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len)
|
||||
{
|
||||
int ret = 0;
|
||||
|
@ -2932,6 +2973,7 @@ exit:
|
|||
SLSI_MUTEX_UNLOCK(sdev->device_config_mutex);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int slsi_rtt_get_capabilities(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len)
|
||||
{
|
||||
|
@ -3581,7 +3623,7 @@ static int slsi_set_roaming_state(struct wiphy *wiphy, struct wireless_dev *wdev
|
|||
}
|
||||
|
||||
SLSI_DBG1_NODEV(SLSI_GSCAN, "SUBCMD_SET_ROAMING_STATE roam_state = %d\n", roam_state);
|
||||
ret = slsi_set_mib_roam(sdev, NULL, SLSI_PSID_UNIFI_ROAMING_ENABLED, roam_state);
|
||||
ret = slsi_set_mib_roam(sdev, NULL, SLSI_PSID_UNIFI_ROAMING_ACTIVATED, roam_state);
|
||||
if (ret < 0)
|
||||
SLSI_ERR_NODEV("Failed to set roaming state\n");
|
||||
|
||||
|
@ -5603,6 +5645,7 @@ static const struct wiphy_vendor_command slsi_vendor_cmd[] = {
|
|||
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
|
||||
.doit = slsi_acs_init
|
||||
},
|
||||
#ifdef CONFIG_SCSC_WLAN_STA_APF
|
||||
{
|
||||
{
|
||||
.vendor_id = OUI_GOOGLE,
|
||||
|
@ -5627,6 +5670,7 @@ static const struct wiphy_vendor_command slsi_vendor_cmd[] = {
|
|||
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
|
||||
.doit = slsi_apf_read_filter
|
||||
},
|
||||
#endif
|
||||
{
|
||||
{
|
||||
.vendor_id = OUI_GOOGLE,
|
||||
|
|
|
@ -219,23 +219,28 @@ static int slsi_nan_get_sdea_params_nl(struct slsi_dev *sdev, struct slsi_nan_sd
|
|||
{
|
||||
switch (nl_attr_id) {
|
||||
case NAN_REQ_ATTR_SDEA_PARAM_NDP_TYPE:
|
||||
sdea_params->ndp_type = nla_get_u8(iter);
|
||||
if (slsi_util_nla_get_u8(iter, &(sdea_params->ndp_type)))
|
||||
return -EINVAL;
|
||||
sdea_params->config_nan_data_path = 1;
|
||||
break;
|
||||
case NAN_REQ_ATTR_SDEA_PARAM_SECURITY_CFG:
|
||||
sdea_params->security_cfg = nla_get_u8(iter);
|
||||
if (slsi_util_nla_get_u8(iter, &(sdea_params->security_cfg)))
|
||||
return -EINVAL;
|
||||
sdea_params->config_nan_data_path = 1;
|
||||
break;
|
||||
case NAN_REQ_ATTR_SDEA_PARAM_RANGING_STATE:
|
||||
sdea_params->ranging_state = nla_get_u8(iter);
|
||||
if (slsi_util_nla_get_u8(iter, &(sdea_params->ranging_state)))
|
||||
return -EINVAL;
|
||||
sdea_params->config_nan_data_path = 1;
|
||||
break;
|
||||
case NAN_REQ_ATTR_SDEA_PARAM_RANGE_REPORT:
|
||||
sdea_params->range_report = nla_get_u8(iter);
|
||||
if (slsi_util_nla_get_u8(iter, &(sdea_params->range_report)))
|
||||
return -EINVAL;
|
||||
sdea_params->config_nan_data_path = 1;
|
||||
break;
|
||||
case NAN_REQ_ATTR_SDEA_PARAM_QOS_CFG:
|
||||
sdea_params->qos_cfg = nla_get_u8(iter);
|
||||
if (slsi_util_nla_get_u8(iter, &(sdea_params->qos_cfg)))
|
||||
return -EINVAL;
|
||||
sdea_params->config_nan_data_path = 1;
|
||||
break;
|
||||
default:
|
||||
|
@ -249,16 +254,20 @@ static int slsi_nan_get_ranging_cfg_nl(struct slsi_dev *sdev, struct slsi_nan_ra
|
|||
{
|
||||
switch (nl_attr_id) {
|
||||
case NAN_REQ_ATTR_RANGING_CFG_INTERVAL:
|
||||
ranging_cfg->ranging_interval_msec = nla_get_u32(iter);
|
||||
if (slsi_util_nla_get_u32(iter, &(ranging_cfg->ranging_interval_msec)))
|
||||
return -EINVAL;
|
||||
break;
|
||||
case NAN_REQ_ATTR_RANGING_CFG_INDICATION:
|
||||
ranging_cfg->config_ranging_indications = nla_get_u32(iter);
|
||||
if (slsi_util_nla_get_u32(iter, &(ranging_cfg->config_ranging_indications)))
|
||||
return -EINVAL;
|
||||
break;
|
||||
case NAN_REQ_ATTR_RANGING_CFG_INGRESS_MM:
|
||||
ranging_cfg->distance_ingress_mm = nla_get_u32(iter);
|
||||
if (slsi_util_nla_get_u32(iter, &(ranging_cfg->distance_ingress_mm)))
|
||||
return -EINVAL;
|
||||
break;
|
||||
case NAN_REQ_ATTR_RANGING_CFG_EGRESS_MM:
|
||||
ranging_cfg->distance_egress_mm = nla_get_u32(iter);
|
||||
if (slsi_util_nla_get_u32(iter, &(ranging_cfg->distance_egress_mm)))
|
||||
return -EINVAL;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
|
@ -273,32 +282,41 @@ static int slsi_nan_get_security_info_nl(struct slsi_dev *sdev, struct slsi_nan_
|
|||
|
||||
switch (nl_attr_id) {
|
||||
case NAN_REQ_ATTR_CIPHER_TYPE:
|
||||
sec_info->cipher_type = nla_get_u32(iter);
|
||||
if (slsi_util_nla_get_u32(iter, &(sec_info->cipher_type)))
|
||||
return -EINVAL;
|
||||
break;
|
||||
case NAN_REQ_ATTR_SECURITY_KEY_TYPE:
|
||||
sec_info->key_info.key_type = nla_get_u8(iter);
|
||||
if (slsi_util_nla_get_u8(iter, &(sec_info->key_info.key_type)))
|
||||
return -EINVAL;
|
||||
break;
|
||||
case NAN_REQ_ATTR_SECURITY_PMK_LEN:
|
||||
len = nla_get_u32(iter);
|
||||
if (slsi_util_nla_get_u32(iter, &len))
|
||||
return -EINVAL;
|
||||
sec_info->key_info.body.pmk_info.pmk_len = len;
|
||||
break;
|
||||
case NAN_REQ_ATTR_SECURITY_PMK:
|
||||
memcpy(sec_info->key_info.body.pmk_info.pmk, nla_data(iter), len);
|
||||
if (slsi_util_nla_get_data(iter, sec_info->key_info.body.pmk_info.pmk_len, sec_info->key_info.body.pmk_info.pmk))
|
||||
return -EINVAL;
|
||||
break;
|
||||
case NAN_REQ_ATTR_SECURITY_PASSPHRASE_LEN:
|
||||
len = nla_get_u32(iter);
|
||||
if (slsi_util_nla_get_u32(iter, &len))
|
||||
return -EINVAL;
|
||||
sec_info->key_info.body.passphrase_info.passphrase_len = len;
|
||||
break;
|
||||
case NAN_REQ_ATTR_SECURITY_PASSPHRASE:
|
||||
memcpy(sec_info->key_info.body.passphrase_info.passphrase, nla_data(iter), len);
|
||||
if (slsi_util_nla_get_data(iter, sec_info->key_info.body.passphrase_info.passphrase_len,
|
||||
sec_info->key_info.body.passphrase_info.passphrase))
|
||||
return -EINVAL;
|
||||
break;
|
||||
case NAN_REQ_ATTR_SCID_LEN:
|
||||
sec_info->scid_len = nla_get_u32(iter);
|
||||
if (slsi_util_nla_get_u32(iter, &(sec_info->scid_len)))
|
||||
return -EINVAL;
|
||||
break;
|
||||
case NAN_REQ_ATTR_SCID:
|
||||
if (sec_info->scid_len > sizeof(sec_info->scid))
|
||||
sec_info->scid_len = sizeof(sec_info->scid);
|
||||
memcpy(sec_info->scid, nla_data(iter), sec_info->scid_len);
|
||||
if (slsi_util_nla_get_data(iter, sec_info->scid_len, sec_info->scid))
|
||||
return -EINVAL;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
|
@ -311,19 +329,23 @@ static int slsi_nan_get_range_resp_cfg_nl(struct slsi_dev *sdev, struct slsi_nan
|
|||
{
|
||||
switch (nl_attr_id) {
|
||||
case NAN_REQ_ATTR_RANGE_RESPONSE_CFG_PUBLISH_ID:
|
||||
cfg->publish_id = nla_get_u16(iter);
|
||||
if (slsi_util_nla_get_u16(iter, &(cfg->publish_id)))
|
||||
return -EINVAL;
|
||||
break;
|
||||
|
||||
case NAN_REQ_ATTR_RANGE_RESPONSE_CFG_REQUESTOR_ID:
|
||||
cfg->requestor_instance_id = nla_get_u32(iter);
|
||||
if (slsi_util_nla_get_u32(iter, &(cfg->requestor_instance_id)))
|
||||
return -EINVAL;
|
||||
break;
|
||||
|
||||
case NAN_REQ_ATTR_RANGE_RESPONSE_CFG_PEER_ADDR:
|
||||
memcpy(cfg->peer_addr, nla_data(iter), ETH_ALEN);
|
||||
if (slsi_util_nla_get_data(iter, ETH_ALEN, cfg->peer_addr))
|
||||
return -EINVAL;
|
||||
break;
|
||||
|
||||
case NAN_REQ_ATTR_RANGE_RESPONSE_CFG_RANGING_RESPONSE:
|
||||
cfg->ranging_response = nla_get_u8(iter);
|
||||
if (slsi_util_nla_get_u8(iter, &(cfg->ranging_response)))
|
||||
return -EINVAL;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -505,30 +527,38 @@ static int slsi_nan_enable_get_nl_params(struct slsi_dev *sdev, struct slsi_hal_
|
|||
break;
|
||||
|
||||
case NAN_REQ_ATTR_SUBSCRIBE_SID_BEACON_VAL:
|
||||
hal_req->subscribe_sid_beacon_val = nla_get_u8(iter);
|
||||
if (slsi_util_nla_get_u8(iter, &val))
|
||||
return -EINVAL;
|
||||
hal_req->subscribe_sid_beacon_val = (u32)val;
|
||||
hal_req->config_subscribe_sid_beacon = 1;
|
||||
break;
|
||||
|
||||
case NAN_REQ_ATTR_DW_2G4_INTERVAL:
|
||||
hal_req->dw_2dot4g_interval_val = nla_get_u8(iter);
|
||||
if (slsi_util_nla_get_u8(iter, &val))
|
||||
return -EINVAL;
|
||||
hal_req->dw_2dot4g_interval_val = (u32)val;
|
||||
/* valid range for 2.4G is 1-5 */
|
||||
if (hal_req->dw_2dot4g_interval_val > 0 && hal_req->dw_2dot4g_interval_val < 5)
|
||||
hal_req->config_2dot4g_dw_band = 1;
|
||||
break;
|
||||
|
||||
case NAN_REQ_ATTR_DW_5G_INTERVAL:
|
||||
hal_req->dw_5g_interval_val = nla_get_u8(iter);
|
||||
if (slsi_util_nla_get_u8(iter, &val))
|
||||
return -EINVAL;
|
||||
hal_req->dw_5g_interval_val = (u32)val;
|
||||
/* valid range for 5g is 0-5 */
|
||||
if (hal_req->dw_5g_interval_val < 5)
|
||||
hal_req->config_5g_dw_band = 1;
|
||||
break;
|
||||
|
||||
case NAN_REQ_ATTR_DISC_MAC_ADDR_RANDOM_INTERVAL:
|
||||
hal_req->disc_mac_addr_rand_interval_sec = nla_get_u32(iter);
|
||||
if (slsi_util_nla_get_u32(iter, &(hal_req->disc_mac_addr_rand_interval_sec)))
|
||||
return -EINVAL;
|
||||
break;
|
||||
|
||||
case NAN_REQ_ATTR_HAL_TRANSACTION_ID:
|
||||
hal_req->transaction_id = nla_get_u16(iter);
|
||||
if (slsi_util_nla_get_u16(iter, &(hal_req->transaction_id)))
|
||||
return -EINVAL;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -632,7 +662,8 @@ int slsi_nan_disable(struct wiphy *wiphy, struct wireless_dev *wdev, const void
|
|||
type = nla_type(iter);
|
||||
switch (type) {
|
||||
case NAN_REQ_ATTR_HAL_TRANSACTION_ID:
|
||||
transaction_id = nla_get_u16(iter);
|
||||
if (slsi_util_nla_get_u16(iter, &(transaction_id)))
|
||||
return -EINVAL;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -774,20 +805,23 @@ static int slsi_nan_publish_get_nl_params(struct slsi_dev *sdev, struct slsi_hal
|
|||
break;
|
||||
|
||||
case NAN_REQ_ATTR_PUBLISH_SDEA_LEN:
|
||||
hal_req->sdea_service_specific_info_len = nla_get_u16(iter);
|
||||
if (slsi_util_nla_get_u16(iter, &(hal_req->sdea_service_specific_info_len)))
|
||||
return -EINVAL;
|
||||
break;
|
||||
|
||||
case NAN_REQ_ATTR_PUBLISH_SDEA:
|
||||
memcpy(hal_req->sdea_service_specific_info, nla_data(iter),
|
||||
hal_req->sdea_service_specific_info_len);
|
||||
if (slsi_util_nla_get_data(iter, hal_req->sdea_service_specific_info_len, hal_req->sdea_service_specific_info))
|
||||
return -EINVAL;
|
||||
break;
|
||||
|
||||
case NAN_REQ_ATTR_RANGING_AUTO_RESPONSE:
|
||||
hal_req->ranging_auto_response = nla_get_u8(iter);
|
||||
if (slsi_util_nla_get_u8(iter, &(hal_req->ranging_auto_response)))
|
||||
return -EINVAL;
|
||||
break;
|
||||
|
||||
case NAN_REQ_ATTR_HAL_TRANSACTION_ID:
|
||||
hal_req->transaction_id = nla_get_u16(iter);
|
||||
if (slsi_util_nla_get_u16(iter, &(hal_req->transaction_id)))
|
||||
return -EINVAL;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -907,7 +941,8 @@ int slsi_nan_publish_cancel(struct wiphy *wiphy, struct wireless_dev *wdev,
|
|||
return -EINVAL;
|
||||
break;
|
||||
case NAN_REQ_ATTR_HAL_TRANSACTION_ID:
|
||||
transaction_id = nla_get_u16(iter);
|
||||
if (slsi_util_nla_get_u16(iter, &(transaction_id)))
|
||||
return -EINVAL;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -1065,20 +1100,24 @@ static int slsi_nan_subscribe_get_nl_params(struct slsi_dev *sdev, struct slsi_h
|
|||
break;
|
||||
|
||||
case NAN_REQ_ATTR_PUBLISH_SDEA_LEN:
|
||||
hal_req->sdea_service_specific_info_len = nla_get_u16(iter);
|
||||
if (slsi_util_nla_get_u16(iter, &(hal_req->sdea_service_specific_info_len)))
|
||||
return -EINVAL;
|
||||
break;
|
||||
|
||||
case NAN_REQ_ATTR_PUBLISH_SDEA:
|
||||
memcpy(hal_req->sdea_service_specific_info, nla_data(iter),
|
||||
hal_req->sdea_service_specific_info_len);
|
||||
if (slsi_util_nla_get_data(iter, hal_req->sdea_service_specific_info_len,
|
||||
hal_req->sdea_service_specific_info))
|
||||
return -EINVAL;
|
||||
break;
|
||||
|
||||
case NAN_REQ_ATTR_RANGING_AUTO_RESPONSE:
|
||||
hal_req->ranging_auto_response = nla_get_u8(iter);
|
||||
if (slsi_util_nla_get_u8(iter, &(hal_req->ranging_auto_response)))
|
||||
return -EINVAL;
|
||||
break;
|
||||
|
||||
case NAN_REQ_ATTR_HAL_TRANSACTION_ID:
|
||||
hal_req->transaction_id = nla_get_u16(iter);
|
||||
if (slsi_util_nla_get_u16(iter, &(hal_req->transaction_id)))
|
||||
return -EINVAL;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -1190,7 +1229,10 @@ int slsi_nan_subscribe_cancel(struct wiphy *wiphy, struct wireless_dev *wdev, co
|
|||
}
|
||||
break;
|
||||
case NAN_REQ_ATTR_HAL_TRANSACTION_ID:
|
||||
transaction_id = nla_get_u16(iter);
|
||||
if (slsi_util_nla_get_u16(iter, &(transaction_id))) {
|
||||
reply_status = SLSI_HAL_NAN_STATUS_INVALID_PARAM;
|
||||
goto exit;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
SLSI_ERR(sdev, "Unexpected NAN subscribecancel attribute TYPE:%d\n", type);
|
||||
|
@ -1274,16 +1316,19 @@ static int slsi_nan_followup_get_nl_params(struct slsi_dev *sdev, struct slsi_ha
|
|||
break;
|
||||
|
||||
case NAN_REQ_ATTR_PUBLISH_SDEA_LEN:
|
||||
hal_req->sdea_service_specific_info_len = nla_get_u16(iter);
|
||||
if (slsi_util_nla_get_u16(iter, &(hal_req->sdea_service_specific_info_len)))
|
||||
return -EINVAL;
|
||||
break;
|
||||
|
||||
case NAN_REQ_ATTR_PUBLISH_SDEA:
|
||||
memcpy(hal_req->sdea_service_specific_info, nla_data(iter),
|
||||
hal_req->sdea_service_specific_info_len);
|
||||
if (slsi_util_nla_get_data(iter, hal_req->sdea_service_specific_info_len,
|
||||
hal_req->sdea_service_specific_info))
|
||||
return -EINVAL;
|
||||
break;
|
||||
|
||||
case NAN_REQ_ATTR_HAL_TRANSACTION_ID:
|
||||
hal_req->transaction_id = nla_get_u16(iter);
|
||||
if (slsi_util_nla_get_u16(iter, &(hal_req->transaction_id)))
|
||||
return -EINVAL;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -1590,30 +1635,39 @@ static int slsi_nan_config_get_nl_params(struct slsi_dev *sdev, struct slsi_hal_
|
|||
break;
|
||||
|
||||
case NAN_REQ_ATTR_SUBSCRIBE_SID_BEACON_VAL:
|
||||
hal_req->subscribe_sid_beacon_val = nla_get_u8(iter);
|
||||
if (slsi_util_nla_get_u8(iter, &val))
|
||||
return -EINVAL;
|
||||
hal_req->subscribe_sid_beacon_val = (u32)val;
|
||||
hal_req->config_subscribe_sid_beacon = 1;
|
||||
break;
|
||||
|
||||
case NAN_REQ_ATTR_DW_2G4_INTERVAL:
|
||||
hal_req->dw_2dot4g_interval_val = nla_get_u8(iter);
|
||||
if (slsi_util_nla_get_u8(iter, &val))
|
||||
return -EINVAL;
|
||||
hal_req->dw_2dot4g_interval_val = (u32)val;
|
||||
/* valid range for 2.4G is 1-5 */
|
||||
if (hal_req->dw_2dot4g_interval_val > 0 && hal_req->dw_2dot4g_interval_val < 6)
|
||||
hal_req->config_2dot4g_dw_band = 1;
|
||||
break;
|
||||
|
||||
case NAN_REQ_ATTR_DW_5G_INTERVAL:
|
||||
hal_req->dw_5g_interval_val = nla_get_u8(iter);
|
||||
if (slsi_util_nla_get_u8(iter, &val))
|
||||
return -EINVAL;
|
||||
hal_req->dw_5g_interval_val = (u32)val;
|
||||
/* valid range for 5g is 0-5 */
|
||||
if (hal_req->dw_5g_interval_val < 6)
|
||||
hal_req->config_5g_dw_band = 1;
|
||||
break;
|
||||
|
||||
case NAN_REQ_ATTR_DISC_MAC_ADDR_RANDOM_INTERVAL:
|
||||
hal_req->disc_mac_addr_rand_interval_sec = nla_get_u8(iter);
|
||||
if (slsi_util_nla_get_u8(iter, &val))
|
||||
return -EINVAL;
|
||||
hal_req->disc_mac_addr_rand_interval_sec = (u32)val;
|
||||
break;
|
||||
|
||||
case NAN_REQ_ATTR_HAL_TRANSACTION_ID:
|
||||
hal_req->transaction_id = nla_get_u16(iter);
|
||||
if (slsi_util_nla_get_u16(iter, &(hal_req->transaction_id)))
|
||||
return -EINVAL;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -1715,7 +1769,8 @@ int slsi_nan_get_capabilities(struct wiphy *wiphy, struct wireless_dev *wdev, co
|
|||
type = nla_type(iter);
|
||||
switch (type) {
|
||||
case NAN_REQ_ATTR_HAL_TRANSACTION_ID:
|
||||
transaction_id = nla_get_u16(iter);
|
||||
if (slsi_util_nla_get_u16(iter, &(transaction_id)))
|
||||
return -EINVAL;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -1800,10 +1855,16 @@ int slsi_nan_data_iface_create(struct wiphy *wiphy, struct wireless_dev *wdev, c
|
|||
|
||||
nla_for_each_attr(iter, data, len, tmp) {
|
||||
type = nla_type(iter);
|
||||
if (type == NAN_REQ_ATTR_DATA_INTERFACE_NAME)
|
||||
if (type == NAN_REQ_ATTR_DATA_INTERFACE_NAME) {
|
||||
/* 16 is the interface length from net_device
|
||||
* structure.
|
||||
*/
|
||||
if (nla_len(iter) > IFNAMSIZ)
|
||||
return -EINVAL;
|
||||
iface_name = nla_data(iter);
|
||||
else if (type == NAN_REQ_ATTR_HAL_TRANSACTION_ID)
|
||||
transaction_id = nla_get_u16(iter);
|
||||
} else if (type == NAN_REQ_ATTR_HAL_TRANSACTION_ID)
|
||||
if (slsi_util_nla_get_u16(iter, &(transaction_id)))
|
||||
return -EINVAL;
|
||||
}
|
||||
if (!iface_name) {
|
||||
SLSI_ERR(sdev, "No NAN data interface name\n");
|
||||
|
@ -1869,10 +1930,16 @@ int slsi_nan_data_iface_delete(struct wiphy *wiphy, struct wireless_dev *wdev, c
|
|||
|
||||
nla_for_each_attr(iter, data, len, tmp) {
|
||||
type = nla_type(iter);
|
||||
if (type == NAN_REQ_ATTR_DATA_INTERFACE_NAME)
|
||||
if (type == NAN_REQ_ATTR_DATA_INTERFACE_NAME) {
|
||||
/* 16 is the interface length from net_device
|
||||
* structure.
|
||||
*/
|
||||
if (nla_len(iter) > IFNAMSIZ)
|
||||
return -EINVAL;
|
||||
iface_name = nla_data(iter);
|
||||
else if (type == NAN_REQ_ATTR_HAL_TRANSACTION_ID)
|
||||
transaction_id = nla_get_u16(iter);
|
||||
} else if (type == NAN_REQ_ATTR_HAL_TRANSACTION_ID)
|
||||
if (slsi_util_nla_get_u16(iter, &(transaction_id)))
|
||||
return -EINVAL;
|
||||
}
|
||||
if (!iface_name) {
|
||||
SLSI_ERR(sdev, "No NAN data interface name\n");
|
||||
|
@ -1911,54 +1978,67 @@ int slsi_nan_ndp_initiate_get_nl_params(struct slsi_dev *sdev, struct slsi_hal_n
|
|||
type = nla_type(iter);
|
||||
switch (type) {
|
||||
case NAN_REQ_ATTR_REQ_INSTANCE_ID:
|
||||
hal_req->requestor_instance_id = nla_get_u32(iter);
|
||||
if (slsi_util_nla_get_u32(iter, &(hal_req->requestor_instance_id)))
|
||||
return -EINVAL;
|
||||
break;
|
||||
|
||||
case NAN_REQ_ATTR_CHAN_REQ_TYPE:
|
||||
hal_req->channel_request_type = nla_get_u8(iter);
|
||||
if (slsi_util_nla_get_u8(iter, &(hal_req->channel_request_type)))
|
||||
return -EINVAL;
|
||||
break;
|
||||
|
||||
case NAN_REQ_ATTR_CHAN:
|
||||
hal_req->channel = nla_get_u32(iter);
|
||||
if (slsi_util_nla_get_u32(iter, &(hal_req->channel)))
|
||||
return -EINVAL;
|
||||
break;
|
||||
|
||||
case NAN_REQ_ATTR_MAC_ADDR_VAL:
|
||||
if (nla_len(iter) < ETH_ALEN)
|
||||
return -EINVAL;
|
||||
ether_addr_copy(hal_req->peer_disc_mac_addr, nla_data(iter));
|
||||
break;
|
||||
|
||||
case NAN_REQ_ATTR_DATA_INTERFACE_NAME:
|
||||
memcpy(hal_req->ndp_iface, nla_data(iter), IFNAMSIZ);
|
||||
if (slsi_util_nla_get_data(iter, IFNAMSIZ, hal_req->ndp_iface))
|
||||
return -EINVAL;
|
||||
break;
|
||||
|
||||
case NAN_REQ_ATTR_DATA_INTERFACE_NAME_LEN:
|
||||
break;
|
||||
|
||||
case NAN_REQ_ATTR_SDEA_PARAM_SECURITY_CFG:
|
||||
hal_req->ndp_cfg.security_cfg = nla_get_u8(iter);
|
||||
if (slsi_util_nla_get_u8(iter, &(hal_req->ndp_cfg.security_cfg)))
|
||||
return -EINVAL;
|
||||
break;
|
||||
|
||||
case NAN_REQ_ATTR_SDEA_PARAM_QOS_CFG:
|
||||
hal_req->ndp_cfg.qos_cfg = nla_get_u8(iter);
|
||||
if (slsi_util_nla_get_u8(iter, &(hal_req->ndp_cfg.qos_cfg)))
|
||||
return -EINVAL;
|
||||
break;
|
||||
|
||||
case NAN_REQ_ATTR_APP_INFO_LEN:
|
||||
hal_req->app_info.ndp_app_info_len = nla_get_u16(iter);
|
||||
if (slsi_util_nla_get_u16(iter, &(hal_req->app_info.ndp_app_info_len)))
|
||||
return -EINVAL;
|
||||
break;
|
||||
|
||||
case NAN_REQ_ATTR_APP_INFO:
|
||||
memcpy(hal_req->app_info.ndp_app_info, nla_data(iter), hal_req->app_info.ndp_app_info_len);
|
||||
if (slsi_util_nla_get_data(iter, hal_req->app_info.ndp_app_info_len, hal_req->app_info.ndp_app_info))
|
||||
return -EINVAL;
|
||||
break;
|
||||
|
||||
case NAN_REQ_ATTR_SERVICE_NAME_LEN:
|
||||
hal_req->service_name_len = nla_get_u32(iter);
|
||||
if (slsi_util_nla_get_u32(iter, &(hal_req->service_name_len)))
|
||||
return -EINVAL;
|
||||
break;
|
||||
|
||||
case NAN_REQ_ATTR_SERVICE_NAME:
|
||||
memcpy(hal_req->service_name, nla_data(iter), hal_req->service_name_len);
|
||||
if (slsi_util_nla_get_data(iter, hal_req->service_name_len, hal_req->service_name))
|
||||
return -EINVAL;
|
||||
break;
|
||||
|
||||
case NAN_REQ_ATTR_HAL_TRANSACTION_ID:
|
||||
hal_req->transaction_id = nla_get_u16(iter);
|
||||
if (slsi_util_nla_get_u16(iter, &(hal_req->transaction_id)))
|
||||
return -EINVAL;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -2047,51 +2127,65 @@ int slsi_nan_ndp_respond_get_nl_param(struct slsi_dev *sdev, struct slsi_hal_nan
|
|||
{
|
||||
int type, tmp, r;
|
||||
const struct nlattr *iter;
|
||||
u8 val = 0;
|
||||
u32 value = 0;
|
||||
|
||||
memset(hal_req, 0, sizeof(*hal_req));
|
||||
nla_for_each_attr(iter, data, len, tmp) {
|
||||
type = nla_type(iter);
|
||||
switch (type) {
|
||||
case NAN_REQ_ATTR_NDP_INSTANCE_ID:
|
||||
hal_req->ndp_instance_id = nla_get_u32(iter);
|
||||
if (slsi_util_nla_get_u32(iter, &(hal_req->ndp_instance_id)))
|
||||
return -EINVAL;
|
||||
break;
|
||||
|
||||
case NAN_REQ_ATTR_DATA_INTERFACE_NAME:
|
||||
memcpy(hal_req->ndp_iface, nla_data(iter), IFNAMSIZ);
|
||||
if (slsi_util_nla_get_data(iter, IFNAMSIZ, hal_req->ndp_iface))
|
||||
return -EINVAL;
|
||||
break;
|
||||
case NAN_REQ_ATTR_DATA_INTERFACE_NAME_LEN:
|
||||
break;
|
||||
|
||||
case NAN_REQ_ATTR_SDEA_PARAM_SECURITY_CFG:
|
||||
hal_req->ndp_cfg.security_cfg = nla_get_u8(iter);
|
||||
if (slsi_util_nla_get_u8(iter, &(hal_req->ndp_cfg.security_cfg)))
|
||||
return -EINVAL;
|
||||
break;
|
||||
|
||||
case NAN_REQ_ATTR_SDEA_PARAM_QOS_CFG:
|
||||
hal_req->ndp_cfg.qos_cfg = nla_get_u8(iter);
|
||||
if (slsi_util_nla_get_u8(iter, &(hal_req->ndp_cfg.qos_cfg)))
|
||||
return -EINVAL;
|
||||
break;
|
||||
|
||||
case NAN_REQ_ATTR_APP_INFO_LEN:
|
||||
hal_req->app_info.ndp_app_info_len = nla_get_u16(iter);
|
||||
if (slsi_util_nla_get_u16(iter, &(hal_req->app_info.ndp_app_info_len)))
|
||||
return -EINVAL;
|
||||
break;
|
||||
|
||||
case NAN_REQ_ATTR_APP_INFO:
|
||||
memcpy(hal_req->app_info.ndp_app_info, nla_data(iter), hal_req->app_info.ndp_app_info_len);
|
||||
if (slsi_util_nla_get_data(iter, hal_req->app_info.ndp_app_info_len, hal_req->app_info.ndp_app_info))
|
||||
return -EINVAL;
|
||||
break;
|
||||
|
||||
case NAN_REQ_ATTR_NDP_RESPONSE_CODE:
|
||||
hal_req->rsp_code = nla_get_u8(iter);
|
||||
if (slsi_util_nla_get_u8(iter, &val))
|
||||
return -EINVAL;
|
||||
hal_req->rsp_code = (u32)val;
|
||||
break;
|
||||
|
||||
case NAN_REQ_ATTR_SERVICE_NAME_LEN:
|
||||
hal_req->service_name_len = nla_get_u32(iter);
|
||||
if (slsi_util_nla_get_u32(iter, &value))
|
||||
return -EINVAL;
|
||||
hal_req->service_name_len = (u8)value;
|
||||
break;
|
||||
|
||||
case NAN_REQ_ATTR_SERVICE_NAME:
|
||||
memcpy(hal_req->service_name, nla_data(iter), hal_req->service_name_len);
|
||||
if (slsi_util_nla_get_data(iter, hal_req->service_name_len, hal_req->service_name))
|
||||
return -EINVAL;
|
||||
break;
|
||||
|
||||
case NAN_REQ_ATTR_HAL_TRANSACTION_ID:
|
||||
hal_req->transaction_id = nla_get_u16(iter);
|
||||
if (slsi_util_nla_get_u16(iter, &(hal_req->transaction_id)))
|
||||
return -EINVAL;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -2167,14 +2261,18 @@ int slsi_nan_ndp_end_get_nl_params(struct slsi_dev *sdev, struct slsi_hal_nan_da
|
|||
{
|
||||
int type, tmp;
|
||||
const struct nlattr *iter;
|
||||
|
||||
u32 val = 0;
|
||||
memset(hal_req, 0, sizeof(*hal_req));
|
||||
nla_for_each_attr(iter, data, len, tmp) {
|
||||
type = nla_type(iter);
|
||||
if (type == NAN_REQ_ATTR_NDP_INSTANCE_ID && hal_req->num_ndp_instances < SLSI_NAN_MAX_NDP_INSTANCES)
|
||||
hal_req->ndp_instance_id[hal_req->num_ndp_instances++] = nla_get_u32(iter);
|
||||
else if (type == NAN_REQ_ATTR_HAL_TRANSACTION_ID)
|
||||
hal_req->transaction_id = nla_get_u16(iter);
|
||||
if (type == NAN_REQ_ATTR_NDP_INSTANCE_ID && hal_req->num_ndp_instances < SLSI_NAN_MAX_NDP_INSTANCES) {
|
||||
if (slsi_util_nla_get_u32(iter, &val))
|
||||
return -EINVAL;
|
||||
hal_req->ndp_instance_id[hal_req->num_ndp_instances++] = val;
|
||||
} else if (type == NAN_REQ_ATTR_HAL_TRANSACTION_ID) {
|
||||
if (slsi_util_nla_get_u16(iter, &(hal_req->transaction_id)))
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
return SLSI_HAL_NAN_STATUS_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -1020,12 +1020,12 @@ struct slsi_acs_chan_info *slsi_acs_scan_results(struct slsi_dev *sdev, struct n
|
|||
ies_len);
|
||||
|
||||
idx = slsi_find_chan_idx(scan_channel->hw_value, ndev_vif->scan[SLSI_SCAN_HW_ID].acs_request->hw_mode);
|
||||
SLSI_DBG3(sdev, SLSI_MLME, "chan_idx:%d chan_value: %d\n", idx, ch_info[idx].chan);
|
||||
|
||||
if (idx < 0) {
|
||||
SLSI_DBG3(sdev, SLSI_MLME, "idx is not in range idx=%d\n", idx);
|
||||
goto next_scan;
|
||||
}
|
||||
SLSI_DBG3(sdev, SLSI_MLME, "chan_idx:%d chan_value: %d\n", idx, ch_info[idx].chan);
|
||||
|
||||
if (ch_info[idx].chan) {
|
||||
ch_info[idx].num_ap += 1;
|
||||
ie = cfg80211_find_ie(WLAN_EID_QBSS_LOAD, mgmt->u.beacon.variable, ies_len);
|
||||
|
@ -1783,15 +1783,15 @@ void slsi_rx_connected_ind(struct slsi_dev *sdev, struct net_device *dev, struct
|
|||
{
|
||||
struct netdev_vif *ndev_vif = netdev_priv(dev);
|
||||
struct slsi_peer *peer = NULL;
|
||||
u16 aid = fapi_get_u16(skb, u.mlme_connected_ind.association_identifier);
|
||||
u16 peer_index = fapi_get_u16(skb, u.mlme_connected_ind.peer_index);
|
||||
|
||||
/* For AP mode, peer_index value is equivalent to aid(association_index) value */
|
||||
/* For AP mode, peer_index value is equivalent to peer_index value */
|
||||
|
||||
SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
|
||||
|
||||
SLSI_NET_DBG1(dev, SLSI_MLME, "mlme_connected_ind(vif:%d, peer_index:%d)\n",
|
||||
fapi_get_vif(skb),
|
||||
aid);
|
||||
peer_index);
|
||||
SLSI_INFO(sdev, "Received Association Response\n");
|
||||
|
||||
if (!ndev_vif->activated) {
|
||||
|
@ -1805,14 +1805,14 @@ void slsi_rx_connected_ind(struct slsi_dev *sdev, struct net_device *dev, struct
|
|||
switch (ndev_vif->vif_type) {
|
||||
case FAPI_VIFTYPE_AP:
|
||||
{
|
||||
if (aid < SLSI_PEER_INDEX_MIN || aid > SLSI_PEER_INDEX_MAX) {
|
||||
SLSI_NET_ERR(dev, "Received incorrect peer_index: %d\n", aid);
|
||||
if (peer_index < SLSI_PEER_INDEX_MIN || peer_index > SLSI_PEER_INDEX_MAX) {
|
||||
SLSI_NET_ERR(dev, "Received incorrect peer_index: %d\n", peer_index);
|
||||
goto exit_with_lock;
|
||||
}
|
||||
|
||||
peer = slsi_get_peer_from_qs(sdev, dev, aid - 1);
|
||||
peer = slsi_get_peer_from_qs(sdev, dev, peer_index - 1);
|
||||
if (!peer) {
|
||||
SLSI_NET_ERR(dev, "Peer (aid:%d) Not Found - Disconnect peer\n", aid);
|
||||
SLSI_NET_ERR(dev, "Peer (peer_index:%d) Not Found - Disconnect peer\n", peer_index);
|
||||
goto exit_with_lock;
|
||||
}
|
||||
|
||||
|
@ -1823,7 +1823,7 @@ void slsi_rx_connected_ind(struct slsi_dev *sdev, struct net_device *dev, struct
|
|||
slsi_ps_port_control(sdev, dev, peer, SLSI_STA_CONN_STATE_DOING_KEY_CONFIG);
|
||||
} else {
|
||||
peer->connected_state = SLSI_STA_CONN_STATE_CONNECTED;
|
||||
slsi_mlme_connected_resp(sdev, dev, aid);
|
||||
slsi_mlme_connected_resp(sdev, dev, peer_index);
|
||||
slsi_ps_port_control(sdev, dev, peer, SLSI_STA_CONN_STATE_CONNECTED);
|
||||
}
|
||||
slsi_rx_buffered_frames(sdev, dev, peer);
|
||||
|
@ -1994,12 +1994,12 @@ void slsi_rx_connect_ind(struct slsi_dev *sdev, struct net_device *dev, struct s
|
|||
SLSI_INFO(sdev, "Connect failed,Result code:AUTH_NO_ACK\n");
|
||||
} else if (fw_result_code == FAPI_RESULTCODE_ASSOC_NO_ACK) {
|
||||
SLSI_INFO(sdev, "Connect failed,Result code:ASSOC_NO_ACK\n");
|
||||
} else if (fw_result_code >= FAPI_RESULTCODE_AUTH_FAILED_CODE && fw_result_code <= 0x81FF) {
|
||||
if (fw_result_code != FAPI_RESULTCODE_AUTH_FAILED_CODE)
|
||||
} else if (fw_result_code >= 0x8100 && fw_result_code <= 0x81FF) {
|
||||
if (fw_result_code != 0x8100)
|
||||
fw_result_code = fw_result_code & 0x00FF;
|
||||
SLSI_INFO(sdev, "Connect failed(Auth failure), Result code:0x%04x\n", fw_result_code);
|
||||
} else if (fw_result_code >= FAPI_RESULTCODE_ASSOC_FAILED_CODE && fw_result_code <= 0x82FF) {
|
||||
if (fw_result_code != FAPI_RESULTCODE_ASSOC_FAILED_CODE)
|
||||
} else if (fw_result_code >= 0x8200 && fw_result_code <= 0x82FF) {
|
||||
if (fw_result_code != 0x8200)
|
||||
fw_result_code = fw_result_code & 0x00FF;
|
||||
SLSI_INFO(sdev, "Connect failed(Assoc Failure), Result code:0x%04x\n", fw_result_code);
|
||||
if (fapi_get_datalen(skb)) {
|
||||
|
@ -2305,10 +2305,10 @@ void slsi_rx_procedure_started_ind(struct slsi_dev *sdev, struct net_device *dev
|
|||
|
||||
SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
|
||||
|
||||
SLSI_NET_DBG1(dev, SLSI_MLME, "mlme_procedure_started_ind(vif:%d, type:%d, aid:%d)\n",
|
||||
SLSI_NET_DBG1(dev, SLSI_MLME, "mlme_procedure_started_ind(vif:%d, type:%d, peer_index:%d)\n",
|
||||
fapi_get_vif(skb),
|
||||
fapi_get_u16(skb, u.mlme_procedure_started_ind.procedure_type),
|
||||
fapi_get_u16(skb, u.mlme_procedure_started_ind.association_identifier));
|
||||
fapi_get_u16(skb, u.mlme_procedure_started_ind.peer_index));
|
||||
SLSI_INFO(sdev, "Send Association Request\n");
|
||||
|
||||
if (!ndev_vif->activated) {
|
||||
|
@ -2321,20 +2321,20 @@ void slsi_rx_procedure_started_ind(struct slsi_dev *sdev, struct net_device *dev
|
|||
switch (ndev_vif->vif_type) {
|
||||
case FAPI_VIFTYPE_AP:
|
||||
{
|
||||
u16 aid = fapi_get_u16(skb, u.mlme_procedure_started_ind.association_identifier);
|
||||
u16 peer_index = fapi_get_u16(skb, u.mlme_procedure_started_ind.peer_index);
|
||||
|
||||
/* Check for MAX client */
|
||||
if ((ndev_vif->peer_sta_records + 1) > SLSI_AP_PEER_CONNECTIONS_MAX) {
|
||||
SLSI_NET_ERR(dev, "MAX Station limit reached. Ignore ind for aid:%d\n", aid);
|
||||
SLSI_NET_ERR(dev, "MAX Station limit reached. Ignore ind for peer_index:%d\n", peer_index);
|
||||
goto exit_with_lock;
|
||||
}
|
||||
|
||||
if (aid < SLSI_PEER_INDEX_MIN || aid > SLSI_PEER_INDEX_MAX) {
|
||||
SLSI_NET_ERR(dev, "Received incorrect aid: %d\n", aid);
|
||||
if (peer_index < SLSI_PEER_INDEX_MIN || peer_index > SLSI_PEER_INDEX_MAX) {
|
||||
SLSI_NET_ERR(dev, "Received incorrect peer_index: %d\n", peer_index);
|
||||
goto exit_with_lock;
|
||||
}
|
||||
|
||||
peer = slsi_peer_add(sdev, dev, (fapi_get_mgmt(skb))->sa, aid);
|
||||
peer = slsi_peer_add(sdev, dev, (fapi_get_mgmt(skb))->sa, peer_index);
|
||||
if (!peer) {
|
||||
SLSI_NET_ERR(dev, "Peer NOT Created\n");
|
||||
goto exit_with_lock;
|
||||
|
|
|
@ -103,14 +103,23 @@ static int slsi_rx_amsdu_deaggregate(struct net_device *dev, struct sk_buff *skb
|
|||
msdu_len = (skb->data[ETH_ALEN * 2] << 8) | skb->data[(ETH_ALEN * 2) + 1];
|
||||
|
||||
/* check if the length of sub-frame is valid */
|
||||
if (msdu_len > skb->len) {
|
||||
if (!msdu_len || msdu_len >= skb->len) {
|
||||
SLSI_NET_ERR(dev, "invalid MSDU length %d, SKB length = %d\n", msdu_len, skb->len);
|
||||
__skb_queue_purge(msdu_list);
|
||||
slsi_kfree_skb(skb);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
subframe_len = msdu_len + (2 * ETH_ALEN) + 2;
|
||||
|
||||
/* check if the length of sub-frame is valid */
|
||||
if (subframe_len > skb->len) {
|
||||
SLSI_NET_ERR(dev, "invalid subframe length %d, SKB length = %d\n", subframe_len, skb->len);
|
||||
__skb_queue_purge(msdu_list);
|
||||
slsi_kfree_skb(skb);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* For the last subframe skb length and subframe length will be same */
|
||||
if (skb->len == subframe_len) {
|
||||
/* Use the original skb for the last subframe */
|
||||
|
@ -122,6 +131,7 @@ static int slsi_rx_amsdu_deaggregate(struct net_device *dev, struct sk_buff *skb
|
|||
/* Clone the skb for the subframe */
|
||||
subframe = slsi_skb_clone(skb, GFP_ATOMIC);
|
||||
if (!subframe) {
|
||||
__skb_queue_purge(msdu_list);
|
||||
slsi_kfree_skb(skb);
|
||||
SLSI_NET_ERR(dev, "Failed to clone the SKB for A-MSDU subframe\n");
|
||||
return -ENOMEM;
|
||||
|
@ -157,8 +167,18 @@ static int slsi_rx_amsdu_deaggregate(struct net_device *dev, struct sk_buff *skb
|
|||
}
|
||||
|
||||
/* If this is not the last subframe then move to the next subframe */
|
||||
if (skb != subframe)
|
||||
skb_pull(skb, (subframe_len + padding));
|
||||
if (skb != subframe) {
|
||||
/* If A-MSDU is not formed correctly (e.g when skb->len < subframe_len + padding),
|
||||
* skb_pull() will return NULL without any manipulation in skb.
|
||||
* It can lead to infinite loop.
|
||||
*/
|
||||
if (!skb_pull(skb, (subframe_len + padding))) {
|
||||
SLSI_NET_ERR(dev, "Invalid subframe + padding length=%d, SKB length=%d\n", subframe_len + padding, skb->len);
|
||||
__skb_queue_purge(msdu_list);
|
||||
slsi_kfree_skb(skb);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
/* If this frame has been filtered out, free the clone and continue */
|
||||
if (skip_frame) {
|
||||
|
|
|
@ -4052,6 +4052,108 @@ void regulator_unregister(struct regulator_dev *rdev)
|
|||
device_unregister(&rdev->dev);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(regulator_unregister);
|
||||
#ifdef CONFIG_SEC_PM_DEBUG
|
||||
struct rdev_check_data {
|
||||
struct regulator_dev *parent;
|
||||
int level;
|
||||
};
|
||||
|
||||
static void regulator_show_enabled_subtree(struct regulator_dev *rdev,
|
||||
int level);
|
||||
|
||||
static int regulator_show_enabled_children(struct device *dev, void *data)
|
||||
{
|
||||
struct regulator_dev *rdev = dev_to_rdev(dev);
|
||||
struct rdev_check_data *check_data = data;
|
||||
|
||||
if (rdev->supply && rdev->supply->rdev == check_data->parent)
|
||||
regulator_show_enabled_subtree(rdev, check_data->level + 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void regulator_show_enabled_subtree(struct regulator_dev *rdev,
|
||||
int level)
|
||||
{
|
||||
struct regulation_constraints *c;
|
||||
struct rdev_check_data check_data;
|
||||
|
||||
if (!rdev)
|
||||
return;
|
||||
|
||||
if (rdev->use_count <= 0)
|
||||
goto out;
|
||||
|
||||
pr_cont("%*s%-*s %3d %4d ",
|
||||
level * 3 + 1, "",
|
||||
30 - level * 3, rdev_get_name(rdev),
|
||||
rdev->use_count, rdev->constraints->initial_mode);
|
||||
|
||||
c = rdev->constraints;
|
||||
if (c) {
|
||||
switch (rdev->desc->type) {
|
||||
case REGULATOR_VOLTAGE:
|
||||
pr_cont("%5dmV %5dmV\n",
|
||||
c->min_uV / 1000, c->max_uV / 1000);
|
||||
break;
|
||||
case REGULATOR_CURRENT:
|
||||
pr_cont("%5dmA %5dmA\n",
|
||||
c->min_uA / 1000, c->max_uA / 1000);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
struct regulator *consumer;
|
||||
|
||||
list_for_each_entry(consumer, &rdev->consumer_list, list) {
|
||||
if (consumer->dev && consumer->dev->class == ®ulator_class)
|
||||
continue;
|
||||
|
||||
pr_cont("%*s%-*s ",
|
||||
(level + 1) * 3 + 1, "",
|
||||
30 - (level + 1) * 3,
|
||||
consumer->dev ? dev_name(consumer->dev) : "deviceless");
|
||||
|
||||
switch (rdev->desc->type) {
|
||||
case REGULATOR_VOLTAGE:
|
||||
pr_cont("%14dmV %5dmV\n",
|
||||
consumer->voltage[PM_SUSPEND_ON].min_uV / 1000,
|
||||
consumer->voltage[PM_SUSPEND_ON].max_uV / 1000);
|
||||
break;
|
||||
case REGULATOR_CURRENT:
|
||||
pr_cont("\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
out:
|
||||
check_data.level = level;
|
||||
check_data.parent = rdev;
|
||||
|
||||
class_for_each_device(®ulator_class, NULL, &check_data,
|
||||
regulator_show_enabled_children);
|
||||
}
|
||||
|
||||
static int _regulator_show_enabled(struct device *dev, void *data)
|
||||
{
|
||||
struct regulator_dev *rdev = dev_to_rdev(dev);
|
||||
|
||||
if (!rdev->supply)
|
||||
regulator_show_enabled_subtree(rdev, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int regulator_show_enabled(void)
|
||||
{
|
||||
pr_info(" regulator use mode min max\n");
|
||||
pr_info("--------------------------------------------------------\n");
|
||||
|
||||
return class_for_each_device(®ulator_class, NULL, NULL,
|
||||
_regulator_show_enabled);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(regulator_show_enabled);
|
||||
#endif /* CONFIG_SEC_PM_DEBUG */
|
||||
|
||||
static int _regulator_suspend_prepare(struct device *dev, void *data)
|
||||
{
|
||||
|
|
81
drivers/security/samsung/five_tee_driver/Kconfig
Normal file
81
drivers/security/samsung/five_tee_driver/Kconfig
Normal file
|
@ -0,0 +1,81 @@
|
|||
#
|
||||
# TEE Driver configuration
|
||||
#
|
||||
|
||||
config FIVE_TEE_DRIVER
|
||||
bool "Integrity TEE Driver"
|
||||
depends on FIVE
|
||||
default y
|
||||
---help---
|
||||
Enable Integrity Trusted Execution Environment support
|
||||
|
||||
choice
|
||||
prompt "FIVE Secure OS"
|
||||
depends on FIVE_TEE_DRIVER
|
||||
default FIVE_USE_TZDEV if TZDEV
|
||||
default FIVE_USE_QSEE if QSEECOM
|
||||
default FIVE_USE_TRUSTONIC
|
||||
---help---
|
||||
Select Secure OS for FIVE TEE Driver
|
||||
|
||||
config FIVE_USE_TRUSTONIC
|
||||
bool "Integrity TEE Driver based on Trustonic Secure OS"
|
||||
depends on TRUSTONIC_TEE || TRUSTONIC_TEE_SUPPORT
|
||||
---help---
|
||||
Use Trustonic as base Trusted Execution Environment
|
||||
|
||||
config FIVE_USE_TZDEV
|
||||
bool "Integrity TEE Driver based on TEEgris Secure OS"
|
||||
depends on TZDEV
|
||||
---help---
|
||||
Use TEEgris as base Trusted Execution Environment
|
||||
|
||||
config FIVE_USE_QSEE
|
||||
bool "Integrity TEE Driver based on QSEE Secure OS"
|
||||
depends on QSEECOM
|
||||
---help---
|
||||
Use QSEE as base Trusted Execution Environment
|
||||
|
||||
endchoice
|
||||
|
||||
config TEE_DRIVER_DEBUG
|
||||
bool "Integrity TEE Driver Debug mode"
|
||||
depends on FIVE_TEE_DRIVER
|
||||
default n
|
||||
---help---
|
||||
Enable Debug mode in TEE Driver
|
||||
|
||||
config FIVE_TRUSTLET_PATH
|
||||
string "FIVE trustlet"
|
||||
depends on FIVE_TEE_DRIVER && FIVE_USE_TRUSTONIC && FIRMWARE_IN_KERNEL
|
||||
default "five/ffffffff000000000000000000000072.tlbin"
|
||||
---help---
|
||||
This option defines FIVE trustlet path which will be built-in kernel
|
||||
|
||||
config FIVE_EARLY_LOAD_TRUSTED_APP
|
||||
bool "Load trusted application in early boot"
|
||||
depends on FIVE_TEE_DRIVER
|
||||
default y if FIVE_USE_QSEE
|
||||
default n
|
||||
help
|
||||
Enable the load of trusted application on during initialization of driver
|
||||
|
||||
config FIVE_SIGN_TA
|
||||
bool "Sign FIVE TA during build"
|
||||
depends on FIVE_TEE_DRIVER && FIVE_USE_QSEE
|
||||
default n
|
||||
help
|
||||
FIVE TA will be signed during build. Otherwise pre-signed TA will be used.
|
||||
|
||||
config FIVE_SIGNCLIENT_PATH
|
||||
string "Path to signclient.jar"
|
||||
depends on FIVE_SIGN_TA
|
||||
help
|
||||
Path to signclient.jar for signing FIVE TA
|
||||
|
||||
config FIVE_PILSPLITTER_PATH
|
||||
string "Path to pil_splitter.py"
|
||||
depends on FIVE_SIGN_TA
|
||||
help
|
||||
Path to pil_splitter.py for preparaing TA to signing
|
||||
|
98
drivers/security/samsung/five_tee_driver/Makefile
Normal file
98
drivers/security/samsung/five_tee_driver/Makefile
Normal file
|
@ -0,0 +1,98 @@
|
|||
#
|
||||
# Integrity TEE Driver
|
||||
#
|
||||
TEEC_CLIENT_PATH := multibuild/source/gp-api/client
|
||||
PROTOCOL_PATH := multibuild/source/gp-api/protocol
|
||||
FIVE_TEE_DRIVER_PATH := drivers/security/samsung/five_tee_driver
|
||||
|
||||
obj-$(CONFIG_FIVE_TEE_DRIVER) += itee_driver.o
|
||||
|
||||
itee_driver-objs += five_tee_driver.o
|
||||
|
||||
ccflags-$(CONFIG_FIVE_TEE_DRIVER) += -Isecurity/samsung/five \
|
||||
-I$(FIVE_TEE_DRIVER_PATH)/$(PROTOCOL_PATH) \
|
||||
-I$(FIVE_TEE_DRIVER_PATH)/$(TEEC_CLIENT_PATH)
|
||||
|
||||
ccflags-$(CONFIG_FIVE_USE_TRUSTONIC) += -DCONFIG_TRUSTONIC
|
||||
ccflags-$(CONFIG_FIVE_USE_TZDEV) += -DCONFIG_TEEGRIS
|
||||
ccflags-$(CONFIG_FIVE_USE_QSEE) += -DCONFIG_QSEE
|
||||
|
||||
# Trustonic
|
||||
obj-$(CONFIG_FIVE_USE_TRUSTONIC) += $(TEEC_CLIENT_PATH)/tee_client_api.o \
|
||||
$(PROTOCOL_PATH)/teec_param_utils.o \
|
||||
$(TEEC_CLIENT_PATH)/teec_common_tbase.o \
|
||||
$(TEEC_CLIENT_PATH)/teec_operation_tbase.o \
|
||||
$(TEEC_CLIENT_PATH)/tee_client_api.o
|
||||
|
||||
ccflags-$(CONFIG_FIVE_USE_TRUSTONIC) += -I$(FIVE_TEE_DRIVER_PATH)/multibuild/include/gp-api
|
||||
ifeq ($(CONFIG_FIVE_USE_TRUSTONIC), y)
|
||||
ifeq ($(CONFIG_SOC_EXYNOS7570), y)
|
||||
PLATFORM := exynos7570
|
||||
ccflags-$(CONFIG_FIVE_TEE_DRIVER) += -Idrivers/gud/gud-$(PLATFORM)/MobiCoreDriver
|
||||
ccflags-$(CONFIG_FIVE_TEE_DRIVER) += -Idrivers/gud/gud-$(PLATFORM)/MobiCoreDriver/public
|
||||
else ifeq ($(CONFIG_SOC_EXYNOS7870), y)
|
||||
PLATFORM := exynos7870
|
||||
ccflags-$(CONFIG_FIVE_TEE_DRIVER) += -Idrivers/gud/gud-$(PLATFORM)/MobiCoreDriver
|
||||
ccflags-$(CONFIG_FIVE_TEE_DRIVER) += -Idrivers/gud/gud-$(PLATFORM)/MobiCoreDriver/public
|
||||
else ifeq ($(CONFIG_SOC_EXYNOS7885), y)
|
||||
PLATFORM := exynos7885
|
||||
ccflags-$(CONFIG_FIVE_TEE_DRIVER) += -Idrivers/gud/gud-$(PLATFORM)/MobiCoreDriver
|
||||
ccflags-$(CONFIG_FIVE_TEE_DRIVER) += -Idrivers/gud/gud-$(PLATFORM)/MobiCoreDriver/public
|
||||
else ifeq ($(CONFIG_SOC_EXYNOS9810), y)
|
||||
PLATFORM := exynos9810
|
||||
ccflags-$(CONFIG_FIVE_TEE_DRIVER) += -Idrivers/gud/gud-$(PLATFORM)/MobiCoreDriver
|
||||
ccflags-$(CONFIG_FIVE_TEE_DRIVER) += -Idrivers/gud/gud-$(PLATFORM)/MobiCoreDriver/public
|
||||
else ifeq ($(CONFIG_SOC_EXYNOS9820), y)
|
||||
PLATFORM := exynos9820
|
||||
ccflags-$(CONFIG_FIVE_TEE_DRIVER) += -Idrivers/gud/gud-$(PLATFORM)/MobiCoreDriver
|
||||
ccflags-$(CONFIG_FIVE_TEE_DRIVER) += -Idrivers/gud/gud-$(PLATFORM)/MobiCoreDriver/public
|
||||
else ifeq ($(CONFIG_SOC_EXYNOS9610), y)
|
||||
PLATFORM := exynos9610
|
||||
ccflags-$(CONFIG_FIVE_TEE_DRIVER) += -Idrivers/gud/gud-$(PLATFORM)/MobiCoreDriver
|
||||
ccflags-$(CONFIG_FIVE_TEE_DRIVER) += -Idrivers/gud/gud-$(PLATFORM)/MobiCoreDriver/public
|
||||
else ifeq ($(CONFIG_MACH_MT6768), y)
|
||||
ccflags-$(CONFIG_FIVE_TEE_DRIVER) += -Idrivers/misc/mediatek/gud/410/MobiCoreDriver
|
||||
ccflags-$(CONFIG_FIVE_TEE_DRIVER) += -Idrivers/misc/mediatek/gud/410/MobiCoreDriver/public
|
||||
else
|
||||
$(error "Unknown SoC")
|
||||
endif
|
||||
endif
|
||||
|
||||
# QSEE
|
||||
obj-$(CONFIG_FIVE_USE_QSEE) += $(TEEC_CLIENT_PATH)/tee_client_api.o \
|
||||
$(PROTOCOL_PATH)/teec_param_utils.o \
|
||||
$(TEEC_CLIENT_PATH)/teec_common_qsee.o \
|
||||
$(TEEC_CLIENT_PATH)/teec_operation_qsee.o
|
||||
|
||||
ccflags-$(CONFIG_FIVE_USE_QSEE) += -I$(FIVE_TEE_DRIVER_PATH)/multibuild/include/gp-api \
|
||||
-Idrivers/misc
|
||||
aflags-$(CONFIG_FIVE_USE_QSEE) += -I$(srctree)
|
||||
|
||||
# Teegris
|
||||
ifeq ($(CONFIG_SOC_EXYNOS7570), y)
|
||||
use_teegris_v2 := y
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SOC_EXYNOS7870), y)
|
||||
use_teegris_v2 := y
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SOC_EXYNOS7885), y)
|
||||
ifeq ($(CONFIG_TEEGRIS_VERSION), 3)
|
||||
ccflags-$(CONFIG_FIVE_USE_TZDEV) += -Idrivers/misc/tzdev/3.0/include/tzdev
|
||||
else
|
||||
use_teegris_v2 := y
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(use_teegris_v2), y)
|
||||
obj-$(CONFIG_FIVE_USE_TZDEV) += $(TEEC_CLIENT_PATH)/teec_common_teegris_v2.o \
|
||||
$(TEEC_CLIENT_PATH)/tee_client_api.o \
|
||||
$(PROTOCOL_PATH)/teec_param_utils.o \
|
||||
$(TEEC_CLIENT_PATH)/teec_operation_teegris_v2.o
|
||||
ccflags-$(CONFIG_FIVE_USE_TZDEV) += -Idrivers/misc/tzdev/include \
|
||||
-I$(FIVE_TEE_DRIVER_PATH)/multibuild/include/gp-api
|
||||
else
|
||||
obj-$(CONFIG_FIVE_USE_TZDEV) += $(TEEC_CLIENT_PATH)/teec_operation_teegris_v3.o
|
||||
ccflags-$(CONFIG_FIVE_USE_TZDEV) += -Idrivers/misc/tzdev/include/tzdev
|
||||
endif
|
52
drivers/security/samsung/five_tee_driver/five_ta_uuid.h
Normal file
52
drivers/security/samsung/five_tee_driver/five_ta_uuid.h
Normal file
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* TEE UUID
|
||||
*
|
||||
* Copyright (C) 2017 Samsung Electronics, Inc.
|
||||
* Egor Uleyskiy, <e.uleyskiy@samsung.com>
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef __FIVE_TEE_UUID_H__
|
||||
#define __FIVE_TEE_UUID_H__
|
||||
|
||||
#if defined(CONFIG_TEEGRIS)
|
||||
static const TEEC_UUID five_ta_uuid = {
|
||||
.timeLow = 0x00000000,
|
||||
.timeMid = 0x0000,
|
||||
.timeHiAndVersion = 0x0000,
|
||||
.clockSeqAndNode = {0x00, 0x00, 0x00, 0x00, 0x46, 0x49, 0x56, 0x45},
|
||||
};
|
||||
#elif defined(CONFIG_QSEECOM)
|
||||
#ifdef CONFIG_ARCH_MSM8917
|
||||
static const TEEC_UUID five_ta_uuid = {
|
||||
.timeLow = 0x6d736d38,
|
||||
.timeMid = 0x3931,
|
||||
.timeHiAndVersion = 0x372f,
|
||||
.clockSeqAndNode = {0x66, 0x69, 0x76, 0x65, 0x00, 0x00, 0x00, 0x00},
|
||||
};
|
||||
#else
|
||||
static const TEEC_UUID five_ta_uuid = {
|
||||
.timeLow = 0x66697665,
|
||||
.timeMid = 0x0000,
|
||||
.timeHiAndVersion = 0x0000,
|
||||
.clockSeqAndNode = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
};
|
||||
#endif // CONFIG_ARCH_MSM8917
|
||||
#elif defined(CONFIG_TRUSTONIC)
|
||||
static const TEEC_UUID five_ta_uuid = {
|
||||
.timeLow = 0xffffffff,
|
||||
.timeMid = 0x0000,
|
||||
.timeHiAndVersion = 0x0000,
|
||||
.clockSeqAndNode = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x72},
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif /* __FIVE_TEE_UUID_H__ */
|
722
drivers/security/samsung/five_tee_driver/five_tee_driver.c
Normal file
722
drivers/security/samsung/five_tee_driver/five_tee_driver.c
Normal file
|
@ -0,0 +1,722 @@
|
|||
/*
|
||||
* TEE Driver
|
||||
*
|
||||
* Copyright (C) 2016 Samsung Electronics, Inc.
|
||||
* Egor Uleyskiy, <e.uleyskiy@samsung.com>
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <five_tee_interface.h>
|
||||
#include "tee_client_api.h"
|
||||
#include "five_ta_uuid.h"
|
||||
#include "five_audit.h"
|
||||
#include "teec_operation.h"
|
||||
|
||||
#ifdef CONFIG_TEE_DRIVER_DEBUG
|
||||
#include <linux/uaccess.h>
|
||||
#endif
|
||||
|
||||
static DEFINE_MUTEX(itee_driver_lock);
|
||||
static char is_initialized;
|
||||
static TEEC_Context *context;
|
||||
static TEEC_Session *session;
|
||||
static DEFINE_SPINLOCK(tee_msg_lock);
|
||||
static LIST_HEAD(tee_msg_queue);
|
||||
struct task_struct *tee_msg_task;
|
||||
|
||||
#define MAX_HASH_LEN 64
|
||||
|
||||
struct tci_msg {
|
||||
uint8_t hash_algo;
|
||||
uint8_t hash[MAX_HASH_LEN];
|
||||
uint8_t signature[MAX_HASH_LEN];
|
||||
uint16_t label_len;
|
||||
uint8_t label[0];
|
||||
} __attribute__((packed));
|
||||
|
||||
#define CMD_SIGN 1
|
||||
#define CMD_VERIFY 2
|
||||
|
||||
#define SEND_CMD_RETRY 1
|
||||
|
||||
static int load_trusted_app(void);
|
||||
static void unload_trusted_app(void);
|
||||
static int send_cmd(unsigned int cmd,
|
||||
enum hash_algo algo,
|
||||
const void *hash,
|
||||
size_t hash_len,
|
||||
const void *label,
|
||||
size_t label_len,
|
||||
void *signature,
|
||||
size_t *signature_len);
|
||||
static int send_cmd_with_retry(unsigned int cmd,
|
||||
enum hash_algo algo,
|
||||
const void *hash,
|
||||
size_t hash_len,
|
||||
const void *label,
|
||||
size_t label_len,
|
||||
void *signature,
|
||||
size_t *signature_len);
|
||||
|
||||
struct tee_msg {
|
||||
struct completion *comp;
|
||||
unsigned int cmd;
|
||||
enum hash_algo algo;
|
||||
const void *hash;
|
||||
size_t hash_len;
|
||||
const void *label;
|
||||
size_t label_len;
|
||||
void *signature;
|
||||
size_t *signature_len;
|
||||
int rc;
|
||||
struct list_head queue;
|
||||
};
|
||||
|
||||
static int tee_msg_thread(void *arg)
|
||||
{
|
||||
for (;;) {
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
if (kthread_should_stop()) {
|
||||
set_current_state(TASK_RUNNING);
|
||||
break;
|
||||
}
|
||||
if (list_empty(&tee_msg_queue))
|
||||
schedule();
|
||||
set_current_state(TASK_RUNNING);
|
||||
|
||||
spin_lock(&tee_msg_lock);
|
||||
while (!list_empty(&tee_msg_queue)) {
|
||||
struct tee_msg *send_cmd_args;
|
||||
int rc;
|
||||
|
||||
send_cmd_args = list_entry(tee_msg_queue.next,
|
||||
struct tee_msg, queue);
|
||||
list_del_init(&send_cmd_args->queue);
|
||||
spin_unlock(&tee_msg_lock);
|
||||
|
||||
rc = send_cmd_with_retry(send_cmd_args->cmd,
|
||||
send_cmd_args->algo,
|
||||
send_cmd_args->hash,
|
||||
send_cmd_args->hash_len,
|
||||
send_cmd_args->label,
|
||||
send_cmd_args->label_len,
|
||||
send_cmd_args->signature,
|
||||
send_cmd_args->signature_len);
|
||||
send_cmd_args->rc = rc;
|
||||
// when processing tee_iovec comp is not NULL
|
||||
// only for last cmd in array
|
||||
if (send_cmd_args->comp)
|
||||
complete(send_cmd_args->comp);
|
||||
spin_lock(&tee_msg_lock);
|
||||
}
|
||||
spin_unlock(&tee_msg_lock);
|
||||
}
|
||||
mutex_lock(&itee_driver_lock);
|
||||
unload_trusted_app();
|
||||
mutex_unlock(&itee_driver_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int send_cmd(unsigned int cmd,
|
||||
enum hash_algo algo,
|
||||
const void *hash,
|
||||
size_t hash_len,
|
||||
const void *label,
|
||||
size_t label_len,
|
||||
void *signature,
|
||||
size_t *signature_len)
|
||||
{
|
||||
TEEC_Operation operation = {};
|
||||
TEEC_SharedMemory shmem = {0};
|
||||
TEEC_Result rc;
|
||||
uint32_t origin;
|
||||
struct tci_msg *msg = NULL;
|
||||
size_t msg_len;
|
||||
size_t sig_len;
|
||||
const bool inout_direction = cmd == CMD_SIGN ? true : false;
|
||||
|
||||
if (!hash || !hash_len ||
|
||||
!signature || !signature_len || !(*signature_len))
|
||||
return -EINVAL;
|
||||
|
||||
msg_len = sizeof(*msg) + label_len;
|
||||
if (label_len > PAGE_SIZE || msg_len > PAGE_SIZE)
|
||||
return -EINVAL;
|
||||
|
||||
switch (algo) {
|
||||
case HASH_ALGO_SHA1:
|
||||
if (hash_len != SHA1_DIGEST_SIZE)
|
||||
return -EINVAL;
|
||||
sig_len = SHA1_DIGEST_SIZE;
|
||||
break;
|
||||
case HASH_ALGO_SHA256:
|
||||
if (hash_len != SHA256_DIGEST_SIZE)
|
||||
return -EINVAL;
|
||||
sig_len = SHA256_DIGEST_SIZE;
|
||||
break;
|
||||
case HASH_ALGO_SHA512:
|
||||
if (hash_len != SHA512_DIGEST_SIZE)
|
||||
return -EINVAL;
|
||||
sig_len = SHA512_DIGEST_SIZE;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (cmd == CMD_SIGN && sig_len > *signature_len)
|
||||
return -EINVAL;
|
||||
if (cmd == CMD_VERIFY && sig_len != *signature_len)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&itee_driver_lock);
|
||||
if (!is_initialized) {
|
||||
rc = load_trusted_app();
|
||||
pr_info("FIVE: Initialize trusted app, ret: %d\n", rc);
|
||||
if (rc) {
|
||||
mutex_unlock(&itee_driver_lock);
|
||||
rc = -EIO;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
shmem.buffer = NULL;
|
||||
shmem.size = msg_len;
|
||||
shmem.flags = TEEC_MEM_INPUT;
|
||||
if (inout_direction)
|
||||
shmem.flags |= TEEC_MEM_OUTPUT;
|
||||
|
||||
rc = TEEC_AllocateSharedMemory(context, &shmem);
|
||||
if (rc != TEEC_SUCCESS || shmem.buffer == NULL) {
|
||||
mutex_unlock(&itee_driver_lock);
|
||||
five_audit_tee_msg("send_cmd",
|
||||
"TEEC_AllocateSharedMemory is failed", rc, 0);
|
||||
rc = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
msg = (struct tci_msg *)shmem.buffer;
|
||||
|
||||
msg->hash_algo = algo;
|
||||
memcpy(msg->hash, hash, hash_len);
|
||||
msg->label_len = label_len;
|
||||
if (label_len)
|
||||
memcpy(msg->label, label, label_len);
|
||||
|
||||
if (cmd == CMD_VERIFY)
|
||||
memcpy(msg->signature, signature, sig_len);
|
||||
|
||||
FillOperationSharedMem(&shmem, &operation, inout_direction);
|
||||
|
||||
rc = TEEC_InvokeCommand(session, cmd, &operation, &origin);
|
||||
|
||||
mutex_unlock(&itee_driver_lock);
|
||||
|
||||
if (rc == TEEC_SUCCESS) {
|
||||
if (origin != TEEC_ORIGIN_TRUSTED_APP) {
|
||||
rc = -EIO;
|
||||
five_audit_tee_msg("send_cmd",
|
||||
"TEEC_InvokeCommand is failed", rc, origin);
|
||||
}
|
||||
} else {
|
||||
five_audit_tee_msg("send_cmd", "TEEC_InvokeCommand is failed.",
|
||||
rc, origin);
|
||||
}
|
||||
|
||||
if (rc == TEEC_SUCCESS && cmd == CMD_SIGN) {
|
||||
memcpy(signature, msg->signature, sig_len);
|
||||
*signature_len = sig_len;
|
||||
}
|
||||
|
||||
TEEC_ReleaseSharedMemory(&shmem);
|
||||
out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int send_cmd_kthread(unsigned int cmd,
|
||||
enum hash_algo algo,
|
||||
const void *hash,
|
||||
size_t hash_len,
|
||||
const void *label,
|
||||
size_t label_len,
|
||||
void *signature,
|
||||
size_t *signature_len)
|
||||
{
|
||||
struct completion cmd_sent;
|
||||
struct tee_msg cmd_msg;
|
||||
|
||||
init_completion(&cmd_sent);
|
||||
|
||||
cmd_msg.comp = &cmd_sent;
|
||||
cmd_msg.cmd = cmd;
|
||||
cmd_msg.algo = algo;
|
||||
cmd_msg.hash = hash;
|
||||
cmd_msg.hash_len = hash_len;
|
||||
cmd_msg.label = label;
|
||||
cmd_msg.label_len = label_len;
|
||||
cmd_msg.signature = signature;
|
||||
cmd_msg.signature_len = signature_len;
|
||||
cmd_msg.rc = -EBADMSG;
|
||||
|
||||
spin_lock(&tee_msg_lock);
|
||||
list_add_tail(&cmd_msg.queue, &tee_msg_queue);
|
||||
spin_unlock(&tee_msg_lock);
|
||||
wake_up_process(tee_msg_task);
|
||||
wait_for_completion(&cmd_sent);
|
||||
return cmd_msg.rc;
|
||||
}
|
||||
|
||||
static int send_cmd_with_retry(unsigned int cmd,
|
||||
enum hash_algo algo,
|
||||
const void *hash,
|
||||
size_t hash_len,
|
||||
const void *label,
|
||||
size_t label_len,
|
||||
void *signature,
|
||||
size_t *signature_len)
|
||||
{
|
||||
int rc;
|
||||
unsigned int retry_num = SEND_CMD_RETRY;
|
||||
|
||||
do {
|
||||
bool need_retry = false;
|
||||
|
||||
rc = send_cmd(cmd, algo,
|
||||
hash, hash_len, label, label_len,
|
||||
signature, signature_len);
|
||||
|
||||
need_retry = (rc == TEEC_ERROR_COMMUNICATION ||
|
||||
rc == TEEC_ERROR_TARGET_DEAD);
|
||||
if (need_retry && retry_num) {
|
||||
pr_err("FIVE: TA got the fatal error rc=%d. Try again\n",
|
||||
rc);
|
||||
mutex_lock(&itee_driver_lock);
|
||||
unload_trusted_app();
|
||||
mutex_unlock(&itee_driver_lock);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} while (retry_num--);
|
||||
|
||||
if (rc == TEEC_ERROR_ACCESS_DENIED) {
|
||||
five_audit_tee_msg("send_cmd_with_retry",
|
||||
"TA got TEEC_ERROR_ACCESS_DENIED", rc, 0);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int send_cmd_kthread_vec(struct tee_msg *cmd_iovec, const size_t iovcnt)
|
||||
{
|
||||
int rc = 0;
|
||||
struct completion cmd_sent;
|
||||
size_t i;
|
||||
|
||||
init_completion(&cmd_sent);
|
||||
cmd_iovec[iovcnt - 1].comp = &cmd_sent;
|
||||
|
||||
for (i = 0; i < iovcnt; ++i) {
|
||||
spin_lock(&tee_msg_lock);
|
||||
list_add_tail(&cmd_iovec[i].queue, &tee_msg_queue);
|
||||
spin_unlock(&tee_msg_lock);
|
||||
}
|
||||
|
||||
wake_up_process(tee_msg_task);
|
||||
wait_for_completion(&cmd_sent);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int verify_hmac(const struct tee_iovec *verify_args)
|
||||
{
|
||||
return send_cmd_kthread(CMD_VERIFY, verify_args->algo,
|
||||
verify_args->hash, verify_args->hash_len,
|
||||
verify_args->label, verify_args->label_len,
|
||||
verify_args->signature,
|
||||
(size_t *)&verify_args->signature_len);
|
||||
}
|
||||
|
||||
static int verify_hmac_vec(struct tee_iovec *verify_iovec,
|
||||
const size_t verify_iovcnt)
|
||||
{
|
||||
int rc = 0;
|
||||
struct tee_msg *cmd_vec;
|
||||
size_t i;
|
||||
|
||||
cmd_vec = kcalloc(verify_iovcnt, sizeof(*cmd_vec), GFP_KERNEL);
|
||||
if (!cmd_vec)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < verify_iovcnt; ++i) {
|
||||
cmd_vec[i].cmd = CMD_VERIFY;
|
||||
cmd_vec[i].algo = verify_iovec[i].algo;
|
||||
cmd_vec[i].hash = verify_iovec[i].hash;
|
||||
cmd_vec[i].hash_len = verify_iovec[i].hash_len;
|
||||
cmd_vec[i].label = verify_iovec[i].label;
|
||||
cmd_vec[i].label_len = verify_iovec[i].label_len;
|
||||
cmd_vec[i].signature = (void *)verify_iovec[i].signature;
|
||||
cmd_vec[i].signature_len =
|
||||
(size_t *)&verify_iovec[i].signature_len;
|
||||
cmd_vec[i].rc = -EBADMSG;
|
||||
}
|
||||
|
||||
rc = send_cmd_kthread_vec(cmd_vec, verify_iovcnt);
|
||||
|
||||
for (i = 0; i < verify_iovcnt; ++i)
|
||||
verify_iovec[i].rc = cmd_vec[i].rc;
|
||||
|
||||
kfree(cmd_vec);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int sign_hmac(struct tee_iovec *sign_args)
|
||||
{
|
||||
return send_cmd_kthread(CMD_SIGN, sign_args->algo,
|
||||
sign_args->hash, sign_args->hash_len,
|
||||
sign_args->label, sign_args->label_len,
|
||||
sign_args->signature,
|
||||
&sign_args->signature_len);
|
||||
}
|
||||
|
||||
static int sign_hmac_vec(struct tee_iovec *sign_iovec,
|
||||
const size_t iovcnt)
|
||||
{
|
||||
int rc = 0;
|
||||
struct tee_msg *cmd_vec;
|
||||
size_t i;
|
||||
|
||||
cmd_vec = kcalloc(iovcnt, sizeof(*cmd_vec), GFP_KERNEL);
|
||||
if (!cmd_vec)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < iovcnt; ++i) {
|
||||
cmd_vec[i].cmd = CMD_SIGN;
|
||||
cmd_vec[i].algo = sign_iovec[i].algo;
|
||||
cmd_vec[i].hash = sign_iovec[i].hash;
|
||||
cmd_vec[i].hash_len = sign_iovec[i].hash_len;
|
||||
cmd_vec[i].label = sign_iovec[i].label;
|
||||
cmd_vec[i].label_len = sign_iovec[i].label_len;
|
||||
cmd_vec[i].signature = sign_iovec[i].signature;
|
||||
cmd_vec[i].signature_len = &sign_iovec[i].signature_len;
|
||||
cmd_vec[i].rc = -EBADMSG;
|
||||
}
|
||||
|
||||
rc = send_cmd_kthread_vec(cmd_vec, iovcnt);
|
||||
|
||||
for (i = 0; i < iovcnt; ++i)
|
||||
sign_iovec[i].rc = cmd_vec[i].rc;
|
||||
|
||||
kfree(cmd_vec);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int load_trusted_app(void)
|
||||
{
|
||||
TEEC_Result rc;
|
||||
uint32_t origin;
|
||||
|
||||
context = kzalloc(sizeof(*context), GFP_KERNEL);
|
||||
if (!context) {
|
||||
pr_err("FIVE: Can't allocate context\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
rc = TEEC_InitializeContext(NULL, context);
|
||||
if (rc) {
|
||||
five_audit_tee_msg("load_trusted_app", "Can't initialize context",
|
||||
rc, 0);
|
||||
goto error;
|
||||
}
|
||||
|
||||
session = kzalloc(sizeof(*session), GFP_KERNEL);
|
||||
if (!session) {
|
||||
pr_err("FIVE: Can't allocate session\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
rc = TEEC_OpenSession(context, session,
|
||||
&five_ta_uuid, 0, NULL, NULL, &origin);
|
||||
if (rc) {
|
||||
five_audit_tee_msg("load_trusted_app", "Can't open session",
|
||||
rc, origin);
|
||||
goto error;
|
||||
}
|
||||
|
||||
is_initialized = 1;
|
||||
|
||||
return 0;
|
||||
error:
|
||||
TEEC_FinalizeContext(context);
|
||||
kfree(session);
|
||||
kfree(context);
|
||||
session = NULL;
|
||||
context = NULL;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int register_tee_driver(void)
|
||||
{
|
||||
struct five_tee_driver_fns fn = {
|
||||
.verify_hmac = verify_hmac,
|
||||
.verify_hmac_vec = verify_hmac_vec,
|
||||
.sign_hmac = sign_hmac,
|
||||
.sign_hmac_vec = sign_hmac_vec,
|
||||
};
|
||||
|
||||
return register_five_tee_driver(&fn);
|
||||
}
|
||||
|
||||
static void unregister_tee_driver(void)
|
||||
{
|
||||
unregister_five_tee_driver();
|
||||
/* Don't close session with TA when */
|
||||
/* tee_integrity_driver has been unloaded */
|
||||
}
|
||||
|
||||
static void unload_trusted_app(void)
|
||||
{
|
||||
is_initialized = 0;
|
||||
TEEC_CloseSession(session);
|
||||
TEEC_FinalizeContext(context);
|
||||
kfree(session);
|
||||
kfree(context);
|
||||
session = NULL;
|
||||
context = NULL;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_TEE_DRIVER_DEBUG
|
||||
|
||||
static int sign_hmac_vec_test(void)
|
||||
{
|
||||
uint8_t hash[SHA1_DIGEST_SIZE][3];
|
||||
uint8_t signature[SHA1_DIGEST_SIZE][3];
|
||||
size_t signature_len[3] = {
|
||||
SHA1_DIGEST_SIZE,
|
||||
SHA1_DIGEST_SIZE,
|
||||
SHA1_DIGEST_SIZE
|
||||
};
|
||||
struct tee_iovec sign_iovec[] = {
|
||||
{
|
||||
.algo = HASH_ALGO_SHA1,
|
||||
.hash = hash[0],
|
||||
.hash_len = SHA1_DIGEST_SIZE,
|
||||
.signature = signature[0],
|
||||
.signature_len = signature_len[0],
|
||||
.label_len = sizeof("label 1"),
|
||||
.label = "label 1",
|
||||
},
|
||||
{
|
||||
.algo = HASH_ALGO_SHA1,
|
||||
.hash = hash[1],
|
||||
.hash_len = SHA1_DIGEST_SIZE,
|
||||
.signature = signature[1],
|
||||
.signature_len = signature_len[1],
|
||||
.label_len = sizeof("label 2 xxxxx"),
|
||||
.label = "label 2 xxxxx",
|
||||
},
|
||||
{
|
||||
.algo = HASH_ALGO_SHA1,
|
||||
.hash = hash[2],
|
||||
.hash_len = SHA1_DIGEST_SIZE,
|
||||
.signature = signature[2],
|
||||
.signature_len = signature_len[2],
|
||||
.label_len = sizeof("label 3 zxzxzzzz"),
|
||||
.label = "label 3 zxzxzzzz",
|
||||
},
|
||||
};
|
||||
|
||||
return sign_hmac_vec(sign_iovec, ARRAY_SIZE(sign_iovec));
|
||||
}
|
||||
|
||||
static int verify_hmac_vec_test(void)
|
||||
{
|
||||
uint8_t hash[SHA1_DIGEST_SIZE][3];
|
||||
uint8_t signature[SHA1_DIGEST_SIZE][3];
|
||||
size_t signature_len[3] = {
|
||||
SHA1_DIGEST_SIZE,
|
||||
SHA1_DIGEST_SIZE,
|
||||
SHA1_DIGEST_SIZE
|
||||
};
|
||||
struct tee_iovec verify_iovec[] = {
|
||||
{
|
||||
.algo = HASH_ALGO_SHA1,
|
||||
.hash = hash[0],
|
||||
.hash_len = SHA1_DIGEST_SIZE,
|
||||
.signature = signature[0],
|
||||
.signature_len = signature_len[0],
|
||||
.label_len = sizeof("label 1"),
|
||||
.label = "label 1",
|
||||
},
|
||||
{
|
||||
.algo = HASH_ALGO_SHA1,
|
||||
.hash = hash[1],
|
||||
.hash_len = SHA1_DIGEST_SIZE,
|
||||
.signature = signature[1],
|
||||
.signature_len = signature_len[1],
|
||||
.label_len = sizeof("label 2 xxxxx"),
|
||||
.label = "label 2 xxxxx",
|
||||
},
|
||||
{
|
||||
.algo = HASH_ALGO_SHA1,
|
||||
.hash = hash[2],
|
||||
.hash_len = SHA1_DIGEST_SIZE,
|
||||
.signature = signature[2],
|
||||
.signature_len = signature_len[2],
|
||||
.label_len = sizeof("label 3 zxzxzzzz"),
|
||||
.label = "label 3 zxzxzzzz",
|
||||
},
|
||||
};
|
||||
|
||||
return verify_hmac_vec(verify_iovec, ARRAY_SIZE(verify_iovec));
|
||||
}
|
||||
|
||||
static ssize_t tee_driver_write(
|
||||
struct file *file, const char __user *buf,
|
||||
size_t count, loff_t *pos)
|
||||
{
|
||||
uint8_t hash[SHA1_DIGEST_SIZE] = {};
|
||||
uint8_t signature[SHA1_DIGEST_SIZE] = {};
|
||||
char command;
|
||||
size_t signature_len = sizeof(signature);
|
||||
|
||||
if (get_user(command, buf))
|
||||
return -EFAULT;
|
||||
|
||||
switch (command) {
|
||||
case '1':
|
||||
pr_info("register_tee_driver: %d\n", register_tee_driver());
|
||||
break;
|
||||
case '2': {
|
||||
struct tee_iovec sign_args = {
|
||||
.algo = HASH_ALGO_SHA1,
|
||||
.hash = hash,
|
||||
.hash_len = sizeof(hash),
|
||||
.signature = signature,
|
||||
.signature_len = signature_len,
|
||||
.label_len = sizeof("label"),
|
||||
.label = "label"
|
||||
};
|
||||
|
||||
pr_info("sign_hmac: %d\n", sign_hmac(&sign_args));
|
||||
break;
|
||||
}
|
||||
case '3': {
|
||||
struct tee_iovec verify_args = {
|
||||
.algo = HASH_ALGO_SHA1,
|
||||
.hash = hash,
|
||||
.hash_len = sizeof(hash),
|
||||
.signature = signature,
|
||||
.signature_len = signature_len,
|
||||
.label_len = sizeof("label"),
|
||||
.label = "label"
|
||||
};
|
||||
|
||||
pr_info("verify_hmac: %d\n", verify_hmac(&verify_args));
|
||||
break;
|
||||
}
|
||||
case '4':
|
||||
pr_info("unregister_tee_driver\n");
|
||||
unregister_tee_driver();
|
||||
mutex_lock(&itee_driver_lock);
|
||||
unload_trusted_app();
|
||||
mutex_unlock(&itee_driver_lock);
|
||||
break;
|
||||
case '5':
|
||||
pr_info("sign_hmac_vec: %d\n", sign_hmac_vec_test());
|
||||
break;
|
||||
case '6':
|
||||
pr_info("verify_hmac_vec: %d\n", verify_hmac_vec_test());
|
||||
break;
|
||||
default:
|
||||
pr_err("FIVE: %s: unknown cmd: %hhx\n", __func__, command);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static const struct file_operations tee_driver_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.write = tee_driver_write
|
||||
};
|
||||
|
||||
static int __init init_fs(void)
|
||||
{
|
||||
struct dentry *debug_file = NULL;
|
||||
umode_t umode =
|
||||
(S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
|
||||
|
||||
debug_file = debugfs_create_file(
|
||||
"integrity_tee_driver", umode, NULL, NULL,
|
||||
&tee_driver_fops);
|
||||
if (IS_ERR_OR_NULL(debug_file))
|
||||
goto error;
|
||||
|
||||
return 0;
|
||||
error:
|
||||
if (debug_file)
|
||||
return -PTR_ERR(debug_file);
|
||||
|
||||
return -EEXIST;
|
||||
}
|
||||
#else
|
||||
static inline int __init init_fs(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int __init tee_driver_init(void)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
mutex_init(&itee_driver_lock);
|
||||
|
||||
#ifdef CONFIG_FIVE_EARLY_LOAD_TRUSTED_APP
|
||||
rc = load_trusted_app();
|
||||
pr_info("FIVE: Initialize trusted app in early boot ret: %d\n", rc);
|
||||
#endif
|
||||
|
||||
tee_msg_task = kthread_run(tee_msg_thread, NULL, "five_tee_msg_thread");
|
||||
if (IS_ERR(tee_msg_task)) {
|
||||
rc = PTR_ERR(tee_msg_task);
|
||||
pr_err("FIVE: Can't create tee_msg_task: %d\n", rc);
|
||||
goto out;
|
||||
}
|
||||
rc = register_tee_driver();
|
||||
if (rc) {
|
||||
pr_err("FIVE: Can't register tee_driver\n");
|
||||
goto out;
|
||||
}
|
||||
rc = init_fs();
|
||||
if (rc) {
|
||||
pr_err("FIVE: Can't initialize debug FS\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void __exit tee_driver_exit(void)
|
||||
{
|
||||
unregister_tee_driver();
|
||||
kthread_stop(tee_msg_task);
|
||||
}
|
||||
|
||||
module_init(tee_driver_init);
|
||||
module_exit(tee_driver_exit);
|
|
@ -0,0 +1,233 @@
|
|||
/*
|
||||
* tee_client_api.h
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* This code is originated from Samsung Electronics proprietary sources.
|
||||
* Author: Iaroslav Makarchuk (i.makarchuk@samsung.com)
|
||||
* Created: 12 Oct 2016
|
||||
*
|
||||
* Copyright (C) 2016 Samsung Electronics, Inc.
|
||||
*
|
||||
* TEE client library
|
||||
*/
|
||||
|
||||
#ifndef __TEE_CLIENT_API_H__
|
||||
#define __TEE_CLIENT_API_H__
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* TEE Client API types and constants definitions */
|
||||
#ifndef __TEEC_ERROR_CODES__
|
||||
#define __TEEC_ERROR_CODES__
|
||||
// The operation was successful
|
||||
#define TEEC_SUCCESS 0x00000000
|
||||
// Non-specific cause
|
||||
#define TEEC_ERROR_GENERIC 0xFFFF0000
|
||||
// Access privileges are not sufficient
|
||||
#define TEEC_ERROR_ACCESS_DENIED 0xFFFF0001
|
||||
// The operation was cancelled
|
||||
#define TEEC_ERROR_CANCEL 0xFFFF0002
|
||||
// Concurrent accesses caused conflict
|
||||
#define TEEC_ERROR_ACCESS_CONFLICT 0xFFFF0003
|
||||
// Too much data for the requested operation was passed
|
||||
#define TEEC_ERROR_EXCESS_DATA 0xFFFF0004
|
||||
// Input data was of invalid format
|
||||
#define TEEC_ERROR_BAD_FORMAT 0xFFFF0005
|
||||
// Input parameters were invalid
|
||||
#define TEEC_ERROR_BAD_PARAMETERS 0xFFFF0006
|
||||
// Operation is not valid in the current state
|
||||
#define TEEC_ERROR_BAD_STATE 0xFFFF0007
|
||||
// The requested data item is not found
|
||||
#define TEEC_ERROR_ITEM_NOT_FOUND 0xFFFF0008
|
||||
// The requested operation should exist but is not yet implemented
|
||||
#define TEEC_ERROR_NOT_IMPLEMENTED 0xFFFF0009
|
||||
// The requested operation is valid but is not supported in this Implementation
|
||||
#define TEEC_ERROR_NOT_SUPPORTED 0xFFFF000A
|
||||
// Expected data was missing
|
||||
#define TEEC_ERROR_NO_DATA 0xFFFF000B
|
||||
// System ran out of resources
|
||||
#define TEEC_ERROR_OUT_OF_MEMORY 0xFFFF000C
|
||||
// The system is busy working on something else.
|
||||
#define TEEC_ERROR_BUSY 0xFFFF000D
|
||||
// Communication with a remote party failed.
|
||||
#define TEEC_ERROR_COMMUNICATION 0xFFFF000E
|
||||
// A security fault was detected.
|
||||
#define TEEC_ERROR_SECURITY 0xFFFF000F
|
||||
// The supplied buffer is too short for the generated output.
|
||||
#define TEEC_ERROR_SHORT_BUFFER 0xFFFF0010
|
||||
|
||||
#define TEEC_ERROR_TARGET_DEAD 0xFFFF3024 // Targed TA panic'ed
|
||||
#define TEEC_ERROR_CORRUPT_OBJECT 0xF0100001
|
||||
#define TEEC_ERROR_STORAGE_NOT_AVAILABLE 0xF0100003
|
||||
#define TEEC_ERROR_SIGNATURE_INVALID 0xFFFF3072 // Invalid TA signature
|
||||
#define TEEC_IMP_MAX 0xFFFEFFFF
|
||||
#define TEEC_RFU_MIN 0xFFFF0011
|
||||
#define TEEC_RFU_MAX 0xFFFFFFFF
|
||||
|
||||
/* Implementation defined error codes */
|
||||
#define TEEC_IMP_MIN 0x00000001
|
||||
// Requested FIPS on/off state failed
|
||||
#define TEEC_ERROR_BAD_FIPS_MODE 0x80000004
|
||||
#define TEEC_ERROR_TA_AUTHORITY_UNKNOWN 0x80000005 // TA AUthority is unknown.
|
||||
#define TEEC_ERROR_DEVICE_ACCESS_DENIED 0x80000007
|
||||
|
||||
#endif
|
||||
|
||||
#define TEEC_ORIGIN_API 0x1
|
||||
#define TEEC_ORIGIN_COMMS 0x2
|
||||
#define TEEC_ORIGIN_TEE 0x3
|
||||
#define TEEC_ORIGIN_TRUSTED_APP 0x4
|
||||
|
||||
typedef uint32_t TEEC_Result;
|
||||
|
||||
#ifndef __TEEC_UUID__
|
||||
#define __TEEC_UUID__
|
||||
/*
|
||||
* Althought this structure is not traveling between worlds, but it used in
|
||||
* tzdaemon, so try to keep TEE_UUID and TEEC_UUID identical.
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t timeLow;
|
||||
uint16_t timeMid;
|
||||
uint16_t timeHiAndVersion;
|
||||
uint8_t clockSeqAndNode[8];
|
||||
} __attribute__((packed)) TEEC_UUID;
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
void *imp;
|
||||
} TEEC_Context;
|
||||
|
||||
typedef struct {
|
||||
void *imp;
|
||||
} TEEC_Session;
|
||||
|
||||
#define TEEC_CONFIG_SHAREDMEM_MAX_SIZE 0x040000
|
||||
|
||||
#define TEEC_MEM_INPUT (1 << 0)
|
||||
#define TEEC_MEM_OUTPUT (1 << 1)
|
||||
|
||||
#define TEEC_NONE 0x00000000
|
||||
#define TEEC_VALUE_INPUT 0x00000001
|
||||
#define TEEC_VALUE_OUTPUT 0x00000002
|
||||
#define TEEC_VALUE_INOUT 0x00000003
|
||||
#define TEEC_MEMREF_TEMP_INPUT 0x00000005
|
||||
#define TEEC_MEMREF_TEMP_OUTPUT 0x00000006
|
||||
#define TEEC_MEMREF_TEMP_INOUT 0x00000007
|
||||
|
||||
#define TEEC_SHMEM_IMP_NONE 0x00000000
|
||||
#define TEEC_SHMEM_IMP_ALLOCED 0x00000001
|
||||
|
||||
typedef struct {
|
||||
TEEC_Context *context;
|
||||
uint32_t flags;
|
||||
} TEEC_SharedMemoryImp;
|
||||
|
||||
typedef struct {
|
||||
void *buffer;
|
||||
size_t size;
|
||||
uint32_t flags;
|
||||
TEEC_SharedMemoryImp imp; /* See above */
|
||||
} TEEC_SharedMemory;
|
||||
|
||||
typedef struct {
|
||||
void *buffer;
|
||||
size_t size;
|
||||
} TEEC_TempMemoryReference;
|
||||
|
||||
typedef struct {
|
||||
TEEC_SharedMemory *parent;
|
||||
size_t size;
|
||||
size_t offset;
|
||||
} TEEC_RegisteredMemoryReference;
|
||||
|
||||
typedef struct {
|
||||
uint32_t a;
|
||||
uint32_t b;
|
||||
} TEEC_Value;
|
||||
|
||||
typedef union {
|
||||
TEEC_TempMemoryReference tmpref;
|
||||
TEEC_RegisteredMemoryReference memref;
|
||||
TEEC_Value value;
|
||||
} TEEC_Parameter;
|
||||
|
||||
#define TEEC_LOGIN_PUBLIC 0x00000000
|
||||
#define TEEC_LOGIN_USER 0x00000001
|
||||
#define TEEC_LOGIN_GROUP 0x00000002
|
||||
#define TEEC_LOGIN_APPLICATION 0x00000004
|
||||
#define TEEC_LOGIN_USER_APPLICATION 0x00000005
|
||||
#define TEEC_LOGIN_GROUP_APPLICATION 0x00000006
|
||||
#define TEEC_LOGIN_IMP_MIN 0x80000000
|
||||
#define TEEC_LOGIN_IMP_MAX 0xEFFFFFFF
|
||||
|
||||
typedef struct {
|
||||
uint32_t started;
|
||||
uint32_t paramTypes;
|
||||
TEEC_Parameter params[4];
|
||||
void *imp;
|
||||
} TEEC_Operation;
|
||||
|
||||
/* This is protection from already implemented GP interface: */
|
||||
#define TEEC_InitializeContext MultibuildInternal_TEEC_InitializeContext
|
||||
#define TEEC_FinalizeContext MultibuildInternal_TEEC_FinalizeContext
|
||||
#define TEEC_OpenSession MultibuildInternal_TEEC_OpenSession
|
||||
#define TEEC_CloseSession MultibuildInternal_TEEC_CloseSession
|
||||
#define TEEC_InvokeCommand MultibuildInternal_TEEC_InvokeCommand
|
||||
#define TEEC_RegisterSharedMemory MultibuildInternal_TEEC_RegisterSharedMemory
|
||||
#define TEEC_AllocateSharedMemory MultibuildInternal_TEEC_AllocateSharedMemory
|
||||
#define TEEC_ReleaseSharedMemory MultibuildInternal_TEEC_ReleaseSharedMemory
|
||||
|
||||
/* TEE Client API functions and macros definitions */
|
||||
|
||||
TEEC_Result TEEC_InitializeContext(const char *name,
|
||||
TEEC_Context *context);
|
||||
|
||||
void TEEC_FinalizeContext(TEEC_Context *context);
|
||||
|
||||
TEEC_Result TEEC_RegisterSharedMemory(TEEC_Context *context,
|
||||
TEEC_SharedMemory *sharedMem);
|
||||
|
||||
TEEC_Result TEEC_AllocateSharedMemory(TEEC_Context *context,
|
||||
TEEC_SharedMemory *sharedMem);
|
||||
|
||||
void TEEC_ReleaseSharedMemory(TEEC_SharedMemory *sharedMem);
|
||||
|
||||
TEEC_Result TEEC_OpenSession(TEEC_Context *context,
|
||||
TEEC_Session *session,
|
||||
const TEEC_UUID *destination,
|
||||
uint32_t connectionMethod,
|
||||
const void *connectionData,
|
||||
TEEC_Operation *operation,
|
||||
uint32_t *returnOrigin);
|
||||
|
||||
void TEEC_CloseSession(TEEC_Session *session);
|
||||
|
||||
TEEC_Result TEEC_InvokeCommand(TEEC_Session *session,
|
||||
uint32_t commandID,
|
||||
TEEC_Operation *operation,
|
||||
uint32_t *returnOrigin);
|
||||
|
||||
#define TEEC_PARAM_TYPES(param0Type, param1Type, param2Type, param3Type) \
|
||||
(uint32_t)(((param0Type) & 0xf) | \
|
||||
(((param1Type) & 0xf) << 4) | \
|
||||
(((param2Type) & 0xf) << 8) | \
|
||||
(((param3Type) & 0xf) << 12))
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __TEE_CLIENT_API_H__ */
|
|
@ -0,0 +1,260 @@
|
|||
/*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* This code is originated from Samsung Electronics proprietary sources.
|
||||
* Author: Iaroslav Makarchuk (i.makarchuk@samsung.com)
|
||||
* Created: 12 Oct 2016
|
||||
*
|
||||
* Copyright (C) 2016 Samsung Electronics, Inc.
|
||||
*/
|
||||
|
||||
#include <linux/slab.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/printk.h>
|
||||
#include "tee_client_api.h"
|
||||
#include "protocol.h"
|
||||
#include "teec_common.h"
|
||||
|
||||
#define CONTEXT_INITIALIZED 0xA7A6A5A4
|
||||
#define MEM_SLOTS_NUM 4
|
||||
|
||||
typedef struct TeecContextStruct {
|
||||
uint32_t initialized;
|
||||
TEEC_SharedMemory *allocated_shmem[MEM_SLOTS_NUM];
|
||||
} TeecContext;
|
||||
|
||||
TEEC_Result TEEC_InvokeCommand(TEEC_Session *session,
|
||||
uint32_t commandID,
|
||||
TEEC_Operation *operation,
|
||||
uint32_t *returnOrigin)
|
||||
{
|
||||
TEEC_Result ret = TEEC_ERROR_BAD_PARAMETERS;
|
||||
PlatformClientImpl *client_impl = GetPlatformClientImpl();
|
||||
|
||||
if (!session || !session->imp)
|
||||
goto exit;
|
||||
|
||||
if (returnOrigin)
|
||||
*returnOrigin = TEEC_ORIGIN_API;
|
||||
|
||||
if (!client_impl || !client_impl->SendCommand) {
|
||||
ret = TEEC_ERROR_NOT_IMPLEMENTED;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ret = client_impl->SendCommand(session->imp,
|
||||
commandID, operation, returnOrigin,
|
||||
MB_INFINITE_TIMEOUT);
|
||||
|
||||
exit:
|
||||
return ret;
|
||||
}
|
||||
|
||||
TEEC_Result TEEC_InitializeContext(const char *name, TEEC_Context *context)
|
||||
{
|
||||
TEEC_Result res = TEEC_ERROR_BAD_PARAMETERS;
|
||||
|
||||
(void) name;
|
||||
if (context) {
|
||||
TeecContext *teec_ctx = kzalloc(sizeof(TeecContext),
|
||||
GFP_KERNEL);
|
||||
if (teec_ctx) {
|
||||
teec_ctx->initialized = CONTEXT_INITIALIZED;
|
||||
context->imp = (void *)teec_ctx;
|
||||
res = TEEC_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void TEEC_FinalizeContext(TEEC_Context *context)
|
||||
{
|
||||
if (context) {
|
||||
TeecContext *teec_ctx = (TeecContext *)context->imp;
|
||||
|
||||
if (teec_ctx) {
|
||||
teec_ctx->initialized = 0;
|
||||
kfree(context->imp);
|
||||
context->imp = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEEC_Result TEEC_OpenSession(TEEC_Context *context,
|
||||
TEEC_Session *session,
|
||||
const TEEC_UUID *destination,
|
||||
uint32_t connectionMethod,
|
||||
const void *connectionData,
|
||||
TEEC_Operation *operation,
|
||||
uint32_t *returnOrigin)
|
||||
{
|
||||
TEEC_Result ret = TEEC_ERROR_BAD_PARAMETERS;
|
||||
PlatformClientImpl *client_impl = GetPlatformClientImpl();
|
||||
/* Fixed waiting initialization of DCI thread in TBase driver */
|
||||
const uint32_t kNumTries = 5;
|
||||
const int32_t kTimeoutMs = 1000;
|
||||
uint32_t elapsed_tries = 0;
|
||||
|
||||
if (!context || !context->imp ||
|
||||
((TeecContext *)(context->imp))->initialized != CONTEXT_INITIALIZED
|
||||
|| !session || !destination) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (returnOrigin)
|
||||
*returnOrigin = TEEC_ORIGIN_API;
|
||||
|
||||
if (!client_impl || !client_impl->SendCommand || !client_impl->LoadTA) {
|
||||
ret = TEEC_ERROR_NOT_IMPLEMENTED;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
session->imp = kzalloc(GetPlatformClientImplSize(), GFP_KERNEL);
|
||||
|
||||
if (!session->imp) {
|
||||
ret = TEEC_ERROR_OUT_OF_MEMORY;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ret = client_impl->LoadTA(session->imp, destination);
|
||||
|
||||
if (ret != TEEC_SUCCESS)
|
||||
goto cleanup;
|
||||
|
||||
do {
|
||||
ret = client_impl->SendCommand(session->imp,
|
||||
PROTOCOL_COMMAND_LOAD, operation, returnOrigin,
|
||||
kTimeoutMs);
|
||||
|
||||
if (TEEC_SUCCESS != ret) {
|
||||
pr_debug(
|
||||
"Try to send %u of %u command in driver: 0x%x.\n",
|
||||
elapsed_tries + 1, kNumTries, ret);
|
||||
}
|
||||
} while ((ret != TEEC_SUCCESS) && (++elapsed_tries < kNumTries));
|
||||
|
||||
if (TEEC_SUCCESS != ret) {
|
||||
pr_debug("Could not send %d commands in driver: 0x%x.\n",
|
||||
kNumTries, ret);
|
||||
client_impl->SendCommand(session->imp, PROTOCOL_COMMAND_UNLOAD,
|
||||
NULL, returnOrigin, MB_INFINITE_TIMEOUT);
|
||||
client_impl->UnloadTA(session->imp);
|
||||
}
|
||||
|
||||
cleanup:
|
||||
if (ret != TEEC_SUCCESS) {
|
||||
kfree(session->imp);
|
||||
session->imp = NULL;
|
||||
}
|
||||
|
||||
exit:
|
||||
return ret;
|
||||
}
|
||||
|
||||
void TEEC_CloseSession(TEEC_Session *session)
|
||||
{
|
||||
uint32_t return_origin;
|
||||
PlatformClientImpl *client_impl = GetPlatformClientImpl();
|
||||
|
||||
if (session && session->imp) {
|
||||
if (client_impl &&
|
||||
client_impl->SendCommand && client_impl->UnloadTA) {
|
||||
client_impl->SendCommand(session->imp,
|
||||
PROTOCOL_COMMAND_UNLOAD, NULL, &return_origin,
|
||||
MB_INFINITE_TIMEOUT);
|
||||
client_impl->UnloadTA(session->imp);
|
||||
}
|
||||
kfree(session->imp);
|
||||
session->imp = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
TEEC_Result TEEC_RegisterSharedMemory(TEEC_Context *context,
|
||||
TEEC_SharedMemory *sharedMem)
|
||||
{
|
||||
TEEC_Result result = TEEC_ERROR_BAD_PARAMETERS;
|
||||
|
||||
if (!context || !sharedMem || !sharedMem->buffer)
|
||||
goto exit;
|
||||
|
||||
if (sharedMem->size > TEEC_CONFIG_SHAREDMEM_MAX_SIZE) {
|
||||
result = TEEC_ERROR_OUT_OF_MEMORY;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
sharedMem->imp.context = context;
|
||||
result = TEEC_SUCCESS;
|
||||
exit:
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline int GetShmemSlotIndex(TeecContext *ctx, TEEC_SharedMemory *mem)
|
||||
{
|
||||
int ret = -1;
|
||||
int i = 0;
|
||||
|
||||
for (i = 0; i < MEM_SLOTS_NUM; i++) {
|
||||
if (ctx->allocated_shmem[i] == mem) {
|
||||
ret = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
TEEC_Result TEEC_AllocateSharedMemory(TEEC_Context *context,
|
||||
TEEC_SharedMemory *sharedMem)
|
||||
{
|
||||
TEEC_Result result = TEEC_ERROR_BAD_PARAMETERS;
|
||||
int ctx_shmem_index = -1;
|
||||
|
||||
if (!context || !context->imp || !sharedMem ||
|
||||
((TeecContext *)(context->imp))->initialized != CONTEXT_INITIALIZED) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ctx_shmem_index =
|
||||
GetShmemSlotIndex((TeecContext *)(context->imp), NULL);
|
||||
|
||||
result = TEEC_ERROR_OUT_OF_MEMORY;
|
||||
if (sharedMem->size > TEEC_CONFIG_SHAREDMEM_MAX_SIZE ||
|
||||
ctx_shmem_index < 0) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
sharedMem->buffer = kzalloc(sharedMem->size, GFP_KERNEL);
|
||||
if (!sharedMem->buffer)
|
||||
goto exit;
|
||||
|
||||
sharedMem->imp.context = context;
|
||||
((TeecContext *)(context->imp))->allocated_shmem[ctx_shmem_index]
|
||||
= sharedMem;
|
||||
result = TEEC_SUCCESS;
|
||||
|
||||
exit:
|
||||
return result;
|
||||
}
|
||||
|
||||
void TEEC_ReleaseSharedMemory(TEEC_SharedMemory *sharedMem)
|
||||
{
|
||||
if (sharedMem &&
|
||||
sharedMem->imp.context && sharedMem->imp.context->imp) {
|
||||
int ctx_shmem_index = GetShmemSlotIndex(
|
||||
(TeecContext *)(sharedMem->imp.context->imp),
|
||||
sharedMem);
|
||||
|
||||
if (ctx_shmem_index >= 0) {
|
||||
((TeecContext *)(sharedMem->imp.context->imp))->
|
||||
allocated_shmem[ctx_shmem_index] = NULL;
|
||||
kzfree(sharedMem->buffer);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* This code is originated from Samsung Electronics proprietary sources.
|
||||
* Author: Iaroslav Makarchuk (i.makarchuk@samsung.com)
|
||||
* Created: 12 Oct 2016
|
||||
*
|
||||
* Copyright (C) 2016 Samsung Electronics, Inc.
|
||||
*/
|
||||
|
||||
#ifndef TEEC_COMMON_H_
|
||||
#define TEEC_COMMON_H_
|
||||
|
||||
#include "tee_client_api.h"
|
||||
#include <linux/types.h>
|
||||
|
||||
#define MB_INFINITE_TIMEOUT (-1)
|
||||
|
||||
typedef TEEC_Result (*ClientImplLoadTA)(void *session, const TEEC_UUID *uuid);
|
||||
typedef TEEC_Result (*ClientImplSendCommand)(void *session,
|
||||
uint32_t command_id,
|
||||
TEEC_Operation *operation, uint32_t *return_origin, int timeout);
|
||||
|
||||
typedef TEEC_Result (*ClientImplUnloadTA)(void *session);
|
||||
typedef void *(*ClientImplAllocateForSession)(void *session, size_t size);
|
||||
typedef void (*ClientImplFreeForSession)(void *session, void *ptr);
|
||||
typedef int (*ClientImplSessionCanRelease)(void *session, void *ptr);
|
||||
|
||||
typedef uint32_t (*ClientMapBuffer)(void *session, void *ptr, size_t size);
|
||||
|
||||
typedef struct PlatformClientImplStruct {
|
||||
ClientImplLoadTA LoadTA;
|
||||
ClientImplUnloadTA UnloadTA;
|
||||
ClientImplSendCommand SendCommand;
|
||||
ClientMapBuffer MapBuffer;
|
||||
ClientImplAllocateForSession AllocateBuffer;
|
||||
ClientImplFreeForSession FreeBuffer;
|
||||
ClientImplSessionCanRelease CanRelease;
|
||||
} PlatformClientImpl;
|
||||
|
||||
PlatformClientImpl *GetPlatformClientImpl(void);
|
||||
size_t GetPlatformClientImplSize(void);
|
||||
#endif /* TEEC_COMMON_H_ */
|
|
@ -0,0 +1,265 @@
|
|||
/*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* This code is originated from Samsung Electronics proprietary sources.
|
||||
* Author: Iaroslav Makarchuk (i.makarchuk@samsung.com)
|
||||
* Created: 12 Oct 2016
|
||||
*
|
||||
* Copyright (C) 2016 Samsung Electronics, Inc.
|
||||
*/
|
||||
|
||||
#include <linux/string.h>
|
||||
#include <linux/bug.h>
|
||||
#include <uapi/linux/qseecom.h>
|
||||
|
||||
#include "teec_common.h"
|
||||
|
||||
#include "protocol.h"
|
||||
#include "qseecom_kernel.h"
|
||||
#include "teec_param_utils.h"
|
||||
#include "linux/errno.h"
|
||||
|
||||
#define MAX_QSEE_UUID_LEN (MAX_APP_NAME_SIZE) // usually 64 bytes
|
||||
#define QSEE_SUCCESS 0
|
||||
|
||||
/* 1. Actually we don't use the response buffer. But RBUF_LEN can't be zero.
|
||||
* 2. The size which is passed to qseecom_start_app must be RBUF_LEN + SBUF_LEN.
|
||||
* 3. There is difference between user space and kernel QSEECOM_ALIGN
|
||||
* implementation. User space one always adds 0x40 to the passed size if
|
||||
* it's already aligned by 0x40 but kernel macro doesn't do it.
|
||||
* QSEECOM_ALIGN_SIZE is 0x40. That's why we add QSEECOM_ALIGN_SIZE
|
||||
* in RBUF_LEN.
|
||||
*/
|
||||
#define SBUF_LEN (sizeof(ProtocolCmd) + MAX_SHAREDMEM_SIZE)
|
||||
#define RBUF_LEN (QSEECOM_ALIGN(SBUF_LEN) - SBUF_LEN + QSEECOM_ALIGN_SIZE)
|
||||
|
||||
typedef struct QseeSessionStruct {
|
||||
struct qseecom_handle *qsee_com_handle;
|
||||
struct qseecom_handle *listener_handle;
|
||||
void *parent_context;
|
||||
TEEC_UUID uuid;
|
||||
} QseeSession;
|
||||
|
||||
static TEEC_Result TeecUuidToQseeUuid(const TEEC_UUID *uuid, char *qsee_uuid)
|
||||
{
|
||||
uint32_t i = 0;
|
||||
uint32_t j = 0;
|
||||
TEEC_Result res = TEEC_SUCCESS;
|
||||
|
||||
if (!uuid || !qsee_uuid) {
|
||||
res = TEEC_ERROR_BAD_PARAMETERS;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
qsee_uuid[i++] = (uuid->timeLow & 0xFF000000) >> 24;
|
||||
qsee_uuid[i++] = (uuid->timeLow & 0xFF0000) >> 16;
|
||||
qsee_uuid[i++] = (uuid->timeLow & 0xFF00) >> 8;
|
||||
qsee_uuid[i++] = (uuid->timeLow & 0xFF);
|
||||
|
||||
qsee_uuid[i++] = (uuid->timeMid & 0xFF00) >> 8;
|
||||
qsee_uuid[i++] = (uuid->timeMid & 0xFF);
|
||||
|
||||
qsee_uuid[i++] = (uuid->timeHiAndVersion & 0xFF00) >> 8;
|
||||
qsee_uuid[i++] = (uuid->timeHiAndVersion & 0xFF);
|
||||
|
||||
for (j = 0; j < (uint32_t)sizeof(uuid->clockSeqAndNode); j++)
|
||||
qsee_uuid[i++] = uuid->clockSeqAndNode[j];
|
||||
|
||||
exit:
|
||||
return res;
|
||||
}
|
||||
|
||||
TEEC_Result QseeUnloadTA(void *ta_session)
|
||||
{
|
||||
TEEC_Result status = TEEC_ERROR_GENERIC;
|
||||
int qsee_res;
|
||||
QseeSession *qsee_session = (QseeSession *)ta_session;
|
||||
|
||||
if (qsee_session->qsee_com_handle == NULL)
|
||||
goto exit;
|
||||
|
||||
qsee_res = qseecom_shutdown_app(&qsee_session->qsee_com_handle);
|
||||
if (qsee_res != QSEE_SUCCESS)
|
||||
goto exit;
|
||||
|
||||
qsee_session->qsee_com_handle = NULL;
|
||||
|
||||
status = TEEC_SUCCESS;
|
||||
exit:
|
||||
return status;
|
||||
}
|
||||
|
||||
TEEC_Result QseeLoadTA(void *ta_session, const TEEC_UUID *uuid)
|
||||
{
|
||||
TEEC_Result status = TEEC_SUCCESS;
|
||||
int qsee_res;
|
||||
char ta_name[MAX_QSEE_UUID_LEN] = "five/";
|
||||
char qsee_uuid[MAX_QSEE_UUID_LEN] = {0};
|
||||
QseeSession *qsee_session = (QseeSession *)ta_session;
|
||||
|
||||
if (!ta_session || !uuid ||
|
||||
TEEC_SUCCESS != TeecUuidToQseeUuid(uuid, qsee_uuid)) {
|
||||
status = TEEC_ERROR_BAD_PARAMETERS;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (strlcat(ta_name, qsee_uuid, sizeof(ta_name)) >= sizeof(ta_name)) {
|
||||
status = TEEC_ERROR_BAD_PARAMETERS;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
memcpy(&qsee_session->uuid, uuid, sizeof(TEEC_UUID));
|
||||
|
||||
BUILD_BUG_ON((SBUF_LEN + RBUF_LEN) & QSEECOM_ALIGN_MASK);
|
||||
|
||||
qsee_res = qseecom_start_app(&qsee_session->qsee_com_handle,
|
||||
ta_name,
|
||||
SBUF_LEN + RBUF_LEN);
|
||||
if (qsee_res != QSEE_SUCCESS) {
|
||||
status = qsee_res == -EINVAL ? TEEC_ERROR_TARGET_DEAD :
|
||||
TEEC_ERROR_GENERIC;
|
||||
}
|
||||
|
||||
exit:
|
||||
return status;
|
||||
}
|
||||
|
||||
TEEC_Result QseeSendCommand(void *ta_session,
|
||||
uint32_t command_id,
|
||||
TEEC_Operation *operation,
|
||||
uint32_t *return_origin,
|
||||
int32_t timeout)
|
||||
{
|
||||
int32_t qsee_res = QSEE_SUCCESS;
|
||||
QseeSession *qsee_session = (QseeSession *)ta_session;
|
||||
ProtocolCmd *command = NULL;
|
||||
TEEC_Result ret = TEEC_ERROR_BAD_PARAMETERS;
|
||||
|
||||
(void)timeout;
|
||||
|
||||
if (!qsee_session)
|
||||
goto exit;
|
||||
|
||||
command = (ProtocolCmd *)qsee_session->qsee_com_handle->sbuf;
|
||||
|
||||
/*
|
||||
* Return origin: "COMMS" by default because of possible
|
||||
* communication errors.
|
||||
*/
|
||||
command->return_origin = TEEC_ORIGIN_COMMS;
|
||||
|
||||
command->cmd_id = command_id;
|
||||
command->param_types = 0;
|
||||
|
||||
if (operation) {
|
||||
command->param_types = operation->paramTypes;
|
||||
ret = FillCommandArgs(command, operation, ta_session);
|
||||
|
||||
if (ret != TEEC_SUCCESS) {
|
||||
command->return_origin = TEEC_ORIGIN_API;
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
/* Call */
|
||||
qsee_res = qseecom_set_bandwidth(qsee_session->qsee_com_handle, true);
|
||||
|
||||
if (qsee_res != QSEE_SUCCESS) {
|
||||
ret = TEEC_ERROR_COMMUNICATION;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Prepare for silent TA death */
|
||||
command->cmd_ret = TEEC_ERROR_TARGET_DEAD;
|
||||
|
||||
/* Send command to TA
|
||||
* Passing zero as response size isn't allowed
|
||||
* that's why it's used QSEECOM_ALIGN_SIZE instead
|
||||
*/
|
||||
qsee_res = qseecom_send_command(qsee_session->qsee_com_handle,
|
||||
qsee_session->qsee_com_handle->sbuf,
|
||||
SBUF_LEN,
|
||||
qsee_session->qsee_com_handle->sbuf,
|
||||
RBUF_LEN);
|
||||
|
||||
if (qsee_res != QSEE_SUCCESS) {
|
||||
if (qsee_res != -EPERM)
|
||||
ret = qsee_res == -EINVAL ? TEEC_ERROR_TARGET_DEAD :
|
||||
TEEC_ERROR_COMMUNICATION;
|
||||
else
|
||||
ret = TEEC_ERROR_ACCESS_DENIED;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
qsee_res = qseecom_set_bandwidth(qsee_session->qsee_com_handle, false);
|
||||
|
||||
if (qsee_res != QSEE_SUCCESS) {
|
||||
ret = (qsee_res == -EINVAL ? TEEC_ERROR_TARGET_DEAD :
|
||||
TEEC_ERROR_COMMUNICATION);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return origin:
|
||||
* "TEE" or "TRUSTED_APP" after communication with TEE.
|
||||
*/
|
||||
ret = command->cmd_ret;
|
||||
|
||||
if (ret == TEEC_SUCCESS && operation) {
|
||||
ret = FillOperationArgs(operation, command);
|
||||
if (ret != TEEC_SUCCESS)
|
||||
command->return_origin = TEEC_ORIGIN_API;
|
||||
}
|
||||
|
||||
exit:
|
||||
if (return_origin && command)
|
||||
*return_origin = command->return_origin;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
PlatformClientImpl g_qsee_platform_impl = {
|
||||
QseeLoadTA,
|
||||
QseeUnloadTA,
|
||||
QseeSendCommand,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
};
|
||||
|
||||
PlatformClientImpl *GetPlatformClientImpl(void)
|
||||
{
|
||||
return &g_qsee_platform_impl;
|
||||
}
|
||||
|
||||
size_t GetPlatformClientImplSize(void)
|
||||
{
|
||||
return sizeof(QseeSession);
|
||||
}
|
||||
|
||||
void ClientImplSetParentContext(void *session, void *context)
|
||||
{
|
||||
QseeSession *qsee_session = (QseeSession *)session;
|
||||
|
||||
if (qsee_session)
|
||||
qsee_session->parent_context = context;
|
||||
}
|
||||
|
||||
void *ClientImplGetParentContext(void *session)
|
||||
{
|
||||
void *ret = NULL;
|
||||
QseeSession *qsee_session = (QseeSession *)session;
|
||||
|
||||
if (qsee_session)
|
||||
ret = qsee_session->parent_context;
|
||||
|
||||
return ret;
|
||||
}
|
|
@ -0,0 +1,327 @@
|
|||
/*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* This code is originated from Samsung Electronics proprietary sources.
|
||||
* Author: Iaroslav Makarchuk (i.makarchuk@samsung.com)
|
||||
* Created: 12 Oct 2016
|
||||
*
|
||||
* Copyright (C) 2016 Samsung Electronics, Inc.
|
||||
*/
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <mobicore_driver_api.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/firmware.h>
|
||||
|
||||
#include "teec_common.h"
|
||||
#include "protocol.h"
|
||||
#include "teec_param_utils.h"
|
||||
|
||||
#define DEVICE_ID MC_DEVICE_ID_DEFAULT
|
||||
#define MC_SPID_SYSTEM 0xFFFFFFFE
|
||||
|
||||
typedef struct TbaseSessionMapInfoStruct {
|
||||
void *src_address;
|
||||
struct mc_bulk_map map_info;
|
||||
} TbaseSessionMapInfo;
|
||||
|
||||
typedef struct TbaseSessionStruct {
|
||||
struct mc_session_handle ta_session;
|
||||
ProtocolCmd *tci_buffer;
|
||||
PersObjectCmd *persistent_object;
|
||||
TbaseSessionMapInfo maps[PARAMS_NUM];
|
||||
void *parent_context;
|
||||
} TbaseSession;
|
||||
|
||||
static TEEC_Result ReadPersistentObjectFromFS(TbaseSession *session,
|
||||
const uint8_t *id,
|
||||
uint8_t *data,
|
||||
uint32_t *data_len)
|
||||
{
|
||||
TEEC_Result result = TEEC_ERROR_NOT_SUPPORTED;
|
||||
return result;
|
||||
}
|
||||
|
||||
static TEEC_Result WritePersistentObjectToFS(TbaseSession *session,
|
||||
const uint8_t *id,
|
||||
const uint8_t *data,
|
||||
uint32_t data_len)
|
||||
{
|
||||
TEEC_Result result = TEEC_ERROR_NOT_SUPPORTED;
|
||||
return result;
|
||||
}
|
||||
|
||||
static void TbaseInitSessionMaps(TbaseSession *session)
|
||||
{
|
||||
if (session)
|
||||
memset(session->maps, 0x00, sizeof(session->maps));
|
||||
}
|
||||
|
||||
static void TbaseCleanSessionMaps(TbaseSession *session)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
if (session) {
|
||||
for (i = 0; i < PARAMS_NUM; i++) {
|
||||
if (session->maps[i].src_address) {
|
||||
mc_unmap(&(session->ta_session),
|
||||
session->maps[i].src_address,
|
||||
&(session->maps[i].map_info));
|
||||
}
|
||||
}
|
||||
memset(session->maps, 0x00, sizeof(session->maps));
|
||||
}
|
||||
}
|
||||
|
||||
TEEC_Result TbaseSendCommand(void *ta_session,
|
||||
uint32_t command_id,
|
||||
TEEC_Operation *operation,
|
||||
uint32_t *return_origin,
|
||||
int32_t timeout)
|
||||
{
|
||||
enum mc_result mc_res = MC_DRV_OK;
|
||||
TEEC_Result ret = TEEC_ERROR_BAD_PARAMETERS;
|
||||
TbaseSession *tbase_session = (TbaseSession *)ta_session;
|
||||
|
||||
if (!tbase_session)
|
||||
goto exit;
|
||||
|
||||
/* tci_buffer is supposed to be not NULL */
|
||||
tbase_session->tci_buffer->return_origin = TEEC_ORIGIN_API;
|
||||
|
||||
tbase_session->tci_buffer->cmd_id = command_id;
|
||||
tbase_session->tci_buffer->param_types = 0;
|
||||
tbase_session->tci_buffer->cmd_ret = TEEC_ERROR_COMMUNICATION;
|
||||
|
||||
TbaseInitSessionMaps(tbase_session);
|
||||
|
||||
if (operation) {
|
||||
tbase_session->tci_buffer->param_types = operation->paramTypes;
|
||||
ret = FillCommandArgs(tbase_session->tci_buffer,
|
||||
operation, tbase_session);
|
||||
|
||||
if (ret != TEEC_SUCCESS)
|
||||
goto exit;
|
||||
}
|
||||
|
||||
do {
|
||||
/* Clear PO command! */
|
||||
tbase_session->persistent_object->cmd_id = 0x00;
|
||||
|
||||
/* Call */
|
||||
mc_res = mc_notify(&tbase_session->ta_session);
|
||||
|
||||
/* Return origin: "COMMS" to handle several conditions below */
|
||||
tbase_session->tci_buffer->return_origin = TEEC_ORIGIN_COMMS;
|
||||
|
||||
if (mc_res != MC_DRV_OK) {
|
||||
ret = TEEC_ERROR_COMMUNICATION;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
mc_res = mc_wait_notification(&tbase_session->ta_session,
|
||||
timeout);
|
||||
|
||||
if (mc_res != MC_DRV_OK) {
|
||||
ret = TEEC_ERROR_COMMUNICATION;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Return origin: "TRUSTED_APP" to handle PO command emulation */
|
||||
tbase_session->tci_buffer->return_origin =
|
||||
TEEC_ORIGIN_TRUSTED_APP;
|
||||
|
||||
if (tbase_session->persistent_object->cmd_id) {
|
||||
switch (tbase_session->persistent_object->cmd_id) {
|
||||
case PROTOCOL_COMMAND_READF: {
|
||||
uint32_t cmd_ret;
|
||||
|
||||
cmd_ret = ReadPersistentObjectFromFS(
|
||||
tbase_session,
|
||||
tbase_session->persistent_object->id,
|
||||
tbase_session->persistent_object->data,
|
||||
&tbase_session->persistent_object->data_len);
|
||||
|
||||
tbase_session->tci_buffer->cmd_ret = cmd_ret;
|
||||
break;
|
||||
}
|
||||
case PROTOCOL_COMMAND_WRITEF: {
|
||||
uint32_t cmd_ret;
|
||||
|
||||
cmd_ret = WritePersistentObjectToFS(
|
||||
tbase_session,
|
||||
tbase_session->persistent_object->id,
|
||||
tbase_session->persistent_object->data,
|
||||
tbase_session->persistent_object->data_len);
|
||||
|
||||
tbase_session->tci_buffer->cmd_ret = cmd_ret;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
uint32_t cmd_ret = TEEC_ERROR_NOT_SUPPORTED;
|
||||
|
||||
tbase_session->tci_buffer->cmd_ret = cmd_ret;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} while (tbase_session->persistent_object->cmd_id);
|
||||
|
||||
/* Return origin: "TEE" or "TRUSTED_APP" after communication with TEE. */
|
||||
|
||||
/* On Success: */
|
||||
if (return_origin)
|
||||
*return_origin = TEEC_ORIGIN_TRUSTED_APP;
|
||||
|
||||
ret = tbase_session->tci_buffer->cmd_ret;
|
||||
|
||||
if (ret == TEEC_SUCCESS && operation) {
|
||||
ret = FillOperationArgs(operation, tbase_session->tci_buffer);
|
||||
if (ret != TEEC_SUCCESS)
|
||||
tbase_session->tci_buffer->return_origin =
|
||||
TEEC_ORIGIN_API;
|
||||
}
|
||||
|
||||
exit:
|
||||
if (return_origin && tbase_session) {
|
||||
/* tci_buffer is supposed to be not NULL */
|
||||
*return_origin = tbase_session->tci_buffer->return_origin;
|
||||
}
|
||||
|
||||
TbaseCleanSessionMaps(tbase_session);
|
||||
return ret;
|
||||
}
|
||||
|
||||
TEEC_Result TbaseUnloadTA(void *ta_session)
|
||||
{
|
||||
enum mc_result mc_res;
|
||||
TEEC_Result status = TEEC_SUCCESS;
|
||||
TbaseSession *session = (TbaseSession *)ta_session;
|
||||
|
||||
mc_res = mc_close_session(&(session->ta_session));
|
||||
|
||||
if (mc_res != MC_DRV_OK)
|
||||
status = TEEC_ERROR_GENERIC;
|
||||
|
||||
if (session->tci_buffer != NULL) {
|
||||
mc_res = mc_free_wsm(DEVICE_ID, (uint8_t *)session->tci_buffer);
|
||||
if (mc_res != MC_DRV_OK)
|
||||
status = TEEC_ERROR_GENERIC;
|
||||
|
||||
session->tci_buffer = NULL;
|
||||
session->persistent_object = NULL;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
TEEC_Result TbaseLoadTA(void *ta_session, const TEEC_UUID *uuid)
|
||||
{
|
||||
enum mc_result mc_res;
|
||||
TEEC_Result status = TEEC_SUCCESS;
|
||||
TbaseSession *session = (TbaseSession *)ta_session;
|
||||
void *po_cmd;
|
||||
const struct firmware *fw = NULL;
|
||||
|
||||
if (!ta_session || !uuid) {
|
||||
status = TEEC_ERROR_BAD_PARAMETERS;
|
||||
goto error;
|
||||
}
|
||||
|
||||
session->tci_buffer = NULL;
|
||||
mc_res = mc_open_device(DEVICE_ID);
|
||||
|
||||
if (mc_res != MC_DRV_OK) {
|
||||
status = TEEC_ERROR_GENERIC;
|
||||
goto error;
|
||||
}
|
||||
|
||||
mc_res = mc_malloc_wsm(DEVICE_ID, 0,
|
||||
sizeof(ProtocolCmd) + sizeof(PersObjectCmd),
|
||||
(uint8_t **)&session->tci_buffer, 0);
|
||||
if (mc_res != MC_DRV_OK) {
|
||||
status = TEEC_ERROR_OUT_OF_MEMORY;
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
po_cmd = (void *)((uint8_t *)session->tci_buffer + sizeof(ProtocolCmd));
|
||||
session->persistent_object = (PersObjectCmd *)po_cmd;
|
||||
|
||||
if (request_firmware_direct(&fw, CONFIG_FIVE_TRUSTLET_PATH, NULL)) {
|
||||
status = TEEC_ERROR_NO_DATA;
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
mc_res = mc_open_trustlet(&(session->ta_session),
|
||||
#if MCDRVMODULEAPI_VERSION_MAJOR < 8
|
||||
MC_SPID_SYSTEM,
|
||||
#endif
|
||||
(u8 *)fw->data,
|
||||
fw->size,
|
||||
(u8 *)session->tci_buffer,
|
||||
sizeof(ProtocolCmd) + sizeof(PersObjectCmd));
|
||||
|
||||
if (mc_res != MC_DRV_OK) {
|
||||
status = TEEC_ERROR_GENERIC;
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
release_firmware(fw);
|
||||
|
||||
return status;
|
||||
|
||||
error_free:
|
||||
release_firmware(fw);
|
||||
mc_free_wsm(DEVICE_ID, (uint8_t *)session->tci_buffer);
|
||||
error_close:
|
||||
mc_close_device(DEVICE_ID);
|
||||
error:
|
||||
return status;
|
||||
}
|
||||
|
||||
PlatformClientImpl g_tbase_platform_impl = {
|
||||
TbaseLoadTA,
|
||||
TbaseUnloadTA,
|
||||
TbaseSendCommand,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
PlatformClientImpl *GetPlatformClientImpl(void)
|
||||
{
|
||||
return &g_tbase_platform_impl;
|
||||
}
|
||||
|
||||
size_t GetPlatformClientImplSize(void)
|
||||
{
|
||||
return sizeof(TbaseSession);
|
||||
}
|
||||
|
||||
void ClientImplSetParentContext(void *session, void *context)
|
||||
{
|
||||
TbaseSession *tbase_session = (TbaseSession *)session;
|
||||
|
||||
if (tbase_session)
|
||||
tbase_session->parent_context = context;
|
||||
}
|
||||
|
||||
void *ClientImplGetParentContext(void *session)
|
||||
{
|
||||
void *ret = NULL;
|
||||
TbaseSession *tbase_session = (TbaseSession *)session;
|
||||
|
||||
if (tbase_session)
|
||||
ret = tbase_session->parent_context;
|
||||
|
||||
return ret;
|
||||
}
|
|
@ -0,0 +1,283 @@
|
|||
/*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* This code is originated from Samsung Electronics proprietary sources.
|
||||
* Author: Iaroslav Makarchuk (i.makarchuk@samsung.com)
|
||||
* Created: 12 Oct 2016
|
||||
*
|
||||
* Copyright (C) 2016 Samsung Electronics, Inc.
|
||||
*/
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <tzdev/kernel_api.h>
|
||||
#include <tzdev/iwnotify.h>
|
||||
#include <tzdev/tzdev.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/mm.h>
|
||||
|
||||
#include "teec_common.h"
|
||||
#include "protocol.h"
|
||||
#include "teec_param_utils.h"
|
||||
|
||||
/* Timeout in seconds */
|
||||
#define FIVE_IWNOTIFY_TIMEOUT 3
|
||||
#define FIVE_IWNOTIFICATION TZ_IWNOTIFY_OEM_NOTIFICATION_FLAG_13
|
||||
|
||||
static DECLARE_COMPLETION(kcmd_event);
|
||||
|
||||
static int __kcmd_notifier(struct notifier_block *nb, unsigned long action,
|
||||
void *data)
|
||||
{
|
||||
complete(&kcmd_event);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct notifier_block kcmd_notifier = {
|
||||
.notifier_call = __kcmd_notifier,
|
||||
};
|
||||
|
||||
static volatile uint8_t g_buffer[ALIGN(sizeof(ProtocolCmd), PAGE_SIZE)]
|
||||
__aligned(PAGE_SIZE) = {0};
|
||||
|
||||
typedef struct TeegrisSessionStruct {
|
||||
int client_id;
|
||||
ProtocolCmd *tci_buffer;
|
||||
void *parent_context;
|
||||
uint32_t shmem_id;
|
||||
struct page *shmem_page;
|
||||
size_t tci_size;
|
||||
} TeegrisSession;
|
||||
|
||||
static TEEC_Result TeegrisSendCommand(void *ta_session,
|
||||
uint32_t command_id,
|
||||
TEEC_Operation *operation,
|
||||
uint32_t *return_origin,
|
||||
int32_t timeout)
|
||||
{
|
||||
int res = 0;
|
||||
TEEC_Result ret = TEEC_ERROR_BAD_PARAMETERS;
|
||||
TeegrisSession *session = (TeegrisSession *)ta_session;
|
||||
ProtocolParam cmd;
|
||||
|
||||
if (!session)
|
||||
goto exit;
|
||||
|
||||
/* tci_buffer is supposed to be not NULL */
|
||||
session->tci_buffer->return_origin = TEEC_ORIGIN_API;
|
||||
|
||||
session->tci_buffer->cmd_id = command_id;
|
||||
session->tci_buffer->param_types = 0;
|
||||
session->tci_buffer->cmd_ret = TEEC_ERROR_COMMUNICATION;
|
||||
|
||||
if (operation) {
|
||||
session->tci_buffer->param_types = operation->paramTypes;
|
||||
ret = FillCommandArgs(session->tci_buffer,
|
||||
operation, session);
|
||||
|
||||
if (ret != TEEC_SUCCESS)
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Return origin: "COMMS" to handle several conditions below */
|
||||
session->tci_buffer->return_origin = TEEC_ORIGIN_COMMS;
|
||||
|
||||
/* Call */
|
||||
cmd.memref.buffer = session->shmem_id;
|
||||
cmd.memref.size = (uint32_t)session->tci_size;
|
||||
res = tzdev_kapi_send(session->client_id, &cmd, sizeof(cmd));
|
||||
if (res < 0) {
|
||||
pr_err("FIVE: Can't send command tzdev_kapi: %d\n", res);
|
||||
ret = TEEC_ERROR_COMMUNICATION;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
res = wait_for_completion_timeout(&kcmd_event,
|
||||
FIVE_IWNOTIFY_TIMEOUT * HZ);
|
||||
if (res <= 0) {
|
||||
pr_err("FIVE: Timeout expired on waiting for tzdev_kapi: %d\n",
|
||||
res);
|
||||
ret = TEEC_ERROR_COMMUNICATION;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
res = tzdev_kapi_recv(session->client_id, NULL, 0);
|
||||
if (res < 0) {
|
||||
pr_err("FIVE: Can't receive answer from tzdev_kapi: %d\n", res);
|
||||
ret = TEEC_ERROR_COMMUNICATION;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Return origin: "TEE" or "TRUSTED_APP" after communication with TEE. */
|
||||
session->tci_buffer->return_origin = TEEC_ORIGIN_TRUSTED_APP;
|
||||
|
||||
/* On Success: */
|
||||
if (return_origin)
|
||||
*return_origin = TEEC_ORIGIN_TRUSTED_APP;
|
||||
|
||||
ret = session->tci_buffer->cmd_ret;
|
||||
|
||||
if (ret == TEEC_SUCCESS && operation) {
|
||||
ret = FillOperationArgs(operation, session->tci_buffer);
|
||||
if (ret != TEEC_SUCCESS)
|
||||
session->tci_buffer->return_origin = TEEC_ORIGIN_API;
|
||||
}
|
||||
|
||||
exit:
|
||||
if (return_origin && session) {
|
||||
/* tci_buffer is supposed to be not NULL */
|
||||
*return_origin = session->tci_buffer->return_origin;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static TEEC_Result TeegrisUnloadTA(void *ta_session)
|
||||
{
|
||||
int res;
|
||||
TEEC_Result status = TEEC_SUCCESS;
|
||||
TeegrisSession *session = (TeegrisSession *)ta_session;
|
||||
|
||||
res = tzdev_kapi_mem_revoke(session->client_id, session->shmem_id);
|
||||
if (res)
|
||||
status = TEEC_ERROR_GENERIC;
|
||||
|
||||
res = tzdev_kapi_mem_release(session->shmem_id);
|
||||
if (res)
|
||||
status = TEEC_ERROR_GENERIC;
|
||||
|
||||
res = tzdev_kapi_close(session->client_id);
|
||||
if (res)
|
||||
status = TEEC_ERROR_GENERIC;
|
||||
|
||||
res = tz_iwnotify_chain_unregister(FIVE_IWNOTIFICATION, &kcmd_notifier);
|
||||
if (res < 0)
|
||||
status = TEEC_ERROR_GENERIC;
|
||||
|
||||
if (session->tci_buffer != NULL) {
|
||||
session->tci_buffer = NULL;
|
||||
session->shmem_page = NULL;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static TEEC_Result TeegrisLoadTA(void *ta_session, const TEEC_UUID *uuid)
|
||||
{
|
||||
int res;
|
||||
TEEC_Result status = TEEC_SUCCESS;
|
||||
TeegrisSession *session = (TeegrisSession *)ta_session;
|
||||
|
||||
if (!ta_session || !uuid) {
|
||||
status = TEEC_ERROR_BAD_PARAMETERS;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
session->shmem_page = virt_to_page(g_buffer);
|
||||
if (!session->shmem_page) {
|
||||
status = TEEC_ERROR_OUT_OF_MEMORY;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (!tzdev_is_up())
|
||||
panic("FIVE: tzdev is not ready\n");
|
||||
|
||||
init_completion(&kcmd_event);
|
||||
res = tz_iwnotify_chain_register(FIVE_IWNOTIFICATION, &kcmd_notifier);
|
||||
if (res < 0) {
|
||||
pr_err("FIVE: Can't register iwnotify tzdev: %d\n", res);
|
||||
status = TEEC_ERROR_COMMUNICATION;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
session->tci_buffer = (ProtocolCmd *)g_buffer;
|
||||
session->tci_size = ALIGN(sizeof(ProtocolCmd), PAGE_SIZE);
|
||||
|
||||
(void)BUILD_BUG_ON_ZERO((sizeof(struct tz_uuid) != sizeof(TEEC_UUID)));
|
||||
res = tzdev_kapi_open((const struct tz_uuid *)uuid);
|
||||
if (res < 0) {
|
||||
pr_err("FIVE: Can't open tzdev_kapi: %d\n", res);
|
||||
status = TEEC_ERROR_GENERIC;
|
||||
goto error_chain;
|
||||
}
|
||||
|
||||
session->client_id = res;
|
||||
|
||||
res = tzdev_kapi_mem_register(session->tci_buffer,
|
||||
session->tci_size, 1);
|
||||
if (res < 0) {
|
||||
pr_err("FIVE: Can't register tzdev_kapi_mem: %d\n", res);
|
||||
status = TEEC_ERROR_GENERIC;
|
||||
goto error_close;
|
||||
}
|
||||
|
||||
session->shmem_id = res;
|
||||
|
||||
res = tzdev_kapi_mem_grant(session->client_id, session->shmem_id);
|
||||
if (res) {
|
||||
pr_err("FIVE: Can't grant memory tzdev_kapi_mem: %d\n", res);
|
||||
status = TEEC_ERROR_GENERIC;
|
||||
goto error_mem;
|
||||
}
|
||||
|
||||
return status;
|
||||
|
||||
error_chain:
|
||||
res = tz_iwnotify_chain_unregister(FIVE_IWNOTIFICATION, &kcmd_notifier);
|
||||
if (res < 0)
|
||||
pr_err("FIVE: Can't unregister iwnotify tzdev: %d\n", res);
|
||||
|
||||
error_mem:
|
||||
tzdev_kapi_mem_release(session->shmem_id);
|
||||
|
||||
error_close:
|
||||
tzdev_kapi_close(session->client_id);
|
||||
|
||||
exit:
|
||||
return status;
|
||||
}
|
||||
|
||||
static PlatformClientImpl g_teegris_platform_impl = {
|
||||
TeegrisLoadTA,
|
||||
TeegrisUnloadTA,
|
||||
TeegrisSendCommand,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
PlatformClientImpl *GetPlatformClientImpl(void)
|
||||
{
|
||||
return &g_teegris_platform_impl;
|
||||
}
|
||||
|
||||
size_t GetPlatformClientImplSize(void)
|
||||
{
|
||||
return sizeof(TeegrisSession);
|
||||
}
|
||||
|
||||
void ClientImplSetParentContext(void *ta_session, void *context)
|
||||
{
|
||||
TeegrisSession *session = (TeegrisSession *)ta_session;
|
||||
|
||||
if (session)
|
||||
session->parent_context = context;
|
||||
}
|
||||
|
||||
void *ClientImplGetParentContext(void *ta_session)
|
||||
{
|
||||
void *ret = NULL;
|
||||
TeegrisSession *session = (TeegrisSession *)ta_session;
|
||||
|
||||
if (session)
|
||||
ret = session->parent_context;
|
||||
|
||||
return ret;
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Set option shared memory and operations for TEE access
|
||||
*
|
||||
* Copyright (C) 2019 Samsung Electronics, Inc.
|
||||
*
|
||||
* Egor Uleyskiy, <e.uleyskiy@samsung.com>
|
||||
* Viacheslav Vovchenko <v.vovchenko@samsung.com>
|
||||
* Yevgen Kopylov <y.kopylov@samsung.com>
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef __LINUX_TEEC_OPERATION_H
|
||||
#define __LINUX_TEEC_OPERATION_H
|
||||
|
||||
#include "tee_client_api.h"
|
||||
|
||||
void FillOperationSharedMem(TEEC_SharedMemory *sharedMem,
|
||||
TEEC_Operation *operation, bool inout_direction);
|
||||
|
||||
#endif // __LINUX_TEEC_OPERATION_H
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Set option shared memory and operations for TEE access
|
||||
*
|
||||
* Copyright (C) 2019 Samsung Electronics, Inc.
|
||||
*
|
||||
* Egor Uleyskiy, <e.uleyskiy@samsung.com>
|
||||
* Viacheslav Vovchenko <v.vovchenko@samsung.com>
|
||||
* Yevgen Kopylov <y.kopylov@samsung.com>
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include "teec_operation.h"
|
||||
|
||||
void FillOperationSharedMem(TEEC_SharedMemory *sharedMem,
|
||||
TEEC_Operation *operation, bool inout_direction)
|
||||
{
|
||||
if (inout_direction) {
|
||||
operation->paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INOUT,
|
||||
TEEC_NONE,
|
||||
TEEC_NONE, TEEC_NONE);
|
||||
} else {
|
||||
operation->paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT,
|
||||
TEEC_NONE,
|
||||
TEEC_NONE, TEEC_NONE);
|
||||
}
|
||||
|
||||
operation->params[0].tmpref.buffer = sharedMem->buffer;
|
||||
operation->params[0].tmpref.size = sharedMem->size;
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Set option shared memory and operations for TEE access
|
||||
*
|
||||
* Copyright (C) 2019 Samsung Electronics, Inc.
|
||||
*
|
||||
* Egor Uleyskiy, <e.uleyskiy@samsung.com>
|
||||
* Viacheslav Vovchenko <v.vovchenko@samsung.com>
|
||||
* Yevgen Kopylov <y.kopylov@samsung.com>
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include "teec_operation.h"
|
||||
|
||||
void FillOperationSharedMem(TEEC_SharedMemory *sharedMem,
|
||||
TEEC_Operation *operation, bool inout_direction)
|
||||
{
|
||||
if (inout_direction) {
|
||||
operation->paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INOUT,
|
||||
TEEC_NONE,
|
||||
TEEC_NONE, TEEC_NONE);
|
||||
} else {
|
||||
operation->paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT,
|
||||
TEEC_NONE,
|
||||
TEEC_NONE, TEEC_NONE);
|
||||
}
|
||||
|
||||
operation->params[0].tmpref.buffer = sharedMem->buffer;
|
||||
operation->params[0].tmpref.size = sharedMem->size;
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Set option shared memory and operations for TEE access
|
||||
*
|
||||
* Copyright (C) 2019 Samsung Electronics, Inc.
|
||||
*
|
||||
* Egor Uleyskiy, <e.uleyskiy@samsung.com>
|
||||
* Viacheslav Vovchenko <v.vovchenko@samsung.com>
|
||||
* Yevgen Kopylov <y.kopylov@samsung.com>
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include "teec_operation.h"
|
||||
|
||||
void FillOperationSharedMem(TEEC_SharedMemory *sharedMem,
|
||||
TEEC_Operation *operation, bool inout_direction)
|
||||
{
|
||||
if (inout_direction) {
|
||||
operation->paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INOUT,
|
||||
TEEC_NONE,
|
||||
TEEC_NONE, TEEC_NONE);
|
||||
} else {
|
||||
operation->paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT,
|
||||
TEEC_NONE,
|
||||
TEEC_NONE, TEEC_NONE);
|
||||
}
|
||||
|
||||
operation->params[0].tmpref.buffer = sharedMem->buffer;
|
||||
operation->params[0].tmpref.size = sharedMem->size;
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Set option shared memory and operations for TEE access
|
||||
*
|
||||
* Copyright (C) 2019 Samsung Electronics, Inc.
|
||||
*
|
||||
* Egor Uleyskiy, <e.uleyskiy@samsung.com>
|
||||
* Viacheslav Vovchenko <v.vovchenko@samsung.com>
|
||||
* Yevgen Kopylov <y.kopylov@samsung.com>
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include "teec_operation.h"
|
||||
|
||||
void FillOperationSharedMem(TEEC_SharedMemory *sharedMem,
|
||||
TEEC_Operation *operation, bool inout_direction)
|
||||
{
|
||||
operation->paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_WHOLE, TEEC_NONE,
|
||||
TEEC_NONE, TEEC_NONE);
|
||||
|
||||
operation->params[0].memref.parent = sharedMem;
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* This code is originated from Samsung Electronics proprietary sources.
|
||||
* Author: Iaroslav Makarchuk (i.makarchuk@samsung.com)
|
||||
* Created: 12 Oct 2016
|
||||
*
|
||||
* Copyright (C) 2016 Samsung Electronics, Inc.
|
||||
*/
|
||||
|
||||
#ifndef PROTOCOL_H_
|
||||
#define PROTOCOL_H_
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
#define PROTOCOL_COMMAND_UNLOAD 0xFF01
|
||||
#define PROTOCOL_COMMAND_LOAD 0xFF02
|
||||
#define PROTOCOL_COMMAND_READF 0xFF03
|
||||
#define PROTOCOL_COMMAND_WRITEF 0xFF04
|
||||
|
||||
/*
|
||||
* Size of command buffer in Linux kernel for the case of kinibi must be less
|
||||
* than 32 KBytes (8 pages):
|
||||
* | struct ProcolCmd | struct PersObjectCmd |
|
||||
* | 20544 bytes | 4180 bytes | = 24724 bytes (7 pages)
|
||||
*
|
||||
* The size of persistent object data should be comparable to the size of one
|
||||
* command parameter.
|
||||
*/
|
||||
#define PROTOCOL_MAX_PARAM_DATA_LEN (4096 + 1024)
|
||||
#define PARAMS_NUM 4
|
||||
#define MAX_SHAREDMEM_SIZE (PARAMS_NUM * PROTOCOL_MAX_PARAM_DATA_LEN)
|
||||
|
||||
#define MAX_PERSISTENT_OBJECT_DATA_LEN 4096
|
||||
#define MAX_PERSISTENT_OBJECT_ID_LEN 64
|
||||
|
||||
/*
|
||||
* All structures which travels across IW boundary must be packed
|
||||
*/
|
||||
#define IW_STRUCTURE __attribute__((packed))
|
||||
|
||||
//TEE_Result is the type used for return codes from the APIs.
|
||||
typedef uint32_t TEE_Result;
|
||||
|
||||
typedef union {
|
||||
struct {
|
||||
uint32_t buffer;
|
||||
uint32_t size;
|
||||
} IW_STRUCTURE memref;
|
||||
struct {
|
||||
uint32_t a, b;
|
||||
} IW_STRUCTURE value;
|
||||
} IW_STRUCTURE ProtocolParam;
|
||||
|
||||
/*
|
||||
* Size of ProtocolCmdStruct should be aligned to size_t, so we added
|
||||
* dummy field to keep alignment
|
||||
*/
|
||||
typedef struct ProtocolCmdStruct {
|
||||
uint32_t cmd_id;
|
||||
uint32_t cmd_ret_origin;
|
||||
uint32_t param_types;
|
||||
ProtocolParam params[PARAMS_NUM];
|
||||
uint8_t param_buffers[PARAMS_NUM][PROTOCOL_MAX_PARAM_DATA_LEN];
|
||||
TEE_Result cmd_ret;
|
||||
uint32_t return_origin;
|
||||
uint32_t dummy;
|
||||
uint64_t teec_oper;
|
||||
} IW_STRUCTURE ProtocolCmd;
|
||||
|
||||
typedef struct PersObjectCmdStruct {
|
||||
uint32_t cmd_id;
|
||||
uint32_t data_len;
|
||||
uint32_t id_len;
|
||||
uint8_t id[MAX_PERSISTENT_OBJECT_ID_LEN];
|
||||
uint8_t data[MAX_PERSISTENT_OBJECT_DATA_LEN];
|
||||
uint64_t teec_oper;
|
||||
} IW_STRUCTURE PersObjectCmd;
|
||||
|
||||
#endif /* !PROTOCOL_H */
|
|
@ -0,0 +1,168 @@
|
|||
/*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* This code is originated from Samsung Electronics proprietary sources.
|
||||
* Author: Iaroslav Makarchuk (i.makarchuk@samsung.com)
|
||||
* Created: 12 Oct 2016
|
||||
*
|
||||
* Copyright (C) 2016 Samsung Electronics, Inc.
|
||||
*/
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/kernel.h>
|
||||
#include "teec_param_utils.h"
|
||||
#include "teec_common.h"
|
||||
#include "protocol.h"
|
||||
|
||||
static inline uint32_t GetParamTypeByFlags(uint32_t flags)
|
||||
{
|
||||
uint32_t param_type = 0;
|
||||
|
||||
if ((flags & TEEC_MEM_INPUT) && (flags & TEEC_MEM_OUTPUT))
|
||||
param_type = TEEC_MEMREF_TEMP_INOUT;
|
||||
else if (flags & TEEC_MEM_INPUT)
|
||||
param_type = TEEC_MEMREF_TEMP_INPUT;
|
||||
else if (flags & TEEC_MEM_OUTPUT)
|
||||
param_type = TEEC_MEMREF_TEMP_OUTPUT;
|
||||
|
||||
return param_type;
|
||||
}
|
||||
|
||||
inline uint32_t GetParamType(uint32_t param_index, uint32_t param_types)
|
||||
{
|
||||
uint32_t mask = 0xF << (param_index * 4);
|
||||
|
||||
return (param_types & mask) >> (param_index * 4);
|
||||
}
|
||||
|
||||
static inline void SetParamType(uint32_t param_index,
|
||||
uint32_t *param_types, uint32_t param_type)
|
||||
{
|
||||
uint32_t mask = param_type << (param_index * 4);
|
||||
*param_types &= ~(0xF << (param_index * 4));
|
||||
*param_types |= mask;
|
||||
}
|
||||
|
||||
TEEC_Result FillCommandArgs(ProtocolCmd *command,
|
||||
TEEC_Operation *operation, void *ta_session)
|
||||
{
|
||||
TEEC_Result ret = TEEC_SUCCESS;
|
||||
uint32_t i = 0;
|
||||
|
||||
if (!command || !operation) {
|
||||
ret = TEEC_ERROR_BAD_PARAMETERS;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
for (i = 0; i < PARAMS_NUM; i++) {
|
||||
switch (GetParamType(i, operation->paramTypes)) {
|
||||
case TEEC_VALUE_INPUT:
|
||||
case TEEC_VALUE_INOUT: {
|
||||
command->params[i].value.a =
|
||||
operation->params[i].value.a;
|
||||
command->params[i].value.b =
|
||||
operation->params[i].value.b;
|
||||
break;
|
||||
}
|
||||
case TEEC_MEMREF_TEMP_INPUT:
|
||||
case TEEC_MEMREF_TEMP_INOUT: {
|
||||
if (operation->params[i].tmpref.size > UINT_MAX ||
|
||||
operation->params[i].tmpref.size >
|
||||
sizeof(command->param_buffers[i])) {
|
||||
ret = TEEC_ERROR_EXCESS_DATA;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
command->params[i].memref.buffer = 0;
|
||||
memcpy((void *)command->param_buffers[i],
|
||||
operation->params[i].tmpref.buffer,
|
||||
operation->params[i].tmpref.size);
|
||||
|
||||
command->params[i].memref.size =
|
||||
(uint32_t)operation->params[i].tmpref.size;
|
||||
break;
|
||||
}
|
||||
case TEEC_MEMREF_TEMP_OUTPUT: {
|
||||
if (operation->params[i].tmpref.size > UINT_MAX ||
|
||||
operation->params[i].tmpref.size >
|
||||
sizeof(command->param_buffers[i])) {
|
||||
ret = TEEC_ERROR_EXCESS_DATA;
|
||||
goto exit;
|
||||
}
|
||||
command->params[i].memref.buffer = 0;
|
||||
command->params[i].memref.size =
|
||||
(uint32_t)operation->params[i].tmpref.size;
|
||||
break;
|
||||
}
|
||||
case TEEC_NONE:
|
||||
case TEEC_VALUE_OUTPUT: {
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
ret = TEEC_ERROR_NOT_SUPPORTED;
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exit:
|
||||
return ret;
|
||||
}
|
||||
|
||||
TEEC_Result FillOperationArgs(TEEC_Operation *operation, ProtocolCmd *command)
|
||||
{
|
||||
TEEC_Result ret = TEEC_SUCCESS;
|
||||
uint32_t i = 0;
|
||||
|
||||
if (!operation || !command) {
|
||||
ret = TEEC_ERROR_BAD_PARAMETERS;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
for (i = 0; i < PARAMS_NUM; i++) {
|
||||
switch (GetParamType(i, operation->paramTypes)) {
|
||||
case TEEC_VALUE_OUTPUT:
|
||||
case TEEC_VALUE_INOUT: {
|
||||
operation->params[i].value.a =
|
||||
command->params[i].value.a;
|
||||
operation->params[i].value.b =
|
||||
command->params[i].value.b;
|
||||
break;
|
||||
}
|
||||
case TEEC_MEMREF_TEMP_OUTPUT:
|
||||
case TEEC_MEMREF_TEMP_INOUT: {
|
||||
if (command->params[i].memref.size <=
|
||||
operation->params[i].tmpref.size) {
|
||||
memcpy(operation->params[i].tmpref.buffer,
|
||||
command->param_buffers[i],
|
||||
command->params[i].memref.size);
|
||||
} else {
|
||||
ret = TEEC_ERROR_SHORT_BUFFER;
|
||||
}
|
||||
operation->params[i].tmpref.size =
|
||||
command->params[i].memref.size;
|
||||
break;
|
||||
}
|
||||
case TEEC_NONE:
|
||||
case TEEC_MEMREF_TEMP_INPUT:
|
||||
case TEEC_VALUE_INPUT: {
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
ret = TEEC_ERROR_NOT_SUPPORTED;
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exit:
|
||||
return ret;
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* This code is originated from Samsung Electronics proprietary sources.
|
||||
* Author: Iaroslav Makarchuk (i.makarchuk@samsung.com)
|
||||
* Created: 12 Oct 2016
|
||||
*
|
||||
* Copyright (C) 2016 Samsung Electronics, Inc.
|
||||
*/
|
||||
|
||||
#ifndef TEEC_PARAM_UTILS_H_
|
||||
#define TEEC_PARAM_UTILS_H_
|
||||
|
||||
#include "tee_client_api.h"
|
||||
#include "protocol.h"
|
||||
|
||||
inline uint32_t GetParamType(uint32_t param_index, uint32_t param_types);
|
||||
TEEC_Result FillCommandArgs(ProtocolCmd *command,
|
||||
TEEC_Operation *operation, void *ta_session);
|
||||
TEEC_Result FillOperationArgs(TEEC_Operation *operation, ProtocolCmd *command);
|
||||
|
||||
#endif /* TEEC_PARAM_UTILS_H_ */
|
42
drivers/security/samsung/tzic/Kconfig
Normal file
42
drivers/security/samsung/tzic/Kconfig
Normal file
|
@ -0,0 +1,42 @@
|
|||
#
|
||||
# TZIC configuration
|
||||
#
|
||||
|
||||
config TZIC
|
||||
bool "TZIC Driver"
|
||||
default y
|
||||
---help---
|
||||
Enable TZIC Driver support.
|
||||
|
||||
choice
|
||||
prompt "IC Secure OS"
|
||||
depends on TZIC
|
||||
default TZIC_USE_QSEECOM if QSEECOM
|
||||
default TZIC_USE_TZDEV if TZDEV
|
||||
default TZIC_USE_TRUSTONIC if TRUSTONIC_TEE
|
||||
default TZIC_DEFAULT
|
||||
---help---
|
||||
Select Secure OS for TZIC
|
||||
|
||||
config TZIC_USE_TRUSTONIC
|
||||
bool "TZIC based on Trustonic Secure OS"
|
||||
depends on TRUSTONIC_TEE
|
||||
---help---
|
||||
Use Trustonic as base Trusted Execution Environment
|
||||
|
||||
config TZIC_USE_TZDEV
|
||||
bool "TZIC based on TEEgris Secure OS"
|
||||
depends on TZDEV
|
||||
---help---
|
||||
Use TEEgris as base Trusted Execution Environment
|
||||
|
||||
config TZIC_USE_QSEECOM
|
||||
bool "TZIC based on Qualcomm Secure OS"
|
||||
depends on QSEECOM
|
||||
---help---
|
||||
Use Qualcomm as base Trusted Execution Environment
|
||||
config TZIC_DEFAULT
|
||||
bool "TZIC Disabled"
|
||||
---help---
|
||||
TZIC disabled
|
||||
endchoice
|
22
drivers/security/samsung/tzic/Makefile
Normal file
22
drivers/security/samsung/tzic/Makefile
Normal file
|
@ -0,0 +1,22 @@
|
|||
#
|
||||
# TZIC Driver
|
||||
#
|
||||
|
||||
ccflags-$(CONFIG_TZDEV) += -I$(srctree)/drivers/misc/tzdev/include
|
||||
MTK_PLATFORM := $(subst ",,$(CONFIG_MTK_PLATFORM))
|
||||
obj-$(CONFIG_TZIC) += tzic64.o
|
||||
|
||||
EXTRA_CFLAGS += -I$(src)
|
||||
obj-$(CONFIG_TZIC_USE_QSEECOM) += tzic_qsee.o
|
||||
obj-$(CONFIG_TZIC_USE_TZDEV) += tzic_tzdev.o
|
||||
ifneq ($(CONFIG_TZIC_EXYNOS7885),)
|
||||
ccflags-$(CONFIG_TZIC_USE_TZDEV) += -Idrivers/misc/tzdev/3.0
|
||||
else
|
||||
ccflags-$(CONFIG_TZIC_USE_TZDEV) += -Idrivers/misc/tzdev
|
||||
endif
|
||||
ifeq ($(MTK_PLATFORM),mt6768)
|
||||
obj-y += tzic_mtk_atf.o
|
||||
else
|
||||
obj-$(CONFIG_TZIC_USE_TRUSTONIC) += tzic_kinibi.o
|
||||
obj-$(CONFIG_TZIC_DEFAULT) += tzic_default.o
|
||||
endif
|
34
drivers/security/samsung/tzic/tzic.h
Normal file
34
drivers/security/samsung/tzic/tzic.h
Normal file
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Get/Set OEM flags
|
||||
*
|
||||
* Copyright (C) 2017 Samsung Electronics, Inc.
|
||||
* Nguyen Hoang Thai Kiet, <kiet.nht@samsung.com>
|
||||
* Jonghun Song, <justin.song@samsung.com>
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef __OEM_FLAG_H
|
||||
#define __OEM_FLAG_H
|
||||
|
||||
enum oemflag_id {
|
||||
OEMFLAG_NONE = 0,
|
||||
OEMFLAG_MIN_FLAG = 2,
|
||||
OEMFLAG_TZ_DRM,
|
||||
OEMFLAG_FIDO,
|
||||
OEMFLAG_CC,
|
||||
OEMFLAG_ETC,
|
||||
OEMFLAG_CUSTOM_KERNEL,
|
||||
OEMFLAG_NUM_OF_FLAG,
|
||||
};
|
||||
|
||||
int tzic_oem_flags_set(enum oemflag_id flag);
|
||||
int tzic_oem_flags_get(enum oemflag_id flag);
|
||||
#endif
|
381
drivers/security/samsung/tzic/tzic64.c
Normal file
381
drivers/security/samsung/tzic/tzic64.c
Normal file
|
@ -0,0 +1,381 @@
|
|||
/*
|
||||
* Samsung TZIC Driver
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
* only version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
#define KMSG_COMPONENT "TZIC"
|
||||
|
||||
#include <linux/printk.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/cdev.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/types.h>
|
||||
#include "tzic.h"
|
||||
|
||||
#ifdef CONFIG_TZDEV
|
||||
#include <linux/init.h>
|
||||
#include <linux/ioctl.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/miscdevice.h>
|
||||
#if defined(CONFIG_TEEGRIS_VERSION) && (CONFIG_TEEGRIS_VERSION >= 4)
|
||||
#include "extensions/irs.h"
|
||||
#else
|
||||
#include "tzirs.h"
|
||||
#endif
|
||||
#endif /* CONFIG_TZDEV */
|
||||
|
||||
#define TZIC_DEV "tzic"
|
||||
|
||||
#define TZIC_IOC_MAGIC 0x9E
|
||||
#define TZIC_IOCTL_GET_FUSE_REQ _IO(TZIC_IOC_MAGIC, 0)
|
||||
#define TZIC_IOCTL_SET_FUSE_REQ _IO(TZIC_IOC_MAGIC, 1)
|
||||
#define TZIC_IOCTL_SET_FUSE_REQ_DEFAULT _IO(TZIC_IOC_MAGIC, 2)
|
||||
#define TZIC_IOCTL_GET_FUSE_REQ_NEW _IO(TZIC_IOC_MAGIC, 10)
|
||||
#define TZIC_IOCTL_SET_FUSE_REQ_NEW _IO(TZIC_IOC_MAGIC, 11)
|
||||
|
||||
#ifndef LOG
|
||||
#define LOG printk
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_TZIC_USE_QSEECOM
|
||||
#define HLOS_IMG_TAMPER_FUSE 0
|
||||
#endif /* CONFIG_TZIC_USE_QSEECOM */
|
||||
|
||||
#ifndef CONFIG_TZDEV
|
||||
// TZ_IRS_CMD
|
||||
enum {
|
||||
IRS_SET_FLAG_CMD = 1,
|
||||
IRS_SET_FLAG_VALUE_CMD,
|
||||
IRS_INC_FLAG_CMD,
|
||||
IRS_GET_FLAG_VAL_CMD,
|
||||
IRS_ADD_FLAG_CMD,
|
||||
IRS_DEL_FLAG_CMD
|
||||
};
|
||||
#endif //CONFIG_TZDEV
|
||||
|
||||
#if defined(CONFIG_TZIC_USE_TZDEV) || defined(CONFIG_TZIC_USE_TRUSTONIC)
|
||||
static int gotoCpu0(void);
|
||||
static int gotoAllCpu(void) __attribute__ ((unused));
|
||||
#endif
|
||||
|
||||
struct t_flag {
|
||||
uint32_t name;
|
||||
uint32_t func_cmd;
|
||||
uint32_t value;
|
||||
};
|
||||
|
||||
static DEFINE_MUTEX(tzic_mutex);
|
||||
static struct class *driver_class;
|
||||
static dev_t tzic_device_no;
|
||||
static struct cdev tzic_cdev;
|
||||
|
||||
/*
|
||||
General set flag function, it call function from tzic64_[secureOs].c
|
||||
*/
|
||||
int tzic_flags_set(enum oemflag_id index)
|
||||
{
|
||||
int ret = 0;
|
||||
uint32_t name = index;
|
||||
|
||||
if (name > OEMFLAG_MIN_FLAG && name < OEMFLAG_NUM_OF_FLAG) {
|
||||
ret = tzic_oem_flags_get(name);
|
||||
if (ret) {
|
||||
LOG(KERN_INFO "[oemflag]flag is already set. %u\n", name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
LOG(KERN_INFO "[oemflag]set_fuse_name : %u\n", name);
|
||||
|
||||
ret = tzic_oem_flags_set(name);
|
||||
if (ret) {
|
||||
LOG(KERN_INFO "set_tamper_fuse error: ret=%d\n", ret);
|
||||
return 1;
|
||||
}
|
||||
ret = tzic_oem_flags_get(name);
|
||||
if (!ret) {
|
||||
LOG(KERN_INFO "get_tamper_fuse error: ret=%d\n", ret);
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
LOG(KERN_INFO "[oemflag]param name is wrong\n");
|
||||
ret = -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
General get flag function, it call function from tzic64_[secureOs].c
|
||||
*/
|
||||
int tzic_flags_get(enum oemflag_id index)
|
||||
{
|
||||
int ret = 0;
|
||||
uint32_t name = index;
|
||||
|
||||
LOG(KERN_INFO "[oemflag]get_fuse_name : %u\n", name);
|
||||
|
||||
if (name > OEMFLAG_MIN_FLAG && name < OEMFLAG_NUM_OF_FLAG) {
|
||||
ret = tzic_oem_flags_get(name);
|
||||
} else {
|
||||
LOG(KERN_INFO "[oemflag]param name is wrong\n");
|
||||
ret = -EINVAL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static long tzic_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
int ret = 0;
|
||||
int i;
|
||||
struct t_flag param = { 0, 0, 0 };
|
||||
|
||||
#ifdef CONFIG_TZDEV
|
||||
if (_IOC_TYPE(cmd) != IOC_MAGIC && _IOC_TYPE(cmd) != TZIC_IOC_MAGIC) {
|
||||
LOG(KERN_INFO "[oemflag]INVALID CMD = %d\n", cmd);
|
||||
return -ENOTTY;
|
||||
}
|
||||
#endif /* CONFIG_TZDEV */
|
||||
|
||||
#if defined(CONFIG_TZIC_USE_TZDEV) || defined(CONFIG_TZIC_USE_TRUSTONIC)
|
||||
ret = gotoCpu0();
|
||||
if (ret != 0) {
|
||||
LOG(KERN_INFO "[oemflag]changing core failed!\n");
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
switch (cmd) {
|
||||
|
||||
#ifdef CONFIG_TZDEV
|
||||
case IOCTL_IRS_CMD:
|
||||
/* get flag id */
|
||||
ret = copy_from_user(¶m, (void *)arg, sizeof(param));
|
||||
if (ret != 0) {
|
||||
LOG(KERN_INFO "[oemflag]copy_from_user failed, ret = 0x%08x\n", ret);
|
||||
break;
|
||||
}
|
||||
|
||||
if(param.func_cmd==IRS_SET_FLAG_VALUE_CMD) {
|
||||
ret = tzic_flags_set(param.name);
|
||||
} else {
|
||||
ret = tzic_flags_get(param.name);
|
||||
}
|
||||
|
||||
break;
|
||||
#endif /* CONFIG_TZDEV */
|
||||
|
||||
#ifdef CONFIG_TZIC_USE_QSEECOM
|
||||
case TZIC_IOCTL_GET_FUSE_REQ:
|
||||
ret = tzic_flags_get(HLOS_IMG_TAMPER_FUSE);
|
||||
LOG(KERN_INFO "[oemflag]tamper_fuse value = %x\n", ret);
|
||||
break;
|
||||
|
||||
case TZIC_IOCTL_SET_FUSE_REQ:
|
||||
ret = tzic_flags_get(HLOS_IMG_TAMPER_FUSE);
|
||||
LOG(KERN_INFO "[oemflag]tamper_fuse before = %x\n", ret);
|
||||
mutex_lock(&tzic_mutex);
|
||||
ret = tzic_flags_set(HLOS_IMG_TAMPER_FUSE);
|
||||
mutex_unlock(&tzic_mutex);
|
||||
if (ret)
|
||||
LOG(KERN_INFO "[oemflag]failed tzic_set_fuse_cmd: %d\n", ret);
|
||||
LOG(KERN_INFO "[oemflag]tamper_fuse after = %x\n", tzic_flags_get(HLOS_IMG_TAMPER_FUSE));
|
||||
break;
|
||||
#endif //CONFIG_TZIC_USE_QSEECOM
|
||||
|
||||
case TZIC_IOCTL_SET_FUSE_REQ_DEFAULT: //SET ALL OEM FLAG EXCEPT 0
|
||||
LOG(KERN_INFO "[oemflag]set_fuse_default\n");
|
||||
ret = copy_from_user(¶m, (void *)arg, sizeof(param));
|
||||
if (ret) {
|
||||
LOG(KERN_INFO "[oemflag]ERROR copy from user\n");
|
||||
return ret;
|
||||
}
|
||||
for (i = OEMFLAG_MIN_FLAG+1; i < OEMFLAG_NUM_OF_FLAG; i++) {
|
||||
param.name = i;
|
||||
ret = tzic_flags_get(param.name);
|
||||
LOG(KERN_INFO "[oemflag]tamper_fuse before = %x\n", ret);
|
||||
mutex_lock(&tzic_mutex);
|
||||
ret = tzic_flags_set(param.name);
|
||||
mutex_unlock(&tzic_mutex);
|
||||
if (ret)
|
||||
LOG(KERN_INFO "[oemflag]failed tzic_set_fuse_cmd: %d\n", ret);
|
||||
ret = tzic_flags_get(param.name);
|
||||
LOG(KERN_INFO "[oemflag]tamper_fuse after = %x\n", ret);
|
||||
}
|
||||
break;
|
||||
|
||||
case TZIC_IOCTL_SET_FUSE_REQ_NEW:
|
||||
ret = copy_from_user(¶m, (void *)arg, sizeof(param));
|
||||
if (ret) {
|
||||
LOG(KERN_INFO "[oemflag]ERROR copy from user\n");
|
||||
break;
|
||||
}
|
||||
if ((param.name > OEMFLAG_MIN_FLAG) && (param.name < OEMFLAG_NUM_OF_FLAG)) {
|
||||
ret = tzic_flags_set(param.name);
|
||||
} else {
|
||||
LOG(KERN_INFO "[oemflag]command error\n");
|
||||
ret = -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case TZIC_IOCTL_GET_FUSE_REQ_NEW:
|
||||
LOG(KERN_INFO "[oemflag]get_fuse_new\n");
|
||||
ret = copy_from_user(¶m, (void *)arg, sizeof(param));
|
||||
if (ret) {
|
||||
LOG(KERN_INFO "[oemflag]ERROR copy from user\n");
|
||||
break;
|
||||
}
|
||||
if ((param.name > OEMFLAG_MIN_FLAG) && (param.name < OEMFLAG_NUM_OF_FLAG)) {
|
||||
ret = tzic_flags_get(param.name);
|
||||
LOG(KERN_INFO "[oemflag]get_oemflag_value : %u\n", ret);
|
||||
} else {
|
||||
LOG(KERN_INFO "[oemflag]command error\n");
|
||||
ret = -1;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG(KERN_INFO "[oemflag]default\n");
|
||||
ret = copy_from_user(¶m, (void *)arg, sizeof(param));
|
||||
if (param.func_cmd == IRS_SET_FLAG_VALUE_CMD) {
|
||||
if (ret) {
|
||||
LOG(KERN_INFO "[oemflag]ERROR copy from user\n");
|
||||
break;
|
||||
}
|
||||
if ((param.name > OEMFLAG_MIN_FLAG) && (param.name < OEMFLAG_NUM_OF_FLAG)) {
|
||||
ret = tzic_flags_set(param.name);
|
||||
} else {
|
||||
LOG(KERN_INFO "[oemflag]command error\n");
|
||||
ret = -1;
|
||||
}
|
||||
} else if (param.func_cmd == IRS_GET_FLAG_VAL_CMD) {
|
||||
LOG(KERN_INFO "[oemflag]get_fuse_new\n");
|
||||
if (ret) {
|
||||
LOG(KERN_INFO "[oemflag]ERROR copy from user\n");
|
||||
break;
|
||||
}
|
||||
if ((param.name > OEMFLAG_MIN_FLAG) && (param.name < OEMFLAG_NUM_OF_FLAG)) {
|
||||
ret = tzic_flags_get(param.name);
|
||||
LOG(KERN_INFO "[oemflag]get_oemflag_value : %u\n", ret);
|
||||
} else {
|
||||
LOG(KERN_INFO "[oemflag]command error\n");
|
||||
ret = -1;
|
||||
}
|
||||
} else {
|
||||
LOG(KERN_INFO "[oemflag]command error\n");
|
||||
ret = -1;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(CONFIG_TZIC_USE_TZDEV) || defined(CONFIG_TZIC_USE_TRUSTONIC)
|
||||
gotoAllCpu();
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct file_operations tzic_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.compat_ioctl = tzic_ioctl,
|
||||
.unlocked_ioctl = tzic_ioctl,
|
||||
};
|
||||
|
||||
static int __init tzic_init(void)
|
||||
{
|
||||
int rc;
|
||||
struct device *class_dev;
|
||||
|
||||
rc = alloc_chrdev_region(&tzic_device_no, 0, 1, TZIC_DEV);
|
||||
if (rc < 0) {
|
||||
LOG(KERN_INFO "alloc_chrdev_region failed %d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
driver_class = class_create(THIS_MODULE, TZIC_DEV);
|
||||
if (IS_ERR(driver_class)) {
|
||||
rc = -ENOMEM;
|
||||
LOG(KERN_INFO "class_create failed %d\n", rc);
|
||||
goto unregister_chrdev_region;
|
||||
}
|
||||
|
||||
class_dev = device_create(driver_class, NULL, tzic_device_no, NULL,
|
||||
TZIC_DEV);
|
||||
if (!class_dev) {
|
||||
LOG(KERN_INFO "class_device_create failed %d\n", rc);
|
||||
rc = -ENOMEM;
|
||||
goto class_destroy;
|
||||
}
|
||||
|
||||
cdev_init(&tzic_cdev, &tzic_fops);
|
||||
tzic_cdev.owner = THIS_MODULE;
|
||||
|
||||
rc = cdev_add(&tzic_cdev, MKDEV(MAJOR(tzic_device_no), 0), 1);
|
||||
if (rc < 0) {
|
||||
LOG(KERN_INFO "cdev_add failed %d\n", rc);
|
||||
goto class_device_destroy;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
class_device_destroy:
|
||||
device_destroy(driver_class, tzic_device_no);
|
||||
class_destroy:
|
||||
class_destroy(driver_class);
|
||||
unregister_chrdev_region:
|
||||
unregister_chrdev_region(tzic_device_no, 1);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void __exit tzic_exit(void)
|
||||
{
|
||||
device_destroy(driver_class, tzic_device_no);
|
||||
class_destroy(driver_class);
|
||||
unregister_chrdev_region(tzic_device_no, 1);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_TZIC_USE_TZDEV) || defined(CONFIG_TZIC_USE_TRUSTONIC)
|
||||
static int gotoCpu0(void)
|
||||
{
|
||||
int ret = 0;
|
||||
struct cpumask mask = CPU_MASK_CPU0;
|
||||
|
||||
ret = set_cpus_allowed_ptr(current, &mask);
|
||||
|
||||
if (ret != 0)
|
||||
LOG(KERN_INFO "set_cpus_allowed_ptr=%d.\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int gotoAllCpu(void)
|
||||
{
|
||||
int ret = 0;
|
||||
struct cpumask mask = CPU_MASK_ALL;
|
||||
|
||||
ret = set_cpus_allowed_ptr(current, &mask);
|
||||
|
||||
if (ret != 0)
|
||||
LOG(KERN_INFO "set_cpus_allowed_ptr=%d.\n", ret);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_DESCRIPTION("Samsung TZIC Driver");
|
||||
MODULE_VERSION("1.00");
|
||||
|
||||
module_init(tzic_init);
|
||||
module_exit(tzic_exit);
|
27
drivers/security/samsung/tzic/tzic_default.c
Normal file
27
drivers/security/samsung/tzic/tzic_default.c
Normal file
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Set OEM flags
|
||||
*
|
||||
* Copyright (C) 2018 Samsung Electronics, Inc.
|
||||
* Nguyen Hoang Thai Kiet, <kiet.nht@samsung.com>
|
||||
* Jonghun Song, <justin.song@samsung.com>
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
#include "tzic.h"
|
||||
|
||||
int tzic_oem_flags_set(enum oemflag_id index)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tzic_oem_flags_get(enum oemflag_id index)
|
||||
{
|
||||
return 0;
|
||||
}
|
58
drivers/security/samsung/tzic/tzic_kinibi.c
Normal file
58
drivers/security/samsung/tzic/tzic_kinibi.c
Normal file
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Set OEM flags
|
||||
*
|
||||
* Copyright (C) 2018 Samsung Electronics, Inc.
|
||||
* Jonghun Song, <justin.song@samsung.com>
|
||||
* Egor Ulesykiy, <e.uelyskiy@samsung.com>
|
||||
* Nguyen Hoang Thai Kiet, <kiet.nht@samsung.com>
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/types.h>
|
||||
#include "tzic.h"
|
||||
|
||||
#define SMC_SET_FUSE 0x83000004
|
||||
#define SMC_GET_FUSE 0x83000003
|
||||
|
||||
static uint32_t run_cmd_kinibi(uint32_t cmd, uint32_t arg1,
|
||||
uint32_t arg2, uint32_t arg3)
|
||||
{
|
||||
register u64 reg0 __asm__("x0") = cmd;
|
||||
register u64 reg1 __asm__("x1") = arg1;
|
||||
register u64 reg2 __asm__("x2") = arg2;
|
||||
register u64 reg3 __asm__("x3") = arg3;
|
||||
|
||||
__asm__ volatile (
|
||||
"dsb sy\n"
|
||||
"smc 0\n"
|
||||
: "+r"(reg0), "+r"(reg1), "+r"(reg2), "+r"(reg3)
|
||||
|
||||
);
|
||||
|
||||
return reg1;
|
||||
}
|
||||
|
||||
int tzic_oem_flags_set(enum oemflag_id index)
|
||||
{
|
||||
int ret;
|
||||
pr_info("[oemflag]kinibi cmd\n");
|
||||
ret = run_cmd_kinibi(SMC_SET_FUSE, 0, index, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int tzic_oem_flags_get(enum oemflag_id index)
|
||||
{
|
||||
int ret;
|
||||
pr_info("[oemflag]kinibi cmd\n");
|
||||
ret = run_cmd_kinibi(SMC_GET_FUSE, 1, index, 0);
|
||||
return ret;
|
||||
}
|
47
drivers/security/samsung/tzic/tzic_mtk_atf.c
Normal file
47
drivers/security/samsung/tzic/tzic_mtk_atf.c
Normal file
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Set OEM flags
|
||||
*
|
||||
* Copyright (C) 2018 Samsung Electronics, Inc.
|
||||
* Nguyen Hoang Thai Kiet, <kiet.nht@samsung.com>
|
||||
* Phung Xuan Chien, <phung.chien@samsung.com>
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/arm-smccc.h>
|
||||
#include <mt-plat/mtk_secure_api.h>
|
||||
#include "tzic.h"
|
||||
|
||||
/*
|
||||
Note: res.a0 = func_cmd, res.a1 = name, res.a2 = value
|
||||
*/
|
||||
static uint32_t run_cmd_mtk_atf(uint32_t cmd, uint32_t index)
|
||||
{
|
||||
struct arm_smccc_res res;
|
||||
arm_smccc_smc(cmd, index, 0, 0, 0, 0, 0, 0, &res);
|
||||
return res.a2;
|
||||
}
|
||||
|
||||
int tzic_oem_flags_set(enum oemflag_id index)
|
||||
{
|
||||
int ret;
|
||||
pr_info("[oemflag]MTK ATF cmd\n");
|
||||
ret = run_cmd_mtk_atf(MTK_SIP_OEM_FLAG_WRITE, index);
|
||||
return (ret == 1) ? 0 : ret;
|
||||
}
|
||||
|
||||
int tzic_oem_flags_get(enum oemflag_id index)
|
||||
{
|
||||
int ret;
|
||||
pr_info("[oemflag]MTK ATF cmd\n");
|
||||
ret = run_cmd_mtk_atf(MTK_SIP_OEM_FLAG_READ, index);
|
||||
return ret;
|
||||
}
|
82
drivers/security/samsung/tzic/tzic_qsee.c
Normal file
82
drivers/security/samsung/tzic/tzic_qsee.c
Normal file
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* Set OEM flags
|
||||
*
|
||||
* Copyright (C) 2018 Samsung Electronics, Inc.
|
||||
* Jonghun Song, <justin.song@samsung.com>
|
||||
* Egor Ulesykiy, <e.uelyskiy@samsung.com>
|
||||
* Nguyen Hoang Thai Kiet, <kiet.nht@samsung.com>
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/task_integrity.h>
|
||||
#include <soc/qcom/scm.h>
|
||||
#include "tzic.h"
|
||||
|
||||
#ifndef SCM_SVC_FUSE
|
||||
#define SCM_SVC_FUSE 0x08
|
||||
#endif
|
||||
#define SCM_BLOW_SW_FUSE_ID 0x01
|
||||
#define SMC_FUSE 0x83000004
|
||||
#define SCM_IS_SW_FUSE_BLOWN_ID 0x02
|
||||
|
||||
static int set_tamper_fuse_qsee(uint32_t index)
|
||||
{
|
||||
struct scm_desc desc = {0};
|
||||
uint32_t fuse_id;
|
||||
|
||||
desc.args[0] = fuse_id = index;
|
||||
desc.arginfo = SCM_ARGS(1);
|
||||
|
||||
return scm_call2(SCM_SIP_FNID(SCM_SVC_FUSE, SCM_BLOW_SW_FUSE_ID),
|
||||
&desc);
|
||||
}
|
||||
|
||||
static int get_tamper_fuse_qsee(uint32_t index)
|
||||
{
|
||||
int ret;
|
||||
uint32_t fuse_id;
|
||||
uint8_t resp_buf;
|
||||
size_t resp_len;
|
||||
struct scm_desc desc = {0};
|
||||
|
||||
resp_len = sizeof(resp_buf);
|
||||
|
||||
desc.args[0] = fuse_id = index;
|
||||
desc.arginfo = SCM_ARGS(1);
|
||||
|
||||
ret = scm_call2(SCM_SIP_FNID(SCM_SVC_FUSE, SCM_IS_SW_FUSE_BLOWN_ID),
|
||||
&desc);
|
||||
resp_buf = desc.ret[0];
|
||||
|
||||
if (ret) {
|
||||
pr_info("scm_call/2 returned %d", ret);
|
||||
resp_buf = 0xff;
|
||||
}
|
||||
|
||||
return resp_buf;
|
||||
}
|
||||
|
||||
int tzic_oem_flags_set(enum oemflag_id index)
|
||||
{
|
||||
int ret;
|
||||
pr_info("[oemflag]qsee cmd\n");
|
||||
ret = set_tamper_fuse_qsee(index);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int tzic_oem_flags_get(enum oemflag_id index)
|
||||
{
|
||||
int ret;
|
||||
pr_info("[oemflag]qsee cmd\n");
|
||||
ret = get_tamper_fuse_qsee(index);
|
||||
return ret;
|
||||
}
|
82
drivers/security/samsung/tzic/tzic_tzdev.c
Normal file
82
drivers/security/samsung/tzic/tzic_tzdev.c
Normal file
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* Set OEM flags
|
||||
*
|
||||
* Copyright (C) 2018 Samsung Electronics, Inc.
|
||||
* Jonghun Song, <justin.song@samsung.com>
|
||||
* Egor Ulesykiy, <e.uelyskiy@samsung.com>
|
||||
* Nguyen Hoang Thai Kiet, <kiet.nht@samsung.com>
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/errno.h>
|
||||
#if defined(CONFIG_TEEGRIS_VERSION) && (CONFIG_TEEGRIS_VERSION >= 4)
|
||||
#include "extensions/irs.h"
|
||||
#else
|
||||
#include "tzirs.h"
|
||||
#endif
|
||||
#include "tzic.h"
|
||||
|
||||
static uint32_t run_cmd_teegris(uint32_t cmd, uint32_t arg1,
|
||||
uint32_t arg2, uint32_t arg3)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned long p1, p2, p3;
|
||||
|
||||
pr_info("[oemflag]tzirs cmd\n");
|
||||
|
||||
p1 = arg2; // param.name
|
||||
p2 = arg3; // param.value
|
||||
p3 = cmd; // param.func_cmd
|
||||
|
||||
pr_info("[oemflag]before: id = 0x%lx, value = 0x%lx, cmd = 0x%lx\n",
|
||||
(unsigned long)p1, (unsigned long)p2, (unsigned long)p3);
|
||||
|
||||
ret = tzirs_smc(&p1, &p2, &p3);
|
||||
|
||||
pr_info("[oemflag]after: id = 0x%lx, value = 0x%lx, cmd = 0x%lx\n",
|
||||
(unsigned long)p1, (unsigned long)p2, (unsigned long)p3);
|
||||
|
||||
if (ret) {
|
||||
pr_info("[oemflag]Unable to send IRS_CMD : id = 0x%lx, ret = %d\n",
|
||||
(unsigned long)p1, ret);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
arg2 = p1;
|
||||
arg3 = p2;
|
||||
cmd = p3;
|
||||
if(arg1) {
|
||||
return p2;
|
||||
}
|
||||
else {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
int tzic_oem_flags_set(enum oemflag_id index)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = run_cmd_teegris(IRS_SET_FLAG_VALUE_CMD, 0, index, 1);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int tzic_oem_flags_get(enum oemflag_id index)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = run_cmd_teegris(IRS_GET_FLAG_VAL_CMD, 1, index, 0);
|
||||
|
||||
return ret;
|
||||
}
|
|
@ -85,6 +85,14 @@ config SENSORS_YAS539
|
|||
If you say yes here you get support for YAMAHA
|
||||
YAS539 Geomagnitor Sensor.
|
||||
|
||||
config SENSORS_YAS539_A20E
|
||||
tristate "YAS539 Sensor Driver"
|
||||
depends on I2C
|
||||
default n
|
||||
help
|
||||
If you say yes here you get support for YAMAHA
|
||||
YAS539 Geomagnitor Sensor.
|
||||
|
||||
config SENSORS_GP2AP070S
|
||||
depends on I2C
|
||||
tristate "GP2AP070S driver"
|
||||
|
|
|
@ -239,7 +239,7 @@ static void gp2ap_StopMeasurement(struct gp2ap_data *data)
|
|||
gp2ap_i2c_write(REG_COM2, wdata, data->client);
|
||||
}
|
||||
|
||||
static uint32_t gp2ap_get_proximity_adc(struct gp2ap_data *data)
|
||||
static int gp2ap_get_proximity_adc(struct gp2ap_data *data)
|
||||
{
|
||||
u8 value[2];
|
||||
int ret;
|
||||
|
@ -257,7 +257,7 @@ static void gp2ap_InitData(struct gp2ap_data *data)
|
|||
{
|
||||
u8 wdata;
|
||||
u8 offset;
|
||||
uint32_t adc = 0;
|
||||
int adc = 0;
|
||||
|
||||
gp2ap_i2c_read(REG_DYNAMIC_CAL_RESULT, &offset, sizeof(offset), data->client);
|
||||
SENSOR_INFO("offset=%d\n", offset);
|
||||
|
@ -272,6 +272,10 @@ static void gp2ap_InitData(struct gp2ap_data *data)
|
|||
if (offset >= OFFSET_TUNE_ADC &&
|
||||
data->tune_adc_count < MAX_RETRY_TUNE_ADC_COUNT) {
|
||||
adc = gp2ap_get_proximity_adc(data);
|
||||
if(adc < 0) {
|
||||
data->tune_adc_count++;
|
||||
return;
|
||||
}
|
||||
wdata = (adc+ 1280)/256;
|
||||
SENSOR_INFO("Tune ADC: adc %d, wdata 0x%x\n", adc, wdata);
|
||||
if(wdata > 0x0D)
|
||||
|
@ -286,7 +290,7 @@ static void gp2ap_InitData(struct gp2ap_data *data)
|
|||
}
|
||||
|
||||
wdata = 0x00; gp2ap_i2c_write(0x81, wdata, data->client);
|
||||
wdata = 0x00; gp2ap_i2c_write(0x82, wdata, data->client);
|
||||
wdata = 0x02; gp2ap_i2c_write(0x82, wdata, data->client);
|
||||
wdata = 0x13; gp2ap_i2c_write(0x83, wdata, data->client);
|
||||
wdata = 0x10; gp2ap_i2c_write(0x85, wdata, data->client);
|
||||
wdata = data->led_reg_val; gp2ap_i2c_write(0x86, wdata, data->client);
|
||||
|
@ -306,11 +310,10 @@ static void gp2ap_InitDataDynamicCalibration(struct gp2ap_data *data)
|
|||
{
|
||||
u8 wdata;
|
||||
|
||||
SENSOR_INFO("\n");
|
||||
SENSOR_INFO("led_reg_val=%d", data->led_reg_val);
|
||||
|
||||
wdata = 0x00; gp2ap_i2c_write(0x81, wdata, data->client);
|
||||
wdata = 0x10; gp2ap_i2c_write(0x82, wdata, data->client);
|
||||
wdata = 0x12; gp2ap_i2c_write(0x82, wdata, data->client);
|
||||
wdata = 0x10; gp2ap_i2c_write(0x83, wdata, data->client);
|
||||
wdata = 0x10; gp2ap_i2c_write(0x85, wdata, data->client);
|
||||
wdata = data->led_reg_val; gp2ap_i2c_write(0x86, wdata, data->client);
|
||||
|
@ -334,7 +337,7 @@ static ssize_t ps_enable_show(struct device *dev,
|
|||
struct gp2ap_data *data = dev_get_drvdata(dev);
|
||||
int enabled;
|
||||
|
||||
SENSOR_INFO("ps_enable_show\n");
|
||||
SENSOR_INFO("ps_enable_show: %d\n", data->ps_enabled);
|
||||
enabled = data->ps_enabled;
|
||||
return sprintf(buf, "%d", enabled);
|
||||
}
|
||||
|
@ -383,7 +386,7 @@ static void gp2ap_ps_setting(struct gp2ap_data *data)
|
|||
|
||||
static int gp2ap_ps_onoff(u8 onoff, struct gp2ap_data *data)
|
||||
{
|
||||
SENSOR_INFO("proximity_sensor onoff = %d\n", onoff);
|
||||
SENSOR_INFO("onoff= %d\n", onoff);
|
||||
|
||||
if (onoff) {
|
||||
gp2ap_ps_setting(data);
|
||||
|
@ -395,22 +398,18 @@ static int gp2ap_ps_onoff(u8 onoff, struct gp2ap_data *data)
|
|||
|
||||
msleep(50);
|
||||
|
||||
SENSOR_INFO("dynamic calibration done\n");
|
||||
data->dynamic_calib_done = 1;
|
||||
SENSOR_INFO("dynamic calibration done\n");
|
||||
|
||||
if(data->zero_detect)
|
||||
data->zero_detect = 0;
|
||||
gp2ap_InitData(data);
|
||||
|
||||
enable_irq_wake(data->ps_irq);
|
||||
enable_irq(data->ps_irq);
|
||||
gp2ap_InitData(data);
|
||||
} else {
|
||||
gp2ap_InitData(data);
|
||||
}
|
||||
gp2ap_StartMeasurement(data);
|
||||
} else {
|
||||
disable_irq_wake(data->ps_irq);
|
||||
disable_irq(data->ps_irq);
|
||||
|
||||
gp2ap_StopMeasurement(data);
|
||||
}
|
||||
|
||||
|
@ -423,8 +422,6 @@ static ssize_t gp2ap_ps_enable_store(struct device *dev,
|
|||
struct gp2ap_data *data = dev_get_drvdata(dev);
|
||||
bool new_value;
|
||||
|
||||
SENSOR_INFO("data=%s\n", buf);
|
||||
|
||||
if (sysfs_streq(buf, "1"))
|
||||
new_value = true;
|
||||
else if (sysfs_streq(buf, "0"))
|
||||
|
@ -436,7 +433,7 @@ static ssize_t gp2ap_ps_enable_store(struct device *dev,
|
|||
|
||||
mutex_lock(&data->mutex_enable);
|
||||
|
||||
SENSOR_INFO("new_value = %d, ps_enabled = %d\n",
|
||||
SENSOR_INFO("new= %d, ps_enabled= %d\n",
|
||||
new_value, data->ps_enabled);
|
||||
|
||||
if (!data->ps_enabled && new_value) {
|
||||
|
@ -459,10 +456,15 @@ static ssize_t gp2ap_ps_enable_store(struct device *dev,
|
|||
mutex_unlock(&data->mutex_ps_onoff);
|
||||
}
|
||||
|
||||
enable_irq_wake(data->ps_irq);
|
||||
enable_irq(data->ps_irq);
|
||||
schedule_delayed_work(&data->offset_work, msecs_to_jiffies(OFFSET_TUNE_DELAY));
|
||||
|
||||
SENSOR_INFO("proximity_sensor enable!! \n");
|
||||
} else if (data->ps_enabled && !new_value) {
|
||||
disable_irq_wake(data->ps_irq);
|
||||
disable_irq(data->ps_irq);
|
||||
|
||||
cancel_delayed_work_sync(&data->offset_work);
|
||||
mutex_lock(&data->mutex_ps_onoff);
|
||||
gp2ap_ps_onoff(0, data);
|
||||
|
@ -559,9 +561,10 @@ irqreturn_t gp2ap_ps_irq_handler(int irq, void *id_data)
|
|||
|
||||
val = gpio_get_value(data->p_out);
|
||||
|
||||
SENSOR_INFO("val:%d\n", val);
|
||||
|
||||
schedule_work(&data->ps_int_work);
|
||||
/*1: Far, 0: Near */
|
||||
SENSOR_INFO("val:%d en:%d\n", val, data->ps_enabled);
|
||||
if(data->ps_enabled)
|
||||
schedule_work(&data->ps_int_work);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
@ -580,15 +583,12 @@ static void gp2ap_ps_work_int_func(struct work_struct *work)
|
|||
return;
|
||||
|
||||
mutex_lock(&data->mutex_interrupt);
|
||||
|
||||
gp2ap_i2c_read(REG_DYNAMIC_CAL_RESULT, &offset, sizeof(offset), data->client);
|
||||
|
||||
// 0 : proximity, 1 : away
|
||||
gp2ap_i2c_read(0x81, &rdata, sizeof(rdata), data->client);
|
||||
if ((rdata & 0x08) == 0x08)
|
||||
distance = 0;
|
||||
distance = 0; // Near
|
||||
else
|
||||
distance = 1;
|
||||
distance = 1; // Far
|
||||
if (data->ps_distance != distance) {
|
||||
data->ps_distance = distance;
|
||||
}
|
||||
|
@ -601,20 +601,23 @@ static void gp2ap_ps_work_int_func(struct work_struct *work)
|
|||
else if (data->ps_count < data->ps_low_th && (data->high_offset + offset < data->min_close_offset && data->ps_count != 0))
|
||||
near_far = 1;
|
||||
|
||||
SENSOR_INFO("ps_distance:%d, near_far:%d, ps_count:%d\n", data->ps_distance, near_far, data->ps_count);
|
||||
|
||||
if (near_far == 0) {
|
||||
data->zero_detect = 0;
|
||||
}
|
||||
|
||||
SENSOR_INFO("zero_detect=%d\n", data->zero_detect);
|
||||
SENSOR_INFO("dis:%d near_far:%d count:%d zero:%d\n",
|
||||
data->ps_distance, near_far, data->ps_count,data->zero_detect);
|
||||
|
||||
if ((near_far == 1) && (data->ps_count == 0) && (data->zero_detect == 0)) {
|
||||
SENSOR_INFO("zero detection!!!\n");
|
||||
data->zero_detect = 1;
|
||||
mutex_lock(&data->mutex_ps_onoff);
|
||||
disable_irq_wake(data->ps_irq);
|
||||
disable_irq(data->ps_irq);
|
||||
gp2ap_ps_onoff(0, data);
|
||||
gp2ap_ps_onoff(1, data);
|
||||
enable_irq_wake(data->ps_irq);
|
||||
enable_irq(data->ps_irq);
|
||||
mutex_unlock(&data->mutex_ps_onoff);
|
||||
|
||||
if(!offset) {
|
||||
|
@ -652,9 +655,9 @@ static int gp2ap_setup_irq(struct gp2ap_data *gp2ap)
|
|||
}
|
||||
|
||||
gp2ap->ps_irq = gpio_to_irq(gp2ap->p_out);
|
||||
ret = request_irq(gp2ap->ps_irq, gp2ap_ps_irq_handler,
|
||||
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "proximity_int", gp2ap);
|
||||
|
||||
ret = request_irq(gp2ap->ps_irq, gp2ap_ps_irq_handler,
|
||||
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, "proximity_int", gp2ap);
|
||||
|
||||
if (ret < 0) {
|
||||
SENSOR_ERR("request_irq(%d) failed for gpio %d (%d)\n",
|
||||
gp2ap->ps_irq, gp2ap->p_out, ret);
|
||||
|
@ -1004,22 +1007,26 @@ static void gp2ap_offset_work_func(struct work_struct *work)
|
|||
struct gp2ap_data *data = container_of((struct delayed_work *)work,
|
||||
struct gp2ap_data, offset_work);
|
||||
|
||||
uint32_t ps_data;
|
||||
int ps_data;
|
||||
u8 offset;
|
||||
|
||||
ps_data = gp2ap_get_proximity_adc(data);
|
||||
if(!data->ps_enabled) return;
|
||||
|
||||
SENSOR_INFO("ps_data_offset_work=%d\n", ps_data);
|
||||
ps_data = gp2ap_get_proximity_adc(data);
|
||||
SENSOR_INFO("offset=%d\n", ps_data);
|
||||
|
||||
if (ps_data > 0)
|
||||
data->zero_detect = 0;
|
||||
|
||||
if (ps_data == 0 && data->zero_detect == 0) {
|
||||
else if (ps_data == 0 && data->zero_detect == 0) {
|
||||
SENSOR_INFO(" zero detection\n");
|
||||
data->zero_detect = 1;
|
||||
mutex_lock(&data->mutex_ps_onoff);
|
||||
disable_irq_wake(data->ps_irq);
|
||||
disable_irq(data->ps_irq);
|
||||
gp2ap_ps_onoff(0, data);
|
||||
gp2ap_ps_onoff(1, data);
|
||||
enable_irq_wake(data->ps_irq);
|
||||
enable_irq(data->ps_irq);
|
||||
mutex_unlock(&data->mutex_ps_onoff);
|
||||
|
||||
gp2ap_i2c_read(REG_DYNAMIC_CAL_RESULT, &offset, sizeof(offset), data->client);
|
||||
|
@ -1043,7 +1050,7 @@ static ssize_t proximity_state_show(struct device *dev,
|
|||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct gp2ap_data *data = dev_get_drvdata(dev);
|
||||
uint32_t ps_data;
|
||||
int ps_data;
|
||||
|
||||
ps_data = gp2ap_get_proximity_adc(data);
|
||||
|
||||
|
@ -1153,11 +1160,12 @@ static void proximity_get_avg_val(struct gp2ap_data *data)
|
|||
{
|
||||
int min = 0, max = 0, avg = 0;
|
||||
int i;
|
||||
u16 ps_data;
|
||||
int ps_data;
|
||||
|
||||
for (i = 0; i < PROX_READ_NUM; i++) {
|
||||
msleep(40);
|
||||
ps_data = gp2ap_get_proximity_adc(data);
|
||||
if(ps_data < 0) continue;
|
||||
avg += ps_data;
|
||||
if (!i)
|
||||
min = ps_data;
|
||||
|
@ -1454,8 +1462,10 @@ static int gp2ap_suspend(struct device *pdev)
|
|||
|
||||
SENSOR_INFO("is called.\n");
|
||||
|
||||
if (data->ps_enabled)
|
||||
if (data->ps_enabled) {
|
||||
disable_irq(data->ps_irq);
|
||||
cancel_delayed_work_sync(&data->offset_work);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1466,8 +1476,10 @@ static int gp2ap_resume(struct device *pdev)
|
|||
|
||||
SENSOR_INFO("is called.\n");
|
||||
|
||||
if (data->ps_enabled)
|
||||
if (data->ps_enabled) {
|
||||
enable_irq(data->ps_irq);
|
||||
schedule_delayed_work(&data->offset_work, msecs_to_jiffies(OFFSET_TUNE_DELAY));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -457,8 +457,8 @@ static void stk3x3x_prox_cal(struct stk3x3x_data *ps_data)
|
|||
, sunlight_protection_mode);
|
||||
goto exit;
|
||||
} else if ((ps_data->cal_status == STK3X3X_CAL_ONGOING)
|
||||
&& (read_value > ps_data->prox_thd_l - 10)) {
|
||||
SENSOR_ERR("cal failed ps_data = %d, thd l %u\n", read_value, ps_data->prox_thd_l);
|
||||
&& (read_value > ps_data->prox_default_thd_l - 20)) {
|
||||
SENSOR_ERR("cal failed ps_data = %d, thd l %u\n", read_value, ps_data->prox_default_thd_l);
|
||||
goto exit;
|
||||
} else if (!ps_data->first_limit_skip && (ps_data->cal_status == STK3X3X_FIRST_CAL)
|
||||
&& read_value > ps_data->first_cal_adc_limit) {
|
||||
|
@ -555,7 +555,7 @@ static void stk3x3x_work_func_pocket_read(struct work_struct *work)
|
|||
if(ret < 0)
|
||||
SENSOR_ERR("WAIT_REG failed %d\n", ret);
|
||||
|
||||
mdelay(10);
|
||||
usleep_range(10000, 10000);
|
||||
|
||||
// check sunlight mode
|
||||
ret = STK3X3X_REG_READ(ps_data, STK3X3X_SUNLIGHT_CHECK_REG);
|
||||
|
@ -586,7 +586,7 @@ static void stk3x3x_work_func_pocket_read(struct work_struct *work)
|
|||
}
|
||||
}
|
||||
if (i < POCKET_DATA_NUM - 1)
|
||||
mdelay(10);
|
||||
usleep_range(10000, 10000);
|
||||
}
|
||||
read_adc = read_adc / POCKET_DATA_NUM;
|
||||
|
||||
|
|
|
@ -257,7 +257,9 @@ static ssize_t yas_self_test_show(struct device *dev,
|
|||
struct yas_state *data = i2c_get_clientdata(this_client);
|
||||
struct yas539_self_test_result r;
|
||||
s8 err[7] = { 0, };
|
||||
|
||||
#ifdef CONFIG_SENSORS_YAS539_A20E
|
||||
int vector_sum;
|
||||
#endif
|
||||
int ret;
|
||||
|
||||
mutex_lock(&data->lock);
|
||||
|
@ -284,12 +286,26 @@ static ssize_t yas_self_test_show(struct device *dev,
|
|||
err[5] = -2;
|
||||
if (unlikely(r.sxy1y2[2] > 16251 || r.sxy1y2[2] < 15584))
|
||||
err[5] = -4;
|
||||
#ifdef CONFIG_SENSORS_YAS539_A20E
|
||||
if (unlikely(r.xyz[0] < -1500 || r.xyz[0] > 1500))
|
||||
err[6] = -1;
|
||||
if (unlikely(r.xyz[1] < -1500 || r.xyz[1] > 1500))
|
||||
err[6] = -1;
|
||||
if (unlikely(r.xyz[2] < -1500 || r.xyz[2] > 1500))
|
||||
err[6] = -1;
|
||||
vector_sum = r.xyz[0] * r.xyz[0] + r.xyz[1] * r.xyz[1] + r.xyz[2] * r.xyz[2];
|
||||
if (unlikely(vector_sum >= 2250000)) {
|
||||
err[6] = -1;
|
||||
pr_info("[SENSOR] Fail vetor_sum^2= %d\n", vector_sum);
|
||||
}
|
||||
#else
|
||||
if (unlikely(r.xyz[0] < -1000 || r.xyz[0] > 1000))
|
||||
err[6] = -1;
|
||||
if (unlikely(r.xyz[1] < -1000 || r.xyz[1] > 1000))
|
||||
err[6] = -1;
|
||||
if (unlikely(r.xyz[2] < -1000 || r.xyz[2] > 1000))
|
||||
err[6] = -1;
|
||||
#endif
|
||||
|
||||
pr_info("[SENSOR] %s\n"
|
||||
"[SENSOR] Test1 - err = %d, id = %d\n"
|
||||
|
|
|
@ -117,6 +117,13 @@ config CM_OFFSET
|
|||
help
|
||||
set Charging Mode Offset when you enable SEC_PARAM.
|
||||
|
||||
config FMM_LOCK_OFFSET
|
||||
int "FMM lock Offset"
|
||||
default 0
|
||||
depends on SEC_PARAM
|
||||
help
|
||||
set FMM lock Offset when you enable SEC_PARAM.
|
||||
|
||||
config SEC_EVENT_LOG
|
||||
bool "Enable Event log parser"
|
||||
depends on SEC_EXT
|
||||
|
@ -302,3 +309,8 @@ config SEC_PERIPHERAL_SECURE_CHK
|
|||
help
|
||||
This option supports secure check
|
||||
|
||||
config SEC_DEBUG_SNAPSHOT_DISABLE
|
||||
bool "Disable EXYNOS SNAPSHOT logging"
|
||||
default n
|
||||
help
|
||||
This option blocks exynos snapshot logging
|
||||
|
|
|
@ -268,6 +268,30 @@ out:
|
|||
}
|
||||
__setup("androidboot.recovery_offset=", sec_debug_recovery_cause_setup);
|
||||
|
||||
static unsigned long fmm_lock_offset;
|
||||
|
||||
static int __init sec_debug_fmm_lock_offset(char *arg)
|
||||
{
|
||||
fmm_lock_offset = simple_strtoul(arg, NULL, 10);
|
||||
return 0;
|
||||
}
|
||||
|
||||
early_param("sec_debug.fmm_lock_offset", sec_debug_fmm_lock_offset);
|
||||
|
||||
static ssize_t store_FMM_lock(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
char lock;
|
||||
|
||||
sscanf(buf, "%c", &lock);
|
||||
pr_info("%s: store %c in FMM_lock\n", __func__, lock);
|
||||
sec_set_param(fmm_lock_offset, lock);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(FMM_lock, 0220, NULL, store_FMM_lock);
|
||||
|
||||
static int __init sec_debug_recovery_cause_init(void)
|
||||
{
|
||||
struct device *dev;
|
||||
|
@ -282,6 +306,9 @@ static int __init sec_debug_recovery_cause_init(void)
|
|||
if (device_create_file(dev, &dev_attr_recovery_cause) < 0)
|
||||
pr_err("%s: Failed to create device file\n", __func__);
|
||||
|
||||
if (device_create_file(dev, &dev_attr_FMM_lock) < 0)
|
||||
pr_err("%s: Failed to create device file\n", __func__);
|
||||
|
||||
return 0;
|
||||
}
|
||||
late_initcall(sec_debug_recovery_cause_init);
|
||||
|
|
|
@ -126,8 +126,14 @@ int sec_set_param(unsigned long offset, char val)
|
|||
|
||||
mutex_lock(&sec_param_mutex);
|
||||
|
||||
if ((offset < CM_OFFSET) || (offset > CM_OFFSET + CM_OFFSET_LIMIT))
|
||||
goto unlock_out;
|
||||
switch (offset) {
|
||||
case CM_OFFSET ... CM_OFFSET_LIMIT:
|
||||
break;
|
||||
default:
|
||||
if (offset != FMM_LOCK_OFFSET)
|
||||
goto unlock_out;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (val) {
|
||||
case PARAM_OFF:
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user