Re: controlling record light on camera

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Adam Wozniak wrote:
> so I know this is a "control output" message with "setup" values
> bmRequestType=21, bRequest=01, wValue=0900, wIndex=0700, wLength=0005
> and data of 01,0N,00,00,0a where N=1 for on and N=0 for off
>
> How would I send this same packet from a userspace application?

Install a libusb-1.0 API provider. I suggest libusb-1.0.9 because I
maintain libusb. I think the author of the kernel driver for your
camera works on the libusbx fork of libusb, so he will probably
suggest libusbx-1.0.12.

--8<-- test.c
/* build: gcc $(pkg-config --cflags --libs libusb-1.0) -o test test.c */

/* run:
 * ./test 0  # turns light off
 * ./test  # with non-zero parameter or without parameter turns light on
 */

#include <stdio.h>
#include <stdlib.h>
#include <libusb.h>

#define TIMEOUT_MS 1000 /* arbitrarily chosen millisecond timeout */

/* USB Video Class 1.1 documentation:
 * http://www.usb.org/developers/devclass_docs/USB_Video_Class_1_1_090711.zip
 */

#define UVC_SET_CUR 0x01 /* bRequest per USB Video Class 1.1 Table A-8 */
#define UVC_CS 0x09 /* See about wValue in USB Video Class 1.1 Table 4-4 */

int main(int argc, char *argv[]) {
  int ret = 1;
  libusb_device_handle *dh;
  unsigned char data[] = { 0x01, 0x01, 0x00, 0x00, 0x0a };

  if (libusb_init(NULL))
    return ret;

  dh = libusb_open_device_with_vid_pid(NULL, 0x046d, 0x0825);
  if (NULL == dh) {
    fprintf(stderr, "open vid:pid 046d:0825 failed\n");
    goto done;
  }

  if (argc > 1)
    data[1] = !!atoi(argv[1]);

  printf("Turning light %s now...\n", data[1] ? "on" : "off");
  fflush(stdout);

  ret = libusb_control_transfer(dh,
    LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE, /* 0x21 */
    UVC_SET_CUR, (UVC_CS << 8), 0x0700, data, sizeof(data), TIMEOUT_MS);

  if (ret) {
    fprintf(stderr, "libusb_control_transfer() returned %d\n", ret);
    goto done;
  }

  ret = 0;

done:
  if (dh)
    libusb_close(dh);
  libusb_exit(NULL);
  return ret;
}
-->8--

BUT! Since this is a recipient=interface request it is not
neccessarily true that wIndex=0x0700 is always correct.

wIndex identifies *which* interface in the device that the request is
destined for, and if any other of the many interface altsettings has
been set by the Linux uvc driver then the 0x0700 will not
neccessarily be correct anymore.

AND! Since this is a type=class request with recipient=interface this
code goes behind the back of the kernel driver which is handling the
interface, and that could lead to corrupted internal state in the
kernel, since it is reasonable for a driver to expect that noone else
will go poking at the device!


The above is very portable code because it uses libusb. But since the
particular USB interface is a standard device class it is worth
investigating if the Linux kernel driver for the USB video class
already exposes this LED control operation to userspace in some way.

The kernel has LED infrastructure, so the kernel driver might already
expose your camera LED there. That would be the appropriate and
friendly (to the driver) way to control the LED in Linux. Of course
it does not work on other systems.


//Peter
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux