当前位置: 首页 > wzjs >正文

微信微官网如何制作成都seo优化推广

微信微官网如何制作,成都seo优化推广,个人做网站如何推广,wordpress微信排版系列文章目录 xHCI 简单分析 USB Root Hub 分析 USB Hub 检测设备 usb host 驱动之 urb xHCI那些事儿 PCIe MMIO、DMA、TLP PCIe配置空间与CPU访问机制 PCIe总线协议基础实战 文章目录 系列文章目录一、xHCI 初始化二、xHCI 驱动识别根集线器(RootHub)…

在这里插入图片描述

系列文章目录


xHCI 简单分析
USB Root Hub 分析
USB Hub 检测设备

usb host 驱动之 urb
xHCI那些事儿

PCIe MMIO、DMA、TLP
PCIe配置空间与CPU访问机制
PCIe总线协议基础实战


文章目录

  • 系列文章目录
  • 一、xHCI 初始化
  • 二、xHCI 驱动识别根集线器(RootHub)
  • 三、发送 USB URB 包
    • 1、设备描述符获取步骤
      • 步骤 1:建立事务(Setup Phase)
      • 步骤 2:数据事务(Data Phase)
      • 步骤 3:状态事务(Status Phase)
      • 步骤 4:二次获取完整描述符(可选)
      • 关键包类型总结
      • 补充说明
    • 2、主机发送 SETUP 令牌包
      • usb_get_device_descriptor
      • usb_submit_urb
      • rh_urb_enqueue
      • rh_call_control
      • xhci_urb_enqueue
    • 3、事件处理
      • (1)HCD 中断注册
      • (2)中断处理
      • (3)usb_hcd_giveback_urb
      • (4)软中断处理
      • (5)__usb_hcd_giveback_urb


一、xHCI 初始化

    在文件 drivers/usb/host/xhci-pci.c 中有 module_init(xhci_pci_init); 函数,其实现 xHCI 的初始化。

在这里插入图片描述

二、xHCI 驱动识别根集线器(RootHub)

    xHCI 驱动调用 xhci_pci_probe 函数识别并初始化根集线器。xhci_pci_probe 函数最终会调用 usb_add_hcd 函数来添加 HCD ,该函数中有如下代码来初始化工作队列。

// drivers/usb/core/hcd.c
int usb_add_hcd(struct usb_hcd *hcd,unsigned int irqnum, unsigned long irqflags)
{// ...init_giveback_urb_bh(&hcd->high_prio_bh);init_giveback_urb_bh(&hcd->low_prio_bh);// ...
}static void init_giveback_urb_bh(struct giveback_urb_bh *bh)
{spin_lock_init(&bh->lock);INIT_LIST_HEAD(&bh->head);INIT_WORK(&bh->bh, usb_giveback_urb_bh);
}

    其初始化两个有优先级的工作队列,工作队列执行函数为 usb_giveback_urb_bh ,该函数实现了成功发送完 URB 后的清理及通知工作。

三、发送 USB URB 包

    USB 可以进行批量传输、中断传输、实时传输、控制传输。我们选取控制传输 usb_get_device_descriptor 函数来说明传输响应过程。

1、设备描述符获取步骤

在 USB 设备枚举过程中,获取设备描述符 的传输包流程分为以下步骤(以标准控制传输为例):


步骤 1:建立事务(Setup Phase)

  1. 主机发送 SETUP 令牌包
    • 包类型SETUP(PID=0xD)
    • 数据方向:主机→设备
    • 内容:包含标准请求 GET_DESCRIPTOR 的请求头(8 字节),例如:
      bmRequestType 	= 0x80 		// (Host→Device, 标准请求, 接收者为设备)
      bRequest 		= 0x06 		// (GET_DESCRIPTOR)
      wValue 			= 0x0100 	// (描述符类型为设备描述符)
      wIndex 			= 0x0000 	// (语言 ID 为 0)
      wLength 		= 0x0012 	// (请求 18 字节,但首次可能仅返回前 8 字节)
      

