//author:DriverMonkey
//phone:13410905075
//mail:bookworepeng@Hotmail.com
//qq:196568501
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define GPIO_TO_PIN(bank, gpio) (32 * (bank) + (gpio))
#define US (1000)
#define PPM_CHANEL 8
#define FIX_LOW_TIME 100*US
struct ppm_dev
{
struct cdev cdev;
dev_t devno;
struct class *ppm_class;
int message_cdev_open;
};
struct ppm_dev ppm_dev;
static long long ppm_values[(PPM_CHANEL + 1)*2] =
{FIX_LOW_TIME,1000*US, // 1
FIX_LOW_TIME,1000*US,// 2
FIX_LOW_TIME,1000*US,// 3
FIX_LOW_TIME,1000*US, // 4
FIX_LOW_TIME,1000*US,// 5
FIX_LOW_TIME,1000*US,// 6
FIX_LOW_TIME,1000*US,// 7
FIX_LOW_TIME,1000*US,// 8
FIX_LOW_TIME,5000*US, };// 9
ktime_t ktime;
static struct hrtimer hr_timer;
static enum hrtimer_restart hrtimer_callback(struct hrtimer *timer)
{
static int index = 0;
static ktime_t ktime;
if(index == ((PPM_CHANEL + 1)*2))
index = 0;
ktime.tv64 = ppm_values[index];
hrtimer_forward(timer, timer->base->get_time(), ktime);
index++;
if(ktime.tv64 == FIX_LOW_TIME)
gpio_direction_output(GPIO_TO_PIN(0,27), 0);
else
gpio_direction_output(GPIO_TO_PIN(0,27), 1);
//printk("%d\n",(int)ktime.tv64);
return HRTIMER_RESTART;
}
static int ppm_open(struct inode *node, struct file *fd)
{
int ret = 0;
printk("ppm_open()++\n");
ktime = ktime_set( 0, 200*1000); // 200us
hrtimer_init( &hr_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL );
hr_timer.function = &hrtimer_callback;
hrtimer_start( &hr_timer, ktime, HRTIMER_MODE_REL );
printk("ppm_open()--\n");
return ret;
}
ssize_t ppm_write(struct file *pfile,
const char __user *buffer,
size_t size,
loff_t *pnull)
{
printk("ppm_write()++\n");
if(size != (PPM_CHANEL * sizeof(long long)))
return 0;
//copy_from_user(ppm_values, buffer, size);
printk("ppm_write()--\n");
return size;
}
static int ppm_fasync(int fd, struct file *filp, int mode)
{
printk("ppm_fasync()++\n");
printk("ppm_fasync()--\n");
return 0;
}
static int ppm_release(struct inode *node, struct file *fd)
{
printk("ppm_release()++\n");
hrtimer_cancel(&hr_timer);
printk("ppm_release()--\n");
return 0;
}
struct file_operations meassage_operatons =
{
.owner = THIS_MODULE,
.open = ppm_open,
.write = ppm_write,
.fasync = ppm_fasync,
.release = ppm_release,
};
static int __init ppm_init(void)
{
struct ppm_dev * dev;
int ret = 0;
dev = &ppm_dev;
alloc_chrdev_region(&dev->devno, 0, 1, "out_ppm");
dev->ppm_class = class_create(THIS_MODULE, "ppm_class");
if(IS_ERR(dev->ppm_class)) {
printk(KERN_ERR"Err: failed in creating class./n");
goto fail1;
}
device_create(dev->ppm_class, NULL, dev->devno, NULL, "ppm");
//init irq
ret = gpio_request(GPIO_TO_PIN(0,27), "ppm_inter");
if(ret){
printk(KERN_ERR"gpio_request() failed !\n");
goto fail1;
}
ret = gpio_direction_output(GPIO_TO_PIN(0,27), 1);
if(ret){
printk(KERN_ERR"gpio_direction_input() failed !\n");
goto fail2;
}
cdev_init(&dev->cdev, &meassage_operatons);
cdev_add(&dev->cdev, dev->devno, 1);
if(ret){
printk(KERN_ERR"request_irq() failed ! %d\n", ret);
goto fail2;
}
printk("ppm_to_app_init(void)--\n");
return 0;
fail2:
gpio_free(GPIO_TO_PIN(0,27));
fail1:
device_destroy(dev->ppm_class, dev->devno);
class_destroy(dev->ppm_class);
cdev_del(&dev->cdev);
unregister_chrdev_region(dev->devno, 1);
return ret;
}
static void __exit ppm_exit(void)
{
struct ppm_dev *dev = &ppm_dev;
// printk("ppm_to_app_exit(void)++\n");
gpio_free(GPIO_TO_PIN(0,27));
device_destroy(dev->ppm_class, dev->devno);
class_destroy(dev->ppm_class);
cdev_del(&dev->cdev);
unregister_chrdev_region(dev->devno, 1);
// printk("ppm_to_app_exit(void)--\n");
}
module_init(ppm_init);
module_exit(ppm_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Driver Monkey");
MODULE_DESCRIPTION("Test ppm");