Pages

Thursday, October 25, 2012

MPS - Exercise 5 - LDD with GPIO


Driver 1 – Bootkey

#include <linux/gpio.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <asm/uaccess.h>
#include <linux/module.h>

#define GPIO 7                     //GPIO port-nr
#define myMAJOR 64
#define myMINOR 0
#define ch 1
#define MAXLEN 512

//static struct cdev My
struct file_operations my_fops;
static int devno;
int err;


MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("NKB");
MODULE_DESCRIPTION("Reads the user_key");
MODULE_LICENSE("Dual BSD/GPL");

ssize_t mygpio_read (struct file *file, char __user *buf, size_t count, loff_t *f_pos);
int mygpio_open (struct inode *inode, struct file *file);
int mygpio_release (struct inode *inode, struct file *file);

struct file_operations my_fops = {
                  .owner = THIS_MODULE,
                  .readmygpio_read,
                  .openmygpio_open,
                  .releasemygpio_release,
};

static struct cdev my_cdev;

Init

static int mygpio_init(void)
{
                  printk(KERN_ALERT "Hello, world\n");

                  err = gpio_request_one(GPIO, GPIOF_DIR_IN, "Init User-key");             //Request GPIO, set GPIO direction (in)
                  if (err != 0)
                                    goto requestError;
                  devno = MKDEV(myMAJOR,myMINOR);                                                                             //make device number

                  cdev_init(&my_cdev, &my_fops);

                  err = cdev_add(&my_cdev, devno, ch);
                  if (err != 0)
                                    goto cdevAddError;
                  err = register_chrdev_region(devno,ch,"User-key");
                  if (err != 0)
                                    goto registerChrdevError;
                  // alloc_chrdev_region() kunne bruges for dynamisk allkoering

                  return 0;

                  requestError:
                  {
                                    printk(KERN_ALERT "Request FAILED!\n");
                                    gpio_free(GPIO);
                                    return 0;
                  }

                  cdevAddError:
                  {
                                    printk(KERN_ALERT "cdev add FAILED!\n");
                                    cdev_del(&my_cdev);
                                    return 0;
                  }

                  registerChrdevError:
                  {
                                    printk(KERN_ALERT "registering FAILED!\n");
                                    unregister_chrdev_region(devno,ch);
                                    return 0;
                  }
}

Exit

static void mygpio_exit(void)
{
                  printk(KERN_ALERT "Goodbye, cruel world\n");
                  unregister_chrdev_region(devno,ch); // skal den ikke være i cleanup func?
                  cdev_del(&my_cdev);
                  gpio_free(GPIO);
}

Open

int mygpio_open(struct inode *inode, struct file *file)
{
                  int major, minor;
                  major = MAJOR(inode->i_rdev);
                  minor = MINOR(inode->i_rdev);
                  printk("Opening MyGpio Device [major], [minor]: %i, %i\n", major, minor);
                  return 0;
}

Release

int mygpio_release(struct inode *inode, struct file *file)
{
                  int minor, major;
                    
                  major = MAJOR(inode->i_rdev);
                  minor = MINOR(inode->i_rdev);
                  return 0;
}

Read

ssize_t mygpio_read(struct file *filep, char __user *buf,
                 size_t count, loff_t *f_pos)
{
                  char readBuf[MAXLEN];
                  int len, result=-1, minor;
                  minor = MINOR(filep->f_dentry->d_inode->i_rdev);

                  result = gpio_get_value(GPIO);
                  len = sprintf(readBuf, "%d", result);
                 
                  printk(KERN_ALERT "testBuf: %s \n", readBuf);
                  if (copy_to_user(buf,readBuf, len))
                                    printk(KERN_ALERT "Bootkey not copied!");
                                   
                  *f_pos += len;
                  return len;   
}

module_init(mygpio_init);
module_exit(mygpio_exit);



Driver 2 -  Sys_Led4


