Fakultas Ilmu Komputer UI

Skip to content
Snippets Groups Projects
Commit 417fcd08 authored by rayhan muzakki's avatar rayhan muzakki
Browse files

push driver

parents
No related branches found
No related tags found
No related merge requests found
#include <linux/init.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
#include <alsa/asoundlib.h>
#include <alsa/mixer.h>
#define DEVICE_NAME "grpdrv" // /dev/<value>
#define CLASS_NAME "grp" // The device class
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Rayhan Muzakki");
MODULE_DESCRIPTION("My 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 *);
static int dev_release(struct inode *, struct file *);
static ssize_t dev_read(struct file *, char *, size_t, loff_t *);
static ssize_t dev_write(struct file *, const char *, size_t, loff_t *);
static struct file_operations fops =
{
.open = dev_open,
.read = dev_read,
.write = dev_write,
.release = dev_release,
.set = dev_set,
.mute = dev_mute,
.unmute = dev_unmute,
};
static int dev_open(struct inode *inodep, struct file *filep){
numberOpens++;
printk(KERN_INFO "GRPdrv: Device has been opened %d time(s)\n", numberOpens);
return 0;
}
static int dev_release(struct inode *inodep, struct file *filep){
printk(KERN_INFO "GRPdrv: Device successfully closed\n");
return 0;
}
static int __init rdchardrv_init(void){
majorNumber = register_chrdev(0, DEVICE_NAME, &fops);
if (majorNumber<0) return majorNumber;
// Register the device class
classptr = class_create(THIS_MODULE, CLASS_NAME);
if (IS_ERR(classptr)){
unregister_chrdev(majorNumber, DEVICE_NAME);
return PTR_ERR(classptr);
}
// Register the device driver
dvcptr = device_create(classptr, NULL, MKDEV(majorNumber, 0), NULL, DEVICE_NAME);
if (IS_ERR(dvcptr)){
class_destroy(classptr);
unregister_chrdev(majorNumber, DEVICE_NAME);
return PTR_ERR(dvcptr);
}
printk(KERN_INFO "GRPdrv: device class created correctly\n");
return 0;
}
static void __exit rdchardrv_exit(void){
device_destroy(classptr, MKDEV(majorNumber, 0));
class_unregister(classptr);
class_destroy(classptr);
unregister_chrdev(majorNumber, DEVICE_NAME);
printk(KERN_INFO "GRPdrv: Goodbye from the LKM!\n");
}
static ssize_t dev_read(struct file *filep, char *buffer, size_t len, loff_t *offset){
// precaution
size_t bytesToCopy = len >= size_of_message ? size_of_message: len;
size_t bytesNotCopied = 0;
if(!bytesToCopy) return 0;
bytesNotCopied = raw_copy_to_user(buffer, message,
bytesToCopy);
if(bytesNotCopied){
return -EFAULT;
}
size_of_message = 0;
return bytesToCopy;
}
static ssize_t dev_write(struct file *filep,
const char *buffer, size_t len, loff_t *offset){
const size_t maxLen = 256 - 1;
size_t bytesToCopy = len >= maxLen ? maxLen: len;
size_t bytesNotCopied = 0;
bytesNotCopied = raw_copy_from_user(message, buffer,bytesToCopy);
size_of_message = bytesToCopy - bytesNotCopied;
if(bytesNotCopied)
return -EFAULT;
return bytesToCopy;
}
static int dev_set(long volume){
long min, max;
snd_mixer_t *handle;
snd_mixer_selem_id_t *sid;
const char *card = "default";
const char *selem_name = "Master";
snd_mixer_open(&handle, 0);
snd_mixer_attach(handle, card);
snd_mixer_selem_register(handle, NULL, NULL);
snd_mixer_load(handle);
snd_mixer_selem_id_alloca(&sid);
snd_mixer_selem_id_set_index(sid, 0);
snd_mixer_selem_id_set_name(sid, selem_name);
snd_mixer_elem_t* elem = snd_mixer_find_selem(handle, sid);
snd_mixer_selem_get_playback_volume_range(elem, &min, &max);
snd_mixer_selem_set_playback_volume_all(elem, volume * max / 100);
snd_mixer_close(handle);
return 0;
}
static int dev_mute(){
long min, max;
snd_mixer_t *handle;
snd_mixer_selem_id_t *sid;
const char *card = "default";
const char *selem_name = "Master";
snd_mixer_open(&handle, 0);
snd_mixer_attach(handle, card);
snd_mixer_selem_register(handle, NULL, NULL);
snd_mixer_load(handle);
snd_mixer_selem_id_alloca(&sid);
snd_mixer_selem_id_set_index(sid, 0);
snd_mixer_selem_id_set_name(sid, selem_name);
snd_mixer_elem_t* elem = snd_mixer_find_selem(handle, sid);
if (snd_mixer_selem_has_playback_switch(elem)) {
snd_mixer_selem_set_playback_switch_all(elem, 0);
}
snd_mixer_close(handle);
return 0
}
static int dev_unmute(){
long min, max;
snd_mixer_t *handle;
snd_mixer_selem_id_t *sid;
const char *card = "default";
const char *selem_name = "Master";
snd_mixer_open(&handle, 0);
snd_mixer_attach(handle, card);
snd_mixer_selem_register(handle, NULL, NULL);
snd_mixer_load(handle);
snd_mixer_selem_id_alloca(&sid);
snd_mixer_selem_id_set_index(sid, 0);
snd_mixer_selem_id_set_name(sid, selem_name);
snd_mixer_elem_t* elem = snd_mixer_find_selem(handle, sid);
if (snd_mixer_selem_has_playback_switch(elem)) {
snd_mixer_selem_set_playback_switch_all(elem, 1);
}
snd_mixer_close(handle);
return 0
}
module_init(rdchardrv_init);
module_exit(rdchardrv_exit);
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment