关于LinuxusbDevice详解-飞外网

1. 简介

整个 USB 系统的通讯模型如上图所示,本文详细解析其中 Device 各模块的架构和原理 (图中彩色部分)。

2. Platform Layer

最底层是 UDC (Usb Device Controller)。

2.1 Platform Device

通常情况下,在 DTS 中定义一个 UDC platform device:

usbd: usb@10200000 { compatible = "snps,dwc2"; reg =  interrupts =  clocks = ,  clock-names = "otg"; resets = ,  reset-names = "dwc2", "dwc2-ecc"; g-rx-fifo-size =  g-np-tx-fifo-size =  g-tx-fifo-size =  dr_mode = "peripheral"; status = "okay";};

2.2 Platform Driver

对应的 UDC platform driver:

driversusbdwc2platform.c:static struct platform_driver dwc2_platform_driver = { .driver = { .name = dwc2_driver_name, .of_match_table = dwc2_of_match_table, .pm = &dwc2_dev_pm_ops, }, .probe = dwc2_driver_probe, .remove = dwc2_driver_remove, .shutdown = dwc2_driver_shutdown,};const struct of_device_id dwc2_of_match_table[] = { ... { .compatible = "snps,dwc2", .data = dwc2_set_usb_params }, {},};

该驱动的主要功能是创建和注册 Gadget Device,一个 UDC 对应一个 Gadget Device:


dwc2_driver_probe() → usb_add_gadget_udc() → usb_add_gadget_udc_release() → usb_add_gadget():int usb_add_gadget(struct usb_gadget *gadget){ struct usb_udc *udc; int ret = -ENOMEM; /* (1.1) 分配 udc 结构 */ udc = kzalloc(sizeof(*udc), GFP_KERNEL); if (!udc) goto error; /* (1.2) 初始化 udc 结构 */ device_initialize(&udc->dev); udc->dev.release = usb_udc_release; udc->dev.class = udc_class; udc->dev.groups = usb_udc_attr_groups; udc->dev.parent = gadget->dev.parent; ret = dev_set_name(&udc->dev, "%s", kobject_name(&gadget->dev.parent->kobj)); if (ret) goto err_put_udc; /* (2.1) 注册 gadget device */ ret = device_add(&gadget->dev); if (ret) goto err_put_udc; /* (2.2) 链接 gadget 和 udc */ udc->gadget = gadget; gadget->udc = udc; mutex_lock(&udc_lock); /* (1.3) 将 udc 加入全局链表 */ list_add_tail(&udc->list, &udc_list); /* (1.4) 注册 udc device */ ret = device_add(&udc->dev); if (ret) goto err_unlist_udc; usb_gadget_set_state(gadget, USB_STATE_NOTATTACHED); udc->vbus = true; /* pick up one of pending gadget drivers */ /* (3) 尝试 match gadget 的 device 和 driver */ ret = check_pending_gadget_drivers(udc); if (ret) goto err_del_udc; mutex_unlock(&udc_lock);}

3. UDC/Gadget Layer

Gadget Layer 层把各式各样的 UDC 封装成标准的 Gadget Device,提供统一的向上接口。Gadget Driver 又把各式各样的 Function 和 Gadget Device 链接起来。

3.1 Gadget Bus

Gadget Layer 层没有定义一个标准的 Bus 总线,而是自定义了两条链表来分别存储 Device 和 Driver:

它们的使用场景如下:

1、在 Gadget Device 创建时,首先把 Device 加入到 udc_list 链表,然后尝试和 gadget_driver_pending_list 链表中的 Driver 进行 match():

usb_add_gadget_udc() → usb_add_gadget_udc_release() → usb_add_gadget():int usb_add_gadget(struct usb_gadget *gadget){ /* (1) 将 device 加入全局链表 */ list_add_tail(&udc->list, &udc_list); /* pick up one of pending gadget drivers */ /* (2) 尝试 match gadget 的 device 和 driver */ ret = check_pending_gadget_drivers(udc); if (ret) goto err_del_udc; mutex_unlock(&udc_lock);}static int check_pending_gadget_drivers(struct usb_udc *udc){ struct usb_gadget_driver *driver; int ret = 0; /* (2.1) 遍历 `gadget_driver_pending_list` 链表中的 Driver,和 Device 进行 match() 且一个 Driver 只能 match 一个 Device,Driver match 成功后会从链表删除 */ list_for_each_entry(driver, &gadget_driver_pending_list, pending) if (!driver->udc_name || strcmp(driver->udc_name, dev_name(&udc->dev)) == 0) { /* (2.2) Match 成功,对 Device 和 Driver 进行 bind() */ ret = udc_bind_to_driver(udc, driver); if (ret != -EPROBE_DEFER) /* (2.3) Driver Match 成功后,从pending链表删除 */ list_del_init(&driver->pending); break; } return ret;}

2、在 Gadget Driver 创建时,首先尝试和 udc_list 链表中的 Device 进行 match(),match() 不成功则把 Driver 加入到 gadget_driver_pending_list 链表中:

gadget_dev_desc_UDC_store() → usb_gadget_probe_driver():int usb_gadget_probe_driver(struct usb_gadget_driver *driver){ struct usb_udc *udc = NULL; int ret = -ENODEV; if (!driver || !driver->bind || !driver->setup) return -EINVAL; mutex_lock(&udc_lock); /* (1.1) 如果 Driver 有 udc_name,尝试和 udc_list 链表中 Device 的 Name 进行 match() */ if (driver->udc_name) { list_for_each_entry(udc, &udc_list, list) { ret = strcmp(driver->udc_name, dev_name(&udc->dev)); if (!ret) break; } if (ret) ret = -ENODEV; else if (udc->driver) ret = -EBUSY; else goto found; /* (1.2) 如果 Driver 没有 udc_name,尝试适配 udc_list 链表中第一个没有适配的 Device */ } else { list_for_each_entry(udc, &udc_list, list) { /* For now we take the first one */ if (!udc->driver) goto found; } } if (!driver->match_existing_only) { /* (2) 如果没有 match() 成功,则把 Driver 加入到 pending 链表 */ list_add_tail(&driver->pending, &gadget_driver_pending_list); pr_info("udc-core: couldn't find an available UDC - added [%s] to list of pending drivers", driver->function); ret = 0; } mutex_unlock(&udc_lock); if (ret) pr_warn("udc-core: couldn't find an available UDC or it's busy"); return ret;found: /* (3) 如果 Match 成功,对 Device 和 Driver 进行 bind() */ ret = udc_bind_to_driver(udc, driver); mutex_unlock(&udc_lock); return ret;}

3、在 Device 和 Driver Match 成功时的 bind() 动作:

static int udc_bind_to_driver(struct usb_udc *udc, struct usb_gadget_driver *driver){ int ret; dev_dbg(&udc->dev, "registering UDC driver [%s]", driver->function); /* (1) 数据成员的赋值 */ udc->driver = driver; udc->dev.driver = &driver->driver; udc->gadget->dev.driver = &driver->driver; usb_gadget_udc_set_speed(udc, driver->max_speed); /* (2) 调用 Gadget Driver 的 bind() 函数 */ ret = driver->bind(udc->gadget, driver); if (ret) goto err1; /* (3) 调用 Gadget Device 的 start() 函数 udc->gadget->ops->udc_start(udc->gadget, udc->driver); */ ret = usb_gadget_udc_start(udc); if (ret) { driver->unbind(udc->gadget); goto err1; } /* (4) 调用 Gadget Device 的 pullup() 函数 gadget->ops->pullup(gadget, 1/0); */ usb_udc_connect_control(udc); kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE); return 0;}


注意:这里和一般的 Device 和 Driver 的适配规则有些不一样。一般的规则是一个 Dirver 可以适配多个 Device,而一个 Device 只能适配一个 Driver。而这里的规则是一个 Gadget Device 只能适配一个 Gadget Driver,而一个 Gadget Driver 只能适配一个 Gadget Device。Gadget Device 代表的是一个 UDC,而 Gadget Driver 代表的是一个 Composite Device。

3.2 Gadget Device

上一节说过 Gadget Device 由 UDC Driver 创建。

dwc2_driver_probe()→usb_add_gadget_udc()→usb_add_gadget_udc_release()→usb_add_gadget()

Gadget Device 的主要作用是提供了 Endpoint 资源,供 Function Layer 使用标准的 Gadget API 来进行访问。

3.2.1 Endpoint Alloc

UDC Driver 在调用 usb_add_gadget_udc() 注册 Gadget Device 之前,初始化了 Gadget 的 Endpoint 资源链表:

dwc2_driver_probe() → dwc2_gadget_init():int dwc2_gadget_init(struct dwc2_hsotg *hsotg){ /* (1) 初始化 Gadget Device 的 Endpoint 资源链表为空 */ INIT_LIST_HEAD(&hsotg->gadget.ep_list); hsotg->gadget.ep0 = &hsotg->eps_out[0]->ep; /* initialise the endpoints now the core has been initialised */ /* (2) 初始化 UDC 拥有的 Endpoint,加入到 Gadget Device 的 Endpoint 资源链表中 */ for (epnum = 0; epnum num_of_eps; epnum++) { if (hsotg->eps_in[epnum]) dwc2_hsotg_initep(hsotg, hsotg->eps_in[epnum], epnum, 1); if (hsotg->eps_out[epnum]) dwc2_hsotg_initep(hsotg, hsotg->eps_out[epnum], epnum, 0); }static void dwc2_hsotg_initep(struct dwc2_hsotg *hsotg, struct dwc2_hsotg_ep *hs_ep, int epnum, bool dir_in){ INIT_LIST_HEAD(&hs_ep->queue); INIT_LIST_HEAD(&hs_ep->ep.ep_list); /* add to the list of endpoints known by the gadget driver */ /* (2.1) UDC 中除了 endpoint0 以外,其他的 endpoint 都加入到Gadget Device 的 Endpoint 资源链表 `gadget.ep_list` 中 endpoint0 的操作由 UDC 驱动自己来处理 */ if (epnum) list_add_tail(&hs_ep->ep.ep_list, &hsotg->gadget.ep_list); /* (2.2) 初始化 endpoint 的结构体成员 */ hs_ep->parent = hsotg; hs_ep->ep.name = hs_ep->name; if (hsotg->params.speed == DWC2_SPEED_PARAM_LOW) usb_ep_set_maxpacket_limit(&hs_ep->ep, 8); else usb_ep_set_maxpacket_limit(&hs_ep->ep, epnum ? 1024 : EP0_MPS_LIMIT); /* (2.3) endpoint 最重要的结构体成员,endpoint 操作函数集 endpoint 的相关操作最后调用到这些函数上 */ hs_ep->ep.ops = &dwc2_hsotg_ep_ops; if (epnum == 0) { hs_ep->ep.caps.type_control = true; } else { if (hsotg->params.speed != DWC2_SPEED_PARAM_LOW) { hs_ep->ep.caps.type_iso = true; hs_ep->ep.caps.type_bulk = true; } hs_ep->ep.caps.type_int = true; } if (dir_in) hs_ep->ep.caps.dir_in = true; else hs_ep->ep.caps.dir_out = true;}

Gadget Device 准备好了 Endpoint 资源链表以后,通过 usb_add_gadget_udc() 注册。这样就可以 Function Layer 就可以通过调用 Gadget Api 来动态分配 Endpoint 了。例如:

static intacm_bind(struct usb_configuration *c, struct usb_function *f){ /* allocate instance-specific endpoints */ /* (1) 从 Gadget Device 中分配一个 in endpoint */ ep = usb_ep_autoconfig(cdev->gadget, &acm_fs_in_desc); if (!ep) goto fail; acm->port.in = ep; /* (2) 从 Gadget Device 中分配一个 out endpoint */ ep = usb_ep_autoconfig(cdev->gadget, &acm_fs_out_desc); if (!ep) goto fail; acm->port.out = ep; /* (3) 从 Gadget Device 中分配一个 notify endpoint */ ep = usb_ep_autoconfig(cdev->gadget, &acm_fs_notify_desc); if (!ep) goto fail; acm->notify = ep;}

其中通过 usb_ep_autoconfig() 函数从 Gadget Device 的 Endpoint 资源链表中分配空闲的 endpoint:

driversusbgadgetfunctionf_acm.c:usb_ep_autoconfig() → usb_ep_autoconfig_ss():struct usb_ep *usb_ep_autoconfig_ss( struct usb_gadget *gadget, struct usb_endpoint_descriptor *desc, struct usb_ss_ep_comp_descriptor *ep_comp){ struct usb_ep *ep; if (gadget->ops->match_ep) { ep = gadget->ops->match_ep(gadget, desc, ep_comp); if (ep) goto found_ep; } /* Second, look at endpoints until an unclaimed one looks usable */ /* (1) 从 Gadget Device 的 Endpoint 资源链表中查找一个空闲的(ep->claimed为空) 且符合要求的 endpoint */ list_for_each_entry (ep, &gadget->ep_list, ep_list) { if (usb_gadget_ep_match_desc(gadget, ep, desc, ep_comp)) goto found_ep; } /* Fail */ return NULL;found_ep: ep->address = desc->bEndpointAddress; ep->desc = NULL; ep->comp_desc = NULL; /* (2) 设置 endpoint 为已分配 */ ep->claimed = true; return ep;}

3.2.2 EndPoint Access

Gadget Device 不仅仅为 Gadget Api 提供了分配 endpoint 的支持,还支持对 endpoint 收发数据的底层支持。在上一节的 endpoint 初始化时,就已经设置 endpoint 的操作函数集 dwc2_hsotg_ep_ops:

dwc2_driver_probe() → dwc2_gadget_init() → dwc2_hsotg_initep():static void dwc2_hsotg_initep(struct dwc2_hsotg *hsotg, struct dwc2_hsotg_ep *hs_ep, int epnum, bool dir_in){ /* (2.3) endpoint 最重要的结构体成员,endpoint 操作函数集 endpoint 的相关操作最后调用到这些函数上 */ hs_ep->ep.ops = &dwc2_hsotg_ep_ops;static const struct usb_ep_ops dwc2_hsotg_ep_ops = { .enable = dwc2_hsotg_ep_enable, .disable = dwc2_hsotg_ep_disable_lock, .alloc_request = dwc2_hsotg_ep_alloc_request, .free_request = dwc2_hsotg_ep_free_request, .queue = dwc2_hsotg_ep_queue_lock, .dequeue = dwc2_hsotg_ep_dequeue, .set_halt = dwc2_hsotg_ep_sethalt_lock, /* note, don't believe we have any call for the fifo routines */};

Gadget Api 提供了以下接口来操作 endpoint 读写数据。在 Host 侧对 endpoint 进行一次操作请求的数据结构是 struct urb,而在 Device 侧也有类似的数据结构称为 struct usb_request,对 endpoint 的数据读写就是围绕 struct usb_request 展开的:

driversusbgadgetfunctionf_acm.c:static int acm_cdc_notify(struct f_acm *acm, u8 type, u16 value, void *data, unsigned length){ struct usb_ep *ep = acm->notify; struct usb_request *req; struct usb_cdc_notification *notify; const unsigned len = sizeof(*notify) + length; void *buf; int status; /* (1) 初始化 `struct usb_request` 数据结构 */ req = acm->notify_req; acm->notify_req = NULL; acm->pending = false; req->length = len; notify = req->buf; buf = notify + 1; notify->bmRequestType = USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE; notify->bNotificationType = type; notify->wValue = cpu_to_le16(value); notify->wIndex = cpu_to_le16(acm->ctrl_id); notify->wLength = cpu_to_le16(length); memcpy(buf, data, length); /* ep_queue() can complete immediately if it fills the fifo... */ spin_unlock(&acm->lock); /* (2) 提交 `usb_request` 请求到 endpoint 处理队列中 */ status = usb_ep_queue(ep, req, GFP_ATOMIC); spin_lock(&acm->lock);}

其中 usb_ep_queue() 函数就会调用 endpoint 的操作函数集 dwc2_hsotg_ep_ops 中的 .queue 函数:


int usb_ep_queue(struct usb_ep *ep, struct usb_request *req, gfp_t gfp_flags){ int ret = 0; if (WARN_ON_ONCE(!ep->enabled && ep->address)) { ret = -ESHUTDOWN; goto out; } /* (1) 实际调用 dwc2_hsotg_ep_queue_lock() */ ret = ep->ops->queue(ep, req, gfp_flags);out: trace_usb_ep_queue(ep, req, ret); return ret;}

3.2.3 UDC Control

Gadget Device 还提供了 UDC 层级的一些操作函数,UDC Driver 在调用 usb_add_gadget_udc() 注册 Gadget Device 之前,初始化了 Gadget 的 操作函数集:

dwc2_driver_probe() → dwc2_gadget_init():int dwc2_gadget_init(struct dwc2_hsotg *hsotg){ hsotg->gadget.max_speed = USB_SPEED_HIGH; /* (1) 初始化 Gadget Device 的操作函数集 */ hsotg->gadget.ops = &dwc2_hsotg_gadget_ops; hsotg->gadget.name = dev_name(dev); hsotg->remote_wakeup_allowed = 0;static const struct usb_gadget_ops dwc2_hsotg_gadget_ops = { .get_frame = dwc2_hsotg_gadget_getframe, .set_selfpowered = dwc2_hsotg_set_selfpowered, .udc_start = dwc2_hsotg_udc_start, .udc_stop = dwc2_hsotg_udc_stop, .pullup = dwc2_hsotg_pullup, .vbus_session = dwc2_hsotg_vbus_session, .vbus_draw = dwc2_hsotg_vbus_draw,};

Gadget Api 提供了一些内部函数来调用:

static inline int usb_gadget_udc_start(struct usb_udc *udc){ return udc->gadget->ops->udc_start(udc->gadget, udc->driver);}static inline void usb_gadget_udc_stop(struct usb_udc *udc){ udc->gadget->ops->udc_stop(udc->gadget);}static inline void usb_gadget_udc_set_speed(struct usb_udc *udc, enum usb_device_speed speed){ if (udc->gadget->ops->udc_set_speed) { enum usb_device_speed s; s = min(speed, udc->gadget->max_speed); udc->gadget->ops->udc_set_speed(udc->gadget, s); }}int usb_gadget_connect(struct usb_gadget *gadget){ int ret = 0; if (!gadget->ops->pullup) { ret = -EOPNOTSUPP; goto out; } if (gadget->deactivated) { /* * If gadget is deactivated we only save new state. * Gadget will be connected automatically after activation. */ gadget->connected = true; goto out; } ret = gadget->ops->pullup(gadget, 1); if (!ret) gadget->connected = 1;out: trace_usb_gadget_connect(gadget, ret); return ret;}int usb_gadget_disconnect(struct usb_gadget *gadget){ int ret = 0; if (!gadget->ops->pullup) { ret = -EOPNOTSUPP; goto out; } if (!gadget->connected) goto out; if (gadget->deactivated) { /* * If gadget is deactivated we only save new state. * Gadget will stay disconnected after activation. */ gadget->connected = false; goto out; } ret = gadget->ops->pullup(gadget, 0); if (!ret) { gadget->connected = 0; gadget->udc->driver->disconnect(gadget); }out: trace_usb_gadget_disconnect(gadget, ret); return ret;}

3.3 Gadget Driver (Configfs)

Gadget Device 支撑了核心 Gadget Api 的实现,而 Function Layer 又需要使用这些 Api。怎么样将两者适配起来?Gadget Driver 就是用来完成这项工作的。

目前存在两种风格的 Gadget Driver,其中包括:

Legacy。这是早期风格的 Gadget Driver,只能通过静态编译的方式指定使用哪些 Function。


Configfs。这是目前流行的 Gadget Driver,可以通过 configfs 文件系统,不用重新编译内核,动态的配置需要使用的 Function。

我们首先介绍 configfs 风格的 Gadget Driver。

3.3.1 configfs 使用

首先从使用上体验一下 configfs 的便捷。例如创建一个 ACM Function:

// 1、挂载configfs文件系统。mount -t configfs none /sys/kernel/configcd /sys/kernel/config/usb_gadget// 2、创建g1目录,实例化一个新的gadget模板 (composite device)。mkdir g1cd g1// 3.1、定义USB产品的VID和PID。echo "0x1d6b" > idVendorecho "0x0104" > idProduct// 3.2、实例化英语语言ID。(0x409是USB language ID 美国英语,不是任意的,可以在USBIF网站上文档查询。)mkdir strings/0x409ls strings/0x409/// 3.3、将开发商、产品和序列号字符串写入内核。echo "0123456789" > strings/0x409/serialnumberecho "AAAA Inc." > strings/0x409/manufacturerecho "Bar Gadget" > strings/0x409/product// 4、创建 `Function` 功能实例,需要注意的是,一个功能如果有多个实例的话,扩展名必须用数字编号。mkdir functions/acm.GS0// 5.1、创建一个USB `Configuration` 配置实例:mkdir configs/c.1ls configs/c.1// 5.2、定义配置描述符使用的字符串mkdir configs/c.1/strings/0x409ls configs/c.1/strings/0x409/echo "ACM" > configs/c.1/strings/0x409/configuration// 6、捆绑功能 `Function` 实例到 `Configuration` 配置c.1ln -s functions/acm.GS0 configs/c.1// 7.1、查找本机可获得的UDC实例 (即 gadget device)# ls /sys/class/udc/10200000.usb// 7.2、将gadget驱动注册到UDC上,插上USB线到电脑上,电脑就会枚举USB设备。echo"10200000.usb">UDC

3.3.2 configfs 层次结构

configfs 并不是 gadget 专用的,它是一个通用文件系统,方便用户通过文件系统创建文件夹、文件的方式来创建内核对象。

configfs 是很好理解的,struct config_group 相当于一个文件夹,struct config_item_type 是这个文件夹的属性集。其中 config_item_type->ct_group_ops->make_group()/drop_item() 定义了创建/销毁下一层子文件夹的方法,config_item_type->ct_attrs 定义了子文件和相关操作函数。

我们通过解析 driversusbgadgetconfigfs.c 文件来深入理解 configfs 的使用方法:

1、首先创建首层文件夹 /sys/kernel/config/usb_gadget:

static struct configfs_group_operations gadgets_ops = { .make_group = &gadgets_make, .drop_item = &gadgets_drop,};static const struct config_item_type gadgets_type = { .ct_group_ops = &gadgets_ops, .ct_owner = THIS_MODULE,};static struct configfs_subsystem gadget_subsys = { .su_group = { .cg_item = { .ci_namebuf = "usb_gadget", .ci_type = &gadgets_type, }, }, .su_mutex = __MUTEX_INITIALIZER(gadget_subsys.su_mutex),};static int __init gadget_cfs_init(void){ int ret; config_group_init(&gadget_subsys.su_group); ret = configfs_register_subsystem(&gadget_subsys); return ret;}module_init(gadget_cfs_init);

2、创建 /sys/kernel/config/usb_gadget/g1 ,相当于创建一个全新的 composite device。会调用顶层 struct config_group 的 config_item_type->ct_group_ops->make_group() 函数,即 gadgets_make():


static struct config_group *gadgets_make( struct config_group *group, const char *name){ struct gadget_info *gi; gi = kzalloc(sizeof(*gi), GFP_KERNEL); if (!gi) return ERR_PTR(-ENOMEM); /* (1) 创建顶层文件夹 `/sys/kernel/config/usb_gadget/g1` 对应的 `struct config_group` 结构 `/sys/kernel/config/usb_gadget/g1` 下对应不少子文件,在 gadget_root_type.ct_attrs 中定义,即 `gadget_root_attrs`: static struct configfs_attribute *gadget_root_attrs[] = { &gadget_dev_desc_attr_bDeviceClass, &gadget_dev_desc_attr_bDeviceSubClass, &gadget_dev_desc_attr_bDeviceProtocol, &gadget_dev_desc_attr_bMaxPacketSize0, &gadget_dev_desc_attr_idVendor, &gadget_dev_desc_attr_idProduct, &gadget_dev_desc_attr_bcdDevice, &gadget_dev_desc_attr_bcdUSB, &gadget_dev_desc_attr_UDC, &gadget_dev_desc_attr_max_speed, NULL, }; */ config_group_init_type_name(&gi->group, name, &gadget_root_type); /* (2) 创建子文件夹 `/sys/kernel/config/usb_gadget/g1/functions` `functions_type` 中定义了进一步创建子文件夹的操作函数 */ config_group_init_type_name(&gi->functions_group, "functions", &functions_type); configfs_add_default_group(&gi->functions_group, &gi->group); /* (3) 创建子文件夹 `/sys/kernel/config/usb_gadget/g1/configs` `config_desc_type` 中定义了进一步创建子文件夹的操作函数 */ config_group_init_type_name(&gi->configs_group, "configs", &config_desc_type); configfs_add_default_group(&gi->configs_group, &gi->group); /* (4) 创建子文件夹 `/sys/kernel/config/usb_gadget/g1/strings` `gadget_strings_strings_type` 中定义了进一步创建子文件夹的操作函数 */ config_group_init_type_name(&gi->strings_group, "strings", &gadget_strings_strings_type); configfs_add_default_group(&gi->strings_group, &gi->group); /* (5) 创建子文件夹 `/sys/kernel/config/usb_gadget/g1/os_desc` `os_desc_type` 中定义了进一步创建哪些子文件 */ config_group_init_type_name(&gi->os_desc_group, "os_desc", &os_desc_type); configfs_add_default_group(&gi->os_desc_group, &gi->group); /* (6) `configfs.c` 的目的很明确就是创建一个 `composite device` 由用户添加和配置这个 `device` 当中的多个 `interface` 即 `function` */ gi->composite.bind = configfs_do_nothing; gi->composite.unbind = configfs_do_nothing; gi->composite.suspend = NULL; gi->composite.resume = NULL; gi->composite.max_speed = USB_SPEED_SUPER_PLUS; spin_lock_init(&gi->spinlock); mutex_init(&gi->lock); INIT_LIST_HEAD(&gi->string_list); INIT_LIST_HEAD(&gi->available_func); composite_init_dev(&gi->cdev); gi->cdev.desc.bLength = USB_DT_DEVICE_SIZE; gi->cdev.desc.bDescriptorType = USB_DT_DEVICE; gi->cdev.desc.bcdDevice = cpu_to_le16(get_default_bcdDevice()); gi->composite.gadget_driver = configfs_driver_template; gi->composite.gadget_driver.function = kstrdup(name, GFP_KERNEL); gi->composite.name = gi->composite.gadget_driver.function; if (!gi->composite.gadget_driver.function) goto err; return &gi->group;err: kfree(gi); return ERR_PTR(-ENOMEM);}

3、创建 /sys/kernel/config/usb_gadget/g1/functions/acm.GS0。会调用 functions_type 中定义的 function_make() 函数:

static struct config_group *function_make( struct config_group *group, const char *name){ struct gadget_info *gi; struct usb_function_instance *fi; char buf[MAX_NAME_LEN]; char *func_name; char *instance_name; int ret; ret = snprintf(buf, MAX_NAME_LEN, "%s", name); if (ret >= MAX_NAME_LEN) return ERR_PTR(-ENAMETOOLONG); /* (1) 把 `acm.GS0` 分割成两部分: func_name = `acm` instance_name = `GS0` */ func_name = buf; instance_name = strchr(func_name, '.'); if (!instance_name) { pr_err("Unable to locate . in FUNC.INSTANCE"); return ERR_PTR(-EINVAL); } *instance_name = '�'; instance_name++; /* (2) 根据 func_name 在全局链表中查找对应 function usb_get_function_instance() → try_get_usb_function_instance() → fd->alloc_inst() → acm_alloc_instance(): 并调用 usb_function_driver->alloc_inst() 分配一个 function 实例 */ fi = usb_get_function_instance(func_name); if (IS_ERR(fi)) return ERR_CAST(fi); /* (3) 初始化 function 实例 */ ret = config_item_set_name(&fi->group.cg_item, "%s", name); if (ret) { usb_put_function_instance(fi); return ERR_PTR(ret); } if (fi->set_inst_name) { ret = fi->set_inst_name(fi, instance_name); if (ret) { usb_put_function_instance(fi); return ERR_PTR(ret); } } gi = container_of(group, struct gadget_info, functions_group); mutex_lock(&gi->lock); /* (4) 将 function 实例挂载到 composite device 的 function 链表当中去 */ list_add_tail(&fi->cfs_list, &gi->available_func); mutex_unlock(&gi->lock); return &fi->group;}

在 ln -s functions/acm.GS0 configs/c.1 时给 function 实例安装实际的函数:

config_usb_cfg_link() → usb_get_function() → fi->fd->alloc_func() → acm_alloc_func():static struct usb_function *acm_alloc_func(struct usb_function_instance *fi){ struct f_serial_opts *opts; struct f_acm *acm; /* (2.1) 对应分配一个 func 实例 */ acm = kzalloc(sizeof(*acm), GFP_KERNEL); if (!acm) return ERR_PTR(-ENOMEM); spin_lock_init(&acm->lock); /* (2.2) 初始化 func 实例的成员函数 */ acm->port.connect = acm_connect; acm->port.disconnect = acm_disconnect; acm->port.send_break = acm_send_break; acm->port.func.name = "acm"; acm->port.func.strings = acm_strings; /* descriptors are per-instance copies */ acm->port.func.bind = acm_bind; acm->port.func.set_alt = acm_set_alt; acm->port.func.setup = acm_setup; acm->port.func.disable = acm_disable; opts = container_of(fi, struct f_serial_opts, func_inst); acm->port_num = opts->port_num; acm->port.func.unbind = acm_unbind; acm->port.func.free_func = acm_free_func; acm->port.func.resume = acm_resume; acm->port.func.suspend = acm_suspend; return &acm->port.func;}

3.3.3 gadget driver

Configfs 风格的 gadget driver 的定义:

driversusbgadgetconfigfs.c:static const struct usb_gadget_driver configfs_driver_template = { .bind = configfs_composite_bind, .unbind = configfs_composite_unbind, .setup = configfs_composite_setup, .reset = configfs_composite_disconnect, .disconnect = configfs_composite_disconnect, .suspend = configfs_composite_suspend, .resume = configfs_composite_resume, .max_speed = USB_SPEED_SUPER_PLUS, .driver = { .owner = THIS_MODULE, .name = "configfs-gadget", }, .match_existing_only = 1,};

在调用 echo "/sys/class/udc/10200000.usb" > /sys/kernel/config/usb_gadget/g1/UDC 时,将上述 gadget driver 进行注册,和 UDC 已经注册好的 gadget device 进行动态适配。

gadget_dev_desc_UDC_store()→usb_gadget_probe_driver(&gi->composite.gadget_driver)→udc_bind_to_driver()

本质上是 使用 configfs 创建好的 composite device 和 gadget device 进行绑定:

gadget_dev_desc_UDC_store() → usb_gadget_probe_driver() → udc_bind_to_driver() → configfs_composite_bind() → usb_add_function() → function->bind() → acm_bind():static intacm_bind(struct usb_configuration *c, struct usb_function *f){ /* (1) 这样 function 实例和 gadget device 进行了绑定 */ struct usb_composite_dev *cdev = c->cdev; struct f_acm *acm = func_to_acm(f); /* allocate instance-specific endpoints */ /* (2) function 实例可以从 gadget device 中分配得到 endpoint */ ep = usb_ep_autoconfig(cdev->gadget, &acm_fs_in_desc); if (!ep) goto fail; acm->port.in = ep; ep = usb_ep_autoconfig(cdev->gadget, &acm_fs_out_desc); if (!ep) goto fail; acm->port.out = ep; ep = usb_ep_autoconfig(cdev->gadget, &acm_fs_notify_desc); if (!ep) goto fail; acm->notify = ep;}

但是 bind() 以后 function 实例只是分配了 endpoint 资源还没有被启动,因为 Device 是被动状态,只有连上 Host,被 Host Set Configuration 操作以后。某一组 Configuration 被配置,相应的 Function 实例 才会被启用:

dwc2_hsotg_complete_setup() → dwc2_hsotg_process_control() → hsotg->driver->setup() → configfs_composite_setup() → composite_setup() → set_config() → f->set_alt() → acm_set_alt():static int acm_set_alt(struct usb_function *f, unsigned intf, unsigned alt){ struct f_acm *acm = func_to_acm(f); struct usb_composite_dev *cdev = f->config->cdev; /* we know 星星科技指导员 发表于 06-30 10:41 •
RT-Thread记录(十、全面认识 I/O 设备模型) 学完 RT-Thread 内核,从本文开始熟悉了解 RT-Thread I/O 设备管理相关知识。 矜辰所致 发表于 06-30 10:38 • 236次
关于Windows和Linux操作系统中线程同步了解 线程可以是可连接的(默认情况下)或分离的。当一个可连接线程终止时,信息(标识符、终止状态、线程计数器.... 星星科技指导员 发表于 06-30 10:31 •
ScarecrowApiDoc接口管理系统 ./oschina_soft/gitee-scarecrowApiDoc.zip 发表于 06-30 10:31 •
如果该部分不受支持,则值得拥有一份最新的 Linux 内核源代码以进行交叉引用。如果最近添加了支.... 星星科技指导员 发表于 06-30 09:46 •
利用YOCTO的力量进行Linux操作系统移植项目 随时可用的 开发工具:作为 Yocto 用户,您可以访问各种开发工具,例如应用程序开发工具包 (.... 星星科技指导员 发表于 06-30 09:05 •
CH559L如何改才能支持无线复合键鼠设备? CH559用USBH_MK_RE.c这个project时,普通有线键鼠可以正常使用,但用无线复合键鼠设备时用不了,打印提示... 发表于 06-30 07:58 •
求助,基于CH554的触摸屏芯片USB转IIC方案可以提供代码? 对基于基于CH554的触摸屏芯片USB转IIC方案比较感兴趣,看官网有这个(1)提供电容触摸屏转接套片;(2)提供电容屏转接... 发表于 06-30 07:42 • 154次
请问CH343PT.DLL驱动有没有支持64位系统x64版本?需要使用CH343PT.DLL来获取USB信息, 我们的软件是64位应用, 能否提供支持64位的版本 CH343PT_x64.DLL 发表于 06-30 07:28 • 154次
请问CH378Q扇区读写和字节读写各有什么优劣啊? 请问CH378Q这个芯片扇区读写和字节读写各有什么优劣啊?还有你们有字节读写的例程吗?08H模式下能达到480Mbps高速USB通... 发表于 06-30 07:00 • 150次
CH563Q usb device和udp client整合到一个程序利,没有发生中断是为什么? 你好, 2个问题请教下, 1.我目前把 CH563Q exam 的 usb device 和 udp client整合一个程序, 由芯片usb接口插入host之后程序... 发表于 06-30 06:50 •
CH341T晶振无法持续正常起振是为什么? USB端口供电,同时将D+/D-拉进板子。12M晶振匹配20PF的谐振电容。当插入USB时,晶振起振一会之后就变成高电平,D+/D... 发表于 06-30 06:32 •
1、 腾讯 ncnn 源码命令如下所示 1) 第一种方法: Orang Pi 百度云盘中提供的 ncnn.tar.gz 压缩包 a) 从... 发表于 06-29 17:26 • 1188次
总之,您必须在生成掩码之前运行软件,以证明您的计算硬件是正确的。仿真是做到这一点的唯一现实方法,.... 星星科技指导员 发表于 06-29 15:25 • 103次
润和海思3559A开发版连接usb摄像头 请问海思3559A开发版连接了usb摄像头怎么获取数据?除了使用apt-get安装第三方软件包之外,有没有海思的API获取数据? 发表于 06-29 12:39 • 466次
摘要:随着物联网技术的发展,各种应用及系统推陈出新,不断更新换代,而通信管理机是系统的数据枢纽,在整.... panqin888 发表于 06-29 12:33 •
RK3566JD4 Linux_SDK源码包 采用RK3566四核64位处理器, 集成双核心架构GPU以及高效能NPU; 支持PCIe2.1和SA.... 发表于 06-29 11:37 •
RK3566JD4 linux-headers 采用RK3566四核64位处理器, 集成双核心架构GPU以及高效能NPU; 支持PCIe2.1和SA.... 发表于 06-29 11:30 •
RK3568J Linux_Upgrade_Tool_v1.65 采用Rockchip RK3588新一代旗舰级八核64位处理器,最大可配32GB大内存;支持8K视频.... 发表于 06-29 11:22 •
RK3566JD4 firefly linux repack工具 采用RK3566四核64位处理器, 集成双核心架构GPU以及高效能NPU; 支持PCIe2.1和SA.... 发表于 06-29 10:54 •
RK3568J firefly-linux-repack 采用Rockchip新一代64位处理器RK3568,集成双核心架构GPU以及高效能NPU;最大支持8.... 发表于 06-29 10:46 •
RK3568J Linux_Upgrade_Tool_v1.59 采用Rockchip新一代64位处理器RK3568,集成双核心架构GPU以及高效能NPU;最大支持8.... 发表于 06-29 10:45 •
RK3568J Linux_SDK 源码包 采用Rockchip新一代64位处理器RK3568,集成双核心架构GPU以及高效能NPU;最大支持8.... 发表于 06-29 10:40 •
RK3568J linux headers 采用Rockchip新一代64位处理器RK3568,集成双核心架构GPU以及高效能NPU;最大支持8.... 发表于 06-29 10:29 •
选择嵌入式设计软件时要考虑的前五个特性 选择正确的嵌入式软件开发工具和正确的工具供应商可能是一项挑战。确保您选择的软件支持您将使用的设备.... 星星科技指导员 发表于 06-29 10:12 •
智能自助洗车机的硬件接口需求及解决方案 说到“洗车”,以前人们最先想到的应该就是汽车美容店人工洗车和自动洗车。 敏敏子呦 发表于 06-29 08:55 •
串口转HID键盘鼠标芯片沁恒CH9329特点与引脚图 CH9329 是一款串口转标准 USB HID 设备(键盘、鼠标、自定义 HID)芯片,根据不同的工.... hw13554961857 发表于 06-29 08:31 • 334次
我们知道,linux系统中用户空间和内核空间是隔离的,用户空间程序不能随意的访问内核空间数据,只能通.... Linux阅码场 发表于 06-28 17:33 • 202次
基于图的场景模型捕获关键的设计和验证知识,通过通用模型实现 SoC 项目团队成员之间更好的沟通,.... 星星科技指导员 发表于 06-28 14:55 • 109次
虚拟硬件平台为开发人员带来了光明的未来,免除了他们等待硬件可用性的痛苦,并提供了硬件开发板无法提.... 星星科技指导员 发表于 06-28 14:42 • 125次
许多嵌入式应用程序都能够从 Flash 技术中受益。例如,集成远程信息处理系统将车队交互、GPS.... 星星科技指导员 发表于 06-28 14:15 • 235次
作为额外的奖励,当 Linux 被故意崩溃时,视频会消失,但音乐会在安全模式下播放,不会出现任何可听.... 星星科技指导员 发表于 06-28 11:53 • 117次
即使桌面平台可以保证从现在起大约五年后,Linux 内核和相关的发行版也是移动的目标。内核和标准库在.... 星星科技指导员 发表于 06-28 11:45 • 181次
使用Eclipse Process Framework构建嵌入式软件 在设计医疗设备时,FDA QSR 规定的设计指南和法规可以与系统和软件开发中的最佳实践同时解决。.... 发表于 06-28 11:35 •
高速USB总线转接芯片CH347概述、特点及封装 CH347是一款高速USB总线转接芯片,通过USB总线提供异步串口、I2C同步串行接口、SPI同步串.... hw13554961857 发表于 06-28 10:33 • 151次
CH341是一个USB总线的转接芯片,通过USB总线提供异步串口、打印口、并口以及常用的2线和4线等.... hw13554961857 发表于 06-28 09:42 • 103次
CH9101是一个USB总线的转接芯片,实现USB转异步串口。提供了常用的MODEM联络信号,用于为.... hw13554961857 发表于 06-28 09:26 •
USB总线的转接芯片CH9102概述及特点 CH9102是一个USB总线的转接芯片,实现USB转高速异步串口。提供了常用的MODEM联络信号,用.... hw13554961857 发表于 06-28 09:14 •
当一个文件在Windows和Linux上交替操作后,经常遇到一些莫名其妙的问题,如shell脚本无法.... 一口Linux 发表于 06-27 15:18 •
RK3568JQ Linux_Upgrade_Tool_v1.59 iCore-3568JQ板载 RK3568J 四核 64 位工业级处理器,支持 8GB 大内存;支持.... 发表于 06-27 14:27 •
TI的Sitara AM6442实时网络处理器 AM6442 的集成 Cortex-A53 内核为 Linux 应用程序提供了理想的计算特性,并.... 发表于 06-27 14:24 • 290次
RK3568JQ Linux_SDK源码包 iCore-3568JQ板载 RK3568J 四核 64 位工业级处理器,支持 8GB 大内存;支持.... 发表于 06-27 14:23 •
RK3568JQ firfly linux repack iCore-3568JQ板载 RK3568J 四核 64 位工业级处理器,支持 8GB 大内存;支持.... 发表于 06-27 14:18 •
RK3568JQ linux-headers iCore-3568JQ板载 RK3568J 四核 64 位工业级处理器,支持 8GB 大内存;支持.... 发表于 06-27 14:13 •
基于ANSI C加密库的RTCA DO-178C的DAL A支持 鉴于与重新启动航空电子系统相关的严格性能要求,wolfSSL 的服务组织随时为希望跟上公司技术的.... 星星科技指导员 发表于 06-27 14:09 • 127次
KTM50X0视频拓展芯片概述、功能特点及应用场景 主要用于主机设备与显示设备高速率的视频拓展芯片,集合了DP,USB-C,HDMI等音视频信号。拓展出.... 杨云 发表于 06-27 13:27 • 165次
这些是您可能每天都在使用的各种基于 Linux 的嵌入式系统背后的关键构建块,甚至可能不知道它们运行.... 星星科技指导员 发表于 06-27 11:56 • 178次
单芯片USB 2.0转10/100M以太网控制电路简介 SR9900是一个高集成度、超低功耗、单芯片USB 2.0转10/100M以太网控制电路。为各类应用.... 国产芯片替换(IC) 大全 发表于 06-27 11:16 • 148次
PL2586 USB2.0高速4端口集线器控制器概述及特点 PL2586是USB 2.0高速4端口集线器控制器的高性能解决方案,完全符合通用串行总线规范2.0。.... 国产芯片替换(IC) 大全 发表于 06-27 11:00 • 501次
NVIDIA 联合发起 Linux 基金会项目,致力于实现数据中心创新的大众化;进一步向软件提供商、.... NVIDIA英伟达 发表于 06-24 15:00 • 119次
当要学习一个新知识点时,比较好的过程是先理解出现这个技术点的背景原因,同期其他解决方案,新技术点解决.... 一口Linux 发表于 06-24 11:35 • 198次
用于 Wi-Fi 和蓝牙网状网络的高度集成片上系统 (SoC) 的可用性显着提高了数据速度、覆盖.... 星星科技指导员 发表于 06-24 10:39 • 172次
4端口USB HUB控制器芯片CH334和CH335概述及特点 沁恒CH334和CH335是符合USB2.0协议规范的全速,下行端口支持USB2.0高速480Mbp.... 国产芯片替换(IC) 大全 发表于 06-24 09:45 • 214次
NB7NPQ7022M 3.3 V USB 3.1双通道高增益线性转接驱动器 7022M是一款3.3 V双通道,高增益,转接驱动器,适用于支持5 Gbps和10 Gbps数据速率的USB 3.1 Gen 1和USB 3.1 Gen 2应用。信号完整性因PCB走线,传输电缆和符号间干扰(ISI)而降低。 NB7NPQ7022M通过在输入接收器上实现不同的均衡电平和输出发送器上的平坦增益放大来补偿这些损耗。平坦增益和均衡由四级控制引脚控制。每个通道都有一组独立的控制引脚,可以实现信号优化。上电后,NB7NPQ7022M定期检查两个TX输出对,以获得接收器连接。当在两个通道上检测到接收器时,RX端接变为使能状态,NB7NPQ7022M设置为执行转接驱动器功能.NB7NPQ7022M采用小型3 x 3 mm UQFN16封装,可在-40的整个工业温度范围内工作°C至85°C。 特性 3.3 V±5%电源 低功耗:活动模式下114mA 支持USB 3.1 Gen 1和USB 3.1 Gen 2数据速率 自动接收器终止检测 集成输入和输出终止 独立,可选均衡和平坦增益 热插拔功能 小型3 x 3 x 0.5 mm UQFN16封装,流通设计t easy PCB布局 工作温度范围:-40C至85C 应用 终端产品 USB3.1 Type-C和... 发表于 07-31 19:02 • 227次
NB7NPQ7041M USB 3.1四通道/双端口线性转接驱动器 3.3 V 7041M是一款3.3 V四通道/双端口线性转接驱动器,适用于支持5 Gbps和10 Gbps数据速率的USB 3.1 Gen 1和USB 3.1 Gen 2应用。信号完整性因PCB走线,传输电缆和符号间干扰(ISI)而降低。 NB7NPQ7041M通过在输入接收器上实现不同的均衡电平和输出发送器上的平坦增益放大来补偿这些损耗。平坦增益和均衡由四级控制引脚控制。每个通道都有一组独立的控制引脚,可以实现信号优化。上电后,NB7NPQ7041M定期检查每个端口的两个TX输出对,以进行接收器连接。当在两个通道上检测到接收器时,RX端接变为相应端口的启用,并设置为执行转接驱动器功能。一旦TX输出检测到50欧姆端接,端口变为活动状态,并且NB7NPQ7041M设置为执行转接功能。端口AB(通道A和B)和端口CD(通道C和D)彼此独立.NB7NPQ7041M采用3.1 x 4.3 mm小型X2QFN34封装,可在整个工业温度范围内工作, - 40°C至85°C。 特性 3.3 V±5%电源 支持USB 3.1 Gen 1和USB 3.1 Gen 2数据速率 集成输入和输出端接 独立,可选均衡和平坦增益 易于PCB布局的流通式设计 工作温度范围:-40°C至85°C ... 发表于 07-31 19:02 • 289次
NB7NPQ7042M 3.3 V USB 3.1四通道/双端口线性转接驱动器 7042M是一款3.3 V四通道/双端口线性转接驱动器,适用于支持5 Gbps和10 Gbps数据速率的USB 3.1 Gen 1和USB 3.1 Gen 2应用。信号完整性因PCB走线,传输电缆和符号间干扰(ISI)而降低。 NB7NPQ7042M通过在输入接收器上实现不同的均衡电平和输出发送器上的平坦增益放大来补偿这些损耗。平坦增益和均衡由四级控制引脚控制。每个通道都有一组独立的控制引脚,可以实现信号优化。上电后,NB7NPQ7042M定期检查每个端口的TX输出对是否有接收器连接。当在两个通道上检测到接收器时,RX终端变为相应端口的启用,并设置为执行重定向驱动器功能。一旦TX输出检测到50欧姆终止,端口变为活动状态,并且NB7NPQ7042M设置为执行转接功能。端口AB(通道A和B)和端口CD(通道C和D)彼此独立.NB7NPQ7042M采用3.1 x 4.3 mm小型X2QFN34封装,可在整个工业温度范围内工作, - 40°C至85°C。 特性 3.3 V±5%电源 支持USB 3.1 Gen 1和USB 3.1 Gen 2数据速率 自动接收器终端检测 集成输入和输出终端 独立,可选择的均衡和平坦增益 具有热插拔功能 易于PCB布局的流... 发表于 07-31 19:02 • 367次
NB7VPQ904M 1.8V USB Type-C™DisplayPort™ALT模式10Gbps线性转接驱动器 904M是1.8 V USB Type-C™DisplayPort™备用模式线性转接驱动器,完全支持DisplayPort 1.4(8.1 Gbps)和USB 3.1 Gen 1 / Gen 2(5/10 Gbps)协议。信号完整性因PCB走线,传输电缆和符号间干扰(ISI)而降低。 NB7VPQ904M通过使用不同级别的用户可选平坦增益来补偿这些损失。均衡,为输出数据信号创建最佳眼图。 特性 1.8 V +/- 5%电源 4通道线性转接驱动器,支持高达10Gbps的数据速率 支持USB Type-C USB3.1 Gen 1 / Gen 2和DP1.4作为具有设备操作模式的备用模式 支持已集成USB3.1 的SOC。 DP1.4 MUX over USB Type-C 可用于USB Type-C电缆,以减少电缆损耗 用于DP AUX通道的USB Type-C SBU信号的集成开关 深度省电模式的芯片使能引脚 具有热插拔功能 ESD保护±4kV HBM 应用 终端产品 移动电话 计算:台式机,笔记本电脑和笔记本电脑平板电脑 带USB-C,USB或DP连接器的扩展坞 游戏控制台 智能电视 USB Type-C有源线 手机 计算:台式机,笔记本电脑和平板电脑 带US... 发表于 07-31 17:02 • 1513次
NB7NPQ1104M 3.3 V USB 3.1 Gen-2 10Gbps四通道/双端口线性转接驱动器 1104M是一款高性能2端口线性转接驱动器,专为支持5 Gbps和10 Gbps数据速率的USB 3.1 Gen 1和USB 3.1 Gen 2应用而设计。信号完整性因PCB走线,传输电缆和符号间干扰(ISI)而降低。 NB7NPQ1104M通过在输入接收器上实现不同的均衡电平和输出发送器上的平坦增益放大来补偿这些损耗。 NB7NPQ1104M为每个独立通道提供可编程均衡和平坦增益,以优化各种物理介质的性能。 NB7NPQ1104M包含一个自动接收器检测功能,用于确定输出是否有效。如果相应通道的信号检测器空闲一段时间,接收器检测环路将处于活动状态。如果未检测到负载,通道将移至“拔出模式”,或者由于不活动而返回低功耗模式(睡眠模式)。 NB7NPQ1104M采用3.5 x 9 mm WQFN42封装,工作温度范围为-40°C至85°C。 特性 3.3 V±0.3 V电源 5 Gbps 带线性放大器的10 Gbps串行链路 设备支持USB 3.1 Gen 1和USB 3.1 Gen 2数据速率 自动接收器检测 集成输入和输出端接 引脚可调节接收器均衡和平坦增益 100-差异CML I / O 自适应电源管理的自动休眠模式 热插拔功能 ESD... 发表于 07-31 17:02 • 276次
FPF2895C 限流负载开关含OVP和TRCB 28 V 5 A. 2895C具有28 V和5A额定电流限制电源开关,提供过流保护(OCP),过压保护(OVP)和真正反向电流模块(TRCB)来保护系统。具有典型值为27mΩ的低导通电阻,WL-CSP可在4 V至22 V的输入电压范围内工作.FPF2895C支持±10%的电流限制精度,500 mA至2 A的过流范围和± 5%的限流精度,2 A至5 A的过流范围,可选择的OVP,可选择的ON极性和可选的OCP行为等灵活操作,可根据系统要求进行优化。 FPF2895C可用于一个24焊球,1.67 mm x 2.60 mm晶圆级芯片级封装(WL-CSP),间距为0.4 mm。“ 特性 28V / 5A能力 宽输入电压范围:4V~22V 超低导通电阻 Typ。在5V和25°C时为27mΩ 外部RSET的可调电流限制: - 500 mA~5 A 带OV1和OV2逻辑输入的可选OVLO: - 5.95 V±50 mV - 10 V±100 mV - 16.8 V±300 mV - 23 V±460 mV 可选ON极性 可选择的过流行为: - 自动重启模式 - 当前来源模式 真实反向当前阻止 热关机 应用 终端产品 带OVP的USB Vbus电源开关和OCP整合 笔记本 平板电脑 PAD 监视器 ... 发表于 07-31 14:02 • 488次
FPF2895V 符合AEC Q100标准(2级)限流负载开关 带OVP和TRCB 28 V 5 A 2895V具有28 V和5A额定电流限制电源开关,提供过流保护(OCP),过压保护(OVP)和真正反向电流模块(TRCB)来保护系统。具有低导通电阻,典型值为27 m,WL-CSP可在4 V至22 V的输入电压范围内工作。 FPF2895V支持±10%的电流限制精度,过电流范围为500 mA至2 A和±5%的电流限制精度,2 A至5 A的过流范围,灵活的操作,如可选择的OVP,可选择的ON极性和可选择的OCP行为,可根据系统要求进行优化。 FPF2895V提供24焊球,1.67 mm x 2.60 mm晶圆级芯片级封装(WL-CSP),0.4 mmpitch。“ 特性 AEC- Q100合格(2级) 28V / 5A能力 超低导通电阻:典型值。在5V和25°C时为27mΩ 宽输入电压范围:4V~22V 外部RSET的可调电流限制: - 500 mA~5 A 具有OV1和OV2逻辑输入的可选OVLO: - 5.95 V±50 mV - 10 V±100 mV - 16.8 V±300 mV - 23 V±460 mV 可选ON极性 可选择的过电流行为: - 自动重启模式 - 电流源模式 真正的反向电流阻断 热关断 打开排水故障FLAGB输出 UL60950-1 IEC 6095... 发表于 07-31 08:02 • 390次
NCP6922C LDO稳压器 双通道 4通道PMIC 双DC-DC转换器 2C是安森美半导体迷你电源管理IC系列的一部分。它经过优化,可提供电池供电的便携式应用子系统,如相机功能,微处理器等。该器件集成了两个高效率800 mA降压DC-DC转换器,具有DVS(动态电压调节)和两个低压差(LDO)稳压器在4x4 mm 20引脚WQFN封装中。 特性 优势 超低静态电流(典型值82 uA) 节省电池寿命 I 2完全可编程 C 提供设计灵活性 两个低噪声,低压差稳压器,可编程输出电压1.0 V至3.3 V,50 mV步进,2 x 150 mA和输出电流能力,50 uVrms典型低输出噪声 提供设计灵活性 两个DC-DC转换器,效率95%,可编程输出电压0.6 V至3.3 V,12.5 mV步进,800 mA输出电流能力 应用 终端产品 电池供电应用电源管理 核心电压低的处理器电源 相机模块 外围子系统 USB供电设备 游戏系统 数码相机 机顶盒框 GPS 车载信息娱乐 电路图、引脚图和封装图... 发表于 07-30 09:02 • 442次
NCP6324 同步降压转换器 3 MHz 2.0 A. 4B / C是一系列同步降压转换器,经过优化,可为一节锂离子电池或三节碱性/镍镉/镍氢电池供电的便携式应用提供不同子系统。这些器件能够在外部可调电压下提供高达2 A的电流。采用3 MHz开关频率工作可以采用小尺寸电感和电容。输入电源电压前馈控制用于处理宽输入电压范围。同步整流和自动PWM / PFM省电模式可提高系统效率。 NCP6324B / C采用节省空间的2.0 x 2.0 x 0.75 mm WDFN-8封装。 特性 优势 2.5 V至5.5 V输入电压范围 支持最新电池 3 MHz开关频率 降低输出电感和电容尺寸 自动省电模式(NCP6324B)或操作模式选择(NCP6324C) 降低静态电流,节省电池寿命 应用 终端产品 Portable 无线应用 计算与安全外围设备应用 消费类应用 移动电话,智能手机和PDA 便携式媒体播放器 数码相机 USB供电设备 游戏及娱乐系统 电路图、引脚图和封装图... 发表于 07-30 05:02 • 305次
FAN53880 一个降压 一个升压和四个LDO PMIC 80是一款用于移动电源应用的低静态电流PMIC。 PMIC包含一个降压,一个升压和四个低噪声LDO。 特性 晶圆级芯片级封装(WLCSP) 可编程输出电压 软启动(SS)浪涌电流限制 可编程启动/降压排序 中断报告的故障保护 低电流待机和关机模式 降压转换器:1.2A,VIN范围: 2.5V至5.5V,VOUT范围:0.6V至3.3V 升压转换器:1.0A,VIN范围:2.5V至5.5V,VOUT范围:3.0V至5.7V 四个LDO:300mA,VIN范围:1.9V至5.5V,VOUT范围:0.8V至3.3V 应用 终端产品 电池和USB供电设备 智能手机 平板电脑 小型相机模块 电路图、引脚图和封装图... 发表于 07-30 04:02 • 598次
NCP1597B 同步降压转换器 1 MHz 2.0 A. 7B是一款固定的1 MHz,高输出电流,同步PWM转换器,集成了低电阻,高侧P沟道MOSFET和低侧N沟道MOSFET。 NCP1597B利用电流模式控制提供快速瞬态响应和出色的环路稳定性。它将输入电压从4.0 V调节至5.5 V,输出电压低至0.8 V,最高可提供2 A. NCP1597B具有固定内部开关频率(FSW)和内部软启动等功能。限制浪涌电流。使用EN引脚,关断电源电流最大降至3μA。其他功能包括逐周期电流限制;短路保护,低压差模式,省电模式和热关断。该器件还采用NCP1597A下的6引脚3x3mm DFN封装。 特性 优势 输入电压范围:4.0 V至5.5 V 优化用于+ 5V输入 内部140mΩ高侧开关P-FET和90mΩ低侧N-FET 高效率运作 固定1 MHz开关频率 小输出电感和输出电容 逐周期电流限制 保护功能 过热保护 保护功能 使用预偏置输出负载启动 与uP核心和I / O要求兼容 0.8 V +/- 1.5%参考电压 能够输出低输出电压 轻载时的省电模式 轻载时提高效率 应用 终端产品 + 5V DC-DC稳压器 机顶盒 液晶电视/数字电视/等离子电... 发表于 07-30 04:02 • 320次
NCP1599 同步降压转换器 1 MHz 3.0 A. 9是一款固定的1 MHz,高输出电流,同步PWM转换器,集成了低电阻,高侧P沟道MOSFET和低侧N沟道MOSFET。 NCP1599利用内部补偿电流模式控制,提供良好的瞬态响应,易于实现和出色的环路稳定性。它可将输入电压从3.0 V调节至5.5 V,输出电压低至0.8 V,并可提供高达3.0 A的负载电流。 NCP1599包括一个内部固定的开关频率(FSW)和一个内部软启动,以限制浪涌电流。其他功能包括逐周期电流限制,短路保护,省电模式和热关断。 特性 优势 输入电压范围为2.7 V至5.5 V 能够与3.3 V或5 V电压轨一起使用 内部140mΩ/90mΩMOSFET 满负荷时的高效率 逐周期电流限制 保护功能 过温保护 保护功能 使用预偏置输出负载启动 兼容uP核心和I / O要求 0.8 V +/- 1.5%参考电压 能够输出低输出电压 轻载期间的省电模式 提高效率在轻载时 应用 终端产品 + 5V DC-DC稳压器 机顶盒 液晶电视/数字电视/等离子电视 USB供电设备 电路图、引脚图和封装图... 发表于 07-30 03:02 • 235次
NCP1529 降压转换器 DC-DC 高效率 可调节输出电压 低纹波 1.7 MHz 1 A. 9降压型DC-DC转换器是一款单片集成电路,适用于由一节锂离子电池或三节碱性/镍镉/镍氢电池供电的便携式应用。该器件可在外部可调范围为0.9 V至3.9 V或固定为1.2 V或1.35 V的输出范围内提供高达1.0 A的电流。它使用同步整流来提高效率并减少外部元件数量。该器件还内置1.7 MHz(标称)振荡器,通过允许使用小型电感器和电容器来减小元件尺寸。自动切换PWM / PFM模式可提高系统效率。 其他功能包括集成软启动,逐周期电流限制和热关断保护。 NCP1529采用节省空间的扁平2x2x0.5 mm UDFN6封装和TSOP-5封装。 特性 优势 96%效率,28 uA静态电流,0.3 uA关断电流 延长电池续航时间和'播放时间' 1.7 MHz开关频率 允许使用更小的电感和电容器 在轻负载条件下自动切换PWM和PFM模式 轻载时的低功耗 可调输出电压0.9V至3.9V 即使在PFM模式下,同类最佳低纹波 应用 终端产品 电池供电应用电源管理 核心电压低的处理器电源 USB供电设备 低压直流电源电源管理 手机,智能手机和掌上电脑 MP3播放器和便携式音频系统 电路图、引脚图和封装图... 发表于 07-30 02:02 • 1111次
NCV6334 3.0 MHz 2.0 A PFM / PWM同步降压转换器 具有良好的功率 4B是一款同步降压转换器,经过优化,可为由一节锂离子电池或三节碱性/镍镉/镍氢电池供电的便携式应用提供不同的子系统。该器件能够在外部可调电压下提供高达2 A的电流。采用3 MHz开关频率工作可以采用小尺寸电感和电容。输入电源电压前馈控制用于处理宽输入电压范围。同步整流可提高系统效率。 NCV6354采用节省空间的扁平2.0x2.0x0.75 mm WDFN-8封装。 特性 优势 2.3 V至5.5 V输入电压范围 支持最新电池 3 MHz开关频率 降低输出电感和电容尺寸 自动省电模式 降低静态当前 应用 终端产品 消费者应用 计算与技术外围设备应用 游戏和娱乐系统 USB供电设备 电路图、引脚图和封装图... 发表于 07-30 01:02 • 252次
NCP6924 6通道电源管理IC(PMIC) 带有2个DC-DC转换器和4个LDO 4是安森美半导体迷你电源管理IC系列的一部分。它经过优化,可提供电池供电的便携式应用子系统,如相机模块,微处理器或任何外围设备。该器件集成了两个高效1000 mA降压DC-DC转换器,带有DVS(动态电压调节)和四个低压差(LDO)稳压器,采用WLCSP-30 2.46 x 2.06mm封装。 特性 优势 非常小的封装2.46 x 2.06 mm 减少PCB空间 超低静态电流(典型值105 uA) 节省电池寿命 I 2 C可访问的先前启用设备允许在启动系统之前更改设置 提供设计灵活性 两个DC-DC转换器,效率95%,可编程输出电压0.6 V至3.3 V,12.5 mV步进,1000 mA输出电流能力 四个低噪声,低压差稳压器,可编程输出电压1.0 V至3.3 V,50 mV步进,2 x 150 mA和2 x 300mA输出电流能力,50 uVrms典型低输出噪声 应用 终端产品 电池供电的应用电源管理 核心电压低的处理器的电源 相机模块 外围子系统 USB供电设备 智能手机 平板电脑 可穿戴设备 MP3播放器 电路图、引脚图和封装图... 发表于 07-30 01:02 • 387次
NCV6323 同步降压转换器 3 MHz 2 A. 3是一款同步降压转换器,经过优化,可为一节锂离子电池或三节碱性/镍镉/镍氢电池供电的便携式应用提供不同的子系统。这些器件能够在外部可调电压下提供高达2 A的电流。采用3 MHz开关频率工作可以采用小尺寸电感和电容。输入电源电压前馈控制用于处理宽输入电压范围。同步整流可提高系统效率。 NCV6323采用节省空间的2.0 x 2.0 x 0.75 mm WDFN-8封装。 特性 优势 2.5 V至5.5 V输入电压范围 支持最新电池 3 MHz开关频率 降低输出电感和电容尺寸 最多2 A输出电流 应用 终端产品 计算 外围设备应用 消费类应用 USB供电设备 游戏和娱乐系统 电路图、引脚图和封装图... 发表于 07-30 00:02 • 399次
NCP6925 电源管理IC(PMIC) 7通道 带2个DC-DC转换器和5个LDO 5是安森美半导体迷你电源管理IC系列的一部分。它经过优化,可提供电池供电的便携式应用子系统,如相机模块,微处理器或任何外围设备。该器件集成了两个高效1000 mA降压DC-DC转换器和DVS(动态电压调节)以及五个低压差(LDO)稳压器,采用WLCSP-36 2.36 x 2.36 mm封装。 特性 优势 2.36 x 2.36 mm WLCSP 0.4 mm间距 小空间应用 超低静态电流(典型值140μA) 节省电池寿命 Id检测能力 附件检测 2一般用途I / O引脚 可以控制内部或外部稳压器,或者可以用作内部序列触发输入 两个DC-DC转换器,效率95%,程序可输出电压0.6 V至3.3 V,12.5 mV步进,1000 mA输出电流能力 四个低噪声,低压差稳压器,可编程输出电压0.8 V至3.5 V,25 mV步进,300 mA输出电流能力,50μVrms典型低输出噪声 灵活的上电和下电顺序可通过I²C编程 三输入10位ADC 2个DC-DC转换器,95%效率,1 A输出电流能力,可编程输出电压0.6 V至3.3 V×12.5 mV步骤 5个低压差稳压器,300 mA输出电流能力,0.8 V至3.5 V,25 mV步进的可编程... 发表于 07-30 00:02 • 550次
LV5683P LDO稳压器 4通道 P是一款多线性稳压器,适用于USB硅调谐器汽车音响系统。该IC具有4个输出,VDD5V(3.3V),AUDIO(8.5V),SWU(3.3V)和USB5V(CD 8V:可用)。关于保护电路,它具有过流保护,过压保护和热关断功能。 VCC1(SWU和USB电源)是VCC的独立端子,接受较低的电压(例如来自DC / DC转换器),可以降低功耗。 特性 4系统稳压器 VDD5V(3.3V),AUDIO(8.5V),SWU(3.3V)和USB5V(CD 8V:可用) 过电流保护 过电压保护:典型21(除VDD外) 热关断Typ 175°C 应用Pch-LDMOS用于输出阶段 应用 汽车音响和信息娱乐系统 电路图、引脚图和封装图... 发表于 07-29 23:02 • 1779次
NCP81231 降压控制器 USB供电和C型应用 31 USB供电(PD)控制器是一款针对USB-PD C型解决方案进行了优化的同步降压控制器。它们是扩展坞,车载充电器,台式机和显示器应用的理想选择。 NCP81231采用I2C接口,可与uC连接,以满足USB-PD时序,压摆率和电压要求。 NCP81231工作在4.5V至28V 特性 优势 I2C可配置性 允许电压曲线,转换速率控制,定时等 带驱动程序的同步降压控制器 提高效率和使用标准mosfet 符合USB-PD规范 支持usb-pd个人资料 过压和过流保护 应用 终端产品 USB Type C 网络配件 消费者 停靠站 车载充电器s 网络中心 桌面 电路图、引脚图和封装图... 发表于 07-29 19:02 • 611次
NCP6992 AIRFUEL-MR无线电源发送器ASIC 2是一款无线电源ASIC,可提供符合AirFuel MR标准的非接触式6.78 MHz电力传输单元(PTU)所需的电源,测量和支持功能。 NCP6992与蓝牙信令协议(BLE)相结合,通过管理功率传输(包括效率和故障条件管理),有助于调整和优化发送器线圈的功率。 特性 输入电压范围4.5V至22V 提供小型7x7mm²可湿性侧翼电镀QFN-56封装,间距0.4mm 直接从墙上适配器或USB端口供电 可通过3.4 MHzI²C接口进行广泛编程 50 W功率升压控制器,具有可在9V至55.2V(200mV步进)下编程的转换器,具有OVP和自动控制输入选项 可配置的睡眠模式和使用直接输入控制的快速唤醒循环 In集成式降压转换器5V 500mA 2通用GPIO可用于逻辑I / O,ADC输入或时钟输出 系统LDO可编程为1.2V至3.6V,100 mV步进,带动态电压调节(DVS) USB BC 1.2检测的前端 具有OCP的四相可选6.78MHz PA驱动器 用于天线切换的PWM控制继电器驱动器 用于PA电源电压,电流和温度测量的10位ADC 一个阻抗控制检测器 具有ADC读数的差分... 发表于 07-29 18:02 • 378次