1、编译和加载usb module.
linux中编译和加载一个module很简单,大致需要以下文件:
//config.mk文件
#Config.mk
CC = gcc
KRNLINC = /usr/src/linux-2.4.18-14/include
#
CFLAGS = -D__KERNEL__ -D__SMP__ -DMODULE -DEXPORT_SYMTAB -c -I$(KRNLINC)
//makefile文件
CONFIG = config.mk
include $(CONFIG)
NakedModule.o: NakedModule.c
$(CC) $(CFLAGS) -o $@ $<
其实这两个文件也不一定需要,只是免得每次编译要在控制台输入以下编译命令:
gcc -D__KERNEL__ -D__SMP__ -DMODULE -DEXPORT_SYMTAB -c -I/usr/src/linux-2.4.18-14/include -o NakedModule.o
NakedModule.c
而有了以上两个文件,你就可以只敲一个make命令就搞定了,呵呵。
注意你的linux版本不一定和我的一样,改/usr/src/linux-2.4.18-14/include就可以了。
//NakedModule.c
//包括一大堆,有的不一定用了,管它呢。
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <asm/uaccess.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/ioctl.h>
#include <linux/sched.h>
#include <linux/smp_lock.h>
#include <linux/devfs_fs_kernel.h>
#include <linux/usb.h>
//以下加一些信息给module,用infmod什么命令看的吧,忘了。#define DRIVER_VERSION "v1.0"
#define DRIVER_AUTHOR "TigerZD"
#define DRIVER_DESC "Naked Linux USB driver"
MODULE_AUTHOR( DRIVER_AUTHOR );
MODULE_DESCRIPTION( DRIVER_DESC );
MODULE_LICENSE("GPL");
//现在的版本很多用MODULE_INIT的宏了,没看是不是就是换个定//义,反正init_module照样好使。
int init_module(void)
{
printk("<5>Module is loaded!/n");
return 0;
}
//
void cleanup_module(void)
{
printk("<5>Module is unloaded!/n");
}
//
好了,敲一个make,NakedModule.o应该出来了,用insmod NakedModule.o命令加载它,没问题的话在/var/log/messages最后应该有Module is loaded!这句了。
如果加载时告诉你什么东西unreseved的话就比较麻烦,在编译命令中加入-DMODVERSIONS,在c文件中#include <linux/modversions.h>试试,反正我的加不加都可以。
用rmmod NakedModule卸载module。
好了,第一步完了,下一步在module中加入usb设备注册。
2、usb driver注册
linux中的usb设备注册也很简单,这要归功于linux简洁的文件系统结构和usbcore的设计了。
首先需要定义一个usb driver:
static struct usb_driver naked_usb_driver = {
name : "nakedusb"
};
关于usb_driver的定义看linux中的usb.c吧,记住linux中的源代码永远是你最大的财富!这里nakedusb就是你要注册的usb驱动程序的名字。
然后在init_module中加入:
usb_register(&naked_usb_driver);
cleanup_module中加入:
usb_deregister(&naked_usb_driver);
即
static struct usb_driver naked_usb_driver = {
name : "nakedusb"
};
int init_module(void)
{
printk("<5>Module is loaded!/n");
usb_register(&naked_usb_driver);
return 0;
}
//
void cleanup_module(void)
{
printk("<5>Module is unloaded!/n");
usb_deregister(&naked_usb_driver);
}
好再敲一次make编译好NakedModule.o,加载,应该是成功的了。到/proc/bus/usb目录下查看drivers文件,应该有5-11:nakedusb一项了,前面的数据是什么不太清楚。好,这一步很简单吧,呵呵,一步一步来嘛。:)
3、设备的即插即用
得益于linux的系统设计,usb设备的即插即用非常简单。
在申明usb driver时只需加入简单代码:
static struct usb_device_id my_usb_id =
{ idVendor : 0xXXXX,//这是你的usb设备的ID号,不要告诉我你连这个都不知道哈!
idProduct : 0xXXXX
};
static struct usb_driver naked_usb_driver = {
name : "nakedusb",
probe : naked_usb_probe,
disconnect : naked_usb_disconnect,
id_table : &my_usb_id
};
当然啦,在之前你得定义naked_usb_probe,naked_usb_disconnect:
static void* naked_usb_probe(struct usb_device *dev)
{
printk("<5>usb device probe./n");
if(dev->descriptor.idVendor == 0xXXXX && dev->descriptor.idProduct == 0xXXXX)
{
printk("<5>My usb device pluged in./n");
}
}
static void naked_usb_disconnect(struct usb_device *dev)
{
printk("<5>usb device disconnected./n");
if(dev->descriptor.idVendor == 0xXXXX && dev->descriptor.idProduct == 0xXXXX)
{
printk("<5>My usb device pluged out./n");
}
}
ok,编译,加载,现在你就得有一个usb的硬件才能往下做了 。什么,你没有?!faint!插上你的设备,一切正常的话会有“My usb device pluged in.”信息在messages尾部。
此时/proc/bus/usb中的001、devices、drivers会有相应的改变,自己动手看看吧。
拔出设备,有My usb device pluged out.吧?
其实到这一步你的usb设备就应该是完全可用的了,通过dev就可以向它发送各种urb块了。这要归功于usbcore了,它已经配置好了你的设备。下一步,我们会为设备加一些数据结构,就好象windows的device extension了,然后为应用程序准备标准接口,方便调试嘛。
4、应用程序接口
为module加入应用程序接口需要作两方面的工作。1、建立特殊设备文件。2、在驱动程序中注册。
先说驱动程序需要做那些改动。
首先要加入一个file_operations结构:
static struct file_operations usb_fops =
{
open : usb_open,
release : usb_close,
ioctl : usb_ioctl,};
static struct usb_driver naked_usb_driver = {
name : "nakedusb",
probe : naked_usb_probe,
disconnect : naked_usb_disconnect,
fops : &usb_fops,
id_table : &my_usb_id
};
然后devfs_register注册设备文件,注册的时机最好在probe例程中:
static void* naked_usb_probe(struct usb_device *dev)
{
printk("<5>usb device probe./n");
if(dev->descriptor.idVendor == 0xXXXX && dev->descriptor.idProduct == 0xXXXX)
{
printk("<5>My usb device pluged in./n");
myusb_devfs_handle = devfs_register(
usb_devfs_handle,
"nakeusb",
DEVFS_FL_DEFAULT,
USB_MAJOR,
0,
S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP |S_IWGRP | S_IROTH | S_IWOTH ,
&usb_fops,
NULL);
}
}
其中usb_devfs_handle是usbcore的输出变量,因此要extern devfs_handle_t usb_devfs_handle;定义
devfs_handle_t myusb_devfs_handle;
在disconnect中注销myusb_devfs_handle:
static void naked_usb_disconnect(struct usb_device *dev)
{
printk("<5>usb device disconnected./n");
if(dev->descriptor.idVendor == 0xXXXX && dev->descriptor.idProduct == 0xXXXX)
{
printk("<5>My usb device pluged out./n");
devfs_unregister(myusb_devfs_handle);
}
}
当然还有open、close、ioctl例程定义:
static int usb_open(struct inode *inode,struct file *file)
{
int err = 0;
printk("<5>app call driver open./n ");
MOD_INC_USE_COUNT;//module使用记数。
if(device_plug_in)//当设备插入时设为true;这就不用我教了吧?
{
return 0;
}
else
{
MOD_DEC_USE_COUNT;
return -EBUSY;
}
}
static int usb_close(struct inode *inode,struct file *file)
{
int err = 0;
printk("<5>app call driver close./n ");
MOD_DEC_USE_COUNT;
return 0;
}
//
static int usb_ioctl(struct inode *inode, struct file *file,unsigned int cmd, unsigned long arg)
{
...
}
这里面是你自己定义的ioctl处理例程,自己看着办吧。
好了,驱动程序更改就这么多了。编译、现在还不能加载,因为还没有建立特殊设备文件不是?
这个简单,在命令行敲:
mknod /dev/usb/nakeusb c 180 0其中nakeusb是在devfs_register的第二个参数,180是USB_MAJOR定义,
0是第5个参数,c表示是字符型设备。
好了,nakeusb设备文件建立了。加载驱动程序,插入设备。
以下是应用程序:
//app.c
#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <linux/types.h>
int main(int argc,char* argv[])
{
int fd = open("/dev/usb/nakeusb",O_RDWR);
if(fd == -1)
{
printf("open w682 failed!/n");
return -1;
}
ioctl(fd,
cmd,//定义参数,就是usb_ioctl中的cmd
&arg//传给驱动程序的参数。
);
close(fd);
}
用gcc -o app app.c编译就可以了。运行应用程序,好啦应该可以通讯了吧。
什么,怎么通过usb得到设备数据?看usb协议吧!
以上是在网上搜索的编写usb module的基本过程,先记录下。