OK335xS pwm buzzer Linux driver hacking

时间:2021-05-13 09:26:42
/****************************************************************************
 *                 OK335xS pwm buzzer Linux driver hacking
 * 声明:
 *   本文仅仅是为了知道如何使用pwm来控制buzzer,已达到控制不同声音的频率。
 *
 *                                  2015-10-7 雨 深圳 南山平山村 曾剑锋
 ***************************************************************************/


#include <linux/init.h>
#include <linux/export.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/errno.h>
#include <linux/miscdevice.h>
#include <linux/types.h>
#include <linux/io.h>
#include <linux/pwm/pwm.h>
#include <linux/fs.h>  

#define DEBUG 
#if defined(DEBUG)            
#define DPRINTK(fmt,arg...) printk(fmt,##arg); 
#else
#define DPRINTK(fmt,arg...)
#endif

#define BUZZER_FREQENCY 1
#define DEV_NAME    "buzzer"

/*pwm for this buzzer*/
struct pwm_device *pwm = NULL;

static int buzzer_open(struct inode *inode, struct file *filp)
{

    if(pwm != NULL)
        return -EBUSY;
    
    /**
     * 申请一个pwm设备
     */ 
    pwm = pwm_request("ecap.1", -1, "buzzer");
    if ( pwm == NULL ) {
        printk("buzzer open error.\n");
    }

    printk("buzzer open\n");
    return 0;
}

static int buzzer_release(struct inode *inode, struct file *filp)
{
    /**
     * 关闭、注销一个pwm设备
     */
    pwm_stop(pwm);
    pwm_release(pwm);
    pwm = NULL;

    printk("buzzer release\n");

    return 0;
}


static long buzzer_ioctl(struct file *filp,
                        unsigned int cmd, unsigned long arg)
{

    if(pwm == NULL)
        return -EINVAL;

    if(arg > 20000 || arg < 0)
        return -EINVAL;

    switch (cmd) {
    case BUZZER_FREQENCY:       // 设置频率
        if(arg==0)
            pwm_stop(pwm);
        else
        {
            pwm_set_period_ns(pwm, 1000000000/arg);
            pwm_set_duty_ns(pwm, 25000);
            pwm_start(pwm);
        }
        
        break;
    default:
        break;
    }

    return 0;
}

static struct file_operations buzzer_fops = {
    .owner   = THIS_MODULE,
    .unlocked_ioctl     = buzzer_ioctl,
    .open    = buzzer_open,
    .release = buzzer_release,
};

static struct miscdevice buzzer_miscdev =
{
     .minor    = MISC_DYNAMIC_MINOR,
     .name    = DEV_NAME,
     .fops    = &buzzer_fops,
};


static int __init buzzer_init(void)
{
    /**
     * 注册杂项设备
     */
    misc_register(&buzzer_miscdev);
    return 0;
}

static void __exit buzzer_exit(void)
{
   misc_deregister(&buzzer_miscdev);
}

module_init(buzzer_init);
module_exit(buzzer_exit);