
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <linux/videodev.h>
#include <linux/videodev2.h>

#define VIEWSIZE_WIDTH	640
#define VIEWSIZE_HEIGHT	480


/* Used with VIDIOCPWCPROBE */
struct pwc_probe
{
        char name[32];
        int type;
};
#define VIDIOCPWCPROBE          _IOR('v', 199, struct pwc_probe)
/* This is used for out-of-kernel decompression. With it, you can get
   all the necessary information to initialize and use the decompressor
   routines in standalone applications.
 */   
struct pwc_video_command
{
        int type;               /* camera type (645, 675, 730, etc.) */
        int release;            /* release number */

        int size;               /* one of PSZ_* */
        int alternate;
        int command_len;        /* length of USB video command */
        unsigned char command_buf[13];  /* Actual USB video command */
        int bandlength;         /* >0 = compressed */
        int frame_size;         /* Size of one (un)compressed frame */
};
#define VIDIOCPWCGVIDCMD        _IOR('v', 215, struct pwc_video_command)

/* Image size (used with GREALSIZE) */
struct pwc_imagesize
{
        int width;
        int height;
};
#define VIDIOCPWCGREALSIZE      _IOR('v', 210, struct pwc_imagesize)

#define PWC_FPS_SHIFT           16


static int fd;
static size_t framesize;

static int grab_buffer(void);

#define xioctl(fd,cmd,arg) do { \
  if (ioctl(fd,cmd,arg)<0) {\
    fprintf(stderr,"%s: %s\n", #cmd, strerror(errno)); \
    exit(1); \
  } \
} while(0) \


int main(int argc, char **argv)
{
  int i;
  struct video_capability videocap;
  struct video_picture videopict;
  struct video_window videowin;
  struct pwc_probe pprobe;
  struct pwc_video_command pvcmd;
  struct pwc_imagesize pimgsize;

  fd = open("/dev/video0",O_RDONLY);
  if (fd<0)
    exit(1);
  xioctl(fd, VIDIOCGCAP, &videocap);
  memset(&pprobe, 0, sizeof(pprobe));
  xioctl(fd, VIDIOCPWCPROBE, &pprobe);
  if (strcmp(pprobe.name, videocap.name))
    exit(2);

  xioctl(fd, VIDIOCGPICT, &videopict);
  videopict.palette = VIDEO_PALETTE_RAW;
  xioctl(fd, VIDIOCSPICT, &videopict);

  ioctl(fd, VIDIOCGWIN, &videowin);
  videowin.width = VIEWSIZE_WIDTH;
  videowin.height = VIEWSIZE_HEIGHT;
  videowin.flags = (5 << PWC_FPS_SHIFT);
  xioctl(fd, VIDIOCSWIN, &videowin);

  xioctl(fd, VIDIOCPWCGVIDCMD, &pvcmd);
  printf("VIDIOCPWCGVIDCMD: ");
  for (i = 0; i < pvcmd.command_len; i++)
   {
     printf("0x%02x ", pvcmd.command_buf[i]);
   }
  printf("\n");
  printf("TYPE: 0x%x\n", pvcmd.type);
  printf("FRAMESIZE: %d\n", pvcmd.frame_size);
  printf("BANDLENGTH: %d\n", pvcmd.bandlength);
  framesize = pvcmd.frame_size;

  xioctl(fd, VIDIOCPWCGREALSIZE, &pimgsize);
  for (i=0;i<10;i++)
   {
     grab_buffer();
   }

  close(fd);
  return 0;
}



static int grab_buffer(void)
{
  unsigned char imgbuffer[1024*1024];
  static int img_idx=0;
  char filename[64];
  int out;

  memset(imgbuffer,0,sizeof(imgbuffer));
  read(fd,imgbuffer,framesize);

  /* Place hook to decompress the raw data */
#if 0
  pwcx_decompress_Nala(&m_RealSize, &m_ViewSize, &m_Offset,
      m_pInputBuffer, m_pImageBuffer,
      PWCX_FLAG_PLANAR,
      m_pPWCXBuffer, m_Bandlength);
#endif


  /* write the raw data into a file */
  snprintf(filename,sizeof(filename),"/tmp/pwc%4.4x.raw", img_idx++);
  out = open(filename, O_WRONLY|O_CREAT,S_IRUSR|S_IWUSR);
  if (out)
   {
     write(out,imgbuffer,framesize);
     close(out);
   }

  return 0;
}






