Skip to content

Commit fd03af2

Browse files
michaelolbrichgregkh
authored andcommitted
usb: gadget: uvc: implement dwPresentationTime and scrSourceClock
This patch adds the fields UVC_STREAM_PTS and UVC_STREAM_SCR to the uvc header, in case this data is available. It also enables the copy of the timestamp to the vb2_v4l2_buffer by setting V4L2_BUF_FLAG_TIMESTAMP_COPY in the queue.timestamp_flags. Signed-off-by: Michael Olbrich <[email protected]> Signed-off-by: Michael Grzeschik <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent f262ce6 commit fd03af2

File tree

3 files changed

+34
-5
lines changed

3 files changed

+34
-5
lines changed

drivers/usb/gadget/function/uvc.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ extern unsigned int uvc_gadget_trace_param;
6868
#define UVC_MAX_REQUEST_SIZE 64
6969
#define UVC_MAX_EVENTS 4
7070

71-
#define UVCG_REQUEST_HEADER_LEN 2
71+
#define UVCG_REQUEST_HEADER_LEN 12
7272

7373
/* ------------------------------------------------------------------------
7474
* Structures

drivers/usb/gadget/function/uvc_queue.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ int uvcg_queue_init(struct uvc_video_queue *queue, struct device *dev, enum v4l2
142142
queue->queue.mem_ops = &vb2_vmalloc_memops;
143143
}
144144

145-
queue->queue.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC
145+
queue->queue.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY
146146
| V4L2_BUF_FLAG_TSTAMP_SRC_EOF;
147147
queue->queue.dev = dev;
148148

drivers/usb/gadget/function/uvc_video.c

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <linux/usb/ch9.h>
1313
#include <linux/usb/gadget.h>
1414
#include <linux/usb/video.h>
15+
#include <asm/unaligned.h>
1516

1617
#include <media/v4l2-dev.h>
1718

@@ -27,13 +28,41 @@ static int
2728
uvc_video_encode_header(struct uvc_video *video, struct uvc_buffer *buf,
2829
u8 *data, int len)
2930
{
30-
data[0] = UVCG_REQUEST_HEADER_LEN;
31+
struct uvc_device *uvc = container_of(video, struct uvc_device, video);
32+
struct usb_composite_dev *cdev = uvc->func.config->cdev;
33+
struct timespec64 ts = ns_to_timespec64(buf->buf.vb2_buf.timestamp);
34+
int pos = 2;
35+
3136
data[1] = UVC_STREAM_EOH | video->fid;
3237

33-
if (buf->bytesused - video->queue.buf_used <= len - UVCG_REQUEST_HEADER_LEN)
38+
if (video->queue.buf_used == 0 && ts.tv_sec) {
39+
/* dwClockFrequency is 48 MHz */
40+
u32 pts = ((u64)ts.tv_sec * USEC_PER_SEC + ts.tv_nsec / NSEC_PER_USEC) * 48;
41+
42+
data[1] |= UVC_STREAM_PTS;
43+
put_unaligned_le32(pts, &data[pos]);
44+
pos += 4;
45+
}
46+
47+
if (cdev->gadget->ops->get_frame) {
48+
u32 sof, stc;
49+
50+
sof = usb_gadget_frame_number(cdev->gadget);
51+
ktime_get_ts64(&ts);
52+
stc = ((u64)ts.tv_sec * USEC_PER_SEC + ts.tv_nsec / NSEC_PER_USEC) * 48;
53+
54+
data[1] |= UVC_STREAM_SCR;
55+
put_unaligned_le32(stc, &data[pos]);
56+
put_unaligned_le16(sof, &data[pos+4]);
57+
pos += 6;
58+
}
59+
60+
data[0] = pos;
61+
62+
if (buf->bytesused - video->queue.buf_used <= len - pos)
3463
data[1] |= UVC_STREAM_EOF;
3564

36-
return UVCG_REQUEST_HEADER_LEN;
65+
return pos;
3766
}
3867

3968
static int

0 commit comments

Comments
 (0)