How to Write a Linux usb module

 

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的基本过程,先记录下。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值