#include <linux/gpio.h>

#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <asm/uaccess.h>
#include <linux/module.h>

#define GPIO 164                                 //GPIO port-nr
#define myMAJOR 64
#define myMINOR 0
#define ch 1
#define MAXLEN 512

//static struct cdev My
struct file_operations my_fops;
static int devno;
int err;


MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("NKB");
MODULE_DESCRIPTION("Reads the user_key");
MODULE_LICENSE("Dual BSD/GPL");

ssize_t mygpio_write(struct file *filep, const char __user *ubuf, size_t count, loff_t *f_pos);
int mygpio_open (struct inode *inode, struct file *file);
int mygpio_release (struct inode *inode, struct file *file);

struct file_operations my_fops = {
                  .owner = THIS_MODULE,
                  .write = mygpio_write,
                  .openmygpio_open,
                  .releasemygpio_release,
};

static struct cdev my_cdev;

Init

static int mygpio_init(void)
{
                  printk(KERN_ALERT "Hello, world\n");

                  err = gpio_request_one(GPIO, GPIOF_DIR_OUT, "Init User-key");         //Request GPIO, set GPIO direction (in)
                  if (err != 0)
                                    goto requestError;
                  devno = MKDEV(myMAJOR,myMINOR);                                                                             //make device number

                  cdev_init(&my_cdev, &my_fops);

                  err = cdev_add(&my_cdev, devno, ch);
                  if (err != 0)
                                    goto cdevAddError;
                  err = register_chrdev_region(devno,ch,"User-key");
                  if (err != 0)
                                    goto registerChrdevError;
                  // alloc_chrdev_region() kunne bruges for dynamisk allkoering

                  return 0;

                  requestError:
                  {
                                    printk(KERN_ALERT "Request FAILED!\n");
                                    gpio_free(GPIO);
                                    return 0;
                  }

                  cdevAddError:
                  {
                                    printk(KERN_ALERT "cdev add FAILED!\n");
                                    cdev_del(&my_cdev);
                                    return 0;
                  }

                  registerChrdevError:
                  {
                                    printk(KERN_ALERT "registering FAILED!\n");
                                    unregister_chrdev_region(devno,ch);
                                    return 0;
                  }
}

Exit

static void mygpio_exit(void)
{
                  printk(KERN_ALERT "Goodbye, cruel world\n");
                  unregister_chrdev_region(devno,ch); // skal den ikke være i cleanup func?
                  cdev_del(&my_cdev);
                  gpio_free(GPIO);
}

Open

int mygpio_open(struct inode *inode, struct file *file)
{
                  int major, minor;
                  major = MAJOR(inode->i_rdev);
                  minor = MINOR(inode->i_rdev);
                  printk("Opening MyGpio Device [major], [minor]: %i, %i\n", major, minor);
                  return 0;
}

Release

int mygpio_release(struct inode *inode, struct file *file)
{
                  int minor, major;
                    
                  major = MAJOR(inode->i_rdev);
                  minor = MINOR(inode->i_rdev);
                  return 0;
}

Write

ssize_t mygpio_write(struct file *filep, const char __user *ubuf, size_t count, loff_t *f_pos)
{
 int minor, len, scanValue;
 char kbuf[MAXLEN];


 minor = MINOR(filep->f_dentry->d_inode->i_rdev);

 if(count < MAXLEN)
   len = count;
 else
   len = MAXLEN;

 copy_from_user(kbuf, ubuf, len);
 kbuf[len]= '\0';

 sscanf(kbuf, "%d",&scanValue);

 gpio_set_value(GPIO, scanValue);

 // Hvilke trin er det der skal udføres?
 // Hint konvertering fra string til int kan gøres via sscanf() - antagelsen er at det er strenge der sendes til og fra user space. Det debugging lettere.
*f_pos += count;
 return count;
}


module_init(mygpio_init);
module_exit(mygpio_exit);




No comments:

Post a Comment