Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bd877e48 authored by Bjørn Mork's avatar Bjørn Mork Committed by David S. Miller
Browse files

net: qmi_wwan: use a single bind function for all device types



Refactoring the bind code lets us use a common driver_info struct
for all supported devices, simplifying the code a bit.  The
real advantage is that devices using the CDC ECM interface
layout now also can be added dynamically using the new_id sysfs
interface.  This simplifies testing of new devices.

Signed-off-by: default avatarBjørn Mork <bjorn@mork.no>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 3ee24037
Loading
Loading
Loading
Loading
+16 −29
Original line number Diff line number Diff line
@@ -139,10 +139,18 @@ static int qmi_wwan_bind(struct usbnet *dev, struct usb_interface *intf)

	BUILD_BUG_ON((sizeof(((struct usbnet *)0)->data) < sizeof(struct qmi_wwan_state)));

	/* require a single interrupt status endpoint for subdriver */
	/* control and data is shared? */
	if (intf->cur_altsetting->desc.bNumEndpoints == 3) {
		info->control = intf;
		info->data = intf;
		goto shared;
	}

	/* else require a single interrupt status endpoint on control intf */
	if (intf->cur_altsetting->desc.bNumEndpoints != 1)
		goto err;

	/* and a number of CDC descriptors */
	while (len > 3) {
		struct usb_descriptor_header *h = (void *)buf;

@@ -231,8 +239,9 @@ static int qmi_wwan_bind(struct usbnet *dev, struct usb_interface *intf)
	if (status < 0)
		goto err;

shared:
	status = qmi_wwan_register_subdriver(dev);
	if (status < 0) {
	if (status < 0 && info->control != info->data) {
		usb_set_intfdata(info->data, NULL);
		usb_driver_release_interface(driver, info->data);
	}
@@ -241,20 +250,6 @@ static int qmi_wwan_bind(struct usbnet *dev, struct usb_interface *intf)
	return status;
}

/* Some devices combine the "control" and "data" functions into a
 * single interface with all three endpoints: interrupt + bulk in and
 * out
 */
static int qmi_wwan_bind_shared(struct usbnet *dev, struct usb_interface *intf)
{
	struct qmi_wwan_state *info = (void *)&dev->data;

	/*  control and data is shared */
	info->control = intf;
	info->data = intf;
	return qmi_wwan_register_subdriver(dev);
}

static void qmi_wwan_unbind(struct usbnet *dev, struct usb_interface *intf)
{
	struct qmi_wwan_state *info = (void *)&dev->data;
@@ -330,20 +325,12 @@ static const struct driver_info qmi_wwan_info = {
	.manage_power	= qmi_wwan_manage_power,
};

static const struct driver_info	qmi_wwan_shared = {
	.description	= "WWAN/QMI device",
	.flags		= FLAG_WWAN,
	.bind		= qmi_wwan_bind_shared,
	.unbind		= qmi_wwan_unbind,
	.manage_power	= qmi_wwan_manage_power,
};

#define HUAWEI_VENDOR_ID	0x12D1

/* map QMI/wwan function by a fixed interface number */
#define QMI_FIXED_INTF(vend, prod, num) \
	USB_DEVICE_INTERFACE_NUMBER(vend, prod, num), \
	.driver_info = (unsigned long)&qmi_wwan_shared
	.driver_info = (unsigned long)&qmi_wwan_info

/* Gobi 1000 QMI/wwan interface number is 3 according to qcserial */
#define QMI_GOBI1K_DEVICE(vend, prod) \
@@ -367,15 +354,15 @@ static const struct usb_device_id products[] = {
	/* 2. Combined interface devices matching on class+protocol */
	{	/* Huawei E392, E398 and possibly others in "Windows mode" */
		USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, USB_CLASS_VENDOR_SPEC, 1, 17),
		.driver_info        = (unsigned long)&qmi_wwan_shared,
		.driver_info        = (unsigned long)&qmi_wwan_info,
	},
	{	/* Pantech UML290 */
		USB_DEVICE_AND_INTERFACE_INFO(0x106c, 0x3718, USB_CLASS_VENDOR_SPEC, 0xf0, 0xff),
		.driver_info        = (unsigned long)&qmi_wwan_shared,
		.driver_info        = (unsigned long)&qmi_wwan_info,
	},
	{	/* Pantech UML290 - newer firmware */
		USB_DEVICE_AND_INTERFACE_INFO(0x106c, 0x3718, USB_CLASS_VENDOR_SPEC, 0xf1, 0xff),
		.driver_info        = (unsigned long)&qmi_wwan_shared,
		.driver_info        = (unsigned long)&qmi_wwan_info,
	},

	/* 3. Combined interface devices matching on interface number */
@@ -457,7 +444,7 @@ static int qmi_wwan_probe(struct usb_interface *intf, const struct usb_device_id
	 */
	if (!id->driver_info) {
		dev_dbg(&intf->dev, "setting defaults for dynamic device id\n");
		id->driver_info = (unsigned long)&qmi_wwan_shared;
		id->driver_info = (unsigned long)&qmi_wwan_info;
	}

	return usbnet_probe(intf, id);