CPAC+Øvelse+8+Timer

toc =Linux Device Driver med Timer= Tilføjer IOCTL understøttelse i. code format="c" struct file_operations mygpio_Fops = {   .owner   = THIS_MODULE, .open   = mygpio_open, .release = mygpio_release, .write  = mygpio_write, .read   = mygpio_read, .ioctl  = mygpio_ioctl, }; code

IOCTL Nummer
Tjekker ioctl-number.txt og ser at 0xF5 er fri. Ioctl numre er system globale så det er meget vigtigt ikke at tage et brugt nummer ellers giver det konflikter. Jeg bruger makroerne _IO (ingen parameter) og _IOW (skriv parameter i driver) fremfor at bare vælge nogle unikke værdier da det først og fremmest er god skik plus det gør debugging nemmere med fx. (5-simple-ways-to-troubleshoot-using-strace.html).

Denne header skal bruges af både kerne modulet og applikationen da de begge skal kende den unikke værdi. code format="c"
 * 1) include 

code
 * 1) define MYGPIO_IOC_MAGIC 0xF5
 * 2) define START_TIMER _IO(MYGPIO_IOC_MAGIC, 0)
 * 3) define STOP_TIMER _IO(MYGPIO_IOC_MAGIC, 1)
 * 4) define SET_FREQUENCY _IOW(MYGPIO_IOC_MAGIC, 2, unsigned int)

Implementer ioctl kald
code format="c"
 * 1) include "ioctl_nr.h"
 * 2) include 
 * 3) include 

struct timer_list my_timer; static unsigned int timeout_in_sec = 1;

ssize_t mygpio_ioctl(struct inode *inode, struct file *filep,                          unsigned int cmd, unsigned long arg) {	int minor = MINOR(filep->f_dentry->d_inode->i_rdev); switch (cmd) {	case START_TIMER: printk(KERN_NOTICE "Received ioctl-command: %d (START_TIMER)\n", cmd); init_timer(&my_timer); my_timer.expires = jiffies + timeout_in_sec * HZ; my_timer.data = minor; my_timer.function = timer_funct; add_timer(&my_timer); break; case STOP_TIMER: printk(KERN_NOTICE "Received ioctl-command: %d (STOP_TIMER)\n", cmd); del_timer(&my_timer); break; case SET_FREQUENCY: printk(KERN_NOTICE "Received ioctl-command: %d (SET_FREQUENCY)\n", cmd); timeout_in_sec = arg; break; default: printk(KERN_ALERT "Unknown ioctl-command: %d \n", cmd); break; }	return 0; } code

Timer funktion
code format="c" static void timer_funct(unsigned long funct_parameter) { // Re-schedule the timer my_timer.expires = jiffies + timeout_in_sec * HZ; my_timer.data = funct_parameter; my_timer.function = timer_funct; add_timer(&my_timer); gpio_set_value(gpio[funct_parameter].num, !gpio_get_value(gpio[funct_parameter].num)); } code er minor nummeret.

Applikation
code format="cpp"
 * 1) include "ioctl_nr.h"
 * 2) include
 * 3) include
 * 4) include 
 * 5) include 
 * 6) include 

using namespace std;

int main {	int fd;

fd = open("/dev/test", O_RDWR); printf("fd: %i\n", fd); printf("Sending START_TIMER\n"); ioctl(fd, START_TIMER); sleep(5); printf("Sending SET_FREQUENCY\n"); ioctl(fd, SET_FREQUENCY, 2); sleep(6); printf("Sending STOP_TIMER\n"); ioctl(fd, STOP_TIMER);

close(fd); return 0; } code