Fakultas Ilmu Komputer UI
Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
Ardhi Putra Pratama
teaching
Commits
05274182
Commit
05274182
authored
Nov 17, 2017
by
Ardhi Putra Pratama
Browse files
renaming, commenting stuffs
parent
14c3c7f2
Changes
2
Hide whitespace changes
Inline
Side-by-side
sys-programming/dev-driver/Makefile
View file @
05274182
obj-m
+=
lkm-drivers
.o
obj-m
+=
rd_devdr
.o
all
:
make
-C
/lib/modules/
$(
shell
uname
-r
)
/build/
M
=
$(PWD)
modules
...
...
sys-programming/dev-driver/
lkm-drivers
.c
→
sys-programming/dev-driver/
rd_devdr
.c
View file @
05274182
#include
<linux/init.h>
// Macros used to mark up functions e.g. __init __exit
#include
<linux/module.h>
// Core header for loading LKMs into the kernel
#include
<linux/device.h>
// Header to support the kernel Driver Model
#include
<linux/kernel.h>
// Contains types, macros, functions for the kernel
#include
<linux/fs.h>
// Header for the Linux file system support
#include
<asm/uaccess.h>
// Required for the copy to user function
#define DEVICE_NAME "rdc
hardrv
" //
/
< The device will appear at /dev/rdchardrv using this
value
#define CLASS_NAME "rdc" //
/<
The device class
-- this is a character device driver
MODULE_LICENSE
(
"GPL"
);
///< The license type -- this affects available functionality
MODULE_AUTHOR
(
"Ardhi Putra Pratama"
);
///< The author -- visible when you use modinfo
MODULE_DESCRIPTION
(
"A simple Linux char driver"
);
///< The description -- see modinfo
MODULE_VERSION
(
"0.1"
);
///< A version number to inform users
static
int
majorNumber
;
///< Stores the device number -- determined automatically
static
char
message
[
256
]
=
{
0
};
///< Memory for the string that is passed from userspace
static
short
size_of_message
;
///< Used to remember the size of the string stored
static
int
numberOpens
=
0
;
///< Counts the number of times the device is opened
static
struct
class
*
classptr
=
NULL
;
///< The device-driver class struct pointer
static
struct
device
*
dvcptr
=
NULL
;
///< The device-driver device struct pointer
#include
<linux/init.h>
#include
<linux/module.h>
#include
<linux/device.h>
#include
<linux/kernel.h>
#include
<linux/fs.h>
#include
<asm/uaccess.h>
#define DEVICE_NAME "rdc
devdr
" //
/dev/<
value
>
#define CLASS_NAME "rdc" // The device class
MODULE_LICENSE
(
"GPL"
);
MODULE_AUTHOR
(
"Ardhi Putra Pratama"
);
MODULE_DESCRIPTION
(
"A simple Linux char driver"
);
MODULE_VERSION
(
"0.1"
);
static
int
majorNumber
;
static
char
message
[
256
]
=
{
0
};
static
short
size_of_message
;
static
int
numberOpens
=
0
;
static
struct
class
*
classptr
=
NULL
;
static
struct
device
*
dvcptr
=
NULL
;
// The prototype functions for the character driver
static
int
dev_open
(
struct
inode
*
,
struct
file
*
);
...
...
@@ -36,16 +36,16 @@ static struct file_operations fops =
};
static
int
__init
rdc
har
dr
v
_init
(
void
){
printk
(
KERN_INFO
"RD
-Char Device
: Initializing the RD
-Char Device LKM
\n
"
);
static
int
__init
rdc
dev
dr_init
(
void
){
printk
(
KERN_INFO
"RD
cdevdr
: Initializing the RD
cdevdr module
\n
"
);
// Try to dynamically allocate a major number for the device
-- more difficult but worth it
// Try to dynamically allocate a major number for the device
majorNumber
=
register_chrdev
(
0
,
DEVICE_NAME
,
&
fops
);
if
(
majorNumber
<
0
){
printk
(
KERN_ALERT
"RD
-Char Device
failed to register a major number
\n
"
);
printk
(
KERN_ALERT
"RD
cdevdr
failed to register a major number
\n
"
);
return
majorNumber
;
}
printk
(
KERN_INFO
"RD
-Char Device
: registered correctly with major number %d
\n
"
,
majorNumber
);
printk
(
KERN_INFO
"RD
cdevdr
: registered correctly with major number %d
\n
"
,
majorNumber
);
// Register the device class
classptr
=
class_create
(
THIS_MODULE
,
CLASS_NAME
);
...
...
@@ -54,61 +54,47 @@ static int __init rdchardrv_init(void){
printk
(
KERN_ALERT
"Failed to register device class
\n
"
);
return
PTR_ERR
(
classptr
);
// Correct way to return an error on a pointer
}
printk
(
KERN_INFO
"RD
-Char Device
: device class registered correctly
\n
"
);
printk
(
KERN_INFO
"RD
cdevdr
: device class registered correctly
\n
"
);
// Register the device driver
dvcptr
=
device_create
(
classptr
,
NULL
,
MKDEV
(
majorNumber
,
0
),
NULL
,
DEVICE_NAME
);
if
(
IS_ERR
(
dvcptr
)){
// Clean up if there is an error
class_destroy
(
classptr
);
// Repeated code but the alternative is goto statements
if
(
IS_ERR
(
dvcptr
)){
class_destroy
(
classptr
);
unregister_chrdev
(
majorNumber
,
DEVICE_NAME
);
printk
(
KERN_ALERT
"Failed to create the device
\n
"
);
return
PTR_ERR
(
dvcptr
);
}
printk
(
KERN_INFO
"RD-Char Device: device class created correctly
\n
"
);
// Made it! device was initialized
// Successfully registered both
printk
(
KERN_INFO
"RDcdevdr: device class created correctly
\n
"
);
return
0
;
}
static
void
__exit
rdc
har
dr
v
_exit
(
void
){
static
void
__exit
rdc
dev
dr_exit
(
void
){
device_destroy
(
classptr
,
MKDEV
(
majorNumber
,
0
));
// remove the device
class_unregister
(
classptr
);
// unregister the device class
class_destroy
(
classptr
);
// remove the device class
unregister_chrdev
(
majorNumber
,
DEVICE_NAME
);
// unregister the major number
printk
(
KERN_INFO
"RD
-Char Device
: Goodbye from the LKM!
\n
"
);
printk
(
KERN_INFO
"RD
cdevdr
: Goodbye from the LKM!
\n
"
);
}
static
int
dev_open
(
struct
inode
*
inodep
,
struct
file
*
filep
){
numberOpens
++
;
printk
(
KERN_INFO
"RD
-Char Device
: Device has been opened %d time(s)
\n
"
,
numberOpens
);
printk
(
KERN_INFO
"RD
cdevdr
: Device has been opened %d time(s)
\n
"
,
numberOpens
);
return
0
;
}
// static ssize_t dev_read(struct file *filep, char *buffer, size_t len, loff_t *offset){
// int error_count = 0;
// // copy_to_user has the format ( * to, *from, size) and returns 0 on success
// error_count = copy_to_user(buffer, message, size_of_message);
//
// if (error_count==0){ // if true then have success
// printk(KERN_INFO "RD-Char Device: Sent %d characters to the user\n", size_of_message);
// return (size_of_message=0); // clear the position to the start and return 0
// }
// else {
// printk(KERN_INFO "RD-Char Device: Failed to send %d characters to the user\n", error_count);
// return -EFAULT; // Failed -- return a bad address message (i.e. -14)
// }
// }
static
ssize_t
dev_read
(
struct
file
*
filep
,
char
*
buffer
,
size_t
len
,
loff_t
*
offset
){
//Always return size_of_message or len bytes, whichever is less
size_t
bytesToCopy
=
len
>=
size_of_message
?
size_of_message
:
len
;
size_t
bytesNotCopied
=
0
;
//If size_of_message == 0, do nothing and return zero.
if
(
!
bytesToCopy
)
return
0
;
bytesNotCopied
=
copy_to_user
(
buffer
,
message
,
bytesToCopy
);
if
(
bytesToCopy
-
bytesNotCopied
)
printk
(
KERN_INFO
"RD
-Char Device
: Sent %d characters to the user
\n
"
,
bytesToCopy
-
bytesNotCopied
);
printk
(
KERN_INFO
"RD
cdevdr
: Sent %d characters to the user
\n
"
,
bytesToCopy
-
bytesNotCopied
);
if
(
bytesNotCopied
){
printk
(
KERN_INFO
"RD
-Char Device
: Failed to send %d characters to the user
\n
"
,
bytesNotCopied
);
printk
(
KERN_INFO
"RD
cdevdr
: Failed to send %d characters to the user
\n
"
,
bytesNotCopied
);
return
-
EFAULT
;
}
size_of_message
=
0
;
...
...
@@ -116,36 +102,30 @@ static ssize_t dev_read(struct file *filep, char *buffer, size_t len, loff_t *of
}
static
ssize_t
dev_write
(
struct
file
*
filep
,
const
char
*
buffer
,
size_t
len
,
loff_t
*
offset
){
/* 14 is the max length of the output of sprintf() below,
and we take one more byte out of maxLen to leave room
for the terminating NULL-character. */
/* 14 "()letters 1234"
* 1 -> terminating NULL
*
*/
const
size_t
maxLen
=
256
-
14
-
1
;
size_t
bytesToCopy
=
len
>=
maxLen
?
maxLen
:
len
;
//
If len is 255 or more, copy only 255 bytes
size_t
bytesToCopy
=
len
>=
maxLen
?
maxLen
:
len
;
//
only copy as max as possible
size_t
bytesNotCopied
=
0
;
bytesNotCopied
=
copy_from_user
(
message
,
buffer
,
bytesToCopy
);
sprintf
(
message
+
bytesToCopy
-
bytesNotCopied
,
"(%zu letters)"
,
bytesToCopy
-
bytesNotCopied
);
size_of_message
=
bytesToCopy
-
bytesNotCopied
+
1
;
printk
(
KERN_INFO
"RD
-Char Device
: Received %zu characters from the user
\n
"
,
bytesToCopy
-
bytesNotCopied
);
printk
(
KERN_INFO
"RD
cdevdr
: Received %zu characters from the user
\n
"
,
bytesToCopy
-
bytesNotCopied
);
if
(
bytesNotCopied
){
printk
(
KERN_INFO
"RD
-Char Device
: Failed to receive %zu characters, -EFAULT!
\n
"
,
bytesNotCopied
);
printk
(
KERN_INFO
"RD
cdevdr
: Failed to receive %zu characters, -EFAULT!
\n
"
,
bytesNotCopied
);
return
-
EFAULT
;
}
return
bytesToCopy
;
}
// static ssize_t dev_write(struct file *filep, const char *buffer, size_t len, loff_t *offset){
// sprintf(message, "%s(%zu letters)", buffer, len); // appending received string with its length
// size_of_message = strlen(message); // store the length of the stored message
// printk(KERN_INFO "RD-Char Device: Received %zu characters from the user\n", len);
// return len;
// }
static
int
dev_release
(
struct
inode
*
inodep
,
struct
file
*
filep
){
printk
(
KERN_INFO
"RD
-Char Device
: Device successfully closed
\n
"
);
printk
(
KERN_INFO
"RD
cdevdr
: Device successfully closed
\n
"
);
return
0
;
}
module_init
(
rdc
har
dr
v
_init
);
module_exit
(
rdc
har
dr
v
_exit
);
module_init
(
rdc
dev
dr_init
);
module_exit
(
rdc
dev
dr_exit
);
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment