Qualcomm技术william hill官网
直播中

李韵鹤

7年用户 132经验值
私信 关注
[经验]

基于Dragonboard 410c的智能遥控器软件实现

     之前已经做过智能遥控器的硬件介绍,这里就不再详细赘述了,现在主要看看软件实现。



#include

#include

#include

#include

#include

#include

#include

#include

#include timer.h>

#include

#include

#include

#include

#include

#include

#include

#include "et4007.h"


#define DEVICE_NAME        "irremote"

#define DRIVER_NAME        "et4007"


#define START_DELAY     200

#define STOP_DELAY      200

#define CLK_DELAY       50

.............

.............

static DECLARE_WAIT_QUEUE_HEAD(remote_waitq);


static volatile int busy_status = 0;

struct timer_list remote_timer;

struct class *et4007_class = NULL;

...............

...............


static int et4007_compare_alldata(struct remote_data rmt_data, uint16_t *sample, int index)

{

    int i;

    uint16_t timeHigh, timeLow;


    for (i = 0; i < index; i += 2) {

        timeHigh = sample;

        timeLow = sample[i + 1];

        if (et4007_compare_time(rmt_data, timeHigh, timeLow)) {

            return 1; // rmt_data is equal sample data

        }

    }

    return 0; // rmt_data is not equal sample data

}


static void et4007_push_sample_time_data(struct remote_data data, uint16_t *sample, int index)

{

    sample[index] = data.high_level;

    sample[index + 1] = data.low_level;

}



............


int et4007_get_index(struct remote_data data, uint16_t *sample, int index)

{

    int i = 0;

    uint16_t timeHigh, timeLow;

    for (i = 0; i < index; i += 2) {

        timeHigh = sample;

        timeLow = sample[i+1];

        if (et4007_compare_time(data, timeHigh, timeLow)) {

            return i;

        }

    }

    return 32;

}



static int et4007_get_data_index(struct ir_remocon_data *ir_data)

{

    int i, j = 0, count = 0;

    char temp;

    struct remote_data rmt_data;


    for (i = 0; i < ir_data->count; i += 2) {

        rmt_data.high_level = ir_data->original;

        rmt_data.low_level = ir_data->original[i+1];


        temp = et4007_get_index(rmt_data, ir_data->sample, ir_data->index);

        if (temp > 32) {

            return -1;

        }

        ir_data->data[count++] = (temp / 2) ;

    }


    ir_data->couple = count;

    i = 0;

    j = 0;

    while (i < count) {

        temp = (ir_data->data[i++] << 4) & 0xf0;

        temp |= (ir_data->data[i++]) & 0x0f;

        ir_data->data[j++] = temp;


        if (j > MAX_DATA) {

            j = MAX_DATA;

            return -1;

        }

    }


    ir_data->data_count = j;


    return j;

}


static int et4007_depress_sample(struct ir_remocon_data *ir_data)

{

    int i, j = 0;

    if (ir_data->index>MAX_SAMPLE_INDEX){

        ir_data->index = MAX_SAMPLE_INDEX;

        return -1;

    }


    for (i = 0; i < ir_data->index; i++) {

        ir_data->zp_sample[j++] = (uint8_t)(ir_data->sample >> 8) & 0xff;

        ir_data->zp_sample[j++] = (uint8_t)ir_data->sample;

    }

    ir_data->index = j;

    return j;

}


..............


static void remote_timer_handle(unsigned long data)

{

    if (!busy_status) {

        mod_timer(&remote_timer,jiffies+msecs_to_jiffies(100));

        if (!ET4007_GET_BUSY_STATE()) {

            busy_status = 1;

            wake_up_interruptible(&remote_waitq);

        }

    }

}


void et4007_start(void)

{

    ET4007_SET_SDA_OUTPUT();

    ET4007_SET_SDA_HIGH();

    ET4007_SET_SCL_OUTPUT();

    ET4007_SET_SCL_HIGH();

    ET4007_SET_SDA_LOW();

    udelay(START_DELAY);

    udelay(START_DELAY);

    udelay(START_DELAY);

    ET4007_SET_SCL_LOW();

    udelay(START_DELAY);

    udelay(START_DELAY);

}


void et4007_stop(void)

{

    udelay(STOP_DELAY);

    ET4007_SET_SDA_LOW();

    ET4007_SET_SDA_OUTPUT();

    udelay(STOP_DELAY);

    ET4007_SET_SCL_HIGH();

    udelay(STOP_DELAY);

    ET4007_SET_SDA_HIGH();

    udelay(STOP_DELAY);

    //ET4007_SET_SDA_INPUT();

    udelay(STOP_DELAY);

}


int et4007_i2c_write_byte(uint8_t dat)

{

    int err = 0;

    uint8_t i, dat_temp;


    dat_temp = dat;

    ET4007_SET_SDA_OUTPUT();

    for (i = 0; i < 8; i++) {

        udelay(10);

        if (dat_temp & 0x80) {

            ET4007_SET_SDA_HIGH();

        } else {

            ET4007_SET_SDA_LOW();

        }

        udelay(CLK_DELAY);

        ET4007_SET_SCL_HIGH();

        dat_temp <<= 1;

        udelay(CLK_DELAY);  // optional

        ET4007_SET_SCL_LOW();

        udelay(CLK_DELAY);

    }

    ET4007_SET_SDA_HIGH();

    ET4007_SET_SDA_INPUT();

    udelay(CLK_DELAY);

    ET4007_SET_SCL_HIGH();

    udelay(CLK_DELAY);

    //if(ET4007_GET_SDA_STATE())err=1;

    //else err=0;

    ET4007_SET_SCL_LOW();

    udelay(CLK_DELAY);


    return err;

}


uint8_t et4007_i2c_read_byte(void)

{

    uint8_t dat, i;


    ET4007_SET_SDA_HIGH();

    ET4007_SET_SDA_INPUT();

    dat = 0;

    for (i = 0; i != 8; i++) {

        udelay(CLK_DELAY);

        ET4007_SET_SCL_HIGH();

        udelay(CLK_DELAY);

        dat <<= 1;

        if(ET4007_GET_SDA_STATE()) dat++;

        ET4007_SET_SCL_LOW();

        udelay(10);

    }


    ET4007_SET_SDA_OUTPUT();

    ET4007_SET_SDA_LOW();

    udelay(CLK_DELAY);

    ET4007_SET_SCL_HIGH();

    udelay(CLK_DELAY);

    ET4007_SET_SCL_LOW();

    udelay(CLK_DELAY);


    return dat;

}



static int et4007_read_device_info(void)

{

    int ret = 0;

    int i;

    char buf[8] = {0};

    pr_info("%s: +n", __func__);


    et4007_start();


    /* write addr and cmd */

    et4007_i2c_write_byte(ET4007_ADDRESS);

    et4007_i2c_write_byte(ET4007_CONTROL_READ_VERSION);


    /* read device info */

    for (i = 0; i < 4; i++) {

        buf = et4007_i2c_read_byte();

    }


    et4007_stop();


    pr_info("%s: dev_id: 0x%02x, 0x%02x, 0x%02x, 0x%02x n", __func__,

            buf[0], buf[1], buf[2], buf[3]);


    ret = buf[0]*0x1000000 + buf[1]*0x10000 + buf[2]*0x100 + buf[3];


    pr_info("%s: -n", __func__);

    return ret;

}


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

{

    int i;

    char buf[4];


...........

...........

    return 0;

}


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

{

    int i;

    char buf[4];


    ...........

    ...........

    return 0;

}


static unsigned int et4007_poll( struct file *file,struct poll_table_struct *wait)

{

    unsigned int mask = 0;

    mod_timer(&remote_timer, jiffies + msecs_to_jiffies(40));

    poll_wait(file, &remote_waitq, wait);

    if (busy_status) {

        busy_status = 0;

        mask |= POLLIN | POLLRDNORM;

    }

    return mask;

}


static ssize_t et4007_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)

{

    char send_buff[256];

    int ret;

    int i;


    if (count == 0) {

        return -1;

    }

    if(buffer[0]==ET4007_CONTROL_SEND_CODE_3) {

        if (count > 384) {

            printk("ET4007---count error---n");

            return -1;

        }

        et4007_start();

        et4007_i2c_write_byte(ET4007_ADDRESS);

        for (i = 0; i < count; i++) {

            et4007_i2c_write_byte(buffer);

        }

        et4007_stop();

        return count;

    } else if (buffer[0] == ET4007_CONTROL_SEND_CODE_1) {

        if (count> 129) {

            count = 129;

            printk("ET4007---size error---n");

            return count;

        }

        memset(send_buff,0x00,129);

        ret = copy_from_user(send_buff, buffer, count) ;


        if (ret) {

            printk("ET4007---copy error---n");

            return ret;

        }

        et4007_start();

        et4007_i2c_write_byte(ET4007_ADDRESS);

        for (i = 0; i < 129; i++) {

            et4007_i2c_write_byte(send_buff);

        }

        et4007_stop();

        return count;

    } else {

        printk("ET4007---command  error---n");

        return -1;

    }

    return count;

}


