linux内核驱动--usbled.c学习分析

来源:互联网 发布:网络出版有什么特点 编辑:程序博客网 时间:2024/06/06 07:15

1.usb驱动添加第一点id_table[]

在写USB驱动必须知道的就是usb设备的设备号和厂家号,比如在usbled.c文件下的:
/* table of devices that work with this driver */static const struct usb_device_id id_table[] = {{ USB_DEVICE(0x0fc5, 0x1223),.driver_info = DELCOM_VISUAL_SIGNAL_INDICATOR },{ USB_DEVICE(0x1d34, 0x0004),.driver_info = DREAM_CHEEKY_WEBMAIL_NOTIFIER },{ USB_DEVICE(0x1d34, 0x000a),.driver_info = DREAM_CHEEKY_WEBMAIL_NOTIFIER },{ },};
这个需要我们认为添加,后边的.driver_info就是驱动的简单信息,这里使用的枚举,直接使用幻数不好理解。
那个这个id_table的作用是什么?usb设备与其他普通的SPI、IIC接口设备不一样,USB设备一旦插到电脑上,电脑的USB控制器就会开始枚举USB设备,这个枚举的结果就是产生一个USB设备结构体--------这里就与SPI、IIC或者其他普通的GPIO驱动不一样,这些普通的GPIO驱动里边,需要我们自己定义一下这个代表设备的结构体,代表USB设备的结构体是由USB控制器驱动产生的,而这个一旦插上USB设备得到的设备结构体会有USB设备的ID号,然后就需要使用这个ID号去寻找有没有也包含这个ID号的USB驱动,这里的ID便是上边的id_table[],由此可知这个id_table[]的重要性了。

2.USB驱动中probe函数

下一个比较中重要的就是这个探测函数,那么就要知道:
1.探测函数在哪被调用
2.探测函数里边一般干什么
第一个问题:这个问题如果要详细分析有点不太可能,毕竟内核版本不同,调用的地方代码也不一样,但是可以肯定的是都是在USB被枚举以后,内核遍历代表驱动链表,使用这个id_table去匹配,找到匹配的就执行这个驱动里边的probe函数。
第二个问题:探测函数一般干什么?
struct usb_device *udev = interface_to_usbdev(interface);
上面这行代码是几乎每个USB驱动都有的,然后在这个探测函数里边,就行你想干什么都行,没有具体要求,传进就两个参数,能使用这两个参数干什么都行,我看在有些USB驱动里边,还在probe函数里边再一次匹配一下id_table[]。

3.最后的难度--USB通信

                        retval = usb_control_msg(led->udev,usb_sndctrlpipe(led->udev, 0),0x09,0x21,0x200,0,buffer,8,2000);
这是上边这个USB驱动里边实现一种简单点亮某一个灯的控制传输---相当于就是通信了。这个得具体USB模块了,可能有说明,得在研究研究这。

4.usb_control_msg(...)函数

USB驱动里边前面都是一些linux驱动下的套路,基本没什么变化,前面的难度便是对驱动熟不熟悉,如果熟悉了便没什么难度了,接下来,便是跟USB协议很相关的编程了,很需要协议知识。
/** * usb_control_msg - Builds a control urb, sends it off and waits for completion * @dev: pointer to the usb device to send the message to * @pipe: endpoint "pipe" to send the message to * @request: USB message request value * @requesttype: USB message request type value * @value: USB message value * @index: USB message index value * @data: pointer to the data to send * @size: length in bytes of the data to send * @timeout: time in msecs to wait for the message to complete before timing *out (if 0 the wait is forever) * * Context: !in_interrupt () * * This function sends a simple control message to a specified endpoint and * waits for the message to complete, or timeout. * * If successful, it returns the number of bytes transferred, otherwise a * negative error number. * * Don't use this function from within an interrupt context, like a bottom half * handler.  If you need an asynchronous message, or need to send a message * from within interrupt context, use usb_submit_urb(). * If a thread in your driver uses this call, make sure your disconnect() * method can wait for it to complete.  Since you don't have a handle on the * URB used, you can't cancel the request. */int usb_control_msg(struct usb_device *dev, //通信对象、设备
    unsigned int pipe, //通过这个管道与端点通信
                    __u8 request,    __u8 requesttype, 
    __u16 value, 
    __u16 index, 
    void *data,    __u16 size, 
    int timeout)