步骤 2:数据事务(Data Phase)

  1. 设备返回数据包
    • 包类型DATA0(PID=0x3)
    • 数据方向:设备→主机
    • 内容:设备描述符的前 8 字节(包含 bLengthbDescriptorType 等关键字段)。
    • 握手包:设备发送 ACK(PID=0x2)确认传输完成。

步骤 3:状态事务(Status Phase)

  1. 主机发送 ACK 握手包
    • 包类型ACK(PID=0x2)
    • 数据方向:主机→设备
    • 作用:确认设备描述符数据接收正确。

步骤 4:二次获取完整描述符(可选)

若首次仅获取前 8 字节(因端点 0 最大包长限制),主机需重新发送请求:

  1. 主机发送 SETUP 令牌包

    • 包类型SETUP(PID=0xD)
    • 内容wLength=0x0012(请求完整 18 字节)。
  2. 设备返回数据包

    • 包类型DATA1(PID=0xB,交替使用 DATA0/DATA1)
    • 内容:完整设备描述符(18 字节)。
  3. 主机发送 ACK 握手包

    • 包类型ACK(PID=0x2)
    • 作用:确认完整描述符接收完成。

关键包类型总结

步骤包类型方向作用
建立事务SETUPHost→Dev发送 GET_DESCRIPTOR 请求
数据事务DATA0/DATA1Dev→Host返回描述符数据
状态事务ACKHost→Dev确认数据接收完成

补充说明

  • 首次获取限制:设备端点 0 的最大包长可能仅为 8 字节,因此首次传输可能仅返回前 8 字节。
  • 地址分配:获取设备描述符后,主机分配新地址(通过 SET_ADDRESS 请求),后续通信使用新地址。
  • 错误处理:若设备未响应,主机会重试或标记设备为不可用。

在这里插入图片描述

【USB笔记】 设备描述符Device Descriptor
USB主机是如何获取设备描述符

2、主机发送 SETUP 令牌包

    主机发送 SETUP 令牌包在系统中调用大致如下:

usb_get_device_descriptor

// drivers/usb/core/message.c
usb_get_device_descriptor();usb_get_descriptor();usb_control_msg();usb_internal_control_msg();usb_alloc_urb();			// 分配 URB 空间usb_fill_control_urb();		// 填充 URBusb_start_wait_urb();		usb_submit_urb();								// 发送 URB 包wait_for_completion_timeout(&ctx.done, expire);	// 等待设备返回设备描述符

usb_submit_urb

    usb_submit_urb() 是 ​USB 主机控制器驱动(HCD)与核心层交互的核心函数,负责将 URB(USB 请求块)提交给具体的主机控制器(如 EHCI、xHCI)进行实际传输。

usb_submit_urb();				// 发送 URB 包usb_hcd_submit_urb();rh_urb_enqueue(hcd, urb);	// 发送给 RootHub,直接获取rh_call_control();			//control urbrh_queue_status(hcd, urb);		//int urb 循环检测 hub 的状态hcd->driver->urb_enqueue(hcd, urb, mem_flags); // 即调用 xhci_urb_enqueue,从设备中获取

    usb_hcd_submit_urb() 代码如下:

int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags) {// ...if (is_root_hub(urb->dev)) {	// 发送给 RootHub,调用 rh_urb_enqueue 获取status = rh_urb_enqueue(hcd, urb);} else {status = map_urb_for_dma(hcd, urb, mem_flags);	// 分配 DMA if (likely(status == 0)) {// 即调用 xhci_urb_enqueue,从设备中获取status = hcd->driver->urb_enqueue(hcd, urb, mem_flags);if (unlikely(status))unmap_urb_for_dma(hcd, urb);}}// ...
}

rh_urb_enqueue

    rh_urb_enqueue 是 ​根集线器(Root Hub)的 URB 处理函数,专门用于处理与根集线器相关的 URB 请求。其核心功能是 ​将 URB 提交给根集线器对应的硬件控制器,并触发控制传输或中断传输的流程。

  1. ​核心功能
  • URB 提交:将 URB 传递给根集线器的主机控制器驱动(HCD)。
  • ​传输类型分发:根据 URB 的端点类型(控制传输或中断传输)选择不同的处理路径。
  • ​硬件状态同步:管理根集线器的电源状态和远程唤醒功能。
