static int sfh7743_misc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { void __user *argp = (void __user *)arg; u8 enable; struct sfh7743_data *sfh = file->private_data; switch (cmd) { case SFH7743_IOCTL_SET_ENABLE: if (copy_from_user(&enable, argp, 1)) return -EFAULT; if (enable > 1) return -EINVAL; if (enable != 0) sfh7743_enable(sfh); else sfh7743_disable(sfh); break; case SFH7743_IOCTL_GET_ENABLE: enable = atomic_read(&sfh->enabled); if (copy_to_user(argp, &enable, 1)) return -EINVAL; break; default: return -EINVAL; } return 0; }
static int sfh7743_resume(struct platform_device *pdev) { struct sfh7743_data *sfh = platform_get_drvdata(pdev); if (sfh->on_before_suspend) return sfh7743_enable(sfh); return 0; }
static int sfh7743_fops_write (struct file *filp, const char __user *buf, size_t count, loff_t *f_pos) { if ( count > 3 ) return -EINVAL; if (copy_from_user(writeBuf, buf, count)) return -EINVAL; /* If disable requested */ if ( !(strncmp(writeBuf, "0", 1 ) ) ) { sfh7743_enable(false); } /* If enable requested */ else { sfh7743_enable(true); } return E_OK; } /* End sfh7743_fops_write */
/*! * @brief Logs data * * This function is called to set the current mode (Enabled/Disabled) of * of the proximity device * */ static ssize_t sfh7743_set_mode(struct device *dev, struct device_attribute *att, const char *buf, size_t count) { /* If disable requested */ if ( !(strncmp(buf, "0", 1 ) ) ) { sfh7743_enable(false); } /* If enable requested */ else { #ifdef CONFIG_MACH_MOT #if 0 if (machine_is_motus() && (mot_hw_rev < 0x2F)) { sfh7743_log(KERN_ERR "PROXIMITY SENSOR NOT" "ENABLED FOR MOTUS P2 BOARDS (< 2F)\n"); return 0; } #endif #endif sfh7743_enable(true); } return 0; }
static int sfh7743_probe(struct platform_device *pdev) { /* Initialize error condition to no-error */ int error = E_OK; sfh7743_log(KERN_INFO "sfh7743_probe: Enter....\n"); /* Initialize input device */ sfh7743_info.idev = NULL; /* Initialize interrupt values */ sfh7743_info.gpio_intr = -1; sfh7743_info.gpio_en = -1; #ifndef CONFIG_MACH_MOT sfh7743_info.vreg_name = NULL; sfh7743_info.vreg_en = NULL; #endif sfh7743_info.irq = -1; sfh7743_info.state = 0; /* Register IR prox device */ error = sfh7743_register(); if (error == E_OK) { /* Initialize the work queue */ INIT_WORK (&sfh7743_info.wq, sfh7743_irq_bottom_half); /* GPIOs and IRQ config */ error = sfh7743_config_int(pdev); if (error == E_OK) { /* Enable proximity sensor */ sfh7743_enable(false); } else { /* Unregistered what was previously registered */ sfh7743_unregister(); return error; } } /* Report init status to log */ if (error == E_OK) { #ifdef CONFIG_MACH_MOT sfh7743_log(KERN_INFO "sfh7743_probe: initialized gpio_int[%d]" "irq[%d] gpio_en[%d]\n", sfh7743_info.gpio_intr, sfh7743_info.irq, sfh7743_info.gpio_en); #else sfh7743_log(KERN_INFO "sfh7743_probe: initialized gpio_int[%d]" "irq[%d] gpio_en[%d] vreg_en[%s]\n", sfh7743_info.gpio_intr, sfh7743_info.irq, sfh7743_info.gpio_en, sfh7743_info.vreg_name); #endif } else { sfh7743_log(KERN_ERR "sfh7743_probe: initialization failed: %d\n", error); } if ( (error = sysfs_create_group(&(pdev->dev.kobj), &sfh7743_attr_group) )) { sfh7743_log(KERN_INFO "sfh7743_probe: Exit....\n"); } return error; }
/** \fn static int sfh7743_config_int (void) * \brief Configure sfh7743 sensor interrupt GPIOs and routine * \return E_OK if successful, -1 if any failure occurred */ static int sfh7743_config_int (struct platform_device *pdev) { struct sfh7743_platform_data *pdata = pdev->dev.platform_data; /* Initialize error condition to no-error */ int error = E_OK; if ( !pdata ) return -EBUSY; /* Read interrupt numbers from hardware config */ sfh7743_info.gpio_intr = pdata->gpio_intr; sfh7743_info.gpio_en = pdata->gpio_en; #ifndef CONFIG_MACH_MOT sfh7743_info.vreg_name = pdata->vreg_en; #endif /* Ensure proper pin numbers are returned */ #ifdef CONFIG_MACH_MOT if ((sfh7743_info.gpio_intr < 0) || (sfh7743_info.gpio_en < 0)) { sfh7743_log(KERN_ERR "sfh7743_config_int: get_gpio failure\n"); #else if ((sfh7743_info.gpio_intr<0) || ((sfh7743_info.gpio_en<0)&&(pdata->vreg_en==NULL))) { sfh7743_log(KERN_ERR "sfh7743_config_int: get_gpio/vreg_get failure\n"); #endif goto sfh7743_error; } /* Configure change interrupt */ if (gpio_request(sfh7743_info.gpio_intr, SFH7743_MODULE_NAME) == E_OK) { /* Set gpio to input direction to allow irq signals */ if (gpio_direction_input(sfh7743_info.gpio_intr) != E_OK) { sfh7743_log(KERN_ERR "sfh7743_config_int: gpio_int direction error\n"); goto sfh7743_error_gpio_int_requested; } } else { sfh7743_log(KERN_ERR "sfh7743_config_int: gpio_request error\n"); goto sfh7743_error; } /* Record irq value to structure. A negative value indicates an error */ sfh7743_info.irq = gpio_to_irq(sfh7743_info.gpio_intr); /* Attempt setup of interrupt request handler if proper irq returned above. * If either fails, indicate and exit */ if ( (sfh7743_info.irq<0) || (request_irq(sfh7743_info.irq, sfh7743_irq_handler,IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING|IRQF_SHARED, SFH7743_MODULE_NAME, &sfh7743_info) != E_OK) ) { sfh7743_log(KERN_ERR "sfh7743_config_int: irq request error\n"); goto sfh7743_error_gpio_int_requested; } #ifdef CONFIG_MACH_MOT set_irq_wake(sfh7743_info.irq, 1); #else if (sfh7743_info.gpio_en < 0) { sfh7743_info.vreg_en = vreg_get(0, sfh7743_info.vreg_name); goto sfh7743_no_cleanup; } #endif /* Configure enable interrupt */ if (gpio_request(sfh7743_info.gpio_en, SFH7743_MODULE_NAME) == E_OK) { /* Set gpio to output direction to allow irq signals */ if (gpio_direction_output(sfh7743_info.gpio_en,0) == E_OK) { /* This is a "total success" condition, so the function is exited */ goto sfh7743_no_cleanup; } else { sfh7743_log(KERN_ERR "sfh7743_config_int: direction error\n"); goto sfh7743_error_gpio_en_requested; } } else { sfh7743_log(KERN_ERR "sfh7743_config_int: gpio_request error\n"); goto sfh7743_error_irq_requested; } /* Naturally flowing into this destruction is impossible */ sfh7743_error_gpio_en_requested: gpio_free (sfh7743_info.gpio_en); sfh7743_error_irq_requested: #ifdef CONFIG_MACH_MOT set_irq_wake(sfh7743_info.irq, 0); #endif free_irq(sfh7743_info.irq, 0); sfh7743_error_gpio_int_requested: gpio_free(sfh7743_info.gpio_intr); sfh7743_error: sfh7743_info.gpio_intr = -1; sfh7743_info.gpio_en = -1; #ifndef CONFIG_MACH_MOT sfh7743_info.vreg_name = NULL; sfh7743_info.vreg_en = NULL; #endif sfh7743_info.irq = -1; error = -1; sfh7743_no_cleanup: return error; } /** \fn void __exit sfh7743_exit (void) * \brief sfh7743 driver cleanup function, called when the driver is destroyed * \return void */ void __exit sfh7743_exit (void) { /* Disable proximity sensor */ sfh7743_enable(false); /* Free irq */ if (sfh7743_info.irq != -1) { #ifdef CONFIG_MACH_MOT set_irq_wake(sfh7743_info.irq, 0); #endif free_irq(sfh7743_info.irq, 0); } /* Free GPIOs */ if (sfh7743_info.gpio_intr != -1) { gpio_free(sfh7743_info.gpio_intr); } if (sfh7743_info.gpio_en != -1) { gpio_free(sfh7743_info.gpio_en); } /* prox_ir unregister */ if (sfh7743_info.idev) { sfh7743_unregister(); } }
/** \fn static int sfh7743_fops_ioctl (struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) * \brief System response point to fop ioctl * \return Error code where zero indicates no-error, or value depending on ioctl call */ static int sfh7743_fops_ioctl (struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { /** \var error * \brief Return error code, initialized to no error */ int error = E_OK; /* Temporary store */ long tmp_var; uint8_t enable; void __user *argp = (void __user *)arg; /* Process the parameter command */ switch (cmd) { case SFH7743_IOCTL_GET_PRESENCE: /* Get/return distance */ /* if devise is disable, return 0 */ if ( sfh7743_info.state ) { sfh7743_log(KERN_INFO "sfh7743_fops_ioctl: device is enabled\n"); sfh7743_get_distance(&tmp_var); sfh7743_log(KERN_INFO "sfh7743_fops_ioctl: Distance value: %d\n",tmp_var); } else { sfh7743_log(KERN_INFO "sfh7743_fops_ioctl: device is disabled\n"); tmp_var = 0; } error = tmp_var; /* error = copy_to_user(&arg, &tmp_var,sizeof(tmp_var)); if ( error != 0 ) { sfh7743_log(KERN_INFO "sfh7743_fops_ioctl: Could not copy %d bytes to user space.\n",error); } */ break; case SFH7743_IOCTL_PUSH_PRESENCE: /* Get/push-to-input distance */ sfh7743_get_distance(&tmp_var); sfh7743_post_data(tmp_var); break; case SFH7743_IOCTL_SET_ENABLE: if (copy_from_user(&enable, argp, 1)) return -EFAULT; if (enable > 1) return -EINVAL; if (enable != 0) sfh7743_enable(true); else sfh7743_enable(false); break; case SFH7743_IOCTL_ENABLE: /* Disable proximity sensor */ sfh7743_enable(true); break; case SFH7743_IOCTL_DISABLE: /* Disable proximity sensor */ sfh7743_enable(false); break; case SFH7743_IOCTL_GET_ENABLE: #ifdef CONFIG_MACH_MOT enable = gpio_get_value(sfh7743_info.gpio_en); if (copy_to_user(argp, &enable, 1)) return -EINVAL; #else error = sfh7743_info.state; #endif break; case SFH7743_IOCTL_GET_STATUS: error = sfh7743_info.state; break; default: sfh7743_log(KERN_ERR "sfh7743: invalid ioctl cmd supplied\n"); /* Indicate inappropriate ioctl for device */ error = -ENOTTY; break; } /* End switch (cmd) */ return error; } /* End sfh7743_fops_ioctl */
int sfh7743_input_open(struct input_dev *input) { struct sfh7743_data *sfh = input_get_drvdata(input); return sfh7743_enable(sfh); }