Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[media] dvb-frontend: split set_delivery_system()

This function is complex, and has different workflows, one for
DVBv3 calls, and another one for DVBv5 calls. Break it into 3
functions, in order to make easier to understand what each
block does.
No functional changes so far. A few comments got improved.

Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>

+165 -129
+165 -129
drivers/media/dvb-core/dvb_frontend.c
··· 1509 1509 return status; 1510 1510 } 1511 1511 1512 - static int set_delivery_system(struct dvb_frontend *fe, u32 desired_system) 1512 + static int emulate_delivery_system(struct dvb_frontend *fe, 1513 + enum dvbv3_emulation_type type, 1514 + u32 delsys, u32 desired_system) 1513 1515 { 1514 - int ncaps, i; 1515 - u32 delsys = SYS_UNDEFINED; 1516 + int i; 1516 1517 struct dtv_frontend_properties *c = &fe->dtv_property_cache; 1517 - enum dvbv3_emulation_type type; 1518 - 1519 - /* 1520 - * It was reported that some old DVBv5 applications were 1521 - * filling delivery_system with SYS_UNDEFINED. If this happens, 1522 - * assume that the application wants to use the first supported 1523 - * delivery system. 1524 - */ 1525 - if (c->delivery_system == SYS_UNDEFINED) 1526 - c->delivery_system = fe->ops.delsys[0]; 1527 - 1528 - if (desired_system == SYS_UNDEFINED) { 1529 - /* 1530 - * A DVBv3 call doesn't know what's the desired system. 1531 - * Also, DVBv3 applications don't know that ops.info->type 1532 - * could be changed, and they simply dies when it doesn't 1533 - * match. 1534 - * So, don't change the current delivery system, as it 1535 - * may be trying to do the wrong thing, like setting an 1536 - * ISDB-T frontend as DVB-T. Instead, find the closest 1537 - * DVBv3 system that matches the delivery system. 1538 - */ 1539 - if (is_dvbv3_delsys(c->delivery_system)) { 1540 - dev_dbg(fe->dvb->device, 1541 - "%s: Using delivery system to %d\n", 1542 - __func__, c->delivery_system); 1543 - return 0; 1544 - } 1545 - type = dvbv3_type(c->delivery_system); 1546 - switch (type) { 1547 - case DVBV3_QPSK: 1548 - desired_system = SYS_DVBS; 1549 - break; 1550 - case DVBV3_QAM: 1551 - desired_system = SYS_DVBC_ANNEX_A; 1552 - break; 1553 - case DVBV3_ATSC: 1554 - desired_system = SYS_ATSC; 1555 - break; 1556 - case DVBV3_OFDM: 1557 - desired_system = SYS_DVBT; 1558 - break; 1559 - default: 1560 - dev_dbg(fe->dvb->device, "%s: This frontend doesn't support DVBv3 calls\n", 1561 - __func__); 1562 - return -EINVAL; 1563 - } 1564 - /* 1565 - * Get a delivery system that is compatible with DVBv3 1566 - * NOTE: in order for this to work with softwares like Kaffeine that 1567 - * uses a DVBv5 call for DVB-S2 and a DVBv3 call to go back to 1568 - * DVB-S, drivers that support both should put the SYS_DVBS entry 1569 - * before the SYS_DVBS2, otherwise it won't switch back to DVB-S. 1570 - * The real fix is that userspace applications should not use DVBv3 1571 - * and not trust on calling FE_SET_FRONTEND to switch the delivery 1572 - * system. 1573 - */ 1574 - ncaps = 0; 1575 - while (fe->ops.delsys[ncaps] && ncaps < MAX_DELSYS) { 1576 - if (fe->ops.delsys[ncaps] == desired_system) { 1577 - delsys = desired_system; 1578 - break; 1579 - } 1580 - ncaps++; 1581 - } 1582 - if (delsys == SYS_UNDEFINED) { 1583 - dev_dbg(fe->dvb->device, "%s: Couldn't find a delivery system that matches %d\n", 1584 - __func__, desired_system); 1585 - } 1586 - } else { 1587 - /* 1588 - * This is a DVBv5 call. So, it likely knows the supported 1589 - * delivery systems. 1590 - */ 1591 - 1592 - /* Check if the desired delivery system is supported */ 1593 - ncaps = 0; 1594 - while (fe->ops.delsys[ncaps] && ncaps < MAX_DELSYS) { 1595 - if (fe->ops.delsys[ncaps] == desired_system) { 1596 - c->delivery_system = desired_system; 1597 - dev_dbg(fe->dvb->device, 1598 - "%s: Changing delivery system to %d\n", 1599 - __func__, desired_system); 1600 - return 0; 1601 - } 1602 - ncaps++; 1603 - } 1604 - type = dvbv3_type(desired_system); 1605 - 1606 - /* 1607 - * The delivery system is not supported. See if it can be 1608 - * emulated. 1609 - * The emulation only works if the desired system is one of the 1610 - * DVBv3 delivery systems 1611 - */ 1612 - if (!is_dvbv3_delsys(desired_system)) { 1613 - dev_dbg(fe->dvb->device, 1614 - "%s: can't use a DVBv3 FE_SET_FRONTEND call on this frontend\n", 1615 - __func__); 1616 - return -EINVAL; 1617 - } 1618 - 1619 - /* 1620 - * Get the last non-DVBv3 delivery system that has the same type 1621 - * of the desired system 1622 - */ 1623 - ncaps = 0; 1624 - while (fe->ops.delsys[ncaps] && ncaps < MAX_DELSYS) { 1625 - if ((dvbv3_type(fe->ops.delsys[ncaps]) == type) && 1626 - !is_dvbv3_delsys(fe->ops.delsys[ncaps])) 1627 - delsys = fe->ops.delsys[ncaps]; 1628 - ncaps++; 1629 - } 1630 - /* There's nothing compatible with the desired delivery system */ 1631 - if (delsys == SYS_UNDEFINED) { 1632 - dev_dbg(fe->dvb->device, 1633 - "%s: Incompatible DVBv3 FE_SET_FRONTEND call for this frontend\n", 1634 - __func__); 1635 - return -EINVAL; 1636 - } 1637 - } 1638 1518 1639 1519 c->delivery_system = delsys; 1640 1520 ··· 1528 1648 * delivery system is the last one at the ops.delsys[] array 1529 1649 */ 1530 1650 dev_dbg(fe->dvb->device, 1531 - "%s: Using delivery system %d emulated as if it were a %d\n", 1532 - __func__, delsys, desired_system); 1651 + "%s: Using delivery system %d emulated as if it were a %d\n", 1652 + __func__, delsys, desired_system); 1533 1653 1534 1654 /* 1535 1655 * For now, handles ISDB-T calls. More code may be needed here for the ··· 1562 1682 __func__, c->delivery_system); 1563 1683 1564 1684 return 0; 1685 + } 1686 + 1687 + static int dvbv5_set_delivery_system(struct dvb_frontend *fe, 1688 + u32 desired_system) 1689 + { 1690 + int ncaps; 1691 + u32 delsys = SYS_UNDEFINED; 1692 + struct dtv_frontend_properties *c = &fe->dtv_property_cache; 1693 + enum dvbv3_emulation_type type; 1694 + 1695 + /* 1696 + * It was reported that some old DVBv5 applications were 1697 + * filling delivery_system with SYS_UNDEFINED. If this happens, 1698 + * assume that the application wants to use the first supported 1699 + * delivery system. 1700 + */ 1701 + if (c->delivery_system == SYS_UNDEFINED) 1702 + c->delivery_system = fe->ops.delsys[0]; 1703 + 1704 + /* 1705 + * This is a DVBv5 call. So, it likely knows the supported 1706 + * delivery systems. 1707 + */ 1708 + 1709 + /* Check if the desired delivery system is supported */ 1710 + ncaps = 0; 1711 + while (fe->ops.delsys[ncaps] && ncaps < MAX_DELSYS) { 1712 + if (fe->ops.delsys[ncaps] == desired_system) { 1713 + c->delivery_system = desired_system; 1714 + dev_dbg(fe->dvb->device, 1715 + "%s: Changing delivery system to %d\n", 1716 + __func__, desired_system); 1717 + return 0; 1718 + } 1719 + ncaps++; 1720 + } 1721 + 1722 + /* 1723 + * Need to emulate a delivery system 1724 + */ 1725 + 1726 + type = dvbv3_type(desired_system); 1727 + 1728 + /* 1729 + * The delivery system is not supported. See if it can be 1730 + * emulated. 1731 + * The emulation only works if the desired system is one of the 1732 + * DVBv3 delivery systems 1733 + */ 1734 + if (!is_dvbv3_delsys(desired_system)) { 1735 + dev_dbg(fe->dvb->device, 1736 + "%s: can't use a DVBv3 FE_SET_FRONTEND call for this frontend\n", 1737 + __func__); 1738 + return -EINVAL; 1739 + } 1740 + 1741 + /* 1742 + * Get the last non-DVBv3 delivery system that has the same type 1743 + * of the desired system 1744 + */ 1745 + ncaps = 0; 1746 + while (fe->ops.delsys[ncaps] && ncaps < MAX_DELSYS) { 1747 + if ((dvbv3_type(fe->ops.delsys[ncaps]) == type) && 1748 + !is_dvbv3_delsys(fe->ops.delsys[ncaps])) 1749 + delsys = fe->ops.delsys[ncaps]; 1750 + ncaps++; 1751 + } 1752 + /* There's nothing compatible with the desired delivery system */ 1753 + if (delsys == SYS_UNDEFINED) { 1754 + dev_dbg(fe->dvb->device, 1755 + "%s: Incompatible DVBv3 FE_SET_FRONTEND call for this frontend\n", 1756 + __func__); 1757 + return -EINVAL; 1758 + } 1759 + 1760 + return emulate_delivery_system(fe, type, delsys, desired_system); 1761 + } 1762 + 1763 + static int dvbv3_set_delivery_system(struct dvb_frontend *fe) 1764 + { 1765 + int ncaps; 1766 + u32 desired_system; 1767 + u32 delsys = SYS_UNDEFINED; 1768 + struct dtv_frontend_properties *c = &fe->dtv_property_cache; 1769 + enum dvbv3_emulation_type type; 1770 + 1771 + /* If not set yet, defaults to the first supported delivery system */ 1772 + if (c->delivery_system == SYS_UNDEFINED) 1773 + c->delivery_system = fe->ops.delsys[0]; 1774 + 1775 + /* 1776 + * A DVBv3 call doesn't know what's the desired system. 1777 + * Also, DVBv3 applications don't know that ops.info->type 1778 + * could be changed, and they simply don't tune when it doesn't 1779 + * match. 1780 + * So, don't change the current delivery system, as it 1781 + * may be trying to do the wrong thing, like setting an 1782 + * ISDB-T frontend as DVB-T. Instead, find the closest 1783 + * DVBv3 system that matches the delivery system. 1784 + */ 1785 + 1786 + /* 1787 + * Trivial case: just use the current one, if it already a DVBv3 1788 + * delivery system 1789 + */ 1790 + if (is_dvbv3_delsys(c->delivery_system)) { 1791 + dev_dbg(fe->dvb->device, 1792 + "%s: Using delivery system to %d\n", 1793 + __func__, c->delivery_system); 1794 + return 0; 1795 + } 1796 + 1797 + /* Convert from DVBv3 into DVBv5 namespace */ 1798 + type = dvbv3_type(c->delivery_system); 1799 + switch (type) { 1800 + case DVBV3_QPSK: 1801 + desired_system = SYS_DVBS; 1802 + break; 1803 + case DVBV3_QAM: 1804 + desired_system = SYS_DVBC_ANNEX_A; 1805 + break; 1806 + case DVBV3_ATSC: 1807 + desired_system = SYS_ATSC; 1808 + break; 1809 + case DVBV3_OFDM: 1810 + desired_system = SYS_DVBT; 1811 + break; 1812 + default: 1813 + dev_dbg(fe->dvb->device, "%s: This frontend doesn't support DVBv3 calls\n", 1814 + __func__); 1815 + return -EINVAL; 1816 + } 1817 + 1818 + /* 1819 + * Get a delivery system that is compatible with DVBv3 1820 + * NOTE: in order for this to work with softwares like Kaffeine that 1821 + * uses a DVBv5 call for DVB-S2 and a DVBv3 call to go back to 1822 + * DVB-S, drivers that support both should put the SYS_DVBS entry 1823 + * before the SYS_DVBS2, otherwise it won't switch back to DVB-S. 1824 + * The real fix is that userspace applications should not use DVBv3 1825 + * and not trust on calling FE_SET_FRONTEND to switch the delivery 1826 + * system. 1827 + */ 1828 + ncaps = 0; 1829 + while (fe->ops.delsys[ncaps] && ncaps < MAX_DELSYS) { 1830 + if (fe->ops.delsys[ncaps] == desired_system) { 1831 + delsys = desired_system; 1832 + break; 1833 + } 1834 + ncaps++; 1835 + } 1836 + if (delsys == SYS_UNDEFINED) { 1837 + dev_dbg(fe->dvb->device, "%s: Couldn't find a delivery system that matches %d\n", 1838 + __func__, desired_system); 1839 + } 1840 + return emulate_delivery_system(fe, type, delsys, desired_system); 1565 1841 } 1566 1842 1567 1843 static int dtv_property_process_set(struct dvb_frontend *fe, ··· 1778 1742 c->rolloff = tvp->u.data; 1779 1743 break; 1780 1744 case DTV_DELIVERY_SYSTEM: 1781 - r = set_delivery_system(fe, tvp->u.data); 1745 + r = dvbv5_set_delivery_system(fe, tvp->u.data); 1782 1746 break; 1783 1747 case DTV_VOLTAGE: 1784 1748 c->voltage = tvp->u.data; ··· 2371 2335 break; 2372 2336 2373 2337 case FE_SET_FRONTEND: 2374 - err = set_delivery_system(fe, SYS_UNDEFINED); 2338 + err = dvbv3_set_delivery_system(fe); 2375 2339 if (err) 2376 2340 break; 2377 2341 ··· 2630 2594 * first supported delivery system (ops->delsys[0]) 2631 2595 */ 2632 2596 2633 - fe->dtv_property_cache.delivery_system = fe->ops.delsys[0]; 2597 + fe->dtv_property_cache.delivery_system = fe->ops.delsys[0]; 2634 2598 dvb_frontend_clear_cache(fe); 2635 2599 2636 2600 mutex_unlock(&frontend_mutex);