// drivers/usb/core/hcd.c
static int rh_urb_enqueue (struct usb_hcd *hcd, struct urb *urb)
{if (usb_endpoint_xfer_int(&urb->ep->desc))return rh_queue_status (hcd, urb);if (usb_endpoint_xfer_control(&urb->ep->desc))return rh_call_control (hcd, urb);return -EINVAL;
}

    其中:

  • 中断传输:调用 rh_queue_status,通过定时器轮询根集线器状态。
  • 控制传输:调用 rh_call_control,构造控制请求并触发硬件操作。

rh_call_control

rh_call_control();			//control urbusb_hcd_link_urb_to_ep(hcd, urb);list_add_tail(&urb->urb_list, &urb->ep->urb_list);	// 添加到端点的 urb_list 链表中urb->hcpriv = hcd;hcd->driver->hub_control();		// 即调用 xhci_hub_control 函数usb_hcd_unlink_urb_from_ep(hcd, urb);list_del_init(&urb->urb_list);usb_hcd_giveback_urb(hcd, urb, status);list_add_tail(&urb->urb_list, &bh->head);	// 添加到工作队列中的链表里queue_work(system_bh_highpri_wq, &bh->bh);	// 触发执行 usb_giveback_urb_bh 函数// 或调用 queue_work(system_bh_wq, &bh->bh);

    rh_call_control 函数用来处理送给根集线器的主机控制器驱动(HCD)的控制传输。其通过 MMIO 直接获取相关的信息,如此处的设备描述符。同时启动工作队列,触发 usb_giveback_urb_bh 函数来对 URB 清理,同时通知 wait_for_completion_timeout 函数已完成了数据获取。

xhci_urb_enqueue

    对于外接的 USB 设备(如 U 盘)的设备描述符获取,则走 hcd->driver->urb_enqueue(hcd, urb, mem_flags)xhci_urb_enqueue 这条链路。

xhci_urb_enqueue();xhci_queue_ctrl_tx();	// 控制传输处理struct xhci_ring *ep_ring = xhci_urb_to_transfer_ring(xhci, urb);	// 即:xhci->devs[slot_id]->eps[ep_index]queue_trb();			// URB 转 TRB,并入传输环giveback_first_trb();	xhci_ring_ep_doorbell();	// 按响门铃寄存器,此时 xHCI 固件会处理此命令__le32 __iomem *db_addr = &xhci->dba->doorbell[slot_id];writel(DB_VALUE(ep_index, stream_id), db_addr);xhci_queue_bulk_tx();	xhci_queue_intr_tx();xhci_queue_isoc_tx_prepare();

    xhci_ring_ep_doorbell() 会按响门铃寄存器,此时 xHCI 固件会处理此命令,处理好后其会生成传输事件 TRB(Transfer Event TRB) 并插入事件环,同时给主机产生中断。主机会在中断处理函数 xhci_irq() 中处理此传输事件。

3、事件处理

(1)HCD 中断注册

    xHCI 驱动识别 HCD 时,其会调用 usb_add_hcd 函数初始化并添加主机控制器,在此函数中会获取中断号,并进行注册。

xhci_pci_probe();xhci_pci_common_probe(dev, id);usb_hcd_pci_probe(dev, &xhci_pci_hc_driver);usb_add_hcd(hcd, hcd_irq, IRQF_SHARED);usb_hcd_request_irqs(hcd, irqnum, irqflags);hcd->driver->start(hcd); 		// => xhci_pci_run
  1. usb_hcd_request_irqs
// drivers/usb/core/hcd.c
static int usb_hcd_request_irqs(struct usb_hcd *hcd,unsigned int irqnum, unsigned long irqflags) {if (hcd->driver->irq) {retval = request_irq(irqnum, &usb_hcd_irq, irqflags,hcd->irq_descr, hcd);hcd->irq = irqnum;}
}
  1. xhci_pci_run
