I.MX6 driver goto 使用

时间:2025-03-28 11:04:19
/**************************************************************************
* I.MX6 driver goto 使用
* 说明:
* 在绝大多数地方,我们都被告诉尽可能不要用goto,甚至都没学过goto,但
* 这种语法却在内核驱动中普遍使用。
*
* 2016-4-13 深圳 南山平山村 曾剑锋
*************************************************************************/ #include <linux/module.h>
#include <linux/fs.h>
#include <linux/gpio.h>
#include <linux/miscdevice.h>
#include <linux/delay.h> #define SABRESD_VO_PIN IMX_GPIO_NR(1, 4)
#define SABRESD_AMPE_PIN IMX_GPIO_NR(1, 5)
#define SABRESD_SD_PIN IMX_GPIO_NR(1, 19)
#define SABRESD_DT_PIN IMX_GPIO_NR(3, 20) #define SPK_HEIGHT 66
#define SPK_LOW 67
#define AMP_HEIGHT 68
#define AMP_LOW 69
#define SD_HEIGHT 70
#define SD_LOW 71
#define DETECT 72 #define GPIO_CTRL_DEBUG
#ifdef GPIO_CTRL_DEBUG
#define mDebug(format, ...) printk("File:%s, Function:%s, Line:%d "format, __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__);
#else
#define mDebug(format, ...)
#endif static int gpioCtrl_open(struct inode *inode, struct file *file)
{
mDebug("Dev open.\n"); return ;
} static int gpioCtrl_close(struct inode *inode, struct file *file)
{
mDebug("Dev close.\n"); return ;
} static ssize_t gpioCtrl_read(struct file *file,
char __user *buf,
size_t count,
loff_t *pos)
{
mDebug("Read data.\n"); return ;
} static long gpioCtrl_ioctl(struct file * file, unsigned int cmd, unsigned long arg) { int ret = ; switch ( cmd ) {
case SPK_HEIGHT :
gpio_set_value(SABRESD_VO_PIN, );
mDebug("SPK_HEIGHT.\n");
break;
case SPK_LOW :
gpio_set_value(SABRESD_VO_PIN, );
mDebug("SPK_LOW.\n");
break;
case AMP_HEIGHT :
gpio_set_value(SABRESD_AMPE_PIN, );
mDebug("AMP_HEIGHT.\n");
break;
case AMP_LOW :
gpio_set_value(SABRESD_AMPE_PIN, );
mDebug("AMP_LOW.\n");
break;
case SD_HEIGHT :
gpio_set_value(SABRESD_SD_PIN, );
mDebug("SD_HEIGHT.\n");
break;
case SD_LOW :
gpio_set_value(SABRESD_SD_PIN, );
mDebug("SD_LOW.\n");
break;
case DETECT :
ret = gpio_get_value(SABRESD_DT_PIN);
(*(int *)arg) = ret;
mDebug("DETECT ret = %d.\n", ret); ret = ;
break;
default :
mDebug("gpioCtrl control error.\n");
ret = -;
break;
}
return ret;
} struct file_operations fops = {
.owner = THIS_MODULE,
.open = gpioCtrl_open,
.release = gpioCtrl_close,
.read = gpioCtrl_read,
.unlocked_ioctl = gpioCtrl_ioctl,
}; struct miscdevice misc = {
.minor = MISC_DYNAMIC_MINOR,
.name = "gpioCtrl",
.fops = &fops,
}; int __init gpioCtrl_init(void)
{
int ret; ret = gpio_request(SABRESD_VO_PIN, "SABRESD_VO_PIN");
if ( ret ) {
mDebug("get SABRESD_VO_PIN gpio FAILED!\n");
return ret;
} ret = gpio_request(SABRESD_AMPE_PIN, "SABRESD_AMPE_PIN");
if ( ret ) {
mDebug("get SABRESD_AMPE_PIN gpio FAILED!\n");
goto fail1;
} ret = gpio_request(SABRESD_SD_PIN, "SABRESD_SD_PIN");
if ( ret ) {
mDebug("get SABRESD_SD_PIN gpio FAILED!\n");
goto fail2;
} ret = gpio_request(SABRESD_DT_PIN, "SABRESD_DT_PIN");
if ( ret ) {
mDebug("get SABRESD_DETECT gpio FAILED!\n");
goto fail3;
} gpio_direction_output(SABRESD_VO_PIN, );
gpio_direction_output(SABRESD_AMPE_PIN, );
gpio_direction_output(SABRESD_SD_PIN, );
gpio_direction_input(SABRESD_DT_PIN); ret = misc_register(&misc);
if(ret) {
mDebug("gpioCtrl_misc_register FAILED!\n");
goto fail4;
} mDebug("gpioCtrl_misc_register over!\n");
return ret; fail4:
gpio_free(SABRESD_DT_PIN);
fail3:
gpio_free(SABRESD_SD_PIN);
fail2:
gpio_free(SABRESD_AMPE_PIN);
fail1:
gpio_free(SABRESD_VO_PIN); return ret;
} void __exit gpioCtrl_exit(void)
{
gpio_set_value(SABRESD_VO_PIN, );
gpio_set_value(SABRESD_AMPE_PIN, );
gpio_set_value(SABRESD_SD_PIN, ); gpio_free(SABRESD_VO_PIN);
gpio_free(SABRESD_AMPE_PIN);
gpio_free(SABRESD_SD_PIN);
gpio_free(SABRESD_DT_PIN); misc_deregister(&misc);
} module_init(gpioCtrl_init);
module_exit(gpioCtrl_exit); MODULE_LICENSE("GPL");