2021年9月7日 星期二
2020年12月25日 星期五
關掉 uart 的功能
要求關掉 uart 的功能,
簡單追一下 kernel code
發現應該可以從userspace改,結果…不如預其
code: copy form here
platform_device是在 /sys/devices/,
因沒有 grep,這樣範圍太大
後來再 /sys/class/tty,有找到ttyHSL0
有個軟連結 device,就能連到目標/sys/devices/soc/78af000.serial,
也找到 console 了,可以 RW,
但, echo 0 > consle 後,就當機了...
只能換個暴力的方法了...
簡單追一下 kernel code
發現應該可以從userspace改,結果…不如預其
code: copy form here
/* show_msm_console - provide per-port serial console state. */ static ssize_t show_msm_console(struct device *dev, struct device_attribute *attr, char *buf) { int enable; struct uart_port *port; struct platform_device *pdev = to_platform_device(dev); port = get_port_from_line(get_line(pdev)); enable = get_console_state(port); return snprintf(buf, sizeof(enable), "%d\n", enable); } /* * set_msm_console - allow to enable/disable serial console on port. * * writing 1 enables serial console on UART port. * writing 0 disables serial console on UART port. */ static ssize_t set_msm_console(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int enable, cur_state; struct uart_port *port; struct platform_device *pdev = to_platform_device(dev); port = get_port_from_line(get_line(pdev)); cur_state = get_console_state(port); enable = buf[0] - '0'; if (enable == cur_state) return count; switch (enable) { case 0: pr_debug("Calling stop_console\n"); console_stop(port->cons); pr_debug("Calling unregister_console\n"); unregister_console(port->cons); pm_runtime_put_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); /* * Disable UART Core clk * 3 - to disable the UART clock * Thid parameter is not used here, but used in serial core. */ msm_hsl_power(port, 3, 1); break; case 1: pr_debug("Calling register_console\n"); /* * Disable UART Core clk * 0 - to enable the UART clock * Thid parameter is not used here, but used in serial core. */ msm_hsl_power(port, 0, 1); pm_runtime_enable(&pdev->dev); register_console(port->cons); break; default: return -EINVAL; } return count; } static DEVICE_ATTR(console, S_IWUSR | S_IRUGO, show_msm_console, set_msm_console);
因沒有 grep,這樣範圍太大
後來再 /sys/class/tty,有找到ttyHSL0
有個軟連結 device,就能連到目標/sys/devices/soc/78af000.serial,
也找到 console 了,可以 RW,
但, echo 0 > consle 後,就當機了...
只能換個暴力的方法了...
標籤:
Linux Driver
2020年12月24日 星期四
2020年6月17日 星期三
Upgrade kernel version
- Use the apt manager to update the kernel 。Search the specific kernel version and headers:
$ sudo apt-cache search linux-image-*
$ sudo apt-cache search linux-headers-*
。After installing the specific kernel, update the Grub2
$ sudo update-grub
sudo apt install fakeroot build-essential ncurses-dev xz-utils libssl-dev bc flex libelf-dev bison -y
。config
$ uname -a
$ sudo cp /boot/config-$(uname -r) .config
or
$ cp arch/x86/configs/x86_64_defconfig .config
$ make menuconfig
$ make savedefconfig
。build code and install the new kernel
$ make -j8
$ make modules -j8
$ sudo make modules_install
$ sudo make install
。After installing the specific kernel, update the Grub2$ sudo update-grub
1. BTF: .tmp_vmlinux.btf: pahole (pahole) is not available
$ sudo apt install dwarves
2. /bin/sh: zstd: command not found
$ sudo apt install zstd
3. CONFIG_MODULE_SIG_KEY="cert/xxxtest.pem"
in Kernel_path/
$ openssl req -x509 -newkey rsa:4096 -keyout certs/xxxtest.pem -out certs/xxxtest.pem -nodes -days 3650
標籤:
Linux Driver
2020年5月11日 星期一
usb
cat /sys/bus/usb/
kernel給的訊息會有點像是usb device插拔的訊息,所以可能是跟suspend & wake up有關
雖然不知道為何在3.18還有碰到這問題,但就朝這方面解決
The article is COPY from Here
What is Remote Wakeup?
When a device has been suspended, it generally doesn’t resume until the computer tells it to. Likewise, if the entire computer has been suspended, it generally doesn’t resume until the user tells it to, say by pressing a power button or opening the cover.
However some devices have the capability of resuming by themselves, or asking the kernel to resume them, or even telling the entire computer to resume. This capability goes by several names such as “Wake On LAN”; we will refer to it generically as “remote wakeup”. When a device is enabled for remote wakeup and it is suspended, it may resume itself (or send a request to be resumed) in response to some external event. Examples include a suspended keyboard resuming when a key is pressed, or a suspended USB hub resuming when a device is plugged in.
lsusb -v | grep -i "remote wakeup"
The article is COPY from Here
When is a USB device idle?
A device is idle whenever the kernel thinks it’s not busy doing anything important and thus is a candidate for being suspended. The exact definition depends on the device’s driver; drivers are allowed to declare that a device isn’t idle even when there’s no actual communication taking place. (For example, a hub isn’t considered idle unless all the devices plugged into that hub are already suspended.) In addition, a device isn’t considered idle so long as a program keeps its usbfs file open, whether or not any I/O is going on.
If a USB device has no driver, its usbfs file isn’t open, and it isn’t being accessed through sysfs, then it definitely is idle.
kernel給的訊息會有點像是usb device插拔的訊息,所以可能是跟suspend & wake up有關
雖然不知道為何在3.18還有碰到這問題,但就朝這方面解決
The article is COPY from Here
What is Remote Wakeup?
When a device has been suspended, it generally doesn’t resume until the computer tells it to. Likewise, if the entire computer has been suspended, it generally doesn’t resume until the user tells it to, say by pressing a power button or opening the cover.
However some devices have the capability of resuming by themselves, or asking the kernel to resume them, or even telling the entire computer to resume. This capability goes by several names such as “Wake On LAN”; we will refer to it generically as “remote wakeup”. When a device is enabled for remote wakeup and it is suspended, it may resume itself (or send a request to be resumed) in response to some external event. Examples include a suspended keyboard resuming when a key is pressed, or a suspended USB hub resuming when a device is plugged in.
lsusb -v | grep -i "remote wakeup"
The article is COPY from Here
When is a USB device idle?
A device is idle whenever the kernel thinks it’s not busy doing anything important and thus is a candidate for being suspended. The exact definition depends on the device’s driver; drivers are allowed to declare that a device isn’t idle even when there’s no actual communication taking place. (For example, a hub isn’t considered idle unless all the devices plugged into that hub are already suspended.) In addition, a device isn’t considered idle so long as a program keeps its usbfs file open, whether or not any I/O is going on.
If a USB device has no driver, its usbfs file isn’t open, and it isn’t being accessed through sysfs, then it definitely is idle.
ref:
標籤:
Linux Driver
2019年12月16日 星期一
create a folder in /sys with kobject and read/write files in user space from kernel space
Create a file of sn and foo in /sys/abcd/efg/ijk/
#include <linux/kobject.h>
#include <linux/string.h>
#include <linux/sysfs.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/module.h>
#define BUF_LEN 16*2
#define PATH "/home/quiet/abcd/abc.txt"
static int foo;
struct kobject *sn_kobj;
struct kobj_attribute *sn_attr;
static char sn[BUF_LEN]= {0};
static int read_file (void)
{
int ret=0, i=0;
loff_t pos;
char buff[BUF_LEN]= {0};
unsigned char empty[16];
struct file *fp;
fp = filp_open(PATH, O_RDONLY | O_CREAT, 0444);
if (IS_ERR(fp))
{
printk(KERN_ERR "Cannot open the file-1 %ld\n, Nice", PTR_ERR(fp));
return -ENOENT;
}
pos = fp->f_pos;
ret=kernel_read(fp, buff, BUF_LEN, &pos); //work on kernel 4.1.5
//ret=kernel_read(fp, pos, buff, BUF_LEN); //work on kernel 4.9
if(ret == BUF_LEN)
{
buff[BUF_LEN-1]='\0';
}
else if (ret < 0)
{
printk(KERN_ERR "reading data has issue");
return -EINVAL;
}
else
{
buff[strlen(buff)]='\0';
}
memcpy(sn, buff, strlen(buff));
filp_close(fp, NULL);
return 0;
}
static int write_file (void)
{
int ret=0;
loff_t pos;
char buff[BUF_LEN]= {0};
struct file *fp;
struct AES_ctx ctx;
fp = filp_open(PATH, O_WRONLY | O_TRUNC, 0644);
if (IS_ERR(fp))
{
printk(KERN_ERR "Cannot open the file-3 %ld\n", PTR_ERR(fp));
return -ENOENT;
}
pos = fp->f_pos;
memcpy(buff, sn, strlen(sn));
if (kernel_write(fp, buff, strlen(buff), &pos)) //work on kernel 4.1.5
//if (kernel_write(fp, buff, strlen(buff), pos)) //wrok on kernel 4.9
{
//nothing to do
ret=0;
}
else
{
printk(KERN_ERR "writing data has issue");
ret = -EINVAL;
}
filp_close(fp, NULL);
return ret;
}
static ssize_t foo_show(struct kobject *kobj, struct kobj_attribute *attr,
char *buf)
{
printk(KERN_WARNING "Nice, foo_show-1");
return sprintf(buf, "%d\n", foo);
}
static ssize_t foo_store(struct kobject *kobj, struct kobj_attribute *attr,
const char *buf, size_t count)
{
int ret=0;
struct kernfs_node *dir_knode, *file_knode;
dir_knode = sn_kobj->sd;
file_knode = sysfs_get_dirent(dir_knode, sn_attr->attr.name);
if (strcmp("12345678", buf) == 0)
{
file_knode->mode = (file_knode->mode & S_IFMT) | 0666;
}
else
{
ret = kstrtoint(buf, BUF_LEN, &foo);
if (ret < 0)
return -EINVAL;
file_knode->mode = (file_knode->mode & S_IFMT) | 0444;
}
return count;
}
static struct kobj_attribute foo_attribute =
//__ATTR(foo1, 0664, foo_show, foo_store);
__ATTR(foo, S_IRUGO|S_IWUSR, foo_show, foo_store);
static ssize_t sn_show(struct kobject *kobj, struct kobj_attribute *attr,
char *buf)
{
sn_kobj=kobj;
sn_attr=attr;
return sprintf(buf, "%s\n", sn);
}
static ssize_t sn_store(struct kobject *kobj, struct kobj_attribute *attr,
const char *buf, size_t count)
{
struct kernfs_node *dir_knode, *file_knode;
dir_knode = kobj->sd;
file_knode = sysfs_get_dirent(dir_knode, attr->attr.name);
if (strcmp("87654321", buf) == 0)
{
file_knode->mode = (file_knode->mode & S_IFMT) | 0666;
}
else
{
memcpy(sn, buf, BUF_LEN);
file_knode->mode = (file_knode->mode & S_IFMT) | 0444;
}
return count;
}
static struct kobj_attribute sn_attribute =
//__ATTR(sn, 0444, sn_show, sn_store);
__ATTR(sn, S_IRUGO, sn_show, sn_store);
static struct attribute *attrs[] =
{
&sn_attribute.attr,
&foo_attribute.attr,
NULL, /* need to NULL terminate the list of attributes */
};
static struct attribute_group attr_group =
{
.attrs = attrs,
};
static struct kobject *init_kobj_abcd;
static struct kobject *init_kobj_efg;
static struct kobject *init_kobj_hij;
static int __init module_newera_init(void)
{
int retval=0;
printk(KERN_WARNING "module_ttt_init");
retval=read_file();
if (retval < 0)
goto err;
init_kobj_abcd = kobject_create_and_add("abcd", NULL);
if (!init_kobj_abcd)
return -ENOMEM;
init_kobj_efg = kobject_create_and_add("efg", init_kobj_monitor);
if (!init_kobj_efg)
return -ENOMEM;
init_kobj_hij = kobject_create_and_add("hij", init_kobj_usbport);
if (!init_kobj_hij)
return -ENOMEM;
/* Create the files associated with this kobject */
retval = sysfs_create_group(init_kobj_hij, &attr_group);
if (retval)
{
kobject_put(init_kobj_hij);
kobject_put(init_kobj_efg);
kobject_put(init_kobj_abcd);
}
err:
printk(KERN_WARNING "init retval=%d", retval);
return retval;
}
static void __exit module_newera_exit(void)
{
printk(KERN_WARNING "module_ttt_exit");
write_file();
kobject_put(init_kobj_hij);
kobject_put(init_kobj_efg);
kobject_put(init_kobj_abcd);
}
module_init(module_newera_init);
module_exit(module_newera_exit);
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Quiet<blue_quiet@gmail.com>");
標籤:
Linux Driver
2015年9月17日 星期四
create proc document
ref : Here
環境: kernel 3.13
test.c
環境: kernel 3.13
test.c
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/uaccess.h>
#include <linux/slab.h>
#define BUF_SIZE 128
// global var
static char *str = NULL;
// linux/seq_file.h
// void * (*start) (struct seq_file *m, loff_t *pos);
// void (*stop) (struct seq_file *m, void *v);
// void * (*next) (struct seq_file *m, void *v, loff_t *pos);
// int (*show) (struct seq_file *m, void *v);
/**
* author: aran
* fuction: seq_operations -> start
*/
static void *my_seq_start(struct seq_file *m, loff_t *pos)
{
if (0 == *pos)
{
++*pos;
return (void *)1; // return anything but NULL, just for test
}
return NULL;
}
/**
* author: aran
* fuction: seq_operations -> next
*/
static void *my_seq_next(struct seq_file *m, void *v, loff_t *pos)
{
// only once, so no next
return NULL;
}
/**
* author: aran
* fuction: seq_operations -> stop
*/
static void my_seq_stop(struct seq_file *m, void *v)
{
// clean sth.
// nothing to do
}
/**
* author: aran
* fuction: seq_operations -> show
*/
static int my_seq_show(struct seq_file *m, void *v)
{
char buf[BUF_SIZE];
int ret = 0;
ret = sprintf(buf, "current kernel time is %llu\n", (unsigned long long) get_jiffies_64());
ret += sprintf(buf + ret, "str is %s\n", str);
seq_printf(m, "%s", buf);
return 0; //!! must be 0, or will show nothing T.T
}
// global var
static struct seq_operations my_seq_fops =
{
.start = my_seq_start,
.next = my_seq_next,
.stop = my_seq_stop,
.show = my_seq_show,
};
// file_operations
// int (*open) (struct inode *, struct file *)
// ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *)
/**
* author: aran
* fuction: file_operations -> open
*/
static int proc_seq_open(struct inode *inode, struct file *file)
{
return seq_open(file, &my_seq_fops);
}
/**
* author: aran
* fuction: file_operations -> write
*/
static ssize_t proc_seq_write(struct file *file, const char __user *buffer, size_t count, loff_t *f_pos)
{
//分配临时缓冲区
char *tmp = kzalloc((count+1), GFP_KERNEL);
if (!tmp)
return -ENOMEM;
//将用户态write的字符串拷贝到内核空间
//copy_to|from_user(to,from,cnt)
if (copy_from_user(tmp, buffer, count))
{
kfree(tmp);
return -EFAULT;
}
//将str的旧空间释放,然后将tmp赋值给str
kfree(str);
str = tmp;
return count;
}
// global var
static struct file_operations proc_seq_fops =
{
.owner = THIS_MODULE,
.open = proc_seq_open,
.read = seq_read,
.write = proc_seq_write,
.llseek = seq_lseek,
.release = seq_release,
};
static int __init my_init(void)
{
struct proc_dir_entry *file;
// create "/proc/proc_seq" file
file = proc_create_data(
"jif", // name
0666, // mode
NULL, // parent dir_entry
&proc_seq_fops, // file_operations
NULL // data
);
if (NULL == file)
{
printk("Count not create /proc/jif file!\n");
return -ENOMEM;
}
return 0;
}
static void __exit my_exit(void)
{
remove_proc_entry("jif", NULL);
kfree(str);
}
module_init(my_init);
module_exit(my_exit);
MODULE_AUTHOR("aran");
MODULE_LICENSE("GPL");
Makefile
CONFIG_MODULE_SIG=n
PWD := $(shell pwd)
KVERSION := $(shell uname -r)
KERNEL_DIR = /usr/src/linux-headers-$(KVERSION)/
MODULE_NAME = test
obj-m := $(MODULE_NAME).o
all:
make -C $(KERNEL_DIR) M=$(PWD) modules
clean:
make -C $(KERNEL_DIR) M=$(PWD) clean
ref : Here
標籤:
Linux Driver
2012年10月25日 星期四
probe function
路過看到先記錄一下…
- Q:
In the linux kernel, what does theprobe()method, that the driver provides, do? How different is it from the driver'sinitfunction, i.e. why can't theprobe()functions actions be performed in the driver'sinitfunction ? - A1:
Different device types can have probe() functions. For example, PCI and USB devices both have probe() functions.
If you're talking about PCI devices, I would recommend you read chapter 12 of Linux Device Drivers, which covers this part of driver initialization. USB is covered in chapter 13.
Shorter answer, assuming PCI: The driver's init function callspci_register_driver()which gives the kernel a list of devices it is able to service, along with a pointer to theprobe()function. The kernel then calls the driver'sprobe()function once for each device.This probe function starts the per-device initialization: initializing hardware, allocating resources, and registering the device with the kernel as a block or network device or whatever it is.This makes is easier for device drivers, because they never need to search for devices or worry about finding a device that was hot-plugged. The kernel handles that part and notifies the right driver when it has a device for you to handle. - A2:Init(void) // runs once when the driver/module is invoked and sets things up for the kernel driver machine.Probe(*pdev) // is used by the kernel driver machine as needed to detect and install actual devices
標籤:
Linux Driver
2012年6月25日 星期一
取消游標
no cursor, when booting time
// if (err)
// soft_cursor(info, &cursor);
// soft_cursor(info, &cursor);
標籤:
Linux Driver
2012年6月7日 星期四
Hello, World! 使用 /dev/hello_world
多了個 write =.=
Question: How to check memory leak 冏
hello.c
#disable module verification failed: signature and/or required key missing - tainting kernel after insmod hello.ko
Question: How to check memory leak 冏
hello.c
#include <linux/fs.h> #include <linux/init.h> #include <linux/miscdevice.h> #include <linux/module.h> #include <asm/uaccess.h> //#include <linux/uaccess.h> #include <linux/slab.h> static char *buf_dev=NULL; static size_t buf_len; static DEFINE_MUTEX(buf_mutex); static int hello_open(struct inode *inode, struct file *file) { return 0; } static ssize_t hello_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { ssize_t retval = -ENOMEM; mutex_lock(&buf_mutex); if (buf_dev) kfree(buf_dev); buf_dev = kmalloc(count, GFP_KERNEL); memset(buf_dev, '\0', count); if (!buf_dev) goto out; if (copy_from_user(buf_dev, buf, count)) { kfree(buf_dev); retval = -EFAULT; goto out; } printk(KERN_INFO "count=%zu\n", count); *ppos = count; retval = count; buf_len = count; out: mutex_unlock(&buf_mutex); return retval; } static ssize_t hello_read(struct file * file, char * buf, size_t count, loff_t *ppos) { ssize_t retval = 0; char *start; mutex_lock(&buf_mutex); if (!buf_dev) { retval = -EINVAL; /* Or whatever you want to do here... */ goto out; } if (*ppos >= buf_len) goto out; /* EOF */ start = buf_dev + *ppos; retval = buf_len - *ppos; if (retval > count) retval = count; if (copy_to_user(buf, start, retval)) { retval = -EFAULT; goto out; } *ppos += retval; out: mutex_unlock(&buf_mutex); return retval; } static int hello_release(struct inode *inode, struct file *file) { return 0; } static const struct file_operations hello_fops = { .owner = THIS_MODULE, .open = hello_open, .read = hello_read, .write = hello_write, .release = hello_release, }; static struct miscdevice hello_dev = { MISC_DYNAMIC_MINOR, "hello", &hello_fops }; static int __init hello_init(void){ int ret; ret = misc_register(&hello_dev); if (ret) printk(KERN_INFO "Unable to register Hello\n"); return ret; } static void __exit hello_exit(void) { kfree(buf_dev); misc_deregister(&hello_dev); } module_init(hello_init); module_exit(hello_exit); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Hello, world! minimal module"); MODULE_VERSION("dev");Makefile
#disable module verification failed: signature and/or required key missing - tainting kernel after insmod hello.ko
CONFIG_MODULE_SIG=n PWD := $(shell pwd) KVERSION := $(shell uname -r) KERNEL_DIR = /usr/src/linux-headers-$(KVERSION)/ MODULE_NAME = hello obj-m := $(MODULE_NAME).o all: make -C $(KERNEL_DIR) M=$(PWD) modules clean: make -C $(KERNEL_DIR) M=$(PWD) clean
不要用 sudo echo 321 > /dev/hello
要用su切換到root
標籤:
Linux Driver
2012年2月21日 星期二
Hello, World! 使用 /dev/hello_world
在/dev目錄下的一個設備文件/dev/hello 實現 Hello,world!
CoolShell
=========================
Makefile 順便
#include <linux/fs.h> #include <linux/init.h> #include <linux/miscdevice.h> #include <linux/module.h> #include <asm/uaccess.h> static ssize_t hello_read(struct file * file, char * buf, size_t count, loff_t *ppos) { char *hello_str = "Hello, world!n"; int len = strlen(hello_str); /* Don't include the null byte. */ /* * We only support reading the whole string at once. */ if (count < len) return -EINVAL; /* * If file position is non-zero, then assume the string has * been read and indicate there is no more data to be read. */ if (*ppos != 0) return 0; /* * Besides copying the string to the user provided buffer, * this function also checks that the user has permission to * write to the buffer, that it is mapped, etc. */ if (copy_to_user(buf, hello_str, len)) return -EINVAL; /* * Tell the user how much data we wrote. */ *ppos = len; return len; } static const struct file_operations hello_fops = { .owner = THIS_MODULE, .read = hello_read, }; static struct miscdevice hello_dev = { /* * We don't care what minor number we end up with, so tell the * kernel to just pick one. */ MISC_DYNAMIC_MINOR, /* * Name ourselves /dev/hello. */ "hello", /* * What functions to call when a program performs file * operations on the device. */ &hello_fops }; static int __init hello_init(void){ int ret; /* * Create the "hello" device in the /sys/class/misc directory. * Udev will automatically create the /dev/hello device using * the default rules. */ ret = misc_register(&hello_dev); if (ret) printk(KERN_INFO "Unable to register Hello\n"); return ret; } static void __exit hello_exit(void){ misc_deregister(&hello_dev); } module_init(hello_init); module_exit(hello_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Valerie Henson val@nmt.edu>"); MODULE_DESCRIPTION("Hello, world! minimal module"); MODULE_VERSION("dev");
cat /dev/helloref:
CoolShell
=========================
Makefile 順便
obj-m += hello.o KVERSION := $(shell uname -r) all: $(MAKE) -C /lib/modules/$(KVERSION)/build M=$(PWD) modules clean: $(MAKE) -C /lib/modules/$(KVERSION)/build M=$(PWD) clean
。沒有 /lib/modules/`uname -r`/build 的人: ( debian )
aptitude install linux-headers-`uname -r`
標籤:
Linux Driver
2012年1月12日 星期四
example: gpio_request
example:
int ret = 0; ret = gpio_request(S5PV210_GPJ1(4), "turn_on_gpio_xxx"); if (ret<0) printk(KERN_INFO "nice: gpio_request error-turn_on_gpio_xxx"); else { gpio_direction_output(S5PV210_GPJ1(4), 1); //set the gpio is output and the value is 1 gpio_export(S5PV210_GPJ1(4), true); //let user can modify the gpio value } if the value of S5PV210_GPJ1(4) is 98 cat /sys/class/gpio/gpio98/value
標籤:
Linux Driver
2012年1月2日 星期一
linux kernel: ALIGN 含義
kernel:2.6.32.2, net/core/dev.c #define ALIGN(x,a) (((x)+(a)-1)&~(a-1)) 就是以a為上界對齊的意思。舉個例子4k頁面邊界的例子,即: a=4096, x = 3888,那麼以上界對齊為4096。 x = 4096, 结果為4096. x = 4222, 结果為8192. 另外還有一種以下界對齊的方式 #define ALIGN(x,a) ((x)&~(a-1)) a=4096, x = 3888,结果為0. x = 4095,结果為0 x = 4096,结果為4096 x = 4222,结果為4096.
ref:
weizhiyuan420的空间
標籤:
Linux Driver
2011年11月10日 星期四
Detect HP jack sense
- check /proc/asound/card0/codec#0 to know the Codec is Realtek ALC269.
- 在 /sound/pci/hda/patch_realtek.c 中可以知道realtek的 Vender ID為0x10ec
(所以ALC 269 ID為 0x10ec0269). - 在 /sound/pci/hda/hda_codec.h 中可以查到定義datasheet中的Verb ID,如圖一.
-
present = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_PIN_SENSE, 0) spec->jack_present = (present & AC_PINSENSE_PRESENCE) != 0;
- 把 spec->jack_present export出去,基本上就可以detect了 =.=(偷懶又只會這一千零一招)
圖一、Realtek ALC269 Datasheet Rev1.4
標籤:
Linux Driver
2011年10月23日 星期日
EXPORT_SYMBOL用法
【轉貼】夜深人靜
EXPORT_SYMBOL定義的函數對全部kernel代碼公開,不用修改kernel code就可以在您的kernel模組中直接使用。您還可以手動修改kernel code来導出另外的函數,用於重新编譯並加戴新kernel後的測試。
Linux symbol export method:
[1] If we want export the symbol in a module, just use the EXPORT_SYMBOL(xxxx) in the C or H file.
And compile the module by adding the compile flag -DEXPORT_SYMTAB.
Then we can use the xxxx in the other module.
[2] If we want export some symbol in Kernel that is not in a module such as xxxx in the /arch/ppc/fec.c.
Firstly, define the xxxx in the fec.c;
Secondly, make a new file which contain the "extern" define the xxxx(for example, extern int xxxx);
Lastly, in the ppc_ksyms.c we includes the new file, and add the EXPORT_SYMBOL(xxxx).
Then we can use the xxxx.
ref:夜深人靜
BTW:
EX: Here
EXPORT_SYMBOL定義的函數對全部kernel代碼公開,不用修改kernel code就可以在您的kernel模組中直接使用。您還可以手動修改kernel code来導出另外的函數,用於重新编譯並加戴新kernel後的測試。
Linux symbol export method:
[1] If we want export the symbol in a module, just use the EXPORT_SYMBOL(xxxx) in the C or H file.
And compile the module by adding the compile flag -DEXPORT_SYMTAB.
Then we can use the xxxx in the other module.
[2] If we want export some symbol in Kernel that is not in a module such as xxxx in the /arch/ppc/fec.c.
Firstly, define the xxxx in the fec.c;
Secondly, make a new file which contain the "extern" define the xxxx(for example, extern int xxxx);
Lastly, in the ppc_ksyms.c we includes the new file, and add the EXPORT_SYMBOL(xxxx).
Then we can use the xxxx.
ref:夜深人靜
BTW:
- EXPORT_SYMBOL和EXPORT_SYMBOL_GPL共存,不知二者有何區别?
- 所有EXPORT_SYMBOL的變數或函式都在 /proc/kallsyms (2.6.32)
EX: Here
/*mod1.c*/ #include <linux/init.h> #include <linux/module.h> MODULE_LICENSE("Dual BSD/GPL"); static int He1(void) { printk(KERN_INFO "He1..\n"); return 0; } EXPORT_SYMBOL(He1); static int __init hello_init(void) { printk(KERN_ALERT "Hello, world\n"); return 0; } static void __exit hello_exit(void) { printk(KERN_ALERT "Goodbye, cruel world\n"); } module_init(hello_init); module_exit(hello_exit); ================================== /*mod2.c*/ #include <linux/init.h> #include <linux/module.h> MODULE_LICENSE("Dual BSD/GPL"); static int He2(void) { extern int He1(void); He1(); printk(KERN_INFO "He2..\n"); return 0; } static int __init hello_init(void) { He2(); printk(KERN_ALERT "Hello, world\n"); return 0; } static void __exit hello_exit(void) { printk(KERN_ALERT "Goodbye, cruel world\n"); } module_init(hello_init); module_exit(hello_exit);### Makefile ---
## Author: hefuhua@163.com
## Version: $Id: Makefile,v 0.0 2007/01/26 02:02:51 leno Exp $
## Keywords:
## X-URL:
ifneq ($(KERNELRELEASE),)
obj-m := -DEXPORT_SYMTAB #加载该参数的地方
obj-m := mod2.o
else
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
default:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
endif
標籤:
Linux Driver
2010年12月15日 星期三
Driver-隨手筆記
Driver-隨手筆記
1. gpio_request(unsigned gpio, const char *label):
為避免不同的driver同時設定同一根GPIO,所以先用gpio_request看看是否有人使用,事後要用gpio_free。
呼叫gpio_get_value和gpio_set_value獲取設置值
example
2. s3c2410_gpio_cfgpin(unsigned int pin, unsigned int to)
作用是規定I/O port的用途:
如果當function mode(10),output port(00),input(01)
3. gpio_direction_output(unsigned gpio, int value)
設為output,並拉low (0), high (1)
4. set_irq_type(unsigned int irq, unsigned int type)
第一個参數是中斷號。第二個参數是中斷類型,表示上升緣觸發、下降緣觸發、高電位觸發或者低電位觸發。
5. int gpio_is_valid(int number);
判斷一個I/O是否合法
6. gpio_export(30, true);
Exporting that particular pin (30) to sysfs entry then use this API
Get value from GPIO pin
1. gpio_request(unsigned gpio, const char *label):
為避免不同的driver同時設定同一根GPIO,所以先用gpio_request看看是否有人使用,事後要用gpio_free。
呼叫gpio_get_value和gpio_set_value獲取設置值
err = gpio_request(S5PV210_GPJ1(4), "GPJ1"); if (err) printk(KERN_ERR "#### failed to request GPJ1 for CAM_2V8\n"); ... ... ... gpio_free(S5PV210_GPJ1(4));
example
2. s3c2410_gpio_cfgpin(unsigned int pin, unsigned int to)
作用是規定I/O port的用途:
如果當function mode(10),output port(00),input(01)
s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(3));
3. gpio_direction_output(unsigned gpio, int value)
設為output,並拉low (0), high (1)
gpio_direction_output(S5PV2XX_GPH0(7), 0); gpio_direction_output(S5PV2XX_GPH0(7), 1);
4. set_irq_type(unsigned int irq, unsigned int type)
第一個参數是中斷號。第二個参數是中斷類型,表示上升緣觸發、下降緣觸發、高電位觸發或者低電位觸發。
5. int gpio_is_valid(int number);
判斷一個I/O是否合法
6. gpio_export(30, true);
Exporting that particular pin (30) to sysfs entry then use this API
7. gpio_get_value(30);
Get value from GPIO pin
標籤:
Linux Driver
2009年11月26日 星期四
Driver 學習文章
Driver 學習文章
1. The Linux Kernel Module Programming Guide (簡)
Here
2. The Linux Kernel Module Programming Guide
Here
1. The Linux Kernel Module Programming Guide (簡)
Here
2. The Linux Kernel Module Programming Guide
Here
標籤:
Linux Driver
2009年11月25日 星期三
「轉貼」Unknown symbol in module的解決辦法
在動態加戴kernel module時如果出現 "Unknown symbol in module",
可以到 /var/log/message下查看具體原因,比如:
Aug 25 10:02:28 lk-laptop kernel: [ 6150.240000] snortl: module license 'unspecified' taints kernel.
Aug 25 10:02:28 lk-laptop kernel: [ 6150.240000] snortl: Unknown symbol register_security
Aug 25 10:02:28 lk-laptop kernel: [ 6150.240000] snortl: Unknown symbol mod_unreg_security
Aug 25 10:02:28 lk-laptop kernel: [ 6150.240000] snortl: Unknown symbol unregister_security
Aug 25 10:02:28 lk-laptop kernel: [ 6150.240000] snortl: Unknown symbol mod_reg_security
因為缺少module的版權資訊,只要在code中加入MODULE_LICENSE("GPL")就可以了。
ref : Unknown symbol in module的解決辦法
在動態加戴kernel module時如果出現 "Unknown symbol in module",
可以到 /var/log/message下查看具體原因,比如:
Aug 25 10:02:28 lk-laptop kernel: [ 6150.240000] snortl: module license 'unspecified' taints kernel.
Aug 25 10:02:28 lk-laptop kernel: [ 6150.240000] snortl: Unknown symbol register_security
Aug 25 10:02:28 lk-laptop kernel: [ 6150.240000] snortl: Unknown symbol mod_unreg_security
Aug 25 10:02:28 lk-laptop kernel: [ 6150.240000] snortl: Unknown symbol unregister_security
Aug 25 10:02:28 lk-laptop kernel: [ 6150.240000] snortl: Unknown symbol mod_reg_security
因為缺少module的版權資訊,只要在code中加入MODULE_LICENSE("GPL")就可以了。
ref : Unknown symbol in module的解決辦法
標籤:
Linux Driver
2009年11月24日 星期二
[轉貼]使用/proc文件系統的一個簡單例子
[轉貼]使用/proc文件系統的一個簡單例子
kernel:2.6.28
ref : 使用/proc文件系統的一個簡單例子
kernel:2.6.28
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/proc_fs.h>
#include <linux/jiffies.h>
#include <asm/uaccess.h>
#define MODULE_VERS "1.0"
#define MODULE_NAME "procfs_example"
#define FOOBAR_LEN 8
struct fb_data_t {
char name[FOOBAR_LEN + 1];
char value[FOOBAR_LEN + 1];
};
static struct proc_dir_entry *example_dir,*foo_file,\
*bar_file,*jiffies_file,*symlink;
struct fb_data_t foo_data,bar_data;
//A read callback function for jiffies file
static int proc_read_jiffies(char *page,char **stat,\
off_t off,int count,int *eof,void *data)
{
int len;
len = sprintf(page,"jiffies = %ld\n",jiffies); //jiffies is used as
//the time counter of in the Kernal
return len;
}
//A read callback function
static int proc_read_foobar (char *page,char **stat,\
off_t off,int count,int *eof,void *data)
{
int len;
struct fb_data_t *fb_data = (struct fb_data_t *) data;
len = sprintf(page,"%s = '%s'\n",fb_data->name,fb_data->value);
return len;
}
//A write callback function for foobar_file
static int proc_write_foobar (struct file *file,const char *buffer,\
unsigned long count,void *data)
{
int len;
struct fb_data_t *fb_data = (struct fb_data_t *)data;
if(count > FOOBAR_LEN)
len = FOOBAR_LEN;
else
len = count;
/*For buffer not exist in memory,so must copy it into Kernal first*/
if(copy_from_user(fb_data->value,buffer,len))
return -EFAULT;
fb_data->value[len] = '\0';
return len;
}
//init the MODULE
static int __init init_procfs_example(void)
{
int rv = 0;
/*create directory*/
example_dir = proc_mkdir(MODULE_NAME,NULL);
/*handle the error*/
if(example_dir == NULL){
rv = -ENOMEM;
goto out;
}
example_dir->owner = THIS_MODULE;
/*create jiffies using convenience function*/
jiffies_file = create_proc_read_entry("jiffies",0444,example_dir,\
proc_read_jiffies,NULL);
if(jiffies_file == NULL){
rv = -ENOMEM;
goto no_jiffies;
}
jiffies_file->owner = THIS_MODULE;
/*creat foo and bar files using same callback functions*/
foo_file = create_proc_entry("foo",0644,example_dir);
if(foo_file == NULL){
rv = -ENOMEM;
goto no_foo;
}
strcpy(foo_data.name,"foo");
strcpy(foo_data.value,"foo");
foo_file->data = &foo_data;
foo_file->read_proc = proc_read_foobar;
foo_file->write_proc = proc_write_foobar;
foo_file->owner = THIS_MODULE;
bar_file = create_proc_entry("bar",0644,example_dir);
if(bar_file == NULL){
rv = -ENOMEM;
goto no_bar;
}
strcpy(bar_data.name,"bar");
strcpy(bar_data.value,"bar");
bar_file->data = &bar_data;
bar_file->read_proc = proc_read_foobar;
bar_file->write_proc= proc_write_foobar;
bar_file->owner = THIS_MODULE;
/*create symlink*/
symlink = proc_symlink("jiffies_too",example_dir,"jiffies");
if(symlink == NULL){
rv = -ENOMEM;
goto no_symlink;
}
symlink->owner = THIS_MODULE;
printk(KERN_INFO "%s %s initialised\n",MODULE_NAME,MODULE_VERS);
return 0;
no_symlink:
remove_proc_entry("symlink",example_dir);
no_bar:
remove_proc_entry("bar",example_dir);
no_foo:
remove_proc_entry("foo",example_dir);
no_jiffies:
remove_proc_entry(MODULE_NAME,NULL);;
out:
return rv;
}
static void __exit cleanup_procfs_example(void)
{
remove_proc_entry("jiffies_too",example_dir);
remove_proc_entry("bar",example_dir);
remove_proc_entry("foo",example_dir);
remove_proc_entry("jiffies",example_dir);
remove_proc_entry(MODULE_NAME,NULL);
printk(KERN_INFO "%s %s removed\n",MODULE_NAME,MODULE_VERS);
}
module_init(init_procfs_example);
module_exit(cleanup_procfs_example);
ref : 使用/proc文件系統的一個簡單例子
標籤:
Linux Driver
訂閱:
文章 (Atom)