// drivers/usb/host/xhci-pci.c
static int xhci_pci_run(struct usb_hcd *hcd) {int ret;if (usb_hcd_is_primary_hcd(hcd)) {ret = xhci_try_enable_msi(hcd);if (ret)return ret;}return xhci_run(hcd);
}static int xhci_try_enable_msi(struct usb_hcd *hcd) {// 注册中断ret = request_irq(pci_irq_vector(pdev, 0), xhci_msi_irq, 0, "xhci_hcd",xhci_to_hcd(xhci));
}// drivers/usb/host/xhci-ring.c
irqreturn_t xhci_msi_irq(int irq, void *hcd)
{return xhci_irq(hcd);
}	  

(2)中断处理

xhci_irq(hcd);xhci_handle_events(xhci, xhci->interrupters[0]);xhci_handle_event_trb(xhci, ir, ir->event_ring->dequeue);// 处理命令完成事件 TRB(Command Completion Event TRB)handle_cmd_completion(xhci, &event->event_cmd);	// 处理 Port Status Change Event TRB ?handle_port_status(xhci, event);// 处理 传输事件 TRB(Transfer Event TRB)handle_tx_event(xhci, ir, &event->trans_event);// 处理 Device Notification Event TRB ?handle_device_notification(xhci, event);handle_vendor_event(xhci, event, trb_type);

    handle_tx_event 函数正是处理获取从设备返回的设备描述符的地方。

// drivers/usb/host/xhci-ring.c
static int handle_tx_event(struct xhci_hcd *xhci,struct xhci_interrupter *ir,struct xhci_transfer_event *event) {// ...struct xhci_td *td = list_first_entry(&ep_ring->td_list, struct xhci_td,  td_list);if (usb_endpoint_xfer_control(&td->urb->ep->desc))		// controlprocess_ctrl_td(xhci, ep, ep_ring, td, ep_trb, event);else if (usb_endpoint_xfer_isoc(&td->urb->ep->desc))	// isocprocess_isoc_td(xhci, ep, ep_ring, td, ep_trb, event);elseprocess_bulk_intr_td(xhci, ep, ep_ring, td, ep_trb, event);	// 中断传输
}	

    usb_get_device_descriptor 属于控制传输,所以这里走的是 process_ctrl_td 这条路径。

process_ctrl_td();td->urb->actual_length = requested - remaining;		// 实际接收到的数据长度finish_td(xhci, ep, ep_ring, td, trb_comp_code);	xhci_td_cleanup(xhci, td, ep_ring, td->status);xhci_unmap_td_bounce_buffer(xhci, ep_ring, td);	// 清理反弹缓冲区(Bounce Buffer)xhci_giveback_urb_in_irq(xhci, td, status);

    xhci_giveback_urb_in_irq 执行一些必要的清理工作,包括把 URB 从端点链表中脱离,同时调用 usb_hcd_giveback_urb 函数执行软中断进行清理。

// drivers/usb/host/xhci-ring.c
static void xhci_giveback_urb_in_irq(struct xhci_hcd *xhci,struct xhci_td *cur_td, int status) {struct urb	*urb		= cur_td->urb;struct urb_priv	*urb_priv	= urb->hcpriv;struct usb_hcd	*hcd		= bus_to_hcd(urb->dev->bus);xhci_urb_free_priv(urb_priv);usb_hcd_unlink_urb_from_ep(hcd, urb);	// 从端点链表中脱离trace_xhci_urb_giveback(urb);usb_hcd_giveback_urb(hcd, urb, status);	// 启动工作队列,执行软中断,做必要的清理工作
}

    回顾上文讲述 rh_call_control 时,当 URB 是发送给根集线器的主机控制器驱动(HCD)时,其最后同样会调用 usb_hcd_giveback_urb 函数进行清理工作。

(3)usb_hcd_giveback_urb

