[PATCH 01/29] USB: serial: allow subdrivers to modify port-endpoint mapping

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Allow subdrivers to modify the port-endpoint mapping by passing the
endpoint descriptors to calc_num_ports.

The callback can now also be used to verify that the required endpoints
exists and abort probing otherwise.

This will allow us to get rid of a few hacks in subdrivers that are
already modifying the port-endpoint mapping (or aborting probe due to
missing endpoints), but only after the port structures have been setup.

Signed-off-by: Johan Hovold <johan@xxxxxxxxxx>
---
 drivers/usb/serial/f81534.c     |  3 ++-
 drivers/usb/serial/ipaq.c       |  6 ++++--
 drivers/usb/serial/mos7720.c    |  3 ++-
 drivers/usb/serial/mos7840.c    |  3 ++-
 drivers/usb/serial/mxuport.c    |  3 ++-
 drivers/usb/serial/quatech2.c   |  3 ++-
 drivers/usb/serial/sierra.c     |  3 ++-
 drivers/usb/serial/usb-serial.c | 19 ++++++-------------
 drivers/usb/serial/visor.c      |  6 ++++--
 include/linux/usb/serial.h      | 19 ++++++++++++++++---
 10 files changed, 42 insertions(+), 26 deletions(-)

diff --git a/drivers/usb/serial/f81534.c b/drivers/usb/serial/f81534.c
index 22f23a429a95..385087c008ed 100644
--- a/drivers/usb/serial/f81534.c
+++ b/drivers/usb/serial/f81534.c
@@ -611,7 +611,8 @@ static int f81534_find_config_idx(struct usb_serial *serial, u8 *index)
  * The f81534_calc_num_ports() will run to "new style" with checking
  * F81534_PORT_UNAVAILABLE section.
  */
