linux 添加misc 字符設備

linux 每個設備分爲主設備號和次設備號,主設備號用於區分設備的種類,此設備號用於區分該種設備有多少個。linux中的字符設備的主設備號是10。如下:

crw------- 1 root root     10, 234 Apr  9 11:44 btrfs-control
crw------- 1 root root     10,  60 Apr  9 11:44 cpu_dma_latency
crw------- 1 root root     10, 203 Apr  9 11:44 cuse
crw------- 1 root root     10,  61 Apr  9 11:44 ecryptfs


次設備號 範圍 0- 255:

#define MAJOR(dev)	((dev)>>8)
10#define MINOR(dev)	((dev) & 0xff)
11#define MKDEV(ma,mi)	((ma)<<8 | (mi))

次設備號說明:

 10 char	Non-serial mice, misc features
		  0 = /dev/logibm	Logitech bus mouse
		  1 = /dev/psaux	PS/2-style mouse port
		  2 = /dev/inportbm	Microsoft Inport bus mouse
		  3 = /dev/atibm	ATI XL bus mouse
		  4 = /dev/jbm		J-mouse
		  4 = /dev/amigamouse	Amiga mouse (68k/Amiga)
		  5 = /dev/atarimouse	Atari mouse
		  6 = /dev/sunmouse	Sun mouse
		  7 = /dev/amigamouse1	Second Amiga mouse
		  8 = /dev/smouse	Simple serial mouse driver
		  9 = /dev/pc110pad	IBM PC-110 digitizer pad
		 10 = /dev/adbmouse	Apple Desktop Bus mouse
		 11 = /dev/vrtpanel	Vr41xx embedded touch panel
		 13 = /dev/vpcmouse	Connectix Virtual PC Mouse
		 14 = /dev/touchscreen/ucb1x00  UCB 1x00 touchscreen
		 15 = /dev/touchscreen/mk712	MK712 touchscreen
		128 = /dev/beep		Fancy beep device
		129 =
		130 = /dev/watchdog	Watchdog timer port
		131 = /dev/temperature	Machine internal temperature
		132 = /dev/hwtrap	Hardware fault trap
		133 = /dev/exttrp	External device trap
		134 = /dev/apm_bios	Advanced Power Management BIOS
		135 = /dev/rtc		Real Time Clock
		137 = /dev/vhci		Bluetooth virtual HCI driver
		139 = /dev/openprom	SPARC OpenBoot PROM
		140 = /dev/relay8	Berkshire Products Octal relay card
		141 = /dev/relay16	Berkshire Products ISO-16 relay card
		142 =
		143 = /dev/pciconf	PCI configuration space
		144 = /dev/nvram	Non-volatile configuration RAM
		145 = /dev/hfmodem	Soundcard shortwave modem control
		146 = /dev/graphics	Linux/SGI graphics device
		147 = /dev/opengl	Linux/SGI OpenGL pipe
		148 = /dev/gfx		Linux/SGI graphics effects device
		149 = /dev/input/mouse	Linux/SGI Irix emulation mouse
		150 = /dev/input/keyboard Linux/SGI Irix emulation keyboard
		151 = /dev/led		Front panel LEDs
		152 = /dev/kpoll	Kernel Poll Driver
		153 = /dev/mergemem	Memory merge device
		154 = /dev/pmu		Macintosh PowerBook power manager
		155 = /dev/isictl	MultiTech ISICom serial control
		156 = /dev/lcd		Front panel LCD display
		157 = /dev/ac		Applicom Intl Profibus card
		158 = /dev/nwbutton	Netwinder external button
		159 = /dev/nwdebug	Netwinder debug interface
		160 = /dev/nwflash	Netwinder flash memory
		161 = /dev/userdma	User-space DMA access
		162 = /dev/smbus	System Management Bus
		163 = /dev/lik		Logitech Internet Keyboard
		164 = /dev/ipmo		Intel Intelligent Platform Management
		165 = /dev/vmmon	VMware virtual machine monitor
		166 = /dev/i2o/ctl	I2O configuration manager
		167 = /dev/specialix_sxctl Specialix serial control
		168 = /dev/tcldrv	Technology Concepts serial control
		169 = /dev/specialix_rioctl Specialix RIO serial control
		170 = /dev/thinkpad/thinkpad	IBM Thinkpad devices
		171 = /dev/srripc	QNX4 API IPC manager
		172 = /dev/usemaclone	Semaphore clone device
		173 = /dev/ipmikcs	Intelligent Platform Management
		174 = /dev/uctrl	SPARCbook 3 microcontroller
		175 = /dev/agpgart	AGP Graphics Address Remapping Table
		176 = /dev/gtrsc	Gorgy Timing radio clock
		177 = /dev/cbm		Serial CBM bus
		178 = /dev/jsflash	JavaStation OS flash SIMM
		179 = /dev/xsvc		High-speed shared-mem/semaphore service
		180 = /dev/vrbuttons	Vr41xx button input device
		181 = /dev/toshiba	Toshiba laptop SMM support
		182 = /dev/perfctr	Performance-monitoring counters
		183 = /dev/hwrng	Generic random number generator
		184 = /dev/cpu/microcode CPU microcode update interface
		186 = /dev/atomicps	Atomic shapshot of process state data
		187 = /dev/irnet	IrNET device
		188 = /dev/smbusbios	SMBus BIOS
		189 = /dev/ussp_ctl	User space serial port control
		190 = /dev/crash	Mission Critical Linux crash dump facility
		191 = /dev/pcl181	<information missing>
		192 = /dev/nas_xbus	NAS xbus LCD/buttons access
		193 = /dev/d7s		SPARC 7-segment display
		194 = /dev/zkshim	Zero-Knowledge network shim control
		195 = /dev/elographics/e2201	Elographics touchscreen E271-2201
		196 = /dev/vfio/vfio	VFIO userspace driver interface
		197 = /dev/pxa3xx-gcu	PXA3xx graphics controller unit driver
		198 = /dev/sexec	Signed executable interface
		199 = /dev/scanners/cuecat :CueCat barcode scanner
		200 = /dev/net/tun	TAP/TUN network device
		201 = /dev/button/gulpb	Transmeta GULP-B buttons
		202 = /dev/emd/ctl	Enhanced Metadisk RAID (EMD) control
		203 = /dev/cuse		Cuse (character device in user-space)
		204 = /dev/video/em8300		EM8300 DVD decoder control
		205 = /dev/video/em8300_mv	EM8300 DVD decoder video
		206 = /dev/video/em8300_ma	EM8300 DVD decoder audio
		207 = /dev/video/em8300_sp	EM8300 DVD decoder subpicture
		208 = /dev/compaq/cpqphpc	Compaq PCI Hot Plug Controller
		209 = /dev/compaq/cpqrid	Compaq Remote Insight Driver
		210 = /dev/impi/bt	IMPI coprocessor block transfer
		211 = /dev/impi/smic	IMPI coprocessor stream interface
		212 = /dev/watchdogs/0	First watchdog device
		213 = /dev/watchdogs/1	Second watchdog device
		214 = /dev/watchdogs/2	Third watchdog device
		215 = /dev/watchdogs/3	Fourth watchdog device
		216 = /dev/fujitsu/apanel	Fujitsu/Siemens application panel
		217 = /dev/ni/natmotn		National Instruments Motion
		218 = /dev/kchuid	Inter-process chuid control
		219 = /dev/modems/mwave	MWave modem firmware upload
		220 = /dev/mptctl	Message passing technology (MPT) control
		221 = /dev/mvista/hssdsi	Montavista PICMG hot swap system driver
		222 = /dev/mvista/hasi		Montavista PICMG high availability
		223 = /dev/input/uinput		User level driver support for input
		224 = /dev/tpm		TCPA TPM driver
		225 = /dev/pps		Pulse Per Second driver
		226 = /dev/systrace	Systrace device
		227 = /dev/mcelog	X86_64 Machine Check Exception driver
		228 = /dev/hpet		HPET driver
		229 = /dev/fuse		Fuse (virtual filesystem in user-space)
		230 = /dev/midishare	MidiShare driver
		231 = /dev/snapshot	System memory snapshot device
		232 = /dev/kvm		Kernel-based virtual machine (hardware virtualization extensions)
		233 = /dev/kmview	View-OS A process with a view
		234 = /dev/btrfs-control	Btrfs control device
		235 = /dev/autofs	Autofs control device
		236 = /dev/mapper/control	Device-Mapper control device
		237 = /dev/loop-control Loopback control device
		238 = /dev/vhost-net	Host kernel accelerator for virtio net
		239 = /dev/uhid		User-space I/O driver support for HID subsystem

		240-254			Reserved for local use
		255			Reserved for MISC_DYNAMIC_MINOR


