linux ir(模拟红外发射)

1 篇文章 0 订阅

/*
 * drivers/pwm/pwm-sunxi-dev.c
 *
 * Allwinnertech pulse-width-modulation controller driver
 *
 * Copyright (C) 2018 AllWinner
 *
 *
 * This file is licensed under the terms of the GNU General Public
 * License version 2. This program is licensed "as is" without any
 * warranty of any kind, whether express or implied.
 */
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/uaccess.h>
#include <linux/slab.h>
#include <linux/clk.h>
#include <linux/gpio.h>
#include <linux/device.h>
#include <linux/pinctrl/consumer.h>
#include <asm/io.h>
#include <linux/pwm.h>

#include <linux/delay.h>
#include <linux/mutex.h>
#include <linux/time.h>
#include <linux/hrtimer.h>
static u32 debug_mask;
#define dprintk(level_mask, fmt, arg...)                \
do {                                    \
    if (unlikely(debug_mask & level_mask))                \
        pr_warn("%s()%d - "fmt, __func__, __LINE__, ##arg);    \
} while (0)

#define IRTX_ERR(fmt, arg...) pr_err("%s()%d - "fmt, __func__, __LINE__, ##arg)

#define assert(expr) \        
do { \ 
        if (!(expr)) { \      
                printk(KERN_ERR "Assertion failed! %s, %s, %s, line %d\n", \
                           #expr, __FILE__, __func__, __LINE__); \
        } \
} while (0)


#define INFRATYPE  'I'
#define INFRA_START _IOW(INFRATYPE, 0, int)
#define INFRA_READ_DATA _IOR(INFRATYPE, 1, int)
#define INFRA_WRITE_DATA _IOW(INFRATYPE, 2, int)

#define PS_SIZE 10
#define MAX_PLUSE 2048

#define IR_TX_EVENT_SIZE 4
#define IR_TX_BUFFER_SIZE 2048

#define PWM_CONFIG    _IOW(PWM_IOCTL_BASE, 1 , struct pwm_config)
#define PWM_ENABLE    _IOW(PWM_IOCTL_BASE, 2 , int)
#define PWM_DISABLE   _IOW(PWM_IOCTL_BASE, 3 , int)

static struct pwm_device *pwm = NULL;

struct sunxi_pwm_dev {
    struct device *dev;
    struct cdev cdev;
    dev_t chrdev;
};

static struct sunxi_pwm_dev    *sunxi_pwm_dev;
static struct class            *sunxi_pwm_class;

static int sunxi_pwm_open(struct inode *inode, struct file *filp)
{
    filp->private_data = sunxi_pwm_dev;
    return 0;
}

static int sunxi_pwm_release(struct inode *inode, struct file *filp)
{
    return 0;
}

struct timeval time1, time2;

static struct hrtimer hrtimer;

static int infra_w_complete_flag;
static struct mutex mutex;

static int data_count = 0;
static unsigned int times_w_state[MAX_PLUSE];
static unsigned int times_w_data[MAX_PLUSE];

static enum hrtimer_restart hrtimer_hander(struct hrtimer *timer)
{
    
    do_gettimeofday(&time2);
    printk(KERN_EMERG"hrtimer_hander\n");
    double elapsed_time = (time2.tv_sec - time1.tv_sec) * 1000. +(time2.tv_usec - time1.tv_usec) / 1000.;

    time1.tv_sec = time2.tv_sec;
    time1.tv_usec = time2.tv_usec;

    assert(timer);

    if (0 == times_w_data[data_count]) {
        infra_w_complete_flag = 1;
        pwm_disable(pwm);
        return HRTIMER_NORESTART;
    }

    if (times_w_state[data_count] == 'u') {
        pwm_disable(pwm);
        printk(KERN_EMERG"%d pwm close %d\n", data_count, times_w_data[data_count]);
    } else {
        pwm_config(pwm, 13158, 26316);        
        pwm_enable(pwm);
        printk(KERN_EMERG"%d pwm run %d\n", data_count, times_w_data[data_count]);
    }
    hrtimer_forward_now(&hrtimer, ktime_set(0, times_w_data[data_count] * 1000));
   
    data_count++;

    return HRTIMER_RESTART;
}


static void timer_start(void)
{
    int ret = 0;
    printk(KERN_EMERG"timer_start\n");
    
    infra_w_complete_flag = 0;
    data_count = 0;
    hrtimer_init(&hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
    ret = hrtimer_start(&hrtimer, ktime_set(0, 100000), HRTIMER_MODE_REL);
    assert(ret >= 0);
    hrtimer.function = hrtimer_hander;
    do_gettimeofday(&time1);
}

static ssize_t irblaster_dev_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos)
{

    char data[MAX_PLUSE];
    char tone[PS_SIZE];
    int i = 0, j = 0, m = 0, ret = 0;
    int val;
    int status = 0;

    printk(KERN_EMERG"%d\n",count);
    
    if(copy_from_user(data, (void __user *)buf, count)){
        printk(KERN_EMERG"copy err\n");
        return 0;
    }
    printk(KERN_EMERG"copy ok\n");

    mutex_init(&mutex);
    mutex_lock(&mutex);
    while (data[i] != '\0' && i < count) {
        if (data[i] == 'u' || data[i] == 'U') {
            tone[j] = '\0';
            ret = kstrtoint(tone, 10, &val);
            //ev->buffer[m] = val * 10;
            times_w_data[m] = val;
            times_w_state[m] = data[i]; 
            printk(KERN_EMERG"data=%d,status=%d\n", val, data[i]);
            j = 0;
            i++;
            m++;
            if (m >= IR_TX_BUFFER_SIZE)
                break;
            continue;
        }
        tone[j] = buf[i];
        i++;
        j++;
        if (j >= PS_SIZE) {
            pr_err("send timing value is out of range,i=%d, j=%d, m=%d\n", i, j, m); 
            mutex_unlock(&mutex);
            return -ENOMEM;
        }
    }

    
    //ev->size = m;
    status = count;
    /*to send cycle to,*/
    //kfifo_put(&rffifo, (const struct tx_event *)ev);

    pr_info("m = %d\n", m);
    for(i=0; i < m; i++) {
        printk(KERN_EMERG"times_w_data[%d] = %d state=%c\n", i, times_w_data[i], times_w_state[i]);
    }

    timer_start();

    while(!infra_w_complete_flag)
        msleep(100);

    hrtimer_cancel(&hrtimer);
    mutex_unlock(&mutex);
    return status;
}


static const struct file_operations sunxi_pwm_fops = {
    .owner        = THIS_MODULE,
    .open        = sunxi_pwm_open,
    .write      = irblaster_dev_write,
    .release    = sunxi_pwm_release,
};

static int __init sunxi_pwm_init(void)
{
    int err = 0;
    struct device *dev;

    sunxi_pwm_dev= kzalloc(sizeof(struct sunxi_pwm_dev), GFP_KERNEL);
    if (sunxi_pwm_dev == NULL) {
        IRTX_ERR("kzalloc failed!\n");
        return -ENOMEM;
    }

    err = alloc_chrdev_region(&sunxi_pwm_dev->chrdev, 0, 1, "pwm-ir-tx");

    if (err) {
        IRTX_ERR("alloc_chrdev_region failed!\n");
        goto alloc_chrdev_err;
    }

    cdev_init(&(sunxi_pwm_dev->cdev), &sunxi_pwm_fops);
    sunxi_pwm_dev->cdev.owner = THIS_MODULE;
    err = cdev_add(&(sunxi_pwm_dev->cdev), sunxi_pwm_dev->chrdev, 1);
    if (err) {
        IRTX_ERR("cdev_add failed!\n");
        goto cdev_add_err;
    }

    sunxi_pwm_class = class_create(THIS_MODULE, "pwm-ir-tx_class");
    if (IS_ERR(sunxi_pwm_class)) {
        err = PTR_ERR(sunxi_pwm_class);
        IRTX_ERR("pwm-ir-tx_class failed!\n");
        goto class_err;
    }

    dev = device_create(sunxi_pwm_class, NULL, sunxi_pwm_dev->chrdev, NULL,
            "pwm-ir-tx%d", 16);
    if (IS_ERR(dev)) {
        err = PTR_ERR(dev);
        IRTX_ERR("device_create failed!\n");
        goto device_err;
    }

    pwm = pwm_request(16, "spwm0");
        if(IS_ERR(pwm)){
        err = PTR_ERR(pwm);
        IRTX_ERR("pwm request err\n");
                goto pwm_err;
        }else
                IRTX_ERR("pwm request success\n");


    return 0;
    
pwm_err:
    pwm_free(pwm);
device_err:
    device_destroy(sunxi_pwm_class, sunxi_pwm_dev->chrdev);
class_err:
    cdev_del(&(sunxi_pwm_dev->cdev));
cdev_add_err:
    unregister_chrdev_region(sunxi_pwm_dev->chrdev, 1);
alloc_chrdev_err:
    kfree(sunxi_pwm_dev);

    return err;
}

static void __exit sunxi_pwm_exit(void)
{
    pwm_free(pwm);
    cdev_del(&(sunxi_pwm_dev->cdev));
    unregister_chrdev_region(sunxi_pwm_dev->chrdev, 1);
    device_destroy(sunxi_pwm_class, sunxi_pwm_dev->chrdev);
    class_destroy(sunxi_pwm_class);
    kfree(sunxi_pwm_dev);
}


module_init(sunxi_pwm_init);
module_exit(sunxi_pwm_exit);
MODULE_AUTHOR("Li huaxing");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("SUNXI_PWM_IR_TX");

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值