diff options
| author | Yuval Adam <_@yuv.al> | 2017-08-30 08:25:59 +0000 |
|---|---|---|
| committer | Yuval Adam <_@yuv.al> | 2017-08-30 08:25:59 +0000 |
| commit | 8e4bff4cab0ddac6060645b0715210484d02ff40 (patch) | |
| tree | 3a5c3024371a04692a3a6d9974d001cdff8ebf84 /drivers/input/touchscreen/mms134s/mms134s_sec.c | |
Diffstat (limited to 'drivers/input/touchscreen/mms134s/mms134s_sec.c')
| -rw-r--r-- | drivers/input/touchscreen/mms134s/mms134s_sec.c | 1000 |
1 files changed, 1000 insertions, 0 deletions
diff --git a/drivers/input/touchscreen/mms134s/mms134s_sec.c b/drivers/input/touchscreen/mms134s/mms134s_sec.c new file mode 100644 index 00000000..e578ceed --- /dev/null +++ b/drivers/input/touchscreen/mms134s/mms134s_sec.c @@ -0,0 +1,1000 @@ +static void set_cmd_result(struct mms_fac_data *fac_data, char *buff, int len) +{ + strncat(fac_data->cmd_result, buff, len); +} + +static void set_default_result(struct mms_fac_data *fac_data) +{ + char delim = ':'; + + memset(fac_data->cmd_result, 0x00, ARRAY_SIZE(fac_data->cmd_result)); + memset(fac_data->cmd_buff, 0x00, ARRAY_SIZE(fac_data->cmd_buff)); + memcpy(fac_data->cmd_result, fac_data->cmd, strlen(fac_data->cmd)); + strncat(fac_data->cmd_result, &delim, 1); +} + +static ssize_t show_cmd_status(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct mms_info *info = dev_get_drvdata(dev); + struct mms_fac_data *fac_data = info->fac_data; + struct i2c_client *client = info->client; + char buff[16] = {0,}; + + dev_info(&client->dev, "cmd status %d\n", fac_data->cmd_state); + + switch (fac_data->cmd_state) { + case CMD_STATUS_WAITING: + sprintf(buff, "%s", "WAITING"); + break; + case CMD_STATUS_RUNNING: + sprintf(buff, "%s", "RUNNING"); + break; + case CMD_STATUS_OK: + sprintf(buff, "%s", "OK"); + break; + case CMD_STATUS_FAIL: + sprintf(buff, "%s", "FAIL"); + break; + case CMD_STATUS_NOT_APPLICABLE: + sprintf(buff, "%s", "NOT_APPLICABLE"); + break; + default: + sprintf(buff, "%s", "NOT_APPLICABLE"); + break; + } + + return sprintf(buf, "%s\n", buff); +} + +static ssize_t show_cmd_result(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct mms_info *info = dev_get_drvdata(dev); + struct mms_fac_data *fac_data = info->fac_data; + struct i2c_client *client = info->client; + + dev_info(&client->dev, "cmd result %s\n", fac_data->cmd_result); + + mutex_lock(&fac_data->cmd_lock); + fac_data->cmd_is_running = false; + mutex_unlock(&fac_data->cmd_lock); + + fac_data->cmd_state = CMD_STATUS_WAITING; + + return sprintf(buf, "%s", fac_data->cmd_result); +} + +static int update_from_req_fw(struct mms_info *info) +{ + struct i2c_client *client = info->client; + const char *path = info->pdata->inkernel_fw_name; + const struct firmware *fw; + int ret = 0; + + dev_info(&client->dev, "%s : firmware load %s\n", __func__, path); + + ret = request_firmware(&fw, path, &client->dev); + if (ret) { + dev_err(&client->dev, "Failed to request built-in fw (%d)\n", ret); + goto out; + } + + ret = mms_flash_fw(fw, info); + release_firmware(fw); + +out: + return ret; +} + +static int update_from_ums(struct mms_info *info) +{ + struct i2c_client *client = info->client; + const char *path = info->pdata->ums_fw_name; + mm_segment_t old_fs; + struct file *fp; + long fsize, nread; + struct firmware fw; + u8 *buff; + int ret = 0; + + dev_info(&client->dev, "%s : file open %s\n", __func__, path); + + old_fs = get_fs(); + set_fs(KERNEL_DS); + + fp = filp_open(path, O_RDONLY, S_IRUSR); + if (IS_ERR(fp)) { + dev_err(&client->dev, "Failed to open file\n"); + ret = PTR_ERR(fp); + goto err_file_open; + } + + fsize = fp->f_path.dentry->d_inode->i_size; + + buff = kzalloc((size_t)fsize, GFP_KERNEL); + if (!buff) { + dev_err(&client->dev, "Failed to allocate memory\n"); + ret = -ENOMEM; + goto err_mem_alloc; + } + + + nread = vfs_read(fp, (char __user *)buff, fsize, &fp->f_pos); + if (fsize != nread) { + dev_err(&client->dev, "Failed to read file correctly\n"); + ret = -EPERM; + goto err_file_read; + } + + fw.size = fsize; + fw.data = buff; + ret = mms_flash_fw(&fw, info); + +err_file_read: + kfree(buff); +err_mem_alloc: + filp_close(fp, NULL); +err_file_open: + set_fs(old_fs); + + return ret; +} + +static void fw_update(void *device_data) +{ + struct mms_info *info = (struct mms_info *)device_data; + struct mms_fac_data *fac_data = info->fac_data; + struct i2c_client *client = info->client; + int fw_type = fac_data->cmd_param[0]; + int ret; + + set_default_result(fac_data); + + if (!info->enabled) { + dev_err(&client->dev, "%s : TSP is disabled\n"); + goto out; + } + + mutex_lock(&info->input_dev->mutex); + disable_irq(info->irq); + + switch (fw_type) { + case FW_FROM_BUILT_IN: + ret = update_from_req_fw(info); + break; + case FW_FROM_UMS: + ret = update_from_ums(info); + break; + default: + dev_err(&client->dev, + "%s : Invalid update type(%d)\n", __func__, fw_type); + goto err_update; + break; + } + + if (ret) { + dev_err(&client->dev, "%s : Failed fw update(%d)\n", __func__, ret); + goto err_update; + } + + enable_irq(info->irq); + mutex_unlock(&info->input_dev->mutex); + + fac_data->cmd_state = (ret) ? CMD_STATUS_FAIL : CMD_STATUS_OK; + sprintf(fac_data->cmd_buff, "%s", (ret) ? "NG" : "OK"); + set_cmd_result(fac_data, fac_data->cmd_buff, strlen(fac_data->cmd_buff)); + + dev_info(&client->dev, "%s : %s\n", __func__, fac_data->cmd_buff); + + return; + +err_update: + enable_irq(info->irq); + mutex_unlock(&info->input_dev->mutex); +out: + fac_data->cmd_state = CMD_STATUS_FAIL; + sprintf(fac_data->cmd_buff, "%s", "NG"); + set_cmd_result(fac_data, fac_data->cmd_buff, strlen(fac_data->cmd_buff)); + + return; +} + +static void get_threshold(void *device_data) +{ + struct mms_info *info = (struct mms_info *)device_data; + struct mms_fac_data *fac_data = info->fac_data; + struct i2c_client *client = info->client; + u8 buff; + + set_default_result(fac_data); + + buff = i2c_smbus_read_byte_data(info->client, MMS_THRESHOLD); + if (buff < 0) { + dev_err(&client->dev, "Failed to read threshold (%d)\n", buff); + goto out; + } + + fac_data->cmd_state = CMD_STATUS_OK; + sprintf(fac_data->cmd_buff, "%d", buff); + set_cmd_result(fac_data, fac_data->cmd_buff, strlen(fac_data->cmd_buff)); + + dev_info(&client->dev, "%s : %s\n", __func__, fac_data->cmd_buff); + + return; + +out: + fac_data->cmd_state = FAIL; + sprintf(fac_data->cmd_buff, "%s", "NG"); + set_cmd_result(fac_data, fac_data->cmd_buff, strlen(fac_data->cmd_buff)); + return ; +} +/* +static void module_off_master(void *device_data) +{ + struct mms_ts_info *info = (struct mms_ts_info *)device_data; + struct i2c_client *client = info->client; + + set_default_result(info); + + if (info->pdata->vdd_on) + info->pdata->vdd_on(&info->client->dev, 0); + + sprintf(info->cmd_buff, "%s", "OK"); + set_cmd_result(info, info->cmd_buff, strlen(info->cmd_buff)); + info->cmd_state = CMD_STATUS_OK; + + dev_info(&client->dev, "%s: \"%s\"(%d)\n", __func__, + info->cmd_buff, strlen(info->cmd_buff)); + + return; +} + +static void module_on_master(void *device_data) +{ + struct mms_ts_info *info = (struct mms_ts_info *)device_data; + struct i2c_client *client = info->client; + + set_default_result(info); + + mms_pwr_on_reset(info); + + sprintf(info->cmd_buff, "%s", "OK"); + set_cmd_result(info, info->cmd_buff, strlen(info->cmd_buff)); + info->cmd_state = CMD_STATUS_OK; + + dev_info(&client->dev, "%s: \"%s\"(%d)\n", __func__, + info->cmd_buff, strlen(info->cmd_buff)); + + return; +} +*/ +static void get_x_num(void *device_data) +{ + struct mms_info *info = (struct mms_info *)device_data; + struct mms_fac_data *fac_data = info->fac_data; + struct i2c_client *client = info->client; + + set_default_result(fac_data); + + fac_data->cmd_state = CMD_STATUS_OK; + sprintf(fac_data->cmd_buff, "%d", fac_data->xnode_num); + set_cmd_result(fac_data, fac_data->cmd_buff, strlen(fac_data->cmd_buff)); + + dev_info(&client->dev, "%s : %s\n", __func__, fac_data->cmd_buff); + + return; +} + +static void get_y_num(void *device_data) +{ + struct mms_info *info = (struct mms_info *)device_data; + struct mms_fac_data *fac_data = info->fac_data; + struct i2c_client *client = info->client; + + set_default_result(fac_data); + + fac_data->cmd_state = CMD_STATUS_OK; + sprintf(fac_data->cmd_buff, "%d", fac_data->ynode_num); + set_cmd_result(fac_data, fac_data->cmd_buff, strlen(fac_data->cmd_buff)); + + dev_info(&client->dev, "%s : %s\n", __func__, fac_data->cmd_buff); + + return; +} + +static int enter_test_mode(struct mms_info *info) +{ + struct i2c_client *client = info->client; + int ret = 0; + + disable_irq(info->irq); + + ret = i2c_smbus_write_byte_data( + client, MMS_UNIVERSAL_CMD, MMS_UNIV_ENTER_TEST); + if (ret < 0) { + dev_err(&client->dev, "Failed to enter test mode(%d)\n", ret); + goto out; + } + + do { + udelay(100); + } while (gpio_get_value(info->pdata->gpio_int)); + + ret = i2c_smbus_read_byte_data(client, MMS_EVENT_PKT); + dev_info(&client->dev, "event(%x)\n", ret); + + if (ret != MMS_TEST_MODE) { + dev_err(&client->dev, "Failed to check maker(%x)\n", ret); + ret = -EPERM; + goto out; + } + + return 0; + +out: + enable_irq(info->irq); + return ret; +} + +static int exit_test_mode(struct mms_info *info) +{ + struct i2c_client *client = info->client; + int ret = 0; + + ret = i2c_smbus_write_byte_data( + client, MMS_UNIVERSAL_CMD, MMS_UNIV_EXIT_TEST); + if (ret < 0) { + dev_err(&client->dev, "Failed to exit test mode(%d)\n", ret); + goto out; + } + + enable_irq(info->irq); + + return 0; + +out: + enable_irq(info->irq); + + return ret; +} + +static int read_cm_data_all(struct mms_info *info, u8 univ_cmd, + u8 univ_key_cmd) +{ + struct mms_fac_data *fac_data = info->fac_data; + struct i2c_client *client = info->client; + int r, t; + int ret = 0; + u8 buf[256] = {0, }; + u8 reg[4] = {0, }; + s16 cm_data; + char data[5]; + struct i2c_msg msg[] = { + { + .addr = client->addr, + .flags = 0, + .buf = reg, + }, + { + .addr = client->addr, + .flags = I2C_M_RD, + }, + }; + + ret = i2c_smbus_write_byte_data(client, MMS_UNIVERSAL_CMD, univ_cmd); + if (ret < 0) { + dev_err(&client->dev, "%s : Failed to send %x cmd(%d)\n", + __func__, univ_cmd, ret); + goto out; + } + + do { + udelay(100); + } while (gpio_get_value(info->pdata->gpio_int)); + + ret = i2c_smbus_read_byte_data(client, MMS_UNIVERSAL_RESULT); + if (ret < 0) { + dev_err(&client->dev, "%s : Failed 0x%x test(%d)\n", __func__, + univ_cmd, ret); + goto out; + } + + msleep(1); + + pr_info("cm_data\n"); + pr_info("view\n"); + for (r = 0 ; r < fac_data->xnode_num; r++) { + reg[0] = MMS_UNIVERSAL_CMD; + reg[1] = univ_cmd + 1; /* get univ_cmd value from node */ + reg[2] = 0xFF; + reg[3] = r; + msg[0].len = 4; + + if (i2c_transfer(client->adapter, &msg[0], 1) != 1) { + dev_err(&client->dev, "%s : Failed to send cmd for node\n", + __func__); + ret = -EPERM; + goto out; + } + + while (gpio_get_value(info->pdata->gpio_int)); + + ret = i2c_smbus_read_byte_data(client, MMS_UNIVERSAL_RESULT_SZ); + if (ret < 0) { + dev_err(&client->dev, "%s : Failed to read node result size\n", + __func__); + goto out; + } + + reg[0] = MMS_UNIVERSAL_RESULT; + msg[0].len = 1; + msg[1].len = ret; + msg[1].buf = buf; + + if (i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg)) + != ARRAY_SIZE(msg)) { + dev_err(&client->dev, "%s : Failed to read node value\n", + __func__); + ret = -EPERM; + goto out; + } + + for (t = 0; t < fac_data->ynode_num; t++){ + cm_data = (s16)(buf[2 * t] | (buf[(2 * t) + 1] << 8)); + pr_info("%d\n", cm_data); + } + pr_info("---------\n"); + } + +#if MMS_HAS_TOUCH_KEY + pr_info("key\n"); + if (fac_data->keynode_num) { + reg[0] = MMS_UNIVERSAL_CMD; + reg[1] = univ_key_cmd; + reg[2] = 0xFF; + reg[3] = 0x00; + msg[0].len = 4; + + if (i2c_transfer(client->adapter, &msg[0],1) != 1) { + dev_err(&client->dev, "%s : Failed to send cmd for key\n", + __func__); + ret = EPERM; + goto out; + } + + while (gpio_get_value(info->pdata->gpio_int)); + + ret = i2c_smbus_read_byte_data(client, MMS_UNIVERSAL_RESULT_SZ); + if (ret < 0) { + dev_err(&client->dev, "%s : Failed to read key result size\n", + __func__); + goto out; + } + + reg[0] = MMS_UNIVERSAL_RESULT; + msg[0].len = 1; + msg[1].len = ret; + msg[1].buf = buf; + + if(i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg)) + != ARRAY_SIZE(msg)){ + ret = -EPERM; + goto out; + } + + for (t = 0; t < fac_data->keynode_num; t++) { + cm_data = (s16)(buf[2 * t] | (buf[(2 * t) + 1] << 8)); + pr_info("%d\n", cm_data); + } + } +#endif + +out: + return ret; +} + +static void run_cm_delta_read(void *device_data) +{ + struct mms_info *info = (struct mms_info *)device_data; + struct mms_fac_data *fac_data = info->fac_data; + struct i2c_client *client = info->client; + int ret; + + set_default_result(fac_data); + + ret = enter_test_mode(info); + if (ret < 0) { + dev_err(&client->dev, "%s : Failed to enter test mode\n", __func__); + goto out; + } + + ret = read_cm_data_all(info, MMS_UNIV_CM_DELTA, MMS_UNIV_GET_DELTA_KEY); + if (ret < 0) { + dev_err(&client->dev, "%s : Failed to read cm data\n", __func__); + goto out; + } + + ret = exit_test_mode(info); + if (ret < 0) { + dev_err(&client->dev, "%s : Failed to exit test mode\n", __func__); + goto out; + } + + fac_data->cmd_state = CMD_STATUS_OK; +// sprintf(fac_data->cmd_buff, "%d,%d", raw_min, raw_max); + set_cmd_result(fac_data, fac_data->cmd_buff, strlen(fac_data->cmd_buff)); + + dev_info(&client->dev, "%s : %s\n", __func__, fac_data->cmd_buff); + + return; + +out: + fac_data->cmd_state = CMD_STATUS_FAIL; + sprintf(fac_data->cmd_buff, "%s", "NG"); + set_cmd_result(fac_data, fac_data->cmd_buff, strlen(fac_data->cmd_buff)); + + return; +} + +static void run_cm_abs_read(void *device_data) +{ + struct mms_info *info = (struct mms_info *)device_data; + struct mms_fac_data *fac_data = info->fac_data; + struct i2c_client *client = info->client; + int ret; + + set_default_result(fac_data); + + ret = enter_test_mode(info); + if (ret < 0) { + dev_err(&client->dev, "%s : Failed to enter test mode\n", __func__); + goto out; + } + + ret = read_cm_data_all(info, MMS_UNIV_CM_ABS, MMS_UNIV_GET_ABS_KEY); + if (ret < 0) { + dev_err(&client->dev, "%s : Failed to read cm data\n", __func__); + goto out; + } + + ret = exit_test_mode(info); + if (ret < 0) { + dev_err(&client->dev, "%s : Failed to exit test mode\n", __func__); + goto out; + } + + fac_data->cmd_state = CMD_STATUS_OK; +// sprintf(fac_data->cmd_buff, "%d,%d", raw_min, raw_max); + set_cmd_result(fac_data, fac_data->cmd_buff, strlen(fac_data->cmd_buff)); + + dev_info(&client->dev, "%s : %s\n", __func__, fac_data->cmd_buff); + + return; + +out: + fac_data->cmd_state = CMD_STATUS_FAIL; + sprintf(fac_data->cmd_buff, "%s", "NG"); + set_cmd_result(fac_data, fac_data->cmd_buff, strlen(fac_data->cmd_buff)); + + return; +} + +static int read_raw_data_all(struct mms_info *info, u8 univ_cmd) +{ + struct mms_fac_data *fac_data = info->fac_data; + struct i2c_client *client = info->client; + int r, t; + int ret = 0; + u8 buf[42] = {0, }; + u8 reg[4] = {0, }; + s16 raw_data; + char data[5]; + struct i2c_msg msg[] = { + { + .addr = client->addr, + .flags = 0, + .buf = reg, + }, + { + .addr = client->addr, + .flags = I2C_M_RD, + }, + }; + + pr_info("raw_data\n"); + pr_info("view\n"); + for (r = 0 ; r < fac_data->xnode_num ; r++) { + reg[0] = MMS_UNIVERSAL_CMD; + reg[1] = univ_cmd; + reg[2] = 0xFF; + reg[3] = r; + msg[0].len = 4; + + msleep(1); + + if (i2c_transfer(client->adapter, &msg[0], 1) != 1) { + dev_err(&client->dev, "%s : Failed to send cmd for node\n", + __func__); + ret = -EPERM; + goto out; + } + + ret = i2c_smbus_read_byte_data(client, MMS_UNIVERSAL_RESULT_SZ); + if (ret < 0) { + dev_err(&client->dev, "%s : Failed to read node result size\n", + __func__); + goto out; + } + + reg[0] = MMS_UNIVERSAL_RESULT; + msg[0].len = 1; + msg[1].len = ret; + msg[1].buf = buf; + + if (i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg)) + != ARRAY_SIZE(msg)){ + ret = -EPERM; + goto out; + } + + ret >>= 1; + + for (t = 0 ; t < ret ; t++) { + raw_data = (s16)(buf[2 * t] | (buf[(2 * t) + 1] << 8)); + pr_info("%d\n", raw_data); + } + pr_info("---------\n"); + } + +#if MMS_HAS_TOUCH_KEY + pr_info("key\n"); + if (fac_data->keynode_num) { + reg[0] = MMS_UNIVERSAL_CMD; + reg[1] = univ_cmd + 1; /* univ_cmd for key */ + reg[2] = 0xFF; + reg[3] = 0x00; + msg[0].len = 4; + + if (i2c_transfer(client->adapter, &msg[0], 1) != 1) { + dev_err(&client->dev, "%s : Failed to send cmd for key\n", + __func__); + ret = EPERM; + goto out; + } + + while (gpio_get_value(info->pdata->gpio_int)); + + ret = i2c_smbus_read_byte_data(client, MMS_UNIVERSAL_RESULT_SZ); + if (ret < 0) { + dev_err(&client->dev, "%s : Failed to read key result size\n", + __func__); + goto out; + } + + reg[0] = MMS_UNIVERSAL_RESULT; + msg[0].len = 1; + msg[1].len = ret; + msg[1].buf = buf; + + if (i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg)) + != ARRAY_SIZE(msg)) { + ret = -EPERM; + return ret; + } + + for (t = 0; t < fac_data->keynode_num; t++){ + raw_data = (s16)(buf[2 * t] | (buf[(2 * t) + 1] << 8)); + pr_info("%d\n", raw_data); + } + } +#endif + +out: + return ret; +} + +static void run_intensity_read(void *device_data) +{ + struct mms_info *info = (struct mms_info *)device_data; + struct mms_fac_data *fac_data = info->fac_data; + struct i2c_client *client = info->client; + int ret; + + set_default_result(fac_data); + + disable_irq(info->irq); + + ret = read_raw_data_all(info, MMS_UNIV_INTENSITY); + if (ret < 0) { + dev_err(&client->dev, "%s : Failed to read raw data\n", __func__); + goto out; + } + + enable_irq(info->irq); + + fac_data->cmd_state = CMD_STATUS_OK; +// sprintf(fac_data->cmd_buff, "%d,%d", raw_min, raw_max); + set_cmd_result(fac_data, fac_data->cmd_buff, strlen(fac_data->cmd_buff)); + + dev_info(&client->dev, "%s : %s\n", __func__, fac_data->cmd_buff); + + return; + +out: + enable_irq(info->irq); + + fac_data->cmd_state = CMD_STATUS_FAIL; + sprintf(fac_data->cmd_buff, "%s", "NG"); + set_cmd_result(fac_data, fac_data->cmd_buff, strlen(fac_data->cmd_buff)); + + return; +} + +static void not_support_cmd(void *device_data) +{ + struct mms_info *info = (struct mms_info *)device_data; + struct mms_fac_data *fac_data = info->fac_data; + struct i2c_client *client = info->client; + + set_default_result(fac_data); + + sprintf(fac_data->cmd_buff, "%s", "NA"); + set_cmd_result(fac_data, fac_data->cmd_buff, strlen(fac_data->cmd_buff)); + fac_data->cmd_state = CMD_STATUS_NOT_APPLICABLE; + dev_info(&client->dev, "%s : %s\n", __func__, fac_data->cmd_buff); + + return; +} + +#define TSP_CMD(name, func) .cmd_name = name, .cmd_func = func + +struct tsp_cmd { + struct list_head list; + const char *cmd_name; + void (*cmd_func)(void *device_data); +}; + +struct tsp_cmd tsp_cmds[] = { + {TSP_CMD("fw_update", fw_update),}, +/* {TSP_CMD("get_fw_ver_bin", get_fw_ver_bin),}, + {TSP_CMD("get_fw_ver_ic", get_fw_ver_ic),}, + {TSP_CMD("get_config_ver", not_support_cmd),},*/ + {TSP_CMD("get_threshold", get_threshold),}, + {TSP_CMD("module_off_master", not_support_cmd),}, + {TSP_CMD("module_on_master", not_support_cmd),}, + {TSP_CMD("module_off_slave", not_support_cmd),}, + {TSP_CMD("module_on_slave", not_support_cmd),}, +/* {TSP_CMD("get_chip_vendor", get_chip_vendor),}, + {TSP_CMD("get_chip_name", get_chip_name),},*/ + {TSP_CMD("get_x_num", get_x_num),}, + {TSP_CMD("get_y_num", get_y_num),}, +/* {TSP_CMD("run_reference_read", run_reference_read),}, + {TSP_CMD("run_inspection_read", run_inspection_read),},*/ + {TSP_CMD("run_cm_delta_read", run_cm_delta_read),}, + {TSP_CMD("run_cm_abs_read", run_cm_abs_read),}, + {TSP_CMD("run_intensity_read", run_intensity_read),}, +/* {TSP_CMD("get_reference", get_reference),}, + {TSP_CMD("get_cm_abs", get_cm_abs),}, + {TSP_CMD("get_inspection", get_inspection),}, + {TSP_CMD("get_cm_delta", get_inspection),}, + {TSP_CMD("get_intensity", get_intensity),},*/ + {TSP_CMD("not_support_cmd", not_support_cmd),}, +}; + +static ssize_t store_cmd(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + struct mms_info *info = dev_get_drvdata(dev); + struct mms_fac_data *fac_data = info->fac_data; + struct i2c_client *client = info->client; + char *cur, *start, *end; + char buff[TSP_CMD_STR_LEN] = {0, }; + int len, i; + struct tsp_cmd *tsp_cmd_ptr = NULL; + char delim = ','; + bool cmd_found = false; + int param_cnt = 0; + + if (!info->enabled) { + dev_err(&client->dev, "%s: device is disabled\n", __func__); + goto err_out; + } + + if (fac_data->cmd_is_running) { + dev_err(&client->dev, "%s: other cmd is running\n", __func__); + goto err_out; + } + + /* check lock */ + mutex_lock(&fac_data->cmd_lock); + fac_data->cmd_is_running = true; + mutex_unlock(&fac_data->cmd_lock); + + fac_data->cmd_state = CMD_STATUS_RUNNING; + + for (i = 0; i < ARRAY_SIZE(fac_data->cmd_param); i++) + fac_data->cmd_param[i] = 0; + + len = (int)count; + + if (*(buf + len - 1) == '\n') + len--; + + memset(fac_data->cmd, 0x00, ARRAY_SIZE(fac_data->cmd)); + memcpy(fac_data->cmd, buf, len); + + cur = strchr(buf, (int)delim); + if (cur) + memcpy(buff, buf, cur - buf); + else + memcpy(buff, buf, len); + + /* find command */ + list_for_each_entry(tsp_cmd_ptr, &fac_data->cmd_list_head, list) { + if (!strcmp(buff, tsp_cmd_ptr->cmd_name)) { + cmd_found = true; + break; + } + } + + /* set not_support_cmd */ + if (!cmd_found) { + list_for_each_entry(tsp_cmd_ptr, &fac_data->cmd_list_head, list) { + if (!strcmp("not_support_cmd", tsp_cmd_ptr->cmd_name)) + break; + } + } + + /* parsing TSP standard tset parameter */ + if (cur && cmd_found) { + cur++; + start = cur; + + do { + if (*cur == delim || cur - buf == len) { + memset(buff, 0x00, ARRAY_SIZE(buff)); + end = cur; + memcpy(buff, start, end - start); + *(buff + strlen(buff)) = '\0'; + kstrtol(buff, 10, fac_data->cmd_param + param_cnt); + start = cur + 1; + param_cnt++; + } + cur++; + } while (cur - buf <= len); + } + + dev_info(&client->dev, "cmd = %s\n", tsp_cmd_ptr->cmd_name); + + for (i = 0; i < param_cnt; i++) + dev_info(&client->dev, "cmd param %d = %d\n", + i, fac_data->cmd_param[i]); + + tsp_cmd_ptr->cmd_func(info); + +err_out: + return count; +} + +static DEVICE_ATTR(cmd, S_IWUSR | S_IWGRP, NULL, store_cmd); +static DEVICE_ATTR(cmd_status, S_IRUGO, show_cmd_status, NULL); +static DEVICE_ATTR(cmd_result, S_IRUGO, show_cmd_result, NULL); + +static struct attribute *touchscreen_attributes[] = { + &dev_attr_cmd.attr, + &dev_attr_cmd_status.attr, + &dev_attr_cmd_result.attr, + NULL, +}; + +static struct attribute_group touchscreen_attr_group = { + .attrs = touchscreen_attributes, +}; + +static int get_nodenum(struct mms_info *info) +{ + struct mms_fac_data *fac_data = info->fac_data; + struct i2c_client *client = info->client; + int ret; + + ret = i2c_smbus_read_byte_data(client, MMS_TX_NUM); + if (ret <= 0) { + dev_err(&client->dev, "Failed to read xnode num(%d)\n", ret); + return ret; + } + fac_data->xnode_num = ret; + + ret = i2c_smbus_read_byte_data(client, MMS_RX_NUM); + if (ret <= 0) { + dev_err(&client->dev, "Failed to read ynode num(%d)\n", ret); + return ret; + } + fac_data->ynode_num = ret; + + ret = i2c_smbus_read_byte_data(client, MMS_KEY_NUM); + if (ret <= 0) { + dev_err(&client->dev, "Failed to read keynode num(%d)\n", ret); + return ret; + } + fac_data->keynode_num = ret; + + return 0; +} + +extern struct class *sec_class; + +static int init_sec(struct mms_info *info) +{ + struct i2c_client *client = info->client; + struct mms_fac_data *fac_data; + int i; + int ret; + + fac_data = kzalloc(sizeof(struct mms_fac_data), GFP_KERNEL); + if (!fac_data) { + dev_err(&client->dev, "Failed to allocate factory data memory\n"); + return -ENOMEM; + } + info->fac_data = fac_data; + + mutex_init(&fac_data->cmd_lock); + fac_data->cmd_is_running = false; + + INIT_LIST_HEAD(&fac_data->cmd_list_head); + for (i = 0; i < ARRAY_SIZE(tsp_cmds); i++) + list_add_tail(&tsp_cmds[i].list, &fac_data->cmd_list_head); + + ret = get_nodenum(info); + if (ret) { + dev_err(&client->dev, "Failed to read node number(%d)\n", ret); + goto err_create_dev_ts; + } + +/* info->raw_cm_abs = kzalloc(raw_data_size, GFP_KERNEL); + info->raw_inspection = kzalloc(raw_data_size, GFP_KERNEL); + info->raw_intensity = kzalloc(raw_data_size, GFP_KERNEL); + info->raw_reference = kzalloc(raw_data_size, GFP_KERNEL); + if (!info->raw_cm_abs || !info->raw_inspection || + !info->raw_intensity || !info->raw_reference) { + dev_err(&client->dev, "Failed to allocate memory\n"); + ret = -ENOMEM; + goto err_create_dev_ts; + } +*/ + fac_data->fac_tsp_dev = device_create( + sec_class, NULL, (dev_t)NULL, info, "tsp"); + if (IS_ERR(fac_data->fac_tsp_dev)) { + ret = PTR_ERR(fac_data->fac_tsp_dev); + dev_err(&client->dev, + "Failed to create device for touch screen (%d)\n", ret); + ret = -ENODEV; + goto err_create_dev_ts; + } + + ret = sysfs_create_group( + &fac_data->fac_tsp_dev->kobj, &touchscreen_attr_group); + if (ret) { + dev_err(&client->dev, + "Failed to create sysfs for touch screen (%d)\n", ret); + ret = (ret > 0) ? -ret : ret; + goto err_create_ts_sysfs; + } + + return 0; + +err_create_ts_sysfs: + device_destroy(sec_class, (dev_t)NULL); +err_create_dev_ts: + kfree(fac_data); + + return ret; +} + +static void destroy_sec(struct mms_info *info) +{ + sysfs_remove_group( + &info->fac_data->fac_tsp_dev->kobj, &touchscreen_attr_group); + device_destroy(sec_class, (dev_t)NULL); + kfree(info->fac_data); +}
\ No newline at end of file |
