示例#1
0
static void akm8975_ecs_close_done(struct akm8975_data *akm)
{
	FUNCDBG("called");
	mutex_lock(&akm->flags_lock);
	mv_flag = 1;
	mutex_unlock(&akm->flags_lock);
}
static rtems_device_driver grtm_close(rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
{
	struct grtm_priv *pDev;
	struct drvmgr_dev *dev;

	FUNCDBG();

	if ( drvmgr_get_dev(&grtm_rmap_drv_info.general, minor, &dev) ) {
		return RTEMS_INVALID_NUMBER;
	}
	pDev = (struct grtm_priv *)dev->priv;

	if ( pDev->running ){
		grtm_stop(pDev);
		pDev->running = 0;
	}
	
	/* Reset core */
	grtm_hw_reset(pDev);

	/* Clear descriptor area just for sure */
	MEMSET(pDev, pDev->bds, 0, 0x400);

	/* Mark not open */
	pDev->open = 0;

	return RTEMS_SUCCESSFUL;
}
示例#3
0
static int akm_aot_release(struct inode *inode, struct file *file)
{
	FUNCDBG("called");
	atomic_set(&open_flag, 0);
	wake_up(&open_wq);
	return 0;
}
示例#4
0
static int akmd_release(struct inode *inode, struct file *file)
{
	struct akm8975_data *akm = file->private_data;

	FUNCDBG("called");
	akm8975_ecs_close_done(akm);
	return 0;
}
示例#5
0
static irqreturn_t akm8975_interrupt(int irq, void *dev_id)
{
	struct akm8975_data *akm = dev_id;
	FUNCDBG("called");

	complete(&akm->data_ready);

	return IRQ_HANDLED;
}
示例#6
0
static int akm_aot_ioctl(struct inode *inode, struct file *file,
	      unsigned int cmd, unsigned long arg)
{
	void __user *argp = (void __user *) arg;
	short flag;
	struct akm8975_data *akm = file->private_data;

 	FUNCDBG("called");

	switch (cmd) {
	case ECS_IOCTL_APP_SET_MVFLAG:
		if (copy_from_user(&flag, argp, sizeof(flag)))
			return -EFAULT;
		if (flag < 0 || flag > 1)
			return -EINVAL;
		break;
	case ECS_IOCTL_APP_SET_DELAY:
		if (copy_from_user(&flag, argp, sizeof(flag)))
			return -EFAULT;
		break;
	default:
		break;
	}

	mutex_lock(&akm->flags_lock);
	switch (cmd) {
	case ECS_IOCTL_APP_SET_MVFLAG:
		mv_flag = flag;
		break;
	case ECS_IOCTL_APP_GET_MVFLAG:
		flag = mv_flag;
		break;
	case ECS_IOCTL_APP_SET_DELAY:
		akmd_delay = flag;
		break;
	case ECS_IOCTL_APP_GET_DELAY:
		flag = akmd_delay;
		break;
	default:
		return -ENOTTY;
	}
	mutex_unlock(&akm->flags_lock);

	switch (cmd) {
	case ECS_IOCTL_APP_GET_MVFLAG:
	case ECS_IOCTL_APP_GET_DELAY:
		if (copy_to_user(argp, &flag, sizeof(flag)))
			return -EFAULT;
		break;
	default:
		break;
	}

	return 0;
}
示例#7
0
static int akmd_open(struct inode *inode, struct file *file)
{
	int err = 0;

	FUNCDBG("called");
	err = nonseekable_open(inode, file);
	if (err)
		return err;

	file->private_data = akmd_data;
	return 0;
}
static rtems_device_driver grtm_open(
	rtems_device_major_number major, 
	rtems_device_minor_number minor, 
	void *arg)
{
	struct grtm_priv *pDev;
	struct drvmgr_dev *dev;

	FUNCDBG();

	if ( drvmgr_get_dev(&grtm_rmap_drv_info.general, minor, &dev) ) {
		DBG("Wrong minor %d\n", minor);
		return RTEMS_INVALID_NUMBER;
	}
	pDev = (struct grtm_priv *)dev->priv;
	
	/* Wait until we get semaphore */
	if ( rtems_semaphore_obtain(grtm_dev_sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT) != RTEMS_SUCCESSFUL ){
		return RTEMS_INTERNAL_ERROR;
	}

	/* Is device in use? */
	if ( pDev->open ){
		rtems_semaphore_release(grtm_dev_sem);
		return RTEMS_RESOURCE_IN_USE;
	}
	
	/* Mark device taken */
	pDev->open = 1;
	
	rtems_semaphore_release(grtm_dev_sem);
	
	DBG("grtm_open: OPENED minor %d (pDev: 0x%x)\n",pDev->minor,(unsigned int)pDev);
	
	/* Set defaults */
	pDev->config.timeout = RTEMS_NO_TIMEOUT;	/* no timeout (wait forever) */
	pDev->config.blocking = 0;			/* polling mode */
	
	pDev->running = 0;				/* not in running mode yet */

	memset(&pDev->config,0,sizeof(pDev->config));
	
	/* The core has been reset when we execute here, so it is possible
	 * to read out what HW is implemented from core.
	 */
	grtm_hw_get_implementation(pDev, &pDev->hw_avail);

	/* Get default modes */
	grtm_hw_get_default_modes(&pDev->config,&pDev->hw_avail);
	
	return RTEMS_SUCCESSFUL;
}
示例#9
0
static int __devexit akm8975_remove(struct i2c_client *client)
{
	struct akm8975_data *akm = i2c_get_clientdata(client);
	FUNCDBG("called");

	gpio_free(irq_to_gpio(client->irq));	
	free_irq(client->irq, NULL);
	input_unregister_device(akm->input_dev);
	misc_deregister(&akmd_device);
	misc_deregister(&akm_aot_device);
	akm8975_power_off(akm);
	kfree(akm);
	return 0;
}
示例#10
0
static int akm_aot_open(struct inode *inode, struct file *file)
{
	int ret = -1;

	FUNCDBG("called");
	if (atomic_cmpxchg(&open_flag, 0, 1) == 0) {
		wake_up(&open_wq);
		ret = 0;
	}

	ret = nonseekable_open(inode, file);
	if (ret)
		return ret;

	file->private_data = akmd_data;

	return ret;
}
示例#11
0
static void akm8975_ecs_report_value(struct akm8975_data *akm, int *rbuf)
{
	struct akm8975_data *data = i2c_get_clientdata(akm->this_client);

	FUNCDBG("called");

#if AK8975DRV_DATA_DBG
	pr_info("Magnetic:	 x = %d , y = %d , z = %d \n\n",
				 rbuf[0], rbuf[1], rbuf[2]);
#endif

	mutex_lock(&akm->flags_lock);

	if (mv_flag) {
		input_report_abs(data->input_dev, ABS_HAT0X, rbuf[0]);
		input_report_abs(data->input_dev, ABS_HAT0Y, rbuf[1]);
		input_report_abs(data->input_dev, ABS_BRAKE, rbuf[2]);
	}
	mutex_unlock(&akm->flags_lock);

	input_sync(data->input_dev);
}
示例#12
0
/*
 * Helper function to write to the I2C device's registers.
 */
static int akm8975_i2c_txdata(struct akm8975_data *akm, u8 reg, u8 val)
{
	struct i2c_msg msg;
	u8 w_data[2];
	int ret = 0;
 
	w_data[0] = reg;
	w_data[1] = val;

	msg.addr = akm->this_client->addr;
	msg.flags = 0;
	msg.len = 2;
	msg.buf = w_data;

	FUNCDBG("called");

	ret = i2c_transfer(akm->this_client->adapter, &msg, 1);

	if (ret < 0) {
		dev_err(&akm->this_client->dev, "Write to device fails status %x\n", ret);
 	}
 
	return ret;
}
示例#13
0
int akm8975_probe(struct i2c_client *client,
		  const struct i2c_device_id *devid)
{
	struct akm8975_data *akm;
	int err;
	FUNCDBG("called");

	if (client->dev.platform_data == NULL) {
		dev_err(&client->dev, "platform data is NULL. exiting.\n");
		err = -ENODEV;
		goto exit_platform_data_null;
	}

	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
		dev_err(&client->dev, "platform data is NULL. exiting.\n");
		err = -ENODEV;
		goto exit_check_functionality_failed;
	}

	akm = kzalloc(sizeof(struct akm8975_data), GFP_KERNEL);
	if (!akm) {
		dev_err(&client->dev,
			"failed to allocate memory for module data\n");
		err = -ENOMEM;
		goto exit_alloc_data_failed;
	}

	akm->pdata = client->dev.platform_data;

	mutex_init(&akm->flags_lock);
	init_completion(&akm->data_ready);

	i2c_set_clientdata(client, akm);

	err = akm8975_power_on(akm);
	if (err < 0)
		goto exit_power_on_failed;

	akm8975_init_client(client);
	akm->this_client = client;
	akmd_data = akm;

	akm->input_dev = input_allocate_device();
	if (!akm->input_dev) {
		err = -ENOMEM;
		dev_err(&akm->this_client->dev,
			"input device allocate failed\n");
		goto exit_input_dev_alloc_failed;
	}

	set_bit(EV_ABS, akm->input_dev->evbit);

	/* x-axis of raw magnetic vector */
	input_set_abs_params(akm->input_dev, ABS_HAT0X, -4096, 4095, 0, 0);
	/* y-axis of raw magnetic vector */
	input_set_abs_params(akm->input_dev, ABS_HAT0Y, -4096, 4095, 0, 0);
	/* z-axis of raw magnetic vector */
	input_set_abs_params(akm->input_dev, ABS_BRAKE, -4096, 4095, 0, 0);

	akm->input_dev->name = "compass";

	err = input_register_device(akm->input_dev);
	if (err) {
		pr_err("akm8975_probe: Unable to register input device: %s\n",
					 akm->input_dev->name);
		goto exit_input_register_device_failed;
	}

	err = misc_register(&akmd_device);
	if (err) {
		pr_err("akm8975_probe: akmd_device register failed\n");
		goto exit_misc_device_register_failed;
	}

	err = misc_register(&akm_aot_device);
	if (err) {
		pr_err("akm8975_probe: akm_aot_device register failed\n");
		goto exit_misc_device_register_failed;
	}

	err = device_create_file(&client->dev, &dev_attr_akm_ms1);

#ifdef CONFIG_HAS_EARLYSUSPEND
	akm->early_suspend.suspend = akm8975_early_suspend;
	akm->early_suspend.resume = akm8975_early_resume;
	register_early_suspend(&akm->early_suspend);
#endif
	return 0;

exit_misc_device_register_failed:
exit_input_register_device_failed:
	input_free_device(akm->input_dev);
exit_input_dev_alloc_failed:
	akm8975_power_off(akm);
exit_power_on_failed:
	kfree(akm);
exit_alloc_data_failed:
exit_check_functionality_failed:
exit_platform_data_null:
	return err;
}
static rtems_device_driver grtm_ioctl(rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
{
	struct grtm_priv *pDev;
	struct drvmgr_dev *dev;
	rtems_libio_ioctl_args_t *ioarg = (rtems_libio_ioctl_args_t *)arg;
	unsigned int *data = ioarg->buffer;
	int status;
	struct grtm_ioc_config *cfg;
	struct grtm_ioc_hw_status *hwregs;
	IRQ_GLOBAL_PREPARE(oldLevel);
	struct grtm_list *chain;
	struct grtm_frame *curr;
	struct grtm_ioc_hw *hwimpl;
	struct grtm_ioc_stats *stats;
	int num,ret;

	FUNCDBG();

	if ( drvmgr_get_dev(&grtm_rmap_drv_info.general, minor, &dev) ) {
		return RTEMS_INVALID_NUMBER;
	}
	pDev = (struct grtm_priv *)dev->priv;

	if (!ioarg)
		return RTEMS_INVALID_NAME;

	ioarg->ioctl_return = 0;
	switch(ioarg->command) {
		case GRTM_IOC_START:
		if ( pDev->running ) {
			return RTEMS_RESOURCE_IN_USE; /* EBUSY */
		}
		if ( (status=grtm_start(pDev)) != RTEMS_SUCCESSFUL ){
			return status;
		}
		/* Register ISR & Enable interrupt */
		drvmgr_interrupt_register(dev, 0, "grtm_rmap", grtm_interrupt, pDev);

		/* Read and write are now open... */
		break;

		case GRTM_IOC_STOP:
		if ( !pDev->running ) {
			return RTEMS_RESOURCE_IN_USE;
		}

		/* Disable interrupts */
		drvmgr_interrupt_unregister(dev, 0, grtm_interrupt, pDev);
		grtm_stop(pDev);
		pDev->running = 0;
		break;

		case GRTM_IOC_ISSTARTED:
		if ( !pDev->running ) {
			return RTEMS_RESOURCE_IN_USE;
		}
		break;

		case GRTM_IOC_SET_BLOCKING_MODE:
		if ( (unsigned int)data > GRTM_BLKMODE_BLK ) {
			return RTEMS_INVALID_NAME;
		}
		DBG("GRTM: Set blocking mode: %d\n",(unsigned int)data);
		pDev->config.blocking = (unsigned int)data;
		break;

		case GRTM_IOC_SET_TIMEOUT:
		DBG("GRTM: Timeout: %d\n",(unsigned int)data);
		pDev->config.timeout = (rtems_interval)data;
		break;

		case GRTM_IOC_SET_CONFIG:
		cfg = (struct grtm_ioc_config *)data;
		if ( !cfg ) {
			return RTEMS_INVALID_NAME;
		}
		
		if ( pDev->running ) {
			return RTEMS_RESOURCE_IN_USE;
		}

		pDev->config = *cfg;
		break;

		case GRTM_IOC_GET_STATS:
		stats = (struct grtm_ioc_stats *)data;
		if ( !stats ) {
			return RTEMS_INVALID_NAME;
		}
		memcpy(stats,&pDev->stats,sizeof(struct grtm_ioc_stats));
		break;

		case GRTM_IOC_CLR_STATS:
		memset(&pDev->stats,0,sizeof(struct grtm_ioc_stats));
		break;

		case GRTM_IOC_GET_CONFIG:
		cfg = (struct grtm_ioc_config *)data;
		if ( !cfg ) {
			return RTEMS_INVALID_NAME;
		}

		*cfg = pDev->config;
		break;

		case GRTM_IOC_GET_OCFREG:
		if ( !pDev->hw_avail.ocf ) {
			/* Hardware does not implement the OCF register */
			return RTEMS_NOT_DEFINED;
		}
		if ( !data ) {
			return RTEMS_INVALID_NAME;
		}
#warning THIS IOCTL COPY THE REMOTE ADDRESS
		*(unsigned int **)data = (unsigned int *)&pDev->regs->ocf;
		break;

		case GRTM_IOC_GET_HW_IMPL:
		hwimpl = (struct grtm_ioc_hw *)data;
		if ( !hwimpl ) {
			return RTEMS_INVALID_NAME;
		}
		*hwimpl = pDev->hw_avail;
		break;

		case GRTM_IOC_GET_HW_STATUS:
		hwregs = (struct grtm_ioc_hw_status *)data;
		if ( !hwregs ) {
			return RTEMS_INVALID_NAME;
		}
		/* We disable interrupt in order to get a snapshot of the registers */
		IRQ_GLOBAL_DISABLE(oldLevel);
#warning IMPLEMENT HWREGS HERE
		IRQ_GLOBAL_ENABLE(oldLevel);
		break;

		/* Put a chain of frames at the back of the "Ready frames" queue. This 
		 * triggers the driver to put frames from the Ready queue into unused 
		 * available descriptors. (Ready -> Scheduled)
		 */

		case GRTM_IOC_SEND:
		if ( !pDev->running ){
			return RTEMS_RESOURCE_IN_USE;
		}
		num=0;

		/* Get pointer to frame chain wished be sent */
		chain = (struct grtm_list *)ioarg->buffer;
		if ( !chain ){
			/* No new frames to send ==> just trigger hardware
			 * to send previously made ready frames to be sent.
			 */
			rtems_semaphore_obtain(pDev->handling_transmission, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
			goto trigger_transmission;
		}
		if ( !chain->tail || !chain->head ){
			return RTEMS_INVALID_NAME;
		}

		DBG("GRTM_SEND: head: 0x%x, tail: 0x%x\n",chain->head,chain->tail);

		/* Mark ready frames unsent by clearing GRTM_FLAGS_SENT of all frames */

		curr = chain->head;
		while(curr != chain->tail){
			curr->flags = curr->flags & ~(GRTM_FLAGS_SENT|GRRM_FLAGS_ERR);
			curr = curr->next;
			num++;
		}
		curr->flags = curr->flags & ~(GRTM_FLAGS_SENT|GRRM_FLAGS_ERR);
		num++;

		rtems_semaphore_obtain(pDev->handling_transmission, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
		/* 1. Put frames into ready queue 
		 *    (New Frames->READY)
		 */
		if ( pDev->ready.head ){
			/* Frames already on ready queue (no free descriptors previously) ==>
			 * Put frames at end of ready queue
			 */
			pDev->ready.tail->next = chain->head;
			pDev->ready.tail = chain->tail;
			chain->tail->next = NULL;
		}else{
			/* All frames is put into the ready queue for later processing */
			pDev->ready.head = chain->head;
			pDev->ready.tail = chain->tail;
			chain->tail->next = NULL;
		}
		pDev->ready_cnt += num;	/* Added 'num' frames to ready queue */
trigger_transmission:
		/* 2. Free used descriptors and put the sent frame into the "Sent queue"  
		 *    (SCHEDULED->SENT)
		 */
		num = grtm_free_sent(pDev);
		pDev->scheduled_cnt -= num;
		pDev->sent_cnt += num;

		/* 3. Use all available free descriptors there are frames for
		 *    in the ready queue.
		 *    (READY->SCHEDULED)
		 */
		num = grtm_schedule_ready(pDev,0);
		pDev->ready_cnt -= num;
		pDev->scheduled_cnt += num;
	
		rtems_semaphore_release(pDev->handling_transmission);
		break;

		/* Take all available sent frames from the "Sent frames" queue.
		 * If no frames has been sent, the thread may get blocked if in blocking
		 * mode. The blocking mode is not available if driver is not in running mode.
		 *
		 * Note this ioctl may return success even if the driver is not in STARTED mode.
		 * This is because in case of a error (link error of similar) and the driver switch
		 * from START to STOP mode we must still be able to get our frames back.
		 * 
		 * Note in case the driver fails to send a frame for some reason (link error),
		 * the sent flag is set to 0 indicating a failure.
		 *
		 */
		case GRTM_IOC_RECLAIM:
		/* Get pointer to were to place reaped chain */
		chain = (struct grtm_list *)ioarg->buffer;
		if ( !chain ){
			return RTEMS_INVALID_NAME;
		}

		/* Lock out interrupt handler */
		rtems_semaphore_obtain(pDev->handling_transmission, RTEMS_WAIT, RTEMS_NO_TIMEOUT);

		do {
			/* Move sent frames from descriptors to Sent queue. This makes more 
			 * descriptors (BDs) available.
			 */
			num = grtm_free_sent(pDev);
			pDev->scheduled_cnt -= num;
			pDev->sent_cnt += num;
			

			if ( pDev->running ){
				/* Fill descriptors with as many frames from the ready list 
				 * as possible.
				 */
				num = grtm_schedule_ready(pDev,0);
				pDev->ready_cnt -= num;
				pDev->scheduled_cnt += num;
			}

			/* Are there any frames on the sent queue waiting to be 
			 * reclaimed?
			 */

			if ( !pDev->sent.head ){
				/* No frames to reclaim - no frame in sent queue.
				 * Instead we block thread until frames have been sent 
				 * if in blocking mode.
				 */
				if ( pDev->running && pDev->config.blocking ){
					ret = rtems_semaphore_obtain(pDev->sem_tx,RTEMS_WAIT,pDev->config.timeout);
					if ( ret == RTEMS_TIMEOUT ) {
						/* do not lock out interrupt handler any more */
						rtems_semaphore_release(pDev->handling_transmission);
						return RTEMS_TIMEOUT;
					} else if ( ret == RTEMS_SUCCESSFUL ) {
						/* There might be frames available, go check */
						continue;
					} else {
						/* any error (driver closed, internal error etc.) */
						rtems_semaphore_release(pDev->handling_transmission);
						return RTEMS_UNSATISFIED;
					}

				}else{
					/* non-blocking mode, we quit */
					chain->head = NULL;
					chain->tail = NULL;
					/* do not lock out interrupt handler any more */
					rtems_semaphore_release(pDev->handling_transmission);
					return RTEMS_TIMEOUT;
				}
			}else{
				/* Take all sent framess from sent queue to userspace queue */
				chain->head = pDev->sent.head;
				chain->tail = pDev->sent.tail;
				chain->tail->next = NULL; /* Just for sure */

				/* Mark no Sent */
				grtm_list_clr(&pDev->sent);

				DBG("TX_RECLAIM: head: 0x%x, tail: 0x%x\n",chain->head,chain->tail);
				break;
			}

		}while(1);
		
		/* do not lock out interrupt handler any more */
		rtems_semaphore_release(pDev->handling_transmission);
		break;

		default:
		return RTEMS_NOT_DEFINED;
	}
	return RTEMS_SUCCESSFUL;
}
static rtems_device_driver grtm_write(rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
{
	FUNCDBG();
	return RTEMS_NOT_IMPLEMENTED;
}
示例#16
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;
}
示例#17
0
static void __exit akm8975_exit(void)
{
	FUNCDBG("AK8975 compass driver: exit\n");
	i2c_del_driver(&akm8975_driver);
}
示例#18
0
static int __init akm8975_init(void)
{
	pr_info("AK8975 compass driver: init\n");
	FUNCDBG("AK8975 compass driver: init\n");
	return i2c_add_driver(&akm8975_driver);
}