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

[MiNT] [PATCH][1/3] Add support for multiple interfaces in USB devices



Until now only the first interface of an USB device was supported,
this means that if for example a device had a mass storage function in
his second interface we couldn't handle it.

Commit message:

Add support for multiple interfaces in USB devices.
Contributed by David Galvez.
Index: sys/usb/src.km/usb.c
===================================================================
RCS file: /mint/freemint/sys/usb/src.km/usb.c,v
retrieving revision 1.20
diff -u -8 -r1.20 usb.c
--- sys/usb/src.km/usb.c	25 Nov 2014 10:04:13 -0000	1.20
+++ sys/usb/src.km/usb.c	23 Feb 2015 09:19:20 -0000
@@ -790,18 +790,21 @@
 		long i;
 
 		ALERT(("USB disconnect on device %ld", dev->parent->devnum));
 		DEBUG(("USB device disconnect on device %s", dev->parent->prod));
 
 		DEBUG(("USB disconnected, device number %ld", dev->devnum));
 		DEBUG(("USB device disconnected, device %s", dev->prod));
 
-		if(dev->driver)
-			dev->driver->disconnect(dev);
+		/* Disconnect drivers from interfaces */
+		for (i = 0; i < dev->config.no_of_if; i++) {
+			if(dev->config.if_desc[i].driver)
+				dev->config.if_desc[i].driver->disconnect(dev);
+		}
 
 		/* Free up all the children.. */
 		for (i = 0; i < dev->maxchild; i++)
 		{
 			DEBUG(("Disconnect children %ld", dev->children[i]->devnum));
 			struct usb_device *child = dev->children[i];
 			DEBUG(("child %lx", child));
 			usb_disconnect(child);
@@ -885,16 +888,17 @@
 long usb_new_device(struct usb_device *dev)
 {
 	long addr, err;
 	unsigned char *tmpbuf;
 	long tmp;
 	struct usb_device_descriptor *desc;
 	long port = -1;
 	struct usb_device *parent = dev->parent;
+	int idx = 0;
 
 	DEBUG(("usb_new_device: "));
 
 	/* We still haven't set the Address yet */
 	addr = dev->devnum;
 	dev->devnum = 0;
 
 	/* send 64-byte GET-DEVICE-DESCRIPTOR request.  Since the descriptor is
@@ -1050,17 +1054,19 @@
 	DEBUG(("Manufacturer %s", dev->mf));
 	DEBUG(("Product      %s", dev->prod));
 	DEBUG(("SerialNumber %s", dev->serial));
 	ALERT(("New USB device (%ld) %s", dev->devnum, dev->prod));
 
 	/* now probe if the device is a hub */
 	if (usb_hub_probe(dev, 0) == 0) {
 		/* assign driver if possible */
-		usb_find_interface_driver(dev, 0);
+		while (idx < dev->config.no_of_if) {
+			usb_find_interface_driver(dev, idx++);
+		}
 	}
 
 	return 0;
 }
 
 
 /********************************************************************
  * USB device driver handling:
@@ -1090,25 +1096,25 @@
 	if ((!dev) || (ifnum >= dev->config.desc.bNumInterfaces)) {
 		DEBUG(("bad find_interface_driver params"));
 		return -1;
 	}
 	
 	/*
 	 * Already attached ?
 	 */
-	if (dev->driver)
+	if (dev->config.if_desc[ifnum].driver)
 		return -1;
 
 	while (driver)
 	{
-		if (!driver->probe(dev))
+		if (!driver->probe(dev, ifnum))
 		{
-			dev->driver = driver;
-			
+			dev->config.if_desc[ifnum].driver = driver;
+			DEBUG(("driver attached to iface %d", ifnum));
 			return 0;
 		}
 
 		driver = driver->next;
 	}
 
 	return -1;
 }
