/* * "DEVICE" = VBUS and "HOST" = !ID, so we have: * Both "DEVICE" and "HOST" can't be set as active at the same time * so if "HOST" is active (i.e. ID is 0) we keep "DEVICE" inactive * even if VBUS is on. * * Role | ID | VBUS * ------------------------------------ * [1] DEVICE | H | H * [2] NONE | H | L * [3] HOST | L | H * [4] HOST | L | L * * In case we have only one of these signals: * - VBUS only - we want to distinguish between [1] and [2], so ID is always 1 * - ID only - we want to distinguish between [1] and [4], so VBUS = ID
*/ staticvoid usb_conn_detect_cable(struct work_struct *work)
{ struct usb_conn_info *info; enum usb_role role; int id, vbus, ret;
info = container_of(to_delayed_work(work), struct usb_conn_info, dw_det);
/* check ID and VBUS */
id = info->id_gpiod ?
gpiod_get_value_cansleep(info->id_gpiod) : 1;
vbus = info->vbus_gpiod ?
gpiod_get_value_cansleep(info->vbus_gpiod) : id;
if (!id)
role = USB_ROLE_HOST; elseif (vbus)
role = USB_ROLE_DEVICE; else
role = USB_ROLE_NONE;
info->vbus_gpiod = devm_gpiod_get_optional(dev, "vbus", GPIOD_IN); if (IS_ERR(info->vbus_gpiod)) return PTR_ERR(info->vbus_gpiod);
if (!info->id_gpiod && !info->vbus_gpiod) {
dev_err(dev, "failed to get gpios\n"); return -ENODEV;
}
if (info->id_gpiod)
ret = gpiod_set_debounce(info->id_gpiod, USB_GPIO_DEB_US); if (!ret && info->vbus_gpiod)
ret = gpiod_set_debounce(info->vbus_gpiod, USB_GPIO_DEB_US); if (ret < 0)
info->debounce_jiffies = msecs_to_jiffies(USB_GPIO_DEB_MS);
if (IS_ERR(info->vbus)) return dev_err_probe(dev, PTR_ERR(info->vbus), "failed to get vbus\n");
info->role_sw = usb_role_switch_get(dev); if (IS_ERR(info->role_sw)) return dev_err_probe(dev, PTR_ERR(info->role_sw), "failed to get role switch\n");
ret = usb_conn_psy_register(info); if (ret) goto put_role_sw;
if (info->id_gpiod) {
info->id_irq = gpiod_to_irq(info->id_gpiod); if (info->id_irq < 0) {
dev_err(dev, "failed to get ID IRQ\n");
ret = info->id_irq; goto put_role_sw;
}
ret = devm_request_threaded_irq(dev, info->id_irq, NULL,
usb_conn_isr, USB_CONN_IRQF,
pdev->name, info); if (ret < 0) {
dev_err(dev, "failed to request ID IRQ\n"); goto put_role_sw;
}
}
if (info->vbus_gpiod) {
info->vbus_irq = gpiod_to_irq(info->vbus_gpiod); if (info->vbus_irq < 0) {
dev_err(dev, "failed to get VBUS IRQ\n");
ret = info->vbus_irq; goto put_role_sw;
}
ret = devm_request_threaded_irq(dev, info->vbus_irq, NULL,
usb_conn_isr, USB_CONN_IRQF,
pdev->name, info); if (ret < 0) {
dev_err(dev, "failed to request VBUS IRQ\n"); goto put_role_sw;
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.