/*
 * bayer.c -- Toggle raw Bayer data capturing for Logitech QuickCam devices.
 *
 * Copyright (c) 2006 Martin Rubli, Logitech.
 * 
 * This program is placed into the public domain.
 *
 * Compilation instructions:
 * 1. Download the Linux UVC driver from http://linux-uvc.berlios.de/.
 * 2. Apply uvcvideo-bayer.patch to the driver.
 * 3. Symlink or copy uvcvideo.h and uvc_compat.h from the driver directory
 *    into the same directory as bayer.c.
 * 4. Simply compile bayer.c like this:
 *      gcc -o bayer bayer.c
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <sys/ioctl.h>

#include <linux/videodev.h>
#include "uvcvideo.h"

static void usage(const char *argv0)
{
	printf("Usage: %s device enable [bpp]\n", argv0);
}

static int video_open(const char *devname)
{
	struct v4l2_capability cap;
	int dev, ret;

	dev = open(devname, O_RDWR);
	if (dev < 0) {
		printf("Error opening device %s: %d.\n", devname, errno);
		return dev;
	}

	memset(&cap, 0, sizeof cap);
	ret = ioctl(dev, VIDIOC_QUERYCAP, &cap);
	if (ret < 0) {
		printf("Error opening device %s: unable to query device.\n",
			devname);
		close(dev);
		return ret;
	}

	if ((cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) == 0) {
		printf("Error opening device %s: video capture not supported.\n",
			devname);
		close(dev);
		return -EINVAL;
	}

	printf("Device %s opened: %s.\n", devname, cap.card);
	return dev;
}

static int set_bayer(int dev, unsigned int bayer, unsigned int bpp)
{
	int ret;
	struct v4l2_control ctrl;

	// Enable/disable color pipeline
	ctrl.id = V4L2_CID_DISABLE_COLOR_PROCESSING;
	ctrl.value = bayer ? 1 : 0;
	printf("%s color pipeline ...\n", bayer ? "Disabling" : "Enabling");
	ret = ioctl(dev, VIDIOC_S_CTRL, &ctrl);
	if(ret < 0) {
		printf("ERROR: Unable to set device control: %d\n", ret);
		return ret;
	}

	// Set bits per pixel
	if(bayer) {
		ctrl.id = V4L2_CID_RAW_DATA_BITS_PER_PIXEL;
		switch(bpp) {
			case 10:
				ctrl.value = 1;
				break;
			default:
				printf("Invalid number of bits per pixel specified. Using default value 8.\n");
				bpp = 8;
			case 8:
				ctrl.value = 0;
				break;
		}
		printf("Setting raw data format to %d bits per pixel ...\n", bpp);
		ret = ioctl(dev, VIDIOC_S_CTRL, &ctrl);
		if (ret < 0) {
			printf("ERROR: Unable to set device control: %d\n", ret);
			return ret;
		}
	}

	return 0;
}

int main(int argc, char *argv[])
{
	int dev, bayer;
	unsigned int bpp;

	if(argc < 3) {
		usage(argv[0]);
		return 1;
	}

	// Open the video device
	dev = video_open(argv[1]);
	if(dev < 0)
		return 1;

	// Set the raw data format
	bayer = atoi(argv[2]);
	bpp = argc < 4 ? 8 : atoi(argv[3]);
	set_bayer(dev, bayer, bpp);

	// Close the video device
	close(dev);
	return 0;
}

