diff options
Diffstat (limited to 'drivers/usb/class/cdc-acm.c')
| -rw-r--r-- | drivers/usb/class/cdc-acm.c | 79 | 
1 files changed, 42 insertions, 37 deletions
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 7f6f3ab5b8a6..30ef946a8e1a 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -173,7 +173,7 @@ static int acm_wb_alloc(struct acm *acm)  	for (;;) {  		wb = &acm->wb[wbn];  		if (!wb->use) { -			wb->use = 1; +			wb->use = true;  			wb->len = 0;  			return wbn;  		} @@ -191,7 +191,8 @@ static int acm_wb_is_avail(struct acm *acm)  	n = ACM_NW;  	spin_lock_irqsave(&acm->write_lock, flags);  	for (i = 0; i < ACM_NW; i++) -		n -= acm->wb[i].use; +		if(acm->wb[i].use) +			n--;  	spin_unlock_irqrestore(&acm->write_lock, flags);  	return n;  } @@ -201,7 +202,7 @@ static int acm_wb_is_avail(struct acm *acm)   */  static void acm_write_done(struct acm *acm, struct acm_wb *wb)  { -	wb->use = 0; +	wb->use = false;  	acm->transmitting--;  	usb_autopm_put_interface_async(acm->control);  } @@ -741,7 +742,7 @@ static void acm_port_shutdown(struct tty_port *port)  		if (!urb)  			break;  		wb = urb->context; -		wb->use = 0; +		wb->use = false;  		usb_autopm_put_interface_async(acm->control);  	} @@ -792,7 +793,7 @@ static int acm_tty_write(struct tty_struct *tty,  	wb = &acm->wb[wbn];  	if (!acm->dev) { -		wb->use = 0; +		wb->use = false;  		spin_unlock_irqrestore(&acm->write_lock, flags);  		return -ENODEV;  	} @@ -804,7 +805,7 @@ static int acm_tty_write(struct tty_struct *tty,  	stat = usb_autopm_get_interface_async(acm->control);  	if (stat) { -		wb->use = 0; +		wb->use = false;  		spin_unlock_irqrestore(&acm->write_lock, flags);  		return stat;  	} @@ -1196,9 +1197,6 @@ static int acm_probe(struct usb_interface *intf,  		return -EINVAL;  	} -	if (!intf->cur_altsetting) -		return -EINVAL; -  	if (!buflen) {  		if (intf->cur_altsetting->endpoint &&  				intf->cur_altsetting->endpoint->extralen && @@ -1221,39 +1219,42 @@ static int acm_probe(struct usb_interface *intf,  		call_intf_num = cmgmd->bDataInterface;  	if (!union_header) { -		if (call_intf_num > 0) { +		if (intf->cur_altsetting->desc.bNumEndpoints == 3) { +			dev_dbg(&intf->dev, "No union descriptor, assuming single interface\n"); +			combined_interfaces = 1; +			control_interface = data_interface = intf; +			goto look_for_collapsed_interface; +		} else if (call_intf_num > 0) {  			dev_dbg(&intf->dev, "No union descriptor, using call management descriptor\n"); -			/* quirks for Droids MuIn LCD */ -			if (quirks & NO_DATA_INTERFACE) { -				data_interface = usb_ifnum_to_if(usb_dev, 0); -			} else { -				data_intf_num = call_intf_num; -				data_interface = usb_ifnum_to_if(usb_dev, data_intf_num); -			} +			data_intf_num = call_intf_num; +			data_interface = usb_ifnum_to_if(usb_dev, data_intf_num);  			control_interface = intf;  		} else { -			if (intf->cur_altsetting->desc.bNumEndpoints != 3) { -				dev_dbg(&intf->dev,"No union descriptor, giving up\n"); -				return -ENODEV; -			} else { -				dev_warn(&intf->dev,"No union descriptor, testing for castrated device\n"); -				combined_interfaces = 1; -				control_interface = data_interface = intf; -				goto look_for_collapsed_interface; -			} +			dev_dbg(&intf->dev, "No union descriptor, giving up\n"); +			return -ENODEV;  		}  	} else { +		int class = -1; +  		data_intf_num = union_header->bSlaveInterface0;  		control_interface = usb_ifnum_to_if(usb_dev, union_header->bMasterInterface0);  		data_interface = usb_ifnum_to_if(usb_dev, data_intf_num); + +		if (control_interface) +			class = control_interface->cur_altsetting->desc.bInterfaceClass; + +		if (class != USB_CLASS_COMM && class != USB_CLASS_CDC_DATA) { +			dev_dbg(&intf->dev, "Broken union descriptor, assuming single interface\n"); +			combined_interfaces = 1; +			control_interface = data_interface = intf; +			goto look_for_collapsed_interface; +		}  	}  	if (!control_interface || !data_interface) {  		dev_dbg(&intf->dev, "no interfaces\n");  		return -ENODEV;  	} -	if (!data_interface->cur_altsetting || !control_interface->cur_altsetting) -		return -ENODEV;  	if (data_intf_num != call_intf_num)  		dev_dbg(&intf->dev, "Separate call control interface. That is not fully supported.\n"); @@ -1280,10 +1281,8 @@ look_for_collapsed_interface:  skip_normal_probe:  	/*workaround for switched interfaces */ -	if (data_interface->cur_altsetting->desc.bInterfaceClass -						!= CDC_DATA_INTERFACE_TYPE) { -		if (control_interface->cur_altsetting->desc.bInterfaceClass -						== CDC_DATA_INTERFACE_TYPE) { +	if (data_interface->cur_altsetting->desc.bInterfaceClass != USB_CLASS_CDC_DATA) { +		if (control_interface->cur_altsetting->desc.bInterfaceClass == USB_CLASS_CDC_DATA) {  			dev_dbg(&intf->dev,  				"Your device has switched interfaces.\n");  			swap(control_interface, data_interface); @@ -1876,11 +1875,6 @@ static const struct usb_device_id acm_ids[] = {  	/* NOTE: non-Nokia COMM/ACM/0xff is likely MSFT RNDIS... NOT a modem! */ -	/* Support for Droids MuIn LCD */ -	{ USB_DEVICE(0x04d8, 0x000b), -	.driver_info = NO_DATA_INTERFACE, -	}, -  #if IS_ENABLED(CONFIG_INPUT_IMS_PCU)  	{ USB_DEVICE(0x04d8, 0x0082),	/* Application mode */  	.driver_info = IGNORE_DEVICE, @@ -1906,6 +1900,17 @@ static const struct usb_device_id acm_ids[] = {  	.driver_info = IGNORE_DEVICE,  	}, +	/* Exclude ETAS ES58x */ +	{ USB_DEVICE(0x108c, 0x0159), /* ES581.4 */ +	.driver_info = IGNORE_DEVICE, +	}, +	{ USB_DEVICE(0x108c, 0x0168), /* ES582.1 */ +	.driver_info = IGNORE_DEVICE, +	}, +	{ USB_DEVICE(0x108c, 0x0169), /* ES584.1 */ +	.driver_info = IGNORE_DEVICE, +	}, +  	{ USB_DEVICE(0x1bc7, 0x0021), /* Telit 3G ACM only composition */  	.driver_info = SEND_ZERO_PACKET,  	},  |