diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/media/video/videobuf2-core.c | 399 |
1 files changed, 399 insertions, 0 deletions
diff --git a/drivers/media/video/videobuf2-core.c b/drivers/media/video/videobuf2-core.c index b856bd105d77..73f3b220b34a 100644 --- a/drivers/media/video/videobuf2-core.c +++ b/drivers/media/video/videobuf2-core.c | |||
@@ -453,6 +453,11 @@ int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req) | |||
453 | unsigned long plane_sizes[VIDEO_MAX_PLANES]; | 453 | unsigned long plane_sizes[VIDEO_MAX_PLANES]; |
454 | int ret = 0; | 454 | int ret = 0; |
455 | 455 | ||
456 | if (q->fileio) { | ||
457 | dprintk(1, "reqbufs: file io in progress\n"); | ||
458 | return -EBUSY; | ||
459 | } | ||
460 | |||
456 | if (req->memory != V4L2_MEMORY_MMAP | 461 | if (req->memory != V4L2_MEMORY_MMAP |
457 | && req->memory != V4L2_MEMORY_USERPTR) { | 462 | && req->memory != V4L2_MEMORY_USERPTR) { |
458 | dprintk(1, "reqbufs: unsupported memory type\n"); | 463 | dprintk(1, "reqbufs: unsupported memory type\n"); |
@@ -824,6 +829,11 @@ int vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b) | |||
824 | struct vb2_buffer *vb; | 829 | struct vb2_buffer *vb; |
825 | int ret = 0; | 830 | int ret = 0; |
826 | 831 | ||
832 | if (q->fileio) { | ||
833 | dprintk(1, "qbuf: file io in progress\n"); | ||
834 | return -EBUSY; | ||
835 | } | ||
836 | |||
827 | if (b->type != q->type) { | 837 | if (b->type != q->type) { |
828 | dprintk(1, "qbuf: invalid buffer type\n"); | 838 | dprintk(1, "qbuf: invalid buffer type\n"); |
829 | return -EINVAL; | 839 | return -EINVAL; |
@@ -1028,6 +1038,11 @@ int vb2_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool nonblocking) | |||
1028 | struct vb2_buffer *vb = NULL; | 1038 | struct vb2_buffer *vb = NULL; |
1029 | int ret; | 1039 | int ret; |
1030 | 1040 | ||
1041 | if (q->fileio) { | ||
1042 | dprintk(1, "dqbuf: file io in progress\n"); | ||
1043 | return -EBUSY; | ||
1044 | } | ||
1045 | |||
1031 | if (b->type != q->type) { | 1046 | if (b->type != q->type) { |
1032 | dprintk(1, "dqbuf: invalid buffer type\n"); | 1047 | dprintk(1, "dqbuf: invalid buffer type\n"); |
1033 | return -EINVAL; | 1048 | return -EINVAL; |
@@ -1087,6 +1102,11 @@ int vb2_streamon(struct vb2_queue *q, enum v4l2_buf_type type) | |||
1087 | { | 1102 | { |
1088 | struct vb2_buffer *vb; | 1103 | struct vb2_buffer *vb; |
1089 | 1104 | ||
1105 | if (q->fileio) { | ||
1106 | dprintk(1, "streamon: file io in progress\n"); | ||
1107 | return -EBUSY; | ||
1108 | } | ||
1109 | |||
1090 | if (type != q->type) { | 1110 | if (type != q->type) { |
1091 | dprintk(1, "streamon: invalid stream type\n"); | 1111 | dprintk(1, "streamon: invalid stream type\n"); |
1092 | return -EINVAL; | 1112 | return -EINVAL; |
@@ -1180,6 +1200,11 @@ static void __vb2_queue_cancel(struct vb2_queue *q) | |||
1180 | */ | 1200 | */ |
1181 | int vb2_streamoff(struct vb2_queue *q, enum v4l2_buf_type type) | 1201 | int vb2_streamoff(struct vb2_queue *q, enum v4l2_buf_type type) |
1182 | { | 1202 | { |
1203 | if (q->fileio) { | ||
1204 | dprintk(1, "streamoff: file io in progress\n"); | ||
1205 | return -EBUSY; | ||
1206 | } | ||
1207 | |||
1183 | if (type != q->type) { | 1208 | if (type != q->type) { |
1184 | dprintk(1, "streamoff: invalid stream type\n"); | 1209 | dprintk(1, "streamoff: invalid stream type\n"); |
1185 | return -EINVAL; | 1210 | return -EINVAL; |
@@ -1303,6 +1328,8 @@ int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma) | |||
1303 | } | 1328 | } |
1304 | EXPORT_SYMBOL_GPL(vb2_mmap); | 1329 | EXPORT_SYMBOL_GPL(vb2_mmap); |
1305 | 1330 | ||
1331 | static int __vb2_init_fileio(struct vb2_queue *q, int read); | ||
1332 | static int __vb2_cleanup_fileio(struct vb2_queue *q); | ||
1306 | 1333 | ||
1307 | /** | 1334 | /** |
1308 | * vb2_poll() - implements poll userspace operation | 1335 | * vb2_poll() - implements poll userspace operation |
@@ -1323,9 +1350,30 @@ EXPORT_SYMBOL_GPL(vb2_mmap); | |||
1323 | unsigned int vb2_poll(struct vb2_queue *q, struct file *file, poll_table *wait) | 1350 | unsigned int vb2_poll(struct vb2_queue *q, struct file *file, poll_table *wait) |
1324 | { | 1351 | { |
1325 | unsigned long flags; | 1352 | unsigned long flags; |
1353 | unsigned int ret; | ||
1326 | struct vb2_buffer *vb = NULL; | 1354 | struct vb2_buffer *vb = NULL; |
1327 | 1355 | ||
1328 | /* | 1356 | /* |
1357 | * Start file io emulator if streaming api has not been used yet. | ||
1358 | */ | ||
1359 | if (q->num_buffers == 0 && q->fileio == NULL) { | ||
1360 | if (!V4L2_TYPE_IS_OUTPUT(q->type) && (q->io_modes & VB2_READ)) { | ||
1361 | ret = __vb2_init_fileio(q, 1); | ||
1362 | if (ret) | ||
1363 | return ret; | ||
1364 | } | ||
1365 | if (V4L2_TYPE_IS_OUTPUT(q->type) && (q->io_modes & VB2_WRITE)) { | ||
1366 | ret = __vb2_init_fileio(q, 0); | ||
1367 | if (ret) | ||
1368 | return ret; | ||
1369 | /* | ||
1370 | * Write to OUTPUT queue can be done immediately. | ||
1371 | */ | ||
1372 | return POLLOUT | POLLWRNORM; | ||
1373 | } | ||
1374 | } | ||
1375 | |||
1376 | /* | ||
1329 | * There is nothing to wait for if no buffers have already been queued. | 1377 | * There is nothing to wait for if no buffers have already been queued. |
1330 | */ | 1378 | */ |
1331 | if (list_empty(&q->queued_list)) | 1379 | if (list_empty(&q->queued_list)) |
@@ -1395,11 +1443,362 @@ EXPORT_SYMBOL_GPL(vb2_queue_init); | |||
1395 | */ | 1443 | */ |
1396 | void vb2_queue_release(struct vb2_queue *q) | 1444 | void vb2_queue_release(struct vb2_queue *q) |
1397 | { | 1445 | { |
1446 | __vb2_cleanup_fileio(q); | ||
1398 | __vb2_queue_cancel(q); | 1447 | __vb2_queue_cancel(q); |
1399 | __vb2_queue_free(q); | 1448 | __vb2_queue_free(q); |
1400 | } | 1449 | } |
1401 | EXPORT_SYMBOL_GPL(vb2_queue_release); | 1450 | EXPORT_SYMBOL_GPL(vb2_queue_release); |
1402 | 1451 | ||
1452 | /** | ||
1453 | * struct vb2_fileio_buf - buffer context used by file io emulator | ||
1454 | * | ||
1455 | * vb2 provides a compatibility layer and emulator of file io (read and | ||
1456 | * write) calls on top of streaming API. This structure is used for | ||
1457 | * tracking context related to the buffers. | ||
1458 | */ | ||
1459 | struct vb2_fileio_buf { | ||
1460 | void *vaddr; | ||
1461 | unsigned int size; | ||
1462 | unsigned int pos; | ||
1463 | unsigned int queued:1; | ||
1464 | }; | ||
1465 | |||
1466 | /** | ||
1467 | * struct vb2_fileio_data - queue context used by file io emulator | ||
1468 | * | ||
1469 | * vb2 provides a compatibility layer and emulator of file io (read and | ||
1470 | * write) calls on top of streaming API. For proper operation it required | ||
1471 | * this structure to save the driver state between each call of the read | ||
1472 | * or write function. | ||
1473 | */ | ||
1474 | struct vb2_fileio_data { | ||
1475 | struct v4l2_requestbuffers req; | ||
1476 | struct v4l2_buffer b; | ||
1477 | struct vb2_fileio_buf bufs[VIDEO_MAX_FRAME]; | ||
1478 | unsigned int index; | ||
1479 | unsigned int q_count; | ||
1480 | unsigned int dq_count; | ||
1481 | unsigned int flags; | ||
1482 | }; | ||
1483 | |||
1484 | /** | ||
1485 | * __vb2_init_fileio() - initialize file io emulator | ||
1486 | * @q: videobuf2 queue | ||
1487 | * @read: mode selector (1 means read, 0 means write) | ||
1488 | */ | ||
1489 | static int __vb2_init_fileio(struct vb2_queue *q, int read) | ||
1490 | { | ||
1491 | struct vb2_fileio_data *fileio; | ||
1492 | int i, ret; | ||
1493 | unsigned int count = 0; | ||
1494 | |||
1495 | /* | ||
1496 | * Sanity check | ||
1497 | */ | ||
1498 | if ((read && !(q->io_modes & VB2_READ)) || | ||
1499 | (!read && !(q->io_modes & VB2_WRITE))) | ||
1500 | BUG(); | ||
1501 | |||
1502 | /* | ||
1503 | * Check if device supports mapping buffers to kernel virtual space. | ||
1504 | */ | ||
1505 | if (!q->mem_ops->vaddr) | ||
1506 | return -EBUSY; | ||
1507 | |||
1508 | /* | ||
1509 | * Check if streaming api has not been already activated. | ||
1510 | */ | ||
1511 | if (q->streaming || q->num_buffers > 0) | ||
1512 | return -EBUSY; | ||
1513 | |||
1514 | /* | ||
1515 | * Start with count 1, driver can increase it in queue_setup() | ||
1516 | */ | ||
1517 | count = 1; | ||
1518 | |||
1519 | dprintk(3, "setting up file io: mode %s, count %d, flags %08x\n", | ||
1520 | (read) ? "read" : "write", count, q->io_flags); | ||
1521 | |||
1522 | fileio = kzalloc(sizeof(struct vb2_fileio_data), GFP_KERNEL); | ||
1523 | if (fileio == NULL) | ||
1524 | return -ENOMEM; | ||
1525 | |||
1526 | fileio->flags = q->io_flags; | ||
1527 | |||
1528 | /* | ||
1529 | * Request buffers and use MMAP type to force driver | ||
1530 | * to allocate buffers by itself. | ||
1531 | */ | ||
1532 | fileio->req.count = count; | ||
1533 | fileio->req.memory = V4L2_MEMORY_MMAP; | ||
1534 | fileio->req.type = q->type; | ||
1535 | ret = vb2_reqbufs(q, &fileio->req); | ||
1536 | if (ret) | ||
1537 | goto err_kfree; | ||
1538 | |||
1539 | /* | ||
1540 | * Check if plane_count is correct | ||
1541 | * (multiplane buffers are not supported). | ||
1542 | */ | ||
1543 | if (q->bufs[0]->num_planes != 1) { | ||
1544 | fileio->req.count = 0; | ||
1545 | ret = -EBUSY; | ||
1546 | goto err_reqbufs; | ||
1547 | } | ||
1548 | |||
1549 | /* | ||
1550 | * Get kernel address of each buffer. | ||
1551 | */ | ||
1552 | for (i = 0; i < q->num_buffers; i++) { | ||
1553 | fileio->bufs[i].vaddr = vb2_plane_vaddr(q->bufs[i], 0); | ||
1554 | if (fileio->bufs[i].vaddr == NULL) | ||
1555 | goto err_reqbufs; | ||
1556 | fileio->bufs[i].size = vb2_plane_size(q->bufs[i], 0); | ||
1557 | } | ||
1558 | |||
1559 | /* | ||
1560 | * Read mode requires pre queuing of all buffers. | ||
1561 | */ | ||
1562 | if (read) { | ||
1563 | /* | ||
1564 | * Queue all buffers. | ||
1565 | */ | ||
1566 | for (i = 0; i < q->num_buffers; i++) { | ||
1567 | struct v4l2_buffer *b = &fileio->b; | ||
1568 | memset(b, 0, sizeof(*b)); | ||
1569 | b->type = q->type; | ||
1570 | b->memory = q->memory; | ||
1571 | b->index = i; | ||
1572 | ret = vb2_qbuf(q, b); | ||
1573 | if (ret) | ||
1574 | goto err_reqbufs; | ||
1575 | fileio->bufs[i].queued = 1; | ||
1576 | } | ||
1577 | |||
1578 | /* | ||
1579 | * Start streaming. | ||
1580 | */ | ||
1581 | ret = vb2_streamon(q, q->type); | ||
1582 | if (ret) | ||
1583 | goto err_reqbufs; | ||
1584 | } | ||
1585 | |||
1586 | q->fileio = fileio; | ||
1587 | |||
1588 | return ret; | ||
1589 | |||
1590 | err_reqbufs: | ||
1591 | vb2_reqbufs(q, &fileio->req); | ||
1592 | |||
1593 | err_kfree: | ||
1594 | kfree(fileio); | ||
1595 | return ret; | ||
1596 | } | ||
1597 | |||
1598 | /** | ||
1599 | * __vb2_cleanup_fileio() - free resourced used by file io emulator | ||
1600 | * @q: videobuf2 queue | ||
1601 | */ | ||
1602 | static int __vb2_cleanup_fileio(struct vb2_queue *q) | ||
1603 | { | ||
1604 | struct vb2_fileio_data *fileio = q->fileio; | ||
1605 | |||
1606 | if (fileio) { | ||
1607 | /* | ||
1608 | * Hack fileio context to enable direct calls to vb2 ioctl | ||
1609 | * interface. | ||
1610 | */ | ||
1611 | q->fileio = NULL; | ||
1612 | |||
1613 | vb2_streamoff(q, q->type); | ||
1614 | fileio->req.count = 0; | ||
1615 | vb2_reqbufs(q, &fileio->req); | ||
1616 | kfree(fileio); | ||
1617 | dprintk(3, "file io emulator closed\n"); | ||
1618 | } | ||
1619 | return 0; | ||
1620 | } | ||
1621 | |||
1622 | /** | ||
1623 | * __vb2_perform_fileio() - perform a single file io (read or write) operation | ||
1624 | * @q: videobuf2 queue | ||
1625 | * @data: pointed to target userspace buffer | ||
1626 | * @count: number of bytes to read or write | ||
1627 | * @ppos: file handle position tracking pointer | ||
1628 | * @nonblock: mode selector (1 means blocking calls, 0 means nonblocking) | ||
1629 | * @read: access mode selector (1 means read, 0 means write) | ||
1630 | */ | ||
1631 | static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_t count, | ||
1632 | loff_t *ppos, int nonblock, int read) | ||
1633 | { | ||
1634 | struct vb2_fileio_data *fileio; | ||
1635 | struct vb2_fileio_buf *buf; | ||
1636 | int ret, index; | ||
1637 | |||
1638 | dprintk(3, "file io: mode %s, offset %ld, count %ld, %sblocking\n", | ||
1639 | read ? "read" : "write", (long)*ppos, count, | ||
1640 | nonblock ? "non" : ""); | ||
1641 | |||
1642 | if (!data) | ||
1643 | return -EINVAL; | ||
1644 | |||
1645 | /* | ||
1646 | * Initialize emulator on first call. | ||
1647 | */ | ||
1648 | if (!q->fileio) { | ||
1649 | ret = __vb2_init_fileio(q, read); | ||
1650 | dprintk(3, "file io: vb2_init_fileio result: %d\n", ret); | ||
1651 | if (ret) | ||
1652 | return ret; | ||
1653 | } | ||
1654 | fileio = q->fileio; | ||
1655 | |||
1656 | /* | ||
1657 | * Hack fileio context to enable direct calls to vb2 ioctl interface. | ||
1658 | * The pointer will be restored before returning from this function. | ||
1659 | */ | ||
1660 | q->fileio = NULL; | ||
1661 | |||
1662 | index = fileio->index; | ||
1663 | buf = &fileio->bufs[index]; | ||
1664 | |||
1665 | /* | ||
1666 | * Check if we need to dequeue the buffer. | ||
1667 | */ | ||
1668 | if (buf->queued) { | ||
1669 | struct vb2_buffer *vb; | ||
1670 | |||
1671 | /* | ||
1672 | * Call vb2_dqbuf to get buffer back. | ||
1673 | */ | ||
1674 | memset(&fileio->b, 0, sizeof(fileio->b)); | ||
1675 | fileio->b.type = q->type; | ||
1676 | fileio->b.memory = q->memory; | ||
1677 | fileio->b.index = index; | ||
1678 | ret = vb2_dqbuf(q, &fileio->b, nonblock); | ||
1679 | dprintk(5, "file io: vb2_dqbuf result: %d\n", ret); | ||
1680 | if (ret) | ||
1681 | goto end; | ||
1682 | fileio->dq_count += 1; | ||
1683 | |||
1684 | /* | ||
1685 | * Get number of bytes filled by the driver | ||
1686 | */ | ||
1687 | vb = q->bufs[index]; | ||
1688 | buf->size = vb2_get_plane_payload(vb, 0); | ||
1689 | buf->queued = 0; | ||
1690 | } | ||
1691 | |||
1692 | /* | ||
1693 | * Limit count on last few bytes of the buffer. | ||
1694 | */ | ||
1695 | if (buf->pos + count > buf->size) { | ||
1696 | count = buf->size - buf->pos; | ||
1697 | dprintk(5, "reducing read count: %ld\n", count); | ||
1698 | } | ||
1699 | |||
1700 | /* | ||
1701 | * Transfer data to userspace. | ||
1702 | */ | ||
1703 | dprintk(3, "file io: copying %ld bytes - buffer %d, offset %u\n", | ||
1704 | count, index, buf->pos); | ||
1705 | if (read) | ||
1706 | ret = copy_to_user(data, buf->vaddr + buf->pos, count); | ||
1707 | else | ||
1708 | ret = copy_from_user(buf->vaddr + buf->pos, data, count); | ||
1709 | if (ret) { | ||
1710 | dprintk(3, "file io: error copying data\n"); | ||
1711 | ret = -EFAULT; | ||
1712 | goto end; | ||
1713 | } | ||
1714 | |||
1715 | /* | ||
1716 | * Update counters. | ||
1717 | */ | ||
1718 | buf->pos += count; | ||
1719 | *ppos += count; | ||
1720 | |||
1721 | /* | ||
1722 | * Queue next buffer if required. | ||
1723 | */ | ||
1724 | if (buf->pos == buf->size || | ||
1725 | (!read && (fileio->flags & VB2_FILEIO_WRITE_IMMEDIATELY))) { | ||
1726 | /* | ||
1727 | * Check if this is the last buffer to read. | ||
1728 | */ | ||
1729 | if (read && (fileio->flags & VB2_FILEIO_READ_ONCE) && | ||
1730 | fileio->dq_count == 1) { | ||
1731 | dprintk(3, "file io: read limit reached\n"); | ||
1732 | /* | ||
1733 | * Restore fileio pointer and release the context. | ||
1734 | */ | ||
1735 | q->fileio = fileio; | ||
1736 | return __vb2_cleanup_fileio(q); | ||
1737 | } | ||
1738 | |||
1739 | /* | ||
1740 | * Call vb2_qbuf and give buffer to the driver. | ||
1741 | */ | ||
1742 | memset(&fileio->b, 0, sizeof(fileio->b)); | ||
1743 | fileio->b.type = q->type; | ||
1744 | fileio->b.memory = q->memory; | ||
1745 | fileio->b.index = index; | ||
1746 | fileio->b.bytesused = buf->pos; | ||
1747 | ret = vb2_qbuf(q, &fileio->b); | ||
1748 | dprintk(5, "file io: vb2_dbuf result: %d\n", ret); | ||
1749 | if (ret) | ||
1750 | goto end; | ||
1751 | |||
1752 | /* | ||
1753 | * Buffer has been queued, update the status | ||
1754 | */ | ||
1755 | buf->pos = 0; | ||
1756 | buf->queued = 1; | ||
1757 | buf->size = q->bufs[0]->v4l2_planes[0].length; | ||
1758 | fileio->q_count += 1; | ||
1759 | |||
1760 | /* | ||
1761 | * Switch to the next buffer | ||
1762 | */ | ||
1763 | fileio->index = (index + 1) % q->num_buffers; | ||
1764 | |||
1765 | /* | ||
1766 | * Start streaming if required. | ||
1767 | */ | ||
1768 | if (!read && !q->streaming) { | ||
1769 | ret = vb2_streamon(q, q->type); | ||
1770 | if (ret) | ||
1771 | goto end; | ||
1772 | } | ||
1773 | } | ||
1774 | |||
1775 | /* | ||
1776 | * Return proper number of bytes processed. | ||
1777 | */ | ||
1778 | if (ret == 0) | ||
1779 | ret = count; | ||
1780 | end: | ||
1781 | /* | ||
1782 | * Restore the fileio context and block vb2 ioctl interface. | ||
1783 | */ | ||
1784 | q->fileio = fileio; | ||
1785 | return ret; | ||
1786 | } | ||
1787 | |||
1788 | size_t vb2_read(struct vb2_queue *q, char __user *data, size_t count, | ||
1789 | loff_t *ppos, int nonblocking) | ||
1790 | { | ||
1791 | return __vb2_perform_fileio(q, data, count, ppos, nonblocking, 1); | ||
1792 | } | ||
1793 | EXPORT_SYMBOL_GPL(vb2_read); | ||
1794 | |||
1795 | size_t vb2_write(struct vb2_queue *q, char __user *data, size_t count, | ||
1796 | loff_t *ppos, int nonblocking) | ||
1797 | { | ||
1798 | return __vb2_perform_fileio(q, data, count, ppos, nonblocking, 0); | ||
1799 | } | ||
1800 | EXPORT_SYMBOL_GPL(vb2_write); | ||
1801 | |||
1403 | MODULE_DESCRIPTION("Driver helper framework for Video for Linux 2"); | 1802 | MODULE_DESCRIPTION("Driver helper framework for Video for Linux 2"); |
1404 | MODULE_AUTHOR("Pawel Osciak, Marek Szyprowski"); | 1803 | MODULE_AUTHOR("Pawel Osciak, Marek Szyprowski"); |
1405 | MODULE_LICENSE("GPL"); | 1804 | MODULE_LICENSE("GPL"); |