tech-kern archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: GSoC - USB Video Class (UVC) webcam driver
pat%polycrystal.org@localhost said:
> the IAD stuff is not yet in -current?
So I've stripped down the IAD code to something which
is harmless enough imho to go into the tree before
the 5.0 branch. It is just the additional device
attachment; there are no changes to kernel config
files necessary unless one actually wants to use
a device which uses a driver which makes use of it -
uvc would be the first candidate.
The intention is to make 5.0 a stable platform where
further uvc work can be done on, without requiring
framework changes.
I'm aware of the fact that there is no time left in soc,
but could you have a look at it and tell whether
it would work with your code?
Unless a driver attaches to "usbfif", it should issue
a message "IAD device at blabla not configured" if
a webcam is connected.
best regards
Matthias
-------------------------------------------------------------------
-------------------------------------------------------------------
Forschungszentrum Juelich GmbH
52425 Juelich
Sitz der Gesellschaft: Juelich
Eingetragen im Handelsregister des Amtsgerichts Dueren Nr. HR B 3498
Vorsitzende des Aufsichtsrats: MinDir'in Baerbel Brumme-Bothe
Geschaeftsfuehrung: Prof. Dr. Achim Bachem (Vorsitzender),
Dr. Ulrich Krafft (stellv. Vorsitzender), Prof. Dr. Harald Bolt,
Dr. Sebastian M. Schmidt
-------------------------------------------------------------------
-------------------------------------------------------------------
/* NetBSD */
struct usbfunction_attach_args {
usbd_device_handle device;
int port;
int vendor, product, release;
int configno;
int type;
#define USBF_IAD 1
#define USBF_LEGACYAUDIO 2
#define USBF_INTERFACE 3
int class, subclass, proto;
int ifaceno;
int nifaces;
usbd_interface_handle *ifaces;
};
/* $NetBSD$ */
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/device.h>
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
#include <dev/usb/usbdi_util.h>
#include <sys/bus.h>
#include <dev/usb/usbdivar.h>
#include <dev/usb/usbfunction.h>
#include "locators.h"
static int usb_fifprint(void *, const char *);
typedef struct {
uByte bLength;
uByte bDescriptorType;
uByte bFirstInterface;
uByte bInterfaceCount;
uByte bFunctionClass;
uByte bFunctionSubClass;
uByte bFunctionProtocol;
uByte iFunction;
} __packed usb_interface_association_descriptor_t;
#define UDESC_INTERFACE_ASSOCIATION 11
/*
* attach by IADs
*/
static usbd_status
usbfcn_scaniads(device_t parent, usbd_device_handle dev,
struct usbfunction_attach_args *ufaa, int *locs)
{
usbd_desc_iter_t di;
const usb_descriptor_t *d;
const usb_interface_association_descriptor_t *iad;
int ifbusy, i;
usbd_interface_handle *ifs;
device_t dv;
usb_desc_iter_init(dev, &di);
while ((d = usb_desc_iter_next(&di))) {
if (d->bDescriptorType != UDESC_INTERFACE_ASSOCIATION)
continue;
iad = (const usb_interface_association_descriptor_t *)d;
if (iad->bFirstInterface + iad->bInterfaceCount
> dev->cdesc->bNumInterface) {
printf("%s: invalid iad\n", device_xname(parent));
return USBD_INVAL;
}
ifbusy = 0;
for (i = 0; i < iad->bInterfaceCount; i++) {
if (dev->subdevs[iad->bFirstInterface + i]) {
ifbusy++;
break;
}
}
if (ifbusy)
continue;
ifs = malloc(iad->bInterfaceCount
* sizeof(usbd_interface_handle *),
M_USBDEV, M_NOWAIT);
if (!ifs)
return USBD_NOMEM;
for (i = 0; i < iad->bInterfaceCount; i++)
ifs[i] = &dev->ifaces[iad->bFirstInterface + i];
ufaa->type = USBF_IAD;
ufaa->class = iad->bFunctionClass;
ufaa->subclass = iad->bFunctionSubClass;
ufaa->proto = iad->bFunctionProtocol;
ufaa->ifaces = ifs;
ufaa->nifaces = iad->bInterfaceCount;
ufaa->ifaceno = iad->bFirstInterface;
locs[USBFIFCF_INTERFACE] = ufaa->ifaceno;
dv = config_found_sm_loc(parent, "usbfif", locs, ufaa,
usb_fifprint, config_stdsubmatch);
if (dv) {
for (i = 0; i < iad->bInterfaceCount; i++)
dev->subdevs[iad->bFirstInterface + i] = dv;
dev->nifaces_claimed += iad->bInterfaceCount;
}
free(ifs, M_USBDEV);
}
return USBD_NORMAL_COMPLETION;
}
#if 0 /* not yet */
/*
* handle audio devices without IADs: look for multiple audio interfaces
* (need at least one control and one streaming interface)
*/
static usbd_status
usbfcn_scanaudio(device_t parent, usbd_device_handle dev,
struct usbfunction_attach_args *ufaa, int *locs)
{
int nifaces, naudioif, i, j;
usbd_interface_handle *ifs;
int *ifacenrs;
device_t dv;
nifaces = dev->cdesc->bNumInterface;
naudioif = 0;
for (i = 0; i < nifaces; i++) {
if (dev->subdevs[i])
continue; /* interface already claimed */
if (dev->ifaces[i].idesc->bInterfaceClass == UICLASS_AUDIO)
naudioif++;
}
if (naudioif < 2)
return USBD_NORMAL_COMPLETION;
ifs = malloc(naudioif * sizeof(usbd_interface_handle *),
M_USBDEV, M_NOWAIT);
if (!ifs)
return USBD_NOMEM;
ifacenrs = malloc(naudioif * sizeof(int), M_USBDEV, M_NOWAIT);
if (!ifacenrs) {
free(ifs, M_USBDEV);
return USBD_NOMEM;
}
j = 0;
for (i = 0; i < nifaces; i++) {
if (dev->subdevs[i])
continue; /* interface already claimed */
if (dev->ifaces[i].idesc->bInterfaceClass == UICLASS_AUDIO) {
ifs[j] = &dev->ifaces[i];
ifacenrs[j] = i;
j++;
if (j == naudioif)
break;
}
}
if (j != naudioif) {
printf("udev_scanaudio: lost interface\n");
free(ifs, M_USBDEV);
return USBD_INVAL;
}
ufaa->type = USBF_LEGACYAUDIO;
ufaa->class = UICLASS_AUDIO;
ufaa->subclass = 0;
ufaa->proto = 0;
ufaa->ifaces = ifs;
ufaa->nifaces = naudioif;
ufaa->ifaceno = ifacenrs[0];
locs[USBFIFCF_INTERFACE] = ufaa->ifaceno;
dv = config_found_sm_loc(parent, "usbfif", locs, ufaa,
usb_fifprint, config_stdsubmatch);
if (dv) {
for (i = 0; i < naudioif; i++)
dev->subdevs[ifacenrs[i]] = dv;
dev->nifaces_claimed += naudioif;
}
free(ifs, M_USBDEV);
free(ifacenrs, M_USBDEV);
return USBD_NORMAL_COMPLETION;
}
static usbd_status
usbfcn_scaninterfaces(device_t parent, usbd_device_handle dev,
struct usbfunction_attach_args *ufaa, int *locs)
{
int i;
usbd_interface_handle ifs;
device_t dv;
for (i = 0; i < dev->cdesc->bNumInterface; i++) {
if (dev->subdevs[i])
continue; /* interface already claimed */
ifs = &dev->ifaces[i];
ufaa->type = USBF_INTERFACE;
ufaa->class = dev->ifaces[i].idesc->bInterfaceClass;
ufaa->subclass = dev->ifaces[i].idesc->bInterfaceSubClass;
ufaa->proto = dev->ifaces[i].idesc->bInterfaceProtocol;
ufaa->ifaces = &ifs;
ufaa->nifaces = 1;
/* ifaceno should be i, else we have a strange device */
ufaa->ifaceno = dev->ifaces[i].idesc->bInterfaceNumber;
locs[USBFIFCF_INTERFACE] = ufaa->ifaceno;
dv = config_found_sm_loc(parent, "usbfif", locs, ufaa,
usb_fifprint, config_stdsubmatch);
if (dv) {
dev->subdevs[i] = dv;
dev->nifaces_claimed++;
}
}
return USBD_NORMAL_COMPLETION;
}
#endif /* not yet */
static int
usb_fifprint(void *aux, const char *pnp)
{
struct usbfunction_attach_args *uaa = aux;
if (pnp) {
if (uaa->type == USBF_IAD)
aprint_normal("IAD device (class=%d) at %s",
uaa->class, pnp);
#if 0 /* not yet */
else if (uaa->type == USBF_LEGACYAUDIO)
aprint_normal("legacy audio device at %s", pnp);
#endif
else
return (QUIET);
}
aprint_normal(" interface %d", uaa->ifaceno);
return (UNCONF);
}
usbd_status
usb_attachfunctions(device_t parent, usbd_device_handle dev, int port)
{
usbd_status res;
usb_device_descriptor_t *dd;
struct usbfunction_attach_args ufaa;
int locs[USBFIFCF_NLOCS];
dd = &dev->ddesc;
ufaa.device = dev;
ufaa.port = port;
ufaa.vendor = UGETW(dd->idVendor);
ufaa.product = UGETW(dd->idProduct);
ufaa.release = UGETW(dd->bcdDevice);
ufaa.configno = dev->cdesc->bConfigurationValue;
locs[USBFIFCF_PORT] = ufaa.port;
locs[USBFIFCF_VENDOR] = ufaa.vendor;
locs[USBFIFCF_PRODUCT] = ufaa.product;
locs[USBFIFCF_RELEASE] = ufaa.release;
locs[USBFIFCF_CONFIGURATION] = ufaa.configno;
if ((dd->bDeviceClass == UDCLASS_MISC) &&
(dd->bDeviceSubClass == UDSUBCLASS_COMMON) &&
(dd->bDeviceProtocol == UDPROTO_IAD) &&
(dev->cdesc->iConfiguration == 0)) {
res = usbfcn_scaniads(parent, dev, &ufaa, locs);
if (res)
return res;
}
#if 0 /* not yet */
res = usbfcn_scanaudio(parent, dev, &ufaa, locs);
if (res)
return res;
res = usbfcn_scaninterfaces(parent, dev, &ufaa, locs);
if (res)
return res;
#endif
return USBD_NORMAL_COMPLETION;
}
#
# old_revision [05483fc8817ab109a28dae727d55611ef093c9cf]
#
# patch "sys/dev/usb/files.usb"
# from [f8965efae43fae946f88304cc9ab9bf6331cb4ae]
# to [e9b86c319bb1e13ab65518db14c12285c4b001bc]
#
# patch "sys/dev/usb/usb.h"
# from [4a00b4b553426a4992979e04792911044710560b]
# to [944759b51fefe5d2fcacbd462a3dd999a0edbefc]
#
# patch "sys/dev/usb/usb_subr.c"
# from [63bcf87e6307cfe6a160d758cbad25c5beca0e5a]
# to [1c50f60faf4aab5a6e0691593dac531e3ec57d6b]
#
# patch "sys/dev/usb/usbdivar.h"
# from [60305dd33cce54cd0c77c04055bb1c430aa6c144]
# to [47ddf7be41c53c0b7df50a75de711a7831058646]
#
============================================================
--- sys/dev/usb/files.usb f8965efae43fae946f88304cc9ab9bf6331cb4ae
+++ sys/dev/usb/files.usb e9b86c319bb1e13ab65518db14c12285c4b001bc
@@ -11,6 +11,8 @@ define usbifif { [port = -1], [configura
[vendor = -1], [product = -1], [release = -1] }
define usbifif { [port = -1], [configuration = -1], [interface = -1],
[vendor = -1], [product = -1], [release = -1] }
+define usbfif { [port = -1], [configuration = -1], [interface = -1],
+ [vendor = -1], [product = -1], [release = -1] }
device usb: usbroothubif
attach usb at usbus
@@ -20,9 +22,10 @@ file dev/usb/usb_quirks.c usb
file dev/usb/usb_mem.c usb
file dev/usb/usb_subr.c usb
file dev/usb/usb_quirks.c usb
+file dev/usb/usb_functions.c usb
# Hub driver
-device uhub: usbdevif, usbifif
+device uhub: usbdevif, usbifif, usbfif
attach uhub at usbroothubif with uroothub
attach uhub at usbdevif
file dev/usb/uhub.c usb
============================================================
--- sys/dev/usb/usb.h 4a00b4b553426a4992979e04792911044710560b
+++ sys/dev/usb/usb.h 944759b51fefe5d2fcacbd462a3dd999a0edbefc
@@ -388,6 +388,9 @@ typedef struct {
#define UDCLASS_WIRELESS 0xe0
#define UDSUBCLASS_RF 0x01
#define UDPROTO_BLUETOOTH 0x01
+#define UDCLASS_MISC 0xef
+#define UDSUBCLASS_COMMON 0x02
+#define UDPROTO_IAD 0x01
#define UDCLASS_VENDOR 0xff
/* Interface class codes */
============================================================
--- sys/dev/usb/usb_subr.c 63bcf87e6307cfe6a160d758cbad25c5beca0e5a
+++ sys/dev/usb/usb_subr.c 1c50f60faf4aab5a6e0691593dac531e3ec57d6b
@@ -932,6 +932,8 @@ usbd_probe_and_attach(device_ptr_t paren
return (USBD_NOMEM);
dev->subdevlen = nifaces;
+ usb_attachfunctions(parent, dev, port);
+
err = usbd_attachinterfaces(parent, dev, port);
if (!dev->nifaces_claimed) {
============================================================
--- sys/dev/usb/usbdivar.h 60305dd33cce54cd0c77c04055bb1c430aa6c144
+++ sys/dev/usb/usbdivar.h 47ddf7be41c53c0b7df50a75de711a7831058646
@@ -246,6 +246,8 @@ void usb_disconnect_port(struct usbd_po
void usb_transfer_complete(usbd_xfer_handle);
void usb_disconnect_port(struct usbd_port *, device_ptr_t);
+usbd_status usb_attachfunctions(device_t, usbd_device_handle, int);
+
/* Routines from usb.c */
void usb_needs_explore(usbd_device_handle);
void usb_needs_reattach(usbd_device_handle);
Home |
Main Index |
Thread Index |
Old Index