// drivers/usb/core/hcd.c
void usb_hcd_giveback_urb(struct usb_hcd *hcd, struct urb *urb, int status)
{// 没在 bh 中并且不是 HCD,则开始进行清理工作if (!hcd_giveback_urb_in_bh(hcd) && !is_root_hub(urb->dev)) {__usb_hcd_giveback_urb(urb);	return;}// 同步端点和中断端点走高优先级中断if (usb_pipeisoc(urb->pipe) || usb_pipeint(urb->pipe))bh = &hcd->high_prio_bh;elsebh = &hcd->low_prio_bh;spin_lock(&bh->lock);list_add_tail(&urb->urb_list, &bh->head);	// 加入 bh 链表中running = bh->running;spin_unlock(&bh->lock);if (running)	// 运行中则等待;else if (bh->high_prio)	// 启动工作队列queue_work(system_bh_highpri_wq, &bh->bh);elsequeue_work(system_bh_wq, &bh->bh);
}

(4)软中断处理

    软中断触发流程大致如下,其最后调用处理函数 usb_giveback_urb_bh

__do_softirq();handle_softirqs(false);h->action(); => tasklet_action()workqueue_softirq_action(false);bh_workerprocess_scheduled_works(worker);process_one_work(worker, work);worker->current_func(work);// INIT_WORK(&bh->bh, usb_giveback_urb_bh);usb_giveback_urb_bh();

    usb_giveback_urb_bh 是 ​USB 子系统的底半部(Bottom Half)处理函数,负责将完成传输的 URB(USB Request Block)返回给设备驱动。其核心作用是将 URB 的状态同步到用户空间或驱动层,并触发驱动注册的回调函数。

  1. 核心功能如下:
  • URB 完成通知:将 URB 的传输结果(如成功、错误、取消)传递给设备驱动。
  • 资源回收:释放 URB 占用的 DMA 缓冲区、减少引用计数等。
  • 中断上下文切换:在硬件中断上下文中触发异步回调,避免阻塞中断处理。
  1. 底半部处理逻辑
// drivers/usb/core/hcd.c
static void usb_giveback_urb_bh(struct work_struct *work)
{struct giveback_urb_bh *bh =container_of(work, struct giveback_urb_bh, bh);struct list_head local_list;spin_lock_irq(&bh->lock);bh->running = true;list_replace_init(&bh->head, &local_list);	// 原子替换链表spin_unlock_irq(&bh->lock);// 循环处理已发送好的 URBwhile (!list_empty(&local_list)) {struct urb *urb;urb = list_entry(local_list.next, struct urb, urb_list);list_del_init(&urb->urb_list);bh->completing_ep = urb->ep;__usb_hcd_giveback_urb(urb);	// 真正的清理与通知处理的地方bh->completing_ep = NULL;}/** giveback new URBs next time to prevent this function* from not exiting for a long time.*/spin_lock_irq(&bh->lock);// 如果还有需要处理的 URB 则开启下一轮处理if (!list_empty(&bh->head)) {if (bh->high_prio)queue_work(system_bh_highpri_wq, &bh->bh);elsequeue_work(system_bh_wq, &bh->bh);}bh->running = false;spin_unlock_irq(&bh->lock);
}

    注意: usb_hcd_giveback_urb 中也调用 __usb_hcd_giveback_urb(urb) 函数进行清理与通知。

(5)__usb_hcd_giveback_urb

__usb_hcd_giveback_urb(urb);unmap_urb_for_dma(hcd, urb);usb_unanchor_urb(urb);urb->complete(urb); 	// => usb_api_blocking_completion

    urb->complete(urb)complete 函数会对等待进行通知,其赋值一般是在初始化 URB 时进行的,如 usb_fill_control_urb

// drivers/usb/core/message.c
usb_fill_control_urb(urb, usb_dev, pipe, (unsigned char *)cmd, data,len, usb_api_blocking_completion, NULL);usb_fill_int_urb(urb, usb_dev, pipe, data, len,usb_api_blocking_completion, NULL,ep->desc.bInterval);usb_fill_bulk_urb(urb, usb_dev, pipe, data, len,usb_api_blocking_completion, NULL);

usb_api_blocking_completion 实现如下,其会对如 usb_start_wait_urb 函数进行通知,传输已完成。