Index: sys/usb/src.km/usb.h
===================================================================
RCS file: /mint/freemint/sys/usb/src.km/usb.h,v
retrieving revision 1.17
diff -u -8 -r1.17 usb.h
--- sys/usb/src.km/usb.h	5 Oct 2014 19:45:58 -0000	1.17
+++ sys/usb/src.km/usb.h	23 Feb 2015 09:19:20 -0000
@@ -129,17 +129,17 @@
 	unsigned char  bmAttributes;
 	unsigned short wBytesPerInterval;
 } __attribute__ ((packed));
 
 #define USB_DT_SS_EP_COMP_SIZE 		6
 
 struct usb_interface {
 	struct usb_interface_descriptor desc;
-
+	struct uddif *driver;
 	unsigned char	no_of_ep;
 	unsigned char	num_altsetting;
 	unsigned char	act_altsetting;
 
 	struct usb_endpoint_descriptor ep_desc[USB_MAXENDPOINTS];
 	/*
 	 * Super Speed Device will have Super Speed Endpoint
 	 * Companion Descriptor  (section 9.6.7 of usb 3.0 spec)
@@ -213,17 +213,16 @@
 	 */
 	unsigned long status;
 	long act_len;			/* transfered bytes */
 	long maxchild;			/* Number of ports if hub */
 	long portnr;
 	struct usb_device *parent;
 	struct usb_device *children[USB_MAXCHILDREN];
 
-	struct uddif *driver;
 	struct ucdif *controller;
 
 };
 
 /* Defines */
 #define USB_UHCI_VEND_ID		0x8086
 #define USB_UHCI_DEV_ID		0x7112
 
Index: sys/usb/src.km/usb_api.h
===================================================================
RCS file: /mint/freemint/sys/usb/src.km/usb_api.h,v
retrieving revision 1.6
diff -u -8 -r1.6 usb_api.h
--- sys/usb/src.km/usb_api.h	25 Nov 2014 10:04:14 -0000	1.6
+++ sys/usb/src.km/usb_api.h	23 Feb 2015 09:19:21 -0000
@@ -21,17 +21,17 @@
 #define _usb_api_h
 
 #include "usb.h"
 #include "hub.h"
 
 /*
  * USB API VERSION. ALL MODULES COMPILED WITH THIS, SO MUST MATCH !
  */
-#define USB_API_VERSION 0
+#define USB_API_VERSION 1
 
 /*
  * UCD - USB Controller Driver.
  */
 #define UCD_OPEN	1
 #define UCD_NAMSIZ	16	/* maximum ucd name len */
 
 #define USB_CONTRLL	0
@@ -111,17 +111,17 @@
 
 	long		class;
 	char		*lname;
 	char		name[UDD_NAMSIZ];
 	short		unit;
 
 	unsigned short	flags;
 
