Re: [PATCH v8 2/3] uvcvideo: send a control event when a Control Change interrupt arrives

2018-07-17 Thread Guennadi Liakhovetski
Hi Laurent,

On Wed, 18 Jul 2018, Laurent Pinchart wrote:

> Hi Guennadi,
> 
> On Wednesday, 18 July 2018 00:30:45 EEST Guennadi Liakhovetski wrote:
> > On Tue, 17 Jul 2018, Laurent Pinchart wrote:
> > > On Thursday, 12 July 2018 10:30:46 EEST Guennadi Liakhovetski wrote:
> > >> On Thu, 12 Jul 2018, Laurent Pinchart wrote:
> > >>> On Tuesday, 8 May 2018 18:07:43 EEST Guennadi Liakhovetski wrote:
> >  UVC defines a method of handling asynchronous controls, which sends a
> >  USB packet over the interrupt pipe. This patch implements support for
> >  such packets by sending a control event to the user. Since this can
> >  involve USB traffic and, therefore, scheduling, this has to be done
> >  in a work queue.
> >  
> >  Signed-off-by: Guennadi Liakhovetski
> >  
> >  ---
> >  
> >  v8:
> >  
> >  * avoid losing events by delaying the status URB resubmission until
> >    after completion of the current event
> >  * extract control value calculation into __uvc_ctrl_get_value()
> >  * do not proactively return EBUSY if the previous control hasn't
> >    completed yet, let the camera handle such cases
> >  * multiple cosmetic changes
> >  
> >   drivers/media/usb/uvc/uvc_ctrl.c   | 166 +--
> >   drivers/media/usb/uvc/uvc_status.c | 112 ++---
> >   drivers/media/usb/uvc/uvc_v4l2.c   |   4 +-
> >   drivers/media/usb/uvc/uvcvideo.h   |  15 +++-
> >   include/uapi/linux/uvcvideo.h  |   2 +
> >   5 files changed, 255 insertions(+), 44 deletions(-)
> >  
> >  diff --git a/drivers/media/usb/uvc/uvc_ctrl.c
> >  b/drivers/media/usb/uvc/uvc_ctrl.c index 2a213c8..796f86a 100644
> >  --- a/drivers/media/usb/uvc/uvc_ctrl.c
> >  +++ b/drivers/media/usb/uvc/uvc_ctrl.c
> > >> 
> > >> [snip]
> > >> 
> >  +static void uvc_ctrl_status_event_work(struct work_struct *work)
> >  +{
> >  +  struct uvc_device *dev = container_of(work, struct uvc_device,
> >  +async_ctrl.work);
> >  +  struct uvc_ctrl_work *w = &dev->async_ctrl;
> >  +  struct uvc_control_mapping *mapping;
> >  +  struct uvc_control *ctrl = w->ctrl;
> >  +  unsigned int i;
> >  +  int ret;
> >  +
> >  +  mutex_lock(&w->chain->ctrl_mutex);
> >  +
> >  +  list_for_each_entry(mapping, &ctrl->info.mappings, list) {
> >  +  s32 value = __uvc_ctrl_get_value(mapping, w->data);
> >  +
> >  +  /*
> >  +   * So far none of the auto-update controls in the 
> >  uvc_ctrls[]
> >  +   * table is mapped to a V4L control with slaves in the
> >  +   * uvc_ctrl_mappings[] list, so slave controls so far 
> >  never have
> >  +   * handle == NULL, but this can change in the future
> >  +   */
> >  +  for (i = 0; i < ARRAY_SIZE(mapping->slave_ids); ++i) {
> >  +  if (!mapping->slave_ids[i])
> >  +  break;
> >  +
> >  +  __uvc_ctrl_send_slave_event(ctrl->handle, 
> >  w->chain,
> >  +  ctrl, 
> >  mapping->slave_ids[i]);
> >  +  }
> >  +
> >  +  uvc_ctrl_send_event(ctrl->handle, ctrl, mapping, value,
> >  +  V4L2_EVENT_CTRL_CH_VALUE);
> >  +  }
> >  +
> >  +  mutex_unlock(&w->chain->ctrl_mutex);
> >  +
> >  +  ctrl->handle = NULL;
> > >>> 
> > >>> Can't this race with a uvc_ctrl_set() call, resulting in ctrl->handle
> > >>> being NULL after the control gets set ?
> > >> 
> > >> Right, it's better to set .handle to NULL before sending events.
> > >> Something like
> > >> 
> > >> mutex_lock();
> > >> 
> > >> handle = ctrl->handle;
> > >> ctrl->handle = NULL;
> > >> 
> > >> list_for_each_entry() {
> > >> 
> > >>  ...
> > >>  uvc_ctrl_send_event(handle,...);
> > >> 
> > >> }
> > >> 
> > >> mutex_unlock();
> > >> 
> > >> ?
> > > 
> > > I think you also have to take the same lock in the uvc_ctrl_set() function
> > > to fix the problem, otherwise the ctrl->handle = NULL line could still be
> > > executed after the ctrl->handle assignment in uvc_ctrl_set(), resulting
> > > in ctrl->handle being NULL while the control is being set.
> > 
> > Doesn't this mean, that you're attempting to send a new instance of the
> > same control before the previous has completed? In which case also taking
> > the lock in uvc_ctrl_set() wouldn't help either, because you can anyway do
> > that immediately after the first instance, before the completion even has
> > fired.
> 
> You're right that it won't solve the race completely, but wouldn't it at 
> least 
> prevent ctrl->handle from being NULL ? We can't guarantee which of the old 
> and 
> new handl

cron job: media_tree daily build: WARNINGS

2018-07-17 Thread Hans Verkuil
This message is generated daily by a cron job that builds media_tree for
the kernels and architectures in the list below.

Results of the daily build of media_tree:

date:   Wed Jul 18 05:00:15 CEST 2018
media-tree git hash:39fbb88165b2bbbc77ea7acab5f10632a31526e6
media_build git hash:   f3b64e45d2f2ef45cd4ae5b90a8f2a4fb284e43c
v4l-utils git hash: e4df0e3cd3a84570714defe279d13eae894cb1fa
edid-decode git hash:   ab18befbcacd6cd4dff63faa82e32700369d6f25
gcc version:i686-linux-gcc (GCC) 8.1.0
sparse version: 0.5.2
smatch version: 0.5.1
host hardware:  x86_64
host os:4.16.0-1-amd64

linux-git-arm-at91: OK
linux-git-arm-davinci: OK
linux-git-arm-multi: OK
linux-git-arm-pxa: OK
linux-git-arm-stm32: OK
linux-git-arm64: OK
linux-git-i686: OK
linux-git-mips: OK
linux-git-powerpc64: OK
linux-git-sh: OK
linux-git-x86_64: WARNINGS
Check COMPILE_TEST: OK
linux-2.6.36.4-i686: OK
linux-2.6.36.4-x86_64: OK
linux-2.6.37.6-i686: OK
linux-2.6.37.6-x86_64: OK
linux-2.6.38.8-i686: OK
linux-2.6.38.8-x86_64: OK
linux-2.6.39.4-i686: OK
linux-2.6.39.4-x86_64: OK
linux-3.0.101-i686: OK
linux-3.0.101-x86_64: OK
linux-3.1.10-i686: OK
linux-3.1.10-x86_64: OK
linux-3.2.102-i686: OK
linux-3.2.102-x86_64: OK
linux-3.3.8-i686: OK
linux-3.3.8-x86_64: OK
linux-3.4.113-i686: OK
linux-3.4.113-x86_64: OK
linux-3.5.7-i686: OK
linux-3.5.7-x86_64: OK
linux-3.6.11-i686: OK
linux-3.6.11-x86_64: OK
linux-3.7.10-i686: OK
linux-3.7.10-x86_64: OK
linux-3.8.13-i686: OK
linux-3.8.13-x86_64: OK
linux-3.9.11-i686: OK
linux-3.9.11-x86_64: OK
linux-3.10.108-i686: OK
linux-3.10.108-x86_64: OK
linux-3.11.10-i686: OK
linux-3.11.10-x86_64: OK
linux-3.12.74-i686: OK
linux-3.12.74-x86_64: OK
linux-3.13.11-i686: OK
linux-3.13.11-x86_64: OK
linux-3.14.79-i686: OK
linux-3.14.79-x86_64: OK
linux-3.15.10-i686: OK
linux-3.15.10-x86_64: OK
linux-3.16.57-i686: OK
linux-3.16.57-x86_64: OK
linux-3.17.8-i686: OK
linux-3.17.8-x86_64: OK
linux-3.18.115-i686: OK
linux-3.18.115-x86_64: OK
linux-3.19.8-i686: OK
linux-3.19.8-x86_64: OK
linux-4.0.9-i686: OK
linux-4.0.9-x86_64: OK
linux-4.1.52-i686: OK
linux-4.1.52-x86_64: OK
linux-4.2.8-i686: OK
linux-4.2.8-x86_64: OK
linux-4.3.6-i686: OK
linux-4.3.6-x86_64: OK
linux-4.4.140-i686: OK
linux-4.4.140-x86_64: OK
linux-4.5.7-i686: OK
linux-4.5.7-x86_64: OK
linux-4.6.7-i686: OK
linux-4.6.7-x86_64: OK
linux-4.7.10-i686: OK
linux-4.7.10-x86_64: OK
linux-4.8.17-i686: OK
linux-4.8.17-x86_64: OK
linux-4.9.112-i686: OK
linux-4.9.112-x86_64: OK
linux-4.10.17-i686: OK
linux-4.10.17-x86_64: OK
linux-4.11.12-i686: OK
linux-4.11.12-x86_64: OK
linux-4.12.14-i686: OK
linux-4.12.14-x86_64: OK
linux-4.13.16-i686: OK
linux-4.13.16-x86_64: OK
linux-4.14.55-i686: OK
linux-4.14.55-x86_64: OK
linux-4.15.18-i686: OK
linux-4.15.18-x86_64: OK
linux-4.16.18-i686: OK
linux-4.16.18-x86_64: OK
linux-4.17.6-i686: OK
linux-4.17.6-x86_64: OK
linux-4.18-rc4-i686: OK
linux-4.18-rc4-x86_64: OK
apps: OK
spec-git: OK

Detailed results are available here:

http://www.xs4all.nl/~hverkuil/logs/Wednesday.log

Full logs are available here:

http://www.xs4all.nl/~hverkuil/logs/Wednesday.tar.bz2

The Media Infrastructure API from this daily build is here:

http://www.xs4all.nl/~hverkuil/spec/index.html


Re: [PATCH v8 2/3] uvcvideo: send a control event when a Control Change interrupt arrives

2018-07-17 Thread Laurent Pinchart
Hi Guennadi,

On Wednesday, 18 July 2018 00:30:45 EEST Guennadi Liakhovetski wrote:
> On Tue, 17 Jul 2018, Laurent Pinchart wrote:
> > On Thursday, 12 July 2018 10:30:46 EEST Guennadi Liakhovetski wrote:
> >> On Thu, 12 Jul 2018, Laurent Pinchart wrote:
> >>> On Tuesday, 8 May 2018 18:07:43 EEST Guennadi Liakhovetski wrote:
>  UVC defines a method of handling asynchronous controls, which sends a
>  USB packet over the interrupt pipe. This patch implements support for
>  such packets by sending a control event to the user. Since this can
>  involve USB traffic and, therefore, scheduling, this has to be done
>  in a work queue.
>  
>  Signed-off-by: Guennadi Liakhovetski
>  
>  ---
>  
>  v8:
>  
>  * avoid losing events by delaying the status URB resubmission until
>    after completion of the current event
>  * extract control value calculation into __uvc_ctrl_get_value()
>  * do not proactively return EBUSY if the previous control hasn't
>    completed yet, let the camera handle such cases
>  * multiple cosmetic changes
>  
>   drivers/media/usb/uvc/uvc_ctrl.c   | 166 +--
>   drivers/media/usb/uvc/uvc_status.c | 112 ++---
>   drivers/media/usb/uvc/uvc_v4l2.c   |   4 +-
>   drivers/media/usb/uvc/uvcvideo.h   |  15 +++-
>   include/uapi/linux/uvcvideo.h  |   2 +
>   5 files changed, 255 insertions(+), 44 deletions(-)
>  
>  diff --git a/drivers/media/usb/uvc/uvc_ctrl.c
>  b/drivers/media/usb/uvc/uvc_ctrl.c index 2a213c8..796f86a 100644
>  --- a/drivers/media/usb/uvc/uvc_ctrl.c
>  +++ b/drivers/media/usb/uvc/uvc_ctrl.c
> >> 
> >> [snip]
> >> 
>  +static void uvc_ctrl_status_event_work(struct work_struct *work)
>  +{
>  +struct uvc_device *dev = container_of(work, struct uvc_device,
>  +  async_ctrl.work);
>  +struct uvc_ctrl_work *w = &dev->async_ctrl;
>  +struct uvc_control_mapping *mapping;
>  +struct uvc_control *ctrl = w->ctrl;
>  +unsigned int i;
>  +int ret;
>  +
>  +mutex_lock(&w->chain->ctrl_mutex);
>  +
>  +list_for_each_entry(mapping, &ctrl->info.mappings, list) {
>  +s32 value = __uvc_ctrl_get_value(mapping, w->data);
>  +
>  +/*
>  + * So far none of the auto-update controls in the 
>  uvc_ctrls[]
>  + * table is mapped to a V4L control with slaves in the
>  + * uvc_ctrl_mappings[] list, so slave controls so far 
>  never have
>  + * handle == NULL, but this can change in the future
>  + */
>  +for (i = 0; i < ARRAY_SIZE(mapping->slave_ids); ++i) {
>  +if (!mapping->slave_ids[i])
>  +break;
>  +
>  +__uvc_ctrl_send_slave_event(ctrl->handle, 
>  w->chain,
>  +ctrl, 
>  mapping->slave_ids[i]);
>  +}
>  +
>  +uvc_ctrl_send_event(ctrl->handle, ctrl, mapping, value,
>  +V4L2_EVENT_CTRL_CH_VALUE);
>  +}
>  +
>  +mutex_unlock(&w->chain->ctrl_mutex);
>  +
>  +ctrl->handle = NULL;
> >>> 
> >>> Can't this race with a uvc_ctrl_set() call, resulting in ctrl->handle
> >>> being NULL after the control gets set ?
> >> 
> >> Right, it's better to set .handle to NULL before sending events.
> >> Something like
> >> 
> >> mutex_lock();
> >> 
> >> handle = ctrl->handle;
> >> ctrl->handle = NULL;
> >> 
> >> list_for_each_entry() {
> >> 
> >>...
> >>uvc_ctrl_send_event(handle,...);
> >> 
> >> }
> >> 
> >> mutex_unlock();
> >> 
> >> ?
> > 
> > I think you also have to take the same lock in the uvc_ctrl_set() function
> > to fix the problem, otherwise the ctrl->handle = NULL line could still be
> > executed after the ctrl->handle assignment in uvc_ctrl_set(), resulting
> > in ctrl->handle being NULL while the control is being set.
> 
> Doesn't this mean, that you're attempting to send a new instance of the
> same control before the previous has completed? In which case also taking
> the lock in uvc_ctrl_set() wouldn't help either, because you can anyway do
> that immediately after the first instance, before the completion even has
> fired.

You're right that it won't solve the race completely, but wouldn't it at least 
prevent ctrl->handle from being NULL ? We can't guarantee which of the old and 
new handle will be used for events when multiple control set operations are 
invoked, but we should try to guarantee that the handle won't be NULL.

>  +/* Resubmit the URB. */
>  +w->urb->interval = dev->int_ep->desc.bInterva

Re: [PATCH v8 3/3] uvcvideo: handle control pipe protocol STALLs

2018-07-17 Thread Laurent Pinchart
Hi Guennadi,

On Tuesday, 17 July 2018 23:58:03 EEST Laurent Pinchart wrote:
> On Tuesday, 8 May 2018 18:07:44 EEST Guennadi Liakhovetski wrote:
> > When a command ends up in a STALL on the control pipe, use the Request
> > Error Code control to provide a more precise error information to the
> > user. For example, if a camera is still busy processing a control,
> > when the same or an interrelated control set request arrives, the
> > camera can react with a STALL and then return the "Not ready" status
> > in response to a UVC_VC_REQUEST_ERROR_CODE_CONTROL command. With this
> > patch the user would then get an EBUSY error code instead of a
> > generic EPIPE.
> > 
> > Signed-off-by: Guennadi Liakhovetski 
> 
> Reviewed-by: Laurent Pinchart 

Can I push this patch already before 2/3 is ready ?

> > ---
> > 
> > v8:
> > 
> > * restrict UVC_VC_REQUEST_ERROR_CODE_CONTROL to the control interface
> > * fix the wIndex value
> > * improve error codes
> > * cosmetic changes
> > 
> >  drivers/media/usb/uvc/uvc_video.c | 52 +-
> >  1 file changed, 46 insertions(+), 6 deletions(-)
> > 
> > diff --git a/drivers/media/usb/uvc/uvc_video.c
> > b/drivers/media/usb/uvc/uvc_video.c index aa0082f..ce65cd6 100644
> > --- a/drivers/media/usb/uvc/uvc_video.c
> > +++ b/drivers/media/usb/uvc/uvc_video.c
> > @@ -73,17 +73,57 @@ int uvc_query_ctrl(struct uvc_device *dev, u8 query,
> > u8
> > unit, u8 intfnum, u8 cs, void *data, u16 size)
> > 
> >  {
> >  
> > int ret;
> > 
> > +   u8 error;
> > +   u8 tmp;
> > 
> > ret = __uvc_query_ctrl(dev, query, unit, intfnum, cs, data, size,
> > 
> > UVC_CTRL_CONTROL_TIMEOUT);
> > 
> > -   if (ret != size) {
> > -   uvc_printk(KERN_ERR, "Failed to query (%s) UVC control %u on "
> > -   "unit %u: %d (exp. %u).\n", uvc_query_name(query), cs,
> > -   unit, ret, size);
> > -   return -EIO;
> > +   if (likely(ret == size))
> > +   return 0;
> > +
> > +   uvc_printk(KERN_ERR,
> > +  "Failed to query (%s) UVC control %u on unit %u: %d (exp. 
> > %u).
\n",
> > +  uvc_query_name(query), cs, unit, ret, size);
> > +
> > +   if (ret != -EPIPE)
> > +   return ret;
> > +
> > +   tmp = *(u8 *)data;
> > +
> > +   ret = __uvc_query_ctrl(dev, UVC_GET_CUR, 0, intfnum,
> > +  UVC_VC_REQUEST_ERROR_CODE_CONTROL, data, 1,
> > +  UVC_CTRL_CONTROL_TIMEOUT);
> > +
> > +   error = *(u8 *)data;
> > +   *(u8 *)data = tmp;
> > +
> > +   if (ret != 1)
> > +   return ret < 0 ? ret : -EPIPE;
> > +
> > +   uvc_trace(UVC_TRACE_CONTROL, "Control error %u\n", error);
> > +
> > +   switch (error) {
> > +   case 0:
> > +   /* Cannot happen - we received a STALL */
> > +   return -EPIPE;
> > +   case 1: /* Not ready */
> > +   return -EBUSY;
> > +   case 2: /* Wrong state */
> > +   return -EILSEQ;
> > +   case 3: /* Power */
> > +   return -EREMOTE;
> > +   case 4: /* Out of range */
> > +   return -ERANGE;
> > +   case 5: /* Invalid unit */
> > +   case 6: /* Invalid control */
> > +   case 7: /* Invalid Request */
> > +   case 8: /* Invalid value within range */
> > +   return -EINVAL;
> > +   default: /* reserved or unknown */
> > +   break;
> > 
> > }
> > 
> > -   return 0;
> > +   return -EPIPE;
> > 
> >  }
> >  
> >  static void uvc_fixup_video_ctrl(struct uvc_streaming *stream,


-- 
Regards,

Laurent Pinchart





[PATCH v4l-utils] ir-ctl: make nec32 scancode encoding match kernel

2018-07-17 Thread Sean Young
For the nec32 encoding, the kernel swaps in the "inverted" and normal
address and command. This might not be the most logical scheme.

Signed-off-by: Sean Young 
---
 utils/common/ir-encode.c | 9 ++---
 1 file changed, 2 insertions(+), 7 deletions(-)

diff --git a/utils/common/ir-encode.c b/utils/common/ir-encode.c
index c7e319eb..ccc75032 100644
--- a/utils/common/ir-encode.c
+++ b/utils/common/ir-encode.c
@@ -64,15 +64,10 @@ static int nec_encode(enum rc_proto proto, unsigned 
scancode, unsigned *buf)
add_byte(~scancode);
break;
case RC_PROTO_NEC32:
-   /*
-* At the time of writing kernel software nec decoder
-* reverses the bit order so it will not match. Hardware
-* decoders do not have this issue.
-*/
-   add_byte(scancode >> 24);
add_byte(scancode >> 16);
-   add_byte(scancode >> 8);
+   add_byte(scancode >> 24);
add_byte(scancode);
+   add_byte(scancode >> 8);
break;
}
 
-- 
2.11.0



[PATCH 2/2] media: rc: self test for IR encoders and decoders

2018-07-17 Thread Sean Young
ir-loopback can transmit IR on one rc device and check the correct
scancode and protocol is decoded on a different rc device. This can be
used to check IR transmission between two rc devices. Using rc-loopback,
we use it to check the IR encoders and decoders themselves.

Signed-off-by: Sean Young 
---
 tools/testing/selftests/Makefile  |   1 +
 tools/testing/selftests/ir/.gitignore |   1 +
 tools/testing/selftests/ir/Makefile   |  19 ++
 tools/testing/selftests/ir/config |  12 ++
 tools/testing/selftests/ir/ir-loopback.c  | 209 ++
 tools/testing/selftests/ir/ir-loopback.sh |  28 +++
 6 files changed, 270 insertions(+)
 create mode 100644 tools/testing/selftests/ir/.gitignore
 create mode 100644 tools/testing/selftests/ir/Makefile
 create mode 100644 tools/testing/selftests/ir/config
 create mode 100644 tools/testing/selftests/ir/ir-loopback.c
 create mode 100755 tools/testing/selftests/ir/ir-loopback.sh

diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile
index f1fe492c8e17..995034ea5546 100644
--- a/tools/testing/selftests/Makefile
+++ b/tools/testing/selftests/Makefile
@@ -15,6 +15,7 @@ TARGETS += futex
 TARGETS += gpio
 TARGETS += intel_pstate
 TARGETS += ipc
+TARGETS += ir
 TARGETS += kcmp
 TARGETS += kvm
 TARGETS += lib
diff --git a/tools/testing/selftests/ir/.gitignore 
b/tools/testing/selftests/ir/.gitignore
new file mode 100644
index ..87bf2989b678
--- /dev/null
+++ b/tools/testing/selftests/ir/.gitignore
@@ -0,0 +1 @@
+ir-loopback
diff --git a/tools/testing/selftests/ir/Makefile 
b/tools/testing/selftests/ir/Makefile
new file mode 100644
index ..501b464e56b5
--- /dev/null
+++ b/tools/testing/selftests/ir/Makefile
@@ -0,0 +1,19 @@
+# SPDX-License-Identifier: GPL-2.0
+uname_M := $(shell uname -m 2>/dev/null || echo not)
+ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/i386/)
+ifeq ($(ARCH),i386)
+ARCH := x86
+   CFLAGS := -DCONFIG_X86_32 -D__i386__
+endif
+ifeq ($(ARCH),x86_64)
+   ARCH := x86
+   CFLAGS := -DCONFIG_X86_64 -D__x86_64__
+endif
+
+CFLAGS += -I../../../../usr/include/
+
+TEST_PROGS := ir-loopback.sh
+
+TEST_GEN_PROGS := ir-loopback
+
+include ../lib.mk
diff --git a/tools/testing/selftests/ir/config 
b/tools/testing/selftests/ir/config
new file mode 100644
index ..78e041e9319e
--- /dev/null
+++ b/tools/testing/selftests/ir/config
@@ -0,0 +1,12 @@
+CONFIG_RC_CORE=y
+CONFIG_RC_LOOPBACK=y
+CONFIG_IR_NEC_DECODER=m
+CONFIG_IR_RC5_DECODER=m
+CONFIG_IR_RC6_DECODER=m
+CONFIG_IR_JVC_DECODER=m
+CONFIG_IR_SONY_DECODER=m
+CONFIG_IR_SANYO_DECODER=m
+CONFIG_IR_SHARP_DECODER=m
+CONFIG_IR_MCE_KBD_DECODER=m
+CONFIG_IR_XMP_DECODER=m
+CONFIG_IR_IMON_DECODER=m
diff --git a/tools/testing/selftests/ir/ir-loopback.c 
b/tools/testing/selftests/ir/ir-loopback.c
new file mode 100644
index ..95b6f0f2f1f5
--- /dev/null
+++ b/tools/testing/selftests/ir/ir-loopback.c
@@ -0,0 +1,209 @@
+// SPDX-License-Identifier: GPL-2.0
+// test ir decoder
+//
+// Copyright (C) 2018 Sean Young 
+
+// When sending LIRC_MODE_SCANCODE, the IR will be encoded. rc-loopback
+// will send this IR to the receiver side, where we try to read the decoded
+// IR. Decoding happens in a separate kernel thread, so we will need to
+// wait until that is scheduled, hence we use poll to check for read
+// readiness.
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define TEST_SCANCODES 10
+#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+
+static const struct {
+   enum rc_proto proto;
+   const char *name;
+   unsigned int mask;
+   const char *decoder;
+} protocols[] = {
+   { RC_PROTO_RC5, "rc-5", 0x1f7f, "rc-5" },
+   { RC_PROTO_RC5X_20, "rc-5x-20", 0x1f7f3f, "rc-5" },
+   { RC_PROTO_RC5_SZ, "rc-5-sz", 0x2fff, "rc-5-sz" },
+   { RC_PROTO_JVC, "jvc", 0x, "jvc" },
+   { RC_PROTO_SONY12, "sony-12", 0x1f007f, "sony" },
+   { RC_PROTO_SONY15, "sony-15", 0xff007f, "sony" },
+   { RC_PROTO_SONY20, "sony-20", 0x1fff7f, "sony" },
+   { RC_PROTO_NEC, "nec", 0x, "nec" },
+   { RC_PROTO_NECX, "nec-x", 0xff, "nec" },
+   { RC_PROTO_NEC32, "nec-32", 0x, "nec" },
+   { RC_PROTO_SANYO, "sanyo", 0x1f, "sanyo" },
+   { RC_PROTO_RC6_0, "rc-6-0", 0x, "rc-6" },
+   { RC_PROTO_RC6_6A_20, "rc-6-6a-20", 0xf, "rc-6" },
+   { RC_PROTO_RC6_6A_24, "rc-6-6a-24", 0xff, "rc-6" },
+   { RC_PROTO_RC6_6A_32, "rc-6-6a-32", 0x, "rc-6" },
+   { RC_PROTO_RC6_MCE, "rc-6-mce", 0x7fff, "rc-6" },
+   { RC_PROTO_SHARP, "sharp", 0x1fff, "sharp" },
+};
+
+int lirc_open(const char *rc)
+{
+   struct dirent *dent;
+   char buf[100];
+   DIR *d;
+   int fd;
+
+   snprintf(buf, sizeof(buf), "/sys/class/rc/%s", rc);
+
+   d = opendir(buf);
+   if (!d) {
+   prin

[PATCH 1/2] media: rc: nec keymaps should specify the nec variant they use

2018-07-17 Thread Sean Young
The rc_proto field should list the exact variant used by the remote. This
does not change the decoder used, but helps with using keymaps for
transmit purposes.

Signed-off-by: Sean Young 
---
 drivers/media/rc/keymaps/rc-behold.c  | 2 +-
 drivers/media/rc/keymaps/rc-delock-61959.c| 2 +-
 drivers/media/rc/keymaps/rc-imon-rsc.c| 2 +-
 drivers/media/rc/keymaps/rc-it913x-v1.c   | 2 +-
 drivers/media/rc/keymaps/rc-it913x-v2.c   | 2 +-
 drivers/media/rc/keymaps/rc-msi-digivox-iii.c | 2 +-
 drivers/media/rc/keymaps/rc-pixelview-002t.c  | 2 +-
 drivers/media/rc/keymaps/rc-pixelview-mk12.c  | 2 +-
 drivers/media/rc/keymaps/rc-reddo.c   | 2 +-
 drivers/media/rc/keymaps/rc-terratec-slim.c   | 2 +-
 drivers/media/rc/keymaps/rc-tivo.c| 2 +-
 drivers/media/rc/keymaps/rc-total-media-in-hand.c | 2 +-
 12 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/drivers/media/rc/keymaps/rc-behold.c 
b/drivers/media/rc/keymaps/rc-behold.c
index 9b1b57e3c875..e1b2c8e26883 100644
--- a/drivers/media/rc/keymaps/rc-behold.c
+++ b/drivers/media/rc/keymaps/rc-behold.c
@@ -115,7 +115,7 @@ static struct rc_map_list behold_map = {
.map = {
.scan = behold,
.size = ARRAY_SIZE(behold),
-   .rc_proto = RC_PROTO_NEC,
+   .rc_proto = RC_PROTO_NECX,
.name = RC_MAP_BEHOLD,
}
 };
diff --git a/drivers/media/rc/keymaps/rc-delock-61959.c 
b/drivers/media/rc/keymaps/rc-delock-61959.c
index 62de69d78d92..da21d6d6d79f 100644
--- a/drivers/media/rc/keymaps/rc-delock-61959.c
+++ b/drivers/media/rc/keymaps/rc-delock-61959.c
@@ -60,7 +60,7 @@ static struct rc_map_list delock_61959_map = {
.map = {
.scan = delock_61959,
.size = ARRAY_SIZE(delock_61959),
-   .rc_proto = RC_PROTO_NEC,
+   .rc_proto = RC_PROTO_NECX,
.name = RC_MAP_DELOCK_61959,
}
 };
diff --git a/drivers/media/rc/keymaps/rc-imon-rsc.c 
b/drivers/media/rc/keymaps/rc-imon-rsc.c
index 83e4564aaa22..6f7ee4859682 100644
--- a/drivers/media/rc/keymaps/rc-imon-rsc.c
+++ b/drivers/media/rc/keymaps/rc-imon-rsc.c
@@ -59,7 +59,7 @@ static struct rc_map_list imon_rsc_map = {
.map = {
.scan = imon_rsc,
.size = ARRAY_SIZE(imon_rsc),
-   .rc_proto = RC_PROTO_NEC,
+   .rc_proto = RC_PROTO_NECX,
.name = RC_MAP_IMON_RSC,
}
 };
diff --git a/drivers/media/rc/keymaps/rc-it913x-v1.c 
b/drivers/media/rc/keymaps/rc-it913x-v1.c
index 908d14848ae8..f1b5c52953ad 100644
--- a/drivers/media/rc/keymaps/rc-it913x-v1.c
+++ b/drivers/media/rc/keymaps/rc-it913x-v1.c
@@ -73,7 +73,7 @@ static struct rc_map_list it913x_v1_map = {
.map = {
.scan = it913x_v1_rc,
.size = ARRAY_SIZE(it913x_v1_rc),
-   .rc_proto = RC_PROTO_NEC,
+   .rc_proto = RC_PROTO_NECX,
.name = RC_MAP_IT913X_V1,
}
 };
diff --git a/drivers/media/rc/keymaps/rc-it913x-v2.c 
b/drivers/media/rc/keymaps/rc-it913x-v2.c
index 05ab7fa4f90b..be5dfb4fae46 100644
--- a/drivers/media/rc/keymaps/rc-it913x-v2.c
+++ b/drivers/media/rc/keymaps/rc-it913x-v2.c
@@ -72,7 +72,7 @@ static struct rc_map_list it913x_v2_map = {
.map = {
.scan = it913x_v2_rc,
.size = ARRAY_SIZE(it913x_v2_rc),
-   .rc_proto = RC_PROTO_NEC,
+   .rc_proto = RC_PROTO_NECX,
.name = RC_MAP_IT913X_V2,
}
 };
diff --git a/drivers/media/rc/keymaps/rc-msi-digivox-iii.c 
b/drivers/media/rc/keymaps/rc-msi-digivox-iii.c
index 8fec0c1dcb12..d50e741c73b7 100644
--- a/drivers/media/rc/keymaps/rc-msi-digivox-iii.c
+++ b/drivers/media/rc/keymaps/rc-msi-digivox-iii.c
@@ -64,7 +64,7 @@ static struct rc_map_list msi_digivox_iii_map = {
.map = {
.scan = msi_digivox_iii,
.size = ARRAY_SIZE(msi_digivox_iii),
-   .rc_proto = RC_PROTO_NEC,
+   .rc_proto = RC_PROTO_NECX,
.name = RC_MAP_MSI_DIGIVOX_III,
}
 };
diff --git a/drivers/media/rc/keymaps/rc-pixelview-002t.c 
b/drivers/media/rc/keymaps/rc-pixelview-002t.c
index 4ed85f61d0ee..c0550e09f255 100644
--- a/drivers/media/rc/keymaps/rc-pixelview-002t.c
+++ b/drivers/media/rc/keymaps/rc-pixelview-002t.c
@@ -51,7 +51,7 @@ static struct rc_map_list pixelview_map = {
.map = {
.scan = pixelview_002t,
.size = ARRAY_SIZE(pixelview_002t),
-   .rc_proto = RC_PROTO_NEC,
+   .rc_proto = RC_PROTO_NECX,
.name = RC_MAP_PIXELVIEW_002T,
}
 };
diff --git a/drivers/media/rc/keymaps/rc-pixelview-mk12.c 
b/drivers/media/rc/keymaps/rc-pixelview-mk12.c
index 6ded64b732a5..864c8ea5d8e3 100644
--- a/drivers/media/rc/keyma

Re: [PATCH v8 2/3] uvcvideo: send a control event when a Control Change interrupt arrives

2018-07-17 Thread Guennadi Liakhovetski
On Tue, 17 Jul 2018, Laurent Pinchart wrote:

> Hi Guennadi,
> 
> On Thursday, 12 July 2018 10:30:46 EEST Guennadi Liakhovetski wrote:
> > On Thu, 12 Jul 2018, Laurent Pinchart wrote:
> > > On Tuesday, 8 May 2018 18:07:43 EEST Guennadi Liakhovetski wrote:
> > >> UVC defines a method of handling asynchronous controls, which sends a
> > >> USB packet over the interrupt pipe. This patch implements support for
> > >> such packets by sending a control event to the user. Since this can
> > >> involve USB traffic and, therefore, scheduling, this has to be done
> > >> in a work queue.
> > >> 
> > >> Signed-off-by: Guennadi Liakhovetski 
> > >> ---
> > >> 
> > >> v8:
> > >> 
> > >> * avoid losing events by delaying the status URB resubmission until
> > >>   after completion of the current event
> > >> * extract control value calculation into __uvc_ctrl_get_value()
> > >> * do not proactively return EBUSY if the previous control hasn't
> > >>   completed yet, let the camera handle such cases
> > >> * multiple cosmetic changes
> > >> 
> > >>  drivers/media/usb/uvc/uvc_ctrl.c   | 166 ---
> > >>  drivers/media/usb/uvc/uvc_status.c | 112 ++---
> > >>  drivers/media/usb/uvc/uvc_v4l2.c   |   4 +-
> > >>  drivers/media/usb/uvc/uvcvideo.h   |  15 +++-
> > >>  include/uapi/linux/uvcvideo.h  |   2 +
> > >>  5 files changed, 255 insertions(+), 44 deletions(-)
> > >> 
> > >> diff --git a/drivers/media/usb/uvc/uvc_ctrl.c
> > >> b/drivers/media/usb/uvc/uvc_ctrl.c index 2a213c8..796f86a 100644
> > >> --- a/drivers/media/usb/uvc/uvc_ctrl.c
> > >> +++ b/drivers/media/usb/uvc/uvc_ctrl.c
> > 
> > [snip]
> > 
> > >> +static void uvc_ctrl_status_event_work(struct work_struct *work)
> > >> +{
> > >> +struct uvc_device *dev = container_of(work, struct uvc_device,
> > >> +  async_ctrl.work);
> > >> +struct uvc_ctrl_work *w = &dev->async_ctrl;
> > >> +struct uvc_control_mapping *mapping;
> > >> +struct uvc_control *ctrl = w->ctrl;
> > >> +unsigned int i;
> > >> +int ret;
> > >> +
> > >> +mutex_lock(&w->chain->ctrl_mutex);
> > >> +
> > >> +list_for_each_entry(mapping, &ctrl->info.mappings, list) {
> > >> +s32 value = __uvc_ctrl_get_value(mapping, w->data);
> > >> +
> > >> +/*
> > >> + * So far none of the auto-update controls in the 
> > >> uvc_ctrls[]
> > >> + * table is mapped to a V4L control with slaves in the
> > >> + * uvc_ctrl_mappings[] list, so slave controls so far 
> > >> never have
> > >> + * handle == NULL, but this can change in the future
> > >> + */
> > >> +for (i = 0; i < ARRAY_SIZE(mapping->slave_ids); ++i) {
> > >> +if (!mapping->slave_ids[i])
> > >> +break;
> > >> +
> > >> +__uvc_ctrl_send_slave_event(ctrl->handle, 
> > >> w->chain,
> > >> +ctrl, 
> > >> mapping->slave_ids[i]);
> > >> +}
> > >> +
> > >> +uvc_ctrl_send_event(ctrl->handle, ctrl, mapping, value,
> > >> +V4L2_EVENT_CTRL_CH_VALUE);
> > >> +}
> > >> +
> > >> +mutex_unlock(&w->chain->ctrl_mutex);
> > >> +
> > >> +ctrl->handle = NULL;
> > > 
> > > Can't this race with a uvc_ctrl_set() call, resulting in ctrl->handle
> > > being NULL after the control gets set ?
> > 
> > Right, it's better to set .handle to NULL before sending events. Something
> > like
> > 
> > mutex_lock();
> > 
> > handle = ctrl->handle;
> > ctrl->handle = NULL;
> > 
> > list_for_each_entry() {
> > ...
> > uvc_ctrl_send_event(handle,...);
> > }
> > 
> > mutex_unlock();
> > 
> > ?
> 
> I think you also have to take the same lock in the uvc_ctrl_set() function to 
> fix the problem, otherwise the ctrl->handle = NULL line could still be 
> executed after the ctrl->handle assignment in uvc_ctrl_set(), resulting in 
> ctrl->handle being NULL while the control is being set.

Doesn't this mean, that you're attempting to send a new instance of the 
same control before the previous has completed? In which case also taking 
the lock in uvc_ctrl_set() wouldn't help either, because you can anyway do 
that immediately after the first instance, before the completion even has 
fired.

> > >> +/* Resubmit the URB. */
> > >> +w->urb->interval = dev->int_ep->desc.bInterval;
> > >> +ret = usb_submit_urb(w->urb, GFP_KERNEL);
> > >> +if (ret < 0)
> > >> +uvc_printk(KERN_ERR, "Failed to resubmit status URB 
> > >> (%d).\n",
> > >> +   ret);
> > >> +}
> 
> [snip]
> 
> > >> diff --git a/drivers/media/usb/uvc/uvc_status.c
> > >> b/drivers/media/usb/uvc/uvc_status.c index 7b71041..a0f2fea 100644
> > >> --- a/drivers/media/usb/uvc/uvc_status.c

[GIT PULL for 4.19] More sensor and rcar-vin driver patches

2018-07-17 Thread Sakari Ailus
Hi Mauro,

Here's another bunch of sensor and rcar-vin driver patches for 4.19. Apart
from the driver- and device-only patches, there's a definition of the
data-enable-active property in video-interfaces.txt as well as a patch that
replaces "sensor-level" in Kconfig documentation by "sensor" in sensor
driver descriptions.

Please pull.


The following changes since commit 39fbb88165b2bbbc77ea7acab5f10632a31526e6:

  media: bpf: ensure bpf program is freed on detach (2018-07-13 11:07:29 -0400)

are available in the git repository at:

  ssh://linuxtv.org/git/sailus/media_tree.git for-4.19-3

for you to fetch changes up to 291af76ffa482649dcce77f4aeac139cb806ab0b:

  v4l: i2c: Replace "sensor-level" by "sensor" (2018-07-17 17:27:40 +0300)


Hugues Fruchet (1):
  media: ov5640: do not change mode if format or frame interval is unchanged

Jacopo Mondi (7):
  dt-bindings: media: rcar-vin: Align Gen2 and Gen3
  dt-bindings: media: rcar-vin: Describe optional ep properties
  dt-bindings: media: Document data-enable-active property
  media: v4l2-fwnode: parse 'data-enable-active' prop
  dt-bindings: media: rcar-vin: Add 'data-enable-active'
  media: rcar-vin: Handle data-enable polarity
  media: i2c: ov7670: Put ep fwnode after use

Luca Ceresoli (1):
  media: smiapp: fix debug message

Sakari Ailus (2):
  smiapp: Set correct MODULE_LICENSE
  v4l: i2c: Replace "sensor-level" by "sensor"

Todor Tomov (1):
  media: ov5645: Supported external clock is 24MHz

 .../devicetree/bindings/media/rcar_vin.txt | 29 --
 .../devicetree/bindings/media/video-interfaces.txt |  2 +
 drivers/media/i2c/Kconfig  | 62 +++---
 drivers/media/i2c/ov5640.c | 14 +++--
 drivers/media/i2c/ov5645.c | 13 ++---
 drivers/media/i2c/ov7670.c |  6 +--
 drivers/media/i2c/smiapp/smiapp-core.c |  4 +-
 drivers/media/platform/rcar-vin/rcar-dma.c |  5 ++
 drivers/media/v4l2-core/v4l2-fwnode.c  |  4 ++
 include/media/v4l2-mediabus.h  |  2 +
 10 files changed, 89 insertions(+), 52 deletions(-)

-- 
Sakari Ailus
e-mail: sakari.ai...@iki.fi


Re: [PATCH v8 3/3] uvcvideo: handle control pipe protocol STALLs

2018-07-17 Thread Laurent Pinchart
Hi Guennadi,

Thank you for the patch.

On Tuesday, 8 May 2018 18:07:44 EEST Guennadi Liakhovetski wrote:
> When a command ends up in a STALL on the control pipe, use the Request
> Error Code control to provide a more precise error information to the
> user. For example, if a camera is still busy processing a control,
> when the same or an interrelated control set request arrives, the
> camera can react with a STALL and then return the "Not ready" status
> in response to a UVC_VC_REQUEST_ERROR_CODE_CONTROL command. With this
> patch the user would then get an EBUSY error code instead of a
> generic EPIPE.
> 
> Signed-off-by: Guennadi Liakhovetski 

Reviewed-by: Laurent Pinchart 

> ---
> 
> v8:
> 
> * restrict UVC_VC_REQUEST_ERROR_CODE_CONTROL to the control interface
> * fix the wIndex value
> * improve error codes
> * cosmetic changes
> 
>  drivers/media/usb/uvc/uvc_video.c | 52 +++-
>  1 file changed, 46 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/media/usb/uvc/uvc_video.c
> b/drivers/media/usb/uvc/uvc_video.c index aa0082f..ce65cd6 100644
> --- a/drivers/media/usb/uvc/uvc_video.c
> +++ b/drivers/media/usb/uvc/uvc_video.c
> @@ -73,17 +73,57 @@ int uvc_query_ctrl(struct uvc_device *dev, u8 query, u8
> unit, u8 intfnum, u8 cs, void *data, u16 size)
>  {
>   int ret;
> + u8 error;
> + u8 tmp;
> 
>   ret = __uvc_query_ctrl(dev, query, unit, intfnum, cs, data, size,
>   UVC_CTRL_CONTROL_TIMEOUT);
> - if (ret != size) {
> - uvc_printk(KERN_ERR, "Failed to query (%s) UVC control %u on "
> - "unit %u: %d (exp. %u).\n", uvc_query_name(query), cs,
> - unit, ret, size);
> - return -EIO;
> + if (likely(ret == size))
> + return 0;
> +
> + uvc_printk(KERN_ERR,
> +"Failed to query (%s) UVC control %u on unit %u: %d (exp. 
> %u).\n",
> +uvc_query_name(query), cs, unit, ret, size);
> +
> + if (ret != -EPIPE)
> + return ret;
> +
> + tmp = *(u8 *)data;
> +
> + ret = __uvc_query_ctrl(dev, UVC_GET_CUR, 0, intfnum,
> +UVC_VC_REQUEST_ERROR_CODE_CONTROL, data, 1,
> +UVC_CTRL_CONTROL_TIMEOUT);
> +
> + error = *(u8 *)data;
> + *(u8 *)data = tmp;
> +
> + if (ret != 1)
> + return ret < 0 ? ret : -EPIPE;
> +
> + uvc_trace(UVC_TRACE_CONTROL, "Control error %u\n", error);
> +
> + switch (error) {
> + case 0:
> + /* Cannot happen - we received a STALL */
> + return -EPIPE;
> + case 1: /* Not ready */
> + return -EBUSY;
> + case 2: /* Wrong state */
> + return -EILSEQ;
> + case 3: /* Power */
> + return -EREMOTE;
> + case 4: /* Out of range */
> + return -ERANGE;
> + case 5: /* Invalid unit */
> + case 6: /* Invalid control */
> + case 7: /* Invalid Request */
> + case 8: /* Invalid value within range */
> + return -EINVAL;
> + default: /* reserved or unknown */
> + break;
>   }
> 
> - return 0;
> + return -EPIPE;
>  }
> 
>  static void uvc_fixup_video_ctrl(struct uvc_streaming *stream,

-- 
Regards,

Laurent Pinchart





Re: [PATCH v8 2/3] uvcvideo: send a control event when a Control Change interrupt arrives

2018-07-17 Thread Laurent Pinchart
Hi Guennadi,

On Thursday, 12 July 2018 10:30:46 EEST Guennadi Liakhovetski wrote:
> On Thu, 12 Jul 2018, Laurent Pinchart wrote:
> > On Tuesday, 8 May 2018 18:07:43 EEST Guennadi Liakhovetski wrote:
> >> UVC defines a method of handling asynchronous controls, which sends a
> >> USB packet over the interrupt pipe. This patch implements support for
> >> such packets by sending a control event to the user. Since this can
> >> involve USB traffic and, therefore, scheduling, this has to be done
> >> in a work queue.
> >> 
> >> Signed-off-by: Guennadi Liakhovetski 
> >> ---
> >> 
> >> v8:
> >> 
> >> * avoid losing events by delaying the status URB resubmission until
> >>   after completion of the current event
> >> * extract control value calculation into __uvc_ctrl_get_value()
> >> * do not proactively return EBUSY if the previous control hasn't
> >>   completed yet, let the camera handle such cases
> >> * multiple cosmetic changes
> >> 
> >>  drivers/media/usb/uvc/uvc_ctrl.c   | 166 ---
> >>  drivers/media/usb/uvc/uvc_status.c | 112 ++---
> >>  drivers/media/usb/uvc/uvc_v4l2.c   |   4 +-
> >>  drivers/media/usb/uvc/uvcvideo.h   |  15 +++-
> >>  include/uapi/linux/uvcvideo.h  |   2 +
> >>  5 files changed, 255 insertions(+), 44 deletions(-)
> >> 
> >> diff --git a/drivers/media/usb/uvc/uvc_ctrl.c
> >> b/drivers/media/usb/uvc/uvc_ctrl.c index 2a213c8..796f86a 100644
> >> --- a/drivers/media/usb/uvc/uvc_ctrl.c
> >> +++ b/drivers/media/usb/uvc/uvc_ctrl.c
> 
> [snip]
> 
> >> +static void uvc_ctrl_status_event_work(struct work_struct *work)
> >> +{
> >> +  struct uvc_device *dev = container_of(work, struct uvc_device,
> >> +async_ctrl.work);
> >> +  struct uvc_ctrl_work *w = &dev->async_ctrl;
> >> +  struct uvc_control_mapping *mapping;
> >> +  struct uvc_control *ctrl = w->ctrl;
> >> +  unsigned int i;
> >> +  int ret;
> >> +
> >> +  mutex_lock(&w->chain->ctrl_mutex);
> >> +
> >> +  list_for_each_entry(mapping, &ctrl->info.mappings, list) {
> >> +  s32 value = __uvc_ctrl_get_value(mapping, w->data);
> >> +
> >> +  /*
> >> +   * So far none of the auto-update controls in the uvc_ctrls[]
> >> +   * table is mapped to a V4L control with slaves in the
> >> +   * uvc_ctrl_mappings[] list, so slave controls so far never have
> >> +   * handle == NULL, but this can change in the future
> >> +   */
> >> +  for (i = 0; i < ARRAY_SIZE(mapping->slave_ids); ++i) {
> >> +  if (!mapping->slave_ids[i])
> >> +  break;
> >> +
> >> +  __uvc_ctrl_send_slave_event(ctrl->handle, w->chain,
> >> +  ctrl, mapping->slave_ids[i]);
> >> +  }
> >> +
> >> +  uvc_ctrl_send_event(ctrl->handle, ctrl, mapping, value,
> >> +  V4L2_EVENT_CTRL_CH_VALUE);
> >> +  }
> >> +
> >> +  mutex_unlock(&w->chain->ctrl_mutex);
> >> +
> >> +  ctrl->handle = NULL;
> > 
> > Can't this race with a uvc_ctrl_set() call, resulting in ctrl->handle
> > being NULL after the control gets set ?
> 
> Right, it's better to set .handle to NULL before sending events. Something
> like
> 
> mutex_lock();
> 
> handle = ctrl->handle;
> ctrl->handle = NULL;
> 
> list_for_each_entry() {
>   ...
>   uvc_ctrl_send_event(handle,...);
> }
> 
> mutex_unlock();
> 
> ?

I think you also have to take the same lock in the uvc_ctrl_set() function to 
fix the problem, otherwise the ctrl->handle = NULL line could still be 
executed after the ctrl->handle assignment in uvc_ctrl_set(), resulting in 
ctrl->handle being NULL while the control is being set.

> >> +  /* Resubmit the URB. */
> >> +  w->urb->interval = dev->int_ep->desc.bInterval;
> >> +  ret = usb_submit_urb(w->urb, GFP_KERNEL);
> >> +  if (ret < 0)
> >> +  uvc_printk(KERN_ERR, "Failed to resubmit status URB (%d).\n",
> >> + ret);
> >> +}

[snip]

> >> diff --git a/drivers/media/usb/uvc/uvc_status.c
> >> b/drivers/media/usb/uvc/uvc_status.c index 7b71041..a0f2fea 100644
> >> --- a/drivers/media/usb/uvc/uvc_status.c
> >> +++ b/drivers/media/usb/uvc/uvc_status.c

[snip]

> >> +static struct uvc_control *uvc_event_find_ctrl(struct uvc_device *dev,
> >> +  const struct uvc_control_status *status,
> >> +  struct uvc_video_chain **chain)
> >> +{
> >> +  list_for_each_entry((*chain), &dev->chains, list) {
> >> +  struct uvc_entity *entity;
> >> +  struct uvc_control *ctrl;
> >> +
> >> +  list_for_each_entry(entity, &(*chain)->entities, chain) {
> >> +  if (entity->id != status->bOriginator)
> >> +  continue;
> >> +
> >> +  ctrl = uvc_event_entity_find_ctrl(entity,
> >> +status->bSelector);
> >> +  if (ctrl &

the photo studio

2018-07-17 Thread Ruby

We have got a team of professional to do image editing service for you.

We have 20 image editors and on daily basis 2000 images can be processed.

If you want to check our quality of work please send us a photo with
instruction and we will work on it.

Our Services:
Photo cut out, masking, clipping path
Color, brightness and contrast correction
Beauty, Model retouching, skin retouching
Image cropping and resizing
Correcting the shape and size

We do unlimited revisions until you are satisfied with the work.

Thanks,
Ruby Young



[PATCH 5/5] cec-gpio: support 5v testing

2018-07-17 Thread Hans Verkuil
From: Hans Verkuil 

Add support for the new (optional) 5V gpio in order to debug 5V
changes. Some displays turn off CEC if the 5V is not detected,
so it is useful to be able to monitor this line.

Signed-off-by: Hans Verkuil 
---
 drivers/media/platform/cec-gpio/cec-gpio.c | 54 ++
 1 file changed, 54 insertions(+)

diff --git a/drivers/media/platform/cec-gpio/cec-gpio.c 
b/drivers/media/platform/cec-gpio/cec-gpio.c
index 69f8242209c2..d2861749d640 100644
--- a/drivers/media/platform/cec-gpio/cec-gpio.c
+++ b/drivers/media/platform/cec-gpio/cec-gpio.c
@@ -23,6 +23,11 @@ struct cec_gpio {
int hpd_irq;
boolhpd_is_high;
ktime_t hpd_ts;
+
+   struct gpio_desc*v5_gpio;
+   int v5_irq;
+   boolv5_is_high;
+   ktime_t v5_ts;
 };
 
 static bool cec_gpio_read(struct cec_adapter *adap)
@@ -65,6 +70,26 @@ static irqreturn_t cec_hpd_gpio_irq_handler_thread(int irq, 
void *priv)
return IRQ_HANDLED;
 }
 
+static irqreturn_t cec_5v_gpio_irq_handler(int irq, void *priv)
+{
+   struct cec_gpio *cec = priv;
+   bool is_high = gpiod_get_value(cec->v5_gpio);
+
+   if (is_high == cec->v5_is_high)
+   return IRQ_HANDLED;
+   cec->v5_ts = ktime_get();
+   cec->v5_is_high = is_high;
+   return IRQ_WAKE_THREAD;
+}
+
+static irqreturn_t cec_5v_gpio_irq_handler_thread(int irq, void *priv)
+{
+   struct cec_gpio *cec = priv;
+
+   cec_queue_pin_5v_event(cec->adap, cec->v5_is_high, cec->v5_ts);
+   return IRQ_HANDLED;
+}
+
 static irqreturn_t cec_hpd_gpio_irq_handler(int irq, void *priv)
 {
struct cec_gpio *cec = priv;
@@ -119,6 +144,9 @@ static void cec_gpio_status(struct cec_adapter *adap, 
struct seq_file *file)
if (cec->hpd_gpio)
seq_printf(file, "hpd: %s\n",
   cec->hpd_is_high ? "high" : "low");
+   if (cec->v5_gpio)
+   seq_printf(file, "5V: %s\n",
+  cec->v5_is_high ? "high" : "low");
 }
 
 static int cec_gpio_read_hpd(struct cec_adapter *adap)
@@ -130,6 +158,15 @@ static int cec_gpio_read_hpd(struct cec_adapter *adap)
return gpiod_get_value(cec->hpd_gpio);
 }
 
+static int cec_gpio_read_5v(struct cec_adapter *adap)
+{
+   struct cec_gpio *cec = cec_get_drvdata(adap);
+
+   if (!cec->v5_gpio)
+   return -ENOTTY;
+   return gpiod_get_value(cec->v5_gpio);
+}
+
 static void cec_gpio_free(struct cec_adapter *adap)
 {
cec_gpio_disable_irq(adap);
@@ -144,6 +181,7 @@ static const struct cec_pin_ops cec_gpio_pin_ops = {
.status = cec_gpio_status,
.free = cec_gpio_free,
.read_hpd = cec_gpio_read_hpd,
+   .read_5v = cec_gpio_read_5v,
 };
 
 static int cec_gpio_probe(struct platform_device *pdev)
@@ -167,6 +205,10 @@ static int cec_gpio_probe(struct platform_device *pdev)
if (IS_ERR(cec->hpd_gpio))
return PTR_ERR(cec->hpd_gpio);
 
+   cec->v5_gpio = devm_gpiod_get_optional(dev, "v5", GPIOD_IN);
+   if (IS_ERR(cec->v5_gpio))
+   return PTR_ERR(cec->v5_gpio);
+
cec->adap = cec_pin_allocate_adapter(&cec_gpio_pin_ops,
cec, pdev->name, CEC_CAP_DEFAULTS | CEC_CAP_PHYS_ADDR |
 CEC_CAP_MONITOR_ALL | CEC_CAP_MONITOR_PIN);
@@ -185,6 +227,18 @@ static int cec_gpio_probe(struct platform_device *pdev)
return ret;
}
 
+   if (cec->v5_gpio) {
+   cec->v5_irq = gpiod_to_irq(cec->v5_gpio);
+   ret = devm_request_threaded_irq(dev, cec->v5_irq,
+   cec_5v_gpio_irq_handler,
+   cec_5v_gpio_irq_handler_thread,
+   IRQF_ONESHOT |
+   IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
+   "v5-gpio", cec);
+   if (ret)
+   return ret;
+   }
+
ret = cec_register_adapter(cec->adap, &pdev->dev);
if (ret) {
cec_delete_adapter(cec->adap);
-- 
2.18.0



[PATCH 2/5] cec-ioc-dqevent.rst: document the new 5V events

2018-07-17 Thread Hans Verkuil
From: Hans Verkuil 

Document the two new 5V events.

Signed-off-by: Hans Verkuil 
---
 .../media/uapi/cec/cec-ioc-dqevent.rst | 18 ++
 1 file changed, 18 insertions(+)

diff --git a/Documentation/media/uapi/cec/cec-ioc-dqevent.rst 
b/Documentation/media/uapi/cec/cec-ioc-dqevent.rst
index b6fd86424fbb..8d5633e6ae04 100644
--- a/Documentation/media/uapi/cec/cec-ioc-dqevent.rst
+++ b/Documentation/media/uapi/cec/cec-ioc-dqevent.rst
@@ -179,6 +179,24 @@ it is guaranteed that the state did change in between the 
two events.
capability set. When open() is called, the HPD pin can be read and
if the HPD is high, then an initial event will be generated for that
filehandle.
+* .. _`CEC-EVENT-PIN-5V-LOW`:
+
+  - ``CEC_EVENT_PIN_5V_LOW``
+  - 6
+  - Generated if the 5V pin goes from a high voltage to a low voltage.
+   Only applies to adapters that have the ``CEC_CAP_MONITOR_PIN``
+   capability set. When open() is called, the 5V pin can be read and
+   if the 5V is low, then an initial event will be generated for that
+   filehandle.
+* .. _`CEC-EVENT-PIN-5V-HIGH`:
+
+  - ``CEC_EVENT_PIN_5V_HIGH``
+  - 7
+  - Generated if the 5V pin goes from a low voltage to a high voltage.
+   Only applies to adapters that have the ``CEC_CAP_MONITOR_PIN``
+   capability set. When open() is called, the 5V pin can be read and
+   if the 5V is high, then an initial event will be generated for that
+   filehandle.
 
 
 .. tabularcolumns:: |p{6.0cm}|p{0.6cm}|p{10.9cm}|
-- 
2.18.0



[PATCH 1/5] cec-gpio.txt: add v5-gpios for testing the 5V line

2018-07-17 Thread Hans Verkuil
From: Hans Verkuil 

In order to debug the HDMI 5V line we need to add a new v5-gpios
property.

Signed-off-by: Hans Verkuil 
---
 .../devicetree/bindings/media/cec-gpio.txt  | 17 ++---
 1 file changed, 10 insertions(+), 7 deletions(-)

diff --git a/Documentation/devicetree/bindings/media/cec-gpio.txt 
b/Documentation/devicetree/bindings/media/cec-gpio.txt
index 12fcd55ed153..1d53ce89da74 100644
--- a/Documentation/devicetree/bindings/media/cec-gpio.txt
+++ b/Documentation/devicetree/bindings/media/cec-gpio.txt
@@ -4,8 +4,8 @@ The HDMI CEC GPIO module supports CEC implementations where the 
CEC line
 is hooked up to a pull-up GPIO line and - optionally - the HPD line is
 hooked up to another GPIO line.
 
-Please note: the maximum voltage for the CEC line is 3.63V, for the HPD
-line it is 5.3V. So you may need some sort of level conversion circuitry
+Please note: the maximum voltage for the CEC line is 3.63V, for the HPD and
+5V lines it is 5.3V. So you may need some sort of level conversion circuitry
 when connecting them to a GPIO line.
 
 Required properties:
@@ -22,15 +22,18 @@ If the CEC line is not associated with an HDMI 
receiver/transmitter, then
 the following property is optional:
 
   - hpd-gpios: gpio that the HPD line is connected to.
+  - v5-gpios: gpio that the 5V line is connected to.
 
 Example for the Raspberry Pi 3 where the CEC line is connected to
-pin 26 aka BCM7 aka CE1 on the GPIO pin header and the HPD line is
-connected to pin 11 aka BCM17 (some level shifter is needed for this!):
+pin 26 aka BCM7 aka CE1 on the GPIO pin header, the HPD line is
+connected to pin 11 aka BCM17 and the 5V line is connected to pin
+15 aka BCM22 (some level shifter is needed for the HPD and 5V lines!):
 
 #include 
 
 cec-gpio {
-   compatible = "cec-gpio";
-   cec-gpios = <&gpio 7 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>;
-   hpd-gpios = <&gpio 17 GPIO_ACTIVE_HIGH>;
+   compatible = "cec-gpio";
+   cec-gpios = <&gpio 7 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>;
+   hpd-gpios = <&gpio 17 GPIO_ACTIVE_HIGH>;
+   v5-gpios = <&gpio 22 GPIO_ACTIVE_HIGH>;
 };
-- 
2.18.0



[PATCH 0/5] cec/cec-gpio: add support for 5V testing

2018-07-17 Thread Hans Verkuil
From: Hans Verkuil 

Some displays disable CEC if the HDMI 5V is not detected. In order
to test issues related to this you want to be able to optionally
detect when the 5V line changes in the cec-gpio driver.

This patch series adds support for this feature.

Regards,

Hans

Hans Verkuil (5):
  cec-gpio.txt: add v5-gpios for testing the 5V line
  cec-ioc-dqevent.rst: document the new 5V events
  uapi/linux/cec.h: add 5V events
  cec: add support for 5V signal testing
  cec-gpio: support 5v testing

 .../devicetree/bindings/media/cec-gpio.txt| 17 +++---
 .../media/uapi/cec/cec-ioc-dqevent.rst| 18 +++
 drivers/media/cec/cec-adap.c  | 18 ++-
 drivers/media/cec/cec-api.c   |  8 +++
 drivers/media/platform/cec-gpio/cec-gpio.c| 54 +++
 include/media/cec-pin.h   |  4 ++
 include/media/cec.h   | 12 -
 include/uapi/linux/cec.h  |  2 +
 8 files changed, 124 insertions(+), 9 deletions(-)

-- 
2.18.0



[PATCH 3/5] uapi/linux/cec.h: add 5V events

2018-07-17 Thread Hans Verkuil
From: Hans Verkuil 

Add two new events to signal when the 5V line goes high or low.

Signed-off-by: Hans Verkuil 
---
 include/uapi/linux/cec.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/include/uapi/linux/cec.h b/include/uapi/linux/cec.h
index 20fe091b7e96..097fcd812471 100644
--- a/include/uapi/linux/cec.h
+++ b/include/uapi/linux/cec.h
@@ -384,6 +384,8 @@ struct cec_log_addrs {
 #define CEC_EVENT_PIN_CEC_HIGH 4
 #define CEC_EVENT_PIN_HPD_LOW  5
 #define CEC_EVENT_PIN_HPD_HIGH 6
+#define CEC_EVENT_PIN_5V_LOW   7
+#define CEC_EVENT_PIN_5V_HIGH  8
 
 #define CEC_EVENT_FL_INITIAL_STATE (1 << 0)
 #define CEC_EVENT_FL_DROPPED_EVENTS(1 << 1)
-- 
2.18.0



[PATCH 4/5] cec: add support for 5V signal testing

2018-07-17 Thread Hans Verkuil
From: Hans Verkuil 

Add support for the new 5V CEC events

Signed-off-by: Hans Verkuil 
---
 drivers/media/cec/cec-adap.c | 18 +-
 drivers/media/cec/cec-api.c  |  8 
 include/media/cec-pin.h  |  4 
 include/media/cec.h  | 12 +++-
 4 files changed, 40 insertions(+), 2 deletions(-)

diff --git a/drivers/media/cec/cec-adap.c b/drivers/media/cec/cec-adap.c
index b7fad0ec5710..030b2602faf0 100644
--- a/drivers/media/cec/cec-adap.c
+++ b/drivers/media/cec/cec-adap.c
@@ -74,7 +74,7 @@ void cec_queue_event_fh(struct cec_fh *fh,
const struct cec_event *new_ev, u64 ts)
 {
static const u16 max_events[CEC_NUM_EVENTS] = {
-   1, 1, 800, 800, 8, 8,
+   1, 1, 800, 800, 8, 8, 8, 8
};
struct cec_event_entry *entry;
unsigned int ev_idx = new_ev->event - 1;
@@ -176,6 +176,22 @@ void cec_queue_pin_hpd_event(struct cec_adapter *adap, 
bool is_high, ktime_t ts)
 }
 EXPORT_SYMBOL_GPL(cec_queue_pin_hpd_event);
 
+/* Notify userspace that the 5V pin changed state at the given time. */
+void cec_queue_pin_5v_event(struct cec_adapter *adap, bool is_high, ktime_t ts)
+{
+   struct cec_event ev = {
+   .event = is_high ? CEC_EVENT_PIN_5V_HIGH :
+  CEC_EVENT_PIN_5V_LOW,
+   };
+   struct cec_fh *fh;
+
+   mutex_lock(&adap->devnode.lock);
+   list_for_each_entry(fh, &adap->devnode.fhs, list)
+   cec_queue_event_fh(fh, &ev, ktime_to_ns(ts));
+   mutex_unlock(&adap->devnode.lock);
+}
+EXPORT_SYMBOL_GPL(cec_queue_pin_5v_event);
+
 /*
  * Queue a new message for this filehandle.
  *
diff --git a/drivers/media/cec/cec-api.c b/drivers/media/cec/cec-api.c
index 10b67fc40318..b6536bbad530 100644
--- a/drivers/media/cec/cec-api.c
+++ b/drivers/media/cec/cec-api.c
@@ -579,6 +579,14 @@ static int cec_open(struct inode *inode, struct file *filp)
cec_queue_event_fh(fh, &ev, 0);
}
}
+   if (adap->pin && adap->pin->ops->read_5v) {
+   err = adap->pin->ops->read_5v(adap);
+   if (err >= 0) {
+   ev.event = err ? CEC_EVENT_PIN_5V_HIGH :
+CEC_EVENT_PIN_5V_LOW;
+   cec_queue_event_fh(fh, &ev, 0);
+   }
+   }
 #endif
 
list_add(&fh->list, &devnode->fhs);
diff --git a/include/media/cec-pin.h b/include/media/cec-pin.h
index ed16c6dde0ba..604e79cb6cbf 100644
--- a/include/media/cec-pin.h
+++ b/include/media/cec-pin.h
@@ -25,6 +25,9 @@
  * @read_hpd:  read the HPD pin. Return true if high, false if low or
  * an error if negative. If NULL or -ENOTTY is returned,
  * then this is not supported.
+ * @read_5v:   read the 5V pin. Return true if high, false if low or
+ * an error if negative. If NULL or -ENOTTY is returned,
+ * then this is not supported.
  *
  * These operations are used by the cec pin framework to manipulate
  * the CEC pin.
@@ -38,6 +41,7 @@ struct cec_pin_ops {
void (*free)(struct cec_adapter *adap);
void (*status)(struct cec_adapter *adap, struct seq_file *file);
int  (*read_hpd)(struct cec_adapter *adap);
+   int  (*read_5v)(struct cec_adapter *adap);
 };
 
 /**
diff --git a/include/media/cec.h b/include/media/cec.h
index 580ab1042898..ff9847f7f99d 100644
--- a/include/media/cec.h
+++ b/include/media/cec.h
@@ -79,7 +79,7 @@ struct cec_event_entry {
 };
 
 #define CEC_NUM_CORE_EVENTS 2
-#define CEC_NUM_EVENTS CEC_EVENT_PIN_HPD_HIGH
+#define CEC_NUM_EVENTS CEC_EVENT_PIN_5V_HIGH
 
 struct cec_fh {
struct list_headlist;
@@ -308,6 +308,16 @@ void cec_queue_pin_cec_event(struct cec_adapter *adap, 
bool is_high,
  */
 void cec_queue_pin_hpd_event(struct cec_adapter *adap, bool is_high, ktime_t 
ts);
 
+/**
+ * cec_queue_pin_5v_event() - queue a pin event with a given timestamp.
+ *
+ * @adap:  pointer to the cec adapter
+ * @is_high:   when true the 5V pin is high, otherwise it is low
+ * @ts:the timestamp for this event
+ *
+ */
+void cec_queue_pin_5v_event(struct cec_adapter *adap, bool is_high, ktime_t 
ts);
+
 /**
  * cec_get_edid_phys_addr() - find and return the physical address
  *
-- 
2.18.0



Re: [PATCH v8 2/3] uvcvideo: send a control event when a Control Change interrupt arrives

2018-07-17 Thread Guennadi Liakhovetski
Hi Laurent,

On Thu, 12 Jul 2018, Guennadi Liakhovetski wrote:

> Hi Laurent,
> 
> Thanks for the review.

[snip]

> Once I get your review of patch #3, I'll fix these two issues and 
> resubmit, so you can also tell me your "minor concerns," since I'll be 
> resubmitting anyway.

Any progress on this?

Thanks
Guennadi


Re: [PATCHv6 02/12] media-ioc-g-topology.rst: document new 'index' field

2018-07-17 Thread Hans Verkuil
On 13/07/18 17:23, Mauro Carvalho Chehab wrote:
> Em Tue, 10 Jul 2018 10:45:02 +0200
> Hans Verkuil  escreveu:
> 
>> From: Hans Verkuil 
>>
>> Document the new struct media_v2_pad 'index' field.
>>
>> Signed-off-by: Hans Verkuil 
>> Acked-by: Sakari Ailus 
>> ---
>>  .../media/uapi/mediactl/media-ioc-g-topology.rst | 12 ++--
>>  1 file changed, 10 insertions(+), 2 deletions(-)
>>
>> diff --git a/Documentation/media/uapi/mediactl/media-ioc-g-topology.rst 
>> b/Documentation/media/uapi/mediactl/media-ioc-g-topology.rst
>> index a3f259f83b25..bae2b4db89cc 100644
>> --- a/Documentation/media/uapi/mediactl/media-ioc-g-topology.rst
>> +++ b/Documentation/media/uapi/mediactl/media-ioc-g-topology.rst
>> @@ -176,7 +176,7 @@ desired arrays with the media graph elements.
>>  *  -  struct media_v2_intf_devnode
>> -  ``devnode``
>> -  Used only for device node interfaces. See
>> -  :c:type:`media_v2_intf_devnode` for details..
>> +  :c:type:`media_v2_intf_devnode` for details.
>>  
>>  
>>  .. tabularcolumns:: |p{1.6cm}|p{3.2cm}|p{12.7cm}|
>> @@ -218,7 +218,15 @@ desired arrays with the media graph elements.
>> -  Pad flags, see :ref:`media-pad-flag` for more details.
>>  
>>  *  -  __u32
>> -   -  ``reserved``\ [5]
>> +   -  ``index``
>> +   -  Pad index, starts at 0. Only valid if 
>> ``MEDIA_V2_PAD_HAS_INDEX(media_version)``
>> +  returns true. The ``media_version`` is defined in struct
>> +  :c:type:`media_device_info` and can be retrieved using
>> +  :ref:`MEDIA_IOC_DEVICE_INFO`. Pad indices are stable. If new pads are 
>> added
>> +  for an entity in the future, then those will be added at the end.
> 
> Hmm... Pad indexes may not be stable. That's by the way why we
> need a better way to enum it, and the Properties API was thinking
> to solve (and why we didn't add PAD index to this ioctl at the
> first place). 
> 
> The problem happens for example on TV demods and tuners:
> different models may have different kinds of output PADs:
> 
>   - analog luminance carrier samples;
>   - analog chrominance sub-carrier samples;
>   - sliced VBI data;
>   - audio RF sub-carrier samples;
>   - audio mono data;
>   - audio stereo data.
> 
> The same bridge chip can live with different demods, but need to
> setup the pipelines according with the type of the PAD. As right now
> we don't have any way to associate a PAD with an specific type of
> output, what happens is that the V4L2 core associates a pad number
> with an specific type of output. So, drivers may be exposing
> PADs that don't exist, in practice, just to make them compatible
> with similar subdevs.
> 
> Once we add a properties API (or something equivalent), the
> PAD numbers will change and subdevs will only expose the ones
> that really exists.

So what do you suggest I do? There are two things here: you need the
pad index in order to use the SETUP_LINK ioctl, so adding this to
G_TOPOLOGY makes sense. The second is whether or not pad numbers
are stable. Currently they are, since there is no other way to
associate a pad with the type of signal it can carry.

Note that the index is already exposed with the older API, so changing
the pad index in the future will already potentially cause problems.

I am inclined to just remove the last two sentences of the description
above, so this becomes:

+   -  Pad index, starts at 0. Only valid if 
``MEDIA_V2_PAD_HAS_INDEX(media_version)``
+ returns true. The ``media_version`` is defined in struct
+ :c:type:`media_device_info` and can be retrieved using
+ :ref:`MEDIA_IOC_DEVICE_INFO`.

And we'll figure out what to do with this once we finally get properties.

That's something I might actually work on myself, but not before we get
the current API consistent.

Regards,

Hans


the editing

2018-07-17 Thread Ruby

We have got a team of professional to do image editing service for you.

We have 20 image editors and on daily basis 2000 images can be processed.

If you want to check our quality of work please send us a photo with
instruction and we will work on it.

Our Services:
Photo cut out, masking, clipping path
Color, brightness and contrast correction
Beauty, Model retouching, skin retouching
Image cropping and resizing
Correcting the shape and size

We do unlimited revisions until you are satisfied with the work.

Thanks,
Ruby Young



images work for you

2018-07-17 Thread Ruby

We have got a team of professional to do image editing service for you.

We have 20 image editors and on daily basis 2000 images can be processed.

If you want to check our quality of work please send us a photo with
instruction and we will work on it.

Our Services:
Photo cut out, masking, clipping path
Color, brightness and contrast correction
Beauty, Model retouching, skin retouching
Image cropping and resizing
Correcting the shape and size

We do unlimited revisions until you are satisfied with the work.

Thanks,
Ruby Young



images work for you

2018-07-17 Thread Ruby

We have got a team of professional to do image editing service for you.

We have 20 image editors and on daily basis 2000 images can be processed.

If you want to check our quality of work please send us a photo with
instruction and we will work on it.

Our Services:
Photo cut out, masking, clipping path
Color, brightness and contrast correction
Beauty, Model retouching, skin retouching
Image cropping and resizing
Correcting the shape and size

We do unlimited revisions until you are satisfied with the work.

Thanks,
Ruby Young