static ssize_t et4007_read(struct file *filp, char *buff,size_t count, loff_t *ppos)

{

    int i, err;

    int ET_crc;

    int ET_PartIndexCount;

    int ET_Sample;

    int ET_Index;

    int ET_Freq;

    int m = 0;

    int max = 0;

    char buf_ir_test[384];


    pr_info("%s: +n", __func__);


    et4007_start();

    et4007_i2c_write_byte(ET4007_ADDRESS);

    et4007_i2c_write_byte(ET4007_CONTROL_READ_CODE);

    ET_crc = et4007_i2c_read_byte();

    buf_ir_test[m++] = ET_crc;

    ET_PartIndexCount = et4007_i2c_read_byte();

    buf_ir_test[m++] = ET_PartIndexCount;

    ET_Sample = et4007_i2c_read_byte();

    buf_ir_test[m++] = ET_Sample;

    ET_Index = et4007_i2c_read_byte();

    buf_ir_test[m++] = ET_Index;

    ET_Freq = et4007_i2c_read_byte();

    buf_ir_test[m++] = ET_Freq;

    max = ET_PartIndexCount+ET_Sample+ET_Index;

    if (max > 380) {

        et4007_stop();

        return  -EFAULT;

    }


    for (i = 0; i < max; i++) {

        buf_ir_test[m] = et4007_i2c_read_byte();

        m++;

    }


    et4007_stop();


    if (m > sizeof(buf_ir_test)) {

        m = sizeof(buf_ir_test);

    }


    err = copy_to_user((void *)buff, (const void *)(&buf_ir_test[0]), m);


    pr_info("%s: -n", __func__);


    return err ? -EFAULT : m;

}


static int et4007_open(struct inode *inode, struct file *file)

{

    et4007_read_device_info();

    setup_timer(&remote_timer, remote_timer_handle, (unsigned long)"remote");

    return 0;

}


static int et4007_close(struct inode *inode, struct file *file)

{

    del_timer_sync(&remote_timer);

    return 0;

}


static struct file_operations et4007_fops = {

    .owner            = THIS_MODULE,

    .open            = et4007_open,

    .release        = et4007_close,

    .write          = et4007_write,

    .read            = et4007_read,

    .poll            = et4007_poll,

    .unlocked_ioctl    = et4007_ioctl,

#ifdef CONFIG_COMPAT

    .compat_ioctl   = et4007_ioctl_compat,

#endif

};


static void et4007_remocon_work(struct ir_remocon_data *ir_data)

{

    struct ir_remocon_data *data = ir_data;

    int sleep_timing;

    int emission_time;

    int i;


    //mutex_lock(&data->mutex);


    et4007_start();

    et4007_i2c_write_byte(ET4007_ADDRESS);

    for (i = 0; i < ir_data->length; i++) {

        et4007_i2c_write_byte(ir_data->signal);

    }

    et4007_stop();


    //mutex_unlock(&data->mutex);


    emission_time = ( (data->ir_sum) * (data->freq) * 4 / 5000);

    sleep_timing = emission_time -10;

    if (sleep_timing < 0) {

        sleep_timing = 10;

    }


    data->freq = 0;

    data->ir_sum = 0;

}


static ssize_t et4007_ir_send_store(struct device *dev, struct device_attribute *attr,

        const char *buf, size_t size)

{

    unsigned int data;

    int err;

    int count = 0, i;


    ir_data->count = 0;

    ir_data->send_flag = 1;

...................

...................

    if (ir_data->count < 5) {

        printk("data->count < 5 error nr");

        return -1;

    }


    err = et4007_compress_original_data(ir_data);

    if (err < 0) {

        printk("et4007_compress_original_data  error nr");

        return -1;

    }


    et4007_remocon_work(ir_data);


    return size;

}


static ssize_t et4007_ir_send_show(struct device *dev, struct device_attribute *attr, char *buf)

{

    int i;

    int len = 0;

    char buf_read[8] = {0};


............

............

    return len;

}


static DEVICE_ATTR(ir_send, 0664, et4007_ir_send_show, et4007_ir_send_store);


static ssize_t et4007_ir_learn_store(struct device *dev, struct device_attribute *attr,

        const char *buf, size_t size)

{

    unsigned int data;


    if (sscanf(buf++, "%u", &data) == 1) {

  .......................

    }

    return size;

}