註冊misc字符設備有方便的接口可用:

/**
 *      misc_register   -       register a miscellaneous device
 *      @misc: device structure
 *      
 *      Register a miscellaneous device with the kernel. If the minor
 *      number is set to %MISC_DYNAMIC_MINOR a minor number is assigned
 *      and placed in the minor field of the structure. For other cases
 *      the minor number requested is used.
 *
 *      The structure passed is linked into the kernel and may not be
 *      destroyed until it has been unregistered.
 *
 *      A zero is returned on success and a negative errno code for
 *      failure.
 */

int misc_register(struct miscdevice * misc)


內核空間:

#include "xyf.h"
#include <linux/miscdevice.h>
#include <linux/fs.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/uaccess.h>

static long xyf_ioctl(struct file *filp, unsigned int cmd, unsigned long arg){
    int ret;
    void __user *ubuf = (void __user *)arg;
    struct buffer_read buff;
    
    printk("xyf_ioctl: %d %lx\n", cmd, arg);
    if (copy_from_user(&buff, ubuf, sizeof(buff))) {
         printk("xyf_ioctl error copy_from_user\n");
    }else{
        printk("xyf_ioctl buff: %d %d\n", buff.buffer_size, buff.read_size);
    }
    switch (cmd) {
        case 11:
            ret = 12;
            break;
        default:
            ret = 0;
            break;
    }
    return ret;
}

