A750FNPUU4CTE3

This commit is contained in:
prashantpaddune 2020-08-18 17:38:19 +05:30
parent 7bf46eb137
commit 671d649fa8
167 changed files with 11715 additions and 5949 deletions

View File

@ -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 */
};
};

View File

@ -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

View File

@ -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;

View File

@ -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,

View File

@ -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);
}
}

View File

@ -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__,

View File

@ -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);

View File

@ -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);

View File

@ -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, &reg_0x41);
s2mu005_read_reg_byte(fuelgauge->i2c, 0x27, &reg_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",

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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)

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;
}

View File

@ -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

View File

@ -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__);
}

View File

@ -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++;
}

View 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"],
}

View File

@ -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;
/*

View File

@ -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);
}

View File

@ -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/

View File

@ -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);

View File

@ -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;

View File

@ -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),},

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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;

View File

@ -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),},

View File

@ -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);
}

View File

@ -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);

View File

@ -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

View File

@ -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);

View File

@ -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;

View File

@ -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 */

View File

@ -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;

View File

@ -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);

View File

@ -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) {

View File

@ -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 {

View File

@ -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;

View File

@ -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) {

View File

@ -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));

View File

@ -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:

View File

@ -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,

View File

@ -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;
}
/**

View File

@ -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[] = {

View File

@ -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,

View File

@ -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);

View File

@ -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 */

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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)

View File

@ -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__*/

View File

@ -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,

View File

@ -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;
}

View File

@ -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;

View File

@ -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) {

View File

@ -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 == &regulator_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(&regulator_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(&regulator_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)
{

View 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

View 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

View 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__ */

View 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);

View File

@ -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__ */

View File

@ -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);
}
}
}

View File

@ -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_ */

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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 */

View File

@ -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;
}

View File

@ -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_ */

View 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

View 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

View 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

View 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(&param, (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(&param, (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(&param, (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(&param, (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(&param, (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);

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View File

@ -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"

View File

@ -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;
}

View File

@ -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;

View File

@ -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"

View File

@ -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

View File

@ -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);

View File

@ -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