/** * call in the main loop * when running under debugger it enable doing direct vl6180x reg access * After breaking at entrance * change the the local index/data and cmd variable to do what needed * reg_cmd -1 wr byte -2wr word -3 wr dword * reg_cmd 1 rd byte 2 rd word 3 rd dword * step to last statement before return and read variable to get rd result exit */ void debug_stuff(void) { int reg_cmd = 0; static uint32_t reg_data; static uint16_t reg_index; if (reg_cmd) { switch (reg_cmd) { case -1: VL6180x_WrByte(theVL6180xDev, reg_index, reg_data); debug("Wr B 0x%X = %d", reg_index, (int)reg_data); break; case -2: VL6180x_WrWord(theVL6180xDev, reg_index, reg_data); debug("Wr W 0x%X = %d", reg_index, (int) reg_data); break; case -3: VL6180x_WrDWord(theVL6180xDev, reg_index, reg_data); debug("WrDW 0x%X = %d", reg_index, (int)reg_data); break; case 1: reg_data = 0; VL6180x_RdByte(theVL6180xDev, reg_index, (uint8_t*) ®_data); debug("RD B 0x%X = %d", reg_index, (int)reg_data); break; case 2: reg_data = 0; VL6180x_RdWord(theVL6180xDev, reg_index, (uint16_t*) ®_data); debug("RD W 0x%X = %d", reg_index, (int)reg_data); break; case 3: VL6180x_RdDWord(theVL6180xDev, reg_index, ®_data); debug("RD DW 0x%X = %d", reg_index, (int)reg_data); break; default: debug("Invalid command %d", reg_cmd); /* nothing to do*/ ; } } }
/* * misc device file operation functions */ static int stmvl6180_ioctl_handler(struct file *file, unsigned int cmd, unsigned long arg, void __user *p) { int rc = 0; unsigned int xtalkint = 0; int8_t offsetint = 0; struct stmvl6180_data *data = gp_vl6180_data; struct stmvl6180_register reg; if (!data) return -EINVAL; vl6180_dbgmsg("Enter enable_ps_sensor:%d\n", data->enable_ps_sensor); switch (cmd) { /* enable */ case VL6180_IOCTL_INIT: pr_err("%s: VL6180_IOCTL_INIT\n", __func__); /* turn on tof sensor only if it's not enabled by other client */ if (data->enable_ps_sensor == 0) { /* to start */ stmvl6180_start(data, 3, NORMAL_MODE); } else rc = -EINVAL; break; /* crosstalk calibration */ case VL6180_IOCTL_XTALKCALB: vl6180_dbgmsg("VL6180_IOCTL_XTALKCALB\n"); /* turn on tof sensor only if it's not enabled by other client */ if (data->enable_ps_sensor == 0) { /* to start */ stmvl6180_start(data, 3, XTALKCALIB_MODE); } else rc = -EINVAL; break; /* set up Xtalk value */ case VL6180_IOCTL_SETXTALK: vl6180_dbgmsg("VL6180_IOCTL_SETXTALK\n"); if (copy_from_user(&xtalkint, (unsigned int *)p, sizeof(unsigned int))) { vl6180_errmsg("%d, fail\n", __LINE__); return -EFAULT; } vl6180_dbgmsg("SETXTALK as 0x%x\n", xtalkint); #ifdef CALIBRATION_FILE xtalk_calib = xtalkint; stmvl6180_write_xtalk_calibration_file(); #endif VL6180x_SetXTalkCompensationRate(vl6180x_dev, xtalkint); break; /* offset calibration */ case VL6180_IOCTL_OFFCALB: vl6180_dbgmsg("VL6180_IOCTL_OFFCALB\n"); if (data->enable_ps_sensor == 0) { /* to start */ stmvl6180_start(data, 3, OFFSETCALIB_MODE); } else rc = -EINVAL; break; /* set up offset value */ case VL6180_IOCTL_SETOFFSET: vl6180_dbgmsg("VL6180_IOCTL_SETOFFSET\n"); if (copy_from_user(&offsetint, (int8_t *)p, sizeof(int8_t))) { vl6180_errmsg("%d, fail\n", __LINE__); return -EFAULT; } vl6180_dbgmsg("SETOFFSET as %d\n", offsetint); #ifdef CALIBRATION_FILE offset_calib = offsetint; stmvl6180_write_offset_calibration_file(); #endif VL6180x_SetOffsetCalibrationData(vl6180x_dev, offsetint); break; /* disable */ case VL6180_IOCTL_STOP: vl6180_errmsg("VL6180_IOCTL_STOP\n"); /* turn off tof sensor only if it's enabled by other client */ if (data->enable_ps_sensor == 1) { data->enable_ps_sensor = 0; /* to stop */ stmvl6180_stop(data); } break; /* Get all range data */ case VL6180_IOCTL_GETDATAS: vl6180_dbgmsg("VL6180_IOCTL_GETDATAS\n"); if (copy_to_user((VL6180x_RangeData_t *)p, &(data->rangeData), sizeof(VL6180x_RangeData_t))) { vl6180_errmsg("%d, fail\n", __LINE__); return -EFAULT; } break; case VL6180_IOCTL_REGISTER: vl6180_dbgmsg("VL6180_IOCTL_REGISTER\n"); if (copy_from_user(®, (struct stmvl6180_register *)p, sizeof(struct stmvl6180_register))) { vl6180_errmsg("%d, fail\n", __LINE__); return -EFAULT; } reg.status = 0; switch (reg.reg_bytes) { case(4): if (reg.is_read) reg.status = VL6180x_RdDWord(vl6180x_dev, (uint16_t)reg.reg_index, ®.reg_data); else reg.status = VL6180x_WrDWord(vl6180x_dev, (uint16_t)reg.reg_index, reg.reg_data); break; case(2): if (reg.is_read) reg.status = VL6180x_RdWord(vl6180x_dev, (uint16_t)reg.reg_index, (uint16_t *)®.reg_data); else reg.status = VL6180x_WrWord(vl6180x_dev, (uint16_t)reg.reg_index, (uint16_t)reg.reg_data); break; case(1): if (reg.is_read) reg.status = VL6180x_RdByte(vl6180x_dev, (uint16_t)reg.reg_index, (uint8_t *)®.reg_data); else reg.status = VL6180x_WrByte(vl6180x_dev, (uint16_t)reg.reg_index, (uint8_t)reg.reg_data); break; default: reg.status = -1; } if (copy_to_user((struct stmvl6180_register *)p, ®, sizeof(struct stmvl6180_register))) { vl6180_errmsg("%d, fail\n", __LINE__); return -EFAULT; } break; default: rc = -EINVAL; break; } return rc; }
static void stmvl6180_read_calibration_file(void) { struct file *f; char buf[8]; mm_segment_t fs; int i, is_sign = 0; if(gp_vl6180_data->offset_buf.file_opened == true) { vl6180_dbgmsg("offset_calib as %d\n", gp_vl6180_data->offset_buf.value); VL6180x_SetOffsetCalibrationData(vl6180x_dev, gp_vl6180_data->offset_buf.value); } else { f = filp_open("/persist/calibration/offset", O_RDONLY, 0); if (f != NULL && !IS_ERR(f) && f->f_dentry != NULL) { fs = get_fs(); set_fs(get_ds()); /* init the buffer with 0 */ for (i = 0; i < 8; i++) buf[i] = 0; f->f_op->read(f, buf, 8, &f->f_pos); set_fs(fs); vl6180_dbgmsg("offset as:%s, buf[0]:%c\n", buf, buf[0]); offset_calib = 0; for (i = 0; i < 8; i++) { if (i == 0 && buf[0] == '-') is_sign = 1; else if (buf[i] >= '0' && buf[i] <= '9') offset_calib = offset_calib * 10 + (buf[i] - '0'); else break; } if (is_sign == 1) offset_calib = -1 * offset_calib; vl6180_dbgmsg("file open offset_calib as %d\n", offset_calib); gp_vl6180_data->offset_buf.file_opened = true; gp_vl6180_data->offset_buf.value = offset_calib; VL6180x_SetOffsetCalibrationData(vl6180x_dev, offset_calib); filp_close(f, NULL); } else { gp_vl6180_data->offset_buf.file_opened = true; gp_vl6180_data->offset_buf.value = 0; vl6180_errmsg("no offset calibration file exist!\n"); } } is_sign = 0; if(gp_vl6180_data->xtalk_buf.file_opened == true) { vl6180_dbgmsg("xtalk_calib as %d\n", gp_vl6180_data->xtalk_buf.value); /* set up threshold ignore */ if ((gp_vl6180_data->xtalk_buf.value+13) < 64 ) VL6180x_WrWord(vl6180x_dev, SYSRANGE_RANGE_IGNORE_THRESHOLD, 64); /* 0.5Mcps */ else VL6180x_WrWord(vl6180x_dev, SYSRANGE_RANGE_IGNORE_THRESHOLD, (gp_vl6180_data->xtalk_buf.value+13)); /* +0.1Mcps */ VL6180x_WrByte(vl6180x_dev, SYSRANGE_RANGE_IGNORE_VALID_HEIGHT, 100); VL6180x_UpdateByte(vl6180x_dev, SYSRANGE_RANGE_CHECK_ENABLES, ~RANGE_CHECK_RANGE_ENABLE_MASK, RANGE_CHECK_RANGE_ENABLE_MASK); /* setup xtalk compensation rate */ VL6180x_SetXTalkCompensationRate(vl6180x_dev, gp_vl6180_data->xtalk_buf.value); } else { f = filp_open("/persist/calibration/xtalk", O_RDONLY, 0); if (f != NULL && !IS_ERR(f) && f->f_dentry != NULL) { fs = get_fs(); set_fs(get_ds()); /* init the buffer with 0 */ for (i = 0; i < 8; i++) buf[i] = 0; f->f_op->read(f, buf, 8, &f->f_pos); set_fs(fs); vl6180_dbgmsg("xtalk as:%s, buf[0]:%c\n", buf, buf[0]); xtalk_calib = 0; for (i = 0; i < 8; i++) { if (i == 0 && buf[0] == '-') is_sign = 1; else if (buf[i] >= '0' && buf[i] <= '9') xtalk_calib = xtalk_calib * 10 + (buf[i] - '0'); else break; } if (is_sign == 1) xtalk_calib = -1 * xtalk_calib; vl6180_dbgmsg("file open xtalk_calib as %d\n", xtalk_calib); gp_vl6180_data->xtalk_buf.file_opened = true; gp_vl6180_data->xtalk_buf.value = xtalk_calib; /* set up threshold ignore */ if ((xtalk_calib+13) < 64 ) VL6180x_WrWord(vl6180x_dev, SYSRANGE_RANGE_IGNORE_THRESHOLD, 64); /* 0.5Mcps */ else VL6180x_WrWord(vl6180x_dev, SYSRANGE_RANGE_IGNORE_THRESHOLD, (xtalk_calib+13)); /* +0.1Mcps */ VL6180x_WrByte(vl6180x_dev, SYSRANGE_RANGE_IGNORE_VALID_HEIGHT, 100); VL6180x_UpdateByte(vl6180x_dev, SYSRANGE_RANGE_CHECK_ENABLES, ~RANGE_CHECK_RANGE_ENABLE_MASK, RANGE_CHECK_RANGE_ENABLE_MASK); /* setup xtalk compensation rate */ VL6180x_SetXTalkCompensationRate(vl6180x_dev, xtalk_calib); filp_close(f, NULL); } else { gp_vl6180_data->xtalk_buf.file_opened = true; gp_vl6180_data->xtalk_buf.value = XTALK_CALIBRATION_DEFAULT; vl6180_errmsg("no xtalk calibration file exist!\n"); } } return; }