-	long		(*probe)	(struct usb_device *);
+	long		(*probe)	(struct usb_device *, unsigned int ifnum);
 	long		(*disconnect)	(struct usb_device *);
 	long		resrvd1;	/* (*output)  */
 	long		(*ioctl)	(struct uddif *, short cmd, long arg);
 	long		resrvd2;	/* (*timeout) */
 };
 
 struct usb_module_api
 {
Index: sys/usb/src.km/udd/eth/usb_ether.c
===================================================================
RCS file: /mint/freemint/sys/usb/src.km/udd/eth/usb_ether.c,v
retrieving revision 1.6
diff -u -8 -r1.6 usb_ether.c
--- sys/usb/src.km/udd/eth/usb_ether.c	25 Nov 2014 10:04:14 -0000	1.6
+++ sys/usb/src.km/udd/eth/usb_ether.c	23 Feb 2015 09:19:21 -0000
@@ -79,17 +79,17 @@
 
 char *drv_version = MSG_VERSION;
 
 
 /*
  * USB device interface
  */
 
-static long ethernet_probe		(struct usb_device *dev);
+static long ethernet_probe		(struct usb_device *dev, unsigned int ifnum);
 static long ethernet_disconnect		(struct usb_device *dev);
 static long ethernet_ioctl		(struct uddif *, short, long);
 
 static char lname[] = "USB ethernet class driver\0";
 
 static struct uddif eth_uif = 
 {
 	0,			/* *next */
@@ -120,17 +120,17 @@
 #include "usb_ether.h"
 
 static struct ueth_data *usb_eth;
 
 /*
  * Given a USB device, ask each driver if it can support it, and attach it
  * to the first driver that says 'yes'
  */
-static long probe_valid_drivers(struct usb_device *dev)
+static long probe_valid_drivers(struct usb_device *dev, unsigned int ifnum)
 {
 	long j, devid;
 	long numDevices = usbNetAPI->numDevices;
 
 	for (j = 0; j < numDevices; j++) {
 		if (usb_eth[j].pusb_dev == NULL)
 			break;
 	}
@@ -140,17 +140,17 @@
 	for (j = 0; j < numDevices; j++) {
 		if (!usbNetAPI->usbnet[j].before_probe ||
 			!usbNetAPI->usbnet[j].probe ||
 			!usbNetAPI->usbnet[j].get_info)
 			continue;
 
 		usbNetAPI->usbnet[j].before_probe(api);
 
-		if (!usbNetAPI->usbnet[j].probe(dev, 0, &usb_eth[devid]))
+		if (!usbNetAPI->usbnet[j].probe(dev, ifnum, &usb_eth[devid]))
 			continue;
 		/*
 		 * ok, it is a supported eth device. Get info and fill it in
 		 */
 		if (usbNetAPI->usbnet[j].get_info(dev, &usb_eth[devid], &usb_eth[devid].eth_dev)) {
 			return 0;
 		}
 	}
@@ -160,28 +160,28 @@
 
 static long _cdecl
 ethernet_ioctl (struct uddif *u, short cmd, long arg)
 {
 	return E_OK;
 }
 
 static long
-ethernet_probe(struct usb_device *dev)
+ethernet_probe(struct usb_device *dev, unsigned int ifnum)
 {
 	int old_async;
 	long r;
 
 	if (dev == NULL)
 		return -1;
 
 	old_async = usb_disable_asynch(1); /* asynch transfer not allowed */
 
 	/* find valid usb_ether driver for this device, if any */
-	r = probe_valid_drivers(dev);
+	r = probe_valid_drivers(dev, ifnum);
 
 	usb_disable_asynch(old_async); /* restore asynch value */
 
 	DEBUG(("Ethernet Device(s) found"));
 
 	return r;
 }
 
Index: sys/usb/src.km/udd/mouse/usb_mouse.c
===================================================================
RCS file: /mint/freemint/sys/usb/src.km/udd/mouse/usb_mouse.c,v
retrieving revision 1.4
diff -u -8 -r1.4 usb_mouse.c
--- sys/usb/src.km/udd/mouse/usb_mouse.c	25 Nov 2014 10:04:15 -0000	1.4
+++ sys/usb/src.km/udd/mouse/usb_mouse.c	23 Feb 2015 09:19:21 -0000
@@ -75,17 +75,17 @@
 /****************************************************************************/
 
 /*
  * USB device interface
  */
 
 static long mouse_ioctl (struct uddif *, short, long);
 static long mouse_disconnect (struct usb_device *dev);
-static long mouse_probe (struct usb_device *dev);
+static long mouse_probe (struct usb_device *dev, unsigned int ifnum);
 
 static char lname[] = "USB mouse class driver\0";
 
 static struct uddif mouse_uif = {
 	0,                          /* *next */
 	USB_API_VERSION,            /* API */
 	USB_DEVICE,                 /* class */
 	lname,                      /* lname */
@@ -285,17 +285,17 @@
 }
 #endif
 
 /*******************************************************************************
  * 
  * 
  */
 static long
-mouse_probe (struct usb_device *dev)
+mouse_probe (struct usb_device *dev, unsigned int ifnum)
 {
 	struct usb_interface *iface;
 	struct usb_endpoint_descriptor *ep_desc;
 
 
 	/*
 	 * Only one mouse at time 
 	 */
@@ -309,17 +309,17 @@
 		return -1;
 	}
 
 	usb_disable_asynch (1);     /* asynch transfer not allowed */
 
 	/*
 	 * let's examine the device now 
 	 */
-	iface = &dev->config.if_desc[0];
+	iface = &dev->config.if_desc[ifnum];
 	if (!iface)
 	{
 		return -1;
 	}
 
 	if (iface->desc.bInterfaceClass != USB_CLASS_HID)
 	{
 		return -1;
Index: sys/usb/src.km/udd/storage/usb_storage.c
===================================================================
RCS file: /mint/freemint/sys/usb/src.km/udd/storage/usb_storage.c,v
retrieving revision 1.19
diff -u -8 -r1.19 usb_storage.c
--- sys/usb/src.km/udd/storage/usb_storage.c	12 Feb 2015 20:24:42 -0000	1.19
+++ sys/usb/src.km/udd/storage/usb_storage.c	23 Feb 2015 09:19:22 -0000
@@ -108,17 +108,17 @@
 /* END kernel interface */
 /****************************************************************************/
 
 /*
  * USB device interface
  */
 
 static long	storage_ioctl		(struct uddif *, short, long);
-static long	storage_probe		(struct usb_device *);
+static long	storage_probe		(struct usb_device *, unsigned int ifnum);
 static long	storage_disconnect	(struct usb_device *);
 
 static char lname[] = "USB mass storage class driver\0";
 
 static struct uddif storage_uif = 
 {
 	0,			/* *next */
 	USB_API_VERSION,	/* API */
@@ -269,17 +269,17 @@
 	unsigned long type;
 	unsigned long	start; /* # of first block in partition	*/
 	unsigned long	size;  /* number of blocks in partition	*/
 	unsigned long	blksz; /* block size in bytes			*/
 } disk_partition_t;
 
 /* Functions prototypes */
 long 		usb_stor_get_info	(struct usb_device *, struct us_data *, block_dev_desc_t *);
-long 		usb_stor_probe		(struct usb_device *, unsigned long, struct us_data *);
+long 		usb_stor_probe		(struct usb_device *, unsigned int, struct us_data *);
 unsigned long 	usb_stor_read		(long, unsigned long, unsigned long, void *);
 unsigned long 	usb_stor_write		(long, unsigned long, unsigned long, void *);
 void		usb_stor_eject		(long);
 block_dev_desc_t *	usb_stor_get_dev	(long);
 static long 		usb_stor_BBB_comdat	(ccb *, struct us_data *);
 static long 		usb_stor_CB_comdat	(ccb *, struct us_data *);
 static long 		usb_stor_CBI_get_status	(ccb *, struct us_data *);
 static long 		usb_stor_BBB_clear_endpt_stall	(struct us_data *, unsigned char);
@@ -1587,17 +1587,17 @@
 	DEBUG(("usb_write: end startblk %lx, blccnt %x buffer %lx", start, smallblks, (long)buf_addr));
 	usb_disable_asynch(0); /* asynch transfer allowed */
 
 	return blkcnt;
 }
 
 /* Probe to see if a new device is actually a Storage device */
 long
-usb_stor_probe(struct usb_device *dev, unsigned long ifnum, struct us_data *ss)
+usb_stor_probe(struct usb_device *dev, unsigned int ifnum, struct us_data *ss)
 {
 	struct usb_interface *iface;
 	struct usb_endpoint_descriptor *ep_desc;
 	long i;
 	unsigned long flags = 0;
 	long protocol = 0;
 	long subclass = 0;
 
@@ -1906,17 +1906,17 @@
 }
 
 
 /*******************************************************************************
  * 
  * 
  */
 static long
-storage_probe(struct usb_device *dev)
+storage_probe(struct usb_device *dev, unsigned int ifnum)
 {
 	long r, i, lun, start;	
 	long max_lun;
 	
 	if(dev == NULL)
 		return -1;
 	
 	for (i = 0; i < USB_MAX_STOR_DEV; i++)
@@ -1931,17 +1931,17 @@
 	if(i == USB_MAX_STOR_DEV)
 	{
 			ALERT(("Max USB Storage Device reached: %ld stopping", USB_MAX_STOR_DEV));
 			return -1;
 	}
 
 	usb_disable_asynch(1); /* asynch transfer not allowed */
 
-	if(!usb_stor_probe(dev, 0, &usb_stor[i])) {
+	if(!usb_stor_probe(dev, ifnum, &usb_stor[i])) {
 		usb_disable_asynch(0); /* asynch transfer allowed */
 		return -1; /* It's not a storage device */
 	}
 
 	start = i;
 	max_lun = usb_get_max_lun(&usb_stor[i]);
 	/* override */
 	max_lun = 0; /* not yet */