linux-usb.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Johan Hovold <johan@kernel.org>
To: Johan Hovold <johan@kernel.org>
Cc: Amireddy mallikarjuna reddy <mallikarjuna.reddy@ftdichip.com>,
	arun.pappan@ftdichip.com, sowjanya.reddy@ftdichip.com,
	malliamireddy009@gmail.com, linux-usb@vger.kernel.org,
	linux-kernel@vger.kernel.org
Subject: [PATCH 06/12] USB: serial: ftdi_sio: tighten device-type detection
Date: Sun, 11 Sep 2022 16:02:10 +0200	[thread overview]
Message-ID: <20220911140216.30481-7-johan@kernel.org> (raw)
In-Reply-To: <20220911140216.30481-1-johan@kernel.org>

Clean up and tighten the device-type detection, which is based on
bcdDevice.

Don't make assumptions about unknown (future) types (currently assumed
to be either FT2232C or FT-X depending on bNumInterfaces) and instead
log an error and refuse to bind so that we can add proper support when
needed.

Note that the bcdDevice values have been provided by FTDI.

Signed-off-by: Johan Hovold <johan@kernel.org>
---
 drivers/usb/serial/ftdi_sio.c | 118 ++++++++++++++++------------------
 1 file changed, 55 insertions(+), 63 deletions(-)

diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index 707dc3d67a19..f372f55a1bdf 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -1547,89 +1547,73 @@ static int get_lsr_info(struct usb_serial_port *port,
 	return 0;
 }
 
-
-/* Determine type of FTDI chip based on USB config and descriptor. */
-static void ftdi_determine_type(struct usb_serial_port *port)
+static int ftdi_determine_type(struct usb_serial_port *port)
 {
 	struct ftdi_private *priv = usb_get_serial_port_data(port);
 	struct usb_serial *serial = port->serial;
 	struct usb_device *udev = serial->dev;
-	unsigned version;
-	unsigned interfaces;
+	unsigned int version, ifnum;
+
+	version = le16_to_cpu(udev->descriptor.bcdDevice);
+	ifnum = serial->interface->cur_altsetting->desc.bInterfaceNumber;
 
-	/* Assume it is not the original SIO device for now. */
 	priv->baud_base = 48000000 / 2;
+	priv->channel = 0;
 
-	version = le16_to_cpu(udev->descriptor.bcdDevice);
-	interfaces = udev->actconfig->desc.bNumInterfaces;
-	dev_dbg(&port->dev, "%s: bcdDevice = 0x%x, bNumInterfaces = %u\n", __func__,
-		version, interfaces);
-	if (interfaces > 1) {
-		struct usb_interface *intf = serial->interface;
-		int ifnum = intf->cur_altsetting->desc.bInterfaceNumber;
-
-		/* Multiple interfaces.*/
-		if (version == 0x0800) {
-			priv->chip_type = FT4232H;
-			/* Hi-speed - baud clock runs at 120MHz */
-			priv->baud_base = 120000000 / 2;
-		} else if (version == 0x0700) {
-			priv->chip_type = FT2232H;
-			/* Hi-speed - baud clock runs at 120MHz */
-			priv->baud_base = 120000000 / 2;
-		} else
-			priv->chip_type = FT2232C;
-
-		if (ifnum == 0)
-			priv->channel = CHANNEL_A;
-		else if (ifnum == 1)
-			priv->channel = CHANNEL_B;
-		else if (ifnum == 2)
-			priv->channel = CHANNEL_C;
-		else if (ifnum == 3)
-			priv->channel = CHANNEL_D;
-
-		/* BM-type devices have a bug where bcdDevice gets set
-		 * to 0x200 when iSerialNumber is 0.  */
-		if (version < 0x500) {
-			dev_dbg(&port->dev,
-				"%s: something fishy - bcdDevice too low for multi-interface device\n",
-				__func__);
-		}
-	} else if (version < 0x200) {
-		/* Old device.  Assume it's the original SIO. */
-		priv->chip_type = SIO;
-		priv->baud_base = 12000000 / 16;
-	} else if (version < 0x400) {
-		/* Assume it's an FT8U232AM (or FT8U245AM) */
+	switch (version) {
+	case 0x200:
 		priv->chip_type = FT232A;
+
 		/*
-		 * It might be a BM type because of the iSerialNumber bug.
-		 * If iSerialNumber==0 and the latency timer is readable,
-		 * assume it is BM type.
+		 * FT232B devices have a bug where bcdDevice gets set to 0x200
+		 * when iSerialNumber is 0. Assume it is an FT232B in case the
+		 * latency timer is readable.
 		 */
 		if (udev->descriptor.iSerialNumber == 0 &&
 				_read_latency_timer(port) >= 0) {
-			dev_dbg(&port->dev,
-				"%s: has latency timer so not an AM type\n",
-				__func__);
 			priv->chip_type = FT232B;
 		}
-	} else if (version < 0x600) {
-		/* Assume it's an FT232BM (or FT245BM) */
+		break;
+	case 0x400:
 		priv->chip_type = FT232B;
-	} else if (version < 0x900) {
-		/* Assume it's an FT232RL */
+		break;
+	case 0x500:
+		priv->chip_type = FT2232C;
+		priv->channel = CHANNEL_A + ifnum;
+		break;
+	case 0x600:
 		priv->chip_type = FT232R;
-	} else if (version < 0x1000) {
-		/* Assume it's an FT232H */
+		break;
+	case 0x700:
+		priv->chip_type = FT2232H;
+		priv->channel = CHANNEL_A + ifnum;
+		priv->baud_base = 120000000 / 2;
+		break;
+	case 0x800:
+		priv->chip_type = FT4232H;
+		priv->channel = CHANNEL_A + ifnum;
+		priv->baud_base = 120000000 / 2;
+		break;
+	case 0x900:
 		priv->chip_type = FT232H;
-	} else {
-		/* Assume it's an FT-X series device */
+		priv->baud_base = 120000000 / 2;
+		break;
+	case 0x1000:
 		priv->chip_type = FTX;
+		break;
+	default:
+		if (version < 0x200) {
+			priv->chip_type = SIO;
+			priv->baud_base = 12000000 / 16;
+		} else {
+			dev_err(&port->dev, "unknown device type: 0x%02x\n", version);
+			return -ENODEV;
+		}
 	}
 
 	dev_info(&udev->dev, "Detected %s\n", ftdi_chip_name[priv->chip_type]);
+
+	return 0;
 }
 
 
@@ -2256,7 +2240,10 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port)
 
 	usb_set_serial_port_data(port, priv);
 
