[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 */