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_OUT 0 /* to device */
#define USB_DIR_IN 0x80 /* 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_MASK 0x1f
#define USB_RECIP_DEVICE 0x00
#define USB_RECIP_INTERFACE 0x01
#define USB_RECIP_ENDPOINT 0x02
#define USB_RECIP_OTHER 0x03
/* From Wireless USB 1.0 */
#define USB_RECIP_PORT 0x04
#define USB_RECIP_RPIPE 0x05
接下来就是上边的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_STATUS 0x00
#define USB_REQ_CLEAR_FEATURE 0x01
#define USB_REQ_SET_FEATURE 0x03
#define USB_REQ_SET_ADDRESS 0x05
#define USB_REQ_GET_DESCRIPTOR 0x06
#define USB_REQ_SET_DESCRIPTOR 0x07
#define USB_REQ_GET_CONFIGURATION 0x08
#define USB_REQ_SET_CONFIGURATION 0x09 //设置配置
#define USB_REQ_GET_INTERFACE 0x0A
#define USB_REQ_SET_INTERFACE 0x0B
#define USB_REQ_SYNCH_FRAME 0x0C
#define USB_REQ_SET_ENCRYPTION 0x0D /* Wireless USB */
#define USB_REQ_GET_ENCRYPTION 0x0E
#define USB_REQ_RPIPE_ABORT 0x0E
#define USB_REQ_SET_HANDSHAKE 0x0F
#define USB_REQ_RPIPE_RESET 0x0F
#define USB_REQ_GET_HANDSHAKE 0x10
#define USB_REQ_SET_CONNECTION 0x11
#define USB_REQ_SET_SECURITY_DATA 0x12
#define USB_REQ_GET_SECURITY_DATA 0x13
#define USB_REQ_SET_WUSB_DATA 0x14
#define USB_REQ_LOOPBACK_DATA_WRITE 0x15
#define USB_REQ_LOOPBACK_DATA_READ 0x16
#define USB_REQ_SET_INTERFACE_DS 0x17
最后剩下: * 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)
*