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

本文深入探讨USB驱动开发的关键环节,包括设备ID表(id_table[])的配置及其重要性、probe函数的功能与作用,以及如何利用usb_control_msg()进行USB通信。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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)
 *




















评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值