// drivers/usb/core/message.c
static void usb_api_blocking_completion(struct urb *urb) {struct api_context *ctx = urb->context;ctx->status = urb->status;complete(&ctx->done);	// 发送
}static int usb_start_wait_urb(struct urb *urb, int timeout, int *actual_length) {struct api_context ctx;unsigned long expire;int retval;init_completion(&ctx.done);urb->context = &ctx;urb->actual_length = 0;retval = usb_submit_urb(urb, GFP_NOIO);expire = timeout ? msecs_to_jiffies(timeout) : MAX_SCHEDULE_TIMEOUT;if (!wait_for_completion_timeout(&ctx.done, expire)) {	// 等待usb_kill_urb(urb);retval = (ctx.status == -ENOENT ? -ETIMEDOUT : ctx.status);} elseretval = ctx.status;
out:if (actual_length)*actual_length = urb->actual_length;usb_free_urb(urb);return retval;
}

    至此,整个发送与接收流程大致已分析完成。关于 DMA 分配与释放请参考此链接。


   
 


文章转载自:

http://q6vhlOQh.fncgw.cn
http://x6x8riuF.fncgw.cn
http://7463jZYM.fncgw.cn
http://7V0vMQDH.fncgw.cn
http://IplpMT3Y.fncgw.cn
http://POYubptr.fncgw.cn
http://OZek7Cqo.fncgw.cn
http://z5Z3fqYd.fncgw.cn
http://gYy4nQiN.fncgw.cn
http://BnDCVKTi.fncgw.cn
http://CZFoM3aj.fncgw.cn
http://P8V76YcW.fncgw.cn
http://ry6BBAnI.fncgw.cn
http://8zyO7Fgn.fncgw.cn
http://MGDjd9xO.fncgw.cn
http://GRoxpvRl.fncgw.cn
http://fw7sfkI8.fncgw.cn
http://LEysJKMa.fncgw.cn
http://FU67VyAg.fncgw.cn
http://YaHW3ZPV.fncgw.cn
http://wQpBG7SW.fncgw.cn
http://MDwfWatp.fncgw.cn
http://mNSl2OHa.fncgw.cn
http://7n1PLiLW.fncgw.cn
http://EY2Mx7Y7.fncgw.cn
http://p42PF8AD.fncgw.cn
http://SNgb3tp9.fncgw.cn
http://JmzqkMAF.fncgw.cn
http://erT3mYa6.fncgw.cn
http://rqtqxKEF.fncgw.cn
http://www.dtcms.com/wzjs/610523.html

相关文章:

  • 上线了建站怎么样建筑公司企业资料
  • 濮阳建站推广哪家好怎么做营销网站推广
  • 江西南昌电子商务网站建设公司网络版微信
  • 长春优惠做网站wordpress修改404
  • 橄榄树网站建设公司网站运营包括哪些方面
  • 企业网站建设代码宝安中心地铁站是几号线
  • 汉源县建设局网站涨口碑说做的网站
  • 湘西网站建设公司企业如何实现高端网站建设
  • 襄阳网站建设遂宁网站建设
  • 科技公司网站开发学习网站建设0学起
  • 网站做电子公章违法吗网站开发棋牌
  • 营销单页网站制作nftkif链之家
  • 网站的建设步骤网站建设开发收费
  • 中煤矿山建设集团网站网站宣传推广的目的
  • 成都网络推广网站长春搜索排名提升
  • 电商网站建设包括哪些方面公司网络组建方案模板
  • 做网站 先上线再调整网站开发的层次
  • 自己怎么建设购物网站网络营销方式有哪些自动售货机景区运营
  • 为拟建设的网站申请一个域名wordpress 移动 插件
  • 网站用户互动企业建站套餐
  • 合肥网站建设设计公司哪家好大型科技网站建设
  • 北京高端网站建设滨州淄博网站建设
  • 运动品牌网站开发题目来源php p2p网站建设
  • 做网站推广的价格十大建筑设计公司
  • 建网站平台安全性网站做的跟别人的一样可以吗
  • 用什么做网站2345高级版
  • 网站建设公司需要什么资质seo查询系统源码
  • 银川网站建设广告公司名单新创建的网站
  • 辽宁城市建设职业技术学院教务网站查看wordpress版本对应的php
  • 网站开发流程及顺序龙岗网站注册