2000字范文,分享全网优秀范文,学习好帮手!
2000字范文 > linux usb驱动u盘启动不了 Linux环境下USB的原理 驱动和配置(4)

linux usb驱动u盘启动不了 Linux环境下USB的原理 驱动和配置(4)

时间:2018-09-23 12:16:43

相关推荐

linux usb驱动u盘启动不了 Linux环境下USB的原理 驱动和配置(4)

在探测函数中会对每一个接口进行一次探测,所以我们在写USB驱动程序的时候,只要做好第一个端点,其它的端点就会自动完成探测。在探测函数中我们要注意的是在内核中用结构体struct usb_host_endpoint来描述USB端点,这个结构体在另一个名为struct usb_endpoint_descriptor的结构体中包含了真正的端点信息,struct usb_endpoint_descriptor结构体包含了所有的USB特定的数据,该结构体中我们要关心的几个字段是:

bEndpointAddress:这个是特定的USB地址,可以结合USB_DIR_IN和USB_DIR_OUT来使用,以确定该端点的数据是传向设备还是主机。

bmAttributes:这个是端点的类型,这个值可以结合位掩码USB_ENDPOINT_XFERTYPE_MASK来使用,以确定此端点的类型是USB_ENDPOINT_XFER_ISOC(等时)、USB_ENDPOINT_XFER_BULK(批量)、USB_ENDPOINT_XFER_INT的哪一种。

wMaxPacketSize:这个是端点一次可以处理的最大字节数,驱动程序可以发送数量大于此值的数据到端点,在实际传输中,数据量如果大于此值会被分割。

bInterval:这个值只有在端点类型是中断类型时才起作用,它是端点中断请求的间隔时间,以毫秒为单位。 {{分页}}

提交和控制urb:当驱动程序有数据要发送到USB设备时(大多数情况是在驱动程序的写函数中),要分配一个urb来把数据传输给设备:

/* 创建一个urb,并且给它分配一个缓存*/

urb = usb_alloc_urb(0, GFP_KERNEL);

if (!urb) {

retval = -ENOMEM;

goto error;

}

当urb被成功分配后,还要创建一个DMA缓冲区来以高效的方式发送数据到设备,传递给驱动程序的数据要复制到这块缓冲中去:

buf = usb_buffer_alloc(dev->udev, count, GFP_KERNEL, &urb->transfer_dma);

if (!buf) {

retval = -ENOMEM;

goto error;

}

if (copy_from_user(buf, user_buffer, count)) {

retval = -EFAULT;

goto error;

}

当数据从用户空间正确复制到局部缓冲区后,urb必须在可以被提交给USB核心之前被正确初始化:

/* 初始化urb */

usb_fill_bulk_urb(urb, dev->udev,

usb_sndbulkpipe(dev->udev, dev->bulk_out_endpointAddr),

buf, count, skel_write_bulk_callback, dev);

urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;

然后urb就可以被提交给USB核心以传输到设备了:

/* 把数据从批量OUT端口发出 */

retval = usb_submit_urb(urb, GFP_KERNEL);

if (retval) {

err("%s - failed submitting write urb, error %d", __FUNCTION__, retval);

goto error;

}

当urb被成功传输到USB设备之后,urb回调函数将被USB核心调用,在我们的例子中,我们初始化urb,使它指向skel_write_bulk_callback函数,以下就是该函数:

static void skel_write_bulk_callback(struct urb *urb, struct pt_regs *regs)

{

struct usb_skel *dev;

dev = (struct usb_skel *)urb->context;

if (urb->status &&

!(urb->status == -ENOENT ||

urb->status == -ECONNRESET ||

urb->status == -ESHUTDOWN)) {

dbg("%s - nonzero write bulk status received: %d",

__FUNCTION__, urb->status);

}

/* 释放已分配的缓冲区 */

usb_buffer_free(urb->dev, urb->transfer_buffer_length,

urb->transfer_buffer, urb->transfer_dma);

}

有时候USB驱动程序只是要发送或者接收一些简单的数据,驱动程序也可以不用urb来进行数据的传输,这是里涉及到两个简单的接口函数:usb_bulk_msg和usb_control_msg ,在这个USB框架程序里读操作就是这样的一个应用:

/* 进行阻塞的批量读以从设备获取数据 */

retval = usb_bulk_msg(dev->udev,

usb_rcvbulkpipe(dev->udev, dev->bulk_in_endpointAddr),

dev->bulk_in_buffer,

min(dev->bulk_in_size, count),

&count, HZ*10);

/*如果读成功,复制到用户空间 */

if (!retval) {

if (copy_to_user(buffer, dev->bulk_in_buffer, count)) (责任编辑:u盘技术员)

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。