这个十一,除了写说明书和整理代码等常规任务外,唯一有点意思的就是写个usb驱动了。
根据师兄的建议,下载了2.6.32的内核源码,在/usr/src/linux-2.6.32.27/drivers/usb/下面可以找到usb-skeleton.c文件,这个就是linux内核给我们提供的usb驱动框架,好好利用这个框架就可以写好linux的usb驱动啦~
看了一天的资料,网上有不少对这个框架的分析。根据网上的帖子,自己尝试编译一个最最最简单的usb驱动,将u盘挂载上去先。
打开usb-skeleton.c文件,只需要修改下面两个id:
/* Define these values to match your devices */
#define USB_SKEL_VENDOR_ID 0x0930
#define USB_SKEL_PRODUCT_ID 0x6545
这两个id是usb设备接入PC机时,PC机会自动读取usb设备的制造商和产品id。我们插上u盘,通过lsusb命令,可以查看u盘的两个id号。
Bus 001 Device 003: ID 0930:6545 Toshiba Corp. Kingston DataTraveler 2.0 Stick (4GB) / PNY Attache 4GB Stick
修改好两个id号后,就可以编译啦。
稳妥起见,将usb-skeleton.c文件拷到~/usb目录下,写一个简单的Makefile文件。
# If KERNELRELEASE is defined, we've been invoked from the
# kernel build system and can use its language.
ifneq ($(KERNELRELEASE),)
obj-m := usb.o
# Otherwise we were called directly from the command line;
# invoke the kernel build system.
else
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
default:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
endif
Makefile里面有个要注意的,$(MAKE)前面的必须是Tab,改了好几次,gedit查看它,$后面的变量颜色还是没变,老是编译不过去,显示make: Nothing to be done for 'default'
无语了一段时间,忽然查看了一下gedit的设置。
gedit首选项-编辑器设置中,居然勾选了插入空格代替制表符,悲剧……
改了配置后,就可以编译过去了,当前文件下出现了usb.ko文件,这个文件名是根据你的.c文件出来的,文件名一致。
然后insmod usb.ko, rmmod usb.ko.
通过dmesg | grep usb,并插入u盘,我们可以查看新编译的usb模块成功插入使用了。当insmod这个模块后,插入u盘,u盘不会在linux中自动弹出来,因为我们写的驱动没有任何的处理,所以就没有任何操作了。
如果要检测usb框架里,模块初始化和退出的情况,我们可以在框架文件的init和exit函数,如下:
static int __init usb_skel_init(void)
{
int result;
/* register this driver with the USB subsystem */
result = usb_register(&skel_driver);
if (result)
err("usb_register failed. Error number %d", result);
printk("<0>" "Jimson! Entering usb init\n");
return result;
}
static void __exit usb_skel_exit(void)
{
/* deregister this driver with the USB subsystem */
usb_deregister(&skel_driver);
printk("<0>" "Jimson! Entering usb exit\n");
}
我在这两个函数里,插入了printk函数,这个是内核态在终端打印信息的函数,跟printf类似,但一个是内核态,另一个是用户态。
将linux切换到命令行模式,Ctrl+Alt+F1~F5,insmod usb.ko,终端就是输出 Jimson! Entering usb init
但在当前X11界面下,终端不会输出这个,X11的终端是一个虚拟终端(控制台),控制台的级别不同,内核的信息显示不出来,可以用dmesg显示出来。
至此,USB驱动挂载U盘算是成功了,接下来就研究一下如何对设备进行读写,两台机器该如何通信。