Exemple #1
0
static int cdc_ncm_bind(struct usbnet *dev, struct usb_interface *intf)
{
	/* MBIM backwards compatible function? */
	cdc_ncm_select_altsetting(dev, intf);
	if (cdc_ncm_comm_intf_is_mbim(intf->cur_altsetting))
		return -ENODEV;

	/* NCM data altsetting is always 1 */
	return cdc_ncm_bind_common(dev, intf, 1);
}
static int cdc_mbim_bind(struct usbnet *dev, struct usb_interface *intf)
{
	struct cdc_ncm_ctx *ctx;
	struct usb_driver *subdriver = ERR_PTR(-ENODEV);
	int ret = -ENODEV;
	u8 data_altsetting = 1;
	struct cdc_mbim_state *info = (void *)&dev->data;

	/* should we change control altsetting on a NCM/MBIM function? */
	if (cdc_ncm_select_altsetting(intf) == CDC_NCM_COMM_ALTSETTING_MBIM) {
		data_altsetting = CDC_NCM_DATA_ALTSETTING_MBIM;
		ret = cdc_mbim_set_ctrlalt(dev, intf, CDC_NCM_COMM_ALTSETTING_MBIM);
		if (ret)
			goto err;
		ret = -ENODEV;
	}

	/* we will hit this for NCM/MBIM functions if prefer_mbim is false */
	if (!cdc_ncm_comm_intf_is_mbim(intf->cur_altsetting))
		goto err;

	ret = cdc_ncm_bind_common(dev, intf, data_altsetting, dev->driver_info->data);
	if (ret)
		goto err;

	ctx = info->ctx;

	/* The MBIM descriptor and the status endpoint are required */
	if (ctx->mbim_desc && dev->status)
		subdriver = usb_cdc_wdm_register(ctx->control,
						 &dev->status->desc,
						 le16_to_cpu(ctx->mbim_desc->wMaxControlMessage),
						 cdc_mbim_wdm_manage_power);
	if (IS_ERR(subdriver)) {
		ret = PTR_ERR(subdriver);
		cdc_ncm_unbind(dev, intf);
		goto err;
	}

	/* can't let usbnet use the interrupt endpoint */
	dev->status = NULL;
	info->subdriver = subdriver;

	/* MBIM cannot do ARP */
	dev->net->flags |= IFF_NOARP;

	/* no need to put the VLAN tci in the packet headers */
	dev->net->features |= NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_FILTER;

	/* monitor VLAN additions and removals */
	dev->net->netdev_ops = &cdc_mbim_netdev_ops;
err:
	return ret;
}
Exemple #3
0
static int cdc_ncm_bind(struct usbnet *dev, struct usb_interface *intf)
{
	int ret;

	/* The MBIM spec defines a NCM compatible default altsetting,
	 * which we may have matched:
	 *
	 *  "Functions that implement both NCM 1.0 and MBIM (an
	 *   “NCM/MBIM function”) according to this recommendation
	 *   shall provide two alternate settings for the
	 *   Communication Interface.  Alternate setting 0, and the
	 *   associated class and endpoint descriptors, shall be
	 *   constructed according to the rules given for the
	 *   Communication Interface in section 5 of [USBNCM10].
	 *   Alternate setting 1, and the associated class and
	 *   endpoint descriptors, shall be constructed according to
	 *   the rules given in section 6 (USB Device Model) of this
	 *   specification."
	 *
	 * Do not bind to such interfaces, allowing cdc_mbim to handle
	 * them
	 */
#if IS_ENABLED(CONFIG_USB_NET_CDC_MBIM)
	if ((intf->num_altsetting == 2) &&
	    !usb_set_interface(dev->udev,
			       intf->cur_altsetting->desc.bInterfaceNumber,
			       CDC_NCM_COMM_ALTSETTING_MBIM)) {
		if (cdc_ncm_comm_intf_is_mbim(intf->cur_altsetting))
			return -ENODEV;
		else
			usb_set_interface(dev->udev,
					  intf->cur_altsetting->desc.bInterfaceNumber,
					  CDC_NCM_COMM_ALTSETTING_NCM);
	}
#endif

	/* NCM data altsetting is always 1 */
	ret = cdc_ncm_bind_common(dev, intf, 1);

	/*
	 * We should get an event when network connection is "connected" or
	 * "disconnected". Set network connection in "disconnected" state
	 * (carrier is OFF) during attach, so the IP network stack does not
	 * start IPv6 negotiation and more.
	 */
	netif_carrier_off(dev->net);
	return ret;
}
Exemple #4
0
static int huawei_cdc_ncm_bind(struct usbnet *usbnet_dev,
			       struct usb_interface *intf)
{
	struct cdc_ncm_ctx *ctx;
	struct usb_driver *subdriver = ERR_PTR(-ENODEV);
	int ret = -ENODEV;
	struct huawei_cdc_ncm_state *drvstate = (void *)&usbnet_dev->data;
	int drvflags = 0;