static int xyf_open(struct inode *nodp, struct file *filp)
{
    printk("xyf_open\n");
    return 0;
}

static ssize_t xyf_read(struct file *filep, char __user *buf, size_t len, loff_t *pos)
{
    int value;
    value = 66;
    if(copy_to_user(buf,&value,sizeof(value))){
        printk("xyf_read error copy_to_user\n");
    }
    printk("xyf_read %d\n", value);
    return 0;
}

static ssize_t xyf_write(struct file *filep, const char __user *buf, size_t len, loff_t *pos)
{
    int value;
    value = 0;
    if (copy_from_user(&value, buf, len)) {
        printk("xyf_write error copy_from_user\n");
    }
    
    printk("xyf_write %d\n", value);
    return len;
}

static const struct file_operations xyf_fops = {
	.owner = THIS_MODULE,
	.unlocked_ioctl = xyf_ioctl,
	.compat_ioctl = xyf_ioctl,
	.open = xyf_open,
    .read = xyf_read,
    .write = xyf_write,
};

static struct miscdevice xyf_miscdev = {
	.minor = MISC_DYNAMIC_MINOR,
	.name = "xyf",
	.fops = &xyf_fops
};

static int __init xyf_init(void)
{
    int ret = misc_register(&xyf_miscdev);;
    
    return ret;
}
device_initcall(xyf_init);

MODULE_LICENSE("GPL v2");



用戶空間訪問字符設備:

#include <unistd.h>
#include <stdio.h>
#include <binder/ProcessState.h>
#include <binder/IPCThreadState.h>
#include <utils/RefBase.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <fcntl.h>

static int open_driver()
{
    int fd = open("/dev/xyf", O_RDWR | O_CLOEXEC);  
    printf("open_driver fd=%d \n", fd);  
    if(fd >= 0){
        buffer_read buff;  
        buff.buffer_size = 55;  
        buff.read_size = 121;  
        int result = ioctl(fd, 11, &buff);  
        printf("ioctl result=%d \n", result);

        if (result == -1) {  
            close(fd);
            fd = -1;  
            return fd;
        }  
        int value_w  = 45;
        write(fd, &value_w, sizeof(value_w));
        int value_r = 0;
        read(fd, &value_r,sizeof(value_r));
        printf("read %d \n", value_r);
        close(fd);
    }else{
        printf("Opening '/dev/xyf' failed: %s\n", strerror(errno));
    }
    return fd;
}
int main() {
    open_driver();
    return 0;
}




