从零开始学USB(二十七、usb鼠标驱动驱动实例分析[2]管道)

端点是USB设备的唯一可识别部分,其是主机和设备之间的通信流的终点。

管道,就是一个USB主机和USB设备端点之间的数据传输的通道。

站在主机的角度,它的目的是设备的某个端点。

而管道这算是主机和端点之间的连线。

 

这里我们先看一下管道在usb里的定义


/*
 * For various legacy reasons, Linux has a small cookie that's paired with
 * a struct usb_device to identify an endpoint queue.  Queue characteristics
 * are defined by the endpoint's descriptor.  This cookie is called a "pipe",
 * an unsigned int encoded as:
 *
 *  - direction:	bit 7		(0 = Host-to-Device [Out],
 *					 1 = Device-to-Host [In] ...
 *					like endpoint bEndpointAddress)
 *  - device address:	bits 8-14       ... bit positions known to uhci-hcd
 *  - endpoint:		bits 15-18      ... bit positions known to uhci-hcd
 *  - pipe type:	bits 30-31	(00 = isochronous, 01 = interrupt,
 *					 10 = control, 11 = bulk)
 *
 * Given the device address and endpoint descriptor, pipes are redundant.
 */

先看看管道,也就是这个整型值的构成, bit7 用来表示方向, bit8~14 表示设备地址,bit15~18 表示端点号,早先说过,设备地址用 7 位来表示,端点号用 4 位来表示,剩下来的 bit30~31 表示管道类型。
 

这里我们先看一下usb协议中给出来的管道类型(属性)的表示

#define PIPE_ISOCHRONOUS		0
#define PIPE_INTERRUPT			1
#define PIPE_CONTROL			2
#define PIPE_BULK			3


#define usb_pipetype(pipe)	(((pipe) >> 30) & 3)    //用30和31bit来表示管道类型
#define usb_pipeisoc(pipe)	(usb_pipetype((pipe)) == PIPE_ISOCHRONOUS)
#define usb_pipeint(pipe)	(usb_pipetype((pipe)) == PIPE_INTERRUPT)
#define usb_pipecontrol(pipe)	(usb_pipetype((pipe)) == PIPE_CONTROL)
#define usb_pipebulk(pipe)	(usb_pipetype((pipe)) == PIPE_BULK)

 

接下来看一下usb中知道管道的如何辨别端点方向

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


#define usb_pipein(pipe)	((pipe) & USB_DIR_IN)        //第7位表示usb端点方向,1表示输入端点
#define usb_pipeout(pipe)	(!usb_pipein(pipe))

 

最后我们看一下知道管道,如何知道设备地址和端点号

/* 8~14位表示设备地址 */
#define usb_pipedevice(pipe)	(((pipe) >> 8) & 0x7f)

/* 15~18位表示端点地址 */
#define usb_pipeendpoint(pipe)	(((pipe) >> 15) & 0xf)

 

 

当然也可以反过来。知道了其它信息也可以得到管道信息。

usb的端点有四种传输类型,2种方向,所以总共有8中组合

/* Create various pipes... */
#define usb_sndctrlpipe(dev, endpoint)	\
	((PIPE_CONTROL << 30) | __create_pipe(dev, endpoint))
#define usb_rcvctrlpipe(dev, endpoint)	\
	((PIPE_CONTROL << 30) | __create_pipe(dev, endpoint) | USB_DIR_IN)
#define usb_sndisocpipe(dev, endpoint)	\
	((PIPE_ISOCHRONOUS << 30) | __create_pipe(dev, endpoint))
#define usb_rcvisocpipe(dev, endpoint)	\
	((PIPE_ISOCHRONOUS << 30) | __create_pipe(dev, endpoint) | USB_DIR_IN)
#define usb_sndbulkpipe(dev, endpoint)	\
	((PIPE_BULK << 30) | __create_pipe(dev, endpoint))
#define usb_rcvbulkpipe(dev, endpoint)	\
	((PIPE_BULK << 30) | __create_pipe(dev, endpoint) | USB_DIR_IN)
#define usb_sndintpipe(dev, endpoint)	\
	((PIPE_INTERRUPT << 30) | __create_pipe(dev, endpoint))
#define usb_rcvintpipe(dev, endpoint)	\
	((PIPE_INTERRUPT << 30) | __create_pipe(dev, endpoint) | USB_DIR_IN)

 

这里的 __create_pipe也就是设备地址和端点号放在pipe这个32bit变量的合适位置了。
 

static inline unsigned int __create_pipe(struct usb_device *dev,
		unsigned int endpoint)
{
	return (dev->devnum << 8) | (endpoint << 15);
}

其实在usb协议传输时,这两个东西也就是一块传输的。

从零开始学USB(二十七、usb鼠标驱动驱动实例分析[2]管道)

 

 

 

回到我们程序最使用的地方,很明显通过端点号和设备号,计算输入类型的中断管道。

pipe = usb_rcvintpipe(udev, endpoint->bEndpointAddress);