aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/v4l2-ctrls.c
diff options
context:
space:
mode:
authorHans Verkuil <hans.verkuil@cisco.com>2011-06-14 09:04:06 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2011-07-27 16:53:31 -0400
commiteb5b16efb26ff5b2d0ba25a114394db69c433f86 (patch)
treedf68e2737553e18218e94247fd6924eeaf09051f /drivers/media/video/v4l2-ctrls.c
parentc12fcfd676e16a82e47ee44fe2d13dc21717063a (diff)
[media] v4l2-ctrls: improve discovery of controls of the same cluster
The implementation of VIDIOC_G/S/TRY_EXT_CTRLS in the control framework has to figure out which controls in the control list belong to the same cluster. Since controls belonging to the same cluster need to be handled as a unit, this is important information. It did that by going over the controls in the list and for each control that belonged to a multi-control cluster it would walk the remainder of the list to try and find controls that belong to that same cluster. This approach has two disadvantages: 1) it was a potentially quadratic algorithm (although highly unlikely that it would ever be that bad in practice). 2) it took place with the control handler's lock held. Since we want to make it possible in the future to change control values from interrupt context, doing a lot of work while holding a lock is not a good idea. In the new code the algorithm is no longer quadratic but linear in the number of controls in the list. Also, it now can be done beforehand. Another change that was made was to so the try and set at the same time. Before when S_TRY_EXT_CTRLS was called it would 'try' the controls first, and then it would 'set' them. The idea was that any 'try' errors would prevent the 'set' from happening, thus avoiding having partially set control lists. However, this caused more problems than it solved because between the 'try' and the 'set' changes might have happened, so it had to try a second time, and since actual controls with a try_ctrl op are very rare (and those that we have just adjust values and do not return an error), I've decided to drop that two-stage approach and just combine try and set. Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/v4l2-ctrls.c')
-rw-r--r--drivers/media/video/v4l2-ctrls.c279
1 files changed, 143 insertions, 136 deletions
diff --git a/drivers/media/video/v4l2-ctrls.c b/drivers/media/video/v4l2-ctrls.c
index 8fb020dd567..4ec3cfbdc3a 100644
--- a/drivers/media/video/v4l2-ctrls.c
+++ b/drivers/media/video/v4l2-ctrls.c
@@ -32,12 +32,14 @@
32 (has_op(master, op) ? master->ops->op(master) : 0) 32 (has_op(master, op) ? master->ops->op(master) : 0)
33 33
34/* Internal temporary helper struct, one for each v4l2_ext_control */ 34/* Internal temporary helper struct, one for each v4l2_ext_control */
35struct ctrl_helper { 35struct v4l2_ctrl_helper {
36 /* Pointer to the control reference of the master control */
37 struct v4l2_ctrl_ref *mref;
36 /* The control corresponding to the v4l2_ext_control ID field. */ 38 /* The control corresponding to the v4l2_ext_control ID field. */
37 struct v4l2_ctrl *ctrl; 39 struct v4l2_ctrl *ctrl;
38 /* Used internally to mark whether this control was already 40 /* v4l2_ext_control index of the next control belonging to the
39 processed. */ 41 same cluster, or 0 if there isn't any. */
40 bool handled; 42 u32 next;
41}; 43};
42 44
43/* Small helper function to determine if the autocluster is set to manual 45/* Small helper function to determine if the autocluster is set to manual
@@ -678,20 +680,6 @@ static int new_to_user(struct v4l2_ext_control *c,
678 return 0; 680 return 0;
679} 681}
680 682
681static int ctrl_to_user(struct v4l2_ext_control *c,
682 struct v4l2_ctrl *ctrl)
683{
684 if (ctrl->is_volatile)
685 return new_to_user(c, ctrl);
686 return cur_to_user(c, ctrl);
687}
688
689static int ctrl_is_volatile(struct v4l2_ext_control *c,
690 struct v4l2_ctrl *ctrl)
691{
692 return ctrl->is_volatile;
693}
694
695/* Copy the new value to the current value. */ 683/* Copy the new value to the current value. */
696static void new_to_cur(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, 684static void new_to_cur(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl,
697 bool update_inactive) 685 bool update_inactive)
@@ -779,13 +767,11 @@ static int cluster_changed(struct v4l2_ctrl *master)
779 return diff; 767 return diff;
780} 768}
781 769
782/* Validate a new control */ 770/* Validate integer-type control */
783static int validate_new(struct v4l2_ctrl *ctrl) 771static int validate_new_int(const struct v4l2_ctrl *ctrl, s32 *pval)
784{ 772{
785 s32 val = ctrl->val; 773 s32 val = *pval;
786 char *s = ctrl->string;
787 u32 offset; 774 u32 offset;
788 size_t len;
789 775
790 switch (ctrl->type) { 776 switch (ctrl->type) {
791 case V4L2_CTRL_TYPE_INTEGER: 777 case V4L2_CTRL_TYPE_INTEGER:
@@ -798,11 +784,11 @@ static int validate_new(struct v4l2_ctrl *ctrl)
798 offset = val - ctrl->minimum; 784 offset = val - ctrl->minimum;
799 offset = ctrl->step * (offset / ctrl->step); 785 offset = ctrl->step * (offset / ctrl->step);
800 val = ctrl->minimum + offset; 786 val = ctrl->minimum + offset;
801 ctrl->val = val; 787 *pval = val;
802 return 0; 788 return 0;
803 789
804 case V4L2_CTRL_TYPE_BOOLEAN: 790 case V4L2_CTRL_TYPE_BOOLEAN:
805 ctrl->val = !!ctrl->val; 791 *pval = !!val;
806 return 0; 792 return 0;
807 793
808 case V4L2_CTRL_TYPE_MENU: 794 case V4L2_CTRL_TYPE_MENU:
@@ -815,9 +801,28 @@ static int validate_new(struct v4l2_ctrl *ctrl)
815 801
816 case V4L2_CTRL_TYPE_BUTTON: 802 case V4L2_CTRL_TYPE_BUTTON:
817 case V4L2_CTRL_TYPE_CTRL_CLASS: 803 case V4L2_CTRL_TYPE_CTRL_CLASS:
818 ctrl->val64 = 0; 804 *pval = 0;
819 return 0; 805 return 0;
820 806
807 default:
808 return -EINVAL;
809 }
810}
811
812/* Validate a new control */
813static int validate_new(const struct v4l2_ctrl *ctrl, struct v4l2_ext_control *c)
814{
815 char *s = c->string;
816 size_t len;
817
818 switch (ctrl->type) {
819 case V4L2_CTRL_TYPE_INTEGER:
820 case V4L2_CTRL_TYPE_BOOLEAN:
821 case V4L2_CTRL_TYPE_MENU:
822 case V4L2_CTRL_TYPE_BUTTON:
823 case V4L2_CTRL_TYPE_CTRL_CLASS:
824 return validate_new_int(ctrl, &c->value);
825
821 case V4L2_CTRL_TYPE_INTEGER64: 826 case V4L2_CTRL_TYPE_INTEGER64:
822 return 0; 827 return 0;
823 828
@@ -1576,12 +1581,15 @@ EXPORT_SYMBOL(v4l2_subdev_querymenu);
1576 Find the controls in the control array and do some basic checks. */ 1581 Find the controls in the control array and do some basic checks. */
1577static int prepare_ext_ctrls(struct v4l2_ctrl_handler *hdl, 1582static int prepare_ext_ctrls(struct v4l2_ctrl_handler *hdl,
1578 struct v4l2_ext_controls *cs, 1583 struct v4l2_ext_controls *cs,
1579 struct ctrl_helper *helpers) 1584 struct v4l2_ctrl_helper *helpers)
1580{ 1585{
1586 struct v4l2_ctrl_helper *h;
1587 bool have_clusters = false;
1581 u32 i; 1588 u32 i;
1582 1589
1583 for (i = 0; i < cs->count; i++) { 1590 for (i = 0, h = helpers; i < cs->count; i++, h++) {
1584 struct v4l2_ext_control *c = &cs->controls[i]; 1591 struct v4l2_ext_control *c = &cs->controls[i];
1592 struct v4l2_ctrl_ref *ref;
1585 struct v4l2_ctrl *ctrl; 1593 struct v4l2_ctrl *ctrl;
1586 u32 id = c->id & V4L2_CTRL_ID_MASK; 1594 u32 id = c->id & V4L2_CTRL_ID_MASK;
1587 1595
@@ -1594,53 +1602,59 @@ static int prepare_ext_ctrls(struct v4l2_ctrl_handler *hdl,
1594 extended controls */ 1602 extended controls */
1595 if (id >= V4L2_CID_PRIVATE_BASE) 1603 if (id >= V4L2_CID_PRIVATE_BASE)
1596 return -EINVAL; 1604 return -EINVAL;
1597 ctrl = v4l2_ctrl_find(hdl, id); 1605 ref = find_ref_lock(hdl, id);
1598 if (ctrl == NULL) 1606 if (ref == NULL)
1599 return -EINVAL; 1607 return -EINVAL;
1608 ctrl = ref->ctrl;
1600 if (ctrl->flags & V4L2_CTRL_FLAG_DISABLED) 1609 if (ctrl->flags & V4L2_CTRL_FLAG_DISABLED)
1601 return -EINVAL; 1610 return -EINVAL;
1602 1611
1603 helpers[i].ctrl = ctrl; 1612 if (ctrl->cluster[0]->ncontrols > 1)
1604 helpers[i].handled = false; 1613 have_clusters = true;
1614 if (ctrl->cluster[0] != ctrl)
1615 ref = find_ref_lock(hdl, ctrl->cluster[0]->id);
1616 /* Store the ref to the master control of the cluster */
1617 h->mref = ref;
1618 h->ctrl = ctrl;
1619 /* Initially set next to 0, meaning that there is no other
1620 control in this helper array belonging to the same
1621 cluster */
1622 h->next = 0;
1605 } 1623 }
1606 return 0;
1607}
1608 1624
1609typedef int (*cluster_func)(struct v4l2_ext_control *c, 1625 /* We are done if there were no controls that belong to a multi-
1610 struct v4l2_ctrl *ctrl); 1626 control cluster. */
1627 if (!have_clusters)
1628 return 0;
1611 1629
1612/* Walk over all controls in v4l2_ext_controls belonging to the same cluster 1630 /* The code below figures out in O(n) time which controls in the list
1613 and call the provided function. */ 1631 belong to the same cluster. */
1614static int cluster_walk(unsigned from,
1615 struct v4l2_ext_controls *cs,
1616 struct ctrl_helper *helpers,
1617 cluster_func f)
1618{
1619 struct v4l2_ctrl **cluster = helpers[from].ctrl->cluster;
1620 int ret = 0;
1621 int i;
1622 1632
1623 /* Find any controls from the same cluster and call the function */ 1633 /* This has to be done with the handler lock taken. */
1624 for (i = from; !ret && i < cs->count; i++) { 1634 mutex_lock(&hdl->lock);
1625 struct v4l2_ctrl *ctrl = helpers[i].ctrl;
1626 1635
1627 if (!helpers[i].handled && ctrl->cluster == cluster) 1636 /* First zero the helper field in the master control references */
1628 ret = f(&cs->controls[i], ctrl); 1637 for (i = 0; i < cs->count; i++)
1638 helpers[i].mref->helper = 0;
1639 for (i = 0, h = helpers; i < cs->count; i++, h++) {
1640 struct v4l2_ctrl_ref *mref = h->mref;
1641
1642 /* If the mref->helper is set, then it points to an earlier
1643 helper that belongs to the same cluster. */
1644 if (mref->helper) {
1645 /* Set the next field of mref->helper to the current
1646 index: this means that that earlier helper now
1647 points to the next helper in the same cluster. */
1648 mref->helper->next = i;
1649 /* mref should be set only for the first helper in the
1650 cluster, clear the others. */
1651 h->mref = NULL;
1652 }
1653 /* Point the mref helper to the current helper struct. */
1654 mref->helper = h;
1629 } 1655 }
1630 return ret; 1656 mutex_unlock(&hdl->lock);
1631} 1657 return 0;
1632
1633static void cluster_done(unsigned from,
1634 struct v4l2_ext_controls *cs,
1635 struct ctrl_helper *helpers)
1636{
1637 struct v4l2_ctrl **cluster = helpers[from].ctrl->cluster;
1638 int i;
1639
1640 /* Find any controls from the same cluster and mark them as handled */
1641 for (i = from; i < cs->count; i++)
1642 if (helpers[i].ctrl->cluster == cluster)
1643 helpers[i].handled = true;
1644} 1658}
1645 1659
1646/* Handles the corner case where cs->count == 0. It checks whether the 1660/* Handles the corner case where cs->count == 0. It checks whether the
@@ -1658,8 +1672,8 @@ static int class_check(struct v4l2_ctrl_handler *hdl, u32 ctrl_class)
1658/* Get extended controls. Allocates the helpers array if needed. */ 1672/* Get extended controls. Allocates the helpers array if needed. */
1659int v4l2_g_ext_ctrls(struct v4l2_ctrl_handler *hdl, struct v4l2_ext_controls *cs) 1673int v4l2_g_ext_ctrls(struct v4l2_ctrl_handler *hdl, struct v4l2_ext_controls *cs)
1660{ 1674{
1661 struct ctrl_helper helper[4]; 1675 struct v4l2_ctrl_helper helper[4];
1662 struct ctrl_helper *helpers = helper; 1676 struct v4l2_ctrl_helper *helpers = helper;
1663 int ret; 1677 int ret;
1664 int i, j; 1678 int i, j;
1665 1679
@@ -1686,37 +1700,38 @@ int v4l2_g_ext_ctrls(struct v4l2_ctrl_handler *hdl, struct v4l2_ext_controls *cs
1686 ret = -EACCES; 1700 ret = -EACCES;
1687 1701
1688 for (i = 0; !ret && i < cs->count; i++) { 1702 for (i = 0; !ret && i < cs->count; i++) {
1689 struct v4l2_ctrl *ctrl = helpers[i].ctrl; 1703 int (*ctrl_to_user)(struct v4l2_ext_control *c,
1690 struct v4l2_ctrl *master = ctrl->cluster[0]; 1704 struct v4l2_ctrl *ctrl) = cur_to_user;
1691 bool has_volatiles; 1705 struct v4l2_ctrl *master;
1692 1706
1693 if (helpers[i].handled) 1707 if (helpers[i].mref == NULL)
1694 continue; 1708 continue;
1695 1709
1710 master = helpers[i].mref->ctrl;
1696 cs->error_idx = i; 1711 cs->error_idx = i;
1697 1712
1698 /* Any volatile controls requested from this cluster? */
1699 has_volatiles = ctrl->is_volatile;
1700 if (!has_volatiles && has_op(master, g_volatile_ctrl) &&
1701 master->ncontrols > 1)
1702 has_volatiles = cluster_walk(i, cs, helpers,
1703 ctrl_is_volatile);
1704
1705 v4l2_ctrl_lock(master); 1713 v4l2_ctrl_lock(master);
1706 1714
1707 /* g_volatile_ctrl will update the new control values */ 1715 /* g_volatile_ctrl will update the new control values */
1708 if (has_volatiles && !is_cur_manual(master)) { 1716 if (has_op(master, g_volatile_ctrl) && !is_cur_manual(master)) {
1709 for (j = 0; j < master->ncontrols; j++) 1717 for (j = 0; j < master->ncontrols; j++)
1710 cur_to_new(master->cluster[j]); 1718 cur_to_new(master->cluster[j]);
1711 ret = call_op(master, g_volatile_ctrl); 1719 ret = call_op(master, g_volatile_ctrl);
1720 ctrl_to_user = new_to_user;
1712 } 1721 }
1713 /* If OK, then copy the current (for non-volatile controls) 1722 /* If OK, then copy the current (for non-volatile controls)
1714 or the new (for volatile controls) control values to the 1723 or the new (for volatile controls) control values to the
1715 caller */ 1724 caller */
1716 if (!ret) 1725 if (!ret) {
1717 ret = cluster_walk(i, cs, helpers, ctrl_to_user); 1726 u32 idx = i;
1727
1728 do {
1729 ret = ctrl_to_user(cs->controls + idx,
1730 helpers[idx].ctrl);
1731 idx = helpers[idx].next;
1732 } while (!ret && idx);
1733 }
1718 v4l2_ctrl_unlock(master); 1734 v4l2_ctrl_unlock(master);
1719 cluster_done(i, cs, helpers);
1720 } 1735 }
1721 1736
1722 if (cs->count > ARRAY_SIZE(helper)) 1737 if (cs->count > ARRAY_SIZE(helper))
@@ -1790,52 +1805,39 @@ static int try_or_set_control_cluster(struct v4l2_fh *fh,
1790 struct v4l2_ctrl *master, bool set) 1805 struct v4l2_ctrl *master, bool set)
1791{ 1806{
1792 bool update_flag; 1807 bool update_flag;
1793 bool try = !set; 1808 int ret;
1794 int ret = 0;
1795 int i; 1809 int i;
1796 1810
1797 /* Go through the cluster and either validate the new value or 1811 /* Go through the cluster and either validate the new value or
1798 (if no new value was set), copy the current value to the new 1812 (if no new value was set), copy the current value to the new
1799 value, ensuring a consistent view for the control ops when 1813 value, ensuring a consistent view for the control ops when
1800 called. */ 1814 called. */
1801 for (i = 0; !ret && i < master->ncontrols; i++) { 1815 for (i = 0; i < master->ncontrols; i++) {
1802 struct v4l2_ctrl *ctrl = master->cluster[i]; 1816 struct v4l2_ctrl *ctrl = master->cluster[i];
1803 1817
1804 if (ctrl == NULL) 1818 if (ctrl == NULL)
1805 continue; 1819 continue;
1806 1820
1807 if (ctrl->is_new) { 1821 if (!ctrl->is_new) {
1808 /* Double check this: it may have changed since the 1822 cur_to_new(ctrl);
1809 last check in try_or_set_ext_ctrls(). */
1810 if (set && (ctrl->flags & V4L2_CTRL_FLAG_GRABBED))
1811 return -EBUSY;
1812
1813 /* Validate if required */
1814 if (!set)
1815 ret = validate_new(ctrl);
1816 continue; 1823 continue;
1817 } 1824 }
1818 /* No new value was set, so copy the current and force 1825 /* Check again: it may have changed since the
1819 a call to try_ctrl later, since the values for the cluster 1826 previous check in try_or_set_ext_ctrls(). */
1820 may now have changed and the end result might be invalid. */ 1827 if (set && (ctrl->flags & V4L2_CTRL_FLAG_GRABBED))
1821 try = true; 1828 return -EBUSY;
1822 cur_to_new(ctrl);
1823 } 1829 }
1824 1830
1825 /* For larger clusters you have to call try_ctrl again to 1831 ret = call_op(master, try_ctrl);
1826 verify that the controls are still valid after the
1827 'cur_to_new' above. */
1828 if (!ret && try)
1829 ret = call_op(master, try_ctrl);
1830 1832
1831 /* Don't set if there is no change */ 1833 /* Don't set if there is no change */
1832 if (ret || !set || !cluster_changed(master)) 1834 if (ret || !set || !cluster_changed(master))
1833 return ret; 1835 return ret;
1834 ret = call_op(master, s_ctrl); 1836 ret = call_op(master, s_ctrl);
1835 /* If OK, then make the new values permanent. */
1836 if (ret) 1837 if (ret)
1837 return ret; 1838 return ret;
1838 1839
1840 /* If OK, then make the new values permanent. */
1839 update_flag = is_cur_manual(master) != is_new_manual(master); 1841 update_flag = is_cur_manual(master) != is_new_manual(master);
1840 for (i = 0; i < master->ncontrols; i++) 1842 for (i = 0; i < master->ncontrols; i++)
1841 new_to_cur(fh, master->cluster[i], update_flag && i > 0); 1843 new_to_cur(fh, master->cluster[i], update_flag && i > 0);
@@ -1846,16 +1848,19 @@ static int try_or_set_control_cluster(struct v4l2_fh *fh,
1846static int try_or_set_ext_ctrls(struct v4l2_fh *fh, 1848static int try_or_set_ext_ctrls(struct v4l2_fh *fh,
1847 struct v4l2_ctrl_handler *hdl, 1849 struct v4l2_ctrl_handler *hdl,
1848 struct v4l2_ext_controls *cs, 1850 struct v4l2_ext_controls *cs,
1849 struct ctrl_helper *helpers, 1851 struct v4l2_ctrl_helper *helpers,
1850 bool set) 1852 bool set)
1851{ 1853{
1852 unsigned i, j; 1854 unsigned i, j;
1853 int ret = 0; 1855 int ret = 0;
1854 1856
1857 /* Phase 1: validation */
1858 cs->error_idx = cs->count;
1855 for (i = 0; i < cs->count; i++) { 1859 for (i = 0; i < cs->count; i++) {
1856 struct v4l2_ctrl *ctrl = helpers[i].ctrl; 1860 struct v4l2_ctrl *ctrl = helpers[i].ctrl;
1857 1861
1858 cs->error_idx = i; 1862 if (!set)
1863 cs->error_idx = i;
1859 1864
1860 if (ctrl->flags & V4L2_CTRL_FLAG_READ_ONLY) 1865 if (ctrl->flags & V4L2_CTRL_FLAG_READ_ONLY)
1861 return -EACCES; 1866 return -EACCES;
@@ -1867,17 +1872,22 @@ static int try_or_set_ext_ctrls(struct v4l2_fh *fh,
1867 best-effort to avoid that. */ 1872 best-effort to avoid that. */
1868 if (set && (ctrl->flags & V4L2_CTRL_FLAG_GRABBED)) 1873 if (set && (ctrl->flags & V4L2_CTRL_FLAG_GRABBED))
1869 return -EBUSY; 1874 return -EBUSY;
1875 ret = validate_new(ctrl, &cs->controls[i]);
1876 if (ret)
1877 return ret;
1870 } 1878 }
1871 1879
1880 /* Phase 2: set/try controls */
1872 for (i = 0; !ret && i < cs->count; i++) { 1881 for (i = 0; !ret && i < cs->count; i++) {
1873 struct v4l2_ctrl *ctrl = helpers[i].ctrl; 1882 struct v4l2_ctrl *master;
1874 struct v4l2_ctrl *master = ctrl->cluster[0]; 1883 u32 idx = i;
1875 1884
1876 if (helpers[i].handled) 1885 if (helpers[i].mref == NULL)
1877 continue; 1886 continue;
1878 1887
1879 cs->error_idx = i; 1888 cs->error_idx = i;
1880 v4l2_ctrl_lock(ctrl); 1889 master = helpers[i].mref->ctrl;
1890 v4l2_ctrl_lock(master);
1881 1891
1882 /* Reset the 'is_new' flags of the cluster */ 1892 /* Reset the 'is_new' flags of the cluster */
1883 for (j = 0; j < master->ncontrols; j++) 1893 for (j = 0; j < master->ncontrols; j++)
@@ -1886,17 +1896,24 @@ static int try_or_set_ext_ctrls(struct v4l2_fh *fh,
1886 1896
1887 /* Copy the new caller-supplied control values. 1897 /* Copy the new caller-supplied control values.
1888 user_to_new() sets 'is_new' to 1. */ 1898 user_to_new() sets 'is_new' to 1. */
1889 ret = cluster_walk(i, cs, helpers, user_to_new); 1899 do {
1900 ret = user_to_new(cs->controls + idx, helpers[idx].ctrl);
1901 idx = helpers[idx].next;
1902 } while (!ret && idx);
1890 1903
1891 if (!ret) 1904 if (!ret)
1892 ret = try_or_set_control_cluster(fh, master, set); 1905 ret = try_or_set_control_cluster(fh, master, set);
1893 1906
1894 /* Copy the new values back to userspace. */ 1907 /* Copy the new values back to userspace. */
1895 if (!ret) 1908 if (!ret) {
1896 ret = cluster_walk(i, cs, helpers, new_to_user); 1909 idx = i;
1897 1910 do {
1898 v4l2_ctrl_unlock(ctrl); 1911 ret = user_to_new(cs->controls + idx,
1899 cluster_done(i, cs, helpers); 1912 helpers[idx].ctrl);
1913 idx = helpers[idx].next;
1914 } while (!ret && idx);
1915 }
1916 v4l2_ctrl_unlock(master);
1900 } 1917 }
1901 return ret; 1918 return ret;
1902} 1919}
@@ -1906,10 +1923,9 @@ static int try_set_ext_ctrls(struct v4l2_fh *fh, struct v4l2_ctrl_handler *hdl,
1906 struct v4l2_ext_controls *cs, 1923 struct v4l2_ext_controls *cs,
1907 bool set) 1924 bool set)
1908{ 1925{
1909 struct ctrl_helper helper[4]; 1926 struct v4l2_ctrl_helper helper[4];
1910 struct ctrl_helper *helpers = helper; 1927 struct v4l2_ctrl_helper *helpers = helper;
1911 int ret; 1928 int ret;
1912 int i;
1913 1929
1914 cs->error_idx = cs->count; 1930 cs->error_idx = cs->count;
1915 cs->ctrl_class = V4L2_CTRL_ID2CLASS(cs->ctrl_class); 1931 cs->ctrl_class = V4L2_CTRL_ID2CLASS(cs->ctrl_class);
@@ -1926,21 +1942,10 @@ static int try_set_ext_ctrls(struct v4l2_fh *fh, struct v4l2_ctrl_handler *hdl,
1926 return -ENOMEM; 1942 return -ENOMEM;
1927 } 1943 }
1928 ret = prepare_ext_ctrls(hdl, cs, helpers); 1944 ret = prepare_ext_ctrls(hdl, cs, helpers);
1929
1930 /* First 'try' all controls and abort on error */
1931 if (!ret) 1945 if (!ret)
1932 ret = try_or_set_ext_ctrls(NULL, hdl, cs, helpers, false); 1946 ret = try_or_set_ext_ctrls(fh, hdl, cs, helpers, set);
1933 /* If this is a 'set' operation and the initial 'try' failed, 1947 else if (set)
1934 then set error_idx to count to tell the application that no
1935 controls changed value yet. */
1936 if (set)
1937 cs->error_idx = cs->count; 1948 cs->error_idx = cs->count;
1938 if (!ret && set) {
1939 /* Reset 'handled' state */
1940 for (i = 0; i < cs->count; i++)
1941 helpers[i].handled = false;
1942 ret = try_or_set_ext_ctrls(fh, hdl, cs, helpers, true);
1943 }
1944 1949
1945 if (cs->count > ARRAY_SIZE(helper)) 1950 if (cs->count > ARRAY_SIZE(helper))
1946 kfree(helpers); 1951 kfree(helpers);
@@ -1979,6 +1984,10 @@ static int set_ctrl(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, s32 *val)
1979 int ret; 1984 int ret;
1980 int i; 1985 int i;
1981 1986
1987 ret = validate_new_int(ctrl, val);
1988 if (ret)
1989 return ret;
1990
1982 v4l2_ctrl_lock(ctrl); 1991 v4l2_ctrl_lock(ctrl);
1983 1992
1984 /* Reset the 'is_new' flags of the cluster */ 1993 /* Reset the 'is_new' flags of the cluster */
@@ -1988,9 +1997,7 @@ static int set_ctrl(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, s32 *val)
1988 1997
1989 ctrl->val = *val; 1998 ctrl->val = *val;
1990 ctrl->is_new = 1; 1999 ctrl->is_new = 1;
1991 ret = try_or_set_control_cluster(NULL, master, false); 2000 ret = try_or_set_control_cluster(fh, master, true);
1992 if (!ret)
1993 ret = try_or_set_control_cluster(fh, master, true);
1994 *val = ctrl->cur.val; 2001 *val = ctrl->cur.val;
1995 v4l2_ctrl_unlock(ctrl); 2002 v4l2_ctrl_unlock(ctrl);
1996 return ret; 2003 return ret;