硬件抽象層:

#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <hardware/hardware.h>

#define XYF_HARDWARE_MODULE_ID "xyf"

char const*const XYF_FILE = "/dev/xyf";
        
struct xyf_device_t {
    struct hw_device_t common;

    /**
     * Set the provided lights to the provided values.
     *
     * Returns: 0 on succes, error code on failure.
     */
    int (*xyf_read)(struct xyf_device_t* dev, int* value);
    int (*xyf_write)(struct xyf_device_t* dev, int value);
};

static int write_int(char const* path, int value)
{
    int fd;
    fd = open(path, O_RDWR);
    if (fd >= 0) {
        ssize_t amt = write(fd, &value, sizeof(value));
        close(fd);
        return amt == -1 ? -errno : 0;
    } else {
        return -errno;
    }
}

static int read_int(char const* path, int* value)
{
    int fd;

    fd = open(path, O_RDWR);
    if (fd >= 0) {
        read(fd, value, sizeof(*value));  
        close(fd);
        return 0;
    } else {
        return -errno;
    }
}

static int xyf_read(struct xyf_device_t* dev, int* value)
{
    read_int(XYF_FILE, value);
    return 0;
}

static int xyf_write(struct xyf_device_t* dev, int value)
{
    write_int(XYF_FILE, value);
    return 0;
}

static int xyf_close(struct xyf_device_t *dev)
{
    if (dev) {
        free(dev);
    }
    return 0;
}

static int xyf_open(const struct hw_module_t* module, char const* name,
        struct hw_device_t** device)
{
    struct xyf_device_t *dev = malloc(sizeof(struct xyf_device_t));
    if(!dev){
        return -ENOMEM;
    }
    memset(dev, 0, sizeof(*dev));
    dev->common.tag = HARDWARE_DEVICE_TAG;
    dev->common.version = 0;
    dev->common.module = (struct hw_module_t*)module;
    dev->common.close = (int (*)(struct hw_device_t*))xyf_close;
    dev->xyf_read = xyf_read;
    dev->xyf_write = xyf_write;
    
    *device = (struct hw_device_t*)dev;
    return 0;
}

static struct hw_module_methods_t xyf_module_methods = {
    .open = xyf_open,
};

struct hw_module_t HAL_MODULE_INFO_SYM = {
    .tag = HARDWARE_MODULE_TAG,
    .version_major = 1,
    .version_minor = 0,
    .id = XYF_HARDWARE_MODULE_ID,
    .name = "xyf Module",
    .author = "The Android Open Source Project",
    .methods = &xyf_module_methods,
};

通過HAL層訪問:

#include <unistd.h>
#include <stdio.h>
#include <utils/RefBase.h>
#include <utils/Log.h>
#include <hardware/hardware.h>
#define XYF_HARDWARE_MODULE_ID "xyf"

struct xyf_device_t {
    struct hw_device_t common;

    /**
     * Set the provided lights to the provided values.
     *
     * Returns: 0 on succes, error code on failure.
     */
    int (*xyf_read)(struct xyf_device_t* dev, int* value);
    int (*xyf_write)(struct xyf_device_t* dev, int value);
};

static xyf_device_t* get_device(hw_module_t* module, char const* name)
{
    int err;
    hw_device_t* device;
    err = module->methods->open(module, name, &device);
    if (err == 0) {
        return (xyf_device_t*)device;
    } else {
        return NULL;
    }
}

int main() {
    int err;
    hw_module_t* module;
    err = hw_get_module(XYF_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
    xyf_device_t* device = get_device(module, XYF_HARDWARE_MODULE_ID);
    if(!device){
        return 0;
    }
    int val = 89;
    device->xyf_write(device, val);
    
    int value = 0;
    device->xyf_read(device, &value);
    printf("hal client read %d\n", value);
    
    return 0;
}

HAL層只是封裝了一下,最終還是通過read,write訪問的kernel。原理都是相通的。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章