/* ioctl - I/O control */ static long compass_dev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct sensor_private_data* sensor = (struct sensor_private_data *)i2c_get_clientdata(this_client); struct i2c_client *client = this_client; void __user *argp = (void __user *)arg; int result = 0; struct akm8975_platform_data compass; /* NOTE: In this function the size of "char" should be 1-byte. */ char compass_data[SENSOR_DATA_SIZE];/* for GETDATA */ char rwbuf[RWBUF_SIZE]; /* for READ/WRITE */ char mode; /* for SET_MODE*/ short value[12]; /* for SET_YPR */ short delay; /* for GET_DELAY */ int status; /* for OPEN/CLOSE_STATUS */ int ret = -1; /* Return value. */ switch (cmd) { case ECS_IOCTL_WRITE: case ECS_IOCTL_READ: if (argp == NULL) { return -EINVAL; } if (copy_from_user(&rwbuf, argp, sizeof(rwbuf))) { return -EFAULT; } break; case ECS_IOCTL_SET_MODE: if (argp == NULL) { return -EINVAL; } if (copy_from_user(&mode, argp, sizeof(mode))) { return -EFAULT; } break; case ECS_IOCTL_SET_YPR: if (argp == NULL) { return -EINVAL; } if (copy_from_user(&value, argp, sizeof(value))) { return -EFAULT; } break; default: break; } switch (cmd) { case ECS_IOCTL_WRITE: DBG("%s:ECS_IOCTL_WRITE start\n",__func__); mutex_lock(&sensor->operation_mutex); if ((rwbuf[0] < 2) || (rwbuf[0] > (RWBUF_SIZE-1))) { mutex_unlock(&sensor->operation_mutex); return -EINVAL; } ret = sensor_tx_data(client, &rwbuf[1], rwbuf[0]); if (ret < 0) { mutex_unlock(&sensor->operation_mutex); printk("%s:fait to tx data\n",__func__); return ret; } mutex_unlock(&sensor->operation_mutex); break; case ECS_IOCTL_READ: DBG("%s:ECS_IOCTL_READ start\n",__func__); mutex_lock(&sensor->operation_mutex); if ((rwbuf[0] < 1) || (rwbuf[0] > (RWBUF_SIZE-1))) { mutex_unlock(&sensor->operation_mutex); printk("%s:data is error\n",__func__); return -EINVAL; } ret = sensor_rx_data(client, &rwbuf[1], rwbuf[0]); if (ret < 0) { mutex_unlock(&sensor->operation_mutex); printk("%s:fait to rx data\n",__func__); return ret; } mutex_unlock(&sensor->operation_mutex); break; case ECS_IOCTL_SET_MODE: DBG("%s:ECS_IOCTL_SET_MODE start\n",__func__); mutex_lock(&sensor->operation_mutex); if(sensor->ops->ctrl_data != mode) { ret = compass_akm_set_mode(client, mode); if (ret < 0) { printk("%s:fait to set mode\n",__func__); mutex_unlock(&sensor->operation_mutex); return ret; } sensor->ops->ctrl_data = mode; } mutex_unlock(&sensor->operation_mutex); break; case ECS_IOCTL_GETDATA: DBG("%s:ECS_IOCTL_GETDATA start\n",__func__); mutex_lock(&sensor->data_mutex); memcpy(compass_data, sensor->sensor_data, SENSOR_DATA_SIZE); //get data from buffer mutex_unlock(&sensor->data_mutex); break; case ECS_IOCTL_SET_YPR: DBG("%s:ECS_IOCTL_SET_YPR start\n",__func__); mutex_lock(&sensor->data_mutex); compass_set_YPR(value); mutex_unlock(&sensor->data_mutex); break; case ECS_IOCTL_GET_OPEN_STATUS: status = compass_akm_get_openstatus(); DBG("%s:openstatus=%d\n",__func__,status); break; case ECS_IOCTL_GET_CLOSE_STATUS: status = compass_akm_get_closestatus(); DBG("%s:closestatus=%d\n",__func__,status); break; case ECS_IOCTL_GET_DELAY: delay = akmd_delay; break; case ECS_IOCTL_GET_PLATFORM_DATA: DBG("%s:ECS_IOCTL_GET_PLATFORM_DATA start\n",__func__); memcpy(compass.m_layout, sensor->pdata->m_layout, sizeof(sensor->pdata->m_layout)); memcpy(compass.project_name, sensor->pdata->project_name, sizeof(sensor->pdata->project_name)); ret = copy_to_user(argp, &compass, sizeof(compass)); if(ret < 0) { printk("%s:error,ret=%d\n",__FUNCTION__, ret); return ret; } break; default: return -ENOTTY; } switch (cmd) { case ECS_IOCTL_READ: if (copy_to_user(argp, &rwbuf, rwbuf[0]+1)) { return -EFAULT; } break; case ECS_IOCTL_GETDATA: if (copy_to_user(argp, &compass_data, sizeof(compass_data))) { 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 result; }
/* ioctl - I/O control */ static long compass_dev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct sensor_private_data* sensor = (struct sensor_private_data *)i2c_get_clientdata(this_client); struct i2c_client *client = this_client; void __user *argp = (void __user *)arg; int result = 0; struct akm_platform_data compass; /* NOTE: In this function the size of "char" should be 1-byte. */ char compass_data[SENSOR_DATA_SIZE]; /* for GETDATA */ char rwbuf[RWBUF_SIZE]; /* for READ/WRITE */ char mode; /* for SET_MODE*/ int value[12]; /* for SET_YPR */ int status; /* for OPEN/CLOSE_STATUS */ int ret = -1; /* Return value. */ //int8_t sensor_buf[SENSOR_DATA_SIZE]; /* for GETDATA */ //int32_t ypr_buf[YPR_DATA_SIZE]; /* for SET_YPR */ int16_t acc_buf[3]; /* for GET_ACCEL */ int64_t delay[AKM_NUM_SENSORS]; /* for GET_DELAY */ char layout; /* for GET_LAYOUT */ char outbit; /* for GET_OUTBIT */ switch (cmd) { case ECS_IOCTL_WRITE: case ECS_IOCTL_READ: if (argp == NULL) { return -EINVAL; } if (copy_from_user(&rwbuf, argp, sizeof(rwbuf))) { return -EFAULT; } break; case ECS_IOCTL_SET_MODE: if (argp == NULL) { return -EINVAL; } if (copy_from_user(&mode, argp, sizeof(mode))) { return -EFAULT; } break; case ECS_IOCTL_SET_YPR: if (argp == NULL) { return -EINVAL; } if (copy_from_user(&value, argp, sizeof(value))) { return -EFAULT; } break; case ECS_IOCTL_GETDATA: case ECS_IOCTL_GET_OPEN_STATUS: case ECS_IOCTL_GET_CLOSE_STATUS: case ECS_IOCTL_GET_DELAY: case ECS_IOCTL_GET_LAYOUT: case ECS_IOCTL_GET_OUTBIT: case ECS_IOCTL_GET_ACCEL: /* Just check buffer pointer */ if (argp == NULL) { printk("%s:invalid argument\n",__func__); return -EINVAL; } break; default: break; } switch (cmd) { case ECS_IOCTL_WRITE: DBG("%s:ECS_IOCTL_WRITE start\n",__func__); mutex_lock(&sensor->operation_mutex); if ((rwbuf[0] < 2) || (rwbuf[0] > (RWBUF_SIZE-1))) { mutex_unlock(&sensor->operation_mutex); return -EINVAL; } ret = sensor_tx_data(client, &rwbuf[1], rwbuf[0]); if (ret < 0) { mutex_unlock(&sensor->operation_mutex); printk("%s:fait to tx data\n",__func__); return ret; } mutex_unlock(&sensor->operation_mutex); break; case ECS_IOCTL_READ: DBG("%s:ECS_IOCTL_READ start\n",__func__); mutex_lock(&sensor->operation_mutex); if ((rwbuf[0] < 1) || (rwbuf[0] > (RWBUF_SIZE-1))) { mutex_unlock(&sensor->operation_mutex); printk("%s:data is error\n",__func__); return -EINVAL; } ret = sensor_rx_data(client, &rwbuf[1], rwbuf[0]); if (ret < 0) { mutex_unlock(&sensor->operation_mutex); printk("%s:fait to rx data\n",__func__); return ret; } mutex_unlock(&sensor->operation_mutex); break; case ECS_IOCTL_SET_MODE: DBG("%s:ECS_IOCTL_SET_MODE start\n",__func__); mutex_lock(&sensor->operation_mutex); if(sensor->ops->ctrl_data != mode) { ret = compass_akm_set_mode(client, mode); if (ret < 0) { printk("%s:fait to set mode\n",__func__); mutex_unlock(&sensor->operation_mutex); return ret; } sensor->ops->ctrl_data = mode; } mutex_unlock(&sensor->operation_mutex); break; case ECS_IOCTL_GETDATA: DBG("%s:ECS_IOCTL_GETDATA start\n",__func__); mutex_lock(&sensor->data_mutex); memcpy(compass_data, sensor->sensor_data, SENSOR_DATA_SIZE); //get data from buffer mutex_unlock(&sensor->data_mutex); break; case ECS_IOCTL_SET_YPR: DBG("%s:ECS_IOCTL_SET_YPR start\n",__func__); mutex_lock(&sensor->data_mutex); compass_set_YPR(value); mutex_unlock(&sensor->data_mutex); break; case ECS_IOCTL_GET_OPEN_STATUS: status = compass_akm_get_openstatus(); DBG("%s:openstatus=%d\n",__func__,status); break; case ECS_IOCTL_GET_CLOSE_STATUS: status = compass_akm_get_closestatus(); DBG("%s:closestatus=%d\n",__func__,status); break; case ECS_IOCTL_GET_DELAY: DBG("%s:ECS_IOCTL_GET_DELAY start\n",__func__); mutex_lock(&sensor->operation_mutex); delay[0] = sensor->flags.delay; delay[1] = sensor->flags.delay; delay[2] = sensor->flags.delay; mutex_unlock(&sensor->operation_mutex); break; case ECS_IOCTL_GET_PLATFORM_DATA: DBG("%s:ECS_IOCTL_GET_PLATFORM_DATA start\n",__func__); memcpy(compass.m_layout, sensor->pdata->m_layout, sizeof(sensor->pdata->m_layout)); memcpy(compass.project_name, sensor->pdata->project_name, sizeof(sensor->pdata->project_name)); ret = copy_to_user(argp, &compass, sizeof(compass)); if(ret < 0) { printk("%s:error,ret=%d\n",__FUNCTION__, ret); return ret; } break; case ECS_IOCTL_GET_LAYOUT: DBG("%s:ECS_IOCTL_GET_LAYOUT start\n",__func__); layout = 1; //sensor->pdata->layout; break; case ECS_IOCTL_GET_OUTBIT: DBG("%s:ECS_IOCTL_GET_OUTBIT start\n",__func__); outbit = 1; //sensor->pdata->outbit; break; case ECS_IOCTL_RESET: DBG("%s:ECS_IOCTL_RESET start\n",__func__); ret = compass_akm_reset(client); if (ret < 0) return ret; break; case ECS_IOCTL_GET_ACCEL: DBG("%s:ECS_IOCTL_GET_ACCEL start,no accel data\n",__func__); mutex_lock(&sensor->operation_mutex); acc_buf[0] = g_akm_rbuf[6]; acc_buf[1] = g_akm_rbuf[7]; acc_buf[2] = g_akm_rbuf[8]; mutex_unlock(&sensor->operation_mutex); break; default: return -ENOTTY; } switch (cmd) { case ECS_IOCTL_READ: if (copy_to_user(argp, &rwbuf, rwbuf[0]+1)) { return -EFAULT; } break; case ECS_IOCTL_GETDATA: if (copy_to_user(argp, &compass_data, sizeof(compass_data))) { 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; case ECS_IOCTL_GET_LAYOUT: if (copy_to_user(argp, &layout, sizeof(layout))) { printk("%s:error:%d\n",__FUNCTION__,__LINE__); return -EFAULT; } break; case ECS_IOCTL_GET_OUTBIT: if (copy_to_user(argp, &outbit, sizeof(outbit))) { printk("%s:error:%d\n",__FUNCTION__,__LINE__); return -EFAULT; } break; case ECS_IOCTL_GET_ACCEL: if (copy_to_user(argp, &acc_buf, sizeof(acc_buf))) { printk("%s:error:%d\n",__FUNCTION__,__LINE__); return -EFAULT; } break; default: break; } return result; }