static ssize_t et4007_ir_learn_show(struct device *dev, struct device_attribute *attr, char *buf)

{

    int crc, part_index_count, sample, index, freq;

    int i, m = 0, max = 0, len = 0;

    char buf_read[386] = {0};


    et4007_start();

    et4007_i2c_write_byte(ET4007_ADDRESS);

    et4007_i2c_write_byte(ET4007_CONTROL_READ_CODE);


    /* crc */

    crc = et4007_i2c_read_byte();

    buf_read[m++] = crc;


    /* part index count */

    part_index_count = et4007_i2c_read_byte();

    buf_read[m++] = part_index_count;


    /* sample */

    sample = et4007_i2c_read_byte();

    buf_read[m++] = sample;


    /* index */

    index = et4007_i2c_read_byte();

    buf_read[m++] = index;


    /* freq */

    freq = et4007_i2c_read_byte();

    buf_read[m++] = freq;


    pr_info("%s: part_index_count = %d, sample = %d, index = %dn", __func__,

            part_index_count, sample, index);


    max = part_index_count + sample + index;

    if (max > 380) {

        et4007_stop();

        sprintf(buf, "error");

        return len;

    }


    for (i = 0; i < max; i++) {

        buf_read[m] = et4007_i2c_read_byte();

        m++;

    }


    et4007_stop();


    for (i = 0; i < m; i++) {

        if (i == 0) {

            len = sprintf(buf, "%d", buf_read);

        } else {

            len += sprintf(buf + len, ",%d", buf_read);

        }

        //pr_info("%s: learn data[%d] = %dn", __func__, i, buf_read);

    }

    pr_info("n");

    len += sprintf(buf + len, "n");

    return    len;

}

static DEVICE_ATTR(ir_learn, 0664, et4007_ir_learn_show, et4007_ir_learn_store);


static ssize_t et4007_ir_state_show(struct device *dev, struct device_attribute *attr, char *buf)

{

    int len = 0;

    if (ET4007_GET_BUSY_STATE()) {

        len = sprintf(buf + len, "%dn", 1);

    } else {

        len = sprintf(buf + len, "%dn", 0);

    }

    return    len;

}

static DEVICE_ATTR(ir_state, 0444, et4007_ir_state_show, NULL);


static ssize_t et4007_ir_info_show(struct device *dev, struct device_attribute *attr, char *buf)

{

    int i, len = 0;

    len += sprintf(buf + len, "%d,", ir_data->send_flag);

    len += sprintf(buf + len, "%d,", ir_data->orig_freq);

    for (i = 0; i < ir_data->count; i++) {

        len += sprintf(buf + len, "%d,", ir_data->original);

    }


    len += sprintf(buf + len, "n");

    ir_data->send_flag = 0;

    return    len;

}

static DEVICE_ATTR(ir_info, 0444, et4007_ir_info_show, NULL);


static int et4007_parse_dt(struct device *dev)

{

    if (!dev || !dev->of_node || !ir_data)

        return -1;


    ir_data->clk_gpio = of_get_named_gpio_flags(dev->of_node, "etek,clk-gpio", 0, NULL);

    if (!gpio_is_valid(ir_data->clk_gpio)) {

        pr_err("%s: clk gpio is invalid !n ", __func__);

        return ir_data->clk_gpio;

    }


    pr_info("%s: clk gpio = %dn", __func__, ir_data->clk_gpio);


    ir_data->sda_gpio = of_get_named_gpio_flags(dev->of_node, "etek,sda-gpio", 0, NULL);

    if (!gpio_is_valid(ir_data->sda_gpio)) {

        pr_err("%s: sda gpio is invalidn ", __func__);

        return ir_data->sda_gpio;

    }


    pr_info("%s: sda gpio = %dn", __func__, ir_data->sda_gpio);


    ir_data->busy_gpio = of_get_named_gpio_flags(dev->of_node, "etek,busy-gpio", 0, NULL);

    if (!gpio_is_valid(ir_data->busy_gpio)) {

        pr_err("%s: busy gpio is invalidn ", __func__);

        return ir_data->busy_gpio;

    }


    pr_info("%s: busy gpio = %dn", __func__, ir_data->busy_gpio);


    return 0;

}


static struct miscdevice et4007_misc_dev = {

    .minor = MISC_DYNAMIC_MINOR,

    .name = DEVICE_NAME,

    .fops = &et4007_fops,

};


static int et4007_probe(struct platform_device *pdev)