-	ftdi_determine_type(port);
+	result = ftdi_determine_type(port);
+	if (result)
+		goto err_free;
+
 	ftdi_set_max_packet_size(port);
 	if (read_latency_timer(port) < 0)
 		priv->latency = 16;
@@ -2271,6 +2258,11 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port)
 	}
 
 	return 0;
+
+err_free:
+	kfree(priv);
+
+	return result;
 }
 
 /* Setup for the USB-UIRT device, which requires hardwired
-- 
2.35.1


  parent reply	other threads:[~2022-09-11 14:03 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-09-11 14:02 [PATCH 00/12] USB: serial: ftdi_sio: type cleanup and HP/HA support Johan Hovold
2022-09-11 14:02 ` [PATCH 01/12] USB: serial: ftdi_sio: clean up chip type enum Johan Hovold
2022-09-11 14:02 ` [PATCH 02/12] USB: serial: ftdi_sio: drop redundant chip type comments Johan Hovold
2022-09-11 14:02 ` [PATCH 03/12] USB: serial: ftdi_sio: rename chip types Johan Hovold
2022-09-11 14:02 ` [PATCH 04/12] USB: serial: ftdi_sio: include FT2232D in type string Johan Hovold
2022-09-11 14:02 ` [PATCH 05/12] USB: serial: ftdi_sio: rename channel index Johan Hovold
2022-09-11 14:02 ` Johan Hovold [this message]
2022-09-11 14:02 ` [PATCH 07/12] USB: serial: ftdi_sio: clean up modem-status handling Johan Hovold
2022-09-11 14:02 ` [PATCH 08/12] USB: serial: ftdi_sio: clean up attribute handling Johan Hovold
2022-09-11 14:02 ` [PATCH 09/12] USB: serial: ftdi_sio: clean up baudrate request Johan Hovold
2022-09-11 14:02 ` [PATCH 10/12] USB: serial: ftdi_sio: assume hi-speed type Johan Hovold
2022-09-11 14:02 ` [PATCH 11/12] USB: serial: ftdi_sio: simplify divisor handling Johan Hovold
2022-09-11 14:02 ` [PATCH 12/12] USB: serial: ftdi_sio: add support for HP and HA devices Johan Hovold

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220911140216.30481-7-johan@kernel.org \
    --to=johan@kernel.org \
    --cc=arun.pappan@ftdichip.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-usb@vger.kernel.org \
    --cc=malliamireddy009@gmail.com \
    --cc=mallikarjuna.reddy@ftdichip.com \
    --cc=sowjanya.reddy@ftdichip.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).