这就相当于填充一个SETUP包然后交给更底层的usb主机控制器,代表SETUP包的结构体如下:
struct usb_ctrlrequest {__u8 bRequestType;__u8 bRequest;__le16 wValue;__le16 wIndex;__le16 wLength;} __attribute__ ((packed));
怎么说呢,在include\linux\usb\ch9.h下有相关内容,下面说明在bRequestType里边是由三部分组成,由此便可推出上面的0x21代表的含义便是:
1.数据方向-----输出个设备
2.USB类型-----类(我不知道好不好理解,当然还有音频、HID类、厂商自定义等等)
3.收件人----一个接口(当然也有很多)
/* CONTROL REQUEST SUPPORT *//* * USB directions * * This bit flag is used in endpoint descriptors' bEndpointAddress field. * It's also one of three fields in control requests bRequestType. */#define USB_DIR_OUT0/* to device */#define USB_DIR_IN0x80/* to host *//* * USB types, the second of three bRequestType fields */#define USB_TYPE_MASK(0x03 << 5)#define USB_TYPE_STANDARD(0x00 << 5)#define USB_TYPE_CLASS(0x01 << 5)#define USB_TYPE_VENDOR(0x02 << 5)#define USB_TYPE_RESERVED(0x03 << 5)/* * USB recipients, the third of three bRequestType fields */#define USB_RECIP_MASK0x1f#define USB_RECIP_DEVICE0x00#define USB_RECIP_INTERFACE0x01#define USB_RECIP_ENDPOINT0x02#define USB_RECIP_OTHER0x03/* From Wireless USB 1.0 */#define USB_RECIP_PORT0x04#define USB_RECIP_RPIPE0x05
接下来就是上边的request----0x09,同样在ch9.h里边有:
/* * Standard requests, for the bRequest field of a SETUP packet. * * These are qualified by the bRequestType field, so that for example * TYPE_CLASS or TYPE_VENDOR specific feature flags could be retrieved * by a GET_STATUS request. */#define USB_REQ_GET_STATUS0x00#define USB_REQ_CLEAR_FEATURE0x01#define USB_REQ_SET_FEATURE0x03#define USB_REQ_SET_ADDRESS0x05#define USB_REQ_GET_DESCRIPTOR0x06#define USB_REQ_SET_DESCRIPTOR0x07#define USB_REQ_GET_CONFIGURATION0x08#define USB_REQ_SET_CONFIGURATION0x09  //设置配置#define USB_REQ_GET_INTERFACE0x0A#define USB_REQ_SET_INTERFACE0x0B#define USB_REQ_SYNCH_FRAME0x0C#define USB_REQ_SET_ENCRYPTION0x0D/* Wireless USB */#define USB_REQ_GET_ENCRYPTION0x0E#define USB_REQ_RPIPE_ABORT0x0E#define USB_REQ_SET_HANDSHAKE0x0F#define USB_REQ_RPIPE_RESET0x0F#define USB_REQ_GET_HANDSHAKE0x10#define USB_REQ_SET_CONNECTION0x11#define USB_REQ_SET_SECURITY_DATA0x12#define USB_REQ_GET_SECURITY_DATA0x13#define USB_REQ_SET_WUSB_DATA0x14#define USB_REQ_LOOPBACK_DATA_WRITE0x15#define USB_REQ_LOOPBACK_DATA_READ0x16#define USB_REQ_SET_INTERFACE_DS0x17
最后剩下:
 * 0x200-----wValue: matches the USB wValue field (le16 byte order)-----高字节02代表输出(01代表输入,03代表特性),低字节代表报告ID *     0-----wIndex: matches the USB wIndex field (le16 byte order)-----接口号 *     8-----wLength: matches the USB wLength field (le16 byte order) *




















1 0