{

    struct device *ir_remocon_dev;

    int error;

    pr_info("%s: +n", __func__);

#ifdef ET_POWERCONTROL

    ET4007_SET_POWER_HIGH();

    mdelay(1);

#endif

    ir_data = kzalloc(sizeof(struct ir_remocon_data), GFP_KERNEL);

    if (NULL == ir_data) {

        pr_err("%s: failed to kzalloc memory for ir_data !n", __func__);

        error = -ENOMEM;

        goto err_free_mem;

    }


    error = et4007_parse_dt(&pdev->dev);

    if (error) {

        pr_err("%s: failed to parse dt !n", __func__);

        return error;

    }


    error = gpio_request(ET4007_SCL_GPIO, DEVICE_NAME);

    if (error) {

        pr_err("%s: failed to request scl gpio (%d) !n", __func__, ET4007_SCL_GPIO);

        return error;

    }


    error = gpio_request(ET4007_SDA_GPIO, DEVICE_NAME);

    if (error) {

        pr_err("%s: failed to request sda gpio (%d) !n", __func__, ET4007_SDA_GPIO);

        return error;

    }


    error = gpio_request(ET4007_BUSY_GPIO, DEVICE_NAME);

    if (error) {

        pr_err("%s: failed to request busy gpio (%d) !n", __func__, ET4007_BUSY_GPIO);

        return error;

    }


    et4007_class = class_create(THIS_MODULE, "etek");

    if (IS_ERR(et4007_class)) {

        pr_err("%s: failed to create class(etek)!n", __func__);

        return PTR_ERR(et4007_class);

    }


    ir_remocon_dev = device_create(et4007_class, NULL, 0, ir_data, "sec_ir");


    if (IS_ERR(ir_remocon_dev))

        pr_err("%s: failed to create ir_remocon_dev devicen", __func__);


    if (device_create_file(ir_remocon_dev, &dev_attr_ir_send) < 0)

        pr_err("%s: failed to create device file(%s)!n", __func__,

                dev_attr_ir_send.attr.name);


    if (device_create_file(ir_remocon_dev, &dev_attr_ir_state) < 0)

        pr_err("%s: failed to create device file(%s)!n", __func__,

                dev_attr_ir_state.attr.name);


    if (device_create_file(ir_remocon_dev, &dev_attr_ir_learn) < 0)

        pr_err("%s: failed to create device file(%s)!n", __func__,

                dev_attr_ir_learn.attr.name);


    if (device_create_file(ir_remocon_dev, &dev_attr_ir_info) < 0)

        pr_err("%s: failed to create device file(%s)!n", __func__,

                dev_attr_ir_info.attr.name);


    ET4007_SET_SCL_OUTPUT();

    ET4007_SET_SDA_OUTPUT();

    ET4007_SET_BUSY_INPUT();

    ET4007_SET_SCL_HIGH();

    ET4007_SET_SDA_HIGH();


    et4007_read_device_info();


    pr_info("%s: -n", __func__);


    return error;

err_free_mem:

#ifdef ET_POWERCONTROL

    ET4007_SET_POWER_LOW();

#endif

    kfree(ir_data);

    ir_data = NULL;

    return error;

}


static int et4007_remove(struct platform_device *pdev)

{

    if (et4007_class)

        device_destroy(et4007_class, 0);


    if (ir_data)

        kfree(ir_data);


    return 0;

}


static struct of_device_id et4007_match_table[] = {

    {.compatible = "etek,ir", },

    { },

};


static struct platform_driver et4007_driver = {

    .probe    = et4007_probe,

    .remove   = et4007_remove,

    // .suspend  = et4007_suspend,

    //  .resume   = et4007_resume,

    .driver   = {

        .owner   = THIS_MODULE,

        .name    = DEVICE_NAME,

        .of_match_table = et4007_match_table,

    },

};


static int __init et4007_init(void)

{

    if(misc_register(&et4007_misc_dev)) {

        pr_err("%s: misc_register register failedn", __func__);

    }

    return platform_driver_register(&et4007_driver);

}


static void __exit et4007_exit(void)

{

    misc_deregister(&et4007_misc_dev);

    platform_driver_unregister(&et4007_driver);

}


module_init(et4007_init);

module_exit(et4007_exit);


MODULE_LICENSE("GPL");

MODULE_AUTHOR("ETEK Inc.");

MODULE_DESCRIPTION("ETEK consumerir Driver");


我们是用gpio模拟的i2c,所以代码比较冗长,但是功能还是可以的。有兴趣的话可以自己动手试一下。

更多回帖

发帖
×
20
完善资料,
赚取积分