On Mon, May 30, 2016 at 04:22:56PM +0200, Martin Pieuchot wrote:

> On 26/05/16(Thu) 16:09, patrick keshishian wrote:
> > 
> > Included is my initial effort to port the dual-licensed driver
> > for Fushicai Audio-Video Grabber (vendor 0x1b71 product 0x3002).
> 
> Nice.  Did you test both bulk and iso? Some comments inline.
> 
> > Index: dev/usb/files.usb
> > ===================================================================
> > RCS file: /cvs/obsd/src/sys/dev/usb/files.usb,v
> > retrieving revision 1.126
> > diff -u -p -u -p -r1.126 files.usb
> > --- dev/usb/files.usb       8 Jan 2016 15:54:13 -0000       1.126
> > +++ dev/usb/files.usb       26 May 2016 22:34:38 -0000
> > @@ -35,6 +35,12 @@ device   uvideo: video, firmload
> >  attach     uvideo at uhub
> >  file       dev/usb/uvideo.c                uvideo
> >  
> > +# USBTV007 devices
> > +device     utvfu: video, audio
> > +attach     utvfu at uhub
> > +file       dev/usb/utvfu.c                 utvfu
> > +file       dev/usb/utvfu_ops.c             utvfu
> 
> I'd appreciate if we can keep the driver in one file, when the license
> issue is solved, this is coherent with the rest of our tree.

Me too.  Would it be ok to merge utvfu.c and utvfu_ops.c by including
both Copyrights in this file?  Should it be

        [Copyright 1]
        [Code 1]
        [Copyright 2]
        [Code 2]

or

        [Copyright 1]
        [Copyright 2]
        [Code 1]
        [Code 2]

then?
 
> > +#ifndef _UTVFU_H_
> > +#define _UTVFU_H_
> 
> Is there any hardware reference for this device or everything is reverse
> engineered?  I mean the values below are specified somewhere?
> 
> > +
> > +#include <sys/queue.h>
> > +#include <sys/videoio.h>
> > +
> > +/* Hardware. */
> > +#define UTVFU_VIDEO_ENDP   0x81
> > +#define UTVFU_AUDIO_ENDP   0x83
> > +#define UTVFU_BASE         0xc000
> > +#define UTVFU_REQUEST_REG  12
> > +
> > +/* Number of concurrent isochronous urbs submitted.
> > + * Higher numbers was seen to overly saturate the USB bus. */
> 
> This comment does not respect style(9).
> 
> > +#define UTVFU_ISOC_TRANSFERS       16
> > +#define UTVFU_ISOC_PACKETS 8
> > +
> > +#define UTVFU_CHUNK_SIZE   256
> > +#define UTVFU_CHUNK                240
> > +
> > +#define UTVFU_AUDIO_URBSIZE        20480
> > +#define UTVFU_AUDIO_HDRSIZE        4
> > +#define UTVFU_AUDIO_BUFFER 65536
> > +
> > +#define    UTVFU_COMPOSITE_INPUT   0
> > +#define    UTVFU_SVIDEO_INPUT      1
>         ^^^^^^
> We try to avoid mixing space and tab after "#define"
> 
> > +/* Chunk header. */
> > +#define UTVFU_MAGIC(hdr)   (hdr & 0xff000000U)
> > +#define UTVFU_MAGIC_OK(hdr)        ((hdr & 0xff000000U) == 0x88000000U)
> > +#define UTVFU_FRAME_ID(hdr)        ((hdr & 0x00ff0000U) >> 16)
> > +#define UTVFU_ODD(hdr)             ((hdr & 0x0000f000U) >> 15)
> > +#define UTVFU_CHUNK_NO(hdr)        (hdr & 0x00000fffU)
> > +
> > +#define UTVFU_TV_STD  (V4L2_STD_525_60 | V4L2_STD_PAL)
> > +
> > +/* parameters for supported TV norms */
> > +struct utvfu_norm_params {
> > +   v4l2_std_id     norm;
> > +   int             cap_width,
> > +                   cap_height,
> > +                   frame_len;
> 
> Please one type per line.
> 
> > +};
> 
> > +extern struct utvfu_norm_params    utvfu_norm_params[];
> > +
> > +#define    UTVFU_MAX_BUFFERS       32
> > +struct utvfu_mmap {
> > +   SIMPLEQ_ENTRY(utvfu_mmap)       q_frames;
> > +   uint8_t                         *buf;
> > +   struct v4l2_buffer              v4l2_buf;
> > +};
> > +typedef SIMPLEQ_HEAD(, utvfu_mmap) q_mmap;
> > +
> > +struct utvfu_frame_buf {
> > +   uint            off;
> > +   uint            size;
> > +   uint16_t        chunks_done;
> > +   uint8_t         fid; 
> > +   uint8_t         last_odd;
> > +   uint8_t         *buf;
> > +};
> > +
> > +#define    UTVFU_NFRAMES_MAX       40
> > +struct utvfu_isoc_xfer {
> > +   struct utvfu_softc      *sc;
> > +   struct usbd_xfer        *xfer;
> > +   void                    *buf;
> > +   uint16_t                size[UTVFU_NFRAMES_MAX];
> > +};
> > +
> > +struct utvfu_bulk_xfer {
> > +   struct usbd_xfer        *xfer;
> > +   void                    *buf;
> 
> I'd use the simpler approach of using KERNADDR(&xfer->dmabuf, 0) instead
> of defining another structure to abstract an USB xfer.  You can look at
> uhidev_get_report_async_cb() for an example.
> 
> > +};
> > +
> > +struct utvfu_vs_iface {
> > +   struct usbd_pipe        *pipeh;
> > +   int                     endpoint;
> > +   uint32_t                psize;
> > +   struct utvfu_isoc_xfer  ixfer[UTVFU_ISOC_TRANSFERS];
> > +};
> > +
> > +struct utvfu_as_iface {
> > +   struct usbd_pipe        *pipeh;
> > +   int                     endpoint;
> > +   struct utvfu_bulk_xfer  bxfer;
> > +};
> > +
> > +struct utvfu_audio_chan {
> > +   uint8_t                 *start;
> > +   uint8_t                 *end;
> > +   uint8_t                 *cur;
> > +   int                     blksize;
> > +   void                    *intr_arg;
> > +   void                    (*intr)(void *);
> > +   struct utvfu_as_iface   iface;
> > +};
> > +
> > +/* Per-device structure. */
> > +struct utvfu_softc {
> > +   struct device           sc_dev;
> > +   struct usbd_device      *sc_udev;
> > +   struct usbd_interface   *sc_uifaceh;
> > +
> > +   /* audio & video device */
> > +   struct device           *sc_audiodev;
> > +   struct device           *sc_videodev;
> > +
> > +   int                     sc_normi;
> > +   int                     sc_nchunks;
> > +   int                     sc_input;
> > +   int                     sc_max_frame_sz;
> > +   int                     sc_nframes;
> > +
> > +   struct utvfu_vs_iface   sc_iface;
> > +   struct utvfu_frame_buf  sc_fb;
> > +
> > +   int                     sc_as_running;
> > +   struct utvfu_audio_chan sc_audio;
> > +
> > +   /* mmap */
> > +   struct utvfu_mmap       sc_mmap[UTVFU_MAX_BUFFERS];
> > +   uint8_t                 *sc_mmap_buffer;
> > +   q_mmap                  sc_mmap_q;
> > +   int                     sc_mmap_bufsz;
> > +   int                     sc_mmap_count;
> > +   int                     sc_mmap_flag;
> > +
> > +   /* uplayer */
> > +   void                    *sc_uplayer_arg;
> > +   int                     *sc_uplayer_fsize;
> > +   uint8_t                 *sc_uplayer_fbuffer;
> > +   void                    (*sc_uplayer_intr)(void *);
> > +};
> > +
> > +int        utvfu_max_frame_size(void);
> > +int        utvfu_set_regs(struct utvfu_softc *, const uint16_t regs[][2], 
> > int);
> > +void       utvfu_image_chunk(struct utvfu_softc *, u_char *);
> > +int        utvfu_configure_for_norm(struct utvfu_softc *, v4l2_std_id);
> > +int        utvfu_start_capture(struct utvfu_softc *);
> > +int        utvfu_mmap_queue(struct utvfu_softc *, uint8_t *, int);
> > +void       utvfu_read(struct utvfu_softc *, uint8_t *, int);
> > +
> > +void       utvfu_audio_decode(struct utvfu_softc *, int);
> > +int        utvfu_audio_start(struct utvfu_softc *);
> > +int        utvfu_audio_stop(struct utvfu_softc *);
> > +int        utvfu_audio_start_chip(struct utvfu_softc *);
> > +int        utvfu_audio_stop_chip(struct utvfu_softc *);
> > +
> > +#endif
> > Index: dev/usb/utvfu.c
> > ===================================================================
> > RCS file: dev/usb/utvfu.c
> > diff -N dev/usb/utvfu.c
> > --- /dev/null       1 Jan 1970 00:00:00 -0000
> > +++ dev/usb/utvfu.c 26 May 2016 22:34:38 -0000
> > @@ -0,0 +1,691 @@
> > +/* $OpenBSD$ */
> > +/*
> > + * Fushicai USBTV007 Audio-Video Grabber Driver
> > + *
> > + * Product web site:
> > + * 
> > http://www.fushicai.com/products_detail/&productId=d05449ee-b690-42f9-a661-aa7353894bed.html
> > + *
> > + * Following LWN articles were very useful in construction of this driver:
> > + * Video4Linux2 API series: http://lwn.net/Articles/203924/
> > + * videobuf2 API explanation: http://lwn.net/Articles/447435/
> > + * Thanks go to Jonathan Corbet for providing this quality documentation.
> > + * He is awesome.
> > + *
> > + * Copyright (c) 2013 Lubomir Rintel
> > + * Copyright (c) 2013 Federico Simoncelli
> > + * All rights reserved.
> > + * No physical hardware was harmed running Windows during the
> > + * reverse-engineering activity
> > + *
> > + * Redistribution and use in source and binary forms, with or without
> > + * modification, are permitted provided that the following conditions
> > + * are met:
> > + * 1. Redistributions of source code must retain the above copyright
> > + *    notice, this list of conditions, and the following disclaimer,
> > + *    without modification.
> > + * 2. The name of the author may not be used to endorse or promote products
> > + *    derived from this software without specific prior written permission.
> > + *
> > + * Alternatively, this software may be distributed under the terms of the
> > + * GNU General Public License ("GPL").
> > + */
> > +
> > +#include <sys/param.h>
> > +#include <sys/systm.h>
> > +#include <sys/kernel.h>
> > +#include <sys/malloc.h>
> > +#include <sys/audioio.h>
> > +#include <sys/videoio.h>
> > +
> > +#include <machine/bus.h>
> > +
> > +#include <dev/audio_if.h>
> > +#include <dev/usb/usb.h>
> > +#include <dev/usb/usbdi.h>
> > +#include <dev/usb/usbdivar.h>
> > +#include <dev/usb/usbdi_util.h>
> > +#include <dev/usb/usbdevs.h>
> > +#include <dev/video_if.h>
> > +
> > +#include "utvfu.h"
> > +
> > +#define UTVFU_DEBUG
> > +#ifdef UTVFU_DEBUG
> > +extern int utvfu_debug;
> > +#define DPRINTF(l, x...) do { if ((l) <= utvfu_debug) printf(x); } while 
> > (0)
> 
> You mostly have 1 level, so do you really want a `D'PRINTF()?  By the
> way, we try to remove debug printf before committing code.  So if you
> think some of the printfs you added won't help later, just get rid of
> them.
> 
> > +#else
> > +#define DPRINTF(l, x...)
> > +#endif
> > +
> > +#define DEVNAME(_s) ((_s)->sc_dev.dv_xname)
> > +
> > +struct utvfu_norm_params utvfu_norm_params[] = {
> > +   {
> > +           .norm = V4L2_STD_525_60,
> > +           .cap_width = 720,
> > +           .cap_height = 480,
> > +           /* 4 bytes/2 pixel YUYV/YUV 4:2:2 */
> > +           .frame_len = (720 * 480 * 2),
> > +   },
> > +   {
> > +           .norm = V4L2_STD_PAL,
> > +           .cap_width = 720,
> > +           .cap_height = 576,
> > +           /* 4 bytes/2 pixel YUYV/YUV 4:2:2 */
> > +           .frame_len = (720 * 576 * 2),
> > +   }
> > +};
> > +
> > +int
> > +utvfu_set_regs(struct utvfu_softc *sc, const uint16_t regs[][2], int size)
> > +{
> > +   int i;
> > +   usbd_status error;
> > +   usb_device_request_t req;
> > +
> > +   DPRINTF(1, "%s: %s: size=%d enter\n", DEVNAME(sc), __func__, size);
> > +
> > +   req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
> > +   req.bRequest = UTVFU_REQUEST_REG;
> > +   USETW(req.wLength, 0);
> > +
> > +   for (i = 0; i < size; i++) {
> > +           USETW(req.wIndex, regs[i][0]);
> > +           USETW(req.wValue, regs[i][1]);
> > +
> > +           error = usbd_do_request(sc->sc_udev, &req, NULL);
> > +           if (USBD_NORMAL_COMPLETION != error) {
> 
> This way of checking for error value might be clever, but I IMHO being
> coherent with the rest of the code base is more important.  So I would
> stick to the "if (variable == constant)" style.

Yes, please.  Also not mixing up e.g. 'i++' and '++i' would be nice.

Reply via email to