2 * USB Video Class Device emulation.
4 * Copyright (c) 2010 Claunia.com
5 * Written by Natalia Portillo <natalia@claunia.com>
7 * Based on hw/usb-hid.c:
8 * Copyright (c) 2005 Fabrice Bellard
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License as
12 * published by the Free Software Foundation in its version 2.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, see <http://www.gnu.org/licenses/>.
26 #include "qemu-error.h"
31 #include <sys/ioctl.h>
32 #include <linux/videodev2.h>
37 #define DPRINTF(fmt, ...) \
38 do { printf("usb-uvc: " fmt , ## __VA_ARGS__); } while (0)
40 #define DPRINTF(fmt, ...) do {} while(0)
43 /* USB Video Class Request codes */
44 #define USB_UVC_RC_UNDEFINED 0x00
45 #define USB_UVC_SET_CUR 0x01
46 #define USB_UVC_GET_CUR 0x81
47 #define USB_UVC_GET_MIN 0x82
48 #define USB_UVC_GET_MAX 0x83
49 #define USB_UVC_GET_RES 0x84
50 #define USB_UVC_GET_LEN 0x85
51 #define USB_UVC_GET_INFO 0x86
52 #define USB_UVC_GET_DEF 0x87
54 /* USB Video Class Request types */
55 #define UVCSetVideoControl 0x2100
56 #define UVCSetVideoStreaming 0x2200
57 #define UVCGetVideoControl 0xA100
58 #define UVCGetVideoStreaming 0xA200
60 typedef struct USBUVCState
{
68 static char *frame_start
;
69 static int frame_length
;
71 static int first_bulk_packet
;
72 static int frame_remaining_bytes
;
73 static int frame_max_length
;
75 static const uint8_t qemu_uvc_dev_descriptor
[] = {
76 0x12, /* u8 bLength; */
77 0x01, /* u8 bDescriptorType; Device */
78 0x00, 0x02, /* u16 bcdUSB; v2.0 */
80 0xEF, /* u8 bDeviceClass; */
81 0x02, /* u8 bDeviceSubClass; */
82 0x01, /* u8 bDeviceProtocol; [ low/full speeds only ] */
83 0x08, /* u8 bMaxPacketSize0; 8 Bytes */
85 /* Vendor and product id are arbitrary. */
86 0x00, 0x00, /* u16 idVendor; */
87 0x00, 0x00, /* u16 idProduct; */
88 0x00, 0x00, /* u16 bcdDevice */
90 0x01, /* u8 iManufacturer; */
91 0x02, /* u8 iProduct; */
92 0x00, /* u8 iSerialNumber; */
93 0x01 /* u8 bNumConfigurations; */
96 static const uint8_t qemu_uvc_config_descriptor
[] = {
98 /* one configuration */
99 0x09, /* u8 bLength; */
100 0x02, /* u8 bDescriptorType; Configuration */
101 0xB7, 0x00, /* u16 wTotalLength; */
102 0x02, /* u8 bNumInterfaces; (2) */
103 0x01, /* u8 bConfigurationValue; */
104 0x00, /* u8 iConfiguration; */
105 0x80, /* u8 bmAttributes;
110 0xFA, /* u8 MaxPower; */
112 /* interface association */
113 0x08, /* u8 ifa_bLength; */
114 0x0B, /* u8 ifa_bDescriptorType; Interface Association */
115 0x00, /* u8 ifa_bFirstInterface; */
116 0x02, /* u8 ifa_bInterfaceCount; */
117 0x0E, /* u8 ifa_bFunctionClass; CC_VIDEO */
118 0x03, /* u8 ifa_bFunctionSubClass; SS_VIDEO_INTERFACE_COLLECTION */
119 0x00, /* u8 ifa_bFunctionProtocol; unused */
120 0x02, /* u8 ifa_iFunction; */
122 /* video control interface */
123 0x09, /* u8 if_bLength; */
124 0x04, /* u8 if_bDescriptorType; Interface */
125 0x00, /* u8 if_bInterfaceNumber; */
126 0x00, /* u8 if_bAlternateSetting; */
127 0x01, /* u8 if_bNumEndpoints; */
128 0x0E, /* u8 if_bInterfaceClass; CC_VIDEO */
129 0x01, /* u8 if_bInterfaceSubClass; SC_VIDEOCONTROL */
130 0x00, /* u8 if_bInterfaceProtocol; unused */
131 0x02, /* u8 if_iInterface; */
133 /* class specific vc interface descriptor */
134 0x0D, /* u8 cif_bLength; */
135 0x24, /* u8 cif_bDescriptorType; CS_INTERFACE */
136 0x01, /* u8 cif_bDescriptorSubType; VC_HEADER */
137 0x00, 0x01, /* u16 cif_bcdUVC; 1.0 */
138 0x42, 0x00, /* u16 cif_wTotalLength */
139 0x80, 0x8D, /* u32 cif_dwClockFrequency; Deprecated, 6Mhz */
141 0x01, /* u8 cif_bInCollection; */
142 0x01, /* u8 cif_baInterfaceNr; */
144 /* input terminal descriptor */
145 0x11, /* u8 itd_bLength; */
146 0x24, /* u8 itd_bDescriptorType; CS_INTERFACE */
147 0x02, /* u8 itd_bDescriptorSubtype; VC_INPUT_TERMINAL */
148 0x01, /* u8 itd_bTerminalID; */
149 0x01, 0x02, /* u16 itd_wTerminalType; ITT_CAMERA */
150 0x00, /* u8 itd_bAssocTerminal; No association */
151 0x00, /* u8 itd_iTerminal; Unused */
152 0x00, 0x00, /* u16 itd_wObjectiveFocalLengthMin; No optical zoom */
153 0x00, 0x00, /* u16 itd_wObjectiveFocalLengthMax; No optical zoom */
154 0x00, 0x00, /* u16 itd_wOcularFocalLength; No optical zoom */
155 0x02, /* u8 itd_bControlSize; No controls implemented */
156 0x00, 0x00, /* u16 itd_bmControls; No controls supported */
158 0x08, /* u8 itd_bLength; */
159 0x24, /* u8 itd_bDescriptorType; CS_INTERFACE */
160 0x02, /* u8 itd_bDescriptorSubtype; VC_INPUT_TERMINAL */
161 0x02, /* u8 itd_bTerminalID; */
162 0x01, 0x04, /* u16 itd_wTerminalType; ITT_COMPOSITE */
163 0x00, /* u8 itd_bAssocTerminal; */
164 0x00, /* u8 itd_iTerminal; */
166 /* output terminal descriptor */
167 0x09, /* u8 otd_bLength; */
168 0x24, /* u8 otd_bDescriptorType; CS_INTERFACE */
169 0x03, /* u8 otd_bDescriptorSubtype; VC_OUTPUT_TERMINAL */
170 0x03, /* u8 otd_bTerminalID; */
171 0x01, 0x01, /* u16 otd_wTerminalType; TT_STREAMING */
172 0x00, /* u8 otd_bAssocTerminal; No association */
173 0x05, /* u8 otd_bSourceID; */
174 0x00, /* u8 otd_iTerminal; */
176 /* selector unit descriptor */
177 0x08, /* u8 sud_bLength; */
178 0x24, /* u8 sud_bDescriptorType; CS_INTERFACE */
179 0x04, /* u8 sud_bDescriptorSubtype; VC_SELECTOR_UNIT */
180 0x04, /* u8 sud_bUnitID; */
181 0x02, /* u8 sud_bNrInPins; */
182 0x01, /* u8 sud_baSourceID; */
184 0x00, /* u8 sud_iSelector; */
186 /* processing unit descriptor */
187 0x0B, /* u8 pud_bLength; */
188 0x24, /* u8 pud_bDescriptorType; CS_INTERFACE */
189 0x05, /* u8 pud_bDescriptorSubtype; VC_PROCESSING_UNIT */
190 0x05, /* u8 pud_bUnitID; */
191 0x04, /* u8 pud_bSourceID; */
192 0x00, 0x00, /* u16 pud_wMaxMultiplier; */
193 0x02, /* u8 pud_bControlSize; */
194 0x01, 0x00, /* u16 pud_bmControls; Brightness control supported */
195 0x00, /* u8 pud_iProcessing; */
197 /* standard interrupt endpoint */
198 0x07, /* u8 ep_bLenght; */
199 0x05, /* u8 ep_bDescriptorType; Endpoint */
200 0x81, /* u8 ep_bEndpointAddress; IN Endpoint 1 */
201 0x03, /* u8 ep_bmAttributes; Interrupt */
202 0x08, 0x00, /* u8 ep_wMaxPacketSize; 8 bytes */
203 0xFF, /* u8 ep_bInterval; 32ms */
205 /* class-specific interrupt endpoint */
206 0x05, /* u8 ep_bLenght; */
207 0x25, /* u8 ep_bDescriptorType; CS_ENDPOINT */
208 0x03, /* u8 ep_bmAttributes; EP_INTERRUPT */
209 0x08, 0x00, /* u8 ep_wMaxPacketSize; 8 bytes */
211 /* standard vs interface descriptor alternate 0 */
212 0x09, /* u8 bLength; */
213 0x04, /* u8 bDescriptorType; INTERFACE */
214 0x01, /* u8 bInterfaceNumber; */
215 0x00, /* u8 bAlternateSetting; */
216 0x01, /* u8 bNumEndpoints; */
217 0x0E, /* u8 bInterfaceClass; CC_VIDEO */
218 0x02, /* u8 bInterfaceSubClass; SC_VIDEO_STREAMING */
219 0x00, /* u8 bInterfaceProtocol; PC_PROTOCOL_UNDEFINED */
220 0x00, /* u8 iInterface; Unused */
222 /* class-specific vs header descriptor input alternate 0 */
223 0x0E, /* u8 bLength; */
224 0x24, /* u8 bDescriptorType; CS_INTERFACE */
225 0x01, /* u8 bDescriptorSubtype; VS_INPUT_HEADER */
226 0x01, /* u8 bNumFormats; */
227 0x46, 0x00, /* u8 wTotalLength; */
228 0x82, /* u8 bEndpointAddress; */
229 0x00, /* u8 bmInfo; */
230 0x03, /* u8 bTerminalLink; */
231 0x00, /* u8 bStillCaptureMethod; */
232 0x00, /* u8 bTriggerSupport; */
233 0x00, /* u8 bTriggerUsage; */
234 0x01, /* u8 bControlSize; */
235 0x00, /* u8 bmaControls; */
237 /* class-specific vs format descriptor alternate 0 */
238 0x0B, /* u8 bLength; */
239 0x24, /* u8 bDescriptorType; CS_INTERFACE */
240 0x06, /* u8 bDescriptorSubtype; VS_FORMAT_MJPEG */
241 0x01, /* u8 bFormatIndex; */
242 0x01, /* u8 bNumFrameDescriptors; */
243 0x01, /* u8 bmFlags; */
244 0x01, /* u8 bDefaultFrameIndex; */
245 0x00, /* u8 bAspectRatioX; */
246 0x00, /* u8 bAspectRatioY; */
247 0x02, /* u8 bmInterlaceFlags; */
248 0x00, /* u8 bCopyProtect; */
250 /* class-specific vs frame descriptor alternate 0 */
251 0x26, /* u8 bLength; */
252 0x24, /* u8 bDescriptorType; CS_INTERFACE */
253 0x07, /* u8 bDescriptorSubtype; VS_FRAME_MJPEG */
254 0x01, /* u8 bFrameIndex; */
255 0x01, /* u8 bmCapabilities; */
256 0x40, 0x01, /* u8 wWidth; 320 */
257 0xF0, 0x00, /* u8 wHeight; 240 */
259 0x0D, 0x00, /* u32 dwMinBitRate; */
261 0x0D, 0x00, /* u32 dwMaxBitRate; */
263 0x00, 0x00, /* u32 dwMaxVideoFrameBufSize; */
265 0x0A, 0x00, /* u32 dwDefaultFrameInterval; */
266 0x00, /* u8 bFrameIntervalType; */
268 0x0A, 0x00, /* u32 dwMinFrameInterval; */
270 0x0A, 0x00, /* u32 dwMaxFrameInterval; */
272 0x00, 0x00, /* u32 dwFrameIntervalStep; */
274 /* standard vs isochronous video data endpoint descriptor */
275 0x07, /* u8 bLength; */
276 0x05, /* u8 bDescriptorType; */
277 0x82, /* u8 bEndpointAddress; IN endpoint 2 */
278 0x02, /* u8 bmAttributes; Isochronous transfer, asynchronous sync */
279 0x40, 0x00, /* u16 wMaxPacketSize; 510 bytes */
280 0x00 /* u8 bInterval; */
283 static void get_frame_read(void)
285 DPRINTF("Getting frame.\n");
287 frame_length
= read(v4l2_fd
, frame
, frame_max_length
);
289 if(frame_length
== -1)
291 DPRINTF("Error while reading frame.\n");
296 frame_id
= frame_id
^ 1;
297 first_bulk_packet
= 1;
298 frame_remaining_bytes
= frame_length
;
299 DPRINTF("Got a frame of %d bytes.\n", frame_length
);
305 static void usb_uvc_handle_reset(USBDevice
*dev
)
307 DPRINTF("Reset called\n");
310 static int usb_uvc_handle_control(USBDevice
*dev
, int request
, int value
,
311 int index
, int length
, uint8_t *data
)
314 USBUVCState
*s
= (USBUVCState
*)dev
;
316 DPRINTF("Control called\n");
317 // DPRINTF("Request: 0x%08X\n", request);
318 // DPRINTF("Value: 0x%08X\n", value);
319 // DPRINTF("Index: 0x%08X\n", index);
320 // DPRINTF("Length: 0x%08X\n", length);
324 case DeviceRequest
| USB_REQ_GET_STATUS
:
325 DPRINTF("USB Request: Get Status\n");
326 data
[0] = (1 << USB_DEVICE_SELF_POWERED
) |
327 (dev
->remote_wakeup
<< USB_DEVICE_REMOTE_WAKEUP
);
331 case DeviceOutRequest
| USB_REQ_CLEAR_FEATURE
:
332 DPRINTF("USB Request: Clear feature\n");
333 if (value
== USB_DEVICE_REMOTE_WAKEUP
) {
334 DPRINTF("USB Request: Unset remote wakeup\n");
335 dev
->remote_wakeup
= 0;
341 case DeviceOutRequest
| USB_REQ_SET_FEATURE
:
342 DPRINTF("USB Request: Set feature\n");
343 if (value
== USB_DEVICE_REMOTE_WAKEUP
) {
344 DPRINTF("USB Request: Set remote wakeup\n");
345 dev
->remote_wakeup
= 1;
351 case DeviceOutRequest
| USB_REQ_SET_ADDRESS
:
352 DPRINTF("USB Request: Set address to 0x%08X\n", value
);
356 case DeviceRequest
| USB_REQ_GET_DESCRIPTOR
:
357 DPRINTF("USB Request: Get descriptor\n");
360 DPRINTF("USB Request: Get device descriptor\n");
361 memcpy(data
, qemu_uvc_dev_descriptor
,
362 sizeof(qemu_uvc_dev_descriptor
));
363 ret
= sizeof(qemu_uvc_dev_descriptor
);
366 DPRINTF("USB Request: Get configuration descriptor\n");
367 memcpy(data
, qemu_uvc_config_descriptor
,
368 sizeof(qemu_uvc_config_descriptor
));
369 ret
= sizeof(qemu_uvc_config_descriptor
);
372 DPRINTF("USB Request: Get device strings\n");
373 switch(value
& 0xff) {
375 DPRINTF("USB Request: Get language IDs\n");
384 /* vendor description */
385 DPRINTF("USB Request: Get vendor string\n");
386 ret
= set_usb_string(data
, "QEMU " QEMU_VERSION
);
389 /* product description */
390 DPRINTF("USB Request: Get product string\n");
391 ret
= set_usb_string(data
, "QEMU USB VIDEO CLASS 2");
395 DPRINTF("USB Request: Get serial number string\n");
396 ret
= set_usb_string(data
, "1");
406 case DeviceRequest
| USB_REQ_GET_CONFIGURATION
:
407 DPRINTF("USB Request: Get configuration\n");
411 case DeviceOutRequest
| USB_REQ_SET_CONFIGURATION
:
412 DPRINTF("USB Request: Set configuration\n");
415 case DeviceRequest
| USB_REQ_GET_INTERFACE
:
416 DPRINTF("USB Request: Get interface\n");
420 case DeviceOutRequest
| USB_REQ_SET_INTERFACE
:
421 DPRINTF("USB Request: Set interface\n");
424 case EndpointOutRequest
| USB_REQ_CLEAR_FEATURE
:
425 DPRINTF("USB Request: Clear endpoint\n");
428 case InterfaceOutRequest
| USB_REQ_SET_INTERFACE
:
429 DPRINTF("USB Request: Set interface\n");
432 /* Class specific requests. */
433 case UVCGetVideoControl
| USB_UVC_GET_CUR
:
436 if((index
&0xFF) == 0x01 && ((value
&0xFF00) == 0x0100 || (value
&0xFF00) == 0x0200))
438 DPRINTF("USB Request: Get video control current setting attribute for interface %d\n", index
&0xFF);
439 if((value
&0xFF00) == 0x0100)
440 DPRINTF("\tVS_PROBE_CONTROL\n");
442 DPRINTF("\tVS_COMMIT_CONTROL\n");
446 DPRINTF("USB Request: Requested %d bytes, expected 26 bytes\n", length
);
450 data
[0] = 0; // bmHint
452 data
[2] = 1; // bFormatIndex
453 data
[3] = 1; // bFrameIndex
454 data
[4] = 0x2A; // dwFrameInterval
458 data
[8] = 0; // wKeyFrameRate
460 data
[10] = 0; // wPFrameRate
462 data
[12] = 0; // wCompQuality
464 data
[14] = 1; // wCompWindowSize
466 data
[16] = 0x20; // wDelay
468 data
[18] = 0x72; // dwMaxVideoFrameSize
472 data
[22] = 0x72; // dwMaxPayloadTransferSize
478 else if((index
&0xFF00) == 0x0400 && (value
&0xFF00) == 0x0100) // Setting input
480 DPRINTF("USB Request: Asking for current input\n");
483 DPRINTF("USB Request: Requested %d bytes, expected 1 byte\n", length
);
487 data
[0] = s
->current_input
;
490 else if((index
&0xFF00) == 0x0500 && (value
&0xFF00) == 0x0200) // PU_BRIGHTNESS_CONTROL of PROCESSING_UNIT
492 DPRINTF("USB Resquest: Asking for current brightness\n");
495 DPRINTF("USB Request: Requested %d bytes, expected 2 bytes\n", length
);
506 case UVCGetVideoControl
| USB_UVC_GET_MIN
:
509 if((index
&0xFF) == 0x01 && ((value
&0xFF00) == 0x0100 || (value
&0xFF00) == 0x0200))
511 DPRINTF("USB Request: Get video control minimum setting attribute for interface %d\n", index
&0xFF);
515 DPRINTF("USB Request: Requested %d bytes, expected 26 bytes\n", length
);
519 data
[0] = 0; // bmHint
521 data
[2] = 1; // bFormatIndex
522 data
[3] = 1; // bFrameIndex
523 data
[4] = 0x2A; // dwFrameInterval
527 data
[8] = 0; // wKeyFrameRate
529 data
[10] = 0; // wPFrameRate
531 data
[12] = 0; // wCompQuality
533 data
[14] = 1; // wCompWindowSize
535 data
[16] = 0x20; // wDelay
537 data
[18] = 0x72; // dwMaxVideoFrameSize
541 data
[22] = 0x72; // dwMaxPayloadTransferSize
547 else if((index
&0xFF00) == 0x0400 && (value
&0xFF00) == 0x0100) // Setting input
549 DPRINTF("USB Request: Asking for minimum input\n");
552 DPRINTF("USB Request: Requested %d bytes, expected 1 byte\n", length
);
559 else if((index
&0xFF00) == 0x0500 && (value
&0xFF00) == 0x0200) // PU_BRIGHTNESS_CONTROL of PROCESSING_UNIT
561 DPRINTF("USB Resquest: Asking for minimum brightness\n");
564 DPRINTF("USB Request: Requested %d bytes, expected 2 bytes\n", length
);
575 case UVCGetVideoControl
| USB_UVC_GET_MAX
:
576 if((index
&0xFF) == 0x01 && ((value
&0xFF00) == 0x0100 || (value
&0xFF00) == 0x0200))
578 DPRINTF("USB Request: Get video control maximum setting attribute for interface %d\n", index
&0xFF);
582 DPRINTF("USB Request: Requested %d bytes, expected 26 bytes\n", length
);
586 data
[0] = 0; // bmHint
588 data
[2] = 1; // bFormatIndex
589 data
[3] = 1; // bFrameIndex
590 data
[4] = 0x2A; // dwFrameInterval
594 data
[8] = 0; // wKeyFrameRate
596 data
[10] = 0; // wPFrameRate
598 data
[12] = 0; // wCompQuality
600 data
[14] = 1; // wCompWindowSize
602 data
[16] = 0x20; // wDelay
604 data
[18] = 0x72; // dwMaxVideoFrameSize
608 data
[22] = 0x72; // dwMaxPayloadTransferSize
614 else if((index
&0xFF00) == 0x0400 && (value
&0xFF00) == 0x0100) // Setting input
616 DPRINTF("USB Request: Asking maximum input\n");
619 DPRINTF("USB Request: Requested %d bytes, expected 1 byte\n", length
);
626 else if((index
&0xFF00) == 0x0500 && (value
&0xFF00) == 0x0200) // PU_BRIGHTNESS_CONTROL of PROCESSING_UNIT
628 DPRINTF("USB Resquest: Asking for maximum brightness\n");
631 DPRINTF("USB Request: Requested %d bytes, expected 2 bytes\n", length
);
642 case UVCGetVideoControl
| USB_UVC_GET_DEF
:
643 if((index
&0xFF) == 0x01 && ((value
&0xFF00) == 0x0100 || (value
&0xFF00) == 0x0200))
645 DPRINTF("USB Request: Get video control default setting attribute for interface %d\n", index
&0xFF);
649 DPRINTF("USB Request: Requested %d bytes, expected 26 bytes\n", length
);
653 data
[0] = 0; // bmHint
655 data
[2] = 1; // bFormatIndex
656 data
[3] = 1; // bFrameIndex
657 data
[4] = 0x2A; // dwFrameInterval
661 data
[8] = 0; // wKeyFrameRate
663 data
[10] = 0; // wPFrameRate
665 data
[12] = 0; // wCompQuality
667 data
[14] = 1; // wCompWindowSize
669 data
[16] = 0x20; // wDelay
671 data
[18] = 0x72; // dwMaxVideoFrameSize
675 data
[22] = 0x72; // dwMaxPayloadTransferSize
681 else if((index
&0xFF00) == 0x0400 && (value
&0xFF00) == 0x0100) // Setting input
683 DPRINTF("USB Request: Asking for default input\n");
686 DPRINTF("USB Request: Requested %d bytes, expected 1 byte\n", length
);
693 else if((index
&0xFF00) == 0x0500 && (value
&0xFF00) == 0x0200) // PU_BRIGHTNESS_CONTROL of PROCESSING_UNIT
695 DPRINTF("USB Resquest: Asking for default brightness\n");
698 DPRINTF("USB Request: Requested %d bytes, expected 2 bytes\n", length
);
709 case UVCSetVideoControl
| USB_UVC_SET_CUR
:
710 DPRINTF("USB Request: Set video control setting attribute for interface %d\n", index
&0xFF);
714 if((index
&0xFF) == 0x01 && ((value
&0xFF00) == 0x0100 || (value
&0xFF00) == 0x0200))
716 if((value
&0xFF00) == 0x0100)
717 DPRINTF("\tVS_PROBE_CONTROL\n");
719 DPRINTF("\tVS_COMMIT_CONTROL\n");
723 DPRINTF("USB Request: Requested %d bytes, expected 26 bytes\n", length
);
727 DPRINTF("\tbmHint = 0x%02X%02X\n", data
[1], data
[0]);
728 DPRINTF("\tbFormatIndex = %d\n", data
[2]);
729 DPRINTF("\tbFrameIndex = %d\n", data
[3]);
730 DPRINTF("\tdwFrameInterval = 0x%02X%02X%02X%02X\n", data
[7], data
[6], data
[5], data
[4]);
731 DPRINTF("\twKeyFrameRate = 0x%02X%02X\n", data
[9], data
[8]);
732 DPRINTF("\twPFrameRate = 0x%02X%02X\n", data
[11], data
[10]);
733 DPRINTF("\twCompQuality = 0x%02X%02X\n", data
[13], data
[12]);
734 DPRINTF("\twCompWindowSize = 0x%02X%02X\n", data
[15], data
[14]);
735 DPRINTF("\twDelay = 0x%02X%02X\n", data
[17], data
[16]);
736 DPRINTF("\tdwMaxVideoFrameSize= 0x%02X%02X%02X%02X\n", data
[21], data
[20], data
[19], data
[18]);
737 DPRINTF("\tdwMaxPayloadTransferSize= 0x%02X%02X%02X%02X\n", data
[25], data
[24], data
[23], data
[22]);
740 frame_remaining_bytes
= frame_length
;
741 first_bulk_packet
= 1;
745 else if((index
&0xFF00) == 0x0400 && (value
&0xFF00) == 0x0100) // Setting input
747 DPRINTF("Setting input to %d\n", data
[0]);
750 DPRINTF("USB Request: Requested %d bytes, expected 1 byte\n", length
);
754 s
->current_input
= data
[0];
757 else if((index
&0xFF00) == 0x0500 && (value
&0xFF00) == 0x0200) // PU_BRIGHTNESS_CONTROL of PROCESSING_UNIT
759 DPRINTF("USB Resquest: Setting brightness, value stays the same\n");
762 DPRINTF("USB Request: Requested %d bytes, expected 2 bytes\n", length
);
771 case UVCGetVideoControl
| USB_UVC_GET_RES
:
772 if((index
&0xFF00) == 0x0500 && (value
&0xFF00) == 0x0200) // PU_BRIGHTNESS_CONTROL of PROCESSING_UNIT
774 DPRINTF("USB Resquest: Asking for brightness resolution\n");
777 DPRINTF("USB Request: Requested %d bytes, expected 2 bytes\n", length
);
790 DPRINTF("USB Request: Unhandled control request\n");
791 DPRINTF("\tRequest: 0x%08X\n", request
);
792 DPRINTF("\tValue: 0x%08X\n", value
);
793 DPRINTF("\tIndex: 0x%08X\n", index
);
794 DPRINTF("\tLength: 0x%08X\n", length
);
802 static int usb_uvc_handle_data(USBDevice
*dev
, USBPacket
*p
)
806 //DPRINTF("Data called\n");
807 //DPRINTF("Packet ID: %d\n", p->pid);
808 //DPRINTF("Device address: %d\n", p->devaddr);
809 //DPRINTF("Device endpoint: %d\n", p->devep);
810 //DPRINTF("Data length: %d\n", p->len);
815 DPRINTF("USB Data Out requested.\n");
818 if(p
->devep
== 1) // IN endpoint 1 (hardware button)
825 else if(p
->devep
== 2) // IN endpoint 2 (video data)
827 if(first_bulk_packet
)
830 p
->data
[1] = 0x82 | frame_id
;
831 memcpy((p
->data
)+2,frame
,62);
835 frame_remaining_bytes
= frame_remaining_bytes
- 62;
837 else if(frame_remaining_bytes
<64)
839 memcpy(p
->data
,frame
,frame_remaining_bytes
);
840 ret
= frame_remaining_bytes
;
843 else if(frame_remaining_bytes
==64)
845 memcpy(p
->data
,frame
,frame_remaining_bytes
);
846 ret
= frame_remaining_bytes
;
847 frame_remaining_bytes
= 0;
849 else if(frame_remaining_bytes
==0)
856 memcpy(p
->data
,frame
,64);
858 frame_remaining_bytes
= frame_remaining_bytes
-64;
864 DPRINTF("USB Data In requested.\n");
865 DPRINTF("Requested data from endpoint %02X\n", p
->devep
);
869 DPRINTF("Bad token: %d\n", p
->pid
);
878 static void usb_uvc_handle_destroy(USBDevice
*dev
)
880 DPRINTF("Destroy called\n");
884 static int usb_uvc_initfn(USBDevice
*dev
)
886 struct v4l2_capability capabilities
;
887 struct v4l2_input video_input
;
888 struct v4l2_format v_format
;
889 int video_input_index
;
892 DPRINTF("Init called\n");
894 USBUVCState
*s
= (USBUVCState
*)dev
;
896 s
->current_input
= 0;
897 s
->dev
.speed
= USB_SPEED_FULL
;
899 if (!s
->v4l2_device
) {
900 error_report("V4L2 device specification needed.\n");
905 DPRINTF("Trying to open %s\n.", s
->v4l2_device
);
908 v4l2_fd
= open(s
->v4l2_device
, O_RDWR
);
915 error_report("Access denied.");
918 error_report("Device busy.");
921 error_report("Device does not exist.");
924 error_report("Not enough memory to open device.");
927 error_report("Process reached maximum files opened.");
930 error_report("System reached maximum files opened.");
933 error_report("Unknown error %d opening device.", errno
);
940 DPRINTF("Device opened correctly.\n");
942 DPRINTF("Querying capabilities.\n");
944 ret_err
= ioctl(v4l2_fd
, VIDIOC_QUERYCAP
, &capabilities
);
951 error_report("Device is not V4L2 device.\n");
954 error_report("Device returned unknown error %d.\n", errno
);
961 DPRINTF("Device driver: %s\n", capabilities
.driver
);
962 DPRINTF("Device name: %s\n", capabilities
.card
);
963 DPRINTF("Device bus: %s\n", capabilities
.bus_info
);
964 DPRINTF("Driver version: %u.%u.%u\n",(capabilities
.version
>> 16) & 0xFF,(capabilities
.version
>> 8) & 0xFF, capabilities
.version
& 0xFF);
965 DPRINTF("Device capabilities: 0x%08X\n", capabilities
.capabilities
);
967 DPRINTF("Enumerating video inputs.\n");
968 memset(&video_input
, 0, sizeof(video_input
));
970 while((ioctl(v4l2_fd
, VIDIOC_ENUMINPUT
, &video_input
)==0))
972 if(video_input
.type
== V4L2_INPUT_TYPE_CAMERA
)
974 video_input_index
= video_input
.index
;
981 DPRINTF("Setting video input to index %d\n", video_input_index
);
982 ret_err
= ioctl(v4l2_fd
, VIDIOC_S_INPUT
, &video_input_index
);
989 error_report("Incorrect video input selected.\n");
992 error_report("Input cannot be switched.\n");
995 error_report("Unknown error %d.\n", errno
);
1002 ioctl(v4l2_fd
, VIDIOC_G_INPUT
, &ret_err
);
1004 if(ret_err
==video_input_index
)
1005 DPRINTF("Video input correctly set.\n");
1008 error_report("Some error happened while setting video input.\n");
1012 DPRINTF("Trying to set 320x240 MJPEG.\n");
1013 memset(&v_format
, 0, sizeof(v_format
));
1014 v_format
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
1015 v_format
.fmt
.pix
.width
= 320;
1016 v_format
.fmt
.pix
.height
= 240;
1017 v_format
.fmt
.pix
.pixelformat
= V4L2_PIX_FMT_MJPEG
;
1018 v_format
.fmt
.pix
.field
= V4L2_FIELD_INTERLACED
;
1020 ret_err
= ioctl (v4l2_fd
, VIDIOC_S_FMT
, &v_format
);
1027 error_report("Device busy while changing format.\n");
1030 error_report("Invalid format.\n");
1033 error_report("Unknown error %d while changing format.\n", errno
);
1040 frame_max_length
= v_format
.fmt
.pix
.sizeimage
;
1042 DPRINTF("Format correctly set.\n");
1043 DPRINTF("Maximum image size: %d bytes.\n", frame_max_length
);
1045 DPRINTF("Allocating memory for frames.\n");
1046 frame
= malloc(frame_max_length
);
1047 frame_start
= frame
;
1056 static USBDevice
*usb_uvc_init(const char *filename
)
1060 dev
= usb_create(NULL
/* FIXME */, "usb-uvc-webcam");
1061 qdev_init_nofail(&dev
->qdev
);
1063 DPRINTF("Filename: %s\n.", filename
);
1066 error_report("character device specification needed");
1073 static struct USBDeviceInfo usb_uvc_info
= {
1074 .product_desc
= "QEMU USB Video Class Device",
1075 .qdev
.name
= "usb-uvc-webcam",
1076 .qdev
.desc
= "QEMU USB Video Class Device",
1077 .usbdevice_name
= "uvc-webcam",
1078 .usbdevice_init
= usb_uvc_init
,
1079 .qdev
.size
= sizeof(USBUVCState
),
1080 .init
= usb_uvc_initfn
,
1081 .handle_packet
= usb_generic_handle_packet
,
1082 .handle_reset
= usb_uvc_handle_reset
,
1083 .handle_control
= usb_uvc_handle_control
,
1084 .handle_data
= usb_uvc_handle_data
,
1085 .handle_destroy
= usb_uvc_handle_destroy
,
1086 .qdev
.props
= (Property
[]) {
1087 DEFINE_PROP_STRING("device", USBUVCState
, v4l2_device
),
1088 DEFINE_PROP_END_OF_LIST(),
1092 static void usb_uvc_register_devices(void)
1094 usb_qdev_register(&usb_uvc_info
);
1096 device_init(usb_uvc_register_devices
)