diff options
Diffstat (limited to 'drivers/usb/core/message.c')
| -rw-r--r-- | drivers/usb/core/message.c | 63 | 
1 files changed, 45 insertions, 18 deletions
| diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 2bed83caacb1..9720e699f472 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -806,6 +806,48 @@ static int usb_string_sub(struct usb_device *dev, unsigned int langid,  	return rc;  } +static int usb_get_langid(struct usb_device *dev, unsigned char *tbuf) +{ +	int err; + +	if (dev->have_langid) +		return 0; + +	if (dev->string_langid < 0) +		return -EPIPE; + +	err = usb_string_sub(dev, 0, 0, tbuf); + +	/* If the string was reported but is malformed, default to english +	 * (0x0409) */ +	if (err == -ENODATA || (err > 0 && err < 4)) { +		dev->string_langid = 0x0409; +		dev->have_langid = 1; +		dev_err(&dev->dev, +			"string descriptor 0 malformed (err = %d), " +			"defaulting to 0x%04x\n", +				err, dev->string_langid); +		return 0; +	} + +	/* In case of all other errors, we assume the device is not able to +	 * deal with strings at all. Set string_langid to -1 in order to +	 * prevent any string to be retrieved from the device */ +	if (err < 0) { +		dev_err(&dev->dev, "string descriptor 0 read error: %d\n", +					err); +		dev->string_langid = -1; +		return -EPIPE; +	} + +	/* always use the first langid listed */ +	dev->string_langid = tbuf[2] | (tbuf[3] << 8); +	dev->have_langid = 1; +	dev_dbg(&dev->dev, "default language 0x%04x\n", +				dev->string_langid); +	return 0; +} +  /**   * usb_string - returns UTF-8 version of a string descriptor   * @dev: the device whose string descriptor is being retrieved @@ -837,24 +879,9 @@ int usb_string(struct usb_device *dev, int index, char *buf, size_t size)  	if (!tbuf)  		return -ENOMEM; -	/* get langid for strings if it's not yet known */ -	if (!dev->have_langid) { -		err = usb_string_sub(dev, 0, 0, tbuf); -		if (err < 0) { -			dev_err(&dev->dev, -				"string descriptor 0 read error: %d\n", -				err); -		} else if (err < 4) { -			dev_err(&dev->dev, "string descriptor 0 too short\n"); -		} else { -			dev->string_langid = tbuf[2] | (tbuf[3] << 8); -			/* always use the first langid listed */ -			dev_dbg(&dev->dev, "default language 0x%04x\n", -				dev->string_langid); -		} - -		dev->have_langid = 1; -	} +	err = usb_get_langid(dev, tbuf); +	if (err < 0) +		goto errout;  	err = usb_string_sub(dev, dev->string_langid, index, tbuf);  	if (err < 0) | 
