//Another way to write a character device driver:
#include "linux/device.h"
#include "linux/module.h"
#include "linux/kernel.h"
#include "linux/fs.h"
#include "linux/init.h"
#include "linux/delay.h"
#include "linux/irq.h"
#include "asm/uaccess.h"
#include "asm/irq.h"
#include "asm/io.h"
#include "linux/poll.h"
#include "linux/cdev.h"
// 1. Determine the major device number
static int major;
static int hello_open(struct inode *inode, struct file *file)
{
printk("hello_open\n");
return 0;
}
static int hello2_open(struct inode *inode, struct file *file)
{
printk("hello2_open\n");
return 0;
}
// 2. Construct file_operations
static struct file_operations hello_fops = {
.owner = THIS_MODULE,
.open = hello_open,
};
static struct file_operations hello2_fops = {
.owner = THIS_MODULE,
.open = hello2_open,
};
#define HELLO_CNT 2
static struct cdev hello_cdev;
static struct cdev hello2_cdev;
static struct class *cls;
static int hello_init(void)
{
dev_t devid;
// 3. Tell the kernel
#if 0
major = register_chrdev(0, "hello", &hello_fops); // (major, 0), (major, 1), ..., (major, 255)都对应hello_fops
#else
if (major) {
devid = MKDEV(major, 0);
register_chrdev_region(devid, HELLO_CNT, "hello"); // (major,0~1) corresponds to hello_fops, (major, 2~255) does not correspond to hello_fops
} else {
alloc_chrdev_region(&devid, 0, HELLO_CNT, "hello"); // (major, 0~1) corresponds to hello_fops, (major, 2~255) does not correspond to hello_fops
major = MAJOR(devid);
}
cdev_init(&hello_cdev, &hello_fops);
cdev_add(&hello_cdev, devid, HELLO_CNT);
div = MKDEV(major, 2);
register_chrdev_region(devid, 1, "hello2");
cdev_init(&hello2_cdev, &hello2_fops);
cdev_add(&hello2_cdev, devid, 1);
#endif
cls = class_create(THIS_MODULE, "hello");
device_create(cls, NULL, MKDEV(major, 0), NULL, "hello0"); // /dev/hello0
device_create(cls, NULL, MKDEV(major, 1), NULL, "hello1"); // /dev/hello1
device_create(cls, NULL, MKDEV(major, 2), NULL, "hello2"); // /dev/hello2
device_create(cls, NULL, MKDEV(major, 3), NULL, "hello3"); // /dev/hello3
return 0;
}
static void hello_exit(void)
{
device_destroy(cls, MKDEV(major, 0));
device_destroy(cls, MKDEV(major, 1));
device_destroy(cls, MKDEV(major, 2));
device_destroy(cls, MKDEV(major, 3));
class_destroy(cls);
cdev_del(&hello_cdev);
unregister_chrdev_region(MKDEV(major, 0), HELLO_CNT);
cdev_del(&hello2_cdev);
unregister_chrdev_region(MKDEV(major, 2), 1);
}
module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");
===================================================================
test program:
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "sys/types.h"
#include "sys/stat.h"
#include "fcntl.h"
// hello_test /dev/hello0
void print_usage(char *file)
{
printf("%s 《dev》\n", file); //“《” is actually “<”
}
int main(int argc, char **argv)
{
int fd;
if (argc != 2)
{
print_usage(argv[0]);
return 0;
}
fd = open(argv[1], O_RDWR);
if (fd < 0)
printf("can't open %s\n", argv[1]);
else
printf("can open %s\n", argv[1]);
return 0;
}
Previous article:u-boot-2014.04 startup process analysis
Next article:Tiny210 IIC driver at24cxx access
Recommended ReadingLatest update time:2024-11-17 00:22
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- Innolux's intelligent steer-by-wire solution makes cars smarter and safer
- 8051 MCU - Parity Check
- How to efficiently balance the sensitivity of tactile sensing interfaces
- What should I do if the servo motor shakes? What causes the servo motor to shake quickly?
- 【Brushless Motor】Analysis of three-phase BLDC motor and sharing of two popular development boards
- Midea Industrial Technology's subsidiaries Clou Electronics and Hekang New Energy jointly appeared at the Munich Battery Energy Storage Exhibition and Solar Energy Exhibition
- Guoxin Sichen | Application of ferroelectric memory PB85RS2MC in power battery management, with a capacity of 2M
- Analysis of common faults of frequency converter
- In a head-on competition with Qualcomm, what kind of cockpit products has Intel come up with?
- Dalian Rongke's all-vanadium liquid flow battery energy storage equipment industrialization project has entered the sprint stage before production
- Allegro MicroSystems Introduces Advanced Magnetic and Inductive Position Sensing Solutions at Electronica 2024
- Car key in the left hand, liveness detection radar in the right hand, UWB is imperative for cars!
- After a decade of rapid development, domestic CIS has entered the market
- Aegis Dagger Battery + Thor EM-i Super Hybrid, Geely New Energy has thrown out two "king bombs"
- A brief discussion on functional safety - fault, error, and failure
- In the smart car 2.0 cycle, these core industry chains are facing major opportunities!
- The United States and Japan are developing new batteries. CATL faces challenges? How should China's new energy battery industry respond?
- Murata launches high-precision 6-axis inertial sensor for automobiles
- Ford patents pre-charge alarm to help save costs and respond to emergencies
- New real-time microcontroller system from Texas Instruments enables smarter processing in automotive and industrial applications
- 【Top Micro Intelligent Display Module】Three: Interface editing tool SGTools
- C2000 LaunchPad - SIC Interrupt Reception
- Things you must know about Gallium Nitride (GaN): Introduction (Part 1)!
- [Automatic clock-in and walking timing system based on face recognition] BLE automatic time calibration and scanning wearable watch/scan
- EEWORLD University ---- Cisco CCNA+CCNP Learning Tutorial
- What are the differences between level conversion chips and digital ADU isolation chips? Aren't they both designed to match their own voltage...
- IIC communication of msp430g2553
- How to get the free page block of STM32' MCU internal flash
- Using MicroPython to run app-like functions on a single chip
- What software do you usually use when doing circuit simulation?