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。原理都是相通的。