Beispiel #1
0
static ssize_t akmd_read(struct file *file, char __user *buf,
					size_t count, loff_t *pos)
{
	struct akm8975_data *akm = container_of(file->private_data,
			struct akm8975_data, akmd_device);
	short x = 0, y = 0, z = 0;
#if defined (CONFIG_EUR_MODEL_GT_I9210)
	short tmp = 0;
#endif
	int ret;
	u8 data[8];

	mutex_lock(&akm->lock);
	ret = akm8975_ecs_set_mode(akm, AK8975_MODE_SNG_MEASURE);
	if (ret) {
		mutex_unlock(&akm->lock);
		goto done;
	}
	ret = akm8975_wait_for_data_ready(akm);
	if (ret) {
		mutex_unlock(&akm->lock);
		goto done;
	}
	ret = i2c_smbus_read_i2c_block_data(akm->this_client, AK8975_REG_ST1,
						sizeof(data), data);
	mutex_unlock(&akm->lock);

	if (ret != sizeof(data)) {
		pr_err("%s: failed to read %d bytes of mag data\n",
		       __func__, sizeof(data));
		goto done;
	}

	if (data[0] & 0x01) {
		x = (data[2] << 8) + data[1];
		y = (data[4] << 8) + data[3];
		z = (data[6] << 8) + data[5];
#if defined (CONFIG_EUR_MODEL_GT_I9210)
		if (get_hw_rev() >= 6 )
		{
			tmp = x;
			x = y;
			y = tmp;
		}
#endif
	} else
		pr_err("%s: invalid raw data(st1 = %d)\n",
					__func__, data[0] & 0x01);

done:
	return sprintf(buf, "%d,%d,%d\n", x, y, z);
}
Beispiel #2
0
/* sysfs for logging Power line noise */
static ssize_t akm8975_rawdata_show(struct device *dev, struct device_attribute *attr, char *buf)
{
	struct akm8975_data *akm = dev_get_drvdata(dev);
	short x = 0, y = 0, z = 0;
	int ret;
	u8 data[8];

	mutex_lock(&akm->lock);
	ret = akm8975_ecs_set_mode(akm, AK8975_MODE_SNG_MEASURE);
	if (ret) {
		mutex_unlock(&akm->lock);
		goto done;
	}
	ret = akm8975_wait_for_data_ready(akm);
	if (ret) {
		mutex_unlock(&akm->lock);
		goto done;
	}
	ret = i2c_smbus_read_i2c_block_data(akm->this_client, AK8975_REG_ST1,
						sizeof(data), data);
	mutex_unlock(&akm->lock);

	if (ret != sizeof(data)) {
		pr_err("%s: failed to read %d bytes of mag data\n",
		       __func__, sizeof(data));
		goto done;
	}

	if (data[0] & 0x01) {
		x = (data[2] << 8) + data[1];
		y = (data[4] << 8) + data[3];
		z = (data[6] << 8) + data[5];
	} else
		pr_err("%s: invalid raw data(st1 = %d)\n",
					__func__, data[0] & 0x01);

done:
	return sprintf(buf, "%d,%d,%d\n", x, y, z);
}
Beispiel #3
0
static long akmd_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
	void __user *argp = (void __user *)arg;
	struct akm8975_data *akm = container_of(file->private_data,
			struct akm8975_data, akmd_device);
	int ret;
	union {
		char raw[RWBUF_SIZE];
		int status;
		char mode;
		u8 data[8];
	} rwbuf;
	
	ret = akmd_copy_in(cmd, argp, rwbuf.raw, sizeof(rwbuf));
	if (ret)
		return ret;

	switch (cmd) {
	case ECS_IOCTL_WRITE:
		if ((rwbuf.raw[0] < 2) || (rwbuf.raw[0] > (RWBUF_SIZE - 1)))
			return -EINVAL;
		if (copy_from_user(&rwbuf.raw[2], argp+2, rwbuf.raw[0]-1))
			return -EFAULT;

		ret = i2c_smbus_write_i2c_block_data(akm->this_client,
						     rwbuf.raw[1],
						     rwbuf.raw[0] - 1,
						     &rwbuf.raw[2]);
		break;
	case ECS_IOCTL_READ:
		if ((rwbuf.raw[0] < 1) || (rwbuf.raw[0] > (RWBUF_SIZE - 1)))
			return -EINVAL;

		ret = i2c_smbus_read_i2c_block_data(akm->this_client,
						    rwbuf.raw[1],
						    rwbuf.raw[0],
						    &rwbuf.raw[1]);
		if (ret < 0)
			return ret;
		if (copy_to_user(argp+1, rwbuf.raw+1, rwbuf.raw[0]))
			return -EFAULT;
		return 0;
	case ECS_IOCTL_SET_MODE:
		mutex_lock(&akm->lock);
		ret = akm8975_ecs_set_mode(akm, rwbuf.mode);
		mutex_unlock(&akm->lock);
		break;
	case ECS_IOCTL_GETDATA:
		mutex_lock(&akm->lock);
		ret = akm8975_wait_for_data_ready(akm);
		if (ret) {
			mutex_unlock(&akm->lock);
			return ret;
		}
		ret = i2c_smbus_read_i2c_block_data(akm->this_client,
						    AK8975_REG_ST1,
						    sizeof(rwbuf.data),
						    rwbuf.data);
		mutex_unlock(&akm->lock);
		if (ret != sizeof(rwbuf.data)) {
			pr_err("%s : failed to read %d bytes of mag data\n",
			       __func__, sizeof(rwbuf.data));
			return -EIO;
		}
		break;
	default:
		return -ENOTTY;
	}

	if (ret < 0)
		return ret;

	return akmd_copy_out(cmd, argp, rwbuf.raw, sizeof(rwbuf));
}
Beispiel #4
0
static int akmd_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
		      unsigned long arg)
{
	void __user *argp = (void __user *) arg;

	char rwbuf[16];
	char databuf[RBUFF_SIZE];
	int ret = -1;
	int status;
	int value[3];
	short delay;
	short mode;
	struct akm8975_data *akm = file->private_data;
	
	FUNCDBG("called");

	switch (cmd) {
	case ECS_IOCTL_READ:
	case ECS_IOCTL_WRITE:
		if (copy_from_user(&rwbuf, argp, sizeof(rwbuf)))
			return -EFAULT;
		break;
	case ECS_IOCTL_SET_MODE:
		if (copy_from_user(&mode, argp, sizeof(mode)))
			return -EFAULT;
		break;
	case ECS_IOCTL_SET_YPR:
		if (copy_from_user(&value, argp, sizeof(value)))
			return -EFAULT;
		break;

	default:
		break;
	}

	switch (cmd) {
	case ECS_IOCTL_READ:
		if ((rwbuf[0] > AK8975_FUSE_ASAZ) || (rwbuf[1] < 1) ||
			(rwbuf[1] > 3)) {
			pr_err("AKM8975 IOCTL_READ invalid argument: %d, %d\n", 
				(int)rwbuf[0], (int)rwbuf[1]);
			return -EINVAL;
		}

		ret = akm8975_i2c_rxdata(akm, rwbuf[0], rwbuf[1], &rwbuf[2]);
		if (ret < 0)
			return ret;
		break;

	case ECS_IOCTL_WRITE:
		if (rwbuf[0] < 2)
			return -EINVAL;

		ret = akm8975_i2c_txdata(akm, rwbuf[0], rwbuf[1]);
		if (ret < 0)
			return ret;
		break;

	case ECS_IOCTL_SET_MODE:
		ret = akm8975_ecs_set_mode(akm, (char) mode);
		if (ret < 0)
			return ret;

		if (mode == AK8975_MODE_SNG_MEASURE) {
			/* wait for data to become ready */
			ret = wait_for_completion_interruptible_timeout(&akm->data_ready, 
						msecs_to_jiffies(AK8975_MAX_CONVERSION_TIMEOUT));
			if (ret < 0) {
				pr_err("AKM8975 conversion timeout happened\n");
				return -EINVAL;
			}
		}
		break;

	case ECS_IOCTL_GETDATA:
		ret = akm8975_ecs_get_data(akm, RBUFF_SIZE, databuf);
		if (ret < 0)
			return ret;

	case ECS_IOCTL_SET_YPR:
		akm8975_ecs_report_value(akm, value);
		break;

	case ECS_IOCTL_GET_OPEN_STATUS:
		wait_event_interruptible(open_wq,
					 (atomic_read(&open_flag) != 0));
		status = atomic_read(&open_flag);
		break;
	case ECS_IOCTL_GET_CLOSE_STATUS:
		wait_event_interruptible(open_wq,
					 (atomic_read(&open_flag) == 0));
		status = atomic_read(&open_flag);
		break;

	case ECS_IOCTL_GET_DELAY:
		delay = akmd_delay;
		break;

	default:
		FUNCDBG("Unknown cmd\n");
		return -ENOTTY;
	}

	switch (cmd) {
	case ECS_IOCTL_READ:
		if (copy_to_user(argp, &rwbuf[2], rwbuf[1]))
			return -EFAULT;
		break;
	case ECS_IOCTL_GETDATA:
		if (copy_to_user(argp, &databuf, RBUFF_SIZE))
			return -EFAULT;
		break;
	case ECS_IOCTL_GET_OPEN_STATUS:
	case ECS_IOCTL_GET_CLOSE_STATUS:
		if (copy_to_user(argp, &status, sizeof(status)))
			return -EFAULT;
		break;
	case ECS_IOCTL_GET_DELAY:
		if (copy_to_user(argp, &delay, sizeof(delay)))
			return -EFAULT;
		break;
	default:
		break;
	}

	return 0;
}