summaryrefslogtreecommitdiff
path: root/multimedia/pwcbsd
diff options
context:
space:
mode:
authorLars Engels <lme@FreeBSD.org>2009-05-27 18:31:56 +0000
committerLars Engels <lme@FreeBSD.org>2009-05-27 18:31:56 +0000
commit7349eb0b67f03ff7feb06786ff95e25efaf578e8 (patch)
tree1ce0a7e6e1656a5ccea62e49deb9c96092008690 /multimedia/pwcbsd
parentfix compilation if the old sane version is still installed (diff)
- Add patches to fix build with USB2
- Bump PORTREVISION Patches Submitted by: hps
Notes
Notes: svn path=/head/; revision=234670
Diffstat (limited to 'multimedia/pwcbsd')
-rw-r--r--multimedia/pwcbsd/Makefile6
-rw-r--r--multimedia/pwcbsd/files/patch-Makefile.kld11
-rw-r--r--multimedia/pwcbsd/files/patch-pwc-ctrl.c50
-rw-r--r--multimedia/pwcbsd/files/patch-pwc-v4l.c11
-rw-r--r--multimedia/pwcbsd/files/patch-pwc.c633
-rw-r--r--multimedia/pwcbsd/files/patch-pwc.h95
6 files changed, 801 insertions, 5 deletions
diff --git a/multimedia/pwcbsd/Makefile b/multimedia/pwcbsd/Makefile
index 02dc1d9e376a..1e45945d991c 100644
--- a/multimedia/pwcbsd/Makefile
+++ b/multimedia/pwcbsd/Makefile
@@ -7,7 +7,7 @@
PORTNAME= pwcbsd
PORTVERSION= 1.4.1
-PORTREVISION= 1
+PORTREVISION= 2
CATEGORIES= multimedia sysutils kld
MASTER_SITES= http://raaf.atspace.org/ \
http://www.bsd-geek.de/FreeBSD/distfiles/ \
@@ -27,10 +27,6 @@ OPTIONS= PROGRAMS "Build the programs" on \
.include <bsd.port.pre.mk>
-.if ${OSVERSION} > 800063
-BROKEN= Does not build with USB2
-.endif
-
.if !exists(/usr/src/sys/Makefile)
IGNORE= requires kernel source files
.endif
diff --git a/multimedia/pwcbsd/files/patch-Makefile.kld b/multimedia/pwcbsd/files/patch-Makefile.kld
new file mode 100644
index 000000000000..b614f0bb891f
--- /dev/null
+++ b/multimedia/pwcbsd/files/patch-Makefile.kld
@@ -0,0 +1,11 @@
+--- Makefile.kld.orig 2006-02-17 00:18:15.000000000 +0100
++++ Makefile.kld 2009-05-27 20:22:49.137318240 +0200
+@@ -1,6 +1,7 @@
+ SRCS=bus_if.h device_if.h opt_usb.h pwc.c pwc-ctrl.c \
+ pwc-dec1.c pwc-dec23.c pwc-kiara.c pwc-misc.c \
+- pwc-timon.c pwc-uncompress.c pwc-v4l.c
++ pwc-timon.c pwc-uncompress.c pwc-v4l.c opt_bus.h \
++ usb_if.h
+ KMOD=pwc
+ KMODDIR?=/boot/modules
+ #DEBUG_FLAGS=-g
diff --git a/multimedia/pwcbsd/files/patch-pwc-ctrl.c b/multimedia/pwcbsd/files/patch-pwc-ctrl.c
new file mode 100644
index 000000000000..73bd0e74c71e
--- /dev/null
+++ b/multimedia/pwcbsd/files/patch-pwc-ctrl.c
@@ -0,0 +1,50 @@
+--- pwc-ctrl.c.orig 2007-07-02 08:54:19.000000000 +0200
++++ pwc-ctrl.c 2009-05-27 20:22:49.137318240 +0200
+@@ -130,7 +130,7 @@
+ static void pwc_set_image_buffer_size(struct pwc_softc *pdev);
+
+ /****************************************************************************/
+-static int usb_control_msg(usbd_device_handle udev,u_int pipe,u_int8_t request,u_int8_t requesttype,
++static int usb_control_msg(struct usb2_device *udev,u_int pipe,u_int8_t request,u_int8_t requesttype,
+ u_int16_t value, u_int16_t index, void *data, u_int16_t size,int timeout)
+ {
+ usb_device_request_t req;
+@@ -139,9 +139,9 @@
+ USETW(req.wValue, value);
+ USETW(req.wIndex, index);
+ USETW(req.wLength,size);
+- return -usbd_do_request(udev, &req, data);
++ return -usb2_do_request(udev, NULL, &req, data);
+ }
+-
++
+
+ #define SendControlMsg(request, value, buflen) \
+ usb_control_msg(pdev->udev, 0, \
+@@ -159,7 +159,7 @@
+ pdev->vcinterface, \
+ &buf, buflen, 500)
+
+-static int send_video_command(usbd_device_handle udev, int index, void *buf, int buflen)
++static int send_video_command(struct usb2_device *udev, int index, void *buf, int buflen)
+ {
+ return usb_control_msg(udev,
+ 0,
+@@ -1150,7 +1150,7 @@
+ pdev->pan_angle += pan;
+ pdev->tilt_angle += tilt;
+ }
+- if (ret == -USBD_STALLED) /* stall -> out of range */
++ if (ret == -USB_ERR_STALLED) /* stall -> out of range */
+ ret = -ERANGE;
+ return ret;
+ }
+@@ -1284,7 +1284,7 @@
+ {
+ ARG_DEF(struct pwc_probe, probe)
+
+- strncpy(ARGR(probe).name, pdev->name,sizeof(ARGR(probe).name) - 1);
++ strncpy(ARGR(probe).name,device_get_desc(pdev->sc_dev),sizeof(ARGR(probe).name) - 1);
+ ARGR(probe).name[sizeof(ARGR(probe).name) - 1] = '\0';
+ ARGR(probe).type = pdev->type;
+ ARG_OUT(probe)
diff --git a/multimedia/pwcbsd/files/patch-pwc-v4l.c b/multimedia/pwcbsd/files/patch-pwc-v4l.c
new file mode 100644
index 000000000000..35ae7c2dfa31
--- /dev/null
+++ b/multimedia/pwcbsd/files/patch-pwc-v4l.c
@@ -0,0 +1,11 @@
+--- pwc-v4l.c.orig 2006-06-07 22:15:52.000000000 +0200
++++ pwc-v4l.c 2009-05-27 20:22:49.137318240 +0200
+@@ -67,7 +67,7 @@
+ {
+ struct video_capability *caps = arg;
+
+- strncpy(caps->name, pdev->name, sizeof(caps->name) - 1);
++ strncpy(caps->name, device_get_desc(pdev->sc_dev), sizeof(caps->name) - 1);
+ caps->name[sizeof(caps->name) - 1] = '\0';
+ caps->type = VID_TYPE_CAPTURE;
+ caps->channels = 1;
diff --git a/multimedia/pwcbsd/files/patch-pwc.c b/multimedia/pwcbsd/files/patch-pwc.c
new file mode 100644
index 000000000000..a0dea9ab5594
--- /dev/null
+++ b/multimedia/pwcbsd/files/patch-pwc.c
@@ -0,0 +1,633 @@
+--- pwc.c.orig 2007-10-09 09:14:01.000000000 +0200
++++ pwc.c 2009-05-27 20:22:49.147289211 +0200
+@@ -28,7 +28,8 @@
+ #include "pwc-dec1.h"
+ #include "pwc-dec23.h"
+
+-static void pwc_isoc_handler(usbd_xfer_handle xfer, usbd_private_handle addr,usbd_status status);
++static void pwc_isoc_rx_callback(struct usb2_xfer *xfer);
++static void pwc_isoc_handler(struct usb2_xfer *xfer, void *addr);
+ static void pwc_reset_buffers(struct pwc_softc *sc);
+ static void pwc_free_buffers(struct pwc_softc *sc, int detach);
+
+@@ -57,55 +58,70 @@
+ .d_mmap = pwc_mmap,
+ .d_name = "pwc",
+ };
+-
+-struct pwc_info {
+- struct usb_devno devno;
+- int type;
+- char *name;
++
++static const struct usb2_config pwc_config[MAX_ISO_BUFS] = {
++ [0] = {
++ .type = UE_ISOCHRONOUS,
++ .endpoint = UE_ADDR_ANY,
++ .direction = UE_DIR_IN,
++ .bufsize = 0, /* use "wMaxPacketSize * frames" */
++ .frames = ISO_FRAMES_PER_DESC,
++ .flags = {.short_xfer_ok = 1,},
++ .callback = &pwc_isoc_rx_callback,
++ },
++
++ [1] = {
++ .type = UE_ISOCHRONOUS,
++ .endpoint = UE_ADDR_ANY,
++ .direction = UE_DIR_IN,
++ .bufsize = 0, /* use "wMaxPacketSize * frames" */
++ .frames = ISO_FRAMES_PER_DESC,
++ .flags = {.short_xfer_ok = 1,},
++ .callback = &pwc_isoc_rx_callback,
++ },
+ };
+-static const struct pwc_info pwc_devs[] = {
+- {{ 0x0471, 0x0302 }, 645, "Philips PCA645VC" },
+- {{ 0x0471, 0x0303 }, 646, "Philips PCA646VC" },
+- {{ 0x0471, 0x0304 }, 646, "Askey VC010 type 2" },
+- {{ 0x0471, 0x0307 }, 675, "Philips PCVC675K (Vesta)" },
+- {{ 0x0471, 0x0308 }, 680, "Philips PCVC680K (Vesta Pro)" },
+- {{ 0x0471, 0x030C }, 690, "Philips PCVC690K (Vesta Pro Scan)" },
+- {{ 0x0471, 0x0310 }, 730, "Philips PCVC730K (ToUCam Fun)/PCVC830 (ToUCam II)" },
+- {{ 0x0471, 0x0311 }, 740, "Philips PCVC740K (ToUCam Pro)/PCVC840 (ToUCam II)" },
+- {{ 0x0471, 0x0312 }, 750, "Philips PCVC750K (ToUCam Pro Scan)" },
+- {{ 0x0471, 0x0313 }, 720, "Philips PCVC720K/40 (ToUCam XS)" },
+- {{ 0x0471, 0x0329 }, 740, "Philips SPC900NC" },
+- {{ 0x069A, 0x0001 }, 645, "Askey VC010 type 1" },
+- {{ 0x046D, 0x08B0 }, 740, "Logitech QuickCam Pro 3000" },
+- {{ 0x046D, 0x08B1 }, 740, "Logitech QuickCam Notebook Pro" },
+- {{ 0x046D, 0x08B2 }, 740, "Logitech QuickCam Pro 4000" },
+- {{ 0x046D, 0x08B3 }, 740, "Logitech QuickCam Zoom" },
+- {{ 0x046D, 0x08B4 }, 740, "Logitech QuickCam Zoom (new model)" },
+- {{ 0x046D, 0x08B5 }, 740, "Logitech QuickCam Orbit/Sphere" },
+- {{ 0x046D, 0x08B6 }, 730, "Logitech QuickCam (reserved ID)" },
+- {{ 0x046D, 0x08B7 }, 730, "Logitech QuickCam (reserved ID)" },
+- {{ 0x046D, 0x08B8 }, 730, "Logitech QuickCam (reserved ID)" },
+- {{ 0x055D, 0x9000 }, 675, "Samsung MPC-C10" },
+- {{ 0x055D, 0x9001 }, 675, "Samsung MPC-C30" },
+- {{ 0x055D, 0x9002 }, 740, "Samsung SNC-35E" },
+- {{ 0x041E, 0x400C }, 730, "Creative Labs Webcam 5" },
+- {{ 0x041E, 0x4011 }, 740, "Creative Labs Webcam Pro Ex" },
+- {{ 0x04CC, 0x8116 }, 730, "Sotec Afina Eye" },
+- {{ 0x06BE, 0x8116 }, 750, "AME Co. Afina Eye" },
+- {{ 0x0d81, 0x1910 }, 740, "Visionite VCS-UC300" },
+- {{ 0x0d81, 0x1900 }, 730, "Visionite VCS-UM100" },
++
++static const struct usb2_device_id pwc_devs[] = {
++ {USB_VPI(0x0471, 0x0302, 645)}, /* Philips PCA645VC */
++ {USB_VPI(0x0471, 0x0303, 646)}, /* Philips PCA646VC */
++ {USB_VPI(0x0471, 0x0304, 646)}, /* Askey VC010 type 2 */
++ {USB_VPI(0x0471, 0x0307, 675)}, /* Philips PCVC675K (Vesta) */
++ {USB_VPI(0x0471, 0x0308, 680)}, /* Philips PCVC680K (Vesta Pro) */
++ {USB_VPI(0x0471, 0x030C, 690)}, /* Philips PCVC690K (Vesta Pro Scan) */
++ {USB_VPI(0x0471, 0x0310, 730)}, /* Philips PCVC730K (ToUCam Fun)/PCVC830 (ToUCam II) */
++ {USB_VPI(0x0471, 0x0311, 740)}, /* Philips PCVC740K (ToUCam Pro)/PCVC840 (ToUCam II) */
++ {USB_VPI(0x0471, 0x0312, 750)}, /* Philips PCVC750K (ToUCam Pro Scan) */
++ {USB_VPI(0x0471, 0x0313, 720)}, /* Philips PCVC720K/40 (ToUCam XS) */
++ {USB_VPI(0x0471, 0x0329, 740)}, /* Philips SPC900NC */
++ {USB_VPI(0x069A, 0x0001, 645)}, /* Askey VC010 type 1 */
++ {USB_VPI(0x046D, 0x08B0, 740)}, /* Logitech QuickCam Pro 3000 */
++ {USB_VPI(0x046D, 0x08B1, 740)}, /* Logitech QuickCam Notebook Pro */
++ {USB_VPI(0x046D, 0x08B2, 740)}, /* Logitech QuickCam Pro 4000 */
++ {USB_VPI(0x046D, 0x08B3, 740)}, /* Logitech QuickCam Zoom */
++ {USB_VPI(0x046D, 0x08B4, 740)}, /* Logitech QuickCam Zoom (new model) */
++ {USB_VPI(0x046D, 0x08B5, 740)}, /* Logitech QuickCam Orbit/Sphere */
++ {USB_VPI(0x046D, 0x08B6, 730)}, /* Logitech QuickCam (reserved ID) */
++ {USB_VPI(0x046D, 0x08B7, 730)}, /* Logitech QuickCam (reserved ID) */
++ {USB_VPI(0x046D, 0x08B8, 730)}, /* Logitech QuickCam (reserved ID) */
++ {USB_VPI(0x055D, 0x9000, 675)}, /* Samsung MPC-C10 */
++ {USB_VPI(0x055D, 0x9001, 675)}, /* Samsung MPC-C30 */
++ {USB_VPI(0x055D, 0x9002, 740)}, /* Samsung SNC-35E */
++ {USB_VPI(0x041E, 0x400C, 730)}, /* Creative Labs Webcam 5 */
++ {USB_VPI(0x041E, 0x4011, 740)}, /* Creative Labs Webcam Pro Ex */
++ {USB_VPI(0x04CC, 0x8116, 730)}, /* Sotec Afina Eye */
++ {USB_VPI(0x06BE, 0x8116, 750)}, /* AME Co. Afina Eye */
++ {USB_VPI(0x0d81, 0x1910, 740)}, /* Visionite VCS-UC300 */
++ {USB_VPI(0x0d81, 0x1900, 730)}, /* Visionite VCS-UM100 */
+ };
+-#define pwc_lookup(v, p) ((const struct pwc_info *)usb_lookup(pwc_devs, v, p))
+-#define PWCUNIT(n) (minor(n))
+
+-static device_probe_t pwc_match;
++static device_probe_t pwc_probe;
+ static device_attach_t pwc_attach;
+ static device_detach_t pwc_detach;
+
+ static devclass_t pwc_devclass;
+
+ static device_method_t pwc_methods[] = {
+- DEVMETHOD(device_probe, pwc_match),
++ DEVMETHOD(device_probe, pwc_probe),
+ DEVMETHOD(device_attach, pwc_attach),
+ DEVMETHOD(device_detach, pwc_detach),
+ {0,0},
+@@ -120,85 +136,52 @@
+ MODULE_DEPEND(pwc, usb, 1, 1, 1);
+
+ static int
+-pwc_match(device_t self)
++pwc_probe(device_t self)
+ {
+- struct usb_attach_arg *uaa = device_get_ivars(self);
+- usb_interface_descriptor_t *id;
++ struct usb2_attach_arg *uaa = device_get_ivars(self);
+
+- Trace(TRACE_PROBE,"pwc_match: vendor=0x%x, product=0x%x release=%04x\n",uaa->vendor, uaa->product,uaa->release);
+-
+- if(pwc_lookup(uaa->vendor, uaa->product) == NULL)
+- return UMATCH_NONE;
++ Trace(TRACE_PROBE,"pwc_probe:\n");
++
++ if (uaa->usb_mode != USB_MODE_HOST)
++ return (ENXIO);
+
+- /* Driver loaded when device was already plugged in, we have to claim all interfaces or get none... */
+- if(uaa->usegeneric)
+- return UMATCH_VENDOR_PRODUCT;
+-
+- /* We don't want all interfaces */
+- if(uaa->iface == NULL)
+- return UMATCH_NONE;
+-
+- id = usbd_get_interface_descriptor(uaa->iface);
+- if(id == NULL) {
+- printf("pwc: failed to get interface descriptor\n");
+- return UMATCH_NONE;
+- }
+-
+- Trace(TRACE_PROBE,"pwc_match: iface=%d\n",id->bInterfaceNumber);
+-
+ /* Interface 0 is the video interface
+ * Interface 1 is supposed to be audiocontrol
+ * Interface 2 is supposed to be audio
+ */
+- if(id->bInterfaceNumber != 0)
+- return UMATCH_NONE;
+-
+- return UMATCH_VENDOR_PRODUCT;
+-
++ if (uaa->info.bIfaceIndex != 0)
++ return (ENXIO);
++
++ return (usb2_lookup_id_by_uaa(pwc_devs, sizeof(pwc_devs), uaa));
++
++ return (0); /* success */
+ }
+
+ static int
+ pwc_attach(device_t self)
+ {
+ struct pwc_softc *sc = device_get_softc(self);
+- struct usb_attach_arg *uaa = device_get_ivars(self);
+- char devinfo[1024];
+- const char *tmpstr;
+- const struct pwc_info *info;
++ struct usb2_attach_arg *uaa = device_get_ivars(self);
+ char *sizenames[PSZ_MAX] = { "sqcif", "qsif", "qcif", "sif", "cif", "vga" };
+- int i, err;
++ const char *tmpstr;
++ int i;
+
+- info = pwc_lookup(uaa->vendor, uaa->product);
+- if(info == NULL) {
+- printf("%s: attach error vendor/product mismatch (vendor=0x%x product=0x%x)\n",
+- device_get_nameunit(sc->sc_dev),uaa->vendor,uaa->product);
+- return ENXIO;
+- }
++ device_set_usb2_desc(self);
+
+- usbd_devinfo(uaa->device, 0, devinfo);
+ sc->sc_dev = self;
+- device_set_desc_copy(self, devinfo);
+- device_printf(self, "%s\n", devinfo);
+-
+- err = usbd_device2interface_handle(uaa->device,0,&sc->sc_iface);
+- if(err) {
+- printf("%s: failed to get interface handle\n",device_get_nameunit(sc->sc_dev));
+- return ENXIO;
+- }
+
+ sc->udev = uaa->device;
+- sc->type = info->type;
+- sc->name = info->name;
+- sc->release = uaa->release;
++ sc->type = USB_GET_DRIVER_INFO(uaa);
++ sc->release = uaa->info.bcdDevice;
+ sc->power_save = 0;
+-
++
+ strcpy(sc->serial,"000-000-000-000");
+
+- if(uaa->vendor == 0x046D) {
+- if(uaa->product == 0x08B4) {
++ if(uaa->info.idVendor == 0x046D) {
++ if(uaa->info.idProduct == 0x08B4) {
+ sc->power_save = 1;
+ }
+- else if(uaa->product == 0x08B5) {
++ else if(uaa->info.idProduct == 0x08B5) {
+
+ /* Logitech QuickCam Orbit */
+ sc->features |= FEATURE_MOTOR_PANTILT;
+@@ -215,6 +198,8 @@
+ resource_string_value("pwc",device_get_unit(self),"devname",&tmpstr);
+ sc->sc_dev_t = make_dev(&pwc_cdevsw, device_get_unit(self),UID_ROOT, GID_OPERATOR,
+ 0666, "%s%d",tmpstr,device_get_unit(self));
++ if (sc->sc_dev_t != NULL)
++ sc->sc_dev_t->si_drv1 = sc;
+
+ resource_int_value("pwc",device_get_unit(self),"power_save",&sc->power_save);
+
+@@ -273,7 +258,6 @@
+ resource_int_value("pwc",device_get_unit(self),"pad",&sc->pwc_pad);
+
+ pwc_construct(sc);
+- printf("%s: %s USB webcam\n",device_get_nameunit(sc->sc_dev),sc->name);
+
+ if(pwc_get_cmos_sensor(sc, &i) >= 0) {
+
+@@ -299,7 +283,6 @@
+ if(sc->power_save)
+ pwc_camera_power(sc, 0);
+
+- usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->udev,sc->sc_dev);
+ return 0;
+ }
+
+@@ -309,12 +292,8 @@
+ struct pwc_softc *sc = device_get_softc(self);
+
+ Trace(TRACE_PROBE,"pwc_detach: sc=%p\n",sc);
+-
+- if(sc->sc_videopipe != NULL) {
+- usbd_abort_pipe(sc->sc_videopipe);
+- usbd_close_pipe(sc->sc_videopipe);
+- sc->sc_videopipe = NULL;
+- }
++
++ usb2_transfer_unsetup(sc->sc_xfer, MAX_ISO_BUFS);
+
+ sc->error_status = EPIPE;
+
+@@ -334,20 +313,15 @@
+
+ mtx_destroy(&sc->ptrlock);
+ pwc_free_buffers(sc,1);
+- usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->udev,sc->sc_dev);
+ return 0;
+ }
+
+ int
+ pwc_open(struct cdev *dev, int flag, int mode, struct thread *p)
+ {
+- struct pwc_softc *sc;
++ struct pwc_softc *sc = dev->si_drv1;
+ int i,err;
+- int unit = PWCUNIT(dev);
+-
+- sc = devclass_get_softc(pwc_devclass,unit);
+- if(sc == NULL)
+- return ENXIO;
++ int unit = device_get_unit(sc->sc_dev);
+
+ Trace(TRACE_OPEN,"pwc_open: flag=%d, mode=%d, unit=%d\n",flag, mode, unit);
+
+@@ -419,23 +393,6 @@
+ for (i = 0; i < sc->pwc_mbufs; i++)
+ sc->image_used[i] = 0;
+
+- /* Allocate iso transfers */
+- for (i = 0; i < MAX_ISO_BUFS; i++) {
+- sc->sbuf[i].sc = sc;
+- sc->sbuf[i].xfer = usbd_alloc_xfer(sc->udev);
+-
+- if(sc->sbuf[i].xfer == NULL) {
+- printf("%s: Failed to allocate transfer\n",device_get_nameunit(sc->sc_dev));
+- goto bad;
+- }
+-
+- sc->sbuf[i].data = usbd_alloc_buffer(sc->sbuf[i].xfer, ISO_BUFFER_SIZE);
+- if(sc->sbuf[i].data == NULL) {
+- printf("%s: Failed to allocate transferbuffer\n",device_get_nameunit(sc->sc_dev));
+- goto bad;
+- }
+- }
+-
+ sc->state = 0;
+ sc->vframe_count = 0;
+ sc->vframes_dumped = 0;
+@@ -476,10 +433,9 @@
+ int
+ pwc_close(struct cdev *dev, int flag, int mode, struct thread *p)
+ {
+- struct pwc_softc *sc;
+- int unit = PWCUNIT(dev);
+-
+- sc = devclass_get_softc(pwc_devclass, unit);
++ struct pwc_softc *sc = dev->si_drv1;
++ int unit = device_get_unit(sc->sc_dev);
++
+ Trace(TRACE_OPEN,"pwc_close: flag=%d, mode=%d, unit=%d\n", flag, mode, unit);
+
+ /* Dump statistics, but only if a reasonable amount of frames were
+@@ -495,19 +451,14 @@
+ pwc_dec1_exit();
+ else
+ pwc_dec23_exit(); /* Timon & Kiara */
+-
+- if(sc->sc_videopipe != NULL) {
+- usbd_abort_pipe(sc->sc_videopipe);
+- usbd_close_pipe(sc->sc_videopipe);
+- sc->sc_videopipe = NULL;
+- }
+
+ pwc_free_buffers(sc,0);
+
+ /* Turn off LEDS and power down camera, but only when not unplugged */
+ if(sc->error_status != EPIPE) {
+-
+- usbd_set_interface(sc->sc_iface, 0);
++
++ usb2_set_alt_interface_index(sc->udev, sc->sc_iface_index, 0);
++
+ pwc_set_leds(sc,0,0);
+
+ if(sc->power_save) {
+@@ -523,15 +474,14 @@
+ int
+ pwc_read(struct cdev *dev, struct uio *uio, int flag)
+ {
+- struct pwc_softc *sc;
+- int unit = PWCUNIT(dev);
++ struct pwc_softc *sc = dev->si_drv1;
++ int unit = device_get_unit(sc->sc_dev);
+ int bytes_to_read;
+ int count = uio->uio_resid;
+ int err;
+
+ Trace(TRACE_READ,"pwc_read: flag=%d, unit=%d\n", flag, unit);
+
+- sc = devclass_get_softc(pwc_devclass, unit);
+ if (sc->error_status)
+ return sc->error_status;
+
+@@ -583,10 +533,9 @@
+ int
+ pwc_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *p)
+ {
+- struct pwc_softc *sc;
+- int unit = PWCUNIT(dev);
++ struct pwc_softc *sc = dev->si_drv1;
++ int unit = device_get_unit(sc->sc_dev);
+
+- sc = devclass_get_softc(pwc_devclass, unit);
+ if (sc->error_status)
+ return sc->error_status;
+
+@@ -596,11 +545,9 @@
+ int
+ pwc_poll(struct cdev *dev, int events, struct thread *p)
+ {
+- struct pwc_softc *sc;
+- int unit = PWCUNIT(dev);
++ struct pwc_softc *sc = dev->si_drv1;
+ int revents = 0;
+
+- sc = devclass_get_softc(pwc_devclass, unit);
+ if(sc->error_status)
+ return sc->error_status;
+
+@@ -628,13 +575,9 @@
+ pwc_mmap(struct cdev *dev, vm_offset_t offset, vm_paddr_t *paddr, int nprot)
+ {
+ #ifdef USE_MMAP
+- struct pwc_softc *sc;
+- int unit = PWCUNIT(dev);
++ struct pwc_softc *sc = dev->si_drv1;
++ int unit = device_get_unit(sc->sc_dev);
+
+- sc = devclass_get_softc(pwc_devclass, unit);
+- if(sc == NULL)
+- return ENXIO;
+-
+ if (sc->error_status)
+ return sc->error_status;
+
+@@ -652,16 +595,10 @@
+ int
+ pwc_try_video_mode(struct pwc_softc *sc, int width, int height, int new_fps, int new_compression, int new_snapshot)
+ {
+- usb_endpoint_descriptor_t *edesc = NULL;
+- u_int8_t nendpt;
+- int i, j, err, ret;
+-
+- if(sc->sc_videopipe != NULL) {
+- usbd_abort_pipe(sc->sc_videopipe);
+- usbd_close_pipe(sc->sc_videopipe);
+- sc->sc_videopipe = NULL;
+- }
+-
++ int i, err, ret;
++
++ usb2_transfer_unsetup(sc->sc_xfer, MAX_ISO_BUFS);
++
+ pwc_reset_buffers(sc);
+
+ /* Try to set video mode... if that fails fallback to previous mode */
+@@ -678,52 +615,21 @@
+ sc->drop_frames++; /* try to avoid garbage during switch */
+ sc->vsync = 0;
+
+- err = usbd_set_interface(sc->sc_iface,sc->valternate);
+- if(err != USBD_NORMAL_COMPLETION) {
++ err = usb2_set_alt_interface_index(sc->udev, sc->sc_iface_index, sc->valternate);
++ if(err != USB_ERR_NORMAL_COMPLETION) {
+ printf("%s: Failed to set alternate interface to: %d (%d)\n",device_get_nameunit(sc->sc_dev),sc->valternate,err);
+ return -err;
+ }
+
+- err = usbd_endpoint_count(sc->sc_iface, &nendpt);
+- if(err != USBD_NORMAL_COMPLETION) {
+- printf("%s: Failed to get endpoint count (%d)\n",device_get_nameunit(sc->sc_dev),err);
+- return -err;
+- }
+- for (i = 0; i < nendpt; i++) {
+- edesc = usbd_interface2endpoint_descriptor(sc->sc_iface, i);
+- if(edesc != NULL && UE_GET_ADDR(edesc->bEndpointAddress) == sc->vendpoint)
+- break;
+- }
+- if(i == nendpt) {
+- printf("%s: Failed to find videoendpoint\n",device_get_nameunit(sc->sc_dev));
+- return -EINVAL;
+- }
+-
+- sc->vmax_packet_size = UGETW(edesc->wMaxPacketSize);
+- if(sc->vmax_packet_size < 0 || sc->vmax_packet_size > ISO_MAX_FRAME_SIZE) {
+- printf("%s: Invalid packetsize (%d) for endpoint %d\n",device_get_nameunit(sc->sc_dev),
+- sc->vmax_packet_size,edesc->bEndpointAddress);
+- return -EINVAL;
+- }
+-
+- err = usbd_open_pipe(sc->sc_iface,edesc->bEndpointAddress, 0, &sc->sc_videopipe);
+- if(err != USBD_NORMAL_COMPLETION) {
+- printf("%s: Failed to open videopipe (%d)\n",device_get_nameunit(sc->sc_dev),err);
++ /* Allocate iso transfers */
++ if (usb2_transfer_setup(sc->udev, &sc->sc_iface_index, sc->sc_xfer,
++ pwc_config, MAX_ISO_BUFS, sc, &Giant)) {
++ printf("%s: Failed to setup USB transfers\n", device_get_nameunit(sc->sc_dev));
+ return -err;
+ }
+
+ for (i = 0; i < MAX_ISO_BUFS; i++) {
+-
+- for(j = 0; j < ISO_FRAMES_PER_DESC; ++j)
+- sc->sbuf[i].sizes[j] = sc->vmax_packet_size;
+-
+- usbd_setup_isoc_xfer(sc->sbuf[i].xfer, sc->sc_videopipe,
+- &sc->sbuf[i],sc->sbuf[i].sizes,
+- ISO_FRAMES_PER_DESC,
+- USBD_NO_COPY|USBD_SHORT_XFER_OK,
+- pwc_isoc_handler);
+-
+- usbd_transfer(sc->sbuf[i].xfer);
++ usb2_transfer_start(sc->sc_xfer[i]);
+ }
+
+ if(sc->state & PWC_INIT)
+@@ -767,37 +673,41 @@
+ }
+
+ static void
+-pwc_isoc_handler(usbd_xfer_handle xfer, usbd_private_handle addr,usbd_status status)
++pwc_isoc_rx_callback(struct usb2_xfer *xfer)
+ {
+- struct pwc_iso_buf *req = addr;
+- struct pwc_softc *sc = req->sc;
++ uint8_t i;
++
++ switch(USB_GET_STATE(xfer)) {
++ case USB_ST_TRANSFERRED:
++ pwc_isoc_handler(xfer, xfer->priv_sc);
++
++ /* FALLTHROUGH */
++
++ case USB_ST_SETUP:
++ tr_setup:
++ for (i = 0; i != xfer->max_frame_count; i++)
++ xfer->frlengths[i] = xfer->max_frame_size;
++
++ xfer->nframes = xfer->max_frame_count;
++ usb2_start_hardware(xfer);
++ break;
++ default:
++ if (xfer->error != USB_ERR_CANCELLED)
++ goto tr_setup;
++ break;
++ }
++}
++
++static void
++pwc_isoc_handler(struct usb2_xfer *xfer, void *addr)
++{
++ struct pwc_softc *sc = addr;
+ struct pwc_frame_buf *fbuf;
+ unsigned char *fillptr = NULL;
+- u_int32_t count;
+ int awake = 0;
+ int i;
+-
+- usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL);
+- Trace(TRACE_ISOC_VERBOSE, "pwc_isoc_handler: status=%d count=%u\n",status,count);
+-
+- if (status == USBD_CANCELLED) {
+- Trace(TRACE_ISOC, "pwc_isoc_handler: status = cancelled\n");
+- return;
+- }
+- if(status != USBD_NORMAL_COMPLETION) {
+-
+- Trace(TRACE_ISOC, "pwc_isoc_handler called with status: %d\n",status);
+-
+- if (++sc->visoc_errors > MAX_ISOC_ERRORS) {
+-
+- if(sc->error_status != EIO)
+- printf("%s: Too many ISOC errors, bailing out.\n",device_get_nameunit(sc->sc_dev));
+
+- sc->error_status = EIO;
+- awake = 1;
+- }
+- goto handler_end; // ugly, but practical
+- }
++ Trace(TRACE_ISOC_VERBOSE, "pwc_isoc_handler: count=%u\n", xfer->actlen);
+
+ /* Reset ISOC error counter. We did get here, after all. */
+ sc->visoc_errors = 0;
+@@ -816,8 +726,8 @@
+ /* XXX there is no individual framestatus in FreeBSD usbstack
+ * so just assume all frames are good
+ */
+- u_int16_t flen = req->sizes[i];
+- unsigned char *iso_buf = req->data + sc->vmax_packet_size * i;
++ u_int16_t flen = xfer->frlengths[i];
++ u_int32_t iso_buf = xfer->max_frame_size * i;
+
+ if (flen > 0) { /* if valid data... */
+ if(sc->vsync > NOCOPY) { /* ...and we are not sync-hunting... */
+@@ -830,7 +740,7 @@
+ sc->vframes_error++;
+ }
+ else {
+- memcpy(fillptr, iso_buf, flen);
++ usb2_copy_out(xfer->frbuffers, iso_buf, fillptr, flen);
+ fillptr += flen;
+ }
+ }
+@@ -943,7 +853,6 @@
+ sc->vlast_packet_size = flen;
+
+ }
+-handler_end:
+ if(awake) {
+ if(sc->state & PWC_ASLEEP) {
+ wakeup(sc);
+@@ -953,16 +862,6 @@
+ selwakeuppri(&sc->rsel, PZERO);
+ }
+ }
+- /* setup size for next transfer */
+- for (i = 0; i < ISO_FRAMES_PER_DESC; i++)
+- req->sizes[i] = sc->vmax_packet_size;
+-
+- usbd_setup_isoc_xfer(xfer, sc->sc_videopipe, req, req->sizes,
+- ISO_FRAMES_PER_DESC,
+- USBD_NO_COPY|USBD_SHORT_XFER_OK,
+- pwc_isoc_handler);
+-
+- usbd_transfer(xfer);
+ }
+
+ int
+@@ -1050,6 +949,9 @@
+ {
+ int i;
+ Trace(TRACE_MEMORY, "Entering free_buffers(%p).\n", sc);
++
++ usb2_transfer_unsetup(sc->sc_xfer, MAX_ISO_BUFS);
++
+ if (sc->fbuf != NULL) {
+ for (i = 0; i < sc->pwc_fbufs; i++) {
+ if (sc->fbuf[i].data != NULL) {
+@@ -1074,13 +976,6 @@
+ free(sc->image_data,M_USBDEV);
+ sc->image_data = NULL;
+ }
+-
+- for (i = 0; i < MAX_ISO_BUFS; i++) {
+- if (sc->sbuf[i].xfer != NULL) {
+- usbd_free_xfer(sc->sbuf[i].xfer); /* implicit buffer free */
+- sc->sbuf[i].xfer = NULL;
+- }
+- }
+ }
+
+-DRIVER_MODULE(pwc, uhub, pwc_driver, pwc_devclass, usbd_driver_load, 0);
++DRIVER_MODULE(pwc, uhub, pwc_driver, pwc_devclass, NULL, 0);
diff --git a/multimedia/pwcbsd/files/patch-pwc.h b/multimedia/pwcbsd/files/patch-pwc.h
new file mode 100644
index 000000000000..5c514ba7f8fc
--- /dev/null
+++ b/multimedia/pwcbsd/files/patch-pwc.h
@@ -0,0 +1,95 @@
+--- pwc.h.orig 2006-09-27 07:21:01.000000000 +0200
++++ pwc.h 2009-05-27 20:22:49.147289211 +0200
+@@ -44,8 +44,16 @@
+ #include <vm/pmap.h>
+
+ #include <dev/usb/usb.h>
+-#include <dev/usb/usbdi.h>
+-#include <dev/usb/usbdi_util.h>
++#include <dev/usb/usb_mfunc.h>
++#include <dev/usb/usb_error.h>
++
++#include <dev/usb/usb_core.h>
++#include <dev/usb/usb_debug.h>
++#include <dev/usb/usb_lookup.h>
++#include <dev/usb/usb_util.h>
++#include <dev/usb/usb_busdma.h>
++#include <dev/usb/usb_request.h>
++
+ #include "pwc-uncompress.h"
+ #include "pwc-ioctl.h"
+ #include "videodev.h"
+@@ -69,7 +77,7 @@
+ #define TRACE_READ_VERBOSE 0x0800
+ #define TRACE_SEQUENCE 0x1000
+
+-#ifdef USB_DEBUG
++#if USB_DEBUG
+ #define Trace(R, A...) if (pwcdebug & R) printf(PWC_NAME " " A)
+ #define Debug(A...) if(pwcdebug) printf(PWC_NAME " " A)
+ extern int pwcdebug;
+@@ -93,14 +101,9 @@
+ #define FRAME_LOWMARK 5
+
+ /* Size and number of buffers for the ISO pipe. */
+-#define MAX_ISO_BUFS 3
+-
+-/* !!!!!!!!!! IMPORTANT DO NOT SET THIS HIGHER THAN 8 !!!!!!!!!!!!!!!
+- * !!!!!!!!!! OHCI IS BUGGY IF YOU DO SO !!!!!!!!!!!!!!!*/
+-#define ISO_FRAMES_PER_DESC 8
++#define MAX_ISO_BUFS 2
+
+-#define ISO_MAX_FRAME_SIZE 960
+-#define ISO_BUFFER_SIZE (ISO_FRAMES_PER_DESC * ISO_MAX_FRAME_SIZE)
++#define ISO_FRAMES_PER_DESC 16 /* should be multiple of 8 */
+
+ /* Frame buffers: contains compressed or uncompressed video data. */
+ #define MAX_FRAMES 5
+@@ -133,17 +136,17 @@
+ struct pwc_softc
+ {
+ device_t sc_dev;
+- usbd_device_handle udev;
+- usbd_interface_handle sc_iface;
+- usbd_pipe_handle sc_videopipe;
++
++ struct usb2_xfer *sc_xfer[MAX_ISO_BUFS];
++ struct usb2_device *udev;
+ struct cdev *sc_dev_t;
+
+ struct selinfo rsel;
+- char *name;
++ uint8_t sc_iface_index;
+ int type; /* type of cam (645, 646, 675, 680, 690, 720, 730, 740, 750) */
+ int release; /* release number */
+ int features; /* feature bits */
+- char serial[USB_MAX_STRING_LEN]; /* serial number (string) */
++ char serial[64]; /* serial number (string) */
+ int error_status; /* set when something goes wrong with the cam (unplugged, USB errors) */
+ int usb_init; /* set when the cam has been initialized over USB */
+
+@@ -165,7 +168,6 @@
+ int vframe_count; /* received frames */
+ int vframes_dumped; /* counter for dumped frames */
+ int vframes_error; /* frames received in error */
+- int vmax_packet_size; /* USB maxpacket size */
+ u_int16_t vlast_packet_size; /* for frame synchronisation */
+ int visoc_errors; /* number of contiguous ISOC errors */
+ int vcompression; /* desired compression factor */
+@@ -187,15 +189,7 @@
+ Note that MAX_ISO_BUFS != MAX_FRAMES != MAX_IMAGES....
+ We have in effect a back-to-back-double-buffer system.
+ */
+- /* 1: isoc */
+- struct pwc_iso_buf
+- {
+- unsigned char *data;
+- usbd_xfer_handle xfer;
+- u_int16_t sizes[ISO_FRAMES_PER_DESC];
+- struct pwc_softc *sc;
+- } sbuf[MAX_ISO_BUFS];
+-
++
+ char iso_init;
+
+ /* 2: frame */