Basic steps for Linux to implement character device drivers

Source: Internet
Author: User
Tags sprintf

The Linux application layer wants to manipulate the API of the kernel layer, for example, to manipulate the relevant Gpio or register, by writing a character device driver.


1, first in the Rootfs in the/dev/under the generation of a character device. Note The main device number and the from device number. Available for example, the following shell scripts are generated:

if [!-e audioin];then     sudo mknod audioin C 0     Fi

The generated device is/dev/audioin, master device number 240, from device number 0.


2, Write Audioindriver.ko, AUDIOINDRIVER.C Basic code framework such as the following: The code defines the device name Audioin, device number 240, 0, consistent with the previously created device.

/************************************************************************** * AUDIOINDRIVER.C * * Kang_liu <[ Email protected]> * 2014-07-15\************************************************************************* * * #include <asm/uaccess.h> #include <asm/errno.h> #include <linux/types.h> #include <linux/fs.h > #include <linux/init.h> #include <linux/module.h> #include <linux/cdev.h> #include <mach/ gpio.h>//#include <mach/at91_rstc.h>/* Debug *///#include <mach/at91_pmc.h>//#include <mach/at91_ rstc.h>//#include <mach/at91_shdwc.h> #include <mach/irqs.h>//#include "generic.h"//#include " Clock.h "#include <mach/w55fa92_reg.h> #include <asm/io.h> #define DEV_MAJOR 240#define Dev_minor 0#define Num_minors 1#define device_name "Audioin" #define ERR (FMT, args ...) printk (Kern_alert __file__ ": FMT, # #args) #define MSG (FMT, args ...) PRINTK (Kern_info __file__ ": FMT, # #args) #define DBG (FMT, args ...) Printk(Kern_debug __file__ ":" FMT, # #args) static ssize_t user_gpio_read (struct FILE *fp, char __user *buff,    size_t count, loff_t *offp) {char str[32] = {0};    Char out[32] = {0};    int N, err;//printk ("Lk~~~~~~~read buff =%s\n", buff);    Err = Copy_from_user (str, buff, count);//PRINTK ("lk~~~~~~~read str =%s\n", str); if (err) return-efault;sprintf (out, "return values"); memset (buff, 0, count); err = Copy_to_user (buff, out, sizeof (OU    t)); if (err) Return-efault; return n;} Static ssize_t user_gpio_write (struct file *fp, const char __user *buff, size_t count, loff_t *OFFP    ) {int err;   Char tmp[32];    PRINTK ("Lk~~~~~~~write buff =%s\n", buff);    Err = Copy_from_user (tmp, Buff, count);//PRINTK ("lk~~~~~~~write tmp =%s\n", TMP); if (err) return-efault;if (' 1 ' = = Tmp[0]) {//line INPRINTK ("line in\n");}    else if (' 0 ' = = tmp[0]) {//mic INPRINTK ("MIC in\n");} return count;} Static ssize_t User_gpio_open (StruCT inode *inode,struct file *fp) {//PRINTK ("Open Gpio devices\n"); return 0; } static struct File_operations user_gpio_file_ops = {. Owner = This_module,. Write = User_gpio_write,. Read = User_gpi O_read,. Open = User_gpio_open,};static struct cdev *dev;static void __exit user_audioin_exit (void) {PRINTK ("Exit Audioin    \ n ");    dev_t Devno = MKDEV (Dev_major, Dev_minor);    Unregister_chrdev_region (Devno, num_minors);    Cdev_del (Dev); return;}    static int __init user_audioin_init (void) {PRINTK ("init audioin\n");    int err = 0;    int i;    dev_t Devno = MKDEV (Dev_major, Dev_minor);    Err = Register_chrdev_region (Devno, num_minors, device_name);    if (err) goto Fail_devno;    dev = Cdev_alloc ();    Dev->ops = &user_gpio_file_ops;       Dev->owner = This_module;    Err = Cdev_add (Dev, Devno, num_minors);        if (err) goto Fail_cdev; Return Err;fail_cdev:fail_devno:unregister_chrdev_region (Devno, num_minors); Fail_gpio:return err;} Module_init (User_audioin_init); Module_exit (User_audioin_exit); Module_license ("GPL"); Module_author ("Kang_liu <[email protected]>");  Module_description ("Access Gseio from userspace.");