-static int f81534_calc_num_ports(struct usb_serial *serial)
+static int f81534_calc_num_ports(struct usb_serial *serial,
+					struct usb_serial_endpoints *epds)
 {
 	u8 setting[F81534_CUSTOM_DATA_SIZE];
 	u8 setting_idx;
diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c
index ec1b8f2c1183..df5f1a7d7c6f 100644
--- a/drivers/usb/serial/ipaq.c
+++ b/drivers/usb/serial/ipaq.c
@@ -33,7 +33,8 @@ static int initial_wait;
 /* Function prototypes for an ipaq */
 static int  ipaq_open(struct tty_struct *tty,
 			struct usb_serial_port *port);
-static int  ipaq_calc_num_ports(struct usb_serial *serial);
+static int ipaq_calc_num_ports(struct usb_serial *serial,
+					struct usb_serial_endpoints *epds);
 static int  ipaq_startup(struct usb_serial *serial);
 
 static const struct usb_device_id ipaq_id_table[] = {
@@ -550,7 +551,8 @@ static int ipaq_open(struct tty_struct *tty,
 	return usb_serial_generic_open(tty, port);
 }
 
-static int ipaq_calc_num_ports(struct usb_serial *serial)
+static int ipaq_calc_num_ports(struct usb_serial *serial,
+					struct usb_serial_endpoints *epds)
 {
 	/*
 	 * some devices have 3 endpoints, the 3rd of which
diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c
index df45ebad5f6f..9ec3e4fb9678 100644
--- a/drivers/usb/serial/mos7720.c
+++ b/drivers/usb/serial/mos7720.c
@@ -973,7 +973,8 @@ static void mos7720_bulk_out_data_callback(struct urb *urb)
 		tty_port_tty_wakeup(&mos7720_port->port->port);
 }
 
-static int mos77xx_calc_num_ports(struct usb_serial *serial)
+static int mos77xx_calc_num_ports(struct usb_serial *serial,
+					struct usb_serial_endpoints *epds)
 {
 	u16 product = le16_to_cpu(serial->dev->descriptor.idProduct);
 	if (product == MOSCHIP_DEVICE_ID_7715)
diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c
index 3821c53fcee9..326d6c5055ef 100644
--- a/drivers/usb/serial/mos7840.c
+++ b/drivers/usb/serial/mos7840.c
@@ -2104,7 +2104,8 @@ static int mos7840_probe(struct usb_serial *serial,
 	return 0;
 }
 
-static int mos7840_calc_num_ports(struct usb_serial *serial)
+static int mos7840_calc_num_ports(struct usb_serial *serial,
+					struct usb_serial_endpoints *epds)
 {
 	int device_type = (unsigned long)usb_get_serial_data(serial);
 	int mos7840_num_ports;
diff --git a/drivers/usb/serial/mxuport.c b/drivers/usb/serial/mxuport.c
index c88215a0fa3d..bf543e6c05ea 100644
--- a/drivers/usb/serial/mxuport.c
+++ b/drivers/usb/serial/mxuport.c
@@ -946,7 +946,8 @@ static void mxuport_set_termios(struct tty_struct *tty,
  * Determine how many ports this device has dynamically.  It will be
  * called after the probe() callback is called, but before attach().
  */
-static int mxuport_calc_num_ports(struct usb_serial *serial)
+static int mxuport_calc_num_ports(struct usb_serial *serial,
+					struct usb_serial_endpoints *epds)
 {
 	unsigned long features = (unsigned long)usb_get_serial_data(serial);
 
diff --git a/drivers/usb/serial/quatech2.c b/drivers/usb/serial/quatech2.c
index fdbb904d153f..6ddcaa2de902 100644
--- a/drivers/usb/serial/quatech2.c
+++ b/drivers/usb/serial/quatech2.c
@@ -246,7 +246,8 @@ static inline int update_mctrl(struct qt2_port_private *port_priv,
 	return status;
 }
 
-static int qt2_calc_num_ports(struct usb_serial *serial)
+static int qt2_calc_num_ports(struct usb_serial *serial,
+					struct usb_serial_endpoints *epds)
 {
 	struct qt2_device_detail d;
 	int i;
diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c
index 465e851b2815..4c4ac4705ac0 100644
--- a/drivers/usb/serial/sierra.c
+++ b/drivers/usb/serial/sierra.c
@@ -85,7 +85,8 @@ static int sierra_vsc_set_nmea(struct usb_device *udev, __u16 enable)
 			USB_CTRL_SET_TIMEOUT);		/* int timeout       */
 }
 
-static int sierra_calc_num_ports(struct usb_serial *serial)
+static int sierra_calc_num_ports(struct usb_serial *serial,
+					struct usb_serial_endpoints *epds)
 {
 	int num_ports = 0;
 	u8 ifnum, numendpoints;
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index 747dd414bef9..f0761f491c5f 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -710,17 +710,6 @@ static const struct tty_port_operations serial_port_ops = {
 	.shutdown		= serial_port_shutdown,
 };
 
-struct usb_serial_endpoints {
-	unsigned char num_bulk_in;
-	unsigned char num_bulk_out;
-	unsigned char num_interrupt_in;
-	unsigned char num_interrupt_out;
-	struct usb_endpoint_descriptor *bulk_in[MAX_NUM_PORTS];
-	struct usb_endpoint_descriptor *bulk_out[MAX_NUM_PORTS];
-	struct usb_endpoint_descriptor *interrupt_in[MAX_NUM_PORTS];
-	struct usb_endpoint_descriptor *interrupt_out[MAX_NUM_PORTS];
-};
-
 static void find_endpoints(struct usb_serial *serial,
 					struct usb_serial_endpoints *epds)
 {
@@ -875,8 +864,12 @@ static int usb_serial_probe(struct usb_interface *interface,
 #endif
 	if (!num_ports) {
 		/* if this device type has a calc_num_ports function, call it */
-		if (type->calc_num_ports)
-			num_ports = type->calc_num_ports(serial);
+		if (type->calc_num_ports) {
+			retval = type->calc_num_ports(serial, epds);
+			if (retval < 0)
+				goto err_free_epds;
+			num_ports = retval;
+		}
 		if (!num_ports)
 			num_ports = type->num_ports;
 	}
diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c
index 337a0be89fcf..3f943f877ac2 100644
--- a/drivers/usb/serial/visor.c
+++ b/drivers/usb/serial/visor.c
@@ -40,7 +40,8 @@ static int  visor_open(struct tty_struct *tty, struct usb_serial_port *port);
 static void visor_close(struct usb_serial_port *port);
 static int  visor_probe(struct usb_serial *serial,
 					const struct usb_device_id *id);
-static int  visor_calc_num_ports(struct usb_serial *serial);
+static int  visor_calc_num_ports(struct usb_serial *serial,
+					struct usb_serial_endpoints *epds);
 static void visor_read_int_callback(struct urb *urb);
 static int  clie_3_5_startup(struct usb_serial *serial);
 static int  treo_attach(struct usb_serial *serial);
@@ -466,7 +467,8 @@ static int visor_probe(struct usb_serial *serial,
 	return retval;
 }
 
-static int visor_calc_num_ports(struct usb_serial *serial)
+static int visor_calc_num_ports(struct usb_serial *serial,
+					struct usb_serial_endpoints *epds)
 {
 	int num_ports = (int)(long)(usb_get_serial_data(serial));
 
diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h
index f1b8a8493762..da528818cfd8 100644
--- a/include/linux/usb/serial.h
+++ b/include/linux/usb/serial.h
@@ -181,6 +181,17 @@ static inline void usb_set_serial_data(struct usb_serial *serial, void *data)
 	serial->private = data;
 }
 
+struct usb_serial_endpoints {
+	unsigned char num_bulk_in;
+	unsigned char num_bulk_out;
+	unsigned char num_interrupt_in;
+	unsigned char num_interrupt_out;
+	struct usb_endpoint_descriptor *bulk_in[MAX_NUM_PORTS];
+	struct usb_endpoint_descriptor *bulk_out[MAX_NUM_PORTS];
+	struct usb_endpoint_descriptor *interrupt_in[MAX_NUM_PORTS];
+	struct usb_endpoint_descriptor *interrupt_out[MAX_NUM_PORTS];
+};
+
 /**
  * usb_serial_driver - describes a usb serial driver
  * @description: pointer to a string that describes this driver.  This string
@@ -196,8 +207,9 @@ static inline void usb_set_serial_data(struct usb_serial *serial, void *data)
  *	(0 = end-point size)
  * @bulk_out_size: bytes to allocate for bulk-out buffer (0 = end-point size)
  * @calc_num_ports: pointer to a function to determine how many ports this
- *	device has dynamically.  It will be called after the probe()
- *	callback is called, but before attach()
+ *	device has dynamically. It can also be used to verify the number of
+ *	endpoints or to modify the port-endpoint mapping. It will be called
+ *	after the probe() callback is called, but before attach().
  * @probe: pointer to the driver's probe function.
  *	This will be called when the device is inserted into the system,
  *	but before the device has been fully initialized by the usb_serial
@@ -249,7 +261,8 @@ struct usb_serial_driver {
 
 	int (*probe)(struct usb_serial *serial, const struct usb_device_id *id);
 	int (*attach)(struct usb_serial *serial);
-	int (*calc_num_ports) (struct usb_serial *serial);
+	int (*calc_num_ports)(struct usb_serial *serial,
+			struct usb_serial_endpoints *epds);
 
 	void (*disconnect)(struct usb_serial *serial);
 	void (*release)(struct usb_serial *serial);
-- 
2.12.0

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux