qemu-devel
[Top][All Lists]
Advanced

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

Re: [Qemu-devel] [RFC PATCH 1/2] USB Video Class device emulation.


From: Blue Swirl
Subject: Re: [Qemu-devel] [RFC PATCH 1/2] USB Video Class device emulation.
Date: Thu, 10 Jun 2010 17:46:16 +0000

On Tue, Jun 8, 2010 at 3:34 PM, Natalia Portillo <address@hidden> wrote:

Please add a short description of the patch.

> Signed-off-by: Natalia Portillo <address@hidden>
> ---
>  hw/usb-uvc.c | 1096 
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 files changed, 1096 insertions(+), 0 deletions(-)
>  create mode 100644 hw/usb-uvc.c
>
> diff --git a/hw/usb-uvc.c b/hw/usb-uvc.c
> new file mode 100644
> index 0000000..b711f51
> --- /dev/null
> +++ b/hw/usb-uvc.c
> @@ -0,0 +1,1096 @@
> +/*
> + * USB Video Class Device emulation.
> + *
> + * Copyright (c) 2010 Claunia.com
> + * Written by Natalia Portillo <address@hidden>
> + *
> + * Based on hw/usb-hid.c:
> + * Copyright (c) 2005 Fabrice Bellard
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation in its version 2.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License along
> + * with this program; if not, see <http://www.gnu.org/licenses/>.
> + *
> + */
> +#include "hw.h"
> +#include "console.h"
> +#include "usb.h"
> +#include "qemu-error.h"
> +#include <stdio.h>
> +#include <fcntl.h>
> +#include <errno.h>
> +// V4L2 ioctls
> +#include <sys/ioctl.h>
> +#include <linux/videodev2.h>
> +
> +#define DEBUG_UVC

This should be commented out.

> +
> +#ifdef DEBUG_UVC
> +#define DPRINTF(fmt, ...) \
> +do { printf("usb-uvc: " fmt , ## __VA_ARGS__); } while (0)
> +#else
> +#define DPRINTF(fmt, ...) do {} while(0)
> +#endif
> +
> +/* USB Video Class Request codes */
> +#define USB_UVC_RC_UNDEFINED   0x00
> +#define USB_UVC_SET_CUR                        0x01
> +#define USB_UVC_GET_CUR                        0x81
> +#define USB_UVC_GET_MIN                        0x82
> +#define USB_UVC_GET_MAX                        0x83
> +#define USB_UVC_GET_RES                        0x84
> +#define USB_UVC_GET_LEN                        0x85
> +#define USB_UVC_GET_INFO               0x86
> +#define USB_UVC_GET_DEF                        0x87
> +
> +/* USB Video Class Request types */
> +#define UVCSetVideoControl             0x2100
> +#define UVCSetVideoStreaming   0x2200
> +#define UVCGetVideoControl             0xA100
> +#define UVCGetVideoStreaming   0xA200
> +
> +typedef struct USBUVCState {
> +    USBDevice dev;
> +       char    current_input;

The formatting seems to be off. Please check that indentation is 4
spaces, no tabs.

> +       char    *v4l2_device;
> +} USBUVCState;
> +
> +static int v4l2_fd;
> +static char *frame;
> +static char *frame_start;
> +static int frame_length;
> +static int frame_id;
> +static int first_bulk_packet;
> +static int frame_remaining_bytes;
> +static int frame_max_length;

Couldn't these belong to USBUVCState?

> +
> +static const uint8_t qemu_uvc_dev_descriptor[] = {
> +       0x12,       /*  u8 bLength; */
> +       0x01,       /*  u8 bDescriptorType; Device */

It would be more readable if you defined structures for all the
descriptors and some #defines or enums for the magic numbers. Then
this would become something like:
    .bLength = 0x12,
    .bDescriptorType = USB_DESCTYPE_DEVICE,

so very few comments would be needed anymore. It's a big task though
and could be taken as later cleanup.

> +       0x00, 0x02, /*  u16 bcdUSB; v2.0 */
> +
> +       0xEF,       /*  u8  bDeviceClass; */
> +       0x02,       /*  u8  bDeviceSubClass; */
> +       0x01,       /*  u8  bDeviceProtocol; [ low/full speeds only ] */
> +       0x08,       /*  u8  bMaxPacketSize0; 8 Bytes */
> +
> +       /* Vendor and product id are arbitrary.  */
> +       0x00, 0x00, /*  u16 idVendor; */
> +       0x00, 0x00, /*  u16 idProduct; */
> +       0x00, 0x00, /*  u16 bcdDevice */
> +
> +       0x01,       /*  u8  iManufacturer; */
> +       0x02,       /*  u8  iProduct; */
> +       0x00,       /*  u8  iSerialNumber; */
> +       0x01        /*  u8  bNumConfigurations; */
> +};
> +
> +static const uint8_t qemu_uvc_config_descriptor[] = {
> +
> +       /* one configuration */
> +       0x09,       /*  u8  bLength; */
> +       0x02,       /*  u8  bDescriptorType; Configuration */
> +       0xB7, 0x00, /*  u16 wTotalLength; */

I'm not familiar with USB at all, is the endianness specified to be
little endian, or should this be different on a big endian host or
guest?

> +       0x02,       /*  u8  bNumInterfaces; (2) */
> +       0x01,       /*  u8  bConfigurationValue; */
> +       0x00,       /*  u8  iConfiguration; */
> +       0x80,       /*  u8  bmAttributes;
> +                                Bit 7: must be set,
> +                                6: Self-powered,
> +                                5: Remote wakeup,
> +                                4..0: resvd */
> +       0xFA,       /*  u8  MaxPower; */
> +
> +       /* interface association */
> +       0x08,           /*  u8  ifa_bLength; */
> +       0x0B,           /*  u8  ifa_bDescriptorType; Interface Association */
> +       0x00,           /*  u8  ifa_bFirstInterface; */
> +       0x02,           /*  u8  ifa_bInterfaceCount; */
> +       0x0E,           /*  u8  ifa_bFunctionClass; CC_VIDEO */
> +       0x03,           /*  u8  ifa_bFunctionSubClass; 
> SS_VIDEO_INTERFACE_COLLECTION */
> +       0x00,           /*  u8  ifa_bFunctionProtocol; unused */
> +       0x02,           /*  u8  ifa_iFunction; */
> +
> +       /* video control interface */
> +       0x09,       /*  u8  if_bLength; */
> +       0x04,       /*  u8  if_bDescriptorType; Interface */
> +       0x00,       /*  u8  if_bInterfaceNumber; */
> +       0x00,       /*  u8  if_bAlternateSetting; */
> +       0x01,       /*  u8  if_bNumEndpoints; */
> +       0x0E,       /*  u8  if_bInterfaceClass; CC_VIDEO */
> +       0x01,       /*  u8  if_bInterfaceSubClass; SC_VIDEOCONTROL */
> +       0x00,       /*  u8  if_bInterfaceProtocol; unused */
> +       0x02,       /*  u8  if_iInterface; */
> +
> +       /* class specific vc interface descriptor */
> +       0x0D,           /*  u8  cif_bLength; */
> +       0x24,           /*  u8  cif_bDescriptorType; CS_INTERFACE */
> +       0x01,           /*  u8  cif_bDescriptorSubType; VC_HEADER */
> +       0x00, 0x01, /*  u16 cif_bcdUVC; 1.0 */
> +       0x42, 0x00, /*  u16 cif_wTotalLength */
> +       0x80, 0x8D, /*  u32 cif_dwClockFrequency; Deprecated, 6Mhz */

It's MHz.

> +       0x5B, 0x00,
> +       0x01,           /*  u8  cif_bInCollection; */
> +       0x01,           /*  u8  cif_baInterfaceNr; */
> +
> +       /* input terminal descriptor */
> +       0x11,           /*  u8  itd_bLength; */
> +       0x24,           /*  u8  itd_bDescriptorType; CS_INTERFACE */
> +       0x02,           /*  u8  itd_bDescriptorSubtype; VC_INPUT_TERMINAL */
> +       0x01,           /*  u8  itd_bTerminalID; */
> +       0x01, 0x02, /*  u16  itd_wTerminalType; ITT_CAMERA */
> +       0x00,           /*  u8  itd_bAssocTerminal; No association */
> +       0x00,           /*  u8  itd_iTerminal; Unused */
> +       0x00, 0x00, /*  u16  itd_wObjectiveFocalLengthMin; No optical zoom */
> +       0x00, 0x00, /*  u16  itd_wObjectiveFocalLengthMax; No optical zoom */
> +       0x00, 0x00, /*  u16  itd_wOcularFocalLength; No optical zoom */
> +       0x02,           /*  u8  itd_bControlSize; No controls implemented */
> +       0x00, 0x00, /*  u16  itd_bmControls; No controls supported */
> +
> +       0x08,           /*      u8      itd_bLength; */
> +       0x24,           /*      u8      itd_bDescriptorType; CS_INTERFACE */
> +       0x02,           /*      u8      itd_bDescriptorSubtype; 
> VC_INPUT_TERMINAL */
> +       0x02,           /*      u8      itd_bTerminalID; */
> +       0x01, 0x04,     /*      u16     itd_wTerminalType; ITT_COMPOSITE */
> +       0x00,           /*      u8      itd_bAssocTerminal; */
> +       0x00,           /*      u8      itd_iTerminal; */
> +
> +       /* output terminal descriptor */
> +       0x09,           /*      u8      otd_bLength; */
> +       0x24,           /*      u8      otd_bDescriptorType; CS_INTERFACE */
> +       0x03,           /*      u8      otd_bDescriptorSubtype; 
> VC_OUTPUT_TERMINAL */
> +       0x03,           /*      u8      otd_bTerminalID; */
> +       0x01, 0x01,     /*      u16     otd_wTerminalType; TT_STREAMING */
> +       0x00,           /*      u8      otd_bAssocTerminal; No association */
> +       0x05,           /*      u8      otd_bSourceID; */
> +       0x00,           /*      u8      otd_iTerminal; */
> +
> +       /* selector unit descriptor */
> +       0x08,           /*      u8      sud_bLength; */
> +       0x24,           /*      u8      sud_bDescriptorType; CS_INTERFACE */
> +       0x04,           /*      u8      sud_bDescriptorSubtype; 
> VC_SELECTOR_UNIT */
> +       0x04,           /*      u8      sud_bUnitID; */
> +       0x02,           /*      u8      sud_bNrInPins; */
> +       0x01,           /*      u8      sud_baSourceID; */
> +       0x02,
> +       0x00,           /*      u8      sud_iSelector; */
> +
> +       /* processing unit descriptor */
> +       0x0B,           /*      u8      pud_bLength; */
> +       0x24,           /*      u8      pud_bDescriptorType; CS_INTERFACE */
> +       0x05,           /*      u8      pud_bDescriptorSubtype; 
> VC_PROCESSING_UNIT */
> +       0x05,           /*      u8      pud_bUnitID; */
> +       0x04,           /*      u8      pud_bSourceID; */
> +       0x00, 0x00,     /*      u16     pud_wMaxMultiplier; */
> +       0x02,           /*      u8      pud_bControlSize; */
> +       0x01, 0x00,     /*      u16     pud_bmControls; Brightness control 
> supported */
> +       0x00,           /*      u8      pud_iProcessing; */
> +
> +       /* standard interrupt endpoint */
> +       0x07,           /*      u8      ep_bLenght; */
> +       0x05,           /*      u8      ep_bDescriptorType; Endpoint */
> +       0x81,           /*      u8      ep_bEndpointAddress; IN Endpoint 1 */
> +       0x03,           /*      u8      ep_bmAttributes; Interrupt */
> +       0x08, 0x00,     /*      u8      ep_wMaxPacketSize; 8 bytes */
> +       0xFF,           /*      u8      ep_bInterval; 32ms */
> +
> +       /* class-specific interrupt endpoint */
> +       0x05,           /*      u8      ep_bLenght; */
> +       0x25,           /*      u8      ep_bDescriptorType; CS_ENDPOINT */
> +       0x03,           /*      u8      ep_bmAttributes; EP_INTERRUPT */
> +       0x08, 0x00,     /*      u8      ep_wMaxPacketSize; 8 bytes */
> +
> +       /* standard vs interface descriptor alternate 0 */
> +       0x09,           /*      u8      bLength; */
> +       0x04,           /*      u8      bDescriptorType; INTERFACE */
> +       0x01,           /*      u8      bInterfaceNumber; */
> +       0x00,           /*      u8      bAlternateSetting; */
> +       0x01,           /*      u8      bNumEndpoints; */
> +       0x0E,           /*      u8      bInterfaceClass; CC_VIDEO */
> +       0x02,           /*      u8      bInterfaceSubClass; 
> SC_VIDEO_STREAMING */
> +       0x00,           /*      u8      bInterfaceProtocol; 
> PC_PROTOCOL_UNDEFINED */
> +       0x00,           /*      u8      iInterface; Unused */
> +
> +       /* class-specific vs header descriptor input alternate 0 */
> +       0x0E,           /*      u8      bLength; */
> +       0x24,           /*      u8      bDescriptorType; CS_INTERFACE */
> +       0x01,           /*      u8      bDescriptorSubtype; VS_INPUT_HEADER */
> +       0x01,           /*      u8      bNumFormats; */
> +       0x46, 0x00,     /*      u8      wTotalLength; */
> +       0x82,           /*      u8      bEndpointAddress; */
> +       0x00,           /*      u8      bmInfo; */
> +       0x03,           /*      u8      bTerminalLink; */
> +       0x00,           /*      u8      bStillCaptureMethod; */
> +       0x00,           /*      u8      bTriggerSupport; */
> +       0x00,           /*      u8      bTriggerUsage; */
> +       0x01,           /*      u8      bControlSize; */
> +       0x00,           /*      u8      bmaControls; */
> +
> +       /* class-specific vs format descriptor alternate 0 */
> +       0x0B,           /*      u8      bLength; */
> +       0x24,           /*      u8      bDescriptorType; CS_INTERFACE */
> +       0x06,           /*      u8      bDescriptorSubtype; VS_FORMAT_MJPEG */
> +       0x01,           /*      u8      bFormatIndex; */
> +       0x01,           /*      u8      bNumFrameDescriptors; */
> +       0x01,           /*      u8      bmFlags; */
> +       0x01,           /*      u8      bDefaultFrameIndex; */
> +       0x00,           /*      u8      bAspectRatioX; */
> +       0x00,           /*      u8      bAspectRatioY; */
> +       0x02,           /*      u8      bmInterlaceFlags; */
> +       0x00,           /*      u8      bCopyProtect; */
> +
> +       /* class-specific vs frame descriptor alternate 0 */
> +       0x26,           /*      u8      bLength; */
> +       0x24,           /*      u8      bDescriptorType; CS_INTERFACE */
> +       0x07,           /*      u8      bDescriptorSubtype; VS_FRAME_MJPEG */
> +       0x01,           /*      u8      bFrameIndex; */
> +       0x01,           /*      u8      bmCapabilities; */
> +       0x40, 0x01,     /*      u8      wWidth; 320 */
> +       0xF0, 0x00,     /*      u8      wHeight; 240 */
> +       0x00, 0xEC,
> +       0x0D, 0x00,     /*      u32     dwMinBitRate; */
> +       0x00, 0xEC,
> +       0x0D, 0x00,     /*      u32     dwMaxBitRate; */
> +       0x72, 0xCE,
> +       0x00, 0x00,     /*      u32     dwMaxVideoFrameBufSize; */
> +       0x2A, 0x2C,
> +       0x0A, 0x00,     /*      u32     dwDefaultFrameInterval; */
> +       0x00,           /*      u8      bFrameIntervalType;     */
> +       0x2A, 0x2C,
> +       0x0A, 0x00,     /*      u32     dwMinFrameInterval; */
> +       0x2A, 0x2C,
> +       0x0A, 0x00,     /*      u32     dwMaxFrameInterval; */
> +       0x00, 0x00,
> +       0x00, 0x00,     /*      u32     dwFrameIntervalStep; */
> +
> +       /* standard vs isochronous video data endpoint descriptor */
> +       0x07,           /*      u8      bLength; */
> +       0x05,           /*      u8      bDescriptorType; */
> +       0x82,           /*      u8      bEndpointAddress; IN endpoint 2 */
> +       0x02,           /*      u8      bmAttributes; Isochronous transfer, 
> asynchronous sync */
> +       0x40, 0x00,     /*      u16     wMaxPacketSize; 510 bytes */
> +       0x00            /*      u8      bInterval; */
> +};
> +
> +static void get_frame_read(void)
> +{
> +       DPRINTF("Getting frame.\n");
> +       frame = frame_start;
> +       frame_length = read(v4l2_fd, frame, frame_max_length);
> +
> +       if(frame_length == -1)
> +       {

There must be a space between 'if' and '(' and the braces must be on
the same line as 'if' etc. Please read CODING_STYLE document.

> +               DPRINTF("Error while reading frame.\n");
> +               frame_length = 0;
> +       }
> +       else
> +       {

} else {

> +               frame_id = frame_id ^ 1;
> +               first_bulk_packet = 1;
> +               frame_remaining_bytes = frame_length;
> +               DPRINTF("Got a frame of %d bytes.\n", frame_length);
> +       }
> +
> +       return;
> +}
> +
> +static void usb_uvc_handle_reset(USBDevice *dev)
> +{
> +       DPRINTF("Reset called\n");
> +}
> +
> +static int usb_uvc_handle_control(USBDevice *dev, int request, int value,
> +                                                                 int index, 
> int length, uint8_t *data)
> +{
> +       int ret = 0;
> +       USBUVCState *s = (USBUVCState *)dev;
> +
> +       DPRINTF("Control called\n");
> +       //      DPRINTF("Request: 0x%08X\n", request);
> +       //      DPRINTF("Value: 0x%08X\n", value);
> +       //      DPRINTF("Index: 0x%08X\n", index);
> +       //      DPRINTF("Length: 0x%08X\n", length);

Are these needed? If they are only used in specific debugging, please
add a separate DPRINTF_xyz function which can be enabled with
DEBUG_xyz.

> +
> +       switch(request)
> +       {
> +               case DeviceRequest | USB_REQ_GET_STATUS:

I think the formatting for 'case' is also not in line.

> +                       DPRINTF("USB Request: Get Status\n");
> +                       data[0] = (1 << USB_DEVICE_SELF_POWERED) |
> +            (dev->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP);
> +                       data[1] = 0x00;
> +                       ret = 2;
> +                       break;
> +               case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
> +                       DPRINTF("USB Request: Clear feature\n");
> +                       if (value == USB_DEVICE_REMOTE_WAKEUP) {
> +                               DPRINTF("USB Request: Unset remote wakeup\n");
> +                               dev->remote_wakeup = 0;
> +                       } else {
> +                               goto fail;
> +                       }
> +                       ret = 0;
> +                       break;
> +               case DeviceOutRequest | USB_REQ_SET_FEATURE:
> +                       DPRINTF("USB Request: Set feature\n");
> +                       if (value == USB_DEVICE_REMOTE_WAKEUP) {
> +                               DPRINTF("USB Request: Set remote wakeup\n");
> +                               dev->remote_wakeup = 1;
> +                       } else {
> +                               goto fail;
> +                       }
> +                       ret = 0;
> +                       break;
> +               case DeviceOutRequest | USB_REQ_SET_ADDRESS:
> +                       DPRINTF("USB Request: Set address to 0x%08X\n", 
> value);
> +                       dev->addr = value;
> +                       ret = 0;
> +                       break;
> +               case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
> +                       DPRINTF("USB Request: Get descriptor\n");
> +                       switch(value >> 8) {
> +                               case USB_DT_DEVICE:
> +                                       DPRINTF("USB Request: Get device 
> descriptor\n");
> +                                       memcpy(data, qemu_uvc_dev_descriptor,
> +                                                  
> sizeof(qemu_uvc_dev_descriptor));
> +                                       ret = sizeof(qemu_uvc_dev_descriptor);
> +                                       break;
> +                               case USB_DT_CONFIG:
> +                                       DPRINTF("USB Request: Get 
> configuration descriptor\n");
> +                                       memcpy(data, 
> qemu_uvc_config_descriptor,
> +                                                  
> sizeof(qemu_uvc_config_descriptor));
> +                                       ret = 
> sizeof(qemu_uvc_config_descriptor);
> +                                       break;
> +                               case USB_DT_STRING:
> +                                       DPRINTF("USB Request: Get device 
> strings\n");
> +                                       switch(value & 0xff) {
> +                                               case 0:
> +                                                       DPRINTF("USB Request: 
> Get language IDs\n");
> +                                                       /* language ids */
> +                                                       data[0] = 4;
> +                                                       data[1] = 3;
> +                                                       data[2] = 0x09;
> +                                                       data[3] = 0x04;
> +                                                       ret = 4;
> +                                                       break;
> +                                               case 1:
> +                                                       /* vendor description 
> */
> +                                                       DPRINTF("USB Request: 
> Get vendor string\n");
> +                                                       ret = 
> set_usb_string(data, "QEMU " QEMU_VERSION);
> +                                                       break;
> +                                               case 2:
> +                                                       /* product 
> description */
> +                                                       DPRINTF("USB Request: 
> Get product string\n");
> +                                                       ret = 
> set_usb_string(data, "QEMU USB VIDEO CLASS 2");
> +                                                       break;
> +                                               case 3:
> +                                                       /* serial number */
> +                                                       DPRINTF("USB Request: 
> Get serial number string\n");
> +                                                       ret = 
> set_usb_string(data, "1");
> +                                                       break;
> +                                               default:
> +                                                       goto fail;
> +                                       }
> +                                       break;
> +                               default:
> +                                       goto fail;
> +                       }
> +                       break;
> +               case DeviceRequest | USB_REQ_GET_CONFIGURATION:
> +                       DPRINTF("USB Request: Get configuration\n");
> +                       data[0] = 1;
> +                       ret = 1;
> +                       break;
> +               case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
> +                       DPRINTF("USB Request: Set configuration\n");
> +                       ret = 0;
> +                       break;
> +               case DeviceRequest | USB_REQ_GET_INTERFACE:
> +                       DPRINTF("USB Request: Get interface\n");
> +                       data[0] = 0;
> +                       ret = 1;
> +                       break;
> +               case DeviceOutRequest | USB_REQ_SET_INTERFACE:
> +                       DPRINTF("USB Request: Set interface\n");
> +                       ret = 0;
> +                       break;
> +               case EndpointOutRequest | USB_REQ_CLEAR_FEATURE:
> +                       DPRINTF("USB Request: Clear endpoint\n");
> +                       ret = 0;
> +                       break;
> +               case InterfaceOutRequest | USB_REQ_SET_INTERFACE:
> +                       DPRINTF("USB Request: Set interface\n");
> +                       ret = 0;
> +                       break;
> +                       /* Class specific requests.  */
> +               case UVCGetVideoControl | USB_UVC_GET_CUR:
> +                       ret = 0;
> +
> +                       if((index&0xFF) == 0x01 && ((value&0xFF00) == 0x0100 
> || (value&0xFF00) == 0x0200))

Please add #defines or enums for the magic values. There should be
spaces around '&'.

> +                       {
> +                               DPRINTF("USB Request: Get video control 
> current setting attribute for interface %d\n", index&0xFF);
> +                               if((value&0xFF00) == 0x0100)
> +                                       DPRINTF("\tVS_PROBE_CONTROL\n");
> +                               else
> +                                       DPRINTF("\tVS_COMMIT_CONTROL\n");
> +
> +                               if(length != 26)
> +                               {
> +                                       DPRINTF("USB Request: Requested %d 
> bytes, expected 26 bytes\n", length);
> +                                       goto fail;
> +                               }
> +
> +                               data[0] = 0; // bmHint
> +                               data[1] = 0;
> +                               data[2] = 1; // bFormatIndex
> +                               data[3] = 1; // bFrameIndex
> +                               data[4] = 0x2A; // dwFrameInterval
> +                               data[5] = 0x2C;
> +                               data[6] = 0x0A;
> +                               data[7] = 0x00;
> +                               data[8] = 0; // wKeyFrameRate
> +                               data[9] = 0;
> +                               data[10] = 0; // wPFrameRate
> +                               data[11] = 0;
> +                               data[12] = 0; // wCompQuality
> +                               data[13] = 0;
> +                               data[14] = 1; // wCompWindowSize
> +                               data[15] = 0;
> +                               data[16] = 0x20; // wDelay
> +                               data[17] = 0;
> +                               data[18] = 0x72; // dwMaxVideoFrameSize
> +                               data[19] = 0xCE;
> +                               data[20] = 0x00;
> +                               data[21] = 0x00;
> +                               data[22] = 0x72; // dwMaxPayloadTransferSize
> +                               data[23] = 0xCE;
> +                               data[24] = 0x00;
> +                               data[25] = 0x00;
> +                               ret = 26;
> +                       }
> +                       else if((index&0xFF00) == 0x0400 && (value&0xFF00) == 
> 0x0100) // Setting input
> +                       {
> +                               DPRINTF("USB Request: Asking for current 
> input\n");
> +                               if(length != 1)
> +                               {
> +                                       DPRINTF("USB Request: Requested %d 
> bytes, expected 1 byte\n", length);
> +                                       goto fail;
> +                               }
> +
> +                               data[0] = s->current_input;
> +                               ret = 1;
> +                       }
> +                       else if((index&0xFF00) == 0x0500 && (value&0xFF00) == 
> 0x0200) // PU_BRIGHTNESS_CONTROL of PROCESSING_UNIT
> +                       {
> +                               DPRINTF("USB Resquest: Asking for current 
> brightness\n");
> +                               if(length != 2)
> +                               {
> +                                       DPRINTF("USB Request: Requested %d 
> bytes, expected 2 bytes\n", length);
> +                                       goto fail;
> +                               }
> +
> +                               data[0] = 1;
> +                               data[1] = 0;
> +                               ret = 2;
> +                       }
> +                       else
> +                               goto fail;
> +                       break;
> +               case UVCGetVideoControl | USB_UVC_GET_MIN:
> +                       ret = 0;
> +
> +                       if((index&0xFF) == 0x01 && ((value&0xFF00) == 0x0100 
> || (value&0xFF00) == 0x0200))
> +                       {
> +                               DPRINTF("USB Request: Get video control 
> minimum setting attribute for interface %d\n", index&0xFF);
> +
> +                               if(length != 26)
> +                               {
> +                                       DPRINTF("USB Request: Requested %d 
> bytes, expected 26 bytes\n", length);
> +                                       goto fail;
> +                               }
> +
> +                               data[0] = 0; // bmHint
> +                               data[1] = 0;
> +                               data[2] = 1; // bFormatIndex
> +                               data[3] = 1; // bFrameIndex
> +                               data[4] = 0x2A; // dwFrameInterval
> +                               data[5] = 0x2C;
> +                               data[6] = 0x0A;
> +                               data[7] = 0x00;
> +                               data[8] = 0; // wKeyFrameRate
> +                               data[9] = 0;
> +                               data[10] = 0; // wPFrameRate
> +                               data[11] = 0;
> +                               data[12] = 0; // wCompQuality
> +                               data[13] = 0;
> +                               data[14] = 1; // wCompWindowSize
> +                               data[15] = 0;
> +                               data[16] = 0x20; // wDelay
> +                               data[17] = 0;
> +                               data[18] = 0x72; // dwMaxVideoFrameSize
> +                               data[19] = 0xCE;
> +                               data[20] = 0x00;
> +                               data[21] = 0x00;
> +                               data[22] = 0x72; // dwMaxPayloadTransferSize
> +                               data[23] = 0xCE;
> +                               data[24] = 0x00;
> +                               data[25] = 0x00;
> +                               ret = 26;
> +                       }
> +                       else if((index&0xFF00) == 0x0400 && (value&0xFF00) == 
> 0x0100) // Setting input
> +                       {
> +                               DPRINTF("USB Request: Asking for minimum 
> input\n");
> +                               if(length != 1)
> +                               {
> +                                       DPRINTF("USB Request: Requested %d 
> bytes, expected 1 byte\n", length);
> +                                       goto fail;
> +                               }
> +
> +                               data[0] = 0;
> +                               ret = 1;
> +                       }
> +                       else if((index&0xFF00) == 0x0500 && (value&0xFF00) == 
> 0x0200) // PU_BRIGHTNESS_CONTROL of PROCESSING_UNIT
> +                       {
> +                               DPRINTF("USB Resquest: Asking for minimum 
> brightness\n");
> +                               if(length != 2)
> +                               {
> +                                       DPRINTF("USB Request: Requested %d 
> bytes, expected 2 bytes\n", length);
> +                                       goto fail;
> +                               }
> +
> +                               data[0] = 1;
> +                               data[1] = 0;
> +                               ret = 2;
> +                       }
> +                       else
> +                               goto fail;
> +                       break;
> +               case UVCGetVideoControl | USB_UVC_GET_MAX:
> +                       if((index&0xFF) == 0x01 && ((value&0xFF00) == 0x0100 
> || (value&0xFF00) == 0x0200))
> +                       {
> +                               DPRINTF("USB Request: Get video control 
> maximum setting attribute for interface %d\n", index&0xFF);
> +
> +                               if(length != 26)
> +                               {
> +                                       DPRINTF("USB Request: Requested %d 
> bytes, expected 26 bytes\n", length);
> +                                       goto fail;
> +                               }
> +
> +                               data[0] = 0; // bmHint
> +                               data[1] = 0;
> +                               data[2] = 1; // bFormatIndex
> +                               data[3] = 1; // bFrameIndex
> +                               data[4] = 0x2A; // dwFrameInterval
> +                               data[5] = 0x2C;
> +                               data[6] = 0x0A;
> +                               data[7] = 0x00;
> +                               data[8] = 0; // wKeyFrameRate
> +                               data[9] = 0;
> +                               data[10] = 0; // wPFrameRate
> +                               data[11] = 0;
> +                               data[12] = 0; // wCompQuality
> +                               data[13] = 0;
> +                               data[14] = 1; // wCompWindowSize
> +                               data[15] = 0;
> +                               data[16] = 0x20; // wDelay
> +                               data[17] = 0;
> +                               data[18] = 0x72; // dwMaxVideoFrameSize
> +                               data[19] = 0xCE;
> +                               data[20] = 0x00;
> +                               data[21] = 0x00;
> +                               data[22] = 0x72; // dwMaxPayloadTransferSize
> +                               data[23] = 0xCE;
> +                               data[24] = 0x00;
> +                               data[25] = 0x00;
> +                               ret = 26;
> +                       }
> +                       else if((index&0xFF00) == 0x0400 && (value&0xFF00) == 
> 0x0100) // Setting input
> +                       {
> +                               DPRINTF("USB Request: Asking maximum 
> input\n");
> +                               if(length != 1)
> +                               {
> +                                       DPRINTF("USB Request: Requested %d 
> bytes, expected 1 byte\n", length);
> +                                       goto fail;
> +                               }
> +
> +                               data[0] = 1;
> +                               ret = 1;
> +                       }
> +                       else if((index&0xFF00) == 0x0500 && (value&0xFF00) == 
> 0x0200) // PU_BRIGHTNESS_CONTROL of PROCESSING_UNIT
> +                       {
> +                               DPRINTF("USB Resquest: Asking for maximum 
> brightness\n");
> +                               if(length != 2)
> +                               {
> +                                       DPRINTF("USB Request: Requested %d 
> bytes, expected 2 bytes\n", length);
> +                                       goto fail;
> +                               }
> +
> +                               data[0] = 1;
> +                               data[1] = 0;
> +                               ret = 2;
> +                       }
> +                       else
> +                               goto fail;
> +                       break;
> +               case UVCGetVideoControl | USB_UVC_GET_DEF:
> +                       if((index&0xFF) == 0x01 && ((value&0xFF00) == 0x0100 
> || (value&0xFF00) == 0x0200))
> +                       {
> +                               DPRINTF("USB Request: Get video control 
> default setting attribute for interface %d\n", index&0xFF);
> +
> +                               if(length != 26)
> +                               {
> +                                       DPRINTF("USB Request: Requested %d 
> bytes, expected 26 bytes\n", length);
> +                                       goto fail;
> +                               }
> +
> +                               data[0] = 0; // bmHint
> +                               data[1] = 0;
> +                               data[2] = 1; // bFormatIndex
> +                               data[3] = 1; // bFrameIndex
> +                               data[4] = 0x2A; // dwFrameInterval
> +                               data[5] = 0x2C;
> +                               data[6] = 0x0A;
> +                               data[7] = 0x00;
> +                               data[8] = 0; // wKeyFrameRate
> +                               data[9] = 0;
> +                               data[10] = 0; // wPFrameRate
> +                               data[11] = 0;
> +                               data[12] = 0; // wCompQuality
> +                               data[13] = 0;
> +                               data[14] = 1; // wCompWindowSize
> +                               data[15] = 0;
> +                               data[16] = 0x20; // wDelay
> +                               data[17] = 0;
> +                               data[18] = 0x72; // dwMaxVideoFrameSize
> +                               data[19] = 0xCE;
> +                               data[20] = 0x00;
> +                               data[21] = 0x00;
> +                               data[22] = 0x72; // dwMaxPayloadTransferSize
> +                               data[23] = 0xCE;
> +                               data[24] = 0x00;
> +                               data[25] = 0x00;
> +                               ret = 26;
> +                       }
> +                       else if((index&0xFF00) == 0x0400 && (value&0xFF00) == 
> 0x0100) // Setting input
> +                       {
> +                               DPRINTF("USB Request: Asking for default 
> input\n");
> +                               if(length != 1)
> +                               {
> +                                       DPRINTF("USB Request: Requested %d 
> bytes, expected 1 byte\n", length);
> +                                       goto fail;
> +                               }
> +
> +                               data[0] = 0;
> +                               ret = 1;
> +                       }
> +                       else if((index&0xFF00) == 0x0500 && (value&0xFF00) == 
> 0x0200) // PU_BRIGHTNESS_CONTROL of PROCESSING_UNIT
> +                       {
> +                               DPRINTF("USB Resquest: Asking for default 
> brightness\n");
> +                               if(length != 2)
> +                               {
> +                                       DPRINTF("USB Request: Requested %d 
> bytes, expected 2 bytes\n", length);
> +                                       goto fail;
> +                               }
> +
> +                               data[0] = 1;
> +                               data[1] = 0;
> +                               ret = 2;
> +                       }
> +                       else
> +                               goto fail;
> +                       break;
> +               case UVCSetVideoControl | USB_UVC_SET_CUR:
> +                       DPRINTF("USB Request: Set video control setting 
> attribute for interface %d\n", index&0xFF);
> +
> +                       ret = 0;
> +
> +                       if((index&0xFF) == 0x01 && ((value&0xFF00) == 0x0100 
> || (value&0xFF00) == 0x0200))
> +                       {
> +                               if((value&0xFF00) == 0x0100)
> +                                       DPRINTF("\tVS_PROBE_CONTROL\n");
> +                               else
> +                                       DPRINTF("\tVS_COMMIT_CONTROL\n");
> +
> +                               if(length != 26)
> +                               {
> +                                       DPRINTF("USB Request: Requested %d 
> bytes, expected 26 bytes\n", length);
> +                                       goto fail;
> +                               }
> +
> +                               DPRINTF("\tbmHint = 0x%02X%02X\n", data[1], 
> data[0]);
> +                               DPRINTF("\tbFormatIndex = %d\n", data[2]);
> +                               DPRINTF("\tbFrameIndex = %d\n", data[3]);
> +                               DPRINTF("\tdwFrameInterval = 
> 0x%02X%02X%02X%02X\n", data[7], data[6], data[5], data[4]);
> +                               DPRINTF("\twKeyFrameRate = 0x%02X%02X\n", 
> data[9], data[8]);
> +                               DPRINTF("\twPFrameRate = 0x%02X%02X\n", 
> data[11], data[10]);
> +                               DPRINTF("\twCompQuality = 0x%02X%02X\n", 
> data[13], data[12]);
> +                               DPRINTF("\twCompWindowSize = 0x%02X%02X\n", 
> data[15], data[14]);
> +                               DPRINTF("\twDelay = 0x%02X%02X\n", data[17], 
> data[16]);
> +                               DPRINTF("\tdwMaxVideoFrameSize= 
> 0x%02X%02X%02X%02X\n", data[21], data[20], data[19], data[18]);
> +                               DPRINTF("\tdwMaxPayloadTransferSize= 
> 0x%02X%02X%02X%02X\n", data[25], data[24], data[23], data[22]);
> +
> +                               frame = frame_start;
> +                               frame_remaining_bytes = frame_length;
> +                               first_bulk_packet = 1;
> +
> +                               ret = 26;
> +                       }
> +                       else if((index&0xFF00) == 0x0400 && (value&0xFF00) == 
> 0x0100) // Setting input
> +                       {
> +                               DPRINTF("Setting input to %d\n", data[0]);
> +                               if(length != 1)
> +                               {
> +                                       DPRINTF("USB Request: Requested %d 
> bytes, expected 1 byte\n", length);
> +                                       goto fail;
> +                               }
> +
> +                               s->current_input = data[0];
> +                               ret = 1;
> +                       }
> +                       else if((index&0xFF00) == 0x0500 && (value&0xFF00) == 
> 0x0200) // PU_BRIGHTNESS_CONTROL of PROCESSING_UNIT
> +                       {
> +                               DPRINTF("USB Resquest: Setting brightness, 
> value stays the same\n");
> +                               if(length != 2)
> +                               {
> +                                       DPRINTF("USB Request: Requested %d 
> bytes, expected 2 bytes\n", length);
> +                                       goto fail;
> +                               }
> +
> +                               ret = 2;
> +                       }
> +                       else
> +                               goto fail;
> +                       break;
> +               case UVCGetVideoControl | USB_UVC_GET_RES:
> +                       if((index&0xFF00) == 0x0500 && (value&0xFF00) == 
> 0x0200) // PU_BRIGHTNESS_CONTROL of PROCESSING_UNIT
> +                       {
> +                               DPRINTF("USB Resquest: Asking for brightness 
> resolution\n");
> +                               if(length != 2)
> +                               {
> +                                       DPRINTF("USB Request: Requested %d 
> bytes, expected 2 bytes\n", length);
> +                                       goto fail;
> +                               }
> +
> +                               data[0] = 1;
> +                               data[1] = 0;
> +                               ret = 2;
> +                       }
> +                       else
> +                               goto fail;
> +                       break;
> +               default:
> +               fail:
> +                       DPRINTF("USB Request: Unhandled control request\n");
> +                       DPRINTF("\tRequest: 0x%08X\n", request);
> +                       DPRINTF("\tValue: 0x%08X\n", value);
> +                       DPRINTF("\tIndex: 0x%08X\n", index);
> +                       DPRINTF("\tLength: 0x%08X\n", length);
> +                       ret = USB_RET_STALL;
> +                       break;
> +    }
> +
> +       return ret;
> +}
> +
> +static int usb_uvc_handle_data(USBDevice *dev, USBPacket *p)
> +{
> +       int ret = 0;
> +
> +       //DPRINTF("Data called\n");
> +       //DPRINTF("Packet ID: %d\n", p->pid);
> +       //DPRINTF("Device address: %d\n", p->devaddr);
> +       //DPRINTF("Device endpoint: %d\n", p->devep);
> +       //DPRINTF("Data length: %d\n", p->len);
> +
> +       switch (p->pid)
> +       {
> +               case USB_TOKEN_OUT:
> +                       DPRINTF("USB Data Out requested.\n");
> +                       break;
> +               case USB_TOKEN_IN:
> +                       if(p->devep == 1) // IN endpoint 1 (hardware button)
> +                       {
> +                               p->data[0] = 2;
> +                               p->data[1] = 1;
> +                               p->data[2] = 0;
> +                               p->data[3] = 0;
> +                       }
> +                       else if(p->devep == 2) // IN endpoint 2 (video data)
> +                       {
> +                               if(first_bulk_packet)
> +                               {
> +                                       p->data[0] = 2;
> +                                       p->data[1] = 0x82 | frame_id;
> +                                       memcpy((p->data)+2,frame,62);
> +                                       ret = 64;
> +                                       first_bulk_packet=0;
> +                                       frame = frame + 62;
> +                                       frame_remaining_bytes = 
> frame_remaining_bytes - 62;
> +                               }
> +                               else if(frame_remaining_bytes<64)
> +                               {
> +                                       
> memcpy(p->data,frame,frame_remaining_bytes);
> +                                       ret = frame_remaining_bytes;
> +                                       get_frame_read();
> +                               }
> +                               else if(frame_remaining_bytes==64)
> +                               {
> +                                       
> memcpy(p->data,frame,frame_remaining_bytes);
> +                                       ret = frame_remaining_bytes;
> +                                       frame_remaining_bytes = 0;
> +                               }
> +                               else if(frame_remaining_bytes==0)
> +                               {
> +                                       ret = 0;
> +                                       get_frame_read();
> +                               }
> +                               else
> +                               {
> +                                       memcpy(p->data,frame,64);
> +                                       frame = frame+64;
> +                                       frame_remaining_bytes = 
> frame_remaining_bytes-64;
> +                                       ret = 64;
> +                               }
> +                       }
> +                       else
> +                       {
> +                               DPRINTF("USB Data In requested.\n");
> +                               DPRINTF("Requested data from endpoint 
> %02X\n", p->devep);
> +                       }
> +                       break;
> +           default:
> +                       DPRINTF("Bad token: %d\n", p->pid);
> +                       //fail:

Probably should be removed.

> +                       ret = USB_RET_STALL;
> +                       break;
> +    }
> +
> +    return ret;
> +}
> +
> +static void usb_uvc_handle_destroy(USBDevice *dev)
> +{
> +       DPRINTF("Destroy called\n");
> +       close(v4l2_fd);
> +}
> +
> +static int usb_uvc_initfn(USBDevice *dev)
> +{
> +       struct v4l2_capability capabilities;
> +       struct v4l2_input video_input;
> +       struct v4l2_format v_format;
> +       int video_input_index;
> +       int ret_err;
> +
> +       DPRINTF("Init called\n");
> +
> +       USBUVCState *s = (USBUVCState *)dev;
> +
> +       s->current_input = 0;
> +       s->dev.speed = USB_SPEED_FULL;
> +
> +       if (!s->v4l2_device) {
> +        error_report("V4L2 device specification needed.\n");
> +        return -1;
> +    }
> +       else
> +       {
> +               DPRINTF("Trying to open %s\n.", s->v4l2_device);
> +       }
> +
> +       v4l2_fd = open(s->v4l2_device, O_RDWR);
> +
> +       if(v4l2_fd==-1)
> +       {
> +               switch(errno)
> +               {
> +                       case EACCES:
> +                               error_report("Access denied.");
> +                               break;
> +                       case EBUSY:
> +                               error_report("Device busy.");
> +                               break;
> +                       case ENXIO:
> +                               error_report("Device does not exist.");
> +                               break;
> +                       case ENOMEM:
> +                               error_report("Not enough memory to open 
> device.");
> +                               break;
> +                       case EMFILE:
> +                               error_report("Process reached maximum files 
> opened.");
> +                               break;
> +                       case ENFILE:
> +                               error_report("System reached maximum files 
> opened.");
> +                               break;
> +                       default:
> +                               error_report("Unknown error %d opening 
> device.", errno);
> +                               break;
> +               }
> +
> +               return -1;
> +       }
> +
> +       DPRINTF("Device opened correctly.\n");
> +
> +       DPRINTF("Querying capabilities.\n");
> +
> +       ret_err = ioctl(v4l2_fd, VIDIOC_QUERYCAP, &capabilities);
> +
> +       if(ret_err==-1)
> +       {
> +               switch(errno)
> +               {
> +                       case EINVAL:
> +                               error_report("Device is not V4L2 device.\n");
> +                               break;
> +                       default:
> +                               error_report("Device returned unknown error 
> %d.\n", errno);
> +                               break;
> +               }
> +
> +               return -1;
> +       }
> +
> +       DPRINTF("Device driver: %s\n", capabilities.driver);
> +       DPRINTF("Device name: %s\n", capabilities.card);
> +       DPRINTF("Device bus: %s\n", capabilities.bus_info);
> +       DPRINTF("Driver version: %u.%u.%u\n",(capabilities.version >> 16) & 
> 0xFF,(capabilities.version >> 8) & 0xFF,    capabilities.version & 0xFF);
> +       DPRINTF("Device capabilities: 0x%08X\n", capabilities.capabilities);
> +
> +       DPRINTF("Enumerating video inputs.\n");
> +       memset(&video_input, 0, sizeof(video_input));
> +       video_input.index=0;
> +       while((ioctl(v4l2_fd, VIDIOC_ENUMINPUT, &video_input)==0))
> +       {
> +               if(video_input.type == V4L2_INPUT_TYPE_CAMERA)
> +               {
> +                       video_input_index = video_input.index;
> +                       break;
> +               }
> +
> +               video_input.index++;
> +       }
> +
> +       DPRINTF("Setting video input to index %d\n", video_input_index);
> +       ret_err = ioctl(v4l2_fd, VIDIOC_S_INPUT, &video_input_index);
> +
> +       if(ret_err==-1)
> +       {
> +               switch(errno)
> +               {
> +                       case EINVAL:
> +                               error_report("Incorrect video input 
> selected.\n");
> +                               break;
> +                       case EBUSY:
> +                               error_report("Input cannot be switched.\n");
> +                               break;
> +                       default:
> +                               error_report("Unknown error %d.\n", errno);
> +                               break;
> +               }
> +
> +               return -1;
> +       }
> +
> +       ioctl(v4l2_fd, VIDIOC_G_INPUT, &ret_err);
> +
> +       if(ret_err==video_input_index)
> +               DPRINTF("Video input correctly set.\n");
> +       else
> +       {
> +               error_report("Some error happened while setting video 
> input.\n");
> +               return -1;
> +       }
> +
> +       DPRINTF("Trying to set 320x240 MJPEG.\n");
> +       memset(&v_format, 0, sizeof(v_format));
> +       v_format.type                = V4L2_BUF_TYPE_VIDEO_CAPTURE;
> +       v_format.fmt.pix.width       = 320;
> +       v_format.fmt.pix.height      = 240;
> +       v_format.fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG;
> +       v_format.fmt.pix.field       = V4L2_FIELD_INTERLACED;
> +
> +       ret_err = ioctl (v4l2_fd, VIDIOC_S_FMT, &v_format);

Please remove the space between 'ioctl' and '(' for consistency.

> +
> +       if(ret_err == -1)
> +       {
> +               switch(errno)
> +               {
> +                       case EBUSY:
> +                               error_report("Device busy while changing 
> format.\n");
> +                               break;
> +                       case EINVAL:
> +                               error_report("Invalid format.\n");
> +                               break;
> +                       default:
> +                               error_report("Unknown error %d while changing 
> format.\n", errno);
> +                               break;
> +               }
> +
> +               return -1;
> +       }
> +
> +       frame_max_length = v_format.fmt.pix.sizeimage;
> +
> +       DPRINTF("Format correctly set.\n");
> +       DPRINTF("Maximum image size: %d bytes.\n", frame_max_length);
> +
> +       DPRINTF("Allocating memory for frames.\n");
> +       frame = malloc(frame_max_length);

qemu_malloc()

> +       frame_start = frame;
> +
> +       frame_id = 1;
> +
> +       get_frame_read();
> +
> +    return 0;
> +}
> +
> +static USBDevice *usb_uvc_init(const char *filename)
> +{
> +    USBDevice *dev;
> +
> +    dev = usb_create(NULL /* FIXME */, "usb-uvc-webcam");
> +    qdev_init_nofail(&dev->qdev);
> +
> +       DPRINTF("Filename: %s\n.", filename);
> +
> +       if (!*filename) {
> +        error_report("character device specification needed");
> +        return NULL;
> +    }
> +
> +    return dev;
> +}
> +
> +static struct USBDeviceInfo usb_uvc_info = {
> +    .product_desc   = "QEMU USB Video Class Device",
> +    .qdev.name      = "usb-uvc-webcam",
> +    .qdev.desc      = "QEMU USB Video Class Device",
> +    .usbdevice_name = "uvc-webcam",
> +       .usbdevice_init = usb_uvc_init,
> +    .qdev.size      = sizeof(USBUVCState),
> +    .init           = usb_uvc_initfn,
> +    .handle_packet  = usb_generic_handle_packet,
> +    .handle_reset   = usb_uvc_handle_reset,
> +    .handle_control = usb_uvc_handle_control,
> +    .handle_data    = usb_uvc_handle_data,
> +    .handle_destroy = usb_uvc_handle_destroy,
> +       .qdev.props             = (Property[]) {
> +               DEFINE_PROP_STRING("device", USBUVCState, v4l2_device),
> +               DEFINE_PROP_END_OF_LIST(),
> +       },
> +};
> +
> +static void usb_uvc_register_devices(void)
> +{
> +    usb_qdev_register(&usb_uvc_info);
> +}
> +device_init(usb_uvc_register_devices)
> --
>
>
>

reply via email to

[Prev in Thread] Current Thread [Next in Thread]