Here you can invoke some APIs from the kernel layer to perform the underlying operation.


Makefile: Generate Audioindriver.ko

# comment/uncomment The following line to disable/enable debugging#debug = Ybuild_tools_pre = arm-linux-cc=$ (BUILD_TOOLS_ PRE) gccld=$ (build_tools_pre) ld# Add your debugging flag (or not) to Cflagsifeq ($ (DEBUG), y) debflags =-o-g-dscull_debu G # "-O" is needed to expand inlineselse debflags =-o2endifkernel_dir =: /.. /.. /linux-2.6.35.4extra_cflags + = $ (debflags) Extra_cflags + =-i$ (lddinc) extra_cflags +=-i$ (Kernel_dir)/arch/arm/ Mach-w55fa92/includeextra_cflags +=-i$ (Kernel_dir)/arch/armextra_cflags +=-i$ (Kernel_dir)/arch/arm/includeEXTRA_ CFLAGS +=-i$ (Kernel_dir)/arch/arm/include/linuxifneq ($ (kernelrelease),) # Call from KERNEL build SYSTEMAUDIOIN-OBJS: = audioindriver.oobj-m:= audioindriver.oelsekerneldir? = $ (kernel_dir) #KERNELDIR? =/lib/modules/$ (Shell uname-r)/ BUILDPWD: = $ (shell pwd) modules:$ (make) Arch=arm cross_compile=$ (Build_tools_pre)-C $ (kerneldir) m=$ (pwd) lddinc=$ ( PWD)/.. /include MODULESENDIFCLEAN:RM-RF *.o *~ core depend. *.cmd *.ko *.mod.c. tmp_versions modulEs.order module.symversdepend. Depend dep:$ (CC) $ (CFLAGS)-M *.c >. Dependifeq (. depend,$ (wildcard. depend)) include. D Ependendif

3. After generating the good. Ko, it is possible to load the driver on the ARM board.

Insmod Audioindriver.ko


4, loading drive success, you can operate the device directly in the application layer/dev/audioin, to achieve the relevant functions, some of the parameters to the drive layer, run the relevant kernel layer code.

Application layer test procedures such as the following:

 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <errno.h> #include <fcntl.h> #include <sys/types.h> #include <sys/ stat.h> #include <sys/syscall.h> #define Buf_len 32int s_audioinfd = 0;int Initaudioindevice () {S_AUDIOINFD = Open ("/dev/audioin", O_RDWR); if (s_audioinfd > 0) {return 1;} else{printf ("Can ' t open the GSE IO device\n"); return 0;}} void Uninitaudioindevice () {if (s_audioinfd > 0) Close (S_AUDIOINFD);} int Getaudioin () {char Buffer[buf_len] = {0};if (s_audioinfd > 0) {memcpy (&buffer[0], "Lk_test", 7);//printf ("Get  Buffer =%s\n ", buffer); int len = read (S_AUDIOINFD, buffer, 7);//printf (" Get buffer =%s, Len =%d\n ", buffer, Len); return Len;} return-1;} int setaudioin (int micline) {char Buffer[buf_len] = {0};if (s_audioinfd > 0) {sprintf (buffer, "%d", micline); int LEN = WR ITE (S_AUDIOINFD, buffer, sizeof (buffer)); if (len > 0) return 1;} return 0;} 

In the Read and write functions, you can get some return values from the driver, or you can pass the string to the driver.

The driving entrance is:

Module_init (User_audioin_init);
Module_exit (User_audioin_exit);


Basic steps for Linux to implement character device drivers

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.