forked from PacktPublishing/Linux-Device-Drivers-Development
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
68 changed files
with
4,616 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
obj-m := helloworld-params.o helloworld.o | ||
|
||
KERNELDIR ?= /lib/modules/$(shell uname -r)/build | ||
|
||
all default: modules | ||
install: modules_install | ||
|
||
modules modules_install help clean: | ||
$(MAKE) -C $(KERNELDIR) M=$(shell pwd) $@ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
# Helloworld drivers | ||
|
||
After running `make` command, there will be two modules: | ||
|
||
* helloworld.ko | ||
* helloworld-params.ko | ||
|
||
The fist module is basic helloworld driver, the second one is the same, but | ||
accepts some parameters, and print these in the kernel debug messages. | ||
After loading the first module, two entries will be added in kernel debug message: | ||
|
||
```bash | ||
# insmod ./helloworld.ko | ||
#dmesg | ||
[...] | ||
[38535.487568] Hello world! | ||
[38542.391099] End of the world | ||
``` | ||
|
||
For the second module, one loads it with: | ||
|
||
```bash | ||
# insmod ./helloworld-params.ko | ||
``` | ||
|
||
If no parameters are provided, the defaults will be used: | ||
|
||
```bash | ||
$ dmesg | ||
[...] | ||
[37858.595126] Hello world with parameters! | ||
[37858.595129] The *mystr* parameter: hello | ||
[37858.595130] The *myint* parameter: 1 | ||
[37858.595131] The *myarr* parameter: 0, 1, 2 | ||
[37887.232643] End of the world | ||
``` | ||
|
||
When parameters are provided, the will be printed | ||
|
||
|
||
```bash | ||
# insmod ./helloworld-params.ko mystr="packtpub" myint=255 myarr=23,4,7 | ||
# dmesg | ||
[...] | ||
[37892.417968] Hello world with parameters! | ||
[37892.417970] The *mystr* parameter: packtpub | ||
[37892.417971] The *myint* parameter: 255 | ||
[37892.417972] The *myarr* parameter: 23, 4, 7 | ||
[37895.222808] End of the world | ||
|
||
``` | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
#include <linux/init.h> | ||
#include <linux/module.h> | ||
#include <linux/kernel.h> | ||
#include <linux/moduleparam.h> | ||
|
||
static char *mystr = "hello"; | ||
static int myint = 1; | ||
static int myarr[3] = {0, 1, 2}; | ||
|
||
|
||
module_param(myint, int, S_IRUGO); | ||
module_param(mystr, charp, S_IRUGO); | ||
module_param_array(myarr, int,NULL, S_IWUSR|S_IRUSR); | ||
|
||
MODULE_PARM_DESC(myint,"this is my int variable"); | ||
MODULE_PARM_DESC(mystr,"this is my char pointer variable"); | ||
MODULE_PARM_DESC(myarr,"this is my array of int"); | ||
MODULE_INFO(my_field_name, "What eeasy value"); | ||
|
||
static int __init hellowolrd_init(void) { | ||
pr_info("Hello world with parameters!\n"); | ||
pr_info("The *mystr* parameter: %s\n", mystr); | ||
pr_info("The *myint* parameter: %d\n", myint); | ||
pr_info("The *myarr* parameter: %d, %d, %d\n", myarr[0], myarr[1], myarr[2]); | ||
return 0; | ||
} | ||
|
||
static void __exit hellowolrd_exit(void) { | ||
pr_info("End of the world\n"); | ||
} | ||
|
||
module_init(hellowolrd_init); | ||
module_exit(hellowolrd_exit); | ||
MODULE_AUTHOR("John Madieu <john.madieu@gmail.com>"); | ||
MODULE_LICENSE("GPL"); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
#include <linux/init.h> | ||
#include <linux/module.h> | ||
#include <linux/kernel.h> | ||
|
||
static int __init hellowolrd_init(void) { | ||
pr_info("Hello world!\n"); | ||
return 0; | ||
} | ||
|
||
static void __exit hellowolrd_exit(void) { | ||
pr_info("End of the world\n"); | ||
} | ||
|
||
module_init(hellowolrd_init); | ||
module_exit(hellowolrd_exit); | ||
MODULE_AUTHOR("John Madieu <john.madieu@gmail.com>"); | ||
MODULE_LICENSE("GPL"); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
obj-m := dedicated-workqueue.o hr-timer.o shared-workqueue.o std-timer.o tasklet.o user-invoke.o waitqueue.o | ||
|
||
KERNELDIR ?= /lib/modules/$(shell uname -r)/build | ||
|
||
all default: modules | ||
install: modules_install | ||
|
||
modules modules_install help clean: | ||
$(MAKE) -C $(KERNELDIR) M=$(shell pwd) $@ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
#include <linux/init.h> | ||
#include <linux/module.h> | ||
#include <linux/workqueue.h> /* for work queue */ | ||
#include <linux/slab.h> /* for kmalloc() */ | ||
|
||
struct workqueue_struct *wq; | ||
|
||
struct work_data { | ||
struct work_struct my_work; | ||
int the_data; | ||
}; | ||
|
||
static void work_handler(struct work_struct *work) | ||
{ | ||
struct work_data * my_data = container_of(work, struct work_data, my_work); | ||
pr_info("Work queue module handler: %s, data is %d\n", | ||
__FUNCTION__, my_data->the_data); | ||
kfree(my_data); | ||
} | ||
|
||
static int __init my_init(void) | ||
{ | ||
struct work_data * my_data; | ||
|
||
pr_info("Work queue module init: %s %d\n", __FUNCTION__, __LINE__); | ||
wq = create_singlethread_workqueue("my_single_thread"); | ||
my_data = kmalloc(sizeof(struct work_data), GFP_KERNEL); | ||
|
||
my_data->the_data = 34; | ||
|
||
INIT_WORK(&my_data->my_work, work_handler); | ||
queue_work(wq, &my_data->my_work); | ||
|
||
return 0; | ||
} | ||
|
||
static void __exit my_exit(void) | ||
{ | ||
flush_workqueue(wq); | ||
destroy_workqueue(wq); | ||
pr_info("Work queue module exit: %s %d\n", __FUNCTION__, __LINE__); | ||
} | ||
|
||
module_init(my_init); | ||
module_exit(my_exit); | ||
MODULE_LICENSE("GPL"); | ||
MODULE_AUTHOR("John Madieu <john.madieu@gmail.com>"); | ||
MODULE_DESCRIPTION("Dedicated workqueue example"); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
#include <linux/init.h> | ||
#include <linux/kernel.h> | ||
#include <linux/module.h> | ||
#include <linux/hrtimer.h> | ||
#include <linux/ktime.h> | ||
|
||
#define MS_TO_NS(x) (x * 1E6L) | ||
|
||
static struct hrtimer hr_timer; | ||
|
||
enum hrtimer_restart my_hrtimer_callback( struct hrtimer *timer ) | ||
{ | ||
pr_info( "my_hrtimer_callback called (%ld).\n", jiffies ); | ||
return HRTIMER_NORESTART; | ||
} | ||
|
||
static int hrt_init_module( void ) | ||
{ | ||
ktime_t ktime; | ||
unsigned long delay_in_ms = 200L; | ||
|
||
pr_info("HR Timer module installing\n"); | ||
|
||
/* | ||
* ktime = ktime_set(0, 200 * 1000 * 1000); | ||
* 200 ms = 10 * 1000 * 1000 ns | ||
*/ | ||
ktime = ktime_set( 0, MS_TO_NS(delay_in_ms) ); | ||
|
||
hrtimer_init( &hr_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL ); | ||
hr_timer.function = &my_hrtimer_callback; | ||
pr_info( "Starting timer to fire in %ldms (%ld)\n", \ | ||
delay_in_ms, jiffies ); | ||
|
||
hrtimer_start( &hr_timer, ktime, HRTIMER_MODE_REL ); | ||
return 0; | ||
} | ||
|
||
static void hrt_cleanup_module( void ) | ||
{ | ||
int ret; | ||
ret = hrtimer_cancel( &hr_timer ); | ||
if (ret) | ||
pr_info("The timer was still in use...\n"); | ||
|
||
pr_info("HR Timer module uninstalling\n"); | ||
return; | ||
} | ||
|
||
module_init(hrt_init_module); | ||
module_exit(hrt_cleanup_module); | ||
MODULE_LICENSE("GPL"); | ||
MODULE_AUTHOR("John Madieu <john.madieu@gmail.com>"); | ||
MODULE_DESCRIPTION("Standard timer example"); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
#include <linux/module.h> | ||
#include <linux/init.h> | ||
#include <linux/sched.h> /* for sleep */ | ||
#include <linux/wait.h> /* for wait queue */ | ||
#include <linux/time.h> | ||
#include <linux/delay.h> | ||
#include <linux/slab.h> /* for kmalloc() */ | ||
#include <linux/workqueue.h> | ||
|
||
//static DECLARE_WAIT_QUEUE_HEAD(my_wq); | ||
static int sleep = 0; | ||
|
||
struct work_data { | ||
struct work_struct my_work; | ||
wait_queue_head_t my_wq; | ||
int the_data; | ||
}; | ||
|
||
static void work_handler(struct work_struct *work) | ||
{ | ||
struct work_data *my_data = container_of(work, \ | ||
struct work_data, my_work); | ||
pr_info("Work queue module handler: %s, data is %d\n", __FUNCTION__, my_data->the_data); | ||
msleep(3000); | ||
wake_up_interruptible(&my_data->my_wq); | ||
kfree(my_data); | ||
} | ||
|
||
static int __init my_init(void) | ||
{ | ||
struct work_data * my_data; | ||
|
||
my_data = kmalloc(sizeof(struct work_data), GFP_KERNEL); | ||
my_data->the_data = 34; | ||
|
||
INIT_WORK(&my_data->my_work, work_handler); | ||
init_waitqueue_head(&my_data->my_wq); | ||
|
||
schedule_work(&my_data->my_work); | ||
pr_info("I'm goint to sleep ...\n"); | ||
wait_event_interruptible(my_data->my_wq, sleep != 0); | ||
pr_info("I am Waked up...\n"); | ||
return 0; | ||
} | ||
|
||
static void __exit my_exit(void) | ||
{ | ||
pr_info("Work queue module exit: %s %d\n", __FUNCTION__, __LINE__); | ||
} | ||
|
||
module_init(my_init); | ||
module_exit(my_exit); | ||
MODULE_LICENSE("GPL"); | ||
MODULE_AUTHOR("John Madieu <john.madieu@gmail.com> "); | ||
MODULE_DESCRIPTION("Shared workqueue"); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
#include <linux/init.h> | ||
#include <linux/kernel.h> | ||
#include <linux/module.h> | ||
#include <linux/timer.h> | ||
|
||
static struct timer_list my_timer; | ||
|
||
void my_timer_callback( unsigned long data ) | ||
{ | ||
pr_info( "%s called (%ld).\n", __FUNCTION__, jiffies ); | ||
} | ||
|
||
static int __init my_init( void ) | ||
{ | ||
int retval; | ||
pr_info("Timer module loaded\n"); | ||
|
||
setup_timer( &my_timer, my_timer_callback, 0 ); | ||
pr_info( "Setup timer to fire in 300ms (%ld)\n", jiffies ); | ||
|
||
retval = mod_timer( &my_timer, jiffies + msecs_to_jiffies(300) ); | ||
if (retval) | ||
pr_info("Timer firing failed\n"); | ||
|
||
return 0; | ||
} | ||
|
||
static void my_exit( void ) | ||
{ | ||
int retval; | ||
retval = del_timer( &my_timer ); | ||
if (retval) | ||
pr_info("The timer is still in use...\n"); | ||
|
||
pr_info("Timer module unloaded\n"); | ||
return; | ||
} | ||
|
||
module_init(my_init); | ||
module_exit(my_exit); | ||
MODULE_AUTHOR("John Madieu <john.madieu@gmail.com>"); | ||
MODULE_DESCRIPTION("Standard timer example"); | ||
MODULE_LICENSE("GPL"); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
#include <linux/kernel.h> | ||
#include <linux/module.h> | ||
#include <linux/interrupt.h> /* for tasklets api */ | ||
|
||
char tasklet_data[]="We use a string; but it could be pointer to a structure"; | ||
|
||
/* Tasklet handler, that just print the data */ | ||
void tasklet_function( unsigned long data ) | ||
{ | ||
pr_info( "%s\n", (char *)data ); | ||
return; | ||
} | ||
|
||
DECLARE_TASKLET( my_tasklet, tasklet_function, (unsigned long) tasklet_data ); | ||
|
||
static int __init my_init( void ) | ||
{ | ||
/* Schedule the handler */ | ||
tasklet_schedule( &my_tasklet ); | ||
pr_info("tasklet example\n"); | ||
return 0; | ||
} | ||
|
||
void my_exit( void ) | ||
{ | ||
/* Stop the tasklet before we exit */ | ||
tasklet_kill( &my_tasklet ); | ||
pr_info("tasklet example cleanup\n"); | ||
return; | ||
} | ||
|
||
module_init(my_init); | ||
module_exit(my_exit); | ||
MODULE_AUTHOR("John Madieu <john.madieu@gmail.com>"); | ||
MODULE_LICENSE("GPL"); |
Oops, something went wrong.