	/* altsetting should always be 1 for NCM devices - so we hard-coded
	 * it here. Some huawei devices will need the NDP part of the NCM package to
	 * be at the end of the frame.
	 */
	drvflags |= CDC_NCM_FLAG_NDP_TO_END;
	ret = cdc_ncm_bind_common(usbnet_dev, intf, 1, drvflags);
	if (ret)
		goto err;

	ctx = drvstate->ctx;

	if (usbnet_dev->status)
		/* The wMaxCommand buffer must be big enough to hold
		 * any message from the modem. Experience has shown
		 * that some replies are more than 256 bytes long
		 */
		subdriver = usb_cdc_wdm_register(ctx->control,
						 &usbnet_dev->status->desc,
						 1024, /* wMaxCommand */
						 huawei_cdc_ncm_wdm_manage_power);
	if (IS_ERR(subdriver)) {
		ret = PTR_ERR(subdriver);
		cdc_ncm_unbind(usbnet_dev, intf);
		goto err;
	}

	/* Prevent usbnet from using the status descriptor */
	usbnet_dev->status = NULL;

	drvstate->subdriver = subdriver;

err:
	return ret;
}
Exemple #5
0
static int cdc_mbim_bind(struct usbnet *dev, struct usb_interface *intf)
{
	struct cdc_ncm_ctx *ctx;
	struct usb_driver *subdriver = ERR_PTR(-ENODEV);
	int ret = -ENODEV;
	u8 data_altsetting = cdc_ncm_select_altsetting(dev, intf);
	struct cdc_mbim_state *info = (void *)&dev->data;

	/* Probably NCM, defer for cdc_ncm_bind */
	if (!cdc_ncm_comm_intf_is_mbim(intf->cur_altsetting))
		goto err;

	ret = cdc_ncm_bind_common(dev, intf, data_altsetting);
	if (ret)
		goto err;

	ctx = info->ctx;

	/* The MBIM descriptor and the status endpoint are required */
	if (ctx->mbim_desc && dev->status)
		subdriver = usb_cdc_wdm_register(ctx->control,
						 &dev->status->desc,
						 le16_to_cpu(ctx->mbim_desc->wMaxControlMessage),
						 cdc_mbim_wdm_manage_power);
	if (IS_ERR(subdriver)) {
		ret = PTR_ERR(subdriver);
		cdc_ncm_unbind(dev, intf);
		goto err;
	}

	/* can't let usbnet use the interrupt endpoint */
	dev->status = NULL;
	info->subdriver = subdriver;

	/* MBIM cannot do ARP */
	dev->net->flags |= IFF_NOARP;

	/* no need to put the VLAN tci in the packet headers */
	dev->net->features |= NETIF_F_HW_VLAN_CTAG_TX;
err:
	return ret;
}
Exemple #6
0
static int cdc_ncm_bind(struct usbnet *dev, struct usb_interface *intf)
{
	int ret;

	/* MBIM backwards compatible function? */
	cdc_ncm_select_altsetting(dev, intf);
	if (cdc_ncm_comm_intf_is_mbim(intf->cur_altsetting))
		return -ENODEV;

	/* NCM data altsetting is always 1 */
	ret = cdc_ncm_bind_common(dev, intf, 1);

	/*
	 * We should get an event when network connection is "connected" or
	 * "disconnected". Set network connection in "disconnected" state
	 * (carrier is OFF) during attach, so the IP network stack does not
	 * start IPv6 negotiation and more.
	 */
	netif_carrier_off(dev->net);
	return ret;
}
Exemple #7
0
static int huawei_cdc_ncm_bind(struct usbnet *usbnet_dev,
			       struct usb_interface *intf)
{
	struct cdc_ncm_ctx *ctx;
	struct usb_driver *subdriver = ERR_PTR(-ENODEV);
	int ret = -ENODEV;
	struct huawei_cdc_ncm_state *drvstate = (void *)&usbnet_dev->data;

	/* altsetting should always be 1 for NCM devices - so we hard-coded
	 * it here
	 */
	ret = cdc_ncm_bind_common(usbnet_dev, intf, 1);
	if (ret)
		goto err;

	ctx = drvstate->ctx;

	if (usbnet_dev->status)
		/* CDC-WMC r1.1 requires wMaxCommand to be "at least 256
		 * decimal (0x100)"
		 */
		subdriver = usb_cdc_wdm_register(ctx->control,
						 &usbnet_dev->status->desc,
						 256, /* wMaxCommand */
						 huawei_cdc_ncm_wdm_manage_power);
	if (IS_ERR(subdriver)) {
		ret = PTR_ERR(subdriver);
		cdc_ncm_unbind(usbnet_dev, intf);
		goto err;
	}

	/* Prevent usbnet from using the status descriptor */
	usbnet_dev->status = NULL;

	drvstate->subdriver = subdriver;

err:
	return ret;
}