static ssize_t proximity_enable_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct gp2a_data *data = dev_get_drvdata(dev); int value = 0; int err = 0; int16_t thrd; u8 reg; err = kstrtoint(buf, 10, &value); if (err) { pr_err("%s, kstrtoint failed.", __func__); goto done; } if (value != 0 && value != 1) goto done; printk(KERN_INFO "[GP2A] proximity_enable_store : value=%d, offset=%d\n", value, data->offset_value); if (data->proximity_enabled && !value) { /* Prox power off */ data->proximity_enabled = value; disable_irq(data->irq); proximity_onoff(0, data); if (data->pdata->led_on) data->pdata->led_on(0); } if (!data->proximity_enabled && value) { /* prox power on */ data->proximity_enabled = value; if (data->pdata->led_on) data->pdata->led_on(1); msleep(5); proximity_onoff(1, data); thrd = gp2a_reg[3][1]+(data->offset_value); THR_REG_LSB(thrd, reg); gp2a_i2c_write(gp2a_reg[3][0], ®); THR_REG_MSB(thrd, reg); gp2a_i2c_write(gp2a_reg[4][0], ®); thrd = gp2a_reg[5][1]+(data->offset_value); THR_REG_LSB(thrd, reg); gp2a_i2c_write(gp2a_reg[5][0], ®); THR_REG_MSB(thrd, reg); gp2a_i2c_write(gp2a_reg[6][0], ®); input_report_abs(data->proximity_input_dev, ABS_DISTANCE, 1); input_sync(data->proximity_input_dev); enable_irq(data->irq); } done: return count; }
static int gp2a_prox_manual_offset(struct gp2a_data *data, u8 change_on) { struct file *cal_filp; int err; int16_t thrd; u8 reg; mm_segment_t old_fs; data->offset_value = change_on; /* update threshold */ thrd = gp2a_reg[3][1]+(data->offset_value); THR_REG_LSB(thrd, reg); gp2a_i2c_write(data, gp2a_reg[3][0], ®); THR_REG_MSB(thrd, reg); gp2a_i2c_write(data, gp2a_reg[4][0], ®); thrd = gp2a_reg[5][1]+(data->offset_value); THR_REG_LSB(thrd, reg); gp2a_i2c_write(data, gp2a_reg[5][0], ®); THR_REG_MSB(thrd, reg); gp2a_i2c_write(data, gp2a_reg[6][0], ®); /* calibration result */ data->cal_result = 1; old_fs = get_fs(); set_fs(KERNEL_DS); cal_filp = filp_open(CAL_PATH, O_CREAT | O_TRUNC | O_WRONLY, S_IRUGO | S_IWUSR | S_IWGRP); if (IS_ERR(cal_filp)) { pr_err("%s Can't open calibration file\n", __func__); set_fs(old_fs); err = PTR_ERR(cal_filp); goto done; } err = cal_filp->f_op->write(cal_filp, (char *)&data->offset_value, sizeof(int), &cal_filp->f_pos); if (err != sizeof(int)) { pr_err("%s Can't write the cal data to file\n", __func__); err = -EIO; } filp_close(cal_filp, current->files); done: set_fs(old_fs); return err; }
static long gp2a_opt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { int ret = 0; short data = 0; u8 thrd = 0; u8 reg; switch (cmd) { case PROX_IOC_SET_CALIBRATION: { printk(KERN_INFO "[GP2A] PROX_IOC_SET_CALIBRATION\n"); if (copy_from_user(&data, (void __user *)arg, sizeof(data))) return -EFAULT; ret = proximity_open_calibration(gp2a_opt_data); if (ret < 0 && ret != -ENOENT) { printk(KERN_INFO "[GP2A] proximity_open_offset() failed\n"); }else { thrd = gp2a_reg[3][1]+(gp2a_opt_data->offset_value); THR_REG_LSB(thrd, reg); gp2a_i2c_write(gp2a_reg[3][0], ®); THR_REG_MSB(thrd, reg); gp2a_i2c_write(gp2a_reg[4][0], ®); thrd = gp2a_reg[5][1]+(gp2a_opt_data->offset_value); THR_REG_LSB(thrd, reg); gp2a_i2c_write(gp2a_reg[5][0], ®); THR_REG_MSB(thrd, reg); gp2a_i2c_write(gp2a_reg[6][0], ®); } break; } case PROX_IOC_GET_CALIBRATION: { printk(KERN_INFO "[GP2A] PROX_IOC_GET_CALIBRATION\n"); data = gp2a_opt_data->offset_value; if (copy_to_user((void __user *)arg, &data, sizeof(data))) return -EFAULT; break; } default: printk(KERN_ERR "Unknown IOCTL command"); ret = -ENOTTY; break; } return ret; }
static ssize_t proximity_enable_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct gp2a_data *data = dev_get_drvdata(dev); int value = 0; char input; int err = 0; int16_t thrd; u8 reg; err = kstrtoint(buf, 10, &value); if (err) { pr_err("%s, kstrtoint failed.", __func__); goto done; } if (value != 0 && value != 1) goto done; pr_info("%s, %d value = %d\n", __func__, __LINE__, value); if (data->proximity_enabled && !value) { /* Prox power off */ disable_irq(data->irq); proximity_onoff(0, data); disable_irq_wake(data->irq); if (data->pdata->led_on) data->pdata->led_on(false); } if (!data->proximity_enabled && value) { /* prox power on */ if (data->pdata->led_on) data->pdata->led_on(true); usleep_range(1000, 1100); proximity_onoff(1, data); err = proximity_open_calibration(data); if (err < 0 && err != -ENOENT) pr_err("%s: proximity_open_offset() failed\n", __func__); else { thrd = gp2a_reg[3][1]+(data->offset_value); THR_REG_LSB(thrd, reg); gp2a_i2c_write(data, gp2a_reg[3][0], ®); THR_REG_MSB(thrd, reg); gp2a_i2c_write(data, gp2a_reg[4][0], ®); thrd = gp2a_reg[5][1]+(data->offset_value); THR_REG_LSB(thrd, reg); gp2a_i2c_write(data, gp2a_reg[5][0], ®); THR_REG_MSB(thrd, reg); gp2a_i2c_write(data, gp2a_reg[6][0], ®); } enable_irq_wake(data->irq); msleep(160); input = gpio_get_value_cansleep(data->pdata->p_out); if (input == 0) { input_report_abs(data->proximity_input_dev, ABS_DISTANCE, 1); input_sync(data->proximity_input_dev); } enable_irq(data->irq); } data->proximity_enabled = value; done: return count; }
static int proximity_do_calibrate(struct gp2a_data *data, bool do_calib, bool thresh_set) { struct file *cal_filp; int err; int xtalk_avg = 0; int offset_change = 0; uint16_t thrd = 0; u8 reg; mm_segment_t old_fs; if (do_calib) { if (thresh_set) { /* for proximity_thresh_store */ data->offset_value = data->threshold_high - (gp2a_reg[6][1] << 8 | gp2a_reg[5][1]); } else { /* tap offset button */ /* get offset value */ xtalk_avg = proximity_adc_read(data); offset_change = (gp2a_reg[6][1] << 8 | gp2a_reg[5][1]) - DEFAULT_HI_THR; if (xtalk_avg < offset_change) { /* do not need calibration */ data->cal_result = 0; err = 0; goto no_cal; } data->offset_value = xtalk_avg - offset_change; } /* update threshold */ thrd = (gp2a_reg[4][1] << 8 | gp2a_reg[3][1]) + (data->offset_value); THR_REG_LSB(thrd, reg); gp2a_i2c_write(data, gp2a_reg[3][0], ®); THR_REG_MSB(thrd, reg); gp2a_i2c_write(data, gp2a_reg[4][0], ®); thrd = (gp2a_reg[4][1] << 8 | gp2a_reg[5][1]) +(data->offset_value); THR_REG_LSB(thrd, reg); gp2a_i2c_write(data, gp2a_reg[5][0], ®); THR_REG_MSB(thrd, reg); gp2a_i2c_write(data, gp2a_reg[6][0], ®); /* calibration result */ if (!thresh_set) data->cal_result = 1; } else { /* tap reset button */ data->offset_value = 0; /* update threshold */ gp2a_i2c_write(data, gp2a_reg[3][0], &gp2a_reg[3][1]); gp2a_i2c_write(data, gp2a_reg[4][0], &gp2a_reg[4][1]); gp2a_i2c_write(data, gp2a_reg[5][0], &gp2a_reg[5][1]); gp2a_i2c_write(data, gp2a_reg[6][0], &gp2a_reg[6][1]); /* calibration result */ data->cal_result = 2; } old_fs = get_fs(); set_fs(KERNEL_DS); cal_filp = filp_open(data->pdata->prox_cal_path, O_CREAT | O_TRUNC | O_WRONLY, S_IRUGO | S_IWUSR | S_IWGRP); if (IS_ERR(cal_filp)) { pr_err("%s: Can't open calibration file\n", __func__); set_fs(old_fs); err = PTR_ERR(cal_filp); goto done; } err = cal_filp->f_op->write(cal_filp, (char *)&data->offset_value, sizeof(int), &cal_filp->f_pos); if (err != sizeof(int)) { pr_err("%s: Can't write the cal data to file\n", __func__); err = -EIO; } filp_close(cal_filp, current->files); done: set_fs(old_fs); no_cal: return err; }
static ssize_t gp2a_prox_enable_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct gp2a_data *data = dev_get_drvdata(dev); int value; int err = 0; err = kstrtoint(buf, 10, &value); if (err) { pr_err("%s kstrtoint failed.", __func__); goto done; } pr_info("%s %d value = %d\n", __func__, __LINE__, value); if (value != SENSOR_DISABLE && value != SENSOR_ENABLE) goto done; if (value) { if (data->prox_enabled == SENSOR_DISABLE) { uint16_t thrd = 0; u8 reg; gp2a_prox_onoff(1, data); err = gp2a_prox_open_calibration(data); if (err < 0 && err != -ENOENT) pr_err("%s gp2a_prox_open_offset() failed\n", __func__); else { thrd = gp2a_reg[3][1]+(data->offset_value); THR_REG_LSB(thrd, reg); gp2a_i2c_write(data, gp2a_reg[3][0], ®); THR_REG_MSB(thrd, reg); gp2a_i2c_write(data, gp2a_reg[4][0], ®); thrd = gp2a_reg[5][1]+(data->offset_value); THR_REG_LSB(thrd, reg); gp2a_i2c_write(data, gp2a_reg[5][0], ®); THR_REG_MSB(thrd, reg); gp2a_i2c_write(data, gp2a_reg[6][0], ®); } enable_irq_wake(data->irq); enable_irq(data->irq); input_report_abs(data->prox_input_dev, ABS_DISTANCE, 1); input_sync(data->prox_input_dev); data->prox_enabled = SENSOR_ENABLE; } else { pr_err("%s already enabled\n", __func__); } } else { if (data->prox_enabled == SENSOR_ENABLE) { disable_irq(data->irq); disable_irq_wake(data->irq); gp2a_prox_onoff(0, data); data->prox_enabled = SENSOR_DISABLE; } else { pr_err("%s already disabled\n", __func__); } } done: return count; }